Skip to content

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

Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 06 Oct 02:47
· 119 commits to master since this release
742a7c1

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 get/denormalize for small responses

    • 10-20% performance improvement due to removing immutablejs check for every call