Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

extract-params

Package Overview
Dependencies
Maintainers
1
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

extract-params - npm Package Compare versions

Comparing version 2.1.1 to 3.0.0

LICENSE

56

lib/extractParams.js

@@ -0,1 +1,7 @@

var assign = require('lodash.assign');
var isPlainObject = require('lodash.isplainobject');
var isString = require('lodash.isstring');
var isFunction = require('lodash.isfunction');
var isUndefined = require('lodash.isundefined');
var paramRegex = /:[a-zA-Z]+/g;

@@ -12,23 +18,45 @@

module.exports = function extractParams(str, pattern, transform) {
if (typeof str !== 'string') {
throw new Error('\'str\' must be a string');
function normalisePattern(pattern) {
if (isString(pattern)) {
return { pattern: pattern, caseSensitive: true, transform: identity };
}
if (isPlainObject(pattern)) {
if (isUndefined(pattern.transform)) {
return assign({ caseSensitive: true, transform: identity }, pattern);
}
if (isFunction(pattern.transform)) {
return assign({ caseSensitive: true }, pattern);
}
throw new Error('\'transform\' must be a function');
return null;
}
if (typeof pattern !== 'string') {
throw new Error('\'pattern\' must be a string');
throw new Error('\'pattern\' must be a string or an object');
return null;
}
module.exports = function extractParams(str, pattern) {
var patternObj = normalisePattern(pattern);
if (patternObj === null) {
return null;
}
if (typeof transform === 'undefined') {
transform = identity;
} else if (typeof transform !== 'function') {
throw new Error('\'transform\' must be a function');
if (!isString(str)) {
throw new Error('\'str\' must be a string');
return null;
}
var valuesRegex = new RegExp('^' + pattern.split(paramRegex).map(function(patternPart) {
if (!(isString(patternObj.pattern))) {
throw new Error('\'pattern\' value must be a string');
return null;
}
var regexFlags = patternObj.caseSensitive ? '' : 'i';
var valuesRegex = new RegExp('^' + patternObj.pattern.split(paramRegex).map(function(patternPart) {
return escapeRegexCharacters(patternPart);
}).join('(.+)') + '$');
}).join('(.+)') + '$', regexFlags);

@@ -41,6 +69,6 @@ var valuesMatch = str.match(valuesRegex);

var paramsMatch = pattern.match(paramRegex);
var paramsMatch = patternObj.pattern.match(paramRegex);
if (paramsMatch === null) {
return transform({});
return patternObj.transform({});
}

@@ -52,3 +80,3 @@

return transform(valuesMatch.slice(1).reduce(function(result, value, index) {
return patternObj.transform(valuesMatch.slice(1).reduce(function(result, value, index) {
result[params[index]] = value;

@@ -55,0 +83,0 @@ return result;

@@ -0,5 +1,7 @@

var isString = require('lodash.isstring');
var isArray = require('lodash.isarray');
var extractParams = require('./extractParams');
module.exports = function extractParamsInFirstMatch(str, patterns) {
if (typeof str !== 'string') {
if (!(isString(str))) {
throw new Error('\'str\' must be a string');

@@ -9,3 +11,3 @@ return null;

if (typeof patterns !== 'object' || typeof patterns.length === 'undefined') {
if (!(isArray(patterns))) {
throw new Error('\'patterns\' must be an array');

@@ -18,3 +20,3 @@ return null;

for (var i = 0; i < patternsCount; i++) {
var params = extractParams(str, patterns[i].pattern, patterns[i].transform);
var params = extractParams(str, patterns[i]);

@@ -21,0 +23,0 @@ if (params !== null) {

{
"name": "extract-params",
"version": "2.1.1",
"version": "3.0.0",
"description": "Extract parameters from a string based on a pattern",

@@ -10,3 +10,4 @@ "main": "index.js",

"test-dev": "mocha test --watch --reporter min",
"build": "npm run lint && npm test"
"build": "npm run lint && npm test",
"postversion": "git push && git push --tags"
},

@@ -29,2 +30,10 @@ "repository": {

],
"dependencies": {
"lodash.assign": "^3.2.0",
"lodash.isarray": "^3.0.4",
"lodash.isfunction": "^3.0.6",
"lodash.isplainobject": "^3.2.0",
"lodash.isstring": "^3.0.1",
"lodash.isundefined": "^3.0.1"
},
"devDependencies": {

@@ -31,0 +40,0 @@ "chai": "^3.4.1",

<a href="https://codeship.com/projects/119982" target="_blank">
<img src="https://img.shields.io/codeship/ff47ba10-7c98-0133-b9e7-2e6bcf2dba9a/master.svg"
<img src="https://img.shields.io/codeship/ff47ba10-7c98-0133-b9e7-2e6bcf2dba9a/master.svg?style=flat-square"
alt="Build Status" />
</a>
<a href="https://npmjs.org/package/extract-params" target="_blank">
<img src="https://img.shields.io/npm/v/extract-params.svg"
alt="NPM Version" />
<a href="http://issuestats.com/github/moroshko/extract-params" target="_blank">
<img src="http://issuestats.com/github/moroshko/extract-params/badge/pr?style=flat-square"
alt="Pull Requests stats" />
</a>
<a href="https://npmjs.org/package/extract-params" target="_blank">
<img src="https://img.shields.io/npm/dm/extract-params.svg"
<img src="https://img.shields.io/npm/dm/extract-params.svg?style=flat-square"
alt="NPM Downloads" />
</a>
<a href="https://npmjs.org/package/extract-params" target="_blank">
<img src="https://img.shields.io/npm/v/extract-params.svg?style=flat-square"
alt="NPM Version" />
</a>

@@ -32,18 +36,12 @@ # Extract Params

* [`extractParams(str, pattern, [transform])`](#extractParams)
* [`extractParams(str, pattern)`](#extractParams)
* [`extractParamsInFirstMatch(str, patterns)`](#extractParamsInFirstMatch)
<a name="extractParams"></a>
### extractParams(str, pattern, [transform])
### extractParams(str, pattern)
Tests whether `str` matches the given parameterized `pattern`. If match is successful, it returns a hash of parameters and their values.
Tests whether `str` matches the given parameterized [pattern](#patterns). If match is successful, it returns a hash of parameters and their values. Otherwise, `extractParams` returns `null`.
Otherwise, `extractParams` returns `null`.
An optional `transform` function can be passed to manipulate the extracted params. If `transform` returns `null`, the match fails. `transform` can be used, for example, to lowercase the values in `params`, or to validate them (return `null` if validation fails).
The match is considered successful only if `str` matches the `pattern` at the start and at the end (see examples 2 and 3 below).
`pattern` parameters must have letters only.
#### Example 1

@@ -102,8 +100,23 @@

var params = extractParams(
'/users/1234/friends/456/photo',
'/users/:userId/friends/:friendId/photo',
function(params) {
var userId = parseInt(params.userId, 10);
'/USERS/123/Friends/456/photo',
'/users/:userId/friends/:friendId/photo'
);
/*
Returns:
null
return userId >= 1 && userId <= 999 ? params : null;
because the pattern is case sensitive by default
*/
```
<a name="case-insensitive-example"></a>
#### Example 5
```js
var params = extractParams(
'/USERS/123/Friends/456/photo',
{
pattern: '/users/:userId/friends/:friendId/photo',
caseSensitive: false
}

@@ -114,5 +127,62 @@ );

Returns:
{
userId: '123',
friendId: '456'
}
*/
```
<a name="lowercase-keys-example"></a>
#### Example 6
```js
function lowercaseValues(params) {
return Object.keys(params).reduce(function(result, param) {
result[param] = params[param].toLowerCase();
return result;
}, {});
}
var params = extractParams(
'/users/Misha/friends/MARK/photo',
{
pattern: '/users/:user/friends/:friend/photo',
transform: lowercaseValues
}
);
/*
Returns:
{
user: 'misha',
friend: 'mark'
}
*/
```
<a name="regex-validation-example"></a>
#### Example 7
```js
var companyRegex = /[a-zA-Z]+/;
var employeeRegex = /[a-z\-]+/;
function validator(params) {
return typeof params.company === 'string' && companyRegex.test(params.company) &&
typeof params.employee === 'string' && employeeRegex.test(params.employee);
}
var params = extractParams(
'/companies/Yahoo7/employees/david-brown',
{
pattern: '/companies/:company/employees/:employee',
transform: validator
}
);
/*
Returns:
null
because userId > 999
because 'Yahoo7' contains a number
*/

@@ -124,3 +194,3 @@ ```

Tests whether `str` matches one of the parameterized `patterns`. Every pattern can have an optional `transform` function. If none of the `patterns` match, `extractParamsInFirstMatch` returns `null`. Otherwise, it returns the matching pattern index and its parameters.
Tests whether `str` matches one of the parameterized [patterns](#patterns). If none of the `patterns` match, `extractParamsInFirstMatch` returns `null`. Otherwise, it returns the matching pattern index and its parameters.

@@ -211,2 +281,23 @@ #### Example 1

<a name="patterns"></a>
## Patterns
The functions in this library operate on a `pattern` type.
### Basic patterns
In its simplest form, pattern is just a string, e.g. `/users`.
Patterns can have parameters, e.g. `/users/:userId/friends/:friendId/photo`.
Parameters must start with a `:`, and can contain letters only. Therefore, `:username`, `:userName`, and `:USERNAME` are valid parameters, but `:user-name`, `:user_name` and `:iphone6` are not.
### Advanced patterns
For more advanced patterns, an object with the following keys can be provided:
* `pattern` - (required) The pattern string.
* `caseSensitive` - (optional) Boolean indicating whether the pattern is considered case sensitive or not. [Example](#case-insensitive-example)<br />Defaults to `true`.
* `transform` - (optional) Function that takes the extracted params, and returns a manipulated version of them. [Example](#lowercase-keys-example)<br />If it returns `null`, the match fails. [Example](#regex-validation-example)<br />Defaults to the identity function.
## Running Tests

@@ -220,2 +311,2 @@

[MIT](http://moroshko.mit-license.org)
<a href="http://moroshko.mit-license.org" target="_blank">MIT</a>

@@ -20,4 +20,6 @@ var expect = require('chai').expect;

str: '/elm',
pattern: '/:language',
transform: {},
pattern: {
pattern: '/:language',
transform: {}
},
throw: '\'transform\' must be a function'

@@ -50,15 +52,17 @@ },

{
should: 'return use the transform function if there is match but the pattern has no parameters',
should: 'use the transform function if there is match but the pattern has no parameters',
str: 'react-is-awesome',
pattern: 'react-is-awesome',
transform: function(params) {
var newParams = {
mood: 'awesome'
};
pattern: {
pattern: 'react-is-awesome',
transform: function(params) {
var newParams = {
mood: 'awesome'
};
for (var param in params) {
newParams[param] = params[param];
for (var param in params) {
newParams[param] = params[param];
}
return newParams;
}
return newParams;
},

@@ -96,13 +100,23 @@ result: {

{
should: 'handle case insensitive patterns',
str: 'My-Name-Is-Misha',
pattern: { pattern: 'my-name-is-:name', caseSensitive: false },
result: {
name: 'Misha'
}
},
{
should: 'transform the extracted params using the transform function',
str: '/users/123/friends/456/photo',
pattern: '/users/:userId/friends/:friendId/photo',
transform: function(params) {
var newParams = {};
pattern: {
pattern: '/users/:userId/friends/:friendId/photo',
transform: function(params) {
var newParams = {};
for (var param in params) {
newParams[param] = '**' + params[param] + '**';
for (var param in params) {
newParams[param] = '**' + params[param] + '**';
}
return newParams;
}
return newParams;
},

@@ -117,7 +131,9 @@ result: {

str: '/users/1234/friends/456/photo',
pattern: '/users/:userId/friends/:friendId/photo',
transform: function(params) {
var userId = parseInt(params.userId, 10);
pattern: {
pattern: '/users/:userId/friends/:friendId/photo',
transform: function(params) {
var userId = parseInt(params.userId, 10);
return userId >= 1 && userId <= 999 ? params : null;
return userId >= 1 && userId <= 999 ? params : null;
}
},

@@ -131,3 +147,3 @@ result: null

it(testCase.should, function() {
var fn = extractParams.bind(null, testCase.str, testCase.pattern, testCase.transform);
var fn = extractParams.bind(null, testCase.str, testCase.pattern);

@@ -134,0 +150,0 @@ if (testCase.throw) {

@@ -67,2 +67,31 @@ var expect = require('chai').expect;

{
should: 'return the first match if the string has mixed case when patterns are not case sensitive',
str: '/UsErS/123',
patterns: [
{ pattern: '/users/:userId/friends/:friendId/photo', caseSensitive: false },
{ pattern: '/users/:userId/friends/:friendId', caseSensitive: false },
{ pattern: '/users/:userId/friends', caseSensitive: false },
{ pattern: '/users/:userId', caseSensitive: false },
{ pattern: '/users', caseSensitive: false }
],
result: {
patternIndex: 3,
params: {
userId: '123'
}
}
},
{
should: 'return null if the string has mixed case given patterns are case sensitive by default',
str: '/UsErS/123',
patterns: [
{ pattern: '/users/:userId/friends/:friendId/photo' },
{ pattern: '/users/:userId/friends/:friendId' },
{ pattern: '/users/:userId/friends' },
{ pattern: '/users/:userId' },
{ pattern: '/users' }
],
result: null
},
{
should: 'use the transform function to return the first match',

@@ -69,0 +98,0 @@ str: '/users/1234/friends/456',

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc