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
@@ -12,9 +12,129 @@ var Filter = /** @class */ (function () {
12
12
  function Filter(apply) {
13
13
  this.apply = apply;
14
14
  }
15
- Filter.createCustom = function (rawFilterTranslator, key) {
15
+ //@internal
16
+ Filter.throwErrorIfFilterIsEmpty = function (where, methodName) {
17
+ if (Filter.isFilterEmpty(where)) {
18
+ throw {
19
+ message: "".concat(methodName, ": requires a filter to protect against accidental delete/update of all rows"),
20
+ httpStatusCode: 400,
21
+ };
22
+ }
23
+ };
24
+ //@internal
25
+ Filter.isFilterEmpty = function (where) {
26
+ var e_1, _a, e_2, _b;
27
+ if (where.$and) {
28
+ try {
29
+ for (var _c = tslib_1.__values(where.$and), _d = _c.next(); !_d.done; _d = _c.next()) {
30
+ var a = _d.value;
31
+ if (!Filter.isFilterEmpty(a)) {
32
+ return false;
33
+ }
34
+ }
35
+ }
36
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
37
+ finally {
38
+ try {
39
+ if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
40
+ }
41
+ finally { if (e_1) throw e_1.error; }
42
+ }
43
+ }
44
+ if (where.$or) {
45
+ try {
46
+ for (var _e = tslib_1.__values(where.$or), _f = _e.next(); !_f.done; _f = _e.next()) {
47
+ var a = _f.value;
48
+ if (Filter.isFilterEmpty(a)) {
49
+ return true;
50
+ }
51
+ }
52
+ }
53
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
54
+ finally {
55
+ try {
56
+ if (_f && !_f.done && (_b = _e.return)) _b.call(_e);
57
+ }
58
+ finally { if (e_2) throw e_2.error; }
59
+ }
60
+ return false;
61
+ }
62
+ if (Object.keys(where).filter(function (x) { return !['$or', '$and'].includes(x); }).length == 0) {
63
+ return true;
64
+ }
65
+ return false;
66
+ };
67
+ /**
68
+ * Retrieves precise values for each property in a filter for an entity.
69
+ * @template entityType The type of the entity being filtered.
70
+ * @param metadata The metadata of the entity being filtered.
71
+ * @param filter The filter to analyze.
72
+ * @returns A promise that resolves to a FilterPreciseValues object containing the precise values for each property.
73
+ * @example
74
+ * const preciseValues = await Filter.getPreciseValues(meta, {
75
+ * status: { $ne: 'active' },
76
+ * $or: [
77
+ * { customerId: ["1", "2"] },
78
+ * { customerId: "3" }
79
+ * ]
80
+ * });
81
+ * console.log(preciseValues);
82
+ * // Output:
83
+ * // {
84
+ * // "customerId": ["1", "2", "3"], // Precise values inferred from the filter
85
+ * // "status": undefined, // Cannot infer precise values for 'status'
86
+ * // }
87
+
88
+ */
89
+ Filter.getPreciseValues = function (metadata, filter) {
90
+ return tslib_1.__awaiter(this, void 0, void 0, function () {
91
+ var result;
92
+ return tslib_1.__generator(this, function (_a) {
93
+ switch (_a.label) {
94
+ case 0:
95
+ result = new preciseValuesCollector();
96
+ return [4 /*yield*/, Filter.fromEntityFilter(metadata, filter).__applyToConsumer(result)];
97
+ case 1:
98
+ _a.sent();
99
+ return [2 /*return*/, result.preciseValues];
100
+ }
101
+ });
102
+ });
103
+ };
104
+ /**
105
+ * Retrieves precise values for each property in a filter for an entity.
106
+ * @template entityType The type of the entity being filtered.
107
+ * @param metadata The metadata of the entity being filtered.
108
+ * @param filter The filter to analyze.
109
+ * @returns A promise that resolves to a FilterPreciseValues object containing the precise values for each property.
110
+ * @example
111
+ * const preciseValues = await where.getPreciseValues();
112
+ * console.log(preciseValues);
113
+ * // Output:
114
+ * // {
115
+ * // "customerId": ["1", "2", "3"], // Precise values inferred from the filter
116
+ * // "status": undefined, // Cannot infer precise values for 'status'
117
+ * // }
118
+
119
+ */
120
+ Filter.prototype.getPreciseValues = function () {
121
+ return tslib_1.__awaiter(this, void 0, void 0, function () {
122
+ var result;
123
+ return tslib_1.__generator(this, function (_a) {
124
+ switch (_a.label) {
125
+ case 0:
126
+ result = new preciseValuesCollector();
127
+ return [4 /*yield*/, this.__applyToConsumer(result)];
128
+ case 1:
129
+ _a.sent();
130
+ return [2 /*return*/, result.preciseValues];
131
+ }
132
+ });
133
+ });
134
+ };
135
+ Filter.createCustom = function (translator, key) {
16
136
  if (key === void 0) { key = ''; }
17
- var rawFilterInfo = { key: key, rawFilterTranslator: rawFilterTranslator };
137
+ var rawFilterInfo = { key: key, rawFilterTranslator: translator };
18
138
  return Object.assign(function (x) {
19
139
  var _a;
20
140
  var z = {};
@@ -206,7 +326,6 @@ var Filter = /** @class */ (function () {
206
326
  });
207
327
  });
208
328
  };
209
- //@internal
210
329
  Filter.prototype.toJson = function () {
211
330
  var r = new FilterSerializer();
212
331
  this.__applyToConsumer(r);
@@ -317,19 +436,19 @@ var filterHelper = /** @class */ (function () {
317
436
  filterHelper.prototype.isNotIn = function (values) {
318
437
  var _this = this;
319
438
  return new Filter(function (add) {
320
- var e_1, _a;
439
+ var e_3, _a;
321
440
  try {
322
441
  for (var values_1 = tslib_1.__values(values), values_1_1 = values_1.next(); !values_1_1.done; values_1_1 = values_1.next()) {
323
442
  var v = values_1_1.value;
324
443
  add.isDifferentFrom(_this.metadata, _this.processVal(v));
325
444
  }
326
445
  }
327
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
446
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
328
447
  finally {
329
448
  try {
330
449
  if (values_1_1 && !values_1_1.done && (_a = values_1.return)) _a.call(values_1);
331
450
  }
332
- finally { if (e_1) throw e_1.error; }
451
+ finally { if (e_3) throw e_3.error; }
333
452
  }
334
453
  });
335
454
  };
@@ -462,7 +581,7 @@ var AndFilter = /** @class */ (function (_super) {
462
581
  filters[_i] = arguments[_i];
463
582
  }
464
583
  var _this = _super.call(this, function (add) {
465
- var e_2, _a;
584
+ var e_4, _a;
466
585
  try {
467
586
  for (var _b = tslib_1.__values(_this.filters), _c = _b.next(); !_c.done; _c = _b.next()) {
468
587
  var iterator = _c.value;
@@ -470,12 +589,12 @@ var AndFilter = /** @class */ (function (_super) {
470
589
  iterator.__applyToConsumer(add);
471
590
  }
472
591
  }
473
- catch (e_2_1) { e_2 = { error: e_2_1 }; }
592
+ catch (e_4_1) { e_4 = { error: e_4_1 }; }
474
593
  finally {
475
594
  try {
476
595
  if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
477
596
  }
478
- finally { if (e_2) throw e_2.error; }
597
+ finally { if (e_4) throw e_4.error; }
479
598
  }
480
599
  }) || this;
481
600
  _this.filters = filters;
@@ -591,17 +710,30 @@ function entityFilterToJson(entityDefs, where) {
591
710
  }
592
711
  exports.entityFilterToJson = entityFilterToJson;
593
712
  function buildFilterFromRequestParameters(entity, filterInfo) {
594
- var where = [];
713
+ var where = {};
714
+ function addAnd(what) {
715
+ if (!where.$and) {
716
+ where.$and = [];
717
+ }
718
+ where.$and.push(what);
719
+ }
720
+ function addToFilterObject(key, val) {
721
+ var _a;
722
+ if (where[key] === undefined)
723
+ where[key] = val;
724
+ else {
725
+ addAnd((_a = {}, _a[key] = val, _a));
726
+ }
727
+ }
728
+ ;
595
729
  tslib_1.__spreadArray([], tslib_1.__read(entity.fields), false).forEach(function (col) {
596
- var _a, _b;
597
730
  function addFilter(operation, theFilter, jsonArray, asString) {
598
- var e_3, _a;
731
+ var e_5, _a;
599
732
  if (jsonArray === void 0) { jsonArray = false; }
600
733
  if (asString === void 0) { asString = false; }
601
734
  var val = filterInfo.get(col.key + operation);
602
735
  if (val !== undefined) {
603
736
  var addFilter_1 = function (val) {
604
- var _a;
605
737
  var theVal = val;
606
738
  if (jsonArray) {
607
739
  var arr = void 0;
@@ -618,7 +750,7 @@ function buildFilterFromRequestParameters(entity, filterInfo) {
618
750
  }
619
751
  var f = theFilter(theVal);
620
752
  if (f !== undefined) {
621
- where.push((_a = {}, _a[col.key] = f, _a));
753
+ addToFilterObject(col.key, f);
622
754
  }
623
755
  };
624
756
  if (!jsonArray && val instanceof Array) {
@@ -638,12 +770,12 @@ function buildFilterFromRequestParameters(entity, filterInfo) {
638
770
  addFilter_1(x);
639
771
  }
640
772
  }
641
- catch (e_3_1) { e_3 = { error: e_3_1 }; }
773
+ catch (e_5_1) { e_5 = { error: e_5_1 }; }
642
774
  finally {
643
775
  try {
644
776
  if (array_1_1 && !array_1_1.done && (_a = array_1.return)) _a.call(array_1);
645
777
  }
646
- finally { if (e_3) throw e_3.error; }
778
+ finally { if (e_5) throw e_5.error; }
647
779
  }
648
780
  }
649
781
  }
@@ -662,10 +794,10 @@ function buildFilterFromRequestParameters(entity, filterInfo) {
662
794
  case 'y':
663
795
  case 'true':
664
796
  case 'yes':
665
- where.push((_a = {}, _a[col.key] = null, _a));
797
+ addToFilterObject(col.key, null);
666
798
  break;
667
799
  default:
668
- where.push((_b = {}, _b[col.key] = { $ne: null }, _b));
800
+ addToFilterObject(col.key, { $ne: null });
669
801
  break;
670
802
  }
671
803
  }
@@ -682,12 +814,19 @@ function buildFilterFromRequestParameters(entity, filterInfo) {
682
814
  });
683
815
  }),
684
816
  }); });
685
- if (or.length == 1)
686
- where.push(or[0]);
687
- else
688
- where.push({
817
+ if (or.length == 1) {
818
+ if (!where.$or) {
819
+ where.$or = or[0].$or;
820
+ }
821
+ else {
822
+ where.$or.push(or[0].$or);
823
+ }
824
+ }
825
+ else {
826
+ addAnd({
689
827
  $and: or,
690
828
  });
829
+ }
691
830
  }
692
831
  var _loop_3 = function (key) {
693
832
  var element = entity.entityType[key];
@@ -697,10 +836,9 @@ function buildFilterFromRequestParameters(entity, filterInfo) {
697
836
  var custom = filterInfo.get(exports.customUrlToken + key);
698
837
  if (custom !== undefined) {
699
838
  var addItem_1 = function (item) {
700
- var _a;
701
839
  if (item[customArrayToken] != undefined)
702
840
  item = item[customArrayToken];
703
- where.push((_a = {}, _a[exports.customUrlToken + key] = item, _a));
841
+ addToFilterObject(exports.customUrlToken + key, item);
704
842
  };
705
843
  if (Array.isArray(custom)) {
706
844
  custom.forEach(function (item) { return addItem_1(item); });
@@ -713,11 +851,9 @@ function buildFilterFromRequestParameters(entity, filterInfo) {
713
851
  for (var key in entity.entityType) {
714
852
  _loop_3(key);
715
853
  }
716
- if (where.length == 1)
717
- return where[0];
718
- return { $and: where };
854
+ return where;
719
855
  function separateArrayFromInnerArray(val) {
720
- var e_4, _a;
856
+ var e_6, _a;
721
857
  if (!Array.isArray(val))
722
858
  return [val];
723
859
  var nonArray = [], array = [];
@@ -731,12 +867,12 @@ function buildFilterFromRequestParameters(entity, filterInfo) {
731
867
  nonArray.push(v);
732
868
  }
733
869
  }
734
- catch (e_4_1) { e_4 = { error: e_4_1 }; }
870
+ catch (e_6_1) { e_6 = { error: e_6_1 }; }
735
871
  finally {
736
872
  try {
737
873
  if (val_1_1 && !val_1_1.done && (_a = val_1.return)) _a.call(val_1);
738
874
  }
739
- finally { if (e_4) throw e_4.error; }
875
+ finally { if (e_6) throw e_6.error; }
740
876
  }
741
877
  array.push(nonArray);
742
878
  return array;
@@ -874,5 +1010,149 @@ function __updateEntityBasedOnWhere(entityDefs, where, r) {
874
1010
  }
875
1011
  }
876
1012
  exports.__updateEntityBasedOnWhere = __updateEntityBasedOnWhere;
877
- // toRaw of default remult threw and exception
878
- // toRaw didn't respect
1013
+ var preciseValuesCollector = /** @class */ (function () {
1014
+ function preciseValuesCollector() {
1015
+ this.rawValues = {};
1016
+ this.preciseValues = new Proxy(this.rawValues, {
1017
+ get: function (target, prop) {
1018
+ if (prop in target) {
1019
+ var result = target[prop];
1020
+ if (result.bad)
1021
+ return undefined;
1022
+ if (result.values.length > 0) {
1023
+ var relInfo_1 = (0, relationInfoMember_js_1.getRelationFieldInfo)(result.field);
1024
+ if (relInfo_1) {
1025
+ if (relInfo_1.type === 'reference') {
1026
+ return result.values.map(function (x) {
1027
+ return relInfo_1.toRepo.metadata.idMetadata.getIdFilter(x);
1028
+ });
1029
+ }
1030
+ else
1031
+ throw new Error('Only relations toOne without field are supported.');
1032
+ }
1033
+ return result.values;
1034
+ }
1035
+ }
1036
+ return undefined;
1037
+ },
1038
+ });
1039
+ }
1040
+ preciseValuesCollector.prototype.ok = function (col) {
1041
+ var _a;
1042
+ var val = [];
1043
+ for (var _i = 1; _i < arguments.length; _i++) {
1044
+ val[_i - 1] = arguments[_i];
1045
+ }
1046
+ var x = this.rawValues[col.key];
1047
+ if (!x) {
1048
+ this.rawValues[col.key] = {
1049
+ field: col,
1050
+ bad: false,
1051
+ values: tslib_1.__spreadArray([], tslib_1.__read(val), false),
1052
+ };
1053
+ }
1054
+ else {
1055
+ (_a = x.values).push.apply(_a, tslib_1.__spreadArray([], tslib_1.__read(val.filter(function (y) { return !x.values.includes(y); })), false));
1056
+ }
1057
+ };
1058
+ preciseValuesCollector.prototype.notOk = function (col) {
1059
+ var x = this.rawValues[col.key];
1060
+ if (!x) {
1061
+ this.rawValues[col.key] = {
1062
+ field: col,
1063
+ bad: true,
1064
+ values: [],
1065
+ };
1066
+ }
1067
+ else {
1068
+ x.bad = true;
1069
+ }
1070
+ };
1071
+ preciseValuesCollector.prototype.or = function (orElements) {
1072
+ var e_7, _a, e_8, _b;
1073
+ var result = orElements.map(function (or) {
1074
+ var x = new preciseValuesCollector();
1075
+ or.__applyToConsumer(x);
1076
+ return x;
1077
+ });
1078
+ try {
1079
+ for (var result_1 = tslib_1.__values(result), result_1_1 = result_1.next(); !result_1_1.done; result_1_1 = result_1.next()) {
1080
+ var or = result_1_1.value;
1081
+ for (var key in or.rawValues) {
1082
+ if (Object.prototype.hasOwnProperty.call(or.rawValues, key)) {
1083
+ var element = or.rawValues[key];
1084
+ if (element) {
1085
+ if (element.bad)
1086
+ this.notOk(element.field);
1087
+ else {
1088
+ this.ok.apply(this, tslib_1.__spreadArray([element.field], tslib_1.__read(element.values), false));
1089
+ }
1090
+ }
1091
+ }
1092
+ }
1093
+ }
1094
+ }
1095
+ catch (e_7_1) { e_7 = { error: e_7_1 }; }
1096
+ finally {
1097
+ try {
1098
+ if (result_1_1 && !result_1_1.done && (_a = result_1.return)) _a.call(result_1);
1099
+ }
1100
+ finally { if (e_7) throw e_7.error; }
1101
+ }
1102
+ for (var key in this.rawValues) {
1103
+ if (Object.prototype.hasOwnProperty.call(this.rawValues, key)) {
1104
+ try {
1105
+ for (var result_2 = (e_8 = void 0, tslib_1.__values(result)), result_2_1 = result_2.next(); !result_2_1.done; result_2_1 = result_2.next()) {
1106
+ var r = result_2_1.value;
1107
+ var element = r.rawValues[key];
1108
+ if (!element)
1109
+ this.notOk(this.rawValues[key].field);
1110
+ }
1111
+ }
1112
+ catch (e_8_1) { e_8 = { error: e_8_1 }; }
1113
+ finally {
1114
+ try {
1115
+ if (result_2_1 && !result_2_1.done && (_b = result_2.return)) _b.call(result_2);
1116
+ }
1117
+ finally { if (e_8) throw e_8.error; }
1118
+ }
1119
+ }
1120
+ }
1121
+ };
1122
+ preciseValuesCollector.prototype.isEqualTo = function (col, val) {
1123
+ this.ok(col, val);
1124
+ };
1125
+ preciseValuesCollector.prototype.isDifferentFrom = function (col, val) {
1126
+ this.notOk(col);
1127
+ };
1128
+ preciseValuesCollector.prototype.isNull = function (col) {
1129
+ this.ok(col, null);
1130
+ };
1131
+ preciseValuesCollector.prototype.isNotNull = function (col) {
1132
+ this.notOk(col);
1133
+ };
1134
+ preciseValuesCollector.prototype.isGreaterOrEqualTo = function (col, val) {
1135
+ this.notOk(col);
1136
+ };
1137
+ preciseValuesCollector.prototype.isGreaterThan = function (col, val) {
1138
+ this.notOk(col);
1139
+ };
1140
+ preciseValuesCollector.prototype.isLessOrEqualTo = function (col, val) {
1141
+ this.notOk(col);
1142
+ };
1143
+ preciseValuesCollector.prototype.isLessThan = function (col, val) {
1144
+ this.notOk(col);
1145
+ };
1146
+ preciseValuesCollector.prototype.containsCaseInsensitive = function (col, val) {
1147
+ this.notOk(col);
1148
+ };
1149
+ preciseValuesCollector.prototype.notContainsCaseInsensitive = function (col, val) {
1150
+ this.notOk(col);
1151
+ };
1152
+ preciseValuesCollector.prototype.isIn = function (col, val) {
1153
+ this.ok.apply(this, tslib_1.__spreadArray([col], tslib_1.__read(val), false));
1154
+ };
1155
+ preciseValuesCollector.prototype.custom = function (key, customItem) { };
1156
+ preciseValuesCollector.prototype.databaseCustom = function (databaseCustom) { };
1157
+ return preciseValuesCollector;
1158
+ }());
@@ -0,0 +1,2 @@
1
+ export declare function isOfType<T>(obj: any, checkMethod: keyof T): obj is T;
2
+ export declare function cast<T>(obj: any, checkMethod: keyof T): T;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.cast = exports.isOfType = void 0;
4
+ function isOfType(obj, checkMethod) {
5
+ return typeof obj[checkMethod] !== 'undefined';
6
+ }
7
+ exports.isOfType = isOfType;
8
+ function cast(obj, checkMethod) {
9
+ if (isOfType(obj, checkMethod)) {
10
+ return obj;
11
+ }
12
+ throw new Error("Object is not of type ".concat(checkMethod.toString()));
13
+ }
14
+ exports.cast = cast;
@@ -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
  }
@@ -9,6 +9,10 @@ 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 addValidator_js_1 = require("./addValidator.js");
13
+ var validateNumber = (0, validators_js_1.createValueValidator)(function (x) {
14
+ return !isNaN(x) && isFinite(x);
15
+ });
12
16
  var Fields = /** @class */ (function () {
13
17
  function Fields() {
14
18
  }
@@ -63,6 +67,7 @@ var Fields = /** @class */ (function () {
63
67
  return Field.apply(void 0, tslib_1.__spreadArray([function () { return Number; },
64
68
  {
65
69
  valueConverter: valueConverters_js_1.ValueConverters.Integer,
70
+ validate: validateNumber,
66
71
  }], tslib_1.__read(options), false));
67
72
  };
68
73
  Fields.autoIncrement = function () {
@@ -82,7 +87,9 @@ var Fields = /** @class */ (function () {
82
87
  for (var _i = 0; _i < arguments.length; _i++) {
83
88
  options[_i] = arguments[_i];
84
89
  }
85
- return Field.apply(void 0, tslib_1.__spreadArray([function () { return Number; }], tslib_1.__read(options), false));
90
+ return Field.apply(void 0, tslib_1.__spreadArray([function () { return Number; }, {
91
+ validate: validateNumber,
92
+ }], tslib_1.__read(options), false));
86
93
  };
87
94
  Fields.createdAt = function () {
88
95
  var options = [];
@@ -127,6 +134,11 @@ var Fields = /** @class */ (function () {
127
134
  },
128
135
  }], tslib_1.__read(options), false));
129
136
  };
137
+ /**
138
+ * A CUID (Collision Resistant Unique Identifier) field.
139
+ * This id value is determined on the backend on insert, and can't be updated through the API.
140
+ * The CUID is generated using the `@paralleldrive/cuid2` npm package.
141
+ */
130
142
  Fields.cuid = function () {
131
143
  var options = [];
132
144
  for (var _i = 0; _i < arguments.length; _i++) {
@@ -142,6 +154,71 @@ var Fields = /** @class */ (function () {
142
154
  },
143
155
  }], tslib_1.__read(options), false));
144
156
  };
157
+ /**
158
+ * Defines a field that can hold a value from a specified set of string literals.
159
+ * @param {() => readonly valueType[]} optionalValues - A function that returns an array of allowed string literals.
160
+ * @returns {ClassFieldDecorator<entityType, valueType | undefined>} - A class field decorator.
161
+ *
162
+ * @example
163
+
164
+ * class MyEntity {
165
+ * .@Fields.literal(() => ['open', 'closed', 'frozen', 'in progress'] as const)
166
+ * status: 'open' | 'closed' | 'frozen' | 'in progress' = 'open';
167
+ * }
168
+
169
+ *
170
+ * // This defines a field `status` in `MyEntity` that can only hold the values 'open', 'closed', 'frozen', or 'in progress'.
171
+ *
172
+ * @example
173
+ * // For better reusability and maintainability:
174
+
175
+ * const statuses = ['open', 'closed', 'frozen', 'in progress'] as const;
176
+ * type StatusType = typeof statuses[number];
177
+ *
178
+ * class MyEntity {
179
+ * .@Fields.literal(() => statuses)
180
+ * status: StatusType = 'open';
181
+ * }
182
+
183
+ *
184
+ * // This approach allows easy management and updates of the allowed values for the `status` field.
185
+ */
186
+ Fields.literal = function (optionalValues) {
187
+ var options = [];
188
+ for (var _i = 1; _i < arguments.length; _i++) {
189
+ options[_i - 1] = arguments[_i];
190
+ }
191
+ return Fields.string.apply(Fields, tslib_1.__spreadArray([{
192
+ validate: function (entity, event) { return validators_js_1.Validators.in(optionalValues())(entity, event); }
193
+ }], tslib_1.__read(options), false));
194
+ };
195
+ Fields.enum = function (enumType) {
196
+ var options = [];
197
+ for (var _i = 1; _i < arguments.length; _i++) {
198
+ options[_i - 1] = arguments[_i];
199
+ }
200
+ var valueConverter;
201
+ return Field.apply(void 0, tslib_1.__spreadArray(tslib_1.__spreadArray([function () {
202
+ //@ts-ignore
203
+ return (enumType());
204
+ },
205
+ {
206
+ validate: function (entity, event) { return validators_js_1.Validators.enum(enumType())(entity, event); }
207
+ }], tslib_1.__read(options), false), [function (options) {
208
+ if (valueConverter === undefined) {
209
+ var enumObj = enumType();
210
+ var enumValues = (0, validators_js_1.getEnumValues)(enumObj);
211
+ valueConverter = enumValues.find(function (x) { return typeof x === "string"; }) ? valueConverters_js_1.ValueConverters.String : valueConverters_js_1.ValueConverters.Integer;
212
+ }
213
+ if (!options.valueConverter) {
214
+ options.valueConverter = valueConverter;
215
+ }
216
+ else if (!options.valueConverter.fieldTypeInDb) {
217
+ //@ts-ignore
218
+ options.valueConverter.fieldTypeInDb = valueConverter.fieldTypeInDb;
219
+ }
220
+ }], false));
221
+ };
145
222
  Fields.string = function () {
146
223
  var options = [];
147
224
  for (var _i = 0; _i < arguments.length; _i++) {
@@ -249,13 +326,13 @@ function Field(valueType) {
249
326
  var factory = function (remult) {
250
327
  var r = (0, RepositoryImplementation_js_1.buildOptions)(options, remult);
251
328
  if (r.required) {
252
- r.validate = addValidator(r.validate, validators_js_1.Validators.required);
329
+ r.validate = (0, addValidator_js_1.addValidator)(r.validate, validators_js_1.Validators.required, true);
253
330
  }
254
331
  if (r.maxLength) {
255
- r.validate = addValidator(r.validate, validators_js_1.Validators.maxLength(r.maxLength));
332
+ r.validate = (0, addValidator_js_1.addValidator)(r.validate, validators_js_1.Validators.maxLength(r.maxLength));
256
333
  }
257
334
  if (r.minLength) {
258
- r.validate = addValidator(r.validate, validators_js_1.Validators.minLength(r.minLength));
335
+ r.validate = (0, addValidator_js_1.addValidator)(r.validate, validators_js_1.Validators.minLength(r.minLength));
259
336
  }
260
337
  if (!r.valueType && valueType) {
261
338
  r.valueType = valueType();
@@ -305,18 +382,3 @@ function checkTarget(target) {
305
382
  throw new Error("Set the 'experimentalDecorators:true' option in your 'tsconfig' or 'jsconfig' (target undefined)");
306
383
  }
307
384
  exports.checkTarget = checkTarget;
308
- function addValidator(validators, newValidator, atStart) {
309
- if (atStart === void 0) { atStart = false; }
310
- if (!newValidator)
311
- return;
312
- var newValidators = Array.isArray(newValidator)
313
- ? newValidator
314
- : [newValidator];
315
- var validatorsArray = Array.isArray(validators)
316
- ? validators
317
- : validators
318
- ? [validators]
319
- : [];
320
- return atStart
321
- ? tslib_1.__spreadArray(tslib_1.__spreadArray([], tslib_1.__read(newValidators), false), tslib_1.__read(validatorsArray), false) : tslib_1.__spreadArray(tslib_1.__spreadArray([], tslib_1.__read(validatorsArray), false), tslib_1.__read(newValidators), false);
322
- }