# KeyNexus JavaScript/TypeScript SDK

Official JavaScript/TypeScript SDK for KeyNexus License Management System.

Works in:
- ✅ Node.js (12+)
- ✅ Browsers (Modern browsers with fetch API)
- ✅ React
- ✅ Next.js
- ✅ Vue
- ✅ Angular
- ✅ Electron
- ✅ React Native (with polyfills)

## Installation

### From KeyNexus Server

```bash
# Download SDK
curl -o keynexus.tgz https://keynexus.es/sdks/javascript/
tar -xzf keynexus.tgz
cd keynexus

# Install dependencies and build
npm install
npm run build

# Use locally
npm link
```

### Direct Download and Use

```bash
# Download source files
wget -r -np -nH --cut-dirs=2 https://keynexus.es/sdks/javascript/

# In your project
npm install ./path-to-downloaded-sdk
```

### Alternative: Copy source directly

Download `src/index.ts` from https://keynexus.es/sdks/javascript/src/index.ts and include it in your project.

**Note:** To install via `npm install keynexus`, the package needs to be published to NPM registry first.

## Quick Start

### Node.js / TypeScript

```typescript
import KeyNexusClient from 'keynexus';

const client = new KeyNexusClient({
  appId: 'app_xxxxxxxxxxxx',
  secretKey: 'sk_xxxxxxxxxxxxxxxxxxxx'
});

// Validate license
const result = await client.validateLicense('XXXXX-XXXXX-XXXXX-XXXXX');

if (result.success) {
  console.log('✅ License valid!');
  console.log('Type:', result.license?.type);
  console.log('Expires:', result.license?.expiresAt);
}
```

### Browser / JavaScript

```html
<script type="module">
  import KeyNexusClient from 'https://cdn.jsdelivr.net/npm/keynexus@latest/dist/index.mjs';
  
  const client = new KeyNexusClient({
    appId: 'app_xxxxxxxxxxxx',
    secretKey: 'sk_xxxxxxxxxxxxxxxxxxxx'
  });
  
  const result = await client.validateLicense('XXXXX-XXXXX-XXXXX-XXXXX');
  console.log(result);
</script>
```

### React

```jsx
import { useState, useEffect } from 'react';
import KeyNexusClient from 'keynexus';

function App() {
  const [client] = useState(() => new KeyNexusClient({
    appId: 'app_xxxxxxxxxxxx',
    secretKey: 'sk_xxxxxxxxxxxxxxxxxxxx'
  }));

  const handleValidate = async (licenseKey) => {
    try {
      const result = await client.validateLicense(licenseKey);
      
      if (result.success) {
        alert('License valid!');
      }
    } catch (error) {
      alert(error.message);
    }
  };

  return (
    <div>
      <button onClick={() => handleValidate('XXXXX-XXXXX-XXXXX-XXXXX')}>
        Validate License
      </button>
    </div>
  );
}
```

## Features

- ✅ **TypeScript Support** - Full type definitions included
- ✅ **Automatic HWID Generation** - Browser fingerprinting & Node.js machine ID
- ✅ **License Validation** - Verify license keys with HWID binding
- ✅ **Authentication** - Username/password login
- ✅ **Session Management** - Get and manage active sessions
- ✅ **Error Handling** - Specific error types for different scenarios
- ✅ **Zero Dependencies** - Uses native fetch API
- ✅ **ESM & CJS** - Works with both module systems

## API Reference

### Constructor

```typescript
new KeyNexusClient(config: KeyNexusConfig)
```

**Config:**
- `appId` (string, required) - Your application ID from KeyNexus dashboard
- `secretKey` (string, required) - Your secret key
- `apiUrl` (string, optional) - API base URL (default: `https://keynexus.es/api`)
- `autoHwid` (boolean, optional) - Auto-generate HWID (default: `true`)

### Methods

#### `initialize(version?: string)`

Initialize the application and verify it's active.

```typescript
const result = await client.initialize('1.0.0');
console.log(result.success); // true
```

#### `validateLicense(licenseKey: string, hwid?: string)`

Validate a license key.

```typescript
try {
  const result = await client.validateLicense('XXXXX-XXXXX-XXXXX-XXXXX');
  
  console.log(result.license?.type); // "lifetime" | "time-based" | "subscription"
  console.log(result.license?.expiresAt); // Date or null
  console.log(result.license?.daysLeft); // Number or null
} catch (error) {
  if (error instanceof InvalidLicenseError) {
    console.log('Invalid license key');
  } else if (error instanceof HWIDMismatchError) {
    console.log('License locked to different device');
  } else if (error instanceof ExpiredLicenseError) {
    console.log('License has expired');
  }
}
```

#### `loginWithPassword(username: string, password: string, hwid?: string)`

Login with username and password.

```typescript
const result = await client.loginWithPassword('myusername', 'mypassword');

if (result.success) {
  console.log('Welcome', result.user?.username);
  console.log('Token:', result.token);
}
```

#### `getUserInfo(token?: string)`

Get information about the current user.

```typescript
const userInfo = await client.getUserInfo();

console.log(userInfo.user?.email);
console.log(userInfo.user?.subscriptionExpiry);
```

#### `logout()`

Logout the current session.

```typescript
await client.logout();
console.log('Logged out successfully');
```

#### `getSessions()`

Get all active sessions for the current user.

```typescript
const result = await client.getSessions();

result.sessions?.forEach(session => {
  console.log('Session:', session.id);
  console.log('IP:', session.ip);
  console.log('Location:', session.location?.city, session.location?.country);
});
```

#### `getHWID()`

Get the current hardware ID.

```typescript
const hwid = client.getHWID();
console.log('HWID:', hwid);
```

#### `setHWID(hwid: string)`

Set a custom hardware ID.

```typescript
client.setHWID('my-custom-hwid');
```

## Error Handling

The SDK provides specific error types:

```typescript
import { 
  KeyNexusError,
  InvalidLicenseError,
  HWIDMismatchError,
  ExpiredLicenseError 
} from 'keynexus';

try {
  await client.validateLicense(key);
} catch (error) {
  if (error instanceof InvalidLicenseError) {
    // License doesn't exist or is invalid
  } else if (error instanceof HWIDMismatchError) {
    // License is locked to another device
  } else if (error instanceof ExpiredLicenseError) {
    // License has expired
  } else if (error instanceof KeyNexusError) {
    // Generic KeyNexus error
  }
}
```

## Examples

### Check License Expiration

```typescript
const result = await client.validateLicense(licenseKey);

if (result.success && result.license) {
  if (result.license.type === 'lifetime') {
    console.log('✅ Lifetime license - never expires');
  } else if (result.license.daysLeft !== null) {
    if (result.license.daysLeft <= 0) {
      console.log('❌ License expired');
    } else if (result.license.daysLeft <= 7) {
      console.log(`⚠️  License expires in ${result.license.daysLeft} days`);
    } else {
      console.log(`✅ License valid for ${result.license.daysLeft} more days`);
    }
  }
}
```

### Store Session Token

```typescript
// After login
const result = await client.loginWithPassword(username, password);
if (result.token) {
  // Store in localStorage (browser)
  localStorage.setItem('keynexus_token', result.token);
  
  // Or store in secure storage (Node.js)
  // fs.writeFileSync('.token', result.token);
}

// Later, restore session
const savedToken = localStorage.getItem('keynexus_token');
if (savedToken) {
  client.setSessionToken(savedToken);
  
  // Verify it's still valid
  try {
    await client.getUserInfo();
  } catch {
    // Token expired, need to login again
    localStorage.removeItem('keynexus_token');
  }
}
```

### React Hook Example

```typescript
import { useState, useEffect } from 'react';
import KeyNexusClient from 'keynexus';

export function useKeyNexus() {
  const [client] = useState(() => new KeyNexusClient({
    appId: process.env.KEYNEXUS_APP_ID,
    secretKey: process.env.KEYNEXUS_SECRET_KEY
  }));
  
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(false);

  const validateLicense = async (key) => {
    setLoading(true);
    try {
      const result = await client.validateLicense(key);
      if (result.success) {
        const userInfo = await client.getUserInfo();
        setUser(userInfo.user);
      }
      return result;
    } finally {
      setLoading(false);
    }
  };

  const logout = async () => {
    await client.logout();
    setUser(null);
  };

  return { client, user, loading, validateLicense, logout };
}
```

## Browser Compatibility

- Chrome 42+
- Firefox 39+
- Safari 10.1+
- Edge 14+

For older browsers, you may need to polyfill the `fetch` API.

## Node.js Compatibility

- Node.js 12+

For better HWID generation in Node.js, the SDK will use the `os` and `crypto` modules if available.

## Documentation

Full documentation: https://keynexus.es/docs

## Support

- Email: support@keynexus.es
- Documentation: https://keynexus.es/docs
- GitHub Issues: https://github.com/keynexus/keynexus-js/issues

## License

MIT License - see LICENSE file for details
