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

@whidb/restapi

v0.4.7

Published

Custom hooks and utilities to make it easier to work with our whirest node server code and its dynamic endpoints.

Downloads

45

Readme

@whidb/restapi

Custom hooks and utilities to make it easier to work with our whirest node server code and its dynamic endpoints.

  • useCrudApi and useQueryApi help with using the dynamic rest endpoints created from the data in the REST_ENDPOINTS table.

See also the @whidb/restui-pr library for ui code utilities that work with these hooks.

Getting Started

  1. Install @whidb/restapi and its dependencies...

    npm i @whidb/restapi
    npm i axios @tanstack/react-query @tanstack/react-query-devtools
  2. Wrap your application code in a RestApiContextProvider (index.js or app.js).

    import { QueryClient } from "@tanstack/react-query"
    import { RestApiContextProvider } from "@whidb/restapi"
    
    const queryClient = new QueryClient()
    
    export default function App() {
       return (
          <RestApiContextProvider client={queryClient}>
             <!--your app code here -->
          </RestApiContextProvider>
       )
    }

    The RestApiContextProvider does several things.

    • it wraps your code in a react-query QueryClientProvider so it can use react-query and adds the react-query devtools to help debugging react-queries in development (little flower thing in the bottom right corner when you run the code in development mode)
    • it sets up a react context so the filtering you apply to useCrudApi and useQueryApi are "remembered" even when you leave and come back to pages
  3. Handy, but not required... Setup .env.development and constants.js files to define paths to the rest apis
    .env.devlopment

    REACT_APP_JSON_API_ROOT = "https://devccc.whi.org/api"

    constants.js

    export const JSON_API_ROOT = process.env.REACT_APP_JSON_API_ROOT || "/api"
    export const QUERYURL = `${JSON_API_ROOT}/query`
    export const CRUDURL = `${JSON_API_ROOT}/crud`
    export const PROCURL = `${JSON_API_ROOT}/proc`

    This way you use path strings like `${QUERYURL}/endpointname` in your useCrudApi calls.

useCrudApi and useQueryApi

Custom hooks to help with performing crud operations with the dynamic rest endpoints defined in our web.rest_endpoints table.

  • useQueryApi is the same as useCrudApi, but doesn't include the crud state and functions in its return values.
  • These hooks include setGlobalFilter and setColFilters functions to performing filtering of the fetched data
  • They also include a few state variables and functions useful for building forms and screens to display the data and perform crud operations (e.g. the @whidb/restui library).

NOTE: These hooks are just a wrapper around react-query useQuery and useMutation hooks. Reading the react-query documentation may be helpful in debugging situations. Also you can use the react-query dev tools for help in debugging query problems.

Usage

const [state, controller] = useCrudApi(queryKey, options)

useCrudApi takes two parameters

  • queryKey

    The endpoint url. It must be either...

    • a string - the url to an endpoint as defined in the REST_ENDPOINTS table,
      e.g. https://devccc.whi.org/api/crud/fact-db.
      Note: this can contain url parameters, but it's recommended that you use the array form of queryKey if you have parameters.

    • an 2 element array - an array with a url string and a url parameter object.
      e.g. [`${CRUDURL}/fact-data-sources`, { dsrcId: dsrcId }].
      This format makes it easier to work with multiple parameters, especially when some of them may be optional, See the examples section below. The elements of the parameter object will be converted into an url parameter string for the fetch.

    Note: This is the queryKey value sent to the react-query useQuery hook. Changing this value will trigger a refetch of the data.

  • options

    An optional object containing one or more of the following

    • Data Processing functions - Rarely needed, these are async functions that are executed before or after crud operations. They allow you to add custom processing to these events (e.g. sorting/manipulating the data after fetching, running pl/sql functions pre or post crud operations).

      • processFetchedData - async function that runs after a fetch. It takes the fetched data as a parameter and returns the modified data object. Use this if you need to manipulate the raw data in some way, e.g. sorting.

      • preProcessEditItem - async function that executes before inserts and updates. Gets passed editItem and must return a possibly modified editItem. Can be used for validation, and will abort crud operation completion if an error is thrown.

      • preInsert, preUpdate and preDelete - async functions that execute before the corresponding crud operation. Gets passed editItem and must return a possibly modified editItem. Can be used for validation, and will abort crud operation completion if an error is thrown.

      • dbDelete - async function to REPLACE the normal db delete operation. e.g. if the object has children that need to be deleted, you can use this to replace the normal delete with a rest call that fires a db procedure to delete the row and its children.

      • postInsert and postUpdate - async functions to execute after the insert or update has fired, but before the new item is added to the data array. Gets passed the return value from the insert/update and returns the object to put into the data array

    • Filtering options - for customizing how the colFilters are applied

      • filterOnServer - if true, apply column filtering on server side. Defaults to false. Turn this on if table is very large and you want to perform filtering before sending to the client.
      • fetchOnlyOnColFilters - if true will not fire the fetch
    • Mutation options - Rarely needed, these allow you to add to or override the normal useCrud mutatation options. See react-query documentation for the options available to mutations.

      • useMutationOptions - will be applied to the insert, update and delete mutations
      • insertMutationOptions - will only be applied to the insert mutation
      • updateMutationOptions - will only be applied to the update mutation
      • deleteMutationOptions - will only be applied to the delete mutation
    • useQuery options - Any other key value pairs in this object will be assumed to be react-query options and will be passed to the useQuery call. See the react-query documentation for available options. Note enabled and staletime options are especially useful, see examples below.

useCrudApi returns an array with two objects

  • state - holds the various state variables related to fetching and crud operations

    • data - the data fetched from the url. *note if filtering is applied this will be the filtered data
    • isLoading - true if data fetch is running (and not idle see react-query docs)
    • isError - true if an error occurred during data fetch
    • isSuccess - true if an error occurred during data fetch
    • query - the return value from the react-query useQuery call
    • globalFilter - current globalFilter value (see filtering)
    • colFilters - current colFilters (see filtering)
    • editItem - used by form ui to hold the item to edit
    • insertMode - if true code will attempt to insert the item, otherwise it will do an edit
  • controller - Crud/Utility functions

    • setGlobalFilter - Sets the text value used for datatable globalfilter property. This will trigger filtering the data.

    • setColFilters - an array of objects to be passed to the server to do server side column filtering. Setting this will trigger filtering the data. If filterOnServer is true, colFilters will be passed to the server for processing (helpful for very large tables)

    • doInsert, doUpdate, doDelete - takes an object of row data to send to the crud endpoint.

    • setNewItem and setEditItem - holds the row data for use by an edit form. using setNewItem sets insertMode to true.

Notes

  • these are in an array so you can name the return variables whatever you want (see examples)
  • You can have several useCrudAPI calls pointing to different urls in the same screen.
  • you dont have to use the crud capabilities, you can use this to just fetch data, although useQueryApi is designed for this usage.

useCrudApi and useQueryApi usage examples

Simple, no parameters

const [dtypState, dtypCtrl] = useCrudApi(`${CRUDURL}/F2_DATA_TYPES`)

fetch will fire immediately

With url parameters

using the array style for parameters, with the url parameters expressed as an object

const [dsrcState, dsrcCtrl] = useCrudApi([`${CRUDURL}/fact-data-sources`, { dsrcId: 5 }])

params will be converted into a url param string ("?dsrcId=5") and added to the fetch. Any change to the params object will fire a re-fetch

Only fire fetch if parameters exist (enabled react-query option)

Add the "enabled" useQuery option to only fire the fetch when enabled condition is true.

const { dsrcId } = useParams()
const [dataSourceQuery] = useQueryApi(`${CRUDURL}/fact-data-sources`, { dsrcId }, { enabled: !!dsrcId })

In this example, useParams is asyncronous and dsrcId will be null at first. The enabled option ensures the query will only fire when the parameter has a value, saving an unneeded fetch that would return all data sources.

Use staletime to reduce the number of fetches react-query performs

React-query automatically refreshes your data at various times. Sometimes the design of your ui will trigger new fetches as you move around (e.g. tabs/modals). If the data doesnt change very often you can use the staletime to keep the data in the react-query cache longer and reduce the number of network fetches.

e.g. this keeps the data in the cache for a minute.

const [dtypState, dtypCtrl] = useCrudApi(`${CRUDURL}/fact-data-types`, undefined, { staleTime: 1000 * 60  })

Crud operations performed in the app will refesh the data regardless of the cache setting, but if there are other users editing data, you would not see those changes for an hour with this setting.

Converting from whireact library

  • whireact is now split into two libraries @whidb/restapi and @whidb/restui
  • make sure to make the changes to your top level components as explained in the getting started instructions