@acodeninja/persist 3.0.0-next.12 → 3.0.0-next.14
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 +58 -4
- package/docs/code-quirks.md +6 -6
- package/docs/defining-models.md +61 -0
- package/docs/http.openapi.yml +138 -0
- package/docs/{model-property-types.md → model-properties.md} +37 -35
- package/docs/models-as-properties.md +40 -40
- package/docs/search-queries.md +3 -5
- package/docs/storage-engines.md +15 -32
- package/docs/structured-queries.md +56 -45
- package/docs/transactions.md +6 -7
- package/exports/storage/http.js +3 -0
- package/exports/storage/s3.js +3 -0
- package/jest.config.cjs +8 -12
- package/package.json +2 -2
- package/src/Connection.js +610 -0
- package/src/Persist.js +27 -30
- package/src/Schema.js +166 -0
- package/src/{Query.js → data/FindIndex.js} +37 -22
- package/src/{type → data}/Model.js +14 -30
- package/src/data/Property.js +19 -0
- package/src/data/SearchIndex.js +19 -4
- package/src/{type/complex → data/properties}/ArrayType.js +1 -1
- package/src/{type/simple → data/properties}/BooleanType.js +1 -1
- package/src/{type/complex → data/properties}/CustomType.js +1 -1
- package/src/{type/simple → data/properties}/DateType.js +1 -1
- package/src/{type/simple → data/properties}/NumberType.js +1 -1
- package/src/{type/resolved → data/properties}/ResolvedType.js +3 -2
- package/src/{type/simple → data/properties}/StringType.js +1 -1
- package/src/engine/storage/HTTPStorageEngine.js +149 -253
- package/src/engine/storage/S3StorageEngine.js +108 -195
- package/src/engine/storage/StorageEngine.js +114 -550
- package/exports/engine/storage/file.js +0 -3
- package/exports/engine/storage/http.js +0 -3
- package/exports/engine/storage/s3.js +0 -3
- package/src/SchemaCompiler.js +0 -196
- package/src/Transactions.js +0 -145
- package/src/engine/StorageEngine.js +0 -517
- package/src/engine/storage/FileStorageEngine.js +0 -213
- package/src/type/index.js +0 -32
- /package/src/{type/resolved → data/properties}/SlugType.js +0 -0
- /package/src/{type → data/properties}/Type.js +0 -0
package/README.md
CHANGED
@@ -14,13 +14,67 @@ A JSON based data modelling and persistence library with alternate storage mecha
|
|
14
14
|
|
15
15
|
- Data modelling with relationships
|
16
16
|
- Data validation
|
17
|
-
- Data
|
18
|
-
-
|
19
|
-
|
17
|
+
- Data queries and fuzzy search
|
18
|
+
- Store data using AWS S3 or HTTP APIs
|
19
|
+
|
20
|
+
## Terms
|
21
|
+
|
22
|
+
`model`
|
23
|
+
: Defines the shape of an entity's data within your application.
|
24
|
+
|
25
|
+
`property`
|
26
|
+
: Analogous to a data type, allows defining the type of properties associated with a `model`.
|
27
|
+
|
28
|
+
`connection`
|
29
|
+
: Abstraction layer that establishes a connection to the configured storage engine and supports CRUD and query functionality.
|
30
|
+
|
31
|
+
`engine`
|
32
|
+
: An engine allows a connection to send instructions to a given service, it may support anything from a RESTFul HTTP API to a cloud service like S3 or DynamoDB.
|
33
|
+
|
34
|
+
## Usage
|
35
|
+
|
36
|
+
### Models
|
37
|
+
|
38
|
+
```javascript
|
39
|
+
import Persist from '@acodeninja/persist';
|
40
|
+
|
41
|
+
class Person extends Persist.Model {
|
42
|
+
static {
|
43
|
+
this.name = Persist.Property.String.required;
|
44
|
+
this.dateOfBirth = Persist.Property.Date.required;
|
45
|
+
this.height = Persist.Property.Number.required;
|
46
|
+
this.isStudent = Persist.Property.Boolean.required;
|
47
|
+
}
|
48
|
+
}
|
49
|
+
```
|
50
|
+
|
51
|
+
### Storage
|
52
|
+
|
53
|
+
```javascript
|
54
|
+
import Persist from '@acodeninja/persist';
|
55
|
+
import S3StorageEngine from '@acodeninja/persist/storage/s3';
|
56
|
+
|
57
|
+
const engine = new S3StorageEngine({
|
58
|
+
bucket: 'person-storage',
|
59
|
+
client: new S3Client(),
|
60
|
+
});
|
61
|
+
|
62
|
+
const connection = Persist.registerConnection('people', engine, [Person]);
|
63
|
+
|
64
|
+
const person = new Person({
|
65
|
+
name: 'Joe Bloggs',
|
66
|
+
dateOfBirth: new Date('1993-04-02T00:00:00.000Z'),
|
67
|
+
height: 1.85,
|
68
|
+
isStudent: true,
|
69
|
+
});
|
70
|
+
|
71
|
+
await connection.put(person);
|
72
|
+
```
|
20
73
|
|
21
74
|
## Find out more
|
22
75
|
|
23
|
-
- [
|
76
|
+
- [Defining Models](./docs/defining-models.md)
|
77
|
+
- [Model Property Types](./docs/model-properties)
|
24
78
|
- [Models as Properties](./docs/models-as-properties.md)
|
25
79
|
- [Structured Queries](./docs/structured-queries.md)
|
26
80
|
- [Search Queries](./docs/search-queries.md)
|
package/docs/code-quirks.md
CHANGED
@@ -9,14 +9,14 @@ When you bundle or minify JavaScript code for production, class names are often
|
|
9
9
|
To avoid this problem, you have two options:
|
10
10
|
|
11
11
|
1. Disable class name mangling in your minifier.
|
12
|
-
2. Use `this.
|
12
|
+
2. Use `this.withName(name)` to manually specify the model's name.
|
13
13
|
|
14
14
|
```javascript
|
15
15
|
import Persist from "@acodeninja/persist";
|
16
16
|
|
17
17
|
export class Person extends Persist.Type.Model {
|
18
18
|
static {
|
19
|
-
this.
|
19
|
+
this.withName('Person');
|
20
20
|
this.name = Persist.Type.String.required;
|
21
21
|
}
|
22
22
|
}
|
@@ -60,12 +60,12 @@ When implementing thee `HTTP` engine for code that runs in the web browser, you
|
|
60
60
|
|
61
61
|
```javascript
|
62
62
|
import Persist from "@acodeninja/persist";
|
63
|
-
import HTTPStorageEngine from "@acodeninja/persist/
|
63
|
+
import HTTPStorageEngine from "@acodeninja/persist/storage/http";
|
64
64
|
|
65
|
-
Persist.
|
66
|
-
|
65
|
+
Persist.registerConnection('people', new HTTPStorageEngine({
|
66
|
+
baseUrl: 'https://api.example.com',
|
67
67
|
fetch: fetch.bind(window),
|
68
|
-
});
|
68
|
+
}));
|
69
69
|
```
|
70
70
|
|
71
71
|
This will ensure that `fetch` can access the window context which is required for it to function.
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# Defining Models
|
2
|
+
|
3
|
+
Persist allows defining models as JavaScript classes and uses static attributes for the properties of each model, this allows for validation and type coercion when saving and retrieving data.
|
4
|
+
|
5
|
+
## Defining a Model
|
6
|
+
|
7
|
+
The most basic model is a JavaScript class that extends `Persist.Model`.
|
8
|
+
|
9
|
+
```javascript
|
10
|
+
class BasicModel extends Persist.Model {
|
11
|
+
}
|
12
|
+
```
|
13
|
+
|
14
|
+
A model will always have an `id` property that is randomly generated using [ULID](https://github.com/ulid/spec).
|
15
|
+
|
16
|
+
```javascript
|
17
|
+
const basic = new BasicModel();
|
18
|
+
|
19
|
+
console.log(basic.id) // BasicModel/01ARZ3NDEKTSV4RRFFQ69G5FAV
|
20
|
+
```
|
21
|
+
|
22
|
+
### Adding properties
|
23
|
+
|
24
|
+
Model properties can be added to a model using `Persist.Property.*`.
|
25
|
+
|
26
|
+
```javascript
|
27
|
+
import Persist from '@acodeninja/persist';
|
28
|
+
|
29
|
+
class Person extends Persist.Model {
|
30
|
+
static {
|
31
|
+
this.name = Persist.Property.String.required;
|
32
|
+
this.dateOfBirth = Persist.Property.Date.required;
|
33
|
+
this.height = Persist.Property.Number.required;
|
34
|
+
this.isStudent = Persist.Property.Boolean.required;
|
35
|
+
}
|
36
|
+
}
|
37
|
+
```
|
38
|
+
|
39
|
+
For a full list of available property types see [Model Property Types](./model-properties).
|
40
|
+
|
41
|
+
### Linking Models
|
42
|
+
|
43
|
+
Models can be linked to other models by declaring them as properties.
|
44
|
+
|
45
|
+
```javascript
|
46
|
+
class Address extends Persist.Model {
|
47
|
+
static {
|
48
|
+
this.address = Persist.Property.String.required;
|
49
|
+
this.postcode = Persist.Property.String.required;
|
50
|
+
}
|
51
|
+
}
|
52
|
+
|
53
|
+
class Person extends Persist.Model {
|
54
|
+
static {
|
55
|
+
this.name = Persist.Property.String.required;
|
56
|
+
this.address = Address;
|
57
|
+
}
|
58
|
+
}
|
59
|
+
```
|
60
|
+
|
61
|
+
For a look at the ways that models can be linked check out [Models as Properties](./models-as-properties.md).
|
@@ -0,0 +1,138 @@
|
|
1
|
+
openapi: 3.1.0
|
2
|
+
|
3
|
+
info:
|
4
|
+
title: Persist Generic HTTP API
|
5
|
+
version: 1.0.0
|
6
|
+
|
7
|
+
paths:
|
8
|
+
/{model}/{id}:
|
9
|
+
get:
|
10
|
+
summary: Retrieve an existing model instance.
|
11
|
+
parameters:
|
12
|
+
- in: path
|
13
|
+
name: model
|
14
|
+
schema:
|
15
|
+
type: string
|
16
|
+
required: true
|
17
|
+
description: Name of the model
|
18
|
+
- in: path
|
19
|
+
name: id
|
20
|
+
schema:
|
21
|
+
type: string
|
22
|
+
required: true
|
23
|
+
description: Unique identifier for a model
|
24
|
+
responses:
|
25
|
+
'200':
|
26
|
+
description: Successful update operation
|
27
|
+
content:
|
28
|
+
application/json:
|
29
|
+
schema:
|
30
|
+
$ref: '#/components/schemas/Model'
|
31
|
+
'404':
|
32
|
+
description: Model not found
|
33
|
+
put:
|
34
|
+
summary: Create or update an existing model instance.
|
35
|
+
parameters:
|
36
|
+
- in: path
|
37
|
+
name: model
|
38
|
+
schema:
|
39
|
+
type: string
|
40
|
+
required: true
|
41
|
+
description: Name of the model
|
42
|
+
- in: path
|
43
|
+
name: id
|
44
|
+
schema:
|
45
|
+
type: string
|
46
|
+
required: true
|
47
|
+
description: Unique identifier for a model
|
48
|
+
requestBody:
|
49
|
+
description: Update or create a model instance.
|
50
|
+
content:
|
51
|
+
application/json:
|
52
|
+
schema:
|
53
|
+
$ref: '#/components/schemas/Model'
|
54
|
+
required: true
|
55
|
+
responses:
|
56
|
+
'200':
|
57
|
+
description: Successful update operation
|
58
|
+
'201':
|
59
|
+
description: Successful create operation
|
60
|
+
'422':
|
61
|
+
description: Validation exception
|
62
|
+
delete:
|
63
|
+
summary: Delete an instance of a model
|
64
|
+
parameters:
|
65
|
+
- in: path
|
66
|
+
name: model
|
67
|
+
schema:
|
68
|
+
type: string
|
69
|
+
required: true
|
70
|
+
description: Name of the model
|
71
|
+
- in: path
|
72
|
+
name: id
|
73
|
+
schema:
|
74
|
+
type: string
|
75
|
+
required: true
|
76
|
+
description: Unique identifier for a model
|
77
|
+
responses:
|
78
|
+
'204':
|
79
|
+
description: Successful operation
|
80
|
+
'422':
|
81
|
+
description: Validation exception
|
82
|
+
/{model}:
|
83
|
+
get:
|
84
|
+
summary: Retrieve an index of the current models.
|
85
|
+
parameters:
|
86
|
+
- in: path
|
87
|
+
name: model
|
88
|
+
schema:
|
89
|
+
type: string
|
90
|
+
required: true
|
91
|
+
description: Name of the model
|
92
|
+
responses:
|
93
|
+
'200':
|
94
|
+
description: Successful update operation
|
95
|
+
content:
|
96
|
+
application/json:
|
97
|
+
schema:
|
98
|
+
$ref: '#/components/schemas/ModelIndex'
|
99
|
+
'404':
|
100
|
+
description: Model not found
|
101
|
+
/{model}/search:
|
102
|
+
get:
|
103
|
+
summary: Retrieve a search index of the current models.
|
104
|
+
parameters:
|
105
|
+
- in: path
|
106
|
+
name: model
|
107
|
+
schema:
|
108
|
+
type: string
|
109
|
+
required: true
|
110
|
+
description: Name of the model
|
111
|
+
responses:
|
112
|
+
'200':
|
113
|
+
description: Successful update operation
|
114
|
+
content:
|
115
|
+
application/json:
|
116
|
+
schema:
|
117
|
+
$ref: '#/components/schemas/ModelIndex'
|
118
|
+
'404':
|
119
|
+
description: Model not found
|
120
|
+
|
121
|
+
components:
|
122
|
+
schemas:
|
123
|
+
Model:
|
124
|
+
required:
|
125
|
+
- id
|
126
|
+
type: object
|
127
|
+
additionalProperties: true
|
128
|
+
properties:
|
129
|
+
id:
|
130
|
+
type: string
|
131
|
+
ModelIndex:
|
132
|
+
properties:
|
133
|
+
"{model}/{id}":
|
134
|
+
type: object
|
135
|
+
additionalProperties: true
|
136
|
+
properties:
|
137
|
+
id:
|
138
|
+
type: string
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Model
|
1
|
+
# Model Properties
|
2
2
|
|
3
3
|
Persist uses a type definition for the properties of each model, this allows for validation and type coercion when saving and retrieving data.
|
4
4
|
|
@@ -11,103 +11,105 @@ Properties can be defined on a model by setting static properties to the value o
|
|
11
11
|
```javascript
|
12
12
|
import Persist from '@acodeninja/persist';
|
13
13
|
|
14
|
-
class Person extends Persist.
|
14
|
+
class Person extends Persist.Model {
|
15
15
|
static {
|
16
|
-
this.firstName = Persist.
|
17
|
-
this.lastName = Persist.
|
16
|
+
this.firstName = Persist.Property.String;
|
17
|
+
this.lastName = Persist.Property.String;
|
18
18
|
}
|
19
19
|
}
|
20
20
|
```
|
21
21
|
|
22
|
-
## Simple
|
22
|
+
## Simple Properties
|
23
23
|
|
24
|
-
### `Persist.
|
24
|
+
### `Persist.Property.String`
|
25
25
|
|
26
26
|
Use the `String` type for model properties that should store a [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String). The `String` type also supports the `.required` modifier to ensure that when the model is persisted a value must exist for it.
|
27
27
|
|
28
28
|
```javascript
|
29
29
|
import Persist from '@acodeninja/persist';
|
30
30
|
|
31
|
-
class Person extends Persist.
|
31
|
+
class Person extends Persist.Model {
|
32
32
|
static {
|
33
|
-
this.firstName = Persist.
|
34
|
-
this.lastName = Persist.
|
33
|
+
this.firstName = Persist.Property.String;
|
34
|
+
this.lastName = Persist.Property.String.required;
|
35
35
|
}
|
36
36
|
}
|
37
37
|
```
|
38
38
|
|
39
|
-
### `Persist.
|
39
|
+
### `Persist.Property.Boolean`
|
40
40
|
|
41
41
|
Use the `Boolean` type for model properties that should store a [boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean). The `Boolean` type also supports the `.required` modifier to ensure that when the model is persisted a value must exist for it.
|
42
42
|
|
43
43
|
```javascript
|
44
44
|
import Persist from '@acodeninja/persist';
|
45
45
|
|
46
|
-
class Person extends Persist.
|
46
|
+
class Person extends Persist.Model {
|
47
47
|
static {
|
48
|
-
this.markettingEmailsActive = Persist.
|
49
|
-
this.accountActive = Persist.
|
48
|
+
this.markettingEmailsActive = Persist.Property.Boolean;
|
49
|
+
this.accountActive = Persist.Property.Boolean.required;
|
50
50
|
}
|
51
51
|
}
|
52
52
|
```
|
53
53
|
|
54
|
-
### `Persist.
|
54
|
+
### `Persist.Property.Number`
|
55
55
|
|
56
56
|
Use the `Number` type for model properties that should store a [number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number). The `Number` type also supports the `.required` modifier to ensure that when the model is persisted a value must exist for it.
|
57
57
|
|
58
58
|
```javascript
|
59
59
|
import Persist from '@acodeninja/persist';
|
60
60
|
|
61
|
-
class Person extends Persist.
|
61
|
+
class Person extends Persist.Model {
|
62
62
|
static {
|
63
|
-
this.loginToken = Persist.
|
64
|
-
this.accountId = Persist.
|
63
|
+
this.loginToken = Persist.Property.Number;
|
64
|
+
this.accountId = Persist.Property.Number.required;
|
65
65
|
}
|
66
66
|
}
|
67
67
|
```
|
68
68
|
|
69
|
-
### `Persist.
|
69
|
+
### `Persist.Property.Date`
|
70
70
|
|
71
71
|
Use the `Date` type for model properties that should store a [date](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date). The `Date` type also supports the `.required` modifier to ensure that when the model is persisted a value must exist for it.
|
72
72
|
|
73
|
+
A property of `Date` will serialise to an ISO 8601 date format like `2011-10-05T14:48:00.000Z` when `.toData` is called on a model.
|
74
|
+
|
73
75
|
```javascript
|
74
76
|
import Persist from '@acodeninja/persist';
|
75
77
|
|
76
|
-
class Person extends Persist.
|
78
|
+
class Person extends Persist.Model {
|
77
79
|
static {
|
78
|
-
this.lastLogin = Persist.
|
79
|
-
this.createdAt = Persist.
|
80
|
+
this.lastLogin = Persist.Property.Date;
|
81
|
+
this.createdAt = Persist.Property.Date.required;
|
80
82
|
}
|
81
83
|
}
|
82
84
|
```
|
83
85
|
|
84
|
-
## Complex
|
86
|
+
## Complex Properties
|
85
87
|
|
86
|
-
### `Persist.
|
88
|
+
### `Persist.Property.Array.of(type)`
|
87
89
|
|
88
90
|
Use the `Array` type for model properties that should store an array of another type or model. The `Array` type also supports the `.required` modifier to ensure that when the model is persisted a value must exist for it.
|
89
91
|
|
90
92
|
```javascript
|
91
93
|
import Persist from '@acodeninja/persist';
|
92
94
|
|
93
|
-
class Person extends Persist.
|
95
|
+
class Person extends Persist.Model {
|
94
96
|
static {
|
95
|
-
this.failedLoginAttempts = Persist.
|
96
|
-
this.fullName = Persist.
|
97
|
+
this.failedLoginAttempts = Persist.Property.Array.of(Persist.Property.Date);
|
98
|
+
this.fullName = Persist.Property.Array.of(Persist.Property.String).required;
|
97
99
|
}
|
98
100
|
}
|
99
101
|
```
|
100
102
|
|
101
|
-
### `Persist.
|
103
|
+
### `Persist.Property.Custom.of(schema)`
|
102
104
|
|
103
105
|
Use the `Custom` type for model properties that should store a custom [json-schema draft-07](https://json-schema.org/draft-07/json-schema-hypermedia) object. You can also use any formats defined by the [`avj-formats`](https://ajv.js.org/packages/ajv-formats.html) library. The `Custom` type also supports the `.required` modifier to ensure that when the model is persisted a value must exist for it.
|
104
106
|
|
105
107
|
```javascript
|
106
108
|
import Persist from '@acodeninja/persist';
|
107
109
|
|
108
|
-
class Person extends Persist.
|
110
|
+
class Person extends Persist.Model {
|
109
111
|
static {
|
110
|
-
this.address = Persist.
|
112
|
+
this.address = Persist.Property.Custom.of({
|
111
113
|
type: 'object',
|
112
114
|
additionalProperties: false,
|
113
115
|
required: ['line1', 'city', 'postcode'],
|
@@ -125,21 +127,21 @@ class Person extends Persist.Type.Model {
|
|
125
127
|
}
|
126
128
|
```
|
127
129
|
|
128
|
-
## Resolved
|
130
|
+
## Resolved Properties
|
129
131
|
|
130
132
|
Resolved types are different from other types in that they do not directly store data themselves, rather they perform an action on another property of the model.
|
131
133
|
|
132
|
-
### `Persist.
|
134
|
+
### `Persist.Property.Resolved.Slug.of(property)`
|
133
135
|
|
134
136
|
Use the `Slug` type for model properties that should have a slug version of another properties value. The `Custom` type also supports the `.required` modifier to ensure that when the model is persisted a value must exist for it.
|
135
137
|
|
136
138
|
```javascript
|
137
139
|
import Persist from '@acodeninja/persist';
|
138
140
|
|
139
|
-
class Page extends Persist.
|
141
|
+
class Page extends Persist.Model {
|
140
142
|
static {
|
141
|
-
this.title = Persist.
|
142
|
-
this.slug = Persist.
|
143
|
+
this.title = Persist.Property.String;
|
144
|
+
this.slug = Persist.Property.Resolved.Slug.of('title');
|
143
145
|
}
|
144
146
|
}
|
145
147
|
|
@@ -158,7 +160,7 @@ Models and most types support a modifier, this will alter the validation and per
|
|
158
160
|
Most types support the `.required` modifier, which will alter validation to enforce the presence of the property when saving data.
|
159
161
|
|
160
162
|
```javascript
|
161
|
-
class RequiredStringModel extends Persist.
|
163
|
+
class RequiredStringModel extends Persist.Model {
|
162
164
|
static {
|
163
165
|
this.requiredString = Type.String.required;
|
164
166
|
this.requiredNumber = Type.Number.required;
|
@@ -1,22 +1,22 @@
|
|
1
1
|
# Models as Properties
|
2
2
|
|
3
|
-
In addition to assigning basic types to model properties, you can assign entire models as properties. This allows for the creation of complex relationships between models. For information on using basic types for properties, refer to [model property types](./model-
|
3
|
+
In addition to assigning basic types to model properties, you can assign entire models as properties. This allows for the creation of complex relationships between models. For information on using basic types for properties, refer to [model property types](./model-properties.md).
|
4
4
|
|
5
5
|
We’ll explore different types of relationships between models using examples of `Person` and `Address` models, evolving the definition step by step.
|
6
6
|
|
7
7
|
```javascript
|
8
8
|
import Persist from "@acodeninja/persist";
|
9
9
|
|
10
|
-
export class Person extends Persist.
|
10
|
+
export class Person extends Persist.Model {
|
11
11
|
static {
|
12
|
-
this.name = Persist.
|
12
|
+
this.name = Persist.Property.String.required;
|
13
13
|
}
|
14
14
|
}
|
15
15
|
|
16
|
-
export class Address extends Persist.
|
16
|
+
export class Address extends Persist.Model {
|
17
17
|
static {
|
18
|
-
this.address = Persist.
|
19
|
-
this.postcode = Persist.
|
18
|
+
this.address = Persist.Property.String.required;
|
19
|
+
this.postcode = Persist.Property.String.required;
|
20
20
|
}
|
21
21
|
}
|
22
22
|
```
|
@@ -28,17 +28,17 @@ To define a **one-to-one** relationship between two models, set a static propert
|
|
28
28
|
```javascript
|
29
29
|
import Persist from "@acodeninja/persist";
|
30
30
|
|
31
|
-
export class Person extends Persist.
|
31
|
+
export class Person extends Persist.Model {
|
32
32
|
static {
|
33
|
-
this.name = Persist.
|
33
|
+
this.name = Persist.Property.String.required;
|
34
34
|
this.address = () => Address;
|
35
35
|
}
|
36
36
|
}
|
37
37
|
|
38
|
-
export class Address extends Persist.
|
38
|
+
export class Address extends Persist.Model {
|
39
39
|
static {
|
40
|
-
this.address = Persist.
|
41
|
-
this.postcode = Persist.
|
40
|
+
this.address = Persist.Property.String.required;
|
41
|
+
this.postcode = Persist.Property.String.required;
|
42
42
|
}
|
43
43
|
}
|
44
44
|
```
|
@@ -46,7 +46,7 @@ export class Address extends Persist.Type.Model {
|
|
46
46
|
> [!IMPORTANT]
|
47
47
|
> **Why Use an Arrow Function?**
|
48
48
|
>
|
49
|
-
> The arrow function allows the model to reference another model that may not have been defined yet. Without it, you might encounter an error like `ReferenceError: Cannot access 'Address' before initialization`.
|
49
|
+
> The arrow function allows the model to reference another model that may not have been defined yet. Without it, you might encounter an error like `ReferenceError: Cannot access 'Address' before initialization`. See [Reference Errors](./code-quirks.md#reference-errors).
|
50
50
|
|
51
51
|
### Circular One-to-One Relationships
|
52
52
|
|
@@ -55,41 +55,41 @@ You can extend the previous example by allowing both models to reference each ot
|
|
55
55
|
```javascript
|
56
56
|
import Persist from "@acodeninja/persist";
|
57
57
|
|
58
|
-
export class Person extends Persist.
|
58
|
+
export class Person extends Persist.Model {
|
59
59
|
static {
|
60
|
-
this.name = Persist.
|
60
|
+
this.name = Persist.Property.String.required;
|
61
61
|
this.address = () => Address;
|
62
62
|
}
|
63
63
|
}
|
64
64
|
|
65
|
-
export class Address extends Persist.
|
65
|
+
export class Address extends Persist.Model {
|
66
66
|
static {
|
67
67
|
this.person = () => Person;
|
68
|
-
this.address = Persist.
|
69
|
-
this.postcode = Persist.
|
68
|
+
this.address = Persist.Property.String.required;
|
69
|
+
this.postcode = Persist.Property.String.required;
|
70
70
|
}
|
71
71
|
}
|
72
72
|
```
|
73
73
|
|
74
74
|
## One-to-Many Relationships
|
75
75
|
|
76
|
-
To model a **one-to-many** relationship, use `Persist.
|
76
|
+
To model a **one-to-many** relationship, use `Persist.Property.Array` to store an array of related models. For instance, if a `Person` can have multiple addresses, this is how it would be defined:
|
77
77
|
|
78
78
|
```javascript
|
79
79
|
import Persist from "@acodeninja/persist";
|
80
80
|
|
81
|
-
export class Person extends Persist.
|
81
|
+
export class Person extends Persist.Model {
|
82
82
|
static {
|
83
|
-
this.name = Persist.
|
84
|
-
this.addresses = () => Persist.
|
83
|
+
this.name = Persist.Property.String.required;
|
84
|
+
this.addresses = () => Persist.Property.Array.of(Address);
|
85
85
|
}
|
86
86
|
}
|
87
87
|
|
88
|
-
export class Address extends Persist.
|
88
|
+
export class Address extends Persist.Model {
|
89
89
|
static {
|
90
90
|
this.person = () => Person;
|
91
|
-
this.address = Persist.
|
92
|
-
this.postcode = Persist.
|
91
|
+
this.address = Persist.Property.String.required;
|
92
|
+
this.postcode = Persist.Property.String.required;
|
93
93
|
}
|
94
94
|
}
|
95
95
|
```
|
@@ -103,18 +103,18 @@ In some cases, you may want to model a many-to-many relationship. For example, i
|
|
103
103
|
```javascript
|
104
104
|
import Persist from "@acodeninja/persist";
|
105
105
|
|
106
|
-
export class Person extends Persist.
|
106
|
+
export class Person extends Persist.Model {
|
107
107
|
static {
|
108
|
-
this.name = Persist.
|
109
|
-
this.addresses = () => Persist.
|
108
|
+
this.name = Persist.Property.String.required;
|
109
|
+
this.addresses = () => Persist.Property.Array.of(Address);
|
110
110
|
}
|
111
111
|
}
|
112
112
|
|
113
|
-
export class Address extends Persist.
|
113
|
+
export class Address extends Persist.Model {
|
114
114
|
static {
|
115
|
-
this.people = () => Persist.
|
116
|
-
this.address = Persist.
|
117
|
-
this.postcode = Persist.
|
115
|
+
this.people = () => Persist.Property.Array.of(Person);
|
116
|
+
this.address = Persist.Property.String.required;
|
117
|
+
this.postcode = Persist.Property.String.required;
|
118
118
|
}
|
119
119
|
}
|
120
120
|
```
|
@@ -128,26 +128,26 @@ In more complex scenarios, you may want to capture additional information about
|
|
128
128
|
```javascript
|
129
129
|
import Persist from "@acodeninja/persist";
|
130
130
|
|
131
|
-
export class Person extends Persist.
|
131
|
+
export class Person extends Persist.Model {
|
132
132
|
static {
|
133
|
-
this.name = Persist.
|
134
|
-
this.addresses = () => Persist.
|
133
|
+
this.name = Persist.Property.String.required;
|
134
|
+
this.addresses = () => Persist.Property.Array.of(Abode);
|
135
135
|
}
|
136
136
|
}
|
137
137
|
|
138
|
-
export class Abode extends Persist.
|
138
|
+
export class Abode extends Persist.Model {
|
139
139
|
static {
|
140
|
-
this.moveInDate = Persist.
|
140
|
+
this.moveInDate = Persist.Property.Date.required;
|
141
141
|
this.address = () => Address;
|
142
142
|
this.person = () => Person;
|
143
143
|
}
|
144
144
|
}
|
145
145
|
|
146
|
-
export class Address extends Persist.
|
146
|
+
export class Address extends Persist.Model {
|
147
147
|
static {
|
148
|
-
this.people = () => Persist.
|
149
|
-
this.address = Persist.
|
150
|
-
this.postcode = Persist.
|
148
|
+
this.people = () => Persist.Property.Array.of(Person);
|
149
|
+
this.address = Persist.Property.String.required;
|
150
|
+
this.postcode = Persist.Property.String.required;
|
151
151
|
}
|
152
152
|
}
|
153
153
|
```
|
package/docs/search-queries.md
CHANGED
@@ -36,12 +36,10 @@ To search for any `Person` who lives on station road, the following search query
|
|
36
36
|
|
37
37
|
```javascript
|
38
38
|
import Persist from "@acodeninja/persist";
|
39
|
-
import Person from "./Person";
|
40
|
-
import FileStorageEngine from "@acodeninja/persist/engine/storage/file"
|
41
39
|
|
42
|
-
|
43
|
-
|
44
|
-
|
40
|
+
const connection = Persist.getConnections('people');
|
41
|
+
|
42
|
+
await connection.search(Person, 'station road');
|
45
43
|
```
|
46
44
|
|
47
45
|
This will find all matches for people who live at any address that includes `station road`.
|