Skip to content

Releases: reactive/data-client

@data-client/vue@0.2.0-beta-20251022010821-0e5f6bd2963b6deecb68b5febe71cdd3b10c801a

22 Oct 01:21
db8bb7d

Choose a tag to compare

Minor Changes

Patch Changes

@data-client/rest@0.15.0-beta-20251022010821-0e5f6bd2963b6deecb68b5febe71cdd3b10c801a

22 Oct 01:21
db8bb7d

Choose a tag to compare

Patch Changes

@data-client/graphql@0.15.0-beta-20251022010821-0e5f6bd2963b6deecb68b5febe71cdd3b10c801a

22 Oct 01:21
db8bb7d

Choose a tag to compare

Patch Changes

@data-client/endpoint@0.15.0-beta-20251022010821-0e5f6bd2963b6deecb68b5febe71cdd3b10c801a

22 Oct 01:21
db8bb7d

Choose a tag to compare

Patch Changes

@data-client/test@0.15.0-beta-20251006024044-92bd01c4976f2921993b8c9f1e4dbb87af87ba7b

06 Oct 02:47
742a7c1

Choose a tag to compare

Minor Changes

  • #3394 d44d36a Thanks @ntucker! - Change NetworkManager bookkeeping data structure for inflight fetches

    BREAKING CHANGE: NetworkManager.fetched, NetworkManager.rejectors, NetworkManager.resolvers, NetworkManager.fetchedAt
    -> NetworkManager.fetching

    Before

    if (action.key in this.fetched)

    After

    if (this.fetching.has(action.key))
  • 769cb78 Thanks @ntucker! - Support 0.15 of @data-client/react

Patch Changes

@data-client/rest@0.15.0-beta-20251006024044-92bd01c4976f2921993b8c9f1e4dbb87af87ba7b

06 Oct 02:47
742a7c1

Choose a tag to compare

Minor Changes

  • #3461 939a4b0 Thanks @ntucker! - Add delegate.INVALID to queryKey

    This is used in schema.All.queryKey().

    Before

    queryKey(args: any, unvisit: any, delegate: IQueryDelegate): any {
      if (!found) return INVALID;
    }

    After

    queryKey(args: any, unvisit: any, delegate: IQueryDelegate): any {
      if (!found) return delegate.INVALID;
    }
  • #3461 939a4b0 Thanks @ntucker! - Add delegate.invalidate() to normalization

    Before

    normalize(
      input: any,
      parent: any,
      key: string | undefined,
      args: any[],
      visit: (...args: any) => any,
      delegate: INormalizeDelegate,
    ): string {
      delegate.setEntity(this as any, pk, INVALID);
    }

    After

    normalize(
      input: any,
      parent: any,
      key: string | undefined,
      args: any[],
      visit: (...args: any) => any,
      delegate: INormalizeDelegate,
    ): string {
      delegate.invalidate(this as any, pk);
    }
  • #3449 1f491a9 Thanks @ntucker! - BREAKING CHANGE: schema.normalize(...args, addEntity, getEntity, checkLoop) -> schema.normalize(...args, delegate)

    We consolidate all 'callback' functions during recursion calls into a single 'delegate' argument.

    /** Helpers during schema.normalize() */
    export interface INormalizeDelegate {
      /** Action meta-data for this normalize call */
      readonly meta: { fetchedAt: number; date: number; expiresAt: number };
      /** Gets any previously normalized entity from store */
      getEntity: GetEntity;
      /** Updates an entity using merge lifecycles when it has previously been set */
      mergeEntity(
        schema: Mergeable & { indexes?: any },
        pk: string,
        incomingEntity: any,
      ): void;
      /** Sets an entity overwriting any previously set values */
      setEntity(
        schema: { key: string; indexes?: any },
        pk: string,
        entity: any,
        meta?: { fetchedAt: number; date: number; expiresAt: number },
      ): void;
      /** Returns true when we're in a cycle, so we should not continue recursing */
      checkLoop(key: string, pk: string, input: object): boolean;
    }

    Before

    addEntity(this, processedEntity, id);

    After

    delegate.mergeEntity(this, id, processedEntity);
  • #3461 939a4b0 Thanks @ntucker! - Remove INVALID symbol export

    Schemas can use delegate.invalidate() in normalize() or return delegate.INVALID in queryKey().

  • #3449 1f491a9 Thanks @ntucker! - BREAKING CHANGE: schema.queryKey(args, queryKey, getEntity, getIndex) -> schema.queryKey(args, unvisit, delegate)
    BREAKING CHANGE: delegate.getIndex() returns the index directly, rather than object.

    We consolidate all 'callback' functions during recursion calls into a single 'delegate' argument.

    Our recursive call is renamed from queryKey to unvisit, and does not require the last two arguments.

    /** Accessors to the currently processing state while building query */
    export interface IQueryDelegate {
      getEntity: GetEntity;
      getIndex: GetIndex;
    }

    Before

    queryKey(args, queryKey, getEntity, getIndex) {
      getIndex(schema.key, indexName, value)[value];
      getEntity(this.key, id);
      return queryKey(this.schema, args, getEntity, getIndex);
    }

    After

    queryKey(args, unvisit, delegate) {
      delegate.getIndex(schema.key, indexName, value);
      delegate.getEntity(this.key, id);
      return unvisit(this.schema, args);
    }

Patch Changes

  • #3449 1f491a9 Thanks @ntucker! - Fix: ensure string id in Entity set when process returns undefined (meaning INVALID)

  • #3560 ba31c9b Thanks @ntucker! - Add Collection.remove

    ctrl.set(MyResource.getList.schema.remove, { id });
    const removeItem = MyResource.delete.extend({
      schema: MyResource.getList.schema.remove,
    });
  • #3558 fcb7d7d Thanks @ntucker! - Normalize delegate.invalidate() first argument only has key param.

    indexes optional param no longer provided as it was never used.

    normalize(
      input: any,
      parent: any,
      key: string | undefined,
      args: any[],
      visit: (...args: any) => any,
      delegate: INormalizeDelegate,
    ): string {
      delegate.invalidate({ key: this._entity.key }, pk);
      return pk;
    }
  • #3558 fcb7d7d Thanks @ntucker! - Unions can query() without type discriminator

    Before

    // @ts-expect-error
    const event = useQuery(EventUnion, { id });
    // event is undefined
    const newsEvent = useQuery(EventUnion, { id, type: 'news' });
    // newsEvent is found

    After

    const event = useQuery(EventUnion, { id });
    // event is found
    const newsEvent = useQuery(EventUnion, { id, type: 'news' });
    // newsEvent is found
  • 35552c7 Thanks @ntucker! - Include GPT link badge in readme

  • Updated dependencies [1f491a9, 939a4b0, 939a4b0, ba31c9b, fcb7d7d, 1f491a9, 4dde1d6, bab907c, 5699005, 939a4b0, fcb7d7d, 1f491a9, 35552c7]:

@data-client/react@0.15.0-beta-20251006024044-92bd01c4976f2921993b8c9f1e4dbb87af87ba7b

06 Oct 02:47
742a7c1

Choose a tag to compare

Minor Changes

  • #3459 997ca20 Thanks @ntucker! - BREAKING CHANGE: useDebounce() returns [val, isPending]

    This was previously exported in @data-client/react/next to make migrations easy. This will
    still be available there.

    Before

    import { useDebounce } from '@data-client/react';
    const debouncedQuery = useDebounce(query, 100);

    After

    import { useDebounce } from '@data-client/react';
    const [debouncedQuery] = useDebounce(query, 100);

    Before

    import { useDebounce } from '@data-client/react/next';
    const [debouncedQuery, isPending] = useDebounce(query, 100);

    After

    import { useDebounce } from '@data-client/react';
    const [debouncedQuery, isPending] = useDebounce(query, 100);
  • #3449 1f491a9 Thanks @ntucker! - BREAKING CHANGE: schema.normalize(...args, addEntity, getEntity, checkLoop) -> schema.normalize(...args, delegate)

    We consolidate all 'callback' functions during recursion calls into a single 'delegate' argument.

    /** Helpers during schema.normalize() */
    export interface INormalizeDelegate {
      /** Action meta-data for this normalize call */
      readonly meta: { fetchedAt: number; date: number; expiresAt: number };
      /** Gets any previously normalized entity from store */
      getEntity: GetEntity;
      /** Updates an entity using merge lifecycles when it has previously been set */
      mergeEntity(
        schema: Mergeable & { indexes?: any },
        pk: string,
        incomingEntity: any,
      ): void;
      /** Sets an entity overwriting any previously set values */
      setEntity(
        schema: { key: string; indexes?: any },
        pk: string,
        entity: any,
        meta?: { fetchedAt: number; date: number; expiresAt: number },
      ): void;
      /** Returns true when we're in a cycle, so we should not continue recursing */
      checkLoop(key: string, pk: string, input: object): boolean;
    }

    Before

    addEntity(this, processedEntity, id);

    After

    delegate.mergeEntity(this, id, processedEntity);
  • #3451 4939456 Thanks @ntucker! - state.entityMeta -> state.entitiesMeta

  • #3449 1f491a9 Thanks @ntucker! - BREAKING CHANGE: schema.queryKey(args, queryKey, getEntity, getIndex) -> schema.queryKey(args, unvisit, delegate)
    BREAKING CHANGE: delegate.getIndex() returns the index directly, rather than object.

    We consolidate all 'callback' functions during recursion calls into a single 'delegate' argument.

    Our recursive call is renamed from queryKey to unvisit, and does not require the last two arguments.

    /** Accessors to the currently processing state while building query */
    export interface IQueryDelegate {
      getEntity: GetEntity;
      getIndex: GetIndex;
    }

    Before

    queryKey(args, queryKey, getEntity, getIndex) {
      getIndex(schema.key, indexName, value)[value];
      getEntity(this.key, id);
      return queryKey(this.schema, args, getEntity, getIndex);
    }

    After

    queryKey(args, unvisit, delegate) {
      delegate.getIndex(schema.key, indexName, value);
      delegate.getEntity(this.key, id);
      return unvisit(this.schema, args);
    }

Patch Changes

@data-client/normalizr@0.15.0-beta-20251006024044-92bd01c4976f2921993b8c9f1e4dbb87af87ba7b

06 Oct 02:47
742a7c1

Choose a tag to compare

Minor Changes

  • #3421 246cde6 Thanks @ntucker! - BREAKING CHANGE: Denormalize always transforms immutablejs entities into the class

    Previously using ImmutableJS structures when calling denormalize() would maintain
    nested schemas as immutablejs structures still. Now everything is converted to normal JS.
    This is how the types have always been specified.

  • #3468 4dde1d6 Thanks @ntucker! - BREAKING: denormalize no longer detects ImmutableJS state

    Use /imm exports to handle ImmutableJS state

    Before

    import { MemoCache, denormalize } from '@data-client/normalizr';
    
    const memo = new MemoCache();

    After

    import { MemoCache } from '@data-client/normalizr';
    import { MemoPolicy, denormalize } from '@data-client/normalizr/imm';
    
    const memo = new MemoCache(MemoPolicy);
  • #3461 939a4b0 Thanks @ntucker! - Add delegate.INVALID to queryKey

    This is used in schema.All.queryKey().

    Before

    queryKey(args: any, unvisit: any, delegate: IQueryDelegate): any {
      if (!found) return INVALID;
    }

    After

    queryKey(args: any, unvisit: any, delegate: IQueryDelegate): any {
      if (!found) return delegate.INVALID;
    }
  • #3461 939a4b0 Thanks @ntucker! - Add delegate.invalidate() to normalization

    Before

    normalize(
      input: any,
      parent: any,
      key: string | undefined,
      args: any[],
      visit: (...args: any) => any,
      delegate: INormalizeDelegate,
    ): string {
      delegate.setEntity(this as any, pk, INVALID);
    }

    After

    normalize(
      input: any,
      parent: any,
      key: string | undefined,
      args: any[],
      visit: (...args: any) => any,
      delegate: INormalizeDelegate,
    ): string {
      delegate.invalidate(this as any, pk);
    }
  • #3454 66e1906 Thanks @ntucker! - BREAKING CHANGE: MemoCache.query() and MemoCache.buildQueryKey() take state as one argument

    Before

    this.memo.buildQueryKey(schema, args, state.entities, state.indexes, key);

    After

    this.memo.buildQueryKey(schema, args, state, key);

    Before

    this.memo.query(schema, args, state.entities, state.indexes);

    After

    this.memo.query(schema, args, state);
  • #3449 1f491a9 Thanks @ntucker! - BREAKING CHANGE: schema.normalize(...args, addEntity, getEntity, checkLoop) -> schema.normalize(...args, delegate)

    We consolidate all 'callback' functions during recursion calls into a single 'delegate' argument.

    /** Helpers during schema.normalize() */
    export interface INormalizeDelegate {
      /** Action meta-data for this normalize call */
      readonly meta: { fetchedAt: number; date: number; expiresAt: number };
      /** Gets any previously normalized entity from store */
      getEntity: GetEntity;
      /** Updates an entity using merge lifecycles when it has previously been set */
      mergeEntity(
        schema: Mergeable & { indexes?: any },
        pk: string,
        incomingEntity: any,
      ): void;
      /** Sets an entity overwriting any previously set values */
      setEntity(
        schema: { key: string; indexes?: any },
        pk: string,
        entity: any,
        meta?: { fetchedAt: number; date: number; expiresAt: number },
      ): void;
      /** Returns true when we're in a cycle, so we should not continue recursing */
      checkLoop(key: string, pk: string, input: object): boolean;
    }

    Before

    addEntity(this, processedEntity, id);

    After

    delegate.mergeEntity(this, id, processedEntity);
  • #3468 4dde1d6 Thanks @ntucker! - delegate.getEntity(key) -> delegate.getEntities(this.key)

    Return value is a restricted interface with keys() and entries() iterator methods.
    This applies to both schema.queryKey and schema.normalize method delegates.

    const entities = delegate.getEntities(key);
    
    // foreach on keys
    for (const key of entities.keys()) {
    }
    // Object.keys() (convert to array)
    return [...entities.keys()];
    // foreach on full entry
    for (const [key, entity] of entities.entries()) {
    }

    Before

    const entities = delegate.getEntity(this.key);
    if (entities)
      Object.keys(entities).forEach(collectionPk => {
        if (!filterCollections(JSON.parse(collectionPk))) return;
        delegate.mergeEntity(this, collectionPk, normalizedValue);
      });

    After

    const entities = delegate.getEntities(this.key);
    if (entities)
      for (const collectionKey of entities.keys()) {
        if (!filterCollections(JSON.parse(collectionKey))) continue;
        delegate.mergeEntity(this, collectionKey, normalizedValue);
      }
  • #3451 4939456 Thanks @ntucker! - state.entityMeta -> state.entitiesMeta

  • #3372 25b153a Thanks @ntucker! - MemoCache.query returns { data, paths } just like denormalize. data could be INVALID

    Before

    return this.memo.query(schema, args, state);

    After

    const { data } = this.memo.query(schema, args, state);
    return typeof data === 'symbol' ? undefined : (data as any);
  • #3449 1f491a9 Thanks @ntucker! - BREAKING CHANGE: schema.queryKey(args, queryKey, getEntity, getIndex) -> schema.queryKey(args, unvisit, delegate)
    BREAKING CHANGE: delegate.getIndex() returns the index directly, rather than object.

    We consolidate all 'callback' functions during recursion calls into a single 'delegate' argument.

    Our recursive call is renamed from queryKey to unvisit, and does not require the last two arguments.

    /** Accessors to the currently processing state while building query */
    export interface IQueryDelegate {
      getEntity: GetEntity;
      getIndex: GetIndex;
    }

    Before

    queryKey(args, queryKey, getEntity, getIndex) {
      getIndex(schema.key, indexName, value)[value];
      getEntity(this.key, id);
      return queryKey(this.schema, args, getEntity, getIndex);
    }

    After

    queryKey(args, unvisit, delegate) {
      delegate.getIndex(schema.key, indexName, value);
      delegate.getEntity(this.key, id);
      return unvisit(this.schema, args);
    }

Patch Changes

  • #3468 4dde1d6 Thanks @ntucker! - Add /imm exports path for handling ImmutableJS state

    MemoCache

    import { MemoCache } from '@data-client/normalizr';
    import { MemoPolicy } from '@data-client/normalizr/imm';
    
    const memo = new MemoCache(MemoPolicy);
    
    // entities is an ImmutableJS Map
    const value = MemoCache.denormalize(Todo, '1', entities);

    denormalize

    non-memoized denormalize

    import { denormalize } from '@data-client/normalizr/imm';
    
    // entities is an ImmutableJS Map
    const value = denormalize(Todo, '1', entities);
  • #3558 fcb7d7d Thanks @ntucker! - Normalize delegate.invalidate() first argument only has key param.

    indexes optional param no longer provided as it was never used.

    normalize(
      input: any,
      parent: any,
      key: string | undefined,
      args: any[],
      visit: (...args: any) => any,
      delegate: INormalizeDelegate,
    ): string {
      delegate.invalidate({ key: this._entity.key }, pk);
      return pk;
    }
  • #3468 4dde1d6 Thanks @ntucker! - Improve performance of ge...

Read more

@data-client/img@0.15.0-beta-20251006024044-92bd01c4976f2921993b8c9f1e4dbb87af87ba7b

06 Oct 02:47
742a7c1

Choose a tag to compare

@data-client/graphql@0.15.0-beta-20251006024044-92bd01c4976f2921993b8c9f1e4dbb87af87ba7b

06 Oct 02:47
742a7c1

Choose a tag to compare

Minor Changes

  • #3461 939a4b0 Thanks @ntucker! - Add delegate.INVALID to queryKey

    This is used in schema.All.queryKey().

    Before

    queryKey(args: any, unvisit: any, delegate: IQueryDelegate): any {
      if (!found) return INVALID;
    }

    After

    queryKey(args: any, unvisit: any, delegate: IQueryDelegate): any {
      if (!found) return delegate.INVALID;
    }
  • #3461 939a4b0 Thanks @ntucker! - Add delegate.invalidate() to normalization

    Before

    normalize(
      input: any,
      parent: any,
      key: string | undefined,
      args: any[],
      visit: (...args: any) => any,
      delegate: INormalizeDelegate,
    ): string {
      delegate.setEntity(this as any, pk, INVALID);
    }

    After

    normalize(
      input: any,
      parent: any,
      key: string | undefined,
      args: any[],
      visit: (...args: any) => any,
      delegate: INormalizeDelegate,
    ): string {
      delegate.invalidate(this as any, pk);
    }
  • #3449 1f491a9 Thanks @ntucker! - BREAKING CHANGE: schema.normalize(...args, addEntity, getEntity, checkLoop) -> schema.normalize(...args, delegate)

    We consolidate all 'callback' functions during recursion calls into a single 'delegate' argument.

    /** Helpers during schema.normalize() */
    export interface INormalizeDelegate {
      /** Action meta-data for this normalize call */
      readonly meta: { fetchedAt: number; date: number; expiresAt: number };
      /** Gets any previously normalized entity from store */
      getEntity: GetEntity;
      /** Updates an entity using merge lifecycles when it has previously been set */
      mergeEntity(
        schema: Mergeable & { indexes?: any },
        pk: string,
        incomingEntity: any,
      ): void;
      /** Sets an entity overwriting any previously set values */
      setEntity(
        schema: { key: string; indexes?: any },
        pk: string,
        entity: any,
        meta?: { fetchedAt: number; date: number; expiresAt: number },
      ): void;
      /** Returns true when we're in a cycle, so we should not continue recursing */
      checkLoop(key: string, pk: string, input: object): boolean;
    }

    Before

    addEntity(this, processedEntity, id);

    After

    delegate.mergeEntity(this, id, processedEntity);
  • #3461 939a4b0 Thanks @ntucker! - Remove INVALID symbol export

    Schemas can use delegate.invalidate() in normalize() or return delegate.INVALID in queryKey().

  • #3449 1f491a9 Thanks @ntucker! - BREAKING CHANGE: schema.queryKey(args, queryKey, getEntity, getIndex) -> schema.queryKey(args, unvisit, delegate)
    BREAKING CHANGE: delegate.getIndex() returns the index directly, rather than object.

    We consolidate all 'callback' functions during recursion calls into a single 'delegate' argument.

    Our recursive call is renamed from queryKey to unvisit, and does not require the last two arguments.

    /** Accessors to the currently processing state while building query */
    export interface IQueryDelegate {
      getEntity: GetEntity;
      getIndex: GetIndex;
    }

    Before

    queryKey(args, queryKey, getEntity, getIndex) {
      getIndex(schema.key, indexName, value)[value];
      getEntity(this.key, id);
      return queryKey(this.schema, args, getEntity, getIndex);
    }

    After

    queryKey(args, unvisit, delegate) {
      delegate.getIndex(schema.key, indexName, value);
      delegate.getEntity(this.key, id);
      return unvisit(this.schema, args);
    }

Patch Changes

  • #3449 1f491a9 Thanks @ntucker! - Fix: ensure string id in Entity set when process returns undefined (meaning INVALID)

  • #3560 ba31c9b Thanks @ntucker! - Add Collection.remove

    ctrl.set(MyResource.getList.schema.remove, { id });
    const removeItem = MyResource.delete.extend({
      schema: MyResource.getList.schema.remove,
    });
  • #3558 fcb7d7d Thanks @ntucker! - Normalize delegate.invalidate() first argument only has key param.

    indexes optional param no longer provided as it was never used.

    normalize(
      input: any,
      parent: any,
      key: string | undefined,
      args: any[],
      visit: (...args: any) => any,
      delegate: INormalizeDelegate,
    ): string {
      delegate.invalidate({ key: this._entity.key }, pk);
      return pk;
    }
  • #3558 fcb7d7d Thanks @ntucker! - Unions can query() without type discriminator

    Before

    // @ts-expect-error
    const event = useQuery(EventUnion, { id });
    // event is undefined
    const newsEvent = useQuery(EventUnion, { id, type: 'news' });
    // newsEvent is found

    After

    const event = useQuery(EventUnion, { id });
    // event is found
    const newsEvent = useQuery(EventUnion, { id, type: 'news' });
    // newsEvent is found
  • Updated dependencies [1f491a9, 939a4b0, 939a4b0, ba31c9b, fcb7d7d, 1f491a9, 4dde1d6, bab907c, 5699005, 939a4b0, fcb7d7d, 1f491a9, 35552c7]: