glacier

Keep your data fresh

Downloads
514
Stars
126
Committers
2

Bot releases are hidden (Show)

glacier - 1.0.80 - The optimistic fetch update

Published by hazae41 about 2 years ago

CHANGES

  • You can now return nothing in your updater in order to use the regular fetcher:
document.update(async function* () {
  yield { data: "My optimistic document" }
  await new Promise(ok => setTimeout(ok, 5000))
  // no return, will use the fetcher to get the new state
})

This is useful when you know the resource will be updated but want to display an optimistic state.
Also, { cache: "reload" } will be passed to the fetcher in order to skip the cache, feel free to pass it to JS fetch or Axios or ignore it

glacier - 1.0.77 - The update params update

Published by hazae41 about 2 years ago

BREAKING CHANGES

  • Mutations are now locked while an optimistic update is ongoing
  • You can pass custom timeout, expiration, cooldown to update: update(updater, params, aborter)
await document.update(async function* (previous) {
  yield { data: "My optimistic document" }
  return await postAsJson("/api/edit", "My updated document")
}, { timeout: 60 * 1000 })

CHANGES

  • Better error logging when aborted or timed out
glacier - 1.0.74 - The generated optimistic update

Published by hazae41 about 2 years ago

BREAKING CHANGES

  • New optimistic API with more control, just use "yield" with your optimistic state, which will be replaced if success or reverted if error
document.update(async function* (previous) {
  yield { data: "My optimistic document" }
  return await postAsJson("/api/edit", "My document")
})
glacier - 1.0.73 - The breaking update

Published by hazae41 about 2 years ago

BREAKING CHANGES

  • Removed N type parameter, just use Data | Ref in your first type parameter
BEFORE: XSWR.single<Data, Error, Ref>(...)

NOW: XSWR.single<Data | Ref, Error>(...)
  • Removed ParamsContext, for avoiding nasty bugs when you use a schema that's in another branch of the params tree. You can still use params in CoreContext for global params
  • Removed Normal in favor of a new normalization pattern with more control and more type safety
async function getDataRef(data: Data | Ref, more: XSWR.NormalizerMore) {
  if ("ref" in data) return data
  const schema = getDataSchema(data.id)
  await schema.normalize(data, more)
  return { ref: true, id: data.id } as Ref
}

See the docs for more details

CHANGES

  • Fixed comparison bug when calling first() on a normalized scrolling resource
glacier - 1.0.71 - The Suspense update

Published by hazae41 about 2 years ago

BREAKING CHANGES

  • fetch, refetch, first and scroll now throw on SSR

CHANGES

  • Added handle.suspend() a super natural and easy way to suspend your components
function Component() {
  const { data, error, suspend } = useData()

  // Throw the error
  if (error) throw error

  // Fetch and suspend until next state change
  if (!data) throw suspend()

  return <div>{JSON.stringify(data)}</div>
}

That's it, you have control over when you suspend and when your throw 🚀

  • Fixed bugs and simplified code
glacier - 1.0.69 - The lazy update

Published by hazae41 about 2 years ago

BREAKING CHANGES

  • Scroll resources now need to have a Normalized type that extends the Data type
    To put it another way, your Data type must have an union with your data and your normalized data:
return XSWR.scroll<Data | string, Error, string>(url, fetcher)

This is because on scroll, previous pages are in normalized form, but the next page is in data form

newData = [...previousPages: Normalized[], nextPage: Data]

CHANGES

  • Object states are now lazy initialized on fetch(), mutate(), refetch(), scroll(), update()
  • Fixed bugs
  • Fixed types
glacier - 1.0.64 - The synchronization update

Published by hazae41 about 2 years ago

BREAKING CHANGES

  • make(), Schema.make() and Object constructors no longer need init parameter, they will get data only once!
  • mutate() now accepts a function
mutate((currentState?: State) => State | undefined)

CHANGES

  • Improved handles synchronization, no longer double gets
  • Handles no longer require a memoized fetcher and static params
  • Handle and object methods will now wait for state initialization, no more need for ready check
  • Handles and schemas now accept an undefined fetcher; fetch() and refetch() will just return the current state
  • Simplified state mutation mechanism, 0% weird behaviour
  • Added a test for complex and nested store normalization
glacier - 1.0.60 - The normalization update

Published by hazae41 about 2 years ago

BREAKING CHANGES

  • All type parameters now follow the order D,E,N,K; some types may break if you used type parameters before

CHANGES

  • Added store normalization, out of the box, no dependency needed

Example

We'll use normalization for an array that contains items of type Data, each with an unique id

interface Data {
  id: string
  name: string
}

First, create a schema factory for an item

function getDataSchema(id: string) {
  return XSWR.single<Data>(`/api/data?id=${id}`, fetchAsJson)
}

Then, create a normal for an item

A normal is an object that encapsulates your data, its schema, and a reference to your data (so we can delete the original data and just keep the reference)

function getDataNormal(data: Data) {
  return new XSWR.Normal(data, getDataSchema(data.id), data.id)
}

Then, create a schema for your container, and create a normalizer, it will return then new structure of your container

In this case, all the array is mapped to normals, which will then automatically be replaced by references by XSWR

function getAllDataSchema() {
  function normalizer(data: Data[]) {
    return data.map(getDataNormal)
  }

  return XSWR.single<Data[], Error, string[]>(
    `/api/data/all`,
    fetchAsJson,
    { normalizer })
}

Notice the extra type parameter string[], it's the final type of our container, after normalization

That's it! No dependency needed, it just works!

You can find a full example in test/next/normalizer

glacier - 1.0.59 - The maker update

Published by hazae41 about 2 years ago

NO BREAKING CHANGES

CHANGES

  • make, Schema.make, and Object constructors now accept initialize as last optional parameter (default true) in order to initialize the object with the current state, it can be set to false for optimizing performances when you just need to call mutate and don't need the data, for example
const object = make(getHelloSchema(), false) // Won't load the state in the object
await object.mutate({ data: "Hello World" })
glacier - 1.0.58 - The storage garbage collection update

Published by hazae41 about 2 years ago

BREAKING CHANGES

  • AsyncLocalStorage and SyncLocalStorage (along with their hooks) now accept a prefix as first parameter
useAsyncLocalStorage("mycache")

Default prefix is xswr:

CHANGES

  • Storages are now doing garbage collection out of the box! ⚡️
  • Added garbage collection on unmount and on page unload for SyncLocalStorage and AsyncLocalStorage
  • Added garbage collection on unmount and on page load for IDBStorage
  • Added collect() and unmount() methods on all storages
glacier - 1.0.57 - The time update

Published by hazae41 about 2 years ago

BREAKING CHANGES

  • Renamed jsoneq to jsonEquals
  • Catched errors are no longer deduplicated or expired

CHANGES

  • You can now return a custom time in your fetcher
async function fetchAsJson<T>(url: string, more: XSWR.PosterMore<T>) {
  const { signal } = more

  const res = await fetch(url, { signal })
  const cooldown = Date.now() + (5 * 1000)
  const expiration = Date.now() + (10 * 1000)

  if (!res.ok) {
    const error = new Error(await res.text())
    return { error, cooldown, expiration } // implicit Date.now()
  }

  const data = await res.json() as T
  return { data, time: data.time, cooldown, expiration } // explicit date.time (milliseconds)
}
  • Fixed bugs
glacier - 1.0.56 - The error update

Published by hazae41 about 2 years ago

NO BREAKING CHANGES

CHANGES

  • You can now return an error in your fetcher instead of throwing
async function fetchAsJson<T>(url: string, more: XSWR.PosterMore<T>) {
  const { signal } = more

  const res = await fetch(url, { signal })
  const cooldown = Date.now() + (5 * 1000)
  const expiration = Date.now() + (10 * 1000)

  if (!res.ok) {
    const error = new Error(await res.text())
    return { error, cooldown, expiration }
  }

  const data = await res.json() as T
  return { data, cooldown, expiration }
}

This way you can still set expiration and cooldown

  • Added scroll tests
  • New mutation merge strategy (not breaking)
  • Bug fixes and performances improvements
glacier - 1.0.55 - The optimistic update

Published by hazae41 about 2 years ago

BREAKING CHANGES

  • refetch() now cancels ongoing requests (unless it's an optimistic update)
  • update() no longer throws on error, it just mutates the state with the error (you can still check for error by checking the returned state)

CHANGES

  • handle.aborter is now available on optimistic updates
  • handle.optimistic is now available to tell whether the ongoing request is optimistic
  • Lot of bug fixes and behaviour fixes
glacier - 1.0.52 - The IndexedDB update

Published by hazae41 about 2 years ago

NO BREAKING CHANGE

CHANGES

  • You can now use IndexedDB storage 🚀
const storage = new XSWR.IDBStorage("mydb")

function getHelloSchema() { // See the docs for the new schema pattern
  return XSWR.single("/api/hello", fetchAsJson, { storage })
}
  • Improved performances
glacier - 1.0.51 - The schema memo update

Published by hazae41 about 2 years ago

BREAKING CHANGES

  • New syntax for XSWR.use: XSWR.use(schema) => XSWR.use(factory, deps)
function getCatShema(id: string) {
  return XSWR.single(["/api/cat", id], fetchAsJson)
}

function useCatBase(id: string) {
 return XSWR.use(getCatSchema, [id])
}

It works like useMemo but the deps are passed to the factory.

glacier - 1.0.49 - The schemas update

Published by hazae41 about 2 years ago

NO BREAKING CHANGES

CHANGES

  • You can now use your favorite resources without using a hook, thanks to schemas and objects:
// Create a schema for your resource
function getHelloSchema(id: string) {
  return XSWR.single("/api/hello", fetchAsJson)
}

// Use it in a hook
function useHello(id: string) {
  const handle = XSWR.use(getHelloSchema(id))

  XSWR.useFetch(handle)
  return handle
}

// Or in a function
function Setter() {
  const { make } = XSWR.useXSWR()

  const set = useCallback(async () => {
    const object = make(getHelloSchema("123"))
    await object.mutate({ data: "hello world" })
    await object.refetch()
  }, [make])

  return <button onClick={set}>
    Click me
  </button>
}
glacier - 1.0.45 - The core parameters update

Published by hazae41 about 2 years ago

NO BREAKING CHANGES

CHANGES

  • You can now use XSWR.ParamsProvider to provide custom params to all children without changing the core provider
export default function Wrapper() {
  return <XSWR.ParamsProvider
    serializer={GZIP}>
    <Page />
  </XSWR.ParamsProvider>
}

Since params = { ...parent, ...current } the downmost params will override.
If I then use a custom serializer in my handle, JSON will be used instead of GZIP.

useSingle(url, fetcher, { serializer: JSON })
glacier - 1.0.42 - The parameters update

Published by hazae41 about 2 years ago

NO BREAKING CHANGES

CHANGES

  • You can now use a custom storage in handle factories
// Create a storage in the hook or at top-level
const storage = XSWR.useAsyncLocalStorage()

const handle = XSWR.useSingle(
  "/api/hello",
  fetchAsJson,
 { storage })

XSWR.useFetch(handle)
return handle
  • You can now use a custom key serializer in handle factories
const handle = XSWR.useSingle(
  "/api/hello",
  fetchAsJson,
 { serializer: GZIP })

XSWR.useFetch(handle)
return handle
  • You can now use a custom equals function in handle factories
const handle = XSWR.useSingle(
  "/api/hello",
  fetchAsJson,
 { equals: deepCompare })

XSWR.useFetch(handle)
return handle
glacier - 1.0.40 - The serializer update

Published by hazae41 about 2 years ago

NO BREAKING CHANGES

CHANGES

  • Allow custom serializer in Core, for serializing arbitrary keys
  • Allow custom serializer in LocalStorages, for serializing states
  • Default serializer is JSON, i added GZIP example in tests
glacier - 1.0.39 - The storage update

Published by hazae41 about 2 years ago

NO BREAKING CHANGES

CHANGES

  • Split cache and storage
  • Added support for async storages
  • Added AsyncLocalStorage (SSR compatible) and SyncLocalStorage (no SSR)
  • Fixed bugs on core unmount
  • Improved performances by avoiding multiple get()
  • Added tests for localStorage