AI Development Guide - JavaScript SDK
This guide provides a comprehensive, fast reference for AI systems to quickly develop applications using the BosBase JavaScript SDK. All examples are production-ready and follow best practices.
Table of Contents
- Authentication
- Initialize Collections
- Define Collection Fields
- Add Data to Collections
- Modify Collection Data
- Delete Data from Collections
- Query Collection Contents
- Add and Delete Fields from Collections
- Query Collection Field Information
- Upload Files
- Query Logs
- Send Emails
Authentication
Initialize Client
import BosBase from 'bosbase';
const pb = new BosBase('http://localhost:8090');
Password Authentication
// Authenticate with email/username and password
const authData = await pb.collection('users').authWithPassword(
'user@example.com',
'password123'
);
// Auth data is automatically stored
console.log(pb.authStore.isValid); // true
console.log(pb.authStore.token); // JWT token
console.log(pb.authStore.record); // User record
OAuth2 Authentication
// Get OAuth2 providers
const methods = await pb.collection('users').listAuthMethods();
console.log(methods.oauth2.providers); // Available providers
// Authenticate with OAuth2
const authData = await pb.collection('users').authWithOAuth2({
provider: 'google',
urlCallback: (url) => {
// Open OAuth2 URL in browser
window.open(url);
},
});
OTP Authentication
// Request OTP
const otpResponse = await pb.collection('users').requestVerification('user@example.com');
// Authenticate with OTP
const authData = await pb.collection('users').authWithOTP(
otpResponse.otpId,
'123456' // OTP code
);
Check Authentication Status
if (pb.authStore.isValid) {
console.log('Authenticated as:', pb.authStore.record.email);
} else {
console.log('Not authenticated');
}
Logout
pb.authStore.clear();
Initialize Collections
Create Base Collection
const collection = await pb.collections.create({
name: 'posts',
type: 'base',
fields: [
{
name: 'title',
type: 'text',
required: true,
},
],
});
console.log('Collection ID:', collection.id);
Create Auth Collection
const authCollection = await pb.collections.create({
name: 'users',
type: 'auth',
fields: [
{
name: 'name',
type: 'text',
required: false,
},
],
passwordAuth: {
enabled: true,
identityFields: ['email', 'username'],
},
});
Create View Collection
const viewCollection = await pb.collections.create({
name: 'published_posts',
type: 'view',
viewQuery: 'SELECT * FROM posts WHERE published = true',
});
Get Collection by ID or Name
const collection = await pb.collections.getOne('posts');
// or by ID
const collection = await pb.collections.getOne('_pbc_2287844090');
Define Collection Fields
Add Field to Collection
const updatedCollection = await pb.collections.addField('posts', {
name: 'content',
type: 'editor',
required: false,
});
Common Field Types
// Text field
{
name: 'title',
type: 'text',
required: true,
min: 10,
max: 255,
}
// Number field
{
name: 'views',
type: 'number',
required: false,
min: 0,
}
// Boolean field
{
name: 'published',
type: 'bool',
required: false,
}
// Date field
{
name: 'published_at',
type: 'date',
required: false,
}
// File field
{
name: 'avatar',
type: 'file',
required: false,
maxSelect: 1,
maxSize: 2097152, // 2MB
mimeTypes: ['image/jpeg', 'image/png'],
}
// Relation field
{
name: 'author',
type: 'relation',
required: true,
collectionId: '_pbc_users_auth_',
maxSelect: 1,
}
// Select field
{
name: 'status',
type: 'select',
required: true,
options: {
values: ['draft', 'published', 'archived'],
},
}
Update Field
const updatedCollection = await pb.collections.updateField('posts', 'title', {
max: 500,
required: true,
});
Remove Field
const updatedCollection = await pb.collections.removeField('posts', 'old_field');
Add Data to Collections
Create Single Record
const record = await pb.collection('posts').create({
title: 'My First Post',
content: 'This is the content',
published: true,
});
console.log('Created record ID:', record.id);
Create Record with File Upload
const formData = new FormData();
formData.append('title', 'Post with Image');
formData.append('image', fileInput.files[0]); // File from input
const record = await pb.collection('posts').create(formData);
Create Record with Relations
const record = await pb.collection('posts').create({
title: 'My Post',
author: 'user_record_id', // Related record ID
categories: ['cat1_id', 'cat2_id'], // Multiple relations
});
Batch Create Records
const records = await pb.batch([
{
method: 'POST',
url: '/api/collections/posts/records',
body: { title: 'Post 1' },
},
{
method: 'POST',
url: '/api/collections/posts/records',
body: { title: 'Post 2' },
},
]);
Modify Collection Data
Update Single Record
const updated = await pb.collection('posts').update('record_id', {
title: 'Updated Title',
content: 'Updated content',
});
Update Record with File
const formData = new FormData();
formData.append('title', 'Updated Title');
formData.append('image', newFile);
const updated = await pb.collection('posts').update('record_id', formData);
Partial Update
// Only update specific fields
const updated = await pb.collection('posts').update('record_id', {
views: 100, // Only update views
});
Delete Data from Collections
Delete Single Record
await pb.collection('posts').delete('record_id');
Delete Multiple Records
// Using batch
await pb.batch([
{
method: 'DELETE',
url: '/api/collections/posts/records/record_id_1',
},
{
method: 'DELETE',
url: '/api/collections/posts/records/record_id_2',
},
]);
Delete All Records (Truncate)
await pb.collections.truncate('posts');
Query Collection Contents
List Records with Pagination
const result = await pb.collection('posts').getList(1, 50);
console.log(result.page); // 1
console.log(result.perPage); // 50
console.log(result.totalItems); // Total count
console.log(result.items); // Array of records
Filter Records
const result = await pb.collection('posts').getList(1, 50, {
filter: 'published = true && views > 100',
sort: '-created',
});
Filter Operators
// Equality
filter: 'status = "published"'
// Comparison
filter: 'views > 100'
filter: 'created >= "2023-01-01"'
// Text search
filter: 'title ~ "javascript"'
// Multiple conditions
filter: 'status = "published" && views > 100'
filter: 'status = "draft" || status = "pending"'
// Relation filter
filter: 'author.id = "user_id"'
Sort Records
// Single field
sort: '-created' // DESC
sort: 'title' // ASC
// Multiple fields
sort: '-created,title' // DESC by created, then ASC by title
Expand Relations
const result = await pb.collection('posts').getList(1, 50, {
expand: 'author,categories',
});
// Access expanded data
result.items.forEach(post => {
console.log(post.expand.author.name);
console.log(post.expand.categories);
});
Get Single Record
const record = await pb.collection('posts').getOne('record_id', {
expand: 'author',
});
Get First Matching Record
const record = await pb.collection('posts').getFirstListItem(
'slug = "my-post-slug"',
{
expand: 'author',
}
);
Get All Records
const allRecords = await pb.collection('posts').getFullList({
filter: 'published = true',
sort: '-created',
});
Add and Delete Fields from Collections
Add Field
const collection = await pb.collections.addField('posts', {
name: 'tags',
type: 'select',
options: {
values: ['tech', 'science', 'art'],
},
});
Update Field
const collection = await pb.collections.updateField('posts', 'tags', {
options: {
values: ['tech', 'science', 'art', 'music'],
},
});
Remove Field
const collection = await pb.collections.removeField('posts', 'old_field');
Get Field Information
const field = await pb.collections.getField('posts', 'title');
console.log(field.type, field.required, field.options);
Query Collection Field Information
Get All Fields for a Collection
const collection = await pb.collections.getOne('posts');
collection.fields.forEach(field => {
console.log(field.name, field.type, field.required);
});
Get Collection Schema (Simplified)
const schema = await pb.collections.getSchema('posts');
console.log(schema.fields); // Array of field info
Get All Collection Schemas
const schemas = await pb.collections.getAllSchemas();
schemas.collections.forEach(collection => {
console.log(collection.name, collection.fields);
});
Query Field Information for Single Collection
// Method 1: Get full collection
const collection = await pb.collections.getOne('posts');
const titleField = collection.fields.find(f => f.name === 'title');
// Method 2: Get specific field
const field = await pb.collections.getField('posts', 'title');
// Method 3: Get schema
const schema = await pb.collections.getSchema('posts');
const titleFieldInfo = schema.fields.find(f => f.name === 'title');
Upload Files
Upload File with Record Creation
const formData = new FormData();
formData.append('title', 'Post Title');
formData.append('image', fileInput.files[0]);
const record = await pb.collection('posts').create(formData);
Upload File with Record Update
const formData = new FormData();
formData.append('image', newFile);
const updated = await pb.collection('posts').update('record_id', formData);
Get File URL
const record = await pb.collection('posts').getOne('record_id');
const fileUrl = pb.files.getURL(record, record.image);
Get File URL with Options
const fileUrl = pb.files.getURL(record, record.image, {
thumb: '100x100', // Thumbnail
download: true, // Force download
});
Get Private File Token
// For accessing private files
const token = await pb.files.getToken();
// Use token in file URL query params
Query Logs
List Logs
const logs = await pb.logs.getList(1, 50);
console.log(logs.items); // Array of log entries
Filter Logs
const logs = await pb.logs.getList(1, 50, {
filter: 'level >= 400', // Error level and above
sort: '-created',
});
Get Single Log
const log = await pb.logs.getOne('log_id');
console.log(log.message, log.data);
Get Log Statistics
const stats = await pb.logs.getStats({
filter: 'level >= 400',
});
stats.forEach(stat => {
console.log(stat.date, stat.total);
});
Log Levels
0- Debug1- Info2- Warning3- Error4- Fatal
Send Emails
Note: Email sending is typically handled server-side via hooks or backend code. The SDK doesn’t provide direct email sending methods, but you can trigger email-related operations.
Trigger Email Verification
// Request verification email
await pb.collection('users').requestVerification('user@example.com');
Trigger Password Reset Email
// Request password reset email
await pb.collection('users').requestPasswordReset('user@example.com');
Email Change Request
// Request email change
await pb.collection('users').requestEmailChange('newemail@example.com');
Server-Side Email Sending
Email sending is configured in the backend settings and triggered automatically by:
- User registration (verification email)
- Password reset requests
- Email change requests
- Custom hooks
To send custom emails, you would typically:
- Create a backend hook that uses
app.NewMailClient() - Or use the admin API to configure email templates
- Or trigger email-related record operations that automatically send emails
Complete Example: Full Application Flow
import BosBase from 'bosbase';
const pb = new BosBase('http://localhost:8090');
async function setupApplication() {
// 1. Authenticate
await pb.collection('users').authWithPassword('admin@example.com', 'password');
// 2. Create collection
const collection = await pb.collections.create({
name: 'posts',
type: 'base',
fields: [
{ name: 'title', type: 'text', required: true },
{ name: 'content', type: 'editor' },
{ name: 'published', type: 'bool' },
],
});
// 3. Add more fields
await pb.collections.addField('posts', {
name: 'views',
type: 'number',
min: 0,
});
// 4. Create records
const post = await pb.collection('posts').create({
title: 'Hello World',
content: 'My first post',
published: true,
views: 0,
});
// 5. Query records
const posts = await pb.collection('posts').getList(1, 10, {
filter: 'published = true',
sort: '-created',
});
// 6. Update record
await pb.collection('posts').update(post.id, {
views: 100,
});
// 7. Query logs
const logs = await pb.logs.getList(1, 20, {
filter: 'level >= 400',
});
console.log('Application setup complete!');
}
setupApplication().catch(console.error);
Quick Reference
Common Patterns
// Check if authenticated
if (pb.authStore.isValid) { /* ... */ }
// Get current user
const user = pb.authStore.record;
// Refresh auth token
await pb.collection('users').authRefresh();
// Error handling
try {
await pb.collection('posts').create({ title: 'Test' });
} catch (err) {
if (err.status === 400) {
console.error('Validation error:', err.data);
} else if (err.status === 401) {
console.error('Not authenticated');
}
}
Field Types Reference
text- Text inputnumber- Numeric valuebool- Booleanemail- Email addressurl- URLdate- Dateselect- Single selectjson- JSON datafile- File uploadrelation- Relation to another collectioneditor- Rich text editor
Best Practices
- Always handle errors: Wrap API calls in try-catch
- Check authentication: Verify
pb.authStore.isValidbefore operations - Use pagination: Don’t fetch all records at once for large collections
- Validate data: Ensure required fields are provided
- Use filters: Filter data on the server, not client-side
- Expand relations wisely: Only expand what you need
- Handle file uploads: Use FormData for file fields
- Refresh tokens: Use
authRefresh()to maintain sessions
LangChaingo Recipes
Quick Completion
const result = await pb.langchaingo.completions({
model: { provider: "openai", model: "gpt-4o-mini" },
messages: [
{ role: "system", content: "Answer with one concise line." },
{ role: "user", content: "Give me a fun fact about Mars." }
],
temperature: 0.4
});
console.log(result.content);
Retrieval-Augmented Answering
const rag = await pb.langchaingo.rag({
collection: "knowledge-base",
question: "Why is the sky blue?",
topK: 3,
returnSources: true
});
console.log(rag.answer);
console.log(rag.sources);
This guide provides all essential operations for building applications with the BosBase JavaScript SDK. For more detailed information, refer to the specific API documentation files.