remult 0.18.1-exp.2 → 0.18.1-exp.21

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.
Files changed (154) hide show
  1. package/README.md +28 -5
  2. package/esm/index.d.ts +4 -3
  3. package/esm/index.js +4 -2
  4. package/esm/live-query/ably.d.ts +6 -6
  5. package/esm/live-query/ably.js +5 -5
  6. package/esm/postgres/postgres-data-provider.d.ts +3 -1
  7. package/esm/postgres/postgres-data-provider.js +11 -1
  8. package/esm/postgres/schema-builder.d.ts +1 -1
  9. package/esm/postgres/schema-builder.js +43 -27
  10. package/esm/remult-express.d.ts +4 -22
  11. package/esm/remult-express.js +30 -28
  12. package/esm/remult-fastify.js +1 -1
  13. package/esm/remult-fresh.js +2 -2
  14. package/esm/remult-knex/index.d.ts +7 -31
  15. package/esm/remult-knex/index.js +71 -42
  16. package/esm/remult-mongo.d.ts +9 -2
  17. package/esm/remult-mongo.js +24 -8
  18. package/esm/remult-next.d.ts +11 -0
  19. package/esm/remult-next.js +27 -0
  20. package/esm/server/expressBridge.d.ts +20 -52
  21. package/esm/server/expressBridge.js +55 -29
  22. package/esm/server/index.d.ts +3 -1
  23. package/esm/server/index.js +6 -1
  24. package/esm/src/column-interfaces.d.ts +44 -8
  25. package/esm/src/context.d.ts +31 -19
  26. package/esm/src/context.js +35 -42
  27. package/esm/src/data-api.js +17 -4
  28. package/esm/src/data-interfaces.d.ts +1 -1
  29. package/esm/src/data-providers/array-entity-data-provider.d.ts +1 -1
  30. package/esm/src/data-providers/array-entity-data-provider.js +1 -1
  31. package/esm/src/data-providers/rest-data-provider.d.ts +4 -15
  32. package/esm/src/data-providers/rest-data-provider.js +38 -23
  33. package/esm/src/data-providers/sql-database.d.ts +6 -3
  34. package/esm/src/data-providers/sql-database.js +57 -16
  35. package/esm/src/data-providers/web-sql-data-provider.d.ts +2 -0
  36. package/esm/src/data-providers/web-sql-data-provider.js +17 -8
  37. package/esm/src/entity.d.ts +2 -2
  38. package/esm/src/filter/filter-consumer-bridge-to-sql-request.d.ts +16 -16
  39. package/esm/src/filter/filter-consumer-bridge-to-sql-request.js +29 -21
  40. package/esm/src/filter/filter-interfaces.d.ts +5 -5
  41. package/esm/src/filter/filter-interfaces.js +31 -26
  42. package/esm/src/live-query/LiveQueryClient.d.ts +1 -19
  43. package/esm/src/live-query/LiveQueryClient.js +81 -50
  44. package/esm/src/live-query/SseSubscriptionClient.d.ts +4 -0
  45. package/esm/src/live-query/{EventSourceLiveQueryProvider.js → SseSubscriptionClient.js} +7 -6
  46. package/esm/src/live-query/SubscriptionChannel.d.ts +41 -0
  47. package/esm/src/live-query/{LiveQuerySubscriber.js → SubscriptionChannel.js} +40 -22
  48. package/esm/src/live-query/SubscriptionServer.d.ts +38 -0
  49. package/esm/src/live-query/{LiveQueryPublisher.js → SubscriptionServer.js} +60 -73
  50. package/esm/src/remult-proxy.js +44 -1
  51. package/esm/src/remult3/RepositoryImplementation.d.ts +8 -2
  52. package/esm/src/remult3/RepositoryImplementation.js +94 -30
  53. package/esm/src/remult3/remult3.d.ts +59 -6
  54. package/esm/src/remult3/remult3.js +1 -0
  55. package/esm/src/server-action.d.ts +1 -1
  56. package/esm/src/shared-tests/db-tests-setup.d.ts +1 -1
  57. package/esm/src/shared-tests/db-tests-setup.js +4 -3
  58. package/esm/src/shared-tests/db-tests.db-tests.js +55 -9
  59. package/esm/src/sql-command.d.ts +4 -2
  60. package/esm/src/tests/entityForCustomFilter.d.ts +6 -6
  61. package/esm/src/tests/entityForCustomFilter.js +20 -21
  62. package/esm/src/tests/frontend-database-tests-setup.spec.js +1 -2
  63. package/esm/src/tests/testHelper.spec.d.ts +2 -2
  64. package/esm/src/tests/testHelper.spec.js +1 -2
  65. package/esm/src/valueConverters.js +17 -7
  66. package/index.d.ts +4 -3
  67. package/index.js +7 -3
  68. package/live-query/ably.d.ts +6 -6
  69. package/live-query/ably.js +12 -12
  70. package/package.json +18 -9
  71. package/postgres/postgres-data-provider.d.ts +3 -1
  72. package/postgres/postgres-data-provider.js +13 -3
  73. package/postgres/schema-builder.d.ts +1 -1
  74. package/postgres/schema-builder.js +64 -50
  75. package/remult-express.d.ts +4 -22
  76. package/remult-express.js +39 -47
  77. package/remult-fastify.js +2 -2
  78. package/remult-fresh.js +1 -1
  79. package/remult-knex/index.d.ts +7 -31
  80. package/remult-knex/index.js +100 -53
  81. package/remult-mongo.d.ts +9 -2
  82. package/remult-mongo.js +39 -7
  83. package/remult-next.d.ts +11 -0
  84. package/remult-next.js +73 -0
  85. package/server/JsonEntityFileStorage.js +2 -2
  86. package/server/expressBridge.d.ts +20 -52
  87. package/server/expressBridge.js +68 -41
  88. package/server/index.d.ts +3 -1
  89. package/server/index.js +7 -2
  90. package/src/column-interfaces.d.ts +44 -8
  91. package/src/context.d.ts +31 -19
  92. package/src/context.js +39 -50
  93. package/src/data-api.js +18 -5
  94. package/src/data-interfaces.d.ts +1 -1
  95. package/src/data-providers/array-entity-data-provider.d.ts +1 -1
  96. package/src/data-providers/array-entity-data-provider.js +1 -1
  97. package/src/data-providers/rest-data-provider.d.ts +4 -15
  98. package/src/data-providers/rest-data-provider.js +48 -24
  99. package/src/data-providers/sql-database.d.ts +6 -3
  100. package/src/data-providers/sql-database.js +75 -15
  101. package/src/data-providers/web-sql-data-provider.d.ts +2 -0
  102. package/src/data-providers/web-sql-data-provider.js +16 -7
  103. package/src/entity.d.ts +2 -2
  104. package/src/filter/filter-consumer-bridge-to-sql-request.d.ts +16 -16
  105. package/src/filter/filter-consumer-bridge-to-sql-request.js +59 -50
  106. package/src/filter/filter-interfaces.d.ts +5 -5
  107. package/src/filter/filter-interfaces.js +31 -26
  108. package/src/live-query/LiveQueryClient.d.ts +1 -19
  109. package/src/live-query/LiveQueryClient.js +117 -64
  110. package/src/live-query/SseSubscriptionClient.d.ts +4 -0
  111. package/src/live-query/{EventSourceLiveQueryProvider.js → SseSubscriptionClient.js} +13 -12
  112. package/src/live-query/SubscriptionChannel.d.ts +41 -0
  113. package/src/live-query/{LiveQuerySubscriber.js → SubscriptionChannel.js} +51 -47
  114. package/src/live-query/SubscriptionServer.d.ts +38 -0
  115. package/src/live-query/SubscriptionServer.js +237 -0
  116. package/src/remult-proxy.js +137 -2
  117. package/src/remult3/RepositoryImplementation.d.ts +8 -2
  118. package/src/remult3/RepositoryImplementation.js +121 -34
  119. package/src/remult3/remult3.d.ts +59 -6
  120. package/src/remult3/remult3.js +1 -0
  121. package/src/server-action.d.ts +1 -1
  122. package/src/shared-tests/db-tests-setup.d.ts +1 -1
  123. package/src/shared-tests/db-tests-setup.js +5 -4
  124. package/src/shared-tests/db-tests.db-tests.js +101 -8
  125. package/src/sql-command.d.ts +4 -2
  126. package/src/tests/entityForCustomFilter.d.ts +6 -6
  127. package/src/tests/entityForCustomFilter.js +30 -31
  128. package/src/tests/frontend-database-tests-setup.spec.js +4 -5
  129. package/src/tests/testHelper.spec.d.ts +2 -2
  130. package/src/tests/testHelper.spec.js +4 -5
  131. package/src/valueConverters.js +17 -7
  132. package/esm/live-query/index.d.ts +0 -3
  133. package/esm/live-query/index.js +0 -3
  134. package/esm/src/backend-tests/backend-database-test-setup.backend-spec.d.ts +0 -5
  135. package/esm/src/backend-tests/backend-database-test-setup.backend-spec.js +0 -113
  136. package/esm/src/backend-tests/my-test.backend-spec.d.ts +0 -1
  137. package/esm/src/backend-tests/my-test.backend-spec.js +0 -59
  138. package/esm/src/backend-tests/test-http-server.backend-spec.d.ts +0 -6
  139. package/esm/src/backend-tests/test-http-server.backend-spec.js +0 -171
  140. package/esm/src/live-query/EventSourceLiveQueryProvider.d.ts +0 -4
  141. package/esm/src/live-query/LiveQueryPublisher.d.ts +0 -49
  142. package/esm/src/live-query/LiveQuerySubscriber.d.ts +0 -67
  143. package/live-query/index.d.ts +0 -3
  144. package/live-query/index.js +0 -10
  145. package/src/backend-tests/backend-database-test-setup.backend-spec.d.ts +0 -5
  146. package/src/backend-tests/backend-database-test-setup.backend-spec.js +0 -231
  147. package/src/backend-tests/my-test.backend-spec.d.ts +0 -1
  148. package/src/backend-tests/my-test.backend-spec.js +0 -160
  149. package/src/backend-tests/test-http-server.backend-spec.d.ts +0 -6
  150. package/src/backend-tests/test-http-server.backend-spec.js +0 -342
  151. package/src/live-query/EventSourceLiveQueryProvider.d.ts +0 -4
  152. package/src/live-query/LiveQueryPublisher.d.ts +0 -49
  153. package/src/live-query/LiveQueryPublisher.js +0 -248
  154. 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
- [Getting Started](#getting-started) | [Documentation](#documentation) |
34
- [Example Apps](#example-apps)
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,4 +1,4 @@
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, LiveQuery, LiveQueryChangeInfo } from './src/remult3';
2
2
  export { StringFieldOptions } from './src/remult3/RepositoryImplementation';
3
3
  export { describeClass } from './src/remult3/DecoratorReplacer';
4
4
  export { EntityOptions } from './src/entity';
@@ -11,7 +11,7 @@ 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
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';
@@ -20,8 +20,9 @@ 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 { SubscriptionListener, SubscriptionClientConnection, SubscriptionClient, SubscriptionChannel, LiveQueryChange, Unsubscribe } from './src/live-query/SubscriptionChannel';
package/esm/index.js CHANGED
@@ -8,7 +8,7 @@ export { InMemoryDataProvider } from './src/data-providers/in-memory-database';
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
14
  export { Controller, BackendMethod, ProgressListener } from './src/server-action';
@@ -17,8 +17,10 @@ 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/SubscriptionChannel';
@@ -1,13 +1,13 @@
1
1
  import type * as Ably from 'ably';
2
- import type { ServerEventDispatcher } from '../src/live-query/LiveQueryPublisher';
3
- import type { LiveQueryProvider, PubSubClient } from '../src/live-query/LiveQuerySubscriber';
4
- export declare class AblyLiveQueryProvider implements LiveQueryProvider {
2
+ import type { SubscriptionServer } from '../src/live-query/SubscriptionServer';
3
+ import type { SubscriptionClient, SubscriptionClientConnection } from '../src/live-query/SubscriptionChannel';
4
+ export declare class AblySubscriptionClient implements SubscriptionClient {
5
5
  private ably;
6
6
  constructor(ably: Ably.Types.RealtimePromise);
7
- openStreamAndReturnCloseFunction(onReconnect: VoidFunction): Promise<PubSubClient>;
7
+ openConnection(onReconnect: VoidFunction): Promise<SubscriptionClientConnection>;
8
8
  }
9
- export declare class AblyServerEventDispatcher implements ServerEventDispatcher {
9
+ export declare class AblySubscriptionServer implements SubscriptionServer {
10
10
  private ably;
11
11
  constructor(ably: Ably.Types.RealtimePromise);
12
- sendChannelMessage<T>(channel: string, message: T): void;
12
+ publishMessage<T>(channel: string, message: T): void;
13
13
  }
@@ -1,10 +1,10 @@
1
- export class AblyLiveQueryProvider {
1
+ export class AblySubscriptionClient {
2
2
  constructor(ably) {
3
3
  this.ably = ably;
4
4
  }
5
- async openStreamAndReturnCloseFunction(onReconnect) {
5
+ async openConnection(onReconnect) {
6
6
  return {
7
- disconnect: () => {
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 AblyServerEventDispatcher {
18
+ export class AblySubscriptionServer {
19
19
  constructor(ably) {
20
20
  this.ably = ably;
21
21
  }
22
- sendChannelMessage(channel, message) {
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
  }
@@ -6,7 +6,7 @@ export declare function postgresColumnSyntax(x: FieldMetadata, dbName: string):
6
6
  export declare function verifyStructureOfAllEntities(db: SqlDatabase, remult: Remult): Promise<void>;
7
7
  export declare class PostgresSchemaBuilder {
8
8
  private pool;
9
- verifyStructureOfAllEntities(remult: Remult): Promise<void>;
9
+ verifyStructureOfAllEntities(remult?: Remult): Promise<void>;
10
10
  createIfNotExist(entity: EntityMetadata): Promise<void>;
11
11
  addColumnIfNotExist<T extends EntityMetadata>(entity: T, c: ((e: T) => FieldMetadata)): Promise<void>;
12
12
  verifyAllColumns<T extends EntityMetadata>(entity: T): Promise<void>;
@@ -1,5 +1,6 @@
1
1
  import { allEntities } from '../src/context';
2
- import { getDbNameProvider } from '../src/filter/filter-consumer-bridge-to-sql-request';
2
+ import { dbNamesOf, isDbReadonly } from '../src/filter/filter-consumer-bridge-to-sql-request';
3
+ import { RemultProxy } from '../src/remult-proxy';
3
4
  import { isAutoIncrement } from '../src/remult3';
4
5
  import { ValueConverters } from '../src/valueConverters';
5
6
  export function postgresColumnSyntax(x, dbName) {
@@ -43,61 +44,73 @@ export class PostgresSchemaBuilder {
43
44
  }
44
45
  }
45
46
  async verifyStructureOfAllEntities(remult) {
46
- console.log("start verify structure"); //keep me
47
- for (const entityClass of allEntities) {
47
+ if (!remult) {
48
+ remult = RemultProxy.defaultRemult;
49
+ }
50
+ if (PostgresSchemaBuilder.logToConsole)
51
+ console.time("Postgres Auto create tables and columns");
52
+ const completed = new Set();
53
+ for (const entityClass of [...allEntities].reverse()) {
48
54
  let entity = remult.repo(entityClass).metadata;
49
- let e = await getDbNameProvider(entity);
55
+ let e = await dbNamesOf(entity);
56
+ if (completed.has(e.$entityName))
57
+ continue;
58
+ completed.add(e.$entityName);
50
59
  try {
51
60
  if (!entity.options.sqlExpression) {
52
- if ((await e.entityName).toLowerCase().indexOf('from ') < 0) {
61
+ if ((await e.$entityName).toLowerCase().indexOf('from ') < 0) {
53
62
  await this.createIfNotExist(entity);
54
63
  await this.verifyAllColumns(entity);
55
64
  }
56
65
  }
57
66
  }
58
67
  catch (err) {
59
- /*keep me */ console.log("failed verify structure of " + e.entityName + " ", err);
68
+ console.error("failed verify structure of " + e.$entityName + " ", err);
60
69
  }
61
70
  }
71
+ if (PostgresSchemaBuilder.logToConsole)
72
+ console.timeEnd("Postgres Auto create tables and columns");
62
73
  }
63
74
  async createIfNotExist(entity) {
64
75
  var c = this.pool.createCommand();
65
- let e = await getDbNameProvider(entity);
66
- await c.execute("select 1 from information_Schema.tables where table_name=" + c.addParameterAndReturnSqlToken((e.entityName).toLowerCase()) + this.additionalWhere).then(async (r) => {
76
+ let e = await dbNamesOf(entity);
77
+ await c.execute("select 1 from information_Schema.tables where table_name=" + c.addParameterAndReturnSqlToken((e.$entityName).toLowerCase()) + this.additionalWhere).then(async (r) => {
67
78
  if (r.rows.length == 0) {
68
79
  let result = '';
69
80
  for (const x of entity.fields) {
70
- if (!e.isDbReadonly(x) || isAutoIncrement(x)) {
81
+ if (!isDbReadonly(x, e) || isAutoIncrement(x)) {
71
82
  if (result.length != 0)
72
83
  result += ',';
73
84
  result += '\r\n ';
74
85
  if (isAutoIncrement(x))
75
- result += e.nameOf(x) + ' serial';
86
+ result += e.$dbNameOf(x) + ' serial';
76
87
  else {
77
- result += postgresColumnSyntax(x, e.nameOf(x));
78
- if (x == entity.idMetadata.field)
79
- result += ' primary key';
88
+ result += postgresColumnSyntax(x, e.$dbNameOf(x));
80
89
  }
90
+ if (x == entity.idMetadata.field)
91
+ result += ' primary key';
81
92
  }
82
93
  }
83
- let sql = 'create table ' + e.entityName + ' (' + result + '\r\n)';
84
- //console.log(sql);
94
+ let sql = 'create table ' + e.$entityName + ' (' + result + '\r\n)';
95
+ if (PostgresSchemaBuilder.logToConsole)
96
+ console.info(sql);
85
97
  await this.pool.execute(sql);
86
98
  }
87
99
  });
88
100
  }
89
101
  async addColumnIfNotExist(entity, c) {
90
- let e = await getDbNameProvider(entity);
91
- if (e.isDbReadonly(c(entity)))
102
+ let e = await dbNamesOf(entity);
103
+ if (isDbReadonly(c(entity), e))
92
104
  return;
93
105
  try {
94
106
  let cmd = this.pool.createCommand();
95
- const colName = e.nameOf(c(entity));
107
+ const colName = e.$dbNameOf(c(entity));
96
108
  if ((await cmd.execute(`select 1
97
109
  FROM information_schema.columns
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
- //console.log(sql);
110
+ WHERE table_name=${cmd.addParameterAndReturnSqlToken((e.$entityName).toLocaleLowerCase())} and column_name=${cmd.addParameterAndReturnSqlToken((colName).toLocaleLowerCase())}` + this.additionalWhere)).rows.length == 0) {
111
+ let sql = `alter table ${e.$entityName} add column ${postgresColumnSyntax(c(entity), colName)}`;
112
+ if (PostgresSchemaBuilder.logToConsole)
113
+ console.info(sql);
101
114
  await this.pool.execute(sql);
102
115
  }
103
116
  }
@@ -108,15 +121,16 @@ export class PostgresSchemaBuilder {
108
121
  async verifyAllColumns(entity) {
109
122
  try {
110
123
  let cmd = this.pool.createCommand();
111
- let e = await getDbNameProvider(entity);
124
+ let e = await dbNamesOf(entity);
112
125
  let cols = (await cmd.execute(`select column_name
113
126
  FROM information_schema.columns
114
- WHERE table_name=${cmd.addParameterAndReturnSqlToken((e.entityName).toLocaleLowerCase())} ` + this.additionalWhere)).rows.map(x => x.column_name);
127
+ WHERE table_name=${cmd.addParameterAndReturnSqlToken((e.$entityName).toLocaleLowerCase())} ` + this.additionalWhere)).rows.map(x => x.column_name);
115
128
  for (const col of entity.fields) {
116
- if (!e.isDbReadonly(col))
117
- if (!cols.includes(e.nameOf(col).toLocaleLowerCase())) {
118
- let sql = `alter table ${e.entityName} add column ${postgresColumnSyntax(col, e.nameOf(col))}`;
119
- //console.log(sql);
129
+ if (!isDbReadonly(col, e))
130
+ if (!cols.includes(e.$dbNameOf(col).toLocaleLowerCase())) {
131
+ let sql = `alter table ${e.$entityName} add column ${postgresColumnSyntax(col, e.$dbNameOf(col))}`;
132
+ if (PostgresSchemaBuilder.logToConsole)
133
+ console.info(sql);
120
134
  await this.pool.execute(sql);
121
135
  }
122
136
  }
@@ -126,3 +140,5 @@ export class PostgresSchemaBuilder {
126
140
  }
127
141
  }
128
142
  }
143
+ //@internal
144
+ PostgresSchemaBuilder.logToConsole = true;
@@ -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 { ServerEventChannelSubscribeDTO } from './src/live-query/LiveQuerySubscriber';
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 ServerEventsController implements ServerEventDispatcher {
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
- sendChannelMessage<T>(channel: string, message: any): void;
17
- debugMessageFileSaver: (id: any, channel: any, message: any) => void;
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 {};
@@ -1,7 +1,6 @@
1
1
  import * as express from 'express';
2
- import { createRemultServer } from './server/expressBridge';
3
- import { liveQueryKeepAliveRoute, streamUrl } from './src/live-query/LiveQuerySubscriber';
4
- import { LiveQueryPublisher, LiveQueryStorageInMemoryImplementation } from './src/live-query/LiveQueryPublisher';
2
+ import { createRemultServer } from './server/index';
3
+ import { streamUrl } from './src/live-query/SubscriptionChannel';
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,16 @@ 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
- if (!options.serverEventDispatcher) {
23
- options.serverEventDispatcher = (router, server) => {
24
- return buildHttpServerEventDispatcher(router, options.rootPath, server);
25
- };
24
+ const canRegisterRoute = options.subscriptionServer;
25
+ if (canRegisterRoute.registerRoutes) {
26
+ canRegisterRoute.registerRoutes(app, options.rootPath, server);
26
27
  }
27
- app.post(options.rootPath + liveQueryKeepAliveRoute, (r, res, n) => server.withRemult(r, res, n), async (req, res) => {
28
- res.send(await remult.liveQueryPublisher.storage.keepAliveAndReturnUnknownIds(req.body));
29
- });
30
- server.liveQueryManager = new LiveQueryPublisher(options.serverEventDispatcher(app, server), new LiveQueryStorageInMemoryImplementation(), async (req, entityKey, what) => {
28
+ server.runWithRequest = async (req, entityKey, what) => {
31
29
  for (const e of options.entities) {
32
30
  let key = getEntityKey(e);
33
31
  if (key === entityKey) {
@@ -41,7 +39,7 @@ export function remultExpress(options) {
41
39
  }
42
40
  }
43
41
  throw new Error("Couldn't find entity " + entityKey);
44
- });
42
+ };
45
43
  return Object.assign(app, {
46
44
  getRemult: (req) => server.getRemult(req),
47
45
  openApiDoc: (options) => server.openApiDoc(options),
@@ -49,16 +47,20 @@ export function remultExpress(options) {
49
47
  withRemult: (...args) => server.withRemult(...args)
50
48
  });
51
49
  }
52
- export class ServerEventsController {
50
+ export class SseSubscriptionServer {
53
51
  constructor(canUserConnectToChannel) {
54
52
  this.canUserConnectToChannel = canUserConnectToChannel;
53
+ //@internal
55
54
  this.connections = [];
55
+ //@internal
56
56
  this.debugMessageFileSaver = (id, channel, message) => { };
57
+ //@internal
57
58
  this.debugFileSaver = () => { };
58
59
  if (!this.canUserConnectToChannel) {
59
60
  this.canUserConnectToChannel = () => true;
60
61
  }
61
62
  }
63
+ //@internal
62
64
  subscribeToChannel({ channel, clientId }, res, remult, remove = false) {
63
65
  for (const c of this.connections) {
64
66
  if (c.connectionId === clientId) {
@@ -80,7 +82,7 @@ export class ServerEventsController {
80
82
  }
81
83
  res.sendStatus(404);
82
84
  }
83
- sendChannelMessage(channel, message) {
85
+ publishMessage(channel, message) {
84
86
  const data = JSON.stringify({ channel, data: message });
85
87
  for (const sc of this.connections) {
86
88
  if (sc.channels[channel]) {
@@ -89,6 +91,7 @@ export class ServerEventsController {
89
91
  }
90
92
  }
91
93
  }
94
+ //@internal
92
95
  openHttpServerStream(req, res) {
93
96
  res.writeHead(200, {
94
97
  'Content-Type': 'text/event-stream',
@@ -106,12 +109,25 @@ export class ServerEventsController {
106
109
  });
107
110
  return cc;
108
111
  }
112
+ //@internal
109
113
  debug() {
110
114
  this.debugFileSaver(this.connections.map(x => ({
111
115
  id: x.connectionId,
112
116
  channels: x.channels
113
117
  })));
114
118
  }
119
+ registerRoutes(router, apiPath, server) {
120
+ const streamPath = apiPath + '/' + streamUrl;
121
+ router.get(streamPath, (r, res, next) => server.withRemult(r, res, next), (req, res) => {
122
+ remult.subscriptionServer.openHttpServerStream(req, res);
123
+ });
124
+ router.post(streamPath + '/subscribe', (r, res, next) => server.withRemult(r, res, next), (req, res) => {
125
+ remult.subscriptionServer.subscribeToChannel(req.body, res, remult);
126
+ });
127
+ router.post(streamPath + '/unsubscribe', (r, res, next) => server.withRemult(r, res, next), (req, res) => {
128
+ remult.subscriptionServer.subscribeToChannel(req.body, res, remult, true);
129
+ });
130
+ }
115
131
  }
116
132
  class clientConnection {
117
133
  constructor(response) {
@@ -143,17 +159,3 @@ class clientConnection {
143
159
  }, 45000);
144
160
  }
145
161
  }
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
- }
@@ -1,4 +1,4 @@
1
- import { createRemultServer } from './server/expressBridge';
1
+ import { createRemultServer } from './server/index';
2
2
  export function remultFastify(options) {
3
3
  function fastifyHandler(handler) {
4
4
  const response = (req, res) => {
@@ -1,6 +1,6 @@
1
- import { createRemultServer } from "./server/expressBridge";
1
+ import { createRemultServerCore } from "./server/expressBridge";
2
2
  export function remultFresh(options, response) {
3
- const server = createRemultServer(options);
3
+ const server = createRemultServerCore(options);
4
4
  return {
5
5
  getRemult: r => server.getRemult(r),
6
6
  openApiDoc: x => server.openApiDoc(x),
@@ -1,46 +1,22 @@
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, any[]>;
11
10
  getEntityDataProvider(entity: EntityMetadata<any>): EntityDataProvider;
12
11
  transaction(action: (dataProvider: DataProvider) => Promise<void>): Promise<void>;
13
- static customFilter(build: CustomKnexFilterBuilderFunction): EntityFilter<any>;
14
- supportsCustomFilter?: boolean;
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
- verifyStructureOfAllEntities(remult: Remult): Promise<void>;
19
+ verifyStructureOfAllEntities(remult?: Remult): Promise<void>;
44
20
  createIfNotExist(entity: EntityMetadata): Promise<void>;
45
21
  addColumnIfNotExist<T extends EntityMetadata>(entity: T, c: ((e: T) => FieldMetadata)): Promise<void>;
46
22
  verifyAllColumns<T extends EntityMetadata>(entity: T): Promise<void>;