@warp-drive/experiments 0.2.5-alpha.8 → 0.2.5-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -22,7 +22,7 @@
22
22
 
23
23
  Install using your javascript package manager of choice. For instance with [pnpm](https://pnpm.io/)
24
24
 
25
- ```no-highlight
25
+ ```sh
26
26
  pnpm add @warp-drive/experiments
27
27
  ```
28
28
 
@@ -31,4 +31,3 @@ pnpm add @warp-drive/experiments
31
31
  - [DataWorker](./src/data-worker/README.md)
32
32
  - [DocumentStorage](./src/document-storage/README.md)
33
33
  - [ImageWorker](./src/image-worker/README.md)
34
- - [PersistedCache](./src/persisted-cache/README.md)
@@ -1,14 +1,6 @@
1
- import type { Store } from "@warp-drive/core";
2
- import type { StableDocumentIdentifier } from "@warp-drive/core/types/identifier";
3
1
  import type { ImmutableCreateRequestOptions, ImmutableDeleteRequestOptions, ImmutableRequestInfo, ImmutableUpdateRequestOptions, StructuredDataDocument } from "@warp-drive/core/types/request";
4
2
  import type { ApiError } from "@warp-drive/core/types/spec/error";
5
3
  export declare const MUTATION_OPS: Set<string>;
6
- /**
7
- * In a Worker, any time we are asked to make a request, data needs to be returned.
8
- * background requests are ergo no different than foreground requests.
9
- * @internal
10
- */
11
- export declare function calcShouldFetch(store: Store, request: ImmutableRequestInfo, hasCachedValue: boolean, identifier: StableDocumentIdentifier | null): boolean;
12
4
  export declare function isMutation(request: Partial<ImmutableRequestInfo>): request is ImmutableUpdateRequestOptions | ImmutableCreateRequestOptions | ImmutableDeleteRequestOptions;
13
5
  export declare function isCacheAffecting<T>(document: StructuredDataDocument<T>): boolean;
14
6
  type RobustError = Error & {
@@ -16,6 +8,5 @@ type RobustError = Error & {
16
8
  errors?: ApiError[];
17
9
  content?: unknown;
18
10
  };
19
- // TODO @runspired, consider if we should deep freeze errors (potentially only in debug) vs cloning them
20
11
  export declare function cloneError(error: RobustError): RobustError;
21
12
  export {};
@@ -1,4 +1,4 @@
1
- import type { ExistingRecordIdentifier } from "@warp-drive/core/types/identifier";
1
+ import type { PersistedResourceKey } from "@warp-drive/core/types/identifier";
2
2
  import type { StructuredDocument } from "@warp-drive/core/types/request";
3
3
  import type { ResourceDataDocument, ResourceDocument } from "@warp-drive/core/types/spec/document";
4
4
  import type { ExistingResourceObject } from "@warp-drive/core/types/spec/json-api-raw";
@@ -29,7 +29,7 @@ export type DocumentStorageOptions = {
29
29
  * CacheFileDocument is a StructuredDocument (request response) whose `content` is
30
30
  * the ResourceDocument returned by inserting the request into a Store's Cache.
31
31
  */
32
- type CacheFileDocument = StructuredDocument<ResourceDocument<ExistingRecordIdentifier>>;
32
+ type CacheFileDocument = StructuredDocument<ResourceDocument>;
33
33
  /**
34
34
  * A CacheDocument is a reconstructed request response that rehydrates ResourceDocument
35
35
  * with the associated resources based on their identifiers.
@@ -56,9 +56,9 @@ declare class InternalDocumentStorage {
56
56
  _read(): Promise<MemCache>;
57
57
  _patch(documentKey: string, document: CacheFileDocument, updatedResources: Map<string, ExistingResourceObject>): Promise<void>;
58
58
  getDocument(key: DocumentIdentifier): Promise<CacheDocument | null>;
59
- putDocument(document: CacheFileDocument, resourceCollector: (resourceIdentifier: ExistingRecordIdentifier) => ExistingResourceObject): Promise<void>;
60
- _getResources(document: ResourceDataDocument<ExistingRecordIdentifier>, resourceCollector: (resourceIdentifier: ExistingRecordIdentifier) => ExistingResourceObject, resources?: Map<string, ExistingResourceObject>): Map<string, ExistingResourceObject>;
61
- putResources(document: ResourceDataDocument<ExistingRecordIdentifier>, resourceCollector: (resourceIdentifier: ExistingRecordIdentifier) => ExistingResourceObject): Promise<void>;
59
+ putDocument(document: CacheFileDocument, resourceCollector: (resourceIdentifier: PersistedResourceKey) => ExistingResourceObject): Promise<void>;
60
+ _getResources(document: ResourceDataDocument, resourceCollector: (resourceIdentifier: PersistedResourceKey) => ExistingResourceObject, resources?: Map<string, ExistingResourceObject>): Map<string, ExistingResourceObject>;
61
+ putResources(document: ResourceDataDocument, resourceCollector: (resourceIdentifier: PersistedResourceKey) => ExistingResourceObject): Promise<void>;
62
62
  clear(reset?: boolean): Promise<void>;
63
63
  }
64
64
  /**
@@ -83,8 +83,8 @@ export declare class DocumentStorage {
83
83
  readonly _storage: InternalDocumentStorage;
84
84
  constructor(options?: Partial<DocumentStorageOptions>);
85
85
  getDocument(key: DocumentIdentifier): Promise<CacheDocument | null>;
86
- putDocument(document: CacheFileDocument, resourceCollector: (resourceIdentifier: ExistingRecordIdentifier) => ExistingResourceObject): Promise<void>;
87
- putResources(document: ResourceDataDocument<ExistingRecordIdentifier>, resourceCollector: (resourceIdentifier: ExistingRecordIdentifier) => ExistingResourceObject): Promise<void>;
86
+ putDocument(document: CacheFileDocument, resourceCollector: (resourceIdentifier: PersistedResourceKey) => ExistingResourceObject): Promise<void>;
87
+ putResources(document: ResourceDataDocument, resourceCollector: (resourceIdentifier: PersistedResourceKey) => ExistingResourceObject): Promise<void>;
88
88
  clear(reset?: boolean): Promise<void>;
89
89
  }
90
90
  export {};
@@ -1,4 +1,5 @@
1
1
  import { D as DocumentStorage } from "./index-CGCX7hY2.js";
2
+ import { assertPrivateStore } from '@warp-drive/core/store/-private';
2
3
  import { SkipCache } from '@warp-drive/core/types/request';
3
4
  import { macroCondition, getGlobalConfig } from '@embroider/macros';
4
5
  const WorkerScope = globalThis.SharedWorkerGlobalScope;
@@ -204,7 +205,7 @@ const CacheHandler = {
204
205
  const {
205
206
  store
206
207
  } = context.request;
207
- const identifier = store.identifierCache.getOrCreateDocumentIdentifier(context.request);
208
+ const identifier = store.cacheKeyManager.getOrCreateDocumentIdentifier(context.request);
208
209
  const peeked = identifier ? store.cache.peekRequest(identifier) : null;
209
210
  if (identifier && !peeked) {
210
211
  // if we are using persisted cache, we should attempt to populate the in-memory cache now
@@ -257,6 +258,7 @@ function maybeUpdateObjects(store, document) {
257
258
  data
258
259
  });
259
260
  } else {
261
+ // @ts-expect-error FIXME investigate why document.data won't accept the signature
260
262
  const data = document.data ? store.cache.peek(document.data) : null;
261
263
  return Object.assign({}, document, {
262
264
  data
@@ -296,7 +298,7 @@ function updateCacheForSuccess(store, request, document) {
296
298
  } else {
297
299
  response = store.cache.put(document);
298
300
  if (response.lid) {
299
- const identifier = store.identifierCache.getOrCreateDocumentIdentifier(request);
301
+ const identifier = store.cacheKeyManager.getOrCreateDocumentIdentifier(request);
300
302
  const full = store.cache.peekRequest(identifier);
301
303
  maybeUpdatePersistedCache(store, full);
302
304
  }
@@ -305,6 +307,7 @@ function updateCacheForSuccess(store, request, document) {
305
307
  }
306
308
  function handleFetchSuccess(store, request, identifier, document) {
307
309
  let response;
310
+ assertPrivateStore(store);
308
311
  store._join(() => {
309
312
  response = updateCacheForSuccess(store, request, document);
310
313
  });
@@ -321,7 +324,7 @@ function updateCacheForError(store, request, error) {
321
324
  const record = request.data?.record || request.records?.[0];
322
325
  store.cache.commitWasRejected(record, errors);
323
326
  } else {
324
- const identifier = store.identifierCache.getOrCreateDocumentIdentifier(request);
327
+ const identifier = store.cacheKeyManager.getOrCreateDocumentIdentifier(request);
325
328
  if (identifier) {
326
329
  maybeUpdatePersistedCache(store, error);
327
330
  }
@@ -332,6 +335,7 @@ function handleFetchError(store, request, identifier, error) {
332
335
  if (request.signal?.aborted) {
333
336
  throw error;
334
337
  }
338
+ assertPrivateStore(store);
335
339
  let response;
336
340
  store._join(() => {
337
341
  response = updateCacheForError(store, request, error);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@warp-drive/experiments",
3
3
  "description": "Experimental features for EmberData/WarpDrive",
4
- "version": "0.2.5-alpha.8",
4
+ "version": "0.2.5-beta.0",
5
5
  "license": "MIT",
6
6
  "author": "Chris Thoburn <runspired@users.noreply.github.com>",
7
7
  "repository": {
@@ -12,10 +12,6 @@
12
12
  "homepage": "https://github.com/emberjs/data",
13
13
  "bugs": "https://github.com/emberjs/data/issues",
14
14
  "exports": {
15
- "./persisted-cache": {
16
- "types": "./declarations/persisted-cache.d.ts",
17
- "default": "./dist/persisted-cache.js"
18
- },
19
15
  "./document-storage": {
20
16
  "types": "./declarations/document-storage.d.ts",
21
17
  "default": "./dist/document-storage.js"
@@ -48,7 +44,7 @@
48
44
  ],
49
45
  "peerDependencies": {
50
46
  "@sqlite.org/sqlite-wasm": "3.46.0-build2",
51
- "@warp-drive/core": "5.7.0-alpha.8"
47
+ "@warp-drive/core": "5.7.0-beta.0"
52
48
  },
53
49
  "peerDependenciesMeta": {
54
50
  "@sqlite.org/sqlite-wasm": {
@@ -56,18 +52,18 @@
56
52
  }
57
53
  },
58
54
  "dependencies": {
59
- "@embroider/macros": "^1.16.12"
55
+ "@embroider/macros": "^1.18.1"
60
56
  },
61
57
  "devDependencies": {
62
- "@babel/core": "^7.26.10",
63
- "@babel/plugin-transform-typescript": "^7.27.0",
64
- "@babel/preset-env": "^7.26.9",
65
- "@babel/preset-typescript": "^7.27.0",
66
- "@warp-drive/internal-config": "5.7.0-alpha.8",
67
- "@warp-drive/core": "5.7.0-alpha.8",
58
+ "@babel/core": "^7.28.3",
59
+ "@babel/plugin-transform-typescript": "^7.28.0",
60
+ "@babel/preset-env": "^7.28.3",
61
+ "@babel/preset-typescript": "^7.27.1",
62
+ "@warp-drive/internal-config": "5.7.0-beta.0",
63
+ "@warp-drive/core": "5.7.0-beta.0",
68
64
  "@sqlite.org/sqlite-wasm": "3.46.0-build2",
69
- "typescript": "^5.8.3",
70
- "vite": "^7.0.0"
65
+ "typescript": "^5.9.2",
66
+ "vite": "^7.1.3"
71
67
  },
72
68
  "volta": {
73
69
  "extends": "../../package.json"
@@ -1,465 +0,0 @@
1
- import type { Cache, ChangedAttributesHash, RelationshipDiff } from "@warp-drive/core/types/cache";
2
- import type { ResourceBlob } from "@warp-drive/core/types/cache/aliases";
3
- import type { Change } from "@warp-drive/core/types/cache/change";
4
- import type { Mutation } from "@warp-drive/core/types/cache/mutations";
5
- import type { Operation } from "@warp-drive/core/types/cache/operations";
6
- import type { CollectionRelationship, ResourceRelationship } from "@warp-drive/core/types/cache/relationship";
7
- import type { StableDocumentIdentifier, StableRecordIdentifier } from "@warp-drive/core/types/identifier";
8
- import type { Value } from "@warp-drive/core/types/json/raw";
9
- import type { TypeFromInstanceOrString } from "@warp-drive/core/types/record";
10
- import type { RequestContext, StructuredDataDocument, StructuredDocument } from "@warp-drive/core/types/request";
11
- import type { ResourceDocument, SingleResourceDataDocument } from "@warp-drive/core/types/spec/document";
12
- import type { ApiError } from "@warp-drive/core/types/spec/error";
13
- /**
14
- * The PersistedCache wraps a Cache to enhance it with
15
- * Persisted Storage capabilities.
16
- *
17
- * @class PersistedCache
18
- * @internal
19
- */
20
- export declare class PersistedCache implements Cache {
21
- _cache: Cache;
22
- _db: IDBDatabase;
23
- version: "2";
24
- constructor(cache: Cache, db: IDBDatabase);
25
- // Cache Management
26
- // ================
27
- /**
28
- * Cache the response to a request
29
- *
30
- * Unlike `store.push` which has UPSERT
31
- * semantics, `put` has `replace` semantics similar to
32
- * the `http` method `PUT`
33
- *
34
- * the individually cacheabl
35
- * e resource data it may contain
36
- * should upsert, but the document data surrounding it should
37
- * fully replace any existing information
38
- *
39
- * Note that in order to support inserting arbitrary data
40
- * to the cache that did not originate from a request `put`
41
- * should expect to sometimes encounter a document with only
42
- * a `content` member and therefor must not assume the existence
43
- * of `request` and `response` on the document.
44
- *
45
- * @param {StructuredDocument} doc
46
- * @return {ResourceDocument}
47
- * @internal
48
- */
49
- put<T>(doc: StructuredDocument<T> | {
50
- content: T;
51
- }): ResourceDocument;
52
- /**
53
- * Perform an operation on the cache to update the remote state.
54
- *
55
- * Note: currently the only valid operation is a MergeOperation
56
- * which occurs when a collision of identifiers is detected.
57
- *
58
- * @internal
59
- * @param op the operation to perform
60
- * @return {void}
61
- */
62
- patch(op: Operation): void;
63
- /**
64
- * Update resource data with a local mutation. Currently supports operations
65
- * on relationships only.
66
- *
67
- * @internal
68
- * @param mutation
69
- */
70
- mutate(mutation: Mutation): void;
71
- /**
72
- * Peek resource data from the Cache.
73
- *
74
- * In development, if the return value
75
- * is JSON the return value
76
- * will be deep-cloned and deep-frozen
77
- * to prevent mutation thereby enforcing cache
78
- * Immutability.
79
- *
80
- * This form of peek is useful for implementations
81
- * that want to feed raw-data from cache to the UI
82
- * or which want to interact with a blob of data
83
- * directly from the presentation cache.
84
- *
85
- * An implementation might want to do this because
86
- * de-referencing records which read from their own
87
- * blob is generally safer because the record does
88
- * not require retainining connections to the Store
89
- * and Cache to present data on a per-field basis.
90
- *
91
- * This generally takes the place of `getAttr` as
92
- * an API and may even take the place of `getRelationship`
93
- * depending on implementation specifics, though this
94
- * latter usage is less recommended due to the advantages
95
- * of the Graph handling necessary entanglements and
96
- * notifications for relational data.
97
- *
98
- * @internal
99
- * @param {StableRecordIdentifier | StableDocumentIdentifier} identifier
100
- * @return {ResourceDocument | ResourceBlob | null} the known resource data
101
- */
102
- peek<T = unknown>(identifier: StableRecordIdentifier<TypeFromInstanceOrString<T>>): T | null;
103
- peek(identifier: StableDocumentIdentifier): ResourceDocument | null;
104
- /**
105
- * Peek resource data from the Cache.
106
- *
107
- * In development, if the return value
108
- * is JSON the return value
109
- * will be deep-cloned and deep-frozen
110
- * to prevent mutation thereby enforcing cache
111
- * Immutability.
112
- *
113
- * This form of peek is useful for implementations
114
- * that want to feed raw-data from cache to the UI
115
- * or which want to interact with a blob of data
116
- * directly from the presentation cache.
117
- *
118
- * An implementation might want to do this because
119
- * de-referencing records which read from their own
120
- * blob is generally safer because the record does
121
- * not require retainining connections to the Store
122
- * and Cache to present data on a per-field basis.
123
- *
124
- * This generally takes the place of `getAttr` as
125
- * an API and may even take the place of `getRelationship`
126
- * depending on implementation specifics, though this
127
- * latter usage is less recommended due to the advantages
128
- * of the Graph handling necessary entanglements and
129
- * notifications for relational data.
130
- *
131
- * @internal
132
- * @param {StableRecordIdentifier | StableDocumentIdentifier} identifier
133
- * @return {ResourceDocument | ResourceBlob | null} the known resource data
134
- */
135
- peekRemoteState<T = unknown>(identifier: StableRecordIdentifier<TypeFromInstanceOrString<T>>): T | null;
136
- peekRemoteState(identifier: StableDocumentIdentifier): ResourceDocument | null;
137
- /**
138
- * Peek the Cache for the existing request data associated with
139
- * a cacheable request
140
- *
141
- * @param {StableDocumentIdentifier}
142
- * @return {StableDocumentIdentifier | null}
143
- * @internal
144
- */
145
- peekRequest(identifier: StableDocumentIdentifier): StructuredDocument<ResourceDocument> | null;
146
- /**
147
- * Push resource data from a remote source into the cache for this identifier
148
- *
149
- * @internal
150
- * @param identifier
151
- * @param data
152
- * @param hasRecord
153
- * @return {void | string[]} if `hasRecord` is true then calculated key changes should be returned
154
- */
155
- upsert(identifier: StableRecordIdentifier, data: ResourceBlob, hasRecord: boolean): void | string[];
156
- // Cache Forking Support
157
- // =====================
158
- /**
159
- * Create a fork of the cache from the current state.
160
- *
161
- * Applications should typically not call this method themselves,
162
- * preferring instead to fork at the Store level, which will
163
- * utilize this method to fork the cache.
164
- *
165
- * @internal
166
- * @return {Promise<Cache>}
167
- */
168
- fork(): Promise<Cache>;
169
- /**
170
- * Merge a fork back into a parent Cache.
171
- *
172
- * Applications should typically not call this method themselves,
173
- * preferring instead to merge at the Store level, which will
174
- * utilize this method to merge the caches.
175
- *
176
- * @param {Cache} cache
177
- * @internal
178
- * @return {Promise<void>}
179
- */
180
- merge(cache: Cache): Promise<void>;
181
- /**
182
- * Generate the list of changes applied to all
183
- * record in the store.
184
- *
185
- * Each individual resource or document that has
186
- * been mutated should be described as an individual
187
- * `Change` entry in the returned array.
188
- *
189
- * A `Change` is described by an object containing up to
190
- * three properties: (1) the `identifier` of the entity that
191
- * changed; (2) the `op` code of that change being one of
192
- * `upsert` or `remove`, and if the op is `upsert` a `patch`
193
- * containing the data to merge into the cache for the given
194
- * entity.
195
- *
196
- * This `patch` is opaque to the Store but should be understood
197
- * by the Cache and may expect to be utilized by an Adapter
198
- * when generating data during a `save` operation.
199
- *
200
- * It is generally recommended that the `patch` contain only
201
- * the updated state, ignoring fields that are unchanged
202
- *
203
- * ```ts
204
- * interface Change {
205
- * identifier: StableRecordIdentifier | StableDocumentIdentifier;
206
- * op: 'upsert' | 'remove';
207
- * patch?: unknown;
208
- * }
209
- * ```
210
- *
211
- * @internal
212
- */
213
- diff(): Promise<Change[]>;
214
- // SSR Support
215
- // ===========
216
- /**
217
- * Serialize the entire contents of the Cache into a Stream
218
- * which may be fed back into a new instance of the same Cache
219
- * via `cache.hydrate`.
220
- *
221
- * @return {Promise<ReadableStream>}
222
- * @internal
223
- */
224
- dump(): Promise<ReadableStream<unknown>>;
225
- /**
226
- * hydrate a Cache from a Stream with content previously serialized
227
- * from another instance of the same Cache, resolving when hydration
228
- * is complete.
229
- *
230
- * This method should expect to be called both in the context of restoring
231
- * the Cache during application rehydration after SSR **AND** at unknown
232
- * times during the lifetime of an already booted application when it is
233
- * desired to bulk-load additional information into the cache. This latter
234
- * behavior supports optimizing pre/fetching of data for route transitions
235
- * via data-only SSR modes.
236
- *
237
- * @param {ReadableStream} stream
238
- * @return {Promise<void>}
239
- * @internal
240
- */
241
- hydrate(stream: ReadableStream<unknown>): Promise<void>;
242
- // Cache
243
- // =====
244
- // Resource Support
245
- // ================
246
- /**
247
- * [LIFECYLCE] Signal to the cache that a new record has been instantiated on the client
248
- *
249
- * It returns properties from options that should be set on the record during the create
250
- * process. This return value behavior is deprecated.
251
- *
252
- * @internal
253
- * @param identifier
254
- * @param options
255
- */
256
- clientDidCreate(identifier: StableRecordIdentifier, options?: Record<string, unknown>): Record<string, unknown>;
257
- /**
258
- * [LIFECYCLE] Signals to the cache that a resource
259
- * will be part of a save transaction.
260
- *
261
- * @internal
262
- * @param identifier
263
- */
264
- willCommit(identifier: StableRecordIdentifier, context: RequestContext): void;
265
- /**
266
- * [LIFECYCLE] Signals to the cache that a resource
267
- * was successfully updated as part of a save transaction.
268
- *
269
- * @internal
270
- * @param identifier
271
- * @param data
272
- */
273
- didCommit(identifier: StableRecordIdentifier, result: StructuredDataDocument<unknown>): SingleResourceDataDocument;
274
- /**
275
- * [LIFECYCLE] Signals to the cache that a resource
276
- * was update via a save transaction failed.
277
- *
278
- * @internal
279
- * @param identifier
280
- * @param errors
281
- */
282
- commitWasRejected(identifier: StableRecordIdentifier, errors?: ApiError[]): void;
283
- /**
284
- * [LIFECYCLE] Signals to the cache that all data for a resource
285
- * should be cleared.
286
- *
287
- * @internal
288
- * @param identifier
289
- */
290
- unloadRecord(identifier: StableRecordIdentifier): void;
291
- // Granular Resource Data APIs
292
- // ===========================
293
- /**
294
- * Retrieve the data for an attribute from the cache
295
- *
296
- * @internal
297
- * @param identifier
298
- * @param propertyName
299
- * @return {unknown}
300
- */
301
- getAttr(identifier: StableRecordIdentifier, field: string): Value | undefined;
302
- /**
303
- * Retrieve the remote state for an attribute from the cache
304
- *
305
- * @internal
306
- * @param identifier
307
- * @param propertyName
308
- * @return {unknown}
309
- */
310
- getRemoteAttr(identifier: StableRecordIdentifier, field: string): Value | undefined;
311
- /**
312
- * Mutate the data for an attribute in the cache
313
- *
314
- * @internal
315
- * @param identifier
316
- * @param propertyName
317
- * @param value
318
- */
319
- setAttr(identifier: StableRecordIdentifier, propertyName: string, value: Value): void;
320
- /**
321
- * Query the cache for the changed attributes of a resource.
322
- *
323
- * @internal
324
- * @param identifier
325
- * @return
326
- */
327
- changedAttrs(identifier: StableRecordIdentifier): ChangedAttributesHash;
328
- /**
329
- * Query the cache for whether any mutated attributes exist
330
- *
331
- * @internal
332
- * @param identifier
333
- * @return {Boolean}
334
- */
335
- hasChangedAttrs(identifier: StableRecordIdentifier): boolean;
336
- /**
337
- * Tell the cache to discard any uncommitted mutations to attributes
338
- *
339
- * @internal
340
- * @param identifier
341
- * @return the names of attributes that were restored
342
- */
343
- rollbackAttrs(identifier: StableRecordIdentifier): string[];
344
- /**
345
- * Query the cache for the changes to relationships of a resource.
346
- *
347
- * Returns a map of relationship names to RelationshipDiff objects.
348
- *
349
- * ```ts
350
- * type RelationshipDiff =
351
- | {
352
- kind: 'collection';
353
- remoteState: StableRecordIdentifier[];
354
- additions: Set<StableRecordIdentifier>;
355
- removals: Set<StableRecordIdentifier>;
356
- localState: StableRecordIdentifier[];
357
- reordered: boolean;
358
- }
359
- | {
360
- kind: 'resource';
361
- remoteState: StableRecordIdentifier | null;
362
- localState: StableRecordIdentifier | null;
363
- };
364
- ```
365
- *
366
- * @public
367
- * @param {StableRecordIdentifier} identifier
368
- * @return {Map<string, RelationshipDiff>}
369
- */
370
- changedRelationships(identifier: StableRecordIdentifier): Map<string, RelationshipDiff>;
371
- /**
372
- * Query the cache for whether any mutated attributes exist
373
- *
374
- * @public
375
- * @param {StableRecordIdentifier} identifier
376
- * @return {Boolean}
377
- */
378
- hasChangedRelationships(identifier: StableRecordIdentifier): boolean;
379
- /**
380
- * Tell the cache to discard any uncommitted mutations to relationships.
381
- *
382
- * This will also discard the change on any appropriate inverses.
383
- *
384
- * This method is a candidate to become a mutation
385
- *
386
- * @public
387
- * @param {StableRecordIdentifier} identifier
388
- * @return {String[]} the names of relationships that were restored
389
- */
390
- rollbackRelationships(identifier: StableRecordIdentifier): string[];
391
- // Relationships
392
- // =============
393
- /**
394
- * Query the cache for the current state of a relationship property
395
- *
396
- * @internal
397
- * @param identifier
398
- * @param propertyName
399
- * @return resource relationship object
400
- */
401
- getRelationship(identifier: StableRecordIdentifier, field: string, isCollection?: boolean): ResourceRelationship | CollectionRelationship;
402
- /**
403
- * Query the remote state for the current state of a relationship property
404
- *
405
- * @internal
406
- * @param identifier
407
- * @param propertyName
408
- * @return resource relationship object
409
- */
410
- getRemoteRelationship(identifier: StableRecordIdentifier, field: string, isCollection?: boolean): ResourceRelationship | CollectionRelationship;
411
- // Resource State
412
- // ===============
413
- /**
414
- * Update the cache state for the given resource to be marked as locally deleted,
415
- * or remove such a mark.
416
- *
417
- * @internal
418
- * @param identifier
419
- * @param isDeleted
420
- */
421
- setIsDeleted(identifier: StableRecordIdentifier, isDeleted: boolean): void;
422
- /**
423
- * Query the cache for any validation errors applicable to the given resource.
424
- *
425
- * @internal
426
- * @param identifier
427
- * @return
428
- */
429
- getErrors(identifier: StableRecordIdentifier): ApiError[];
430
- /**
431
- * Query the cache for whether a given resource has any available data
432
- *
433
- * @internal
434
- * @param identifier
435
- * @return {Boolean}
436
- */
437
- isEmpty(identifier: StableRecordIdentifier): boolean;
438
- /**
439
- * Query the cache for whether a given resource was created locally and not
440
- * yet persisted.
441
- *
442
- * @internal
443
- * @param identifier
444
- * @return {Boolean}
445
- */
446
- isNew(identifier: StableRecordIdentifier): boolean;
447
- /**
448
- * Query the cache for whether a given resource is marked as deleted (but not
449
- * necessarily persisted yet).
450
- *
451
- * @internal
452
- * @param identifier
453
- * @return {Boolean}
454
- */
455
- isDeleted(identifier: StableRecordIdentifier): boolean;
456
- /**
457
- * Query the cache for whether a given resource has been deleted and that deletion
458
- * has also been persisted.
459
- *
460
- * @internal
461
- * @param identifier
462
- * @return {Boolean}
463
- */
464
- isDeletionCommitted(identifier: StableRecordIdentifier): boolean;
465
- }
@@ -1 +0,0 @@
1
- export { PersistedCache } from "./persisted-cache/cache.js";
@@ -1,588 +0,0 @@
1
- /**
2
- * The PersistedCache wraps a Cache to enhance it with
3
- * Persisted Storage capabilities.
4
- *
5
- * @class PersistedCache
6
- * @internal
7
- */
8
- class PersistedCache {
9
- constructor(cache, db) {
10
- this.version = '2';
11
- this._cache = cache;
12
- this._db = db;
13
- }
14
-
15
- // Cache Management
16
- // ================
17
-
18
- /**
19
- * Cache the response to a request
20
- *
21
- * Unlike `store.push` which has UPSERT
22
- * semantics, `put` has `replace` semantics similar to
23
- * the `http` method `PUT`
24
- *
25
- * the individually cacheabl
26
- * e resource data it may contain
27
- * should upsert, but the document data surrounding it should
28
- * fully replace any existing information
29
- *
30
- * Note that in order to support inserting arbitrary data
31
- * to the cache that did not originate from a request `put`
32
- * should expect to sometimes encounter a document with only
33
- * a `content` member and therefor must not assume the existence
34
- * of `request` and `response` on the document.
35
- *
36
- * @param {StructuredDocument} doc
37
- * @return {ResourceDocument}
38
- * @internal
39
- */
40
- put(doc) {
41
- const result = this._cache.put(doc);
42
- if (!result.lid) {
43
- return result;
44
- }
45
- const transaction = this._db.transaction(['request', 'resource'], 'readwrite', {
46
- durability: 'relaxed'
47
- });
48
- const request = this._cache.peekRequest({
49
- lid: result.lid
50
- });
51
- const requests = transaction.objectStore('request');
52
- const resources = transaction.objectStore('resource');
53
- requests.put(request);
54
- if ('data' in result && result.data) {
55
- const resourceData = Array.isArray(result.data) ? result.data : [result.data];
56
- resourceData.forEach(identifier => {
57
- resources.put(this._cache.peek(identifier), identifier.lid);
58
- });
59
- }
60
- if ('included' in result && result.included) {
61
- const included = result.included;
62
- included.forEach(identifier => {
63
- resources.put(this._cache.peek(identifier), identifier.lid);
64
- });
65
- }
66
- return result;
67
- }
68
-
69
- /**
70
- * Perform an operation on the cache to update the remote state.
71
- *
72
- * Note: currently the only valid operation is a MergeOperation
73
- * which occurs when a collision of identifiers is detected.
74
- *
75
- * @internal
76
- * @param op the operation to perform
77
- * @return {void}
78
- */
79
- patch(op) {
80
- this._cache.patch(op);
81
- }
82
-
83
- /**
84
- * Update resource data with a local mutation. Currently supports operations
85
- * on relationships only.
86
- *
87
- * @internal
88
- * @param mutation
89
- */
90
- mutate(mutation) {
91
- this._cache.mutate(mutation);
92
- }
93
-
94
- /**
95
- * Peek resource data from the Cache.
96
- *
97
- * In development, if the return value
98
- * is JSON the return value
99
- * will be deep-cloned and deep-frozen
100
- * to prevent mutation thereby enforcing cache
101
- * Immutability.
102
- *
103
- * This form of peek is useful for implementations
104
- * that want to feed raw-data from cache to the UI
105
- * or which want to interact with a blob of data
106
- * directly from the presentation cache.
107
- *
108
- * An implementation might want to do this because
109
- * de-referencing records which read from their own
110
- * blob is generally safer because the record does
111
- * not require retainining connections to the Store
112
- * and Cache to present data on a per-field basis.
113
- *
114
- * This generally takes the place of `getAttr` as
115
- * an API and may even take the place of `getRelationship`
116
- * depending on implementation specifics, though this
117
- * latter usage is less recommended due to the advantages
118
- * of the Graph handling necessary entanglements and
119
- * notifications for relational data.
120
- *
121
- * @internal
122
- * @param {StableRecordIdentifier | StableDocumentIdentifier} identifier
123
- * @return {ResourceDocument | ResourceBlob | null} the known resource data
124
- */
125
-
126
- peek(identifier) {
127
- return this._cache.peek(identifier);
128
- }
129
-
130
- /**
131
- * Peek resource data from the Cache.
132
- *
133
- * In development, if the return value
134
- * is JSON the return value
135
- * will be deep-cloned and deep-frozen
136
- * to prevent mutation thereby enforcing cache
137
- * Immutability.
138
- *
139
- * This form of peek is useful for implementations
140
- * that want to feed raw-data from cache to the UI
141
- * or which want to interact with a blob of data
142
- * directly from the presentation cache.
143
- *
144
- * An implementation might want to do this because
145
- * de-referencing records which read from their own
146
- * blob is generally safer because the record does
147
- * not require retainining connections to the Store
148
- * and Cache to present data on a per-field basis.
149
- *
150
- * This generally takes the place of `getAttr` as
151
- * an API and may even take the place of `getRelationship`
152
- * depending on implementation specifics, though this
153
- * latter usage is less recommended due to the advantages
154
- * of the Graph handling necessary entanglements and
155
- * notifications for relational data.
156
- *
157
- * @internal
158
- * @param {StableRecordIdentifier | StableDocumentIdentifier} identifier
159
- * @return {ResourceDocument | ResourceBlob | null} the known resource data
160
- */
161
-
162
- peekRemoteState(identifier) {
163
- return this._cache.peekRemoteState(identifier);
164
- }
165
-
166
- /**
167
- * Peek the Cache for the existing request data associated with
168
- * a cacheable request
169
- *
170
- * @param {StableDocumentIdentifier}
171
- * @return {StableDocumentIdentifier | null}
172
- * @internal
173
- */
174
- peekRequest(identifier) {
175
- return this._cache.peekRequest(identifier);
176
- }
177
-
178
- /**
179
- * Push resource data from a remote source into the cache for this identifier
180
- *
181
- * @internal
182
- * @param identifier
183
- * @param data
184
- * @param hasRecord
185
- * @return {void | string[]} if `hasRecord` is true then calculated key changes should be returned
186
- */
187
- upsert(identifier, data, hasRecord) {
188
- return this._cache.upsert(identifier, data, hasRecord);
189
- }
190
-
191
- // Cache Forking Support
192
- // =====================
193
-
194
- /**
195
- * Create a fork of the cache from the current state.
196
- *
197
- * Applications should typically not call this method themselves,
198
- * preferring instead to fork at the Store level, which will
199
- * utilize this method to fork the cache.
200
- *
201
- * @internal
202
- * @return {Promise<Cache>}
203
- */
204
- fork() {
205
- return this._cache.fork();
206
- }
207
-
208
- /**
209
- * Merge a fork back into a parent Cache.
210
- *
211
- * Applications should typically not call this method themselves,
212
- * preferring instead to merge at the Store level, which will
213
- * utilize this method to merge the caches.
214
- *
215
- * @param {Cache} cache
216
- * @internal
217
- * @return {Promise<void>}
218
- */
219
- merge(cache) {
220
- return this._cache.merge(cache);
221
- }
222
-
223
- /**
224
- * Generate the list of changes applied to all
225
- * record in the store.
226
- *
227
- * Each individual resource or document that has
228
- * been mutated should be described as an individual
229
- * `Change` entry in the returned array.
230
- *
231
- * A `Change` is described by an object containing up to
232
- * three properties: (1) the `identifier` of the entity that
233
- * changed; (2) the `op` code of that change being one of
234
- * `upsert` or `remove`, and if the op is `upsert` a `patch`
235
- * containing the data to merge into the cache for the given
236
- * entity.
237
- *
238
- * This `patch` is opaque to the Store but should be understood
239
- * by the Cache and may expect to be utilized by an Adapter
240
- * when generating data during a `save` operation.
241
- *
242
- * It is generally recommended that the `patch` contain only
243
- * the updated state, ignoring fields that are unchanged
244
- *
245
- * ```ts
246
- * interface Change {
247
- * identifier: StableRecordIdentifier | StableDocumentIdentifier;
248
- * op: 'upsert' | 'remove';
249
- * patch?: unknown;
250
- * }
251
- * ```
252
- *
253
- * @internal
254
- */
255
- diff() {
256
- return this._cache.diff();
257
- }
258
-
259
- // SSR Support
260
- // ===========
261
-
262
- /**
263
- * Serialize the entire contents of the Cache into a Stream
264
- * which may be fed back into a new instance of the same Cache
265
- * via `cache.hydrate`.
266
- *
267
- * @return {Promise<ReadableStream>}
268
- * @internal
269
- */
270
- dump() {
271
- return this._cache.dump();
272
- }
273
-
274
- /**
275
- * hydrate a Cache from a Stream with content previously serialized
276
- * from another instance of the same Cache, resolving when hydration
277
- * is complete.
278
- *
279
- * This method should expect to be called both in the context of restoring
280
- * the Cache during application rehydration after SSR **AND** at unknown
281
- * times during the lifetime of an already booted application when it is
282
- * desired to bulk-load additional information into the cache. This latter
283
- * behavior supports optimizing pre/fetching of data for route transitions
284
- * via data-only SSR modes.
285
- *
286
- * @param {ReadableStream} stream
287
- * @return {Promise<void>}
288
- * @internal
289
- */
290
- hydrate(stream) {
291
- return this._cache.hydrate(stream);
292
- }
293
-
294
- // Cache
295
- // =====
296
-
297
- // Resource Support
298
- // ================
299
-
300
- /**
301
- * [LIFECYLCE] Signal to the cache that a new record has been instantiated on the client
302
- *
303
- * It returns properties from options that should be set on the record during the create
304
- * process. This return value behavior is deprecated.
305
- *
306
- * @internal
307
- * @param identifier
308
- * @param options
309
- */
310
- clientDidCreate(identifier, options) {
311
- return this._cache.clientDidCreate(identifier, options);
312
- }
313
-
314
- /**
315
- * [LIFECYCLE] Signals to the cache that a resource
316
- * will be part of a save transaction.
317
- *
318
- * @internal
319
- * @param identifier
320
- */
321
- willCommit(identifier, context) {
322
- this._cache.willCommit(identifier, context);
323
- }
324
-
325
- /**
326
- * [LIFECYCLE] Signals to the cache that a resource
327
- * was successfully updated as part of a save transaction.
328
- *
329
- * @internal
330
- * @param identifier
331
- * @param data
332
- */
333
- didCommit(identifier, result) {
334
- return this._cache.didCommit(identifier, result);
335
- }
336
-
337
- /**
338
- * [LIFECYCLE] Signals to the cache that a resource
339
- * was update via a save transaction failed.
340
- *
341
- * @internal
342
- * @param identifier
343
- * @param errors
344
- */
345
- commitWasRejected(identifier, errors) {
346
- this._cache.commitWasRejected(identifier, errors);
347
- }
348
-
349
- /**
350
- * [LIFECYCLE] Signals to the cache that all data for a resource
351
- * should be cleared.
352
- *
353
- * @internal
354
- * @param identifier
355
- */
356
- unloadRecord(identifier) {
357
- this._cache.unloadRecord(identifier);
358
- }
359
-
360
- // Granular Resource Data APIs
361
- // ===========================
362
-
363
- /**
364
- * Retrieve the data for an attribute from the cache
365
- *
366
- * @internal
367
- * @param identifier
368
- * @param propertyName
369
- * @return {unknown}
370
- */
371
- getAttr(identifier, field) {
372
- return this._cache.getAttr(identifier, field);
373
- }
374
-
375
- /**
376
- * Retrieve the remote state for an attribute from the cache
377
- *
378
- * @internal
379
- * @param identifier
380
- * @param propertyName
381
- * @return {unknown}
382
- */
383
- getRemoteAttr(identifier, field) {
384
- return this._cache.getRemoteAttr(identifier, field);
385
- }
386
-
387
- /**
388
- * Mutate the data for an attribute in the cache
389
- *
390
- * @internal
391
- * @param identifier
392
- * @param propertyName
393
- * @param value
394
- */
395
- setAttr(identifier, propertyName, value) {
396
- this._cache.setAttr(identifier, propertyName, value);
397
- }
398
-
399
- /**
400
- * Query the cache for the changed attributes of a resource.
401
- *
402
- * @internal
403
- * @param identifier
404
- * @return
405
- */
406
- changedAttrs(identifier) {
407
- return this._cache.changedAttrs(identifier);
408
- }
409
-
410
- /**
411
- * Query the cache for whether any mutated attributes exist
412
- *
413
- * @internal
414
- * @param identifier
415
- * @return {Boolean}
416
- */
417
- hasChangedAttrs(identifier) {
418
- return this._cache.hasChangedAttrs(identifier);
419
- }
420
-
421
- /**
422
- * Tell the cache to discard any uncommitted mutations to attributes
423
- *
424
- * @internal
425
- * @param identifier
426
- * @return the names of attributes that were restored
427
- */
428
- rollbackAttrs(identifier) {
429
- return this._cache.rollbackAttrs(identifier);
430
- }
431
-
432
- /**
433
- * Query the cache for the changes to relationships of a resource.
434
- *
435
- * Returns a map of relationship names to RelationshipDiff objects.
436
- *
437
- * ```ts
438
- * type RelationshipDiff =
439
- | {
440
- kind: 'collection';
441
- remoteState: StableRecordIdentifier[];
442
- additions: Set<StableRecordIdentifier>;
443
- removals: Set<StableRecordIdentifier>;
444
- localState: StableRecordIdentifier[];
445
- reordered: boolean;
446
- }
447
- | {
448
- kind: 'resource';
449
- remoteState: StableRecordIdentifier | null;
450
- localState: StableRecordIdentifier | null;
451
- };
452
- ```
453
- *
454
- * @public
455
- * @param {StableRecordIdentifier} identifier
456
- * @return {Map<string, RelationshipDiff>}
457
- */
458
- changedRelationships(identifier) {
459
- return this._cache.changedRelationships(identifier);
460
- }
461
-
462
- /**
463
- * Query the cache for whether any mutated attributes exist
464
- *
465
- * @public
466
- * @param {StableRecordIdentifier} identifier
467
- * @return {Boolean}
468
- */
469
- hasChangedRelationships(identifier) {
470
- return this._cache.hasChangedRelationships(identifier);
471
- }
472
-
473
- /**
474
- * Tell the cache to discard any uncommitted mutations to relationships.
475
- *
476
- * This will also discard the change on any appropriate inverses.
477
- *
478
- * This method is a candidate to become a mutation
479
- *
480
- * @public
481
- * @param {StableRecordIdentifier} identifier
482
- * @return {String[]} the names of relationships that were restored
483
- */
484
- rollbackRelationships(identifier) {
485
- return this._cache.rollbackRelationships(identifier);
486
- }
487
-
488
- // Relationships
489
- // =============
490
-
491
- /**
492
- * Query the cache for the current state of a relationship property
493
- *
494
- * @internal
495
- * @param identifier
496
- * @param propertyName
497
- * @return resource relationship object
498
- */
499
- getRelationship(identifier, field, isCollection) {
500
- return this._cache.getRelationship(identifier, field, isCollection);
501
- }
502
-
503
- /**
504
- * Query the remote state for the current state of a relationship property
505
- *
506
- * @internal
507
- * @param identifier
508
- * @param propertyName
509
- * @return resource relationship object
510
- */
511
- getRemoteRelationship(identifier, field, isCollection) {
512
- return this._cache.getRemoteRelationship(identifier, field, isCollection);
513
- }
514
-
515
- // Resource State
516
- // ===============
517
-
518
- /**
519
- * Update the cache state for the given resource to be marked as locally deleted,
520
- * or remove such a mark.
521
- *
522
- * @internal
523
- * @param identifier
524
- * @param isDeleted
525
- */
526
- setIsDeleted(identifier, isDeleted) {
527
- this._cache.setIsDeleted(identifier, isDeleted);
528
- }
529
-
530
- /**
531
- * Query the cache for any validation errors applicable to the given resource.
532
- *
533
- * @internal
534
- * @param identifier
535
- * @return
536
- */
537
- getErrors(identifier) {
538
- return this._cache.getErrors(identifier);
539
- }
540
-
541
- /**
542
- * Query the cache for whether a given resource has any available data
543
- *
544
- * @internal
545
- * @param identifier
546
- * @return {Boolean}
547
- */
548
- isEmpty(identifier) {
549
- return this._cache.isEmpty(identifier);
550
- }
551
-
552
- /**
553
- * Query the cache for whether a given resource was created locally and not
554
- * yet persisted.
555
- *
556
- * @internal
557
- * @param identifier
558
- * @return {Boolean}
559
- */
560
- isNew(identifier) {
561
- return this._cache.isNew(identifier);
562
- }
563
-
564
- /**
565
- * Query the cache for whether a given resource is marked as deleted (but not
566
- * necessarily persisted yet).
567
- *
568
- * @internal
569
- * @param identifier
570
- * @return {Boolean}
571
- */
572
- isDeleted(identifier) {
573
- return this._cache.isDeleted(identifier);
574
- }
575
-
576
- /**
577
- * Query the cache for whether a given resource has been deleted and that deletion
578
- * has also been persisted.
579
- *
580
- * @internal
581
- * @param identifier
582
- * @return {Boolean}
583
- */
584
- isDeletionCommitted(identifier) {
585
- return this._cache.isDeletionCommitted(identifier);
586
- }
587
- }
588
- export { PersistedCache };