remult 0.26.6 → 0.26.8-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.
- package/esm/index.js +1 -1
- package/esm/remult-knex/index.js +6 -12
- package/esm/remult-mongo.js +2 -6
- package/esm/remult-sqlite-core.js +3 -1
- package/esm/remult-sqlite3.js +58 -0
- package/esm/server/expressBridge.js +4 -1
- package/esm/src/data-providers/sql-database.js +41 -5
- package/esm/src/filter/filter-interfaces.js +1 -1
- package/esm/src/remult3/RepositoryImplementation.js +1 -0
- package/esm/src/remult3/{DecoratorReplacer.js → classDescribers.js} +18 -3
- package/esm/src/remult3/getEntityRef.js +9 -0
- package/esm/src/remult3/remult3.js +14 -2
- package/index.d.ts +1 -1
- package/index.js +5 -3
- package/package.json +6 -1
- package/remult-knex/index.js +10 -17
- package/remult-mongo.js +3 -7
- package/remult-sqlite-core.d.ts +2 -1
- package/remult-sqlite-core.js +3 -1
- package/remult-sqlite3.d.ts +12 -0
- package/remult-sqlite3.js +74 -0
- package/server/expressBridge.js +15 -13
- package/src/column-interfaces.d.ts +63 -6
- package/src/data-providers/sql-database.d.ts +1 -0
- package/src/data-providers/sql-database.js +57 -6
- package/src/entity.d.ts +10 -4
- package/src/filter/filter-interfaces.js +1 -1
- package/src/remult3/RepositoryImplementation.js +1 -0
- package/src/remult3/classDescribers.d.ts +16 -0
- package/src/remult3/classDescribers.js +41 -0
- package/src/remult3/getEntityRef.d.ts +9 -0
- package/src/remult3/getEntityRef.js +9 -0
- package/src/remult3/remult3.d.ts +13 -2
- package/src/remult3/remult3.js +14 -2
- package/src/sql-command.d.ts +2 -0
- package/src/remult3/DecoratorReplacer.d.ts +0 -9
- package/src/remult3/DecoratorReplacer.js +0 -24
package/esm/index.js
CHANGED
|
@@ -4,7 +4,7 @@ export { Entity } from './src/remult3/entity.js';
|
|
|
4
4
|
export { getEntityRef } from './src/remult3/getEntityRef.js';
|
|
5
5
|
export { Field, Fields, Relations, } from './src/remult3/Fields.js';
|
|
6
6
|
export { IdEntity } from './src/remult3/IdEntity.js';
|
|
7
|
-
export { describeClass } from './src/remult3/
|
|
7
|
+
export { describeClass, describeBackendMethods, describeEntity, } from './src/remult3/classDescribers.js';
|
|
8
8
|
export { RestDataProvider } from './src/data-providers/rest-data-provider.js'; //V
|
|
9
9
|
export { InMemoryDataProvider } from './src/data-providers/in-memory-database.js'; //V
|
|
10
10
|
export { WebSqlDataProvider } from './src/data-providers/web-sql-data-provider.js'; //V
|
package/esm/remult-knex/index.js
CHANGED
|
@@ -7,6 +7,7 @@ import { Sort } from '../src/sort.js';
|
|
|
7
7
|
import { ValueConverters } from '../src/valueConverters.js';
|
|
8
8
|
import { getRepositoryInternals } from '../src/remult3/repository-internals.js';
|
|
9
9
|
import { remultStatic } from '../src/remult-static.js';
|
|
10
|
+
import { getRowAfterUpdate } from '../src/data-providers/sql-database.js';
|
|
10
11
|
export class KnexDataProvider {
|
|
11
12
|
knex;
|
|
12
13
|
constructor(knex) {
|
|
@@ -196,9 +197,6 @@ class KnexEntityDataProvider {
|
|
|
196
197
|
const e = await this.init();
|
|
197
198
|
let f = new FilterConsumerBridgeToKnexRequest(e, this.rawSqlWrapIdentifier);
|
|
198
199
|
Filter.fromEntityFilter(this.entity, this.entity.idMetadata.getIdFilter(id)).__applyToConsumer(f);
|
|
199
|
-
let resultFilter = this.entity.idMetadata.getIdFilter(id);
|
|
200
|
-
if (data.id != undefined)
|
|
201
|
-
resultFilter = this.entity.idMetadata.getIdFilter(data.id);
|
|
202
200
|
let updateObject = {};
|
|
203
201
|
for (const x of this.entity.fields) {
|
|
204
202
|
if (isDbReadonly(x, e)) {
|
|
@@ -215,9 +213,7 @@ class KnexEntityDataProvider {
|
|
|
215
213
|
await this.knex(e.$entityName)
|
|
216
214
|
.update(updateObject)
|
|
217
215
|
.where((b) => where.forEach((w) => w(b)));
|
|
218
|
-
return this.
|
|
219
|
-
where: Filter.fromEntityFilter(this.entity, resultFilter),
|
|
220
|
-
}).then((y) => y[0]);
|
|
216
|
+
return getRowAfterUpdate(this.entity, this, data, id, 'update');
|
|
221
217
|
}
|
|
222
218
|
async delete(id) {
|
|
223
219
|
const e = await this.init();
|
|
@@ -230,8 +226,6 @@ class KnexEntityDataProvider {
|
|
|
230
226
|
}
|
|
231
227
|
async insert(data) {
|
|
232
228
|
const e = await this.init();
|
|
233
|
-
let resultFilter;
|
|
234
|
-
resultFilter = Filter.fromEntityFilter(this.entity, this.entity.idMetadata.getIdFilter(data[this.entity.idMetadata.field.key]));
|
|
235
229
|
let insertObject = {};
|
|
236
230
|
for (const x of this.entity.fields) {
|
|
237
231
|
if (isDbReadonly(x, e)) {
|
|
@@ -256,13 +250,13 @@ class KnexEntityDataProvider {
|
|
|
256
250
|
let result = await insert.returning(this.entity.idMetadata.field.key);
|
|
257
251
|
newId = result[0].id;
|
|
258
252
|
}
|
|
259
|
-
|
|
253
|
+
return this.find({
|
|
254
|
+
where: new Filter((x) => x.isEqualTo(this.entity.idMetadata.field, newId)),
|
|
255
|
+
}).then((y) => y[0]);
|
|
260
256
|
}
|
|
261
257
|
else
|
|
262
258
|
await insert;
|
|
263
|
-
return this.
|
|
264
|
-
return y[0];
|
|
265
|
-
});
|
|
259
|
+
return getRowAfterUpdate(this.entity, this, data, undefined, 'insert');
|
|
266
260
|
}
|
|
267
261
|
}
|
|
268
262
|
class FilterConsumerBridgeToKnexRequest {
|
package/esm/remult-mongo.js
CHANGED
|
@@ -4,6 +4,7 @@ import { dbNamesOf } from './src/filter/filter-consumer-bridge-to-sql-request.js
|
|
|
4
4
|
import { remult as remultContext } from './src/remult-proxy.js';
|
|
5
5
|
import { getRepository } from './src/remult3/RepositoryImplementation.js';
|
|
6
6
|
import { getRepositoryInternals } from './src/remult3/repository-internals.js';
|
|
7
|
+
import { getRowAfterUpdate } from './src/data-providers/sql-database.js';
|
|
7
8
|
export class MongoDataProvider {
|
|
8
9
|
db;
|
|
9
10
|
client;
|
|
@@ -126,9 +127,6 @@ class MongoEntityDataProvider {
|
|
|
126
127
|
let { collection, e } = await this.collection();
|
|
127
128
|
let f = new FilterConsumerBridgeToMongo(e);
|
|
128
129
|
Filter.fromEntityFilter(this.entity, this.entity.idMetadata.getIdFilter(id)).__applyToConsumer(f);
|
|
129
|
-
let resultFilter = this.entity.idMetadata.getIdFilter(id);
|
|
130
|
-
if (data.id != undefined)
|
|
131
|
-
resultFilter = this.entity.idMetadata.getIdFilter(data.id);
|
|
132
130
|
let newR = {};
|
|
133
131
|
let keys = Object.keys(data);
|
|
134
132
|
for (const f of this.entity.fields) {
|
|
@@ -141,9 +139,7 @@ class MongoEntityDataProvider {
|
|
|
141
139
|
let r = await collection.updateOne(await f.resolveWhere(), {
|
|
142
140
|
$set: newR,
|
|
143
141
|
}, { session: this.session });
|
|
144
|
-
return this.
|
|
145
|
-
where: Filter.fromEntityFilter(this.entity, resultFilter),
|
|
146
|
-
}).then((y) => y[0]);
|
|
142
|
+
return getRowAfterUpdate(this.entity, this, data, id, 'update');
|
|
147
143
|
}
|
|
148
144
|
async delete(id) {
|
|
149
145
|
const { e, collection } = await this.collection();
|
|
@@ -4,9 +4,11 @@ import { isAutoIncrement } from './src/remult3/RepositoryImplementation.js';
|
|
|
4
4
|
export class SqliteCoreDataProvider {
|
|
5
5
|
createCommand;
|
|
6
6
|
end;
|
|
7
|
-
|
|
7
|
+
doesNotSupportReturningSyntax;
|
|
8
|
+
constructor(createCommand, end, doesNotSupportReturningSyntax = false) {
|
|
8
9
|
this.createCommand = createCommand;
|
|
9
10
|
this.end = end;
|
|
11
|
+
this.doesNotSupportReturningSyntax = doesNotSupportReturningSyntax;
|
|
10
12
|
}
|
|
11
13
|
orderByNullsFirst;
|
|
12
14
|
getLimitSqlSyntax(limit, offset) {
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { SqliteCoreDataProvider } from '../core/remult-sqlite-core.js';
|
|
2
|
+
export class Sqlite3DataProvider extends SqliteCoreDataProvider {
|
|
3
|
+
constructor(db) {
|
|
4
|
+
super(() => new Sqlite3Command(db), async () => {
|
|
5
|
+
db.close();
|
|
6
|
+
}, true);
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
class Sqlite3Command {
|
|
10
|
+
db;
|
|
11
|
+
values = {};
|
|
12
|
+
i = 1;
|
|
13
|
+
constructor(db) {
|
|
14
|
+
this.db = db;
|
|
15
|
+
}
|
|
16
|
+
async execute(sql) {
|
|
17
|
+
return new Promise((resolve, error) => {
|
|
18
|
+
if (sql.startsWith('insert into')) {
|
|
19
|
+
this.db.run(sql, this.values, function (err, rows) {
|
|
20
|
+
if (err)
|
|
21
|
+
error(err);
|
|
22
|
+
else
|
|
23
|
+
resolve(new Sqlite3SqlResult([this.lastID]));
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
else
|
|
27
|
+
this.db.all(sql, this.values, (err, rows) => {
|
|
28
|
+
if (err)
|
|
29
|
+
error(err);
|
|
30
|
+
else
|
|
31
|
+
resolve(new Sqlite3SqlResult(rows));
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
addParameterAndReturnSqlToken(val) {
|
|
36
|
+
return this.param(val);
|
|
37
|
+
}
|
|
38
|
+
param(val) {
|
|
39
|
+
if (val instanceof Date)
|
|
40
|
+
val = val.valueOf();
|
|
41
|
+
if (typeof val === 'boolean')
|
|
42
|
+
val = val ? 1 : 0;
|
|
43
|
+
const key = ':' + this.i++;
|
|
44
|
+
this.values[key.substring(1)] = val;
|
|
45
|
+
return key;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
export class Sqlite3SqlResult {
|
|
49
|
+
result;
|
|
50
|
+
constructor(result) {
|
|
51
|
+
this.result = result;
|
|
52
|
+
this.rows = result;
|
|
53
|
+
}
|
|
54
|
+
rows;
|
|
55
|
+
getColumnKeyInResultForIndexInSelect(index) {
|
|
56
|
+
return Object.keys(this.result[0])[index];
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -266,11 +266,14 @@ export class RemultServerImplementation {
|
|
|
266
266
|
}
|
|
267
267
|
//runs with remult but without init request
|
|
268
268
|
async runWithRemult(what, options) {
|
|
269
|
+
let dataProvider;
|
|
270
|
+
if (!options?.skipDataProvider)
|
|
271
|
+
dataProvider = await this.dataProvider;
|
|
269
272
|
return await withRemult(async (remult) => {
|
|
270
273
|
var x = remult;
|
|
271
274
|
x.liveQueryPublisher = new LiveQueryPublisher(() => remult.subscriptionServer, () => remult.liveQueryStorage, this.runWithSerializedJsonContextData);
|
|
272
275
|
if (!options?.skipDataProvider)
|
|
273
|
-
x.dataProvider =
|
|
276
|
+
x.dataProvider = dataProvider;
|
|
274
277
|
x.subscriptionServer = this.subscriptionServer;
|
|
275
278
|
x.liveQueryStorage = this.liveQueryStorage;
|
|
276
279
|
return await what(x);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { FilterConsumerBridgeToSqlRequest, dbNamesOf, isDbReadonly, } from '../filter/filter-consumer-bridge-to-sql-request.js';
|
|
2
2
|
import { Filter, customDatabaseFilterToken, } from '../filter/filter-interfaces.js';
|
|
3
3
|
import { remult as defaultRemult } from '../remult-proxy.js';
|
|
4
|
-
import { getRepository } from '../remult3/RepositoryImplementation.js';
|
|
4
|
+
import { getRepository, isAutoIncrement, } from '../remult3/RepositoryImplementation.js';
|
|
5
5
|
import { Sort } from '../sort.js';
|
|
6
6
|
import { ValueConverters } from '../valueConverters.js';
|
|
7
7
|
import { getRepositoryInternals } from '../remult3/repository-internals.js';
|
|
@@ -323,8 +323,6 @@ class ActualSQLServerDataProvider {
|
|
|
323
323
|
async update(id, data) {
|
|
324
324
|
let e = await this.init();
|
|
325
325
|
let r = this.sql.createCommand();
|
|
326
|
-
let f = new FilterConsumerBridgeToSqlRequest(r, e);
|
|
327
|
-
Filter.fromEntityFilter(this.entity, this.entity.idMetadata.getIdFilter(id)).__applyToConsumer(f);
|
|
328
326
|
let statement = 'update ' + e.$entityName + ' set ';
|
|
329
327
|
let added = false;
|
|
330
328
|
for (const x of this.entity.fields) {
|
|
@@ -341,11 +339,18 @@ class ActualSQLServerDataProvider {
|
|
|
341
339
|
}
|
|
342
340
|
}
|
|
343
341
|
}
|
|
342
|
+
const idFilter = this.entity.idMetadata.getIdFilter(id);
|
|
343
|
+
let f = new FilterConsumerBridgeToSqlRequest(r, e);
|
|
344
|
+
Filter.fromEntityFilter(this.entity, idFilter).__applyToConsumer(f);
|
|
344
345
|
statement += await f.resolveWhere();
|
|
345
346
|
let { colKeys, select } = this.buildSelect(e);
|
|
346
|
-
|
|
347
|
+
if (!this.sql._getSourceSql().doesNotSupportReturningSyntax)
|
|
348
|
+
statement += ' returning ' + select;
|
|
347
349
|
return r.execute(statement).then((sqlResult) => {
|
|
348
350
|
this.sql._getSourceSql().afterMutation?.();
|
|
351
|
+
if (this.sql._getSourceSql().doesNotSupportReturningSyntax) {
|
|
352
|
+
return getRowAfterUpdate(this.entity, this, data, id, 'update');
|
|
353
|
+
}
|
|
349
354
|
if (sqlResult.rows.length != 1)
|
|
350
355
|
throw new Error('Failed to update row with id ' +
|
|
351
356
|
id +
|
|
@@ -390,9 +395,24 @@ class ActualSQLServerDataProvider {
|
|
|
390
395
|
}
|
|
391
396
|
let statement = `insert into ${e.$entityName} (${cols}) values (${vals})`;
|
|
392
397
|
let { colKeys, select } = this.buildSelect(e);
|
|
393
|
-
|
|
398
|
+
if (!this.sql._getSourceSql().doesNotSupportReturningSyntax)
|
|
399
|
+
statement += ' returning ' + select;
|
|
394
400
|
return await r.execute(statement).then((sql) => {
|
|
395
401
|
this.sql._getSourceSql().afterMutation?.();
|
|
402
|
+
if (this.sql._getSourceSql().doesNotSupportReturningSyntax) {
|
|
403
|
+
if (isAutoIncrement(this.entity.idMetadata.field)) {
|
|
404
|
+
const id = sql.rows[0];
|
|
405
|
+
if (typeof id !== 'number')
|
|
406
|
+
throw new Error('Auto increment, for a database that is does not support returning syntax, should return an array with the single last added id. Instead it returned: ' +
|
|
407
|
+
JSON.stringify(id));
|
|
408
|
+
return this.find({
|
|
409
|
+
where: new Filter((x) => x.isEqualTo(this.entity.idMetadata.field, id)),
|
|
410
|
+
}).then((r) => r[0]);
|
|
411
|
+
}
|
|
412
|
+
else {
|
|
413
|
+
return getRowAfterUpdate(this.entity, this, data, undefined, 'insert');
|
|
414
|
+
}
|
|
415
|
+
}
|
|
396
416
|
return this.buildResultRow(colKeys, sql.rows[0], sql);
|
|
397
417
|
});
|
|
398
418
|
}
|
|
@@ -440,3 +460,19 @@ async function bulkInsert(array, db) {
|
|
|
440
460
|
await c.execute(sql);
|
|
441
461
|
}
|
|
442
462
|
}
|
|
463
|
+
export function getRowAfterUpdate(meta, dataProvider, data, id, operation) {
|
|
464
|
+
const idFilter = id !== undefined ? meta.idMetadata.getIdFilter(id) : {};
|
|
465
|
+
return dataProvider
|
|
466
|
+
.find({
|
|
467
|
+
where: new Filter((x) => {
|
|
468
|
+
for (const field of meta.idMetadata.fields) {
|
|
469
|
+
x.isEqualTo(field, data[field.key] ?? idFilter[field.key]);
|
|
470
|
+
}
|
|
471
|
+
}),
|
|
472
|
+
})
|
|
473
|
+
.then((r) => {
|
|
474
|
+
if (r.length != 1)
|
|
475
|
+
throw new Error(`Failed to ${operation} row - result contained ${r.length} rows`);
|
|
476
|
+
return r[0];
|
|
477
|
+
});
|
|
478
|
+
}
|
|
@@ -304,7 +304,7 @@ class filterHelper {
|
|
|
304
304
|
processVal(val) {
|
|
305
305
|
let ei = getEntitySettings(this.metadata.valueType, false);
|
|
306
306
|
if (ei) {
|
|
307
|
-
if (
|
|
307
|
+
if (val === undefined || val === null) {
|
|
308
308
|
if (val === null && !this.metadata.allowNull) {
|
|
309
309
|
const rel = getRelationFieldInfo(this.metadata);
|
|
310
310
|
if (rel?.type === 'reference')
|
|
@@ -1312,6 +1312,7 @@ export class rowHelperImplementation extends rowHelperBase {
|
|
|
1312
1312
|
}
|
|
1313
1313
|
}
|
|
1314
1314
|
await this.loadDataFrom(updatedRow);
|
|
1315
|
+
e.id = this.getId();
|
|
1315
1316
|
if (!this.repository._dataProvider.isProxy) {
|
|
1316
1317
|
if (this.info.entityInfo.saved)
|
|
1317
1318
|
await this.info.entityInfo.saved(this.instance, e);
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { BackendMethod } from '../server-action.js';
|
|
2
|
+
import { Entity } from './entity.js';
|
|
3
|
+
export function describeClass(classType, classDescriber, members, staticMembers) {
|
|
4
|
+
if (classDescriber)
|
|
5
|
+
classDescriber(classType);
|
|
4
6
|
for (const fieldKey in members) {
|
|
5
7
|
if (Object.prototype.hasOwnProperty.call(members, fieldKey)) {
|
|
6
8
|
const element = members[fieldKey];
|
|
@@ -18,3 +20,16 @@ export function describeClass(classType, classDecorator, members, staticMembers)
|
|
|
18
20
|
Object.defineProperty(classType, staticFieldKey, prop);
|
|
19
21
|
}
|
|
20
22
|
}
|
|
23
|
+
export function describeBackendMethods(classType, backendMethods) {
|
|
24
|
+
let result = {};
|
|
25
|
+
for (const key in backendMethods) {
|
|
26
|
+
if (Object.prototype.hasOwnProperty.call(backendMethods, key)) {
|
|
27
|
+
const options = backendMethods[key];
|
|
28
|
+
result[key] = BackendMethod(options);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
describeClass(classType, undefined, undefined, result);
|
|
32
|
+
}
|
|
33
|
+
export function describeEntity(classType, key, fields, options) {
|
|
34
|
+
describeClass(classType, Entity(key, options), fields);
|
|
35
|
+
}
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Retrieves the EntityRef object associated with the specified entity instance.
|
|
3
|
+
* The EntityRef provides methods for performing operations on the entity instance.
|
|
4
|
+
* @param {entityType} entity - The entity instance.
|
|
5
|
+
* @param {boolean} [throwException=true] - Indicates whether to throw an exception if the EntityRef object cannot be retrieved.
|
|
6
|
+
* @returns {EntityRef<entityType>} The EntityRef object associated with the specified entity instance.
|
|
7
|
+
* @throws {Error} If throwException is true and the EntityRef object cannot be retrieved.
|
|
8
|
+
* @see [Active Record & EntityBase](https://remult.dev/docs/active-record)
|
|
9
|
+
*/
|
|
1
10
|
export function getEntityRef(entity, throwException = true) {
|
|
2
11
|
let x = entity[entityMember];
|
|
3
12
|
if (!x && throwException)
|
|
@@ -1,7 +1,20 @@
|
|
|
1
1
|
export {};
|
|
2
|
+
//p1 - remove controller and instance backend methods from the regular backend method article
|
|
3
|
+
//p1 - describe entity
|
|
4
|
+
//p1 - fix includeInApi documentation - figure out why we can't see the see?
|
|
2
5
|
//y2 - soft-delete-discussion https://discord.com/channels/975754286384418847/1230386433093533698/1230386433093533698
|
|
3
|
-
//y1 - In the esm version of our tutorial - the imports are automatically .ts and not .js
|
|
6
|
+
//y1 - In the esm version of our tutorial - the imports are automatically .ts and not .js in react and not in vue
|
|
7
|
+
//y1 - talk about insert with relations
|
|
4
8
|
//y1 - consider id to also support keyof (id:['company','index']) - had problem with | (keyof Partial<entityType>)[] & `entity`
|
|
9
|
+
//y1 - change exp version to preview?
|
|
10
|
+
//y1 - talk about insert / update / delete with relations
|
|
11
|
+
/*
|
|
12
|
+
repo(Order).insert({},{
|
|
13
|
+
relations:{
|
|
14
|
+
orderItems:[{},{},{}]
|
|
15
|
+
}
|
|
16
|
+
})
|
|
17
|
+
*/
|
|
5
18
|
//y1 - repo batch - for multiple operations:
|
|
6
19
|
/*
|
|
7
20
|
const result = await repo.batch(x=>({
|
|
@@ -12,7 +25,6 @@ export {};
|
|
|
12
25
|
//p1 - add documentation for bun sqlite
|
|
13
26
|
//p1 - consider upsert (where,set)
|
|
14
27
|
//p1 - wait a second to close stream
|
|
15
|
-
//p1 - describe entity
|
|
16
28
|
//p1 - prepare the createEntity discussion
|
|
17
29
|
//p1 - write active record article
|
|
18
30
|
//p1 - return error on connection error
|
package/index.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ export { Entity } from './src/remult3/entity.js';
|
|
|
9
9
|
export { getEntityRef } from './src/remult3/getEntityRef.js';
|
|
10
10
|
export { Field, Fields, StringFieldOptions, Relations, } from './src/remult3/Fields.js';
|
|
11
11
|
export { IdEntity } from './src/remult3/IdEntity.js';
|
|
12
|
-
export { describeClass } from './src/remult3/
|
|
12
|
+
export { describeClass, describeBackendMethods, describeEntity, } from './src/remult3/classDescribers.js';
|
|
13
13
|
export { EntityOptions, PreprocessFilterEvent } from './src/entity.js';
|
|
14
14
|
export { DataProvider, EntityDataProvider, EntityDataProviderFindOptions, ErrorInfo, RestDataProviderHttpProvider, } from './src/data-interfaces.js';
|
|
15
15
|
export { SqlCommand, SqlCommandWithParameters, SqlImplementation, SqlResult, } from './src/sql-command.js';
|
package/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.repo = exports.SubscriptionChannel = exports.InMemoryLiveQueryStorage = exports.remult = exports.ValueConverters = exports.createValueValidator = exports.createValueValidatorWithArgs = exports.createValidatorWithArgs = exports.createValidator = exports.valueValidator = exports.Validators = exports.UrlBuilder = exports.Filter = exports.CompoundIdField = exports.Sort = exports.EventSource = exports.isBackend = exports.withRemult = exports.Remult = exports.Allow = exports.ForbiddenError = exports.ProgressListener = exports.BackendMethod = exports.Controller = exports.JsonEntityOpfsStorage = exports.JsonDataProvider = exports.dbNamesOf = exports.CustomSqlFilterBuilder = exports.SqlDatabase = exports.WebSqlDataProvider = exports.InMemoryDataProvider = exports.RestDataProvider = exports.describeClass = exports.IdEntity = exports.Relations = exports.Fields = exports.Field = exports.getEntityRef = exports.Entity = exports.CaptionTransformer = exports.ValueListInfo = exports.getValueList = exports.ValueListFieldType = exports.getFields = exports.FieldType = exports.ControllerBase = exports.EntityBase = exports.ArrayEntityDataProvider = void 0;
|
|
3
|
+
exports.repo = exports.SubscriptionChannel = exports.InMemoryLiveQueryStorage = exports.remult = exports.ValueConverters = exports.createValueValidator = exports.createValueValidatorWithArgs = exports.createValidatorWithArgs = exports.createValidator = exports.valueValidator = exports.Validators = exports.UrlBuilder = exports.Filter = exports.CompoundIdField = exports.Sort = exports.EventSource = exports.isBackend = exports.withRemult = exports.Remult = exports.Allow = exports.ForbiddenError = exports.ProgressListener = exports.BackendMethod = exports.Controller = exports.JsonEntityOpfsStorage = exports.JsonDataProvider = exports.dbNamesOf = exports.CustomSqlFilterBuilder = exports.SqlDatabase = exports.WebSqlDataProvider = exports.InMemoryDataProvider = exports.RestDataProvider = exports.describeEntity = exports.describeBackendMethods = exports.describeClass = exports.IdEntity = exports.Relations = exports.Fields = exports.Field = exports.getEntityRef = exports.Entity = exports.CaptionTransformer = exports.ValueListInfo = exports.getValueList = exports.ValueListFieldType = exports.getFields = exports.FieldType = exports.ControllerBase = exports.EntityBase = exports.ArrayEntityDataProvider = void 0;
|
|
4
4
|
var array_entity_data_provider_js_1 = require("./src/data-providers/array-entity-data-provider.js");
|
|
5
5
|
Object.defineProperty(exports, "ArrayEntityDataProvider", { enumerable: true, get: function () { return array_entity_data_provider_js_1.ArrayEntityDataProvider; } });
|
|
6
6
|
var RepositoryImplementation_js_1 = require("./src/remult3/RepositoryImplementation.js");
|
|
@@ -22,8 +22,10 @@ Object.defineProperty(exports, "Fields", { enumerable: true, get: function () {
|
|
|
22
22
|
Object.defineProperty(exports, "Relations", { enumerable: true, get: function () { return Fields_js_1.Relations; } });
|
|
23
23
|
var IdEntity_js_1 = require("./src/remult3/IdEntity.js");
|
|
24
24
|
Object.defineProperty(exports, "IdEntity", { enumerable: true, get: function () { return IdEntity_js_1.IdEntity; } });
|
|
25
|
-
var
|
|
26
|
-
Object.defineProperty(exports, "describeClass", { enumerable: true, get: function () { return
|
|
25
|
+
var classDescribers_js_1 = require("./src/remult3/classDescribers.js");
|
|
26
|
+
Object.defineProperty(exports, "describeClass", { enumerable: true, get: function () { return classDescribers_js_1.describeClass; } });
|
|
27
|
+
Object.defineProperty(exports, "describeBackendMethods", { enumerable: true, get: function () { return classDescribers_js_1.describeBackendMethods; } });
|
|
28
|
+
Object.defineProperty(exports, "describeEntity", { enumerable: true, get: function () { return classDescribers_js_1.describeEntity; } });
|
|
27
29
|
var rest_data_provider_js_1 = require("./src/data-providers/rest-data-provider.js"); //V
|
|
28
30
|
Object.defineProperty(exports, "RestDataProvider", { enumerable: true, get: function () { return rest_data_provider_js_1.RestDataProvider; } });
|
|
29
31
|
var in_memory_database_js_1 = require("./src/data-providers/in-memory-database.js"); //V
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "remult",
|
|
3
|
-
"version": "0.26.
|
|
3
|
+
"version": "0.26.8-next.0",
|
|
4
4
|
"description": "A CRUD framework for full-stack TypeScript",
|
|
5
5
|
"homepage": "https://remult.dev",
|
|
6
6
|
"repository": {
|
|
@@ -111,6 +111,11 @@
|
|
|
111
111
|
"import": "./esm/remult-better-sqlite3.js",
|
|
112
112
|
"types": "./remult-better-sqlite3.d.ts"
|
|
113
113
|
},
|
|
114
|
+
"./remult-sqlite3": {
|
|
115
|
+
"require": "./remult-sqlite3.js",
|
|
116
|
+
"import": "./esm/remult-sqlite3.js",
|
|
117
|
+
"types": "./remult-sqlite3.d.ts"
|
|
118
|
+
},
|
|
114
119
|
"./remult-bun-sqlite": {
|
|
115
120
|
"require": "./remult-bun-sqlite.js",
|
|
116
121
|
"import": "./esm/remult-bun-sqlite.js",
|
package/remult-knex/index.js
CHANGED
|
@@ -11,6 +11,7 @@ var sort_js_1 = require("../src/sort.js");
|
|
|
11
11
|
var valueConverters_js_1 = require("../src/valueConverters.js");
|
|
12
12
|
var repository_internals_js_1 = require("../src/remult3/repository-internals.js");
|
|
13
13
|
var remult_static_js_1 = require("../src/remult-static.js");
|
|
14
|
+
var sql_database_js_1 = require("../src/data-providers/sql-database.js");
|
|
14
15
|
var KnexDataProvider = /** @class */ (function () {
|
|
15
16
|
function KnexDataProvider(knex) {
|
|
16
17
|
var _this = this;
|
|
@@ -326,7 +327,7 @@ var KnexEntityDataProvider = /** @class */ (function () {
|
|
|
326
327
|
};
|
|
327
328
|
KnexEntityDataProvider.prototype.update = function (id, data) {
|
|
328
329
|
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
|
329
|
-
var e, f,
|
|
330
|
+
var e, f, updateObject, _a, _b, x, v, key, e_4_1, where;
|
|
330
331
|
var e_4, _c;
|
|
331
332
|
return tslib_1.__generator(this, function (_d) {
|
|
332
333
|
switch (_d.label) {
|
|
@@ -335,9 +336,6 @@ var KnexEntityDataProvider = /** @class */ (function () {
|
|
|
335
336
|
e = _d.sent();
|
|
336
337
|
f = new FilterConsumerBridgeToKnexRequest(e, this.rawSqlWrapIdentifier);
|
|
337
338
|
filter_interfaces_js_1.Filter.fromEntityFilter(this.entity, this.entity.idMetadata.getIdFilter(id)).__applyToConsumer(f);
|
|
338
|
-
resultFilter = this.entity.idMetadata.getIdFilter(id);
|
|
339
|
-
if (data.id != undefined)
|
|
340
|
-
resultFilter = this.entity.idMetadata.getIdFilter(data.id);
|
|
341
339
|
updateObject = {};
|
|
342
340
|
_d.label = 2;
|
|
343
341
|
case 2:
|
|
@@ -380,9 +378,7 @@ var KnexEntityDataProvider = /** @class */ (function () {
|
|
|
380
378
|
.where(function (b) { return where.forEach(function (w) { return w(b); }); })];
|
|
381
379
|
case 12:
|
|
382
380
|
_d.sent();
|
|
383
|
-
return [2 /*return*/, this.
|
|
384
|
-
where: filter_interfaces_js_1.Filter.fromEntityFilter(this.entity, resultFilter),
|
|
385
|
-
}).then(function (y) { return y[0]; })];
|
|
381
|
+
return [2 /*return*/, (0, sql_database_js_1.getRowAfterUpdate)(this.entity, this, data, id, 'update')];
|
|
386
382
|
}
|
|
387
383
|
});
|
|
388
384
|
});
|
|
@@ -412,7 +408,7 @@ var KnexEntityDataProvider = /** @class */ (function () {
|
|
|
412
408
|
};
|
|
413
409
|
KnexEntityDataProvider.prototype.insert = function (data) {
|
|
414
410
|
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
|
415
|
-
var e,
|
|
411
|
+
var e, insertObject, _a, _b, x, v, key, e_5_1, insert, newId_1, result, result;
|
|
416
412
|
var e_5, _c;
|
|
417
413
|
var _this = this;
|
|
418
414
|
return tslib_1.__generator(this, function (_d) {
|
|
@@ -420,7 +416,6 @@ var KnexEntityDataProvider = /** @class */ (function () {
|
|
|
420
416
|
case 0: return [4 /*yield*/, this.init()];
|
|
421
417
|
case 1:
|
|
422
418
|
e = _d.sent();
|
|
423
|
-
resultFilter = filter_interfaces_js_1.Filter.fromEntityFilter(this.entity, this.entity.idMetadata.getIdFilter(data[this.entity.idMetadata.field.key]));
|
|
424
419
|
insertObject = {};
|
|
425
420
|
_d.label = 2;
|
|
426
421
|
case 2:
|
|
@@ -469,18 +464,16 @@ var KnexEntityDataProvider = /** @class */ (function () {
|
|
|
469
464
|
result = _d.sent();
|
|
470
465
|
newId_1 = result[0].id;
|
|
471
466
|
_d.label = 14;
|
|
472
|
-
case 14:
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
return [
|
|
467
|
+
case 14: return [2 /*return*/, this.find({
|
|
468
|
+
where: new filter_interfaces_js_1.Filter(function (x) {
|
|
469
|
+
return x.isEqualTo(_this.entity.idMetadata.field, newId_1);
|
|
470
|
+
}),
|
|
471
|
+
}).then(function (y) { return y[0]; })];
|
|
477
472
|
case 15: return [4 /*yield*/, insert];
|
|
478
473
|
case 16:
|
|
479
474
|
_d.sent();
|
|
480
475
|
_d.label = 17;
|
|
481
|
-
case 17: return [2 /*return*/, this.
|
|
482
|
-
return y[0];
|
|
483
|
-
})];
|
|
476
|
+
case 17: return [2 /*return*/, (0, sql_database_js_1.getRowAfterUpdate)(this.entity, this, data, undefined, 'insert')];
|
|
484
477
|
}
|
|
485
478
|
});
|
|
486
479
|
});
|
package/remult-mongo.js
CHANGED
|
@@ -8,6 +8,7 @@ var filter_consumer_bridge_to_sql_request_js_1 = require("./src/filter/filter-co
|
|
|
8
8
|
var remult_proxy_js_1 = require("./src/remult-proxy.js");
|
|
9
9
|
var RepositoryImplementation_js_1 = require("./src/remult3/RepositoryImplementation.js");
|
|
10
10
|
var repository_internals_js_1 = require("./src/remult3/repository-internals.js");
|
|
11
|
+
var sql_database_js_1 = require("./src/data-providers/sql-database.js");
|
|
11
12
|
var MongoDataProvider = /** @class */ (function () {
|
|
12
13
|
function MongoDataProvider(db, client, options) {
|
|
13
14
|
this.db = db;
|
|
@@ -221,7 +222,7 @@ var MongoEntityDataProvider = /** @class */ (function () {
|
|
|
221
222
|
};
|
|
222
223
|
MongoEntityDataProvider.prototype.update = function (id, data) {
|
|
223
224
|
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
|
224
|
-
var _a, collection, e, f,
|
|
225
|
+
var _a, collection, e, f, newR, keys, _b, _c, f_1, r, _d, _e;
|
|
225
226
|
var e_4, _f;
|
|
226
227
|
return tslib_1.__generator(this, function (_g) {
|
|
227
228
|
switch (_g.label) {
|
|
@@ -230,9 +231,6 @@ var MongoEntityDataProvider = /** @class */ (function () {
|
|
|
230
231
|
_a = _g.sent(), collection = _a.collection, e = _a.e;
|
|
231
232
|
f = new FilterConsumerBridgeToMongo(e);
|
|
232
233
|
index_js_1.Filter.fromEntityFilter(this.entity, this.entity.idMetadata.getIdFilter(id)).__applyToConsumer(f);
|
|
233
|
-
resultFilter = this.entity.idMetadata.getIdFilter(id);
|
|
234
|
-
if (data.id != undefined)
|
|
235
|
-
resultFilter = this.entity.idMetadata.getIdFilter(data.id);
|
|
236
234
|
newR = {};
|
|
237
235
|
keys = Object.keys(data);
|
|
238
236
|
try {
|
|
@@ -260,9 +258,7 @@ var MongoEntityDataProvider = /** @class */ (function () {
|
|
|
260
258
|
{ session: this.session }])];
|
|
261
259
|
case 3:
|
|
262
260
|
r = _g.sent();
|
|
263
|
-
return [2 /*return*/, this.
|
|
264
|
-
where: index_js_1.Filter.fromEntityFilter(this.entity, resultFilter),
|
|
265
|
-
}).then(function (y) { return y[0]; })];
|
|
261
|
+
return [2 /*return*/, (0, sql_database_js_1.getRowAfterUpdate)(this.entity, this, data, id, 'update')];
|
|
266
262
|
}
|
|
267
263
|
});
|
|
268
264
|
});
|
package/remult-sqlite-core.d.ts
CHANGED
|
@@ -4,7 +4,8 @@ import type { CanBuildMigrations, MigrationBuilder, MigrationCode } from './migr
|
|
|
4
4
|
export declare class SqliteCoreDataProvider implements SqlImplementation, CanBuildMigrations {
|
|
5
5
|
createCommand: () => SqlCommand;
|
|
6
6
|
end: () => Promise<void>;
|
|
7
|
-
|
|
7
|
+
doesNotSupportReturningSyntax: boolean;
|
|
8
|
+
constructor(createCommand: () => SqlCommand, end: () => Promise<void>, doesNotSupportReturningSyntax?: boolean);
|
|
8
9
|
orderByNullsFirst?: boolean;
|
|
9
10
|
getLimitSqlSyntax(limit: number, offset: number): string;
|
|
10
11
|
afterMutation?: VoidFunction;
|
package/remult-sqlite-core.js
CHANGED
|
@@ -6,9 +6,11 @@ var sql_database_js_1 = require("./src/data-providers/sql-database.js");
|
|
|
6
6
|
var filter_consumer_bridge_to_sql_request_js_1 = require("./src/filter/filter-consumer-bridge-to-sql-request.js");
|
|
7
7
|
var RepositoryImplementation_js_1 = require("./src/remult3/RepositoryImplementation.js");
|
|
8
8
|
var SqliteCoreDataProvider = /** @class */ (function () {
|
|
9
|
-
function SqliteCoreDataProvider(createCommand, end) {
|
|
9
|
+
function SqliteCoreDataProvider(createCommand, end, doesNotSupportReturningSyntax) {
|
|
10
|
+
if (doesNotSupportReturningSyntax === void 0) { doesNotSupportReturningSyntax = false; }
|
|
10
11
|
this.createCommand = createCommand;
|
|
11
12
|
this.end = end;
|
|
13
|
+
this.doesNotSupportReturningSyntax = doesNotSupportReturningSyntax;
|
|
12
14
|
}
|
|
13
15
|
SqliteCoreDataProvider.prototype.getLimitSqlSyntax = function (limit, offset) {
|
|
14
16
|
return ' limit ' + limit + ' offset ' + offset;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { SqlResult } from '../core/index.js';
|
|
2
|
+
import { SqliteCoreDataProvider } from '../core/remult-sqlite-core.js';
|
|
3
|
+
import { Database } from 'sqlite3';
|
|
4
|
+
export declare class Sqlite3DataProvider extends SqliteCoreDataProvider {
|
|
5
|
+
constructor(db: Database);
|
|
6
|
+
}
|
|
7
|
+
export declare class Sqlite3SqlResult implements SqlResult {
|
|
8
|
+
private result;
|
|
9
|
+
constructor(result: any[]);
|
|
10
|
+
rows: any[];
|
|
11
|
+
getColumnKeyInResultForIndexInSelect(index: number): string;
|
|
12
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Sqlite3SqlResult = exports.Sqlite3DataProvider = void 0;
|
|
4
|
+
var tslib_1 = require("tslib");
|
|
5
|
+
var remult_sqlite_core_js_1 = require("../core/remult-sqlite-core.js");
|
|
6
|
+
var Sqlite3DataProvider = /** @class */ (function (_super) {
|
|
7
|
+
tslib_1.__extends(Sqlite3DataProvider, _super);
|
|
8
|
+
function Sqlite3DataProvider(db) {
|
|
9
|
+
var _this = _super.call(this, function () { return new Sqlite3Command(db); }, function () { return tslib_1.__awaiter(_this, void 0, void 0, function () {
|
|
10
|
+
return tslib_1.__generator(this, function (_a) {
|
|
11
|
+
db.close();
|
|
12
|
+
return [2 /*return*/];
|
|
13
|
+
});
|
|
14
|
+
}); }, true) || this;
|
|
15
|
+
return _this;
|
|
16
|
+
}
|
|
17
|
+
return Sqlite3DataProvider;
|
|
18
|
+
}(remult_sqlite_core_js_1.SqliteCoreDataProvider));
|
|
19
|
+
exports.Sqlite3DataProvider = Sqlite3DataProvider;
|
|
20
|
+
var Sqlite3Command = /** @class */ (function () {
|
|
21
|
+
function Sqlite3Command(db) {
|
|
22
|
+
this.db = db;
|
|
23
|
+
this.values = {};
|
|
24
|
+
this.i = 1;
|
|
25
|
+
}
|
|
26
|
+
Sqlite3Command.prototype.execute = function (sql) {
|
|
27
|
+
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
|
28
|
+
var _this = this;
|
|
29
|
+
return tslib_1.__generator(this, function (_a) {
|
|
30
|
+
return [2 /*return*/, new Promise(function (resolve, error) {
|
|
31
|
+
if (sql.startsWith('insert into')) {
|
|
32
|
+
_this.db.run(sql, _this.values, function (err, rows) {
|
|
33
|
+
if (err)
|
|
34
|
+
error(err);
|
|
35
|
+
else
|
|
36
|
+
resolve(new Sqlite3SqlResult([this.lastID]));
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
else
|
|
40
|
+
_this.db.all(sql, _this.values, function (err, rows) {
|
|
41
|
+
if (err)
|
|
42
|
+
error(err);
|
|
43
|
+
else
|
|
44
|
+
resolve(new Sqlite3SqlResult(rows));
|
|
45
|
+
});
|
|
46
|
+
})];
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
};
|
|
50
|
+
Sqlite3Command.prototype.addParameterAndReturnSqlToken = function (val) {
|
|
51
|
+
return this.param(val);
|
|
52
|
+
};
|
|
53
|
+
Sqlite3Command.prototype.param = function (val) {
|
|
54
|
+
if (val instanceof Date)
|
|
55
|
+
val = val.valueOf();
|
|
56
|
+
if (typeof val === 'boolean')
|
|
57
|
+
val = val ? 1 : 0;
|
|
58
|
+
var key = ':' + this.i++;
|
|
59
|
+
this.values[key.substring(1)] = val;
|
|
60
|
+
return key;
|
|
61
|
+
};
|
|
62
|
+
return Sqlite3Command;
|
|
63
|
+
}());
|
|
64
|
+
var Sqlite3SqlResult = /** @class */ (function () {
|
|
65
|
+
function Sqlite3SqlResult(result) {
|
|
66
|
+
this.result = result;
|
|
67
|
+
this.rows = result;
|
|
68
|
+
}
|
|
69
|
+
Sqlite3SqlResult.prototype.getColumnKeyInResultForIndexInSelect = function (index) {
|
|
70
|
+
return Object.keys(this.result[0])[index];
|
|
71
|
+
};
|
|
72
|
+
return Sqlite3SqlResult;
|
|
73
|
+
}());
|
|
74
|
+
exports.Sqlite3SqlResult = Sqlite3SqlResult;
|
package/server/expressBridge.js
CHANGED
|
@@ -499,31 +499,33 @@ var RemultServerImplementation = /** @class */ (function () {
|
|
|
499
499
|
//runs with remult but without init request
|
|
500
500
|
RemultServerImplementation.prototype.runWithRemult = function (what, options) {
|
|
501
501
|
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
|
502
|
+
var dataProvider;
|
|
502
503
|
var _this = this;
|
|
503
504
|
return tslib_1.__generator(this, function (_a) {
|
|
504
505
|
switch (_a.label) {
|
|
505
|
-
case 0:
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
506
|
+
case 0:
|
|
507
|
+
if (!!(options === null || options === void 0 ? void 0 : options.skipDataProvider)) return [3 /*break*/, 2];
|
|
508
|
+
return [4 /*yield*/, this.dataProvider];
|
|
509
|
+
case 1:
|
|
510
|
+
dataProvider = _a.sent();
|
|
511
|
+
_a.label = 2;
|
|
512
|
+
case 2: return [4 /*yield*/, (0, context_js_1.withRemult)(function (remult) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
|
|
513
|
+
var x;
|
|
514
|
+
return tslib_1.__generator(this, function (_a) {
|
|
515
|
+
switch (_a.label) {
|
|
509
516
|
case 0:
|
|
510
517
|
x = remult;
|
|
511
518
|
x.liveQueryPublisher = new SubscriptionServer_js_1.LiveQueryPublisher(function () { return remult.subscriptionServer; }, function () { return remult.liveQueryStorage; }, this.runWithSerializedJsonContextData);
|
|
512
|
-
if (
|
|
513
|
-
|
|
514
|
-
return [4 /*yield*/, this.dataProvider];
|
|
515
|
-
case 1:
|
|
516
|
-
_a.dataProvider = _b.sent();
|
|
517
|
-
_b.label = 2;
|
|
518
|
-
case 2:
|
|
519
|
+
if (!(options === null || options === void 0 ? void 0 : options.skipDataProvider))
|
|
520
|
+
x.dataProvider = dataProvider;
|
|
519
521
|
x.subscriptionServer = this.subscriptionServer;
|
|
520
522
|
x.liveQueryStorage = this.liveQueryStorage;
|
|
521
523
|
return [4 /*yield*/, what(x)];
|
|
522
|
-
case
|
|
524
|
+
case 1: return [2 /*return*/, _a.sent()];
|
|
523
525
|
}
|
|
524
526
|
});
|
|
525
527
|
}); })];
|
|
526
|
-
case
|
|
528
|
+
case 3: return [2 /*return*/, _a.sent()];
|
|
527
529
|
}
|
|
528
530
|
});
|
|
529
531
|
});
|
|
@@ -11,11 +11,32 @@ export interface FieldOptions<entityType = any, valueType = any> {
|
|
|
11
11
|
allowNull?: boolean;
|
|
12
12
|
/** If a value is required */
|
|
13
13
|
required?: boolean;
|
|
14
|
-
/**
|
|
15
|
-
*
|
|
14
|
+
/**
|
|
15
|
+
* Specifies whether this field should be included in the API. This can be configured
|
|
16
|
+
* based on access control levels.
|
|
17
|
+
* @example
|
|
18
|
+
* // Do not include in the API
|
|
19
|
+
* @Fields.string({ includeInApi: false })
|
|
20
|
+
* password = '';
|
|
21
|
+
* // Include in the API for 'admin' only
|
|
22
|
+
* @Fields.number({ includeInApi: 'admin' })
|
|
23
|
+
* salary = 0;
|
|
24
|
+
* @see [allowed](https://remult.dev/docs/allowed.html)
|
|
25
|
+
* @see [Access Control](https://remult.dev/docs/access-control)
|
|
26
|
+
* @type {AllowedForInstance<entityType>}
|
|
27
|
+
*/
|
|
16
28
|
includeInApi?: AllowedForInstance<entityType>;
|
|
17
|
-
/**
|
|
18
|
-
*
|
|
29
|
+
/**
|
|
30
|
+
* Determines whether this field can be updated via the API. This setting can also
|
|
31
|
+
* be controlled based on user roles or other access control checks.
|
|
32
|
+
* @example
|
|
33
|
+
* // Prevent API from updating this field
|
|
34
|
+
* @Fields.string({ allowApiUpdate: false })
|
|
35
|
+
* createdBy = remult.user?.id;
|
|
36
|
+
* @see [allowed](https://remult.dev/docs/allowed.html)
|
|
37
|
+
* @see [Access Control](https://remult.dev/docs/access-control)
|
|
38
|
+
* @type {AllowedForInstance<entityType>}
|
|
39
|
+
*/
|
|
19
40
|
allowApiUpdate?: AllowedForInstance<entityType>;
|
|
20
41
|
/** An arrow function that'll be used to perform validations on it
|
|
21
42
|
* @example
|
|
@@ -109,6 +130,7 @@ export interface FieldMetadata<valueType = any, entityType = any> {
|
|
|
109
130
|
/** A human readable caption for the field. Can be used to achieve a consistent caption for a field throughout the app
|
|
110
131
|
* @example
|
|
111
132
|
* <input placeholder={taskRepo.metadata.fields.title.caption}/>
|
|
133
|
+
* @see {@link FieldOptions#caption} for configuration details
|
|
112
134
|
*/
|
|
113
135
|
readonly caption: string;
|
|
114
136
|
/** The name of the column in the database that holds the data for this field. If no name is set, the key will be used instead.
|
|
@@ -116,6 +138,7 @@ export interface FieldMetadata<valueType = any, entityType = any> {
|
|
|
116
138
|
*
|
|
117
139
|
* @Fields.string({ dbName: 'userName'})
|
|
118
140
|
* userName=''
|
|
141
|
+
* @see {@link FieldOptions#dbName} for configuration details
|
|
119
142
|
*/
|
|
120
143
|
dbName: string;
|
|
121
144
|
/** The field's value type (number,string etc...) */
|
|
@@ -124,7 +147,10 @@ export interface FieldMetadata<valueType = any, entityType = any> {
|
|
|
124
147
|
readonly options: FieldOptions;
|
|
125
148
|
/** The `inputType` relevant for this field, determined by the options sent to it's decorator and the valueConverter in these options */
|
|
126
149
|
readonly inputType: string;
|
|
127
|
-
/** if null is allowed for this field
|
|
150
|
+
/** if null is allowed for this field
|
|
151
|
+
* @see {@link FieldOptions#allowNull} for configuration details
|
|
152
|
+
*
|
|
153
|
+
*/
|
|
128
154
|
readonly allowNull: boolean;
|
|
129
155
|
/** The class that contains this field
|
|
130
156
|
* @example
|
|
@@ -137,16 +163,45 @@ export interface FieldMetadata<valueType = any, entityType = any> {
|
|
|
137
163
|
getDbName(): Promise<string>;
|
|
138
164
|
/** Indicates if this field is based on a server express */
|
|
139
165
|
readonly isServerExpression: boolean;
|
|
140
|
-
/** indicates that this field should only be included in select statement, and excluded from update or insert. useful for db generated ids etc...
|
|
166
|
+
/** indicates that this field should only be included in select statement, and excluded from update or insert. useful for db generated ids etc...
|
|
167
|
+
* @see {@link FieldOptions#dbReadOnly} for configuration details
|
|
168
|
+
*/
|
|
141
169
|
readonly dbReadOnly: boolean;
|
|
142
170
|
/** the Value converter for this field */
|
|
143
171
|
readonly valueConverter: Required<ValueConverter<valueType>>;
|
|
144
172
|
/** Get the display value for a specific item
|
|
173
|
+
* @see {@link FieldOptions#displayValue} for configuration details
|
|
145
174
|
* @example
|
|
146
175
|
* repo.fields.createDate.displayValue(task) //will display the date as defined in the `displayValue` option defined for it.
|
|
147
176
|
*/
|
|
148
177
|
displayValue(item: Partial<entityType>): string;
|
|
178
|
+
/**
|
|
179
|
+
* Determines if the current user is allowed to update a specific entity instance.
|
|
180
|
+
|
|
181
|
+
* @example
|
|
182
|
+
* const taskRepo = remult.repo(Task);
|
|
183
|
+
* // Check if the current user is allowed to update a specific task
|
|
184
|
+
* if (taskRepo.metadata.apiUpdateAllowed(task)){
|
|
185
|
+
* // Allow user to edit the entity
|
|
186
|
+
* }
|
|
187
|
+
* @see {@link FieldOptions#allowApiUpdate} for configuration details
|
|
188
|
+
* @param {Partial<entityType>} item - Partial entity instance to check permissions against.
|
|
189
|
+
* @returns {boolean} True if the update is allowed.
|
|
190
|
+
*/
|
|
149
191
|
apiUpdateAllowed(item?: Partial<entityType>): boolean;
|
|
192
|
+
/**
|
|
193
|
+
* Determines if a specific entity field should be included in the API based on the current user's permissions.
|
|
194
|
+
* This method checks visibility permissions for a field within a partial entity instance.
|
|
195
|
+
* @example
|
|
196
|
+
* const employeeRepo = remult.repo(Employee);
|
|
197
|
+
* // Determine if the 'salary' field of an employee should be visible in the API for the current user
|
|
198
|
+
* if (employeeRepo.fields.salary.includedInApi({ id: 123, name: 'John Doe' })) {
|
|
199
|
+
* // The salary field is included in the API
|
|
200
|
+
* }
|
|
201
|
+
* @see {@link FieldOptions#includeInApi} for configuration details
|
|
202
|
+
* @param {Partial<entityType>} item - The partial entity instance used to evaluate field visibility.
|
|
203
|
+
* @returns {boolean} True if the field is included in the API.
|
|
204
|
+
*/
|
|
150
205
|
includedInApi(item?: Partial<entityType>): boolean;
|
|
151
206
|
/** Adapts the value for usage with html input
|
|
152
207
|
* @example
|
|
@@ -154,6 +209,7 @@ export interface FieldMetadata<valueType = any, entityType = any> {
|
|
|
154
209
|
* birthDate = new Date(1976,5,16)
|
|
155
210
|
* //...
|
|
156
211
|
* input.value = repo.fields.birthDate.toInput(person) // will return '1976-06-16'
|
|
212
|
+
* @see {@link ValueConverter#toInput} for configuration details
|
|
157
213
|
*/
|
|
158
214
|
toInput(value: valueType, inputType?: string): string;
|
|
159
215
|
/** Adapts the value for usage with html input
|
|
@@ -162,6 +218,7 @@ export interface FieldMetadata<valueType = any, entityType = any> {
|
|
|
162
218
|
* birthDate = new Date(1976,5,16)
|
|
163
219
|
* //...
|
|
164
220
|
* person.birthDate = repo.fields.birthDate.fromInput(personFormState) // will return Date
|
|
221
|
+
* @see {@link ValueConverter#fromInput} for configuration details
|
|
165
222
|
*/
|
|
166
223
|
fromInput(inputValue: string, inputType?: string): valueType;
|
|
167
224
|
}
|
|
@@ -44,3 +44,4 @@ export declare class SqlDatabase implements DataProvider, HasWrapIdentifier, Can
|
|
|
44
44
|
private createdEntities;
|
|
45
45
|
end: () => Promise<void>;
|
|
46
46
|
}
|
|
47
|
+
export declare function getRowAfterUpdate<entityType>(meta: EntityMetadata<entityType>, dataProvider: EntityDataProvider, data: any, id: any, operation: string): any;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SqlDatabase = void 0;
|
|
3
|
+
exports.getRowAfterUpdate = exports.SqlDatabase = void 0;
|
|
4
4
|
var tslib_1 = require("tslib");
|
|
5
5
|
var filter_consumer_bridge_to_sql_request_js_1 = require("../filter/filter-consumer-bridge-to-sql-request.js");
|
|
6
6
|
var filter_interfaces_js_1 = require("../filter/filter-interfaces.js");
|
|
@@ -475,7 +475,7 @@ var ActualSQLServerDataProvider = /** @class */ (function () {
|
|
|
475
475
|
};
|
|
476
476
|
ActualSQLServerDataProvider.prototype.update = function (id, data) {
|
|
477
477
|
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
|
478
|
-
var e, r,
|
|
478
|
+
var e, r, statement, added, _a, _b, x, v, idFilter, f, _c, _d, colKeys, select;
|
|
479
479
|
var e_5, _e;
|
|
480
480
|
var _this = this;
|
|
481
481
|
return tslib_1.__generator(this, function (_f) {
|
|
@@ -484,8 +484,6 @@ var ActualSQLServerDataProvider = /** @class */ (function () {
|
|
|
484
484
|
case 1:
|
|
485
485
|
e = _f.sent();
|
|
486
486
|
r = this.sql.createCommand();
|
|
487
|
-
f = new filter_consumer_bridge_to_sql_request_js_1.FilterConsumerBridgeToSqlRequest(r, e);
|
|
488
|
-
filter_interfaces_js_1.Filter.fromEntityFilter(this.entity, this.entity.idMetadata.getIdFilter(id)).__applyToConsumer(f);
|
|
489
487
|
statement = 'update ' + e.$entityName + ' set ';
|
|
490
488
|
added = false;
|
|
491
489
|
try {
|
|
@@ -512,15 +510,22 @@ var ActualSQLServerDataProvider = /** @class */ (function () {
|
|
|
512
510
|
}
|
|
513
511
|
finally { if (e_5) throw e_5.error; }
|
|
514
512
|
}
|
|
513
|
+
idFilter = this.entity.idMetadata.getIdFilter(id);
|
|
514
|
+
f = new filter_consumer_bridge_to_sql_request_js_1.FilterConsumerBridgeToSqlRequest(r, e);
|
|
515
|
+
filter_interfaces_js_1.Filter.fromEntityFilter(this.entity, idFilter).__applyToConsumer(f);
|
|
515
516
|
_c = statement;
|
|
516
517
|
return [4 /*yield*/, f.resolveWhere()];
|
|
517
518
|
case 2:
|
|
518
519
|
statement = _c + _f.sent();
|
|
519
520
|
_d = this.buildSelect(e), colKeys = _d.colKeys, select = _d.select;
|
|
520
|
-
|
|
521
|
+
if (!this.sql._getSourceSql().doesNotSupportReturningSyntax)
|
|
522
|
+
statement += ' returning ' + select;
|
|
521
523
|
return [2 /*return*/, r.execute(statement).then(function (sqlResult) {
|
|
522
524
|
var _a, _b;
|
|
523
525
|
(_b = (_a = _this.sql._getSourceSql()).afterMutation) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
526
|
+
if (_this.sql._getSourceSql().doesNotSupportReturningSyntax) {
|
|
527
|
+
return getRowAfterUpdate(_this.entity, _this, data, id, 'update');
|
|
528
|
+
}
|
|
524
529
|
if (sqlResult.rows.length != 1)
|
|
525
530
|
throw new Error('Failed to update row with id ' +
|
|
526
531
|
id +
|
|
@@ -600,10 +605,27 @@ var ActualSQLServerDataProvider = /** @class */ (function () {
|
|
|
600
605
|
}
|
|
601
606
|
statement = "insert into ".concat(e.$entityName, " (").concat(cols, ") values (").concat(vals, ")");
|
|
602
607
|
_c = this.buildSelect(e), colKeys = _c.colKeys, select = _c.select;
|
|
603
|
-
|
|
608
|
+
if (!this.sql._getSourceSql().doesNotSupportReturningSyntax)
|
|
609
|
+
statement += ' returning ' + select;
|
|
604
610
|
return [4 /*yield*/, r.execute(statement).then(function (sql) {
|
|
605
611
|
var _a, _b;
|
|
606
612
|
(_b = (_a = _this.sql._getSourceSql()).afterMutation) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
613
|
+
if (_this.sql._getSourceSql().doesNotSupportReturningSyntax) {
|
|
614
|
+
if ((0, RepositoryImplementation_js_1.isAutoIncrement)(_this.entity.idMetadata.field)) {
|
|
615
|
+
var id_1 = sql.rows[0];
|
|
616
|
+
if (typeof id_1 !== 'number')
|
|
617
|
+
throw new Error('Auto increment, for a database that is does not support returning syntax, should return an array with the single last added id. Instead it returned: ' +
|
|
618
|
+
JSON.stringify(id_1));
|
|
619
|
+
return _this.find({
|
|
620
|
+
where: new filter_interfaces_js_1.Filter(function (x) {
|
|
621
|
+
return x.isEqualTo(_this.entity.idMetadata.field, id_1);
|
|
622
|
+
}),
|
|
623
|
+
}).then(function (r) { return r[0]; });
|
|
624
|
+
}
|
|
625
|
+
else {
|
|
626
|
+
return getRowAfterUpdate(_this.entity, _this, data, undefined, 'insert');
|
|
627
|
+
}
|
|
628
|
+
}
|
|
607
629
|
return _this.buildResultRow(colKeys, sql.rows[0], sql);
|
|
608
630
|
})];
|
|
609
631
|
case 2: return [2 /*return*/, _e.sent()];
|
|
@@ -696,3 +718,32 @@ function bulkInsert(array, db) {
|
|
|
696
718
|
});
|
|
697
719
|
});
|
|
698
720
|
}
|
|
721
|
+
function getRowAfterUpdate(meta, dataProvider, data, id, operation) {
|
|
722
|
+
var idFilter = id !== undefined ? meta.idMetadata.getIdFilter(id) : {};
|
|
723
|
+
return dataProvider
|
|
724
|
+
.find({
|
|
725
|
+
where: new filter_interfaces_js_1.Filter(function (x) {
|
|
726
|
+
var e_7, _a;
|
|
727
|
+
var _b;
|
|
728
|
+
try {
|
|
729
|
+
for (var _c = tslib_1.__values(meta.idMetadata.fields), _d = _c.next(); !_d.done; _d = _c.next()) {
|
|
730
|
+
var field = _d.value;
|
|
731
|
+
x.isEqualTo(field, (_b = data[field.key]) !== null && _b !== void 0 ? _b : idFilter[field.key]);
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
catch (e_7_1) { e_7 = { error: e_7_1 }; }
|
|
735
|
+
finally {
|
|
736
|
+
try {
|
|
737
|
+
if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
|
|
738
|
+
}
|
|
739
|
+
finally { if (e_7) throw e_7.error; }
|
|
740
|
+
}
|
|
741
|
+
}),
|
|
742
|
+
})
|
|
743
|
+
.then(function (r) {
|
|
744
|
+
if (r.length != 1)
|
|
745
|
+
throw new Error("Failed to ".concat(operation, " row - result contained ").concat(r.length, " rows"));
|
|
746
|
+
return r[0];
|
|
747
|
+
});
|
|
748
|
+
}
|
|
749
|
+
exports.getRowAfterUpdate = getRowAfterUpdate;
|
package/src/entity.d.ts
CHANGED
|
@@ -15,13 +15,19 @@ export interface EntityOptions<entityType = any> {
|
|
|
15
15
|
allowApiRead?: Allowed;
|
|
16
16
|
/**
|
|
17
17
|
* Determines if this entity can be updated through the api.
|
|
18
|
-
* @see [allowed](http://remult.dev/docs/allowed.html)
|
|
18
|
+
* @see [allowed](http://remult.dev/docs/allowed.html)
|
|
19
|
+
* @see [Access Control](https://remult.dev/docs/access-control)
|
|
20
|
+
* */
|
|
19
21
|
allowApiUpdate?: AllowedForInstance<entityType>;
|
|
20
22
|
/** Determines if entries for this entity can be deleted through the api.
|
|
21
|
-
* @see [allowed](http://remult.dev/docs/allowed.html)
|
|
23
|
+
* @see [allowed](http://remult.dev/docs/allowed.html)
|
|
24
|
+
* @see [Access Control](https://remult.dev/docs/access-control)
|
|
25
|
+
* */
|
|
22
26
|
allowApiDelete?: AllowedForInstance<entityType>;
|
|
23
27
|
/** Determines if new entries for this entity can be posted through the api.
|
|
24
|
-
* @see [allowed](http://remult.dev/docs/allowed.html)
|
|
28
|
+
* @see [allowed](http://remult.dev/docs/allowed.html)
|
|
29
|
+
* @see [Access Control](https://remult.dev/docs/access-control)
|
|
30
|
+
* */
|
|
25
31
|
allowApiInsert?: AllowedForInstance<entityType>;
|
|
26
32
|
/** sets the `allowApiUpdate`, `allowApiDelete` and `allowApiInsert` properties in a single set */
|
|
27
33
|
allowApiCrud?: Allowed;
|
|
@@ -190,7 +196,7 @@ export interface PreprocessFilterEvent<entityType> {
|
|
|
190
196
|
* @param filter Optional filter to analyze. If not provided, the current filter being preprocessed is used.
|
|
191
197
|
* @returns A promise that resolves to a FilterPreciseValues object containing the precise values for each property.
|
|
192
198
|
|
|
193
|
-
* {@Link FilterPreciseValues }
|
|
199
|
+
* @see {@Link FilterPreciseValues }
|
|
194
200
|
*/
|
|
195
201
|
getFilterPreciseValues(filter?: EntityFilter<entityType>): Promise<FilterPreciseValues<entityType>>;
|
|
196
202
|
}
|
|
@@ -396,7 +396,7 @@ var filterHelper = /** @class */ (function () {
|
|
|
396
396
|
filterHelper.prototype.processVal = function (val) {
|
|
397
397
|
var ei = (0, getEntityRef_js_1.getEntitySettings)(this.metadata.valueType, false);
|
|
398
398
|
if (ei) {
|
|
399
|
-
if (
|
|
399
|
+
if (val === undefined || val === null) {
|
|
400
400
|
if (val === null && !this.metadata.allowNull) {
|
|
401
401
|
var rel = (0, relationInfoMember_js_1.getRelationFieldInfo)(this.metadata);
|
|
402
402
|
if ((rel === null || rel === void 0 ? void 0 : rel.type) === 'reference')
|
|
@@ -2185,6 +2185,7 @@ var rowHelperImplementation = /** @class */ (function (_super) {
|
|
|
2185
2185
|
case 20: return [4 /*yield*/, this.loadDataFrom(updatedRow)];
|
|
2186
2186
|
case 21:
|
|
2187
2187
|
_p.sent();
|
|
2188
|
+
e.id = this.getId();
|
|
2188
2189
|
if (!!this.repository._dataProvider.isProxy) return [3 /*break*/, 31];
|
|
2189
2190
|
if (!this.info.entityInfo.saved) return [3 /*break*/, 23];
|
|
2190
2191
|
return [4 /*yield*/, this.info.entityInfo.saved(this.instance, e)];
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ClassType } from '../../classType.js';
|
|
2
|
+
import { EntityOptions } from '../entity.js';
|
|
3
|
+
import { BackendMethodOptions } from '../server-action.js';
|
|
4
|
+
type Descriptor<T = any> = (a: T, b: string, c?: any) => void;
|
|
5
|
+
type FieldsDescriptor<T> = T extends new (...args: any[]) => infer R ? {
|
|
6
|
+
[K in keyof R]?: Descriptor;
|
|
7
|
+
} : never;
|
|
8
|
+
type StaticMemberDescriptors<T> = {
|
|
9
|
+
[K in keyof T]?: Descriptor;
|
|
10
|
+
};
|
|
11
|
+
export declare function describeClass<classType>(classType: classType, classDescriber: ((x: any, context?: any) => any) | undefined, members?: FieldsDescriptor<classType> | undefined, staticMembers?: StaticMemberDescriptors<classType>): void;
|
|
12
|
+
export declare function describeBackendMethods<T>(classType: T, backendMethods: {
|
|
13
|
+
[K in keyof T]?: BackendMethodOptions<unknown>;
|
|
14
|
+
}): void;
|
|
15
|
+
export declare function describeEntity<entityType extends ClassType<any>>(classType: entityType, key: string, fields: FieldsDescriptor<entityType>, options?: EntityOptions<InstanceType<entityType>>): void;
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.describeEntity = exports.describeBackendMethods = exports.describeClass = void 0;
|
|
4
|
+
var server_action_js_1 = require("../server-action.js");
|
|
5
|
+
var entity_js_1 = require("./entity.js");
|
|
6
|
+
function describeClass(classType, classDescriber, members, staticMembers) {
|
|
7
|
+
if (classDescriber)
|
|
8
|
+
classDescriber(classType);
|
|
9
|
+
for (var fieldKey in members) {
|
|
10
|
+
if (Object.prototype.hasOwnProperty.call(members, fieldKey)) {
|
|
11
|
+
var element = members[fieldKey];
|
|
12
|
+
var prop = Object.getOwnPropertyDescriptor(classType.prototype, fieldKey);
|
|
13
|
+
element(classType.prototype, fieldKey, prop);
|
|
14
|
+
if (prop)
|
|
15
|
+
Object.defineProperty(classType.prototype, fieldKey, prop);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
for (var staticFieldKey in staticMembers) {
|
|
19
|
+
var staticElement = staticMembers[staticFieldKey];
|
|
20
|
+
var prop = Object.getOwnPropertyDescriptor(classType, staticFieldKey);
|
|
21
|
+
staticElement(classType, staticFieldKey, prop);
|
|
22
|
+
if (prop)
|
|
23
|
+
Object.defineProperty(classType, staticFieldKey, prop);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
exports.describeClass = describeClass;
|
|
27
|
+
function describeBackendMethods(classType, backendMethods) {
|
|
28
|
+
var result = {};
|
|
29
|
+
for (var key in backendMethods) {
|
|
30
|
+
if (Object.prototype.hasOwnProperty.call(backendMethods, key)) {
|
|
31
|
+
var options = backendMethods[key];
|
|
32
|
+
result[key] = (0, server_action_js_1.BackendMethod)(options);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
describeClass(classType, undefined, undefined, result);
|
|
36
|
+
}
|
|
37
|
+
exports.describeBackendMethods = describeBackendMethods;
|
|
38
|
+
function describeEntity(classType, key, fields, options) {
|
|
39
|
+
describeClass(classType, (0, entity_js_1.Entity)(key, options), fields);
|
|
40
|
+
}
|
|
41
|
+
exports.describeEntity = describeEntity;
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
import type { ClassType } from '../../classType.js';
|
|
2
2
|
import type { EntityOptionsFactory } from './RepositoryImplementation.js';
|
|
3
3
|
import type { EntityRef } from './remult3.js';
|
|
4
|
+
/**
|
|
5
|
+
* Retrieves the EntityRef object associated with the specified entity instance.
|
|
6
|
+
* The EntityRef provides methods for performing operations on the entity instance.
|
|
7
|
+
* @param {entityType} entity - The entity instance.
|
|
8
|
+
* @param {boolean} [throwException=true] - Indicates whether to throw an exception if the EntityRef object cannot be retrieved.
|
|
9
|
+
* @returns {EntityRef<entityType>} The EntityRef object associated with the specified entity instance.
|
|
10
|
+
* @throws {Error} If throwException is true and the EntityRef object cannot be retrieved.
|
|
11
|
+
* @see [Active Record & EntityBase](https://remult.dev/docs/active-record)
|
|
12
|
+
*/
|
|
4
13
|
export declare function getEntityRef<entityType>(entity: entityType, throwException?: boolean): EntityRef<entityType>;
|
|
5
14
|
export declare const entityMember: unique symbol;
|
|
6
15
|
export declare const entityInfo: unique symbol;
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getEntityKey = exports.getEntitySettings = exports.entityInfo_key = exports.entityInfo = exports.entityMember = exports.getEntityRef = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Retrieves the EntityRef object associated with the specified entity instance.
|
|
6
|
+
* The EntityRef provides methods for performing operations on the entity instance.
|
|
7
|
+
* @param {entityType} entity - The entity instance.
|
|
8
|
+
* @param {boolean} [throwException=true] - Indicates whether to throw an exception if the EntityRef object cannot be retrieved.
|
|
9
|
+
* @returns {EntityRef<entityType>} The EntityRef object associated with the specified entity instance.
|
|
10
|
+
* @throws {Error} If throwException is true and the EntityRef object cannot be retrieved.
|
|
11
|
+
* @see [Active Record & EntityBase](https://remult.dev/docs/active-record)
|
|
12
|
+
*/
|
|
4
13
|
function getEntityRef(entity, throwException) {
|
|
5
14
|
var _a;
|
|
6
15
|
if (throwException === void 0) { throwException = true; }
|
package/src/remult3/remult3.d.ts
CHANGED
|
@@ -188,17 +188,22 @@ export interface EntityMetadata<entityType = any> {
|
|
|
188
188
|
/** A human readable caption for the entity. Can be used to achieve a consistent caption for a field throughout the app
|
|
189
189
|
* @example
|
|
190
190
|
* <h1>Create a new item in {taskRepo.metadata.caption}</h1>
|
|
191
|
+
* @see {@link EntityOptions.caption}
|
|
191
192
|
*/
|
|
192
193
|
readonly caption: string;
|
|
193
194
|
/** The name of the table in the database that holds the data for this entity.
|
|
194
195
|
* If no name is set in the entity options, the `key` will be used instead.
|
|
196
|
+
* @see {@link EntityOptions.dbName}
|
|
195
197
|
*/
|
|
196
198
|
readonly dbName: string;
|
|
197
|
-
/** The options send to the `Entity`'s decorator
|
|
199
|
+
/** The options send to the `Entity`'s decorator
|
|
200
|
+
* @see {@link EntityOptions}
|
|
201
|
+
*/
|
|
198
202
|
readonly options: EntityOptions;
|
|
199
203
|
/** The class type of the entity */
|
|
200
204
|
readonly entityType: ClassType<entityType>;
|
|
201
205
|
/** true if the current user is allowed to update an entity instance
|
|
206
|
+
* @see {@link EntityOptions.allowApiUpdate
|
|
202
207
|
* @example
|
|
203
208
|
* const taskRepo = remult.repo(Task);
|
|
204
209
|
* if (taskRepo.metadata.apiUpdateAllowed(task)){
|
|
@@ -207,6 +212,7 @@ export interface EntityMetadata<entityType = any> {
|
|
|
207
212
|
*/
|
|
208
213
|
apiUpdateAllowed(item?: entityType): boolean;
|
|
209
214
|
/** true if the current user is allowed to read from entity
|
|
215
|
+
* @see {@link EntityOptions.allowApiRead}
|
|
210
216
|
* @example
|
|
211
217
|
* const taskRepo = remult.repo(Task);
|
|
212
218
|
* if (taskRepo.metadata.apiReadAllowed){
|
|
@@ -215,6 +221,7 @@ export interface EntityMetadata<entityType = any> {
|
|
|
215
221
|
*/
|
|
216
222
|
readonly apiReadAllowed: boolean;
|
|
217
223
|
/** true if the current user is allowed to delete an entity instance
|
|
224
|
+
* * @see {@link EntityOptions.allowApiDelete}
|
|
218
225
|
* @example
|
|
219
226
|
* const taskRepo = remult.repo(Task);
|
|
220
227
|
* if (taskRepo.metadata.apiDeleteAllowed(task)){
|
|
@@ -223,6 +230,7 @@ export interface EntityMetadata<entityType = any> {
|
|
|
223
230
|
*/
|
|
224
231
|
apiDeleteAllowed(item?: entityType): boolean;
|
|
225
232
|
/** true if the current user is allowed to create an entity instance
|
|
233
|
+
* @see {@link EntityOptions.allowApiInsert}
|
|
226
234
|
* @example
|
|
227
235
|
* const taskRepo = remult.repo(Task);
|
|
228
236
|
* if (taskRepo.metadata.apiInsertAllowed(task)){
|
|
@@ -233,7 +241,10 @@ export interface EntityMetadata<entityType = any> {
|
|
|
233
241
|
/**
|
|
234
242
|
* @deprecated Returns the dbName - based on it's `dbName` option and it's `sqlExpression` option */
|
|
235
243
|
getDbName(): Promise<string>;
|
|
236
|
-
/** Metadata for the Entity's id
|
|
244
|
+
/** Metadata for the Entity's id
|
|
245
|
+
* @see {@link EntityOptions.id} for configuration
|
|
246
|
+
*
|
|
247
|
+
*/
|
|
237
248
|
readonly idMetadata: IdMetadata<entityType>;
|
|
238
249
|
}
|
|
239
250
|
export declare type MembersOnly<T> = {
|
package/src/remult3/remult3.js
CHANGED
|
@@ -1,8 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
//p1 - remove controller and instance backend methods from the regular backend method article
|
|
4
|
+
//p1 - describe entity
|
|
5
|
+
//p1 - fix includeInApi documentation - figure out why we can't see the see?
|
|
3
6
|
//y2 - soft-delete-discussion https://discord.com/channels/975754286384418847/1230386433093533698/1230386433093533698
|
|
4
|
-
//y1 - In the esm version of our tutorial - the imports are automatically .ts and not .js
|
|
7
|
+
//y1 - In the esm version of our tutorial - the imports are automatically .ts and not .js in react and not in vue
|
|
8
|
+
//y1 - talk about insert with relations
|
|
5
9
|
//y1 - consider id to also support keyof (id:['company','index']) - had problem with | (keyof Partial<entityType>)[] & `entity`
|
|
10
|
+
//y1 - change exp version to preview?
|
|
11
|
+
//y1 - talk about insert / update / delete with relations
|
|
12
|
+
/*
|
|
13
|
+
repo(Order).insert({},{
|
|
14
|
+
relations:{
|
|
15
|
+
orderItems:[{},{},{}]
|
|
16
|
+
}
|
|
17
|
+
})
|
|
18
|
+
*/
|
|
6
19
|
//y1 - repo batch - for multiple operations:
|
|
7
20
|
/*
|
|
8
21
|
const result = await repo.batch(x=>({
|
|
@@ -13,7 +26,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
13
26
|
//p1 - add documentation for bun sqlite
|
|
14
27
|
//p1 - consider upsert (where,set)
|
|
15
28
|
//p1 - wait a second to close stream
|
|
16
|
-
//p1 - describe entity
|
|
17
29
|
//p1 - prepare the createEntity discussion
|
|
18
30
|
//p1 - write active record article
|
|
19
31
|
//p1 - return error on connection error
|
package/src/sql-command.d.ts
CHANGED
|
@@ -6,6 +6,8 @@ export interface SqlImplementation extends HasWrapIdentifier {
|
|
|
6
6
|
entityIsUsedForTheFirstTime(entity: EntityMetadata): Promise<void>;
|
|
7
7
|
ensureSchema?(entities: EntityMetadata[]): Promise<void>;
|
|
8
8
|
supportsJsonColumnType?: boolean;
|
|
9
|
+
/** true by default */
|
|
10
|
+
doesNotSupportReturningSyntax?: boolean;
|
|
9
11
|
orderByNullsFirst?: boolean;
|
|
10
12
|
end(): Promise<void>;
|
|
11
13
|
afterMutation?: VoidFunction;
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
type Decorator<T = any> = (a: T, b: string, c?: any) => void;
|
|
2
|
-
type Decorators<T> = T extends new (...args: any[]) => infer R ? {
|
|
3
|
-
[K in keyof R]?: Decorator;
|
|
4
|
-
} : never;
|
|
5
|
-
type StaticDecorators<T> = {
|
|
6
|
-
[K in keyof T]?: Decorator;
|
|
7
|
-
};
|
|
8
|
-
export declare function describeClass<classType>(classType: classType, classDecorator: ((x: any, context?: any) => any) | undefined, members?: Decorators<classType> | undefined, staticMembers?: StaticDecorators<classType>): void;
|
|
9
|
-
export {};
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.describeClass = void 0;
|
|
4
|
-
function describeClass(classType, classDecorator, members, staticMembers) {
|
|
5
|
-
if (classDecorator)
|
|
6
|
-
classDecorator(classType);
|
|
7
|
-
for (var fieldKey in members) {
|
|
8
|
-
if (Object.prototype.hasOwnProperty.call(members, fieldKey)) {
|
|
9
|
-
var element = members[fieldKey];
|
|
10
|
-
var prop = Object.getOwnPropertyDescriptor(classType.prototype, fieldKey);
|
|
11
|
-
element(classType.prototype, fieldKey, prop);
|
|
12
|
-
if (prop)
|
|
13
|
-
Object.defineProperty(classType.prototype, fieldKey, prop);
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
for (var staticFieldKey in staticMembers) {
|
|
17
|
-
var staticElement = staticMembers[staticFieldKey];
|
|
18
|
-
var prop = Object.getOwnPropertyDescriptor(classType, staticFieldKey);
|
|
19
|
-
staticElement(classType, staticFieldKey, prop);
|
|
20
|
-
if (prop)
|
|
21
|
-
Object.defineProperty(classType, staticFieldKey, prop);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
exports.describeClass = describeClass;
|