All Projects → fortunejs → Fortune

fortunejs / Fortune

Licence: mit
Non-native graph database abstraction layer for Node.js and web browsers.

Programming Languages

javascript
184084 projects - #8 most used programming language
CSS
56736 projects
Mustache
554 projects
shell
77523 projects

Projects that are alternatives of or similar to Fortune

Indradb
A graph database written in rust
Stars: ✭ 1,035 (-27.47%)
Mutual labels:  graph-database
Neo4j sips
Elixir driver for the Neo4j graph database server
Stars: ✭ 78 (-94.53%)
Mutual labels:  graph-database
Crux
General purpose bitemporal database for SQL, Datalog & graph queries
Stars: ✭ 1,296 (-9.18%)
Mutual labels:  graph-database
Vertexium
High-security graph database
Stars: ✭ 55 (-96.15%)
Mutual labels:  graph-database
Movies Java Bolt
Neo4j Movies Example application with SparkJava backend using the neo4j-java-driver
Stars: ✭ 66 (-95.37%)
Mutual labels:  graph-database
Terminusdb
Open source graph database and document store. Designed for collaboratively building data-intensive applications and knowledge graphs.
Stars: ✭ 1,250 (-12.4%)
Mutual labels:  graph-database
R2d2 Cypher
Cypher support for the r2d2 connection pool
Stars: ✭ 8 (-99.44%)
Mutual labels:  graph-database
Neo4j Core
A simple unified API that can access both the server and embedded Neo4j database. Used by the neo4j gem
Stars: ✭ 99 (-93.06%)
Mutual labels:  graph-database
Neo4j Symfony
Symfony Bundle for the Neo4j Graph Database
Stars: ✭ 69 (-95.16%)
Mutual labels:  graph-database
Cog
A Persistent Embedded Graph Database for Python
Stars: ✭ 90 (-93.69%)
Mutual labels:  graph-database
Neo4j Tableau
Neo4j Tableau Integration via WDC
Stars: ✭ 56 (-96.08%)
Mutual labels:  graph-database
Subgraph
Reactive graph database for re-frame
Stars: ✭ 63 (-95.59%)
Mutual labels:  graph-database
Neo4j Apoc Procedures
Awesome Procedures On Cypher for Neo4j - codenamed "apoc"                     If you like it, please ★ above ⇧            
Stars: ✭ 1,291 (-9.53%)
Mutual labels:  graph-database
Agensgraph
AgensGraph, a transactional graph database based on PostgreSQL
Stars: ✭ 1,056 (-26%)
Mutual labels:  graph-database
Tinkerpop
Apache TinkerPop - a graph computing framework
Stars: ✭ 1,309 (-8.27%)
Mutual labels:  graph-database
Llvm2graphml
Explore LLVM Bitcode interactively using a graph database
Stars: ✭ 44 (-96.92%)
Mutual labels:  graph-database
Neo4j
Graphs for Everyone
Stars: ✭ 9,582 (+571.48%)
Mutual labels:  graph-database
Homebase React
The React state management library for write-heavy applications
Stars: ✭ 101 (-92.92%)
Mutual labels:  graph-database
Activegraph
An active model wrapper for the Neo4j Graph Database for Ruby.
Stars: ✭ 1,329 (-6.87%)
Mutual labels:  graph-database
Redisgraph
A graph database as a Redis module
Stars: ✭ 1,292 (-9.46%)
Mutual labels:  graph-database

Fortune.js

Build Status npm Version License

Fortune.js is a non-native graph database abstraction layer that implements graph-like features on the application-level for Node.js and web browsers. It provides a common interface for databases, as well as relationships, inverse updates, referential integrity, which are built upon assumptions in the data model.

It's particularly useful for:

  • Bi-directional relationships in any database.
  • Applications that need storage options to be portable.
  • Sharing the same data models on the server and client.

View the website for documentation. Get it from npm:

$ npm install fortune --save

This is the core module. Additional features such as networking (HTTP, WebSocket), database adapters, serialization formats are listed in the plugins page.

Usage

Only record type definitions need to be provided. These definitions describe what data types may belong on a record and what relationships they may have, for which Fortune.js does inverse updates and maintains referential integrity. Here's an example of a basic micro-blogging service:

const fortune = require('fortune') // Works in web browsers, too.

const store = fortune({
  user: {
    name: String,

    // Following and followers are inversely related (many-to-many).
    following: [ Array('user'), 'followers' ],
    followers: [ Array('user'), 'following' ],

    // Many-to-one relationship of user posts to post author.
    posts: [ Array('post'), 'author' ]
  },
  post: {
    message: String,

    // One-to-many relationship of post author to user posts.
    author: [ 'user', 'posts' ]
  }
})

Note that the primary key id is reserved, so there is no need to specify this. Links are ids that are maintained internally at the application-level by Fortune.js, and are always denormalized so that every link has a back-link. What this also means is that changes in a record will affect the links in related records.

By default, the data is persisted in memory (and IndexedDB for the browser). There are adapters for databases such as MongoDB, Postgres, and NeDB. See the plugins page for more details.

Fortune has 4 main methods: find, create, update, & delete, which correspond to CRUD. The method signatures are as follows:

// The first argument `type` is always required. The optional `include`
// argument is used for finding related records in the same request and is
// documented in the `request` method, and the optional `meta` is specific to
// the adapter. All methods return promises.
store.find(type, ids, options, include, meta)
store.create(type, records, include, meta) // Records required.
store.update(type, updates, include, meta) // Updates required.
store.delete(type, ids, include, meta)

// For example...
store.find('user', 123).then(results => { ... })

The first method call to interact with the database will trigger a connection to the data store, and it returns the result as a Promise. The specific methods wrap around the more general request method, see the API documentation for request.

Input and Output Hooks

I/O hooks isolate business logic, and are part of what makes the interface reusable across different protocols. An input and output hook function may be defined per record type. Hook functions accept at least two arguments, the context object, the record, and optionally the update object for an update request. The method of an input hook may be any method except find, and an output hook may be applied on all methods.

An input hook function may optionally return or resolve a value to determine what gets persisted, and it is safe to mutate any of its arguments. The returned or resolved value must be the record if it's a create request, the update if it's an update request, or anything (or simply null) if it's a delete request. For example, an input hook function for a record may look like this:

function input (context, record, update) {
  switch (context.request.method) {
    // If it's a create request, return the record.
    case 'create': return record

    // If it's an update request, return the update.
    case 'update': return update

    // If it's a delete request, the return value doesn't matter.
    case 'delete': return null
  }
}

An output hook function may optionally return or resolve a record, and it is safe to mutate any of its arguments.

function output (context, record) {
  record.accessedAt = new Date()
  return record
}

Based on whether or not the resolved record is different from what was passed in, serializers may decide not to show the resolved record of the output hook for update and delete requests.

Hooks for a record type may be defined as follows:

const store = fortune({
  user: { ... }
}, {
  hooks: {
    // Hook functions must be defined in order: input first, output last.
    user: [ input, output ]
  }
})

Networking

There is a HTTP listener implementation, which returns a Node.js request listener that may be composed within larger applications. It maps Fortune requests and responses to the HTTP protocol automatically:

// Bring your own HTTP! This makes it easier to add SSL and allows the user to
// choose between different HTTP implementations, such as HTTP/2.
const http = require('http')
const fortune = require('fortune')
const fortuneHTTP = require('fortune-http')

const store = fortune(...)

// The `fortuneHTTP` function returns a listener function which does
// content negotiation, and maps the internal response to a HTTP response.
const listener = fortuneHTTP(store)
const server = http.createServer((request, response) =>
  listener(request, response)
  .catch(error => { /* error logging */ }))

store.connect().then(() => server.listen(1337))

This yields an ad hoc JSON over HTTP API, as well as a HTML interface for humans. There are also serializers for Micro API (JSON-LD) and JSON API.

Fortune.js implements its own wire protocol based on WebSocket and MessagePack, which is useful for soft real-time applications.

Features and Non-Features

  • Inverse relationship updates, automatically maintain both sides of relationships between records.
  • Referential integrity, ensure that links must be valid at the application level.
  • Type validations, fields are guaranteed to belong to a single type.
  • Adapter interface, use any database that can implement an adapter.
  • No object-relational mapping (ORM) or active record pattern, just plain data objects.
  • No coupling with network protocol, handle requests from anywhere.

Requirements

Fortune.js is written in ECMAScript 5.1, with one ECMAScript 6 addition: Promise. Most of its public API returns Promises to be compatible with future editions of the language.

License

This software is licensed under the MIT license.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].