@acodeninja/persist 3.0.0-next.2 → 3.0.0-next.21

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.
Files changed (41) hide show
  1. package/README.md +60 -4
  2. package/docs/code-quirks.md +6 -6
  3. package/docs/defining-models.md +61 -0
  4. package/docs/http.openapi.yml +138 -0
  5. package/docs/{model-property-types.md → model-properties.md} +37 -35
  6. package/docs/models-as-properties.md +40 -40
  7. package/docs/search-queries.md +3 -5
  8. package/docs/storage-engines.md +19 -35
  9. package/docs/structured-queries.md +56 -45
  10. package/docs/transactions.md +6 -7
  11. package/exports/storage/http.js +3 -0
  12. package/exports/storage/s3.js +3 -0
  13. package/jest.config.cjs +8 -12
  14. package/package.json +2 -2
  15. package/src/Connection.js +631 -0
  16. package/src/Persist.js +29 -30
  17. package/src/Schema.js +175 -0
  18. package/src/{Query.js → data/FindIndex.js} +40 -24
  19. package/src/{type → data}/Model.js +41 -26
  20. package/src/data/Property.js +19 -0
  21. package/src/data/SearchIndex.js +106 -0
  22. package/src/{type/complex → data/properties}/ArrayType.js +1 -1
  23. package/src/{type/simple → data/properties}/BooleanType.js +1 -1
  24. package/src/{type/complex → data/properties}/CustomType.js +1 -1
  25. package/src/{type/simple → data/properties}/DateType.js +1 -1
  26. package/src/{type/simple → data/properties}/NumberType.js +1 -1
  27. package/src/{type/resolved → data/properties}/ResolvedType.js +3 -2
  28. package/src/{type/simple → data/properties}/StringType.js +1 -1
  29. package/src/{type → data/properties}/Type.js +8 -0
  30. package/src/engine/storage/HTTPStorageEngine.js +149 -253
  31. package/src/engine/storage/S3StorageEngine.js +108 -195
  32. package/src/engine/storage/StorageEngine.js +114 -550
  33. package/exports/engine/storage/file.js +0 -3
  34. package/exports/engine/storage/http.js +0 -3
  35. package/exports/engine/storage/s3.js +0 -3
  36. package/src/SchemaCompiler.js +0 -192
  37. package/src/Transactions.js +0 -145
  38. package/src/engine/StorageEngine.js +0 -250
  39. package/src/engine/storage/FileStorageEngine.js +0 -213
  40. package/src/type/index.js +0 -32
  41. /package/src/{type/resolved → data/properties}/SlugType.js +0 -0
package/README.md CHANGED
@@ -9,18 +9,74 @@ A JSON based data modelling and persistence library with alternate storage mecha
9
9
 
10
10
  [![DeepSource](https://app.deepsource.com/gh/acodeninja/persist.svg/?label=active+issues&show_trend=true&token=Vd8_PJuRwwoq4_uBJ0_ymc06)](https://app.deepsource.com/gh/acodeninja/persist/)
11
11
  [![DeepSource](https://app.deepsource.com/gh/acodeninja/persist.svg/?label=code+coverage&show_trend=true&token=Vd8_PJuRwwoq4_uBJ0_ymc06)](https://app.deepsource.com/gh/acodeninja/persist/)
12
+ ![CodeRabbit PR Reviews](https://img.shields.io/coderabbit/prs/github/acodeninja/persist?utm_source=oss&utm_medium=github&utm_campaign=acodeninja%2Fpersist&labelColor=171717&color=FF570A&link=https%3A%2F%2Fcoderabbit.ai&label=CodeRabbit+Reviews)
12
13
 
13
14
  ## Features
14
15
 
15
16
  - Data modelling with relationships
16
17
  - Data validation
17
- - Data querying
18
- - Fuzzy search
19
- - Storage with: S3, HTTP and Filesystem
18
+ - Data queries and fuzzy search
19
+ - Store data using AWS S3 or HTTP APIs
20
+
21
+ ## Terms
22
+
23
+ `model`
24
+ : Defines the shape of an entity's data within your application.
25
+
26
+ `property`
27
+ : Analogous to a data type, allows defining the type of properties associated with a `model`.
28
+
29
+ `connection`
30
+ : Abstraction layer that establishes a connection to the configured storage engine and supports CRUD and query functionality.
31
+
32
+ `engine`
33
+ : 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.
34
+
35
+ ## Usage
36
+
37
+ ### Models
38
+
39
+ ```javascript
40
+ import Persist from '@acodeninja/persist';
41
+
42
+ class Person extends Persist.Model {
43
+ static {
44
+ this.name = Persist.Property.String.required;
45
+ this.dateOfBirth = Persist.Property.Date.required;
46
+ this.height = Persist.Property.Number.required;
47
+ this.isStudent = Persist.Property.Boolean.required;
48
+ }
49
+ }
50
+ ```
51
+
52
+ ### Storage
53
+
54
+ ```javascript
55
+ import Persist from '@acodeninja/persist';
56
+ import {S3Client} from "@aws-sdk/client-s3";
57
+ import S3StorageEngine from '@acodeninja/persist/storage/s3';
58
+
59
+ const engine = new S3StorageEngine({
60
+ bucket: 'person-storage',
61
+ client: new S3Client(),
62
+ });
63
+
64
+ const connection = Persist.registerConnection('people', engine, [Person]);
65
+
66
+ const person = new Person({
67
+ name: 'Joe Bloggs',
68
+ dateOfBirth: new Date('1993-04-02T00:00:00.000Z'),
69
+ height: 1.85,
70
+ isStudent: true,
71
+ });
72
+
73
+ await connection.put(person);
74
+ ```
20
75
 
21
76
  ## Find out more
22
77
 
23
- - [Model Property Types](./docs/model-property-types.md)
78
+ - [Defining Models](./docs/defining-models.md)
79
+ - [Model Property Types](./docs/model-properties.md)
24
80
  - [Models as Properties](./docs/models-as-properties.md)
25
81
  - [Structured Queries](./docs/structured-queries.md)
26
82
  - [Search Queries](./docs/search-queries.md)
@@ -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.setMinifiedName(name)` to manually specify the model's name.
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.setMinifiedName('Person');
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/engine/storage/http";
63
+ import HTTPStorageEngine from "@acodeninja/persist/storage/http";
64
64
 
65
- Persist.addEngine('remote', HTTPStorageEngine, {
66
- host: 'https://api.example.com',
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 Property Types
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.Type.Model {
14
+ class Person extends Persist.Model {
15
15
  static {
16
- this.firstName = Persist.Type.String;
17
- this.lastName = Persist.Type.String;
16
+ this.firstName = Persist.Property.String;
17
+ this.lastName = Persist.Property.String;
18
18
  }
19
19
  }
20
20
  ```
21
21
 
22
- ## Simple Types
22
+ ## Simple Properties
23
23
 
24
- ### `Persist.Type.String`
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.Type.Model {
31
+ class Person extends Persist.Model {
32
32
  static {
33
- this.firstName = Persist.Type.String;
34
- this.lastName = Persist.Type.String.required;
33
+ this.firstName = Persist.Property.String;
34
+ this.lastName = Persist.Property.String.required;
35
35
  }
36
36
  }
37
37
  ```
38
38
 
39
- ### `Persist.Type.Boolean`
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.Type.Model {
46
+ class Person extends Persist.Model {
47
47
  static {
48
- this.markettingEmailsActive = Persist.Type.Boolean;
49
- this.accountActive = Persist.Type.Boolean.required;
48
+ this.markettingEmailsActive = Persist.Property.Boolean;
49
+ this.accountActive = Persist.Property.Boolean.required;
50
50
  }
51
51
  }
52
52
  ```
53
53
 
54
- ### `Persist.Type.Number`
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.Type.Model {
61
+ class Person extends Persist.Model {
62
62
  static {
63
- this.loginToken = Persist.Type.Number;
64
- this.accountId = Persist.Type.Number.required;
63
+ this.loginToken = Persist.Property.Number;
64
+ this.accountId = Persist.Property.Number.required;
65
65
  }
66
66
  }
67
67
  ```
68
68
 
69
- ### `Persist.Type.Date`
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.Type.Model {
78
+ class Person extends Persist.Model {
77
79
  static {
78
- this.lastLogin = Persist.Type.Date;
79
- this.createdAt = Persist.Type.Date.required;
80
+ this.lastLogin = Persist.Property.Date;
81
+ this.createdAt = Persist.Property.Date.required;
80
82
  }
81
83
  }
82
84
  ```
83
85
 
84
- ## Complex Types
86
+ ## Complex Properties
85
87
 
86
- ### `Persist.Type.Array.of(type)`
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.Type.Model {
95
+ class Person extends Persist.Model {
94
96
  static {
95
- this.failedLoginAttempts = Persist.Type.Array.of(Persist.Type.Date);
96
- this.fullName = Persist.Type.Array.of(Persist.Type.String).required;
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.Type.Custom.of(schema)`
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.Type.Model {
110
+ class Person extends Persist.Model {
109
111
  static {
110
- this.address = Persist.Type.Custom.of({
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 Types
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.Type.Resolved.Slug.of(property)`
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.Type.Model {
141
+ class Page extends Persist.Model {
140
142
  static {
141
- this.title = Persist.Type.String;
142
- this.slug = Persist.Type.Resolved.Slug.of('title');
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.Type.Model {
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-property-types.md).
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.Type.Model {
10
+ export class Person extends Persist.Model {
11
11
  static {
12
- this.name = Persist.Type.String.required;
12
+ this.name = Persist.Property.String.required;
13
13
  }
14
14
  }
15
15
 
16
- export class Address extends Persist.Type.Model {
16
+ export class Address extends Persist.Model {
17
17
  static {
18
- this.address = Persist.Type.String.required;
19
- this.postcode = Persist.Type.String.required;
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.Type.Model {
31
+ export class Person extends Persist.Model {
32
32
  static {
33
- this.name = Persist.Type.String.required;
33
+ this.name = Persist.Property.String.required;
34
34
  this.address = () => Address;
35
35
  }
36
36
  }
37
37
 
38
- export class Address extends Persist.Type.Model {
38
+ export class Address extends Persist.Model {
39
39
  static {
40
- this.address = Persist.Type.String.required;
41
- this.postcode = Persist.Type.String.required;
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.Type.Model {
58
+ export class Person extends Persist.Model {
59
59
  static {
60
- this.name = Persist.Type.String.required;
60
+ this.name = Persist.Property.String.required;
61
61
  this.address = () => Address;
62
62
  }
63
63
  }
64
64
 
65
- export class Address extends Persist.Type.Model {
65
+ export class Address extends Persist.Model {
66
66
  static {
67
67
  this.person = () => Person;
68
- this.address = Persist.Type.String.required;
69
- this.postcode = Persist.Type.String.required;
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.Type.Array` to store an array of related models. For instance, if a `Person` can have multiple addresses, this is how it would be defined:
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.Type.Model {
81
+ export class Person extends Persist.Model {
82
82
  static {
83
- this.name = Persist.Type.String.required;
84
- this.addresses = () => Persist.Type.Array.of(Address);
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.Type.Model {
88
+ export class Address extends Persist.Model {
89
89
  static {
90
90
  this.person = () => Person;
91
- this.address = Persist.Type.String.required;
92
- this.postcode = Persist.Type.String.required;
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.Type.Model {
106
+ export class Person extends Persist.Model {
107
107
  static {
108
- this.name = Persist.Type.String.required;
109
- this.addresses = () => Persist.Type.Array.of(Address);
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.Type.Model {
113
+ export class Address extends Persist.Model {
114
114
  static {
115
- this.people = () => Persist.Type.Array.of(Person);
116
- this.address = Persist.Type.String.required;
117
- this.postcode = Persist.Type.String.required;
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.Type.Model {
131
+ export class Person extends Persist.Model {
132
132
  static {
133
- this.name = Persist.Type.String.required;
134
- this.addresses = () => Persist.Type.Array.of(Abode);
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.Type.Model {
138
+ export class Abode extends Persist.Model {
139
139
  static {
140
- this.moveInDate = Persist.Type.Date.required;
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.Type.Model {
146
+ export class Address extends Persist.Model {
147
147
  static {
148
- this.people = () => Persist.Type.Array.of(Person);
149
- this.address = Persist.Type.String.required;
150
- this.postcode = Persist.Type.String.required;
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
  ```
@@ -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
- FileStorageEngine
43
- .configure(configuration)
44
- .search(Person, 'station road');
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`.