path-parser
Advanced tools
Comparing version 5.1.0 to 6.0.0
@@ -0,1 +1,16 @@ | ||
# [6.0.0](https://github.com/troch/path-parser/compare/v5.1.0...v6.0.0) (2020-01-05) | ||
### Features | ||
* add option `urlParamsEncoding` for specifying encoding and decoding of URL params ([#46](https://github.com/troch/path-parser/issues/46)) ([eb8d728](https://github.com/troch/path-parser/commit/eb8d728f99afe5fe6fa1eee45562813a16dcf118)) | ||
### BREAKING CHANGES | ||
* `queryParams` options from `build`, `test` and `partialTest` has been moved to `Path` constructor | ||
* The new `urlParamsEncoding` option changes the default encoding and decoding. See the README for available encoding and decoding methods. | ||
* Option interfaces have been renamed (`PathTestOptions`, `PathBuildOptions`, `PathPartialTestOptions`) | ||
# [5.1.0](https://github.com/troch/path-parser/compare/v5.0.1...v5.1.0) (2019-12-30) | ||
@@ -2,0 +17,0 @@ |
@@ -8,4 +8,55 @@ 'use strict'; | ||
/** | ||
* We encode using encodeURIComponent but we want to | ||
* preserver certain characters which are commonly used | ||
* (sub delimiters and ':') | ||
* | ||
* https://www.ietf.org/rfc/rfc3986.txt | ||
* | ||
* reserved = gen-delims / sub-delims | ||
* | ||
* gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" | ||
* | ||
* sub-delims = "!" / "$" / "&" / "'" / "(" / ")" | ||
/ "*" / "+" / "," / ";" / "=" | ||
*/ | ||
var excludeSubDelimiters = /[^!$'()*+,;|:]/g; | ||
var encodeURIComponentExcludingSubDelims = function encodeURIComponentExcludingSubDelims(segment) { | ||
return segment.replace(excludeSubDelimiters, function (match) { | ||
return encodeURIComponent(match); | ||
}); | ||
}; | ||
var encodingMethods = { | ||
"default": encodeURIComponentExcludingSubDelims, | ||
uri: encodeURI, | ||
uriComponent: encodeURIComponent, | ||
none: function none(val) { | ||
return val; | ||
}, | ||
legacy: encodeURI | ||
}; | ||
var decodingMethods = { | ||
"default": decodeURIComponent, | ||
uri: decodeURI, | ||
uriComponent: decodeURIComponent, | ||
none: function none(val) { | ||
return val; | ||
}, | ||
legacy: decodeURIComponent | ||
}; | ||
var encodeParam = function encodeParam(param, encoding, isSpatParam) { | ||
var encoder = encodingMethods[encoding] || encodeURIComponentExcludingSubDelims; | ||
if (isSpatParam) { | ||
return String(param).split('/').map(encoder).join('/'); | ||
} | ||
return encoder(String(param)); | ||
}; | ||
var decodeParam = function decodeParam(param, encoding) { | ||
return (decodingMethods[encoding] || decodeURIComponent)(param); | ||
}; | ||
var defaultOrConstrained = function defaultOrConstrained(match) { | ||
return '(' + (match ? match.replace(/(^<|>$)/g, '') : "[a-zA-Z0-9-_.~%':|=+\\*@]+") + ')'; | ||
return '(' + (match ? match.replace(/(^<|>$)/g, '') : "[a-zA-Z0-9-_.~%':|=+\\*@$]+") + ')'; | ||
}; | ||
@@ -86,6 +137,2 @@ var rules = [{ | ||
var identity = function identity(_) { | ||
return _; | ||
}; | ||
var exists = function exists(val) { | ||
@@ -115,6 +162,2 @@ return val !== undefined && val !== null; | ||
var encodeSpatParam = function encodeSpatParam(value) { | ||
return value.split('/').map(encodeURI).join('/'); | ||
}; | ||
var appendQueryParam = function appendQueryParam(params, param, val) { | ||
@@ -136,2 +179,6 @@ if (val === void 0) { | ||
var defaultOptions = { | ||
urlParamsEncoding: 'default' | ||
}; | ||
var Path = | ||
@@ -142,3 +189,3 @@ /*#__PURE__*/ | ||
function () { | ||
function Path(path) { | ||
function Path(path, options) { | ||
if (!path) { | ||
@@ -149,2 +196,3 @@ throw new Error('Missing path in Path constructor'); | ||
this.path = path; | ||
this.options = tslib.__assign(tslib.__assign({}, defaultOptions), options); | ||
this.tokens = tokenise(path); | ||
@@ -179,4 +227,4 @@ this.hasUrlParams = this.tokens.filter(function (t) { | ||
Path.createPath = function (path) { | ||
return new Path(path); | ||
Path.createPath = function (path, options) { | ||
return new Path(path, options); | ||
}; | ||
@@ -195,7 +243,5 @@ | ||
var _a; | ||
var options = tslib.__assign({ | ||
strictTrailingSlash: false, | ||
queryParams: {} | ||
caseSensitive: false, | ||
strictTrailingSlash: false | ||
}, opts); // trailingSlash: falsy => non optional, truthy => optional | ||
@@ -206,3 +252,3 @@ | ||
var match = this.urlTest(path, source + (this.hasQueryParams ? '(\\?.*$|$)' : '$'), (_a = opts) === null || _a === void 0 ? void 0 : _a.caseSensitive); // If no match, or no query params, no need to go further | ||
var match = this.urlTest(path, source + (this.hasQueryParams ? '(\\?.*$|$)' : '$'), options.caseSensitive); // If no match, or no query params, no need to go further | ||
@@ -214,3 +260,3 @@ if (!match || !this.hasQueryParams) { | ||
var queryParams = searchParams.parse(path, options.queryParams); | ||
var queryParams = searchParams.parse(path, this.options.queryParams); | ||
var unexpectedQueryParams = Object.keys(queryParams).filter(function (p) { | ||
@@ -235,7 +281,5 @@ return !_this.isQueryParam(p); | ||
var _a; | ||
var options = tslib.__assign({ | ||
delimited: true, | ||
queryParams: {} | ||
caseSensitive: false, | ||
delimited: true | ||
}, opts); // Check if partial match (start of given path matches regex) | ||
@@ -246,3 +290,3 @@ // trailingSlash: falsy => non optional, truthy => optional | ||
var source = upToDelimiter(this.source, options.delimited); | ||
var match = this.urlTest(path, source, (_a = opts) === null || _a === void 0 ? void 0 : _a.caseSensitive); | ||
var match = this.urlTest(path, source, options.caseSensitive); | ||
@@ -257,3 +301,3 @@ if (!match) { | ||
var queryParams = searchParams.parse(path, options.queryParams); | ||
var queryParams = searchParams.parse(path, this.options.queryParams); | ||
Object.keys(queryParams).filter(function (p) { | ||
@@ -277,3 +321,4 @@ return _this.isQueryParam(p); | ||
ignoreSearch: false, | ||
queryParams: {} | ||
queryParams: {}, | ||
urlParamsEncoding: 'default' | ||
}, opts); | ||
@@ -289,10 +334,13 @@ | ||
var val = params[key]; | ||
var encode = _this.isQueryParam(key) ? identity : _this.isSpatParam(key) ? encodeSpatParam : encodeURI; | ||
var isSpatParam = _this.isSpatParam(key); | ||
if (typeof val === 'boolean') { | ||
acc[key] = val; | ||
} else if (Array.isArray(val)) { | ||
acc[key] = val.map(encode); | ||
acc[key] = val.map(function (v) { | ||
return encodeParam(v, _this.options.urlParamsEncoding, isSpatParam); | ||
}); | ||
} else { | ||
acc[key] = encode(val); | ||
acc[key] = encodeParam(val, _this.options.urlParamsEncoding, isSpatParam); | ||
} | ||
@@ -345,3 +393,3 @@ | ||
}, {}); | ||
var searchPart = searchParams.build(searchParams$1, options.queryParams); | ||
var searchPart = searchParams.build(searchParams$1, this.options.queryParams); | ||
return searchPart ? base + '?' + searchPart : base; | ||
@@ -364,6 +412,2 @@ }; | ||
if (caseSensitive === void 0) { | ||
caseSensitive = false; | ||
} | ||
var regex = new RegExp('^' + source, caseSensitive ? '' : 'i'); | ||
@@ -380,3 +424,3 @@ var match = path.match(regex); | ||
return match.slice(1, this.urlParams.length + 1).reduce(function (params, m, i) { | ||
params[_this.urlParams[i]] = decodeURIComponent(m); | ||
params[_this.urlParams[i]] = decodeParam(m, _this.options.urlParamsEncoding); | ||
return params; | ||
@@ -383,0 +427,0 @@ }, {}); |
@@ -1,2 +0,2 @@ | ||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var r=require("tslib"),t=require("search-params"),e=function(r){return"("+(r?r.replace(/(^<|>$)/g,""):"[a-zA-Z0-9-_.~%':|=+\\*@]+")+")"},n=[{name:"url-parameter",pattern:/^:([a-zA-Z0-9-_]*[a-zA-Z0-9]{1})(<(.+?)>)?/,regex:function(r){return new RegExp(e(r[2]))}},{name:"url-parameter-splat",pattern:/^\*([a-zA-Z0-9-_]*[a-zA-Z0-9]{1})/,regex:/([^?]*)/},{name:"url-parameter-matrix",pattern:/^;([a-zA-Z0-9-_]*[a-zA-Z0-9]{1})(<(.+?)>)?/,regex:function(r){return new RegExp(";"+r[1]+"="+e(r[2]))}},{name:"query-parameter",pattern:/^(?:\?|&)(?::)?([a-zA-Z0-9-_]*[a-zA-Z0-9]{1})/},{name:"delimiter",pattern:/^(\/|\?)/,regex:function(r){return new RegExp("\\"+r[0])}},{name:"sub-delimiter",pattern:/^(!|&|-|_|\.|;)/,regex:function(r){return new RegExp(r[0])}},{name:"fragment",pattern:/^([0-9a-zA-Z]+)/,regex:function(r){return new RegExp(r[0])}}],a=function r(t,e){if(void 0===e&&(e=[]),!n.some((function(n){var a=t.match(n.pattern);return!!a&&(e.push({type:n.name,match:a[0],val:a.slice(1,2),otherVal:a.slice(2),regex:n.regex instanceof Function?n.regex(a):n.regex}),a[0].length<t.length&&(e=r(t.substr(a[0].length),e)),!0)})))throw new Error("Could not parse path '"+t+"'");return e},i=function(r){return r},s=function(r){return null!=r},u=function(r){return r.split("/").map(encodeURI).join("/")};exports.Path=function(){function n(r){if(!r)throw new Error("Missing path in Path constructor");this.path=r,this.tokens=a(r),this.hasUrlParams=this.tokens.filter((function(r){return/^url-parameter/.test(r.type)})).length>0,this.hasSpatParam=this.tokens.filter((function(r){return/splat$/.test(r.type)})).length>0,this.hasMatrixParams=this.tokens.filter((function(r){return/matrix$/.test(r.type)})).length>0,this.hasQueryParams=this.tokens.filter((function(r){return/^query-parameter/.test(r.type)})).length>0,this.spatParams=this.getParams("url-parameter-splat"),this.urlParams=this.getParams(/^url-parameter/),this.queryParams=this.getParams("query-parameter"),this.params=this.urlParams.concat(this.queryParams),this.source=this.tokens.filter((function(r){return void 0!==r.regex})).map((function(r){return r.regex.source})).join("")}return n.createPath=function(r){return new n(r)},n.prototype.isQueryParam=function(r){return-1!==this.queryParams.indexOf(r)},n.prototype.isSpatParam=function(r){return-1!==this.spatParams.indexOf(r)},n.prototype.test=function(e,n){var a,i=this,s=r.__assign({strictTrailingSlash:!1,queryParams:{}},n),u=function(r,t){return t?r:"\\/"===r?r:r.replace(/\\\/$/,"")+"(?:\\/)?"}(this.source,s.strictTrailingSlash),o=this.urlTest(e,u+(this.hasQueryParams?"(\\?.*$|$)":"$"),null===(a=n)||void 0===a?void 0:a.caseSensitive);if(!o||!this.hasQueryParams)return o;var c=t.parse(e,s.queryParams);return 0===Object.keys(c).filter((function(r){return!i.isQueryParam(r)})).length?(Object.keys(c).forEach((function(r){return o[r]=c[r]})),o):null},n.prototype.partialTest=function(e,n){var a,i=this,s=r.__assign({delimited:!0,queryParams:{}},n),u=function(r,t){return t?/(\/)$/.test(r)?r:r+"(\\/|\\?|\\.|;|$)":r}(this.source,s.delimited),o=this.urlTest(e,u,null===(a=n)||void 0===a?void 0:a.caseSensitive);if(!o)return o;if(!this.hasQueryParams)return o;var c=t.parse(e,s.queryParams);return Object.keys(c).filter((function(r){return i.isQueryParam(r)})).forEach((function(r){return function(r,t,e){void 0===e&&(e="");var n=r[t];return r[t]=void 0===n?e:Array.isArray(n)?n.concat(e):[n,e],r}(o,r,c[r])})),o},n.prototype.build=function(n,a){var o=this;void 0===n&&(n={});var c=r.__assign({ignoreConstraints:!1,ignoreSearch:!1,queryParams:{}},a),p=Object.keys(n).filter((function(r){return!o.isQueryParam(r)})).reduce((function(r,t){if(!s(n[t]))return r;var e=n[t],a=o.isQueryParam(t)?i:o.isSpatParam(t)?u:encodeURI;return r[t]="boolean"==typeof e?e:Array.isArray(e)?e.map(a):a(e),r}),{});if(this.urlParams.some((function(r){return!s(n[r])}))){var l=this.urlParams.filter((function(r){return!s(n[r])}));throw new Error("Cannot build path: '"+this.path+"' requires missing parameters { "+l.join(", ")+" }")}if(!c.ignoreConstraints&&!this.tokens.filter((function(r){return/^url-parameter/.test(r.type)&&!/-splat$/.test(r.type)})).every((function(r){return new RegExp("^"+e(r.otherVal[0])+"$").test(p[r.val])})))throw new Error("Some parameters of '"+this.path+"' are of invalid format");var h=this.tokens.filter((function(r){return!1===/^query-parameter/.test(r.type)})).map((function(r){return"url-parameter-matrix"===r.type?";"+r.val+"="+p[r.val[0]]:/^url-parameter/.test(r.type)?p[r.val[0]]:r.match})).join("");if(c.ignoreSearch)return h;var m=this.queryParams.filter((function(r){return-1!==Object.keys(n).indexOf(r)})).reduce((function(r,t){return r[t]=n[t],r}),{}),f=t.build(m,c.queryParams);return f?h+"?"+f:h},n.prototype.getParams=function(r){var t=r instanceof RegExp?function(t){return r.test(t.type)}:function(t){return t.type===r};return this.tokens.filter(t).map((function(r){return r.val[0]}))},n.prototype.urlTest=function(r,t,e){var n=this;void 0===e&&(e=!1);var a=new RegExp("^"+t,e?"":"i"),i=r.match(a);return i?this.urlParams.length?i.slice(1,this.urlParams.length+1).reduce((function(r,t,e){return r[n.urlParams[e]]=decodeURIComponent(t),r}),{}):{}:null},n}(); | ||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var t=require("tslib"),r=require("search-params"),e=/[^!$'()*+,;|:]/g,n=function(t){return t.replace(e,(function(t){return encodeURIComponent(t)}))},a={default:n,uri:encodeURI,uriComponent:encodeURIComponent,none:function(t){return t},legacy:encodeURI},i={default:decodeURIComponent,uri:decodeURI,uriComponent:decodeURIComponent,none:function(t){return t},legacy:decodeURIComponent},s=function(t,r,e){var i=a[r]||n;return e?String(t).split("/").map(i).join("/"):i(String(t))},u=function(t){return"("+(t?t.replace(/(^<|>$)/g,""):"[a-zA-Z0-9-_.~%':|=+\\*@$]+")+")"},o=[{name:"url-parameter",pattern:/^:([a-zA-Z0-9-_]*[a-zA-Z0-9]{1})(<(.+?)>)?/,regex:function(t){return new RegExp(u(t[2]))}},{name:"url-parameter-splat",pattern:/^\*([a-zA-Z0-9-_]*[a-zA-Z0-9]{1})/,regex:/([^?]*)/},{name:"url-parameter-matrix",pattern:/^;([a-zA-Z0-9-_]*[a-zA-Z0-9]{1})(<(.+?)>)?/,regex:function(t){return new RegExp(";"+t[1]+"="+u(t[2]))}},{name:"query-parameter",pattern:/^(?:\?|&)(?::)?([a-zA-Z0-9-_]*[a-zA-Z0-9]{1})/},{name:"delimiter",pattern:/^(\/|\?)/,regex:function(t){return new RegExp("\\"+t[0])}},{name:"sub-delimiter",pattern:/^(!|&|-|_|\.|;)/,regex:function(t){return new RegExp(t[0])}},{name:"fragment",pattern:/^([0-9a-zA-Z]+)/,regex:function(t){return new RegExp(t[0])}}],c=function t(r,e){if(void 0===e&&(e=[]),!o.some((function(n){var a=r.match(n.pattern);return!!a&&(e.push({type:n.name,match:a[0],val:a.slice(1,2),otherVal:a.slice(2),regex:n.regex instanceof Function?n.regex(a):n.regex}),a[0].length<r.length&&(e=t(r.substr(a[0].length),e)),!0)})))throw new Error("Could not parse path '"+r+"'");return e},p=function(t){return null!=t},l={urlParamsEncoding:"default"};exports.Path=function(){function e(r,e){if(!r)throw new Error("Missing path in Path constructor");this.path=r,this.options=t.__assign(t.__assign({},l),e),this.tokens=c(r),this.hasUrlParams=this.tokens.filter((function(t){return/^url-parameter/.test(t.type)})).length>0,this.hasSpatParam=this.tokens.filter((function(t){return/splat$/.test(t.type)})).length>0,this.hasMatrixParams=this.tokens.filter((function(t){return/matrix$/.test(t.type)})).length>0,this.hasQueryParams=this.tokens.filter((function(t){return/^query-parameter/.test(t.type)})).length>0,this.spatParams=this.getParams("url-parameter-splat"),this.urlParams=this.getParams(/^url-parameter/),this.queryParams=this.getParams("query-parameter"),this.params=this.urlParams.concat(this.queryParams),this.source=this.tokens.filter((function(t){return void 0!==t.regex})).map((function(t){return t.regex.source})).join("")}return e.createPath=function(t,r){return new e(t,r)},e.prototype.isQueryParam=function(t){return-1!==this.queryParams.indexOf(t)},e.prototype.isSpatParam=function(t){return-1!==this.spatParams.indexOf(t)},e.prototype.test=function(e,n){var a=this,i=t.__assign({caseSensitive:!1,strictTrailingSlash:!1},n),s=function(t,r){return r?t:"\\/"===t?t:t.replace(/\\\/$/,"")+"(?:\\/)?"}(this.source,i.strictTrailingSlash),u=this.urlTest(e,s+(this.hasQueryParams?"(\\?.*$|$)":"$"),i.caseSensitive);if(!u||!this.hasQueryParams)return u;var o=r.parse(e,this.options.queryParams);return 0===Object.keys(o).filter((function(t){return!a.isQueryParam(t)})).length?(Object.keys(o).forEach((function(t){return u[t]=o[t]})),u):null},e.prototype.partialTest=function(e,n){var a=this,i=t.__assign({caseSensitive:!1,delimited:!0},n),s=function(t,r){return r?/(\/)$/.test(t)?t:t+"(\\/|\\?|\\.|;|$)":t}(this.source,i.delimited),u=this.urlTest(e,s,i.caseSensitive);if(!u)return u;if(!this.hasQueryParams)return u;var o=r.parse(e,this.options.queryParams);return Object.keys(o).filter((function(t){return a.isQueryParam(t)})).forEach((function(t){return function(t,r,e){void 0===e&&(e="");var n=t[r];return t[r]=void 0===n?e:Array.isArray(n)?n.concat(e):[n,e],t}(u,t,o[t])})),u},e.prototype.build=function(e,n){var a=this;void 0===e&&(e={});var i=t.__assign({ignoreConstraints:!1,ignoreSearch:!1,queryParams:{},urlParamsEncoding:"default"},n),o=Object.keys(e).filter((function(t){return!a.isQueryParam(t)})).reduce((function(t,r){if(!p(e[r]))return t;var n=e[r],i=a.isSpatParam(r);return t[r]="boolean"==typeof n?n:Array.isArray(n)?n.map((function(t){return s(t,a.options.urlParamsEncoding,i)})):s(n,a.options.urlParamsEncoding,i),t}),{});if(this.urlParams.some((function(t){return!p(e[t])}))){var c=this.urlParams.filter((function(t){return!p(e[t])}));throw new Error("Cannot build path: '"+this.path+"' requires missing parameters { "+c.join(", ")+" }")}if(!i.ignoreConstraints&&!this.tokens.filter((function(t){return/^url-parameter/.test(t.type)&&!/-splat$/.test(t.type)})).every((function(t){return new RegExp("^"+u(t.otherVal[0])+"$").test(o[t.val])})))throw new Error("Some parameters of '"+this.path+"' are of invalid format");var l=this.tokens.filter((function(t){return!1===/^query-parameter/.test(t.type)})).map((function(t){return"url-parameter-matrix"===t.type?";"+t.val+"="+o[t.val[0]]:/^url-parameter/.test(t.type)?o[t.val[0]]:t.match})).join("");if(i.ignoreSearch)return l;var m=this.queryParams.filter((function(t){return-1!==Object.keys(e).indexOf(t)})).reduce((function(t,r){return t[r]=e[r],t}),{}),h=r.build(m,this.options.queryParams);return h?l+"?"+h:l},e.prototype.getParams=function(t){var r=t instanceof RegExp?function(r){return t.test(r.type)}:function(r){return r.type===t};return this.tokens.filter(r).map((function(t){return t.val[0]}))},e.prototype.urlTest=function(t,r,e){var n=this,a=new RegExp("^"+r,e?"":"i"),s=t.match(a);return s?this.urlParams.length?s.slice(1,this.urlParams.length+1).reduce((function(t,r,e){return t[n.urlParams[e]]=(i[n.options.urlParamsEncoding]||decodeURIComponent)(r),t}),{}):{}:null},e}(); | ||
//# sourceMappingURL=path-parser.cjs.production.min.js.map |
import { __assign } from 'tslib'; | ||
import { parse, build } from 'search-params'; | ||
/** | ||
* We encode using encodeURIComponent but we want to | ||
* preserver certain characters which are commonly used | ||
* (sub delimiters and ':') | ||
* | ||
* https://www.ietf.org/rfc/rfc3986.txt | ||
* | ||
* reserved = gen-delims / sub-delims | ||
* | ||
* gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" | ||
* | ||
* sub-delims = "!" / "$" / "&" / "'" / "(" / ")" | ||
/ "*" / "+" / "," / ";" / "=" | ||
*/ | ||
var excludeSubDelimiters = /[^!$'()*+,;|:]/g; | ||
var encodeURIComponentExcludingSubDelims = function encodeURIComponentExcludingSubDelims(segment) { | ||
return segment.replace(excludeSubDelimiters, function (match) { | ||
return encodeURIComponent(match); | ||
}); | ||
}; | ||
var encodingMethods = { | ||
"default": encodeURIComponentExcludingSubDelims, | ||
uri: encodeURI, | ||
uriComponent: encodeURIComponent, | ||
none: function none(val) { | ||
return val; | ||
}, | ||
legacy: encodeURI | ||
}; | ||
var decodingMethods = { | ||
"default": decodeURIComponent, | ||
uri: decodeURI, | ||
uriComponent: decodeURIComponent, | ||
none: function none(val) { | ||
return val; | ||
}, | ||
legacy: decodeURIComponent | ||
}; | ||
var encodeParam = function encodeParam(param, encoding, isSpatParam) { | ||
var encoder = encodingMethods[encoding] || encodeURIComponentExcludingSubDelims; | ||
if (isSpatParam) { | ||
return String(param).split('/').map(encoder).join('/'); | ||
} | ||
return encoder(String(param)); | ||
}; | ||
var decodeParam = function decodeParam(param, encoding) { | ||
return (decodingMethods[encoding] || decodeURIComponent)(param); | ||
}; | ||
var defaultOrConstrained = function defaultOrConstrained(match) { | ||
return '(' + (match ? match.replace(/(^<|>$)/g, '') : "[a-zA-Z0-9-_.~%':|=+\\*@]+") + ')'; | ||
return '(' + (match ? match.replace(/(^<|>$)/g, '') : "[a-zA-Z0-9-_.~%':|=+\\*@$]+") + ')'; | ||
}; | ||
@@ -81,6 +132,2 @@ var rules = [{ | ||
var identity = function identity(_) { | ||
return _; | ||
}; | ||
var exists = function exists(val) { | ||
@@ -110,6 +157,2 @@ return val !== undefined && val !== null; | ||
var encodeSpatParam = function encodeSpatParam(value) { | ||
return value.split('/').map(encodeURI).join('/'); | ||
}; | ||
var appendQueryParam = function appendQueryParam(params, param, val) { | ||
@@ -131,2 +174,6 @@ if (val === void 0) { | ||
var defaultOptions = { | ||
urlParamsEncoding: 'default' | ||
}; | ||
var Path = | ||
@@ -137,3 +184,3 @@ /*#__PURE__*/ | ||
function () { | ||
function Path(path) { | ||
function Path(path, options) { | ||
if (!path) { | ||
@@ -144,2 +191,3 @@ throw new Error('Missing path in Path constructor'); | ||
this.path = path; | ||
this.options = __assign(__assign({}, defaultOptions), options); | ||
this.tokens = tokenise(path); | ||
@@ -174,4 +222,4 @@ this.hasUrlParams = this.tokens.filter(function (t) { | ||
Path.createPath = function (path) { | ||
return new Path(path); | ||
Path.createPath = function (path, options) { | ||
return new Path(path, options); | ||
}; | ||
@@ -190,7 +238,5 @@ | ||
var _a; | ||
var options = __assign({ | ||
strictTrailingSlash: false, | ||
queryParams: {} | ||
caseSensitive: false, | ||
strictTrailingSlash: false | ||
}, opts); // trailingSlash: falsy => non optional, truthy => optional | ||
@@ -201,3 +247,3 @@ | ||
var match = this.urlTest(path, source + (this.hasQueryParams ? '(\\?.*$|$)' : '$'), (_a = opts) === null || _a === void 0 ? void 0 : _a.caseSensitive); // If no match, or no query params, no need to go further | ||
var match = this.urlTest(path, source + (this.hasQueryParams ? '(\\?.*$|$)' : '$'), options.caseSensitive); // If no match, or no query params, no need to go further | ||
@@ -209,3 +255,3 @@ if (!match || !this.hasQueryParams) { | ||
var queryParams = parse(path, options.queryParams); | ||
var queryParams = parse(path, this.options.queryParams); | ||
var unexpectedQueryParams = Object.keys(queryParams).filter(function (p) { | ||
@@ -230,7 +276,5 @@ return !_this.isQueryParam(p); | ||
var _a; | ||
var options = __assign({ | ||
delimited: true, | ||
queryParams: {} | ||
caseSensitive: false, | ||
delimited: true | ||
}, opts); // Check if partial match (start of given path matches regex) | ||
@@ -241,3 +285,3 @@ // trailingSlash: falsy => non optional, truthy => optional | ||
var source = upToDelimiter(this.source, options.delimited); | ||
var match = this.urlTest(path, source, (_a = opts) === null || _a === void 0 ? void 0 : _a.caseSensitive); | ||
var match = this.urlTest(path, source, options.caseSensitive); | ||
@@ -252,3 +296,3 @@ if (!match) { | ||
var queryParams = parse(path, options.queryParams); | ||
var queryParams = parse(path, this.options.queryParams); | ||
Object.keys(queryParams).filter(function (p) { | ||
@@ -272,3 +316,4 @@ return _this.isQueryParam(p); | ||
ignoreSearch: false, | ||
queryParams: {} | ||
queryParams: {}, | ||
urlParamsEncoding: 'default' | ||
}, opts); | ||
@@ -284,10 +329,13 @@ | ||
var val = params[key]; | ||
var encode = _this.isQueryParam(key) ? identity : _this.isSpatParam(key) ? encodeSpatParam : encodeURI; | ||
var isSpatParam = _this.isSpatParam(key); | ||
if (typeof val === 'boolean') { | ||
acc[key] = val; | ||
} else if (Array.isArray(val)) { | ||
acc[key] = val.map(encode); | ||
acc[key] = val.map(function (v) { | ||
return encodeParam(v, _this.options.urlParamsEncoding, isSpatParam); | ||
}); | ||
} else { | ||
acc[key] = encode(val); | ||
acc[key] = encodeParam(val, _this.options.urlParamsEncoding, isSpatParam); | ||
} | ||
@@ -340,3 +388,3 @@ | ||
}, {}); | ||
var searchPart = build(searchParams, options.queryParams); | ||
var searchPart = build(searchParams, this.options.queryParams); | ||
return searchPart ? base + '?' + searchPart : base; | ||
@@ -359,6 +407,2 @@ }; | ||
if (caseSensitive === void 0) { | ||
caseSensitive = false; | ||
} | ||
var regex = new RegExp('^' + source, caseSensitive ? '' : 'i'); | ||
@@ -375,3 +419,3 @@ var match = path.match(regex); | ||
return match.slice(1, this.urlParams.length + 1).reduce(function (params, m, i) { | ||
params[_this.urlParams[i]] = decodeURIComponent(m); | ||
params[_this.urlParams[i]] = decodeParam(m, _this.options.urlParamsEncoding); | ||
return params; | ||
@@ -378,0 +422,0 @@ }, {}); |
import { IOptions } from 'search-params'; | ||
import { IToken } from './tokeniser'; | ||
export interface IPartialTestOptions { | ||
import { URLParamsEncodingType } from './encoding'; | ||
import { Token } from './tokeniser'; | ||
export { URLParamsEncodingType }; | ||
export interface PathOptions { | ||
/** | ||
* Query parameters buiding and matching options, see | ||
* https://github.com/troch/search-params#options | ||
*/ | ||
queryParams?: IOptions; | ||
/** | ||
* Specifies the method used to encode URL parameters: | ||
* - `'default': `encodeURIComponent` and `decodeURIComponent` | ||
* are used but some characters to encode and decode URL parameters, | ||
* but some characters are preserved when encoding | ||
* (sub-delimiters: `+`, `:`, `'`, `!`, `,`, `;`, `'*'`). | ||
* - `'uriComponent'`: use `encodeURIComponent` and `decodeURIComponent` | ||
* for encoding and decoding URL parameters. | ||
* - `'uri'`: use `encodeURI` and `decodeURI for encoding amd decoding | ||
* URL parameters. | ||
* - `'none'`: no encoding or decoding is performed | ||
* - `'legacy'`: the approach for version 5.x and below (not recoomended) | ||
*/ | ||
urlParamsEncoding?: URLParamsEncodingType; | ||
} | ||
export interface InternalPathOptions { | ||
queryParams?: IOptions; | ||
urlParamsEncoding: URLParamsEncodingType; | ||
} | ||
export interface PathPartialTestOptions { | ||
caseSensitive?: boolean; | ||
delimited?: boolean; | ||
queryParams?: IOptions; | ||
} | ||
export interface ITestOptions { | ||
export interface PathTestOptions { | ||
caseSensitive?: boolean; | ||
strictTrailingSlash?: boolean; | ||
queryParams?: IOptions; | ||
} | ||
export interface IBuildOptions { | ||
export interface PathBuildOptions { | ||
ignoreConstraints?: boolean; | ||
ignoreSearch?: boolean; | ||
queryParams?: IOptions; | ||
} | ||
export declare type TestMatch<T extends Record<string, any> = Record<string, any>> = T | null; | ||
export declare class Path<T extends Record<string, any> = Record<string, any>> { | ||
static createPath<T extends Record<string, any> = Record<string, any>>(path: string): Path<T>; | ||
static createPath<T extends Record<string, any> = Record<string, any>>(path: string, options?: PathOptions): Path<T>; | ||
path: string; | ||
tokens: IToken[]; | ||
tokens: Token[]; | ||
hasUrlParams: boolean; | ||
@@ -27,2 +51,3 @@ hasSpatParam: boolean; | ||
hasQueryParams: boolean; | ||
options: InternalPathOptions; | ||
spatParams: string[]; | ||
@@ -33,8 +58,8 @@ urlParams: string[]; | ||
source: string; | ||
constructor(path: string); | ||
constructor(path: string, options?: PathOptions); | ||
isQueryParam(name: string): boolean; | ||
isSpatParam(name: string): boolean; | ||
test(path: string, opts?: ITestOptions): TestMatch<T>; | ||
partialTest(path: string, opts?: IPartialTestOptions): TestMatch<T>; | ||
build(params?: Record<string, any>, opts?: IBuildOptions): string; | ||
test(path: string, opts?: PathTestOptions): TestMatch<T>; | ||
partialTest(path: string, opts?: PathPartialTestOptions): TestMatch<T>; | ||
build(params?: T, opts?: PathBuildOptions): string; | ||
private getParams; | ||
@@ -41,0 +66,0 @@ private urlTest; |
@@ -1,2 +0,2 @@ | ||
export interface IToken { | ||
export interface Token { | ||
type: string; | ||
@@ -8,3 +8,3 @@ match: string; | ||
} | ||
declare const tokenise: (str: string, tokens?: IToken[]) => IToken[]; | ||
declare const tokenise: (str: string, tokens?: Token[]) => Token[]; | ||
export default tokenise; |
{ | ||
"name": "path-parser", | ||
"version": "5.1.0", | ||
"version": "6.0.0", | ||
"description": "A small utility to parse, match and generate paths", | ||
@@ -5,0 +5,0 @@ "license": "MIT", |
@@ -72,2 +72,21 @@ [![npm version](https://badge.fury.io/js/path-parser.svg)](http://badge.fury.io/js/path-parser) | ||
### Constructor | ||
A path instance can be created two ways: | ||
- `new Path(path: string, opts?: object): object` | ||
- `Path.create(path: string, opts?: object): object` | ||
Options available are: | ||
- `'queryParams'`: [options for query parameters](https://github.com/troch/search-params#options) | ||
- `'urlParamsEncoding`, to specify how URL parameters are encoded and decoded: | ||
- `'default':`encodeURIComponent`and`decodeURIComponent`are used but some characters to encode and decode URL parameters, but some characters are preserved when encoding (sub-delimiters:`+`,`:`,`'`,`!`,`,`,`;`,`'\*'`). | ||
- `'uriComponent'`: use `encodeURIComponent` and `decodeURIComponent` | ||
for encoding and decoding URL parameters. | ||
- `'uri'`: use `encodeURI` and `decodeURI for encoding amd decoding | ||
URL parameters. | ||
- `'none'`: no encoding or decoding is performed | ||
- `'legacy'`: the approach for version 5.x and below (not recoomended) | ||
### path.test(path: string, opts?: object): object | null; | ||
@@ -79,3 +98,2 @@ | ||
- `'strictTrailingSlash'`: whether or not it should strictly match trailing slashes (default to `false`) | ||
- `'queryParams'`: [options for query parameters](https://github.com/troch/search-params#options) | ||
@@ -88,3 +106,2 @@ ### path.partialTest(path: string, opts?: object): object | null; | ||
- `'delimited'`: whether or not a partial match should only be successful if it reaches a delimiter (`/`, `?`, `.` and `;`). Default to `true`. | ||
- `'queryParams'`: [options for query parameters](https://github.com/troch/search-params#options) | ||
@@ -95,6 +112,5 @@ ### path.build(params?: object, opts?: object): string; | ||
- `'caseSensitive'`: whether matching should be case sensitive or not (default to `false`) | ||
- `'ignoreConstraints'`: whether or not to ignore parameter constraints (default to `false`) | ||
- `'ignoreSearch'`: whether or not to build query parameters (default to `false`) | ||
- `'caseSensitive'`: whether matching should be case sensitive or not (default to `false`) | ||
- `'queryParams'`: [options for query parameters](https://github.com/troch/search-params#options) | ||
@@ -101,0 +117,0 @@ ## Related modules |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
126587
17
810
117