npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@ogentx/store

v0.1.2

Published

Shared persistence layer for OgentDoc - provides PackagePersist and DatabaseServiceResolver for both Engine and Hub

Readme

@ogentx/store

Shared persistence layer for OgentDoc - provides PackagePersist and DatabaseServiceResolver for both Engine and Hub services.

Overview

This package implements the core persistence logic for OgentDoc packages and services. It is designed to be framework-agnostic and works with any Prisma-compatible client through the StorePrismaClient interface.

Key Features

  • Package & Service Persistence: Upsert operations with business logic
  • Revision History: Complete version control for OgentDoc files
  • Service Inheritance: Resolve and merge parent service definitions
  • Skill, Dependency, Implementer Management: Full CRUD operations
  • Schema Definitions: Package-level schema management

Installation

pnpm add @ogentx/store

Quick Start

import { PackagePersist, StorePrismaClient } from '@ogentx/store';
import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();
const store = new PackagePersist(prisma as unknown as StorePrismaClient);

// Create a package revision
const revision = await store.createPackageRevision({
  packageId: 123,
  rawMarkdown: '# My Package\n...',
  version: '1.0.0',
  changeLog: 'Initial version',
});

// Get revision history
const revisions = await store.getPackageRevisions({
  packageId: 123,
  limit: 50,
});

Architecture

Layer Architecture

┌─────────────────────────────────────────────────────────────┐
│                      Hub / Engine REST API                    │
│  Controllers handle HTTP requests/responses                   │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                   Service Layer (NestJS)                      │
│  - Transaction support via @nestjs-cls/transactional         │
│  - Tenant context via ABAC                                    │
│  - Delegates business logic to PackagePersist                 │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│              Store Layer (PackagePersist)                     │
│  - ALL business logic for package/service persistence         │
│  - Revision history management                                │
│  - Inheritance resolution and merging                         │
│  - Framework-agnostic (works with any Prisma client)          │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                    Database (PostgreSQL)                      │
│  Package, Service, Skill, Dependency, Implementer, etc.       │
│  PackageRevision (revision history)                           │
└─────────────────────────────────────────────────────────────┘

Why This Architecture?

  1. Single Source of Truth: All business logic lives in PackagePersist
  2. Reusability: Both Engine and Hub use the same persistence logic
  3. Testability: Easy to unit test with mock Prisma clients
  4. Maintainability: Changes to business logic only need to be made once

Core Concepts

1. Document-Level Revision

Key Principle: Revision is at the OgentDoc.md file level, not at the database model level.

OgentDoc.md (Source of Truth)
    ↓
PackageRevision.rawMarkdown (Snapshot)
    ↓
Parse → PackageAST → DB Models (Package, Service, Skill, etc.)

Why Document-Level?

  • ✅ Users work with complete .md files
  • ✅ Preserves document structure and comments
  • ✅ Simple and reliable
  • ✅ Easy to restore and compare

2. Revision Lifecycle

1. User creates/updates OgentDoc.md
    ↓
2. CLI/API sends rawMarkdown + AST to Hub
    ↓
3. Hub creates PackageRevision (before updating DB)
    ↓
4. Hub parses and persists to DB models
    ↓
5. If release, mark revision as released

3. Business Rules

Released Package Immutability

  • Immutable fields: name, version, license, releasedAt, org
  • Mutable fields: desc, author (metadata only)
  • Released packages cannot be deleted and recreated

Released Service Immutability

  • Immutable fields: org, slug, version, inheritedId, visibility, releasedAt
  • Mutable fields: name, desc, docs (display information only)
  • Changes to immutable fields would break dependent services

API Reference

Revision History Methods

createPackageRevision

Create a new package revision. This method should be called BEFORE updating the package in DB.

Features:

  • Automatic revision number increment
  • Content deduplication (skip if identical to previous)
  • SHA-256 hash computation
const revision = await store.createPackageRevision({
  packageId: 123,
  rawMarkdown: '# My Package\n...',
  version: '1.0.0',
  changeLog: 'Added new service', // Optional
  wasReleased: false, // Optional, default: false
});

Returns: The created revision record, or the previous revision if content is identical.

getPackageRevisions

Get package revision history with pagination.

Performance: Does NOT load rawMarkdown by default (for performance).

const revisions = await store.getPackageRevisions({
  packageId: 123,
  limit: 50, // Optional, default: 50
  offset: 0, // Optional, default: 0
  releasedOnly: false, // Optional, default: false
});

Returns: Array of revision records (without rawMarkdown).

getPackageRevision

Get a specific package revision with full content.

const revision = await store.getPackageRevision(123, 5);
console.log(revision.rawMarkdown); // Complete .md content

Returns: The revision record with rawMarkdown, or null if not found.

comparePackageRevisions

Compare two package revisions and get a unified diff.

const diff = await store.comparePackageRevisions({
  packageId: 123,
  fromRevision: 3,
  toRevision: 5,
});

console.log(diff.patch); // Unified diff format
console.log(diff.additions); // Number of added lines
console.log(diff.deletions); // Number of deleted lines

Returns: Diff result with patch and statistics.

restorePackageRevision

Restore package to a specific revision.

IMPORTANT: This creates a NEW revision with the old content. It does NOT modify history.

const pkg = await store.restorePackageRevision({
  packageId: 123,
  revision: 3,
  changeLog: 'Restored from revision 3', // Optional
});

Process:

  1. Load the historical rawMarkdown
  2. Validate content hash
  3. Create new revision with old content
  4. Update package version

Returns: The restored package record.

Package & Service Methods

upsertPackageFromAST

Upsert a package from an OgentDoc AST with business logic.

const pkg = await store.upsertPackageFromAST({
  ast: myPackageAST,
  tenantId: 1,
  org: 'acme',
  releasedAt: new Date(), // Optional
});

upsertServiceFromAST

Upsert a service from an OgentDoc AST with business logic.

const service = await store.upsertServiceFromAST({
  packageId: 1,
  service: myServiceAST,
  ast: myPackageAST,
  tenantId: 1,
  org: 'acme',
});

resolveAndMergeInheritance

Resolve and merge inheritance for a service.

const merged = await store.resolveAndMergeInheritance({
  service: {
    slug: 'email-pro',
    inherits: { org: 'acme', service: 'email', version: '1.0.0' },
    skills: [...]
  },
  tenantSlug: 'acme'
});

Other Methods

  • upsertPackage() - Upsert a package
  • upsertService() - Upsert a service
  • upsertSkills() - Upsert skills for a service
  • upsertDependencies() - Upsert dependencies for a service
  • upsertImplementers() - Upsert implementers for a service
  • upsertSchemas() - Upsert schema definitions for a package
  • deletePackageCascade() - Delete a package and all related entities
  • deleteServiceCascade() - Delete a service and all related entities

Performance Optimization

Content Deduplication

// Content hash is computed automatically
// If content is identical to previous revision, no new revision is created
const revision1 = await store.createPackageRevision({
  packageId: 123,
  rawMarkdown: '# My Package',
  version: '1.0.0',
});

// This will return revision1 (no new revision created)
const revision2 = await store.createPackageRevision({
  packageId: 123,
  rawMarkdown: '# My Package',
  version: '1.0.0',
});

expect(revision1.id).toBe(revision2.id);

Lazy Loading

// List queries don't load rawMarkdown (performance)
const revisions = await store.getPackageRevisions({ packageId: 123 });

// Get specific revision loads full content
const revision = await store.getPackageRevision(123, 5);
console.log(revision.rawMarkdown); // Available

Error Handling

All methods throw descriptive errors for common scenarios:

// Revision not found
await store.getPackageRevision(123, 999);
// Error: Revision not found

// Content corruption
await store.restorePackageRevision({ packageId: 123, revision: 1 });
// Error: Revision content corrupted: hash mismatch

// Package not found
await store.restorePackageRevision({ packageId: 999, revision: 1 });
// Error: Package 999 not found

// Circular inheritance
await store.resolveAndMergeInheritance({ ... });
// Error: Circular inheritance detected

Testing

Run tests:

pnpm test

Run tests in watch mode:

pnpm test:watch

Development

Build:

pnpm build

Type check:

pnpm typecheck

Lint:

pnpm lint

Type Definitions

PackageRevisionRecord

interface PackageRevisionRecord {
  id: number;
  packageId: number;
  revision: number;
  rawMarkdown: string;
  version: string;
  changeLog?: string;
  wasReleased: boolean;
  contentHash: string;
  createdBy: number;
  createdAt: Date;
  tenantId_: number;
}

RevisionDiff

interface RevisionDiff {
  from: number;
  to: number;
  patch: string;
  additions: number;
  deletions: number;
}

StorePrismaClient

interface StorePrismaClient {
  package: IPackageDelegate;
  service: IServiceDelegate;
  skill: ISkillDelegate;
  dependency: IDependencyDelegate;
  implementer: IImplementerDelegate;
  schemaDef: ISchemaDefDelegate;
  packageRevision: IPackageRevisionDelegate;
}

License

Apache-2.0