remult 0.18.1-exp.2 → 0.18.1-exp.4
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 +28 -5
- package/esm/index.d.ts +6 -5
- package/esm/index.js +6 -4
- package/esm/live-query/ably.d.ts +6 -6
- package/esm/live-query/ably.js +5 -5
- package/esm/postgres/postgres-data-provider.d.ts +3 -1
- package/esm/postgres/postgres-data-provider.js +11 -1
- package/esm/postgres/schema-builder.js +20 -20
- package/esm/remult-express.d.ts +4 -22
- package/esm/remult-express.js +31 -26
- package/esm/remult-fastify.js +1 -1
- package/esm/remult-fresh.js +2 -2
- package/esm/remult-knex/index.d.ts +6 -30
- package/esm/remult-knex/index.js +58 -37
- package/esm/remult-mongo.d.ts +9 -2
- package/esm/remult-mongo.js +24 -8
- package/esm/remult-zod.d.ts +8 -0
- package/esm/remult-zod.js +50 -0
- package/esm/server/expressBridge.d.ts +19 -47
- package/esm/server/expressBridge.js +37 -27
- package/esm/server/index.d.ts +3 -1
- package/esm/server/index.js +6 -1
- package/esm/src/column.d.ts +5 -2
- package/esm/src/column.js +28 -12
- package/esm/src/context.d.ts +18 -14
- package/esm/src/context.js +20 -38
- package/esm/src/data-api.js +15 -2
- package/esm/src/data-interfaces.d.ts +1 -1
- package/esm/src/data-providers/array-entity-data-provider.d.ts +1 -1
- package/esm/src/data-providers/array-entity-data-provider.js +1 -1
- package/esm/src/data-providers/rest-data-provider.d.ts +4 -15
- package/esm/src/data-providers/rest-data-provider.js +36 -22
- package/esm/src/data-providers/sql-database.d.ts +6 -3
- package/esm/src/data-providers/sql-database.js +55 -16
- package/esm/src/data-providers/web-sql-data-provider.d.ts +3 -0
- package/esm/src/data-providers/web-sql-data-provider.js +16 -8
- package/esm/src/entity.d.ts +2 -2
- package/esm/src/filter/filter-consumer-bridge-to-sql-request.d.ts +16 -16
- package/esm/src/filter/filter-consumer-bridge-to-sql-request.js +29 -21
- package/esm/src/filter/filter-interfaces.d.ts +5 -5
- package/esm/src/filter/filter-interfaces.js +9 -9
- package/esm/src/live-query/LiveQueryClient.d.ts +1 -19
- package/esm/src/live-query/LiveQueryClient.js +44 -40
- package/esm/src/live-query/SseSubscriptionClient.d.ts +4 -0
- package/esm/src/live-query/{EventSourceLiveQueryProvider.js → SseSubscriptionClient.js} +4 -4
- package/esm/src/live-query/SubscriptionClient.d.ts +35 -0
- package/esm/src/live-query/{LiveQuerySubscriber.js → SubscriptionClient.js} +30 -21
- package/esm/src/live-query/SubscriptionServer.d.ts +37 -0
- package/esm/src/live-query/{LiveQueryPublisher.js → SubscriptionServer.js} +57 -73
- package/esm/src/remult-proxy.js +20 -0
- package/esm/src/remult3/DecoratorReplacer.d.ts +7 -1
- package/esm/src/remult3/DecoratorReplacer.js +25 -2
- package/esm/src/remult3/RepositoryImplementation.d.ts +47 -26
- package/esm/src/remult3/RepositoryImplementation.js +252 -78
- package/esm/src/remult3/remult3.d.ts +20 -4
- package/esm/src/remult3/remult3.js +1 -0
- package/esm/src/server-action.d.ts +24 -2
- package/esm/src/server-action.js +83 -46
- package/esm/src/shared-tests/db-tests-setup.d.ts +1 -1
- package/esm/src/shared-tests/db-tests-setup.js +4 -3
- package/esm/src/shared-tests/db-tests.db-tests.js +6 -6
- package/esm/src/sql-command.d.ts +4 -2
- package/esm/src/tests/entityForCustomFilter.d.ts +6 -6
- package/esm/src/tests/entityForCustomFilter.js +20 -21
- package/esm/src/tests/frontend-database-tests-setup.spec.js +1 -2
- package/esm/src/tests/testHelper.spec.d.ts +1 -1
- package/esm/src/tests/testHelper.spec.js +2 -3
- package/esm/src/valueConverters.js +3 -1
- package/index.d.ts +6 -5
- package/index.js +10 -3
- package/live-query/ably.d.ts +6 -6
- package/live-query/ably.js +12 -12
- package/package.json +17 -9
- package/postgres/postgres-data-provider.d.ts +3 -1
- package/postgres/postgres-data-provider.js +11 -1
- package/postgres/schema-builder.js +19 -19
- package/remult-express.d.ts +4 -22
- package/remult-express.js +40 -35
- package/remult-fastify.js +2 -2
- package/remult-fresh.js +1 -1
- package/remult-knex/index.d.ts +6 -30
- package/remult-knex/index.js +85 -47
- package/remult-mongo.d.ts +9 -2
- package/remult-mongo.js +39 -7
- package/remult-zod.d.ts +8 -0
- package/remult-zod.js +71 -0
- package/server/expressBridge.d.ts +19 -47
- package/server/expressBridge.js +39 -38
- package/server/index.d.ts +3 -1
- package/server/index.js +7 -2
- package/src/column.d.ts +5 -2
- package/src/column.js +32 -12
- package/src/context.d.ts +18 -14
- package/src/context.js +20 -45
- package/src/data-api.js +16 -3
- package/src/data-interfaces.d.ts +1 -1
- package/src/data-providers/array-entity-data-provider.d.ts +1 -1
- package/src/data-providers/array-entity-data-provider.js +1 -1
- package/src/data-providers/rest-data-provider.d.ts +4 -15
- package/src/data-providers/rest-data-provider.js +45 -23
- package/src/data-providers/sql-database.d.ts +6 -3
- package/src/data-providers/sql-database.js +73 -15
- package/src/data-providers/web-sql-data-provider.d.ts +3 -0
- package/src/data-providers/web-sql-data-provider.js +15 -7
- package/src/entity.d.ts +2 -2
- package/src/filter/filter-consumer-bridge-to-sql-request.d.ts +16 -16
- package/src/filter/filter-consumer-bridge-to-sql-request.js +59 -50
- package/src/filter/filter-interfaces.d.ts +5 -5
- package/src/filter/filter-interfaces.js +9 -9
- package/src/live-query/LiveQueryClient.d.ts +1 -19
- package/src/live-query/LiveQueryClient.js +80 -54
- package/src/live-query/SseSubscriptionClient.d.ts +4 -0
- package/src/live-query/{EventSourceLiveQueryProvider.js → SseSubscriptionClient.js} +11 -11
- package/src/live-query/SubscriptionClient.d.ts +35 -0
- package/src/live-query/{LiveQuerySubscriber.js → SubscriptionClient.js} +40 -46
- package/src/live-query/SubscriptionServer.d.ts +37 -0
- package/src/live-query/SubscriptionServer.js +234 -0
- package/src/remult-proxy.js +28 -0
- package/src/remult3/DecoratorReplacer.d.ts +7 -1
- package/src/remult3/DecoratorReplacer.js +38 -4
- package/src/remult3/RepositoryImplementation.d.ts +47 -26
- package/src/remult3/RepositoryImplementation.js +362 -108
- package/src/remult3/remult3.d.ts +20 -4
- package/src/remult3/remult3.js +1 -0
- package/src/server-action.d.ts +24 -2
- package/src/server-action.js +179 -105
- package/src/shared-tests/db-tests-setup.d.ts +1 -1
- package/src/shared-tests/db-tests-setup.js +5 -4
- package/src/shared-tests/db-tests.db-tests.js +5 -5
- package/src/sql-command.d.ts +4 -2
- package/src/tests/entityForCustomFilter.d.ts +6 -6
- package/src/tests/entityForCustomFilter.js +30 -31
- package/src/tests/frontend-database-tests-setup.spec.js +4 -5
- package/src/tests/testHelper.spec.d.ts +1 -1
- package/src/tests/testHelper.spec.js +5 -6
- package/src/valueConverters.js +3 -1
- package/esm/live-query/index.d.ts +0 -3
- package/esm/live-query/index.js +0 -3
- package/esm/src/backend-tests/backend-database-test-setup.backend-spec.d.ts +0 -5
- package/esm/src/backend-tests/backend-database-test-setup.backend-spec.js +0 -113
- package/esm/src/backend-tests/my-test.backend-spec.d.ts +0 -1
- package/esm/src/backend-tests/my-test.backend-spec.js +0 -59
- package/esm/src/backend-tests/test-http-server.backend-spec.d.ts +0 -6
- package/esm/src/backend-tests/test-http-server.backend-spec.js +0 -171
- package/esm/src/live-query/EventSourceLiveQueryProvider.d.ts +0 -4
- package/esm/src/live-query/LiveQueryPublisher.d.ts +0 -49
- package/esm/src/live-query/LiveQuerySubscriber.d.ts +0 -67
- package/live-query/index.d.ts +0 -3
- package/live-query/index.js +0 -10
- package/src/live-query/EventSourceLiveQueryProvider.d.ts +0 -4
- package/src/live-query/LiveQueryPublisher.d.ts +0 -49
- package/src/live-query/LiveQueryPublisher.js +0 -248
- package/src/live-query/LiveQuerySubscriber.d.ts +0 -67
package/README.md
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
<img src="https://github.com/remult/remult/raw/master/docs/.vuepress/public/logo.png" width="140" height="140">
|
|
4
4
|
</a>
|
|
5
5
|
<h1>Remult</h1>
|
|
6
|
+
<p>A CRUD framework for full-stack TypeScript</p>
|
|
6
7
|
<a href="https://circleci.com/gh/remult/remult/tree/master" rel="nofollow">
|
|
7
8
|
<img alt="CircleCI" src="https://circleci.com/gh/remult/remult/tree/master.svg?style=shield">
|
|
8
9
|
</a>
|
|
@@ -24,14 +25,29 @@
|
|
|
24
25
|
<a href="https://twitter.com/intent/tweet?text=Remult%20-%20open-source%20CRUD%20framework%20for%20full-stack%20TypeScript%0A%0A%40remultjs%0A&url=https%3A%2F%2Fgithub.com%2Fremult%2Fremult">
|
|
25
26
|
<img alt="Twitter URL" src="https://img.shields.io/twitter/url?style=social&url=https%3A%2F%2Ftwitter.com%2Fintent%2Ftweet%3Ftext%3DRemult%2520-%2520open-source%2520CRUD%2520framework%2520for%2520full-stack%2520TypeScript%250A%250A%2540remultjs%250A%26url%3Dhttps%253A%252F%252Fgithub.com%252Fremult%252Fremult">
|
|
26
27
|
</a>
|
|
27
|
-
<a href="https://twitter.com/remultjs" rel="nofollow">
|
|
28
|
-
<img alt="Twitter Follow" src="https://img.shields.io/twitter/url.svg?label=Follow%20%40remultjs&style=social&url=https%3A%2F%2Ftwitter.com%2FRemultJs">
|
|
29
|
-
</a>
|
|
30
28
|
</div>
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
<br/>
|
|
32
|
+
|
|
33
|
+
<div align="center">
|
|
34
|
+
<a href="#getting-started">Getting Started</a> |
|
|
35
|
+
<a href="#documentation">Documentation</a> |
|
|
36
|
+
<a href="#example-apps">Example Apps</a>
|
|
37
|
+
</div>
|
|
38
|
+
|
|
31
39
|
<hr/>
|
|
40
|
+
<br/>
|
|
32
41
|
|
|
33
|
-
|
|
34
|
-
|
|
42
|
+
<a href="https://www.youtube.com/watch?v=rEoScmSVNUE" target="_blank">
|
|
43
|
+
<p align="center">
|
|
44
|
+
<img src="https://github.com/remult/remult/raw/master/static/images/video-thumbnail.jpg" alt="Video thumbnail" />
|
|
45
|
+
</p>
|
|
46
|
+
</a>
|
|
47
|
+
|
|
48
|
+
<a href="https://www.youtube.com/watch?v=rEoScmSVNUE" target="_blank">
|
|
49
|
+
<p align="center">Watch code demo on YouTube here (14 mins)</p>
|
|
50
|
+
</a>
|
|
35
51
|
|
|
36
52
|
## What is Remult?
|
|
37
53
|
|
|
@@ -39,6 +55,13 @@
|
|
|
39
55
|
as a single source of truth for your API, frontend type-safe API client and
|
|
40
56
|
backend ORM**.
|
|
41
57
|
|
|
58
|
+
* :zap: Zero-boilerplate CRUD API routes with paging, sorting, and filtering for Express / Fastify / Next.js / NestJS / Koa / others...
|
|
59
|
+
* :ok_hand: Fullstack type-safety for API queries, mutations and RPC, without code generation
|
|
60
|
+
* :sparkles: Input validation, defined once, runs both on the backend and on the frontend for best UX
|
|
61
|
+
* :lock: Fine-grained code-based API authorization
|
|
62
|
+
* :relieved: Incrementally adoptable
|
|
63
|
+
* :rocket: Production ready
|
|
64
|
+
|
|
42
65
|
### Status
|
|
43
66
|
|
|
44
67
|
Remult is **production-ready** and, in fact, used in production apps since 2018.
|
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 } from './src/remult3';
|
|
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, InferMemberType, InferredType, MemberType as TypedDecorator, LiveQuery, LiveQueryChangeInfo } from './src/remult3';
|
|
2
|
+
export { describeClass, createEntity, createClass } from './src/remult3/DecoratorReplacer';
|
|
2
3
|
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';
|
|
@@ -11,17 +11,18 @@ export { InMemoryDataProvider } from './src/data-providers/in-memory-database';
|
|
|
11
11
|
export { ArrayEntityDataProvider } from './src/data-providers/array-entity-data-provider';
|
|
12
12
|
export { WebSqlDataProvider } from './src/data-providers/web-sql-data-provider';
|
|
13
13
|
export { SqlDatabase, } from './src/data-providers/sql-database';
|
|
14
|
-
export { CustomSqlFilterObject, CustomSqlFilterBuilder } from './src/filter/filter-consumer-bridge-to-sql-request';
|
|
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 } from './src/server-action';
|
|
16
|
+
export { Controller, BackendMethodOptions, BackendMethod, ProgressListener, createBackendMethod, CreateBackendMethodOptions, BackendMethodType, InferredMethodType, } 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';
|
|
20
20
|
export { SortSegment, Sort } from './src/sort';
|
|
21
21
|
export { OneToMany, CompoundIdField } from './src/column';
|
|
22
22
|
export { Filter } from './src/filter/filter-interfaces';
|
|
23
|
-
export { FilterConsumerBridgeToSqlRequest } from './src/filter/filter-consumer-bridge-to-sql-request';
|
|
24
23
|
export { UrlBuilder } from './urlBuilder';
|
|
25
24
|
export { Validators } from './src/validators';
|
|
26
25
|
export { ValueConverters } from './src/valueConverters';
|
|
27
26
|
export { remult } from './src/remult-proxy';
|
|
27
|
+
export { SubscriptionServer, LiveQueryStorage, StoredQuery, InMemoryLiveQueryStorage } from "./src/live-query/SubscriptionServer";
|
|
28
|
+
export { SubscriptionClientConnection, SubscriptionClient, SubscriptionChannel, LiveQueryChange, Unsubscribe } from './src/live-query/SubscriptionClient';
|
package/esm/index.js
CHANGED
|
@@ -2,23 +2,25 @@
|
|
|
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 } from './src/remult3/DecoratorReplacer';
|
|
5
|
+
export { describeClass, createEntity, createClass } 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
|
|
9
9
|
export { WebSqlDataProvider } from './src/data-providers/web-sql-data-provider'; //V
|
|
10
10
|
export { SqlDatabase, } from './src/data-providers/sql-database'; //V
|
|
11
|
-
export { CustomSqlFilterBuilder } from './src/filter/filter-consumer-bridge-to-sql-request';
|
|
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 } from './src/server-action';
|
|
14
|
+
export { Controller, BackendMethod, ProgressListener, createBackendMethod, } 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';
|
|
18
18
|
export { OneToMany, CompoundIdField } from './src/column';
|
|
19
19
|
export { Filter } from './src/filter/filter-interfaces';
|
|
20
|
-
export { FilterConsumerBridgeToSqlRequest } from './src/filter/filter-consumer-bridge-to-sql-request';
|
|
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
|
+
//export { getId } from './src/remult3/getId';
|
|
25
|
+
export { InMemoryLiveQueryStorage } from "./src/live-query/SubscriptionServer";
|
|
26
|
+
export { SubscriptionChannel } from './src/live-query/SubscriptionClient';
|
package/esm/live-query/ably.d.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import type * as Ably from 'ably';
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
4
|
-
export declare class
|
|
2
|
+
import type { SubscriptionServer } from '../src/live-query/SubscriptionServer';
|
|
3
|
+
import type { SubscriptionClient, SubscriptionClientConnection } from '../src/live-query/SubscriptionClient';
|
|
4
|
+
export declare class AblySubscriptionClient implements SubscriptionClient {
|
|
5
5
|
private ably;
|
|
6
6
|
constructor(ably: Ably.Types.RealtimePromise);
|
|
7
|
-
|
|
7
|
+
openConnection(onReconnect: VoidFunction): Promise<SubscriptionClientConnection>;
|
|
8
8
|
}
|
|
9
|
-
export declare class
|
|
9
|
+
export declare class AblySubscriptionServer implements SubscriptionServer {
|
|
10
10
|
private ably;
|
|
11
11
|
constructor(ably: Ably.Types.RealtimePromise);
|
|
12
|
-
|
|
12
|
+
publishMessage<T>(channel: string, message: T): void;
|
|
13
13
|
}
|
package/esm/live-query/ably.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
export class
|
|
1
|
+
export class AblySubscriptionClient {
|
|
2
2
|
constructor(ably) {
|
|
3
3
|
this.ably = ably;
|
|
4
4
|
}
|
|
5
|
-
async
|
|
5
|
+
async openConnection(onReconnect) {
|
|
6
6
|
return {
|
|
7
|
-
|
|
7
|
+
close: () => {
|
|
8
8
|
this.ably.connection.close();
|
|
9
9
|
},
|
|
10
10
|
subscribe: (channel, handler) => {
|
|
@@ -15,11 +15,11 @@ export class AblyLiveQueryProvider {
|
|
|
15
15
|
};
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
|
-
export class
|
|
18
|
+
export class AblySubscriptionServer {
|
|
19
19
|
constructor(ably) {
|
|
20
20
|
this.ably = ably;
|
|
21
21
|
}
|
|
22
|
-
|
|
22
|
+
publishMessage(channel, message) {
|
|
23
23
|
this.ably.channels.get(channel).publish({ data: message });
|
|
24
24
|
}
|
|
25
25
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { PoolConfig, QueryResult } from 'pg';
|
|
1
|
+
import { ClientBase, PoolConfig, QueryResult } from 'pg';
|
|
2
|
+
import { Remult } from '../src/context';
|
|
2
3
|
import { EntityMetadata } from '../src/remult3';
|
|
3
4
|
import { SqlCommand, SqlImplementation } from '../src/sql-command';
|
|
4
5
|
import { SqlDatabase } from '../src/data-providers/sql-database';
|
|
@@ -10,6 +11,7 @@ export interface PostgresClient extends PostgresCommandSource {
|
|
|
10
11
|
}
|
|
11
12
|
export declare class PostgresDataProvider implements SqlImplementation {
|
|
12
13
|
private pool;
|
|
14
|
+
static getDb(remult?: Remult): ClientBase;
|
|
13
15
|
entityIsUsedForTheFirstTime(entity: EntityMetadata): Promise<void>;
|
|
14
16
|
getLimitSqlSyntax(limit: number, offset: number): string;
|
|
15
17
|
createCommand(): SqlCommand;
|
|
@@ -6,6 +6,14 @@ export class PostgresDataProvider {
|
|
|
6
6
|
constructor(pool) {
|
|
7
7
|
this.pool = pool;
|
|
8
8
|
}
|
|
9
|
+
static getDb(remult) {
|
|
10
|
+
const sql = SqlDatabase.getDb(remult);
|
|
11
|
+
const me = sql._getSourceSql();
|
|
12
|
+
if (!me.pool) {
|
|
13
|
+
throw "the data provider is not a PostgresDataProvider";
|
|
14
|
+
}
|
|
15
|
+
return me.pool;
|
|
16
|
+
}
|
|
9
17
|
async entityIsUsedForTheFirstTime(entity) {
|
|
10
18
|
}
|
|
11
19
|
getLimitSqlSyntax(limit, offset) {
|
|
@@ -22,7 +30,9 @@ export class PostgresDataProvider {
|
|
|
22
30
|
createCommand: () => new PostgresBridgeToSQLCommand(client),
|
|
23
31
|
entityIsUsedForTheFirstTime: this.entityIsUsedForTheFirstTime,
|
|
24
32
|
transaction: () => { throw "nested transactions not allowed"; },
|
|
25
|
-
getLimitSqlSyntax: this.getLimitSqlSyntax
|
|
33
|
+
getLimitSqlSyntax: this.getLimitSqlSyntax,
|
|
34
|
+
//@ts-ignore
|
|
35
|
+
pool: client
|
|
26
36
|
});
|
|
27
37
|
await client.query('COMMIT');
|
|
28
38
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { allEntities } from '../src/context';
|
|
2
|
-
import {
|
|
2
|
+
import { dbNamesOf, isDbReadonly } from '../src/filter/filter-consumer-bridge-to-sql-request';
|
|
3
3
|
import { isAutoIncrement } from '../src/remult3';
|
|
4
4
|
import { ValueConverters } from '../src/valueConverters';
|
|
5
5
|
export function postgresColumnSyntax(x, dbName) {
|
|
@@ -46,57 +46,57 @@ export class PostgresSchemaBuilder {
|
|
|
46
46
|
console.log("start verify structure"); //keep me
|
|
47
47
|
for (const entityClass of allEntities) {
|
|
48
48
|
let entity = remult.repo(entityClass).metadata;
|
|
49
|
-
let e = await
|
|
49
|
+
let e = await dbNamesOf(entity);
|
|
50
50
|
try {
|
|
51
51
|
if (!entity.options.sqlExpression) {
|
|
52
|
-
if ((await e
|
|
52
|
+
if ((await e.$entityName).toLowerCase().indexOf('from ') < 0) {
|
|
53
53
|
await this.createIfNotExist(entity);
|
|
54
54
|
await this.verifyAllColumns(entity);
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
catch (err) {
|
|
59
|
-
|
|
59
|
+
console.log("failed verify structure of " + e.$entityName + " ", err);
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
async createIfNotExist(entity) {
|
|
64
64
|
var c = this.pool.createCommand();
|
|
65
|
-
let e = await
|
|
66
|
-
await c.execute("select 1 from information_Schema.tables where table_name=" + c.addParameterAndReturnSqlToken((e
|
|
65
|
+
let e = await dbNamesOf(entity);
|
|
66
|
+
await c.execute("select 1 from information_Schema.tables where table_name=" + c.addParameterAndReturnSqlToken((e.$entityName).toLowerCase()) + this.additionalWhere).then(async (r) => {
|
|
67
67
|
if (r.rows.length == 0) {
|
|
68
68
|
let result = '';
|
|
69
69
|
for (const x of entity.fields) {
|
|
70
|
-
if (!
|
|
70
|
+
if (!isDbReadonly(x, e) || isAutoIncrement(x)) {
|
|
71
71
|
if (result.length != 0)
|
|
72
72
|
result += ',';
|
|
73
73
|
result += '\r\n ';
|
|
74
74
|
if (isAutoIncrement(x))
|
|
75
|
-
result += e
|
|
75
|
+
result += e.$dbNameOf(x) + ' serial';
|
|
76
76
|
else {
|
|
77
|
-
result += postgresColumnSyntax(x, e
|
|
77
|
+
result += postgresColumnSyntax(x, e.$dbNameOf(x));
|
|
78
78
|
if (x == entity.idMetadata.field)
|
|
79
79
|
result += ' primary key';
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
|
-
let sql = 'create table ' + e
|
|
83
|
+
let sql = 'create table ' + e.$entityName + ' (' + result + '\r\n)';
|
|
84
84
|
//console.log(sql);
|
|
85
85
|
await this.pool.execute(sql);
|
|
86
86
|
}
|
|
87
87
|
});
|
|
88
88
|
}
|
|
89
89
|
async addColumnIfNotExist(entity, c) {
|
|
90
|
-
let e = await
|
|
91
|
-
if (
|
|
90
|
+
let e = await dbNamesOf(entity);
|
|
91
|
+
if (isDbReadonly(c(entity), e))
|
|
92
92
|
return;
|
|
93
93
|
try {
|
|
94
94
|
let cmd = this.pool.createCommand();
|
|
95
|
-
const colName = e
|
|
95
|
+
const colName = e.$dbNameOf(c(entity));
|
|
96
96
|
if ((await cmd.execute(`select 1
|
|
97
97
|
FROM information_schema.columns
|
|
98
|
-
WHERE table_name=${cmd.addParameterAndReturnSqlToken((e
|
|
99
|
-
let sql = `alter table ${e
|
|
98
|
+
WHERE table_name=${cmd.addParameterAndReturnSqlToken((e.$entityName).toLocaleLowerCase())} and column_name=${cmd.addParameterAndReturnSqlToken((colName).toLocaleLowerCase())}` + this.additionalWhere)).rows.length == 0) {
|
|
99
|
+
let sql = `alter table ${e.$entityName} add column ${postgresColumnSyntax(c(entity), colName)}`;
|
|
100
100
|
//console.log(sql);
|
|
101
101
|
await this.pool.execute(sql);
|
|
102
102
|
}
|
|
@@ -108,14 +108,14 @@ export class PostgresSchemaBuilder {
|
|
|
108
108
|
async verifyAllColumns(entity) {
|
|
109
109
|
try {
|
|
110
110
|
let cmd = this.pool.createCommand();
|
|
111
|
-
let e = await
|
|
111
|
+
let e = await dbNamesOf(entity);
|
|
112
112
|
let cols = (await cmd.execute(`select column_name
|
|
113
113
|
FROM information_schema.columns
|
|
114
|
-
WHERE table_name=${cmd.addParameterAndReturnSqlToken((e
|
|
114
|
+
WHERE table_name=${cmd.addParameterAndReturnSqlToken((e.$entityName).toLocaleLowerCase())} ` + this.additionalWhere)).rows.map(x => x.column_name);
|
|
115
115
|
for (const col of entity.fields) {
|
|
116
|
-
if (!
|
|
117
|
-
if (!cols.includes(e
|
|
118
|
-
let sql = `alter table ${e
|
|
116
|
+
if (!isDbReadonly(col, e))
|
|
117
|
+
if (!cols.includes(e.$dbNameOf(col).toLocaleLowerCase())) {
|
|
118
|
+
let sql = `alter table ${e.$entityName} add column ${postgresColumnSyntax(col, e.$dbNameOf(col))}`;
|
|
119
119
|
//console.log(sql);
|
|
120
120
|
await this.pool.execute(sql);
|
|
121
121
|
}
|
package/esm/remult-express.d.ts
CHANGED
|
@@ -1,32 +1,14 @@
|
|
|
1
1
|
import * as express from 'express';
|
|
2
2
|
import { RemultServer, RemultServerOptions } from './server/expressBridge';
|
|
3
3
|
import { Remult } from './src/context';
|
|
4
|
-
import {
|
|
5
|
-
import { ServerEventDispatcher } from './src/live-query/LiveQueryPublisher';
|
|
4
|
+
import { SubscriptionServer } from './src/live-query/SubscriptionServer';
|
|
6
5
|
export declare function remultExpress(options?: RemultServerOptions<express.Request> & {
|
|
7
6
|
bodyParser?: boolean;
|
|
8
7
|
bodySizeLimit?: string;
|
|
9
|
-
serverEventDispatcher?: (router: express.Router, server: RemultServer) => ServerEventDispatcher;
|
|
10
8
|
}): express.RequestHandler & RemultServer;
|
|
11
|
-
export declare class
|
|
9
|
+
export declare class SseSubscriptionServer implements SubscriptionServer {
|
|
12
10
|
private canUserConnectToChannel?;
|
|
13
|
-
subscribeToChannel({ channel, clientId }: ServerEventChannelSubscribeDTO, res: import('express').Response, remult: Remult, remove?: boolean): void;
|
|
14
|
-
connections: clientConnection[];
|
|
15
11
|
constructor(canUserConnectToChannel?: (channel: string, remult: Remult) => boolean);
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
openHttpServerStream(req: import('express').Request, res: import('express').Response): clientConnection;
|
|
19
|
-
debug(): void;
|
|
20
|
-
debugFileSaver: (x: any) => void;
|
|
12
|
+
publishMessage<T>(channel: string, message: any): void;
|
|
13
|
+
registerRoutes(router: express.Router, apiPath: string, server: RemultServer): void;
|
|
21
14
|
}
|
|
22
|
-
declare class clientConnection {
|
|
23
|
-
response: import('express').Response;
|
|
24
|
-
channels: Record<string, boolean>;
|
|
25
|
-
close(): void;
|
|
26
|
-
closed: boolean;
|
|
27
|
-
write(eventData: string, eventType?: string): void;
|
|
28
|
-
connectionId: any;
|
|
29
|
-
constructor(response: import('express').Response);
|
|
30
|
-
sendLiveMessage(): void;
|
|
31
|
-
}
|
|
32
|
-
export {};
|
package/esm/remult-express.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import * as express from 'express';
|
|
2
|
-
import { createRemultServer } from './server/
|
|
3
|
-
import { liveQueryKeepAliveRoute, streamUrl } from './src/live-query/
|
|
4
|
-
import { LiveQueryPublisher, LiveQueryStorageInMemoryImplementation } from './src/live-query/LiveQueryPublisher';
|
|
2
|
+
import { createRemultServer } from './server/index';
|
|
3
|
+
import { liveQueryKeepAliveRoute, streamUrl } from './src/live-query/SubscriptionClient';
|
|
5
4
|
import { v4 as uuid } from 'uuid';
|
|
6
5
|
import { remult } from './src/remult-proxy';
|
|
7
6
|
import { getEntityKey } from './src/remult3';
|
|
@@ -17,17 +16,19 @@ export function remultExpress(options) {
|
|
|
17
16
|
app.use(express.json({ limit: options.bodySizeLimit }));
|
|
18
17
|
app.use(express.urlencoded({ extended: true, limit: options.bodySizeLimit }));
|
|
19
18
|
}
|
|
19
|
+
if (!options.subscriptionServer) {
|
|
20
|
+
options.subscriptionServer = new SseSubscriptionServer();
|
|
21
|
+
}
|
|
20
22
|
const server = createRemultServer(options);
|
|
21
23
|
server.registerRouter(app);
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
};
|
|
24
|
+
const canRegisterRoute = options.subscriptionServer;
|
|
25
|
+
if (canRegisterRoute.registerRoutes) {
|
|
26
|
+
canRegisterRoute.registerRoutes(app, options.rootPath, server);
|
|
26
27
|
}
|
|
27
28
|
app.post(options.rootPath + liveQueryKeepAliveRoute, (r, res, n) => server.withRemult(r, res, n), async (req, res) => {
|
|
28
|
-
res.send(await remult.
|
|
29
|
+
res.send(await remult.liveQueryStorage.keepAliveAndReturnUnknownQueryIds(req.body));
|
|
29
30
|
});
|
|
30
|
-
server.
|
|
31
|
+
server.runWithRequest = async (req, entityKey, what) => {
|
|
31
32
|
for (const e of options.entities) {
|
|
32
33
|
let key = getEntityKey(e);
|
|
33
34
|
if (key === entityKey) {
|
|
@@ -41,7 +42,7 @@ export function remultExpress(options) {
|
|
|
41
42
|
}
|
|
42
43
|
}
|
|
43
44
|
throw new Error("Couldn't find entity " + entityKey);
|
|
44
|
-
}
|
|
45
|
+
};
|
|
45
46
|
return Object.assign(app, {
|
|
46
47
|
getRemult: (req) => server.getRemult(req),
|
|
47
48
|
openApiDoc: (options) => server.openApiDoc(options),
|
|
@@ -49,16 +50,20 @@ export function remultExpress(options) {
|
|
|
49
50
|
withRemult: (...args) => server.withRemult(...args)
|
|
50
51
|
});
|
|
51
52
|
}
|
|
52
|
-
export class
|
|
53
|
+
export class SseSubscriptionServer {
|
|
53
54
|
constructor(canUserConnectToChannel) {
|
|
54
55
|
this.canUserConnectToChannel = canUserConnectToChannel;
|
|
56
|
+
//@internal
|
|
55
57
|
this.connections = [];
|
|
58
|
+
//@internal
|
|
56
59
|
this.debugMessageFileSaver = (id, channel, message) => { };
|
|
60
|
+
//@internal
|
|
57
61
|
this.debugFileSaver = () => { };
|
|
58
62
|
if (!this.canUserConnectToChannel) {
|
|
59
63
|
this.canUserConnectToChannel = () => true;
|
|
60
64
|
}
|
|
61
65
|
}
|
|
66
|
+
//@internal
|
|
62
67
|
subscribeToChannel({ channel, clientId }, res, remult, remove = false) {
|
|
63
68
|
for (const c of this.connections) {
|
|
64
69
|
if (c.connectionId === clientId) {
|
|
@@ -80,7 +85,7 @@ export class ServerEventsController {
|
|
|
80
85
|
}
|
|
81
86
|
res.sendStatus(404);
|
|
82
87
|
}
|
|
83
|
-
|
|
88
|
+
publishMessage(channel, message) {
|
|
84
89
|
const data = JSON.stringify({ channel, data: message });
|
|
85
90
|
for (const sc of this.connections) {
|
|
86
91
|
if (sc.channels[channel]) {
|
|
@@ -89,6 +94,7 @@ export class ServerEventsController {
|
|
|
89
94
|
}
|
|
90
95
|
}
|
|
91
96
|
}
|
|
97
|
+
//@internal
|
|
92
98
|
openHttpServerStream(req, res) {
|
|
93
99
|
res.writeHead(200, {
|
|
94
100
|
'Content-Type': 'text/event-stream',
|
|
@@ -106,12 +112,25 @@ export class ServerEventsController {
|
|
|
106
112
|
});
|
|
107
113
|
return cc;
|
|
108
114
|
}
|
|
115
|
+
//@internal
|
|
109
116
|
debug() {
|
|
110
117
|
this.debugFileSaver(this.connections.map(x => ({
|
|
111
118
|
id: x.connectionId,
|
|
112
119
|
channels: x.channels
|
|
113
120
|
})));
|
|
114
121
|
}
|
|
122
|
+
registerRoutes(router, apiPath, server) {
|
|
123
|
+
const streamPath = apiPath + '/' + streamUrl;
|
|
124
|
+
router.get(streamPath, (r, res, next) => server.withRemult(r, res, next), (req, res) => {
|
|
125
|
+
remult.subscriptionServer.openHttpServerStream(req, res);
|
|
126
|
+
});
|
|
127
|
+
router.post(streamPath + '/subscribe', (r, res, next) => server.withRemult(r, res, next), (req, res) => {
|
|
128
|
+
remult.subscriptionServer.subscribeToChannel(req.body, res, remult);
|
|
129
|
+
});
|
|
130
|
+
router.post(streamPath + '/unsubscribe', (r, res, next) => server.withRemult(r, res, next), (req, res) => {
|
|
131
|
+
remult.subscriptionServer.subscribeToChannel(req.body, res, remult, true);
|
|
132
|
+
});
|
|
133
|
+
}
|
|
115
134
|
}
|
|
116
135
|
class clientConnection {
|
|
117
136
|
constructor(response) {
|
|
@@ -143,17 +162,3 @@ class clientConnection {
|
|
|
143
162
|
}, 45000);
|
|
144
163
|
}
|
|
145
164
|
}
|
|
146
|
-
function buildHttpServerEventDispatcher(router, apiPath, server) {
|
|
147
|
-
const streamPath = apiPath + '/' + streamUrl;
|
|
148
|
-
let httpServerEvents = new ServerEventsController();
|
|
149
|
-
router.get(streamPath, (r, res, next) => server.withRemult(r, res, next), (req, res) => {
|
|
150
|
-
remult.liveQueryPublisher.dispatcher.openHttpServerStream(req, res);
|
|
151
|
-
});
|
|
152
|
-
router.post(streamPath + '/subscribe', (r, res, next) => server.withRemult(r, res, next), (req, res) => {
|
|
153
|
-
remult.liveQueryPublisher.dispatcher.subscribeToChannel(req.body, res, remult);
|
|
154
|
-
});
|
|
155
|
-
router.post(streamPath + '/unsubscribe', (r, res, next) => server.withRemult(r, res, next), (req, res) => {
|
|
156
|
-
remult.liveQueryPublisher.dispatcher.subscribeToChannel(req.body, res, remult, true);
|
|
157
|
-
});
|
|
158
|
-
return httpServerEvents;
|
|
159
|
-
}
|
package/esm/remult-fastify.js
CHANGED
package/esm/remult-fresh.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createRemultServerCore } from "./server/expressBridge";
|
|
2
2
|
export function remultFresh(options, response) {
|
|
3
|
-
const server =
|
|
3
|
+
const server = createRemultServerCore(options);
|
|
4
4
|
return {
|
|
5
5
|
getRemult: r => server.getRemult(r),
|
|
6
6
|
openApiDoc: x => server.openApiDoc(x),
|
|
@@ -1,43 +1,19 @@
|
|
|
1
|
-
import { Knex } from 'knex';
|
|
2
|
-
import { Filter, FilterConsumer } from "../src/filter/filter-interfaces";
|
|
3
|
-
import { dbNameProvider } from "../src/filter/filter-consumer-bridge-to-sql-request";
|
|
1
|
+
import type { Knex } from 'knex';
|
|
4
2
|
import { Remult } from "../src/context";
|
|
5
|
-
import { EntityFilter, EntityMetadata } from "../src/remult3";
|
|
3
|
+
import { EntityFilter, EntityMetadata, RepositoryOverloads } from "../src/remult3";
|
|
6
4
|
import { DataProvider, EntityDataProvider } from '../src/data-interfaces';
|
|
7
5
|
import { FieldMetadata } from '../src/column-interfaces';
|
|
8
6
|
export declare class KnexDataProvider implements DataProvider {
|
|
9
7
|
knex: Knex;
|
|
10
8
|
constructor(knex: Knex);
|
|
9
|
+
static getDb(remult?: Remult): Knex<any, Record<string, any>[]>;
|
|
11
10
|
getEntityDataProvider(entity: EntityMetadata<any>): EntityDataProvider;
|
|
12
11
|
transaction(action: (dataProvider: DataProvider) => Promise<void>): Promise<void>;
|
|
13
|
-
static
|
|
14
|
-
|
|
12
|
+
static rawFilter(build: CustomKnexFilterBuilderFunction): EntityFilter<any>;
|
|
13
|
+
static filterToRaw<entityType>(entity: RepositoryOverloads<entityType>, condition: EntityFilter<entityType>): Promise<(knex: any) => void>;
|
|
14
|
+
supportsrawFilter?: boolean;
|
|
15
15
|
}
|
|
16
16
|
export declare type CustomKnexFilterBuilderFunction = () => Promise<(builder: Knex.QueryBuilder) => void>;
|
|
17
|
-
export declare class FilterConsumerBridgeToKnexRequest implements FilterConsumer {
|
|
18
|
-
private nameProvider;
|
|
19
|
-
_addWhere: boolean;
|
|
20
|
-
promises: Promise<void>[];
|
|
21
|
-
result: ((builder: Knex.QueryBuilder) => void)[];
|
|
22
|
-
resolveWhere(): Promise<((builder: Knex.QueryBuilder<any, any>) => void)[]>;
|
|
23
|
-
constructor(nameProvider: dbNameProvider);
|
|
24
|
-
custom(key: string, customItem: any): void;
|
|
25
|
-
or(orElements: Filter[]): void;
|
|
26
|
-
isNull(col: FieldMetadata): void;
|
|
27
|
-
isNotNull(col: FieldMetadata): void;
|
|
28
|
-
isIn(col: FieldMetadata, val: any[]): void;
|
|
29
|
-
isEqualTo(col: FieldMetadata, val: any): void;
|
|
30
|
-
isDifferentFrom(col: FieldMetadata, val: any): void;
|
|
31
|
-
isGreaterOrEqualTo(col: FieldMetadata, val: any): void;
|
|
32
|
-
isGreaterThan(col: FieldMetadata, val: any): void;
|
|
33
|
-
isLessOrEqualTo(col: FieldMetadata, val: any): void;
|
|
34
|
-
isLessThan(col: FieldMetadata, val: any): void;
|
|
35
|
-
containsCaseInsensitive(col: FieldMetadata, val: any): void;
|
|
36
|
-
private add;
|
|
37
|
-
databaseCustom(databaseCustom: {
|
|
38
|
-
buildKnex: CustomKnexFilterBuilderFunction;
|
|
39
|
-
}): void;
|
|
40
|
-
}
|
|
41
17
|
export declare class KnexSchemaBuilder {
|
|
42
18
|
private knex;
|
|
43
19
|
verifyStructureOfAllEntities(remult: Remult): Promise<void>;
|