remult 3.0.2 → 3.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/esm/internals.js CHANGED
@@ -5,4 +5,5 @@ export { decorateColumnSettings, controllerRefImpl, getControllerRef, fieldOptio
5
5
  export { getEntitySettings } from './src/remult3/getEntityRef.js';
6
6
  export { __updateEntityBasedOnWhere } from './src/filter/filter-interfaces.js';
7
7
  export const actionInfo = remultStatic.actionInfo;
8
+ export { isOfType } from './src/isOfType.js';
8
9
  export { flags } from './src/remult3/remult3.js';
@@ -63,6 +63,9 @@ export function remultApi(options) {
63
63
  });
64
64
  const res = new Response(JSON.stringify(responseFromRemultHandler.data), {
65
65
  status: responseFromRemultHandler.statusCode,
66
+ headers: {
67
+ 'Content-Type': 'application/json',
68
+ }
66
69
  });
67
70
  return res;
68
71
  }
@@ -14,17 +14,20 @@ export function TestApiDataProvider(options) {
14
14
  buildGenericRequestInfo: (req) => req,
15
15
  ignoreAsyncStorage: true,
16
16
  });
17
+ const lock = new AsyncLock();
17
18
  async function handleOnServer(req) {
18
- return await MakeServerCallWithDifferentStaticRemult(async () => {
19
- if (newEntities.length > 0 && options?.ensureSchema != false) {
20
- await (await dp).ensureSchema?.(newEntities);
21
- newEntities = [];
22
- }
23
- var result = await server.handle(req);
24
- if ((result?.statusCode ?? 200) >= 400) {
25
- throw { ...result?.data, status: result?.statusCode ?? 500 };
26
- }
27
- return result?.data;
19
+ return lock.runExclusive(async () => {
20
+ return await MakeServerCallWithDifferentStaticRemult(async () => {
21
+ if (newEntities.length > 0 && options?.ensureSchema != false) {
22
+ await (await dp).ensureSchema?.(newEntities);
23
+ newEntities = [];
24
+ }
25
+ var result = await server.handle(req);
26
+ if ((result?.statusCode ?? 200) >= 400) {
27
+ throw { ...result?.data, status: result?.statusCode ?? 500 };
28
+ }
29
+ return result?.data;
30
+ });
28
31
  });
29
32
  }
30
33
  const registeredEntities = new Set();
@@ -58,6 +61,24 @@ export function TestApiDataProvider(options) {
58
61
  }
59
62
  });
60
63
  }
64
+ export class AsyncLock {
65
+ static enabled = true;
66
+ current = Promise.resolve();
67
+ i = 0;
68
+ async runExclusive(fn) {
69
+ const previous = this.current;
70
+ let resolveNext;
71
+ this.current = new Promise((resolve) => (resolveNext = resolve));
72
+ if (AsyncLock.enabled)
73
+ await previous;
74
+ try {
75
+ return await fn();
76
+ }
77
+ finally {
78
+ resolveNext();
79
+ }
80
+ }
81
+ }
61
82
  async function MakeServerCallWithDifferentStaticRemult(what) {
62
83
  var x = remultStatic.asyncContext;
63
84
  var y = remultStatic.remultFactory;
@@ -52,4 +52,13 @@ export class JsonEntityIndexedDbStorage {
52
52
  request.onsuccess = (event) => resolve();
53
53
  });
54
54
  }
55
+ async removeItem(entityDbName) {
56
+ return new Promise(async (resolve, reject) => {
57
+ const transaction = (await this.init()).transaction([this.storeName], 'readwrite');
58
+ const store = transaction.objectStore(this.storeName);
59
+ const request = store.delete(entityDbName);
60
+ request.onerror = (_event) => reject(request.error);
61
+ request.onsuccess = (_event) => resolve();
62
+ });
63
+ }
55
64
  }
package/internals.d.ts CHANGED
@@ -12,5 +12,6 @@ export declare const actionInfo: {
12
12
  close: () => void;
13
13
  };
14
14
  };
15
+ export { isOfType } from './src/isOfType.js';
15
16
  export type { ClassType } from './classType.js';
16
17
  export { flags } from './src/remult3/remult3.js';
package/internals.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.flags = exports.actionInfo = exports.__updateEntityBasedOnWhere = exports.getEntitySettings = exports.fieldOptionsEnricher = exports.getControllerRef = exports.controllerRefImpl = exports.decorateColumnSettings = exports.getRelationFieldInfo = exports.getRelationInfo = exports.sqlRelationsFilter = exports.sqlRelations = void 0;
3
+ exports.flags = exports.isOfType = exports.actionInfo = exports.__updateEntityBasedOnWhere = exports.getEntitySettings = exports.fieldOptionsEnricher = exports.getControllerRef = exports.controllerRefImpl = exports.decorateColumnSettings = exports.getRelationFieldInfo = exports.getRelationInfo = exports.sqlRelationsFilter = exports.sqlRelations = void 0;
4
4
  var remult_static_js_1 = require("./src/remult-static.js");
5
5
  var sql_relations_js_1 = require("./src/data-providers/sql-relations.js");
6
6
  Object.defineProperty(exports, "sqlRelations", { enumerable: true, get: function () { return sql_relations_js_1.sqlRelations; } });
@@ -18,5 +18,7 @@ Object.defineProperty(exports, "getEntitySettings", { enumerable: true, get: fun
18
18
  var filter_interfaces_js_1 = require("./src/filter/filter-interfaces.js");
19
19
  Object.defineProperty(exports, "__updateEntityBasedOnWhere", { enumerable: true, get: function () { return filter_interfaces_js_1.__updateEntityBasedOnWhere; } });
20
20
  exports.actionInfo = remult_static_js_1.remultStatic.actionInfo;
21
+ var isOfType_js_1 = require("./src/isOfType.js");
22
+ Object.defineProperty(exports, "isOfType", { enumerable: true, get: function () { return isOfType_js_1.isOfType; } });
21
23
  var remult3_js_1 = require("./src/remult3/remult3.js");
22
24
  Object.defineProperty(exports, "flags", { enumerable: true, get: function () { return remult3_js_1.flags; } });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "remult",
3
- "version": "3.0.2",
3
+ "version": "3.0.3",
4
4
  "description": "A CRUD framework for full-stack TypeScript",
5
5
  "homepage": "https://remult.dev",
6
6
  "repository": {
@@ -86,6 +86,9 @@ function remultApi(options) {
86
86
  })];
87
87
  res = new Response(JSON.stringify(responseFromRemultHandler.data), {
88
88
  status: responseFromRemultHandler.statusCode,
89
+ headers: {
90
+ 'Content-Type': 'application/json',
91
+ }
89
92
  });
90
93
  return [2 /*return*/, res];
91
94
  }
@@ -1,3 +1,9 @@
1
1
  import { RestDataProvider } from '../index.js';
2
2
  import type { RemultServerOptions } from './index.js';
3
3
  export declare function TestApiDataProvider(options?: Pick<RemultServerOptions<unknown>, 'ensureSchema' | 'dataProvider'>): RestDataProvider;
4
+ export declare class AsyncLock {
5
+ static enabled: boolean;
6
+ private current;
7
+ i: number;
8
+ runExclusive<T>(fn: () => Promise<T>): Promise<T>;
9
+ }
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AsyncLock = void 0;
3
4
  exports.TestApiDataProvider = TestApiDataProvider;
4
5
  var tslib_1 = require("tslib");
5
6
  var index_js_1 = require("../index.js");
@@ -23,36 +24,42 @@ function TestApiDataProvider(options) {
23
24
  buildGenericRequestInfo: function (req) { return req; },
24
25
  ignoreAsyncStorage: true,
25
26
  });
27
+ var lock = new AsyncLock();
26
28
  function handleOnServer(req) {
27
29
  return tslib_1.__awaiter(this, void 0, void 0, function () {
28
30
  var _this = this;
29
31
  return tslib_1.__generator(this, function (_a) {
30
- switch (_a.label) {
31
- case 0: return [4 /*yield*/, MakeServerCallWithDifferentStaticRemult(function () { return tslib_1.__awaiter(_this, void 0, void 0, function () {
32
- var result;
33
- var _a, _b, _c, _d;
34
- return tslib_1.__generator(this, function (_e) {
35
- switch (_e.label) {
36
- case 0:
37
- if (!(newEntities.length > 0 && (options === null || options === void 0 ? void 0 : options.ensureSchema) != false)) return [3 /*break*/, 3];
38
- return [4 /*yield*/, dp];
39
- case 1: return [4 /*yield*/, ((_b = (_a = (_e.sent())).ensureSchema) === null || _b === void 0 ? void 0 : _b.call(_a, newEntities))];
40
- case 2:
41
- _e.sent();
42
- newEntities = [];
43
- _e.label = 3;
44
- case 3: return [4 /*yield*/, server.handle(req)];
45
- case 4:
46
- result = _e.sent();
47
- if (((_c = result === null || result === void 0 ? void 0 : result.statusCode) !== null && _c !== void 0 ? _c : 200) >= 400) {
48
- throw tslib_1.__assign(tslib_1.__assign({}, result === null || result === void 0 ? void 0 : result.data), { status: (_d = result === null || result === void 0 ? void 0 : result.statusCode) !== null && _d !== void 0 ? _d : 500 });
49
- }
50
- return [2 /*return*/, result === null || result === void 0 ? void 0 : result.data];
51
- }
52
- });
53
- }); })];
54
- case 1: return [2 /*return*/, _a.sent()];
55
- }
32
+ return [2 /*return*/, lock.runExclusive(function () { return tslib_1.__awaiter(_this, void 0, void 0, function () {
33
+ var _this = this;
34
+ return tslib_1.__generator(this, function (_a) {
35
+ switch (_a.label) {
36
+ case 0: return [4 /*yield*/, MakeServerCallWithDifferentStaticRemult(function () { return tslib_1.__awaiter(_this, void 0, void 0, function () {
37
+ var result;
38
+ var _a, _b, _c, _d;
39
+ return tslib_1.__generator(this, function (_e) {
40
+ switch (_e.label) {
41
+ case 0:
42
+ if (!(newEntities.length > 0 && (options === null || options === void 0 ? void 0 : options.ensureSchema) != false)) return [3 /*break*/, 3];
43
+ return [4 /*yield*/, dp];
44
+ case 1: return [4 /*yield*/, ((_b = (_a = (_e.sent())).ensureSchema) === null || _b === void 0 ? void 0 : _b.call(_a, newEntities))];
45
+ case 2:
46
+ _e.sent();
47
+ newEntities = [];
48
+ _e.label = 3;
49
+ case 3: return [4 /*yield*/, server.handle(req)];
50
+ case 4:
51
+ result = _e.sent();
52
+ if (((_c = result === null || result === void 0 ? void 0 : result.statusCode) !== null && _c !== void 0 ? _c : 200) >= 400) {
53
+ throw tslib_1.__assign(tslib_1.__assign({}, result === null || result === void 0 ? void 0 : result.data), { status: (_d = result === null || result === void 0 ? void 0 : result.statusCode) !== null && _d !== void 0 ? _d : 500 });
54
+ }
55
+ return [2 /*return*/, result === null || result === void 0 ? void 0 : result.data];
56
+ }
57
+ });
58
+ }); })];
59
+ case 1: return [2 /*return*/, _a.sent()];
60
+ }
61
+ });
62
+ }); })];
56
63
  });
57
64
  });
58
65
  }
@@ -95,6 +102,40 @@ function TestApiDataProvider(options) {
95
102
  }
96
103
  });
97
104
  }
105
+ var AsyncLock = /** @class */ (function () {
106
+ function AsyncLock() {
107
+ this.current = Promise.resolve();
108
+ this.i = 0;
109
+ }
110
+ AsyncLock.prototype.runExclusive = function (fn) {
111
+ return tslib_1.__awaiter(this, void 0, void 0, function () {
112
+ var previous, resolveNext;
113
+ return tslib_1.__generator(this, function (_a) {
114
+ switch (_a.label) {
115
+ case 0:
116
+ previous = this.current;
117
+ this.current = new Promise(function (resolve) { return (resolveNext = resolve); });
118
+ if (!AsyncLock.enabled) return [3 /*break*/, 2];
119
+ return [4 /*yield*/, previous];
120
+ case 1:
121
+ _a.sent();
122
+ _a.label = 2;
123
+ case 2:
124
+ _a.trys.push([2, , 4, 5]);
125
+ return [4 /*yield*/, fn()];
126
+ case 3: return [2 /*return*/, _a.sent()];
127
+ case 4:
128
+ resolveNext();
129
+ return [7 /*endfinally*/];
130
+ case 5: return [2 /*return*/];
131
+ }
132
+ });
133
+ });
134
+ };
135
+ AsyncLock.enabled = true;
136
+ return AsyncLock;
137
+ }());
138
+ exports.AsyncLock = AsyncLock;
98
139
  function MakeServerCallWithDifferentStaticRemult(what) {
99
140
  return tslib_1.__awaiter(this, void 0, void 0, function () {
100
141
  var x, y, user, store;
@@ -35,6 +35,10 @@ export interface FieldOptions<entityType = unknown, valueType = unknown> {
35
35
  * // Prevent API from updating this field
36
36
  * @Fields.string({ allowApiUpdate: false })
37
37
  * createdBy = remult.user?.id;
38
+ * @example
39
+ * // Allow API update only on new items
40
+ * @Fields.string<Category>({ allowApiUpdate: (c) => getEntityRef(c).isNew() })
41
+ * Description = ""
38
42
  * @see [allowed](https://remult.dev/docs/allowed.html)
39
43
  * @see [Access Control](https://remult.dev/docs/access-control)
40
44
  * @type {AllowedForInstance<entityType>}
@@ -6,4 +6,5 @@ export declare class JsonEntityIndexedDbStorage implements JsonEntityStorage {
6
6
  supportsRawJson: boolean;
7
7
  getItem(entityDbName: string): Promise<string>;
8
8
  setItem(entityDbName: string, json: string): Promise<void>;
9
+ removeItem(entityDbName: string): Promise<void>;
9
10
  }
@@ -92,6 +92,28 @@ var JsonEntityIndexedDbStorage = /** @class */ (function () {
92
92
  });
93
93
  });
94
94
  };
95
+ JsonEntityIndexedDbStorage.prototype.removeItem = function (entityDbName) {
96
+ return tslib_1.__awaiter(this, void 0, void 0, function () {
97
+ var _this = this;
98
+ return tslib_1.__generator(this, function (_a) {
99
+ return [2 /*return*/, new Promise(function (resolve, reject) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
100
+ var transaction, store, request;
101
+ return tslib_1.__generator(this, function (_a) {
102
+ switch (_a.label) {
103
+ case 0: return [4 /*yield*/, this.init()];
104
+ case 1:
105
+ transaction = (_a.sent()).transaction([this.storeName], 'readwrite');
106
+ store = transaction.objectStore(this.storeName);
107
+ request = store.delete(entityDbName);
108
+ request.onerror = function (_event) { return reject(request.error); };
109
+ request.onsuccess = function (_event) { return resolve(); };
110
+ return [2 /*return*/];
111
+ }
112
+ });
113
+ }); })];
114
+ });
115
+ });
116
+ };
95
117
  return JsonEntityIndexedDbStorage;
96
118
  }());
97
119
  exports.JsonEntityIndexedDbStorage = JsonEntityIndexedDbStorage;