@routr/common 2.0.8-alpha.0 → 2.0.8-alpha.10

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.
package/dist/auth.d.ts CHANGED
@@ -13,3 +13,42 @@ export declare const calculateAuthResponse: (res: AuthChallengeResponse, credent
13
13
  username: string;
14
14
  secret: string;
15
15
  }) => string;
16
+ export declare const getCredentials: (username: string, users: {
17
+ username: string;
18
+ secret: string;
19
+ }[]) => {
20
+ username: string;
21
+ secret: string;
22
+ };
23
+ export declare const createUnauthorizedResponse: (realm: string, params?: {
24
+ qop: string;
25
+ algorithm: string;
26
+ }) => {
27
+ message: {
28
+ responseType: number;
29
+ wwwAuthenticate: {
30
+ scheme: string;
31
+ realm: string;
32
+ qop: string;
33
+ opaque: string;
34
+ stale: boolean;
35
+ nonce: string;
36
+ algorithm: string;
37
+ };
38
+ };
39
+ };
40
+ export declare const createUnauthorizedResponseWithoutChallenge: () => {
41
+ message: {
42
+ responseType: number;
43
+ };
44
+ };
45
+ export declare const createServerInternalErrorResponse: () => {
46
+ message: {
47
+ responseType: number;
48
+ };
49
+ };
50
+ export declare const createForbideenResponse: () => {
51
+ message: {
52
+ responseType: number;
53
+ };
54
+ };
package/dist/auth.js CHANGED
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.calculateAuthResponse = exports.buildAuthChallenge = exports.generateNonce = void 0;
6
+ exports.createForbideenResponse = exports.createServerInternalErrorResponse = exports.createUnauthorizedResponseWithoutChallenge = exports.createUnauthorizedResponse = exports.getCredentials = exports.calculateAuthResponse = exports.buildAuthChallenge = exports.generateNonce = void 0;
7
7
  const crypto_1 = __importDefault(require("crypto"));
8
8
  const DEFAULT_ALGORITHM = "MD5";
9
9
  const md5hex = (str, algorithm = DEFAULT_ALGORITHM) => crypto_1.default.createHash(algorithm).update(str).digest("hex");
@@ -35,3 +35,50 @@ const calculateAuthResponse = (res, credentials) => {
35
35
  : md5hex(`${ha1}:${res.nonce}:${ha2}`);
36
36
  };
37
37
  exports.calculateAuthResponse = calculateAuthResponse;
38
+ const getCredentials = (username, users) => users.find((user) => user.username === username);
39
+ exports.getCredentials = getCredentials;
40
+ const createUnauthorizedResponse = (realm, params = { qop: "auth", algorithm: "MD5" }) => {
41
+ return {
42
+ message: {
43
+ // Unauthorized Code
44
+ responseType: 17,
45
+ wwwAuthenticate: {
46
+ scheme: "Digest",
47
+ realm: realm,
48
+ qop: params.qop,
49
+ opaque: "",
50
+ stale: false,
51
+ nonce: (0, exports.generateNonce)(),
52
+ algorithm: params.algorithm
53
+ }
54
+ }
55
+ };
56
+ };
57
+ exports.createUnauthorizedResponse = createUnauthorizedResponse;
58
+ const createUnauthorizedResponseWithoutChallenge = () => {
59
+ return {
60
+ message: {
61
+ // Unauthorized Code
62
+ responseType: 17
63
+ }
64
+ };
65
+ };
66
+ exports.createUnauthorizedResponseWithoutChallenge = createUnauthorizedResponseWithoutChallenge;
67
+ const createServerInternalErrorResponse = () => {
68
+ return {
69
+ message: {
70
+ // Unauthorized Code
71
+ responseType: 46
72
+ }
73
+ };
74
+ };
75
+ exports.createServerInternalErrorResponse = createServerInternalErrorResponse;
76
+ const createForbideenResponse = () => {
77
+ return {
78
+ message: {
79
+ // Forbideen Code
80
+ responseType: 19
81
+ }
82
+ };
83
+ };
84
+ exports.createForbideenResponse = createForbideenResponse;
@@ -60,7 +60,7 @@ function dataAPI(apiAddr) {
60
60
  get: (ref) => new Promise((resolve, reject) => {
61
61
  client.get({ ref }, (err, response) => {
62
62
  if (err) {
63
- return (err === null || err === void 0 ? void 0 : err.code) === grpc.status.UNAVAILABLE
63
+ return err.code === grpc.status.UNAVAILABLE
64
64
  ? reject(new errors_1.ServiceUnavailableError(`api server at ${apiAddr} is unavailable`))
65
65
  : reject(err);
66
66
  }
@@ -74,7 +74,7 @@ function dataAPI(apiAddr) {
74
74
  client.findBy(request, (err, response) => {
75
75
  var _a;
76
76
  if (err) {
77
- return (err === null || err === void 0 ? void 0 : err.code) === grpc.status.UNAVAILABLE
77
+ return err.code === grpc.status.UNAVAILABLE
78
78
  ? reject(new errors_1.ServiceUnavailableError(`api server at ${apiAddr} is unavailable`))
79
79
  : reject(err);
80
80
  }
@@ -1,21 +1,24 @@
1
- export declare enum KIND {
1
+ export declare enum Kind {
2
2
  AGENT = "agent",
3
3
  PEER = "peer",
4
4
  NUMBER = "number",
5
5
  TRUNK = "trunk",
6
6
  DOMAIN = "domain",
7
7
  UNKNOWN = "unknown",
8
- CREDENTIAL = "credential"
8
+ CREDENTIAL = "credential",
9
+ ACL = "accesscontrollist"
9
10
  }
10
11
  export declare enum FindCriteria {
11
12
  FIND_AGENT_BY_USERNAME = "find_agent_by_username",
13
+ FIND_PEER_BY_USERNAME = "find_peer_by_username",
12
14
  FIND_CREDENTIAL_BY_REFERENCE = "find_credential_by_reference",
13
15
  FIND_DOMAIN_BY_DOMAINURI = "find_domain_by_domainuri",
14
16
  FIND_NUMBER_BY_TELURL = "find_number_by_telurl",
15
- FIND_TRUNKS_WITH_SEND_REGISTER = "find_trunks_with_send_register"
17
+ FIND_TRUNKS_WITH_SEND_REGISTER = "find_trunks_with_send_register",
18
+ FIND_TRUNK_BY_REQUEST_URI = "find_trunk_by_request_uri"
16
19
  }
17
20
  export interface FindParameters {
18
- kind: KIND;
21
+ kind: Kind;
19
22
  criteria: FindCriteria;
20
23
  parameters: Record<string, string>;
21
24
  }
@@ -25,7 +28,7 @@ export interface DataAPI {
25
28
  }
26
29
  export interface Resource {
27
30
  apiVersion: string;
28
- kind: string;
31
+ kind: Kind;
29
32
  ref: string;
30
33
  metadata: {
31
34
  name: string;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.FindCriteria = exports.KIND = void 0;
3
+ exports.FindCriteria = exports.Kind = void 0;
4
4
  /*
5
5
  * Copyright (C) 2022 by Fonoster Inc (https://fonoster.com)
6
6
  * http://github.com/fonoster
@@ -19,21 +19,24 @@ exports.FindCriteria = exports.KIND = void 0;
19
19
  * See the License for the specific language governing permissions and
20
20
  * limitations under the License.
21
21
  */
22
- var KIND;
23
- (function (KIND) {
24
- KIND["AGENT"] = "agent";
25
- KIND["PEER"] = "peer";
26
- KIND["NUMBER"] = "number";
27
- KIND["TRUNK"] = "trunk";
28
- KIND["DOMAIN"] = "domain";
29
- KIND["UNKNOWN"] = "unknown";
30
- KIND["CREDENTIAL"] = "credential";
31
- })(KIND = exports.KIND || (exports.KIND = {}));
22
+ var Kind;
23
+ (function (Kind) {
24
+ Kind["AGENT"] = "agent";
25
+ Kind["PEER"] = "peer";
26
+ Kind["NUMBER"] = "number";
27
+ Kind["TRUNK"] = "trunk";
28
+ Kind["DOMAIN"] = "domain";
29
+ Kind["UNKNOWN"] = "unknown";
30
+ Kind["CREDENTIAL"] = "credential";
31
+ Kind["ACL"] = "accesscontrollist";
32
+ })(Kind = exports.Kind || (exports.Kind = {}));
32
33
  var FindCriteria;
33
34
  (function (FindCriteria) {
34
35
  FindCriteria["FIND_AGENT_BY_USERNAME"] = "find_agent_by_username";
36
+ FindCriteria["FIND_PEER_BY_USERNAME"] = "find_peer_by_username";
35
37
  FindCriteria["FIND_CREDENTIAL_BY_REFERENCE"] = "find_credential_by_reference";
36
38
  FindCriteria["FIND_DOMAIN_BY_DOMAINURI"] = "find_domain_by_domainuri";
37
39
  FindCriteria["FIND_NUMBER_BY_TELURL"] = "find_number_by_telurl";
38
40
  FindCriteria["FIND_TRUNKS_WITH_SEND_REGISTER"] = "find_trunks_with_send_register";
41
+ FindCriteria["FIND_TRUNK_BY_REQUEST_URI"] = "find_trunk_by_request_uri";
39
42
  })(FindCriteria = exports.FindCriteria || (exports.FindCriteria = {}));
package/dist/helper.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { NetInterface, Transport } from "./types";
1
2
  /**
2
3
  * Makes a deep copy of an object.
3
4
  *
@@ -5,3 +6,11 @@
5
6
  * @return {object} The deep copy of the source object.
6
7
  */
7
8
  export declare const deepCopy: <T>(source: T) => T;
9
+ /**
10
+ * Gets a listening point from a request.
11
+ *
12
+ * @param {NetInterface[]} listeningPoints - The listening points.
13
+ * @param {Transport} transport - The transport.
14
+ * @return {NetInterface} transport The deep copy of the source object.
15
+ */
16
+ export declare const getListeningPoint: (listeningPoints: NetInterface[], transport: Transport) => NetInterface;
package/dist/helper.js CHANGED
@@ -1,4 +1,6 @@
1
1
  "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getListeningPoint = exports.deepCopy = void 0;
2
4
  /*
3
5
  * Copyright (C) 2022 by Fonoster Inc (https://fonoster.com)
4
6
  * http://github.com/fonoster/routr
@@ -17,8 +19,7 @@
17
19
  * See the License for the specific language governing permissions and
18
20
  * limitations under the License.
19
21
  */
20
- Object.defineProperty(exports, "__esModule", { value: true });
21
- exports.deepCopy = void 0;
22
+ const types_1 = require("./types");
22
23
  /**
23
24
  * Makes a deep copy of an object.
24
25
  *
@@ -40,3 +41,20 @@ const deepCopy = (source) => {
40
41
  : source;
41
42
  };
42
43
  exports.deepCopy = deepCopy;
44
+ /**
45
+ * Gets a listening point from a request.
46
+ *
47
+ * @param {NetInterface[]} listeningPoints - The listening points.
48
+ * @param {Transport} transport - The transport.
49
+ * @return {NetInterface} transport The deep copy of the source object.
50
+ */
51
+ const getListeningPoint = (listeningPoints, transport) => {
52
+ const listeningPoint = transport
53
+ ? listeningPoints.find((lp) => lp.transport.toLowerCase() === transport.toLowerCase())
54
+ : listeningPoints.find((lp) => lp.transport.toLowerCase() === types_1.Transport.UDP);
55
+ if (!listeningPoint) {
56
+ throw new Error(`no listening point found for transport ${transport}`);
57
+ }
58
+ return listeningPoint;
59
+ };
60
+ exports.getListeningPoint = getListeningPoint;
package/dist/index.d.ts CHANGED
@@ -1,8 +1,7 @@
1
- import { calculateAuthResponse, generateNonce } from "./auth";
2
1
  import { ServiceUnavailableError } from "./errors";
3
2
  import createService, { getObjectProto, LOCATION_OBJECT_PROTO, PROCESSOR_OBJECT_PROTO } from "./service";
4
3
  import { HeaderModifier, MessageRequest, MessageResponse, Method, NetInterface, ObjectProto, ProcessorConfig, Route, ServiceInfo, Transport } from "./types";
5
- export { createService, getObjectProto, generateNonce, calculateAuthResponse, HeaderModifier, Route, ServiceUnavailableError, Transport, ProcessorConfig, MessageRequest, MessageResponse, NetInterface, Method, ObjectProto, ServiceInfo, PROCESSOR_OBJECT_PROTO, LOCATION_OBJECT_PROTO };
4
+ export { createService, getObjectProto, HeaderModifier, Route, ServiceUnavailableError, Transport, ProcessorConfig, MessageRequest, MessageResponse, NetInterface, Method, ObjectProto, ServiceInfo, PROCESSOR_OBJECT_PROTO, LOCATION_OBJECT_PROTO };
6
5
  export * as Redis from "./redis";
7
6
  export * as CommonTypes from "./types";
8
7
  export * as Helper from "./helper";
@@ -11,3 +10,4 @@ export * as Tracer from "./tracer";
11
10
  export * as Assertions from "./assertions";
12
11
  export * as CommonConnect from "./connect";
13
12
  export * as CommonRequester from "./requester";
13
+ export * as Auth from "./auth";
package/dist/index.js CHANGED
@@ -23,7 +23,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
23
23
  return result;
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.CommonRequester = exports.CommonConnect = exports.Assertions = exports.Tracer = exports.IpUtils = exports.Helper = exports.CommonTypes = exports.Redis = exports.LOCATION_OBJECT_PROTO = exports.PROCESSOR_OBJECT_PROTO = exports.Method = exports.Transport = exports.ServiceUnavailableError = exports.calculateAuthResponse = exports.generateNonce = exports.getObjectProto = exports.createService = void 0;
26
+ exports.Auth = exports.CommonRequester = exports.CommonConnect = exports.Assertions = exports.Tracer = exports.IpUtils = exports.Helper = exports.CommonTypes = exports.Redis = exports.LOCATION_OBJECT_PROTO = exports.PROCESSOR_OBJECT_PROTO = exports.Method = exports.Transport = exports.ServiceUnavailableError = exports.getObjectProto = exports.createService = void 0;
27
27
  /*
28
28
  * Copyright (C) 2022 by Fonoster Inc (https://fonoster.com)
29
29
  * http://github.com/fonoster/routr
@@ -42,9 +42,6 @@ exports.CommonRequester = exports.CommonConnect = exports.Assertions = exports.T
42
42
  * See the License for the specific language governing permissions and
43
43
  * limitations under the License.
44
44
  */
45
- const auth_1 = require("./auth");
46
- Object.defineProperty(exports, "calculateAuthResponse", { enumerable: true, get: function () { return auth_1.calculateAuthResponse; } });
47
- Object.defineProperty(exports, "generateNonce", { enumerable: true, get: function () { return auth_1.generateNonce; } });
48
45
  const errors_1 = require("./errors");
49
46
  Object.defineProperty(exports, "ServiceUnavailableError", { enumerable: true, get: function () { return errors_1.ServiceUnavailableError; } });
50
47
  const service_1 = __importStar(require("./service"));
@@ -63,3 +60,4 @@ exports.Tracer = __importStar(require("./tracer"));
63
60
  exports.Assertions = __importStar(require("./assertions"));
64
61
  exports.CommonConnect = __importStar(require("./connect"));
65
62
  exports.CommonRequester = __importStar(require("./requester"));
63
+ exports.Auth = __importStar(require("./auth"));
@@ -2,3 +2,4 @@ export declare const formatNet: (net: string) => string;
2
2
  export declare const hasIp: (net: string, addr: string) => boolean;
3
3
  export declare const addressCount: (net: string) => number;
4
4
  export declare const isLocalnet: (nets: string[], addr: string) => boolean;
5
+ export declare const getLocalnetIp: (nets: string[], addr: string) => string;
package/dist/ip_utils.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isLocalnet = exports.addressCount = exports.hasIp = exports.formatNet = void 0;
3
+ exports.getLocalnetIp = exports.isLocalnet = exports.addressCount = exports.hasIp = exports.formatNet = void 0;
4
4
  /*
5
5
  * Copyright (C) 2022 by Fonoster Inc (https://fonoster.com)
6
6
  * http://github.com/fonoster/routr
@@ -39,5 +39,7 @@ const hasIp = (net, addr) => (0, ip_utils_1.subnet)((0, exports.formatNet)(net))
39
39
  exports.hasIp = hasIp;
40
40
  const addressCount = (net) => (0, ip_utils_1.cidrInfo)((0, exports.formatNet)(net)).inclusiveNumberHosts;
41
41
  exports.addressCount = addressCount;
42
- const isLocalnet = (nets, addr) => nets && nets.length > 0 && nets.filter((net) => (0, exports.hasIp)(net, addr)).length > 0;
42
+ const isLocalnet = (nets, addr) => (nets === null || nets === void 0 ? void 0 : nets.filter((net) => (0, exports.hasIp)(net, addr)).length) > 0;
43
43
  exports.isLocalnet = isLocalnet;
44
+ const getLocalnetIp = (nets, addr) => { var _a; return (_a = nets === null || nets === void 0 ? void 0 : nets.filter((net) => (0, exports.hasIp)(net, addr))[0]) === null || _a === void 0 ? void 0 : _a.split("/")[0]; };
45
+ exports.getLocalnetIp = getLocalnetIp;
@@ -34,7 +34,7 @@ service Location {
34
34
  rpc RemoveRoutes (RemoveRoutesRequest) returns (fonoster.routr.common.v2draft1.Empty) {}
35
35
  }
36
36
 
37
- // A binding create by an actual endpoint (Softphone, PBX, Conference System, etc.)
37
+ // A binding created by an actual endpoint (Softphone, PBX, Conference System, etc.)
38
38
  message Route {
39
39
  string user = 1;
40
40
  string host = 2;
@@ -44,11 +44,13 @@ message Route {
44
44
  int32 expires = 6;
45
45
  int32 session_count = 7;
46
46
  string edge_port_ref = 8;
47
- fonoster.routr.processor.v2draft1.NetInterface listening_point = 9;
47
+ repeated fonoster.routr.processor.v2draft1.NetInterface listening_points = 9;
48
+ repeated string localnets = 10;
49
+ repeated string external_addrs = 11;
48
50
  // During route creation, an endpoint can request to add labels than can later be
49
51
  // used as selectors. For example, a Softphone can add a label `priority=1` to indicate
50
52
  // that it is the prefered endpoint for the given AOR.
51
- map<string, string> labels = 10;
53
+ map<string, string> labels = 12;
52
54
  }
53
55
 
54
56
  message AddRouteRequest {
@@ -78,11 +78,11 @@ message MessageRequest {
78
78
  string edge_port_ref = 2;
79
79
  Method method = 3;
80
80
  NetInterface sender = 4;
81
- NetInterface listening_point = 5;
81
+ repeated NetInterface listening_points = 5;
82
82
  repeated string external_addrs = 6;
83
83
  repeated string localnets = 7;
84
84
  fonoster.routr.sipmessage.v2draft1.SIPMessage message = 8;
85
- // .google.protobuf.Struct metadata = 8;
85
+ // .google.protobuf.Struct metadata = 9;
86
86
  }
87
87
 
88
88
  message MessageResponse {
package/dist/types.d.ts CHANGED
@@ -13,18 +13,20 @@ export declare enum Method {
13
13
  OPTIONS = "OPTIONS"
14
14
  }
15
15
  export declare enum Transport {
16
- TCP = "TCP",
17
- UDP = "UDP",
18
- TLS = "TLS",
19
- SCTP = "SCTP",
20
- WS = "WS",
21
- WSS = "WSS"
16
+ TCP = "tcp",
17
+ UDP = "udp",
18
+ TLS = "tls",
19
+ SCTP = "sctp",
20
+ WS = "ws",
21
+ WSS = "wss"
22
22
  }
23
23
  export declare enum ExtraHeader {
24
24
  REQUEST_URI = "X-Request-Uri",
25
25
  GATEWAY_AUTH = "X-Gateway-Auth",
26
26
  EDGEPORT_REF = "X-Edgeport-Ref",
27
- SESSION_COUNT = "X-Session-Count"
27
+ SESSION_COUNT = "X-Session-Count",
28
+ DOD_NUMBER = "X-DOD-Number",
29
+ DOD_PRIVACY = "X-DOD-Privacy"
28
30
  }
29
31
  export declare enum Privacy {
30
32
  NONE = "none",
@@ -40,7 +42,7 @@ export interface MessageRequest {
40
42
  edgePortRef: string;
41
43
  method: Method;
42
44
  sender: NetInterface;
43
- listeningPoint: NetInterface;
45
+ listeningPoints: NetInterface[];
44
46
  externalAddrs: string[];
45
47
  localnets: string[];
46
48
  message: SIPMessage;
@@ -113,7 +115,9 @@ export interface Route {
113
115
  sessionCount?: number;
114
116
  expires?: number;
115
117
  edgePortRef: string;
116
- listeningPoint: NetInterface;
118
+ listeningPoints: NetInterface[];
119
+ localnets: string[];
120
+ externalAddrs: string[];
117
121
  labels?: Map<string, string>;
118
122
  headers?: HeaderModifier[];
119
123
  }
@@ -281,10 +285,10 @@ export interface SIPMessage {
281
285
  wwwAuthenticate?: WWWAuthenticate;
282
286
  maxForwards: MaxForwards;
283
287
  authorization?: Authorization;
284
- extensions?: Extension[];
285
- via?: Via[];
286
- route?: RouteHeader[];
287
- recordRoute?: RecordRoute[];
288
+ extensions: Extension[];
289
+ via: Via[];
290
+ route: RouteHeader[];
291
+ recordRoute: RecordRoute[];
288
292
  }
289
293
  export interface GrpcCallback {
290
294
  (error: Error | {
package/dist/types.js CHANGED
@@ -17,12 +17,12 @@ var Method;
17
17
  })(Method = exports.Method || (exports.Method = {}));
18
18
  var Transport;
19
19
  (function (Transport) {
20
- Transport["TCP"] = "TCP";
21
- Transport["UDP"] = "UDP";
22
- Transport["TLS"] = "TLS";
23
- Transport["SCTP"] = "SCTP";
24
- Transport["WS"] = "WS";
25
- Transport["WSS"] = "WSS";
20
+ Transport["TCP"] = "tcp";
21
+ Transport["UDP"] = "udp";
22
+ Transport["TLS"] = "tls";
23
+ Transport["SCTP"] = "sctp";
24
+ Transport["WS"] = "ws";
25
+ Transport["WSS"] = "wss";
26
26
  })(Transport = exports.Transport || (exports.Transport = {}));
27
27
  var ExtraHeader;
28
28
  (function (ExtraHeader) {
@@ -30,6 +30,8 @@ var ExtraHeader;
30
30
  ExtraHeader["GATEWAY_AUTH"] = "X-Gateway-Auth";
31
31
  ExtraHeader["EDGEPORT_REF"] = "X-Edgeport-Ref";
32
32
  ExtraHeader["SESSION_COUNT"] = "X-Session-Count";
33
+ ExtraHeader["DOD_NUMBER"] = "X-DOD-Number";
34
+ ExtraHeader["DOD_PRIVACY"] = "X-DOD-Privacy";
33
35
  })(ExtraHeader = exports.ExtraHeader || (exports.ExtraHeader = {}));
34
36
  var Privacy;
35
37
  (function (Privacy) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@routr/common",
3
- "version": "2.0.8-alpha.0",
3
+ "version": "2.0.8-alpha.10",
4
4
  "description": "Common package",
5
5
  "author": "Pedro Sanders <psanders@fonoster.com>",
6
6
  "homepage": "https://github.com/fonoster/routr#readme",
@@ -45,5 +45,5 @@
45
45
  "bugs": {
46
46
  "url": "https://github.com/fonoster/routr/issues"
47
47
  },
48
- "gitHead": "69c60f113c27bc00cbadb62dbdbbb70960ef0f4d"
48
+ "gitHead": "5082233fb155ddb8535f934550fa4013da87468e"
49
49
  }