Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { ItemCleanupPair } from '@isograph/disposable-types';
import {
afterEach,
assert,
Expand All @@ -8,6 +7,7 @@ import {
test,
vi,
} from 'vitest';
import { ItemCleanupPair } from '.';
import {
CacheItem,
CacheItemState,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
import {
CleanupFn,
Factory,
ItemCleanupPair,
} from '@isograph/disposable-types';
import { CleanupFn, Factory, ItemCleanupPair } from '.';

const DEFAULT_TEMPORARY_RETAIN_TIME = 5000;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ItemCleanupPair } from '@isograph/disposable-types';
import { assert, describe, expect, test, vi } from 'vitest';
import { ItemCleanupPair } from '.';
import { CacheItem } from './CacheItem';
import { ParentCache } from './ParentCache';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
import {
CleanupFn,
Factory,
ItemCleanupPair,
} from '@isograph/disposable-types';
import { CleanupFn, Factory, ItemCleanupPair } from '.';
import { CacheItem, createTemporarilyRetainedCacheItem } from './CacheItem';

// TODO convert cache impl to a getter and setter and free functions
Expand Down
3 changes: 3 additions & 0 deletions libs/isograph-disposable-types/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
export type CleanupFn = () => void;
export type ItemCleanupPair<T> = [T, CleanupFn];
export type Factory<T> = () => ItemCleanupPair<T>;

export * from './CacheItem';
export * from './ParentCache';
2 changes: 0 additions & 2 deletions libs/isograph-react-disposable-state/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
export * from '@isograph/disposable-types';

export * from './CacheItem';
export * from './ParentCache';
export * from './useCachedResponsivePrecommitValue';
export * from './useDisposableState';
export * from './useHasCommittedRef';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { ItemCleanupPair } from '@isograph/disposable-types';
import {
CacheItem,
CacheItemState,
ItemCleanupPair,
ParentCache,
} from '@isograph/disposable-types';
import React from 'react';
import { create } from 'react-test-renderer';
import { assert, describe, expect, test, vi } from 'vitest';
import { CacheItem, CacheItemState } from './CacheItem';
import { ParentCache } from './ParentCache';
import { useCachedResponsivePrecommitValue } from './useCachedResponsivePrecommitValue';

function getItem<T>(cache: ParentCache<T>): CacheItem<T> | null {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
'use strict';

import { ItemCleanupPair } from '@isograph/disposable-types';
import { ItemCleanupPair, ParentCache } from '@isograph/disposable-types';
import { useEffect, useRef, useState } from 'react';
import { ParentCache } from './ParentCache';

/**
* useCachedResponsivePrecommitValue<T>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { ItemCleanupPair } from '@isograph/disposable-types';
import { ItemCleanupPair, ParentCache } from '@isograph/disposable-types';
import { useEffect, useRef } from 'react';
import { ParentCache } from './ParentCache';
import { useCachedResponsivePrecommitValue } from './useCachedResponsivePrecommitValue';
import {
UNASSIGNED_STATE,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { ItemCleanupPair } from '@isograph/disposable-types';
import { ItemCleanupPair, ParentCache } from '@isograph/disposable-types';
import React, { useEffect, useState } from 'react';
import { create } from 'react-test-renderer';
import { describe, expect, test, vi } from 'vitest';
import { ParentCache } from './ParentCache';
import { useLazyDisposableState } from './useLazyDisposableState';

function createCache<T>(value: T) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
'use strict';

import type { ItemCleanupPair } from '@isograph/isograph-disposable-types';
import {
ParentCache,
type ItemCleanupPair,
} from '@isograph/isograph-disposable-types';
import { useEffect, useRef } from 'react';
import { ParentCache } from './ParentCache';
import { useCachedResponsivePrecommitValue } from './useCachedResponsivePrecommitValue';
import { type UnassignedState } from './useUpdatableDisposableState';

Expand Down
2 changes: 1 addition & 1 deletion libs/isograph-react/src/core/FragmentReference.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ReaderWithRefetchQueries } from '../core/entrypoint';
import { stableCopy } from './cache';
import { ReaderWithRefetchQueries } from './entrypoint';
import { type Link } from './IsographEnvironment';
import { PromiseWrapper } from './PromiseWrapper';
import type { StartUpdate } from './reader';
Expand Down
27 changes: 21 additions & 6 deletions libs/isograph-react/src/core/IsographEnvironment.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ParentCache } from '@isograph/react-disposable-state';
import { ParentCache } from '@isograph/disposable-types';
import { IsographEntrypoint } from './entrypoint';
import {
ExtractStartUpdate,
FragmentReference,
Variables,
type StableIdForFragmentReference,
Expand All @@ -9,7 +10,7 @@ import {
import { RetainedQuery } from './garbageCollection';
import { LogFunction, WrappedLogFunction } from './logging';
import { PromiseWrapper, wrapPromise } from './PromiseWrapper';
import { WithEncounteredRecords } from './read';
import { NetworkRequestReaderOptions, WithEncounteredRecords } from './read';
import type { ReaderAst, StartUpdate } from './reader';

export type ComponentOrFieldName = string;
Expand Down Expand Up @@ -50,11 +51,12 @@ export type Subscriptions = Set<Subscription>;
// Should this be a map?
export type CacheMap<T> = { [index: string]: ParentCache<T> };

export type IsographEnvironment = {
export type IsographEnvironment<TComponent = unknown> = {
readonly store: IsographStore;
readonly networkFunction: IsographNetworkFunction;
readonly componentFunction: IsographComponentFunction<TComponent>;
readonly missingFieldHandler: MissingFieldHandler | null;
readonly componentCache: FieldCache<React.FC<any>>;
readonly componentCache: FieldCache<TComponent>;
readonly eagerReaderCache: FieldCache<StartUpdate<any> | undefined>;
readonly subscriptions: Subscriptions;
// N.B. this must be <any, any>, but all *usages* of this should go through
Expand Down Expand Up @@ -84,6 +86,17 @@ export type IsographNetworkFunction = (
variables: Variables,
) => Promise<any>;

export type IsographComponentFunction<
TComponent,
TReadFromStore extends UnknownTReadFromStore = any,
> = (
environment: IsographEnvironment,
componentName: string,
fragmentReference: FragmentReference<TReadFromStore, any>,
networkRequestOptions: NetworkRequestReaderOptions,
startUpdate: ExtractStartUpdate<TReadFromStore>,
) => TComponent;

export type Link = {
readonly __link: DataId;
readonly __typename: TypeName;
Expand Down Expand Up @@ -125,18 +138,20 @@ export type IsographStore = {
};

const DEFAULT_GC_BUFFER_SIZE = 10;
export function createIsographEnvironment(
export function createIsographEnvironment<TComponent>(
store: IsographStore,
networkFunction: IsographNetworkFunction,
componentFunction: IsographComponentFunction<TComponent>,
missingFieldHandler?: MissingFieldHandler | null,
logFunction?: LogFunction | null,
): IsographEnvironment {
): IsographEnvironment<TComponent> {
logFunction?.({
kind: 'EnvironmentCreated',
});
return {
store,
networkFunction,
componentFunction,
missingFieldHandler: missingFieldHandler ?? null,
componentCache: {},
eagerReaderCache: {},
Expand Down
8 changes: 4 additions & 4 deletions libs/isograph-react/src/core/cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ import {
Factory,
ItemCleanupPair,
ParentCache,
} from '@isograph/react-disposable-state';
} from '@isograph/disposable-types';
import { mergeObjectsUsingReaderAst } from './areEqualWithDeepComparison';
import { FetchOptions } from './check';
import {
IsographEntrypoint,
NormalizationInlineFragment,
Expand All @@ -12,9 +14,7 @@ import {
type NormalizationAst,
type NormalizationAstLoader,
type NormalizationAstNodes,
} from '../core/entrypoint';
import { mergeObjectsUsingReaderAst } from './areEqualWithDeepComparison';
import { FetchOptions } from './check';
} from './entrypoint';
import {
ExtractParameters,
FragmentReference,
Expand Down
48 changes: 10 additions & 38 deletions libs/isograph-react/src/core/componentCache.ts
Original file line number Diff line number Diff line change
@@ -1,55 +1,27 @@
import { useReadAndSubscribe } from '../react/useReadAndSubscribe';
import {
FragmentReference,
stableIdForFragmentReference,
} from './FragmentReference';
import { IsographEnvironment } from './IsographEnvironment';
import { logMessage } from './logging';
import { readPromise } from './PromiseWrapper';
import { NetworkRequestReaderOptions } from './read';
import { createStartUpdate } from './startUpdate';

export function getOrCreateCachedComponent(
environment: IsographEnvironment,
export function getOrCreateCachedComponent<TComponent>(
environment: IsographEnvironment<TComponent>,
componentName: string,
fragmentReference: FragmentReference<any, any>,
networkRequestOptions: NetworkRequestReaderOptions,
): React.FC<any> {
): TComponent {
// We create startUpdate outside of component to make it stable
const startUpdate = createStartUpdate(environment, fragmentReference);

return (environment.componentCache[
stableIdForFragmentReference(fragmentReference, componentName)
] ??= (() => {
function Component(additionalRuntimeProps: { [key: string]: any }) {
const readerWithRefetchQueries = readPromise(
fragmentReference.readerWithRefetchQueries,
);

const data = useReadAndSubscribe(
fragmentReference,
networkRequestOptions,
readerWithRefetchQueries.readerArtifact.readerAst,
);

logMessage(environment, () => ({
kind: 'ComponentRerendered',
componentName,
rootLink: fragmentReference.root,
}));

return readerWithRefetchQueries.readerArtifact.resolver(
{
data,
parameters: fragmentReference.variables,
startUpdate: readerWithRefetchQueries.readerArtifact.hasUpdatable
? startUpdate
: undefined,
},
additionalRuntimeProps,
);
}
Component.displayName = `${componentName} (id: ${fragmentReference.root}) @component`;
return Component;
})());
] ??= environment.componentFunction(
environment,
componentName,
fragmentReference,
networkRequestOptions,
startUpdate,
));
}
8 changes: 6 additions & 2 deletions libs/isograph-react/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,14 @@ export {
ROOT_ID,
type DataId,
type DataTypeValue,
type IsographEnvironment,
type IsographEnvironment as RawIsographEnvironment,
type IsographNetworkFunction,
type IsographStore,
type MissingFieldHandler,
type Link,
type StoreRecord,
type CacheMap,
createIsographEnvironment,
createIsographEnvironment as createRawIsographEnvironment,
createIsographStore,
type FieldCache,
type Subscriptions,
Expand Down Expand Up @@ -127,6 +127,10 @@ export {
type RequiredShouldFetch,
} from './core/check';

export {
IsographReactEnvironment as IsographEnvironment,
createIsographReactEnvironment as createIsographEnvironment,
} from './react/IsographReactEnvironment';
export {
IsographEnvironmentProvider,
useIsographEnvironment,
Expand Down
8 changes: 4 additions & 4 deletions libs/isograph-react/src/react/IsographEnvironmentProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import * as React from 'react';
import { createContext, ReactNode, useContext } from 'react';
import { type IsographEnvironment } from '../core/IsographEnvironment';
import { IsographReactEnvironment } from './IsographReactEnvironment';

export const IsographEnvironmentContext =
createContext<IsographEnvironment | null>(null);
createContext<IsographReactEnvironment | null>(null);

export type IsographEnvironmentProviderProps = {
readonly environment: IsographEnvironment;
readonly environment: IsographReactEnvironment;
readonly children: ReactNode;
};

Expand All @@ -21,7 +21,7 @@ export function IsographEnvironmentProvider({
);
}

export function useIsographEnvironment(): IsographEnvironment {
export function useIsographEnvironment(): IsographReactEnvironment {
const context = useContext(IsographEnvironmentContext);
if (context == null) {
throw new Error(
Expand Down
Loading
Loading