nport 2.0.7 โ†’ 2.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/CHANGELOG.md CHANGED
@@ -5,6 +5,120 @@ All notable changes to NPort will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [2.1.0] - 2026-01-27
9
+
10
+ ### Added
11
+ - ๐Ÿ”ท **Full TypeScript Migration**: Complete rewrite of CLI and Server in TypeScript
12
+ - Strict type checking enabled across the entire codebase
13
+ - All modules converted from JavaScript to TypeScript
14
+ - Type-safe interfaces for configuration, tunnels, analytics, and i18n
15
+ - Better IDE support with IntelliSense and autocompletion
16
+ - ๐Ÿ“š **Comprehensive Documentation**: New docs folder with detailed guides
17
+ - `docs/ARCHITECTURE.md`: System overview, component diagrams, and data flow
18
+ - `docs/API.md`: Complete API reference with endpoints and examples
19
+ - `docs/CONTRIBUTING.md`: Contribution guidelines and development setup
20
+ - ๐Ÿค– **AI Context Support**: Added `.ai/context.md` for AI-assisted development
21
+ - Project structure and key patterns documented
22
+ - Coding conventions and architecture decisions
23
+ - Makes AI pair programming more effective
24
+ - ๐Ÿงช **Unit Testing with Vitest**: Comprehensive test suite for CLI
25
+ - Tests for argument parsing (`tests/args.test.ts`)
26
+ - Tests for version comparison (`tests/version.test.ts`)
27
+ - Tests for state management (`tests/state.test.ts`)
28
+ - Easy to run with `npm test`
29
+ - ๐Ÿ“‹ **Code Ownership**: Added `.github/CODEOWNERS` file
30
+ - Clear ownership for code review assignments
31
+ - Faster PR reviews with automatic reviewer assignment
32
+ - ๐Ÿ“ **Cursor Rules**: Added `.cursorrules` for consistent AI assistance
33
+ - Project-specific coding conventions
34
+ - TypeScript and naming guidelines
35
+ - Common patterns and anti-patterns
36
+ - ๐Ÿ”„ **Auto-download Cloudflared**: Binary downloads automatically on first run
37
+ - No need to run separate install commands
38
+ - Seamless first-time user experience
39
+ - Progress indicator during download
40
+ - ๐Ÿ”’ **Protected Subdomain Support**: Enhanced error handling for reserved subdomains
41
+ - User-friendly error message when trying to create protected subdomains (like `api`)
42
+ - Formatted error output matching existing error style
43
+ - Helpful suggestions to use alternative subdomain names
44
+ - Prevents accidental use of backend service subdomains
45
+ - ๐Ÿ“‹ **TODO Management**: Added `TODO.md` for tracking planned features
46
+ - Move time limit enforcement to backend
47
+ - Update README powered-by section
48
+ - Track terminal link clicks
49
+
50
+ ### Changed
51
+ - ๐Ÿ—๏ธ **Project Structure**: Reorganized for better maintainability
52
+ - All source code in `src/` directory
53
+ - Type definitions in `src/types/`
54
+ - Shared constants in `src/constants.ts`
55
+ - Tests in `tests/` directory
56
+ - ๐Ÿ“ฆ **Build System**: Updated to TypeScript compilation
57
+ - Uses `tsc` for compilation
58
+ - Output to `dist/` directory
59
+ - Source maps for debugging
60
+ - ๐Ÿ”ง **Development Workflow**: Improved developer experience
61
+ - `npm run dev` for watch mode
62
+ - `npm run build` for production
63
+ - `npm test` for running tests
64
+ - `npm run lint` for type checking
65
+ - โš™๏ธ **System Requirements**: Updated to Node.js 20+
66
+ - Minimum Node.js version: 20.0.0
67
+ - Minimum npm version: 10.0.0
68
+ - Better security and performance with latest LTS
69
+
70
+ ### Improved
71
+ - โœจ **Better Error Messages**: Enhanced user feedback for protected subdomains
72
+ - Catches `SUBDOMAIN_PROTECTED` errors from backend
73
+ - Formats error messages consistently with other error types
74
+ - Shows actionable options when subdomain is reserved
75
+
76
+ ### Fixed
77
+ - ๐Ÿ› **Intel Mac Binary Download**: Fixed cloudflared binary download on Intel Macs
78
+ - Node.js reports architecture as `x64`, not `amd64` - now correctly mapped
79
+ - Fixed ARM64 Macs to download the correct `cloudflared-darwin-arm64.tgz` binary
80
+ - Previously ARM64 Macs were incorrectly downloading the AMD64 binary
81
+
82
+ ### Server (v1.1.0)
83
+ - ๐Ÿ”ท **TypeScript Migration**: Server fully converted to TypeScript
84
+ - Type-safe Cloudflare Worker handlers
85
+ - Properly typed API responses
86
+ - Full type coverage for Cloudflare API interactions
87
+ - ๐Ÿงช **Server Tests**: Updated test suite for TypeScript
88
+ - Vitest with Cloudflare Workers pool
89
+ - Tests for all API endpoints
90
+ - Scheduled task testing
91
+ - ๐Ÿ”’ **Protected Subdomains**: Infrastructure to protect critical subdomains from deletion or overwriting
92
+ - New `PROTECTED_SUBDOMAINS` constant array for easy management of reserved subdomains
93
+ - Default protected subdomain: `api` (reserved for NPort backend service)
94
+ - Easy to add more protected subdomains by updating the array
95
+ - Protected subdomains are blocked at both creation and cleanup stages
96
+ - ๐Ÿ›ก๏ธ **Backend Service Protection**: Prevents accidental deletion or overwriting of production services
97
+ - `api` subdomain is now protected from user creation attempts
98
+ - Scheduled cleanup job skips protected subdomains
99
+ - Returns clear error message when users try to use protected names
100
+ - ๐Ÿ”ง **Manual Cleanup Endpoint**: Added `GET /scheduled` endpoint to manually trigger cleanup
101
+ - Useful for testing and on-demand cleanup
102
+ - Respects protected subdomains configuration
103
+ - Returns JSON response with cleanup results
104
+
105
+ ### Technical Details
106
+ - **Type System**:
107
+ - `TunnelConfig`, `TunnelState`, `ConnectionInfo` interfaces
108
+ - `AnalyticsParams`, `VersionInfo`, `I18nStrings` types
109
+ - `LogPatterns` with readonly arrays for constants
110
+ - **ESM Compliance**: All imports use `.js` extensions as required
111
+ - **Constants**: Centralized in `src/constants.ts` with `as const` assertions
112
+ - **Error Handling**: Type-safe error boundaries throughout
113
+
114
+ ### Migration
115
+ - Automatic migration - no manual steps required
116
+ - Existing configuration in `~/.nport/config.json` remains compatible
117
+ - All CLI flags and options unchanged
118
+
119
+ ### Breaking Changes
120
+ - None - fully backward compatible!
121
+
8
122
  ## [2.0.7] - 2026-01-14
9
123
 
10
124
  ### Added
@@ -186,6 +300,48 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
186
300
 
187
301
  ## Version Upgrade Guide
188
302
 
303
+ ### From 2.0.7 to 2.1.0
304
+
305
+ ```bash
306
+ npm install -g nport@latest
307
+ ```
308
+
309
+ **What's New:**
310
+
311
+ 1. **Full TypeScript Rewrite**
312
+ - Both CLI and Server now fully typed
313
+ - Better IDE support and autocompletion
314
+ - Catches errors at compile time
315
+
316
+ 2. **Comprehensive Documentation**
317
+ - Architecture guide in `docs/ARCHITECTURE.md`
318
+ - API reference in `docs/API.md`
319
+ - Contributing guide in `docs/CONTRIBUTING.md`
320
+
321
+ 3. **Unit Testing**
322
+ - Run tests with `npm test`
323
+ - Covers argument parsing, version checks, state management
324
+
325
+ 4. **Auto-download Cloudflared**
326
+ - Binary downloads automatically on first `nport` run
327
+ - No separate install step needed
328
+
329
+ 5. **AI-Friendly Codebase**
330
+ - `.ai/context.md` for AI assistants
331
+ - `.cursorrules` for consistent AI suggestions
332
+ - JSDoc comments throughout
333
+
334
+ **For Contributors:**
335
+ ```bash
336
+ git clone https://github.com/tuanngocptn/nport
337
+ cd nport
338
+ npm install
339
+ npm run build
340
+ npm run dev # Watch mode
341
+ ```
342
+
343
+ **Breaking Changes:** None - fully backward compatible!
344
+
189
345
  ### From 2.0.6 to 2.0.7
190
346
 
191
347
  ```bash
package/README.md CHANGED
@@ -6,6 +6,7 @@
6
6
  [![NPM](https://img.shields.io/npm/v/nport?color=red&logo=npm)](https://www.npmjs.com/package/nport)
7
7
  [![Website](https://img.shields.io/website?url=https%3A%2F%2Fnport.link&up_message=nport.link&up_color=blue&down_color=lightgrey&down_message=offline)](https://nport.link)
8
8
  [![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
9
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.7-blue.svg)](https://www.typescriptlang.org/)
9
10
 
10
11
  ## What is NPort?
11
12
 
@@ -269,25 +270,30 @@ Internet โ†’ Cloudflare Edge โ†’ Cloudflare Tunnel โ†’ Your localhost:3000
269
270
 
270
271
  ## ๐Ÿ—๏ธ Project Structure
271
272
 
272
- NPort uses a modular architecture for better maintainability:
273
-
274
273
  ```
275
274
  nport/
276
- โ”œโ”€โ”€ index.js # Main entry point
277
- โ”œโ”€โ”€ src/
278
- โ”‚ โ”œโ”€โ”€ analytics.js # Analytics tracking
279
- โ”‚ โ”œโ”€โ”€ api.js # Backend API client
280
- โ”‚ โ”œโ”€โ”€ args.js # CLI argument parser
281
- โ”‚ โ”œโ”€โ”€ binary.js # Cloudflared binary manager
282
- โ”‚ โ”œโ”€โ”€ bin-manager.js # Binary download/installation
283
- โ”‚ โ”œโ”€โ”€ config.js # Configuration constants
284
- โ”‚ โ”œโ”€โ”€ lang.js # Multilingual support
285
- โ”‚ โ”œโ”€โ”€ state.js # Application state
286
- โ”‚ โ”œโ”€โ”€ tunnel.js # Tunnel orchestration
287
- โ”‚ โ”œโ”€โ”€ ui.js # User interface display
288
- โ”‚ โ””โ”€โ”€ version.js # Version management
289
- โ””โ”€โ”€ bin/
290
- โ””โ”€โ”€ cloudflared # Cloudflare tunnel binary
275
+ โ”œโ”€โ”€ src/ # TypeScript source files
276
+ โ”‚ โ”œโ”€โ”€ index.ts # Entry point
277
+ โ”‚ โ”œโ”€โ”€ tunnel.ts # Tunnel orchestration
278
+ โ”‚ โ”œโ”€โ”€ api.ts # Backend API client
279
+ โ”‚ โ”œโ”€โ”€ args.ts # CLI argument parser
280
+ โ”‚ โ”œโ”€โ”€ binary.ts # Cloudflared process manager
281
+ โ”‚ โ”œโ”€โ”€ ui.ts # Console UI components
282
+ โ”‚ โ”œโ”€โ”€ lang.ts # Multilingual support
283
+ โ”‚ โ”œโ”€โ”€ types/ # TypeScript type definitions
284
+ โ”‚ โ””โ”€โ”€ ...
285
+ โ”‚
286
+ โ”œโ”€โ”€ tests/ # Unit tests (vitest)
287
+ โ”œโ”€โ”€ dist/ # Compiled output
288
+ โ”œโ”€โ”€ bin/ # cloudflared binary (downloaded)
289
+ โ”‚
290
+ โ”œโ”€โ”€ server/ # Backend (Cloudflare Worker)
291
+ โ”œโ”€โ”€ website/ # Static landing page
292
+ โ”œโ”€โ”€ docs/ # Documentation
293
+ โ”‚ โ”œโ”€โ”€ ARCHITECTURE.md # Technical architecture
294
+ โ”‚ โ”œโ”€โ”€ API.md # API reference
295
+ โ”‚ โ””โ”€โ”€ CONTRIBUTING.md # Contribution guide
296
+ โ””โ”€โ”€ .ai/ # AI context files
291
297
  ```
292
298
 
293
299
  ## ๐Ÿ›ก๏ธ Security
@@ -370,7 +376,7 @@ Then select your preferred language from the menu.
370
376
  - ๐Ÿ‡บ๐Ÿ‡ธ **English** (`en`) - Default
371
377
  - ๐Ÿ‡ป๐Ÿ‡ณ **Vietnamese** (`vi`) - Tiแบฟng Viแป‡t
372
378
 
373
- Want to add your language? Contributions are welcome! Check out `src/lang.js` to see how easy it is to add translations.
379
+ Want to add your language? Contributions are welcome! Check out the [Contributing Guide](docs/CONTRIBUTING.md).
374
380
 
375
381
  ## ๐Ÿค Contributing
376
382
 
@@ -382,22 +388,26 @@ Contributions are welcome! Please feel free to submit a Pull Request.
382
388
  4. Push to the branch (`git push origin feature/amazing-feature`)
383
389
  5. Open a Pull Request
384
390
 
385
- ### Adding a New Language
391
+ See [docs/CONTRIBUTING.md](docs/CONTRIBUTING.md) for detailed guidelines.
392
+
393
+ ### Development Setup
394
+
395
+ ```bash
396
+ # Clone the repository
397
+ git clone https://github.com/tuanngocptn/nport.git
398
+ cd nport
399
+
400
+ # Install dependencies
401
+ npm install
386
402
 
387
- To add a new language:
403
+ # Build TypeScript
404
+ npm run build
388
405
 
389
- 1. Open `src/lang.js`
390
- 2. Add your language code to `availableLanguages` array
391
- 3. Add translations to the `TRANSLATIONS` object
392
- 4. Submit a PR!
406
+ # Run tests
407
+ npm test
393
408
 
394
- Example:
395
- ```javascript
396
- const TRANSLATIONS = {
397
- en: { /* English translations */ },
398
- vi: { /* Vietnamese translations */ },
399
- es: { /* Your Spanish translations */ },
400
- };
409
+ # Run CLI locally
410
+ node dist/index.js 3000 -s test
401
411
  ```
402
412
 
403
413
  ## ๐Ÿ’– Support
@@ -408,7 +418,7 @@ If you find NPort useful, please consider supporting the project:
408
418
  - โ˜• [Buy me a coffee](https://buymeacoffee.com/tuanngocptn)
409
419
  - ๐Ÿ’ฌ Share with your friends and colleagues
410
420
  - ๐Ÿ› [Report bugs](https://github.com/tuanngocptn/nport/issues)
411
- - ๐ŸŒ [Add translations](https://github.com/tuanngocptn/nport/blob/main/src/lang.js)
421
+ - ๐ŸŒ [Add translations](docs/CONTRIBUTING.md#adding-translations)
412
422
 
413
423
  ## ๐Ÿ“„ License
414
424
 
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "nport",
3
- "version": "2.0.7",
3
+ "version": "2.1.0",
4
4
  "description": "Free & open source ngrok alternative - Tunnel HTTP/HTTPS connections via Cloudflare Edge with custom subdomains",
5
5
  "type": "module",
6
- "main": "index.js",
6
+ "main": "dist/index.js",
7
7
  "bin": {
8
- "nport": "index.js"
8
+ "nport": "dist/index.js"
9
9
  },
10
10
  "engines": {
11
11
  "node": ">=20.0.0",
@@ -63,17 +63,28 @@
63
63
  }
64
64
  ],
65
65
  "scripts": {
66
- "postinstall": "node src/bin-manager.js",
67
- "start": "node index.js"
66
+ "build": "tsc",
67
+ "dev": "tsc --watch",
68
+ "start": "node dist/index.js",
69
+ "postinstall": "node scripts/postinstall.js",
70
+ "test": "vitest run",
71
+ "test:watch": "vitest",
72
+ "lint": "tsc --noEmit"
68
73
  },
69
74
  "dependencies": {
70
75
  "axios": "^1.13.2",
71
76
  "chalk": "^5.6.2",
72
77
  "ora": "^9.0.0"
73
78
  },
79
+ "devDependencies": {
80
+ "@types/node": "^22.0.0",
81
+ "typescript": "^5.7.0",
82
+ "vitest": "~3.2.0"
83
+ },
74
84
  "files": [
75
- "index.js",
76
- "src/",
85
+ "dist/",
86
+ "bin/",
87
+ "scripts/",
77
88
  "README.md",
78
89
  "CHANGELOG.md",
79
90
  "LICENSE"
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Post-install script
5
+ *
6
+ * Runs bin-manager to download cloudflared binary if dist/ exists.
7
+ * Silently skips if dist/ doesn't exist (e.g., during development before build).
8
+ */
9
+
10
+ import { existsSync } from 'fs';
11
+ import { fileURLToPath } from 'url';
12
+ import { dirname, join } from 'path';
13
+
14
+ const __dirname = dirname(fileURLToPath(import.meta.url));
15
+ const binManagerPath = join(__dirname, '..', 'dist', 'bin-manager.js');
16
+
17
+ if (existsSync(binManagerPath)) {
18
+ // Dynamic import to run the bin-manager
19
+ import(binManagerPath).catch(() => {
20
+ // Silently fail if import fails
21
+ });
22
+ } else {
23
+ // For development: dist/ doesn't exist yet, skip silently
24
+ console.log('โ„น๏ธ Skipping binary download (run "npm run build" first for development)');
25
+ }
package/index.js DELETED
@@ -1,110 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- import ora from "ora";
4
- import chalk from "chalk";
5
- import { ArgumentParser } from "./src/args.js";
6
- import { TunnelOrchestrator } from "./src/tunnel.js";
7
- import { VersionManager } from "./src/version.js";
8
- import { UI } from "./src/ui.js";
9
- import { CONFIG } from "./src/config.js";
10
- import { lang } from "./src/lang.js";
11
- import { configManager } from "./src/config-manager.js";
12
-
13
- /**
14
- * NPort - Free & Open Source ngrok Alternative
15
- *
16
- * Main entry point for the NPort CLI application.
17
- * Handles command-line arguments and orchestrates tunnel creation.
18
- */
19
-
20
- /**
21
- * Display version information with update check
22
- */
23
- async function displayVersion() {
24
- const spinner = ora(lang.t("checkingUpdates")).start();
25
- const updateInfo = await VersionManager.checkForUpdates();
26
- spinner.stop();
27
-
28
- UI.displayVersion(CONFIG.CURRENT_VERSION, updateInfo);
29
- }
30
-
31
- /**
32
- * Handle --set-backend command
33
- */
34
- function handleSetBackend(value) {
35
- if (value === 'clear') {
36
- // Clear saved backend URL
37
- configManager.setBackendUrl(null);
38
- console.log(chalk.green('โœ” Backend URL cleared. Using default backend.'));
39
- console.log(chalk.gray(' Default: https://api.nport.link\n'));
40
- } else {
41
- // Save new backend URL
42
- configManager.setBackendUrl(value);
43
- console.log(chalk.green('โœ” Backend URL saved successfully!'));
44
- console.log(chalk.cyan(` Backend: ${value}`));
45
- console.log(chalk.gray('\n This backend will be used for all future sessions.'));
46
- console.log(chalk.gray(' To clear: nport --set-backend\n'));
47
- }
48
-
49
- // Show current configuration
50
- const savedUrl = configManager.getBackendUrl();
51
- if (savedUrl) {
52
- console.log(chalk.white('Current configuration:'));
53
- console.log(chalk.cyan(` Saved backend: ${savedUrl}`));
54
- }
55
- }
56
-
57
- /**
58
- * Main application entry point
59
- */
60
- async function main() {
61
- try {
62
- const args = process.argv.slice(2);
63
-
64
- // Parse arguments
65
- const config = ArgumentParser.parse(args);
66
-
67
- // Initialize language first (may prompt user)
68
- await lang.initialize(config.language);
69
-
70
- // Check for version flag (after language is set)
71
- if (args.includes('-v') || args.includes('--version')) {
72
- await displayVersion();
73
- process.exit(0);
74
- }
75
-
76
- // Handle --set-backend command
77
- if (config.setBackend) {
78
- handleSetBackend(config.setBackend);
79
- process.exit(0);
80
- }
81
-
82
- // If only --language flag was used, show success message and exit
83
- if (config.language === 'prompt' &&
84
- (args.includes('--language') || args.includes('--lang') || args.includes('-l'))) {
85
- // Language was already selected in initialize(), just exit
86
- process.exit(0);
87
- }
88
-
89
- // Load saved backend URL if no CLI backend specified
90
- if (!config.backendUrl) {
91
- const savedBackend = configManager.getBackendUrl();
92
- if (savedBackend) {
93
- config.backendUrl = savedBackend;
94
- }
95
- }
96
-
97
- // Start tunnel
98
- await TunnelOrchestrator.start(config);
99
- } catch (error) {
100
- console.error(`Fatal Error: ${error.message}`);
101
- process.exit(1);
102
- }
103
- }
104
-
105
- // Register cleanup handlers for graceful shutdown
106
- process.on("SIGINT", () => TunnelOrchestrator.cleanup());
107
- process.on("SIGTERM", () => TunnelOrchestrator.cleanup());
108
-
109
- // Start application
110
- main();