tokx-cli 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Hammad Khan
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,67 @@
1
+ # tokx
2
+
3
+ JWT decode, encode, verify from your terminal.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install -g tokx-cli
9
+ ```
10
+
11
+ ## Commands
12
+
13
+ ### Decode
14
+
15
+ ```bash
16
+ tokx decode <token>
17
+ tokx decode <token> --json
18
+ ```
19
+
20
+ Pretty-prints header + payload with color-coded JWT parts, claim status icons, and relative expiry time.
21
+
22
+ ### Encode
23
+
24
+ ```bash
25
+ tokx encode --secret <secret> --payload '{"sub":"123"}'
26
+ tokx encode --secret <secret> --payload '{"sub":"123"}' --algorithm HS512 --expires 3600
27
+ tokx encode --secret <secret> --payload '{"sub":"123"}' --json
28
+ ```
29
+
30
+ ### Verify
31
+
32
+ ```bash
33
+ tokx verify <token> --secret <secret>
34
+ tokx verify <token> --secret <secret> --json
35
+ ```
36
+
37
+ Auto-detects algorithm from token header. Shows a verification badge.
38
+
39
+ ### Libraries
40
+
41
+ ```bash
42
+ tokx libs
43
+ tokx libs --language Python
44
+ tokx libs --algorithm EdDSA
45
+ tokx libs --json
46
+ ```
47
+
48
+ ## Exit Codes
49
+
50
+ | Code | Meaning |
51
+ |------|---------|
52
+ | 0 | Success |
53
+ | 1 | Invalid input |
54
+ | 2 | Verification failed |
55
+ | 3 | Internal error |
56
+
57
+ ## Features
58
+
59
+ - Color-coded JWT parts (header=red, payload=purple, signature=cyan)
60
+ - Box-framed output for decoded header/payload
61
+ - Spinner for async operations
62
+ - `--json` flag on all commands for machine-readable output
63
+ - Respects `NO_COLOR` environment variable
64
+
65
+ ## License
66
+
67
+ MIT
package/dist/api.d.ts ADDED
@@ -0,0 +1 @@
1
+ export { DecodedJwt, EncodeOptions, VerifyOptions, VerifyResult, decode, encode, verify } from '@tokx/core';
package/dist/api.js ADDED
@@ -0,0 +1,8 @@
1
+ // src/api.ts
2
+ import { decode, encode, verify } from "@tokx/core";
3
+ export {
4
+ decode,
5
+ encode,
6
+ verify
7
+ };
8
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/api.ts"],"sourcesContent":["export type { DecodedJwt, EncodeOptions, VerifyOptions, VerifyResult } from '@tokx/core';\nexport { decode, encode, verify } from '@tokx/core';\n"],"mappings":";AACA,SAAS,QAAQ,QAAQ,cAAc;","names":[]}
@@ -0,0 +1,2 @@
1
+
2
+ export { }
package/dist/index.js ADDED
@@ -0,0 +1,559 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/index.ts
4
+ import { readFileSync } from "fs";
5
+ import { program } from "commander";
6
+
7
+ // src/commands/decode.ts
8
+ import { decode } from "@tokx/core";
9
+
10
+ // src/ui/colors.ts
11
+ import pc from "picocolors";
12
+ var noColor = process.env.NO_COLOR !== void 0;
13
+ function wrap(fn) {
14
+ return noColor ? (s) => s : fn;
15
+ }
16
+ var c = {
17
+ red: wrap(pc.red),
18
+ green: wrap(pc.green),
19
+ yellow: wrap(pc.yellow),
20
+ blue: wrap(pc.blue),
21
+ cyan: wrap(pc.cyan),
22
+ magenta: wrap(pc.magenta),
23
+ gray: wrap(pc.gray),
24
+ bold: wrap(pc.bold),
25
+ dim: wrap(pc.dim)
26
+ };
27
+ function isTTY() {
28
+ return !noColor && process.stdout.isTTY === true;
29
+ }
30
+
31
+ // src/ui/animation.ts
32
+ function sleep(ms) {
33
+ return new Promise((r) => setTimeout(r, ms));
34
+ }
35
+ async function playDecodeAnimation(token) {
36
+ if (!isTTY()) return;
37
+ const parts = token.split(".");
38
+ if (parts.length !== 3) return;
39
+ const frames = [
40
+ ` ${c.dim(token.slice(0, 40))}${c.dim("...")}`,
41
+ ` ${c.red(parts[0].slice(0, 12))}${c.dim("...")} ${c.dim("\xB7")} ${c.magenta(parts[1].slice(0, 12))}${c.dim("...")} ${c.dim("\xB7")} ${c.cyan(parts[2].slice(0, 12))}${c.dim("...")}`,
42
+ ` ${c.red("\u25A0 header")} ${c.dim("\xB7")} ${c.magenta("\u25A0 payload")} ${c.dim("\xB7")} ${c.cyan("\u25A0 signature")}`
43
+ ];
44
+ process.stdout.write("\n");
45
+ for (const frame of frames) {
46
+ process.stdout.write(`\r${frame}${" ".repeat(20)}`);
47
+ await sleep(120);
48
+ }
49
+ process.stdout.write("\n\n");
50
+ }
51
+
52
+ // src/ui/box.ts
53
+ function drawBox(title, content, color) {
54
+ const lines = content.split("\n");
55
+ const maxLen = Math.max(title.length + 4, ...lines.map((l) => l.length));
56
+ const width = Math.min(maxLen + 4, 60);
57
+ const top = color(` \u250C\u2500 ${title} ${"\u2500".repeat(Math.max(0, width - title.length - 5))}\u2510`);
58
+ const bottom = color(` \u2514${"\u2500".repeat(width - 1)}\u2518`);
59
+ const body = lines.map((line) => {
60
+ const padded = line.padEnd(width - 4);
61
+ return ` ${color("\u2502")} ${padded} ${color("\u2502")}`;
62
+ });
63
+ return [top, ...body, bottom].join("\n");
64
+ }
65
+ function drawBadge(text, color, icon) {
66
+ const inner = ` ${icon} ${text} `;
67
+ const width = inner.length + 2;
68
+ const top = color(` \u2554${"\u2550".repeat(width)}\u2557`);
69
+ const mid = color(` \u2551${inner}\u2551`);
70
+ const bottom = color(` \u255A${"\u2550".repeat(width)}\u255D`);
71
+ return `${top}
72
+ ${mid}
73
+ ${bottom}`;
74
+ }
75
+ function tokenBar(header, payload, signature) {
76
+ const total = 50;
77
+ const hLen = Math.max(
78
+ 2,
79
+ Math.round(header.length / (header.length + payload.length + signature.length) * total)
80
+ );
81
+ const pLen = Math.max(
82
+ 2,
83
+ Math.round(payload.length / (header.length + payload.length + signature.length) * total)
84
+ );
85
+ const sLen = Math.max(2, total - hLen - pLen);
86
+ return ` ${c.red("\u2588".repeat(hLen))}${c.dim(".")}${c.magenta("\u2588".repeat(pLen))}${c.dim(".")}${c.cyan("\u2588".repeat(sLen))}`;
87
+ }
88
+
89
+ // src/commands/decode.ts
90
+ function relativeTime(epoch) {
91
+ const diff = epoch - Date.now() / 1e3;
92
+ const abs = Math.abs(diff);
93
+ const past = diff < 0;
94
+ const units = [
95
+ [86400, "d"],
96
+ [3600, "h"],
97
+ [60, "m"]
98
+ ];
99
+ const parts = [];
100
+ let remaining = abs;
101
+ for (const [sec, label] of units) {
102
+ if (remaining >= sec) {
103
+ parts.push(`${Math.floor(remaining / sec)}${label}`);
104
+ remaining %= sec;
105
+ }
106
+ }
107
+ const str = parts.length > 0 ? parts.slice(0, 2).join(" ") : "<1m";
108
+ return past ? `${str} ago` : `in ${str}`;
109
+ }
110
+ function claimIcon(present, valid) {
111
+ if (!present) return c.dim("\u25CB");
112
+ if (valid === false) return c.red("\u2717");
113
+ return c.green("\u2713");
114
+ }
115
+ async function decodeCommand(token, options) {
116
+ try {
117
+ const result = decode(token);
118
+ if (options.json) {
119
+ process.stdout.write(
120
+ `${JSON.stringify({ header: result.header, payload: result.payload }, null, 2)}
121
+ `
122
+ );
123
+ return;
124
+ }
125
+ await playDecodeAnimation(token);
126
+ process.stdout.write(
127
+ `${tokenBar(result.raw.header, result.raw.payload, result.raw.signature)}
128
+
129
+ `
130
+ );
131
+ const headerJson = JSON.stringify(result.header, null, 2);
132
+ process.stdout.write(
133
+ `${drawBox(`HEADER ${c.dim(`(${result.header.alg})`)}`, headerJson, c.red)}
134
+
135
+ `
136
+ );
137
+ const payloadJson = JSON.stringify(result.payload, null, 2);
138
+ process.stdout.write(`${drawBox("PAYLOAD", payloadJson, c.magenta)}
139
+
140
+ `);
141
+ const p = result.payload;
142
+ const now = Date.now() / 1e3;
143
+ process.stdout.write(` ${c.bold("Claims")}
144
+ `);
145
+ const expValid = p.exp ? p.exp > now : void 0;
146
+ const nbfValid = p.nbf ? p.nbf <= now : void 0;
147
+ const claims = [
148
+ { key: "iss", val: p.iss },
149
+ { key: "sub", val: p.sub },
150
+ { key: "aud", val: p.aud },
151
+ { key: "iat", val: p.iat ? new Date(p.iat * 1e3).toISOString() : void 0 },
152
+ {
153
+ key: "exp",
154
+ val: p.exp ? `${new Date(p.exp * 1e3).toISOString()} ${c.dim(`(${relativeTime(p.exp)})`)}` : void 0,
155
+ valid: expValid
156
+ },
157
+ {
158
+ key: "nbf",
159
+ val: p.nbf ? new Date(p.nbf * 1e3).toISOString() : void 0,
160
+ valid: nbfValid
161
+ },
162
+ { key: "jti", val: p.jti }
163
+ ];
164
+ for (const claim of claims) {
165
+ const icon = claimIcon(claim.val !== void 0, claim.valid);
166
+ const value = claim.val ? c.dim(String(claim.val)) : c.dim("\u2014");
167
+ process.stdout.write(` ${icon} ${c.bold(claim.key.padEnd(4))} ${value}
168
+ `);
169
+ }
170
+ process.stdout.write(`
171
+ ${c.dim("Algorithm:")} ${c.cyan(result.header.alg)}
172
+
173
+ `);
174
+ } catch (err) {
175
+ process.stderr.write(
176
+ `${c.red("error")}: ${err instanceof Error ? err.message : "Failed to decode token"}
177
+ `
178
+ );
179
+ process.exit(1);
180
+ }
181
+ }
182
+
183
+ // src/commands/encode.ts
184
+ import { encode } from "@tokx/core";
185
+
186
+ // src/ui/spinner.ts
187
+ var FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
188
+ function startSpinner(message) {
189
+ if (!isTTY()) {
190
+ return {
191
+ stop: (success, finalMsg) => {
192
+ const icon = success ? c.green("\u2713") : c.red("\u2717");
193
+ process.stderr.write(`${icon} ${finalMsg}
194
+ `);
195
+ }
196
+ };
197
+ }
198
+ let i = 0;
199
+ const interval = setInterval(() => {
200
+ process.stderr.write(`\r ${c.cyan(FRAMES[i % FRAMES.length])} ${message}`);
201
+ i++;
202
+ }, 80);
203
+ return {
204
+ stop: (success, finalMsg) => {
205
+ clearInterval(interval);
206
+ const icon = success ? c.green("\u2713") : c.red("\u2717");
207
+ process.stderr.write(`\r ${icon} ${finalMsg}${" ".repeat(20)}
208
+ `);
209
+ }
210
+ };
211
+ }
212
+
213
+ // src/commands/encode.ts
214
+ async function encodeCommand(options) {
215
+ try {
216
+ if (!options.secret) {
217
+ process.stderr.write(`${c.red("error")}: --secret is required
218
+ `);
219
+ process.exit(1);
220
+ }
221
+ if (!options.payload) {
222
+ process.stderr.write(`${c.red("error")}: --payload is required
223
+ `);
224
+ process.exit(1);
225
+ }
226
+ let payloadObj;
227
+ try {
228
+ payloadObj = JSON.parse(options.payload);
229
+ } catch {
230
+ process.stderr.write(`${c.red("error")}: --payload must be valid JSON
231
+ `);
232
+ process.exit(1);
233
+ }
234
+ const spinner = startSpinner("Signing token...");
235
+ const token = await encode({
236
+ algorithm: options.algorithm,
237
+ payload: payloadObj,
238
+ secret: options.secret,
239
+ expiresIn: options.expires ? Number(options.expires) : void 0
240
+ });
241
+ spinner.stop(true, `Token signed ${c.dim(`(${options.algorithm})`)}`);
242
+ if (options.json) {
243
+ process.stdout.write(`${JSON.stringify({ token })}
244
+ `);
245
+ } else {
246
+ const parts = token.split(".");
247
+ process.stdout.write("\n");
248
+ if (parts.length === 3) {
249
+ process.stdout.write(`${tokenBar(parts[0], parts[1], parts[2])}
250
+
251
+ `);
252
+ process.stdout.write(
253
+ ` ${c.red(parts[0])}
254
+ ${c.dim(".")}
255
+ ${c.magenta(parts[1])}
256
+ ${c.dim(".")}
257
+ ${c.cyan(parts[2])}
258
+ `
259
+ );
260
+ } else {
261
+ process.stdout.write(` ${token}
262
+ `);
263
+ }
264
+ process.stdout.write("\n");
265
+ }
266
+ } catch (err) {
267
+ process.stderr.write(
268
+ `${c.red("error")}: ${err instanceof Error ? err.message : "Failed to encode token"}
269
+ `
270
+ );
271
+ process.exit(1);
272
+ }
273
+ }
274
+
275
+ // src/commands/libs.ts
276
+ import Table from "cli-table3";
277
+ var LANG_TAGS = {
278
+ JavaScript: "JS",
279
+ Python: "PY",
280
+ Java: "JV",
281
+ Go: "GO",
282
+ Rust: "RS",
283
+ Ruby: "RB",
284
+ PHP: "PHP",
285
+ ".NET": "NET",
286
+ Swift: "SW",
287
+ Kotlin: "KT",
288
+ Dart: "DT",
289
+ Erlang: "ER"
290
+ };
291
+ var LIBRARIES = [
292
+ {
293
+ name: "jose",
294
+ language: "JavaScript",
295
+ author: "panva",
296
+ url: "https://github.com/panva/jose",
297
+ stars: 6200,
298
+ install: "npm install jose",
299
+ signing: ["HS256", "RS256", "ES256", "EdDSA"],
300
+ verifying: ["HS256", "RS256", "ES256", "EdDSA"]
301
+ },
302
+ {
303
+ name: "jsonwebtoken",
304
+ language: "JavaScript",
305
+ author: "auth0",
306
+ url: "https://github.com/auth0/node-jsonwebtoken",
307
+ stars: 17500,
308
+ install: "npm install jsonwebtoken",
309
+ signing: ["HS256", "RS256", "ES256"],
310
+ verifying: ["HS256", "RS256", "ES256"]
311
+ },
312
+ {
313
+ name: "PyJWT",
314
+ language: "Python",
315
+ author: "jpadilla",
316
+ url: "https://github.com/jpadilla/pyjwt",
317
+ stars: 5100,
318
+ install: "pip install PyJWT",
319
+ signing: ["HS256", "RS256", "ES256", "EdDSA"],
320
+ verifying: ["HS256", "RS256", "ES256", "EdDSA"]
321
+ },
322
+ {
323
+ name: "java-jwt",
324
+ language: "Java",
325
+ author: "auth0",
326
+ url: "https://github.com/auth0/java-jwt",
327
+ stars: 5800,
328
+ install: "implementation 'com.auth0:java-jwt:4.4.0'",
329
+ signing: ["HS256", "RS256", "ES256"],
330
+ verifying: ["HS256", "RS256", "ES256"]
331
+ },
332
+ {
333
+ name: "jjwt",
334
+ language: "Java",
335
+ author: "jwtk",
336
+ url: "https://github.com/jwtk/jjwt",
337
+ stars: 10300,
338
+ install: "implementation 'io.jsonwebtoken:jjwt-api:0.12.6'",
339
+ signing: ["HS256", "RS256", "ES256", "EdDSA"],
340
+ verifying: ["HS256", "RS256", "ES256", "EdDSA"]
341
+ },
342
+ {
343
+ name: "golang-jwt",
344
+ language: "Go",
345
+ author: "golang-jwt",
346
+ url: "https://github.com/golang-jwt/jwt",
347
+ stars: 7200,
348
+ install: "go get github.com/golang-jwt/jwt/v5",
349
+ signing: ["HS256", "RS256", "ES256", "EdDSA"],
350
+ verifying: ["HS256", "RS256", "ES256", "EdDSA"]
351
+ },
352
+ {
353
+ name: "jsonwebtoken",
354
+ language: "Rust",
355
+ author: "Keats",
356
+ url: "https://github.com/Keats/jsonwebtoken",
357
+ stars: 1700,
358
+ install: "cargo add jsonwebtoken",
359
+ signing: ["HS256", "RS256", "ES256", "EdDSA"],
360
+ verifying: ["HS256", "RS256", "ES256", "EdDSA"]
361
+ },
362
+ {
363
+ name: "ruby-jwt",
364
+ language: "Ruby",
365
+ author: "jwt",
366
+ url: "https://github.com/jwt/ruby-jwt",
367
+ stars: 3600,
368
+ install: "gem install jwt",
369
+ signing: ["HS256", "RS256", "ES256", "EdDSA"],
370
+ verifying: ["HS256", "RS256", "ES256", "EdDSA"]
371
+ },
372
+ {
373
+ name: "php-jwt",
374
+ language: "PHP",
375
+ author: "firebase",
376
+ url: "https://github.com/firebase/php-jwt",
377
+ stars: 9400,
378
+ install: "composer require firebase/php-jwt",
379
+ signing: ["HS256", "RS256", "ES256"],
380
+ verifying: ["HS256", "RS256", "ES256"]
381
+ },
382
+ {
383
+ name: "System.IdentityModel.Tokens.Jwt",
384
+ language: ".NET",
385
+ author: "AzureAD",
386
+ url: "https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet",
387
+ stars: 1100,
388
+ install: "dotnet add package System.IdentityModel.Tokens.Jwt",
389
+ signing: ["HS256", "RS256", "ES256"],
390
+ verifying: ["HS256", "RS256", "ES256"]
391
+ }
392
+ ];
393
+ function formatStars(n) {
394
+ return n >= 1e3 ? `${(n / 1e3).toFixed(1)}k` : String(n);
395
+ }
396
+ function libsCommand(options) {
397
+ try {
398
+ let results = LIBRARIES;
399
+ if (options.language) {
400
+ const lang = options.language.toLowerCase();
401
+ results = results.filter((l) => l.language.toLowerCase() === lang);
402
+ }
403
+ if (options.algorithm) {
404
+ const alg = options.algorithm.toUpperCase();
405
+ results = results.filter((l) => l.signing.includes(alg) || l.verifying.includes(alg));
406
+ }
407
+ results.sort((a, b) => b.stars - a.stars);
408
+ if (options.json) {
409
+ process.stdout.write(`${JSON.stringify(results, null, 2)}
410
+ `);
411
+ return;
412
+ }
413
+ if (results.length === 0) {
414
+ process.stderr.write(` ${c.dim("No libraries match your filters.")}
415
+ `);
416
+ return;
417
+ }
418
+ const table = new Table({
419
+ head: [c.bold("Library"), c.bold("Lang"), c.bold("\u2605"), c.bold("Install")],
420
+ style: { head: [], border: [] },
421
+ colWidths: [28, 7, 8, 48],
422
+ wordWrap: true
423
+ });
424
+ for (const lib of results) {
425
+ const tag = LANG_TAGS[lib.language] || lib.language.slice(0, 3).toUpperCase();
426
+ const langTag = c.blue(`[${tag}]`);
427
+ table.push([
428
+ c.cyan(lib.name),
429
+ langTag,
430
+ c.yellow(`\u2605 ${formatStars(lib.stars)}`),
431
+ c.dim(lib.install)
432
+ ]);
433
+ }
434
+ process.stdout.write(`
435
+ ${table.toString()}
436
+
437
+ `);
438
+ process.stderr.write(` ${c.dim(`${results.length} libraries found`)}
439
+
440
+ `);
441
+ } catch (err) {
442
+ process.stderr.write(
443
+ `${c.red("error")}: ${err instanceof Error ? err.message : "Failed to list libraries"}
444
+ `
445
+ );
446
+ process.exit(3);
447
+ }
448
+ }
449
+
450
+ // src/commands/verify.ts
451
+ import { decode as decode2, verify } from "@tokx/core";
452
+ async function verifyCommand(token, options) {
453
+ try {
454
+ if (!options.secret && !options.publicKey) {
455
+ process.stderr.write(`${c.red("error")}: --secret or --public-key is required
456
+ `);
457
+ process.exit(1);
458
+ }
459
+ let alg = options.algorithm;
460
+ if (!alg) {
461
+ try {
462
+ const decoded = decode2(token);
463
+ alg = decoded.header.alg;
464
+ } catch {
465
+ process.stderr.write(
466
+ `${c.red("error")}: Could not detect algorithm. Use --algorithm to specify.
467
+ `
468
+ );
469
+ process.exit(1);
470
+ }
471
+ }
472
+ const spinner = startSpinner("Verifying signature...");
473
+ const result = await verify(token, {
474
+ algorithm: alg,
475
+ secret: options.secret || "",
476
+ publicKey: options.publicKey
477
+ });
478
+ if (options.json) {
479
+ spinner.stop(result.valid, result.valid ? "Valid" : "Invalid");
480
+ process.stdout.write(`${JSON.stringify(result)}
481
+ `);
482
+ if (!result.valid) process.exit(2);
483
+ return;
484
+ }
485
+ if (result.valid) {
486
+ spinner.stop(true, "Verification complete");
487
+ process.stdout.write(`
488
+ ${drawBadge("SIGNATURE VERIFIED", c.green, "\u2713")}
489
+
490
+ `);
491
+ } else {
492
+ spinner.stop(false, "Verification failed");
493
+ process.stdout.write(`
494
+ ${drawBadge("INVALID SIGNATURE", c.red, "\u2717")}
495
+ `);
496
+ if (result.error) process.stderr.write(` ${c.dim(result.error)}
497
+ `);
498
+ if (result.expired) process.stderr.write(` ${c.yellow("Token has expired")}
499
+ `);
500
+ process.stdout.write("\n");
501
+ process.exit(2);
502
+ }
503
+ } catch (err) {
504
+ process.stderr.write(
505
+ `${c.red("error")}: ${err instanceof Error ? err.message : "Verification failed"}
506
+ `
507
+ );
508
+ process.exit(1);
509
+ }
510
+ }
511
+
512
+ // src/ui/banner.ts
513
+ function printBanner() {
514
+ if (!isTTY()) return;
515
+ const t = c.red("t");
516
+ const o = c.magenta("o");
517
+ const k = c.cyan("k");
518
+ const x = c.cyan("x");
519
+ process.stderr.write("\n");
520
+ process.stderr.write(` ${c.dim("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510")}
521
+ `);
522
+ process.stderr.write(
523
+ ` ${c.dim("\u2502")} ${t} ${o} ${k} ${x} ${c.dim("\u2502")}
524
+ `
525
+ );
526
+ process.stderr.write(
527
+ ` ${c.dim("\u2502")} ${c.dim("JWT decode \xB7 encode \xB7 verify")} ${c.dim("\u2502")}
528
+ `
529
+ );
530
+ process.stderr.write(` ${c.dim("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518")}
531
+ `);
532
+ process.stderr.write("\n");
533
+ }
534
+
535
+ // src/index.ts
536
+ var pkg = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf-8"));
537
+ program.name("tokx").description("JWT decode, encode, verify from your terminal").version(pkg.version);
538
+ if (process.argv.length <= 2) {
539
+ printBanner();
540
+ }
541
+ async function readStdin() {
542
+ const chunks = [];
543
+ for await (const chunk of process.stdin) chunks.push(chunk);
544
+ return Buffer.concat(chunks).toString().trim();
545
+ }
546
+ program.command("decode <token>").description("Decode a JWT and display header + payload (use - for stdin)").option("--json", "Output as JSON").action(async (token, options) => {
547
+ const t = token === "-" ? await readStdin() : token;
548
+ return decodeCommand(t, options);
549
+ });
550
+ program.command("encode").description("Encode (sign) a new JWT").requiredOption("--secret <secret>", "Signing secret (HMAC)").requiredOption("--payload <json>", "Payload as JSON string").option("--algorithm <alg>", "Algorithm", "HS256").option("--expires <seconds>", "Expiration in seconds from now").option("--json", "Output as JSON").action(encodeCommand);
551
+ program.command("verify <token>").description("Verify a JWT signature (use - for stdin)").option("--secret <secret>", "Verification secret (HMAC)").option("--public-key <path>", "Public key PEM file path").option("--algorithm <alg>", "Algorithm (auto-detected if omitted)").option("--json", "Output as JSON").action(
552
+ async (token, options) => {
553
+ const t = token === "-" ? await readStdin() : token;
554
+ return verifyCommand(t, options);
555
+ }
556
+ );
557
+ program.command("libs").description("List JWT libraries").option("--language <lang>", "Filter by language").option("--algorithm <alg>", "Filter by algorithm").option("--json", "Output as JSON").action(libsCommand);
558
+ program.parse();
559
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/commands/decode.ts","../src/ui/colors.ts","../src/ui/animation.ts","../src/ui/box.ts","../src/commands/encode.ts","../src/ui/spinner.ts","../src/commands/libs.ts","../src/commands/verify.ts","../src/ui/banner.ts"],"sourcesContent":["import { readFileSync } from 'node:fs';\nimport { program } from 'commander';\nimport { decodeCommand } from './commands/decode.js';\nimport { encodeCommand } from './commands/encode.js';\nimport { libsCommand } from './commands/libs.js';\nimport { verifyCommand } from './commands/verify.js';\nimport { printBanner } from './ui/banner.js';\n\nconst pkg = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf-8'));\n\nprogram\n .name('tokx')\n .description('JWT decode, encode, verify from your terminal')\n .version(pkg.version);\n\n// Show banner when no command provided\nif (process.argv.length <= 2) {\n printBanner();\n}\n\n// Helper: read token from stdin if '-' is passed\nasync function readStdin(): Promise<string> {\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) chunks.push(chunk as Buffer);\n return Buffer.concat(chunks).toString().trim();\n}\n\nprogram\n .command('decode <token>')\n .description('Decode a JWT and display header + payload (use - for stdin)')\n .option('--json', 'Output as JSON')\n .action(async (token: string, options: { json?: boolean }) => {\n const t = token === '-' ? await readStdin() : token;\n return decodeCommand(t, options);\n });\n\nprogram\n .command('encode')\n .description('Encode (sign) a new JWT')\n .requiredOption('--secret <secret>', 'Signing secret (HMAC)')\n .requiredOption('--payload <json>', 'Payload as JSON string')\n .option('--algorithm <alg>', 'Algorithm', 'HS256')\n .option('--expires <seconds>', 'Expiration in seconds from now')\n .option('--json', 'Output as JSON')\n .action(encodeCommand);\n\nprogram\n .command('verify <token>')\n .description('Verify a JWT signature (use - for stdin)')\n .option('--secret <secret>', 'Verification secret (HMAC)')\n .option('--public-key <path>', 'Public key PEM file path')\n .option('--algorithm <alg>', 'Algorithm (auto-detected if omitted)')\n .option('--json', 'Output as JSON')\n .action(\n async (\n token: string,\n options: { secret?: string; publicKey?: string; algorithm?: string; json?: boolean },\n ) => {\n const t = token === '-' ? await readStdin() : token;\n return verifyCommand(t, options);\n },\n );\n\nprogram\n .command('libs')\n .description('List JWT libraries')\n .option('--language <lang>', 'Filter by language')\n .option('--algorithm <alg>', 'Filter by algorithm')\n .option('--json', 'Output as JSON')\n .action(libsCommand);\n\nprogram.parse();\n","import { decode } from '@tokx/core';\nimport { playDecodeAnimation } from '../ui/animation.js';\nimport { drawBox, tokenBar } from '../ui/box.js';\nimport { c } from '../ui/colors.js';\n\ninterface DecodeOptions {\n json?: boolean;\n}\n\nfunction relativeTime(epoch: number): string {\n const diff = epoch - Date.now() / 1000;\n const abs = Math.abs(diff);\n const past = diff < 0;\n const units: [number, string][] = [\n [86400, 'd'],\n [3600, 'h'],\n [60, 'm'],\n ];\n const parts: string[] = [];\n let remaining = abs;\n for (const [sec, label] of units) {\n if (remaining >= sec) {\n parts.push(`${Math.floor(remaining / sec)}${label}`);\n remaining %= sec;\n }\n }\n const str = parts.length > 0 ? parts.slice(0, 2).join(' ') : '<1m';\n return past ? `${str} ago` : `in ${str}`;\n}\n\nfunction claimIcon(present: boolean, valid?: boolean): string {\n if (!present) return c.dim('○');\n if (valid === false) return c.red('✗');\n return c.green('✓');\n}\n\nexport async function decodeCommand(token: string, options: DecodeOptions): Promise<void> {\n try {\n const result = decode(token);\n\n if (options.json) {\n process.stdout.write(\n `${JSON.stringify({ header: result.header, payload: result.payload }, null, 2)}\\n`,\n );\n return;\n }\n\n await playDecodeAnimation(token);\n\n // Token bar\n process.stdout.write(\n `${tokenBar(result.raw.header, result.raw.payload, result.raw.signature)}\\n\\n`,\n );\n\n // Header box\n const headerJson = JSON.stringify(result.header, null, 2);\n process.stdout.write(\n `${drawBox(`HEADER ${c.dim(`(${result.header.alg})`)}`, headerJson, c.red)}\\n\\n`,\n );\n\n // Payload box\n const payloadJson = JSON.stringify(result.payload, null, 2);\n process.stdout.write(`${drawBox('PAYLOAD', payloadJson, c.magenta)}\\n\\n`);\n\n // Claims summary\n const p = result.payload;\n const now = Date.now() / 1000;\n process.stdout.write(` ${c.bold('Claims')}\\n`);\n\n const expValid = p.exp ? (p.exp as number) > now : undefined;\n const nbfValid = p.nbf ? (p.nbf as number) <= now : undefined;\n\n const claims = [\n { key: 'iss', val: p.iss as string | undefined },\n { key: 'sub', val: p.sub as string | undefined },\n { key: 'aud', val: p.aud as string | undefined },\n { key: 'iat', val: p.iat ? new Date((p.iat as number) * 1000).toISOString() : undefined },\n {\n key: 'exp',\n val: p.exp\n ? `${new Date((p.exp as number) * 1000).toISOString()} ${c.dim(`(${relativeTime(p.exp as number)})`)}`\n : undefined,\n valid: expValid,\n },\n {\n key: 'nbf',\n val: p.nbf ? new Date((p.nbf as number) * 1000).toISOString() : undefined,\n valid: nbfValid,\n },\n { key: 'jti', val: p.jti as string | undefined },\n ];\n\n for (const claim of claims) {\n const icon = claimIcon(claim.val !== undefined, (claim as { valid?: boolean }).valid);\n const value = claim.val ? c.dim(String(claim.val)) : c.dim('—');\n process.stdout.write(` ${icon} ${c.bold(claim.key.padEnd(4))} ${value}\\n`);\n }\n\n process.stdout.write(`\\n ${c.dim('Algorithm:')} ${c.cyan(result.header.alg)}\\n\\n`);\n } catch (err) {\n process.stderr.write(\n `${c.red('error')}: ${err instanceof Error ? err.message : 'Failed to decode token'}\\n`,\n );\n process.exit(1);\n }\n}\n","import pc from 'picocolors';\n\nconst noColor = process.env.NO_COLOR !== undefined;\n\nfunction wrap(fn: (s: string) => string): (s: string) => string {\n return noColor ? (s: string) => s : fn;\n}\n\nexport const c = {\n red: wrap(pc.red),\n green: wrap(pc.green),\n yellow: wrap(pc.yellow),\n blue: wrap(pc.blue),\n cyan: wrap(pc.cyan),\n magenta: wrap(pc.magenta),\n gray: wrap(pc.gray),\n bold: wrap(pc.bold),\n dim: wrap(pc.dim),\n};\n\nexport function isTTY(): boolean {\n return !noColor && process.stdout.isTTY === true;\n}\n","import { c, isTTY } from './colors.js';\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((r) => setTimeout(r, ms));\n}\n\nexport async function playDecodeAnimation(token: string): Promise<void> {\n if (!isTTY()) return;\n\n const parts = token.split('.');\n if (parts.length !== 3) return;\n\n const frames = [\n ` ${c.dim(token.slice(0, 40))}${c.dim('...')}`,\n ` ${c.red(parts[0].slice(0, 12))}${c.dim('...')} ${c.dim('·')} ${c.magenta(parts[1].slice(0, 12))}${c.dim('...')} ${c.dim('·')} ${c.cyan(parts[2].slice(0, 12))}${c.dim('...')}`,\n ` ${c.red('■ header')} ${c.dim('·')} ${c.magenta('■ payload')} ${c.dim('·')} ${c.cyan('■ signature')}`,\n ];\n\n process.stdout.write('\\n');\n for (const frame of frames) {\n process.stdout.write(`\\r${frame}${' '.repeat(20)}`);\n await sleep(120);\n }\n process.stdout.write('\\n\\n');\n}\n","import { c } from './colors.js';\n\ntype ColorFn = (s: string) => string;\n\nexport function drawBox(title: string, content: string, color: ColorFn): string {\n const lines = content.split('\\n');\n const maxLen = Math.max(title.length + 4, ...lines.map((l) => l.length));\n const width = Math.min(maxLen + 4, 60);\n\n const top = color(` ┌─ ${title} ${'─'.repeat(Math.max(0, width - title.length - 5))}┐`);\n const bottom = color(` └${'─'.repeat(width - 1)}┘`);\n\n const body = lines.map((line) => {\n const padded = line.padEnd(width - 4);\n return ` ${color('│')} ${padded} ${color('│')}`;\n });\n\n return [top, ...body, bottom].join('\\n');\n}\n\nexport function drawBadge(text: string, color: ColorFn, icon: string): string {\n const inner = ` ${icon} ${text} `;\n const width = inner.length + 2;\n const top = color(` ╔${'═'.repeat(width)}╗`);\n const mid = color(` ║${inner}║`);\n const bottom = color(` ╚${'═'.repeat(width)}╝`);\n return `${top}\\n${mid}\\n${bottom}`;\n}\n\nexport function tokenBar(header: string, payload: string, signature: string): string {\n const total = 50;\n const hLen = Math.max(\n 2,\n Math.round((header.length / (header.length + payload.length + signature.length)) * total),\n );\n const pLen = Math.max(\n 2,\n Math.round((payload.length / (header.length + payload.length + signature.length)) * total),\n );\n const sLen = Math.max(2, total - hLen - pLen);\n\n return ` ${c.red('█'.repeat(hLen))}${c.dim('.')}${c.magenta('█'.repeat(pLen))}${c.dim('.')}${c.cyan('█'.repeat(sLen))}`;\n}\n","import type { JwtAlgorithm } from '@tokx/core';\nimport { encode } from '@tokx/core';\nimport { tokenBar } from '../ui/box.js';\nimport { c } from '../ui/colors.js';\nimport { startSpinner } from '../ui/spinner.js';\n\ninterface EncodeOptions {\n algorithm: string;\n secret: string;\n payload: string;\n expires?: string;\n json?: boolean;\n}\n\nexport async function encodeCommand(options: EncodeOptions): Promise<void> {\n try {\n if (!options.secret) {\n process.stderr.write(`${c.red('error')}: --secret is required\\n`);\n process.exit(1);\n }\n if (!options.payload) {\n process.stderr.write(`${c.red('error')}: --payload is required\\n`);\n process.exit(1);\n }\n\n let payloadObj: Record<string, unknown>;\n try {\n payloadObj = JSON.parse(options.payload);\n } catch {\n process.stderr.write(`${c.red('error')}: --payload must be valid JSON\\n`);\n process.exit(1);\n }\n\n const spinner = startSpinner('Signing token...');\n\n const token = await encode({\n algorithm: options.algorithm as JwtAlgorithm,\n payload: payloadObj,\n secret: options.secret,\n expiresIn: options.expires ? Number(options.expires) : undefined,\n });\n\n spinner.stop(true, `Token signed ${c.dim(`(${options.algorithm})`)}`);\n\n if (options.json) {\n process.stdout.write(`${JSON.stringify({ token })}\\n`);\n } else {\n const parts = token.split('.');\n process.stdout.write('\\n');\n if (parts.length === 3) {\n process.stdout.write(`${tokenBar(parts[0], parts[1], parts[2])}\\n\\n`);\n process.stdout.write(\n ` ${c.red(parts[0])}\\n ${c.dim('.')}\\n ${c.magenta(parts[1])}\\n ${c.dim('.')}\\n ${c.cyan(parts[2])}\\n`,\n );\n } else {\n process.stdout.write(` ${token}\\n`);\n }\n process.stdout.write('\\n');\n }\n } catch (err) {\n process.stderr.write(\n `${c.red('error')}: ${err instanceof Error ? err.message : 'Failed to encode token'}\\n`,\n );\n process.exit(1);\n }\n}\n","import { c, isTTY } from './colors.js';\n\nconst FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];\n\nexport function startSpinner(message: string): {\n stop: (success: boolean, finalMsg: string) => void;\n} {\n if (!isTTY()) {\n return {\n stop: (success, finalMsg) => {\n const icon = success ? c.green('✓') : c.red('✗');\n process.stderr.write(`${icon} ${finalMsg}\\n`);\n },\n };\n }\n\n let i = 0;\n const interval = setInterval(() => {\n process.stderr.write(`\\r ${c.cyan(FRAMES[i % FRAMES.length])} ${message}`);\n i++;\n }, 80);\n\n return {\n stop: (success, finalMsg) => {\n clearInterval(interval);\n const icon = success ? c.green('✓') : c.red('✗');\n process.stderr.write(`\\r ${icon} ${finalMsg}${' '.repeat(20)}\\n`);\n },\n };\n}\n","import Table from 'cli-table3';\nimport { c } from '../ui/colors.js';\n\ninterface LibsOptions {\n language?: string;\n algorithm?: string;\n json?: boolean;\n}\n\ninterface LibEntry {\n name: string;\n language: string;\n author: string;\n url: string;\n stars: number;\n install: string;\n signing: string[];\n verifying: string[];\n}\n\nconst LANG_TAGS: Record<string, string> = {\n JavaScript: 'JS',\n Python: 'PY',\n Java: 'JV',\n Go: 'GO',\n Rust: 'RS',\n Ruby: 'RB',\n PHP: 'PHP',\n '.NET': 'NET',\n Swift: 'SW',\n Kotlin: 'KT',\n Dart: 'DT',\n Erlang: 'ER',\n};\n\nconst LIBRARIES: LibEntry[] = [\n {\n name: 'jose',\n language: 'JavaScript',\n author: 'panva',\n url: 'https://github.com/panva/jose',\n stars: 6200,\n install: 'npm install jose',\n signing: ['HS256', 'RS256', 'ES256', 'EdDSA'],\n verifying: ['HS256', 'RS256', 'ES256', 'EdDSA'],\n },\n {\n name: 'jsonwebtoken',\n language: 'JavaScript',\n author: 'auth0',\n url: 'https://github.com/auth0/node-jsonwebtoken',\n stars: 17500,\n install: 'npm install jsonwebtoken',\n signing: ['HS256', 'RS256', 'ES256'],\n verifying: ['HS256', 'RS256', 'ES256'],\n },\n {\n name: 'PyJWT',\n language: 'Python',\n author: 'jpadilla',\n url: 'https://github.com/jpadilla/pyjwt',\n stars: 5100,\n install: 'pip install PyJWT',\n signing: ['HS256', 'RS256', 'ES256', 'EdDSA'],\n verifying: ['HS256', 'RS256', 'ES256', 'EdDSA'],\n },\n {\n name: 'java-jwt',\n language: 'Java',\n author: 'auth0',\n url: 'https://github.com/auth0/java-jwt',\n stars: 5800,\n install: \"implementation 'com.auth0:java-jwt:4.4.0'\",\n signing: ['HS256', 'RS256', 'ES256'],\n verifying: ['HS256', 'RS256', 'ES256'],\n },\n {\n name: 'jjwt',\n language: 'Java',\n author: 'jwtk',\n url: 'https://github.com/jwtk/jjwt',\n stars: 10300,\n install: \"implementation 'io.jsonwebtoken:jjwt-api:0.12.6'\",\n signing: ['HS256', 'RS256', 'ES256', 'EdDSA'],\n verifying: ['HS256', 'RS256', 'ES256', 'EdDSA'],\n },\n {\n name: 'golang-jwt',\n language: 'Go',\n author: 'golang-jwt',\n url: 'https://github.com/golang-jwt/jwt',\n stars: 7200,\n install: 'go get github.com/golang-jwt/jwt/v5',\n signing: ['HS256', 'RS256', 'ES256', 'EdDSA'],\n verifying: ['HS256', 'RS256', 'ES256', 'EdDSA'],\n },\n {\n name: 'jsonwebtoken',\n language: 'Rust',\n author: 'Keats',\n url: 'https://github.com/Keats/jsonwebtoken',\n stars: 1700,\n install: 'cargo add jsonwebtoken',\n signing: ['HS256', 'RS256', 'ES256', 'EdDSA'],\n verifying: ['HS256', 'RS256', 'ES256', 'EdDSA'],\n },\n {\n name: 'ruby-jwt',\n language: 'Ruby',\n author: 'jwt',\n url: 'https://github.com/jwt/ruby-jwt',\n stars: 3600,\n install: 'gem install jwt',\n signing: ['HS256', 'RS256', 'ES256', 'EdDSA'],\n verifying: ['HS256', 'RS256', 'ES256', 'EdDSA'],\n },\n {\n name: 'php-jwt',\n language: 'PHP',\n author: 'firebase',\n url: 'https://github.com/firebase/php-jwt',\n stars: 9400,\n install: 'composer require firebase/php-jwt',\n signing: ['HS256', 'RS256', 'ES256'],\n verifying: ['HS256', 'RS256', 'ES256'],\n },\n {\n name: 'System.IdentityModel.Tokens.Jwt',\n language: '.NET',\n author: 'AzureAD',\n url: 'https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet',\n stars: 1100,\n install: 'dotnet add package System.IdentityModel.Tokens.Jwt',\n signing: ['HS256', 'RS256', 'ES256'],\n verifying: ['HS256', 'RS256', 'ES256'],\n },\n];\n\nfunction formatStars(n: number): string {\n return n >= 1000 ? `${(n / 1000).toFixed(1)}k` : String(n);\n}\n\nexport function libsCommand(options: LibsOptions): void {\n try {\n let results = LIBRARIES;\n\n if (options.language) {\n const lang = options.language.toLowerCase();\n results = results.filter((l) => l.language.toLowerCase() === lang);\n }\n\n if (options.algorithm) {\n const alg = options.algorithm.toUpperCase();\n results = results.filter((l) => l.signing.includes(alg) || l.verifying.includes(alg));\n }\n\n results.sort((a, b) => b.stars - a.stars);\n\n if (options.json) {\n process.stdout.write(`${JSON.stringify(results, null, 2)}\\n`);\n return;\n }\n\n if (results.length === 0) {\n process.stderr.write(` ${c.dim('No libraries match your filters.')}\\n`);\n return;\n }\n\n const table = new Table({\n head: [c.bold('Library'), c.bold('Lang'), c.bold('★'), c.bold('Install')],\n style: { head: [], border: [] },\n colWidths: [28, 7, 8, 48],\n wordWrap: true,\n });\n\n for (const lib of results) {\n const tag = LANG_TAGS[lib.language] || lib.language.slice(0, 3).toUpperCase();\n const langTag = c.blue(`[${tag}]`);\n table.push([\n c.cyan(lib.name),\n langTag,\n c.yellow(`★ ${formatStars(lib.stars)}`),\n c.dim(lib.install),\n ]);\n }\n\n process.stdout.write(`\\n${table.toString()}\\n\\n`);\n process.stderr.write(` ${c.dim(`${results.length} libraries found`)}\\n\\n`);\n } catch (err) {\n process.stderr.write(\n `${c.red('error')}: ${err instanceof Error ? err.message : 'Failed to list libraries'}\\n`,\n );\n process.exit(3);\n }\n}\n","import type { JwtAlgorithm } from '@tokx/core';\nimport { decode, verify } from '@tokx/core';\nimport { drawBadge } from '../ui/box.js';\nimport { c } from '../ui/colors.js';\nimport { startSpinner } from '../ui/spinner.js';\n\ninterface VerifyOptions {\n algorithm?: string;\n secret?: string;\n publicKey?: string;\n json?: boolean;\n}\n\nexport async function verifyCommand(token: string, options: VerifyOptions): Promise<void> {\n try {\n if (!options.secret && !options.publicKey) {\n process.stderr.write(`${c.red('error')}: --secret or --public-key is required\\n`);\n process.exit(1);\n }\n\n let alg = options.algorithm as JwtAlgorithm | undefined;\n if (!alg) {\n try {\n const decoded = decode(token);\n alg = decoded.header.alg as JwtAlgorithm;\n } catch {\n process.stderr.write(\n `${c.red('error')}: Could not detect algorithm. Use --algorithm to specify.\\n`,\n );\n process.exit(1);\n }\n }\n\n const spinner = startSpinner('Verifying signature...');\n\n const result = await verify(token, {\n algorithm: alg as JwtAlgorithm,\n secret: options.secret || '',\n publicKey: options.publicKey,\n });\n\n if (options.json) {\n spinner.stop(result.valid, result.valid ? 'Valid' : 'Invalid');\n process.stdout.write(`${JSON.stringify(result)}\\n`);\n if (!result.valid) process.exit(2);\n return;\n }\n\n if (result.valid) {\n spinner.stop(true, 'Verification complete');\n process.stdout.write(`\\n${drawBadge('SIGNATURE VERIFIED', c.green, '✓')}\\n\\n`);\n } else {\n spinner.stop(false, 'Verification failed');\n process.stdout.write(`\\n${drawBadge('INVALID SIGNATURE', c.red, '✗')}\\n`);\n if (result.error) process.stderr.write(` ${c.dim(result.error)}\\n`);\n if (result.expired) process.stderr.write(` ${c.yellow('Token has expired')}\\n`);\n process.stdout.write('\\n');\n process.exit(2);\n }\n } catch (err) {\n process.stderr.write(\n `${c.red('error')}: ${err instanceof Error ? err.message : 'Verification failed'}\\n`,\n );\n process.exit(1);\n }\n}\n","import { c, isTTY } from './colors.js';\n\nexport function printBanner(): void {\n if (!isTTY()) return;\n\n const t = c.red('t');\n const o = c.magenta('o');\n const k = c.cyan('k');\n const x = c.cyan('x');\n\n process.stderr.write('\\n');\n process.stderr.write(` ${c.dim('┌─────────────────────────────────┐')}\\n`);\n process.stderr.write(\n ` ${c.dim('│')} ${t} ${o} ${k} ${x} ${c.dim('│')}\\n`,\n );\n process.stderr.write(\n ` ${c.dim('│')} ${c.dim('JWT decode · encode · verify')} ${c.dim('│')}\\n`,\n );\n process.stderr.write(` ${c.dim('└─────────────────────────────────┘')}\\n`);\n process.stderr.write('\\n');\n}\n"],"mappings":"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","names":["decode","decode"]}
package/package.json ADDED
@@ -0,0 +1,73 @@
1
+ {
2
+ "name": "tokx-cli",
3
+ "version": "0.1.0",
4
+ "description": "JWT decode, encode, verify from your terminal",
5
+ "type": "module",
6
+ "bin": {
7
+ "tokx": "./dist/index.js"
8
+ },
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/api.js",
12
+ "types": "./dist/api.d.ts"
13
+ },
14
+ "./cli": {
15
+ "import": "./dist/index.js",
16
+ "types": "./dist/index.d.ts"
17
+ }
18
+ },
19
+ "files": [
20
+ "dist",
21
+ "README.md",
22
+ "LICENSE"
23
+ ],
24
+ "scripts": {
25
+ "build": "tsup",
26
+ "dev": "tsup --watch",
27
+ "test": "vitest run",
28
+ "test:watch": "vitest",
29
+ "test:coverage": "vitest run --coverage",
30
+ "typecheck": "tsc --noEmit",
31
+ "clean": "rm -rf dist",
32
+ "prepublishOnly": "pnpm build"
33
+ },
34
+ "dependencies": {
35
+ "@tokx/core": "workspace:*",
36
+ "commander": "^13.1.0",
37
+ "picocolors": "^1.1.1",
38
+ "cli-table3": "^0.6.5"
39
+ },
40
+ "devDependencies": {
41
+ "@types/node": "^22.13.0",
42
+ "tsup": "^8.4.0",
43
+ "vitest": "^3.1.1"
44
+ },
45
+ "engines": {
46
+ "node": ">=22"
47
+ },
48
+ "main": "./dist/api.js",
49
+ "keywords": [
50
+ "jwt",
51
+ "json-web-token",
52
+ "cli",
53
+ "decode",
54
+ "encode",
55
+ "verify",
56
+ "token",
57
+ "jose"
58
+ ],
59
+ "repository": {
60
+ "type": "git",
61
+ "url": "git+https://github.com/hammadxcm/tokx.git",
62
+ "directory": "packages/cli"
63
+ },
64
+ "homepage": "https://tokx.fyniti.co.uk",
65
+ "bugs": {
66
+ "url": "https://github.com/hammadxcm/tokx/issues"
67
+ },
68
+ "license": "MIT",
69
+ "author": "Hammad Khan",
70
+ "publishConfig": {
71
+ "access": "public"
72
+ }
73
+ }