Resources
Harper's Resource API is the foundation for building custom data access logic and connecting data sources. Resources are JavaScript classes that define how data is accessed, modified, subscribed to, and served over HTTP, MQTT, and WebSocket protocols.
What Is a Resource?
A Resource is a class that provides a unified interface for a set of records or entities. Harper's built-in tables extend the base Resource class, and you can extend either Resource or a table class to implement custom behavior for any data source — internal or external.
Added in: v4.2.0
The Resource API is designed to mirror REST/HTTP semantics: methods map directly to HTTP verbs (get, put, patch, post, delete), making it straightforward to build API endpoints alongside custom data logic.
Relationship to Other Features
- Database tables extend
Resourceautomatically. You can use tables through the Resource API without writing any custom code. - The REST plugin maps incoming HTTP requests to Resource methods. See REST Overview.
- The MQTT plugin routes publish/subscribe messages to
publishandsubscribeResource methods. See MQTT Overview. - Global APIs (
tables,databases,transaction) provide access to resources from JavaScript code. - The
jsResourceplugin (configured inconfig.yaml) registers a JavaScript file's exported Resource classes as endpoints.
Resource API Versions
The Resource API has two behavioral modes controlled by the loadAsInstance static property:
- V2 (recommended,
loadAsInstance = false): Instance methods receive aRequestTargetas the first argument; no record is preloaded ontothis. Recommended for all new code. - V1 (legacy,
loadAsInstance = true): Instance methods are called withthispre-bound to the matching record. Preserved for backwards compatibility.
The Resource API reference is written against V2. For V1 behavior and migration guidance, see the legacy instance binding section of that page.
Extending a Table
The most common use case is extending an existing table to add custom logic.
Starting with a table definition in a schema.graphql:
# Omit the `@export` directive
type MyTable @table {
id: Long @primaryKey
# ...
}
For more info on the schema API see
Database / Schema
Then, in a resources.js extend from the tables.MyTable global:
export class MyTable extends tables.MyTable {
static loadAsInstance = false; // use V2 API
async get(target) {
// add a computed property before returning
const record = await super.get(target);
return { ...record, computedField: 'value' };
}
post(target, data) {
// custom action on POST
this.create({ ...data, status: 'pending' });
}
}
Finally, ensure everything is configured appropriately:
rest: true
graphqlSchema:
files: schema.graphql
jsResource:
files: resources.js
Custom External Data Source
You can also extend the base Resource class directly to implement custom endpoints, or even wrap an external API or service as a custom caching layer:
export class CustomEndpoint extends Resource {
static loadAsInstance = false;
get(target) {
return {
data: doSomething(),
};
}
}
export class MyExternalData extends Resource {
static loadAsInstance = false;
async get(target) {
const response = await fetch(`https://api.example.com/${target.id}`);
return response.json();
}
put(target, data) {
return fetch(`https://api.example.com/${target.id}`, {
method: 'PUT',
body: JSON.stringify(data),
});
}
}
// Use as a cache source for a local table
tables.MyCache.sourcedFrom(MyExternalData);
Resources are the true customization point for Harper. This is where the business logic of a Harper application really lives. There is a lot more to this API than these examples show. Ensure you fully review the Resource API documentation, and consider exploring the Learn guides for more information.
Exporting Resources as Endpoints
Resources become HTTP/MQTT endpoints when they are exported. As the examples demonstrated if a Resource extends an existing table, make sure to not have conflicting exports between the schema and the JavaScript implementation. Alternatively, you can register resources programmatically using server.resources.set(). See HTTP API for server extension documentation.
Pages in This Section
| Page | Description |
|---|---|
| Resource API | Complete reference for instance methods, static methods, the Query object, RequestTarget, and response handling |
| Query Optimization | How Harper executes queries and how to write performant conditions |