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