Skip to content
Snippets Groups Projects
types.ts 14.1 KiB
Newer Older
  • Learn to ignore specific revisions
  • export type CommandType =
      | "GET"
      | "SET"
      | "ADD"
      | "DELETE"
      | "OPERATE"
      | "NOTIFY"
      | "GET_SUPPORTED_DM"
      | "GET_INSTANCES"
      | "GET_SUPPORTED_PROTO";
    
    export type GetCommandOptions = {
      raw?: boolean;
    };
    
    
    export type GetReturn = string | Record<string, any> | Record<string, any>[];
    
    export type GetCommand = (
      paths: string | string[],
      options?: GetCommandOptions
    ) => Promise<GetReturn>;
    
    export type SetCommand = (
    
      path: string | string[],
    
      value:
        | (JSValue | JSValue[] | InputRecord)
        | (JSValue | JSValue[] | InputRecord)[]
    
      path: string | string[],
      value?: InputRecord | InputRecord[]
    
    export type DelCommand = (
      path: string,
      allowPartial?: boolean
    
    
    export type OperateSubscribeOptions = {
      /**
       * Skip response from calling operate, defaults to true
       */
    
      subscribe: (
        cb: (msg: any) => void,
        opts?: OperateSubscribeOptions
      ) => {
    
        trigger: (input?: Record<string, any>) => Promise<any>;
      };
      (input?: Record<string, string>): Promise<any>;
    };
    
    export type OperateClearFn = () => Promise<void>;
    export type OperateRecipe = (
      path: string,
      opts?: OperateOptions
    ) => Promise<[OperateFn, OperateClearFn]>;
    
    export type OperateCommand = (
      path: string,
      id: string,
    
      resp: boolean,
    
    ) => Promise<any>;
    
    export type SupportedDMCommand = (
      paths: string | string[],
      opts?: SuportedCommandOpts
    ) => Promise<Record<string, any>>;
    export type InstancesCommand = (
      paths: string | string[],
    
      opts?: { firstLevelOnly?: boolean }
    
    ) => Promise<Record<string, any>>;
    export type SupportedProtoCommand = (versions: string) => Promise<string>;
    export type SubscribeRecipe = (
      opts: SubscriptionOptions,
      callback: SubscriptionCallback
    ) => Promise<PromiseClearFn>;
    
    export type PromiseClearFn = () => Promise<void>;
    
    export type Command =
      | GetCommand
      | SetCommand
      | AddCommand
      | DelCommand
    
      | OperateCommand
    
      | OperateRecipe
      | SubscribeRecipe
      | SupportedDMCommand
      | InstancesCommand
      | SupportedProtoCommand;
    
    export type PbRequestCommand =
      | PbRequestCommandGet
      | PbRequestCommandSet
      | PbRequestCommandAdd
      | PbRequestCommandDel
      | PbRequestCommandOperate
      | PbRequestCommandSupport
      | PbRequestCommandInstance
      | PbRequestCommandSupportProto;
    
    export interface SuportedCommandOpts {
      firstLevelOnly?: boolean;
      returnCommands?: boolean;
      returnEvents?: boolean;
      returnParams?: boolean;
    
    Marin Karamihalev's avatar
    Marin Karamihalev committed
    }
    
    
    export type InputRecord = {
      [k: string]:
        | {
            required: boolean;
            value: any;
          }
        | string
        | number
        | boolean;
    } & { allowPartial?: boolean };
    
    export type PbRequestCommandSupportProto = {
      getSupportedProtocol: {
    
        controllerSupportedProtocolVersions: string;
    
      };
    };
    
    export type PbRequestCommandInstance = {
      getInstances: {
        objPaths: string[];
        firstLevelOnly: boolean;
      };
    };
    
    export type PbRequestCommandSupport = {
      getSupportedDm: {
        objPaths: string[];
        firstLevelOnly: boolean;
        returnCommands: boolean;
        returnEvents: boolean;
        returnParams: boolean;
      };
    };
    
    export type PbRequestCommandOperate = {
      operate: {
        command: string;
        commandKey: string;
        sendResp: boolean;
        inputArgs: Record<string, any>;
      };
    };
    
    export type PbRequestCommandDel = {
      delete: {
        allowPartial: boolean;
        objPaths: string[];
      };
    };
    
    export type PbRequestCommandGet = {
      get: {
        paramPaths: string[];
      };
    };
    
    
    export type SetLookupUpdateObject = "Set.UpdateObject";
    export type SetLookupUpdateParamSetting = "Set.UpdateParamSetting";
    
    
    export type PbRequestCommandSet = {
      set: {
        allowPartial: boolean;
        updateObjs: {
          objPath: string;
    
          lookup: SetLookupUpdateObject;
    
            lookup: SetLookupUpdateParamSetting;
    
            param: string;
            value: any;
            required: boolean;
          }[];
        }[];
      };
    };
    
    
    export type AddLookupCreateObject = "Add.CreateObject";
    export type AddLookupCreateParamSetting = "Add.CreateParamSetting";
    
    
    export type PbRequestCommandAdd = {
      add: {
        allowPartial: boolean;
        createObjs: {
    
          objPath: string;
          paramSettings: {
            param: string;
            value: any;
            required: boolean;
    
          }[];
        }[];
      };
    };
    
    export type Recipe = ResolveRecipe;
    export type ResolveRecipe = (
      msg: GetReturn,
      level?: number
    ) => Promise<GetReturn>;
    
    
    export type PreCallCallback = (name: string, args: any[]) => void;
    export type PostCallCallback = (name: string, args: any[], result: any) => void;
    
    /** Options that allow extending command funcitonality */
    export type Options = {
      /** Timeout command after given number of milliseconds (throws an error for handling with catch) */
    
      timeout?: number;
    
      /** Call function before command */
      preCall?: PreCallCallback;
      /** Call after before command */
      postCall?: PostCallCallback;
    
    Marin Karamihalev's avatar
    Marin Karamihalev committed
    /** Device API */
    
    Marin Karamihalev's avatar
    Marin Karamihalev committed
       * Get value at path
       * @param path Location of value (e.g. "Device.DeviceInfo.")
       * ```
       * await usp.get("Device.WiFi.Radio.1.")
    
    Marin Karamihalev's avatar
    Marin Karamihalev committed
       * await usp.get(["Device.WiFi.Radio.1.", "Device.WiFi.Radio.2."])
    
       *
       * await usp.get("Device.WiFi.Radio.1.", { raw: true }) // skips parsing, produces raw results
    
    Marin Karamihalev's avatar
    Marin Karamihalev committed
       * ```
       */
    
    Marin Karamihalev's avatar
    Marin Karamihalev committed
       * Set value at path
       * @param path Location of value (e.g. "Device.DeviceInfo.")
       * @param value Value to assign
       * ```
       * await usp.set("Device.WiFi.Radio.1.", { Name: "radio-1" })
    
    Marin Karamihalev's avatar
    Marin Karamihalev committed
       * await usp.set("Device.WiFi.Radio.1.Name", "radio-1")
    
       * // or
       * await usp.set(
          ["Device.NAT.PortMapping.1.", "Device.NAT.PortMapping.2."],
          [{ Description: "cat-1" }, { Description: "cat-2" }]
        )
    
    Marin Karamihalev's avatar
    Marin Karamihalev committed
       * ```
       */
    
      /**
       * Create a command
       * @param path Full path of command (e.g. "Device.IP.Diagnostics.IPPing()")
       * @param opts Subscription options (not required)
       * @returns Function that executes command
    
    Marin Karamihalev's avatar
    Marin Karamihalev committed
       * ```
    
       * const [ping, cleanPing] = await usp.operate("Device.IP.Diagnostics.IPPing()")
       * const results = await ping({ Host: "iopsys.eu" })
       * await cleanPing()
    
    Marin Karamihalev's avatar
    Marin Karamihalev committed
       * ```
       */
    
       * Directly call operate without creating a subscription (avoid using unless certain subscription exists),
       * useful for calling sync operate commands for which either output is expected in response or
       * no output is expected
    
       * @param path Full path of command (e.g. "Device.IP.Diagnostics.IPPing()")
       * @param id Full id of subscription (can be found in Device.LocalAgent.Subscription.)
    
       * @param resp to get the response of operate command, useful when response has output
    
       * @param input Optional arguments for command
       * @returns Command results
       * ```
    
       * await usp._operate("Device.Reboot()", 'msg-1', false)
       * await usp._operate("Device.LocalAgent.ControllerTrust.RequestChallenge()", 'msg-2', true, {ChallengeRef: "Device.LocalAgent.ControllerTrust.Challenge.1"})
    
       * ```
       */
      _operate: OperateCommand;
    
    
    Marin Karamihalev's avatar
    Marin Karamihalev committed
       * Add object to path
    
       * @param path Path to add to (e.g. "Device.NAT.PortMapping." or ["Device.NAT.PortMapping."] for multiple)
       * @param values Optional object to add (if skipped will use default values), allows using arrays for multiple objects
       * @returns Full path(s) of new object(s)
    
    Marin Karamihalev's avatar
    Marin Karamihalev committed
       * ```
       * await usp.add("Device.NAT.PortMapping.")
    
       * await usp.add("Device.NAT.PortMapping.", { Description: "cpe-1" })
    
       * await usp.add("Device.NAT.PortMapping.", { Description: "cpe-1", allowPartial: true })
    
       * await usp.add("Device.NAT.PortMapping.", { Description: { value: "cpe-1", required: false }, allowPartial: true })
       * await usp.add(
          ["Device.NAT.PortMapping.", "Device.NAT.PortMapping."],
          [{ Description: "cpe-1" }, { Description: "cpe-2" }]
        );
    
    Marin Karamihalev's avatar
    Marin Karamihalev committed
       * ```
       */
    
    Marin Karamihalev's avatar
    Marin Karamihalev committed
       * Delete object at path
       * @param path Full path to delete (e.g. "Device.NAT.PortMapping.1.")
    
       * @param allowPartial [Optional] Allow partial (defaults to false)
    
    Marin Karamihalev's avatar
    Marin Karamihalev committed
       * ```
       * await usp.del("Device.NAT.PortMapping.1.")
    
       * await usp.del("Device.NAT.PortMapping.1.", true)
    
    Marin Karamihalev's avatar
    Marin Karamihalev committed
       * ```
       */
    
    Marin Karamihalev's avatar
    Marin Karamihalev committed
       * Resolve references in message
       * @param msg Message with reference in it
       * @param level Optional level of nesting to resolve to (avoid using high numbers)
       * ```
       * await usp.get("Device.WiFi.Radio.1.").then(device.resolve)
       * ```
       */
    
      resolve: ResolveRecipe;
    
      /**
       * Get Supported DM
       * @param paths Path(s)
       * @param opts [Optional] Response options
       * ```
       * await usp.supportedDM("Device.WiFi.")
       * ```
       */
      supportedDM: SupportedDMCommand;
    
      /**
       * Get Supported Protocol
    
       * @param versions Controller supported protocol versions
    
       * await usp.supportedProto("1.0")
    
       * ```
       */
      supportedProto: SupportedProtoCommand;
    
       * Get instances
       * @param paths Path(s)
       * @param firstLevelOnly [Optional] Return only first level
       * ```
       * await usp.instances("Device.WiFi.")
       * ```
       */
      instances: SupportedDMCommand;
    
      /**
       * Subscribe to event
       * @param options Subscription options
       * @param callback Callback on relevant message
       * @returns Returns function to clear subscription
       * ```
       * const clearSub = await usp.subscribe({ id: '1234', notif: 'ObjectCreation', reference: 'Device.NAT.PortMapping.' }, console.log)
       * ```
       */
      subscribe: SubscribeRecipe;
    
      /**
       * Add handler for messages
       * @param ident Message identifier (identifies by id, can be a string or regexp)
       * @param callback Callback on relevant message
       * @returns Returns function to clear handler
       * ```
       * const clear = usp.on("error", () => console.log('An error!'))
       * ```
       */
      on: OnFn;
    
      /**
       * Disconnect from device
    
    Marin Karamihalev's avatar
    Marin Karamihalev committed
       * ```
       * await usp.disconnect()
       * ```
       */
    
    Marin Karamihalev's avatar
    Marin Karamihalev committed
      disconnect: () => Promise<void>;
    
    
      /**
       * Add general options to commands, extending their functionality
       * @param opts Options
       * @returns Entire USP API
       * ```
       * await usp.options({ timeout: 1000 }).get("Device.DeviceInfo.SerialNumber")
       * ```
       */
      options: (opts: Options) => USP;
    
    /**
     * Connect to device
     * @param opts - Connection options
     * @param events - Optional event handlers
     * @returns A set of functions for interacting with the device
     */
    
    export type Connect = (
      options: ConnectionOptions,
      events?: ConnectionEvents
    ) => Promise<USP>;
    
    
    type NotifType =
      | "Event"
      | "ValueChange"
      | "ObjectCreation"
      | "ObjectDeletion"
      | "OperationComplete"
      | "OnBoardRequest";
    
    export interface SubscriptionOptions {
    
      notif: NotifType;
      reference: string | string[];
    
    export type SubscriptionCallback = (
      msg: Response,
      fullMsg?: Record<string, any>
    ) => void;
    
    export interface OperateOptions {
    
      ID?: string;
      Persistent?: boolean;
    
      isAsync?: boolean;
    
    export interface PbRequestHeader {
      msgId: string;
      msgType: CommandType;
      lookup: "Header";
    
    export interface PbRequestBody {
      lookup: "Body";
      request: {
        lookup: "Request";
      } & PbRequestCommand;
    
    export interface PbRequestMessage {
      header: PbRequestHeader;
      body: PbRequestBody;
      lookup: "Msg";
    
    export type URLConnectionOptions = {
      url: string;
    } & OtherConnectionOptions;
    
    export type HostConnectionOptions = {
      host: string;
      port: number;
      protocol: "wss" | "ws" | "mqtt" | "mqtts" | "tcp" | "ssl" | "wx" | "wxs";
    } & OtherConnectionOptions;
    
    export type CertType = string | string[] | Buffer | Buffer[];
    export interface OtherConnectionOptions {
      username: string;
      password: string;
    
      fromId?: string;
      toId?: string;
      idEndpoint?: string;
    
      publishEndpoint?: string;
      subscribeEndpoint?: string;
      ca?: CertType | Object[];
      key?: CertType;
      cert?: CertType;
    
      closeOnDisconnect?: boolean;
      reconnectsBeforeClosing?: number;
    
      connectTimeout?: number;
    
    export type ConnectionOptions = URLConnectionOptions | HostConnectionOptions;
    
    export type Response = string | Record<string, any>;
    
    
    export type DecodeOptions = {
      raw?: boolean;
    };
    
    export type DecodeFn = (
      msg: Record<string, any>,
      decodeOptions?: DecodeOptions
    ) => DecodeResponse | [any];
    
    export type DecodeResponse =
      | [any]
      | [any, ResponseID | null, null | Response]
      | [any, ResponseID | null, null | Response, CommandType];
    
    export type EncodeArgs = {
    
      rootMsg: any;
      rootRecord: any;
    
      header: any;
      options: Record<string, string>;
      args: Record<string, any>;
    };
    
    export type OnIdent = string | RegExp;
    
    export type EncodeFn = (args: Record<string, any>) => PbRequestMessage;
    export type CallArgs = Record<string, any>;
    export type ClearFn = () => void;
    
    export type OnFn = (ident: OnIdent, callback: SubscriptionCallback) => ClearFn;
    
    export type MakeFn = (call: CallFn, on: OnFn) => Command;
    export type MakeRecipeFn = (call: CallFn) => Recipe;
    export type CommandTrigger = {
      decode: string | ((msg: Record<string, string>) => boolean);
      encode: string;
    };
    export type CommandObject = {
      encode: EncodeFn;
      decode: DecodeFn;
    };
    
    export interface ConnectionEvents {
      onError?: (err: string) => void;
    
      onOffline?: () => void;
      onReconnect?: () => void;
      onClose?: () => void;
    
    export interface RecipeObject {
      name: string;
      make: MakeFn;
    
    Marin Karamihalev's avatar
    Marin Karamihalev committed
    }
    
    export type CallOptions = {
      responseMsgType?: CommandType;
    };
    
    
    export type ResponseID = "ignore" | "error" | string;
    export type JSValue = string | number | boolean;
    
    export type CallFn = (
      cmd: CommandType,
      args: Record<string, any>,
      callOpts?: CallOptions
    ) => Promise<any>;
    
    
    export type ConnectionClient = {
      on: (key: string, responseFn: (topic: string, data: any) => void) => void;
      subscribe: (to: string) => void;
      unsubscribe: (from: string) => void;
      publish: (endpoint: string, msg: any) => void;
      end: () => void;
    };
    
    export type ConnectClientFn = (options: ConnectionOptions) => ConnectionClient;
    
    export type DecodeIDFn = (data: any) => string;
    
    export type Proto = {
    
      rootRecord: any;
      rootMsg: any;
    
      header: any;
    };
    
    export type LoadProtobufFn = () => Promise<Proto>;
    
    
    export type BuildConnectionFn = (connectConfig: {
      connectClient: ConnectClientFn;
      decodeID: DecodeIDFn;
      loadProtobuf: LoadProtobufFn;
    }) => Connect;