remult 0.18.1-exp.4 → 0.18.1-exp.5

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.
Files changed (79) hide show
  1. package/esm/index.d.ts +4 -4
  2. package/esm/index.js +3 -3
  3. package/esm/live-query/ably.d.ts +1 -1
  4. package/esm/postgres/schema-builder.js +13 -5
  5. package/esm/remult-express.js +1 -1
  6. package/esm/remult-knex/index.d.ts +1 -1
  7. package/esm/remult-knex/index.js +13 -7
  8. package/esm/server/expressBridge.d.ts +4 -3
  9. package/esm/server/expressBridge.js +2 -1
  10. package/esm/src/column-interfaces.d.ts +44 -8
  11. package/esm/src/column.d.ts +2 -5
  12. package/esm/src/column.js +12 -28
  13. package/esm/src/context.d.ts +28 -20
  14. package/esm/src/context.js +26 -15
  15. package/esm/src/data-api.js +2 -2
  16. package/esm/src/data-providers/rest-data-provider.js +1 -1
  17. package/esm/src/data-providers/sql-database.js +2 -0
  18. package/esm/src/filter/filter-interfaces.js +17 -17
  19. package/esm/src/live-query/LiveQueryClient.js +36 -11
  20. package/esm/src/live-query/SseSubscriptionClient.d.ts +1 -1
  21. package/esm/src/live-query/SseSubscriptionClient.js +1 -1
  22. package/{src/live-query/SubscriptionClient.d.ts → esm/src/live-query/SubscriptionChannel.d.ts} +8 -2
  23. package/esm/src/live-query/{SubscriptionClient.js → SubscriptionChannel.js} +12 -3
  24. package/esm/src/remult-proxy.js +24 -1
  25. package/esm/src/remult3/DecoratorReplacer.d.ts +1 -7
  26. package/esm/src/remult3/DecoratorReplacer.js +2 -25
  27. package/esm/src/remult3/RepositoryImplementation.d.ts +27 -41
  28. package/esm/src/remult3/RepositoryImplementation.js +100 -205
  29. package/esm/src/remult3/remult3.d.ts +46 -11
  30. package/esm/src/server-action.d.ts +1 -23
  31. package/esm/src/server-action.js +46 -83
  32. package/esm/src/shared-tests/db-tests.db-tests.js +18 -1
  33. package/esm/src/tests/testHelper.spec.js +1 -1
  34. package/esm/src/valueConverters.js +9 -2
  35. package/index.d.ts +4 -4
  36. package/index.js +3 -6
  37. package/live-query/ably.d.ts +1 -1
  38. package/package.json +2 -9
  39. package/postgres/schema-builder.js +15 -9
  40. package/remult-express.js +3 -3
  41. package/remult-knex/index.d.ts +1 -1
  42. package/remult-knex/index.js +15 -8
  43. package/server/expressBridge.d.ts +4 -3
  44. package/server/expressBridge.js +2 -1
  45. package/src/column-interfaces.d.ts +44 -8
  46. package/src/column.d.ts +2 -5
  47. package/src/column.js +12 -32
  48. package/src/context.d.ts +28 -20
  49. package/src/context.js +29 -15
  50. package/src/data-api.js +2 -2
  51. package/src/data-providers/rest-data-provider.js +1 -1
  52. package/src/data-providers/sql-database.js +2 -0
  53. package/src/filter/filter-interfaces.js +17 -17
  54. package/src/live-query/LiveQueryClient.js +38 -13
  55. package/src/live-query/SseSubscriptionClient.d.ts +1 -1
  56. package/src/live-query/SseSubscriptionClient.js +4 -4
  57. package/{esm/src/live-query/SubscriptionClient.d.ts → src/live-query/SubscriptionChannel.d.ts} +8 -2
  58. package/src/live-query/{SubscriptionClient.js → SubscriptionChannel.js} +13 -3
  59. package/src/remult-proxy.js +109 -2
  60. package/src/remult3/DecoratorReplacer.d.ts +1 -7
  61. package/src/remult3/DecoratorReplacer.js +4 -38
  62. package/src/remult3/RepositoryImplementation.d.ts +27 -41
  63. package/src/remult3/RepositoryImplementation.js +139 -298
  64. package/src/remult3/remult3.d.ts +46 -11
  65. package/src/server-action.d.ts +1 -23
  66. package/src/server-action.js +105 -179
  67. package/src/shared-tests/db-tests.db-tests.js +35 -1
  68. package/src/tests/testHelper.spec.js +1 -1
  69. package/src/valueConverters.js +9 -2
  70. package/esm/remult-zod.d.ts +0 -8
  71. package/esm/remult-zod.js +0 -50
  72. package/remult-zod.d.ts +0 -8
  73. package/remult-zod.js +0 -71
  74. package/src/backend-tests/backend-database-test-setup.backend-spec.d.ts +0 -5
  75. package/src/backend-tests/backend-database-test-setup.backend-spec.js +0 -231
  76. package/src/backend-tests/my-test.backend-spec.d.ts +0 -1
  77. package/src/backend-tests/my-test.backend-spec.js +0 -160
  78. package/src/backend-tests/test-http-server.backend-spec.d.ts +0 -6
  79. package/src/backend-tests/test-http-server.backend-spec.js +0 -342
package/esm/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- export { Field, Fields, FieldsMetadata, Entity, EntityBase, ControllerBase, FieldRef, IdFieldRef, FieldsRef, EntityMetadata, EntityOrderBy, EntityFilter, FindOptions, QueryResult, QueryOptions, Repository, FieldType, FindFirstOptions, ComparisonValueFilter, ValueFilter, IdFilter, ContainsStringValueFilter, getFields, EntityRef, getEntityRef, SortSegments, ValueListFieldType, getValueList, ValueListFieldOptions, ValueListInfo, OmitEB, Paginator, CaptionTransformer, InferMemberType, InferredType, MemberType as TypedDecorator, LiveQuery, LiveQueryChangeInfo } from './src/remult3';
2
- export { describeClass, createEntity, createClass } from './src/remult3/DecoratorReplacer';
1
+ export { Field, Fields, FieldsMetadata, Entity, EntityBase, ControllerBase, FieldRef, IdFieldRef, FieldsRef, EntityMetadata, EntityOrderBy, EntityFilter, FindOptions, QueryResult, QueryOptions, Repository, FieldType, FindFirstOptions, ComparisonValueFilter, ValueFilter, IdFilter, ContainsStringValueFilter, getFields, EntityRef, getEntityRef, SortSegments, ValueListFieldType, getValueList, ValueListFieldOptions, ValueListInfo, OmitEB, Paginator, CaptionTransformer, LiveQuery, LiveQueryChangeInfo } from './src/remult3';
3
2
  export { StringFieldOptions } from './src/remult3/RepositoryImplementation';
3
+ export { describeClass } from './src/remult3/DecoratorReplacer';
4
4
  export { EntityOptions } from './src/entity';
5
5
  export { DataProvider, EntityDataProvider, EntityDataProviderFindOptions, ErrorInfo, RestDataProviderHttpProvider } from './src/data-interfaces';
6
6
  export { SqlCommand, SqlImplementation, SqlResult } from './src/sql-command';
@@ -13,7 +13,7 @@ export { WebSqlDataProvider } from './src/data-providers/web-sql-data-provider';
13
13
  export { SqlDatabase, } from './src/data-providers/sql-database';
14
14
  export { CustomSqlFilterObject, CustomSqlFilterBuilder, dbNamesOf } from './src/filter/filter-consumer-bridge-to-sql-request';
15
15
  export { JsonDataProvider, JsonEntityStorage } from './src/data-providers/json-data-provider';
16
- export { Controller, BackendMethodOptions, BackendMethod, ProgressListener, createBackendMethod, CreateBackendMethodOptions, BackendMethodType, InferredMethodType, } from './src/server-action';
16
+ export { Controller, BackendMethodOptions, BackendMethod, ProgressListener } from './src/server-action';
17
17
  export { Allowed, Allow, Remult, RemultContext, ApiClient, isBackend, AllowedForInstance, EventDispatcher, EventSource, Unobserve, UserInfo } from './src/context';
18
18
  export { ExternalHttpProvider } from './src/buildRestDataProvider';
19
19
  export { IdEntity } from './src/id-entity';
@@ -25,4 +25,4 @@ export { Validators } from './src/validators';
25
25
  export { ValueConverters } from './src/valueConverters';
26
26
  export { remult } from './src/remult-proxy';
27
27
  export { SubscriptionServer, LiveQueryStorage, StoredQuery, InMemoryLiveQueryStorage } from "./src/live-query/SubscriptionServer";
28
- export { SubscriptionClientConnection, SubscriptionClient, SubscriptionChannel, LiveQueryChange, Unsubscribe } from './src/live-query/SubscriptionClient';
28
+ export { SubscriptionListener, SubscriptionClientConnection, SubscriptionClient, SubscriptionChannel, LiveQueryChange, Unsubscribe } from './src/live-query/SubscriptionChannel';
package/esm/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  * Public API Surface of remult
3
3
  */
4
4
  export { Field, Fields, Entity, EntityBase, ControllerBase, FieldType, getFields, getEntityRef, ValueListFieldType, getValueList, ValueListInfo, CaptionTransformer } from './src/remult3';
5
- export { describeClass, createEntity, createClass } from './src/remult3/DecoratorReplacer';
5
+ export { describeClass } from './src/remult3/DecoratorReplacer';
6
6
  export { RestDataProvider } from './src/data-providers/rest-data-provider'; //V
7
7
  export { InMemoryDataProvider } from './src/data-providers/in-memory-database'; //V
8
8
  export { ArrayEntityDataProvider } from './src/data-providers/array-entity-data-provider'; //V
@@ -11,7 +11,7 @@ export { SqlDatabase, } from './src/data-providers/sql-database'; //V
11
11
  export { CustomSqlFilterBuilder, dbNamesOf } from './src/filter/filter-consumer-bridge-to-sql-request';
12
12
  export { JsonDataProvider } from './src/data-providers/json-data-provider'; //V
13
13
  //export * from './src/data-api'; //reconsider if to make internal
14
- export { Controller, BackendMethod, ProgressListener, createBackendMethod, } from './src/server-action';
14
+ export { Controller, BackendMethod, ProgressListener } from './src/server-action';
15
15
  export { Allow, Remult, isBackend, EventSource } from './src/context';
16
16
  export { IdEntity } from './src/id-entity';
17
17
  export { Sort } from './src/sort';
@@ -23,4 +23,4 @@ export { ValueConverters } from './src/valueConverters';
23
23
  export { remult } from './src/remult-proxy';
24
24
  //export { getId } from './src/remult3/getId';
25
25
  export { InMemoryLiveQueryStorage } from "./src/live-query/SubscriptionServer";
26
- export { SubscriptionChannel } from './src/live-query/SubscriptionClient';
26
+ export { SubscriptionChannel } from './src/live-query/SubscriptionChannel';
@@ -1,6 +1,6 @@
1
1
  import type * as Ably from 'ably';
2
2
  import type { SubscriptionServer } from '../src/live-query/SubscriptionServer';
3
- import type { SubscriptionClient, SubscriptionClientConnection } from '../src/live-query/SubscriptionClient';
3
+ import type { SubscriptionClient, SubscriptionClientConnection } from '../src/live-query/SubscriptionChannel';
4
4
  export declare class AblySubscriptionClient implements SubscriptionClient {
5
5
  private ably;
6
6
  constructor(ably: Ably.Types.RealtimePromise);
@@ -43,7 +43,8 @@ export class PostgresSchemaBuilder {
43
43
  }
44
44
  }
45
45
  async verifyStructureOfAllEntities(remult) {
46
- console.log("start verify structure"); //keep me
46
+ if (PostgresSchemaBuilder.logToConsole)
47
+ console.time("Postgres Auto create tables and columns");
47
48
  for (const entityClass of allEntities) {
48
49
  let entity = remult.repo(entityClass).metadata;
49
50
  let e = await dbNamesOf(entity);
@@ -56,9 +57,11 @@ export class PostgresSchemaBuilder {
56
57
  }
57
58
  }
58
59
  catch (err) {
59
- console.log("failed verify structure of " + e.$entityName + " ", err);
60
+ console.error("failed verify structure of " + e.$entityName + " ", err);
60
61
  }
61
62
  }
63
+ if (PostgresSchemaBuilder.logToConsole)
64
+ console.timeEnd("Postgres Auto create tables and columns");
62
65
  }
63
66
  async createIfNotExist(entity) {
64
67
  var c = this.pool.createCommand();
@@ -81,7 +84,8 @@ export class PostgresSchemaBuilder {
81
84
  }
82
85
  }
83
86
  let sql = 'create table ' + e.$entityName + ' (' + result + '\r\n)';
84
- //console.log(sql);
87
+ if (PostgresSchemaBuilder.logToConsole)
88
+ console.info(sql);
85
89
  await this.pool.execute(sql);
86
90
  }
87
91
  });
@@ -97,7 +101,8 @@ export class PostgresSchemaBuilder {
97
101
  FROM information_schema.columns
98
102
  WHERE table_name=${cmd.addParameterAndReturnSqlToken((e.$entityName).toLocaleLowerCase())} and column_name=${cmd.addParameterAndReturnSqlToken((colName).toLocaleLowerCase())}` + this.additionalWhere)).rows.length == 0) {
99
103
  let sql = `alter table ${e.$entityName} add column ${postgresColumnSyntax(c(entity), colName)}`;
100
- //console.log(sql);
104
+ if (PostgresSchemaBuilder.logToConsole)
105
+ console.info(sql);
101
106
  await this.pool.execute(sql);
102
107
  }
103
108
  }
@@ -116,7 +121,8 @@ export class PostgresSchemaBuilder {
116
121
  if (!isDbReadonly(col, e))
117
122
  if (!cols.includes(e.$dbNameOf(col).toLocaleLowerCase())) {
118
123
  let sql = `alter table ${e.$entityName} add column ${postgresColumnSyntax(col, e.$dbNameOf(col))}`;
119
- //console.log(sql);
124
+ if (PostgresSchemaBuilder.logToConsole)
125
+ console.info(sql);
120
126
  await this.pool.execute(sql);
121
127
  }
122
128
  }
@@ -126,3 +132,5 @@ export class PostgresSchemaBuilder {
126
132
  }
127
133
  }
128
134
  }
135
+ //@internal
136
+ PostgresSchemaBuilder.logToConsole = true;
@@ -1,6 +1,6 @@
1
1
  import * as express from 'express';
2
2
  import { createRemultServer } from './server/index';
3
- import { liveQueryKeepAliveRoute, streamUrl } from './src/live-query/SubscriptionClient';
3
+ import { liveQueryKeepAliveRoute, streamUrl } from './src/live-query/SubscriptionChannel';
4
4
  import { v4 as uuid } from 'uuid';
5
5
  import { remult } from './src/remult-proxy';
6
6
  import { getEntityKey } from './src/remult3';
@@ -6,7 +6,7 @@ import { FieldMetadata } from '../src/column-interfaces';
6
6
  export declare class KnexDataProvider implements DataProvider {
7
7
  knex: Knex;
8
8
  constructor(knex: Knex);
9
- static getDb(remult?: Remult): Knex<any, Record<string, any>[]>;
9
+ static getDb(remult?: Remult): Knex<any, any[]>;
10
10
  getEntityDataProvider(entity: EntityMetadata<any>): EntityDataProvider;
11
11
  transaction(action: (dataProvider: DataProvider) => Promise<void>): Promise<void>;
12
12
  static rawFilter(build: CustomKnexFilterBuilderFunction): EntityFilter<any>;
@@ -277,7 +277,8 @@ export class KnexSchemaBuilder {
277
277
  this.additionalWhere = '';
278
278
  }
279
279
  async verifyStructureOfAllEntities(remult) {
280
- console.info("start verify structure");
280
+ if (KnexSchemaBuilder.logToConsole)
281
+ console.time("Knex Auto create tables and columns");
281
282
  for (const entity of allEntities) {
282
283
  let metadata = remult.repo(entity).metadata;
283
284
  try {
@@ -289,9 +290,11 @@ export class KnexSchemaBuilder {
289
290
  }
290
291
  }
291
292
  catch (err) {
292
- console.log("failed verify structure of " + await metadata.getDbName() + " ", err);
293
+ console.error("failed verify structure of " + await metadata.getDbName() + " ", err);
293
294
  }
294
295
  }
296
+ if (KnexSchemaBuilder.logToConsole)
297
+ console.timeEnd("Knex Auto create tables and columns");
295
298
  }
296
299
  async createIfNotExist(entity) {
297
300
  const e = await dbNamesOf(entity);
@@ -325,16 +328,16 @@ export class KnexSchemaBuilder {
325
328
  let col = c(entity);
326
329
  let colName = e.$dbNameOf(col);
327
330
  if (!await this.knex.schema.hasColumn(e.$entityName, colName)) {
328
- await this.knex.schema.alterTable(e.$entityName, b => {
331
+ await logSql(this.knex.schema.alterTable(e.$entityName, b => {
329
332
  buildColumn(col, colName, b);
330
- });
333
+ }));
331
334
  }
332
335
  }
333
336
  async verifyAllColumns(entity) {
334
337
  let e = await dbNamesOf(entity);
335
338
  try {
336
- for (const col of entity.fields) {
337
- if (isDbReadonly(col, e)) {
339
+ for (const col of entity.fields.toArray()) {
340
+ if (!isDbReadonly(col, e)) {
338
341
  await this.addColumnIfNotExist(entity, () => col);
339
342
  }
340
343
  }
@@ -344,6 +347,8 @@ export class KnexSchemaBuilder {
344
347
  }
345
348
  }
346
349
  }
350
+ //@internal
351
+ KnexSchemaBuilder.logToConsole = true;
347
352
  export function buildColumn(x, dbName, b) {
348
353
  if (x.valueType == Number) {
349
354
  if (!x.valueConverter.fieldTypeInDb) {
@@ -394,7 +399,8 @@ export function buildColumn(x, dbName, b) {
394
399
  }
395
400
  }
396
401
  function logSql(who) {
397
- //console.log(who.toSQL().sql);
402
+ if (KnexSchemaBuilder.logToConsole)
403
+ console.info(who.toSQL());
398
404
  return who;
399
405
  }
400
406
  export async function createKnexDataProvider(config, autoCreateTables = true) {
@@ -1,6 +1,6 @@
1
1
  import { queuedJobInfoResponse } from '../src/server-action';
2
2
  import { DataProvider } from '../src/data-interfaces';
3
- import { EntityInfoProvider, Remult, UserInfo } from '../src/context';
3
+ import { Remult, UserInfo } from '../src/context';
4
4
  import { ClassType } from '../classType';
5
5
  import { Repository } from '../src/remult3';
6
6
  import { IdEntity } from '../src/id-entity';
@@ -14,7 +14,7 @@ export interface RemultServerOptions<RequestType extends GenericRequest> {
14
14
  queueStorage?: QueueStorage;
15
15
  liveQueryStorage?: LiveQueryStorage;
16
16
  subscriptionServer?: SubscriptionServer;
17
- initRequest?: (remult: Remult, origReq: RequestType, options: InitRequestOptions) => Promise<void>;
17
+ initRequest?: (request: RequestType, options: InitRequestOptions) => Promise<void>;
18
18
  requestSerializer?: {
19
19
  toJson: (request: RequestType) => any;
20
20
  fromJson: (request: any) => RequestType;
@@ -23,12 +23,13 @@ export interface RemultServerOptions<RequestType extends GenericRequest> {
23
23
  initApi?: (remult: Remult) => void | Promise<void>;
24
24
  logApiEndPoints?: boolean;
25
25
  defaultGetLimit?: number;
26
- entities?: (ClassType<any> | EntityInfoProvider<any>)[];
26
+ entities?: ClassType<any>[];
27
27
  controllers?: ClassType<any>[];
28
28
  rootPath?: string;
29
29
  }
30
30
  export interface InitRequestOptions {
31
31
  liveQueryStorage: LiveQueryStorage;
32
+ readonly remult: Remult;
32
33
  }
33
34
  export declare function createRemultServerCore<RequestType extends GenericRequest = GenericRequest>(options?: RemultServerOptions<RequestType>): RemultServer;
34
35
  export declare type GenericRequestHandler = (req: GenericRequest, res: GenericResponse, next: VoidFunction) => void;
@@ -217,7 +217,8 @@ export class RemultServerImplementation {
217
217
  remult.user = (user);
218
218
  }
219
219
  if (this.options.initRequest) {
220
- await this.options.initRequest(remult, req, {
220
+ await this.options.initRequest(req, {
221
+ remult,
221
222
  get liveQueryStorage() {
222
223
  return remult.liveQueryStorage;
223
224
  },
@@ -2,7 +2,10 @@ import { ClassType } from '../classType';
2
2
  import { Allowed, AllowedForInstance } from './context';
3
3
  import { EntityMetadata, FieldRef } from './remult3';
4
4
  export interface FieldOptions<entityType = any, valueType = any> {
5
- /**A human readable name for the field */
5
+ /** A human readable name for the field. Can be used to achieve a consistent caption for a field throughout the app
6
+ * @example
7
+ * <input placeholder={taskRepo.metadata.fields.title.caption}/>
8
+ */
6
9
  caption?: string;
7
10
  /** If it can store null in the database */
8
11
  allowNull?: boolean;
@@ -32,14 +35,23 @@ export interface FieldOptions<entityType = any, valueType = any> {
32
35
  * }
33
36
  * })
34
37
  */
35
- validate?: ((entity: entityType, col: FieldRef<entityType, valueType>) => (any | Promise<any>)) | ((entity: entityType, col: FieldRef<entityType, valueType>) => (any | Promise<any>))[];
38
+ validate?: ((entity: entityType, fieldRef: FieldRef<entityType, valueType>) => (any | Promise<any>)) | ((entity: entityType, fieldRef: FieldRef<entityType, valueType>) => (any | Promise<any>))[];
36
39
  /** Will be fired before this field is saved to the server/database */
37
- saving?: ((entity: entityType, col: FieldRef<entityType, valueType>) => (any | Promise<any>));
40
+ saving?: ((entity: entityType, fieldRef: FieldRef<entityType, valueType>) => (any | Promise<any>));
38
41
  /** An expression that will determine this fields value on the backend and be provided to the front end*/
39
42
  serverExpression?: (entity: entityType) => valueType | Promise<valueType>;
40
43
  /** 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. */
41
44
  dbName?: string;
42
- /** Used or fields that are based on an sql expressions, instead of a physical table column */
45
+ /** Used or fields that are based on an sql expressions, instead of a physical table column
46
+ * @example
47
+ *
48
+ * @Fields.integer({
49
+ * sqlExpression:e=> 'length(title)'
50
+ * })
51
+ * titleLength = 0;
52
+ * @Fields.string()
53
+ * title='';
54
+ */
43
55
  sqlExpression?: string | ((entity: EntityMetadata<entityType>) => string | Promise<string>);
44
56
  /** For fields that shouldn't be part of an update or insert statement */
45
57
  dbReadOnly?: boolean;
@@ -62,18 +74,42 @@ export interface FieldOptions<entityType = any, valueType = any> {
62
74
  /** The key to be used for this field */
63
75
  key?: string;
64
76
  }
77
+ /**Metadata for a `Field`, this metadata can be used in the user interface to provide a richer UI experience */
65
78
  export interface FieldMetadata<valueType = any> {
79
+ /** The field's member name in an object.
80
+ * @example
81
+ * const taskRepo = remult.repo(Task);
82
+ * console.log(taskRepo.metadata.fields.title.key);
83
+ * // result: title
84
+ */
66
85
  readonly key: string;
67
- readonly target: ClassType<valueType>;
68
- readonly valueType: any;
86
+ /** A human readable caption for the field. Can be used to achieve a consistent caption for a field throughout the app
87
+ * @example
88
+ * <input placeholder={taskRepo.metadata.fields.title.caption}/>
89
+ */
69
90
  readonly caption: string;
91
+ /** The field's value type (number,string etc...) */
92
+ readonly valueType: any;
93
+ /** The options sent to this field's decorator */
94
+ readonly options: FieldOptions;
95
+ /** The `inputType` relevant for this field, determined by the options sent to it's decorator and the valueConverter in these options */
70
96
  readonly inputType: string;
97
+ /** if null is allowed for this field */
71
98
  readonly allowNull: boolean;
99
+ /** The class that contains this field
100
+ * @example
101
+ * const taskRepo = remult.repo(Task);
102
+ * Task == taskRepo.metadata.fields.title.target //will return true
103
+ */
104
+ readonly target: ClassType<valueType>;
105
+ /** Returns the dbName - based on it's `dbName` option and it's `sqlExpression` option */
72
106
  getDbName(): Promise<string>;
107
+ /** Indicates if this field is based on a server express */
73
108
  readonly isServerExpression: boolean;
109
+ /** indicates that this field should only be included in select statement, and excluded from update or insert. useful for db generated ids etc... */
74
110
  readonly dbReadOnly: boolean;
111
+ /** the Value converter for this field */
75
112
  readonly valueConverter: ValueConverter<valueType>;
76
- readonly options: FieldOptions;
77
113
  }
78
114
  export interface ValueConverter<valueType> {
79
115
  fromJson?(val: any): valueType;
@@ -86,7 +122,7 @@ export interface ValueConverter<valueType> {
86
122
  readonly fieldTypeInDb?: string;
87
123
  readonly inputType?: string;
88
124
  }
89
- export declare type FieldValidator<entityType = any, valueType = any> = (entity: entityType, col: FieldRef<entityType, valueType>) => void | Promise<void>;
125
+ export declare type FieldValidator<entityType = any, valueType = any> = (entity: entityType, fieldRef: FieldRef<entityType, valueType>) => void | Promise<void>;
90
126
  export declare type ValueOrExpression<valueType> = valueType | (() => valueType);
91
127
  export declare function valueOrExpressionToValue<valueType>(f: ValueOrExpression<valueType>): valueType;
92
128
  export interface ValueListItem {
@@ -25,15 +25,12 @@ export declare class CompoundIdField implements FieldMetadata<string> {
25
25
  }
26
26
  export declare class LookupColumn<T> {
27
27
  private repository;
28
- private _id;
28
+ id: idType<T>;
29
29
  setId(val: any): void;
30
30
  waitLoadOf(id: any): Promise<T>;
31
31
  get(id: any): any;
32
32
  set(item: T): void;
33
- constructor(repository: RepositoryImplementation<T>, _id: idType<T>);
34
- private _item;
35
- get id(): any;
36
- set id(value: any);
33
+ constructor(repository: RepositoryImplementation<T>, id: idType<T>);
37
34
  get item(): T;
38
35
  waitLoad(): Promise<T>;
39
36
  }
package/esm/src/column.js CHANGED
@@ -52,10 +52,9 @@ export class CompoundIdField {
52
52
  }
53
53
  }
54
54
  export class LookupColumn {
55
- constructor(repository, _id) {
55
+ constructor(repository, id) {
56
56
  this.repository = repository;
57
- this._id = _id;
58
- this._item = undefined;
57
+ this.id = id;
59
58
  }
60
59
  setId(val) {
61
60
  if (this.repository.metadata.idMetadata.field.valueType == Number)
@@ -69,54 +68,39 @@ export class LookupColumn {
69
68
  }
70
69
  get(id) {
71
70
  if (id === undefined || id === null)
72
- if (!this._item)
73
- return null;
74
- else
75
- return this._item;
71
+ return null;
76
72
  return this.repository.getCachedById(id);
77
73
  }
78
74
  set(item) {
79
- this._item = item;
80
75
  if (item) {
81
- if (typeof item === "string" || typeof item === "number") {
82
- this._id = item;
83
- this._item = undefined;
84
- }
76
+ if (typeof item === "string" || typeof item === "number")
77
+ this.id = item;
85
78
  else {
86
79
  let eo = getEntityRef(item, false);
87
80
  if (eo) {
88
81
  this.repository.addToCache(item);
89
- this._id = eo.getId();
82
+ this.id = eo.getId();
90
83
  }
91
84
  else {
92
- this._item = item;
93
- this._id = item[this.repository.metadata.idMetadata.field.key];
85
+ this.id = item[this.repository.metadata.idMetadata.field.key];
94
86
  }
95
87
  }
96
88
  }
97
89
  else if (item === null) {
98
- this._id = null;
90
+ this.id = null;
99
91
  }
100
92
  else {
101
- this._id = undefined;
93
+ this.id = undefined;
102
94
  }
103
95
  }
104
- get id() {
105
- return this._id;
106
- }
107
- set id(value) {
108
- this._id = value;
109
- this._item = undefined;
110
- }
111
96
  get item() {
112
- if (this._item)
113
- return this._item;
114
- return this.get(this._id);
97
+ return this.get(this.id);
115
98
  }
116
99
  async waitLoad() {
117
- return this.waitLoadOf(this._id);
100
+ return this.waitLoadOf(this.id);
118
101
  }
119
102
  }
103
+ 9000;
120
104
  export class OneToMany {
121
105
  constructor(provider, settings) {
122
106
  this.provider = provider;
@@ -3,28 +3,18 @@ import { EntityMetadata, EntityRef, FindOptions, Repository } from "./remult3";
3
3
  import { ClassType } from "../classType";
4
4
  import type { SubscriptionServer } from "./live-query/SubscriptionServer";
5
5
  import { ExternalHttpProvider } from "./buildRestDataProvider";
6
- import { SubscriptionClient } from "./live-query/SubscriptionClient";
7
- import { EntityOptions } from "./entity";
8
- import { FieldOptions } from "./column-interfaces";
6
+ import { SubscriptionClient } from "./live-query/SubscriptionChannel";
9
7
  export declare function isBackend(): boolean;
10
- export interface EntityInfoProvider<InstanceType> {
11
- $entity$key: string;
12
- $entity$getInfo(remult: Remult): EntityInfo<InstanceType>;
13
- }
14
- export interface EntityInfo<instanceType> {
15
- options: EntityOptions;
16
- fields: FieldOptions[];
17
- createInstance?(remult: Remult): instanceType;
18
- entityType?: any;
19
- }
20
8
  export declare class Remult {
21
9
  /**Return's a `Repository` of the specific entity type
22
10
  * @example
23
11
  * const taskRepo = remult.repo(Task);
24
12
  * @see [Repository](https://remult.dev/docs/ref_repository.html)
25
- *
13
+ * @param entity - the entity to use
14
+ * @param dataProvider - an optional alternative data provider to use. Useful for writing to offline storage or an alternative data provider
26
15
  */
27
- repo<T>(entity: (ClassType<T> | EntityInfoProvider<T>), dataProvider?: DataProvider): Repository<T>;
16
+ repo<T>(entity: ClassType<T>, dataProvider?: DataProvider): Repository<T>;
17
+ /** Returns the current user's info */
28
18
  user?: UserInfo;
29
19
  /** Checks if a user was authenticated */
30
20
  authenticated(): boolean;
@@ -40,6 +30,8 @@ export declare class Remult {
40
30
  * [Allowed](https://remult.dev/docs/allowed.html)
41
31
  */
42
32
  isAllowedForInstance(instance: any, allowed?: AllowedForInstance<any>): boolean;
33
+ /** The current data provider */
34
+ dataProvider: DataProvider;
43
35
  /** Creates a new instance of the `remult` object.
44
36
  *
45
37
  * Can receive either an HttpProvider or a DataProvider as a parameter - which will be used to fetch data from.
@@ -50,22 +42,38 @@ export declare class Remult {
50
42
  constructor(p: DataProvider);
51
43
  constructor();
52
44
  subscriptionServer?: SubscriptionServer;
45
+ /** Used to call a `backendMethod` using a specific `remult` object
46
+ * @example
47
+ * await remult.call(TasksController.setAll, undefined, true);
48
+ * @param backendMethod - the backend method to call
49
+ * @param classInstance - the class instance of the backend method, for static backend methods use undefined
50
+ * @param args - the arguments to send to the backend method
51
+ */
53
52
  call<T extends ((...args: any[]) => Promise<any>)>(backendMethod: T, classInstance?: any, ...args: GetArguments<T>): ReturnType<T>;
54
- /** The current data provider */
55
- dataProvider: DataProvider;
56
53
  /** A helper callback that can be used to debug and trace all find operations. Useful in debugging scenarios */
57
54
  static onFind: (metadata: EntityMetadata, options: FindOptions<any>) => void;
58
55
  clearAllCache(): any;
59
56
  /** A helper callback that is called whenever an entity is created. */
60
57
  static entityRefInit?: (ref: EntityRef<any>, row: any) => void;
58
+ /** context information that can be used to store custom information that will be disposed as part of the `remult` object */
61
59
  readonly context: RemultContext;
60
+ /** The api client that will be used by `remult` to perform calls to the `api` */
62
61
  apiClient: ApiClient;
63
62
  }
64
63
  export declare type GetArguments<T> = T extends (...args: infer FirstArgument) => any ? FirstArgument : never;
65
64
  export interface RemultContext {
66
65
  }
67
66
  export interface ApiClient {
67
+ /** The http client to use when making api calls.
68
+ * @example
69
+ * remult.apiClient.httpClient = axios;
70
+ * @example
71
+ * remult.apiClient.httpClient = httpClient;//angular http client
72
+ * @example
73
+ * remult.apiClient.httpClient = fetch; //this is the default
74
+ */
68
75
  httpClient?: ExternalHttpProvider | typeof fetch;
76
+ /** The base url to for making api calls */
69
77
  url?: string;
70
78
  subscriptionClient?: SubscriptionClient;
71
79
  wrapMessageHandling?: (x: VoidFunction) => void;
@@ -84,11 +92,11 @@ export interface UserInfo {
84
92
  name?: string;
85
93
  roles?: string[];
86
94
  }
87
- export declare type Allowed = boolean | string | string[] | ((c: Remult) => boolean);
88
- export declare type AllowedForInstance<T> = boolean | string | string[] | ((c: Remult, entity?: T) => boolean);
95
+ export declare type Allowed = boolean | string | string[] | ((c?: Remult) => boolean);
96
+ export declare type AllowedForInstance<T> = boolean | string | string[] | ((entity?: T, c?: Remult) => boolean);
89
97
  export declare class Allow {
90
98
  static everyone: () => boolean;
91
- static authenticated: (remult: Remult) => boolean;
99
+ static authenticated: (...args: any[]) => any;
92
100
  }
93
101
  export declare const queryConfig: {
94
102
  defaultPageSize: number;
@@ -1,6 +1,6 @@
1
1
  import { actionInfo, serverActionField } from './server-action';
2
2
  import { RestDataProvider } from './data-providers/rest-data-provider';
3
- import { createOldEntity, decorateColumnSettings, EntityFullInfo, getEntityKey, RepositoryImplementation } from "./remult3/RepositoryImplementation";
3
+ import { RepositoryImplementation } from "./remult3/RepositoryImplementation";
4
4
  import { LiveQueryClient } from "./live-query/LiveQueryClient";
5
5
  import { SseSubscriptionClient } from "./live-query/SseSubscriptionClient";
6
6
  import { RemultProxy } from "./remult-proxy";
@@ -10,17 +10,19 @@ export function isBackend() {
10
10
  }
11
11
  export class Remult {
12
12
  constructor(provider) {
13
+ /** The current data provider */
14
+ this.dataProvider = new RestDataProvider(() => this.apiClient);
13
15
  /* @internal */
14
16
  this.repCache = new Map();
15
17
  /* @internal*/
16
18
  this.liveQueryPublisher = {
17
19
  itemChanged: () => { }
18
20
  };
19
- /** The current data provider */
20
- this.dataProvider = new RestDataProvider(() => this.apiClient);
21
21
  /* @internal*/
22
22
  this.liveQuerySubscriber = new LiveQueryClient(() => this.apiClient);
23
+ /** context information that can be used to store custom information that will be disposed as part of the `remult` object */
23
24
  this.context = {};
25
+ /** The api client that will be used by `remult` to perform calls to the `api` */
24
26
  this.apiClient = {
25
27
  url: '/api',
26
28
  subscriptionClient: new SseSubscriptionClient()
@@ -50,7 +52,8 @@ export class Remult {
50
52
  * @example
51
53
  * const taskRepo = remult.repo(Task);
52
54
  * @see [Repository](https://remult.dev/docs/ref_repository.html)
53
- *
55
+ * @param entity - the entity to use
56
+ * @param dataProvider - an optional alternative data provider to use. Useful for writing to offline storage or an alternative data provider
54
57
  */
55
58
  repo(entity, dataProvider) {
56
59
  if (dataProvider === undefined)
@@ -60,18 +63,10 @@ export class Remult {
60
63
  this.repCache.set(dataProvider, dpCache = new Map());
61
64
  let r = dpCache.get(entity);
62
65
  if (!r) {
63
- const z = entity;
64
- if (z.$entity$getInfo) {
65
- let info = z.$entity$getInfo(this);
66
- info.fields.forEach(f => decorateColumnSettings(f, this));
67
- dpCache.set(entity, r = new RepositoryImplementation(new EntityFullInfo(info, getEntityKey(z), this), this, dataProvider));
68
- }
69
- else
70
- dpCache.set(entity, r = new RepositoryImplementation(createOldEntity(entity, this), this, dataProvider));
66
+ dpCache.set(entity, r = new RepositoryImplementation(entity, this, dataProvider));
71
67
  }
72
68
  return r;
73
69
  }
74
- /* delete me */
75
70
  /** Checks if a user was authenticated */
76
71
  authenticated() {
77
72
  return this.user?.id !== undefined;
@@ -117,12 +112,19 @@ export class Remult {
117
112
  }
118
113
  }
119
114
  else if (typeof (allowed) === "function") {
120
- return allowed(this, instance);
115
+ return allowed(instance, this);
121
116
  }
122
117
  else
123
118
  return this.isAllowed(allowed);
124
119
  }
125
120
  //@ts-ignore // type error of typescript regarding args that doesn't appear in my normal development
121
+ /** Used to call a `backendMethod` using a specific `remult` object
122
+ * @example
123
+ * await remult.call(TasksController.setAll, undefined, true);
124
+ * @param backendMethod - the backend method to call
125
+ * @param classInstance - the class instance of the backend method, for static backend methods use undefined
126
+ * @param args - the arguments to send to the backend method
127
+ */
126
128
  call(backendMethod, classInstance, ...args) {
127
129
  const z = (backendMethod[serverActionField]);
128
130
  if (!z.doWork)
@@ -161,7 +163,16 @@ export function setControllerSettings(target, options) {
161
163
  export class Allow {
162
164
  }
163
165
  Allow.everyone = () => true;
164
- Allow.authenticated = (remult) => remult.authenticated();
166
+ Allow.authenticated = (...args) => {
167
+ if (args.length > 1) {
168
+ return args[1].authenticated();
169
+ }
170
+ else if (args.length == 1) {
171
+ if (args[0].authenticated)
172
+ return args[0].authenticated();
173
+ }
174
+ return RemultProxy.defaultRemult.authenticated();
175
+ };
165
176
  export const queryConfig = {
166
177
  defaultPageSize: 200
167
178
  };
@@ -200,8 +200,8 @@ export class DataApi {
200
200
  response.forbidden();
201
201
  return;
202
202
  }
203
- await this.repository.getEntityRef(row).save();
204
- response.success(this.repository.getEntityRef(row).toApiJson());
203
+ await ref.save();
204
+ response.success(ref.toApiJson());
205
205
  });
206
206
  }
207
207
  async delete(response, id) {
@@ -225,7 +225,7 @@ export function addFilterToUrlAndReturnTrueIfSuccessful(filter, url) {
225
225
  if (Object.prototype.hasOwnProperty.call(filter, key)) {
226
226
  const element = filter[key];
227
227
  if (Array.isArray(element)) {
228
- if (key.endsWith("_in"))
228
+ if (key.endsWith(".in"))
229
229
  url.add(key, JSON.stringify(element));
230
230
  else
231
231
  element.forEach(e => url.add(key, e));