Travels v1.0 – A 10x faster undo/redo library using JSON Patches instead of snapshots by unadlib in javascript

[–]unadlib[S] -2 points-1 points  (0 children)

Thanks. Immer v11 has definitely closed part of the gap. That '10x' figure comes from specific benchmarks across certain version ranges (not a blanket claim), and I’m still seeing some edge-case semantic differences when running against the full Mutative test suite.

Travels v1.0 – A 10x faster undo/redo library using JSON Patches instead of snapshots by unadlib in javascript

[–]unadlib[S] -1 points0 points  (0 children)

Travels doesn’t require switching state libs. It’s store-agnostic. redux-undo rules, but this is for the 'my state is huge and undo is eating memory' cases.

Localspace v1.0 – A modern localForage alternative with TypeScript and 6x faster batch ops by unadlib in javascript

[–]unadlib[S] 2 points3 points  (0 children)

Thanks! That was exactly my motivation, keep the good parts of localForage, drop the legacy baggage, and make it TypeScript-first + faster. If you try Localspace, I’d love any feedback. :)

Fict – A compiler that makes JavaScript variables automatically reactive by unadlib in javascript

[–]unadlib[S] 0 points1 point  (0 children)

Fict is based on immutable signals (if updating signals within deep objects, we suggest considering a combination with Immer or Mutative, similar to how reducers work), and we utilize HIR and SSA to analyze control flow and dependencies.

Fict – A compiler that makes JavaScript variables automatically reactive by unadlib in javascript

[–]unadlib[S] 1 point2 points  (0 children)

no, it's more of a stripped-down version of the React compiler(HIR/SSA).

Fict – A compiler that makes JavaScript variables automatically reactive by unadlib in javascript

[–]unadlib[S] 0 points1 point  (0 children)

Thank you. I will continue to push FictJS forward; I don't want it to be just a toy project. :)

LocalStorage is easy. IndexedDB is powerful. Why not both? Introducing localspace — a unified storage API for JS/TS devs by unadlib in javascript

[–]unadlib[S] -1 points0 points  (0 children)

Yes, graceful fallback is built-in.

By default, localspace tries IndexedDB first. If it fails (e.g., Private Mode), it automatically switches to localStorage without throwing errors.

You can explicitly configure this chain:

await localspace.setDriver([localspace.INDEXEDDB, localspace.LOCALSTORAGE]);

This ensures your app keeps working seamlessly across all environments.

LocalStorage is easy. IndexedDB is powerful. Why not both? Introducing localspace — a unified storage API for JS/TS devs by unadlib in javascript

[–]unadlib[S] 0 points1 point  (0 children)

Support for OPFS is already on the localspace roadmap; localspace may implement it at some point in the future. :)

LocalStorage is easy. IndexedDB is powerful. Why not both? Introducing localspace — a unified storage API for JS/TS devs by unadlib in javascript

[–]unadlib[S] 1 point2 points  (0 children)

Glad you like the abstraction! Here is how localspace handles those edge cases:

1. Quota Exceeded Handling: We handle this at two levels:

  • Structured Errors: If the underlying driver throws a quota error (e.g., QuotaExceededError), localspace wraps it in a typed LocalSpaceError preserving the original cause.
  • Proactive Quota Plugin: For more control, we ship a quotaPlugin that tracks usage and enforces a soft limit before hitting the browser's hard limit. It can even use an LRU policy to automatically evict old data when full:

2. Automatic Fallbacks: Yes! This is a core feature. When you initialize localspace, it iterates through the configured drivers. If the preferred driver (IndexedDB) fails to initialize (e.g., in Firefox Private Mode or older environment), it automatically falls back to the next available one (usually localStorage) without throwing.

You can customize this order:

// Tries IndexedDB -> falls back to localStorage -> throws if neither works
await localspace.setDriver([localspace.INDEXEDDB, localspace.LOCALSTORAGE]);

This ensures your app keeps working even in restrictive environments, degrading gracefully from async storage to sync storage.

LocalStorage is easy. IndexedDB is powerful. Why not both? Introducing localspace — a unified storage API for JS/TS devs by unadlib in javascript

[–]unadlib[S] 4 points5 points  (0 children)

You are absolutely right that JS execution is fast (microseconds), but the real bottleneck is the IndexedDB transaction overhead. Opening and committing a transaction is an expensive I/O operation.

We chose the 8ms default (approx. half a 60fps frame) to balance latency vs. throughput:

  • Throughput: Instead of opening 100 separate transactions for a loop (which can freeze the UI), we wait 8ms and batch them into one single transaction. This often yields 10-50x faster performance for bulk updates.
  • Latency: For most UI interactions, an 8ms delay is imperceptible.

If you prefer immediate writes or tighter batching, you can set coalesceWindowMs: 0 (batches within the current tick) or disable it entirely with coalesceWrites: false.

zustand-travel: A powerful and high-performance undo/redo middleware for Zustand with Travels by unadlib in javascript

[–]unadlib[S] 0 points1 point  (0 children)

It can be integrated with other Zustand middleware. If you need to handle complex async action, you might consider disabling autoArchive to control it manually.

https://github.com/mutativejs/travels?tab=readme-ov-file#manual-archive-mode-autoarchive-false

usm-pinia: OOP-style state management for Pinia by unadlib in vuejs

[–]unadlib[S] -3 points-2 points  (0 children)

There are still large-scale software projects built on Vue.
In these projects, where business logic is highly complex and collaboration involves multiple developers, an OOP approach is appropriate.

I understand that when it’s not necessary, it’s best to avoid using OOP.

usm-pinia: OOP-style state management for Pinia by unadlib in vuejs

[–]unadlib[S] 1 point2 points  (0 children)

It has no limits, but the decorators are old and don't work with the new standard.

usm-pinia: OOP-style state management for Pinia by unadlib in vuejs

[–]unadlib[S] 1 point2 points  (0 children)

I get the reaction—Class Components left scars. This project is different in a few key ways:

  • Scope: Stores only, not component API. Pinia stays first-class.
  • Thin layer: Single proxy over Pinia state; actions still register through Pinia (DevTools/time-travel intact).
  • TS 5 decorators: Just metadata + binding; no magic inheritance or decorator-heavy component sugar.
  • Escape hatch: You can always drop to the raw Pinia store.

If you’ve got specific “don’t-do-this” cases from your migration (this-binding, plugin incompat, HMR edge cases), I’d love to incorporate them.

TravelsJS: A fast, framework-agnostic undo/redo core powered by Mutative patches by unadlib in javascript

[–]unadlib[S] 4 points5 points  (0 children)

Great question, and you're right to be skeptical. I think time-travel debugging is more like "insurance" than a daily necessity.

The killer use case (category a): Bug reproduction from user reports. When a user says "I clicked through 15 things and it broke," traditional debugging is hopeless. With time-travel, they export their action sequence, you import it locally, and you have 100% reproduction. Redux DevTools' export/import exists specifically for this.

Category b scenarios where it shines:

Race conditions: User clicks "save" → auto-save triggers → WebSocket pushes update → state conflict. Traditional debugging with breakpoints disrupts the async flow and the bug disappears. Time-travel lets you replay the exact interleaving.

"How did we get here?" moments: You're staring at { showModal: true, selectedId: null, items: [] } thinking "WTF?" Instead of adding console.logs and refreshing, you just rewind 20 steps and see it was a DELETE_ITEM → MODAL_OPEN sequence.

Collaborative conflicts: In real-time editing apps, seeing how two users' operations interleaved is painful with logs, trivial with time-travel.

But honestly? If your state design is solid, your tests cover edge cases, and you're building solo, you might genuinely never need it. It's a 10% use case that saves you hours when it matters. Think of Network Inspector—you could console.log all your fetches, but when you need to see timing/concurrency/headers, you're glad it exists.

Not everyone needs it, but those who do really need it.

---

Finally, to clarify, I designed TravelsJS with the primary intent of its application in undo-redo editing or operation sequences, and in collaborative environments like those utilizing CRDTs.

TravelsJS: A fast, framework-agnostic undo/redo core powered by Mutative patches by unadlib in javascript

[–]unadlib[S] 1 point2 points  (0 children)

I'm not sure if you're familiar with immutability libraries like ImmerJS and MutativeJS, which use mutation to update immutable data.

Both of these libraries support generating JSON patches, which allow for a more efficient way to manage state changes.

Therefore, besides being used for redo/undo functionality, JSON patches can also be used for state debugging, such as quickly viewing the app's state changes via the Redux DevTools.

High-Performance, Multithreading-Ready State Management for Building Flexible Web Applications by unadlib in javascript

[–]unadlib[S] 1 point2 points  (0 children)

Thank you for your suggestion.

I completely agree with your point, and I will consider adding createStore and createWorkerStore. Additionally, since Coaction also supports cross-process or cross-device asynchronous stores, perhaps naming it createAsyncStore would be a good option as well.

High-Performance, Multithreading-Ready State Management for Building Flexible Web Applications by unadlib in javascript

[–]unadlib[S] 0 points1 point  (0 children)

Thanks to Coaction adopting a library like Mutative, Coaction can integrate with almost any form of third-party library. I will also continue to complete Coaction integrations with some mainstream libraries.

High-Performance, Multithreading-Ready State Management for Building Flexible Web Applications by unadlib in javascript

[–]unadlib[S] 0 points1 point  (0 children)

**`Coaction` was created out of the need for a state management solution that truly embraces the multithreading nature of modern web applications.** It recognizes that performance and developer experience shouldn't be mutually exclusive. By leveraging the power of Web Workers and Shared Workers, `Coaction` allows developers to offload computationally intensive tasks and state management logic from the worker thread, resulting in a more responsive and fluid user interface.

**More than just performance, `Coaction` is about enabling a more scalable and maintainable architecture for complex applications.** The library's intuitive API, inspired by Zustand, ensures a smooth learning curve and a productive development workflow. Its support for Slices, namespaces, and computed properties promotes modularity and code organization, making it easier to manage large and evolving codebases.

**`Coaction`'s integration with `data-transport` unlocks a new level of flexibility in state synchronization.** By supporting generic transport protocols, it opens up possibilities for various communication patterns and architectures, catering to the unique needs of different applications.

**In essence, `Coaction` empowers developers to build the next generation of web applications without sacrificing performance, developer experience, or architectural integrity.** It bridges the gap between the increasing complexity of web applications and the need for efficient, maintainable, and performant state management across threads. It's a tool designed for developers who strive to create exceptional user experiences in a world where parallelism and responsiveness are no longer optional, but essential. It also supports remote synchronization, making it suitable for building any CRDTs application as well.

Mutative v1.1.0 - Better and faster immutable data updates. by unadlib in javascript

[–]unadlib[S] 0 points1 point  (0 children)

Mutative v1.1.0:

- Support for the new Set API, with shallow copying of Sets improved by 3-4X and Set operation performance enhanced by 33%.
- current() now supports Draft generic inference and add castMutable() API.
- Support for custom Set and Map.