@todesktop/client-comm-server
Advanced tools
Comparing version 0.49.0 to 0.50.0
@@ -1,3 +0,3 @@ | ||
export declare type HandleBroadcastFunc<Request extends Record<string, any>, Response> = (callback: (data: Request) => Response | Promise<Response>) => () => void; | ||
export declare type BroadcastFunc<Request extends Record<string, any>, Response> = (params: Request) => Promise<ErrorResponse | SuccessResponse<Response> | undefined>; | ||
export type HandleBroadcastFunc<Request extends Record<string, any>, Response> = (callback: (data: Request) => Response | Promise<Response>) => () => void; | ||
export type BroadcastFunc<Request extends Record<string, any>, Response> = (params: Request) => Promise<ErrorResponse | SuccessResponse<Response> | undefined>; | ||
/** | ||
@@ -21,7 +21,10 @@ * Returns bound functions for interacting with the communication server. | ||
export declare function checkIfCommServerRunning(ports: number[]): Promise<boolean | undefined>; | ||
declare type SuccessResponse<T> = { | ||
export declare class NotRunningError extends Error { | ||
code: string; | ||
} | ||
type SuccessResponse<T> = { | ||
success: true; | ||
data: T; | ||
}; | ||
declare type ErrorResponse = { | ||
type ErrorResponse = { | ||
success: false; | ||
@@ -28,0 +31,0 @@ error: string; |
@@ -12,3 +12,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.checkIfCommServerRunning = exports.createBroadcastService = void 0; | ||
exports.NotRunningError = exports.checkIfCommServerRunning = exports.createBroadcastService = void 0; | ||
const client_util_1 = require("@todesktop/client-util"); | ||
@@ -77,14 +77,56 @@ const client_core_1 = require("@todesktop/client-core"); | ||
exports.checkIfCommServerRunning = checkIfCommServerRunning; | ||
class NotRunningError extends Error { | ||
constructor() { | ||
super(...arguments); | ||
this.code = "ENOTRUNNING"; | ||
} | ||
} | ||
exports.NotRunningError = NotRunningError; | ||
const isValidResponse = (response) => { | ||
return (response !== null && typeof response === "object" && "success" in response); | ||
}; | ||
function fetchWithFallback(ports, path) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
for (const port of ports) { | ||
let response; | ||
let throwImmediately = false; | ||
try { | ||
const response = yield fetch(new URL(path, `http://localhost:${port}`)); | ||
return response.json(); | ||
response = yield fetch(new URL(path, `http://localhost:${port}`)); | ||
} | ||
catch (e) { | ||
// ignore | ||
// If the promise rejects then it's a network error. | ||
// The promise won’t reject on HTTP error status even if the response is an HTTP 404 or 500 | ||
continue; | ||
} | ||
try { | ||
if (response.status === 403) { | ||
// This is a forbidden error which means the server is running but the origin is not correct. | ||
// We will try the next port because there may be multiple different instances of the desktop app running. | ||
throw new Error("Forbidden"); | ||
} | ||
const json = yield response.json(); | ||
if (isValidResponse(json)) { | ||
if (json.success) { | ||
return json; | ||
} | ||
else if (!json.success && "error" in json) { | ||
throwImmediately = true; | ||
throw new Error(json.error); | ||
} | ||
} | ||
} | ||
catch (e) { | ||
if (throwImmediately) { | ||
// This looks like our server is running but it's responding with an error so throw immediately. | ||
throw e; | ||
} | ||
else if (ports.indexOf(port) === ports.length - 1) { | ||
// This is the last port in the list and it's throwing an unknown error (not a network error). | ||
// This usually means there is a different server running on the same port. | ||
throw e; | ||
} | ||
// Otherwise, we'll continue to the next port or throw `NotRunningError`. | ||
} | ||
} | ||
throw new Error("Failed to fetch"); | ||
throw new NotRunningError("Communication server is not running"); | ||
}); | ||
@@ -91,0 +133,0 @@ } |
{ | ||
"name": "@todesktop/client-comm-server", | ||
"version": "0.49.0", | ||
"version": "0.50.0", | ||
"description": "", | ||
@@ -25,8 +25,8 @@ "main": "dist/index.js", | ||
"copyfiles": "^2.4.1", | ||
"typescript": "^4.4.4" | ||
"typescript": "^4.9.5" | ||
}, | ||
"dependencies": { | ||
"@todesktop/client-core": "^1.0.0-alpha38", | ||
"@todesktop/client-util": "^1.0.0-alpha20" | ||
"@todesktop/client-core": "^1.0.0-alpha46", | ||
"@todesktop/client-util": "^1.0.0-alpha27" | ||
} | ||
} |
@@ -87,15 +87,53 @@ import { checkIfCompatibleWithPlugin } from "@todesktop/client-util"; | ||
export class NotRunningError extends Error { | ||
code = "ENOTRUNNING"; | ||
} | ||
const isValidResponse = <T>(response: unknown): response is ResponseData<T> => { | ||
return ( | ||
response !== null && typeof response === "object" && "success" in response | ||
); | ||
}; | ||
async function fetchWithFallback<T>( | ||
ports: number[], | ||
path: string | ||
): FetchResponse<T> { | ||
): Promise<SuccessResponse<T>> { | ||
for (const port of ports) { | ||
let response: Response; | ||
let throwImmediately = false; | ||
try { | ||
const response = await fetch(new URL(path, `http://localhost:${port}`)); | ||
return response.json(); | ||
response = await fetch(new URL(path, `http://localhost:${port}`)); | ||
} catch (e) { | ||
// ignore | ||
// If the promise rejects then it's a network error. | ||
// The promise won’t reject on HTTP error status even if the response is an HTTP 404 or 500 | ||
continue; | ||
} | ||
try { | ||
if (response.status === 403) { | ||
// This is a forbidden error which means the server is running but the origin is not correct. | ||
// We will try the next port because there may be multiple different instances of the desktop app running. | ||
throw new Error("Forbidden"); | ||
} | ||
const json = await response.json(); | ||
if (isValidResponse<T>(json)) { | ||
if (json.success) { | ||
return json; | ||
} else if (!json.success && "error" in json) { | ||
throwImmediately = true; | ||
throw new Error(json.error); | ||
} | ||
} | ||
} catch (e) { | ||
if (throwImmediately) { | ||
// This looks like our server is running but it's responding with an error so throw immediately. | ||
throw e; | ||
} else if (ports.indexOf(port) === ports.length - 1) { | ||
// This is the last port in the list and it's throwing an unknown error (not a network error). | ||
// This usually means there is a different server running on the same port. | ||
throw e; | ||
} | ||
// Otherwise, we'll continue to the next port or throw `NotRunningError`. | ||
} | ||
} | ||
throw new Error("Failed to fetch"); | ||
throw new NotRunningError("Communication server is not running"); | ||
} | ||
@@ -112,2 +150,3 @@ | ||
type ErrorResponse = { success: false; error: string }; | ||
type FetchResponse<T> = Promise<SuccessResponse<T> | ErrorResponse | undefined>; | ||
type ResponseData<T> = SuccessResponse<T> | ErrorResponse; | ||
type FetchResponse<T> = Promise<ResponseData<T>>; |
15785
311