コード例 #1
0
ファイル: paths.js プロジェクト: glennjones/hapi-swagger
exports = module.exports = internals.paths = function(settings) {
  this.settings = settings;
  this.definitions = new Definitions(settings);
  this.properties = new Properties(settings, {}, {});
  this.responses = new Responses(settings, {}, {});

  this.defaults = {
    responses: {}
  };

  this.schema = Joi.object({
    tags: Joi.array().items(Joi.string()),
    summary: Joi.string(),
    description: Joi.string(),
    externalDocs: Joi.object({
      description: Joi.string(),
      url: Joi.string().uri()
    }),
    operationId: Joi.string(),
    consumes: Joi.array().items(Joi.string()),
    produces: Joi.array().items(Joi.string()),
    parameters: Joi.array().items(Joi.object()),
    responses: Joi.object().required(),
    schemes: Joi.array().items(Joi.string().valid(['http', 'https', 'ws', 'wss'])),
    deprecated: Joi.boolean(),
    security: Joi.array().items(Joi.object())
  });
};
コード例 #2
0
  lab.test('reuseDefinitions = false', async () => {
    // forces two models even though the model hash is the same

    const tempRoutes = [
      {
        method: 'POST',
        path: '/store1/',
        options: {
          handler: Helper.defaultHandler,
          tags: ['api'],
          validate: {
            payload: Joi.object({
              a: Joi.number(),
              b: Joi.number(),
              operator: Joi.string(),
              equals: Joi.number()
            }).label('A')
          }
        }
      },
      {
        method: 'POST',
        path: '/store2/',
        options: {
          handler: Helper.defaultHandler,
          tags: ['api'],
          validate: {
            payload: Joi.object({
              a: Joi.number(),
              b: Joi.number(),
              operator: Joi.string(),
              equals: Joi.number()
            }).label('B')
          }
        }
      }
    ];

    const server = await Helper.createServer({ reuseDefinitions: false }, tempRoutes);

    const response = await server.inject({ method: 'GET', url: '/swagger.json' });

    //console.log(JSON.stringify(response.result));
    expect(response.statusCode).to.equal(200);
    expect(response.result.definitions.A).to.exist();
    expect(response.result.definitions.B).to.exist();
    const isValid = await Validate.test(response.result);
    expect(isValid).to.be.true();
  });
コード例 #3
0
  lab.test('test that name changing for required', async () => {
    const FormDependencyDefinition = Joi.object({
      id: Joi.number().required()
    }).label('FormDependencyDefinition');

    const ActionDefinition = Joi.object({
      id: Joi.number()
        .required()
        .allow(null),
      reminder: FormDependencyDefinition.required()
    }).label('ActionDefinition');

    let testRoutes = [
      {
        method: 'POST',
        path: '/server/',
        options: {
          handler: Helper.defaultHandler,
          tags: ['api'],
          validate: {
            payload: ActionDefinition
          }
        }
      }
    ];

    const server = await Helper.createServer({}, testRoutes);

    const response = await server.inject({ method: 'GET', url: '/swagger.json' });

    expect(response.statusCode).to.equal(200);
    expect(response.result.definitions.ActionDefinition).to.equal({
      type: 'object',
      properties: {
        id: {
          type: 'number'
        },
        reminder: {
          $ref: '#/definitions/FormDependencyDefinition'
        }
      },
      required: ['id', 'reminder']
    });
  });
コード例 #4
0
ファイル: paths.js プロジェクト: glennjones/hapi-swagger
 ['queryParams', 'pathParams', 'headerParams', 'payloadParams'].forEach(function(property) {
   // swap out any custom validation function for Joi object/string
   if (Utilities.isFunction(routeData[property])) {
     if (property !== 'pathParams') {
       self.settings.log(
         ['validation', 'warning'],
         'Using a Joi.function for a query, header or payload is not supported.'
       );
       if (property === 'payloadParams') {
         routeData[property] = Joi.object().label('Hidden Model');
       } else {
         routeData[property] = Joi.object({ 'Hidden Model': Joi.string() });
       }
     } else {
       self.settings.log(
         ['validation', 'error'],
         'Using a Joi.function for a params is not supported and has been removed.'
       );
       routeData[property] = null;
     }
   }
 });
コード例 #5
0
  lab.test('test that optional array is not in swagger output', async () => {
    let testRoutes = [
      {
        method: 'POST',
        path: '/server/1/',
        options: {
          handler: Helper.defaultHandler,
          tags: ['api'],
          validate: {
            payload: Joi.object({
              a: Joi.number().required(),
              b: Joi.string().optional()
            }).label('test')
          }
        }
      }
    ];

    const server = await Helper.createServer({}, testRoutes);

    const response = await server.inject({ method: 'GET', url: '/swagger.json' });

    expect(response.statusCode).to.equal(200);
    expect(response.result.definitions.test).to.equal({
      type: 'object',
      properties: {
        a: {
          type: 'number'
        },
        b: {
          type: 'string'
        }
      },
      required: ['a']
    });
  });
コード例 #6
0
ファイル: index.js プロジェクト: hapijs/heavy
'use strict';

const Boom = require('@hapi/boom');
const Hoek = require('@hapi/hoek');
const Joi = require('@hapi/joi');


const internals = {};


internals.schema = Joi.object({
    sampleInterval: Joi.number().min(0),
    maxHeapUsedBytes: Joi.number().min(0),
    maxEventLoopDelay: Joi.number().min(0),
    maxRssBytes: Joi.number().min(0)
})
    .unknown();


internals.defaults = {
    sampleInterval: 0,                          // Frequency of load sampling in milliseconds (zero is no sampling)
    maxHeapUsedBytes: 0,                        // Reject requests when V8 heap is over size in bytes (zero is no max)
    maxRssBytes: 0,                             // Reject requests when process RSS is over size in bytes (zero is no max)
    maxEventLoopDelay: 0                        // Milliseconds of delay after which requests are rejected (zero is no max)
};


exports = module.exports = internals.Heavy = function (options) {

    options = options || {};
コード例 #7
0
ファイル: paths.js プロジェクト: glennjones/hapi-swagger
  routes.forEach(route => {
    let routeOptions = Hoek.reach(route, 'settings.plugins.hapi-swagger') || {};
    let routeData = {
      path: route.path,
      method: route.method.toUpperCase(),
      description: route.settings.description,
      notes: route.settings.notes,
      tags: Hoek.reach(route, 'settings.tags'),
      queryParams: Hoek.reach(route, 'settings.validate.query'),
      pathParams: Hoek.reach(route, 'settings.validate.params'),
      payloadParams: Hoek.reach(route, 'settings.validate.payload'),
      responseSchema: Hoek.reach(route, 'settings.response.schema'),
      responseStatus: Hoek.reach(route, 'settings.response.status'),
      headerParams: Hoek.reach(route, 'settings.validate.headers'),
      consumes: Hoek.reach(routeOptions, 'consumes') || null,
      produces: Hoek.reach(routeOptions, 'produces') || null,
      responses: Hoek.reach(routeOptions, 'responses') || null,
      payloadType: Hoek.reach(routeOptions, 'payloadType') || null,
      security: Hoek.reach(routeOptions, 'security') || null,
      order: Hoek.reach(routeOptions, 'order') || null,
      deprecated: Hoek.reach(routeOptions, 'deprecated') || null,
      id: Hoek.reach(routeOptions, 'id') || null,
      groups: route.group
    };

    Utilities.assignVendorExtensions(routeData, routeOptions);
    routeData.path = Utilities.replaceInPath(routeData.path, ['endpoints'], this.settings.pathReplacements);

    // user configured interface through route plugin options
    if (Hoek.reach(routeOptions, 'validate.query')) {
      routeData.queryParams = Utilities.toJoiObject(Hoek.reach(routeOptions, 'validate.query'));
    }
    if (Hoek.reach(routeOptions, 'validate.params')) {
      routeData.pathParams = Utilities.toJoiObject(Hoek.reach(routeOptions, 'validate.params'));
    }
    if (Hoek.reach(routeOptions, 'validate.headers')) {
      routeData.headerParams = Utilities.toJoiObject(Hoek.reach(routeOptions, 'validate.headers'));
    }
    if (Hoek.reach(routeOptions, 'validate.payload')) {
      // has different structure, just pass straight through
      routeData.payloadParams = Hoek.reach(routeOptions, 'validate.payload');
      // if its a native javascript object convert it to JOI
      if (!routeData.payloadParams.isJoi) {
        routeData.payloadParams = Joi.object(routeData.payloadParams);
      }
    }

    // swap out any custom validation function for Joi object/string
    ['queryParams', 'pathParams', 'headerParams', 'payloadParams'].forEach(function(property) {
      // swap out any custom validation function for Joi object/string
      if (Utilities.isFunction(routeData[property])) {
        if (property !== 'pathParams') {
          self.settings.log(
            ['validation', 'warning'],
            'Using a Joi.function for a query, header or payload is not supported.'
          );
          if (property === 'payloadParams') {
            routeData[property] = Joi.object().label('Hidden Model');
          } else {
            routeData[property] = Joi.object({ 'Hidden Model': Joi.string() });
          }
        } else {
          self.settings.log(
            ['validation', 'error'],
            'Using a Joi.function for a params is not supported and has been removed.'
          );
          routeData[property] = null;
        }
      }
    });

    // hapi wildcard method support
    if (routeData.method === '*') {
      // OPTIONS not supported by Swagger and HEAD not support by HAPI
      ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'].forEach(method => {
        var newRoute = Hoek.clone(routeData);
        newRoute.method = method.toUpperCase();
        routesData.push(newRoute);
      });
    } else {
      routesData.push(routeData);
    }
  });
コード例 #8
0
const js2xmlparser = require('js2xmlparser');

const sumModel = Joi.object({
  id: Joi.string()
    .required()
    .example('x78P9c'),
  a: Joi.number()
    .required()
    .example(5),
  b: Joi.number()
    .required()
    .example(5),
  operator: Joi.string()
    .required()
    .description('either +, -, /, or *')
    .example('+'),
  equals: Joi.number()
    .required()
    .example(10),
  created: Joi.string()
    .required()
    .isoDate()
    .description('ISO date string')
    .example('2015-12-01'),
  modified: Joi.string()
    .isoDate()
    .description('ISO date string')
    .example('2015-12-01')
})
  .label('Sum')
  .description('json body for sum');
コード例 #9
0
ファイル: index.js プロジェクト: hapijs/crumb
'use strict';

const Stream = require('stream');

const Boom = require('@hapi/boom');
const Cryptiles = require('@hapi/cryptiles');
const Hoek = require('@hapi/hoek');
const Joi = require('@hapi/joi');


const internals = {
    restfulValidatedMethods: ['post', 'put', 'patch', 'delete']
};


internals.schema = Joi.object().keys({
    key: Joi.string().optional(),
    size: Joi.number().optional(),
    autoGenerate: Joi.boolean().optional(),
    addToViewContext: Joi.boolean().optional(),
    cookieOptions: Joi.object().keys(null),
    headerName: Joi.string().optional(),
    restful: Joi.boolean().optional(),
    skip: Joi.func().optional(),
    enforce: Joi.boolean().optional(),
    logUnauthorized: Joi.boolean().optional()
});


internals.defaults = {
    key: 'crumb',
コード例 #10
0
ファイル: index.js プロジェクト: hapijs/bell
internals.schema = Joi.object({
    provider: Joi.object({
        name: Joi.string().optional().default('custom'),
        protocol: Joi.string().valid('oauth', 'oauth2'),
        temporary: Joi.string().when('protocol', { is: 'oauth', then: Joi.required(), otherwise: Joi.forbidden() }),
        signatureMethod: Joi.string().valid('HMAC-SHA1', 'RSA-SHA1').when('protocol', { is: 'oauth', then: Joi.default('HMAC-SHA1'), otherwise: Joi.forbidden() }),
        auth: Joi.string().required(),
        useParamsAuth: internals.flexBoolean.default(false).when('protocol', { is: 'oauth2', then: Joi.optional(), otherwise: Joi.forbidden() }),
        token: Joi.string().required(),
        headers: Joi.object(),
        profile: Joi.func(),
        profileMethod: Joi.string().valid('get', 'post').default('get'),
        scope: Joi.alternatives().try(
            Joi.array().items(Joi.string()),
            Joi.func()
        ).when('protocol', { is: 'oauth2', otherwise: Joi.forbidden() }),
        scopeSeparator: Joi.string().when('protocol', { is: 'oauth2', otherwise: Joi.forbidden() })
    }).required(),
    password: Joi.string().required(),
    clientId: Joi.string().required(),
    clientSecret: Joi.alternatives().when('protocol', {
        is: 'oauth',
        then: Joi.string().required().allow(''),
        otherwise: Joi.alternatives().try(Joi.string().allow(''), Joi.object())
    }).required(),
    cookie: Joi.string(),
    isSameSite: Joi.valid('Strict', 'Lax').allow(false).default('Strict'),
    isSecure: internals.flexBoolean,
    isHttpOnly: internals.flexBoolean,
    ttl: Joi.number(),
    domain: Joi.string().allow(null),
    providerParams: Joi.alternatives().try(Joi.object(), Joi.func()),
    allowRuntimeProviderParams: internals.flexBoolean.default(false),
    scope: Joi.alternatives().try(
        Joi.array().items(Joi.string()),
        Joi.func()
    ).when('provider.protocol', { is: 'oauth2', otherwise: Joi.forbidden() }),
    name: Joi.string().required(),
    config: Joi.object(),
    profileParams: Joi.object(),
    skipProfile: internals.flexBoolean.optional().default(false),
    forceHttps: internals.flexBoolean.optional().default(false),
    location: Joi.alternatives().try(
        Joi.func().maxArity(1),
        Joi.string()
    ).default(false),
    runtimeStateCallback: Joi.func().optional()
});
コード例 #11
0
ファイル: schema.js プロジェクト: nlf/blankie
module.exports = Joi.object({
    baseUri: Joi.array().items(Joi.string()).single().default(['self']),
    childSrc: Joi.array().items(Joi.string()).single(),
    connectSrc: Joi.array().items(Joi.string()).single().default(['self']),
    defaultSrc: Joi.array().items(Joi.string()).single().default(['none']),
    fontSrc: Joi.array().items(Joi.string()).single(),
    formAction: Joi.array().items(Joi.string()).single(),
    frameAncestors: Joi.array().items(Joi.string()).single(),
    frameSrc: Joi.array().items(Joi.string()).single(),
    imgSrc: Joi.array().items(Joi.string()).single().default(['self']),
    manifestSrc: Joi.array().items(Joi.string()).single(),
    mediaSrc: Joi.array().items(Joi.string()).single(),
    objectSrc: Joi.array().items(Joi.string()).single(),
    oldSafari: Joi.boolean(),
    pluginTypes: Joi.array().items(Joi.string()).single(),
    reflectedXss: Joi.string().valid('allow', 'block', 'filter'),
    reportOnly: Joi.boolean(),
    reportUri: Joi.string(),
    requireSriFor: Joi.array().items(Joi.string()).single(),
    sandbox: [
        Joi.array().items(Joi.string().valid('allow-forms', 'allow-same-origin', 'allow-scripts', 'allow-top-navigation')).single(),
        Joi.boolean()
    ],
    scriptSrc: Joi.array().items(Joi.string()).single().default(['self'])
        .when('generateNonces', { is: [false, 'style'], then: Joi.array().items(Joi.string().valid('strict-dynamic').forbidden()) }),
    styleSrc: Joi.array().items(Joi.string()).single().default(['self'])
        .when('generateNonces', { is: [false, 'script'], then: Joi.array().items(Joi.string().valid('strict-dynamic').forbidden()) }),
    workerSrc: Joi.array().items(Joi.string()).single().default(['self']),
    generateNonces: Joi.alternatives().try([Joi.boolean(), Joi.string().valid('script', 'style')]).default(true)
}).with('reportOnly', 'reportUri');
コード例 #12
0
ファイル: phabricator.js プロジェクト: hapijs/bell
'use strict';

const Joi = require('@hapi/joi');


const internals = {
    schema: Joi.object({
        uri: Joi.string().uri().required()
    }).required()
};


exports = module.exports = function (options) {

    const settings = Joi.attempt(options, internals.schema);

    return {
        protocol: 'oauth2',
        useParamsAuth: true,
        auth: settings.uri + '/oauthserver/auth/',
        token: settings.uri + '/oauthserver/token/',
        scope: ['whoami'],
        scopeSeparator: ',',
        profile: async function (credentials, params, get) {

            const query = {
                access_token: credentials.token
            };

            const profile = await get(settings.uri + '/api/user.whoami', query);
コード例 #13
0
const baseSchema = require('./base-schema');
const defaults = require('./defaults');
const regExpObject = require('./reg-exp-object');

// Add some constraints that apply to both generateSW and generateSWString.
module.exports = baseSchema.keys({
  cacheId: joi.string(),
  cleanupOutdatedCaches: joi.boolean().default(defaults.cleanupOutdatedCaches),
  clientsClaim: joi.boolean().default(defaults.clientsClaim),
  directoryIndex: joi.string(),
  ignoreURLParametersMatching: joi.array().items(regExpObject),
  navigateFallback: joi.string().default(defaults.navigateFallback),
  navigateFallbackBlacklist: joi.array().items(regExpObject),
  navigateFallbackWhitelist: joi.array().items(regExpObject),
  navigationPreload: joi.boolean().default(defaults.navigationPreload),
  offlineGoogleAnalytics: joi.alternatives().try(joi.boolean(), joi.object())
      .default(defaults.offlineGoogleAnalytics),
  runtimeCaching: joi.array().items(joi.object().keys({
    method: joi.string().valid(
        'DELETE',
        'GET',
        'HEAD',
        'PATCH',
        'POST',
        'PUT'
    ),
    urlPattern: [regExpObject, joi.string(), joi.func()],
    handler: [
      joi.func(),
      joi.string().valid(
          'CacheFirst',
コード例 #14
0
ファイル: stripe.js プロジェクト: hapijs/bell
'use strict';

const Joi = require('@hapi/joi');


const internals = {
    schema: Joi.object({
        express: Joi.boolean().optional()
    }).optional()
};


exports = module.exports = (options = {}) => {

    const settings = Joi.attempt(options, internals.schema);
    const domain = 'connect.stripe.com';
    const authPrefix = settings.express ? '/express' : '';

    return {
        protocol: 'oauth2',
        useParamsAuth: true,
        auth: `https://${domain}${authPrefix}/oauth/authorize`,
        token: `https://${domain}/oauth/token`,
        scope: [],
        headers: { 'User-Agent': 'hapi-bell-stripe' },
        profile: async function (credentials, params, get) {

            const user = `https://${credentials.token}@${domain}/v1/account`;

            const profile = await get(user);
            credentials.profile = {
コード例 #15
0
  lab.test('definitionPrefix = useLabel', async () => {
    // use the label as a prefix for dynamic model names

    const tempRoutes = [
      {
        method: 'POST',
        path: '/store1/',
        options: {
          handler: Helper.defaultHandler,
          tags: ['api'],
          validate: {
            payload: Joi.object({
              a: Joi.number(),
              b: Joi.number(),
              operator: Joi.string(),
              equals: Joi.number()
            }).label('A')
          }
        }
      },
      {
        method: 'POST',
        path: '/store2/',
        options: {
          handler: Helper.defaultHandler,
          tags: ['api'],
          validate: {
            payload: Joi.object({
              c: Joi.number(),
              v: Joi.number(),
              operator: Joi.string(),
              equals: Joi.number()
            }).label('A A')
          }
        }
      },
      {
        method: 'POST',
        path: '/store3/',
        options: {
          handler: Helper.defaultHandler,
          tags: ['api'],
          validate: {
            payload: Joi.object({
              c: Joi.number(),
              f: Joi.number(),
              operator: Joi.string(),
              equals: Joi.number()
            }).label('A')
          }
        }
      }
    ];

    const server = await Helper.createServer({ definitionPrefix: 'useLabel' }, tempRoutes);

    const response = await server.inject({ method: 'GET', url: '/swagger.json' });

    expect(response.statusCode).to.equal(200);
    expect(response.result.definitions.A).to.exist();
    expect(response.result.definitions['A A']).to.exist();
    expect(response.result.definitions['A 1']).to.exist();
    const isValid = await Validate.test(response.result);
    expect(isValid).to.be.true();
  });
コード例 #16
0
ファイル: index.js プロジェクト: hapijs/statehood
const internals = {};


internals.schema = Joi.object({
    strictHeader: Joi.boolean(),
    ignoreErrors: Joi.boolean(),
    isSecure: Joi.boolean(),
    isHttpOnly: Joi.boolean(),
    isSameSite: Joi.valid('Strict', 'Lax').allow(false),
    path: Joi.string().allow(null),
    domain: Joi.string().allow(null),
    ttl: Joi.number().allow(null),
    encoding: Joi.string().valid('base64json', 'base64', 'form', 'iron', 'none'),
    sign: Joi.object({
        password: [Joi.string(), Joi.binary(), Joi.object()],
        integrity: Joi.object()
    }),
    iron: Joi.object(),
    password: [Joi.string(), Joi.binary(), Joi.object()],

    // Used by hapi

    clearInvalid: Joi.boolean(),
    autoValue: Joi.any(),
    passThrough: Joi.boolean()
});


internals.defaults = {
    strictHeader: true,                             // Require an RFC 6265 compliant header format
コード例 #17
0
ファイル: index.js プロジェクト: felixheck/akaya
/**
 * @type {Object}
 * @private
 *
 * Store internal objects
 */
const internals = {
  regexp: {
    braces: /[{}']+/g,
    params: /\{(\w+\*?|\w+\?|\w+\*[1-9][0-9]*)\}/g,
    wildcard: /\*$/g
  },
  scheme: {
    params: {
      query: joi.object(),
      params: joi.object()
    },
    options: {
      secure: joi.boolean(),
      rel: joi.boolean().default(false),
      host: joi.string()
    }
  }
}

/**
 * @function
 * @private
 *
 * Check if condition is true and throw error if not
コード例 #18
0
ファイル: index.js プロジェクト: hapijs/h2o2
};


internals.schema = Joi.object({
    httpClient: Joi.object({
        request: Joi.func(),
        parseCacheControl: Joi.func()
    }),
    host: Joi.string(),
    port: Joi.number().integer(),
    protocol: Joi.string().valid('http', 'https', 'http:', 'https:'),
    uri: Joi.string(),
    passThrough: Joi.boolean(),
    localStatePassThrough: Joi.boolean(),
    acceptEncoding: Joi.boolean().when('passThrough', { is: true, otherwise: Joi.forbidden() }),
    rejectUnauthorized: Joi.boolean(),
    xforward: Joi.boolean(),
    redirects: Joi.number().min(0).integer().allow(false),
    timeout: Joi.number().integer(),
    mapUri: Joi.func(),
    onResponse: Joi.func(),
    onRequest: Joi.func(),
    agent: Joi.object(),
    ttl: Joi.string().valid('upstream').allow(null),
    maxSockets: Joi.number().positive().allow(false),
    secureProtocol: Joi.string(),
    ciphers: Joi.string(),
    downstreamResponseTime: Joi.boolean()
})
    .xor('host', 'mapUri', 'uri')
    .without('mapUri', 'port')
    .without('mapUri', 'protocol')
コード例 #19
0
ファイル: ping.js プロジェクト: ipfs/js-ipfs
'use strict'

const Joi = require('@hapi/joi')
const pull = require('pull-stream')
const ndjson = require('pull-ndjson')
const { PassThrough } = require('readable-stream')

module.exports = {
  validate: {
    query: Joi.object().keys({
      n: Joi.alternatives()
        .when('count', {
          is: Joi.any().exist(),
          then: Joi.any().forbidden(),
          otherwise: Joi.number().integer().greater(0)
        }),
      count: Joi.number().integer().greater(0),
      arg: Joi.string().required()
    }).unknown()
  },
  async handler (request, h) {
    const { ipfs } = request.server.app
    const peerId = request.query.arg

    // Default count to 10
    const count = request.query.n || request.query.count || 10

    const responseStream = await new Promise((resolve, reject) => {
      const stream = new PassThrough()

      pull(
コード例 #20
0
ファイル: config.js プロジェクト: addyosmani/critical
const DEFAULT = {
  width: 1300,
  height: 900,
  timeout: 30000,
  maxImageFileSize: 10240,
  minify: true,
  inline: false,
  strict: false,
  extract: false,
  inlineImages: false,
  concurrency: Infinity,
  include: [],
};

const schema = Joi.object()
  .keys({
    html: Joi.string(),
    src: [Joi.string(), Joi.object()],
    css: [Joi.string(), Joi.array()],
    base: Joi.string(),
    strict: Joi.boolean().default(DEFAULT.strict),
    extract: Joi.boolean().default(DEFAULT.extract),
    inlineImages: Joi.boolean().default(DEFAULT.inlineImages),
    postcss: Joi.array(),
    ignore: [Joi.array(), Joi.object().unknown(true)],
    width: Joi.number().default(DEFAULT.width),
    height: Joi.number().default(DEFAULT.height),
    minify: Joi.boolean().default(DEFAULT.minify),
    dimensions: Joi.array().items({width: Joi.number(), height: Joi.number()}),
    inline: [Joi.boolean().default(DEFAULT.inline), Joi.object().unknown(true)],
コード例 #21
0
ファイル: salesforce.js プロジェクト: hapijs/bell
'use strict';

const Hoek = require('@hapi/hoek');
const Joi = require('@hapi/joi');


const internals = {};


internals.schema = Joi.object({
    uri: Joi.string().uri().optional(),
    extendedProfile: Joi.boolean().optional(),
    identityServiceProfile: Joi.boolean().optional().when('extendedProfile', { is: false, then: Joi.invalid(true) })
});


internals.defaults = {
    uri: 'https://login.salesforce.com',
    extendedProfile: true,
    identityServiceProfile: false
};


exports = module.exports = function (options) {

    const combinedSettings = Hoek.applyToDefaults(internals.defaults, options || {});
    const settings = Joi.attempt(combinedSettings, internals.schema);

    return {
        protocol: 'oauth2',
        auth: settings.uri + '/services/oauth2/authorize',
コード例 #22
0
ファイル: lout-test.js プロジェクト: glennjones/hapi-swagger
lab.experiment('lout examples', () => {
  // these are example are taken from https://github.com/hapijs/lout/blob/master/test/routes/default.js
  /*
    Copyright (c) 2012-2014, Walmart and other contributors.
    All rights reserved.

    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions are met:
        * Redistributions of source '@hapi/code' must retain the above copyright
        notice, this list of conditions and the following disclaimer.
        * Redistributions in binary form must reproduce the above copyright
        notice, this list of conditions and the following disclaimer in the
        documentation and/or other materials provided with the distribution.
        * The names of any contributors may not be used to endorse or promote
        products derived from this software without specific prior written
        permission.

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY
    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    */
  const routes = [
    {
      method: 'GET',
      path: '/test',
      config: {
        handler: Helper.defaultHandler,
        validate: {
          query: {
            param1: Joi.string()
              .insensitive()
              .required()
          }
        },
        tags: ['api'],
        description: 'Test GET',
        notes: 'test note'
      }
    },
    {
      method: 'GET',
      path: '/another/test',
      config: {
        tags: ['api'],
        handler: Helper.defaultHandler,
        validate: {
          query: {
            param1: Joi.string().required()
          }
        }
      }
    },
    {
      method: 'GET',
      path: '/zanother/test',
      config: {
        tags: ['api'],
        handler: Helper.defaultHandler,
        validate: {
          query: {
            param1: Joi.string().required()
          }
        }
      }
    },
    {
      method: 'POST',
      path: '/test',
      config: {
        tags: ['api'],
        handler: Helper.defaultHandler,
        validate: {
          query: {
            param2: Joi.string().valid('first', 'last'),
            param3: 'third',
            param4: 42
          }
        }
      }
    },
    {
      method: 'DELETE',
      path: '/test',
      config: {
        tags: ['api'],
        handler: Helper.defaultHandler,
        validate: {
          query: {
            param2: Joi.string().valid('first', 'last')
          }
        }
      }
    },
    {
      method: 'PUT',
      path: '/test',
      config: {
        tags: ['api'],
        handler: Helper.defaultHandler,
        validate: {
          query: {
            param2: Joi.string().valid('first', 'last')
          }
        }
      }
    },
    {
      method: 'PATCH',
      path: '/test',
      config: {
        tags: ['api'],
        handler: Helper.defaultHandler,
        validate: {
          query: {
            param2: Joi.string().valid('first', 'last'),
            param3: Joi.number().valid(42)
          }
        }
      }
    },
    {
      method: 'GET',
      path: '/notincluded',
      config: {
        tags: ['api'],
        handler: Helper.defaultHandler,
        plugins: {
          lout: false
        }
      }
    },
    {
      method: 'GET',
      path: '/nested',
      config: {
        tags: ['api'],
        handler: Helper.defaultHandler,
        validate: {
          query: {
            param1: Joi.object({
              nestedparam1: Joi.string().required(),
              array: Joi.array()
            })
          }
        }
      }
    },
    {
      method: 'GET',
      path: '/rootobject',
      config: {
        tags: ['api'],
        handler: Helper.defaultHandler,
        validate: {
          query: Joi.object({
            param1: Joi.string().required()
          })
        }
      }
    },
    {
      method: 'GET',
      path: '/rootarray',
      config: {
        tags: ['api'],
        handler: Helper.defaultHandler,
        validate: {
          query: Joi.array()
            .items(Joi.string().required(), Joi.object({ param1: Joi.number() }), Joi.number().forbidden())
            .min(2)
            .max(5)
            .length(3)
        }
      }
    },
    {
      method: 'GET',
      path: '/complexarray',
      config: {
        tags: ['api'],
        handler: Helper.defaultHandler,
        validate: {
          query: Joi.array()
            .ordered('foo', 'bar')
            .items(
              Joi.string().required(),
              Joi.string()
                .valid('four')
                .forbidden(),
              Joi.object({ param1: Joi.number() }),
              Joi.number().forbidden()
            )
            .min(2)
            .max(5)
            .length(3)
            .ordered('bar', 'bar')
            .items(Joi.number().required())
        }
      }
    },
    {
      method: 'GET',
      path: '/path/{pparam}/test',
      config: {
        tags: ['api'],
        handler: Helper.defaultHandler,
        validate: {
          params: {
            pparam: Joi.string().required()
          }
        }
      }
    },
    {
      method: 'GET',
      path: '/emptyobject',
      config: {
        tags: ['api'],
        handler: Helper.defaultHandler,
        validate: {
          query: {
            param1: Joi.object()
          }
        }
      }
    },
    {
      method: 'GET',
      path: '/alternatives',
      config: {
        tags: ['api'],
        handler: Helper.defaultHandler,
        validate: {
          query: {
            param1: Joi.alternatives().try(Joi.number().required(), Joi.string().valid('first', 'last'))
          }
        }
      }
    },
    {
      method: 'GET',
      path: '/withnestedalternatives',
      config: {
        tags: ['api'],
        handler: Helper.defaultHandler,
        validate: {
          query: {
            param1: Joi.object({
              param2: Joi.alternatives().try(
                {
                  param3: Joi.object({
                    param4: Joi.number().example(5)
                  }).description('this is cool too')
                },
                Joi.number().min(42)
              )
            }).description('something really cool'),
            param2: Joi.array()
              .items(
                Joi.object({
                  param2: Joi.alternatives().try(
                    {
                      param3: Joi.object({
                        param4: Joi.number().example(5)
                      }).description('this is cool too')
                    },
                    Joi.array().items('foo', 'bar'),
                    Joi.number()
                      .min(42)
                      .required(),
                    Joi.number()
                      .max(42)
                      .required()
                  )
                }).description('all the way down')
              )
              .description('something really cool')
          }
        }
      }
    },
    {
      method: 'GET',
      path: '/novalidation',
      config: {
        tags: ['api'],
        handler: Helper.defaultHandler
      }
    },
    {
      method: 'GET',
      path: '/withresponse',
      config: {
        tags: ['api'],
        handler: Helper.defaultHandler,
        response: {
          schema: {
            param1: Joi.string()
          }
        }
      }
    },
    {
      method: 'GET',
      path: '/withstatus',
      config: {
        tags: ['api'],
        handler: Helper.defaultHandler,
        response: {
          schema: {
            param1: Joi.string()
          },
          status: {
            204: {
              param2: Joi.string()
            },
            404: {
              error: 'Failure'
            }
          }
        }
      }
    },
    {
      method: 'GET',
      path: '/withpojoinarray',
      config: {
        tags: ['api'],
        handler: Helper.defaultHandler,
        validate: {
          query: {
            param1: Joi.array().items({
              param2: Joi.string()
            })
          }
        }
      }
    },
    {
      method: 'POST',
      path: '/withnestedrulesarray',
      config: {
        tags: ['api'],
        handler: Helper.defaultHandler,
        validate: {
          payload: {
            param1: Joi.array().items(
              Joi.object({
                param2: Joi.array()
                  .items(
                    Joi.object({
                      param3: Joi.string()
                    })
                  )
                  .optional()
              })
            )
          }
        }
      }
    },
    {
      method: 'GET',
      path: '/withhtmlnote',
      config: {
        tags: ['api'],
        handler: Helper.defaultHandler,
        validate: {
          query: {
            param1: Joi.string().notes('<span class="htmltypenote">HTML type note</span>')
          }
        },
        notes: '<span class="htmlroutenote">HTML route note</span>'
      }
    },
    {
      method: 'GET',
      path: '/withnotesarray',
      config: {
        tags: ['api'],
        handler: Helper.defaultHandler,
        validate: {
          query: {
            param1: Joi.string().notes([
              '<span class="htmltypenote">HTML type note</span>',
              '<span class="htmltypenote">HTML type note</span>'
            ])
          }
        }
      }
    },
    {
      method: 'GET',
      path: '/withexample',
      config: {
        tags: ['api'],
        handler: Helper.defaultHandler,
        validate: {
          query: {
            param1: Joi.string()
              .regex(/^\w{1,5}$/)
              .example('abcde')
          }
        }
      }
    },
    {
      method: 'POST',
      path: '/denybody',
      config: {
        tags: ['api'],
        handler: Helper.defaultHandler,
        validate: {
          payload: false
        }
      }
    },
    {
      method: 'POST',
      path: '/rootemptyobject',
      config: {
        tags: ['api'],
        handler: Helper.defaultHandler,
        validate: {
          payload: Joi.object()
        }
      }
    },
    {
      method: 'GET',
      path: '/withnestedexamples',
      config: {
        tags: ['api'],
        handler: Helper.defaultHandler,
        validate: {
          query: {
            param1: Joi.object({
              param2: Joi.object({
                param3: Joi.number().example(5)
              }).example({
                param3: 5
              })
            }).example({
              param2: {
                param3: 5
              }
            })
          }
        }
      }
    },
    {
      method: 'GET',
      path: '/withmeta',
      config: {
        tags: ['api'],
        handler: Helper.defaultHandler,
        validate: {
          query: {
            param1: Joi.string().meta({
              index: true,
              unique: true
            })
          }
        }
      }
    },
    {
      method: 'GET',
      path: '/withunit',
      config: {
        tags: ['api'],
        handler: Helper.defaultHandler,
        validate: {
          query: {
            param1: Joi.number().unit('ms')
          }
        }
      }
    },
    {
      method: 'GET',
      path: '/withdefaultvalue',
      config: {
        tags: ['api'],
        handler: Helper.defaultHandler,
        validate: {
          query: {
            param1: Joi.number().default(42)
          }
        }
      }
    },
    {
      method: 'GET',
      path: '/withbinaryencoding',
      config: {
        tags: ['api'],
        handler: Helper.defaultHandler,
        validate: {
          query: {
            param1: Joi.binary()
              .min(42)
              .max(128)
              .length(64)
              .encoding('base64')
          }
        }
      }
    },
    {
      method: 'GET',
      path: '/withdate',
      config: {
        tags: ['api'],
        handler: Helper.defaultHandler,
        validate: {
          query: {
            param1: Joi.date()
              .min('1-1-1974')
              .max('12-31-2020')
          }
        }
      }
    },
    {
      method: 'GET',
      path: '/withpeersconditions',
      config: {
        tags: ['api'],
        handler: Helper.defaultHandler,
        validate: {
          query: {
            param1: Joi.object()
              .and('a', 'b', 'c')
              .or('a', 'b', 'c')
              .xor('a', 'b', 'c')
              .with('a', ['b', 'c'])
              .without('a', ['b', 'c'])
          }
        }
      }
    },
    {
      method: 'GET',
      path: '/withpattern',
      config: {
        tags: ['api'],
        handler: Helper.defaultHandler,
        validate: {
          query: {
            param1: Joi.object({
              a: Joi.string()
            }).pattern(/\w\d/, Joi.boolean())
          }
        }
      }
    },
    {
      method: 'GET',
      path: '/withallowunknown',
      config: {
        tags: ['api'],
        handler: Helper.defaultHandler,
        validate: {
          query: {
            param1: Joi.object().unknown(),
            param2: Joi.object().unknown(false)
          }
        }
      }
    },
    {
      method: 'GET',
      path: '/withstringspecifics',
      config: {
        tags: ['api'],
        handler: Helper.defaultHandler,
        validate: {
          query: {
            param1: Joi.string()
              .alphanum()
              .regex(/\d{3}.*/)
              .token()
              .email()
              .guid()
              .isoDate()
              .hostname()
              .lowercase()
              .uppercase()
              .trim(),
            param2: Joi.string().email()
          }
        }
      }
    },
    {
      method: 'GET',
      path: '/withconditionalalternatives',
      config: {
        tags: ['api'],
        handler: Helper.defaultHandler,
        validate: {
          query: {
            param1: Joi.alternatives()
              .when('b', {
                is: 5,
                then: Joi.string(),
                otherwise: Joi.number()
                  .required()
                  .description('Things and stuff')
              })
              .when('a', {
                is: true,
                then: Joi.date(),
                otherwise: Joi.any()
              }),
            param2: Joi.alternatives()
              .when('b', {
                is: 5,
                then: Joi.string()
              })
              .when('a', {
                is: true,
                otherwise: Joi.any()
              })
          }
        }
      }
    },
    {
      method: 'GET',
      path: '/withreferences',
      config: {
        tags: ['api'],
        handler: Helper.defaultHandler,
        validate: {
          query: {
            param1: Joi.ref('a.b'),
            param2: Joi.ref('$x')
          }
        }
      }
    },
    {
      method: 'GET',
      path: '/withassert',
      config: {
        tags: ['api'],
        handler: Helper.defaultHandler,
        validate: {
          query: {
            param1: Joi.object().assert('d.e', Joi.ref('a.c'), 'equal to a.c'),
            param2: Joi.object().assert('$x', Joi.ref('b.e'), 'equal to b.e')
          }
        }
      }
    },
    {
      method: 'GET',
      path: '/withproperties',
      vhost: 'john.doe',
      config: {
        tags: ['api'],
        handler: Helper.defaultHandler,
        cors: {
          maxAge: 12345
        },
        jsonp: 'callback'
      }
    },
    {
      method: 'OPTIONS',
      path: '/optionstest',
      handler: Helper.defaultHandler
    },
    {
      method: 'GET',
      path: '/withrulereference',
      config: {
        tags: ['api'],
        handler: Helper.defaultHandler,
        validate: {
          query: {
            param1: Joi.date().min(Joi.ref('param2')),
            param2: Joi.date()
          }
        }
      }
    },
    {
      method: 'GET',
      path: '/withcorstrue',
      vhost: 'john.doe',
      config: {
        tags: ['api'],
        handler: Helper.defaultHandler,
        cors: true
      }
    },
    {
      method: 'GET',
      path: '/withstrip',
      config: {
        tags: ['api'],
        handler: Helper.defaultHandler,
        validate: {
          query: {
            param1: Joi.any().strip(),
            param2: Joi.any()
          }
        }
      }
    },
    {
      method: 'GET',
      path: '/internal',
      config: {
        tags: ['api'],
        isInternal: true,
        handler: Helper.defaultHandler
      }
    }
  ];

  lab.test('all routes parsed', async () => {
    const server = await Helper.createServer({}, routes);
    const response = await server.inject({ method: 'GET', url: '/swagger.json' });
    expect(response.statusCode).to.equal(200);
    // the 40 to 45 difference is in one route having a number of methods
    expect(response.result.paths).to.have.length(40);
  });
});
コード例 #23
0
ファイル: base-schema.js プロジェクト: bwu86/GroupMeet-App
/*
  Copyright 2018 Google LLC

  Use of this source code is governed by an MIT-style
  license that can be found in the LICENSE file or at
  https://opensource.org/licenses/MIT.
*/

const joi = require('@hapi/joi');

const defaults = require('./defaults');
const regExpObject = require('./reg-exp-object');

// Define some common constraints used by all methods.
module.exports = joi.object().keys({
  dontCacheBustURLsMatching: regExpObject,
  globFollow: joi.boolean().default(defaults.globFollow),
  globIgnores: joi.array().items(joi.string()).default(defaults.globIgnores),
  globPatterns: joi.array().items(joi.string()).default(defaults.globPatterns),
  globStrict: joi.boolean().default(defaults.globStrict),
  manifestTransforms: joi.array().items(joi.func().arity(1)),
  maximumFileSizeToCacheInBytes: joi.number().min(1)
      .default(defaults.maximumFileSizeToCacheInBytes),
  modifyURLPrefix: joi.object(),
  // templatedURLs is an object where any property name is valid, and the values
  // can be either a string or an array of strings.
  templatedURLs: joi.object().pattern(/./,
      [joi.string(), joi.array().items(joi.string())]),
});
コード例 #24
0
// Declare Internals

const internals = {};

internals.defaults = {
    accessTokenName: 'access_token',
    allowQueryToken: false,
    allowCookieToken: false,
    allowMultipleHeaders: false,
    allowChaining: false,
    tokenType: 'Bearer',
    unauthorized: Boom.unauthorized
};

internals.schema = Joi.object().keys({
    validate: Joi.func().required(),
    accessTokenName: Joi.string().required(),
    allowQueryToken: Joi.boolean(),
    allowCookieToken: Joi.boolean(),
    allowMultipleHeaders: Joi.boolean(),
    allowChaining: Joi.boolean(),
    tokenType: Joi.string().required(),
    unauthorized: Joi.func()
});

internals.implementation = (server, options) => {

    Hoek.assert(options, 'Missing bearer auth strategy options');

    const settings = Hoek.applyToDefaults(internals.defaults, options);
コード例 #25
0
lab.experiment('definitions', () => {
  const routes = [
    {
      method: 'POST',
      path: '/test/',
      options: {
        handler: Helper.defaultHandler,
        tags: ['api'],
        validate: {
          payload: {
            a: Joi.number()
              .required()
              .description('the first number'),

            b: Joi.number()
              .required()
              .description('the second number'),

            operator: Joi.string()
              .required()
              .default('+')
              .description('the opertator i.e. + - / or *'),

            equals: Joi.number()
              .required()
              .description('the result of the sum')
          }
        }
      }
    },
    {
      method: 'POST',
      path: '/test/2',
      options: {
        handler: Helper.defaultHandler,
        tags: ['api'],
        validate: {
          payload: Joi.object({
            a: Joi.string(),
            b: Joi.object({
              c: Joi.string()
            })
          }).label('Model')
        }
      }
    },
    {
      method: 'POST',
      path: '/test/3',
      options: {
        handler: Helper.defaultHandler,
        tags: ['api'],
        validate: {
          payload: Joi.object({
            a: Joi.string(),
            b: Joi.object({
              c: Joi.string()
            })
          }).label('Model 1')
        }
      }
    }
  ];

  lab.test('payload with inline definition', async () => {
    const server = await Helper.createServer({}, routes);

    const defination = {
      properties: {
        a: {
          description: 'the first number',
          type: 'number'
        },
        b: {
          description: 'the second number',
          type: 'number'
        },
        operator: {
          description: 'the opertator i.e. + - / or *',
          default: '+',
          type: 'string'
        },
        equals: {
          description: 'the result of the sum',
          type: 'number'
        }
      },
      required: ['a', 'b', 'operator', 'equals'],
      type: 'object'
    };

    const response = await server.inject({ method: 'GET', url: '/swagger.json' });

    expect(response.statusCode).to.equal(200);
    expect(response.result.paths['/test/'].post.parameters[0].schema).to.equal({
      $ref: '#/definitions/Model 1'
    });
    expect(response.result.definitions['Model 1']).to.equal(defination);
    const isValid = await Validate.test(response.result);
    expect(isValid).to.be.true();
  });

  lab.test('override definition named Model', async () => {
    const server = await Helper.createServer({}, routes);
    const response = await server.inject({ method: 'GET', url: '/swagger.json' });

    //console.log(JSON.stringify(response.result.definitions));
    expect(response.result.definitions.b).to.exists();
    expect(response.result.definitions.Model).to.exists();
    expect(response.result.definitions['Model 1']).to.exists();

    const isValid = await Validate.test(response.result);
    expect(isValid).to.be.true();
  });

  lab.test('reuseDefinitions = false', async () => {
    // forces two models even though the model hash is the same

    const tempRoutes = [
      {
        method: 'POST',
        path: '/store1/',
        options: {
          handler: Helper.defaultHandler,
          tags: ['api'],
          validate: {
            payload: Joi.object({
              a: Joi.number(),
              b: Joi.number(),
              operator: Joi.string(),
              equals: Joi.number()
            }).label('A')
          }
        }
      },
      {
        method: 'POST',
        path: '/store2/',
        options: {
          handler: Helper.defaultHandler,
          tags: ['api'],
          validate: {
            payload: Joi.object({
              a: Joi.number(),
              b: Joi.number(),
              operator: Joi.string(),
              equals: Joi.number()
            }).label('B')
          }
        }
      }
    ];

    const server = await Helper.createServer({ reuseDefinitions: false }, tempRoutes);

    const response = await server.inject({ method: 'GET', url: '/swagger.json' });

    //console.log(JSON.stringify(response.result));
    expect(response.statusCode).to.equal(200);
    expect(response.result.definitions.A).to.exist();
    expect(response.result.definitions.B).to.exist();
    const isValid = await Validate.test(response.result);
    expect(isValid).to.be.true();
  });

  lab.test('definitionPrefix = useLabel', async () => {
    // use the label as a prefix for dynamic model names

    const tempRoutes = [
      {
        method: 'POST',
        path: '/store1/',
        options: {
          handler: Helper.defaultHandler,
          tags: ['api'],
          validate: {
            payload: Joi.object({
              a: Joi.number(),
              b: Joi.number(),
              operator: Joi.string(),
              equals: Joi.number()
            }).label('A')
          }
        }
      },
      {
        method: 'POST',
        path: '/store2/',
        options: {
          handler: Helper.defaultHandler,
          tags: ['api'],
          validate: {
            payload: Joi.object({
              c: Joi.number(),
              v: Joi.number(),
              operator: Joi.string(),
              equals: Joi.number()
            }).label('A A')
          }
        }
      },
      {
        method: 'POST',
        path: '/store3/',
        options: {
          handler: Helper.defaultHandler,
          tags: ['api'],
          validate: {
            payload: Joi.object({
              c: Joi.number(),
              f: Joi.number(),
              operator: Joi.string(),
              equals: Joi.number()
            }).label('A')
          }
        }
      }
    ];

    const server = await Helper.createServer({ definitionPrefix: 'useLabel' }, tempRoutes);

    const response = await server.inject({ method: 'GET', url: '/swagger.json' });

    expect(response.statusCode).to.equal(200);
    expect(response.result.definitions.A).to.exist();
    expect(response.result.definitions['A A']).to.exist();
    expect(response.result.definitions['A 1']).to.exist();
    const isValid = await Validate.test(response.result);
    expect(isValid).to.be.true();
  });

  lab.test('test that optional array is not in swagger output', async () => {
    let testRoutes = [
      {
        method: 'POST',
        path: '/server/1/',
        options: {
          handler: Helper.defaultHandler,
          tags: ['api'],
          validate: {
            payload: Joi.object({
              a: Joi.number().required(),
              b: Joi.string().optional()
            }).label('test')
          }
        }
      }
    ];

    const server = await Helper.createServer({}, testRoutes);

    const response = await server.inject({ method: 'GET', url: '/swagger.json' });

    expect(response.statusCode).to.equal(200);
    expect(response.result.definitions.test).to.equal({
      type: 'object',
      properties: {
        a: {
          type: 'number'
        },
        b: {
          type: 'string'
        }
      },
      required: ['a']
    });
  });

  lab.test('test that name changing for required', async () => {
    const FormDependencyDefinition = Joi.object({
      id: Joi.number().required()
    }).label('FormDependencyDefinition');

    const ActionDefinition = Joi.object({
      id: Joi.number()
        .required()
        .allow(null),
      reminder: FormDependencyDefinition.required()
    }).label('ActionDefinition');

    let testRoutes = [
      {
        method: 'POST',
        path: '/server/',
        options: {
          handler: Helper.defaultHandler,
          tags: ['api'],
          validate: {
            payload: ActionDefinition
          }
        }
      }
    ];

    const server = await Helper.createServer({}, testRoutes);

    const response = await server.inject({ method: 'GET', url: '/swagger.json' });

    expect(response.statusCode).to.equal(200);
    expect(response.result.definitions.ActionDefinition).to.equal({
      type: 'object',
      properties: {
        id: {
          type: 'number'
        },
        reminder: {
          $ref: '#/definitions/FormDependencyDefinition'
        }
      },
      required: ['id', 'reminder']
    });
  });
});
コード例 #26
0
ファイル: index.js プロジェクト: hapijs/shot
'use strict';

const Hoek = require('@hapi/hoek');
const Joi = require('@hapi/joi');

const Request = require('./request');
const Response = require('./response');
const Symbols = require('./symbols');


const internals = {};


internals.options = Joi.object().keys({
    url: Joi.alternatives([
        Joi.string(),
        Joi.object().keys({
            protocol: Joi.string(),
            hostname: Joi.string(),
            port: Joi.any(),
            pathname: Joi.string().required(),
            query: Joi.any()
        })
    ])
        .required(),
    headers: Joi.object(),
    payload: Joi.any(),
    simulate: {
        end: Joi.boolean(),
        split: Joi.boolean(),
        error: Joi.boolean(),