Files
flipper/desktop/flipper-common/src/clientUtils.tsx
Michel Weststrate c97cf6eaf8 Add logging for "Attempted to build clientId with invalid app" event
Summary: The `Error: Attempted to build clientId with invalid app: "` event shows up in our monitoring regularly, but it is unclear which kind of app is trying to connect, so adding some more info to the error, to be able to pin point it better a next time

Reviewed By: lawrencelomax

Differential Revision: D33982871

fbshipit-source-id: 34c2612a9fe86a6815f1cc655f6def1f734e4b1e
2022-02-04 01:15:41 -08:00

102 lines
2.7 KiB
TypeScript

/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
/* A Client uniuely identifies an app running on some device.
Always use this utility to construct and parse clientId strings.
*/
export type ClientIdConstituents = {
app: string;
os: string;
device: string;
device_id: string;
};
/* A plugin key is a string uniquely identifying an instance of a plugin.
This can be a device plugin for a particular device, or a client plugin for a particular client (app).
In the device plugin case, the "client" is the device it's connected to.
In the client plugin case (normal plugins), the "client" is the app it's connected to.
Always use this utility to construct and parse pluginKey strings.
*/
type PluginKeyConstituents =
| {
type: 'device';
pluginName: string;
client: string;
}
| ({
type: 'client';
pluginName: string;
client: string;
} & ClientIdConstituents);
export function buildClientId(clientInfo: {
app: string;
os: string;
device: string;
device_id: string;
}): string {
const escapedName = escape(clientInfo.app);
const result = `${escapedName}#${clientInfo.os}#${clientInfo.device}#${clientInfo.device_id}`;
// N.B.: device_id can be empty, which designates the host device
for (const key of ['app', 'os', 'device'] as Array<
keyof ClientIdConstituents
>) {
if (!clientInfo[key]) {
console.error(
`Attempted to build clientId with invalid ${key}: "${clientInfo[key]} (identifier: ${result})`,
);
}
}
return result;
}
export function deconstructClientId(clientId: string): ClientIdConstituents {
if (!clientId || clientId.split('#').length !== 4) {
console.error(`Attempted to deconstruct invalid clientId: "${clientId}"`);
}
let [app, os, device, device_id] = clientId.split('#');
app = unescape(app);
return {
app,
os,
device,
device_id,
};
}
export function deconstructPluginKey(pluginKey: string): PluginKeyConstituents {
const parts = pluginKey.split('#');
if (parts.length === 2) {
// Device plugin
return {
type: 'device',
client: parts[0],
pluginName: parts[1],
};
} else {
// Client plugin
const lastHashIndex = pluginKey.lastIndexOf('#');
const clientId = pluginKey.slice(0, lastHashIndex);
const pluginName = pluginKey.slice(lastHashIndex + 1);
if (!pluginName) {
console.error(
`Attempted to deconstruct invalid pluginKey: "${pluginKey}"`,
);
}
return {
type: 'client',
...deconstructClientId(clientId),
client: clientId,
pluginName: pluginName,
};
}
}