@warp-drive/core 5.9.0-alpha.18 → 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.
- package/declarations/index.d.ts +10 -1
- package/dist/graph/-private.js +17 -21
- package/dist/{index-BoY6aNE5.js → index-LI2ckwf9.js} +244 -1
- package/dist/index.js +1 -1
- package/dist/reactive.js +1 -1
- package/dist/store/-private.js +1 -1
- package/dist/types/-private.js +1 -1
- package/dist/unpkg/dev/graph/-private.js +17 -21
- package/dist/unpkg/dev/{index-BZ6PKU-a.js → index-DU_HLpg-.js} +244 -1
- package/dist/unpkg/dev/index.js +1 -1
- package/dist/unpkg/dev/reactive.js +1 -1
- package/dist/unpkg/dev/store/-private.js +2 -2
- package/dist/unpkg/dev/types/-private.js +1 -1
- package/dist/unpkg/dev-deprecated/graph/-private.js +17 -21
- package/dist/unpkg/dev-deprecated/{index-CDjd631s.js → index-BYFUHVPd.js} +244 -1
- package/dist/unpkg/dev-deprecated/index.js +1 -1
- package/dist/unpkg/dev-deprecated/reactive.js +1 -1
- package/dist/unpkg/dev-deprecated/store/-private.js +1 -1
- package/dist/unpkg/dev-deprecated/types/-private.js +1 -1
- package/dist/unpkg/prod/{index-BMBm3kYx.js → index-C-AhVafS.js} +146 -1
- package/dist/unpkg/prod/index.js +1 -1
- package/dist/unpkg/prod/reactive.js +1 -1
- package/dist/unpkg/prod/store/-private.js +2 -2
- package/dist/unpkg/prod/types/-private.js +1 -1
- package/dist/unpkg/prod-deprecated/{index-CZkDXZog.js → index-CplZl2hv.js} +146 -1
- package/dist/unpkg/prod-deprecated/index.js +1 -1
- package/dist/unpkg/prod-deprecated/reactive.js +1 -1
- package/dist/unpkg/prod-deprecated/store/-private.js +1 -1
- package/dist/unpkg/prod-deprecated/types/-private.js +1 -1
- package/package.json +3 -3
|
@@ -7738,6 +7738,9 @@ class ReactiveResource {
|
|
|
7738
7738
|
if (prop === Destroy || prop === Checkout) {
|
|
7739
7739
|
return true;
|
|
7740
7740
|
}
|
|
7741
|
+
if (prop === identityField?.name) {
|
|
7742
|
+
return true;
|
|
7743
|
+
}
|
|
7741
7744
|
return fields.has(prop);
|
|
7742
7745
|
},
|
|
7743
7746
|
getOwnPropertyDescriptor(target, prop) {
|
|
@@ -8488,6 +8491,90 @@ function registerDerivations(schema) {
|
|
|
8488
8491
|
schema.registerDerivation(fromIdentity);
|
|
8489
8492
|
schema.registerDerivation(_constructor);
|
|
8490
8493
|
}
|
|
8494
|
+
|
|
8495
|
+
/**
|
|
8496
|
+
* A relationship field capable of declaring `options.as`, marking it as a
|
|
8497
|
+
* concrete implementation of an abstract polymorphic type.
|
|
8498
|
+
*/
|
|
8499
|
+
|
|
8500
|
+
/**
|
|
8501
|
+
* A relationship field contributed to an abstract type's schema, along with
|
|
8502
|
+
* the name of the type that contributed it (either a concrete implementer,
|
|
8503
|
+
* via `options.as`, or the abstract type's own schema), for use in assertion
|
|
8504
|
+
* messages when two contributions disagree on shape.
|
|
8505
|
+
*/
|
|
8506
|
+
|
|
8507
|
+
/**
|
|
8508
|
+
* Reduces a field to a plain object with a fixed key order, covering every
|
|
8509
|
+
* option any relationship-implementer field can declare, so two fields can
|
|
8510
|
+
* be compared for exact equality via `JSON.stringify` regardless of the key
|
|
8511
|
+
* order the schema author happened to write them in.
|
|
8512
|
+
*
|
|
8513
|
+
* `options.as` is included and is *not* special-cased: every contributor to
|
|
8514
|
+
* a given field name on an abstract type - including the abstract type's
|
|
8515
|
+
* own schema, if it has one - is expected to declare `as` equal to that
|
|
8516
|
+
* abstract type's own name. This is redundant/self-referential for the
|
|
8517
|
+
* abstract type's own schema, but required for consistency: relationship
|
|
8518
|
+
* resolution elsewhere (e.g. `inverse` name-matching) does not itself
|
|
8519
|
+
* validate `as`, so a field with a missing or incorrect `as` can otherwise
|
|
8520
|
+
* be silently pulled into a relationship it never declared it implements.
|
|
8521
|
+
*/
|
|
8522
|
+
function comparableAbstractFieldShape(field) {
|
|
8523
|
+
const {
|
|
8524
|
+
kind,
|
|
8525
|
+
name,
|
|
8526
|
+
type,
|
|
8527
|
+
sourceKey,
|
|
8528
|
+
options
|
|
8529
|
+
} = field;
|
|
8530
|
+
return {
|
|
8531
|
+
kind,
|
|
8532
|
+
name,
|
|
8533
|
+
type,
|
|
8534
|
+
sourceKey,
|
|
8535
|
+
options: {
|
|
8536
|
+
as: options?.as,
|
|
8537
|
+
async: options?.async,
|
|
8538
|
+
inverse: options?.inverse,
|
|
8539
|
+
polymorphic: options?.polymorphic,
|
|
8540
|
+
linksMode: options?.linksMode,
|
|
8541
|
+
resetOnRemoteUpdate: options?.resetOnRemoteUpdate,
|
|
8542
|
+
arrayExtensions: options?.arrayExtensions
|
|
8543
|
+
}
|
|
8544
|
+
};
|
|
8545
|
+
}
|
|
8546
|
+
|
|
8547
|
+
/**
|
|
8548
|
+
* Asserts that two contributions to the same field name on an abstract
|
|
8549
|
+
* polymorphic type - whether from two different concrete implementers, or
|
|
8550
|
+
* from an implementer and the abstract type's own schema - declare an
|
|
8551
|
+
* identical shape: `kind`, `type`, and every option, including `as` (which
|
|
8552
|
+
* every contributor, the abstract type's own schema included, must declare
|
|
8553
|
+
* equal to `abstractType`). A mismatch here (e.g. one implementer's field
|
|
8554
|
+
* being a `hasMany` while another's is a `belongsTo`, the two disagreeing on
|
|
8555
|
+
* `inverse`/`async`/`polymorphic`, or one omitting or misdeclaring `as`)
|
|
8556
|
+
* cannot be resolved by picking one side arbitrarily, since that would
|
|
8557
|
+
* silently leave whichever side lost the mismatch pointing at a relationship
|
|
8558
|
+
* whose true shape differs from what its own schema declared.
|
|
8559
|
+
*/
|
|
8560
|
+
function assertConsistentAbstractFieldShape(abstractType, fieldName, existing, incoming) {
|
|
8561
|
+
// This function exists solely to support the `assert()` call below - there
|
|
8562
|
+
// is no other work here with an effect in production. Since `assert()`'s
|
|
8563
|
+
// own babel-macro stripping only removes the call expression itself, not
|
|
8564
|
+
// the (comparatively expensive, involving `JSON.stringify`) computation of
|
|
8565
|
+
// its arguments, guard the whole body so none of it survives in production
|
|
8566
|
+
// builds, matching how `assertPolymorphicType`/`assertInheritedSchema` and
|
|
8567
|
+
// their call sites are gated in `assert-polymorphic-type.ts`.
|
|
8568
|
+
{
|
|
8569
|
+
const existingShape = comparableAbstractFieldShape(existing.field);
|
|
8570
|
+
const incomingShape = comparableAbstractFieldShape(incoming.field);
|
|
8571
|
+
(test => {
|
|
8572
|
+
if (!test) {
|
|
8573
|
+
throw new Error(`Expected the relationship '${fieldName}' on the abstract polymorphic type '${abstractType}' to be declared identically everywhere it is implemented (including 'options.as', which every contributor - the abstract type's own schema included - must declare equal to '${abstractType}'), but '${existing.source}' declares it as:\n\n${JSON.stringify(existingShape, null, 2)}\n\nwhile '${incoming.source}' declares it as:\n\n${JSON.stringify(incomingShape, null, 2)}\n\nAll concrete implementers of an abstract type - and the abstract type's own schema, if it has one - must declare an identical shape for any relationship field they share.`);
|
|
8574
|
+
}
|
|
8575
|
+
})(JSON.stringify(existingShape) === JSON.stringify(incomingShape));
|
|
8576
|
+
}
|
|
8577
|
+
}
|
|
8491
8578
|
/**
|
|
8492
8579
|
* Wraps a derivation in a new function with Derivation signature but that looks
|
|
8493
8580
|
* up the value in the cache before recomputing.
|
|
@@ -8527,6 +8614,18 @@ class SchemaService {
|
|
|
8527
8614
|
|
|
8528
8615
|
/** @internal */
|
|
8529
8616
|
|
|
8617
|
+
/**
|
|
8618
|
+
* Tracks, per abstract type, the relationship fields that concrete
|
|
8619
|
+
* implementers have contributed via `options.as`, along with the type
|
|
8620
|
+
* that contributed each one (for assertion messages). This is
|
|
8621
|
+
* independent of whatever schema (synthesized or user-registered)
|
|
8622
|
+
* currently occupies `_schemas` for that type, so that these fields
|
|
8623
|
+
* survive regardless of the order in which the abstract type's
|
|
8624
|
+
* implementers and its own (optional) concrete schema are registered.
|
|
8625
|
+
*
|
|
8626
|
+
* @internal
|
|
8627
|
+
*/
|
|
8628
|
+
|
|
8530
8629
|
/** @internal */
|
|
8531
8630
|
|
|
8532
8631
|
/** @internal */
|
|
@@ -8538,6 +8637,7 @@ class SchemaService {
|
|
|
8538
8637
|
this._derivations = new Map();
|
|
8539
8638
|
this._traits = new Map();
|
|
8540
8639
|
this._modes = new Map();
|
|
8640
|
+
this._abstractImplementerFields = new Map();
|
|
8541
8641
|
this._extensions = {
|
|
8542
8642
|
object: new Map(),
|
|
8543
8643
|
array: new Map()
|
|
@@ -8633,6 +8733,7 @@ class SchemaService {
|
|
|
8633
8733
|
const fields = new Map();
|
|
8634
8734
|
const relationships = {};
|
|
8635
8735
|
const attributes = {};
|
|
8736
|
+
const abstractImplementations = [];
|
|
8636
8737
|
for (const field of schema.fields) {
|
|
8637
8738
|
(test => {
|
|
8638
8739
|
if (!test) {
|
|
@@ -8646,6 +8747,31 @@ class SchemaService {
|
|
|
8646
8747
|
attributes[field.name] = field;
|
|
8647
8748
|
} else if (field.kind === 'belongsTo' || field.kind === 'hasMany') {
|
|
8648
8749
|
relationships[field.name] = field;
|
|
8750
|
+
if (field.options?.as) {
|
|
8751
|
+
abstractImplementations.push(field);
|
|
8752
|
+
}
|
|
8753
|
+
}
|
|
8754
|
+
}
|
|
8755
|
+
|
|
8756
|
+
// This type may already be known as an abstract polymorphic type,
|
|
8757
|
+
// implemented by other concrete types via `options.as`, from before it
|
|
8758
|
+
// ever had a schema of its own (see `_registerAbstractTypeImplementation`).
|
|
8759
|
+
// Carry those previously-contributed fields forward so that registering
|
|
8760
|
+
// a "real" schema for the type - whenever that happens to occur - never
|
|
8761
|
+
// erases the relationships its implementers depend on.
|
|
8762
|
+
const implementerFields = this._abstractImplementerFields.get(schema.type);
|
|
8763
|
+
if (implementerFields) {
|
|
8764
|
+
for (const [name, contribution] of implementerFields) {
|
|
8765
|
+
const ownField = fields.get(name);
|
|
8766
|
+
if (!ownField) {
|
|
8767
|
+
fields.set(name, contribution.field);
|
|
8768
|
+
relationships[name] = contribution.field;
|
|
8769
|
+
} else {
|
|
8770
|
+
assertConsistentAbstractFieldShape(schema.type, name, contribution, {
|
|
8771
|
+
field: ownField,
|
|
8772
|
+
source: schema.type
|
|
8773
|
+
});
|
|
8774
|
+
}
|
|
8649
8775
|
}
|
|
8650
8776
|
}
|
|
8651
8777
|
const cacheFields = null;
|
|
@@ -8664,6 +8790,101 @@ class SchemaService {
|
|
|
8664
8790
|
internalSchema.cacheFields = getCacheFields(internalSchema);
|
|
8665
8791
|
}
|
|
8666
8792
|
this._schemas.set(schema.type, internalSchema);
|
|
8793
|
+
|
|
8794
|
+
// A relationship field's `as` option marks it as a valid concrete
|
|
8795
|
+
// implementer of an abstract polymorphic type (e.g. `as: 'commentable'`).
|
|
8796
|
+
// That abstract type may never be given its own schema by the user - it
|
|
8797
|
+
// may exist only to be implemented by concrete types like this one - or
|
|
8798
|
+
// it may already have (or later receive) a schema of its own, e.g. if it
|
|
8799
|
+
// turns out to also be a real, directly-resolvable resource. Either way,
|
|
8800
|
+
// ensure it has a schema with this field present, so that it behaves
|
|
8801
|
+
// like any other registered resource (`hasResource`, `fields`, etc.)
|
|
8802
|
+
// instead of requiring special-casing wherever abstract relationship
|
|
8803
|
+
// types are resolved.
|
|
8804
|
+
for (const field of abstractImplementations) {
|
|
8805
|
+
this._registerAbstractTypeImplementation(field, schema.type);
|
|
8806
|
+
}
|
|
8807
|
+
}
|
|
8808
|
+
|
|
8809
|
+
/** @internal */
|
|
8810
|
+
_registerAbstractTypeImplementation(field, implementer) {
|
|
8811
|
+
const abstractType = field.options.as;
|
|
8812
|
+
let implementerFields = this._abstractImplementerFields.get(abstractType);
|
|
8813
|
+
if (!implementerFields) {
|
|
8814
|
+
implementerFields = new Map();
|
|
8815
|
+
this._abstractImplementerFields.set(abstractType, implementerFields);
|
|
8816
|
+
}
|
|
8817
|
+
|
|
8818
|
+
// Unlike the original approach this replaced, `as` is *not* stripped here:
|
|
8819
|
+
// the field as synthesized onto the abstract type's own schema keeps
|
|
8820
|
+
// `options.as === abstractType`, redundant/self-referential as that is.
|
|
8821
|
+
// This keeps every contributor - implementers and the abstract type's
|
|
8822
|
+
// own schema alike - declaring the same thing, which is what
|
|
8823
|
+
// `assertConsistentAbstractFieldShape` checks, and it is also what lets
|
|
8824
|
+
// `assertPolymorphicType` (which reads a field's declared `as` off
|
|
8825
|
+
// whatever `schema.fields()` serves for its type) correctly permit the
|
|
8826
|
+
// abstract type itself to be pushed directly into this relationship.
|
|
8827
|
+
const abstractField = {
|
|
8828
|
+
...field
|
|
8829
|
+
};
|
|
8830
|
+
const contribution = {
|
|
8831
|
+
field: abstractField,
|
|
8832
|
+
source: implementer
|
|
8833
|
+
};
|
|
8834
|
+
|
|
8835
|
+
// all concrete implementations of an abstract type are required to
|
|
8836
|
+
// share the same shape for the field that implements it, so the first
|
|
8837
|
+
// one registered is as good a canonical source as any - but a later,
|
|
8838
|
+
// differently-shaped one is almost certainly a mistake rather than an
|
|
8839
|
+
// intentional override, so we catch it rather than silently ignoring it.
|
|
8840
|
+
const existingImplementer = implementerFields.get(field.name);
|
|
8841
|
+
if (existingImplementer) {
|
|
8842
|
+
{
|
|
8843
|
+
assertConsistentAbstractFieldShape(abstractType, field.name, existingImplementer, contribution);
|
|
8844
|
+
}
|
|
8845
|
+
return;
|
|
8846
|
+
}
|
|
8847
|
+
implementerFields.set(field.name, contribution);
|
|
8848
|
+
let abstractSchema = this._schemas.get(abstractType);
|
|
8849
|
+
if (!abstractSchema) {
|
|
8850
|
+
abstractSchema = {
|
|
8851
|
+
original: {
|
|
8852
|
+
legacy: true,
|
|
8853
|
+
identity: {
|
|
8854
|
+
kind: '@id',
|
|
8855
|
+
name: 'id'
|
|
8856
|
+
},
|
|
8857
|
+
type: abstractType,
|
|
8858
|
+
fields: []
|
|
8859
|
+
},
|
|
8860
|
+
finalized: true,
|
|
8861
|
+
fields: new Map(),
|
|
8862
|
+
cacheFields: new Map(),
|
|
8863
|
+
relationships: {},
|
|
8864
|
+
attributes: {},
|
|
8865
|
+
traits: new Set()
|
|
8866
|
+
};
|
|
8867
|
+
this._schemas.set(abstractType, abstractSchema);
|
|
8868
|
+
}
|
|
8869
|
+
const existingAbstractField = abstractSchema.fields.get(field.name);
|
|
8870
|
+
if (existingAbstractField) {
|
|
8871
|
+
{
|
|
8872
|
+
assertConsistentAbstractFieldShape(abstractType, field.name, {
|
|
8873
|
+
field: existingAbstractField,
|
|
8874
|
+
source: abstractType
|
|
8875
|
+
}, contribution);
|
|
8876
|
+
}
|
|
8877
|
+
return;
|
|
8878
|
+
}
|
|
8879
|
+
abstractSchema.fields.set(field.name, abstractField);
|
|
8880
|
+
abstractSchema.relationships[field.name] = abstractField;
|
|
8881
|
+
|
|
8882
|
+
// If the schema is mid-finalization (traits pending), finalizeResource
|
|
8883
|
+
// will recompute cacheFields from the current `fields` map anyway; avoid
|
|
8884
|
+
// doing so prematurely from a partially-resolved set of fields.
|
|
8885
|
+
if (abstractSchema.finalized) {
|
|
8886
|
+
abstractSchema.cacheFields = getCacheFields(abstractSchema);
|
|
8887
|
+
}
|
|
8667
8888
|
}
|
|
8668
8889
|
|
|
8669
8890
|
/**
|
|
@@ -9429,7 +9650,29 @@ globalThis.setWarpDriveIsMaybeMirage = setIsMaybeMirage;
|
|
|
9429
9650
|
*/
|
|
9430
9651
|
function useRecommendedStore(options, StoreKlass = Store) {
|
|
9431
9652
|
return class AppStore extends StoreKlass {
|
|
9432
|
-
|
|
9653
|
+
constructor(createArgs) {
|
|
9654
|
+
super(createArgs);
|
|
9655
|
+
// installed via defineProperty (rather than a class field/accessor) so that
|
|
9656
|
+
// this lazy override of the inherited `requestManager` field does not
|
|
9657
|
+
// conflict with the documented pattern of assigning it directly on
|
|
9658
|
+
// consumer-authored Store subclasses. The setter preserves the ability
|
|
9659
|
+
// to replace `requestManager` outright after construction.
|
|
9660
|
+
let requestManager;
|
|
9661
|
+
Object.defineProperty(this, 'requestManager', {
|
|
9662
|
+
configurable: true,
|
|
9663
|
+
enumerable: true,
|
|
9664
|
+
get: () => {
|
|
9665
|
+
if (!requestManager) {
|
|
9666
|
+
const handlers = typeof options.handlers === 'function' ? options.handlers(this) : options.handlers ?? [];
|
|
9667
|
+
requestManager = new RequestManager().use([...handlers, Fetch]).useCache(CacheHandler);
|
|
9668
|
+
}
|
|
9669
|
+
return requestManager;
|
|
9670
|
+
},
|
|
9671
|
+
set: value => {
|
|
9672
|
+
requestManager = value;
|
|
9673
|
+
}
|
|
9674
|
+
});
|
|
9675
|
+
}
|
|
9433
9676
|
lifetimes = options.policy ?? new DefaultCachePolicy({
|
|
9434
9677
|
apiCacheHardExpires: 15 * 60 * 1000,
|
|
9435
9678
|
// 15 minutes
|
package/dist/unpkg/dev/index.js
CHANGED
|
@@ -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-
|
|
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-
|
|
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-
|
|
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-
|
|
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
|
}
|
|
@@ -757,7 +757,7 @@ let assertInheritedSchema;
|
|
|
757
757
|
errors.set('type', ` <---- should be '${definition.inverseType}'`);
|
|
758
758
|
}
|
|
759
759
|
if (definition.inverseKind !== meta.kind) {
|
|
760
|
-
errors.set('
|
|
760
|
+
errors.set('kind', ` <---- should be '${definition.inverseKind}'`);
|
|
761
761
|
}
|
|
762
762
|
if (definition.inverseIsAsync !== meta.options.async) {
|
|
763
763
|
errors.set('async', ` <---- should be ${definition.inverseIsAsync}`);
|
|
@@ -768,7 +768,12 @@ let assertInheritedSchema;
|
|
|
768
768
|
if (definition.key !== meta.options.inverse) {
|
|
769
769
|
errors.set('inverse', ` <---- should be '${definition.key}'`);
|
|
770
770
|
}
|
|
771
|
-
|
|
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) {
|
|
772
777
|
errors.set('as', ` <---- should be '${definition.type}'`);
|
|
773
778
|
}
|
|
774
779
|
return errors;
|
|
@@ -807,18 +812,6 @@ let assertInheritedSchema;
|
|
|
807
812
|
|
|
808
813
|
`;
|
|
809
814
|
}
|
|
810
|
-
function metaFrom(definition) {
|
|
811
|
-
return {
|
|
812
|
-
name: definition.key,
|
|
813
|
-
type: definition.type,
|
|
814
|
-
kind: definition.kind,
|
|
815
|
-
options: {
|
|
816
|
-
async: definition.isAsync,
|
|
817
|
-
polymorphic: definition.isPolymorphic,
|
|
818
|
-
inverse: definition.inverseKey
|
|
819
|
-
}
|
|
820
|
-
};
|
|
821
|
-
}
|
|
822
815
|
function inverseMetaFrom(definition) {
|
|
823
816
|
return {
|
|
824
817
|
name: definition.inverseKey,
|
|
@@ -861,15 +854,18 @@ let assertInheritedSchema;
|
|
|
861
854
|
});
|
|
862
855
|
}
|
|
863
856
|
assertInheritedSchema = function assertInheritedSchema(definition, type) {
|
|
864
|
-
|
|
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.
|
|
865
866
|
const meta2 = inverseMetaFrom(definition);
|
|
866
|
-
const errors1 = validateSchema(inverseDefinition(definition), meta1);
|
|
867
867
|
const errors2 = validateSchema(definitionWithPolymorphic(definition), meta2);
|
|
868
|
-
if (errors2.size
|
|
869
|
-
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)}`);
|
|
870
|
-
} else if (errors1.size > 0) {
|
|
871
|
-
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)}`);
|
|
872
|
-
} else if (errors2.size > 0) {
|
|
868
|
+
if (errors2.size > 0) {
|
|
873
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)}`);
|
|
874
870
|
}
|
|
875
871
|
};
|