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

@dukefun/js-ext

v0.0.1

Published

### `Router.resources(views, name, routes)`

Downloads

3

Readme

Router

Router.resources(views, name, routes)

Generates the list of routers based on routes and expands by CRUD routes. Later the list would be used as props for the SwitchRoutes component

import { Router } from '@dukefun/js-ext'

// more info about settings format see https://github.com/dukexoom/awesome-crud
const settings = { cdnServers: { list: {}, gql: { create: 'some query', update: 'some query', show: 'some query' } } }
const components = { New, Edit, Show, List } // the map of universal CRUD components

const views = {
  custom: { cdnServers: { CustomAction } },
  crud: { components, settings },
}
Router.resources(views, 'cdnServers', [{ routeAction: 'customAction' }])

<SwitchRoutes />

This is the extension for react-dom-router <Switch />, which flexible resolves role based control, inner routing and redirects

// You have to implement the function `isPermittedRoute`
const isPermittedRoute = (route) => {
  if (route.skipPermissions) return true
  ...
}
// For CRUD should be `Router.resources` used
const routes = [
  { requiredPermissions: ['cdn_servers', 'edit'], path: '/cdn_servers/new', component: SomeComponent },
  { requiredPermissions: ['cdn_servers', 'edit'], path: '/cdn_servers/:id/edit', component: SomeComponent },
  { redirect: true, path: '/', pathTo: '/build_info' },
]

<SwitchRoutes isPermittedRoute={isPermittedRoute} routes={routes} />

Interface Route

| Name | Type | Example | Description | | :------------------ | :------------ | :------------------------ | :---------------------------------------------------------------------------------------------------------------------------------------------------------------- | | path | string | /cdn_servers/:id/edit | Any valid URL path (the same like in react-router) | | exact | boolean | true | When true, will only match if the path matches the location.pathname exactly. (the same like in react-router) | | pathTo | string | /build_info | A string representation of the Link location, created by concatenating the location’s pathname, search, and hash properties. (the same like to in react-router) | | component | React.FC | () => <div /> | A React component to render only when the location matches. (the same like in react-router) | | isAuthorized | boolean | true | When true, the route appears only when the user is authorized | | routes | Route[] | | The list of inner routes | | requiredPermissions | string[] | ['cdn_servers', 'edit'] | The list can be used inside isPermittedRoute function in order to filter not permitted routes | | redirect | boolean | true | When true, <Redirect /> will be rendered. Works together with pathTo |

Form

Configure

  1. Fill Config

    // jsExt.js config
       
    import Form from 'youselfComponents/Form'
    ...
    
    export default {
      form: {
        Form,
        InputList,
        InputRow,
        hasPermissions,
        inputs: {
          select: Select,
          text: Text,
          integer: Text,
          float: Text,
          password: Text,
          json: JSON,
          smartJSON: SmartJSON,
          checkbox: Checkbox,
          datePicker: DatePicker,
          file: File,
        },
      },
    }
       
    // or using `@dukefun/mui-components`
    import { FormComponents } from '@dukefun/mui-components'
       
    export default {
      form: FormComponents,
    }
  2. Or pass config to the prop field config

    <Form config={FormComponents} />

hasPermission

Sometimes we have to hide some input fields based on user permissions

Form also provides this ability. We have to add yourself implementation

export default {
  form: { ...FormComponents, hasPermission: hasPermission },
}

Config

Allows to create common config object

import { Config } from '@dukefun/js-ext'

Initialization

  1. Create config file

    // config/config.js
    
    import jsExt from './common/jsExt'
    
    export default {
      jsExt,
      cookies: {
        expires: 14, // days
        secretKey: process.env.REACT_APP_SECRET_KEY,
      },
    }
  2. Create initializer for config and start it with application

    import { Config } from '@dukefun/js-ext'
    import config from '../config'
    
    export default function() {
      Config.set(config)
    }

Config.get(path, defaultValue)

Get value from config

path can be string or list of strings

Config.get(['jsExt', 'secretKey'], '')
Config.get('secretKey')

Config.setIn(path, value)

Add new value to config after initialization

path can be string or list of strings

Config.setIn(['jsExt', 'expires'], 10)
Config.setIn('expires', 10)

Utils

Cookies

Encrypting cookies

Setup

Add secretKey and expires to jsExt config

Example:

// config/common/jsExt.js

export default {
  ...
  cookies: {
    secretKey: 'secretKey',
    cookiesExpires: 14, // days
  }
}

Functions:

  1. Cookies.set(key, value) Sets encrypted value to cookies
    Cookies.set('key', 'value')
  2. Cookies.get(key) Get not decrypted value from cookies
    Cookies.get('key')
  3. Cookies.getDecrypted(key) Get decrypted value from cookies
    Cookies.getDecrypted('key')
  4. Cookies.remove(key) Remove cookie by key
    Cookies.remove('key')

GQLFetch

Create config file for jsExt:

export default {
  gql: {
    url: `${process.env.REACT_APP_SERVER_URL}/public`,
    options: { withCredentials: true },
  },
}

Usage example:

import { GQLFetch } from '@dukefun/js-ext'

GQLFetch.run(query, variables)

Redux

Api middleware

Provide gql middleware for redux store

import { Redux } from '@dukefun/js-ext'

const interceptors = [
  {
    condition: (resp) => resp.data.errors && false,
    callback: () => alert('This callback will not called'),
  },
  {
    condition: (resp) => resp.data.errors && true,
    callback: () => alert('This callback will be called'),
  },
]
const invalidTokenCallback = (action, errors) => {
  console.log('action', action)
  console.log('errors', errors)
}

const api = Redux.apiMiddleware(invalidTokenCallback, interceptors)

invalidTokenCallback will called if errors.response?.data === 'invalid_access_token'

When response has no errors will be called first callback from callbackList where condition is true

Request for api middleware

Example of action creator:

list = (variables) => ({
  type: 'LIST',
  request: {
    query: gqlRequest,
    variables,
    multi: true,
  },
})

query - Graphql request created by graphql-tag lib

variables - variables for Graphql request

multi - if true allows to handle multi Graphql response

combineHandlers(handlers, defaultState)

Creates reducer based on handlers.

Handlers is the object where key is action type (or list of action types) and value is function which return updated state.

Example:

const defaultState = {}

const UPDATE = 'user/UPDATE'
const SIGN_UP = 'user/SIGN_UP'
const SIGN_IN = 'user/SIGN_IN'

const HANDLERS = {
  [UPDATE]: (state, { data }) => ({ ...state, ...data }),
  [[SIGN_UP, SIGN_IN]]: (state, { data: { user } }) => ({ ...state, ...user }),
}

export default Redux.combineHandlers(HANDLERS, defaultState)

Modal component

This component controls modal windows

Example:

import React from 'react'
import { Modal } from '@dukefun/js-ext'
import modals from '../index'

export default function BaseModal({ current }) {
  return <Modal current={current} modals={modals} />
}

current - list of objects. Example:

;[
  { name: 'Profile', params: { title: 'My Profile' } },
  { name: 'Error', params: { title: 'Error!' } },
]

modals - object where key is modal name, value is modal component Example:

{
  Profile: ProfileModal,
  Error: ErrorModal,
}
// modals/index.js

import AlertModal from './AlertModal'
import ConfirmModal from './ConfirmModal'
import ProfileModal from './ProfileModal'

export default {
  Alert: AlertModal,
  Confirm: ConfirmModal,
  Profile: ProfileModal,
}