@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
|
@@ -8326,6 +8326,9 @@ class ReactiveResource {
|
|
|
8326
8326
|
if (prop === Destroy || prop === Checkout) {
|
|
8327
8327
|
return true;
|
|
8328
8328
|
}
|
|
8329
|
+
if (prop === identityField?.name) {
|
|
8330
|
+
return true;
|
|
8331
|
+
}
|
|
8329
8332
|
return fields.has(prop);
|
|
8330
8333
|
},
|
|
8331
8334
|
getOwnPropertyDescriptor(target, prop) {
|
|
@@ -9076,6 +9079,90 @@ function registerDerivations(schema) {
|
|
|
9076
9079
|
schema.registerDerivation(fromIdentity);
|
|
9077
9080
|
schema.registerDerivation(_constructor);
|
|
9078
9081
|
}
|
|
9082
|
+
|
|
9083
|
+
/**
|
|
9084
|
+
* A relationship field capable of declaring `options.as`, marking it as a
|
|
9085
|
+
* concrete implementation of an abstract polymorphic type.
|
|
9086
|
+
*/
|
|
9087
|
+
|
|
9088
|
+
/**
|
|
9089
|
+
* A relationship field contributed to an abstract type's schema, along with
|
|
9090
|
+
* the name of the type that contributed it (either a concrete implementer,
|
|
9091
|
+
* via `options.as`, or the abstract type's own schema), for use in assertion
|
|
9092
|
+
* messages when two contributions disagree on shape.
|
|
9093
|
+
*/
|
|
9094
|
+
|
|
9095
|
+
/**
|
|
9096
|
+
* Reduces a field to a plain object with a fixed key order, covering every
|
|
9097
|
+
* option any relationship-implementer field can declare, so two fields can
|
|
9098
|
+
* be compared for exact equality via `JSON.stringify` regardless of the key
|
|
9099
|
+
* order the schema author happened to write them in.
|
|
9100
|
+
*
|
|
9101
|
+
* `options.as` is included and is *not* special-cased: every contributor to
|
|
9102
|
+
* a given field name on an abstract type - including the abstract type's
|
|
9103
|
+
* own schema, if it has one - is expected to declare `as` equal to that
|
|
9104
|
+
* abstract type's own name. This is redundant/self-referential for the
|
|
9105
|
+
* abstract type's own schema, but required for consistency: relationship
|
|
9106
|
+
* resolution elsewhere (e.g. `inverse` name-matching) does not itself
|
|
9107
|
+
* validate `as`, so a field with a missing or incorrect `as` can otherwise
|
|
9108
|
+
* be silently pulled into a relationship it never declared it implements.
|
|
9109
|
+
*/
|
|
9110
|
+
function comparableAbstractFieldShape(field) {
|
|
9111
|
+
const {
|
|
9112
|
+
kind,
|
|
9113
|
+
name,
|
|
9114
|
+
type,
|
|
9115
|
+
sourceKey,
|
|
9116
|
+
options
|
|
9117
|
+
} = field;
|
|
9118
|
+
return {
|
|
9119
|
+
kind,
|
|
9120
|
+
name,
|
|
9121
|
+
type,
|
|
9122
|
+
sourceKey,
|
|
9123
|
+
options: {
|
|
9124
|
+
as: options?.as,
|
|
9125
|
+
async: options?.async,
|
|
9126
|
+
inverse: options?.inverse,
|
|
9127
|
+
polymorphic: options?.polymorphic,
|
|
9128
|
+
linksMode: options?.linksMode,
|
|
9129
|
+
resetOnRemoteUpdate: options?.resetOnRemoteUpdate,
|
|
9130
|
+
arrayExtensions: options?.arrayExtensions
|
|
9131
|
+
}
|
|
9132
|
+
};
|
|
9133
|
+
}
|
|
9134
|
+
|
|
9135
|
+
/**
|
|
9136
|
+
* Asserts that two contributions to the same field name on an abstract
|
|
9137
|
+
* polymorphic type - whether from two different concrete implementers, or
|
|
9138
|
+
* from an implementer and the abstract type's own schema - declare an
|
|
9139
|
+
* identical shape: `kind`, `type`, and every option, including `as` (which
|
|
9140
|
+
* every contributor, the abstract type's own schema included, must declare
|
|
9141
|
+
* equal to `abstractType`). A mismatch here (e.g. one implementer's field
|
|
9142
|
+
* being a `hasMany` while another's is a `belongsTo`, the two disagreeing on
|
|
9143
|
+
* `inverse`/`async`/`polymorphic`, or one omitting or misdeclaring `as`)
|
|
9144
|
+
* cannot be resolved by picking one side arbitrarily, since that would
|
|
9145
|
+
* silently leave whichever side lost the mismatch pointing at a relationship
|
|
9146
|
+
* whose true shape differs from what its own schema declared.
|
|
9147
|
+
*/
|
|
9148
|
+
function assertConsistentAbstractFieldShape(abstractType, fieldName, existing, incoming) {
|
|
9149
|
+
// This function exists solely to support the `assert()` call below - there
|
|
9150
|
+
// is no other work here with an effect in production. Since `assert()`'s
|
|
9151
|
+
// own babel-macro stripping only removes the call expression itself, not
|
|
9152
|
+
// the (comparatively expensive, involving `JSON.stringify`) computation of
|
|
9153
|
+
// its arguments, guard the whole body so none of it survives in production
|
|
9154
|
+
// builds, matching how `assertPolymorphicType`/`assertInheritedSchema` and
|
|
9155
|
+
// their call sites are gated in `assert-polymorphic-type.ts`.
|
|
9156
|
+
{
|
|
9157
|
+
const existingShape = comparableAbstractFieldShape(existing.field);
|
|
9158
|
+
const incomingShape = comparableAbstractFieldShape(incoming.field);
|
|
9159
|
+
(test => {
|
|
9160
|
+
if (!test) {
|
|
9161
|
+
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.`);
|
|
9162
|
+
}
|
|
9163
|
+
})(JSON.stringify(existingShape) === JSON.stringify(incomingShape));
|
|
9164
|
+
}
|
|
9165
|
+
}
|
|
9079
9166
|
/**
|
|
9080
9167
|
* Wraps a derivation in a new function with Derivation signature but that looks
|
|
9081
9168
|
* up the value in the cache before recomputing.
|
|
@@ -9115,6 +9202,18 @@ class SchemaService {
|
|
|
9115
9202
|
|
|
9116
9203
|
/** @internal */
|
|
9117
9204
|
|
|
9205
|
+
/**
|
|
9206
|
+
* Tracks, per abstract type, the relationship fields that concrete
|
|
9207
|
+
* implementers have contributed via `options.as`, along with the type
|
|
9208
|
+
* that contributed each one (for assertion messages). This is
|
|
9209
|
+
* independent of whatever schema (synthesized or user-registered)
|
|
9210
|
+
* currently occupies `_schemas` for that type, so that these fields
|
|
9211
|
+
* survive regardless of the order in which the abstract type's
|
|
9212
|
+
* implementers and its own (optional) concrete schema are registered.
|
|
9213
|
+
*
|
|
9214
|
+
* @internal
|
|
9215
|
+
*/
|
|
9216
|
+
|
|
9118
9217
|
/** @internal */
|
|
9119
9218
|
|
|
9120
9219
|
/** @internal */
|
|
@@ -9126,6 +9225,7 @@ class SchemaService {
|
|
|
9126
9225
|
this._derivations = new Map();
|
|
9127
9226
|
this._traits = new Map();
|
|
9128
9227
|
this._modes = new Map();
|
|
9228
|
+
this._abstractImplementerFields = new Map();
|
|
9129
9229
|
this._extensions = {
|
|
9130
9230
|
object: new Map(),
|
|
9131
9231
|
array: new Map()
|
|
@@ -9221,6 +9321,7 @@ class SchemaService {
|
|
|
9221
9321
|
const fields = new Map();
|
|
9222
9322
|
const relationships = {};
|
|
9223
9323
|
const attributes = {};
|
|
9324
|
+
const abstractImplementations = [];
|
|
9224
9325
|
for (const field of schema.fields) {
|
|
9225
9326
|
(test => {
|
|
9226
9327
|
if (!test) {
|
|
@@ -9234,6 +9335,31 @@ class SchemaService {
|
|
|
9234
9335
|
attributes[field.name] = field;
|
|
9235
9336
|
} else if (field.kind === 'belongsTo' || field.kind === 'hasMany') {
|
|
9236
9337
|
relationships[field.name] = field;
|
|
9338
|
+
if (field.options?.as) {
|
|
9339
|
+
abstractImplementations.push(field);
|
|
9340
|
+
}
|
|
9341
|
+
}
|
|
9342
|
+
}
|
|
9343
|
+
|
|
9344
|
+
// This type may already be known as an abstract polymorphic type,
|
|
9345
|
+
// implemented by other concrete types via `options.as`, from before it
|
|
9346
|
+
// ever had a schema of its own (see `_registerAbstractTypeImplementation`).
|
|
9347
|
+
// Carry those previously-contributed fields forward so that registering
|
|
9348
|
+
// a "real" schema for the type - whenever that happens to occur - never
|
|
9349
|
+
// erases the relationships its implementers depend on.
|
|
9350
|
+
const implementerFields = this._abstractImplementerFields.get(schema.type);
|
|
9351
|
+
if (implementerFields) {
|
|
9352
|
+
for (const [name, contribution] of implementerFields) {
|
|
9353
|
+
const ownField = fields.get(name);
|
|
9354
|
+
if (!ownField) {
|
|
9355
|
+
fields.set(name, contribution.field);
|
|
9356
|
+
relationships[name] = contribution.field;
|
|
9357
|
+
} else {
|
|
9358
|
+
assertConsistentAbstractFieldShape(schema.type, name, contribution, {
|
|
9359
|
+
field: ownField,
|
|
9360
|
+
source: schema.type
|
|
9361
|
+
});
|
|
9362
|
+
}
|
|
9237
9363
|
}
|
|
9238
9364
|
}
|
|
9239
9365
|
const cacheFields = null;
|
|
@@ -9252,6 +9378,101 @@ class SchemaService {
|
|
|
9252
9378
|
internalSchema.cacheFields = getCacheFields(internalSchema);
|
|
9253
9379
|
}
|
|
9254
9380
|
this._schemas.set(schema.type, internalSchema);
|
|
9381
|
+
|
|
9382
|
+
// A relationship field's `as` option marks it as a valid concrete
|
|
9383
|
+
// implementer of an abstract polymorphic type (e.g. `as: 'commentable'`).
|
|
9384
|
+
// That abstract type may never be given its own schema by the user - it
|
|
9385
|
+
// may exist only to be implemented by concrete types like this one - or
|
|
9386
|
+
// it may already have (or later receive) a schema of its own, e.g. if it
|
|
9387
|
+
// turns out to also be a real, directly-resolvable resource. Either way,
|
|
9388
|
+
// ensure it has a schema with this field present, so that it behaves
|
|
9389
|
+
// like any other registered resource (`hasResource`, `fields`, etc.)
|
|
9390
|
+
// instead of requiring special-casing wherever abstract relationship
|
|
9391
|
+
// types are resolved.
|
|
9392
|
+
for (const field of abstractImplementations) {
|
|
9393
|
+
this._registerAbstractTypeImplementation(field, schema.type);
|
|
9394
|
+
}
|
|
9395
|
+
}
|
|
9396
|
+
|
|
9397
|
+
/** @internal */
|
|
9398
|
+
_registerAbstractTypeImplementation(field, implementer) {
|
|
9399
|
+
const abstractType = field.options.as;
|
|
9400
|
+
let implementerFields = this._abstractImplementerFields.get(abstractType);
|
|
9401
|
+
if (!implementerFields) {
|
|
9402
|
+
implementerFields = new Map();
|
|
9403
|
+
this._abstractImplementerFields.set(abstractType, implementerFields);
|
|
9404
|
+
}
|
|
9405
|
+
|
|
9406
|
+
// Unlike the original approach this replaced, `as` is *not* stripped here:
|
|
9407
|
+
// the field as synthesized onto the abstract type's own schema keeps
|
|
9408
|
+
// `options.as === abstractType`, redundant/self-referential as that is.
|
|
9409
|
+
// This keeps every contributor - implementers and the abstract type's
|
|
9410
|
+
// own schema alike - declaring the same thing, which is what
|
|
9411
|
+
// `assertConsistentAbstractFieldShape` checks, and it is also what lets
|
|
9412
|
+
// `assertPolymorphicType` (which reads a field's declared `as` off
|
|
9413
|
+
// whatever `schema.fields()` serves for its type) correctly permit the
|
|
9414
|
+
// abstract type itself to be pushed directly into this relationship.
|
|
9415
|
+
const abstractField = {
|
|
9416
|
+
...field
|
|
9417
|
+
};
|
|
9418
|
+
const contribution = {
|
|
9419
|
+
field: abstractField,
|
|
9420
|
+
source: implementer
|
|
9421
|
+
};
|
|
9422
|
+
|
|
9423
|
+
// all concrete implementations of an abstract type are required to
|
|
9424
|
+
// share the same shape for the field that implements it, so the first
|
|
9425
|
+
// one registered is as good a canonical source as any - but a later,
|
|
9426
|
+
// differently-shaped one is almost certainly a mistake rather than an
|
|
9427
|
+
// intentional override, so we catch it rather than silently ignoring it.
|
|
9428
|
+
const existingImplementer = implementerFields.get(field.name);
|
|
9429
|
+
if (existingImplementer) {
|
|
9430
|
+
{
|
|
9431
|
+
assertConsistentAbstractFieldShape(abstractType, field.name, existingImplementer, contribution);
|
|
9432
|
+
}
|
|
9433
|
+
return;
|
|
9434
|
+
}
|
|
9435
|
+
implementerFields.set(field.name, contribution);
|
|
9436
|
+
let abstractSchema = this._schemas.get(abstractType);
|
|
9437
|
+
if (!abstractSchema) {
|
|
9438
|
+
abstractSchema = {
|
|
9439
|
+
original: {
|
|
9440
|
+
legacy: true,
|
|
9441
|
+
identity: {
|
|
9442
|
+
kind: '@id',
|
|
9443
|
+
name: 'id'
|
|
9444
|
+
},
|
|
9445
|
+
type: abstractType,
|
|
9446
|
+
fields: []
|
|
9447
|
+
},
|
|
9448
|
+
finalized: true,
|
|
9449
|
+
fields: new Map(),
|
|
9450
|
+
cacheFields: new Map(),
|
|
9451
|
+
relationships: {},
|
|
9452
|
+
attributes: {},
|
|
9453
|
+
traits: new Set()
|
|
9454
|
+
};
|
|
9455
|
+
this._schemas.set(abstractType, abstractSchema);
|
|
9456
|
+
}
|
|
9457
|
+
const existingAbstractField = abstractSchema.fields.get(field.name);
|
|
9458
|
+
if (existingAbstractField) {
|
|
9459
|
+
{
|
|
9460
|
+
assertConsistentAbstractFieldShape(abstractType, field.name, {
|
|
9461
|
+
field: existingAbstractField,
|
|
9462
|
+
source: abstractType
|
|
9463
|
+
}, contribution);
|
|
9464
|
+
}
|
|
9465
|
+
return;
|
|
9466
|
+
}
|
|
9467
|
+
abstractSchema.fields.set(field.name, abstractField);
|
|
9468
|
+
abstractSchema.relationships[field.name] = abstractField;
|
|
9469
|
+
|
|
9470
|
+
// If the schema is mid-finalization (traits pending), finalizeResource
|
|
9471
|
+
// will recompute cacheFields from the current `fields` map anyway; avoid
|
|
9472
|
+
// doing so prematurely from a partially-resolved set of fields.
|
|
9473
|
+
if (abstractSchema.finalized) {
|
|
9474
|
+
abstractSchema.cacheFields = getCacheFields(abstractSchema);
|
|
9475
|
+
}
|
|
9255
9476
|
}
|
|
9256
9477
|
|
|
9257
9478
|
/**
|
|
@@ -10044,7 +10265,29 @@ globalThis.setWarpDriveIsMaybeMirage = setIsMaybeMirage;
|
|
|
10044
10265
|
*/
|
|
10045
10266
|
function useRecommendedStore(options, StoreKlass = Store) {
|
|
10046
10267
|
return class AppStore extends StoreKlass {
|
|
10047
|
-
|
|
10268
|
+
constructor(createArgs) {
|
|
10269
|
+
super(createArgs);
|
|
10270
|
+
// installed via defineProperty (rather than a class field/accessor) so that
|
|
10271
|
+
// this lazy override of the inherited `requestManager` field does not
|
|
10272
|
+
// conflict with the documented pattern of assigning it directly on
|
|
10273
|
+
// consumer-authored Store subclasses. The setter preserves the ability
|
|
10274
|
+
// to replace `requestManager` outright after construction.
|
|
10275
|
+
let requestManager;
|
|
10276
|
+
Object.defineProperty(this, 'requestManager', {
|
|
10277
|
+
configurable: true,
|
|
10278
|
+
enumerable: true,
|
|
10279
|
+
get: () => {
|
|
10280
|
+
if (!requestManager) {
|
|
10281
|
+
const handlers = typeof options.handlers === 'function' ? options.handlers(this) : options.handlers ?? [];
|
|
10282
|
+
requestManager = new RequestManager().use([...handlers, Fetch]).useCache(CacheHandler);
|
|
10283
|
+
}
|
|
10284
|
+
return requestManager;
|
|
10285
|
+
},
|
|
10286
|
+
set: value => {
|
|
10287
|
+
requestManager = value;
|
|
10288
|
+
}
|
|
10289
|
+
});
|
|
10290
|
+
}
|
|
10048
10291
|
lifetimes = options.policy ?? new DefaultCachePolicy({
|
|
10049
10292
|
apiCacheHardExpires: 15 * 60 * 1000,
|
|
10050
10293
|
// 15 minutes
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { C as CacheHandler, F as Fetch, z as RequestManager, S as Store, r as cacheKeyFor, r as recordIdentifierFor, E as setIdentifierForgetMethod, B as setIdentifierGenerationMethod, G as setIdentifierResetMethod, D as setIdentifierUpdateMethod, H as setKeyInfoForResource, s as storeFor, A as useRecommendedStore } from "./index-
|
|
1
|
+
export { C as CacheHandler, F as Fetch, z as RequestManager, S as Store, r as cacheKeyFor, r as recordIdentifierFor, E as setIdentifierForgetMethod, B as setIdentifierGenerationMethod, G as setIdentifierResetMethod, D as setIdentifierUpdateMethod, H as setKeyInfoForResource, s as storeFor, A as useRecommendedStore } from "./index-BYFUHVPd.js";
|
|
2
2
|
import "./-private-3C1OkYtZ.js";
|
|
3
3
|
import "./-leaked-C40gfiH-.js";
|
|
4
4
|
import './store.js';
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { u as SchemaService, p as checkout, y as commit, v as fromIdentity, q as instantiateRecord, x as registerDerivations, t as teardownRecord, w as withDefaults } from "./index-
|
|
1
|
+
export { u as SchemaService, p as checkout, y as commit, v as fromIdentity, q as instantiateRecord, x as registerDerivations, t as teardownRecord, w as withDefaults } from "./index-BYFUHVPd.js";
|
|
2
2
|
export { C as Checkout } from "./-private-3C1OkYtZ.js";
|
|
3
3
|
export { c as createRequestSubscription, a as getPromiseState, g as getRequestState } from "./-leaked-C40gfiH-.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { C as CacheHandler, R as RecordArrayManager, S as Store, k as StoreMap, _ as _clearCaches, n as _deprecatingNormalize, h as assertPrivateCapabilities, d as assertPrivateStore, b as coerceId, c as constructResource, l as createLegacyManyArray, e as ensureStringId, f as fastPush, g as isPrivateStore, a as isRequestKey, i as isResourceKey, m as log, o as logGroup, r as recordIdentifierFor, j as setRecordIdentifier, s as storeFor } from "../index-
|
|
1
|
+
export { C as CacheHandler, R as RecordArrayManager, S as Store, k as StoreMap, _ as _clearCaches, n as _deprecatingNormalize, h as assertPrivateCapabilities, d as assertPrivateStore, b as coerceId, c as constructResource, l as createLegacyManyArray, e as ensureStringId, f as fastPush, g as isPrivateStore, a as isRequestKey, i as isResourceKey, m as log, o as logGroup, r as recordIdentifierFor, j as setRecordIdentifier, s as storeFor } from "../index-BYFUHVPd.js";
|
|
@@ -5947,6 +5947,9 @@ class ReactiveResource {
|
|
|
5947
5947
|
if (prop === Destroy || prop === Checkout) {
|
|
5948
5948
|
return true;
|
|
5949
5949
|
}
|
|
5950
|
+
if (prop === identityField?.name) {
|
|
5951
|
+
return true;
|
|
5952
|
+
}
|
|
5950
5953
|
return fields.has(prop);
|
|
5951
5954
|
},
|
|
5952
5955
|
getOwnPropertyDescriptor(target, prop) {
|
|
@@ -6643,6 +6646,18 @@ class SchemaService {
|
|
|
6643
6646
|
|
|
6644
6647
|
/** @internal */
|
|
6645
6648
|
|
|
6649
|
+
/**
|
|
6650
|
+
* Tracks, per abstract type, the relationship fields that concrete
|
|
6651
|
+
* implementers have contributed via `options.as`, along with the type
|
|
6652
|
+
* that contributed each one (for assertion messages). This is
|
|
6653
|
+
* independent of whatever schema (synthesized or user-registered)
|
|
6654
|
+
* currently occupies `_schemas` for that type, so that these fields
|
|
6655
|
+
* survive regardless of the order in which the abstract type's
|
|
6656
|
+
* implementers and its own (optional) concrete schema are registered.
|
|
6657
|
+
*
|
|
6658
|
+
* @internal
|
|
6659
|
+
*/
|
|
6660
|
+
|
|
6646
6661
|
/** @internal */
|
|
6647
6662
|
|
|
6648
6663
|
/** @internal */
|
|
@@ -6654,6 +6669,7 @@ class SchemaService {
|
|
|
6654
6669
|
this._derivations = new Map();
|
|
6655
6670
|
this._traits = new Map();
|
|
6656
6671
|
this._modes = new Map();
|
|
6672
|
+
this._abstractImplementerFields = new Map();
|
|
6657
6673
|
this._extensions = {
|
|
6658
6674
|
object: new Map(),
|
|
6659
6675
|
array: new Map()
|
|
@@ -6699,12 +6715,33 @@ class SchemaService {
|
|
|
6699
6715
|
const fields = new Map();
|
|
6700
6716
|
const relationships = {};
|
|
6701
6717
|
const attributes = {};
|
|
6718
|
+
const abstractImplementations = [];
|
|
6702
6719
|
for (const field of schema.fields) {
|
|
6703
6720
|
fields.set(field.name, field);
|
|
6704
6721
|
if (field.kind === 'attribute') {
|
|
6705
6722
|
attributes[field.name] = field;
|
|
6706
6723
|
} else if (field.kind === 'belongsTo' || field.kind === 'hasMany') {
|
|
6707
6724
|
relationships[field.name] = field;
|
|
6725
|
+
if (field.options?.as) {
|
|
6726
|
+
abstractImplementations.push(field);
|
|
6727
|
+
}
|
|
6728
|
+
}
|
|
6729
|
+
}
|
|
6730
|
+
|
|
6731
|
+
// This type may already be known as an abstract polymorphic type,
|
|
6732
|
+
// implemented by other concrete types via `options.as`, from before it
|
|
6733
|
+
// ever had a schema of its own (see `_registerAbstractTypeImplementation`).
|
|
6734
|
+
// Carry those previously-contributed fields forward so that registering
|
|
6735
|
+
// a "real" schema for the type - whenever that happens to occur - never
|
|
6736
|
+
// erases the relationships its implementers depend on.
|
|
6737
|
+
const implementerFields = this._abstractImplementerFields.get(schema.type);
|
|
6738
|
+
if (implementerFields) {
|
|
6739
|
+
for (const [name, contribution] of implementerFields) {
|
|
6740
|
+
const ownField = fields.get(name);
|
|
6741
|
+
if (!ownField) {
|
|
6742
|
+
fields.set(name, contribution.field);
|
|
6743
|
+
relationships[name] = contribution.field;
|
|
6744
|
+
}
|
|
6708
6745
|
}
|
|
6709
6746
|
}
|
|
6710
6747
|
const cacheFields = null;
|
|
@@ -6723,6 +6760,92 @@ class SchemaService {
|
|
|
6723
6760
|
internalSchema.cacheFields = getCacheFields(internalSchema);
|
|
6724
6761
|
}
|
|
6725
6762
|
this._schemas.set(schema.type, internalSchema);
|
|
6763
|
+
|
|
6764
|
+
// A relationship field's `as` option marks it as a valid concrete
|
|
6765
|
+
// implementer of an abstract polymorphic type (e.g. `as: 'commentable'`).
|
|
6766
|
+
// That abstract type may never be given its own schema by the user - it
|
|
6767
|
+
// may exist only to be implemented by concrete types like this one - or
|
|
6768
|
+
// it may already have (or later receive) a schema of its own, e.g. if it
|
|
6769
|
+
// turns out to also be a real, directly-resolvable resource. Either way,
|
|
6770
|
+
// ensure it has a schema with this field present, so that it behaves
|
|
6771
|
+
// like any other registered resource (`hasResource`, `fields`, etc.)
|
|
6772
|
+
// instead of requiring special-casing wherever abstract relationship
|
|
6773
|
+
// types are resolved.
|
|
6774
|
+
for (const field of abstractImplementations) {
|
|
6775
|
+
this._registerAbstractTypeImplementation(field, schema.type);
|
|
6776
|
+
}
|
|
6777
|
+
}
|
|
6778
|
+
|
|
6779
|
+
/** @internal */
|
|
6780
|
+
_registerAbstractTypeImplementation(field, implementer) {
|
|
6781
|
+
const abstractType = field.options.as;
|
|
6782
|
+
let implementerFields = this._abstractImplementerFields.get(abstractType);
|
|
6783
|
+
if (!implementerFields) {
|
|
6784
|
+
implementerFields = new Map();
|
|
6785
|
+
this._abstractImplementerFields.set(abstractType, implementerFields);
|
|
6786
|
+
}
|
|
6787
|
+
|
|
6788
|
+
// Unlike the original approach this replaced, `as` is *not* stripped here:
|
|
6789
|
+
// the field as synthesized onto the abstract type's own schema keeps
|
|
6790
|
+
// `options.as === abstractType`, redundant/self-referential as that is.
|
|
6791
|
+
// This keeps every contributor - implementers and the abstract type's
|
|
6792
|
+
// own schema alike - declaring the same thing, which is what
|
|
6793
|
+
// `assertConsistentAbstractFieldShape` checks, and it is also what lets
|
|
6794
|
+
// `assertPolymorphicType` (which reads a field's declared `as` off
|
|
6795
|
+
// whatever `schema.fields()` serves for its type) correctly permit the
|
|
6796
|
+
// abstract type itself to be pushed directly into this relationship.
|
|
6797
|
+
const abstractField = {
|
|
6798
|
+
...field
|
|
6799
|
+
};
|
|
6800
|
+
const contribution = {
|
|
6801
|
+
field: abstractField,
|
|
6802
|
+
source: implementer
|
|
6803
|
+
};
|
|
6804
|
+
|
|
6805
|
+
// all concrete implementations of an abstract type are required to
|
|
6806
|
+
// share the same shape for the field that implements it, so the first
|
|
6807
|
+
// one registered is as good a canonical source as any - but a later,
|
|
6808
|
+
// differently-shaped one is almost certainly a mistake rather than an
|
|
6809
|
+
// intentional override, so we catch it rather than silently ignoring it.
|
|
6810
|
+
const existingImplementer = implementerFields.get(field.name);
|
|
6811
|
+
if (existingImplementer) {
|
|
6812
|
+
return;
|
|
6813
|
+
}
|
|
6814
|
+
implementerFields.set(field.name, contribution);
|
|
6815
|
+
let abstractSchema = this._schemas.get(abstractType);
|
|
6816
|
+
if (!abstractSchema) {
|
|
6817
|
+
abstractSchema = {
|
|
6818
|
+
original: {
|
|
6819
|
+
legacy: true,
|
|
6820
|
+
identity: {
|
|
6821
|
+
kind: '@id',
|
|
6822
|
+
name: 'id'
|
|
6823
|
+
},
|
|
6824
|
+
type: abstractType,
|
|
6825
|
+
fields: []
|
|
6826
|
+
},
|
|
6827
|
+
finalized: true,
|
|
6828
|
+
fields: new Map(),
|
|
6829
|
+
cacheFields: new Map(),
|
|
6830
|
+
relationships: {},
|
|
6831
|
+
attributes: {},
|
|
6832
|
+
traits: new Set()
|
|
6833
|
+
};
|
|
6834
|
+
this._schemas.set(abstractType, abstractSchema);
|
|
6835
|
+
}
|
|
6836
|
+
const existingAbstractField = abstractSchema.fields.get(field.name);
|
|
6837
|
+
if (existingAbstractField) {
|
|
6838
|
+
return;
|
|
6839
|
+
}
|
|
6840
|
+
abstractSchema.fields.set(field.name, abstractField);
|
|
6841
|
+
abstractSchema.relationships[field.name] = abstractField;
|
|
6842
|
+
|
|
6843
|
+
// If the schema is mid-finalization (traits pending), finalizeResource
|
|
6844
|
+
// will recompute cacheFields from the current `fields` map anyway; avoid
|
|
6845
|
+
// doing so prematurely from a partially-resolved set of fields.
|
|
6846
|
+
if (abstractSchema.finalized) {
|
|
6847
|
+
abstractSchema.cacheFields = getCacheFields(abstractSchema);
|
|
6848
|
+
}
|
|
6726
6849
|
}
|
|
6727
6850
|
|
|
6728
6851
|
/**
|
|
@@ -7342,7 +7465,29 @@ globalThis.setWarpDriveIsMaybeMirage = setIsMaybeMirage;
|
|
|
7342
7465
|
*/
|
|
7343
7466
|
function useRecommendedStore(options, StoreKlass = Store) {
|
|
7344
7467
|
return class AppStore extends StoreKlass {
|
|
7345
|
-
|
|
7468
|
+
constructor(createArgs) {
|
|
7469
|
+
super(createArgs);
|
|
7470
|
+
// installed via defineProperty (rather than a class field/accessor) so that
|
|
7471
|
+
// this lazy override of the inherited `requestManager` field does not
|
|
7472
|
+
// conflict with the documented pattern of assigning it directly on
|
|
7473
|
+
// consumer-authored Store subclasses. The setter preserves the ability
|
|
7474
|
+
// to replace `requestManager` outright after construction.
|
|
7475
|
+
let requestManager;
|
|
7476
|
+
Object.defineProperty(this, 'requestManager', {
|
|
7477
|
+
configurable: true,
|
|
7478
|
+
enumerable: true,
|
|
7479
|
+
get: () => {
|
|
7480
|
+
if (!requestManager) {
|
|
7481
|
+
const handlers = typeof options.handlers === 'function' ? options.handlers(this) : options.handlers ?? [];
|
|
7482
|
+
requestManager = new RequestManager().use([...handlers, Fetch]).useCache(CacheHandler);
|
|
7483
|
+
}
|
|
7484
|
+
return requestManager;
|
|
7485
|
+
},
|
|
7486
|
+
set: value => {
|
|
7487
|
+
requestManager = value;
|
|
7488
|
+
}
|
|
7489
|
+
});
|
|
7490
|
+
}
|
|
7346
7491
|
lifetimes = options.policy ?? new DefaultCachePolicy({
|
|
7347
7492
|
apiCacheHardExpires: 15 * 60 * 1000,
|
|
7348
7493
|
// 15 minutes
|
package/dist/unpkg/prod/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { C as CacheHandler, F as Fetch, v as RequestManager, S as Store, r as cacheKeyFor, r as recordIdentifierFor, A as setIdentifierForgetMethod, y as setIdentifierGenerationMethod, B as setIdentifierResetMethod, z as setIdentifierUpdateMethod, D as setKeyInfoForResource, s as storeFor, x as useRecommendedStore } from "./index-
|
|
1
|
+
export { C as CacheHandler, F as Fetch, v as RequestManager, S as Store, r as cacheKeyFor, r as recordIdentifierFor, A as setIdentifierForgetMethod, y as setIdentifierGenerationMethod, B as setIdentifierResetMethod, z as setIdentifierUpdateMethod, D as setKeyInfoForResource, s as storeFor, x as useRecommendedStore } from "./index-C-AhVafS.js";
|
|
2
2
|
import './types/-private.js';
|
|
3
3
|
import "./-leaked-DgjQ5X55.js";
|
|
4
4
|
import './store.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { o as SchemaService, l as checkout, u as commit, p as fromIdentity, m as instantiateRecord, q as registerDerivations, t as teardownRecord, w as withDefaults } from "./index-
|
|
1
|
+
export { o as SchemaService, l as checkout, u as commit, p as fromIdentity, m as instantiateRecord, q as registerDerivations, t as teardownRecord, w as withDefaults } from "./index-C-AhVafS.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-DgjQ5X55.js";
|
|
4
4
|
import './types/-private.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import '../types/-private.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, r as recordIdentifierFor, h as setRecordIdentifier, s as storeFor } from "../index-
|
|
2
|
+
import { i as isResourceKey, c as coerceId } from "../index-C-AhVafS.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, r as recordIdentifierFor, h as setRecordIdentifier, s as storeFor } from "../index-C-AhVafS.js";
|
|
4
4
|
const TEXT_COLORS = {
|
|
5
5
|
TEXT: 'inherit',
|
|
6
6
|
notify: ['white', 'white', 'inherit', 'magenta', 'inherit'],
|