@nocoo/zhe 1.11.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.
Files changed (54) hide show
  1. package/README.md +57 -0
  2. package/dist/api/client.d.ts +45 -0
  3. package/dist/api/client.d.ts.map +1 -0
  4. package/dist/api/client.js +145 -0
  5. package/dist/api/client.js.map +1 -0
  6. package/dist/api/types.d.ts +45 -0
  7. package/dist/api/types.d.ts.map +1 -0
  8. package/dist/api/types.js +5 -0
  9. package/dist/api/types.js.map +1 -0
  10. package/dist/commands/create.d.ts +43 -0
  11. package/dist/commands/create.d.ts.map +1 -0
  12. package/dist/commands/create.js +173 -0
  13. package/dist/commands/create.js.map +1 -0
  14. package/dist/commands/delete.d.ts +20 -0
  15. package/dist/commands/delete.d.ts.map +1 -0
  16. package/dist/commands/delete.js +93 -0
  17. package/dist/commands/delete.js.map +1 -0
  18. package/dist/commands/get.d.ts +15 -0
  19. package/dist/commands/get.d.ts.map +1 -0
  20. package/dist/commands/get.js +67 -0
  21. package/dist/commands/get.js.map +1 -0
  22. package/dist/commands/list.d.ts +29 -0
  23. package/dist/commands/list.d.ts.map +1 -0
  24. package/dist/commands/list.js +90 -0
  25. package/dist/commands/list.js.map +1 -0
  26. package/dist/commands/login.d.ts +5 -0
  27. package/dist/commands/login.d.ts.map +1 -0
  28. package/dist/commands/login.js +112 -0
  29. package/dist/commands/login.js.map +1 -0
  30. package/dist/commands/logout.d.ts +5 -0
  31. package/dist/commands/logout.d.ts.map +1 -0
  32. package/dist/commands/logout.js +21 -0
  33. package/dist/commands/logout.js.map +1 -0
  34. package/dist/commands/open.d.ts +11 -0
  35. package/dist/commands/open.d.ts.map +1 -0
  36. package/dist/commands/open.js +53 -0
  37. package/dist/commands/open.js.map +1 -0
  38. package/dist/commands/update.d.ts +40 -0
  39. package/dist/commands/update.d.ts.map +1 -0
  40. package/dist/commands/update.js +134 -0
  41. package/dist/commands/update.js.map +1 -0
  42. package/dist/config.d.ts +38 -0
  43. package/dist/config.d.ts.map +1 -0
  44. package/dist/config.js +66 -0
  45. package/dist/config.js.map +1 -0
  46. package/dist/index.d.ts +6 -0
  47. package/dist/index.d.ts.map +1 -0
  48. package/dist/index.js +32 -0
  49. package/dist/index.js.map +1 -0
  50. package/dist/utils.d.ts +41 -0
  51. package/dist/utils.d.ts.map +1 -0
  52. package/dist/utils.js +105 -0
  53. package/dist/utils.js.map +1 -0
  54. package/package.json +47 -0
package/README.md ADDED
@@ -0,0 +1,57 @@
1
+ # zhe CLI
2
+
3
+ CLI for managing zhe.to short links.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install -g @nocoo/zhe
9
+ # or
10
+ bun add -g @nocoo/zhe
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ```bash
16
+ # Authenticate
17
+ zhe login
18
+
19
+ # Create a short link
20
+ zhe create https://example.com/long/url
21
+
22
+ # List your links
23
+ zhe list
24
+
25
+ # Get link details
26
+ zhe get 123
27
+
28
+ # Update a link
29
+ zhe update 123 --slug new-slug
30
+
31
+ # Delete a link
32
+ zhe delete 123
33
+
34
+ # Open a short link in browser
35
+ zhe open my-slug
36
+ ```
37
+
38
+ ## Commands
39
+
40
+ | Command | Description |
41
+ |---------|-------------|
42
+ | `zhe login` | Authenticate with API Key |
43
+ | `zhe logout` | Clear stored credentials |
44
+ | `zhe list` | List all links |
45
+ | `zhe create <url>` | Create a new short link |
46
+ | `zhe get <id>` | Get link details |
47
+ | `zhe update <id>` | Update a link |
48
+ | `zhe delete <id>` | Delete a link |
49
+ | `zhe open <slug>` | Open short URL in browser |
50
+
51
+ ## Configuration
52
+
53
+ Config file location: `~/.config/zhe/config.json`
54
+
55
+ ## License
56
+
57
+ MIT
@@ -0,0 +1,45 @@
1
+ /**
2
+ * HTTP client for zhe.to API v1
3
+ */
4
+ import type { CreateLinkRequest, LinkResponse, LinksResponse, ListLinksParams, UpdateLinkRequest } from "./types.js";
5
+ export declare class ApiClient {
6
+ private apiKey;
7
+ private userAgent;
8
+ constructor(apiKey: string, version?: string);
9
+ private request;
10
+ /**
11
+ * List links with optional filters
12
+ */
13
+ listLinks(params?: ListLinksParams): Promise<LinksResponse>;
14
+ /**
15
+ * Get a single link by ID
16
+ */
17
+ getLink(id: number): Promise<LinkResponse>;
18
+ /**
19
+ * Create a new link
20
+ */
21
+ createLink(data: CreateLinkRequest): Promise<LinkResponse>;
22
+ /**
23
+ * Update an existing link
24
+ */
25
+ updateLink(id: number, data: UpdateLinkRequest): Promise<LinkResponse>;
26
+ /**
27
+ * Delete a link
28
+ */
29
+ deleteLink(id: number): Promise<void>;
30
+ /**
31
+ * Verify API key by making a test request
32
+ */
33
+ verifyKey(): Promise<boolean>;
34
+ }
35
+ export declare class ApiClientError extends Error {
36
+ readonly status: number;
37
+ constructor(status: number, message: string);
38
+ }
39
+ export declare const EXIT_SUCCESS = 0;
40
+ export declare const EXIT_ERROR = 1;
41
+ export declare const EXIT_INVALID_ARGS = 2;
42
+ export declare const EXIT_AUTH_REQUIRED = 3;
43
+ export declare const EXIT_NOT_FOUND = 4;
44
+ export declare const EXIT_RATE_LIMITED = 5;
45
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAEX,iBAAiB,EACjB,YAAY,EACZ,aAAa,EACb,eAAe,EACf,iBAAiB,EACjB,MAAM,YAAY,CAAC;AAKpB,qBAAa,SAAS;IACrB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,SAAS,CAAS;gBAEd,MAAM,EAAE,MAAM,EAAE,OAAO,SAAU;YAK/B,OAAO;IA0ErB;;OAEG;IACG,SAAS,CAAC,MAAM,GAAE,eAAoB,GAAG,OAAO,CAAC,aAAa,CAAC;IAWrE;;OAEG;IACG,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAIhD;;OAEG;IACG,UAAU,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,YAAY,CAAC;IAIhE;;OAEG;IACG,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,YAAY,CAAC;IAI5E;;OAEG;IACG,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3C;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC;CAanC;AAED,qBAAa,cAAe,SAAQ,KAAK;aAEvB,MAAM,EAAE,MAAM;gBAAd,MAAM,EAAE,MAAM,EAC9B,OAAO,EAAE,MAAM;CAKhB;AAgBD,eAAO,MAAM,YAAY,IAAI,CAAC;AAC9B,eAAO,MAAM,UAAU,IAAI,CAAC;AAC5B,eAAO,MAAM,iBAAiB,IAAI,CAAC;AACnC,eAAO,MAAM,kBAAkB,IAAI,CAAC;AACpC,eAAO,MAAM,cAAc,IAAI,CAAC;AAChC,eAAO,MAAM,iBAAiB,IAAI,CAAC"}
@@ -0,0 +1,145 @@
1
+ /**
2
+ * HTTP client for zhe.to API v1
3
+ */
4
+ const API_BASE = "https://zhe.to/api/v1";
5
+ const TIMEOUT_MS = 30_000;
6
+ export class ApiClient {
7
+ apiKey;
8
+ userAgent;
9
+ constructor(apiKey, version = "1.0.0") {
10
+ this.apiKey = apiKey;
11
+ this.userAgent = `zhe-cli/${version}`;
12
+ }
13
+ async request(method, path, body) {
14
+ const url = `${API_BASE}${path}`;
15
+ const controller = new AbortController();
16
+ const timeoutId = setTimeout(() => controller.abort(), TIMEOUT_MS);
17
+ try {
18
+ const response = await fetch(url, {
19
+ method,
20
+ headers: {
21
+ Authorization: `Bearer ${this.apiKey}`,
22
+ "Content-Type": "application/json",
23
+ "User-Agent": this.userAgent,
24
+ },
25
+ ...(body ? { body: JSON.stringify(body) } : {}),
26
+ signal: controller.signal,
27
+ });
28
+ clearTimeout(timeoutId);
29
+ // Handle rate limit warning
30
+ const remaining = response.headers.get("X-RateLimit-Remaining");
31
+ if (remaining && Number.parseInt(remaining, 10) < 10) {
32
+ console.warn(`Warning: Rate limit low (${remaining} requests remaining)`);
33
+ }
34
+ if (!response.ok) {
35
+ const errorBody = (await response.json().catch(() => ({})));
36
+ throw new ApiClientError(response.status, errorBody.error || getDefaultErrorMessage(response.status));
37
+ }
38
+ // Handle 204 No Content
39
+ if (response.status === 204) {
40
+ return {};
41
+ }
42
+ return (await response.json());
43
+ }
44
+ catch (error) {
45
+ clearTimeout(timeoutId);
46
+ if (error instanceof ApiClientError) {
47
+ throw error;
48
+ }
49
+ if (error instanceof Error) {
50
+ if (error.name === "AbortError") {
51
+ throw new ApiClientError(0, "Request timed out. Check your connection and try again.");
52
+ }
53
+ if (error.message.includes("ENOTFOUND") ||
54
+ error.message.includes("getaddrinfo")) {
55
+ throw new ApiClientError(0, "Could not reach zhe.to. Check your connection.");
56
+ }
57
+ }
58
+ throw new ApiClientError(0, "Network error. Please try again.");
59
+ }
60
+ }
61
+ /**
62
+ * List links with optional filters
63
+ */
64
+ async listLinks(params = {}) {
65
+ const searchParams = new URLSearchParams();
66
+ if (params.limit)
67
+ searchParams.set("limit", String(params.limit));
68
+ if (params.offset)
69
+ searchParams.set("offset", String(params.offset));
70
+ if (params.folderId)
71
+ searchParams.set("folderId", params.folderId);
72
+ const query = searchParams.toString();
73
+ const path = query ? `/links?${query}` : "/links";
74
+ return this.request("GET", path);
75
+ }
76
+ /**
77
+ * Get a single link by ID
78
+ */
79
+ async getLink(id) {
80
+ return this.request("GET", `/links/${id}`);
81
+ }
82
+ /**
83
+ * Create a new link
84
+ */
85
+ async createLink(data) {
86
+ return this.request("POST", "/links", data);
87
+ }
88
+ /**
89
+ * Update an existing link
90
+ */
91
+ async updateLink(id, data) {
92
+ return this.request("PATCH", `/links/${id}`, data);
93
+ }
94
+ /**
95
+ * Delete a link
96
+ */
97
+ async deleteLink(id) {
98
+ await this.request("DELETE", `/links/${id}`);
99
+ }
100
+ /**
101
+ * Verify API key by making a test request
102
+ */
103
+ async verifyKey() {
104
+ try {
105
+ await this.listLinks({ limit: 1 });
106
+ return true;
107
+ }
108
+ catch (error) {
109
+ if (error instanceof ApiClientError) {
110
+ if (error.status === 401 || error.status === 403) {
111
+ return false;
112
+ }
113
+ }
114
+ throw error;
115
+ }
116
+ }
117
+ }
118
+ export class ApiClientError extends Error {
119
+ status;
120
+ constructor(status, message) {
121
+ super(message);
122
+ this.status = status;
123
+ this.name = "ApiClientError";
124
+ }
125
+ }
126
+ function getDefaultErrorMessage(status) {
127
+ const messages = {
128
+ 400: "Invalid request",
129
+ 401: "Not authenticated. Run `zhe login`.",
130
+ 403: "Permission denied. Check your API Key scopes.",
131
+ 404: "Not found",
132
+ 409: "Conflict",
133
+ 429: "Rate limit exceeded. Try again later.",
134
+ 500: "Server error",
135
+ };
136
+ return messages[status] || `HTTP error ${status}`;
137
+ }
138
+ // Exit codes
139
+ export const EXIT_SUCCESS = 0;
140
+ export const EXIT_ERROR = 1;
141
+ export const EXIT_INVALID_ARGS = 2;
142
+ export const EXIT_AUTH_REQUIRED = 3;
143
+ export const EXIT_NOT_FOUND = 4;
144
+ export const EXIT_RATE_LIMITED = 5;
145
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * API types for zhe.to v1 API
3
+ */
4
+ export interface Link {
5
+ id: number;
6
+ slug: string;
7
+ originalUrl: string;
8
+ shortUrl: string;
9
+ isCustom: boolean;
10
+ clicks: number;
11
+ folderId: string | null;
12
+ note: string | null;
13
+ expiresAt: string | null;
14
+ createdAt: string;
15
+ updatedAt: string;
16
+ }
17
+ export interface LinksResponse {
18
+ links: Link[];
19
+ }
20
+ export interface LinkResponse {
21
+ link: Link;
22
+ }
23
+ export interface CreateLinkRequest {
24
+ url: string;
25
+ slug?: string;
26
+ folderId?: string;
27
+ note?: string;
28
+ expiresAt?: string;
29
+ }
30
+ export interface UpdateLinkRequest {
31
+ originalUrl?: string;
32
+ slug?: string;
33
+ folderId?: string | null;
34
+ note?: string | null;
35
+ expiresAt?: string | null;
36
+ }
37
+ export interface ApiError {
38
+ error: string;
39
+ }
40
+ export interface ListLinksParams {
41
+ limit?: number;
42
+ offset?: number;
43
+ folderId?: string;
44
+ }
45
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/api/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,IAAI;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC7B,KAAK,EAAE,IAAI,EAAE,CAAC;CACd;AAED,MAAM,WAAW,YAAY;IAC5B,IAAI,EAAE,IAAI,CAAC;CACX;AAED,MAAM,WAAW,iBAAiB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IACjC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,QAAQ;IACxB,KAAK,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,eAAe;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * API types for zhe.to v1 API
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/api/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * zhe create <url> — Create a new short link
3
+ */
4
+ export declare const createCommand: import("citty").CommandDef<{
5
+ readonly url: {
6
+ readonly type: "positional";
7
+ readonly description: "The URL to shorten";
8
+ readonly required: true;
9
+ };
10
+ readonly slug: {
11
+ readonly type: "string";
12
+ readonly alias: "s";
13
+ readonly description: "Custom slug (auto-generated if not provided)";
14
+ };
15
+ readonly folder: {
16
+ readonly type: "string";
17
+ readonly alias: "f";
18
+ readonly description: "Folder ID";
19
+ };
20
+ readonly note: {
21
+ readonly type: "string";
22
+ readonly alias: "n";
23
+ readonly description: "Note/description";
24
+ };
25
+ readonly expires: {
26
+ readonly type: "string";
27
+ readonly alias: "e";
28
+ readonly description: "Expiration date (ISO 8601)";
29
+ };
30
+ readonly copy: {
31
+ readonly type: "boolean";
32
+ readonly description: "Copy short URL to clipboard";
33
+ };
34
+ readonly open: {
35
+ readonly type: "boolean";
36
+ readonly description: "Open short URL in browser";
37
+ };
38
+ readonly json: {
39
+ readonly type: "boolean";
40
+ readonly description: "Output as JSON";
41
+ };
42
+ }>;
43
+ //# sourceMappingURL=create.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../src/commands/create.ts"],"names":[],"mappings":"AAAA;;GAEG;AAeH,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+FxB,CAAC"}
@@ -0,0 +1,173 @@
1
+ /**
2
+ * zhe create <url> — Create a new short link
3
+ */
4
+ import { exec } from "node:child_process";
5
+ import { defineCommand, pc } from "@nocoo/cli-base";
6
+ import { ApiClient, ApiClientError, EXIT_AUTH_REQUIRED, EXIT_ERROR, EXIT_INVALID_ARGS, EXIT_RATE_LIMITED, } from "../api/client.js";
7
+ import { getApiKey } from "../config.js";
8
+ export const createCommand = defineCommand({
9
+ meta: {
10
+ name: "create",
11
+ description: "Create a new short link",
12
+ },
13
+ args: {
14
+ url: {
15
+ type: "positional",
16
+ description: "The URL to shorten",
17
+ required: true,
18
+ },
19
+ slug: {
20
+ type: "string",
21
+ alias: "s",
22
+ description: "Custom slug (auto-generated if not provided)",
23
+ },
24
+ folder: {
25
+ type: "string",
26
+ alias: "f",
27
+ description: "Folder ID",
28
+ },
29
+ note: {
30
+ type: "string",
31
+ alias: "n",
32
+ description: "Note/description",
33
+ },
34
+ expires: {
35
+ type: "string",
36
+ alias: "e",
37
+ description: "Expiration date (ISO 8601)",
38
+ },
39
+ copy: {
40
+ type: "boolean",
41
+ description: "Copy short URL to clipboard",
42
+ },
43
+ open: {
44
+ type: "boolean",
45
+ description: "Open short URL in browser",
46
+ },
47
+ json: {
48
+ type: "boolean",
49
+ description: "Output as JSON",
50
+ },
51
+ },
52
+ async run({ args }) {
53
+ const apiKey = getApiKey();
54
+ if (!apiKey) {
55
+ console.log(pc.red("Not authenticated. Run `zhe login` first."));
56
+ process.exit(EXIT_AUTH_REQUIRED);
57
+ }
58
+ const url = args.url;
59
+ // Basic URL validation
60
+ if (!isValidUrl(url)) {
61
+ console.log(pc.red("Invalid URL format. Include protocol (https://)."));
62
+ process.exit(EXIT_INVALID_ARGS);
63
+ }
64
+ const client = new ApiClient(apiKey);
65
+ try {
66
+ // Build request object, only including defined fields
67
+ const createRequest = { url };
68
+ if (args.slug)
69
+ createRequest.slug = args.slug;
70
+ if (args.folder)
71
+ createRequest.folderId = args.folder;
72
+ if (args.note)
73
+ createRequest.note = args.note;
74
+ if (args.expires)
75
+ createRequest.expiresAt = args.expires;
76
+ const response = await client.createLink(createRequest);
77
+ const shortUrl = response.link.shortUrl;
78
+ // Handle clipboard
79
+ let copied = false;
80
+ if (args.copy) {
81
+ copied = await copyToClipboard(shortUrl);
82
+ }
83
+ // Handle open in browser
84
+ if (args.open) {
85
+ openInBrowser(shortUrl);
86
+ }
87
+ // Output
88
+ if (args.json) {
89
+ console.log(JSON.stringify(response, null, 2));
90
+ }
91
+ else {
92
+ const suffix = copied ? " (copied to clipboard)" : "";
93
+ console.log(pc.green(`✓ Created ${pc.cyan(shortUrl)}${suffix}`));
94
+ }
95
+ }
96
+ catch (error) {
97
+ handleApiError(error);
98
+ }
99
+ },
100
+ });
101
+ function isValidUrl(url) {
102
+ try {
103
+ const parsed = new URL(url);
104
+ return parsed.protocol === "http:" || parsed.protocol === "https:";
105
+ }
106
+ catch {
107
+ return false;
108
+ }
109
+ }
110
+ async function copyToClipboard(text) {
111
+ return new Promise((resolve) => {
112
+ const platform = process.platform;
113
+ let command;
114
+ if (platform === "darwin") {
115
+ command = "pbcopy";
116
+ }
117
+ else if (platform === "linux") {
118
+ command = "xclip -selection clipboard";
119
+ }
120
+ else if (platform === "win32") {
121
+ command = "clip";
122
+ }
123
+ else {
124
+ resolve(false);
125
+ return;
126
+ }
127
+ const child = exec(command, (error) => {
128
+ resolve(!error);
129
+ });
130
+ child.stdin?.write(text);
131
+ child.stdin?.end();
132
+ });
133
+ }
134
+ function openInBrowser(url) {
135
+ const platform = process.platform;
136
+ let command;
137
+ if (platform === "darwin") {
138
+ command = `open "${url}"`;
139
+ }
140
+ else if (platform === "linux") {
141
+ command = `xdg-open "${url}"`;
142
+ }
143
+ else if (platform === "win32") {
144
+ command = `start "" "${url}"`;
145
+ }
146
+ else {
147
+ return;
148
+ }
149
+ exec(command);
150
+ }
151
+ function handleApiError(error) {
152
+ if (error instanceof ApiClientError) {
153
+ // Provide specific error messages
154
+ if (error.status === 409) {
155
+ console.log(pc.red("Slug is already in use."));
156
+ }
157
+ else if (error.status === 400) {
158
+ console.log(pc.red(`Error: ${error.message}`));
159
+ }
160
+ else {
161
+ console.log(pc.red(`Error: ${error.message}`));
162
+ }
163
+ if (error.status === 401) {
164
+ process.exit(EXIT_AUTH_REQUIRED);
165
+ }
166
+ if (error.status === 429) {
167
+ process.exit(EXIT_RATE_LIMITED);
168
+ }
169
+ process.exit(EXIT_ERROR);
170
+ }
171
+ throw error;
172
+ }
173
+ //# sourceMappingURL=create.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create.js","sourceRoot":"","sources":["../../src/commands/create.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * zhe delete <id> — Delete a link
3
+ */
4
+ export declare const deleteCommand: import("citty").CommandDef<{
5
+ readonly id: {
6
+ readonly type: "positional";
7
+ readonly description: "Link ID (numeric)";
8
+ readonly required: true;
9
+ };
10
+ readonly yes: {
11
+ readonly type: "boolean";
12
+ readonly alias: "y";
13
+ readonly description: "Skip confirmation prompt";
14
+ };
15
+ readonly json: {
16
+ readonly type: "boolean";
17
+ readonly description: "Output as JSON";
18
+ };
19
+ }>;
20
+ //# sourceMappingURL=delete.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delete.d.ts","sourceRoot":"","sources":["../../src/commands/delete.ts"],"names":[],"mappings":"AAAA;;GAEG;AAgBH,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;EA0DxB,CAAC"}
@@ -0,0 +1,93 @@
1
+ /**
2
+ * zhe delete <id> — Delete a link
3
+ */
4
+ import * as readline from "node:readline";
5
+ import { defineCommand, pc } from "@nocoo/cli-base";
6
+ import { ApiClient, ApiClientError, EXIT_AUTH_REQUIRED, EXIT_ERROR, EXIT_INVALID_ARGS, EXIT_NOT_FOUND, EXIT_RATE_LIMITED, } from "../api/client.js";
7
+ import { getApiKey } from "../config.js";
8
+ import { parseLinkId } from "../utils.js";
9
+ export const deleteCommand = defineCommand({
10
+ meta: {
11
+ name: "delete",
12
+ description: "Delete a link",
13
+ },
14
+ args: {
15
+ id: {
16
+ type: "positional",
17
+ description: "Link ID (numeric)",
18
+ required: true,
19
+ },
20
+ yes: {
21
+ type: "boolean",
22
+ alias: "y",
23
+ description: "Skip confirmation prompt",
24
+ },
25
+ json: {
26
+ type: "boolean",
27
+ description: "Output as JSON",
28
+ },
29
+ },
30
+ async run({ args }) {
31
+ const apiKey = getApiKey();
32
+ if (!apiKey) {
33
+ console.log(pc.red("Not authenticated. Run `zhe login` first."));
34
+ process.exit(EXIT_AUTH_REQUIRED);
35
+ }
36
+ const idStr = args.id;
37
+ const id = parseLinkId(idStr);
38
+ if (id === null) {
39
+ console.log(pc.red("Invalid link ID. Must be a number."));
40
+ process.exit(EXIT_INVALID_ARGS);
41
+ }
42
+ // Confirmation prompt unless --yes flag
43
+ if (!args.yes) {
44
+ const confirmed = await confirm(`Delete link #${id}?`);
45
+ if (!confirmed) {
46
+ console.log(pc.dim("Cancelled."));
47
+ return;
48
+ }
49
+ }
50
+ const client = new ApiClient(apiKey);
51
+ try {
52
+ await client.deleteLink(id);
53
+ if (args.json) {
54
+ console.log(JSON.stringify({ success: true }));
55
+ }
56
+ else {
57
+ console.log(pc.green("✓ Deleted"));
58
+ }
59
+ }
60
+ catch (error) {
61
+ handleApiError(error);
62
+ }
63
+ },
64
+ });
65
+ async function confirm(message) {
66
+ return new Promise((resolve) => {
67
+ const rl = readline.createInterface({
68
+ input: process.stdin,
69
+ output: process.stdout,
70
+ });
71
+ rl.question(`${message} [y/N] `, (answer) => {
72
+ rl.close();
73
+ resolve(answer.toLowerCase() === "y");
74
+ });
75
+ });
76
+ }
77
+ function handleApiError(error) {
78
+ if (error instanceof ApiClientError) {
79
+ console.log(pc.red(`Error: ${error.message}`));
80
+ if (error.status === 401) {
81
+ process.exit(EXIT_AUTH_REQUIRED);
82
+ }
83
+ if (error.status === 404) {
84
+ process.exit(EXIT_NOT_FOUND);
85
+ }
86
+ if (error.status === 429) {
87
+ process.exit(EXIT_RATE_LIMITED);
88
+ }
89
+ process.exit(EXIT_ERROR);
90
+ }
91
+ throw error;
92
+ }
93
+ //# sourceMappingURL=delete.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delete.js","sourceRoot":"","sources":["../../src/commands/delete.ts"],"names":[],"mappings":"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"}