@putdotio/taizn 1.3.0 → 1.5.0
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 +6 -1
- package/dist/taizn.mjs +118 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -46,6 +46,9 @@ Project files:
|
|
|
46
46
|
|
|
47
47
|
```bash
|
|
48
48
|
taizn check
|
|
49
|
+
taizn apps
|
|
50
|
+
taizn apps put
|
|
51
|
+
taizn launch GinifYRGmZ.putio
|
|
49
52
|
taizn profile
|
|
50
53
|
taizn package
|
|
51
54
|
taizn install
|
|
@@ -58,7 +61,9 @@ taizn --version
|
|
|
58
61
|
```
|
|
59
62
|
|
|
60
63
|
`check` verifies the configured Tizen CLI and `sdb`, then prints connected
|
|
61
|
-
targets without requiring `taizn.json`. `
|
|
64
|
+
targets without requiring `taizn.json`. `apps` lists installed applications on
|
|
65
|
+
the target, with an optional query filter. `launch` starts an already-installed
|
|
66
|
+
application by exact application ID, exact name, or a unique query. `profile` imports
|
|
62
67
|
`.taizn/certificates/author.p12` and
|
|
63
68
|
`.taizn/certificates/distributor.p12` into a Tizen security profile.
|
|
64
69
|
`package` builds and signs a `.wgt`. `install` packages and sideloads it.
|
package/dist/taizn.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { NodeRuntime, NodeServices } from "@effect/platform-node";
|
|
3
3
|
import { Argument, CliError, Command, Flag } from "effect/unstable/cli";
|
|
4
|
-
import { Console, Context, Effect, FileSystem, Layer, Schema, Stream } from "effect";
|
|
4
|
+
import { Console, Context, Effect, FileSystem, Layer, Option, Schema, Stream } from "effect";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import { homedir } from "node:os";
|
|
7
7
|
import { existsSync } from "node:fs";
|
|
@@ -57,6 +57,19 @@ var CommandFailed = class extends Schema.TaggedErrorClass()("CommandFailed", {
|
|
|
57
57
|
return `Command failed: ${this.command} ${this.args.join(" ")}`;
|
|
58
58
|
}
|
|
59
59
|
};
|
|
60
|
+
var ApplicationNotFound = class extends Schema.TaggedErrorClass()("ApplicationNotFound", { query: Schema.String }) {
|
|
61
|
+
get message() {
|
|
62
|
+
return `No installed Tizen application matched "${this.query}".`;
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
var MultipleApplicationsMatched = class extends Schema.TaggedErrorClass()("MultipleApplicationsMatched", {
|
|
66
|
+
matches: Schema.Array(Schema.String),
|
|
67
|
+
query: Schema.String
|
|
68
|
+
}) {
|
|
69
|
+
get message() {
|
|
70
|
+
return `Multiple installed Tizen applications matched "${this.query}": ${this.matches.join(", ")}. Use the application ID.`;
|
|
71
|
+
}
|
|
72
|
+
};
|
|
60
73
|
var PackageNotProduced = class extends Schema.TaggedErrorClass()("PackageNotProduced", { outputDir: Schema.String }) {
|
|
61
74
|
get message() {
|
|
62
75
|
return `No .wgt package was produced in ${this.outputDir}`;
|
|
@@ -80,6 +93,11 @@ var MultipleTargetsConnected = class extends Schema.TaggedErrorClass()("Multiple
|
|
|
80
93
|
return `Multiple Tizen targets are connected: ${this.targets.join(", ")}. Set TAIZN_TARGET explicitly.`;
|
|
81
94
|
}
|
|
82
95
|
};
|
|
96
|
+
var MissingTizenTarget = class extends Schema.TaggedErrorClass()("MissingTizenTarget", {}) {
|
|
97
|
+
get message() {
|
|
98
|
+
return "No Tizen target is connected. Set TAIZN_TARGET or connect exactly one device.";
|
|
99
|
+
}
|
|
100
|
+
};
|
|
83
101
|
var MissingTvRemoteHost = class extends Schema.TaggedErrorClass()("MissingTvRemoteHost", {}) {
|
|
84
102
|
get message() {
|
|
85
103
|
return "Samsung TV host is required. Set TAIZN_TV_HOST or TAIZN_TARGET.";
|
|
@@ -793,6 +811,32 @@ const runWidget = Effect.fn("runWidget")(function* ({ config, env }) {
|
|
|
793
811
|
], { env: yield* baseChildEnv() });
|
|
794
812
|
yield* Console.log(`Launched ${variant.applicationId}`);
|
|
795
813
|
});
|
|
814
|
+
const listInstalledApplications = Effect.fn("listInstalledApplications")(function* (env, query) {
|
|
815
|
+
const { applications: installedApplications, target } = yield* loadInstalledApplications(env);
|
|
816
|
+
const queryLabel = query?.trim();
|
|
817
|
+
const normalizedQuery = normalizeQuery(queryLabel);
|
|
818
|
+
const applications = installedApplications.filter((application) => matchesApplicationQuery(application, normalizedQuery));
|
|
819
|
+
const suffix = queryLabel ? ` matching "${queryLabel}"` : "";
|
|
820
|
+
yield* Console.log(`Installed Tizen applications${suffix} on ${target}:`);
|
|
821
|
+
if (applications.length === 0) {
|
|
822
|
+
yield* Console.log("none");
|
|
823
|
+
return;
|
|
824
|
+
}
|
|
825
|
+
for (const application of applications) yield* Console.log(`- ${application.name} (${application.applicationId})`);
|
|
826
|
+
});
|
|
827
|
+
const launchInstalledApplication = Effect.fn("launchInstalledApplication")(function* (env, query) {
|
|
828
|
+
const tizenPath = yield* resolveTizenCli(env);
|
|
829
|
+
const { applications, target } = yield* loadInstalledApplications(env);
|
|
830
|
+
const application = yield* resolveInstalledApplication(query, applications);
|
|
831
|
+
yield* run$1(tizenPath, [
|
|
832
|
+
"run",
|
|
833
|
+
"-p",
|
|
834
|
+
application.applicationId,
|
|
835
|
+
"-s",
|
|
836
|
+
target
|
|
837
|
+
], { env: yield* baseChildEnv() });
|
|
838
|
+
yield* Console.log(`Launched ${application.name} (${application.applicationId}) on ${target}`);
|
|
839
|
+
});
|
|
796
840
|
const resolveTizenCli = Effect.fn("resolveTizenCli")(function* (env) {
|
|
797
841
|
return yield* requireFile(env.tizenCli ?? (yield* defaultTizenCli()), "Tizen CLI");
|
|
798
842
|
});
|
|
@@ -971,6 +1015,71 @@ const resolveRunTarget = Effect.fn("resolveRunTarget")(function* (env, sdbPath)
|
|
|
971
1015
|
}
|
|
972
1016
|
if (devices.length > 1) return yield* MultipleTargetsConnected.make({ targets: devices.map((device) => device.id) });
|
|
973
1017
|
});
|
|
1018
|
+
const resolveRequiredSdbTarget = Effect.fn("resolveRequiredSdbTarget")(function* (env, sdbPath) {
|
|
1019
|
+
if (env.target) return env.target;
|
|
1020
|
+
const devices = yield* listSdbDevices(sdbPath);
|
|
1021
|
+
if (devices.length === 1) {
|
|
1022
|
+
const device = devices[0];
|
|
1023
|
+
if (device) {
|
|
1024
|
+
yield* Console.log(`Using connected Tizen target: ${device.id}${device.label ? ` (${device.label})` : ""}`);
|
|
1025
|
+
return device.id;
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
if (devices.length > 1) return yield* MultipleTargetsConnected.make({ targets: devices.map((device) => device.id) });
|
|
1029
|
+
return yield* MissingTizenTarget.make({});
|
|
1030
|
+
});
|
|
1031
|
+
const loadInstalledApplications = Effect.fn("loadInstalledApplications")(function* (env) {
|
|
1032
|
+
const sdbPath = yield* resolveSdb(env);
|
|
1033
|
+
if (env.target) yield* run$1(sdbPath, ["connect", env.target], { env: yield* baseChildEnv() });
|
|
1034
|
+
const target = yield* resolveRequiredSdbTarget(env, sdbPath);
|
|
1035
|
+
return {
|
|
1036
|
+
applications: parseInstalledApplications(yield* capture(sdbPath, [
|
|
1037
|
+
"-s",
|
|
1038
|
+
target,
|
|
1039
|
+
"shell",
|
|
1040
|
+
"0",
|
|
1041
|
+
"applist"
|
|
1042
|
+
])),
|
|
1043
|
+
target
|
|
1044
|
+
};
|
|
1045
|
+
});
|
|
1046
|
+
const parseInstalledApplications = (output) => output.split("\n").flatMap((line) => {
|
|
1047
|
+
const match = line.match(/^\s*'([^']*)'\s+'([^']*)'\s*$/);
|
|
1048
|
+
const name = match?.[1]?.trim();
|
|
1049
|
+
const applicationId = match?.[2]?.trim();
|
|
1050
|
+
return name && applicationId ? [{
|
|
1051
|
+
applicationId,
|
|
1052
|
+
name
|
|
1053
|
+
}] : [];
|
|
1054
|
+
});
|
|
1055
|
+
const normalizeQuery = (query) => query?.trim().toLowerCase();
|
|
1056
|
+
const matchesApplicationQuery = (application, normalizedQuery) => !normalizedQuery || application.name.toLowerCase().includes(normalizedQuery) || application.applicationId.toLowerCase().includes(normalizedQuery);
|
|
1057
|
+
const resolveInstalledApplication = Effect.fn("resolveInstalledApplication")(function* (query, applications) {
|
|
1058
|
+
const queryLabel = query.trim();
|
|
1059
|
+
const normalizedQuery = normalizeQuery(queryLabel);
|
|
1060
|
+
if (!normalizedQuery) return yield* ApplicationNotFound.make({ query });
|
|
1061
|
+
const exactMatch = applications.find((application) => application.applicationId.toLowerCase() === normalizedQuery);
|
|
1062
|
+
if (exactMatch) return exactMatch;
|
|
1063
|
+
const exactNameMatches = applications.filter((application) => application.name.toLowerCase() === normalizedQuery);
|
|
1064
|
+
if (exactNameMatches.length === 1) {
|
|
1065
|
+
const [match] = exactNameMatches;
|
|
1066
|
+
if (match) return match;
|
|
1067
|
+
}
|
|
1068
|
+
if (exactNameMatches.length > 1) return yield* MultipleApplicationsMatched.make({
|
|
1069
|
+
matches: exactNameMatches.map((application) => `${application.name} (${application.applicationId})`),
|
|
1070
|
+
query: queryLabel
|
|
1071
|
+
});
|
|
1072
|
+
const matches = applications.filter((application) => matchesApplicationQuery(application, normalizedQuery));
|
|
1073
|
+
if (matches.length === 1) {
|
|
1074
|
+
const [match] = matches;
|
|
1075
|
+
if (match) return match;
|
|
1076
|
+
}
|
|
1077
|
+
if (matches.length > 1) return yield* MultipleApplicationsMatched.make({
|
|
1078
|
+
matches: matches.map((application) => `${application.name} (${application.applicationId})`),
|
|
1079
|
+
query: queryLabel
|
|
1080
|
+
});
|
|
1081
|
+
return yield* ApplicationNotFound.make({ query: queryLabel });
|
|
1082
|
+
});
|
|
974
1083
|
const run$1 = Effect.fn("run")(function* (command, args, options) {
|
|
975
1084
|
const paths = yield* getPaths();
|
|
976
1085
|
const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;
|
|
@@ -1028,6 +1137,12 @@ const taizn = Command.make("taizn", {}, () => withContext((context) => packageWi
|
|
|
1028
1137
|
const check = Command.make("check", {}, () => Effect.gen(function* () {
|
|
1029
1138
|
yield* checkTizen(yield* loadEnv());
|
|
1030
1139
|
}));
|
|
1140
|
+
const apps = Command.make("apps", { query: Argument.string("query").pipe(Argument.optional) }, ({ query }) => Effect.gen(function* () {
|
|
1141
|
+
yield* listInstalledApplications(yield* loadEnv(), Option.getOrUndefined(query));
|
|
1142
|
+
}));
|
|
1143
|
+
const launch = Command.make("launch", { query: Argument.string("query") }, ({ query }) => Effect.gen(function* () {
|
|
1144
|
+
yield* launchInstalledApplication(yield* loadEnv(), query);
|
|
1145
|
+
}));
|
|
1031
1146
|
const profile = Command.make("profile", {}, () => withContext((context) => createProfile(context)));
|
|
1032
1147
|
const pack = Command.make("package", {}, () => withContext((context) => packageWidget(context).pipe(Effect.asVoid)));
|
|
1033
1148
|
const install = Command.make("install", {}, () => withContext((context) => installWidget(context)));
|
|
@@ -1050,7 +1165,9 @@ const tv = Command.make("tv", {}).pipe(Command.withSubcommands([
|
|
|
1050
1165
|
tvInfo
|
|
1051
1166
|
]));
|
|
1052
1167
|
const command = taizn.pipe(Command.withSubcommands([
|
|
1168
|
+
apps,
|
|
1053
1169
|
check,
|
|
1170
|
+
launch,
|
|
1054
1171
|
profile,
|
|
1055
1172
|
pack,
|
|
1056
1173
|
install,
|