This repository was archived by the owner on Feb 25, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathindex.ts
More file actions
162 lines (146 loc) · 6.45 KB
/
index.ts
File metadata and controls
162 lines (146 loc) · 6.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
import { QuerySet, QuerySetSelector } from './queryset';
import { ORM, Model } from 'redux-orm';
/**
* Select data from redux-orm
*
* This call replicates the API from redux-orm so the query syntax is the same.
* Only "read" functions are available: all, get, hasId, withId
*/
export class ORMSelector {
/**
* The name of the model that we are querying
*/
modelName: string;
/**
* @param string modelName The name of the model to query
*/
constructor(model: Object | string) {
if (typeof model === 'function' && model['modelName']) {
this.modelName = model['modelName'];
} else if(typeof model === 'string') {
this.modelName = model;
} else {
throw new Error('A valid model name (string) or model (object) must be provided to selectData');
}
}
/**
* Build a selector that queries the ORM
* See the `all` function from http://tommikaikkonen.github.io/redux-orm/Model.html
*
* @return QuerySetSelector A function that gets all model instances from the state and allows further filtering
*/
all(): QuerySetSelector {
return QuerySet(this.getModelFromState.bind(this));
}
/**
* Build a selector that gets a model instance that matches properties in the `query` object
* See the `get` function from http://tommikaikkonen.github.io/redux-orm/Model.html
*
* If there is no instance matching the properties, `null` will be returned and no exception will be thrown (contrary to the behavior of redux-orm). This helps dealing with these cases in Angular.
* Warning: if there are multiple instances matching the properties, we will throw an error just like redux-orm does.
*
* @param object query The properties used to match a model instance
*
* @return function A function that gets a model instance from the state
*/
get(query): (state: any) => Model {
return (state) => {
try {
return this.getModelFromState(state).get(query);
} catch(error) {
if (error.message === 'Model instance not found when calling get method') {
// No instance matches the query
// Simply return null
return null;
}
// Unhandled error, re-throw
throw error;
}
}
}
/**
* Build a selector that checks if a model instance with a given `id` exists in the store
* See the `hasId` function from http://tommikaikkonen.github.io/redux-orm/Model.html
*
* @param string id The id to look for
*
* @return function A function that returns a boolean indicating if an entity with the id `id` exists in the state
*/
hasId(id): (state: any) => boolean {
return (state) => {
return this.getModelFromState(state).hasId(id);
}
}
/**
* Build a selector that gets a model instance with the specified `id`
* See the `withId` function from http://tommikaikkonen.github.io/redux-orm/Model.html
*
* If there is no instance with that id, `null` will be returned and no exception will be thrown (contrary to the behavior of redux-orm). This helps dealing with these cases in Angular.
* Warning: if there are multiple instances matching the properties, we will throw an error just like redux-orm does.
*
* @param string id The `id` used to match a model instance
*
* @return function A function that gets a model instance from the state
*/
withId(id): (state: any) => Model {
return (state) => {
try {
return this.getModelFromState(state).withId(id);
} catch(error) {
/* istanbul ignore else */
if (error.message.indexOf(`instance with id ${id} not found`) !== -1) {
// No instance matches the query
// Simply return null
return null;
}
// Unhandled error, re-throw
/* istanbul ignore next */
throw error;
}
}
}
/**
* Get a model from a session populated from the current state
*
* @param Object state The current state
*
* @return Object A session model
*/
getModelFromState(state) {
const config = ORM.angularConfig;
// We use a global shared ORM instance that is expected to be set for the project during setup
// This is not ideal but that's how angular-redux does it as well because we could be in a decorator
// and do not have access to the Angular objects (components, services, etc.)
if (!config) {
throw new Error('ORM.angularConfig should be set before using `selectData`');
}
if (!config.instance) {
throw new Error('Impossible to find the ORM instance to use. Make sure you have configured ORM.angularConfig.instance to the ORM instance that you want to use with `selectData`');
}
if (!config.stateKey) {
throw new Error('Impossible to find the state key from the config. Make sure you have configured ORM.angularConfig.stateKey to a non-empty value');
}
if (!state[config.stateKey]) {
throw new Error('Impossible to find the DB state; make sure you have configured ORM.angularConfig.stateKey and that you have a reducer running your ORM');
}
// Create a session from the ORM instance
const session = config.instance.session(state[config.stateKey]);
const model = session[this.modelName];
return model;
}
}
/**
* Select data from redux-orm
*
* A helper function that can be used with angular-redux in the @select decorator or when calling
* ngRedux.select (https://github.com/angular-redux/store/blob/master/articles/select-pattern.md) to select
* models from redux-orm.
*
* The function replicates the API from redux-orm so the query syntax is the same.
* Only "read" functions (withId, all) are available.
*
* @param {Object | string} model The name of the Model or the Model object that we are querying
*/
export function selectData(model: Object | string): ORMSelector {
return new ORMSelector(model);
}