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 🙏

© 2024 – Pkg Stats / Ryan Hefner

faunatic

v1.0.8

Published

<div align="center"> <br /> <p> <a href="https://www.npmjs.com/package/faunatic"><img src="https://raw.githubusercontent.com/faunatic/faunatic/main/_readme/cover.png" width="400" alt="faunatic logo" /></a> </p> <br /> <p> <a href="https://

Downloads

24

Readme


Note: This package is in alpha release, it's currently a MVP and should at the moment not be used 100% reliably in production.

About

Faunatic is a simple wrapper for Fauna (DB) / FaunaDB that makes it easier to do simple operations in a type-friendly and efficient way. The goal is to drastically improve developer experience by ensuring everything is properly typed and parsed/validated.

Getting started

It's really simple to get started:

  1. Install faunatic (yarn add faunatic or npm i faunatic)
  2. Retrieve your Fauna secrets (Fauna)
  3. Define your data models
  4. Setup your database

1. Installing

Install the module with your preferred package manager!

Yarn:

yarn add faunatic

NPM:

npm i faunatic

2. Retrieving secrets

In order to use Faunatic you have to retrieve the admin/server secret from your current database in Fauna. Keep this noted down.

3. Define your schemas

Now that faunatic has been installed, you can go ahead and define models for your database. As an example:

import { faunatic } from "./faunatic";


const UserSchema = new faunatic.DefinedSchema(
    z.object({
        name: z.string(),
        email: z.string()
            .email()
    })
);

const TeamSchema = new faunatic.DefinedSchema(
    z.object({
        name: z.string(),
        ownerUser: z.string()
    })
);

Schemas are what defines how the data structure should be. With Faunatic, it's required that all schemas are objects.

4. Set up your models

With the schemas defined, it's time to connect the schemas with a corresponding model. If you've used Mongoose previously, it's somewhat similar, but with some extra features and parameters. Example:

// Here we define a model/collection called "team", with the TeamSchema, no relations and one index
const teams = faunatic.model({
    name: "team",
    schema: TeamSchema,
    relations: {},
    indexes: {
        // This index allows us to retrieve teams based on the ownerUser
        byOwner: {
            terms: [
                d => d.data.ownerUser
            ]
        }
    },
});

const users = faunatic.model({
    name: "user",
    schema: UserSchema,
    relations: {},
    indexes: {
        // This index sets a unique constraint based on the "data.email" field, and also allows us to get a user by email! 
        byEmail: {
            unique: true,
            terms: [
                d => d.data.email
            ]
        }
    }
});

5. Initiate your models

Now that everything is set up, all that remains is to initiate the models. Faunatic goes through the provided model definitions, and creates them if they don't exist, in addition to the indexes you have provided. It's super simple to do!

const client = new faunatic.Client({ secret: "my-fauna-secret" });
await client.init([
    teams,
    users
]);

6. Start coding!

Now, faunatic has handled collection creation and index creation for you automatically, and provides a strict schema approach on all your models. Here are some things you can do:

// == CRUD operations == //

// == CREATION
const createdUser = await users.create({
    name: "my name",
    email: "[email protected]"
});

// == RETRIEVAL
const user = await users.get("123");
console.log(user.id); // => "123"
console.log(user.data.email); // => "[email protected]"

// == UPDATING 
// Option 1:
const updatedUser = await users.update("123", {
    name: "hello world"
});

// Option 2:
const updatedUser2 = await user.update({
    name: "hello world"
});

// == DELETION
// Option 1:
const deletedUser = await users.delete("123");
// Option 2:
const deletedUser2 = await createdUser.delete();

const countedUsers = await users.count();
const countedTeams = await teams.count();

console.log(`There are ${ countedUsers } users and ${ countedTeams } teams!`);
const listedUsers = await users.list();
const listedTeams = await teams.list();

listedUsers.data.map(user => {
    console.log(`User: ${ user.id }`); // => "User: XXX"
});

FAQ

Performance considerations

For small use cases, faunatic works pretty well. However, for many schemas and large complicated, nested schemas you may encounter big output types and notice some slower performance as a result. Faunatic has under the hood attempted to minimize its output, but there are still some caveats in typescript (to my knowledge) that still result in large outputs.

One thing you can do is to explicitly denote the type for the schemas you're using, it requires some more code but results in massive savings in output types. As an example:

import { z } from "zod";
import { faunatic } from "./faunatic";


// => ❌ The following code results in large output types as everything is being inferred and passed on.
const BigZodSchema = z.object({});
const myModel = faunatic.model({
    name: "mymodel",
    schema: faunatic.model(BigZodSchema)
});

// => 👌 The following code explicitly denotes the schema type which makes typescript able to reference it
const BigZodSchema = z.object({});
// We define a type which typescript and faunatic can reference to instead of redoing the types
type ModelSchema = faunatic.DefinedSchema<typeof BigZodSchema>;
// and "declare" it as the variable type
const ModelSchema: ModelSchema = faunatic.schema(BigZodSchema);

const myModel = faunatic.model({
    name: "mymodel",
    schema: ModelSchema
});

Roadmap

There are a lot of features that I personally want to see added to this project, and I've tried to outline them below:

Idea: Type-safe query builder

Fauna is really nice for developers as it offers a nice free plan, is extremely scalable and cost-effective. However, the DX experience when building bigger and more complex queries is a bit lacking. Although I would love to launch faunatic with a query builder from the start, it requires some thorough thoughts, and a planned "syntax".

For now, I've started with nothing in this field, but I am looking forward to suggestions and feedback overall.

Idea: CLI Tool and setup

As with the other popular ORMs/wrappers on the market, I wish for faunatic to introduce CLI commands to set up databases, update collections/indexes and handle other operations (such as migrations).

Idea: Schema/data migration (tool)

Although Fauna is a NoSQL (document) database, practically all applications today have defined data structures/schemas. In the standard relational databases and with other tools, migrating data and schema is not that tough as everything is enforced on the database level, and updating a schema practically means the database needs to change as well immediately.

This is different with Fauna, as it's a NoSQL database and there's no database-level schema defined, so one needs to develop a tool for migration that can handle multiple strategies. For example, here are some common migration patterns in NoSQL:

  • Migrate documents only on retrieval - Whenever you retrieve a document, it would check the migration version and apply the correct migrations on the document, then save it.
  • Go through all documents and migrate - Pretty straightforward, go through all the documents and migrate each document to the latest version.
  • Don't migrate documents, only add backwards compatibility

Each come with their own pros and cons. Ultimately, it's up to the developer to handle how they should migrate (if at all) their data, but I think it would be really nice to provide a tool similar to Prisma Migrate which handles a lot of common use cases for this.