mirror of
https://github.com/koush/scrypted.git
synced 2026-05-05 22:00:27 +01:00
noImplicitReturns: enabled implicit return checking
Fixed all 32 errors by: - Adding '| undefined' to return type signatures where functions could return undefined - Changing 'return;' to 'return undefined;' (explicit instead of implicit) - Adding 'return undefined;' at function ends where needed Functions updated: - src/cluster/cluster-setup.ts: getClusterObject, getScryptedClusterMode - src/fetch/index.ts: getHttpFetchAccept - src/infer-defaults.ts: inferRoomFromName, getProvidedRoomOrDefault, getDisplayRoom - src/level.ts: tryGet - src/plugin/plugin-api.ts: getDeviceById - src/plugin/plugin-device.ts: findMethod, findMixin - src/plugin/plugin-host-api.ts: setDeviceProperty - src/plugin/system.ts: getOwnPropertyDescriptor - src/rpc.ts: getIteratorNext - src/runtime.ts: getAccessControlAllowOrigin, getDeviceLogger, getEndpointPluginData, getAccessControls, invalidatePluginDevice, rebuildPluginDeviceMixinTable, installNpm, getPluginHostForDevice, getDevice - src/scrypted-server-main.ts: getDefaultAuthentication, checkValidUserToken - src/services/addresses.ts: getLocalAddresses - src/state.ts: setState
This commit is contained in:
@@ -18,10 +18,10 @@ export function isClusterAddress(address: string) {
|
||||
return !address || address === process.env.SCRYPTED_CLUSTER_ADDRESS;
|
||||
}
|
||||
|
||||
export function getClusterObject(clusterId: string, value: any) {
|
||||
export function getClusterObject(clusterId: string, value: any): ClusterObject | undefined {
|
||||
const clusterObject: ClusterObject = value?.__cluster;
|
||||
if (clusterObject?.id !== clusterId)
|
||||
return;
|
||||
return undefined;
|
||||
return clusterObject;
|
||||
}
|
||||
|
||||
@@ -400,7 +400,7 @@ export function setupCluster(peer: RpcPeer) {
|
||||
|
||||
export type InitializeCluster = (cluster: { clusterId: string, clusterSecret: string, clusterWorkerId: string, }) => Promise<void>;
|
||||
|
||||
export function getScryptedClusterMode(): ['server' | 'client', string, number] {
|
||||
export function getScryptedClusterMode(): ['server' | 'client', string, number] | undefined {
|
||||
const mode = process.env.SCRYPTED_CLUSTER_MODE as 'server' | 'client';
|
||||
|
||||
if (!mode) {
|
||||
@@ -416,7 +416,7 @@ export function getScryptedClusterMode(): ['server' | 'client', string, number]
|
||||
console.warn('SCRYPTED_CLUSTER_SECRET is set but SCRYPTED_CLUSTER_MODE is not set. This setting will be ignored.');
|
||||
delete process.env.SCRYPTED_CLUSTER_SECRET;
|
||||
}
|
||||
return;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (!['server', 'client'].includes(mode))
|
||||
|
||||
@@ -66,14 +66,14 @@ export type fetcher<B, M> = <T extends HttpFetchOptions<B>>(options: T) => Promi
|
||||
>>;
|
||||
|
||||
|
||||
export function getHttpFetchAccept(responseType: HttpFetchResponseType | undefined) {
|
||||
export function getHttpFetchAccept(responseType: HttpFetchResponseType | undefined): string | undefined {
|
||||
switch (responseType) {
|
||||
case 'json':
|
||||
return 'application/json';
|
||||
case 'text':
|
||||
return 'text/plain';
|
||||
}
|
||||
return;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function hasHeader(headers: [string, string][], key: string) {
|
||||
|
||||
@@ -96,24 +96,24 @@ const roomHints: { [hint: string]: string } = {
|
||||
'Laundry': 'Laundry Room',
|
||||
}
|
||||
|
||||
export function inferRoomFromName(name: string): string {
|
||||
export function inferRoomFromName(name: string): string | undefined {
|
||||
if (!name)
|
||||
return;
|
||||
return undefined;
|
||||
for (const hint of Object.keys(roomHints)) {
|
||||
if (name.includes(hint))
|
||||
return roomHints[hint];
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function getProvidedRoomOrDefault(pluginDevice: PluginDevice): string {
|
||||
export function getProvidedRoomOrDefault(pluginDevice: PluginDevice): string | undefined {
|
||||
const providedRoom = getState(pluginDevice, ScryptedInterfaceProperty.providedRoom);
|
||||
if (providedRoom)
|
||||
return providedRoom;
|
||||
const room = inferRoomFromName(getDisplayName(pluginDevice));
|
||||
return room;
|
||||
return inferRoomFromName(getDisplayName(pluginDevice));
|
||||
}
|
||||
|
||||
export function getDisplayRoom(pluginDevice: PluginDevice): string {
|
||||
export function getDisplayRoom(pluginDevice: PluginDevice): string | undefined {
|
||||
const room = getState(pluginDevice, ScryptedInterfaceProperty.room);
|
||||
if (room)
|
||||
return room;
|
||||
|
||||
@@ -31,7 +31,7 @@ export class WrappedLevel extends Level<string, string | number> {
|
||||
}
|
||||
|
||||
|
||||
async tryGet<T>(documentConstructor: new () => T, _id: any, options?: GetOptions<string, string | number>): Promise<T> {
|
||||
async tryGet<T>(documentConstructor: new () => T, _id: any, options?: GetOptions<string, string | number>): Promise<T | undefined> {
|
||||
try {
|
||||
const _documentType = documentConstructor.name;
|
||||
const key = `${_documentType}/${_id}`;
|
||||
@@ -39,6 +39,7 @@ export class WrappedLevel extends Level<string, string | number> {
|
||||
return createLevelDocument(documentConstructor, json);
|
||||
}
|
||||
catch (e) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -108,9 +108,9 @@ export class PluginAPIProxy extends PluginAPIManagedListeners implements PluginA
|
||||
this.acl?.deny();
|
||||
return this.api.setStorage(nativeId, storage);
|
||||
}
|
||||
getDeviceById(id: string): Promise<ScryptedDevice> {
|
||||
getDeviceById(id: string): Promise<ScryptedDevice | undefined> {
|
||||
if (this.acl?.shouldRejectDevice(id))
|
||||
return;
|
||||
return undefined;
|
||||
return this.api.getDeviceById(id);
|
||||
}
|
||||
setDeviceProperty(id: string, property: ScryptedInterfaceProperty, value: any): Promise<void> {
|
||||
|
||||
@@ -382,7 +382,7 @@ export class PluginDeviceProxyHandler implements PrimitiveProxyHandler<any> {
|
||||
throw new PluginError(`${method} not implemented`)
|
||||
}
|
||||
|
||||
async findMethod(method: string) {
|
||||
async findMethod(method: string): Promise<{ mixin: MixinTable, entry: MixinTableEntry } | undefined> {
|
||||
for (const mixin of this.mixinTable) {
|
||||
const entry = await mixin.entry;
|
||||
if (!entry.methods) {
|
||||
@@ -402,9 +402,10 @@ export class PluginDeviceProxyHandler implements PrimitiveProxyHandler<any> {
|
||||
return { mixin, entry };
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
async findMixin(iface: string) {
|
||||
async findMixin(iface: string): Promise<{ mixin: MixinTable, entry: MixinTableEntry } | undefined> {
|
||||
for (const mixin of this.mixinTable) {
|
||||
const entry = await mixin.entry;
|
||||
const { interfaces } = entry;
|
||||
@@ -412,6 +413,7 @@ export class PluginDeviceProxyHandler implements PrimitiveProxyHandler<any> {
|
||||
return { mixin, entry };
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
async apply(target: any, thisArg: any, argArray?: any): Promise<any> {
|
||||
|
||||
@@ -103,7 +103,7 @@ export class PluginHostAPI extends PluginAPIManagedListeners implements PluginAP
|
||||
return this.scrypted.getComponent(id);
|
||||
}
|
||||
|
||||
setDeviceProperty(id: string, property: ScryptedInterfaceProperty, value: any): Promise<void> {
|
||||
async setDeviceProperty(id: string, property: ScryptedInterfaceProperty, value: any): Promise<void> {
|
||||
switch (property) {
|
||||
case ScryptedInterfaceProperty.room:
|
||||
case ScryptedInterfaceProperty.type:
|
||||
|
||||
@@ -26,7 +26,7 @@ class DeviceProxyHandler implements PrimitiveProxyHandler<any> {
|
||||
return [...methods, ...properties];
|
||||
}
|
||||
|
||||
getOwnPropertyDescriptor(target: any, p: string | symbol): PropertyDescriptor {
|
||||
getOwnPropertyDescriptor(target: any, p: string | symbol): PropertyDescriptor | undefined {
|
||||
const interfaces = new Set<string>(this.systemManager.state[this.id].interfaces.value);
|
||||
const methods = getInterfaceMethods(this.systemManager.descriptors || ScryptedInterfaceDescriptors, interfaces);
|
||||
const prop = p.toString();
|
||||
@@ -42,6 +42,7 @@ class DeviceProxyHandler implements PrimitiveProxyHandler<any> {
|
||||
value: this.systemManager.state[this.id][prop]?.value
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
deleteProperty(target: any, p: string | symbol): boolean {
|
||||
|
||||
@@ -350,9 +350,9 @@ export class RpcPeer {
|
||||
// return value?.[RpcPeer.PROPERTY_PROXY_PROPERTIES];
|
||||
// }
|
||||
|
||||
static getIteratorNext(target: any): string {
|
||||
static getIteratorNext(target: any): string | undefined {
|
||||
if (!target[Symbol.asyncIterator])
|
||||
return;
|
||||
return undefined;
|
||||
const proxyProps = target[this.PROPERTY_PROXY_PROPERTIES]?.[Symbol.asyncIterator.toString()];
|
||||
return proxyProps?.next || 'next';
|
||||
}
|
||||
|
||||
@@ -196,7 +196,7 @@ export class ScryptedRuntime extends PluginHttp<HttpPluginData> {
|
||||
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With, Access-Control-Request-Method');
|
||||
}
|
||||
|
||||
getAccessControlAllowOrigin(headers: http.IncomingHttpHeaders) {
|
||||
getAccessControlAllowOrigin(headers: http.IncomingHttpHeaders): string | undefined {
|
||||
let { origin, referer } = headers;
|
||||
if (!origin && referer) {
|
||||
try {
|
||||
@@ -204,22 +204,22 @@ export class ScryptedRuntime extends PluginHttp<HttpPluginData> {
|
||||
origin = u.origin;
|
||||
}
|
||||
catch (e) {
|
||||
return;
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
if (!origin)
|
||||
return;
|
||||
return undefined;
|
||||
const servers: string[] = process.env.SCRYPTED_ACCESS_CONTROL_ALLOW_ORIGINS?.split(',') || [];
|
||||
servers.push(...Object.values(this.corsControl.origins).flat());
|
||||
if (!servers.includes(origin))
|
||||
return;
|
||||
return undefined;
|
||||
|
||||
return origin;
|
||||
}
|
||||
|
||||
getDeviceLogger(device: PluginDevice): Logger {
|
||||
getDeviceLogger(device: PluginDevice): Logger | undefined {
|
||||
if (!device)
|
||||
return;
|
||||
return undefined;
|
||||
return this.devicesLogger.getLogger(device._id, getState(device, ScryptedInterfaceProperty.name));
|
||||
}
|
||||
|
||||
@@ -273,7 +273,7 @@ export class ScryptedRuntime extends PluginHttp<HttpPluginData> {
|
||||
this.connectRPCObjectIO.handleRequest(reqany, res);
|
||||
}
|
||||
|
||||
async getEndpointPluginData(req: Request, endpoint: string, isUpgrade: boolean, isEngineIOEndpoint: boolean): Promise<HttpPluginData> {
|
||||
async getEndpointPluginData(req: Request, endpoint: string, isUpgrade: boolean, isEngineIOEndpoint: boolean): Promise<HttpPluginData | undefined> {
|
||||
const ret = await this.getPluginForEndpoint(endpoint);
|
||||
if (req.url.indexOf('/engine.io/api') !== -1)
|
||||
return ret;
|
||||
@@ -283,12 +283,12 @@ export class ScryptedRuntime extends PluginHttp<HttpPluginData> {
|
||||
// check if upgrade requests can be handled. must be websocket.
|
||||
if (isUpgrade) {
|
||||
if (!pluginDevice?.state.interfaces.value.includes(ScryptedInterface.EngineIOHandler)) {
|
||||
return;
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!isEngineIOEndpoint && !pluginDevice?.state.interfaces.value.includes(ScryptedInterface.HttpRequestHandler)) {
|
||||
return;
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -380,18 +380,19 @@ export class ScryptedRuntime extends PluginHttp<HttpPluginData> {
|
||||
return packageJson;
|
||||
}
|
||||
|
||||
async getAccessControls(username: string) {
|
||||
async getAccessControls(username: string): Promise<AccessControls | undefined> {
|
||||
if (!username)
|
||||
return;
|
||||
return undefined;
|
||||
|
||||
const user = await this.datastore.tryGet(ScryptedUser, username);
|
||||
if (user?.aclId) {
|
||||
const accessControl = this.getDevice<SU>(user.aclId);
|
||||
const acls = await accessControl.getScryptedUserAccessControl();
|
||||
if (!acls)
|
||||
return;
|
||||
return undefined;
|
||||
return new AccessControls(acls);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
async handleEngineIOEndpoint(req: Request, res: ServerResponse & { locals: any }, endpointRequest: HttpRequest, pluginData: HttpPluginData) {
|
||||
@@ -472,20 +473,18 @@ export class ScryptedRuntime extends PluginHttp<HttpPluginData> {
|
||||
this.invalidatePluginMixins(pluginId);
|
||||
}
|
||||
|
||||
// should this be async?
|
||||
invalidatePluginDevice(id: string) {
|
||||
invalidatePluginDevice(id: string): DeviceProxyPair | undefined {
|
||||
const proxyPair = this.devices[id];
|
||||
if (!proxyPair)
|
||||
return;
|
||||
return undefined;
|
||||
proxyPair.handler.invalidate();
|
||||
return proxyPair;
|
||||
}
|
||||
|
||||
// should this be async?
|
||||
rebuildPluginDeviceMixinTable(id: string) {
|
||||
rebuildPluginDeviceMixinTable(id: string): DeviceProxyPair | undefined {
|
||||
const proxyPair = this.devices[id];
|
||||
if (!proxyPair)
|
||||
return;
|
||||
return undefined;
|
||||
proxyPair.handler.rebuildMixinTable();
|
||||
return proxyPair;
|
||||
}
|
||||
@@ -541,11 +540,11 @@ export class ScryptedRuntime extends PluginHttp<HttpPluginData> {
|
||||
return ret;
|
||||
}
|
||||
|
||||
async installNpm(pkg: string, version?: string, installedSet?: Set<string>): Promise<PluginHost> {
|
||||
async installNpm(pkg: string, version?: string, installedSet?: Set<string>): Promise<PluginHost | undefined> {
|
||||
if (!installedSet)
|
||||
installedSet = new Set();
|
||||
if (installedSet.has(pkg))
|
||||
return;
|
||||
return undefined;
|
||||
installedSet.add(pkg);
|
||||
|
||||
const registry = await getNpmPackageInfo(pkg);
|
||||
@@ -774,21 +773,21 @@ export class ScryptedRuntime extends PluginHttp<HttpPluginData> {
|
||||
return Object.values(this.pluginDevices).filter(e => e.state && e.pluginId === pluginId)
|
||||
}
|
||||
|
||||
getPluginHostForDeviceId(id: string): PluginHost {
|
||||
getPluginHostForDeviceId(id: string): PluginHost | undefined {
|
||||
const device = this.pluginDevices[id];
|
||||
if (!device)
|
||||
return;
|
||||
return undefined;
|
||||
return this.plugins[device.pluginId];
|
||||
}
|
||||
|
||||
getDevice<T>(id: string): T & ScryptedDevice {
|
||||
getDevice<T>(id: string): (T & ScryptedDevice) | undefined {
|
||||
const device = this.devices[id];
|
||||
if (device)
|
||||
return device.proxy as any;
|
||||
|
||||
if (!this.pluginDevices[id]) {
|
||||
console.warn('device not found', id);
|
||||
return;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const handler = new PluginDeviceProxyHandler(this, id);
|
||||
|
||||
@@ -236,7 +236,7 @@ async function start(mainFilename: string, options?: {
|
||||
};
|
||||
}
|
||||
|
||||
const getDefaultAuthentication = (req: Request) => {
|
||||
const getDefaultAuthentication = (req: Request): ScryptedUser | undefined => {
|
||||
const defaultAuthentication = !req.query.disableDefaultAuthentication && process.env.SCRYPTED_DEFAULT_AUTHENTICATION;
|
||||
if (defaultAuthentication) {
|
||||
const referer = req.headers.referer;
|
||||
@@ -244,7 +244,7 @@ async function start(mainFilename: string, options?: {
|
||||
try {
|
||||
const u = new URL(referer);
|
||||
if (u.searchParams.has('disableDefaultAuthentication'))
|
||||
return;
|
||||
return undefined;
|
||||
}
|
||||
catch (e) {
|
||||
// no/invalid referer, allow the default auth
|
||||
@@ -252,6 +252,7 @@ async function start(mainFilename: string, options?: {
|
||||
}
|
||||
return scrypted.usersService.users.get(defaultAuthentication);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
app.use(async (req, res, next) => {
|
||||
@@ -544,9 +545,9 @@ async function start(mainFilename: string, options?: {
|
||||
return req.secure ? 'login_user_token' : 'login_user_token_insecure';
|
||||
};
|
||||
|
||||
const checkValidUserToken = (token: string) => {
|
||||
const checkValidUserToken = (token: string): UserToken | undefined => {
|
||||
if (!token)
|
||||
return;
|
||||
return undefined;
|
||||
try {
|
||||
const userToken = UserToken.validateToken(token);
|
||||
if (scrypted.usersService.users.has(userToken.username))
|
||||
@@ -555,6 +556,7 @@ async function start(mainFilename: string, options?: {
|
||||
catch (e) {
|
||||
// console.warn('invalid token', e.message);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const getSignedLoginUserToken = (req: Request<any>) => {
|
||||
|
||||
@@ -25,11 +25,11 @@ export class AddressSettings {
|
||||
await this.scrypted.datastore.upsert(localAddresses);
|
||||
}
|
||||
|
||||
async getLocalAddresses(raw?: boolean): Promise<string[]> {
|
||||
async getLocalAddresses(raw?: boolean): Promise<string[] | undefined> {
|
||||
const settings = await this.scrypted.datastore.tryGet(Settings, 'localAddresses');
|
||||
|
||||
if (!settings?.value?.[0])
|
||||
return;
|
||||
return undefined;
|
||||
|
||||
const ret: string[] = [];
|
||||
const networkInterfaces = os.networkInterfaces();
|
||||
|
||||
@@ -266,10 +266,10 @@ function isSameValue(value1: any, value2: any) {
|
||||
return value1 === value2 || JSON.stringify(value1) === JSON.stringify(value2);
|
||||
}
|
||||
|
||||
export function setState(pluginDevice: PluginDevice, property: string, value: any): boolean {
|
||||
export function setState(pluginDevice: PluginDevice, property: string, value: any): boolean | undefined {
|
||||
// device may have been deleted.
|
||||
if (!pluginDevice.state)
|
||||
return;
|
||||
return undefined;
|
||||
if (!pluginDevice.state[property])
|
||||
pluginDevice.state[property] = {};
|
||||
const state = pluginDevice.state[property];
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
"strictFunctionTypes": true,
|
||||
"noUncheckedIndexedAccess": true,
|
||||
"noImplicitOverride": true,
|
||||
"noImplicitReturns": true,
|
||||
"outDir": "./dist",
|
||||
"esModuleInterop": true,
|
||||
"moduleResolution": "NodeNext",
|
||||
|
||||
Reference in New Issue
Block a user