@qikdev/sdk 0.1.180 → 0.1.182
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/dist/main.js +1 -1
- package/package.json +1 -1
- package/src/api/qik.content.js +705 -729
- package/src/api/qik.utils.js +1190 -1037
- package/src/version.js +1 -1
package/src/api/qik.content.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import axios from
|
|
2
|
-
import _ from
|
|
1
|
+
import axios from "axios";
|
|
2
|
+
import _ from "lodash";
|
|
3
3
|
|
|
4
4
|
///////////////////////////////////////////////////
|
|
5
5
|
|
|
@@ -11,137 +11,127 @@ import _ from 'lodash';
|
|
|
11
11
|
* @hideconstructor
|
|
12
12
|
* @param {QikCore} qik A reference to the parent instance of the QikCore module. This module is usually created by a QikCore instance that passes itself in as the first argument.
|
|
13
13
|
*/
|
|
14
|
-
export default function(qik) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
14
|
+
export default function (qik) {
|
|
15
|
+
if (!qik.api) {
|
|
16
|
+
throw new Error(`Can't Instantiate QikContent before QikAPI exists`);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
///////////////////////////////////////////////////
|
|
20
|
+
|
|
21
|
+
var service = {
|
|
22
|
+
debug: false,
|
|
23
|
+
loadingGlossary: false,
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
27
|
+
|
|
28
|
+
const variables = {};
|
|
29
|
+
let inflightVariablesRequest;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
*
|
|
33
|
+
* Retrieves all global variables for the current user. This is often used when running custom code in an action.
|
|
34
|
+
* @alias content.variables
|
|
35
|
+
* @param {Array} keys Provide specific keys of variables you want to retrieve
|
|
36
|
+
* @param {Object} options Additional options when making the request
|
|
37
|
+
* @param {Boolean} options.reload Force variables to reload and not be cached. If false will retrieve any variables that are already known from the in memory cache.
|
|
38
|
+
* @example
|
|
39
|
+
*
|
|
40
|
+
* const { OAUTH_CLIENT_ID, OAUTH_KEY } = await sdk.content.variables();
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
service.variables = async function (keys, options) {
|
|
44
|
+
options = options || {};
|
|
45
|
+
keys = keys || [];
|
|
46
|
+
|
|
47
|
+
var reload = options.refresh || options.reload || !variables.data;
|
|
48
|
+
if (reload) {
|
|
49
|
+
if (!inflightVariablesRequest) {
|
|
50
|
+
inflightVariablesRequest = qik.api.post(`/variables`, { keys });
|
|
51
|
+
inflightVariablesRequest.then(resolveRequest, resolveRequest);
|
|
52
|
+
function resolveRequest() {
|
|
53
|
+
inflightVariablesRequest = null;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
21
56
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
57
|
+
const { data } = await inflightVariablesRequest;
|
|
58
|
+
variables.data = data;
|
|
59
|
+
qik.dispatch("variables", data);
|
|
25
60
|
}
|
|
26
61
|
|
|
62
|
+
return variables.data;
|
|
63
|
+
};
|
|
27
64
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
const variables = {}
|
|
31
|
-
let inflightVariablesRequest;
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
*
|
|
36
|
-
* Retrieves all global variables for the current user. This is often used when running custom code in an action.
|
|
37
|
-
* @alias content.variables
|
|
38
|
-
* @param {Array} keys Provide specific keys of variables you want to retrieve
|
|
39
|
-
* @param {Object} options Additional options when making the request
|
|
40
|
-
* @param {Boolean} options.reload Force variables to reload and not be cached. If false will retrieve any variables that are already known from the in memory cache.
|
|
41
|
-
* @example
|
|
42
|
-
*
|
|
43
|
-
* const { OAUTH_CLIENT_ID, OAUTH_KEY } = await sdk.content.variables();
|
|
44
|
-
*/
|
|
45
|
-
|
|
46
|
-
service.variables = async function(keys, options) {
|
|
47
|
-
options = options || {};
|
|
48
|
-
keys = keys || [];
|
|
49
|
-
|
|
50
|
-
var reload = options.refresh || options.reload || !variables.data;
|
|
51
|
-
if (reload) {
|
|
52
|
-
if(!inflightVariablesRequest) {
|
|
53
|
-
inflightVariablesRequest = qik.api.post(`/variables`, {keys});
|
|
54
|
-
inflightVariablesRequest.then(resolveRequest, resolveRequest);
|
|
55
|
-
function resolveRequest() {
|
|
56
|
-
inflightVariablesRequest = null;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const { data } = await inflightVariablesRequest
|
|
61
|
-
variables.data = data;
|
|
62
|
-
qik.dispatch('variables', data)
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
return variables.data;
|
|
66
|
-
}
|
|
65
|
+
///////////////////////////////////////////////////
|
|
67
66
|
|
|
68
|
-
|
|
67
|
+
const glossaryCache = qik.cache.get("user:glossary");
|
|
69
68
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
let inflightGlossaryRequest;
|
|
69
|
+
let inflightGlossaryRequest;
|
|
73
70
|
|
|
74
|
-
|
|
75
|
-
*
|
|
76
|
-
* Retrieves the glossary of all content types visible to the requesting user.
|
|
71
|
+
/**
|
|
72
|
+
*
|
|
73
|
+
* Retrieves the glossary of all content types visible to the requesting user.
|
|
77
74
|
By default this will include all fields, validation, expressions and other configuration
|
|
78
75
|
* @alias content.glossary
|
|
79
76
|
* @param {Object} options Additional options
|
|
80
|
-
* @param {Boolean} options.hash Whether to return the data as a keyed object
|
|
77
|
+
* @param {Boolean} options.hash Whether to return the data as a keyed object
|
|
81
78
|
allowing for fast selection of specific content types, by default will return as an array
|
|
82
79
|
* @param {Boolean} options.reload Force glossary to reload and not be cached.
|
|
83
80
|
If false will retrieve content type data from the in memory cache
|
|
84
81
|
* @example
|
|
85
|
-
*
|
|
82
|
+
*
|
|
86
83
|
* const { article, profile } = await sdk.content.glossary({hash:true});
|
|
87
84
|
*/
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
inflightGlossaryRequest = null;
|
|
106
|
-
service.loadingGlossary = false;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// Now we have the glossary
|
|
111
|
-
const { data } = await inflightGlossaryRequest
|
|
112
|
-
|
|
113
|
-
// Cache it for later
|
|
114
|
-
glossaryCache.set('glossary', data);
|
|
115
|
-
cached = data;
|
|
116
|
-
qik.dispatch('glossary', data)
|
|
85
|
+
service.glossary = async function (options) {
|
|
86
|
+
options = options || {};
|
|
87
|
+
|
|
88
|
+
// Check if we already have the glossary cached
|
|
89
|
+
let cached = glossaryCache.get("glossary");
|
|
90
|
+
var reload = options.refresh || options.reload || !cached;
|
|
91
|
+
|
|
92
|
+
// If we are forcing a reload
|
|
93
|
+
if (reload) {
|
|
94
|
+
if (!inflightGlossaryRequest) {
|
|
95
|
+
service.loadingGlossary = true;
|
|
96
|
+
|
|
97
|
+
inflightGlossaryRequest = qik.api.get(`/glossary`, { cache: false });
|
|
98
|
+
inflightGlossaryRequest.then(resolveRequest, resolveRequest);
|
|
99
|
+
function resolveRequest() {
|
|
100
|
+
inflightGlossaryRequest = null;
|
|
101
|
+
service.loadingGlossary = false;
|
|
117
102
|
}
|
|
103
|
+
}
|
|
118
104
|
|
|
105
|
+
// Now we have the glossary
|
|
106
|
+
const { data } = await inflightGlossaryRequest;
|
|
119
107
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
if (options.hex) {
|
|
126
|
-
var result = qik.utils.hash(cached, 'hex');
|
|
127
|
-
return result;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
return cached;
|
|
108
|
+
// Cache it for later
|
|
109
|
+
glossaryCache.set("glossary", data);
|
|
110
|
+
cached = data;
|
|
111
|
+
qik.dispatch("glossary", data);
|
|
131
112
|
}
|
|
132
113
|
|
|
114
|
+
if (options.hash) {
|
|
115
|
+
var result = qik.utils.hash(cached, "key");
|
|
116
|
+
return result;
|
|
117
|
+
}
|
|
133
118
|
|
|
119
|
+
if (options.hex) {
|
|
120
|
+
var result = qik.utils.hash(cached, "hex");
|
|
121
|
+
return result;
|
|
122
|
+
}
|
|
134
123
|
|
|
135
|
-
|
|
124
|
+
return cached;
|
|
125
|
+
};
|
|
136
126
|
|
|
137
|
-
|
|
127
|
+
///////////////////////////////////////////////////
|
|
138
128
|
|
|
139
|
-
|
|
129
|
+
const scopeGlossary = {};
|
|
140
130
|
|
|
141
|
-
|
|
131
|
+
let inflightScopeGlossaryRequest;
|
|
142
132
|
|
|
143
|
-
|
|
144
|
-
*
|
|
133
|
+
/**
|
|
134
|
+
*
|
|
145
135
|
* Retrieves the scope glossary of all scopes the user can know about. This helps to convert a scope id into a human readable title.
|
|
146
136
|
* @alias content.scopeGlossary
|
|
147
137
|
* @param {Object} options Additional options
|
|
@@ -150,709 +140,695 @@ export default function(qik) {
|
|
|
150
140
|
* @param {Boolean} options.reload Force the glossary to reload and not be cached.
|
|
151
141
|
If false will retrieve content type data from the in memory cache
|
|
152
142
|
* @example
|
|
153
|
-
*
|
|
143
|
+
*
|
|
154
144
|
* const scopes = await sdk.content.scopeGlossary();
|
|
155
145
|
*/
|
|
156
146
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
var reload = options.refresh || options.reload || !scopeGlossary.data;
|
|
161
|
-
|
|
147
|
+
service.scopeGlossary = async function (options) {
|
|
148
|
+
options = options || {};
|
|
162
149
|
|
|
163
|
-
|
|
150
|
+
var reload = options.refresh || options.reload || !scopeGlossary.data;
|
|
164
151
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
const { data } = await inflightScopeGlossaryRequest
|
|
174
|
-
scopeGlossary.data = data;
|
|
152
|
+
if (reload) {
|
|
153
|
+
if (!inflightScopeGlossaryRequest) {
|
|
154
|
+
inflightScopeGlossaryRequest = qik.api.get(`/scope/glossary`, {
|
|
155
|
+
cache: false,
|
|
156
|
+
});
|
|
157
|
+
inflightScopeGlossaryRequest.then(resolveRequest, resolveRequest);
|
|
158
|
+
function resolveRequest() {
|
|
159
|
+
inflightScopeGlossaryRequest = null;
|
|
175
160
|
}
|
|
161
|
+
}
|
|
176
162
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
return result;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
return scopeGlossary.data;
|
|
163
|
+
const { data } = await inflightScopeGlossaryRequest;
|
|
164
|
+
scopeGlossary.data = data;
|
|
183
165
|
}
|
|
184
166
|
|
|
167
|
+
if (options.hash) {
|
|
168
|
+
var result = qik.utils.hash(scopeGlossary.data, "_id");
|
|
169
|
+
return result;
|
|
170
|
+
}
|
|
185
171
|
|
|
172
|
+
return scopeGlossary.data;
|
|
173
|
+
};
|
|
186
174
|
|
|
175
|
+
///////////////////////////////////////////////////
|
|
187
176
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
* console.log(hash) // {equal:[{title:'Is equal to', operator:'equal'...}]}
|
|
200
|
-
*/
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
const comparators = {}
|
|
204
|
-
|
|
205
|
-
service.comparators = async function(options) {
|
|
206
|
-
options = options || {};
|
|
207
|
-
|
|
208
|
-
var reload = options.reload || options.refresh || !comparators.data;
|
|
209
|
-
|
|
210
|
-
if (reload) {
|
|
211
|
-
const { data } = await qik.api.get(`/system/comparators`);
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
/////////////////////////////
|
|
177
|
+
/**
|
|
178
|
+
*
|
|
179
|
+
* Retrieves all available filter comparators for each data type
|
|
180
|
+
* @alias content.comparators
|
|
181
|
+
* @param {Object} options Additional options
|
|
182
|
+
* @param {Boolean} options.reload Ignore any locally cached data
|
|
183
|
+
* @example
|
|
184
|
+
* const {hash, available, types} = await sdk.content.comparators();
|
|
185
|
+
* console.log(available) // {boolean:[{title:'Is equal to', operator:'equal'...}]}
|
|
186
|
+
* console.log(hash) // {equal:[{title:'Is equal to', operator:'equal'...}]}
|
|
187
|
+
*/
|
|
215
188
|
|
|
216
|
-
|
|
189
|
+
const comparators = {};
|
|
217
190
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
return data.hash[comparatorKey];
|
|
221
|
-
})
|
|
222
|
-
});
|
|
191
|
+
service.comparators = async function (options) {
|
|
192
|
+
options = options || {};
|
|
223
193
|
|
|
194
|
+
var reload = options.reload || options.refresh || !comparators.data;
|
|
224
195
|
|
|
225
|
-
|
|
196
|
+
if (reload) {
|
|
197
|
+
const { data } = await qik.api.get(`/system/comparators`);
|
|
226
198
|
|
|
227
|
-
|
|
228
|
-
}
|
|
199
|
+
/////////////////////////////
|
|
229
200
|
|
|
201
|
+
data.available = {};
|
|
230
202
|
|
|
203
|
+
Object.entries(data.types).forEach(([key, value]) => {
|
|
204
|
+
data.available[key] = value.map(function (comparatorKey) {
|
|
205
|
+
return data.hash[comparatorKey];
|
|
206
|
+
});
|
|
207
|
+
});
|
|
231
208
|
|
|
232
|
-
|
|
233
|
-
// var result = qik.utils.hash(comparators.data, 'key');
|
|
234
|
-
// return result;
|
|
235
|
-
// }
|
|
209
|
+
/////////////////////////////
|
|
236
210
|
|
|
237
|
-
|
|
211
|
+
comparators.data = data;
|
|
238
212
|
}
|
|
239
213
|
|
|
240
|
-
|
|
214
|
+
// if (options.hash) {
|
|
215
|
+
// var result = qik.utils.hash(comparators.data, 'key');
|
|
216
|
+
// return result;
|
|
217
|
+
// }
|
|
241
218
|
|
|
219
|
+
return comparators.data;
|
|
220
|
+
};
|
|
242
221
|
|
|
243
|
-
|
|
222
|
+
///////////////////////////////////////////////////
|
|
244
223
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
224
|
+
function getLimits(fieldDefinition) {
|
|
225
|
+
var { minimum, maximum } = fieldDefinition;
|
|
226
|
+
minimum = qik.utils.parseInt(minimum);
|
|
227
|
+
minimum = Math.max(minimum, 0);
|
|
248
228
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
229
|
+
maximum = qik.utils.parseInt(maximum);
|
|
230
|
+
maximum = Math.max(maximum, 0); // cant be less than 0
|
|
231
|
+
if (maximum == 0) {
|
|
232
|
+
//Unlimited maximum
|
|
233
|
+
} else {
|
|
234
|
+
maximum = Math.max(maximum, minimum); // cant be less than the minimum
|
|
235
|
+
}
|
|
236
|
+
return { minimum, maximum };
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
service.meetsValidationRequirements = function (
|
|
240
|
+
input,
|
|
241
|
+
fieldType,
|
|
242
|
+
validationCriteria,
|
|
243
|
+
) {
|
|
244
|
+
if (validationCriteria.minLength) {
|
|
245
|
+
var stringLength = String(input).length;
|
|
246
|
+
if (stringLength < validationCriteria.minLength) {
|
|
247
|
+
return `Must be at least ${validationCriteria.minLength} characters`;
|
|
248
|
+
}
|
|
257
249
|
}
|
|
258
250
|
|
|
251
|
+
if (validationCriteria.maxLength) {
|
|
252
|
+
var stringLength = String(input).length;
|
|
253
|
+
if (stringLength > validationCriteria.maxLength) {
|
|
254
|
+
return `Can be no more than ${validationCriteria.maxLength} characters`;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
259
257
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
var stringLength = String(input).length;
|
|
266
|
-
if (stringLength < validationCriteria.minLength) {
|
|
267
|
-
return `Must be at least ${validationCriteria.minLength} characters`;
|
|
268
|
-
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
if (validationCriteria.maxLength) {
|
|
273
|
-
var stringLength = String(input).length;
|
|
274
|
-
if (stringLength > validationCriteria.maxLength) {
|
|
275
|
-
return `Can be no more than ${validationCriteria.maxLength} characters`;
|
|
276
|
-
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
if (validationCriteria.minValue) {
|
|
281
|
-
if(input !== undefined) {
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
var number = Number(input);
|
|
285
|
-
if (number < validationCriteria.minValue) {
|
|
286
|
-
return `Must be at least ${validationCriteria.minValue}`;
|
|
287
|
-
|
|
288
|
-
}
|
|
289
|
-
}
|
|
258
|
+
if (validationCriteria.minValue) {
|
|
259
|
+
if (input !== undefined) {
|
|
260
|
+
var number = Number(input);
|
|
261
|
+
if (number < validationCriteria.minValue) {
|
|
262
|
+
return `Must be at least ${validationCriteria.minValue}`;
|
|
290
263
|
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
291
266
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
if (number > validationCriteria.maxValue) {
|
|
298
|
-
return `Can be no greater than ${validationCriteria.maxValue}`;
|
|
299
|
-
|
|
300
|
-
}
|
|
301
|
-
}
|
|
267
|
+
if (validationCriteria.maxValue) {
|
|
268
|
+
if (input !== undefined) {
|
|
269
|
+
var number = Number(input);
|
|
270
|
+
if (number > validationCriteria.maxValue) {
|
|
271
|
+
return `Can be no greater than ${validationCriteria.maxValue}`;
|
|
302
272
|
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Checks if a certain input validates against a field definition
|
|
279
|
+
* @alias content.validateField
|
|
280
|
+
* @param {Any} input The input to validate
|
|
281
|
+
* @param {Object} fieldDefinition The field to validate against
|
|
282
|
+
* @param {Object} options Additional options when calling the function
|
|
283
|
+
* @example
|
|
284
|
+
* const validationResult = await sdk.content.validateField('Johnny Bobbins', {title:'Name', key:'firstName', type:'string', minimum:1, maximum:1, ...});
|
|
285
|
+
* console.log(validationResult)
|
|
286
|
+
* // Results in { valid:true }
|
|
287
|
+
*
|
|
288
|
+
* const validationResult = await sdk.content.validateField('Johnny Bobbins', {title:'Number', key:'number', type:'integer', minimum:1, maximum:1, ...});
|
|
289
|
+
* console.log(validationResult)
|
|
290
|
+
* // Results in { valid:false, status:400, message:'Invalid number input for field' }
|
|
291
|
+
*/
|
|
292
|
+
|
|
293
|
+
service.validateField = function (input, fieldDefinition, options) {
|
|
294
|
+
options = options || {};
|
|
295
|
+
|
|
296
|
+
var fieldType = fieldDefinition.type || "string";
|
|
297
|
+
var { minimum, maximum } = getLimits(fieldDefinition);
|
|
298
|
+
|
|
299
|
+
var isObject = fieldDefinition.type == "group" && fieldDefinition.asObject;
|
|
300
|
+
var singleValue = isObject
|
|
301
|
+
? minimum === maximum && maximum === 1
|
|
302
|
+
: maximum === 1;
|
|
303
|
+
var multiValue = !singleValue;
|
|
304
|
+
|
|
305
|
+
//////////////////
|
|
306
|
+
|
|
307
|
+
var isNumeric;
|
|
308
|
+
switch (fieldType) {
|
|
309
|
+
case "integer":
|
|
310
|
+
case "decimal":
|
|
311
|
+
case "number":
|
|
312
|
+
case "float":
|
|
313
|
+
isNumeric = true;
|
|
314
|
+
break;
|
|
303
315
|
}
|
|
304
316
|
|
|
305
|
-
|
|
306
|
-
* Checks if a certain input validates against a field definition
|
|
307
|
-
* @alias content.validateField
|
|
308
|
-
* @param {Any} input The input to validate
|
|
309
|
-
* @param {Object} fieldDefinition The field to validate against
|
|
310
|
-
* @param {Object} options Additional options when calling the function
|
|
311
|
-
* @example
|
|
312
|
-
* const validationResult = await sdk.content.validateField('Johnny Bobbins', {title:'Name', key:'firstName', type:'string', minimum:1, maximum:1, ...});
|
|
313
|
-
* console.log(validationResult)
|
|
314
|
-
* // Results in { valid:true }
|
|
315
|
-
*
|
|
316
|
-
* const validationResult = await sdk.content.validateField('Johnny Bobbins', {title:'Number', key:'number', type:'integer', minimum:1, maximum:1, ...});
|
|
317
|
-
* console.log(validationResult)
|
|
318
|
-
* // Results in { valid:false, status:400, message:'Invalid number input for field' }
|
|
319
|
-
*/
|
|
320
|
-
|
|
321
|
-
service.validateField = function(input, fieldDefinition, options) {
|
|
322
|
-
options = options || {}
|
|
323
|
-
|
|
324
|
-
var fieldType = fieldDefinition.type || 'string';
|
|
325
|
-
var { minimum, maximum } = getLimits(fieldDefinition);
|
|
326
|
-
|
|
327
|
-
var isObject = (fieldDefinition.type == 'group' && fieldDefinition.asObject);
|
|
328
|
-
var singleValue = isObject ? minimum === maximum && maximum === 1 : maximum === 1;
|
|
329
|
-
var multiValue = !singleValue;
|
|
330
|
-
|
|
331
|
-
//////////////////
|
|
317
|
+
//////////////////
|
|
332
318
|
|
|
333
|
-
|
|
334
|
-
switch (fieldType) {
|
|
335
|
-
case 'integer':
|
|
336
|
-
case 'decimal':
|
|
337
|
-
case 'number':
|
|
338
|
-
case 'float':
|
|
339
|
-
isNumeric = true;
|
|
340
|
-
break;
|
|
341
|
-
}
|
|
319
|
+
var inputWasProvided = qik.utils.exists(input);
|
|
342
320
|
|
|
343
|
-
|
|
321
|
+
//If an answer is required
|
|
322
|
+
if (minimum) {
|
|
323
|
+
//but none was provided
|
|
324
|
+
if (!inputWasProvided) {
|
|
325
|
+
//Throw an error
|
|
326
|
+
return {
|
|
327
|
+
valid: false,
|
|
328
|
+
message: `${fieldDefinition.title} is a required field`,
|
|
329
|
+
status: 400,
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
} else {
|
|
333
|
+
//No answer is needed and none was provided
|
|
334
|
+
if (!inputWasProvided) {
|
|
335
|
+
return {
|
|
336
|
+
valid: true,
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
}
|
|
344
340
|
|
|
345
|
-
|
|
341
|
+
//////////////////
|
|
346
342
|
|
|
347
|
-
|
|
343
|
+
//If we are requiring multiple values
|
|
344
|
+
if (multiValue) {
|
|
345
|
+
//But the input is not an array
|
|
346
|
+
if (!Array.isArray(input)) {
|
|
348
347
|
if (minimum) {
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
message: `${fieldDefinition.title} is a required field`,
|
|
355
|
-
status: 400,
|
|
356
|
-
}
|
|
357
|
-
}
|
|
348
|
+
return {
|
|
349
|
+
valid: false,
|
|
350
|
+
message: `${fieldDefinition.title} requires at least ${minimum} values`,
|
|
351
|
+
status: 400,
|
|
352
|
+
};
|
|
358
353
|
} else {
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
354
|
+
console.log("NOT PROVIDED AS ARRAY", fieldDefinition.title, input);
|
|
355
|
+
return {
|
|
356
|
+
valid: false,
|
|
357
|
+
message: `${fieldDefinition.title} must be provided as an array`,
|
|
358
|
+
status: 400,
|
|
359
|
+
};
|
|
365
360
|
}
|
|
361
|
+
}
|
|
366
362
|
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
//If we are requiring multiple values
|
|
371
|
-
if (multiValue) {
|
|
372
|
-
|
|
373
|
-
//But the input is not an array
|
|
374
|
-
if (!Array.isArray(input)) {
|
|
375
|
-
|
|
376
|
-
if (minimum) {
|
|
377
|
-
return {
|
|
378
|
-
valid: false,
|
|
379
|
-
message: `${fieldDefinition.title} requires at least ${minimum} values`,
|
|
380
|
-
status: 400,
|
|
381
|
-
}
|
|
382
|
-
} else {
|
|
383
|
-
|
|
384
|
-
console.log('NOT PROVIDED AS ARRAY', fieldDefinition.title, input)
|
|
385
|
-
return {
|
|
386
|
-
valid: false,
|
|
387
|
-
message: `${fieldDefinition.title} must be provided as an array`,
|
|
388
|
-
status: 400,
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
////////////////////////////
|
|
396
|
-
|
|
397
|
-
var compacted = input;
|
|
363
|
+
////////////////////////////
|
|
398
364
|
|
|
399
|
-
|
|
400
|
-
//Check if we care about this value
|
|
401
|
-
var empty = v === undefined || v === null || v === '';
|
|
402
|
-
return !empty;
|
|
403
|
-
})
|
|
365
|
+
var compacted = input;
|
|
404
366
|
|
|
367
|
+
compacted = compacted.filter(function (v) {
|
|
368
|
+
//Check if we care about this value
|
|
369
|
+
var empty = v === undefined || v === null || v === "";
|
|
370
|
+
return !empty;
|
|
371
|
+
});
|
|
405
372
|
|
|
406
|
-
|
|
373
|
+
// console.log('COMPACTED', input.length, compacted.length);
|
|
407
374
|
|
|
408
|
-
|
|
375
|
+
////////////////////////////
|
|
409
376
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
//We have too many answers
|
|
424
|
-
if (maximum && (compacted.length > maximum)) {
|
|
425
|
-
|
|
426
|
-
return {
|
|
427
|
-
valid: false,
|
|
428
|
-
message: `${fieldDefinition.title} requires less than ${maximum+1} values`,
|
|
429
|
-
status: 400,
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
//We don't have enough answers
|
|
434
|
-
if (compacted.length < minimum) {
|
|
435
|
-
|
|
436
|
-
// console.log(fieldDefinition.title, 'INPUT', input.length, minimum, input, compacted)
|
|
437
|
-
|
|
438
|
-
return {
|
|
439
|
-
valid: false,
|
|
440
|
-
message: `${fieldDefinition.title} requires at least ${minimum} values`,
|
|
441
|
-
status: 400,
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
////////////////////////////
|
|
446
|
-
|
|
447
|
-
var foundBadEntry;
|
|
448
|
-
|
|
449
|
-
//Find any bad values
|
|
450
|
-
var badEntry = compacted.find(function(val) {
|
|
451
|
-
var valueFieldType = fieldType;
|
|
452
|
-
|
|
453
|
-
if (fieldDefinition.type === 'group') {
|
|
454
|
-
valueFieldType = 'object';
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
if (fieldDefinition.type === 'reference' && fieldDefinition.widget === 'form') {
|
|
458
|
-
valueFieldType = 'object';
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
var isValid = qik.utils.isValidValue(val, valueFieldType, options.strict);
|
|
462
|
-
|
|
463
|
-
////////////////////////////
|
|
464
|
-
|
|
465
|
-
if (!isValid) {
|
|
466
|
-
foundBadEntry = true;
|
|
467
|
-
return true;
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
////////////////////////////
|
|
471
|
-
|
|
472
|
-
//Is there additional validation requirements
|
|
473
|
-
if (fieldDefinition.validation) {
|
|
474
|
-
var additionalValidationErrors = service.meetsValidationRequirements(val, fieldType, fieldDefinition.validation)
|
|
475
|
-
if (additionalValidationErrors) {
|
|
476
|
-
foundBadEntry = true;
|
|
477
|
-
return true;
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
})
|
|
481
|
-
|
|
482
|
-
if (foundBadEntry) {
|
|
483
|
-
let badValueMessage = `Invalid input for ${fieldDefinition.title}`;
|
|
484
|
-
return {
|
|
485
|
-
valid: false,
|
|
486
|
-
message: badValueMessage,
|
|
487
|
-
status: 400,
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
} else {
|
|
492
|
-
|
|
493
|
-
var dataType = fieldType;
|
|
494
|
-
var widgetType = fieldDefinition.widget;
|
|
495
|
-
if (dataType === 'group') {
|
|
496
|
-
dataType = 'object';
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
if (dataType === 'reference' && widgetType === 'form') {
|
|
500
|
-
dataType = 'object';
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
//////////////////
|
|
505
|
-
|
|
506
|
-
var cleanedValue = service.getCleanedValue(input, dataType, options);
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
//////////////////
|
|
510
|
-
|
|
511
|
-
var isValidValue = qik.utils.isValidValue(cleanedValue, dataType, options.strict);
|
|
512
|
-
|
|
513
|
-
//////////////////
|
|
514
|
-
|
|
515
|
-
//Invalid input
|
|
516
|
-
if (!isValidValue) {
|
|
517
|
-
return {
|
|
518
|
-
valid: false,
|
|
519
|
-
message: `Single value '${input}' is not a valid ${dataType} for ${fieldDefinition.title}`,
|
|
520
|
-
criteria: {
|
|
521
|
-
isValidValue,
|
|
522
|
-
cleanedValue,
|
|
523
|
-
fieldType,
|
|
524
|
-
options,
|
|
525
|
-
},
|
|
526
|
-
status: 400,
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
//Is there additional validation requirements
|
|
531
|
-
let hasAdditionalValidation = false;
|
|
532
|
-
|
|
533
|
-
const validation = {}
|
|
534
|
-
if(String(fieldDefinition.minValue)) { validation.minValue = parseInt(fieldDefinition.minValue); hasAdditionalValidation = true }
|
|
535
|
-
if(String(fieldDefinition.maxValue)) { validation.maxValue = parseInt(fieldDefinition.maxValue); hasAdditionalValidation = true }
|
|
536
|
-
if(String(fieldDefinition.minLength)) { validation.minLength = parseInt(fieldDefinition.minLength); hasAdditionalValidation = true }
|
|
537
|
-
if(String(fieldDefinition.maxLength)) { validation.maxLength = parseInt(fieldDefinition.maxLength); hasAdditionalValidation = true }
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
if (hasAdditionalValidation) {
|
|
541
|
-
const validationCriteria = Object.assign({}, validation, fieldDefinition.validation || {});
|
|
542
|
-
var additionalValidationError = service.meetsValidationRequirements(input, fieldType, validationCriteria)
|
|
543
|
-
if (additionalValidationError) {
|
|
544
|
-
return {
|
|
545
|
-
valid: false,
|
|
546
|
-
message: additionalValidationError,
|
|
547
|
-
status: 400,
|
|
548
|
-
};
|
|
549
|
-
}
|
|
550
|
-
}
|
|
377
|
+
//We need an exact number of answers
|
|
378
|
+
if (minimum == maximum) {
|
|
379
|
+
//But we don't have the number of answers needed
|
|
380
|
+
if (minimum && compacted.length != minimum) {
|
|
381
|
+
return {
|
|
382
|
+
valid: false,
|
|
383
|
+
message: `${fieldDefinition.title} requires exactly ${maximum} values`,
|
|
384
|
+
status: 400,
|
|
385
|
+
};
|
|
551
386
|
}
|
|
387
|
+
}
|
|
552
388
|
|
|
553
|
-
|
|
554
|
-
|
|
389
|
+
//We have too many answers
|
|
390
|
+
if (maximum && compacted.length > maximum) {
|
|
555
391
|
return {
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
service.getCleanedValue = function(input, dataType, options) {
|
|
562
|
-
switch (dataType) {
|
|
563
|
-
case 'number':
|
|
564
|
-
case 'float':
|
|
565
|
-
case 'decimal':
|
|
566
|
-
if (!qik.utils.exists(input)) {
|
|
567
|
-
return undefined;
|
|
568
|
-
} else {
|
|
569
|
-
return Number(input);
|
|
570
|
-
}
|
|
571
|
-
break;
|
|
572
|
-
case 'integer':
|
|
573
|
-
if (!qik.utils.exists(input)) {
|
|
574
|
-
return undefined;
|
|
575
|
-
} else {
|
|
576
|
-
return parseInt(input);
|
|
577
|
-
}
|
|
578
|
-
break;
|
|
579
|
-
case 'boolean':
|
|
580
|
-
if (!qik.utils.exists(input)) {
|
|
581
|
-
return undefined;
|
|
582
|
-
}
|
|
583
|
-
return qik.utils.parseBoolean(input);
|
|
584
|
-
break;
|
|
585
|
-
case 'email':
|
|
586
|
-
return options.strict ? input : String(input).toLowerCase();
|
|
587
|
-
break;
|
|
588
|
-
case 'reference':
|
|
589
|
-
return options.strict ? input : qik.utils.id(input);
|
|
590
|
-
break;
|
|
591
|
-
default:
|
|
592
|
-
return options.strict ? input : qik.utils.cleanValue(input, dataType, options);
|
|
593
|
-
break
|
|
594
|
-
}
|
|
392
|
+
valid: false,
|
|
393
|
+
message: `${fieldDefinition.title} requires less than ${maximum + 1} values`,
|
|
394
|
+
status: 400,
|
|
395
|
+
};
|
|
396
|
+
}
|
|
595
397
|
|
|
596
|
-
|
|
597
|
-
|
|
398
|
+
//We don't have enough answers
|
|
399
|
+
if (compacted.length < minimum) {
|
|
400
|
+
// console.log(fieldDefinition.title, 'INPUT', input.length, minimum, input, compacted)
|
|
598
401
|
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
* @param {String} type The type or definition of records we want to retrieve
|
|
606
|
-
* @param {Object} options The options for our query
|
|
607
|
-
* @param {String} options.search Freeform text keywords
|
|
608
|
-
* @param {Object} options.sort How to sort the results
|
|
609
|
-
* @param {String} options.sort.key Which key to sort on
|
|
610
|
-
* @param {String} options.sort.direction Which direction to sort on
|
|
611
|
-
* @param {Object} options.sort.type What type of data is being sorted
|
|
612
|
-
* @param {Object} options.page Page configuration
|
|
613
|
-
* @param {Number} options.page.size Page size
|
|
614
|
-
* @param {Number} options.page.index Page index
|
|
615
|
-
* @param {Object} options.filter How to filter the results
|
|
616
|
-
* @example
|
|
617
|
-
*
|
|
618
|
-
*
|
|
619
|
-
* sdk.content.list('profile', {
|
|
620
|
-
* search:'Jim',
|
|
621
|
-
* page:{
|
|
622
|
-
* size:50,
|
|
623
|
-
* index:2,
|
|
624
|
-
* },
|
|
625
|
-
* sort:{
|
|
626
|
-
* key:'age',
|
|
627
|
-
* direction:'asc',
|
|
628
|
-
* type:'integer',
|
|
629
|
-
* },
|
|
630
|
-
* filter:{
|
|
631
|
-
* operator:'and',
|
|
632
|
-
* filters:[{
|
|
633
|
-
* key:'age',
|
|
634
|
-
* comparator:'>',
|
|
635
|
-
* value:5,
|
|
636
|
-
* }],
|
|
637
|
-
* },
|
|
638
|
-
* })
|
|
639
|
-
*/
|
|
402
|
+
return {
|
|
403
|
+
valid: false,
|
|
404
|
+
message: `${fieldDefinition.title} requires at least ${minimum} values`,
|
|
405
|
+
status: 400,
|
|
406
|
+
};
|
|
407
|
+
}
|
|
640
408
|
|
|
641
|
-
|
|
409
|
+
////////////////////////////
|
|
642
410
|
|
|
643
|
-
|
|
411
|
+
var foundBadEntry;
|
|
644
412
|
|
|
413
|
+
//Find any bad values
|
|
414
|
+
var badEntry = compacted.find(function (val) {
|
|
415
|
+
var valueFieldType = fieldType;
|
|
645
416
|
|
|
646
|
-
if (
|
|
647
|
-
|
|
417
|
+
if (fieldDefinition.type === "group") {
|
|
418
|
+
valueFieldType = "object";
|
|
648
419
|
}
|
|
649
420
|
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
advanced.config = {}
|
|
656
|
-
}
|
|
657
|
-
|
|
658
|
-
//Create a cancel token
|
|
659
|
-
const CancelToken = qik.api.CancelToken;
|
|
660
|
-
const source = CancelToken.source();
|
|
661
|
-
advanced.config.cancelToken = source.token;
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
const promise = qik.api.post(remoteURL, options, advanced.config);
|
|
665
|
-
return {
|
|
666
|
-
promise,
|
|
667
|
-
cancel(message) {
|
|
668
|
-
source.cancel(message || 'Operation canceled by the user.');
|
|
669
|
-
},
|
|
670
|
-
}
|
|
671
|
-
|
|
672
|
-
} else {
|
|
673
|
-
const { data } = await qik.api.post(remoteURL, options, advanced.config);
|
|
674
|
-
return data;
|
|
421
|
+
if (
|
|
422
|
+
fieldDefinition.type === "reference" &&
|
|
423
|
+
fieldDefinition.widget === "form"
|
|
424
|
+
) {
|
|
425
|
+
valueFieldType = "object";
|
|
675
426
|
}
|
|
676
427
|
|
|
428
|
+
var isValid = qik.utils.isValidValue(
|
|
429
|
+
val,
|
|
430
|
+
valueFieldType,
|
|
431
|
+
options.strict,
|
|
432
|
+
);
|
|
677
433
|
|
|
434
|
+
////////////////////////////
|
|
678
435
|
|
|
436
|
+
if (!isValid) {
|
|
437
|
+
foundBadEntry = true;
|
|
438
|
+
return true;
|
|
439
|
+
}
|
|
679
440
|
|
|
441
|
+
////////////////////////////
|
|
442
|
+
|
|
443
|
+
//Is there additional validation requirements
|
|
444
|
+
if (fieldDefinition.validation) {
|
|
445
|
+
var additionalValidationErrors = service.meetsValidationRequirements(
|
|
446
|
+
val,
|
|
447
|
+
fieldType,
|
|
448
|
+
fieldDefinition.validation,
|
|
449
|
+
);
|
|
450
|
+
if (additionalValidationErrors) {
|
|
451
|
+
foundBadEntry = true;
|
|
452
|
+
return true;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
});
|
|
680
456
|
|
|
457
|
+
if (foundBadEntry) {
|
|
458
|
+
let badValueMessage = `Invalid input for ${fieldDefinition.title}`;
|
|
459
|
+
return {
|
|
460
|
+
valid: false,
|
|
461
|
+
message: badValueMessage,
|
|
462
|
+
status: 400,
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
} else {
|
|
466
|
+
var dataType = fieldType;
|
|
467
|
+
var widgetType = fieldDefinition.widget;
|
|
468
|
+
if (dataType === "group") {
|
|
469
|
+
dataType = "object";
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
if (dataType === "reference" && widgetType === "form") {
|
|
473
|
+
dataType = "object";
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
//////////////////
|
|
477
|
+
|
|
478
|
+
var cleanedValue = service.getCleanedValue(input, dataType, options);
|
|
479
|
+
|
|
480
|
+
//////////////////
|
|
481
|
+
|
|
482
|
+
var isValidValue = qik.utils.isValidValue(
|
|
483
|
+
cleanedValue,
|
|
484
|
+
dataType,
|
|
485
|
+
options.strict,
|
|
486
|
+
);
|
|
487
|
+
|
|
488
|
+
//////////////////
|
|
489
|
+
|
|
490
|
+
//Invalid input
|
|
491
|
+
if (!isValidValue) {
|
|
492
|
+
return {
|
|
493
|
+
valid: false,
|
|
494
|
+
message: `Single value '${input}' is not a valid ${dataType} for ${fieldDefinition.title}`,
|
|
495
|
+
criteria: {
|
|
496
|
+
isValidValue,
|
|
497
|
+
cleanedValue,
|
|
498
|
+
fieldType,
|
|
499
|
+
options,
|
|
500
|
+
},
|
|
501
|
+
status: 400,
|
|
502
|
+
};
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
//Is there additional validation requirements
|
|
506
|
+
let hasAdditionalValidation = false;
|
|
507
|
+
|
|
508
|
+
const validation = {};
|
|
509
|
+
if (String(fieldDefinition.minValue)) {
|
|
510
|
+
validation.minValue = parseInt(fieldDefinition.minValue);
|
|
511
|
+
hasAdditionalValidation = true;
|
|
512
|
+
}
|
|
513
|
+
if (String(fieldDefinition.maxValue)) {
|
|
514
|
+
validation.maxValue = parseInt(fieldDefinition.maxValue);
|
|
515
|
+
hasAdditionalValidation = true;
|
|
516
|
+
}
|
|
517
|
+
if (String(fieldDefinition.minLength)) {
|
|
518
|
+
validation.minLength = parseInt(fieldDefinition.minLength);
|
|
519
|
+
hasAdditionalValidation = true;
|
|
520
|
+
}
|
|
521
|
+
if (String(fieldDefinition.maxLength)) {
|
|
522
|
+
validation.maxLength = parseInt(fieldDefinition.maxLength);
|
|
523
|
+
hasAdditionalValidation = true;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
if (hasAdditionalValidation) {
|
|
527
|
+
const validationCriteria = Object.assign(
|
|
528
|
+
{},
|
|
529
|
+
validation,
|
|
530
|
+
fieldDefinition.validation || {},
|
|
531
|
+
);
|
|
532
|
+
var additionalValidationError = service.meetsValidationRequirements(
|
|
533
|
+
input,
|
|
534
|
+
fieldType,
|
|
535
|
+
validationCriteria,
|
|
536
|
+
);
|
|
537
|
+
if (additionalValidationError) {
|
|
538
|
+
return {
|
|
539
|
+
valid: false,
|
|
540
|
+
message: additionalValidationError,
|
|
541
|
+
status: 400,
|
|
542
|
+
};
|
|
543
|
+
}
|
|
544
|
+
}
|
|
681
545
|
}
|
|
682
546
|
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
/**
|
|
686
|
-
*
|
|
687
|
-
* Create an item
|
|
688
|
-
* @alias content.create
|
|
689
|
-
* @param {String} type The type or definition of the record we want to create
|
|
690
|
-
* @param {Object} input The data for our new record
|
|
691
|
-
* @example
|
|
692
|
-
*
|
|
693
|
-
*
|
|
694
|
-
* const result = await sdk.content.create('profile', {
|
|
695
|
-
* firstName:'Mickey',
|
|
696
|
-
* lastName:'Mouse',
|
|
697
|
-
* gender:'male',
|
|
698
|
-
* meta:{
|
|
699
|
-
* scopes:['61eca4746971e75c1fc670cf'],
|
|
700
|
-
* }
|
|
701
|
-
* })
|
|
702
|
-
*/
|
|
703
|
-
|
|
704
|
-
service.create = async function(type, input) {
|
|
547
|
+
//////////////////
|
|
705
548
|
|
|
706
|
-
|
|
549
|
+
return {
|
|
550
|
+
valid: true,
|
|
551
|
+
};
|
|
552
|
+
};
|
|
707
553
|
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
554
|
+
service.getCleanedValue = function (input, dataType, options) {
|
|
555
|
+
switch (dataType) {
|
|
556
|
+
case "number":
|
|
557
|
+
case "float":
|
|
558
|
+
case "decimal":
|
|
559
|
+
if (!qik.utils.exists(input)) {
|
|
560
|
+
return undefined;
|
|
561
|
+
} else {
|
|
562
|
+
return Number(input);
|
|
711
563
|
}
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
/**
|
|
719
|
-
*
|
|
720
|
-
* Update an item, Only fields the user has permission to view will be returned
|
|
721
|
-
* @alias content.update
|
|
722
|
-
* @param {String} id The id of the record we want to update
|
|
723
|
-
* @param {Object} input The data to update
|
|
724
|
-
* @example
|
|
725
|
-
*
|
|
726
|
-
* const result = await sdk.content.update('61eca4746971e75c1fc670cd', {
|
|
727
|
-
* firstName:'Minnie',
|
|
728
|
-
* lastName:'Mouse',
|
|
729
|
-
* gender:'female',
|
|
730
|
-
* meta:{
|
|
731
|
-
* scopes:['61eca4746971e75c1fc670cd'],
|
|
732
|
-
* }
|
|
733
|
-
* })
|
|
734
|
-
*/
|
|
735
|
-
service.update = async function(id, input) {
|
|
736
|
-
id = qik.utils.id(id);
|
|
737
|
-
|
|
738
|
-
const dataModel = {...input};
|
|
739
|
-
|
|
740
|
-
// Sanitize down to just ids before we send
|
|
741
|
-
if(dataModel.meta?.scopes) {
|
|
742
|
-
dataModel.meta.scopes = qik.utils.ids(dataModel.meta.scopes);
|
|
564
|
+
break;
|
|
565
|
+
case "integer":
|
|
566
|
+
if (!qik.utils.exists(input)) {
|
|
567
|
+
return undefined;
|
|
568
|
+
} else {
|
|
569
|
+
return parseInt(input);
|
|
743
570
|
}
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
}
|
|
749
|
-
|
|
750
|
-
/**
|
|
751
|
-
*
|
|
752
|
-
* Partially update and patch an item, Only fields the user has permission to edit will be updated
|
|
753
|
-
* @alias content.patch
|
|
754
|
-
* @param {String} id The id of the record we want to update
|
|
755
|
-
* @param {Object} input The data to update, this will be merged with existing data
|
|
756
|
-
* @example
|
|
757
|
-
*
|
|
758
|
-
* const result = await sdk.content.patch('61eca4746971e75c1fc670cd', {
|
|
759
|
-
* firstName:'Mickey',
|
|
760
|
-
* gender:'male',
|
|
761
|
-
* })
|
|
762
|
-
*/
|
|
763
|
-
service.patch = async function(id, input) {
|
|
764
|
-
id = qik.utils.id(id);
|
|
765
|
-
|
|
766
|
-
const dataModel = {...input};
|
|
767
|
-
|
|
768
|
-
// Sanitize down to just ids before we send
|
|
769
|
-
if(dataModel.meta?.scopes) {
|
|
770
|
-
dataModel.meta.scopes = qik.utils.ids(dataModel.meta.scopes);
|
|
571
|
+
break;
|
|
572
|
+
case "boolean":
|
|
573
|
+
if (!qik.utils.exists(input)) {
|
|
574
|
+
return undefined;
|
|
771
575
|
}
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
return
|
|
576
|
+
return qik.utils.parseBoolean(input);
|
|
577
|
+
break;
|
|
578
|
+
case "email":
|
|
579
|
+
return options.strict ? input : String(input).toLowerCase();
|
|
580
|
+
break;
|
|
581
|
+
case "reference":
|
|
582
|
+
return options.strict ? input : qik.utils.id(input);
|
|
583
|
+
break;
|
|
584
|
+
default:
|
|
585
|
+
return options.strict
|
|
586
|
+
? input
|
|
587
|
+
: qik.utils.cleanValue(input, dataType, options);
|
|
588
|
+
break;
|
|
776
589
|
}
|
|
777
590
|
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
591
|
+
return input;
|
|
592
|
+
};
|
|
593
|
+
|
|
594
|
+
///////////////////////////////////////////////////
|
|
595
|
+
|
|
596
|
+
/**
|
|
597
|
+
*
|
|
598
|
+
* Retrieves a list of records matching the provided criteria
|
|
599
|
+
* @alias content.list
|
|
600
|
+
* @param {String} type The type or definition of records we want to retrieve
|
|
601
|
+
* @param {Object} options The options for our query
|
|
602
|
+
* @param {String} options.search Freeform text keywords
|
|
603
|
+
* @param {Object} options.sort How to sort the results
|
|
604
|
+
* @param {String} options.sort.key Which key to sort on
|
|
605
|
+
* @param {String} options.sort.direction Which direction to sort on
|
|
606
|
+
* @param {Object} options.sort.type What type of data is being sorted
|
|
607
|
+
* @param {Object} options.page Page configuration
|
|
608
|
+
* @param {Number} options.page.size Page size
|
|
609
|
+
* @param {Number} options.page.index Page index
|
|
610
|
+
* @param {Object} options.filter How to filter the results
|
|
611
|
+
* @example
|
|
612
|
+
*
|
|
613
|
+
*
|
|
614
|
+
* sdk.content.list('profile', {
|
|
615
|
+
* search:'Jim',
|
|
616
|
+
* page:{
|
|
617
|
+
* size:50,
|
|
618
|
+
* index:2,
|
|
619
|
+
* },
|
|
620
|
+
* sort:{
|
|
621
|
+
* key:'age',
|
|
622
|
+
* direction:'asc',
|
|
623
|
+
* type:'integer',
|
|
624
|
+
* },
|
|
625
|
+
* filter:{
|
|
626
|
+
* operator:'and',
|
|
627
|
+
* filters:[{
|
|
628
|
+
* key:'age',
|
|
629
|
+
* comparator:'>',
|
|
630
|
+
* value:5,
|
|
631
|
+
* }],
|
|
632
|
+
* },
|
|
633
|
+
* })
|
|
634
|
+
*/
|
|
635
|
+
|
|
636
|
+
service.list = async function (type, options, advanced) {
|
|
637
|
+
if (!advanced) {
|
|
638
|
+
advanced = {};
|
|
793
639
|
}
|
|
794
640
|
|
|
795
|
-
|
|
796
|
-
|
|
641
|
+
const remoteURL = advanced.remoteURL || `/content/${type}/list`;
|
|
642
|
+
|
|
643
|
+
if (advanced.cancellable) {
|
|
644
|
+
if (!advanced.config) {
|
|
645
|
+
advanced.config = {};
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
//Create a cancel token
|
|
649
|
+
const CancelToken = qik.api.CancelToken;
|
|
650
|
+
const source = CancelToken.source();
|
|
651
|
+
advanced.config.cancelToken = source.token;
|
|
652
|
+
|
|
653
|
+
const promise = qik.api.post(remoteURL, options, advanced.config);
|
|
654
|
+
return {
|
|
655
|
+
promise,
|
|
656
|
+
cancel(message) {
|
|
657
|
+
source.cancel(message || "Operation canceled by the user.");
|
|
658
|
+
},
|
|
659
|
+
};
|
|
660
|
+
} else {
|
|
661
|
+
const { data } = await qik.api.post(remoteURL, options, advanced.config);
|
|
662
|
+
return data;
|
|
797
663
|
}
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
664
|
+
};
|
|
665
|
+
|
|
666
|
+
///////////////////////////////////////////////////
|
|
667
|
+
|
|
668
|
+
/**
|
|
669
|
+
*
|
|
670
|
+
* Create an item
|
|
671
|
+
* @alias content.create
|
|
672
|
+
* @param {String} type The type or definition of the record we want to create
|
|
673
|
+
* @param {Object} input The data for our new record
|
|
674
|
+
* @example
|
|
675
|
+
*
|
|
676
|
+
*
|
|
677
|
+
* const result = await sdk.content.create('profile', {
|
|
678
|
+
* firstName:'Mickey',
|
|
679
|
+
* lastName:'Mouse',
|
|
680
|
+
* gender:'male',
|
|
681
|
+
* meta:{
|
|
682
|
+
* scopes:['61eca4746971e75c1fc670cf'],
|
|
683
|
+
* }
|
|
684
|
+
* })
|
|
685
|
+
*/
|
|
686
|
+
|
|
687
|
+
service.create = async function (type, input) {
|
|
688
|
+
const dataModel = { ...input };
|
|
689
|
+
|
|
690
|
+
// Sanitize down to just ids before we send
|
|
691
|
+
if (dataModel.meta?.scopes) {
|
|
692
|
+
dataModel.meta.scopes = qik.utils.ids(dataModel.meta.scopes);
|
|
811
693
|
}
|
|
812
694
|
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
695
|
+
const { data } = await qik.api.post(`/content/${type}/create`, dataModel);
|
|
696
|
+
return data;
|
|
697
|
+
};
|
|
698
|
+
|
|
699
|
+
/**
|
|
700
|
+
*
|
|
701
|
+
* Update an item, Only fields the user has permission to view will be returned
|
|
702
|
+
* @alias content.update
|
|
703
|
+
* @param {String} id The id of the record we want to update
|
|
704
|
+
* @param {Object} input The data to update
|
|
705
|
+
* @example
|
|
706
|
+
*
|
|
707
|
+
* const result = await sdk.content.update('61eca4746971e75c1fc670cd', {
|
|
708
|
+
* firstName:'Minnie',
|
|
709
|
+
* lastName:'Mouse',
|
|
710
|
+
* gender:'female',
|
|
711
|
+
* meta:{
|
|
712
|
+
* scopes:['61eca4746971e75c1fc670cd'],
|
|
713
|
+
* }
|
|
714
|
+
* })
|
|
715
|
+
*/
|
|
716
|
+
service.update = async function (id, input) {
|
|
717
|
+
id = qik.utils.id(id);
|
|
718
|
+
|
|
719
|
+
const dataModel = { ...input };
|
|
720
|
+
|
|
721
|
+
// Sanitize down to just ids before we send
|
|
722
|
+
if (dataModel.meta?.scopes) {
|
|
723
|
+
dataModel.meta.scopes = qik.utils.ids(dataModel.meta.scopes);
|
|
825
724
|
}
|
|
826
725
|
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
726
|
+
const { data } = await qik.api.put(`/content/${id}`, dataModel);
|
|
727
|
+
return data;
|
|
728
|
+
};
|
|
729
|
+
|
|
730
|
+
/**
|
|
731
|
+
*
|
|
732
|
+
* Partially update and patch an item, Only fields the user has permission to edit will be updated
|
|
733
|
+
* @alias content.patch
|
|
734
|
+
* @param {String} id The id of the record we want to update
|
|
735
|
+
* @param {Object} input The data to update, this will be merged with existing data
|
|
736
|
+
* @example
|
|
737
|
+
*
|
|
738
|
+
* const result = await sdk.content.patch('61eca4746971e75c1fc670cd', {
|
|
739
|
+
* firstName:'Mickey',
|
|
740
|
+
* gender:'male',
|
|
741
|
+
* })
|
|
742
|
+
*/
|
|
743
|
+
service.patch = async function (id, input) {
|
|
744
|
+
id = qik.utils.id(id);
|
|
745
|
+
|
|
746
|
+
const dataModel = { ...input };
|
|
747
|
+
|
|
748
|
+
// Sanitize down to just ids before we send
|
|
749
|
+
if (dataModel.meta?.scopes) {
|
|
750
|
+
dataModel.meta.scopes = qik.utils.ids(dataModel.meta.scopes);
|
|
843
751
|
}
|
|
844
752
|
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
753
|
+
const { data } = await qik.api.patch(`/content/${id}`, dataModel);
|
|
754
|
+
return data;
|
|
755
|
+
};
|
|
756
|
+
|
|
757
|
+
/**
|
|
758
|
+
*
|
|
759
|
+
* Get an item from the database, Only fields the user has permission to view will be returned
|
|
760
|
+
* @alias content.get
|
|
761
|
+
* @param {String} id The id of the record we want to update
|
|
762
|
+
* @example
|
|
763
|
+
*
|
|
764
|
+
* const result = await sdk.content.get('61eca4746971e75c1fc670cd')
|
|
765
|
+
*/
|
|
766
|
+
service.get = async function (id, params) {
|
|
767
|
+
id = qik.utils.id(id);
|
|
768
|
+
params = params || {};
|
|
769
|
+
|
|
770
|
+
const { data } = await qik.api.get(`/content/${id}`, params);
|
|
771
|
+
return data;
|
|
772
|
+
};
|
|
773
|
+
|
|
774
|
+
service.getFromID = async function (id) {
|
|
775
|
+
return service.get(id);
|
|
776
|
+
};
|
|
777
|
+
|
|
778
|
+
/**
|
|
779
|
+
*
|
|
780
|
+
* Delete an item from the database
|
|
781
|
+
* @alias content.delete
|
|
782
|
+
* @param {String} id The id of the record we want to delete
|
|
783
|
+
* @example
|
|
784
|
+
* const result = await sdk.content.delete('61eca4746971e75c1fc670cd')
|
|
785
|
+
*/
|
|
786
|
+
service.delete = async function (id, input) {
|
|
787
|
+
id = qik.utils.id(id);
|
|
788
|
+
const { data } = await qik.api.delete(`/content/${id}`, input);
|
|
789
|
+
return data;
|
|
790
|
+
};
|
|
791
|
+
|
|
792
|
+
/**
|
|
793
|
+
*
|
|
794
|
+
* Restore a deleted item from the database
|
|
795
|
+
* @alias content.restore
|
|
796
|
+
* @param {String} id The id of the record we want to restore
|
|
797
|
+
* @example
|
|
798
|
+
* const result = await sdk.content.restore('61eca4746971e75c1fc670cd')
|
|
799
|
+
*/
|
|
800
|
+
service.restore = async function (id, input) {
|
|
801
|
+
id = qik.utils.id(id);
|
|
802
|
+
const { data } = await qik.api.get(`/content/${id}/restore`, input);
|
|
803
|
+
return data;
|
|
804
|
+
};
|
|
805
|
+
|
|
806
|
+
/**
|
|
807
|
+
*
|
|
808
|
+
* Retrieve an item from the database by providing it's 'slug'
|
|
809
|
+
* @alias content.getFromSlug
|
|
810
|
+
* @param {String} slug The slug id of the record we want to retrieve
|
|
811
|
+
* it must be provided as either `(type):(slug)`` or `(definition):(slug)`
|
|
812
|
+
* (if unsure use the `meta.abs` absolute slug property of the item you are wanting to retrieve).
|
|
813
|
+
* @example
|
|
814
|
+
* const result = await sdk.content.getFromSlug('article:how-to-get-started')
|
|
815
|
+
* const result = await sdk.content.getFromSlug('car:toyota-landcruiser')
|
|
816
|
+
* const result = await sdk.content.getFromSlug('article:toyota-landcruiser')
|
|
817
|
+
*/
|
|
818
|
+
service.getFromSlug = async function (slug) {
|
|
819
|
+
const { data } = await qik.api.get(`/content/slug/${slug}`);
|
|
820
|
+
return data;
|
|
821
|
+
};
|
|
822
|
+
|
|
823
|
+
// service.getFromSlug = async function(type, slug) {
|
|
824
|
+
// const { data } = await qik.api.get(`/content/${type}/slug/${slug}`);
|
|
825
|
+
// return data;
|
|
826
|
+
// }
|
|
827
|
+
|
|
828
|
+
// service.getFromExternalID = async function(type, externalID) {
|
|
829
|
+
// const { data } = await qik.api.get(`/content/${type}/external/${externalID}`);
|
|
830
|
+
// return data;
|
|
831
|
+
// }
|
|
832
|
+
|
|
833
|
+
return service;
|
|
834
|
+
}
|