Stone.jsDocs
Paradigm

Foundations

The uncertainty principle

The Continuum borrows its name from physics, and this is where the borrowing earns its keep. There is a real trade-off at the heart of every application, and most frameworks resolve it in the wrong direction.

#The trade-off, stated

A domain cannot, at the same time, know its execution context exactly and evolve independently of it.
The Continuum Architecture

Know the context too well, hard-code the server, the request object, the platform SDK, and you are coupled: the domain now ages with the platform. Ignore the context entirely and you fail the intent: code has to run somewhere, and pretending otherwise produces abstractions that do not fit any real runtime. Both extremes lose.

#The resolution

The principle

The way out is not to eliminate the uncertainty but to place it. Keep the where deliberately uncertain while you build the what, and resolve the where at the last responsible moment, through an abstraction that mediates between domain and platform.

This is an architectural stance you can adopt anywhere: a boundary whose job is to hold the platform at arm's length, so the core can move fast on meaning while the edge absorbs change.

In Stone.js

Stone.js places the uncertainty in the adapter and resolves it at runtime. The domain is written against an IncomingEvent, an intention, never a platform object. The adapter is the mediator that collapses a real cause into that intention.

So you build the what at full speed, and the where is decided when the adapter runs, not when you write the handler.

#What it looks like in practice

The domain reads meaning from the event. Whether the value arrived as a JSON body, a query string, a CLI flag or an agent argument is the adapter's problem, and stays the adapter's problem.

app/Tasks.tsts
@Post('/')
create (event) {
  // "title" is an intention. Its transport is unknown here, on purpose.
  const title = event.get('title')
  return this.store.add({ title })
}

#The two failure modes, in code

The trade-off is easiest to see side by side. Know the context too exactly and the handler is welded to one platform; hold it uncertain and the same handler runs anywhere.

coupled-vs-deferred.tsts
// Coupled: knows the platform exactly. Runs on Node, and only Node.
create (req, res) {
  res.status(201).json(store.add({ title: req.body.title }))   // Express-shaped, forever
}

// Deferred: reads an intention, returns a value. Runs on every context.
create (event) {
  return store.add({ title: event.get('title') })              // no platform in sight
}

Stone.js

Your app exists in every runtime. Until you run it.

An open-source project by Stone Foundation
Created by Mr. Stone (Evens Pierre)