Skip to content

Spyxpo/node.js_scs

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

SCS Node.js SDK

Official Node.js SDK for SCS (Spyxpo Cloud Services) - a comprehensive Backend-as-a-Service platform.

Installation

npm install @spyxpo/scs

This package includes both the SDK and the CLI tool.

Quick Start

Initialize from config file

const SCS = require('@spyxpo/scs');

// Initialize from scs-info.json
const scs = SCS.initializeApp('./scs-info.json');

Initialize with config object

const SCS = require('@spyxpo/scs');

const scs = new SCS({
  apiKey: 'your-api-key',
  projectId: 'your-project-id',
  baseUrl: 'https://your-scs-instance.com'
});

Services

Authentication

// Register a new user
const { token, user } = await scs.auth.register({
  email: '[email protected]',
  password: 'securepassword',
  displayName: 'John Doe',
  customData: { role: 'admin' }
});

// Login
const { token, user } = await scs.auth.login({
  email: '[email protected]',
  password: 'securepassword'
});

// Get current user
const user = await scs.auth.getCurrentUser();

// Update profile
await scs.auth.updateProfile({
  displayName: 'Jane Doe',
  customData: { preferences: { theme: 'dark' } }
});

// Change password
await scs.auth.changePassword({
  currentPassword: 'oldpassword',
  newPassword: 'newpassword'
});

// Logout
scs.auth.logout();

// Admin: List users
const { users, total } = await scs.auth.listUsers({ limit: 10 });

// Admin: Disable/Enable user
await scs.auth.disableUser('user-id');
await scs.auth.enableUser('user-id');

OAuth and Social Sign-In

SCS supports multiple OAuth providers for seamless social authentication. Each provider follows a similar pattern but requires different credentials obtained from their respective SDKs.

Google Sign-In

Authenticate users with their Google account. Requires the Google Sign-In SDK on the client.

// Sign in with Google
const { token, user } = await scs.auth.signInWithGoogle({
  idToken: 'google-id-token',      // Required: ID token from Google Sign-In
  accessToken: 'google-access-token' // Optional: Access token for additional scopes
});

console.log('User ID:', user.uid);
console.log('Email:', user.email);
console.log('Display Name:', user.displayName);
console.log('Photo URL:', user.photoURL);
console.log('Provider:', user.providerId); // 'google'

Parameters:

Parameter Type Required Description
idToken string Yes The ID token obtained from Google Sign-In SDK
accessToken string No Access token for additional Google API scopes

Returns: { token: string, user: User }

Example with Google Sign-In Web SDK:

// Client-side: Get tokens from Google
const auth2 = gapi.auth2.getAuthInstance();
const googleUser = await auth2.signIn();
const idToken = googleUser.getAuthResponse().id_token;
const accessToken = googleUser.getAuthResponse().access_token;

// Sign in to SCS
const { token, user } = await scs.auth.signInWithGoogle({ idToken, accessToken });
Facebook Sign-In

Authenticate users with their Facebook account. Requires the Facebook SDK.

// Sign in with Facebook
const { token, user } = await scs.auth.signInWithFacebook({
  accessToken: 'facebook-access-token' // Required: Access token from Facebook Login
});

console.log('User:', user.displayName);
console.log('Email:', user.email); // May be null if user didn't grant email permission

Parameters:

Parameter Type Required Description
accessToken string Yes Access token from Facebook Login SDK

Example with Facebook SDK:

// Client-side: Login with Facebook
FB.login(async (response) => {
  if (response.authResponse) {
    const accessToken = response.authResponse.accessToken;

    // Sign in to SCS
    const { token, user } = await scs.auth.signInWithFacebook({ accessToken });
    console.log('Signed in as:', user.displayName);
  }
}, { scope: 'email,public_profile' });
Apple Sign-In

Authenticate users with their Apple ID. Ideal for iOS apps and required for apps with social login on the App Store.

// Sign in with Apple
const { token, user } = await scs.auth.signInWithApple({
  identityToken: 'apple-identity-token',     // Required: Identity token from Sign in with Apple
  authorizationCode: 'apple-auth-code',      // Optional: Authorization code for server verification
  fullName: 'John Doe'                        // Optional: User's name (only available on first sign-in)
});

Parameters:

Parameter Type Required Description
identityToken string Yes JWT identity token from Sign in with Apple
authorizationCode string No Authorization code for additional verification
fullName string No User's full name (Apple only provides this on first sign-in)

Important Notes:

  • Apple only provides the user's name on the first sign-in. Store it immediately.
  • Users can choose to hide their email (Apple provides a relay email).
  • Required for apps using social login on iOS/macOS.

Example with Apple JS SDK:

// Client-side: Configure and sign in
AppleID.auth.init({
  clientId: 'com.yourapp.client',
  scope: 'name email',
  redirectURI: 'https://yourapp.com/callback',
  usePopup: true
});

const response = await AppleID.auth.signIn();
const { token, user } = await scs.auth.signInWithApple({
  identityToken: response.authorization.id_token,
  authorizationCode: response.authorization.code,
  fullName: response.user ? `${response.user.name.firstName} ${response.user.name.lastName}` : null
});
GitHub Sign-In

Authenticate users with their GitHub account. Popular for developer-focused applications.

// Sign in with GitHub
const { token, user } = await scs.auth.signInWithGitHub({
  code: 'github-oauth-code',                    // Required: OAuth authorization code
  redirectUri: 'https://yourapp.com/callback'   // Optional: Must match OAuth app settings
});

console.log('GitHub username:', user.displayName);
console.log('Email:', user.email);

Parameters:

Parameter Type Required Description
code string Yes OAuth authorization code from GitHub OAuth flow
redirectUri string No Redirect URI (must match your GitHub OAuth App settings)

OAuth Flow Example:

// Step 1: Redirect user to GitHub authorization
const clientId = 'your-github-client-id';
const redirectUri = 'https://yourapp.com/auth/github/callback';
const scope = 'read:user user:email';
const authUrl = `https://github.com/login/oauth/authorize?client_id=${clientId}&redirect_uri=${redirectUri}&scope=${scope}`;
window.location.href = authUrl;

// Step 2: Handle callback (on your callback page)
const urlParams = new URLSearchParams(window.location.search);
const code = urlParams.get('code');

if (code) {
  const { token, user } = await scs.auth.signInWithGitHub({ code, redirectUri });
  console.log('Signed in:', user.displayName);
}
Twitter/X Sign-In

Authenticate users with their Twitter/X account using OAuth 1.0a.

// Sign in with Twitter/X
const { token, user } = await scs.auth.signInWithTwitter({
  oauthToken: 'twitter-oauth-token',           // Required: OAuth token
  oauthTokenSecret: 'twitter-oauth-secret'     // Required: OAuth token secret
});

Parameters:

Parameter Type Required Description
oauthToken string Yes OAuth token from Twitter authentication
oauthTokenSecret string Yes OAuth token secret from Twitter authentication

Note: Twitter uses OAuth 1.0a which requires a more complex flow. Consider using a library like passport-twitter or Twitter's official SDK.

Microsoft Sign-In

Authenticate users with their Microsoft account (personal, work, or school accounts).

// Sign in with Microsoft
const { token, user } = await scs.auth.signInWithMicrosoft({
  accessToken: 'microsoft-access-token',  // Required: Access token from MSAL
  idToken: 'microsoft-id-token'           // Optional: ID token for additional claims
});

Parameters:

Parameter Type Required Description
accessToken string Yes Access token from Microsoft Authentication Library (MSAL)
idToken string No ID token for additional user claims

Example with MSAL.js:

import { PublicClientApplication } from '@azure/msal-browser';

const msalConfig = {
  auth: {
    clientId: 'your-client-id',
    authority: 'https://login.microsoftonline.com/common',
    redirectUri: 'https://yourapp.com'
  }
};

const msalInstance = new PublicClientApplication(msalConfig);
await msalInstance.initialize();

// Login
const loginResponse = await msalInstance.loginPopup({
  scopes: ['openid', 'profile', 'email']
});

// Sign in to SCS
const { token, user } = await scs.auth.signInWithMicrosoft({
  accessToken: loginResponse.accessToken,
  idToken: loginResponse.idToken
});

Anonymous Authentication

Allow users to use your app without creating an account. Anonymous accounts can later be upgraded to permanent accounts by linking a provider.

// Sign in anonymously (creates a temporary account)
const { token, user } = await scs.auth.signInAnonymously({
  customData: { referrer: 'landing-page', campaign: 'summer-sale' } // optional
});

console.log('Anonymous user ID:', user.uid);
console.log('Is anonymous:', user.isAnonymous); // true

Parameters:

Parameter Type Required Description
customData object No Custom data to store with the anonymous user for analytics

Use Cases:

  • Allow users to try your app before signing up
  • Guest checkout in e-commerce
  • Save user progress/preferences before account creation
  • A/B testing with user tracking

Converting Anonymous to Permanent Account:

// User decides to create a permanent account
// Link their anonymous account to a provider
try {
  await scs.auth.linkProvider('google', {
    idToken: 'google-id-token'
  });

  console.log('Account upgraded! User data preserved.');
  console.log('Is anonymous:', user.isAnonymous); // false
} catch (error) {
  if (error.code === 'auth/credential-already-in-use') {
    // This Google account is already linked to another user
    console.log('This account is already registered. Please sign in instead.');
  }
}

Phone Number Authentication

Two-step authentication flow using SMS verification codes.

// Step 1: Send verification code to phone
const { verificationId } = await scs.auth.sendPhoneVerificationCode({
  phoneNumber: '+1234567890',           // Required: E.164 format
  recaptchaToken: 'recaptcha-token'     // Optional: For bot protection
});

console.log('Verification ID:', verificationId);
// Store this ID - you'll need it in step 2

// Step 2: User enters the code they received
const { token, user } = await scs.auth.signInWithPhoneNumber({
  verificationId: verificationId,  // The ID from step 1
  code: '123456'                   // 6-digit code from SMS
});

console.log('Phone verified:', user.phoneNumber);

sendPhoneVerificationCode Parameters:

Parameter Type Required Description
phoneNumber string Yes Phone number in E.164 format (e.g., +1234567890)
recaptchaToken string No reCAPTCHA token for abuse prevention

signInWithPhoneNumber Parameters:

Parameter Type Required Description
verificationId string Yes Verification ID from sendPhoneVerificationCode
code string Yes 6-digit verification code from SMS

Complete Flow Example:

async function signInWithPhone(phoneNumber) {
  try {
    // Step 1: Send code
    const { verificationId } = await scs.auth.sendPhoneVerificationCode({
      phoneNumber: phoneNumber
    });

    // Show UI for code entry
    const code = await promptUserForCode(); // Your UI implementation

    // Step 2: Verify code
    const { token, user } = await scs.auth.signInWithPhoneNumber({
      verificationId,
      code
    });

    return user;
  } catch (error) {
    switch (error.code) {
      case 'auth/invalid-phone-number':
        throw new Error('Invalid phone number format. Use E.164 format (+1234567890)');
      case 'auth/too-many-requests':
        throw new Error('Too many attempts. Please try again later.');
      case 'auth/invalid-verification-code':
        throw new Error('Invalid verification code. Please try again.');
      case 'auth/code-expired':
        throw new Error('Code expired. Please request a new one.');
      default:
        throw error;
    }
  }
}

Custom Token Authentication

Sign in using a JWT token generated by your own backend. Useful for migrating users from another system or integrating with custom authentication.

// Sign in with a custom token (generated by your backend)
const { token, user } = await scs.auth.signInWithCustomToken('your-custom-jwt-token');

console.log('Signed in user:', user.uid);

Parameters:

Parameter Type Required Description
token string Yes JWT token generated by your backend

Backend Token Generation Example (Node.js):

const jwt = require('jsonwebtoken');

function createCustomToken(uid, claims = {}) {
  const payload = {
    uid: uid,
    claims: claims,
    iat: Math.floor(Date.now() / 1000),
    exp: Math.floor(Date.now() / 1000) + (60 * 60) // 1 hour
  };

  return jwt.sign(payload, process.env.SCS_SECRET_KEY, {
    algorithm: 'HS256',
    issuer: 'your-project-id'
  });
}

// Generate token for a user
const customToken = createCustomToken('user-123', { role: 'admin' });
// Send this token to the client for sign-in

Use Cases:

  • Migrating users from another authentication system
  • Server-side user creation with immediate client sign-in
  • Integration with enterprise SSO systems
  • Machine-to-machine authentication

Account Linking

Link multiple authentication providers to a single account. Users can sign in with any linked provider.

// Link a provider to current account
const updatedUser = await scs.auth.linkProvider('facebook', {
  accessToken: 'facebook-access-token'
});

console.log('Linked providers:', updatedUser.providerData);
// [{ providerId: 'password' }, { providerId: 'google' }, { providerId: 'facebook' }]

// Unlink a provider from current account
const user = await scs.auth.unlinkProvider('facebook');
console.log('Remaining providers:', user.providerData);

// Get available sign-in methods for an email
const { methods } = await scs.auth.fetchSignInMethodsForEmail('[email protected]');
console.log('Available methods:', methods);
// ['password', 'google', 'facebook']

linkProvider Parameters:

Parameter Type Required Description
provider string Yes Provider name: 'google', 'facebook', 'apple', 'github', 'twitter', 'microsoft'
credentials object Yes Provider-specific credentials (tokens)

Supported Providers and Credentials:

Provider Required Credentials
google { idToken, accessToken? }
facebook { accessToken }
apple { identityToken, authorizationCode?, fullName? }
github { code, redirectUri? }
twitter { oauthToken, oauthTokenSecret }
microsoft { accessToken, idToken? }

Complete Account Linking Flow:

// Check if user can link a provider
async function canLinkProvider(email, provider) {
  const { methods } = await scs.auth.fetchSignInMethodsForEmail(email);

  if (methods.includes(provider)) {
    throw new Error(`${provider} is already linked to this account`);
  }

  return true;
}

// Link Google to existing account
async function linkGoogleAccount(googleIdToken) {
  try {
    // Verify user is signed in
    const currentUser = await scs.auth.getCurrentUser();
    if (!currentUser) {
      throw new Error('Must be signed in to link accounts');
    }

    // Link the provider
    const updatedUser = await scs.auth.linkProvider('google', {
      idToken: googleIdToken
    });

    console.log('Successfully linked Google account');
    return updatedUser;
  } catch (error) {
    if (error.code === 'auth/credential-already-in-use') {
      console.error('This Google account is already linked to another user');
    } else if (error.code === 'auth/provider-already-linked') {
      console.error('Google is already linked to this account');
    }
    throw error;
  }
}

Password Reset & Email Verification

Handle password recovery and email verification flows.

// Send password reset email
await scs.auth.sendPasswordResetEmail('[email protected]');
console.log('Password reset email sent');

// Confirm password reset (user clicks link in email, you extract the code)
await scs.auth.confirmPasswordReset({
  code: 'reset-code-from-email',      // Code from the reset link
  newPassword: 'newSecurePassword123'  // User's new password
});
console.log('Password successfully reset');

// Send email verification to current user
await scs.auth.sendEmailVerification();
console.log('Verification email sent');

// Verify email with code (user clicks link, you extract the code)
await scs.auth.verifyEmail('verification-code');
console.log('Email verified');

Error Handling:

// Password Reset with error handling
async function resetPassword(email) {
  try {
    await scs.auth.sendPasswordResetEmail(email);
    return { success: true, message: 'Reset email sent' };
  } catch (error) {
    switch (error.code) {
      case 'auth/user-not-found':
        // Don't reveal if user exists for security
        return { success: true, message: 'If this email exists, a reset link was sent' };
      case 'auth/too-many-requests':
        return { success: false, message: 'Too many attempts. Please try later.' };
      default:
        throw error;
    }
  }
}

// Confirm password reset with validation
async function confirmReset(code, newPassword) {
  // Validate password strength
  if (newPassword.length < 8) {
    throw new Error('Password must be at least 8 characters');
  }

  try {
    await scs.auth.confirmPasswordReset({ code, newPassword });
    return { success: true };
  } catch (error) {
    switch (error.code) {
      case 'auth/expired-action-code':
        return { success: false, message: 'Reset link expired. Please request a new one.' };
      case 'auth/invalid-action-code':
        return { success: false, message: 'Invalid reset link.' };
      case 'auth/weak-password':
        return { success: false, message: 'Password is too weak.' };
      default:
        throw error;
    }
  }
}

Authentication State Management

Listen for authentication state changes and manage user sessions.

// Check if user is logged in
const isLoggedIn = scs.auth.isLoggedIn;
console.log('Is logged in:', isLoggedIn);

// Get current user (from cache)
const cachedUser = scs.auth.currentUser;

// Get current user (fresh from server)
const user = await scs.auth.getCurrentUser();

// Refresh user data
const refreshedUser = await scs.auth.reload();

// Get the current auth token
const token = scs.auth.token;

// Listen for auth state changes (if supported)
scs.auth.onAuthStateChanged((user) => {
  if (user) {
    console.log('User signed in:', user.uid);
  } else {
    console.log('User signed out');
  }
});

Complete Authentication Example

const SCS = require('@spyxpo/scs');

const scs = new SCS({
  apiKey: 'your-api-key',
  projectId: 'your-project-id',
  baseUrl: 'https://your-scs-instance.com'
});

class AuthService {
  // Email/Password registration
  async register(email, password, displayName) {
    const { token, user } = await scs.auth.register({
      email,
      password,
      displayName
    });

    // Send verification email
    await scs.auth.sendEmailVerification();

    return user;
  }

  // Email/Password login
  async login(email, password) {
    return await scs.auth.login({ email, password });
  }

  // Social login (works for any provider)
  async socialLogin(provider, credentials) {
    const methods = {
      google: () => scs.auth.signInWithGoogle(credentials),
      facebook: () => scs.auth.signInWithFacebook(credentials),
      apple: () => scs.auth.signInWithApple(credentials),
      github: () => scs.auth.signInWithGitHub(credentials),
      twitter: () => scs.auth.signInWithTwitter(credentials),
      microsoft: () => scs.auth.signInWithMicrosoft(credentials)
    };

    if (!methods[provider]) {
      throw new Error(`Unknown provider: ${provider}`);
    }

    return await methods[provider]();
  }

  // Guest mode
  async continueAsGuest(customData = {}) {
    return await scs.auth.signInAnonymously({ customData });
  }

  // Upgrade guest to permanent account
  async upgradeGuestAccount(provider, credentials) {
    const user = await scs.auth.getCurrentUser();
    if (!user?.isAnonymous) {
      throw new Error('Current user is not anonymous');
    }

    return await scs.auth.linkProvider(provider, credentials);
  }

  // Logout
  logout() {
    scs.auth.logout();
  }
}

// Usage
const auth = new AuthService();

// Register new user
const user = await auth.register('[email protected]', 'password123', 'John Doe');

// Or sign in with Google
const googleUser = await auth.socialLogin('google', { idToken: 'xxx' });

// Or continue as guest and upgrade later
const guest = await auth.continueAsGuest({ source: 'homepage' });
// ... user decides to create account ...
const upgraded = await auth.upgradeGuestAccount('google', { idToken: 'xxx' });

Database

NoSQL document database with nested collections. SCS supports two powerful database options:

Database Types

Type Name Description Best For
eazi eaZI Database Document-based NoSQL with Firestore-like collections, documents, and subcollections Development, prototyping, small to medium apps
reladb RelaDB Production-grade NoSQL database with relational-style views Production, scalability, advanced queries

Initialize with eaZI (Default)

import SCS from 'scs-sdk';

// eaZI is the default database - no special configuration needed
const scs = new SCS({
  projectId: 'your-project-id',
  apiKey: 'your-api-key'
  // databaseType: 'eazi' is implicit
});

Initialize with RelaDB (Production)

import SCS from 'scs-sdk';

// Use RelaDB for production
const scs = new SCS({
  projectId: 'your-project-id',
  apiKey: 'your-api-key',
  databaseType: 'reladb'  // Enable RelaDB
});

eaZI Database Features

  • Document-based: Firestore-like collections and documents
  • Subcollections: Nested data organization
  • File-based storage: No external dependencies required
  • Zero configuration: Works out of the box
  • Query support: Filtering, ordering, and pagination

RelaDB Features

  • Production-ready: Built for reliability and performance
  • Scalable: Horizontal scaling and replication support
  • Advanced queries: Aggregation pipelines, complex filters
  • Indexing: Custom indexes for optimized performance
  • Schema flexibility: Dynamic schema with validation support
  • Relational-style views: Table view with columns and rows in the console

Collection Operations

// Get a collection reference
const users = scs.database.collection('users');

// List all collections
const collections = await scs.database.listCollections();

// Create a collection
await scs.database.createCollection('newCollection');

// Delete a collection
await scs.database.deleteCollection('oldCollection');

Document Operations

// Add document with auto-generated ID
const doc = await scs.database.collection('users').add({
  name: 'John Doe',
  email: '[email protected]',
  age: 30,
  tags: ['developer', 'nodejs'],
  profile: {
    bio: 'Software developer',
    avatar: 'https://example.com/avatar.jpg'
  }
});
console.log('Document ID:', doc.id);

// Set document with custom ID (creates or overwrites)
await scs.database.collection('users').doc('user-123').set({
  name: 'Jane Doe',
  email: '[email protected]'
});

// Get a single document
const user = await scs.database.collection('users').doc('user-123').get();
console.log(user.data);

// Update document (partial update)
await scs.database.collection('users').doc('user-123').update({
  age: 31,
  'profile.bio': 'Senior developer'
});

// Delete document
await scs.database.collection('users').doc('user-123').delete();

Query Operations

// Simple query with single filter
const activeUsers = await scs.database.collection('users')
  .where('status', '==', 'active')
  .get();

// Multiple filters
const results = await scs.database.collection('users')
  .where('age', '>=', 18)
  .where('status', '==', 'active')
  .get();

// Ordering and pagination
const posts = await scs.database.collection('posts')
  .where('published', '==', true)
  .orderBy('createdAt', 'desc')
  .limit(10)
  .skip(20)
  .get();

// Using 'in' operator
const featured = await scs.database.collection('posts')
  .where('category', 'in', ['tech', 'science', 'news'])
  .get();

// Using 'contains' for array fields
const tagged = await scs.database.collection('posts')
  .where('tags', 'contains', 'javascript')
  .get();

Query Operators

Operator Description Example
== Equal to .where('status', '==', 'active')
!= Not equal to .where('status', '!=', 'deleted')
> Greater than .where('age', '>', 18)
>= Greater than or equal .where('age', '>=', 18)
< Less than .where('price', '<', 100)
<= Less than or equal .where('price', '<=', 50)
in Value in array .where('status', 'in', ['active', 'pending'])
contains Array contains value .where('tags', 'contains', 'featured')

Subcollections

// Access a subcollection
const postsRef = scs.database
  .collection('users')
  .doc('userId')
  .collection('posts');

// Add to subcollection
const post = await postsRef.add({
  title: 'My First Post',
  content: 'Hello World!',
  createdAt: new Date()
});

// Query subcollection
const userPosts = await postsRef
  .orderBy('createdAt', 'desc')
  .limit(5)
  .get();

// Nested subcollections (e.g., users/userId/posts/postId/comments)
const commentsRef = scs.database
  .collection('users')
  .doc('userId')
  .collection('posts')
  .doc('postId')
  .collection('comments');

// List subcollections of a document
const subcollections = await scs.database
  .collection('users')
  .doc('userId')
  .listCollections();

Storage

// Upload a file from path
const file = await scs.storage.upload('./image.png', {
  folder: 'images',
  filename: 'profile.png'
});

// Upload from buffer
const buffer = fs.readFileSync('./document.pdf');
const file = await scs.storage.upload(buffer, {
  folder: 'documents',
  filename: 'report.pdf',
  contentType: 'application/pdf'
});

// List files
const { files, total } = await scs.storage.list({
  folder: 'images',
  limit: 20
});

// Get file URL
const url = scs.storage.getUrl('file-id');

// Get file metadata
const metadata = await scs.storage.getMetadata('file-id');

// Download file
const buffer = await scs.storage.download('file-id');

// Download to file
await scs.storage.downloadToFile('file-id', './downloaded.png');

// Delete file
await scs.storage.delete('file-id');

// Create/delete folders
await scs.storage.createFolder('documents/reports');
await scs.storage.deleteFolder('documents/reports');

// File reference
const fileRef = scs.storage.ref('file-id');
console.log(fileRef.url);
await fileRef.delete();

Realtime Database

Real-time data synchronization via WebSocket.

// Connect to realtime database
await scs.realtime.connect();

// Get a reference
const chatRef = scs.realtime.ref('chat/room1');

// Set data
await chatRef.set({
  name: 'General Chat',
  created: new Date().toISOString()
});

// Update data (merge)
await chatRef.update({
  lastMessage: 'Hello!'
});

// Push new child with auto-generated key
const messageRef = await chatRef.child('messages').push({
  text: 'Hello everyone!',
  sender: 'user123',
  timestamp: Date.now()
});

// Get data
const data = await chatRef.get();

// Listen for real-time updates
const unsubscribe = await chatRef.on((data, event) => {
  console.log('Data changed:', data, 'Event:', event);
});

// Stop listening
unsubscribe();

// Remove data
await chatRef.remove();

// Disconnect
scs.realtime.disconnect();

Cloud Messaging

Push notifications with topics.

// Register device token
await scs.messaging.registerToken({
  token: 'device-token',
  platform: 'web' // 'web', 'ios', or 'android'
});

// Create a topic
await scs.messaging.createTopic({
  name: 'news',
  description: 'Breaking news updates'
});

// Subscribe to topic
await scs.messaging.subscribeToTopic('news', 'device-token');

// Send to topic
await scs.messaging.sendToTopic('news', {
  title: 'Breaking News',
  body: 'Something important happened!',
  data: { articleId: '123' }
});

// Send to specific token
await scs.messaging.sendToToken('device-token', {
  title: 'Personal Update',
  body: 'You have a new message',
  data: { messageId: '456' }
});

// Topic reference
const newsTopic = scs.messaging.topic('news');
await newsTopic.send({ title: 'Update', body: 'New content available' });

// Unsubscribe from topic
await scs.messaging.unsubscribeFromTopic('news', 'device-token');

// List topics
const topics = await scs.messaging.listTopics();

Remote Config

Dynamic configuration management.

// Fetch configuration
const config = await scs.remoteConfig.fetch();

// Get typed values
const welcomeMessage = await scs.remoteConfig.getString('welcome_message', 'Hello!');
const maxItems = await scs.remoteConfig.getNumber('max_items', 10);
const featureEnabled = await scs.remoteConfig.getBoolean('new_feature', false);
const settings = await scs.remoteConfig.getJson('app_settings', {});

// Force refresh from server
const freshConfig = await scs.remoteConfig.fetch({ forceRefresh: true });

// Set cache duration (in milliseconds)
scs.remoteConfig.setCacheDuration(10 * 60 * 1000); // 10 minutes

// Admin: Create parameter
await scs.remoteConfig.createParam({
  key: 'welcome_message',
  value: 'Welcome to our app!',
  type: 'string',
  description: 'Message shown on home screen'
});

// Admin: Update parameter
await scs.remoteConfig.updateParam('welcome_message', {
  value: 'Welcome back!'
});

// Admin: Publish changes
await scs.remoteConfig.publish();

// Admin: Rollback to previous version
await scs.remoteConfig.rollback('version-id');

Serverless Functions

// Create a function
await scs.functions.create({
  name: 'hello',
  code: `
    module.exports = async (req, res) => {
      const name = req.body.name || 'World';
      res.json({ message: \`Hello, \${name}!\` });
    };
  `,
  timeout: 30,
  memoryLimit: 128,
  public: true
});

// Invoke a function
const result = await scs.functions.invoke('hello', { name: 'John' });

// Use httpsCallable for cleaner syntax
const helloFn = scs.functions.httpsCallable('hello');
const response = await helloFn.call({ name: 'Jane' });

// Test a function (admin)
const testResult = await scs.functions.test('function-id', { test: true });

// Get function logs
const logs = await scs.functions.getLogs('function-id', { limit: 50 });

// Update function
await scs.functions.update('function-id', {
  code: 'new code...',
  timeout: 60
});

// Delete function
await scs.functions.delete('function-id');

AI

Chat, text completion, and image generation with local LLM models.

// Chat with AI
const response = await scs.ai.chat({
  message: 'What is the capital of France?',
  systemPrompt: 'You are a helpful geography assistant.'
});
console.log(response.content);

// Text completion
const completion = await scs.ai.complete({
  prompt: 'Once upon a time'
});
console.log(completion.content);

// Generate image
const image = await scs.ai.generateImage({
  prompt: 'A sunset over mountains'
});
console.log(image.imageUrl);

// List available models
const models = await scs.ai.listModels();

// Conversation management
const conversation = await scs.ai.createConversation({ title: 'Geography Chat' });
await scs.ai.getConversation(conversation.conversationId);
await scs.ai.deleteConversation(conversation.conversationId);

AI Agents

Create and manage AI agents with custom instructions and tools.

// Create an agent
const agent = await scs.ai.createAgent({
  name: 'Customer Support',
  instructions: 'You are a helpful customer support assistant. Be polite and helpful.',
  model: 'llama3.2',
  temperature: 0.7
});
console.log('Created agent:', agent.agentId);

// List agents
const agents = await scs.ai.listAgents();

// Run the agent
let response = await scs.ai.runAgent(agent.agentId, {
  input: 'How do I reset my password?'
});
console.log('Agent:', response.output);
console.log('Session:', response.sessionId);

// Continue the conversation in the same session
response = await scs.ai.runAgent(agent.agentId, {
  input: 'Thanks! What about enabling 2FA?',
  sessionId: response.sessionId
});

// List agent sessions
const sessions = await scs.ai.listAgentSessions(agent.agentId);

// Get full session history
const session = await scs.ai.getAgentSession(agent.agentId, response.sessionId);
session.messages.forEach(msg => {
  console.log(`${msg.role}: ${msg.content}`);
});

// Update agent
await scs.ai.updateAgent(agent.agentId, {
  instructions: 'Updated instructions here',
  temperature: 0.5
});

// Define a tool for agents
const tool = await scs.ai.defineTool({
  name: 'get_weather',
  description: 'Get weather for a location',
  parameters: {
    type: 'object',
    properties: {
      location: { type: 'string', description: 'City name' }
    }
  }
});

// List tools
const tools = await scs.ai.listTools();

// Delete agent and sessions
await scs.ai.deleteAgentSession(agent.agentId, response.sessionId);
await scs.ai.deleteAgent(agent.agentId);

CLI Tool

The SCS CLI allows you to deploy your application from the command line.

Basic Usage

# Initialize a new project
scs init

# Deploy all targets
scs deploy

# Deploy specific targets
scs deploy hosting
scs deploy functions
scs deploy rules

# Deploy multiple targets
scs deploy hosting functions

# Use --only or --except flags
scs deploy --only hosting,functions
scs deploy --except rules

Commands

Command Description
scs init Initialize a new SCS project
scs deploy Deploy to SCS (all targets by default)
scs list <target> List deployments for a target
scs login Authenticate with SCS
scs logout Log out from SCS
scs help Show help information

Deploy Targets

Target Description
hosting Static website hosting
app-hosting Dynamic app hosting (Node.js, Python, etc.)
functions Cloud functions
rules Security rules

Options

Option Description
--config <path> Path to scs.json config file
--project <id> Project ID to use
--message <msg> Deployment message/description
--only <targets> Only deploy specified targets (comma-separated)
--except <targets> Deploy all except specified targets
--verbose Show detailed error information

Configuration

The CLI reads from scs.json in your project root:

{
  "sdk_config": {
    "api_key": "YOUR_API_KEY",
    "project_id": "YOUR_PROJECT_ID",
    "base_url": "https://your-scs-instance.com"
  },
  "hosting": {
    "public": "public"
  },
  "functions": {
    "source": "functions",
    "runtime": "nodejs18"
  },
  "appHosting": {
    "source": ".",
    "runtime": "nodejs18",
    "buildCommand": "npm run build",
    "startCommand": "npm start"
  },
  "database": {
    "rules": "scs.rules.json"
  }
}

Examples

# Initialize and deploy
scs init
scs deploy

# Deploy only hosting with a message
scs deploy hosting --message "Updated homepage"

# Deploy functions from a custom directory
scs deploy functions --source ./my-functions

# List all hosting deployments
scs list hosting

# List deployed functions
scs list functions

TypeScript Support

The SDK includes TypeScript type definitions. Just import and use:

import SCS from '@spyxpo/scs-sdk';

const scs = new SCS({
  apiKey: 'your-api-key',
  projectId: 'your-project-id',
  baseUrl: 'https://your-scs-instance.com'
});

// Full type inference and autocompletion
const user = await scs.auth.getCurrentUser();
console.log(user.email); // TypeScript knows this is a string

Error Handling

All methods throw errors with useful information:

try {
  await scs.auth.login({ email: '[email protected]', password: 'wrong' });
} catch (error) {
  console.error('Error:', error.message);
  console.error('Status:', error.status);      // HTTP status code
  console.error('Response:', error.response);  // Full response body
}

Configuration File Format

The SDK can read from a scs-info.json file:

{
  "sdk_config": {
    "api_key": "pk_your_api_key",
    "project_id": "your-project-id",
    "base_url": "https://your-scs-instance.com"
  },
  "project_info": {
    "project_id": "your-project-id",
    "api_url": "https://your-scs-instance.com"
  },
  "client": {
    "api_key": "pk_your_api_key"
  }
}

Requirements

  • Node.js >= 14.0.0
  • socket.io-client (for realtime features)
  • form-data (for file uploads)

License

MIT

About

The official node.js SDK for Spyxpo Cloud Services

Resources

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published