11import { Store } from 'vuex'
2+ import { error } from '../support/Utils'
23import { Constructor } from '../types'
34import { Element , Item , Collection , Collections } from '../data/Data'
45import { Model } from '../model/Model'
@@ -9,7 +10,14 @@ import {
910 OrderDirection
1011} from '../query/Options'
1112
12- export class Repository < M extends Model > {
13+ export class Repository < M extends Model = Model > {
14+ /**
15+ * A special flag to indicate if this is the repository class or not. It's
16+ * used when retrieving repository instance from `store.$repo()` method to
17+ * determine whether the passed in class is either a repository or a model.
18+ */
19+ static _isRepository : boolean = true
20+
1321 /**
1422 * The store instance.
1523 */
@@ -18,21 +26,78 @@ export class Repository<M extends Model> {
1826 /**
1927 * The model instance.
2028 */
21- protected model : M
29+ protected model ! : M
30+
31+ /**
32+ * The model object to be used for the custom repository.
33+ */
34+ use ?: typeof Model
2235
2336 /**
2437 * Create a new Repository instance.
2538 */
26- constructor ( store : Store < any > , model : Constructor < M > ) {
39+ constructor ( store : Store < any > ) {
2740 this . store = store
28- this . model = new model ( ) . $setStore ( store )
41+ }
42+
43+ /**
44+ * Initialize the repository by setting the model instance.
45+ */
46+ initialize ( model ?: Constructor < M > ) : this {
47+ // If there's a model passed in, just use that and return immediately.
48+ if ( model ) {
49+ this . model = new model ( ) . $setStore ( this . store )
50+
51+ return this
52+ }
53+
54+ // If no model was passed to the initializer, that means the user has
55+ // passed repository to the `store.$repo` method instead of a model.
56+ // In this case, we'll check if the user has set model to the `use`
57+ // property and instantiate that.
58+ if ( this . use ) {
59+ this . model = ( new this . use ( ) as M ) . $setStore ( this . store )
60+
61+ return this
62+ }
63+
64+ // Else just return for now. If the user tries to call methods that require
65+ // a model, the error will be thrown at that time.
66+ return this
67+ }
68+
69+ /**
70+ * Get the model instance. If the model is not registered to the repository,
71+ * it will throw an error. It happens when users use a custom repository
72+ * without setting `use` property.
73+ */
74+ getModel ( ) : M {
75+ if ( ! this . model ) {
76+ error ( [
77+ 'The model is not registered. Please define the model to be used at' ,
78+ '`use` property of the repository class.'
79+ ] )
80+ }
81+
82+ return this . model
83+ }
84+
85+ /**
86+ * Create a new repository with the given model.
87+ */
88+ repo < M extends Model > ( model : Constructor < M > ) : Repository < M >
89+ repo < R extends Repository < any > > ( repository : Constructor < R > ) : R
90+ repo ( modelOrRepository : any ) : any {
91+ return modelOrRepository . _isRepository
92+ ? new modelOrRepository ( this . store ) . initialize ( )
93+ : new Repository ( this . store ) . initialize ( modelOrRepository )
2994 }
3095
3196 /**
3297 * Create a new Query instance.
3398 */
3499 query ( ) : Query < M > {
35- return new Query ( this . store , this . model )
100+ return new Query ( this . store , this . getModel ( ) )
36101 }
37102
38103 /**
@@ -91,7 +156,7 @@ export class Repository<M extends Model> {
91156 * the store instance to support model instance methods in SSR environment.
92157 */
93158 make ( attributes ?: Element ) : M {
94- return this . model . $newInstance ( attributes , {
159+ return this . getModel ( ) . $newInstance ( attributes , {
95160 relations : false
96161 } )
97162 }
0 commit comments