diff --git a/coverage.html b/coverage.html index d82a96e2..319277f1 100644 --- a/coverage.html +++ b/coverage.html @@ -611,7 +611,7 @@
273 | + | + | // Joi post v10 | +||
274 | +59 | +if (Utilities.isObject(test.arg) && test.arg.pattern) { | +|||
275 | ++ | 3 | +property.pattern = test.arg.pattern.toString(); | +||
276 | ++ | + | } | +||
277 | ++ | + | // Joi pre v10 | +||
278 | ++ | + | /* $lab:coverage:off$ */ | +||
279 | ++ | if (Utilities.isRegex(test.arg)) { | |||
274 | +280 | - | 4 | +property.pattern = test.arg.toString(); | |
275 | +281 | } | |||
276 | +282 | ++ | + | /* $lab:coverage:on$ */ | +|
283 | }); | ||||
277 | +284 | ||||
278 | +285 | ||||
279 | +286 | // add extended properties not part of openAPI spec | |||
280 | +287 | 251 | if (this.settings.xProperties === true) { | ||
281 | +288 | 212 | internals.convertRules(property, describe.rules, [ | ||
282 | +289 | 'insensitive', | |||
283 | +290 | 'length' | |||
284 | +291 | ], 'x-constraint'); | |||
285 | +292 | ||||
286 | +293 | 212 | internals.convertRules(property, describe.rules, [ | ||
287 | +294 | 'creditCard', | |||
288 | +295 | 'alphanum', | |||
289 | +296 | 'token', | |||
290 | +297 | 'email', | |||
291 | +298 | 'ip', | |||
292 | +299 | 'uri', | |||
293 | +300 | 'guid', | |||
294 | +301 | 'hex', | |||
295 | +302 | 'hostname', | |||
296 | +303 | 'isoDate' | |||
297 | +304 | ], 'x-format'); | |||
298 | +305 | ||||
299 | +306 | 212 | internals.convertRules(property, describe.rules, [ | ||
300 | +307 | 'lowercase', | |||
301 | +308 | 'uppercase', | |||
302 | +309 | 'trim' | |||
303 | +310 | ], 'x-convert'); | |||
304 | +311 | } | |||
305 | +312 | ||||
306 | +313 | 251 | return property; | ||
307 | +314 | }; | |||
308 | +315 | ||||
309 | +316 | ||||
310 | +317 | /** | |||
311 | +318 | * parse number property | |||
312 | +319 | * | |||
313 | +320 | * @param {Object} property | |||
314 | +321 | * @param {Object} joiObj | |||
315 | +322 | * @return {Object} | |||
316 | +323 | */ | |||
317 | +324 | 1 | internals.properties.prototype.parseNumber = function (property, joiObj) { | ||
318 | +325 | ||||
319 | +326 | 205 | const describe = joiObj.describe(); | ||
320 | +327 | 205 | property.minimum = internals.getArgByName(describe.rules, 'min'); | ||
321 | +328 | 205 | property.maximum = internals.getArgByName(describe.rules, 'max'); | ||
322 | +329 | 205 | if (internals.hasPropertyByName(describe.rules, 'integer')) { | ||
323 | +330 | 5 | property.type = 'integer'; | ||
324 | +331 | } | |||
325 | +332 | ||||
326 | +333 | // add extended properties not part of openAPI spec | |||
327 | +334 | 205 | if (this.settings.xProperties === true) { | ||
328 | +335 | 191 | internals.convertRules(property, describe.rules, [ | ||
329 | +336 | 'greater', | |||
330 | +337 | 'less', | |||
331 | +338 | 'precision', | |||
332 | +339 | 'multiple', | |||
333 | +340 | 'positive', | |||
334 | +341 | 'negative' | |||
335 | +342 | ], 'x-constraint'); | |||
336 | +343 | } | |||
337 | +344 | ||||
338 | +345 | 205 | return property; | ||
339 | +346 | }; | |||
340 | +347 | ||||
341 | +348 | ||||
342 | +349 | /** | |||
343 | +350 | * parse date property | |||
344 | +351 | * | |||
345 | +352 | * @param {Object} property | |||
346 | +353 | * @param {Object} joiObj | |||
347 | +354 | * @return {Object} | |||
348 | +355 | */ | |||
349 | +356 | 1 | internals.properties.prototype.parseDate = function (property, joiObj) { | ||
350 | +357 | ||||
351 | +358 | 12 | if (joiObj._flags.timestamp) { | ||
352 | +359 | 2 | property.type = 'number'; | ||
353 | +360 | 2 | delete property.format; | ||
354 | +361 | } | |||
355 | +362 | ||||
356 | +363 | 12 | return property; | ||
357 | +364 | }; | |||
358 | +365 | ||||
359 | +366 | ||||
360 | +367 | /** | |||
361 | +368 | * parse object property | |||
362 | +369 | * | |||
363 | +370 | * @param {Object} property | |||
364 | +371 | * @param {Object} joiObj | |||
365 | +372 | * @param {String} name | |||
366 | +373 | * @param {Boolean} useDefinitions | |||
367 | +374 | * @param {Boolean} isAlt | |||
368 | +375 | * @return {Object} | |||
369 | +376 | */ | |||
370 | +377 | 1 | internals.properties.prototype.parseObject = function (property, joiObj, name, parameterType, useDefinitions, isAlt) { | ||
371 | +378 | ||||
372 | +379 | 230 | property.properties = {}; | ||
373 | +380 | 230 | joiObj = joiObj._inner.children; | ||
374 | +381 | 230 | joiObj.forEach((obj) => { | ||
375 | +382 | ||||
376 | +383 | 433 | let keyName = obj.key; | ||
377 | +384 | 433 | let itemName = obj.key; | ||
378 | +385 | 433 | let joiChildObj = obj.schema; | ||
379 | +386 | // get name form label if set | |||
380 | +387 | 433 | if (Utilities.geJoiLabel(joiChildObj)) { | ||
381 | +388 | 22 | itemName = Utilities.geJoiLabel(joiChildObj); | ||
382 | +389 | } | |||
383 | +390 | //name, joiObj, parent, parameterType, useDefinitions, isAlt | |||
384 | +391 | 433 | property.properties[keyName] = this.parseProperty(itemName, joiChildObj, property, parameterType, useDefinitions, isAlt); | ||
385 | +392 | // switch references if naming has changed | |||
386 | +393 | 433 | if (keyName !== itemName) { | ||
387 | +394 | 18 | property.required = Utilities.replaceValue(property.required, itemName, keyName); | ||
388 | +395 | 18 | property.optional = Utilities.replaceValue(property.optional, itemName, keyName); | ||
389 | +396 | } | |||
390 | +397 | }); | |||
391 | +398 | 230 | property.name = name; | ||
392 | +399 | 230 | return property; | ||
393 | +400 | }; | |||
394 | +401 | ||||
395 | +402 | ||||
396 | +403 | /** | |||
397 | +404 | * parse array property | |||
398 | +405 | * | |||
399 | +406 | * @param {Object} property | |||
400 | +407 | * @param {Object} joiObj | |||
401 | +408 | * @param {String} name | |||
402 | +409 | * @param {String} parameterType, | |||
403 | +410 | * @param {Boolean} useDefinitions | |||
404 | +411 | * @param {Boolean} isAlt | |||
405 | +412 | * @return {Object} | |||
406 | +413 | */ | |||
407 | +414 | 1 | internals.properties.prototype.parseArray = function (property, joiObj, name, parameterType, useDefinitions, isAlt) { | ||
408 | +415 | ||||
409 | +416 | 44 | const describe = joiObj.describe(); | ||
410 | +417 | 44 | property.minItems = internals.getArgByName(describe.rules, 'min'); | ||
411 | +418 | 44 | property.maxItems = internals.getArgByName(describe.rules, 'max'); | ||
412 | +419 | ||||
413 | +420 | ||||
414 | +421 | // add extended properties not part of openAPI spec | |||
415 | +422 | 44 | if (this.settings.xProperties === true) { | ||
416 | +423 | 28 | internals.convertRules(property, describe.rules, [ | ||
417 | +424 | 'length', | |||
418 | +425 | 'unique' | |||
419 | +426 | ], 'x-constraint'); | |||
420 | +427 | ||||
421 | +428 | 28 | if (describe.flags.sparse) { | ||
422 | +429 | 1 | internals.addToPropertyObject(property, 'x-constraint', 'sparse', true); | ||
423 | +430 | } | |||
424 | +431 | 28 | if (describe.flags.single) { | ||
425 | +432 | 1 | internals.addToPropertyObject(property, 'x-constraint', 'single', true); | ||
426 | +433 | } | |||
427 | +434 | } | |||
428 | +435 | ||||
429 | +436 | ||||
430 | +437 | // default the items with type:string | |||
431 | +438 | 44 | property.items = { | ||
432 | +439 | 'type': 'string' | |||
433 | +440 | }; | |||
434 | +441 | ||||
435 | +442 | // set swaggers collectionFormat to one that works with hapi | |||
436 | +443 | 44 | if (parameterType === 'query' || parameterType === 'formData') { | ||
437 | +444 | 5 | property.collectionFormat = 'multi'; | ||
438 | +445 | } | |||
439 | +446 | ||||
440 | +447 | // swagger appears to only support one array item type at a time, so grab the first one | |||
441 | +448 | 44 | let arrayItemTypes = joiObj._inner.items; // joiObj._inner.inclusions; | ||
442 | +449 | 44 | let arrayItem = Utilities.first(arrayItemTypes); | ||
443 | +450 | ||||
444 | +451 | 44 | if (arrayItem) { | ||
445 | +452 | // get name of item if it has one | |||
446 | +453 | 31 | let itemName; | ||
447 | +454 | 31 | if (Utilities.geJoiLabel(arrayItem)) { | ||
448 | +455 | 15 | itemName = Utilities.geJoiLabel(arrayItem); | ||
449 | +456 | } | |||
450 | +457 | ||||
451 | +458 | //name, joiObj, parent, parameterType, useDefinitions, isAlt | |||
452 | +459 | 31 | let arrayItemProperty = this.parseProperty(itemName, arrayItem, property, parameterType, useDefinitions, isAlt); | ||
453 | +460 | 31 | if (this.simpleTypePropertyMap[arrayItem._type.toLowerCase()]) { | ||
454 | +461 | // map simple types directly | |||
455 | +462 | 10 | property.items = {}; | ||
456 | +463 | 10 | for (let key in arrayItemProperty) { | ||
457 | +464 | 14 | property.items[key] = arrayItemProperty[key]; | ||
458 | +465 | } | |||
459 | +466 | } else { | |||
460 | +467 | 21 | property.items = arrayItemProperty; | ||
461 | +468 | } | |||
462 | +469 | ||||
463 | +470 | } | |||
464 | +471 | ||||
465 | +472 | 44 | property.name = name; | ||
466 | +473 | 44 | return property; | ||
467 | +474 | }; | |||
468 | +475 | ||||
469 | +476 | ||||
470 | +477 | /** | |||
471 | +478 | * parse alternatives property | |||
472 | +479 | * | |||
473 | +480 | * @param {Object} property | |||
474 | +481 | * @param {Object} joiObj | |||
475 | +482 | * @param {String} name | |||
476 | +483 | * @param {String} parameterType | |||
477 | +484 | * @param {Boolean} useDefinitions | |||
478 | +485 | * @return {Object} | |||
479 | +486 | */ | |||
480 | +487 | 1 | internals.properties.prototype.parseAlternatives = function (property, joiObj, name, parameterType, useDefinitions) { | ||
481 | +488 | ||||
482 | +489 | // convert .try() alternatives structures | |||
483 | +490 | 21 | if (Hoek.reach(joiObj, '_inner.matches.0.schema')) { | ||
484 | +491 | // add first into definitionCollection | |||
485 | +492 | 11 | let child = joiObj._inner.matches[0].schema; | ||
486 | +493 | 11 | let childName = Utilities.geJoiLabel(joiObj); | ||
487 | +494 | //name, joiObj, parent, parameterType, useDefinitions, isAlt | |||
488 | +495 | 11 | property = this.parseProperty(childName, child, property, parameterType, useDefinitions, false); | ||
489 | +496 | ||||
490 | +497 | // create the alternatives without appending to the definitionCollection | |||
491 | +498 | 11 | if (this.settings.xProperties === true) { | ||
492 | +499 | 7 | let altArray = joiObj._inner.matches.map((obj) => { | ||
493 | +500 | 16 | let altName = (Utilities.geJoiLabel(obj.schema) || name); | ||
494 | +501 | //name, joiObj, parent, parameterType, useDefinitions, isAlt | |||
495 | +502 | 16 | return this.parseProperty(altName, obj.schema, property, parameterType, useDefinitions, true); | ||
496 | +503 | }); | |||
497 | +504 | 7 | property['x-alternatives'] = Hoek.clone(altArray); | ||
498 | +505 | } | |||
499 | +506 | } | |||
500 | +507 | ||||
501 | +508 | // convert .when() alternatives structures | |||
502 | +509 | else { | |||
503 | +510 | // add first into definitionCollection | |||
504 | +511 | 10 | let child = joiObj._inner.matches[0].then; | ||
505 | +512 | 10 | let childName = (Utilities.geJoiLabel(child) || name); | ||
506 | +513 | //name, joiObj, parent, parameterType, useDefinitions, isAlt | |||
507 | +514 | 10 | property = this.parseProperty(childName, child, property, parameterType, useDefinitions, false); | ||
508 | +515 | ||||
509 | +516 | // create the alternatives without appending to the definitionCollection | |||
510 | +517 | 10 | if (this.settings.xProperties === true) { | ||
511 | +518 | 6 | let altArray = joiObj._inner.matches | ||
512 | +519 | .reduce((res, obj) => { | |||
513 | +520 | 12 | obj.then && res.push(obj.then); | ||
514 | +521 | 12 | obj.otherwise && res.push(obj.otherwise); | ||
515 | +522 | 12 | return res; | ||
516 | +523 | }, []) | |||
517 | +524 | .map((joiNewObj) => { | |||
518 | +525 | 16 | let altName = (Utilities.geJoiLabel(joiNewObj) || name); | ||
519 | +526 | 16 | return this.parseProperty(altName, joiNewObj, property, parameterType, useDefinitions, true); | ||
520 | +527 | }) | |||
521 | +528 | .filter((obj) => obj); | |||
522 | +529 | 6 | property['x-alternatives'] = Hoek.clone(altArray); | ||
523 | +530 | } | |||
524 | +531 | } | |||
525 | +532 | ||||
526 | +533 | //if (!property.$ref && Utilities.geJoiLabel(joiObj)) { | |||
527 | +534 | // property.name = Utilities.geJoiLabel(joiObj); | |||
528 | +535 | //} | |||
529 | +536 | ||||
530 | +537 | 21 | return property; | ||
531 | +538 | }; | |||
532 | +539 | ||||
533 | +540 | ||||
534 | +541 | /** | |||
535 | +542 | * selects the correct definition collection | |||
536 | +543 | * | |||
537 | +544 | * @param {Boolean} isAlt | |||
538 | +545 | * @return {Object} | |||
539 | +546 | */ | |||
540 | +547 | 1 | internals.properties.prototype.getDefinitionCollection = function (isAlt) { | ||
541 | +548 | ||||
542 | +549 | 175 | return (isAlt === true) ? this.altDefinitionCollection : this.definitionCollection; | ||
543 | +550 | }; | |||
544 | +551 | ||||
545 | +552 | ||||
546 | +553 | /** | |||
547 | +554 | * selects the correct definition reference | |||
548 | +555 | * | |||
549 | +556 | * @param {Boolean} isAlt | |||
550 | +557 | * @return {String} | |||
551 | +558 | */ | |||
552 | +559 | 1 | internals.properties.prototype.getDefinitionRef = function (isAlt) { | ||
553 | +560 | ||||
554 | +561 | 175 | return (isAlt === true) ? '#/x-alt-definitions/' : '#/definitions/'; | ||
555 | +562 | }; | |||
556 | +563 | ||||
557 | +564 | ||||
558 | +565 | /** | |||
559 | +566 | * coverts rules into property objects | |||
560 | +567 | * | |||
561 | +568 | * @param {Object} property | |||
562 | +569 | * @param {Array} rules | |||
563 | +570 | * @param {Array} ruleNames | |||
564 | +571 | * @param {String} groupName | |||
565 | +572 | */ | |||
566 | +573 | 1 | internals.convertRules = function (property, rules, ruleNames, groupName) { | ||
567 | +574 | ||||
568 | +575 | 1538 | ruleNames.forEach((ruleName) => { | ||
569 | +576 | 5065 | internals.appendToPropertyObject(property, rules, groupName, ruleName); | ||
570 | +577 | }); | |||
571 | +578 | }; | |||
572 | +579 | ||||
573 | +580 | ||||
574 | +581 | /** | |||
575 | +582 | * appends a name item to object on a property | |||
576 | +583 | * | |||
577 | +584 | * @param {Object} property | |||
578 | +585 | * @param {Array} rules | |||
579 | +586 | * @param {String} groupName | |||
580 | +587 | * @param {String} ruleName | |||
581 | +588 | */ | |||
582 | +589 | 1 | internals.appendToPropertyObject = function (property, rules, groupName, ruleName) { | ||
583 | +590 | ||||
584 | +591 | 5065 | if (internals.hasPropertyByName(rules, ruleName)) { | ||
585 | +592 | 56 | let value = internals.getArgByName(rules, ruleName); | ||
586 | +593 | 56 | if (Utilities.isObject(value) && Utilities.hasProperties(value) === false) { | ||
587 | +594 | 1 | value = undefined; | ||
588 | +595 | } | |||
589 | +596 | 56 | internals.addToPropertyObject(property, groupName, ruleName, value); | ||
590 | +597 | } | |||
591 | +598 | }; | |||
592 | +599 | ||||
593 | +600 | ||||
594 | +601 | /** | |||
595 | +602 | * add a name item to object on a property | |||
596 | +603 | * | |||
597 | +604 | * @param {Object} property | |||
598 | +605 | * @param {String} groupName | |||
599 | +606 | * @param {String} ruleName | |||
600 | +607 | * @param {String} value | |||
601 | +608 | */ | |||
602 | +609 | 1 | internals.addToPropertyObject = function (property, groupName, ruleName, value) { | ||
603 | +610 | ||||
604 | +611 | 58 | if (!property[groupName]) { | ||
605 | +612 | 51 | property[groupName] = {}; | ||
606 | +613 | } | |||
607 | +614 | 58 | property[groupName][ruleName] = (value !== undefined) ? value : true; | ||
608 | +615 | }; | |||
609 | +616 | ||||
610 | +617 | ||||
611 | +618 | /** | |||
612 | +619 | * return the value of an item in array of object by name - structure [ { name: 'value', arg: 'value' } ] | |||
613 | +620 | * | |||
614 | +621 | * @param {Array} array | |||
615 | +622 | * @param {String} name | |||
616 | +623 | * @return {String || Undefined} | |||
617 | +624 | */ | |||
618 | +625 | 1 | internals.getArgByName = function (array, name) { | ||
619 | +626 | ||||
620 | +627 | 1056 | if (Array.isArray(array)) { | ||
621 | +628 | 206 | let i = array.length; | ||
622 | +629 | 206 | while (i--) { | ||
623 | +630 | 267 | if (array[i].name === name) { | ||
624 | +631 | 76 | return array[i].arg; | ||
625 | +632 | } | |||
626 | +633 | } | |||
627 | +634 | } | |||
628 | +635 | 980 | return undefined; | ||
629 | +636 | }; | |||
630 | +637 | ||||
631 | +638 | ||||
632 | +639 | /** | |||
633 | +640 | * return existance of an item in array of - structure [ { name: 'value' } ] | |||
634 | +641 | * | |||
635 | +642 | * @param {Array} array | |||
636 | +643 | * @param {String} name | |||
637 | +644 | * @return {Boolean} | |||
638 | +645 | */ | |||
639 | +646 | 1 | internals.hasPropertyByName = function (array, name) { | ||
640 | +647 | ||||
641 | +648 | 5270 | return array && array.some((obj) => { | ||
642 | +649 | ||||
643 | +650 | 960 | return obj.name === name; | ||
644 | +651 | }); | |||
645 | +652 | }; | |||
646 | +653 | @@ -16969,7 +17011,7 @@ | |||
15 | - | 8148 | +8207 | return obj !== null && obj !== undefined && typeof obj === 'object' && !Array.isArray(obj); | |