@iamjulianacosta/mobx-data 1.1.0 → 1.4.0
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/README.md +273 -102
- package/dist/{CacheHandler-BTU_rYkv.js → CacheHandler-BhfbVHed.js} +17 -20
- package/dist/CacheHandler-BhfbVHed.js.map +1 -0
- package/dist/{CacheHandler-CXgY9IJo.cjs → CacheHandler-Q5VXOgh9.cjs} +2 -2
- package/dist/CacheHandler-Q5VXOgh9.cjs.map +1 -0
- package/dist/EmbeddedRecordsMixin-6mSCXsJ3.js +173 -0
- package/dist/EmbeddedRecordsMixin-6mSCXsJ3.js.map +1 -0
- package/dist/EmbeddedRecordsMixin-BkF7MdbY.cjs +2 -0
- package/dist/EmbeddedRecordsMixin-BkF7MdbY.cjs.map +1 -0
- package/dist/{JsonApiSerializer-BLoE046A.js → JsonApiSerializer-BV61cFAZ.js} +3 -3
- package/dist/JsonApiSerializer-BV61cFAZ.js.map +1 -0
- package/dist/{JsonApiSerializer-DKemcyw-.cjs → JsonApiSerializer-Dt_Y_FIo.cjs} +2 -2
- package/dist/JsonApiSerializer-Dt_Y_FIo.cjs.map +1 -0
- package/dist/JsonSerializer-BzUCyUSf.cjs +2 -0
- package/dist/JsonSerializer-BzUCyUSf.cjs.map +1 -0
- package/dist/JsonSerializer-CFqo6GjC.js +98 -0
- package/dist/JsonSerializer-CFqo6GjC.js.map +1 -0
- package/dist/MdqlMemoryExecutor-BUlsalKm.cjs +2 -0
- package/dist/MdqlMemoryExecutor-BUlsalKm.cjs.map +1 -0
- package/dist/MdqlMemoryExecutor-BWMP31zG.js +127 -0
- package/dist/MdqlMemoryExecutor-BWMP31zG.js.map +1 -0
- package/dist/{MemoryAdapter-Bp-BGHH3.js → MemoryAdapter-BW1HKixm.js} +2 -2
- package/dist/{MemoryAdapter-Bp-BGHH3.js.map → MemoryAdapter-BW1HKixm.js.map} +1 -1
- package/dist/{MemoryAdapter-DH-gzSSl.cjs → MemoryAdapter-C8iXAa2v.cjs} +2 -2
- package/dist/{MemoryAdapter-DH-gzSSl.cjs.map → MemoryAdapter-C8iXAa2v.cjs.map} +1 -1
- package/dist/{ODataAdapter-RQUjVTcf.js → ODataAdapter-CeBJblLQ.js} +25 -22
- package/dist/ODataAdapter-CeBJblLQ.js.map +1 -0
- package/dist/{ODataAdapter-CrDFvBEZ.cjs → ODataAdapter-DdE6MWkG.cjs} +2 -2
- package/dist/ODataAdapter-DdE6MWkG.cjs.map +1 -0
- package/dist/RestAdapter-D7GSrsJo.cjs +2 -0
- package/dist/RestAdapter-D7GSrsJo.cjs.map +1 -0
- package/dist/{RestAdapter-D6bGIHZT.js → RestAdapter-DYUoyV5h.js} +112 -77
- package/dist/RestAdapter-DYUoyV5h.js.map +1 -0
- package/dist/SchemaService-C_pkh-vI.js +180 -0
- package/dist/SchemaService-C_pkh-vI.js.map +1 -0
- package/dist/SchemaService-DbJLoYb9.cjs +2 -0
- package/dist/SchemaService-DbJLoYb9.cjs.map +1 -0
- package/dist/Serializer-Bap9U-kR.cjs +2 -0
- package/dist/Serializer-Bap9U-kR.cjs.map +1 -0
- package/dist/{Serializer-FxJbsZ50.js → Serializer-Ca6w_QNQ.js} +63 -49
- package/dist/Serializer-Ca6w_QNQ.js.map +1 -0
- package/dist/adapter/index.cjs +1 -1
- package/dist/adapter/index.js +2 -2
- package/dist/createStore-7PecKT54.cjs +2 -0
- package/dist/createStore-7PecKT54.cjs.map +1 -0
- package/dist/createStore-BfmRfZ_2.js +1229 -0
- package/dist/createStore-BfmRfZ_2.js.map +1 -0
- package/dist/date-Bj4O2W1F.js.map +1 -1
- package/dist/date-CRCe-9gf.cjs.map +1 -1
- package/dist/decorators-CKneHgoF.js +56 -0
- package/dist/decorators-CKneHgoF.js.map +1 -0
- package/dist/decorators-DCVYKzrL.cjs +2 -0
- package/dist/decorators-DCVYKzrL.cjs.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +100 -90
- package/dist/index.js.map +1 -1
- package/dist/inspector/ConsoleInspector.d.ts +49 -0
- package/dist/inspector/ConsoleInspector.d.ts.map +1 -0
- package/dist/inspector/DevToolsBridge.d.ts +21 -0
- package/dist/inspector/DevToolsBridge.d.ts.map +1 -0
- package/dist/inspector/QueryParser.d.ts +21 -0
- package/dist/inspector/QueryParser.d.ts.map +1 -0
- package/dist/inspector/StoreInspector.d.ts +31 -0
- package/dist/inspector/StoreInspector.d.ts.map +1 -0
- package/dist/inspector/index.cjs +17 -0
- package/dist/inspector/index.cjs.map +1 -0
- package/dist/inspector/index.d.ts +9 -0
- package/dist/inspector/index.d.ts.map +1 -0
- package/dist/inspector/index.js +896 -0
- package/dist/inspector/index.js.map +1 -0
- package/dist/inspector/integration.d.ts +15 -0
- package/dist/inspector/integration.d.ts.map +1 -0
- package/dist/inspector/serialization.d.ts +7 -0
- package/dist/inspector/serialization.d.ts.map +1 -0
- package/dist/inspector/types.d.ts +139 -0
- package/dist/inspector/types.d.ts.map +1 -0
- package/dist/json-api/index.cjs +1 -1
- package/dist/json-api/index.js +1 -1
- package/dist/mdql/MdqlMemoryExecutor.d.ts +17 -0
- package/dist/mdql/MdqlMemoryExecutor.d.ts.map +1 -0
- package/dist/mdql/MdqlQueryBuilder.d.ts +38 -0
- package/dist/mdql/MdqlQueryBuilder.d.ts.map +1 -0
- package/dist/mdql/MdqlValidator.d.ts +13 -0
- package/dist/mdql/MdqlValidator.d.ts.map +1 -0
- package/dist/mdql/index.d.ts +6 -0
- package/dist/mdql/index.d.ts.map +1 -0
- package/dist/mdql/types.d.ts +48 -0
- package/dist/mdql/types.d.ts.map +1 -0
- package/dist/model/Model.d.ts +4 -0
- package/dist/model/Model.d.ts.map +1 -1
- package/dist/model/Snapshot.d.ts +2 -0
- package/dist/model/Snapshot.d.ts.map +1 -1
- package/dist/model/index.cjs +1 -1
- package/dist/model/index.js +1 -1
- package/dist/odata/ODataAdapter.d.ts.map +1 -1
- package/dist/odata/index.cjs +1 -1
- package/dist/odata/index.js +1 -1
- package/dist/relationships-BgM0NKdb.cjs +2 -0
- package/dist/relationships-BgM0NKdb.cjs.map +1 -0
- package/dist/{relationships-BEXANmWg.js → relationships-DvSi8fVN.js} +37 -28
- package/dist/relationships-DvSi8fVN.js.map +1 -0
- package/dist/request/CacheHandler.d.ts.map +1 -1
- package/dist/request/index.cjs +1 -1
- package/dist/request/index.js +1 -1
- package/dist/schema/SchemaService.d.ts +38 -1
- package/dist/schema/SchemaService.d.ts.map +1 -1
- package/dist/schema/decorators.d.ts +20 -1
- package/dist/schema/decorators.d.ts.map +1 -1
- package/dist/schema/index.cjs +1 -1
- package/dist/schema/index.d.ts +1 -1
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +10 -8
- package/dist/schema/types.d.ts +31 -0
- package/dist/schema/types.d.ts.map +1 -1
- package/dist/serializer/JsonSerializer.d.ts +2 -0
- package/dist/serializer/JsonSerializer.d.ts.map +1 -1
- package/dist/serializer/Serializer.d.ts +9 -0
- package/dist/serializer/Serializer.d.ts.map +1 -1
- package/dist/serializer/index.cjs +1 -1
- package/dist/serializer/index.js +6 -5
- package/dist/serializer/index.js.map +1 -1
- package/dist/store/Store.d.ts +3 -0
- package/dist/store/Store.d.ts.map +1 -1
- package/dist/store/createStore.d.ts +12 -0
- package/dist/store/createStore.d.ts.map +1 -0
- package/dist/store/index.cjs +1 -1
- package/dist/store/index.d.ts +1 -0
- package/dist/store/index.d.ts.map +1 -1
- package/dist/store/index.js +5 -4
- package/dist/types-CC2fG3FP.js +8 -0
- package/dist/types-CC2fG3FP.js.map +1 -0
- package/dist/types-DCLy5XYj.cjs +2 -0
- package/dist/types-DCLy5XYj.cjs.map +1 -0
- package/package.json +7 -1
- package/src/index.ts +3 -0
- package/src/inspector/ConsoleInspector.ts +470 -0
- package/src/inspector/DevToolsBridge.ts +214 -0
- package/src/inspector/QueryParser.ts +343 -0
- package/src/inspector/StoreInspector.ts +162 -0
- package/src/inspector/index.ts +20 -0
- package/src/inspector/integration.ts +56 -0
- package/src/inspector/serialization.ts +100 -0
- package/src/inspector/types.ts +161 -0
- package/src/mdql/MdqlMemoryExecutor.ts +229 -0
- package/src/mdql/MdqlQueryBuilder.ts +170 -0
- package/src/mdql/MdqlValidator.ts +193 -0
- package/src/mdql/index.ts +21 -0
- package/src/mdql/types.ts +107 -0
- package/src/model/Model.ts +15 -0
- package/src/model/Snapshot.ts +3 -0
- package/src/odata/ODataAdapter.ts +4 -1
- package/src/request/CacheHandler.ts +2 -6
- package/src/schema/SchemaService.ts +123 -1
- package/src/schema/decorators.ts +29 -0
- package/src/schema/index.ts +1 -1
- package/src/schema/types.ts +34 -0
- package/src/serializer/JsonSerializer.ts +14 -2
- package/src/serializer/Serializer.ts +24 -1
- package/src/store/Store.ts +57 -14
- package/src/store/createStore.ts +39 -0
- package/src/store/index.ts +1 -0
- package/dist/CacheHandler-BTU_rYkv.js.map +0 -1
- package/dist/CacheHandler-CXgY9IJo.cjs.map +0 -1
- package/dist/EmbeddedRecordsMixin-CBvqNdgC.cjs +0 -2
- package/dist/EmbeddedRecordsMixin-CBvqNdgC.cjs.map +0 -1
- package/dist/EmbeddedRecordsMixin-VoHluHCT.js +0 -261
- package/dist/EmbeddedRecordsMixin-VoHluHCT.js.map +0 -1
- package/dist/JsonApiSerializer-BLoE046A.js.map +0 -1
- package/dist/JsonApiSerializer-DKemcyw-.cjs.map +0 -1
- package/dist/ODataAdapter-CrDFvBEZ.cjs.map +0 -1
- package/dist/ODataAdapter-RQUjVTcf.js.map +0 -1
- package/dist/RestAdapter-CSoJg7D2.cjs +0 -2
- package/dist/RestAdapter-CSoJg7D2.cjs.map +0 -1
- package/dist/RestAdapter-D6bGIHZT.js.map +0 -1
- package/dist/SchemaService-DZwkFgZu.js +0 -102
- package/dist/SchemaService-DZwkFgZu.js.map +0 -1
- package/dist/SchemaService-Di_yjVzU.cjs +0 -2
- package/dist/SchemaService-Di_yjVzU.cjs.map +0 -1
- package/dist/Serializer-95gi5edy.cjs +0 -2
- package/dist/Serializer-95gi5edy.cjs.map +0 -1
- package/dist/Serializer-FxJbsZ50.js.map +0 -1
- package/dist/Store-Bm5JivTc.js +0 -957
- package/dist/Store-Bm5JivTc.js.map +0 -1
- package/dist/Store-DX9D0Mmy.cjs +0 -2
- package/dist/Store-DX9D0Mmy.cjs.map +0 -1
- package/dist/cache-utils-B2wFhisx.js +0 -39
- package/dist/cache-utils-B2wFhisx.js.map +0 -1
- package/dist/cache-utils-CSwsqOi3.cjs +0 -2
- package/dist/cache-utils-CSwsqOi3.cjs.map +0 -1
- package/dist/decorators-HQ1KnRdh.cjs +0 -2
- package/dist/decorators-HQ1KnRdh.cjs.map +0 -1
- package/dist/decorators-Zr35qr6A.js +0 -50
- package/dist/decorators-Zr35qr6A.js.map +0 -1
- package/dist/relationships-B55LBaCW.cjs +0 -2
- package/dist/relationships-B55LBaCW.cjs.map +0 -1
- package/dist/relationships-BEXANmWg.js.map +0 -1
- package/dist/types-C9NB2gRj.js +0 -7
- package/dist/types-C9NB2gRj.js.map +0 -1
- package/dist/types-uWOXMPWW.cjs +0 -2
- package/dist/types-uWOXMPWW.cjs.map +0 -1
package/dist/Store-Bm5JivTc.js
DELETED
|
@@ -1,957 +0,0 @@
|
|
|
1
|
-
import { singleton as M, injectable as F, inject as z } from "tsyringe";
|
|
2
|
-
import { makeObservable as _, action as b, observable as y, computed as u, runInAction as p } from "mobx";
|
|
3
|
-
import { S as D } from "./SchemaService-DZwkFgZu.js";
|
|
4
|
-
import { b as S, A as C, a as E, M as O } from "./relationships-BEXANmWg.js";
|
|
5
|
-
import { e as m, p as v } from "./cache-utils-B2wFhisx.js";
|
|
6
|
-
class q {
|
|
7
|
-
constructor() {
|
|
8
|
-
this._buckets = /* @__PURE__ */ new Map(), _(this, {
|
|
9
|
-
_buckets: y.shallow,
|
|
10
|
-
set: b,
|
|
11
|
-
delete: b,
|
|
12
|
-
clear: b
|
|
13
|
-
});
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* Returns the bucket for `modelName`, optionally creating it when absent.
|
|
17
|
-
* Internal helper — not part of the public API.
|
|
18
|
-
*/
|
|
19
|
-
bucket(e, s = !1) {
|
|
20
|
-
let i = this._buckets.get(e);
|
|
21
|
-
return !i && s && (i = y.map({}, { deep: !1 }), this._buckets.set(e, i)), i;
|
|
22
|
-
}
|
|
23
|
-
/** Adds or replaces the record with the given `id` under `modelName`. */
|
|
24
|
-
set(e, s, i) {
|
|
25
|
-
this.bucket(e, !0).set(s, i);
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Returns the record for `modelName` + `id`, or `null` when not found.
|
|
29
|
-
*/
|
|
30
|
-
get(e, s) {
|
|
31
|
-
var i;
|
|
32
|
-
return ((i = this.bucket(e)) == null ? void 0 : i.get(s)) ?? null;
|
|
33
|
-
}
|
|
34
|
-
/** Returns `true` when a record exists for `modelName` + `id`. */
|
|
35
|
-
has(e, s) {
|
|
36
|
-
var i;
|
|
37
|
-
return ((i = this.bucket(e)) == null ? void 0 : i.has(s)) ?? !1;
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Removes the record for `modelName` + `id`.
|
|
41
|
-
* @returns `true` when the record existed and was deleted.
|
|
42
|
-
*/
|
|
43
|
-
delete(e, s) {
|
|
44
|
-
var i;
|
|
45
|
-
return ((i = this.bucket(e)) == null ? void 0 : i.delete(s)) ?? !1;
|
|
46
|
-
}
|
|
47
|
-
/** Returns all records stored under `modelName` as an array. */
|
|
48
|
-
all(e) {
|
|
49
|
-
const s = this.bucket(e);
|
|
50
|
-
return s ? Array.from(s.values()) : [];
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Clears all records for `modelName`, or all records across all types when
|
|
54
|
-
* `modelName` is omitted.
|
|
55
|
-
*/
|
|
56
|
-
clear(e) {
|
|
57
|
-
var s;
|
|
58
|
-
if (e)
|
|
59
|
-
(s = this.bucket(e)) == null || s.clear();
|
|
60
|
-
else
|
|
61
|
-
for (const i of this._buckets.values())
|
|
62
|
-
i.clear();
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* Returns the number of records stored for `modelName`, or the total across
|
|
66
|
-
* all types when `modelName` is omitted.
|
|
67
|
-
*/
|
|
68
|
-
size(e) {
|
|
69
|
-
var i;
|
|
70
|
-
if (e)
|
|
71
|
-
return ((i = this.bucket(e)) == null ? void 0 : i.size) ?? 0;
|
|
72
|
-
let s = 0;
|
|
73
|
-
for (const a of this._buckets.values())
|
|
74
|
-
s += a.size;
|
|
75
|
-
return s;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
class k {
|
|
79
|
-
constructor(e) {
|
|
80
|
-
this.updating = !1, this.opts = e, _(this, {
|
|
81
|
-
resolved: e.keepAlive ? u({ keepAlive: !0 }) : u,
|
|
82
|
-
updating: y,
|
|
83
|
-
length: u,
|
|
84
|
-
modelName: u
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
/** Current record list, derived from the injected `source` function. */
|
|
88
|
-
get resolved() {
|
|
89
|
-
return this.opts.source();
|
|
90
|
-
}
|
|
91
|
-
/** `true` while a background `update()` call is in progress. */
|
|
92
|
-
get isLoading() {
|
|
93
|
-
return this.updating;
|
|
94
|
-
}
|
|
95
|
-
/** Alias for `isLoading`. */
|
|
96
|
-
get isUpdating() {
|
|
97
|
-
return this.updating;
|
|
98
|
-
}
|
|
99
|
-
/** Number of records in the array. */
|
|
100
|
-
get length() {
|
|
101
|
-
return this.resolved.length;
|
|
102
|
-
}
|
|
103
|
-
/** The registered model name for the records in this array. */
|
|
104
|
-
get modelName() {
|
|
105
|
-
return this.opts.modelName;
|
|
106
|
-
}
|
|
107
|
-
/** Returns the record at `index`, or `undefined`. */
|
|
108
|
-
at(e) {
|
|
109
|
-
return this.resolved[e];
|
|
110
|
-
}
|
|
111
|
-
/** Returns a plain array snapshot of all records. */
|
|
112
|
-
toArray() {
|
|
113
|
-
return [...this.resolved];
|
|
114
|
-
}
|
|
115
|
-
/** Maps over records. */
|
|
116
|
-
map(e) {
|
|
117
|
-
return this.resolved.map(e);
|
|
118
|
-
}
|
|
119
|
-
/** Filters records. */
|
|
120
|
-
filter(e) {
|
|
121
|
-
return this.resolved.filter(e);
|
|
122
|
-
}
|
|
123
|
-
/** Iterates records. */
|
|
124
|
-
forEach(e) {
|
|
125
|
-
this.resolved.forEach(e);
|
|
126
|
-
}
|
|
127
|
-
/** Returns `true` when `record` is in the array. */
|
|
128
|
-
includes(e) {
|
|
129
|
-
return this.resolved.includes(e);
|
|
130
|
-
}
|
|
131
|
-
/**
|
|
132
|
-
* Triggers the `update` callback (if any) to refresh the array from the
|
|
133
|
-
* adapter. Sets `isLoading` while the request is in flight.
|
|
134
|
-
*/
|
|
135
|
-
async update() {
|
|
136
|
-
if (!this.opts.update)
|
|
137
|
-
return this;
|
|
138
|
-
this.updating = !0;
|
|
139
|
-
try {
|
|
140
|
-
await this.opts.update();
|
|
141
|
-
} finally {
|
|
142
|
-
this.updating = !1;
|
|
143
|
-
}
|
|
144
|
-
return this;
|
|
145
|
-
}
|
|
146
|
-
[Symbol.iterator]() {
|
|
147
|
-
return this.resolved[Symbol.iterator]();
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
class I extends k {
|
|
151
|
-
constructor(e) {
|
|
152
|
-
super(e), this.queryParams = e.query, this.metaData = e.meta ?? {}, this.linksData = e.links ?? {}, _(this, {
|
|
153
|
-
metaData: y.ref,
|
|
154
|
-
linksData: y.ref,
|
|
155
|
-
meta: u,
|
|
156
|
-
links: u,
|
|
157
|
-
query: u
|
|
158
|
-
});
|
|
159
|
-
}
|
|
160
|
-
/** Server-side metadata attached to the last response (e.g. pagination). */
|
|
161
|
-
get meta() {
|
|
162
|
-
return this.metaData;
|
|
163
|
-
}
|
|
164
|
-
/** Links attached to the last response. */
|
|
165
|
-
get links() {
|
|
166
|
-
return this.linksData;
|
|
167
|
-
}
|
|
168
|
-
/** The query parameters that produced this array. */
|
|
169
|
-
get query() {
|
|
170
|
-
return this.queryParams;
|
|
171
|
-
}
|
|
172
|
-
/** Called by the store to update `meta` after a successful query. */
|
|
173
|
-
_setMeta(e) {
|
|
174
|
-
this.metaData = e;
|
|
175
|
-
}
|
|
176
|
-
/** Called by the store to update `links` after a successful query. */
|
|
177
|
-
_setLinks(e) {
|
|
178
|
-
this.linksData = e;
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
var T = Object.getOwnPropertyDescriptor, P = (t, e, s, i) => {
|
|
182
|
-
for (var a = i > 1 ? void 0 : i ? T(e, s) : e, r = t.length - 1, o; r >= 0; r--)
|
|
183
|
-
(o = t[r]) && (a = o(a) || a);
|
|
184
|
-
return a;
|
|
185
|
-
}, j = (t, e) => (s, i) => e(s, i, t);
|
|
186
|
-
let f = class {
|
|
187
|
-
constructor(t) {
|
|
188
|
-
this.identityMap = new q(), this.adapters = /* @__PURE__ */ new Map(), this.serializers = /* @__PURE__ */ new Map(), this.newRecords = /* @__PURE__ */ new Map(), this.newRecordTypes = /* @__PURE__ */ new WeakMap(), this.relationshipCache = /* @__PURE__ */ new WeakMap(), this.pendingMembers = /* @__PURE__ */ new WeakMap(), this._cache = null, this.coalescePending = /* @__PURE__ */ new Map(), this.coalesceScheduled = /* @__PURE__ */ new Set(), this.schema = t;
|
|
189
|
-
}
|
|
190
|
-
static refEquals(t, e) {
|
|
191
|
-
return t.id === e.id && t.type === e.type;
|
|
192
|
-
}
|
|
193
|
-
// --- registration ---
|
|
194
|
-
/** Registers an adapter for a given model name (or `'application'` as a fallback). */
|
|
195
|
-
registerAdapter(t, e) {
|
|
196
|
-
this.adapters.set(t, e);
|
|
197
|
-
}
|
|
198
|
-
/** Registers a serializer for a given model name (or `'application'` as a fallback). */
|
|
199
|
-
registerSerializer(t, e) {
|
|
200
|
-
this.serializers.set(t, e);
|
|
201
|
-
}
|
|
202
|
-
/** Registers a persistent cache layer (e.g. IndexedDB) for offline-first reads. */
|
|
203
|
-
registerCache(t) {
|
|
204
|
-
this._cache = t;
|
|
205
|
-
}
|
|
206
|
-
/**
|
|
207
|
-
* Returns the adapter for `modelName`, falling back to `'application'`.
|
|
208
|
-
* @throws when no adapter is registered.
|
|
209
|
-
*/
|
|
210
|
-
adapterFor(t) {
|
|
211
|
-
const e = this.adapters.get(t) ?? this.adapters.get("application");
|
|
212
|
-
if (!e)
|
|
213
|
-
throw new Error(`No adapter registered for "${t}"`);
|
|
214
|
-
return e;
|
|
215
|
-
}
|
|
216
|
-
/**
|
|
217
|
-
* Returns the serializer for `modelName`, falling back to `'application'`.
|
|
218
|
-
* @throws when no serializer is registered.
|
|
219
|
-
*/
|
|
220
|
-
serializerFor(t) {
|
|
221
|
-
const e = this.serializers.get(t) ?? this.serializers.get("application");
|
|
222
|
-
if (!e)
|
|
223
|
-
throw new Error(`No serializer registered for "${t}"`);
|
|
224
|
-
return e;
|
|
225
|
-
}
|
|
226
|
-
// --- creating ---
|
|
227
|
-
/**
|
|
228
|
-
* Creates a new (unsaved) record of the given type with optional initial data.
|
|
229
|
-
* The record is tracked in `newRecords` until it is saved or rolled back.
|
|
230
|
-
*
|
|
231
|
-
* @throws when `modelName` has not been registered with `SchemaService`.
|
|
232
|
-
*/
|
|
233
|
-
createRecord(t, e = {}) {
|
|
234
|
-
if (!this.schema.doesTypeExist(t))
|
|
235
|
-
throw new Error(`Unknown model type: "${t}"`);
|
|
236
|
-
const s = this.schema.modelFor(t), i = new s({ id: null, data: e, store: this });
|
|
237
|
-
return this.trackNewRecord(t, i), i;
|
|
238
|
-
}
|
|
239
|
-
trackNewRecord(t, e) {
|
|
240
|
-
let s = this.newRecords.get(t);
|
|
241
|
-
s || (s = /* @__PURE__ */ new Set(), this.newRecords.set(t, s)), s.add(e), this.newRecordTypes.set(e, t);
|
|
242
|
-
}
|
|
243
|
-
untrackNewRecord(t) {
|
|
244
|
-
var s;
|
|
245
|
-
const e = this.newRecordTypes.get(t);
|
|
246
|
-
e && ((s = this.newRecords.get(e)) == null || s.delete(t), this.newRecordTypes.delete(t));
|
|
247
|
-
}
|
|
248
|
-
// --- peeking ---
|
|
249
|
-
/**
|
|
250
|
-
* Synchronously returns a record from the identity map, or `null` when not
|
|
251
|
-
* found. Does not trigger a network request.
|
|
252
|
-
*/
|
|
253
|
-
peekRecord(t, e) {
|
|
254
|
-
const s = e == null ? null : String(e);
|
|
255
|
-
return s === null ? null : this.identityMap.get(t, s) ?? null;
|
|
256
|
-
}
|
|
257
|
-
/**
|
|
258
|
-
* Returns a live `RecordArray` backed by the identity map for `modelName`.
|
|
259
|
-
* New (unsaved) records are included at the end.
|
|
260
|
-
* Does not trigger a network request.
|
|
261
|
-
*/
|
|
262
|
-
peekAll(t) {
|
|
263
|
-
return new k({
|
|
264
|
-
modelName: t,
|
|
265
|
-
source: () => {
|
|
266
|
-
const e = this.identityMap.all(t), s = this.newRecords.get(t);
|
|
267
|
-
return !s || s.size === 0 ? e : [...e, ...s];
|
|
268
|
-
}
|
|
269
|
-
});
|
|
270
|
-
}
|
|
271
|
-
// --- push / normalize ---
|
|
272
|
-
/**
|
|
273
|
-
* Pushes a normalized document into the identity map.
|
|
274
|
-
* Side-loaded (`included`) records are pushed first.
|
|
275
|
-
*
|
|
276
|
-
* @returns The primary record(s), or `null` for empty payloads.
|
|
277
|
-
*/
|
|
278
|
-
push(t) {
|
|
279
|
-
const e = t;
|
|
280
|
-
if (e.included)
|
|
281
|
-
for (const s of e.included)
|
|
282
|
-
this.pushResource(s);
|
|
283
|
-
return e.data === null || e.data === void 0 ? null : Array.isArray(e.data) ? e.data.map((s) => this.pushResource(s)) : this.pushResource(e.data);
|
|
284
|
-
}
|
|
285
|
-
/**
|
|
286
|
-
* Normalizes a raw payload via the registered serializer and pushes the
|
|
287
|
-
* result. `modelName` is optional; when omitted the payload is pushed
|
|
288
|
-
* directly without normalization.
|
|
289
|
-
*/
|
|
290
|
-
pushPayload(t, e) {
|
|
291
|
-
let s, i;
|
|
292
|
-
typeof t == "string" ? (s = t, i = e) : (s = null, i = t);
|
|
293
|
-
const a = s ? this.serializerFor(s).normalizeResponse(
|
|
294
|
-
this,
|
|
295
|
-
this.schema.modelFor(s),
|
|
296
|
-
i,
|
|
297
|
-
null,
|
|
298
|
-
"pushPayload"
|
|
299
|
-
) : i;
|
|
300
|
-
this.push(a);
|
|
301
|
-
}
|
|
302
|
-
/**
|
|
303
|
-
* Normalizes a raw payload for `modelName` via the registered serializer
|
|
304
|
-
* and returns the `NormalizedDocument` without pushing it.
|
|
305
|
-
*/
|
|
306
|
-
normalize(t, e) {
|
|
307
|
-
return this.serializerFor(t).normalizeResponse(
|
|
308
|
-
this,
|
|
309
|
-
this.schema.modelFor(t),
|
|
310
|
-
e,
|
|
311
|
-
null,
|
|
312
|
-
"normalize"
|
|
313
|
-
);
|
|
314
|
-
}
|
|
315
|
-
/**
|
|
316
|
-
* Inserts or merges a single normalized resource into the identity map.
|
|
317
|
-
* - Existing record → calls `_applyServerData` to merge attributes and
|
|
318
|
-
* relationships in place (preserving the live reference).
|
|
319
|
-
* - New record → instantiates via `Model.push` and sets it in the map.
|
|
320
|
-
*
|
|
321
|
-
* @throws when `type` has not been registered or `id` is `null`.
|
|
322
|
-
*/
|
|
323
|
-
pushResource(t) {
|
|
324
|
-
const { type: e, id: s } = t;
|
|
325
|
-
if (!this.schema.doesTypeExist(e))
|
|
326
|
-
throw new Error(`Unknown model type: "${e}"`);
|
|
327
|
-
if (s === null)
|
|
328
|
-
throw new Error(`Cannot push a resource of type "${e}" without an id`);
|
|
329
|
-
const i = this.identityMap.get(e, s);
|
|
330
|
-
if (i)
|
|
331
|
-
return p(() => {
|
|
332
|
-
i._applyServerData(null, t.attributes ?? {}, t.relationships);
|
|
333
|
-
}), this.trackInverseForResource(i, t), i;
|
|
334
|
-
const a = this.schema.modelFor(e), r = S.push.call(a, {
|
|
335
|
-
id: s,
|
|
336
|
-
data: t.attributes ?? {},
|
|
337
|
-
relationships: t.relationships,
|
|
338
|
-
store: this
|
|
339
|
-
});
|
|
340
|
-
return this.identityMap.set(e, s, r), this.trackInverseForResource(r, t), r;
|
|
341
|
-
}
|
|
342
|
-
/**
|
|
343
|
-
* After pushing a resource, updates the inverse side of every declared
|
|
344
|
-
* inverse relationship so both sides stay consistent.
|
|
345
|
-
*/
|
|
346
|
-
trackInverseForResource(t, e) {
|
|
347
|
-
if (e.relationships)
|
|
348
|
-
for (const [s, i] of Object.entries(e.relationships)) {
|
|
349
|
-
const a = this.schema.relationshipsDefinitionFor(t.modelName).get(s);
|
|
350
|
-
if (!a || !a.options.inverse || !i.data)
|
|
351
|
-
continue;
|
|
352
|
-
const r = Array.isArray(i.data) ? i.data : [i.data];
|
|
353
|
-
for (const o of r)
|
|
354
|
-
this.addInverse(o.type, o.id, a.options.inverse, t);
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
/**
|
|
358
|
-
* Adds `inverseRecord` to the inverse relationship on `targetType:targetId`.
|
|
359
|
-
* No-ops when the target record is not in the identity map.
|
|
360
|
-
*/
|
|
361
|
-
addInverse(t, e, s, i) {
|
|
362
|
-
const a = this.identityMap.get(t, e);
|
|
363
|
-
if (!a)
|
|
364
|
-
return;
|
|
365
|
-
const o = this.schema.relationshipsDefinitionFor(t).get(s);
|
|
366
|
-
if (!o)
|
|
367
|
-
return;
|
|
368
|
-
const n = a._getRelationshipRef(s), h = { type: i.modelName, id: i.id };
|
|
369
|
-
p(() => {
|
|
370
|
-
if (o.kind === "hasMany") {
|
|
371
|
-
const c = n != null && n.data && Array.isArray(n.data) ? n.data : [];
|
|
372
|
-
c.some((d) => f.refEquals(d, h)) || a._setRelationshipRef(s, { data: [...c, h] });
|
|
373
|
-
} else
|
|
374
|
-
a._setRelationshipRef(s, { data: h });
|
|
375
|
-
});
|
|
376
|
-
}
|
|
377
|
-
/**
|
|
378
|
-
* Removes `inverseRecord` from the inverse relationship on `targetType:targetId`.
|
|
379
|
-
* No-ops when the target record is not in the identity map.
|
|
380
|
-
*/
|
|
381
|
-
removeInverse(t, e, s, i) {
|
|
382
|
-
const a = this.identityMap.get(t, e);
|
|
383
|
-
if (!a)
|
|
384
|
-
return;
|
|
385
|
-
const o = this.schema.relationshipsDefinitionFor(t).get(s);
|
|
386
|
-
if (!o)
|
|
387
|
-
return;
|
|
388
|
-
const n = a._getRelationshipRef(s);
|
|
389
|
-
p(() => {
|
|
390
|
-
if (o.kind === "hasMany") {
|
|
391
|
-
const c = (n != null && n.data && Array.isArray(n.data) ? n.data : []).filter((d) => !(d.id === i.id && d.type === i.modelName));
|
|
392
|
-
a._setRelationshipRef(s, { data: c });
|
|
393
|
-
} else
|
|
394
|
-
a._setRelationshipRef(s, { data: null });
|
|
395
|
-
});
|
|
396
|
-
}
|
|
397
|
-
// --- unload ---
|
|
398
|
-
/**
|
|
399
|
-
* Removes a record from the identity map and clears its relationship cache.
|
|
400
|
-
* Called by `record.unloadRecord()` and internally after `deleteRecord`.
|
|
401
|
-
*/
|
|
402
|
-
unloadRecord(t) {
|
|
403
|
-
t.id !== null && this.identityMap.delete(t.modelName, t.id), this.untrackNewRecord(t), this.relationshipCache.delete(t);
|
|
404
|
-
}
|
|
405
|
-
/**
|
|
406
|
-
* Unloads all records for `modelName`, or all records across all types when
|
|
407
|
-
* `modelName` is omitted.
|
|
408
|
-
*/
|
|
409
|
-
unloadAll(t) {
|
|
410
|
-
var e;
|
|
411
|
-
if (t) {
|
|
412
|
-
for (const s of this.identityMap.all(t))
|
|
413
|
-
this.relationshipCache.delete(s);
|
|
414
|
-
this.identityMap.clear(t), (e = this.newRecords.get(t)) == null || e.clear();
|
|
415
|
-
} else
|
|
416
|
-
this.identityMap.clear(), this.newRecords.clear();
|
|
417
|
-
}
|
|
418
|
-
// --- find ---
|
|
419
|
-
/**
|
|
420
|
-
* Finds a single record by id. Returns the cached record immediately when
|
|
421
|
-
* `options.reload` is not set; otherwise re-fetches.
|
|
422
|
-
*
|
|
423
|
-
* When the adapter has `coalesceFindRequests: true` and `findMany` is
|
|
424
|
-
* implemented, multiple concurrent `findRecord` calls for the same type
|
|
425
|
-
* are batched into a single `findMany` network request.
|
|
426
|
-
*/
|
|
427
|
-
async findRecord(t, e, s = {}) {
|
|
428
|
-
const i = this.peekRecord(t, e);
|
|
429
|
-
if (i && !s.reload && !s.include)
|
|
430
|
-
return i;
|
|
431
|
-
if (!s.reload && !s.include && this._cache) {
|
|
432
|
-
const l = await this._cache.get(t, e);
|
|
433
|
-
if (l)
|
|
434
|
-
return this.push({
|
|
435
|
-
data: {
|
|
436
|
-
type: l.modelName,
|
|
437
|
-
id: l.id,
|
|
438
|
-
attributes: l.attributes,
|
|
439
|
-
relationships: l.relationships
|
|
440
|
-
}
|
|
441
|
-
});
|
|
442
|
-
}
|
|
443
|
-
const a = this.adapterFor(t);
|
|
444
|
-
if (a.coalesceFindRequests && a.findMany && !s.include)
|
|
445
|
-
return this.scheduleCoalescedFind(t, e);
|
|
446
|
-
const r = i ? this.createSnapshot(i) : this.createEmptySnapshot(t, e), o = s.include ? { include: s.include, adapterOptions: s.adapterOptions } : s.adapterOptions ? { adapterOptions: s.adapterOptions } : void 0, n = await a.findRecord(this, t, e, r, o), h = m(n), c = this.serializerFor(t).normalizeResponse(
|
|
447
|
-
this,
|
|
448
|
-
this.schema.modelFor(t),
|
|
449
|
-
n,
|
|
450
|
-
e,
|
|
451
|
-
"findRecord"
|
|
452
|
-
), d = this.push(c);
|
|
453
|
-
if (this._cache) {
|
|
454
|
-
const l = h ? v(h) : null;
|
|
455
|
-
l !== 0 && this.cacheNormalizedDocument(c, l ?? void 0);
|
|
456
|
-
}
|
|
457
|
-
return d;
|
|
458
|
-
}
|
|
459
|
-
/**
|
|
460
|
-
* Fetches all records of `modelName` from the server and returns a
|
|
461
|
-
* `RecordArray` backed by the identity map.
|
|
462
|
-
*/
|
|
463
|
-
async findAll(t, e = {}) {
|
|
464
|
-
const s = this.adapterFor(t), i = e.include ? { include: e.include, adapterOptions: e.adapterOptions } : e.adapterOptions ? { adapterOptions: e.adapterOptions } : void 0, a = await s.findAll(this, t, null, [], i), r = m(a), o = this.serializerFor(t).normalizeResponse(
|
|
465
|
-
this,
|
|
466
|
-
this.schema.modelFor(t),
|
|
467
|
-
a,
|
|
468
|
-
null,
|
|
469
|
-
"findAll"
|
|
470
|
-
);
|
|
471
|
-
if (this.push(o), this._cache) {
|
|
472
|
-
const n = r ? v(r) : null;
|
|
473
|
-
n !== 0 && this.cacheNormalizedDocument(o, n ?? void 0);
|
|
474
|
-
}
|
|
475
|
-
return this.peekAll(t);
|
|
476
|
-
}
|
|
477
|
-
/**
|
|
478
|
-
* Executes an adapter query and returns an `AdapterPopulatedRecordArray`
|
|
479
|
-
* whose `update()` method re-issues the same query.
|
|
480
|
-
*/
|
|
481
|
-
async query(t, e) {
|
|
482
|
-
const s = [], i = new I({
|
|
483
|
-
modelName: t,
|
|
484
|
-
query: e,
|
|
485
|
-
source: () => s.map((a) => this.peekRecord(t, a)).filter((a) => a !== null),
|
|
486
|
-
update: async () => {
|
|
487
|
-
await this.runQuery(t, e, i, s);
|
|
488
|
-
}
|
|
489
|
-
});
|
|
490
|
-
return await this.runQuery(t, e, i, s), i;
|
|
491
|
-
}
|
|
492
|
-
async runQuery(t, e, s, i) {
|
|
493
|
-
const r = await this.adapterFor(t).query(this, t, e, s), o = this.serializerFor(t).normalizeResponse(
|
|
494
|
-
this,
|
|
495
|
-
this.schema.modelFor(t),
|
|
496
|
-
r,
|
|
497
|
-
null,
|
|
498
|
-
"query"
|
|
499
|
-
);
|
|
500
|
-
if (this.push(o), i.length = 0, Array.isArray(o.data))
|
|
501
|
-
for (const n of o.data)
|
|
502
|
-
n.id && i.push(n.id);
|
|
503
|
-
o.meta && s._setMeta(o.meta), o.links && s._setLinks(o.links);
|
|
504
|
-
}
|
|
505
|
-
/**
|
|
506
|
-
* Executes an adapter query that returns at most one record.
|
|
507
|
-
* Returns `null` when the adapter returns an empty payload.
|
|
508
|
-
*/
|
|
509
|
-
async queryRecord(t, e) {
|
|
510
|
-
const i = await this.adapterFor(t).queryRecord(this, t, e), a = this.serializerFor(t).normalizeResponse(
|
|
511
|
-
this,
|
|
512
|
-
this.schema.modelFor(t),
|
|
513
|
-
i,
|
|
514
|
-
null,
|
|
515
|
-
"queryRecord"
|
|
516
|
-
), r = this.push(a);
|
|
517
|
-
return Array.isArray(r) ? r[0] ?? null : r ?? null;
|
|
518
|
-
}
|
|
519
|
-
// --- save / delete / reload from Model ---
|
|
520
|
-
/**
|
|
521
|
-
* Persists a record to the server.
|
|
522
|
-
* - New records → `adapter.createRecord` (POST)
|
|
523
|
-
* - Existing dirty records → `adapter.updateRecord` (PUT) by default
|
|
524
|
-
* - With `{ patch: true }` → `adapter.patchRecord` (PATCH, partial payload)
|
|
525
|
-
*
|
|
526
|
-
* After the response is received the server data is applied back to the
|
|
527
|
-
* record via `_applyServerData` so it transitions to `saved`.
|
|
528
|
-
*/
|
|
529
|
-
async saveRecord(t, e = {}) {
|
|
530
|
-
const s = this.adapterFor(t.modelName), i = this.createSnapshot(t), { isNew: a } = t;
|
|
531
|
-
let r;
|
|
532
|
-
a ? r = await s.createRecord(this, t.modelName, i) : e.patch && s.patchRecord ? r = await s.patchRecord(this, t.modelName, i) : r = await s.updateRecord(this, t.modelName, i);
|
|
533
|
-
const o = this.serializerFor(t.modelName).normalizeResponse(
|
|
534
|
-
this,
|
|
535
|
-
this.schema.modelFor(t.modelName),
|
|
536
|
-
r,
|
|
537
|
-
t.id,
|
|
538
|
-
a ? "createRecord" : "updateRecord"
|
|
539
|
-
), n = o.data;
|
|
540
|
-
if (n) {
|
|
541
|
-
const h = n.id ?? t.id;
|
|
542
|
-
p(() => {
|
|
543
|
-
t._applyServerData(h, n.attributes ?? {}, n.relationships);
|
|
544
|
-
}), a && h && (this.untrackNewRecord(t), this.identityMap.set(t.modelName, h, t));
|
|
545
|
-
}
|
|
546
|
-
if (o.included)
|
|
547
|
-
for (const h of o.included)
|
|
548
|
-
this.pushResource(h);
|
|
549
|
-
if (this._cache && t.id) {
|
|
550
|
-
const h = t, c = {};
|
|
551
|
-
for (const [d, l] of h._relationships)
|
|
552
|
-
c[d] = l;
|
|
553
|
-
this._cache.set(t.modelName, t.id, { ...h._data }, {
|
|
554
|
-
relationships: Object.keys(c).length > 0 ? c : void 0
|
|
555
|
-
});
|
|
556
|
-
}
|
|
557
|
-
return t;
|
|
558
|
-
}
|
|
559
|
-
/**
|
|
560
|
-
* Issues a DELETE request and unloads the record from the identity map.
|
|
561
|
-
*/
|
|
562
|
-
async deleteRecord(t) {
|
|
563
|
-
const e = this.adapterFor(t.modelName), s = this.createSnapshot(t);
|
|
564
|
-
return await e.deleteRecord(this, t.modelName, s), this._cache && t.id && this._cache.invalidate(t.modelName, t.id), this.unloadRecord(t), t;
|
|
565
|
-
}
|
|
566
|
-
/**
|
|
567
|
-
* Re-fetches a record from the server and merges the response into the
|
|
568
|
-
* existing instance.
|
|
569
|
-
*/
|
|
570
|
-
async reloadRecord(t) {
|
|
571
|
-
if (!t.id)
|
|
572
|
-
throw new Error("Cannot reload a record without an id");
|
|
573
|
-
const e = this.adapterFor(t.modelName), s = this.createSnapshot(t), i = await e.findRecord(this, t.modelName, t.id, s), a = this.serializerFor(t.modelName).normalizeResponse(
|
|
574
|
-
this,
|
|
575
|
-
this.schema.modelFor(t.modelName),
|
|
576
|
-
i,
|
|
577
|
-
t.id,
|
|
578
|
-
"findRecord"
|
|
579
|
-
);
|
|
580
|
-
return this.push(a), t;
|
|
581
|
-
}
|
|
582
|
-
// --- snapshot ---
|
|
583
|
-
/**
|
|
584
|
-
* Creates a `Snapshot` for a live record.
|
|
585
|
-
* The snapshot reads directly from the record's internal state so it
|
|
586
|
-
* reflects the current (possibly dirty) values.
|
|
587
|
-
*/
|
|
588
|
-
createSnapshot(t) {
|
|
589
|
-
const { modelName: e } = t, s = this.schema.attributesDefinitionFor(e), i = this.schema.relationshipsDefinitionFor(e), a = t;
|
|
590
|
-
return {
|
|
591
|
-
id: t.id,
|
|
592
|
-
modelName: e,
|
|
593
|
-
record: t,
|
|
594
|
-
attr: (r) => a._data[r],
|
|
595
|
-
belongsTo: (r, o) => {
|
|
596
|
-
const n = a._getRelationshipRef(r);
|
|
597
|
-
return !(n != null && n.data) || Array.isArray(n.data) ? null : o != null && o.id ? n.data.id : this.peekRecord(n.data.type, n.data.id);
|
|
598
|
-
},
|
|
599
|
-
hasMany: (r, o) => {
|
|
600
|
-
const n = a._getRelationshipRef(r), h = n != null && n.data && Array.isArray(n.data) ? n.data : [];
|
|
601
|
-
return o != null && o.ids ? h.map((c) => c.id) : h.map((c) => this.peekRecord(c.type, c.id)).filter((c) => c !== null);
|
|
602
|
-
},
|
|
603
|
-
changedAttributes: () => a.changedAttributes(),
|
|
604
|
-
eachAttribute: (r) => {
|
|
605
|
-
for (const [o, n] of s)
|
|
606
|
-
r(o, n);
|
|
607
|
-
},
|
|
608
|
-
eachRelationship: (r) => {
|
|
609
|
-
for (const [o, n] of i)
|
|
610
|
-
r(o, n);
|
|
611
|
-
}
|
|
612
|
-
};
|
|
613
|
-
}
|
|
614
|
-
/**
|
|
615
|
-
* Creates a placeholder `Snapshot` for a record that is not yet in the
|
|
616
|
-
* identity map (used when fetching a record that isn't cached).
|
|
617
|
-
*/
|
|
618
|
-
createEmptySnapshot(t, e) {
|
|
619
|
-
const s = this.schema.attributesDefinitionFor(t), i = this.schema.relationshipsDefinitionFor(t);
|
|
620
|
-
return {
|
|
621
|
-
id: e,
|
|
622
|
-
modelName: t,
|
|
623
|
-
record: null,
|
|
624
|
-
attr: () => {
|
|
625
|
-
},
|
|
626
|
-
belongsTo: () => null,
|
|
627
|
-
hasMany: () => [],
|
|
628
|
-
changedAttributes: () => ({}),
|
|
629
|
-
eachAttribute: (a) => {
|
|
630
|
-
for (const [r, o] of s)
|
|
631
|
-
a(r, o);
|
|
632
|
-
},
|
|
633
|
-
eachRelationship: (a) => {
|
|
634
|
-
for (const [r, o] of i)
|
|
635
|
-
a(r, o);
|
|
636
|
-
}
|
|
637
|
-
};
|
|
638
|
-
}
|
|
639
|
-
// --- relationship resolution (called by Model) ---
|
|
640
|
-
getRelationshipCache(t, e) {
|
|
641
|
-
var s;
|
|
642
|
-
return (s = this.relationshipCache.get(t)) == null ? void 0 : s.get(e);
|
|
643
|
-
}
|
|
644
|
-
setRelationshipCache(t, e, s) {
|
|
645
|
-
let i = this.relationshipCache.get(t);
|
|
646
|
-
i || (i = /* @__PURE__ */ new Map(), this.relationshipCache.set(t, i)), i.set(e, s);
|
|
647
|
-
}
|
|
648
|
-
/**
|
|
649
|
-
* Called by the `Model` relationship getter to resolve a relationship.
|
|
650
|
-
*
|
|
651
|
-
* - **Async** `belongsTo` → returns an `AsyncBelongsTo` wrapper.
|
|
652
|
-
* - **Async** `hasMany` → returns an `AsyncHasMany` wrapper.
|
|
653
|
-
* - **Sync** `belongsTo` → peeks the related record from the identity map.
|
|
654
|
-
* - **Sync** `hasMany` → returns a `ManyArray` backed by the store.
|
|
655
|
-
*
|
|
656
|
-
* Results are cached per record + name so the same proxy is returned on
|
|
657
|
-
* repeated accesses (important for MobX observability).
|
|
658
|
-
*/
|
|
659
|
-
resolveRelationship(t, e, s) {
|
|
660
|
-
const i = s.options.async === !0, a = this.getRelationshipCache(t, e);
|
|
661
|
-
if (a)
|
|
662
|
-
return a;
|
|
663
|
-
const r = {
|
|
664
|
-
parent: t,
|
|
665
|
-
name: e,
|
|
666
|
-
meta: s,
|
|
667
|
-
store: this
|
|
668
|
-
};
|
|
669
|
-
if (i) {
|
|
670
|
-
if (s.kind === "belongsTo") {
|
|
671
|
-
const h = new C(r);
|
|
672
|
-
return this.setRelationshipCache(t, e, h), h;
|
|
673
|
-
}
|
|
674
|
-
const n = new E(r);
|
|
675
|
-
return this.setRelationshipCache(t, e, n), n;
|
|
676
|
-
}
|
|
677
|
-
if (s.kind === "belongsTo") {
|
|
678
|
-
const n = t._getRelationshipRef(e);
|
|
679
|
-
return !(n != null && n.data) || Array.isArray(n.data) ? null : this.peekRecord(n.data.type, n.data.id);
|
|
680
|
-
}
|
|
681
|
-
const o = new O(r);
|
|
682
|
-
return this.setRelationshipCache(t, e, o), o;
|
|
683
|
-
}
|
|
684
|
-
/**
|
|
685
|
-
* Called by the `Model` `belongsTo` setter to update a relationship ref
|
|
686
|
-
* and keep its inverse in sync.
|
|
687
|
-
*/
|
|
688
|
-
setRelationshipValue(t, e, s, i) {
|
|
689
|
-
if (s.kind !== "belongsTo")
|
|
690
|
-
return;
|
|
691
|
-
const a = t._getRelationshipRef(e), r = a != null && a.data && !Array.isArray(a.data) ? a.data : null;
|
|
692
|
-
if (i == null) {
|
|
693
|
-
p(() => {
|
|
694
|
-
t._setRelationshipRef(e, { data: null });
|
|
695
|
-
}), r && s.options.inverse && this.removeInverse(r.type, r.id, s.options.inverse, t);
|
|
696
|
-
return;
|
|
697
|
-
}
|
|
698
|
-
const o = i, n = { type: o.modelName, id: o.id };
|
|
699
|
-
p(() => {
|
|
700
|
-
t._setRelationshipRef(e, { data: n });
|
|
701
|
-
}), s.options.inverse && (r && !f.refEquals(r, n) && this.removeInverse(r.type, r.id, s.options.inverse, t), this.addInverse(n.type, n.id, s.options.inverse, t));
|
|
702
|
-
}
|
|
703
|
-
// --- hooks used by ManyArray ---
|
|
704
|
-
/** Returns the raw relationship ref stored on `record` for `name`. */
|
|
705
|
-
_getRelationshipRefFor(t, e) {
|
|
706
|
-
return t._getRelationshipRef(e);
|
|
707
|
-
}
|
|
708
|
-
/** Returns any pending (unsaved) members for a `hasMany` relationship. */
|
|
709
|
-
_getPendingMembers(t, e) {
|
|
710
|
-
var s;
|
|
711
|
-
return ((s = this.pendingMembers.get(t)) == null ? void 0 : s.get(e)) ?? [];
|
|
712
|
-
}
|
|
713
|
-
addPendingMember(t, e, s) {
|
|
714
|
-
let i = this.pendingMembers.get(t);
|
|
715
|
-
i || (i = /* @__PURE__ */ new Map(), this.pendingMembers.set(t, i));
|
|
716
|
-
let a = i.get(e);
|
|
717
|
-
a || (a = y.set(), i.set(e, a)), a.add(s);
|
|
718
|
-
}
|
|
719
|
-
removePendingMember(t, e, s) {
|
|
720
|
-
var i, a;
|
|
721
|
-
(a = (i = this.pendingMembers.get(t)) == null ? void 0 : i.get(e)) == null || a.delete(s);
|
|
722
|
-
}
|
|
723
|
-
/**
|
|
724
|
-
* Appends `value` to the `hasMany` relationship ref on `record` and syncs
|
|
725
|
-
* the inverse. Unsaved records (`value.id === null`) are tracked as
|
|
726
|
-
* "pending members" until they are persisted.
|
|
727
|
-
*/
|
|
728
|
-
_hasManyAppend(t, e, s, i) {
|
|
729
|
-
if (i.id === null) {
|
|
730
|
-
if (this.addPendingMember(t, e, i), s.options.inverse) {
|
|
731
|
-
const n = this.schema.relationshipsDefinitionFor(i.modelName).get(s.options.inverse);
|
|
732
|
-
(n == null ? void 0 : n.kind) === "belongsTo" && p(() => {
|
|
733
|
-
i._setRelationshipRef(s.options.inverse, {
|
|
734
|
-
data: { type: t.modelName, id: t.id }
|
|
735
|
-
});
|
|
736
|
-
});
|
|
737
|
-
}
|
|
738
|
-
return;
|
|
739
|
-
}
|
|
740
|
-
const a = this._getRelationshipRefFor(t, e), r = a != null && a.data && Array.isArray(a.data) ? a.data : [], o = { type: i.modelName, id: i.id };
|
|
741
|
-
r.some((n) => f.refEquals(n, o)) || p(() => {
|
|
742
|
-
t._setRelationshipRef(e, { data: [...r, o] });
|
|
743
|
-
}), s.options.inverse && this.addInverse(i.modelName, i.id, s.options.inverse, t);
|
|
744
|
-
}
|
|
745
|
-
/**
|
|
746
|
-
* Removes `value` from the `hasMany` relationship ref on `record` and syncs
|
|
747
|
-
* the inverse. Pending members are removed from the pending set.
|
|
748
|
-
*/
|
|
749
|
-
_hasManyRemove(t, e, s, i) {
|
|
750
|
-
if (i.id === null) {
|
|
751
|
-
this.removePendingMember(t, e, i);
|
|
752
|
-
return;
|
|
753
|
-
}
|
|
754
|
-
const a = this._getRelationshipRefFor(t, e), o = (a != null && a.data && Array.isArray(a.data) ? a.data : []).filter(
|
|
755
|
-
(n) => !(n.id === i.id && n.type === i.modelName)
|
|
756
|
-
);
|
|
757
|
-
p(() => {
|
|
758
|
-
t._setRelationshipRef(e, { data: o });
|
|
759
|
-
}), s.options.inverse && this.removeInverse(i.modelName, i.id, s.options.inverse, t);
|
|
760
|
-
}
|
|
761
|
-
// --- persistent cache helpers ---
|
|
762
|
-
cacheNormalizedDocument(t, e) {
|
|
763
|
-
if (!this._cache)
|
|
764
|
-
return;
|
|
765
|
-
const s = [];
|
|
766
|
-
t.data && (Array.isArray(t.data) ? s.push(...t.data) : s.push(t.data)), t.included && s.push(...t.included);
|
|
767
|
-
for (const i of s)
|
|
768
|
-
i.id && this._cache.set(i.type, i.id, i.attributes ?? {}, {
|
|
769
|
-
relationships: i.relationships,
|
|
770
|
-
ttl: e
|
|
771
|
-
});
|
|
772
|
-
}
|
|
773
|
-
scheduleCoalescedFind(t, e) {
|
|
774
|
-
return new Promise((s, i) => {
|
|
775
|
-
let a = this.coalescePending.get(t);
|
|
776
|
-
a || (a = /* @__PURE__ */ new Map(), this.coalescePending.set(t, a));
|
|
777
|
-
let r = a.get(e);
|
|
778
|
-
r || (r = [], a.set(e, r)), r.push({ resolve: s, reject: i }), this.coalesceScheduled.has(t) || (this.coalesceScheduled.add(t), queueMicrotask(() => this.flushCoalescedFind(t)));
|
|
779
|
-
});
|
|
780
|
-
}
|
|
781
|
-
async flushCoalescedFind(t) {
|
|
782
|
-
this.coalesceScheduled.delete(t);
|
|
783
|
-
const e = this.coalescePending.get(t);
|
|
784
|
-
if (!e || e.size === 0)
|
|
785
|
-
return;
|
|
786
|
-
const s = new Map(e);
|
|
787
|
-
e.clear();
|
|
788
|
-
const i = Array.from(s.keys()), a = this.adapterFor(t);
|
|
789
|
-
try {
|
|
790
|
-
const r = i.map((h) => {
|
|
791
|
-
const c = this.peekRecord(t, h);
|
|
792
|
-
return c ? this.createSnapshot(c) : this.createEmptySnapshot(t, h);
|
|
793
|
-
}), o = await a.findMany(this, t, i, r), n = this.serializerFor(t).normalizeResponse(
|
|
794
|
-
this,
|
|
795
|
-
this.schema.modelFor(t),
|
|
796
|
-
o,
|
|
797
|
-
null,
|
|
798
|
-
"findMany"
|
|
799
|
-
);
|
|
800
|
-
this.push(n);
|
|
801
|
-
for (const h of i) {
|
|
802
|
-
const c = this.peekRecord(t, h), d = s.get(h);
|
|
803
|
-
if (d)
|
|
804
|
-
for (const l of d)
|
|
805
|
-
c ? l.resolve(c) : l.reject(new Error(`Record not found after findMany: ${t}:${h}`));
|
|
806
|
-
}
|
|
807
|
-
} catch (r) {
|
|
808
|
-
for (const o of s.values())
|
|
809
|
-
for (const n of o)
|
|
810
|
-
n.reject(r);
|
|
811
|
-
}
|
|
812
|
-
}
|
|
813
|
-
// --- liveQuery ---
|
|
814
|
-
/**
|
|
815
|
-
* Returns a reactive `RecordArray` that auto-updates whenever records matching
|
|
816
|
-
* the predicate are added, removed, or mutated in the identity map.
|
|
817
|
-
*
|
|
818
|
-
* The underlying computed uses `keepAlive: true` so it remains cached even
|
|
819
|
-
* without active MobX observers — useful for long-lived filtered views.
|
|
820
|
-
*
|
|
821
|
-
* @param modelName - The registered model type to query.
|
|
822
|
-
* @param predicate - Filter function applied to each record of `modelName`.
|
|
823
|
-
* @returns A live `RecordArray` containing only records that satisfy `predicate`.
|
|
824
|
-
*/
|
|
825
|
-
liveQuery(t, e) {
|
|
826
|
-
return new k({
|
|
827
|
-
modelName: t,
|
|
828
|
-
keepAlive: !0,
|
|
829
|
-
source: () => {
|
|
830
|
-
const s = this.identityMap.all(t), i = this.newRecords.get(t);
|
|
831
|
-
return (i && i.size > 0 ? [...s, ...i] : s).filter(e);
|
|
832
|
-
}
|
|
833
|
-
});
|
|
834
|
-
}
|
|
835
|
-
// --- optimisticUpdate ---
|
|
836
|
-
/**
|
|
837
|
-
* Applies attribute changes to a record immediately (optimistically), then
|
|
838
|
-
* executes `persistFn`. If `persistFn` throws, the record is automatically
|
|
839
|
-
* rolled back to its state before the optimistic update.
|
|
840
|
-
*
|
|
841
|
-
* @param record - The record to update optimistically.
|
|
842
|
-
* @param optimisticAttributes - Attributes to apply before persistence.
|
|
843
|
-
* @param persistFn - Async function that persists the change (e.g. `record.save()`).
|
|
844
|
-
* @returns The record on success.
|
|
845
|
-
* @throws Re-throws the error from `persistFn` after rollback.
|
|
846
|
-
*/
|
|
847
|
-
async optimisticUpdate(t, e, s) {
|
|
848
|
-
const i = t, a = { ...i._data };
|
|
849
|
-
p(() => {
|
|
850
|
-
Object.assign(i._data, e);
|
|
851
|
-
});
|
|
852
|
-
try {
|
|
853
|
-
return await s(), t;
|
|
854
|
-
} catch (r) {
|
|
855
|
-
throw p(() => {
|
|
856
|
-
for (const [o, n] of Object.entries(a))
|
|
857
|
-
i._data[o] = n;
|
|
858
|
-
}), r;
|
|
859
|
-
}
|
|
860
|
-
}
|
|
861
|
-
// --- runInTransaction ---
|
|
862
|
-
/**
|
|
863
|
-
* Executes multiple store mutations as a single MobX action, guaranteeing
|
|
864
|
-
* that observers (and therefore UI renders) react only once — after all
|
|
865
|
-
* mutations have been applied.
|
|
866
|
-
*
|
|
867
|
-
* @param callback - Synchronous function containing one or more store mutations.
|
|
868
|
-
*/
|
|
869
|
-
runInTransaction(t) {
|
|
870
|
-
p(t);
|
|
871
|
-
}
|
|
872
|
-
// --- SSR: serialize / hydrate ---
|
|
873
|
-
/**
|
|
874
|
-
* Produces a JSON-serializable snapshot of all records in the identity map.
|
|
875
|
-
* Designed for server-side rendering: serialize on the server, transfer as
|
|
876
|
-
* JSON, then `hydrate()` on the client to restore the full store state
|
|
877
|
-
* without network requests.
|
|
878
|
-
*
|
|
879
|
-
* @param options.exclude - Per-model-type list of attribute keys to omit
|
|
880
|
-
* (e.g. `{ user: ['password', 'token'] }`) to prevent leaking sensitive
|
|
881
|
-
* data in SSR payloads.
|
|
882
|
-
* @returns A snapshot object safe to pass through `JSON.stringify`.
|
|
883
|
-
*/
|
|
884
|
-
serialize(t = {}) {
|
|
885
|
-
var i;
|
|
886
|
-
const e = {}, s = this.identityMap._buckets;
|
|
887
|
-
for (const [a, r] of s) {
|
|
888
|
-
const o = (i = t.exclude) == null ? void 0 : i[a], n = [];
|
|
889
|
-
for (const [h, c] of r) {
|
|
890
|
-
const d = c;
|
|
891
|
-
let l;
|
|
892
|
-
if (o && o.length > 0) {
|
|
893
|
-
l = {};
|
|
894
|
-
for (const [R, w] of Object.entries(d._data))
|
|
895
|
-
o.includes(R) || (l[R] = w);
|
|
896
|
-
} else
|
|
897
|
-
l = { ...d._data };
|
|
898
|
-
const g = {
|
|
899
|
-
id: h,
|
|
900
|
-
attributes: l
|
|
901
|
-
};
|
|
902
|
-
if (d._relationships && d._relationships.size > 0) {
|
|
903
|
-
const R = {};
|
|
904
|
-
for (const [w, A] of d._relationships)
|
|
905
|
-
R[w] = A;
|
|
906
|
-
g.relationships = R;
|
|
907
|
-
}
|
|
908
|
-
n.push(g);
|
|
909
|
-
}
|
|
910
|
-
n.length > 0 && (e[a] = n);
|
|
911
|
-
}
|
|
912
|
-
return { records: e };
|
|
913
|
-
}
|
|
914
|
-
/**
|
|
915
|
-
* Restores records from a snapshot produced by `serialize()` into this store
|
|
916
|
-
* instance. All records are pushed into the identity map in `loaded.saved`
|
|
917
|
-
* state — no network requests are issued.
|
|
918
|
-
*
|
|
919
|
-
* @param snapshot - A snapshot object previously returned by `serialize()`.
|
|
920
|
-
*/
|
|
921
|
-
hydrate(t) {
|
|
922
|
-
p(() => {
|
|
923
|
-
for (const [e, s] of Object.entries(t.records))
|
|
924
|
-
for (const i of s)
|
|
925
|
-
this.pushResource({
|
|
926
|
-
type: e,
|
|
927
|
-
id: i.id,
|
|
928
|
-
attributes: i.attributes,
|
|
929
|
-
relationships: i.relationships
|
|
930
|
-
});
|
|
931
|
-
});
|
|
932
|
-
}
|
|
933
|
-
/**
|
|
934
|
-
* Factory method that creates a new `Store` and immediately hydrates it from
|
|
935
|
-
* the given snapshot. Convenience for SSR client-side bootstrap.
|
|
936
|
-
*
|
|
937
|
-
* @param schema - SchemaService with all model types registered.
|
|
938
|
-
* @param snapshot - A snapshot object previously returned by `serialize()`.
|
|
939
|
-
* @returns A fully populated `Store` instance ready for use.
|
|
940
|
-
*/
|
|
941
|
-
static hydrate(t, e) {
|
|
942
|
-
const s = new f(t);
|
|
943
|
-
return s.hydrate(e), s;
|
|
944
|
-
}
|
|
945
|
-
};
|
|
946
|
-
f = P([
|
|
947
|
-
M(),
|
|
948
|
-
F(),
|
|
949
|
-
j(0, z(D))
|
|
950
|
-
], f);
|
|
951
|
-
export {
|
|
952
|
-
I as A,
|
|
953
|
-
q as I,
|
|
954
|
-
k as R,
|
|
955
|
-
f as S
|
|
956
|
-
};
|
|
957
|
-
//# sourceMappingURL=Store-Bm5JivTc.js.map
|