@omnicajs/symfony-router
Version:
[](https://www.npmjs.com/package/@omnicajs/symfony-router)
233 lines (232 loc) • 8.62 kB
JavaScript
;
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
class Router {
constructor(context, routes) {
__publicField(this, "context_");
__publicField(this, "routes_");
this.context_ = context || { base_url: "", prefix: "", host: "", port: "", scheme: "", locale: "" };
this.setRoutes(routes || {});
}
static getInstance() {
return Routing;
}
static setData(data) {
const router = Router.getInstance();
router.setRoutingData(data);
}
setRoutingData(data) {
this.setBaseUrl(data["base_url"]);
this.setRoutes(data["routes"]);
if (typeof data.prefix !== "undefined") {
this.setPrefix(data["prefix"]);
}
if (typeof data.port !== "undefined") {
this.setPort(data["port"]);
}
if (typeof data.locale !== "undefined") {
this.setLocale(data["locale"]);
}
this.setHost(data["host"]);
if (typeof data.scheme !== "undefined") {
this.setScheme(data["scheme"]);
}
}
setRoutes(routes) {
this.routes_ = Object.freeze(routes);
}
getRoutes() {
return this.routes_;
}
setBaseUrl(baseUrl) {
this.context_.base_url = baseUrl;
}
getBaseUrl() {
return this.context_.base_url;
}
setPrefix(prefix) {
this.context_.prefix = prefix;
}
setScheme(scheme) {
this.context_.scheme = scheme;
}
getScheme() {
return this.context_.scheme;
}
setHost(host) {
this.context_.host = host;
}
getHost() {
return this.context_.host;
}
setPort(port) {
this.context_.port = port;
}
getPort() {
return this.context_.port;
}
setLocale(locale) {
this.context_.locale = locale;
}
getLocale() {
return this.context_.locale;
}
/**
* Builds query string params added to a URL.
* Port of jQuery's $.param() function, so credit is due there.
*/
buildQueryParams(prefix, params, add) {
let name;
let rbracket = new RegExp(/\[\]$/);
if (params instanceof Array) {
params.forEach((val, i) => {
if (rbracket.test(prefix)) {
add(prefix, val);
} else {
this.buildQueryParams(prefix + "[" + (typeof val === "object" ? i : "") + "]", val, add);
}
});
} else if (typeof params === "object") {
for (name in params) {
this.buildQueryParams(prefix + "[" + name + "]", params[name], add);
}
} else {
add(prefix, params);
}
}
/**
* Returns a raw route object.
*/
getRoute(name) {
let prefixedName = this.context_.prefix + name;
let sf41i18nName = name + "." + this.context_.locale;
let prefixedSf41i18nName = this.context_.prefix + name + "." + this.context_.locale;
let variants = [prefixedName, sf41i18nName, prefixedSf41i18nName, name];
for (let i in variants) {
if (variants[i] in this.routes_) {
return this.routes_[variants[i]];
}
}
throw new Error('The route "' + name + '" does not exist.');
}
/**
* Generates the URL for a route.
*/
generate(name, opt_params, absolute) {
let route = this.getRoute(name);
let params = opt_params || {};
let unusedParams = Object.assign({}, params);
let url = "";
let optional = true;
let host = "";
let port = typeof this.getPort() == "undefined" || this.getPort() === null ? "" : this.getPort();
route.tokens.forEach((token) => {
if ("text" === token[0] && typeof token[1] === "string") {
url = Router.encodePathComponent(token[1]) + url;
optional = false;
return;
}
if ("variable" === token[0]) {
if (token.length === 6 && token[5] === true) {
optional = false;
}
let hasDefault = route.defaults && !Array.isArray(route.defaults) && typeof token[3] === "string" && token[3] in route.defaults;
if (false === optional || !hasDefault || typeof token[3] === "string" && token[3] in params && !Array.isArray(route.defaults) && params[token[3]] != route.defaults[token[3]]) {
let value;
if (typeof token[3] === "string" && token[3] in params) {
value = params[token[3]];
delete unusedParams[token[3]];
} else if (typeof token[3] === "string" && hasDefault && !Array.isArray(route.defaults)) {
value = route.defaults[token[3]];
} else if (optional) {
return;
} else {
throw new Error('The route "' + name + '" requires the parameter "' + token[3] + '".');
}
let empty = true === value || false === value || "" === value;
if (!empty || !optional) {
let encodedValue = Router.encodePathComponent(value);
if ("null" === encodedValue && null === value) {
encodedValue = "";
}
url = token[1] + encodedValue + url;
}
optional = false;
} else if (hasDefault && (typeof token[3] === "string" && token[3] in unusedParams)) {
delete unusedParams[token[3]];
}
return;
}
throw new Error('The token type "' + token[0] + '" is not supported.');
});
if (url === "") {
url = "/";
}
route.hosttokens.forEach((token) => {
let value;
if ("text" === token[0]) {
host = token[1] + host;
return;
}
if ("variable" === token[0]) {
if (token[3] in params) {
value = params[token[3]];
delete unusedParams[token[3]];
} else if (route.defaults && !Array.isArray(route.defaults) && token[3] in route.defaults) {
value = route.defaults[token[3]];
}
host = token[1] + value + host;
}
});
url = this.context_.base_url + url;
if (route.requirements && "_scheme" in route.requirements && this.getScheme() != route.requirements["_scheme"]) {
const currentHost = host || this.getHost();
url = route.requirements["_scheme"] + "://" + currentHost + (currentHost.indexOf(":" + port) > -1 || "" === port ? "" : ":" + port) + url;
} else if ("undefined" !== typeof route.schemes && "undefined" !== typeof route.schemes[0] && this.getScheme() !== route.schemes[0]) {
const currentHost = host || this.getHost();
url = route.schemes[0] + "://" + currentHost + (currentHost.indexOf(":" + port) > -1 || "" === port ? "" : ":" + port) + url;
} else if (host && this.getHost() !== host + (host.indexOf(":" + port) > -1 || "" === port ? "" : ":" + port)) {
url = this.getScheme() + "://" + host + (host.indexOf(":" + port) > -1 || "" === port ? "" : ":" + port) + url;
} else if (absolute === true) {
url = this.getScheme() + "://" + this.getHost() + (this.getHost().indexOf(":" + port) > -1 || "" === port ? "" : ":" + port) + url;
}
if (Object.keys(unusedParams).length > 0) {
let queryParams = [];
let add = (key, value) => {
value = typeof value === "function" ? value() : value;
value = value === null ? "" : value;
queryParams.push(Router.encodeQueryComponent(key) + "=" + Router.encodeQueryComponent(value));
};
for (const prefix in unusedParams) {
if (unusedParams.hasOwnProperty(prefix)) {
this.buildQueryParams(prefix, unusedParams[prefix], add);
}
}
url = url + "?" + queryParams.join("&");
}
return url;
}
/**
* Returns the given string encoded to mimic Symfony URL generator.
*/
static customEncodeURIComponent(value) {
return encodeURIComponent(value).replace(/%2F/g, "/").replace(/%40/g, "@").replace(/%3A/g, ":").replace(/%21/g, "!").replace(/%3B/g, ";").replace(/%2C/g, ",").replace(/%2A/g, "*").replace(/\(/g, "%28").replace(/\)/g, "%29").replace(/'/g, "%27");
}
/**
* Returns the given path properly encoded to mimic Symfony URL generator.
*/
static encodePathComponent(value) {
return Router.customEncodeURIComponent(value).replace(/%3D/g, "=").replace(/%2B/g, "+").replace(/%21/g, "!").replace(/%7C/g, "|");
}
/**
* Returns the given query parameter or value properly encoded to mimic Symfony URL generator.
*/
static encodeQueryComponent(value) {
return Router.customEncodeURIComponent(value).replace(/%3F/g, "?");
}
}
const Routing = new Router();
exports.Router = Router;
exports.Routing = Routing;