@lde/fastify-rdf
v0.4.4
Published
Fastify plugin for serving RDF data with content negotiation
Downloads
618
Readme
Fastify RDF
Fastify plugin for serving RDF data with automatic content negotiation.
Installation
npm install @lde/fastify-rdfFeatures
- Content negotiation for all RDF serialisation formats supported by rdf-serialize
- Handles
Acceptheaders to serve data in the requested RDF format (Turtle, N-Triples, JSON-LD, etc.) - Defaults to Turtle when no
Acceptheader is provided - Provides a
reply.sendRdf()decorator for explicit RDF responses - Optional
overrideSendmode to automatically serialise all responses as RDF
Usage
Basic Setup
import fastify from 'fastify';
import fastifyRdf from '@lde/fastify-rdf';
const app = fastify();
await app.register(fastifyRdf);Explicit RDF Responses with reply.sendRdf()
Use reply.sendRdf() to send RDF data with content negotiation:
import { Store, DataFactory } from 'n3';
const { namedNode, literal, quad } = DataFactory;
app.get('/resource', async (request, reply) => {
const store = new Store();
store.add(
quad(
namedNode('http://example.org/subject'),
namedNode('http://example.org/predicate'),
literal('object'),
),
);
return reply.sendRdf(store);
});Automatic Serialisation with overrideSend
Enable overrideSend to automatically serialise all responses as RDF. This is useful for APIs that exclusively serve RDF data:
await app.register(fastifyRdf, {
overrideSend: true,
});
// Simply return DatasetCore or Stream - they will be serialised automatically
app.get('/resource', async () => {
const store = new Store();
store.add(
quad(
namedNode('http://example.org/subject'),
namedNode('http://example.org/predicate'),
literal('object'),
),
);
return store;
});Parsing RDF Request Bodies
The plugin registers content type parsers for all RDF formats supported by rdf-parse. Individual routes opt in via config: { parseRdf: true } — the body is then parsed into a DatasetCore:
app.post('/data', { config: { parseRdf: true } }, async (request) => {
const dataset = request.body as DatasetCore; // N3 Store
console.log(`Received ${dataset.size} quads`);
});To parse RDF bodies on all routes, enable parseRdf at the plugin level:
await app.register(fastifyRdf, { parseRdf: true });Routes without per-route or plugin-level parseRdf get JSON fallback for application/ld+json (parsed as plain JSON) and 415 Unsupported Media Type for other RDF content types.
Hydra Error Responses with reply.sendHydraError()
Send Hydra error responses with content negotiation. This maps error.message to hydra:title and error.cause (when it is a string) to hydra:description:
app.get('/resource', async (request, reply) => {
const error = new Error('Not Found', {
cause: 'The requested dataset was not found',
}) as Error & { statusCode: number };
error.statusCode = 404;
return reply.sendHydraError(error);
});The status code is taken from error.statusCode (standard in Fastify and http-errors), defaulting to 500.
For Accept: application/ld+json, the response is compact JSON-LD — no jsonld dependency needed:
{
"@context": "http://www.w3.org/ns/hydra/core#",
"@type": "Error",
"title": "Not Found",
"description": "The requested dataset was not found"
}For all other RDF formats (Turtle, N-Triples, etc.), the error is serialised through the standard RDF pipeline.
Custom Default Content Type
By default, the plugin uses text/turtle when no Accept header is provided. You can change this:
await app.register(fastifyRdf, {
defaultContentType: 'application/n-triples',
});Content Negotiation
The plugin supports all content types provided by rdf-serialize, including:
text/turtle(Turtle)application/n-triples(N-Triples)application/n-quads(N-Quads)application/ld+json(JSON-LD)application/rdf+xml(RDF/XML)- And more...
Clients can request their preferred format via the Accept header:
# Request Turtle
curl -H "Accept: text/turtle" http://localhost:3000/resource
# Request N-Triples
curl -H "Accept: application/n-triples" http://localhost:3000/resource
# No Accept header - defaults to Turtle
curl http://localhost:3000/resourceAPI
Plugin Options
interface FastifyRdfOptions {
/**
* Default content type when no Accept header is provided.
* @default 'text/turtle'
*/
defaultContentType?: string;
/**
* Override reply.send() to serialise all responses as RDF.
* When enabled, all payloads returned from route handlers will be
* serialised as RDF without type checking.
* @default false
*/
overrideSend?: boolean;
/**
* Parse RDF request bodies into a DatasetCore on all routes.
* @default false
*/
parseRdf?: boolean;
}Supported Data Types
The plugin accepts the following RDF data types:
- DatasetCore: RDF.js dataset (e.g., from n3
Store) - Stream: RDF.js quad stream (e.g., from parsers)
import type { RdfData, FastifyRdfOptions } from '@lde/fastify-rdf';TypeScript
The plugin includes full TypeScript support with type augmentation for Fastify's reply object:
// reply.sendRdf() is automatically typed
app.get('/data', async (request, reply) => {
return reply.sendRdf(dataset);
});