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

@macellan/dux-core

v0.3.0

Published

Dux core for building and navigating rich dashboard apps

Downloads

3

Readme

Introduction

Dux is a simple boilerplate reducing tamplate for creating dashboards written in TypeScript and React. While the Dux Core doesn't have much dependencies, Dux Components package heavily relies on Mantine as a UI kit and hook library of choice. Dux is unopinonated about your state management of choice.

Installation

To get started with Dux, install the core and components package to your existing app or create a template with Codux tool (coming soon).

Using npm:

npm install @macellan/dux-core @macellan/dux-components

Using yarn:

yarn add @macellan/dux-core @macellan/dux-components

Using pnpm:

pnpm install @macellan/dux-core @macellan/dux-components

Usage

To start using the Dux Core you should create a new dux instance, best place to this would be a config file or your main.tsx file where you initialize your react app.

This documentation will examplify the code in TypeScript but things shouldn't change much for JavaScript.

import { createDux } from '@macellan/dux-core';

const app = createDux();

Dux expects some essential options for creating an instance, like your views. Under the hood Dux uses react-router to implement client side routing. You can pass a router object to the views property as a router. This object can be extended with allowedRoles propery to do authenticated routing. Dux provides 3 builtin roles to give you a headstart and handle internal mechanisms. These are;

  • * Anyone can access this route.
  • authenticated Only users that are authenticated with given Dux primitive can access this route.
  • unauthenticated Only users that are unauthenticated with given Dux primitive can access this route. This is useful for creating a login or signup page that only the users that are not logged in can see.
import { createDux } from '@macellan/dux-core';

const app = createDux({
  views: [
    {
      path: '/',
      element: <div>This is the home page</div>,
      // Anyone can see this page
      allowedRoles: ['*'],
    },
    {
      path: '/dashboard',
      element: <div>This is the dashboard page</div>,
      // Only logged in users can see this page
      allowedRoles: ['authenticated'],
    },
    {
      path: '/admin',
      element: <div>This is the admin page</div>,
      // You can define your arbitrary roles as well
      // Only logged in users that has the admin role can see this page
      allowedRoles: ['authenticated', 'admin'],
    },
    {
      path: '/login',
      element: <div>This is the login page</div>,
      // Only logged out users can see this page
      allowedRoles: ['unauthenticated'],
    },
  ],
});

allowedRoles property only works at the root level so you have to manage your routes accordingly.

Another neccessary property a Dux instance needs is the initial authentication state. Implementing the authentication is on you but we're planning a @macellan/dux-auth package to speed up this process as well.

import { createDux } from '@macellan/dux-core';

const app = createDux({
  views: [
    {
      path: '/',
      element: <div>This is the home page</div>,
      // Anyone can see this page
      allowedRoles: ['*'],
    },
    {
      path: '/dashboard',
      element: <div>This is the dashboard page</div>,
      // Only logged in users can see this page
      allowedRoles: ['authenticated'],
    },
    {
      path: '/admin',
      element: <div>This is the admin page</div>,
      // You can define your arbitrary roles as well
      // Only logged in users that has the admin role can see this page
      allowedRoles: ['authenticated', 'admin'],
    },
    {
      path: '/login',
      element: <div>This is the login page</div>,
      // Only logged out users can see this page
      allowedRoles: ['unauthenticated'],
    },
  ],
  auth: {
    // For kepping track on if the user is logged in. Implement your own logic here
    initialState: false,
    // You should fetch your user before reaching here and provide your roles
    initialRoles: [],
  },
});

initialRoles accepts a RoleObject array, this is a simple object with a name and an identifier properties. You can provide your arbitrary roles here.

export interface RoleObject {
  identifier: string;
  name: string;
}

With that, you are ready to render your app. Simply create your app provider and render it with react.

// This is an async funtion that you need to wait
app.createProvider().then(DuxProvider => {
  ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
    <React.StrictMode>
      <DuxProvider />
    </React.StrictMode>
  );
});

Authorization

At some point you may need an authorization manager. For instance you might want to redirect unauthroized pages or simply show an "unauthorized" view. app instance provides a method to manage your views. You basically provide a function that would be called when Dux encounters an unauthorized view visit.

You get the view and the roles the user has in this callback function. You need to provide an object that has 2 properties;

  • redirects for redirection
  • replaces for displaying a custom view

You should pass null for at least one of these properties but redirection will take precedence otherwise.

app.configureAuthorizationManager((view: ViewObject, roles: RoleObject[]) => {
  // Let's redirect the client if the user is 'unauthenticated' 
  if (roles.map(role => role.identifier).includes('unauthenticated')) {
    return {
      redirects: "/login",
      replaces: null,
    };
  }

  return {
    redirects: null,
    replaces: null,
  };
})

We might want to show an "unauthorized" view for other pages.

app.configureAuthorizationManager((view: ViewObject, roles: RoleObject[]) => {
  if (roles.map(role => role.identifier).includes('unauthenticated')) {
    return {
      redirects: "/login",
      replaces: null,
    };
  }

  // Let's first exlude views like login and signup
  const authRedirectRoutes = ["/login", "/signup"]
  if (authRedirectRoutes.includes(view.path as string)) {
    return {
      redirects: "/",
      replaces: null,
    };
  }

  // Otherwise show the unauthorized view
  return {
    redirects: null,
    replaces: () => <div>You are not authorized to see this page</div>,
  };
});

Dux provides a simple factory for this simple usage. Simply pass your primary authentication page, your non authenticated view paths, default redirect and unauthorized view to this function and you're good to go.

import { createDux, defaultAuthorizationManager } from "@macellan/dux-core"

// ...

app.configureAuthorizationManager(
  defaultAuthorizationManager('/login', ['/login', '/signup'], '/', () => <div>You are not authorized to see this page</div>)
);

Authentication

Authentication is quite simple with Dux. Simply use the useAuth hook and login and logout your user.

Dux Core does NOT handle the storage or management of the user, that is on you. Dux simply governs the auth state and the roles.

function Login() {
  // use your app instance here
  const { login } = app.useAuth()

  const handleLogin = () => {
    // Provide your users roles as a RoleObject array. 
    // You can pass an empty array for basic users
    login([{ identifier: "admin", name: "Admin" }]);
  }

  return // ...
}
function UserMenu() {
  // use your app instance here
  const { logout } = app.useAuth()

  const handleLogout = () => {
    logout();
  }

  return // ...
}

These functions will automatically redirect the user.