@fonoster/sipnet 0.27.0 → 0.31.0

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.
Files changed (42) hide show
  1. package/dist/acls/updateAcl.d.ts +0 -19
  2. package/dist/acls/updateAcl.js +5 -4
  3. package/dist/agents/buildService.js +4 -2
  4. package/dist/agents/operations.d.ts +3 -2
  5. package/dist/agents/operations.js +5 -4
  6. package/dist/domains/buildService.d.ts +7 -1
  7. package/dist/domains/buildService.js +10 -3
  8. package/dist/domains/operations.d.ts +3 -2
  9. package/dist/domains/operations.js +5 -4
  10. package/dist/numbers/buildService.d.ts +3 -1
  11. package/dist/numbers/buildService.js +6 -3
  12. package/dist/numbers/convertToRoutrNumber.d.ts +6 -2
  13. package/dist/numbers/convertToRoutrNumber.js +8 -4
  14. package/dist/numbers/createNumber.d.ts +3 -1
  15. package/dist/numbers/createNumber.js +13 -4
  16. package/dist/numbers/engineRouting.d.ts +29 -0
  17. package/dist/numbers/engineRouting.js +44 -0
  18. package/dist/numbers/getNumber.d.ts +0 -19
  19. package/dist/numbers/getNumber.js +6 -6
  20. package/dist/numbers/index.d.ts +2 -0
  21. package/dist/numbers/index.js +16 -0
  22. package/dist/numbers/repointNumbers.d.ts +49 -0
  23. package/dist/numbers/repointNumbers.js +83 -0
  24. package/dist/numbers/repointNumbersCli.d.ts +1 -0
  25. package/dist/numbers/repointNumbersCli.js +106 -0
  26. package/dist/numbers/updateNumber.d.ts +4 -2
  27. package/dist/numbers/updateNumber.js +20 -7
  28. package/dist/resources/checkRefs.d.ts +26 -0
  29. package/dist/resources/checkRefs.js +138 -0
  30. package/dist/resources/createResource.d.ts +2 -1
  31. package/dist/resources/createResource.js +5 -2
  32. package/dist/resources/paginationUtils.d.ts +6 -5
  33. package/dist/resources/paginationUtils.js +34 -55
  34. package/dist/resources/sipNames.d.ts +35 -0
  35. package/dist/resources/sipNames.js +46 -0
  36. package/dist/resources/updateResource.d.ts +2 -1
  37. package/dist/resources/updateResource.js +7 -2
  38. package/dist/trunks/buildService.d.ts +7 -1
  39. package/dist/trunks/buildService.js +10 -3
  40. package/dist/trunks/operations.d.ts +10 -3
  41. package/dist/trunks/operations.js +40 -4
  42. package/package.json +9 -10
@@ -1,22 +1,3 @@
1
- /**
2
- * Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
3
- * http://github.com/fonoster/fonoster
4
- *
5
- * This file is part of Fonoster
6
- *
7
- * Licensed under the MIT License (the "License");
8
- * you may not use this file except in compliance with
9
- * the License. You may obtain a copy of the License at
10
- *
11
- * https://opensource.org/licenses/MIT
12
- *
13
- * Unless required by applicable law or agreed to in writing, software
14
- * distributed under the License is distributed on an "AS IS" BASIS,
15
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
- * See the License for the specific language governing permissions and
17
- * limitations under the License.
18
- */
19
- import { GrpcErrorMessage } from "@fonoster/common";
20
1
  import { AclsApi } from "@fonoster/types";
21
2
  declare function updateAcl(api: AclsApi): (call: {
22
3
  request: unknown;
@@ -29,15 +29,16 @@ exports.updateAcl = updateAcl;
29
29
  * limitations under the License.
30
30
  */
31
31
  const common_1 = require("@fonoster/common");
32
+ const identity_1 = require("@fonoster/identity");
32
33
  const logger_1 = require("@fonoster/logger");
33
34
  const logger = (0, logger_1.getLogger)({ service: "sipnet", filePath: __filename });
34
35
  function updateAcl(api) {
35
- const fn = (call, callback) => __awaiter(this, void 0, void 0, function* () {
36
+ const fn = (call) => __awaiter(this, void 0, void 0, function* () {
36
37
  const { request } = call;
37
38
  const accessKeyId = (0, common_1.getAccessKeyIdFromCall)(call);
38
39
  logger.verbose("call to updateAcl", Object.assign(Object.assign({}, request), { accessKeyId }));
39
- const response = yield api.updateAcl(Object.assign(Object.assign({}, request), { deny: ["0.0.0.0/0"] }));
40
- callback(null, response);
40
+ return yield api.updateAcl(Object.assign(Object.assign({}, request), { deny: ["0.0.0.0/0"] }));
41
41
  });
42
- return (0, common_1.withErrorHandlingAndValidation)(fn, common_1.Validators.updateAclRequestSchema);
42
+ // Only the caller's own ACLs can be updated, like every other resource.
43
+ return (0, common_1.withErrorHandlingAndValidation)((0, identity_1.withAccess)(fn, ((ref) => api.getAcl(ref))), common_1.Validators.updateAclRequestSchema);
43
44
  }
@@ -23,9 +23,11 @@ exports.buildService = buildService;
23
23
  * limitations under the License.
24
24
  */
25
25
  const sdk_1 = __importDefault(require("@routr/sdk"));
26
+ const checkRefs_1 = require("../resources/checkRefs");
26
27
  const operations_1 = require("./operations");
27
28
  function buildService(clientOptions) {
28
29
  const client = new sdk_1.default.Agents(clientOptions);
30
+ const checkRefs = (0, checkRefs_1.createCheckRefs)((0, checkRefs_1.createRefLookups)(clientOptions));
29
31
  return {
30
32
  definition: {
31
33
  serviceName: "Agents",
@@ -34,8 +36,8 @@ function buildService(clientOptions) {
34
36
  proto: "agents.proto"
35
37
  },
36
38
  handlers: {
37
- createAgent: (0, operations_1.createAgent)(client),
38
- updateAgent: (0, operations_1.updateAgent)(client),
39
+ createAgent: (0, operations_1.createAgent)(client, checkRefs),
40
+ updateAgent: (0, operations_1.updateAgent)(client, checkRefs),
39
41
  getAgent: (0, operations_1.getAgent)(client),
40
42
  listAgents: (0, operations_1.listAgents)(client),
41
43
  deleteAgent: (0, operations_1.deleteAgent)(client)
@@ -1,8 +1,9 @@
1
1
  import { AgentsApi } from "@fonoster/types";
2
- declare function createAgent(agents: AgentsApi): (call: {
2
+ import { CheckRefs } from "../resources/checkRefs";
3
+ declare function createAgent(agents: AgentsApi, checkRefs?: CheckRefs): (call: {
3
4
  request: unknown;
4
5
  }, callback: (error?: import("@fonoster/common").GrpcErrorMessage, response?: unknown) => void) => Promise<void>;
5
- declare function updateAgent(agents: AgentsApi): (call: {
6
+ declare function updateAgent(agents: AgentsApi, checkRefs?: CheckRefs): (call: {
6
7
  request: unknown;
7
8
  }, callback: (error?: import("@fonoster/common").GrpcErrorMessage, response?: unknown) => void) => Promise<void>;
8
9
  declare function getAgent(agents: AgentsApi): (call: {
@@ -24,17 +24,18 @@ exports.updateAgent = updateAgent;
24
24
  * limitations under the License.
25
25
  */
26
26
  const common_1 = require("@fonoster/common");
27
+ const checkRefs_1 = require("../resources/checkRefs");
27
28
  const createResource_1 = require("../resources/createResource");
28
29
  const deleteResource_1 = require("../resources/deleteResource");
29
30
  const getResource_1 = require("../resources/getResource");
30
31
  const listResources_1 = require("../resources/listResources");
31
32
  const updateResource_1 = require("../resources/updateResource");
32
33
  const RESOURCE = "Agent";
33
- function createAgent(agents) {
34
- return (0, createResource_1.createResource)(agents, RESOURCE, common_1.Validators.createAgentRequestSchema);
34
+ function createAgent(agents, checkRefs) {
35
+ return (0, createResource_1.createResource)(agents, RESOURCE, common_1.Validators.createAgentRequestSchema, (0, checkRefs_1.refsChecker)(checkRefs, checkRefs_1.agentRefs));
35
36
  }
36
- function updateAgent(agents) {
37
- return (0, updateResource_1.updateResource)(agents, RESOURCE, common_1.Validators.updateAgentRequestSchema);
37
+ function updateAgent(agents, checkRefs) {
38
+ return (0, updateResource_1.updateResource)(agents, RESOURCE, common_1.Validators.updateAgentRequestSchema, (0, checkRefs_1.refsChecker)(checkRefs, checkRefs_1.agentRefs));
38
39
  }
39
40
  function getAgent(agents) {
40
41
  return (0, getResource_1.getResource)(agents, RESOURCE);
@@ -1,5 +1,11 @@
1
1
  import { ClientOptions } from "../types";
2
- declare function buildService(clientOptions: ClientOptions): {
2
+ /**
3
+ * `namesRoot` (e.g. `sip.example.com`) makes every domain one label under it;
4
+ * leave it out to accept any domain.
5
+ */
6
+ declare function buildService(clientOptions: ClientOptions, options?: {
7
+ namesRoot?: string;
8
+ }): {
3
9
  definition: {
4
10
  serviceName: string;
5
11
  pckg: string;
@@ -23,9 +23,16 @@ exports.buildService = buildService;
23
23
  * limitations under the License.
24
24
  */
25
25
  const sdk_1 = __importDefault(require("@routr/sdk"));
26
+ const checkRefs_1 = require("../resources/checkRefs");
27
+ const sipNames_1 = require("../resources/sipNames");
26
28
  const operations_1 = require("./operations");
27
- function buildService(clientOptions) {
29
+ /**
30
+ * `namesRoot` (e.g. `sip.example.com`) makes every domain one label under it;
31
+ * leave it out to accept any domain.
32
+ */
33
+ function buildService(clientOptions, options = {}) {
28
34
  const client = new sdk_1.default.Domains(clientOptions);
35
+ const checkRefs = (0, checkRefs_1.createCheckRefs)((0, checkRefs_1.createRefLookups)(clientOptions));
29
36
  return {
30
37
  definition: {
31
38
  serviceName: "Domains",
@@ -34,8 +41,8 @@ function buildService(clientOptions) {
34
41
  proto: "domains.proto"
35
42
  },
36
43
  handlers: {
37
- createDomain: (0, operations_1.createDomain)(client),
38
- updateDomain: (0, operations_1.updateDomain)(client),
44
+ createDomain: (0, sipNames_1.withSipNameCheck)((0, operations_1.createDomain)(client, checkRefs), "domainUri", "domain", options.namesRoot),
45
+ updateDomain: (0, sipNames_1.withSipNameCheck)((0, operations_1.updateDomain)(client, checkRefs), "domainUri", "domain", options.namesRoot),
39
46
  getDomain: (0, operations_1.getDomain)(client),
40
47
  listDomains: (0, operations_1.listDomains)(client),
41
48
  deleteDomain: (0, operations_1.deleteDomain)(client)
@@ -1,8 +1,9 @@
1
1
  import { DomainsApi } from "@fonoster/types";
2
- declare function createDomain(domains: DomainsApi): (call: {
2
+ import { CheckRefs } from "../resources/checkRefs";
3
+ declare function createDomain(domains: DomainsApi, checkRefs?: CheckRefs): (call: {
3
4
  request: unknown;
4
5
  }, callback: (error?: import("@fonoster/common").GrpcErrorMessage, response?: unknown) => void) => Promise<void>;
5
- declare function updateDomain(domains: DomainsApi): (call: {
6
+ declare function updateDomain(domains: DomainsApi, checkRefs?: CheckRefs): (call: {
6
7
  request: unknown;
7
8
  }, callback: (error?: import("@fonoster/common").GrpcErrorMessage, response?: unknown) => void) => Promise<void>;
8
9
  declare function getDomain(domains: DomainsApi): (call: {
@@ -24,17 +24,18 @@ exports.updateDomain = updateDomain;
24
24
  * limitations under the License.
25
25
  */
26
26
  const common_1 = require("@fonoster/common");
27
+ const checkRefs_1 = require("../resources/checkRefs");
27
28
  const createResource_1 = require("../resources/createResource");
28
29
  const deleteResource_1 = require("../resources/deleteResource");
29
30
  const getResource_1 = require("../resources/getResource");
30
31
  const listResources_1 = require("../resources/listResources");
31
32
  const updateResource_1 = require("../resources/updateResource");
32
33
  const RESOURCE = "Domain";
33
- function createDomain(domains) {
34
- return (0, createResource_1.createResource)(domains, RESOURCE, common_1.Validators.createDomainRequestSchema);
34
+ function createDomain(domains, checkRefs) {
35
+ return (0, createResource_1.createResource)(domains, RESOURCE, common_1.Validators.createDomainRequestSchema, (0, checkRefs_1.refsChecker)(checkRefs, checkRefs_1.domainRefs));
35
36
  }
36
- function updateDomain(domains) {
37
- return (0, updateResource_1.updateResource)(domains, RESOURCE, common_1.Validators.updateDomainRequestSchema);
37
+ function updateDomain(domains, checkRefs) {
38
+ return (0, updateResource_1.updateResource)(domains, RESOURCE, common_1.Validators.updateDomainRequestSchema, (0, checkRefs_1.refsChecker)(checkRefs, checkRefs_1.domainRefs));
38
39
  }
39
40
  function getDomain(domains) {
40
41
  return (0, getResource_1.getResource)(domains, RESOURCE);
@@ -18,7 +18,9 @@
18
18
  */
19
19
  import { NumberPreconditionsCheck } from "@fonoster/common";
20
20
  import { ClientOptions } from "../types";
21
- declare function buildService(clientOptions: ClientOptions, checkNumberPreconditions: NumberPreconditionsCheck): {
21
+ import { NumberRouting } from "./engineRouting";
22
+ /** `routing` picks the peer app-linked numbers point at (default: the roomr peer). */
23
+ declare function buildService(clientOptions: ClientOptions, checkNumberPreconditions: NumberPreconditionsCheck, routing?: NumberRouting): {
22
24
  definition: {
23
25
  serviceName: string;
24
26
  pckg: string;
@@ -5,13 +5,16 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.buildService = buildService;
7
7
  const sdk_1 = __importDefault(require("@routr/sdk"));
8
+ const checkRefs_1 = require("../resources/checkRefs");
8
9
  const createNumber_1 = require("./createNumber");
9
10
  const getNumber_1 = require("./getNumber");
10
11
  const listNumbers_1 = require("./listNumbers");
11
12
  const operations_1 = require("./operations");
12
13
  const updateNumber_1 = require("./updateNumber");
13
- function buildService(clientOptions, checkNumberPreconditions) {
14
+ /** `routing` picks the peer app-linked numbers point at (default: the roomr peer). */
15
+ function buildService(clientOptions, checkNumberPreconditions, routing) {
14
16
  const client = new sdk_1.default.Numbers(clientOptions);
17
+ const checkRefs = (0, checkRefs_1.createCheckRefs)((0, checkRefs_1.createRefLookups)(clientOptions));
15
18
  return {
16
19
  definition: {
17
20
  serviceName: "Numbers",
@@ -20,8 +23,8 @@ function buildService(clientOptions, checkNumberPreconditions) {
20
23
  proto: "numbers.proto"
21
24
  },
22
25
  handlers: {
23
- createNumber: (0, createNumber_1.createNumber)(client, checkNumberPreconditions),
24
- updateNumber: (0, updateNumber_1.updateNumber)(client, checkNumberPreconditions),
26
+ createNumber: (0, createNumber_1.createNumber)(client, checkNumberPreconditions, routing, checkRefs),
27
+ updateNumber: (0, updateNumber_1.updateNumber)(client, checkNumberPreconditions, routing, checkRefs),
25
28
  getNumber: (0, getNumber_1.getNumber)(client),
26
29
  listNumbers: (0, listNumbers_1.listNumbers)(client),
27
30
  deleteNumber: (0, operations_1.deleteNumber)(client)
@@ -1,5 +1,9 @@
1
1
  import { CreateNumberRequest, UpdateNumberRequest } from "@fonoster/types";
2
- declare function convertToRoutrNumber(number: CreateNumberRequest, accessKeyId: string): {
2
+ /**
3
+ * `appPeerAor` is the peer an app-linked number routes to: the roomr peer by default (see
4
+ * engineRouting.ts).
5
+ */
6
+ declare function convertToRoutrNumber(number: CreateNumberRequest, accessKeyId: string, appPeerAor?: string): {
3
7
  name: string;
4
8
  telUrl: string;
5
9
  aorLink: string;
@@ -13,7 +17,7 @@ declare function convertToRoutrNumber(number: CreateNumberRequest, accessKeyId:
13
17
  trunkRef: string;
14
18
  extended: Record<string, unknown>;
15
19
  };
16
- declare function convertToRoutrNumberUpdate(number: UpdateNumberRequest): {
20
+ declare function convertToRoutrNumberUpdate(number: UpdateNumberRequest, appPeerAor?: string): {
17
21
  ref: string;
18
22
  name: string;
19
23
  aorLink: string;
@@ -21,8 +21,12 @@ exports.convertToRoutrNumberUpdate = convertToRoutrNumberUpdate;
21
21
  * limitations under the License.
22
22
  */
23
23
  const common_1 = require("@fonoster/common");
24
- function convertToRoutrNumber(number, accessKeyId) {
25
- const aorLink = number.appRef ? common_1.ROUTR_DEFAULT_PEER_AOR : number.agentAor;
24
+ /**
25
+ * `appPeerAor` is the peer an app-linked number routes to: the roomr peer by default (see
26
+ * engineRouting.ts).
27
+ */
28
+ function convertToRoutrNumber(number, accessKeyId, appPeerAor = common_1.ROUTR_DEFAULT_PEER_AOR) {
29
+ const aorLink = number.appRef ? appPeerAor : number.agentAor;
26
30
  return {
27
31
  name: number.name,
28
32
  telUrl: number.telUrl,
@@ -42,11 +46,11 @@ function convertToRoutrNumber(number, accessKeyId) {
42
46
  extended: { accessKeyId }
43
47
  };
44
48
  }
45
- function convertToRoutrNumberUpdate(number) {
49
+ function convertToRoutrNumberUpdate(number, appPeerAor = common_1.ROUTR_DEFAULT_PEER_AOR) {
46
50
  let aorLink;
47
51
  let extraHeaders = [];
48
52
  if (number.appRef) {
49
- aorLink = common_1.ROUTR_DEFAULT_PEER_AOR;
53
+ aorLink = appPeerAor;
50
54
  extraHeaders.push({
51
55
  name: common_1.APP_REF_HEADER,
52
56
  value: number.appRef
@@ -18,7 +18,9 @@
18
18
  */
19
19
  import { GrpcErrorMessage, NumberPreconditionsCheck } from "@fonoster/common";
20
20
  import { NumbersApi } from "@fonoster/types";
21
- declare function createNumber(api: NumbersApi, checkNumberPreconditions: NumberPreconditionsCheck): (call: {
21
+ import { CheckRefs } from "../resources/checkRefs";
22
+ import { NumberRouting } from "./engineRouting";
23
+ declare function createNumber(api: NumbersApi, checkNumberPreconditions: NumberPreconditionsCheck, routing?: NumberRouting, checkRefs?: CheckRefs): (call: {
22
24
  request: unknown;
23
25
  }, callback: (error?: import("@fonoster/common").GrpcErrorMessage, response?: unknown) => void) => Promise<void>;
24
26
  export { createNumber };
@@ -30,16 +30,25 @@ exports.createNumber = createNumber;
30
30
  */
31
31
  const common_1 = require("@fonoster/common");
32
32
  const logger_1 = require("@fonoster/logger");
33
+ const checkRefs_1 = require("../resources/checkRefs");
33
34
  const convertToRoutrNumber_1 = require("./convertToRoutrNumber");
34
35
  const logger = (0, logger_1.getLogger)({ service: "sipnet", filePath: __filename });
35
- function createNumber(api, checkNumberPreconditions) {
36
+ function createNumber(api, checkNumberPreconditions, routing, checkRefs) {
36
37
  const fn = (call, callback) => __awaiter(this, void 0, void 0, function* () {
37
38
  const { request } = call;
38
- // Validates that the appRef or agentAor exists in the system
39
- yield checkNumberPreconditions(request);
40
39
  const accessKeyId = (0, common_1.getAccessKeyIdFromCall)(call);
40
+ // Validates that the appRef exists in the caller's workspace (RV-B4)
41
+ yield checkNumberPreconditions(Object.assign(Object.assign({}, request), { accessKeyId }));
42
+ // ...and the trunk too (H7)
43
+ yield (checkRefs === null || checkRefs === void 0 ? void 0 : checkRefs(accessKeyId, (0, checkRefs_1.numberRefs)(request)));
41
44
  logger.verbose("call to createNumber", Object.assign(Object.assign({}, request), { accessKeyId }));
42
- const response = yield api.createNumber((0, convertToRoutrNumber_1.convertToRoutrNumber)(request, accessKeyId));
45
+ const appPeerAor = routing && request.appRef
46
+ ? yield routing.aorFor({
47
+ appRef: request.appRef,
48
+ telUrl: request.telUrl
49
+ })
50
+ : undefined;
51
+ const response = yield api.createNumber((0, convertToRoutrNumber_1.convertToRoutrNumber)(request, accessKeyId, appPeerAor));
43
52
  callback(null, response);
44
53
  });
45
54
  return (0, common_1.withErrorHandlingAndValidation)(fn, common_1.Validators.createNumberRequestSchema);
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Where app-linked numbers point (add-roomr 4.1). Asterisk is retired (cleanbreak CB-B3):
3
+ * every app-linked number goes to the roomr peer that Go Roomr nodes register under with
4
+ * least-sessions. `rebuild` is the only engine left; the type stays so repoint reports keep
5
+ * their shape.
6
+ */
7
+ export type VoiceEngine = "rebuild";
8
+ export type EngineRoutingConfig = {
9
+ /** The roomr peer AOR (default sip:roomr@default). */
10
+ roomrNodeAor?: string;
11
+ };
12
+ export declare const ROOMR_PEER_AOR = "sip:roomr@default";
13
+ /** The AOR of the retired Asterisk peer, for moving numbers created before the rebuild. */
14
+ export declare const LEGACY_ASTERISK_PEER_AOR = "sip:voice@default";
15
+ export type NumberRouting = {
16
+ /** The engine for an app-linked number. */
17
+ engineFor(target: {
18
+ appRef: string;
19
+ telUrl?: string;
20
+ }): Promise<VoiceEngine>;
21
+ /** The peer AOR (Number.aorLink) for an app-linked number. */
22
+ aorFor(target: {
23
+ appRef: string;
24
+ telUrl?: string;
25
+ }): Promise<string>;
26
+ /** The peer AOR of an engine. */
27
+ aorOf(engine: VoiceEngine): string;
28
+ };
29
+ export declare function createNumberRouting(config?: EngineRoutingConfig): NumberRouting;
@@ -0,0 +1,44 @@
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.LEGACY_ASTERISK_PEER_AOR = exports.ROOMR_PEER_AOR = void 0;
13
+ exports.createNumberRouting = createNumberRouting;
14
+ /**
15
+ * Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
16
+ * http://github.com/fonoster/fonoster
17
+ *
18
+ * This file is part of Fonoster
19
+ *
20
+ * Licensed under the MIT License (the "License");
21
+ * you may not use this file except in compliance with
22
+ * the License. You may obtain a copy of the License at
23
+ *
24
+ * https://opensource.org/licenses/MIT
25
+ *
26
+ * Unless required by applicable law or agreed to in writing, software
27
+ * distributed under the License is distributed on an "AS IS" BASIS,
28
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
29
+ * See the License for the specific language governing permissions and
30
+ * limitations under the License.
31
+ */
32
+ const common_1 = require("@fonoster/common");
33
+ exports.ROOMR_PEER_AOR = common_1.ROUTR_DEFAULT_PEER_AOR;
34
+ /** The AOR of the retired Asterisk peer, for moving numbers created before the rebuild. */
35
+ exports.LEGACY_ASTERISK_PEER_AOR = "sip:voice@default";
36
+ function createNumberRouting(config = {}) {
37
+ var _a;
38
+ const aor = (_a = config.roomrNodeAor) !== null && _a !== void 0 ? _a : exports.ROOMR_PEER_AOR;
39
+ return {
40
+ engineFor: () => __awaiter(this, void 0, void 0, function* () { return "rebuild"; }),
41
+ aorFor: () => __awaiter(this, void 0, void 0, function* () { return aor; }),
42
+ aorOf: () => aor
43
+ };
44
+ }
@@ -1,22 +1,3 @@
1
- /**
2
- * Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
3
- * http://github.com/fonoster/fonoster
4
- *
5
- * This file is part of Fonoster
6
- *
7
- * Licensed under the MIT License (the "License");
8
- * you may not use this file except in compliance with
9
- * the License. You may obtain a copy of the License at
10
- *
11
- * https://opensource.org/licenses/MIT
12
- *
13
- * Unless required by applicable law or agreed to in writing, software
14
- * distributed under the License is distributed on an "AS IS" BASIS,
15
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
- * See the License for the specific language governing permissions and
17
- * limitations under the License.
18
- */
19
- import { GrpcErrorMessage } from "@fonoster/common";
20
1
  import { NumbersApi } from "@fonoster/types";
21
2
  declare function getNumber(api: NumbersApi): (call: {
22
3
  request: unknown;
@@ -29,16 +29,16 @@ exports.getNumber = getNumber;
29
29
  * limitations under the License.
30
30
  */
31
31
  const common_1 = require("@fonoster/common");
32
+ const identity_1 = require("@fonoster/identity");
32
33
  const logger_1 = require("@fonoster/logger");
33
34
  const convertToFonosterNumber_1 = require("./convertToFonosterNumber");
34
35
  const logger = (0, logger_1.getLogger)({ service: "sipnet", filePath: __filename });
35
36
  function getNumber(api) {
36
- const fn = (call, callback) => __awaiter(this, void 0, void 0, function* () {
37
- const { request } = call;
38
- const { ref } = request;
37
+ const fn = (call) => __awaiter(this, void 0, void 0, function* () {
38
+ const { ref } = call.request;
39
39
  logger.verbose("call to getNumber", { ref });
40
- const response = yield api.getNumber(ref);
41
- callback(null, (0, convertToFonosterNumber_1.convertToFonosterNumber)(response));
40
+ return (0, convertToFonosterNumber_1.convertToFonosterNumber)(yield api.getNumber(ref));
42
41
  });
43
- return (0, common_1.withErrorHandlingAndValidation)(fn, common_1.Validators.emptySchema);
42
+ // Only the caller's own numbers can be read, like every other resource.
43
+ return (0, common_1.withErrorHandlingAndValidation)((0, identity_1.withAccess)(fn, ((ref) => api.getNumber(ref))), common_1.Validators.emptySchema);
44
44
  }
@@ -17,3 +17,5 @@
17
17
  * limitations under the License.
18
18
  */
19
19
  export { buildService as buildNumbersService } from "./buildService";
20
+ export * from "./engineRouting";
21
+ export * from "./repointNumbers";
@@ -1,4 +1,18 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
2
16
  Object.defineProperty(exports, "__esModule", { value: true });
3
17
  exports.buildNumbersService = void 0;
4
18
  /**
@@ -21,3 +35,5 @@ exports.buildNumbersService = void 0;
21
35
  */
22
36
  var buildService_1 = require("./buildService");
23
37
  Object.defineProperty(exports, "buildNumbersService", { enumerable: true, get: function () { return buildService_1.buildService; } });
38
+ __exportStar(require("./engineRouting"), exports);
39
+ __exportStar(require("./repointNumbers"), exports);
@@ -0,0 +1,49 @@
1
+ import { NumberRouting, VoiceEngine } from "./engineRouting";
2
+ /** The slice of Routr's Numbers API that repointing needs (`new SDK.Numbers(...)` fits). */
3
+ export type RoutrNumbersClient = {
4
+ listNumbers(request: {
5
+ pageSize: number;
6
+ pageToken?: string;
7
+ }): Promise<{
8
+ items: RoutrNumber[];
9
+ nextPageToken?: string;
10
+ }>;
11
+ updateNumber(request: {
12
+ ref: string;
13
+ name: string;
14
+ aorLink: string;
15
+ extraHeaders?: {
16
+ name: string;
17
+ value: string;
18
+ }[];
19
+ }): Promise<unknown>;
20
+ };
21
+ export type RoutrNumber = {
22
+ ref: string;
23
+ name: string;
24
+ telUrl: string;
25
+ aorLink?: string;
26
+ extraHeaders?: {
27
+ name: string;
28
+ value: string;
29
+ }[];
30
+ };
31
+ export type RepointChange = {
32
+ ref: string;
33
+ telUrl: string;
34
+ appRef: string;
35
+ engine: VoiceEngine;
36
+ from?: string;
37
+ to: string;
38
+ };
39
+ /**
40
+ * Moves app-linked Numbers to the peer routing says (the Roomr nodes). Routr stores `aorLink` on
41
+ * each Number, so numbers created for Asterisk keep pointing at it until they are rewritten;
42
+ * agent-linked Numbers are never touched. Returns what changed (or would,
43
+ * with `dryRun`).
44
+ */
45
+ export declare function repointNumbers(client: RoutrNumbersClient, routing: NumberRouting, options?: {
46
+ appRefs?: string[];
47
+ dryRun?: boolean;
48
+ pageSize?: number;
49
+ }): Promise<RepointChange[]>;
@@ -0,0 +1,83 @@
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.repointNumbers = repointNumbers;
13
+ /**
14
+ * Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
15
+ * http://github.com/fonoster/fonoster
16
+ *
17
+ * This file is part of Fonoster
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 common_1 = require("@fonoster/common");
32
+ /**
33
+ * Moves app-linked Numbers to the peer routing says (the Roomr nodes). Routr stores `aorLink` on
34
+ * each Number, so numbers created for Asterisk keep pointing at it until they are rewritten;
35
+ * agent-linked Numbers are never touched. Returns what changed (or would,
36
+ * with `dryRun`).
37
+ */
38
+ function repointNumbers(client_1, routing_1) {
39
+ return __awaiter(this, arguments, void 0, function* (client, routing, options = {}) {
40
+ var _a, _b, _c;
41
+ const changes = [];
42
+ let pageToken;
43
+ const numbers = [];
44
+ do {
45
+ const page = yield client.listNumbers({
46
+ pageSize: (_a = options.pageSize) !== null && _a !== void 0 ? _a : 100,
47
+ pageToken
48
+ });
49
+ numbers.push(...page.items);
50
+ pageToken = page.nextPageToken || undefined;
51
+ } while (pageToken);
52
+ for (const n of numbers) {
53
+ // Header names are case-insensitive (sipnet writes x-app-ref; operators may write X-App-Ref).
54
+ const appRef = (_c = (_b = n.extraHeaders) === null || _b === void 0 ? void 0 : _b.find((h) => h.name.toLowerCase() === common_1.APP_REF_HEADER.toLowerCase())) === null || _c === void 0 ? void 0 : _c.value;
55
+ if (!appRef)
56
+ continue;
57
+ if (options.appRefs && !options.appRefs.includes(appRef))
58
+ continue;
59
+ const engine = yield routing.engineFor({ appRef, telUrl: n.telUrl });
60
+ const to = routing.aorOf(engine);
61
+ if (n.aorLink === to)
62
+ continue;
63
+ changes.push({
64
+ ref: n.ref,
65
+ telUrl: n.telUrl,
66
+ appRef,
67
+ engine,
68
+ from: n.aorLink,
69
+ to
70
+ });
71
+ if (!options.dryRun) {
72
+ // Routr's update needs the name; extra headers are kept as they are.
73
+ yield client.updateNumber({
74
+ ref: n.ref,
75
+ name: n.name,
76
+ aorLink: to,
77
+ extraHeaders: n.extraHeaders
78
+ });
79
+ }
80
+ }
81
+ return changes;
82
+ });
83
+ }
@@ -0,0 +1 @@
1
+ export {};