From 2b7a26f6d64f37e80ef69b608114194a36060f80 Mon Sep 17 00:00:00 2001 From: rosen-vladimirov Date: Wed, 1 Feb 2017 13:01:28 +0200 Subject: [PATCH] Allow require of nativescript-cli as library The entry point of current cli is used only from `bin/tns`. In fact the `main` entry in package.json is used when you want to require the module, but CLI is never required. It's installed globally and spawned from it's bin dir (`bin` key in package.json defines which is the "entry" point when package is installed globally). So I've changed the entry point to a file, that does not use commandDispatcher - when requiring {N} CLI as library, we'll not execute commands. In order to allow executing specific device operations (like device detection through events), require the mobile-cli-lib's appbuilder bootstrap in the entry point. This will be fixed with other PR's and finally we'll not have to require this bootstrap. --- lib/common | 2 +- lib/nativescript-cli-lib-bootstrap.ts | 8 ++++++++ lib/nativescript-cli-lib.ts | 3 +++ package.json | 2 +- test/nativescript-cli-lib.ts | 24 ++++++++++++++++++++++++ 5 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 lib/nativescript-cli-lib-bootstrap.ts create mode 100644 lib/nativescript-cli-lib.ts create mode 100644 test/nativescript-cli-lib.ts diff --git a/lib/common b/lib/common index 188650c82b..5515997e5d 160000 --- a/lib/common +++ b/lib/common @@ -1 +1 @@ -Subproject commit 188650c82b3c7126993706b66af992e0182dfc7c +Subproject commit 5515997e5d7a31263f0f7145832fe5466f00ee63 diff --git a/lib/nativescript-cli-lib-bootstrap.ts b/lib/nativescript-cli-lib-bootstrap.ts new file mode 100644 index 0000000000..efaed1377c --- /dev/null +++ b/lib/nativescript-cli-lib-bootstrap.ts @@ -0,0 +1,8 @@ +require("./bootstrap"); + +$injector.overrideAlreadyRequiredModule = true; + +// Temporary!!! Should not require appbuilder's entry point of mobile-cli-lib, +// but once we separate logics in mobile-cli-lib, we should be able to require only specific bootstrap. +// Use this hack for now, as this will allow requiring {N} CLI as library directly and executing some device specific operations. +require("./common/appbuilder/proton-bootstrap"); diff --git a/lib/nativescript-cli-lib.ts b/lib/nativescript-cli-lib.ts new file mode 100644 index 0000000000..fd1aed9294 --- /dev/null +++ b/lib/nativescript-cli-lib.ts @@ -0,0 +1,3 @@ +require("./nativescript-cli-lib-bootstrap"); + +module.exports = $injector.publicApi; diff --git a/package.json b/package.json index c7e5cc5106..a4570e6dc5 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "tns": "./bin/tns", "nativescript": "./bin/tns" }, - "main": "./lib/nativescript-cli.js", + "main": "./lib/nativescript-cli-lib.js", "scripts": { "test": "node test-scripts/istanbul.js", "postinstall": "node postinstall.js", diff --git a/test/nativescript-cli-lib.ts b/test/nativescript-cli-lib.ts new file mode 100644 index 0000000000..a86bdce74d --- /dev/null +++ b/test/nativescript-cli-lib.ts @@ -0,0 +1,24 @@ +import { assert } from "chai"; +import * as fs from "fs"; +import * as path from "path"; +import * as childProcess from "child_process"; +const nodeArgs = require(path.join(__dirname, "..", "lib", "common", "scripts", "node-args")).getNodeArgs(); + +describe("nativescript-cli-lib", () => { + it("is main entry of the package", () => { + const packageJsonContent = fs.readFileSync(path.join(__dirname, "..", "package.json")).toString(); + const jsonContent = JSON.parse(packageJsonContent); + const expectedEntryPoint = "./lib/nativescript-cli-lib.js"; + assert.deepEqual(jsonContent.main, expectedEntryPoint); + }); + + it("resolves publicly available module - deviceEmitter, when it is required", () => { + const pathToEntryPoint = path.join(__dirname, "..", "lib", "nativescript-cli-lib.js").replace(/\\/g, "\\\\"); + // HACK: If we try to require the entry point directly, the below code will fail as mocha requires all test files before starting the tests. + // When the files are required, $injector.register adds each dependency to $injector's cache. + // For example $injector.register("errors", Errors) will add the errors module with its resolver (Errors) to $injector's cache. + // Calling $injector.require("errors", ), that's executed in our bootstrap, will fail, as the module errors is already in the cache. + // In order to workaround this problem, start new process and assert there. This way all files will not be required in it and $injector.require(...) will work correctly. + childProcess.execSync(`"${process.execPath}" ${nodeArgs.join(" ")} -e "var assert = require('chai').assert; var result = require('${pathToEntryPoint}'); assert.ok(result.deviceEmitter);"`); + }); +});