📚 StoneJS Developer Guide

Complete reference for building modern web applications with the StoneJS Framework

🌐 Global Context

What is Global Context?

The Global Context ($context) provides access to all request data, services, and shared state:

Available Objects

Object Description Key Properties/Methods
$req Express request object method, path, query, body, headers, ip
$res Express response object send(), json(), redirect(), status(), setHeader()
$session User session data (read/write) id, any custom properties (userId, cart, etc.)
$db Database connection pool query(), secureQuery(), getConnection()
$cache Cache manager get(), set(), remember(), cacheSelf(), delete(), flush()
$env Environment variables from .env DB_HOST, SESSION_SECRET, NODE_ENV, etc.
$ver Version and git information version, commit, shortCommit, date, branch
$context Context with custom data storage get(), set(), has(), componentPath, autohandlers

Custom Context Data

<%%js> // Set custom data (available in autohandlers, components) $context.set('title', 'My Page'); $context.set('user', { name: 'Alice', role: 'admin' }); $context.set('theme', 'dark'); // Get custom data const title = $context.get('pageTitle'); const user = $context.get('user'); // Check if exists if ($context.has('user')) { // ... }

Request Object ($req)

The request object contains all information about the incoming HTTP request. It's an Express request object with these commonly used properties:

Property Type Description Example
method string HTTP method of the request 'GET', 'POST', 'PUT', 'DELETE'
path string URL path without query string '/users/profile'
url string Full URL path with query string '/users/profile?id=123'
query object Parsed query string parameters { id: '123', filter: 'active' }
body object Parsed request body (POST/PUT) { name: 'Alice', email: '...' }
headers object HTTP request headers { 'user-agent': '...', 'content-type': '...' }
ip string Client IP address '192.168.1.100'
cookies object Parsed cookies from request { sessionId: 'abc123...' }

Example Usage:

<%%js> // Check HTTP method if ($req.method === 'POST') { const formData = $req.body; // Process form submission } // Get query parameters const userId = $req.query.id; const page = parseInt($req.query.page) || 1; // Access headers const userAgent = $req.headers['user-agent'];

Response Object ($res)

The response object is used to send data back to the client. It's an Express response object with these methods:

Method Description Example
json(data) Send JSON response $res.json({ success: true, data: users })
send(content) Send text/HTML response $res.send('Hello, World!')
redirect(url) Redirect to another URL $res.redirect('/login')
status(code) Set HTTP status code (chainable) $res.status(404).send('Not found')
setHeader(name, value) Set HTTP response header $res.setHeader('Content-Type', 'application/json')
render(view, data) Render a template (advanced) $res.render('template', { user })

Example Usage:

<%%js> // Return JSON API response $res.json({ success: true, message: 'User created' }); // Redirect after form submission if ($req.method === 'POST') { // ... process form ... return $res.redirect('/success'); } // Send error response $res.status(404).send('Page not found');

Session Object ($session)

The session object stores user-specific data that persists across requests. You can read and write any properties to it.

Property/Method Type Description
id string Unique session identifier (auto-generated)
userId any Example: Store authenticated user ID
username any Example: Store username
cart any Example: Store shopping cart items
* (any property) any You can store any custom data as session properties
$req.session.destroy(callback) method Destroy the entire session (logout)

Example Usage:

<%%js> // Read session data const userId = $session.userId; const cart = $session.cart || []; // Write session data (auto-saved) $session.userId = 123; $session.isAuthenticated = true; $session.cart = [...cart, newItem]; // Remove property delete $session.temporaryData; // Logout (destroy session) $req.session.destroy((err) => { $res.redirect('/'); });

Database Object ($db)

The database object provides methods for querying your PostgreSQL or MySQL database with connection pooling built-in.

Method Description
query(sql, params) Execute a single SQL query with optional parameters. Returns array of rows.
query([queries]) Execute multiple queries in sequence on the same connection. Returns array of results.
secureQuery(sql, params, varName, varValue) Execute query with session variables for Row-Level Security (RLS). Sets PostgreSQL session variables before query.
secureQuery(sql, params, {vars}) Execute query with multiple session variables for RLS.
getConnection() Get a raw connection from the pool for advanced use (transactions, etc.). Must call conn.release() when done.

Example Usage:

<%%js> // Simple query const users = await $db.query('SELECT * FROM users'); // Parameterized query (prevents SQL injection!) const user = await $db.query( 'SELECT * FROM users WHERE id = $1', [userId] ); // Multiple queries const [users, orders] = await $db.query([ { sql: 'SELECT * FROM users WHERE active = $1', params: [true] }, { sql: 'SELECT * FROM orders WHERE status = $1', params: ['pending'] } ]); // Secure query with RLS const orders = await $db.secureQuery( 'SELECT * FROM orders', [], 'session.accountcode', $session.accountcode );

⚠️ Important: Always use parameterized queries ($1, $2, etc.) to prevent SQL injection attacks. Never concatenate user input directly into SQL strings!

Cache Object ($cache)

The cache object provides in-memory caching to speed up your application by storing frequently accessed data.

Method Description
get(key) Get value from cache. Returns null if not found or expired.
set(key, value, ttl) Store value in cache with TTL in seconds.
remember(key, ttl, callback) Get from cache, or execute callback and cache result if not found. Recommended pattern!
cacheSelf(options) Cache entire component output. Options: expiresIn, busyLock, key. Returns true if cached version served.
delete(key) Remove specific item from cache.
flush() Clear all items from cache.
has(key) Check if key exists in cache (not expired).
getStats() Get cache statistics. Returns { store, size, defaultTTL }.

Example Usage:

<%%js> // Remember pattern (recommended) const users = await $cache.remember('all-users', 600, async () => { return await $db.query('SELECT * FROM users'); }); // Component caching (cache entire page) if (await $cache.cacheSelf({ expiresIn: '3 hours', busyLock: '10 sec' })) { return; // Cached version served } // Manual get/set let data = await $cache.get('mykey'); if (!data) { data = await expensiveOperation(); await $cache.set('mykey', data, 300); } // Invalidate cache when data changes await $db.query('UPDATE users SET name = $1 WHERE id = $2', [name, id]); await $cache.delete('all-users');

Version Object ($ver)

The version object contains version and Git information about your application, loaded from version.json.

Property Type Description Example Value
version string Semantic version number '1.2.3'
commit string Full Git commit hash 'abc123def456789...'
shortCommit string Short Git commit hash (first 7 chars) 'abc123d'
date string Build date in ISO 8601 format '2025-01-15T10:30:00Z'
branch string Git branch name 'main' or 'develop'

Common Use Cases:

  • Cache Busting: Append version to static asset URLs to force reload on updates
  • Footer Display: Show version and commit in page footer
  • Debugging: Include version in error logs to identify which code version caused issues
  • API Versioning: Include version in API responses

Example Usage:

<!-- Cache busting for CSS/JS --> <link rel="stylesheet" href="/css/styles.css?v=<%= $ver.shortCommit %>"> <script src="/js/app.js?v=<%= $ver.shortCommit "></script> <!-- Display in footer --> <footer> <p>Version <%= $ver.version (<%= $ver.shortCommit ) - Built <%= new Date($ver.date).toLocaleDateString() </p> </footer> <%%js> // Include in API response $res.json({ data: results, meta: { version: $ver.version, commit: $ver.shortCommit } });

Environment Variables ($env)

The environment object provides access to all environment variables from your .env file and system environment.

Common Variables Description Example Value
NODE_ENV Application environment 'development', 'production'
DB_HOST Database server hostname 'localhost'
DB_PORT Database server port '5432'
DB_USER Database username 'myuser'
DB_PASSWORD Database password 'secret123'
DB_NAME Database name 'myapp'
SESSION_SECRET Secret key for session encryption 'random-secret-key'
PORT Server port number '3000'
* (custom) Any custom environment variable you define -

Example Usage:

<%%js> // Check environment if ($env.NODE_ENV === 'production') { // Use production settings } else { // Use development settings } // Access database config const dbConfig = { host: $env.DB_HOST, port: $env.DB_PORT, user: $env.DB_USER }; // Custom variables const stripeKey = $env.STRIPE_API_KEY; const appName = $env.APP_NAME || 'My Application';

💡 Tip: Never commit your .env file to version control! Use .env.example with dummy values instead.

Context Object ($context)

The context object is the global context itself, providing custom data storage and component metadata.

Property/Method Description
set(key, value) Store custom data in context (shared across components)
get(key) Retrieve custom data from context
has(key) Check if key exists in context
componentPath Path to currently executing component (read-only)
autohandlers Array of autohandler paths in the chain (read-only)
dhandlerPath Path of dhandler that matched request, if any (read-only)

Example Usage:

<%%js> // Store page metadata $context.set('pageTitle', 'User Dashboard'); $context.set('breadcrumbs', ['Home', 'Users', 'Dashboard']); $context.set('user', { name: 'Alice', role: 'admin' }); // Retrieve in components or autohandlers const title = $context.get('pageTitle'); const user = $context.get('user'); // Check before using if ($context.has('user')) { const userName = $context.get('user').name; } // Component metadata console.log('Current component:', $context.componentPath); console.log('Autohandlers:', $context.autohandlers);

Context in Components

Pass data to components via context:

<!-- Parent page --> <%%js> $context.set('userName', 'Alice'); $context.set('showDetails', true); <%- await include('components/user-profile') %> <!-- components/user-profile.html --> <%%js> const userName = $context.get('userName'); const showDetails = $context.get('showDetails'); <div class="profile"> <h2><%= userName %></h2> <% if (showDetails) { <!-- Show details --> <% } </div>

Best Practices

  • Use $context.set() to share data across components
  • Access request data via $req instead of raw Express
  • Use descriptive keys for context data
  • Don't modify $req or $res directly (use helpers)
  • Store page metadata (title, description) in context

Database → Context Demo

Need more help?

View All Demos Getting Started GitHub Repository