remult 0.13.19 → 0.13.22

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.
@@ -42,7 +42,7 @@ export interface Subscribable {
42
42
  }
43
43
  export declare type FieldsRef<entityType> = {
44
44
  [Properties in keyof OmitEB<entityType>]: entityType[Properties] extends {
45
- id: (number | string);
45
+ id?: (number | string);
46
46
  } ? IdFieldRef<entityType, entityType[Properties]> : FieldRef<entityType, entityType[Properties]>;
47
47
  } & {
48
48
  find(fieldMetadataOrKey: FieldMetadata | string): FieldRef<entityType, any>;
@@ -63,10 +63,15 @@ export declare type SortSegments<entityType> = {
63
63
  };
64
64
  export interface IdFieldRef<entityType, valueType> extends FieldRef<entityType, valueType> {
65
65
  setId(id: valueType extends {
66
- id: number;
66
+ id?: number;
67
67
  } ? number : valueType extends {
68
- id: string;
68
+ id?: string;
69
69
  } ? string : (string | number)): any;
70
+ getId(): (valueType extends {
71
+ id?: number;
72
+ } ? number : valueType extends {
73
+ id?: string;
74
+ } ? string : (string | number));
70
75
  }
71
76
  export interface FieldRef<entityType = any, valueType = any> extends Subscribable {
72
77
  error: string;
@@ -77,7 +82,7 @@ export interface FieldRef<entityType = any, valueType = any> extends Subscribabl
77
82
  valueChanged(): boolean;
78
83
  entityRef: EntityRef<entityType>;
79
84
  container: entityType;
80
- metadata: FieldMetadata<entityType>;
85
+ metadata: FieldMetadata<valueType>;
81
86
  load(): Promise<valueType>;
82
87
  valueIsNull(): boolean;
83
88
  originalValueIsNull(): boolean;
@@ -103,43 +108,80 @@ export interface EntityMetadata<entityType = any> {
103
108
  getDbName(): Promise<string>;
104
109
  }
105
110
  export declare type OmitEB<T> = Omit<T, keyof import('./RepositoryImplementation').EntityBase>;
111
+ /**used to perform CRUD operations on an `entityType` */
106
112
  export interface Repository<entityType> {
107
- /**creates a json representation of the object */
108
- fromJson(x: any, isNew?: boolean): Promise<entityType>;
109
- metadata: EntityMetadata<entityType>;
110
113
  /** returns a result array based on the provided options */
111
114
  find(options?: FindOptions<entityType>): Promise<entityType[]>;
112
- query(options?: QueryOptions<entityType>): QueryResult<entityType>;
115
+ /** returns the first item that matchers the `where` condition */
113
116
  findFirst(where?: EntityFilter<entityType>, options?: FindFirstOptions<entityType>): Promise<entityType>;
117
+ /** returns the items that matches the idm the result is cached unless specified differently in the `options` parameter */
114
118
  findId(id: entityType extends {
115
- id: number;
119
+ id?: number;
116
120
  } ? number : entityType extends {
117
- id: string;
121
+ id?: string;
118
122
  } ? string : (string | number), options?: FindFirstOptionsBase<entityType>): Promise<entityType>;
123
+ /** An alternative form of fetching data from the API server, which is intended for operating on large numbers of entity objects.
124
+ *
125
+ * It also has it's own paging mechanism that can be used n paging scenarios.
126
+ *
127
+ * The `query` method doesn't return an array (as the `find` method) and instead returns an `iteratable` `QueryResult` object
128
+ * which supports iterations using the JavaScript `for await` statement.
129
+ * @example
130
+ * for await (const task of taskRepo.query()) {
131
+ * // do something.
132
+ * }
133
+ * */
134
+ query(options?: QueryOptions<entityType>): QueryResult<entityType>;
135
+ /** Returns a count of the items matching the criteria.
136
+ * @see [EntityFilter](http://remult.dev/docs/entityFilter.html)
137
+ * @example
138
+ * await taskRepo.count({ completed:false })
139
+ */
119
140
  count(where?: EntityFilter<entityType>): Promise<number>;
120
- create(item?: Partial<OmitEB<entityType>>): entityType;
121
- getEntityRef(item: entityType): EntityRef<entityType>;
141
+ /** saves an item or item[] to the data source. It assumes that if an `id` value exists, it's an existing row - otherwise it's a new row
142
+ * @example
143
+ * await taskRepo.save({...task, completed:true })
144
+ */
122
145
  save(item: Partial<OmitEB<entityType>>[]): Promise<entityType[]>;
123
146
  save(item: Partial<OmitEB<entityType>>): Promise<entityType>;
147
+ /**Insert an item or item[] to the data source
148
+ * @example
149
+ * await taskRepo.insert({title:"task a"})
150
+ * @example
151
+ * await taskRepo.insert([{title:"task a"}, {title:"task b", completed:true }])
152
+ */
124
153
  insert(item: Partial<OmitEB<entityType>>[]): Promise<entityType[]>;
125
154
  insert(item: Partial<OmitEB<entityType>>): Promise<entityType>;
155
+ /** Updates an item, based on it's `id`
156
+ * @example
157
+ * taskRepo.update(task.id,{...task,completed:true})
158
+ */
126
159
  update(id: (entityType extends {
127
- id: number;
160
+ id?: number;
128
161
  } ? number : entityType extends {
129
- id: string;
162
+ id?: string;
130
163
  } ? string : (string | number)), item: Partial<OmitEB<entityType>>): Promise<entityType>;
164
+ /** Deletes an Item*/
131
165
  delete(id: (entityType extends {
132
- id: number;
166
+ id?: number;
133
167
  } ? number : entityType extends {
134
- id: string;
168
+ id?: string;
135
169
  } ? string : (string | number))): Promise<void>;
136
170
  delete(item: entityType): Promise<void>;
171
+ /** Creates an instance of an item. It'll not be saved to the data source unless `save` or `insert` will be called for that item */
172
+ create(item?: Partial<OmitEB<entityType>>): entityType;
173
+ /** Translates a json object to an item instance */
174
+ fromJson(x: any, isNew?: boolean): Promise<entityType>;
175
+ /** returns an `entityRef` for an item returned by `create`, `find` etc... */
176
+ getEntityRef(item: entityType): EntityRef<entityType>;
177
+ /**The metadata for the `entity` */
178
+ metadata: EntityMetadata<entityType>;
137
179
  addEventListener(listener: entityEventListener<entityType>): Unobserve;
138
180
  }
139
181
  export interface FindOptions<entityType> extends FindOptionsBase<entityType> {
140
182
  /** Determines the number of rows returned by the request, on the browser the default is 100 rows
141
183
  * @example
142
- * this.products = await this.remult.repo(Products).find({
184
+ * await this.remult.repo(Products).find({
143
185
  * limit:10,
144
186
  * page:2
145
187
  * })
@@ -147,27 +189,28 @@ export interface FindOptions<entityType> extends FindOptionsBase<entityType> {
147
189
  limit?: number;
148
190
  /** Determines the page number that will be used to extract the data
149
191
  * @example
150
- * this.products = await this.remult.repo(Products).find({
192
+ * await this.remult.repo(Products).find({
151
193
  * limit:10,
152
194
  * page:2
153
195
  * })
154
196
  */
155
197
  page?: number;
156
198
  }
157
- /** Determines the order of rows returned by the query.
199
+ /** Determines the order of items returned .
158
200
  * @example
159
201
  * await this.remult.repo(Products).find({ orderBy: { name: "asc" }})
160
202
  * @example
161
- * await this.remult.repo(Products).find({ orderBy: { price: "asc", name: "asc" }})
162
- * @example
163
203
  * await this.remult.repo(Products).find({ orderBy: { price: "desc", name: "asc" }})
164
204
  */
165
205
  export declare type EntityOrderBy<entityType> = {
166
206
  [Properties in keyof Partial<OmitEB<entityType>>]?: "asc" | "desc";
167
207
  };
208
+ /**Used to filter the desired result set
209
+ * @see [EntityFilter](http://remult.dev/docs/entityFilter.html)
210
+ */
168
211
  export declare type EntityFilter<entityType> = {
169
212
  [Properties in keyof Partial<OmitEB<entityType>>]?: (Partial<OmitEB<entityType>>[Properties] extends (number | Date | undefined) ? ComparisonValueFilter<Partial<OmitEB<entityType>>[Properties]> : Partial<OmitEB<entityType>>[Properties] extends (string | undefined) ? ContainsStringValueFilter & ComparisonValueFilter<string> : Partial<OmitEB<entityType>>[Properties] extends (boolean | undefined) ? ValueFilter<boolean> : Partial<OmitEB<entityType>>[Properties] extends ({
170
- id: (string | number);
213
+ id?: (string | number);
171
214
  } | undefined) ? IdFilter<Partial<OmitEB<entityType>>[Properties]> : ValueFilter<Partial<OmitEB<entityType>>[Properties]>) & ContainsStringValueFilter;
172
215
  } & {
173
216
  $or?: EntityFilter<entityType>[];
@@ -192,7 +235,7 @@ export interface ContainsStringValueFilter {
192
235
  }
193
236
  export declare type IdFilter<valueType> = ValueFilter<valueType> | {
194
237
  $id: ValueFilter<valueType extends {
195
- id: number;
238
+ id?: number;
196
239
  } ? number : string>;
197
240
  };
198
241
  export interface LoadOptions<entityType> {
@@ -201,41 +244,64 @@ export interface LoadOptions<entityType> {
201
244
  export interface FindOptionsBase<entityType> extends LoadOptions<entityType> {
202
245
  /** filters the data
203
246
  * @example
204
- * where p => p.price.isGreaterOrEqualTo(5)
205
- * @see For more usage examples see [EntityWhere](https://remult-ts.github.io/guide/ref_entitywhere)
247
+ * await taskRepo.find({where: { completed:false }})
248
+ * @see For more usage examples see [EntityFilter](https://remult.dev/docs/entityFilter.html)
206
249
  */
207
250
  where?: EntityFilter<entityType>;
208
- /** Determines the order in which the result will be sorted in
209
- * @see See [EntityOrderBy](https://remult-ts.github.io/guide/ref__entityorderby) for more examples on how to sort
210
- */
251
+ /** Determines the order of items returned .
252
+ * @example
253
+ * await this.remult.repo(Products).find({ orderBy: { name: "asc" }})
254
+ * @example
255
+ * await this.remult.repo(Products).find({ orderBy: { price: "desc", name: "asc" }})
256
+ */
211
257
  orderBy?: EntityOrderBy<entityType>;
212
258
  }
213
259
  export interface FindFirstOptions<entityType> extends FindOptionsBase<entityType>, FindFirstOptionsBase<entityType> {
214
260
  }
215
261
  export interface FindFirstOptionsBase<entityType> extends LoadOptions<entityType> {
216
- /** default true
262
+ /** determines if to cache the result, and return the results from cache.
217
263
  */
218
264
  useCache?: boolean;
265
+ /** If set to true and an item is not found, it's created and returned*/
219
266
  createIfNotFound?: boolean;
220
267
  }
221
268
  export interface QueryOptions<entityType> extends FindOptionsBase<entityType> {
269
+ /** The number of items to return in each step */
222
270
  pageSize?: number;
271
+ /** A callback method to indicate the progress of the iteration */
223
272
  progress?: {
224
273
  progress: (progress: number) => void;
225
274
  };
226
275
  }
276
+ /** The result of a call to the `query` method in the `Repository` object.
277
+ */
227
278
  export interface QueryResult<entityType> {
228
- getPage(pageNumber?: number): Promise<entityType[]>;
229
- count(): Promise<number>;
230
- forEach(what: (item: entityType) => Promise<any>): Promise<number>;
231
- paginator(): Promise<Paginator<entityType>>;
279
+ /** returns an iterator that iterates the rows in the result using a paging mechanism
280
+ * @example
281
+ * for await (const task of taskRepo.query()) {
282
+ * await taskRepo.save({ ...task, completed });
283
+ * }
284
+ */
232
285
  [Symbol.asyncIterator](): {
233
286
  next: () => Promise<IteratorResult<entityType, entityType>>;
234
287
  };
288
+ /** returns the number of rows that match the query critiria */
289
+ count(): Promise<number>;
290
+ /** Returns a `Paginator` object that is used for efficient paging */
291
+ paginator(): Promise<Paginator<entityType>>;
292
+ /** gets the items in a specific page */
293
+ getPage(pageNumber?: number): Promise<entityType[]>;
294
+ /** Performs an operation on all the items matching the query criteria */
295
+ forEach(what: (item: entityType) => Promise<any>): Promise<number>;
235
296
  }
297
+ /** An interface used to paginating using the `query` method in the `Repository` object */
236
298
  export interface Paginator<entityType> {
299
+ /** the items in the current page */
237
300
  items: entityType[];
238
- count(): Promise<number>;
301
+ /** True if next page exists */
239
302
  hasNextPage: boolean;
303
+ /** Get's the next page in the query's result set */
240
304
  nextPage(): Promise<Paginator<entityType>>;
305
+ /** the count of the total items in the `query`'s result */
306
+ count(): Promise<number>;
241
307
  }
@@ -27,9 +27,12 @@ export declare class myServerAction extends Action<inArgs, result> {
27
27
  protected execute(info: inArgs, remult: Remult, res: DataApiResponse): Promise<result>;
28
28
  }
29
29
  export interface BackendMethodOptions<type> {
30
+ /**Determines when this `BackendMethod` can execute, see: [Allowed](https://remult.dev/docs/allowed.html) */
30
31
  allowed: AllowedForInstance<type>;
31
- blockUser?: boolean;
32
+ /** EXPERIMENTAL: Determines if this method should be queued for later execution */
32
33
  queue?: boolean;
34
+ /** EXPERIMENTAL: Determines if the user should be blocked while this `BackendMethod` is running*/
35
+ blockUser?: boolean;
33
36
  }
34
37
  export declare const actionInfo: {
35
38
  allActions: any[];
@@ -42,6 +45,7 @@ export declare const actionInfo: {
42
45
  };
43
46
  export declare const serverActionField: unique symbol;
44
47
  export declare function Controller(key: string): (target: any) => any;
48
+ /** Indicates that the decorated methods runs on the backend. See: [Backend Methods](https://remult.dev/docs/backendMethods.html) */
45
49
  export declare function BackendMethod<type = any>(options: BackendMethodOptions<type>): (target: any, key: string, descriptor: any) => any;
46
50
  export interface registrableAction {
47
51
  __register: (reg: (url: string, queue: boolean, allowed: AllowedForInstance<any>, what: ((data: any, req: DataApiRequest, res: DataApiResponse) => void)) => void) => void;
@@ -178,6 +178,7 @@ function Controller(key) {
178
178
  };
179
179
  }
180
180
  exports.Controller = Controller;
181
+ /** Indicates that the decorated methods runs on the backend. See: [Backend Methods](https://remult.dev/docs/backendMethods.html) */
181
182
  function BackendMethod(options) {
182
183
  return function (target, key, descriptor) {
183
184
  if (target.prototype !== undefined) {
@@ -218,7 +218,58 @@ db_tests_setup_1.testAll("empty find works", function (_a) {
218
218
  }
219
219
  });
220
220
  });
221
- });
221
+ }, false);
222
+ db_tests_setup_1.testAll("test descending", function (_a) {
223
+ var createEntity = _a.createEntity;
224
+ return tslib_1.__awaiter(void 0, void 0, void 0, function () {
225
+ var repo, rows;
226
+ return tslib_1.__generator(this, function (_b) {
227
+ switch (_b.label) {
228
+ case 0: return [4 /*yield*/, createEntity(remult_3_entities_1.Categories)];
229
+ case 1:
230
+ repo = _b.sent();
231
+ return [4 /*yield*/, repo.create({ id: 1, categoryName: 'a' }).save()];
232
+ case 2:
233
+ _b.sent();
234
+ return [4 /*yield*/, repo.create({ id: 2, categoryName: 'b' }).save()];
235
+ case 3:
236
+ _b.sent();
237
+ return [4 /*yield*/, repo.find({
238
+ orderBy: { categoryName: 'desc' },
239
+ page: -1
240
+ })];
241
+ case 4:
242
+ rows = _b.sent();
243
+ expect(rows[0].id).toBe(2);
244
+ return [2 /*return*/];
245
+ }
246
+ });
247
+ });
248
+ }, false);
249
+ db_tests_setup_1.testAll("test descending 2", function (_a) {
250
+ var createEntity = _a.createEntity;
251
+ return tslib_1.__awaiter(void 0, void 0, void 0, function () {
252
+ var repo, rows;
253
+ return tslib_1.__generator(this, function (_b) {
254
+ switch (_b.label) {
255
+ case 0: return [4 /*yield*/, createEntity(remult_3_entities_1.Categories)];
256
+ case 1:
257
+ repo = _b.sent();
258
+ return [4 /*yield*/, repo.insert([{ id: 1, categoryName: 'a' }, { id: 2, categoryName: 'b' }])];
259
+ case 2:
260
+ _b.sent();
261
+ return [4 /*yield*/, repo.find({
262
+ orderBy: { categoryName: 'desc' },
263
+ page: -1
264
+ })];
265
+ case 3:
266
+ rows = _b.sent();
267
+ expect(rows[0].id).toBe(2);
268
+ return [2 /*return*/];
269
+ }
270
+ });
271
+ });
272
+ }, false);
222
273
  db_tests_setup_1.testAll("partial updates", function (_a) {
223
274
  var remult = _a.remult, createEntity = _a.createEntity;
224
275
  return tslib_1.__awaiter(void 0, void 0, void 0, function () {
@@ -64,26 +64,12 @@ var entityWithValidations = /** @class */ (function (_super) {
64
64
  remult3_1.Entity('', {
65
65
  allowApiCrud: true,
66
66
  saving: function (t) { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
67
- var e;
68
67
  return tslib_1.__generator(this, function (_a) {
69
- switch (_a.label) {
70
- case 0:
71
- if (!t.name || t.name.length < 3)
72
- t._.fields.name.error = 'invalid';
73
- if (!(t._.isNew() && (!t.myId || t.myId == 0))) return [3 /*break*/, 2];
74
- return [4 /*yield*/, t.remult.repo(entityWithValidations_1).find({
75
- orderBy: { myId: "desc" },
76
- limit: 1
77
- })];
78
- case 1:
79
- e = _a.sent();
80
- t.myId = e.length ? e[0].myId + 1 : 1;
81
- _a.label = 2;
82
- case 2:
83
- if (!exports.testConfiguration.restDbRunningOnServer)
84
- entityWithValidations_1.savingRowCount++;
85
- return [2 /*return*/];
86
- }
68
+ if (!t.name || t.name.length < 3)
69
+ t._.fields.name.error = 'invalid';
70
+ if (!exports.testConfiguration.restDbRunningOnServer)
71
+ entityWithValidations_1.savingRowCount++;
72
+ return [2 /*return*/];
87
73
  });
88
74
  }); }
89
75
  }),
@@ -7,22 +7,22 @@ var TestDataApiResponse = /** @class */ (function () {
7
7
  TestDataApiResponse.prototype.progress = function (progress) {
8
8
  };
9
9
  TestDataApiResponse.prototype.success = function (data) {
10
- fail('didnt expect success: ' + JSON.stringify(data));
10
+ throw new Error(('didnt expect success: ' + JSON.stringify(data)));
11
11
  };
12
12
  TestDataApiResponse.prototype.forbidden = function () {
13
- fail('didnt expect forbidden:');
13
+ throw new Error('didnt expect forbidden:');
14
14
  };
15
15
  TestDataApiResponse.prototype.created = function (data) {
16
- fail('didnt expect created: ' + JSON.stringify(data));
16
+ throw new Error('didnt expect created: ' + JSON.stringify(data));
17
17
  };
18
18
  TestDataApiResponse.prototype.deleted = function () {
19
- fail('didnt expect deleted:');
19
+ throw new Error('didnt expect deleted:');
20
20
  };
21
21
  TestDataApiResponse.prototype.notFound = function () {
22
- fail('not found');
22
+ throw new Error('not found');
23
23
  };
24
24
  TestDataApiResponse.prototype.error = function (data) {
25
- fail('error: ' + data + " " + JSON.stringify(data));
25
+ throw new Error('error: ' + data + " " + JSON.stringify(data));
26
26
  };
27
27
  return TestDataApiResponse;
28
28
  }());
package/src/tests/d.d.ts CHANGED
@@ -3,5 +3,4 @@ export declare class d extends EntityBase {
3
3
  id: number;
4
4
  b: number;
5
5
  static count: number;
6
- doIt(): Promise<boolean>;
7
6
  }
package/src/tests/d.js CHANGED
@@ -2,22 +2,12 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.d = void 0;
4
4
  var tslib_1 = require("tslib");
5
- var server_action_1 = require("../server-action");
6
5
  var remult3_1 = require("../remult3");
7
- var dWithPrefilter_1 = require("./dWithPrefilter");
8
6
  var d = /** @class */ (function (_super) {
9
7
  tslib_1.__extends(d, _super);
10
8
  function d() {
11
9
  return _super !== null && _super.apply(this, arguments) || this;
12
10
  }
13
- d.prototype.doIt = function () {
14
- return tslib_1.__awaiter(this, void 0, void 0, function () {
15
- return tslib_1.__generator(this, function (_a) {
16
- dWithPrefilter_1.dWithPrefilter.count++;
17
- return [2 /*return*/, true];
18
- });
19
- });
20
- };
21
11
  d.count = 0;
22
12
  tslib_1.__decorate([
23
13
  remult3_1.Fields.integer(),
@@ -27,12 +17,6 @@ var d = /** @class */ (function (_super) {
27
17
  remult3_1.Fields.integer(),
28
18
  tslib_1.__metadata("design:type", Number)
29
19
  ], d.prototype, "b", void 0);
30
- tslib_1.__decorate([
31
- server_action_1.BackendMethod({ allowed: true }),
32
- tslib_1.__metadata("design:type", Function),
33
- tslib_1.__metadata("design:paramtypes", []),
34
- tslib_1.__metadata("design:returntype", Promise)
35
- ], d.prototype, "doIt", null);
36
20
  d = tslib_1.__decorate([
37
21
  remult3_1.Entity('d1', {
38
22
  allowApiCrud: true
@@ -267,7 +267,7 @@ var MockRestDataProvider = /** @class */ (function () {
267
267
  MockRestDataProvider.prototype.getEntityDataProvider = function (metadata) {
268
268
  var _this = this;
269
269
  var dataApi = new data_api_1.DataApi(this.remult.repo(metadata.entityType), this.remult);
270
- return new rest_data_provider_1.RestEntityDataProvider("", {
270
+ return new rest_data_provider_1.RestEntityDataProvider("", new context_1.HttpProviderBridgeToRestDataProviderHttpProvider({
271
271
  delete: function (url) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
272
272
  var urlSplit, r, result;
273
273
  return tslib_1.__generator(this, function (_a) {
@@ -359,7 +359,7 @@ var MockRestDataProvider = /** @class */ (function () {
359
359
  }
360
360
  });
361
361
  }); }
362
- }, metadata);
362
+ }), metadata);
363
363
  };
364
364
  MockRestDataProvider.prototype.transaction = function (action) {
365
365
  throw new Error('Method not implemented.');
@@ -5,7 +5,6 @@ export declare class Status {
5
5
  static closed: Status;
6
6
  static hold: Status;
7
7
  constructor(id: number, name: string);
8
- toString(): string;
9
8
  }
10
9
  export declare class TestStatus {
11
10
  id?: string;
@@ -9,9 +9,6 @@ var Status = /** @class */ (function () {
9
9
  this.name = name;
10
10
  }
11
11
  Status_1 = Status;
12
- Status.prototype.toString = function () {
13
- return this.name;
14
- };
15
12
  var Status_1;
16
13
  Status.open = new Status_1(0, "open");
17
14
  Status.closed = new Status_1(1, "closed");