remult 0.14.7 → 0.14.10
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/LICENSE +21 -0
- package/esm/assign.d.ts +1 -0
- package/esm/assign.js +5 -0
- package/esm/classType.d.ts +3 -0
- package/esm/classType.js +1 -0
- package/esm/graphql.d.ts +5 -0
- package/esm/graphql.js +102 -0
- package/esm/index.d.ts +36 -0
- package/esm/index.js +30 -0
- package/esm/inputTypes.d.ts +9 -0
- package/esm/inputTypes.js +9 -0
- package/esm/postgres/index.d.ts +2 -0
- package/esm/postgres/index.js +2 -0
- package/esm/postgres/postgres-data-provider.d.ts +28 -0
- package/esm/postgres/postgres-data-provider.js +97 -0
- package/esm/postgres/schema-builder.d.ts +15 -0
- package/esm/postgres/schema-builder.js +128 -0
- package/esm/remult-express.d.ts +5 -0
- package/esm/remult-express.js +16 -0
- package/esm/remult-knex/index.d.ts +51 -0
- package/esm/remult-knex/index.js +381 -0
- package/esm/remult-middleware.d.ts +2 -0
- package/esm/remult-middleware.js +63 -0
- package/esm/remult-mongo.d.ts +9 -0
- package/esm/remult-mongo.js +220 -0
- package/esm/server/JsonEntityFileStorage.d.ts +7 -0
- package/esm/server/JsonEntityFileStorage.js +20 -0
- package/esm/server/expressBridge.d.ts +140 -0
- package/esm/server/expressBridge.js +668 -0
- package/esm/server/index.d.ts +4 -0
- package/esm/server/index.js +4 -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/__EntityValueProvider.d.ts +10 -0
- package/esm/src/__EntityValueProvider.js +1 -0
- package/esm/src/__RowsOfDataForTesting.d.ts +3 -0
- package/esm/src/__RowsOfDataForTesting.js +1 -0
- package/esm/src/backend-tests/backend-database-test-setup.backend-spec.d.ts +5 -0
- package/esm/src/backend-tests/backend-database-test-setup.backend-spec.js +113 -0
- package/esm/src/backend-tests/my-test.backend-spec.d.ts +1 -0
- package/esm/src/backend-tests/my-test.backend-spec.js +49 -0
- package/esm/src/column-interfaces.d.ts +95 -0
- package/esm/src/column-interfaces.js +7 -0
- package/esm/src/column.d.ts +49 -0
- package/esm/src/column.js +133 -0
- package/esm/src/context.d.ts +124 -0
- package/esm/src/context.js +285 -0
- package/esm/src/data-api.d.ts +33 -0
- package/esm/src/data-api.js +204 -0
- package/esm/src/data-interfaces.d.ts +37 -0
- package/esm/src/data-interfaces.js +12 -0
- package/esm/src/data-providers/array-entity-data-provider.d.ts +22 -0
- package/esm/src/data-providers/array-entity-data-provider.js +264 -0
- package/esm/src/data-providers/in-memory-database.d.ts +9 -0
- package/esm/src/data-providers/in-memory-database.js +16 -0
- package/esm/src/data-providers/json-data-provider.d.ts +12 -0
- package/esm/src/data-providers/json-data-provider.js +52 -0
- package/esm/src/data-providers/rest-data-provider.d.ts +35 -0
- package/esm/src/data-providers/rest-data-provider.js +188 -0
- package/esm/src/data-providers/sql-database.d.ts +16 -0
- package/esm/src/data-providers/sql-database.js +261 -0
- package/esm/src/data-providers/web-sql-data-provider.d.ts +18 -0
- package/esm/src/data-providers/web-sql-data-provider.js +121 -0
- package/esm/src/entity.d.ts +82 -0
- package/esm/src/entity.js +1 -0
- package/esm/src/filter/filter-consumer-bridge-to-sql-request.d.ts +50 -0
- package/esm/src/filter/filter-consumer-bridge-to-sql-request.js +139 -0
- package/esm/src/filter/filter-consumer-bridge-to-url-builder.d.ts +1 -0
- package/esm/src/filter/filter-consumer-bridge-to-url-builder.js +1 -0
- package/esm/src/filter/filter-interfaces.d.ts +85 -0
- package/esm/src/filter/filter-interfaces.js +467 -0
- package/esm/src/id-entity.d.ts +4 -0
- package/esm/src/id-entity.js +8 -0
- package/esm/src/remult3/RepositoryImplementation.d.ts +326 -0
- package/esm/src/remult3/RepositoryImplementation.js +1806 -0
- package/esm/src/remult3/index.d.ts +2 -0
- package/esm/src/remult3/index.js +2 -0
- package/esm/src/remult3/remult3.d.ts +312 -0
- package/esm/src/remult3/remult3.js +1 -0
- package/esm/src/server-action.d.ts +70 -0
- package/esm/src/server-action.js +365 -0
- package/esm/src/shared-tests/db-tests-setup.d.ts +23 -0
- package/esm/src/shared-tests/db-tests-setup.js +66 -0
- package/esm/src/shared-tests/db-tests.db-tests.d.ts +26 -0
- package/esm/src/shared-tests/db-tests.db-tests.js +723 -0
- package/esm/src/shared-tests/deleteAll.d.ts +2 -0
- package/esm/src/shared-tests/deleteAll.js +4 -0
- package/esm/src/shared-tests/entityWithValidations.d.ts +14 -0
- package/esm/src/shared-tests/entityWithValidations.js +53 -0
- package/esm/src/shared-tests/index.d.ts +4 -0
- package/esm/src/shared-tests/index.js +4 -0
- package/esm/src/shared-tests/test-custom-id-column.spec.d.ts +1 -0
- package/esm/src/shared-tests/test-custom-id-column.spec.js +62 -0
- package/esm/src/shared-tests/test-special-value.spec.d.ts +10 -0
- package/esm/src/shared-tests/test-special-value.spec.js +88 -0
- package/esm/src/shared-tests/test-update-with-null.spec.d.ts +1 -0
- package/esm/src/shared-tests/test-update-with-null.spec.js +47 -0
- package/esm/src/sort.d.ts +15 -0
- package/esm/src/sort.js +82 -0
- package/esm/src/sql-command.d.ts +15 -0
- package/esm/src/sql-command.js +1 -0
- package/esm/src/tests/Done.d.ts +5 -0
- package/esm/src/tests/Done.js +11 -0
- package/esm/src/tests/TestDataApiResponse.d.ts +10 -0
- package/esm/src/tests/TestDataApiResponse.js +22 -0
- package/esm/src/tests/c.d.ts +8 -0
- package/esm/src/tests/c.js +22 -0
- package/esm/src/tests/createData.d.ts +7 -0
- package/esm/src/tests/createData.js +22 -0
- package/esm/src/tests/d.d.ts +6 -0
- package/esm/src/tests/d.js +19 -0
- package/esm/src/tests/dWithPrefilter.d.ts +7 -0
- package/esm/src/tests/dWithPrefilter.js +32 -0
- package/esm/src/tests/entityForCustomFilter.d.ts +16 -0
- package/esm/src/tests/entityForCustomFilter.js +44 -0
- package/esm/src/tests/entityWithValidationsOnColumn.d.ts +5 -0
- package/esm/src/tests/entityWithValidationsOnColumn.js +21 -0
- package/esm/src/tests/frontend-database-tests-setup.spec.d.ts +4 -0
- package/esm/src/tests/frontend-database-tests-setup.spec.js +38 -0
- package/esm/src/tests/h.d.ts +6 -0
- package/esm/src/tests/h.js +35 -0
- package/esm/src/tests/remult-3-entities.d.ts +23 -0
- package/esm/src/tests/remult-3-entities.js +72 -0
- package/esm/src/tests/tasks.d.ts +6 -0
- package/esm/src/tests/tasks.js +24 -0
- package/esm/src/tests/testHelper.spec.d.ts +34 -0
- package/esm/src/tests/testHelper.spec.js +217 -0
- package/esm/src/tests/testModel/models.d.ts +16 -0
- package/esm/src/tests/testModel/models.js +31 -0
- package/esm/src/validators.d.ts +14 -0
- package/esm/src/validators.js +33 -0
- package/esm/urlBuilder.d.ts +6 -0
- package/esm/urlBuilder.js +19 -0
- package/esm/valueConverters.d.ts +12 -0
- package/esm/valueConverters.js +169 -0
- package/index.d.ts +1 -0
- package/index.js +1 -0
- package/package.json +22 -1
- package/postgres/index.d.ts +1 -0
- package/postgres/index.js +1 -0
- package/postgres/postgres-data-provider.d.ts +1 -13
- package/postgres/postgres-data-provider.js +28 -262
- package/postgres/schema-builder.d.ts +15 -0
- package/postgres/schema-builder.js +270 -0
- package/readme.md +68 -30
- package/src/data-providers/web-sql-data-provider.js +4 -3
- package/src/entity.d.ts +9 -2
- package/src/remult3/RepositoryImplementation.js +11 -3
- package/src/shared-tests/test-update-with-null.spec.js +38 -0
- package/valueConverters.js +4 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
var entityForCustomFilter_1;
|
|
2
|
+
import { __decorate, __metadata } from "tslib";
|
|
3
|
+
import { SqlDatabase } from '../data-providers/sql-database';
|
|
4
|
+
import { Entity, EntityBase, Fields } from '../remult3';
|
|
5
|
+
import { Filter } from '../filter/filter-interfaces';
|
|
6
|
+
import { ArrayEntityDataProvider } from '../data-providers/array-entity-data-provider';
|
|
7
|
+
import { getDbNameProvider } from '../filter/filter-consumer-bridge-to-sql-request';
|
|
8
|
+
let entityForCustomFilter = entityForCustomFilter_1 = class entityForCustomFilter extends EntityBase {
|
|
9
|
+
};
|
|
10
|
+
entityForCustomFilter.filter = Filter.createCustom(async (remult, c) => {
|
|
11
|
+
let r = [];
|
|
12
|
+
if (c.oneAndThree)
|
|
13
|
+
r.push({ id: [1, 3] });
|
|
14
|
+
if (c.two)
|
|
15
|
+
r.push({ id: 2 });
|
|
16
|
+
if (c.dbOneOrThree) {
|
|
17
|
+
let meta = remult.repo(entityForCustomFilter_1).metadata;
|
|
18
|
+
const e = await getDbNameProvider(meta);
|
|
19
|
+
r.push({
|
|
20
|
+
$and: [
|
|
21
|
+
SqlDatabase.customFilter(async (x) => x.sql = e.nameOf(meta.fields.id) + ' in (' + x.addParameterAndReturnSqlToken(1) + "," + x.addParameterAndReturnSqlToken(3) + ")"),
|
|
22
|
+
ArrayEntityDataProvider.customFilter(x => x.id == 1 || x.id == 3)
|
|
23
|
+
]
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
return { $and: r };
|
|
27
|
+
});
|
|
28
|
+
entityForCustomFilter.oneAndThree = Filter.createCustom(() => ({ id: [1, 3] }));
|
|
29
|
+
entityForCustomFilter.testNumericValue = Filter.createCustom((r, val) => ({ id: val }));
|
|
30
|
+
entityForCustomFilter.testObjectValue = Filter.createCustom((r, val) => ({ id: val.val }));
|
|
31
|
+
__decorate([
|
|
32
|
+
Fields.integer(),
|
|
33
|
+
__metadata("design:type", Number)
|
|
34
|
+
], entityForCustomFilter.prototype, "id", void 0);
|
|
35
|
+
entityForCustomFilter = entityForCustomFilter_1 = __decorate([
|
|
36
|
+
Entity('entityForCustomFilter', { allowApiCrud: true })
|
|
37
|
+
], entityForCustomFilter);
|
|
38
|
+
export { entityForCustomFilter };
|
|
39
|
+
let entityForCustomFilter1 = class entityForCustomFilter1 extends entityForCustomFilter {
|
|
40
|
+
};
|
|
41
|
+
entityForCustomFilter1 = __decorate([
|
|
42
|
+
Entity('entityForCustomFilter1', { allowApiCrud: true })
|
|
43
|
+
], entityForCustomFilter1);
|
|
44
|
+
export { entityForCustomFilter1 };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { __decorate, __metadata } from "tslib";
|
|
2
|
+
import { Entity, EntityBase, Fields } from '../remult3';
|
|
3
|
+
let entityWithValidationsOnColumn = class entityWithValidationsOnColumn extends EntityBase {
|
|
4
|
+
};
|
|
5
|
+
__decorate([
|
|
6
|
+
Fields.integer(),
|
|
7
|
+
__metadata("design:type", Number)
|
|
8
|
+
], entityWithValidationsOnColumn.prototype, "myId", void 0);
|
|
9
|
+
__decorate([
|
|
10
|
+
Fields.string({
|
|
11
|
+
validate: (t, c) => {
|
|
12
|
+
if (!t.name || t.name.length < 3)
|
|
13
|
+
c.error = 'invalid on column';
|
|
14
|
+
}
|
|
15
|
+
}),
|
|
16
|
+
__metadata("design:type", String)
|
|
17
|
+
], entityWithValidationsOnColumn.prototype, "name", void 0);
|
|
18
|
+
entityWithValidationsOnColumn = __decorate([
|
|
19
|
+
Entity('', { allowApiCrud: true })
|
|
20
|
+
], entityWithValidationsOnColumn);
|
|
21
|
+
export { entityWithValidationsOnColumn };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { dbTestWhatSignature } from "../shared-tests/db-tests-setup";
|
|
2
|
+
export declare function testWebSqlImpl(key: string, what: dbTestWhatSignature, focus?: boolean): void;
|
|
3
|
+
export declare function testRest(key: string, what: dbTestWhatSignature, focus?: boolean): void;
|
|
4
|
+
import '../shared-tests/';
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { addDatabaseToTest, itWithFocus } from "../shared-tests/db-tests-setup";
|
|
2
|
+
import { InMemoryDataProvider } from "../..";
|
|
3
|
+
import { Remult } from "../context";
|
|
4
|
+
import { SqlDatabase } from "../data-providers/sql-database";
|
|
5
|
+
import { WebSqlDataProvider } from "../data-providers/web-sql-data-provider";
|
|
6
|
+
import { MockRestDataProvider } from "./testHelper.spec";
|
|
7
|
+
export function testWebSqlImpl(key, what, focus = false) {
|
|
8
|
+
itWithFocus(key + " - WebSql", async () => {
|
|
9
|
+
let webSql = new WebSqlDataProvider('test');
|
|
10
|
+
const sql = new SqlDatabase(webSql);
|
|
11
|
+
for (const r of await (await sql.execute("select name from sqlite_master where type='table'")).rows) {
|
|
12
|
+
switch (r.name) {
|
|
13
|
+
case "__WebKitDatabaseInfoTable__":
|
|
14
|
+
break;
|
|
15
|
+
case "sqlite_sequence":
|
|
16
|
+
break;
|
|
17
|
+
default:
|
|
18
|
+
await sql.execute("drop table if exists " + r.name);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
let remult = new Remult();
|
|
22
|
+
remult.setDataProvider(sql);
|
|
23
|
+
await what({ db: sql, remult, createEntity: async (x) => remult.repo(x) });
|
|
24
|
+
}, focus);
|
|
25
|
+
}
|
|
26
|
+
addDatabaseToTest(testWebSqlImpl);
|
|
27
|
+
export function testRest(key, what, focus = false) {
|
|
28
|
+
itWithFocus(key + " - Rest Provider", async () => {
|
|
29
|
+
let r = new Remult();
|
|
30
|
+
r.setDataProvider(new InMemoryDataProvider());
|
|
31
|
+
let remult = new Remult();
|
|
32
|
+
let db = new MockRestDataProvider(r);
|
|
33
|
+
remult.setDataProvider(db);
|
|
34
|
+
await what({ db, remult, createEntity: async (x) => remult.repo(x) });
|
|
35
|
+
}, focus);
|
|
36
|
+
}
|
|
37
|
+
addDatabaseToTest(testRest);
|
|
38
|
+
import '../shared-tests/';
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
var h_1;
|
|
2
|
+
import { __decorate, __metadata } from "tslib";
|
|
3
|
+
import { Field, Entity, EntityBase, FieldType, Fields } from '../remult3';
|
|
4
|
+
let h = h_1 = class h extends EntityBase {
|
|
5
|
+
};
|
|
6
|
+
__decorate([
|
|
7
|
+
Fields.string(),
|
|
8
|
+
__metadata("design:type", String)
|
|
9
|
+
], h.prototype, "id", void 0);
|
|
10
|
+
__decorate([
|
|
11
|
+
Field(() => h_1),
|
|
12
|
+
__metadata("design:type", h)
|
|
13
|
+
], h.prototype, "refH", void 0);
|
|
14
|
+
__decorate([
|
|
15
|
+
Fields.string(),
|
|
16
|
+
__metadata("design:type", String)
|
|
17
|
+
], h.prototype, "refHId", void 0);
|
|
18
|
+
h = h_1 = __decorate([
|
|
19
|
+
FieldType({
|
|
20
|
+
valueConverter: {
|
|
21
|
+
toJson: x => x != undefined ? x : '',
|
|
22
|
+
fromJson: x => x ? x : null
|
|
23
|
+
},
|
|
24
|
+
}),
|
|
25
|
+
Entity('h', {
|
|
26
|
+
saving: self => {
|
|
27
|
+
if (self.refH)
|
|
28
|
+
self.refHId = self.refH.id;
|
|
29
|
+
else
|
|
30
|
+
self.refHId = '';
|
|
31
|
+
},
|
|
32
|
+
allowApiCrud: true
|
|
33
|
+
})
|
|
34
|
+
], h);
|
|
35
|
+
export { h };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { EntityBase } from "../remult3";
|
|
2
|
+
import { Status } from "./testModel/models";
|
|
3
|
+
export declare class Products {
|
|
4
|
+
id: number;
|
|
5
|
+
name: string;
|
|
6
|
+
price: number;
|
|
7
|
+
archived: boolean;
|
|
8
|
+
availableFrom: Date;
|
|
9
|
+
}
|
|
10
|
+
export interface CategoriesForTesting extends EntityBase {
|
|
11
|
+
id: number;
|
|
12
|
+
categoryName: string;
|
|
13
|
+
description: string;
|
|
14
|
+
status: Status;
|
|
15
|
+
}
|
|
16
|
+
export declare class Categories extends EntityBase {
|
|
17
|
+
id: number;
|
|
18
|
+
categoryName: string;
|
|
19
|
+
description: string;
|
|
20
|
+
categoryNameLength: number;
|
|
21
|
+
categoryNameLengthAsync: number;
|
|
22
|
+
status: Status;
|
|
23
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { __decorate, __metadata } from "tslib";
|
|
2
|
+
import { EntityBase, Field, Entity, Fields } from "../remult3";
|
|
3
|
+
import { Status } from "./testModel/models";
|
|
4
|
+
let Products = class Products {
|
|
5
|
+
};
|
|
6
|
+
__decorate([
|
|
7
|
+
Fields.integer(),
|
|
8
|
+
__metadata("design:type", Number)
|
|
9
|
+
], Products.prototype, "id", void 0);
|
|
10
|
+
__decorate([
|
|
11
|
+
Fields.string(),
|
|
12
|
+
__metadata("design:type", String)
|
|
13
|
+
], Products.prototype, "name", void 0);
|
|
14
|
+
__decorate([
|
|
15
|
+
Fields.number(),
|
|
16
|
+
__metadata("design:type", Number)
|
|
17
|
+
], Products.prototype, "price", void 0);
|
|
18
|
+
__decorate([
|
|
19
|
+
Fields.boolean(),
|
|
20
|
+
__metadata("design:type", Boolean)
|
|
21
|
+
], Products.prototype, "archived", void 0);
|
|
22
|
+
__decorate([
|
|
23
|
+
Fields.date(),
|
|
24
|
+
__metadata("design:type", Date)
|
|
25
|
+
], Products.prototype, "availableFrom", void 0);
|
|
26
|
+
Products = __decorate([
|
|
27
|
+
Entity('Products')
|
|
28
|
+
], Products);
|
|
29
|
+
export { Products };
|
|
30
|
+
let r;
|
|
31
|
+
let Categories = class Categories extends EntityBase {
|
|
32
|
+
constructor() {
|
|
33
|
+
super(...arguments);
|
|
34
|
+
this.id = 0;
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
__decorate([
|
|
38
|
+
Fields.number({
|
|
39
|
+
dbName: 'CategoryID'
|
|
40
|
+
}),
|
|
41
|
+
__metadata("design:type", Number)
|
|
42
|
+
], Categories.prototype, "id", void 0);
|
|
43
|
+
__decorate([
|
|
44
|
+
Fields.string({ allowNull: true }),
|
|
45
|
+
__metadata("design:type", String)
|
|
46
|
+
], Categories.prototype, "categoryName", void 0);
|
|
47
|
+
__decorate([
|
|
48
|
+
Fields.string(),
|
|
49
|
+
__metadata("design:type", String)
|
|
50
|
+
], Categories.prototype, "description", void 0);
|
|
51
|
+
__decorate([
|
|
52
|
+
Fields.number({
|
|
53
|
+
serverExpression: c => c.categoryName ? c.categoryName.length : undefined
|
|
54
|
+
}),
|
|
55
|
+
__metadata("design:type", Number)
|
|
56
|
+
], Categories.prototype, "categoryNameLength", void 0);
|
|
57
|
+
__decorate([
|
|
58
|
+
Fields.number({
|
|
59
|
+
serverExpression: (c) => Promise.resolve(c.categoryName ? c.categoryName.length : undefined)
|
|
60
|
+
}),
|
|
61
|
+
__metadata("design:type", Number)
|
|
62
|
+
], Categories.prototype, "categoryNameLengthAsync", void 0);
|
|
63
|
+
__decorate([
|
|
64
|
+
Field(() => Status),
|
|
65
|
+
__metadata("design:type", Status)
|
|
66
|
+
], Categories.prototype, "status", void 0);
|
|
67
|
+
Categories = __decorate([
|
|
68
|
+
Entity('Categories', {
|
|
69
|
+
allowApiCrud: true
|
|
70
|
+
})
|
|
71
|
+
], Categories);
|
|
72
|
+
export { Categories };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { __decorate, __metadata } from "tslib";
|
|
2
|
+
import { Entity, EntityBase, Fields } from '../remult3';
|
|
3
|
+
let tasks = class tasks extends EntityBase {
|
|
4
|
+
constructor() {
|
|
5
|
+
super(...arguments);
|
|
6
|
+
this.completed = false;
|
|
7
|
+
}
|
|
8
|
+
};
|
|
9
|
+
__decorate([
|
|
10
|
+
Fields.integer(),
|
|
11
|
+
__metadata("design:type", Number)
|
|
12
|
+
], tasks.prototype, "id", void 0);
|
|
13
|
+
__decorate([
|
|
14
|
+
Fields.string(),
|
|
15
|
+
__metadata("design:type", String)
|
|
16
|
+
], tasks.prototype, "name", void 0);
|
|
17
|
+
__decorate([
|
|
18
|
+
Fields.boolean(),
|
|
19
|
+
__metadata("design:type", Boolean)
|
|
20
|
+
], tasks.prototype, "completed", void 0);
|
|
21
|
+
tasks = __decorate([
|
|
22
|
+
Entity('tasks', { allowApiCrud: true })
|
|
23
|
+
], tasks);
|
|
24
|
+
export { tasks };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import './frontend-database-tests-setup.spec';
|
|
2
|
+
import { Remult } from "../context";
|
|
3
|
+
import { DataProvider, EntityDataProvider } from "../data-interfaces";
|
|
4
|
+
import { InMemoryDataProvider } from "../data-providers/in-memory-database";
|
|
5
|
+
import { EntityMetadata } from "../remult3";
|
|
6
|
+
export declare function itForEach<T>(name: string, arrayOfT: T[], runAsync: (item: T) => Promise<any>): void;
|
|
7
|
+
export declare function fitForEach<T>(name: string, arrayOfT: T[], runAsync: (item: T) => Promise<any>): void;
|
|
8
|
+
export declare function testAsIfOnBackend(what: () => Promise<any>): Promise<void>;
|
|
9
|
+
export declare const ActionTestConfig: {
|
|
10
|
+
db: InMemoryDataProvider;
|
|
11
|
+
};
|
|
12
|
+
export declare function testSql(runAsync: (db: {
|
|
13
|
+
db: DataProvider;
|
|
14
|
+
remult: Remult;
|
|
15
|
+
}) => Promise<void>): Promise<void>;
|
|
16
|
+
export declare function testInMemoryDb(runAsync: (db: {
|
|
17
|
+
db: DataProvider;
|
|
18
|
+
remult: Remult;
|
|
19
|
+
}) => Promise<void>): Promise<void>;
|
|
20
|
+
export declare function testRestDb(runAsync: (db: {
|
|
21
|
+
db: DataProvider;
|
|
22
|
+
remult: Remult;
|
|
23
|
+
}) => Promise<void>): Promise<void>;
|
|
24
|
+
export declare function testAllDataProviders(runAsync: (db: {
|
|
25
|
+
db: DataProvider;
|
|
26
|
+
remult: Remult;
|
|
27
|
+
}) => Promise<void>): Promise<void>;
|
|
28
|
+
export declare class MockRestDataProvider implements DataProvider {
|
|
29
|
+
private remult;
|
|
30
|
+
constructor(remult: Remult);
|
|
31
|
+
getEntityDataProvider(metadata: EntityMetadata<any>): EntityDataProvider;
|
|
32
|
+
transaction(action: (dataProvider: DataProvider) => Promise<void>): Promise<void>;
|
|
33
|
+
supportsCustomFilter: boolean;
|
|
34
|
+
}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import './frontend-database-tests-setup.spec';
|
|
2
|
+
import { HttpProviderBridgeToRestDataProviderHttpProvider, Remult } from "../context";
|
|
3
|
+
import { DataApi, serializeError } from "../data-api";
|
|
4
|
+
import { InMemoryDataProvider } from "../data-providers/in-memory-database";
|
|
5
|
+
import { RestEntityDataProvider } from "../data-providers/rest-data-provider";
|
|
6
|
+
import { SqlDatabase } from "../data-providers/sql-database";
|
|
7
|
+
import { WebSqlDataProvider } from "../data-providers/web-sql-data-provider";
|
|
8
|
+
import { Action, actionInfo, serverActionField } from "../server-action";
|
|
9
|
+
import { testConfiguration } from '../shared-tests/entityWithValidations';
|
|
10
|
+
import { TestDataApiResponse } from './TestDataApiResponse';
|
|
11
|
+
jasmine.DEFAULT_TIMEOUT_INTERVAL = 999999;
|
|
12
|
+
//actionInfo.runningOnServer = false;
|
|
13
|
+
export function itForEach(name, arrayOfT, runAsync) {
|
|
14
|
+
arrayOfT.forEach(i => {
|
|
15
|
+
it(name + ' - ' + i, (done) => {
|
|
16
|
+
runAsync(i).catch(e => {
|
|
17
|
+
fail(e);
|
|
18
|
+
done();
|
|
19
|
+
}).then(done, e => {
|
|
20
|
+
fail(e);
|
|
21
|
+
done();
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
export function fitForEach(name, arrayOfT, runAsync) {
|
|
27
|
+
arrayOfT.forEach(i => {
|
|
28
|
+
fit(name + ' - ' + i, (done) => {
|
|
29
|
+
runAsync(i).catch(e => {
|
|
30
|
+
fail(e);
|
|
31
|
+
done();
|
|
32
|
+
}).then(done, e => {
|
|
33
|
+
fail(e);
|
|
34
|
+
done();
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
export async function testAsIfOnBackend(what) {
|
|
40
|
+
try {
|
|
41
|
+
actionInfo.runningOnServer = true;
|
|
42
|
+
await what();
|
|
43
|
+
}
|
|
44
|
+
finally {
|
|
45
|
+
actionInfo.runningOnServer = false;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
export const ActionTestConfig = {
|
|
49
|
+
db: new InMemoryDataProvider()
|
|
50
|
+
};
|
|
51
|
+
Action.provider = {
|
|
52
|
+
delete: undefined,
|
|
53
|
+
get: undefined,
|
|
54
|
+
post: async (urlreq, data) => {
|
|
55
|
+
return await new Promise((res, r) => {
|
|
56
|
+
let found = false;
|
|
57
|
+
actionInfo.allActions.forEach(action => {
|
|
58
|
+
action[serverActionField].
|
|
59
|
+
__register((url, queue, allowed, what) => {
|
|
60
|
+
if (Remult.apiBaseUrl + '/' + url == urlreq) {
|
|
61
|
+
found = true;
|
|
62
|
+
let t = new TestDataApiResponse();
|
|
63
|
+
actionInfo.runningOnServer = true;
|
|
64
|
+
t.success = data => {
|
|
65
|
+
res(data);
|
|
66
|
+
actionInfo.runningOnServer = false;
|
|
67
|
+
};
|
|
68
|
+
t.error = data => {
|
|
69
|
+
r(JSON.parse(JSON.stringify(serializeError(data))));
|
|
70
|
+
actionInfo.runningOnServer = false;
|
|
71
|
+
};
|
|
72
|
+
let remult = new Remult();
|
|
73
|
+
remult.setDataProvider(ActionTestConfig.db);
|
|
74
|
+
what(JSON.parse(JSON.stringify(data)), remult, t);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
if (!found) {
|
|
79
|
+
r("did not find " + urlreq);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
},
|
|
83
|
+
put: undefined
|
|
84
|
+
};
|
|
85
|
+
export async function testSql(runAsync) {
|
|
86
|
+
let webSql = new WebSqlDataProvider('test');
|
|
87
|
+
const sql = new SqlDatabase(webSql);
|
|
88
|
+
for (const r of await (await sql.execute("select name from sqlite_master where type='table'")).rows) {
|
|
89
|
+
switch (r.name) {
|
|
90
|
+
case "__WebKitDatabaseInfoTable__":
|
|
91
|
+
break;
|
|
92
|
+
default:
|
|
93
|
+
await sql.execute("drop table if exists " + r.name);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
let remult = new Remult();
|
|
97
|
+
remult.setDataProvider(sql);
|
|
98
|
+
await runAsync({ db: sql, remult });
|
|
99
|
+
}
|
|
100
|
+
export async function testInMemoryDb(runAsync) {
|
|
101
|
+
let remult = new Remult();
|
|
102
|
+
let db = new InMemoryDataProvider();
|
|
103
|
+
remult.setDataProvider(db);
|
|
104
|
+
await runAsync({ db, remult });
|
|
105
|
+
}
|
|
106
|
+
export async function testRestDb(runAsync) {
|
|
107
|
+
let r = new Remult();
|
|
108
|
+
r.setDataProvider(new InMemoryDataProvider());
|
|
109
|
+
let remult = new Remult();
|
|
110
|
+
let db = new MockRestDataProvider(r);
|
|
111
|
+
remult.setDataProvider(db);
|
|
112
|
+
await runAsync({ db, remult });
|
|
113
|
+
}
|
|
114
|
+
export async function testAllDataProviders(runAsync) {
|
|
115
|
+
await testSql(runAsync);
|
|
116
|
+
await testInMemoryDb(runAsync);
|
|
117
|
+
await testRestDb(runAsync);
|
|
118
|
+
}
|
|
119
|
+
function urlToReq(url) {
|
|
120
|
+
let args = new Map();
|
|
121
|
+
let params = url?.split('?')[1]?.split('&');
|
|
122
|
+
if (params)
|
|
123
|
+
for (const p of params) {
|
|
124
|
+
if (!p)
|
|
125
|
+
continue;
|
|
126
|
+
let z = p.split('=');
|
|
127
|
+
let key = decodeURIComponent(z[0]);
|
|
128
|
+
let value = decodeURIComponent(z[1]);
|
|
129
|
+
let x = args.get(key);
|
|
130
|
+
if (x === undefined) {
|
|
131
|
+
args.set(key, value);
|
|
132
|
+
}
|
|
133
|
+
else if (Array.isArray(x))
|
|
134
|
+
x.push(value);
|
|
135
|
+
else
|
|
136
|
+
args.set(key, [args.get(key), value]);
|
|
137
|
+
}
|
|
138
|
+
let req = {
|
|
139
|
+
get: (key) => {
|
|
140
|
+
let r = args.get(key);
|
|
141
|
+
if (r !== undefined) {
|
|
142
|
+
r.toString();
|
|
143
|
+
}
|
|
144
|
+
return r;
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
return req;
|
|
148
|
+
}
|
|
149
|
+
export class MockRestDataProvider {
|
|
150
|
+
constructor(remult) {
|
|
151
|
+
this.remult = remult;
|
|
152
|
+
this.supportsCustomFilter = true;
|
|
153
|
+
}
|
|
154
|
+
getEntityDataProvider(metadata) {
|
|
155
|
+
let dataApi = new DataApi(this.remult.repo(metadata.entityType), this.remult);
|
|
156
|
+
return new RestEntityDataProvider("", new HttpProviderBridgeToRestDataProviderHttpProvider({
|
|
157
|
+
delete: async (url) => {
|
|
158
|
+
let urlSplit = url.split('/');
|
|
159
|
+
let r = new TestDataApiResponse();
|
|
160
|
+
let result;
|
|
161
|
+
r.deleted = () => { };
|
|
162
|
+
try {
|
|
163
|
+
testConfiguration.restDbRunningOnServer = true;
|
|
164
|
+
await dataApi.delete(r, urlSplit[urlSplit.length - 1]);
|
|
165
|
+
}
|
|
166
|
+
finally {
|
|
167
|
+
testConfiguration.restDbRunningOnServer = false;
|
|
168
|
+
}
|
|
169
|
+
return result;
|
|
170
|
+
},
|
|
171
|
+
get: async (url) => {
|
|
172
|
+
let r = new TestDataApiResponse();
|
|
173
|
+
let result;
|
|
174
|
+
r.success = data => { result = data; };
|
|
175
|
+
try {
|
|
176
|
+
testConfiguration.restDbRunningOnServer = true;
|
|
177
|
+
await dataApi.httpGet(r, urlToReq(url));
|
|
178
|
+
}
|
|
179
|
+
finally {
|
|
180
|
+
testConfiguration.restDbRunningOnServer = false;
|
|
181
|
+
}
|
|
182
|
+
return result;
|
|
183
|
+
},
|
|
184
|
+
post: async (url, data) => {
|
|
185
|
+
let r = new TestDataApiResponse();
|
|
186
|
+
let result;
|
|
187
|
+
r.created = data => { result = data; };
|
|
188
|
+
r.success = data => { result = data; };
|
|
189
|
+
try {
|
|
190
|
+
testConfiguration.restDbRunningOnServer = true;
|
|
191
|
+
await dataApi.httpPost(r, urlToReq(url), data);
|
|
192
|
+
}
|
|
193
|
+
finally {
|
|
194
|
+
testConfiguration.restDbRunningOnServer = false;
|
|
195
|
+
}
|
|
196
|
+
return result;
|
|
197
|
+
},
|
|
198
|
+
put: async (url, data) => {
|
|
199
|
+
let urlSplit = url.split('/');
|
|
200
|
+
let r = new TestDataApiResponse();
|
|
201
|
+
let result;
|
|
202
|
+
r.success = data => { result = data; };
|
|
203
|
+
try {
|
|
204
|
+
testConfiguration.restDbRunningOnServer = true;
|
|
205
|
+
await dataApi.put(r, urlSplit[urlSplit.length - 1], data);
|
|
206
|
+
}
|
|
207
|
+
finally {
|
|
208
|
+
testConfiguration.restDbRunningOnServer = false;
|
|
209
|
+
}
|
|
210
|
+
return result;
|
|
211
|
+
}
|
|
212
|
+
}), metadata);
|
|
213
|
+
}
|
|
214
|
+
transaction(action) {
|
|
215
|
+
throw new Error('Method not implemented.');
|
|
216
|
+
}
|
|
217
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export declare class Status {
|
|
2
|
+
id: number;
|
|
3
|
+
name: string;
|
|
4
|
+
static open: Status;
|
|
5
|
+
static closed: Status;
|
|
6
|
+
static hold: Status;
|
|
7
|
+
constructor(id: number, name: string);
|
|
8
|
+
}
|
|
9
|
+
export declare class TestStatus {
|
|
10
|
+
id?: string;
|
|
11
|
+
caption?: string;
|
|
12
|
+
static open: TestStatus;
|
|
13
|
+
static closed: TestStatus;
|
|
14
|
+
static hold: TestStatus;
|
|
15
|
+
constructor(id?: string, caption?: string);
|
|
16
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
var Status_1, TestStatus_1;
|
|
2
|
+
import { __decorate, __metadata } from "tslib";
|
|
3
|
+
import { ValueListFieldType } from "../../remult3";
|
|
4
|
+
let Status = Status_1 = class Status {
|
|
5
|
+
constructor(id, name) {
|
|
6
|
+
this.id = id;
|
|
7
|
+
this.name = name;
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
Status.open = new Status_1(0, "open");
|
|
11
|
+
Status.closed = new Status_1(1, "closed");
|
|
12
|
+
Status.hold = new Status_1(2, "hold");
|
|
13
|
+
Status = Status_1 = __decorate([
|
|
14
|
+
ValueListFieldType(),
|
|
15
|
+
__metadata("design:paramtypes", [Number, String])
|
|
16
|
+
], Status);
|
|
17
|
+
export { Status };
|
|
18
|
+
let TestStatus = TestStatus_1 = class TestStatus {
|
|
19
|
+
constructor(id, caption) {
|
|
20
|
+
this.id = id;
|
|
21
|
+
this.caption = caption;
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
TestStatus.open = new TestStatus_1();
|
|
25
|
+
TestStatus.closed = new TestStatus_1('cc');
|
|
26
|
+
TestStatus.hold = new TestStatus_1(undefined, 'hh');
|
|
27
|
+
TestStatus = TestStatus_1 = __decorate([
|
|
28
|
+
ValueListFieldType(),
|
|
29
|
+
__metadata("design:paramtypes", [String, String])
|
|
30
|
+
], TestStatus);
|
|
31
|
+
export { TestStatus };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { FieldRef } from "./remult3";
|
|
2
|
+
export declare class Validators {
|
|
3
|
+
static required: ((entity: any, col: FieldRef<any, string>, message?: any) => void) & {
|
|
4
|
+
withMessage: (message: string) => (entity: any, col: FieldRef<any, string>) => void;
|
|
5
|
+
defaultMessage: string;
|
|
6
|
+
};
|
|
7
|
+
static unique: ((entity: any, col: FieldRef<any, any>, message?: any) => Promise<void>) & {
|
|
8
|
+
withMessage: (message: string) => (entity: any, col: FieldRef<any, any>) => Promise<void>;
|
|
9
|
+
defaultMessage: string;
|
|
10
|
+
};
|
|
11
|
+
static uniqueOnBackend: ((entity: any, col: FieldRef<any, any>, message?: any) => Promise<void>) & {
|
|
12
|
+
withMessage: (message: string) => (entity: any, col: FieldRef<any, any>) => Promise<void>;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { isBackend } from "./context";
|
|
2
|
+
export class Validators {
|
|
3
|
+
}
|
|
4
|
+
Validators.required = Object.assign((entity, col, message = undefined) => {
|
|
5
|
+
if (!col.value || typeof (col.value) === "string" && col.value.trim().length == 0)
|
|
6
|
+
col.error = message || Validators.required.defaultMessage;
|
|
7
|
+
}, {
|
|
8
|
+
withMessage: (message) => {
|
|
9
|
+
return (entity, col) => Validators.required(entity, col, message);
|
|
10
|
+
},
|
|
11
|
+
defaultMessage: 'Should not be empty'
|
|
12
|
+
});
|
|
13
|
+
Validators.unique = Object.assign(async (entity, col, message = undefined) => {
|
|
14
|
+
if (!col.entityRef)
|
|
15
|
+
throw "unique validation may only work on columns that are attached to an entity";
|
|
16
|
+
if (col.entityRef.isNew() || col.valueChanged()) {
|
|
17
|
+
if (await col.entityRef.repository.count({ [col.metadata.key]: col.value }))
|
|
18
|
+
col.error = message || Validators.unique.defaultMessage;
|
|
19
|
+
}
|
|
20
|
+
}, {
|
|
21
|
+
withMessage: (message) => {
|
|
22
|
+
return (entity, col) => Validators.unique(entity, col, message);
|
|
23
|
+
},
|
|
24
|
+
defaultMessage: 'already exists'
|
|
25
|
+
});
|
|
26
|
+
Validators.uniqueOnBackend = Object.assign(async (entity, col, message = undefined) => {
|
|
27
|
+
if (isBackend())
|
|
28
|
+
return Validators.unique(entity, col, message);
|
|
29
|
+
}, {
|
|
30
|
+
withMessage: (message) => {
|
|
31
|
+
return (entity, col) => Validators.uniqueOnBackend(entity, col, message);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export class UrlBuilder {
|
|
2
|
+
constructor(url) {
|
|
3
|
+
this.url = url;
|
|
4
|
+
}
|
|
5
|
+
add(key, value) {
|
|
6
|
+
if (this.url.indexOf('?') >= 0)
|
|
7
|
+
this.url += '&';
|
|
8
|
+
else
|
|
9
|
+
this.url += '?';
|
|
10
|
+
this.url += encodeURIComponent(key) + '=' + encodeURIComponent(value);
|
|
11
|
+
}
|
|
12
|
+
addObject(object, suffix = '') {
|
|
13
|
+
if (object != undefined)
|
|
14
|
+
for (var key in object) {
|
|
15
|
+
let val = object[key];
|
|
16
|
+
this.add(key + suffix, val);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|