diff --git a/bin/ns-upgrade-tsconfig b/bin/ns-upgrade-tsconfig new file mode 100644 index 0000000..e8e093e --- /dev/null +++ b/bin/ns-upgrade-tsconfig @@ -0,0 +1,7 @@ +#!/usr/bin/env node +var path = require("path"); +var upgrader = require("../tsconfig-upgrader"); + +var projectDir = path.dirname(path.dirname(path.dirname(__dirname))); +var tsConfigPath = path.join(projectDir, "tsconfig.json"); +upgrader.migrateTsConfig(tsConfigPath, projectDir); diff --git a/bin/ns-upgrade-tsconfig.cmd b/bin/ns-upgrade-tsconfig.cmd new file mode 100644 index 0000000..2f7a4c2 --- /dev/null +++ b/bin/ns-upgrade-tsconfig.cmd @@ -0,0 +1 @@ +@node %~dp0\ns-upgrade-tsconfig %* diff --git a/package.json b/package.json index 3c8deac..dd233c0 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,15 @@ { "name": "nativescript-dev-typescript", - "version": "0.4.1", + "version": "0.4.2", "description": "TypeScript support for NativeScript projects. Install using `tns install typescript`.", "scripts": { "test": "exit 0", "postinstall": "node postinstall.js", "preuninstall": "node preuninstall.js" }, + "bin": { + "ns-upgrade-tsconfig": "./bin/ns-upgrade-tsconfig" + }, "nativescript": { "hooks": [ { diff --git a/postinstall.js b/postinstall.js index 1a95f6c..6f350e5 100644 --- a/postinstall.js +++ b/postinstall.js @@ -3,126 +3,31 @@ hook.postinstall(); var fs = require("fs"); var path = require("path"); - -var __migrations = [ - inlineSourceMapMigration, - addDomLibs, - addIterableToAngularProjects, -]; - +var upgrader = require("./tsconfig-upgrader"); var projectDir = hook.findProjectDir(); if (projectDir) { var tsconfigPath = path.join(projectDir, "tsconfig.json"); if (fs.existsSync(tsconfigPath)) { - migrateTsconfig(tsconfigPath); + upgrader.migrateTsConfig(tsconfigPath, projectDir); } else { createTsconfig(tsconfigPath); } - createReferenceFile(); + if (!upgrader.hasModules30(projectDir)) { + createReferenceFile(); + } installTypescript(); } function createReferenceFile() { var referenceFilePath = path.join(projectDir, "references.d.ts"), - content = '/// Needed for autocompletion and compilation.'; + content = "/// Needed for autocompletion and compilation."; if (!fs.existsSync(referenceFilePath)) { fs.appendFileSync(referenceFilePath, content); } } -function inlineSourceMapMigration(existingConfig, displayableTsconfigPath) { - if (existingConfig.compilerOptions) { - if ("sourceMap" in existingConfig["compilerOptions"]) { - delete existingConfig["compilerOptions"]["sourceMap"]; - console.warn("> Deleted \"compilerOptions.sourceMap\" setting in \"" + displayableTsconfigPath + "\"."); - console.warn("> Inline source maps will be used when building in Debug configuration from now on."); - } - } -} - -function addIterableToAngularProjects(existingConfig) { - var packageJsonPath = path.join(projectDir, "package.json"); - var packageJson = JSON.parse(fs.readFileSync(packageJsonPath)); - var dependencies = packageJson.dependencies || []; - - var hasAngular = Object.keys(dependencies).includes("nativescript-angular"); - var hasRelevantAngularVersion = /[4-9]\.\d+\.\d+/i.test(dependencies["@angular/core"]); - if (hasAngular && hasRelevantAngularVersion) { - console.log("Adding 'es2015.iterable' lib to tsconfig.json..."); - addTsLib(existingConfig, "es2015.iterable"); - } -} - -function addDomLibs(existingConfig) { - function relevantModulesVersion(version) { - return /[3-9]\.\d+\.\d+/i.test(version); - } - - function hasRelevantModulesDependency() { - var packageJsonPath = path.join(projectDir, "package.json"); - var packageJson = JSON.parse(fs.readFileSync(packageJsonPath)); - var dependencies = packageJson.dependencies || []; - - return relevantModulesVersion(dependencies["tns-core-modules"]); - } - - function hasRelevantModulesPackage() { - var packageJsonPath = path.join(projectDir, "node_modules", "tns-core-modules", "package.json"); - if (!fs.existsSync(packageJsonPath)) { - return false; - } - - var packageJson = JSON.parse(fs.readFileSync(packageJsonPath)); - return relevantModulesVersion(packageJson.version); - } - - if (hasRelevantModulesDependency() || hasRelevantModulesPackage()) { - console.log("Adding 'es6' lib to tsconfig.json..."); - addTsLib(existingConfig, "es6"); - console.log("Adding 'dom' lib to tsconfig.json..."); - addTsLib(existingConfig, "dom"); - } -} - -function addTsLib(existingConfig, libName) { - if (existingConfig.compilerOptions) { - var options = existingConfig.compilerOptions; - if (!options.lib) { - options.lib = []; - } - if (!options.lib.find(function(l) { - return libName.toLowerCase() === l.toLowerCase(); - })) { - options.lib.push(libName); - } - } -} - -function migrateTsconfig(tsconfigPath) { - var displayableTsconfigPath = path.relative(projectDir, tsconfigPath); - - function withTsConfig(action) { - var existingConfig = null; - try { - var existingConfigContents = fs.readFileSync(tsconfigPath); - existingConfig = JSON.parse(existingConfigContents); - } catch (e) { - console.error("Invalid " + displayableTsconfigPath + ": " + e); - return; - } - action(existingConfig); - fs.writeFileSync(tsconfigPath, JSON.stringify(existingConfig, null, 4)); - } - - withTsConfig(function(existingConfig) { - __migrations.forEach(function(migration) { - migration(existingConfig, displayableTsconfigPath); - }); - }); -} - function createTsconfig(tsconfigPath) { var tsconfig = {}; @@ -134,8 +39,7 @@ function createTsconfig(tsconfigPath) { noEmitHelpers: true, noEmitOnError: true, }; - addDomLibs(tsconfig); - addIterableToAngularProjects(tsconfig); + upgrader.migrateProject(tsconfig, tsconfigPath, projectDir); tsconfig.exclude = ["node_modules", "platforms", "**/*.aot.ts"]; diff --git a/tsconfig-upgrader.js b/tsconfig-upgrader.js new file mode 100644 index 0000000..fa5aba4 --- /dev/null +++ b/tsconfig-upgrader.js @@ -0,0 +1,126 @@ +var fs = require("fs"); +var path = require("path"); + +var __migrations = [ + inlineSourceMapMigration, + addDomLibs, + addIterableToAngularProjects, + addTnsCoreModulesPathMappings, +]; + +function migrateProject(tsConfig, tsconfigPath, projectDir) { + var displayableTsconfigPath = path.relative(projectDir, tsconfigPath); + __migrations.forEach(function(migration) { + migration(tsConfig, displayableTsconfigPath, projectDir); + }); +} +exports.migrateProject = migrateProject; + +function migrateTsConfig(tsconfigPath, projectDir) { + var displayableTsconfigPath = path.relative(projectDir, tsconfigPath); + + function withTsConfig(action) { + var existingConfig = null; + try { + var existingConfigContents = fs.readFileSync(tsconfigPath); + existingConfig = JSON.parse(existingConfigContents); + } catch (e) { + console.error("Invalid " + displayableTsconfigPath + ": " + e); + return; + } + action(existingConfig); + fs.writeFileSync(tsconfigPath, JSON.stringify(existingConfig, null, 4)); + } + + withTsConfig(function(existingConfig) { + migrateProject(existingConfig, displayableTsconfigPath, projectDir); + }); +} +exports.migrateTsConfig = migrateTsConfig; + +function inlineSourceMapMigration(existingConfig, displayableTsconfigPath) { + if (existingConfig.compilerOptions) { + if ("sourceMap" in existingConfig["compilerOptions"]) { + delete existingConfig["compilerOptions"]["sourceMap"]; + console.warn("> Deleted \"compilerOptions.sourceMap\" setting in \"" + displayableTsconfigPath + "\"."); + console.warn("> Inline source maps will be used when building in Debug configuration from now on."); + } + } +} + +function addIterableToAngularProjects(existingConfig, displayableTsconfigPath, projectDir) { + var packageJsonPath = path.join(projectDir, "package.json"); + var packageJson = JSON.parse(fs.readFileSync(packageJsonPath)); + var dependencies = packageJson.dependencies || []; + + var hasAngular = Object.keys(dependencies).includes("nativescript-angular"); + var hasRelevantAngularVersion = /[4-9]\.\d+\.\d+/i.test(dependencies["@angular/core"]); + if (hasAngular && hasRelevantAngularVersion) { + console.log("Adding 'es2015.iterable' lib to tsconfig.json..."); + addTsLib(existingConfig, "es2015.iterable"); + } +} + +function hasModules30(projectDir) { + function relevantModulesVersion(version) { + return /[3-9]\.\d+\.\d+/i.test(version); + } + + function hasRelevantModulesDependency() { + var packageJsonPath = path.join(projectDir, "package.json"); + var packageJson = JSON.parse(fs.readFileSync(packageJsonPath)); + var dependencies = packageJson.dependencies || []; + + return relevantModulesVersion(dependencies["tns-core-modules"]); + } + + function hasRelevantModulesPackage() { + var packageJsonPath = path.join(projectDir, "node_modules", "tns-core-modules", "package.json"); + if (!fs.existsSync(packageJsonPath)) { + return false; + } + + var packageJson = JSON.parse(fs.readFileSync(packageJsonPath)); + return relevantModulesVersion(packageJson.version); + } + + return hasRelevantModulesDependency() || hasRelevantModulesPackage(); +} +exports.hasModules30 = hasModules30; + +function addDomLibs(existingConfig, displayableTsconfigPath, projectDir) { + if (hasModules30(projectDir)) { + console.log("Adding 'es6' lib to tsconfig.json..."); + addTsLib(existingConfig, "es6"); + console.log("Adding 'dom' lib to tsconfig.json..."); + addTsLib(existingConfig, "dom"); + } +} + +function addTsLib(existingConfig, libName) { + if (existingConfig.compilerOptions) { + var options = existingConfig.compilerOptions; + if (!options.lib) { + options.lib = []; + } + if (!options.lib.find(function(l) { + return libName.toLowerCase() === l.toLowerCase(); + })) { + options.lib.push(libName); + } + } +} + +function addTnsCoreModulesPathMappings(existingConfig, displayableTsconfigPath, projectDir) { + if (hasModules30(projectDir)) { + console.log("Adding tns-core-modules path mappings lib to tsconfig.json..."); + existingConfig["compilerOptions"] = existingConfig["compilerOptions"] || {}; + var compilerOptions = existingConfig["compilerOptions"]; + compilerOptions["baseUrl"] = "."; + compilerOptions["paths"] = compilerOptions["paths"] || {}; + compilerOptions["paths"]["*"] = [ + "./node_modules/tns-core-modules/*", + "./node_modules/*" + ]; + } +}