@unboundcx/sdk-internal 2.2.0 → 2.3.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.
package/index.js CHANGED
@@ -9,6 +9,9 @@ import { InternalSocketService } from './services/socket.js';
9
9
  import { InternalMasterAuthService } from './services/masterAuth.js';
10
10
  import { InternalBrandingService } from './services/branding.js';
11
11
  import { InternalPhoneNumbersService } from './services/phoneNumbers.js';
12
+ import { InternalVideoService } from './services/video.js';
13
+ import { InternalVoicemailService } from './services/voicemail.js';
14
+ import { InternalVoiceService } from './services/voice.js';
12
15
  import { buildObjectEventV2 } from './utils/buildObjectEventV2.js';
13
16
 
14
17
  export class InternalSDK {
@@ -25,6 +28,9 @@ export class InternalSDK {
25
28
  this.masterAuth = new InternalMasterAuthService(sdk);
26
29
  this.branding = new InternalBrandingService(sdk);
27
30
  this.phoneNumbers = new InternalPhoneNumbersService(sdk);
31
+ this.video = new InternalVideoService(sdk);
32
+ this.voicemail = new InternalVoicemailService(sdk);
33
+ this.voice = new InternalVoiceService(sdk);
28
34
 
29
35
  // Proxy all base SDK properties and methods
30
36
  this._proxyBaseSDK();
@@ -98,6 +104,34 @@ export class InternalSDK {
98
104
  }
99
105
  return this.sdk.token;
100
106
  }
107
+
108
+ /**
109
+ * Governed escape hatch for internal routes reached by path-as-data
110
+ * mechanisms (e.g. a voice-app webhook command that carries its target
111
+ * `url` at runtime), where a typed per-route method isn't possible
112
+ * because the caller doesn't know the route ahead of time. This is the
113
+ * ONLY sanctioned way to hit an internal route this way — if you know
114
+ * the route at write time, add (or use) a typed method on the matching
115
+ * service instead of calling this directly.
116
+ *
117
+ * @param {string} path - Must start with '/internal/'.
118
+ * @param {object} body
119
+ * @param {object} [options]
120
+ * @param {number} [options.timeoutMs]
121
+ */
122
+ async post(path, body, { timeoutMs } = {}) {
123
+ if (typeof path !== 'string' || !path.startsWith('/internal/')) {
124
+ throw new Error(
125
+ `InternalSDK.post: path must be a string starting with '/internal/', got: ${path}`,
126
+ );
127
+ }
128
+
129
+ const params = { body };
130
+ if (timeoutMs) params.timeoutMs = timeoutMs;
131
+
132
+ const result = await this.sdk._fetch(path, 'POST', params);
133
+ return result;
134
+ }
101
135
  }
102
136
 
103
137
  // Extension pattern for the main SDK
@@ -127,4 +161,7 @@ export { InternalSocketService } from './services/socket.js';
127
161
  export { InternalMasterAuthService } from './services/masterAuth.js';
128
162
  export { InternalBrandingService } from './services/branding.js';
129
163
  export { InternalPhoneNumbersService } from './services/phoneNumbers.js';
164
+ export { InternalVideoService } from './services/video.js';
165
+ export { InternalVoicemailService } from './services/voicemail.js';
166
+ export { InternalVoiceService } from './services/voice.js';
130
167
  export { buildObjectEventV2 } from './utils/buildObjectEventV2.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unboundcx/sdk-internal",
3
- "version": "2.2.0",
3
+ "version": "2.3.0",
4
4
  "description": "Internal SDK extension for Unbound - Provides access to internal APIs and administrative functions",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -0,0 +1,111 @@
1
+ export class InternalVideoService {
2
+ constructor(sdk) {
3
+ this.sdk = sdk;
4
+ }
5
+
6
+ /**
7
+ * Meet PSTN bridge join (D2/D3/D10). Called by media-manager's `webhook`
8
+ * v2 command from the meetDialIn app once the caller has DTMF'd a
9
+ * meetingId + PIN. Matches
10
+ * app1-api/src/services/INTERNAL/video/controllers/meetJoin.js.
11
+ *
12
+ * POST /internal/video/meetJoin
13
+ * Body: { callId, from, variables: { meetingId, meetingPin, attempt? } }
14
+ */
15
+ async meetJoin({ callId, from, variables }) {
16
+ this.sdk.validateParams(
17
+ { callId },
18
+ {
19
+ callId: { type: 'string', required: true },
20
+ from: { type: 'string', required: false },
21
+ variables: { type: 'object', required: false },
22
+ },
23
+ );
24
+
25
+ const body = { callId };
26
+ if (from) body.from = from;
27
+ if (variables) body.variables = variables;
28
+
29
+ const params = {
30
+ body,
31
+ };
32
+
33
+ const result = await this.sdk._fetch(
34
+ '/internal/video/meetJoin',
35
+ 'POST',
36
+ params,
37
+ );
38
+ return result;
39
+ }
40
+
41
+ /**
42
+ * Meet PSTN bridge D9 (phone-hangs-up teardown). POST when a callId ==
43
+ * sipCallId leg observed on an active Meet participant ends. Matches
44
+ * app1-api/src/services/INTERNAL/video/controllers/meetCallEnded.js.
45
+ *
46
+ * POST /internal/video/meetCallEnded
47
+ * Body: { sipCallId, accountId }
48
+ */
49
+ async meetCallEnded({ sipCallId, accountId }) {
50
+ this.sdk.validateParams(
51
+ { sipCallId, accountId },
52
+ {
53
+ sipCallId: { type: 'string', required: true },
54
+ accountId: { type: 'string', required: true },
55
+ },
56
+ );
57
+
58
+ const params = {
59
+ body: { sipCallId, accountId },
60
+ };
61
+
62
+ const result = await this.sdk._fetch(
63
+ '/internal/video/meetCallEnded',
64
+ 'POST',
65
+ params,
66
+ );
67
+ return result;
68
+ }
69
+
70
+ /**
71
+ * Meet PSTN bridge dial-out status callback. media-manager's
72
+ * DialEventHandler posts here (fire-and-forget) for pre-answer progress
73
+ * ('trying' | 'ringing' | 'answered') and terminal 'failed' outcomes on a
74
+ * standalone-outbound leg placed via placeOutboundCall's statusWebhook.
75
+ * Matches
76
+ * app1-api/src/services/INTERNAL/video/controllers/meetOutboundStatus.js.
77
+ *
78
+ * The api controller is intentionally tolerant of unknown/extra fields
79
+ * (it only requires participantId, roomId, event), so this method passes
80
+ * the payload through as-is rather than enumerating every static field —
81
+ * add a typed field here if a fixed shape solidifies.
82
+ *
83
+ * POST /internal/video/meetOutboundStatus
84
+ * Body: { event, callId, requestId, participantId, roomId, reason? }
85
+ */
86
+ async meetOutboundStatus(payload) {
87
+ this.sdk.validateParams(
88
+ { payload },
89
+ {
90
+ payload: { type: 'object', required: true },
91
+ },
92
+ );
93
+ const { event, participantId, roomId } = payload || {};
94
+ if (!event || !participantId || !roomId) {
95
+ throw new Error(
96
+ 'meetOutboundStatus requires event, participantId, and roomId.',
97
+ );
98
+ }
99
+
100
+ const params = {
101
+ body: payload,
102
+ };
103
+
104
+ const result = await this.sdk._fetch(
105
+ '/internal/video/meetOutboundStatus',
106
+ 'POST',
107
+ params,
108
+ );
109
+ return result;
110
+ }
111
+ }
@@ -0,0 +1,39 @@
1
+ export class InternalVoiceService {
2
+ constructor(sdk) {
3
+ this.sdk = sdk;
4
+ }
5
+
6
+ /**
7
+ * Bulk write endpoint for the CDR discrete-event timeline (WP6.5).
8
+ * Emitters (sip-processor / media-manager / task-router) call this to
9
+ * report events; fire-and-forget semantics are the CALLER's job, not
10
+ * this method's. Matches
11
+ * app1-api/src/services/INTERNAL/voice/controllers/createCdrEvents.js.
12
+ *
13
+ * POST /internal/voice/cdrEvents
14
+ * Body: {
15
+ * accountId,
16
+ * events: [{ cdrId, sipCallId?, eventType, ts, actorType, actorId?, data? }]
17
+ * } -- max 50 events per request (enforced by the api).
18
+ */
19
+ async createCdrEvents({ accountId, events }) {
20
+ this.sdk.validateParams(
21
+ { accountId, events },
22
+ {
23
+ accountId: { type: 'string', required: true },
24
+ events: { type: 'array', required: true },
25
+ },
26
+ );
27
+
28
+ const params = {
29
+ body: { accountId, events },
30
+ };
31
+
32
+ const result = await this.sdk._fetch(
33
+ '/internal/voice/cdrEvents',
34
+ 'POST',
35
+ params,
36
+ );
37
+ return result;
38
+ }
39
+ }
@@ -0,0 +1,47 @@
1
+ export class InternalVoicemailService {
2
+ constructor(sdk) {
3
+ this.sdk = sdk;
4
+ }
5
+
6
+ /**
7
+ * app1-transcription reports the result of a batch voicemail
8
+ * transcription here after POST /transcription/voicemail finishes
9
+ * (success or failure). Matches
10
+ * app1-api/src/services/INTERNAL/voicemail/controllers/transcriptionComplete.js.
11
+ *
12
+ * POST /internal/voicemail/transcription
13
+ * Body: { accountId, voicemailMessageId, transcription, transcriptionStatus }
14
+ */
15
+ async transcriptionComplete({
16
+ accountId,
17
+ voicemailMessageId,
18
+ transcription,
19
+ transcriptionStatus,
20
+ }) {
21
+ this.sdk.validateParams(
22
+ { accountId, voicemailMessageId, transcriptionStatus },
23
+ {
24
+ accountId: { type: 'string', required: true },
25
+ voicemailMessageId: { type: 'string', required: true },
26
+ transcription: { type: 'string', required: false },
27
+ transcriptionStatus: { type: 'string', required: true },
28
+ },
29
+ );
30
+
31
+ const params = {
32
+ body: {
33
+ accountId,
34
+ voicemailMessageId,
35
+ transcription,
36
+ transcriptionStatus,
37
+ },
38
+ };
39
+
40
+ const result = await this.sdk._fetch(
41
+ '/internal/voicemail/transcription',
42
+ 'POST',
43
+ params,
44
+ );
45
+ return result;
46
+ }
47
+ }