@warp-drive/schema-record 4.13.0-alpha.5 → 4.13.0-alpha.6
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/dist/index.js +160 -75
- package/dist/index.js.map +1 -1
- package/package.json +17 -16
- package/unstable-preview-types/-private/fields/managed-object.d.ts.map +1 -1
- package/unstable-preview-types/-private/hooks.d.ts.map +1 -1
- package/unstable-preview-types/-private/record.d.ts.map +1 -1
- package/unstable-preview-types/-private/schema.d.ts +12 -9
- package/unstable-preview-types/-private/schema.d.ts.map +1 -1
package/dist/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isResourceSchema } from '@warp-drive/core-types/schema/fields';
|
|
1
2
|
import { macroCondition, getGlobalConfig, dependencySatisfies, importSync } from '@embroider/macros';
|
|
2
3
|
import { SOURCE as SOURCE$1, fastPush, RelatedCollection, setRecordIdentifier, recordIdentifierFor } from '@ember-data/store/-private';
|
|
3
4
|
import { createSignal, subscribe, defineSignal, peekSignal, getSignal, Signals, addToTransaction, entangleSignal } from '@ember-data/tracking/-private';
|
|
@@ -307,7 +308,7 @@ class ManagedObject {
|
|
|
307
308
|
return self[prop];
|
|
308
309
|
}
|
|
309
310
|
if (prop === Symbol.toPrimitive) {
|
|
310
|
-
return null;
|
|
311
|
+
return () => null;
|
|
311
312
|
}
|
|
312
313
|
if (prop === Symbol.toStringTag) {
|
|
313
314
|
return `ManagedObject<${identifier.type}:${identifier.id} (${identifier.lid})>`;
|
|
@@ -322,7 +323,12 @@ class ManagedObject {
|
|
|
322
323
|
}
|
|
323
324
|
if (prop === 'toHTML') {
|
|
324
325
|
return function () {
|
|
325
|
-
return '<
|
|
326
|
+
return '<span>ManagedObject</span>';
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
if (prop === 'toJSON') {
|
|
330
|
+
return function () {
|
|
331
|
+
return structuredClone(self[SOURCE]);
|
|
326
332
|
};
|
|
327
333
|
}
|
|
328
334
|
if (_SIGNAL.shouldReset) {
|
|
@@ -661,6 +667,9 @@ const RecordSymbols = new Set(symbolList);
|
|
|
661
667
|
function isPathMatch(a, b) {
|
|
662
668
|
return a.length === b.length && a.every((v, i) => v === b[i]);
|
|
663
669
|
}
|
|
670
|
+
function isNonEnumerableProp(prop) {
|
|
671
|
+
return prop === 'constructor' || prop === 'prototype' || prop === '__proto__' || prop === 'toString' || prop === 'toJSON' || prop === 'toHTML' || typeof prop === 'symbol';
|
|
672
|
+
}
|
|
664
673
|
const Editables = new WeakMap();
|
|
665
674
|
class SchemaRecord {
|
|
666
675
|
constructor(store, identifier, Mode, isEmbedded = false, embeddedType = null, embeddedPath = null) {
|
|
@@ -676,22 +685,25 @@ class SchemaRecord {
|
|
|
676
685
|
this[Legacy] = Mode[Legacy] ?? false;
|
|
677
686
|
const schema = store.schema;
|
|
678
687
|
const cache = store.cache;
|
|
679
|
-
const identityField = schema.resource(
|
|
688
|
+
const identityField = schema.resource(isEmbedded ? {
|
|
689
|
+
type: embeddedType
|
|
690
|
+
} : identifier).identity;
|
|
691
|
+
const BoundFns = new Map();
|
|
680
692
|
this[EmbeddedType] = embeddedType;
|
|
681
693
|
this[EmbeddedPath] = embeddedPath;
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
type: embeddedType
|
|
686
|
-
});
|
|
687
|
-
} else {
|
|
688
|
-
fields = schema.fields(identifier);
|
|
689
|
-
}
|
|
694
|
+
const fields = isEmbedded ? schema.fields({
|
|
695
|
+
type: embeddedType
|
|
696
|
+
}) : schema.fields(identifier);
|
|
690
697
|
const signals = new Map();
|
|
691
698
|
this[Signals] = signals;
|
|
692
699
|
const proxy = new Proxy(this, {
|
|
693
700
|
ownKeys() {
|
|
694
|
-
|
|
701
|
+
const identityKey = identityField?.name;
|
|
702
|
+
const keys = Array.from(fields.keys());
|
|
703
|
+
if (identityKey) {
|
|
704
|
+
keys.unshift(identityKey);
|
|
705
|
+
}
|
|
706
|
+
return keys;
|
|
695
707
|
},
|
|
696
708
|
has(target, prop) {
|
|
697
709
|
if (prop === Destroy || prop === Checkout) {
|
|
@@ -700,10 +712,19 @@ class SchemaRecord {
|
|
|
700
712
|
return fields.has(prop);
|
|
701
713
|
},
|
|
702
714
|
getOwnPropertyDescriptor(target, prop) {
|
|
703
|
-
|
|
704
|
-
|
|
715
|
+
const schemaForField = prop === identityField?.name ? identityField : fields.get(prop);
|
|
716
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
717
|
+
if (!test) {
|
|
718
|
+
throw new Error(`No field named ${String(prop)} on ${identifier.type}`);
|
|
719
|
+
}
|
|
720
|
+
})(schemaForField) : {};
|
|
721
|
+
if (isNonEnumerableProp(prop)) {
|
|
722
|
+
return {
|
|
723
|
+
writable: false,
|
|
724
|
+
enumerable: false,
|
|
725
|
+
configurable: true
|
|
726
|
+
};
|
|
705
727
|
}
|
|
706
|
-
const schemaForField = fields.get(prop);
|
|
707
728
|
switch (schemaForField.kind) {
|
|
708
729
|
case 'derived':
|
|
709
730
|
return {
|
|
@@ -711,6 +732,12 @@ class SchemaRecord {
|
|
|
711
732
|
enumerable: true,
|
|
712
733
|
configurable: true
|
|
713
734
|
};
|
|
735
|
+
case '@id':
|
|
736
|
+
return {
|
|
737
|
+
writable: identifier.id === null,
|
|
738
|
+
enumerable: true,
|
|
739
|
+
configurable: true
|
|
740
|
+
};
|
|
714
741
|
case '@local':
|
|
715
742
|
case 'field':
|
|
716
743
|
case 'attribute':
|
|
@@ -728,28 +755,18 @@ class SchemaRecord {
|
|
|
728
755
|
enumerable: true,
|
|
729
756
|
configurable: true
|
|
730
757
|
};
|
|
758
|
+
default:
|
|
759
|
+
return {
|
|
760
|
+
writable: false,
|
|
761
|
+
enumerable: false,
|
|
762
|
+
configurable: false
|
|
763
|
+
};
|
|
731
764
|
}
|
|
732
765
|
},
|
|
733
766
|
get(target, prop, receiver) {
|
|
734
767
|
if (RecordSymbols.has(prop)) {
|
|
735
768
|
return target[prop];
|
|
736
769
|
}
|
|
737
|
-
if (prop === Symbol.toStringTag) {
|
|
738
|
-
return `SchemaRecord<${identifier.type}:${identifier.id} (${identifier.lid})>`;
|
|
739
|
-
}
|
|
740
|
-
if (prop === 'toString') {
|
|
741
|
-
return function () {
|
|
742
|
-
return `SchemaRecord<${identifier.type}:${identifier.id} (${identifier.lid})>`;
|
|
743
|
-
};
|
|
744
|
-
}
|
|
745
|
-
if (prop === 'toHTML') {
|
|
746
|
-
return function () {
|
|
747
|
-
return `<div>SchemaRecord<${identifier.type}:${identifier.id} (${identifier.lid})></div>`;
|
|
748
|
-
};
|
|
749
|
-
}
|
|
750
|
-
if (prop === Symbol.toPrimitive) {
|
|
751
|
-
return null;
|
|
752
|
-
}
|
|
753
770
|
|
|
754
771
|
// TODO make this a symbol
|
|
755
772
|
if (prop === '___notifications') {
|
|
@@ -765,18 +782,75 @@ class SchemaRecord {
|
|
|
765
782
|
if (IgnoredGlobalFields.has(prop)) {
|
|
766
783
|
return undefined;
|
|
767
784
|
}
|
|
785
|
+
|
|
786
|
+
/////////////////////////////////////////////////////////////
|
|
787
|
+
//// Note these bound function behaviors are essentially ////
|
|
788
|
+
//// built-in but overrideable derivations. ////
|
|
789
|
+
//// ////
|
|
790
|
+
//// The bar for this has to be "basic expectations of ////
|
|
791
|
+
/// an object" – very, very high ////
|
|
792
|
+
/////////////////////////////////////////////////////////////
|
|
793
|
+
|
|
794
|
+
if (prop === Symbol.toStringTag || prop === 'toString') {
|
|
795
|
+
let fn = BoundFns.get('toString');
|
|
796
|
+
if (!fn) {
|
|
797
|
+
fn = function () {
|
|
798
|
+
entangleSignal(signals, receiver, '@identity');
|
|
799
|
+
return `Record<${identifier.type}:${identifier.id} (${identifier.lid})>`;
|
|
800
|
+
};
|
|
801
|
+
BoundFns.set(prop, fn);
|
|
802
|
+
}
|
|
803
|
+
return fn;
|
|
804
|
+
}
|
|
805
|
+
if (prop === 'toHTML') {
|
|
806
|
+
let fn = BoundFns.get('toHTML');
|
|
807
|
+
if (!fn) {
|
|
808
|
+
fn = function () {
|
|
809
|
+
entangleSignal(signals, receiver, '@identity');
|
|
810
|
+
return `<span>Record<${identifier.type}:${identifier.id} (${identifier.lid})></span>`;
|
|
811
|
+
};
|
|
812
|
+
BoundFns.set(prop, fn);
|
|
813
|
+
}
|
|
814
|
+
return fn;
|
|
815
|
+
}
|
|
816
|
+
if (prop === 'toJSON') {
|
|
817
|
+
let fn = BoundFns.get('toJSON');
|
|
818
|
+
if (!fn) {
|
|
819
|
+
fn = function () {
|
|
820
|
+
const json = {};
|
|
821
|
+
for (const key in receiver) {
|
|
822
|
+
json[key] = receiver[key];
|
|
823
|
+
}
|
|
824
|
+
return json;
|
|
825
|
+
};
|
|
826
|
+
BoundFns.set(prop, fn);
|
|
827
|
+
}
|
|
828
|
+
return fn;
|
|
829
|
+
}
|
|
830
|
+
if (prop === Symbol.toPrimitive) return () => null;
|
|
831
|
+
if (prop === Symbol.iterator) {
|
|
832
|
+
let fn = BoundFns.get(Symbol.iterator);
|
|
833
|
+
if (!fn) {
|
|
834
|
+
fn = function* () {
|
|
835
|
+
for (const key in receiver) {
|
|
836
|
+
yield [key, receiver[key]];
|
|
837
|
+
}
|
|
838
|
+
};
|
|
839
|
+
BoundFns.set(Symbol.iterator, fn);
|
|
840
|
+
}
|
|
841
|
+
return fn;
|
|
842
|
+
}
|
|
768
843
|
if (prop === 'constructor') {
|
|
769
844
|
return SchemaRecord;
|
|
770
845
|
}
|
|
771
846
|
// too many things check for random symbols
|
|
772
|
-
if (typeof prop === 'symbol')
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
throw new Error(`No field named ${String(prop)} on ${type}`);
|
|
847
|
+
if (typeof prop === 'symbol') return undefined;
|
|
848
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
849
|
+
{
|
|
850
|
+
throw new Error(`No field named ${String(prop)} on ${isEmbedded ? embeddedType : identifier.type}`);
|
|
851
|
+
}
|
|
852
|
+
})() : {};
|
|
853
|
+
return undefined;
|
|
780
854
|
}
|
|
781
855
|
const field = maybeField.kind === 'alias' ? maybeField.options : maybeField;
|
|
782
856
|
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
@@ -804,49 +878,24 @@ class SchemaRecord {
|
|
|
804
878
|
return lastValue;
|
|
805
879
|
}
|
|
806
880
|
case 'field':
|
|
807
|
-
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
808
|
-
if (!test) {
|
|
809
|
-
throw new Error(`SchemaRecord.${field.name} is not available in legacy mode because it has type '${field.kind}'`);
|
|
810
|
-
}
|
|
811
|
-
})(!target[Legacy]) : {};
|
|
812
881
|
entangleSignal(signals, receiver, field.name);
|
|
813
882
|
return computeField(schema, cache, target, identifier, field, propArray, IS_EDITABLE);
|
|
814
883
|
case 'attribute':
|
|
815
884
|
entangleSignal(signals, receiver, field.name);
|
|
816
885
|
return computeAttribute(cache, identifier, prop, IS_EDITABLE);
|
|
817
886
|
case 'resource':
|
|
818
|
-
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
819
|
-
if (!test) {
|
|
820
|
-
throw new Error(`SchemaRecord.${field.name} is not available in legacy mode because it has type '${field.kind}'`);
|
|
821
|
-
}
|
|
822
|
-
})(!target[Legacy]) : {};
|
|
823
887
|
entangleSignal(signals, receiver, field.name);
|
|
824
888
|
return computeResource(store, cache, target, identifier, field, prop, IS_EDITABLE);
|
|
825
889
|
case 'derived':
|
|
826
890
|
return computeDerivation(schema, receiver, identifier, field, prop);
|
|
827
891
|
case 'schema-array':
|
|
828
892
|
case 'array':
|
|
829
|
-
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
830
|
-
if (!test) {
|
|
831
|
-
throw new Error(`SchemaRecord.${field.name} is not available in legacy mode because it has type '${field.kind}'`);
|
|
832
|
-
}
|
|
833
|
-
})(!target[Legacy]) : {};
|
|
834
893
|
entangleSignal(signals, receiver, field.name);
|
|
835
894
|
return computeArray(store, schema, cache, target, identifier, field, propArray, Mode[Editable], Mode[Legacy]);
|
|
836
895
|
case 'object':
|
|
837
|
-
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
838
|
-
if (!test) {
|
|
839
|
-
throw new Error(`SchemaRecord.${field.name} is not available in legacy mode because it has type '${field.kind}'`);
|
|
840
|
-
}
|
|
841
|
-
})(!target[Legacy]) : {};
|
|
842
896
|
entangleSignal(signals, receiver, field.name);
|
|
843
897
|
return computeObject(schema, cache, target, identifier, field, propArray, Mode[Editable], Mode[Legacy]);
|
|
844
898
|
case 'schema-object':
|
|
845
|
-
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
846
|
-
if (!test) {
|
|
847
|
-
throw new Error(`SchemaRecord.${field.name} is not available in legacy mode because it has type '${field.kind}'`);
|
|
848
|
-
}
|
|
849
|
-
})(!target[Legacy]) : {};
|
|
850
899
|
entangleSignal(signals, receiver, field.name);
|
|
851
900
|
// run transform, then use that value as the object to manage
|
|
852
901
|
return computeSchemaObject(store, cache, target, identifier, field, propArray, Mode[Legacy], Mode[Editable]);
|
|
@@ -1292,6 +1341,19 @@ class SchemaRecord {
|
|
|
1292
1341
|
break;
|
|
1293
1342
|
}
|
|
1294
1343
|
});
|
|
1344
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
1345
|
+
Object.defineProperty(this, '__SHOW_ME_THE_DATA_(debug mode only)__', {
|
|
1346
|
+
enumerable: false,
|
|
1347
|
+
configurable: true,
|
|
1348
|
+
get() {
|
|
1349
|
+
const data = {};
|
|
1350
|
+
for (const key of fields.keys()) {
|
|
1351
|
+
data[key] = proxy[key];
|
|
1352
|
+
}
|
|
1353
|
+
return data;
|
|
1354
|
+
}
|
|
1355
|
+
});
|
|
1356
|
+
}
|
|
1295
1357
|
return proxy;
|
|
1296
1358
|
}
|
|
1297
1359
|
[Destroy]() {
|
|
@@ -1328,7 +1390,13 @@ class SchemaRecord {
|
|
|
1328
1390
|
}
|
|
1329
1391
|
function instantiateRecord(store, identifier, createArgs) {
|
|
1330
1392
|
const schema = store.schema;
|
|
1331
|
-
const
|
|
1393
|
+
const resourceSchema = schema.resource(identifier);
|
|
1394
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1395
|
+
if (!test) {
|
|
1396
|
+
throw new Error(`Expected a resource schema`);
|
|
1397
|
+
}
|
|
1398
|
+
})(isResourceSchema(resourceSchema)) : {};
|
|
1399
|
+
const isLegacy = resourceSchema?.legacy ?? false;
|
|
1332
1400
|
const isEditable = isLegacy || store.cache.isNew(identifier);
|
|
1333
1401
|
const record = new SchemaRecord(store, identifier, {
|
|
1334
1402
|
[Editable]: isEditable,
|
|
@@ -1351,18 +1419,23 @@ function teardownRecord(record) {
|
|
|
1351
1419
|
record[Destroy]();
|
|
1352
1420
|
}
|
|
1353
1421
|
const Support = getOrSetGlobal('Support', new WeakMap());
|
|
1354
|
-
const
|
|
1422
|
+
const ConstructorField = {
|
|
1355
1423
|
type: '@constructor',
|
|
1356
1424
|
name: 'constructor',
|
|
1357
1425
|
kind: 'derived'
|
|
1358
|
-
}
|
|
1426
|
+
};
|
|
1427
|
+
const TypeField = {
|
|
1359
1428
|
type: '@identity',
|
|
1360
1429
|
name: '$type',
|
|
1361
1430
|
kind: 'derived',
|
|
1362
1431
|
options: {
|
|
1363
1432
|
key: 'type'
|
|
1364
1433
|
}
|
|
1365
|
-
}
|
|
1434
|
+
};
|
|
1435
|
+
const DefaultIdentityField = {
|
|
1436
|
+
name: 'id',
|
|
1437
|
+
kind: '@id'
|
|
1438
|
+
};
|
|
1366
1439
|
function _constructor(record) {
|
|
1367
1440
|
let state = Support.get(record);
|
|
1368
1441
|
if (!state) {
|
|
@@ -1372,17 +1445,29 @@ function _constructor(record) {
|
|
|
1372
1445
|
return state._constructor = state._constructor || {
|
|
1373
1446
|
name: `SchemaRecord<${recordIdentifierFor$1(record).type}>`,
|
|
1374
1447
|
get modelName() {
|
|
1375
|
-
|
|
1448
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1449
|
+
{
|
|
1450
|
+
throw new Error(`record.constructor.modelName is not available outside of legacy mode`);
|
|
1451
|
+
}
|
|
1452
|
+
})() : {};
|
|
1453
|
+
return undefined;
|
|
1376
1454
|
}
|
|
1377
1455
|
};
|
|
1378
1456
|
}
|
|
1379
1457
|
_constructor[Type] = '@constructor';
|
|
1458
|
+
|
|
1459
|
+
/**
|
|
1460
|
+
* Utility for constructing a ResourceSchema with the recommended fields
|
|
1461
|
+
* for the Polaris experience.
|
|
1462
|
+
*/
|
|
1380
1463
|
function withDefaults(schema) {
|
|
1381
|
-
schema.identity = schema.identity ||
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1464
|
+
schema.identity = schema.identity || DefaultIdentityField;
|
|
1465
|
+
|
|
1466
|
+
// because fields gets iterated in definition order,
|
|
1467
|
+
// we add TypeField to the beginning so that it will
|
|
1468
|
+
// appear right next to the identity field
|
|
1469
|
+
schema.fields.unshift(TypeField);
|
|
1470
|
+
schema.fields.push(ConstructorField);
|
|
1386
1471
|
return schema;
|
|
1387
1472
|
}
|
|
1388
1473
|
function fromIdentity(record, options, key) {
|
|
@@ -1534,7 +1619,7 @@ class SchemaService {
|
|
|
1534
1619
|
relationships[field.name] = field;
|
|
1535
1620
|
}
|
|
1536
1621
|
});
|
|
1537
|
-
const traits = new Set(schema.traits);
|
|
1622
|
+
const traits = new Set(isResourceSchema(schema) ? schema.traits : []);
|
|
1538
1623
|
traits.forEach(trait => {
|
|
1539
1624
|
this._traits.add(trait);
|
|
1540
1625
|
});
|