@warp-drive/core 5.7.0-alpha.4 → 5.7.0-alpha.5
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/reactive/-private/default-mode.d.ts +3 -1
- package/declarations/reactive/-private/kind/array-field.d.ts +2 -7
- package/declarations/reactive/-private/schema.d.ts +1 -1
- package/declarations/reactive.d.ts +1 -0
- package/declarations/store/-types/q/schema-service.d.ts +1 -1
- package/declarations/types/schema/fields.d.ts +39 -8
- package/dist/graph/-private.js +1 -1
- package/dist/{handler-Gm-q2q05.js → handler-SdXlte1w.js} +1 -1
- package/dist/index.js +2 -2
- package/dist/reactive.js +324 -222
- package/dist/{request-state-Bj0zUw2r.js → request-state-CeN66aML.js} +7 -10
- package/dist/store/-private.js +2 -2
- package/dist/types/-private.js +1 -1
- package/dist/types/schema/fields.js +4 -2
- package/package.json +3 -3
|
@@ -20,17 +20,19 @@ export interface BaseContext {
|
|
|
20
20
|
export interface ResourceContext extends BaseContext {
|
|
21
21
|
path: null;
|
|
22
22
|
field: null;
|
|
23
|
+
value: null;
|
|
23
24
|
}
|
|
24
25
|
export interface ObjectContext extends BaseContext {
|
|
25
26
|
path: string[];
|
|
26
27
|
field: SchemaObjectField | SchemaArrayField;
|
|
28
|
+
value: string;
|
|
27
29
|
}
|
|
28
30
|
export interface KindContext<T extends FieldSchema | IdentityField | HashField> extends BaseContext {
|
|
29
31
|
path: string[];
|
|
30
32
|
field: T;
|
|
33
|
+
value: unknown;
|
|
31
34
|
record: ReactiveResource;
|
|
32
35
|
signals: SignalStore;
|
|
33
|
-
value: unknown;
|
|
34
36
|
}
|
|
35
37
|
export interface KindImpl<T extends FieldSchema | IdentityField | HashField> {
|
|
36
38
|
/**
|
|
@@ -1,9 +1,4 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { ArrayField, FieldSchema, SchemaArrayField } from "../../../types/schema/fields.js";
|
|
1
|
+
import type { ArrayField, SchemaArrayField } from "../../../types/schema/fields.js";
|
|
3
2
|
import type { KindContext } from "../default-mode.js";
|
|
4
|
-
import { ManagedArray } from "../fields/managed-array.js";
|
|
5
|
-
import type { ReactiveResource } from "../record.js";
|
|
6
|
-
export declare const ManagedArrayMap: Map<ReactiveResource, Map<string, ManagedArray | ManyArray>>;
|
|
7
|
-
export declare function peekManagedArray(record: ReactiveResource, field: FieldSchema): ManyArray | ManagedArray | undefined;
|
|
8
3
|
export declare function getArrayField(context: KindContext<ArrayField | SchemaArrayField>): unknown;
|
|
9
|
-
export declare function setArrayField(context: KindContext<ArrayField
|
|
4
|
+
export declare function setArrayField(context: KindContext<ArrayField>): boolean;
|
|
@@ -271,7 +271,7 @@ export declare class SchemaService implements SchemaServiceInterface {
|
|
|
271
271
|
CAUTION_MEGA_DANGER_ZONE_resourceExtensions(resource: StableRecordIdentifier | {
|
|
272
272
|
type: string;
|
|
273
273
|
}): null | ProcessedExtension["features"];
|
|
274
|
-
CAUTION_MEGA_DANGER_ZONE_objectExtensions(field: ExtensibleField): null | ProcessedExtension["features"];
|
|
274
|
+
CAUTION_MEGA_DANGER_ZONE_objectExtensions(field: ExtensibleField, resolvedType: string | null): null | ProcessedExtension["features"];
|
|
275
275
|
CAUTION_MEGA_DANGER_ZONE_arrayExtensions(field: ExtensibleField): null | ProcessedExtension["features"];
|
|
276
276
|
CAUTION_MEGA_DANGER_ZONE_hasExtension(ext: {
|
|
277
277
|
kind: "object" | "array";
|
|
@@ -2,3 +2,4 @@ export { instantiateRecord, teardownRecord } from "./reactive/-private/hooks.js"
|
|
|
2
2
|
export { type CAUTION_MEGA_DANGER_ZONE_Extension, type ProcessedExtension, type ExtensionDef, type Transformation, SchemaService, withDefaults, fromIdentity, registerDerivations } from "./reactive/-private/schema.js";
|
|
3
3
|
export { type ReactiveResource } from "./reactive/-private/record.js";
|
|
4
4
|
export { Checkout } from "./reactive/-private/symbols.js";
|
|
5
|
+
export { type ReactiveDocument } from "./reactive/-private/document.js";
|
|
@@ -358,7 +358,7 @@ export interface SchemaService {
|
|
|
358
358
|
*
|
|
359
359
|
* @public
|
|
360
360
|
*/
|
|
361
|
-
CAUTION_MEGA_DANGER_ZONE_objectExtensions?(field: ExtensibleField): null | ProcessedExtension["features"];
|
|
361
|
+
CAUTION_MEGA_DANGER_ZONE_objectExtensions?(field: ExtensibleField, resolvedType: string | null): null | ProcessedExtension["features"];
|
|
362
362
|
/**
|
|
363
363
|
* Retrieve the extension map for an array field
|
|
364
364
|
*
|
|
@@ -294,7 +294,7 @@ export interface IdentityField {
|
|
|
294
294
|
* perform those itself.
|
|
295
295
|
*
|
|
296
296
|
* A schema-array can declare its "key" value to be `@hash` if
|
|
297
|
-
*
|
|
297
|
+
* the schema-objects it contains have such a field.
|
|
298
298
|
*
|
|
299
299
|
* Only one hash field is permittable per schema-object, and
|
|
300
300
|
* it should be placed in the `ResourceSchema`'s `@id` field
|
|
@@ -476,11 +476,13 @@ export interface ObjectField {
|
|
|
476
476
|
/**
|
|
477
477
|
* Represents a field whose value is an object
|
|
478
478
|
* with a well-defined structure described by
|
|
479
|
-
* a non-resource schema.
|
|
479
|
+
* a schema-object (a non-resource schema).
|
|
480
480
|
*
|
|
481
481
|
* If the object's structure is not well-defined,
|
|
482
482
|
* use 'object' instead.
|
|
483
483
|
*
|
|
484
|
+
* By default, a SchemaObject within
|
|
485
|
+
*
|
|
484
486
|
* @public
|
|
485
487
|
*/
|
|
486
488
|
export interface SchemaObjectField {
|
|
@@ -520,12 +522,19 @@ export interface SchemaObjectField {
|
|
|
520
522
|
*/
|
|
521
523
|
sourceKey?: string;
|
|
522
524
|
/**
|
|
525
|
+
* If the field is not polymorphic:
|
|
526
|
+
*
|
|
523
527
|
* The name of the ObjectSchema that describes the
|
|
524
528
|
* structure of the object.
|
|
525
529
|
*
|
|
530
|
+
* If the field is polymorphic:
|
|
531
|
+
*
|
|
532
|
+
* The name of the hashFn to use to extract
|
|
533
|
+
* the type from the contained value or null.
|
|
534
|
+
*
|
|
526
535
|
* @public
|
|
527
536
|
*/
|
|
528
|
-
type: string;
|
|
537
|
+
type: string | null;
|
|
529
538
|
/**
|
|
530
539
|
* Options for configuring the behavior of the
|
|
531
540
|
* SchemaObject.
|
|
@@ -562,7 +571,15 @@ export interface SchemaObjectField {
|
|
|
562
571
|
* If the SchemaObject is Polymorphic, the key on the raw cache data to use
|
|
563
572
|
* as the "resource-type" value for the schema-object.
|
|
564
573
|
*
|
|
565
|
-
*
|
|
574
|
+
* The default is `'type'`.
|
|
575
|
+
*
|
|
576
|
+
* Valid options are:
|
|
577
|
+
*
|
|
578
|
+
* - `'@hash'` : will lookup the `@hash` function specified by
|
|
579
|
+
* SchemaObjectField.type and use it to calculate the type for each value.
|
|
580
|
+
* - \<field-name> (string) : the name of a field to use as the key, only GenericFields (kind `field`)
|
|
581
|
+
* Are valid field names for this purpose. The cache state without transforms applied will be
|
|
582
|
+
* used when comparing values.
|
|
566
583
|
*
|
|
567
584
|
* @public
|
|
568
585
|
*/
|
|
@@ -694,12 +711,19 @@ export interface SchemaArrayField {
|
|
|
694
711
|
*/
|
|
695
712
|
sourceKey?: string;
|
|
696
713
|
/**
|
|
714
|
+
* If the SchemaArray is not polymorphic:
|
|
715
|
+
*
|
|
697
716
|
* The name of the ObjectSchema that describes the
|
|
698
717
|
* structure of the objects in the array.
|
|
699
718
|
*
|
|
719
|
+
* If the SchemaArray is polymorphic:
|
|
720
|
+
*
|
|
721
|
+
* The name of the hashFn to use to extract
|
|
722
|
+
* the type from contained members or null.
|
|
723
|
+
*
|
|
700
724
|
* @public
|
|
701
725
|
*/
|
|
702
|
-
type: string;
|
|
726
|
+
type: string | null;
|
|
703
727
|
/**
|
|
704
728
|
* Options for configuring the behavior of the
|
|
705
729
|
* SchemaArray.
|
|
@@ -713,13 +737,13 @@ export interface SchemaArrayField {
|
|
|
713
737
|
*
|
|
714
738
|
* Valid options are:
|
|
715
739
|
*
|
|
716
|
-
* - `'@identity'`
|
|
740
|
+
* - `'@identity'`(default) : the cached object's referential identity will be used.
|
|
717
741
|
* This may result in significant instability when resource data is updated from the API
|
|
718
742
|
* - `'@index'` : the cached object's index in the array will be used.
|
|
719
743
|
* This is only a good choice for arrays that rarely if ever change membership
|
|
720
744
|
* - `'@hash'` : will lookup the `@hash` function supplied in the ResourceSchema for
|
|
721
745
|
* The contained schema-object and use the computed result to determine and compare identity.
|
|
722
|
-
* - \<field-name> (string)
|
|
746
|
+
* - \<field-name> (string) : the name of a field to use as the key, only GenericFields (kind `field`)
|
|
723
747
|
* Are valid field names for this purpose. The cache state without transforms applied will be
|
|
724
748
|
* used when comparing values. The field value should be unique enough to guarantee two schema-objects
|
|
725
749
|
* of the same type will not collide.
|
|
@@ -791,8 +815,15 @@ export interface SchemaArrayField {
|
|
|
791
815
|
* If the SchemaArray is Polymorphic, the key on the raw cache data to use
|
|
792
816
|
* as the "resource-type" value for the schema-object.
|
|
793
817
|
*
|
|
794
|
-
*
|
|
818
|
+
* The default is `'type'`.
|
|
795
819
|
*
|
|
820
|
+
* Valid options are:
|
|
821
|
+
*
|
|
822
|
+
* - `'@hash'` : will lookup the `@hash` function specified by
|
|
823
|
+
* SchemaArrayField.type and use it to calculate the type for each value.
|
|
824
|
+
* - \<field-name> (string) : the name of a field to use as the key, only GenericFields (kind `field`)
|
|
825
|
+
* Are valid field names for this purpose. The cache state without transforms applied will be
|
|
826
|
+
* used when comparing values.
|
|
796
827
|
*/
|
|
797
828
|
type?: string;
|
|
798
829
|
};
|
package/dist/graph/-private.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { deprecate, warn } from '@ember/debug';
|
|
2
|
-
import { p as peekCache } from "../request-state-
|
|
2
|
+
import { p as peekCache } from "../request-state-CeN66aML.js";
|
|
3
3
|
import '../types/request.js';
|
|
4
4
|
import { macroCondition, getGlobalConfig } from '@embroider/macros';
|
|
5
5
|
import '../utils/string.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { K as ReactiveDocument } from "./request-state-
|
|
1
|
+
import { K as ReactiveDocument } from "./request-state-CeN66aML.js";
|
|
2
2
|
import { SkipCache, EnableHydration } from './types/request.js';
|
|
3
3
|
import { macroCondition, getGlobalConfig } from '@embroider/macros';
|
|
4
4
|
const MUTATION_OPS = new Set(['createRecord', 'updateRecord', 'deleteRecord']);
|
package/dist/index.js
CHANGED
|
@@ -3,8 +3,8 @@ import { a as cloneResponseProperties, I as IS_CACHE_HANDLER, b as assertValidRe
|
|
|
3
3
|
import { macroCondition, getGlobalConfig } from '@embroider/macros';
|
|
4
4
|
import { w as waitFor } from "./configure-B48bFHOl.js";
|
|
5
5
|
import { peekUniversalTransient, setUniversalTransient } from './types/-private.js';
|
|
6
|
-
export { S as Store, r as recordIdentifierFor, O as setIdentifierForgetMethod, L as setIdentifierGenerationMethod, P as setIdentifierResetMethod, N as setIdentifierUpdateMethod, Q as setKeyInfoForResource, s as storeFor } from "./request-state-
|
|
7
|
-
export { C as CacheHandler } from "./handler-
|
|
6
|
+
export { S as Store, r as recordIdentifierFor, O as setIdentifierForgetMethod, L as setIdentifierGenerationMethod, P as setIdentifierResetMethod, N as setIdentifierUpdateMethod, Q as setKeyInfoForResource, s as storeFor } from "./request-state-CeN66aML.js";
|
|
7
|
+
export { C as CacheHandler } from "./handler-SdXlte1w.js";
|
|
8
8
|
import '@ember/debug';
|
|
9
9
|
import './utils/string.js';
|
|
10
10
|
|
package/dist/reactive.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { isResourceSchema } from './types/schema/fields.js';
|
|
2
|
-
import { F as withSignalStore, T as isExtensionProp, U as performExtensionSet, H as consumeInternalSignal, V as performArrayExtensionGet, x as entangleSignal, d as SOURCE$1, f as fastPush, l as RelatedCollection, J as getOrCreateInternalSignal, G as notifyInternalSignal, W as performObjectExtensionGet, y as defineSignal, B as Signals, h as setRecordIdentifier, r as recordIdentifierFor } from "./request-state-
|
|
2
|
+
import { F as withSignalStore, T as isExtensionProp, U as performExtensionSet, H as consumeInternalSignal, V as performArrayExtensionGet, x as entangleSignal, E as peekInternalSignal, d as SOURCE$1, f as fastPush, l as RelatedCollection, J as getOrCreateInternalSignal, G as notifyInternalSignal, W as performObjectExtensionGet, y as defineSignal, B as Signals, h as setRecordIdentifier, r as recordIdentifierFor } from "./request-state-CeN66aML.js";
|
|
3
3
|
import { EnableHydration, STRUCTURED } from './types/request.js';
|
|
4
4
|
import { macroCondition, getGlobalConfig } from '@embroider/macros';
|
|
5
5
|
import { warn, deprecate } from '@ember/debug';
|
|
6
6
|
import './utils/string.js';
|
|
7
7
|
import { A as ARRAY_SIGNAL, O as OBJECT_SIGNAL, c as createMemo } from "./configure-B48bFHOl.js";
|
|
8
8
|
import { RecordStore, Type } from './types/symbols.js';
|
|
9
|
+
import { S as SOURCE, E as Editable, L as Legacy, D as Destroy, I as Identifier, P as Parent, a as EmbeddedPath, C as Checkout, b as EmbeddedField } from "./symbols-SIstXMLI.js";
|
|
9
10
|
import { getOrSetGlobal } from './types/-private.js';
|
|
10
|
-
import { S as SOURCE, E as Editable, L as Legacy, I as Identifier, P as Parent, a as EmbeddedPath, D as Destroy, C as Checkout, b as EmbeddedField } from "./symbols-SIstXMLI.js";
|
|
11
11
|
import './index.js';
|
|
12
12
|
function getAliasField(context) {
|
|
13
13
|
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
@@ -78,6 +78,9 @@ class ManagedArray {
|
|
|
78
78
|
this[Legacy] = context.legacy;
|
|
79
79
|
const schema = context.store.schema;
|
|
80
80
|
const cache = context.store.cache;
|
|
81
|
+
const {
|
|
82
|
+
field
|
|
83
|
+
} = context;
|
|
81
84
|
const signals = withSignalStore(this);
|
|
82
85
|
let _SIGNAL = null;
|
|
83
86
|
const boundFns = new Map();
|
|
@@ -85,8 +88,9 @@ class ManagedArray {
|
|
|
85
88
|
this.path = context.path;
|
|
86
89
|
this.owner = owner;
|
|
87
90
|
let transaction = false;
|
|
88
|
-
const
|
|
89
|
-
|
|
91
|
+
const KeyMode = field.options?.key ?? '@identity';
|
|
92
|
+
// listener.
|
|
93
|
+
const RefStorage = KeyMode === '@identity' ? WeakMap :
|
|
90
94
|
// CAUTION CAUTION CAUTION
|
|
91
95
|
// this is a pile of lies
|
|
92
96
|
// the Map is Map<string, WeakRef<ReactiveResource>>
|
|
@@ -94,8 +98,8 @@ class ManagedArray {
|
|
|
94
98
|
// internal to a method like ours without us duplicating the code
|
|
95
99
|
// into two separate methods.
|
|
96
100
|
Map;
|
|
97
|
-
const ManagedRecordRefs =
|
|
98
|
-
const extensions = context.legacy ? schema.CAUTION_MEGA_DANGER_ZONE_arrayExtensions(
|
|
101
|
+
const ManagedRecordRefs = field.kind === 'schema-array' ? new RefStorage() : null;
|
|
102
|
+
const extensions = context.legacy ? schema.CAUTION_MEGA_DANGER_ZONE_arrayExtensions(field) : null;
|
|
99
103
|
const proxy = new Proxy(this[SOURCE], {
|
|
100
104
|
get(target, prop, receiver) {
|
|
101
105
|
if (prop === ARRAY_SIGNAL) {
|
|
@@ -121,14 +125,72 @@ class ManagedArray {
|
|
|
121
125
|
}
|
|
122
126
|
if (prop === '[]') return consumeInternalSignal(_SIGNAL), receiver;
|
|
123
127
|
if (index !== null) {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
128
|
+
if (!transaction) {
|
|
129
|
+
consumeInternalSignal(_SIGNAL);
|
|
130
|
+
}
|
|
131
|
+
const rawValue = target[index];
|
|
132
|
+
if (field.kind === 'array') {
|
|
133
|
+
if (field.type) {
|
|
134
|
+
const transform = schema.transformation(field);
|
|
135
|
+
return transform.hydrate(rawValue, field.options ?? null, self.owner);
|
|
136
|
+
}
|
|
137
|
+
return rawValue;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* When the array is polymorphic, we need to determine the real type
|
|
142
|
+
* in order to apply the correct identity as schema-object identity
|
|
143
|
+
* is only required to be unique by type
|
|
144
|
+
*/
|
|
145
|
+
let objectType;
|
|
146
|
+
if (field.options?.polymorphic) {
|
|
147
|
+
const typePath = field.options.type ?? 'type';
|
|
148
|
+
// if we are polymorphic, then context.field.options.type will
|
|
149
|
+
// either specify a path on the rawValue to use as the type, defaulting to "type" or
|
|
150
|
+
// the special string "@hash" which tells us to treat field.type as a hashFn name with which
|
|
151
|
+
// to calc the type.
|
|
152
|
+
if (typePath === '@hash') {
|
|
153
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
154
|
+
if (!test) {
|
|
155
|
+
throw new Error(`Expected the field to define a hashFn as its type`);
|
|
156
|
+
}
|
|
157
|
+
})(field.type) : {};
|
|
158
|
+
const hashFn = schema.hashFn({
|
|
159
|
+
type: field.type
|
|
160
|
+
});
|
|
161
|
+
// TODO consider if there are better options and name args we could provide.
|
|
162
|
+
objectType = hashFn(rawValue, null, null);
|
|
163
|
+
} else {
|
|
164
|
+
objectType = rawValue[typePath];
|
|
165
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
166
|
+
if (!test) {
|
|
167
|
+
throw new Error(`Expected the type path for the field to be a value on the raw object`);
|
|
168
|
+
}
|
|
169
|
+
})(typePath && objectType && typeof objectType === 'string') : {};
|
|
170
|
+
}
|
|
171
|
+
} else {
|
|
172
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
173
|
+
if (!test) {
|
|
174
|
+
throw new Error(`A non-polymorphic SchemaArrayField must provide a SchemaObject type in its definition`);
|
|
175
|
+
}
|
|
176
|
+
})(field.type) : {};
|
|
177
|
+
objectType = field.type;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* When KeyMode=@hash the ReactiveResource is keyed into
|
|
182
|
+
* ManagedRecordRefs by the return value of @hash on the rawValue.
|
|
183
|
+
*
|
|
184
|
+
* This means that we could find a way to only recompute the identity
|
|
185
|
+
* when ARRAY_SIGNAL is dirty if hash performance becomes a bottleneck.
|
|
186
|
+
*/
|
|
187
|
+
let schemaObjectKeyValue;
|
|
188
|
+
if (KeyMode === '@hash') {
|
|
127
189
|
const hashField = schema.resource({
|
|
128
|
-
type:
|
|
190
|
+
type: objectType
|
|
129
191
|
}).identity;
|
|
130
192
|
const hashFn = schema.hashFn(hashField);
|
|
131
|
-
|
|
193
|
+
schemaObjectKeyValue = hashFn(rawValue, hashField.options ?? null, hashField.name);
|
|
132
194
|
} else {
|
|
133
195
|
// if mode is not @identity or @index, then access the key path.
|
|
134
196
|
// we should assert that `mode` is a string
|
|
@@ -136,74 +198,78 @@ class ManagedArray {
|
|
|
136
198
|
// and, we likely should lookup the associated field and throw an error IF
|
|
137
199
|
// the given field does not exist OR
|
|
138
200
|
// the field is anything other than a GenericField or LegacyAttributeField.
|
|
139
|
-
if (
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
}
|
|
161
|
-
if (context.field.kind === 'schema-array') {
|
|
162
|
-
if (!transaction) {
|
|
163
|
-
consumeInternalSignal(_SIGNAL);
|
|
164
|
-
}
|
|
165
|
-
if (val) {
|
|
166
|
-
const recordRef = ManagedRecordRefs.get(val);
|
|
167
|
-
let record = recordRef?.deref();
|
|
168
|
-
if (!record) {
|
|
169
|
-
const recordPath = context.path.slice();
|
|
170
|
-
// this is a dirty lie since path is string[] but really we
|
|
171
|
-
// should change the types for paths to `Array<string | number>`
|
|
172
|
-
// TODO we should allow the schema for the field to define a "key"
|
|
173
|
-
// for stability. Default should be `@identity` which means that
|
|
174
|
-
// same object reference from cache should result in same ReactiveResource
|
|
175
|
-
// embedded object.
|
|
176
|
-
recordPath.push(index);
|
|
177
|
-
record = new ReactiveResource({
|
|
178
|
-
store: context.store,
|
|
179
|
-
resourceKey: context.resourceKey,
|
|
180
|
-
modeName: context.modeName,
|
|
181
|
-
legacy: context.legacy,
|
|
182
|
-
editable: context.editable,
|
|
183
|
-
path: recordPath,
|
|
184
|
-
field: context.field
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
// if mode is not @identity or @index, then access the key path now
|
|
188
|
-
// to determine the key value.
|
|
189
|
-
// chris says we can implement this as a special kind `@hash` which
|
|
190
|
-
// would be a function that only has access to the cache value and not
|
|
191
|
-
// the record itself, so derivation is possible but intentionally limited
|
|
192
|
-
// and non-reactive?
|
|
193
|
-
ManagedRecordRefs.set(val, new WeakRef(record));
|
|
201
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
202
|
+
const isPathKeyMode = KeyMode !== '@identity' && KeyMode !== '@index';
|
|
203
|
+
if (isPathKeyMode) {
|
|
204
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
205
|
+
if (!test) {
|
|
206
|
+
throw new Error('mode must be a string');
|
|
207
|
+
}
|
|
208
|
+
})(typeof KeyMode === 'string' && KeyMode !== '') : {};
|
|
209
|
+
const modeField = schema.fields({
|
|
210
|
+
type: objectType
|
|
211
|
+
}).get(KeyMode);
|
|
212
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
213
|
+
if (!test) {
|
|
214
|
+
throw new Error('field must exist in schema');
|
|
215
|
+
}
|
|
216
|
+
})(modeField) : {};
|
|
217
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
218
|
+
if (!test) {
|
|
219
|
+
throw new Error('field must be a GenericField or LegacyAttributeField');
|
|
220
|
+
}
|
|
221
|
+
})(modeField.kind === 'field' || modeField.kind === 'attribute') : {};
|
|
194
222
|
}
|
|
195
|
-
return record;
|
|
196
223
|
}
|
|
197
|
-
|
|
224
|
+
schemaObjectKeyValue = KeyMode === '@identity' ? rawValue : KeyMode === '@index' ? index : rawValue[KeyMode];
|
|
198
225
|
}
|
|
199
|
-
if (!
|
|
200
|
-
|
|
226
|
+
if (!schemaObjectKeyValue) {
|
|
227
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
228
|
+
{
|
|
229
|
+
throw new Error(`Unexpected out of bounds access on SchemaArray`);
|
|
230
|
+
}
|
|
231
|
+
})() : {};
|
|
232
|
+
return undefined;
|
|
201
233
|
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
234
|
+
const recordRef = ManagedRecordRefs.get(schemaObjectKeyValue);
|
|
235
|
+
const record = recordRef?.value.deref();
|
|
236
|
+
|
|
237
|
+
// confirm the type and key still match
|
|
238
|
+
if (record && recordRef.type === objectType && recordRef.identity === schemaObjectKeyValue) {
|
|
239
|
+
if (recordRef.index !== index) {
|
|
240
|
+
recordRef.index = index;
|
|
241
|
+
recordRef.context.path[recordRef.context.path.length - 1] = index;
|
|
242
|
+
}
|
|
243
|
+
return record;
|
|
244
|
+
} else if (record) {
|
|
245
|
+
// TODO schedule idle once we can
|
|
246
|
+
void Promise.resolve().then(() => {
|
|
247
|
+
record[Destroy]();
|
|
248
|
+
});
|
|
205
249
|
}
|
|
206
|
-
|
|
250
|
+
const recordPath = context.path.slice();
|
|
251
|
+
// this is a dirty lie since path is string[] but really we
|
|
252
|
+
// should change the types for paths to `Array<string | number>`
|
|
253
|
+
recordPath.push(index);
|
|
254
|
+
const objectContext = {
|
|
255
|
+
store: context.store,
|
|
256
|
+
resourceKey: context.resourceKey,
|
|
257
|
+
modeName: context.modeName,
|
|
258
|
+
legacy: context.legacy,
|
|
259
|
+
editable: context.editable,
|
|
260
|
+
path: recordPath,
|
|
261
|
+
field: field,
|
|
262
|
+
value: objectType
|
|
263
|
+
};
|
|
264
|
+
const schemaObject = new ReactiveResource(objectContext);
|
|
265
|
+
ManagedRecordRefs.set(schemaObjectKeyValue, {
|
|
266
|
+
type: objectType,
|
|
267
|
+
identity: schemaObjectKeyValue,
|
|
268
|
+
index,
|
|
269
|
+
context: objectContext,
|
|
270
|
+
value: new WeakRef(schemaObject)
|
|
271
|
+
});
|
|
272
|
+
return schemaObject;
|
|
207
273
|
}
|
|
208
274
|
if (isArrayGetter(prop)) {
|
|
209
275
|
let fn = boundFns.get(prop);
|
|
@@ -274,18 +340,18 @@ class ManagedArray {
|
|
|
274
340
|
}
|
|
275
341
|
const reflect = Reflect.set(target, prop, value, receiver);
|
|
276
342
|
if (reflect) {
|
|
277
|
-
if (!
|
|
343
|
+
if (!field.type) {
|
|
278
344
|
cache.setAttr(context.resourceKey, context.path, self[SOURCE]);
|
|
279
345
|
_SIGNAL.isStale = true;
|
|
280
346
|
return true;
|
|
281
347
|
}
|
|
282
348
|
let rawValue = self[SOURCE];
|
|
283
|
-
if (
|
|
284
|
-
const transform = schema.transformation(
|
|
349
|
+
if (field.kind !== 'schema-array') {
|
|
350
|
+
const transform = schema.transformation(field);
|
|
285
351
|
if (!transform) {
|
|
286
|
-
throw new Error(`No '${
|
|
352
|
+
throw new Error(`No '${field.type}' transform defined for use by ${context.resourceKey.type}.${String(prop)}`);
|
|
287
353
|
}
|
|
288
|
-
rawValue = self[SOURCE].map(item => transform.serialize(item,
|
|
354
|
+
rawValue = self[SOURCE].map(item => transform.serialize(item, field.options ?? null, self.owner));
|
|
289
355
|
}
|
|
290
356
|
cache.setAttr(context.resourceKey, context.path, rawValue);
|
|
291
357
|
_SIGNAL.isStale = true;
|
|
@@ -324,29 +390,17 @@ const desc = {
|
|
|
324
390
|
};
|
|
325
391
|
// compat(desc);
|
|
326
392
|
Object.defineProperty(ManagedArray.prototype, '[]', desc);
|
|
327
|
-
const ManagedArrayMap = getOrSetGlobal('ManagedArrayMap', new Map());
|
|
328
|
-
function peekManagedArray(record, field) {
|
|
329
|
-
const managedArrayMapForRecord = ManagedArrayMap.get(record);
|
|
330
|
-
if (managedArrayMapForRecord) {
|
|
331
|
-
return managedArrayMapForRecord.get(field.name);
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
393
|
function getArrayField(context) {
|
|
335
|
-
entangleSignal(context.signals, context.record, context.path.at(-1), null);
|
|
394
|
+
const signal = entangleSignal(context.signals, context.record, context.path.at(-1), null);
|
|
336
395
|
// the thing we hand out needs to know its owner and path in a private manner
|
|
337
396
|
// its "address" is the parent identifier (identifier) + field name (field.name)
|
|
338
397
|
// in the nested object case field name here is the full dot path from root resource to this value
|
|
339
398
|
// its "key" is the field on the parent record
|
|
340
399
|
// its "owner" is the parent record
|
|
341
400
|
const {
|
|
342
|
-
field,
|
|
343
401
|
record
|
|
344
402
|
} = context;
|
|
345
|
-
|
|
346
|
-
let managedArray;
|
|
347
|
-
if (managedArrayMapForRecord) {
|
|
348
|
-
managedArray = managedArrayMapForRecord.get(field.name);
|
|
349
|
-
}
|
|
403
|
+
let managedArray = signal.value;
|
|
350
404
|
if (managedArray) {
|
|
351
405
|
return managedArray;
|
|
352
406
|
} else {
|
|
@@ -363,11 +417,7 @@ function getArrayField(context) {
|
|
|
363
417
|
return null;
|
|
364
418
|
}
|
|
365
419
|
managedArray = new ManagedArray(context, record, rawValue);
|
|
366
|
-
|
|
367
|
-
ManagedArrayMap.set(record, new Map([[field.name, managedArray]]));
|
|
368
|
-
} else {
|
|
369
|
-
managedArrayMapForRecord.set(field.name, managedArray);
|
|
370
|
-
}
|
|
420
|
+
signal.value = managedArray;
|
|
371
421
|
}
|
|
372
422
|
return managedArray;
|
|
373
423
|
}
|
|
@@ -381,27 +431,11 @@ function setArrayField(context) {
|
|
|
381
431
|
cache,
|
|
382
432
|
schema
|
|
383
433
|
} = context.store;
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
389
|
-
if (!test) {
|
|
390
|
-
throw new Error(`Expected the peekManagedArray for ${field.kind} to return a ManagedArray`);
|
|
391
|
-
}
|
|
392
|
-
})(ARRAY_SIGNAL in peeked) : {};
|
|
393
|
-
const arrSignal = peeked[ARRAY_SIGNAL];
|
|
394
|
-
arrSignal.isStale = true;
|
|
395
|
-
}
|
|
396
|
-
if (!Array.isArray(value)) {
|
|
397
|
-
ManagedArrayMap.delete(record);
|
|
398
|
-
}
|
|
399
|
-
return true;
|
|
400
|
-
}
|
|
401
|
-
const transform = schema.transformation(field);
|
|
402
|
-
const rawValue = value.map(item => transform.serialize(item, field.options ?? null, record));
|
|
434
|
+
const fieldSignal = peekInternalSignal(context.signals, context.path.at(-1));
|
|
435
|
+
const peeked = fieldSignal?.value;
|
|
436
|
+
const transform = field.type ? schema.transformation(field) : null;
|
|
437
|
+
const rawValue = field.type ? value.map(item => transform.serialize(item, field.options ?? null, record)) : value?.slice();
|
|
403
438
|
cache.setAttr(context.resourceKey, context.path, rawValue);
|
|
404
|
-
const peeked = peekManagedArray(record, field);
|
|
405
439
|
if (peeked) {
|
|
406
440
|
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
407
441
|
if (!test) {
|
|
@@ -410,6 +444,10 @@ function setArrayField(context) {
|
|
|
410
444
|
})(ARRAY_SIGNAL in peeked) : {};
|
|
411
445
|
const arrSignal = peeked[ARRAY_SIGNAL];
|
|
412
446
|
arrSignal.isStale = true;
|
|
447
|
+
// TODO run array destroy?
|
|
448
|
+
}
|
|
449
|
+
if (!Array.isArray(rawValue) && fieldSignal) {
|
|
450
|
+
fieldSignal.value = null;
|
|
413
451
|
}
|
|
414
452
|
return true;
|
|
415
453
|
}
|
|
@@ -619,7 +657,7 @@ function extractCacheOptions(options) {
|
|
|
619
657
|
return cacheOptions;
|
|
620
658
|
}
|
|
621
659
|
function getHasManyField(context) {
|
|
622
|
-
entangleSignal(context.signals, context.record, context.path.at(-1), null);
|
|
660
|
+
const signal = entangleSignal(context.signals, context.record, context.path.at(-1), null);
|
|
623
661
|
const {
|
|
624
662
|
store,
|
|
625
663
|
field
|
|
@@ -634,52 +672,43 @@ function getHasManyField(context) {
|
|
|
634
672
|
// its "key" is the field on the parent record
|
|
635
673
|
// its "owner" is the parent record
|
|
636
674
|
|
|
637
|
-
const
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
managedArray = managedArrayMapForRecord.get(getFieldCacheKeyStrict(field));
|
|
675
|
+
const cached = signal.value;
|
|
676
|
+
if (cached) {
|
|
677
|
+
return cached;
|
|
641
678
|
}
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
const rawValue = cache.getRelationship(resourceKey, getFieldCacheKeyStrict(field));
|
|
653
|
-
if (!rawValue) {
|
|
654
|
-
return null;
|
|
655
|
-
}
|
|
656
|
-
managedArray = new RelatedCollection({
|
|
657
|
-
store,
|
|
658
|
-
type: field.type,
|
|
659
|
-
identifier: resourceKey,
|
|
660
|
-
cache,
|
|
661
|
-
field: context.legacy ? field : undefined,
|
|
662
|
-
// we divorce the reference here because ManyArray mutates the target directly
|
|
663
|
-
// before sending the mutation op to the cache. We may be able to avoid this in the future
|
|
664
|
-
identifiers: rawValue.data?.slice(),
|
|
665
|
-
key: field.name,
|
|
666
|
-
meta: rawValue.meta || null,
|
|
667
|
-
links: rawValue.links || null,
|
|
668
|
-
isPolymorphic: field.options.polymorphic ?? false,
|
|
669
|
-
isAsync: field.options.async ?? false,
|
|
670
|
-
// TODO: Grab the proper value
|
|
671
|
-
_inverseIsAsync: false,
|
|
672
|
-
// @ts-expect-error Typescript doesn't have a way for us to thread the generic backwards so it infers unknown instead of T
|
|
673
|
-
manager: new ManyArrayManager(record, editable),
|
|
674
|
-
isLoaded: true,
|
|
675
|
-
allowMutation: editable
|
|
676
|
-
});
|
|
677
|
-
if (!managedArrayMapForRecord) {
|
|
678
|
-
ManagedArrayMap.set(record, new Map([[field.name, managedArray]]));
|
|
679
|
-
} else {
|
|
680
|
-
managedArrayMapForRecord.set(field.name, managedArray);
|
|
681
|
-
}
|
|
679
|
+
const {
|
|
680
|
+
editable,
|
|
681
|
+
resourceKey
|
|
682
|
+
} = context;
|
|
683
|
+
const {
|
|
684
|
+
cache
|
|
685
|
+
} = store;
|
|
686
|
+
const rawValue = cache.getRelationship(resourceKey, getFieldCacheKeyStrict(field));
|
|
687
|
+
if (!rawValue) {
|
|
688
|
+
return null;
|
|
682
689
|
}
|
|
690
|
+
const managedArray = new RelatedCollection({
|
|
691
|
+
store,
|
|
692
|
+
type: field.type,
|
|
693
|
+
identifier: resourceKey,
|
|
694
|
+
cache,
|
|
695
|
+
field: context.legacy ? field : undefined,
|
|
696
|
+
// we divorce the reference here because ManyArray mutates the target directly
|
|
697
|
+
// before sending the mutation op to the cache. We may be able to avoid this in the future
|
|
698
|
+
identifiers: rawValue.data?.slice(),
|
|
699
|
+
key: field.name,
|
|
700
|
+
meta: rawValue.meta || null,
|
|
701
|
+
links: rawValue.links || null,
|
|
702
|
+
isPolymorphic: field.options.polymorphic ?? false,
|
|
703
|
+
isAsync: field.options.async ?? false,
|
|
704
|
+
// TODO: Grab the proper value
|
|
705
|
+
_inverseIsAsync: false,
|
|
706
|
+
// @ts-expect-error Typescript doesn't have a way for us to thread the generic backwards so it infers unknown instead of T
|
|
707
|
+
manager: new ManyArrayManager(record, editable),
|
|
708
|
+
isLoaded: true,
|
|
709
|
+
allowMutation: editable
|
|
710
|
+
});
|
|
711
|
+
signal.value = managedArray;
|
|
683
712
|
return managedArray;
|
|
684
713
|
}
|
|
685
714
|
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
@@ -807,7 +836,7 @@ class ManagedObject {
|
|
|
807
836
|
} = context.store;
|
|
808
837
|
|
|
809
838
|
// prettier-ignore
|
|
810
|
-
const extensions = !context.legacy ? null : schema.CAUTION_MEGA_DANGER_ZONE_objectExtensions(field);
|
|
839
|
+
const extensions = !context.legacy ? null : schema.CAUTION_MEGA_DANGER_ZONE_objectExtensions(field, null);
|
|
811
840
|
const proxy = new Proxy(this[SOURCE], {
|
|
812
841
|
ownKeys() {
|
|
813
842
|
return Object.keys(self[SOURCE]);
|
|
@@ -1070,11 +1099,9 @@ function setResourceField(context) {
|
|
|
1070
1099
|
}
|
|
1071
1100
|
function setSchemaArrayField(context) {
|
|
1072
1101
|
const arrayValue = context.value?.slice();
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
}
|
|
1102
|
+
const fieldSignal = peekInternalSignal(context.signals, context.path.at(-1));
|
|
1103
|
+
const peeked = fieldSignal?.value;
|
|
1076
1104
|
context.store.cache.setAttr(context.resourceKey, context.path, arrayValue);
|
|
1077
|
-
const peeked = peekManagedArray(context.record, context.field);
|
|
1078
1105
|
if (peeked) {
|
|
1079
1106
|
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1080
1107
|
if (!test) {
|
|
@@ -1083,50 +1110,104 @@ function setSchemaArrayField(context) {
|
|
|
1083
1110
|
})(ARRAY_SIGNAL in peeked) : {};
|
|
1084
1111
|
const arrSignal = peeked[ARRAY_SIGNAL];
|
|
1085
1112
|
arrSignal.isStale = true;
|
|
1113
|
+
if (!Array.isArray(arrayValue)) {
|
|
1114
|
+
fieldSignal.value = null;
|
|
1115
|
+
}
|
|
1086
1116
|
}
|
|
1087
1117
|
return true;
|
|
1088
1118
|
}
|
|
1089
1119
|
function getSchemaObjectField(context) {
|
|
1090
|
-
entangleSignal(context.signals, context.record, context.path.at(-1), null);
|
|
1120
|
+
const signal = entangleSignal(context.signals, context.record, context.path.at(-1), null);
|
|
1091
1121
|
const {
|
|
1092
|
-
|
|
1093
|
-
|
|
1122
|
+
store,
|
|
1123
|
+
resourceKey,
|
|
1124
|
+
path
|
|
1094
1125
|
} = context;
|
|
1095
|
-
const
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
} = context;
|
|
1108
|
-
const {
|
|
1109
|
-
cache
|
|
1110
|
-
} = store;
|
|
1111
|
-
const rawValue = context.editable ? cache.getAttr(resourceKey, path) : cache.getRemoteAttr(resourceKey, path);
|
|
1112
|
-
if (!rawValue) {
|
|
1113
|
-
return null;
|
|
1126
|
+
const {
|
|
1127
|
+
cache
|
|
1128
|
+
} = store;
|
|
1129
|
+
const rawValue = context.editable ? cache.getAttr(resourceKey, path) : cache.getRemoteAttr(resourceKey, path);
|
|
1130
|
+
if (!rawValue) {
|
|
1131
|
+
if (signal.value) {
|
|
1132
|
+
const value = signal.value;
|
|
1133
|
+
// TODO if we had idle scheduling this should be done there.
|
|
1134
|
+
void Promise.resolve().then(() => {
|
|
1135
|
+
value.value[Destroy]();
|
|
1136
|
+
});
|
|
1137
|
+
signal.value = null;
|
|
1114
1138
|
}
|
|
1115
|
-
|
|
1116
|
-
store: context.store,
|
|
1117
|
-
resourceKey: context.resourceKey,
|
|
1118
|
-
modeName: context.modeName,
|
|
1119
|
-
legacy: context.legacy,
|
|
1120
|
-
editable: context.editable,
|
|
1121
|
-
path: context.path,
|
|
1122
|
-
field: context.field
|
|
1123
|
-
});
|
|
1139
|
+
return null;
|
|
1124
1140
|
}
|
|
1125
|
-
|
|
1126
|
-
|
|
1141
|
+
const {
|
|
1142
|
+
field
|
|
1143
|
+
} = context;
|
|
1144
|
+
const {
|
|
1145
|
+
schema
|
|
1146
|
+
} = store;
|
|
1147
|
+
let objectType;
|
|
1148
|
+
if (field.options?.polymorphic) {
|
|
1149
|
+
const typePath = field.options.type ?? 'type';
|
|
1150
|
+
// if we are polymorphic, then context.field.options.type will
|
|
1151
|
+
// either specify a path on the rawValue to use as the type, defaulting to "type" or
|
|
1152
|
+
// the special string "@hash" which tells us to treat field.type as a hashFn name with which
|
|
1153
|
+
// to calc the type.
|
|
1154
|
+
if (typePath === '@hash') {
|
|
1155
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1156
|
+
if (!test) {
|
|
1157
|
+
throw new Error(`Expected the field to define a hashFn as its type`);
|
|
1158
|
+
}
|
|
1159
|
+
})(field.type) : {};
|
|
1160
|
+
const hashFn = schema.hashFn({
|
|
1161
|
+
type: field.type
|
|
1162
|
+
});
|
|
1163
|
+
// TODO consider if there are better options and name args we could provide.
|
|
1164
|
+
objectType = hashFn(rawValue, null, null);
|
|
1165
|
+
} else {
|
|
1166
|
+
objectType = rawValue[typePath];
|
|
1167
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1168
|
+
if (!test) {
|
|
1169
|
+
throw new Error(`Expected the type path for the field to be a value on the raw object`);
|
|
1170
|
+
}
|
|
1171
|
+
})(typePath && objectType && typeof objectType === 'string') : {};
|
|
1172
|
+
}
|
|
1127
1173
|
} else {
|
|
1128
|
-
|
|
1174
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1175
|
+
if (!test) {
|
|
1176
|
+
throw new Error(`A non-polymorphic SchemaObjectField must provide a SchemaObject type in its definition`);
|
|
1177
|
+
}
|
|
1178
|
+
})(field.type) : {};
|
|
1179
|
+
objectType = field.type;
|
|
1180
|
+
}
|
|
1181
|
+
const hashField = schema.resource({
|
|
1182
|
+
type: objectType
|
|
1183
|
+
}).identity;
|
|
1184
|
+
const identity = hashField ? schema.hashFn(hashField)(rawValue, hashField.options ?? null, hashField.name) : field.name;
|
|
1185
|
+
const cachedSchemaObject = signal.value;
|
|
1186
|
+
if (cachedSchemaObject) {
|
|
1187
|
+
if (cachedSchemaObject.type === objectType && cachedSchemaObject.identity === identity) {
|
|
1188
|
+
return cachedSchemaObject.value;
|
|
1189
|
+
} else {
|
|
1190
|
+
// TODO if we had idle scheduling this should be done there.
|
|
1191
|
+
void Promise.resolve().then(() => {
|
|
1192
|
+
cachedSchemaObject.value[Destroy]();
|
|
1193
|
+
});
|
|
1194
|
+
}
|
|
1129
1195
|
}
|
|
1196
|
+
const schemaObject = new ReactiveResource({
|
|
1197
|
+
store: context.store,
|
|
1198
|
+
resourceKey: context.resourceKey,
|
|
1199
|
+
modeName: context.modeName,
|
|
1200
|
+
legacy: context.legacy,
|
|
1201
|
+
editable: context.editable,
|
|
1202
|
+
path: context.path,
|
|
1203
|
+
field: context.field,
|
|
1204
|
+
value: objectType
|
|
1205
|
+
});
|
|
1206
|
+
signal.value = {
|
|
1207
|
+
type: objectType,
|
|
1208
|
+
identity: identity,
|
|
1209
|
+
value: schemaObject
|
|
1210
|
+
};
|
|
1130
1211
|
return schemaObject;
|
|
1131
1212
|
}
|
|
1132
1213
|
function setSchemaObjectField(context) {
|
|
@@ -1309,17 +1390,26 @@ class ReactiveResource {
|
|
|
1309
1390
|
this[Identifier] = identifier;
|
|
1310
1391
|
}
|
|
1311
1392
|
const IS_EDITABLE = this[Editable] = context.editable ?? false;
|
|
1312
|
-
this[Legacy] = context.legacy ?? false;
|
|
1313
1393
|
const schema = store.schema;
|
|
1314
|
-
|
|
1394
|
+
this[Legacy] = context.legacy ?? false;
|
|
1395
|
+
const objectType = isEmbedded ? context.value : identifier.type;
|
|
1396
|
+
const ResourceSchema = schema.resource(isEmbedded ? {
|
|
1397
|
+
type: objectType
|
|
1398
|
+
} : identifier);
|
|
1315
1399
|
const identityField = ResourceSchema.identity;
|
|
1316
1400
|
const BoundFns = new Map();
|
|
1317
1401
|
|
|
1318
1402
|
// prettier-ignore
|
|
1319
|
-
const extensions = !context.legacy ? null : isEmbedded ? schema.CAUTION_MEGA_DANGER_ZONE_objectExtensions(embeddedField) : schema.CAUTION_MEGA_DANGER_ZONE_resourceExtensions(identifier);
|
|
1403
|
+
const extensions = !context.legacy ? null : isEmbedded ? schema.CAUTION_MEGA_DANGER_ZONE_objectExtensions(embeddedField, objectType) : schema.CAUTION_MEGA_DANGER_ZONE_resourceExtensions(identifier);
|
|
1320
1404
|
this[EmbeddedField] = embeddedField;
|
|
1321
1405
|
this[EmbeddedPath] = embeddedPath;
|
|
1322
|
-
const fields = isEmbedded ? schema.fields(
|
|
1406
|
+
const fields = isEmbedded ? schema.fields({
|
|
1407
|
+
type: objectType
|
|
1408
|
+
}) : schema.fields(identifier);
|
|
1409
|
+
const method = typeof schema.cacheFields === 'function' ? 'cacheFields' : 'fields';
|
|
1410
|
+
const cacheFields = isEmbedded ? schema[method]({
|
|
1411
|
+
type: objectType
|
|
1412
|
+
}) : schema[method](identifier);
|
|
1323
1413
|
const signals = withSignalStore(this);
|
|
1324
1414
|
const proxy = new Proxy(this, {
|
|
1325
1415
|
ownKeys() {
|
|
@@ -1684,9 +1774,9 @@ class ReactiveResource {
|
|
|
1684
1774
|
if (signal) {
|
|
1685
1775
|
notifyInternalSignal(signal);
|
|
1686
1776
|
}
|
|
1687
|
-
const field =
|
|
1777
|
+
const field = cacheFields.get(key);
|
|
1688
1778
|
if (field?.kind === 'array' || field?.kind === 'schema-array') {
|
|
1689
|
-
const peeked =
|
|
1779
|
+
const peeked = signal?.value;
|
|
1690
1780
|
if (peeked) {
|
|
1691
1781
|
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1692
1782
|
if (!test) {
|
|
@@ -1712,7 +1802,7 @@ class ReactiveResource {
|
|
|
1712
1802
|
if (Array.isArray(key)) ;else {
|
|
1713
1803
|
if (isEmbedded) return; // base paths never apply to embedded records
|
|
1714
1804
|
|
|
1715
|
-
const field =
|
|
1805
|
+
const field = cacheFields.get(key);
|
|
1716
1806
|
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1717
1807
|
if (!test) {
|
|
1718
1808
|
throw new Error(`Expected relationship ${key} to be the name of a field`);
|
|
@@ -1728,9 +1818,12 @@ class ReactiveResource {
|
|
|
1728
1818
|
// FIXME
|
|
1729
1819
|
} else if (field.kind === 'resource') ;else if (field.kind === 'hasMany') {
|
|
1730
1820
|
if (field.options.linksMode) {
|
|
1731
|
-
const
|
|
1732
|
-
if (
|
|
1733
|
-
|
|
1821
|
+
const signal = signals.get(key);
|
|
1822
|
+
if (signal) {
|
|
1823
|
+
const peeked = signal.value;
|
|
1824
|
+
if (peeked) {
|
|
1825
|
+
notifyInternalSignal(peeked[ARRAY_SIGNAL]);
|
|
1826
|
+
}
|
|
1734
1827
|
}
|
|
1735
1828
|
return;
|
|
1736
1829
|
}
|
|
@@ -1801,8 +1894,9 @@ function _CHECKOUT(record) {
|
|
|
1801
1894
|
modeName: legacy ? 'legacy' : 'polaris',
|
|
1802
1895
|
legacy: legacy,
|
|
1803
1896
|
editable: true,
|
|
1804
|
-
path:
|
|
1805
|
-
field:
|
|
1897
|
+
path: null,
|
|
1898
|
+
field: null,
|
|
1899
|
+
value: null
|
|
1806
1900
|
});
|
|
1807
1901
|
setRecordIdentifier(editableRecord, recordIdentifierFor(record));
|
|
1808
1902
|
return Promise.resolve(editableRecord);
|
|
@@ -1815,6 +1909,9 @@ function _DESTROY(record) {
|
|
|
1815
1909
|
record.isDestroyed = true;
|
|
1816
1910
|
}
|
|
1817
1911
|
record[RecordStore].notifications.unsubscribe(record.___notifications);
|
|
1912
|
+
|
|
1913
|
+
// FIXME we need a way to also unsubscribe all SchemaObjects when the primary
|
|
1914
|
+
// resource is destroyed.
|
|
1818
1915
|
}
|
|
1819
1916
|
function assertNeverField(identifier, field, path) {
|
|
1820
1917
|
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
@@ -1841,7 +1938,8 @@ function instantiateRecord(store, identifier, createArgs) {
|
|
|
1841
1938
|
legacy: legacy,
|
|
1842
1939
|
editable: editable,
|
|
1843
1940
|
path: null,
|
|
1844
|
-
field: null
|
|
1941
|
+
field: null,
|
|
1942
|
+
value: null
|
|
1845
1943
|
});
|
|
1846
1944
|
if (createArgs) {
|
|
1847
1945
|
Object.assign(record, createArgs);
|
|
@@ -1978,7 +2076,7 @@ function getExt(extCache, type, extName) {
|
|
|
1978
2076
|
function hasObjectSchema(field) {
|
|
1979
2077
|
return 'kind' in field && (field.kind === 'schema-array' || field.kind === 'schema-object');
|
|
1980
2078
|
}
|
|
1981
|
-
function processExtensions(schema, field, scenario) {
|
|
2079
|
+
function processExtensions(schema, field, scenario, resolvedType) {
|
|
1982
2080
|
// if we're looking up extensions for a resource, there is no
|
|
1983
2081
|
// merging required so if we have no objectExtensions
|
|
1984
2082
|
// we are done.
|
|
@@ -2005,12 +2103,16 @@ function processExtensions(schema, field, scenario) {
|
|
|
2005
2103
|
if (!hasObjectSchema(field)) {
|
|
2006
2104
|
return null;
|
|
2007
2105
|
}
|
|
2008
|
-
return schema.CAUTION_MEGA_DANGER_ZONE_resourceExtensions(
|
|
2106
|
+
return schema.CAUTION_MEGA_DANGER_ZONE_resourceExtensions(resolvedType ? {
|
|
2107
|
+
type: resolvedType
|
|
2108
|
+
} : field);
|
|
2009
2109
|
}
|
|
2010
2110
|
|
|
2011
2111
|
// if we have made it here, we have extensions, lets check if there's
|
|
2012
2112
|
// a cached version we can use
|
|
2013
|
-
const baseExtensions = scenario === 'resource' && hasObjectSchema(field) ? schema.CAUTION_MEGA_DANGER_ZONE_resourceExtensions(field) : scenario === 'object' && hasObjectSchema(field) ? schema.CAUTION_MEGA_DANGER_ZONE_resourceExtensions(
|
|
2113
|
+
const baseExtensions = scenario === 'resource' && hasObjectSchema(field) ? schema.CAUTION_MEGA_DANGER_ZONE_resourceExtensions(field) : scenario === 'object' && hasObjectSchema(field) ? schema.CAUTION_MEGA_DANGER_ZONE_resourceExtensions(resolvedType ? {
|
|
2114
|
+
type: resolvedType
|
|
2115
|
+
} : field) : null;
|
|
2014
2116
|
if (!baseExtensions && extensions.length === 1) {
|
|
2015
2117
|
const value = getExt(extCache, type, extensions[0]);
|
|
2016
2118
|
fieldCache[type].set(field, value);
|
|
@@ -2339,13 +2441,13 @@ class SchemaService {
|
|
|
2339
2441
|
}
|
|
2340
2442
|
CAUTION_MEGA_DANGER_ZONE_resourceExtensions(resource) {
|
|
2341
2443
|
const schema = this.resource(resource);
|
|
2342
|
-
return processExtensions(this, schema, 'resource');
|
|
2444
|
+
return processExtensions(this, schema, 'resource', null);
|
|
2343
2445
|
}
|
|
2344
|
-
CAUTION_MEGA_DANGER_ZONE_objectExtensions(field) {
|
|
2345
|
-
return processExtensions(this, field, 'object');
|
|
2446
|
+
CAUTION_MEGA_DANGER_ZONE_objectExtensions(field, resolvedType) {
|
|
2447
|
+
return processExtensions(this, field, 'object', resolvedType);
|
|
2346
2448
|
}
|
|
2347
2449
|
CAUTION_MEGA_DANGER_ZONE_arrayExtensions(field) {
|
|
2348
|
-
return processExtensions(this, field, 'array');
|
|
2450
|
+
return processExtensions(this, field, 'array', null);
|
|
2349
2451
|
}
|
|
2350
2452
|
CAUTION_MEGA_DANGER_ZONE_hasExtension(ext) {
|
|
2351
2453
|
return this._extensions[ext.kind].has(ext.name);
|
|
@@ -3481,7 +3481,7 @@ function extractIdentifierFromRecord$2(record) {
|
|
|
3481
3481
|
return recordIdentifierFor(record);
|
|
3482
3482
|
}
|
|
3483
3483
|
const FAKE_ARR = getOrSetGlobal('FAKE_ARR', {});
|
|
3484
|
-
const SLICE_BATCH_SIZE =
|
|
3484
|
+
const SLICE_BATCH_SIZE = 4761;
|
|
3485
3485
|
/**
|
|
3486
3486
|
* This is a clever optimization.
|
|
3487
3487
|
*
|
|
@@ -3521,15 +3521,12 @@ const SLICE_BATCH_SIZE = 1200;
|
|
|
3521
3521
|
* @param source the items to push into target
|
|
3522
3522
|
*/
|
|
3523
3523
|
function fastPush(target, source) {
|
|
3524
|
-
let
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
target.push.apply(target, source.slice(startLength, startLength + SLICE_BATCH_SIZE));
|
|
3529
|
-
startLength += SLICE_BATCH_SIZE;
|
|
3524
|
+
let batch;
|
|
3525
|
+
while (source.length > SLICE_BATCH_SIZE) {
|
|
3526
|
+
batch = source.splice(0, SLICE_BATCH_SIZE);
|
|
3527
|
+
target.push(...batch);
|
|
3530
3528
|
}
|
|
3531
|
-
|
|
3532
|
-
target.push.apply(target, source.slice(startLength));
|
|
3529
|
+
target.push(...source);
|
|
3533
3530
|
}
|
|
3534
3531
|
/**
|
|
3535
3532
|
@class RecordArrayManager
|
|
@@ -5078,7 +5075,7 @@ class Store extends BaseClass {
|
|
|
5078
5075
|
if (!cache) {
|
|
5079
5076
|
cache = this._instanceCache.cache = this.createCache(this._instanceCache._storeWrapper);
|
|
5080
5077
|
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
5081
|
-
cache = new CacheManager(cache);
|
|
5078
|
+
cache = this._instanceCache.cache = new CacheManager(cache);
|
|
5082
5079
|
}
|
|
5083
5080
|
}
|
|
5084
5081
|
return cache;
|
package/dist/store/-private.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { C as CollectionRecordArray, D as DISPOSE, I as LiveArray, M as MUTATE, R as RecordArrayManager, l as RelatedCollection, d as SOURCE, B as Signals, S as Store, j as StoreMap, _ as _clearCaches, n as _deprecatingNormalize, b as coerceId, c as constructResource, H as consumeInternalSignal, t as createRequestSubscription, z as defineGate, A as defineNonEnumerableSignal, y as defineSignal, e as ensureStringId, x as entangleSignal, f as fastPush, w as gate, J as getOrCreateInternalSignal, q as getPromiseState, u as getRequestState, a as isDocumentIdentifier, i as isStableIdentifier, m as log, o as logGroup, v as memoized, G as notifyInternalSignal, p as peekCache, E as peekInternalSignal, r as recordIdentifierFor, g as removeRecordDataFor, k as setCacheFor, h as setRecordIdentifier, s as storeFor, F as withSignalStore } from "../request-state-
|
|
2
|
-
export { C as CacheHandler } from "../handler-
|
|
1
|
+
export { C as CollectionRecordArray, D as DISPOSE, I as LiveArray, M as MUTATE, R as RecordArrayManager, l as RelatedCollection, d as SOURCE, B as Signals, S as Store, j as StoreMap, _ as _clearCaches, n as _deprecatingNormalize, b as coerceId, c as constructResource, H as consumeInternalSignal, t as createRequestSubscription, z as defineGate, A as defineNonEnumerableSignal, y as defineSignal, e as ensureStringId, x as entangleSignal, f as fastPush, w as gate, J as getOrCreateInternalSignal, q as getPromiseState, u as getRequestState, a as isDocumentIdentifier, i as isStableIdentifier, m as log, o as logGroup, v as memoized, G as notifyInternalSignal, p as peekCache, E as peekInternalSignal, r as recordIdentifierFor, g as removeRecordDataFor, k as setCacheFor, h as setRecordIdentifier, s as storeFor, F as withSignalStore } from "../request-state-CeN66aML.js";
|
|
2
|
+
export { C as CacheHandler } from "../handler-SdXlte1w.js";
|
|
3
3
|
export { A as ARRAY_SIGNAL, O as OBJECT_SIGNAL, c as createMemo, w as waitFor } from "../configure-B48bFHOl.js";
|
package/dist/types/-private.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { macroCondition, getGlobalConfig } from '@embroider/macros';
|
|
2
2
|
const name = "@warp-drive/core";
|
|
3
|
-
const version = "5.7.0-alpha.
|
|
3
|
+
const version = "5.7.0-alpha.5";
|
|
4
4
|
|
|
5
5
|
// in testing mode, we utilize globals to ensure only one copy exists of
|
|
6
6
|
// these maps, due to bugs in ember-auto-import
|
|
@@ -134,7 +134,7 @@
|
|
|
134
134
|
* perform those itself.
|
|
135
135
|
*
|
|
136
136
|
* A schema-array can declare its "key" value to be `@hash` if
|
|
137
|
-
*
|
|
137
|
+
* the schema-objects it contains have such a field.
|
|
138
138
|
*
|
|
139
139
|
* Only one hash field is permittable per schema-object, and
|
|
140
140
|
* it should be placed in the `ResourceSchema`'s `@id` field
|
|
@@ -188,11 +188,13 @@
|
|
|
188
188
|
/**
|
|
189
189
|
* Represents a field whose value is an object
|
|
190
190
|
* with a well-defined structure described by
|
|
191
|
-
* a non-resource schema.
|
|
191
|
+
* a schema-object (a non-resource schema).
|
|
192
192
|
*
|
|
193
193
|
* If the object's structure is not well-defined,
|
|
194
194
|
* use 'object' instead.
|
|
195
195
|
*
|
|
196
|
+
* By default, a SchemaObject within
|
|
197
|
+
*
|
|
196
198
|
* @public
|
|
197
199
|
*/
|
|
198
200
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@warp-drive/core",
|
|
3
|
-
"version": "5.7.0-alpha.
|
|
3
|
+
"version": "5.7.0-alpha.5",
|
|
4
4
|
"description": "Core package for WarpDrive | All the Universal Basics",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ember-addon"
|
|
@@ -37,13 +37,13 @@
|
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"@embroider/macros": "^1.16.12",
|
|
40
|
-
"@warp-drive/build-config": "5.7.0-alpha.
|
|
40
|
+
"@warp-drive/build-config": "5.7.0-alpha.5"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@babel/core": "^7.26.10",
|
|
44
44
|
"@babel/plugin-transform-typescript": "^7.27.0",
|
|
45
45
|
"@babel/preset-typescript": "^7.27.0",
|
|
46
|
-
"@warp-drive/internal-config": "5.7.0-alpha.
|
|
46
|
+
"@warp-drive/internal-config": "5.7.0-alpha.5",
|
|
47
47
|
"decorator-transforms": "^2.3.0",
|
|
48
48
|
"ember-source": "~6.3.0",
|
|
49
49
|
"expect-type": "^1.2.1",
|