remult 0.22.8 → 0.22.9
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/internals.d.ts +7 -0
- package/esm/internals.js +5 -0
- package/esm/src/remult3/Fields.d.ts +52 -0
- package/esm/src/remult3/Fields.js +195 -0
- package/esm/src/remult3/IdEntity.d.ts +4 -0
- package/esm/src/remult3/IdEntity.js +10 -0
- package/esm/src/remult3/RepositoryImplementation.d.ts +1 -1
- package/esm/src/remult3/RepositoryImplementation.js +2 -1
- package/esm/src/remult3/columnInfo.d.ts +6 -0
- package/esm/src/remult3/columnInfo.js +1 -0
- package/esm/src/remult3/relation-loader-types.d.ts +7 -0
- package/esm/src/remult3/relation-loader-types.js +1 -0
- package/esm/src/remult3/relation-loader.d.ts +40 -0
- package/esm/src/remult3/relation-loader.js +142 -0
- package/esm/src/remult3/relationInfoMember.d.ts +4 -0
- package/esm/src/remult3/relationInfoMember.js +4 -0
- package/esm/src/remult3/repository-internals.d.ts +14 -0
- package/esm/src/remult3/repository-internals.js +7 -0
- package/esm/src/server-action.js +1 -1
- package/internals.d.ts +7 -0
- package/internals.js +15 -0
- package/package.json +1 -1
- package/src/remult3/Fields.d.ts +52 -0
- package/src/remult3/Fields.js +259 -0
- package/src/remult3/IdEntity.d.ts +4 -0
- package/src/remult3/IdEntity.js +18 -0
- package/src/remult3/RepositoryImplementation.d.ts +1 -1
- package/src/remult3/RepositoryImplementation.js +3 -1
- package/src/remult3/columnInfo.d.ts +6 -0
- package/src/remult3/columnInfo.js +2 -0
- package/src/remult3/relation-loader-types.d.ts +7 -0
- package/src/remult3/relation-loader-types.js +2 -0
- package/src/remult3/relation-loader.d.ts +40 -0
- package/src/remult3/relation-loader.js +219 -0
- package/src/remult3/relationInfoMember.d.ts +4 -0
- package/src/remult3/relationInfoMember.js +8 -0
- package/src/remult3/repository-internals.d.ts +14 -0
- package/src/remult3/repository-internals.js +11 -0
- package/src/server-action.js +1 -1
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { getRelationInfo } from './src/remult3/relationInfoMember';
|
|
2
|
+
export { decorateColumnSettings, controllerRefImpl, getControllerRef, } from './src/remult3/RepositoryImplementation';
|
|
3
|
+
export { getEntitySettings } from './src/remult3/getEntityRef';
|
|
4
|
+
export { __updateEntityBasedOnWhere } from './src/filter/filter-interfaces';
|
|
5
|
+
export { actionInfo } from './src/server-action-info';
|
|
6
|
+
export { RelationInfo } from './src/remult3/remult3';
|
|
7
|
+
export { ClassType } from './classType';
|
package/esm/internals.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { getRelationInfo } from './src/remult3/relationInfoMember';
|
|
2
|
+
export { decorateColumnSettings, controllerRefImpl, getControllerRef, } from './src/remult3/RepositoryImplementation';
|
|
3
|
+
export { getEntitySettings } from './src/remult3/getEntityRef';
|
|
4
|
+
export { __updateEntityBasedOnWhere } from './src/filter/filter-interfaces';
|
|
5
|
+
export { actionInfo } from './src/server-action-info';
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { ClassType } from '../../classType';
|
|
2
|
+
import type { FieldOptions } from '../column-interfaces';
|
|
3
|
+
import type { Remult } from '../context';
|
|
4
|
+
import type { FindOptions, RelationOptions, ClassFieldDecorator, ClassFieldDecoratorContextStub } from './remult3';
|
|
5
|
+
export declare class Fields {
|
|
6
|
+
/**
|
|
7
|
+
* Stored as a JSON.stringify - to store as json use Fields.json
|
|
8
|
+
*/
|
|
9
|
+
static object<entityType = any, valueType = any>(...options: (FieldOptions<entityType, valueType> | ((options: FieldOptions<entityType, valueType>, remult: Remult) => void))[]): ClassFieldDecorator<entityType, valueType | undefined>;
|
|
10
|
+
static json<entityType = any, valueType = any>(...options: (FieldOptions<entityType, valueType> | ((options: FieldOptions<entityType, valueType>, remult: Remult) => void))[]): ClassFieldDecorator<entityType, valueType | undefined>;
|
|
11
|
+
static dateOnly<entityType = any>(...options: (FieldOptions<entityType, Date> | ((options: FieldOptions<entityType, Date>, remult: Remult) => void))[]): ClassFieldDecorator<entityType, Date | undefined>;
|
|
12
|
+
static date<entityType = any>(...options: (FieldOptions<entityType, Date> | ((options: FieldOptions<entityType, Date>, remult: Remult) => void))[]): ClassFieldDecorator<entityType, Date | undefined>;
|
|
13
|
+
static integer<entityType = any>(...options: (FieldOptions<entityType, Number> | ((options: FieldOptions<entityType, Number>, remult: Remult) => void))[]): ClassFieldDecorator<entityType, number | undefined>;
|
|
14
|
+
static autoIncrement<entityType = any>(...options: (FieldOptions<entityType, Number> | ((options: FieldOptions<entityType, Number>, remult: Remult) => void))[]): ClassFieldDecorator<entityType, number | undefined>;
|
|
15
|
+
static number<entityType = any>(...options: (FieldOptions<entityType, Number> | ((options: FieldOptions<entityType, Number>, remult: Remult) => void))[]): ClassFieldDecorator<entityType, number | undefined>;
|
|
16
|
+
static createdAt<entityType = any>(...options: (FieldOptions<entityType, Date> | ((options: FieldOptions<entityType, Date>, remult: Remult) => void))[]): ClassFieldDecorator<entityType, Date | undefined>;
|
|
17
|
+
static updatedAt<entityType = any>(...options: (FieldOptions<entityType, Date> | ((options: FieldOptions<entityType, Date>, remult: Remult) => void))[]): ClassFieldDecorator<entityType, Date | undefined>;
|
|
18
|
+
static uuid<entityType = any>(...options: (FieldOptions<entityType, string> | ((options: FieldOptions<entityType, string>, remult: Remult) => void))[]): ClassFieldDecorator<entityType, string | undefined>;
|
|
19
|
+
static cuid<entityType = any>(...options: (FieldOptions<entityType, string> | ((options: FieldOptions<entityType, string>, remult: Remult) => void))[]): ClassFieldDecorator<entityType, string | undefined>;
|
|
20
|
+
static string<entityType = any>(...options: (StringFieldOptions<entityType> | ((options: StringFieldOptions<entityType>, remult: Remult) => void))[]): ClassFieldDecorator<entityType, string | undefined>;
|
|
21
|
+
static boolean<entityType = any>(...options: (FieldOptions<entityType, boolean> | ((options: FieldOptions<entityType, boolean>, remult: Remult) => void))[]): ClassFieldDecorator<entityType, boolean | undefined>;
|
|
22
|
+
}
|
|
23
|
+
export declare class Relations {
|
|
24
|
+
/** A to one relation with an automatically generated field */
|
|
25
|
+
static toOne<entityType, toEntityType>(toEntityType: () => ClassType<toEntityType>, options?: FieldOptions<entityType, toEntityType> & Pick<RelationOptions<entityType, toEntityType, any, any>, 'defaultIncluded'>): ClassFieldDecorator<entityType, toEntityType | undefined>;
|
|
26
|
+
/** A to one relation with fields defined in the second parameter */
|
|
27
|
+
static toOne<entityType, toEntityType>(toEntityType: () => ClassType<toEntityType>, fieldInMyEntity?: keyof entityType): ClassFieldDecorator<entityType, toEntityType | undefined>;
|
|
28
|
+
/** A to one relation with fields defined in the field/fields parameter */
|
|
29
|
+
static toOne<entityType, toEntityType>(toEntityType: () => ClassType<toEntityType>, options: Omit<RelationOptions<entityType, toEntityType, entityType>, keyof Pick<RelationOptions<entityType, toEntityType, entityType>, 'field'>>): ClassFieldDecorator<entityType, toEntityType | undefined>;
|
|
30
|
+
/** A to one relation with fields defined in the field/fields parameter */
|
|
31
|
+
static toOne<entityType, toEntityType>(toEntityType: () => ClassType<toEntityType>, options: Omit<RelationOptions<entityType, toEntityType, entityType>, keyof Pick<RelationOptions<entityType, toEntityType, entityType>, 'fields'>>): ClassFieldDecorator<entityType, toEntityType | undefined>;
|
|
32
|
+
static toMany<entityType, toEntityType>(toEntityType: () => ClassType<toEntityType>, fieldInToEntity?: keyof toEntityType): ClassFieldDecorator<entityType, toEntityType[] | undefined>;
|
|
33
|
+
static toMany<entityType, toEntityType>(toEntityType: () => ClassType<toEntityType>, options: RelationOptions<entityType, toEntityType, toEntityType, FindOptions<toEntityType>>): ClassFieldDecorator<entityType, toEntityType[] | undefined>;
|
|
34
|
+
}
|
|
35
|
+
/**Decorates fields that should be used as fields.
|
|
36
|
+
* for more info see: [Field Types](https://remult.dev/docs/field-types.html)
|
|
37
|
+
*
|
|
38
|
+
* FieldOptions can be set in two ways:
|
|
39
|
+
* @example
|
|
40
|
+
* // as an object
|
|
41
|
+
* @Fields.string({ includeInApi:false })
|
|
42
|
+
* title='';
|
|
43
|
+
* @example
|
|
44
|
+
* // as an arrow function that receives `remult` as a parameter
|
|
45
|
+
* @Fields.string((options,remult) => options.includeInApi = true)
|
|
46
|
+
* title='';
|
|
47
|
+
*/
|
|
48
|
+
export declare function Field<entityType = any, valueType = any>(valueType: (() => ClassType<valueType>) | undefined, ...options: (FieldOptions<entityType, valueType> | ((options: FieldOptions<entityType, valueType>, remult: Remult) => void))[]): (target: any, context: ClassFieldDecoratorContextStub<entityType, valueType | undefined> | string, c?: any) => void;
|
|
49
|
+
export interface StringFieldOptions<entityType = any> extends FieldOptions<entityType, string> {
|
|
50
|
+
maxLength?: number;
|
|
51
|
+
}
|
|
52
|
+
export declare function checkTarget(target: any): void;
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { createId } from '@paralleldrive/cuid2';
|
|
2
|
+
import { v4 as uuid } from 'uuid';
|
|
3
|
+
import { ValueConverters } from '../valueConverters';
|
|
4
|
+
import { buildOptions, columnsOfType } from './RepositoryImplementation';
|
|
5
|
+
import { relationInfoMember } from './relationInfoMember';
|
|
6
|
+
export class Fields {
|
|
7
|
+
/**
|
|
8
|
+
* Stored as a JSON.stringify - to store as json use Fields.json
|
|
9
|
+
*/
|
|
10
|
+
static object(...options) {
|
|
11
|
+
return Field(undefined, ...options);
|
|
12
|
+
}
|
|
13
|
+
static json(...options) {
|
|
14
|
+
return Field(undefined, {
|
|
15
|
+
valueConverter: {
|
|
16
|
+
fieldTypeInDb: 'json',
|
|
17
|
+
},
|
|
18
|
+
}, ...options);
|
|
19
|
+
}
|
|
20
|
+
static dateOnly(...options) {
|
|
21
|
+
return Field(() => Date, {
|
|
22
|
+
valueConverter: ValueConverters.DateOnly,
|
|
23
|
+
}, ...options);
|
|
24
|
+
}
|
|
25
|
+
static date(...options) {
|
|
26
|
+
return Field(() => Date, ...options);
|
|
27
|
+
}
|
|
28
|
+
static integer(...options) {
|
|
29
|
+
return Field(() => Number, {
|
|
30
|
+
valueConverter: ValueConverters.Integer,
|
|
31
|
+
}, ...options);
|
|
32
|
+
}
|
|
33
|
+
static autoIncrement(...options) {
|
|
34
|
+
return Field(() => Number, {
|
|
35
|
+
allowApiUpdate: false,
|
|
36
|
+
dbReadOnly: true,
|
|
37
|
+
valueConverter: {
|
|
38
|
+
...ValueConverters.Integer,
|
|
39
|
+
fieldTypeInDb: 'autoincrement',
|
|
40
|
+
},
|
|
41
|
+
}, ...options);
|
|
42
|
+
}
|
|
43
|
+
static number(...options) {
|
|
44
|
+
return Field(() => Number, ...options);
|
|
45
|
+
}
|
|
46
|
+
static createdAt(...options) {
|
|
47
|
+
return Field(() => Date, {
|
|
48
|
+
allowApiUpdate: false,
|
|
49
|
+
saving: (_, { isNew }, ref) => {
|
|
50
|
+
if (isNew)
|
|
51
|
+
ref.value = new Date();
|
|
52
|
+
},
|
|
53
|
+
}, ...options);
|
|
54
|
+
}
|
|
55
|
+
static updatedAt(...options) {
|
|
56
|
+
return Field(() => Date, {
|
|
57
|
+
allowApiUpdate: false,
|
|
58
|
+
saving: (_, _1, ref) => {
|
|
59
|
+
ref.value = new Date();
|
|
60
|
+
},
|
|
61
|
+
}, ...options);
|
|
62
|
+
}
|
|
63
|
+
static uuid(...options) {
|
|
64
|
+
return Field(() => String, {
|
|
65
|
+
allowApiUpdate: false,
|
|
66
|
+
defaultValue: () => uuid(),
|
|
67
|
+
saving: (_, _1, r) => {
|
|
68
|
+
if (!r.value)
|
|
69
|
+
r.value = uuid();
|
|
70
|
+
},
|
|
71
|
+
}, ...options);
|
|
72
|
+
}
|
|
73
|
+
static cuid(...options) {
|
|
74
|
+
return Field(() => String, {
|
|
75
|
+
allowApiUpdate: false,
|
|
76
|
+
defaultValue: () => createId(),
|
|
77
|
+
saving: (_, _1, r) => {
|
|
78
|
+
if (!r.value)
|
|
79
|
+
r.value = createId();
|
|
80
|
+
},
|
|
81
|
+
}, ...options);
|
|
82
|
+
}
|
|
83
|
+
static string(...options) {
|
|
84
|
+
return Field(() => String, ...options);
|
|
85
|
+
}
|
|
86
|
+
static boolean(...options) {
|
|
87
|
+
return Field(() => Boolean, ...options);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
export class Relations {
|
|
91
|
+
static toOne(toEntityType, options) {
|
|
92
|
+
let op = (typeof options === 'string'
|
|
93
|
+
? { field: options }
|
|
94
|
+
: !options
|
|
95
|
+
? {}
|
|
96
|
+
: options);
|
|
97
|
+
if (!op.field && !op.fields && !op.findOptions)
|
|
98
|
+
return Field(toEntityType, {
|
|
99
|
+
...op,
|
|
100
|
+
//@ts-ignore
|
|
101
|
+
[relationInfoMember]: {
|
|
102
|
+
//field,
|
|
103
|
+
toType: toEntityType,
|
|
104
|
+
type: 'reference',
|
|
105
|
+
},
|
|
106
|
+
});
|
|
107
|
+
return Field(() => undefined, {
|
|
108
|
+
...op,
|
|
109
|
+
serverExpression: () => undefined,
|
|
110
|
+
//@ts-ignore
|
|
111
|
+
[relationInfoMember]: {
|
|
112
|
+
//field,
|
|
113
|
+
toType: toEntityType,
|
|
114
|
+
type: 'toOne',
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
static toMany(toEntityType, options) {
|
|
119
|
+
let op = (typeof options === 'string'
|
|
120
|
+
? { field: options }
|
|
121
|
+
: options);
|
|
122
|
+
return Field(() => undefined, {
|
|
123
|
+
...op,
|
|
124
|
+
serverExpression: () => undefined,
|
|
125
|
+
//@ts-ignore
|
|
126
|
+
[relationInfoMember]: {
|
|
127
|
+
//field,
|
|
128
|
+
toType: toEntityType,
|
|
129
|
+
type: 'toMany',
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**Decorates fields that should be used as fields.
|
|
135
|
+
* for more info see: [Field Types](https://remult.dev/docs/field-types.html)
|
|
136
|
+
*
|
|
137
|
+
* FieldOptions can be set in two ways:
|
|
138
|
+
* @example
|
|
139
|
+
* // as an object
|
|
140
|
+
* @Fields.string({ includeInApi:false })
|
|
141
|
+
* title='';
|
|
142
|
+
* @example
|
|
143
|
+
* // as an arrow function that receives `remult` as a parameter
|
|
144
|
+
* @Fields.string((options,remult) => options.includeInApi = true)
|
|
145
|
+
* title='';
|
|
146
|
+
*/
|
|
147
|
+
export function Field(valueType, ...options) {
|
|
148
|
+
// import ANT!!!! if you call this in another decorator, make sure to set It's return type correctly with the | undefined
|
|
149
|
+
return (target, context, c) => {
|
|
150
|
+
const key = typeof context === 'string' ? context : context.name.toString();
|
|
151
|
+
let factory = (remult) => {
|
|
152
|
+
let r = buildOptions(options, remult);
|
|
153
|
+
if (!r.valueType && valueType) {
|
|
154
|
+
r.valueType = valueType();
|
|
155
|
+
}
|
|
156
|
+
if (!r.key) {
|
|
157
|
+
r.key = key;
|
|
158
|
+
}
|
|
159
|
+
if (!r.dbName)
|
|
160
|
+
r.dbName = r.key;
|
|
161
|
+
let type = r.valueType;
|
|
162
|
+
if (!type) {
|
|
163
|
+
type = Reflect.getMetadata('design:type', target, key);
|
|
164
|
+
r.valueType = type;
|
|
165
|
+
}
|
|
166
|
+
if (!r.target)
|
|
167
|
+
r.target = target;
|
|
168
|
+
return r;
|
|
169
|
+
};
|
|
170
|
+
checkTarget(target);
|
|
171
|
+
let names = columnsOfType.get(target.constructor);
|
|
172
|
+
if (!names) {
|
|
173
|
+
names = [];
|
|
174
|
+
columnsOfType.set(target.constructor, names);
|
|
175
|
+
}
|
|
176
|
+
let set = names.find((x) => x.key == key);
|
|
177
|
+
if (!set)
|
|
178
|
+
names.push({
|
|
179
|
+
key,
|
|
180
|
+
settings: factory,
|
|
181
|
+
});
|
|
182
|
+
else {
|
|
183
|
+
let prev = set.settings;
|
|
184
|
+
set.settings = (c) => {
|
|
185
|
+
let prevO = prev(c);
|
|
186
|
+
let curr = factory(c);
|
|
187
|
+
return Object.assign(prevO, curr);
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
export function checkTarget(target) {
|
|
193
|
+
if (!target)
|
|
194
|
+
throw new Error("Set the 'experimentalDecorators:true' option in your 'tsconfig' or 'jsconfig' (target undefined)");
|
|
195
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { __decorate, __metadata } from "tslib";
|
|
2
|
+
import { Fields } from './Fields';
|
|
3
|
+
import { EntityBase } from './RepositoryImplementation';
|
|
4
|
+
export class IdEntity extends EntityBase {
|
|
5
|
+
id;
|
|
6
|
+
}
|
|
7
|
+
__decorate([
|
|
8
|
+
Fields.uuid(),
|
|
9
|
+
__metadata("design:type", String)
|
|
10
|
+
], IdEntity.prototype, "id", void 0);
|
|
@@ -98,7 +98,7 @@ declare abstract class rowHelperBase<T> {
|
|
|
98
98
|
__validateEntity(): Promise<void>;
|
|
99
99
|
__performColumnAndEntityValidations(): Promise<void>;
|
|
100
100
|
toApiJson(includeRelatedEntities?: boolean): any;
|
|
101
|
-
_updateEntityBasedOnApi(body: any): Promise<void>;
|
|
101
|
+
_updateEntityBasedOnApi(body: any, ignoreApiAllowed?: boolean): Promise<void>;
|
|
102
102
|
}
|
|
103
103
|
export declare class rowHelperImplementation<T> extends rowHelperBase<T> implements EntityRef<T> {
|
|
104
104
|
private info;
|
|
@@ -815,13 +815,14 @@ class rowHelperBase {
|
|
|
815
815
|
}
|
|
816
816
|
return result;
|
|
817
817
|
}
|
|
818
|
-
async _updateEntityBasedOnApi(body) {
|
|
818
|
+
async _updateEntityBasedOnApi(body, ignoreApiAllowed = false) {
|
|
819
819
|
let keys = Object.keys(body);
|
|
820
820
|
for (const col of this.columnsInfo) {
|
|
821
821
|
if (keys.includes(col.key))
|
|
822
822
|
if (col.includeInApi === undefined ||
|
|
823
823
|
this.remult.isAllowed(col.includeInApi)) {
|
|
824
824
|
if (!this.remult ||
|
|
825
|
+
ignoreApiAllowed ||
|
|
825
826
|
col.allowApiUpdate === undefined ||
|
|
826
827
|
this.remult.isAllowedForInstance(this.instance, col.allowApiUpdate)) {
|
|
827
828
|
let lu = this.lookups.get(col.key);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ClassType } from '../../classType';
|
|
2
|
+
import type { EntityMetadata, FindOptions } from './remult3';
|
|
3
|
+
export interface RelationLoaderHelper<toEntity> {
|
|
4
|
+
metadata: EntityMetadata<toEntity>;
|
|
5
|
+
entityType: ClassType<toEntity>;
|
|
6
|
+
find(options: FindOptions<toEntity>): Promise<toEntity[]>;
|
|
7
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { RelationLoaderHelper } from './relation-loader-types';
|
|
2
|
+
import type { FindOptions } from './remult3';
|
|
3
|
+
export declare class RelationLoader {
|
|
4
|
+
entityLoaders: Map<any, EntityLoader>;
|
|
5
|
+
promises: any[];
|
|
6
|
+
load(rel: RelationLoaderHelper<any>, findOptions: FindOptions<any>): Promise<any[]>;
|
|
7
|
+
constructor();
|
|
8
|
+
resolveAll(): Promise<void>;
|
|
9
|
+
}
|
|
10
|
+
declare class EntityLoader {
|
|
11
|
+
private rel;
|
|
12
|
+
queries: Map<string, QueryVariation>;
|
|
13
|
+
find(findOptions: FindOptions<any>): Promise<any[]>;
|
|
14
|
+
constructor(rel: RelationLoaderHelper<any>);
|
|
15
|
+
}
|
|
16
|
+
declare class QueryVariation {
|
|
17
|
+
private rel;
|
|
18
|
+
find(findOptions: FindOptions<any>, where: any): Promise<any[]>;
|
|
19
|
+
constructor(rel: RelationLoaderHelper<any>);
|
|
20
|
+
resolve(): void;
|
|
21
|
+
pendingInStatements: Map<string, PendingInStatements>;
|
|
22
|
+
whereVariations: Map<string, {
|
|
23
|
+
result: Promise<any[]>;
|
|
24
|
+
}>;
|
|
25
|
+
}
|
|
26
|
+
declare class PendingInStatements {
|
|
27
|
+
private rel;
|
|
28
|
+
private key;
|
|
29
|
+
private options;
|
|
30
|
+
resolve(): void;
|
|
31
|
+
find(where: any): Promise<any[]>;
|
|
32
|
+
values: Map<any, {
|
|
33
|
+
value: any;
|
|
34
|
+
resolve: (value: any[]) => void;
|
|
35
|
+
reject: (error: any) => void;
|
|
36
|
+
result: Promise<any[]>;
|
|
37
|
+
}>;
|
|
38
|
+
constructor(rel: RelationLoaderHelper<any>, key: string, options: FindOptions<any>);
|
|
39
|
+
}
|
|
40
|
+
export {};
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { findOptionsToJson } from '../data-providers/rest-data-provider';
|
|
2
|
+
import { getEntityRef } from './getEntityRef';
|
|
3
|
+
import { getRelationInfo } from './relationInfoMember';
|
|
4
|
+
export class RelationLoader {
|
|
5
|
+
entityLoaders = new Map();
|
|
6
|
+
promises = [];
|
|
7
|
+
load(rel, findOptions) {
|
|
8
|
+
let e = this.entityLoaders.get(rel.entityType);
|
|
9
|
+
if (!e) {
|
|
10
|
+
this.entityLoaders.set(rel.entityType, (e = new EntityLoader(rel)));
|
|
11
|
+
}
|
|
12
|
+
const p = e.find(findOptions);
|
|
13
|
+
this.promises.push(p);
|
|
14
|
+
return p;
|
|
15
|
+
}
|
|
16
|
+
constructor() { }
|
|
17
|
+
async resolveAll() {
|
|
18
|
+
for (const entity of this.entityLoaders.values()) {
|
|
19
|
+
for (const variation of entity.queries.values()) {
|
|
20
|
+
variation.resolve();
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
if (this.promises.length === 0)
|
|
24
|
+
return;
|
|
25
|
+
const x = this.promises;
|
|
26
|
+
this.promises = [];
|
|
27
|
+
await Promise.all(x);
|
|
28
|
+
await this.resolveAll();
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
class EntityLoader {
|
|
32
|
+
rel;
|
|
33
|
+
queries = new Map();
|
|
34
|
+
find(findOptions) {
|
|
35
|
+
const { where, ...options } = findOptionsToJson(findOptions, this.rel.metadata);
|
|
36
|
+
const optionKeys = JSON.stringify(options);
|
|
37
|
+
let q = this.queries.get(optionKeys);
|
|
38
|
+
if (!q) {
|
|
39
|
+
this.queries.set(optionKeys, (q = new QueryVariation(this.rel)));
|
|
40
|
+
}
|
|
41
|
+
return q.find(findOptions, where);
|
|
42
|
+
}
|
|
43
|
+
constructor(rel) {
|
|
44
|
+
this.rel = rel;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
class QueryVariation {
|
|
48
|
+
rel;
|
|
49
|
+
find(findOptions, where) {
|
|
50
|
+
const whereKey = JSON.stringify(where);
|
|
51
|
+
let w = this.whereVariations.get(whereKey);
|
|
52
|
+
if (!w) {
|
|
53
|
+
const keys = Object.keys(where);
|
|
54
|
+
if (keys.length === 1 &&
|
|
55
|
+
typeof where[keys[0]] !== 'object' &&
|
|
56
|
+
!findOptions.limit // because merging calls in that case may bring non more rows than the limit
|
|
57
|
+
) {
|
|
58
|
+
let inVariation = this.pendingInStatements.get(keys[0]);
|
|
59
|
+
if (!inVariation) {
|
|
60
|
+
this.pendingInStatements.set(keys[0], (inVariation = new PendingInStatements(this.rel, keys[0], findOptions)));
|
|
61
|
+
}
|
|
62
|
+
this.whereVariations.set(whereKey, (w = {
|
|
63
|
+
result: inVariation.find(where),
|
|
64
|
+
}));
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
this.whereVariations.set(whereKey, (w = {
|
|
68
|
+
result: this.rel.find(findOptions),
|
|
69
|
+
}));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return w.result;
|
|
73
|
+
}
|
|
74
|
+
constructor(rel) {
|
|
75
|
+
this.rel = rel;
|
|
76
|
+
}
|
|
77
|
+
resolve() {
|
|
78
|
+
const statements = [...this.pendingInStatements.values()];
|
|
79
|
+
this.pendingInStatements.clear();
|
|
80
|
+
for (const statement of statements) {
|
|
81
|
+
statement.resolve();
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
pendingInStatements = new Map();
|
|
85
|
+
whereVariations = new Map();
|
|
86
|
+
}
|
|
87
|
+
class PendingInStatements {
|
|
88
|
+
rel;
|
|
89
|
+
key;
|
|
90
|
+
options;
|
|
91
|
+
resolve() {
|
|
92
|
+
const values = [...this.values.values()];
|
|
93
|
+
if (values.length == 1) {
|
|
94
|
+
this.rel.find(this.options).then(values[0].resolve, values[0].reject);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
var op = { ...this.options };
|
|
98
|
+
op.where = { [this.key]: values.map((v) => v.value) };
|
|
99
|
+
this.rel.find(op).then((val) => {
|
|
100
|
+
for (const value of this.values.values()) {
|
|
101
|
+
value.resolve(val.filter((x) => {
|
|
102
|
+
const ref = getEntityRef(x);
|
|
103
|
+
const field = ref.fields.find(this.key);
|
|
104
|
+
const rel = getRelationInfo(field.metadata.options);
|
|
105
|
+
const val = rel?.type === 'reference'
|
|
106
|
+
? field.getId()
|
|
107
|
+
: x[this.key];
|
|
108
|
+
return value.value == val;
|
|
109
|
+
}));
|
|
110
|
+
}
|
|
111
|
+
}, (err) => {
|
|
112
|
+
for (const value of this.values.values()) {
|
|
113
|
+
value.reject(err);
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
find(where) {
|
|
118
|
+
const val = where[this.key];
|
|
119
|
+
let valHandler = this.values.get(val);
|
|
120
|
+
if (!valHandler) {
|
|
121
|
+
let resolve;
|
|
122
|
+
let reject;
|
|
123
|
+
let result = new Promise((resolve1, reject1) => {
|
|
124
|
+
resolve = resolve1;
|
|
125
|
+
reject = reject1;
|
|
126
|
+
});
|
|
127
|
+
this.values.set(val, (valHandler = {
|
|
128
|
+
value: val,
|
|
129
|
+
resolve,
|
|
130
|
+
reject,
|
|
131
|
+
result,
|
|
132
|
+
}));
|
|
133
|
+
}
|
|
134
|
+
return valHandler.result;
|
|
135
|
+
}
|
|
136
|
+
values = new Map();
|
|
137
|
+
constructor(rel, key, options) {
|
|
138
|
+
this.rel = rel;
|
|
139
|
+
this.key = key;
|
|
140
|
+
this.options = options;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
@@ -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";
|
package/esm/src/server-action.js
CHANGED
|
@@ -267,7 +267,7 @@ export function BackendMethod(options) {
|
|
|
267
267
|
id: defs.getOriginalId(),
|
|
268
268
|
},
|
|
269
269
|
}, baseUrl, http);
|
|
270
|
-
await defs._updateEntityBasedOnApi(r.rowInfo.data);
|
|
270
|
+
await defs._updateEntityBasedOnApi(r.rowInfo.data, true);
|
|
271
271
|
return r.result;
|
|
272
272
|
}
|
|
273
273
|
catch (err) {
|
package/internals.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { getRelationInfo } from './src/remult3/relationInfoMember';
|
|
2
|
+
export { decorateColumnSettings, controllerRefImpl, getControllerRef, } from './src/remult3/RepositoryImplementation';
|
|
3
|
+
export { getEntitySettings } from './src/remult3/getEntityRef';
|
|
4
|
+
export { __updateEntityBasedOnWhere } from './src/filter/filter-interfaces';
|
|
5
|
+
export { actionInfo } from './src/server-action-info';
|
|
6
|
+
export { RelationInfo } from './src/remult3/remult3';
|
|
7
|
+
export { ClassType } from './classType';
|
package/internals.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.actionInfo = exports.__updateEntityBasedOnWhere = exports.getEntitySettings = exports.getControllerRef = exports.controllerRefImpl = exports.decorateColumnSettings = exports.getRelationInfo = void 0;
|
|
4
|
+
var relationInfoMember_1 = require("./src/remult3/relationInfoMember");
|
|
5
|
+
Object.defineProperty(exports, "getRelationInfo", { enumerable: true, get: function () { return relationInfoMember_1.getRelationInfo; } });
|
|
6
|
+
var RepositoryImplementation_1 = require("./src/remult3/RepositoryImplementation");
|
|
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; } });
|
|
10
|
+
var getEntityRef_1 = require("./src/remult3/getEntityRef");
|
|
11
|
+
Object.defineProperty(exports, "getEntitySettings", { enumerable: true, get: function () { return getEntityRef_1.getEntitySettings; } });
|
|
12
|
+
var filter_interfaces_1 = require("./src/filter/filter-interfaces");
|
|
13
|
+
Object.defineProperty(exports, "__updateEntityBasedOnWhere", { enumerable: true, get: function () { return filter_interfaces_1.__updateEntityBasedOnWhere; } });
|
|
14
|
+
var server_action_info_1 = require("./src/server-action-info");
|
|
15
|
+
Object.defineProperty(exports, "actionInfo", { enumerable: true, get: function () { return server_action_info_1.actionInfo; } });
|
package/package.json
CHANGED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { ClassType } from '../../classType';
|
|
2
|
+
import type { FieldOptions } from '../column-interfaces';
|
|
3
|
+
import type { Remult } from '../context';
|
|
4
|
+
import type { FindOptions, RelationOptions, ClassFieldDecorator, ClassFieldDecoratorContextStub } from './remult3';
|
|
5
|
+
export declare class Fields {
|
|
6
|
+
/**
|
|
7
|
+
* Stored as a JSON.stringify - to store as json use Fields.json
|
|
8
|
+
*/
|
|
9
|
+
static object<entityType = any, valueType = any>(...options: (FieldOptions<entityType, valueType> | ((options: FieldOptions<entityType, valueType>, remult: Remult) => void))[]): ClassFieldDecorator<entityType, valueType | undefined>;
|
|
10
|
+
static json<entityType = any, valueType = any>(...options: (FieldOptions<entityType, valueType> | ((options: FieldOptions<entityType, valueType>, remult: Remult) => void))[]): ClassFieldDecorator<entityType, valueType | undefined>;
|
|
11
|
+
static dateOnly<entityType = any>(...options: (FieldOptions<entityType, Date> | ((options: FieldOptions<entityType, Date>, remult: Remult) => void))[]): ClassFieldDecorator<entityType, Date | undefined>;
|
|
12
|
+
static date<entityType = any>(...options: (FieldOptions<entityType, Date> | ((options: FieldOptions<entityType, Date>, remult: Remult) => void))[]): ClassFieldDecorator<entityType, Date | undefined>;
|
|
13
|
+
static integer<entityType = any>(...options: (FieldOptions<entityType, Number> | ((options: FieldOptions<entityType, Number>, remult: Remult) => void))[]): ClassFieldDecorator<entityType, number | undefined>;
|
|
14
|
+
static autoIncrement<entityType = any>(...options: (FieldOptions<entityType, Number> | ((options: FieldOptions<entityType, Number>, remult: Remult) => void))[]): ClassFieldDecorator<entityType, number | undefined>;
|
|
15
|
+
static number<entityType = any>(...options: (FieldOptions<entityType, Number> | ((options: FieldOptions<entityType, Number>, remult: Remult) => void))[]): ClassFieldDecorator<entityType, number | undefined>;
|
|
16
|
+
static createdAt<entityType = any>(...options: (FieldOptions<entityType, Date> | ((options: FieldOptions<entityType, Date>, remult: Remult) => void))[]): ClassFieldDecorator<entityType, Date | undefined>;
|
|
17
|
+
static updatedAt<entityType = any>(...options: (FieldOptions<entityType, Date> | ((options: FieldOptions<entityType, Date>, remult: Remult) => void))[]): ClassFieldDecorator<entityType, Date | undefined>;
|
|
18
|
+
static uuid<entityType = any>(...options: (FieldOptions<entityType, string> | ((options: FieldOptions<entityType, string>, remult: Remult) => void))[]): ClassFieldDecorator<entityType, string | undefined>;
|
|
19
|
+
static cuid<entityType = any>(...options: (FieldOptions<entityType, string> | ((options: FieldOptions<entityType, string>, remult: Remult) => void))[]): ClassFieldDecorator<entityType, string | undefined>;
|
|
20
|
+
static string<entityType = any>(...options: (StringFieldOptions<entityType> | ((options: StringFieldOptions<entityType>, remult: Remult) => void))[]): ClassFieldDecorator<entityType, string | undefined>;
|
|
21
|
+
static boolean<entityType = any>(...options: (FieldOptions<entityType, boolean> | ((options: FieldOptions<entityType, boolean>, remult: Remult) => void))[]): ClassFieldDecorator<entityType, boolean | undefined>;
|
|
22
|
+
}
|
|
23
|
+
export declare class Relations {
|
|
24
|
+
/** A to one relation with an automatically generated field */
|
|
25
|
+
static toOne<entityType, toEntityType>(toEntityType: () => ClassType<toEntityType>, options?: FieldOptions<entityType, toEntityType> & Pick<RelationOptions<entityType, toEntityType, any, any>, 'defaultIncluded'>): ClassFieldDecorator<entityType, toEntityType | undefined>;
|
|
26
|
+
/** A to one relation with fields defined in the second parameter */
|
|
27
|
+
static toOne<entityType, toEntityType>(toEntityType: () => ClassType<toEntityType>, fieldInMyEntity?: keyof entityType): ClassFieldDecorator<entityType, toEntityType | undefined>;
|
|
28
|
+
/** A to one relation with fields defined in the field/fields parameter */
|
|
29
|
+
static toOne<entityType, toEntityType>(toEntityType: () => ClassType<toEntityType>, options: Omit<RelationOptions<entityType, toEntityType, entityType>, keyof Pick<RelationOptions<entityType, toEntityType, entityType>, 'field'>>): ClassFieldDecorator<entityType, toEntityType | undefined>;
|
|
30
|
+
/** A to one relation with fields defined in the field/fields parameter */
|
|
31
|
+
static toOne<entityType, toEntityType>(toEntityType: () => ClassType<toEntityType>, options: Omit<RelationOptions<entityType, toEntityType, entityType>, keyof Pick<RelationOptions<entityType, toEntityType, entityType>, 'fields'>>): ClassFieldDecorator<entityType, toEntityType | undefined>;
|
|
32
|
+
static toMany<entityType, toEntityType>(toEntityType: () => ClassType<toEntityType>, fieldInToEntity?: keyof toEntityType): ClassFieldDecorator<entityType, toEntityType[] | undefined>;
|
|
33
|
+
static toMany<entityType, toEntityType>(toEntityType: () => ClassType<toEntityType>, options: RelationOptions<entityType, toEntityType, toEntityType, FindOptions<toEntityType>>): ClassFieldDecorator<entityType, toEntityType[] | undefined>;
|
|
34
|
+
}
|
|
35
|
+
/**Decorates fields that should be used as fields.
|
|
36
|
+
* for more info see: [Field Types](https://remult.dev/docs/field-types.html)
|
|
37
|
+
*
|
|
38
|
+
* FieldOptions can be set in two ways:
|
|
39
|
+
* @example
|
|
40
|
+
* // as an object
|
|
41
|
+
* @Fields.string({ includeInApi:false })
|
|
42
|
+
* title='';
|
|
43
|
+
* @example
|
|
44
|
+
* // as an arrow function that receives `remult` as a parameter
|
|
45
|
+
* @Fields.string((options,remult) => options.includeInApi = true)
|
|
46
|
+
* title='';
|
|
47
|
+
*/
|
|
48
|
+
export declare function Field<entityType = any, valueType = any>(valueType: (() => ClassType<valueType>) | undefined, ...options: (FieldOptions<entityType, valueType> | ((options: FieldOptions<entityType, valueType>, remult: Remult) => void))[]): (target: any, context: ClassFieldDecoratorContextStub<entityType, valueType | undefined> | string, c?: any) => void;
|
|
49
|
+
export interface StringFieldOptions<entityType = any> extends FieldOptions<entityType, string> {
|
|
50
|
+
maxLength?: number;
|
|
51
|
+
}
|
|
52
|
+
export declare function checkTarget(target: any): void;
|