@tmturtle/cli 1.0.0 → 1.0.2
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/CHANGELOG.md +9 -0
- package/README.md +7 -1
- package/dist/tt.js +61 -4
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Trademark Turtle CLI Changelog
|
|
2
2
|
|
|
3
|
+
## v1.0.2 - 2026-07-22
|
|
4
|
+
|
|
5
|
+
- API keys entered through `tt auth set` remain hidden in real terminals.
|
|
6
|
+
|
|
7
|
+
## v1.0.1 - 2026-07-22
|
|
8
|
+
|
|
9
|
+
- `tt auth set` now opens a hidden interactive prompt, while `--stdin` remains
|
|
10
|
+
available for scripts and agent workflows.
|
|
11
|
+
|
|
3
12
|
## v1.0.0 - 2026-07-22
|
|
4
13
|
|
|
5
14
|
- Search United States trademarks with Exact, Multi, Split, and Wildcard modes.
|
package/README.md
CHANGED
|
@@ -12,7 +12,13 @@ The CLI requires Bun 1.3.5 or newer.
|
|
|
12
12
|
bun add --global @tmturtle/cli
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
-
Store a Trademark Turtle API key in macOS Keychain:
|
|
15
|
+
Store a Trademark Turtle API key interactively in macOS Keychain:
|
|
16
|
+
|
|
17
|
+
```sh
|
|
18
|
+
tt auth set
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
For non-interactive setup:
|
|
16
22
|
|
|
17
23
|
```sh
|
|
18
24
|
printf '%s' "$TMTURTLE_API_KEY" | tt auth set --stdin
|
package/dist/tt.js
CHANGED
|
@@ -1287,7 +1287,7 @@ function createTmturtleClient({ apiKey, baseUrl }) {
|
|
|
1287
1287
|
// package.json
|
|
1288
1288
|
var package_default = {
|
|
1289
1289
|
name: "@tmturtle/cli",
|
|
1290
|
-
version: "1.0.
|
|
1290
|
+
version: "1.0.2",
|
|
1291
1291
|
description: "Command-line access to Trademark Turtle search, reports, and service status",
|
|
1292
1292
|
repository: {
|
|
1293
1293
|
type: "git",
|
|
@@ -1412,6 +1412,62 @@ class BadRequestError extends CliError {
|
|
|
1412
1412
|
}
|
|
1413
1413
|
}
|
|
1414
1414
|
|
|
1415
|
+
// src/prompt.ts
|
|
1416
|
+
function readHiddenApiKey(input = process.stdin, output = process.stderr) {
|
|
1417
|
+
if (!(input.isTTY && output.isTTY && input.setRawMode)) {
|
|
1418
|
+
return Promise.reject(new BadRequestError("Interactive input requires a terminal; use --stdin instead"));
|
|
1419
|
+
}
|
|
1420
|
+
const wasFlowing = input.readableFlowing === true;
|
|
1421
|
+
const wasRaw = input.isRaw === true;
|
|
1422
|
+
input.setRawMode(true);
|
|
1423
|
+
return new Promise((resolve, reject) => {
|
|
1424
|
+
const bytes = [];
|
|
1425
|
+
const finish = (result) => {
|
|
1426
|
+
input.removeListener("data", onData);
|
|
1427
|
+
input.removeListener("end", onEnd);
|
|
1428
|
+
input.removeListener("error", onError);
|
|
1429
|
+
if (!wasRaw) {
|
|
1430
|
+
input.setRawMode?.(false);
|
|
1431
|
+
}
|
|
1432
|
+
if (!wasFlowing) {
|
|
1433
|
+
input.pause();
|
|
1434
|
+
}
|
|
1435
|
+
output.write(`
|
|
1436
|
+
`);
|
|
1437
|
+
if (result.error) {
|
|
1438
|
+
reject(result.error);
|
|
1439
|
+
} else {
|
|
1440
|
+
resolve(result.value ?? "");
|
|
1441
|
+
}
|
|
1442
|
+
};
|
|
1443
|
+
const cancel = () => finish({ error: new BadRequestError("API key input cancelled") });
|
|
1444
|
+
const onData = (chunk) => {
|
|
1445
|
+
for (const byte of Buffer.from(chunk)) {
|
|
1446
|
+
if (byte === 3 || byte === 4) {
|
|
1447
|
+
cancel();
|
|
1448
|
+
return;
|
|
1449
|
+
}
|
|
1450
|
+
if (byte === 10 || byte === 13) {
|
|
1451
|
+
finish({ value: Buffer.from(bytes).toString("utf8") });
|
|
1452
|
+
return;
|
|
1453
|
+
}
|
|
1454
|
+
if (byte === 8 || byte === 127) {
|
|
1455
|
+
bytes.pop();
|
|
1456
|
+
continue;
|
|
1457
|
+
}
|
|
1458
|
+
bytes.push(byte);
|
|
1459
|
+
}
|
|
1460
|
+
};
|
|
1461
|
+
const onEnd = () => cancel();
|
|
1462
|
+
const onError = (error) => finish({ error });
|
|
1463
|
+
input.on("data", onData);
|
|
1464
|
+
input.once("end", onEnd);
|
|
1465
|
+
input.once("error", onError);
|
|
1466
|
+
input.resume();
|
|
1467
|
+
output.write("API key: ");
|
|
1468
|
+
});
|
|
1469
|
+
}
|
|
1470
|
+
|
|
1415
1471
|
// ../../node_modules/.bun/commander@15.0.0/node_modules/commander/lib/error.js
|
|
1416
1472
|
class CommanderError extends Error {
|
|
1417
1473
|
constructor(exitCode, code, message) {
|
|
@@ -3582,8 +3638,8 @@ Examples:
|
|
|
3582
3638
|
printf '%s' "shirt title" | tt match --stdin
|
|
3583
3639
|
`);
|
|
3584
3640
|
const auth = program2.command("auth").description("Manage the selected API credential");
|
|
3585
|
-
auth.command("set").description("Store an API key
|
|
3586
|
-
command = { kind: "auth-set" };
|
|
3641
|
+
auth.command("set").description("Store an API key in macOS Keychain").option("--stdin", "Read the API key from stdin instead of prompting").action((options) => {
|
|
3642
|
+
command = { kind: "auth-set", readsStdin: options.stdin === true };
|
|
3587
3643
|
});
|
|
3588
3644
|
auth.command("status").description("Validate and describe the selected credential").action(() => {
|
|
3589
3645
|
command = { kind: "auth-status" };
|
|
@@ -3734,7 +3790,7 @@ async function runCli(args, dependencies) {
|
|
|
3734
3790
|
const invocation = parsed.command;
|
|
3735
3791
|
if (invocation.kind === "auth-set") {
|
|
3736
3792
|
const origin = configuredOrigin(dependencies, parsed.baseUrl);
|
|
3737
|
-
const token = dependencies.stdin.trim();
|
|
3793
|
+
const token = (invocation.readsStdin ? dependencies.stdin : await dependencies.promptSecret()).trim();
|
|
3738
3794
|
if (!tokenPattern.test(token)) {
|
|
3739
3795
|
throw new BadRequestError("Invalid Trademark Turtle API key");
|
|
3740
3796
|
}
|
|
@@ -3803,6 +3859,7 @@ try {
|
|
|
3803
3859
|
createClient: createTmturtleClient,
|
|
3804
3860
|
env: process.env,
|
|
3805
3861
|
keychain: createMacOsKeychain(),
|
|
3862
|
+
promptSecret: readHiddenApiKey,
|
|
3806
3863
|
stdin: args.includes("--stdin") ? await new Response(Bun.stdin.stream()).text() : "",
|
|
3807
3864
|
version: package_default.version
|
|
3808
3865
|
});
|