@absolutejs/voice 0.0.22-beta.271 → 0.0.22-beta.273
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/index.d.ts +4 -2
- package/dist/index.js +341 -10
- package/dist/telephony/security.d.ts +95 -0
- package/dist/telephony/telnyx.d.ts +44 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -159,13 +159,15 @@ export type { VoiceS3ReviewStoreClient, VoiceS3ReviewStoreFile, VoiceS3ReviewSto
|
|
|
159
159
|
export type { VoiceSQLiteRuntimeStorage, VoiceSQLiteStoreOptions } from './sqliteStore';
|
|
160
160
|
export type { StoredVoiceIntegrationEvent, StoredVoiceExternalObjectMap, StoredVoiceOpsTask, VoiceExternalObjectMap, VoiceExternalObjectMapStore, VoiceOpsTaskAgeBucket, VoiceOpsTaskAnalyticsOptions, VoiceOpsTaskAnalyticsSummary, VoiceOpsTaskAssignmentRule, VoiceOpsTaskAssignmentRuleCondition, VoiceOpsTaskAssignmentRules, VoiceOpsTaskAssigneeAnalytics, VoiceOpsDispositionTaskPolicies, VoiceOpsSLABreachPolicy, VoiceIntegrationDeliveryStatus, VoiceIntegrationEvent, VoiceIntegrationEventStore, VoiceIntegrationSinkDelivery, VoiceIntegrationEventType, VoiceIntegrationWebhookConfig, VoiceOpsTask, VoiceOpsTaskHistoryEntry, VoiceOpsTaskKind, VoiceOpsTaskPolicy, VoiceOpsTaskPriority, VoiceOpsTaskStatus, VoiceOpsTaskStore, VoiceOpsTaskSummary, VoiceOpsTaskWorkerAnalytics } from './ops';
|
|
161
161
|
export { createTwilioMediaStreamBridge, createTwilioVoiceRoutes, createTwilioVoiceResponse, decodeTwilioMulawBase64, encodeTwilioMulawBase64, transcodePCMToTwilioOutboundPayload, transcodeTwilioInboundPayloadToPCM16 } from './telephony/twilio';
|
|
162
|
+
export { createVoiceTelephonyWebhookSecurityPreset } from './telephony/security';
|
|
162
163
|
export { evaluateVoiceTelephonyContract } from './telephony/contract';
|
|
163
|
-
export { createTelnyxMediaStreamBridge, createTelnyxVoiceResponse, createTelnyxVoiceRoutes, verifyVoiceTelnyxWebhookSignature } from './telephony/telnyx';
|
|
164
|
+
export { createMemoryVoiceTelnyxWebhookEventStore, createTelnyxMediaStreamBridge, createTelnyxVoiceResponse, createTelnyxVoiceRoutes, createVoicePostgresTelnyxWebhookEventStore, createVoiceRedisTelnyxWebhookEventStore, createVoiceSQLiteTelnyxWebhookEventStore, createVoiceTelnyxWebhookVerifier, verifyVoiceTelnyxWebhookSignature } from './telephony/telnyx';
|
|
164
165
|
export { createMemoryVoicePlivoWebhookNonceStore, createPlivoMediaStreamBridge, createPlivoVoiceResponse, createPlivoVoiceRoutes, createVoicePostgresPlivoWebhookNonceStore, createVoicePlivoWebhookVerifier, createVoiceRedisPlivoWebhookNonceStore, createVoiceSQLitePlivoWebhookNonceStore, signVoicePlivoWebhook, verifyVoicePlivoWebhookSignature } from './telephony/plivo';
|
|
165
166
|
export { createVoiceTelephonyCarrierMatrix, createVoiceTelephonyCarrierMatrixRoutes, renderVoiceTelephonyCarrierMatrixHTML } from './telephony/matrix';
|
|
166
167
|
export type { TwilioInboundMessage, TwilioMediaStreamBridge, TwilioMediaStreamBridgeOptions, TwilioMediaStreamSocket, TwilioOutboundClearMessage, TwilioOutboundMarkMessage, TwilioOutboundMediaMessage, TwilioOutboundMessage, TwilioVoiceRouteParameters, TwilioVoiceResponseOptions, TwilioVoiceSmokeCheck, TwilioVoiceSmokeOptions, TwilioVoiceSmokeReport, TwilioVoiceSetupOptions, TwilioVoiceSetupStatus, TwilioVoiceRoutesOptions } from './telephony/twilio';
|
|
168
|
+
export type { VoiceTelephonyWebhookSecurityOptions, VoiceTelephonyWebhookSecurityPreset, VoiceTelephonyWebhookSecurityStorePreset } from './telephony/security';
|
|
167
169
|
export type { VoiceTelephonyContractIssue, VoiceTelephonyContractOptions, VoiceTelephonyContractReport, VoiceTelephonyContractRequirement, VoiceTelephonyProvider, VoiceTelephonySetupStatus, VoiceTelephonySmokeCheck, VoiceTelephonySmokeReport } from './telephony/contract';
|
|
168
|
-
export type { TelnyxInboundMessage, TelnyxMediaPayload, TelnyxMediaStreamBridge, TelnyxMediaStreamBridgeOptions, TelnyxMediaStreamSocket, TelnyxOutboundClearMessage, TelnyxOutboundMarkMessage, TelnyxOutboundMediaMessage, TelnyxOutboundMessage, TelnyxVoiceResponseOptions, TelnyxVoiceRoutesOptions, TelnyxVoiceSetupOptions, TelnyxVoiceSetupStatus, TelnyxVoiceSmokeCheck, TelnyxVoiceSmokeOptions, TelnyxVoiceSmokeReport } from './telephony/telnyx';
|
|
170
|
+
export type { TelnyxInboundMessage, TelnyxMediaPayload, TelnyxMediaStreamBridge, TelnyxMediaStreamBridgeOptions, TelnyxMediaStreamSocket, TelnyxOutboundClearMessage, TelnyxOutboundMarkMessage, TelnyxOutboundMediaMessage, TelnyxOutboundMessage, TelnyxVoiceResponseOptions, TelnyxVoiceRoutesOptions, TelnyxVoiceSetupOptions, TelnyxVoiceSetupStatus, TelnyxVoiceSmokeCheck, TelnyxVoiceSmokeOptions, TelnyxVoiceSmokeReport, VoicePostgresTelnyxWebhookEventStoreOptions, VoiceRedisTelnyxWebhookEventClient, VoiceRedisTelnyxWebhookEventStoreOptions, VoiceSQLiteTelnyxWebhookEventStoreOptions, VoiceTelnyxWebhookEventStore, VoiceTelnyxWebhookEventStoreOptions, VoiceTelnyxWebhookVerifierOptions } from './telephony/telnyx';
|
|
169
171
|
export type { PlivoInboundMessage, PlivoMediaStreamBridge, PlivoMediaStreamBridgeOptions, PlivoMediaStreamSocket, PlivoOutboundCheckpointMessage, PlivoOutboundClearAudioMessage, PlivoOutboundMessage, PlivoOutboundPlayAudioMessage, PlivoVoiceResponseOptions, PlivoVoiceRoutesOptions, PlivoVoiceSetupOptions, PlivoVoiceSetupStatus, PlivoVoiceSmokeCheck, PlivoVoiceSmokeOptions, PlivoVoiceSmokeReport, VoicePostgresPlivoWebhookNonceStoreOptions, VoicePlivoWebhookNonceStore, VoicePlivoWebhookNonceStoreOptions, VoicePlivoWebhookVerifierOptions, VoiceRedisPlivoWebhookNonceClient, VoiceRedisPlivoWebhookNonceStoreOptions, VoiceSQLitePlivoWebhookNonceStoreOptions } from './telephony/plivo';
|
|
170
172
|
export type { VoiceTelephonyCarrierMatrix, VoiceTelephonyCarrierMatrixEntry, VoiceTelephonyCarrierMatrixInput, VoiceTelephonyCarrierMatrixOptions, VoiceTelephonyCarrierMatrixRoutesOptions, VoiceTelephonyCarrierMatrixStatus } from './telephony/matrix';
|
|
171
173
|
export { shapeTelephonyAssistantText } from './telephony/response';
|
package/dist/index.js
CHANGED
|
@@ -19549,6 +19549,7 @@ var createPlivoVoiceRoutes = (options = {}) => {
|
|
|
19549
19549
|
|
|
19550
19550
|
// src/telephony/telnyx.ts
|
|
19551
19551
|
import { Buffer as Buffer6 } from "buffer";
|
|
19552
|
+
import { Database as Database2 } from "bun:sqlite";
|
|
19552
19553
|
import { Elysia as Elysia31 } from "elysia";
|
|
19553
19554
|
var escapeXml4 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
19554
19555
|
var escapeHtml30 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
@@ -19721,6 +19722,198 @@ var verifyVoiceTelnyxWebhookSignature = async (input) => {
|
|
|
19721
19722
|
return { ok: false, reason: "invalid-signature" };
|
|
19722
19723
|
}
|
|
19723
19724
|
};
|
|
19725
|
+
var createMemoryVoiceTelnyxWebhookEventStore = () => {
|
|
19726
|
+
const eventIds = new Set;
|
|
19727
|
+
return {
|
|
19728
|
+
claim: (eventId) => {
|
|
19729
|
+
if (eventIds.has(eventId)) {
|
|
19730
|
+
return false;
|
|
19731
|
+
}
|
|
19732
|
+
eventIds.add(eventId);
|
|
19733
|
+
return true;
|
|
19734
|
+
},
|
|
19735
|
+
has: (eventId) => eventIds.has(eventId),
|
|
19736
|
+
set: (eventId) => {
|
|
19737
|
+
eventIds.add(eventId);
|
|
19738
|
+
}
|
|
19739
|
+
};
|
|
19740
|
+
};
|
|
19741
|
+
var normalizeTelnyxStoreIdentifierSegment = (value) => value.trim().replace(/[^a-zA-Z0-9_]+/g, "_").replace(/^_+|_+$/g, "") || "voice";
|
|
19742
|
+
var quoteTelnyxStoreIdentifier = (value) => `"${value.replace(/"/g, '""')}"`;
|
|
19743
|
+
var resolveTelnyxEventTableName = (input) => {
|
|
19744
|
+
if (input.tableName) {
|
|
19745
|
+
return normalizeTelnyxStoreIdentifierSegment(input.tableName);
|
|
19746
|
+
}
|
|
19747
|
+
return `${normalizeTelnyxStoreIdentifierSegment(input.tablePrefix ?? "voice")}_${normalizeTelnyxStoreIdentifierSegment(input.fallback)}`;
|
|
19748
|
+
};
|
|
19749
|
+
var getTelnyxEventExpiresAt = (ttlSeconds) => typeof ttlSeconds === "number" && ttlSeconds > 0 ? Date.now() + Math.ceil(ttlSeconds * 1000) : null;
|
|
19750
|
+
var createVoiceSQLiteTelnyxWebhookEventStore = (options) => {
|
|
19751
|
+
const database = options.database ?? new Database2(options.path ?? ":memory:", {
|
|
19752
|
+
create: true
|
|
19753
|
+
});
|
|
19754
|
+
const tableName = resolveTelnyxEventTableName({
|
|
19755
|
+
fallback: "telnyx_webhook_events",
|
|
19756
|
+
tableName: options.tableName,
|
|
19757
|
+
tablePrefix: options.tablePrefix
|
|
19758
|
+
});
|
|
19759
|
+
database.exec(`CREATE TABLE IF NOT EXISTS "${tableName}" (
|
|
19760
|
+
event_id TEXT PRIMARY KEY,
|
|
19761
|
+
created_at INTEGER NOT NULL,
|
|
19762
|
+
expires_at INTEGER
|
|
19763
|
+
)`);
|
|
19764
|
+
const pruneExpired = database.query(`DELETE FROM "${tableName}" WHERE expires_at IS NOT NULL AND expires_at <= ?1`);
|
|
19765
|
+
const select = database.query(`SELECT event_id FROM "${tableName}" WHERE event_id = ?1 AND (expires_at IS NULL OR expires_at > ?2) LIMIT 1`);
|
|
19766
|
+
const insert = database.query(`INSERT OR IGNORE INTO "${tableName}" (event_id, created_at, expires_at) VALUES (?1, ?2, ?3)`);
|
|
19767
|
+
const upsert = database.query(`INSERT INTO "${tableName}" (event_id, created_at, expires_at) VALUES (?1, ?2, ?3)
|
|
19768
|
+
ON CONFLICT(event_id) DO UPDATE SET expires_at = excluded.expires_at`);
|
|
19769
|
+
return {
|
|
19770
|
+
claim: (eventId) => {
|
|
19771
|
+
const now = Date.now();
|
|
19772
|
+
pruneExpired.run(now);
|
|
19773
|
+
const result = insert.run(eventId, now, getTelnyxEventExpiresAt(options.ttlSeconds));
|
|
19774
|
+
return result.changes > 0;
|
|
19775
|
+
},
|
|
19776
|
+
has: (eventId) => Boolean(select.get(eventId, Date.now())),
|
|
19777
|
+
set: (eventId) => {
|
|
19778
|
+
upsert.run(eventId, Date.now(), getTelnyxEventExpiresAt(options.ttlSeconds));
|
|
19779
|
+
}
|
|
19780
|
+
};
|
|
19781
|
+
};
|
|
19782
|
+
var createVoiceTelnyxPostgresClient = async (options) => {
|
|
19783
|
+
if (options.sql) {
|
|
19784
|
+
return options.sql;
|
|
19785
|
+
}
|
|
19786
|
+
if (!options.connectionString) {
|
|
19787
|
+
throw new Error("createVoicePostgresTelnyxWebhookEventStore requires either options.sql or options.connectionString.");
|
|
19788
|
+
}
|
|
19789
|
+
const sql = new Bun.SQL(options.connectionString);
|
|
19790
|
+
return {
|
|
19791
|
+
unsafe: sql.unsafe.bind(sql)
|
|
19792
|
+
};
|
|
19793
|
+
};
|
|
19794
|
+
var resolveTelnyxEventQualifiedTableName = (options) => {
|
|
19795
|
+
const schema = normalizeTelnyxStoreIdentifierSegment(options.schemaName ?? "public");
|
|
19796
|
+
const table = resolveTelnyxEventTableName({
|
|
19797
|
+
fallback: "telnyx_webhook_events",
|
|
19798
|
+
tableName: options.tableName,
|
|
19799
|
+
tablePrefix: options.tablePrefix
|
|
19800
|
+
});
|
|
19801
|
+
return `${quoteTelnyxStoreIdentifier(schema)}.${quoteTelnyxStoreIdentifier(table)}`;
|
|
19802
|
+
};
|
|
19803
|
+
var createVoicePostgresTelnyxWebhookEventStore = (options = {}) => {
|
|
19804
|
+
const qualifiedTableName = resolveTelnyxEventQualifiedTableName(options);
|
|
19805
|
+
const schemaMatch = qualifiedTableName.match(/^"([^"]+)"\./);
|
|
19806
|
+
const client = createVoiceTelnyxPostgresClient(options);
|
|
19807
|
+
const initialized = (async () => {
|
|
19808
|
+
const sql = await client;
|
|
19809
|
+
if (schemaMatch?.[1]) {
|
|
19810
|
+
await sql.unsafe(`CREATE SCHEMA IF NOT EXISTS ${quoteTelnyxStoreIdentifier(schemaMatch[1])}`);
|
|
19811
|
+
}
|
|
19812
|
+
await sql.unsafe(`CREATE TABLE IF NOT EXISTS ${qualifiedTableName} (
|
|
19813
|
+
event_id TEXT PRIMARY KEY,
|
|
19814
|
+
created_at BIGINT NOT NULL,
|
|
19815
|
+
expires_at BIGINT
|
|
19816
|
+
)`);
|
|
19817
|
+
})();
|
|
19818
|
+
const pruneExpired = async () => {
|
|
19819
|
+
await initialized;
|
|
19820
|
+
const sql = await client;
|
|
19821
|
+
await sql.unsafe(`DELETE FROM ${qualifiedTableName} WHERE expires_at IS NOT NULL AND expires_at <= $1`, [Date.now()]);
|
|
19822
|
+
};
|
|
19823
|
+
return {
|
|
19824
|
+
claim: async (eventId) => {
|
|
19825
|
+
await pruneExpired();
|
|
19826
|
+
const sql = await client;
|
|
19827
|
+
const rows = await sql.unsafe(`INSERT INTO ${qualifiedTableName} (event_id, created_at, expires_at)
|
|
19828
|
+
VALUES ($1, $2, $3)
|
|
19829
|
+
ON CONFLICT (event_id) DO NOTHING
|
|
19830
|
+
RETURNING event_id`, [eventId, Date.now(), getTelnyxEventExpiresAt(options.ttlSeconds)]);
|
|
19831
|
+
return rows.length > 0;
|
|
19832
|
+
},
|
|
19833
|
+
has: async (eventId) => {
|
|
19834
|
+
await initialized;
|
|
19835
|
+
const sql = await client;
|
|
19836
|
+
const rows = await sql.unsafe(`SELECT event_id FROM ${qualifiedTableName}
|
|
19837
|
+
WHERE event_id = $1 AND (expires_at IS NULL OR expires_at > $2)
|
|
19838
|
+
LIMIT 1`, [eventId, Date.now()]);
|
|
19839
|
+
return rows.length > 0;
|
|
19840
|
+
},
|
|
19841
|
+
set: async (eventId) => {
|
|
19842
|
+
await initialized;
|
|
19843
|
+
const sql = await client;
|
|
19844
|
+
await sql.unsafe(`INSERT INTO ${qualifiedTableName} (event_id, created_at, expires_at)
|
|
19845
|
+
VALUES ($1, $2, $3)
|
|
19846
|
+
ON CONFLICT (event_id) DO UPDATE SET expires_at = EXCLUDED.expires_at`, [eventId, Date.now(), getTelnyxEventExpiresAt(options.ttlSeconds)]);
|
|
19847
|
+
}
|
|
19848
|
+
};
|
|
19849
|
+
};
|
|
19850
|
+
var getTelnyxRedisEventKey = (keyPrefix, eventId) => `${keyPrefix}:${eventId}`;
|
|
19851
|
+
var createVoiceRedisTelnyxWebhookEventStore = (options = {}) => {
|
|
19852
|
+
const client = options.client ?? new Bun.RedisClient(options.url);
|
|
19853
|
+
const keyPrefix = options.keyPrefix?.trim() || "voice:telnyx-webhook-event";
|
|
19854
|
+
const ttlSeconds = options.ttlSeconds;
|
|
19855
|
+
const setEvent = async (eventId, nx) => {
|
|
19856
|
+
const key = getTelnyxRedisEventKey(keyPrefix, eventId);
|
|
19857
|
+
if (typeof ttlSeconds === "number" && ttlSeconds > 0) {
|
|
19858
|
+
return client.set(key, "1", "EX", String(Math.ceil(ttlSeconds)), ...nx ? ["NX"] : []);
|
|
19859
|
+
}
|
|
19860
|
+
return client.set(key, "1", ...nx ? ["NX"] : []);
|
|
19861
|
+
};
|
|
19862
|
+
return {
|
|
19863
|
+
claim: async (eventId) => await setEvent(eventId, true) === "OK",
|
|
19864
|
+
has: async (eventId) => Boolean(await client.exists(getTelnyxRedisEventKey(keyPrefix, eventId))),
|
|
19865
|
+
set: async (eventId) => {
|
|
19866
|
+
await setEvent(eventId, false);
|
|
19867
|
+
}
|
|
19868
|
+
};
|
|
19869
|
+
};
|
|
19870
|
+
var readTelnyxWebhookEventId = (rawBody) => {
|
|
19871
|
+
try {
|
|
19872
|
+
const body = JSON.parse(rawBody);
|
|
19873
|
+
if (!body || typeof body !== "object" || Array.isArray(body)) {
|
|
19874
|
+
return;
|
|
19875
|
+
}
|
|
19876
|
+
const record = body;
|
|
19877
|
+
const data = record.data;
|
|
19878
|
+
if (data && typeof data === "object" && !Array.isArray(data)) {
|
|
19879
|
+
const eventId2 = data.id;
|
|
19880
|
+
if (typeof eventId2 === "string" && eventId2.trim()) {
|
|
19881
|
+
return eventId2;
|
|
19882
|
+
}
|
|
19883
|
+
}
|
|
19884
|
+
const eventId = record.id ?? record.event_id;
|
|
19885
|
+
return typeof eventId === "string" && eventId.trim() ? eventId : undefined;
|
|
19886
|
+
} catch {
|
|
19887
|
+
return;
|
|
19888
|
+
}
|
|
19889
|
+
};
|
|
19890
|
+
var createVoiceTelnyxWebhookVerifier = (options) => async (input) => {
|
|
19891
|
+
const verification = await verifyVoiceTelnyxWebhookSignature({
|
|
19892
|
+
body: input.rawBody,
|
|
19893
|
+
headers: input.headers,
|
|
19894
|
+
publicKey: options.publicKey,
|
|
19895
|
+
toleranceSeconds: options.toleranceSeconds
|
|
19896
|
+
});
|
|
19897
|
+
if (!verification.ok) {
|
|
19898
|
+
return verification;
|
|
19899
|
+
}
|
|
19900
|
+
const eventStore = options.eventStore;
|
|
19901
|
+
if (!eventStore) {
|
|
19902
|
+
return verification;
|
|
19903
|
+
}
|
|
19904
|
+
const eventId = readTelnyxWebhookEventId(input.rawBody);
|
|
19905
|
+
if (!eventId) {
|
|
19906
|
+
return { ok: false, reason: "invalid-signature" };
|
|
19907
|
+
}
|
|
19908
|
+
if (eventStore.claim) {
|
|
19909
|
+
return await eventStore.claim(eventId) ? verification : { ok: false, reason: "invalid-signature" };
|
|
19910
|
+
}
|
|
19911
|
+
if (await eventStore.has(eventId)) {
|
|
19912
|
+
return { ok: false, reason: "invalid-signature" };
|
|
19913
|
+
}
|
|
19914
|
+
await eventStore.set(eventId);
|
|
19915
|
+
return verification;
|
|
19916
|
+
};
|
|
19724
19917
|
var buildTelnyxVoiceSetupStatus = async (options, input) => {
|
|
19725
19918
|
const origin = resolveRequestOrigin3(input.request);
|
|
19726
19919
|
const stream = await resolveTelnyxStreamUrl(options, input);
|
|
@@ -19854,11 +20047,10 @@ var createTelnyxVoiceRoutes = (options = {}) => {
|
|
|
19854
20047
|
const smokePath = options.smoke?.path === false ? false : options.smoke?.path ?? "/api/voice/telnyx/smoke";
|
|
19855
20048
|
const bridges = new WeakMap;
|
|
19856
20049
|
const webhookPolicy = options.webhook?.policy ?? options.outcomePolicy ?? createVoiceTelephonyOutcomePolicy();
|
|
19857
|
-
const verify = options.webhook?.verify ?? (options.webhook?.publicKey ? (
|
|
19858
|
-
|
|
19859
|
-
|
|
19860
|
-
|
|
19861
|
-
toleranceSeconds: options.webhook?.toleranceSeconds
|
|
20050
|
+
const verify = options.webhook?.verify ?? (options.webhook?.publicKey ? createVoiceTelnyxWebhookVerifier({
|
|
20051
|
+
eventStore: options.webhook.eventStore,
|
|
20052
|
+
publicKey: options.webhook.publicKey,
|
|
20053
|
+
toleranceSeconds: options.webhook.toleranceSeconds
|
|
19862
20054
|
}) : undefined);
|
|
19863
20055
|
const app = new Elysia31({
|
|
19864
20056
|
name: options.name ?? "absolutejs-voice-telnyx"
|
|
@@ -23990,7 +24182,7 @@ var createVoiceOpsRecoveryRoutes = (options = {}) => {
|
|
|
23990
24182
|
|
|
23991
24183
|
// src/observabilityExport.ts
|
|
23992
24184
|
import { Elysia as Elysia41 } from "elysia";
|
|
23993
|
-
import { Database as
|
|
24185
|
+
import { Database as Database3 } from "bun:sqlite";
|
|
23994
24186
|
import { createHash } from "crypto";
|
|
23995
24187
|
import { mkdir as mkdir4, readFile as readFile2, stat, unlink } from "fs/promises";
|
|
23996
24188
|
import { join as join3 } from "path";
|
|
@@ -25220,7 +25412,7 @@ var loadVoiceObservabilityExportReplaySource = async (source) => {
|
|
|
25220
25412
|
if (!source.database && !source.path) {
|
|
25221
25413
|
throw new Error("SQLite observability export replay requires source.database or source.path.");
|
|
25222
25414
|
}
|
|
25223
|
-
const database = source.database ?? new
|
|
25415
|
+
const database = source.database ?? new Database3(source.path, { create: false });
|
|
25224
25416
|
const table2 = quoteObservabilityIdentifier(normalizeObservabilityIdentifier(source.tableName));
|
|
25225
25417
|
const row2 = database.query(`SELECT manifest_json, artifact_index_json, payload_json FROM ${table2} WHERE run_id = $runId`).get({ $runId: source.runId });
|
|
25226
25418
|
if (!row2) {
|
|
@@ -25297,7 +25489,7 @@ var deliverObservabilityExportToSQLite = async (input) => {
|
|
|
25297
25489
|
if (!input.destination.database && !input.destination.path) {
|
|
25298
25490
|
throw new Error("SQLite observability export delivery requires destination.database or destination.path.");
|
|
25299
25491
|
}
|
|
25300
|
-
const database = input.destination.database ?? new
|
|
25492
|
+
const database = input.destination.database ?? new Database3(input.destination.path, { create: true });
|
|
25301
25493
|
const table = quoteObservabilityIdentifier(normalizeObservabilityIdentifier(input.destination.tableName));
|
|
25302
25494
|
const record = buildObservabilityExportDatabaseRecord(input);
|
|
25303
25495
|
database.exec(`CREATE TABLE IF NOT EXISTS ${table} (
|
|
@@ -29407,7 +29599,7 @@ var createVoiceTraceDeliveryRoutes = (options) => {
|
|
|
29407
29599
|
return routes;
|
|
29408
29600
|
};
|
|
29409
29601
|
// src/sqliteStore.ts
|
|
29410
|
-
import { Database as
|
|
29602
|
+
import { Database as Database4 } from "bun:sqlite";
|
|
29411
29603
|
var normalizeTableNameSegment = (value) => value.trim().replace(/[^a-zA-Z0-9_]+/g, "_").replace(/^_+|_+$/g, "") || "voice";
|
|
29412
29604
|
var resolveTableName = (input) => {
|
|
29413
29605
|
if (input.options.tableName) {
|
|
@@ -29418,7 +29610,7 @@ var resolveTableName = (input) => {
|
|
|
29418
29610
|
return `${prefix}_${fallback}`;
|
|
29419
29611
|
};
|
|
29420
29612
|
var openVoiceSQLiteDatabase = (path) => {
|
|
29421
|
-
const database = new
|
|
29613
|
+
const database = new Database4(path, {
|
|
29422
29614
|
create: true
|
|
29423
29615
|
});
|
|
29424
29616
|
database.exec("PRAGMA journal_mode = WAL;");
|
|
@@ -31472,6 +31664,139 @@ var createVoiceSTTRoutingCorrectionHandler = (mode = "generic") => {
|
|
|
31472
31664
|
}
|
|
31473
31665
|
return createPhraseHintCorrectionHandler();
|
|
31474
31666
|
};
|
|
31667
|
+
// src/telephony/security.ts
|
|
31668
|
+
var resolveVerificationUrl2 = (option, input) => typeof option === "function" ? option(input) : option ?? input.request.url;
|
|
31669
|
+
var createStores = (options) => {
|
|
31670
|
+
const ttlSeconds = options.ttlSeconds;
|
|
31671
|
+
const store = options.store ?? { kind: "memory" };
|
|
31672
|
+
if (store.kind === "sqlite") {
|
|
31673
|
+
return {
|
|
31674
|
+
idempotency: options.twilio?.idempotencyStore ?? createVoiceSQLiteTelephonyWebhookIdempotencyStore({
|
|
31675
|
+
path: store.path,
|
|
31676
|
+
tableName: "voice_twilio_webhook_idempotency",
|
|
31677
|
+
tablePrefix: store.tablePrefix
|
|
31678
|
+
}),
|
|
31679
|
+
plivo: options.plivo?.nonceStore ?? createVoiceSQLitePlivoWebhookNonceStore({
|
|
31680
|
+
path: store.path,
|
|
31681
|
+
tableName: "voice_plivo_webhook_nonces",
|
|
31682
|
+
tablePrefix: store.tablePrefix,
|
|
31683
|
+
ttlSeconds
|
|
31684
|
+
}),
|
|
31685
|
+
telnyx: options.telnyx?.eventStore ?? createVoiceSQLiteTelnyxWebhookEventStore({
|
|
31686
|
+
path: store.path,
|
|
31687
|
+
tableName: "voice_telnyx_webhook_events",
|
|
31688
|
+
tablePrefix: store.tablePrefix,
|
|
31689
|
+
ttlSeconds
|
|
31690
|
+
})
|
|
31691
|
+
};
|
|
31692
|
+
}
|
|
31693
|
+
if (store.kind === "postgres") {
|
|
31694
|
+
return {
|
|
31695
|
+
idempotency: options.twilio?.idempotencyStore ?? createVoicePostgresTelephonyWebhookIdempotencyStore({
|
|
31696
|
+
connectionString: store.connectionString,
|
|
31697
|
+
schemaName: store.schemaName,
|
|
31698
|
+
sql: store.sql,
|
|
31699
|
+
tableName: "voice_twilio_webhook_idempotency",
|
|
31700
|
+
tablePrefix: store.tablePrefix
|
|
31701
|
+
}),
|
|
31702
|
+
plivo: options.plivo?.nonceStore ?? createVoicePostgresPlivoWebhookNonceStore({
|
|
31703
|
+
connectionString: store.connectionString,
|
|
31704
|
+
schemaName: store.schemaName,
|
|
31705
|
+
sql: store.sql,
|
|
31706
|
+
tableName: "voice_plivo_webhook_nonces",
|
|
31707
|
+
tablePrefix: store.tablePrefix,
|
|
31708
|
+
ttlSeconds
|
|
31709
|
+
}),
|
|
31710
|
+
telnyx: options.telnyx?.eventStore ?? createVoicePostgresTelnyxWebhookEventStore({
|
|
31711
|
+
connectionString: store.connectionString,
|
|
31712
|
+
schemaName: store.schemaName,
|
|
31713
|
+
sql: store.sql,
|
|
31714
|
+
tableName: "voice_telnyx_webhook_events",
|
|
31715
|
+
tablePrefix: store.tablePrefix,
|
|
31716
|
+
ttlSeconds
|
|
31717
|
+
})
|
|
31718
|
+
};
|
|
31719
|
+
}
|
|
31720
|
+
if (store.kind === "redis") {
|
|
31721
|
+
const keyPrefix = store.keyPrefix?.trim() || "voice:webhook-security";
|
|
31722
|
+
return {
|
|
31723
|
+
idempotency: options.twilio?.idempotencyStore ?? createVoiceRedisTelephonyWebhookIdempotencyStore({
|
|
31724
|
+
client: store.idempotencyClient,
|
|
31725
|
+
keyPrefix: `${keyPrefix}:twilio:idempotency`,
|
|
31726
|
+
ttlSeconds,
|
|
31727
|
+
url: store.url
|
|
31728
|
+
}),
|
|
31729
|
+
plivo: options.plivo?.nonceStore ?? createVoiceRedisPlivoWebhookNonceStore({
|
|
31730
|
+
client: store.plivoClient,
|
|
31731
|
+
keyPrefix: `${keyPrefix}:plivo:nonce`,
|
|
31732
|
+
ttlSeconds,
|
|
31733
|
+
url: store.url
|
|
31734
|
+
}),
|
|
31735
|
+
telnyx: options.telnyx?.eventStore ?? createVoiceRedisTelnyxWebhookEventStore({
|
|
31736
|
+
client: store.telnyxClient,
|
|
31737
|
+
keyPrefix: `${keyPrefix}:telnyx:event`,
|
|
31738
|
+
ttlSeconds,
|
|
31739
|
+
url: store.url
|
|
31740
|
+
})
|
|
31741
|
+
};
|
|
31742
|
+
}
|
|
31743
|
+
return {
|
|
31744
|
+
idempotency: options.twilio?.idempotencyStore ?? createMemoryVoiceTelephonyWebhookIdempotencyStore(),
|
|
31745
|
+
plivo: options.plivo?.nonceStore ?? createMemoryVoicePlivoWebhookNonceStore(),
|
|
31746
|
+
telnyx: options.telnyx?.eventStore ?? createMemoryVoiceTelnyxWebhookEventStore()
|
|
31747
|
+
};
|
|
31748
|
+
};
|
|
31749
|
+
var createVoiceTelephonyWebhookSecurityPreset = (options = {}) => {
|
|
31750
|
+
const stores = createStores(options);
|
|
31751
|
+
const twilioVerificationUrl = options.twilio?.verificationUrl;
|
|
31752
|
+
const plivoVerify = createVoicePlivoWebhookVerifier({
|
|
31753
|
+
authToken: options.plivo?.authToken,
|
|
31754
|
+
nonceStore: stores.plivo,
|
|
31755
|
+
verificationUrl: options.plivo?.verificationUrl
|
|
31756
|
+
});
|
|
31757
|
+
const telnyxVerify = createVoiceTelnyxWebhookVerifier({
|
|
31758
|
+
eventStore: stores.telnyx,
|
|
31759
|
+
publicKey: options.telnyx?.publicKey,
|
|
31760
|
+
toleranceSeconds: options.telnyx?.toleranceSeconds
|
|
31761
|
+
});
|
|
31762
|
+
const twilioVerify = async (input) => verifyVoiceTwilioWebhookSignature({
|
|
31763
|
+
authToken: options.twilio?.authToken,
|
|
31764
|
+
body: input.body,
|
|
31765
|
+
headers: input.headers,
|
|
31766
|
+
url: resolveVerificationUrl2(twilioVerificationUrl, {
|
|
31767
|
+
query: input.query,
|
|
31768
|
+
request: input.request
|
|
31769
|
+
})
|
|
31770
|
+
});
|
|
31771
|
+
return {
|
|
31772
|
+
plivo: {
|
|
31773
|
+
authToken: options.plivo?.authToken,
|
|
31774
|
+
nonceStore: stores.plivo,
|
|
31775
|
+
verify: plivoVerify
|
|
31776
|
+
},
|
|
31777
|
+
telnyx: {
|
|
31778
|
+
eventStore: stores.telnyx,
|
|
31779
|
+
publicKey: options.telnyx?.publicKey,
|
|
31780
|
+
toleranceSeconds: options.telnyx?.toleranceSeconds,
|
|
31781
|
+
verify: telnyxVerify
|
|
31782
|
+
},
|
|
31783
|
+
twilio: {
|
|
31784
|
+
idempotency: {
|
|
31785
|
+
enabled: true,
|
|
31786
|
+
store: stores.idempotency
|
|
31787
|
+
},
|
|
31788
|
+
requireVerification: true,
|
|
31789
|
+
signingSecret: options.twilio?.authToken,
|
|
31790
|
+
verificationUrl: twilioVerificationUrl,
|
|
31791
|
+
verify: twilioVerify
|
|
31792
|
+
},
|
|
31793
|
+
verify: {
|
|
31794
|
+
plivo: plivoVerify,
|
|
31795
|
+
telnyx: telnyxVerify,
|
|
31796
|
+
twilio: twilioVerify
|
|
31797
|
+
}
|
|
31798
|
+
};
|
|
31799
|
+
};
|
|
31475
31800
|
// src/telephony/response.ts
|
|
31476
31801
|
var normalizeWhitespace = (value) => value.replace(/\s+/g, " ").trim();
|
|
31477
31802
|
var DEFAULT_MAX_WORDS = 12;
|
|
@@ -31780,7 +32105,9 @@ export {
|
|
|
31780
32105
|
createVoiceToolContractJSONHandler,
|
|
31781
32106
|
createVoiceToolContractHTMLHandler,
|
|
31782
32107
|
createVoiceToolContract,
|
|
32108
|
+
createVoiceTelnyxWebhookVerifier,
|
|
31783
32109
|
createVoiceTelnyxCampaignDialer,
|
|
32110
|
+
createVoiceTelephonyWebhookSecurityPreset,
|
|
31784
32111
|
createVoiceTelephonyWebhookRoutes,
|
|
31785
32112
|
createVoiceTelephonyWebhookHandler,
|
|
31786
32113
|
createVoiceTelephonyOutcomePolicy,
|
|
@@ -31803,6 +32130,7 @@ export {
|
|
|
31803
32130
|
createVoiceSTTProviderRouter,
|
|
31804
32131
|
createVoiceSQLiteTraceSinkDeliveryStore,
|
|
31805
32132
|
createVoiceSQLiteTraceEventStore,
|
|
32133
|
+
createVoiceSQLiteTelnyxWebhookEventStore,
|
|
31806
32134
|
createVoiceSQLiteTelephonyWebhookIdempotencyStore,
|
|
31807
32135
|
createVoiceSQLiteTaskStore,
|
|
31808
32136
|
createVoiceSQLiteSessionStore,
|
|
@@ -31820,6 +32148,7 @@ export {
|
|
|
31820
32148
|
createVoiceRoutingDecisionSummary,
|
|
31821
32149
|
createVoiceReviewSavedEvent,
|
|
31822
32150
|
createVoiceResilienceRoutes,
|
|
32151
|
+
createVoiceRedisTelnyxWebhookEventStore,
|
|
31823
32152
|
createVoiceRedisTelephonyWebhookIdempotencyStore,
|
|
31824
32153
|
createVoiceRedisTaskLeaseCoordinator,
|
|
31825
32154
|
createVoiceRedisPlivoWebhookNonceStore,
|
|
@@ -31843,6 +32172,7 @@ export {
|
|
|
31843
32172
|
createVoiceProductionReadinessRoutes,
|
|
31844
32173
|
createVoicePostgresTraceSinkDeliveryStore,
|
|
31845
32174
|
createVoicePostgresTraceEventStore,
|
|
32175
|
+
createVoicePostgresTelnyxWebhookEventStore,
|
|
31846
32176
|
createVoicePostgresTelephonyWebhookIdempotencyStore,
|
|
31847
32177
|
createVoicePostgresTaskStore,
|
|
31848
32178
|
createVoicePostgresSessionStore,
|
|
@@ -31998,6 +32328,7 @@ export {
|
|
|
31998
32328
|
createOpenAIVoiceTTS,
|
|
31999
32329
|
createOpenAIVoiceAssistantModel,
|
|
32000
32330
|
createOpenAIRealtimeAdapter,
|
|
32331
|
+
createMemoryVoiceTelnyxWebhookEventStore,
|
|
32001
32332
|
createMemoryVoiceTelephonyWebhookIdempotencyStore,
|
|
32002
32333
|
createMemoryVoicePlivoWebhookNonceStore,
|
|
32003
32334
|
createJSONVoiceAssistantModel,
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { type VoiceTelephonyWebhookIdempotencyStore, type VoiceTelephonyWebhookVerificationResult } from '../telephonyOutcome';
|
|
2
|
+
import { type VoicePostgresClient } from '../postgresStore';
|
|
3
|
+
import { type VoiceRedisTelephonyWebhookIdempotencyClient } from '../queue';
|
|
4
|
+
import { type VoicePlivoWebhookNonceStore, type VoiceRedisPlivoWebhookNonceClient } from './plivo';
|
|
5
|
+
import { type VoiceRedisTelnyxWebhookEventClient, type VoiceTelnyxWebhookEventStore } from './telnyx';
|
|
6
|
+
export type VoiceTelephonyWebhookSecurityStorePreset = {
|
|
7
|
+
kind?: 'memory';
|
|
8
|
+
} | {
|
|
9
|
+
kind: 'sqlite';
|
|
10
|
+
path: string;
|
|
11
|
+
tablePrefix?: string;
|
|
12
|
+
} | {
|
|
13
|
+
connectionString?: string;
|
|
14
|
+
kind: 'postgres';
|
|
15
|
+
schemaName?: string;
|
|
16
|
+
sql?: VoicePostgresClient;
|
|
17
|
+
tablePrefix?: string;
|
|
18
|
+
} | {
|
|
19
|
+
idempotencyClient?: VoiceRedisTelephonyWebhookIdempotencyClient;
|
|
20
|
+
keyPrefix?: string;
|
|
21
|
+
kind: 'redis';
|
|
22
|
+
plivoClient?: VoiceRedisPlivoWebhookNonceClient;
|
|
23
|
+
telnyxClient?: VoiceRedisTelnyxWebhookEventClient;
|
|
24
|
+
url?: string;
|
|
25
|
+
};
|
|
26
|
+
export type VoiceTelephonyWebhookSecurityOptions<TResult = unknown> = {
|
|
27
|
+
plivo?: {
|
|
28
|
+
authToken?: string;
|
|
29
|
+
nonceStore?: VoicePlivoWebhookNonceStore;
|
|
30
|
+
verificationUrl?: string | ((input: {
|
|
31
|
+
query: Record<string, unknown>;
|
|
32
|
+
request: Request;
|
|
33
|
+
}) => string);
|
|
34
|
+
};
|
|
35
|
+
store?: VoiceTelephonyWebhookSecurityStorePreset;
|
|
36
|
+
telnyx?: {
|
|
37
|
+
eventStore?: VoiceTelnyxWebhookEventStore;
|
|
38
|
+
publicKey?: string;
|
|
39
|
+
toleranceSeconds?: number;
|
|
40
|
+
};
|
|
41
|
+
ttlSeconds?: number;
|
|
42
|
+
twilio?: {
|
|
43
|
+
authToken?: string;
|
|
44
|
+
idempotencyStore?: VoiceTelephonyWebhookIdempotencyStore<TResult>;
|
|
45
|
+
verificationUrl?: string | ((input: {
|
|
46
|
+
query: Record<string, unknown>;
|
|
47
|
+
request: Request;
|
|
48
|
+
}) => string);
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
export type VoiceTelephonyWebhookSecurityPreset<TResult = unknown> = {
|
|
52
|
+
plivo: {
|
|
53
|
+
authToken?: string;
|
|
54
|
+
nonceStore: VoicePlivoWebhookNonceStore;
|
|
55
|
+
verify: (input: {
|
|
56
|
+
body: unknown;
|
|
57
|
+
headers: Headers;
|
|
58
|
+
query: Record<string, unknown>;
|
|
59
|
+
request: Request;
|
|
60
|
+
}) => Promise<VoiceTelephonyWebhookVerificationResult>;
|
|
61
|
+
};
|
|
62
|
+
telnyx: {
|
|
63
|
+
eventStore: VoiceTelnyxWebhookEventStore;
|
|
64
|
+
publicKey?: string;
|
|
65
|
+
toleranceSeconds?: number;
|
|
66
|
+
verify: (input: {
|
|
67
|
+
headers: Headers;
|
|
68
|
+
rawBody: string;
|
|
69
|
+
}) => Promise<VoiceTelephonyWebhookVerificationResult>;
|
|
70
|
+
};
|
|
71
|
+
twilio: {
|
|
72
|
+
idempotency: {
|
|
73
|
+
enabled: true;
|
|
74
|
+
store: VoiceTelephonyWebhookIdempotencyStore<TResult>;
|
|
75
|
+
};
|
|
76
|
+
requireVerification: true;
|
|
77
|
+
signingSecret?: string;
|
|
78
|
+
verificationUrl?: string | ((input: {
|
|
79
|
+
query: Record<string, unknown>;
|
|
80
|
+
request: Request;
|
|
81
|
+
}) => string);
|
|
82
|
+
verify: (input: {
|
|
83
|
+
body: unknown;
|
|
84
|
+
headers: Headers;
|
|
85
|
+
query: Record<string, unknown>;
|
|
86
|
+
request: Request;
|
|
87
|
+
}) => Promise<VoiceTelephonyWebhookVerificationResult>;
|
|
88
|
+
};
|
|
89
|
+
verify: {
|
|
90
|
+
plivo: VoiceTelephonyWebhookSecurityPreset<TResult>['plivo']['verify'];
|
|
91
|
+
telnyx: VoiceTelephonyWebhookSecurityPreset<TResult>['telnyx']['verify'];
|
|
92
|
+
twilio: VoiceTelephonyWebhookSecurityPreset<TResult>['twilio']['verify'];
|
|
93
|
+
};
|
|
94
|
+
};
|
|
95
|
+
export declare const createVoiceTelephonyWebhookSecurityPreset: <TResult = unknown>(options?: VoiceTelephonyWebhookSecurityOptions<TResult>) => VoiceTelephonyWebhookSecurityPreset<TResult>;
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
import { Database } from 'bun:sqlite';
|
|
2
|
+
import type { RedisClient } from 'bun';
|
|
1
3
|
import { Elysia } from 'elysia';
|
|
2
4
|
import { type VoiceTelephonyContractReport, type VoiceTelephonySetupStatus, type VoiceTelephonySmokeCheck, type VoiceTelephonySmokeReport } from './contract';
|
|
3
5
|
import { type VoiceTelephonyOutcomePolicy, type VoiceTelephonyWebhookRoutesOptions, type VoiceTelephonyWebhookVerificationResult } from '../telephonyOutcome';
|
|
4
6
|
import type { VoiceServerMessage, VoiceSessionRecord } from '../types';
|
|
5
7
|
import { type TwilioMediaStreamBridgeOptions } from './twilio';
|
|
8
|
+
import type { VoicePostgresClient } from '../postgresStore';
|
|
6
9
|
export type TelnyxMediaPayload = {
|
|
7
10
|
chunk?: string;
|
|
8
11
|
payload: string;
|
|
@@ -151,12 +154,45 @@ export type TelnyxVoiceRoutesOptions<TContext = unknown, TSession extends VoiceS
|
|
|
151
154
|
}) => Promise<string> | string);
|
|
152
155
|
};
|
|
153
156
|
webhook?: Omit<VoiceTelephonyWebhookRoutesOptions<TContext, TSession, TResult>, 'context' | 'path' | 'policy' | 'provider'> & {
|
|
157
|
+
eventStore?: VoiceTelnyxWebhookEventStore;
|
|
154
158
|
path?: string;
|
|
155
159
|
policy?: VoiceTelephonyOutcomePolicy;
|
|
156
160
|
publicKey?: string;
|
|
157
161
|
toleranceSeconds?: number;
|
|
158
162
|
};
|
|
159
163
|
};
|
|
164
|
+
export type VoiceTelnyxWebhookEventStore = {
|
|
165
|
+
claim?: (eventId: string) => Promise<boolean> | boolean;
|
|
166
|
+
has: (eventId: string) => Promise<boolean> | boolean;
|
|
167
|
+
set: (eventId: string) => Promise<void> | void;
|
|
168
|
+
};
|
|
169
|
+
export type VoiceTelnyxWebhookEventStoreOptions = {
|
|
170
|
+
ttlSeconds?: number;
|
|
171
|
+
};
|
|
172
|
+
export type VoiceSQLiteTelnyxWebhookEventStoreOptions = VoiceTelnyxWebhookEventStoreOptions & {
|
|
173
|
+
database?: Database;
|
|
174
|
+
path?: string;
|
|
175
|
+
tableName?: string;
|
|
176
|
+
tablePrefix?: string;
|
|
177
|
+
};
|
|
178
|
+
export type VoicePostgresTelnyxWebhookEventStoreOptions = VoiceTelnyxWebhookEventStoreOptions & {
|
|
179
|
+
connectionString?: string;
|
|
180
|
+
schemaName?: string;
|
|
181
|
+
sql?: VoicePostgresClient;
|
|
182
|
+
tableName?: string;
|
|
183
|
+
tablePrefix?: string;
|
|
184
|
+
};
|
|
185
|
+
export type VoiceRedisTelnyxWebhookEventClient = Pick<RedisClient, 'exists' | 'set'>;
|
|
186
|
+
export type VoiceRedisTelnyxWebhookEventStoreOptions = VoiceTelnyxWebhookEventStoreOptions & {
|
|
187
|
+
client?: VoiceRedisTelnyxWebhookEventClient;
|
|
188
|
+
keyPrefix?: string;
|
|
189
|
+
url?: string;
|
|
190
|
+
};
|
|
191
|
+
export type VoiceTelnyxWebhookVerifierOptions = {
|
|
192
|
+
eventStore?: VoiceTelnyxWebhookEventStore;
|
|
193
|
+
publicKey?: string;
|
|
194
|
+
toleranceSeconds?: number;
|
|
195
|
+
};
|
|
160
196
|
export declare const createTelnyxVoiceResponse: (options: TelnyxVoiceResponseOptions) => string;
|
|
161
197
|
export declare const createTelnyxMediaStreamBridge: <TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TResult = unknown>(socket: TelnyxMediaStreamSocket, options: TelnyxMediaStreamBridgeOptions<TContext, TSession, TResult>) => TelnyxMediaStreamBridge;
|
|
162
198
|
export declare const verifyVoiceTelnyxWebhookSignature: (input: {
|
|
@@ -165,6 +201,14 @@ export declare const verifyVoiceTelnyxWebhookSignature: (input: {
|
|
|
165
201
|
publicKey?: string;
|
|
166
202
|
toleranceSeconds?: number;
|
|
167
203
|
}) => Promise<VoiceTelephonyWebhookVerificationResult>;
|
|
204
|
+
export declare const createMemoryVoiceTelnyxWebhookEventStore: () => VoiceTelnyxWebhookEventStore;
|
|
205
|
+
export declare const createVoiceSQLiteTelnyxWebhookEventStore: (options: VoiceSQLiteTelnyxWebhookEventStoreOptions) => VoiceTelnyxWebhookEventStore;
|
|
206
|
+
export declare const createVoicePostgresTelnyxWebhookEventStore: (options?: VoicePostgresTelnyxWebhookEventStoreOptions) => VoiceTelnyxWebhookEventStore;
|
|
207
|
+
export declare const createVoiceRedisTelnyxWebhookEventStore: (options?: VoiceRedisTelnyxWebhookEventStoreOptions) => VoiceTelnyxWebhookEventStore;
|
|
208
|
+
export declare const createVoiceTelnyxWebhookVerifier: (options: VoiceTelnyxWebhookVerifierOptions) => (input: {
|
|
209
|
+
rawBody: string;
|
|
210
|
+
headers: Headers;
|
|
211
|
+
}) => Promise<VoiceTelephonyWebhookVerificationResult>;
|
|
168
212
|
export declare const createTelnyxVoiceRoutes: <TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TResult = unknown>(options?: TelnyxVoiceRoutesOptions<TContext, TSession, TResult>) => Elysia<"", {
|
|
169
213
|
decorator: {};
|
|
170
214
|
store: {};
|