@apollo/client/core#StoreObject TypeScript Examples

The following examples show how to use @apollo/client/core#StoreObject. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: InvalidationPolicyCache.ts    From apollo-cache-policies with Apache License 2.0 6 votes vote down vote up
protected readField<T>(
    fieldNameOrOptions?: string | ReadFieldOptions,
    from?: StoreObject | Reference
  ) {
    if (!fieldNameOrOptions) {
      return;
    }

    const options = typeof fieldNameOrOptions === "string"
      ? {
        fieldName: fieldNameOrOptions,
        from,
      }
      : fieldNameOrOptions;

    if (void 0 === options.from) {
      options.from = { __ref: 'ROOT_QUERY' };
    }

    return this.policies.readField<T>(
      options,
      {
        store: this.entityStoreRoot,
      }
    );
  }
Example #2
Source File: EntityStoreWatcher.ts    From apollo-cache-policies with Apache License 2.0 6 votes vote down vote up
private merge = (dataId: string, incomingStoreObject: StoreObject) => {
    const { entityStore, entityTypeMap } = this.config;

    if (isQuery(dataId)) {
      Object.keys(incomingStoreObject)
        .filter(
          (storeFieldName) =>
            // If there is a valid response, it will contain the type Query and then the nested response types for each requested field. We want
            // to record a map of the types for those fields to their field store names. If there is no incoming data it is because that cache entry for storeFieldName
            // is being deleted so do nothing
            storeFieldName !== "__typename" &&
            (incomingStoreObject[storeFieldName] as StoreObject)?.__typename
        )
        .forEach((storeFieldName) => {
          const entityStoreObject = incomingStoreObject[
            storeFieldName
          ] as StoreObject;
          entityTypeMap.write(
            entityStoreObject.__typename!,
            dataId,
            storeFieldName
          );
        });
    } else {
      const typename = incomingStoreObject.__typename;
      // If the incoming data is empty, the dataId entry in the cache is being deleted so do nothing
      if (dataId && typename && typename !== cacheExtensionsCollectionTypename) {
        this.config.updateCollectionField(typename, dataId);
        entityTypeMap.write(typename, dataId);
      }
    }
    return this.storeFunctions.merge.call(
      entityStore,
      dataId,
      incomingStoreObject
    );
  };
Example #3
Source File: EntityStoreWatcher.test.ts    From apollo-cache-policies with Apache License 2.0 4 votes vote down vote up
describe("#EntityStoreWatcher", () => {
  let entityStoreWatcher: EntityStoreWatcher;
  let entityTypeMap: EntityTypeMap;
  let entityStore: EntityStore;
  let policies: Policies;
  let reactiveVarsCache: ReactiveVarsCache;
  let dateNowSpy: any;

  beforeEach(() => {
    dateNowSpy = jest.spyOn(Date, "now").mockReturnValue(0);
    policies = new Policies({ cache: new InMemoryCache() });
    entityTypeMap = new EntityTypeMap();
    entityStore = new EntityStore.Root({
      policies,
    });
    reactiveVarsCache = new ReactiveVarsCache({
      cache: new InvalidationPolicyCache(),
    });
    entityStoreWatcher = new EntityStoreWatcher({
      policies,
      entityTypeMap,
      entityStore,
      reactiveVarsCache,
      updateCollectionField: () => { }
    });
  });

  afterEach(() => {
    dateNowSpy.mockRestore();
  });

  describe("#merge", () => {
    let entityTypeMapSpy: any;

    beforeEach(() => {
      entityTypeMapSpy = jest.spyOn(entityTypeMap, "write");
    });

    afterEach(() => {
      entityTypeMapSpy.mockRestore();
    });

    test("should call the entityStore merge", () => {
      const mergeSpy = jest.spyOn(entityStore, "merge");
      entityStoreWatcher = new EntityStoreWatcher({
        policies,
        entityTypeMap,
        entityStore,
        reactiveVarsCache,
        updateCollectionField: () => { }
      });
      const mergeArgs: [string, StoreObject] = [
        "ROOT_QUERY",
        {
          employees: {
            __typename: "EmployeesResponse",
          },
        },
      ];
      entityStore.merge(...mergeArgs);
      expect(mergeSpy).toHaveBeenCalledWith(...mergeArgs);
      mergeSpy.mockRestore();
    });

    describe("with a query entity", () => {
      test("should call the entityTypeMap write", () => {
        // @ts-ignore
        entityStoreWatcher.merge("ROOT_QUERY", {
          employees: {
            __typename: "EmployeesResponse",
          },
        });
        expect(entityTypeMapSpy).toHaveBeenCalledWith(
          "EmployeesResponse",
          "ROOT_QUERY",
          "employees"
        );
      });
    });

    describe("with a normalized cache entity", () => {
      test("should call the entityTypeMap write", () => {
        entityStore.merge("Employee:1", {
          __typename: "Employee",
          id: 1,
        });
        expect(entityTypeMapSpy).toHaveBeenCalledWith("Employee", "Employee:1");
      });
    });
  });

  describe("#delete", () => {
    let entityTypeMapSpy: any;

    beforeEach(() => {
      entityTypeMapSpy = jest.spyOn(entityTypeMap, "evict");
    });

    afterEach(() => {
      entityTypeMapSpy.mockRestore();
    });

    test("should call the entityStore delete", () => {
      const deleteSpy = jest.spyOn(entityStore, "delete");
      entityStoreWatcher = new EntityStoreWatcher({
        policies,
        entityTypeMap,
        entityStore,
        reactiveVarsCache,
        updateCollectionField: () => { }
      });
      entityStore.delete("ROOT_QUERY", "employees", undefined);
      expect(deleteSpy).toHaveBeenCalledWith(
        "ROOT_QUERY",
        "employees",
        undefined
      );
      deleteSpy.mockRestore();
    });

    describe("with a query entity", () => {
      describe("without variables", () => {
        test("should call the entityTypeMap evict", () => {
          entityStore.delete("ROOT_QUERY", "employees");
          expect(entityTypeMapSpy).toHaveBeenCalledWith(
            "ROOT_QUERY",
            "employees"
          );
        });
      });

      describe("with variables", () => {
        test("should call the entityTypeMap evict", () => {
          entityStore.delete("ROOT_QUERY", "employees", {
            name: "Test",
          });
          // prettier-ignore
          expect(entityTypeMapSpy).toHaveBeenCalledWith("ROOT_QUERY", "employees({\"name\":\"Test\"})");
        });
      });
    });

    describe("with a normalized cache entity", () => {
      test("should call the entityTypeMap evict", () => {
        entityStore.delete("Employee:1");
        expect(entityTypeMapSpy).toHaveBeenCalledWith("Employee:1", undefined);
      });
    });
  });

  describe("#clear", () => {
    test("should call the entityStore clear", () => {
      const clearSpy = jest.spyOn(entityStore, "clear");
      entityStoreWatcher = new EntityStoreWatcher({
        policies,
        entityTypeMap,
        entityStore,
        reactiveVarsCache,
        updateCollectionField: () => { }
      });
      entityStore.clear();
      expect(clearSpy).toHaveBeenCalled();
      clearSpy.mockRestore();
    });

    test("should call the entityTypeMap clear", () => {
      const clearSpy = jest.spyOn(entityTypeMap, "clear");
      entityStore.clear();
      expect(clearSpy).toHaveBeenCalled();
      clearSpy.mockRestore();
    });
  });

  describe("#replace", () => {
    let replaceSpy: any;

    beforeEach(() => {
      replaceSpy = jest.spyOn(entityStore, "replace");
      entityStoreWatcher = new EntityStoreWatcher({
        policies,
        entityTypeMap,
        entityStore,
        reactiveVarsCache,
        updateCollectionField: () => { }
      });
    });

    afterEach(() => {
      replaceSpy.mockRestore();
    });

    test("should call entityStore replace without invalidation data", () => {
      // @ts-ignore
      entityStore.replace({
        invalidation: {
          entitiesById: {},
        },
      });

      expect(replaceSpy).toHaveBeenCalledWith({});
    });

    test("should pause the entityStoreWatcher before calling entityStore replace and then resume", () => {
      // @ts-ignore
      let pauseSpy = jest.spyOn(entityStoreWatcher, "pause");
      // @ts-ignore
      let watchSpy = jest.spyOn(entityStoreWatcher, "watch");
      // @ts-ignore
      entityStore.replace({
        invalidation: {
          entitiesById: {},
        },
      });
      expect(pauseSpy).toHaveBeenCalledBefore(replaceSpy);
      expect(watchSpy).toHaveBeenCalledAfter(replaceSpy);
    });
  });

  describe("#pause and #watch", () => {
    test("should pause entity store proxies and resume them", () => {
      const entityStoreMergeSpy = jest
        .spyOn(entityStore, "merge")
        .mockImplementation();
      const entityStoreDeleteSpy = jest
        .spyOn(entityStore, "delete")
        .mockImplementation();
      const entityStoreClearSpy = jest
        .spyOn(entityStore, "clear")
        .mockImplementation();
      const entityStoreReplaceSpy = jest
        .spyOn(entityStore, "replace")
        .mockImplementation();
      entityStoreWatcher = new EntityStoreWatcher({
        policies,
        entityTypeMap,
        entityStore,
        reactiveVarsCache,
        updateCollectionField: () => { }
      });
      const entityStoreWatcherMergeSpy = jest
        // @ts-ignore
        .spyOn(entityStoreWatcher, "merge")
        .mockImplementation();
      const entityStoreWatcherDeleteSpy = jest
        // @ts-ignore
        .spyOn(entityStoreWatcher, "delete")
        .mockImplementation();
      const entityStoreWatcherClearSpy = jest
        // @ts-ignore
        .spyOn(entityStoreWatcher, "clear")
        .mockImplementation();
      const entityStoreWatcherReplaceSpy = jest
        // @ts-ignore
        .spyOn(entityStoreWatcher, "replace")
        .mockImplementation();

      // @ts-ignore
      entityStoreWatcher.pause();
      entityStore.merge("test", {});
      entityStore.delete("test");
      entityStore.clear();
      entityStore.replace({});
      expect(entityStoreMergeSpy).toHaveBeenCalled();
      expect(entityStoreDeleteSpy).toHaveBeenCalled();
      expect(entityStoreClearSpy).toHaveBeenCalled();
      expect(entityStoreReplaceSpy).toHaveBeenCalled();

      expect(entityStoreWatcherMergeSpy).not.toHaveBeenCalled();
      expect(entityStoreWatcherDeleteSpy).not.toHaveBeenCalled();
      expect(entityStoreWatcherClearSpy).not.toHaveBeenCalled();
      expect(entityStoreWatcherReplaceSpy).not.toHaveBeenCalled();

      // @ts-ignore
      entityStoreWatcher.watch();
      entityStore.merge("test", {});
      entityStore.delete("test");
      entityStore.clear();
      entityStore.replace({});

      expect(entityStoreWatcherMergeSpy).toHaveBeenCalled();
      expect(entityStoreWatcherDeleteSpy).toHaveBeenCalled();
      expect(entityStoreWatcherClearSpy).toHaveBeenCalled();
      expect(entityStoreWatcherReplaceSpy).toHaveBeenCalled();
    });
  });
});