@tinyurl-ca/cli 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.
package/README.md ADDED
@@ -0,0 +1,139 @@
1
+ # TinyURL.ca CLI
2
+
3
+ Command-line tool for creating and managing short links from your terminal.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install -g @tinyurl-ca/cli
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ### 1. Configure your API key
14
+
15
+ ```bash
16
+ tinyurl config --key YOUR_API_KEY
17
+ ```
18
+
19
+ Get your API key from https://tinyurl.ca/dashboard/settings
20
+
21
+ ### 2. Shorten a URL
22
+
23
+ ```bash
24
+ tinyurl shorten https://example.com
25
+ ```
26
+
27
+ ## Commands
28
+
29
+ ### `config`
30
+ Configure your API key
31
+
32
+ ```bash
33
+ tinyurl config --key YOUR_API_KEY
34
+ ```
35
+
36
+ ### `shorten`
37
+ Create a new short link
38
+
39
+ ```bash
40
+ # Basic usage
41
+ tinyurl shorten https://example.com
42
+
43
+ # Custom short code
44
+ tinyurl shorten https://example.com --custom my-link
45
+
46
+ # Add title
47
+ tinyurl shorten https://example.com --title "My Website"
48
+
49
+ # Set expiration (30 days)
50
+ tinyurl shorten https://example.com --expires 2592000
51
+
52
+ # Show QR code
53
+ tinyurl shorten https://example.com --qr
54
+ ```
55
+
56
+ ### `list`
57
+ List your short links
58
+
59
+ ```bash
60
+ # List 20 most recent links
61
+ tinyurl list
62
+
63
+ # List 50 links
64
+ tinyurl list --limit 50
65
+ ```
66
+
67
+ ### `get`
68
+ Get details of a specific link
69
+
70
+ ```bash
71
+ tinyurl get LINK_ID
72
+
73
+ # Show with QR code
74
+ tinyurl get LINK_ID --qr
75
+ ```
76
+
77
+ ### `delete`
78
+ Delete a short link
79
+
80
+ ```bash
81
+ tinyurl delete LINK_ID
82
+
83
+ # Alias
84
+ tinyurl rm LINK_ID
85
+ ```
86
+
87
+ ### `stats`
88
+ Get analytics for a link
89
+
90
+ ```bash
91
+ tinyurl stats LINK_ID
92
+ ```
93
+
94
+ ## Options
95
+
96
+ | Option | Description |
97
+ |--------|-------------|
98
+ | `-k, --key <apiKey>` | Your API key |
99
+ | `-c, --custom <code>` | Custom short code |
100
+ | `-t, --title <title>` | Link title |
101
+ | `-e, --expires <seconds>` | Expiration time in seconds |
102
+ | `-q, --qr` | Show QR code |
103
+ | `-l, --limit <number>` | Number of items to display |
104
+
105
+ ## Examples
106
+
107
+ ### Create a link with custom code
108
+ ```bash
109
+ tinyurl shorten https://mywebsite.com --custom promo2024
110
+ # → https://tinyurl.ca/promo2024
111
+ ```
112
+
113
+ ### Create temporary link (expires in 1 hour)
114
+ ```bash
115
+ tinyurl shorten https://example.com --expires 3600
116
+ ```
117
+
118
+ ### List last 100 links
119
+ ```bash
120
+ tinyurl list --limit 100
121
+ ```
122
+
123
+ ## Environment Variables
124
+
125
+ You can also set your API key via environment variable:
126
+
127
+ ```bash
128
+ export TINYURL_API_KEY=your_api_key_here
129
+ ```
130
+
131
+ ## License
132
+
133
+ MIT
134
+
135
+ ## Support
136
+
137
+ - Documentation: https://tinyurl.ca/docs
138
+ - Issues: https://github.com/raj-iwt/tinyurl-cli/issues
139
+ - Email: support@tinyurl.ca
package/bin/cli.js ADDED
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import { readFileSync } from 'fs';
4
+ import { fileURLToPath } from 'url';
5
+ import { dirname, join } from 'path';
6
+ import * as commands from '../dist/commands.js';
7
+
8
+ const __filename = fileURLToPath(import.meta.url);
9
+ const __dirname = dirname(__filename);
10
+ const packageJson = JSON.parse(readFileSync(join(__dirname, '../package.json'), 'utf-8'));
11
+ const { version } = packageJson;
12
+
13
+ const program = new Command();
14
+
15
+ program
16
+ .name('tinyurl')
17
+ .description('TinyURL.ca CLI - Create and manage short links from your terminal')
18
+ .version(version);
19
+
20
+ // Configure API key
21
+ program
22
+ .command('config')
23
+ .description('Configure your API key')
24
+ .option('-k, --key <apiKey>', 'Your TinyURL.ca API key')
25
+ .action(commands.config);
26
+
27
+ // Create a short link
28
+ program
29
+ .command('shorten')
30
+ .description('Create a new short link')
31
+ .argument('<url>', 'URL to shorten')
32
+ .option('-c, --custom <code>', 'Custom short code')
33
+ .option('-t, --title <title>', 'Link title')
34
+ .option('-e, --expires <seconds>', 'Expiration time in seconds')
35
+ .option('-q, --qr', 'Show QR code')
36
+ .action(commands.shorten);
37
+
38
+ // List all links
39
+ program
40
+ .command('list')
41
+ .description('List your short links')
42
+ .option('-l, --limit <number>', 'Number of links to display', '20')
43
+ .action(commands.list);
44
+
45
+ // Get link details
46
+ program
47
+ .command('get')
48
+ .description('Get details of a specific link')
49
+ .argument('<id>', 'Link ID or short code')
50
+ .option('-q, --qr', 'Show QR code')
51
+ .action(commands.get);
52
+
53
+ // Delete a link
54
+ program
55
+ .command('delete')
56
+ .alias('rm')
57
+ .description('Delete a short link')
58
+ .argument('<id>', 'Link ID to delete')
59
+ .action(commands.deleteLink);
60
+
61
+ // Get link analytics
62
+ program
63
+ .command('stats')
64
+ .description('Get analytics for a link')
65
+ .argument('<id>', 'Link ID or short code')
66
+ .action(commands.stats);
67
+
68
+ program.parse();
@@ -0,0 +1,12 @@
1
+ export declare function config(options: {
2
+ key?: string;
3
+ }): Promise<void>;
4
+ export declare function shorten(url: string, options: any): Promise<void>;
5
+ export declare function list(options: {
6
+ limit: string;
7
+ }): Promise<void>;
8
+ export declare function get(id: string, options: {
9
+ qr?: boolean;
10
+ }): Promise<void>;
11
+ export declare function deleteLink(id: string): Promise<void>;
12
+ export declare function stats(id: string): Promise<void>;
@@ -0,0 +1,162 @@
1
+ import axios from 'axios';
2
+ import Conf from 'conf';
3
+ import chalk from 'chalk';
4
+ import ora from 'ora';
5
+ import Table from 'cli-table3';
6
+ import qrcode from 'qrcode-terminal';
7
+ const store = new Conf({ projectName: 'tinyurl-cli' });
8
+ const API_BASE = 'https://tinyurl.ca/api/v1';
9
+ // Helper to get API client
10
+ function getApiClient() {
11
+ const apiKey = store.get('apiKey');
12
+ if (!apiKey) {
13
+ console.log(chalk.red('❌ API key not configured'));
14
+ console.log(chalk.yellow('Run: tinyurl config --key YOUR_API_KEY'));
15
+ process.exit(1);
16
+ }
17
+ return axios.create({
18
+ baseURL: API_BASE,
19
+ headers: {
20
+ 'X-API-Key': apiKey,
21
+ 'Content-Type': 'application/json',
22
+ },
23
+ });
24
+ }
25
+ // Configure API key
26
+ export async function config(options) {
27
+ if (options.key) {
28
+ store.set('apiKey', options.key);
29
+ console.log(chalk.green('✓ API key configured successfully'));
30
+ console.log(chalk.gray('You can now use the CLI to create short links'));
31
+ }
32
+ else {
33
+ const currentKey = store.get('apiKey');
34
+ if (currentKey) {
35
+ console.log(chalk.blue('Current API key:'), chalk.gray(currentKey.substring(0, 20) + '...'));
36
+ }
37
+ else {
38
+ console.log(chalk.yellow('No API key configured'));
39
+ console.log(chalk.gray('Run: tinyurl config --key YOUR_API_KEY'));
40
+ }
41
+ }
42
+ }
43
+ // Shorten a URL
44
+ export async function shorten(url, options) {
45
+ const spinner = ora('Creating short link...').start();
46
+ try {
47
+ const api = getApiClient();
48
+ const response = await api.post('/links', {
49
+ url,
50
+ customCode: options.custom,
51
+ title: options.title,
52
+ expiresIn: options.expires ? parseInt(options.expires) : null,
53
+ });
54
+ spinner.succeed('Short link created!');
55
+ const { data } = response.data;
56
+ console.log('');
57
+ console.log(chalk.green.bold('✓ Success!'));
58
+ console.log('');
59
+ console.log(chalk.cyan('Short URL:'), chalk.bold.underline(data.shortUrl));
60
+ console.log(chalk.gray('Original:'), data.originalUrl);
61
+ if (data.title) {
62
+ console.log(chalk.gray('Title:'), data.title);
63
+ }
64
+ console.log(chalk.gray('Created:'), new Date(data.createdAt).toLocaleString());
65
+ if (options.qr) {
66
+ console.log('');
67
+ qrcode.generate(data.shortUrl, { small: true });
68
+ }
69
+ }
70
+ catch (error) {
71
+ spinner.fail('Failed to create short link');
72
+ console.log(chalk.red('Error:'), error.response?.data?.error || error.message);
73
+ process.exit(1);
74
+ }
75
+ }
76
+ // List links
77
+ export async function list(options) {
78
+ const spinner = ora('Fetching your links...').start();
79
+ try {
80
+ const api = getApiClient();
81
+ const response = await api.get('/links', {
82
+ params: { limit: options.limit }
83
+ });
84
+ spinner.stop();
85
+ const { data } = response.data;
86
+ if (data.length === 0) {
87
+ console.log(chalk.yellow('No links found'));
88
+ return;
89
+ }
90
+ const table = new Table({
91
+ head: ['Short Code', 'Original URL', 'Clicks', 'Created'].map(h => chalk.cyan(h)),
92
+ colWidths: [15, 50, 10, 20],
93
+ });
94
+ data.forEach((link) => {
95
+ table.push([
96
+ chalk.bold(link.shortCode),
97
+ link.originalUrl.substring(0, 47) + '...',
98
+ link.clicks.toString(),
99
+ new Date(link.createdAt).toLocaleDateString(),
100
+ ]);
101
+ });
102
+ console.log('');
103
+ console.log(table.toString());
104
+ console.log('');
105
+ console.log(chalk.gray(`Showing ${data.length} links`));
106
+ }
107
+ catch (error) {
108
+ spinner.fail('Failed to fetch links');
109
+ console.log(chalk.red('Error:'), error.response?.data?.error || error.message);
110
+ process.exit(1);
111
+ }
112
+ }
113
+ // Get link details
114
+ export async function get(id, options) {
115
+ const spinner = ora('Fetching link details...').start();
116
+ try {
117
+ const api = getApiClient();
118
+ const response = await api.get(`/links/${id}`);
119
+ spinner.succeed('Link found!');
120
+ const { data } = response.data;
121
+ console.log('');
122
+ console.log(chalk.cyan.bold('Link Details'));
123
+ console.log('');
124
+ console.log(chalk.gray('ID:'), data.id);
125
+ console.log(chalk.gray('Short Code:'), chalk.bold(data.shortCode));
126
+ console.log(chalk.gray('Short URL:'), chalk.bold.underline(data.shortUrl));
127
+ console.log(chalk.gray('Original URL:'), data.originalUrl);
128
+ if (data.title) {
129
+ console.log(chalk.gray('Title:'), data.title);
130
+ }
131
+ console.log(chalk.gray('Clicks:'), chalk.bold(data.clicks));
132
+ console.log(chalk.gray('Created:'), new Date(data.createdAt).toLocaleString());
133
+ if (options.qr) {
134
+ console.log('');
135
+ qrcode.generate(data.shortUrl, { small: true });
136
+ }
137
+ }
138
+ catch (error) {
139
+ spinner.fail('Failed to fetch link');
140
+ console.log(chalk.red('Error:'), error.response?.data?.error || error.message);
141
+ process.exit(1);
142
+ }
143
+ }
144
+ // Delete link
145
+ export async function deleteLink(id) {
146
+ const spinner = ora('Deleting link...').start();
147
+ try {
148
+ const api = getApiClient();
149
+ await api.delete(`/links/${id}`);
150
+ spinner.succeed('Link deleted successfully!');
151
+ }
152
+ catch (error) {
153
+ spinner.fail('Failed to delete link');
154
+ console.log(chalk.red('Error:'), error.response?.data?.error || error.message);
155
+ process.exit(1);
156
+ }
157
+ }
158
+ // Get stats (placeholder)
159
+ export async function stats(id) {
160
+ console.log(chalk.yellow('Analytics feature coming soon!'));
161
+ console.log(chalk.gray('Use the web dashboard at https://tinyurl.ca/dashboard for detailed analytics'));
162
+ }
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@tinyurl-ca/cli",
3
+ "version": "1.0.1",
4
+ "description": "Command-line tool for TinyURL.ca - create and manage short links from your terminal",
5
+ "type": "module",
6
+ "bin": {
7
+ "tinyurl": "./bin/cli.js"
8
+ },
9
+ "main": "dist/index.js",
10
+ "types": "dist/index.d.ts",
11
+ "scripts": {
12
+ "build": "tsc",
13
+ "prepublishOnly": "npm run build"
14
+ },
15
+ "keywords": [
16
+ "url-shortener",
17
+ "tinyurl",
18
+ "cli",
19
+ "short-links",
20
+ "tiny url canada"
21
+ ],
22
+ "author": "TinyURL.ca",
23
+ "license": "MIT",
24
+ "dependencies": {
25
+ "commander": "^11.1.0",
26
+ "axios": "^1.6.0",
27
+ "chalk": "^5.3.0",
28
+ "ora": "^8.0.1",
29
+ "conf": "^12.0.0",
30
+ "cli-table3": "^0.6.3",
31
+ "qrcode-terminal": "^0.12.0"
32
+ },
33
+ "devDependencies": {
34
+ "@types/node": "^20.10.0",
35
+ "typescript": "^5.3.0"
36
+ },
37
+ "repository": {
38
+ "type": "git",
39
+ "url": "git+https://github.com/raj-iwt/linksnap.git",
40
+ "directory": "cli"
41
+ },
42
+ "homepage": "https://tinyurl.ca/docs"
43
+ }