import type { CacheCapabilitiesManager } from "@warp-drive/core/types"; import type { Cache, ChangedAttributesHash, RelationshipDiff } from "@warp-drive/core/types/cache"; import type { Change } from "@warp-drive/core/types/cache/change"; import type { Operation } from "@warp-drive/core/types/cache/operations"; import type { CollectionRelationship, ResourceRelationship } from "@warp-drive/core/types/cache/relationship"; import type { LocalRelationshipOperation } from "@warp-drive/core/types/graph"; import type { RequestKey, ResourceKey } from "@warp-drive/core/types/identifier"; import type { Value } from "@warp-drive/core/types/json/raw"; import type { RequestContext, StructuredDataDocument, StructuredDocument, StructuredErrorDocument } from "@warp-drive/core/types/request"; import type { CollectionResourceDataDocument, ResourceDocument, ResourceErrorDocument, ResourceMetaDocument, SingleResourceDataDocument } from "@warp-drive/core/types/spec/document"; import type { ApiError } from "@warp-drive/core/types/spec/error"; import type { CollectionResourceDocument, ExistingResourceObject, ResourceObject, SingleResourceDocument } from "@warp-drive/core/types/spec/json-api-raw"; /** * ```ts * import { JSONAPICache } from '@warp-drive/json-api'; * ``` * * A {@link Cache} implementation tuned for [{json:api}](https://jsonapi.org/) * * @categoryDescription Cache Management * APIs for primary cache management functionality * @categoryDescription Cache Forking * APIs that support Cache Forking * @categoryDescription SSR Support * APIs that support SSR functionality * @categoryDescription Resource Lifecycle * APIs that support management of resource data * @categoryDescription Resource Data * APIs that support granular field level management of resource data * @categoryDescription Resource State * APIs that support managing Resource states * * @public */ export declare class JSONAPICache implements Cache { /** * The Cache Version that this implementation implements. * * @public */ version: "2"; constructor(capabilities: CacheCapabilitiesManager); /** * Cache the response to a request * * Implements `Cache.put`. * * Expects a StructuredDocument whose `content` member is a JsonApiDocument. * * ```js * cache.put({ * request: { url: 'https://api.example.com/v1/user/1' }, * content: { * data: { * type: 'user', * id: '1', * attributes: { * name: 'Chris' * } * } * } * }) * ``` * * > **Note** * > The nested `content` and `data` members are not a mistake. This is because * > there are two separate concepts involved here, the `StructuredDocument` which contains * > the context of a given Request that has been issued with the returned contents as its * > `content` property, and a `JSON:API Document` which is the json contents returned by * > this endpoint and which uses its `data` property to signify which resources are the * > primary resources associated with the request. * * StructuredDocument's with urls will be cached as full documents with * associated resource membership order and contents preserved but linked * into the cache. * * @category Cache Management * @public */ put(doc: StructuredDataDocument): SingleResourceDataDocument; put(doc: StructuredDataDocument): CollectionResourceDataDocument; put(doc: StructuredErrorDocument): ResourceErrorDocument; put(doc: StructuredDataDocument): ResourceMetaDocument; /** * Update the "remote" or "canonical" (persisted) state of the Cache * by merging new information into the existing state. * * @category Cache Management * @public * @param op the operation or list of operations to perform */ patch(op: Operation | Operation[]): void; /** * Update the "local" or "current" (unpersisted) state of the Cache * * @category Cache Management * @public */ mutate(mutation: LocalRelationshipOperation): void; /** * Peek resource data from the Cache. * * In development, if the return value * is JSON the return value * will be deep-cloned and deep-frozen * to prevent mutation thereby enforcing cache * Immutability. * * This form of peek is useful for implementations * that want to feed raw-data from cache to the UI * or which want to interact with a blob of data * directly from the presentation cache. * * An implementation might want to do this because * de-referencing records which read from their own * blob is generally safer because the record does * not require retainining connections to the Store * and Cache to present data on a per-field basis. * * This generally takes the place of `getAttr` as * an API and may even take the place of `getRelationship` * depending on implementation specifics, though this * latter usage is less recommended due to the advantages * of the Graph handling necessary entanglements and * notifications for relational data. * * :::warning * It is not recommended to use the return value as * a serialized representation of the resource both * due to it containing local mutations and because * it may contain additional fields not recognized * by the {json:api} API implementation such as `lid` and * the various internal WarpDrive bookkeeping fields. * ::: * * @category Cache Management * @public */ peek(identifier: ResourceKey): ResourceObject | null; peek(identifier: RequestKey): ResourceDocument | null; /** * Peek the remote resource data from the Cache. * * @category Cache Management * @public */ peekRemoteState(identifier: ResourceKey): ResourceObject | null; peekRemoteState(identifier: RequestKey): ResourceDocument | null; /** * Peek the Cache for the existing request data associated with * a cacheable request. * * This is effectively the reverse of `put` for a request in * that it will return the the request, response, and content * whereas `peek` will return just the `content`. * * @category Cache Management * @public */ peekRequest(identifier: RequestKey): StructuredDocument | null; /** * Push resource data from a remote source into the cache for this identifier * * @category Cache Management * @public * @return if `calculateChanges` is true then calculated key changes should be returned */ upsert(identifier: ResourceKey, data: ExistingResourceObject, calculateChanges?: boolean): void | string[]; /** * Create a fork of the cache from the current state. * * Applications should typically not call this method themselves, * preferring instead to fork at the Store level, which will * utilize this method to fork the cache. * * @category Cache Forking * @private */ fork(): Promise; /** * Merge a fork back into a parent Cache. * * Applications should typically not call this method themselves, * preferring instead to merge at the Store level, which will * utilize this method to merge the caches. * * @category Cache Forking * @private */ merge(_cache: Cache): Promise; /** * Generate the list of changes applied to all * record in the store. * * Each individual resource or document that has * been mutated should be described as an individual * `Change` entry in the returned array. * * A `Change` is described by an object containing up to * three properties: (1) the `identifier` of the entity that * changed; (2) the `op` code of that change being one of * `upsert` or `remove`, and if the op is `upsert` a `patch` * containing the data to merge into the cache for the given * entity. * * This `patch` is opaque to the Store but should be understood * by the Cache and may expect to be utilized by an Adapter * when generating data during a `save` operation. * * It is generally recommended that the `patch` contain only * the updated state, ignoring fields that are unchanged * * ```ts * interface Change { * identifier: ResourceKey | RequestKey; * op: 'upsert' | 'remove'; * patch?: unknown; * } * ``` * * @category Cache Forking * @private */ diff(): Promise; /** * Serialize the entire contents of the Cache into a Stream * which may be fed back into a new instance of the same Cache * via `cache.hydrate`. * * @category SSR Support * @private */ dump(): Promise>; /** * hydrate a Cache from a Stream with content previously serialized * from another instance of the same Cache, resolving when hydration * is complete. * * This method should expect to be called both in the context of restoring * the Cache during application rehydration after SSR **AND** at unknown * times during the lifetime of an already booted application when it is * desired to bulk-load additional information into the cache. This latter * behavior supports optimizing pre/fetching of data for route transitions * via data-only SSR modes. * * @category SSR Support * @private */ hydrate(stream: ReadableStream): Promise; /** * [LIFECYCLE] Signal to the cache that a new record has been instantiated on the client * * It returns properties from options that should be set on the record during the create * process. This return value behavior is deprecated. * * @category Resource Lifecycle * @public */ clientDidCreate(identifier: ResourceKey, options?: Record): Record; /** * [LIFECYCLE] Signals to the cache that a resource * will be part of a save transaction. * * @category Resource Lifecycle * @public */ willCommit(identifier: ResourceKey | ResourceKey[], _context: RequestContext | null): void; /** * [LIFECYCLE] Signals to the cache that a resource * was successfully updated as part of a save transaction. * * @category Resource Lifecycle * @public */ didCommit(committedIdentifier: ResourceKey, result: StructuredDataDocument | null): SingleResourceDataDocument; didCommit(committedIdentifier: ResourceKey[], result: StructuredDataDocument | null): SingleResourceDataDocument; didCommit(committedIdentifier: ResourceKey[], result: StructuredDataDocument | null): CollectionResourceDataDocument; /** * [LIFECYCLE] Signals to the cache that a resource * was update via a save transaction failed. * * @category Resource Lifecycle * @public */ commitWasRejected(identifier: ResourceKey | ResourceKey[], errors?: ApiError[]): void; /** * [LIFECYCLE] Signals to the cache that all data for a resource * should be cleared. * * This method is a candidate to become a mutation * * @category Resource Lifecycle * @public */ unloadRecord(identifier: ResourceKey): void; /** * Retrieve the data for an attribute from the cache * with local mutations applied. * * @category Resource Data * @public */ getAttr(identifier: ResourceKey, attr: string | string[]): Value | undefined; /** * Retrieve the remote data for an attribute from the cache * * @category Resource Data * @public */ getRemoteAttr(identifier: ResourceKey, attr: string | string[]): Value | undefined; /** * Mutate the data for an attribute in the cache * * This method is a candidate to become a mutation * * @category Resource Data * @public */ setAttr(identifier: ResourceKey, attr: string | string[], value: Value): void; /** * Query the cache for the changed attributes of a resource. * * @category Resource Data * @public * @return `{ '': ['', ''] }` */ changedAttrs(identifier: ResourceKey): ChangedAttributesHash; /** * Query the cache for whether any mutated attributes exist * * @category Resource Data * @public */ hasChangedAttrs(identifier: ResourceKey): boolean; /** * Tell the cache to discard any uncommitted mutations to attributes * * This method is a candidate to become a mutation * * @category Resource Data * @public * @return the names of fields that were restored */ rollbackAttrs(identifier: ResourceKey): string[]; /** * Query the cache for the changes to relationships of a resource. * * Returns a map of relationship names to RelationshipDiff objects. * * ```ts * type RelationshipDiff = | { kind: 'collection'; remoteState: ResourceKey[]; additions: Set; removals: Set; localState: ResourceKey[]; reordered: boolean; } | { kind: 'resource'; remoteState: ResourceKey | null; localState: ResourceKey | null; }; ``` * * @category Resource Data * @public */ changedRelationships(identifier: ResourceKey): Map; /** * Query the cache for whether any mutated relationships exist * * @category Resource Data * @public */ hasChangedRelationships(identifier: ResourceKey): boolean; /** * Tell the cache to discard any uncommitted mutations to relationships. * * This will also discard the change on any appropriate inverses. * * This method is a candidate to become a mutation * * @category Resource Data * @public * @return the names of relationships that were restored */ rollbackRelationships(identifier: ResourceKey): string[]; /** * Query the cache for the current state of a relationship property * * @category Resource Data * @public * @return resource relationship object */ getRelationship(identifier: ResourceKey, field: string): ResourceRelationship | CollectionRelationship; /** * Query the cache for the remote state of a relationship property * * @category Resource Data * @public * @return resource relationship object */ getRemoteRelationship(identifier: ResourceKey, field: string): ResourceRelationship | CollectionRelationship; /** * Update the cache state for the given resource to be marked * as locally deleted, or remove such a mark. * * This method is a candidate to become a mutation * * @category Resource State * @public */ setIsDeleted(identifier: ResourceKey, isDeleted: boolean): void; /** * Query the cache for any validation errors applicable to the given resource. * * @category Resource State * @public */ getErrors(identifier: ResourceKey): ApiError[]; /** * Query the cache for whether a given resource has any available data * * @category Resource State * @public */ isEmpty(identifier: ResourceKey): boolean; /** * Query the cache for whether a given resource was created locally and not * yet persisted. * * @category Resource State * @public */ isNew(identifier: ResourceKey): boolean; /** * Query the cache for whether a given resource is marked as deleted (but not * necessarily persisted yet). * * @category Resource State * @public */ isDeleted(identifier: ResourceKey): boolean; /** * Query the cache for whether a given resource has been deleted and that deletion * has also been persisted. * * @category Resource State * @public */ isDeletionCommitted(identifier: ResourceKey): boolean; }