@putdotio/taizn 1.0.1

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.
Files changed (4) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +120 -0
  3. package/dist/taizn.mjs +377 -0
  4. package/package.json +65 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 put.io
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,120 @@
1
+ <div align="center">
2
+ <p>
3
+ <img src="https://static.put.io/images/putio-boncuk.png" width="72">
4
+ </p>
5
+
6
+ <h1>taizn</h1>
7
+
8
+ <p>A tiny CLI companion for interacting with Tizen ecosystem.</p>
9
+
10
+ <p>
11
+ <a href="https://github.com/putdotio/taizn/actions/workflows/ci.yml?query=branch%3Amain" style="text-decoration:none;"><img src="https://img.shields.io/github/actions/workflow/status/putdotio/taizn/ci.yml?branch=main&style=flat&label=ci&colorA=000000&colorB=000000" alt="CI"></a>
12
+ <a href="https://www.npmjs.com/package/@putdotio/taizn" style="text-decoration:none;"><img src="https://img.shields.io/npm/v/%40putdotio%2Ftaizn?style=flat&label=npm&logo=npm&colorA=000000&colorB=000000" alt="npm version"></a>
13
+ <a href="https://github.com/putdotio/taizn/blob/main/LICENSE" style="text-decoration:none;"><img src="https://img.shields.io/github/license/putdotio/taizn?style=flat&label=license&colorA=000000&colorB=000000" alt="License"></a>
14
+ </p>
15
+ </div>
16
+
17
+ ## Install
18
+
19
+ ```bash
20
+ pnpm add -D @putdotio/taizn
21
+ ```
22
+
23
+ Install the Tizen command-line tools and make sure `tizen` and `sdb` work
24
+ locally.
25
+
26
+ ## Usage
27
+
28
+ Create `taizn.json` in the app directory, keep `.taizn/` ignored, then run:
29
+
30
+ ```bash
31
+ pnpm exec taizn package
32
+ pnpm exec taizn install
33
+ ```
34
+
35
+ Project files:
36
+
37
+ - `taizn.json`: app build, widget, signing, and variant config
38
+ - `.taizn/.env`: optional local secrets read by Node
39
+ - `.taizn/certificates/`: optional local author/distributor certs for `taizn profile`
40
+ - `.taizn/build/`: generated package staging and output
41
+
42
+ ## Commands
43
+
44
+ ```bash
45
+ taizn profile
46
+ taizn package
47
+ taizn install
48
+ taizn --version
49
+ ```
50
+
51
+ `profile` imports `.taizn/certificates/author.p12` and
52
+ `.taizn/certificates/distributor.p12` into a Tizen security profile.
53
+ `package` builds and signs a `.wgt`. `install` packages and sideloads it.
54
+
55
+ ## Environment
56
+
57
+ ```bash
58
+ TAIZN_CERT_PASSWORD=...
59
+ TAIZN_DIST_PASSWORD=...
60
+ TAIZN_VARIANT=development
61
+ TAIZN_TARGET=<tv-ip>:26101
62
+ TAIZN_TIZEN_CLI=~/tizen-studio/tools/ide/bin/tizen
63
+ TAIZN_SDB=~/tizen-studio/tools/sdb
64
+ ```
65
+
66
+ ## Config
67
+
68
+ ```json
69
+ {
70
+ "build": {
71
+ "command": ["pnpm", "build"],
72
+ "output": "dist",
73
+ "requiredFiles": ["main.css", "main.js"]
74
+ },
75
+ "signing": {
76
+ "certificateDir": ".taizn/certificates",
77
+ "profile": "my-tizen-profile"
78
+ },
79
+ "widget": {
80
+ "configXml": "platforms/tizen/config.xml",
81
+ "indexHtml": "platforms/tizen/index.html",
82
+ "injectWebapis": true,
83
+ "rewriteAssetUrls": false,
84
+ "variants": {
85
+ "development": {
86
+ "applicationId": "ExampleDev.app",
87
+ "bundleName": "example-dev",
88
+ "icon": "platforms/tizen/icons/dev.png",
89
+ "name": "Example Dev",
90
+ "packageId": "ExampleDev"
91
+ },
92
+ "production": {
93
+ "applicationId": "Example.app",
94
+ "bundleName": "example",
95
+ "icon": "platforms/tizen/icon.png",
96
+ "name": "Example",
97
+ "packageId": "Example"
98
+ }
99
+ }
100
+ }
101
+ }
102
+ ```
103
+
104
+ ## Docs
105
+
106
+ - [Contributing](./CONTRIBUTING.md)
107
+ - [Distribution](./docs/DISTRIBUTION.md)
108
+ - [Security](./SECURITY.md)
109
+
110
+ ## Repo Internals
111
+
112
+ - [Agent guide](./AGENTS.md)
113
+
114
+ ## Contributing
115
+
116
+ See [Contributing](./CONTRIBUTING.md) for setup, checks, and pull request flow.
117
+
118
+ ## License
119
+
120
+ [MIT](./LICENSE)
package/dist/taizn.mjs ADDED
@@ -0,0 +1,377 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from "@effect/cli";
3
+ import { NodeContext, NodeRuntime } from "@effect/platform-node";
4
+ import { Effect } from "effect";
5
+ import { copyFileSync, cpSync, existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
6
+ import * as ParseResult from "effect/ParseResult";
7
+ import * as Schema from "effect/Schema";
8
+ import { execFileSync } from "node:child_process";
9
+ import { homedir } from "node:os";
10
+ import { isAbsolute, join } from "node:path";
11
+ //#region src/runtime.ts
12
+ const appDir = process.cwd();
13
+ const configPath = join(appDir, "taizn.json");
14
+ const taiznDir = join(appDir, ".taizn");
15
+ const envPath = join(taiznDir, ".env");
16
+ const stageDir = join(taiznDir, "build", "stage");
17
+ const outputDir = join(taiznDir, "build", "output");
18
+ const appPath = (path) => isAbsolute(path) ? path : join(appDir, path);
19
+ const loadLocalEnv = () => {
20
+ if (existsSync(envPath)) process.loadEnvFile(envPath);
21
+ };
22
+ const fail = (message) => {
23
+ console.error(message);
24
+ process.exit(1);
25
+ };
26
+ const requireFile = (path, label) => {
27
+ if (!existsSync(path)) fail(`${label} not found: ${path}`);
28
+ return path;
29
+ };
30
+ const baseChildEnv = () => {
31
+ const env = { ...process.env };
32
+ delete env.DYLD_INSERT_LIBRARIES;
33
+ return env;
34
+ };
35
+ const appBuildEnv = () => {
36
+ const env = baseChildEnv();
37
+ for (const key of Object.keys(env)) if (key.startsWith("TAIZN_") || key.startsWith("TIZEN_")) delete env[key];
38
+ delete env.SDB;
39
+ return env;
40
+ };
41
+ const run = (command, args, options = {}) => {
42
+ const env = options.env || baseChildEnv();
43
+ try {
44
+ execFileSync(command, args, {
45
+ cwd: options.cwd || appDir,
46
+ env: {
47
+ ...env,
48
+ PATH: `${join(homedir(), "tizen-studio/tools/ide/bin")}:${join(homedir(), "tizen-studio/tools")}:${env.PATH || ""}`
49
+ },
50
+ stdio: options.stdio || "inherit"
51
+ });
52
+ } catch {
53
+ fail(`Command failed: ${command} ${redactCommandArgs(args).join(" ")}`);
54
+ }
55
+ };
56
+ const tizenCli = (path) => requireFile(path || join(homedir(), "tizen-studio/tools/ide/bin/tizen"), "Tizen CLI");
57
+ const sdb = (path) => requireFile(path || join(homedir(), "tizen-studio/tools/sdb"), "sdb");
58
+ const readPassword = async (value, prompt) => {
59
+ if (value) return value;
60
+ return readSecret(prompt);
61
+ };
62
+ const redactCommandArgs = (args) => {
63
+ const sensitiveValueFlags = new Set(["-p", "-dp"]);
64
+ return args.map((arg, index) => {
65
+ if (index > 0 && sensitiveValueFlags.has(args[index - 1])) return "[redacted]";
66
+ return arg;
67
+ });
68
+ };
69
+ const readSecret = (prompt) => new Promise((resolve) => {
70
+ if (!process.stdin.isTTY) {
71
+ resolve("");
72
+ return;
73
+ }
74
+ let value = "";
75
+ process.stdout.write(prompt);
76
+ process.stdin.setRawMode(true);
77
+ process.stdin.resume();
78
+ process.stdin.setEncoding("utf8");
79
+ const onData = (char) => {
80
+ if (char === "") {
81
+ process.stdout.write("\n");
82
+ process.exit(130);
83
+ }
84
+ if (char === "\r" || char === "\n") {
85
+ process.stdin.setRawMode(false);
86
+ process.stdin.pause();
87
+ process.stdin.off("data", onData);
88
+ process.stdout.write("\n");
89
+ resolve(value);
90
+ return;
91
+ }
92
+ if (char === "") {
93
+ value = value.slice(0, -1);
94
+ return;
95
+ }
96
+ value += char;
97
+ };
98
+ process.stdin.on("data", onData);
99
+ });
100
+ //#endregion
101
+ //#region src/config.ts
102
+ const TizenVariantSchema = Schema.Struct({
103
+ applicationId: Schema.NonEmptyString,
104
+ bundleName: Schema.NonEmptyString,
105
+ icon: Schema.NonEmptyString,
106
+ name: Schema.NonEmptyString,
107
+ packageId: Schema.NonEmptyString
108
+ });
109
+ const TizenConfigSchema = Schema.Struct({
110
+ build: Schema.Struct({
111
+ command: Schema.NonEmptyArray(Schema.NonEmptyString),
112
+ output: Schema.NonEmptyString,
113
+ requiredFiles: Schema.optional(Schema.Array(Schema.NonEmptyString))
114
+ }),
115
+ signing: Schema.Struct({
116
+ certificateDir: Schema.NonEmptyString,
117
+ profile: Schema.NonEmptyString
118
+ }),
119
+ widget: Schema.Struct({
120
+ configXml: Schema.NonEmptyString,
121
+ indexHtml: Schema.NonEmptyString,
122
+ injectWebapis: Schema.optional(Schema.Boolean),
123
+ rewriteAssetUrls: Schema.optional(Schema.Boolean),
124
+ variants: Schema.Struct({
125
+ development: TizenVariantSchema,
126
+ production: TizenVariantSchema
127
+ })
128
+ })
129
+ });
130
+ const loadConfig = () => {
131
+ if (!existsSync(configPath)) fail(`Config file not found: ${configPath}`);
132
+ return decodeConfig(readFileSync(configPath, "utf8"));
133
+ };
134
+ const decodeConfig = (source) => {
135
+ try {
136
+ return Schema.decodeUnknownSync(Schema.parseJson(TizenConfigSchema), { errors: "all" })(source);
137
+ } catch (error) {
138
+ if (ParseResult.isParseError(error)) return fail(`Invalid taizn.json:\n${formatParseIssues$1(error)}`);
139
+ return fail(`Invalid taizn.json: ${error instanceof Error ? error.message : String(error)}`);
140
+ }
141
+ };
142
+ const formatParseIssues$1 = (error) => ParseResult.ArrayFormatter.formatErrorSync(error).map((issue) => {
143
+ return `- ${issue.path.length > 0 ? issue.path.join(".") : "taizn.json"}: ${issue.message}`;
144
+ }).join("\n");
145
+ //#endregion
146
+ //#region src/env.ts
147
+ const TaiznEnvSchema = Schema.Struct({
148
+ certPassword: Schema.optional(Schema.String),
149
+ distPassword: Schema.optional(Schema.String),
150
+ sdb: Schema.optional(Schema.String),
151
+ target: Schema.optional(Schema.String),
152
+ tizenCli: Schema.optional(Schema.String),
153
+ variant: Schema.optional(Schema.Literal("development", "production"))
154
+ });
155
+ const loadEnv = () => {
156
+ try {
157
+ const env = Schema.decodeUnknownSync(TaiznEnvSchema)({
158
+ certPassword: process.env.TAIZN_CERT_PASSWORD,
159
+ distPassword: process.env.TAIZN_DIST_PASSWORD,
160
+ sdb: process.env.TAIZN_SDB,
161
+ target: process.env.TAIZN_TARGET,
162
+ tizenCli: process.env.TAIZN_TIZEN_CLI,
163
+ variant: process.env.TAIZN_VARIANT
164
+ });
165
+ return {
166
+ ...env,
167
+ variant: env.variant ?? "development"
168
+ };
169
+ } catch (error) {
170
+ if (ParseResult.isParseError(error)) return fail(`Invalid TAIZN environment:\n${formatParseIssues(error)}`);
171
+ return fail(`Invalid TAIZN environment: ${error instanceof Error ? error.message : String(error)}`);
172
+ }
173
+ };
174
+ const formatParseIssues = (error) => ParseResult.ArrayFormatter.formatErrorSync(error).map((issue) => {
175
+ return `- ${issue.path.length > 0 ? issue.path.join(".") : "TAIZN environment"}: ${issue.message}`;
176
+ }).join("\n");
177
+ //#endregion
178
+ //#region src/context.ts
179
+ const loadContext = () => ({
180
+ config: loadConfig(),
181
+ env: loadEnv()
182
+ });
183
+ //#endregion
184
+ //#region src/xml.ts
185
+ const escapeXml = (value) => value.replaceAll("&", "&amp;").replaceAll("\"", "&quot;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
186
+ const setXmlAttribute = (tag, attribute, value) => {
187
+ const escapedValue = escapeXml(value);
188
+ const attributePattern = new RegExp(`\\b${attribute}="[^"]*"`);
189
+ if (attributePattern.test(tag)) return tag.replace(attributePattern, `${attribute}="${escapedValue}"`);
190
+ return tag.replace(/\/?>$/, ` ${attribute}="${escapedValue}"$&`);
191
+ };
192
+ //#endregion
193
+ //#region src/tizen.ts
194
+ const createProfile = async ({ config, env }) => {
195
+ const password = await readPassword(env.certPassword, "Tizen certificate password: ");
196
+ if (!password) fail("TAIZN_CERT_PASSWORD is required to create the signing profile.");
197
+ const certificates = getCertificates(config);
198
+ const distributorPassword = env.distPassword || password;
199
+ run(tizenCli(env.tizenCli), [
200
+ "security-profiles",
201
+ "add",
202
+ "-f",
203
+ "-A",
204
+ "-n",
205
+ config.signing.profile,
206
+ "-a",
207
+ certificates.author,
208
+ "-p",
209
+ password,
210
+ "-d",
211
+ certificates.distributor,
212
+ "-dp",
213
+ distributorPassword
214
+ ]);
215
+ console.log(`Configured active Tizen signing profile: ${config.signing.profile}`);
216
+ };
217
+ const packageWidget = ({ config, env }) => {
218
+ const [command, ...args] = config.build.command;
219
+ run(command, args, { env: appBuildEnv() });
220
+ stageWidget(config, getVariant(config, env.variant));
221
+ run(tizenCli(env.tizenCli), [
222
+ "package",
223
+ "-t",
224
+ "wgt",
225
+ "-s",
226
+ config.signing.profile,
227
+ "-o",
228
+ outputDir,
229
+ "--",
230
+ stageDir
231
+ ]);
232
+ const built = findBuiltWidget();
233
+ const installable = join(outputDir, `${getVariant(config, env.variant).bundleName}.wgt`);
234
+ if (built !== installable) copyFileSync(built, installable);
235
+ console.log(`Packaged ${installable}`);
236
+ return installable;
237
+ };
238
+ const installWidget = (context) => {
239
+ const built = packageWidget(context);
240
+ const target = resolveInstallTarget(context.env);
241
+ if (context.env.target) run(sdb(context.env.sdb), ["connect", context.env.target]);
242
+ const installArgs = [
243
+ "install",
244
+ "-n",
245
+ built
246
+ ];
247
+ if (target) installArgs.push("-s", target);
248
+ run(tizenCli(context.env.tizenCli), installArgs);
249
+ };
250
+ const getVariant = (config, variant) => config.widget.variants[variant];
251
+ const getCertificates = (config) => {
252
+ const certificatesDir = appPath(config.signing.certificateDir);
253
+ return {
254
+ author: requireFile(join(certificatesDir, "author.p12"), "Author certificate"),
255
+ distributor: requireFile(join(certificatesDir, "distributor.p12"), "Distributor certificate")
256
+ };
257
+ };
258
+ const rewriteConfigForWidget = (variant) => {
259
+ const targetPath = join(stageDir, "config.xml");
260
+ let widgetConfig = readFileSync(targetPath, "utf8");
261
+ widgetConfig = widgetConfig.replace(/<tizen:application\b[^>]*\/>/, (tag) => setXmlAttribute(setXmlAttribute(tag, "id", variant.applicationId), "package", variant.packageId));
262
+ widgetConfig = widgetConfig.replace(/<name>[^<]*<\/name>/, `<name>${escapeXml(variant.name)}</name>`);
263
+ writeFileSync(targetPath, widgetConfig);
264
+ };
265
+ const rewriteIndexForWidget = (config) => {
266
+ const targetPath = join(stageDir, "index.html");
267
+ const webapisScript = "<script src=\"$WEBAPIS/webapis/webapis.js\"><\/script>";
268
+ let html = readFileSync(appPath(config.widget.indexHtml), "utf8");
269
+ if (config.widget.rewriteAssetUrls) html = html.replaceAll("href=\"/", "href=\"./").replaceAll("src=\"/", "src=\"./");
270
+ if (config.widget.injectWebapis !== false && !html.includes("$WEBAPIS/webapis/webapis.js")) html = html.replace("</head>", `${webapisScript}</head>`);
271
+ writeFileSync(targetPath, html);
272
+ };
273
+ const assertBuildOutput = (config) => {
274
+ const sourceDir = appPath(config.build.output);
275
+ requireFile(sourceDir, "Tizen build output");
276
+ for (const requiredFile of config.build.requiredFiles || []) requireFile(join(sourceDir, requiredFile), `Tizen build output ${requiredFile}`);
277
+ return sourceDir;
278
+ };
279
+ const stageWidget = (config, variant) => {
280
+ const sourceDir = assertBuildOutput(config);
281
+ rmSync(stageDir, {
282
+ force: true,
283
+ recursive: true
284
+ });
285
+ rmSync(outputDir, {
286
+ force: true,
287
+ recursive: true
288
+ });
289
+ mkdirSync(stageDir, { recursive: true });
290
+ mkdirSync(outputDir, { recursive: true });
291
+ cpSync(sourceDir, stageDir, { recursive: true });
292
+ copyFileSync(appPath(config.widget.configXml), join(stageDir, "config.xml"));
293
+ copyFileSync(requireFile(appPath(variant.icon), "Tizen widget icon"), join(stageDir, "icon.png"));
294
+ rewriteConfigForWidget(variant);
295
+ rewriteIndexForWidget(config);
296
+ };
297
+ const findBuiltWidget = () => {
298
+ const built = execFileSync("find", [
299
+ outputDir,
300
+ "-maxdepth",
301
+ "1",
302
+ "-name",
303
+ "*.wgt",
304
+ "-print"
305
+ ], { encoding: "utf8" }).trim().split("\n").filter(Boolean).at(0);
306
+ if (typeof built === "string") return built;
307
+ return fail(`No .wgt package was produced in ${outputDir}`);
308
+ };
309
+ const listSdbDevices = (sdbPath) => {
310
+ return execFileSync(sdb(sdbPath), ["devices"], {
311
+ cwd: appDir,
312
+ encoding: "utf8",
313
+ env: {
314
+ ...baseChildEnv(),
315
+ PATH: `${join(homedir(), "tizen-studio/tools")}:${process.env.PATH || ""}`
316
+ }
317
+ }).split("\n").slice(1).map((line) => line.trim()).filter(Boolean).map(parseSdbDevice).filter((device) => device.id && device.state === "device");
318
+ };
319
+ const parseSdbDevice = (line) => {
320
+ const [id = "", state = "", label = ""] = line.split(/\s+/, 3);
321
+ return {
322
+ id,
323
+ label,
324
+ state
325
+ };
326
+ };
327
+ const resolveInstallTarget = (env) => {
328
+ if (env.target) return env.target;
329
+ const devices = listSdbDevices(env.sdb);
330
+ if (devices.length === 1) {
331
+ const [device] = devices;
332
+ console.log(`Using connected Tizen target: ${device.id}${device.label ? ` (${device.label})` : ""}`);
333
+ return device.id;
334
+ }
335
+ if (devices.length > 1) fail(`Multiple Tizen targets are connected: ${devices.map((device) => device.id).join(", ")}. Set TAIZN_TARGET explicitly.`);
336
+ return null;
337
+ };
338
+ //#endregion
339
+ //#region src/cli.ts
340
+ const runSync = (operation) => Effect.sync(() => {
341
+ operation(loadContext());
342
+ });
343
+ const taizn = Command.make("taizn", {}, () => runSync((context) => {
344
+ packageWidget(context);
345
+ }));
346
+ const profile = Command.make("profile", {}, () => Effect.promise(async () => {
347
+ await createProfile(loadContext());
348
+ }));
349
+ const pack = Command.make("package", {}, () => runSync((context) => {
350
+ packageWidget(context);
351
+ }));
352
+ const install = Command.make("install", {}, () => runSync((context) => {
353
+ installWidget(context);
354
+ }));
355
+ const command = taizn.pipe(Command.withSubcommands([
356
+ profile,
357
+ pack,
358
+ install
359
+ ]));
360
+ //#endregion
361
+ //#region src/taizn.ts
362
+ const PackageJsonSchema = Schema.Struct({ version: Schema.String });
363
+ loadLocalEnv();
364
+ Command.run(command, {
365
+ name: "taizn",
366
+ version: getPackageVersion()
367
+ })(process.argv).pipe(Effect.provide(NodeContext.layer), NodeRuntime.runMain);
368
+ function getPackageVersion() {
369
+ try {
370
+ return Schema.decodeUnknownSync(Schema.parseJson(PackageJsonSchema))(readFileSync(new URL("../package.json", import.meta.url), "utf8")).version;
371
+ } catch (error) {
372
+ if (ParseResult.isParseError(error)) return "0.0.0";
373
+ return "0.0.0";
374
+ }
375
+ }
376
+ //#endregion
377
+ export {};
package/package.json ADDED
@@ -0,0 +1,65 @@
1
+ {
2
+ "name": "@putdotio/taizn",
3
+ "version": "1.0.1",
4
+ "description": "A tiny CLI companion for interacting with Tizen ecosystem.",
5
+ "keywords": [
6
+ "cli",
7
+ "samsung",
8
+ "tizen",
9
+ "widget"
10
+ ],
11
+ "homepage": "https://github.com/putdotio/taizn#readme",
12
+ "bugs": {
13
+ "url": "https://github.com/putdotio/taizn/issues"
14
+ },
15
+ "license": "MIT",
16
+ "author": "put.io <devs@put.io>",
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/putdotio/taizn.git"
20
+ },
21
+ "bin": {
22
+ "taizn": "dist/taizn.mjs"
23
+ },
24
+ "files": [
25
+ "dist",
26
+ "README.md"
27
+ ],
28
+ "type": "module",
29
+ "sideEffects": false,
30
+ "publishConfig": {
31
+ "access": "public"
32
+ },
33
+ "scripts": {
34
+ "build": "vp pack src/taizn.ts",
35
+ "check": "vp check .",
36
+ "clean": "rm -rf .turbo coverage dist",
37
+ "dev": "vp pack src/taizn.ts --watch",
38
+ "live:test": "vp pack src/taizn.ts && node live-test/run-live-test.ts",
39
+ "live:test:install": "vp pack src/taizn.ts && node live-test/run-live-test.ts --install",
40
+ "live:test:profile": "vp pack src/taizn.ts && node live-test/run-live-test.ts --profile",
41
+ "prepack": "vp pack src/taizn.ts",
42
+ "smoke": "vp pack src/taizn.ts && node dist/taizn.mjs --version && node dist/taizn.mjs --help >/dev/null",
43
+ "test": "vp test --passWithNoTests",
44
+ "typecheck": "tsc --noEmit",
45
+ "verify": "vp check . && tsc --noEmit && vp pack src/taizn.ts && vp test --passWithNoTests && npm pack --dry-run"
46
+ },
47
+ "dependencies": {
48
+ "@effect/cli": "^0.75.1",
49
+ "@effect/platform": "^0.96.1",
50
+ "@effect/platform-node": "^0.106.0",
51
+ "@effect/printer": "^0.49.0",
52
+ "@effect/printer-ansi": "^0.49.0",
53
+ "effect": "^3.21.2"
54
+ },
55
+ "devDependencies": {
56
+ "@types/node": "^24.12.2",
57
+ "typescript": "^6.0.2",
58
+ "vite-plus": "^0.1.20",
59
+ "vitest": "^4.1.5"
60
+ },
61
+ "engines": {
62
+ "node": ">=24.14.0 <25"
63
+ },
64
+ "packageManager": "pnpm@11.0.0"
65
+ }