New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

@echoes-io/models

Package Overview
Dependencies
Maintainers
1
Versions
6
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@echoes-io/models

TypeScript models and validation schemas for Echoes - Multi-POV storytelling platform. Provides shared types, interfaces, and Zod schemas.

latest
Source
npmnpm
Version
1.2.0
Version published
Maintainers
1
Created
Source

@echoes-io/models

TypeScript models and validation schemas for Echoes - a multi-POV digital storytelling platform.

Table of Contents

Overview

This package provides shared TypeScript interfaces, types, and validation schemas used across the Echoes ecosystem:

  • Timeline repositories (content storage)
  • Tracker service (content management and API)
  • RAG service (semantic search and AI context)
  • Web application (frontend)
  • CLI tools and utilities

Architecture Context

Echoes is organized as a multi-repository system:

@echoes-io/utils     # Shared utilities (markdown parsing, text stats)
@echoes-io/models    # This package - shared types and schemas
@echoes-io/tracker   # Content management API and database
@echoes-io/rag       # Semantic search and AI context
echoes-timeline-*    # Individual timeline content repositories
echoes-web-app       # Frontend application

Content Structure

Echoes organizes storytelling content in a hierarchical structure:

erDiagram
    Timeline ||--o{ Arc : contains
    Arc ||--o{ Episode : contains
    Episode ||--o{ Part : contains
    Episode ||--o{ Chapter : contains
    Part ||--o{ Chapter : "belongs to"
    
    Timeline {
        string name PK
        string description
    }
    
    Arc {
        string timelineName FK
        string name PK
        int number
        string description
    }
    
    Episode {
        string timelineName FK
        string arcName FK
        int number PK
        string slug
        string title
        string description
    }
    
    Part {
        string timelineName FK
        string arcName FK
        int episodeNumber FK
        int number PK
        string slug
        string title
        string description
    }
    
    Chapter {
        string timelineName FK
        string arcName FK
        int episodeNumber FK
        int partNumber FK
        int number PK
        string pov
        string title
        string date
        string summary
        string location
        string outfit "optional"
        string kink "optional"
        int words
        int characters
        int charactersNoSpaces
        int paragraphs
        int sentences
        int readingTimeMinutes
    }

Hierarchy

Timeline
  └─ Arc (ordered)
      └─ Episode (numbered)
          ├─ Part (numbered, optional subdivision)
          └─ Chapter (numbered, continuous within episode)

Note: Chapter numbering is continuous within an episode and does NOT reset per part.

File Structure Convention

timeline-repo/
├── content/
│   ├── <arc-name>/
│   │   └── <ep01-episode-title>/
│   │       └── <ep01-ch001-pov-title>.md

Naming Conventions:

  • Episode numbers: 2-digit padding (ep01, ep02, ep12)
  • Chapter numbers: 3-digit padding (ch001, ch005, ch123)
  • Slugification: lowercase, hyphens, no special characters
  • Example: content/introduction-arc/ep01-first-meeting/ep01-ch005-alice-first-meeting.md

Models

This package defines TypeScript interfaces for:

Core Content Models

  • Timeline - Root story container with name and description
  • Arc - Story arc within timeline with ordering
  • Episode - Episode within arc with numbering, slug, title, description
  • Part - Part within episode with numbering, slug, title, description
  • Chapter - Individual content file with metadata and stats (content stored in .md files)

Metadata Models

  • ChapterMetadata - Frontmatter structure for .md files:
    • Required fields: pov, title, date, timeline, arc, episode (number), part (number), chapter (number), summary, location
    • Optional fields: outfit, kink
  • TextStats - Text statistics from content analysis:
    • words, characters, charactersNoSpaces, paragraphs, sentences, readingTimeMinutes

Compatibility with @echoes-io/utils

This package provides the same interfaces as @echoes-io/utils but adds:

  • Database-ready models with IDs and relationships
  • Zod validation schemas for runtime type checking
  • API request/response types for the tracker service
  • Extended metadata for content management
// These interfaces match @echoes-io/utils exactly
import type { ChapterMetadata, TextStats } from '@echoes-io/models';

// These are new database models
import type { Timeline, Arc, Episode, Chapter } from '@echoes-io/models';

// These are new validation schemas
import { validateChapterMetadata, validateTimeline } from '@echoes-io/models';

Installation

npm install @echoes-io/models

Models Reference

Timeline

Root container for a story universe.

FieldTypeKeyDescription
namestringPKTimeline name (unique identifier)
descriptionstringTimeline description

Example:

const timeline: Timeline = {
  name: 'main-story',
  description: 'The primary storyline',
};

Arc

Story arc within a timeline. Represents major story phases (e.g., "Introduction", "Rising Action").

FieldTypeKeyDescription
timelineNamestringFK, PKTimeline name (foreign key)
namestringPKArc name
numbernumberArc order/number within timeline
descriptionstringArc description

Primary Key: (timelineName, name)

Example:

const arc: Arc = {
  timelineName: 'main-story',
  name: 'introduction',
  number: 1,
  description: 'The beginning of the story',
};

Episode

Episode within an arc. Represents story events or time periods.

FieldTypeKeyDescription
timelineNamestringFK, PKTimeline name (foreign key)
arcNamestringFK, PKArc name (foreign key)
numbernumberPKEpisode number (e.g., 1, 2, 3)
slugstringEpisode slug (URL-friendly)
titlestringEpisode title
descriptionstringEpisode description

Primary Key: (timelineName, arcName, number)

Example:

const episode: Episode = {
  timelineName: 'main-story',
  arcName: 'introduction',
  number: 1,
  slug: 'first-meeting',
  title: 'First Meeting',
  description: 'Alice and Bob meet for the first time',
};

Part

Part within an episode. Used for organizing longer episodes into subdivisions.

FieldTypeKeyDescription
timelineNamestringFK, PKTimeline name (foreign key)
arcNamestringFK, PKArc name (foreign key)
episodeNumbernumberFK, PKEpisode number (foreign key)
numbernumberPKPart number within episode
slugstringPart slug (URL-friendly)
titlestringPart title
descriptionstringPart description

Primary Key: (timelineName, arcName, episodeNumber, number)

Example:

const part: Part = {
  timelineName: 'main-story',
  arcName: 'introduction',
  episodeNumber: 1,
  number: 1,
  slug: 'morning',
  title: 'Morning',
  description: 'The morning scene',
};

Chapter

Individual content file (.md with frontmatter). Extends ChapterMetadata and TextStats from @echoes-io/utils.

Note: Chapter numbering is continuous within an episode and does NOT reset per part.

Structure:

interface Chapter extends ChapterMetadata, TextStats {
  timelineName: string;
  arcName: string;
  episodeNumber: number;
  partNumber: number;
  number: number;
}
FieldTypeKeyRequiredDescription
Database Keys
timelineNamestringFK, PKTimeline name (foreign key)
arcNamestringFK, PKArc name (foreign key)
episodeNumbernumberFK, PKEpisode number (foreign key)
partNumbernumberFKPart number (indicates which part the chapter belongs to)
numbernumberPKChapter number (unique within episode)
From ChapterMetadata
povstringPoint of view character
titlestringChapter title
datestringChapter date (free text, e.g., "2025-01-01 Monday")
timelinestringTimeline name (from frontmatter)
arcstringArc name (from frontmatter)
episodenumberEpisode number (from frontmatter)
partnumberPart number (from frontmatter)
chapternumberChapter number (from frontmatter)
summarystringBrief chapter description
locationstringChapter location/setting
outfitstringCharacter outfit description (optional)
kinkstringContent tags/kinks (optional)
From TextStats
wordsnumberTotal word count
charactersnumberTotal character count (including spaces)
charactersNoSpacesnumberCharacter count excluding spaces
paragraphsnumberNumber of paragraphs
sentencesnumberNumber of sentences
readingTimeMinutesnumberEstimated reading time in minutes (200 words/min)

Primary Key: (timelineName, arcName, episodeNumber, number)

Example:

const chapter: Chapter = {
  // Database keys
  timelineName: 'main-story',
  arcName: 'introduction',
  episodeNumber: 1,
  partNumber: 1,
  number: 1,
  // Metadata (from ChapterMetadata)
  pov: 'Alice',
  title: 'First Meeting',
  date: '2025-01-01 Monday',
  timeline: 'main-story',
  arc: 'introduction',
  episode: 1,
  part: 1,
  chapter: 1,
  summary: 'Alice meets Bob at the coffee shop',
  location: 'Coffee Shop',
  outfit: 'Blue dress', // optional
  kink: 'romance', // optional
  // Text statistics (from TextStats)
  words: 1000,
  characters: 5000,
  charactersNoSpaces: 4000,
  paragraphs: 10,
  sentences: 50,
  readingTimeMinutes: 5,
};

ChapterMetadata

Frontmatter structure for .md files. This is the source of truth that gets replicated into the database.

FieldTypeRequiredDescription
povstringPoint of view character
titlestringChapter title
datestringChapter date (free text, e.g., "2025-01-01 Monday")
timelinestringTimeline name
arcstringArc name
episodenumberEpisode number
partnumberPart number
chapternumberChapter number
summarystringBrief chapter description
locationstringChapter location/setting
outfitstringCharacter outfit description (optional)
kinkstringContent tags/kinks (optional)

Example:

const metadata: ChapterMetadata = {
  pov: 'Alice',
  title: 'First Meeting',
  date: '2025-01-01 Monday',
  timeline: 'main-story',
  arc: 'introduction',
  episode: 1,
  part: 1,
  chapter: 1,
  summary: 'Alice meets Bob at the coffee shop',
  location: 'Coffee Shop',
};

TextStats

Text statistics calculated from content analysis (via @echoes-io/utils).

FieldTypeDescription
wordsnumberTotal word count
charactersnumberTotal character count (including spaces)
charactersNoSpacesnumberCharacter count excluding spaces
paragraphsnumberNumber of paragraphs
sentencesnumberNumber of sentences
readingTimeMinutesnumberEstimated reading time in minutes (200 words/min)

Example:

const stats: TextStats = {
  words: 1000,
  characters: 5000,
  charactersNoSpaces: 4000,
  paragraphs: 10,
  sentences: 50,
  readingTimeMinutes: 5,
};

Usage

import { 
  Timeline, 
  Arc, 
  Episode, 
  Part, 
  Chapter, 
  ChapterMetadata,
  validateTimeline,
  validateChapter,
} from '@echoes-io/models';

// Type-safe content structures
const timeline: Timeline = {
  name: 'main-story',
  description: 'The primary storyline',
};

const arc: Arc = {
  timelineName: 'main-story',
  name: 'introduction',
  number: 1,
  description: 'The beginning of the story',
};

const episode: Episode = {
  timelineName: 'main-story',
  arcName: 'introduction',
  number: 1,
  slug: 'first-meeting',
  title: 'First Meeting',
  description: 'Alice and Bob meet for the first time',
};

const part: Part = {
  timelineName: 'main-story',
  arcName: 'introduction',
  episodeNumber: 1,
  number: 1,
  slug: 'morning',
  title: 'Morning',
  description: 'The morning scene',
};

const chapter: Chapter = {
  timelineName: 'main-story',
  arcName: 'introduction',
  episodeNumber: 1,
  partNumber: 1,
  number: 1,
  pov: 'Alice',
  title: 'First Meeting',
  date: '2025-01-01 Monday',
  timeline: 'main-story',
  arc: 'introduction',
  episode: 1,
  part: 1,
  chapter: 1,
  summary: 'Alice meets Bob at the coffee shop',
  location: 'Coffee Shop',
  words: 1000,
  characters: 5000,
  charactersNoSpaces: 4000,
  paragraphs: 10,
  sentences: 50,
  readingTimeMinutes: 5,
};

// Validation with Zod
try {
  validateTimeline(timeline);
  validateChapter(chapter);
  console.log('Valid!');
} catch (error) {
  console.error('Validation error:', error);
}

Development

Tech Stack

  • Language: TypeScript (strict mode)
  • Validation: Zod (planned)
  • Testing: Vitest
  • Linting: Biome

Scripts

# Run tests
npm test

# Type checking
npm run type-check

# Lint code
npm run lint

Integration

With @echoes-io/utils

  • Uses ChapterMetadata interface from this package
  • Provides validation for parsed frontmatter

With @echoes-io/tracker

  • Implements these models in database schema
  • Uses types for API endpoints and operations

With @echoes-io/rag

  • Uses models for content indexing
  • Provides types for semantic search results

License

MIT

Keywords

echoes

FAQs

Package last updated on 12 Dec 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts