remult 0.13.28 → 0.14.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "remult",
3
- "version": "0.13.28",
3
+ "version": "0.14.2",
4
4
  "description": "A CRUD framework for full-stack TypeScript",
5
5
  "homepage": "https://remult.dev/",
6
6
  "repository": {
package/readme.md CHANGED
@@ -21,6 +21,9 @@
21
21
  <a href="https://discord.gg/GXHk7ZfuG5">
22
22
  <img alt="chat on discord" src="https://img.shields.io/badge/chat-on%20discord-blueviolet"/>
23
23
  </a>
24
+ <a href="https://twitter.com/remultjs">
25
+ <img alt="Twitter Follow" src="https://img.shields.io/twitter/follow/remultjs?style=social">
26
+ </a>
24
27
  </div>
25
28
 
26
29
  ## What is Remult?
@@ -114,24 +117,29 @@ static async increasePriceOfTofu(priceIncrease: number, remult?: Remult) {
114
117
  ### :ballot_box_with_check: Data validation and constraints - defined once
115
118
 
116
119
  ```ts
117
- import { Entity, Fields } from 'remult';
120
+ import { Entity, Fields, Validators } from 'remult';
118
121
 
119
122
  @Entity('products', {
120
123
  allowApiCrud: true
121
124
  })
122
125
  export class Product {
126
+ @Fields.string({
127
+ validate: Validators.required
128
+ })
129
+ name = '';
130
+
123
131
  @Fields.string<Product>({
124
132
  validate: product => {
125
- if (product.name.trim().length == 0)
126
- throw 'required';
133
+ if (product.description.trim().length < 50)
134
+ throw "too short";
127
135
  }
128
136
  })
129
- name = '';
137
+ description = '';
130
138
 
131
139
  @Fields.number({
132
140
  validate: (_, field) => {
133
141
  if (field.value < 0)
134
- throw "must not be less than 0";
142
+ field.error = "must not be less than 0"; // or: throw "must not be less than 0";
135
143
  }
136
144
  })
137
145
  unitPrice = 0;
@@ -181,7 +189,11 @@ export class Article {
181
189
  [CRM demo](https://github.com/remult/crm-demo) with a React + [MUI](https://mui.com) front-end and Postgres database.
182
190
 
183
191
  ## Contributing
184
- Contributions are welcome. See [CONTRIBUTING](CONTRIBUTING.md).
192
+ Contributions are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md).
193
+
194
+ * :speech_balloon: Any feedback or suggestions? Start a [discussion](https://github.com/remult/remult/discussions).
195
+ * :muscle: Want to help out? Look for "help wanted" labeled [issues](https://github.com/remult/remult/issues).
196
+ * :star: Give this repo a star.
185
197
 
186
198
  ## License
187
199
  Remult is [MIT Licensed](LICENSE).
@@ -1 +1,5 @@
1
- export { remultExpress, RemultExpressBridge } from './server/expressBridge';
1
+ import { RemultMiddlewareOptions } from './server/expressBridge';
2
+ export declare function remultExpress(options?: RemultMiddlewareOptions & {
3
+ bodyParser?: boolean;
4
+ bodySizeLimit?: string;
5
+ }): import("./server/expressBridge").RemultExpressBridge;
package/remult-express.js CHANGED
@@ -1,5 +1,20 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.remultExpress = void 0;
4
+ var express = require("express");
4
5
  var expressBridge_1 = require("./server/expressBridge");
5
- Object.defineProperty(exports, "remultExpress", { enumerable: true, get: function () { return expressBridge_1.remultExpress; } });
6
+ function remultExpress(options) {
7
+ var app = express.Router();
8
+ if (!options) {
9
+ options = {};
10
+ }
11
+ if (options.bodySizeLimit === undefined) {
12
+ options.bodySizeLimit = '10mb';
13
+ }
14
+ if ((options === null || options === void 0 ? void 0 : options.bodyParser) !== false) {
15
+ app.use(express.json({ limit: options.bodySizeLimit }));
16
+ app.use(express.urlencoded({ extended: true, limit: options.bodySizeLimit }));
17
+ }
18
+ return expressBridge_1.remultMiddlewareBase(app, options);
19
+ }
20
+ exports.remultExpress = remultExpress;
@@ -0,0 +1,2 @@
1
+ import { RemultMiddlewareOptions } from './server/expressBridge';
2
+ export declare function remultMiddleware(options?: RemultMiddlewareOptions): import("./server/expressBridge").RemultExpressBridge;
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.remultMiddleware = void 0;
4
+ var expressBridge_1 = require("./server/expressBridge");
5
+ function remultMiddleware(options) {
6
+ var m = new middleware();
7
+ var app = Object.assign(m, function (req, res, next) { return m.handleRequest(req, res, next); });
8
+ return expressBridge_1.remultMiddlewareBase(app, options);
9
+ }
10
+ exports.remultMiddleware = remultMiddleware;
11
+ var middleware = /** @class */ (function () {
12
+ function middleware() {
13
+ this.map = new Map();
14
+ }
15
+ middleware.prototype.route = function (path) {
16
+ //consider using:
17
+ //* https://raw.githubusercontent.com/cmorten/opine/main/src/utils/pathToRegex.ts
18
+ //* https://github.com/pillarjs/path-to-regexp
19
+ var r = path.toLowerCase();
20
+ var m = new Map();
21
+ this.map.set(r, m);
22
+ var route = {
23
+ get: function (h) {
24
+ m.set("get", h);
25
+ return route;
26
+ },
27
+ put: function (h) {
28
+ m.set("put", h);
29
+ return route;
30
+ },
31
+ post: function (h) {
32
+ m.set("post", h);
33
+ return route;
34
+ },
35
+ delete: function (h) {
36
+ m.set("delete", h);
37
+ return route;
38
+ }
39
+ };
40
+ return route;
41
+ };
42
+ middleware.prototype.handleRequest = function (req, res, next) {
43
+ var lowerPath = req.path.toLowerCase();
44
+ var m = this.map.get(lowerPath);
45
+ if (m) {
46
+ var h = m.get(req.method.toLowerCase());
47
+ if (h) {
48
+ h(req, res, next);
49
+ return;
50
+ }
51
+ }
52
+ var idPosition = req.path.lastIndexOf('/');
53
+ if (idPosition >= 0) {
54
+ lowerPath = req.path.substring(0, idPosition) + '/:id';
55
+ m = this.map.get(lowerPath);
56
+ if (m) {
57
+ var h = m.get(req.method.toLowerCase());
58
+ if (h) {
59
+ req.params.id = req.path.substring(idPosition + 1);
60
+ h(req, res, next);
61
+ return;
62
+ }
63
+ }
64
+ }
65
+ console.log(req.path);
66
+ next();
67
+ };
68
+ return middleware;
69
+ }());
@@ -1,20 +1,17 @@
1
- import { DataProvider, Remult, IdEntity } from '../';
2
- import * as express from 'express';
3
- import { Repository } from '../src/remult3';
1
+ import { DataProvider, Remult, IdEntity, Repository } from '../';
4
2
  import { queuedJobInfoResponse } from '../src/server-action';
5
3
  import { DataApi, DataApiRequest, DataApiResponse } from '../src/data-api';
6
4
  import { AllowedForInstance } from '../src/context';
7
5
  import { ClassType } from '../classType';
8
- export declare function remultExpress(options?: {
6
+ export declare type RemultMiddlewareOptions = {
9
7
  /** Sets a database connection for Remult.
10
8
  *
11
9
  * @see [Connecting to a Database](https://remult.dev/docs/databases.html).
12
10
  */
13
11
  dataProvider?: DataProvider | Promise<DataProvider> | (() => Promise<DataProvider | undefined>);
14
- bodySizeLimit?: string;
15
12
  disableAutoApi?: boolean;
16
13
  queueStorage?: QueueStorage;
17
- initRequest?: (remult: Remult, origReq: express.Request) => Promise<void>;
14
+ initRequest?: (remult: Remult, origReq: GenericRequest) => Promise<void>;
18
15
  initApi?: (remult: Remult) => void | Promise<void>;
19
16
  logApiEndPoints?: boolean;
20
17
  defaultGetLimit?: number;
@@ -22,42 +19,70 @@ export declare function remultExpress(options?: {
22
19
  controllers?: ClassType<any>[];
23
20
  bodyParser?: boolean;
24
21
  rootPath?: string;
25
- }): RemultExpressBridge;
26
- export interface RemultExpressBridge extends express.RequestHandler {
27
- getRemult(req: express.Request): Promise<Remult>;
22
+ };
23
+ export declare function remultMiddlewareBase(app: GenericRouter, options: RemultMiddlewareOptions): RemultExpressBridge;
24
+ export interface RemultExpressBridge extends GenericRequestHandler {
25
+ getRemult(req: GenericRequest): Promise<Remult>;
28
26
  openApiDoc(options: {
29
27
  title: string;
30
28
  }): any;
31
29
  addArea(rootUrl: string): any;
32
30
  }
31
+ export interface GenericRequest {
32
+ method: any;
33
+ path: any;
34
+ originalUrl: any;
35
+ query: any;
36
+ body: any;
37
+ params: any;
38
+ }
39
+ export interface GenericResponse {
40
+ status(arg0: number): any;
41
+ statusCode: number;
42
+ json(data: any): any;
43
+ writeHead(status: number): {
44
+ end: VoidFunction;
45
+ };
46
+ }
47
+ export declare type GenericRouter = GenericRequestHandler & {
48
+ route(path: string): SpecificRoute;
49
+ };
50
+ export declare type SpecificRoute = {
51
+ get(handler: GenericRequestHandler): SpecificRoute;
52
+ put(handler: GenericRequestHandler): SpecificRoute;
53
+ post(handler: GenericRequestHandler): SpecificRoute;
54
+ delete(handler: GenericRequestHandler): SpecificRoute;
55
+ };
56
+ export declare type GenericRequestHandler = (req: GenericRequest, res: GenericResponse, next: VoidFunction) => void;
33
57
  declare class ExpressBridge {
34
58
  private app;
35
59
  queue: inProcessQueueHandler;
36
- initRequest: (remult: Remult, origReq: express.Request) => Promise<void>;
60
+ initRequest: (remult: Remult, origReq: GenericRequest) => Promise<void>;
37
61
  dataProvider: DataProvider | Promise<DataProvider>;
38
62
  openApiDoc(options: {
39
63
  title: string;
64
+ version?: string;
40
65
  }): any;
41
66
  backendMethodsOpenApi: {
42
67
  path: string;
43
68
  allowed: AllowedForInstance<any>;
44
69
  tag: string;
45
70
  }[];
46
- constructor(app: express.Router, queue: inProcessQueueHandler, initRequest: (remult: Remult, origReq: express.Request) => Promise<void>, dataProvider: DataProvider | Promise<DataProvider>);
71
+ constructor(app: GenericRouter, queue: inProcessQueueHandler, initRequest: (remult: Remult, origReq: GenericRequest) => Promise<void>, dataProvider: DataProvider | Promise<DataProvider>);
47
72
  logApiEndPoints: boolean;
48
73
  private firstArea;
49
74
  addArea(rootUrl: string): SiteArea;
50
- getRemult(req?: express.Request): Promise<Remult>;
75
+ getRemult(req?: GenericRequest): Promise<Remult>;
51
76
  }
52
77
  export declare class SiteArea {
53
78
  private bridge;
54
79
  private app;
55
80
  private rootUrl;
56
81
  private logApiEndpoints;
57
- constructor(bridge: ExpressBridge, app: express.Router, rootUrl: string, logApiEndpoints: boolean);
82
+ constructor(bridge: ExpressBridge, app: GenericRouter, rootUrl: string, logApiEndpoints: boolean);
58
83
  add(key: string, dataApiFactory: ((req: Remult) => DataApi)): void;
59
- process(what: (remult: Remult, myReq: DataApiRequest, myRes: DataApiResponse, origReq: express.Request) => Promise<void>): (req: express.Request, res: express.Response) => Promise<void>;
60
- getRemult(req: express.Request): Promise<Remult>;
84
+ process(what: (remult: Remult, myReq: DataApiRequest, myRes: DataApiResponse, origReq: GenericRequest) => Promise<void>): (req: GenericRequest, res: GenericResponse) => Promise<void>;
85
+ getRemult(req: GenericRequest): Promise<Remult>;
61
86
  initQueue(): void;
62
87
  addAction(action: {
63
88
  __register: (reg: (url: string, queue: boolean, allowed: AllowedForInstance<any>, what: ((data: any, req: Remult, res: DataApiResponse) => void)) => void) => void;
@@ -66,7 +91,7 @@ export declare class SiteArea {
66
91
  export declare class ExpressRequestBridgeToDataApiRequest implements DataApiRequest {
67
92
  private r;
68
93
  get(key: string): any;
69
- constructor(r: express.Request);
94
+ constructor(r: GenericRequest);
70
95
  }
71
96
  declare class inProcessQueueHandler {
72
97
  private storage;
@@ -1,20 +1,17 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.JobsInQueueEntity = exports.EntityQueueStorage = exports.ExpressRequestBridgeToDataApiRequest = exports.SiteArea = exports.remultExpress = void 0;
3
+ exports.JobsInQueueEntity = exports.EntityQueueStorage = exports.ExpressRequestBridgeToDataApiRequest = exports.SiteArea = exports.remultMiddlewareBase = void 0;
4
4
  var tslib_1 = require("tslib");
5
5
  var __1 = require("../");
6
- var express = require("express");
7
6
  var register_actions_on_server_1 = require("./register-actions-on-server");
8
7
  var register_entities_on_server_1 = require("./register-entities-on-server");
9
8
  var JsonEntityFileStorage_1 = require("./JsonEntityFileStorage");
10
- var json_data_provider_1 = require("../src/data-providers/json-data-provider");
11
- var remult3_1 = require("../src/remult3");
12
9
  var server_action_1 = require("../src/server-action");
13
10
  var data_api_1 = require("../src/data-api");
14
11
  var context_1 = require("../src/context");
15
- function remultExpress(options) {
12
+ var remult3_1 = require("../src/remult3");
13
+ function remultMiddlewareBase(app, options) {
16
14
  var _this = this;
17
- var app = express.Router();
18
15
  if (!options) {
19
16
  options = {};
20
17
  }
@@ -22,16 +19,9 @@ function remultExpress(options) {
22
19
  if (options.defaultGetLimit) {
23
20
  data_api_1.DataApi.defaultGetLimit = options.defaultGetLimit;
24
21
  }
25
- if (options.bodySizeLimit === undefined) {
26
- options.bodySizeLimit = '10mb';
27
- }
28
22
  if (!options.queueStorage) {
29
23
  options.queueStorage = new InMemoryQueueStorage();
30
24
  }
31
- if ((options === null || options === void 0 ? void 0 : options.bodyParser) !== false) {
32
- app.use(express.json({ limit: options.bodySizeLimit }));
33
- app.use(express.urlencoded({ extended: true, limit: options.bodySizeLimit }));
34
- }
35
25
  var dataProvider;
36
26
  if (typeof options.dataProvider === "function") {
37
27
  dataProvider = options.dataProvider();
@@ -41,7 +31,7 @@ function remultExpress(options) {
41
31
  dataProvider = dataProvider.then(function (dp) {
42
32
  if (dp)
43
33
  return dp;
44
- return new json_data_provider_1.JsonDataProvider(new JsonEntityFileStorage_1.JsonEntityFileStorage('./db'));
34
+ return new __1.JsonDataProvider(new JsonEntityFileStorage_1.JsonEntityFileStorage('./db'));
45
35
  });
46
36
  if (options.initApi) {
47
37
  dataProvider = dataProvider.then(function (dp) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
@@ -79,7 +69,7 @@ function remultExpress(options) {
79
69
  addArea: function (x) { return bridge.addArea(x); }
80
70
  });
81
71
  }
82
- exports.remultExpress = remultExpress;
72
+ exports.remultMiddlewareBase = remultMiddlewareBase;
83
73
  var ExpressBridge = /** @class */ (function () {
84
74
  function ExpressBridge(app, queue, initRequest, dataProvider) {
85
75
  this.app = app;
@@ -93,11 +83,14 @@ var ExpressBridge = /** @class */ (function () {
93
83
  ExpressBridge.prototype.openApiDoc = function (options) {
94
84
  var e_1, _a, e_2, _b;
95
85
  var r = new __1.Remult();
86
+ if (!options.version)
87
+ options.version = "1.0.0";
96
88
  var spec = {
97
- info: { title: options.title },
89
+ info: { title: options.title, version: options.version },
98
90
  openapi: "3.0.0",
99
91
  //swagger: "2.0",
100
92
  "components": {
93
+ "schemas": {},
101
94
  "securitySchemes": {
102
95
  "bearerAuth": {
103
96
  "scheme": "bearer",
@@ -106,8 +99,7 @@ var ExpressBridge = /** @class */ (function () {
106
99
  }
107
100
  }
108
101
  },
109
- paths: {},
110
- definitions: {}
102
+ paths: {}
111
103
  };
112
104
  var validationError = {
113
105
  "400": {
@@ -115,7 +107,7 @@ var ExpressBridge = /** @class */ (function () {
115
107
  "content": {
116
108
  "application/json": {
117
109
  "schema": {
118
- "$ref": "#/definitions/InvalidResponse"
110
+ "$ref": "#/components/schemas/InvalidResponse"
119
111
  }
120
112
  }
121
113
  }
@@ -182,12 +174,12 @@ var ExpressBridge = /** @class */ (function () {
182
174
  }
183
175
  finally { if (e_3) throw e_3.error; }
184
176
  }
185
- spec.definitions[key] = {
177
+ spec.components.schemas[key] = {
186
178
  type: "object",
187
179
  properties: properties
188
180
  };
189
181
  var definition = {
190
- "$ref": "#/definitions/" + key
182
+ "$ref": "#/components/schemas/" + key
191
183
  };
192
184
  var secure = function (condition, def, item) {
193
185
  item.tags = [meta.key];
@@ -206,28 +198,28 @@ var ExpressBridge = /** @class */ (function () {
206
198
  "description": "limit the number of returned rows, default 100",
207
199
  "required": false,
208
200
  "style": "simple",
209
- "type": "int"
201
+ "schema": { "type": "integer" }
210
202
  },
211
203
  {
212
204
  "name": "_page",
213
205
  "in": "query",
214
206
  "description": "to be used for paging",
215
207
  "required": false,
216
- "type": "int"
208
+ "schema": { "type": "integer" }
217
209
  },
218
210
  {
219
211
  "name": "_sort",
220
212
  "in": "query",
221
213
  "description": "the columns to sort on",
222
214
  "required": false,
223
- "type": "string"
215
+ "schema": { "type": "string" }
224
216
  },
225
217
  {
226
218
  "name": "_order",
227
219
  "in": "query",
228
220
  "description": "the sort order to user for the columns in `_sort`",
229
221
  "required": false,
230
- "type": "string"
222
+ "schema": { "type": "string" }
231
223
  }], parameters),
232
224
  responses: {
233
225
  "200": {
@@ -248,14 +240,14 @@ var ExpressBridge = /** @class */ (function () {
248
240
  "in": "path",
249
241
  "description": "id of " + key,
250
242
  "required": true,
251
- "type": "string"
243
+ "schema": { "type": "string" },
252
244
  };
253
245
  var itemInBody = {
254
246
  "requestBody": {
255
247
  "content": {
256
248
  "application/json": {
257
249
  "schema": {
258
- "$ref": "#/definitions/" + key
250
+ "$ref": "#/components/schemas/" + key
259
251
  }
260
252
  }
261
253
  }
@@ -269,7 +261,7 @@ var ExpressBridge = /** @class */ (function () {
269
261
  "content": {
270
262
  "application/json": {
271
263
  "schema": {
272
- "$ref": "#/definitions/" + key
264
+ "$ref": "#/components/schemas/" + key
273
265
  }
274
266
  }
275
267
  }
@@ -282,7 +274,7 @@ var ExpressBridge = /** @class */ (function () {
282
274
  "content": {
283
275
  "application/json": {
284
276
  "schema": {
285
- "$ref": "#/definitions/" + key
277
+ "$ref": "#/components/schemas/" + key
286
278
  }
287
279
  }
288
280
  }
@@ -299,7 +291,7 @@ var ExpressBridge = /** @class */ (function () {
299
291
  "content": {
300
292
  "application/json": {
301
293
  "schema": {
302
- "$ref": "#/definitions/" + key
294
+ "$ref": "#/components/schemas/" + key
303
295
  }
304
296
  }
305
297
  }
@@ -378,7 +370,7 @@ var ExpressBridge = /** @class */ (function () {
378
370
  }
379
371
  finally { if (e_2) throw e_2.error; }
380
372
  }
381
- spec.definitions["InvalidResponse"] = {
373
+ spec.components.schemas["InvalidResponse"] = {
382
374
  "type": "object",
383
375
  properties: {
384
376
  "message": {
@@ -819,42 +811,43 @@ var JobsInQueueEntity = /** @class */ (function (_super) {
819
811
  return _super !== null && _super.apply(this, arguments) || this;
820
812
  }
821
813
  tslib_1.__decorate([
822
- remult3_1.Fields.string(),
814
+ __1.Fields.string(),
823
815
  tslib_1.__metadata("design:type", String)
824
816
  ], JobsInQueueEntity.prototype, "userId", void 0);
825
817
  tslib_1.__decorate([
826
- remult3_1.Fields.string(),
818
+ __1.Fields.string(),
827
819
  tslib_1.__metadata("design:type", String)
828
820
  ], JobsInQueueEntity.prototype, "url", void 0);
829
821
  tslib_1.__decorate([
830
- remult3_1.Fields.date(),
822
+ __1.Fields.date(),
831
823
  tslib_1.__metadata("design:type", Date)
832
824
  ], JobsInQueueEntity.prototype, "submitTime", void 0);
833
825
  tslib_1.__decorate([
834
- remult3_1.Fields.date(),
826
+ __1.Fields.date(),
835
827
  tslib_1.__metadata("design:type", Date)
836
828
  ], JobsInQueueEntity.prototype, "doneTime", void 0);
837
829
  tslib_1.__decorate([
838
- remult3_1.Fields.string(),
830
+ __1.Fields.string(),
839
831
  tslib_1.__metadata("design:type", String)
840
832
  ], JobsInQueueEntity.prototype, "result", void 0);
841
833
  tslib_1.__decorate([
842
- remult3_1.Fields.boolean(),
834
+ __1.Fields.boolean(),
843
835
  tslib_1.__metadata("design:type", Boolean)
844
836
  ], JobsInQueueEntity.prototype, "done", void 0);
845
837
  tslib_1.__decorate([
846
- remult3_1.Fields.boolean(),
838
+ __1.Fields.boolean(),
847
839
  tslib_1.__metadata("design:type", Boolean)
848
840
  ], JobsInQueueEntity.prototype, "error", void 0);
849
841
  tslib_1.__decorate([
850
- remult3_1.Fields.number(),
842
+ __1.Fields.number(),
851
843
  tslib_1.__metadata("design:type", Number)
852
844
  ], JobsInQueueEntity.prototype, "progress", void 0);
853
845
  JobsInQueueEntity = tslib_1.__decorate([
854
- remult3_1.Entity(undefined, {
846
+ __1.Entity(undefined, {
855
847
  dbName: 'jobsInQueue'
856
848
  })
857
849
  ], JobsInQueueEntity);
858
850
  return JobsInQueueEntity;
859
851
  }(__1.IdEntity));
860
852
  exports.JobsInQueueEntity = JobsInQueueEntity;
853
+ context_1.allEntities.splice(context_1.allEntities.indexOf(JobsInQueueEntity), 1);
@@ -14,18 +14,18 @@ export interface FieldOptions<entityType = any, valueType = any> {
14
14
  allowApiUpdate?: AllowedForInstance<entityType>;
15
15
  /** An arrow function that'll be used to perform validations on it
16
16
  * @example
17
- * .@Fields.string({
17
+ * @Fields.string({
18
18
  * validate: Validators.required
19
19
  * })
20
20
  * @example
21
- * .@Fields.string<Task>({
21
+ * @Fields.string<Task>({
22
22
  * validate: task=>{
23
23
  * if (task.title.length<3)
24
24
  * throw "Too Short";
25
25
  * }
26
26
  * })
27
27
  * @example
28
- * .@Fields.string({
28
+ * @Fields.string({
29
29
  * validate: (_, fieldRef)=>{
30
30
  * if (fieldRef.value.length<3)
31
31
  * fieldRef.error = "Too Short";
package/src/context.js CHANGED
@@ -41,28 +41,28 @@ var HttpProviderBridgeToRestDataProviderHttpProvider = /** @class */ (function (
41
41
  }());
42
42
  exports.HttpProviderBridgeToRestDataProviderHttpProvider = HttpProviderBridgeToRestDataProviderHttpProvider;
43
43
  function retry(what) {
44
- var _a, _b, _c;
44
+ var _a, _b, _c, _d;
45
45
  return tslib_1.__awaiter(this, void 0, void 0, function () {
46
46
  var err_1;
47
- return tslib_1.__generator(this, function (_d) {
48
- switch (_d.label) {
47
+ return tslib_1.__generator(this, function (_e) {
48
+ switch (_e.label) {
49
49
  case 0:
50
50
  if (!true) return [3 /*break*/, 7];
51
- _d.label = 1;
51
+ _e.label = 1;
52
52
  case 1:
53
- _d.trys.push([1, 3, , 6]);
53
+ _e.trys.push([1, 3, , 6]);
54
54
  return [4 /*yield*/, what()];
55
- case 2: return [2 /*return*/, _d.sent()];
55
+ case 2: return [2 /*return*/, _e.sent()];
56
56
  case 3:
57
- err_1 = _d.sent();
58
- if (!(((_a = err_1.message) === null || _a === void 0 ? void 0 : _a.startsWith("Error occurred while trying to proxy")) || ((_b = err_1.message) === null || _b === void 0 ? void 0 : _b.startsWith("Error occured while trying to proxy")) || ((_c = err_1.message) === null || _c === void 0 ? void 0 : _c.startsWith("Gateway Timeout")))) return [3 /*break*/, 5];
57
+ err_1 = _e.sent();
58
+ if (!(((_a = err_1.message) === null || _a === void 0 ? void 0 : _a.startsWith("Error occurred while trying to proxy")) || ((_b = err_1.message) === null || _b === void 0 ? void 0 : _b.startsWith("Error occured while trying to proxy")) || ((_c = err_1.message) === null || _c === void 0 ? void 0 : _c.includes("http proxy error")) || ((_d = err_1.message) === null || _d === void 0 ? void 0 : _d.startsWith("Gateway Timeout")))) return [3 /*break*/, 5];
59
59
  return [4 /*yield*/, new Promise(function (res, req) {
60
60
  setTimeout(function () {
61
61
  res({});
62
62
  }, 250);
63
63
  })];
64
64
  case 4:
65
- _d.sent();
65
+ _e.sent();
66
66
  return [3 /*break*/, 0];
67
67
  case 5: throw err_1;
68
68
  case 6: return [3 /*break*/, 0];
@@ -4,7 +4,6 @@ exports.ArrayEntityDataProvider = void 0;
4
4
  var tslib_1 = require("tslib");
5
5
  var filter_interfaces_1 = require("../filter/filter-interfaces");
6
6
  var column_1 = require("../column");
7
- var sort_1 = require("../sort");
8
7
  var ArrayEntityDataProvider = /** @class */ (function () {
9
8
  function ArrayEntityDataProvider(entity, rows) {
10
9
  var e_1, _a;
@@ -220,34 +219,38 @@ var ArrayEntityDataProvider = /** @class */ (function () {
220
219
  ArrayEntityDataProvider.prototype.insert = function (data) {
221
220
  var _a;
222
221
  return tslib_1.__awaiter(this, void 0, void 0, function () {
223
- var idf, lastRow, j;
224
- return tslib_1.__generator(this, function (_b) {
225
- switch (_b.label) {
226
- case 0:
227
- idf = this.entity.idMetadata.field;
228
- if (!!(idf instanceof column_1.CompoundIdField)) return [3 /*break*/, 3];
229
- if (!(((_a = idf.options.valueConverter) === null || _a === void 0 ? void 0 : _a.fieldTypeInDb) === 'autoincrement')) return [3 /*break*/, 2];
230
- return [4 /*yield*/, this.find({ orderBy: new sort_1.Sort({ field: idf, isDescending: true }) })];
231
- case 1:
232
- lastRow = _b.sent();
233
- if (lastRow.length > 0)
234
- data[idf.key] = lastRow[0][idf.key] + 1;
235
- else
236
- data[idf.key] = 1;
237
- _b.label = 2;
238
- case 2:
239
- if (data[idf.key])
240
- this.rows.forEach(function (i) {
241
- if (data[idf.key] == i[idf.key])
242
- throw Error("id already exists");
243
- });
244
- _b.label = 3;
245
- case 3:
246
- j = this.translateToJson(data);
247
- this.verifyThatRowHasAllNotNullColumns(j);
248
- this.rows.push(j);
249
- return [2 /*return*/, Promise.resolve(this.translateFromJson(j))];
222
+ var idf, _b, _c, row, j;
223
+ var e_6, _d;
224
+ return tslib_1.__generator(this, function (_e) {
225
+ idf = this.entity.idMetadata.field;
226
+ if (!(idf instanceof column_1.CompoundIdField)) {
227
+ if (((_a = idf.options.valueConverter) === null || _a === void 0 ? void 0 : _a.fieldTypeInDb) === 'autoincrement') {
228
+ data[idf.key] = 1;
229
+ try {
230
+ for (_b = tslib_1.__values(this.rows), _c = _b.next(); !_c.done; _c = _b.next()) {
231
+ row = _c.value;
232
+ if (row[idf.key] >= data[idf.key])
233
+ data[idf.key] = row[idf.key] + 1;
234
+ }
235
+ }
236
+ catch (e_6_1) { e_6 = { error: e_6_1 }; }
237
+ finally {
238
+ try {
239
+ if (_c && !_c.done && (_d = _b.return)) _d.call(_b);
240
+ }
241
+ finally { if (e_6) throw e_6.error; }
242
+ }
243
+ }
244
+ if (data[idf.key])
245
+ this.rows.forEach(function (i) {
246
+ if (data[idf.key] == i[idf.key])
247
+ throw Error("id already exists");
248
+ });
250
249
  }
250
+ j = this.translateToJson(data);
251
+ this.verifyThatRowHasAllNotNullColumns(j);
252
+ this.rows.push(j);
253
+ return [2 /*return*/, Promise.resolve(this.translateFromJson(j))];
251
254
  });
252
255
  });
253
256
  };
@@ -287,7 +290,7 @@ var FilterConsumerBridgeToObject = /** @class */ (function () {
287
290
  throw new Error('Custom Filter should be translated before it gets here');
288
291
  };
289
292
  FilterConsumerBridgeToObject.prototype.or = function (orElements) {
290
- var e_6, _a;
293
+ var e_7, _a;
291
294
  try {
292
295
  for (var orElements_1 = tslib_1.__values(orElements), orElements_1_1 = orElements_1.next(); !orElements_1_1.done; orElements_1_1 = orElements_1.next()) {
293
296
  var element = orElements_1_1.value;
@@ -298,12 +301,12 @@ var FilterConsumerBridgeToObject = /** @class */ (function () {
298
301
  }
299
302
  }
300
303
  }
301
- catch (e_6_1) { e_6 = { error: e_6_1 }; }
304
+ catch (e_7_1) { e_7 = { error: e_7_1 }; }
302
305
  finally {
303
306
  try {
304
307
  if (orElements_1_1 && !orElements_1_1.done && (_a = orElements_1.return)) _a.call(orElements_1);
305
308
  }
306
- finally { if (e_6) throw e_6.error; }
309
+ finally { if (e_7) throw e_7.error; }
307
310
  }
308
311
  this.ok = false;
309
312
  };
@@ -316,7 +319,7 @@ var FilterConsumerBridgeToObject = /** @class */ (function () {
316
319
  this.ok = false;
317
320
  };
318
321
  FilterConsumerBridgeToObject.prototype.isIn = function (col, val) {
319
- var e_7, _a;
322
+ var e_8, _a;
320
323
  try {
321
324
  for (var val_1 = tslib_1.__values(val), val_1_1 = val_1.next(); !val_1_1.done; val_1_1 = val_1.next()) {
322
325
  var v = val_1_1.value;
@@ -325,12 +328,12 @@ var FilterConsumerBridgeToObject = /** @class */ (function () {
325
328
  }
326
329
  }
327
330
  }
328
- catch (e_7_1) { e_7 = { error: e_7_1 }; }
331
+ catch (e_8_1) { e_8 = { error: e_8_1 }; }
329
332
  finally {
330
333
  try {
331
334
  if (val_1_1 && !val_1_1.done && (_a = val_1.return)) _a.call(val_1);
332
335
  }
333
- finally { if (e_7) throw e_7.error; }
336
+ finally { if (e_8) throw e_8.error; }
334
337
  }
335
338
  this.ok = false;
336
339
  };
package/src/entity.d.ts CHANGED
@@ -29,7 +29,7 @@ export interface EntityOptions<entityType = any> {
29
29
  apiPrefilter?: EntityFilter<entityType> | (() => EntityFilter<entityType> | Promise<EntityFilter<entityType>>);
30
30
  /** A filter that will be used for all queries from this entity both from the API and from within the backend.
31
31
  * @example
32
- * fixedWhereFilter: { archive:false }
32
+ * backendPrefilter: { archive:false }
33
33
  * @see [EntityFilter](http://remult.dev/docs/entityFilter.html)
34
34
  */
35
35
  backendPrefilter?: EntityFilter<entityType> | (() => EntityFilter<entityType> | Promise<EntityFilter<entityType>>);
@@ -45,7 +45,7 @@ export interface EntityOptions<entityType = any> {
45
45
  * If the `error` property of the entity's ref or any of it's fields will be set, the save will be aborted and an exception will be thrown.
46
46
  * this is the place to run logic that we want to run in any case before an entity is saved.
47
47
  * @example
48
- * .@Entity<Task>("tasks", {
48
+ * @Entity<Task>("tasks", {
49
49
  * saving: async task => {
50
50
  * task.lastUpdated = new Date()
51
51
  * }
@@ -256,11 +256,11 @@ export declare function getValueList<T>(type: ClassType<T>): T[];
256
256
  * FieldOptions can be set in two ways:
257
257
  * @example
258
258
  * // as an object
259
- * .@Fields.string({ includeInApi:false })
259
+ * @Fields.string({ includeInApi:false })
260
260
  * title='';
261
261
  * @example
262
262
  * // as an arrow function that receives `remult` as a parameter
263
- * .@Fields.string((options,remult) => options.includeInApi = true)
263
+ * @Fields.string((options,remult) => options.includeInApi = true)
264
264
  * title='';
265
265
  */
266
266
  export declare function Field<entityType = any, valueType = any>(valueType: () => ClassType<valueType>, ...options: (FieldOptions<entityType, valueType> | ((options: FieldOptions<entityType, valueType>, remult: Remult) => void))[]): (target: any, key: any, c?: any) => void;
@@ -289,13 +289,14 @@ export declare function BuildEntity<entityType>(c: ClassType<entityType>, key: s
289
289
  * @Fields.boolean()
290
290
  * completed = false;
291
291
  * }
292
- * *EntityOptions can be set in two ways:*
292
+ * @note
293
+ * EntityOptions can be set in two ways:
293
294
  * @example
294
295
  * // as an object
295
- * .@Entity("tasks",{ allowApiCrud:true })
296
+ * @Entity("tasks",{ allowApiCrud:true })
296
297
  * @example
297
298
  * // as an arrow function that receives `remult` as a parameter
298
- * .@Entity("tasks", (options,remult) => options.allowApiCrud = true)
299
+ * @Entity("tasks", (options,remult) => options.allowApiCrud = true)
299
300
  */
300
301
  export declare function Entity<entityType>(key: string, ...options: (EntityOptions<entityType> | ((options: EntityOptions<entityType>, remult: Remult) => void))[]): (target: any) => any;
301
302
  export declare class EntityBase {
@@ -2467,11 +2467,11 @@ exports.getValueList = getValueList;
2467
2467
  * FieldOptions can be set in two ways:
2468
2468
  * @example
2469
2469
  * // as an object
2470
- * .@Fields.string({ includeInApi:false })
2470
+ * @Fields.string({ includeInApi:false })
2471
2471
  * title='';
2472
2472
  * @example
2473
2473
  * // as an arrow function that receives `remult` as a parameter
2474
- * .@Fields.string((options,remult) => options.includeInApi = true)
2474
+ * @Fields.string((options,remult) => options.includeInApi = true)
2475
2475
  * title='';
2476
2476
  */
2477
2477
  function Field(valueType) {
@@ -2637,13 +2637,14 @@ exports.BuildEntity = BuildEntity;
2637
2637
  * @Fields.boolean()
2638
2638
  * completed = false;
2639
2639
  * }
2640
- * *EntityOptions can be set in two ways:*
2640
+ * @note
2641
+ * EntityOptions can be set in two ways:
2641
2642
  * @example
2642
2643
  * // as an object
2643
- * .@Entity("tasks",{ allowApiCrud:true })
2644
+ * @Entity("tasks",{ allowApiCrud:true })
2644
2645
  * @example
2645
2646
  * // as an arrow function that receives `remult` as a parameter
2646
- * .@Entity("tasks", (options,remult) => options.allowApiCrud = true)
2647
+ * @Entity("tasks", (options,remult) => options.allowApiCrud = true)
2647
2648
  */
2648
2649
  function Entity(key) {
2649
2650
  var options = [];
@@ -112,7 +112,12 @@ export declare type OmitEB<T> = Omit<T, keyof import('./RepositoryImplementation
112
112
  export interface Repository<entityType> {
113
113
  /** returns a result array based on the provided options */
114
114
  find(options?: FindOptions<entityType>): Promise<entityType[]>;
115
- /** returns the first item that matchers the `where` condition */
115
+ /** returns the first item that matchers the `where` condition
116
+ * @example
117
+ * await taskRepo.findFirst({ completed:false })
118
+ * @example
119
+ * await taskRepo.findFirst({ completed:false },{ createIfNotFound: true })
120
+ * */
116
121
  findFirst(where?: EntityFilter<entityType>, options?: FindFirstOptions<entityType>): Promise<entityType>;
117
122
  /** returns the items that matches the idm the result is cached unless specified differently in the `options` parameter */
118
123
  findId(id: entityType extends {
@@ -285,7 +290,7 @@ export interface QueryResult<entityType> {
285
290
  [Symbol.asyncIterator](): {
286
291
  next: () => Promise<IteratorResult<entityType, entityType>>;
287
292
  };
288
- /** returns the number of rows that match the query critiria */
293
+ /** returns the number of rows that match the query criteria */
289
294
  count(): Promise<number>;
290
295
  /** Returns a `Paginator` object that is used for efficient paging */
291
296
  paginator(): Promise<Paginator<entityType>>;
@@ -300,7 +305,7 @@ export interface Paginator<entityType> {
300
305
  items: entityType[];
301
306
  /** True if next page exists */
302
307
  hasNextPage: boolean;
303
- /** Get's the next page in the query's result set */
308
+ /** Gets the next page in the `query`'s result set */
304
309
  nextPage(): Promise<Paginator<entityType>>;
305
310
  /** the count of the total items in the `query`'s result */
306
311
  count(): Promise<number>;