@prestizni-software/server-dem 0.4.86 → 0.4.88

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.
@@ -1,26 +1,18 @@
1
1
  import "reflect-metadata";
2
2
  import _ from "lodash";
3
- import { EVENT_INTERNAL_PRE_LOADED, EVENT_DELETE, EVENT_GET, EVENT_NEW, EVENT_UPDATE, } from "./CommonTypes.js";
3
+ import { EVENT_INTERNAL_PRE_LOADED, EVENT_DELETE, EVENT_GET, EVENT_NEW, EVENT_UPDATE, globalCache, } from "./CommonTypes.js";
4
4
  import { ObjectId } from "bson";
5
- import { stringSimilarity } from "string-similarity-js";
6
5
  export class AutoUpdatedClientObject {
7
- //From server type for overlapping keys
8
6
  entry;
9
7
  preLoad;
10
8
  registerSocket;
11
9
  readyLoggers;
12
10
  loadFromDB(a) { }
13
11
  setValue_(a, b) { }
14
- //-*--
15
12
  socket;
16
13
  data;
17
14
  isServer = false;
18
- loggers = {
19
- info: () => { },
20
- debug: () => { },
21
- error: () => { },
22
- warn: () => { },
23
- };
15
+ loggers;
24
16
  isLoading = true;
25
17
  isLoadingReferences = true;
26
18
  checkedMissingRefs = false;
@@ -33,36 +25,21 @@ export class AutoUpdatedClientObject {
33
25
  toChangeOnParents = [];
34
26
  callbacks;
35
27
  loadReferencesAsync = async () => {
36
- if (this.isLoaded) {
37
- try {
38
- this.generateSettersAndGetters();
39
- await this.loadForceReferences();
40
- for (const thing of this.toChangeOnParents) {
41
- await this.setValue__(thing.key, thing.value, true, false, true);
42
- }
43
- }
44
- catch (error) {
45
- this.loggers.error("Error loading references");
46
- this.loggers.error(error.message);
47
- this.loggers.error(error.stack);
48
- }
49
- this.isLoadingReferences = false;
50
- return;
51
- }
52
- await this.waitForPreloaded();
53
- this.generateSettersAndGetters();
54
28
  try {
29
+ if (!this.isLoaded) {
30
+ await this.waitForPreloaded();
31
+ }
32
+ this.generateSettersAndGetters();
55
33
  await this.loadForceReferences();
56
34
  for (const thing of this.toChangeOnParents) {
57
- await this.setValue__(thing.key, thing.value, true, false, true);
35
+ await this.setValue__(thing.key, thing.value, true, false, false, true);
58
36
  }
59
- this.isLoadingReferences = false;
60
37
  }
61
38
  catch (error) {
39
+ this.loggers.error("Error loading references: " + error.message);
40
+ }
41
+ finally {
62
42
  this.isLoadingReferences = false;
63
- this.loggers.error("Error loading references");
64
- this.loggers.error(error.message);
65
- this.loggers.error(error.stack);
66
43
  }
67
44
  };
68
45
  /** @deprecated Use loadReferencesAsync instead */
@@ -74,7 +51,6 @@ export class AutoUpdatedClientObject {
74
51
  !loggers ||
75
52
  !className ||
76
53
  !parentManager ||
77
- !callback ||
78
54
  !emitter) {
79
55
  this.classParam = classParam;
80
56
  this.socket = socket;
@@ -98,64 +74,36 @@ export class AutoUpdatedClientObject {
98
74
  throw new Error("Missing arguments???");
99
75
  }
100
76
  this.classParam = classParam;
101
- if (typeof data !== "string" && data._id) {
102
- processIsRefProperties(data, this, undefined, [], loggers);
103
- }
77
+ this.socket = socket;
104
78
  this.isServer = isServer;
105
79
  this.emitter = emitter;
106
80
  this.isLoadingReferences = true;
107
81
  this.isLoading = true;
108
82
  this.parentManager = parentManager;
109
83
  this.className = className;
110
- this.properties = Reflect.getMetadata("props", classParam.prototype);
84
+ const allProps = new Set();
85
+ let proto_ = classParam.prototype;
86
+ while (proto_ && proto_ !== Object.prototype) {
87
+ const props = Reflect.getOwnMetadata("props", proto_) || [];
88
+ for (const p of props)
89
+ allProps.add(p);
90
+ proto_ = Object.getPrototypeOf(proto_);
91
+ }
92
+ this.properties = Array.from(allProps);
111
93
  this.callbacks = callback;
112
- this.loggers.debug = (s) => loggers.debug("[DEM - " +
113
- this.className +
114
- ": " +
115
- (this.data?._id ?? "not loaded") +
116
- "] " +
117
- s);
118
- this.loggers.info = (s) => loggers.info("[DEM - " +
119
- this.className +
120
- ": " +
121
- (this.data?._id ?? "not loaded") +
122
- "] " +
123
- s);
124
- this.loggers.error = (s) => loggers.error("[DEM - " +
125
- this.className +
126
- ": " +
127
- (this.data?._id ?? "not loaded") +
128
- "] " +
129
- s);
130
- this.loggers.warn = (s) => loggers.warn("[DEM - " +
131
- this.className +
132
- ": " +
133
- (this.data?._id ?? "not loaded") +
134
- "] " +
135
- s);
136
- for (const prop of this.properties) {
137
- if (typeof prop !== "string")
138
- throw new Error("Property '" + prop.toString() + "' is not a string");
139
- if (prop.includes("."))
140
- throw new Error("Property '" +
141
- prop.toString() +
142
- "' constain the illegal character '.'");
143
- }
144
- this.socket = socket;
94
+ this.loggers = {
95
+ debug: (s) => loggers.debug(`[DEM - ${this.className}: ${this.data?._id ?? this._id ?? "not loaded"}] ${s}`),
96
+ info: (s) => loggers.info(`[DEM - ${this.className}: ${this.data?._id ?? this._id ?? "not loaded"}] ${s}`),
97
+ warn: (s) => loggers.warn(`[DEM - ${this.className}: ${this.data?._id ?? this._id ?? "not loaded"}] ${s}`),
98
+ error: (s) => loggers.error(`[DEM - ${this.className}: ${this.data?._id ?? this._id ?? "not loaded"}] ${s}`),
99
+ };
145
100
  if (typeof data === "string") {
101
+ this.data = { _id: data };
146
102
  if (this.isServer) {
147
103
  this.isLoading = false;
148
- this.data = { _id: data };
104
+ this.generateSettersAndGetters();
149
105
  return;
150
106
  }
151
- if (!data || data === "" || data === "undefined") {
152
- this.loggers.error("Cannot create a new AutoUpdatedClientClass with an empty string for ID. Data typeof: " +
153
- typeof data +
154
- " Data: " +
155
- data);
156
- throw new Error("Cannot create a new AutoUpdatedClientClass with an empty string for ID.");
157
- }
158
- this.loggers.debug("Getting new object from server " + this.className + " - " + data);
159
107
  this.socket.emit(EVENT_GET + this.className + data, null, (res) => {
160
108
  if (!res.success) {
161
109
  this.isLoading = false;
@@ -169,38 +117,24 @@ export class AutoUpdatedClientObject {
169
117
  this.emitter.emit(EVENT_INTERNAL_PRE_LOADED + this.EmitterID);
170
118
  this.openSockets();
171
119
  });
172
- this.data = { _id: data };
173
120
  }
174
121
  else {
175
122
  this.isLoading = true;
176
123
  this.data = data;
177
- const dataKeys = Object.keys(data);
178
- for (const key of this.properties) {
179
- if (typeof key !== "string")
180
- throw new Error("Only string keys allowed. Not this shit: " + String(key));
181
- dataKeys.splice(dataKeys.indexOf(key), 1);
124
+ for (const key of this.properties || []) {
182
125
  const isRef = getMetadataRecursive("isRef", this, key);
183
- if (isRef) {
126
+ if (isRef && this.data[key]) {
184
127
  if (Array.isArray(this.data[key])) {
185
128
  this.data[key] = this.data[key].map((obj) => obj._id?.toString() ?? obj?.toString());
186
129
  }
187
130
  else {
188
- this.data[key] =
189
- this.data[key]?._id?.toString() ??
190
- this.data[key]?.toString();
131
+ this.data[key] = this.data[key]?._id?.toString() ?? this.data[key]?.toString();
191
132
  }
192
133
  }
193
134
  }
194
- if (dataKeys.includes("__v"))
195
- dataKeys.splice(dataKeys.indexOf("__v"), 1);
196
- if (dataKeys.length > 0)
197
- this.loggers.warn((dataKeys.length > 1 ? "Properties " : "Property ") +
198
- dataKeys.join(", ") +
199
- (dataKeys.length > 1 ? " were " : " was ") +
200
- "unexpected. These properties are not known by the class. Please check your level of skill issue. Known properties are:\n" +
201
- this.properties.join("\n"));
202
- if ((!this.data._id || this.data._id === "") && !this.isServer)
135
+ if ((!this.data._id || this.data._id === "") && !this.isServer) {
203
136
  this.handleNewObject(data);
137
+ }
204
138
  else {
205
139
  this.isLoading = false;
206
140
  if (!this.isServer)
@@ -208,15 +142,18 @@ export class AutoUpdatedClientObject {
208
142
  }
209
143
  }
210
144
  this.generateSettersAndGetters();
145
+ // Re-apply getters in a microtask to override any shadowing from subclass field initializers.
146
+ Promise.resolve().then(() => {
147
+ this.generateSettersAndGetters();
148
+ });
211
149
  }
212
150
  async waitForPreloaded() {
213
151
  if (this.isLoaded)
214
152
  return;
215
153
  await new Promise((resolve, reject) => {
216
154
  this.emitter.once(EVENT_INTERNAL_PRE_LOADED + this.EmitterID, (failed, reason) => {
217
- if (failed) {
155
+ if (failed)
218
156
  reject(new Error(reason));
219
- }
220
157
  else
221
158
  resolve();
222
159
  });
@@ -224,31 +161,6 @@ export class AutoUpdatedClientObject {
224
161
  }
225
162
  handleNewObject(data) {
226
163
  this.isLoading = true;
227
- if (!this.className)
228
- throw new Error("Cannot create a new AutoUpdatedClientClass without a class name.");
229
- this.loggers.debug(this.className + " - Requesting new object creation on server");
230
- if (this.isServer)
231
- for (const key of this.properties) {
232
- if (typeof key !== "string")
233
- continue;
234
- let pointer = getMetadataRecursive("refsTo", this, key);
235
- if (pointer) {
236
- pointer = pointer.split(":");
237
- if (pointer.length != 2)
238
- throw new Error("population ref incorrectly defined. Sould be 'ParentClass:PropName.Path'");
239
- const temp = data[key];
240
- delete data[key];
241
- if (temp)
242
- this.toChangeOnParents.push({ key: key, value: temp });
243
- }
244
- }
245
- try {
246
- data = _.cloneDeep(data);
247
- }
248
- catch (error) {
249
- this.loggers.error("Most likely cycled object: " + error.message);
250
- this.loggers.error(error.stack);
251
- }
252
164
  this.socket.emit(EVENT_NEW + this.className, data, (res) => {
253
165
  if (!res.success) {
254
166
  this.isLoading = false;
@@ -259,7 +171,6 @@ export class AutoUpdatedClientObject {
259
171
  this.data = res.data;
260
172
  this.generateSettersAndGetters();
261
173
  this.isLoading = false;
262
- this.loggers.debug("Created new object: " + this.data._id);
263
174
  this.emitter.emit(EVENT_INTERNAL_PRE_LOADED + this.EmitterID);
264
175
  if (!this.isServer)
265
176
  this.openSockets();
@@ -274,7 +185,6 @@ export class AutoUpdatedClientObject {
274
185
  }
275
186
  async isPreLoadedAsync() {
276
187
  await this.loadShit();
277
- this.generateSettersAndGetters();
278
188
  return true;
279
189
  }
280
190
  async loadMissingReferences() {
@@ -282,7 +192,8 @@ export class AutoUpdatedClientObject {
282
192
  this.generateSettersAndGetters();
283
193
  }
284
194
  openSockets() {
285
- const event = EVENT_UPDATE + this.className + this.data._id.toString();
195
+ const id = this.data?._id ?? this._id;
196
+ const event = EVENT_UPDATE + this.className + id.toString();
286
197
  this.socket.on(event, async (update, ack) => {
287
198
  const res = await this.handleUpdateRequest(update);
288
199
  if (ack && typeof ack === "function")
@@ -293,58 +204,79 @@ export class AutoUpdatedClientObject {
293
204
  async handleUpdateRequest(update) {
294
205
  try {
295
206
  await this.setValue__(update.key, update.value, true);
296
- this.loggers.debug(`Applied patch ${update.key} set to ${JSON.stringify(update.value)}`);
297
- // Return success with the applied patch
298
207
  if (this.isLoaded)
299
208
  this.callbacks.update(this, update.key);
300
209
  return { success: true, data: undefined, message: "" };
301
210
  }
302
211
  catch (error) {
303
- this.loggers.error(`[${this.data._id}] Error applying patch: ` +
304
- error.message +
305
- "\n" +
306
- error.stack);
307
- return {
308
- success: false,
309
- message: "Error applying update: " + error.message,
310
- };
212
+ this.loggers.error(`[${this.data._id}] Error applying patch: ${error.message}`);
213
+ return { success: false, message: "Error applying update: " + error.message };
311
214
  }
312
215
  }
313
216
  generateSettersAndGetters() {
217
+ if (!this.properties)
218
+ return;
314
219
  for (const key of this.properties) {
315
220
  if (typeof key !== "string")
316
- return;
317
- const k = key;
221
+ continue;
318
222
  const isRef = getMetadataRecursive("isRef", this, key);
223
+ // CRITICAL: Delete any existing property on the instance to ensure our getter is used.
224
+ delete this[key];
319
225
  Object.defineProperty(this, key, {
320
226
  get: () => {
321
- if (isRef) {
322
- if (Array.isArray(this.data[k])) {
323
- const filtered = this.data[k]
324
- .map((id) => this.findReference(id, key))
325
- .filter(Boolean);
326
- return filtered;
227
+ if (!this.data)
228
+ return undefined;
229
+ let val = this.data[key];
230
+ if (val === null)
231
+ val = undefined; // Fix for server-side MongoDB nulls
232
+ if (isRef && val) {
233
+ if (Array.isArray(val)) {
234
+ return val.map((id) => this.findReference(id, key)).filter(Boolean);
327
235
  }
328
236
  else {
329
- const result = this.findReference(this.data[k], key);
330
- return result;
237
+ return this.findReference(val, key);
331
238
  }
332
239
  }
333
- else
334
- return this.data[k];
240
+ return val;
241
+ },
242
+ set: (v) => {
243
+ if (this.data)
244
+ this.data[key] = v;
335
245
  },
336
246
  enumerable: true,
337
247
  configurable: true,
338
248
  });
339
249
  }
340
250
  }
251
+ getValue(key_) {
252
+ const key = key_;
253
+ const parts = key.split(".");
254
+ let value = this;
255
+ for (const part of parts) {
256
+ if (value === undefined || value === null)
257
+ return undefined;
258
+ // Try instance first (getters), then fallback to data
259
+ const nextValue = value[part];
260
+ if (nextValue !== undefined) {
261
+ value = nextValue;
262
+ }
263
+ else if (value.data && value.data[part] !== undefined) {
264
+ value = value.data[part];
265
+ }
266
+ else {
267
+ return undefined;
268
+ }
269
+ }
270
+ return value;
271
+ }
341
272
  findReference(id, key) {
342
- if (typeof id !== "string" && !ObjectId.isValid(id))
343
- return id;
273
+ if (!id)
274
+ return undefined;
275
+ const idStr = id.toString();
344
276
  if (this.parentManager.cache.references[key])
345
- return this.parentManager.cache.references[key].getObject(id.toString());
277
+ return this.parentManager.cache.references[key].getObject(idStr);
346
278
  for (const manager of Object.values(this.parentManager.managers)) {
347
- const result = manager.getObject(id.toString());
279
+ const result = manager.getObject(idStr);
348
280
  if (result) {
349
281
  this.parentManager.cache.references[key] = manager;
350
282
  return result;
@@ -353,326 +285,87 @@ export class AutoUpdatedClientObject {
353
285
  return undefined;
354
286
  }
355
287
  async setValue(key, val) {
356
- const result = await this.setValue__(key, val);
357
- return result;
288
+ return await this.setValue__(key, val);
358
289
  }
359
- async setValue__(key, val, silent = false, noGet = false, noUpdate = false) {
360
- let message = "Setting value " + key + " of " + this.className + " to ";
361
- const isRef = getMetadataRecursive("isRef", this, key);
362
- if (isRef)
363
- val = Array.isArray(val)
364
- ? val.map((v) => {
365
- return v._id?.toString() ?? v;
366
- })
367
- : (val?._id ?? val);
290
+ async setValue__(key, val, silent = false, noGet = false, noUpdate = false, isParentUpdate = false) {
368
291
  try {
369
- message += JSON.stringify(val);
370
- }
371
- catch (error) {
372
- const _ = error;
373
- this.loggers.error("Circular object detected when setting value: " + key);
374
- if (val instanceof AutoUpdatedClientObject) {
375
- val = val.extractedData._id;
376
- message += JSON.stringify(val);
377
- }
378
- }
379
- this.loggers.debug(message);
380
- try {
381
- if (val instanceof AutoUpdatedClientObject)
382
- val = val.extractedData._id;
383
- if (Array.isArray(val))
384
- val = val.map((v) => v instanceof AutoUpdatedClientObject ? v.extractedData._id : v);
385
- let originalVal = this.getValue(key);
386
- if (Array.isArray(originalVal)) {
387
- originalVal = originalVal.map((v) => v instanceof AutoUpdatedClientObject ? v.extractedData._id : v);
388
- }
389
- else {
390
- originalVal =
391
- originalVal instanceof AutoUpdatedClientObject
392
- ? originalVal.extractedData._id
393
- : originalVal;
394
- }
395
- if ((Array.isArray(originalVal) &&
396
- Array.isArray(val) &&
397
- originalVal.length === val.length &&
398
- !originalVal.some((v) => !val.includes(v))) ||
399
- (Array.isArray(originalVal) &&
400
- !Array.isArray(val) &&
401
- originalVal.includes(val)) ||
402
- (!Array.isArray(originalVal) &&
403
- !Array.isArray(val) &&
404
- originalVal === val)) {
405
- return { success: true, msg: "" };
292
+ const isRef = getMetadataRecursive("isRef", this, key);
293
+ const pointer = getMetadataRecursive("refsTo", this, key);
294
+ if (pointer && !isParentUpdate && !silent && !this.isServer) {
295
+ throw new Error("Cannot set value of a reference pointer directly.");
406
296
  }
297
+ let valueToStore = val;
298
+ if (isRef) {
299
+ valueToStore = Array.isArray(val)
300
+ ? val.map((v) => v._id?.toString() ?? v.toString())
301
+ : (val?._id ?? val?.toString() ?? val);
302
+ }
303
+ const currentVal = this.getValue(key);
304
+ const currentValId = Array.isArray(currentVal)
305
+ ? currentVal.map(v => v._id?.toString() ?? v.toString())
306
+ : (currentVal?._id ?? currentVal?.toString());
307
+ if (_.isEqual(currentValId, valueToStore))
308
+ return { success: true, msg: "Successfully set " + key + " to " + val };
407
309
  const path = key.split(".");
408
- let obj = this.data;
409
- let lastClass = this;
410
- let lastPath = path[0];
411
- for (let i = 0; i < path.length - 1; i++) {
412
- if (typeof obj[path[i]] === "string" ||
413
- ObjectId.isValid(obj[path[i]])) {
414
- let temp;
415
- try {
416
- temp = (await this.resolveReference(obj[path[i]]?.toString()));
417
- }
418
- catch (error) {
419
- message +=
420
- "\n Error: likely undefined property on path: " +
421
- path +
422
- " on index: " +
423
- i +
424
- " with error: " +
425
- error.message;
310
+ if (path.length > 1) {
311
+ let obj = this.data;
312
+ for (let i = 0; i < path.length - 1; i++) {
313
+ const currentKey = path[i];
314
+ if (typeof obj[currentKey] === 'string' || ObjectId.isValid(obj[currentKey])) {
315
+ const ref = await this.resolveReference(obj[currentKey].toString());
316
+ if (!ref)
317
+ throw new Error("Could not resolve reference on path: " + key);
318
+ return await ref.setValue(path.slice(i + 1).join("."), val);
426
319
  }
427
- if (!temp) {
428
- message +=
429
- "\nLikely undefined property " +
430
- path[i] +
431
- " on path: " +
432
- path +
433
- " at index: " +
434
- i;
435
- this.loggers.warn("Failed to set value for " + this.className + "\n" + message);
436
- return {
437
- success: false,
438
- msg: message,
439
- };
440
- }
441
- lastClass = temp;
442
- lastPath = path.slice(i + 1).join(".");
443
- const res = await lastClass.setValue(lastPath, val);
444
- if (!noUpdate)
445
- await this.onUpdate(noUpdate);
446
- return res;
320
+ obj = obj[currentKey];
447
321
  }
448
- else
449
- obj = obj[path[i]];
450
322
  }
451
- if (lastClass !== this) {
452
- message +=
453
- "\n What the actual fuckity fuck error on path: " +
454
- path +
455
- " on index: " +
456
- (path.length - 1);
457
- this.loggers.error("Failed to set value for " + this.className + "\n" + message);
458
- return {
459
- success: false,
460
- msg: message,
461
- };
462
- }
463
- if (!this.properties.includes(lastPath) && !lastPath.includes(".")) {
464
- let nearest = "";
465
- for (const prop of this.properties) {
466
- if (typeof prop !== "string")
467
- continue;
468
- if (stringSimilarity(lastPath, prop) > 0 &&
469
- stringSimilarity(lastPath, prop) > stringSimilarity(nearest, prop)) {
470
- nearest = prop;
471
- }
323
+ const res = await this.setValueInternal(key, valueToStore, silent, noUpdate);
324
+ if (res.success) {
325
+ const pathArr = key.split(".");
326
+ let obj = this.data;
327
+ for (let i = 0; i < pathArr.length - 1; i++) {
328
+ obj = obj[pathArr[i]];
472
329
  }
473
- throw new Error(`Property ${lastPath} not found in class ${this.className}, did you mean ${nearest ?? "--No similar prop found--"}?`);
330
+ obj[pathArr[pathArr.length - 1]] = valueToStore;
331
+ await this.findAndLoadReferences(key, valueToStore);
332
+ if (isRef && this.parentManager.isLoaded)
333
+ await this.contactChildren();
334
+ if (this.isLoaded)
335
+ this.callbacks.update(this, key);
474
336
  }
475
- let success;
476
- try {
477
- let isPopulated = getMetadataRecursive("refsTo", this, lastPath);
478
- if (isPopulated) {
479
- isPopulated = isPopulated.split(":");
480
- if (val !== null && val !== undefined) {
481
- const parentObj = this.parentManager.managers[isPopulated[0]].getObject(val);
482
- if (!parentObj) {
483
- message +=
484
- "\n Failed to set value for " +
485
- this.className +
486
- " parent not found";
487
- this.loggers.error(message);
488
- return { success: false, msg: message };
489
- }
490
- if (parentObj.getValue(isPopulated[1]) &&
491
- !Array.isArray(parentObj.getValue(isPopulated[1]))) {
492
- message +=
493
- "\nThis is a 1:1 relationship and the parent already has a parent with the ID: " +
494
- (parentObj.getValue(isPopulated[1])._id?.toString() ??
495
- parentObj.getValue(isPopulated[1]).toString()) +
496
- this.loggers.error(message);
497
- return { success: false, msg: message };
498
- }
499
- let res;
500
- if (this.isServer) {
501
- const value = parentObj.getValue(isPopulated[1]);
502
- if (Array.isArray(value)) {
503
- if (value
504
- .map((v) => v._id?.toString() ?? v.toString())
505
- .includes(this.data._id.toString()))
506
- return {
507
- success: true,
508
- msg: message + "\nValue already set",
509
- };
510
- res = await parentObj.setValue__(isPopulated[1], value.concat(this.data._id.toString()), false, false, true);
511
- }
512
- else {
513
- if ((value?._id?.toString() ?? value?.toString()) ===
514
- this.data._id.toString())
515
- return {
516
- success: true,
517
- msg: message + "\nValue already set",
518
- };
519
- res = await parentObj.setValue__(isPopulated[1], this.data._id.toString(), false, false, true);
520
- }
521
- }
522
- else {
523
- const value = parentObj.getValue(isPopulated[1]);
524
- if (Array.isArray(value)
525
- ? value
526
- .map((v) => v._id?.toString() ?? v.toString())
527
- .includes(this.data._id.toString())
528
- : (value._id?.toString() ?? value.toString()) ===
529
- this.data._id.toString())
530
- return { success: true, msg: message + "\nValue already set" };
531
- ({ res, val } = await this.preInnerSetValue(noGet, key, val, lastPath, silent, noUpdate));
532
- }
533
- success = res.success;
534
- message +=
535
- "\nReport from inner setValue function: " +
536
- res.msg.split("\n").join("\n ");
537
- }
538
- else {
539
- const originalParenValue = this.getValue(key).getValue(isPopulated[1]);
540
- if (!originalParenValue ||
541
- (Array.isArray(originalParenValue) &&
542
- !originalParenValue.some((v) => (v._id?.toString() ?? v.toString()) === this._id.toString()))) {
543
- message += "\n Value already set";
544
- return { success: true, msg: message };
545
- }
546
- const parentObj = this.parentManager.managers[isPopulated[0]].getObject(originalVal);
547
- if (!parentObj) {
548
- message +=
549
- "\n Failed to set value for " +
550
- this.className +
551
- " parent not found";
552
- this.loggers.error(message);
553
- return { success: false, msg: message };
554
- }
555
- let res;
556
- if (Array.isArray(originalParenValue)) {
557
- res = await parentObj.setValue__(isPopulated[1], originalParenValue
558
- .map((v) => v._id?.toString() ?? v.toString())
559
- .filter((v) => v !== this._id.toString()));
560
- }
561
- else {
562
- res = await parentObj.setValue__(isPopulated[1], null);
563
- }
564
- success = res.success;
565
- message +=
566
- "\nReport from inner setValue function: " +
567
- res.msg.split("\n").join("\n ");
568
- }
569
- }
570
- else {
571
- const isRef = getMetadataRecursive("isRef", this, key);
572
- if (isRef && this.isServer && Array.isArray(val)
573
- ? !val.some((v) => !ObjectId.isValid(v))
574
- : ObjectId.isValid(val))
575
- val = Array.isArray(val)
576
- ? val.map((v) => new ObjectId(v))
577
- : new ObjectId(val);
578
- let res;
579
- ({ res, val } = await this.preInnerSetValue(noGet, key, val, lastPath, silent, noUpdate));
580
- if (res.success) {
581
- const originalValue = obj[path.at(-1)];
582
- if (!Array.isArray(val) && Array.isArray(originalValue)) {
583
- if (!originalValue.includes(val))
584
- originalValue.push(val);
585
- val = originalValue;
586
- }
587
- else
588
- obj[path.at(-1)] = val;
589
- }
590
- success = res.success;
591
- message += "\nReport from inner setValue function: \n " + res.msg;
592
- }
593
- }
594
- catch (error) {
595
- success = false;
596
- message += "\nError from inner setValue function: \n " + error.message;
597
- message += error.stack;
598
- }
599
- if (!success) {
600
- this.loggers.warn("Failed to set value for " + this.className + "\n" + message);
601
- return { success: false, msg: message };
602
- }
603
- const pathArr = lastPath.split(".");
604
- if (pathArr.length === 1) {
605
- this.data[key] = val;
606
- }
607
- else {
608
- const last = pathArr.splice(-1, 1);
609
- let ref = this;
610
- for (const p of pathArr) {
611
- ref = ref[p];
612
- }
613
- ref[last.at(-1)] = val;
614
- }
615
- if (!noUpdate)
616
- await this.onUpdate(noUpdate);
617
- await this.findAndLoadReferences(lastPath, val);
618
- const isRef = getMetadataRecursive("isRef", this, path.at(-1));
619
- if (isRef && this.parentManager.isLoaded) {
620
- await this.contactChildren();
621
- }
622
- if (this.isLoaded)
623
- this.callbacks.update(this, key);
624
- return {
625
- success: true,
626
- msg: "Successfully set " + key + " to " + val,
627
- };
337
+ return { ...res, msg: res.msg ?? "Successfully set " + key + " to " + val };
628
338
  }
629
339
  catch (error) {
630
- this.loggers.error("An error occurred setting value for " +
631
- this.className +
632
- "\n" +
633
- message +
634
- "\n Random error here: " +
635
- error.message +
636
- "\n" +
637
- error.stack);
638
- this.loggers.error(error);
639
- return {
640
- success: false,
641
- msg: message +
642
- "\n Random error here: " +
643
- error.message +
644
- "\n" +
645
- error.stack,
646
- };
340
+ this.loggers.error(`Error setting value ${key}: ${error.message}`);
341
+ return { success: false, msg: error.message };
647
342
  }
648
343
  }
649
- async preInnerSetValue(noGet, key, val, lastPath, silent, noUpdate) {
650
- if (!noGet &&
651
- this.isServer &&
652
- this.getValue(key) &&
653
- Array.isArray(this.getValue(key)) &&
654
- !Array.isArray(val)) {
655
- val = [
656
- ...new Set(this.getValue(key)
657
- .concat(val)
658
- .map((v) => v?._id?.toString() ?? new ObjectId(v))
659
- .filter(Boolean)),
660
- ];
344
+ async setValueInternal(key, value, silent = false, noUpdate = false) {
345
+ if (silent)
346
+ return { success: true, msg: "Silent" };
347
+ return new Promise((resolve) => {
348
+ const id = this.data?._id ?? this._id;
349
+ this.socket.emit(EVENT_UPDATE + this.className + id, { _id: id.toString(), key, value }, (res) => {
350
+ resolve({ success: res.success, msg: res.message ?? (res.success ? "Success" : "Error") });
351
+ });
352
+ });
353
+ }
354
+ makeUpdate(key, value) {
355
+ const id = this.data?._id ?? this._id;
356
+ if (!id) {
357
+ this.loggers.error(`Probably missing the identifier ['_id'] again: ${key} = ${value}`);
358
+ throw new Error(`Cannot make update for ${this.className} because _id is missing.`);
661
359
  }
662
- const res = await this.setValueInternal(lastPath, val, silent, noUpdate);
663
- if (!noGet &&
664
- !this.isServer &&
665
- this.getValue(key) &&
666
- Array.isArray(this.getValue(key)) &&
667
- !Array.isArray(val)) {
668
- val = [
669
- ...new Set(this.getValue(key)
670
- .concat(val)
671
- .map((v) => v?._id?.toString() ?? new ObjectId(v))
672
- .filter(Boolean)),
673
- ];
360
+ return { _id: id.toString(), key, value };
361
+ }
362
+ async resolveReference(id) {
363
+ for (const manager of Object.values(this.parentManager.managers)) {
364
+ const obj = manager.getObject(id);
365
+ if (obj)
366
+ return obj;
674
367
  }
675
- return { res, val };
368
+ return null;
676
369
  }
677
370
  async findAndLoadReferences(lastPath, value) {
678
371
  const isRef = getMetadataRecursive("isRef", this, lastPath);
@@ -686,395 +379,149 @@ export class AutoUpdatedClientObject {
686
379
  if (result)
687
380
  break;
688
381
  }
689
- if (!result) {
690
- for (const manager of Object.values(this.parentManager.managers)) {
691
- try {
692
- result = await manager.handleGetMissingObject(id?.toString());
693
- if (result)
694
- break;
695
- }
696
- catch (error) {
697
- const _ = error;
698
- }
699
- }
700
- if (!result) {
701
- this.loggers.warn("Failed to update childerns parent for " +
702
- this.className +
703
- " updating " +
704
- id +
705
- "'s parent to " +
706
- this.data._id);
707
- continue;
708
- }
709
- }
710
382
  if (result && typeof result.loadMissingReferences === "function") {
711
383
  await result.loadMissingReferences();
712
384
  }
713
- else if (result) {
714
- this.loggers.warn(`Object in reference resolution is missing loadMissingReferences function. Type: ${typeof result}, ID: ${result._id ?? result}`);
715
- }
716
385
  }
717
386
  }
718
387
  }
719
- getValue(key_) {
720
- const key = key_;
721
- if (!key.includes(".")) {
722
- let val = this[key];
723
- val ??= this.data[key];
724
- return val;
725
- }
726
- let value;
727
- const parts = key.split(".");
728
- for (const part of parts) {
729
- try {
730
- if (value !== undefined && value !== null) {
731
- value = value[part];
732
- }
733
- else {
734
- value = this[part];
735
- }
736
- }
737
- catch (error) {
738
- this.loggers.error(`Error getting value for ${this.className} on key ${key} at index ${part}: ${error.message}`);
739
- return undefined;
740
- }
741
- }
742
- return value;
743
- }
744
- async setValueInternal(key, value, silent = false, noUpdate = false) {
745
- const update = this.makeUpdate(key, value);
746
- const promise = new Promise((resolve) => {
747
- if (silent) {
748
- if (noUpdate)
749
- return resolve({ success: true, msg: "Success - no update" });
750
- return this.onUpdate(true).then(() => {
751
- if (this.isLoaded)
752
- this.callbacks.update(this, key);
753
- return resolve({ success: true, msg: "Success - silent" });
754
- });
755
- }
756
- try {
757
- this.socket.emit(EVENT_UPDATE + this.className + this.data._id, update, async (res) => {
758
- if (!res.success) {
759
- this.loggers.error("Error sending update: " + res.message);
760
- resolve({ success: false, msg: res.message });
761
- return;
762
- }
763
- if (!noUpdate)
764
- await this.onUpdate(noUpdate);
765
- resolve({
766
- success: res.success,
767
- msg: res.message ?? "Success",
768
- });
769
- });
770
- }
771
- catch (error) {
772
- this.loggers.error("Error sending update:" + error.message);
773
- this.loggers.error(error.stack);
774
- resolve({ success: false, msg: error.message });
775
- }
776
- });
777
- return promise;
778
- }
779
- makeUpdate(key, value) {
780
- try {
781
- const id = this.data._id.toString();
782
- return { _id: id, key, value };
783
- }
784
- catch (error) {
785
- this.loggers.error("Probably missing the fucking identifier ['_id'] again: " +
786
- error.message);
787
- throw error;
788
- }
789
- }
790
- async onUpdate(_) {
791
- return;
792
- }
793
- // return a properly typed AutoUpdatedClientClass (or null)
794
- // inside AutoUpdatedClientClass
795
- async resolveReference(id) {
796
- if (!this.parentManager)
797
- throw new Error("No Manager");
798
- for (const manager of Object.values(this.parentManager.managers)) {
799
- const data = manager.getObject(id);
800
- if (data)
801
- return data;
388
+ async wipeSelf() {
389
+ if (this.data.Wiped)
390
+ return;
391
+ const id = this.data?._id ?? this._id;
392
+ const _id = id ? id.toString() : "unknown";
393
+ for (const key of Object.keys(this.data)) {
394
+ delete this.data[key];
802
395
  }
803
- return null;
396
+ this.data = { Wiped: true };
397
+ this.loggers.info(`[${_id}] ${this.className} object wiped`);
804
398
  }
805
399
  async loadForceReferences(obj = this.data, proto = this, alreadySeen = []) {
806
400
  const props = Reflect.getMetadata("props", proto) || [];
807
401
  for (const key of props) {
808
402
  if (typeof key !== "string")
809
- return;
403
+ continue;
810
404
  const isRef = Reflect.getMetadata("isRef", proto, key);
811
405
  const pointer = Reflect.getMetadata("refsTo", proto, key);
812
- if (pointer &&
813
- obj === this.data &&
814
- obj[key] &&
815
- !alreadySeen.includes(obj))
406
+ if (pointer && obj === this.data && obj[key] && !alreadySeen.includes(obj)) {
816
407
  await this.createdWithParent(pointer.split(":"), obj[key]);
817
- alreadySeen.push(obj[key]);
818
- if (isRef) {
819
- await this.handleLoad(obj, key, alreadySeen);
820
408
  }
821
- await this.checkRecursiveReferenceLoading(obj, key, alreadySeen);
822
- }
823
- }
824
- async checkRecursiveReferenceLoading(obj, key, alreadySeen) {
825
- const val = obj ? obj[key] : null;
826
- if (val && typeof val === "object") {
827
- const nestedProto = Object.getPrototypeOf(val);
828
- if (nestedProto && !alreadySeen.includes(val)) {
829
- alreadySeen.push(val);
830
- await this.loadForceReferences(val, nestedProto, alreadySeen);
409
+ if (obj[key] && !alreadySeen.includes(obj[key]))
410
+ alreadySeen.push(obj[key]);
411
+ if (isRef)
412
+ await this.handleLoad(obj, key, alreadySeen);
413
+ const val = obj[key];
414
+ if (val && typeof val === "object") {
415
+ const nestedProto = Object.getPrototypeOf(val);
416
+ if (nestedProto && !alreadySeen.includes(val)) {
417
+ alreadySeen.push(val);
418
+ await this.loadForceReferences(val, nestedProto, alreadySeen);
419
+ }
831
420
  }
832
421
  }
833
422
  }
834
423
  async handleLoad(obj, key, alreadySeen) {
835
- if (!this.parentManager)
836
- throw new Error("No manager");
837
424
  const refIds = Array.isArray(obj[key]) ? obj[key] : [obj[key]];
838
425
  for (const refId of refIds) {
839
426
  if (refId) {
840
- for (const manager of Object.values(this.parentManager.managers)) {
841
- const result = manager.getObject(refId);
842
- if (result && !alreadySeen.includes(refId)) {
843
- alreadySeen.push(refId);
844
- await result.loadForceReferences(undefined, undefined, alreadySeen);
845
- break;
427
+ const idStr = refId.toString();
428
+ let result = globalCache.objects[idStr]?.object;
429
+ if (!result) {
430
+ for (const manager of Object.values(this.parentManager.managers)) {
431
+ result = manager.getObject(idStr);
432
+ if (result)
433
+ break;
846
434
  }
847
435
  }
436
+ if (result && !alreadySeen.includes(idStr)) {
437
+ alreadySeen.push(idStr);
438
+ await result.loadForceReferences(undefined, undefined, alreadySeen);
439
+ }
848
440
  }
849
441
  }
850
442
  }
443
+ async onUpdate(noUpdate = false) {
444
+ return;
445
+ }
851
446
  async createdWithParent(pointer, parent) {
852
- if (pointer.length !== 2) {
853
- throw new Error("Invalid pointer: " +
854
- JSON.stringify(pointer) +
855
- " for " +
856
- this.className +
857
- ", poiter must be 'className:pathToParentProperty'");
858
- }
859
- if (!parent)
860
- throw new Error("Invalid pointer: " +
861
- JSON.stringify(pointer) +
862
- " for " +
863
- this.className +
864
- ", parent is null");
865
- const obj = this.parentManager.managers[pointer[0]]?.getObject(parent._id?.toString() ?? parent.toString());
447
+ if (pointer.length !== 2)
448
+ return;
449
+ const parentId = parent._id?.toString() ?? parent.toString();
450
+ const obj = this.parentManager.managers[pointer[0]]?.getObject(parentId);
866
451
  if (!obj)
867
452
  return;
868
453
  const val = obj.getValue(pointer[1]);
454
+ const myId = this.data._id.toString();
869
455
  if (Array.isArray(val)) {
870
- const originalLength = val.length;
871
- const filtred = val.filter(Boolean);
872
- if (filtred.length !== originalLength) {
873
- await obj.setValue__(pointer[1], filtred, true, false, true);
874
- this.loggers.warn("Array value changed from " +
875
- originalLength +
876
- " to " +
877
- filtred.length +
878
- " - some values were undefined");
456
+ const ids = val.map(v => v._id?.toString() ?? v.toString());
457
+ if (!ids.includes(myId)) {
458
+ await obj.setValue__(pointer[1], [...val, myId], true, false, false, true);
879
459
  }
880
- if (filtred.map((id) => id?._id?.toString()).includes(this.data._id))
881
- await obj.contactChildren();
882
- else
883
- await obj.setValue__(pointer[1], [
884
- ...new Set([...filtred, this.data._id]),
885
- ], true, false, true);
886
460
  }
887
- else if (val?.toString() === this.data?._id?.toString())
888
- await obj.contactChildren();
889
- else
890
- await obj.setValue__(pointer[1], this.data?._id?.toString(), true, false, true);
461
+ else if ((val?._id?.toString() ?? val?.toString()) !== myId) {
462
+ await obj.setValue__(pointer[1], myId, true, false, false, true);
463
+ }
891
464
  }
892
465
  async destroy(once = false) {
893
- if (!once) {
466
+ if (!once)
894
467
  return await this.parentManager.deleteObject(this.data._id);
895
- }
896
- const res = await new Promise((resolve) => {
897
- this.socket.emit(EVENT_DELETE + this.className, this.data._id, async (res) => {
898
- if (!res.success) {
899
- this.loggers.error("Error deleting object from database - " +
900
- this.className +
901
- " - " +
902
- this.data._id);
903
- this.loggers.error(res.message);
904
- resolve({
905
- success: false,
906
- message: res.message,
907
- });
908
- return;
909
- }
910
- resolve({
911
- success: true,
912
- message: "Deleted",
913
- });
468
+ return new Promise((resolve) => {
469
+ this.socket.emit(EVENT_DELETE + this.className, this.data._id, (res) => {
470
+ resolve({ success: res.success, message: res.message ?? "" });
914
471
  });
915
472
  });
916
- return res;
917
473
  }
918
474
  async checkForMissingRefs() {
919
475
  for (const prop of this.properties) {
920
- let pointer = getMetadataRecursive("refsTo", this, prop.toString());
476
+ const pointer = getMetadataRecursive("refsTo", this, prop.toString());
921
477
  if (pointer) {
922
- pointer = pointer.split(":");
923
- if (pointer.length != 2)
924
- throw new Error("population ref incorrectly defined. Sould be 'ParentClass:PropName'");
925
- await this.findMissingObjectReference(prop, pointer);
478
+ const parts = pointer.split(":");
479
+ if (parts.length === 2)
480
+ await this.findMissingObjectReference(prop, parts);
926
481
  }
927
482
  }
928
483
  }
929
484
  async findMissingObjectReference(prop, pointer) {
930
- if (this.checkedMissingRefs && this.isLoadingReferences)
485
+ if (this.checkedMissingRefs)
931
486
  return;
932
487
  this.checkedMissingRefs = true;
933
488
  const ac = this.parentManager.managers[pointer[0]];
934
489
  if (!ac)
935
- throw new Error(`No AutoUpdateManager found for class ${pointer[0]}`);
490
+ return;
936
491
  const targetId = this.data._id.toString();
937
- const pointerKey = pointer[1];
938
- const isNested = pointerKey.includes(".");
939
- const pathParts = isNested ? pointerKey.split(".") : [];
940
- const pendingObjects = ac.objectsAsArray.filter(obj => !obj.isLoaded);
941
- if (pendingObjects.length > 0) {
942
- await Promise.all(pendingObjects.map(obj => obj.waitForPreloaded()));
943
- }
944
- for (const obj of ac.objectsAsArray) {
945
- if (!obj.isLoaded) {
492
+ const allObjects = Object.values(ac.objects);
493
+ for (const obj of allObjects) {
494
+ if (!obj.isLoaded)
946
495
  await obj.waitForPreloaded();
947
- }
948
- let val;
949
- if (isNested) {
950
- val = obj;
951
- for (const element of pathParts) {
952
- if (!val)
953
- break;
954
- val = val[element] ?? val.data?.[element];
955
- }
956
- }
957
- else {
958
- val = obj[pointerKey] ?? obj.data?.[pointerKey];
959
- }
496
+ const val = obj.getValue(pointer[1]);
960
497
  if (!val)
961
498
  continue;
962
- let found = false;
963
- if (Array.isArray(val)) {
964
- for (const element of val) {
965
- const item = element;
966
- if (!item)
967
- continue;
968
- const idStr = item._id ? item._id.toString() : item.toString();
969
- if (idStr === targetId) {
970
- found = true;
971
- break;
972
- }
973
- }
974
- }
975
- else {
976
- const idStr = val._id ? val._id.toString() : val.toString();
977
- found = (idStr === targetId);
978
- }
979
- if (found) {
499
+ const ids = Array.isArray(val) ? val.map(v => v._id?.toString() ?? v.toString()) : [val._id?.toString() ?? val.toString()];
500
+ if (ids.includes(targetId)) {
980
501
  this.data[prop] = obj._id;
981
502
  return;
982
503
  }
983
504
  }
984
505
  }
985
- async wipeSelf() {
986
- if (this.data.Wiped)
987
- return;
988
- const _id = this.data._id.toString();
989
- for (const key of Object.keys(this.data)) {
990
- delete this.data[key];
991
- }
992
- this.data = { Wiped: true };
993
- this.loggers.info(`[${_id}] ${this.className} object wiped`);
994
- }
995
506
  async contactChildren() {
996
- let childsManager = null;
997
- const findMissingObjectWithoutKnownManager = async (o) => {
998
- if (o instanceof AutoUpdatedClientObject)
999
- return o;
1000
- if (childsManager)
1001
- try {
1002
- return await childsManager.handleGetMissingObject(o._id?.toString() ?? o.toString());
1003
- }
1004
- catch (error) {
1005
- this.loggers.error("This should fucking not happen wtffffff");
1006
- this.loggers.error(error.message);
1007
- childsManager = null;
1008
- }
1009
- else {
1010
- for (const manager of Object.values(this.parentManager.managers)) {
1011
- try {
1012
- const newO = await manager.handleGetMissingObject(o._id?.toString() ?? o.toString());
1013
- childsManager = manager;
1014
- return newO;
1015
- }
1016
- catch (e) {
1017
- const _ = e;
1018
- }
1019
- }
1020
- return undefined;
1021
- }
1022
- };
1023
507
  for (const prop of this.properties) {
1024
- const pointer = getMetadataRecursive("refsTo", this, prop.toString());
1025
508
  const isRef = getMetadataRecursive("isRef", this, prop.toString());
509
+ const pointer = getMetadataRecursive("refsTo", this, prop.toString());
1026
510
  if (!isRef || pointer)
1027
511
  continue;
1028
- let obj = this.getValue(prop);
1029
- if (!obj || (Array.isArray(obj) && obj.length == 0)) {
1030
- obj = this.getValueInternal(prop);
1031
- try {
1032
- if (Array.isArray(obj))
1033
- obj = await Promise.all(obj.map(findMissingObjectWithoutKnownManager));
1034
- else
1035
- obj = await findMissingObjectWithoutKnownManager(obj);
1036
- }
1037
- catch (error) {
1038
- const _ = error;
1039
- }
1040
- }
512
+ const obj = this.getValue(prop);
1041
513
  if (!obj)
1042
514
  continue;
1043
- if (Array.isArray(obj)) {
1044
- for (const child of obj) {
1045
- try {
1046
- if (child && typeof child.loadMissingReferences === "function") {
1047
- await child.loadMissingReferences();
1048
- }
1049
- else if (child) {
1050
- this.loggers.warn(`Object in property ${prop.toString()} is missing loadMissingReferences function. Type: ${typeof child}, ID: ${child._id ?? child}`);
1051
- }
1052
- }
1053
- catch (error) {
1054
- this.loggers.error(error.message);
1055
- }
1056
- }
1057
- }
1058
- else {
1059
- if (obj && typeof obj.loadMissingReferences === "function") {
1060
- await obj.loadMissingReferences();
1061
- }
1062
- else if (obj) {
1063
- this.loggers.warn(`Object in property ${prop.toString()} is missing loadMissingReferences function. Type: ${typeof obj}, ID: ${obj._id ?? obj}`);
515
+ const children = Array.isArray(obj) ? obj : [obj];
516
+ for (const child of children) {
517
+ if (child && typeof child.loadMissingReferences === "function") {
518
+ await child.loadMissingReferences();
1064
519
  }
1065
520
  }
1066
521
  }
1067
522
  }
1068
- getValueInternal(key) {
1069
- const keys = key.toString().split(".");
1070
- let value = this.data;
1071
- for (const k of keys) {
1072
- value = value[k];
1073
- }
1074
- return value;
1075
- }
1076
523
  }
1077
- export function processIsRefProperties(instance, target, prefix = null, allProps = [], newData = {}, loggers = console) {
524
+ export function processIsRefProperties(instance, target, prefix, allProps, newData, loggers) {
1078
525
  const props = Reflect.getMetadata("props", target) || [];
1079
526
  for (const prop of props) {
1080
527
  const path = prefix ? `${prefix}.${prop}` : prop;
@@ -1085,19 +532,17 @@ export function processIsRefProperties(instance, target, prefix = null, allProps
1085
532
  if (Reflect.getMetadata("isRef", target, prop)) {
1086
533
  if (Array.isArray(instance[prop]))
1087
534
  newData[prop] = instance[prop]
1088
- .map((item) => item?._id?.toString() ?? item?.toString() ?? undefined)
535
+ .map((item) => item?._id?.toString() ?? item?.toString())
1089
536
  .filter(Boolean);
1090
537
  else
1091
538
  newData[prop] =
1092
- instance[prop]?._id?.toString() ??
1093
- instance[prop]?.toString() ??
1094
- undefined;
539
+ instance[prop]?._id?.toString() ?? instance[prop]?.toString();
1095
540
  }
1096
541
  const type = Reflect.getMetadata("design:type", target, prop);
1097
542
  if (type?.prototype) {
1098
543
  const nestedProps = Reflect.getMetadata("props", type.prototype);
1099
544
  if (nestedProps && instance[prop]) {
1100
- newData[prop] = processIsRefProperties(instance[prop], type.prototype, path, allProps, undefined, loggers).newData;
545
+ newData[prop] = processIsRefProperties(instance[prop], type.prototype, path, allProps, {}, loggers).newData;
1101
546
  }
1102
547
  }
1103
548
  }