Crescent.js logoCrescent.jsv1.0.3
Guides

Backend Guide

Write server-side logic with functions, conditionals, loops, and API endpoints.

Functions

Functions are the core of your backend logic. Define a function with a unique function_id, a list of params, and a body that executes when it is called.

functions.js
crescent.function({
  function_id: 'greet_user',
  params: ['name', 'age'],
  body: function (name, age) {
    return 'Hello ' + name + '! You are ' + age + ' years old.';
  }
});

// Call the function
crescent.get_function('greet_user').call('Alice', 25);

Reusable logic

Functions are stored by function_id and can be retrieved anywhere with crescent.get_function(). Define them once and call them from any page or API endpoint.

Conditionals

Branch your logic using crescent.conditional(). Each branch has a check function and a list of actions to run when it passes.

conditionals.js
function grant_access() { console.log('Access granted'); }
function limited_access() { console.log('Limited access'); }
function deny_access() { console.log('Access denied'); }

const check = crescent.conditional({
  conditional_id: 'age_gate',
  if: {
    check: function () { return age >= 18; },
    actions: [grant_access]
  },
  else_if: [
    {
      check: function () { return age >= 13; },
      actions: [limited_access]
    }
  ],
  else: {
    actions: [deny_access]
  }
});

check.evaluate();

Branch checks

A check is any function that returns true or false. If it returns a conditional instance, its evaluate() result is used instead.

Loops

Iterate over collections with crescent.loop(). Use loop_type: 'for_in' to iterate an array, or 'for'/'while' for counter-driven loops. Call run() to execute and collect results.

loops.js
const loop = crescent.loop({
  loop_id: 'render_items',
  loop_type: 'for_in',
  iterable: ['apple', 'banana', 'cherry'],
  actions: [
    function (item) {
      console.log(item);
    }
  ]
});

loop.run();

// Counter loop: 0, 1, 2, ..., 9
crescent.loop({
  loop_id: 'count_to_ten',
  loop_type: 'for',
  start: 0,
  end: 10,
  step: 1,
  actions: [
    function (i) { console.log(i); }
  ]
}).run();

API Endpoints

Create an HTTP server with crescent.api_make(), register endpoints with add_endpoint(), and start listening with start().

apis.js
const api = crescent.api_make({
  api_id: 'main',
  port: 3000
});

api.add_endpoint('GET', '/users', function (req, res) {
  res.writeHead(200, { 'Content-Type': 'application/json' });
  res.end(JSON.stringify({ users: ['Alice', 'Bob'] }));
});

api.add_endpoint('POST', '/users', function (req, res) {
  res.writeHead(200, { 'Content-Type': 'application/json' });
  res.end(JSON.stringify({ created: true, user: req.body }));
});

api.start();

Request handling

Handlers are Node.js HTTP handlers. Write a response with res.writeHead() and res.end(). Incoming JSON bodies are parsed into req.body for you.

Combining It All

Functions, conditionals, loops, and APIs compose together. A common pattern is an API endpoint that validates input with a function and returns the result.

full-example.js
// Create a backend function
crescent.function({
  function_id: 'validate_email',
  params: ['email'],
  body: function (email) {
    return email.includes('@');
  }
});

// Use it in an API endpoint
const api = crescent.api_make({
  api_id: 'main',
  port: 3000
});

api.add_endpoint('POST', '/signup', function (req, res) {
  const valid = crescent.get_function('validate_email').call(req.body.email);
  res.writeHead(valid ? 200 : 400, { 'Content-Type': 'application/json' });
  res.end(JSON.stringify(valid ? { status: 'ok' } : { error: 'Invalid email address' }));
});

api.start();

Next Steps