remult 0.26.6-exp.0 → 0.26.7

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 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/DecoratorReplacer.js';
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
@@ -0,0 +1,50 @@
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
+ });
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
+ this.db.all(sql, this.values, (err, rows) => {
19
+ console.log(sql, rows);
20
+ if (err)
21
+ error(err);
22
+ else
23
+ resolve(new Sqlite3SqlResult(rows));
24
+ });
25
+ });
26
+ }
27
+ addParameterAndReturnSqlToken(val) {
28
+ return this.param(val);
29
+ }
30
+ param(val) {
31
+ if (val instanceof Date)
32
+ val = val.valueOf();
33
+ if (typeof val === 'boolean')
34
+ val = val ? 1 : 0;
35
+ const key = ':' + this.i++;
36
+ this.values[key.substring(1)] = val;
37
+ return key;
38
+ }
39
+ }
40
+ export class Sqlite3SqlResult {
41
+ result;
42
+ constructor(result) {
43
+ this.result = result;
44
+ this.rows = result;
45
+ }
46
+ rows;
47
+ getColumnKeyInResultForIndexInSelect(index) {
48
+ return Object.keys(this.result[0])[index];
49
+ }
50
+ }
@@ -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 = await this.dataProvider;
276
+ x.dataProvider = dataProvider;
274
277
  x.subscriptionServer = this.subscriptionServer;
275
278
  x.liveQueryStorage = this.liveQueryStorage;
276
279
  return await what(x);
@@ -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
- export function describeClass(classType, classDecorator, members, staticMembers) {
2
- if (classDecorator)
3
- classDecorator(classType);
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/DecoratorReplacer.js';
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 DecoratorReplacer_js_1 = require("./src/remult3/DecoratorReplacer.js");
26
- Object.defineProperty(exports, "describeClass", { enumerable: true, get: function () { return DecoratorReplacer_js_1.describeClass; } });
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.6-exp.0",
3
+ "version": "0.26.7",
4
4
  "description": "A CRUD framework for full-stack TypeScript",
5
5
  "homepage": "https://remult.dev",
6
6
  "repository": {
@@ -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,66 @@
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
+ }); }) || 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
+ _this.db.all(sql, _this.values, function (err, rows) {
32
+ console.log(sql, rows);
33
+ if (err)
34
+ error(err);
35
+ else
36
+ resolve(new Sqlite3SqlResult(rows));
37
+ });
38
+ })];
39
+ });
40
+ });
41
+ };
42
+ Sqlite3Command.prototype.addParameterAndReturnSqlToken = function (val) {
43
+ return this.param(val);
44
+ };
45
+ Sqlite3Command.prototype.param = function (val) {
46
+ if (val instanceof Date)
47
+ val = val.valueOf();
48
+ if (typeof val === 'boolean')
49
+ val = val ? 1 : 0;
50
+ var key = ':' + this.i++;
51
+ this.values[key.substring(1)] = val;
52
+ return key;
53
+ };
54
+ return Sqlite3Command;
55
+ }());
56
+ var Sqlite3SqlResult = /** @class */ (function () {
57
+ function Sqlite3SqlResult(result) {
58
+ this.result = result;
59
+ this.rows = result;
60
+ }
61
+ Sqlite3SqlResult.prototype.getColumnKeyInResultForIndexInSelect = function (index) {
62
+ return Object.keys(this.result[0])[index];
63
+ };
64
+ return Sqlite3SqlResult;
65
+ }());
66
+ exports.Sqlite3SqlResult = Sqlite3SqlResult;
@@ -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: return [4 /*yield*/, (0, context_js_1.withRemult)(function (remult) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
506
- var x, _a;
507
- return tslib_1.__generator(this, function (_b) {
508
- switch (_b.label) {
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 (!!(options === null || options === void 0 ? void 0 : options.skipDataProvider)) return [3 /*break*/, 2];
513
- _a = x;
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 3: return [2 /*return*/, _b.sent()];
524
+ case 1: return [2 /*return*/, _a.sent()];
523
525
  }
524
526
  });
525
527
  }); })];
526
- case 1: return [2 /*return*/, _a.sent()];
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
- /** If this field data is included in the api.
15
- * @see [allowed](http://remult.dev/docs/allowed.html)*/
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
- /** If this field data can be updated in the api.
18
- * @see [allowed](http://remult.dev/docs/allowed.html)*/
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
  }
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
  }
@@ -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; }
@@ -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> = {
@@ -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
@@ -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;