remult 3.0.1 → 3.0.3-next.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.
@@ -1,10 +1,13 @@
1
+ import { DuckDBTypeId } from '@duckdb/node-api';
1
2
  import { SqliteCoreDataProvider } from './remult-sqlite-core.js';
2
3
  import { ValueConverters, dbNamesOf, } from './index.js';
3
4
  import { shouldNotCreateField } from './src/filter/filter-consumer-bridge-to-sql-request.js';
4
5
  import { isAutoIncrement } from './src/remult3/RepositoryImplementation.js';
5
6
  export class DuckDBDataProvider extends SqliteCoreDataProvider {
6
- constructor(db) {
7
- super(() => new DuckDBCommand(db), async () => (await db).close(), false, true);
7
+ connection;
8
+ constructor(connection) {
9
+ super(() => new DuckDBCommand(this.connection), async () => this.connection.disconnectSync(), false, true);
10
+ this.connection = connection;
8
11
  }
9
12
  wrapIdentifier(name) {
10
13
  return `"${name}"`;
@@ -12,7 +15,8 @@ export class DuckDBDataProvider extends SqliteCoreDataProvider {
12
15
  async getCreateTableSql(entity) {
13
16
  let result = '';
14
17
  let e = await dbNamesOf(entity, this.wrapIdentifier);
15
- let sql = '';
18
+ const createSequenceStatements = [];
19
+ let createTableSql = '';
16
20
  for (const x of entity.fields) {
17
21
  if (!shouldNotCreateField(x, e) || isAutoIncrement(x)) {
18
22
  if (result.length != 0)
@@ -20,7 +24,7 @@ export class DuckDBDataProvider extends SqliteCoreDataProvider {
20
24
  result += '\r\n ';
21
25
  if (isAutoIncrement(x)) {
22
26
  const sequenceName = `${entity.dbName}_${x.dbName}_seq`;
23
- sql += `create sequence if not exists "${sequenceName}";\r\n`;
27
+ createSequenceStatements.push(`create sequence if not exists "${sequenceName}";`);
24
28
  result += `${e.$dbNameOf(x)} integer default nextval('${sequenceName}')`;
25
29
  }
26
30
  else {
@@ -31,9 +35,9 @@ export class DuckDBDataProvider extends SqliteCoreDataProvider {
31
35
  result += `,\r\n primary key (${entity.idMetadata.fields
32
36
  .map((f) => e.$dbNameOf(f))
33
37
  .join(',')})`;
34
- sql +=
38
+ createTableSql =
35
39
  'create table if not exists ' + e.$entityName + ' (' + result + '\r\n)';
36
- return [sql];
40
+ return [...createSequenceStatements, createTableSql];
37
41
  }
38
42
  addColumnSqlSyntax(x, dbName, isAlterColumn) {
39
43
  let result = dbName;
@@ -74,38 +78,83 @@ export class DuckDBDataProvider extends SqliteCoreDataProvider {
74
78
  }
75
79
  }
76
80
  class DuckDBCommand {
77
- db;
81
+ connection;
78
82
  values = [];
79
- constructor(db) {
80
- this.db = db;
83
+ constructor(connection) {
84
+ this.connection = connection;
81
85
  }
82
86
  async execute(sql) {
83
- return new Promise((resolve, error) => {
84
- this.db.all(sql, ...this.values, (err, rows) => {
85
- if (err)
86
- error(err);
87
- else
88
- resolve(new DuckDBSqlResult(rows));
89
- });
90
- });
87
+ try {
88
+ const result = await this.connection.run(sql, this.values);
89
+ this.values = [];
90
+ return new DuckDBSqlResult(result);
91
+ }
92
+ catch (err) {
93
+ this.values = [];
94
+ throw err;
95
+ }
96
+ }
97
+ addParamInternal(val) {
98
+ if (val === undefined) {
99
+ this.values.push(null);
100
+ }
101
+ else if (val instanceof Date) {
102
+ this.values.push(val.toISOString());
103
+ }
104
+ else {
105
+ this.values.push(val);
106
+ }
107
+ return '?';
91
108
  }
92
109
  addParameterAndReturnSqlToken(val) {
93
- return this.param(val);
110
+ return this.addParamInternal(val);
94
111
  }
95
112
  param(val) {
96
- const key = '?';
97
- this.values.push(val);
98
- return key;
113
+ return this.addParamInternal(val);
99
114
  }
100
115
  }
101
116
  class DuckDBSqlResult {
102
- result;
103
- constructor(result) {
104
- this.result = result;
105
- this.rows = result;
106
- }
117
+ duckDbResult;
107
118
  rows;
119
+ constructor(duckDbResult) {
120
+ this.duckDbResult = duckDbResult;
121
+ this.rows = [];
122
+ const columnNames = this.duckDbResult.columnNames();
123
+ const columnTypes = this.duckDbResult.columnTypes();
124
+ const chunkCount = this.duckDbResult.chunkCount;
125
+ for (let i = 0; i < chunkCount; i++) {
126
+ const chunk = this.duckDbResult.getChunk(i);
127
+ const chunkRowObjects = chunk.getRowObjects(columnNames).map((row) => {
128
+ const convertedRow = {};
129
+ columnNames.forEach((colName, colIndex) => {
130
+ const value = row[colName];
131
+ if (value === null) {
132
+ convertedRow[colName] = null;
133
+ }
134
+ else {
135
+ const colType = columnTypes[colIndex];
136
+ const typeId = colType.typeId;
137
+ if (typeId === DuckDBTypeId.TIMESTAMP) {
138
+ const timestampValue = value;
139
+ const parts = timestampValue.toParts();
140
+ convertedRow[colName] = new Date(Date.UTC(parts.date.year, parts.date.month - 1, parts.date.day, parts.time.hour, parts.time.min, parts.time.sec, Math.floor(parts.time.micros / 1000)));
141
+ }
142
+ else if (typeId === DuckDBTypeId.DATE) {
143
+ const dateValue = value;
144
+ const parts = dateValue.toParts();
145
+ convertedRow[colName] = new Date(Date.UTC(parts.year, parts.month - 1, parts.day));
146
+ }
147
+ else {
148
+ convertedRow[colName] = value;
149
+ }
150
+ }
151
+ });
152
+ return convertedRow;
153
+ });
154
+ this.rows.push(...chunkRowObjects);
155
+ }
156
+ }
108
157
  getColumnKeyInResultForIndexInSelect(index) {
109
- return Object.keys(this.result[0])[index];
158
+ return this.duckDbResult.columnName(index);
110
159
  }
111
160
  }
@@ -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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "remult",
3
- "version": "3.0.1",
3
+ "version": "3.0.3-next.0",
4
4
  "description": "A CRUD framework for full-stack TypeScript",
5
5
  "homepage": "https://remult.dev",
6
6
  "repository": {
@@ -1,8 +1,9 @@
1
- import type { Database } from 'duckdb';
1
+ import type { DuckDBConnection } from '@duckdb/node-api';
2
2
  import { SqliteCoreDataProvider } from './remult-sqlite-core.js';
3
3
  import { type FieldMetadata, type EntityMetadata } from './index.js';
4
4
  export declare class DuckDBDataProvider extends SqliteCoreDataProvider {
5
- constructor(db: Database);
5
+ private connection;
6
+ constructor(connection: DuckDBConnection);
6
7
  wrapIdentifier(name: string): string;
7
8
  getCreateTableSql(entity: EntityMetadata<any>): Promise<string[]>;
8
9
  addColumnSqlSyntax(x: FieldMetadata, dbName: string, isAlterColumn: boolean): string;
package/remult-duckdb.js CHANGED
@@ -2,19 +2,18 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.DuckDBDataProvider = void 0;
4
4
  var tslib_1 = require("tslib");
5
+ var node_api_1 = require("@duckdb/node-api");
5
6
  var remult_sqlite_core_js_1 = require("./remult-sqlite-core.js");
6
7
  var index_js_1 = require("./index.js");
7
8
  var filter_consumer_bridge_to_sql_request_js_1 = require("./src/filter/filter-consumer-bridge-to-sql-request.js");
8
9
  var RepositoryImplementation_js_1 = require("./src/remult3/RepositoryImplementation.js");
9
10
  var DuckDBDataProvider = /** @class */ (function (_super) {
10
11
  tslib_1.__extends(DuckDBDataProvider, _super);
11
- function DuckDBDataProvider(db) {
12
- var _this = _super.call(this, function () { return new DuckDBCommand(db); }, function () { return tslib_1.__awaiter(_this, void 0, void 0, function () { return tslib_1.__generator(this, function (_a) {
13
- switch (_a.label) {
14
- case 0: return [4 /*yield*/, db];
15
- case 1: return [2 /*return*/, (_a.sent()).close()];
16
- }
12
+ function DuckDBDataProvider(connection) {
13
+ var _this = _super.call(this, function () { return new DuckDBCommand(_this.connection); }, function () { return tslib_1.__awaiter(_this, void 0, void 0, function () { return tslib_1.__generator(this, function (_a) {
14
+ return [2 /*return*/, this.connection.disconnectSync()];
17
15
  }); }); }, false, true) || this;
16
+ _this.connection = connection;
18
17
  return _this;
19
18
  }
20
19
  DuckDBDataProvider.prototype.wrapIdentifier = function (name) {
@@ -22,7 +21,7 @@ var DuckDBDataProvider = /** @class */ (function (_super) {
22
21
  };
23
22
  DuckDBDataProvider.prototype.getCreateTableSql = function (entity) {
24
23
  return tslib_1.__awaiter(this, void 0, void 0, function () {
25
- var result, e, sql, _a, _b, x, sequenceName;
24
+ var result, e, createSequenceStatements, createTableSql, _a, _b, x, sequenceName;
26
25
  var e_1, _c;
27
26
  return tslib_1.__generator(this, function (_d) {
28
27
  switch (_d.label) {
@@ -31,7 +30,8 @@ var DuckDBDataProvider = /** @class */ (function (_super) {
31
30
  return [4 /*yield*/, (0, index_js_1.dbNamesOf)(entity, this.wrapIdentifier)];
32
31
  case 1:
33
32
  e = _d.sent();
34
- sql = '';
33
+ createSequenceStatements = [];
34
+ createTableSql = '';
35
35
  try {
36
36
  for (_a = tslib_1.__values(entity.fields), _b = _a.next(); !_b.done; _b = _a.next()) {
37
37
  x = _b.value;
@@ -41,7 +41,7 @@ var DuckDBDataProvider = /** @class */ (function (_super) {
41
41
  result += '\r\n ';
42
42
  if ((0, RepositoryImplementation_js_1.isAutoIncrement)(x)) {
43
43
  sequenceName = "".concat(entity.dbName, "_").concat(x.dbName, "_seq");
44
- sql += "create sequence if not exists \"".concat(sequenceName, "\";\r\n");
44
+ createSequenceStatements.push("create sequence if not exists \"".concat(sequenceName, "\";"));
45
45
  result += "".concat(e.$dbNameOf(x), " integer default nextval('").concat(sequenceName, "')");
46
46
  }
47
47
  else {
@@ -60,9 +60,9 @@ var DuckDBDataProvider = /** @class */ (function (_super) {
60
60
  result += ",\r\n primary key (".concat(entity.idMetadata.fields
61
61
  .map(function (f) { return e.$dbNameOf(f); })
62
62
  .join(','), ")");
63
- sql +=
63
+ createTableSql =
64
64
  'create table if not exists ' + e.$entityName + ' (' + result + '\r\n)';
65
- return [2 /*return*/, [sql]];
65
+ return [2 /*return*/, tslib_1.__spreadArray(tslib_1.__spreadArray([], tslib_1.__read(createSequenceStatements), false), [createTableSql], false)];
66
66
  }
67
67
  });
68
68
  });
@@ -108,43 +108,93 @@ var DuckDBDataProvider = /** @class */ (function (_super) {
108
108
  }(remult_sqlite_core_js_1.SqliteCoreDataProvider));
109
109
  exports.DuckDBDataProvider = DuckDBDataProvider;
110
110
  var DuckDBCommand = /** @class */ (function () {
111
- function DuckDBCommand(db) {
112
- this.db = db;
111
+ function DuckDBCommand(connection) {
112
+ this.connection = connection;
113
113
  this.values = [];
114
114
  }
115
115
  DuckDBCommand.prototype.execute = function (sql) {
116
116
  return tslib_1.__awaiter(this, void 0, void 0, function () {
117
- var _this = this;
117
+ var result, err_1;
118
118
  return tslib_1.__generator(this, function (_a) {
119
- return [2 /*return*/, new Promise(function (resolve, error) {
120
- var _a;
121
- (_a = _this.db).all.apply(_a, tslib_1.__spreadArray(tslib_1.__spreadArray([sql], tslib_1.__read(_this.values), false), [function (err, rows) {
122
- if (err)
123
- error(err);
124
- else
125
- resolve(new DuckDBSqlResult(rows));
126
- }], false));
127
- })];
119
+ switch (_a.label) {
120
+ case 0:
121
+ _a.trys.push([0, 2, , 3]);
122
+ return [4 /*yield*/, this.connection.run(sql, this.values)];
123
+ case 1:
124
+ result = _a.sent();
125
+ this.values = [];
126
+ return [2 /*return*/, new DuckDBSqlResult(result)];
127
+ case 2:
128
+ err_1 = _a.sent();
129
+ this.values = [];
130
+ throw err_1;
131
+ case 3: return [2 /*return*/];
132
+ }
128
133
  });
129
134
  });
130
135
  };
136
+ DuckDBCommand.prototype.addParamInternal = function (val) {
137
+ if (val === undefined) {
138
+ this.values.push(null);
139
+ }
140
+ else if (val instanceof Date) {
141
+ this.values.push(val.toISOString());
142
+ }
143
+ else {
144
+ this.values.push(val);
145
+ }
146
+ return '?';
147
+ };
131
148
  DuckDBCommand.prototype.addParameterAndReturnSqlToken = function (val) {
132
- return this.param(val);
149
+ return this.addParamInternal(val);
133
150
  };
134
151
  DuckDBCommand.prototype.param = function (val) {
135
- var key = '?';
136
- this.values.push(val);
137
- return key;
152
+ return this.addParamInternal(val);
138
153
  };
139
154
  return DuckDBCommand;
140
155
  }());
141
156
  var DuckDBSqlResult = /** @class */ (function () {
142
- function DuckDBSqlResult(result) {
143
- this.result = result;
144
- this.rows = result;
157
+ function DuckDBSqlResult(duckDbResult) {
158
+ var _a;
159
+ this.duckDbResult = duckDbResult;
160
+ this.rows = [];
161
+ var columnNames = this.duckDbResult.columnNames();
162
+ var columnTypes = this.duckDbResult.columnTypes();
163
+ var chunkCount = this.duckDbResult.chunkCount;
164
+ for (var i = 0; i < chunkCount; i++) {
165
+ var chunk = this.duckDbResult.getChunk(i);
166
+ var chunkRowObjects = chunk.getRowObjects(columnNames).map(function (row) {
167
+ var convertedRow = {};
168
+ columnNames.forEach(function (colName, colIndex) {
169
+ var value = row[colName];
170
+ if (value === null) {
171
+ convertedRow[colName] = null;
172
+ }
173
+ else {
174
+ var colType = columnTypes[colIndex];
175
+ var typeId = colType.typeId;
176
+ if (typeId === node_api_1.DuckDBTypeId.TIMESTAMP) {
177
+ var timestampValue = value;
178
+ var parts = timestampValue.toParts();
179
+ convertedRow[colName] = new Date(Date.UTC(parts.date.year, parts.date.month - 1, parts.date.day, parts.time.hour, parts.time.min, parts.time.sec, Math.floor(parts.time.micros / 1000)));
180
+ }
181
+ else if (typeId === node_api_1.DuckDBTypeId.DATE) {
182
+ var dateValue = value;
183
+ var parts = dateValue.toParts();
184
+ convertedRow[colName] = new Date(Date.UTC(parts.year, parts.month - 1, parts.day));
185
+ }
186
+ else {
187
+ convertedRow[colName] = value;
188
+ }
189
+ }
190
+ });
191
+ return convertedRow;
192
+ });
193
+ (_a = this.rows).push.apply(_a, tslib_1.__spreadArray([], tslib_1.__read(chunkRowObjects), false));
194
+ }
145
195
  }
146
196
  DuckDBSqlResult.prototype.getColumnKeyInResultForIndexInSelect = function (index) {
147
- return Object.keys(this.result[0])[index];
197
+ return this.duckDbResult.columnName(index);
148
198
  };
149
199
  return DuckDBSqlResult;
150
200
  }());
@@ -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>}