server/sdk: add support for local addresses preference at sdk level

This commit is contained in:
Koushik Dutta
2022-11-25 20:58:05 -08:00
parent 5143d74596
commit 5fefc8b4fb
12 changed files with 121 additions and 38 deletions

View File

@@ -210,7 +210,7 @@ class ScryptedCloud extends ScryptedDeviceBase implements OauthClient, Settings,
}
}
getDevice(nativeId: string) {
async getDevice(nativeId: string) {
return this.push;
}

4
sdk/package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "@scrypted/sdk",
"version": "0.2.14",
"version": "0.2.21",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@scrypted/sdk",
"version": "0.2.14",
"version": "0.2.21",
"license": "ISC",
"dependencies": {
"@babel/preset-typescript": "^7.16.7",

View File

@@ -1,6 +1,6 @@
{
"name": "@scrypted/sdk",
"version": "0.2.14",
"version": "0.2.21",
"description": "",
"main": "dist/src/index.js",
"exports": {

View File

@@ -1,12 +1,12 @@
{
"name": "@scrypted/types",
"version": "0.2.11",
"version": "0.2.18",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@scrypted/types",
"version": "0.2.11",
"version": "0.2.18",
"license": "ISC",
"devDependencies": {
"@types/rimraf": "^3.0.2",

View File

@@ -1,6 +1,6 @@
{
"name": "@scrypted/types",
"version": "0.2.11",
"version": "0.2.18",
"description": "",
"main": "dist/index.js",
"author": "",

View File

@@ -1155,7 +1155,7 @@ class EndpointManager:
pass
async def getInsecurePublicLocalEndpoint(self, nativeId: str = None) -> str:
pass
def getLocalAddresses(self) -> list[str]:
async def getLocalAddresses(self) -> list[str]:
pass
async def getLocalEndpoint(self, nativeId: str = None, options: Any = None) -> str:
pass

View File

@@ -1404,12 +1404,12 @@ export interface EndpointManager {
* Set the recommended local addresses used by Scrypted plugins that listen for incoming connections.
* @param addresses
*/
setLocalAddresses(...addresses: string[]): Promise<void>;
setLocalAddresses(addresses: string[]): Promise<void>;
/**
* Get the recommended local addresess used by Scrypted plugins that listen for incoming connections.
*/
getLocalAddresses(): Promise<string>[];
getLocalAddresses(): Promise<string[]>;
}
/**
* SystemManager is used by scripts to query device state and access devices.

View File

@@ -11,7 +11,7 @@
"dependencies": {
"@ffmpeg-installer/ffmpeg": "^1.1.0",
"@mapbox/node-pre-gyp": "^1.0.10",
"@scrypted/types": "^0.2.8",
"@scrypted/types": "^0.2.18",
"adm-zip": "^0.5.9",
"axios": "^0.21.4",
"body-parser": "^1.19.0",
@@ -245,9 +245,9 @@
}
},
"node_modules/@scrypted/types": {
"version": "0.2.8",
"resolved": "https://registry.npmjs.org/@scrypted/types/-/types-0.2.8.tgz",
"integrity": "sha512-wH28nmRzsflZPNoBK/Oyog6w6Wx0KEw4S8AZFBz7DreQZ4km8sqa72L2muiZIsZmt76OcsGm2RoRMGZP6EHoCA=="
"version": "0.2.18",
"resolved": "https://registry.npmjs.org/@scrypted/types/-/types-0.2.18.tgz",
"integrity": "sha512-LEhdAgpWZbVMDt74zM/jqBQr42xQl4fDaGwAGtwz0XJ1xnx/hXBXVLs+SdP+Gtnoujjqd1kWTdZCDrnPP4/luw=="
},
"node_modules/@tootallnate/once": {
"version": "1.1.2",
@@ -1084,9 +1084,9 @@
}
},
"node_modules/engine.io": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.2.0.tgz",
"integrity": "sha512-4KzwW3F3bk+KlzSOY57fj/Jx6LyRQ1nbcyIadehl+AnXjKT7gDO0ORdRi/84ixvMKTym6ZKuxvbzN62HDDU1Lg==",
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.2.1.tgz",
"integrity": "sha512-ECceEFcAaNRybd3lsGQKas3ZlMVjN3cyWwMP25D2i0zWfyiytVbTpRPa34qrr+FHddtpBVOmq4H/DCv1O0lZRA==",
"dependencies": {
"@types/cookie": "^0.4.1",
"@types/cors": "^2.8.12",
@@ -3281,9 +3281,9 @@
}
},
"@scrypted/types": {
"version": "0.2.8",
"resolved": "https://registry.npmjs.org/@scrypted/types/-/types-0.2.8.tgz",
"integrity": "sha512-wH28nmRzsflZPNoBK/Oyog6w6Wx0KEw4S8AZFBz7DreQZ4km8sqa72L2muiZIsZmt76OcsGm2RoRMGZP6EHoCA=="
"version": "0.2.18",
"resolved": "https://registry.npmjs.org/@scrypted/types/-/types-0.2.18.tgz",
"integrity": "sha512-LEhdAgpWZbVMDt74zM/jqBQr42xQl4fDaGwAGtwz0XJ1xnx/hXBXVLs+SdP+Gtnoujjqd1kWTdZCDrnPP4/luw=="
},
"@tootallnate/once": {
"version": "1.1.2",
@@ -3979,9 +3979,9 @@
}
},
"engine.io": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.2.0.tgz",
"integrity": "sha512-4KzwW3F3bk+KlzSOY57fj/Jx6LyRQ1nbcyIadehl+AnXjKT7gDO0ORdRi/84ixvMKTym6ZKuxvbzN62HDDU1Lg==",
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.2.1.tgz",
"integrity": "sha512-ECceEFcAaNRybd3lsGQKas3ZlMVjN3cyWwMP25D2i0zWfyiytVbTpRPa34qrr+FHddtpBVOmq4H/DCv1O0lZRA==",
"requires": {
"@types/cookie": "^0.4.1",
"@types/cors": "^2.8.12",

View File

@@ -5,7 +5,7 @@
"dependencies": {
"@ffmpeg-installer/ffmpeg": "^1.1.0",
"@mapbox/node-pre-gyp": "^1.0.10",
"@scrypted/types": "^0.2.8",
"@scrypted/types": "^0.2.18",
"adm-zip": "^0.5.9",
"axios": "^0.21.4",
"body-parser": "^1.19.0",

View File

@@ -78,26 +78,82 @@ class EndpointManagerImpl implements EndpointManager {
return ip?.includes(':') ? `[${ip}]` : ip;
}
/**
* @deprecated
*/
async getAuthenticatedPath(nativeId?: ScryptedNativeId): Promise<string> {
return `/endpoint/${this.getEndpoint(nativeId)}/`;
return this.getPath(nativeId);
}
/**
* @deprecated
*/
async getInsecurePublicLocalEndpoint(nativeId?: ScryptedNativeId): Promise<string> {
return `http://${await this.getUrlSafeIp()}:${await this.api.getComponent('SCRYPTED_INSECURE_PORT')}/endpoint/${this.getEndpoint(nativeId)}/public/`;
return this.getLocalEndpoint(nativeId, {
insecure: true,
public: true,
})
}
/**
* @deprecated
*/
async getPublicCloudEndpoint(nativeId?: ScryptedNativeId): Promise<string> {
const local = await this.getPublicLocalEndpoint(nativeId);
const mo = await this.mediaManager.createMediaObject(Buffer.from(local), ScryptedMimeTypes.LocalUrl);
return this.mediaManager.convertMediaObjectToUrl(mo, ScryptedMimeTypes.LocalUrl);
return this.getCloudEndpoint(nativeId, {
public: true,
});
}
/**
* @deprecated
*/
async getPublicLocalEndpoint(nativeId?: ScryptedNativeId): Promise<string> {
return `https://${await this.getUrlSafeIp()}:${await this.api.getComponent('SCRYPTED_SECURE_PORT')}/endpoint/${this.getEndpoint(nativeId)}/public/`;
return this.getLocalEndpoint(nativeId, {
public: true,
})
}
/**
* @deprecated
*/
async getPublicPushEndpoint(nativeId?: ScryptedNativeId): Promise<string> {
const mo = await this.mediaManager.createMediaObject(Buffer.from(this.getEndpoint(nativeId)), ScryptedMimeTypes.PushEndpoint);
return this.mediaManager.convertMediaObjectToUrl(mo, ScryptedMimeTypes.PushEndpoint);
}
async deliverPush(endpoint: string, request: HttpRequest) {
return this.api.deliverPush(endpoint, request);
async deliverPush(id: string, request: HttpRequest) {
return this.api.deliverPush(id, request);
}
async getPath(nativeId?: string, options?: { public?: boolean; }): Promise<string> {
return `/endpoint/${this.getEndpoint(nativeId)}/${options?.public ? '' : 'public/'}`
}
async getLocalEndpoint(nativeId?: string, options?: { public?: boolean; insecure?: boolean; }): Promise<string> {
const protocol = options?.insecure ? 'http' : 'https';
const port = await this.api.getComponent(options?.insecure ? 'SCRYPTED_INSECURE_PORT' : 'SCRYPTED_INSECURE_PORT');
return `${protocol}://${await this.getUrlSafeIp()}:${port}${this.getPath(nativeId, options)}`;
}
async getCloudEndpoint(nativeId?: string, options?: { public?: boolean; }): Promise<string> {
const local = await this.getLocalEndpoint(nativeId, options);
const mo = await this.mediaManager.createMediaObject(Buffer.from(local), ScryptedMimeTypes.LocalUrl);
return this.mediaManager.convertMediaObjectToUrl(mo, ScryptedMimeTypes.LocalUrl);
}
async getCloudPushEndpoint(nativeId?: string): Promise<string> {
const mo = await this.mediaManager.createMediaObject(Buffer.from(this.getEndpoint(nativeId)), ScryptedMimeTypes.PushEndpoint);
return this.mediaManager.convertMediaObjectToUrl(mo, ScryptedMimeTypes.PushEndpoint);
}
async setLocalAddresses(addresses: string[]): Promise<void> {
const addressSettings = await this.api.getComponent('addresses');
return addressSettings.setLocalAddresses(addresses);
}
async getLocalAddresses(): Promise<string[]> {
const addressSettings = await this.api.getComponent('addresses');
return await addressSettings.getLocalAddresses() as string[];
}
}
@@ -326,10 +382,10 @@ export async function setupPluginRemote(peer: RpcPeer, api: PluginAPI, pluginId:
}
if (eventDetails.property) {
remote.notify(id, eventDetails.eventTime, eventDetails.eventInterface, eventDetails.property, getSystemState()[id]?.[eventDetails.property], eventDetails.changed).catch(() => {});
remote.notify(id, eventDetails.eventTime, eventDetails.eventInterface, eventDetails.property, getSystemState()[id]?.[eventDetails.property], eventDetails.changed).catch(() => { });
}
else {
remote.notify(id, eventDetails.eventTime, eventDetails.eventInterface, eventDetails.property, eventData, eventDetails.changed).catch(() => {});
remote.notify(id, eventDetails.eventTime, eventDetails.eventInterface, eventDetails.property, eventData, eventDetails.changed).catch(() => { });
}
});

View File

@@ -28,6 +28,7 @@ import { isConnectionUpgrade, PluginHttp } from './plugin/plugin-http';
import { WebSocketConnection } from './plugin/plugin-remote-websocket';
import { getPluginVolume } from './plugin/plugin-volume';
import { getIpAddress, SCRYPTED_INSECURE_PORT, SCRYPTED_SECURE_PORT } from './server-settings';
import { AddressSettigns as AddressSettings } from './services/addresses';
import { Alerts } from './services/alerts';
import { CORSControl, CORSServer } from './services/cors';
import { Info } from './services/info';
@@ -70,6 +71,11 @@ export class ScryptedRuntime extends PluginHttp<HttpPluginData> {
},
});
cors: CORSServer[] = [];
pluginComponent = new PluginComponent(this);
servieControl = new ServiceControl(this);
alerts = new Alerts(this);
corsControl = new CORSControl(this);
addressSettings = new AddressSettings(this);
constructor(datastore: Level, insecure: http.Server, secure: https.Server, app: express.Application) {
super(app);
@@ -353,15 +359,17 @@ export class ScryptedRuntime extends PluginHttp<HttpPluginData> {
case 'info':
return new Info();
case 'plugins':
return new PluginComponent(this);
return this.pluginComponent;
case 'service-control':
return new ServiceControl(this);
return this.servieControl;
case 'logger':
return this.logger;
case 'alerts':
return new Alerts(this);
return this.alerts;
case 'cors':
return new CORSControl(this);
return this.corsControl;
case 'addresses':
return this.addressSettings;
}
}

View File

@@ -0,0 +1,19 @@
import { Settings } from "../db-types";
import { ScryptedRuntime } from "../runtime";
export class AddressSettigns {
constructor(public scrypted: ScryptedRuntime) {
}
async setLocalAddresses(addresses: string[]) {
const localAddresses = new Settings();
localAddresses._id = 'localAddresses';
localAddresses.value = addresses;
await this.scrypted.datastore.upsert(localAddresses);
}
async getLocalAddresses(): Promise<string[]> {
const settings = await this.scrypted.datastore.tryGet(Settings, 'localAddresses');
return settings.value as string[];
}
}