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.
- package/README.md +28 -5
- package/esm/index.d.ts +4 -3
- package/esm/index.js +4 -2
- 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.d.ts +1 -1
- package/esm/postgres/schema-builder.js +43 -27
- package/esm/remult-express.d.ts +4 -22
- package/esm/remult-express.js +30 -28
- package/esm/remult-fastify.js +1 -1
- package/esm/remult-fresh.js +2 -2
- package/esm/remult-knex/index.d.ts +7 -31
- package/esm/remult-knex/index.js +71 -42
- 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/expressBridge.d.ts +20 -52
- package/esm/server/expressBridge.js +55 -29
- package/esm/server/index.d.ts +3 -1
- package/esm/server/index.js +6 -1
- package/esm/src/column-interfaces.d.ts +44 -8
- package/esm/src/context.d.ts +31 -19
- package/esm/src/context.js +35 -42
- package/esm/src/data-api.js +17 -4
- 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 +38 -23
- package/esm/src/data-providers/sql-database.d.ts +6 -3
- package/esm/src/data-providers/sql-database.js +57 -16
- package/esm/src/data-providers/web-sql-data-provider.d.ts +2 -0
- package/esm/src/data-providers/web-sql-data-provider.js +17 -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 +31 -26
- package/esm/src/live-query/LiveQueryClient.d.ts +1 -19
- package/esm/src/live-query/LiveQueryClient.js +81 -50
- package/esm/src/live-query/SseSubscriptionClient.d.ts +4 -0
- package/esm/src/live-query/{EventSourceLiveQueryProvider.js → SseSubscriptionClient.js} +7 -6
- package/esm/src/live-query/SubscriptionChannel.d.ts +41 -0
- package/esm/src/live-query/{LiveQuerySubscriber.js → SubscriptionChannel.js} +40 -22
- package/esm/src/live-query/SubscriptionServer.d.ts +38 -0
- package/esm/src/live-query/{LiveQueryPublisher.js → SubscriptionServer.js} +60 -73
- package/esm/src/remult-proxy.js +44 -1
- package/esm/src/remult3/RepositoryImplementation.d.ts +8 -2
- package/esm/src/remult3/RepositoryImplementation.js +94 -30
- package/esm/src/remult3/remult3.d.ts +59 -6
- package/esm/src/remult3/remult3.js +1 -0
- package/esm/src/server-action.d.ts +1 -1
- 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 +55 -9
- 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 +2 -2
- package/esm/src/tests/testHelper.spec.js +1 -2
- package/esm/src/valueConverters.js +17 -7
- package/index.d.ts +4 -3
- package/index.js +7 -3
- package/live-query/ably.d.ts +6 -6
- package/live-query/ably.js +12 -12
- package/package.json +18 -9
- package/postgres/postgres-data-provider.d.ts +3 -1
- package/postgres/postgres-data-provider.js +13 -3
- package/postgres/schema-builder.d.ts +1 -1
- package/postgres/schema-builder.js +64 -50
- package/remult-express.d.ts +4 -22
- package/remult-express.js +39 -47
- package/remult-fastify.js +2 -2
- package/remult-fresh.js +1 -1
- package/remult-knex/index.d.ts +7 -31
- package/remult-knex/index.js +100 -53
- 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/expressBridge.d.ts +20 -52
- package/server/expressBridge.js +68 -41
- package/server/index.d.ts +3 -1
- package/server/index.js +7 -2
- package/src/column-interfaces.d.ts +44 -8
- package/src/context.d.ts +31 -19
- package/src/context.js +39 -50
- package/src/data-api.js +18 -5
- 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 +48 -24
- package/src/data-providers/sql-database.d.ts +6 -3
- package/src/data-providers/sql-database.js +75 -15
- package/src/data-providers/web-sql-data-provider.d.ts +2 -0
- package/src/data-providers/web-sql-data-provider.js +16 -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 +31 -26
- package/src/live-query/LiveQueryClient.d.ts +1 -19
- package/src/live-query/LiveQueryClient.js +117 -64
- package/src/live-query/SseSubscriptionClient.d.ts +4 -0
- package/src/live-query/{EventSourceLiveQueryProvider.js → SseSubscriptionClient.js} +13 -12
- package/src/live-query/SubscriptionChannel.d.ts +41 -0
- package/src/live-query/{LiveQuerySubscriber.js → SubscriptionChannel.js} +51 -47
- package/src/live-query/SubscriptionServer.d.ts +38 -0
- package/src/live-query/SubscriptionServer.js +237 -0
- package/src/remult-proxy.js +137 -2
- package/src/remult3/RepositoryImplementation.d.ts +8 -2
- package/src/remult3/RepositoryImplementation.js +121 -34
- package/src/remult3/remult3.d.ts +59 -6
- package/src/remult3/remult3.js +1 -0
- package/src/server-action.d.ts +1 -1
- 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 +101 -8
- 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 +2 -2
- package/src/tests/testHelper.spec.js +4 -5
- package/src/valueConverters.js +17 -7
- 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/backend-tests/backend-database-test-setup.backend-spec.d.ts +0 -5
- package/src/backend-tests/backend-database-test-setup.backend-spec.js +0 -231
- package/src/backend-tests/my-test.backend-spec.d.ts +0 -1
- package/src/backend-tests/my-test.backend-spec.js +0 -160
- package/src/backend-tests/test-http-server.backend-spec.d.ts +0 -6
- package/src/backend-tests/test-http-server.backend-spec.js +0 -342
- package/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/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 {
|
|
2
|
+
import { dbNamesOf, isDbReadonly } from "../src/filter/filter-consumer-bridge-to-sql-request";
|
|
4
3
|
import { allEntities, Remult } from "../src/context";
|
|
5
|
-
import { isAutoIncrement } from "../src/remult3";
|
|
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,21 @@ 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
|
+
}
|
|
34
48
|
}
|
|
35
49
|
class KnexEntityDataProvider {
|
|
36
50
|
constructor(entity, knex) {
|
|
@@ -42,7 +56,7 @@ class KnexEntityDataProvider {
|
|
|
42
56
|
const br = new FilterConsumerBridgeToKnexRequest(e);
|
|
43
57
|
where.__applyToConsumer(br);
|
|
44
58
|
let r = await br.resolveWhere();
|
|
45
|
-
const result = (await this.knex(e
|
|
59
|
+
const result = (await this.knex(e.$entityName)
|
|
46
60
|
.count().where(b => r.forEach(w => w(b))));
|
|
47
61
|
var row = result[0];
|
|
48
62
|
for (const key in row) {
|
|
@@ -60,11 +74,11 @@ class KnexEntityDataProvider {
|
|
|
60
74
|
if (x.isServerExpression) {
|
|
61
75
|
}
|
|
62
76
|
else {
|
|
63
|
-
cols.push(e
|
|
77
|
+
cols.push(e.$dbNameOf(x));
|
|
64
78
|
colKeys.push(x);
|
|
65
79
|
}
|
|
66
80
|
}
|
|
67
|
-
let query = this.knex(e
|
|
81
|
+
let query = this.knex(e.$entityName).select(cols);
|
|
68
82
|
if (options?.where) {
|
|
69
83
|
const br = new FilterConsumerBridgeToKnexRequest(e);
|
|
70
84
|
options.where.__applyToConsumer(br);
|
|
@@ -76,7 +90,7 @@ class KnexEntityDataProvider {
|
|
|
76
90
|
}
|
|
77
91
|
if (options.orderBy) {
|
|
78
92
|
query = query.orderBy(options.orderBy.Segments.map(s => ({
|
|
79
|
-
column: e
|
|
93
|
+
column: e.$dbNameOf(s.field),
|
|
80
94
|
order: s.isDescending ? "desc" : "asc"
|
|
81
95
|
})));
|
|
82
96
|
}
|
|
@@ -102,7 +116,7 @@ class KnexEntityDataProvider {
|
|
|
102
116
|
});
|
|
103
117
|
}
|
|
104
118
|
async init() {
|
|
105
|
-
return await
|
|
119
|
+
return await dbNamesOf(this.entity);
|
|
106
120
|
}
|
|
107
121
|
async update(id, data) {
|
|
108
122
|
const e = await this.init();
|
|
@@ -113,17 +127,17 @@ class KnexEntityDataProvider {
|
|
|
113
127
|
resultFilter = this.entity.idMetadata.getIdFilter(data.id);
|
|
114
128
|
let updateObject = {};
|
|
115
129
|
for (const x of this.entity.fields) {
|
|
116
|
-
if (
|
|
130
|
+
if (isDbReadonly(x, e)) { }
|
|
117
131
|
else if (data[x.key] !== undefined) {
|
|
118
132
|
let v = x.valueConverter.toDb(data[x.key]);
|
|
119
133
|
if (v !== undefined) {
|
|
120
|
-
let key = await e
|
|
134
|
+
let key = await e.$dbNameOf(x);
|
|
121
135
|
updateObject[key] = v;
|
|
122
136
|
}
|
|
123
137
|
}
|
|
124
138
|
}
|
|
125
139
|
let where = await f.resolveWhere();
|
|
126
|
-
await this.knex(e
|
|
140
|
+
await this.knex(e.$entityName).update(updateObject).where(b => where.forEach(w => w(b)));
|
|
127
141
|
return this.find({ where: Filter.fromEntityFilter(this.entity, resultFilter) }).then(y => y[0]);
|
|
128
142
|
}
|
|
129
143
|
async delete(id) {
|
|
@@ -131,7 +145,7 @@ class KnexEntityDataProvider {
|
|
|
131
145
|
let f = new FilterConsumerBridgeToKnexRequest(e);
|
|
132
146
|
Filter.fromEntityFilter(this.entity, this.entity.idMetadata.getIdFilter(id)).__applyToConsumer(f);
|
|
133
147
|
let where = await f.resolveWhere();
|
|
134
|
-
await this.knex(e
|
|
148
|
+
await this.knex(e.$entityName).delete().where(b => where.forEach(w => w(b)));
|
|
135
149
|
}
|
|
136
150
|
async insert(data) {
|
|
137
151
|
const e = await this.init();
|
|
@@ -142,19 +156,26 @@ class KnexEntityDataProvider {
|
|
|
142
156
|
resultFilter = Filter.fromEntityFilter(this.entity, this.entity.idMetadata.getIdFilter(data[this.entity.idMetadata.field.key]));
|
|
143
157
|
let insertObject = {};
|
|
144
158
|
for (const x of this.entity.fields) {
|
|
145
|
-
if (
|
|
159
|
+
if (isDbReadonly(x, e)) { }
|
|
146
160
|
else {
|
|
147
161
|
let v = x.valueConverter.toDb(data[x.key]);
|
|
148
162
|
if (v != undefined) {
|
|
149
|
-
let key = await e
|
|
163
|
+
let key = await e.$dbNameOf(x);
|
|
150
164
|
insertObject[key] = v;
|
|
151
165
|
}
|
|
152
166
|
}
|
|
153
167
|
}
|
|
154
|
-
let insert = this.knex(e
|
|
168
|
+
let insert = this.knex(e.$entityName).insert(insertObject);
|
|
155
169
|
if (isAutoIncrement(this.entity.idMetadata.field)) {
|
|
156
|
-
let
|
|
157
|
-
|
|
170
|
+
let newId;
|
|
171
|
+
if (this.knex.client.config.client === 'mysql2') {
|
|
172
|
+
let result = await insert;
|
|
173
|
+
newId = result[0];
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
let result = await insert.returning(this.entity.idMetadata.field.key);
|
|
177
|
+
newId = result[0].id;
|
|
178
|
+
}
|
|
158
179
|
resultFilter = new Filter(x => x.isEqualTo(this.entity.idMetadata.field, newId));
|
|
159
180
|
}
|
|
160
181
|
else
|
|
@@ -164,7 +185,7 @@ class KnexEntityDataProvider {
|
|
|
164
185
|
});
|
|
165
186
|
}
|
|
166
187
|
}
|
|
167
|
-
|
|
188
|
+
class FilterConsumerBridgeToKnexRequest {
|
|
168
189
|
constructor(nameProvider) {
|
|
169
190
|
this.nameProvider = nameProvider;
|
|
170
191
|
this._addWhere = true;
|
|
@@ -208,13 +229,13 @@ export class FilterConsumerBridgeToKnexRequest {
|
|
|
208
229
|
})());
|
|
209
230
|
}
|
|
210
231
|
isNull(col) {
|
|
211
|
-
this.result.push(b => b.whereNull(this.nameProvider
|
|
232
|
+
this.result.push(b => b.whereNull(this.nameProvider.$dbNameOf(col)));
|
|
212
233
|
}
|
|
213
234
|
isNotNull(col) {
|
|
214
|
-
this.result.push(b => b.whereNotNull(this.nameProvider
|
|
235
|
+
this.result.push(b => b.whereNotNull(this.nameProvider.$dbNameOf(col)));
|
|
215
236
|
}
|
|
216
237
|
isIn(col, val) {
|
|
217
|
-
this.result.push(knex => knex.whereIn(this.nameProvider
|
|
238
|
+
this.result.push(knex => knex.whereIn(this.nameProvider.$dbNameOf(col), val.map(x => col.valueConverter.toDb(x))));
|
|
218
239
|
}
|
|
219
240
|
isEqualTo(col, val) {
|
|
220
241
|
this.add(col, val, "=");
|
|
@@ -235,12 +256,12 @@ export class FilterConsumerBridgeToKnexRequest {
|
|
|
235
256
|
this.add(col, val, "<");
|
|
236
257
|
}
|
|
237
258
|
containsCaseInsensitive(col, val) {
|
|
238
|
-
this.result.push(b => b.whereRaw('lower (' + this.nameProvider
|
|
259
|
+
this.result.push(b => b.whereRaw('lower (' + this.nameProvider.$dbNameOf(col) + ") like lower ('%" + val.replace(/'/g, '\'\'') + "%')"));
|
|
239
260
|
this.promises.push((async () => {
|
|
240
261
|
})());
|
|
241
262
|
}
|
|
242
263
|
add(col, val, operator) {
|
|
243
|
-
this.result.push(b => b.where(this.nameProvider
|
|
264
|
+
this.result.push(b => b.where(this.nameProvider.$dbNameOf(col), operator, col.valueConverter.toDb(val)));
|
|
244
265
|
}
|
|
245
266
|
databaseCustom(databaseCustom) {
|
|
246
267
|
this.promises.push((async () => {
|
|
@@ -256,7 +277,10 @@ export class KnexSchemaBuilder {
|
|
|
256
277
|
this.additionalWhere = '';
|
|
257
278
|
}
|
|
258
279
|
async verifyStructureOfAllEntities(remult) {
|
|
259
|
-
|
|
280
|
+
if (!remult)
|
|
281
|
+
remult = RemultProxy.defaultRemult;
|
|
282
|
+
if (KnexSchemaBuilder.logToConsole)
|
|
283
|
+
console.time("Knex Auto create tables and columns");
|
|
260
284
|
for (const entity of allEntities) {
|
|
261
285
|
let metadata = remult.repo(entity).metadata;
|
|
262
286
|
try {
|
|
@@ -268,21 +292,23 @@ export class KnexSchemaBuilder {
|
|
|
268
292
|
}
|
|
269
293
|
}
|
|
270
294
|
catch (err) {
|
|
271
|
-
console.
|
|
295
|
+
console.error("failed verify structure of " + await metadata.getDbName() + " ", err);
|
|
272
296
|
}
|
|
273
297
|
}
|
|
298
|
+
if (KnexSchemaBuilder.logToConsole)
|
|
299
|
+
console.timeEnd("Knex Auto create tables and columns");
|
|
274
300
|
}
|
|
275
301
|
async createIfNotExist(entity) {
|
|
276
|
-
const e = await
|
|
277
|
-
if (!await this.knex.schema.hasTable(e
|
|
302
|
+
const e = await dbNamesOf(entity);
|
|
303
|
+
if (!await this.knex.schema.hasTable(e.$entityName)) {
|
|
278
304
|
let cols = new Map();
|
|
279
305
|
for (const f of entity.fields) {
|
|
280
306
|
cols.set(f, {
|
|
281
|
-
name: e
|
|
282
|
-
readonly:
|
|
307
|
+
name: e.$dbNameOf(f),
|
|
308
|
+
readonly: isDbReadonly(f, e)
|
|
283
309
|
});
|
|
284
310
|
}
|
|
285
|
-
await logSql(this.knex.schema.createTable(e
|
|
311
|
+
await logSql(this.knex.schema.createTable(e.$entityName, b => {
|
|
286
312
|
for (const x of entity.fields) {
|
|
287
313
|
if (!cols.get(x).readonly || isAutoIncrement(x)) {
|
|
288
314
|
if (isAutoIncrement(x))
|
|
@@ -298,22 +324,22 @@ export class KnexSchemaBuilder {
|
|
|
298
324
|
}
|
|
299
325
|
}
|
|
300
326
|
async addColumnIfNotExist(entity, c) {
|
|
301
|
-
let e = await
|
|
302
|
-
if (
|
|
327
|
+
let e = await dbNamesOf(entity);
|
|
328
|
+
if (isDbReadonly(c(entity), e))
|
|
303
329
|
return;
|
|
304
330
|
let col = c(entity);
|
|
305
|
-
let colName = e
|
|
306
|
-
if (!await this.knex.schema.hasColumn(e
|
|
307
|
-
await this.knex.schema.alterTable(e
|
|
331
|
+
let colName = e.$dbNameOf(col);
|
|
332
|
+
if (!await this.knex.schema.hasColumn(e.$entityName, colName)) {
|
|
333
|
+
await logSql(this.knex.schema.alterTable(e.$entityName, b => {
|
|
308
334
|
buildColumn(col, colName, b);
|
|
309
|
-
});
|
|
335
|
+
}));
|
|
310
336
|
}
|
|
311
337
|
}
|
|
312
338
|
async verifyAllColumns(entity) {
|
|
313
|
-
let e = await
|
|
339
|
+
let e = await dbNamesOf(entity);
|
|
314
340
|
try {
|
|
315
|
-
for (const col of entity.fields) {
|
|
316
|
-
if (!
|
|
341
|
+
for (const col of entity.fields.toArray()) {
|
|
342
|
+
if (!isDbReadonly(col, e)) {
|
|
317
343
|
await this.addColumnIfNotExist(entity, () => col);
|
|
318
344
|
}
|
|
319
345
|
}
|
|
@@ -323,6 +349,8 @@ export class KnexSchemaBuilder {
|
|
|
323
349
|
}
|
|
324
350
|
}
|
|
325
351
|
}
|
|
352
|
+
//@internal
|
|
353
|
+
KnexSchemaBuilder.logToConsole = true;
|
|
326
354
|
export function buildColumn(x, dbName, b) {
|
|
327
355
|
if (x.valueType == Number) {
|
|
328
356
|
if (!x.valueConverter.fieldTypeInDb) {
|
|
@@ -373,11 +401,12 @@ export function buildColumn(x, dbName, b) {
|
|
|
373
401
|
}
|
|
374
402
|
}
|
|
375
403
|
function logSql(who) {
|
|
376
|
-
|
|
404
|
+
if (KnexSchemaBuilder.logToConsole)
|
|
405
|
+
console.info(who.toSQL());
|
|
377
406
|
return who;
|
|
378
407
|
}
|
|
379
408
|
export async function createKnexDataProvider(config, autoCreateTables = true) {
|
|
380
|
-
let k = knex(config);
|
|
409
|
+
let k = (await import('knex')).default(config);
|
|
381
410
|
let result = new KnexDataProvider(k);
|
|
382
411
|
if (autoCreateTables)
|
|
383
412
|
await new KnexSchemaBuilder(k).verifyStructureOfAllEntities(new Remult(result));
|
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
|
+
}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { queuedJobInfoResponse } from '../src/server-action';
|
|
2
2
|
import { DataProvider } from '../src/data-interfaces';
|
|
3
|
-
import {
|
|
4
|
-
import { AllowedForInstance, Remult, UserInfo } from '../src/context';
|
|
3
|
+
import { Remult, UserInfo } from '../src/context';
|
|
5
4
|
import { ClassType } from '../classType';
|
|
6
5
|
import { Repository } from '../src/remult3';
|
|
7
6
|
import { IdEntity } from '../src/id-entity';
|
|
8
|
-
import {
|
|
7
|
+
import { LiveQueryStorage, SubscriptionServer } from '../src/live-query/SubscriptionServer';
|
|
9
8
|
export interface RemultServerOptions<RequestType extends GenericRequest> {
|
|
10
9
|
/** Sets a database connection for Remult.
|
|
11
10
|
*
|
|
@@ -13,12 +12,14 @@ export interface RemultServerOptions<RequestType extends GenericRequest> {
|
|
|
13
12
|
*/
|
|
14
13
|
dataProvider?: DataProvider | Promise<DataProvider> | (() => Promise<DataProvider | undefined>);
|
|
15
14
|
queueStorage?: QueueStorage;
|
|
16
|
-
|
|
15
|
+
liveQueryStorage?: LiveQueryStorage;
|
|
16
|
+
subscriptionServer?: SubscriptionServer;
|
|
17
|
+
initRequest?: (request: RequestType, options: InitRequestOptions) => Promise<void>;
|
|
17
18
|
requestSerializer?: {
|
|
18
19
|
toJson: (request: RequestType) => any;
|
|
19
20
|
fromJson: (request: any) => RequestType;
|
|
20
21
|
};
|
|
21
|
-
getUser?: (request: RequestType) => Promise<UserInfo>;
|
|
22
|
+
getUser?: (request: RequestType) => Promise<UserInfo | undefined>;
|
|
22
23
|
initApi?: (remult: Remult) => void | Promise<void>;
|
|
23
24
|
logApiEndPoints?: boolean;
|
|
24
25
|
defaultGetLimit?: number;
|
|
@@ -26,7 +27,11 @@ export interface RemultServerOptions<RequestType extends GenericRequest> {
|
|
|
26
27
|
controllers?: ClassType<any>[];
|
|
27
28
|
rootPath?: string;
|
|
28
29
|
}
|
|
29
|
-
export
|
|
30
|
+
export interface InitRequestOptions {
|
|
31
|
+
liveQueryStorage: LiveQueryStorage;
|
|
32
|
+
readonly remult: Remult;
|
|
33
|
+
}
|
|
34
|
+
export declare function createRemultServerCore<RequestType extends GenericRequest = GenericRequest>(options?: RemultServerOptions<RequestType>): RemultServer;
|
|
30
35
|
export declare type GenericRequestHandler = (req: GenericRequest, res: GenericResponse, next: VoidFunction) => void;
|
|
31
36
|
export interface ServerHandleResponse {
|
|
32
37
|
data?: any;
|
|
@@ -63,39 +68,14 @@ export interface GenericResponse {
|
|
|
63
68
|
status(statusCode: number): GenericResponse;
|
|
64
69
|
end(): any;
|
|
65
70
|
}
|
|
66
|
-
export declare class
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
constructor(
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
handle(req: GenericRequest, gRes?: GenericResponse): Promise<ServerHandleResponse>;
|
|
75
|
-
registeredRouter: boolean;
|
|
76
|
-
registerRouter(r: GenericRouter): void;
|
|
77
|
-
add(key: string, dataApiFactory: ((req: Remult) => DataApi), r: GenericRouter): void;
|
|
78
|
-
process(what: (remult: Remult, myReq: DataApiRequest, myRes: DataApiResponse, origReq: GenericRequest) => Promise<void>): (req: GenericRequest, res: GenericResponse) => Promise<void>;
|
|
79
|
-
getRemult(req: GenericRequest): Promise<Remult>;
|
|
80
|
-
hasQueue: boolean;
|
|
81
|
-
addAction(action: ActionInterface, r: GenericRouter): void;
|
|
82
|
-
openApiDoc(options: {
|
|
83
|
-
title: string;
|
|
84
|
-
version?: string;
|
|
85
|
-
}): any;
|
|
86
|
-
backendMethodsOpenApi: {
|
|
87
|
-
path: string;
|
|
88
|
-
allowed: AllowedForInstance<any>;
|
|
89
|
-
tag: string;
|
|
90
|
-
}[];
|
|
91
|
-
}
|
|
92
|
-
declare class inProcessQueueHandler {
|
|
93
|
-
private storage;
|
|
94
|
-
constructor(storage: QueueStorage);
|
|
95
|
-
submitJob(url: string, req: Remult, body: any): Promise<string>;
|
|
96
|
-
mapQueuedAction(url: string, what: (data: any, r: Remult, res: ApiActionResponse) => void): void;
|
|
97
|
-
actions: Map<string, (data: any, r: Remult, res: ApiActionResponse) => void>;
|
|
98
|
-
getJobInfo(queuedJobId: string): Promise<queuedJobInfo>;
|
|
71
|
+
export declare class RemultAsyncLocalStorage {
|
|
72
|
+
private readonly remultObjectStorage;
|
|
73
|
+
static enable(): void;
|
|
74
|
+
static disable(): void;
|
|
75
|
+
constructor(remultObjectStorage: import('async_hooks').AsyncLocalStorage<Remult>);
|
|
76
|
+
run(remult: Remult, callback: VoidFunction): void;
|
|
77
|
+
getRemult(): Remult;
|
|
78
|
+
static instance: RemultAsyncLocalStorage;
|
|
99
79
|
}
|
|
100
80
|
export interface queuedJobInfo {
|
|
101
81
|
info: queuedJobInfoResponse;
|
|
@@ -104,11 +84,6 @@ export interface queuedJobInfo {
|
|
|
104
84
|
setResult(result: any): void;
|
|
105
85
|
setProgress(progress: number): void;
|
|
106
86
|
}
|
|
107
|
-
export interface ApiActionResponse {
|
|
108
|
-
error(error: any): void;
|
|
109
|
-
success(result: any): void;
|
|
110
|
-
progress(progress: number): void;
|
|
111
|
-
}
|
|
112
87
|
export interface QueueStorage {
|
|
113
88
|
createJob(url: string, userId: string): Promise<string>;
|
|
114
89
|
getJobInfo(queuedJobId: string): Promise<queuedJobInfo>;
|
|
@@ -121,12 +96,6 @@ export declare class EntityQueueStorage implements QueueStorage {
|
|
|
121
96
|
getJobInfo(queuedJobId: string): Promise<queuedJobInfo>;
|
|
122
97
|
createJob(url: string, userId: string): Promise<string>;
|
|
123
98
|
}
|
|
124
|
-
declare class RouteImplementation {
|
|
125
|
-
map: Map<string, Map<string, GenericRequestHandler>>;
|
|
126
|
-
route(path: string): SpecificRoute;
|
|
127
|
-
handle(req: GenericRequest, gRes?: GenericResponse): Promise<ServerHandleResponse | undefined>;
|
|
128
|
-
middleware(req: GenericRequest, res: GenericResponse, next: VoidFunction): void;
|
|
129
|
-
}
|
|
130
99
|
export declare class JobsInQueueEntity extends IdEntity {
|
|
131
100
|
userId: string;
|
|
132
101
|
url: string;
|
|
@@ -137,4 +106,3 @@ export declare class JobsInQueueEntity extends IdEntity {
|
|
|
137
106
|
error: boolean;
|
|
138
107
|
progress: number;
|
|
139
108
|
}
|
|
140
|
-
export {};
|