@rstreamlabs/tunnels 3.8.1 → 3.8.3
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/README.md +7 -2
- package/dist/index.d.mts +240 -224
- package/dist/index.d.ts +240 -224
- package/dist/index.js +160 -45
- package/dist/index.mjs +156 -41
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1766,15 +1766,61 @@ var RstreamTunnelsResource = class {
|
|
|
1766
1766
|
};
|
|
1767
1767
|
|
|
1768
1768
|
// src/tunnels.ts
|
|
1769
|
-
var import_rstream11 = require("@rstreamlabs/rstream");
|
|
1770
1769
|
var import_rstream12 = require("@rstreamlabs/rstream");
|
|
1771
1770
|
var import_rstream13 = require("@rstreamlabs/rstream");
|
|
1771
|
+
var import_rstream14 = require("@rstreamlabs/rstream");
|
|
1772
1772
|
|
|
1773
1773
|
// src/turn.ts
|
|
1774
1774
|
var import_rstream8 = require("@rstreamlabs/rstream");
|
|
1775
1775
|
var import_rstream9 = require("@rstreamlabs/rstream");
|
|
1776
1776
|
var import_rstream10 = require("@rstreamlabs/rstream");
|
|
1777
1777
|
var import_turn = require("@rstreamlabs/rstream/turn");
|
|
1778
|
+
|
|
1779
|
+
// src/control-plane-fetch.ts
|
|
1780
|
+
function createRequestLifetime(parent, timeoutMilliseconds) {
|
|
1781
|
+
const controller = new AbortController();
|
|
1782
|
+
const abort = () => controller.abort(parent.reason);
|
|
1783
|
+
if (parent.aborted) {
|
|
1784
|
+
abort();
|
|
1785
|
+
} else {
|
|
1786
|
+
parent.addEventListener("abort", abort, { once: true });
|
|
1787
|
+
}
|
|
1788
|
+
const timeout = setTimeout(
|
|
1789
|
+
() => controller.abort(new Error("Control plane request timed out.")),
|
|
1790
|
+
timeoutMilliseconds
|
|
1791
|
+
);
|
|
1792
|
+
return {
|
|
1793
|
+
close: () => {
|
|
1794
|
+
clearTimeout(timeout);
|
|
1795
|
+
parent.removeEventListener("abort", abort);
|
|
1796
|
+
},
|
|
1797
|
+
signal: controller.signal
|
|
1798
|
+
};
|
|
1799
|
+
}
|
|
1800
|
+
function createBoundedControlPlaneFetch(timeoutMilliseconds) {
|
|
1801
|
+
return async (input, init) => {
|
|
1802
|
+
const request = new Request(input, init);
|
|
1803
|
+
const headers = new Headers(request.headers);
|
|
1804
|
+
headers.set("Connection", "close");
|
|
1805
|
+
const lifetime = createRequestLifetime(request.signal, timeoutMilliseconds);
|
|
1806
|
+
try {
|
|
1807
|
+
const response = await globalThis.fetch(request, {
|
|
1808
|
+
headers,
|
|
1809
|
+
signal: lifetime.signal
|
|
1810
|
+
});
|
|
1811
|
+
const responseBody = response.body === null ? null : new Uint8Array(await response.arrayBuffer());
|
|
1812
|
+
return new Response(responseBody, {
|
|
1813
|
+
headers: Object.fromEntries(response.headers.entries()),
|
|
1814
|
+
status: response.status,
|
|
1815
|
+
statusText: response.statusText
|
|
1816
|
+
});
|
|
1817
|
+
} finally {
|
|
1818
|
+
lifetime.close();
|
|
1819
|
+
}
|
|
1820
|
+
};
|
|
1821
|
+
}
|
|
1822
|
+
|
|
1823
|
+
// src/turn.ts
|
|
1778
1824
|
var z8 = __toESM(require("zod"));
|
|
1779
1825
|
var import_crypto = __toESM(require("crypto"));
|
|
1780
1826
|
var defaultTURNPort = 3478;
|
|
@@ -1782,6 +1828,8 @@ var defaultTURNSPort = 5349;
|
|
|
1782
1828
|
var defaultTURNCredentialTTLSeconds = 10 * 60;
|
|
1783
1829
|
var maxTURNCredentialTTLSeconds = 60 * 60;
|
|
1784
1830
|
var maxTURNKeyringBytes = 8 * 1024;
|
|
1831
|
+
var defaultAPIRequestTimeoutMilliseconds = 1e4;
|
|
1832
|
+
var maxAPIRequestTimeoutMilliseconds = 6e4;
|
|
1785
1833
|
var turnTokenClaimsSchema = z8.object({
|
|
1786
1834
|
exp: z8.number().int().optional(),
|
|
1787
1835
|
iat: z8.number().int().optional(),
|
|
@@ -1815,6 +1863,15 @@ function normalizeTTLSeconds(ttlSeconds) {
|
|
|
1815
1863
|
}
|
|
1816
1864
|
return ttl;
|
|
1817
1865
|
}
|
|
1866
|
+
function normalizeAPIRequestTimeoutMilliseconds(timeoutMilliseconds) {
|
|
1867
|
+
const timeout = timeoutMilliseconds ?? defaultAPIRequestTimeoutMilliseconds;
|
|
1868
|
+
if (!Number.isInteger(timeout) || timeout < 1 || timeout > maxAPIRequestTimeoutMilliseconds) {
|
|
1869
|
+
throw new Error(
|
|
1870
|
+
"TURN API request timeout must be an integer between 1 and 60000 milliseconds."
|
|
1871
|
+
);
|
|
1872
|
+
}
|
|
1873
|
+
return timeout;
|
|
1874
|
+
}
|
|
1818
1875
|
function createAPITURNCredentialsParams(ttlSeconds) {
|
|
1819
1876
|
return ttlSeconds === void 0 ? {} : { ttlSeconds: normalizeTTLSeconds(ttlSeconds) };
|
|
1820
1877
|
}
|
|
@@ -1831,14 +1888,14 @@ function normalizeTURNPort(port) {
|
|
|
1831
1888
|
function normalizeTURNSPort(port) {
|
|
1832
1889
|
return normalizePort(port, defaultTURNSPort, "TURNS port");
|
|
1833
1890
|
}
|
|
1834
|
-
function createTURNURLs(
|
|
1891
|
+
function createTURNURLs(turnDomain, turnPort, turnsPort) {
|
|
1835
1892
|
const normalizedTURNPort = normalizeTURNPort(turnPort);
|
|
1836
1893
|
const normalizedTURNSPort = normalizeTURNSPort(turnsPort);
|
|
1837
1894
|
return [
|
|
1838
|
-
`turn:${
|
|
1839
|
-
`turn:${
|
|
1840
|
-
`turns:${
|
|
1841
|
-
`turns:${
|
|
1895
|
+
`turn:${turnDomain}:${normalizedTURNPort}?transport=udp`,
|
|
1896
|
+
`turn:${turnDomain}:${normalizedTURNPort}?transport=tcp`,
|
|
1897
|
+
`turns:${turnDomain}:${normalizedTURNSPort}?transport=udp`,
|
|
1898
|
+
`turns:${turnDomain}:${normalizedTURNSPort}?transport=tcp`
|
|
1842
1899
|
];
|
|
1843
1900
|
}
|
|
1844
1901
|
function parseTURNTokenClaims(token) {
|
|
@@ -2008,11 +2065,16 @@ async function createAPITURNCredentials(options) {
|
|
|
2008
2065
|
"Project ID or project endpoint is required for TURN API mode."
|
|
2009
2066
|
);
|
|
2010
2067
|
}
|
|
2068
|
+
const requestTimeoutMilliseconds = normalizeAPIRequestTimeoutMilliseconds(
|
|
2069
|
+
options.requestTimeoutMilliseconds
|
|
2070
|
+
);
|
|
2071
|
+
const params = createAPITURNCredentialsParams(options.ttlSeconds);
|
|
2072
|
+
const request = options.fetch ?? createBoundedControlPlaneFetch(requestTimeoutMilliseconds);
|
|
2011
2073
|
const client = new import_rstream10.RstreamClient({
|
|
2012
2074
|
apiUrl: options.apiUrl,
|
|
2013
|
-
credentials: options.credentials
|
|
2075
|
+
credentials: options.credentials,
|
|
2076
|
+
fetch: request
|
|
2014
2077
|
});
|
|
2015
|
-
const params = createAPITURNCredentialsParams(options.ttlSeconds);
|
|
2016
2078
|
if (projectId) {
|
|
2017
2079
|
return await client.tunnels.projects.createTurnCredentials(
|
|
2018
2080
|
projectId,
|
|
@@ -2030,9 +2092,14 @@ async function createAPITURNCredentials(options) {
|
|
|
2030
2092
|
);
|
|
2031
2093
|
}
|
|
2032
2094
|
function createPATTURNCredentials(options) {
|
|
2033
|
-
const
|
|
2034
|
-
|
|
2035
|
-
|
|
2095
|
+
const legacyDomain = normalizeClusterDomain(options.clusterDomain);
|
|
2096
|
+
const turnDomain = normalizeClusterDomain(options.turnDomain) ?? legacyDomain;
|
|
2097
|
+
const turnRealm = normalizeClusterDomain(options.turnRealm) ?? legacyDomain;
|
|
2098
|
+
if (!turnDomain) {
|
|
2099
|
+
throw new Error("TURN domain is required for TURN PAT mode.");
|
|
2100
|
+
}
|
|
2101
|
+
if (!turnRealm) {
|
|
2102
|
+
throw new Error("TURN realm is required for TURN PAT mode.");
|
|
2036
2103
|
}
|
|
2037
2104
|
const projectEndpoint = normalizeOptionalString2(options.projectEndpoint);
|
|
2038
2105
|
if (!projectEndpoint) {
|
|
@@ -2046,12 +2113,19 @@ function createPATTURNCredentials(options) {
|
|
|
2046
2113
|
if (claims.type !== "pat") {
|
|
2047
2114
|
throw new Error("TURN PAT mode requires a PAT token.");
|
|
2048
2115
|
}
|
|
2049
|
-
const
|
|
2116
|
+
const claimsTokenEndpoint = normalizeOptionalString2(
|
|
2117
|
+
claims.token_endpoint ?? claims.tokendpoint
|
|
2118
|
+
);
|
|
2119
|
+
const configuredTokenEndpoint = normalizeOptionalString2(
|
|
2120
|
+
options.tokenEndpoint
|
|
2121
|
+
);
|
|
2122
|
+
const tokenEndpoint = configuredTokenEndpoint ?? claimsTokenEndpoint;
|
|
2050
2123
|
if (!tokenEndpoint) {
|
|
2051
|
-
throw new Error(
|
|
2124
|
+
throw new Error(
|
|
2125
|
+
"TURN PAT mode requires a PAT token carrying a token endpoint."
|
|
2126
|
+
);
|
|
2052
2127
|
}
|
|
2053
|
-
|
|
2054
|
-
if (claimsTokenEndpoint !== void 0 && claimsTokenEndpoint !== tokenEndpoint) {
|
|
2128
|
+
if (configuredTokenEndpoint !== void 0 && claimsTokenEndpoint !== void 0 && claimsTokenEndpoint !== configuredTokenEndpoint) {
|
|
2055
2129
|
throw new Error("Token endpoint does not match the PAT token.");
|
|
2056
2130
|
}
|
|
2057
2131
|
const now = normalizeNow(options.now);
|
|
@@ -2064,7 +2138,7 @@ function createPATTURNCredentials(options) {
|
|
|
2064
2138
|
import_crypto.default.hkdfSync(
|
|
2065
2139
|
"sha256",
|
|
2066
2140
|
tokenHash,
|
|
2067
|
-
Buffer.from(
|
|
2141
|
+
Buffer.from(turnRealm, "utf8"),
|
|
2068
2142
|
Buffer.from("turn-pat-v1", "utf8"),
|
|
2069
2143
|
32
|
|
2070
2144
|
)
|
|
@@ -2073,14 +2147,19 @@ function createPATTURNCredentials(options) {
|
|
|
2073
2147
|
return import_turn.turnCredentialsSchema.parse({
|
|
2074
2148
|
credential,
|
|
2075
2149
|
ttl,
|
|
2076
|
-
urls: createTURNURLs(
|
|
2150
|
+
urls: createTURNURLs(turnDomain, options.turnPort, options.turnsPort),
|
|
2077
2151
|
username
|
|
2078
2152
|
});
|
|
2079
2153
|
}
|
|
2080
2154
|
async function createAPPTURNCredentials(options) {
|
|
2081
|
-
const
|
|
2082
|
-
|
|
2083
|
-
|
|
2155
|
+
const legacyDomain = normalizeClusterDomain(options.clusterDomain);
|
|
2156
|
+
const turnDomain = normalizeClusterDomain(options.turnDomain) ?? legacyDomain;
|
|
2157
|
+
const turnRealm = normalizeClusterDomain(options.turnRealm) ?? legacyDomain;
|
|
2158
|
+
if (!turnDomain) {
|
|
2159
|
+
throw new Error("TURN domain is required for TURN APP mode.");
|
|
2160
|
+
}
|
|
2161
|
+
if (!turnRealm) {
|
|
2162
|
+
throw new Error("TURN realm is required for TURN APP mode.");
|
|
2084
2163
|
}
|
|
2085
2164
|
const projectEndpoint = normalizeOptionalString2(options.projectEndpoint);
|
|
2086
2165
|
if (!projectEndpoint) {
|
|
@@ -2098,7 +2177,7 @@ async function createAPPTURNCredentials(options) {
|
|
|
2098
2177
|
const exp = normalizeNow(options.now) + ttlSeconds;
|
|
2099
2178
|
const username = `v1:${exp}:app:${projectEndpoint}:${clientId}`;
|
|
2100
2179
|
const clientPrivateKey = parseAPPPrivateKey(clientSecret);
|
|
2101
|
-
const serverPublicKeyHex = normalizeOptionalString2(options.serverPublicKeyHex) ?? await loadTURNServerPublicKeyHex(
|
|
2180
|
+
const serverPublicKeyHex = normalizeOptionalString2(options.serverPublicKeyHex) ?? await loadTURNServerPublicKeyHex(turnRealm, options);
|
|
2102
2181
|
const serverPublicKey = parseTURNServerPublicKeyHex(serverPublicKeyHex);
|
|
2103
2182
|
requireMatchingCurve(clientPrivateKey, serverPublicKey);
|
|
2104
2183
|
const sharedSecret = import_crypto.default.diffieHellman({
|
|
@@ -2109,7 +2188,7 @@ async function createAPPTURNCredentials(options) {
|
|
|
2109
2188
|
import_crypto.default.hkdfSync(
|
|
2110
2189
|
"sha256",
|
|
2111
2190
|
sharedSecret,
|
|
2112
|
-
Buffer.from(
|
|
2191
|
+
Buffer.from(turnRealm, "utf8"),
|
|
2113
2192
|
Buffer.from("turn-app-v1", "utf8"),
|
|
2114
2193
|
32
|
|
2115
2194
|
)
|
|
@@ -2118,7 +2197,7 @@ async function createAPPTURNCredentials(options) {
|
|
|
2118
2197
|
return import_turn.turnCredentialsSchema.parse({
|
|
2119
2198
|
credential,
|
|
2120
2199
|
ttl: ttlSeconds,
|
|
2121
|
-
urls: createTURNURLs(
|
|
2200
|
+
urls: createTURNURLs(turnDomain, options.turnPort, options.turnsPort),
|
|
2122
2201
|
username
|
|
2123
2202
|
});
|
|
2124
2203
|
}
|
|
@@ -2136,33 +2215,38 @@ async function createTURNCredentials(options) {
|
|
|
2136
2215
|
return await createAPITURNCredentials({
|
|
2137
2216
|
apiUrl: options.apiUrl,
|
|
2138
2217
|
credentials: controlPlaneCredentials,
|
|
2218
|
+
fetch: options.fetch,
|
|
2139
2219
|
projectEndpoint,
|
|
2140
2220
|
projectId: options.projectId,
|
|
2221
|
+
requestTimeoutMilliseconds: options.requestTimeoutMilliseconds,
|
|
2141
2222
|
ttlSeconds: options.ttlSeconds
|
|
2142
2223
|
});
|
|
2143
2224
|
}
|
|
2144
|
-
const
|
|
2225
|
+
const legacyDomain = normalizeClusterDomain(options.clusterDomain);
|
|
2226
|
+
const turnDomain = normalizeClusterDomain(options.turnDomain) ?? legacyDomain ?? (projectEndpoint && options.engine ? deriveClusterDomainFromEngine(projectEndpoint, options.engine) : void 0);
|
|
2227
|
+
const turnRealm = normalizeClusterDomain(options.turnRealm) ?? legacyDomain;
|
|
2145
2228
|
if (mode === "pat") {
|
|
2146
2229
|
if (!(0, import_rstream9.isTokenCredentials)(credentials)) {
|
|
2147
2230
|
throw new Error("A PAT token is required for TURN PAT mode.");
|
|
2148
2231
|
}
|
|
2149
2232
|
return createPATTURNCredentials({
|
|
2150
|
-
clusterDomain: requireOption(
|
|
2151
|
-
clusterDomain,
|
|
2152
|
-
"Cluster domain is required for TURN PAT mode."
|
|
2153
|
-
),
|
|
2154
2233
|
now: options.now,
|
|
2155
2234
|
projectEndpoint: requireOption(
|
|
2156
2235
|
projectEndpoint,
|
|
2157
2236
|
"Project endpoint is required for TURN PAT mode."
|
|
2158
2237
|
),
|
|
2159
2238
|
token: credentials.token,
|
|
2160
|
-
tokenEndpoint:
|
|
2161
|
-
normalizeOptionalString2(options.tokenEndpoint),
|
|
2162
|
-
"Token endpoint is required for TURN PAT mode."
|
|
2163
|
-
),
|
|
2239
|
+
tokenEndpoint: options.tokenEndpoint,
|
|
2164
2240
|
ttlSeconds: options.ttlSeconds,
|
|
2241
|
+
turnDomain: requireOption(
|
|
2242
|
+
turnDomain,
|
|
2243
|
+
"TURN domain is required for TURN PAT mode."
|
|
2244
|
+
),
|
|
2165
2245
|
turnPort: options.turnPort,
|
|
2246
|
+
turnRealm: requireOption(
|
|
2247
|
+
turnRealm,
|
|
2248
|
+
"TURN realm is required for TURN PAT mode."
|
|
2249
|
+
),
|
|
2166
2250
|
turnsPort: options.turnsPort
|
|
2167
2251
|
});
|
|
2168
2252
|
}
|
|
@@ -2173,10 +2257,6 @@ async function createTURNCredentials(options) {
|
|
|
2173
2257
|
apiUrl: options.apiUrl,
|
|
2174
2258
|
clientId: credentials.clientId,
|
|
2175
2259
|
clientSecret: credentials.clientSecret,
|
|
2176
|
-
clusterDomain: requireOption(
|
|
2177
|
-
clusterDomain,
|
|
2178
|
-
"Cluster domain is required for TURN APP mode."
|
|
2179
|
-
),
|
|
2180
2260
|
keyringBaseUrl: options.keyringBaseUrl,
|
|
2181
2261
|
now: options.now,
|
|
2182
2262
|
projectEndpoint: requireOption(
|
|
@@ -2185,24 +2265,36 @@ async function createTURNCredentials(options) {
|
|
|
2185
2265
|
),
|
|
2186
2266
|
serverPublicKeyHex: options.serverPublicKeyHex,
|
|
2187
2267
|
ttlSeconds: options.ttlSeconds,
|
|
2268
|
+
turnDomain: requireOption(
|
|
2269
|
+
turnDomain,
|
|
2270
|
+
"TURN domain is required for TURN APP mode."
|
|
2271
|
+
),
|
|
2188
2272
|
turnPort: options.turnPort,
|
|
2273
|
+
turnRealm: requireOption(
|
|
2274
|
+
turnRealm,
|
|
2275
|
+
"TURN realm is required for TURN APP mode."
|
|
2276
|
+
),
|
|
2189
2277
|
turnsPort: options.turnsPort
|
|
2190
2278
|
});
|
|
2191
2279
|
}
|
|
2192
2280
|
|
|
2193
2281
|
// src/turn-resource.ts
|
|
2282
|
+
var import_rstream11 = require("@rstreamlabs/rstream");
|
|
2194
2283
|
var RstreamTURNResource = class {
|
|
2195
2284
|
client;
|
|
2196
2285
|
constructor(client) {
|
|
2197
2286
|
this.client = client;
|
|
2198
2287
|
}
|
|
2199
2288
|
async createCredentials(options = {}) {
|
|
2200
|
-
const
|
|
2289
|
+
const credentials = options.credentials ?? this.client.credentials;
|
|
2290
|
+
const localMode = options.mode === "app" || options.mode === "pat" || options.mode === void 0 && (0, import_rstream11.isClientCredentials)(credentials);
|
|
2291
|
+
const target = localMode && (options.turnDomain === void 0 || options.turnRealm === void 0) && options.clusterDomain === void 0 ? await this.client.getTURNTarget() : void 0;
|
|
2292
|
+
const engine = options.engine ?? (options.clusterDomain === void 0 && options.turnDomain === void 0 && target === void 0 ? await this.client.getEngine().catch(() => void 0) : void 0);
|
|
2201
2293
|
return await createTURNCredentials({
|
|
2202
2294
|
apiUrl: options.apiUrl ?? this.client.apiUrl,
|
|
2203
2295
|
clusterDomain: options.clusterDomain,
|
|
2204
2296
|
controlPlaneCredentials: options.controlPlaneCredentials ?? this.client.controlPlaneCredentials,
|
|
2205
|
-
credentials
|
|
2297
|
+
credentials,
|
|
2206
2298
|
engine,
|
|
2207
2299
|
keyringBaseUrl: options.keyringBaseUrl,
|
|
2208
2300
|
mode: options.mode,
|
|
@@ -2212,8 +2304,10 @@ var RstreamTURNResource = class {
|
|
|
2212
2304
|
serverPublicKeyHex: options.serverPublicKeyHex,
|
|
2213
2305
|
tokenEndpoint: options.tokenEndpoint,
|
|
2214
2306
|
ttlSeconds: options.ttlSeconds,
|
|
2215
|
-
|
|
2216
|
-
|
|
2307
|
+
turnDomain: options.turnDomain ?? target?.turnDomain,
|
|
2308
|
+
turnPort: options.turnPort ?? target?.turnPort,
|
|
2309
|
+
turnRealm: options.turnRealm ?? target?.turnRealm,
|
|
2310
|
+
turnsPort: options.turnsPort ?? target?.turnsPort
|
|
2217
2311
|
});
|
|
2218
2312
|
}
|
|
2219
2313
|
};
|
|
@@ -2394,7 +2488,7 @@ var RstreamTunnelsClient = class {
|
|
|
2394
2488
|
this.config?.projectEndpoint
|
|
2395
2489
|
);
|
|
2396
2490
|
if (region !== void 0) {
|
|
2397
|
-
if (normalizeOptionalString3(this.config?.engine) !== void 0 || (0,
|
|
2491
|
+
if (normalizeOptionalString3(this.config?.engine) !== void 0 || (0, import_rstream14.readEnvironment)().engine !== void 0) {
|
|
2398
2492
|
throw new Error(
|
|
2399
2493
|
"Region selection cannot be combined with an explicit engine override."
|
|
2400
2494
|
);
|
|
@@ -2406,17 +2500,17 @@ var RstreamTunnelsClient = class {
|
|
|
2406
2500
|
}
|
|
2407
2501
|
const project = await this.getManagedProject();
|
|
2408
2502
|
if (project !== void 0) {
|
|
2409
|
-
const engine = (0,
|
|
2503
|
+
const engine = (0, import_rstream12.getTunnelsProjectEngine)(project, region);
|
|
2410
2504
|
if (engine) return normalizeEngineAddress(engine);
|
|
2411
2505
|
}
|
|
2412
2506
|
throw new Error(
|
|
2413
2507
|
"Failed to resolve the selected regional engine from the managed tunnels project."
|
|
2414
2508
|
);
|
|
2415
2509
|
}
|
|
2416
|
-
if (projectEndpoint !== void 0 && normalizeOptionalString3(this.config?.engine) === void 0 && (0,
|
|
2510
|
+
if (projectEndpoint !== void 0 && normalizeOptionalString3(this.config?.engine) === void 0 && (0, import_rstream14.readEnvironment)().engine === void 0) {
|
|
2417
2511
|
const project = await this.getManagedProject();
|
|
2418
2512
|
if (project !== void 0) {
|
|
2419
|
-
const engine = (0,
|
|
2513
|
+
const engine = (0, import_rstream12.getTunnelsProjectEngine)(project);
|
|
2420
2514
|
if (engine) {
|
|
2421
2515
|
return normalizeEngineAddress(engine);
|
|
2422
2516
|
}
|
|
@@ -2435,6 +2529,27 @@ var RstreamTunnelsClient = class {
|
|
|
2435
2529
|
region: this.config?.region
|
|
2436
2530
|
});
|
|
2437
2531
|
}
|
|
2532
|
+
async getTURNTarget() {
|
|
2533
|
+
const project = await this.getManagedProject();
|
|
2534
|
+
if (project === void 0) {
|
|
2535
|
+
throw new Error(
|
|
2536
|
+
"Managed project endpoint is required to resolve the TURN target."
|
|
2537
|
+
);
|
|
2538
|
+
}
|
|
2539
|
+
const turnDomain = project.turnDomain?.trim() || project.domain.trim();
|
|
2540
|
+
const turnRealm = project.turnRealm?.trim();
|
|
2541
|
+
if (!turnRealm) {
|
|
2542
|
+
throw new Error(
|
|
2543
|
+
"Managed project metadata does not expose the TURN realm; use API credential mode or provide turnRealm explicitly."
|
|
2544
|
+
);
|
|
2545
|
+
}
|
|
2546
|
+
return {
|
|
2547
|
+
turnDomain,
|
|
2548
|
+
turnPort: project.turnPort,
|
|
2549
|
+
turnRealm,
|
|
2550
|
+
turnsPort: project.turnsPort
|
|
2551
|
+
};
|
|
2552
|
+
}
|
|
2438
2553
|
async getManagedProject() {
|
|
2439
2554
|
const projectEndpoint = normalizeOptionalString3(
|
|
2440
2555
|
this.config?.projectEndpoint
|
|
@@ -2511,7 +2626,7 @@ var RstreamTunnelsClient = class {
|
|
|
2511
2626
|
if (!credentials) {
|
|
2512
2627
|
return void 0;
|
|
2513
2628
|
}
|
|
2514
|
-
if (!(0,
|
|
2629
|
+
if (!(0, import_rstream13.isClientCredentials)(credentials)) {
|
|
2515
2630
|
return credentials.token;
|
|
2516
2631
|
}
|
|
2517
2632
|
const tokenParams = await this.getEngineAuthTokenParams();
|