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 CHANGED
@@ -1,4 +1,4 @@
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';
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.UUIDField = exports.Field = void 0;
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, "UUIDField", { enumerable: true, get: function () { return remult3_1.UUIDField; } });
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "remult",
3
- "version": "0.9.25",
3
+ "version": "0.9.26",
4
4
  "description": "remult core lib",
5
5
  "homepage": "https://remult.dev/",
6
6
  "repository": {
package/readme.md CHANGED
@@ -1,13 +1,44 @@
1
1
  # Remult
2
2
  ![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg) [![npm version](https://badge.fury.io/js/remult.svg)](https://badge.fury.io/js/remult)
3
3
 
4
- Remult is an unopinionated CRUD framework for fullstack TypeScript development.
4
+ ## What is Remult?
5
5
 
6
- ### Define Entity classes
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('Products', {
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
- ### Find and manipulate data in front end code...
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
- static increasePriceOfTofu(priceIncrease: number) {
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
- await product.save();
66
+ product.save();
28
67
  }
29
68
  ```
30
- ### ...*exactly* the same way as in back end code
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.repo(Product).findFirst({ name:'Tofu' });
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
- ### Secure the API with Fine-grained Authorization
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
- ## Remult handles the REST:
61
- * Secured back-end API endpoints for Entities and back-end methods
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 UUIDField<entityType = any, valueType = any>(...options: (FieldOptions<entityType, valueType> | ((options: FieldOptions<entityType, valueType>, remult: Remult) => void))[]): (target: any, key: any, c?: any) => void;
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.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;
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 UUIDField() {
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.UUIDField = UUIDField;
2139
+ exports.UuidField = UuidField;
2140
2140
  function Field() {
2141
2141
  var options = [];
2142
2142
  for (var _i = 0; _i < arguments.length; _i++) {