Skip to main content

@adrper79-dot/content

CRUD content management with Neon Postgres and optional LLM-assisted generation. Depends on @adrper79-dot/neon and @adrper79-dot/copy.

Installation

npm install @adrper79-dot/content

Database

import { CREATE_CONTENT_TABLE } from '@adrper79-dot/content';
await db.execute(CREATE_CONTENT_TABLE);
Schema:
CREATE TABLE IF NOT EXISTS content (
  id          UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  app_id      TEXT NOT NULL,
  slug        TEXT NOT NULL,
  title       TEXT NOT NULL,
  body        TEXT NOT NULL,
  status      TEXT DEFAULT 'draft',
  author_id   TEXT,
  metadata    JSONB DEFAULT '{}',
  created_at  TIMESTAMPTZ DEFAULT now(),
  updated_at  TIMESTAMPTZ DEFAULT now(),
  UNIQUE (app_id, slug)
);

API

createContent(db, opts)

function createContent(db: Db, opts: {
  appId: string;
  slug: string;
  title: string;
  body: string;
  authorId?: string;
  metadata?: Record<string, unknown>;
}): Promise<Content>;

getContent(db, appId, slug)

function getContent(db: Db, appId: string, slug: string): Promise<Content | null>;

listContent(db, opts)

function listContent(db: Db, opts: {
  appId: string;
  status?: 'draft' | 'published';
  limit?: number;
  offset?: number;
}): Promise<Content[]>;

updateContent(db, id, updates)

function updateContent(
  db: Db,
  id: string,
  updates: Partial<Pick<Content, 'title' | 'body' | 'status' | 'metadata'>>,
): Promise<Content>;

publishContent(db, id)

function publishContent(db: Db, id: string): Promise<Content>;

Example

import { createContent, publishContent } from '@adrper79-dot/content';

const article = await createContent(db, {
  appId: 'focusbro',
  slug: 'getting-started-with-focus',
  title: 'Getting Started with Deep Focus',
  body: '<p>...</p>',
  authorId: user.id,
});

await publishContent(db, article.id);