@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.
@@ -1,5 +1,5 @@
1
- import axios from 'axios';
2
- import _ from 'lodash';
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
- if (!qik.api) {
17
- throw new Error(`Can't Instantiate QikContent before QikAPI exists`);
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
- var service = {
23
- debug: false,
24
- loadingGlossary:false,
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
- const glossaryCache = qik.cache.get('user:glossary');
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
- service.glossary = async function(options) {
89
- options = options || {};
90
-
91
-
92
- // Check if we already have the glossary cached
93
- let cached = glossaryCache.get('glossary');
94
- var reload = options.refresh || options.reload || !cached;
95
-
96
- // If we are forcing a reload
97
- if (reload) {
98
- if(!inflightGlossaryRequest) {
99
-
100
- service.loadingGlossary = true;
101
-
102
- inflightGlossaryRequest = qik.api.get(`/glossary`, {cache:false});
103
- inflightGlossaryRequest.then(resolveRequest, resolveRequest);
104
- function resolveRequest() {
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
- if (options.hash) {
121
- var result = qik.utils.hash(cached, 'key');
122
- return result;
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
- const scopeGlossary = {}
129
+ const scopeGlossary = {};
140
130
 
141
- let inflightScopeGlossaryRequest;
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
- service.scopeGlossary = async function(options) {
158
- options = options || {};
159
-
160
- var reload = options.refresh || options.reload || !scopeGlossary.data;
161
-
147
+ service.scopeGlossary = async function (options) {
148
+ options = options || {};
162
149
 
163
- if (reload) {
150
+ var reload = options.refresh || options.reload || !scopeGlossary.data;
164
151
 
165
- if(!inflightScopeGlossaryRequest) {
166
- inflightScopeGlossaryRequest = qik.api.get(`/scope/glossary`, {cache:false});
167
- inflightScopeGlossaryRequest.then(resolveRequest, resolveRequest);
168
- function resolveRequest() {
169
- inflightScopeGlossaryRequest = null;
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
- if (options.hash) {
178
- var result = qik.utils.hash(scopeGlossary.data, '_id');
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
- * Retrieves all available filter comparators for each data type
193
- * @alias content.comparators
194
- * @param {Object} options Additional options
195
- * @param {Boolean} options.reload Ignore any locally cached data
196
- * @example
197
- * const {hash, available, types} = await sdk.content.comparators();
198
- * console.log(available) // {boolean:[{title:'Is equal to', operator:'equal'...}]}
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
- data.available = {};
189
+ const comparators = {};
217
190
 
218
- Object.entries(data.types).forEach(([key, value]) => {
219
- data.available[key] = value.map(function(comparatorKey) {
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
- comparators.data = data;
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
- // if (options.hash) {
233
- // var result = qik.utils.hash(comparators.data, 'key');
234
- // return result;
235
- // }
209
+ /////////////////////////////
236
210
 
237
- return comparators.data;
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
- function getLimits(fieldDefinition) {
222
+ ///////////////////////////////////////////////////
244
223
 
245
- var { minimum, maximum } = fieldDefinition;
246
- minimum = qik.utils.parseInt(minimum);
247
- minimum = Math.max(minimum, 0);
224
+ function getLimits(fieldDefinition) {
225
+ var { minimum, maximum } = fieldDefinition;
226
+ minimum = qik.utils.parseInt(minimum);
227
+ minimum = Math.max(minimum, 0);
248
228
 
249
- maximum = qik.utils.parseInt(maximum);
250
- maximum = Math.max(maximum, 0); // cant be less than 0
251
- if (maximum == 0) {
252
- //Unlimited maximum
253
- } else {
254
- maximum = Math.max(maximum, minimum); // cant be less than the minimum
255
- }
256
- return { minimum, maximum };
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
- service.meetsValidationRequirements = function(input, fieldType, validationCriteria) {
263
-
264
- if (validationCriteria.minLength) {
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
- if (validationCriteria.maxValue) {
293
- if(input !== undefined) {
294
-
295
-
296
- var number = Number(input);
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
- var isNumeric;
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
- var inputWasProvided = qik.utils.exists(input);
341
+ //////////////////
346
342
 
347
- //If an answer is required
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
- //but none was provided
350
- if (!inputWasProvided) {
351
- //Throw an error
352
- return {
353
- valid: false,
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
- //No answer is needed and none was provided
360
- if (!inputWasProvided) {
361
- return {
362
- valid: true,
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
- compacted = compacted.filter(function(v) {
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
- // console.log('COMPACTED', input.length, compacted.length);
373
+ // console.log('COMPACTED', input.length, compacted.length);
407
374
 
408
- ////////////////////////////
375
+ ////////////////////////////
409
376
 
410
- //We need an exact number of answers
411
- if (minimum == maximum) {
412
-
413
- //But we don't have the number of answers needed
414
- if (minimum && (compacted.length != minimum)) {
415
- return {
416
- valid: false,
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
- }
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
- valid: true,
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
- return input;
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
- * 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
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
- service.list = async function(type, options, advanced) {
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 (!advanced) {
647
- advanced = {};
417
+ if (fieldDefinition.type === "group") {
418
+ valueFieldType = "object";
648
419
  }
649
420
 
650
- const remoteURL = advanced.remoteURL || `/content/${type}/list`;
651
-
652
- if (advanced.cancellable) {
653
-
654
- if (!advanced.config) {
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
- const dataModel = {...input};
549
+ return {
550
+ valid: true,
551
+ };
552
+ };
707
553
 
708
- // Sanitize down to just ids before we send
709
- if(dataModel.meta?.scopes) {
710
- dataModel.meta.scopes = qik.utils.ids(dataModel.meta.scopes);
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
- const { data } = await qik.api.post(`/content/${type}/create`, dataModel);
715
- return data;
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
- const { data } = await qik.api.put(`/content/${id}`, dataModel);
747
- return data;
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
- const { data } = await qik.api.patch(`/content/${id}`, dataModel);
775
- return data;
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
- * Get an item from the database, Only fields the user has permission to view will be returned
781
- * @alias content.get
782
- * @param {String} id The id of the record we want to update
783
- * @example
784
- *
785
- * const result = await sdk.content.get('61eca4746971e75c1fc670cd')
786
- */
787
- service.get = async function(id, params) {
788
- id = qik.utils.id(id);
789
- params = params || {}
790
-
791
- const { data } = await qik.api.get(`/content/${id}`, params);
792
- return data;
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
- service.getFromID = async function(id) {
796
- return service.get(id);
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
- * Delete an item from the database
802
- * @alias content.delete
803
- * @param {String} id The id of the record we want to delete
804
- * @example
805
- * const result = await sdk.content.delete('61eca4746971e75c1fc670cd')
806
- */
807
- service.delete = async function(id, input) {
808
- id = qik.utils.id(id);
809
- const { data } = await qik.api.delete(`/content/${id}`, input);
810
- return data;
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
- * Restore a deleted item from the database
816
- * @alias content.restore
817
- * @param {String} id The id of the record we want to restore
818
- * @example
819
- * const result = await sdk.content.restore('61eca4746971e75c1fc670cd')
820
- */
821
- service.restore = async function(id, input) {
822
- id = qik.utils.id(id);
823
- const { data } = await qik.api.get(`/content/${id}/restore`, input);
824
- return data;
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
- * Retrieve an item from the database by providing it's 'slug'
831
- * @alias content.getFromSlug
832
- * @param {String} slug The slug id of the record we want to retrieve
833
- * it must be provided as either `(type):(slug)`` or `(definition):(slug)`
834
- * (if unsure use the `meta.abs` absolute slug property of the item you are wanting to retrieve).
835
- * @example
836
- * const result = await sdk.content.getFromSlug('article:how-to-get-started')
837
- * const result = await sdk.content.getFromSlug('car:toyota-landcruiser')
838
- * const result = await sdk.content.getFromSlug('article:toyota-landcruiser')
839
- */
840
- service.getFromSlug = async function(slug) {
841
- const { data } = await qik.api.get(`/content/slug/${slug}`);
842
- return data;
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
- // service.getFromSlug = async function(type, slug) {
846
- // const { data } = await qik.api.get(`/content/${type}/slug/${slug}`);
847
- // return data;
848
- // }
849
-
850
- // service.getFromExternalID = async function(type, externalID) {
851
- // const { data } = await qik.api.get(`/content/${type}/external/${externalID}`);
852
- // return data;
853
- // }
854
-
855
-
856
- return service;
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
+ }