remult 0.17.3 → 0.18.0
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/SseSubscriptionServer.d.ts +23 -0
- package/SseSubscriptionServer.js +143 -0
- package/ably.d.ts +13 -0
- package/ably.js +59 -0
- package/esm/SseSubscriptionServer.d.ts +23 -0
- package/esm/SseSubscriptionServer.js +102 -0
- package/esm/ably.d.ts +13 -0
- package/esm/ably.js +28 -0
- package/esm/index.d.ts +7 -4
- package/esm/index.js +4 -2
- package/esm/live-query/data-provider-live-query-storage.d.ts +23 -0
- package/esm/live-query/data-provider-live-query-storage.js +78 -0
- package/esm/myLog.d.ts +1 -0
- package/esm/myLog.js +5 -0
- package/esm/postgres/postgres-data-provider.d.ts +4 -2
- package/esm/postgres/postgres-data-provider.js +18 -6
- package/esm/postgres/schema-builder.d.ts +2 -1
- package/esm/postgres/schema-builder.js +49 -29
- package/esm/remult-knex/index.d.ts +10 -32
- package/esm/remult-knex/index.js +75 -51
- package/esm/remult-mongo.d.ts +9 -2
- package/esm/remult-mongo.js +24 -8
- package/esm/remult-next.d.ts +11 -0
- package/esm/remult-next.js +27 -0
- package/esm/server/core.d.ts +2 -0
- package/esm/server/core.js +2 -0
- package/esm/server/expressBridge.d.ts +19 -7
- package/esm/server/expressBridge.js +135 -31
- package/esm/server/index.d.ts +2 -1
- package/esm/server/index.js +2 -1
- package/esm/server/initDataProvider.d.ts +2 -0
- package/esm/server/initDataProvider.js +14 -0
- package/esm/src/buildRestDataProvider.d.ts +31 -0
- package/esm/src/buildRestDataProvider.js +110 -0
- package/esm/src/column-interfaces.d.ts +44 -8
- package/esm/src/column.d.ts +3 -3
- package/esm/src/context.d.ts +39 -36
- package/esm/src/context.js +87 -117
- package/esm/src/data-api.d.ts +9 -3
- package/esm/src/data-api.js +130 -63
- package/esm/src/data-interfaces.d.ts +5 -1
- package/esm/src/data-providers/array-entity-data-provider.d.ts +1 -1
- package/esm/src/data-providers/array-entity-data-provider.js +2 -17
- package/esm/src/data-providers/rest-data-provider.d.ts +4 -3
- package/esm/src/data-providers/rest-data-provider.js +64 -23
- package/esm/src/data-providers/sql-database.d.ts +7 -3
- package/esm/src/data-providers/sql-database.js +60 -17
- package/esm/src/data-providers/web-sql-data-provider.d.ts +3 -0
- package/esm/src/data-providers/web-sql-data-provider.js +23 -9
- 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 +31 -26
- package/esm/src/live-query/LiveQueryClient.d.ts +1 -0
- package/esm/src/live-query/LiveQueryClient.js +184 -0
- package/esm/src/live-query/SseSubscriptionClient.d.ts +5 -0
- package/esm/src/live-query/SseSubscriptionClient.js +86 -0
- package/esm/src/live-query/SubscriptionChannel.d.ts +41 -0
- package/esm/src/live-query/SubscriptionChannel.js +121 -0
- package/esm/src/live-query/SubscriptionServer.d.ts +38 -0
- package/esm/src/live-query/SubscriptionServer.js +108 -0
- package/esm/src/remult-proxy.d.ts +1 -1
- package/esm/src/remult-proxy.js +52 -7
- package/esm/src/remult3/RepositoryImplementation.d.ts +14 -5
- package/esm/src/remult3/RepositoryImplementation.js +124 -44
- package/esm/src/remult3/getId.d.ts +2 -0
- package/esm/src/remult3/getId.js +7 -0
- package/esm/src/remult3/remult3.d.ts +67 -10
- package/esm/src/remult3/remult3.js +1 -0
- package/esm/src/server-action.d.ts +5 -1
- package/esm/src/server-action.js +11 -12
- package/esm/src/shared-tests/db-tests-setup.d.ts +12 -5
- package/esm/src/shared-tests/db-tests-setup.js +14 -6
- package/esm/src/shared-tests/db-tests.db-tests.js +71 -10
- package/esm/src/sort.d.ts +1 -0
- package/esm/src/sort.js +18 -0
- package/esm/src/sql-command.d.ts +5 -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 +3 -4
- package/esm/src/tests/testHelper.spec.d.ts +3 -1
- package/esm/src/tests/testHelper.spec.js +63 -60
- package/esm/src/valueConverters.js +15 -7
- package/index.d.ts +7 -4
- package/index.js +7 -3
- package/live-query/data-provider-live-query-storage.d.ts +23 -0
- package/live-query/data-provider-live-query-storage.js +236 -0
- package/myLog.d.ts +1 -0
- package/myLog.js +20 -0
- package/package.json +18 -1
- package/postgres/postgres-data-provider.d.ts +4 -2
- package/postgres/postgres-data-provider.js +54 -39
- package/postgres/schema-builder.d.ts +2 -1
- package/postgres/schema-builder.js +118 -70
- package/remult-express.js +1 -1
- package/remult-knex/index.d.ts +10 -32
- package/remult-knex/index.js +134 -87
- package/remult-mongo.d.ts +9 -2
- package/remult-mongo.js +39 -7
- package/remult-next.d.ts +11 -0
- package/remult-next.js +73 -0
- package/server/JsonEntityFileStorage.js +2 -2
- package/server/core.d.ts +2 -0
- package/server/core.js +5 -1
- package/server/expressBridge.d.ts +19 -7
- package/server/expressBridge.js +283 -69
- package/server/index.d.ts +2 -1
- package/server/index.js +3 -1
- package/server/initDataProvider.d.ts +2 -0
- package/server/initDataProvider.js +26 -0
- package/src/buildRestDataProvider.d.ts +31 -0
- package/src/buildRestDataProvider.js +162 -0
- package/src/column-interfaces.d.ts +44 -8
- package/src/column.d.ts +3 -3
- package/src/context.d.ts +39 -36
- package/src/context.js +171 -166
- package/src/data-api.d.ts +9 -3
- package/src/data-api.js +233 -88
- package/src/data-interfaces.d.ts +5 -1
- package/src/data-providers/array-entity-data-provider.d.ts +1 -1
- package/src/data-providers/array-entity-data-provider.js +2 -17
- package/src/data-providers/rest-data-provider.d.ts +4 -3
- package/src/data-providers/rest-data-provider.js +105 -39
- package/src/data-providers/sql-database.d.ts +7 -3
- package/src/data-providers/sql-database.js +89 -16
- package/src/data-providers/web-sql-data-provider.d.ts +3 -0
- package/src/data-providers/web-sql-data-provider.js +56 -11
- 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 +31 -26
- package/src/live-query/LiveQueryClient.d.ts +1 -0
- package/src/live-query/LiveQueryClient.js +283 -0
- package/src/live-query/SseSubscriptionClient.d.ts +5 -0
- package/src/live-query/SseSubscriptionClient.js +150 -0
- package/src/live-query/SubscriptionChannel.d.ts +41 -0
- package/src/live-query/SubscriptionChannel.js +209 -0
- package/src/live-query/SubscriptionServer.d.ts +38 -0
- package/src/live-query/SubscriptionServer.js +258 -0
- package/src/remult-proxy.d.ts +1 -1
- package/src/remult-proxy.js +153 -8
- package/src/remult3/RepositoryImplementation.d.ts +14 -5
- package/src/remult3/RepositoryImplementation.js +200 -85
- package/src/remult3/getId.d.ts +2 -0
- package/src/remult3/getId.js +11 -0
- package/src/remult3/remult3.d.ts +67 -10
- package/src/remult3/remult3.js +1 -0
- package/src/server-action.d.ts +5 -1
- package/src/server-action.js +11 -11
- package/src/shared-tests/db-tests-setup.d.ts +12 -5
- package/src/shared-tests/db-tests-setup.js +17 -8
- package/src/shared-tests/db-tests.db-tests.js +140 -8
- package/src/sort.d.ts +1 -0
- package/src/sort.js +18 -0
- package/src/sql-command.d.ts +5 -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 +5 -6
- package/src/tests/testHelper.spec.d.ts +3 -1
- package/src/tests/testHelper.spec.js +104 -100
- package/src/valueConverters.js +15 -7
|
@@ -6,7 +6,8 @@ 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
|
|
9
|
+
verifyStructureOfAllEntities(remult?: Remult): Promise<void>;
|
|
10
|
+
ensureSchema(entities: EntityMetadata<any>[]): Promise<void>;
|
|
10
11
|
createIfNotExist(entity: EntityMetadata): Promise<void>;
|
|
11
12
|
addColumnIfNotExist<T extends EntityMetadata>(entity: T, c: ((e: T) => FieldMetadata)): Promise<void>;
|
|
12
13
|
verifyAllColumns<T extends EntityMetadata>(entity: T): Promise<void>;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { allEntities } from '../src/context';
|
|
2
|
-
import {
|
|
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,86 +44,105 @@ export class PostgresSchemaBuilder {
|
|
|
43
44
|
}
|
|
44
45
|
}
|
|
45
46
|
async verifyStructureOfAllEntities(remult) {
|
|
46
|
-
|
|
47
|
-
|
|
47
|
+
if (!remult) {
|
|
48
|
+
remult = RemultProxy.defaultRemult;
|
|
49
|
+
}
|
|
50
|
+
const completed = new Set();
|
|
51
|
+
const entities = [];
|
|
52
|
+
for (const entityClass of [...allEntities].reverse()) {
|
|
48
53
|
let entity = remult.repo(entityClass).metadata;
|
|
49
|
-
let e = await
|
|
54
|
+
let e = await dbNamesOf(entity);
|
|
55
|
+
if (completed.has(e.$entityName))
|
|
56
|
+
continue;
|
|
57
|
+
completed.add(e.$entityName);
|
|
58
|
+
entities.push(entity);
|
|
59
|
+
}
|
|
60
|
+
await this.ensureSchema(entities);
|
|
61
|
+
}
|
|
62
|
+
async ensureSchema(entities) {
|
|
63
|
+
for (const entity of entities) {
|
|
64
|
+
let e = await dbNamesOf(entity);
|
|
50
65
|
try {
|
|
51
66
|
if (!entity.options.sqlExpression) {
|
|
52
|
-
if (
|
|
67
|
+
if (e.$entityName.toLowerCase().indexOf('from ') < 0) {
|
|
53
68
|
await this.createIfNotExist(entity);
|
|
54
69
|
await this.verifyAllColumns(entity);
|
|
55
70
|
}
|
|
56
71
|
}
|
|
57
72
|
}
|
|
58
73
|
catch (err) {
|
|
59
|
-
console.
|
|
74
|
+
console.error("failed verify structure of " + e.$entityName + " ", err);
|
|
60
75
|
}
|
|
61
76
|
}
|
|
62
77
|
}
|
|
63
78
|
async createIfNotExist(entity) {
|
|
64
79
|
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
|
|
80
|
+
let e = await dbNamesOf(entity);
|
|
81
|
+
await c.execute("select 1 from information_Schema.tables where table_name=" + c.addParameterAndReturnSqlToken((e.$entityName).toLowerCase()) + this.additionalWhere).then(async (r) => {
|
|
67
82
|
if (r.rows.length == 0) {
|
|
68
83
|
let result = '';
|
|
69
84
|
for (const x of entity.fields) {
|
|
70
|
-
if (!
|
|
85
|
+
if (!isDbReadonly(x, e) || isAutoIncrement(x)) {
|
|
71
86
|
if (result.length != 0)
|
|
72
87
|
result += ',';
|
|
73
88
|
result += '\r\n ';
|
|
74
89
|
if (isAutoIncrement(x))
|
|
75
|
-
result += e
|
|
90
|
+
result += e.$dbNameOf(x) + ' serial';
|
|
76
91
|
else {
|
|
77
|
-
result += postgresColumnSyntax(x, e
|
|
78
|
-
if (x == entity.idMetadata.field)
|
|
79
|
-
result += ' primary key';
|
|
92
|
+
result += postgresColumnSyntax(x, e.$dbNameOf(x));
|
|
80
93
|
}
|
|
94
|
+
if (x == entity.idMetadata.field)
|
|
95
|
+
result += ' primary key';
|
|
81
96
|
}
|
|
82
97
|
}
|
|
83
|
-
let sql = 'create table ' + e
|
|
84
|
-
|
|
98
|
+
let sql = 'create table ' + e.$entityName + ' (' + result + '\r\n)';
|
|
99
|
+
if (PostgresSchemaBuilder.logToConsole)
|
|
100
|
+
console.info(sql);
|
|
85
101
|
await this.pool.execute(sql);
|
|
86
102
|
}
|
|
87
103
|
});
|
|
88
104
|
}
|
|
89
105
|
async addColumnIfNotExist(entity, c) {
|
|
90
|
-
let e = await
|
|
91
|
-
if (
|
|
106
|
+
let e = await dbNamesOf(entity);
|
|
107
|
+
if (isDbReadonly(c(entity), e))
|
|
92
108
|
return;
|
|
93
109
|
try {
|
|
94
110
|
let cmd = this.pool.createCommand();
|
|
95
|
-
const colName = e
|
|
111
|
+
const colName = e.$dbNameOf(c(entity));
|
|
96
112
|
if ((await cmd.execute(`select 1
|
|
97
113
|
FROM information_schema.columns
|
|
98
|
-
WHERE table_name=${cmd.addParameterAndReturnSqlToken((e
|
|
99
|
-
let sql = `alter table ${e
|
|
100
|
-
|
|
114
|
+
WHERE table_name=${cmd.addParameterAndReturnSqlToken((e.$entityName).toLocaleLowerCase())} and column_name=${cmd.addParameterAndReturnSqlToken((colName).toLocaleLowerCase())}` + this.additionalWhere)).rows.length == 0) {
|
|
115
|
+
let sql = `alter table ${e.$entityName} add column ${postgresColumnSyntax(c(entity), colName)}`;
|
|
116
|
+
if (PostgresSchemaBuilder.logToConsole)
|
|
117
|
+
console.info(sql);
|
|
101
118
|
await this.pool.execute(sql);
|
|
102
119
|
}
|
|
103
120
|
}
|
|
104
121
|
catch (err) {
|
|
105
|
-
console.
|
|
122
|
+
console.error(err);
|
|
106
123
|
}
|
|
107
124
|
}
|
|
108
125
|
async verifyAllColumns(entity) {
|
|
109
126
|
try {
|
|
110
127
|
let cmd = this.pool.createCommand();
|
|
111
|
-
let e = await
|
|
128
|
+
let e = await dbNamesOf(entity);
|
|
112
129
|
let cols = (await cmd.execute(`select column_name
|
|
113
130
|
FROM information_schema.columns
|
|
114
|
-
WHERE table_name=${cmd.addParameterAndReturnSqlToken((e
|
|
131
|
+
WHERE table_name=${cmd.addParameterAndReturnSqlToken((e.$entityName).toLocaleLowerCase())} ` + this.additionalWhere)).rows.map(x => x.column_name);
|
|
115
132
|
for (const col of entity.fields) {
|
|
116
|
-
if (!
|
|
117
|
-
if (!cols.includes(e
|
|
118
|
-
let sql = `alter table ${e
|
|
119
|
-
|
|
133
|
+
if (!isDbReadonly(col, e))
|
|
134
|
+
if (!cols.includes(e.$dbNameOf(col).toLocaleLowerCase())) {
|
|
135
|
+
let sql = `alter table ${e.$entityName} add column ${postgresColumnSyntax(col, e.$dbNameOf(col))}`;
|
|
136
|
+
if (PostgresSchemaBuilder.logToConsole)
|
|
137
|
+
console.info(sql);
|
|
120
138
|
await this.pool.execute(sql);
|
|
121
139
|
}
|
|
122
140
|
}
|
|
123
141
|
}
|
|
124
142
|
catch (err) {
|
|
125
|
-
console.
|
|
143
|
+
console.error(err);
|
|
126
144
|
}
|
|
127
145
|
}
|
|
128
146
|
}
|
|
147
|
+
//@internal
|
|
148
|
+
PostgresSchemaBuilder.logToConsole = true;
|
|
@@ -1,46 +1,24 @@
|
|
|
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
|
|
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
|
+
ensureSchema(entities: EntityMetadata<any>[]): Promise<void>;
|
|
15
16
|
}
|
|
16
17
|
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
18
|
export declare class KnexSchemaBuilder {
|
|
42
19
|
private knex;
|
|
43
|
-
verifyStructureOfAllEntities(remult
|
|
20
|
+
verifyStructureOfAllEntities(remult?: Remult): Promise<void>;
|
|
21
|
+
ensureSchema(entities: EntityMetadata<any>[]): Promise<void>;
|
|
44
22
|
createIfNotExist(entity: EntityMetadata): Promise<void>;
|
|
45
23
|
addColumnIfNotExist<T extends EntityMetadata>(entity: T, c: ((e: T) => FieldMetadata)): Promise<void>;
|
|
46
24
|
verifyAllColumns<T extends EntityMetadata>(entity: T): Promise<void>;
|
|
@@ -48,4 +26,4 @@ export declare class KnexSchemaBuilder {
|
|
|
48
26
|
constructor(knex: Knex);
|
|
49
27
|
}
|
|
50
28
|
export declare function buildColumn(x: FieldMetadata, dbName: string, b: Knex.CreateTableBuilder): void;
|
|
51
|
-
export declare function createKnexDataProvider(config: Knex.Config
|
|
29
|
+
export declare function createKnexDataProvider(config: Knex.Config): Promise<KnexDataProvider>;
|
package/esm/remult-knex/index.js
CHANGED
|
@@ -1,15 +1,21 @@
|
|
|
1
|
-
import knex from 'knex';
|
|
2
1
|
import { customDatabaseFilterToken, Filter } from "../src/filter/filter-interfaces";
|
|
3
|
-
import {
|
|
4
|
-
import { allEntities
|
|
5
|
-
import { isAutoIncrement } from "../src/remult3";
|
|
2
|
+
import { dbNamesOf, isDbReadonly } from "../src/filter/filter-consumer-bridge-to-sql-request";
|
|
3
|
+
import { allEntities } from "../src/context";
|
|
4
|
+
import { isAutoIncrement, getRepository } from "../src/remult3";
|
|
6
5
|
import { ValueConverters } from "../src/valueConverters";
|
|
7
6
|
import { CompoundIdField } from '../src/column';
|
|
8
7
|
import { Sort } from '../src/sort';
|
|
8
|
+
import { remult as remultContext, RemultProxy } from '../src/remult-proxy';
|
|
9
9
|
export class KnexDataProvider {
|
|
10
10
|
constructor(knex) {
|
|
11
11
|
this.knex = knex;
|
|
12
12
|
}
|
|
13
|
+
static getDb(remult) {
|
|
14
|
+
const r = (remult || remultContext).dataProvider;
|
|
15
|
+
if (!r.knex)
|
|
16
|
+
throw "the data provider is not an KnexDataProvider";
|
|
17
|
+
return r.knex;
|
|
18
|
+
}
|
|
13
19
|
getEntityDataProvider(entity) {
|
|
14
20
|
return new KnexEntityDataProvider(entity, this.knex);
|
|
15
21
|
}
|
|
@@ -24,13 +30,25 @@ export class KnexDataProvider {
|
|
|
24
30
|
throw err;
|
|
25
31
|
}
|
|
26
32
|
}
|
|
27
|
-
static
|
|
33
|
+
static rawFilter(build) {
|
|
28
34
|
return {
|
|
29
35
|
[customDatabaseFilterToken]: {
|
|
30
36
|
buildKnex: build
|
|
31
37
|
}
|
|
32
38
|
};
|
|
33
39
|
}
|
|
40
|
+
static async filterToRaw(entity, condition) {
|
|
41
|
+
const repo = getRepository(entity);
|
|
42
|
+
var b = new FilterConsumerBridgeToKnexRequest(await dbNamesOf(repo.metadata));
|
|
43
|
+
b._addWhere = false;
|
|
44
|
+
await (await (repo.translateWhereToFilter(condition))).__applyToConsumer(b);
|
|
45
|
+
let r = await b.resolveWhere();
|
|
46
|
+
return knex => r.forEach(y => y(knex));
|
|
47
|
+
}
|
|
48
|
+
async ensureSchema(entities) {
|
|
49
|
+
var sb = new KnexSchemaBuilder(this.knex);
|
|
50
|
+
await sb.ensureSchema(entities);
|
|
51
|
+
}
|
|
34
52
|
}
|
|
35
53
|
class KnexEntityDataProvider {
|
|
36
54
|
constructor(entity, knex) {
|
|
@@ -42,7 +60,7 @@ class KnexEntityDataProvider {
|
|
|
42
60
|
const br = new FilterConsumerBridgeToKnexRequest(e);
|
|
43
61
|
where.__applyToConsumer(br);
|
|
44
62
|
let r = await br.resolveWhere();
|
|
45
|
-
const result = (await this.knex(e
|
|
63
|
+
const result = (await this.knex(e.$entityName)
|
|
46
64
|
.count().where(b => r.forEach(w => w(b))));
|
|
47
65
|
var row = result[0];
|
|
48
66
|
for (const key in row) {
|
|
@@ -60,11 +78,11 @@ class KnexEntityDataProvider {
|
|
|
60
78
|
if (x.isServerExpression) {
|
|
61
79
|
}
|
|
62
80
|
else {
|
|
63
|
-
cols.push(e
|
|
81
|
+
cols.push(e.$dbNameOf(x));
|
|
64
82
|
colKeys.push(x);
|
|
65
83
|
}
|
|
66
84
|
}
|
|
67
|
-
let query = this.knex(e
|
|
85
|
+
let query = this.knex(e.$entityName).select(cols);
|
|
68
86
|
if (options?.where) {
|
|
69
87
|
const br = new FilterConsumerBridgeToKnexRequest(e);
|
|
70
88
|
options.where.__applyToConsumer(br);
|
|
@@ -76,7 +94,7 @@ class KnexEntityDataProvider {
|
|
|
76
94
|
}
|
|
77
95
|
if (options.orderBy) {
|
|
78
96
|
query = query.orderBy(options.orderBy.Segments.map(s => ({
|
|
79
|
-
column: e
|
|
97
|
+
column: e.$dbNameOf(s.field),
|
|
80
98
|
order: s.isDescending ? "desc" : "asc"
|
|
81
99
|
})));
|
|
82
100
|
}
|
|
@@ -102,7 +120,7 @@ class KnexEntityDataProvider {
|
|
|
102
120
|
});
|
|
103
121
|
}
|
|
104
122
|
async init() {
|
|
105
|
-
return await
|
|
123
|
+
return await dbNamesOf(this.entity);
|
|
106
124
|
}
|
|
107
125
|
async update(id, data) {
|
|
108
126
|
const e = await this.init();
|
|
@@ -113,17 +131,17 @@ class KnexEntityDataProvider {
|
|
|
113
131
|
resultFilter = this.entity.idMetadata.getIdFilter(data.id);
|
|
114
132
|
let updateObject = {};
|
|
115
133
|
for (const x of this.entity.fields) {
|
|
116
|
-
if (
|
|
134
|
+
if (isDbReadonly(x, e)) { }
|
|
117
135
|
else if (data[x.key] !== undefined) {
|
|
118
136
|
let v = x.valueConverter.toDb(data[x.key]);
|
|
119
137
|
if (v !== undefined) {
|
|
120
|
-
let key = await e
|
|
138
|
+
let key = await e.$dbNameOf(x);
|
|
121
139
|
updateObject[key] = v;
|
|
122
140
|
}
|
|
123
141
|
}
|
|
124
142
|
}
|
|
125
143
|
let where = await f.resolveWhere();
|
|
126
|
-
await this.knex(e
|
|
144
|
+
await this.knex(e.$entityName).update(updateObject).where(b => where.forEach(w => w(b)));
|
|
127
145
|
return this.find({ where: Filter.fromEntityFilter(this.entity, resultFilter) }).then(y => y[0]);
|
|
128
146
|
}
|
|
129
147
|
async delete(id) {
|
|
@@ -131,7 +149,7 @@ class KnexEntityDataProvider {
|
|
|
131
149
|
let f = new FilterConsumerBridgeToKnexRequest(e);
|
|
132
150
|
Filter.fromEntityFilter(this.entity, this.entity.idMetadata.getIdFilter(id)).__applyToConsumer(f);
|
|
133
151
|
let where = await f.resolveWhere();
|
|
134
|
-
await this.knex(e
|
|
152
|
+
await this.knex(e.$entityName).delete().where(b => where.forEach(w => w(b)));
|
|
135
153
|
}
|
|
136
154
|
async insert(data) {
|
|
137
155
|
const e = await this.init();
|
|
@@ -142,16 +160,16 @@ class KnexEntityDataProvider {
|
|
|
142
160
|
resultFilter = Filter.fromEntityFilter(this.entity, this.entity.idMetadata.getIdFilter(data[this.entity.idMetadata.field.key]));
|
|
143
161
|
let insertObject = {};
|
|
144
162
|
for (const x of this.entity.fields) {
|
|
145
|
-
if (
|
|
163
|
+
if (isDbReadonly(x, e)) { }
|
|
146
164
|
else {
|
|
147
165
|
let v = x.valueConverter.toDb(data[x.key]);
|
|
148
166
|
if (v != undefined) {
|
|
149
|
-
let key = await e
|
|
167
|
+
let key = await e.$dbNameOf(x);
|
|
150
168
|
insertObject[key] = v;
|
|
151
169
|
}
|
|
152
170
|
}
|
|
153
171
|
}
|
|
154
|
-
let insert = this.knex(e
|
|
172
|
+
let insert = this.knex(e.$entityName).insert(insertObject);
|
|
155
173
|
if (isAutoIncrement(this.entity.idMetadata.field)) {
|
|
156
174
|
let newId;
|
|
157
175
|
if (this.knex.client.config.client === 'mysql2') {
|
|
@@ -171,7 +189,7 @@ class KnexEntityDataProvider {
|
|
|
171
189
|
});
|
|
172
190
|
}
|
|
173
191
|
}
|
|
174
|
-
|
|
192
|
+
class FilterConsumerBridgeToKnexRequest {
|
|
175
193
|
constructor(nameProvider) {
|
|
176
194
|
this.nameProvider = nameProvider;
|
|
177
195
|
this._addWhere = true;
|
|
@@ -215,13 +233,13 @@ export class FilterConsumerBridgeToKnexRequest {
|
|
|
215
233
|
})());
|
|
216
234
|
}
|
|
217
235
|
isNull(col) {
|
|
218
|
-
this.result.push(b => b.whereNull(this.nameProvider
|
|
236
|
+
this.result.push(b => b.whereNull(this.nameProvider.$dbNameOf(col)));
|
|
219
237
|
}
|
|
220
238
|
isNotNull(col) {
|
|
221
|
-
this.result.push(b => b.whereNotNull(this.nameProvider
|
|
239
|
+
this.result.push(b => b.whereNotNull(this.nameProvider.$dbNameOf(col)));
|
|
222
240
|
}
|
|
223
241
|
isIn(col, val) {
|
|
224
|
-
this.result.push(knex => knex.whereIn(this.nameProvider
|
|
242
|
+
this.result.push(knex => knex.whereIn(this.nameProvider.$dbNameOf(col), val.map(x => col.valueConverter.toDb(x))));
|
|
225
243
|
}
|
|
226
244
|
isEqualTo(col, val) {
|
|
227
245
|
this.add(col, val, "=");
|
|
@@ -242,12 +260,12 @@ export class FilterConsumerBridgeToKnexRequest {
|
|
|
242
260
|
this.add(col, val, "<");
|
|
243
261
|
}
|
|
244
262
|
containsCaseInsensitive(col, val) {
|
|
245
|
-
this.result.push(b => b.whereRaw('lower (' + this.nameProvider
|
|
263
|
+
this.result.push(b => b.whereRaw('lower (' + this.nameProvider.$dbNameOf(col) + ") like lower ('%" + val.replace(/'/g, '\'\'') + "%')"));
|
|
246
264
|
this.promises.push((async () => {
|
|
247
265
|
})());
|
|
248
266
|
}
|
|
249
267
|
add(col, val, operator) {
|
|
250
|
-
this.result.push(b => b.where(this.nameProvider
|
|
268
|
+
this.result.push(b => b.where(this.nameProvider.$dbNameOf(col), operator, col.valueConverter.toDb(val)));
|
|
251
269
|
}
|
|
252
270
|
databaseCustom(databaseCustom) {
|
|
253
271
|
this.promises.push((async () => {
|
|
@@ -263,33 +281,38 @@ export class KnexSchemaBuilder {
|
|
|
263
281
|
this.additionalWhere = '';
|
|
264
282
|
}
|
|
265
283
|
async verifyStructureOfAllEntities(remult) {
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
284
|
+
if (!remult)
|
|
285
|
+
remult = RemultProxy.defaultRemult;
|
|
286
|
+
const entities = allEntities.map(x => remult.repo(x).metadata);
|
|
287
|
+
this.ensureSchema(entities);
|
|
288
|
+
}
|
|
289
|
+
async ensureSchema(entities) {
|
|
290
|
+
for (const entity of entities) {
|
|
291
|
+
let e = await dbNamesOf(entity);
|
|
269
292
|
try {
|
|
270
|
-
if (!
|
|
271
|
-
if (
|
|
272
|
-
await this.createIfNotExist(
|
|
273
|
-
await this.verifyAllColumns(
|
|
293
|
+
if (!entity.options.sqlExpression) {
|
|
294
|
+
if (e.$entityName.toLowerCase().indexOf('from ') < 0) {
|
|
295
|
+
await this.createIfNotExist(entity);
|
|
296
|
+
await this.verifyAllColumns(entity);
|
|
274
297
|
}
|
|
275
298
|
}
|
|
276
299
|
}
|
|
277
300
|
catch (err) {
|
|
278
|
-
console.
|
|
301
|
+
console.error("failed ensure schema of " + e.$entityName + " ", err);
|
|
279
302
|
}
|
|
280
303
|
}
|
|
281
304
|
}
|
|
282
305
|
async createIfNotExist(entity) {
|
|
283
|
-
const e = await
|
|
284
|
-
if (!await this.knex.schema.hasTable(e
|
|
306
|
+
const e = await dbNamesOf(entity);
|
|
307
|
+
if (!await this.knex.schema.hasTable(e.$entityName)) {
|
|
285
308
|
let cols = new Map();
|
|
286
309
|
for (const f of entity.fields) {
|
|
287
310
|
cols.set(f, {
|
|
288
|
-
name: e
|
|
289
|
-
readonly:
|
|
311
|
+
name: e.$dbNameOf(f),
|
|
312
|
+
readonly: isDbReadonly(f, e)
|
|
290
313
|
});
|
|
291
314
|
}
|
|
292
|
-
await logSql(this.knex.schema.createTable(e
|
|
315
|
+
await logSql(this.knex.schema.createTable(e.$entityName, b => {
|
|
293
316
|
for (const x of entity.fields) {
|
|
294
317
|
if (!cols.get(x).readonly || isAutoIncrement(x)) {
|
|
295
318
|
if (isAutoIncrement(x))
|
|
@@ -305,31 +328,33 @@ export class KnexSchemaBuilder {
|
|
|
305
328
|
}
|
|
306
329
|
}
|
|
307
330
|
async addColumnIfNotExist(entity, c) {
|
|
308
|
-
let e = await
|
|
309
|
-
if (
|
|
331
|
+
let e = await dbNamesOf(entity);
|
|
332
|
+
if (isDbReadonly(c(entity), e))
|
|
310
333
|
return;
|
|
311
334
|
let col = c(entity);
|
|
312
|
-
let colName = e
|
|
313
|
-
if (!await this.knex.schema.hasColumn(e
|
|
314
|
-
await this.knex.schema.alterTable(e
|
|
335
|
+
let colName = e.$dbNameOf(col);
|
|
336
|
+
if (!await this.knex.schema.hasColumn(e.$entityName, colName)) {
|
|
337
|
+
await logSql(this.knex.schema.alterTable(e.$entityName, b => {
|
|
315
338
|
buildColumn(col, colName, b);
|
|
316
|
-
});
|
|
339
|
+
}));
|
|
317
340
|
}
|
|
318
341
|
}
|
|
319
342
|
async verifyAllColumns(entity) {
|
|
320
|
-
let e = await
|
|
343
|
+
let e = await dbNamesOf(entity);
|
|
321
344
|
try {
|
|
322
|
-
for (const col of entity.fields) {
|
|
323
|
-
if (!
|
|
345
|
+
for (const col of entity.fields.toArray()) {
|
|
346
|
+
if (!isDbReadonly(col, e)) {
|
|
324
347
|
await this.addColumnIfNotExist(entity, () => col);
|
|
325
348
|
}
|
|
326
349
|
}
|
|
327
350
|
}
|
|
328
351
|
catch (err) {
|
|
329
|
-
console.
|
|
352
|
+
console.error(err);
|
|
330
353
|
}
|
|
331
354
|
}
|
|
332
355
|
}
|
|
356
|
+
//@internal
|
|
357
|
+
KnexSchemaBuilder.logToConsole = true;
|
|
333
358
|
export function buildColumn(x, dbName, b) {
|
|
334
359
|
if (x.valueType == Number) {
|
|
335
360
|
if (!x.valueConverter.fieldTypeInDb) {
|
|
@@ -380,13 +405,12 @@ export function buildColumn(x, dbName, b) {
|
|
|
380
405
|
}
|
|
381
406
|
}
|
|
382
407
|
function logSql(who) {
|
|
383
|
-
|
|
408
|
+
if (KnexSchemaBuilder.logToConsole)
|
|
409
|
+
console.info(who.toSQL());
|
|
384
410
|
return who;
|
|
385
411
|
}
|
|
386
|
-
export async function createKnexDataProvider(config
|
|
387
|
-
let k = knex(config);
|
|
412
|
+
export async function createKnexDataProvider(config) {
|
|
413
|
+
let k = (await import('knex')).default(config);
|
|
388
414
|
let result = new KnexDataProvider(k);
|
|
389
|
-
if (autoCreateTables)
|
|
390
|
-
await new KnexSchemaBuilder(k).verifyStructureOfAllEntities(new Remult(result));
|
|
391
415
|
return result;
|
|
392
416
|
}
|
package/esm/remult-mongo.d.ts
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
|
-
import { MongoClient, Db } from 'mongodb';
|
|
2
|
-
import { DataProvider, EntityDataProvider, EntityMetadata } from '.';
|
|
1
|
+
import type { MongoClient, Db } from 'mongodb';
|
|
2
|
+
import { DataProvider, EntityDataProvider, EntityFilter, EntityMetadata, Remult } from '.';
|
|
3
|
+
import { RepositoryOverloads } from './src/remult3';
|
|
3
4
|
export declare class MongoDataProvider implements DataProvider {
|
|
4
5
|
private db;
|
|
5
6
|
private client;
|
|
6
7
|
constructor(db: Db, client: MongoClient);
|
|
8
|
+
static getDb(remult?: Remult): Db;
|
|
7
9
|
getEntityDataProvider(entity: EntityMetadata<any>): EntityDataProvider;
|
|
8
10
|
transaction(action: (dataProvider: DataProvider) => Promise<void>): Promise<void>;
|
|
11
|
+
static filterToRaw<entityType>(entity: RepositoryOverloads<entityType>, condition: EntityFilter<entityType>): Promise<{
|
|
12
|
+
$and: any[];
|
|
13
|
+
} | {
|
|
14
|
+
$and?: undefined;
|
|
15
|
+
}>;
|
|
9
16
|
}
|
package/esm/remult-mongo.js
CHANGED
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
import { CompoundIdField, Filter } from '.';
|
|
2
|
-
import {
|
|
2
|
+
import { dbNamesOf } from './src/filter/filter-consumer-bridge-to-sql-request';
|
|
3
|
+
import { getRepository } from './src/remult3';
|
|
4
|
+
import { remult as remultContext } from './src/remult-proxy';
|
|
3
5
|
export class MongoDataProvider {
|
|
4
6
|
constructor(db, client) {
|
|
5
7
|
this.db = db;
|
|
6
8
|
this.client = client;
|
|
7
9
|
}
|
|
10
|
+
static getDb(remult) {
|
|
11
|
+
const r = (remult || remultContext).dataProvider;
|
|
12
|
+
if (!r.db)
|
|
13
|
+
throw "the data provider is not a MongoDataProvider";
|
|
14
|
+
return r.db;
|
|
15
|
+
}
|
|
8
16
|
getEntityDataProvider(entity) {
|
|
9
17
|
return new MongoEntityDataProvider(this.db, entity);
|
|
10
18
|
}
|
|
@@ -20,6 +28,14 @@ export class MongoDataProvider {
|
|
|
20
28
|
throw err;
|
|
21
29
|
}
|
|
22
30
|
}
|
|
31
|
+
static async filterToRaw(entity, condition) {
|
|
32
|
+
const repo = getRepository(entity);
|
|
33
|
+
var b = new FilterConsumerBridgeToMongo(await dbNamesOf(repo.metadata));
|
|
34
|
+
b._addWhere = false;
|
|
35
|
+
await (await (repo.translateWhereToFilter(condition))).__applyToConsumer(b);
|
|
36
|
+
let r = await b.resolveWhere();
|
|
37
|
+
return r;
|
|
38
|
+
}
|
|
23
39
|
}
|
|
24
40
|
const NULL = { $null: "$null" };
|
|
25
41
|
function isNull(x) {
|
|
@@ -33,7 +49,7 @@ class MongoEntityDataProvider {
|
|
|
33
49
|
translateFromJson(row, nameProvider) {
|
|
34
50
|
let result = {};
|
|
35
51
|
for (const col of this.entity.fields) {
|
|
36
|
-
let val = row[nameProvider
|
|
52
|
+
let val = row[nameProvider.$dbNameOf(col)];
|
|
37
53
|
if (isNull(val))
|
|
38
54
|
val = null;
|
|
39
55
|
result[col.key] = col.valueConverter.fromDb(val);
|
|
@@ -46,7 +62,7 @@ class MongoEntityDataProvider {
|
|
|
46
62
|
let val = col.valueConverter.toDb(row[col.key]);
|
|
47
63
|
if (val === null)
|
|
48
64
|
val = NULL;
|
|
49
|
-
result[nameProvider
|
|
65
|
+
result[nameProvider.$dbNameOf(col)] = val;
|
|
50
66
|
}
|
|
51
67
|
return result;
|
|
52
68
|
}
|
|
@@ -73,7 +89,7 @@ class MongoEntityDataProvider {
|
|
|
73
89
|
if (options.orderBy) {
|
|
74
90
|
op.sort = {};
|
|
75
91
|
for (const s of options.orderBy.Segments) {
|
|
76
|
-
op.sort[e
|
|
92
|
+
op.sort[e.$dbNameOf(s.field)] = s.isDescending ? -1 : 1;
|
|
77
93
|
}
|
|
78
94
|
}
|
|
79
95
|
return await Promise.all(await collection.find(where, op).map(x => this.translateFromJson(x, e)).toArray());
|
|
@@ -116,8 +132,8 @@ class MongoEntityDataProvider {
|
|
|
116
132
|
return await this.translateFromJson(await collection.findOne({ _id: r.insertedId }), e);
|
|
117
133
|
}
|
|
118
134
|
async collection() {
|
|
119
|
-
const e = await
|
|
120
|
-
const collection = this.db.collection(e
|
|
135
|
+
const e = await dbNamesOf(this.entity);
|
|
136
|
+
const collection = this.db.collection(e.$entityName);
|
|
121
137
|
return { e, collection };
|
|
122
138
|
}
|
|
123
139
|
}
|
|
@@ -171,7 +187,7 @@ class FilterConsumerBridgeToMongo {
|
|
|
171
187
|
}
|
|
172
188
|
isIn(col, val) {
|
|
173
189
|
this.result.push(() => ({
|
|
174
|
-
[this.nameProvider
|
|
190
|
+
[this.nameProvider.$dbNameOf(col)]: {
|
|
175
191
|
$in: val.map(x => col.valueConverter.toDb(x))
|
|
176
192
|
}
|
|
177
193
|
}));
|
|
@@ -203,7 +219,7 @@ class FilterConsumerBridgeToMongo {
|
|
|
203
219
|
}
|
|
204
220
|
add(col, val, operator) {
|
|
205
221
|
this.result.push(() => ({
|
|
206
|
-
[this.nameProvider
|
|
222
|
+
[this.nameProvider.$dbNameOf(col)]: { [operator]: isNull(val) ? val : col.valueConverter.toDb(val) }
|
|
207
223
|
}));
|
|
208
224
|
}
|
|
209
225
|
databaseCustom(databaseCustom) {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import type { GetServerSideProps, NextApiRequest, PreviewData, NextApiHandler } from "next";
|
|
3
|
+
import type { ParsedUrlQuery } from "querystring";
|
|
4
|
+
import { RemultServer, RemultServerOptions } from "./server";
|
|
5
|
+
export declare function remultNext(options?: RemultServerOptions<NextApiRequest>): RemultServer & NextApiHandler & {
|
|
6
|
+
getServerSideProps<P extends {
|
|
7
|
+
[key: string]: any;
|
|
8
|
+
} = {
|
|
9
|
+
[key: string]: any;
|
|
10
|
+
}, Q extends ParsedUrlQuery = ParsedUrlQuery, D extends PreviewData = PreviewData>(getServerPropsFunction: GetServerSideProps<P, Q, D>): GetServerSideProps<P, Q, D>;
|
|
11
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { createRemultServer } from "./server";
|
|
2
|
+
export function remultNext(options) {
|
|
3
|
+
let result = createRemultServer(options);
|
|
4
|
+
return Object.assign((req, res) => result.handle(req, res), result, {
|
|
5
|
+
getRemult: (...args) => result.getRemult(...args),
|
|
6
|
+
handle: (...args) => result.handle(...args),
|
|
7
|
+
openApiDoc: (...args) => result.openApiDoc(...args),
|
|
8
|
+
registerRouter: (...args) => result.registerRouter(...args),
|
|
9
|
+
withRemult: (...args) => result.withRemult(...args),
|
|
10
|
+
}, {
|
|
11
|
+
getServerSideProps: (getServerPropsFunction) => {
|
|
12
|
+
return (context) => {
|
|
13
|
+
return new Promise((res, err) => {
|
|
14
|
+
result.withRemult(context, undefined, async () => {
|
|
15
|
+
try {
|
|
16
|
+
let r = await getServerPropsFunction(context);
|
|
17
|
+
res(JSON.parse(JSON.stringify(r)));
|
|
18
|
+
}
|
|
19
|
+
catch (e) {
|
|
20
|
+
err(e);
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
}
|