@routr/processor 2.0.8-alpha.9 → 2.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,13 +1,15 @@
1
1
  import { MessageRequest, Route } from "@routr/common";
2
- export declare const updateRequestURI: (route: Route) => (request: MessageRequest) => MessageRequest;
2
+ export declare const fixRequestURI: (route: Route) => (request: MessageRequest) => MessageRequest;
3
3
  export declare const addSelfVia: (route: Route) => (request: MessageRequest) => MessageRequest;
4
- export declare const addRoute: (route: Route) => (request: MessageRequest) => MessageRequest;
4
+ export declare const addRouteToNextHop: (route: Route) => (request: MessageRequest) => MessageRequest;
5
5
  export declare const addRouteToPeerEdgePort: (route: Route) => (request: MessageRequest) => MessageRequest;
6
6
  export declare const applyXHeaders: (route: Route) => (request: MessageRequest) => MessageRequest;
7
7
  export declare const addSelfRecordRoute: (route: Route) => (request: MessageRequest) => MessageRequest;
8
8
  export declare const addXEdgePortRef: (request: MessageRequest) => MessageRequest;
9
9
  export declare const removeXEdgePortRef: (request: MessageRequest) => MessageRequest;
10
10
  export declare const removeAuthorization: (request: MessageRequest) => MessageRequest;
11
- export declare const removeRoutes: (request: MessageRequest) => MessageRequest;
11
+ export declare const removeSelfRoutes: (request: MessageRequest) => MessageRequest;
12
12
  export declare const removeTopVia: (request: MessageRequest) => MessageRequest;
13
13
  export declare const decreaseMaxForwards: (request: MessageRequest) => MessageRequest;
14
+ export declare const fixInvalidContact: (request: MessageRequest) => MessageRequest;
15
+ export declare const enforceE164: (enforceE164: boolean, validateMobilePrefix: boolean) => (request: MessageRequest) => MessageRequest;
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.decreaseMaxForwards = exports.removeTopVia = exports.removeRoutes = exports.removeAuthorization = exports.removeXEdgePortRef = exports.addXEdgePortRef = exports.addSelfRecordRoute = exports.applyXHeaders = exports.addRouteToPeerEdgePort = exports.addRoute = exports.addSelfVia = exports.updateRequestURI = void 0;
3
+ exports.enforceE164 = exports.fixInvalidContact = exports.decreaseMaxForwards = exports.removeTopVia = exports.removeSelfRoutes = exports.removeAuthorization = exports.removeXEdgePortRef = exports.addXEdgePortRef = exports.addSelfRecordRoute = exports.applyXHeaders = exports.addRouteToPeerEdgePort = exports.addRouteToNextHop = exports.addSelfVia = exports.fixRequestURI = void 0;
4
4
  /*
5
- * Copyright (C) 2022 by Fonoster Inc (https://fonoster.com)
5
+ * Copyright (C) 2023 by Fonoster Inc (https://fonoster.com)
6
6
  * http://github.com/fonoster/routr
7
7
  *
8
8
  * This file is part of Routr
@@ -20,31 +20,33 @@ exports.decreaseMaxForwards = exports.removeTopVia = exports.removeRoutes = expo
20
20
  * limitations under the License.
21
21
  */
22
22
  const common_1 = require("@routr/common");
23
+ const phone_1 = require("phone");
23
24
  const helper_1 = require("./helper");
24
- // Q: Should we deprecate this method since we are not doing strict routing?
25
- const updateRequestURI = (route) => (request) => {
25
+ // Forces the requestURI to be the same as the trunk uri.
26
+ // This is a workaround for Twilio.
27
+ const fixRequestURI = (route) => (request) => {
26
28
  const req = common_1.Helper.deepCopy(request);
27
- if (route.user) {
28
- req.message.requestUri.user = route.user;
29
- }
30
- else {
31
- req.message.requestUri.user = null;
32
- }
33
29
  req.message.requestUri.host = route.host;
34
30
  req.message.requestUri.port = route.port;
35
31
  req.message.requestUri.transportParam = route.transport;
36
32
  return req;
37
33
  };
38
- exports.updateRequestURI = updateRequestURI;
34
+ exports.fixRequestURI = fixRequestURI;
39
35
  const addSelfVia = (route) => (request) => {
40
36
  const req = common_1.Helper.deepCopy(request);
41
- const routingObjects = request.edgePortRef === route.edgePortRef ? request : route;
37
+ const routingObjects = request.edgePortRef === route.edgePortRef ? route : request;
42
38
  const targetIntf = (0, helper_1.getEdgeInterface)(Object.assign(Object.assign({}, routingObjects), { endpointIntf: route }));
43
- req.message.via = [Object.assign({}, targetIntf), ...req.message.via];
39
+ req.message.via = [
40
+ Object.assign(Object.assign({}, targetIntf), { rPortFlag: true }),
41
+ ...req.message.via
42
+ ];
44
43
  return req;
45
44
  };
46
45
  exports.addSelfVia = addSelfVia;
47
- const addRoute = (route) => (request) => {
46
+ const addRouteToNextHop = (route) => (request) => {
47
+ if (request.message.requestUri.host === route.host) {
48
+ return request;
49
+ }
48
50
  const req = common_1.Helper.deepCopy(request);
49
51
  const r = {
50
52
  address: {
@@ -59,7 +61,7 @@ const addRoute = (route) => (request) => {
59
61
  req.message.route = [r, ...req.message.route];
60
62
  return req;
61
63
  };
62
- exports.addRoute = addRoute;
64
+ exports.addRouteToNextHop = addRouteToNextHop;
63
65
  const addRouteToPeerEdgePort = (route) => (request) => {
64
66
  const req = common_1.Helper.deepCopy(request);
65
67
  const targetIntf = (0, helper_1.getEdgeInterface)({
@@ -87,8 +89,8 @@ const applyXHeaders = (route) => (request) => {
87
89
  if (route.headers && route.headers.length > 0) {
88
90
  const headersToRemove = route.headers
89
91
  .filter((h) => h.action === common_1.CommonTypes.HeaderModifierAction.REMOVE)
90
- .map((h) => h.name);
91
- const headersToAdd = route.headers.filter((h) => h.action !== common_1.CommonTypes.HeaderModifierAction.REMOVE);
92
+ .map((h) => h.name.toLowerCase());
93
+ const headersToAdd = route.headers.filter((h) => h.action === common_1.CommonTypes.HeaderModifierAction.ADD);
92
94
  req.message.extensions = req.message.extensions.filter((h) => !headersToRemove.includes(h.name.toLowerCase()));
93
95
  headersToAdd.forEach((h) => {
94
96
  req.message.extensions.push({ name: h.name, value: h.value });
@@ -175,12 +177,12 @@ const removeAuthorization = (request) => {
175
177
  return req;
176
178
  };
177
179
  exports.removeAuthorization = removeAuthorization;
178
- const removeRoutes = (request) => {
180
+ const removeSelfRoutes = (request) => {
179
181
  const req = common_1.Helper.deepCopy(request);
180
182
  const localIps = request.localnets.map((ln) => ln.split("/")[0]);
181
183
  req.message.route = req.message.route.filter((r) => {
182
184
  var _a;
183
- const lp = common_1.Helper.getListeningPoint(request.listeningPoints, ((_a = r.address.uri.transportParam) === null || _a === void 0 ? void 0 : _a.toLowerCase()) ||
185
+ const lp = common_1.Helper.getListeningPoint(request.listeningPoints, ((_a = r.address.uri.transportParam) === null || _a === void 0 ? void 0 : _a.toUpperCase()) ||
184
186
  common_1.Transport.UDP);
185
187
  const routeUri = r.address.uri;
186
188
  return !((localIps.includes(routeUri.host) ||
@@ -189,7 +191,7 @@ const removeRoutes = (request) => {
189
191
  });
190
192
  return req;
191
193
  };
192
- exports.removeRoutes = removeRoutes;
194
+ exports.removeSelfRoutes = removeSelfRoutes;
193
195
  const removeTopVia = (request) => {
194
196
  const req = common_1.Helper.deepCopy(request);
195
197
  req.message.via.shift();
@@ -205,3 +207,48 @@ const decreaseMaxForwards = (request) => {
205
207
  return req;
206
208
  };
207
209
  exports.decreaseMaxForwards = decreaseMaxForwards;
210
+ const fixInvalidContact = (request) => {
211
+ var _a;
212
+ const req = common_1.Helper.deepCopy(request);
213
+ const via = req.message.via[0];
214
+ if ((_a = req.message.contact) === null || _a === void 0 ? void 0 : _a.address.uri.host.includes(".invalid")) {
215
+ req.message.contact.address.uri.host = via.received || via.host;
216
+ req.message.contact.address.uri.port =
217
+ via.rPort !== -1 ? via.rPort : via.port;
218
+ req.message.contact.address.uri.transportParam =
219
+ via.transport.toUpperCase();
220
+ }
221
+ return req;
222
+ };
223
+ exports.fixInvalidContact = fixInvalidContact;
224
+ // Will do the best effort to normalize from/to/requestUri users as e164 values
225
+ const enforceE164 = (enforceE164, validateMobilePrefix) => (request) => {
226
+ var _a, _b, _c;
227
+ if (!enforceE164)
228
+ return request;
229
+ const req = common_1.Helper.deepCopy(request);
230
+ // Removes the + to ensure not having duplicates
231
+ const fromUser = (_a = req.message.from.address.uri.user) === null || _a === void 0 ? void 0 : _a.replace("+", "");
232
+ const toUser = (_b = req.message.to.address.uri.user) === null || _b === void 0 ? void 0 : _b.replace("+", "");
233
+ const requestUriUser = (_c = req.message.requestUri.user) === null || _c === void 0 ? void 0 : _c.replace("+", "");
234
+ // Normalizing as e164
235
+ const normalizedTo = (0, phone_1.phone)(`+${toUser}`, { validateMobilePrefix });
236
+ const normalizedFrom = (0, phone_1.phone)(`+${fromUser}`, {
237
+ validateMobilePrefix: true
238
+ });
239
+ const normalizedReqUri = (0, phone_1.phone)(`+${requestUriUser}`, {
240
+ validateMobilePrefix
241
+ });
242
+ // If the normalization worked we overwrite the original values
243
+ if (normalizedFrom.isValid) {
244
+ req.message.from.address.uri.user = normalizedFrom.phoneNumber;
245
+ }
246
+ if (normalizedTo.isValid) {
247
+ req.message.to.address.uri.user = normalizedTo.phoneNumber;
248
+ }
249
+ if (normalizedReqUri.isValid) {
250
+ req.message.requestUri.user = normalizedReqUri.phoneNumber;
251
+ }
252
+ return req;
253
+ };
254
+ exports.enforceE164 = enforceE164;
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.removeHeader = exports.addHeader = exports.updateHeader = exports.getHeaderValue = void 0;
4
4
  /*
5
- * Copyright (C) 2022 by Fonoster Inc (https://fonoster.com)
5
+ * Copyright (C) 2023 by Fonoster Inc (https://fonoster.com)
6
6
  * http://github.com/fonoster/routr
7
7
  *
8
8
  * This file is part of Routr
@@ -22,7 +22,7 @@ exports.removeHeader = exports.addHeader = exports.updateHeader = exports.getHea
22
22
  const common_1 = require("@routr/common");
23
23
  const getHeaderValue = (request, name) => {
24
24
  var _a;
25
- return (_a = request.message.extensions.find((ext) => ext.name.toLowerCase() === name.toLowerCase())) === null || _a === void 0 ? void 0 : _a.value;
25
+ return ((_a = request.message.extensions.find((ext) => ext.name.toLowerCase() === (name === null || name === void 0 ? void 0 : name.toLowerCase()))) === null || _a === void 0 ? void 0 : _a.value) || null;
26
26
  };
27
27
  exports.getHeaderValue = getHeaderValue;
28
28
  const updateHeader = (request, header) => {
package/dist/helper.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { MessageRequest, Route, NetInterface } from "@routr/common";
1
+ import { MessageRequest, Transport, NetInterface } from "@routr/common";
2
2
  export declare const isTypeResponse: (request: MessageRequest) => boolean;
3
3
  export declare const isTypeRequest: (request: MessageRequest) => boolean;
4
4
  export declare const getEdgeInterface: (nets: {
@@ -7,11 +7,10 @@ export declare const getEdgeInterface: (nets: {
7
7
  localnets: string[];
8
8
  externalAddrs: string[];
9
9
  }) => NetInterface;
10
- /**
11
- * A request traversing a second EdgePort would have an updated the requestUri.
12
- * Therefore, we are able to re-construct the Route from the request.
13
- *
14
- * @param {MessageRequest} request - the request
15
- * @return {Route} the route
16
- */
17
- export declare function createRouteFromLastMessage(request: MessageRequest): Route;
10
+ export declare const hasSDP: (request: MessageRequest) => boolean;
11
+ export declare const isOk: (request: MessageRequest) => boolean;
12
+ export declare const isRinging: (request: MessageRequest) => boolean;
13
+ export declare const isWebRTC: (transport: Transport) => boolean;
14
+ export declare const isInviteOrAckWithSDP: (request: MessageRequest) => boolean;
15
+ export declare const isOkOrRingingWithSDP: (request: MessageRequest) => boolean;
16
+ export declare const isBye: (request: MessageRequest) => boolean;
package/dist/helper.js CHANGED
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createRouteFromLastMessage = exports.getEdgeInterface = exports.isTypeRequest = exports.isTypeResponse = void 0;
3
+ exports.isBye = exports.isOkOrRingingWithSDP = exports.isInviteOrAckWithSDP = exports.isWebRTC = exports.isRinging = exports.isOk = exports.hasSDP = exports.getEdgeInterface = exports.isTypeRequest = exports.isTypeResponse = void 0;
4
4
  /*
5
- * Copyright (C) 2022 by Fonoster Inc (https://fonoster.com)
5
+ * Copyright (C) 2023 by Fonoster Inc (https://fonoster.com)
6
6
  * http://github.com/fonoster/routr
7
7
  *
8
8
  * This file is part of Routr
@@ -21,7 +21,6 @@ exports.createRouteFromLastMessage = exports.getEdgeInterface = exports.isTypeRe
21
21
  */
22
22
  const common_1 = require("@routr/common");
23
23
  const common_2 = require("@routr/common");
24
- const index_1 = require("./index");
25
24
  const isTypeResponse = (request) => request.message.messageType === common_1.CommonTypes.MessageType.RESPONSE;
26
25
  exports.isTypeResponse = isTypeResponse;
27
26
  const isTypeRequest = (request) => !(0, exports.isTypeResponse)(request);
@@ -44,30 +43,21 @@ const getEdgeInterface = (nets) => {
44
43
  };
45
44
  };
46
45
  exports.getEdgeInterface = getEdgeInterface;
47
- /**
48
- * A request traversing a second EdgePort would have an updated the requestUri.
49
- * Therefore, we are able to re-construct the Route from the request.
50
- *
51
- * @param {MessageRequest} request - the request
52
- * @return {Route} the route
53
- */
54
- function createRouteFromLastMessage(request) {
55
- const uri = request.message.requestUri;
56
- const sessionCount = index_1.Extensions.getHeaderValue(request, common_1.CommonTypes.ExtraHeader.SESSION_COUNT)
57
- ? parseInt(index_1.Extensions.getHeaderValue(request, common_1.CommonTypes.ExtraHeader.SESSION_COUNT))
58
- : -1;
59
- return {
60
- edgePortRef: request.edgePortRef,
61
- user: uri.user,
62
- host: uri.host,
63
- port: uri.port,
64
- transport: uri.transportParam.toLowerCase(),
65
- registeredOn: Date.now(),
66
- sessionCount,
67
- expires: index_1.Target.getTargetExpires(request),
68
- listeningPoints: request.listeningPoints,
69
- localnets: request.localnets,
70
- externalAddrs: request.externalAddrs
71
- };
72
- }
73
- exports.createRouteFromLastMessage = createRouteFromLastMessage;
46
+ const hasSDP = (request) => { var _a; return ((_a = request.message.body) === null || _a === void 0 ? void 0 : _a.length) > 0; };
47
+ exports.hasSDP = hasSDP;
48
+ const isOk = (request) => request.message.responseType === common_1.CommonTypes.ResponseType.OK;
49
+ exports.isOk = isOk;
50
+ const isRinging = (request) => request.message.responseType === common_1.CommonTypes.ResponseType.RINGING;
51
+ exports.isRinging = isRinging;
52
+ const isWebRTC = (transport) => transport === common_1.Transport.WS || transport === common_1.Transport.WSS;
53
+ exports.isWebRTC = isWebRTC;
54
+ const isInviteOrAckWithSDP = (request) => (0, exports.isTypeRequest)(request) &&
55
+ (0, exports.hasSDP)(request) &&
56
+ (request.method === common_1.Method.INVITE || request.method === common_1.Method.ACK);
57
+ exports.isInviteOrAckWithSDP = isInviteOrAckWithSDP;
58
+ const isOkOrRingingWithSDP = (request) => (0, exports.isTypeResponse)(request) &&
59
+ (0, exports.hasSDP)(request) &&
60
+ ((0, exports.isOk)(request) || (0, exports.isRinging)(request));
61
+ exports.isOkOrRingingWithSDP = isOkOrRingingWithSDP;
62
+ const isBye = (request) => (0, exports.isTypeRequest)(request) && request.method === common_1.Method.BYE;
63
+ exports.isBye = isBye;
package/dist/processor.js CHANGED
@@ -4,7 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  /*
7
- * Copyright (C) 2022 by Fonoster Inc (https://fonoster.com)
7
+ * Copyright (C) 2023 by Fonoster Inc (https://fonoster.com)
8
8
  * http://github.com/fonoster/routr
9
9
  *
10
10
  * This file is part of Routr
@@ -31,6 +31,10 @@ export default class Response {
31
31
  * Sends a not implemented response.
32
32
  */
33
33
  sendNotImplemented(): void;
34
+ /**
35
+ * Sends a internal server error response.
36
+ */
37
+ sendInternalServerError(): void;
34
38
  /**
35
39
  * Sends a response with a SIP Message.
36
40
  *
@@ -41,6 +45,7 @@ export default class Response {
41
45
  * Sends an error response.
42
46
  *
43
47
  * @param {Error} error - The error to be sent.
48
+ * @deprecated
44
49
  */
45
50
  sendError(error: Error): void;
46
51
  }
package/dist/response.js CHANGED
@@ -1,7 +1,32 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- const buildResponse = (code, extraHeaders) => {
4
- return { message: { responseType: code, extensions: extraHeaders } };
3
+ /*
4
+ * Copyright (C) 2023 by Fonoster Inc (https://fonoster.com)
5
+ * http://github.com/fonoster/routr
6
+ *
7
+ * This file is part of Routr
8
+ *
9
+ * Licensed under the MIT License (the "License")
10
+ * you may not use this file except in compliance with
11
+ * the License. You may obtain a copy of the License at
12
+ *
13
+ * https://opensource.org/licenses/MIT
14
+ *
15
+ * Unless required by applicable law or agreed to in writing, software
16
+ * distributed under the License is distributed on an "AS IS" BASIS,
17
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
+ * See the License for the specific language governing permissions and
19
+ * limitations under the License.
20
+ */
21
+ const common_1 = require("@routr/common");
22
+ const buildResponse = (info) => {
23
+ return {
24
+ message: {
25
+ responseType: info.code,
26
+ reasonPhrase: info.reasonPhrase,
27
+ extensions: info.extraHeaders
28
+ }
29
+ };
5
30
  };
6
31
  /**
7
32
  * Response object.
@@ -21,25 +46,43 @@ class Response {
21
46
  * @param {object[]} extraHeaders - Optional extra headers to be sent.
22
47
  */
23
48
  sendOk(extraHeaders) {
24
- this.callback(null, buildResponse(7, extraHeaders));
49
+ this.callback(null, buildResponse({ code: common_1.CommonTypes.ResponseType.OK, extraHeaders }));
25
50
  }
26
51
  /**
27
52
  * Sends a method not allowed response.
28
53
  */
29
54
  sendMethodNotAllowed() {
30
- this.callback(null, buildResponse(21));
55
+ this.callback(null, buildResponse({
56
+ code: common_1.CommonTypes.ResponseType.METHOD_NOT_ALLOWED,
57
+ reasonPhrase: "Method Not Allowed"
58
+ }));
31
59
  }
32
60
  /**
33
61
  * Sends a not found response.
34
62
  */
35
63
  sendNotFound() {
36
- this.callback(null, buildResponse(20));
64
+ this.callback(null, buildResponse({
65
+ code: common_1.CommonTypes.ResponseType.NOT_FOUND,
66
+ reasonPhrase: "Not Found"
67
+ }));
37
68
  }
38
69
  /**
39
70
  * Sends a not implemented response.
40
71
  */
41
72
  sendNotImplemented() {
42
- this.callback(null, buildResponse(47));
73
+ this.callback(null, buildResponse({
74
+ code: common_1.CommonTypes.ResponseType.NOT_IMPLEMENTED,
75
+ reasonPhrase: "Not Implemented"
76
+ }));
77
+ }
78
+ /**
79
+ * Sends a internal server error response.
80
+ */
81
+ sendInternalServerError() {
82
+ this.callback(null, buildResponse({
83
+ code: common_1.CommonTypes.ResponseType.SERVER_INTERNAL_ERROR,
84
+ reasonPhrase: "Internal Server Error"
85
+ }));
43
86
  }
44
87
  /**
45
88
  * Sends a response with a SIP Message.
@@ -53,6 +96,7 @@ class Response {
53
96
  * Sends an error response.
54
97
  *
55
98
  * @param {Error} error - The error to be sent.
99
+ * @deprecated
56
100
  */
57
101
  sendError(error) {
58
102
  this.callback(error, null);
package/dist/tracer.js CHANGED
@@ -5,7 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.init = void 0;
7
7
  /*
8
- * Copyright (C) 2022 by Fonoster Inc (https://fonoster.com)
8
+ * Copyright (C) 2023 by Fonoster Inc (https://fonoster.com)
9
9
  * http://github.com/fonoster/routr
10
10
  *
11
11
  * This file is part of Routr
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@routr/processor",
3
- "version": "2.0.8-alpha.9",
3
+ "version": "2.0.9",
4
4
  "description": "Processor server and API",
5
5
  "author": "Pedro Sanders <psanders@fonoster.com>",
6
6
  "homepage": "https://github.com/fonoster/routr#readme",
@@ -12,9 +12,9 @@
12
12
  "build": "tsc -b tsconfig.json"
13
13
  },
14
14
  "dependencies": {
15
- "@fonoster/logger": "0.3.18",
16
- "@grpc/grpc-js": "^1.5.9",
17
- "@grpc/proto-loader": "^0.6.9",
15
+ "@fonoster/logger": "0.3.20",
16
+ "@grpc/grpc-js": "^1.8.4",
17
+ "@grpc/proto-loader": "^0.7.2",
18
18
  "@opentelemetry/api": "^1.0.4",
19
19
  "@opentelemetry/exporter-jaeger": "^1.0.4",
20
20
  "@opentelemetry/instrumentation": "^0.27.0",
@@ -23,8 +23,9 @@
23
23
  "@opentelemetry/sdk-trace-base": "^1.0.4",
24
24
  "@opentelemetry/sdk-trace-node": "^1.0.4",
25
25
  "@opentelemetry/semantic-conventions": "^1.0.4",
26
- "@routr/common": "^2.0.8-alpha.9",
27
- "fp-ts": "^2.11.8"
26
+ "@routr/common": "^2.0.9",
27
+ "fp-ts": "^2.11.8",
28
+ "phone": "^3.1.32"
28
29
  },
29
30
  "directories": {
30
31
  "src": "src",
@@ -43,5 +44,5 @@
43
44
  "bugs": {
44
45
  "url": "https://github.com/fonoster/routr/issues"
45
46
  },
46
- "gitHead": "9ebb361db74fad2b3891fc9add683ddfde2efdff"
47
+ "gitHead": "62eb05f0b3bfa05d84c9ce4b4644de5fb5453295"
47
48
  }