@routr/connect 2.0.8-alpha.2 → 2.0.8-alpha.22
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/access.d.ts +28 -0
- package/dist/access.js +117 -0
- package/dist/errors.d.ts +3 -3
- package/dist/errors.js +4 -4
- package/dist/handlers.d.ts +3 -3
- package/dist/handlers.js +45 -15
- package/dist/router.d.ts +2 -3
- package/dist/router.js +126 -49
- package/dist/service.js +2 -2
- package/dist/tailor.js +2 -3
- package/dist/types.d.ts +1 -1
- package/dist/types.js +11 -10
- package/dist/utils.d.ts +15 -11
- package/dist/utils.js +72 -60
- package/package.json +5 -5
package/dist/access.d.ts
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
import { MessageRequest, CommonTypes as CT, CommonConnect as CC } from "@routr/common";
|
2
|
+
import { RoutingDirection } from "./types";
|
3
|
+
export declare const checkAccess: (accessRequest: {
|
4
|
+
apiClient: CC.APIClient;
|
5
|
+
request: MessageRequest;
|
6
|
+
caller: CC.RoutableResourceUnion;
|
7
|
+
callee: CC.RoutableResourceUnion;
|
8
|
+
routingDirection: RoutingDirection;
|
9
|
+
}) => Promise<Record<string, unknown>>;
|
10
|
+
export declare const checkAgentOrPeerAccess: (request: MessageRequest, caller: CC.RoutableResourceUnion) => Promise<{
|
11
|
+
message: {
|
12
|
+
responseType: CT.ResponseType;
|
13
|
+
wwwAuthenticate: {
|
14
|
+
scheme: string;
|
15
|
+
realm: string;
|
16
|
+
qop: string;
|
17
|
+
opaque: string;
|
18
|
+
stale: boolean;
|
19
|
+
nonce: string;
|
20
|
+
algorithm: string;
|
21
|
+
};
|
22
|
+
};
|
23
|
+
}>;
|
24
|
+
export declare const checkAccessFromPSTN: (apiClient: CC.APIClient, request: MessageRequest, callee: CC.INumber) => Promise<{
|
25
|
+
message: {
|
26
|
+
responseType: CT.ResponseType;
|
27
|
+
};
|
28
|
+
}>;
|
package/dist/access.js
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
9
|
+
});
|
10
|
+
};
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
12
|
+
exports.checkAccessFromPSTN = exports.checkAgentOrPeerAccess = exports.checkAccess = void 0;
|
13
|
+
/*
|
14
|
+
* Copyright (C) 2022 by Fonoster Inc (https://fonoster.com)
|
15
|
+
* http://github.com/fonoster
|
16
|
+
*
|
17
|
+
* This file is part of Routr.
|
18
|
+
*
|
19
|
+
* Licensed under the MIT License (the "License");
|
20
|
+
* you may not use this file except in compliance with
|
21
|
+
* the License. You may obtain a copy of the License at
|
22
|
+
*
|
23
|
+
* https://opensource.org/licenses/MIT
|
24
|
+
*
|
25
|
+
* Unless required by applicable law or agreed to in writing, software
|
26
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
27
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
28
|
+
* See the License for the specific language governing permissions and
|
29
|
+
* limitations under the License.
|
30
|
+
*/
|
31
|
+
const logger_1 = require("@fonoster/logger");
|
32
|
+
const common_1 = require("@routr/common");
|
33
|
+
const types_1 = require("./types");
|
34
|
+
const logger = (0, logger_1.getLogger)({ service: "connect", filePath: __filename });
|
35
|
+
const checkAccess = (accessRequest) => __awaiter(void 0, void 0, void 0, function* () {
|
36
|
+
const { apiClient, request, caller, callee, routingDirection } = accessRequest;
|
37
|
+
switch (routingDirection) {
|
38
|
+
case types_1.RoutingDirection.PEER_TO_PSTN:
|
39
|
+
case types_1.RoutingDirection.AGENT_TO_AGENT:
|
40
|
+
case types_1.RoutingDirection.AGENT_TO_PSTN:
|
41
|
+
return (0, exports.checkAgentOrPeerAccess)(request, caller);
|
42
|
+
case types_1.RoutingDirection.FROM_PSTN:
|
43
|
+
return (0, exports.checkAccessFromPSTN)(apiClient, request, callee);
|
44
|
+
case types_1.RoutingDirection.UNKNOWN:
|
45
|
+
return common_1.Auth.createForbideenResponse();
|
46
|
+
}
|
47
|
+
});
|
48
|
+
exports.checkAccess = checkAccess;
|
49
|
+
const checkAgentOrPeerAccess = (request, caller) => __awaiter(void 0, void 0, void 0, function* () {
|
50
|
+
// Calculate and return challenge
|
51
|
+
if (request.message.authorization) {
|
52
|
+
const auth = Object.assign({}, request.message.authorization);
|
53
|
+
auth.method = request.method;
|
54
|
+
const credentials = caller.credentials;
|
55
|
+
// Calculate response and compare with the one send by the endpoint
|
56
|
+
const calcRes = common_1.Auth.calculateAuthResponse(auth, {
|
57
|
+
username: credentials === null || credentials === void 0 ? void 0 : credentials.username,
|
58
|
+
secret: credentials === null || credentials === void 0 ? void 0 : credentials.password
|
59
|
+
});
|
60
|
+
if (calcRes !== auth.response) {
|
61
|
+
return common_1.Auth.createUnauthorizedResponse(request.message.requestUri.host);
|
62
|
+
}
|
63
|
+
}
|
64
|
+
else {
|
65
|
+
return common_1.Auth.createUnauthorizedResponse(request.message.requestUri.host);
|
66
|
+
}
|
67
|
+
});
|
68
|
+
exports.checkAgentOrPeerAccess = checkAgentOrPeerAccess;
|
69
|
+
const checkAccessFromPSTN = (apiClient, request, callee) => __awaiter(void 0, void 0, void 0, function* () {
|
70
|
+
// Get the Trunk associated with the SIP URI
|
71
|
+
const trunk = (yield apiClient.trunks.findBy({
|
72
|
+
fieldName: "inboundUri",
|
73
|
+
fieldValue: request.message.requestUri.host
|
74
|
+
})).items[0];
|
75
|
+
// If the Trunk or Number doesn't exist reject the call
|
76
|
+
if (!callee || !trunk) {
|
77
|
+
return common_1.Auth.createForbideenResponse();
|
78
|
+
}
|
79
|
+
if (callee.trunk.ref !== trunk.ref) {
|
80
|
+
return common_1.Auth.createForbideenResponse();
|
81
|
+
}
|
82
|
+
// Verify that the IP is whitelisted which means getting the access control list for the trunk
|
83
|
+
if (trunk.accessControlList) {
|
84
|
+
try {
|
85
|
+
const allow = trunk.accessControlList.allow.filter((net) => {
|
86
|
+
return common_1.IpUtils.hasIp(net, request.sender.host);
|
87
|
+
})[0];
|
88
|
+
if (!allow) {
|
89
|
+
return common_1.Auth.createUnauthorizedResponseWithoutChallenge();
|
90
|
+
}
|
91
|
+
}
|
92
|
+
catch (e) {
|
93
|
+
logger.error(e);
|
94
|
+
return common_1.Auth.createServerInternalErrorResponse();
|
95
|
+
}
|
96
|
+
}
|
97
|
+
// If the Trunk has a User/Password we must verify that the User/Password are valid
|
98
|
+
if (trunk.inboundCredentials) {
|
99
|
+
// Calculate and return challenge
|
100
|
+
if (request.message.authorization) {
|
101
|
+
const auth = Object.assign({}, request.message.authorization);
|
102
|
+
auth.method = request.method;
|
103
|
+
// Calculate response and compare with the one send by the endpoint
|
104
|
+
const calcRes = common_1.Auth.calculateAuthResponse(auth, {
|
105
|
+
username: trunk.inboundCredentials.username,
|
106
|
+
secret: trunk.inboundCredentials.password
|
107
|
+
});
|
108
|
+
if (calcRes !== auth.response) {
|
109
|
+
return common_1.Auth.createUnauthorizedResponse(request.message.requestUri.host);
|
110
|
+
}
|
111
|
+
}
|
112
|
+
else {
|
113
|
+
return common_1.Auth.createUnauthorizedResponse(request.message.requestUri.host);
|
114
|
+
}
|
115
|
+
}
|
116
|
+
});
|
117
|
+
exports.checkAccessFromPSTN = checkAccessFromPSTN;
|
package/dist/errors.d.ts
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import {
|
1
|
+
import { RoutingDirection } from "./types";
|
2
2
|
/**
|
3
3
|
* Throw when the API server is unavailable.
|
4
4
|
*/
|
@@ -19,7 +19,7 @@ export declare class UnsuportedRoutingError extends Error {
|
|
19
19
|
/**
|
20
20
|
* Create a new ServiceUnavailableError.
|
21
21
|
*
|
22
|
-
* @param {
|
22
|
+
* @param {RoutingDirection} routingDirection - The routing direction
|
23
23
|
*/
|
24
|
-
constructor(
|
24
|
+
constructor(routingDirection: RoutingDirection);
|
25
25
|
}
|
package/dist/errors.js
CHANGED
@@ -67,11 +67,11 @@ class UnsuportedRoutingError extends Error {
|
|
67
67
|
/**
|
68
68
|
* Create a new ServiceUnavailableError.
|
69
69
|
*
|
70
|
-
* @param {
|
70
|
+
* @param {RoutingDirection} routingDirection - The routing direction
|
71
71
|
*/
|
72
|
-
constructor(
|
73
|
-
super("unsupported routing direction: " +
|
74
|
-
this.code = grpc.status.
|
72
|
+
constructor(routingDirection) {
|
73
|
+
super("unsupported routing direction: " + routingDirection);
|
74
|
+
this.code = grpc.status.UNIMPLEMENTED;
|
75
75
|
// Set the prototype explicitly.
|
76
76
|
Object.setPrototypeOf(this, ServiceUnavailableError.prototype);
|
77
77
|
}
|
package/dist/handlers.d.ts
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
import { MessageRequest, Response } from "@routr/processor";
|
2
|
-
import { ILocationService } from "@routr/location
|
2
|
+
import { ILocationService } from "@routr/location";
|
3
3
|
import { CommonConnect as CC } from "@routr/common";
|
4
|
-
export declare const handleRegister: (location: ILocationService) => (request: MessageRequest, res: Response) => Promise<void>;
|
4
|
+
export declare const handleRegister: (apiClient: CC.APIClient, location: ILocationService) => (request: MessageRequest, res: Response) => Promise<void>;
|
5
5
|
export declare const handleRegistry: (req: MessageRequest, res: Response) => void;
|
6
|
-
export declare const handleRequest: (location: ILocationService,
|
6
|
+
export declare const handleRequest: (location: ILocationService, apiClient?: CC.APIClient) => (req: MessageRequest, res: Response) => Promise<void>;
|
package/dist/handlers.js
CHANGED
@@ -34,37 +34,67 @@ const processor_1 = require("@routr/processor");
|
|
34
34
|
const function_1 = require("fp-ts/function");
|
35
35
|
const router_1 = require("./router");
|
36
36
|
const common_1 = require("@routr/common");
|
37
|
-
const
|
37
|
+
const utils_1 = require("./utils");
|
38
|
+
const handleRegister = (apiClient, location) => {
|
38
39
|
return (request, res) => __awaiter(void 0, void 0, void 0, function* () {
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
40
|
+
// Calculate and return challenge
|
41
|
+
if (request.message.authorization) {
|
42
|
+
const auth = Object.assign({}, request.message.authorization);
|
43
|
+
auth.method = request.method;
|
44
|
+
const fromURI = request.message.from.address.uri;
|
45
|
+
const peerOrAgent = yield (0, utils_1.findResource)(apiClient, fromURI.host, fromURI.user);
|
46
|
+
if (!peerOrAgent) {
|
47
|
+
return res.send(common_1.Auth.createForbideenResponse());
|
48
|
+
}
|
49
|
+
const credentials = peerOrAgent.credentials;
|
50
|
+
// Calculate response and compare with the one send by the endpoint
|
51
|
+
const calcRes = common_1.Auth.calculateAuthResponse(auth, {
|
52
|
+
username: credentials === null || credentials === void 0 ? void 0 : credentials.username,
|
53
|
+
secret: credentials === null || credentials === void 0 ? void 0 : credentials.password
|
54
|
+
});
|
55
|
+
if (calcRes !== auth.response) {
|
56
|
+
return res.send(common_1.Auth.createUnauthorizedResponse(request.message.requestUri.host));
|
57
|
+
}
|
58
|
+
// TODO: Needs test
|
59
|
+
yield location.addRoute({
|
60
|
+
aor: "aor" in peerOrAgent ? peerOrAgent.aor : processor_1.Target.getTargetAOR(request),
|
61
|
+
route: location_1.Helper.createRoute(request)
|
62
|
+
});
|
63
|
+
res.sendOk();
|
64
|
+
}
|
65
|
+
else {
|
66
|
+
return res.send(common_1.Auth.createUnauthorizedResponse(request.message.requestUri.host));
|
67
|
+
}
|
44
68
|
});
|
45
69
|
};
|
46
70
|
exports.handleRegister = handleRegister;
|
47
71
|
// TODO: Needs test
|
48
72
|
const handleRegistry = (req, res) => {
|
49
73
|
const route = processor_1.Helper.createRouteFromLastMessage(req);
|
50
|
-
res.send((0, function_1.pipe)(req, processor_1.Alterations.addSelfVia(route), processor_1.Alterations.decreaseMaxForwards, processor_1.Alterations.removeAuthorization, processor_1.Alterations.
|
74
|
+
res.send((0, function_1.pipe)(req, processor_1.Alterations.addSelfVia(route), processor_1.Alterations.decreaseMaxForwards, processor_1.Alterations.removeAuthorization, processor_1.Alterations.removeSelfRoutes, processor_1.Alterations.removeXEdgePortRef));
|
51
75
|
};
|
52
76
|
exports.handleRegistry = handleRegistry;
|
53
77
|
// TODO: If request has X-Connect-Token then validate the JWT value and continue
|
54
|
-
const handleRequest = (location,
|
78
|
+
const handleRequest = (location, apiClient) => (req, res) => __awaiter(void 0, void 0, void 0, function* () {
|
55
79
|
try {
|
56
80
|
const route = processor_1.Extensions.getHeaderValue(req, common_1.CommonTypes.ExtraHeader.EDGEPORT_REF)
|
57
81
|
? processor_1.Helper.createRouteFromLastMessage(req)
|
58
|
-
: yield (0, router_1.router)(location,
|
82
|
+
: yield (0, router_1.router)(location, apiClient)(req);
|
59
83
|
if (!route)
|
60
84
|
return res.sendNotFound();
|
61
|
-
//
|
62
|
-
if (
|
63
|
-
return
|
64
|
-
|
65
|
-
|
85
|
+
// If route is not type Route then return
|
86
|
+
if (!("listeningPoints" in route)) {
|
87
|
+
return res.send(route);
|
88
|
+
}
|
89
|
+
else {
|
90
|
+
// Forward request to peer edgeport
|
91
|
+
if (req.edgePortRef !== route.edgePortRef) {
|
92
|
+
return res.send((0, function_1.pipe)(req, processor_1.Alterations.addSelfVia(route), processor_1.Alterations.addSelfRecordRoute(route),
|
93
|
+
// The order of the routes is important
|
94
|
+
processor_1.Alterations.addRouteToPeerEdgePort(route), processor_1.Alterations.addRouteToNextHop(route), processor_1.Alterations.addXEdgePortRef, processor_1.Alterations.decreaseMaxForwards));
|
95
|
+
}
|
96
|
+
res.send((0, tailor_1.tailor)(route, req));
|
66
97
|
}
|
67
|
-
res.send((0, tailor_1.tailor)(route, req));
|
68
98
|
}
|
69
99
|
catch (err) {
|
70
100
|
res.sendError(err);
|
package/dist/router.d.ts
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
import { Route } from "@routr/common";
|
1
|
+
import { CommonConnect as CC, Route } from "@routr/common";
|
2
2
|
import { MessageRequest } from "@routr/processor";
|
3
3
|
import { ILocationService } from "@routr/location";
|
4
|
-
|
5
|
-
export declare function router(location: ILocationService, dataAPI: CC.DataAPI): (req: MessageRequest) => Promise<Route>;
|
4
|
+
export declare function router(location: ILocationService, apiClient: CC.APIClient): (request: MessageRequest) => Promise<Route | Record<string, unknown>>;
|
package/dist/router.js
CHANGED
@@ -32,33 +32,51 @@ const types_1 = require("./types");
|
|
32
32
|
const common_1 = require("@routr/common");
|
33
33
|
const utils_1 = require("./utils");
|
34
34
|
const processor_1 = require("@routr/processor");
|
35
|
-
const errors_1 = require("./errors");
|
36
35
|
const location_1 = require("@routr/location");
|
36
|
+
const errors_1 = require("./errors");
|
37
37
|
const logger_1 = require("@fonoster/logger");
|
38
|
-
const
|
38
|
+
const access_1 = require("./access");
|
39
39
|
const logger = (0, logger_1.getLogger)({ service: "connect", filePath: __filename });
|
40
|
-
const getSIPURI = (uri) => `sip:${uri.user}@${uri.host}`;
|
41
40
|
// eslint-disable-next-line require-jsdoc
|
42
|
-
function router(location,
|
43
|
-
return (
|
44
|
-
const fromURI =
|
45
|
-
const requestURI =
|
41
|
+
function router(location, apiClient) {
|
42
|
+
return (request) => __awaiter(this, void 0, void 0, function* () {
|
43
|
+
const fromURI = request.message.from.address.uri;
|
44
|
+
const requestURI = request.message.requestUri;
|
45
|
+
const caller = yield (0, utils_1.findResource)(apiClient, fromURI.host, fromURI.user);
|
46
|
+
const callee = yield (0, utils_1.findResource)(apiClient, requestURI.host, requestURI.user);
|
47
|
+
const routingDirection = (0, utils_1.getRoutingDirection)(caller, callee);
|
46
48
|
logger.verbose("routing request from: " +
|
47
|
-
getSIPURI(fromURI) +
|
49
|
+
(0, utils_1.getSIPURI)(fromURI) +
|
48
50
|
", to: " +
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
51
|
+
(0, utils_1.getSIPURI)(requestURI), {
|
52
|
+
fromURI: (0, utils_1.getSIPURI)(fromURI),
|
53
|
+
requestURI: (0, utils_1.getSIPURI)(requestURI),
|
54
|
+
routingDirection
|
55
|
+
// sessionAffinityHeader: callee?.spec.location?.sessionAffinityHeader
|
56
|
+
});
|
57
|
+
if (request.method === common_1.CommonTypes.Method.INVITE) {
|
58
|
+
const failedCheck = yield (0, access_1.checkAccess)({
|
59
|
+
apiClient,
|
60
|
+
request,
|
61
|
+
caller,
|
62
|
+
callee,
|
63
|
+
routingDirection
|
64
|
+
});
|
65
|
+
if (failedCheck) {
|
66
|
+
return failedCheck;
|
67
|
+
}
|
68
|
+
}
|
69
|
+
switch (routingDirection) {
|
70
|
+
case types_1.RoutingDirection.AGENT_TO_AGENT:
|
71
|
+
return agentToAgent(location, request);
|
72
|
+
case types_1.RoutingDirection.AGENT_TO_PSTN:
|
73
|
+
return yield agentToPSTN(request, caller, requestURI.user);
|
74
|
+
case types_1.RoutingDirection.FROM_PSTN:
|
75
|
+
return yield fromPSTN(apiClient, location, callee, request);
|
76
|
+
case types_1.RoutingDirection.PEER_TO_PSTN:
|
77
|
+
return yield peerToPSTN(apiClient, request);
|
60
78
|
default:
|
61
|
-
throw new errors_1.UnsuportedRoutingError(
|
79
|
+
throw new errors_1.UnsuportedRoutingError(routingDirection);
|
62
80
|
}
|
63
81
|
});
|
64
82
|
}
|
@@ -66,33 +84,50 @@ exports.router = router;
|
|
66
84
|
// eslint-disable-next-line require-jsdoc
|
67
85
|
function agentToAgent(location, req) {
|
68
86
|
return __awaiter(this, void 0, void 0, function* () {
|
69
|
-
return (yield location.findRoutes({ aor: processor_1.Target.getTargetAOR(req) }))[0];
|
87
|
+
return (yield location.findRoutes({ aor: processor_1.Target.getTargetAOR(req), callId: req.ref }))[0];
|
70
88
|
});
|
71
89
|
}
|
72
90
|
/**
|
73
91
|
* From PSTN routing.
|
74
92
|
*
|
93
|
+
* @param {APIClient} apiClient - API client
|
75
94
|
* @param {ILocationService} location - Location service
|
76
|
-
* @param {uknown} _
|
77
95
|
* @param {Resource} callee - The callee
|
96
|
+
* @param {MessageRequest} req - The request
|
78
97
|
* @return {Promise<Route>}
|
79
98
|
*/
|
80
|
-
function fromPSTN(location,
|
99
|
+
function fromPSTN(apiClient, location, callee, req) {
|
81
100
|
var _a;
|
82
101
|
return __awaiter(this, void 0, void 0, function* () {
|
102
|
+
const sessionAffinityRef = processor_1.Extensions.getHeaderValue(req, callee.sessionAffinityHeader);
|
103
|
+
let backend;
|
104
|
+
if (callee.aorLink.startsWith("backend:")) {
|
105
|
+
const peer = (yield apiClient.peers.findBy({
|
106
|
+
fieldName: "aor",
|
107
|
+
fieldValue: callee.aorLink
|
108
|
+
})).items[0];
|
109
|
+
backend = {
|
110
|
+
ref: peer.ref,
|
111
|
+
balancingAlgorithm: peer.balancingAlgorithm,
|
112
|
+
withSessionAffinity: peer.withSessionAffinity
|
113
|
+
};
|
114
|
+
}
|
83
115
|
const route = (yield location.findRoutes({
|
84
|
-
aor: callee.
|
116
|
+
aor: callee.aorLink,
|
117
|
+
callId: req.ref,
|
118
|
+
sessionAffinityRef,
|
119
|
+
backend
|
85
120
|
}))[0];
|
86
121
|
if (!route) {
|
87
|
-
throw new location_1.NotRoutesFoundForAOR(callee.
|
122
|
+
throw new location_1.NotRoutesFoundForAOR(callee.aorLink);
|
88
123
|
}
|
89
124
|
if (!route.headers)
|
90
125
|
route.headers = [];
|
91
|
-
(_a = callee.
|
126
|
+
(_a = callee.extraHeaders) === null || _a === void 0 ? void 0 : _a.forEach((prop) => {
|
92
127
|
const p = {
|
93
128
|
name: prop.name,
|
94
129
|
value: prop.value,
|
95
|
-
action:
|
130
|
+
action: common_1.CommonTypes.HeaderModifierAction.ADD
|
96
131
|
};
|
97
132
|
route.headers.push(p);
|
98
133
|
});
|
@@ -100,50 +135,92 @@ function fromPSTN(location, _, callee) {
|
|
100
135
|
});
|
101
136
|
}
|
102
137
|
// eslint-disable-next-line require-jsdoc
|
103
|
-
function
|
104
|
-
var _a, _b;
|
138
|
+
function agentToPSTN(req, agent, calleeNumber) {
|
139
|
+
var _a, _b, _c, _d, _e;
|
105
140
|
return __awaiter(this, void 0, void 0, function* () {
|
106
|
-
|
141
|
+
if (!((_a = agent.domain) === null || _a === void 0 ? void 0 : _a.egressPolicies)) {
|
142
|
+
// TODO: Create custom error
|
143
|
+
throw new Error(`no egress policy found for Domain ref: ${agent.domain.ref}`);
|
144
|
+
}
|
107
145
|
// Look for Number in domain that matches regex callee
|
108
|
-
const policy =
|
146
|
+
const policy = agent.domain.egressPolicies.find((policy) => {
|
109
147
|
const regex = new RegExp(policy.rule);
|
110
148
|
return regex.test(calleeNumber);
|
111
149
|
});
|
112
|
-
const
|
113
|
-
const trunk = yield dataAPI.get(number === null || number === void 0 ? void 0 : number.spec.trunkRef);
|
114
|
-
if (!domain.spec.context.egressPolicies) {
|
115
|
-
// TODO: Create custom error
|
116
|
-
throw new Error(`no egress policy found for Domain ref: ${domain.ref}`);
|
117
|
-
}
|
150
|
+
const trunk = (_b = policy.number) === null || _b === void 0 ? void 0 : _b.trunk;
|
118
151
|
if (!trunk) {
|
119
|
-
//
|
120
|
-
throw new Error(`no trunk associated with Number ref: ${number === null ||
|
152
|
+
// This should never happen
|
153
|
+
throw new Error(`no trunk associated with Number ref: ${(_c = policy.number) === null || _c === void 0 ? void 0 : _c.ref}`);
|
121
154
|
}
|
122
155
|
const uri = (0, utils_1.getTrunkURI)(trunk);
|
123
|
-
|
156
|
+
return {
|
157
|
+
user: uri.user,
|
158
|
+
host: uri.host,
|
159
|
+
port: uri.port,
|
160
|
+
transport: (_d = uri.transport) === null || _d === void 0 ? void 0 : _d.toUpperCase(),
|
161
|
+
edgePortRef: req.edgePortRef,
|
162
|
+
listeningPoints: req.listeningPoints,
|
163
|
+
localnets: req.localnets,
|
164
|
+
externalAddrs: req.externalAddrs,
|
165
|
+
headers: [
|
166
|
+
// TODO: Find a more deterministic way to re-add the Privacy header
|
167
|
+
{
|
168
|
+
name: "Privacy",
|
169
|
+
action: common_1.CommonTypes.HeaderModifierAction.REMOVE
|
170
|
+
},
|
171
|
+
{
|
172
|
+
name: "Privacy",
|
173
|
+
value: ((_e = agent.privacy) === null || _e === void 0 ? void 0 : _e.toUpperCase()) === common_1.CommonTypes.Privacy.PRIVATE
|
174
|
+
? common_1.CommonTypes.Privacy.PRIVATE.toLowerCase()
|
175
|
+
: common_1.CommonTypes.Privacy.NONE.toLowerCase(),
|
176
|
+
action: common_1.CommonTypes.HeaderModifierAction.ADD
|
177
|
+
},
|
178
|
+
(0, utils_1.createRemotePartyId)(trunk, policy.number),
|
179
|
+
(0, utils_1.createPAssertedIdentity)(req, trunk, policy.number),
|
180
|
+
yield (0, utils_1.createTrunkAuthentication)(trunk)
|
181
|
+
]
|
182
|
+
};
|
183
|
+
});
|
184
|
+
}
|
185
|
+
// eslint-disable-next-line require-jsdoc
|
186
|
+
function peerToPSTN(apiClient, req) {
|
187
|
+
return __awaiter(this, void 0, void 0, function* () {
|
188
|
+
const numberTel = processor_1.Extensions.getHeaderValue(req, common_1.CommonTypes.ExtraHeader.DOD_NUMBER);
|
189
|
+
const privacy = processor_1.Extensions.getHeaderValue(req, common_1.CommonTypes.ExtraHeader.DOD_PRIVACY);
|
190
|
+
const number = yield (0, utils_1.findNumberByTelUrl)(apiClient, `tel:${numberTel}`);
|
191
|
+
if (!number) {
|
192
|
+
throw new Error(`no Number found for tel: ${numberTel}`);
|
193
|
+
}
|
194
|
+
if (!number.trunk) {
|
195
|
+
// TODO: Create custom error
|
196
|
+
throw new Error(`no trunk associated with Number ref: ${number.ref}`);
|
197
|
+
}
|
198
|
+
const uri = (0, utils_1.getTrunkURI)(number.trunk);
|
124
199
|
return {
|
125
200
|
user: uri.user,
|
126
201
|
host: uri.host,
|
127
202
|
port: uri.port,
|
128
203
|
transport: uri.transport,
|
129
204
|
edgePortRef: req.edgePortRef,
|
130
|
-
|
205
|
+
listeningPoints: req.listeningPoints,
|
206
|
+
localnets: req.localnets,
|
207
|
+
externalAddrs: req.externalAddrs,
|
131
208
|
headers: [
|
132
209
|
// TODO: Find a more deterministic way to re-add the Privacy header
|
133
210
|
{
|
134
211
|
name: "Privacy",
|
135
|
-
action:
|
212
|
+
action: common_1.CommonTypes.HeaderModifierAction.REMOVE
|
136
213
|
},
|
137
214
|
{
|
138
215
|
name: "Privacy",
|
139
|
-
value: (
|
140
|
-
?
|
141
|
-
:
|
142
|
-
action:
|
216
|
+
value: (privacy === null || privacy === void 0 ? void 0 : privacy.toLocaleLowerCase()) === common_1.CommonTypes.Privacy.PRIVATE
|
217
|
+
? common_1.CommonTypes.Privacy.PRIVATE.toLowerCase()
|
218
|
+
: common_1.CommonTypes.Privacy.NONE.toLowerCase(),
|
219
|
+
action: common_1.CommonTypes.HeaderModifierAction.ADD
|
143
220
|
},
|
144
|
-
(0, utils_1.createRemotePartyId)(trunk, number),
|
145
|
-
(0, utils_1.createPAssertedIdentity)(req, trunk, number),
|
146
|
-
yield (0, utils_1.createTrunkAuthentication)(
|
221
|
+
(0, utils_1.createRemotePartyId)(number.trunk, number),
|
222
|
+
(0, utils_1.createPAssertedIdentity)(req, number.trunk, number),
|
223
|
+
yield (0, utils_1.createTrunkAuthentication)(number.trunk)
|
147
224
|
]
|
148
225
|
};
|
149
226
|
});
|
package/dist/service.js
CHANGED
@@ -70,7 +70,7 @@ function ConnectProcessor(config) {
|
|
70
70
|
(0, handlers_1.handleRegistry)(req, res);
|
71
71
|
}
|
72
72
|
else {
|
73
|
-
(0, handlers_1.handleRegister)(location)(req, res);
|
73
|
+
(0, handlers_1.handleRegister)(common_2.CommonConnect.apiClient({ apiAddr: config.apiAddr }), location)(req, res);
|
74
74
|
}
|
75
75
|
break;
|
76
76
|
case common_1.Method.BYE:
|
@@ -78,7 +78,7 @@ function ConnectProcessor(config) {
|
|
78
78
|
res.send((0, tailor_1.tailor)(processor_1.Helper.createRouteFromLastMessage(req), req));
|
79
79
|
break;
|
80
80
|
default:
|
81
|
-
|
81
|
+
(0, handlers_1.handleRequest)(location, common_2.CommonConnect.apiClient({ apiAddr: config.apiAddr }))(req, res);
|
82
82
|
}
|
83
83
|
}));
|
84
84
|
}
|
package/dist/tailor.js
CHANGED
@@ -22,7 +22,6 @@ exports.tailor = void 0;
|
|
22
22
|
const processor_1 = require("@routr/processor");
|
23
23
|
const function_1 = require("fp-ts/function");
|
24
24
|
// Q: Should we add support for strict routing?
|
25
|
-
|
26
|
-
|
27
|
-
);
|
25
|
+
// TODO: Add updateContact for SIP.js support
|
26
|
+
const tailor = (route, req) => (0, function_1.pipe)(req, processor_1.Alterations.decreaseMaxForwards, processor_1.Alterations.removeAuthorization, processor_1.Alterations.removeSelfRoutes, processor_1.Alterations.removeXEdgePortRef, processor_1.Alterations.addSelfVia(route), processor_1.Alterations.applyXHeaders(route), processor_1.Alterations.addSelfRecordRoute(route), processor_1.Alterations.addRouteToNextHop(route));
|
28
27
|
exports.tailor = tailor;
|
package/dist/types.d.ts
CHANGED
package/dist/types.js
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.
|
4
|
-
var
|
5
|
-
(function (
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
3
|
+
exports.RoutingDirection = void 0;
|
4
|
+
var RoutingDirection;
|
5
|
+
(function (RoutingDirection) {
|
6
|
+
RoutingDirection["FROM_PSTN"] = "from-pstn";
|
7
|
+
RoutingDirection["AGENT_TO_AGENT"] = "agent-to-agent";
|
8
|
+
RoutingDirection["AGENT_TO_PSTN"] = "agent-to-pstn";
|
9
|
+
// WARNING: This is not supported yet
|
10
|
+
RoutingDirection["PEER_TO_AGENT"] = "peer-to-agent";
|
11
|
+
RoutingDirection["PEER_TO_PSTN"] = "peer-to-pstn";
|
12
|
+
RoutingDirection["UNKNOWN"] = "unknown";
|
13
|
+
})(RoutingDirection = exports.RoutingDirection || (exports.RoutingDirection = {}));
|
package/dist/utils.d.ts
CHANGED
@@ -1,16 +1,20 @@
|
|
1
|
-
import { HeaderModifier, MessageRequest, Transport } from "@routr/common";
|
2
|
-
import {
|
3
|
-
|
4
|
-
export declare const
|
5
|
-
export declare const
|
6
|
-
export declare const findResource: (
|
7
|
-
export declare const getRoutingDirection: (caller: CC.
|
8
|
-
export declare const createPAssertedIdentity: (req: MessageRequest, trunk: CC.
|
9
|
-
export declare const createRemotePartyId: (trunk: CC.
|
10
|
-
export declare const createTrunkAuthentication: (
|
11
|
-
export declare const getTrunkURI: (trunk: CC.
|
1
|
+
import { HeaderModifier, MessageRequest, Transport, CommonConnect as CC } from "@routr/common";
|
2
|
+
import { RoutingDirection } from "./types";
|
3
|
+
export declare const isKind: (res: CC.RoutableResourceUnion, kind: CC.Kind) => boolean;
|
4
|
+
export declare const findDomain: (apiClient: CC.APIClient, domainUri: string) => Promise<CC.Domain>;
|
5
|
+
export declare const findNumberByTelUrl: (apiClient: CC.APIClient, telUrl: string) => Promise<CC.INumber>;
|
6
|
+
export declare const findResource: (apiClient: CC.APIClient, domainUri: string, userpart: string) => Promise<CC.RoutableResourceUnion>;
|
7
|
+
export declare const getRoutingDirection: (caller: CC.RoutableResourceUnion, callee: CC.RoutableResourceUnion) => RoutingDirection;
|
8
|
+
export declare const createPAssertedIdentity: (req: MessageRequest, trunk: CC.Trunk, number: CC.INumber) => HeaderModifier;
|
9
|
+
export declare const createRemotePartyId: (trunk: CC.Trunk, number: CC.INumber) => HeaderModifier;
|
10
|
+
export declare const createTrunkAuthentication: (trunk: CC.Trunk) => Promise<HeaderModifier>;
|
11
|
+
export declare const getTrunkURI: (trunk: CC.Trunk) => {
|
12
12
|
host: string;
|
13
13
|
port: number;
|
14
14
|
user: string;
|
15
15
|
transport: Transport;
|
16
16
|
};
|
17
|
+
export declare const getSIPURI: (uri: {
|
18
|
+
user?: string;
|
19
|
+
host: string;
|
20
|
+
}) => string;
|
package/dist/utils.js
CHANGED
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
9
9
|
});
|
10
10
|
};
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
12
|
-
exports.getTrunkURI = exports.createTrunkAuthentication = exports.createRemotePartyId = exports.createPAssertedIdentity = exports.getRoutingDirection = exports.findResource = exports.findDomain = exports.isKind = void 0;
|
12
|
+
exports.getSIPURI = exports.getTrunkURI = exports.createTrunkAuthentication = exports.createRemotePartyId = exports.createPAssertedIdentity = exports.getRoutingDirection = exports.findResource = exports.findNumberByTelUrl = exports.findDomain = exports.isKind = void 0;
|
13
13
|
/*
|
14
14
|
* Copyright (C) 2022 by Fonoster Inc (https://fonoster.com)
|
15
15
|
* http://github.com/fonoster/routr
|
@@ -29,116 +29,128 @@ exports.getTrunkURI = exports.createTrunkAuthentication = exports.createRemotePa
|
|
29
29
|
* limitations under the License.
|
30
30
|
*/
|
31
31
|
const common_1 = require("@routr/common");
|
32
|
-
const common_2 = require("@routr/common");
|
33
32
|
const types_1 = require("./types");
|
33
|
+
// OMG, this is so ugly and hacky
|
34
34
|
const isKind = (res, kind) => {
|
35
|
-
if (res == null && kind ===
|
35
|
+
if (res == null && kind === common_1.CommonConnect.Kind.UNKNOWN) {
|
36
|
+
return true;
|
37
|
+
}
|
38
|
+
else if (res == null) {
|
39
|
+
return false;
|
40
|
+
}
|
41
|
+
else if ("privacy" in res && kind === common_1.CommonConnect.Kind.AGENT) {
|
42
|
+
return true;
|
43
|
+
}
|
44
|
+
else if ("telUrl" in res && kind === common_1.CommonConnect.Kind.NUMBER) {
|
45
|
+
return true;
|
46
|
+
}
|
47
|
+
else if ("username" in res && kind === common_1.CommonConnect.Kind.PEER) {
|
36
48
|
return true;
|
37
49
|
}
|
38
|
-
return (res === null || res === void 0 ? void 0 : res.kind.toLowerCase()) === kind;
|
39
50
|
};
|
40
51
|
exports.isKind = isKind;
|
41
|
-
const findDomain = (
|
42
|
-
return (yield
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
domainUri
|
47
|
-
}
|
48
|
-
}))[0];
|
52
|
+
const findDomain = (apiClient, domainUri) => __awaiter(void 0, void 0, void 0, function* () {
|
53
|
+
return (yield apiClient.domains.findBy({
|
54
|
+
fieldName: "domainUri",
|
55
|
+
fieldValue: domainUri
|
56
|
+
})).items[0];
|
49
57
|
});
|
50
58
|
exports.findDomain = findDomain;
|
51
|
-
const
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
: res;
|
71
|
-
if ((0, exports.isKind)(res, common_2.CommonConnect.KIND.AGENT) && res.spec.domainRef != (domain === null || domain === void 0 ? void 0 : domain.ref)) {
|
59
|
+
const findNumberByTelUrl = (apiClient, telUrl) => __awaiter(void 0, void 0, void 0, function* () {
|
60
|
+
return (yield apiClient.numbers.findBy({
|
61
|
+
fieldName: "telUrl",
|
62
|
+
fieldValue: telUrl
|
63
|
+
})).items[0];
|
64
|
+
});
|
65
|
+
exports.findNumberByTelUrl = findNumberByTelUrl;
|
66
|
+
const findResource = (apiClient, domainUri, userpart) => __awaiter(void 0, void 0, void 0, function* () {
|
67
|
+
const domain = yield (0, exports.findDomain)(apiClient, domainUri);
|
68
|
+
// First, try to find a number
|
69
|
+
const number = yield (0, exports.findNumberByTelUrl)(apiClient, `tel:${userpart}`);
|
70
|
+
if (number != null)
|
71
|
+
return number;
|
72
|
+
// Next, try to find an agent
|
73
|
+
const agent = (yield apiClient.agents.findBy({
|
74
|
+
fieldName: "username",
|
75
|
+
fieldValue: userpart
|
76
|
+
})).items[0];
|
77
|
+
if (agent && agent.domain.ref != (domain === null || domain === void 0 ? void 0 : domain.ref)) {
|
72
78
|
// Not in the same domain
|
73
79
|
return null;
|
74
80
|
}
|
75
|
-
|
81
|
+
if (agent != null)
|
82
|
+
return agent;
|
83
|
+
// Next, try to find a peer
|
84
|
+
return (yield apiClient.peers.findBy({
|
85
|
+
fieldName: "username",
|
86
|
+
fieldValue: userpart
|
87
|
+
})).items[0];
|
76
88
|
});
|
77
89
|
exports.findResource = findResource;
|
78
90
|
const getRoutingDirection = (caller, callee) => {
|
79
|
-
if ((0, exports.isKind)(caller,
|
80
|
-
return types_1.
|
91
|
+
if ((0, exports.isKind)(caller, common_1.CommonConnect.Kind.AGENT) && (0, exports.isKind)(callee, common_1.CommonConnect.Kind.AGENT)) {
|
92
|
+
return types_1.RoutingDirection.AGENT_TO_AGENT;
|
81
93
|
}
|
82
|
-
if ((0, exports.isKind)(caller,
|
83
|
-
return types_1.
|
94
|
+
if ((0, exports.isKind)(caller, common_1.CommonConnect.Kind.AGENT) && (0, exports.isKind)(callee, common_1.CommonConnect.Kind.UNKNOWN)) {
|
95
|
+
return types_1.RoutingDirection.AGENT_TO_PSTN;
|
84
96
|
}
|
85
|
-
if ((0, exports.isKind)(caller,
|
86
|
-
return types_1.
|
97
|
+
if ((0, exports.isKind)(caller, common_1.CommonConnect.Kind.PEER) && (0, exports.isKind)(callee, common_1.CommonConnect.Kind.AGENT)) {
|
98
|
+
return types_1.RoutingDirection.PEER_TO_AGENT;
|
87
99
|
}
|
88
100
|
// All we know is that the Number is managed by this instance of Routr
|
89
|
-
if ((0, exports.isKind)(callee,
|
90
|
-
return types_1.
|
101
|
+
if ((0, exports.isKind)(callee, common_1.CommonConnect.Kind.NUMBER)) {
|
102
|
+
return types_1.RoutingDirection.FROM_PSTN;
|
91
103
|
}
|
92
|
-
if ((0, exports.isKind)(caller,
|
93
|
-
return types_1.
|
104
|
+
if ((0, exports.isKind)(caller, common_1.CommonConnect.Kind.PEER) && (0, exports.isKind)(callee, common_1.CommonConnect.Kind.UNKNOWN)) {
|
105
|
+
return types_1.RoutingDirection.PEER_TO_PSTN;
|
94
106
|
}
|
95
|
-
return types_1.
|
107
|
+
return types_1.RoutingDirection.UNKNOWN;
|
96
108
|
};
|
97
109
|
exports.getRoutingDirection = getRoutingDirection;
|
98
110
|
const createPAssertedIdentity = (req, trunk, number) => {
|
99
111
|
const displayName = req.message.from.address.displayName;
|
100
|
-
const remoteNumber = number.
|
112
|
+
const remoteNumber = number.telUrl.split(":")[1];
|
101
113
|
const trunkHost = (0, exports.getTrunkURI)(trunk).host;
|
102
114
|
return {
|
103
115
|
name: "P-Asserted-Identity",
|
104
116
|
value: displayName
|
105
117
|
? `"${displayName}" <sip:${remoteNumber}@${trunkHost};user=phone>`
|
106
118
|
: `<sip:${remoteNumber}@${trunkHost};user=phone>`,
|
107
|
-
action:
|
119
|
+
action: common_1.CommonTypes.HeaderModifierAction.ADD
|
108
120
|
};
|
109
121
|
};
|
110
122
|
exports.createPAssertedIdentity = createPAssertedIdentity;
|
111
123
|
const createRemotePartyId = (trunk, number) => {
|
112
|
-
const remoteNumber = number.
|
124
|
+
const remoteNumber = number.telUrl.split(":")[1];
|
113
125
|
const trunkHost = (0, exports.getTrunkURI)(trunk).host;
|
114
126
|
return {
|
115
127
|
name: "Remote-Party-ID",
|
116
128
|
value: `<sip:${remoteNumber}@${trunkHost}>;screen=yes;party=calling`,
|
117
|
-
action:
|
129
|
+
action: common_1.CommonTypes.HeaderModifierAction.ADD
|
118
130
|
};
|
119
131
|
};
|
120
132
|
exports.createRemotePartyId = createRemotePartyId;
|
121
|
-
const createTrunkAuthentication = (
|
133
|
+
const createTrunkAuthentication = (trunk) => __awaiter(void 0, void 0, void 0, function* () {
|
122
134
|
var _a, _b;
|
123
|
-
const credentials = yield dataAPI.get(trunk.spec.outbound.credentialsRef);
|
124
135
|
return {
|
125
|
-
name:
|
126
|
-
value: Buffer.from(`${(_a =
|
127
|
-
action:
|
136
|
+
name: common_1.CommonTypes.ExtraHeader.GATEWAY_AUTH,
|
137
|
+
value: Buffer.from(`${(_a = trunk.outboundCredentials) === null || _a === void 0 ? void 0 : _a.username}:${(_b = trunk.outboundCredentials) === null || _b === void 0 ? void 0 : _b.password}`).toString("base64"),
|
138
|
+
action: common_1.CommonTypes.HeaderModifierAction.ADD
|
128
139
|
};
|
129
140
|
});
|
130
141
|
exports.createTrunkAuthentication = createTrunkAuthentication;
|
131
142
|
const getTrunkURI = (trunk) => {
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
: Object.values(common_1.Transport)[Object.values(common_1.Transport).indexOf(transport.toLowerCase())];
|
143
|
+
if (!trunk.uris) {
|
144
|
+
throw new Error(`trunk ${trunk.ref} has no outbound settings`);
|
145
|
+
}
|
146
|
+
const { user, host, port, transport } = trunk.uris[0];
|
137
147
|
return {
|
138
148
|
user,
|
139
149
|
host,
|
140
150
|
port: port !== null && port !== void 0 ? port : 5060,
|
141
|
-
transport:
|
151
|
+
transport: transport !== null && transport !== void 0 ? transport : common_1.Transport.UDP
|
142
152
|
};
|
143
153
|
};
|
144
154
|
exports.getTrunkURI = getTrunkURI;
|
155
|
+
const getSIPURI = (uri) => uri.user ? `sip:${uri.user}@${uri.host}` : `sip:${uri.host}`;
|
156
|
+
exports.getSIPURI = getSIPURI;
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@routr/connect",
|
3
|
-
"version": "2.0.8-alpha.
|
3
|
+
"version": "2.0.8-alpha.22",
|
4
4
|
"description": "Default processor",
|
5
5
|
"author": "Pedro Sanders <psanders@fonoster.com>",
|
6
6
|
"homepage": "https://github.com/fonoster/routr#readme",
|
@@ -28,9 +28,9 @@
|
|
28
28
|
"@opentelemetry/sdk-trace-base": "^1.0.4",
|
29
29
|
"@opentelemetry/sdk-trace-node": "^1.0.4",
|
30
30
|
"@opentelemetry/semantic-conventions": "^1.0.4",
|
31
|
-
"@routr/common": "^2.0.8-alpha.
|
32
|
-
"@routr/location": "^2.0.8-alpha.
|
33
|
-
"@routr/processor": "^2.0.8-alpha.
|
31
|
+
"@routr/common": "^2.0.8-alpha.22",
|
32
|
+
"@routr/location": "^2.0.8-alpha.22",
|
33
|
+
"@routr/processor": "^2.0.8-alpha.22"
|
34
34
|
},
|
35
35
|
"files": [
|
36
36
|
"dist"
|
@@ -45,5 +45,5 @@
|
|
45
45
|
"bugs": {
|
46
46
|
"url": "https://github.com/fonoster/routr/issues"
|
47
47
|
},
|
48
|
-
"gitHead": "
|
48
|
+
"gitHead": "7c1e14c20e077f817605be62cf61a68904583bb8"
|
49
49
|
}
|