remult 0.13.22 → 0.13.23
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/package.json +1 -2
- package/readme.md +15 -13
- package/server/expressBridge.d.ts +1 -0
- package/server/expressBridge.js +10 -4
- package/server/register-actions-on-server.d.ts +2 -1
- package/server/register-actions-on-server.js +36 -4
- package/server/register-entities-on-server.d.ts +2 -1
- package/server/register-entities-on-server.js +4 -2
- package/src/data-providers/web-sql-data-provider.d.ts +1 -1
- package/src/data-providers/web-sql-data-provider.js +3 -2
- package/src/remult3/RepositoryImplementation.d.ts +1 -1
- package/src/server-action.d.ts +1 -0
- package/src/server-action.js +8 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "remult",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.23",
|
|
4
4
|
"description": "A CRUD framework for full-stack TypeScript",
|
|
5
5
|
"homepage": "https://remult.dev/",
|
|
6
6
|
"repository": {
|
|
@@ -13,7 +13,6 @@
|
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
15
|
"uuid": "^8.3.2",
|
|
16
|
-
"body-parser": "^1.18.3",
|
|
17
16
|
"reflect-metadata": "^0.1.13",
|
|
18
17
|
"tslib": "^2.3.1"
|
|
19
18
|
}
|
package/readme.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
</a>
|
|
5
5
|
<h1>Remult</h1>
|
|
6
6
|
<a href="https://circleci.com/gh/remult/remult/tree/master">
|
|
7
|
-
<img alt="CircleCI" src="https://circleci.com/gh/remult/remult/tree/master.svg?style=
|
|
7
|
+
<img alt="CircleCI" src="https://circleci.com/gh/remult/remult/tree/master.svg?style=shield">
|
|
8
8
|
</a>
|
|
9
9
|
<a href="https://codecov.io/gh/remult/remult">
|
|
10
10
|
<img src="https://codecov.io/gh/remult/remult/branch/master/graph/badge.svg?token=LYWQRUN3D1"/>
|
|
@@ -18,11 +18,9 @@
|
|
|
18
18
|
<a href="https://www.npmjs.com/package/remult">
|
|
19
19
|
<img alt="npm downloads" src="https://img.shields.io/npm/dm/remult">
|
|
20
20
|
</a>
|
|
21
|
-
<a href="https://
|
|
22
|
-
<img alt="
|
|
23
|
-
|
|
24
|
-
<a href="https://github.com/remult/remult/pulse" alt="Activity">
|
|
25
|
-
<img src="https://img.shields.io/github/commit-activity/m/remult/remult" /></a>
|
|
21
|
+
<a href="https://discord.gg/GXHk7ZfuG5">
|
|
22
|
+
<img alt="chat on discord" src="https://img.shields.io/badge/chat-on%20discord-blueviolet"/>
|
|
23
|
+
</a>
|
|
26
24
|
</div>
|
|
27
25
|
|
|
28
26
|
## What is Remult?
|
|
@@ -33,15 +31,15 @@
|
|
|
33
31
|
* Type-safe frontend API client
|
|
34
32
|
* Type-safe backend query builder
|
|
35
33
|
|
|
36
|
-
#### Remult :heart:
|
|
34
|
+
#### Remult :heart: Code Sharing
|
|
37
35
|
|
|
38
|
-
|
|
36
|
+
With model types shared between frontend and backend code, Remult can **enforce data validation and constraints, defined once, both in the front-end and witin back-end API routes**.
|
|
39
37
|
|
|
40
38
|
## Getting started
|
|
41
39
|
The best way to learn Remult is by following a tutorial of a simple Todo web app with a Node.js Express backend.
|
|
42
40
|
|
|
43
41
|
* [Tutorial with React](https://remult.dev/tutorials/react/)
|
|
44
|
-
* [Tutorial with Angular](https://remult.dev/tutorials/
|
|
42
|
+
* [Tutorial with Angular](https://remult.dev/tutorials/angular/)
|
|
45
43
|
|
|
46
44
|
## Installation
|
|
47
45
|
```sh
|
|
@@ -123,7 +121,7 @@ export class Product {
|
|
|
123
121
|
@Fields.string<Product>({
|
|
124
122
|
validate: product => {
|
|
125
123
|
if (product.name.trim().length == 0)
|
|
126
|
-
|
|
124
|
+
throw 'required';
|
|
127
125
|
}
|
|
128
126
|
})
|
|
129
127
|
name = '';
|
|
@@ -131,7 +129,7 @@ export class Product {
|
|
|
131
129
|
@Fields.number({
|
|
132
130
|
validate: (_, field) => {
|
|
133
131
|
if (field.value < 0)
|
|
134
|
-
|
|
132
|
+
throw "must not be less than 0";
|
|
135
133
|
}
|
|
136
134
|
})
|
|
137
135
|
unitPrice = 0;
|
|
@@ -145,14 +143,14 @@ const product = productsRepo.create();
|
|
|
145
143
|
try {
|
|
146
144
|
await productsRepo.save(product);
|
|
147
145
|
}
|
|
148
|
-
catch (e:
|
|
146
|
+
catch (e: any) {
|
|
149
147
|
console.error(e.message); // Browser console will display - "Name: required"
|
|
150
148
|
}
|
|
151
149
|
```
|
|
152
150
|
|
|
153
151
|
### Enforced in backend:
|
|
154
152
|
```sh
|
|
155
|
-
> curl
|
|
153
|
+
> curl http://localhost:3001/api/products -H "Content-Type: application/json" -d "{""unitPrice"":-1}"
|
|
156
154
|
|
|
157
155
|
{"modelState":{"unitPrice":"must not be less than 0","name":"required"},"message":"Name: required"}
|
|
158
156
|
```
|
|
@@ -176,6 +174,10 @@ export class Article {
|
|
|
176
174
|
}
|
|
177
175
|
```
|
|
178
176
|
|
|
177
|
+
## Example App
|
|
178
|
+
|
|
179
|
+
[CRM demo](https://github.com/remult/crm-demo) with a React + [MUI](https://mui.com) front-end and Postgres database.
|
|
180
|
+
|
|
179
181
|
## Contributing
|
|
180
182
|
Contributions are welcome. See [CONTRIBUTING](CONTRIBUTING.md).
|
|
181
183
|
|
|
@@ -20,6 +20,7 @@ export declare function remultExpress(options?: {
|
|
|
20
20
|
defaultGetLimit?: number;
|
|
21
21
|
entities?: ClassType<any>[];
|
|
22
22
|
controllers?: ClassType<any>[];
|
|
23
|
+
bodyParser?: boolean;
|
|
23
24
|
}): RemultExpressBridge;
|
|
24
25
|
export interface RemultExpressBridge extends express.RequestHandler {
|
|
25
26
|
getRemult(req: express.Request): Promise<Remult>;
|
package/server/expressBridge.js
CHANGED
|
@@ -4,7 +4,6 @@ exports.JobsInQueueEntity = exports.EntityQueueStorage = exports.ExpressRequestB
|
|
|
4
4
|
var tslib_1 = require("tslib");
|
|
5
5
|
var __1 = require("../");
|
|
6
6
|
var express = require("express");
|
|
7
|
-
var bodyParser = require("body-parser");
|
|
8
7
|
var register_actions_on_server_1 = require("./register-actions-on-server");
|
|
9
8
|
var register_entities_on_server_1 = require("./register-entities-on-server");
|
|
10
9
|
var JsonEntityFileStorage_1 = require("./JsonEntityFileStorage");
|
|
@@ -29,8 +28,10 @@ function remultExpress(options) {
|
|
|
29
28
|
if (!options.queueStorage) {
|
|
30
29
|
options.queueStorage = new InMemoryQueueStorage();
|
|
31
30
|
}
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
if ((options === null || options === void 0 ? void 0 : options.bodyParser) !== false) {
|
|
32
|
+
app.use(express.json({ limit: options.bodySizeLimit }));
|
|
33
|
+
app.use(express.urlencoded({ extended: true, limit: options.bodySizeLimit }));
|
|
34
|
+
}
|
|
34
35
|
var dataProvider;
|
|
35
36
|
if (typeof options.dataProvider === "function") {
|
|
36
37
|
dataProvider = options.dataProvider();
|
|
@@ -62,7 +63,12 @@ function remultExpress(options) {
|
|
|
62
63
|
bridge.logApiEndPoints = options.logApiEndPoints;
|
|
63
64
|
var apiArea = bridge.addArea(__1.Remult.apiBaseUrl);
|
|
64
65
|
if (!options.disableAutoApi) {
|
|
65
|
-
|
|
66
|
+
var actions = [];
|
|
67
|
+
if (options.entities)
|
|
68
|
+
actions.push.apply(actions, tslib_1.__spread(options.entities));
|
|
69
|
+
if (options.controllers)
|
|
70
|
+
actions.push.apply(actions, tslib_1.__spread(options.controllers));
|
|
71
|
+
register_actions_on_server_1.registerActionsOnServer(apiArea, actions);
|
|
66
72
|
register_entities_on_server_1.registerEntitiesOnServer(apiArea);
|
|
67
73
|
}
|
|
68
74
|
return Object.assign(app, {
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.registerActionsOnServer = void 0;
|
|
4
|
+
var tslib_1 = require("tslib");
|
|
4
5
|
var server_action_1 = require("../src/server-action");
|
|
5
|
-
function registerActionsOnServer(area) {
|
|
6
|
+
function registerActionsOnServer(area, controllers) {
|
|
7
|
+
var e_1, _a, e_2, _b;
|
|
6
8
|
var addAction = function (a) {
|
|
7
9
|
var x = a[server_action_1.serverActionField];
|
|
8
10
|
if (!x) {
|
|
@@ -11,8 +13,38 @@ function registerActionsOnServer(area) {
|
|
|
11
13
|
area.addAction(x);
|
|
12
14
|
};
|
|
13
15
|
server_action_1.actionInfo.runningOnServer = true;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
if (controllers && controllers.length > 0) {
|
|
17
|
+
try {
|
|
18
|
+
for (var controllers_1 = tslib_1.__values(controllers), controllers_1_1 = controllers_1.next(); !controllers_1_1.done; controllers_1_1 = controllers_1.next()) {
|
|
19
|
+
var c = controllers_1_1.value;
|
|
20
|
+
var z = c[server_action_1.classBackendMethodsArray];
|
|
21
|
+
if (z)
|
|
22
|
+
try {
|
|
23
|
+
for (var z_1 = (e_2 = void 0, tslib_1.__values(z)), z_1_1 = z_1.next(); !z_1_1.done; z_1_1 = z_1.next()) {
|
|
24
|
+
var a = z_1_1.value;
|
|
25
|
+
addAction(a);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
29
|
+
finally {
|
|
30
|
+
try {
|
|
31
|
+
if (z_1_1 && !z_1_1.done && (_b = z_1.return)) _b.call(z_1);
|
|
32
|
+
}
|
|
33
|
+
finally { if (e_2) throw e_2.error; }
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
38
|
+
finally {
|
|
39
|
+
try {
|
|
40
|
+
if (controllers_1_1 && !controllers_1_1.done && (_a = controllers_1.return)) _a.call(controllers_1);
|
|
41
|
+
}
|
|
42
|
+
finally { if (e_1) throw e_1.error; }
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
else
|
|
46
|
+
server_action_1.actionInfo.allActions.forEach(function (a) {
|
|
47
|
+
addAction(a);
|
|
48
|
+
});
|
|
17
49
|
}
|
|
18
50
|
exports.registerActionsOnServer = registerActionsOnServer;
|
|
@@ -4,9 +4,11 @@ exports.registerEntitiesOnServer = void 0;
|
|
|
4
4
|
var remult3_1 = require("../src/remult3");
|
|
5
5
|
var context_1 = require("../src/context");
|
|
6
6
|
var data_api_1 = require("../src/data-api");
|
|
7
|
-
function registerEntitiesOnServer(area) {
|
|
7
|
+
function registerEntitiesOnServer(area, entities) {
|
|
8
|
+
if (!entities)
|
|
9
|
+
entities = context_1.allEntities;
|
|
8
10
|
//add Api Entries
|
|
9
|
-
|
|
11
|
+
entities.forEach(function (e) {
|
|
10
12
|
var key = remult3_1.getEntityKey(e);
|
|
11
13
|
if (key != undefined)
|
|
12
14
|
area.add(key, function (c) {
|
|
@@ -6,7 +6,7 @@ export declare class WebSqlDataProvider implements SqlImplementation, __RowsOfDa
|
|
|
6
6
|
rows: {
|
|
7
7
|
[tableName: string]: any;
|
|
8
8
|
};
|
|
9
|
-
constructor(databaseName: string);
|
|
9
|
+
constructor(databaseName: string, databaseSize?: number);
|
|
10
10
|
getLimitSqlSyntax(limit: number, offset: number): string;
|
|
11
11
|
entityIsUsedForTheFirstTime(entity: EntityMetadata): Promise<void>;
|
|
12
12
|
dropTable(entity: EntityMetadata): Promise<void>;
|
|
@@ -7,10 +7,11 @@ var sql_database_1 = require("./sql-database");
|
|
|
7
7
|
var filter_consumer_bridge_to_sql_request_1 = require("../filter/filter-consumer-bridge-to-sql-request");
|
|
8
8
|
//SqlDatabase.LogToConsole = true;
|
|
9
9
|
var WebSqlDataProvider = /** @class */ (function () {
|
|
10
|
-
function WebSqlDataProvider(databaseName) {
|
|
10
|
+
function WebSqlDataProvider(databaseName, databaseSize) {
|
|
11
|
+
if (databaseSize === void 0) { databaseSize = 2 * 1024 * 1024; }
|
|
11
12
|
this.databaseName = databaseName;
|
|
12
13
|
//@ts-ignore
|
|
13
|
-
this.db = window.openDatabase(databaseName, '1.0', databaseName,
|
|
14
|
+
this.db = window.openDatabase(databaseName, '1.0', databaseName, databaseSize);
|
|
14
15
|
}
|
|
15
16
|
WebSqlDataProvider.prototype.getLimitSqlSyntax = function (limit, offset) {
|
|
16
17
|
return ' limit ' + limit + ' offset ' + offset;
|
|
@@ -224,7 +224,7 @@ export declare function isAutoIncrement(f: FieldMetadata): boolean;
|
|
|
224
224
|
export interface StringFieldOptions<entityType = any> extends FieldOptions<entityType, string> {
|
|
225
225
|
maxLength?: number;
|
|
226
226
|
}
|
|
227
|
-
export declare function ValueListFieldType<
|
|
227
|
+
export declare function ValueListFieldType<valueType extends ValueListItem = any>(...options: (ValueListFieldOptions<any, valueType> | ((options: FieldOptions<any, valueType>, remult: Remult) => void))[]): (type: ClassType<valueType>) => void;
|
|
228
228
|
export interface ValueListFieldOptions<entityType, valueType> extends FieldOptions<entityType, valueType> {
|
|
229
229
|
getValues?: () => valueType[];
|
|
230
230
|
}
|
package/src/server-action.d.ts
CHANGED
|
@@ -66,4 +66,5 @@ export declare class ProgressListener {
|
|
|
66
66
|
}
|
|
67
67
|
export declare function prepareArgsToSend(types: any[], args: any[]): any[];
|
|
68
68
|
export declare function prepareReceivedArgs(types: any[], args: any[], remult: Remult, ds: DataProvider, res: DataApiResponse): Promise<any[]>;
|
|
69
|
+
export declare const classBackendMethodsArray: unique symbol;
|
|
69
70
|
export {};
|
package/src/server-action.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.prepareReceivedArgs = exports.prepareArgsToSend = exports.ProgressListener = exports.BackendMethod = exports.Controller = exports.serverActionField = exports.actionInfo = exports.myServerAction = exports.Action = void 0;
|
|
3
|
+
exports.classBackendMethodsArray = exports.prepareReceivedArgs = exports.prepareArgsToSend = exports.ProgressListener = exports.BackendMethod = exports.Controller = exports.serverActionField = exports.actionInfo = exports.myServerAction = exports.Action = void 0;
|
|
4
4
|
var tslib_1 = require("tslib");
|
|
5
5
|
require("reflect-metadata");
|
|
6
6
|
var context_1 = require("./context");
|
|
@@ -216,7 +216,7 @@ function BackendMethod(options) {
|
|
|
216
216
|
});
|
|
217
217
|
});
|
|
218
218
|
};
|
|
219
|
-
|
|
219
|
+
registerAction(target, descriptor);
|
|
220
220
|
descriptor.value[exports.serverActionField] = serverAction_1;
|
|
221
221
|
return descriptor;
|
|
222
222
|
}
|
|
@@ -479,7 +479,7 @@ function BackendMethod(options) {
|
|
|
479
479
|
});
|
|
480
480
|
});
|
|
481
481
|
};
|
|
482
|
-
|
|
482
|
+
registerAction(target.constructor, descriptor);
|
|
483
483
|
descriptor.value[exports.serverActionField] = serverAction;
|
|
484
484
|
return descriptor;
|
|
485
485
|
};
|
|
@@ -488,6 +488,10 @@ exports.BackendMethod = BackendMethod;
|
|
|
488
488
|
var customUndefined = {
|
|
489
489
|
_isUndefined: true
|
|
490
490
|
};
|
|
491
|
+
function registerAction(target, descriptor) {
|
|
492
|
+
(target[exports.classBackendMethodsArray] || (target[exports.classBackendMethodsArray] = [])).push(descriptor.value);
|
|
493
|
+
exports.actionInfo.allActions.push(descriptor.value);
|
|
494
|
+
}
|
|
491
495
|
function isCustomUndefined(x) {
|
|
492
496
|
return x && x._isUndefined;
|
|
493
497
|
}
|
|
@@ -592,3 +596,4 @@ function prepareReceivedArgs(types, args, remult, ds, res) {
|
|
|
592
596
|
});
|
|
593
597
|
}
|
|
594
598
|
exports.prepareReceivedArgs = prepareReceivedArgs;
|
|
599
|
+
exports.classBackendMethodsArray = Symbol('classBackendMethodsArray');
|