@warp-drive-mirror/json-api 5.6.0-beta.1 → 5.6.0-beta.3

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.
@@ -1,34 +1,15 @@
1
- import type { Graph } from "@warp-drive-mirror/core/graph/-private";
2
1
  import type { CacheCapabilitiesManager } from "@warp-drive-mirror/core/types";
3
2
  import type { Cache, ChangedAttributesHash, RelationshipDiff } from "@warp-drive-mirror/core/types/cache";
4
3
  import type { Change } from "@warp-drive-mirror/core/types/cache/change";
5
4
  import type { Operation } from "@warp-drive-mirror/core/types/cache/operations";
6
5
  import type { CollectionRelationship, ResourceRelationship } from "@warp-drive-mirror/core/types/cache/relationship";
7
6
  import type { LocalRelationshipOperation } from "@warp-drive-mirror/core/types/graph";
8
- import type { StableDocumentIdentifier, StableExistingRecordIdentifier, StableRecordIdentifier } from "@warp-drive-mirror/core/types/identifier";
7
+ import type { RequestKey, ResourceKey } from "@warp-drive-mirror/core/types/identifier";
9
8
  import type { Value } from "@warp-drive-mirror/core/types/json/raw";
10
- import type { StructuredDataDocument, StructuredDocument, StructuredErrorDocument } from "@warp-drive-mirror/core/types/request";
9
+ import type { RequestContext, StructuredDataDocument, StructuredDocument, StructuredErrorDocument } from "@warp-drive-mirror/core/types/request";
11
10
  import type { CollectionResourceDataDocument, ResourceDocument, ResourceErrorDocument, ResourceMetaDocument, SingleResourceDataDocument } from "@warp-drive-mirror/core/types/spec/document";
12
11
  import type { ApiError } from "@warp-drive-mirror/core/types/spec/error";
13
12
  import type { CollectionResourceDocument, ExistingResourceObject, ResourceObject, SingleResourceDocument } from "@warp-drive-mirror/core/types/spec/json-api-raw";
14
- interface CachedResource {
15
- id: string | null;
16
- remoteAttrs: Record<string, Value | undefined> | null;
17
- localAttrs: Record<string, Value | undefined> | null;
18
- defaultAttrs: Record<string, Value | undefined> | null;
19
- inflightAttrs: Record<string, Value | undefined> | null;
20
- changes: Record<string, [Value | undefined, Value]> | null;
21
- errors: ApiError[] | null;
22
- isNew: boolean;
23
- isDeleted: boolean;
24
- isDeletionCommitted: boolean;
25
- /**
26
- * debugging only
27
- *
28
- * @internal
29
- */
30
- inflightRelationships?: Record<string, unknown> | null;
31
- }
32
13
  /**
33
14
  * ### JSONAPICache
34
15
  *
@@ -128,20 +109,7 @@ export declare class JSONAPICache implements Cache {
128
109
  * @public
129
110
  */
130
111
  version: "2";
131
- /** @internal */
132
- _capabilities: CacheCapabilitiesManager;
133
- /** @internal */
134
- __cache: Map<StableRecordIdentifier, CachedResource>;
135
- /** @internal */
136
- __destroyedCache: Map<StableRecordIdentifier, CachedResource>;
137
- /** @internal */
138
- __documents: Map<string, StructuredDocument<ResourceDocument>>;
139
- /** @internal */
140
- __graph: Graph;
141
112
  constructor(capabilities: CacheCapabilitiesManager);
142
- ////////// ================ //////////
143
- ////////// Cache Management //////////
144
- ////////// ================ //////////
145
113
  /**
146
114
  * Cache the response to a request
147
115
  *
@@ -183,11 +151,6 @@ export declare class JSONAPICache implements Cache {
183
151
  put<T extends CollectionResourceDocument>(doc: StructuredDataDocument<T>): CollectionResourceDataDocument;
184
152
  put<T extends ResourceErrorDocument>(doc: StructuredErrorDocument<T>): ResourceErrorDocument;
185
153
  put<T extends ResourceMetaDocument>(doc: StructuredDataDocument<T>): ResourceMetaDocument;
186
- /** @internal */
187
- _putDocument<T extends ResourceErrorDocument>(doc: StructuredErrorDocument<T>, data: undefined, included: undefined): ResourceErrorDocument;
188
- _putDocument<T extends ResourceMetaDocument>(doc: StructuredDataDocument<T>, data: undefined, included: undefined): ResourceMetaDocument;
189
- _putDocument<T extends SingleResourceDocument>(doc: StructuredDataDocument<T>, data: StableExistingRecordIdentifier | null, included: StableExistingRecordIdentifier[] | undefined): SingleResourceDataDocument;
190
- _putDocument<T extends CollectionResourceDocument>(doc: StructuredDataDocument<T>, data: StableExistingRecordIdentifier[], included: StableExistingRecordIdentifier[] | undefined): CollectionResourceDataDocument;
191
154
  /**
192
155
  * Update the "remote" or "canonical" (persisted) state of the Cache
193
156
  * by merging new information into the existing state.
@@ -234,16 +197,16 @@ export declare class JSONAPICache implements Cache {
234
197
  * @category Cache Management
235
198
  * @public
236
199
  */
237
- peek(identifier: StableRecordIdentifier): ResourceObject | null;
238
- peek(identifier: StableDocumentIdentifier): ResourceDocument | null;
200
+ peek(identifier: ResourceKey): ResourceObject | null;
201
+ peek(identifier: RequestKey): ResourceDocument | null;
239
202
  /**
240
203
  * Peek the remote resource data from the Cache.
241
204
  *
242
205
  * @category Cache Management
243
206
  * @public
244
207
  */
245
- peekRemoteState(identifier: StableRecordIdentifier): ResourceObject | null;
246
- peekRemoteState(identifier: StableDocumentIdentifier): ResourceDocument | null;
208
+ peekRemoteState(identifier: ResourceKey): ResourceObject | null;
209
+ peekRemoteState(identifier: RequestKey): ResourceDocument | null;
247
210
  /**
248
211
  * Peek the Cache for the existing request data associated with
249
212
  * a cacheable request.
@@ -255,7 +218,7 @@ export declare class JSONAPICache implements Cache {
255
218
  * @category Cache Management
256
219
  * @public
257
220
  */
258
- peekRequest(identifier: StableDocumentIdentifier): StructuredDocument<ResourceDocument> | null;
221
+ peekRequest(identifier: RequestKey): StructuredDocument<ResourceDocument> | null;
259
222
  /**
260
223
  * Push resource data from a remote source into the cache for this identifier
261
224
  *
@@ -263,10 +226,7 @@ export declare class JSONAPICache implements Cache {
263
226
  * @public
264
227
  * @return if `calculateChanges` is true then calculated key changes should be returned
265
228
  */
266
- upsert(identifier: StableRecordIdentifier, data: ExistingResourceObject, calculateChanges?: boolean): void | string[];
267
- ////////// ============= //////////
268
- ////////// Cache Forking //////////
269
- ////////// ============= //////////
229
+ upsert(identifier: ResourceKey, data: ExistingResourceObject, calculateChanges?: boolean): void | string[];
270
230
  /**
271
231
  * Create a fork of the cache from the current state.
272
232
  *
@@ -275,7 +235,7 @@ export declare class JSONAPICache implements Cache {
275
235
  * utilize this method to fork the cache.
276
236
  *
277
237
  * @category Cache Forking
278
- * @internal
238
+ * @private
279
239
  */
280
240
  fork(): Promise<Cache>;
281
241
  /**
@@ -286,7 +246,7 @@ export declare class JSONAPICache implements Cache {
286
246
  * utilize this method to merge the caches.
287
247
  *
288
248
  * @category Cache Forking
289
- * @internal
249
+ * @private
290
250
  */
291
251
  merge(_cache: Cache): Promise<void>;
292
252
  /**
@@ -313,26 +273,23 @@ export declare class JSONAPICache implements Cache {
313
273
  *
314
274
  * ```ts
315
275
  * interface Change {
316
- * identifier: StableRecordIdentifier | StableDocumentIdentifier;
276
+ * identifier: ResourceKey | RequestKey;
317
277
  * op: 'upsert' | 'remove';
318
278
  * patch?: unknown;
319
279
  * }
320
280
  * ```
321
281
  *
322
282
  * @category Cache Forking
323
- * @internal
283
+ * @private
324
284
  */
325
285
  diff(): Promise<Change[]>;
326
- ////////// =========== //////////
327
- ////////// SSR Support //////////
328
- ////////// =========== //////////
329
286
  /**
330
287
  * Serialize the entire contents of the Cache into a Stream
331
288
  * which may be fed back into a new instance of the same Cache
332
289
  * via `cache.hydrate`.
333
290
  *
334
291
  * @category SSR Support
335
- * @internal
292
+ * @private
336
293
  */
337
294
  dump(): Promise<ReadableStream<unknown>>;
338
295
  /**
@@ -348,12 +305,9 @@ export declare class JSONAPICache implements Cache {
348
305
  * via data-only SSR modes.
349
306
  *
350
307
  * @category SSR Support
351
- * @internal
308
+ * @private
352
309
  */
353
310
  hydrate(stream: ReadableStream<unknown>): Promise<void>;
354
- ////////// ================== //////////
355
- ////////// Resource Lifecycle //////////
356
- ////////// ================== //////////
357
311
  /**
358
312
  * [LIFECYCLE] Signal to the cache that a new record has been instantiated on the client
359
313
  *
@@ -363,7 +317,7 @@ export declare class JSONAPICache implements Cache {
363
317
  * @category Resource Lifecycle
364
318
  * @public
365
319
  */
366
- clientDidCreate(identifier: StableRecordIdentifier, options?: Record<string, Value>): Record<string, unknown>;
320
+ clientDidCreate(identifier: ResourceKey, options?: Record<string, Value>): Record<string, unknown>;
367
321
  /**
368
322
  * [LIFECYCLE] Signals to the cache that a resource
369
323
  * will be part of a save transaction.
@@ -371,7 +325,7 @@ export declare class JSONAPICache implements Cache {
371
325
  * @category Resource Lifecycle
372
326
  * @public
373
327
  */
374
- willCommit(identifier: StableRecordIdentifier): void;
328
+ willCommit(identifier: ResourceKey, _context: RequestContext | null): void;
375
329
  /**
376
330
  * [LIFECYCLE] Signals to the cache that a resource
377
331
  * was successfully updated as part of a save transaction.
@@ -379,7 +333,7 @@ export declare class JSONAPICache implements Cache {
379
333
  * @category Resource Lifecycle
380
334
  * @public
381
335
  */
382
- didCommit(committedIdentifier: StableRecordIdentifier, result: StructuredDataDocument<SingleResourceDocument>): SingleResourceDataDocument;
336
+ didCommit(committedIdentifier: ResourceKey, result: StructuredDataDocument<SingleResourceDocument> | null): SingleResourceDataDocument;
383
337
  /**
384
338
  * [LIFECYCLE] Signals to the cache that a resource
385
339
  * was update via a save transaction failed.
@@ -387,7 +341,7 @@ export declare class JSONAPICache implements Cache {
387
341
  * @category Resource Lifecycle
388
342
  * @public
389
343
  */
390
- commitWasRejected(identifier: StableRecordIdentifier, errors?: ApiError[]): void;
344
+ commitWasRejected(identifier: ResourceKey, errors?: ApiError[]): void;
391
345
  /**
392
346
  * [LIFECYCLE] Signals to the cache that all data for a resource
393
347
  * should be cleared.
@@ -397,10 +351,7 @@ export declare class JSONAPICache implements Cache {
397
351
  * @category Resource Lifecycle
398
352
  * @public
399
353
  */
400
- unloadRecord(identifier: StableRecordIdentifier): void;
401
- ////////// ============= //////////
402
- ////////// Resource Data //////////
403
- ////////// ============= //////////
354
+ unloadRecord(identifier: ResourceKey): void;
404
355
  /**
405
356
  * Retrieve the data for an attribute from the cache
406
357
  * with local mutations applied.
@@ -408,14 +359,14 @@ export declare class JSONAPICache implements Cache {
408
359
  * @category Resource Data
409
360
  * @public
410
361
  */
411
- getAttr(identifier: StableRecordIdentifier, attr: string | string[]): Value | undefined;
362
+ getAttr(identifier: ResourceKey, attr: string | string[]): Value | undefined;
412
363
  /**
413
364
  * Retrieve the remote data for an attribute from the cache
414
365
  *
415
366
  * @category Resource Data
416
367
  * @public
417
368
  */
418
- getRemoteAttr(identifier: StableRecordIdentifier, attr: string | string[]): Value | undefined;
369
+ getRemoteAttr(identifier: ResourceKey, attr: string | string[]): Value | undefined;
419
370
  /**
420
371
  * Mutate the data for an attribute in the cache
421
372
  *
@@ -424,7 +375,7 @@ export declare class JSONAPICache implements Cache {
424
375
  * @category Resource Data
425
376
  * @public
426
377
  */
427
- setAttr(identifier: StableRecordIdentifier, attr: string | string[], value: Value): void;
378
+ setAttr(identifier: ResourceKey, attr: string | string[], value: Value): void;
428
379
  /**
429
380
  * Query the cache for the changed attributes of a resource.
430
381
  *
@@ -432,14 +383,14 @@ export declare class JSONAPICache implements Cache {
432
383
  * @public
433
384
  * @return `{ '<field>': ['<old>', '<new>'] }`
434
385
  */
435
- changedAttrs(identifier: StableRecordIdentifier): ChangedAttributesHash;
386
+ changedAttrs(identifier: ResourceKey): ChangedAttributesHash;
436
387
  /**
437
388
  * Query the cache for whether any mutated attributes exist
438
389
  *
439
390
  * @category Resource Data
440
391
  * @public
441
392
  */
442
- hasChangedAttrs(identifier: StableRecordIdentifier): boolean;
393
+ hasChangedAttrs(identifier: ResourceKey): boolean;
443
394
  /**
444
395
  * Tell the cache to discard any uncommitted mutations to attributes
445
396
  *
@@ -449,7 +400,7 @@ export declare class JSONAPICache implements Cache {
449
400
  * @public
450
401
  * @return the names of fields that were restored
451
402
  */
452
- rollbackAttrs(identifier: StableRecordIdentifier): string[];
403
+ rollbackAttrs(identifier: ResourceKey): string[];
453
404
  /**
454
405
  * Query the cache for the changes to relationships of a resource.
455
406
  *
@@ -459,30 +410,30 @@ export declare class JSONAPICache implements Cache {
459
410
  * type RelationshipDiff =
460
411
  | {
461
412
  kind: 'collection';
462
- remoteState: StableRecordIdentifier[];
463
- additions: Set<StableRecordIdentifier>;
464
- removals: Set<StableRecordIdentifier>;
465
- localState: StableRecordIdentifier[];
413
+ remoteState: ResourceKey[];
414
+ additions: Set<ResourceKey>;
415
+ removals: Set<ResourceKey>;
416
+ localState: ResourceKey[];
466
417
  reordered: boolean;
467
418
  }
468
419
  | {
469
420
  kind: 'resource';
470
- remoteState: StableRecordIdentifier | null;
471
- localState: StableRecordIdentifier | null;
421
+ remoteState: ResourceKey | null;
422
+ localState: ResourceKey | null;
472
423
  };
473
424
  ```
474
425
  *
475
426
  * @category Resource Data
476
427
  * @public
477
428
  */
478
- changedRelationships(identifier: StableRecordIdentifier): Map<string, RelationshipDiff>;
429
+ changedRelationships(identifier: ResourceKey): Map<string, RelationshipDiff>;
479
430
  /**
480
431
  * Query the cache for whether any mutated relationships exist
481
432
  *
482
433
  * @category Resource Data
483
434
  * @public
484
435
  */
485
- hasChangedRelationships(identifier: StableRecordIdentifier): boolean;
436
+ hasChangedRelationships(identifier: ResourceKey): boolean;
486
437
  /**
487
438
  * Tell the cache to discard any uncommitted mutations to relationships.
488
439
  *
@@ -494,7 +445,7 @@ export declare class JSONAPICache implements Cache {
494
445
  * @public
495
446
  * @return the names of relationships that were restored
496
447
  */
497
- rollbackRelationships(identifier: StableRecordIdentifier): string[];
448
+ rollbackRelationships(identifier: ResourceKey): string[];
498
449
  /**
499
450
  * Query the cache for the current state of a relationship property
500
451
  *
@@ -502,7 +453,7 @@ export declare class JSONAPICache implements Cache {
502
453
  * @public
503
454
  * @return resource relationship object
504
455
  */
505
- getRelationship(identifier: StableRecordIdentifier, field: string): ResourceRelationship | CollectionRelationship;
456
+ getRelationship(identifier: ResourceKey, field: string): ResourceRelationship | CollectionRelationship;
506
457
  /**
507
458
  * Query the cache for the remote state of a relationship property
508
459
  *
@@ -510,10 +461,7 @@ export declare class JSONAPICache implements Cache {
510
461
  * @public
511
462
  * @return resource relationship object
512
463
  */
513
- getRemoteRelationship(identifier: StableRecordIdentifier, field: string): ResourceRelationship | CollectionRelationship;
514
- ////////// ============== //////////
515
- ////////// Resource State //////////
516
- ////////// ============== //////////
464
+ getRemoteRelationship(identifier: ResourceKey, field: string): ResourceRelationship | CollectionRelationship;
517
465
  /**
518
466
  * Update the cache state for the given resource to be marked
519
467
  * as locally deleted, or remove such a mark.
@@ -523,21 +471,21 @@ export declare class JSONAPICache implements Cache {
523
471
  * @category Resource State
524
472
  * @public
525
473
  */
526
- setIsDeleted(identifier: StableRecordIdentifier, isDeleted: boolean): void;
474
+ setIsDeleted(identifier: ResourceKey, isDeleted: boolean): void;
527
475
  /**
528
476
  * Query the cache for any validation errors applicable to the given resource.
529
477
  *
530
478
  * @category Resource State
531
479
  * @public
532
480
  */
533
- getErrors(identifier: StableRecordIdentifier): ApiError[];
481
+ getErrors(identifier: ResourceKey): ApiError[];
534
482
  /**
535
483
  * Query the cache for whether a given resource has any available data
536
484
  *
537
485
  * @category Resource State
538
486
  * @public
539
487
  */
540
- isEmpty(identifier: StableRecordIdentifier): boolean;
488
+ isEmpty(identifier: ResourceKey): boolean;
541
489
  /**
542
490
  * Query the cache for whether a given resource was created locally and not
543
491
  * yet persisted.
@@ -545,7 +493,7 @@ export declare class JSONAPICache implements Cache {
545
493
  * @category Resource State
546
494
  * @public
547
495
  */
548
- isNew(identifier: StableRecordIdentifier): boolean;
496
+ isNew(identifier: ResourceKey): boolean;
549
497
  /**
550
498
  * Query the cache for whether a given resource is marked as deleted (but not
551
499
  * necessarily persisted yet).
@@ -553,7 +501,7 @@ export declare class JSONAPICache implements Cache {
553
501
  * @category Resource State
554
502
  * @public
555
503
  */
556
- isDeleted(identifier: StableRecordIdentifier): boolean;
504
+ isDeleted(identifier: ResourceKey): boolean;
557
505
  /**
558
506
  * Query the cache for whether a given resource has been deleted and that deletion
559
507
  * has also been persisted.
@@ -561,26 +509,5 @@ export declare class JSONAPICache implements Cache {
561
509
  * @category Resource State
562
510
  * @public
563
511
  */
564
- isDeletionCommitted(identifier: StableRecordIdentifier): boolean;
565
- /**
566
- * Private method used to populate an entry for the identifier
567
- *
568
- * @internal
569
- */
570
- _createCache(identifier: StableRecordIdentifier): CachedResource;
571
- /**
572
- * Peek whether we have cached resource data matching the identifier
573
- * without asserting if the resource data is missing.
574
- *
575
- * @internal
576
- */
577
- __safePeek(identifier: StableRecordIdentifier, allowDestroyed: boolean): CachedResource | undefined;
578
- /**
579
- * Peek whether we have cached resource data matching the identifier
580
- * Asserts if the resource data is missing.
581
- *
582
- * @internal
583
- */
584
- __peek(identifier: StableRecordIdentifier, allowDestroyed: boolean): CachedResource;
512
+ isDeletionCommitted(identifier: ResourceKey): boolean;
585
513
  }
586
- export {};
@@ -1,12 +1 @@
1
- import type { ResourceDocument } from "@warp-drive-mirror/core/types/spec/document";
2
- import { type Reporter } from "../utils.js";
3
- /**
4
- * Reports issues which violate the JSON:API spec for top-level members.
5
- *
6
- * Version: 1.1
7
- * Section: 7.1
8
- * Link: https://jsonapi.org/format/#document-top-level
9
- *
10
- * @internal
11
- */
12
- export declare function validateTopLevelDocumentMembers(reporter: Reporter, doc: ResourceDocument): void;
1
+ export {};
@@ -1,13 +1 @@
1
- import type { ResourceDocument } from "@warp-drive-mirror/core/types/spec/document";
2
- import { type Reporter } from "../utils.js";
3
- /**
4
- * Validates the resource objects in either the `data` or `included` members of
5
- * JSON:API document.
6
- *
7
- * Version: 1.1
8
- * Section: 7.2
9
- * Link: https://jsonapi.org/format/#document-resource-objects
10
- *
11
- * @internal
12
- */
13
- export declare function validateDocumentResources(reporter: Reporter, doc: ResourceDocument): void;
1
+ export {};
@@ -1,23 +1 @@
1
- import type { ResourceDocument } from "@warp-drive-mirror/core/types/spec/document";
2
- import type { CollectionResourceRelationship, ResourceObject, SingleResourceRelationship } from "@warp-drive-mirror/core/types/spec/json-api-raw";
3
- import { type PathLike, type Reporter } from "../utils.js";
4
- /**
5
- * Validates the links object in a top-level JSON API document or resource object
6
- *
7
- * Version: 1.1
8
- *
9
- * Section: 7.1 Top Level
10
- * Link: https://jsonapi.org/format/#document-top-level
11
- *
12
- * Section: 7.2.3 Resource Objects
13
- * Link: https://jsonapi.org/format/#document-resource-object-links
14
- *
15
- * Section: 7.2.2.2 Resource Relationships
16
- * Link: https://jsonapi.org/format/#document-resource-object-relationships
17
- *
18
- * Section: 7.6 Document Links
19
- * Link: https://jsonapi.org/format/#document-links
20
- *
21
- * @internal
22
- */
23
- export declare function validateLinks(reporter: Reporter, doc: ResourceDocument | ResourceObject | SingleResourceRelationship | CollectionResourceRelationship, type: "collection-document" | "resource-document" | "resource" | "resource-relationship" | "collection-relationship", path?: PathLike): void;
1
+ export {};
@@ -33,8 +33,6 @@ export declare class Reporter {
33
33
  errors: ErrorReport[];
34
34
  ast: ReturnType<typeof jsonToAst>;
35
35
  jsonStr: string;
36
- // TODO @runspired make this configurable to consuming apps before
37
- // activating by default
38
36
  strict: {
39
37
  linkage: boolean;
40
38
  unknownType: boolean;
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { graphFor, peekGraph, isBelongsTo } from '@warp-drive-mirror/core/graph/-private';
2
- import { logGroup, isStableIdentifier, isDocumentIdentifier } from '@warp-drive-mirror/core/store/-private';
2
+ import { logGroup, isResourceKey, assertPrivateCapabilities, isRequestKey } from '@warp-drive-mirror/core/store/-private';
3
3
  import Fuse from 'fuse.js';
4
4
  import jsonToAst from 'json-to-ast';
5
5
  import { macroCondition, getGlobalConfig } from '@embroider/macros';
@@ -793,7 +793,7 @@ function validateResourceAttributes(reporter, type, resource, path) {
793
793
  const field = getRemoteField(schema, key);
794
794
  const actualField = schema.get(key);
795
795
  if (!field && actualField) {
796
- reporter.warn([...path, key], `Expected the ${actualField.kind} field to not have its own resource data. Likely this field should either not be returned in this payload or the field definition should be updated in the schema.`);
796
+ reporter.warn([...path, key], `Expected the ${actualField.kind} field "${key}" to not have its own data in the ResourceObject's attributes. Likely this field should either not be returned in this payload or the field definition should be updated in the schema.`);
797
797
  } else if (!field) {
798
798
  if (key.includes(':')) {
799
799
  const extensionName = key.split(':')[0];
@@ -827,7 +827,7 @@ function validateResourceRelationships(reporter, type, resource, path) {
827
827
  const field = getRemoteField(schema, key);
828
828
  const actualField = schema.get(key);
829
829
  if (!field && actualField) {
830
- reporter.warn([...path, key], `Expected the ${actualField.kind} field to not have its own resource data. Likely this field should either not be returned in this payload or the field definition should be updated in the schema.`);
830
+ reporter.warn([...path, key], `Expected the ${actualField.kind} field "${key}" to not have its own data in the ResourceObject's relationships. Likely this field should either not be returned in this payload or the field definition should be updated in the schema.`);
831
831
  } else if (!field) {
832
832
  if (key.includes(':')) {
833
833
  const extensionName = key.split(':')[0];
@@ -927,7 +927,6 @@ function validateResourceDocument(reporter, doc) {
927
927
  function isImplicit(relationship) {
928
928
  return relationship.definition.isImplicit;
929
929
  }
930
- function upgradeCapabilities(obj) {}
931
930
  const EMPTY_ITERATOR = {
932
931
  iterator() {
933
932
  return {
@@ -1129,7 +1128,7 @@ class JSONAPICache {
1129
1128
  const included = jsonApiDoc.included;
1130
1129
  let i, length;
1131
1130
  const {
1132
- identifierCache
1131
+ cacheKeyManager
1133
1132
  } = this._capabilities;
1134
1133
  if (macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG)) {
1135
1134
  validateDocumentFields(this._capabilities.schema, jsonApiDoc);
@@ -1181,26 +1180,33 @@ class JSONAPICache {
1181
1180
  }
1182
1181
  if (included) {
1183
1182
  for (i = 0, length = included.length; i < length; i++) {
1184
- included[i] = putOne(this, identifierCache, included[i]);
1183
+ included[i] = putOne(this, cacheKeyManager, included[i]);
1185
1184
  }
1186
1185
  }
1187
1186
  if (Array.isArray(jsonApiDoc.data)) {
1188
1187
  length = jsonApiDoc.data.length;
1189
1188
  const identifiers = [];
1190
1189
  for (i = 0; i < length; i++) {
1191
- identifiers.push(putOne(this, identifierCache, jsonApiDoc.data[i]));
1190
+ identifiers.push(putOne(this, cacheKeyManager, jsonApiDoc.data[i]));
1192
1191
  }
1193
1192
  return this._putDocument(doc, identifiers, included);
1194
1193
  }
1195
1194
  if (jsonApiDoc.data === null) {
1196
1195
  return this._putDocument(doc, null, included);
1197
1196
  }
1198
- const identifier = putOne(this, identifierCache, jsonApiDoc.data);
1197
+ const identifier = putOne(this, cacheKeyManager, jsonApiDoc.data);
1199
1198
  return this._putDocument(doc, identifier, included);
1200
1199
  }
1201
1200
 
1202
1201
  /** @internal */
1203
1202
 
1203
+ /** @internal */
1204
+
1205
+ /** @internal */
1206
+
1207
+ /** @internal */
1208
+
1209
+ /** @internal */
1204
1210
  _putDocument(doc, data, included) {
1205
1211
  // @ts-expect-error narrowing within is just horrible in TS :/
1206
1212
  const resourceDocument = isErrorDocument(doc) ? fromStructuredError(doc) : fromBaseDocument(doc);
@@ -1221,7 +1227,7 @@ class JSONAPICache {
1221
1227
  resourceDocument.included = included;
1222
1228
  }
1223
1229
  const request = doc.request;
1224
- const identifier = request ? this._capabilities.identifierCache.getOrCreateDocumentIdentifier(request) : null;
1230
+ const identifier = request ? this._capabilities.cacheKeyManager.getOrCreateDocumentIdentifier(request) : null;
1225
1231
  if (identifier) {
1226
1232
  resourceDocument.lid = identifier.lid;
1227
1233
 
@@ -1243,7 +1249,7 @@ class JSONAPICache {
1243
1249
  if (!test) {
1244
1250
  throw new Error(`Expected a parent identifier for a findHasMany request`);
1245
1251
  }
1246
- })(parentIdentifier && isStableIdentifier(parentIdentifier)) : {};
1252
+ })(parentIdentifier && isResourceKey(parentIdentifier)) : {};
1247
1253
  if (parentField && parentIdentifier) {
1248
1254
  this.__graph.push({
1249
1255
  op: 'updateRelationship',
@@ -1271,7 +1277,7 @@ class JSONAPICache {
1271
1277
  logGroup('cache', 'patch', '<BATCH>', String(op.length) + ' operations', '', '');
1272
1278
  }
1273
1279
  }
1274
- upgradeCapabilities(this._capabilities);
1280
+ assertPrivateCapabilities(this._capabilities);
1275
1281
  this._capabilities._store._join(() => {
1276
1282
  for (const operation of op) {
1277
1283
  patchCache(this, operation);
@@ -1349,7 +1355,7 @@ class JSONAPICache {
1349
1355
  */
1350
1356
 
1351
1357
  peek(identifier) {
1352
- if ('type' in identifier) {
1358
+ if (isResourceKey(identifier)) {
1353
1359
  const peeked = this.__safePeek(identifier, false);
1354
1360
  if (!peeked) {
1355
1361
  return null;
@@ -1372,13 +1378,10 @@ class JSONAPICache {
1372
1378
  }
1373
1379
  });
1374
1380
  }
1375
- upgradeCapabilities(this._capabilities);
1381
+ assertPrivateCapabilities(this._capabilities);
1376
1382
  const store = this._capabilities._store;
1377
- const attrs = this._capabilities.schema.fields(identifier);
1383
+ const attrs = getCacheFields(this, identifier);
1378
1384
  attrs.forEach((attr, key) => {
1379
- if (attr.kind === 'alias') {
1380
- return;
1381
- }
1382
1385
  if (key in attributes && attributes[key] !== undefined) {
1383
1386
  return;
1384
1387
  }
@@ -1410,7 +1413,7 @@ class JSONAPICache {
1410
1413
  */
1411
1414
 
1412
1415
  peekRemoteState(identifier) {
1413
- if ('type' in identifier) {
1416
+ if (isResourceKey(identifier)) {
1414
1417
  const peeked = this.__safePeek(identifier, false);
1415
1418
  if (!peeked) {
1416
1419
  return null;
@@ -1433,9 +1436,9 @@ class JSONAPICache {
1433
1436
  }
1434
1437
  });
1435
1438
  }
1436
- upgradeCapabilities(this._capabilities);
1439
+ assertPrivateCapabilities(this._capabilities);
1437
1440
  const store = this._capabilities._store;
1438
- const attrs = this._capabilities.schema.fields(identifier);
1441
+ const attrs = getCacheFields(this, identifier);
1439
1442
  attrs.forEach((attr, key) => {
1440
1443
  if (key in attributes && attributes[key] !== undefined) {
1441
1444
  return;
@@ -1483,7 +1486,7 @@ class JSONAPICache {
1483
1486
  * @return if `calculateChanges` is true then calculated key changes should be returned
1484
1487
  */
1485
1488
  upsert(identifier, data, calculateChanges) {
1486
- upgradeCapabilities(this._capabilities);
1489
+ assertPrivateCapabilities(this._capabilities);
1487
1490
  const store = this._capabilities._store;
1488
1491
  if (!store._cbs) {
1489
1492
  let result = undefined;
@@ -1507,7 +1510,7 @@ class JSONAPICache {
1507
1510
  * utilize this method to fork the cache.
1508
1511
  *
1509
1512
  * @category Cache Forking
1510
- * @internal
1513
+ * @private
1511
1514
  */
1512
1515
  fork() {
1513
1516
  throw new Error(`Not Implemented`);
@@ -1521,7 +1524,7 @@ class JSONAPICache {
1521
1524
  * utilize this method to merge the caches.
1522
1525
  *
1523
1526
  * @category Cache Forking
1524
- * @internal
1527
+ * @private
1525
1528
  */
1526
1529
  merge(_cache) {
1527
1530
  throw new Error(`Not Implemented`);
@@ -1551,14 +1554,14 @@ class JSONAPICache {
1551
1554
  *
1552
1555
  * ```ts
1553
1556
  * interface Change {
1554
- * identifier: StableRecordIdentifier | StableDocumentIdentifier;
1557
+ * identifier: ResourceKey | RequestKey;
1555
1558
  * op: 'upsert' | 'remove';
1556
1559
  * patch?: unknown;
1557
1560
  * }
1558
1561
  * ```
1559
1562
  *
1560
1563
  * @category Cache Forking
1561
- * @internal
1564
+ * @private
1562
1565
  */
1563
1566
  diff() {
1564
1567
  throw new Error(`Not Implemented`);
@@ -1574,7 +1577,7 @@ class JSONAPICache {
1574
1577
  * via `cache.hydrate`.
1575
1578
  *
1576
1579
  * @category SSR Support
1577
- * @internal
1580
+ * @private
1578
1581
  */
1579
1582
  dump() {
1580
1583
  throw new Error(`Not Implemented`);
@@ -1593,7 +1596,7 @@ class JSONAPICache {
1593
1596
  * via data-only SSR modes.
1594
1597
  *
1595
1598
  * @category SSR Support
1596
- * @internal
1599
+ * @private
1597
1600
  */
1598
1601
  hydrate(stream) {
1599
1602
  throw new Error('Not Implemented');
@@ -1629,8 +1632,7 @@ class JSONAPICache {
1629
1632
  cached.isNew = true;
1630
1633
  const createOptions = {};
1631
1634
  if (options !== undefined) {
1632
- const storeWrapper = this._capabilities;
1633
- const fields = storeWrapper.schema.fields(identifier);
1635
+ const fields = getCacheFields(this, identifier);
1634
1636
  const graph = this.__graph;
1635
1637
  const propertyNames = Object.keys(options);
1636
1638
  for (let i = 0; i < propertyNames.length; i++) {
@@ -1686,7 +1688,7 @@ class JSONAPICache {
1686
1688
  * @category Resource Lifecycle
1687
1689
  * @public
1688
1690
  */
1689
- willCommit(identifier) {
1691
+ willCommit(identifier, _context) {
1690
1692
  const cached = this.__peek(identifier, false);
1691
1693
 
1692
1694
  /*
@@ -1720,7 +1722,7 @@ class JSONAPICache {
1720
1722
  if (macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG)) {
1721
1723
  if (macroCondition(!getGlobalConfig().WarpDriveMirror.deprecations.DEPRECATE_RELATIONSHIP_REMOTE_UPDATE_CLEARING_LOCAL_STATE)) {
1722
1724
  // save off info about saved relationships
1723
- const fields = this._capabilities.schema.fields(identifier);
1725
+ const fields = getCacheFields(this, identifier);
1724
1726
  fields.forEach((schema, name) => {
1725
1727
  if (schema.kind === 'belongsTo') {
1726
1728
  if (this.__graph._isDirty(identifier, name)) {
@@ -1742,8 +1744,8 @@ class JSONAPICache {
1742
1744
  * @public
1743
1745
  */
1744
1746
  didCommit(committedIdentifier, result) {
1745
- const payload = result.content;
1746
- const operation = result.request.op;
1747
+ const payload = result ? result.content : null;
1748
+ const operation = result ? result.request.op : null;
1747
1749
  const data = payload && payload.data;
1748
1750
  if (macroCondition(getGlobalConfig().WarpDriveMirror.activeLogging.LOG_CACHE)) {
1749
1751
  if (getGlobalConfig().WarpDriveMirror.debug.LOG_CACHE || globalThis.getWarpDriveRuntimeConfig().debug.LOG_CACHE) {
@@ -1765,10 +1767,10 @@ class JSONAPICache {
1765
1767
  })(committedIdentifier.id) : {};
1766
1768
  }
1767
1769
  const {
1768
- identifierCache
1770
+ cacheKeyManager
1769
1771
  } = this._capabilities;
1770
1772
  const existingId = committedIdentifier.id;
1771
- const identifier = operation !== 'deleteRecord' && data ? identifierCache.updateRecordIdentifier(committedIdentifier, data) : committedIdentifier;
1773
+ const identifier = operation !== 'deleteRecord' && data ? cacheKeyManager.updateRecordIdentifier(committedIdentifier, data) : committedIdentifier;
1772
1774
  const cached = this.__peek(identifier, false);
1773
1775
  if (cached.isDeleted) {
1774
1776
  this.__graph.push({
@@ -1790,7 +1792,7 @@ class JSONAPICache {
1790
1792
  throw error;
1791
1793
  }
1792
1794
  }
1793
- const fields = this._capabilities.schema.fields(identifier);
1795
+ const fields = getCacheFields(this, identifier);
1794
1796
  cached.isNew = false;
1795
1797
  let newCanonicalAttributes;
1796
1798
  if (data) {
@@ -1818,7 +1820,7 @@ class JSONAPICache {
1818
1820
  if (!inFlightData || !('data' in inFlightData)) {
1819
1821
  return;
1820
1822
  }
1821
- const actualData = relationshipData ? this._capabilities.identifierCache.getOrCreateRecordIdentifier(relationshipData) : null;
1823
+ const actualData = relationshipData ? this._capabilities.cacheKeyManager.getOrCreateRecordIdentifier(relationshipData) : null;
1822
1824
  macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
1823
1825
  if (!test) {
1824
1826
  throw new Error(`Expected the resource relationship '<${identifier.type}>.${name}' on ${identifier.lid} to be saved as ${inFlightData.data ? inFlightData.data.lid : '<null>'} but it was saved as ${actualData ? actualData.lid : '<null>'}`);
@@ -1847,7 +1849,7 @@ class JSONAPICache {
1847
1849
  const included = payload && payload.included;
1848
1850
  if (included) {
1849
1851
  for (let i = 0, length = included.length; i < length; i++) {
1850
- putOne(this, identifierCache, included[i]);
1852
+ putOne(this, cacheKeyManager, included[i]);
1851
1853
  }
1852
1854
  }
1853
1855
  return {
@@ -1997,8 +1999,8 @@ class JSONAPICache {
1997
1999
  } else if (cached.defaultAttrs && attribute in cached.defaultAttrs) {
1998
2000
  return cached.defaultAttrs[attribute];
1999
2001
  } else {
2000
- const attrSchema = this._capabilities.schema.fields(identifier).get(attribute);
2001
- upgradeCapabilities(this._capabilities);
2002
+ const attrSchema = getCacheFields(this, identifier).get(attribute);
2003
+ assertPrivateCapabilities(this._capabilities);
2002
2004
  const defaultValue = getDefaultValue(attrSchema, identifier, this._capabilities._store);
2003
2005
  if (schemaHasLegacyDefaultValueFn(attrSchema)) {
2004
2006
  cached.defaultAttrs = cached.defaultAttrs || Object.create(null);
@@ -2064,8 +2066,8 @@ class JSONAPICache {
2064
2066
  } else if (cached.defaultAttrs && attribute in cached.defaultAttrs) {
2065
2067
  return cached.defaultAttrs[attribute];
2066
2068
  } else {
2067
- const attrSchema = this._capabilities.schema.fields(identifier).get(attribute);
2068
- upgradeCapabilities(this._capabilities);
2069
+ const attrSchema = getCacheFields(this, identifier).get(attribute);
2070
+ assertPrivateCapabilities(this._capabilities);
2069
2071
  const defaultValue = getDefaultValue(attrSchema, identifier, this._capabilities._store);
2070
2072
  if (schemaHasLegacyDefaultValueFn(attrSchema)) {
2071
2073
  cached.defaultAttrs = cached.defaultAttrs || Object.create(null);
@@ -2285,16 +2287,16 @@ class JSONAPICache {
2285
2287
  * type RelationshipDiff =
2286
2288
  | {
2287
2289
  kind: 'collection';
2288
- remoteState: StableRecordIdentifier[];
2289
- additions: Set<StableRecordIdentifier>;
2290
- removals: Set<StableRecordIdentifier>;
2291
- localState: StableRecordIdentifier[];
2290
+ remoteState: ResourceKey[];
2291
+ additions: Set<ResourceKey>;
2292
+ removals: Set<ResourceKey>;
2293
+ localState: ResourceKey[];
2292
2294
  reordered: boolean;
2293
2295
  }
2294
2296
  | {
2295
2297
  kind: 'resource';
2296
- remoteState: StableRecordIdentifier | null;
2297
- localState: StableRecordIdentifier | null;
2298
+ remoteState: ResourceKey | null;
2299
+ localState: ResourceKey | null;
2298
2300
  };
2299
2301
  ```
2300
2302
  *
@@ -2327,7 +2329,7 @@ class JSONAPICache {
2327
2329
  * @return the names of relationships that were restored
2328
2330
  */
2329
2331
  rollbackRelationships(identifier) {
2330
- upgradeCapabilities(this._capabilities);
2332
+ assertPrivateCapabilities(this._capabilities);
2331
2333
  let result;
2332
2334
  this._capabilities._store._join(() => {
2333
2335
  result = this.__graph.rollback(identifier);
@@ -2719,11 +2721,6 @@ function hasLegacyDefaultValueFn(options) {
2719
2721
  return !!options && typeof options.defaultValue === 'function';
2720
2722
  }
2721
2723
  function getDefaultValue(schema, identifier, store) {
2722
- macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
2723
- if (!test) {
2724
- throw new Error(`AliasFields should not be directly accessed from the cache`);
2725
- }
2726
- })(schema?.kind !== 'alias') : {};
2727
2724
  const options = schema?.options;
2728
2725
  if (!schema || !options && !schema.type) {
2729
2726
  return;
@@ -2830,6 +2827,7 @@ function recordIsLoaded(cached, filterDeleted = false) {
2830
2827
  return filterDeleted && cached.isDeletionCommitted ? false : !isEmpty;
2831
2828
  }
2832
2829
  function _isLoading(peeked, capabilities, identifier) {
2830
+ assertPrivateCapabilities(capabilities);
2833
2831
  // TODO refactor things such that the cache is not required to know
2834
2832
  // about isLoading
2835
2833
  const req = capabilities._store.getRequestStateService();
@@ -3055,7 +3053,7 @@ function cacheUpsert(cache, identifier, data, calculateChanges) {
3055
3053
  cache._capabilities.notifyChange(identifier, 'identity', null);
3056
3054
  cache._capabilities.notifyChange(identifier, 'state', null);
3057
3055
  }
3058
- const fields = cache._capabilities.schema.fields(identifier);
3056
+ const fields = getCacheFields(cache, identifier);
3059
3057
 
3060
3058
  // if no cache entry existed, no record exists / property has been accessed
3061
3059
  // and thus we do not need to notify changes to any properties.
@@ -3089,8 +3087,8 @@ function cacheUpsert(cache, identifier, data, calculateChanges) {
3089
3087
  return changedKeys?.size ? Array.from(changedKeys) : undefined;
3090
3088
  }
3091
3089
  function patchCache(Cache, op) {
3092
- const isRecord = isStableIdentifier(op.record);
3093
- const isDocument = !isRecord && isDocumentIdentifier(op.record);
3090
+ const isRecord = isResourceKey(op.record);
3091
+ const isDocument = !isRecord && isRequestKey(op.record);
3094
3092
  macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
3095
3093
  if (!test) {
3096
3094
  throw new Error(`Expected Cache.patch op.record to be a record or document identifier`);
@@ -3124,7 +3122,7 @@ function patchCache(Cache, op) {
3124
3122
  {
3125
3123
  if (isRecord) {
3126
3124
  if ('field' in op) {
3127
- const field = Cache._capabilities.schema.fields(op.record).get(op.field);
3125
+ const field = getCacheFields(Cache, op.record).get(op.field);
3128
3126
  macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG) ? (test => {
3129
3127
  if (!test) {
3130
3128
  throw new Error(`Expected ${op.field} to be a field on ${op.record.type}`);
@@ -3227,5 +3225,13 @@ function patchCache(Cache, op) {
3227
3225
  }
3228
3226
  }
3229
3227
  }
3228
+ function getCacheFields(cache, identifier) {
3229
+ if (cache._capabilities.schema.cacheFields) {
3230
+ return cache._capabilities.schema.cacheFields(identifier);
3231
+ }
3232
+
3233
+ // the model schema service cannot process fields that are not cache fields
3234
+ return cache._capabilities.schema.fields(identifier);
3235
+ }
3230
3236
 
3231
3237
  export { JSONAPICache };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@warp-drive-mirror/json-api",
3
- "version": "5.6.0-beta.1",
3
+ "version": "5.6.0-beta.3",
4
4
  "description": "A {JSON:API} Cache Implementation for WarpDrive",
5
5
  "keywords": [
6
6
  "ember-addon"
@@ -32,24 +32,24 @@
32
32
  }
33
33
  },
34
34
  "peerDependencies": {
35
- "@warp-drive-mirror/core": "5.6.0-beta.1"
35
+ "@warp-drive-mirror/core": "5.6.0-beta.3"
36
36
  },
37
37
  "dependencies": {
38
- "@embroider/macros": "^1.16.12",
38
+ "@embroider/macros": "^1.18.1",
39
39
  "json-to-ast": "2.1.0",
40
40
  "fuse.js": "7.1.0"
41
41
  },
42
42
  "devDependencies": {
43
- "@babel/core": "^7.26.10",
44
- "@babel/plugin-transform-typescript": "^7.27.0",
45
- "@babel/preset-typescript": "^7.27.0",
43
+ "@babel/core": "^7.28.3",
44
+ "@babel/plugin-transform-typescript": "^7.28.0",
45
+ "@babel/preset-typescript": "^7.27.1",
46
46
  "@types/json-to-ast": "^2.1.4",
47
- "@warp-drive/internal-config": "5.6.0-beta.2",
48
- "@warp-drive-mirror/core": "5.6.0-beta.1",
47
+ "@warp-drive/internal-config": "5.6.0-beta.4",
48
+ "@warp-drive-mirror/core": "5.6.0-beta.3",
49
49
  "decorator-transforms": "^2.3.0",
50
- "expect-type": "^1.2.1",
51
- "typescript": "^5.8.3",
52
- "vite": "^7.0.0"
50
+ "expect-type": "^1.2.2",
51
+ "typescript": "^5.9.2",
52
+ "vite": "^7.1.3"
53
53
  },
54
54
  "volta": {
55
55
  "extends": "../../../../../../package.json"