← Back to archive

Repo of the Day

klis87/normy

Published: Mar 5, 2025

Open repository ↗

Automatic normalization and data updates for data fetching libraries (react-query, swr, rtk-query and more)

Summary

normy is a TypeScript library that automatically normalizes application data and updates dependent queries when mutations return, removing the need to manually rewrite query caches after every change. It is shipped as a monorepo of integration packages for react-query, vue-query, swr, and rtk-query, plus a @normy/core package for custom adapters. The repository is MIT-licensed and written primarily in TypeScript.

What it is useful for

normy targets a recurring problem: when a mutation response includes an updated object, you typically have to find every cached query that contains that object and patch it. The README shows a react-query example where two useMutation calls manually rewrite both ['books'] and ['book'] query data after editing. With normy those manual onSuccess handlers disappear because the library stores objects by id and deep-merges mutation responses into a normalized store, then re-renders every query that references them. Nested objects with ids are normalized recursively, so authors inside books are tracked on their own.

It is also useful for array-heavy data. Beyond replacing arrays when a parent object is updated, normy offers built-in array operations like __append, __prepend, __insert, __remove, __replace, __move, __swap, __clear, and __replaceAll, applied via "operation hints" on mutation responses such as { id: '3', name: 'Name 3', __append: 'books' }. The README also shows how to add custom operations through customArrayOperations, with a __reverse example, and how to extend arrayHelpers with typed node and nodeless operations.

How engineers can use it

Install the package that matches your stack (commands from the README):

npm install @normy/react-query
npm install @normy/vue-query
npm install @normy/swr
npm install @normy/rtk-query
npm install @normy/core   # for writing your own integration

Then wrap your app with the provider. For react-query, the README shows:

<QueryNormalizerProvider
  queryClient={queryClient}
  normalizerConfig={{ getArrayType: ({ arrayKey }) => arrayKey }}
>
  <QueryClientProvider client={queryClient}>{/* ... */}</QueryClientProvider>
</QueryNormalizerProvider>

After that, drop the manual onSuccess setters from your mutations. You can decorate mutation responses with arrayHelpers for type-safe hints, e.g. arrayHelpers.append(node, 'books'), or chain operations with arrayHelpers.chain(node).append('books').insert('favouriteBooks', { index: 1 }).apply(). For visibility, normalizerConfig: { devLogging: true } prints when queries are updated (development only).

Documented conditions and limitations: every normalized object needs an id; ids must be unique across the whole app (use getNormalizationObjectKey for custom keys or to combine id with a type, similar to GraphQL's _typename); and objects sharing an id must have a consistent shape. The README also warns that tens of thousands of normalized objects can introduce overhead, so you can scope normalization to specific queries and mutations if needed. For libraries outside the four documented integrations, the README suggests opening a GitHub issue or modeling a new integration after @normy/react-query.