A lightweight JavaScript/TypeScript client library for the Light Framework, providing an easy-to-use API for GraphQL queries/mutations, authentication, file management, user management, and more.
- 🔐 Authentication - Login/logout, password management, OAuth (Google, Facebook, Microsoft), WebAuthn support
- 📊 GraphQL Client - Simplified query and mutation APIs with automatic file upload handling
- 📁 File System - Complete file and folder management operations
- 👥 User Management - CRUD operations for users and roles
- 📧 Email - Send emails via the backend
- 🔄 Token Refresh - Automatic access token refresh with request queuing
- 🌐 Universal - Works in both browser and Node.js environments
npm install @hostlink/lightimport{createClient}from'@hostlink/light';// Create a client instanceconstapi=createClient('https://your-api.com/graphql');// Loginawaitapi.auth.login('username','password');// Query dataconstusers=awaitapi.query({app: {users: {user_id: true,username: true,first_name: true}}});// Logoutawaitapi.auth.logout();import{createClient}from'@hostlink/light';constapi=createClient('https://your-api.com/graphql');The client provides:
api.auth- Authentication methodsapi.query- GraphQL queriesapi.mutation- GraphQL mutationsapi.users- User managementapi.roles- Role managementapi.mail- Email sendingapi.config- Configuration accessapi.collect- Collection builderapi.list- List builder
// Login with username and passwordawaitapi.auth.login('username','password');// Login with 2FA codeawaitapi.auth.login('username','password','123456');// Logoutawaitapi.auth.logout();constuser=awaitapi.auth.getCurrentUser();// Returns: { user_id, username, first_name, last_name, status }// With custom fieldsconstuser=awaitapi.auth.getCurrentUser({user_id: true,username: true,email: true});// Update passwordawaitapi.auth.updatePassword('oldPassword','newPassword');// Change expired passwordawaitapi.auth.changeExpiredPassword('username','oldPassword','newPassword');// Forgot password flowconstjwt=awaitapi.auth.forgetPassword('username','email@example.com');awaitapi.auth.verifyCode(jwt,'123456');awaitapi.auth.resetPassword(jwt,'newPassword','123456');// Googleawaitapi.auth.google.login(credential);awaitapi.auth.google.register(credential);awaitapi.auth.google.unlink();// Facebookawaitapi.auth.facebook.login(accessToken);awaitapi.auth.facebook.register(accessToken);awaitapi.auth.facebook.unlink();// Microsoftawaitapi.auth.microsoft.login(accessToken);awaitapi.auth.microsoft.register(accountId);awaitapi.auth.microsoft.unlink();import{webAuthn}from'@hostlink/light';// Register a new passkeyawaitwebAuthn.register();// Login with passkeyawaitwebAuthn.login();// Check single permissionconstcanEdit=awaitapi.auth.isGranted('edit_users');// Check multiple permissionsconstrights=awaitapi.auth.grantedRights(['edit_users','delete_users']);constresult=awaitapi.query({app: {users: {user_id: true,username: true,profile: {avatar: true,bio: true}}}});constresult=awaitapi.mutation({createPost: {__args: {title: 'Hello World',content: 'My first post'}}});File uploads are automatically handled in mutations:
// Single file uploadawaitapi.mutation({uploadAvatar: {__args: {file: fileInput.files[0]}}});// Multiple file uploadawaitapi.mutation({uploadImages: {__args: {files: Array.from(fileInput.files)}}});import{createList}from'@hostlink/light';// Create a list queryconstusers=awaitcreateList('Users',{user_id: true,username: true,first_name: true}).where('status',1).where('role','admin').sort('-created_at').limit(10).fetch();// Get first itemconstuser=awaitcreateList('Users',{user_id: true,username: true}).where('username','john').first();list.where('status',1)// Exact match.where('age','>',18)// Greater than.where('age','>=',18)// Greater than or equal.where('age','<',65)// Less than.where('age','<=',65)// Less than or equal.where('status','!=',0)// Not equal.whereIn('role',['admin','moderator'])// In array.whereContains('name','john')// Contains string.whereBetween('age',18,65)// Between rangeimport{createCollection}from'@hostlink/light';constcollection=createCollection('Products',{id: true,name: true,price: true,category: true});// Filter and transform dataconstresult=awaitcollection.where('category','==','electronics').where('price','<',1000).sortBy('price').map(item=>({ ...item,discounted: item.price*0.9})).all();// AggregationsconstavgPrice=awaitcollection.avg('price');consttotal=awaitcollection.count();constmaxPrice=awaitcollection.max('price');// List usersconstusers=awaitapi.users.list();// Create userawaitapi.users.create({username: 'newuser',first_name: 'John',last_name: 'Doe',password: 'securepassword',join_date: '2024-01-01'});// Update userawaitapi.users.update(userId,{first_name: 'Jane'});// Delete userawaitapi.users.delete(userId);// List rolesconstroles=awaitapi.roles.list();// Create role with child rolesawaitapi.roles.create('admin',['editor','viewer']);// Delete roleawaitapi.roles.delete('admin');For direct filesystem access:
import{fs}from'@hostlink/light';// Create folderawaitfs.createFolder('local://path/to/folder');// Delete folderawaitfs.deleteFolder('local://path/to/folder');// Rename folderawaitfs.renameFolder('local://path/to/folder','newName');// Write fileawaitfs.writeFile('local://path/to/file.txt','content');// Upload fileawaitfs.uploadFile('local://path/to/destination',file);// Delete fileawaitfs.deleteFile('local://path/to/file.txt');// Check if existsconstexists=awaitfs.exists('local://path/to/file.txt');// Move file/folderawaitfs.move('local://from/path','local://to/path');// Search filesconstresults=awaitfs.find('searchterm','document');// labels: document, image, audio, video, archiveawaitapi.mail.send('recipient@example.com','Subject Line','Email message body');Create reusable model definitions:
importmodelfrom'@hostlink/light';constProduct=model('Product',{id: {name: 'product_id'},name: {gql: {name: true}},price: {gql: {price: true,currency: true}}});// CRUD operationsawaitProduct.add({name: 'New Product',price: 99.99});awaitProduct.update(1,{price: 89.99});awaitProduct.delete(1);constproduct=awaitProduct.get({id: 1},{name: true,price: true});constproducts=awaitProduct.list({name: true,price: true}).fetch();import{setApiClient,getApiClient}from'@hostlink/light';// Set a custom API clientsetApiClient(customClient);// Get the current API clientconstclient=getApiClient();// Access the underlying axios instanceconst{ axios }=getApiClient();The client automatically handles token refresh when receiving TOKEN_EXPIRED errors. Failed requests are queued and retried after the token is refreshed.
This library is written in TypeScript and includes full type definitions.
importtype{UserFields,CreateUserFields,QueryUserFieldsUserFields,RoleFields,FileFields,FolderFields,GraphQLQuery}from'@hostlink/light';MIT