Research
Security News
Threat Actor Exposes Playbook for Exploiting npm to Build Blockchain-Powered Botnets
A threat actor's playbook for exploiting the npm ecosystem was exposed on the dark web, detailing how to build a blockchain-powered botnet.
mobile-cli-lib
Advanced tools
Provides an easy way for working with devices. Contains common infrastructure for CLIs - mainly AppBuilder and NativeScript.
Latest version: 0.16.0
Release date: 2016, June 29
Before installing the mobile-cli-lib
, verify that your system meets the following requirements.
Minimum Software Requirements
mobile-cli-lib
from working properly with Node.js 0.10.34.cmd
shells on Windows 8 or later systems with Node.js 0.10.x.Additional Software Requirements for iOS On-Device Deployment
The bitness of Node.js and iTunes must match.
Additional Software Requirements for Android On-Device Deployment
Additional Software Requirements for Windows Phone On-Device Deployment
In this version of the
mobile-cli-lib
, you cannot deploy and LiveSync to connected Windows Phone devices from the command line.
Minimum Software Requirements
mobile-cli-lib
from working properly with Node.js 0.10.34.Additional Software Requirements for iOS On-Device Deployment
Additional Software Requirements for Android On-Device Deployment
Additional Software Requirements for Windows Phone On-Device Deployment
In this version of the
mobile-cli-lib
, you cannot deploy and LiveSync to connected Windows Phone devices from the command line.
Minimum Software Requirements
Ubuntu 14.04 LTS
The mobile-cli-lib
is tested and verified to run on Ubuntu 14.04 LTS. You might be able to run the mobile-cli-lib
on other Linux distributions.
Node.js 0.10.26 or a later stable official release except 0.10.34
A known issue prevents the mobile-cli-lib
from working properly with Node.js 0.10.34.
TIP: You can follow the instructions provided here to install Node.js on your system.
An Internet browser (latest official release)
(64-bit systems) The runtime libraries for the ia32/i386 architecture
In the terminal, run the following command.
sudo apt-get install lib32z1 lib32ncurses5 lib32bz2-1.0 libstdc++6:i386
Additional Software Requirements for iOS On-Device Deployment
In this version of the
mobile-cli-lib
, you cannot deploy and LiveSync on connected iOS devices from the command line. You need to manually deploy the application package using iTunes.
Additional Software Requirements for Android On-Device Deployment
sudo apt-get install g++
Additional Software Requirements for Windows Phone On-Device Deployment
In this version of the
mobile-cli-lib
, you cannot deploy and LiveSync to connected Windows Phone devices from the command line.
The mobile-cli-lib
should be added as dependency in your project's package.json
.
In order to use mobile-cli-lib, just add a reference to it in your package.json:
dependencies: {
"mobile-cli-lib": "0.4.0"
}
After that execute npm install
in the directory, where your package.json
is located. This command will install all your dependencies in node_modules
directory. Now you are ready to use mobile-cli-lib
in your project:
var common = require("mobile-cli-lib");
common.fs.getFileSize("D:\\Work\\t.txt")
.then(function (result) {
console.log("File size is: " + result);
return result;
}, function (err) {
console.log("Error happened:");
console.log(err);
});
You can find a sample application here. Just download the zip file and execute npm install
in the project directory.
After that you can execute node index.js
in your terminal. In case you have file D:\Work\t.txt
, the application will show you its size. In case you do not have such file, the application will show an error.
You can change the filename in index.js
.
This section contains information about each public method.
Device related public API, exposes IDeviceInfo
data, that contains the following information:
/**
* Describes available information for a device.
*/
interface IDeviceInfo {
/**
* Unique identifier of the device.
*/
identifier: string;
/**
* The name of the device.
* For Android this is the value of device's 'ro.product.name' property.
* For iOS this is the value of device's 'DeviceName' property.
*/
displayName: string;
/**
* Device model.
* For Android this is the value of device's 'ro.product.model' property.
* For iOS this is the value of device's 'ProductType' property.
*/
model: string;
/**
* Version of the OS.
* For Android this is the value of device's 'ro.build.version.release' property.
* For iOS this is the value of device's 'ProductVersion' property.
*/
version: string;
/**
* Vendor of the device.
* For Android this is the value of device's 'ro.product.brand' property.
* For iOS the value is always "Apple".
*/
vendor: string;
/**
* Device's platform.
* Can be Android or iOS.
*/
platform: string;
/**
* Status of device describing if you can work with this device or there's communication error.
* Can be Connected or Unreachable.
*/
status: string;
/**
* Additional information for errors that prevents working with this device.
* It will be null when status is Connected.
*/
errorHelp: string;
/**
* Defines if the device is tablet or not.
* For Android the value will be true when device's 'ro.build.characteristics' property contains "tablet" word or when the 'ro.build.version.release' is 3.x
* For iOS the value will be true when device's 'ProductType' property contains "ipad" word.
*/
isTablet: boolean;
/**
* Optional property describing the color of the device.
* Available for iOS only - the value of device's 'DeviceColor' property.
*/
color?: string;
/**
* Optional property describing the architecture of the device
* Available for iOS only - can be "armv7" or "arm64"
*/
activeArchitecture?: string;
}
Stability 2 - Stable
companionAppsService
gives access to companion apps identifiers.
getAllCompanionAppIdentifiers
: returns all companion app identifiers in a JSON object, where the top level keys are frameworks (cordova and nativescript) and inner keys are platforms (android, ios, wp8).
Sample usage:var companionAppIdentifiers = require("mobile-cli-lib").companionAppsService.getAllCompanionAppIdentifiers();
Result object is something like:
{
'cordova': {
'android': 'android.cordova.companion.app.identifier',
'ios': 'ios.cordova.companion.app.identifier',
'wp8': 'wp8.cordova.companion.app.identifier'
},
'nativescript': {
'android': 'android.nativescript.companion.app.identifier',
'ios': 'ios.nativescript.companion.app.identifier',
'wp8': null
}
}
getCompanionAppIdentifier(framework: string, platform: string): string
- returns companion app identifier for specified framework and platform.
Sample usage:var companionAppIdentifiers = require("mobile-cli-lib").companionAppsService.getCompanionAppIdentifier("cordova", "android");
Stability 2 - Stable
deviceEmitter
module is used to emit different events related to devices attached to the system.
You can use deviceEmitter
to add handles for the following events:
deviceFound
- Raised when a new device is attached to the system. The callback function will receive one argument - deviceInfoData.
Sample usage:require("mobile-cli-lib").deviceEmitter.on("deviceFound", function(deviceInfoData) {
console.log("Found device with identifier: " + deviceInfoData.identifier);
});
deviceLost
- Raised when a device is detached from the system. The callback function will receive one argument - deviceInfoData.
Sample usage:require("mobile-cli-lib").deviceEmitter.on("deviceLost", function(deviceInfoData) {
console.log("Detached device with identifier: " + deviceInfoData.identifier);
});
deviceLogData
- Raised when attached device reports any information. This is the output of adb logcat
for Android devices. For iOS this is the iOS SysLog
.
The event is raised for any device that reports data. The callback function has two arguments - deviceIdentifier
and reportedData
. require("mobile-cli-lib").deviceEmitter.on("deviceLogData", function(identifier, reportedData) {
console.log("Device " + identifier + " reports: " + reportedData);
});
applicationInstalled
- Raised when application is installed on a device. The callback has two arguments - deviceIdentifier
and applicationIdentifier
. require("mobile-cli-lib").deviceEmitter.on("applicationInstalled", function(identifier, applicationIdentifier) {
console.log("Application " + applicationIdentifier + " has been installed on device with id: " + identifier);
});
debuggableAppFound
- Raised when application on a device becomes available for debugging. The callback has one argument - applicationInfo
. require("mobile-cli-lib").deviceEmitter.on("debuggableAppFound", function(applicationInfo) {
console.log("Application " + applicationInfo.appIdentifier + " is available for debugging on device with id: " + applicationInfo.deviceIdentifier);
});
Sample result for applicationInfo
will be:
{
"deviceIdentifier": "4df18f307d8a8f1b",
"appIdentifier": "com.telerik.Fitness",
"framework": "NativeScript",
"title": "NativeScript Application"
}
debuggableAppLost
- Raised when application on a device is not available for debugging anymore. The callback has one argument - applicationInfo
. require("mobile-cli-lib").deviceEmitter.on("debuggableAppLost", function(applicationInfo) {
console.log("Application " + applicationInfo.appIdentifier + " is not available for debugging anymore on device with id: " + applicationInfo.deviceIdentifier);
});
Sample result for applicationInfo
will be:
{
"deviceIdentifier": "4df18f307d8a8f1b",
"appIdentifier": "com.telerik.Fitness",
"framework": "NativeScript",
"title": "NativeScript Application"
}
applicationUninstalled
- Raised when application is removed from device. The callback has two arguments - deviceIdentifier
and applicationIdentifier
. require("mobile-cli-lib").deviceEmitter.on("applicationUninstalled", function(identifier, applicationIdentifier) {
console.log("Application " + applicationIdentifier + " has been uninstalled from device with id: " + identifier);
});
companionAppInstalled
- Raised when application is removed from device. The callback has two arguments - deviceIdentifier
and framwork
. require("mobile-cli-lib").deviceEmitter.on("companionAppInstalled", function(identifier, framwework) {
console.log("Companion app for " + framework + " has been installed on device with id: " + identifier);
});
companionAppUninstalled
- Raised when application is removed from device. The callback has two arguments - deviceIdentifier
and framwork
. require("mobile-cli-lib").deviceEmitter.on("companionAppUninstalled", function(identifier, framwework) {
console.log("Companion app for " + framework + " has been uninstalled from device with id: " + identifier);
});
Stability: 2 - Stable
This module allows interaction with devices. You can get a list of the attached devices or deploy on specific devices.
getDevices()
- This function returns array of all connected devices. For each of them the following information is provided:
Sample usage:var devices = require("mobile-cli-lib").devicesService.getDevices();
devices.forEach(function(device) {
console.log("Device " + device.identifier + " is connected.");
});
deployOnDevices(deviceIdentifiers: string[], packageFile: string, packageName: string, framework: string)
- Deploys the specified package to the specified devices.
Returns array of Promises. Each of them will be rejected in case the file cannot be deployed on the device or in case there's no device with such identifier.
The function accepts three arguments:
deviceIdentifiers
- array of the unique identifiers of the devices where the application will be deployed.packageFile
- path to the specified package (.apk
or .ipa
);packageName
- the identifier of the package. This corresponds to appId from .abproject
.framework
- the framework of the project. Valid values are Cordova
and NativeScript
.Sample usage:
Promise.all(require("mobile-cli-lib")
.devicesService
.deployOnDevices(["129604ab96a4d0053023b4bf5b288cf34a9ed5fa", "153544fa45f4a5646543b5bf1b221fe31a8fa6bc"], "./app.ipa", "com.telerik.testApp", "Cordova"))
.then(function(data) {
console.log(data);
}, function(err) {
console.log(err);
});
setLogLevel(logLevel: string, deviceIdentifier?: string)
- Sets the logging level for device(s) to INFO
or FULL
.
The method has two parameters, only the first one is mandatory. When only logLevel
is passed, it's value is used for all currently connected devices and all devices that will be connected in the future.
By default the logging level is set to INFO
. For example when there are two devices attached and this method is called in the following way:require("mobile-cli-lib").devicesService.setLogLevel("FULL");
Everything that the devices report will be raised in deviceEmitter.deviceLogData
event. When a new device is attached, all of the information that it reports will also be send.
When the deviceIdentifier
is passed, the value of the log level will be used only for this device. For example when all devices report all of their logs (FULL
) level, you may call:
require("mobile-cli-lib").devicesService.setLogLevel("INFO", "129604ab96a4d0053023b4bf5b288cf34a9ed5fa");
This will set the logging level to INFO
only for device with identifier 129604ab96a4d0053023b4bf5b288cf34a9ed5fa
.
isAppInstalledOnDevices(deviceIdentifiers: string[], appIdentifier: string, framework: string): Promise<IAppInstalledInfo>[]
- checks if the specified application is installed on each of the specified devices and is LiveSync supported for this application.
The returned type for each device is IAppInstalledInfo
:/**
* Describes if LiveSync is supported for specific device and application.
*/
interface IAppInstalledInfo extends ILiveSyncSupportedInfo {
/**
* Unique identifier of the device.
*/
deviceIdentifier: string;
/**
* Application identifier.
*/
appIdentifier: string;
/**
* Defines if application is installed on device.
*/
isInstalled: boolean;
/**
* Result, indicating is livesync supported for specified device and specified application.
* `true` in case livesync is supported and false otherwise.
*/
isLiveSyncSupported: boolean;
}
NOTE: This method will try to start the application on each device in order to understand is LiveSync supported. Sample usage:
Promise.all(require("mobile-cli-lib")
.devicesService
.isAppInstalledOnDevices(devicesFound, "com.telerik.myApp", "cordova"))
.then(function(data) {
console.log(data);
}, function(err) {
console.log(err);
});
Sample result will be:
[{
"deviceIdentifier": "deviceId1",
"appIdentifier": "appId",
"isInstalled": true,
"isLiveSyncSupported": true
}, {
"deviceIdentifier": "deviceId2",
"appIdentifier": "appId",
"isInstalled": false,
"isLiveSyncSupported": false
}]
isCompanionAppInstalledOnDevices(deviceIdentifiers: string[], framework: string): Promise<IAppInstalledInfo>[]
- checks if the companion application is installed on each of the specified devices and is LiveSync supported for this application.
The returned type for each device is IAppInstalledInfo
(check above for full description of the interface).
Sample usage:Promise.all(require("mobile-cli-lib")
.devicesService
.isCompanionAppInstalledOnDevices(devicesFound, "cordova"))
.then(function(data) {
console.log(data);
}, function(err) {
console.log(err);
});
Sample result will be:
[{
"deviceIdentifier": "deviceId1",
"appIdentifier": "com.telerik.AppBuilder",
"isInstalled": true,
"isLiveSyncSupported": true
}, {
"deviceIdentifier": "deviceId2",
"appIdentifier": "com.telerik.AppBuilder",
"isInstalled": false,
"isLiveSyncSupported": false
}]
mapAbstractToTcpPort(deviceIdentifier: string, appIdentifier: string): Promise<string>
- This function forwards the abstract port of the web view on the device to available tcp port on the host and returns the tcp port.Sample usage:
require("mobile-cli-lib").devicesService.mapAbstractToTcpPort("4df18f307d8a8f1b", "com.telerik.test")
.then(function(port) {
console.log(port);
}, function(err) {
console.log(err);
});
getDebuggableApps(deviceIdentifiers: string[]): Promise<IAndroidApplicationInformation[]>[]
- This function checks the proc/net/unix file of each device from the deviceIdentifiers argument for web views connected to abstract ports and returns information about the applications./**
* Describes basic information about Android application.
*/
interface IAndroidApplicationInformation {
/**
* The device identifier.
*/
deviceIdentifier: string;
/**
* The application identifier.
*/
appIdentifier: string;
/**
* The framework of the project (Cordova or NativeScript).
*/
framework: string;
/**
* The title of the current html view which is loaded in the Android WebView. For NativeScript applications the title cannot be acquired.
*/
title?: string;
}
Sample usage:
Promise.all(require("mobile-cli-lib").devicesService.getDebuggableApps(["4df18f307d8a8f1b", "JJY5KBTW75TCHQUK"]))
.then(function(data) {
data.forEach(function(apps) {
console.log(apps);
});
}, function(err) {
console.log(err);
});
Sample result will be:
[[{
"deviceIdentifier": "4df18f307d8a8f1b",
"appIdentifier": "com.telerik.Fitness",
"framework": "NativeScript",
"title": "NativeScript Application"
}, {
"deviceIdentifier": "4df18f307d8a8f1b",
"appIdentifier": "com.telerik.livesynctest",
"framework": "Cordova",
"title": "Home View"
}], [{
"deviceIdentifier": "JJY5KBTW75TCHQUK",
"appIdentifier": "com.telerik.PhotoAlbum",
"framework": "NativeScript",
"title": "NativeScript Application"
}]]
Stability: 1 - Could be changed due to some new requirments.
This module allows LiveSync applications on different devices.
The following types are used:
/**
* Describes the result of a single livesync operation started by Proton.
*/
interface ILiveSyncOperationResult {
/**
* Defines if the operation is successful (set to true) or not (value is false).
*/
isResolved: boolean;
/**
* Error when livesync operation fails. If `isResolved` is true, error will be undefined.
*/
error?: Error;
}
/**
* Describes result of all LiveSync operations per device.
*/
interface IDeviceLiveSyncResult {
/**
* Identifier of the device.
*/
deviceIdentifier: string;
/**
* Result of LiveSync operation for application.
*/
liveSyncToApp?: ILiveSyncOperationResult;
/**
* Result of LiveSync operation to companion app.
*/
liveSyncToCompanion?: ILiveSyncOperationResult;
}
livesync(devicesInfo: IDeviceLiveSyncInfo[], projectDir: string, filePaths?: string[]): Promise<IDeviceLiveSyncResult>[]
- LiveSync changes on the specified devices.
In case filePaths are not specified, the whole project directory will be synced.
The devicesInfo
array describes livesync operations for each device. Each object should be described with the following properties:/**
* Describes device's LiveSync information.
*/
interface IDeviceLiveSyncInfo {
/**
* Unique identifier of the device.
*/
deviceIdentifier: string;
/**
* Defines if changes have to be synced to installed application.
*/
syncToApp: boolean;
/**
* Defines if changes have to be synced to companion app.
*/
syncToCompanion: boolean;
}
Sample usage:
var deviceInfos = [{"deviceIdentifier": "129604ab96a4d0053023b4bf5b288cf34a9ed5fa", "syncToApp": true, "syncToCompanion": false},
{"deviceIdentifier": "153544fa45f4a5646543b5bf1b221fe31a8fa6bc", "syncToApp": true, "syncToCompanion": false}];
// Full Sync - the whole project dir will be synced
Promise.all(require("mobile-cli-lib").liveSyncService.livesync(deviceInfos, projectDir))
.then(function(result) {
console.log("Finished with full sync, result is: ", result);
}).catch(function(err) {
console.log("Error while livesyncing: ", err);
});
// Or use livesync only for some files:
var filesToSync = [path.join(projectDir,"app","components", "homeView", "homeView.xml"),
path.join(projectDir,"app","components", "addressView", "addressView.xml")]
Promise.all(require("mobile-cli-lib").liveSyncService.livesync(deviceInfos, projectDir, filesToSync))
.then(function(result) {
console.log("Finished with partial sync, result is: ", result);
}).catch(function(err) {
console.log("Error while livesyncing: ", err);
});
deleteFiles(devicesInfo: IDeviceLiveSyncInfo[], projectDir: string, filePaths: string[]): Promise<IDeviceLiveSyncResult>[]
- Deletes specified files from devices's livesync directories.
The devicesInfo
array describes livesync operations for each device. Check livesync
method above fore more information.Sample usage:
var deviceInfos = [{"deviceIdentifier": "129604ab96a4d0053023b4bf5b288cf34a9ed5fa", "syncToApp": true, "syncToCompanion": false},
{"deviceIdentifier": "153544fa45f4a5646543b5bf1b221fe31a8fa6bc", "syncToApp": true, "syncToCompanion": false}];
var filesToSync = [path.join(projectDir,"app","components", "homeView", "homeView.xml"),
path.join(projectDir,"app","components", "addressView", "addressView.xml")]
Promise.all(require("mobile-cli-lib").liveSyncService.deleteFiles(deviceInfos, projectDir, filesToSync))
.then(function(result) {
console.log("Finished with deleting files, result is: ", result);
}).catch(function(err) {
console.log("Error while deleting files: ", err);
});
Similar to AngularJS
, mobile-cli-lib
is using $injector
to retrive object instances, instantiate types and load modules. Each module must be registered in the $injector
, so when another module depends on it, the $injector
will create a new instance of the dependency or reuse already created one.
Add a new file with kebab-case (spinal-case) name. For example when the class that you'll add is called DeviceService
, it is good practice to call the file device-service.ts
.
Add your class in the file. The class name should be in Pascal case
class DeviceService {
}
NOTE: The reference path at the top must point the the root of the project, where
.d.ts
file is created bygrunt
.
DeviceService
. The name should be in Camel case:class DeviceService {
}
$injector.register("deviceService", DeviceService);
class DeviceService {
public listDevices(): void {
// implementation is here
}
}
$injector.register("deviceService", DeviceService);
$injector
, you can access them by adding them as parameters of the constructor:class DeviceService {
constructor(private $fs: IFileSystem) { }
}
$injector.register("deviceService", DeviceService);
NOTE: In case you do not place access modifier (
private
,protected
orpublic
, you'll be able to use the dependant module only in the constructor.
NOTE: The name of the module must be exactly the same as the one used for registering in the
$injector
, in this case this isfs
module. The preceding dollar symbol$
is mandatory. Now you can accessfs
methods by usingthis.$fs.<method>
.
bootstrap.ts
:$injector.require("deviceService", "./device-service");
This line tells the $injector
to look for module called "deviceService" in a file device-service
located at the root of the mobile-cli-lib
.
NOTE: The name of the module must be the same as the one used in
$injector.register
call.$injector.require
will not load the file. It will be loaded by$injector
when someone asks for module "deviceService".
In order to expose public API, we use TypeScript decorators and some "magic" in our bootstrapping. When you want to expose method B
from class A
, you have to do the following:
bootstrap.ts
make sure to use requirePublic
method of the $injector
when requiring the file:$injector.requirePublic("deviceService", "./device-service")
@decorators.exported('deviceService')
, where decorators are imported from the root of the project: import decorators = require("./decorators");
IMPORTANT:
exported
decorator requires one parameter which MUST be the first parameter passed torequirePublic
method. This is the name of the module that will be publicly exposed.
After you have executed these two steps, you can start using your publicly available method:
var common = require("mobile-cli-lib");
common.deviceService.listDevices() /* NOTE: here we are not using the class name DeviceService, but the module name - deviceService */
.then(function (a) {
console.log("After promise had returned.");
return a;
})
.catch(function (err) {
console.log("Error happened:");
console.log(err);
});
requirePublic
method of the injector
is doing some "magic" in order to support lazy loading, correct dependency resolving and exposing only some of the methods, not the whole power of the common lib.
When you require mobile-cli-lib
module, you receive $injector's publicApi - it is the "exported one". requirePublic
method defines getter for each module that is passed, for example when you say:
$injector.requirePublic("deviceService", "./device-service")
a new property is added to publicApi - deviceService
and a getter is added for it. When you try to access this module, require("mobile-cli-lib").deviceService.listDevices()
, the getter is called. It resolves the module, by parsing the provided file (./device-service
)
and that's the time when decorators are executed. For each decorated method, a new entry in $injector.publicApi.__modules__
is created. This is not the same method that you've decorated - it's entirely new method, that returns a Promise.
The new method will be used in the publicApi, while original implementation will still be used in all other places in the code. The promisified method will call the original one (in a separate Fiber) and will resolve the Promise with the result of the method.
Some of our modules must be added: staticConfig, config, analyticsService, etc.
Add more tests for yok and for register decorator.
FAQs
common lib used by different CLI
The npm package mobile-cli-lib receives a total of 10 weekly downloads. As such, mobile-cli-lib popularity was classified as not popular.
We found that mobile-cli-lib demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 8 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
A threat actor's playbook for exploiting the npm ecosystem was exposed on the dark web, detailing how to build a blockchain-powered botnet.
Security News
NVD’s backlog surpasses 20,000 CVEs as analysis slows and NIST announces new system updates to address ongoing delays.
Security News
Research
A malicious npm package disguised as a WhatsApp client is exploiting authentication flows with a remote kill switch to exfiltrate data and destroy files.