Skip to content

Commit 1da1204

Browse files
authored
Improve dynamics import docs and tests (#135)
* Improve the way dynamic imports are done in tests * Update dynamic import docs * Fix typo
1 parent 8539a49 commit 1da1204

File tree

11 files changed

+149
-33
lines changed

11 files changed

+149
-33
lines changed

docs/schema-concept/circular-references-and-dynamic-types.md

Lines changed: 121 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Sometimes we may need to have a type reference itself in its attributes, or have
44

55
When using dynamic types you can pass a string instead of the type itself in the type definition, this string will contain the type **identifier**, and then pass an object as the _second_ parameter of the `attributes` function with a key `dynamics` where the concrete type for each identifier is declared:
66

7-
```javascript
7+
```js
88
/*
99
* User.js
1010
*/
@@ -13,27 +13,29 @@ const User = attributes(
1313
name: String,
1414
friends: {
1515
type: Array,
16-
itemType: 'User', // << dynamic type with inferred identifier
16+
itemType: 'User', // << identifier
1717
},
1818
favoriteBook: {
19-
type: 'BookStructure', // << dynamic type with custom identifier
19+
type: 'BookStructure', // << identifier
2020
required: true,
2121
},
2222
books: {
23-
type: 'BooksCollection', // << dynamic type with inferred identifier
23+
type: 'BooksCollection', // << identifier
2424
itemType: String,
2525
},
2626
},
2727
{
2828
dynamics: {
29-
/* dynamic types */
29+
/* dynamic types for each identifier */
3030
User: () => User,
3131
BookStructure: () => require('./Book'),
3232
BooksCollection: () => require('./BooksCollection'),
3333
},
3434
}
3535
)(class User {});
3636

37+
module.exports = User;
38+
3739
/*
3840
* Book.js
3941
*/
@@ -46,14 +48,18 @@ const Book = attributes(
4648
{
4749
identifier: 'BookStructure', // << custom identifier
4850
dynamics: {
49-
/* dynamic types */
51+
/* dynamic types for each identifier */
5052
User: () => require('./User'),
5153
BookStructure: () => Book,
5254
},
5355
}
5456
)(class Book {});
57+
58+
module.exports = Book;
5559
```
5660

61+
If you're using `import` instead of `require` (thus having to import the dynamic value in the top-level of the file), go to the [With ES Modules](#with-es-modules) section of this page.
62+
5763
## Dynamic type identifier
5864

5965
The type's identifier has to be same everywhere it's used, and can be defined in two ways:
@@ -75,7 +81,7 @@ const User = attributes(
7581
}
7682
)(
7783
class User {
78-
// ^ the name of this class is the identifier
84+
// ⬑-- the name of this class is the identifier
7985
// so if we change this name to UserEntity, we'll have to change
8086
// both [A] and [B] to use the string 'UserEntity' instead of 'User'
8187
}
@@ -97,15 +103,22 @@ const User = attributes(
97103
{
98104
identifier: 'UserEntity', // << custom identifier
99105
dynamics: {
100-
UserEntity: () => User, // << custom identifier concrete type
106+
// ⬐--- custom identifier concrete type
107+
UserEntity: () => User,
101108
},
102109
}
103110
)(class User {});
104111
```
105112

106-
### Concrete type definition inside `dynamics`
113+
## Concrete type definition inside `dynamics`
114+
115+
For the cases where the dynamic type is in a different file, it's important that the actual needs type to be resolved **inside** the function with the identifier. Let's break it down in two cases:
107116

108-
For the cases where the dynamic type is in a different file, it's important to call the `require` **inside** the function that returns the dynamic type, **not** in the top level of your file:
117+
### With CommonJS modules
118+
119+
When using CommonJS modules you have two possibilities:
120+
121+
1. Putting the `require` call directly inside the concrete type resolution function:
109122

110123
```js
111124
const Book = attributes(
@@ -122,4 +135,102 @@ const Book = attributes(
122135
},
123136
}
124137
)(class Book {});
138+
139+
module.exports = Book;
140+
```
141+
142+
2. Exporting an **object** containing your other structure (instead of exporting the structure itself) and only access it inside the concrete type resolution function:
143+
144+
```js
145+
/*
146+
* User.js
147+
*/
148+
const BookModule = require('./Book');
149+
150+
const User = attributes(
151+
{
152+
name: String,
153+
favoriteBook: {
154+
type: 'Book',
155+
required: true,
156+
},
157+
},
158+
{
159+
dynamics: {
160+
User: () => User,
161+
Book: () => BookModule.Book,
162+
},
163+
}
164+
)(class User {});
165+
166+
exports.User = User;
167+
168+
/*
169+
* Book.js
170+
*/
171+
const UserModule = require('./User');
172+
173+
const Book = attributes(
174+
{
175+
name: String,
176+
owner: 'User',
177+
},
178+
{
179+
dynamics: {
180+
User: () => UserModule.User,
181+
Book: () => Book,
182+
},
183+
}
184+
)(class Book {});
185+
186+
exports.Book = Book;
187+
```
188+
189+
### With ES Modules
190+
191+
When using ES Modules you have a single possibility, which is importing the other structure from the top-level of your file and then returning it from the concrete type resolution function. It's important to note that this **only** works with ES Modules, if you're using CommonJS, check the [With CommonJS modules](#with-commonjs-modules) section.
192+
193+
```javascript
194+
/*
195+
* User.js
196+
*/
197+
import Book from './Book';
198+
199+
const User = attributes(
200+
{
201+
name: String,
202+
favoriteBook: {
203+
type: 'Book',
204+
required: true,
205+
},
206+
},
207+
{
208+
dynamics: {
209+
User: () => User,
210+
Book: () => Book,
211+
},
212+
}
213+
)(class User {});
214+
215+
export default User;
216+
217+
/*
218+
* Book.js
219+
*/
220+
import User from './User';
221+
222+
const Book = attributes(
223+
{
224+
name: String,
225+
owner: 'User',
226+
},
227+
{
228+
dynamics: {
229+
User: () => User,
230+
Book: () => Book,
231+
},
232+
}
233+
)(class Book {});
234+
235+
export default Book;
125236
```

packages/structure/test/fixtures/CircularBook.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
const { attributes } = require('../../src');
2+
const UserModule = require('./CircularUser');
23

34
const Book = attributes(
45
{
@@ -11,10 +12,10 @@ const Book = attributes(
1112
},
1213
{
1314
dynamics: {
14-
User: () => require('./CircularUser'),
15+
User: () => UserModule.User,
1516
Book: () => Book,
1617
},
1718
}
1819
)(class Book {});
1920

20-
module.exports = Book;
21+
exports.Book = Book;

packages/structure/test/fixtures/CircularBookCustomIdentifier.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
const { attributes } = require('../../src');
2+
const UserModule = require('./CircularUserCustomIdentifier');
23

34
const Book = attributes(
45
{
@@ -12,10 +13,10 @@ const Book = attributes(
1213
{
1314
identifier: 'BookEntity',
1415
dynamics: {
15-
UserEntity: () => require('./CircularUserCustomIdentifier'),
16+
UserEntity: () => UserModule.User,
1617
BookEntity: () => Book,
1718
},
1819
}
1920
)(class Book {});
2021

21-
module.exports = Book;
22+
exports.Book = Book;

packages/structure/test/fixtures/CircularUser.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
const { attributes } = require('../../src');
2+
const BookModule = require('./CircularBook');
3+
const BooksCollection = require('./BooksCollection');
24

35
const User = attributes(
46
{
@@ -23,10 +25,10 @@ const User = attributes(
2325
{
2426
dynamics: {
2527
User: () => User,
26-
Book: () => require('./CircularBook'),
27-
BooksCollection: () => require('./BooksCollection'),
28+
Book: () => BookModule.Book,
29+
BooksCollection: () => BooksCollection,
2830
},
2931
}
3032
)(class User {});
3133

32-
module.exports = User;
34+
exports.User = User;

packages/structure/test/fixtures/CircularUserCustomIdentifier.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
const { attributes } = require('../../src');
2+
const BookModule = require('./CircularBookCustomIdentifier');
23

34
const User = attributes(
45
{
@@ -17,9 +18,9 @@ const User = attributes(
1718
identifier: 'UserEntity',
1819
dynamics: {
1920
UserEntity: () => User,
20-
BookEntity: () => require('./CircularBookCustomIdentifier'),
21+
BookEntity: () => BookModule.Book,
2122
},
2223
}
2324
)(class User {});
2425

25-
module.exports = User;
26+
exports.User = User;

packages/structure/test/unit/coercion/array.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ describe('type coercion', () => {
184184
let BooksCollection;
185185

186186
beforeEach(() => {
187-
CircularUser = require('../../fixtures/CircularUser');
187+
CircularUser = require('../../fixtures/CircularUser').User;
188188
BooksCollection = require('../../fixtures/BooksCollection');
189189
});
190190

packages/structure/test/unit/coercion/structure.spec.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,8 @@ describe('type coercion', () => {
101101
let CircularBook;
102102

103103
beforeEach(() => {
104-
CircularUser = require('../../fixtures/CircularUser');
105-
CircularBook = require('../../fixtures/CircularBook');
104+
CircularUser = require('../../fixtures/CircularUser').User;
105+
CircularBook = require('../../fixtures/CircularBook').Book;
106106
});
107107

108108
describe('when there are not allowed nullable attributes', () => {

packages/structure/test/unit/instanceAndUpdate.spec.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -355,8 +355,8 @@ describe('instantiating a structure with dynamic attribute types', () => {
355355
let CircularBook;
356356

357357
beforeEach(() => {
358-
CircularUser = require('../fixtures/CircularUser');
359-
CircularBook = require('../fixtures/CircularBook');
358+
CircularUser = require('../fixtures/CircularUser').User;
359+
CircularBook = require('../fixtures/CircularBook').Book;
360360
});
361361

362362
it('creates instance properly', () => {
@@ -490,8 +490,8 @@ describe('updating a structure with dynamic attribute types', () => {
490490
let CircularBook;
491491

492492
beforeEach(() => {
493-
CircularUser = require('../fixtures/CircularUser');
494-
CircularBook = require('../fixtures/CircularBook');
493+
CircularUser = require('../fixtures/CircularUser').User;
494+
CircularBook = require('../fixtures/CircularBook').Book;
495495
});
496496

497497
it('updates instance attribute when assigned a new value', () => {

packages/structure/test/unit/serialization/nestedStructure.spec.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@ describe('serialization', () => {
8181
let CircularBook;
8282

8383
beforeEach(() => {
84-
CircularUser = require('../../fixtures/CircularUser');
85-
CircularBook = require('../../fixtures/CircularBook');
84+
CircularUser = require('../../fixtures/CircularUser').User;
85+
CircularBook = require('../../fixtures/CircularBook').Book;
8686
});
8787

8888
describe('when all data is present', () => {

packages/structure/test/unit/validation/array.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ describe('validation', () => {
226226
let CircularUser;
227227

228228
beforeEach(() => {
229-
CircularUser = require('../../fixtures/CircularUser');
229+
CircularUser = require('../../fixtures/CircularUser').User;
230230
});
231231

232232
describe('when nested value is present', () => {

0 commit comments

Comments
 (0)