Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modernize codebase to take advantage of node.js 22(lts) #383

Open
12 of 29 tasks
billchurch opened this issue Dec 11, 2024 · 1 comment
Open
12 of 29 tasks

Modernize codebase to take advantage of node.js 22(lts) #383

billchurch opened this issue Dec 11, 2024 · 1 comment

Comments

@billchurch
Copy link
Owner

billchurch commented Dec 11, 2024

Overview

This issue outlines the plan to upgrade the WebSSH2 server from Node.js v6.9.1 to v22.12.0 LTS. This modernization will improve code quality, reduce dependencies, and leverage modern Node.js features.

Current State Analysis

Key Dependencies to Update

Code Patterns Needing Modernization

  1. Callback-based patterns in:

    • ssh.js: SSH connection handling
    • socket.js: Socket.IO event handling
    • middleware.js: Express middleware
    • File operations in multiple modules
  2. CommonJS require statements throughout:

    const SSH = require('ssh2').Client
    const EventEmitter = require('events')
  3. Older error handling patterns:

    // Current pattern in ssh.js
    this.conn.on('error', err => {
      if (this.authAttempts < DEFAULTS.MAX_AUTH_ATTEMPTS) {
        // ... callback handling
      }
    })

Modernization Tasks

Phase 1: Development Environment Setup

  • update .devcontainer environment to Node.js 22.12.0
  • Update Node.js version requirement in package.json
  • Add .nvmrc file with Node.js 22.12.0
  • use native node --watch and remove nodemon
  • Update ESLint configuration for modern JavaScript
  • Add TypeScript configuration
  • Convert imports to ES module syntax
  • Update test runner configuration
  • Add GitHub Actions for automated testing

Phase 2: Dependencies Update

  • Update webssh2_client socket.io to 4.7.4
  • Update core dependencies:
    {
      "dependencies": {
    -   "socket.io": "~2.2.0",
    +   "socket.io": "^4.7.4",
    -   "ssh2": "~0.8.9",
    +   "ssh2": "^1.15.0",
    -   "express": "^4.14.1",
    +   "express": "^4.18.2",
    -   "ajv": "^4.11.8",
    +   "ajv": "^8.12.0"
      }
    }
  • webssh2_client package socket.io-client module to 4.7.4 webssh2_client 8
  • Remove unnecessary dependencies:
    • Replace basic-auth with native HTTP authentication
    • Evaluate other dependencies for removal

Phase 3: Code Modernization

3.1 Module System

  • Convert to ESM:
    // Before
    const SSH = require('ssh2').Client
    module.exports = SSHConnection
    
    // After
    import { Client as SSH } from 'ssh2'
    export default SSHConnection
  • Update import paths
  • Add "type": "module" to package.json

3.2 Async/Await Implementation

  • Refactor SSH connection handling:

    // Before
    connect(creds) {
      return new Promise((resolve, reject) => {
        this.conn.on('ready', () => {
          resolve(this.conn)
        })
      })
    }
    
    // After
    async connect(creds) {
      try {
        await this.setupConnection(creds)
        return this.conn
      } catch (error) {
        throw new SSHConnectionError(`Connection failed: ${error.message}`)
      }
    }
  • Update socket event handlers:

    // Before
    handleAuthenticate(creds) {
      if (isValidCredentials(creds)) {
        this.initializeConnection(creds)
          .then(() => {
            // ... success handling
          })
          .catch(err => {
            // ... error handling
          })
      }
    }
    
    // After
    async handleAuthenticate(creds) {
      try {
        if (!isValidCredentials(creds)) {
          throw new Error('Invalid credentials format')
        }
        await this.initializeConnection(creds)
        // ... success handling
      } catch (error) {
        // ... error handling
      }
    }

3.3 Native API Usage

  • Replace custom file operations with fs/promises:
    // Before
    fs.readFile(filePath, 'utf8', (err, data) => {
      if (err) return res.status(500).send('Error')
      res.send(modifyHtml(data, config))
    })
    
    // After
    import { readFile } from 'node:fs/promises'
    
    try {
      const data = await readFile(filePath, 'utf8')
      res.send(modifyHtml(data, config))
    } catch (error) {
      res.status(500).send('Error')
    }

3.4 Testing Updates

  • Migrate to Node.js test runner:
    // Before (Jest)
    describe('SSHConnection', () => {
      it('should connect successfully', async () => {
        expect(await sshConnection.connect(creds)).toBeDefined()
      })
    })
    
    // After (node:test)
    import test from 'node:test'
    import assert from 'node:assert/strict'
    
    test('SSHConnection', async (t) => {
      await t.test('should connect successfully', async () => {
        const connection = await sshConnection.connect(creds)
        assert.ok(connection)
      })
    })

Phase 4: Security Enhancements

  • Implement proper HTTP/2 support
  • Add native crypto module usage
  • Update security headers
  • Implement rate limiting
  • Add input validation using modern patterns

Phase 5: Documentation and Type Safety

  • Add JSDoc comments with TypeScript types
  • Update API documentation
  • Document new features and patterns
  • Add migration guide for users

Breaking Changes

  • Node.js version requirement: 22.12.0 LTS
  • Module system: ESM only
  • Updated Socket.IO client requirements (webssh2_client)
  • New error handling patterns
  • Changed configuration format

Migration Strategy

  1. Create a new branch for modernization
  2. Implement changes in phases
  3. Maintain parallel support during transition
  4. Add comprehensive tests
  5. Document migration path for users
  6. Release as major version update

Additional Considerations

  • Consider adding TypeScript support
  • Evaluate WebAssembly for performance-critical parts
  • Consider adding Docker multi-stage builds
  • Evaluate GraphQL for API modernization

Resources

Timeline Estimate

  • Phase 1: 1 week
  • Phase 2: 2 weeks
  • Phase 3: 4 weeks
  • Phase 4: 2 weeks
  • Phase 5: 1 week

Total estimated time: 10 weeks

Please comment on this issue if you have questions or suggestions for the modernization plan.

@shirshak55
Copy link

will there be library version of it, so i can just create node server and import library?

Lastly, will there be easy way to import in React JS?

Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants