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

swiftify

v1.3.2

Published

Web server framework

Downloads

43

Readme

Swiftify: A Fastify-based Web Server Framework for Rapid Development

Swiftify Logo

Swiftify is an opinionated and powerful web server framework for Node.js, built on the blazing-fast Fastify web framework. It's designed to dramatically accelerate the development of RESTful APIs, GraphQL services, and command-line tools by providing a cohesive, convention-over-configuration approach and integrating battle-tested libraries.

Why Swiftify? The Core Value Proposition

Swiftify empowers developers to build robust applications with unprecedented speed and clarity by focusing on:

  • Unified Model Definition (Define Once, Use Everywhere):

    • Define your database models with an extremely concise and readable syntax.
    • Automatically generate SQL schemas (via knexMigration) without writing a single line of SQL.
    • Simplify complex database relationships (e.g., one-to-many, many-to-many) with a more intuitive and readable API than raw Objection.js.
    • Your model definitions seamlessly integrate with RESTful APIs, GraphQL, and validation.
  • Effortless API Development (RESTful & GraphQL):

    • Implement sophisticated RESTful APIs and GraphQL APIs with minimal code and highly readable syntax.
    • Leverage powerful, built-in features like automatic CRUD generation, pagination, filtering, searching, and sorting through rich, yet simple, configurations.
    • Focus on your business logic, not boilerplate.
  • Integrated & Elegant CLI Tooling:

    • Develop powerful command-line interfaces for your application with concise and elegant APIs.
    • Swiftify provides a unified solution for most Node.js development scenarios, from web servers to background tasks and CLI tools, all within a consistent and easy-to-understand framework.

Features

  • ⚡️ Blazing Fast: Built on Fastify, ensuring high performance and low overhead.
  • 📦 Convention Over Configuration: Sensible defaults and structured patterns for rapid development.
  • 💾 Integrated ORM: Seamless database interactions with Objection.js + Knex.js, offering powerful model definitions, relations, and migrations.
  • 🚀 RESTful API Generation: Effortlessly create CRUD endpoints for your models with RESTfulRouter, including built-in support for pagination, filtering, searching, and sorting.
  • GraphQL Ready: First-class GraphQL support via Mercurius, with automatic GraphQL schema generation from your Objection.js models and efficient data fetching using DataLoader presets.
  • 💻 CLI Tooling: Build robust command-line interfaces for your application using Commander.js integration.
  • Robust Validation: Data validation powered by Yup integrated directly into your models.

Installation

To get started with Swiftify, install it via npm:

npm install swiftify knex sqlite3 # knex and a database driver are typically needed

Quick Start: Build a RESTful API in Minutes

Let's create a simple User model and expose a full RESTful API for it, including nested resources.

First, create an app.mjs file:

// app.mjs
import { WebServer, Model, RESTfulRouter, knexMigration } from 'swiftify';
import Knex from 'knex'; // Required for database connection
import { gql } from 'mercurius'; // For GraphQL example

// 1. Define your Models with concise schemas and relations
class User extends Model {
  static tableName = 'users';
  static idColumn = 'id';

  static fields = {
    id: { type: 'increments', constraints: { primary: true } },
    name: { type: 'string', constraints: { notNullable: true } },
    email: { type: 'string', constraints: { unique: true, notNullable: true } },
    createdAt: { type: 'datetime', timestamp: 'insert' },
    updatedAt: { type: 'datetime', timestamp: 'update' },
  };

  static get relations() {
    return {
      posts: Model.hasMany(Post, { foreignKey: 'userId' }), // User has many posts
    };
  }
}

class Post extends Model {
  static tableName = 'posts';
  static idColumn = 'id';

  static fields = {
    id: { type: 'increments', constraints: { primary: true } },
    title: { type: 'string', constraints: { notNullable: true } },
    content: { type: 'text' },
    userId: { type: 'integer', constraints: { notNullable: true } }, // Foreign key to User
    createdAt: { type: 'datetime', timestamp: 'insert' },
    updatedAt: { type: 'datetime', timestamp: 'update' },
  };

  static get relations() {
    return {
      author: Model.belongsToOne(User, { localKey: 'userId' }), // Post belongs to one User
    };
  }
}

async function startServer() {
  // 2. Configure and connect to your database (using SQLite for simplicity)
  const knexConfig = {
    client: 'sqlite3',
    connection: { filename: './dev.sqlite3' },
    useNullAsDefault: true,
  };
  const knex = Knex(knexConfig);
  Model.knex(knex);

  // 3. Run migrations to create tables (no SQL needed!)
  await knexMigration([User, Post], { drop: true });

  // Optional: Seed some initial data
  const alice = await User.query().insert({ name: 'Alice', email: '[email protected]' });
  const bob = await User.query().insert({ name: 'Bob', email: '[email protected]' });
  await Post.query().insert([
    { title: "Alice's First Post", content: 'Hello world!', userId: alice.id },
    { title: "Alice's Second Post", content: 'Another one.', userId: alice.id },
    { title: "Bob's Post", content: 'Greetings.', userId: bob.id },
  ]);

  // 4. Initialize WebServer
  const app = new WebServer({ logger: true });

  // 5. Create a RESTfulRouter for the User model and enable all CRUD operations
  const userRouter = new RESTfulRouter(User);
  userRouter.crud(); // Creates /users, /users/:id endpoints

  // 6. Add nested RESTful API for user's posts: /users/:userId/posts
  userRouter.child(Post, (postRouter) => {
    postRouter.crud(); // Creates /users/:userId/posts, /users/:userId/posts/:postId endpoints
  });

  // 7. Register the router as a Fastify plugin
  app.register(userRouter.plugin());

  // 8. Start the server
  try {
    await app.listen({ port: 3000 });
  } catch (err) {
    app.log.error(err);
    process.exit(1);
  }
}

startServer();

Explanation of RESTful API Endpoints:

After running the startServer() function, the Swiftify server will be listening on http://localhost:3000. You can try the following RESTful API endpoints:

  • GET http://localhost:3000/users
  • GET http://localhost:3000/users/1/posts (Nested resource!)

Quick Start: Build a Powerful GraphQL API

Swiftify makes building GraphQL APIs incredibly easy, especially with automatic schema generation from your models and efficient relation resolution. It leverages mercurius for GraphQL and provides powerful presets for common operations like fetching, searching, and mutations.

// app.mjs (continued from above, or in a separate file)
import { WebServer, Model, graphql, knexMigration } from 'swiftify';
import Knex from 'knex'; // Required for database connection

// 1. Define your Models with concise schemas and relations
// These models are the same as in the RESTful example, ensuring consistency.
class User extends Model {
  static tableName = 'users';
  static idColumn = 'id';

  static fields = {
    id: { type: 'increments', constraints: { primary: true } },
    name: { type: 'string', constraints: { notNullable: true } },
    email: { type: 'string', constraints: { unique: true, notNullable: true } },
    createdAt: { type: 'datetime', timestamp: 'insert' },
    updatedAt: { type: 'datetime', timestamp: 'update' },
  };

  static get relations() {
    return {
      posts: Model.hasMany(Post, { foreignKey: 'userId' }), // User has many posts
    };
  }
}

class Post extends Model {
  static tableName = 'posts';
  static idColumn = 'id';

  static fields = {
    id: { type: 'increments', constraints: { primary: true } },
    title: { type: 'string', constraints: { notNullable: true } },
    content: { type: 'text' },
    userId: { type: 'integer', constraints: { notNullable: true } }, // Foreign key to User
    createdAt: { type: 'datetime', timestamp: 'insert' },
    updatedAt: { type: 'datetime', timestamp: 'update' },
  };

  static get relations() {
    return {
      author: Model.belongsToOne(User, { localKey: 'userId' }), // Post belongs to one User
    };
  }
}

async function startGraphQLServer() {
  // 2. Configure and connect to your database (using SQLite for simplicity)
  const knexConfig = {
    client: 'sqlite3',
    connection: { filename: './dev.sqlite3' },
    useNullAsDefault: true,
  };
  const knex = Knex(knexConfig);
  Model.knex(knex);

  // 3. Run migrations to create tables
  await knexMigration([User, Post], { drop: true });

  // Optional: Seed some initial data
  const alice = await User.query().insert({ name: 'Alice', email: '[email protected]' });
  const bob = await User.query().insert({ name: 'Bob', email: '[email protected]' });
  await Post.query().insert([
    { title: "Alice's First Post", content: 'Hello GraphQL!', userId: alice.id },
    { title: "Alice's Second Post", content: 'Another GraphQL post.', userId: alice.id },
    { title: "Bob's Post", content: 'Greetings from Bob.', userId: bob.id },
  ]);

  // 4. Initialize WebServer
  const app = new WebServer({ logger: true });

  // 5. Register the GraphQL plugin
  app.register(graphql.plugin({
    context: ({ ctx }) => ({ loader: new graphql.Loader() }), // Required for DataLoader
    schema: graphql.type('Schema', {
      query: graphql.type('ObjectType', {
        name: 'Query',
        fields: {
          // Automatically generate GraphQL types and resolvers from your Swiftify Models!
          // This handles fields, relations (e.g., User.posts, Post.author), and efficient data loading.
          // Use graphql.model(Model) to expose a model as a GraphQL type.
          users: {
            type: graphql.type('List', graphql.model(User)),
            resolve: async () => User.query(),
          },
          posts: {
            type: graphql.type('List', graphql.model(Post)),
            resolve: async () => Post.query(),
          },
          // Use graphql.presets.fetch for fetching single or multiple instances by ID
          fetch: graphql.presets.fetch({
            USER: { model: User },
            POST: { model: Post },
          }),
          // Use graphql.presets.search for powerful filtering, sorting, and pagination
          search: graphql.presets.search({
            USER: {
              model: User,
              resolverOptions: {
                filterable: ['name', 'email'], // Allow filtering by name and email
                sortable: ['name', 'createdAt'], // Allow sorting by name and createdAt
              },
            },
            POST: {
              model: Post,
              resolverOptions: {
                filterable: ['title', 'content'],
                sortable: ['title', 'createdAt'],
              },
            },
          }),
        },
      }),
      mutation: graphql.type('ObjectType', {
        name: 'Mutation',
        fields: {
          // Use graphql.presets.mutation for create, update, and destroy operations
          ...graphql.presets.mutation(User).create().update().destroy().mutations,
          ...graphql.presets.mutation(Post).create().update().destroy().mutations,
        },
      }),
    }),
    graphiql: true, // Enable GraphiQL IDE for easy testing
  }));

  // 6. Start the server
  try {
    await app.listen({ port: 3000 });
  } catch (err) {
    app.log.error(err);
    process.exit(1);
  }
}

// startGraphQLServer(); // Uncomment to run this example

Explanation of GraphQL API Endpoints and Examples:

After running the startGraphQLServer() function, the GraphQL server will be listening on http://localhost:3000/graphql. You can open http://localhost:3000/graphiql to explore the API.

--- Example GraphQL Queries ---

Fetch all users with their posts:

query {
  users {
    id
    name
    email
    posts { # Automatically resolved relation!
      id
      title
      content
    }
  }
}

Fetch a specific user by ID using the "fetch" preset:

query {
  user: fetch(type: USER, id: "1") {
    ... on User {
      id
      name
      email
    }
  }
}

Search for posts, filter by title, sort by creation date, and paginate:

query {
  search(type: POST, filterBy: { title: "GraphQL" }, orderBy: "-createdAt", first: 1) {
    edges {
      node {
        ... on Post {
          id
          title
          content
          author {
            name
          }
        }
      }
    }
    pageInfo {
      hasNextPage
      endCursor
    }
    total
  }
}

--- Example GraphQL Mutations ---

Create a new user:

mutation {
  createUser(input: { name: "Charlie", email: "[email protected]" }) {
    id
    name
    email
  }
}

Update an existing post:

mutation {
  updatePost(input: { id: 1, patch: { content: "Updated content for Alice's first post." } }) {
    id
    title
    content
  }
}

Destroy a user (and their related posts due to cascade delete if configured in DB):

mutation {
  destroyUser(input: { id: 2 }) { # Assuming Bob is user ID 2
    id
    name
  }
}

Documentation

For detailed usage instructions, advanced configurations, and API references, please refer to the DOCS.md file.

License

Swiftify is MIT licensed.