@quatrain/core 0.5.0 → 0.5.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 +103 -2
- package/lib/backends/middlewares/InjectMetaMiddleware.d.ts +3 -2
- package/lib/backends/middlewares/InjectMetaMiddleware.js +3 -3
- package/lib/components/DataObject.d.ts +1 -1
- package/lib/components/DataObject.js +14 -2
- package/lib/components/ObjectUri.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -11,13 +11,114 @@ and storage.
|
|
|
11
11
|
|
|
12
12
|
## How to install
|
|
13
13
|
|
|
14
|
-
```
|
|
14
|
+
```bash
|
|
15
15
|
yarn install @quatrain/core
|
|
16
16
|
```
|
|
17
17
|
|
|
18
18
|
Quatrain Core comes with a built-in Mock backend adapter. Other adapters are available in
|
|
19
19
|
different packages. For example, a Google Firestore adapter is available:
|
|
20
20
|
|
|
21
|
-
```
|
|
21
|
+
```bash
|
|
22
22
|
yarn install @quatrain/backend-firestore
|
|
23
23
|
```
|
|
24
|
+
|
|
25
|
+
## How to use
|
|
26
|
+
|
|
27
|
+
### Setup
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
import { Core } from '@quatrain/core'
|
|
31
|
+
|
|
32
|
+
Core.addBackend(myAdapter, 'myDB', true)
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Create a model
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
import { BaseObjectCore } from '@quatrain/core'
|
|
39
|
+
|
|
40
|
+
export type Cat = {
|
|
41
|
+
name: string
|
|
42
|
+
color: `#${string}`
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export class CatCore extends BaseObjectCore {
|
|
46
|
+
static COLLECTION = 'cats'
|
|
47
|
+
|
|
48
|
+
static PROPERTIES = [
|
|
49
|
+
{
|
|
50
|
+
name: 'name',
|
|
51
|
+
type: Property.STRING,
|
|
52
|
+
minLength: 1,
|
|
53
|
+
maxLength: 32,
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
name: 'color',
|
|
57
|
+
type: Property.STRING,
|
|
58
|
+
minLength: 4,
|
|
59
|
+
maxLength: 7,
|
|
60
|
+
},
|
|
61
|
+
]
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Instantiate a model
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
const catData: Cat = {
|
|
69
|
+
name: 'Garfield',
|
|
70
|
+
color: '#ffa502',
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const garfield = CatCore.fromObject(catData)
|
|
74
|
+
|
|
75
|
+
console.log(garfield.name)
|
|
76
|
+
// > "Garfield"
|
|
77
|
+
console.log(garfield.color)
|
|
78
|
+
// > "#ffa502"
|
|
79
|
+
console.log(garfield.core)
|
|
80
|
+
// > CatCore { ... }
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Interact with backend
|
|
84
|
+
|
|
85
|
+
```ts
|
|
86
|
+
// Let's save Garfield in our database
|
|
87
|
+
garfield.core.save()
|
|
88
|
+
|
|
89
|
+
// Now, let's retrieve Garfield in the database
|
|
90
|
+
const persistedGarfield = await CatCore.fromBackend('garfield')
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Using repositories
|
|
94
|
+
|
|
95
|
+
You can use repositories as an alternative way to persist and retrieve models in your backend.
|
|
96
|
+
|
|
97
|
+
This module provides a BaseRepository class that you can extend and override to apply your business logic when doing backend operations.
|
|
98
|
+
|
|
99
|
+
Let's create a repository for our Cat model, that prevents us from deleting a cat.
|
|
100
|
+
|
|
101
|
+
```ts
|
|
102
|
+
import { Core, BackendInterface, BaseRepository } from '@quatrain/core'
|
|
103
|
+
|
|
104
|
+
export default class CatRepository extends BaseRepository<Cat> {
|
|
105
|
+
constructor(backendAdapter: BackendInterface = Core.getBackend()) {
|
|
106
|
+
super(CatCore, backendAdapter)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
async delete(uid: string) {
|
|
110
|
+
throw Error("Don't delete the cats!")
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Now, let's use our new CatRepository.
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
const repository = new CatRepository()
|
|
119
|
+
|
|
120
|
+
repository.create(garfield)
|
|
121
|
+
repository.read('garfield')
|
|
122
|
+
repository.update(persistedGarfield)
|
|
123
|
+
repository.delete('garfield') // Will throw "Don't delete the cats!"
|
|
124
|
+
```
|
|
@@ -2,11 +2,12 @@ import { DataObjectClass } from '../../components';
|
|
|
2
2
|
import { BackendAction } from '../../Backend';
|
|
3
3
|
import { User } from '../../components/User';
|
|
4
4
|
import Middleware from './Middleware';
|
|
5
|
+
import { Proxy } from '../../components/types/ProxyConstructor';
|
|
5
6
|
export interface InjectMetaMiddlewareParams {
|
|
6
|
-
user: User
|
|
7
|
+
user: Proxy<User>;
|
|
7
8
|
}
|
|
8
9
|
export declare class InjectMetaMiddleware implements Middleware {
|
|
9
|
-
protected _user: User
|
|
10
|
+
protected _user: Proxy<User>;
|
|
10
11
|
constructor(params: InjectMetaMiddlewareParams);
|
|
11
12
|
execute(dataObject: DataObjectClass<any>, action: BackendAction): void;
|
|
12
13
|
}
|
|
@@ -10,15 +10,15 @@ class InjectMetaMiddleware {
|
|
|
10
10
|
switch (action) {
|
|
11
11
|
// add properties existence validation
|
|
12
12
|
case Backend_1.BackendAction.CREATE:
|
|
13
|
-
dataObject.set('createdBy', this._user);
|
|
13
|
+
dataObject.set('createdBy', this._user.core.dataObject.uri);
|
|
14
14
|
dataObject.set('createdAt', Date.now());
|
|
15
15
|
break;
|
|
16
16
|
case Backend_1.BackendAction.UPDATE:
|
|
17
|
-
dataObject.set('updatedBy', this._user);
|
|
17
|
+
dataObject.set('updatedBy', this._user.core.dataObject.uri);
|
|
18
18
|
dataObject.set('updatedAt', Date.now());
|
|
19
19
|
break;
|
|
20
20
|
case Backend_1.BackendAction.DELETE:
|
|
21
|
-
dataObject.set('deletedBy', this._user);
|
|
21
|
+
dataObject.set('deletedBy', this._user.core.dataObject.uri);
|
|
22
22
|
dataObject.set('deletedAt', Date.now());
|
|
23
23
|
break;
|
|
24
24
|
default:
|
|
@@ -65,7 +65,7 @@ export declare class DataObject implements DataObjectClass<any> {
|
|
|
65
65
|
set uid(uid: string | undefined);
|
|
66
66
|
get uid(): string | undefined;
|
|
67
67
|
get data(): any;
|
|
68
|
-
set uri(uri:
|
|
68
|
+
set uri(uri: ObjectUri);
|
|
69
69
|
get uri(): ObjectUri;
|
|
70
70
|
get class(): any;
|
|
71
71
|
has(key: string): boolean;
|
|
@@ -85,7 +85,19 @@ class DataObject {
|
|
|
85
85
|
if (this._populated === false) {
|
|
86
86
|
for (const key in data) {
|
|
87
87
|
if (Reflect.get(this._properties, key)) {
|
|
88
|
-
|
|
88
|
+
const val = data[key];
|
|
89
|
+
if (val &&
|
|
90
|
+
typeof val === 'object' &&
|
|
91
|
+
'ref' in val &&
|
|
92
|
+
typeof val.ref == 'string' &&
|
|
93
|
+
'label' in val &&
|
|
94
|
+
typeof val.label == 'string') {
|
|
95
|
+
const { ref, label } = val;
|
|
96
|
+
Reflect.get(this._properties, key).set(new ObjectUri_1.ObjectUri(ref, label));
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
Reflect.get(this._properties, key).set(data[key]);
|
|
100
|
+
}
|
|
89
101
|
}
|
|
90
102
|
}
|
|
91
103
|
this._populated = true;
|
|
@@ -141,7 +153,7 @@ class DataObject {
|
|
|
141
153
|
return this._properties;
|
|
142
154
|
}
|
|
143
155
|
set uri(uri) {
|
|
144
|
-
this._objectUri = uri
|
|
156
|
+
this._objectUri = uri;
|
|
145
157
|
if (this._objectUri.collection !== ObjectUri_1.ObjectUri.MISSING_COLLECTION) {
|
|
146
158
|
this._persisted = true;
|
|
147
159
|
}
|
|
@@ -19,7 +19,7 @@ class ObjectUri {
|
|
|
19
19
|
this._label = '';
|
|
20
20
|
this._str = str;
|
|
21
21
|
this._label = label;
|
|
22
|
-
if (str.
|
|
22
|
+
if (str.includes(':')) {
|
|
23
23
|
const [backend, path] = str.split(':');
|
|
24
24
|
this._backend = backend || Core_1.Core.defaultBackend;
|
|
25
25
|
this._path = path;
|