remult 0.23.0-exp.2 → 0.23.0-exp.21

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 (92) hide show
  1. package/README.md +26 -27
  2. package/esm/graphql.js +7 -1
  3. package/esm/index.d.ts +16 -3
  4. package/esm/index.js +17 -2
  5. package/esm/internals.d.ts +2 -1
  6. package/esm/internals.js +1 -1
  7. package/esm/remult-express.js +1 -1
  8. package/esm/remult-knex/index.js +2 -1
  9. package/esm/remult-mongo.js +2 -1
  10. package/esm/server/JsonEntityFileStorage.js +1 -1
  11. package/esm/server/expressBridge.js +1 -1
  12. package/esm/src/CompoundIdField.d.ts +1 -1
  13. package/esm/src/CompoundIdField.js +3 -1
  14. package/esm/src/buildRestDataProvider.d.ts +1 -2
  15. package/esm/src/column-interfaces.d.ts +19 -7
  16. package/esm/src/column.d.ts +4 -18
  17. package/esm/src/column.js +10 -44
  18. package/esm/src/context.d.ts +1 -1
  19. package/esm/src/context.js +5 -1
  20. package/esm/src/data-interfaces.js +1 -2
  21. package/esm/src/data-providers/array-entity-data-provider.d.ts +1 -1
  22. package/esm/src/data-providers/array-entity-data-provider.js +6 -6
  23. package/esm/src/data-providers/sql-database.js +2 -1
  24. package/esm/src/data-providers/web-sql-data-provider.js +3 -3
  25. package/esm/src/entity.d.ts +48 -17
  26. package/esm/src/filter/filter-interfaces.d.ts +2 -16
  27. package/esm/src/filter/filter-interfaces.js +87 -6
  28. package/esm/src/live-query/LiveQueryClient.js +2 -1
  29. package/esm/src/live-query/SubscriptionChannel.js +4 -3
  30. package/esm/src/remult-proxy.js +10 -2
  31. package/esm/src/remult3/Fields.d.ts +140 -21
  32. package/esm/src/remult3/Fields.js +26 -30
  33. package/esm/src/remult3/RepositoryImplementation.d.ts +10 -16
  34. package/esm/src/remult3/RepositoryImplementation.js +165 -48
  35. package/esm/src/remult3/entity.d.ts +1 -1
  36. package/esm/src/remult3/entity.js +0 -1
  37. package/esm/src/remult3/getEntityRef.d.ts +1 -1
  38. package/esm/src/remult3/getEntityRef.js +1 -1
  39. package/esm/src/remult3/relation-loader.js +4 -1
  40. package/esm/src/remult3/remult3.d.ts +132 -7
  41. package/esm/src/remult3/remult3.js +30 -0
  42. package/esm/src/remult3/repository-internals.d.ts +14 -0
  43. package/esm/src/remult3/repository-internals.js +7 -0
  44. package/esm/src/server-action.js +1 -1
  45. package/esm/src/sort.d.ts +3 -3
  46. package/esm/src/sort.js +36 -8
  47. package/graphql.js +10 -2
  48. package/index.d.ts +16 -3
  49. package/index.js +19 -3
  50. package/internals.d.ts +2 -1
  51. package/internals.js +3 -1
  52. package/package.json +1 -1
  53. package/remult-express.js +1 -1
  54. package/remult-knex/index.js +2 -1
  55. package/remult-mongo.js +2 -1
  56. package/server/JsonEntityFileStorage.js +1 -1
  57. package/server/expressBridge.js +1 -1
  58. package/src/CompoundIdField.d.ts +1 -1
  59. package/src/CompoundIdField.js +3 -0
  60. package/src/buildRestDataProvider.d.ts +1 -2
  61. package/src/column-interfaces.d.ts +19 -7
  62. package/src/column.d.ts +4 -18
  63. package/src/column.js +10 -56
  64. package/src/context.d.ts +1 -1
  65. package/src/context.js +5 -1
  66. package/src/data-interfaces.js +1 -2
  67. package/src/data-providers/array-entity-data-provider.d.ts +1 -1
  68. package/src/data-providers/array-entity-data-provider.js +5 -6
  69. package/src/data-providers/sql-database.js +2 -1
  70. package/src/data-providers/web-sql-data-provider.js +3 -3
  71. package/src/entity.d.ts +48 -17
  72. package/src/filter/filter-interfaces.d.ts +2 -16
  73. package/src/filter/filter-interfaces.js +101 -9
  74. package/src/live-query/LiveQueryClient.js +2 -1
  75. package/src/live-query/SubscriptionChannel.js +4 -3
  76. package/src/remult-proxy.js +43 -29
  77. package/src/remult3/Fields.d.ts +140 -21
  78. package/src/remult3/Fields.js +32 -32
  79. package/src/remult3/RepositoryImplementation.d.ts +10 -16
  80. package/src/remult3/RepositoryImplementation.js +286 -163
  81. package/src/remult3/entity.d.ts +1 -1
  82. package/src/remult3/entity.js +0 -1
  83. package/src/remult3/getEntityRef.d.ts +1 -1
  84. package/src/remult3/getEntityRef.js +2 -1
  85. package/src/remult3/relation-loader.js +4 -1
  86. package/src/remult3/remult3.d.ts +132 -7
  87. package/src/remult3/remult3.js +30 -0
  88. package/src/remult3/repository-internals.d.ts +14 -0
  89. package/src/remult3/repository-internals.js +11 -0
  90. package/src/server-action.js +1 -1
  91. package/src/sort.d.ts +3 -3
  92. package/src/sort.js +43 -11
@@ -23,11 +23,56 @@ export interface EntityRef<entityType> extends Subscribable {
23
23
  metadata: EntityMetadata<entityType>;
24
24
  toApiJson(): any;
25
25
  validate(): Promise<ErrorInfo<entityType> | undefined>;
26
+ relations: RepositoryRelations<entityType>;
26
27
  readonly apiUpdateAllowed: boolean;
27
28
  readonly apiDeleteAllowed: boolean;
28
29
  readonly apiInsertAllowed: boolean;
29
30
  readonly isLoading: boolean;
30
31
  }
32
+ /**
33
+ * Represents a lifecycle event associated with an entity instance. These events
34
+ * are triggered during various stages of the entity's lifecycle, such as validation,
35
+ * saving, saved, deleting, and deleted.
36
+ *
37
+ * @template entityType The type of the entity associated with the event.
38
+ * @see [Entity Lifecycle Hooks](http://remult.dev/docs/lifecycle-hooks)
39
+ */
40
+ export interface LifecycleEvent<entityType> {
41
+ /**
42
+ * Indicates whether the entity is new or existing.
43
+ */
44
+ isNew: boolean;
45
+ /**
46
+ * A reference to the fields of the entity, providing access to its properties.
47
+ */
48
+ fields: FieldsRef<entityType>;
49
+ /**
50
+ * The ID of the entity.
51
+ */
52
+ id: idType<entityType>;
53
+ /**
54
+ * The original ID of the entity, useful for tracking changes.
55
+ */
56
+ originalId: idType<entityType>;
57
+ /**
58
+ * The repository associated with the entity, providing access to repository methods.
59
+ */
60
+ repository: Repository<entityType>;
61
+ /**
62
+ * Metadata describing the entity's structure and configuration.
63
+ */
64
+ metadata: EntityMetadata<entityType>;
65
+ /**
66
+ * A function that can be used to prevent the default behavior associated with
67
+ * the lifecycle event.
68
+ */
69
+ preventDefault: VoidFunction;
70
+ /**
71
+ * A reference to the repository relations associated with the entity, providing
72
+ * access to related entities and their data.
73
+ */
74
+ relations: RepositoryRelations<entityType>;
75
+ }
31
76
  export interface ControllerRef<entityType> extends Subscribable {
32
77
  hasErrors(): boolean;
33
78
  fields: FieldsRef<entityType>;
@@ -44,7 +89,7 @@ export interface Subscribable {
44
89
  subscribe(listener: RefSubscriber): Unsubscribe;
45
90
  }
46
91
  export type FieldsRef<entityType> = {
47
- [Properties in keyof OmitEB<entityType>]: entityType[Properties] extends {
92
+ [Properties in keyof OmitEB<entityType>]: NonNullable<entityType[Properties]> extends {
48
93
  id?: number | string;
49
94
  } ? IdFieldRef<entityType, entityType[Properties]> : FieldRef<entityType, entityType[Properties]>;
50
95
  } & {
@@ -301,7 +346,7 @@ export declare type EntityOrderBy<entityType> = {
301
346
  export declare type EntityFilter<entityType> = {
302
347
  [Properties in keyof Partial<OmitEB<entityType>>]?: (Partial<OmitEB<entityType>>[Properties] extends number | Date | undefined ? ComparisonValueFilter<Partial<OmitEB<entityType>>[Properties]> : Partial<OmitEB<entityType>>[Properties] extends string | undefined ? ContainsStringValueFilter & ComparisonValueFilter<string> : Partial<OmitEB<entityType>>[Properties] extends boolean | undefined ? ValueFilter<boolean> : Partial<OmitEB<entityType>>[Properties] extends {
303
348
  id?: string | number;
304
- } | undefined ? IdFilter<Partial<OmitEB<entityType>>[Properties]> : ValueFilter<Partial<OmitEB<entityType>>[Properties]>) & ContainsStringValueFilter;
349
+ } | undefined ? IdFilter<Partial<OmitEB<entityType>>[Properties]> : ValueFilter<Partial<OmitEB<entityType>>[Properties]>) | ContainsStringValueFilter;
305
350
  } & {
306
351
  $or?: EntityFilter<entityType>[];
307
352
  $and?: EntityFilter<entityType>[];
@@ -331,7 +376,46 @@ export type IdFilter<valueType> = ValueFilter<valueType> | {
331
376
  } ? number : string>;
332
377
  };
333
378
  export interface LoadOptions<entityType> {
379
+ /**
380
+ * @deprecated The 'load' option is deprecated and will be removed in future versions.
381
+ * Use 'Relations.toOne' along with the 'include' option instead.
382
+ *
383
+ * Example usage:
384
+ * ```
385
+ * // Deprecated usage with 'load' option
386
+ * await remult.repo(Order).find({
387
+ * load: (o) => [o.customer],
388
+ * });
389
+ *
390
+ *
391
+ * // Preferred usage with 'Relations.toOne' and 'include' option
392
+ * await remult.repo(Order).find({
393
+ * include: { customer: true },
394
+ * });
395
+ * ```
396
+ */
334
397
  load?: (entity: FieldsMetadata<entityType>) => FieldMetadata[];
398
+ /**
399
+ * An option used in the `find` and `findFirst` methods to specify which related entities should be included
400
+ * when querying the source entity. It allows you to eagerly load related data to avoid N+1 query problems.
401
+ *
402
+ * @param include An object specifying the related entities to include, their options, and filtering criteria.
403
+ *
404
+ * Example usage:
405
+ * ```
406
+ * const orders = await customerRepo.find({
407
+ * include: {
408
+ * // Include the 'tags' relation for each customer.
409
+ * tags: true,
410
+ * },
411
+ * });
412
+ * ```
413
+ * In this example, the `tags` relation for each customer will be loaded and included in the query result.
414
+ *
415
+ * @see {@link Relations.toMany}
416
+ * @see {@link Relations.toOne}
417
+ * @see {@link RelationOptions}
418
+ */
335
419
  include?: MembersToInclude<entityType>;
336
420
  }
337
421
  export interface FindOptionsBase<entityType> extends LoadOptions<entityType> {
@@ -402,26 +486,67 @@ export interface RelationInfo {
402
486
  toType: () => any;
403
487
  type: 'reference' | 'toOne' | 'toMany';
404
488
  }
489
+ /**
490
+ * Options for configuring a relation between entities.
491
+ *
492
+ * @template fromEntity The type of the source entity (the entity defining the relation).
493
+ * @template toEntity The type of the target entity (the related entity).
494
+ * @template matchIdEntity The type used for matching IDs in the relation.
495
+ * @template optionsType The type of find options to apply to the relation (default is FindOptionsBase<toEntity>).
496
+ */
405
497
  export type RelationOptions<fromEntity, toEntity, matchIdEntity, optionsType extends FindOptionsBase<toEntity> = FindOptionsBase<toEntity>> = {
498
+ /**
499
+ * An object specifying custom field names for the relation.
500
+ * Each key represents a field in the related entity, and its value is the corresponding field in the source entity.
501
+ * For example, `{ customerId: 'id' }` maps the 'customerId' field in the related entity to the 'id' field in the source entity.
502
+ * This is useful when you want to define custom field mappings for the relation.
503
+ */
406
504
  fields?: {
407
505
  [K in keyof toEntity]?: keyof fromEntity;
408
506
  };
507
+ /**
508
+ * The name of the field for this relation.
509
+ */
409
510
  field?: keyof matchIdEntity;
410
- } & RelationOptionsBase<fromEntity, toEntity, optionsType>;
411
- export type RelationOptionsBase<fromEntity, toEntity, optionsType extends LoadOptions<toEntity> = LoadOptions<toEntity>> = {
511
+ /**
512
+ * Find options to apply to the relation when fetching related entities.
513
+ * You can specify a predefined set of find options or provide a function that takes the source entity
514
+ * and returns find options dynamically.
515
+ * These options allow you to customize how related entities are retrieved.
516
+ */
412
517
  findOptions?: optionsType | ((entity: fromEntity) => optionsType);
518
+ /**
519
+ * Determines whether the relation should be included by default when querying the source entity.
520
+ * When set to true, related entities will be automatically included when querying the source entity.
521
+ * If false or not specified, related entities will need to be explicitly included using the `include` option.
522
+ */
413
523
  defaultIncluded?: boolean;
414
- } & FieldOptions<fromEntity, toEntity>;
524
+ } & Pick<FieldOptions, 'caption'>;
415
525
  export type ObjectMembersOnly<T> = {
416
526
  [K in keyof Pick<T, {
417
527
  [K in keyof T]: T[K] extends object | undefined | null ? T[K] extends Date | undefined | null ? never : K : never;
418
528
  }[keyof T]>]: T[K];
419
529
  };
420
530
  export type MembersToInclude<T> = {
421
- [K in keyof ObjectMembersOnly<T>]?: true | (T[K] extends Array<any> ? FindOptions<T[K][number]> : FindFirstOptions<T[K]>);
531
+ [K in keyof ObjectMembersOnly<T>]?: boolean | (NonNullable<T[K]> extends Array<any> ? FindOptions<NonNullable<T[K]>[number]> : FindFirstOptions<NonNullable<T[K]>>);
422
532
  };
423
533
  export type RepositoryRelations<entityType> = {
424
- [K in keyof ObjectMembersOnly<entityType>]: entityType[K] extends Array<infer R> ? Repository<R> : entityType[K] extends infer R ? {
534
+ [K in keyof ObjectMembersOnly<entityType>]-?: NonNullable<entityType[K]> extends Array<infer R> ? Repository<R> : entityType[K] extends infer R ? {
425
535
  findOne: (options?: FindOptionsBase<R>) => Promise<R>;
426
536
  } : never;
427
537
  };
538
+ export declare type EntityIdFields<entityType> = {
539
+ [Properties in keyof Partial<OmitEB<entityType>>]?: true;
540
+ };
541
+ export interface ClassFieldDecoratorContextStub<entityType, valueType> {
542
+ readonly access: {
543
+ set(object: entityType, value: valueType): void;
544
+ };
545
+ readonly name: string;
546
+ }
547
+ export interface ClassDecoratorContextStub<Class extends new (...args: any) => any = new (...args: any) => any> {
548
+ readonly kind: 'class';
549
+ readonly name: string | undefined;
550
+ addInitializer(initializer: (this: Class) => void): void;
551
+ }
552
+ export type ClassFieldDecorator<entityType, valueType> = (target: any, context: string | ClassFieldDecoratorContextStub<entityType, valueType | undefined>, c?: any) => void;
@@ -1 +1,31 @@
1
1
  export {};
2
+ //p1 - include relations in the api docs
3
+ //p1 - include Relation options in the api docs
4
+ //p1 - fix { allowApiRead: r => r.user.name === 'superman' } } in allowed for instace docs
5
+ //p1 - fix seeallowed in ref_entity
6
+ //p1 - write doc about controlling updates of rows...
7
+ //p1 - 'eventId' autocomplete in task app did not work
8
+ //p1 - need a way to extract the fields from the relation - for generating relation based sql
9
+ //p1 - remult object was used outside context
10
+ // ```
11
+ // sqlExpression: async (e) => {
12
+ // const v = await dbNamesOf(volunteerInTask)
13
+ // return `select true from ${v} where ${
14
+ // v.task
15
+ // }=${await e.getDbName()}.${await e.fields.id.getDbName()} and ${SqlDatabase.filterToRaw<volunteerInTask>(
16
+ // repo(volunteerInTask),
17
+ // {
18
+ // canceled: false,
19
+ // }
20
+ // )}`
21
+ // },
22
+ // })
23
+ // ```
24
+ //p2 - consider includeInApi as AllowedForInstance
25
+ //p1 - why didn't this._.relations.statusChanges.insert({})work?
26
+ //p1 - active record with include thinks that the row was change!
27
+ //p1 - add docs for apply changes
28
+ //p1 - update related field with null should respect it's allowed null - otherwise we get a null error for that field.
29
+ //p1 - when the include doesn't find the many to one - it deletes the id!!!
30
+ //y1 - discuss a default date formatter
31
+ //p1 - consider using this in saving etc...
@@ -0,0 +1,14 @@
1
+ import type { EntityDataProviderFindOptions } from '../data-interfaces';
2
+ import type { Filter } from '../filter/filter-interfaces';
3
+ import type { EntityFilter, EntityOrderBy, FindOptions, LoadOptions, Repository } from './remult3';
4
+ export interface RepositoryInternal<entityType> {
5
+ createAfterFilter(orderBy: EntityOrderBy<entityType>, lastRow: entityType): Promise<EntityFilter<entityType>>;
6
+ fromJsonArray(jsonItems: any[], loadOptions: LoadOptions<entityType>): Promise<entityType[]>;
7
+ buildEntityDataProviderFindOptions(options: FindOptions<entityType>): Promise<EntityDataProviderFindOptions>;
8
+ translateWhereToFilter(where: EntityFilter<entityType>): Promise<Filter>;
9
+ getCachedById(id: any, doNotLoadIfNotFound: boolean): entityType;
10
+ getCachedByIdAsync(id: any, doNotLoadIfNotFound: boolean): Promise<entityType>;
11
+ addToCache(item: entityType): any;
12
+ }
13
+ export declare function getRepositoryInternals<entityType>(repo: Repository<entityType>): RepositoryInternal<entityType>;
14
+ export declare const getInternalKey = "getInternal";
@@ -0,0 +1,7 @@
1
+ export function getRepositoryInternals(repo) {
2
+ const x = repo;
3
+ if (typeof x[getInternalKey] === 'function')
4
+ return x[getInternalKey]();
5
+ throw Error('Error getting repository internal from ' + repo);
6
+ }
7
+ export const getInternalKey = 'getInternal';
@@ -268,7 +268,7 @@ export function BackendMethod(options) {
268
268
  id: defs.getOriginalId(),
269
269
  },
270
270
  }, baseUrl, http);
271
- await defs._updateEntityBasedOnApi(r.rowInfo.data);
271
+ await defs._updateEntityBasedOnApi(r.rowInfo.data, true);
272
272
  return r.result;
273
273
  }
274
274
  catch (err) {
package/esm/src/sort.d.ts CHANGED
@@ -6,9 +6,9 @@ export declare class Sort {
6
6
  Segments: SortSegment[];
7
7
  reverse(): Sort;
8
8
  compare(a: any, b: any, getFieldKey?: (field: FieldMetadata) => string): number;
9
- static translateOrderByToSort<T>(entityDefs: EntityMetadata<T>, orderBy: EntityOrderBy<T>): Sort;
10
- static createUniqueSort<T>(entityMetadata: EntityMetadata<T>, orderBy: Sort): Sort;
11
- static createUniqueEntityOrderBy<T>(entityMetadata: EntityMetadata<T>, orderBy: EntityOrderBy<T>): EntityOrderBy<T>;
9
+ static translateOrderByToSort<T>(entityDefs: EntityMetadata<T>, orderBy?: EntityOrderBy<T>): Sort;
10
+ static createUniqueSort<T>(entityMetadata: EntityMetadata<T>, orderBy?: Sort): Sort;
11
+ static createUniqueEntityOrderBy<T>(entityMetadata: EntityMetadata<T>, orderBy?: EntityOrderBy<T>): EntityOrderBy<T>;
12
12
  }
13
13
  export interface SortSegment {
14
14
  field: FieldMetadata;
package/esm/src/sort.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { getRelationInfo } from '../internals';
1
2
  import { CompoundIdField } from './CompoundIdField';
2
3
  export class Sort {
3
4
  toEntityOrderBy() {
@@ -28,8 +29,8 @@ export class Sort {
28
29
  let r = 0;
29
30
  for (let i = 0; i < this.Segments.length; i++) {
30
31
  let seg = this.Segments[i];
31
- let left = a[getFieldKey(seg.field)];
32
- let right = b[getFieldKey(seg.field)];
32
+ let left = fixValueForSort(a[getFieldKey(seg.field)]);
33
+ let right = fixValueForSort(b[getFieldKey(seg.field)]);
33
34
  if (left > right)
34
35
  r = 1;
35
36
  else if (left < right)
@@ -45,14 +46,13 @@ export class Sort {
45
46
  static translateOrderByToSort(entityDefs, orderBy) {
46
47
  if (!orderBy)
47
48
  return undefined;
48
- let sort;
49
- if (orderBy) {
50
- sort = new Sort();
49
+ let sort = new Sort();
50
+ if (orderBy)
51
51
  for (const key in orderBy) {
52
52
  if (Object.prototype.hasOwnProperty.call(orderBy, key)) {
53
53
  const element = orderBy[key];
54
54
  let field = entityDefs.fields.find(key);
55
- if (field) {
55
+ const addSegment = (field) => {
56
56
  switch (element) {
57
57
  case 'desc':
58
58
  sort.Segments.push({ field, isDescending: true });
@@ -60,14 +60,35 @@ export class Sort {
60
60
  case 'asc':
61
61
  sort.Segments.push({ field });
62
62
  }
63
+ };
64
+ if (field) {
65
+ const rel = getRelationInfo(field.options);
66
+ const op = field.options;
67
+ if (rel?.type === 'toOne') {
68
+ if (typeof op.field === 'string') {
69
+ addSegment(entityDefs.fields.find(op.field));
70
+ }
71
+ else {
72
+ if (op.fields) {
73
+ for (const key in op.fields) {
74
+ if (Object.prototype.hasOwnProperty.call(op.fields, key)) {
75
+ const keyInMyEntity = op.fields[key];
76
+ addSegment(entityDefs.fields.find(keyInMyEntity.toString()));
77
+ }
78
+ }
79
+ }
80
+ }
81
+ }
82
+ else
83
+ addSegment(field);
63
84
  }
64
85
  }
65
86
  }
66
- }
67
87
  return sort;
68
88
  }
69
89
  static createUniqueSort(entityMetadata, orderBy) {
70
- if (!orderBy || Object.keys(orderBy).length === 0)
90
+ if ((!orderBy || Object.keys(orderBy).length === 0) &&
91
+ entityMetadata.options.defaultOrderBy)
71
92
  orderBy = Sort.translateOrderByToSort(entityMetadata, entityMetadata.options.defaultOrderBy);
72
93
  if (!orderBy)
73
94
  orderBy = new Sort({ field: entityMetadata.idMetadata.field });
@@ -105,3 +126,10 @@ export class Sort {
105
126
  return orderBy;
106
127
  }
107
128
  }
129
+ function fixValueForSort(a) {
130
+ if (a == undefined || a == null)
131
+ return a;
132
+ if (a.id !== undefined)
133
+ return a.id;
134
+ return a;
135
+ }
package/graphql.js CHANGED
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.translateWhereToRestBody = exports.remultGraphql = void 0;
4
4
  var tslib_1 = require("tslib");
5
+ var internals_1 = require("./internals");
5
6
  var index_1 = require("./index");
6
7
  var data_api_1 = require("./src/data-api");
7
8
  var v2ConnectionAndPagination = false;
@@ -522,6 +523,11 @@ function remultGraphql(options) {
522
523
  }
523
524
  var whereTypeFields = [];
524
525
  var _loop_2 = function (f) {
526
+ var ri = (0, internals_1.getRelationInfo)(f.options);
527
+ // let's not consider toMany relations for now
528
+ if ((ri === null || ri === void 0 ? void 0 : ri.type) === 'toMany') {
529
+ return "break";
530
+ }
525
531
  if (f.options.includeInApi === false)
526
532
  return "continue";
527
533
  var type = 'String';
@@ -634,7 +640,9 @@ function remultGraphql(options) {
634
640
  try {
635
641
  for (var _s = (e_6 = void 0, tslib_1.__values(meta.fields)), _t = _s.next(); !_t.done; _t = _s.next()) {
636
642
  var f = _t.value;
637
- _loop_2(f);
643
+ var state_1 = _loop_2(f);
644
+ if (state_1 === "break")
645
+ break;
638
646
  }
639
647
  }
640
648
  catch (e_6_1) { e_6 = { error: e_6_1 }; }
@@ -900,7 +908,7 @@ function translateWhereToRestBody(fields, _a) {
900
908
  var result = {};
901
909
  var _loop_3 = function (field) {
902
910
  var e_8, _c;
903
- if (field.includedInApi === false)
911
+ if (field.options.includeInApi === false)
904
912
  return "continue";
905
913
  var condition = where[field.key];
906
914
  if (condition) {
package/index.d.ts CHANGED
@@ -1,8 +1,9 @@
1
- export { OmitEB, FieldsMetadata, FieldRef, IdFieldRef, FieldsRef, EntityMetadata, EntityOrderBy, EntityFilter, FindOptions, QueryResult, QueryOptions, Repository, FindFirstOptions, ComparisonValueFilter, ValueFilter, IdFilter, ContainsStringValueFilter, EntityRef, SortSegments, Paginator, LiveQuery, LiveQueryChangeInfo, Subscribable, RefSubscriber, RefSubscriberBase, RelationOptions, RelationOptionsBase, ObjectMembersOnly, MembersToInclude, RepositoryRelations, } from './src/remult3/remult3';
1
+ import type { ClassType } from './classType';
2
+ export { OmitEB, FieldsMetadata, FieldRef, IdFieldRef, FieldsRef, EntityMetadata, EntityOrderBy, EntityFilter, FindOptions, QueryResult, QueryOptions, Repository, FindFirstOptions, ComparisonValueFilter, ValueFilter, IdFilter, ContainsStringValueFilter, EntityRef, SortSegments, Paginator, LiveQuery, LiveQueryChangeInfo, Subscribable, RefSubscriber, RefSubscriberBase, RelationOptions, ObjectMembersOnly, MembersToInclude, RepositoryRelations, EntityIdFields, ClassFieldDecorator as MemberDecorator, ClassFieldDecoratorContextStub, } from './src/remult3/remult3';
2
3
  export { EntityBase, ControllerBase, FieldType, getFields, ValueListFieldType, getValueList, ValueListFieldOptions, ValueListInfo, CaptionTransformer, } from './src/remult3/RepositoryImplementation';
3
4
  export { Entity } from './src/remult3/entity';
4
5
  export { getEntityRef } from './src/remult3/getEntityRef';
5
- export { Field, Fields, StringFieldOptions } from './src/remult3/Fields';
6
+ export { Field, Fields, StringFieldOptions, Relations, } from './src/remult3/Fields';
6
7
  export { IdEntity } from './src/remult3/IdEntity';
7
8
  export { describeClass } from './src/remult3/DecoratorReplacer';
8
9
  export { EntityOptions } from './src/entity';
@@ -21,7 +22,6 @@ export { Controller, BackendMethodOptions, BackendMethod, ProgressListener, } fr
21
22
  export { Allowed, Allow, Remult, RemultContext, ApiClient, isBackend, AllowedForInstance, EventDispatcher, EventSource, UserInfo, } from './src/context';
22
23
  export { ExternalHttpProvider } from './src/buildRestDataProvider';
23
24
  export { SortSegment, Sort } from './src/sort';
24
- export { OneToMany } from './src/column';
25
25
  export { CompoundIdField } from './src/CompoundIdField';
26
26
  export { Filter } from './src/filter/filter-interfaces';
27
27
  export { UrlBuilder } from './urlBuilder';
@@ -30,3 +30,16 @@ export { ValueConverters } from './src/valueConverters';
30
30
  export { remult } from './src/remult-proxy';
31
31
  export { SubscriptionServer, LiveQueryStorage, StoredQuery, InMemoryLiveQueryStorage, } from './src/live-query/SubscriptionServer';
32
32
  export { SubscriptionListener, SubscriptionClientConnection, SubscriptionClient, SubscriptionChannel, LiveQueryChange, Unsubscribe, } from './src/live-query/SubscriptionChannel';
33
+ /**
34
+ * A convenient shortcut function to quickly obtain a repository for a specific entity type in Remult.
35
+ *
36
+ * @param entity The entity class type for which you want to get a repository.
37
+ * @returns A repository instance for the specified entity type.
38
+ *
39
+ * Example usage:
40
+ * ```ts
41
+ * await repo(Task).find()
42
+ * await repo(Customer).insert()
43
+ * ```
44
+ */
45
+ export declare function repo<entityType>(entity: ClassType<entityType>): import("./src/remult3/remult3").Repository<entityType>;
package/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SubscriptionChannel = exports.InMemoryLiveQueryStorage = exports.remult = exports.ValueConverters = exports.Validators = exports.UrlBuilder = exports.Filter = exports.CompoundIdField = exports.OneToMany = exports.Sort = exports.EventSource = exports.isBackend = exports.Remult = exports.Allow = exports.ProgressListener = exports.BackendMethod = exports.Controller = exports.JsonDataProvider = exports.dbNamesOf = exports.CustomSqlFilterBuilder = exports.SqlDatabase = exports.WebSqlDataProvider = exports.ArrayEntityDataProvider = exports.InMemoryDataProvider = exports.RestDataProvider = exports.describeClass = exports.IdEntity = exports.Fields = exports.Field = exports.getEntityRef = exports.Entity = exports.CaptionTransformer = exports.ValueListInfo = exports.getValueList = exports.ValueListFieldType = exports.getFields = exports.FieldType = exports.ControllerBase = exports.EntityBase = void 0;
3
+ exports.repo = exports.SubscriptionChannel = exports.InMemoryLiveQueryStorage = exports.remult = exports.ValueConverters = exports.Validators = exports.UrlBuilder = exports.Filter = exports.CompoundIdField = exports.Sort = exports.EventSource = exports.isBackend = exports.Remult = exports.Allow = exports.ProgressListener = exports.BackendMethod = exports.Controller = exports.JsonDataProvider = exports.dbNamesOf = exports.CustomSqlFilterBuilder = exports.SqlDatabase = exports.WebSqlDataProvider = exports.ArrayEntityDataProvider = 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 = void 0;
4
4
  var RepositoryImplementation_1 = require("./src/remult3/RepositoryImplementation");
5
5
  Object.defineProperty(exports, "EntityBase", { enumerable: true, get: function () { return RepositoryImplementation_1.EntityBase; } });
6
6
  Object.defineProperty(exports, "ControllerBase", { enumerable: true, get: function () { return RepositoryImplementation_1.ControllerBase; } });
@@ -17,6 +17,7 @@ Object.defineProperty(exports, "getEntityRef", { enumerable: true, get: function
17
17
  var Fields_1 = require("./src/remult3/Fields");
18
18
  Object.defineProperty(exports, "Field", { enumerable: true, get: function () { return Fields_1.Field; } });
19
19
  Object.defineProperty(exports, "Fields", { enumerable: true, get: function () { return Fields_1.Fields; } });
20
+ Object.defineProperty(exports, "Relations", { enumerable: true, get: function () { return Fields_1.Relations; } });
20
21
  var IdEntity_1 = require("./src/remult3/IdEntity");
21
22
  Object.defineProperty(exports, "IdEntity", { enumerable: true, get: function () { return IdEntity_1.IdEntity; } });
22
23
  var DecoratorReplacer_1 = require("./src/remult3/DecoratorReplacer");
@@ -48,8 +49,6 @@ Object.defineProperty(exports, "isBackend", { enumerable: true, get: function ()
48
49
  Object.defineProperty(exports, "EventSource", { enumerable: true, get: function () { return context_1.EventSource; } });
49
50
  var sort_1 = require("./src/sort");
50
51
  Object.defineProperty(exports, "Sort", { enumerable: true, get: function () { return sort_1.Sort; } });
51
- var column_1 = require("./src/column");
52
- Object.defineProperty(exports, "OneToMany", { enumerable: true, get: function () { return column_1.OneToMany; } });
53
52
  var CompoundIdField_1 = require("./src/CompoundIdField");
54
53
  Object.defineProperty(exports, "CompoundIdField", { enumerable: true, get: function () { return CompoundIdField_1.CompoundIdField; } });
55
54
  var filter_interfaces_1 = require("./src/filter/filter-interfaces");
@@ -62,8 +61,25 @@ var valueConverters_1 = require("./src/valueConverters");
62
61
  Object.defineProperty(exports, "ValueConverters", { enumerable: true, get: function () { return valueConverters_1.ValueConverters; } });
63
62
  var remult_proxy_1 = require("./src/remult-proxy");
64
63
  Object.defineProperty(exports, "remult", { enumerable: true, get: function () { return remult_proxy_1.remult; } });
64
+ var remult_proxy_2 = require("./src/remult-proxy");
65
65
  //export { getId } from './src/remult3/getId';
66
66
  var SubscriptionServer_1 = require("./src/live-query/SubscriptionServer");
67
67
  Object.defineProperty(exports, "InMemoryLiveQueryStorage", { enumerable: true, get: function () { return SubscriptionServer_1.InMemoryLiveQueryStorage; } });
68
68
  var SubscriptionChannel_1 = require("./src/live-query/SubscriptionChannel");
69
69
  Object.defineProperty(exports, "SubscriptionChannel", { enumerable: true, get: function () { return SubscriptionChannel_1.SubscriptionChannel; } });
70
+ /**
71
+ * A convenient shortcut function to quickly obtain a repository for a specific entity type in Remult.
72
+ *
73
+ * @param entity The entity class type for which you want to get a repository.
74
+ * @returns A repository instance for the specified entity type.
75
+ *
76
+ * Example usage:
77
+ * ```ts
78
+ * await repo(Task).find()
79
+ * await repo(Customer).insert()
80
+ * ```
81
+ */
82
+ function repo(entity) {
83
+ return remult_proxy_2.remult.repo(entity);
84
+ }
85
+ exports.repo = repo;
package/internals.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export { getRelationInfo } from './src/remult3/relationInfoMember';
2
- export { decorateColumnSettings } from './src/remult3/RepositoryImplementation';
2
+ export { decorateColumnSettings, controllerRefImpl, getControllerRef, } from './src/remult3/RepositoryImplementation';
3
3
  export { getEntitySettings } from './src/remult3/getEntityRef';
4
4
  export { __updateEntityBasedOnWhere } from './src/filter/filter-interfaces';
5
5
  export { actionInfo } from './src/server-action-info';
6
6
  export { RelationInfo } from './src/remult3/remult3';
7
+ export { ClassType } from './classType';
package/internals.js CHANGED
@@ -1,10 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.actionInfo = exports.__updateEntityBasedOnWhere = exports.getEntitySettings = exports.decorateColumnSettings = exports.getRelationInfo = void 0;
3
+ exports.actionInfo = exports.__updateEntityBasedOnWhere = exports.getEntitySettings = exports.getControllerRef = exports.controllerRefImpl = exports.decorateColumnSettings = exports.getRelationInfo = void 0;
4
4
  var relationInfoMember_1 = require("./src/remult3/relationInfoMember");
5
5
  Object.defineProperty(exports, "getRelationInfo", { enumerable: true, get: function () { return relationInfoMember_1.getRelationInfo; } });
6
6
  var RepositoryImplementation_1 = require("./src/remult3/RepositoryImplementation");
7
7
  Object.defineProperty(exports, "decorateColumnSettings", { enumerable: true, get: function () { return RepositoryImplementation_1.decorateColumnSettings; } });
8
+ Object.defineProperty(exports, "controllerRefImpl", { enumerable: true, get: function () { return RepositoryImplementation_1.controllerRefImpl; } });
9
+ Object.defineProperty(exports, "getControllerRef", { enumerable: true, get: function () { return RepositoryImplementation_1.getControllerRef; } });
8
10
  var getEntityRef_1 = require("./src/remult3/getEntityRef");
9
11
  Object.defineProperty(exports, "getEntitySettings", { enumerable: true, get: function () { return getEntityRef_1.getEntitySettings; } });
10
12
  var filter_interfaces_1 = require("./src/filter/filter-interfaces");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "remult",
3
- "version": "0.23.0-exp.2",
3
+ "version": "0.23.0-exp.21",
4
4
  "description": "A CRUD framework for full-stack TypeScript",
5
5
  "types": "index.d.ts",
6
6
  "module": "esm/index.js",
package/remult-express.js CHANGED
@@ -28,7 +28,7 @@ function remultExpress(options) {
28
28
  getRemult: function (req) { return server.getRemult(req); },
29
29
  openApiDoc: function (options) { return server.openApiDoc(options); },
30
30
  withRemult: function (req, res, next) { return server.withRemult(req, res, next); },
31
- // [ ]- add with remult promise
31
+ // [ ] V1.5 add with remult promise
32
32
  });
33
33
  }
34
34
  exports.remultExpress = remultExpress;
@@ -11,6 +11,7 @@ var RepositoryImplementation_1 = require("../src/remult3/RepositoryImplementatio
11
11
  var sort_1 = require("../src/sort");
12
12
  var valueConverters_1 = require("../src/valueConverters");
13
13
  var resultCompoundIdFilter_1 = require("../src/resultCompoundIdFilter");
14
+ var repository_internals_1 = require("../src/remult3/repository-internals");
14
15
  var KnexDataProvider = /** @class */ (function () {
15
16
  function KnexDataProvider(knex) {
16
17
  this.knex = knex;
@@ -91,7 +92,7 @@ var KnexDataProvider = /** @class */ (function () {
91
92
  case 1:
92
93
  b = new (_a.apply(FilterConsumerBridgeToKnexRequest, [void 0, _b.sent()]))();
93
94
  b._addWhere = false;
94
- return [4 /*yield*/, repo.translateWhereToFilter(condition)];
95
+ return [4 /*yield*/, (0, repository_internals_1.getRepositoryInternals)(repo).translateWhereToFilter(condition)];
95
96
  case 2: return [4 /*yield*/, (_b.sent()).__applyToConsumer(b)];
96
97
  case 3:
97
98
  _b.sent();
package/remult-mongo.js CHANGED
@@ -7,6 +7,7 @@ var filter_consumer_bridge_to_sql_request_1 = require("./src/filter/filter-consu
7
7
  var remult_proxy_1 = require("./src/remult-proxy");
8
8
  var RepositoryImplementation_1 = require("./src/remult3/RepositoryImplementation");
9
9
  var resultCompoundIdFilter_1 = require("./src/resultCompoundIdFilter");
10
+ var repository_internals_1 = require("./src/remult3/repository-internals");
10
11
  var MongoDataProvider = /** @class */ (function () {
11
12
  function MongoDataProvider(db, client, options) {
12
13
  this.db = db;
@@ -80,7 +81,7 @@ var MongoDataProvider = /** @class */ (function () {
80
81
  case 1:
81
82
  b = new (_a.apply(FilterConsumerBridgeToMongo, [void 0, _b.sent()]))();
82
83
  b._addWhere = false;
83
- return [4 /*yield*/, repo.translateWhereToFilter(condition)];
84
+ return [4 /*yield*/, (0, repository_internals_1.getRepositoryInternals)(repo).translateWhereToFilter(condition)];
84
85
  case 2: return [4 /*yield*/, (_b.sent()).__applyToConsumer(b)];
85
86
  case 3:
86
87
  _b.sent();
@@ -14,7 +14,7 @@ var JsonEntityFileStorage = /** @class */ (function () {
14
14
  if (fs.existsSync(fn)) {
15
15
  return fs.readFileSync(fn).toString();
16
16
  }
17
- return undefined;
17
+ return null;
18
18
  };
19
19
  JsonEntityFileStorage.prototype.setItem = function (entityDbName, json) {
20
20
  if (!fs.existsSync(this.folderPath)) {
@@ -255,7 +255,7 @@ var RemultServerImplementation = /** @class */ (function () {
255
255
  });
256
256
  };
257
257
  RemultServerImplementation.prototype.getEntities = function () {
258
- //TODO - consider using entitiesMetaData - but it may require making it all awaitable
258
+ //TODO V2 - consider using entitiesMetaData - but it may require making it all awaitable
259
259
  var r = new context_1.Remult();
260
260
  return this.options.entities.map(function (x) { return r.repo(x).metadata; });
261
261
  };
@@ -6,7 +6,7 @@ export declare class CompoundIdField implements FieldMetadata<string> {
6
6
  constructor(...columns: FieldMetadata[]);
7
7
  apiUpdateAllowed(item: any): boolean;
8
8
  displayValue(item: any): string;
9
- includedInApi: boolean;
9
+ includedInApi(item: any): boolean;
10
10
  toInput(value: string, inputType?: string): string;
11
11
  fromInput(inputValue: string, inputType?: string): string;
12
12
  getDbName(): Promise<string>;
@@ -15,6 +15,9 @@ var CompoundIdField = /** @class */ (function () {
15
15
  CompoundIdField.prototype.displayValue = function (item) {
16
16
  throw new Error('Method not implemented.');
17
17
  };
18
+ CompoundIdField.prototype.includedInApi = function (item) {
19
+ throw new Error('Method not implemented.');
20
+ };
18
21
  CompoundIdField.prototype.toInput = function (value, inputType) {
19
22
  throw new Error('Method not implemented.');
20
23
  };
@@ -1,6 +1,5 @@
1
1
  import type { RestDataProviderHttpProvider } from './data-interfaces';
2
- import { RestDataProviderHttpProviderUsingFetch } from './data-providers/rest-data-provider';
3
- export declare function buildRestDataProvider(provider: ExternalHttpProvider | typeof fetch): RestDataProviderHttpProviderUsingFetch | RestDataProviderHttpProvider;
2
+ export declare function buildRestDataProvider(provider: ExternalHttpProvider | typeof fetch): RestDataProviderHttpProvider;
4
3
  export declare function isExternalHttpProvider(item: any): boolean;
5
4
  export declare class HttpProviderBridgeToRestDataProviderHttpProvider implements RestDataProviderHttpProvider {
6
5
  private http;