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
Quick Setup
import { SJM } from 'sjm';
// Initialize client
const client = new SJM({
apiKey: process.env.SJM_API_KEY,
timeout: 30000 // Optional, in milliseconds
});
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)}`);
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`);
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(', ')}`);
}
}
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)}`);
}
});
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`);
});
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}`);
}
}
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>;
};
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();
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();
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);
}
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;
}
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();