remult 0.25.8 → 0.26.0

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.
Files changed (102) hide show
  1. package/README.md +194 -129
  2. package/esm/graphql.js +131 -59
  3. package/esm/index.js +1 -1
  4. package/esm/migrations/compare-migration-snapshots.js +61 -0
  5. package/esm/migrations/generate-migrations.js +68 -0
  6. package/esm/migrations/index.js +2 -0
  7. package/esm/migrations/migrate.js +90 -0
  8. package/esm/migrations/migration-types.js +36 -0
  9. package/esm/migrations/update-migrations-ts-file.js +115 -0
  10. package/esm/postgres/postgres-data-provider.js +24 -3
  11. package/esm/postgres/schema-builder.js +35 -26
  12. package/esm/remult-better-sqlite3.js +47 -0
  13. package/esm/remult-bun-sqlite.js +41 -0
  14. package/esm/remult-knex/index.js +180 -51
  15. package/esm/remult-mongo.js +2 -2
  16. package/esm/remult-sql-js.js +3 -78
  17. package/esm/remult-sqlite-core.js +104 -0
  18. package/esm/server/expressBridge.js +130 -29
  19. package/esm/server/initAsyncHooks.js +75 -1
  20. package/esm/src/CompoundIdField.js +8 -2
  21. package/esm/src/context.js +20 -24
  22. package/esm/src/data-api.js +71 -30
  23. package/esm/src/data-providers/rest-data-provider.js +17 -15
  24. package/esm/src/data-providers/sql-database.js +32 -7
  25. package/esm/src/data-providers/web-sql-data-provider.js +1 -9
  26. package/esm/src/filter/filter-consumer-bridge-to-sql-request.js +37 -11
  27. package/esm/src/filter/filter-interfaces.js +229 -17
  28. package/esm/src/isOfType.js +9 -0
  29. package/esm/src/remult3/Fields.js +70 -18
  30. package/esm/src/remult3/RepositoryImplementation.js +47 -21
  31. package/esm/src/remult3/addValidator.js +15 -0
  32. package/esm/src/remult3/remult3.js +28 -57
  33. package/esm/src/server-action.js +4 -4
  34. package/esm/src/validators.js +6 -3
  35. package/esm/src/valueConverters.js +1 -1
  36. package/graphql.js +156 -71
  37. package/index.d.ts +4 -4
  38. package/index.js +2 -1
  39. package/migrations/compare-migration-snapshots.d.ts +27 -0
  40. package/migrations/compare-migration-snapshots.js +165 -0
  41. package/migrations/generate-migrations.d.ts +21 -0
  42. package/migrations/generate-migrations.js +104 -0
  43. package/migrations/index.d.ts +3 -0
  44. package/migrations/index.js +7 -0
  45. package/migrations/migrate.d.ts +27 -0
  46. package/migrations/migrate.js +175 -0
  47. package/migrations/migration-types.d.ts +48 -0
  48. package/migrations/migration-types.js +88 -0
  49. package/migrations/update-migrations-ts-file.d.ts +1 -0
  50. package/migrations/update-migrations-ts-file.js +141 -0
  51. package/package.json +21 -1
  52. package/postgres/postgres-data-provider.d.ts +8 -3
  53. package/postgres/postgres-data-provider.js +46 -3
  54. package/postgres/schema-builder.js +81 -48
  55. package/remult-better-sqlite3.d.ts +12 -0
  56. package/remult-better-sqlite3.js +64 -0
  57. package/remult-bun-sqlite.d.ts +11 -0
  58. package/remult-bun-sqlite.js +56 -0
  59. package/remult-knex/index.d.ts +12 -5
  60. package/remult-knex/index.js +257 -90
  61. package/remult-mongo.d.ts +2 -2
  62. package/remult-mongo.js +2 -2
  63. package/remult-sql-js.d.ts +2 -15
  64. package/remult-sql-js.js +11 -152
  65. package/remult-sqlite-core.d.ts +21 -0
  66. package/remult-sqlite-core.js +217 -0
  67. package/server/expressBridge.d.ts +30 -1
  68. package/server/expressBridge.js +140 -32
  69. package/server/initAsyncHooks.d.ts +16 -0
  70. package/server/initAsyncHooks.js +128 -2
  71. package/src/CompoundIdField.js +8 -2
  72. package/src/column-interfaces.d.ts +9 -3
  73. package/src/context.d.ts +8 -6
  74. package/src/context.js +27 -36
  75. package/src/data-api.d.ts +13 -9
  76. package/src/data-api.js +184 -135
  77. package/src/data-providers/rest-data-provider.js +26 -15
  78. package/src/data-providers/sql-database.d.ts +17 -5
  79. package/src/data-providers/sql-database.js +31 -7
  80. package/src/data-providers/web-sql-data-provider.d.ts +1 -2
  81. package/src/data-providers/web-sql-data-provider.js +4 -8
  82. package/src/entity.d.ts +64 -6
  83. package/src/filter/filter-consumer-bridge-to-sql-request.d.ts +31 -7
  84. package/src/filter/filter-consumer-bridge-to-sql-request.js +46 -21
  85. package/src/filter/filter-interfaces.d.ts +106 -39
  86. package/src/filter/filter-interfaces.js +312 -32
  87. package/src/isOfType.d.ts +2 -0
  88. package/src/isOfType.js +14 -0
  89. package/src/remult3/Fields.d.ts +36 -0
  90. package/src/remult3/Fields.js +81 -19
  91. package/src/remult3/RepositoryImplementation.d.ts +7 -3
  92. package/src/remult3/RepositoryImplementation.js +106 -71
  93. package/src/remult3/addValidator.d.ts +2 -0
  94. package/src/remult3/addValidator.js +20 -0
  95. package/src/remult3/remult3.d.ts +6 -2
  96. package/src/remult3/remult3.js +28 -57
  97. package/src/server-action.d.ts +1 -1
  98. package/src/server-action.js +5 -4
  99. package/src/sql-command.d.ts +6 -1
  100. package/src/validators.d.ts +1 -0
  101. package/src/validators.js +10 -4
  102. package/src/valueConverters.js +1 -1
@@ -16,6 +16,7 @@ var server_action_info_js_1 = require("../src/server-action-info.js");
16
16
  var initDataProvider_js_1 = require("./initDataProvider.js");
17
17
  var remult_static_js_1 = require("../src/remult-static.js");
18
18
  var remult_admin_js_1 = tslib_1.__importDefault(require("./remult-admin.js"));
19
+ var isOfType_js_1 = require("../src/isOfType.js");
19
20
  function createRemultServerCore(options, serverCoreOptions) {
20
21
  if (!options) {
21
22
  options = {};
@@ -443,16 +444,16 @@ var RemultServerImplementation = /** @class */ (function () {
443
444
  return tslib_1.__generator(this, function (_d) {
444
445
  switch (_d.label) {
445
446
  case 0:
446
- _b = (_a = dataApiFactory(c)).put;
447
+ _b = (_a = dataApiFactory(c)).updateManyThroughPutRequest;
447
448
  _c = [res,
448
- ''];
449
+ req];
449
450
  return [4 /*yield*/, this.coreOptions.getRequestBody(orig)];
450
451
  case 1: return [2 /*return*/, _b.apply(_a, _c.concat([_d.sent()]))];
451
452
  }
452
453
  });
453
454
  }); }))
454
- .delete(this.process(function (c, req, res, orig) { return tslib_1.__awaiter(_this, void 0, void 0, function () { return tslib_1.__generator(this, function (_a) {
455
- return [2 /*return*/, dataApiFactory(c).delete(res, '')];
455
+ .delete(this.process(function (c, req, res, _, __, orig) { return tslib_1.__awaiter(_this, void 0, void 0, function () { return tslib_1.__generator(this, function (_a) {
456
+ return [2 /*return*/, dataApiFactory(c).deleteMany(res, req, undefined)];
456
457
  }); }); }))
457
458
  .post(this.process(function (c, req, res, _, __, orig) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
458
459
  var _a, _b, _c;
@@ -543,7 +544,7 @@ var RemultServerImplementation = /** @class */ (function () {
543
544
  genReq.params = req['_tempParams'];
544
545
  }
545
546
  myReq = new ExpressRequestBridgeToDataApiRequest(genReq);
546
- myRes = new ExpressResponseBridgeToDataApiResponse(origRes, req);
547
+ myRes = new ExpressResponseBridgeToDataApiResponse(origRes, req, this.options.error);
547
548
  _a.label = 1;
548
549
  case 1:
549
550
  _a.trys.push([1, 3, , 4]);
@@ -592,7 +593,7 @@ var RemultServerImplementation = /** @class */ (function () {
592
593
  return [3 /*break*/, 4];
593
594
  case 3:
594
595
  err_1 = _a.sent();
595
- myRes.error((0, data_api_js_1.serializeError)(err_1));
596
+ myRes.error(err_1, undefined);
596
597
  return [3 /*break*/, 4];
597
598
  case 4: return [2 /*return*/];
598
599
  }
@@ -791,6 +792,17 @@ var RemultServerImplementation = /** @class */ (function () {
791
792
  return secureBase(condition, def, item);
792
793
  };
793
794
  var apiPath = (spec.paths[this_2.options.rootPath + '/' + key] = {});
795
+ var itemInBody = {
796
+ requestBody: {
797
+ content: {
798
+ 'application/json': {
799
+ schema: {
800
+ $ref: '#/components/schemas/' + mutationKey,
801
+ },
802
+ },
803
+ },
804
+ },
805
+ };
794
806
  var apiPathWithId = (spec.paths[this_2.options.rootPath + '/' + key + '/{id}'] = {});
795
807
  //https://github.com/2fd/open-api.d.ts
796
808
  apiPath.get = secure(meta.options.allowApiRead, true, {
@@ -842,6 +854,68 @@ var RemultServerImplementation = /** @class */ (function () {
842
854
  },
843
855
  },
844
856
  });
857
+ apiPath.delete = secure(meta.options.allowApiDelete, true, {
858
+ description: 'deletes row of ' +
859
+ key +
860
+ '. supports filter operators. For more info on filtering [see this article](https://remult.dev/docs/rest-api.html#filter)',
861
+ parameters: tslib_1.__spreadArray([], tslib_1.__read(parameters), false),
862
+ responses: {
863
+ '400': {
864
+ description: 'Error: Bad Request',
865
+ content: {
866
+ 'application/json': {
867
+ schema: {
868
+ $ref: '#/components/schemas/InvalidResponse',
869
+ },
870
+ },
871
+ },
872
+ },
873
+ '200': {
874
+ description: 'returns the number of deleted rows ' + key,
875
+ content: {
876
+ 'application/json': {
877
+ schema: {
878
+ type: 'object',
879
+ properties: {
880
+ deleted: {
881
+ type: 'number',
882
+ },
883
+ },
884
+ },
885
+ },
886
+ },
887
+ },
888
+ },
889
+ });
890
+ apiPath.put = secure(meta.options.allowApiDelete, true, tslib_1.__assign(tslib_1.__assign({ description: 'updates row of ' +
891
+ key +
892
+ '. supports filter operators. For more info on filtering [see this article](https://remult.dev/docs/rest-api.html#filter)', parameters: tslib_1.__spreadArray([], tslib_1.__read(parameters), false) }, itemInBody), { responses: {
893
+ '400': {
894
+ description: 'Error: Bad Request',
895
+ content: {
896
+ 'application/json': {
897
+ schema: {
898
+ $ref: '#/components/schemas/InvalidResponse',
899
+ },
900
+ },
901
+ },
902
+ },
903
+ '200': {
904
+ description: 'returns the number of updated rows ' + key,
905
+ content: {
906
+ 'application/json': {
907
+ schema: {
908
+ type: 'object',
909
+ properties: {
910
+ updated: {
911
+ type: 'number',
912
+ },
913
+ },
914
+ },
915
+ },
916
+ },
917
+ },
918
+ } }));
845
919
  var idParameter = {
846
920
  name: 'id',
847
921
  in: 'path',
@@ -849,17 +923,6 @@ var RemultServerImplementation = /** @class */ (function () {
849
923
  required: true,
850
924
  schema: { type: 'string' },
851
925
  };
852
- var itemInBody = {
853
- requestBody: {
854
- content: {
855
- 'application/json': {
856
- schema: {
857
- $ref: '#/components/schemas/' + mutationKey,
858
- },
859
- },
860
- },
861
- },
862
- };
863
926
  apiPath.post = secure(meta.options.allowApiInsert, false, tslib_1.__assign(tslib_1.__assign({
864
927
  //"summary": "insert a " + key,
865
928
  //"description": "insert a " + key,
@@ -1001,12 +1064,13 @@ var ExpressRequestBridgeToDataApiRequest = /** @class */ (function () {
1001
1064
  return ExpressRequestBridgeToDataApiRequest;
1002
1065
  }());
1003
1066
  var ExpressResponseBridgeToDataApiResponse = /** @class */ (function () {
1004
- function ExpressResponseBridgeToDataApiResponse(r, req) {
1067
+ function ExpressResponseBridgeToDataApiResponse(r, req, handleError) {
1005
1068
  this.r = r;
1006
1069
  this.req = req;
1070
+ this.handleError = handleError;
1007
1071
  }
1008
1072
  ExpressResponseBridgeToDataApiResponse.prototype.forbidden = function () {
1009
- this.setStatus(403).end();
1073
+ this.error({ message: 'Forbidden' }, undefined, 403);
1010
1074
  };
1011
1075
  ExpressResponseBridgeToDataApiResponse.prototype.setStatus = function (status) {
1012
1076
  return this.r.status(status);
@@ -1022,24 +1086,68 @@ var ExpressResponseBridgeToDataApiResponse = /** @class */ (function () {
1022
1086
  this.setStatus(204).end();
1023
1087
  };
1024
1088
  ExpressResponseBridgeToDataApiResponse.prototype.notFound = function () {
1025
- this.setStatus(404).end();
1089
+ this.error({ message: 'Forbidden' }, undefined, 404);
1026
1090
  };
1027
- ExpressResponseBridgeToDataApiResponse.prototype.error = function (data) {
1028
- var _a, _b, _c;
1029
- data = (0, data_api_js_1.serializeError)(data);
1030
- console.error({
1031
- message: data.message,
1032
- stack: (_a = data.stack) === null || _a === void 0 ? void 0 : _a.split('\n'),
1033
- url: (_b = this.req) === null || _b === void 0 ? void 0 : _b.url,
1034
- method: (_c = this.req) === null || _c === void 0 ? void 0 : _c.method,
1091
+ ExpressResponseBridgeToDataApiResponse.prototype.error = function (exception, entity, httpStatusCode) {
1092
+ var _a;
1093
+ return tslib_1.__awaiter(this, void 0, void 0, function () {
1094
+ var data, responseSent, sendError;
1095
+ var _this = this;
1096
+ return tslib_1.__generator(this, function (_b) {
1097
+ switch (_b.label) {
1098
+ case 0:
1099
+ data = (0, data_api_js_1.serializeError)(exception);
1100
+ if (!httpStatusCode) {
1101
+ if (data.httpStatusCode) {
1102
+ httpStatusCode = data.httpStatusCode;
1103
+ }
1104
+ else if ((0, isOfType_js_1.isOfType)(exception, 'isForbiddenError') &&
1105
+ exception.isForbiddenError) {
1106
+ httpStatusCode = 403;
1107
+ }
1108
+ else if (data.modelState) {
1109
+ httpStatusCode = 400;
1110
+ }
1111
+ else {
1112
+ httpStatusCode = 500;
1113
+ }
1114
+ }
1115
+ responseSent = false;
1116
+ sendError = function (httpStatusCode, body) {
1117
+ var _a, _b, _c;
1118
+ if (responseSent) {
1119
+ throw Error('Error response already sent');
1120
+ }
1121
+ responseSent = true;
1122
+ console.error({
1123
+ message: body.message,
1124
+ httpStatusCode: httpStatusCode,
1125
+ stack: (_a = data.stack) === null || _a === void 0 ? void 0 : _a.split('\n'),
1126
+ url: (_b = _this.req) === null || _b === void 0 ? void 0 : _b.url,
1127
+ method: (_c = _this.req) === null || _c === void 0 ? void 0 : _c.method,
1128
+ });
1129
+ _this.setStatus(httpStatusCode).json(body);
1130
+ };
1131
+ return [4 /*yield*/, ((_a = this.handleError) === null || _a === void 0 ? void 0 : _a.call(this, {
1132
+ httpStatusCode: httpStatusCode,
1133
+ req: this.req,
1134
+ entity: entity,
1135
+ exception: exception,
1136
+ responseBody: data,
1137
+ sendError: sendError,
1138
+ }))];
1139
+ case 1:
1140
+ _b.sent();
1141
+ if (!responseSent) {
1142
+ sendError(httpStatusCode, data);
1143
+ }
1144
+ return [2 /*return*/];
1145
+ }
1146
+ });
1035
1147
  });
1036
- this.setStatus(400).json(data);
1037
1148
  };
1038
1149
  return ExpressResponseBridgeToDataApiResponse;
1039
1150
  }());
1040
- function throwError() {
1041
- throw 'Invalid';
1042
- }
1043
1151
  var inProcessQueueHandler = /** @class */ (function () {
1044
1152
  function inProcessQueueHandler(storage) {
1045
1153
  this.storage = storage;
@@ -1 +1,17 @@
1
+ import { type RemultAsyncLocalStorageCore } from '../src/context.js';
1
2
  export declare function initAsyncHooks(): void;
3
+ export declare class AsyncLocalStorageBridgeToRemultAsyncLocalStorageCoreImpl<T> implements RemultAsyncLocalStorageCore<T> {
4
+ private asyncLocalStorage;
5
+ wasImplemented: 'yes';
6
+ run<R>(store: T, callback: () => Promise<R>): Promise<R>;
7
+ getStore(): T;
8
+ }
9
+ export declare class SequentialRemultAsyncLocalStorageCore<T> implements RemultAsyncLocalStorageCore<T> {
10
+ wasImplemented: 'yes';
11
+ run<R>(store: T, callback: () => Promise<R>): Promise<R>;
12
+ getStore(): T;
13
+ lastPromise: Promise<T>;
14
+ currentValue: T;
15
+ }
16
+ export declare class AsyncLocalStorageBridgeToRemultAsyncLocalStorageCore<T> extends AsyncLocalStorageBridgeToRemultAsyncLocalStorageCoreImpl<T> {
17
+ }
@@ -1,14 +1,140 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.initAsyncHooks = void 0;
3
+ exports.AsyncLocalStorageBridgeToRemultAsyncLocalStorageCore = exports.SequentialRemultAsyncLocalStorageCore = exports.AsyncLocalStorageBridgeToRemultAsyncLocalStorageCoreImpl = exports.initAsyncHooks = void 0;
4
+ var tslib_1 = require("tslib");
4
5
  var async_hooks_1 = require("async_hooks");
5
6
  var context_js_1 = require("../src/context.js");
6
7
  var remult_static_js_1 = require("../src/remult-static.js");
7
8
  var init = false;
8
9
  function initAsyncHooks() {
10
+ var _this = this;
9
11
  if (init)
10
12
  return;
11
13
  init = true;
12
- remult_static_js_1.remultStatic.asyncContext = new context_js_1.RemultAsyncLocalStorage(new async_hooks_1.AsyncLocalStorage());
14
+ remult_static_js_1.remultStatic.asyncContext = new context_js_1.RemultAsyncLocalStorage(new AsyncLocalStorageBridgeToRemultAsyncLocalStorageCore());
15
+ var test = new async_hooks_1.AsyncLocalStorage();
16
+ test.run(1, function () { return tslib_1.__awaiter(_this, void 0, void 0, function () {
17
+ return tslib_1.__generator(this, function (_a) {
18
+ switch (_a.label) {
19
+ case 0: return [4 /*yield*/, Promise.resolve()];
20
+ case 1:
21
+ _a.sent();
22
+ if (test.getStore() === undefined) {
23
+ console.log("async_hooks.AsyncLocalStorage not working, using sequential implementation (You're probably running on stackblitz, this will work on a normal nodejs environment");
24
+ remult_static_js_1.remultStatic.asyncContext = new context_js_1.RemultAsyncLocalStorage(new SequentialRemultAsyncLocalStorageCore());
25
+ }
26
+ return [2 /*return*/];
27
+ }
28
+ });
29
+ }); });
13
30
  }
14
31
  exports.initAsyncHooks = initAsyncHooks;
32
+ var AsyncLocalStorageBridgeToRemultAsyncLocalStorageCoreImpl = /** @class */ (function () {
33
+ function AsyncLocalStorageBridgeToRemultAsyncLocalStorageCoreImpl() {
34
+ this.asyncLocalStorage = new async_hooks_1.AsyncLocalStorage();
35
+ }
36
+ AsyncLocalStorageBridgeToRemultAsyncLocalStorageCoreImpl.prototype.run = function (store, callback) {
37
+ var _this = this;
38
+ var r;
39
+ this.asyncLocalStorage.run(store, function () {
40
+ r = new Promise(function (res, rej) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
41
+ var _a, err_1;
42
+ return tslib_1.__generator(this, function (_b) {
43
+ switch (_b.label) {
44
+ case 0:
45
+ _b.trys.push([0, 2, , 3]);
46
+ _a = res;
47
+ return [4 /*yield*/, callback()];
48
+ case 1:
49
+ _a.apply(void 0, [_b.sent()]);
50
+ return [3 /*break*/, 3];
51
+ case 2:
52
+ err_1 = _b.sent();
53
+ rej(err_1);
54
+ return [3 /*break*/, 3];
55
+ case 3: return [2 /*return*/];
56
+ }
57
+ });
58
+ }); });
59
+ });
60
+ return r;
61
+ };
62
+ AsyncLocalStorageBridgeToRemultAsyncLocalStorageCoreImpl.prototype.getStore = function () {
63
+ return this.asyncLocalStorage.getStore();
64
+ };
65
+ return AsyncLocalStorageBridgeToRemultAsyncLocalStorageCoreImpl;
66
+ }());
67
+ exports.AsyncLocalStorageBridgeToRemultAsyncLocalStorageCoreImpl = AsyncLocalStorageBridgeToRemultAsyncLocalStorageCoreImpl;
68
+ var ignoreInStack = ["AsyncLocalStorageBridgeToRemultAsyncLocalStorageCore.run", "RemultAsyncLocalStorage.run", "Module.withRemult", "RemultServerImplementation.runWithRemult"];
69
+ var SequentialRemultAsyncLocalStorageCore = /** @class */ (function () {
70
+ function SequentialRemultAsyncLocalStorageCore() {
71
+ this.lastPromise = Promise.resolve(undefined);
72
+ }
73
+ SequentialRemultAsyncLocalStorageCore.prototype.run = function (store, callback) {
74
+ return tslib_1.__awaiter(this, void 0, void 0, function () {
75
+ var log, stack_1, y, nextPromise;
76
+ var _this = this;
77
+ return tslib_1.__generator(this, function (_a) {
78
+ switch (_a.label) {
79
+ case 0:
80
+ log = function (msg) {
81
+ };
82
+ if (false) {
83
+ stack_1 = new Error().stack;
84
+ y = stack_1.split('\n');
85
+ while (y.length > 0 && (y[0].trim().startsWith("Error") || ignoreInStack.includes(y[0].trim().split(' ')[1]))) {
86
+ y.splice(0, 1);
87
+ }
88
+ stack_1 = y.join('\n');
89
+ log = function (msg) {
90
+ console.log(msg, stack_1);
91
+ };
92
+ }
93
+ log('waiting on ');
94
+ nextPromise = this.lastPromise.then(function () { return tslib_1.__awaiter(_this, void 0, void 0, function () {
95
+ var previousValue, result;
96
+ return tslib_1.__generator(this, function (_a) {
97
+ switch (_a.label) {
98
+ case 0:
99
+ log('executing ');
100
+ previousValue = this.currentValue;
101
+ this.currentValue = store;
102
+ return [4 /*yield*/, callback()];
103
+ case 1:
104
+ result = _a.sent();
105
+ this.currentValue = previousValue;
106
+ return [2 /*return*/, result];
107
+ }
108
+ });
109
+ }); });
110
+ this.lastPromise = nextPromise.catch(function () {
111
+ log("Error on ");
112
+ return undefined;
113
+ });
114
+ _a.label = 1;
115
+ case 1:
116
+ _a.trys.push([1, , 3, 4]);
117
+ return [4 /*yield*/, nextPromise];
118
+ case 2: return [2 /*return*/, _a.sent()];
119
+ case 3:
120
+ log('completed ');
121
+ return [7 /*endfinally*/];
122
+ case 4: return [2 /*return*/];
123
+ }
124
+ });
125
+ });
126
+ };
127
+ SequentialRemultAsyncLocalStorageCore.prototype.getStore = function () {
128
+ return this.currentValue;
129
+ };
130
+ return SequentialRemultAsyncLocalStorageCore;
131
+ }());
132
+ exports.SequentialRemultAsyncLocalStorageCore = SequentialRemultAsyncLocalStorageCore;
133
+ var AsyncLocalStorageBridgeToRemultAsyncLocalStorageCore = /** @class */ (function (_super) {
134
+ tslib_1.__extends(AsyncLocalStorageBridgeToRemultAsyncLocalStorageCore, _super);
135
+ function AsyncLocalStorageBridgeToRemultAsyncLocalStorageCore() {
136
+ return _super !== null && _super.apply(this, arguments) || this;
137
+ }
138
+ return AsyncLocalStorageBridgeToRemultAsyncLocalStorageCore;
139
+ }(AsyncLocalStorageBridgeToRemultAsyncLocalStorageCoreImpl));
140
+ exports.AsyncLocalStorageBridgeToRemultAsyncLocalStorageCore = AsyncLocalStorageBridgeToRemultAsyncLocalStorageCore;
@@ -28,11 +28,17 @@ var CompoundIdField = /** @class */ (function () {
28
28
  return Promise.resolve('');
29
29
  };
30
30
  CompoundIdField.prototype.getId = function (instance) {
31
+ var get = function (field) {
32
+ return instance[field.key];
33
+ };
34
+ if (typeof instance === 'function') {
35
+ get = instance;
36
+ }
31
37
  var r = '';
32
38
  this.fields.forEach(function (c) {
33
39
  if (r.length > 0)
34
40
  r += ',';
35
- r += instance[c.key];
41
+ r += c.valueConverter.toJson(get(c));
36
42
  });
37
43
  return r;
38
44
  };
@@ -48,7 +54,7 @@ var CompoundIdField = /** @class */ (function () {
48
54
  var val = value.toString();
49
55
  var id = val.split(',');
50
56
  this.fields.forEach(function (c, i) {
51
- result[c.key] = id[i];
57
+ result[c.key] = c.valueConverter.fromJson(id[i]);
52
58
  });
53
59
  return result;
54
60
  };
@@ -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
- * readonly fieldTypeInDb = 'decimal(18,2)';
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
- * readonly inputType = 'date';
266
+ * inputType = 'date';
261
267
  */
262
268
  readonly inputType?: string;
263
269
  }
package/src/context.d.ts CHANGED
@@ -8,13 +8,14 @@ export declare class RemultAsyncLocalStorage {
8
8
  private readonly remultObjectStorage;
9
9
  static enable(): void;
10
10
  static disable(): void;
11
- constructor(remultObjectStorage: myAsyncLocalStorage<Remult>);
12
- run(remult: Remult, callback: (remult: Remult) => void): void;
11
+ constructor(remultObjectStorage: RemultAsyncLocalStorageCore<Remult>);
12
+ run<T>(remult: Remult, callback: (remult: Remult) => Promise<T>): Promise<T>;
13
13
  getRemult(): Remult;
14
14
  }
15
- type myAsyncLocalStorage<T> = {
16
- run<R>(store: T, callback: (...args: any[]) => R, ...args: any[]): R;
15
+ export type RemultAsyncLocalStorageCore<T> = {
16
+ run<R>(store: T, callback: () => Promise<R>): Promise<R>;
17
17
  getStore(): T | undefined;
18
+ wasImplemented: 'yes';
18
19
  };
19
20
  export declare function isBackend(): boolean;
20
21
  export declare class Remult {
@@ -92,6 +93,8 @@ export interface ApiClient {
92
93
  * @example
93
94
  * // Using Angular HttpClient
94
95
  * remult.apiClient.httpClient = httpClient;
96
+ * @see
97
+ * If you want to add headers using angular httpClient, see: https://medium.com/angular-shots/shot-3-how-to-add-http-headers-to-every-request-in-angular-fab3d10edc26
95
98
  *
96
99
  * @example
97
100
  * // Using fetch (default)
@@ -183,8 +186,7 @@ export interface itemChange {
183
186
  oldId: any;
184
187
  deleted: boolean;
185
188
  }
186
- export declare function doTransaction(remult: Remult, what: () => Promise<void>): Promise<void>;
189
+ export declare function doTransaction(remult: Remult, what: (dp: DataProvider) => Promise<void>): Promise<void>;
187
190
  export declare function withRemult<T>(callback: (remult: any) => Promise<T>, options?: {
188
191
  dataProvider?: DataProvider;
189
192
  }): Promise<T>;
190
- export {};
package/src/context.js CHANGED
@@ -28,10 +28,16 @@ var RemultAsyncLocalStorage = /** @class */ (function () {
28
28
  (0, remult_static_js_1.resetFactory)();
29
29
  };
30
30
  RemultAsyncLocalStorage.prototype.run = function (remult, callback) {
31
- if (this.remultObjectStorage)
32
- this.remultObjectStorage.run(remult, function () { return callback(remult); });
33
- else
34
- callback(remult);
31
+ return tslib_1.__awaiter(this, void 0, void 0, function () {
32
+ return tslib_1.__generator(this, function (_a) {
33
+ if (this.remultObjectStorage) {
34
+ return [2 /*return*/, this.remultObjectStorage.run(remult, function () { return callback(remult); })];
35
+ }
36
+ else
37
+ return [2 /*return*/, callback(remult)];
38
+ return [2 /*return*/];
39
+ });
40
+ });
35
41
  };
36
42
  RemultAsyncLocalStorage.prototype.getRemult = function () {
37
43
  if (!this.remultObjectStorage) {
@@ -322,20 +328,24 @@ var EventSource = /** @class */ (function () {
322
328
  exports.EventSource = EventSource;
323
329
  function doTransaction(remult, what) {
324
330
  return tslib_1.__awaiter(this, void 0, void 0, function () {
325
- var trans, ok, result;
331
+ var trans, ok, prev;
326
332
  var _this = this;
327
333
  return tslib_1.__generator(this, function (_a) {
328
334
  switch (_a.label) {
329
335
  case 0:
330
336
  trans = new transactionLiveQueryPublisher(remult.liveQueryPublisher);
331
337
  ok = true;
338
+ prev = remult.dataProvider;
339
+ _a.label = 1;
340
+ case 1:
341
+ _a.trys.push([1, , 5, 6]);
332
342
  return [4 /*yield*/, remult.dataProvider.transaction(function (ds) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
333
343
  return tslib_1.__generator(this, function (_a) {
334
344
  switch (_a.label) {
335
345
  case 0:
336
346
  remult.dataProvider = ds;
337
347
  remult.liveQueryPublisher = trans;
338
- return [4 /*yield*/, what()];
348
+ return [4 /*yield*/, what(ds)];
339
349
  case 1:
340
350
  _a.sent();
341
351
  ok = true;
@@ -343,14 +353,18 @@ function doTransaction(remult, what) {
343
353
  }
344
354
  });
345
355
  }); })];
346
- case 1:
347
- result = _a.sent();
348
- if (!ok) return [3 /*break*/, 3];
349
- return [4 /*yield*/, trans.flush()];
350
356
  case 2:
351
357
  _a.sent();
352
- _a.label = 3;
353
- case 3: return [2 /*return*/];
358
+ if (!ok) return [3 /*break*/, 4];
359
+ return [4 /*yield*/, trans.flush()];
360
+ case 3:
361
+ _a.sent();
362
+ _a.label = 4;
363
+ case 4: return [3 /*break*/, 6];
364
+ case 5:
365
+ remult.dataProvider = prev;
366
+ return [7 /*endfinally*/];
367
+ case 6: return [2 /*return*/];
354
368
  }
355
369
  });
356
370
  });
@@ -441,32 +455,9 @@ var transactionLiveQueryPublisher = /** @class */ (function () {
441
455
  return transactionLiveQueryPublisher;
442
456
  }());
443
457
  function withRemult(callback, options) {
444
- var _this = this;
445
458
  var remult = new Remult();
446
459
  if (options === null || options === void 0 ? void 0 : options.dataProvider)
447
460
  remult.dataProvider = options.dataProvider;
448
- var r;
449
- remult_static_js_1.remultStatic.asyncContext.run(remult, function () {
450
- r = new Promise(function (res, rej) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
451
- var _a, err_1;
452
- return tslib_1.__generator(this, function (_b) {
453
- switch (_b.label) {
454
- case 0:
455
- _b.trys.push([0, 2, , 3]);
456
- _a = res;
457
- return [4 /*yield*/, callback(remult)];
458
- case 1:
459
- _a.apply(void 0, [_b.sent()]);
460
- return [3 /*break*/, 3];
461
- case 2:
462
- err_1 = _b.sent();
463
- rej(err_1);
464
- return [3 /*break*/, 3];
465
- case 3: return [2 /*return*/];
466
- }
467
- });
468
- }); });
469
- });
470
- return r;
461
+ return remult_static_js_1.remultStatic.asyncContext.run(remult, function (r) { return callback(r); });
471
462
  }
472
463
  exports.withRemult = withRemult;
package/src/data-api.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type { Remult } from './context.js';
2
2
  import type { ErrorInfo } from './data-interfaces.js';
3
- import type { FindOptions, Repository } from './remult3/remult3.js';
3
+ import type { EntityMetadata, FindOptions, Repository } from './remult3/remult3.js';
4
4
  import type { rowHelperImplementation } from './remult3/RepositoryImplementation.js';
5
5
  export declare class DataApi<T = any> {
6
6
  private repository;
@@ -10,18 +10,22 @@ export declare class DataApi<T = any> {
10
10
  httpPost(res: DataApiResponse, req: DataApiRequest, body: any, serializeContext: () => Promise<any>): Promise<void>;
11
11
  static defaultGetLimit: number;
12
12
  get(response: DataApiResponse, id: any): Promise<void>;
13
- count(response: DataApiResponse, request: DataApiRequest, filterBody?: any): Promise<void>;
14
- deleteMany(response: DataApiResponse, request: DataApiRequest, filterBody?: any): Promise<void>;
15
- getArrayImpl(response: DataApiResponse, request: DataApiRequest, filterBody: any): Promise<{
13
+ count(response: DataApiResponse, request: DataApiRequest, body?: any): Promise<void>;
14
+ deleteMany(response: DataApiResponse, request: DataApiRequest, body?: any): Promise<void>;
15
+ getArrayImpl(response: DataApiResponse, request: DataApiRequest, body: any): Promise<{
16
16
  r: any[];
17
17
  findOptions: FindOptions<T>;
18
18
  }>;
19
19
  private includeNone;
20
- getArray(response: DataApiResponse, request: DataApiRequest, filterBody?: any): Promise<void>;
21
- liveQuery(response: DataApiResponse, request: DataApiRequest, filterBody: any, serializeContext: () => Promise<any>, queryChannel: string): Promise<void>;
20
+ getArray(response: DataApiResponse, request: DataApiRequest, body?: any): Promise<void>;
21
+ liveQuery(response: DataApiResponse, request: DataApiRequest, body: any, serializeContext: () => Promise<any>, queryChannel: string): Promise<void>;
22
22
  private buildWhere;
23
23
  private doOnId;
24
- updateMany(response: DataApiResponse, request: DataApiRequest, body?: any): Promise<void>;
24
+ updateManyThroughPutRequest(response: DataApiResponse, request: DataApiRequest, body: any): Promise<void>;
25
+ updateManyImplementation(response: DataApiResponse, request: DataApiRequest, body: {
26
+ where: any;
27
+ set: any;
28
+ }): Promise<void>;
25
29
  actualUpdate(row: any, body: any): Promise<rowHelperImplementation<T>>;
26
30
  put(response: DataApiResponse, id: any, body: any): Promise<void>;
27
31
  actualDelete(row: any): Promise<void>;
@@ -33,8 +37,8 @@ export interface DataApiResponse {
33
37
  deleted(): void;
34
38
  created(data: any): void;
35
39
  notFound(): void;
36
- error(data: ErrorInfo): void;
37
- forbidden(): void;
40
+ error(data: ErrorInfo, entity: EntityMetadata | undefined, statusCode?: number | undefined): void;
41
+ forbidden(message?: string): void;
38
42
  progress(progress: number): void;
39
43
  }
40
44
  export interface DataApiRequest {