remult 0.9.25 → 0.9.26
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/index.d.ts +1 -1
- package/index.js +2 -2
- package/package.json +1 -1
- package/readme.md +96 -34
- package/src/remult3/RepositoryImplementation.d.ts +1 -1
- package/src/remult3/RepositoryImplementation.js +3 -3
package/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { Field,
|
|
1
|
+
export { Field, UuidField, FieldsMetadata, Entity, EntityBase, ControllerBase, FieldRef, Fields, EntityMetadata, EntityOrderBy, EntityFilter, FindOptions, QueryResult, QueryOptions, Repository, FieldType, FindFirstOptions, ComparisonValueFilter, ValueFilter, ContainsStringValueFilter, getFields, EntityRef, getEntityRef, SortSegments, ValueListFieldType, DateOnlyField, JsonField, IntegerField, OmitEB, Paginator, CaptionTransformer } from './src/remult3';
|
|
2
2
|
export { EntityOptions } from './src/entity';
|
|
3
3
|
export { DataProvider, EntityDataProvider, EntityDataProviderFindOptions, ErrorInfo, RestDataProviderHttpProvider } from './src/data-interfaces';
|
|
4
4
|
export { SqlCommand, SqlImplementation, SqlResult } from './src/sql-command';
|
package/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Validators = exports.UrlBuilder = exports.FilterConsumerBridgeToSqlRequest = exports.Filter = exports.CompoundIdField = exports.OneToMany = exports.Sort = exports.IdEntity = exports.EventSource = exports.isBackend = exports.Remult = exports.Allow = exports.ProgressListener = exports.BackendMethod = exports.Controller = exports.JsonDataProvider = exports.SqlDatabase = exports.WebSqlDataProvider = exports.ArrayEntityDataProvider = exports.InMemoryDataProvider = exports.RestDataProvider = exports.CaptionTransformer = exports.IntegerField = exports.JsonField = exports.DateOnlyField = exports.ValueListFieldType = exports.getEntityRef = exports.getFields = exports.FieldType = exports.ControllerBase = exports.EntityBase = exports.Entity = exports.
|
|
3
|
+
exports.Validators = exports.UrlBuilder = exports.FilterConsumerBridgeToSqlRequest = exports.Filter = exports.CompoundIdField = exports.OneToMany = exports.Sort = exports.IdEntity = exports.EventSource = exports.isBackend = exports.Remult = exports.Allow = exports.ProgressListener = exports.BackendMethod = exports.Controller = exports.JsonDataProvider = exports.SqlDatabase = exports.WebSqlDataProvider = exports.ArrayEntityDataProvider = exports.InMemoryDataProvider = exports.RestDataProvider = exports.CaptionTransformer = exports.IntegerField = exports.JsonField = exports.DateOnlyField = exports.ValueListFieldType = exports.getEntityRef = exports.getFields = exports.FieldType = exports.ControllerBase = exports.EntityBase = exports.Entity = exports.UuidField = exports.Field = void 0;
|
|
4
4
|
/*
|
|
5
5
|
* Public API Surface of remult
|
|
6
6
|
*/
|
|
7
7
|
var remult3_1 = require("./src/remult3");
|
|
8
8
|
Object.defineProperty(exports, "Field", { enumerable: true, get: function () { return remult3_1.Field; } });
|
|
9
|
-
Object.defineProperty(exports, "
|
|
9
|
+
Object.defineProperty(exports, "UuidField", { enumerable: true, get: function () { return remult3_1.UuidField; } });
|
|
10
10
|
Object.defineProperty(exports, "Entity", { enumerable: true, get: function () { return remult3_1.Entity; } });
|
|
11
11
|
Object.defineProperty(exports, "EntityBase", { enumerable: true, get: function () { return remult3_1.EntityBase; } });
|
|
12
12
|
Object.defineProperty(exports, "ControllerBase", { enumerable: true, get: function () { return remult3_1.ControllerBase; } });
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -1,13 +1,44 @@
|
|
|
1
1
|
# Remult
|
|
2
2
|
 [](https://badge.fury.io/js/remult)
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
## What is Remult?
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
**Remult** is a fullstack CRUD framework which uses your TypeScript model types to provide:
|
|
7
|
+
|
|
8
|
+
* Secured REST API (highly configurable)
|
|
9
|
+
* Type-safe frontend API client
|
|
10
|
+
* Type-safe backend query builder
|
|
11
|
+
|
|
12
|
+
### Remult :heart: Monorepos
|
|
13
|
+
|
|
14
|
+
Using a `monorepo` approach, with model types shared between frontend and backend code, Remult can enforce data validation and constraints, defined once, on both frontend and REST API level.
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
```sh
|
|
19
|
+
npm i remult
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### Setup API backend using a Node.js Express middleware
|
|
23
|
+
```ts
|
|
24
|
+
import express from 'express';
|
|
25
|
+
import { remultExpress } from 'remult/remult-express';
|
|
26
|
+
|
|
27
|
+
const port = 3001;
|
|
28
|
+
const app = express();
|
|
29
|
+
|
|
30
|
+
app.use(remultExpress());
|
|
31
|
+
|
|
32
|
+
app.listen(port, () => {
|
|
33
|
+
console.log(`Example API listening at http://localhost:${port}`);
|
|
34
|
+
});
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Define model classes
|
|
7
38
|
```ts
|
|
8
39
|
import { Entity, EntityBase, Field } from 'remult';
|
|
9
40
|
|
|
10
|
-
@Entity('
|
|
41
|
+
@Entity('products', {
|
|
11
42
|
allowApiCrud: true
|
|
12
43
|
})
|
|
13
44
|
export class Product extends EntityBase {
|
|
@@ -18,27 +49,79 @@ export class Product extends EntityBase {
|
|
|
18
49
|
unitPrice: number = 0;
|
|
19
50
|
}
|
|
20
51
|
```
|
|
21
|
-
|
|
52
|
+
|
|
53
|
+
### :rocket: API Ready
|
|
54
|
+
```sh
|
|
55
|
+
> curl http://localhost:3001/api/products
|
|
56
|
+
|
|
57
|
+
[{"name":"Tofu","unitPrice":5}]
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Find and manipulate data in type-safe frontend code
|
|
22
61
|
```ts
|
|
23
|
-
|
|
24
|
-
const product = await remult.repo(Product).findFirst({ name:'Tofu' });
|
|
62
|
+
async function increasePriceOfTofu(priceIncrease: number) {
|
|
63
|
+
const product = await remult.repo(Product).findFirst({ name: 'Tofu' });
|
|
25
64
|
|
|
26
65
|
product.unitPrice += priceIncrease;
|
|
27
|
-
|
|
66
|
+
product.save();
|
|
28
67
|
}
|
|
29
68
|
```
|
|
30
|
-
|
|
69
|
+
|
|
70
|
+
### ...*exactly* the same way as in backend code
|
|
31
71
|
```ts
|
|
32
72
|
@BackendMethod({ allowed: Allow.authenticated })
|
|
33
|
-
static increasePriceOfTofu(priceIncrease: number, remult?: Remult) {
|
|
34
|
-
const product = await remult
|
|
73
|
+
static async increasePriceOfTofu(priceIncrease: number, remult?: Remult) {
|
|
74
|
+
const product = await remult!.repo(Product).findFirst({ name: 'Tofu' });
|
|
35
75
|
|
|
36
76
|
product.unitPrice += priceIncrease;
|
|
77
|
+
product.save();
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## :ballot_box_with_check: Data validation and constraints - defined once
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
import { Entity, EntityBase, Field } from 'remult';
|
|
85
|
+
import { Min } from 'class-validator';
|
|
86
|
+
|
|
87
|
+
@Entity('products', {
|
|
88
|
+
allowApiCrud: true
|
|
89
|
+
})
|
|
90
|
+
export class Product extends EntityBase {
|
|
91
|
+
@Field<Product>({
|
|
92
|
+
validate: p => {
|
|
93
|
+
if (p.name.trim().length == 0)
|
|
94
|
+
p.$.name.error = 'required';
|
|
95
|
+
}
|
|
96
|
+
})
|
|
97
|
+
name: string = '';
|
|
98
|
+
|
|
99
|
+
@Field()
|
|
100
|
+
@Min(0)
|
|
101
|
+
unitPrice: number = 0;
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Enforced in frontend:
|
|
106
|
+
```ts
|
|
107
|
+
const product = remult.repo(Product).create();
|
|
108
|
+
|
|
109
|
+
try {
|
|
37
110
|
await product.save();
|
|
38
111
|
}
|
|
112
|
+
catch {
|
|
113
|
+
console.error(product._.error); // Browser console will display - "Name: required"
|
|
114
|
+
}
|
|
39
115
|
```
|
|
40
116
|
|
|
41
|
-
###
|
|
117
|
+
### Enforced in backend:
|
|
118
|
+
```sh
|
|
119
|
+
> curl -d "{""unitPrice"":-1}" -H "Content-Type: application/json" -X POST http://localhost:3001/api/products
|
|
120
|
+
|
|
121
|
+
{"modelState":{"unitPrice":"unitPrice must not be less than 0","name":"required"},"message":"Name: required"}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## :lock: Secure the API with fine-grained authorization
|
|
42
125
|
```ts
|
|
43
126
|
@Entity<Article>('Articles', {
|
|
44
127
|
allowApiRead: true,
|
|
@@ -57,26 +140,5 @@ export class Article extends EntityBase {
|
|
|
57
140
|
}
|
|
58
141
|
```
|
|
59
142
|
|
|
60
|
-
##
|
|
61
|
-
|
|
62
|
-
* CRUD API requests (front end) / database commands (back end)
|
|
63
|
-
* Object-relational mapping
|
|
64
|
-
* Validations
|
|
65
|
-
* Caching
|
|
66
|
-
* Authorization
|
|
67
|
-
|
|
68
|
-
## Installation
|
|
69
|
-
```sh
|
|
70
|
-
npm i remult
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
## API Setup using Express
|
|
74
|
-
```ts
|
|
75
|
-
import * as express from 'express';
|
|
76
|
-
import { remultExpress } from 'remult/remult-express';
|
|
77
|
-
import 'entities';
|
|
78
|
-
|
|
79
|
-
let app = express();
|
|
80
|
-
app.use(remultExpress());
|
|
81
|
-
app.listen(3002, () => console.log("Server started"));
|
|
82
|
-
```
|
|
143
|
+
## Getting started
|
|
144
|
+
The best way to learn Remult is by following a tutorial of a simple fullstack Todo app using [React](https://remult.dev/tutorials/tutorial-react.html) or [Angular](https://remult.dev/tutorials/tutorial-angular.html).
|
|
@@ -201,7 +201,7 @@ export declare function JsonField<entityType = any, valueType = any>(...options:
|
|
|
201
201
|
export declare function DateOnlyField<entityType = any>(...options: (FieldOptions<entityType, Date> | ((options: FieldOptions<entityType, Date>, remult: Remult) => void))[]): (target: any, key: any, c?: any) => void;
|
|
202
202
|
export declare function IntegerField<entityType = any>(...options: (FieldOptions<entityType, Number> | ((options: FieldOptions<entityType, Number>, remult: Remult) => void))[]): (target: any, key: any, c?: any) => void;
|
|
203
203
|
export declare function ValueListFieldType<entityType = any, valueType extends ValueListItem = any>(type: ClassType<valueType>, ...options: (FieldOptions<entityType, valueType> | ((options: FieldOptions<entityType, valueType>, remult: Remult) => void))[]): (target: any) => any;
|
|
204
|
-
export declare function
|
|
204
|
+
export declare function UuidField<entityType = any, valueType = any>(...options: (FieldOptions<entityType, valueType> | ((options: FieldOptions<entityType, valueType>, remult: Remult) => void))[]): (target: any, key: any, c?: any) => void;
|
|
205
205
|
export declare function Field<entityType = any, valueType = any>(...options: (FieldOptions<entityType, valueType> | ((options: FieldOptions<entityType, valueType>, remult: Remult) => void))[]): (target: any, key: any, c?: any) => void;
|
|
206
206
|
export declare function decorateColumnSettings<valueType>(settings: FieldOptions<any, valueType>, remult: Remult): FieldOptions<any, valueType>;
|
|
207
207
|
interface columnInfo {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ControllerBase = exports.EntityBase = exports.Entity = exports.decorateColumnSettings = exports.Field = exports.
|
|
3
|
+
exports.ControllerBase = exports.EntityBase = exports.Entity = exports.decorateColumnSettings = exports.Field = exports.UuidField = exports.ValueListFieldType = exports.IntegerField = exports.DateOnlyField = exports.JsonField = exports.FieldType = exports.columnDefsImpl = exports.buildCaption = exports.CaptionTransformer = exports.getEntityRef = exports.FieldRefImplementation = exports.controllerRefImpl = exports.getControllerRef = exports.getFields = exports.rowHelperImplementation = exports.createOldEntity = exports.columnsOfType = exports.getEntityKey = exports.getEntitySettings = exports.entityInfo_key = exports.entityInfo = exports.__updateEntityBasedOnWhere = exports.RepositoryImplementation = void 0;
|
|
4
4
|
var tslib_1 = require("tslib");
|
|
5
5
|
var column_1 = require("../column");
|
|
6
6
|
var context_1 = require("../context");
|
|
@@ -2126,7 +2126,7 @@ function ValueListFieldType(type) {
|
|
|
2126
2126
|
}], options));
|
|
2127
2127
|
}
|
|
2128
2128
|
exports.ValueListFieldType = ValueListFieldType;
|
|
2129
|
-
function
|
|
2129
|
+
function UuidField() {
|
|
2130
2130
|
var options = [];
|
|
2131
2131
|
for (var _i = 0; _i < arguments.length; _i++) {
|
|
2132
2132
|
options[_i] = arguments[_i];
|
|
@@ -2136,7 +2136,7 @@ function UUIDField() {
|
|
|
2136
2136
|
defaultValue: function () { return uuid_1.v4(); }
|
|
2137
2137
|
}], options));
|
|
2138
2138
|
}
|
|
2139
|
-
exports.
|
|
2139
|
+
exports.UuidField = UuidField;
|
|
2140
2140
|
function Field() {
|
|
2141
2141
|
var options = [];
|
|
2142
2142
|
for (var _i = 0; _i < arguments.length; _i++) {
|