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