@prestizni-software/server-dem 0.5.7 → 0.5.8

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,6 +1,6 @@
1
- import { AutoUpdateManager } from "./AutoUpdateManagerClass.js";
2
- import { createAutoUpdatedClass, } from "./AutoUpdatedServerObjectClass.js";
3
- import { EVENT_NEW, EVENT_UPDATE, EVENT_DELETE, EVENT_GET, EVENT_STARTUP, globalCache, } from "./CommonTypes.js";
1
+ import { AutoUpdateManager } from "./AutoUpdateManagerClass";
2
+ import { createAutoUpdatedClass } from "./AutoUpdatedServerObjectClass";
3
+ import { globalCache, EVENT_NEW, EVENT_UPDATE, EVENT_DELETE, EVENT_GET, EVENT_STARTUP } from "./CommonTypes";
4
4
  import { EventEmitter } from "eventemitter3";
5
5
  import * as machineId from "node-machine-id";
6
6
  import { getModelForClass } from "@typegoose/typegoose";
@@ -12,40 +12,205 @@ export var DEMEventTypes;
12
12
  DEMEventTypes["get"] = "get";
13
13
  DEMEventTypes["startup"] = "startup";
14
14
  })(DEMEventTypes || (DEMEventTypes = {}));
15
- export async function AUSManagerFactory(defs, loggers, socket, disableDEMDebugMessages = false, emitter = new EventEmitter(), models) {
15
+ function setupSocketMiddleware(socket_server, loggers, managers, _models) {
16
+ socket_server.use(async (socket, next) => {
17
+ socket.use((async (event, nextEvent) => {
18
+ if (event.length !== 3 ||
19
+ typeof event[0] !== "string" ||
20
+ typeof event[2] !== "function") {
21
+ loggers.warn?.("Invalid event: [" +
22
+ event.map((e) => JSON.stringify(e)).join("], [") +
23
+ "]");
24
+ return;
25
+ }
26
+ if (!socket
27
+ .eventNames()
28
+ .some((e) => e.toString() === event[0] ||
29
+ e.toString() === event[0].slice(0, -24))) {
30
+ loggers.warn?.("Undefined event: [" +
31
+ event.map((e) => JSON.stringify(e)).join("], [") +
32
+ "]");
33
+ event[2]({
34
+ success: false,
35
+ message: "Undefined event, event: " + event[0] + " not found",
36
+ });
37
+ return;
38
+ }
39
+ try {
40
+ const e = event[0];
41
+ let demEvent = {};
42
+ const id = e.slice(-24);
43
+ switch (true) {
44
+ case e.startsWith(EVENT_NEW):
45
+ demEvent = {
46
+ type: DEMEventTypes.new,
47
+ manager: managers[e.replace(EVENT_NEW, "")],
48
+ data: event[1],
49
+ object: undefined,
50
+ };
51
+ break;
52
+ case e.startsWith(EVENT_UPDATE):
53
+ {
54
+ const manager = managers[e.replace(EVENT_UPDATE, "").replace(id, "")];
55
+ demEvent = {
56
+ type: DEMEventTypes.update,
57
+ manager: manager,
58
+ object: manager.getObject(id),
59
+ data: event[1],
60
+ };
61
+ }
62
+ break;
63
+ case e.startsWith(EVENT_DELETE):
64
+ {
65
+ const manager = managers[e.replace(EVENT_DELETE, "")];
66
+ const obj = manager.getObject(event[1]);
67
+ if (!obj) {
68
+ event[2]({
69
+ success: true,
70
+ message: "Object already deleted",
71
+ data: undefined,
72
+ });
73
+ return;
74
+ }
75
+ demEvent = {
76
+ type: DEMEventTypes.delete,
77
+ manager: manager,
78
+ object: obj,
79
+ data: undefined,
80
+ };
81
+ }
82
+ break;
83
+ case e.startsWith(EVENT_GET):
84
+ {
85
+ const manager = managers[e.replace(EVENT_GET, "").replace(id, "")];
86
+ demEvent = {
87
+ type: DEMEventTypes.get,
88
+ manager: manager,
89
+ object: manager.getObject(id),
90
+ data: undefined,
91
+ };
92
+ }
93
+ break;
94
+ case e.startsWith(EVENT_STARTUP):
95
+ demEvent = {
96
+ type: DEMEventTypes.startup,
97
+ manager: managers[e.replace(EVENT_STARTUP, "")],
98
+ object: undefined,
99
+ data: undefined,
100
+ };
101
+ break;
102
+ default:
103
+ throw new Error("Unknown event: " +
104
+ e +
105
+ " - known events: [" +
106
+ Object.values(DEMEventTypes).join(", ") +
107
+ "]");
108
+ }
109
+ try {
110
+ await demEvent.manager.options?.accessDefinitions?.eventMiddleware?.(demEvent, managers, socket);
111
+ nextEvent();
112
+ }
113
+ catch (error) {
114
+ loggers.warn?.("Someone got access denied:\nUser (" +
115
+ JSON.stringify(socket.handshake.auth) +
116
+ ")\nWith ID: '" +
117
+ socket.id +
118
+ "'\nFrom: '" +
119
+ socket.handshake.address +
120
+ "'\nTo the event: '" +
121
+ event[0] +
122
+ "'\nFor: '" +
123
+ (error instanceof Error ? error.message : String(error)) +
124
+ "'");
125
+ event[2]({
126
+ success: false,
127
+ message: "You were denied access to this event '" +
128
+ event[0] +
129
+ "' by the server.\n" +
130
+ (error instanceof Error ? error.message : String(error)),
131
+ });
132
+ }
133
+ }
134
+ catch (error) {
135
+ loggers.error?.("Error with event: " +
136
+ event[0] +
137
+ "\nError: " +
138
+ (error instanceof Error ? error.message : String(error)));
139
+ return;
140
+ }
141
+ }));
142
+ next();
143
+ });
144
+ }
145
+ export async function AUSManagerFactory(defs, loggers, socket, _disableDEMDebugMessages = false, emitter = new EventEmitter(), models) {
16
146
  readyLoggers(loggers);
147
+ /* if (disableDEMDebugMessages) {
148
+ loggers.debug = (_) => { };
149
+ } */
150
+ socket.use((socket, next) => {
151
+ socket.onAny((event) => {
152
+ loggers.debug?.("Recieved event: " + event + " from client: " + socket.id);
153
+ });
154
+ next();
155
+ });
17
156
  const managers = {};
18
157
  for (const key in defs) {
158
+ loggers.debug?.(`Creating manager for ${key}`);
19
159
  const def = defs[key];
20
160
  const model = getModelForClass(def.class);
21
- const manager = new AutoUpdateServerManager(def.class, key, loggers, socket, model, managers, emitter, def.options);
22
- managers[key] = manager;
161
+ try {
162
+ const c = new AutoUpdateServerManager(def.class, key, socket, loggers, model, managers, emitter, def.options);
163
+ managers[key] = c;
164
+ }
165
+ catch (error) {
166
+ loggers.error?.("Error creating manager: " + key);
167
+ loggers.error?.(error instanceof Error ? error.message : String(error));
168
+ if (error instanceof Error && error.stack)
169
+ loggers.error?.(error.stack);
170
+ continue;
171
+ }
172
+ loggers.debug?.("Loading DB for manager: " + key);
173
+ try {
174
+ await managers[key].preLoad();
175
+ }
176
+ catch (error) {
177
+ loggers.error?.("Error loading DB for manager: " + key);
178
+ loggers.error?.(error instanceof Error ? error.message : String(error));
179
+ if (error instanceof Error && error.stack)
180
+ loggers.error?.(error.stack);
181
+ }
23
182
  }
24
183
  for (const manager of Object.values(managers)) {
25
184
  try {
26
- await manager.preLoad();
185
+ manager.loadReferences();
27
186
  }
28
187
  catch (error) {
29
- loggers?.error?.("Error preloading manager: " +
188
+ loggers.error?.("Error loading DB for manager: " +
30
189
  manager.className +
31
- " - " +
32
- error.message);
190
+ " (loadReferences)");
191
+ loggers.error?.(error instanceof Error ? error.message : String(error));
192
+ if (error instanceof Error && error.stack)
193
+ loggers.error?.(error.stack);
33
194
  }
34
195
  }
35
- socket.on("connection", async (clientSocket) => {
36
- loggers?.debug?.(`Client connected: ${clientSocket.id}`);
37
- const startupData = {};
196
+ socket.on("connection", async (socket) => {
197
+ loggers.debug?.(`Client connected: ${socket.id}`);
38
198
  for (const manager of Object.values(managers)) {
39
- await manager.loadReferences();
40
- manager.registerSocket(clientSocket);
41
- }
42
- if (typeof clientSocket.emit === "function") {
43
- clientSocket.emit(EVENT_STARTUP, startupData);
199
+ manager.registerSocket(socket);
44
200
  }
45
- clientSocket.on("disconnect", () => {
46
- loggers?.debug?.(`Client disconnected: ${clientSocket.id}`);
201
+ socket.on("disconnect", () => {
202
+ loggers.debug?.(`Client disconnected: ${socket.id}`);
47
203
  });
48
204
  });
205
+ try {
206
+ setupSocketMiddleware(socket, loggers, managers, models);
207
+ }
208
+ catch (error) {
209
+ loggers.error?.("Error setting up socket middleware");
210
+ loggers.error?.(error instanceof Error ? error.message : String(error));
211
+ if (error instanceof Error && error.stack)
212
+ loggers.error?.(error.stack);
213
+ }
49
214
  return managers;
50
215
  }
51
216
  export class AutoUpdateServerManager extends AutoUpdateManager {
@@ -53,7 +218,8 @@ export class AutoUpdateServerManager extends AutoUpdateManager {
53
218
  clientSockets = new Set();
54
219
  options;
55
220
  objects_ = {};
56
- constructor(classParam, className, loggers, socket, model, managers, emitter, options) {
221
+ managers;
222
+ constructor(classParam, className, socket, loggers, model, managers, emitter, options) {
57
223
  super(classParam, className, socket, loggers, managers, emitter);
58
224
  this.managers = managers;
59
225
  this.model = model;
@@ -62,135 +228,149 @@ export class AutoUpdateServerManager extends AutoUpdateManager {
62
228
  async preLoad() {
63
229
  this.loggers.debug("Loading manager DB " + this.className);
64
230
  const docs = await this.model.find({});
65
- for (const d of docs) {
66
- const docId = d._id.toString();
67
- this.objects_[docId] = await createAutoUpdatedClass(this.classParam, this.className, this.socket, docId, this.loggers, this, this.emitter, d);
68
- globalCache.objects[docId] = {
231
+ for (const doc of docs) {
232
+ const id = doc._id?.toString();
233
+ if (!id) {
234
+ this.loggers.debug("Invalid document, no _id: " + JSON.stringify(doc));
235
+ continue;
236
+ }
237
+ this.objects_[id] =
238
+ this.objects_[id] ??
239
+ (await createAutoUpdatedClass(this.classParam, this.className, this.socket, id, this.loggers, this, this.emitter, doc));
240
+ globalCache.objects[id] = {
69
241
  className: this.className,
70
- object: this.objects_[docId],
242
+ object: this.objects_[id],
71
243
  };
72
244
  }
73
- this.isLoaded_ = true;
74
- this.loggers.info(`Created manager [${Object.keys(this.objects_).length}/${docs.length}]`);
245
+ for (const object of this.objectsAsArray) {
246
+ await object.isPreLoadedAsync();
247
+ await object.contactChildren();
248
+ await object.loadMissingReferences();
249
+ }
250
+ this.loggers.debug("Loaded manager DB " +
251
+ this.className +
252
+ " - [" +
253
+ docs.length +
254
+ "] entries");
75
255
  }
76
256
  registerSocket(socket) {
77
257
  this.clientSockets.add(socket);
78
- const runMiddleware = async (event) => {
79
- if (this.options?.accessDefinitions?.eventMiddleware) {
80
- await this.options.accessDefinitions.eventMiddleware(event, this.managers, socket);
81
- }
82
- };
83
258
  socket.on(EVENT_STARTUP + this.className, async (_, ack) => {
84
259
  try {
85
- const objects = await (this.options?.accessDefinitions?.startupMiddleware?.(this.objectsAsArray, this.managers, socket) ?? Promise.resolve(this.objectsAsArray));
86
- const ids = objects.map((obj) => obj._id.toString());
87
- if (typeof ack === "function") {
88
- ack({
89
- data: { ids, properties: this.properties },
90
- success: true,
91
- });
92
- }
260
+ const ids = ((await this.options?.accessDefinitions?.startupMiddleware?.(this.objectsAsArray, this.managers, socket))?.map((obj) => obj._id) ?? this.objectIDs).filter(Boolean);
261
+ this.loggers.debug("Sending startup data for manager " + this.className);
262
+ ack({
263
+ data: { ids, properties: this.properties },
264
+ success: true,
265
+ });
93
266
  }
94
267
  catch (error) {
95
- if (typeof ack === "function") {
96
- ack({ success: false, message: error.message });
97
- }
268
+ this.loggers.error("Error sending startup data for manager " +
269
+ this.className +
270
+ ": " +
271
+ (error instanceof Error ? error.message : String(error)));
272
+ if (error instanceof Error && error.stack)
273
+ this.loggers.error(error.stack);
274
+ ack({
275
+ success: false,
276
+ message: (error instanceof Error ? error.message : String(error)),
277
+ });
98
278
  }
99
279
  });
100
- socket.on(EVENT_NEW + this.className, async (data, ack) => {
280
+ socket.on(EVENT_DELETE + this.className, async (id, ack) => {
281
+ this.loggers.debug("Deleting object from manager " + this.className + " - " + id);
101
282
  try {
102
- // console.log("SERVER RECEIVED NEW for " + this.className, data);
103
- await runMiddleware({
104
- type: DEMEventTypes.new,
105
- manager: this,
106
- data,
107
- object: undefined,
283
+ await this.deleteObject(id);
284
+ ack({
285
+ success: true,
286
+ message: "Deleted successfully",
287
+ data: undefined,
108
288
  });
109
- const newObj = await this.createObject(data);
110
- if (typeof ack === "function") {
111
- ack({ data: newObj.extractedData, success: true });
112
- }
113
289
  }
114
290
  catch (error) {
115
- if (typeof ack === "function") {
116
- ack({ success: false, message: error.message });
117
- }
291
+ this.loggers.error("Error deleting object from manager " +
292
+ this.className +
293
+ " - " +
294
+ id +
295
+ ": " +
296
+ (error instanceof Error ? error.message : String(error)));
297
+ if (error instanceof Error && error.stack)
298
+ this.loggers.error(error.stack);
299
+ ack({ success: false, message: error instanceof Error ? error.message : String(error) });
118
300
  }
119
301
  });
120
- socket.on(EVENT_DELETE + this.className, async (id, ack) => {
302
+ socket.on(EVENT_NEW + this.className, async (data, ack) => {
303
+ this.loggers.debug("Recieved new object creation in manager " + this.className);
121
304
  try {
122
- // console.log("SERVER RECEIVED DELETE for " + this.className, id);
123
- const obj = this.getObject(id);
124
- if (obj) {
125
- await runMiddleware({
126
- type: DEMEventTypes.delete,
127
- manager: this,
128
- object: obj,
129
- data: undefined,
130
- });
131
- }
132
- const delRes = await this.deleteObject(id);
133
- if (typeof ack === "function") {
134
- ack({
135
- success: delRes.success,
136
- data: undefined,
137
- message: delRes.message,
138
- });
139
- }
305
+ const newDoc = await this.createObject(data);
306
+ ack({
307
+ data: newDoc.extractedData,
308
+ success: true,
309
+ message: "Created successfully",
310
+ });
140
311
  }
141
312
  catch (error) {
142
- if (typeof ack === "function") {
143
- ack({ success: false, message: error.message });
144
- }
313
+ this.loggers.error("Error creating new object creation in manager " +
314
+ this.className +
315
+ " - " +
316
+ (error instanceof Error ? error.message : String(error)));
317
+ if (error instanceof Error && error.stack)
318
+ this.loggers.error(error.stack);
319
+ ack({ success: false, message: error instanceof Error ? error.message : String(error) });
145
320
  }
146
321
  });
147
- socket.onAny(async (eventName, ...args) => {
148
- if (typeof eventName !== "string")
149
- return;
150
- const ack = args[args.length - 1];
151
- try {
152
- if (eventName.startsWith(EVENT_UPDATE + this.className)) {
153
- const id = eventName.replace(EVENT_UPDATE + this.className, "");
154
- const data = args[0];
155
- if (!data || !data.key)
156
- return;
157
- const obj = this.getObject(id);
322
+ socket.on(EVENT_UPDATE + this.className, async () => { });
323
+ socket.on(EVENT_GET + this.className, async () => { });
324
+ socket.onAny(async (event, data, ack) => {
325
+ if (event.startsWith(EVENT_UPDATE + this.className) &&
326
+ event.replace(EVENT_UPDATE + this.className, "").length === 24) {
327
+ this.loggers.debug("Updating object in manager " +
328
+ this.className +
329
+ ": " +
330
+ event +
331
+ " - " +
332
+ JSON.stringify(data));
333
+ try {
334
+ const id = event.replace(EVENT_UPDATE + this.className, "");
335
+ let obj = this.objects_[id];
158
336
  if (!obj)
159
- return;
160
- await runMiddleware({
161
- type: DEMEventTypes.update,
162
- manager: this,
163
- object: obj,
164
- data,
165
- });
166
- const res = await obj.setValue(data.key, data.value, {
167
- silent: false,
168
- });
169
- if (typeof ack === "function")
170
- ack({
171
- data: obj.extractedData,
337
+ throw new Error(`Never... failed to get object somehow: ${id}`);
338
+ const res = await obj.setValue(data.key, data.value);
339
+ res.success
340
+ ? ack({
341
+ data: null,
172
342
  success: res.success,
173
343
  message: res.msg,
174
- });
344
+ })
345
+ : ack({ success: res.success, message: res.msg });
175
346
  }
176
- else if (eventName.startsWith(EVENT_GET + this.className)) {
177
- const id = eventName.replace(EVENT_GET + this.className, "");
178
- const obj = this.getObject(id);
347
+ catch (error) {
348
+ this.loggers.warn("Failed to update object in manager " + this.className);
349
+ ack({ success: false, message: error instanceof Error ? error.message : String(error) });
350
+ }
351
+ }
352
+ else if (event.startsWith(EVENT_GET + this.className) &&
353
+ event.replace(EVENT_GET + this.className, "").length === 24) {
354
+ try {
355
+ const id = event.replace(EVENT_GET + this.className, "");
356
+ let obj = this.objects_[id];
179
357
  if (!obj)
180
- return;
181
- await runMiddleware({
182
- type: DEMEventTypes.get,
183
- manager: this,
184
- object: obj,
185
- data: undefined,
358
+ throw new Error(`Object not found: ${id}`);
359
+ ack({
360
+ data: obj.extractedData,
361
+ success: true,
362
+ message: "Updated successfully",
186
363
  });
187
- if (typeof ack === "function")
188
- ack({ data: obj.extractedData, success: true });
189
364
  }
190
- }
191
- catch (error) {
192
- if (typeof ack === "function")
193
- ack({ success: false, message: error.message });
365
+ catch (error) {
366
+ this.loggers.error("Error sending startup data for manager " +
367
+ this.className +
368
+ ": " +
369
+ (error instanceof Error ? error.message : String(error)));
370
+ if (error instanceof Error && error.stack)
371
+ this.loggers.error(error.stack);
372
+ ack({ success: false, message: error instanceof Error ? error.message : String(error) });
373
+ }
194
374
  }
195
375
  });
196
376
  socket.on("disconnect", () => {
@@ -198,9 +378,9 @@ export class AutoUpdateServerManager extends AutoUpdateManager {
198
378
  });
199
379
  }
200
380
  getObject(_id) {
201
- if (_id === undefined)
381
+ if (!_id)
202
382
  return null;
203
- return this.objects_[_id] || undefined;
383
+ return this.objects_[_id.toString()] || undefined;
204
384
  }
205
385
  get objects() {
206
386
  return this.objects_;
@@ -209,58 +389,68 @@ export class AutoUpdateServerManager extends AutoUpdateManager {
209
389
  return Object.values(this.objects_);
210
390
  }
211
391
  async handleGetMissingObject(_id) {
392
+ const _idStr = _id.toString();
393
+ if (this.getObject(_idStr))
394
+ return this.getObject(_idStr);
395
+ const document = await this.model.findById(_idStr);
396
+ if (!document)
397
+ throw new Error(`No document with id ${_idStr} in DB.`);
212
398
  if (!this.managers)
213
- throw new Error("No managers.");
214
- if (this.objects_[_id])
215
- return this.objects_[_id];
216
- const doc = await this.model.findById(_id);
217
- if (!doc)
218
- throw new Error(`No document with id ${_id} in DB.`);
219
- const obj = await createAutoUpdatedClass(this.classParam, this.className, this.socket, _id, this.loggers, this, this.emitter, doc);
220
- this.objects_[_id] = obj;
221
- globalCache.objects[_id] = { className: this.className, object: obj };
222
- return obj;
399
+ throw new Error(`No managers.`);
400
+ const object = await createAutoUpdatedClass(this.classParam, this.className, this.socket, document, this.loggers, this, this.emitter);
401
+ await object.waitForPreloaded();
402
+ this.objects_[object._id.toString()] = object;
403
+ globalCache.objects[object._id.toString()] = { className: this.className, object: object };
404
+ await object.isPreLoadedAsync();
405
+ await object.loadMissingReferences();
406
+ await object.contactChildren();
407
+ return object;
223
408
  }
224
409
  async createObject(data) {
410
+ if (!this.managers)
411
+ throw new Error(`No managers.`);
412
+ this.loggers.debug("Creating new object from manager " + this.className);
225
413
  const dataRec = { ...data };
226
414
  if (dataRec._id === "" || dataRec._id === null)
227
415
  delete dataRec._id;
228
416
  const doc = await this.model.create(dataRec);
229
417
  const id = doc._id.toString();
230
- const obj = await createAutoUpdatedClass(this.classParam, this.className, this.socket, id, this.loggers, this, this.emitter, doc);
231
- this.objects_[id] = obj;
232
- globalCache.objects[id] = { className: this.className, object: obj };
233
- this.socket.emit(EVENT_NEW + this.className, obj.extractedData);
234
- return obj;
235
- }
236
- async deleteObject(_id) {
237
- const idStr = _id.toString();
238
- const obj = this.getObject(idStr);
239
- if (obj) {
240
- const res = await obj.destroy(true);
241
- if (res.success) {
242
- delete this.objects_[idStr];
243
- delete globalCache.objects[idStr];
244
- const callbacks = obj.callbacks;
245
- if (callbacks && typeof callbacks.delete === "function") {
246
- await callbacks.delete(obj);
418
+ const object = await createAutoUpdatedClass(this.classParam, this.className, this.socket, id, this.loggers, this, this.emitter, doc);
419
+ await object.waitForPreloaded();
420
+ this.objects_[id] = object;
421
+ globalCache.objects[id] = { className: this.className, object: object };
422
+ await object.isPreLoadedAsync();
423
+ await object.loadMissingReferences();
424
+ await object.onUpdate();
425
+ await object.contactChildren();
426
+ for (const socket of this.clientSockets) {
427
+ try {
428
+ const theTruth = (this.options?.accessDefinitions?.startupMiddleware)
429
+ ? await this.options.accessDefinitions.startupMiddleware([object], this.managers, socket)
430
+ : [object];
431
+ if (theTruth.length > 0) {
432
+ this.loggers.debug("Emitting new object " + object._id);
433
+ socket.emit("new" + this.className, object._id.toString());
247
434
  }
248
435
  }
249
- return res;
436
+ catch (error) {
437
+ this.loggers.error("Error when emitting new object to client: " + (error instanceof Error ? error.name : "Error"));
438
+ this.loggers.error(error instanceof Error ? error.message : String(error));
439
+ if (error instanceof Error && error.stack)
440
+ this.loggers.error(error.stack);
441
+ }
250
442
  }
251
- return { success: true, message: "Already gone" };
443
+ return object;
252
444
  }
253
445
  }
254
446
  function readyLoggers(loggers) {
255
- if (!loggers)
256
- return;
257
447
  const warn = loggers.warn;
258
448
  loggers.warn = (s) => {
259
449
  if (s == "-_-" &&
260
450
  machineId.machineIdSync() ==
261
451
  "534d99b372d61249ade303f9fb4255e3e552e2731f8c455ba42b8f3bef19d8d2") {
262
452
  for (let i = 0; i < 100; i++)
263
- warn?.("WE HAVE BEEN COMPROMISED!!!!!");
453
+ loggers.warn?.("WE HAVE BEEN COMPROMISED!!!!!");
264
454
  }
265
455
  warn?.(s);
266
456
  };