UNPKG

nativescript

Version:

Command-line interface for building NativeScript projects

282 lines (272 loc) • 11.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.NativeAddSwiftCommand = exports.NativeAddObjectiveCCommand = exports.NativeAddKotlinCommand = exports.NativeAddJavaCommand = exports.NativeAddAndroidCommand = exports.NativeAddSingleCommand = exports.NativeAddCommand = void 0; const fs = require("fs"); const path = require("path"); const yok_1 = require("../common/yok"); const utils_1 = require("../common/utils"); const os_1 = require("os"); class NativeAddCommand { constructor($projectData, $logger, $errors) { this.$projectData = $projectData; this.$logger = $logger; this.$errors = $errors; this.allowedParameters = []; this.$projectData.initializeProjectData(); } async execute(args) { this.failWithUsage(); return Promise.resolve(); } failWithUsage() { this.$errors.failWithHelp("Usage: ns native add [swift|objective-c|java|kotlin] [class name]"); } async canExecute(args) { this.failWithUsage(); return false; } getIosSourcePathBase() { const resources = this.$projectData.getAppResourcesDirectoryPath(); return path.join(resources, "iOS", "src"); } getAndroidSourcePathBase() { const resources = this.$projectData.getAppResourcesDirectoryPath(); return path.join(resources, "Android", "src", "main", "java"); } } exports.NativeAddCommand = NativeAddCommand; class NativeAddSingleCommand extends NativeAddCommand { constructor($projectData, $logger, $errors) { super($projectData, $logger, $errors); } async canExecute(args) { if (!args || args.length !== 1) { this.failWithUsage(); } return true; } } exports.NativeAddSingleCommand = NativeAddSingleCommand; class NativeAddAndroidCommand extends NativeAddSingleCommand { constructor($projectData, $logger, $errors) { super($projectData, $logger, $errors); } getPackageName(className) { const lastDotIndex = className.lastIndexOf("."); if (lastDotIndex !== -1) { return className.substring(0, lastDotIndex); } return ""; } getClassSimpleName(className) { const lastDotIndex = className.lastIndexOf("."); if (lastDotIndex !== -1) { return className.substring(lastDotIndex + 1); } return className; } generateJavaClassContent(packageName, classSimpleName) { return ((packageName.length > 0 ? `package ${packageName};` : "") + ` import android.util.Log; public class ${classSimpleName} { public void logMessage() { Log.d("JS", "Hello from ${classSimpleName}!"); } } `); } generateKotlinClassContent(packageName, classSimpleName) { return ((packageName.length > 0 ? `package ${packageName};` : "") + ` import android.util.Log class ${classSimpleName} { fun logMessage() { Log.d("JS", "Hello from ${classSimpleName}!") } } `); } doJavaKotlin(className, extension) { const fileExt = extension == "java" ? extension : "kt"; const packageName = this.getPackageName(className); const classSimpleName = this.getClassSimpleName(className); const packagePath = path.join(this.getAndroidSourcePathBase(), ...packageName.split(".")); const filePath = path.join(packagePath, `${classSimpleName}.${fileExt}`); if (fs.existsSync(filePath)) { this.$errors.failWithHelp(`${extension} file '${filePath}' already exists.`); return; } if (extension == "kotlin" && !this.checkAndUpdateGradleProperties()) { return; } const fileContent = extension == "java" ? this.generateJavaClassContent(packageName, classSimpleName) : this.generateKotlinClassContent(packageName, classSimpleName); fs.mkdirSync(packagePath, { recursive: true }); fs.writeFileSync(filePath, fileContent); this.$logger.info(`${(0, utils_1.capitalizeFirstLetter)(extension)} file '${filePath}' generated successfully.`); } checkAndUpdateGradleProperties() { const resources = this.$projectData.getAppResourcesDirectoryPath(); const filePath = path.join(resources, "Android", "gradle.properties"); if (fs.existsSync(filePath)) { const fileContent = fs.readFileSync(filePath, "utf8"); const propertyRegex = /^useKotlin\s*=\s*(true|false)$/m; const match = propertyRegex.exec(fileContent); if (match) { const useKotlin = match[1]; if (useKotlin === "false") { this.$errors.failWithHelp("The useKotlin property is set to false. Stopping processing. Kotlin must be enabled in gradle.properties to use."); return false; } if (useKotlin === "true") { return true; } } else { fs.appendFileSync(filePath, `${os_1.EOL}useKotlin=true${os_1.EOL}`); this.$logger.info('Added "useKotlin=true" property to gradle.properties.'); } } else { fs.writeFileSync(filePath, `useKotlin=true${os_1.EOL}`); this.$logger.info('Created gradle.properties with "useKotlin=true" property.'); } return true; } } exports.NativeAddAndroidCommand = NativeAddAndroidCommand; class NativeAddJavaCommand extends NativeAddAndroidCommand { constructor($projectData, $logger, $errors) { super($projectData, $logger, $errors); } async execute(args) { this.doJavaKotlin(args[0], "java"); return Promise.resolve(); } } exports.NativeAddJavaCommand = NativeAddJavaCommand; class NativeAddKotlinCommand extends NativeAddAndroidCommand { constructor($projectData, $logger, $errors) { super($projectData, $logger, $errors); } async execute(args) { this.doJavaKotlin(args[0], "kotlin"); return Promise.resolve(); } } exports.NativeAddKotlinCommand = NativeAddKotlinCommand; class NativeAddObjectiveCCommand extends NativeAddSingleCommand { constructor($projectData, $logger, $errors) { super($projectData, $logger, $errors); } async execute(args) { this.doObjectiveC(args[0]); return Promise.resolve(); } doObjectiveC(className) { const iosSourceBase = this.getIosSourcePathBase(); const classFilePath = path.join(iosSourceBase, `${className}.m`); const headerFilePath = path.join(iosSourceBase, `${className}.h`); if (this.generateObjectiveCFiles(className, classFilePath, headerFilePath)) { // Modify/Generate moduleMap this.generateOrUpdateModuleMap(`${className}.h`, path.join(iosSourceBase, "module.modulemap")); } } generateOrUpdateModuleMap(headerFileName, moduleMapPath) { const moduleName = "LocalModule"; const headerPath = headerFileName; let moduleMapContent = ""; if (fs.existsSync(moduleMapPath)) { moduleMapContent = fs.readFileSync(moduleMapPath, "utf8"); } const headerDeclaration = `header "${headerPath}"`; if (moduleMapContent.includes(`module ${moduleName}`)) { // Module declaration already exists in the module map if (moduleMapContent.includes(headerDeclaration)) { // Header is already present in the module map this.$logger.warn(`Header '${headerFileName}' is already added to the module map.`); return; } const updatedModuleMapContent = moduleMapContent.replace(new RegExp(`module ${moduleName} {\\s*([^}]*)\\s*}`, "s"), `module ${moduleName} {${os_1.EOL} $1${os_1.EOL} ${headerDeclaration}${os_1.EOL}}`); fs.writeFileSync(moduleMapPath, updatedModuleMapContent); } else { // Module declaration does not exist in the module map const moduleDeclaration = `module ${moduleName} {${os_1.EOL} ${headerDeclaration}${os_1.EOL} export *${os_1.EOL}}`; moduleMapContent += `${os_1.EOL}${os_1.EOL}${moduleDeclaration}`; fs.writeFileSync(moduleMapPath, moduleMapContent); } this.$logger.info(`Module map '${moduleMapPath}' has been updated with the header '${headerFileName}'.`); } generateObjectiveCFiles(className, classFilePath, interfaceFilePath) { if (fs.existsSync(classFilePath)) { this.$errors.failWithHelp(`Error: File '${classFilePath}' already exists.`); return false; } if (fs.existsSync(interfaceFilePath)) { this.$errors.failWithHelp(`Error: File '${interfaceFilePath}' already exists.`); return false; } const interfaceContent = `#import <Foundation/Foundation.h> @interface ${className} : NSObject - (void)logMessage; @end `; const classContent = `#import "${className}.h" @implementation ${className} - (void)logMessage { NSLog(@"Hello from ${className} class!"); } @end `; fs.writeFileSync(classFilePath, classContent); this.$logger.trace(`Objective-C class file '${classFilePath}' generated successfully.`); fs.writeFileSync(interfaceFilePath, interfaceContent); this.$logger.trace(`Objective-C interface file '${interfaceFilePath}' generated successfully.`); return true; } } exports.NativeAddObjectiveCCommand = NativeAddObjectiveCCommand; class NativeAddSwiftCommand extends NativeAddSingleCommand { constructor($projectData, $logger, $errors) { super($projectData, $logger, $errors); } async execute(args) { this.doSwift(args[0]); return Promise.resolve(); } doSwift(className) { const iosSourceBase = this.getIosSourcePathBase(); const swiftFilePath = path.join(iosSourceBase, `${className}.swift`); this.generateSwiftFile(className, swiftFilePath); } generateSwiftFile(className, filePath) { const directory = path.dirname(filePath); if (!fs.existsSync(directory)) { fs.mkdirSync(directory, { recursive: true }); this.$logger.trace(`Created directory: '${directory}'.`); } if (fs.existsSync(filePath)) { this.$errors.failWithHelp(`Error: File '${filePath}' already exists.`); return; } const content = `import Foundation; import os; @objc class ${className}: NSObject { @objc func logMessage() { os_log("Hello from ${className} class!") } }`; fs.writeFileSync(filePath, content); this.$logger.info(`Swift file '${filePath}' generated successfully.`); } } exports.NativeAddSwiftCommand = NativeAddSwiftCommand; yok_1.injector.registerCommand(["native|add"], NativeAddCommand); yok_1.injector.registerCommand(["native|add|java"], NativeAddJavaCommand); yok_1.injector.registerCommand(["native|add|kotlin"], NativeAddKotlinCommand); yok_1.injector.registerCommand(["native|add|swift"], NativeAddSwiftCommand); yok_1.injector.registerCommand(["native|add|objective-c"], NativeAddObjectiveCCommand); //# sourceMappingURL=native-add.js.map