Back to the documentation

Integration

Read and write Pod data with drizzle-solid

The official README's minimal read/write path, put in order, and an explicit note that we have not executed the example.

This page turns the official README’s minimal read/write path into an order you can follow, and marks the prerequisite for each step.

To be clear up front: we have not executed the example below. Package names, types, commands, and example code are quoted from the official repository’s README and documentation. We did not install the package, connect to a Pod, or run examples/01-quick-start.ts. We cannot confirm for you whether it runs or what it prints. To verify, go to the official sources listed here.

Which version, and where to install it

  • Package: @undefineds.co/drizzle-solid. Note the scope is @undefineds.co, not an unscoped package with a similar name.

  • Version: 0.3.24 was the latest published version when we checked.

  • Dependency: drizzle-orm.

  • The official install source is npm. The README gives two forms:

    npm install @undefineds.co/drizzle-solid drizzle-orm
    
    # optional: install when your app wants the built-in SPARQL engine
    npm install @comunica/query-sparql-solid
    yarn add @undefineds.co/drizzle-solid drizzle-orm
    
    # optional: install when your app wants the built-in SPARQL engine
    yarn add @comunica/query-sparql-solid
  • @comunica/query-sparql-solid is an optional peer dependency. The current supported line is 4.x; 3.x is outside the supported matrix. If your runtime already ships Comunica, the official guidance is to inject that engine instead of installing a second copy.

  • npm page: https://www.npmjs.com/package/@undefineds.co/drizzle-solid

Prerequisite: an authenticated session

In the official quickstart, both pod(session) and drizzle(session) take a session. That means you need an existing session that is connected to the target Pod and already authenticated.

  • Where the Pod comes from: your own Xpod deployment, or another Solid service. Deployment steps are in Self-host Xpod; compatibility with the current version depends on the versions the example uses.
  • Where the session comes from: the official installation guide at docs/guides/installation.md. We have not run the authentication flow, so there is no guessed sign-in command here.
  • The application works with one specific user’s identity and permissions, and reads and writes are subject to the Pod’s access control. That is covered in Storage, access, and migration.

Where reads and writes land

Every model describes both its shape and its placement. The three fields in the official README:

  • base: where documents live, for example https://alice.example/data/posts/.
  • id: a base-relative resource id such as post-1.ttl, or a fragment form such as chat-1/messages.ttl#msg-1.
  • type: the primary rdf:type used when writing.

subjectTemplate is deprecated and kept only for legacy layouts. New schemas should store the exact resource path in the id column.

There is also a rule the official README calls “the most important runtime rule”: use collection reads for lists and filters, namely client.collection(table).list(...), db.select().from(table)..., and db.query.<resource>.findMany(...); use the exact-target helpers when you mean one concrete entity, namely client.entity(resource, iri), findById, findByIri, updateById, deleteById, updateByIri, and deleteByIri. Do not use where({ id: ... }) or where(eq(table.id, ...)) as a shortcut for exact lookup.

The official minimal example

Below is the official README’s Quick start, quoted as-is. We have not run it:

import { pod, podTable, string, datetime } from '@undefineds.co/drizzle-solid';

const posts = podTable('posts', {
  id: string('id').primaryKey(),
  title: string('title').predicate('http://schema.org/headline'),
  content: string('content').predicate('http://schema.org/text'),
  createdAt: datetime('createdAt').predicate('http://schema.org/dateCreated'),
}, {
  base: 'https://alice.example/data/posts/',
  type: 'http://schema.org/CreativeWork',
});

const client = pod(session);
await client.init(posts);

const created = await client.collection(posts).create({
  id: 'post-1.ttl',
  title: 'Hello Solid',
  content: 'Stored as RDF in a Pod document.',
  createdAt: new Date(),
});

if (!created) {
  throw new Error('Create failed');
}

const post = client.entity(posts, created['@id']);

console.log(await post.get());
await post.update({ title: 'Updated title' });
await post.delete();

If you prefer the Drizzle shape, the README also gives a drizzle(session) version using insert(posts).values(...), findById, updateById, and deleteById.

What this example does

This explanation comes only from reading the code; it is not a report of a successful run:

  • Write: client.collection(posts).create(...) writes a post-1.ttl document under base, with fields mapped to RDF predicates through predicate.
  • Read back: client.entity(posts, created['@id']) targets the record just created, and post.get() reads it.
  • Update and delete: post.update({ title: 'Updated title' }) and post.delete().
  • Failure path: the example uses if (!created) throw new Error('Create failed') for the case where the write returns nothing.

Status: none of this is verified by us