Stone.jsDocs
Paradigm

Extensions

Resources

Your internal model and your public representation are not the same thing. A resource is the deliberate projection between them: the place where you decide, once, what the world sees and what stays private.

#Install

terminalbash
npm i @stone-js/resources

#Define the projection

The principle

Returning raw models leaks internals and couples your API to your storage. A resource draws a stable line between the two, so the model can change without breaking the contract, and secrets never slip out by accident.

In Stone.js

defineResource(transform) declares the projection. Use .item()for one model and .collection() for many; sparse fieldsets, conditional fields and the { data, meta } envelope are handled for you.

app/resources.tsts
import { defineResource, only } from '@stone-js/resources'

export const taskResource = defineResource((task) => ({
  id: task.id,
  title: task.title,
  done: task.done,
  createdAt: task.createdAt.toISOString()
  // note: no ownerId, no internal flags. The projection is the contract.
}))

#Using it in a handler

app/Tasks.tsts
@Get('/')
list () {
  return taskResource.collection(this.tasks.list())         // many
}

@Get('/:id')
show (event) {
  return taskResource.item(this.tasks.find(event.get('id')), only(['id', 'title']))  // sparse
}

#Helpers

HelperTypeDescription
.item(model, ctx?)oneProject a single model.
.collection(models, ctx?)manyProject an array of models.
.envelope(...)wrapWrap the result in a { data, meta } envelope.
only([...]) / except([...])fieldsSparse fieldsets: include or drop fields.
whenIncluded(ctx, key, fn)conditionalInclude related data only when requested.

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)