{"version":3,"file":"IsographEnvironment.mjs","names":["ROOT_ID: DataId & '__ROOT'"],"sources":["../../src/core/IsographEnvironment.ts"],"sourcesContent":["import type { ParentCache } from '@isograph/react-disposable-state';\nimport type { Brand } from './brand';\nimport type {\n  IsographEntrypoint,\n  IsographOperation,\n  IsographPersistedOperation,\n  ReaderWithRefetchQueries,\n  ReaderWithRefetchQueriesLoader,\n} from './entrypoint';\nimport type {\n  ExtractStartUpdate,\n  FragmentReference,\n  StableIdForFragmentReference,\n  UnknownTReadFromStore,\n  Variables,\n} from './FragmentReference';\nimport type { RetainedQuery } from './garbageCollection';\nimport type { LogFunction, WrappedLogFunction } from './logging';\nimport { type StoreLayer } from './optimisticProxy';\nimport type { PromiseWrapper } from './PromiseWrapper';\nimport { wrapPromise, wrapResolvedValue } from './PromiseWrapper';\nimport type {\n  NetworkRequestReaderOptions,\n  WithEncounteredRecords,\n} from './read';\nimport type { ReaderAst, StartUpdate } from './reader';\nimport { isArray } from './util';\n\nexport type ComponentOrFieldName = string;\nexport type StringifiedArgs = string;\n\nexport type FieldCache<T> = {\n  [key: StableIdForFragmentReference]: T;\n};\n\nexport type FragmentSubscription<TReadFromStore extends UnknownTReadFromStore> =\n  {\n    readonly kind: 'FragmentSubscription';\n    readonly callback: (\n      newEncounteredDataAndRecords: WithEncounteredRecords<TReadFromStore>,\n    ) => void;\n    /** The value read out from the previous call to readButDoNotEvaluate */\n    encounteredDataAndRecords: WithEncounteredRecords<TReadFromStore>;\n    readonly fragmentReference: FragmentReference<TReadFromStore, any>;\n    readonly readerAst: ReaderAst<TReadFromStore>;\n  };\n\nexport type AnyChangesToRecordSubscription = {\n  readonly kind: 'AnyChangesToRecord';\n  readonly callback: () => void;\n  readonly recordLink: StoreLink;\n};\n\nexport type AnyRecordSubscription = {\n  readonly kind: 'AnyRecords';\n  readonly callback: () => void;\n};\n\nexport type Subscription =\n  | FragmentSubscription<any>\n  | AnyChangesToRecordSubscription\n  | AnyRecordSubscription;\nexport type Subscriptions = Set<Subscription>;\n// Should this be a map?\nexport type CacheMap<T> = { [index: string]: ParentCache<T> };\n\nexport type IsographEnvironment = {\n  store: StoreLayer;\n  readonly networkFunction: IsographNetworkFunction;\n  readonly componentFunction: IsographComponentFunction;\n  readonly missingFieldHandler: MissingFieldHandler | null;\n  readonly componentCache: FieldCache<React.FC<any>>;\n  readonly eagerReaderCache: FieldCache<StartUpdate<any> | undefined>;\n  readonly subscriptions: Subscriptions;\n  // N.B. this must be <any, any>, but all *usages* of this should go through\n  // a function that adds type parameters.\n  readonly fragmentCache: CacheMap<FragmentReference<any, any>>;\n  // TODO make this a CacheMap and add GC\n  readonly entrypointArtifactCache: Map<\n    string,\n    PromiseWrapper<IsographEntrypoint<any, any, any, any>>\n  >;\n  readonly retainedQueries: Set<RetainedQuery>;\n  readonly gcBuffer: Array<RetainedQuery>;\n  readonly gcBufferSize: number;\n  readonly loggers: Set<WrappedLogFunction>;\n};\n\nexport type MissingFieldHandler = (\n  storeRecord: StoreRecord,\n  root: StoreLink,\n  fieldName: string,\n  arguments_: { [index: string]: any } | null,\n  variables: Variables | null,\n) => StoreLink | undefined;\n\nexport type IsographNetworkFunction = (\n  operation: IsographOperation | IsographPersistedOperation,\n  variables: Variables,\n) => Promise<any>;\n\nexport type IsographComponentFunction = <\n  TReadFromStore extends UnknownTReadFromStore = any,\n>(\n  environment: IsographEnvironment,\n  fragmentReference: FragmentReference<TReadFromStore, any>,\n  networkRequestOptions: NetworkRequestReaderOptions,\n  startUpdate: ExtractStartUpdate<TReadFromStore>,\n) => React.FC<any>;\n\nexport interface Link<T extends TypeName> extends StoreLink {\n  readonly __link: Brand<DataId, T>;\n  readonly __typename: T;\n}\n\nexport type StoreLink = {\n  readonly __link: DataId;\n  readonly __typename: TypeName;\n};\n\nexport type DataTypeValue =\n  // N.B. undefined is here to support optional id's, but\n  // undefined should not *actually* be present in the store.\n  | undefined\n  // Singular scalar fields:\n  | number\n  | boolean\n  | string\n  | null\n  // Singular linked fields:\n  | StoreLink\n  // Plural scalar and linked fields:\n  | readonly DataTypeValue[];\n\nexport type StoreRecord = {\n  [index: DataId | string]: DataTypeValue;\n  // TODO __typename?: T, which is restricted to being a concrete string\n  // TODO this shouldn't always be named id\n  readonly id?: DataId;\n};\n\nexport type TypeName = string;\nexport type DataId = string;\n\nexport const ROOT_ID: DataId & '__ROOT' = '__ROOT';\n\nexport type StoreLayerData = {\n  [index: TypeName]: {\n    [index: DataId]: StoreRecord | null;\n  } | null;\n};\n\nexport interface BaseStoreLayerData extends StoreLayerData {\n  readonly Query: {\n    readonly __ROOT: StoreRecord;\n  };\n}\n\nconst DEFAULT_GC_BUFFER_SIZE = 10;\nexport function createIsographEnvironmentCore(\n  baseStoreLayerData: BaseStoreLayerData,\n  networkFunction: IsographNetworkFunction,\n  componentFunction: IsographComponentFunction,\n  missingFieldHandler?: MissingFieldHandler | null,\n  logFunction?: LogFunction | null,\n): IsographEnvironment {\n  logFunction?.({\n    kind: 'EnvironmentCreated',\n  });\n  let store = {\n    kind: 'BaseStoreLayer',\n    data: baseStoreLayerData,\n    parentStoreLayer: null,\n    childStoreLayer: null,\n  } as const;\n  return {\n    store,\n    networkFunction,\n    componentFunction,\n    missingFieldHandler: missingFieldHandler ?? null,\n    componentCache: {},\n    eagerReaderCache: {},\n    subscriptions: new Set(),\n    fragmentCache: {},\n    entrypointArtifactCache: new Map(),\n    retainedQueries: new Set(),\n    gcBuffer: [],\n    gcBufferSize: DEFAULT_GC_BUFFER_SIZE,\n    loggers: logFunction != null ? new Set([{ log: logFunction }]) : new Set(),\n  };\n}\n\nexport function createIsographStore(): BaseStoreLayerData {\n  return {\n    Query: {\n      [ROOT_ID]: {},\n    },\n  };\n}\n\nexport function assertLink(link: DataTypeValue): StoreLink | null | undefined {\n  if (isArray(link)) {\n    throw new Error('Unexpected array');\n  }\n  if (link == null) {\n    return link;\n  }\n  if (typeof link === 'object') {\n    return link;\n  }\n  throw new Error('Invalid link');\n}\n\nexport function getLink(maybeLink: DataTypeValue): StoreLink | null {\n  if (\n    maybeLink != null &&\n    typeof maybeLink === 'object' &&\n    '__link' in maybeLink &&\n    maybeLink.__link != null &&\n    '__typename' in maybeLink &&\n    maybeLink.__typename != null\n  ) {\n    return maybeLink;\n  }\n  return null;\n}\n\nexport function getOrLoadIsographArtifact(\n  environment: IsographEnvironment,\n  key: string,\n  loader: () => Promise<IsographEntrypoint<any, any, any, any>>,\n): PromiseWrapper<IsographEntrypoint<any, any, any, any>> {\n  const value = environment.entrypointArtifactCache.get(key);\n  if (value != null) {\n    return value;\n  }\n  const wrapped = wrapPromise(loader());\n  environment.entrypointArtifactCache.set(key, wrapped);\n  return wrapped;\n}\n\nexport function getOrLoadReaderWithRefetchQueries(\n  _environment: IsographEnvironment,\n  readerWithRefetchQueries:\n    | ReaderWithRefetchQueries<any, any>\n    | ReaderWithRefetchQueriesLoader<any, any>,\n): {\n  readerWithRefetchQueries: PromiseWrapper<ReaderWithRefetchQueries<any, any>>;\n  fieldName: string;\n  readerArtifactKind: 'EagerReaderArtifact' | 'ComponentReaderArtifact';\n} {\n  switch (readerWithRefetchQueries.kind) {\n    case 'ReaderWithRefetchQueries':\n      return {\n        readerWithRefetchQueries: wrapResolvedValue(readerWithRefetchQueries),\n        fieldName: readerWithRefetchQueries.readerArtifact.fieldName,\n        readerArtifactKind: readerWithRefetchQueries.readerArtifact.kind,\n      };\n    case 'ReaderWithRefetchQueriesLoader':\n      return {\n        // TODO: cache promise wrapper\n        readerWithRefetchQueries: wrapPromise(\n          readerWithRefetchQueries.loader(),\n        ),\n        fieldName: readerWithRefetchQueries.fieldName,\n        readerArtifactKind: readerWithRefetchQueries.readerArtifactKind,\n      };\n  }\n}\n"],"mappings":";;;;AAgJA,MAAaA,UAA6B;AAc1C,MAAM,yBAAyB;AAC/B,SAAgB,8BACd,oBACA,iBACA,mBACA,qBACA,aACqB;AACrB,eAAc,EACZ,MAAM,sBACP,CAAC;AAOF,QAAO;EACL,OAPU;GACV,MAAM;GACN,MAAM;GACN,kBAAkB;GAClB,iBAAiB;GAClB;EAGC;EACA;EACA,qBAAqB,uBAAuB;EAC5C,gBAAgB,EAAE;EAClB,kBAAkB,EAAE;EACpB,+BAAe,IAAI,KAAK;EACxB,eAAe,EAAE;EACjB,yCAAyB,IAAI,KAAK;EAClC,iCAAiB,IAAI,KAAK;EAC1B,UAAU,EAAE;EACZ,cAAc;EACd,SAAS,eAAe,OAAO,IAAI,IAAI,CAAC,EAAE,KAAK,aAAa,CAAC,CAAC,mBAAG,IAAI,KAAK;EAC3E;;AAGH,SAAgB,sBAA0C;AACxD,QAAO,EACL,OAAO,GACJ,UAAU,EAAE,EACd,EACF;;AAGH,SAAgB,WAAW,MAAmD;AAC5E,KAAI,QAAQ,KAAK,CACf,OAAM,IAAI,MAAM,mBAAmB;AAErC,KAAI,QAAQ,KACV,QAAO;AAET,KAAI,OAAO,SAAS,SAClB,QAAO;AAET,OAAM,IAAI,MAAM,eAAe;;AAGjC,SAAgB,QAAQ,WAA4C;AAClE,KACE,aAAa,QACb,OAAO,cAAc,YACrB,YAAY,aACZ,UAAU,UAAU,QACpB,gBAAgB,aAChB,UAAU,cAAc,KAExB,QAAO;AAET,QAAO;;AAGT,SAAgB,0BACd,aACA,KACA,QACwD;CACxD,MAAM,QAAQ,YAAY,wBAAwB,IAAI,IAAI;AAC1D,KAAI,SAAS,KACX,QAAO;CAET,MAAM,UAAU,YAAY,QAAQ,CAAC;AACrC,aAAY,wBAAwB,IAAI,KAAK,QAAQ;AACrD,QAAO;;AAGT,SAAgB,kCACd,cACA,0BAOA;AACA,SAAQ,yBAAyB,MAAjC;EACE,KAAK,2BACH,QAAO;GACL,0BAA0B,kBAAkB,yBAAyB;GACrE,WAAW,yBAAyB,eAAe;GACnD,oBAAoB,yBAAyB,eAAe;GAC7D;EACH,KAAK,iCACH,QAAO;GAEL,0BAA0B,YACxB,yBAAyB,QAAQ,CAClC;GACD,WAAW,yBAAyB;GACpC,oBAAoB,yBAAyB;GAC9C"}