@warp-drive/core 5.9.0-alpha.17 → 5.9.0-alpha.19

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.
Files changed (57) hide show
  1. package/declarations/graph/-private/-state.d.ts +1 -0
  2. package/declarations/index.d.ts +10 -1
  3. package/declarations/reactive/-private/default-mode.d.ts +22 -9
  4. package/declarations/reactive/-private/kind/belongs-to-field.d.ts +3 -0
  5. package/declarations/types/runtime.d.ts +16 -0
  6. package/declarations/types/schema/fields.d.ts +40 -12
  7. package/dist/graph/-private.js +67 -52
  8. package/dist/{index-CFwnjldF.js → index-LI2ckwf9.js} +332 -10
  9. package/dist/index.js +1 -1
  10. package/dist/reactive.js +1 -1
  11. package/dist/store/-private.js +1 -1
  12. package/dist/types/-private.js +1 -1
  13. package/dist/types/runtime.js +20 -1
  14. package/dist/unpkg/dev/graph/-private.js +67 -52
  15. package/dist/unpkg/dev/{index-BZRBBa34.js → index-DU_HLpg-.js} +332 -10
  16. package/dist/unpkg/dev/index.js +1 -1
  17. package/dist/unpkg/dev/reactive.js +1 -1
  18. package/dist/unpkg/dev/store/-private.js +2 -2
  19. package/dist/unpkg/dev/types/-private.js +1 -1
  20. package/dist/unpkg/dev/types/runtime.js +20 -1
  21. package/dist/unpkg/dev-deprecated/graph/-private.js +67 -52
  22. package/dist/unpkg/dev-deprecated/{index-Bu52tQ9I.js → index-BYFUHVPd.js} +332 -10
  23. package/dist/unpkg/dev-deprecated/index.js +1 -1
  24. package/dist/unpkg/dev-deprecated/reactive.js +1 -1
  25. package/dist/unpkg/dev-deprecated/store/-private.js +1 -1
  26. package/dist/unpkg/dev-deprecated/types/-private.js +1 -1
  27. package/dist/unpkg/dev-deprecated/types/runtime.js +20 -1
  28. package/dist/unpkg/prod/{-leaked-BHLmJyaw.js → -leaked-DgjQ5X55.js} +2 -2
  29. package/dist/unpkg/prod/configure.js +1 -1
  30. package/dist/unpkg/prod/graph/-private.js +17 -25
  31. package/dist/unpkg/prod/{schema-BdC3DirM.js → index-C-AhVafS.js} +2383 -73
  32. package/dist/unpkg/prod/index.js +5 -483
  33. package/dist/unpkg/prod/{promise-cache-DIT8Ypjq.js → promise-cache-DUblkX-U.js} +1 -1
  34. package/dist/unpkg/prod/reactive.js +3 -29
  35. package/dist/unpkg/prod/{request-BrJSCG6r.js → request-eb7Zm-oS.js} +1 -1
  36. package/dist/unpkg/prod/request.js +2 -2
  37. package/dist/unpkg/prod/signals/-leaked.js +1 -1
  38. package/dist/unpkg/prod/store/-private.js +2 -3
  39. package/dist/unpkg/prod/types/-private.js +1 -1
  40. package/dist/unpkg/prod/types/runtime.js +20 -1
  41. package/dist/unpkg/prod-deprecated/{-leaked-D_5Yrs5c.js → -leaked-BNVttukY.js} +1 -1
  42. package/dist/unpkg/prod-deprecated/configure.js +1 -1
  43. package/dist/unpkg/prod-deprecated/graph/-private.js +17 -25
  44. package/dist/unpkg/prod-deprecated/{schema-h0nuUTCj.js → index-CplZl2hv.js} +1035 -7
  45. package/dist/unpkg/prod-deprecated/index.js +5 -483
  46. package/dist/unpkg/prod-deprecated/{promise-cache-DIT8Ypjq.js → promise-cache-DUblkX-U.js} +1 -1
  47. package/dist/unpkg/prod-deprecated/reactive.js +2 -3
  48. package/dist/unpkg/prod-deprecated/{request-BrJSCG6r.js → request-eb7Zm-oS.js} +1 -1
  49. package/dist/unpkg/prod-deprecated/request.js +2 -2
  50. package/dist/unpkg/prod-deprecated/signals/-leaked.js +1 -1
  51. package/dist/unpkg/prod-deprecated/store/-private.js +1 -2
  52. package/dist/unpkg/prod-deprecated/types/-private.js +1 -1
  53. package/dist/unpkg/prod-deprecated/types/runtime.js +20 -1
  54. package/package.json +3 -3
  55. package/dist/unpkg/prod/handler-BJogFbfS.js +0 -1619
  56. package/dist/unpkg/prod-deprecated/handler-kGR8zguj.js +0 -334
  57. package/dist/unpkg/prod-deprecated/hooks-wJdveHPi.js +0 -26
@@ -1,4 +1,4 @@
1
- export { C as CacheHandler, F as Fetch, y as RequestManager, S as Store, r as cacheKeyFor, r as recordIdentifierFor, D as setIdentifierForgetMethod, A as setIdentifierGenerationMethod, E as setIdentifierResetMethod, B as setIdentifierUpdateMethod, G as setKeyInfoForResource, s as storeFor, z as useRecommendedStore } from "./index-BZRBBa34.js";
1
+ export { C as CacheHandler, F as Fetch, y as RequestManager, S as Store, r as cacheKeyFor, r as recordIdentifierFor, D as setIdentifierForgetMethod, A as setIdentifierGenerationMethod, E as setIdentifierResetMethod, B as setIdentifierUpdateMethod, G as setKeyInfoForResource, s as storeFor, z as useRecommendedStore } from "./index-DU_HLpg-.js";
2
2
  import "./-private-sql1_mdx.js";
3
3
  import "./-leaked-BohmerbH.js";
4
4
  import './store.js';
@@ -1,3 +1,3 @@
1
- export { q as SchemaService, o as checkout, x as commit, u as fromIdentity, p as instantiateRecord, v as registerDerivations, t as teardownRecord, w as withDefaults } from "./index-BZRBBa34.js";
1
+ export { q as SchemaService, o as checkout, x as commit, u as fromIdentity, p as instantiateRecord, v as registerDerivations, t as teardownRecord, w as withDefaults } from "./index-DU_HLpg-.js";
2
2
  export { a as Checkout } from "./-private-sql1_mdx.js";
3
3
  export { k as createRequestSubscription, m as getPromiseState, l as getRequestState } from "./-leaked-BohmerbH.js";
@@ -1,6 +1,6 @@
1
1
  import '../types/request.js';
2
- import { i as isResourceKey, c as coerceId } from "../index-BZRBBa34.js";
3
- export { C as CacheHandler, R as RecordArrayManager, S as Store, j as StoreMap, _ as _clearCaches, n as _deprecatingNormalize, g as assertPrivateCapabilities, b as assertPrivateStore, k as createLegacyManyArray, e as ensureStringId, f as fastPush, d as isPrivateStore, a as isRequestKey, l as log, m as logGroup, r as recordIdentifierFor, h as setRecordIdentifier, s as storeFor } from "../index-BZRBBa34.js";
2
+ import { i as isResourceKey, c as coerceId } from "../index-DU_HLpg-.js";
3
+ export { C as CacheHandler, R as RecordArrayManager, S as Store, j as StoreMap, _ as _clearCaches, n as _deprecatingNormalize, g as assertPrivateCapabilities, b as assertPrivateStore, k as createLegacyManyArray, e as ensureStringId, f as fastPush, d as isPrivateStore, a as isRequestKey, l as log, m as logGroup, r as recordIdentifierFor, h as setRecordIdentifier, s as storeFor } from "../index-DU_HLpg-.js";
4
4
  function isNonEmptyString(str) {
5
5
  return Boolean(str && typeof str === 'string');
6
6
  }
@@ -1,5 +1,5 @@
1
1
  const name = "@warp-drive/core";
2
- const version = "5.9.0-alpha.17";
2
+ const version = "5.9.0-alpha.19";
3
3
 
4
4
  // in testing mode, we utilize globals to ensure only one copy exists of
5
5
  // these maps, due to bugs in ember-auto-import
@@ -31,4 +31,23 @@ function setLogging(config) {
31
31
  Object.assign(RuntimeConfig.debug, config);
32
32
  storage?.setItem('WarpDriveRuntimeConfig', JSON.stringify(RuntimeConfig));
33
33
  }
34
- export { getRuntimeConfig, setLogging };
34
+
35
+ /**
36
+ * Explicitly declares whether requests may be served by Mirage (or another
37
+ * Pretender-based fetch mock) instead of a native `fetch` implementation.
38
+ *
39
+ * The `Fetch` request handler otherwise infers this via a heuristic (the
40
+ * presence of `window.server.pretender`, or `window.fetch` appearing to be
41
+ * patched), which can be wrong in either direction: some Mirage setups don't
42
+ * expose `window.server`, while some unrelated tools (APM agents, browser
43
+ * extensions) also patch `fetch`. Call this to override that heuristic:
44
+ * `true` to force Mirage-compatible behavior on, `false` to force it off.
45
+ *
46
+ * globalThis.setWarpDriveIsMaybeMirage(true);
47
+ *
48
+ */
49
+ function setIsMaybeMirage(value) {
50
+ RuntimeConfig.mirage = value;
51
+ storage?.setItem('WarpDriveRuntimeConfig', JSON.stringify(RuntimeConfig));
52
+ }
53
+ export { getRuntimeConfig, setIsMaybeMirage, setLogging };
@@ -59,9 +59,14 @@ function assertValidRelationshipPayload(graph, op) {
59
59
  kind
60
60
  } = definition;
61
61
  if (payload.links) {
62
- console.warn(`You pushed a record of type '${type}' with a relationship '${field}' configured as 'async: false'. You've included a link but no primary data, this may be an error in your payload. WarpDrive will treat this relationship as known-to-be-empty.`, isAsync || payload.data === null || !!payload.data || state.hasReceivedData, {
63
- id: 'ds.store.push-link-for-sync-relationship'
64
- });
62
+ // once JSON_API_CACHE_VALIDATION_ERRORS is active, this warning is instead
63
+ // the responsibility of the new document validator (see validateResourceRelationships
64
+ // in warp-drive-packages/json-api/src/-private/validator/1.1/7.2_resource-objects.ts)
65
+ {
66
+ console.warn(`You pushed a record of type '${type}' with a relationship '${field}' configured as 'async: false'. You've included a link but no primary data, this may be an error in your payload. WarpDrive will treat this relationship as known-to-be-empty.`, isAsync || payload.data === null || !!payload.data || state.hasReceivedData, {
67
+ id: 'ds.store.push-link-for-sync-relationship'
68
+ });
69
+ }
65
70
  } else if (payload.data) {
66
71
  if (kind === 'belongsTo') {
67
72
  (test => {
@@ -752,7 +757,7 @@ let assertInheritedSchema;
752
757
  errors.set('type', ` <---- should be '${definition.inverseType}'`);
753
758
  }
754
759
  if (definition.inverseKind !== meta.kind) {
755
- errors.set('type', ` <---- should be '${definition.inverseKind}'`);
760
+ errors.set('kind', ` <---- should be '${definition.inverseKind}'`);
756
761
  }
757
762
  if (definition.inverseIsAsync !== meta.options.async) {
758
763
  errors.set('async', ` <---- should be ${definition.inverseIsAsync}`);
@@ -763,7 +768,12 @@ let assertInheritedSchema;
763
768
  if (definition.key !== meta.options.inverse) {
764
769
  errors.set('inverse', ` <---- should be '${definition.key}'`);
765
770
  }
766
- if (definition.type !== meta.options.as) {
771
+ // `as` is only meaningful when `definition` itself is polymorphic (i.e. it
772
+ // points at an abstract type that `meta` is expected to implement). When
773
+ // `definition` isn't polymorphic, there's no abstract type for `meta` to
774
+ // declare `as` against, so `meta.options.as` is correctly absent - that's
775
+ // not an error to report.
776
+ if (definition.isPolymorphic && definition.type !== meta.options.as) {
767
777
  errors.set('as', ` <---- should be '${definition.type}'`);
768
778
  }
769
779
  return errors;
@@ -802,18 +812,6 @@ let assertInheritedSchema;
802
812
 
803
813
  `;
804
814
  }
805
- function metaFrom(definition) {
806
- return {
807
- name: definition.key,
808
- type: definition.type,
809
- kind: definition.kind,
810
- options: {
811
- async: definition.isAsync,
812
- polymorphic: definition.isPolymorphic,
813
- inverse: definition.inverseKey
814
- }
815
- };
816
- }
817
815
  function inverseMetaFrom(definition) {
818
816
  return {
819
817
  name: definition.inverseKey,
@@ -856,15 +854,18 @@ let assertInheritedSchema;
856
854
  });
857
855
  }
858
856
  assertInheritedSchema = function assertInheritedSchema(definition, type) {
859
- const meta1 = metaFrom(definition);
857
+ // `definition` is the only source of truth we have here - there is no
858
+ // second, independently-declared schema available to diff it against.
859
+ // That means the only thing we can actually verify is internal: does
860
+ // `definition`'s own resolved inverse agree that this relationship is
861
+ // polymorphic? Every other field of `meta2` below (name/type/kind/async/
862
+ // inverse) is derived directly from `definition` itself, so comparing
863
+ // them back to `definition` can never disagree - only the polymorphic
864
+ // flag is independently meaningful, because `definitionWithPolymorphic`
865
+ // asserts what it *should* be rather than mirroring what it already is.
860
866
  const meta2 = inverseMetaFrom(definition);
861
- const errors1 = validateSchema(inverseDefinition(definition), meta1);
862
867
  const errors2 = validateSchema(definitionWithPolymorphic(definition), meta2);
863
- if (errors2.size === 0 && errors1.size > 0) {
864
- throw new Error(`The schema for the relationship '${type}.${definition.key}' is not configured to satisfy '${definition.inverseType}' and thus cannot utilize the '${definition.inverseType}.${definition.key}' relationship to connect with '${definition.type}.${definition.inverseKey}'\n\nIf using this relationship in a polymorphic manner is desired, the relationships schema definition for '${type}' should include:${printSchema(meta1, errors1)}`);
865
- } else if (errors1.size > 0) {
866
- throw new Error(`The schema for the relationship '${type}.${definition.key}' is not configured to satisfy '${definition.inverseType}' and thus cannot utilize the '${definition.inverseType}.${definition.key}' relationship to connect with '${definition.type}.${definition.inverseKey}'\n\nIf using this relationship in a polymorphic manner is desired, the relationships schema definition for '${type}' should include:${printSchema(meta1, errors1)} and the relationships schema definition for '${definition.type}' should include:${printSchema(meta2, errors2)}`);
867
- } else if (errors2.size > 0) {
868
+ if (errors2.size > 0) {
868
869
  throw new Error(`The schema for the relationship '${type}.${definition.key}' satisfies '${definition.inverseType}' but cannot utilize the '${definition.inverseType}.${definition.key}' relationship to connect with '${definition.type}.${definition.inverseKey}' because that relationship is not polymorphic.\n\nIf using this relationship in a polymorphic manner is desired, the relationships schema definition for '${definition.type}' should include:${printSchema(meta2, errors2)}`);
869
870
  }
870
871
  };
@@ -1409,8 +1410,10 @@ function replaceRelatedRecord(graph, op, isRemote = false) {
1409
1410
  if (op.value === existingState) {
1410
1411
  // if we were empty before but now know we are empty this needs to be true
1411
1412
  state.hasReceivedData = true;
1413
+
1412
1414
  // if this is a remote update we still sync
1413
1415
  if (isRemote) {
1416
+ state.hasReceivedRemoteData = true;
1414
1417
  const {
1415
1418
  localState
1416
1419
  } = relationship;
@@ -1441,6 +1444,15 @@ function replaceRelatedRecord(graph, op, isRemote = false) {
1441
1444
  // update value to the new value
1442
1445
  relationship[prop] = op.value;
1443
1446
  state.hasReceivedData = true;
1447
+ /**
1448
+ * Local mutations never give us additional information about
1449
+ * whether the relationship has received *remote* data. This is
1450
+ * what `getRemoteRelationship` relies on to avoid reflecting
1451
+ * local-only edits.
1452
+ */
1453
+ if (isRemote) {
1454
+ state.hasReceivedRemoteData = true;
1455
+ }
1444
1456
  state.isEmpty = op.value === null;
1445
1457
  state.isStale = false;
1446
1458
  state.hasFailedLoadAttempt = false;
@@ -2085,8 +2097,30 @@ function rollbackRelationship(graph, key, field, relationship) {
2085
2097
  }
2086
2098
  }
2087
2099
  function createState() {
2100
+ {
2101
+ {
2102
+ if (getGlobalConfig().WarpDrive.debug.LOG_GRAPH || globalThis.getWarpDriveRuntimeConfig().debug.LOG_GRAPH) {
2103
+ let hasReceivedData = false;
2104
+ return {
2105
+ get hasReceivedData() {
2106
+ return hasReceivedData;
2107
+ },
2108
+ set hasReceivedData(value) {
2109
+ hasReceivedData = value;
2110
+ },
2111
+ hasReceivedRemoteData: false,
2112
+ isEmpty: true,
2113
+ isStale: false,
2114
+ hasFailedLoadAttempt: false,
2115
+ shouldForceReload: false,
2116
+ hasDematerializedInverse: false
2117
+ };
2118
+ }
2119
+ }
2120
+ }
2088
2121
  return {
2089
2122
  hasReceivedData: false,
2123
+ hasReceivedRemoteData: false,
2090
2124
  isEmpty: true,
2091
2125
  isStale: false,
2092
2126
  hasFailedLoadAttempt: false,
@@ -2191,13 +2225,10 @@ function legacyGetResourceRelationshipData(source, getRemoteState) {
2191
2225
  source.accessed = true;
2192
2226
  let data;
2193
2227
  const payload = {};
2194
- if (getRemoteState && source.remoteState) {
2195
- data = source.remoteState;
2196
- } else if (!getRemoteState && source.localState) {
2197
- data = source.localState;
2198
- }
2199
- if ((getRemoteState && source.remoteState === null || source.localState === null) && source.state.hasReceivedData) {
2200
- data = null;
2228
+ if (getRemoteState && (source.remoteState || source.state.hasReceivedRemoteData)) {
2229
+ data = source.remoteState ?? null;
2230
+ } else if (!getRemoteState && (source.localState || source.state.hasReceivedData)) {
2231
+ data = source.localState ?? null;
2201
2232
  }
2202
2233
  if (source.links) {
2203
2234
  payload.links = source.links;
@@ -2411,7 +2442,6 @@ function updateRelationshipOperation(graph, op) {
2411
2442
  })(isHasMany(relationship) || isBelongsTo(relationship));
2412
2443
  const {
2413
2444
  definition,
2414
- state,
2415
2445
  identifier
2416
2446
  } = relationship;
2417
2447
  const {
@@ -2451,23 +2481,6 @@ function updateRelationshipOperation(graph, op) {
2451
2481
  value: payload.data ? graph.store.cacheKeyManager.upgradeIdentifier(payload.data) : null
2452
2482
  }, true);
2453
2483
  }
2454
- } else if (definition.isAsync === false && !state.hasReceivedData) {
2455
- hasRelationshipDataProperty = true;
2456
- if (isCollection) {
2457
- graph.update({
2458
- op: 'replaceRelatedRecords',
2459
- record: identifier,
2460
- field: op.field,
2461
- value: []
2462
- }, true);
2463
- } else {
2464
- graph.update({
2465
- op: 'replaceRelatedRecord',
2466
- record: identifier,
2467
- field: op.field,
2468
- value: null
2469
- }, true);
2470
- }
2471
2484
  }
2472
2485
  if (payload.links) {
2473
2486
  const originalLinks = relationship.links;
@@ -2477,9 +2490,10 @@ function updateRelationshipOperation(graph, op) {
2477
2490
  const currentLink = originalLinks && originalLinks.related ? _normalizeLink(originalLinks.related) : null;
2478
2491
  const currentLinkHref = currentLink ? currentLink.href : null;
2479
2492
  if (relatedLink && relatedLink.href && relatedLink.href !== currentLinkHref) {
2480
- console.warn(`You pushed a record of type '${identifier.type}' with a relationship '${definition.key}' configured as 'async: false'. You've included a link but no primary data, this may be an error in your payload. WarpDrive will treat this relationship as known-to-be-empty.`, definition.isAsync || state.hasReceivedData, {
2481
- id: 'ds.store.push-link-for-sync-relationship'
2482
- });
2493
+ // Note: the equivalent warning for this case is issued eagerly (and with a more
2494
+ // complete condition, since it also accounts for `payload.data` being present) by
2495
+ // `assertValidRelationshipPayload` in `-utils.ts`, which always runs immediately
2496
+ // before this operation in DEBUG builds. Warning here too would double-warn.
2483
2497
  (test => {
2484
2498
  if (!test) {
2485
2499
  throw new Error(`You have pushed a record of type '${identifier.type}' with '${definition.key}' as a link, but the value of that link is not a string.`);
@@ -2510,6 +2524,7 @@ function updateRelationshipOperation(graph, op) {
2510
2524
  // we don't need to notify here as the update op we pushed in above will notify once
2511
2525
  // membership is in the correct state.
2512
2526
  relationship.state.hasReceivedData = true;
2527
+ relationship.state.hasReceivedRemoteData = true;
2513
2528
  relationship.state.isStale = false;
2514
2529
  relationship.state.hasDematerializedInverse = false;
2515
2530
  relationship.state.isEmpty = relationshipIsEmpty;