@table-js/platform 0.0.3 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -1
- package/dist/cli.mjs +324 -103
- package/dist/index.d.mts +24 -11
- package/dist/index.d.ts +24 -11
- package/dist/index.js +322 -102
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +322 -102
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/builder.ts","../src/adapters/tizen.ts","../src/adapters/webos.ts","../src/adapters/android.ts"],"sourcesContent":["export { build } from './builder'\nexport type { Platform, BuildOptions, PlatformAdapter, ManifestBase } from './types'\nexport { TizenAdapter } from './adapters/tizen'\nexport { WebOSAdapter } from './adapters/webos'\nexport { AndroidAdapter } from './adapters/android'\n","import { build as viteBuild } from 'vite'\nimport type { BuildOptions, Platform, PlatformAdapter } from './types'\nimport { TizenAdapter } from './adapters/tizen'\nimport { WebOSAdapter } from './adapters/webos'\nimport { AndroidAdapter } from './adapters/android'\n\nexport async function build(platform: Platform, options: Partial<BuildOptions> = {}) {\n const opts: BuildOptions = {\n platform,\n outDir: options.outDir || 'dist',\n minify: options.minify ?? true,\n sourcemap: options.sourcemap ?? false,\n }\n\n if (platform === 'all') {\n await Promise.all([\n buildPlatform('tizen', opts),\n buildPlatform('webos', opts),\n buildPlatform('android', opts),\n ])\n return\n }\n\n await buildPlatform(platform, opts)\n}\n\nasync function buildPlatform(platform: Platform, options: BuildOptions) {\n const adapter = getAdapter(platform)\n\n await viteBuild({\n build: {\n outDir: `${options.outDir}/${platform}`,\n minify: options.minify,\n sourcemap: options.sourcemap,\n emptyOutDir: true,\n },\n define: {\n __TABLE_PLATFORM__: JSON.stringify(platform),\n },\n })\n\n await adapter.build(options)\n\n const packagePath = await adapter.package(`${options.outDir}/${platform}`)\n console.log(`✓ ${adapter.name} package created: ${packagePath}`)\n}\n\nfunction getAdapter(platform: Platform): PlatformAdapter {\n switch (platform) {\n case 'tizen':\n return new TizenAdapter()\n case 'webos':\n return new WebOSAdapter()\n case 'android':\n return new AndroidAdapter()\n default:\n throw new Error(`Unknown platform: ${platform}`)\n }\n}\n","import path from 'path'\nimport fs from 'fs-extra'\nimport archiver from 'archiver'\nimport { createWriteStream } from 'fs'\nimport type { BuildOptions, PlatformAdapter, ManifestBase } from '../types'\n\nexport class TizenAdapter implements PlatformAdapter {\n name = 'Tizen (Samsung)'\n\n async build(options: BuildOptions): Promise<void> {\n const distDir = `${options.outDir}/tizen`\n await this.createConfig(distDir)\n }\n\n async package(distDir: string): Promise<string> {\n const outputPath = path.join(distDir, '..', 'app.wgt')\n\n await new Promise<void>((resolve, reject) => {\n const output = createWriteStream(outputPath)\n const archive = archiver('zip', { zlib: { level: 9 } })\n\n output.on('close', () => resolve())\n archive.on('error', reject)\n\n archive.pipe(output)\n archive.directory(distDir, false)\n archive.finalize()\n })\n\n return outputPath\n }\n\n private async createConfig(distDir: string) {\n const pkg = await this.readPackageJson()\n\n const config = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<widget xmlns=\"http://www.w3.org/ns/widgets\" \n xmlns:tizen=\"http://tizen.org/ns/widgets\"\n id=\"${pkg.id || 'com.example.app'}\"\n version=\"${pkg.version}\"\n viewmodes=\"maximized\">\n <tizen:application id=\"${pkg.id || 'com.example.app'}.App\" \n package=\"${pkg.id || 'com.example.app'}\"\n required_version=\"6.0\"/>\n <content src=\"index.html\"/>\n <feature name=\"http://tizen.org/feature/screen.size.all\"/>\n <icon src=\"icon.png\"/>\n <name>${pkg.name}</name>\n <tizen:profile name=\"tv\"/>\n <tizen:setting screen-orientation=\"landscape\" \n context-menu=\"disable\" \n background-support=\"disable\" \n encryption=\"disable\" \n install-location=\"auto\"/>\n</widget>`\n\n await fs.writeFile(path.join(distDir, 'config.xml'), config)\n }\n\n private async readPackageJson(): Promise<ManifestBase> {\n try {\n const pkg = await fs.readJson('package.json')\n return {\n id: pkg.tizenAppId || pkg.name,\n name: pkg.name,\n version: pkg.version,\n description: pkg.description,\n }\n } catch {\n return {\n id: 'com.example.app',\n name: 'Table App',\n version: '1.0.0',\n }\n }\n }\n}\n","import path from 'path'\nimport fs from 'fs-extra'\nimport archiver from 'archiver'\nimport { createWriteStream } from 'fs'\nimport type { BuildOptions, PlatformAdapter, ManifestBase } from '../types'\n\nexport class WebOSAdapter implements PlatformAdapter {\n name = 'webOS (LG)'\n\n async build(options: BuildOptions): Promise<void> {\n const distDir = `${options.outDir}/webos`\n await this.createAppInfo(distDir)\n }\n\n async package(distDir: string): Promise<string> {\n const outputPath = path.join(distDir, '..', 'app.ipk')\n\n await new Promise<void>((resolve, reject) => {\n const output = createWriteStream(outputPath)\n const archive = archiver('tar', { gzip: true })\n\n output.on('close', () => resolve())\n archive.on('error', reject)\n\n archive.pipe(output)\n archive.directory(distDir, false)\n archive.finalize()\n })\n\n return outputPath\n }\n\n private async createAppInfo(distDir: string) {\n const pkg = await this.readPackageJson()\n\n const appInfo = {\n id: pkg.id || 'com.example.app',\n version: pkg.version,\n vendor: 'Table.js',\n type: 'web',\n main: 'index.html',\n title: pkg.name,\n icon: 'icon.png',\n largeIcon: 'icon.png',\n bgImage: 'splash.png',\n resolution: '1920x1080',\n disallowScrollingInMainWindow: true,\n }\n\n await fs.writeJson(path.join(distDir, 'appinfo.json'), appInfo, { spaces: 2 })\n }\n\n private async readPackageJson(): Promise<ManifestBase> {\n try {\n const pkg = await fs.readJson('package.json')\n return {\n id: pkg.webosAppId || pkg.name,\n name: pkg.name,\n version: pkg.version,\n description: pkg.description,\n }\n } catch {\n return {\n id: 'com.example.app',\n name: 'Table App',\n version: '1.0.0',\n }\n }\n }\n}\n","import path from 'path'\nimport fs from 'fs-extra'\nimport { execa } from 'execa'\nimport type { BuildOptions, PlatformAdapter, ManifestBase } from '../types'\n\nexport class AndroidAdapter implements PlatformAdapter {\n name = 'Android TV'\n\n async build(options: BuildOptions): Promise<void> {\n const distDir = `${options.outDir}/android`\n await this.createWebViewProject(distDir)\n }\n\n async package(distDir: string): Promise<string> {\n const projectDir = path.join(distDir, 'android-project')\n\n try {\n await execa('./gradlew', ['assembleRelease'], {\n cwd: projectDir,\n stdio: 'inherit',\n })\n\n const apkPath = path.join(projectDir, 'app/build/outputs/apk/release/app-release.apk')\n\n const outputPath = path.join(distDir, '..', 'app.apk')\n await fs.copy(apkPath, outputPath)\n\n return outputPath\n } catch (error) {\n throw new Error('Android build failed. Make sure Android SDK is installed.')\n }\n }\n\n private async createWebViewProject(distDir: string) {\n const pkg = await this.readPackageJson()\n const projectDir = path.join(distDir, 'android-project')\n\n await fs.ensureDir(projectDir)\n await fs.copy(distDir, path.join(projectDir, 'app/src/main/assets/www'))\n\n await this.createManifest(projectDir, pkg)\n await this.createGradleFiles(projectDir, pkg)\n await this.createMainActivity(projectDir, pkg)\n }\n\n private async createManifest(projectDir: string, pkg: ManifestBase) {\n const manifest = `<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n package=\"${pkg.id || 'com.example.app'}\">\n\n <uses-permission android:name=\"android.permission.INTERNET\" />\n <uses-feature android:name=\"android.software.leanback\" android:required=\"true\" />\n <uses-feature android:name=\"android.hardware.touchscreen\" android:required=\"false\" />\n\n <application\n android:allowBackup=\"true\"\n android:icon=\"@mipmap/ic_launcher\"\n android:label=\"${pkg.name}\"\n android:banner=\"@drawable/banner\"\n android:theme=\"@style/Theme.Leanback\">\n \n <activity\n android:name=\".MainActivity\"\n android:exported=\"true\"\n android:screenOrientation=\"landscape\">\n <intent-filter>\n <action android:name=\"android.intent.action.MAIN\" />\n <category android:name=\"android.intent.category.LEANBACK_LAUNCHER\" />\n </intent-filter>\n </activity>\n </application>\n</manifest>`\n\n const manifestPath = path.join(projectDir, 'app/src/main/AndroidManifest.xml')\n await fs.ensureDir(path.dirname(manifestPath))\n await fs.writeFile(manifestPath, manifest)\n }\n\n private async createGradleFiles(projectDir: string, pkg: ManifestBase) {\n const buildGradle = `plugins {\n id 'com.android.application'\n}\n\nandroid {\n namespace '${pkg.id || 'com.example.app'}'\n compileSdk 34\n\n defaultConfig {\n applicationId \"${pkg.id || 'com.example.app'}\"\n minSdk 21\n targetSdk 34\n versionCode 1\n versionName \"${pkg.version}\"\n }\n\n buildTypes {\n release {\n minifyEnabled true\n proguardFiles getDefaultProguardFile('proguard-android-optimize.txt')\n }\n }\n}\n\ndependencies {\n implementation 'androidx.leanback:leanback:1.0.0'\n}`\n\n await fs.writeFile(path.join(projectDir, 'app/build.gradle'), buildGradle)\n }\n\n private async createMainActivity(projectDir: string, pkg: ManifestBase) {\n const packageName = pkg.id || 'com.example.app'\n const activity = `package ${packageName};\n\nimport android.app.Activity;\nimport android.os.Bundle;\nimport android.webkit.WebView;\nimport android.webkit.WebSettings;\n\npublic class MainActivity extends Activity {\n private WebView webView;\n\n @Override\n protected void onCreate(Bundle savedInstanceState) {\n super.onCreate(savedInstanceState);\n \n webView = new WebView(this);\n setContentView(webView);\n \n WebSettings settings = webView.getSettings();\n settings.setJavaScriptEnabled(true);\n settings.setDomStorageEnabled(true);\n settings.setAllowFileAccess(true);\n \n webView.loadUrl(\"file:///android_asset/www/index.html\");\n }\n}`\n\n const activityPath = path.join(\n projectDir,\n `app/src/main/java/${packageName.replace(/\\./g, '/')}/MainActivity.java`,\n )\n await fs.ensureDir(path.dirname(activityPath))\n await fs.writeFile(activityPath, activity)\n }\n\n private async readPackageJson(): Promise<ManifestBase> {\n try {\n const pkg = await fs.readJson('package.json')\n return {\n id: pkg.androidAppId || pkg.name.replace(/[^a-z0-9]/gi, '.').toLowerCase(),\n name: pkg.name,\n version: pkg.version,\n description: pkg.description,\n }\n } catch {\n return {\n id: 'com.example.app',\n name: 'Table App',\n version: '1.0.0',\n }\n }\n }\n}\n"],"mappings":"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","names":["path","archiver","fs","import_path","import_fs_extra","import_archiver","import_fs","path","archiver","fs","import_path","import_fs_extra","path","fs","viteBuild"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/builder.ts","../src/adapters/tizen.ts","../src/adapters/webos.ts","../src/adapters/android.ts"],"sourcesContent":["export { build } from './builder'\nexport type { Platform, Target, Mode, BuildOptions, PlatformAdapter, ManifestBase } from './types'\nexport { TizenAdapter } from './adapters/tizen'\nexport { WebOSAdapter } from './adapters/webos'\nexport { AndroidAdapter } from './adapters/android'\n","import fs from 'fs-extra'\nimport { build as viteBuild } from 'vite'\nimport type { BuildOptions, Mode, Platform, PlatformAdapter, Target } from './types'\nimport { TizenAdapter } from './adapters/tizen'\nimport { WebOSAdapter } from './adapters/webos'\nimport { AndroidAdapter } from './adapters/android'\n\nexport async function build(platform: Platform, options: Partial<BuildOptions> = {}) {\n const opts = {\n outDir: options.outDir || 'dist',\n mode: options.mode || 'webview',\n minify: options.minify ?? true,\n sourcemap: options.sourcemap ?? false,\n }\n\n if (platform === 'all') {\n await Promise.all([\n buildPlatform('tizen', opts),\n buildPlatform('webos', opts),\n buildPlatform('android', opts),\n ])\n return\n }\n\n await buildPlatform(platform, opts)\n}\n\nasync function buildPlatform(platform: Target, base: Omit<BuildOptions, 'dir' | 'platform'>) {\n const options: BuildOptions = {\n ...base,\n dir: out(base.outDir, platform, base.mode),\n platform,\n }\n const adapter = getAdapter(platform)\n\n if (web(platform, options.mode)) {\n await viteBuild({\n build: {\n outDir: dir(options),\n minify: options.minify,\n sourcemap: options.sourcemap,\n emptyOutDir: true,\n },\n define: {\n __TABLE_PLATFORM__: JSON.stringify(platform),\n },\n })\n } else {\n await fs.emptyDir(options.dir)\n }\n\n await adapter.build(options)\n\n const packagePath = await adapter.package(options)\n console.log(`✓ ${adapter.name} package created: ${packagePath}`)\n}\n\nfunction getAdapter(platform: Target): PlatformAdapter {\n switch (platform) {\n case 'tizen':\n return new TizenAdapter()\n case 'webos':\n return new WebOSAdapter()\n case 'android':\n return new AndroidAdapter()\n default:\n throw new Error(`Unknown platform: ${platform}`)\n }\n}\n\nfunction out(root: string, platform: Target, mode: Mode) {\n if (platform === 'android' && mode === 'native') {\n return `${root}/android-native`\n }\n\n return `${root}/${platform}`\n}\n\nfunction dir(options: BuildOptions) {\n if (options.platform === 'android') {\n return `${options.dir}/www`\n }\n\n return options.dir\n}\n\nfunction web(platform: Target, mode: Mode) {\n return platform !== 'android' || mode === 'webview'\n}\n","import path from 'path'\nimport fs from 'fs-extra'\nimport archiver from 'archiver'\nimport { createWriteStream } from 'fs'\nimport type { BuildOptions, PlatformAdapter, ManifestBase } from '../types'\n\nexport class TizenAdapter implements PlatformAdapter {\n name = 'Tizen (Samsung)'\n\n async build(options: BuildOptions): Promise<void> {\n await this.createConfig(options.dir)\n }\n\n async package(options: BuildOptions): Promise<string> {\n const outputPath = path.join(options.dir, '..', 'app.wgt')\n\n await new Promise<void>((resolve, reject) => {\n const output = createWriteStream(outputPath)\n const archive = archiver('zip', { zlib: { level: 9 } })\n\n output.on('close', () => resolve())\n archive.on('error', reject)\n\n archive.pipe(output)\n archive.directory(options.dir, false)\n archive.finalize()\n })\n\n return outputPath\n }\n\n private async createConfig(distDir: string) {\n const pkg = await this.readPackageJson()\n\n const config = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<widget xmlns=\"http://www.w3.org/ns/widgets\" \n xmlns:tizen=\"http://tizen.org/ns/widgets\"\n id=\"${pkg.id || 'com.example.app'}\"\n version=\"${pkg.version}\"\n viewmodes=\"maximized\">\n <tizen:application id=\"${pkg.id || 'com.example.app'}.App\" \n package=\"${pkg.id || 'com.example.app'}\"\n required_version=\"6.0\"/>\n <content src=\"index.html\"/>\n <feature name=\"http://tizen.org/feature/screen.size.all\"/>\n <icon src=\"icon.png\"/>\n <name>${pkg.name}</name>\n <tizen:profile name=\"tv\"/>\n <tizen:setting screen-orientation=\"landscape\" \n context-menu=\"disable\" \n background-support=\"disable\" \n encryption=\"disable\" \n install-location=\"auto\"/>\n</widget>`\n\n await fs.writeFile(path.join(distDir, 'config.xml'), config)\n }\n\n private async readPackageJson(): Promise<ManifestBase> {\n try {\n const pkg = await fs.readJson('package.json')\n return {\n id: pkg.tizenAppId || pkg.name,\n name: pkg.name,\n version: pkg.version,\n description: pkg.description,\n }\n } catch {\n return {\n id: 'com.example.app',\n name: 'Table App',\n version: '1.0.0',\n }\n }\n }\n}\n","import path from 'path'\nimport fs from 'fs-extra'\nimport archiver from 'archiver'\nimport { createWriteStream } from 'fs'\nimport type { BuildOptions, PlatformAdapter, ManifestBase } from '../types'\n\nexport class WebOSAdapter implements PlatformAdapter {\n name = 'webOS (LG)'\n\n async build(options: BuildOptions): Promise<void> {\n await this.createAppInfo(options.dir)\n }\n\n async package(options: BuildOptions): Promise<string> {\n const outputPath = path.join(options.dir, '..', 'app.ipk')\n\n await new Promise<void>((resolve, reject) => {\n const output = createWriteStream(outputPath)\n const archive = archiver('tar', { gzip: true })\n\n output.on('close', () => resolve())\n archive.on('error', reject)\n\n archive.pipe(output)\n archive.directory(options.dir, false)\n archive.finalize()\n })\n\n return outputPath\n }\n\n private async createAppInfo(distDir: string) {\n const pkg = await this.readPackageJson()\n\n const appInfo = {\n id: pkg.id || 'com.example.app',\n version: pkg.version,\n vendor: 'Table.js',\n type: 'web',\n main: 'index.html',\n title: pkg.name,\n icon: 'icon.png',\n largeIcon: 'icon.png',\n bgImage: 'splash.png',\n resolution: '1920x1080',\n disallowScrollingInMainWindow: true,\n }\n\n await fs.writeJson(path.join(distDir, 'appinfo.json'), appInfo, { spaces: 2 })\n }\n\n private async readPackageJson(): Promise<ManifestBase> {\n try {\n const pkg = await fs.readJson('package.json')\n return {\n id: pkg.webosAppId || pkg.name,\n name: pkg.name,\n version: pkg.version,\n description: pkg.description,\n }\n } catch {\n return {\n id: 'com.example.app',\n name: 'Table App',\n version: '1.0.0',\n }\n }\n }\n}\n","import path from 'path'\nimport fs from 'fs-extra'\nimport { execa } from 'execa'\nimport type { BuildOptions, PlatformAdapter, ManifestBase } from '../types'\n\nexport class AndroidAdapter implements PlatformAdapter {\n name = 'Android TV'\n\n async build(options: BuildOptions): Promise<void> {\n if (options.mode === 'native') {\n await this.native(options.dir)\n return\n }\n\n await this.web(options.dir)\n }\n\n async package(options: BuildOptions): Promise<string> {\n const proj = path.join(options.dir, 'project')\n const cmd = await this.cmd(proj)\n\n if (!cmd) {\n return proj\n }\n\n try {\n await execa(cmd, ['assembleRelease'], {\n cwd: proj,\n stdio: 'inherit',\n })\n\n const apk = path.join(proj, 'app/build/outputs/apk/release/app-release.apk')\n const out = path.join(options.dir, '..', this.apk(options))\n await fs.copy(apk, out)\n\n return out\n } catch {\n throw new Error('Android build failed. Install the Android SDK and Gradle, or add a Gradle wrapper.')\n }\n }\n\n private async web(dir: string) {\n const pkg = await this.pkg()\n const proj = path.join(dir, 'project')\n\n await fs.remove(proj)\n await this.root(proj, pkg)\n await this.man(proj, pkg, true)\n await this.app(proj, pkg, false)\n await this.res(proj)\n await this.webKt(proj, pkg)\n await fs.copy(path.join(dir, 'www'), path.join(proj, 'app/src/main/assets/www'))\n }\n\n private async native(dir: string) {\n const pkg = await this.pkg()\n const proj = path.join(dir, 'project')\n\n await fs.remove(proj)\n await this.root(proj, pkg)\n await this.man(proj, pkg, false)\n await this.app(proj, pkg, true)\n await this.res(proj)\n await this.nativeKt(proj, pkg)\n }\n\n private async root(proj: string, pkg: ManifestBase) {\n const settings = `pluginManagement {\n repositories {\n google()\n mavenCentral()\n gradlePluginPortal()\n }\n}\n\ndependencyResolutionManagement {\n repositoriesMode.set(org.gradle.api.initialization.resolve.RepositoriesMode.FAIL_ON_PROJECT_REPOS)\n repositories {\n google()\n mavenCentral()\n }\n}\n\nrootProject.name = \"${this.safe(pkg.name)}\"\ninclude(\":app\")\n`\n\n const build = `plugins {\n id(\"com.android.application\") version \"9.1.0\" apply false\n id(\"org.jetbrains.kotlin.android\") version \"2.3.10\" apply false\n id(\"org.jetbrains.kotlin.plugin.compose\") version \"2.3.10\" apply false\n}\n`\n\n const props = `org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8\nandroid.useAndroidX=true\nkotlin.code.style=official\n`\n\n await fs.ensureDir(proj)\n await fs.ensureDir(path.join(proj, 'app'))\n await fs.writeFile(path.join(proj, 'settings.gradle.kts'), settings)\n await fs.writeFile(path.join(proj, 'build.gradle.kts'), build)\n await fs.writeFile(path.join(proj, 'gradle.properties'), props)\n await fs.writeFile(path.join(proj, 'app/proguard-rules.pro'), '')\n }\n\n private async man(proj: string, pkg: ManifestBase, web: boolean) {\n const net = web ? '<uses-permission android:name=\"android.permission.INTERNET\" />\\n' : ''\n const clear = web ? ' android:usesCleartextTraffic=\"true\"\\n' : ''\n const manifest = `<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n package=\"${pkg.id || 'com.example.app'}\">\n\n ${net} <uses-feature android:name=\"android.software.leanback\" android:required=\"true\" />\n <uses-feature android:name=\"android.hardware.touchscreen\" android:required=\"false\" />\n\n <application\n android:allowBackup=\"true\"\n android:banner=\"@drawable/banner\"\n android:icon=\"@android:drawable/sym_def_app_icon\"\n android:label=\"${pkg.name}\"\n${clear} android:theme=\"@android:style/Theme.DeviceDefault.NoActionBar\">\n\n <activity\n android:name=\".MainActivity\"\n android:exported=\"true\"\n android:screenOrientation=\"landscape\">\n <intent-filter>\n <action android:name=\"android.intent.action.MAIN\" />\n <category android:name=\"android.intent.category.LEANBACK_LAUNCHER\" />\n </intent-filter>\n </activity>\n </application>\n</manifest>`\n\n const file = path.join(proj, 'app/src/main/AndroidManifest.xml')\n await fs.ensureDir(path.dirname(file))\n await fs.writeFile(file, manifest)\n }\n\n private async app(proj: string, pkg: ManifestBase, native: boolean) {\n const plugins = native\n ? `plugins {\n id(\"com.android.application\")\n id(\"org.jetbrains.kotlin.android\")\n id(\"org.jetbrains.kotlin.plugin.compose\")\n}`\n : `plugins {\n id(\"com.android.application\")\n id(\"org.jetbrains.kotlin.android\")\n}`\n\n const flags = native\n ? `\n buildFeatures {\n compose = true\n }`\n : ''\n\n const deps = native\n ? `dependencies {\n val bom = platform(\"androidx.compose:compose-bom:2026.02.01\")\n\n implementation(bom)\n androidTestImplementation(bom)\n\n implementation(\"androidx.activity:activity-compose:1.12.4\")\n implementation(\"androidx.compose.foundation:foundation\")\n implementation(\"androidx.compose.ui:ui\")\n implementation(\"androidx.compose.ui:ui-tooling-preview\")\n implementation(\"androidx.tv:tv-material:1.0.0\")\n debugImplementation(\"androidx.compose.ui:ui-tooling\")\n}`\n : `dependencies {\n implementation(\"androidx.leanback:leanback:1.0.0\")\n}`\n\n const build = `${plugins}\nandroid {\n namespace = \"${pkg.id || 'com.example.app'}\"\n compileSdk = 34\n\n defaultConfig {\n applicationId = \"${pkg.id || 'com.example.app'}\"\n minSdk = 21\n targetSdk = 34\n versionCode = 1\n versionName = \"${pkg.version}\"\n }\n\n compileOptions {\n sourceCompatibility = JavaVersion.VERSION_17\n targetCompatibility = JavaVersion.VERSION_17\n }\n\n kotlinOptions {\n jvmTarget = \"17\"\n }\n${flags}\n\n buildTypes {\n release {\n isMinifyEnabled = true\n proguardFiles(\n getDefaultProguardFile(\"proguard-android-optimize.txt\"),\n \"proguard-rules.pro\",\n )\n }\n }\n}\n\n${deps}\n`\n\n await fs.writeFile(path.join(proj, 'app/build.gradle.kts'), build)\n }\n\n private async res(proj: string) {\n const banner = `<shape xmlns:android=\"http://schemas.android.com/apk/res/android\" android:shape=\"rectangle\">\n <solid android:color=\"#10151E\" />\n <corners android:radius=\"18dp\" />\n</shape>\n`\n\n const file = path.join(proj, 'app/src/main/res/drawable/banner.xml')\n await fs.ensureDir(path.dirname(file))\n await fs.writeFile(file, banner)\n }\n\n private async webKt(proj: string, pkg: ManifestBase) {\n const id = pkg.id || 'com.example.app'\n const main = `package ${id}\n\nimport android.app.Activity\nimport android.os.Bundle\nimport android.webkit.WebSettings\nimport android.webkit.WebView\n\nclass MainActivity : Activity() {\n override fun onCreate(savedInstanceState: Bundle?) {\n super.onCreate(savedInstanceState)\n\n val web = WebView(this)\n setContentView(web)\n\n val set: WebSettings = web.settings\n set.javaScriptEnabled = true\n set.domStorageEnabled = true\n set.allowFileAccess = true\n\n web.loadUrl(\"file:///android_asset/www/index.html\")\n }\n}\n`\n\n const file = path.join(proj, `app/src/main/java/${id.replace(/\\./g, '/')}/MainActivity.kt`)\n await fs.ensureDir(path.dirname(file))\n await fs.writeFile(file, main)\n }\n\n private async nativeKt(proj: string, pkg: ManifestBase) {\n const id = pkg.id || 'com.example.app'\n const main = `package ${id}\n\nimport android.os.Bundle\nimport androidx.activity.ComponentActivity\nimport androidx.activity.compose.setContent\nimport androidx.compose.foundation.background\nimport androidx.compose.foundation.layout.Arrangement\nimport androidx.compose.foundation.layout.Box\nimport androidx.compose.foundation.layout.Column\nimport androidx.compose.foundation.layout.fillMaxSize\nimport androidx.compose.foundation.layout.fillMaxWidth\nimport androidx.compose.foundation.layout.padding\nimport androidx.compose.foundation.shape.RoundedCornerShape\nimport androidx.compose.ui.Alignment\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.graphics.Color\nimport androidx.compose.ui.text.style.TextAlign\nimport androidx.compose.ui.unit.dp\nimport androidx.tv.material3.Button\nimport androidx.tv.material3.MaterialTheme\nimport androidx.tv.material3.Surface\nimport androidx.tv.material3.Text\n\nclass MainActivity : ComponentActivity() {\n override fun onCreate(savedInstanceState: Bundle?) {\n super.onCreate(savedInstanceState)\n setContent {\n MaterialTheme {\n Surface(modifier = Modifier.fillMaxSize()) {\n Box(\n modifier = Modifier\n .fillMaxSize()\n .background(Color(0xFF05070A))\n .padding(48.dp),\n contentAlignment = Alignment.Center,\n ) {\n Column(\n modifier = Modifier\n .fillMaxWidth()\n .background(Color(0xFF10151E), RoundedCornerShape(28.dp))\n .padding(32.dp),\n horizontalAlignment = Alignment.CenterHorizontally,\n verticalArrangement = Arrangement.spacedBy(20.dp),\n ) {\n Text(\n text = \"${pkg.name}\",\n style = MaterialTheme.typography.displayMedium,\n textAlign = TextAlign.Center,\n )\n Text(\n text = \"Android native mode uses Kotlin and Compose for TV instead of WebView.\",\n style = MaterialTheme.typography.bodyLarge,\n textAlign = TextAlign.Center,\n color = Color(0xFFD4D7DD),\n )\n Button(onClick = {}) {\n Text(\"Ready\")\n }\n }\n }\n }\n }\n }\n }\n}\n`\n\n const file = path.join(proj, `app/src/main/java/${id.replace(/\\./g, '/')}/MainActivity.kt`)\n await fs.ensureDir(path.dirname(file))\n await fs.writeFile(file, main)\n }\n\n private async cmd(proj: string) {\n if (await fs.pathExists(path.join(proj, 'gradlew'))) {\n return './gradlew'\n }\n\n if (await this.has('gradle')) {\n return 'gradle'\n }\n\n return null\n }\n\n private async has(cmd: string) {\n try {\n await execa(cmd, ['--version'])\n return true\n } catch {\n return false\n }\n }\n\n private apk(options: BuildOptions) {\n return options.mode === 'native' ? 'app-native.apk' : 'app.apk'\n }\n\n private safe(name: string) {\n return name.replace(/[^a-z0-9._-]/gi, '-')\n }\n\n private async pkg(): Promise<ManifestBase> {\n try {\n const pkg = await fs.readJson('package.json')\n return {\n id: pkg.androidAppId || this.id(pkg.name),\n name: pkg.name,\n version: pkg.version,\n description: pkg.description,\n }\n } catch {\n return {\n id: 'com.example.app',\n name: 'Table App',\n version: '1.0.0',\n }\n }\n }\n\n private id(name: string) {\n const slug = name\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '.')\n .replace(/^\\.+|\\.+$/g, '')\n .replace(/\\.\\.+/g, '.')\n\n return `com.tablejs.${slug || 'app'}`\n }\n}\n"],"mappings":"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","names":["import_fs_extra","path","archiver","fs","import_path","import_fs_extra","import_archiver","import_fs","path","archiver","fs","import_path","import_fs_extra","path","out","fs","dir","build","web","viteBuild","fs"]}
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// src/builder.ts
|
|
2
|
+
import fs4 from "fs-extra";
|
|
2
3
|
import { build as viteBuild } from "vite";
|
|
3
4
|
|
|
4
5
|
// src/adapters/tizen.ts
|
|
@@ -9,18 +10,17 @@ import { createWriteStream } from "fs";
|
|
|
9
10
|
var TizenAdapter = class {
|
|
10
11
|
name = "Tizen (Samsung)";
|
|
11
12
|
async build(options) {
|
|
12
|
-
|
|
13
|
-
await this.createConfig(distDir);
|
|
13
|
+
await this.createConfig(options.dir);
|
|
14
14
|
}
|
|
15
|
-
async package(
|
|
16
|
-
const outputPath = path.join(
|
|
15
|
+
async package(options) {
|
|
16
|
+
const outputPath = path.join(options.dir, "..", "app.wgt");
|
|
17
17
|
await new Promise((resolve, reject) => {
|
|
18
18
|
const output = createWriteStream(outputPath);
|
|
19
19
|
const archive = archiver("zip", { zlib: { level: 9 } });
|
|
20
20
|
output.on("close", () => resolve());
|
|
21
21
|
archive.on("error", reject);
|
|
22
22
|
archive.pipe(output);
|
|
23
|
-
archive.directory(
|
|
23
|
+
archive.directory(options.dir, false);
|
|
24
24
|
archive.finalize();
|
|
25
25
|
});
|
|
26
26
|
return outputPath;
|
|
@@ -76,18 +76,17 @@ import { createWriteStream as createWriteStream2 } from "fs";
|
|
|
76
76
|
var WebOSAdapter = class {
|
|
77
77
|
name = "webOS (LG)";
|
|
78
78
|
async build(options) {
|
|
79
|
-
|
|
80
|
-
await this.createAppInfo(distDir);
|
|
79
|
+
await this.createAppInfo(options.dir);
|
|
81
80
|
}
|
|
82
|
-
async package(
|
|
83
|
-
const outputPath = path2.join(
|
|
81
|
+
async package(options) {
|
|
82
|
+
const outputPath = path2.join(options.dir, "..", "app.ipk");
|
|
84
83
|
await new Promise((resolve, reject) => {
|
|
85
84
|
const output = createWriteStream2(outputPath);
|
|
86
85
|
const archive = archiver2("tar", { gzip: true });
|
|
87
86
|
output.on("close", () => resolve());
|
|
88
87
|
archive.on("error", reject);
|
|
89
88
|
archive.pipe(output);
|
|
90
|
-
archive.directory(
|
|
89
|
+
archive.directory(options.dir, false);
|
|
91
90
|
archive.finalize();
|
|
92
91
|
});
|
|
93
92
|
return outputPath;
|
|
@@ -135,49 +134,106 @@ import { execa } from "execa";
|
|
|
135
134
|
var AndroidAdapter = class {
|
|
136
135
|
name = "Android TV";
|
|
137
136
|
async build(options) {
|
|
138
|
-
|
|
139
|
-
|
|
137
|
+
if (options.mode === "native") {
|
|
138
|
+
await this.native(options.dir);
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
await this.web(options.dir);
|
|
140
142
|
}
|
|
141
|
-
async package(
|
|
142
|
-
const
|
|
143
|
+
async package(options) {
|
|
144
|
+
const proj = path3.join(options.dir, "project");
|
|
145
|
+
const cmd = await this.cmd(proj);
|
|
146
|
+
if (!cmd) {
|
|
147
|
+
return proj;
|
|
148
|
+
}
|
|
143
149
|
try {
|
|
144
|
-
await execa(
|
|
145
|
-
cwd:
|
|
150
|
+
await execa(cmd, ["assembleRelease"], {
|
|
151
|
+
cwd: proj,
|
|
146
152
|
stdio: "inherit"
|
|
147
153
|
});
|
|
148
|
-
const
|
|
149
|
-
const
|
|
150
|
-
await fs3.copy(
|
|
151
|
-
return
|
|
152
|
-
} catch
|
|
153
|
-
throw new Error("Android build failed.
|
|
154
|
+
const apk = path3.join(proj, "app/build/outputs/apk/release/app-release.apk");
|
|
155
|
+
const out2 = path3.join(options.dir, "..", this.apk(options));
|
|
156
|
+
await fs3.copy(apk, out2);
|
|
157
|
+
return out2;
|
|
158
|
+
} catch {
|
|
159
|
+
throw new Error("Android build failed. Install the Android SDK and Gradle, or add a Gradle wrapper.");
|
|
154
160
|
}
|
|
155
161
|
}
|
|
156
|
-
async
|
|
157
|
-
const pkg = await this.
|
|
158
|
-
const
|
|
159
|
-
await fs3.
|
|
160
|
-
await
|
|
161
|
-
await this.
|
|
162
|
-
await this.
|
|
163
|
-
await this.
|
|
162
|
+
async web(dir2) {
|
|
163
|
+
const pkg = await this.pkg();
|
|
164
|
+
const proj = path3.join(dir2, "project");
|
|
165
|
+
await fs3.remove(proj);
|
|
166
|
+
await this.root(proj, pkg);
|
|
167
|
+
await this.man(proj, pkg, true);
|
|
168
|
+
await this.app(proj, pkg, false);
|
|
169
|
+
await this.res(proj);
|
|
170
|
+
await this.webKt(proj, pkg);
|
|
171
|
+
await fs3.copy(path3.join(dir2, "www"), path3.join(proj, "app/src/main/assets/www"));
|
|
172
|
+
}
|
|
173
|
+
async native(dir2) {
|
|
174
|
+
const pkg = await this.pkg();
|
|
175
|
+
const proj = path3.join(dir2, "project");
|
|
176
|
+
await fs3.remove(proj);
|
|
177
|
+
await this.root(proj, pkg);
|
|
178
|
+
await this.man(proj, pkg, false);
|
|
179
|
+
await this.app(proj, pkg, true);
|
|
180
|
+
await this.res(proj);
|
|
181
|
+
await this.nativeKt(proj, pkg);
|
|
182
|
+
}
|
|
183
|
+
async root(proj, pkg) {
|
|
184
|
+
const settings = `pluginManagement {
|
|
185
|
+
repositories {
|
|
186
|
+
google()
|
|
187
|
+
mavenCentral()
|
|
188
|
+
gradlePluginPortal()
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
dependencyResolutionManagement {
|
|
193
|
+
repositoriesMode.set(org.gradle.api.initialization.resolve.RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
|
194
|
+
repositories {
|
|
195
|
+
google()
|
|
196
|
+
mavenCentral()
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
rootProject.name = "${this.safe(pkg.name)}"
|
|
201
|
+
include(":app")
|
|
202
|
+
`;
|
|
203
|
+
const build2 = `plugins {
|
|
204
|
+
id("com.android.application") version "9.1.0" apply false
|
|
205
|
+
id("org.jetbrains.kotlin.android") version "2.3.10" apply false
|
|
206
|
+
id("org.jetbrains.kotlin.plugin.compose") version "2.3.10" apply false
|
|
207
|
+
}
|
|
208
|
+
`;
|
|
209
|
+
const props = `org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
|
|
210
|
+
android.useAndroidX=true
|
|
211
|
+
kotlin.code.style=official
|
|
212
|
+
`;
|
|
213
|
+
await fs3.ensureDir(proj);
|
|
214
|
+
await fs3.ensureDir(path3.join(proj, "app"));
|
|
215
|
+
await fs3.writeFile(path3.join(proj, "settings.gradle.kts"), settings);
|
|
216
|
+
await fs3.writeFile(path3.join(proj, "build.gradle.kts"), build2);
|
|
217
|
+
await fs3.writeFile(path3.join(proj, "gradle.properties"), props);
|
|
218
|
+
await fs3.writeFile(path3.join(proj, "app/proguard-rules.pro"), "");
|
|
164
219
|
}
|
|
165
|
-
async
|
|
220
|
+
async man(proj, pkg, web2) {
|
|
221
|
+
const net = web2 ? '<uses-permission android:name="android.permission.INTERNET" />\n' : "";
|
|
222
|
+
const clear = web2 ? ' android:usesCleartextTraffic="true"\n' : "";
|
|
166
223
|
const manifest = `<?xml version="1.0" encoding="utf-8"?>
|
|
167
224
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
168
225
|
package="${pkg.id || "com.example.app"}">
|
|
169
226
|
|
|
170
|
-
<uses-
|
|
171
|
-
<uses-feature android:name="android.software.leanback" android:required="true" />
|
|
227
|
+
${net} <uses-feature android:name="android.software.leanback" android:required="true" />
|
|
172
228
|
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />
|
|
173
229
|
|
|
174
230
|
<application
|
|
175
231
|
android:allowBackup="true"
|
|
176
|
-
android:icon="@mipmap/ic_launcher"
|
|
177
|
-
android:label="${pkg.name}"
|
|
178
232
|
android:banner="@drawable/banner"
|
|
179
|
-
android:
|
|
180
|
-
|
|
233
|
+
android:icon="@android:drawable/sym_def_app_icon"
|
|
234
|
+
android:label="${pkg.name}"
|
|
235
|
+
${clear} android:theme="@android:style/Theme.DeviceDefault.NoActionBar">
|
|
236
|
+
|
|
181
237
|
<activity
|
|
182
238
|
android:name=".MainActivity"
|
|
183
239
|
android:exported="true"
|
|
@@ -189,79 +245,215 @@ var AndroidAdapter = class {
|
|
|
189
245
|
</activity>
|
|
190
246
|
</application>
|
|
191
247
|
</manifest>`;
|
|
192
|
-
const
|
|
193
|
-
await fs3.ensureDir(path3.dirname(
|
|
194
|
-
await fs3.writeFile(
|
|
248
|
+
const file = path3.join(proj, "app/src/main/AndroidManifest.xml");
|
|
249
|
+
await fs3.ensureDir(path3.dirname(file));
|
|
250
|
+
await fs3.writeFile(file, manifest);
|
|
195
251
|
}
|
|
196
|
-
async
|
|
197
|
-
const
|
|
198
|
-
id
|
|
199
|
-
|
|
252
|
+
async app(proj, pkg, native) {
|
|
253
|
+
const plugins = native ? `plugins {
|
|
254
|
+
id("com.android.application")
|
|
255
|
+
id("org.jetbrains.kotlin.android")
|
|
256
|
+
id("org.jetbrains.kotlin.plugin.compose")
|
|
257
|
+
}` : `plugins {
|
|
258
|
+
id("com.android.application")
|
|
259
|
+
id("org.jetbrains.kotlin.android")
|
|
260
|
+
}`;
|
|
261
|
+
const flags = native ? `
|
|
262
|
+
buildFeatures {
|
|
263
|
+
compose = true
|
|
264
|
+
}` : "";
|
|
265
|
+
const deps = native ? `dependencies {
|
|
266
|
+
val bom = platform("androidx.compose:compose-bom:2026.02.01")
|
|
200
267
|
|
|
268
|
+
implementation(bom)
|
|
269
|
+
androidTestImplementation(bom)
|
|
270
|
+
|
|
271
|
+
implementation("androidx.activity:activity-compose:1.12.4")
|
|
272
|
+
implementation("androidx.compose.foundation:foundation")
|
|
273
|
+
implementation("androidx.compose.ui:ui")
|
|
274
|
+
implementation("androidx.compose.ui:ui-tooling-preview")
|
|
275
|
+
implementation("androidx.tv:tv-material:1.0.0")
|
|
276
|
+
debugImplementation("androidx.compose.ui:ui-tooling")
|
|
277
|
+
}` : `dependencies {
|
|
278
|
+
implementation("androidx.leanback:leanback:1.0.0")
|
|
279
|
+
}`;
|
|
280
|
+
const build2 = `${plugins}
|
|
201
281
|
android {
|
|
202
|
-
namespace
|
|
203
|
-
compileSdk 34
|
|
282
|
+
namespace = "${pkg.id || "com.example.app"}"
|
|
283
|
+
compileSdk = 34
|
|
204
284
|
|
|
205
285
|
defaultConfig {
|
|
206
|
-
applicationId "${pkg.id || "com.example.app"}"
|
|
207
|
-
minSdk 21
|
|
208
|
-
targetSdk 34
|
|
209
|
-
versionCode 1
|
|
210
|
-
versionName "${pkg.version}"
|
|
286
|
+
applicationId = "${pkg.id || "com.example.app"}"
|
|
287
|
+
minSdk = 21
|
|
288
|
+
targetSdk = 34
|
|
289
|
+
versionCode = 1
|
|
290
|
+
versionName = "${pkg.version}"
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
compileOptions {
|
|
294
|
+
sourceCompatibility = JavaVersion.VERSION_17
|
|
295
|
+
targetCompatibility = JavaVersion.VERSION_17
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
kotlinOptions {
|
|
299
|
+
jvmTarget = "17"
|
|
211
300
|
}
|
|
301
|
+
${flags}
|
|
212
302
|
|
|
213
303
|
buildTypes {
|
|
214
304
|
release {
|
|
215
|
-
|
|
216
|
-
proguardFiles
|
|
305
|
+
isMinifyEnabled = true
|
|
306
|
+
proguardFiles(
|
|
307
|
+
getDefaultProguardFile("proguard-android-optimize.txt"),
|
|
308
|
+
"proguard-rules.pro",
|
|
309
|
+
)
|
|
217
310
|
}
|
|
218
311
|
}
|
|
219
312
|
}
|
|
220
313
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
await fs3.writeFile(path3.join(projectDir, "app/build.gradle"), buildGradle);
|
|
314
|
+
${deps}
|
|
315
|
+
`;
|
|
316
|
+
await fs3.writeFile(path3.join(proj, "app/build.gradle.kts"), build2);
|
|
225
317
|
}
|
|
226
|
-
async
|
|
227
|
-
const
|
|
228
|
-
|
|
318
|
+
async res(proj) {
|
|
319
|
+
const banner = `<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
|
320
|
+
<solid android:color="#10151E" />
|
|
321
|
+
<corners android:radius="18dp" />
|
|
322
|
+
</shape>
|
|
323
|
+
`;
|
|
324
|
+
const file = path3.join(proj, "app/src/main/res/drawable/banner.xml");
|
|
325
|
+
await fs3.ensureDir(path3.dirname(file));
|
|
326
|
+
await fs3.writeFile(file, banner);
|
|
327
|
+
}
|
|
328
|
+
async webKt(proj, pkg) {
|
|
329
|
+
const id = pkg.id || "com.example.app";
|
|
330
|
+
const main = `package ${id}
|
|
331
|
+
|
|
332
|
+
import android.app.Activity
|
|
333
|
+
import android.os.Bundle
|
|
334
|
+
import android.webkit.WebSettings
|
|
335
|
+
import android.webkit.WebView
|
|
336
|
+
|
|
337
|
+
class MainActivity : Activity() {
|
|
338
|
+
override fun onCreate(savedInstanceState: Bundle?) {
|
|
339
|
+
super.onCreate(savedInstanceState)
|
|
229
340
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
import android.webkit.WebView;
|
|
233
|
-
import android.webkit.WebSettings;
|
|
341
|
+
val web = WebView(this)
|
|
342
|
+
setContentView(web)
|
|
234
343
|
|
|
235
|
-
|
|
236
|
-
|
|
344
|
+
val set: WebSettings = web.settings
|
|
345
|
+
set.javaScriptEnabled = true
|
|
346
|
+
set.domStorageEnabled = true
|
|
347
|
+
set.allowFileAccess = true
|
|
237
348
|
|
|
238
|
-
|
|
239
|
-
protected void onCreate(Bundle savedInstanceState) {
|
|
240
|
-
super.onCreate(savedInstanceState);
|
|
241
|
-
|
|
242
|
-
webView = new WebView(this);
|
|
243
|
-
setContentView(webView);
|
|
244
|
-
|
|
245
|
-
WebSettings settings = webView.getSettings();
|
|
246
|
-
settings.setJavaScriptEnabled(true);
|
|
247
|
-
settings.setDomStorageEnabled(true);
|
|
248
|
-
settings.setAllowFileAccess(true);
|
|
249
|
-
|
|
250
|
-
webView.loadUrl("file:///android_asset/www/index.html");
|
|
349
|
+
web.loadUrl("file:///android_asset/www/index.html")
|
|
251
350
|
}
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
);
|
|
257
|
-
await fs3.ensureDir(path3.dirname(activityPath));
|
|
258
|
-
await fs3.writeFile(activityPath, activity);
|
|
351
|
+
}
|
|
352
|
+
`;
|
|
353
|
+
const file = path3.join(proj, `app/src/main/java/${id.replace(/\./g, "/")}/MainActivity.kt`);
|
|
354
|
+
await fs3.ensureDir(path3.dirname(file));
|
|
355
|
+
await fs3.writeFile(file, main);
|
|
259
356
|
}
|
|
260
|
-
async
|
|
357
|
+
async nativeKt(proj, pkg) {
|
|
358
|
+
const id = pkg.id || "com.example.app";
|
|
359
|
+
const main = `package ${id}
|
|
360
|
+
|
|
361
|
+
import android.os.Bundle
|
|
362
|
+
import androidx.activity.ComponentActivity
|
|
363
|
+
import androidx.activity.compose.setContent
|
|
364
|
+
import androidx.compose.foundation.background
|
|
365
|
+
import androidx.compose.foundation.layout.Arrangement
|
|
366
|
+
import androidx.compose.foundation.layout.Box
|
|
367
|
+
import androidx.compose.foundation.layout.Column
|
|
368
|
+
import androidx.compose.foundation.layout.fillMaxSize
|
|
369
|
+
import androidx.compose.foundation.layout.fillMaxWidth
|
|
370
|
+
import androidx.compose.foundation.layout.padding
|
|
371
|
+
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
372
|
+
import androidx.compose.ui.Alignment
|
|
373
|
+
import androidx.compose.ui.Modifier
|
|
374
|
+
import androidx.compose.ui.graphics.Color
|
|
375
|
+
import androidx.compose.ui.text.style.TextAlign
|
|
376
|
+
import androidx.compose.ui.unit.dp
|
|
377
|
+
import androidx.tv.material3.Button
|
|
378
|
+
import androidx.tv.material3.MaterialTheme
|
|
379
|
+
import androidx.tv.material3.Surface
|
|
380
|
+
import androidx.tv.material3.Text
|
|
381
|
+
|
|
382
|
+
class MainActivity : ComponentActivity() {
|
|
383
|
+
override fun onCreate(savedInstanceState: Bundle?) {
|
|
384
|
+
super.onCreate(savedInstanceState)
|
|
385
|
+
setContent {
|
|
386
|
+
MaterialTheme {
|
|
387
|
+
Surface(modifier = Modifier.fillMaxSize()) {
|
|
388
|
+
Box(
|
|
389
|
+
modifier = Modifier
|
|
390
|
+
.fillMaxSize()
|
|
391
|
+
.background(Color(0xFF05070A))
|
|
392
|
+
.padding(48.dp),
|
|
393
|
+
contentAlignment = Alignment.Center,
|
|
394
|
+
) {
|
|
395
|
+
Column(
|
|
396
|
+
modifier = Modifier
|
|
397
|
+
.fillMaxWidth()
|
|
398
|
+
.background(Color(0xFF10151E), RoundedCornerShape(28.dp))
|
|
399
|
+
.padding(32.dp),
|
|
400
|
+
horizontalAlignment = Alignment.CenterHorizontally,
|
|
401
|
+
verticalArrangement = Arrangement.spacedBy(20.dp),
|
|
402
|
+
) {
|
|
403
|
+
Text(
|
|
404
|
+
text = "${pkg.name}",
|
|
405
|
+
style = MaterialTheme.typography.displayMedium,
|
|
406
|
+
textAlign = TextAlign.Center,
|
|
407
|
+
)
|
|
408
|
+
Text(
|
|
409
|
+
text = "Android native mode uses Kotlin and Compose for TV instead of WebView.",
|
|
410
|
+
style = MaterialTheme.typography.bodyLarge,
|
|
411
|
+
textAlign = TextAlign.Center,
|
|
412
|
+
color = Color(0xFFD4D7DD),
|
|
413
|
+
)
|
|
414
|
+
Button(onClick = {}) {
|
|
415
|
+
Text("Ready")
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
`;
|
|
425
|
+
const file = path3.join(proj, `app/src/main/java/${id.replace(/\./g, "/")}/MainActivity.kt`);
|
|
426
|
+
await fs3.ensureDir(path3.dirname(file));
|
|
427
|
+
await fs3.writeFile(file, main);
|
|
428
|
+
}
|
|
429
|
+
async cmd(proj) {
|
|
430
|
+
if (await fs3.pathExists(path3.join(proj, "gradlew"))) {
|
|
431
|
+
return "./gradlew";
|
|
432
|
+
}
|
|
433
|
+
if (await this.has("gradle")) {
|
|
434
|
+
return "gradle";
|
|
435
|
+
}
|
|
436
|
+
return null;
|
|
437
|
+
}
|
|
438
|
+
async has(cmd) {
|
|
439
|
+
try {
|
|
440
|
+
await execa(cmd, ["--version"]);
|
|
441
|
+
return true;
|
|
442
|
+
} catch {
|
|
443
|
+
return false;
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
apk(options) {
|
|
447
|
+
return options.mode === "native" ? "app-native.apk" : "app.apk";
|
|
448
|
+
}
|
|
449
|
+
safe(name) {
|
|
450
|
+
return name.replace(/[^a-z0-9._-]/gi, "-");
|
|
451
|
+
}
|
|
452
|
+
async pkg() {
|
|
261
453
|
try {
|
|
262
454
|
const pkg = await fs3.readJson("package.json");
|
|
263
455
|
return {
|
|
264
|
-
id: pkg.androidAppId || pkg.name
|
|
456
|
+
id: pkg.androidAppId || this.id(pkg.name),
|
|
265
457
|
name: pkg.name,
|
|
266
458
|
version: pkg.version,
|
|
267
459
|
description: pkg.description
|
|
@@ -274,13 +466,17 @@ public class MainActivity extends Activity {
|
|
|
274
466
|
};
|
|
275
467
|
}
|
|
276
468
|
}
|
|
469
|
+
id(name) {
|
|
470
|
+
const slug = name.toLowerCase().replace(/[^a-z0-9]+/g, ".").replace(/^\.+|\.+$/g, "").replace(/\.\.+/g, ".");
|
|
471
|
+
return `com.tablejs.${slug || "app"}`;
|
|
472
|
+
}
|
|
277
473
|
};
|
|
278
474
|
|
|
279
475
|
// src/builder.ts
|
|
280
476
|
async function build(platform, options = {}) {
|
|
281
477
|
const opts = {
|
|
282
|
-
platform,
|
|
283
478
|
outDir: options.outDir || "dist",
|
|
479
|
+
mode: options.mode || "webview",
|
|
284
480
|
minify: options.minify ?? true,
|
|
285
481
|
sourcemap: options.sourcemap ?? false
|
|
286
482
|
};
|
|
@@ -294,21 +490,30 @@ async function build(platform, options = {}) {
|
|
|
294
490
|
}
|
|
295
491
|
await buildPlatform(platform, opts);
|
|
296
492
|
}
|
|
297
|
-
async function buildPlatform(platform,
|
|
493
|
+
async function buildPlatform(platform, base) {
|
|
494
|
+
const options = {
|
|
495
|
+
...base,
|
|
496
|
+
dir: out(base.outDir, platform, base.mode),
|
|
497
|
+
platform
|
|
498
|
+
};
|
|
298
499
|
const adapter = getAdapter(platform);
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
500
|
+
if (web(platform, options.mode)) {
|
|
501
|
+
await viteBuild({
|
|
502
|
+
build: {
|
|
503
|
+
outDir: dir(options),
|
|
504
|
+
minify: options.minify,
|
|
505
|
+
sourcemap: options.sourcemap,
|
|
506
|
+
emptyOutDir: true
|
|
507
|
+
},
|
|
508
|
+
define: {
|
|
509
|
+
__TABLE_PLATFORM__: JSON.stringify(platform)
|
|
510
|
+
}
|
|
511
|
+
});
|
|
512
|
+
} else {
|
|
513
|
+
await fs4.emptyDir(options.dir);
|
|
514
|
+
}
|
|
310
515
|
await adapter.build(options);
|
|
311
|
-
const packagePath = await adapter.package(
|
|
516
|
+
const packagePath = await adapter.package(options);
|
|
312
517
|
console.log(`\u2713 ${adapter.name} package created: ${packagePath}`);
|
|
313
518
|
}
|
|
314
519
|
function getAdapter(platform) {
|
|
@@ -323,6 +528,21 @@ function getAdapter(platform) {
|
|
|
323
528
|
throw new Error(`Unknown platform: ${platform}`);
|
|
324
529
|
}
|
|
325
530
|
}
|
|
531
|
+
function out(root, platform, mode) {
|
|
532
|
+
if (platform === "android" && mode === "native") {
|
|
533
|
+
return `${root}/android-native`;
|
|
534
|
+
}
|
|
535
|
+
return `${root}/${platform}`;
|
|
536
|
+
}
|
|
537
|
+
function dir(options) {
|
|
538
|
+
if (options.platform === "android") {
|
|
539
|
+
return `${options.dir}/www`;
|
|
540
|
+
}
|
|
541
|
+
return options.dir;
|
|
542
|
+
}
|
|
543
|
+
function web(platform, mode) {
|
|
544
|
+
return platform !== "android" || mode === "webview";
|
|
545
|
+
}
|
|
326
546
|
export {
|
|
327
547
|
AndroidAdapter,
|
|
328
548
|
TizenAdapter,
|