Skip to content
reaatechREAATECH

@reaatech/prompt-version-control-shared

pending npm

Provides shared TypeScript types, Zod schemas, and utility functions for validating, checksumming, and rendering prompt templates within the Prompt Version Control ecosystem. It exports a collection of Zod schemas for runtime validation and Handlebars-based helpers for prompt interpolation and variable analysis.

@reaatech/prompt-version-control-shared

npm version License: MIT CI

Status: Pre-1.0 — APIs may change in minor versions. Pin to a specific version in production.

Canonical TypeScript types, Zod schemas, and shared utilities for Prompt Version Control. This package is the single source of truth for all protocol shapes used throughout the @reaatech/prompt-version-control-* ecosystem.

Installation

terminal
npm install @reaatech/prompt-version-control-shared
# or
pnpm add @reaatech/prompt-version-control-shared

Feature Overview

  • 25+ Zod schemas — runtime validation for API inputs and outputs
  • Fully inferred types — every schema exports a matching z.infer<typeof> type for compile-time safety
  • Template rendering — Handlebars-based prompt interpolation with variable tracking and missing-variable analysis
  • API key utilities — SHA-256 hashing, HMAC with pepper, and pvc_ prefix key generation
  • Checksumming — SHA-256 content checksums for deduplication and diffing
  • Zero runtime dependencies beyond zod and handlebars — lightweight and tree-shakeable

Quick Start

typescript
import {
  CreatePromptSchema,
  calculateChecksum,
  renderTemplate,
  generateApiKey,
  type Prompt,
} from "@reaatech/prompt-version-control-shared";
 
// Validate at the boundary
const raw = JSON.parse(inputJson);
const input = CreatePromptSchema.parse(raw);
 
// Hash prompt content
const checksum = calculateChecksum("You are a helpful assistant. Help with: {{topic}}");
 
// Render a template with variables
const result = renderTemplate(
  "Hello, {{name}}! Your order #{{orderId}} is ready.",
  { name: "Alice", orderId: "12345" }
);
console.log(result.rendered);            // "Hello, Alice! Your order #12345 is ready."
console.log(result.variablesUsed);       // ["name", "orderId"]
console.log(result.missingVariables);    // [] (all provided)
 
// Generate an API key
const apiKey = generateApiKey("my-pepper");
// Returns: { key: "pvc_abc123...", prefix: "pvc_", hash: "<hmac>" }

Exports

Zod Schemas

All schemas are exported as both a schema (for runtime validation) and an inferred type (for TypeScript). Use the schema for parsing, the type for annotating.

Core Schemas

SchemaDescription
IdSchemaz.string().cuid2() — common ID validator
PaginationSchema{ limit, cursor } — cursor-based pagination params
PaginatedResponseSchema(item)Factory producing { data: T[], meta: { limit, nextCursor?, total? } }

Projects

SchemaDescription
CreateProjectSchema{ name, slug, settings? }
ProjectSchemaFull project with id, timestamps

Prompts & Versions

SchemaDescription
CreatePromptSchema{ name, description?, template, variables?, metadata? }
UpdatePromptSchemaPartial of Create, omitting name
PromptSchemaFull prompt: id, projectId, name, template, archived, timestamps
CreateVersionSchema{ content, template, variables?, metadata? }
VersionSchemaFull version: id, promptId, number, checksum, timestamps

Tags

SchemaDescription
TagNameSchemaz.enum(['draft', 'staging', 'production'])
MoveTagSchema{ versionId } — move a tag to a specific version
TagSchemaFull tag: promptId, name, versionId, movedAt

Diffing

SchemaDescription
DiffRequestSchema{ fromVersion, toVersion }
DiffSectionSchema`{ type: ‘added'
DiffResultSchema`{ fromVersion, toVersion, sections: DiffSection[], semanticImpact: ‘none'

Evaluations

SchemaDescription
EvalStatusSchemaz.enum(['pending', 'running', 'passed', 'failed', 'error'])
EvaluationSchemaFull evaluation: id, versionId, status, results, timestamps

Metrics

SchemaDescription
MetricTypeSchemaz.enum(['cost', 'latency', 'quality'])
IngestMetricSchema{ versionId, type, name, value, unit, timestamp?, dimensions? }
MetricSchemaFull metric: id, versionId, type, name, value, unit, timestamps

API Keys

SchemaDescription
CreateApiKeySchema{ name, permissions?, expiresAt? }
ApiKeySchemaFull key: id, name, prefix, permissions, expiresAt, timestamps

App-Level Interfaces

InterfaceDescription
AppErrorDetails{ code, status, message, details? } — structured error shape
AuditLogEntryFull audit trail record with actor, action, resource, and payload diffs
PromotionResult{ allowed, reason?, evaluations? } — eval-gated promotion outcome
TemplateVariable`{ type: ‘string'
RenderedPrompt{ version, content, rendered, variablesUsed, missingVariables, metadata }

Utility Functions

FunctionSignatureDescription
calculateChecksum(content: string) => stringSHA-256 hex hash of content
hashApiKey(key: string, pepper?: string) => stringHMAC-SHA-256 with optional pepper
generateApiKey(pepper?: string) => { key, prefix, hash }Generate pvc_-prefixed API key
sleep(ms: number) => Promise<void>Promise-based delay
pick<T, K>(obj: T, keys: K[]) => Pick<T, K>Utility object picker

Template Rendering

ExportDescription
renderTemplate(template, variables?)Handlebars interpolation with noEscape. Returns { rendered: string, variablesUsed: string[], missingVariables: string[] }
RenderTemplateResultReturn type of renderTemplate

Usage Patterns

Schema + Type Pairing

Every schema has a matching type. Use the schema at boundaries and the type everywhere else:

typescript
import { VersionSchema, type Version } from "@reaatech/prompt-version-control-shared";
 
function handleResponse(raw: unknown): Version {
  // Parse at the boundary — throws ZodError on invalid data
  return VersionSchema.parse(raw);
}

Template Rendering

typescript
import { renderTemplate } from "@reaatech/prompt-version-control-shared";
 
const result = renderTemplate(
  "You are a {{role}}. Respond to: {{query}}",
  { role: "support agent" }
);
 
// result.rendered === "You are a support agent. Respond to: "
// result.variablesUsed === ["role"]
// result.missingVariables === ["query"]  ← not provided, highlighted for debugging

API Key Generation & Verification

typescript
import { generateApiKey, hashApiKey } from "@reaatech/prompt-version-control-shared";
 
const pepper = process.env.API_KEY_PEPPER;
 
// Generate a new key
const { key, prefix, hash } = generateApiKey(pepper);
// Store `hash` in the database, return `key` to the user once
 
// Verify an incoming key
const incomingHash = hashApiKey(incomingKey, pepper);
const storedKey = await db.apiKey.findUnique({ where: { hash: incomingHash } });

Checksum-Based Deduplication

typescript
import { calculateChecksum } from "@reaatech/prompt-version-control-shared";
 
const content = "You are a helpful assistant. Help with: {{topic}}";
const checksum = calculateChecksum(content);
 
// Only create a new version if content actually changed
const existing = await db.version.findFirst({ where: { promptId, checksum } });
if (existing) {
  console.log(`Content unchanged — existing version: ${existing.number}`);
  return existing;
}

License

MIT