Node.js SDK Reference

Node.js Integration

Enterprise-grade SDK for seamless freelancer matching and AI-powered interviews in Node.js applications

Installation

npm install sjm
1

Quick Setup

import { SJM } from 'sjm';

// Initialize client
const client = new SJM({
apiKey: process.env.SJM_API_KEY,
timeout: 30000 // Optional, in milliseconds
});
1
2
3
4
5
6
7

Core Methods

Health Check

Check the health status of the SJM API.

// Health check
const health = await client.health();

console.log(`API Status: ${health.status}`);
console.log(`Components: ${JSON.stringify(health.components)}`);
1
2
3
4
5

Freelancer Matching

Find freelancers that match your project requirements.

// Basic matching
const matches = await client.match({
description: "Build a React Native mobile app with Firebase backend",
required_skills: ["React Native", "JavaScript", "Firebase"]
});

console.log(`Found ${matches.matches.length} matching freelancers`);
1
2
3
4
5
6
7

Skill Verification

Verify if skills exist in the SJM database and find similar terms.

// Verify a skill
const result = await client.verifySkill("React.js");

if (result.data.exists) {
console.log(`✓ "React.js" is a recognized skill`);
console.log(`Exact matches: ${result.data.skills.join(', ')}`);
} else {
console.log(`✗ "React.js" is not recognized`);

if (result.data.similar_terms.length > 0) {
  console.log(`Did you mean: ${result.data.similar_terms.join(', ')}`);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13

AI-Powered Interviews

Conduct intelligent technical interviews with freelancers.

// Step 1: Generate interview questions
const interview = await client.interview({
freelancer_id: "f123",
project_description: "Build a React web application with Node.js backend",
required_skills: ["React.js", "Node.js", "Express.js", "MongoDB"],
job_title: "Full Stack Developer",
mode: "ai_questions"
});

// Store the session ID for later use
const sessionId = interview.data.session_id;

// Display generated questions
const questions = interview.data.interview_data.questions;
questions.forEach((q, i) => {
console.log(`Q${i+1}: ${q.text}`);

if (q.scoring_criteria) {
  console.log(`Scoring criteria: ${JSON.stringify(q.scoring_criteria)}`);
}
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

Test Data Generation

Generate test freelancer data for development and testing.

// Generate test data
const result = await client.generateTestData(10); // Generate 10 test freelancers

console.log(`Generated ${result.data.length} test freelancers`);

// Display sample freelancers
result.data.slice(0, 3).forEach((freelancer, i) => {
console.log(`\nFreelancer #${i+1}: ${freelancer.name}`);
console.log(`Job Title: ${freelancer.job_title}`);
console.log(`Skills: ${freelancer.skills.join(', ')}`);
console.log(`Experience: ${freelancer.experience} years`);
console.log(`Hourly Rate: $${freelancer.hourly_rate}/hr`);
});
1
2
3
4
5
6
7
8
9
10
11
12
13

Error Handling

SJM SDK provides detailed error information to help diagnose and resolve issues.

try {
const matches = await client.match({
  description: "React developer",
  required_skills: ["React.js"]
});

// Process matches...
} catch (error) {
if (error.message.includes('Authentication failed')) {
  console.error('API Key Error: Check your API key');
} else if (error.message.includes('Rate limit exceeded')) {
  console.error('Rate Limit Error: Too many requests');
  
  // Extract rate limit reset time if available
  const resetMatch = error.message.match(/Retry after (d+) seconds/);
  if (resetMatch) {
    const resetSeconds = parseInt(resetMatch[1]);
    console.log(`Rate limit resets in ${resetSeconds} seconds`);
  }
} else if (error.message.includes('Request error')) {
  console.error('Network Error: Check your connection');
} else {
  console.error(`API Error: ${error.message}`);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

TypeScript Support

The SJM SDK includes comprehensive TypeScript definitions for excellent type safety and editor support.

import { 
SJM, 
SJMConfig,
HealthResponse,
MatchParams,
MatchResponse,
MatchResult,
Freelancer,
VerifySkillResponse,
InterviewParams,
InterviewResponse,
InterviewQuestion,
InterviewEvaluation,
TestDataResponse
} from 'sjm';

// Client configuration
const config: SJMConfig = {
apiKey: string;
timeout?: number;
};

// Match parameters
const matchParams: MatchParams = {
description: string;
required_skills: string[];
budget_range?: [number, number];
complexity?: 'low' | 'medium' | 'high';
timeline?: number;
};

// Interview parameters
const interviewParams: InterviewParams = {
freelancer_id: string;
project_description: string;
required_skills: string[];
job_title: string;
mode?: 'ai_full' | 'ai_questions' | 'custom_full' | 'hybrid';
session_id?: string;
provided_answers?: string[];
custom_questions?: InterviewQuestion[];
scoring_criteria?: Record<string, number>;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

Complete Example

import { SJM } from 'sjm';
import * as readline from 'readline';
import * as dotenv from 'dotenv';

// Load environment variables from .env file
dotenv.config();

// Create readline interface for prompting
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});

// Promisify readline question
function ask(query) {
return new Promise(resolve => rl.question(query, resolve));
}

async function main() {
try {
  // Initialize client
  const client = new SJM({
    apiKey: process.env.SJM_API_KEY
  });
  
  // Check API health
  console.log('Checking API health...');
  const health = await client.health();
  console.log(`API Status: ${health.status}`);
  
  if (health.status !== 'healthy') {
    console.error('API is not healthy. Exiting.');
    return;
  }
  
  // Get project description
  const description = await ask('Enter project description: ');
  const skillsInput = await ask('Enter required skills (comma separated): ');
  const skills = skillsInput.split(',').map(s => s.trim());
  
  // Find matching freelancers
  console.log('\nFinding matching freelancers...');
  const matches = await client.match({
    description,
    required_skills: skills
  });
  
  console.log(`\nFound ${matches.matches.length} matching freelancers\n`);
  
  // Display top 3 matches
  matches.matches.slice(0, 3).forEach((match, i) => {
    const freelancer = match.freelancer;
    console.log(`Match #${i+1}: ${freelancer.name} (${freelancer.job_title})`);
    console.log(`Match Score: ${(match.score * 100).toFixed(1)}%`);
    console.log(`Skills: ${freelancer.skills.join(', ')}`);
    console.log(`Experience: ${freelancer.experience} years`);
    console.log(`Hourly Rate: $${freelancer.hourly_rate}/hr`);
    console.log('---');
  });
  
  // Ask if user wants to conduct an interview
  const wantInterview = await ask('\nDo you want to conduct an interview with the top match? (y/n): ');
  
  if (wantInterview.toLowerCase() === 'y') {
    const freelancer = matches.matches[0].freelancer;
    console.log(`\nSetting up interview with ${freelancer.name}...`);
    
    // Generate interview questions
    const interview = await client.interview({
      freelancer_id: freelancer.id,
      project_description: description,
      required_skills: skills,
      job_title: freelancer.job_title,
      mode: 'ai_questions'
    });
    
    console.log('\nInterview Questions:\n');
    const questions = interview.data.interview_data.questions;
    questions.forEach((q, i) => {
      console.log(`Q${i+1}: ${q.text}\n`);
    });
    
    console.log(`Save session ID for later evaluation: ${interview.data.session_id}`);
  }
  
} catch (error) {
  console.error(`Error: ${error.message}`);
} finally {
  rl.close();
}
}

main();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93

CLI Integration

The SJM package includes a CLI that you can use in your Node.js projects.

// Execute SJM CLI commands from your Node.js application
import { exec } from 'child_process';
import { promisify } from 'util';

const execPromise = promisify(exec);

async function runSJMCommand(command) {
try {
  const { stdout, stderr } = await execPromise(`sjm ${command}`);
  
  if (stderr) {
    console.error(`Command error: ${stderr}`);
    return null;
  }
  
  return stdout;
} catch (error) {
  console.error(`Execution error: ${error.message}`);
  return null;
}
}

// Run a match command
async function matchViaCLI() {
const result = await runSJMCommand(
  'match --description "React.js developer" --skills "React.js,TypeScript" --budget "3000-8000"'
);

console.log(result);
}

matchViaCLI();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

Advanced Features

Environment Configuration

Configure the SDK to work in different environments.

// Production environment
const productionClient = new SJM({
apiKey: process.env.SJM_PROD_API_KEY,
timeout: 30000
});

// Development environment with longer timeout
const developmentClient = new SJM({
apiKey: process.env.SJM_DEV_API_KEY,
timeout: 60000
});

// Create a client factory
function createSJMClient(environment = 'production') {
const config = {
  production: {
    apiKey: process.env.SJM_PROD_API_KEY,
    timeout: 30000
  },
};

return new SJM(config[environment] || config.production);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

Custom Request Configuration

Fine-tune request settings for specific use cases.

// Retry on failure with exponential backoff
async function retryMatch(client, params, maxRetries = 3) {
let retries = 0;
let lastError = null;

while (retries < maxRetries) {
  try {
    return await client.match(params);
  } catch (error) {
    lastError = error;
    
    if (error.message.includes('Rate limit exceeded')) {
      // Extract retry-after time if available
      const retryAfterMatch = error.message.match(/Retry after (d+) seconds/);
      const retryAfter = retryAfterMatch ? parseInt(retryAfterMatch[1]) * 1000 : 1000 * Math.pow(2, retries);
      
      console.log(`Rate limited. Retrying after ${retryAfter / 1000} seconds...`);
      await new Promise(resolve => setTimeout(resolve, retryAfter));
      retries++;
    } else {
      // For other errors, don't retry
      throw error;
    }
  }
}

throw lastError;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

Interactive Demo

SJM Node.js SDK Demo

Try out the SJM SDK with this interactive example

Code Editor

// Import SJM client
const { SJM } = require('sjm');

// Initialize client with demo key
const client = new SJM({
apiKey: 'demo_key'
});

// Define project requirements
const project = {
description: "Build a responsive e-commerce website with React frontend and Node.js backend",
required_skills: ["React.js", "Node.js", "MongoDB", "Express.js"],
budget_range: [8000, 15000],
complexity: "medium",
timeline: 45
};

// Find matching freelancers
async function findMatches() {
try {
  // Check API health
  const health = await client.health();
  console.log(`API Status: ${health.status}`);
  
  // Match freelancers to project
  const result = await client.match(project);
  console.log(`Found ${result.matches.length} matching freelancers`);
  
  // Display top 3 matches
  const topMatches = result.matches.slice(0, 3);
  for (const match of topMatches) {
    const freelancer = match.freelancer;
    console.log(`\nMatch: ${freelancer.name} (${freelancer.job_title})`);
    console.log(`Score: ${(match.score * 100).toFixed(1)}%`);
    console.log(`Skills: ${freelancer.skills.join(', ')}`);
    console.log(`Experience: ${freelancer.experience} years`);
    console.log(`Hourly Rate: $${freelancer.hourly_rate}/hr`);
  }
  
  // Return the number of matches found
  return { 
    matchCount: result.matches.length,
    topScore: result.matches[0]?.score * 100 || 0
  };
} catch (error) {
  console.error(`Error: ${error.message}`);
  return { error: error.message };
}
}

// Run the demo
findMatches();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

Output

Additional Resources