remult 0.16.3-exp.3 → 0.16.3
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 +27 -5
- package/esm/index.d.ts +2 -1
- package/esm/index.js +2 -1
- package/esm/postgres/postgres-data-provider.d.ts +1 -3
- package/esm/postgres/postgres-data-provider.js +1 -11
- package/esm/postgres/postgresColumnSyntax.d.ts +2 -0
- package/esm/postgres/postgresColumnSyntax.js +30 -0
- package/esm/postgres/schema-builder.js +20 -20
- package/esm/remult-express.js +2 -0
- package/esm/remult-fastify.js +2 -0
- package/esm/remult-knex/index.d.ts +28 -4
- package/esm/remult-knex/index.js +33 -46
- package/esm/remult-middleware.d.ts +2 -0
- package/esm/remult-middleware.js +65 -0
- package/esm/remult-mongo.d.ts +2 -8
- package/esm/remult-mongo.js +8 -22
- package/esm/server/expressBridge.d.ts +9 -0
- package/esm/server/expressBridge.js +18 -24
- package/esm/server/initAsyncHooks.d.ts +1 -0
- package/esm/server/initAsyncHooks.js +9 -0
- package/esm/server/register-actions-on-server.d.ts +3 -0
- package/esm/server/register-actions-on-server.js +24 -0
- package/esm/server/register-entities-on-server.d.ts +3 -0
- package/esm/server/register-entities-on-server.js +15 -0
- package/esm/src/backend-tests/my-test.backend-spec.js +48 -64
- package/esm/src/data-providers/sql-database.d.ts +0 -2
- package/esm/src/data-providers/sql-database.js +15 -26
- package/esm/src/data-providers/web-sql-data-provider.d.ts +0 -3
- package/esm/src/data-providers/web-sql-data-provider.js +8 -16
- package/esm/src/filter/filter-consumer-bridge-to-sql-request.d.ts +14 -13
- package/esm/src/filter/filter-consumer-bridge-to-sql-request.js +19 -52
- package/esm/src/filter/filter-interfaces.d.ts +3 -3
- package/esm/src/filter/filter-interfaces.js +1 -1
- package/esm/src/remult-proxy.js +4 -0
- package/esm/src/remult3/RepositoryImplementation.d.ts +2 -1
- package/esm/src/remult3/RepositoryImplementation.js +12 -17
- package/esm/src/shared-tests/db-tests-setup.js +2 -1
- package/esm/src/tests/entityForCustomFilter.js +7 -6
- package/esm/src/tests/frontend-database-tests-setup.spec.js +2 -1
- package/esm/src/tests/testHelper.spec.js +1 -0
- package/esm/valueConverters.d.ts +12 -0
- package/esm/valueConverters.js +169 -0
- package/index.d.ts +2 -1
- package/index.js +3 -3
- package/package.json +1 -1
- package/postgres/postgres-data-provider.d.ts +1 -3
- package/postgres/postgres-data-provider.js +1 -11
- package/postgres/postgresColumnSyntax.d.ts +2 -0
- package/postgres/postgresColumnSyntax.js +34 -0
- package/postgres/schema-builder.js +19 -19
- package/remult-express.js +2 -0
- package/remult-fastify.js +2 -0
- package/remult-knex/index.d.ts +28 -4
- package/remult-knex/index.js +38 -68
- package/remult-middleware.d.ts +2 -0
- package/remult-middleware.js +70 -0
- package/remult-mongo.d.ts +2 -8
- package/remult-mongo.js +8 -39
- package/server/expressBridge.d.ts +9 -0
- package/server/expressBridge.js +19 -34
- package/server/initAsyncHooks.d.ts +1 -0
- package/server/initAsyncHooks.js +13 -0
- package/server/register-actions-on-server.d.ts +3 -0
- package/server/register-actions-on-server.js +50 -0
- package/server/register-entities-on-server.d.ts +3 -0
- package/server/register-entities-on-server.js +19 -0
- package/src/backend-tests/my-test.backend-spec.js +55 -210
- package/src/data-providers/sql-database.d.ts +0 -2
- package/src/data-providers/sql-database.js +14 -25
- package/src/data-providers/web-sql-data-provider.d.ts +0 -3
- package/src/data-providers/web-sql-data-provider.js +7 -15
- package/src/filter/filter-consumer-bridge-to-sql-request.d.ts +14 -13
- package/src/filter/filter-consumer-bridge-to-sql-request.js +46 -95
- package/src/filter/filter-interfaces.d.ts +3 -3
- package/src/filter/filter-interfaces.js +1 -1
- package/src/remult-proxy.js +4 -0
- package/src/remult3/RepositoryImplementation.d.ts +2 -1
- package/src/remult3/RepositoryImplementation.js +16 -31
- package/src/shared-tests/db-tests-setup.js +3 -2
- package/src/tests/entityForCustomFilter.js +7 -6
- package/src/tests/frontend-database-tests-setup.spec.js +5 -4
- package/src/tests/testHelper.spec.js +4 -3
- package/valueConverters.d.ts +12 -0
- package/valueConverters.js +168 -0
package/esm/remult-mongo.d.ts
CHANGED
|
@@ -1,15 +1,9 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { DataProvider, EntityDataProvider,
|
|
1
|
+
import { MongoClient, Db } from 'mongodb';
|
|
2
|
+
import { DataProvider, EntityDataProvider, EntityMetadata } from '.';
|
|
3
3
|
export declare class MongoDataProvider implements DataProvider {
|
|
4
4
|
private db;
|
|
5
5
|
private client;
|
|
6
6
|
constructor(db: Db, client: MongoClient);
|
|
7
|
-
static getDb(remult?: Remult): Db;
|
|
8
7
|
getEntityDataProvider(entity: EntityMetadata<any>): EntityDataProvider;
|
|
9
8
|
transaction(action: (dataProvider: DataProvider) => Promise<void>): Promise<void>;
|
|
10
9
|
}
|
|
11
|
-
export declare function mongoCondition<entityType>(repo: Repository<entityType>, condition: EntityFilter<entityType>): Promise<{
|
|
12
|
-
$and: any[];
|
|
13
|
-
} | {
|
|
14
|
-
$and?: undefined;
|
|
15
|
-
}>;
|
package/esm/remult-mongo.js
CHANGED
|
@@ -1,17 +1,10 @@
|
|
|
1
1
|
import { CompoundIdField, Filter } from '.';
|
|
2
|
-
import {
|
|
3
|
-
import { remult as remultContext } from './src/remult-proxy';
|
|
2
|
+
import { getDbNameProvider } from './src/filter/filter-consumer-bridge-to-sql-request';
|
|
4
3
|
export class MongoDataProvider {
|
|
5
4
|
constructor(db, client) {
|
|
6
5
|
this.db = db;
|
|
7
6
|
this.client = client;
|
|
8
7
|
}
|
|
9
|
-
static getDb(remult) {
|
|
10
|
-
const r = (remult || remultContext).dataProvider;
|
|
11
|
-
if (!r.db)
|
|
12
|
-
throw "the data provider is not a MongoDataProvider";
|
|
13
|
-
return r.db;
|
|
14
|
-
}
|
|
15
8
|
getEntityDataProvider(entity) {
|
|
16
9
|
return new MongoEntityDataProvider(this.db, entity);
|
|
17
10
|
}
|
|
@@ -40,7 +33,7 @@ class MongoEntityDataProvider {
|
|
|
40
33
|
translateFromJson(row, nameProvider) {
|
|
41
34
|
let result = {};
|
|
42
35
|
for (const col of this.entity.fields) {
|
|
43
|
-
let val = row[nameProvider.
|
|
36
|
+
let val = row[nameProvider.nameOf(col)];
|
|
44
37
|
if (isNull(val))
|
|
45
38
|
val = null;
|
|
46
39
|
result[col.key] = col.valueConverter.fromDb(val);
|
|
@@ -53,7 +46,7 @@ class MongoEntityDataProvider {
|
|
|
53
46
|
let val = col.valueConverter.toDb(row[col.key]);
|
|
54
47
|
if (val === null)
|
|
55
48
|
val = NULL;
|
|
56
|
-
result[nameProvider.
|
|
49
|
+
result[nameProvider.nameOf(col)] = val;
|
|
57
50
|
}
|
|
58
51
|
return result;
|
|
59
52
|
}
|
|
@@ -80,7 +73,7 @@ class MongoEntityDataProvider {
|
|
|
80
73
|
if (options.orderBy) {
|
|
81
74
|
op.sort = {};
|
|
82
75
|
for (const s of options.orderBy.Segments) {
|
|
83
|
-
op.sort[e.
|
|
76
|
+
op.sort[e.nameOf(s.field)] = s.isDescending ? -1 : 1;
|
|
84
77
|
}
|
|
85
78
|
}
|
|
86
79
|
return await Promise.all(await collection.find(where, op).map(x => this.translateFromJson(x, e)).toArray());
|
|
@@ -123,8 +116,8 @@ class MongoEntityDataProvider {
|
|
|
123
116
|
return await this.translateFromJson(await collection.findOne({ _id: r.insertedId }), e);
|
|
124
117
|
}
|
|
125
118
|
async collection() {
|
|
126
|
-
const e = await
|
|
127
|
-
const collection = this.db.collection(e
|
|
119
|
+
const e = await getDbNameProvider(this.entity);
|
|
120
|
+
const collection = this.db.collection(e.entityName);
|
|
128
121
|
return { e, collection };
|
|
129
122
|
}
|
|
130
123
|
}
|
|
@@ -178,7 +171,7 @@ class FilterConsumerBridgeToMongo {
|
|
|
178
171
|
}
|
|
179
172
|
isIn(col, val) {
|
|
180
173
|
this.result.push(() => ({
|
|
181
|
-
[this.nameProvider.
|
|
174
|
+
[this.nameProvider.nameOf(col)]: {
|
|
182
175
|
$in: val.map(x => col.valueConverter.toDb(x))
|
|
183
176
|
}
|
|
184
177
|
}));
|
|
@@ -210,7 +203,7 @@ class FilterConsumerBridgeToMongo {
|
|
|
210
203
|
}
|
|
211
204
|
add(col, val, operator) {
|
|
212
205
|
this.result.push(() => ({
|
|
213
|
-
[this.nameProvider.
|
|
206
|
+
[this.nameProvider.nameOf(col)]: { [operator]: isNull(val) ? val : col.valueConverter.toDb(val) }
|
|
214
207
|
}));
|
|
215
208
|
}
|
|
216
209
|
databaseCustom(databaseCustom) {
|
|
@@ -226,10 +219,3 @@ class FilterConsumerBridgeToMongo {
|
|
|
226
219
|
// })());
|
|
227
220
|
}
|
|
228
221
|
}
|
|
229
|
-
export async function mongoCondition(repo, condition) {
|
|
230
|
-
var b = new FilterConsumerBridgeToMongo(await dbNamesOf(repo.metadata));
|
|
231
|
-
b._addWhere = false;
|
|
232
|
-
await (await (repo.translateWhereToFilter(condition))).__applyToConsumer(b);
|
|
233
|
-
let r = await b.resolveWhere();
|
|
234
|
-
return r;
|
|
235
|
-
}
|
|
@@ -57,6 +57,15 @@ export interface GenericResponse {
|
|
|
57
57
|
status(statusCode: number): GenericResponse;
|
|
58
58
|
end(): any;
|
|
59
59
|
}
|
|
60
|
+
export declare class RemultAsyncLocalStorage {
|
|
61
|
+
private readonly remultObjectStorage;
|
|
62
|
+
static enable(): void;
|
|
63
|
+
static disable(): void;
|
|
64
|
+
constructor(remultObjectStorage: import('async_hooks').AsyncLocalStorage<Remult>);
|
|
65
|
+
run(remult: Remult, callback: VoidFunction): void;
|
|
66
|
+
getRemult(): Remult;
|
|
67
|
+
static instance: RemultAsyncLocalStorage;
|
|
68
|
+
}
|
|
60
69
|
export interface queuedJobInfo {
|
|
61
70
|
info: queuedJobInfoResponse;
|
|
62
71
|
userId: string;
|
|
@@ -30,30 +30,12 @@ export function createRemultServer(options) {
|
|
|
30
30
|
return dp;
|
|
31
31
|
return new (await import('./JsonEntityFileStorage')).JsonFileDataProvider('./db');
|
|
32
32
|
});
|
|
33
|
-
|
|
34
|
-
dataProvider = dataProvider.then(async (dp) => {
|
|
35
|
-
try {
|
|
36
|
-
const asyncHooks = await import('async_hooks');
|
|
37
|
-
remultObjectStorage = new RemultAsyncLocalStorage(new asyncHooks.AsyncLocalStorage());
|
|
38
|
-
}
|
|
39
|
-
catch {
|
|
40
|
-
remultObjectStorage = new RemultAsyncLocalStorage(undefined);
|
|
41
|
-
}
|
|
42
|
-
remult.remultFactory = () => {
|
|
43
|
-
const r = remultObjectStorage.getRemult();
|
|
44
|
-
if (r)
|
|
45
|
-
return r;
|
|
46
|
-
else
|
|
47
|
-
throw new Error("remult object was requested outside of a valid context, try running it within initApi or a remult request cycle");
|
|
48
|
-
};
|
|
49
|
-
return dp;
|
|
50
|
-
});
|
|
51
|
-
}
|
|
33
|
+
RemultAsyncLocalStorage.enable();
|
|
52
34
|
if (options.initApi) {
|
|
53
35
|
dataProvider = dataProvider.then(async (dp) => {
|
|
54
36
|
var remult = new Remult(dp);
|
|
55
37
|
await new Promise((res) => {
|
|
56
|
-
|
|
38
|
+
RemultAsyncLocalStorage.instance.run(remult, async () => {
|
|
57
39
|
await options.initApi(remult);
|
|
58
40
|
res({});
|
|
59
41
|
});
|
|
@@ -78,10 +60,22 @@ export function createRemultServer(options) {
|
|
|
78
60
|
return bridge;
|
|
79
61
|
}
|
|
80
62
|
;
|
|
81
|
-
class RemultAsyncLocalStorage {
|
|
63
|
+
export class RemultAsyncLocalStorage {
|
|
82
64
|
constructor(remultObjectStorage) {
|
|
83
65
|
this.remultObjectStorage = remultObjectStorage;
|
|
84
66
|
}
|
|
67
|
+
static enable() {
|
|
68
|
+
remult.remultFactory = () => {
|
|
69
|
+
const r = RemultAsyncLocalStorage.instance.getRemult();
|
|
70
|
+
if (r)
|
|
71
|
+
return r;
|
|
72
|
+
else
|
|
73
|
+
throw new Error("remult object was requested outside of a valid context, try running it within initApi or a remult request cycle");
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
static disable() {
|
|
77
|
+
remult.resetFactory();
|
|
78
|
+
}
|
|
85
79
|
run(remult, callback) {
|
|
86
80
|
if (this.remultObjectStorage)
|
|
87
81
|
this.remultObjectStorage.run(remult, callback);
|
|
@@ -90,12 +84,12 @@ class RemultAsyncLocalStorage {
|
|
|
90
84
|
}
|
|
91
85
|
getRemult() {
|
|
92
86
|
if (!this.remultObjectStorage) {
|
|
93
|
-
throw "can't use static remult in this environment, `async_hooks` were not
|
|
87
|
+
throw new Error("can't use static remult in this environment, `async_hooks` were not initialized");
|
|
94
88
|
}
|
|
95
89
|
return this.remultObjectStorage.getStore();
|
|
96
90
|
}
|
|
97
91
|
}
|
|
98
|
-
|
|
92
|
+
RemultAsyncLocalStorage.instance = new RemultAsyncLocalStorage(undefined);
|
|
99
93
|
class RemultServerImplementation {
|
|
100
94
|
constructor(queue, options, dataProvider) {
|
|
101
95
|
this.queue = queue;
|
|
@@ -182,7 +176,7 @@ class RemultServerImplementation {
|
|
|
182
176
|
let remult = new Remult();
|
|
183
177
|
remult.dataProvider = (await this.dataProvider);
|
|
184
178
|
await new Promise(res => {
|
|
185
|
-
|
|
179
|
+
RemultAsyncLocalStorage.instance.run(remult, async () => {
|
|
186
180
|
if (req) {
|
|
187
181
|
let user;
|
|
188
182
|
if (this.options.getUser)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function initAsyncHooks(): void;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { AsyncLocalStorage } from 'async_hooks';
|
|
2
|
+
import { RemultAsyncLocalStorage } from './expressBridge';
|
|
3
|
+
let init = false;
|
|
4
|
+
export function initAsyncHooks() {
|
|
5
|
+
if (init)
|
|
6
|
+
return;
|
|
7
|
+
init = true;
|
|
8
|
+
RemultAsyncLocalStorage.instance = new RemultAsyncLocalStorage(new AsyncLocalStorage());
|
|
9
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { serverActionField, actionInfo, classBackendMethodsArray } from '../src/server-action';
|
|
2
|
+
export function registerActionsOnServer(area, controllers) {
|
|
3
|
+
var addAction = (a) => {
|
|
4
|
+
let x = a[serverActionField];
|
|
5
|
+
if (!x) {
|
|
6
|
+
throw 'failed to set server action, did you forget the BackendMethod Decorator?';
|
|
7
|
+
}
|
|
8
|
+
area.addAction(x);
|
|
9
|
+
};
|
|
10
|
+
actionInfo.runningOnServer = true;
|
|
11
|
+
if (controllers && controllers.length > 0) {
|
|
12
|
+
for (const c of controllers) {
|
|
13
|
+
let z = c[classBackendMethodsArray];
|
|
14
|
+
if (z)
|
|
15
|
+
for (const a of z) {
|
|
16
|
+
addAction(a);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
else
|
|
21
|
+
actionInfo.allActions.forEach((a) => {
|
|
22
|
+
addAction(a);
|
|
23
|
+
});
|
|
24
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { getEntityKey } from "../src/remult3";
|
|
2
|
+
import { allEntities } from "../src/context";
|
|
3
|
+
import { DataApi } from "../src/data-api";
|
|
4
|
+
export function registerEntitiesOnServer(area, entities) {
|
|
5
|
+
if (!entities)
|
|
6
|
+
entities = allEntities;
|
|
7
|
+
//add Api Entries
|
|
8
|
+
entities.forEach(e => {
|
|
9
|
+
let key = getEntityKey(e);
|
|
10
|
+
if (key != undefined)
|
|
11
|
+
area.add(key, c => {
|
|
12
|
+
return new DataApi(c.repo(e), c);
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { Remult } from "../context";
|
|
2
|
-
import {
|
|
2
|
+
import { KnexDataProvider } from '../../remult-knex';
|
|
3
3
|
import { config } from 'dotenv';
|
|
4
|
-
import { testKnexPGSqlImpl,
|
|
4
|
+
import { testKnexPGSqlImpl, testPostgresImplementation } from "./backend-database-test-setup.backend-spec";
|
|
5
5
|
import { entityWithValidations } from "../shared-tests/entityWithValidations";
|
|
6
|
-
import { PostgresDataProvider } from "../../postgres";
|
|
7
|
-
import { MongoDataProvider, mongoCondition } from "../../remult-mongo";
|
|
8
6
|
import { SqlDatabase } from "../data-providers/sql-database";
|
|
9
|
-
import {
|
|
7
|
+
import { RemultAsyncLocalStorage } from "../../server/expressBridge";
|
|
8
|
+
import { initAsyncHooks } from "../../server/initAsyncHooks";
|
|
9
|
+
import { remult } from "../remult-proxy";
|
|
10
10
|
config();
|
|
11
11
|
testPostgresImplementation("default order by", async ({ createEntity }) => {
|
|
12
12
|
let s = await entityWithValidations.create4RowsInDp(createEntity);
|
|
@@ -61,63 +61,47 @@ testKnexPGSqlImpl("knex filter2", async ({ createEntity }) => {
|
|
|
61
61
|
}
|
|
62
62
|
})).length).toBe(3);
|
|
63
63
|
}, false);
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
64
|
+
it("test async hooks and static remult", async () => {
|
|
65
|
+
let gotException = true;
|
|
66
|
+
try {
|
|
67
|
+
RemultAsyncLocalStorage.instance.getRemult();
|
|
68
|
+
gotException = false;
|
|
69
|
+
}
|
|
70
|
+
catch { }
|
|
71
|
+
expect(gotException).toBe(true);
|
|
72
|
+
initAsyncHooks();
|
|
73
|
+
expect(RemultAsyncLocalStorage.instance.getRemult()).toBe(undefined);
|
|
74
|
+
RemultAsyncLocalStorage.enable();
|
|
75
|
+
try {
|
|
76
|
+
remult.isAllowed(false);
|
|
77
|
+
gotException = false;
|
|
78
|
+
}
|
|
79
|
+
catch { }
|
|
80
|
+
expect(gotException).toBe(true);
|
|
81
|
+
const promises = [];
|
|
82
|
+
RemultAsyncLocalStorage.instance.run(new Remult(), () => {
|
|
83
|
+
remult.user = { id: 'noam' };
|
|
84
|
+
promises.push(new Promise(res => {
|
|
85
|
+
setTimeout(() => {
|
|
86
|
+
expect(remult.user.id).toBe('noam');
|
|
87
|
+
res({});
|
|
88
|
+
}, 10);
|
|
89
|
+
}));
|
|
90
|
+
RemultAsyncLocalStorage.instance.run(new Remult(), () => {
|
|
91
|
+
remult.user = { id: 'yoni' };
|
|
92
|
+
promises.push(new Promise(res => {
|
|
93
|
+
setTimeout(() => {
|
|
94
|
+
expect(remult.user.id).toBe('yoni');
|
|
95
|
+
res({});
|
|
96
|
+
}, 10);
|
|
97
|
+
}));
|
|
98
|
+
});
|
|
99
|
+
promises.push(new Promise(res => {
|
|
100
|
+
setTimeout(() => {
|
|
101
|
+
expect(remult.user.id).toBe('noam');
|
|
102
|
+
res({});
|
|
103
|
+
}, 10);
|
|
104
|
+
}));
|
|
96
105
|
});
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
const repo = await entityWithValidations.create4RowsInDp(createEntity);
|
|
100
|
-
const knex = KnexDataProvider.getDb(remult);
|
|
101
|
-
const t = await dbNamesOf(repo);
|
|
102
|
-
const r = await knex((await t).$entityName).select(t.myId, t.name);
|
|
103
|
-
expect(r.length).toBe(4);
|
|
104
|
-
}, false);
|
|
105
|
-
testMongo("work with native mongo", async ({ remult, createEntity }) => {
|
|
106
|
-
const repo = await entityWithValidations.create4RowsInDp(createEntity);
|
|
107
|
-
const mongo = MongoDataProvider.getDb(remult);
|
|
108
|
-
const r = await (await mongo.collection(repo.metadata.options.dbName)).countDocuments();
|
|
109
|
-
expect(r).toBe(4);
|
|
110
|
-
}, false);
|
|
111
|
-
testKnexPGSqlImpl("knex with filter", async ({ remult, createEntity }) => {
|
|
112
|
-
const repo = await entityWithValidations.create4RowsInDp(createEntity);
|
|
113
|
-
const knex = KnexDataProvider.getDb(remult);
|
|
114
|
-
const e = await dbNamesOf(repo);
|
|
115
|
-
const r = await knex(e.$entityName).count().where(await knexCondition(repo, { myId: [1, 3] }));
|
|
116
|
-
expect(r[0].count).toBe('2');
|
|
117
|
-
}, false);
|
|
118
|
-
testMongo("work with native mongo and condition", async ({ remult, createEntity }) => {
|
|
119
|
-
const repo = await entityWithValidations.create4RowsInDp(createEntity);
|
|
120
|
-
const mongo = MongoDataProvider.getDb(remult);
|
|
121
|
-
const r = await (await mongo.collection(repo.metadata.options.dbName)).countDocuments(await mongoCondition(repo, { myId: [1, 2] }));
|
|
122
|
-
expect(r).toBe(2);
|
|
123
|
-
}, false);
|
|
106
|
+
await Promise.all(promises);
|
|
107
|
+
});
|
|
@@ -2,10 +2,8 @@ import { EntityDataProvider, DataProvider } from "../data-interfaces";
|
|
|
2
2
|
import { SqlCommand, SqlImplementation, SqlResult } from "../sql-command";
|
|
3
3
|
import { CustomSqlFilterBuilderFunction } from "../filter/filter-consumer-bridge-to-sql-request";
|
|
4
4
|
import { EntityMetadata, EntityFilter } from "../remult3";
|
|
5
|
-
import { Remult } from "../context";
|
|
6
5
|
export declare class SqlDatabase implements DataProvider {
|
|
7
6
|
private sql;
|
|
8
|
-
static getDb(remult?: Remult): SqlDatabase;
|
|
9
7
|
createCommand(): SqlCommand;
|
|
10
8
|
execute(sql: string): Promise<SqlResult>;
|
|
11
9
|
getEntityDataProvider(entity: EntityMetadata): EntityDataProvider;
|
|
@@ -1,34 +1,23 @@
|
|
|
1
1
|
import { CompoundIdField } from "../column";
|
|
2
|
-
import {
|
|
2
|
+
import { FilterConsumerBridgeToSqlRequest, getDbNameProvider } from "../filter/filter-consumer-bridge-to-sql-request";
|
|
3
3
|
import { customDatabaseFilterToken, Filter } from '../filter/filter-interfaces';
|
|
4
4
|
import { Sort } from '../sort';
|
|
5
|
-
import { RepositoryImplementation } from "../remult3";
|
|
6
5
|
// @dynamic
|
|
7
6
|
export class SqlDatabase {
|
|
8
7
|
constructor(sql) {
|
|
9
8
|
this.sql = sql;
|
|
10
9
|
this.createdEntities = [];
|
|
11
10
|
}
|
|
12
|
-
static getDb(remult) {
|
|
13
|
-
const r = (remult || RepositoryImplementation.defaultRemult).dataProvider;
|
|
14
|
-
if (!r.createCommand)
|
|
15
|
-
throw "the data provider is not an SqlDatabase";
|
|
16
|
-
return r;
|
|
17
|
-
}
|
|
18
11
|
createCommand() {
|
|
19
12
|
return new LogSQLCommand(this.sql.createCommand(), SqlDatabase.LogToConsole);
|
|
20
13
|
}
|
|
21
14
|
async execute(sql) {
|
|
22
15
|
return await this.createCommand().execute(sql);
|
|
23
16
|
}
|
|
24
|
-
/* @internal*/
|
|
25
|
-
_getSourceSql() {
|
|
26
|
-
return this.sql;
|
|
27
|
-
}
|
|
28
17
|
getEntityDataProvider(entity) {
|
|
29
18
|
return new ActualSQLServerDataProvider(entity, this, async (dbName) => {
|
|
30
|
-
if (this.createdEntities.indexOf(dbName
|
|
31
|
-
this.createdEntities.push(dbName
|
|
19
|
+
if (this.createdEntities.indexOf(dbName.entityName) < 0) {
|
|
20
|
+
this.createdEntities.push(dbName.entityName);
|
|
32
21
|
await this.sql.entityIsUsedForTheFirstTime(entity);
|
|
33
22
|
}
|
|
34
23
|
}, this.sql);
|
|
@@ -106,13 +95,13 @@ class ActualSQLServerDataProvider {
|
|
|
106
95
|
this.strategy = strategy;
|
|
107
96
|
}
|
|
108
97
|
async init() {
|
|
109
|
-
let dbNameProvider = await
|
|
98
|
+
let dbNameProvider = await getDbNameProvider(this.entity);
|
|
110
99
|
await this.iAmUsed(dbNameProvider);
|
|
111
100
|
return dbNameProvider;
|
|
112
101
|
}
|
|
113
102
|
async count(where) {
|
|
114
103
|
let e = await this.init();
|
|
115
|
-
let select = 'select count(*) count from ' + e
|
|
104
|
+
let select = 'select count(*) count from ' + e.entityName;
|
|
116
105
|
let r = this.sql.createCommand();
|
|
117
106
|
if (where) {
|
|
118
107
|
let wc = new FilterConsumerBridgeToSqlRequest(r, e);
|
|
@@ -127,7 +116,7 @@ class ActualSQLServerDataProvider {
|
|
|
127
116
|
let e = await this.init();
|
|
128
117
|
let { colKeys, select } = this.buildSelect(e);
|
|
129
118
|
select = 'select ' + select;
|
|
130
|
-
select += '\n from ' + e
|
|
119
|
+
select += '\n from ' + e.entityName;
|
|
131
120
|
let r = this.sql.createCommand();
|
|
132
121
|
if (options) {
|
|
133
122
|
if (options.where) {
|
|
@@ -158,7 +147,7 @@ class ActualSQLServerDataProvider {
|
|
|
158
147
|
}
|
|
159
148
|
else
|
|
160
149
|
select += ', ';
|
|
161
|
-
select += e.
|
|
150
|
+
select += e.nameOf(c.field);
|
|
162
151
|
if (c.isDescending)
|
|
163
152
|
select += ' desc';
|
|
164
153
|
}
|
|
@@ -200,7 +189,7 @@ class ActualSQLServerDataProvider {
|
|
|
200
189
|
else {
|
|
201
190
|
if (colKeys.length > 0)
|
|
202
191
|
select += ', ';
|
|
203
|
-
select += e.
|
|
192
|
+
select += e.nameOf(x);
|
|
204
193
|
colKeys.push(x);
|
|
205
194
|
}
|
|
206
195
|
}
|
|
@@ -211,12 +200,12 @@ class ActualSQLServerDataProvider {
|
|
|
211
200
|
let r = this.sql.createCommand();
|
|
212
201
|
let f = new FilterConsumerBridgeToSqlRequest(r, e);
|
|
213
202
|
Filter.fromEntityFilter(this.entity, this.entity.idMetadata.getIdFilter(id)).__applyToConsumer(f);
|
|
214
|
-
let statement = 'update ' + e
|
|
203
|
+
let statement = 'update ' + e.entityName + ' set ';
|
|
215
204
|
let added = false;
|
|
216
205
|
for (const x of this.entity.fields) {
|
|
217
206
|
if (x instanceof CompoundIdField) {
|
|
218
207
|
}
|
|
219
|
-
if (isDbReadonly(x
|
|
208
|
+
if (e.isDbReadonly(x)) { }
|
|
220
209
|
else if (data[x.key] !== undefined) {
|
|
221
210
|
let v = x.valueConverter.toDb(data[x.key]);
|
|
222
211
|
if (v !== undefined) {
|
|
@@ -224,7 +213,7 @@ class ActualSQLServerDataProvider {
|
|
|
224
213
|
added = true;
|
|
225
214
|
else
|
|
226
215
|
statement += ', ';
|
|
227
|
-
statement += e.
|
|
216
|
+
statement += e.nameOf(x) + ' = ' + r.addParameterAndReturnSqlToken(v);
|
|
228
217
|
}
|
|
229
218
|
}
|
|
230
219
|
}
|
|
@@ -240,7 +229,7 @@ class ActualSQLServerDataProvider {
|
|
|
240
229
|
let r = this.sql.createCommand();
|
|
241
230
|
let f = new FilterConsumerBridgeToSqlRequest(r, e);
|
|
242
231
|
Filter.fromEntityFilter(this.entity, this.entity.idMetadata.getIdFilter(id)).__applyToConsumer(f);
|
|
243
|
-
let statement = 'delete from ' + e
|
|
232
|
+
let statement = 'delete from ' + e.entityName;
|
|
244
233
|
statement += await f.resolveWhere();
|
|
245
234
|
return r.execute(statement).then(() => { });
|
|
246
235
|
}
|
|
@@ -251,7 +240,7 @@ class ActualSQLServerDataProvider {
|
|
|
251
240
|
let vals = '';
|
|
252
241
|
let added = false;
|
|
253
242
|
for (const x of this.entity.fields) {
|
|
254
|
-
if (isDbReadonly(x
|
|
243
|
+
if (e.isDbReadonly(x)) { }
|
|
255
244
|
else {
|
|
256
245
|
let v = x.valueConverter.toDb(data[x.key]);
|
|
257
246
|
if (v != undefined) {
|
|
@@ -261,12 +250,12 @@ class ActualSQLServerDataProvider {
|
|
|
261
250
|
cols += ', ';
|
|
262
251
|
vals += ', ';
|
|
263
252
|
}
|
|
264
|
-
cols += e.
|
|
253
|
+
cols += e.nameOf(x);
|
|
265
254
|
vals += r.addParameterAndReturnSqlToken(v);
|
|
266
255
|
}
|
|
267
256
|
}
|
|
268
257
|
}
|
|
269
|
-
let statement = `insert into ${e
|
|
258
|
+
let statement = `insert into ${e.entityName} (${cols}) values (${vals})`;
|
|
270
259
|
let { colKeys, select } = this.buildSelect(e);
|
|
271
260
|
statement += ' returning ' + select;
|
|
272
261
|
return await r.execute(statement).then(sql => this.buildResultRow(colKeys, sql.rows[0], sql));
|
|
@@ -1,15 +1,12 @@
|
|
|
1
|
-
/// <reference types="websql" />
|
|
2
1
|
import { __RowsOfDataForTesting } from "../__RowsOfDataForTesting";
|
|
3
2
|
import { SqlCommand, SqlImplementation } from "../sql-command";
|
|
4
3
|
import { EntityMetadata } from "../remult3";
|
|
5
|
-
import { Remult } from "../context";
|
|
6
4
|
export declare class WebSqlDataProvider implements SqlImplementation, __RowsOfDataForTesting {
|
|
7
5
|
private databaseName;
|
|
8
6
|
rows: {
|
|
9
7
|
[tableName: string]: any;
|
|
10
8
|
};
|
|
11
9
|
constructor(databaseName: string, databaseSize?: number);
|
|
12
|
-
static getDb(remult?: Remult): Database;
|
|
13
10
|
getLimitSqlSyntax(limit: number, offset: number): string;
|
|
14
11
|
entityIsUsedForTheFirstTime(entity: EntityMetadata): Promise<void>;
|
|
15
12
|
dropTable(entity: EntityMetadata): Promise<void>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { isAutoIncrement } from "../remult3";
|
|
2
2
|
import { SqlDatabase } from "./sql-database";
|
|
3
|
-
import {
|
|
3
|
+
import { getDbNameProvider } from "../filter/filter-consumer-bridge-to-sql-request";
|
|
4
4
|
//SqlDatabase.LogToConsole = true;
|
|
5
5
|
export class WebSqlDataProvider {
|
|
6
6
|
constructor(databaseName, databaseSize = 2 * 1024 * 1024) {
|
|
@@ -8,14 +8,6 @@ export class WebSqlDataProvider {
|
|
|
8
8
|
//@ts-ignore
|
|
9
9
|
this.db = window.openDatabase(databaseName, '1.0', databaseName, databaseSize);
|
|
10
10
|
}
|
|
11
|
-
static getDb(remult) {
|
|
12
|
-
const sql = SqlDatabase.getDb(remult);
|
|
13
|
-
const me = sql._getSourceSql();
|
|
14
|
-
if (!me.db) {
|
|
15
|
-
throw "the data provider is not a WebSqlDataProvider";
|
|
16
|
-
}
|
|
17
|
-
return me.db;
|
|
18
|
-
}
|
|
19
11
|
getLimitSqlSyntax(limit, offset) {
|
|
20
12
|
return ' limit ' + limit + ' offset ' + offset;
|
|
21
13
|
}
|
|
@@ -23,34 +15,34 @@ export class WebSqlDataProvider {
|
|
|
23
15
|
await this.createTable(entity);
|
|
24
16
|
}
|
|
25
17
|
async dropTable(entity) {
|
|
26
|
-
let e = await
|
|
27
|
-
let sql = 'drop table if exists ' + e
|
|
18
|
+
let e = await getDbNameProvider(entity);
|
|
19
|
+
let sql = 'drop table if exists ' + e.entityName;
|
|
28
20
|
if (SqlDatabase.LogToConsole)
|
|
29
21
|
console.log(sql);
|
|
30
22
|
await this.createCommand().execute(sql);
|
|
31
23
|
}
|
|
32
24
|
async createTable(entity) {
|
|
33
25
|
let result = '';
|
|
34
|
-
let e = await
|
|
26
|
+
let e = await getDbNameProvider(entity);
|
|
35
27
|
for (const x of entity.fields) {
|
|
36
|
-
if (!isDbReadonly(x
|
|
28
|
+
if (!e.isDbReadonly(x) || isAutoIncrement(x)) {
|
|
37
29
|
if (result.length != 0)
|
|
38
30
|
result += ',';
|
|
39
31
|
result += '\r\n ';
|
|
40
32
|
if (isAutoIncrement(x)) {
|
|
41
33
|
if (x.key != entity.idMetadata.field.key)
|
|
42
34
|
throw "in web sql, autoincrement is only allowed for primary key";
|
|
43
|
-
result += e.
|
|
35
|
+
result += e.nameOf(x) + ' integer primary key autoincrement';
|
|
44
36
|
}
|
|
45
37
|
else {
|
|
46
|
-
result += this.addColumnSqlSyntax(x, e.
|
|
38
|
+
result += this.addColumnSqlSyntax(x, e.nameOf(x));
|
|
47
39
|
if (x.key == entity.idMetadata.field.key) {
|
|
48
40
|
result += ' primary key';
|
|
49
41
|
}
|
|
50
42
|
}
|
|
51
43
|
}
|
|
52
44
|
}
|
|
53
|
-
let sql = 'create table if not exists ' + e
|
|
45
|
+
let sql = 'create table if not exists ' + e.entityName + ' (' + result + '\r\n)';
|
|
54
46
|
if (SqlDatabase.LogToConsole)
|
|
55
47
|
console.log(sql);
|
|
56
48
|
await this.createCommand().execute(sql);
|