remult 0.26.4 → 0.26.5-exp.1

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/README.md CHANGED
@@ -84,7 +84,9 @@ export class Product {
84
84
  unitPrice = 0
85
85
  }
86
86
  ```
87
-
87
+ > [!NOTE]
88
+ > Don't like decorators? we have full support for [Working without decorators](https://remult.dev/docs/working-without-decorators)
89
+ >
88
90
  ### Add backend API with a [single line of code](https://remult.dev/docs/quickstart#server-side-initialization)
89
91
 
90
92
  _Example:_
@@ -155,10 +155,11 @@ export class PostgresSchemaBuilder {
155
155
  else {
156
156
  result += postgresColumnSyntax(x, e.$dbNameOf(x));
157
157
  }
158
- if (x == entity.idMetadata.field)
159
- result += ' primary key';
160
158
  }
161
159
  }
160
+ result += `,\r\n primary key (${entity.idMetadata.fields
161
+ .map((f) => e.$dbNameOf(f))
162
+ .join(',')})`;
162
163
  let sql = `CREATE SCHEMA IF NOT EXISTS ${this.schemaOnly(e)};
163
164
  CREATE table ${this.schemaAndName(e)} (${result}\r\n)`;
164
165
  return sql;
@@ -1,12 +1,10 @@
1
1
  import { CustomSqlFilterBuilder, } from '../src/filter/filter-consumer-bridge-to-sql-request.js';
2
2
  import { dbNamesOf, isDbReadonly, shouldCreateEntity, shouldNotCreateField, } from '../src/filter/filter-consumer-bridge-to-sql-request.js';
3
3
  import { customDatabaseFilterToken, Filter, } from '../src/filter/filter-interfaces.js';
4
- import { CompoundIdField } from '../src/CompoundIdField.js';
5
4
  import { remult as remultContext } from '../src/remult-proxy.js';
6
5
  import { getRepository, isAutoIncrement, } from '../src/remult3/RepositoryImplementation.js';
7
6
  import { Sort } from '../src/sort.js';
8
7
  import { ValueConverters } from '../src/valueConverters.js';
9
- import { resultCompoundIdFilter as resultCompoundIdFilter } from '../src/resultCompoundIdFilter.js';
10
8
  import { getRepositoryInternals } from '../src/remult3/repository-internals.js';
11
9
  import { remultStatic } from '../src/remult-static.js';
12
10
  export class KnexDataProvider {
@@ -233,10 +231,7 @@ class KnexEntityDataProvider {
233
231
  async insert(data) {
234
232
  const e = await this.init();
235
233
  let resultFilter;
236
- if (this.entity.idMetadata.field instanceof CompoundIdField)
237
- resultFilter = resultCompoundIdFilter(this.entity.idMetadata.field, undefined, data);
238
- else
239
- resultFilter = Filter.fromEntityFilter(this.entity, this.entity.idMetadata.getIdFilter(data[this.entity.idMetadata.field.key]));
234
+ resultFilter = Filter.fromEntityFilter(this.entity, this.entity.idMetadata.getIdFilter(data[this.entity.idMetadata.field.key]));
240
235
  let insertObject = {};
241
236
  for (const x of this.entity.fields) {
242
237
  if (isDbReadonly(x, e)) {
@@ -426,11 +421,10 @@ export class KnexSchemaBuilder {
426
421
  b.increments(cols.get(x).name);
427
422
  else {
428
423
  buildColumn(x, cols.get(x).name, b, supportsJsonDataStorage(this.knex));
429
- if (x == entity.idMetadata.field)
430
- b.primary([cols.get(x).name]);
431
424
  }
432
425
  }
433
426
  }
427
+ b.primary(entity.idMetadata.fields.map((f) => e.$dbNameOf(f)));
434
428
  });
435
429
  }
436
430
  async addColumnIfNotExist(entity, c) {
@@ -1,9 +1,8 @@
1
1
  import { ObjectId, } from 'mongodb';
2
- import { CompoundIdField, Filter } from './index.js';
2
+ import { Filter } from './index.js';
3
3
  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
- import { resultCompoundIdFilter } from './src/resultCompoundIdFilter.js';
7
6
  import { getRepositoryInternals } from './src/remult3/repository-internals.js';
8
7
  export class MongoDataProvider {
9
8
  db;
@@ -130,11 +129,6 @@ class MongoEntityDataProvider {
130
129
  let resultFilter = this.entity.idMetadata.getIdFilter(id);
131
130
  if (data.id != undefined)
132
131
  resultFilter = this.entity.idMetadata.getIdFilter(data.id);
133
- for (const x of this.entity.fields) {
134
- if (x instanceof CompoundIdField) {
135
- resultFilter = resultCompoundIdFilter(x, id, data);
136
- }
137
- }
138
132
  let newR = {};
139
133
  let keys = Object.keys(data);
140
134
  for (const f of this.entity.fields) {
@@ -84,7 +84,7 @@ export class SqliteCoreDataProvider {
84
84
  result += '\r\n ';
85
85
  if (isAutoIncrement(x)) {
86
86
  if (x.key != entity.idMetadata.field.key)
87
- throw 'in web sql, autoincrement is only allowed for primary key';
87
+ throw 'in sqlite, autoincrement is only allowed for primary key';
88
88
  result += e.$dbNameOf(x) + ' integer primary key autoincrement';
89
89
  }
90
90
  else {
@@ -1,4 +1,3 @@
1
- import { CompoundIdField } from '../src/CompoundIdField.js';
2
1
  import { getRelationFieldInfo, } from '../src/remult3/relationInfoMember.js';
3
2
  import { Filter } from '../src/filter/filter-interfaces.js';
4
3
  import { getHtml } from './get-remult-admin-html.js';
@@ -17,13 +16,9 @@ export function buildEntityInfo(options) {
17
16
  let fields = [];
18
17
  let relations = [];
19
18
  let ids = {};
20
- if (metadata.idMetadata.field instanceof CompoundIdField) {
21
- for (const field of metadata.idMetadata.field.fields) {
22
- ids[field.key] = true;
23
- }
19
+ for (const f of metadata.idMetadata.fields) {
20
+ ids[f.key] = true;
24
21
  }
25
- else
26
- ids[metadata.idMetadata.field.key] = true;
27
22
  for (const x of metadata.fields.toArray()) {
28
23
  if (!x.includedInApi(undefined))
29
24
  continue;
@@ -1,4 +1,3 @@
1
- import { CompoundIdField } from '../CompoundIdField.js';
2
1
  import { FilterConsumerBridgeToSqlRequest, dbNamesOf, isDbReadonly, } from '../filter/filter-consumer-bridge-to-sql-request.js';
3
2
  import { Filter, customDatabaseFilterToken, } from '../filter/filter-interfaces.js';
4
3
  import { remult as defaultRemult } from '../remult-proxy.js';
@@ -256,14 +255,7 @@ class ActualSQLServerDataProvider {
256
255
  let first = true;
257
256
  let segs = [];
258
257
  for (const s of options.orderBy.Segments) {
259
- if (s.field instanceof CompoundIdField) {
260
- segs.push(...s.field.fields.map((c) => ({
261
- field: c,
262
- isDescending: s.isDescending,
263
- })));
264
- }
265
- else
266
- segs.push(s);
258
+ segs.push(s);
267
259
  }
268
260
  for (const c of segs) {
269
261
  if (first) {
@@ -336,8 +328,6 @@ class ActualSQLServerDataProvider {
336
328
  let statement = 'update ' + e.$entityName + ' set ';
337
329
  let added = false;
338
330
  for (const x of this.entity.fields) {
339
- if (x instanceof CompoundIdField) {
340
- }
341
331
  if (isDbReadonly(x, e)) {
342
332
  }
343
333
  else if (data[x.key] !== undefined) {
@@ -229,7 +229,15 @@ export async function entityDbName(metadata, wrapIdentifier = (x) => x) {
229
229
  if (typeof metadata.options.sqlExpression === 'string')
230
230
  return metadata.options.sqlExpression;
231
231
  else if (typeof metadata.options.sqlExpression === 'function') {
232
- return await metadata.options.sqlExpression(metadata);
232
+ const prev = metadata.options.sqlExpression;
233
+ try {
234
+ metadata.options.sqlExpression =
235
+ "recursive sqlExpression call for entity '" + metadata.key + "'. ";
236
+ return await prev(metadata);
237
+ }
238
+ finally {
239
+ metadata.options.sqlExpression = prev;
240
+ }
233
241
  }
234
242
  }
235
243
  return wrapIdentifier(metadata.dbName);
@@ -272,7 +272,7 @@ export class RepositoryImplementation {
272
272
  }
273
273
  }
274
274
  }
275
- async updateMany({ where }, set) {
275
+ async updateMany({ where, set, }) {
276
276
  Filter.throwErrorIfFilterIsEmpty(where, 'updateMany');
277
277
  if (this._dataProvider.isProxy) {
278
278
  return this._edp.updateMany(await this._translateWhereToFilter(where), set);
@@ -1928,6 +1928,11 @@ class EntityFullInfo {
1928
1928
  return item[this.idMetadata.field.key];
1929
1929
  },
1930
1930
  field: undefined,
1931
+ get fields() {
1932
+ return this.field instanceof CompoundIdField
1933
+ ? this.field.fields
1934
+ : [this.field];
1935
+ },
1931
1936
  createIdInFilter: (items) => {
1932
1937
  if (items.length > 0)
1933
1938
  return {
@@ -1,21 +1,26 @@
1
1
  export {};
2
2
  //y1 - https://discord.com/channels/975754286384418847/1230386433093533698/1230386433093533698
3
3
  //y1 - fix async hooks - was it fixed?
4
- //p1 - consider upsert (where,set)
5
- //p1 - consider id to also support keyof (id:['company','index'])
6
- //p1 - wait a second to close stream
4
+ //y1 - repo batch - for multiple operations:
5
+ /*
6
+ const result = await repo.batch(x=>({
7
+ data:x.find(),
8
+ count:x.count()
9
+ }))
10
+ */
11
+ //p1 - adjust react tutorial to esm
7
12
  //p1 - add solid tutorial to the getting started page
8
13
  //p1 - update the examples section
9
- //p1 - support dbnamesof in sqlexpression of entity
10
- //p1 - adjust sql expression of entity docs to include a union example
11
- //p1 - reconsider update many, maybe the second parameter should be in a set option - break existing
12
14
  //p1 - add documentation for bun sqlite
15
+ //p1 - consider upsert (where,set)
16
+ //p1 - wait a second to close stream
17
+ //y1 - consider id to also support keyof (id:['company','index']) - had problem with | (keyof Partial<entityType>)[] & `entity`
13
18
  //p1 - describe entity
14
19
  //p1 - prepare the createEntity discussion
15
20
  //p1 - write active record article
16
- //p1 - maybe add decorator comment in the readme as well (I heard you've lost me in decorators) - and improve the describeClass function
17
21
  //p1 - return error on connection error
18
22
  //p1 - consider including the admin in the tutorial - and maybe even in the demo when we setup the api
23
+ //p1 - reconsider key typing to be keyof & string
19
24
  //p2 -fix remult admin not to load the html into memory until used
20
25
  //y2 - JY suggestion of having generate as part of the ensure schema - not sure
21
26
  //y2 - currently for string fields we default for 255 in knex (which is their default) why not just use text (varchar max) - and only use exact length when one is provided?
@@ -92,4 +97,3 @@ export {};
92
97
  //y2 - add some api testing framework for user unit tests (will help with codesandbox based discussions)
93
98
  //[ ] V2 - what to do about for relations count?
94
99
  //[ ] V2 - condition? not to fetch if null etc....
95
- //p1 - adjust react tutorial to esm
@@ -26,10 +26,15 @@ export class Validators {
26
26
  static regex = createValueValidatorWithArgs((val, regex) => regex.test(val));
27
27
  static email = createValueValidator((val) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(val), 'Invalid Email');
28
28
  static url = createValueValidator((val) => !!new URL(val), 'Invalid Url');
29
- static in = createValueValidatorWithArgs((val, values) => values.includes(val), (values) => `Value must be one of ${values.map(y => typeof y === "object" ? y['id'] !== undefined ? y['id'] : y.toString() : y).join(', ')}`);
30
- static notNull = createValueValidator((val) => val != null, 'Should not be null');
31
- static enum = createValueValidatorWithArgs((value, enumObj) => Object.values(enumObj).includes(value), (enumObj) => `Value must be one of ${getEnumValues(enumObj)
29
+ static in = createValueValidatorWithArgs((val, values) => values.includes(val), (values) => `Value must be one of: ${values
30
+ .map((y) => typeof y === 'object'
31
+ ? y['id'] !== undefined
32
+ ? y['id']
33
+ : y.toString()
34
+ : y)
32
35
  .join(', ')}`);
36
+ static notNull = createValueValidator((val) => val != null, 'Should not be null');
37
+ static enum = createValueValidatorWithArgs((value, enumObj) => Object.values(enumObj).includes(value), (enumObj) => `Value must be one of ${getEnumValues(enumObj).join(', ')}`);
33
38
  static relationExists = createValidator(async (_, e) => {
34
39
  if (e.valueIsNull())
35
40
  return true;
@@ -134,6 +139,5 @@ function createValidatorWithArgsInternal(validate, defaultMessage, isValueValida
134
139
  });
135
140
  }
136
141
  export function getEnumValues(enumObj) {
137
- return Object.values(enumObj)
138
- .filter((x) => typeof enumObj[x] !== 'number');
142
+ return Object.values(enumObj).filter((x) => typeof enumObj[x] !== 'number');
139
143
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "remult",
3
- "version": "0.26.4",
3
+ "version": "0.26.5-exp.1",
4
4
  "description": "A CRUD framework for full-stack TypeScript",
5
5
  "homepage": "https://remult.dev",
6
6
  "repository": {
@@ -287,8 +287,6 @@ var PostgresSchemaBuilder = /** @class */ (function () {
287
287
  else {
288
288
  result += postgresColumnSyntax(x, e.$dbNameOf(x));
289
289
  }
290
- if (x == entity.idMetadata.field)
291
- result += ' primary key';
292
290
  }
293
291
  }
294
292
  }
@@ -299,6 +297,9 @@ var PostgresSchemaBuilder = /** @class */ (function () {
299
297
  }
300
298
  finally { if (e_3) throw e_3.error; }
301
299
  }
300
+ result += ",\r\n primary key (".concat(entity.idMetadata.fields
301
+ .map(function (f) { return e.$dbNameOf(f); })
302
+ .join(','), ")");
302
303
  sql = "CREATE SCHEMA IF NOT EXISTS ".concat(this.schemaOnly(e), ";\nCREATE table ").concat(this.schemaAndName(e), " (").concat(result, "\r\n)");
303
304
  return [2 /*return*/, sql];
304
305
  }
@@ -5,12 +5,10 @@ var tslib_1 = require("tslib");
5
5
  var filter_consumer_bridge_to_sql_request_js_1 = require("../src/filter/filter-consumer-bridge-to-sql-request.js");
6
6
  var filter_consumer_bridge_to_sql_request_js_2 = require("../src/filter/filter-consumer-bridge-to-sql-request.js");
7
7
  var filter_interfaces_js_1 = require("../src/filter/filter-interfaces.js");
8
- var CompoundIdField_js_1 = require("../src/CompoundIdField.js");
9
8
  var remult_proxy_js_1 = require("../src/remult-proxy.js");
10
9
  var RepositoryImplementation_js_1 = require("../src/remult3/RepositoryImplementation.js");
11
10
  var sort_js_1 = require("../src/sort.js");
12
11
  var valueConverters_js_1 = require("../src/valueConverters.js");
13
- var resultCompoundIdFilter_js_1 = require("../src/resultCompoundIdFilter.js");
14
12
  var repository_internals_js_1 = require("../src/remult3/repository-internals.js");
15
13
  var remult_static_js_1 = require("../src/remult-static.js");
16
14
  var KnexDataProvider = /** @class */ (function () {
@@ -422,10 +420,7 @@ var KnexEntityDataProvider = /** @class */ (function () {
422
420
  case 0: return [4 /*yield*/, this.init()];
423
421
  case 1:
424
422
  e = _d.sent();
425
- if (this.entity.idMetadata.field instanceof CompoundIdField_js_1.CompoundIdField)
426
- resultFilter = (0, resultCompoundIdFilter_js_1.resultCompoundIdFilter)(this.entity.idMetadata.field, undefined, data);
427
- else
428
- resultFilter = filter_interfaces_js_1.Filter.fromEntityFilter(this.entity, this.entity.idMetadata.getIdFilter(data[this.entity.idMetadata.field.key]));
423
+ resultFilter = filter_interfaces_js_1.Filter.fromEntityFilter(this.entity, this.entity.idMetadata.getIdFilter(data[this.entity.idMetadata.field.key]));
429
424
  insertObject = {};
430
425
  _d.label = 2;
431
426
  case 2:
@@ -838,8 +833,6 @@ var KnexSchemaBuilder = /** @class */ (function () {
838
833
  b.increments(cols.get(x).name);
839
834
  else {
840
835
  buildColumn(x, cols.get(x).name, b, supportsJsonDataStorage(_this.knex));
841
- if (x == entity.idMetadata.field)
842
- b.primary([cols.get(x).name]);
843
836
  }
844
837
  }
845
838
  }
@@ -851,6 +844,7 @@ var KnexSchemaBuilder = /** @class */ (function () {
851
844
  }
852
845
  finally { if (e_10) throw e_10.error; }
853
846
  }
847
+ b.primary(entity.idMetadata.fields.map(function (f) { return e.$dbNameOf(f); }));
854
848
  });
855
849
  };
856
850
  KnexSchemaBuilder.prototype.addColumnIfNotExist = function (entity, c) {
package/remult-mongo.js CHANGED
@@ -7,7 +7,6 @@ var index_js_1 = require("./index.js");
7
7
  var filter_consumer_bridge_to_sql_request_js_1 = require("./src/filter/filter-consumer-bridge-to-sql-request.js");
8
8
  var remult_proxy_js_1 = require("./src/remult-proxy.js");
9
9
  var RepositoryImplementation_js_1 = require("./src/remult3/RepositoryImplementation.js");
10
- var resultCompoundIdFilter_js_1 = require("./src/resultCompoundIdFilter.js");
11
10
  var repository_internals_js_1 = require("./src/remult3/repository-internals.js");
12
11
  var MongoDataProvider = /** @class */ (function () {
13
12
  function MongoDataProvider(db, client, options) {
@@ -222,38 +221,23 @@ var MongoEntityDataProvider = /** @class */ (function () {
222
221
  };
223
222
  MongoEntityDataProvider.prototype.update = function (id, data) {
224
223
  return tslib_1.__awaiter(this, void 0, void 0, function () {
225
- var _a, collection, e, f, resultFilter, _b, _c, x, newR, keys, _d, _e, f_1, r, _f, _g;
226
- var e_4, _h, e_5, _j;
227
- return tslib_1.__generator(this, function (_k) {
228
- switch (_k.label) {
224
+ var _a, collection, e, f, resultFilter, newR, keys, _b, _c, f_1, r, _d, _e;
225
+ var e_4, _f;
226
+ return tslib_1.__generator(this, function (_g) {
227
+ switch (_g.label) {
229
228
  case 0: return [4 /*yield*/, this.collection()];
230
229
  case 1:
231
- _a = _k.sent(), collection = _a.collection, e = _a.e;
230
+ _a = _g.sent(), collection = _a.collection, e = _a.e;
232
231
  f = new FilterConsumerBridgeToMongo(e);
233
232
  index_js_1.Filter.fromEntityFilter(this.entity, this.entity.idMetadata.getIdFilter(id)).__applyToConsumer(f);
234
233
  resultFilter = this.entity.idMetadata.getIdFilter(id);
235
234
  if (data.id != undefined)
236
235
  resultFilter = this.entity.idMetadata.getIdFilter(data.id);
237
- try {
238
- for (_b = tslib_1.__values(this.entity.fields), _c = _b.next(); !_c.done; _c = _b.next()) {
239
- x = _c.value;
240
- if (x instanceof index_js_1.CompoundIdField) {
241
- resultFilter = (0, resultCompoundIdFilter_js_1.resultCompoundIdFilter)(x, id, data);
242
- }
243
- }
244
- }
245
- catch (e_4_1) { e_4 = { error: e_4_1 }; }
246
- finally {
247
- try {
248
- if (_c && !_c.done && (_h = _b.return)) _h.call(_b);
249
- }
250
- finally { if (e_4) throw e_4.error; }
251
- }
252
236
  newR = {};
253
237
  keys = Object.keys(data);
254
238
  try {
255
- for (_d = tslib_1.__values(this.entity.fields), _e = _d.next(); !_e.done; _e = _d.next()) {
256
- f_1 = _e.value;
239
+ for (_b = tslib_1.__values(this.entity.fields), _c = _b.next(); !_c.done; _c = _b.next()) {
240
+ f_1 = _c.value;
257
241
  if (!f_1.dbReadOnly && !f_1.isServerExpression) {
258
242
  if (keys.includes(f_1.key)) {
259
243
  newR[f_1.key] = toDb(f_1, data[f_1.key]);
@@ -261,21 +245,21 @@ var MongoEntityDataProvider = /** @class */ (function () {
261
245
  }
262
246
  }
263
247
  }
264
- catch (e_5_1) { e_5 = { error: e_5_1 }; }
248
+ catch (e_4_1) { e_4 = { error: e_4_1 }; }
265
249
  finally {
266
250
  try {
267
- if (_e && !_e.done && (_j = _d.return)) _j.call(_d);
251
+ if (_c && !_c.done && (_f = _b.return)) _f.call(_b);
268
252
  }
269
- finally { if (e_5) throw e_5.error; }
253
+ finally { if (e_4) throw e_4.error; }
270
254
  }
271
- _g = (_f = collection).updateOne;
255
+ _e = (_d = collection).updateOne;
272
256
  return [4 /*yield*/, f.resolveWhere()];
273
- case 2: return [4 /*yield*/, _g.apply(_f, [_k.sent(), {
257
+ case 2: return [4 /*yield*/, _e.apply(_d, [_g.sent(), {
274
258
  $set: newR,
275
259
  },
276
260
  { session: this.session }])];
277
261
  case 3:
278
- r = _k.sent();
262
+ r = _g.sent();
279
263
  return [2 /*return*/, this.find({
280
264
  where: index_js_1.Filter.fromEntityFilter(this.entity, resultFilter),
281
265
  }).then(function (y) { return y[0]; })];
@@ -350,8 +334,8 @@ var FilterConsumerBridgeToMongo = /** @class */ (function () {
350
334
  }
351
335
  FilterConsumerBridgeToMongo.prototype.resolveWhere = function () {
352
336
  return tslib_1.__awaiter(this, void 0, void 0, function () {
353
- var p, p_1, p_1_1, pr, e_6_1;
354
- var e_6, _a;
337
+ var p, p_1, p_1_1, pr, e_5_1;
338
+ var e_5, _a;
355
339
  return tslib_1.__generator(this, function (_b) {
356
340
  switch (_b.label) {
357
341
  case 0:
@@ -361,7 +345,7 @@ var FilterConsumerBridgeToMongo = /** @class */ (function () {
361
345
  _b.label = 1;
362
346
  case 1:
363
347
  _b.trys.push([1, 6, 7, 8]);
364
- p_1 = (e_6 = void 0, tslib_1.__values(p)), p_1_1 = p_1.next();
348
+ p_1 = (e_5 = void 0, tslib_1.__values(p)), p_1_1 = p_1.next();
365
349
  _b.label = 2;
366
350
  case 2:
367
351
  if (!!p_1_1.done) return [3 /*break*/, 5];
@@ -375,14 +359,14 @@ var FilterConsumerBridgeToMongo = /** @class */ (function () {
375
359
  return [3 /*break*/, 2];
376
360
  case 5: return [3 /*break*/, 8];
377
361
  case 6:
378
- e_6_1 = _b.sent();
379
- e_6 = { error: e_6_1 };
362
+ e_5_1 = _b.sent();
363
+ e_5 = { error: e_5_1 };
380
364
  return [3 /*break*/, 8];
381
365
  case 7:
382
366
  try {
383
367
  if (p_1_1 && !p_1_1.done && (_a = p_1.return)) _a.call(p_1);
384
368
  }
385
- finally { if (e_6) throw e_6.error; }
369
+ finally { if (e_5) throw e_5.error; }
386
370
  return [7 /*endfinally*/];
387
371
  case 8: return [3 /*break*/, 0];
388
372
  case 9:
@@ -401,8 +385,8 @@ var FilterConsumerBridgeToMongo = /** @class */ (function () {
401
385
  FilterConsumerBridgeToMongo.prototype.or = function (orElements) {
402
386
  var _this = this;
403
387
  this.promises.push((function () { return tslib_1.__awaiter(_this, void 0, void 0, function () {
404
- var result, orElements_1, orElements_1_1, element, f, where, e_7_1;
405
- var e_7, _a;
388
+ var result, orElements_1, orElements_1_1, element, f, where, e_6_1;
389
+ var e_6, _a;
406
390
  var _b;
407
391
  return tslib_1.__generator(this, function (_c) {
408
392
  switch (_c.label) {
@@ -433,14 +417,14 @@ var FilterConsumerBridgeToMongo = /** @class */ (function () {
433
417
  return [3 /*break*/, 2];
434
418
  case 5: return [3 /*break*/, 8];
435
419
  case 6:
436
- e_7_1 = _c.sent();
437
- e_7 = { error: e_7_1 };
420
+ e_6_1 = _c.sent();
421
+ e_6 = { error: e_6_1 };
438
422
  return [3 /*break*/, 8];
439
423
  case 7:
440
424
  try {
441
425
  if (orElements_1_1 && !orElements_1_1.done && (_a = orElements_1.return)) _a.call(orElements_1);
442
426
  }
443
- finally { if (e_7) throw e_7.error; }
427
+ finally { if (e_6) throw e_6.error; }
444
428
  return [7 /*endfinally*/];
445
429
  case 8:
446
430
  this.result.push(function () { return ({
@@ -184,7 +184,7 @@ var SqliteCoreDataProvider = /** @class */ (function () {
184
184
  result += '\r\n ';
185
185
  if ((0, RepositoryImplementation_js_1.isAutoIncrement)(x)) {
186
186
  if (x.key != entity.idMetadata.field.key)
187
- throw 'in web sql, autoincrement is only allowed for primary key';
187
+ throw 'in sqlite, autoincrement is only allowed for primary key';
188
188
  result += e.$dbNameOf(x) + ' integer primary key autoincrement';
189
189
  }
190
190
  else {
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.buildEntityInfo = void 0;
4
4
  var tslib_1 = require("tslib");
5
- var CompoundIdField_js_1 = require("../src/CompoundIdField.js");
6
5
  var relationInfoMember_js_1 = require("../src/remult3/relationInfoMember.js");
7
6
  var filter_interfaces_js_1 = require("../src/filter/filter-interfaces.js");
8
7
  var get_remult_admin_html_js_1 = require("./get-remult-admin-html.js");
@@ -24,23 +23,19 @@ function buildEntityInfo(options) {
24
23
  var fields = [];
25
24
  var relations = [];
26
25
  var ids = {};
27
- if (metadata.idMetadata.field instanceof CompoundIdField_js_1.CompoundIdField) {
28
- try {
29
- for (var _g = (e_2 = void 0, tslib_1.__values(metadata.idMetadata.field.fields)), _h = _g.next(); !_h.done; _h = _g.next()) {
30
- var field = _h.value;
31
- ids[field.key] = true;
32
- }
26
+ try {
27
+ for (var _g = (e_2 = void 0, tslib_1.__values(metadata.idMetadata.fields)), _h = _g.next(); !_h.done; _h = _g.next()) {
28
+ var f = _h.value;
29
+ ids[f.key] = true;
33
30
  }
34
- catch (e_2_1) { e_2 = { error: e_2_1 }; }
35
- finally {
36
- try {
37
- if (_h && !_h.done && (_b = _g.return)) _b.call(_g);
38
- }
39
- finally { if (e_2) throw e_2.error; }
31
+ }
32
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
33
+ finally {
34
+ try {
35
+ if (_h && !_h.done && (_b = _g.return)) _b.call(_g);
40
36
  }
37
+ finally { if (e_2) throw e_2.error; }
41
38
  }
42
- else
43
- ids[metadata.idMetadata.field.key] = true;
44
39
  var _loop_1 = function (x) {
45
40
  if (!x.includedInApi(undefined))
46
41
  return "continue";
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SqlDatabase = void 0;
4
4
  var tslib_1 = require("tslib");
5
- var CompoundIdField_js_1 = require("../CompoundIdField.js");
6
5
  var filter_consumer_bridge_to_sql_request_js_1 = require("../filter/filter-consumer-bridge-to-sql-request.js");
7
6
  var filter_interfaces_js_1 = require("../filter/filter-interfaces.js");
8
7
  var remult_proxy_js_1 = require("../remult-proxy.js");
@@ -343,7 +342,7 @@ var ActualSQLServerDataProvider = /** @class */ (function () {
343
342
  };
344
343
  ActualSQLServerDataProvider.prototype.find = function (options) {
345
344
  return tslib_1.__awaiter(this, void 0, void 0, function () {
346
- var e, _a, colKeys, select, r, where, _b, first, segs, _loop_1, _c, _d, s, segs_1, segs_1_1, c, page;
345
+ var e, _a, colKeys, select, r, where, _b, first, segs, _c, _d, s, segs_1, segs_1_1, c, page;
347
346
  var e_2, _e, e_3, _f;
348
347
  var _this = this;
349
348
  return tslib_1.__generator(this, function (_g) {
@@ -374,20 +373,10 @@ var ActualSQLServerDataProvider = /** @class */ (function () {
374
373
  if (options.orderBy) {
375
374
  first = true;
376
375
  segs = [];
377
- _loop_1 = function (s) {
378
- if (s.field instanceof CompoundIdField_js_1.CompoundIdField) {
379
- segs.push.apply(segs, tslib_1.__spreadArray([], tslib_1.__read(s.field.fields.map(function (c) { return ({
380
- field: c,
381
- isDescending: s.isDescending,
382
- }); })), false));
383
- }
384
- else
385
- segs.push(s);
386
- };
387
376
  try {
388
377
  for (_c = tslib_1.__values(options.orderBy.Segments), _d = _c.next(); !_d.done; _d = _c.next()) {
389
378
  s = _d.value;
390
- _loop_1(s);
379
+ segs.push(s);
391
380
  }
392
381
  }
393
382
  catch (e_2_1) { e_2 = { error: e_2_1 }; }
@@ -502,8 +491,6 @@ var ActualSQLServerDataProvider = /** @class */ (function () {
502
491
  try {
503
492
  for (_a = tslib_1.__values(this.entity.fields), _b = _a.next(); !_b.done; _b = _a.next()) {
504
493
  x = _b.value;
505
- if (x instanceof CompoundIdField_js_1.CompoundIdField) {
506
- }
507
494
  if ((0, filter_consumer_bridge_to_sql_request_js_1.isDbReadonly)(x, e)) {
508
495
  }
509
496
  else if (data[x.key] !== undefined) {
@@ -652,14 +639,14 @@ var myDummySQLCommand = /** @class */ (function () {
652
639
  }());
653
640
  function bulkInsert(array, db) {
654
641
  return tslib_1.__awaiter(this, void 0, void 0, function () {
655
- var chunkSize, _loop_2, i;
642
+ var chunkSize, _loop_1, i;
656
643
  return tslib_1.__generator(this, function (_a) {
657
644
  switch (_a.label) {
658
645
  case 0:
659
646
  if (array.length == 0)
660
647
  return [2 /*return*/];
661
648
  chunkSize = 250;
662
- _loop_2 = function (i) {
649
+ _loop_1 = function (i) {
663
650
  var items, c, sql, _b, _c;
664
651
  return tslib_1.__generator(this, function (_d) {
665
652
  switch (_d.label) {
@@ -697,7 +684,7 @@ function bulkInsert(array, db) {
697
684
  _a.label = 1;
698
685
  case 1:
699
686
  if (!(i < array.length)) return [3 /*break*/, 4];
700
- return [5 /*yield**/, _loop_2(i)];
687
+ return [5 /*yield**/, _loop_1(i)];
701
688
  case 2:
702
689
  _a.sent();
703
690
  _a.label = 3;
package/src/entity.d.ts CHANGED
@@ -150,7 +150,19 @@ export interface EntityOptions<entityType = any> {
150
150
  * dbName:'public."myProducts"'
151
151
  */
152
152
  dbName?: string;
153
- /** For entities that are based on SQL expressions instead of a physical table or view*/
153
+ /** For entities that are based on SQL expressions instead of a physical table or view
154
+ * @example
155
+ * .@Entity('people',{
156
+ * sqlExpression:`select id,name from employees
157
+ * union all select id,name from contractors`,
158
+ * })
159
+ * export class Person{
160
+ * .@Fields.string()
161
+ * id=''
162
+ * .@Fields.string()
163
+ * name=''
164
+ * }
165
+ */
154
166
  sqlExpression?: string | ((entity: EntityMetadata<entityType>) => string | Promise<string>);
155
167
  /** An arrow function that identifies the `id` column to use for this entity
156
168
  * @example
@@ -369,17 +369,27 @@ exports.dbNamesOf = dbNamesOf;
369
369
  function entityDbName(metadata, wrapIdentifier) {
370
370
  if (wrapIdentifier === void 0) { wrapIdentifier = function (x) { return x; }; }
371
371
  return tslib_1.__awaiter(this, void 0, void 0, function () {
372
+ var prev;
372
373
  return tslib_1.__generator(this, function (_a) {
373
374
  switch (_a.label) {
374
375
  case 0:
375
- if (!metadata.options.sqlExpression) return [3 /*break*/, 3];
376
+ if (!metadata.options.sqlExpression) return [3 /*break*/, 5];
376
377
  if (!(typeof metadata.options.sqlExpression === 'string')) return [3 /*break*/, 1];
377
378
  return [2 /*return*/, metadata.options.sqlExpression];
378
379
  case 1:
379
- if (!(typeof metadata.options.sqlExpression === 'function')) return [3 /*break*/, 3];
380
- return [4 /*yield*/, metadata.options.sqlExpression(metadata)];
381
- case 2: return [2 /*return*/, _a.sent()];
382
- case 3: return [2 /*return*/, wrapIdentifier(metadata.dbName)];
380
+ if (!(typeof metadata.options.sqlExpression === 'function')) return [3 /*break*/, 5];
381
+ prev = metadata.options.sqlExpression;
382
+ _a.label = 2;
383
+ case 2:
384
+ _a.trys.push([2, , 4, 5]);
385
+ metadata.options.sqlExpression =
386
+ "recursive sqlExpression call for entity '" + metadata.key + "'. ";
387
+ return [4 /*yield*/, prev(metadata)];
388
+ case 3: return [2 /*return*/, _a.sent()];
389
+ case 4:
390
+ metadata.options.sqlExpression = prev;
391
+ return [7 /*endfinally*/];
392
+ case 5: return [2 /*return*/, wrapIdentifier(metadata.dbName)];
383
393
  }
384
394
  });
385
395
  });
@@ -47,9 +47,10 @@ export declare class RepositoryImplementation<entityType> implements Repository<
47
47
  insert(item: Partial<MembersOnly<entityType>>): Promise<entityType>;
48
48
  get fields(): FieldsMetadata<entityType>;
49
49
  validate(entity: Partial<MembersOnly<entityType>>, ...fields: Extract<keyof MembersOnly<entityType>, string>[]): Promise<ErrorInfo<entityType> | undefined>;
50
- updateMany({ where }: {
50
+ updateMany({ where, set, }: {
51
51
  where: EntityFilter<entityType>;
52
- }, set: Partial<MembersOnly<entityType>>): Promise<number>;
52
+ set: Partial<MembersOnly<entityType>>;
53
+ }): Promise<number>;
53
54
  update(id: idType<entityType>, item: Partial<MembersOnly<entityType>>): Promise<entityType>;
54
55
  update(originalItem: Partial<MembersOnly<entityType>>, item: Partial<MembersOnly<entityType>>): Promise<entityType>;
55
56
  private _getRefForExistingRow;
@@ -438,9 +438,9 @@ var RepositoryImplementation = /** @class */ (function () {
438
438
  });
439
439
  });
440
440
  };
441
- RepositoryImplementation.prototype.updateMany = function (_a, set) {
441
+ RepositoryImplementation.prototype.updateMany = function (_a) {
442
442
  var _b, e_7, _c, _d;
443
- var where = _a.where;
443
+ var where = _a.where, set = _a.set;
444
444
  return tslib_1.__awaiter(this, void 0, void 0, function () {
445
445
  var _e, _f, updated, _g, _h, _j, item, e_7_1;
446
446
  return tslib_1.__generator(this, function (_k) {
@@ -3101,6 +3101,11 @@ var EntityFullInfo = /** @class */ (function () {
3101
3101
  return item[_this.idMetadata.field.key];
3102
3102
  },
3103
3103
  field: undefined,
3104
+ get fields() {
3105
+ return this.field instanceof CompoundIdField_js_1.CompoundIdField
3106
+ ? this.field.fields
3107
+ : [this.field];
3108
+ },
3104
3109
  createIdInFilter: function (items) {
3105
3110
  if (items.length > 0)
3106
3111
  return {
@@ -174,6 +174,7 @@ export interface IdMetadata<entityType = any> {
174
174
  */
175
175
  getId(item: Partial<MembersOnly<entityType>>): any;
176
176
  field: FieldMetadata<any>;
177
+ fields: FieldMetadata<unknown>[];
177
178
  getIdFilter(...ids: any[]): EntityFilter<entityType>;
178
179
  isIdField(col: FieldMetadata): boolean;
179
180
  createIdInFilter(items: Partial<MembersOnly<entityType>>[]): EntityFilter<entityType>;
@@ -317,7 +318,8 @@ export interface Repository<entityType> {
317
318
  */
318
319
  updateMany(options: {
319
320
  where: EntityFilter<entityType>;
320
- }, item: Partial<MembersOnly<entityType>>): Promise<number>;
321
+ set: Partial<MembersOnly<entityType>>;
322
+ }): Promise<number>;
321
323
  /** Deletes an Item*/
322
324
  delete(id: idType<entityType>): Promise<void>;
323
325
  delete(item: Partial<MembersOnly<entityType>>): Promise<void>;
@@ -2,21 +2,26 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  //y1 - https://discord.com/channels/975754286384418847/1230386433093533698/1230386433093533698
4
4
  //y1 - fix async hooks - was it fixed?
5
- //p1 - consider upsert (where,set)
6
- //p1 - consider id to also support keyof (id:['company','index'])
7
- //p1 - wait a second to close stream
5
+ //y1 - repo batch - for multiple operations:
6
+ /*
7
+ const result = await repo.batch(x=>({
8
+ data:x.find(),
9
+ count:x.count()
10
+ }))
11
+ */
12
+ //p1 - adjust react tutorial to esm
8
13
  //p1 - add solid tutorial to the getting started page
9
14
  //p1 - update the examples section
10
- //p1 - support dbnamesof in sqlexpression of entity
11
- //p1 - adjust sql expression of entity docs to include a union example
12
- //p1 - reconsider update many, maybe the second parameter should be in a set option - break existing
13
15
  //p1 - add documentation for bun sqlite
16
+ //p1 - consider upsert (where,set)
17
+ //p1 - wait a second to close stream
18
+ //y1 - consider id to also support keyof (id:['company','index']) - had problem with | (keyof Partial<entityType>)[] & `entity`
14
19
  //p1 - describe entity
15
20
  //p1 - prepare the createEntity discussion
16
21
  //p1 - write active record article
17
- //p1 - maybe add decorator comment in the readme as well (I heard you've lost me in decorators) - and improve the describeClass function
18
22
  //p1 - return error on connection error
19
23
  //p1 - consider including the admin in the tutorial - and maybe even in the demo when we setup the api
24
+ //p1 - reconsider key typing to be keyof & string
20
25
  //p2 -fix remult admin not to load the html into memory until used
21
26
  //y2 - JY suggestion of having generate as part of the ensure schema - not sure
22
27
  //y2 - currently for string fields we default for 255 in knex (which is their default) why not just use text (varchar max) - and only use exact length when one is provided?
@@ -93,4 +98,3 @@ Object.defineProperty(exports, "__esModule", { value: true });
93
98
  //y2 - add some api testing framework for user unit tests (will help with codesandbox based discussions)
94
99
  //[ ] V2 - what to do about for relations count?
95
100
  //[ ] V2 - condition? not to fetch if null etc....
96
- //p1 - adjust react tutorial to esm
package/src/validators.js CHANGED
@@ -48,14 +48,19 @@ var Validators = /** @class */ (function () {
48
48
  });
49
49
  Validators.email = createValueValidator(function (val) { return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(val); }, 'Invalid Email');
50
50
  Validators.url = createValueValidator(function (val) { return !!new URL(val); }, 'Invalid Url');
51
- Validators.in = createValueValidatorWithArgs(function (val, values) { return values.includes(val); }, function (values) { return "Value must be one of ".concat(values.map(function (y) {
52
- return typeof y === "object" ? y['id'] !== undefined ? y['id'] : y.toString() : y;
53
- }).join(', ')); });
54
- Validators.notNull = createValueValidator(function (val) { return val != null; }, 'Should not be null');
55
- Validators.enum = createValueValidatorWithArgs(function (value, enumObj) { return Object.values(enumObj).includes(value); }, function (enumObj) {
56
- return "Value must be one of ".concat(getEnumValues(enumObj)
51
+ Validators.in = createValueValidatorWithArgs(function (val, values) { return values.includes(val); }, function (values) {
52
+ return "Value must be one of: ".concat(values
53
+ .map(function (y) {
54
+ return typeof y === 'object'
55
+ ? y['id'] !== undefined
56
+ ? y['id']
57
+ : y.toString()
58
+ : y;
59
+ })
57
60
  .join(', '));
58
61
  });
62
+ Validators.notNull = createValueValidator(function (val) { return val != null; }, 'Should not be null');
63
+ Validators.enum = createValueValidatorWithArgs(function (value, enumObj) { return Object.values(enumObj).includes(value); }, function (enumObj) { return "Value must be one of ".concat(getEnumValues(enumObj).join(', ')); });
59
64
  Validators.relationExists = createValidator(function (_, e) { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
60
65
  var _b;
61
66
  return tslib_1.__generator(_a, function (_c) {
@@ -209,7 +214,6 @@ function createValidatorWithArgsInternal(validate, defaultMessage, isValueValida
209
214
  });
210
215
  }
211
216
  function getEnumValues(enumObj) {
212
- return Object.values(enumObj)
213
- .filter(function (x) { return typeof enumObj[x] !== 'number'; });
217
+ return Object.values(enumObj).filter(function (x) { return typeof enumObj[x] !== 'number'; });
214
218
  }
215
219
  exports.getEnumValues = getEnumValues;
@@ -1,16 +0,0 @@
1
- import { Filter } from './filter/filter-interfaces.js';
2
- export function resultCompoundIdFilter(idField, id, data) {
3
- return new Filter((add) => {
4
- let idParts = [];
5
- if (id != undefined)
6
- idParts = id.split(',');
7
- idField.fields.forEach((c, i) => {
8
- let val = undefined;
9
- if (i < idParts.length)
10
- val = idParts[i];
11
- if (data[c.key] != undefined)
12
- val = data[c.key];
13
- add.isEqualTo(c, val);
14
- });
15
- });
16
- }
@@ -1,3 +0,0 @@
1
- import type { CompoundIdField } from './CompoundIdField.js';
2
- import { Filter } from './filter/filter-interfaces.js';
3
- export declare function resultCompoundIdFilter(idField: CompoundIdField, id: string | undefined, data: any): Filter;
@@ -1,20 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.resultCompoundIdFilter = void 0;
4
- var filter_interfaces_js_1 = require("./filter/filter-interfaces.js");
5
- function resultCompoundIdFilter(idField, id, data) {
6
- return new filter_interfaces_js_1.Filter(function (add) {
7
- var idParts = [];
8
- if (id != undefined)
9
- idParts = id.split(',');
10
- idField.fields.forEach(function (c, i) {
11
- var val = undefined;
12
- if (i < idParts.length)
13
- val = idParts[i];
14
- if (data[c.key] != undefined)
15
- val = data[c.key];
16
- add.isEqualTo(c, val);
17
- });
18
- });
19
- }
20
- exports.resultCompoundIdFilter = resultCompoundIdFilter;