@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/README.md
CHANGED
|
@@ -18,13 +18,17 @@ table build --platform all
|
|
|
18
18
|
table build --platform tizen
|
|
19
19
|
table build --platform webos
|
|
20
20
|
table build --platform android
|
|
21
|
+
|
|
22
|
+
# Build Android as a native Kotlin + Compose TV project
|
|
23
|
+
table build --platform android --mode native
|
|
21
24
|
```
|
|
22
25
|
|
|
23
26
|
## Supported Platforms
|
|
24
27
|
|
|
25
28
|
- **Tizen** - Samsung Smart TV (.wgt)
|
|
26
29
|
- **webOS** - LG Smart TV (.ipk)
|
|
27
|
-
- **Android TV** - Android TV (.apk)
|
|
30
|
+
- **Android TV** - Android TV WebView (.apk / Gradle project)
|
|
31
|
+
- **Android TV Native** - Kotlin + Compose for TV project (`--mode native`)
|
|
28
32
|
|
|
29
33
|
## License
|
|
30
34
|
|
package/dist/cli.mjs
CHANGED
|
@@ -6,6 +6,7 @@ import chalk from "chalk";
|
|
|
6
6
|
import ora from "ora";
|
|
7
7
|
|
|
8
8
|
// src/builder.ts
|
|
9
|
+
import fs4 from "fs-extra";
|
|
9
10
|
import { build as viteBuild } from "vite";
|
|
10
11
|
|
|
11
12
|
// src/adapters/tizen.ts
|
|
@@ -16,18 +17,17 @@ import { createWriteStream } from "fs";
|
|
|
16
17
|
var TizenAdapter = class {
|
|
17
18
|
name = "Tizen (Samsung)";
|
|
18
19
|
async build(options) {
|
|
19
|
-
|
|
20
|
-
await this.createConfig(distDir);
|
|
20
|
+
await this.createConfig(options.dir);
|
|
21
21
|
}
|
|
22
|
-
async package(
|
|
23
|
-
const outputPath = path.join(
|
|
22
|
+
async package(options) {
|
|
23
|
+
const outputPath = path.join(options.dir, "..", "app.wgt");
|
|
24
24
|
await new Promise((resolve, reject) => {
|
|
25
25
|
const output = createWriteStream(outputPath);
|
|
26
26
|
const archive = archiver("zip", { zlib: { level: 9 } });
|
|
27
27
|
output.on("close", () => resolve());
|
|
28
28
|
archive.on("error", reject);
|
|
29
29
|
archive.pipe(output);
|
|
30
|
-
archive.directory(
|
|
30
|
+
archive.directory(options.dir, false);
|
|
31
31
|
archive.finalize();
|
|
32
32
|
});
|
|
33
33
|
return outputPath;
|
|
@@ -83,18 +83,17 @@ import { createWriteStream as createWriteStream2 } from "fs";
|
|
|
83
83
|
var WebOSAdapter = class {
|
|
84
84
|
name = "webOS (LG)";
|
|
85
85
|
async build(options) {
|
|
86
|
-
|
|
87
|
-
await this.createAppInfo(distDir);
|
|
86
|
+
await this.createAppInfo(options.dir);
|
|
88
87
|
}
|
|
89
|
-
async package(
|
|
90
|
-
const outputPath = path2.join(
|
|
88
|
+
async package(options) {
|
|
89
|
+
const outputPath = path2.join(options.dir, "..", "app.ipk");
|
|
91
90
|
await new Promise((resolve, reject) => {
|
|
92
91
|
const output = createWriteStream2(outputPath);
|
|
93
92
|
const archive = archiver2("tar", { gzip: true });
|
|
94
93
|
output.on("close", () => resolve());
|
|
95
94
|
archive.on("error", reject);
|
|
96
95
|
archive.pipe(output);
|
|
97
|
-
archive.directory(
|
|
96
|
+
archive.directory(options.dir, false);
|
|
98
97
|
archive.finalize();
|
|
99
98
|
});
|
|
100
99
|
return outputPath;
|
|
@@ -142,49 +141,106 @@ import { execa } from "execa";
|
|
|
142
141
|
var AndroidAdapter = class {
|
|
143
142
|
name = "Android TV";
|
|
144
143
|
async build(options) {
|
|
145
|
-
|
|
146
|
-
|
|
144
|
+
if (options.mode === "native") {
|
|
145
|
+
await this.native(options.dir);
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
await this.web(options.dir);
|
|
147
149
|
}
|
|
148
|
-
async package(
|
|
149
|
-
const
|
|
150
|
+
async package(options) {
|
|
151
|
+
const proj = path3.join(options.dir, "project");
|
|
152
|
+
const cmd = await this.cmd(proj);
|
|
153
|
+
if (!cmd) {
|
|
154
|
+
return proj;
|
|
155
|
+
}
|
|
150
156
|
try {
|
|
151
|
-
await execa(
|
|
152
|
-
cwd:
|
|
157
|
+
await execa(cmd, ["assembleRelease"], {
|
|
158
|
+
cwd: proj,
|
|
153
159
|
stdio: "inherit"
|
|
154
160
|
});
|
|
155
|
-
const
|
|
156
|
-
const
|
|
157
|
-
await fs3.copy(
|
|
158
|
-
return
|
|
159
|
-
} catch
|
|
160
|
-
throw new Error("Android build failed.
|
|
161
|
+
const apk = path3.join(proj, "app/build/outputs/apk/release/app-release.apk");
|
|
162
|
+
const out2 = path3.join(options.dir, "..", this.apk(options));
|
|
163
|
+
await fs3.copy(apk, out2);
|
|
164
|
+
return out2;
|
|
165
|
+
} catch {
|
|
166
|
+
throw new Error("Android build failed. Install the Android SDK and Gradle, or add a Gradle wrapper.");
|
|
161
167
|
}
|
|
162
168
|
}
|
|
163
|
-
async
|
|
164
|
-
const pkg = await this.
|
|
165
|
-
const
|
|
166
|
-
await fs3.
|
|
167
|
-
await
|
|
168
|
-
await this.
|
|
169
|
-
await this.
|
|
170
|
-
await this.
|
|
169
|
+
async web(dir2) {
|
|
170
|
+
const pkg = await this.pkg();
|
|
171
|
+
const proj = path3.join(dir2, "project");
|
|
172
|
+
await fs3.remove(proj);
|
|
173
|
+
await this.root(proj, pkg);
|
|
174
|
+
await this.man(proj, pkg, true);
|
|
175
|
+
await this.app(proj, pkg, false);
|
|
176
|
+
await this.res(proj);
|
|
177
|
+
await this.webKt(proj, pkg);
|
|
178
|
+
await fs3.copy(path3.join(dir2, "www"), path3.join(proj, "app/src/main/assets/www"));
|
|
171
179
|
}
|
|
172
|
-
async
|
|
180
|
+
async native(dir2) {
|
|
181
|
+
const pkg = await this.pkg();
|
|
182
|
+
const proj = path3.join(dir2, "project");
|
|
183
|
+
await fs3.remove(proj);
|
|
184
|
+
await this.root(proj, pkg);
|
|
185
|
+
await this.man(proj, pkg, false);
|
|
186
|
+
await this.app(proj, pkg, true);
|
|
187
|
+
await this.res(proj);
|
|
188
|
+
await this.nativeKt(proj, pkg);
|
|
189
|
+
}
|
|
190
|
+
async root(proj, pkg) {
|
|
191
|
+
const settings = `pluginManagement {
|
|
192
|
+
repositories {
|
|
193
|
+
google()
|
|
194
|
+
mavenCentral()
|
|
195
|
+
gradlePluginPortal()
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
dependencyResolutionManagement {
|
|
200
|
+
repositoriesMode.set(org.gradle.api.initialization.resolve.RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
|
201
|
+
repositories {
|
|
202
|
+
google()
|
|
203
|
+
mavenCentral()
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
rootProject.name = "${this.safe(pkg.name)}"
|
|
208
|
+
include(":app")
|
|
209
|
+
`;
|
|
210
|
+
const build2 = `plugins {
|
|
211
|
+
id("com.android.application") version "9.1.0" apply false
|
|
212
|
+
id("org.jetbrains.kotlin.android") version "2.3.10" apply false
|
|
213
|
+
id("org.jetbrains.kotlin.plugin.compose") version "2.3.10" apply false
|
|
214
|
+
}
|
|
215
|
+
`;
|
|
216
|
+
const props = `org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
|
|
217
|
+
android.useAndroidX=true
|
|
218
|
+
kotlin.code.style=official
|
|
219
|
+
`;
|
|
220
|
+
await fs3.ensureDir(proj);
|
|
221
|
+
await fs3.ensureDir(path3.join(proj, "app"));
|
|
222
|
+
await fs3.writeFile(path3.join(proj, "settings.gradle.kts"), settings);
|
|
223
|
+
await fs3.writeFile(path3.join(proj, "build.gradle.kts"), build2);
|
|
224
|
+
await fs3.writeFile(path3.join(proj, "gradle.properties"), props);
|
|
225
|
+
await fs3.writeFile(path3.join(proj, "app/proguard-rules.pro"), "");
|
|
226
|
+
}
|
|
227
|
+
async man(proj, pkg, web2) {
|
|
228
|
+
const net = web2 ? '<uses-permission android:name="android.permission.INTERNET" />\n' : "";
|
|
229
|
+
const clear = web2 ? ' android:usesCleartextTraffic="true"\n' : "";
|
|
173
230
|
const manifest = `<?xml version="1.0" encoding="utf-8"?>
|
|
174
231
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
175
232
|
package="${pkg.id || "com.example.app"}">
|
|
176
233
|
|
|
177
|
-
<uses-
|
|
178
|
-
<uses-feature android:name="android.software.leanback" android:required="true" />
|
|
234
|
+
${net} <uses-feature android:name="android.software.leanback" android:required="true" />
|
|
179
235
|
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />
|
|
180
236
|
|
|
181
237
|
<application
|
|
182
238
|
android:allowBackup="true"
|
|
183
|
-
android:icon="@mipmap/ic_launcher"
|
|
184
|
-
android:label="${pkg.name}"
|
|
185
239
|
android:banner="@drawable/banner"
|
|
186
|
-
android:
|
|
187
|
-
|
|
240
|
+
android:icon="@android:drawable/sym_def_app_icon"
|
|
241
|
+
android:label="${pkg.name}"
|
|
242
|
+
${clear} android:theme="@android:style/Theme.DeviceDefault.NoActionBar">
|
|
243
|
+
|
|
188
244
|
<activity
|
|
189
245
|
android:name=".MainActivity"
|
|
190
246
|
android:exported="true"
|
|
@@ -196,79 +252,215 @@ var AndroidAdapter = class {
|
|
|
196
252
|
</activity>
|
|
197
253
|
</application>
|
|
198
254
|
</manifest>`;
|
|
199
|
-
const
|
|
200
|
-
await fs3.ensureDir(path3.dirname(
|
|
201
|
-
await fs3.writeFile(
|
|
255
|
+
const file = path3.join(proj, "app/src/main/AndroidManifest.xml");
|
|
256
|
+
await fs3.ensureDir(path3.dirname(file));
|
|
257
|
+
await fs3.writeFile(file, manifest);
|
|
202
258
|
}
|
|
203
|
-
async
|
|
204
|
-
const
|
|
205
|
-
id
|
|
206
|
-
|
|
259
|
+
async app(proj, pkg, native) {
|
|
260
|
+
const plugins = native ? `plugins {
|
|
261
|
+
id("com.android.application")
|
|
262
|
+
id("org.jetbrains.kotlin.android")
|
|
263
|
+
id("org.jetbrains.kotlin.plugin.compose")
|
|
264
|
+
}` : `plugins {
|
|
265
|
+
id("com.android.application")
|
|
266
|
+
id("org.jetbrains.kotlin.android")
|
|
267
|
+
}`;
|
|
268
|
+
const flags = native ? `
|
|
269
|
+
buildFeatures {
|
|
270
|
+
compose = true
|
|
271
|
+
}` : "";
|
|
272
|
+
const deps = native ? `dependencies {
|
|
273
|
+
val bom = platform("androidx.compose:compose-bom:2026.02.01")
|
|
274
|
+
|
|
275
|
+
implementation(bom)
|
|
276
|
+
androidTestImplementation(bom)
|
|
207
277
|
|
|
278
|
+
implementation("androidx.activity:activity-compose:1.12.4")
|
|
279
|
+
implementation("androidx.compose.foundation:foundation")
|
|
280
|
+
implementation("androidx.compose.ui:ui")
|
|
281
|
+
implementation("androidx.compose.ui:ui-tooling-preview")
|
|
282
|
+
implementation("androidx.tv:tv-material:1.0.0")
|
|
283
|
+
debugImplementation("androidx.compose.ui:ui-tooling")
|
|
284
|
+
}` : `dependencies {
|
|
285
|
+
implementation("androidx.leanback:leanback:1.0.0")
|
|
286
|
+
}`;
|
|
287
|
+
const build2 = `${plugins}
|
|
208
288
|
android {
|
|
209
|
-
namespace
|
|
210
|
-
compileSdk 34
|
|
289
|
+
namespace = "${pkg.id || "com.example.app"}"
|
|
290
|
+
compileSdk = 34
|
|
211
291
|
|
|
212
292
|
defaultConfig {
|
|
213
|
-
applicationId "${pkg.id || "com.example.app"}"
|
|
214
|
-
minSdk 21
|
|
215
|
-
targetSdk 34
|
|
216
|
-
versionCode 1
|
|
217
|
-
versionName "${pkg.version}"
|
|
293
|
+
applicationId = "${pkg.id || "com.example.app"}"
|
|
294
|
+
minSdk = 21
|
|
295
|
+
targetSdk = 34
|
|
296
|
+
versionCode = 1
|
|
297
|
+
versionName = "${pkg.version}"
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
compileOptions {
|
|
301
|
+
sourceCompatibility = JavaVersion.VERSION_17
|
|
302
|
+
targetCompatibility = JavaVersion.VERSION_17
|
|
218
303
|
}
|
|
219
304
|
|
|
305
|
+
kotlinOptions {
|
|
306
|
+
jvmTarget = "17"
|
|
307
|
+
}
|
|
308
|
+
${flags}
|
|
309
|
+
|
|
220
310
|
buildTypes {
|
|
221
311
|
release {
|
|
222
|
-
|
|
223
|
-
proguardFiles
|
|
312
|
+
isMinifyEnabled = true
|
|
313
|
+
proguardFiles(
|
|
314
|
+
getDefaultProguardFile("proguard-android-optimize.txt"),
|
|
315
|
+
"proguard-rules.pro",
|
|
316
|
+
)
|
|
224
317
|
}
|
|
225
318
|
}
|
|
226
319
|
}
|
|
227
320
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
321
|
+
${deps}
|
|
322
|
+
`;
|
|
323
|
+
await fs3.writeFile(path3.join(proj, "app/build.gradle.kts"), build2);
|
|
324
|
+
}
|
|
325
|
+
async res(proj) {
|
|
326
|
+
const banner = `<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
|
327
|
+
<solid android:color="#10151E" />
|
|
328
|
+
<corners android:radius="18dp" />
|
|
329
|
+
</shape>
|
|
330
|
+
`;
|
|
331
|
+
const file = path3.join(proj, "app/src/main/res/drawable/banner.xml");
|
|
332
|
+
await fs3.ensureDir(path3.dirname(file));
|
|
333
|
+
await fs3.writeFile(file, banner);
|
|
232
334
|
}
|
|
233
|
-
async
|
|
234
|
-
const
|
|
235
|
-
const
|
|
335
|
+
async webKt(proj, pkg) {
|
|
336
|
+
const id = pkg.id || "com.example.app";
|
|
337
|
+
const main = `package ${id}
|
|
236
338
|
|
|
237
|
-
import android.app.Activity
|
|
238
|
-
import android.os.Bundle
|
|
239
|
-
import android.webkit.
|
|
240
|
-
import android.webkit.
|
|
339
|
+
import android.app.Activity
|
|
340
|
+
import android.os.Bundle
|
|
341
|
+
import android.webkit.WebSettings
|
|
342
|
+
import android.webkit.WebView
|
|
241
343
|
|
|
242
|
-
|
|
243
|
-
|
|
344
|
+
class MainActivity : Activity() {
|
|
345
|
+
override fun onCreate(savedInstanceState: Bundle?) {
|
|
346
|
+
super.onCreate(savedInstanceState)
|
|
244
347
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
settings.setDomStorageEnabled(true);
|
|
255
|
-
settings.setAllowFileAccess(true);
|
|
256
|
-
|
|
257
|
-
webView.loadUrl("file:///android_asset/www/index.html");
|
|
348
|
+
val web = WebView(this)
|
|
349
|
+
setContentView(web)
|
|
350
|
+
|
|
351
|
+
val set: WebSettings = web.settings
|
|
352
|
+
set.javaScriptEnabled = true
|
|
353
|
+
set.domStorageEnabled = true
|
|
354
|
+
set.allowFileAccess = true
|
|
355
|
+
|
|
356
|
+
web.loadUrl("file:///android_asset/www/index.html")
|
|
258
357
|
}
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
);
|
|
264
|
-
await fs3.ensureDir(path3.dirname(activityPath));
|
|
265
|
-
await fs3.writeFile(activityPath, activity);
|
|
358
|
+
}
|
|
359
|
+
`;
|
|
360
|
+
const file = path3.join(proj, `app/src/main/java/${id.replace(/\./g, "/")}/MainActivity.kt`);
|
|
361
|
+
await fs3.ensureDir(path3.dirname(file));
|
|
362
|
+
await fs3.writeFile(file, main);
|
|
266
363
|
}
|
|
267
|
-
async
|
|
364
|
+
async nativeKt(proj, pkg) {
|
|
365
|
+
const id = pkg.id || "com.example.app";
|
|
366
|
+
const main = `package ${id}
|
|
367
|
+
|
|
368
|
+
import android.os.Bundle
|
|
369
|
+
import androidx.activity.ComponentActivity
|
|
370
|
+
import androidx.activity.compose.setContent
|
|
371
|
+
import androidx.compose.foundation.background
|
|
372
|
+
import androidx.compose.foundation.layout.Arrangement
|
|
373
|
+
import androidx.compose.foundation.layout.Box
|
|
374
|
+
import androidx.compose.foundation.layout.Column
|
|
375
|
+
import androidx.compose.foundation.layout.fillMaxSize
|
|
376
|
+
import androidx.compose.foundation.layout.fillMaxWidth
|
|
377
|
+
import androidx.compose.foundation.layout.padding
|
|
378
|
+
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
379
|
+
import androidx.compose.ui.Alignment
|
|
380
|
+
import androidx.compose.ui.Modifier
|
|
381
|
+
import androidx.compose.ui.graphics.Color
|
|
382
|
+
import androidx.compose.ui.text.style.TextAlign
|
|
383
|
+
import androidx.compose.ui.unit.dp
|
|
384
|
+
import androidx.tv.material3.Button
|
|
385
|
+
import androidx.tv.material3.MaterialTheme
|
|
386
|
+
import androidx.tv.material3.Surface
|
|
387
|
+
import androidx.tv.material3.Text
|
|
388
|
+
|
|
389
|
+
class MainActivity : ComponentActivity() {
|
|
390
|
+
override fun onCreate(savedInstanceState: Bundle?) {
|
|
391
|
+
super.onCreate(savedInstanceState)
|
|
392
|
+
setContent {
|
|
393
|
+
MaterialTheme {
|
|
394
|
+
Surface(modifier = Modifier.fillMaxSize()) {
|
|
395
|
+
Box(
|
|
396
|
+
modifier = Modifier
|
|
397
|
+
.fillMaxSize()
|
|
398
|
+
.background(Color(0xFF05070A))
|
|
399
|
+
.padding(48.dp),
|
|
400
|
+
contentAlignment = Alignment.Center,
|
|
401
|
+
) {
|
|
402
|
+
Column(
|
|
403
|
+
modifier = Modifier
|
|
404
|
+
.fillMaxWidth()
|
|
405
|
+
.background(Color(0xFF10151E), RoundedCornerShape(28.dp))
|
|
406
|
+
.padding(32.dp),
|
|
407
|
+
horizontalAlignment = Alignment.CenterHorizontally,
|
|
408
|
+
verticalArrangement = Arrangement.spacedBy(20.dp),
|
|
409
|
+
) {
|
|
410
|
+
Text(
|
|
411
|
+
text = "${pkg.name}",
|
|
412
|
+
style = MaterialTheme.typography.displayMedium,
|
|
413
|
+
textAlign = TextAlign.Center,
|
|
414
|
+
)
|
|
415
|
+
Text(
|
|
416
|
+
text = "Android native mode uses Kotlin and Compose for TV instead of WebView.",
|
|
417
|
+
style = MaterialTheme.typography.bodyLarge,
|
|
418
|
+
textAlign = TextAlign.Center,
|
|
419
|
+
color = Color(0xFFD4D7DD),
|
|
420
|
+
)
|
|
421
|
+
Button(onClick = {}) {
|
|
422
|
+
Text("Ready")
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
`;
|
|
432
|
+
const file = path3.join(proj, `app/src/main/java/${id.replace(/\./g, "/")}/MainActivity.kt`);
|
|
433
|
+
await fs3.ensureDir(path3.dirname(file));
|
|
434
|
+
await fs3.writeFile(file, main);
|
|
435
|
+
}
|
|
436
|
+
async cmd(proj) {
|
|
437
|
+
if (await fs3.pathExists(path3.join(proj, "gradlew"))) {
|
|
438
|
+
return "./gradlew";
|
|
439
|
+
}
|
|
440
|
+
if (await this.has("gradle")) {
|
|
441
|
+
return "gradle";
|
|
442
|
+
}
|
|
443
|
+
return null;
|
|
444
|
+
}
|
|
445
|
+
async has(cmd) {
|
|
446
|
+
try {
|
|
447
|
+
await execa(cmd, ["--version"]);
|
|
448
|
+
return true;
|
|
449
|
+
} catch {
|
|
450
|
+
return false;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
apk(options) {
|
|
454
|
+
return options.mode === "native" ? "app-native.apk" : "app.apk";
|
|
455
|
+
}
|
|
456
|
+
safe(name) {
|
|
457
|
+
return name.replace(/[^a-z0-9._-]/gi, "-");
|
|
458
|
+
}
|
|
459
|
+
async pkg() {
|
|
268
460
|
try {
|
|
269
461
|
const pkg = await fs3.readJson("package.json");
|
|
270
462
|
return {
|
|
271
|
-
id: pkg.androidAppId || pkg.name
|
|
463
|
+
id: pkg.androidAppId || this.id(pkg.name),
|
|
272
464
|
name: pkg.name,
|
|
273
465
|
version: pkg.version,
|
|
274
466
|
description: pkg.description
|
|
@@ -281,13 +473,17 @@ public class MainActivity extends Activity {
|
|
|
281
473
|
};
|
|
282
474
|
}
|
|
283
475
|
}
|
|
476
|
+
id(name) {
|
|
477
|
+
const slug = name.toLowerCase().replace(/[^a-z0-9]+/g, ".").replace(/^\.+|\.+$/g, "").replace(/\.\.+/g, ".");
|
|
478
|
+
return `com.tablejs.${slug || "app"}`;
|
|
479
|
+
}
|
|
284
480
|
};
|
|
285
481
|
|
|
286
482
|
// src/builder.ts
|
|
287
483
|
async function build(platform, options = {}) {
|
|
288
484
|
const opts = {
|
|
289
|
-
platform,
|
|
290
485
|
outDir: options.outDir || "dist",
|
|
486
|
+
mode: options.mode || "webview",
|
|
291
487
|
minify: options.minify ?? true,
|
|
292
488
|
sourcemap: options.sourcemap ?? false
|
|
293
489
|
};
|
|
@@ -301,21 +497,30 @@ async function build(platform, options = {}) {
|
|
|
301
497
|
}
|
|
302
498
|
await buildPlatform(platform, opts);
|
|
303
499
|
}
|
|
304
|
-
async function buildPlatform(platform,
|
|
500
|
+
async function buildPlatform(platform, base) {
|
|
501
|
+
const options = {
|
|
502
|
+
...base,
|
|
503
|
+
dir: out(base.outDir, platform, base.mode),
|
|
504
|
+
platform
|
|
505
|
+
};
|
|
305
506
|
const adapter = getAdapter(platform);
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
507
|
+
if (web(platform, options.mode)) {
|
|
508
|
+
await viteBuild({
|
|
509
|
+
build: {
|
|
510
|
+
outDir: dir(options),
|
|
511
|
+
minify: options.minify,
|
|
512
|
+
sourcemap: options.sourcemap,
|
|
513
|
+
emptyOutDir: true
|
|
514
|
+
},
|
|
515
|
+
define: {
|
|
516
|
+
__TABLE_PLATFORM__: JSON.stringify(platform)
|
|
517
|
+
}
|
|
518
|
+
});
|
|
519
|
+
} else {
|
|
520
|
+
await fs4.emptyDir(options.dir);
|
|
521
|
+
}
|
|
317
522
|
await adapter.build(options);
|
|
318
|
-
const packagePath = await adapter.package(
|
|
523
|
+
const packagePath = await adapter.package(options);
|
|
319
524
|
console.log(`\u2713 ${adapter.name} package created: ${packagePath}`);
|
|
320
525
|
}
|
|
321
526
|
function getAdapter(platform) {
|
|
@@ -330,11 +535,26 @@ function getAdapter(platform) {
|
|
|
330
535
|
throw new Error(`Unknown platform: ${platform}`);
|
|
331
536
|
}
|
|
332
537
|
}
|
|
538
|
+
function out(root, platform, mode) {
|
|
539
|
+
if (platform === "android" && mode === "native") {
|
|
540
|
+
return `${root}/android-native`;
|
|
541
|
+
}
|
|
542
|
+
return `${root}/${platform}`;
|
|
543
|
+
}
|
|
544
|
+
function dir(options) {
|
|
545
|
+
if (options.platform === "android") {
|
|
546
|
+
return `${options.dir}/www`;
|
|
547
|
+
}
|
|
548
|
+
return options.dir;
|
|
549
|
+
}
|
|
550
|
+
function web(platform, mode) {
|
|
551
|
+
return platform !== "android" || mode === "webview";
|
|
552
|
+
}
|
|
333
553
|
|
|
334
554
|
// src/cli.ts
|
|
335
555
|
var program = new Command();
|
|
336
556
|
program.name("table").description("Table.js build tool for Smart TV platforms").version("0.0.1");
|
|
337
|
-
program.command("build").description("Build for target platform").option("-p, --platform <platform>", "Target platform (tizen, webos, android, all)", "all").option("-o, --out <dir>", "Output directory", "dist").option("--no-minify", "Disable minification").option("--sourcemap", "Generate sourcemaps").action(async (options) => {
|
|
557
|
+
program.command("build").description("Build for target platform").option("-p, --platform <platform>", "Target platform (tizen, webos, android, all)", "all").option("-m, --mode <mode>", "Android mode (webview, native)", "webview").option("-o, --out <dir>", "Output directory", "dist").option("--no-minify", "Disable minification").option("--sourcemap", "Generate sourcemaps").action(async (options) => {
|
|
338
558
|
const platform = options.platform;
|
|
339
559
|
console.log();
|
|
340
560
|
console.log(chalk.bold(" table.js") + chalk.dim(" \u2014 Building for Smart TV"));
|
|
@@ -343,6 +563,7 @@ program.command("build").description("Build for target platform").option("-p, --
|
|
|
343
563
|
try {
|
|
344
564
|
await build(platform, {
|
|
345
565
|
outDir: options.out,
|
|
566
|
+
mode: options.mode,
|
|
346
567
|
minify: options.minify,
|
|
347
568
|
sourcemap: options.sourcemap
|
|
348
569
|
});
|
package/dist/index.d.mts
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
type Platform = 'tizen' | 'webos' | 'android' | 'all';
|
|
2
|
+
type Target = Exclude<Platform, 'all'>;
|
|
3
|
+
type Mode = 'webview' | 'native';
|
|
2
4
|
interface BuildOptions {
|
|
3
|
-
platform:
|
|
5
|
+
platform: Target;
|
|
4
6
|
outDir: string;
|
|
7
|
+
dir: string;
|
|
5
8
|
minify: boolean;
|
|
9
|
+
mode: Mode;
|
|
6
10
|
sourcemap: boolean;
|
|
7
11
|
}
|
|
8
12
|
interface PlatformAdapter {
|
|
9
13
|
name: string;
|
|
10
14
|
build(options: BuildOptions): Promise<void>;
|
|
11
|
-
package(
|
|
15
|
+
package(options: BuildOptions): Promise<string>;
|
|
12
16
|
}
|
|
13
17
|
interface ManifestBase {
|
|
14
18
|
id: string;
|
|
@@ -23,7 +27,7 @@ declare function build(platform: Platform, options?: Partial<BuildOptions>): Pro
|
|
|
23
27
|
declare class TizenAdapter implements PlatformAdapter {
|
|
24
28
|
name: string;
|
|
25
29
|
build(options: BuildOptions): Promise<void>;
|
|
26
|
-
package(
|
|
30
|
+
package(options: BuildOptions): Promise<string>;
|
|
27
31
|
private createConfig;
|
|
28
32
|
private readPackageJson;
|
|
29
33
|
}
|
|
@@ -31,7 +35,7 @@ declare class TizenAdapter implements PlatformAdapter {
|
|
|
31
35
|
declare class WebOSAdapter implements PlatformAdapter {
|
|
32
36
|
name: string;
|
|
33
37
|
build(options: BuildOptions): Promise<void>;
|
|
34
|
-
package(
|
|
38
|
+
package(options: BuildOptions): Promise<string>;
|
|
35
39
|
private createAppInfo;
|
|
36
40
|
private readPackageJson;
|
|
37
41
|
}
|
|
@@ -39,12 +43,21 @@ declare class WebOSAdapter implements PlatformAdapter {
|
|
|
39
43
|
declare class AndroidAdapter implements PlatformAdapter {
|
|
40
44
|
name: string;
|
|
41
45
|
build(options: BuildOptions): Promise<void>;
|
|
42
|
-
package(
|
|
43
|
-
private
|
|
44
|
-
private
|
|
45
|
-
private
|
|
46
|
-
private
|
|
47
|
-
private
|
|
46
|
+
package(options: BuildOptions): Promise<string>;
|
|
47
|
+
private web;
|
|
48
|
+
private native;
|
|
49
|
+
private root;
|
|
50
|
+
private man;
|
|
51
|
+
private app;
|
|
52
|
+
private res;
|
|
53
|
+
private webKt;
|
|
54
|
+
private nativeKt;
|
|
55
|
+
private cmd;
|
|
56
|
+
private has;
|
|
57
|
+
private apk;
|
|
58
|
+
private safe;
|
|
59
|
+
private pkg;
|
|
60
|
+
private id;
|
|
48
61
|
}
|
|
49
62
|
|
|
50
|
-
export { AndroidAdapter, type BuildOptions, type ManifestBase, type Platform, type PlatformAdapter, TizenAdapter, WebOSAdapter, build };
|
|
63
|
+
export { AndroidAdapter, type BuildOptions, type ManifestBase, type Mode, type Platform, type PlatformAdapter, type Target, TizenAdapter, WebOSAdapter, build };
|