remult 0.23.0-exp.2 → 0.23.0-exp.20
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/README.md +26 -27
- package/esm/graphql.js +7 -1
- package/esm/index.d.ts +16 -3
- package/esm/index.js +17 -2
- package/esm/internals.d.ts +2 -1
- package/esm/internals.js +1 -1
- package/esm/remult-express.js +1 -1
- package/esm/remult-knex/index.js +2 -1
- package/esm/remult-mongo.js +2 -1
- package/esm/server/JsonEntityFileStorage.js +1 -1
- package/esm/server/expressBridge.js +1 -1
- package/esm/src/CompoundIdField.d.ts +1 -1
- package/esm/src/CompoundIdField.js +3 -1
- package/esm/src/buildRestDataProvider.d.ts +1 -2
- package/esm/src/column-interfaces.d.ts +19 -7
- package/esm/src/column.d.ts +4 -18
- package/esm/src/column.js +10 -44
- package/esm/src/context.d.ts +1 -1
- package/esm/src/context.js +5 -1
- package/esm/src/data-interfaces.js +1 -2
- package/esm/src/data-providers/array-entity-data-provider.d.ts +1 -1
- package/esm/src/data-providers/array-entity-data-provider.js +6 -6
- package/esm/src/data-providers/sql-database.js +2 -1
- package/esm/src/data-providers/web-sql-data-provider.js +3 -3
- package/esm/src/entity.d.ts +48 -17
- package/esm/src/filter/filter-interfaces.d.ts +2 -16
- package/esm/src/filter/filter-interfaces.js +87 -6
- package/esm/src/live-query/LiveQueryClient.js +2 -1
- package/esm/src/live-query/SubscriptionChannel.js +4 -3
- package/esm/src/remult-proxy.js +10 -2
- package/esm/src/remult3/Fields.d.ts +140 -21
- package/esm/src/remult3/Fields.js +26 -30
- package/esm/src/remult3/RepositoryImplementation.d.ts +10 -16
- package/esm/src/remult3/RepositoryImplementation.js +165 -48
- package/esm/src/remult3/entity.d.ts +1 -1
- package/esm/src/remult3/entity.js +0 -1
- package/esm/src/remult3/getEntityRef.d.ts +1 -1
- package/esm/src/remult3/getEntityRef.js +1 -1
- package/esm/src/remult3/relation-loader.js +4 -1
- package/esm/src/remult3/remult3.d.ts +132 -7
- package/esm/src/remult3/remult3.js +30 -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/esm/src/sort.d.ts +3 -3
- package/esm/src/sort.js +39 -8
- package/graphql.js +10 -2
- package/index.d.ts +16 -3
- package/index.js +19 -3
- package/internals.d.ts +2 -1
- package/internals.js +3 -1
- package/package.json +1 -1
- package/remult-express.js +1 -1
- package/remult-knex/index.js +2 -1
- package/remult-mongo.js +2 -1
- package/server/JsonEntityFileStorage.js +1 -1
- package/server/expressBridge.js +1 -1
- package/src/CompoundIdField.d.ts +1 -1
- package/src/CompoundIdField.js +3 -0
- package/src/buildRestDataProvider.d.ts +1 -2
- package/src/column-interfaces.d.ts +19 -7
- package/src/column.d.ts +4 -18
- package/src/column.js +10 -56
- package/src/context.d.ts +1 -1
- package/src/context.js +5 -1
- package/src/data-interfaces.js +1 -2
- package/src/data-providers/array-entity-data-provider.d.ts +1 -1
- package/src/data-providers/array-entity-data-provider.js +5 -6
- package/src/data-providers/sql-database.js +2 -1
- package/src/data-providers/web-sql-data-provider.js +3 -3
- package/src/entity.d.ts +48 -17
- package/src/filter/filter-interfaces.d.ts +2 -16
- package/src/filter/filter-interfaces.js +101 -9
- package/src/live-query/LiveQueryClient.js +2 -1
- package/src/live-query/SubscriptionChannel.js +4 -3
- package/src/remult-proxy.js +43 -29
- package/src/remult3/Fields.d.ts +140 -21
- package/src/remult3/Fields.js +32 -32
- package/src/remult3/RepositoryImplementation.d.ts +10 -16
- package/src/remult3/RepositoryImplementation.js +286 -163
- package/src/remult3/entity.d.ts +1 -1
- package/src/remult3/entity.js +0 -1
- package/src/remult3/getEntityRef.d.ts +1 -1
- package/src/remult3/getEntityRef.js +2 -1
- package/src/remult3/relation-loader.js +4 -1
- package/src/remult3/remult3.d.ts +132 -7
- package/src/remult3/remult3.js +30 -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
- package/src/sort.d.ts +3 -3
- package/src/sort.js +46 -11
package/README.md
CHANGED
|
@@ -22,7 +22,6 @@
|
|
|
22
22
|
<a href="https://discord.gg/GXHk7ZfuG5" rel="nofollow">
|
|
23
23
|
<img alt="Join Discord" src="https://badgen.net/discord/online-members/GXHk7ZfuG5?icon=discord&label=Discord"/>
|
|
24
24
|
</a>
|
|
25
|
-
</a>
|
|
26
25
|
</div>
|
|
27
26
|
|
|
28
27
|
<br/>
|
|
@@ -101,14 +100,14 @@ npm i remult
|
|
|
101
100
|
```ts
|
|
102
101
|
// shared/product.ts
|
|
103
102
|
|
|
104
|
-
import { Entity, Fields } from
|
|
103
|
+
import { Entity, Fields } from 'remult'
|
|
105
104
|
|
|
106
|
-
@Entity(
|
|
107
|
-
allowApiCrud: true
|
|
105
|
+
@Entity('products', {
|
|
106
|
+
allowApiCrud: true,
|
|
108
107
|
})
|
|
109
108
|
export class Product {
|
|
110
109
|
@Fields.string()
|
|
111
|
-
name =
|
|
110
|
+
name = ''
|
|
112
111
|
|
|
113
112
|
@Fields.number()
|
|
114
113
|
unitPrice = 0
|
|
@@ -120,17 +119,17 @@ export class Product {
|
|
|
120
119
|
```ts
|
|
121
120
|
// backend/index.ts
|
|
122
121
|
|
|
123
|
-
import express from
|
|
124
|
-
import { remultExpress } from
|
|
125
|
-
import { Product } from
|
|
122
|
+
import express from 'express'
|
|
123
|
+
import { remultExpress } from 'remult/remult-express'
|
|
124
|
+
import { Product } from '../shared/product'
|
|
126
125
|
|
|
127
126
|
const port = 3001
|
|
128
127
|
const app = express()
|
|
129
128
|
|
|
130
129
|
app.use(
|
|
131
130
|
remultExpress({
|
|
132
|
-
entities: [Product]
|
|
133
|
-
})
|
|
131
|
+
entities: [Product],
|
|
132
|
+
}),
|
|
134
133
|
)
|
|
135
134
|
|
|
136
135
|
app.listen(port, () => {
|
|
@@ -151,13 +150,13 @@ app.listen(port, () => {
|
|
|
151
150
|
```ts
|
|
152
151
|
// frontend/code.ts
|
|
153
152
|
|
|
154
|
-
import { remult } from
|
|
155
|
-
import { Product } from
|
|
153
|
+
import { remult } from 'remult'
|
|
154
|
+
import { Product } from '../shared/product'
|
|
156
155
|
|
|
157
156
|
async function increasePriceOfTofu(priceIncrease: number) {
|
|
158
157
|
const productsRepo = remult.repo(Product)
|
|
159
158
|
|
|
160
|
-
const product = await productsRepo.findFirst({ name:
|
|
159
|
+
const product = await productsRepo.findFirst({ name: 'Tofu' }) // filter is passed through API request all the way to the db
|
|
161
160
|
product.unitPrice += priceIncrease
|
|
162
161
|
productsRepo.save(product) // mutation request updates the db with no boilerplate code
|
|
163
162
|
}
|
|
@@ -179,32 +178,32 @@ static async increasePriceOfTofu(priceIncrease: number) {
|
|
|
179
178
|
### :ballot_box_with_check: Data validation and constraints - defined once
|
|
180
179
|
|
|
181
180
|
```ts
|
|
182
|
-
import { Entity, Fields, Validators } from
|
|
181
|
+
import { Entity, Fields, Validators } from 'remult'
|
|
183
182
|
|
|
184
|
-
@Entity(
|
|
185
|
-
allowApiCrud: true
|
|
183
|
+
@Entity('products', {
|
|
184
|
+
allowApiCrud: true,
|
|
186
185
|
})
|
|
187
186
|
export class Product {
|
|
188
187
|
@Fields.string({
|
|
189
|
-
validate: Validators.required
|
|
188
|
+
validate: Validators.required,
|
|
190
189
|
})
|
|
191
|
-
name =
|
|
190
|
+
name = ''
|
|
192
191
|
|
|
193
192
|
@Fields.string<Product>({
|
|
194
193
|
validate: (product) => {
|
|
195
194
|
if (product.description.trim().length < 50) {
|
|
196
|
-
throw
|
|
195
|
+
throw 'too short'
|
|
197
196
|
}
|
|
198
|
-
}
|
|
197
|
+
},
|
|
199
198
|
})
|
|
200
|
-
description =
|
|
199
|
+
description = ''
|
|
201
200
|
|
|
202
201
|
@Fields.number({
|
|
203
202
|
validate: (_, field) => {
|
|
204
203
|
if (field.value < 0) {
|
|
205
|
-
field.error =
|
|
204
|
+
field.error = 'must not be less than 0' // or: throw "must not be less than 0";
|
|
206
205
|
}
|
|
207
|
-
}
|
|
206
|
+
},
|
|
208
207
|
})
|
|
209
208
|
unitPrice = 0
|
|
210
209
|
}
|
|
@@ -233,20 +232,20 @@ try {
|
|
|
233
232
|
### :lock: Secure the API with fine-grained authorization
|
|
234
233
|
|
|
235
234
|
```ts
|
|
236
|
-
@Entity<Article>(
|
|
235
|
+
@Entity<Article>('Articles', {
|
|
237
236
|
allowApiRead: true,
|
|
238
237
|
allowApiInsert: (_, remult) => remult.authenticated(),
|
|
239
|
-
allowApiUpdate: (article, remult) => article.author.id == remult.user.id
|
|
238
|
+
allowApiUpdate: (article, remult) => article.author.id == remult.user.id,
|
|
240
239
|
})
|
|
241
240
|
export class Article {
|
|
242
241
|
@Fields.string({ allowApiUpdate: false })
|
|
243
|
-
slug =
|
|
242
|
+
slug = ''
|
|
244
243
|
|
|
245
244
|
@Field(() => Profile, { allowApiUpdate: false })
|
|
246
245
|
author!: Profile
|
|
247
246
|
|
|
248
247
|
@Fields.string()
|
|
249
|
-
content =
|
|
248
|
+
content = ''
|
|
250
249
|
}
|
|
251
250
|
```
|
|
252
251
|
|
package/esm/graphql.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getRelationInfo } from './internals';
|
|
1
2
|
import { Remult, remult } from './index';
|
|
2
3
|
import { DataApi } from './src/data-api';
|
|
3
4
|
const v2ConnectionAndPagination = false;
|
|
@@ -447,6 +448,11 @@ Select a dedicated page.`,
|
|
|
447
448
|
}
|
|
448
449
|
const whereTypeFields = [];
|
|
449
450
|
for (const f of meta.fields) {
|
|
451
|
+
const ri = getRelationInfo(f.options);
|
|
452
|
+
// let's not consider toMany relations for now
|
|
453
|
+
if (ri?.type === 'toMany') {
|
|
454
|
+
break;
|
|
455
|
+
}
|
|
450
456
|
if (f.options.includeInApi === false)
|
|
451
457
|
continue;
|
|
452
458
|
let type = 'String';
|
|
@@ -788,7 +794,7 @@ export function translateWhereToRestBody(fields, { where }) {
|
|
|
788
794
|
return undefined;
|
|
789
795
|
const result = {};
|
|
790
796
|
for (const field of fields) {
|
|
791
|
-
if (field.
|
|
797
|
+
if (field.options.includeInApi === false)
|
|
792
798
|
continue;
|
|
793
799
|
const condition = where[field.key];
|
|
794
800
|
if (condition) {
|
package/esm/index.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
|
|
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/esm/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { EntityBase, ControllerBase, FieldType, getFields, ValueListFieldType, getValueList, ValueListInfo, CaptionTransformer, } from './src/remult3/RepositoryImplementation';
|
|
2
2
|
export { Entity } from './src/remult3/entity';
|
|
3
3
|
export { getEntityRef } from './src/remult3/getEntityRef';
|
|
4
|
-
export { Field, Fields } from './src/remult3/Fields';
|
|
4
|
+
export { Field, Fields, Relations, } from './src/remult3/Fields';
|
|
5
5
|
export { IdEntity } from './src/remult3/IdEntity';
|
|
6
6
|
export { describeClass } from './src/remult3/DecoratorReplacer';
|
|
7
7
|
export { RestDataProvider } from './src/data-providers/rest-data-provider'; //V
|
|
@@ -15,13 +15,28 @@ export { JsonDataProvider, } from './src/data-providers/json-data-provider'; //V
|
|
|
15
15
|
export { Controller, BackendMethod, ProgressListener, } from './src/server-action';
|
|
16
16
|
export { Allow, Remult, isBackend, EventSource, } from './src/context';
|
|
17
17
|
export { Sort } from './src/sort';
|
|
18
|
-
export { OneToMany } from './src/column';
|
|
19
18
|
export { CompoundIdField } from './src/CompoundIdField';
|
|
20
19
|
export { Filter } from './src/filter/filter-interfaces';
|
|
21
20
|
export { UrlBuilder } from './urlBuilder';
|
|
22
21
|
export { Validators } from './src/validators';
|
|
23
22
|
export { ValueConverters } from './src/valueConverters';
|
|
24
23
|
export { remult } from './src/remult-proxy';
|
|
24
|
+
import { remult } from './src/remult-proxy';
|
|
25
25
|
//export { getId } from './src/remult3/getId';
|
|
26
26
|
export { InMemoryLiveQueryStorage, } from './src/live-query/SubscriptionServer';
|
|
27
27
|
export { SubscriptionChannel, } from './src/live-query/SubscriptionChannel';
|
|
28
|
+
/**
|
|
29
|
+
* A convenient shortcut function to quickly obtain a repository for a specific entity type in Remult.
|
|
30
|
+
*
|
|
31
|
+
* @param entity The entity class type for which you want to get a repository.
|
|
32
|
+
* @returns A repository instance for the specified entity type.
|
|
33
|
+
*
|
|
34
|
+
* Example usage:
|
|
35
|
+
* ```ts
|
|
36
|
+
* await repo(Task).find()
|
|
37
|
+
* await repo(Customer).insert()
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export function repo(entity) {
|
|
41
|
+
return remult.repo(entity);
|
|
42
|
+
}
|
package/esm/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/esm/internals.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
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';
|
package/esm/remult-express.js
CHANGED
|
@@ -21,6 +21,6 @@ export function remultExpress(options) {
|
|
|
21
21
|
getRemult: (req) => server.getRemult(req),
|
|
22
22
|
openApiDoc: (options) => server.openApiDoc(options),
|
|
23
23
|
withRemult: (req, res, next) => server.withRemult(req, res, next),
|
|
24
|
-
// [ ]
|
|
24
|
+
// [ ] V1.5 add with remult promise
|
|
25
25
|
});
|
|
26
26
|
}
|
package/esm/remult-knex/index.js
CHANGED
|
@@ -7,6 +7,7 @@ import { getRepository, isAutoIncrement, } from '../src/remult3/RepositoryImplem
|
|
|
7
7
|
import { Sort } from '../src/sort';
|
|
8
8
|
import { ValueConverters } from '../src/valueConverters';
|
|
9
9
|
import { resultCompoundIdFilter as resultCompoundIdFilter } from '../src/resultCompoundIdFilter';
|
|
10
|
+
import { getRepositoryInternals } from '../src/remult3/repository-internals';
|
|
10
11
|
export class KnexDataProvider {
|
|
11
12
|
knex;
|
|
12
13
|
constructor(knex) {
|
|
@@ -54,7 +55,7 @@ export class KnexDataProvider {
|
|
|
54
55
|
const repo = getRepository(entity);
|
|
55
56
|
var b = new FilterConsumerBridgeToKnexRequest(await dbNamesOf(repo.metadata));
|
|
56
57
|
b._addWhere = false;
|
|
57
|
-
await (await repo.translateWhereToFilter(condition)).__applyToConsumer(b);
|
|
58
|
+
await (await getRepositoryInternals(repo).translateWhereToFilter(condition)).__applyToConsumer(b);
|
|
58
59
|
let r = await b.resolveWhere();
|
|
59
60
|
return (knex) => r.forEach((y) => y(knex));
|
|
60
61
|
}
|
package/esm/remult-mongo.js
CHANGED
|
@@ -3,6 +3,7 @@ import { dbNamesOf } from './src/filter/filter-consumer-bridge-to-sql-request';
|
|
|
3
3
|
import { remult as remultContext } from './src/remult-proxy';
|
|
4
4
|
import { getRepository } from './src/remult3/RepositoryImplementation';
|
|
5
5
|
import { resultCompoundIdFilter } from './src/resultCompoundIdFilter';
|
|
6
|
+
import { getRepositoryInternals } from './src/remult3/repository-internals';
|
|
6
7
|
export class MongoDataProvider {
|
|
7
8
|
db;
|
|
8
9
|
client;
|
|
@@ -50,7 +51,7 @@ export class MongoDataProvider {
|
|
|
50
51
|
const repo = getRepository(entity);
|
|
51
52
|
var b = new FilterConsumerBridgeToMongo(await dbNamesOf(repo.metadata));
|
|
52
53
|
b._addWhere = false;
|
|
53
|
-
await (await repo.translateWhereToFilter(condition)).__applyToConsumer(b);
|
|
54
|
+
await (await getRepositoryInternals(repo).translateWhereToFilter(condition)).__applyToConsumer(b);
|
|
54
55
|
let r = await b.resolveWhere();
|
|
55
56
|
return r;
|
|
56
57
|
}
|
|
@@ -116,7 +116,7 @@ export class RemultServerImplementation {
|
|
|
116
116
|
});
|
|
117
117
|
}
|
|
118
118
|
getEntities() {
|
|
119
|
-
//TODO - consider using entitiesMetaData - but it may require making it all awaitable
|
|
119
|
+
//TODO V2 - consider using entitiesMetaData - but it may require making it all awaitable
|
|
120
120
|
var r = new Remult();
|
|
121
121
|
return this.options.entities.map((x) => r.repo(x).metadata);
|
|
122
122
|
}
|
|
@@ -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>;
|
|
@@ -9,7 +9,9 @@ export class CompoundIdField {
|
|
|
9
9
|
displayValue(item) {
|
|
10
10
|
throw new Error('Method not implemented.');
|
|
11
11
|
}
|
|
12
|
-
includedInApi
|
|
12
|
+
includedInApi(item) {
|
|
13
|
+
throw new Error('Method not implemented.');
|
|
14
|
+
}
|
|
13
15
|
toInput(value, inputType) {
|
|
14
16
|
throw new Error('Method not implemented.');
|
|
15
17
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { RestDataProviderHttpProvider } from './data-interfaces';
|
|
2
|
-
|
|
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;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ClassType } from '../classType';
|
|
2
|
-
import type {
|
|
3
|
-
import type { EntityMetadata, FieldRef, OmitEB } from './remult3/remult3';
|
|
2
|
+
import type { AllowedForInstance } from './context';
|
|
3
|
+
import type { EntityMetadata, FieldRef, LifecycleEvent, OmitEB } 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
|
|
@@ -11,7 +11,7 @@ export interface FieldOptions<entityType = any, valueType = any> {
|
|
|
11
11
|
allowNull?: boolean;
|
|
12
12
|
/** If this field data is included in the api.
|
|
13
13
|
* @see [allowed](http://remult.dev/docs/allowed.html)*/
|
|
14
|
-
includeInApi?:
|
|
14
|
+
includeInApi?: AllowedForInstance<entityType>;
|
|
15
15
|
/** If this field data can be updated in the api.
|
|
16
16
|
* @see [allowed](http://remult.dev/docs/allowed.html)*/
|
|
17
17
|
allowApiUpdate?: AllowedForInstance<entityType>;
|
|
@@ -37,7 +37,7 @@ export interface FieldOptions<entityType = any, valueType = any> {
|
|
|
37
37
|
*/
|
|
38
38
|
validate?: ((entity: entityType, fieldRef: FieldRef<entityType, valueType>) => any | Promise<any>) | ((entity: entityType, fieldRef: FieldRef<entityType, valueType>) => any | Promise<any>)[];
|
|
39
39
|
/** Will be fired before this field is saved to the server/database */
|
|
40
|
-
saving?: (entity: entityType, fieldRef: FieldRef<entityType, valueType>) => any | Promise<any>;
|
|
40
|
+
saving?: (entity: entityType, e: LifecycleEvent<entityType>, fieldRef: FieldRef<entityType, valueType>) => any | Promise<any>;
|
|
41
41
|
/** An expression that will determine this fields value on the backend and be provided to the front end*/
|
|
42
42
|
serverExpression?: (entity: entityType) => valueType | Promise<valueType>;
|
|
43
43
|
/** The name of the column in the database that holds the data for this field. If no name is set, the key will be used instead.
|
|
@@ -69,8 +69,20 @@ export interface FieldOptions<entityType = any, valueType = any> {
|
|
|
69
69
|
defaultValue?: (entity: entityType) => valueType | Promise<valueType>;
|
|
70
70
|
/** The html input type for this field */
|
|
71
71
|
inputType?: string;
|
|
72
|
-
/**
|
|
73
|
-
* @
|
|
72
|
+
/**
|
|
73
|
+
* @deprecated The 'lazy' option is deprecated and will be removed in future versions.
|
|
74
|
+
* Use 'Relations.toOne' instead.
|
|
75
|
+
*
|
|
76
|
+
* Example usage:
|
|
77
|
+
* ```
|
|
78
|
+
* // Deprecated usage with 'lazy' option
|
|
79
|
+
* @Field(() => Customer, { lazy: true })
|
|
80
|
+
* customer?: Customer;
|
|
81
|
+
*
|
|
82
|
+
* // Preferred usage with 'Relations.toOne'
|
|
83
|
+
* @Relations.toOne(() => Customer)
|
|
84
|
+
* customer?: Customer;
|
|
85
|
+
* ```
|
|
74
86
|
*/
|
|
75
87
|
lazy?: boolean;
|
|
76
88
|
/** The value type for this field */
|
|
@@ -122,7 +134,7 @@ export interface FieldMetadata<valueType = any, entityType = any> {
|
|
|
122
134
|
*/
|
|
123
135
|
displayValue(item: Partial<OmitEB<entityType>>): string;
|
|
124
136
|
apiUpdateAllowed(item?: Partial<OmitEB<entityType>>): boolean;
|
|
125
|
-
|
|
137
|
+
includedInApi(item?: Partial<OmitEB<entityType>>): boolean;
|
|
126
138
|
/** Adapts the value for usage with html input
|
|
127
139
|
* @example
|
|
128
140
|
* @Fields.dateOnly()
|
package/esm/src/column.d.ts
CHANGED
|
@@ -1,32 +1,18 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { RepositoryImplementation } from './remult3/RepositoryImplementation';
|
|
1
|
+
import type { idType, Repository } from './remult3/remult3';
|
|
3
2
|
export declare function makeTitle(name: string): string;
|
|
4
3
|
export declare class LookupColumn<T> {
|
|
5
4
|
private repository;
|
|
6
|
-
private
|
|
5
|
+
private isReferenceRelation;
|
|
7
6
|
toJson(): any;
|
|
8
7
|
setId(val: any): void;
|
|
9
8
|
waitLoadOf(id: any): Promise<T>;
|
|
10
9
|
get(id: any): any;
|
|
11
|
-
storedItem
|
|
10
|
+
storedItem?: {
|
|
12
11
|
item: T;
|
|
13
12
|
};
|
|
14
13
|
set(item: T): void;
|
|
15
14
|
id: idType<T>;
|
|
16
|
-
constructor(repository:
|
|
15
|
+
constructor(repository: Repository<T>, isReferenceRelation: any);
|
|
17
16
|
get item(): T;
|
|
18
17
|
waitLoad(): Promise<T>;
|
|
19
18
|
}
|
|
20
|
-
export declare class OneToMany<T> {
|
|
21
|
-
private provider;
|
|
22
|
-
private settings?;
|
|
23
|
-
constructor(provider: Repository<T>, settings?: {
|
|
24
|
-
create?: (newItem: T) => void;
|
|
25
|
-
} & FindOptions<T>);
|
|
26
|
-
private _items;
|
|
27
|
-
private _currentPromise;
|
|
28
|
-
get lazyItems(): T[];
|
|
29
|
-
load(): Promise<T[]>;
|
|
30
|
-
private find;
|
|
31
|
-
create(item?: Partial<T>): T;
|
|
32
|
-
}
|
package/esm/src/column.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { assign } from '../assign';
|
|
2
|
-
import { __updateEntityBasedOnWhere } from './remult3/__updateEntityBasedOnWhere';
|
|
3
1
|
import { getEntityRef } from './remult3/getEntityRef';
|
|
2
|
+
import { getRepositoryInternals } from './remult3/repository-internals';
|
|
4
3
|
export function makeTitle(name) {
|
|
5
4
|
// insert a space before all caps
|
|
6
5
|
return (name
|
|
@@ -12,7 +11,7 @@ export function makeTitle(name) {
|
|
|
12
11
|
}
|
|
13
12
|
export class LookupColumn {
|
|
14
13
|
repository;
|
|
15
|
-
|
|
14
|
+
isReferenceRelation;
|
|
16
15
|
toJson() {
|
|
17
16
|
if (!this.storedItem)
|
|
18
17
|
return undefined;
|
|
@@ -28,12 +27,14 @@ export class LookupColumn {
|
|
|
28
27
|
waitLoadOf(id) {
|
|
29
28
|
if (id === undefined || id === null)
|
|
30
29
|
return null;
|
|
31
|
-
return this.repository.getCachedByIdAsync(id, false);
|
|
30
|
+
return getRepositoryInternals(this.repository).getCachedByIdAsync(id, false);
|
|
32
31
|
}
|
|
33
32
|
get(id) {
|
|
34
33
|
if (id === undefined || id === null)
|
|
35
34
|
return null;
|
|
36
|
-
|
|
35
|
+
if (this.isReferenceRelation && !this.storedItem)
|
|
36
|
+
return undefined;
|
|
37
|
+
return getRepositoryInternals(this.repository).getCachedById(id, this.isReferenceRelation);
|
|
37
38
|
}
|
|
38
39
|
storedItem;
|
|
39
40
|
set(item) {
|
|
@@ -43,8 +44,8 @@ export class LookupColumn {
|
|
|
43
44
|
this.id = item;
|
|
44
45
|
else {
|
|
45
46
|
let eo = getEntityRef(item, false);
|
|
46
|
-
if (eo) {
|
|
47
|
-
this.repository.addToCache(item);
|
|
47
|
+
if (eo && !this.isReferenceRelation) {
|
|
48
|
+
getRepositoryInternals(this.repository).addToCache(item);
|
|
48
49
|
this.id = eo.getId();
|
|
49
50
|
}
|
|
50
51
|
else {
|
|
@@ -61,9 +62,9 @@ export class LookupColumn {
|
|
|
61
62
|
}
|
|
62
63
|
}
|
|
63
64
|
id;
|
|
64
|
-
constructor(repository,
|
|
65
|
+
constructor(repository, isReferenceRelation) {
|
|
65
66
|
this.repository = repository;
|
|
66
|
-
this.
|
|
67
|
+
this.isReferenceRelation = isReferenceRelation;
|
|
67
68
|
}
|
|
68
69
|
get item() {
|
|
69
70
|
if (this.storedItem)
|
|
@@ -74,38 +75,3 @@ export class LookupColumn {
|
|
|
74
75
|
return this.waitLoadOf(this.id);
|
|
75
76
|
}
|
|
76
77
|
}
|
|
77
|
-
9000;
|
|
78
|
-
export class OneToMany {
|
|
79
|
-
provider;
|
|
80
|
-
settings;
|
|
81
|
-
constructor(provider, settings) {
|
|
82
|
-
this.provider = provider;
|
|
83
|
-
this.settings = settings;
|
|
84
|
-
}
|
|
85
|
-
_items;
|
|
86
|
-
_currentPromise;
|
|
87
|
-
get lazyItems() {
|
|
88
|
-
this.load();
|
|
89
|
-
return this._items;
|
|
90
|
-
}
|
|
91
|
-
async load() {
|
|
92
|
-
if (this._currentPromise != null)
|
|
93
|
-
return this._currentPromise;
|
|
94
|
-
if (this._items === undefined)
|
|
95
|
-
this._items = [];
|
|
96
|
-
return (this._currentPromise = this.find().then((x) => {
|
|
97
|
-
this._items.splice(0);
|
|
98
|
-
this._items.push(...x);
|
|
99
|
-
return this._items;
|
|
100
|
-
}));
|
|
101
|
-
}
|
|
102
|
-
async find() {
|
|
103
|
-
return this.provider.find(this.settings);
|
|
104
|
-
}
|
|
105
|
-
create(item) {
|
|
106
|
-
let r = this.provider.create();
|
|
107
|
-
__updateEntityBasedOnWhere(this.provider.metadata, this.settings.where, r);
|
|
108
|
-
assign(r, item);
|
|
109
|
-
return r;
|
|
110
|
-
}
|
|
111
|
-
}
|
package/esm/src/context.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ export declare class RemultAsyncLocalStorage {
|
|
|
15
15
|
}
|
|
16
16
|
type myAsyncLocalStorage<T> = {
|
|
17
17
|
run<R>(store: T, callback: (...args: any[]) => R, ...args: any[]): R;
|
|
18
|
-
getStore(): T;
|
|
18
|
+
getStore(): T | undefined;
|
|
19
19
|
};
|
|
20
20
|
export declare function isBackend(): boolean;
|
|
21
21
|
export declare class Remult {
|
package/esm/src/context.js
CHANGED
|
@@ -90,7 +90,7 @@ export class Remult {
|
|
|
90
90
|
if (typeof roles === 'boolean')
|
|
91
91
|
return roles;
|
|
92
92
|
if (typeof roles === 'string')
|
|
93
|
-
if (this.user?.roles?.
|
|
93
|
+
if (this.user?.roles?.includes(roles.toString()))
|
|
94
94
|
return true;
|
|
95
95
|
return false;
|
|
96
96
|
}
|
|
@@ -112,6 +112,7 @@ export class Remult {
|
|
|
112
112
|
}
|
|
113
113
|
else
|
|
114
114
|
return this.isAllowed(allowed);
|
|
115
|
+
return undefined;
|
|
115
116
|
}
|
|
116
117
|
/** The current data provider */
|
|
117
118
|
dataProvider = new RestDataProvider(() => this.apiClient);
|
|
@@ -285,3 +286,6 @@ class transactionLiveQueryPublisher {
|
|
|
285
286
|
}
|
|
286
287
|
}
|
|
287
288
|
}
|
|
289
|
+
//p1 - seems that after backend methods relations are loaded for some reason - see trempim - intake doRequest backend method
|
|
290
|
+
//p1 - reconsider the case in tremping where create user id was updated with some user and not the actual user
|
|
291
|
+
//[ ] - when value changes for field with error, clear error - so the user will feel comfortable
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { Sort } from './sort';
|
|
2
2
|
export function extractSort(sort) {
|
|
3
|
-
if (sort instanceof Sort)
|
|
4
|
-
return sort;
|
|
5
3
|
if (sort instanceof Array) {
|
|
6
4
|
let r = new Sort();
|
|
7
5
|
sort.forEach((i) => {
|
|
@@ -9,4 +7,5 @@ export function extractSort(sort) {
|
|
|
9
7
|
});
|
|
10
8
|
return r;
|
|
11
9
|
}
|
|
10
|
+
return sort;
|
|
12
11
|
}
|
|
@@ -4,8 +4,8 @@ import { Filter } from '../filter/filter-interfaces';
|
|
|
4
4
|
import type { EntityFilter, EntityMetadata } from '../remult3/remult3';
|
|
5
5
|
export declare class ArrayEntityDataProvider implements EntityDataProvider {
|
|
6
6
|
private entity;
|
|
7
|
-
private rows?;
|
|
8
7
|
static rawFilter(filter: CustomArrayFilter): EntityFilter<any>;
|
|
8
|
+
private rows;
|
|
9
9
|
constructor(entity: EntityMetadata, rows?: any[]);
|
|
10
10
|
__names: EntityDbNamesBase;
|
|
11
11
|
init(): Promise<EntityDbNamesBase>;
|
|
@@ -3,7 +3,6 @@ import { dbNamesOf, isDbReadonly, } from '../filter/filter-consumer-bridge-to-sq
|
|
|
3
3
|
import { Filter, customDatabaseFilterToken } from '../filter/filter-interfaces';
|
|
4
4
|
export class ArrayEntityDataProvider {
|
|
5
5
|
entity;
|
|
6
|
-
rows;
|
|
7
6
|
static rawFilter(filter) {
|
|
8
7
|
return {
|
|
9
8
|
[customDatabaseFilterToken]: {
|
|
@@ -11,13 +10,13 @@ export class ArrayEntityDataProvider {
|
|
|
11
10
|
},
|
|
12
11
|
};
|
|
13
12
|
}
|
|
13
|
+
rows;
|
|
14
14
|
constructor(entity, rows) {
|
|
15
15
|
this.entity = entity;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
16
|
+
if (rows === undefined)
|
|
17
|
+
this.rows = [];
|
|
18
|
+
else
|
|
19
|
+
this.rows = rows;
|
|
21
20
|
}
|
|
22
21
|
__names;
|
|
23
22
|
async init() {
|
|
@@ -88,6 +87,7 @@ export class ArrayEntityDataProvider {
|
|
|
88
87
|
return rows.map((i) => {
|
|
89
88
|
return this.translateFromJson(i, dbNames);
|
|
90
89
|
});
|
|
90
|
+
return [];
|
|
91
91
|
}
|
|
92
92
|
translateFromJson(row, dbNames) {
|
|
93
93
|
let result = {};
|
|
@@ -5,6 +5,7 @@ import { remult as defaultRemult } from '../remult-proxy';
|
|
|
5
5
|
import { getRepository } from '../remult3/RepositoryImplementation';
|
|
6
6
|
import { Sort } from '../sort';
|
|
7
7
|
import { ValueConverters } from '../valueConverters';
|
|
8
|
+
import { getRepositoryInternals } from '../remult3/repository-internals';
|
|
8
9
|
// @dynamic
|
|
9
10
|
export class SqlDatabase {
|
|
10
11
|
sql;
|
|
@@ -89,7 +90,7 @@ export class SqlDatabase {
|
|
|
89
90
|
const r = getRepository(repo);
|
|
90
91
|
var b = new FilterConsumerBridgeToSqlRequest(sqlCommand, await dbNamesOf(r.metadata));
|
|
91
92
|
b._addWhere = false;
|
|
92
|
-
await (await r.translateWhereToFilter(condition)).__applyToConsumer(b);
|
|
93
|
+
await (await getRepositoryInternals(r).translateWhereToFilter(condition)).__applyToConsumer(b);
|
|
93
94
|
return await b.resolveWhere();
|
|
94
95
|
}
|
|
95
96
|
/**
|