v0.19: Batch Controller.set(), Faster TypeScript
· 25 min read
v0.19 lets a Manager write a whole batch of streamed rows in one store update, type-checks endpoint code about 2x faster, and fixes a round of TypeScript and Vue issues. Coding agents also get a Claude Code plugin, Vue skills and llms.txt; see Data Client for Coding Agents.
New APIs:
- Controller.set() with Array schemas - Write many entities in one store update with
ctrl.set([Entity], rows), up to 95x faster than oneset()per row
Performance:
- Faster TypeScript - Editors and
tsccheck RestEndpoint and resource() code about 2x faster with 40% less memory, catching every error they caught before
Other Improvements:
- Fix TypeScript 7 module resolution for package
exports; imports now resolve to declaration files (#4019) - renderDataHook() runs provider mount effects when the first render suspends (#4099)
- Controller.set() values are typed by the schema, so
ctrl.set(new schema.All(Todo), 42)is a TypeScript error (#4133) - Controller.set() deletes one entity with an Invalidate schema without the one-row batch workaround (#4230)
- process() gets typed params in
new RestEndpoint(),.extend()andresource().extend(), so a wrong path parameter is a TypeScript error instead ofundefinedat runtime (#4183, #4184) - Vue useSuspense() and useLive() keep the previous data while new arguments load, instead of returning
undefined(#4131) - Vue useSuspense() and useLive() send fetch errors after arguments change to
onErrorCaptured()instead of an unhandled promise rejection (#4135) - Vue useSuspense(), useDLE() and useFetch() no longer refetch stale data on every store update, so a
controller.set()is not overwritten (#4134) - Vue useSuspense() shows stale data on mount and refetches in the background, like React, instead of showing the
<Suspense>fallback until the refetch finishes (#4169) - Vue useDLE() and useCache() keep expired
invalidIfStaledata through unrelated store updates instead of getting stuck loading (#4142) - Vue
DataClientPlugininstalls on Vue versions before 3.5 instead of throwingapp.onUnmount is not a function(#4146) - Vue DataClientPlugin garbage collects by default, matching React's DataProvider, so you no longer need to pass
gcPolicy; how it decides what to remove (#4148) - Vue composables accept getter arguments like
() => ({ id: props.id }); they were typed to allow them but passed the function itself to the endpoint (#4115) - Fix
Cannot find name 'NoInfer'andexport typeerrors on TypeScript 4.x withskipLibCheckoff (#4138) - Fix
Entity,Endpoint,UnionandRestEndpointtype errors on TypeScript 4.0–4.5 withskipLibCheckoff (#4140) - Fix
',' expectederrors importing@data-client/react/redux,@data-client/react/nextjsor@data-client/teston TypeScript 4.0–4.4 (#4232) - Fix
actandrenderHookfrom@data-client/testtyped asanyon TypeScript 4.0–4.4 (#4251) - Entity classes can be used where an
EntityInterfaceis expected (#4149); preparepk()overrides for a future release - useCache() and useDLE() return
undefinedfor a deleted entity whose refetch failed, instead of a truthySymbolthat slipped pastif (!data)checks; remove any workarounds (#4150) - Vue useFetch() keeps its data from being garbage collected while mounted, like useSuspense(), so a configured
gcPolicyno longer evicts prefetched data that components read later (#4152) - Apps with Redux DevTools open no longer stutter in development on large stores or frequent updates; each update serializes 40-60x faster (#4163)
- resource().extend() with an object of endpoint overrides keeps endpoints added earlier with
.extend('name', options)in its type, so using them is no longer a TypeScript error (#4184) - RestEndpoint.push,
unshiftandremoveaccept the Entity's fields as the body when a Query or Lazy wraps the Collection, instead of onlyFormData(#4226) - Vue useFetch() is typed as the read-only
Refit returns, sopromise.resolved(alwaysundefined) is now a TypeScript error; readpromise.value.resolvedinstead (#4114) - A
Controllersubclass passed to DataProvider or DataClientPlugin no longer needs a cast to type-check (#4228) - prepareStore()'s
storecan be passed to react-redux's<Provider>without a cast, and hasdispatch()in its type (#4238) - resource().create accepts FormData without a cast, like
update,partialUpdateandgetList.push(#4235) - Vue
createDataClient()is deprecated, since it's internal to DataClientPlugin; install the plugin withapp.use(DataClientPlugin, options)instead of calling it directly (#4193) - Vue
renderDataCompose()'swaitForNextUpdate()is deprecated, since it gives up silently after 1 second and lets a test pass while still suspended;await resultinstead, orawait allSettled()after a change, which now also waits for fetches a prop change starts (unit testing composables, #4221)
- TypeScript 4.0 or later is required - the TypeScript 3.x declarations are removed (#4151)
