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

neogm

v2.0.7

Published

TypeScript-first Neo4j Object Graph Mapper (OGM) for building type-safe graph database applications

Downloads

19

Readme

NeoGM - Neo4j Object Graph Mapper

A TypeScript-first Neo4j ORM with decorator-based entities for building type-safe graph database applications. NeoGM provides an intuitive, modern API for working with Neo4j databases while maintaining full type safety and excellent developer experience.

Features

  • Decorator-Based Entities: Modern @Node, @Property, @Relationship decorators for clean entity definitions
  • TypeScript Native: Built from the ground up with TypeScript for excellent type safety and developer experience
  • Repository Pattern: Type-safe data access with built-in CRUD operations
  • Advanced Query Builder: Fluent API for building complex Cypher queries
  • Transaction Support: Full transaction handling with rollback capabilities
  • Validation & Transformation: Built-in data validation and transformation pipeline
  • Graph-First: Designed specifically for graph database patterns and workflows
  • Production Ready: Comprehensive test suite with 107 tests and 95%+ coverage

Installation

npm install neogm reflect-metadata
# or
yarn add neogm reflect-metadata

Quick Start

1. Define Your Entities

import { Node, Property, Relationship, BaseEntity } from 'neogm';
import 'reflect-metadata';

@Node('Person')
class Person extends BaseEntity {
  @Property({ required: true })
  name!: string;

  @Property({ 
    validator: (email: string) => email.includes('@')
  })
  email!: string;

  @Property()
  age?: number;

  @Relationship({ type: 'WORKS_FOR', direction: 'OUT', target: () => Company })
  employer?: Company;

  @Relationship({ type: 'FOLLOWS', direction: 'OUT', target: () => Person })
  following?: Person[];
}

@Node('Company')
class Company extends BaseEntity {
  @Property({ required: true })
  name!: string;

  @Property()
  industry?: string;

  @Relationship({ type: 'WORKS_FOR', direction: 'IN', target: () => Person })
  employees?: Person[];
}

2. Connect and Use

import { NeoGM } from 'neogm';

// Initialize connection
const neogm = new NeoGM({
  uri: 'bolt://localhost:7687',
  user: 'neo4j',
  password: 'your-password',
  database: 'neo4j'  // optional
});

await neogm.connect();

// Get repositories
const personRepo = neogm.getRepository(Person);
const companyRepo = neogm.getRepository(Company);

// Create entities
const person = neogm.createEntity(Person, {
  name: 'Alice Johnson',
  email: '[email protected]',
  age: 30
});

const company = neogm.createEntity(Company, {
  name: 'TechCorp',
  industry: 'Technology'
});

// Save to database
await personRepo.save(person);
await companyRepo.save(company);

// Create relationships using raw queries
await neogm.rawQuery().execute(`
  MATCH (p:Person {id: $personId}), (c:Company {id: $companyId})
  CREATE (p)-[:WORKS_FOR {position: 'Software Engineer', startDate: '2024-01-15'}]->(c)
`, { personId: person.id, companyId: company.id });

// Query with repository
const allPeople = await personRepo.find();
const alice = await personRepo.findOne({ name: 'Alice Johnson' });
const personById = await personRepo.findById(person.getId()!);

// Advanced queries
const employees = await neogm.queryBuilder()
  .match('(p:Person)-[:WORKS_FOR]->(c:Company)')
  .where({ 'c.name': 'TechCorp' })
  .return('p.name as name, p.email as email')
  .execute();

console.log('Employees:', employees.records);

await neogm.disconnect();

Core Concepts

Entities with Decorators

Define your graph entities using modern TypeScript decorators:

@Node('User')
class User extends BaseEntity {
  @Property({ required: true, unique: true })
  username!: string;

  @Property({ 
    required: true,
    validator: (email: string) => /\S+@\S+\.\S+/.test(email)
  })
  email!: string;

  @Property({
    transformer: {
      to: (date: Date) => date.toISOString(),
      from: (isoString: string) => new Date(isoString)
    }
  })
  createdAt?: Date;

  @Relationship({ type: 'FOLLOWS', direction: 'OUT', target: () => User })
  following?: User[];

  @Relationship({ type: 'FOLLOWS', direction: 'IN', target: () => User })
  followers?: User[];
}

Repository Pattern

Work with entities using type-safe repositories:

const userRepo = neogm.getRepository(User);

// Create and save
const user = neogm.createEntity(User, {
  username: 'john_doe',
  email: '[email protected]',
  createdAt: new Date()
});
await userRepo.save(user);

// Find operations
const allUsers = await userRepo.find();
const activeUsers = await userRepo.find({ where: { isActive: true } });
const john = await userRepo.findOne({ username: 'john_doe' });
const userById = await userRepo.findById(123);

// Count and existence
const userCount = await userRepo.count();
const exists = await userRepo.exists({ username: 'john_doe' });

// Delete
await userRepo.delete(user);

Advanced Querying

Build complex queries with the fluent query builder:

// Complex relationship queries
const influencers = await neogm.queryBuilder()
  .match('(u:User)<-[:FOLLOWS]-(follower:User)')
  .return('u.username as username, count(follower) as followerCount')
  .orderBy('followerCount', 'DESC')
  .limit(10)
  .execute();

// Multi-hop relationships
const friendsOfFriends = await neogm.queryBuilder()
  .match('(me:User)-[:FOLLOWS]->(friend:User)-[:FOLLOWS]->(fof:User)')
  .where({ 'me.username': 'alice' })
  .where('fof.username <> me.username')
  .return('DISTINCT fof.username as suggestion')
  .execute();

// Raw Cypher for complex scenarios
const customQuery = await neogm.rawQuery().execute(`
  MATCH (u:User)-[:FOLLOWS]->(f:User)
  WHERE u.createdAt > datetime($since)
  RETURN u.username, collect(f.username) as following
`, { since: '2024-01-01T00:00:00Z' });

Transactions

Execute operations within transactions:

// Write transaction
await neogm.executeInTransaction(async (tx) => {
  await tx.run('CREATE (u:User {username: $username})', { username: 'alice' });
  await tx.run('CREATE (u:User {username: $username})', { username: 'bob' });
  await tx.run(`
    MATCH (a:User {username: 'alice'}), (b:User {username: 'bob'})
    CREATE (a)-[:FOLLOWS]->(b)
  `);
});

// Read transaction
const result = await neogm.executeReadTransaction(async (tx) => {
  const users = await tx.run('MATCH (u:User) RETURN count(u) as count');
  return users.records[0].get('count').toNumber();
});

Property Features

Validation

@Node('Product')
class Product extends BaseEntity {
  @Property({ 
    required: true,
    validator: (price: number) => price > 0
  })
  price!: number;

  @Property({
    validator: (email: string) => /\S+@\S+\.\S+/.test(email)
  })
  contactEmail?: string;
}

Transformation

@Node('Event')
class Event extends BaseEntity {
  @Property({
    transformer: {
      to: (date: Date) => date.toISOString(),
      from: (isoString: string) => new Date(isoString)
    }
  })
  eventDate!: Date;

  @Property({
    transformer: {
      to: (tags: string[]) => tags.join(','),
      from: (csv: string) => csv.split(',')
    }
  })
  tags?: string[];
}

Migration from v1.x

NeoGM 2.0 introduces breaking changes with the new decorator-based approach. See the examples/ directory for migration guides and examples.

Key Changes:

  • Replace neogm.createNode() with decorator-based entities and repositories
  • Use @Node, @Property, @Relationship decorators instead of manual class definitions
  • Leverage getRepository() for type-safe data access
  • Continue using the same query builder and transaction APIs

API Reference

Decorators

  • @Node(label: string) - Define a node entity
  • @Property(options?) - Define a node property
  • @Relationship(options) - Define a relationship

Core Classes

  • NeoGM - Main ORM class
  • BaseEntity - Base class for all entities
  • Repository<T> - Type-safe data access layer
  • QueryBuilder - Fluent query building API

Examples

Check out the examples/ directory for:

  • basic-usage.ts - Getting started with decorators
  • decorator-usage.ts - Advanced decorator features
  • Complete workflow examples

License

ISC License - see LICENSE file for details.

Contributing

Contributions are welcome! Please read our contributing guidelines and submit pull requests to our GitHub repository.