remult 0.23.0-exp.34 → 0.23.0-exp.36

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.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import type { ClassType } from './classType';
2
- export { OmitEB, OmitFunctions, 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, ClassFieldDecoratorContextStub, //n1 consider removing in ts5
2
+ export type { ClassType } from './classType';
3
+ export { MembersOnly, 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, ClassFieldDecoratorContextStub, //n1 consider removing in ts5
3
4
  LifecycleEvent, } from './src/remult3/remult3';
4
5
  export { EntityBase, ControllerBase, FieldType, getFields, ValueListFieldType, getValueList, ValueListFieldOptions, ValueListInfo, CaptionTransformer, } from './src/remult3/RepositoryImplementation';
5
6
  export { Entity } from './src/remult3/entity';
@@ -1,6 +1,6 @@
1
1
  import type { ClassType } from '../classType';
2
2
  import type { AllowedForInstance } from './context';
3
- import type { EntityMetadata, FieldRef, LifecycleEvent, OmitEB } from './remult3/remult3';
3
+ import type { EntityMetadata, FieldRef, LifecycleEvent } from './remult3/remult3';
4
4
  export interface FieldOptions<entityType = any, valueType = any> {
5
5
  /** A human readable name for the field. Can be used to achieve a consistent caption for a field throughout the app
6
6
  * @example
@@ -132,9 +132,9 @@ export interface FieldMetadata<valueType = any, entityType = any> {
132
132
  * @example
133
133
  * repo.fields.createDate.displayValue(task) //will display the date as defined in the `displayValue` option defined for it.
134
134
  */
135
- displayValue(item: Partial<OmitEB<entityType>>): string;
136
- apiUpdateAllowed(item?: Partial<OmitEB<entityType>>): boolean;
137
- includedInApi(item?: Partial<OmitEB<entityType>>): boolean;
135
+ displayValue(item: Partial<entityType>): string;
136
+ apiUpdateAllowed(item?: Partial<entityType>): boolean;
137
+ includedInApi(item?: Partial<entityType>): boolean;
138
138
  /** Adapts the value for usage with html input
139
139
  * @example
140
140
  * @Fields.dateOnly()
@@ -3,6 +3,7 @@ export declare function makeTitle(name: string): string;
3
3
  export declare class LookupColumn<T> {
4
4
  private repository;
5
5
  private isReferenceRelation;
6
+ private allowNull;
6
7
  toJson(): any;
7
8
  setId(val: any): void;
8
9
  waitLoadOf(id: any): Promise<T>;
@@ -12,7 +13,7 @@ export declare class LookupColumn<T> {
12
13
  };
13
14
  set(item: T): void;
14
15
  id: idType<T>;
15
- constructor(repository: Repository<T>, isReferenceRelation: any);
16
+ constructor(repository: Repository<T>, isReferenceRelation: any, allowNull: any);
16
17
  get item(): T;
17
18
  waitLoad(): Promise<T>;
18
19
  }
package/esm/src/column.js CHANGED
@@ -12,6 +12,7 @@ export function makeTitle(name) {
12
12
  export class LookupColumn {
13
13
  repository;
14
14
  isReferenceRelation;
15
+ allowNull;
15
16
  toJson() {
16
17
  if (!this.storedItem)
17
18
  return undefined;
@@ -32,12 +33,23 @@ export class LookupColumn {
32
33
  get(id) {
33
34
  if (id === undefined || id === null)
34
35
  return null;
35
- if (this.isReferenceRelation && !this.storedItem)
36
+ const result = getRepositoryInternals(this.repository).getCachedById(id, this.isReferenceRelation);
37
+ if (this.isReferenceRelation && !this.storedItem) {
38
+ if (!this.allowNull && (this.id === 0 || this.id === ''))
39
+ return null;
36
40
  return undefined;
37
- return getRepositoryInternals(this.repository).getCachedById(id, this.isReferenceRelation);
41
+ }
42
+ return result;
38
43
  }
39
44
  storedItem;
40
45
  set(item) {
46
+ if (item === null &&
47
+ !this.allowNull &&
48
+ this.isReferenceRelation &&
49
+ (this.id == 0 || this.id == '')) {
50
+ this.storedItem = { item: null };
51
+ return;
52
+ }
41
53
  this.storedItem = undefined;
42
54
  if (item) {
43
55
  if (typeof item === 'string' || typeof item === 'number')
@@ -62,9 +74,10 @@ export class LookupColumn {
62
74
  }
63
75
  }
64
76
  id;
65
- constructor(repository, isReferenceRelation) {
77
+ constructor(repository, isReferenceRelation, allowNull) {
66
78
  this.repository = repository;
67
79
  this.isReferenceRelation = isReferenceRelation;
80
+ this.allowNull = allowNull;
68
81
  }
69
82
  get item() {
70
83
  if (this.storedItem)
@@ -1,5 +1,5 @@
1
1
  import type { Filter } from './filter/filter-interfaces';
2
- import type { EntityMetadata, OmitEB, OmitFunctions } from './remult3/remult3';
2
+ import type { EntityMetadata, MembersOnly } from './remult3/remult3';
3
3
  import { Sort } from './sort';
4
4
  export interface DataProvider {
5
5
  getEntityDataProvider(entity: EntityMetadata): EntityDataProvider;
@@ -33,7 +33,7 @@ export declare function extractSort(sort: any): Sort;
33
33
  export interface ErrorInfo<entityType = any> {
34
34
  message?: string;
35
35
  modelState?: {
36
- [Properties in keyof Partial<OmitFunctions<OmitEB<entityType>>>]?: string;
36
+ [Properties in keyof Partial<MembersOnly<entityType>>]?: string;
37
37
  };
38
38
  stack?: string;
39
39
  exception?: any;
@@ -1,24 +1,3 @@
1
- import type { EntityDataProvider, EntityDataProviderFindOptions } from '../data-interfaces';
2
- import { type EntityDbNamesBase } from '../filter/filter-consumer-bridge-to-sql-request';
3
- import { Filter } from '../filter/filter-interfaces';
4
- import type { EntityFilter, EntityMetadata } from '../remult3/remult3';
5
- export declare class ArrayEntityDataProvider implements EntityDataProvider {
6
- private entity;
7
- static rawFilter(filter: CustomArrayFilter): EntityFilter<any>;
8
- private rows;
9
- constructor(entity: EntityMetadata, rows?: any[]);
10
- __names: EntityDbNamesBase;
11
- init(): Promise<EntityDbNamesBase>;
12
- private verifyThatRowHasAllNotNullColumns;
13
- count(where?: Filter): Promise<number>;
14
- find(options?: EntityDataProviderFindOptions): Promise<any[]>;
15
- translateFromJson(row: any, dbNames: EntityDbNamesBase): {};
16
- translateToJson(row: any, dbNames: EntityDbNamesBase): {};
17
- private idMatches;
18
- update(id: any, data: any): Promise<any>;
19
- delete(id: any): Promise<void>;
20
- insert(data: any): Promise<any>;
21
- }
22
1
  export type CustomArrayFilter = (item: any) => boolean;
23
2
  export interface CustomArrayFilterObject {
24
3
  arrayFilter: CustomArrayFilter;
@@ -1,6 +1,7 @@
1
1
  import { CompoundIdField } from '../CompoundIdField';
2
2
  import { dbNamesOf, isDbReadonly, } from '../filter/filter-consumer-bridge-to-sql-request';
3
3
  import { Filter, customDatabaseFilterToken } from '../filter/filter-interfaces';
4
+ //@internal
4
5
  export class ArrayEntityDataProvider {
5
6
  entity;
6
7
  static rawFilter(filter) {
@@ -10,6 +11,7 @@ export class ArrayEntityDataProvider {
10
11
  },
11
12
  };
12
13
  }
14
+ //@internal
13
15
  rows;
14
16
  constructor(entity, rows) {
15
17
  this.entity = entity;
@@ -18,7 +20,9 @@ export class ArrayEntityDataProvider {
18
20
  else
19
21
  this.rows = rows;
20
22
  }
23
+ //@internal
21
24
  __names;
25
+ //@internal
22
26
  async init() {
23
27
  if (this.__names)
24
28
  return this.__names;
@@ -28,6 +32,7 @@ export class ArrayEntityDataProvider {
28
32
  }
29
33
  return this.__names;
30
34
  }
35
+ //@internal
31
36
  verifyThatRowHasAllNotNullColumns(r, names) {
32
37
  for (const f of this.entity.fields) {
33
38
  const key = names.$dbNameOf(f);
@@ -89,6 +94,7 @@ export class ArrayEntityDataProvider {
89
94
  });
90
95
  return [];
91
96
  }
97
+ //@internal
92
98
  translateFromJson(row, dbNames) {
93
99
  let result = {};
94
100
  for (const col of this.entity.fields) {
@@ -96,6 +102,7 @@ export class ArrayEntityDataProvider {
96
102
  }
97
103
  return result;
98
104
  }
105
+ //@internal
99
106
  translateToJson(row, dbNames) {
100
107
  let result = {};
101
108
  for (const col of this.entity.fields) {
@@ -104,6 +111,7 @@ export class ArrayEntityDataProvider {
104
111
  }
105
112
  return result;
106
113
  }
114
+ //@internal
107
115
  idMatches(id, names) {
108
116
  return (item) => {
109
117
  let x = new FilterConsumerBridgeToObject(item, names);
@@ -1,6 +1,6 @@
1
1
  import type { FieldMetadata } from '../column-interfaces';
2
2
  import type { EntityMetadataOverloads, RepositoryOverloads } from '../remult3/RepositoryImplementation';
3
- import type { EntityFilter, OmitEB, OmitFunctions } from '../remult3/remult3';
3
+ import type { EntityFilter, MembersOnly } from '../remult3/remult3';
4
4
  import type { SqlCommandWithParameters } from '../sql-command';
5
5
  import type { Filter, FilterConsumer } from './filter-interfaces';
6
6
  export declare class FilterConsumerBridgeToSqlRequest implements FilterConsumer {
@@ -45,6 +45,6 @@ export declare type EntityDbNamesBase = {
45
45
  toString(): string;
46
46
  };
47
47
  export declare type EntityDbNames<entityType> = {
48
- [Properties in keyof Required<OmitFunctions<OmitEB<entityType>>>]: string;
48
+ [Properties in keyof Required<MembersOnly<entityType>>]: string;
49
49
  } & EntityDbNamesBase;
50
50
  export declare function dbNamesOf<entityType>(repo: EntityMetadataOverloads<entityType>): Promise<EntityDbNames<entityType>>;
@@ -1,7 +1,6 @@
1
- import type { OmitEB } from './remult3';
2
1
  type Decorator<T = any> = (a: T, b: string, c?: any) => void;
3
2
  type Decorators<T> = T extends new (...args: any[]) => infer R ? {
4
- [K in keyof OmitEB<R>]?: Decorator;
3
+ [K in keyof R]?: Decorator;
5
4
  } : never;
6
5
  type StaticDecorators<T> = {
7
6
  [K in keyof T]?: Decorator;
@@ -35,37 +35,27 @@ export declare class Relations {
35
35
  * @Relations.toOne(() => Customer)
36
36
  * customer?: Customer;
37
37
  * ```
38
- */
39
- static toOne<entityType, toEntityType>(toEntityType: () => ClassType<toEntityType>, options?: FieldOptions<entityType, toEntityType> & Pick<RelationOptions<entityType, toEntityType, any, any>, 'defaultIncluded'>): ClassFieldDecorator<entityType, toEntityType | undefined>;
40
- /**
41
- * Define a to-one relation between entities, indicating a one-to-one relationship.
42
- * If no `fieldInMyEntity` is provided, this overload will automatically create a field in the database
43
- * to represent the relation.
44
- *
45
- * @param toEntityType A function that returns the target entity type.
46
- * @param fieldInMyEntity (Optional): The field in the current entity that represents the relation.
47
- * Use this if you want to specify a custom field name for the relation.
48
- * @returns A decorator function to apply the to-one relation to an entity field.
49
- *
50
- * Example usage:
51
38
  * ```
52
- * @Relations.toOne(() => Customer)
39
+ * Fields.string()
40
+ * customerId?: string;
41
+ *
42
+ * @Relations.toOne(() => Customer, "customerId")
53
43
  * customer?: Customer;
54
44
  * ```
55
- */
56
- static toOne<entityType, toEntityType>(toEntityType: () => ClassType<toEntityType>, fieldInMyEntity?: keyof entityType): ClassFieldDecorator<entityType, toEntityType | undefined>;
57
- /**
58
- * Define a to-one relation between entities, indicating a one-to-one relationship.
59
- * If no field or fields are provided, it will automatically create a field in the database
60
- * to represent the relation.
61
- *
62
- * @param toEntityType A function that returns the target entity type.
63
- * @param options An object containing options for configuring the to-one relation.
64
- * - fields (Optional): An object specifying custom field names for the relation.
65
- * @returns A decorator function to apply the virtual to-one relation to an entity field.
45
+ * ```
46
+ * Fields.string()
47
+ * customerId?: string;
66
48
  *
67
- * Example usage:
49
+ * @Relations.toOne(() => Customer, {
50
+ * field: "customerId",
51
+ * defaultIncluded: true
52
+ * })
53
+ * customer?: Customer;
68
54
  * ```
55
+ * ```
56
+ * Fields.string()
57
+ * customerId?: string;
58
+ *
69
59
  * @Relations.toOne(() => Customer, {
70
60
  * fields: {
71
61
  * customerId: "id",
@@ -73,10 +63,8 @@ export declare class Relations {
73
63
  * })
74
64
  * customer?: Customer;
75
65
  * ```
76
- */
77
- static toOne<entityType, toEntityType>(toEntityType: () => ClassType<toEntityType>, options: Omit<RelationOptions<entityType, toEntityType, entityType>, keyof Pick<RelationOptions<entityType, toEntityType, entityType>, 'field'>>): ClassFieldDecorator<entityType, toEntityType | undefined>;
78
- /** A to one relation with fields defined in the field/fields parameter */
79
- static toOne<entityType, toEntityType>(toEntityType: () => ClassType<toEntityType>, options: Omit<RelationOptions<entityType, toEntityType, entityType>, keyof Pick<RelationOptions<entityType, toEntityType, entityType>, 'fields'>>): ClassFieldDecorator<entityType, toEntityType | undefined>;
66
+ */
67
+ static toOne<entityType, toEntityType>(toEntityType: () => ClassType<toEntityType>, options?: FieldOptions<entityType, toEntityType> & Pick<RelationOptions<entityType, toEntityType, any, any>, 'defaultIncluded'> | RelationOptions<entityType, toEntityType, entityType> | keyof entityType): (target: any, context: string | ClassFieldDecoratorContextStub<any, toEntityType>, c?: any) => void;
80
68
  /**
81
69
  * Define a toMany relation between entities, indicating a one-to-many relationship.
82
70
  * This method allows you to establish a relationship where one entity can have multiple related entities.
@@ -88,6 +88,49 @@ export class Fields {
88
88
  }
89
89
  }
90
90
  export class Relations {
91
+ /**
92
+ * Define a to-one relation between entities, indicating a one-to-one relationship.
93
+ * If no field or fields are provided, it will automatically create a field in the database
94
+ * to represent the relation.
95
+ *
96
+ * @param toEntityType A function that returns the target entity type.
97
+ * @param options (Optional): An object containing options for configuring the to-one relation.
98
+ * @returns A decorator function to apply the to-one relation to an entity field.
99
+ *
100
+ * Example usage:
101
+ * ```
102
+ * @Relations.toOne(() => Customer)
103
+ * customer?: Customer;
104
+ * ```
105
+ * ```
106
+ * Fields.string()
107
+ * customerId?: string;
108
+ *
109
+ * @Relations.toOne(() => Customer, "customerId")
110
+ * customer?: Customer;
111
+ * ```
112
+ * ```
113
+ * Fields.string()
114
+ * customerId?: string;
115
+ *
116
+ * @Relations.toOne(() => Customer, {
117
+ * field: "customerId",
118
+ * defaultIncluded: true
119
+ * })
120
+ * customer?: Customer;
121
+ * ```
122
+ * ```
123
+ * Fields.string()
124
+ * customerId?: string;
125
+ *
126
+ * @Relations.toOne(() => Customer, {
127
+ * fields: {
128
+ * customerId: "id",
129
+ * },
130
+ * })
131
+ * customer?: Customer;
132
+ * ```
133
+ */
91
134
  static toOne(toEntityType, options) {
92
135
  let op = (typeof options === 'string'
93
136
  ? { field: options }
@@ -3,7 +3,7 @@ import { LookupColumn } from '../column';
3
3
  import type { FieldMetadata, FieldOptions, ValueConverter, ValueListItem } from '../column-interfaces';
4
4
  import { Remult } from '../context';
5
5
  import type { EntityOptions } from '../entity';
6
- import type { ControllerRef, EntityFilter, EntityMetadata, EntityOrderBy, EntityRef, FieldRef, FieldsMetadata, FieldsRef, FindFirstOptions, FindFirstOptionsBase, FindOptions, IdMetadata, LiveQuery, LoadOptions, OmitEB, QueryOptions, QueryResult, Repository, RepositoryRelations, Subscribable } from './remult3';
6
+ import type { ControllerRef, ControllerRefForEntityBase, EntityFilter, EntityMetadata, EntityOrderBy, EntityRef, EntityRefForEntityBase, FieldRef, FieldsMetadata, FieldsRef, FieldsRefForEntityBase, FindFirstOptions, FindFirstOptionsBase, FindOptions, IdMetadata, LiveQuery, LoadOptions, MembersOnly, QueryOptions, QueryResult, Repository, RepositoryRelations, Subscribable } from './remult3';
7
7
  import type { RefSubscriber } from './remult3';
8
8
  import type { entityEventListener } from '../__EntityValueProvider';
9
9
  import type { DataProvider, EntityDataProvider, EntityDataProviderFindOptions, ErrorInfo } from '../data-interfaces';
@@ -38,19 +38,19 @@ export declare class RepositoryImplementation<entityType> implements Repository<
38
38
  id?: string;
39
39
  } ? string : string | number): Promise<void>;
40
40
  delete(item: entityType): Promise<void>;
41
- insert(item: Partial<OmitEB<entityType>>[]): Promise<entityType[]>;
42
- insert(item: Partial<OmitEB<entityType>>): Promise<entityType>;
41
+ insert(item: Partial<MembersOnly<entityType>>[]): Promise<entityType[]>;
42
+ insert(item: Partial<MembersOnly<entityType>>): Promise<entityType>;
43
43
  get fields(): FieldsMetadata<entityType>;
44
- validate(entity: Partial<OmitEB<entityType>>, ...fields: Extract<keyof OmitEB<entityType>, string>[]): Promise<ErrorInfo<entityType> | undefined>;
44
+ validate(entity: Partial<MembersOnly<entityType>>, ...fields: Extract<keyof MembersOnly<entityType>, string>[]): Promise<ErrorInfo<entityType> | undefined>;
45
45
  update(id: entityType extends {
46
46
  id?: number;
47
47
  } ? number : entityType extends {
48
48
  id?: string;
49
- } ? string : string | number, item: Partial<OmitEB<entityType>>): Promise<entityType>;
50
- update(originalItem: Partial<OmitEB<entityType>>, item: Partial<OmitEB<entityType>>): Promise<entityType>;
49
+ } ? string : string | number, item: Partial<MembersOnly<entityType>>): Promise<entityType>;
50
+ update(originalItem: Partial<MembersOnly<entityType>>, item: Partial<MembersOnly<entityType>>): Promise<entityType>;
51
51
  private getRefForExistingRow;
52
- save(item: Partial<OmitEB<entityType>>[]): Promise<entityType[]>;
53
- save(item: Partial<OmitEB<entityType>>): Promise<entityType>;
52
+ save(item: Partial<MembersOnly<entityType>>[]): Promise<entityType[]>;
53
+ save(item: Partial<MembersOnly<entityType>>): Promise<entityType>;
54
54
  liveQuery(options?: FindOptions<entityType>): LiveQuery<entityType>;
55
55
  rawFind(options: FindOptions<entityType>, skipOrderByAndLimit: boolean, loader: RelationLoader): Promise<entityType[]>;
56
56
  find(options: FindOptions<entityType>, skipOrderByAndLimit?: boolean): Promise<entityType[]>;
@@ -64,7 +64,7 @@ export declare class RepositoryImplementation<entityType> implements Repository<
64
64
  private cache;
65
65
  findFirst(where?: EntityFilter<entityType>, options?: FindFirstOptions<entityType>, skipOrderByAndLimit?: boolean): Promise<entityType>;
66
66
  private fieldsOf;
67
- create(item?: Partial<OmitEB<entityType>>): entityType;
67
+ create(item?: Partial<MembersOnly<entityType>>): entityType;
68
68
  fixTypes(item: any): Promise<any>;
69
69
  findId(id: any, options?: FindFirstOptionsBase<entityType>): Promise<entityType>;
70
70
  }
@@ -98,7 +98,7 @@ declare abstract class rowHelperBase<T> {
98
98
  __clearErrorsAndReportChanged(): void;
99
99
  _reportChangedToEntityAndFields(): void;
100
100
  hasErrors(): boolean;
101
- copyDataToObject(): any;
101
+ copyDataToObject(isNew?: boolean): any;
102
102
  originalValues: any;
103
103
  saveOriginalData(): void;
104
104
  saveMoreOriginalData(): void;
@@ -259,19 +259,19 @@ export declare const storableMember: unique symbol;
259
259
  export declare function buildOptions<entityType = any, valueType = any>(options: (FieldOptions<entityType, valueType> | ((options: FieldOptions<entityType, valueType>, remult: Remult) => void))[], remult: Remult): FieldOptions<entityType, valueType>;
260
260
  export declare function decorateColumnSettings<valueType>(settings: FieldOptions<any, valueType>, remult: Remult): FieldOptions<any, valueType>;
261
261
  export declare class EntityBase {
262
- get _(): EntityRef<this>;
262
+ get _(): EntityRefForEntityBase<this>;
263
263
  save(): Promise<this>;
264
264
  assign(values: Partial<Omit<this, keyof EntityBase>>): this;
265
265
  delete(): Promise<void>;
266
266
  isNew(): boolean;
267
- get $(): FieldsRef<this>;
267
+ get $(): FieldsRefForEntityBase<this>;
268
268
  }
269
269
  export declare class ControllerBase {
270
270
  protected remult: Remult;
271
271
  constructor(remult?: Remult);
272
272
  assign(values: Partial<Omit<this, keyof EntityBase>>): this;
273
- get $(): FieldsRef<this>;
274
- get _(): ControllerRef<this>;
273
+ get $(): FieldsRefForEntityBase<this>;
274
+ get _(): ControllerRefForEntityBase<this>;
275
275
  }
276
276
  declare class SubscribableImp implements Subscribable {
277
277
  reportChanged(): void;
@@ -259,6 +259,7 @@ export class RepositoryImplementation {
259
259
  let f = ref.fields[key];
260
260
  if (entity[key] === undefined && getRelationInfo(f.metadata.options))
261
261
  continue;
262
+ //@ts-ignore
262
263
  if (f)
263
264
  r[key] = entity[key];
264
265
  }
@@ -559,6 +560,8 @@ export class RepositoryImplementation {
559
560
  let val = rel.type === 'reference'
560
561
  ? getEntityRef(row).fields.find(requireField(field.key, this.metadata)).getId()
561
562
  : row[field.key];
563
+ if (!field.allowNull && (val === 0 || val === ''))
564
+ val = null;
562
565
  if (val === null)
563
566
  returnNull = true;
564
567
  if (val === undefined)
@@ -827,7 +830,7 @@ class rowHelperBase {
827
830
  for (const col of columnsInfo) {
828
831
  let ei = getEntitySettings(col.valueType, false);
829
832
  if (ei && remult) {
830
- let lookup = new LookupColumn(remult.repo(col.valueType), Boolean(col?.[relationInfoMember]));
833
+ let lookup = new LookupColumn(remult.repo(col.valueType), Boolean(col?.[relationInfoMember]), col.allowNull);
831
834
  this.lookups.set(col.key, lookup);
832
835
  let val = instance[col.key];
833
836
  let refImpl;
@@ -1003,21 +1006,28 @@ class rowHelperBase {
1003
1006
  this._subscribers?.reportObserved();
1004
1007
  return !!!this.error && this.errors == undefined;
1005
1008
  }
1006
- copyDataToObject() {
1009
+ copyDataToObject(isNew = false) {
1007
1010
  let d = {};
1008
1011
  for (const col of this.columnsInfo) {
1009
1012
  let lu = this.lookups.get(col.key);
1010
1013
  let val = undefined;
1014
+ const rel = getRelationInfo(col);
1011
1015
  if (lu)
1012
1016
  val = lu.id;
1013
1017
  else
1014
1018
  val = this.instance[col.key];
1019
+ if (rel && isNew && !col.allowNull && (val === undefined || null)) {
1020
+ if (this.remult.repo(rel.toType()).metadata.idMetadata.field.valueType ===
1021
+ Number)
1022
+ val = 0;
1023
+ else
1024
+ val = '';
1025
+ }
1015
1026
  if (val !== undefined) {
1016
1027
  val = col.valueConverter.toJson(val);
1017
1028
  if (val !== undefined && val !== null)
1018
1029
  val = col.valueConverter.fromJson(JSON.parse(JSON.stringify(val)));
1019
1030
  }
1020
- const rel = getRelationInfo(col);
1021
1031
  if (!rel || rel.type === 'reference')
1022
1032
  d[col.key] = val;
1023
1033
  }
@@ -1216,7 +1226,7 @@ export class rowHelperImplementation extends rowHelperBase {
1216
1226
  }
1217
1227
  }
1218
1228
  this.__assertValidity();
1219
- let d = this.copyDataToObject();
1229
+ let d = this.copyDataToObject(this.isNew());
1220
1230
  let ignoreKeys = [];
1221
1231
  for (const field of this.metadata.fields) {
1222
1232
  if (field.dbReadOnly ||
@@ -2118,7 +2128,7 @@ export class EntityBase {
2118
2128
  return getEntityRef(this);
2119
2129
  }
2120
2130
  save() {
2121
- return this._.save();
2131
+ return getEntityRef(this).save();
2122
2132
  }
2123
2133
  assign(values) {
2124
2134
  assign(this, values);