UNPKG

nodulator

Version:

Complete NodeJS Framework for Restfull APIs

173 lines (149 loc) 4.84 kB
/* * Copyright 2015 the original author or authors * @license MIT, see LICENSE.txt for details * * @author Scott Andrews */ (function (define) { 'use strict'; var undef; define(function (require) { var uriEncoder, operations, prefixRE; uriEncoder = require('./uriEncoder'); prefixRE = /^([^:]*):([0-9]+)$/; operations = { '': { first: '', separator: ',', named: false, empty: '', encoder: uriEncoder.encode }, '+': { first: '', separator: ',', named: false, empty: '', encoder: uriEncoder.encodeURL }, '#': { first: '#', separator: ',', named: false, empty: '', encoder: uriEncoder.encodeURL }, '.': { first: '.', separator: '.', named: false, empty: '', encoder: uriEncoder.encode }, '/': { first: '/', separator: '/', named: false, empty: '', encoder: uriEncoder.encode }, ';': { first: ';', separator: ';', named: true, empty: '', encoder: uriEncoder.encode }, '?': { first: '?', separator: '&', named: true, empty: '=', encoder: uriEncoder.encode }, '&': { first: '&', separator: '&', named: true, empty: '=', encoder: uriEncoder.encode }, '=': { reserved: true }, ',': { reserved: true }, '!': { reserved: true }, '@': { reserved: true }, '|': { reserved: true } }; function apply(operation, expression, params) { /*jshint maxcomplexity:11 */ return expression.split(',').reduce(function (result, variable) { var opts, value; opts = {}; if (variable.slice(-1) === '*') { variable = variable.slice(0, -1); opts.explode = true; } if (prefixRE.test(variable)) { var prefix = prefixRE.exec(variable); variable = prefix[1]; opts.maxLength = parseInt(prefix[2]); } variable = uriEncoder.decode(variable); value = params[variable]; if (value === undef || value === null) { return result; } if (Array.isArray(value)) { result += value.reduce(function (result, value) { if (result.length) { result += opts.explode ? operation.separator : ','; if (operation.named && opts.explode) { result += operation.encoder(variable); result += value.length ? '=' : operation.empty; } } else { result += operation.first; if (operation.named) { result += operation.encoder(variable); result += value.length ? '=' : operation.empty; } } result += operation.encoder(value); return result; }, ''); } else if (typeof value === 'object') { result += Object.keys(value).reduce(function (result, name) { if (result.length) { result += opts.explode ? operation.separator : ','; } else { result += operation.first; if (operation.named && !opts.explode) { result += operation.encoder(variable); result += value[name].length ? '=' : operation.empty; } } result += operation.encoder(name); result += opts.explode ? '=' : ','; result += operation.encoder(value[name]); return result; }, ''); } else { value = String(value); if (opts.maxLength) { value = value.slice(0, opts.maxLength); } result += result.length ? operation.separator : operation.first; if (operation.named) { result += operation.encoder(variable); result += value.length ? '=' : operation.empty; } result += operation.encoder(value); } return result; }, ''); } function expandExpression(expression, params) { var operation; operation = operations[expression.slice(0,1)]; if (operation) { expression = expression.slice(1); } else { operation = operations['']; } if (operation.reserved) { throw new Error('Reserved expression operations are not supported'); } return apply(operation, expression, params); } function expandTemplate(template, params) { var start, end, uri; uri = ''; end = 0; while (true) { start = template.indexOf('{', end); if (start === -1) { // no more expressions uri += template.slice(end); break; } uri += template.slice(end, start); end = template.indexOf('}', start) + 1; uri += expandExpression(template.slice(start + 1, end - 1), params); } return uri; } return { /** * Expand a URI Template with parameters to form a URI. * * Full implementation (level 4) of rfc6570. * @see https://tools.ietf.org/html/rfc6570 * * @param {string} template URI template * @param {Object} [params] params to apply to the template durring expantion * @returns {string} expanded URI */ expand: expandTemplate }; }); }( typeof define === 'function' && define.amd ? define : function (factory) { module.exports = factory(require); } // Boilerplate for AMD and Node ));