diff --git a/CHANGELOG.md b/CHANGELOG.md index bae86e4cd3..16cafb03d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,28 @@ NativeScript CLI Changelog ================ +5.0.1 (2018, November 14) +== +### Implemented +* [Implemented #4083](https://github.com/NativeScript/nativescript-cli/pull/4083): API: Add public API for deviceFound and deviceLost for preview devices +* [Implemented #4087](https://github.com/NativeScript/nativescript-cli/pull/4087): API: Expose public method for getting the qr code of playground app +* [Implemented #4093](https://github.com/NativeScript/nativescript-cli/pull/4093): API: Expose public api for starting the livesync operation to preview app + +### Fixed +* [Fixed #2670](https://github.com/NativeScript/nativescript-cli/issues/2670): Command line `tns run android --clean` rebuilds +* [Fixed #4043](https://github.com/NativeScript/nativescript-cli/issues/4043): `tns preview` fails when local plugin is referenced with tag in `package.json` +* [Fixed #4046](https://github.com/NativeScript/nativescript-cli/issues/4046):`tns debug ios` does not work with bigger projects on slower devices +* [Fixed #4055](https://github.com/NativeScript/nativescript-cli/pull/4055): API: Remove persisted emulator's data on deviceLost event +* [Fixed #4056](https://github.com/NativeScript/nativescript-cli/pull/4056): API: `TypeError: Invalid Version: null` is thrown when emulator is stopped immediately after start +* [Fixed #4071](https://github.com/NativeScript/nativescript-cli/issues/4071): Unable to run `tns test ` +* [Fixed #4073](https://github.com/NativeScript/nativescript-cli/pull/4073): Error is thrown when Node.js 11 is used +* [Fixed #4076](https://github.com/NativeScript/nativescript-cli/issues/4076): Cannot connect to device socket when run debug with justlaunch +* [Fixed #4079](https://github.com/NativeScript/nativescript-cli/pull/4079): API: Reset errors when fallback to list avds from director +* [Fixed #4090](https://github.com/NativeScript/nativescript-cli/issues/4090): `tns preview` and `tns platform add ...` issue +* [Fixed #4096](https://github.com/NativeScript/nativescript-cli/issues/4096): NativeScript v4 is not using the v4 of the app templates during project creation +* [Fixed #4100](https://github.com/NativeScript/nativescript-cli/issues/4100): Apply `before-plugins.gradle` file in the plugin `build.gradle` + + 5.0.0 (2018, November 1) == diff --git a/lib/base-package-manager.ts b/lib/base-package-manager.ts index 58cec10363..ecfdfbfb0e 100644 --- a/lib/base-package-manager.ts +++ b/lib/base-package-manager.ts @@ -1,13 +1,62 @@ import { isInteractive } from "./common/helpers"; -export class BasePackageManager { +export abstract class BasePackageManager implements INodePackageManager { + public abstract install(packageName: string, pathToSave: string, config: INodePackageManagerInstallOptions): Promise; + public abstract uninstall(packageName: string, config?: IDictionary, path?: string): Promise; + public abstract view(packageName: string, config: Object): Promise; + public abstract search(filter: string[], config: IDictionary): Promise; + public abstract searchNpms(keyword: string): Promise; + public abstract getRegistryPackageData(packageName: string): Promise; + public abstract getCachePath(): Promise; + constructor( protected $childProcess: IChildProcess, + protected $fs: IFileSystem, private $hostInfo: IHostInfo, private $pacoteService: IPacoteService, private packageManager: string ) { } + public async isRegistered(packageName: string): Promise { + if (this.isURL(packageName) || this.$fs.exists(packageName) || this.isTgz(packageName)) { + return false; + } + + try { + const viewResult = await this.view(packageName, { name: true }); + + // `npm view nonExistingPackageName` will return `nativescript` + // if executed in the root dir of the CLI (npm 6.4.1) + const packageNameRegex = new RegExp(packageName, "i"); + const isProperResult = packageNameRegex.test(viewResult); + + return isProperResult; + } catch (e) { + return false; + } + } + + public async getPackageNameParts(fullPackageName: string): Promise { + // support @ syntax, for example typescript@1.0.0 + // support @ syntax, for example @nativescript/vue-template@1.0.0 + const lastIndexOfAtSign = fullPackageName.lastIndexOf("@"); + let version = ""; + let templateName = ""; + if (lastIndexOfAtSign > 0) { + templateName = fullPackageName.substr(0, lastIndexOfAtSign).toLowerCase(); + version = fullPackageName.substr(lastIndexOfAtSign + 1); + } + + return { + name: templateName || fullPackageName, + version: version + }; + } + + public async getPackageFullName(packageNameParts: INpmPackageNameParts): Promise { + return packageNameParts.version ? `${packageNameParts.name}@${packageNameParts.version}` : packageNameParts.name; + } + protected getPackageManagerExecutableName(): string { let npmExecutableName = this.packageManager; @@ -44,7 +93,7 @@ export class BasePackageManager { array.push(`--${flag}`); array.push(`${config[flag]}`); } else if (config[flag]) { - if (flag === "dist-tags" || flag === "versions") { + if (flag === "dist-tags" || flag === "versions" || flag === "name") { array.push(` ${flag}`); continue; } @@ -57,4 +106,14 @@ export class BasePackageManager { return array.join(" "); } + + private isTgz(packageName: string): boolean { + return packageName.indexOf(".tgz") >= 0; + } + + private isURL(str: string): boolean { + const urlRegex = '^(?!mailto:)(?:(?:http|https|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))|localhost)(?::\\d{2,5})?(?:(/|\\?|#)[^\\s]*)?$'; + const url = new RegExp(urlRegex, 'i'); + return str.length < 2083 && url.test(str); + } } diff --git a/lib/bootstrap.ts b/lib/bootstrap.ts index 2bf6a97f0e..54f9cfa4ac 100644 --- a/lib/bootstrap.ts +++ b/lib/bootstrap.ts @@ -137,6 +137,7 @@ $injector.require("androidLiveSyncService", "./services/livesync/android-livesyn $injector.require("iOSLiveSyncService", "./services/livesync/ios-livesync-service"); $injector.require("usbLiveSyncService", "./services/livesync/livesync-service"); // The name is used in https://github.com/NativeScript/nativescript-dev-typescript $injector.require("previewAppLiveSyncService", "./services/livesync/playground/preview-app-livesync-service"); +$injector.require("previewAppLogProvider", "./services/livesync/playground/preview-app-log-provider"); $injector.require("previewAppPluginsService", "./services/livesync/playground/preview-app-plugins-service"); $injector.require("previewSdkService", "./services/livesync/playground/preview-sdk-service"); $injector.requirePublicClass("previewDevicesService", "./services/livesync/playground/devices/preview-devices-service"); diff --git a/lib/commands/preview.ts b/lib/commands/preview.ts index bc42413b3f..f3bf388a30 100644 --- a/lib/commands/preview.ts +++ b/lib/commands/preview.ts @@ -1,3 +1,5 @@ +import { DEVICE_LOG_EVENT_NAME } from "../common/constants"; + export class PreviewCommand implements ICommand { public allowedParameters: ICommandParameter[] = []; private static MIN_SUPPORTED_WEBPACK_VERSION = "0.17.0"; @@ -5,12 +7,18 @@ export class PreviewCommand implements ICommand { constructor(private $bundleValidatorHelper: IBundleValidatorHelper, private $errors: IErrors, private $liveSyncService: ILiveSyncService, + private $logger: ILogger, private $networkConnectivityValidator: INetworkConnectivityValidator, private $projectData: IProjectData, private $options: IOptions, + private $previewAppLogProvider: IPreviewAppLogProvider, private $previewQrCodeService: IPreviewQrCodeService) { } public async execute(): Promise { + this.$previewAppLogProvider.on(DEVICE_LOG_EVENT_NAME, (deviceId: string, message: string) => { + this.$logger.info(message); + }); + await this.$liveSyncService.liveSync([], { syncToPreviewApp: true, projectDir: this.$projectData.projectDir, diff --git a/lib/declarations.d.ts b/lib/declarations.d.ts index af9bd81cd6..2feaee2d6e 100644 --- a/lib/declarations.d.ts +++ b/lib/declarations.d.ts @@ -25,6 +25,27 @@ interface INodePackageManager { */ view(packageName: string, config: Object): Promise; + /** + * Checks if the specified string is name of a packaged published in the NPM registry. + * @param {string} packageName The string to be checked. + * @return {Promise} True if the specified string is a registered package name, false otherwise. + */ + isRegistered(packageName: string): Promise; + + /** + * Separates the package name and version from a specified fullPackageName. + * @param {string} fullPackageName The full name of the package like nativescript@10.0.0. + * @return {INpmPackageNameParts} An object containing the separated package name and version. + */ + getPackageNameParts(fullPackageName: string): Promise + + /** + * Returns the full name of an npm package based on the provided name and version. + * @param {INpmPackageNameParts} packageNameParts An object containing the package name and version. + * @return {string} The full name of the package like nativescript@10.0.0. + */ + getPackageFullName(packageNameParts: INpmPackageNameParts): Promise + /** * Searches for a package. * @param {string[]} filter Keywords with which to perform the search. @@ -59,6 +80,7 @@ interface IPackageInstallationManager { getLatestVersion(packageName: string): Promise; getNextVersion(packageName: string): Promise; getLatestCompatibleVersion(packageName: string, referenceVersion?: string): Promise; + getLatestCompatibleVersionSafe(packageName: string, referenceVersion?: string): Promise; getInspectorFromCache(inspectorNpmPackageName: string, projectDir: string): Promise; } @@ -353,6 +375,11 @@ interface INpmsPackageData { maintainers: INpmsUser[]; } +interface INpmPackageNameParts { + name: string; + version: string; +} + interface IUsername { username: string; } @@ -537,9 +564,9 @@ interface IEnvOptions { interface IAndroidBuildOptionsSettings extends IAndroidReleaseOptions, IRelease, IHasAndroidBundle { } - interface IHasAndroidBundle { +interface IHasAndroidBundle { androidBundle?: boolean; - } +} interface IAppFilesUpdaterOptions extends IBundle, IRelease, IOptionalWatchAllFiles, IHasUseHotModuleReloadOption { } diff --git a/lib/definitions/preview-app-livesync.d.ts b/lib/definitions/preview-app-livesync.d.ts index 01faa8bda3..bac20cb7b0 100644 --- a/lib/definitions/preview-app-livesync.d.ts +++ b/lib/definitions/preview-app-livesync.d.ts @@ -8,7 +8,7 @@ declare global { stopLiveSync(): Promise; } - interface IPreviewAppLiveSyncData extends IProjectDir, IAppFilesUpdaterOptionsComposition, IEnvOptions { } + interface IPreviewAppLiveSyncData extends IProjectDir, IHasUseHotModuleReloadOption, IBundle, IEnvOptions { } interface IPreviewSdkService extends EventEmitter { getQrCodeUrl(options: IHasUseHotModuleReloadOption): string; @@ -18,10 +18,15 @@ declare global { } interface IPreviewAppPluginsService { + getPluginsUsageWarnings(data: IPreviewAppLiveSyncData, device: Device): string[]; comparePluginsOnDevice(data: IPreviewAppLiveSyncData, device: Device): Promise; getExternalPlugins(device: Device): string[]; } + interface IPreviewAppLogProvider extends EventEmitter { + logData(log: string, deviceName: string, deviceId: string): void; + } + interface IPreviewQrCodeService { getPlaygroundAppQrCode(options?: IPlaygroundAppQrCodeOptions): Promise>; getLiveSyncQrCode(url: string): Promise; @@ -45,5 +50,6 @@ declare global { updateConnectedDevices(devices: Device[]): void; getDeviceById(id: string): Device; getDevicesForPlatform(platform: string): Device[]; + getPluginsUsageWarnings(data: IPreviewAppLiveSyncData, device: Device): string[]; } } \ No newline at end of file diff --git a/lib/definitions/project-changes.d.ts b/lib/definitions/project-changes.d.ts index 9096f1cee9..7da52ca180 100644 --- a/lib/definitions/project-changes.d.ts +++ b/lib/definitions/project-changes.d.ts @@ -1,14 +1,14 @@ interface IAppFilesHashes { - appFilesHashes: IStringDictionary; + appFilesHashes?: IStringDictionary; } interface IPrepareInfo extends IAddedNativePlatform, IAppFilesHashes { - time: string; - bundle: boolean; - release: boolean; - projectFileHash: string; - changesRequireBuild: boolean; - changesRequireBuildTime: string; + time?: string; + bundle?: boolean; + release?: boolean; + projectFileHash?: string; + changesRequireBuild?: boolean; + changesRequireBuildTime?: string; iOSProvisioningProfileUUID?: string; } diff --git a/lib/node-package-manager.ts b/lib/node-package-manager.ts index ffc3b39119..39d0965661 100644 --- a/lib/node-package-manager.ts +++ b/lib/node-package-manager.ts @@ -3,16 +3,16 @@ import { BasePackageManager } from "./base-package-manager"; import { exported, cache } from "./common/decorators"; import { CACACHE_DIRECTORY_NAME } from "./constants"; -export class NodePackageManager extends BasePackageManager implements INodePackageManager { +export class NodePackageManager extends BasePackageManager { constructor( $childProcess: IChildProcess, private $errors: IErrors, - private $fs: IFileSystem, + $fs: IFileSystem, $hostInfo: IHostInfo, private $logger: ILogger, private $httpClient: Server.IHttpClient, $pacoteService: IPacoteService) { - super($childProcess, $hostInfo, $pacoteService, 'npm'); + super($childProcess, $fs, $hostInfo, $pacoteService, 'npm'); } @exported("npm") diff --git a/lib/package-installation-manager.ts b/lib/package-installation-manager.ts index 15ba2a9249..fcd42b493f 100644 --- a/lib/package-installation-manager.ts +++ b/lib/package-installation-manager.ts @@ -39,6 +39,16 @@ export class PackageInstallationManager implements IPackageInstallationManager { return maxSatisfying || latestVersion; } + public async getLatestCompatibleVersionSafe(packageName: string, referenceVersion?: string): Promise { + let version = ""; + const canGetVersionFromNpm = await this.$packageManager.isRegistered(packageName); + if (canGetVersionFromNpm) { + version = await this.getLatestCompatibleVersion(packageName, referenceVersion); + } + + return version; + } + public async install(packageToInstall: string, projectDir: string, opts?: INpmInstallOptions): Promise { try { const pathToSave = projectDir; @@ -101,6 +111,7 @@ export class PackageInstallationManager implements IPackageInstallationManager { if (this.$fs.exists(pathToInspector)) { return true; } + return false; } @@ -110,28 +121,13 @@ export class PackageInstallationManager implements IPackageInstallationManager { packageName = possiblePackageName; } - // check if the packageName is url or local file and if it is, let npm install deal with the version - if (this.isURL(packageName) || this.$fs.exists(packageName) || this.isTgz(packageName)) { - version = null; - } else { - version = version || await this.getLatestCompatibleVersion(packageName); - } - + version = version || await this.getLatestCompatibleVersionSafe(packageName); const installResultInfo = await this.npmInstall(packageName, pathToSave, version, dependencyType); const installedPackageName = installResultInfo.name; const pathToInstalledPackage = path.join(pathToSave, "node_modules", installedPackageName); - return pathToInstalledPackage; - } - private isTgz(packageName: string): boolean { - return packageName.indexOf(".tgz") >= 0; - } - - private isURL(str: string): boolean { - const urlRegex = '^(?!mailto:)(?:(?:http|https|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))|localhost)(?::\\d{2,5})?(?:(/|\\?|#)[^\\s]*)?$'; - const url = new RegExp(urlRegex, 'i'); - return str.length < 2083 && url.test(str); + return pathToInstalledPackage; } private async npmInstall(packageName: string, pathToSave: string, version: string, dependencyType: string): Promise { diff --git a/lib/package-manager.ts b/lib/package-manager.ts index 6f36883c18..61ea037b82 100644 --- a/lib/package-manager.ts +++ b/lib/package-manager.ts @@ -9,7 +9,7 @@ export class PackageManager implements INodePackageManager { private $options: IOptions, private $yarn: INodePackageManager, private $userSettingsService: IUserSettingsService - ) {} + ) { } @cache() protected async init(): Promise { @@ -42,6 +42,21 @@ export class PackageManager implements INodePackageManager { return this.packageManager.searchNpms(keyword); } + @invokeInit() + public async isRegistered(packageName: string): Promise { + return this.packageManager.isRegistered(packageName); + } + + @invokeInit() + public async getPackageFullName(packageNameParts: INpmPackageNameParts): Promise { + return this.packageManager.getPackageFullName(packageNameParts); + } + + @invokeInit() + public async getPackageNameParts(fullPackageName: string): Promise { + return this.packageManager.getPackageNameParts(fullPackageName); + } + @invokeInit() public getRegistryPackageData(packageName: string): Promise { return this.packageManager.getRegistryPackageData(packageName); diff --git a/lib/services/livesync/livesync-service.ts b/lib/services/livesync/livesync-service.ts index 6741cca82a..ecac15210b 100644 --- a/lib/services/livesync/livesync-service.ts +++ b/lib/services/livesync/livesync-service.ts @@ -57,13 +57,13 @@ export class LiveSyncService extends EventEmitter implements IDebugLiveSyncServi await this.liveSync([], { syncToPreviewApp: true, projectDir: data.projectDir, - bundle: data.appFilesUpdaterOptions.bundle, - useHotModuleReload: data.appFilesUpdaterOptions.useHotModuleReload, + bundle: data.bundle, + useHotModuleReload: data.useHotModuleReload, release: false, env: data.env, }); - const url = this.$previewSdkService.getQrCodeUrl({ useHotModuleReload: data.appFilesUpdaterOptions.useHotModuleReload }); + const url = this.$previewSdkService.getQrCodeUrl({ useHotModuleReload: data.useHotModuleReload }); const result = await this.$previewQrCodeService.getLiveSyncQrCode(url); return result; } @@ -362,13 +362,10 @@ export class LiveSyncService extends EventEmitter implements IDebugLiveSyncServi if (liveSyncData.syncToPreviewApp) { await this.$previewAppLiveSyncService.initialize({ - appFilesUpdaterOptions: { - bundle: liveSyncData.bundle, - release: liveSyncData.release, - useHotModuleReload: liveSyncData.useHotModuleReload - }, - env: liveSyncData.env, - projectDir: projectData.projectDir + projectDir: projectData.projectDir, + bundle: liveSyncData.bundle, + useHotModuleReload: liveSyncData.useHotModuleReload, + env: liveSyncData.env }); } else { // In case liveSync is called for a second time for the same projectDir. @@ -641,13 +638,10 @@ export class LiveSyncService extends EventEmitter implements IDebugLiveSyncServi if (liveSyncData.syncToPreviewApp) { await this.addActionToChain(projectData.projectDir, async () => { await this.$previewAppLiveSyncService.syncFiles({ - appFilesUpdaterOptions: { - bundle: liveSyncData.bundle, - release: liveSyncData.release, - useHotModuleReload: liveSyncData.useHotModuleReload - }, - env: liveSyncData.env, - projectDir: projectData.projectDir + projectDir: projectData.projectDir, + bundle: liveSyncData.bundle, + useHotModuleReload: liveSyncData.useHotModuleReload, + env: liveSyncData.env }, currentFilesToSync, currentFilesToRemove); }); } else { diff --git a/lib/services/livesync/playground/devices/preview-devices-service.ts b/lib/services/livesync/playground/devices/preview-devices-service.ts index 09e18f275a..93429b789e 100644 --- a/lib/services/livesync/playground/devices/preview-devices-service.ts +++ b/lib/services/livesync/playground/devices/preview-devices-service.ts @@ -1,10 +1,17 @@ import { Device } from "nativescript-preview-sdk"; import { EventEmitter } from "events"; -import { DeviceDiscoveryEventNames } from "../../../../common/constants"; +import { DeviceDiscoveryEventNames, DEVICE_LOG_EVENT_NAME } from "../../../../common/constants"; export class PreviewDevicesService extends EventEmitter implements IPreviewDevicesService { private connectedDevices: Device[] = []; + constructor(private $previewAppLogProvider: IPreviewAppLogProvider, + private $previewAppPluginsService: IPreviewAppPluginsService) { + super(); + + this.initialize(); + } + public getConnectedDevices(): Device[] { return this.connectedDevices; } @@ -27,6 +34,16 @@ export class PreviewDevicesService extends EventEmitter implements IPreviewDevic return _.filter(this.connectedDevices, { platform: platform.toLowerCase() }); } + public getPluginsUsageWarnings(data: IPreviewAppLiveSyncData, device: Device): string[] { + return this.$previewAppPluginsService.getPluginsUsageWarnings(data, device); + } + + private initialize(): void { + this.$previewAppLogProvider.on(DEVICE_LOG_EVENT_NAME, (deviceId: string, message: string) => { + this.emit(DEVICE_LOG_EVENT_NAME, deviceId, message); + }); + } + private raiseDeviceFound(device: Device) { this.emit(DeviceDiscoveryEventNames.DEVICE_FOUND, device); this.connectedDevices.push(device); diff --git a/lib/services/livesync/playground/preview-app-livesync-service.ts b/lib/services/livesync/playground/preview-app-livesync-service.ts index a1727430a0..1b8de93f86 100644 --- a/lib/services/livesync/playground/preview-app-livesync-service.ts +++ b/lib/services/livesync/playground/preview-app-livesync-service.ts @@ -66,7 +66,7 @@ export class PreviewAppLiveSyncService implements IPreviewAppLiveSyncService { .uniq() .value(); for (const platform of platforms) { - await this.syncFilesForPlatformSafe(data, platform, { filesToSync, filesToRemove, useHotModuleReload: data.appFilesUpdaterOptions.useHotModuleReload }); + await this.syncFilesForPlatformSafe(data, platform, { filesToSync, filesToRemove, useHotModuleReload: data.useHotModuleReload }); } } @@ -78,7 +78,7 @@ export class PreviewAppLiveSyncService implements IPreviewAppLiveSyncService { const hookArgs = this.getHookArgs(data, device); await this.$hooksService.executeBeforeHooks("preview-sync", { hookArgs }); await this.$previewAppPluginsService.comparePluginsOnDevice(data, device); - const payloads = await this.syncFilesForPlatformSafe(data, device.platform, { isInitialSync: true, useHotModuleReload: data.appFilesUpdaterOptions.useHotModuleReload }); + const payloads = await this.syncFilesForPlatformSafe(data, device.platform, { isInitialSync: true, useHotModuleReload: data.useHotModuleReload }); return payloads; } @@ -92,7 +92,11 @@ export class PreviewAppLiveSyncService implements IPreviewAppLiveSyncService { config: { env: data.env, platform: device.platform, - appFilesUpdaterOptions: data.appFilesUpdaterOptions, + appFilesUpdaterOptions: { + bundle: data.bundle, + useHotModuleReload: data.useHotModuleReload, + release: false + }, }, externals: this.$previewAppPluginsService.getExternalPlugins(device), filesToSyncMap, @@ -109,10 +113,10 @@ export class PreviewAppLiveSyncService implements IPreviewAppLiveSyncService { const platformHmrData = currentHmrData[platform] || {}; const filesToSync = _.cloneDeep(filesToSyncMap[platform]); // We don't need to prepare when webpack emits changed files. We just need to send a message to pubnub. - promise = this.syncFilesForPlatformSafe(data, platform, { filesToSync, skipPrepare: true, useHotModuleReload: data.appFilesUpdaterOptions.useHotModuleReload }); + promise = this.syncFilesForPlatformSafe(data, platform, { filesToSync, skipPrepare: true, useHotModuleReload: data.useHotModuleReload }); await promise; - if (data.appFilesUpdaterOptions.useHotModuleReload && platformHmrData.hash) { + if (data.useHotModuleReload && platformHmrData.hash) { const devices = this.$previewDevicesService.getDevicesForPlatform(platform); await Promise.all(_.map(devices, async (previewDevice: Device) => { @@ -133,12 +137,12 @@ export class PreviewAppLiveSyncService implements IPreviewAppLiveSyncService { let payloads = null; try { - const { appFilesUpdaterOptions, env, projectDir } = data; + const { env, projectDir } = data; const projectData = this.$projectDataService.getProjectData(projectDir); const platformData = this.$platformsData.getPlatformData(platform, projectData); if (!opts.skipPrepare) { - await this.preparePlatform(platform, appFilesUpdaterOptions, env, projectData); + await this.preparePlatform(platform, data, env, projectData); } if (opts.isInitialSync) { @@ -178,7 +182,12 @@ export class PreviewAppLiveSyncService implements IPreviewAppLiveSyncService { return { files: payloads, platform: platformData.normalizedPlatformName.toLowerCase(), hmrMode, deviceId }; } - private async preparePlatform(platform: string, appFilesUpdaterOptions: IAppFilesUpdaterOptions, env: Object, projectData: IProjectData): Promise { + private async preparePlatform(platform: string, data: IPreviewAppLiveSyncData, env: Object, projectData: IProjectData): Promise { + const appFilesUpdaterOptions = { + bundle: data.bundle, + useHotModuleReload: data.useHotModuleReload, + release: false + }; const nativePrepare = { skipNativePrepare: true }; const config = {}; const platformTemplate = null; diff --git a/lib/services/livesync/playground/preview-app-log-provider.ts b/lib/services/livesync/playground/preview-app-log-provider.ts new file mode 100644 index 0000000000..3e0c900f86 --- /dev/null +++ b/lib/services/livesync/playground/preview-app-log-provider.ts @@ -0,0 +1,10 @@ +import { EventEmitter } from "events"; +import { DEVICE_LOG_EVENT_NAME } from "../../../common/constants"; + +export class PreviewAppLogProvider extends EventEmitter implements IPreviewAppLogProvider { + public logData(log: string, deviceName: string, deviceId: string): void { + const message = `LOG from device ${deviceName}: ${log}`; + this.emit(DEVICE_LOG_EVENT_NAME, deviceId, message); + } +} +$injector.register("previewAppLogProvider", PreviewAppLogProvider); diff --git a/lib/services/livesync/playground/preview-app-plugins-service.ts b/lib/services/livesync/playground/preview-app-plugins-service.ts index ecf7fc0b57..3c8c80a178 100644 --- a/lib/services/livesync/playground/preview-app-plugins-service.ts +++ b/lib/services/livesync/playground/preview-app-plugins-service.ts @@ -9,11 +9,20 @@ import { PLATFORMS_DIR_NAME, PACKAGE_JSON_FILE_NAME } from "../../../constants"; export class PreviewAppPluginsService implements IPreviewAppPluginsService { private previewAppVersionWarnings: IDictionary = {}; - constructor(private $fs: IFileSystem, + constructor(private $errors: IErrors, + private $fs: IFileSystem, private $logger: ILogger, private $pluginsService: IPluginsService) { } - public async comparePluginsOnDevice(data: IPreviewAppLiveSyncData, device: Device): Promise { + public getPluginsUsageWarnings(data: IPreviewAppLiveSyncData, device: Device): string[] { + if (!device) { + this.$errors.failWithoutHelp("No device provided."); + } + + if (!device.previewAppVersion) { + this.$errors.failWithoutHelp("No version of preview app provided."); + } + if (!this.previewAppVersionWarnings[device.previewAppVersion]) { const devicePlugins = this.getDevicePlugins(device); const localPlugins = this.getLocalPlugins(data.projectDir); @@ -27,7 +36,12 @@ export class PreviewAppPluginsService implements IPreviewAppPluginsService { this.previewAppVersionWarnings[device.previewAppVersion] = warnings; } - this.previewAppVersionWarnings[device.previewAppVersion].map(warning => this.$logger.warn(warning)); + return this.previewAppVersionWarnings[device.previewAppVersion]; + } + + public async comparePluginsOnDevice(data: IPreviewAppLiveSyncData, device: Device): Promise { + const warnings = this.getPluginsUsageWarnings(data, device); + _.map(warnings, warning => this.$logger.warn(warning)); } public getExternalPlugins(device: Device): string[] { @@ -60,7 +74,7 @@ export class PreviewAppPluginsService implements IPreviewAppPluginsService { } private getWarningForPlugin(data: IPreviewAppLiveSyncData, localPlugin: string, localPluginVersion: string, devicePluginVersion: string, device: Device): string { - if (data && data.appFilesUpdaterOptions && data.appFilesUpdaterOptions.bundle) { + if (data && data.bundle) { const pluginPackageJsonPath = path.join(data.projectDir, NODE_MODULES_DIR_NAME, localPlugin, PACKAGE_JSON_FILE_NAME); const isNativeScriptPlugin = this.$pluginsService.isNativeScriptPlugin(pluginPackageJsonPath); if (!isNativeScriptPlugin || (isNativeScriptPlugin && !this.hasNativeCode(localPlugin, device.platform, data.projectDir))) { diff --git a/lib/services/livesync/playground/preview-sdk-service.ts b/lib/services/livesync/playground/preview-sdk-service.ts index 603f1bbae5..5947e11632 100644 --- a/lib/services/livesync/playground/preview-sdk-service.ts +++ b/lib/services/livesync/playground/preview-sdk-service.ts @@ -1,7 +1,6 @@ import { MessagingService, Config, Device, DeviceConnectedMessage, SdkCallbacks, ConnectedDevices, FilesPayload } from "nativescript-preview-sdk"; import { PubnubKeys } from "./preview-app-constants"; import { EventEmitter } from "events"; -import { DEVICE_LOG_EVENT_NAME } from "../../../common/constants"; const pako = require("pako"); export class PreviewSdkService extends EventEmitter implements IPreviewSdkService { @@ -12,7 +11,8 @@ export class PreviewSdkService extends EventEmitter implements IPreviewSdkServic constructor(private $config: IConfiguration, private $httpClient: Server.IHttpClient, private $logger: ILogger, - private $previewDevicesService: IPreviewDevicesService) { + private $previewDevicesService: IPreviewDevicesService, + private $previewAppLogProvider: IPreviewAppLogProvider) { super(); } @@ -61,9 +61,7 @@ export class PreviewSdkService extends EventEmitter implements IPreviewSdkServic this.$logger.trace("Received onLogSdkMessage message: ", log); }, onLogMessage: (log: string, deviceName: string, deviceId: string) => { - const device = this.$previewDevicesService.getDeviceById(deviceId); - this.emit(DEVICE_LOG_EVENT_NAME, log, deviceId, device ? device.platform : ""); - this.$logger.info(`LOG from device ${deviceName}: ${log}`); + this.$previewAppLogProvider.logData(log, deviceName, deviceId); }, onRestartMessage: () => { this.$logger.trace("Received onRestartMessage event."); diff --git a/lib/services/platform-service.ts b/lib/services/platform-service.ts index 0c7e758f3a..c594ba9971 100644 --- a/lib/services/platform-service.ts +++ b/lib/services/platform-service.ts @@ -818,10 +818,10 @@ export class PlatformService extends EventEmitter implements IPlatformService { private shouldPersistWebpackFiles(platform: string, projectData: IProjectData, prepareInfo: IPrepareInfo, appFilesUpdaterOptions: IAppFilesUpdaterOptions, nativePrepare: INativePrepare): boolean { const hasPlatformDirectory = this.hasPlatformDirectory(platform, projectData); const isWebpackWatcherStarted = this.$usbLiveSyncService.isInitialized; - const hasNativePlatformStatus = !prepareInfo || !prepareInfo.nativePlatformStatus; + const hasNativePlatformStatus = prepareInfo && prepareInfo.nativePlatformStatus; const requiresPlatformAdd = prepareInfo && prepareInfo.nativePlatformStatus === constants.NativePlatformStatus.requiresPlatformAdd; const shouldAddNativePlatform = !nativePrepare || !nativePrepare.skipNativePrepare; - const shouldAddPlatform = hasNativePlatformStatus || (requiresPlatformAdd && shouldAddNativePlatform); + const shouldAddPlatform = !hasNativePlatformStatus || (requiresPlatformAdd && shouldAddNativePlatform); const result = appFilesUpdaterOptions.bundle && isWebpackWatcherStarted && hasPlatformDirectory && shouldAddPlatform; return result; } diff --git a/lib/services/prepare-platform-native-service.ts b/lib/services/prepare-platform-native-service.ts index 1c788c9ff9..e1f01e57b7 100644 --- a/lib/services/prepare-platform-native-service.ts +++ b/lib/services/prepare-platform-native-service.ts @@ -19,6 +19,8 @@ export class PreparePlatformNativeService extends PreparePlatformService impleme info.platformData.platformProjectService.ensureConfigurationFileInAppResources(info.projectData); await info.platformData.platformProjectService.interpolateData(info.projectData, info.config); info.platformData.platformProjectService.afterCreateProject(info.platformData.projectRoot, info.projectData); + this.$projectChangesService.setNativePlatformStatus(info.platformData.normalizedPlatformName, info.projectData, + { nativePlatformStatus: constants.NativePlatformStatus.requiresPrepare }); } public async preparePlatform(config: IPreparePlatformJSInfo): Promise { @@ -111,7 +113,7 @@ export class PreparePlatformNativeService extends PreparePlatformService impleme } const previousPrepareInfo = this.$projectChangesService.getPrepareInfo(platform, projectData); - if (!previousPrepareInfo) { + if (!previousPrepareInfo || previousPrepareInfo.nativePlatformStatus !== constants.NativePlatformStatus.alreadyPrepared) { return; } diff --git a/lib/services/project-changes-service.ts b/lib/services/project-changes-service.ts index fd828b92bd..ac3be05546 100644 --- a/lib/services/project-changes-service.ts +++ b/lib/services/project-changes-service.ts @@ -173,8 +173,13 @@ export class ProjectChangesService implements IProjectChangesService { this._prepareInfo = this._prepareInfo || this.getPrepareInfo(platform, projectData); if (this._prepareInfo) { this._prepareInfo.nativePlatformStatus = addedPlatform.nativePlatformStatus; - this.savePrepareInfo(platform, projectData); + } else { + this._prepareInfo = { + nativePlatformStatus: addedPlatform.nativePlatformStatus + }; } + + this.savePrepareInfo(platform, projectData); } private async ensurePrepareInfo(platform: string, projectData: IProjectData, projectChangesOptions: IProjectChangesOptions): Promise { diff --git a/lib/services/project-templates-service.ts b/lib/services/project-templates-service.ts index 3efa82d306..30a655b197 100644 --- a/lib/services/project-templates-service.ts +++ b/lib/services/project-templates-service.ts @@ -12,42 +12,33 @@ export class ProjectTemplatesService implements IProjectTemplatesService { private $logger: ILogger, private $packageInstallationManager: IPackageInstallationManager, private $pacoteService: IPacoteService, - private $errors: IErrors) { } + private $errors: IErrors, + private $packageManager: INodePackageManager) { } - public async prepareTemplate(originalTemplateName: string, projectDir: string): Promise { - if (!originalTemplateName) { - originalTemplateName = constants.RESERVED_TEMPLATE_NAMES["default"]; + public async prepareTemplate(templateValue: string, projectDir: string): Promise { + if (!templateValue) { + templateValue = constants.RESERVED_TEMPLATE_NAMES["default"]; } - // support @ syntax, for example typescript@1.0.0 - // support @ syntax, for example @nativescript/vue-template@1.0.0 - const lastIndexOfAtSign = originalTemplateName.lastIndexOf("@"); - let name = originalTemplateName; - let version = ""; - if (lastIndexOfAtSign > 0) { - name = originalTemplateName.substr(0, lastIndexOfAtSign); - version = originalTemplateName.substr(lastIndexOfAtSign + 1); - } + const templateNameParts = await this.$packageManager.getPackageNameParts(templateValue); + templateValue = constants.RESERVED_TEMPLATE_NAMES[templateNameParts.name] || templateNameParts.name; - const templateName = constants.RESERVED_TEMPLATE_NAMES[name.toLowerCase()] || name; - if (!this.$fs.exists(templateName)) { - version = version || await this.$packageInstallationManager.getLatestCompatibleVersion(templateName); - } + const version = templateNameParts.version || await this.$packageInstallationManager.getLatestCompatibleVersionSafe(templateValue); + const fullTemplateName = await this.$packageManager.getPackageFullName({ name: templateValue, version: version }); - const fullTemplateName = version ? `${templateName}@${version}` : templateName; const templatePackageJsonContent = await this.getTemplatePackageJsonContent(fullTemplateName); const templateVersion = await this.getTemplateVersion(fullTemplateName); let templatePath = null; if (templateVersion === constants.TemplateVersions.v1) { - templatePath = await this.prepareNativeScriptTemplate(templateName, version, projectDir); + templatePath = await this.prepareNativeScriptTemplate(templateValue, version, projectDir); // this removes dependencies from templates so they are not copied to app folder this.$fs.deleteDirectory(path.join(templatePath, constants.NODE_MODULES_FOLDER_NAME)); } - await this.$analyticsService.track("Template used for project creation", templateName); + await this.$analyticsService.track("Template used for project creation", templateValue); - const templateNameToBeTracked = this.getTemplateNameToBeTracked(templateName, templatePackageJsonContent); + const templateNameToBeTracked = this.getTemplateNameToBeTracked(templateValue, templatePackageJsonContent); if (templateNameToBeTracked) { await this.$analyticsService.trackEventActionInGoogleAnalytics({ action: constants.TrackActionNames.CreateProject, @@ -61,7 +52,7 @@ export class ProjectTemplatesService implements IProjectTemplatesService { }); } - return { templateName, templatePath, templateVersion, templatePackageJsonContent, version }; + return { templateName: templateValue, templatePath, templateVersion, templatePackageJsonContent, version }; } private async getTemplateVersion(templateName: string): Promise { diff --git a/lib/yarn-package-manager.ts b/lib/yarn-package-manager.ts index 4897cb13b9..661ab57e91 100644 --- a/lib/yarn-package-manager.ts +++ b/lib/yarn-package-manager.ts @@ -2,18 +2,18 @@ import * as path from "path"; import { BasePackageManager } from "./base-package-manager"; import { exported } from './common/decorators'; -export class YarnPackageManager extends BasePackageManager implements INodePackageManager { +export class YarnPackageManager extends BasePackageManager { constructor( $childProcess: IChildProcess, private $errors: IErrors, - private $fs: IFileSystem, + $fs: IFileSystem, $hostInfo: IHostInfo, private $httpClient: Server.IHttpClient, private $logger: ILogger, $pacoteService: IPacoteService ) { - super($childProcess, $hostInfo, $pacoteService, 'yarn'); + super($childProcess, $fs, $hostInfo, $pacoteService, 'yarn'); } @exported("yarn") diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 4087ae3d71..0a16c041d9 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -442,12 +442,12 @@ "integrity": "sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk=" }, "anymatch": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", - "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", "requires": { - "micromatch": "^2.1.5", - "normalize-path": "^2.0.0" + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" } }, "aproba": { @@ -465,12 +465,9 @@ } }, "arr-diff": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", - "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "requires": { - "arr-flatten": "^1.0.1" - } + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" }, "arr-flatten": { "version": "1.1.0", @@ -510,9 +507,9 @@ "dev": true }, "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=" + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" }, "arrify": { "version": "1.0.1", @@ -669,16 +666,6 @@ "is-data-descriptor": "^1.0.0", "kind-of": "^6.0.2" } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" } } }, @@ -850,13 +837,30 @@ } }, "braces": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", - "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", "requires": { - "expand-range": "^1.8.1", - "preserve": "^0.2.0", - "repeat-element": "^1.1.2" + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } } }, "browser-stdout": { @@ -960,13 +964,6 @@ "to-object-path": "^0.3.0", "union-value": "^1.0.0", "unset-value": "^1.0.0" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - } } }, "caller-path": { @@ -1077,19 +1074,23 @@ "dev": true }, "chokidar": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", - "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", + "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", "requires": { - "anymatch": "^1.3.0", + "anymatch": "^2.0.0", "async-each": "^1.0.0", - "fsevents": "^1.0.0", - "glob-parent": "^2.0.0", + "braces": "^2.3.0", + "fsevents": "^1.2.2", + "glob-parent": "^3.1.0", "inherits": "^2.0.1", "is-binary-path": "^1.0.0", - "is-glob": "^2.0.0", + "is-glob": "^4.0.0", + "lodash.debounce": "^4.0.8", + "normalize-path": "^2.1.1", "path-is-absolute": "^1.0.0", - "readdirp": "^2.0.0" + "readdirp": "^2.0.0", + "upath": "^1.0.5" } }, "chownr": { @@ -1121,11 +1122,6 @@ "requires": { "is-descriptor": "^0.1.0" } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" } } }, @@ -1513,16 +1509,6 @@ "is-data-descriptor": "^1.0.0", "kind-of": "^6.0.2" } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" } } }, @@ -2050,19 +2036,86 @@ "dev": true }, "expand-brackets": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", - "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", "requires": { - "is-posix-bracket": "^0.1.0" + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } } }, "expand-range": { "version": "1.8.2", "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, "requires": { "fill-range": "^2.1.0" + }, + "dependencies": { + "fill-range": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", + "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", + "dev": true, + "requires": { + "is-number": "^2.1.0", + "isobject": "^2.0.0", + "randomatic": "^3.0.0", + "repeat-element": "^1.1.2", + "repeat-string": "^1.5.2" + } + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } } }, "extend": { @@ -2110,11 +2163,62 @@ } }, "extglob": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", - "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", "requires": { - "is-extglob": "^1.0.0" + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } } }, "extsprintf": { @@ -2188,18 +2292,28 @@ "filename-regex": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", - "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=" + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true }, "fill-range": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", - "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", "requires": { - "is-number": "^2.1.0", - "isobject": "^2.0.0", - "randomatic": "^3.0.0", - "repeat-element": "^1.1.2", - "repeat-string": "^1.5.2" + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } } }, "find-up": { @@ -2291,6 +2405,7 @@ "version": "0.1.5", "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, "requires": { "for-in": "^1.0.1" } @@ -3002,17 +3117,55 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, "requires": { "glob-parent": "^2.0.0", "is-glob": "^2.0.0" + }, + "dependencies": { + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "^2.0.0" + } + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + } } }, "glob-parent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", "requires": { - "is-glob": "^2.0.0" + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "requires": { + "is-extglob": "^2.1.0" + } + } } }, "global": { @@ -3349,12 +3502,137 @@ "strip-bom": "^2.0.0" }, "dependencies": { + "anymatch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "dev": true, + "requires": { + "micromatch": "^2.1.5", + "normalize-path": "^2.0.0" + } + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "^1.0.1" + } + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "requires": { + "expand-range": "^1.8.1", + "preserve": "^0.2.0", + "repeat-element": "^1.1.2" + } + }, + "chokidar": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "dev": true, + "requires": { + "anymatch": "^1.3.0", + "async-each": "^1.0.0", + "fsevents": "^1.0.0", + "glob-parent": "^2.0.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^2.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0" + } + }, "es6-promise": { "version": "0.1.2", "resolved": "http://registry.npmjs.org/es6-promise/-/es6-promise-0.1.2.tgz", "integrity": "sha1-8RLCn+paCZhTn8tqL9IUQ9KPBfc=", "dev": true }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "requires": { + "is-posix-bracket": "^0.1.0" + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "^2.0.0" + } + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "^2.0.0", + "array-unique": "^0.2.1", + "braces": "^1.8.2", + "expand-brackets": "^0.1.4", + "extglob": "^0.3.1", + "filename-regex": "^2.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.1", + "kind-of": "^3.0.2", + "normalize-path": "^2.0.1", + "object.omit": "^2.0.0", + "parse-glob": "^3.0.4", + "regex-cache": "^0.4.2" + } + }, "rimraf": { "version": "2.2.6", "resolved": "http://registry.npmjs.org/rimraf/-/rimraf-2.2.6.tgz", @@ -3427,13 +3705,6 @@ "get-value": "^2.0.6", "has-values": "^1.0.0", "isobject": "^3.0.0" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - } } }, "has-values": { @@ -3445,24 +3716,6 @@ "kind-of": "^4.0.0" }, "dependencies": { - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, "kind-of": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", @@ -3913,6 +4166,16 @@ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "requires": { "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } } }, "is-arrayish": { @@ -3952,6 +4215,16 @@ "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "requires": { "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } } }, "is-descriptor": { @@ -3974,12 +4247,14 @@ "is-dotfile": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", - "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=" + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true }, "is-equal-shallow": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, "requires": { "is-primitive": "^2.0.0" } @@ -3990,9 +4265,9 @@ "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" }, "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" }, "is-finite": { "version": "1.0.2", @@ -4014,11 +4289,11 @@ "integrity": "sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU=" }, "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", "requires": { - "is-extglob": "^1.0.0" + "is-extglob": "^2.1.1" } }, "is-my-ip-valid": { @@ -4041,11 +4316,21 @@ } }, "is-number": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", - "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "requires": { "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } } }, "is-path-cwd": { @@ -4078,24 +4363,19 @@ "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "requires": { "isobject": "^3.0.1" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - } } }, "is-posix-bracket": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", - "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=" + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true }, "is-primitive": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", - "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=" + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true }, "is-promise": { "version": "2.1.0", @@ -4140,12 +4420,9 @@ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "requires": { - "isarray": "1.0.0" - } + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" }, "isstream": { "version": "0.1.2", @@ -4391,12 +4668,9 @@ "dev": true }, "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" }, "lcid": { "version": "1.0.0", @@ -4518,6 +4792,11 @@ "lodash._isiterateecall": "^3.0.0" } }, + "lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" + }, "lodash.get": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", @@ -4778,7 +5057,8 @@ "math-random": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.1.tgz", - "integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w=" + "integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w=", + "dev": true }, "media-typer": { "version": "0.3.0", @@ -4818,23 +5098,23 @@ "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" }, "micromatch": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", - "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "requires": { - "arr-diff": "^2.0.0", - "array-unique": "^0.2.1", - "braces": "^1.8.2", - "expand-brackets": "^0.1.4", - "extglob": "^0.3.1", - "filename-regex": "^2.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.1", - "kind-of": "^3.0.2", - "normalize-path": "^2.0.1", - "object.omit": "^2.0.0", - "parse-glob": "^3.0.4", - "regex-cache": "^0.4.2" + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" } }, "mime": { @@ -5083,23 +5363,6 @@ "regex-not": "^1.0.0", "snapdragon": "^0.8.1", "to-regex": "^3.0.1" - }, - "dependencies": { - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" - } } }, "natives": { @@ -5319,6 +5582,14 @@ "requires": { "is-descriptor": "^0.1.0" } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -5328,19 +5599,13 @@ "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", "requires": { "isobject": "^3.0.0" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - } } }, "object.omit": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, "requires": { "for-own": "^0.1.4", "is-extendable": "^0.1.1" @@ -5352,13 +5617,6 @@ "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", "requires": { "isobject": "^3.0.1" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - } } }, "on-finished": { @@ -5647,11 +5905,29 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, "requires": { "glob-base": "^0.3.0", "is-dotfile": "^1.0.0", "is-extglob": "^1.0.0", "is-glob": "^2.0.0" + }, + "dependencies": { + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + } } }, "parse-headers": { @@ -5682,6 +5958,11 @@ "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=" + }, "path-exists": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", @@ -5883,7 +6164,8 @@ "preserve": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=" + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true }, "process": { "version": "0.5.2", @@ -6078,9 +6360,10 @@ "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" }, "randomatic": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.0.tgz", - "integrity": "sha512-KnGPVE0lo2WoXxIZ7cPR8YBpiol4gsSuOwDSg410oHh80ZMp5EiypNqL2K4Z77vJn6lB5rap7IkAmcUlalcnBQ==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", + "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", + "dev": true, "requires": { "is-number": "^4.0.0", "kind-of": "^6.0.0", @@ -6090,12 +6373,8 @@ "is-number": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==" - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true } } }, @@ -6166,256 +6445,6 @@ "graceful-fs": "^4.1.11", "micromatch": "^3.1.10", "readable-stream": "^2.0.2" - }, - "dependencies": { - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - } } }, "readline2": { @@ -6477,6 +6506,7 @@ "version": "0.4.4", "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "dev": true, "requires": { "is-equal-shallow": "^0.1.3" } @@ -6650,7 +6680,7 @@ }, "safe-regex": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", "requires": { "ret": "~0.1.10" @@ -6970,16 +7000,6 @@ "is-data-descriptor": "^1.0.0", "kind-of": "^6.0.2" } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" } } }, @@ -6989,6 +7009,16 @@ "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", "requires": { "kind-of": "^3.2.0" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } } }, "sntp": { @@ -7520,6 +7550,16 @@ "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", "requires": { "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } } }, "to-regex": { @@ -7540,16 +7580,6 @@ "requires": { "is-number": "^3.0.0", "repeat-string": "^1.6.1" - }, - "dependencies": { - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "requires": { - "kind-of": "^3.0.2" - } - } } }, "tough-cookie": { @@ -7798,11 +7828,6 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" } } }, @@ -7842,6 +7867,11 @@ } } }, + "upath": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz", + "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==" + }, "urix": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", @@ -8136,4 +8166,4 @@ "integrity": "sha512-99p+ohUBZ2Es0AXrw/tpazMcJ0/acpdQXr0UPrVWF0p7i8XiOYvjiXTdwXUVCTPopBGCSDtWBzOoYNPtF3z/8w==" } } -} \ No newline at end of file +} diff --git a/package.json b/package.json index 40b7466647..b83cf3f5a0 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "@nativescript/schematics-executor": "0.0.2", "byline": "4.2.1", "chalk": "1.1.0", - "chokidar": "1.7.0", + "chokidar": "2.0.4", "cli-table": "https://github.com/telerik/cli-table/tarball/v0.3.1.2", "color": "3.0.0", "colors": "1.1.2", @@ -130,4 +130,4 @@ "engines": { "node": ">=8.0.0 <11.0.0" } -} \ No newline at end of file +} diff --git a/test/node-package-manager.ts b/test/node-package-manager.ts new file mode 100644 index 0000000000..48b3c6eb81 --- /dev/null +++ b/test/node-package-manager.ts @@ -0,0 +1,88 @@ +import { Yok } from "../lib/common/yok"; +import * as stubs from "./stubs"; +import { assert } from "chai"; +import { NodePackageManager } from "../lib/node-package-manager"; + +function createTestInjector(configuration: { +} = {}): IInjector { + const injector = new Yok(); + injector.register("hostInfo", {}); + injector.register("errors", stubs.ErrorsStub); + injector.register("logger", stubs.LoggerStub); + injector.register("childProcess", stubs.ChildProcessStub); + injector.register("httpClient", {}); + injector.register("fs", stubs.FileSystemStub); + injector.register("npm", NodePackageManager); + + return injector; +} + +describe("node-package-manager", () => { + + describe("getPackageNameParts", () => { + [ + { + name: "should return both name and version when valid fullName passed", + templateFullName: "some-template@1.0.0", + expectedVersion: "1.0.0", + expectedName: "some-template", + }, + { + name: "should return both name and version when valid fullName with scope passed", + templateFullName: "@nativescript/some-template@1.0.0", + expectedVersion: "1.0.0", + expectedName: "@nativescript/some-template", + }, + { + name: "should return only name when version is not specified and the template is scoped", + templateFullName: "@nativescript/some-template", + expectedVersion: "", + expectedName: "@nativescript/some-template", + }, + { + name: "should return only name when version is not specified", + templateFullName: "some-template", + expectedVersion: "", + expectedName: "some-template", + } + ].forEach(testCase => { + it(testCase.name, async () => { + const testInjector = createTestInjector(); + const npm = testInjector.resolve("npm"); + const templateNameParts = await npm.getPackageNameParts(testCase.templateFullName); + assert.strictEqual(templateNameParts.name, testCase.expectedName); + assert.strictEqual(templateNameParts.version, testCase.expectedVersion); + }); + }); + }); + + describe("getPackageFullName", () => { + [ + { + name: "should return name and version when specified", + templateName: "some-template", + templateVersion: "1.0.0", + expectedFullName: "some-template@1.0.0", + }, + { + name: "should return only the github url when no version specified", + templateName: "https://github.com/NativeScript/template-drawer-navigation-ng#master", + templateVersion: "", + expectedFullName: "https://github.com/NativeScript/template-drawer-navigation-ng#master", + }, + { + name: "should return only the name when no version specified", + templateName: "some-template", + templateVersion: "", + expectedFullName: "some-template", + } + ].forEach(testCase => { + it(testCase.name, async () => { + const testInjector = createTestInjector(); + const npm = testInjector.resolve("npm"); + const templateFullName = await npm.getPackageFullName({ name: testCase.templateName, version: testCase.templateVersion }); + assert.strictEqual(templateFullName, testCase.expectedFullName); + }); + }); + }); +}); diff --git a/test/platform-service.ts b/test/platform-service.ts index c5f253c878..16881a7d57 100644 --- a/test/platform-service.ts +++ b/test/platform-service.ts @@ -921,6 +921,7 @@ describe('Platform Service Tests', () => { appResourcesDestinationDirectoryPath: testDirData.appResourcesFolderPath, normalizedPlatformName: "Android", projectRoot: testDirData.tempFolder, + configurationFileName: "configFileName", platformProjectService: { prepareProject: (): any => null, prepareAppResources: (): any => null, diff --git a/test/project-changes-service.ts b/test/project-changes-service.ts index 8dd5f7946d..47eae49639 100644 --- a/test/project-changes-service.ts +++ b/test/project-changes-service.ts @@ -176,4 +176,16 @@ describe("Project Changes Service Tests", () => { assert.isFalse(!!androidChanges.signingChanged, "Android signingChanged expected to be false"); }); }); + + describe("setNativePlatformStatus", () => { + it("creates prepare info and sets only the native platform status when there isn't an existing prepare info", () => { + for (const platform of ["ios", "android"]) { + serviceTest.projectChangesService.setNativePlatformStatus(platform, serviceTest.projectData, { nativePlatformStatus: Constants.NativePlatformStatus.requiresPrepare }); + + const actualPrepareInfo = serviceTest.projectChangesService.getPrepareInfo(platform, serviceTest.projectData); + + assert.deepEqual(actualPrepareInfo, { nativePlatformStatus: Constants.NativePlatformStatus.requiresPrepare }); + } + }); + }); }); diff --git a/test/project-templates-service.ts b/test/project-templates-service.ts index ec8d4b55f0..b136079513 100644 --- a/test/project-templates-service.ts +++ b/test/project-templates-service.ts @@ -10,7 +10,12 @@ let isDeleteDirectoryCalledForNodeModulesDir = false; const nativeScriptValidatedTemplatePath = "nsValidatedTemplatePath"; const compatibleTemplateVersion = "1.2.3"; -function createTestInjector(configuration: { shouldNpmInstallThrow?: boolean, packageJsonContent?: any } = {}): IInjector { +function createTestInjector(configuration: { + shouldNpmInstallThrow?: boolean, + packageJsonContent?: any, + packageVersion?: string, + packageName?: string +} = {}): IInjector { const injector = new Yok(); injector.register("errors", stubs.ErrorsStub); injector.register("logger", stubs.LoggerStub); @@ -26,28 +31,38 @@ function createTestInjector(configuration: { shouldNpmInstallThrow?: boolean, pa } }); - injector.register("npm", { - install: (packageName: string, pathToSave: string, config?: any) => { + class NpmStub extends stubs.NodePackageManagerStub { + public async install(packageName: string, pathToSave: string, config: INodePackageManagerInstallOptions): Promise { if (configuration.shouldNpmInstallThrow) { throw new Error("NPM install throws error."); } - return "sample result"; + return { name: "Some Result", version: "1" }; } - }); + async getPackageNameParts(fullPackageName: string): Promise { + return { + name: configuration.packageName || fullPackageName, + version: configuration.packageVersion || "" + }; + } + } + + injector.register("packageManager", NpmStub); - injector.register("packageInstallationManager", { - install: (packageName: string, options?: INpmInstallOptions) => { + class NpmInstallationManagerStub extends stubs.PackageInstallationManagerStub { + async install(packageName: string, pathToSave?: string, options?: INpmInstallOptions): Promise { if (configuration.shouldNpmInstallThrow) { throw new Error("NPM install throws error."); } return Promise.resolve(nativeScriptValidatedTemplatePath); - }, - getLatestCompatibleVersion: (packageName: string) => { + } + async getLatestCompatibleVersionSafe(packageName: string): Promise { return compatibleTemplateVersion; } - }); + } + + injector.register("packageInstallationManager", NpmInstallationManagerStub); injector.register("projectTemplatesService", ProjectTemplatesService); @@ -67,7 +82,7 @@ function createTestInjector(configuration: { shouldNpmInstallThrow?: boolean, pa return injector; } -describe("project-templates-service", () => { +describe.only("project-templates-service", () => { beforeEach(() => { isDeleteDirectoryCalledForNodeModulesDir = false; }); @@ -253,7 +268,7 @@ describe("project-templates-service", () => { } ].forEach(testCase => { it(testCase.name, async () => { - const testInjector = createTestInjector(); + const testInjector = createTestInjector({ packageVersion: testCase.expectedVersion, packageName: testCase.expectedTemplateName }); const projectTemplatesService = testInjector.resolve("projectTemplatesService"); const { version, templateName } = await projectTemplatesService.prepareTemplate(testCase.templateName, "tempFolder"); assert.strictEqual(version, testCase.expectedVersion); diff --git a/test/services/android-debug-service.ts b/test/services/android-debug-service.ts index f8aa1e90ed..234d8aa26c 100644 --- a/test/services/android-debug-service.ts +++ b/test/services/android-debug-service.ts @@ -27,6 +27,7 @@ const createTestInjector = (): IInjector => { testInjector.register("devicesService", {}); testInjector.register("errors", stubs.ErrorsStub); testInjector.register("logger", stubs.LoggerStub); + testInjector.register("npm", stubs.NodePackageManagerStub); testInjector.register("androidDeviceDiscovery", {}); testInjector.register("androidProcessService", {}); testInjector.register("net", {}); diff --git a/test/services/playground/preview-app-livesync-service.ts b/test/services/playground/preview-app-livesync-service.ts index d4ab2e2551..95d7008458 100644 --- a/test/services/playground/preview-app-livesync-service.ts +++ b/test/services/playground/preview-app-livesync-service.ts @@ -60,11 +60,8 @@ const defaultProjectFiles = [ ]; const syncFilesMockData = { projectDir: projectDirPath, - appFilesUpdaterOptions: { - release: false, - bundle: false, - useHotModuleReload: false - }, + bundle: false, + useHotModuleReload: false, env: {} }; @@ -182,7 +179,7 @@ async function initialSync(input?: IActInput) { const { previewAppLiveSyncService, previewSdkService, actOptions } = input; const syncFilesData = _.cloneDeep(syncFilesMockData); - syncFilesData.appFilesUpdaterOptions.useHotModuleReload = actOptions.hmr; + syncFilesData.useHotModuleReload = actOptions.hmr; await previewAppLiveSyncService.initialize(syncFilesData); if (actOptions.callGetInitialFiles) { await previewSdkService.getInitialFiles(deviceMockData); @@ -195,7 +192,7 @@ async function syncFiles(input?: IActInput) { const { previewAppLiveSyncService, previewSdkService, projectFiles, actOptions } = input; const syncFilesData = _.cloneDeep(syncFilesMockData); - syncFilesData.appFilesUpdaterOptions.useHotModuleReload = actOptions.hmr; + syncFilesData.useHotModuleReload = actOptions.hmr; await previewAppLiveSyncService.initialize(syncFilesData); if (actOptions.callGetInitialFiles) { await previewSdkService.getInitialFiles(deviceMockData); diff --git a/test/services/playground/preview-app-plugins-service.ts b/test/services/playground/preview-app-plugins-service.ts index 13087a0a7f..277b5be34b 100644 --- a/test/services/playground/preview-app-plugins-service.ts +++ b/test/services/playground/preview-app-plugins-service.ts @@ -4,6 +4,7 @@ import { Device } from "nativescript-preview-sdk"; import { assert } from "chai"; import * as util from "util"; import { PluginComparisonMessages } from "../../../lib/services/livesync/playground/preview-app-constants"; +import { ErrorsStub } from "../../stubs"; let readJsonParams: string[] = []; let warnParams: string[] = []; @@ -43,6 +44,7 @@ function createTestInjector(localPlugins: IStringDictionary, options?: { isNativ trace: () => ({}), warn: (message: string) => warnParams.push(message) }); + injector.register("errors", ErrorsStub); injector.register("previewAppPluginsService", PreviewAppPluginsService); return injector; } @@ -64,10 +66,8 @@ function createDevice(plugins: string): Device { function createPreviewLiveSyncData(options?: { bundle: boolean }) { return { projectDir, - appFilesUpdaterOptions: { - release: false, - bundle: options.bundle - }, + release: false, + bundle: options.bundle, env: {} }; } diff --git a/test/services/preview-devices-service.ts b/test/services/preview-devices-service.ts index 7fc2305115..ccc9339a66 100644 --- a/test/services/preview-devices-service.ts +++ b/test/services/preview-devices-service.ts @@ -3,14 +3,19 @@ import { PreviewDevicesService } from "../../lib/services/livesync/playground/de import { Device } from "nativescript-preview-sdk"; import { assert } from "chai"; import { DeviceDiscoveryEventNames } from "../../lib/common/constants"; -import { LoggerStub } from "../stubs"; +import { LoggerStub, ErrorsStub } from "../stubs"; let foundDevices: Device[] = []; let lostDevices: Device[] = []; function createTestInjector(): IInjector { const injector = new Yok(); + injector.register("errors", ErrorsStub); injector.register("previewDevicesService", PreviewDevicesService); + injector.register("previewAppLogProvider", { + on: () => ({}) + }); + injector.register("previewAppPluginsService", {}); injector.register("logger", LoggerStub); return injector; } diff --git a/test/services/preview-sdk-service.ts b/test/services/preview-sdk-service.ts index e4698c03e4..3385173648 100644 --- a/test/services/preview-sdk-service.ts +++ b/test/services/preview-sdk-service.ts @@ -9,6 +9,7 @@ const getPreviewSdkService = (): IPreviewSdkService => { testInjector.register("config", {}); testInjector.register("previewSdkService", PreviewSdkService); testInjector.register("previewDevicesService", {}); + testInjector.register("previewAppLogProvider", {}); testInjector.register("httpClient", { httpRequest: async (options: any, proxySettings?: IProxySettings): Promise => undefined }); diff --git a/test/stubs.ts b/test/stubs.ts index 9c38431f4b..aab3095ab6 100644 --- a/test/stubs.ts +++ b/test/stubs.ts @@ -243,16 +243,67 @@ export class PackageInstallationManagerStub implements IPackageInstallationManag return Promise.resolve(""); } + async getLatestCompatibleVersionSafe(packageName: string): Promise { + return Promise.resolve(""); + } + async getInspectorFromCache(name: string, projectDir: string): Promise { return Promise.resolve(""); } } +export class NodePackageManagerStub implements INodePackageManager { + constructor() { } + + public async install(packageName: string, pathToSave: string, config: INodePackageManagerInstallOptions): Promise { + return null; + } + + public async uninstall(packageName: string, config?: any, path?: string): Promise { + return ""; + } + + public async search(filter: string[], config: any): Promise { + return ""; + } + + public async view(packageName: string, config: Object): Promise { + return {}; + } + + public async isRegistered(packageName: string): Promise { + return true; + } + + public async getPackageNameParts(fullPackageName: string): Promise { + return { + name: fullPackageName, + version: "" + }; + } + + public async getPackageFullName(packageNameParts: INpmPackageNameParts): Promise { + return packageNameParts.version ? `${packageNameParts.name}@${packageNameParts.version}` : packageNameParts.name; + } + + public async searchNpms(keyword: string): Promise { + return null; + } + + public async getRegistryPackageData(packageName: string): Promise { + return null; + } + + public async getCachePath(): Promise { + return ""; + } +} + export class ProjectDataStub implements IProjectData { projectDir: string; projectName: string; get platformsDir(): string { - return this.plafromsDir; + return this.plafromsDir || (this.projectDir && path.join(this.projectDir, "platforms")) || ""; } set platformsDir(value) { this.plafromsDir = value; @@ -275,7 +326,7 @@ export class ProjectDataStub implements IProjectData { public initializeProjectData(projectDir?: string): void { this.projectDir = this.projectDir || projectDir; - this.projectIdentifiers = { android: "", ios: ""}; + this.projectIdentifiers = { android: "", ios: "" }; this.projectId = ""; } public initializeProjectDataFromContent(): void { @@ -429,7 +480,7 @@ export class PlatformsDataStub extends EventEmitter implements IPlatformsData { normalizedPlatformName: "", appDestinationDirectoryPath: "", deviceBuildOutputPath: "", - getValidBuildOutputData: (buildOptions: IBuildOutputOptions) => ({ packageNames: []}), + getValidBuildOutputData: (buildOptions: IBuildOutputOptions) => ({ packageNames: [] }), frameworkFilesExtensions: [], relativeToFrameworkConfigurationFilePath: "", fastLivesyncFileExtensions: []