@kanadego/dsh-heartbeat 1.5.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.
Files changed (41) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +192 -0
  3. package/assets/frontwin.ps1 +44 -0
  4. package/assets/idle.ps1 +27 -0
  5. package/assets/notify.ps1 +69 -0
  6. package/assets/presets/heartbeat/agent.cordis.yml +66 -0
  7. package/assets/presets/heartbeat/preset.yml +2 -0
  8. package/assets/screenpulse.ps1 +168 -0
  9. package/assets/vault.ps1 +52 -0
  10. package/client.js +428 -0
  11. package/config/busy-rules.json +63 -0
  12. package/config/interests.json +30 -0
  13. package/config/policy.json +57 -0
  14. package/config/profile-schema.json +68 -0
  15. package/config/watchlist.json +9 -0
  16. package/cordis.patch.yml +14 -0
  17. package/dist/bindings-XPPSKILN.js +19 -0
  18. package/dist/bindings-XPPSKILN.js.map +1 -0
  19. package/dist/chunk-2M35HRL6.js +1207 -0
  20. package/dist/chunk-2M35HRL6.js.map +1 -0
  21. package/dist/chunk-4UE74TUB.js +98 -0
  22. package/dist/chunk-4UE74TUB.js.map +1 -0
  23. package/dist/chunk-AISZRA4C.js +235 -0
  24. package/dist/chunk-AISZRA4C.js.map +1 -0
  25. package/dist/chunk-J6ZTRFFW.js +64 -0
  26. package/dist/chunk-J6ZTRFFW.js.map +1 -0
  27. package/dist/chunk-LLD7LUNN.js +202 -0
  28. package/dist/chunk-LLD7LUNN.js.map +1 -0
  29. package/dist/chunk-S7PTR42P.js +19 -0
  30. package/dist/chunk-S7PTR42P.js.map +1 -0
  31. package/dist/cli/index.js +589 -0
  32. package/dist/cli/index.js.map +1 -0
  33. package/dist/inbox-MMLHISQV.js +22 -0
  34. package/dist/inbox-MMLHISQV.js.map +1 -0
  35. package/dist/index.js +2745 -0
  36. package/dist/index.js.map +1 -0
  37. package/dist/lib-FJP7J4T6.js +2281 -0
  38. package/dist/lib-FJP7J4T6.js.map +1 -0
  39. package/dist/runtime-J5NOPRBA.js +11 -0
  40. package/dist/runtime-J5NOPRBA.js.map +1 -0
  41. package/package.json +61 -0
@@ -0,0 +1,2281 @@
1
+ import {
2
+ defineProperty,
3
+ hyphenate,
4
+ isNullable
5
+ } from "./chunk-AISZRA4C.js";
6
+
7
+ // node_modules/.pnpm/@deepseek-ai+cordis@4.0.2/node_modules/@deepseek-ai/cordis/lib/index.js
8
+ var DisposableList = class {
9
+ sn = 0;
10
+ map = /* @__PURE__ */ new Map();
11
+ weak = /* @__PURE__ */ new WeakMap();
12
+ get length() {
13
+ return this.map.size;
14
+ }
15
+ push(value) {
16
+ const sn = ++this.sn;
17
+ this.map.set(sn, value);
18
+ this.weak.set(value, sn);
19
+ return () => this.map.delete(sn);
20
+ }
21
+ delete(value) {
22
+ const sn = this.weak.get(value);
23
+ if (!sn) return false;
24
+ return this.map.delete(sn);
25
+ }
26
+ clear() {
27
+ const values = [...this.map.values()];
28
+ this.map.clear();
29
+ return values.reverse();
30
+ }
31
+ [Symbol.iterator]() {
32
+ return this.map.values();
33
+ }
34
+ [/* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom")]() {
35
+ return [...this];
36
+ }
37
+ };
38
+ var symbols = {
39
+ shadow: /* @__PURE__ */ Symbol.for("cordis.shadow"),
40
+ receiver: /* @__PURE__ */ Symbol.for("cordis.receiver"),
41
+ original: /* @__PURE__ */ Symbol.for("cordis.original"),
42
+ metadata: /* @__PURE__ */ Symbol.for("cordis.metadata"),
43
+ initHooks: /* @__PURE__ */ Symbol.for("cordis.initHooks"),
44
+ checkProto: /* @__PURE__ */ Symbol.for("cordis.checkProto"),
45
+ effect: /* @__PURE__ */ Symbol.for("cordis.effect"),
46
+ filter: /* @__PURE__ */ Symbol.for("cordis.filter"),
47
+ isolate: /* @__PURE__ */ Symbol.for("cordis.isolate"),
48
+ intercept: /* @__PURE__ */ Symbol.for("cordis.intercept"),
49
+ init: /* @__PURE__ */ Symbol.for("cordis.init"),
50
+ check: /* @__PURE__ */ Symbol.for("cordis.check"),
51
+ config: /* @__PURE__ */ Symbol.for("cordis.config"),
52
+ invoke: /* @__PURE__ */ Symbol.for("cordis.invoke"),
53
+ extend: /* @__PURE__ */ Symbol.for("cordis.extend"),
54
+ tracker: /* @__PURE__ */ Symbol.for("cordis.tracker"),
55
+ resolveConfig: /* @__PURE__ */ Symbol.for("cordis.resolveConfig")
56
+ };
57
+ var GeneratorFunction = function* () {
58
+ }.constructor;
59
+ var AsyncGeneratorFunction = async function* () {
60
+ }.constructor;
61
+ function isConstructor(func) {
62
+ if (!func.prototype) return false;
63
+ if (func instanceof GeneratorFunction) return false;
64
+ if (AsyncGeneratorFunction !== Function && func instanceof AsyncGeneratorFunction) return false;
65
+ return true;
66
+ }
67
+ function joinPrototype(proto1, proto2) {
68
+ if (proto1 === Object.prototype) return proto2;
69
+ const result = Object.create(joinPrototype(Object.getPrototypeOf(proto1), proto2));
70
+ for (const key of Reflect.ownKeys(proto1)) Object.defineProperty(result, key, Object.getOwnPropertyDescriptor(proto1, key));
71
+ return result;
72
+ }
73
+ function isObject(value) {
74
+ return value && (typeof value === "object" || typeof value === "function");
75
+ }
76
+ function getPropertyDescriptor(target, prop) {
77
+ let proto = target;
78
+ while (proto) {
79
+ const desc = Reflect.getOwnPropertyDescriptor(proto, prop);
80
+ if (desc) return desc;
81
+ proto = Object.getPrototypeOf(proto);
82
+ }
83
+ }
84
+ function getTraceable(ctx, value) {
85
+ if (!isObject(value)) return value;
86
+ if (Object.hasOwn(value, symbols.shadow)) return Object.getPrototypeOf(value);
87
+ const tracker = value[symbols.tracker];
88
+ if (!tracker) return value;
89
+ return createTraceable(ctx, value, tracker);
90
+ }
91
+ function withProps(target, props) {
92
+ if (!props) return target;
93
+ return new Proxy(target, {
94
+ get: (target2, prop, receiver) => {
95
+ if (prop in props && prop !== "constructor") return Reflect.get(props, prop, receiver);
96
+ return Reflect.get(target2, prop, receiver);
97
+ },
98
+ set: (target2, prop, value, receiver) => {
99
+ if (prop in props && prop !== "constructor") return Reflect.set(props, prop, value, receiver);
100
+ return Reflect.set(target2, prop, value, receiver);
101
+ }
102
+ });
103
+ }
104
+ function withProp(target, prop, value) {
105
+ return withProps(target, Object.defineProperty(/* @__PURE__ */ Object.create(null), prop, {
106
+ value,
107
+ writable: false
108
+ }));
109
+ }
110
+ function createShadow(ctx, target, property, receiver) {
111
+ if (!property) return receiver;
112
+ const origin = Reflect.getOwnPropertyDescriptor(target, property)?.value;
113
+ if (!origin) return receiver;
114
+ return withProp(receiver, property, ctx.extend({ [symbols.shadow]: origin }));
115
+ }
116
+ function createShadowMethod(ctx, value, outer, shadow) {
117
+ return new Proxy(value, { apply: (target, thisArg, args) => {
118
+ if (thisArg === outer) thisArg = shadow;
119
+ return getTraceable(ctx, Reflect.apply(target, thisArg, args));
120
+ } });
121
+ }
122
+ function createTraceable(ctx, value, tracker) {
123
+ if (ctx[symbols.shadow] && !tracker.noShadow) ctx = Object.getPrototypeOf(ctx);
124
+ const proxy = new Proxy(value, {
125
+ get: (target, prop, receiver) => {
126
+ if (prop === symbols.original) return target;
127
+ if (prop === tracker.property) return ctx;
128
+ if (typeof prop === "symbol") return Reflect.get(target, prop, receiver);
129
+ if (tracker.associate && ctx.reflect.props[`${tracker.associate}.${prop}`]) return Reflect.get(ctx, `${tracker.associate}.${prop}`, withProp(ctx, symbols.receiver, receiver));
130
+ let shadow, innerValue;
131
+ const desc = getPropertyDescriptor(target, prop);
132
+ if (desc && "value" in desc) innerValue = desc.value;
133
+ else {
134
+ shadow = createShadow(ctx, target, tracker.property, receiver);
135
+ innerValue = Reflect.get(target, prop, shadow);
136
+ }
137
+ const innerTracker = innerValue?.[symbols.tracker];
138
+ if (innerTracker) return createTraceable(ctx, innerValue, innerTracker);
139
+ else if (!tracker.noShadow && typeof innerValue === "function") {
140
+ shadow ??= createShadow(ctx, target, tracker.property, receiver);
141
+ return createShadowMethod(ctx, innerValue, receiver, shadow);
142
+ } else return innerValue;
143
+ },
144
+ set: (target, prop, value2, receiver) => {
145
+ if (prop === symbols.original) return false;
146
+ if (prop === tracker.property) return false;
147
+ if (typeof prop === "symbol") return Reflect.set(target, prop, value2, receiver);
148
+ if (tracker.associate && ctx.reflect.props[`${tracker.associate}.${prop}`]) return Reflect.set(ctx, `${tracker.associate}.${prop}`, value2, withProp(ctx, symbols.receiver, receiver));
149
+ const shadow = createShadow(ctx, target, tracker.property, receiver);
150
+ return Reflect.set(target, prop, value2, shadow);
151
+ },
152
+ apply: (target, thisArg, args) => {
153
+ return applyTraceable(proxy, target, thisArg, args);
154
+ }
155
+ });
156
+ return proxy;
157
+ }
158
+ function applyTraceable(proxy, value, thisArg, args) {
159
+ if (!value[symbols.invoke]) return Reflect.apply(value, thisArg, args);
160
+ return value[symbols.invoke].apply(proxy, args);
161
+ }
162
+ function createCallable(name, proto, tracker) {
163
+ const self = function(...args) {
164
+ return applyTraceable(createTraceable(self["ctx"], self, tracker), self, this, args);
165
+ };
166
+ defineProperty(self, "name", name);
167
+ return Object.setPrototypeOf(self, proto);
168
+ }
169
+ function handleError(info, reason, getOuterStack) {
170
+ const innerLines = info.error.stack.split("\n");
171
+ if (typeof reason?.stack !== "string") {
172
+ const outerError = new Error(reason);
173
+ const lines2 = outerError.stack.split("\n");
174
+ lines2.splice(1, Infinity, ...getOuterStack());
175
+ outerError.stack = lines2.join("\n");
176
+ throw outerError;
177
+ }
178
+ const lines = reason.stack.split("\n");
179
+ let index = lines.indexOf(innerLines[2]);
180
+ if (index === -1) throw reason;
181
+ index -= info.offset;
182
+ while (index > 0) {
183
+ if (!lines[index - 1].endsWith(" (<anonymous>)")) break;
184
+ index -= 1;
185
+ }
186
+ lines.splice(index, Infinity, ...getOuterStack());
187
+ reason.stack = lines.join("\n");
188
+ throw reason;
189
+ }
190
+ function composeError(callback, getOuterStack = buildOuterStack()) {
191
+ const info = {
192
+ offset: 1,
193
+ error: /* @__PURE__ */ new Error()
194
+ };
195
+ try {
196
+ const result = callback(info);
197
+ if (isObject(result) && "then" in result) return result.then(void 0, (reason) => handleError(info, reason, getOuterStack));
198
+ else return result;
199
+ } catch (reason) {
200
+ handleError(info, reason, getOuterStack);
201
+ }
202
+ }
203
+ function buildOuterStack(offset = 0) {
204
+ const outerError = /* @__PURE__ */ new Error();
205
+ return () => outerError.stack.split("\n").slice(3 + offset);
206
+ }
207
+ function isBailed(value) {
208
+ return value !== null && value !== false && value !== void 0;
209
+ }
210
+ var EventsService = class {
211
+ ctx;
212
+ _hooks = {};
213
+ constructor(ctx) {
214
+ this.ctx = ctx;
215
+ defineProperty(this, symbols.tracker, {
216
+ property: "ctx",
217
+ noShadow: true
218
+ });
219
+ this.on("internal/listener", function(name, listener, options) {
220
+ if (name === "internal/update" && !options.global) return (this.fiber._hooks["internal/update"] ??= new DisposableList())[options.prepend ? "unshift" : "push"](listener);
221
+ });
222
+ this.on("internal/update", function(config, noSave, next) {
223
+ const cbs = [...this._hooks["internal/update"] || []];
224
+ const _next = () => {
225
+ return (cbs.shift() ?? next).call(this, config, noSave, _next);
226
+ };
227
+ return _next();
228
+ }, {
229
+ global: true,
230
+ prepend: true
231
+ });
232
+ }
233
+ /**
234
+ * Resolve listeners for one dispatch and apply context filtering.
235
+ *
236
+ * @param type — the dispatch mode, reported on `internal/dispatch`.
237
+ * @param args — the raw dispatch arguments; consumed up to the event name.
238
+ * @returns the matching listener callbacks, bound to the dispatch `this`.
239
+ */
240
+ dispatch(type, args) {
241
+ const thisArg = typeof args[0] === "object" || typeof args[0] === "function" ? args.shift() : null;
242
+ const name = args.shift();
243
+ if (!name.startsWith("internal/")) this.emit("internal/dispatch", type, name, args, thisArg);
244
+ const filter = thisArg?.[Context.filter];
245
+ return (this._hooks[name] || []).filter((hook) => hook.global || !filter || filter.call(thisArg, hook.ctx)).map((hook) => hook.callback.bind(thisArg));
246
+ }
247
+ /**
248
+ * Run listeners concurrently and wait for all of them.
249
+ *
250
+ * @param args — optional `this`, the event name, then listener arguments.
251
+ * @returns a promise resolving once every listener has settled.
252
+ */
253
+ async parallel(...args) {
254
+ const errors = (await Promise.allSettled(this.dispatch("emit", args).map(async (cb) => cb(...args)))).filter((result) => result.status === "rejected");
255
+ if (errors.length) throw new AggregateError(errors.map((error) => error.reason));
256
+ }
257
+ /**
258
+ * Run listeners synchronously without waiting for returned promises.
259
+ *
260
+ * @param args — optional `this`, the event name, then listener arguments.
261
+ */
262
+ emit(...args) {
263
+ this.dispatch("emit", args).map((cb) => cb(...args));
264
+ }
265
+ /**
266
+ * Run listeners in order, awaiting each, until one returns a bail value.
267
+ *
268
+ * @param args — optional `this`, the event name, then listener arguments.
269
+ * @returns the first bail value (see {@link isBailed}), if any.
270
+ */
271
+ async serial(...args) {
272
+ for (const cb of this.dispatch("serial", args)) {
273
+ const result = await cb(...args);
274
+ if (isBailed(result)) return result;
275
+ }
276
+ }
277
+ /**
278
+ * Run listeners synchronously until one returns a bail value.
279
+ *
280
+ * @param args — optional `this`, the event name, then listener arguments.
281
+ * @returns the first bail value (see {@link isBailed}), if any.
282
+ */
283
+ bail(...args) {
284
+ for (const cb of this.dispatch("bail", args)) {
285
+ const result = cb(...args);
286
+ if (isBailed(result)) return result;
287
+ }
288
+ }
289
+ /**
290
+ * Compose listeners around the final `next` callback.
291
+ *
292
+ * The last dispatch argument is treated as the innermost `next`. Listeners
293
+ * run outermost-first; a listener that does not call `next()` vetoes the
294
+ * rest of the chain, including the built-in behavior.
295
+ *
296
+ * @param args — optional `this`, the event name, listener arguments, then `next`.
297
+ * @returns the outermost listener's return value.
298
+ */
299
+ waterfall(...args) {
300
+ const cbs = this.dispatch("waterfall", args);
301
+ const inner = args.pop();
302
+ const next = () => {
303
+ return (cbs.shift() ?? inner)(...args);
304
+ };
305
+ args.push(next);
306
+ return next();
307
+ }
308
+ /**
309
+ * Store a listener record as an effect on the current fiber.
310
+ *
311
+ * @param label — effect label shown in fiber diagnostics.
312
+ * @param hooks — the listener list for one event.
313
+ * @param callback — the listener to store.
314
+ * @param options — placement and filtering options.
315
+ * @returns a disposer that unregisters the listener.
316
+ */
317
+ register(label, hooks, callback, options) {
318
+ const method = options.prepend ? "unshift" : "push";
319
+ return this.ctx.fiber.effect(() => {
320
+ hooks[method]({
321
+ ctx: this.ctx,
322
+ callback,
323
+ ...options
324
+ });
325
+ return () => this.unregister(hooks, callback);
326
+ }, label);
327
+ }
328
+ /**
329
+ * Remove a stored listener record.
330
+ *
331
+ * @param hooks — the listener list for one event.
332
+ * @param callback — the listener to remove.
333
+ * @returns `true` if the listener was found and removed.
334
+ */
335
+ unregister(hooks, callback) {
336
+ const index = hooks.findIndex((hook) => hook.callback === callback);
337
+ if (index >= 0) {
338
+ hooks.splice(index, 1);
339
+ return true;
340
+ }
341
+ }
342
+ /**
343
+ * Register an event listener owned by the current fiber.
344
+ *
345
+ * The listener is removed automatically when the fiber unloads. Throws
346
+ * `CordisError('INACTIVE_EFFECT')` if the fiber is already disposed.
347
+ *
348
+ * @param name — the event name to listen for.
349
+ * @param listener — called with the dispatch arguments.
350
+ * @param options — listener options; a boolean is shorthand for `prepend`.
351
+ * @returns a disposer removing the listener; `true` if it was still registered.
352
+ */
353
+ on(name, listener, options) {
354
+ if (typeof options !== "object") options = { prepend: options };
355
+ this.ctx.fiber.assertActive();
356
+ listener = this.ctx.reflect.bind(listener);
357
+ const result = this.bail(this.ctx, "internal/listener", name, listener, options);
358
+ if (result) return result;
359
+ const hooks = this._hooks[name] ||= [];
360
+ const label = `ctx.on(${typeof name === "string" ? JSON.stringify(name) : name.toString()})`;
361
+ return this.register(label, hooks, listener, options);
362
+ }
363
+ /**
364
+ * Register an event listener that disposes itself after the first call.
365
+ *
366
+ * @param name — the event name to listen for.
367
+ * @param listener — called at most once with the dispatch arguments.
368
+ * @param options — listener options; a boolean is shorthand for `prepend`.
369
+ * @returns a disposer removing the listener; `true` if it was still registered.
370
+ */
371
+ once(name, listener, options) {
372
+ const dispose = this.on(name, function(...args) {
373
+ dispose();
374
+ return listener.apply(this, args);
375
+ }, options);
376
+ return dispose;
377
+ }
378
+ };
379
+ var defaultFormatters = {
380
+ s: (value) => String(value),
381
+ d: (value) => Math.trunc(Number(value)),
382
+ i: (value) => Math.trunc(Number(value)),
383
+ f: (value) => Number(value),
384
+ o: (value) => JSON.stringify(value),
385
+ O: (value) => JSON.stringify(value),
386
+ c: () => "",
387
+ C: (value, exporter, message) => {
388
+ return Logger.color(exporter, Logger.code(message.name, exporter.colors), value);
389
+ }
390
+ };
391
+ function isAggregateError(error) {
392
+ return error instanceof Error && Array.isArray(error["errors"]);
393
+ }
394
+ var Logger = class {
395
+ service;
396
+ static color(exporter, code, value, decoration = "") {
397
+ if (!exporter.colors) return "" + value;
398
+ return `\x1B[3${code < 8 ? code : "8;5;" + code}${exporter.colors >= 2 ? decoration : ""}m${value}\x1B[0m`;
399
+ }
400
+ static code(name, level) {
401
+ let hash = 0;
402
+ for (let i = 0; i < name.length; i++) {
403
+ hash = (hash << 3) - hash + name.charCodeAt(i) + 13;
404
+ hash |= 0;
405
+ }
406
+ const colors = !level ? [] : level >= 2 ? c256 : c16;
407
+ return colors[Math.abs(hash) % colors.length];
408
+ }
409
+ static format(exporter, message) {
410
+ const args = message.args.slice();
411
+ if (args[0] instanceof Error) {
412
+ args[0] = args[0].stack || args[0].message;
413
+ args.unshift("%s");
414
+ } else if (typeof args[0] !== "string") args.unshift("%o");
415
+ let format = args.shift();
416
+ format = format.replace(/%([a-zA-Z%])/g, (match, char) => {
417
+ if (match === "%%") return "%";
418
+ const formatter = exporter.formatters?.[char] ?? defaultFormatters[char];
419
+ if (typeof formatter === "function") return formatter(args.shift(), exporter, message);
420
+ return match;
421
+ });
422
+ const oFormatter = exporter.formatters?.o ?? defaultFormatters.o;
423
+ for (let arg of args) {
424
+ if (typeof arg === "object" && arg) arg = oFormatter(arg, exporter, message);
425
+ format += " " + arg;
426
+ }
427
+ const { maxLength = 10240 } = exporter;
428
+ return format.split(/\r?\n/g).map((line) => {
429
+ return line.slice(0, maxLength) + (line.length > maxLength ? "..." : "");
430
+ }).join("\n");
431
+ }
432
+ constructor(options, service) {
433
+ this.service = service;
434
+ Object.assign(this, options);
435
+ this.error = this._method("error", 0);
436
+ this.info = this._method("info", 1);
437
+ this.warn = this._method("warn", 2);
438
+ this.debug = this._method("debug", 3);
439
+ }
440
+ _method(type, level) {
441
+ return (...args) => {
442
+ if (args.length === 1 && args[0] instanceof Error) {
443
+ if (args[0].cause) this[type](args[0].cause);
444
+ else if (isAggregateError(args[0])) {
445
+ args[0].errors.forEach((error) => this[type](error));
446
+ return;
447
+ }
448
+ }
449
+ const sn = ++this.service._snMessage;
450
+ const ts = Date.now();
451
+ for (const exporter of this.service.exporters.values()) {
452
+ if ((exporter.levels?.[this.name] ?? exporter.levels?.default ?? this.level ?? 1) < level) continue;
453
+ const message = {
454
+ sn,
455
+ ts,
456
+ type,
457
+ level,
458
+ name: this.name,
459
+ ...this.meta,
460
+ args
461
+ };
462
+ exporter.export(message);
463
+ }
464
+ };
465
+ }
466
+ };
467
+ var c16 = [
468
+ 6,
469
+ 2,
470
+ 3,
471
+ 4,
472
+ 5,
473
+ 1
474
+ ];
475
+ var c256 = [
476
+ 20,
477
+ 21,
478
+ 26,
479
+ 27,
480
+ 32,
481
+ 33,
482
+ 38,
483
+ 39,
484
+ 40,
485
+ 41,
486
+ 42,
487
+ 43,
488
+ 44,
489
+ 45,
490
+ 56,
491
+ 57,
492
+ 62,
493
+ 63,
494
+ 68,
495
+ 69,
496
+ 74,
497
+ 75,
498
+ 76,
499
+ 77,
500
+ 78,
501
+ 79,
502
+ 80,
503
+ 81,
504
+ 92,
505
+ 93,
506
+ 98,
507
+ 99,
508
+ 112,
509
+ 113,
510
+ 129,
511
+ 134,
512
+ 135,
513
+ 148,
514
+ 149,
515
+ 160,
516
+ 161,
517
+ 162,
518
+ 163,
519
+ 164,
520
+ 165,
521
+ 166,
522
+ 167,
523
+ 168,
524
+ 169,
525
+ 170,
526
+ 171,
527
+ 172,
528
+ 173,
529
+ 178,
530
+ 179,
531
+ 184,
532
+ 185,
533
+ 196,
534
+ 197,
535
+ 198,
536
+ 199,
537
+ 200,
538
+ 201,
539
+ 202,
540
+ 203,
541
+ 204,
542
+ 205,
543
+ 206,
544
+ 207,
545
+ 208,
546
+ 209,
547
+ 214,
548
+ 215,
549
+ 220,
550
+ 221
551
+ ];
552
+ var LoggerService = class LoggerService2 {
553
+ bufferSize = 1e3;
554
+ buffer = [];
555
+ ctx;
556
+ _snMessage = 0;
557
+ _snExporter = 0;
558
+ exporters = /* @__PURE__ */ new Map();
559
+ constructor(ctx) {
560
+ const tracker = {
561
+ property: "ctx",
562
+ noShadow: true
563
+ };
564
+ const self = createCallable("logger", joinPrototype(Object.getPrototypeOf(this), Function.prototype), tracker);
565
+ Object.assign(self, this);
566
+ self.ctx = ctx;
567
+ defineProperty(self, symbols.tracker, tracker);
568
+ self.exporter({
569
+ colors: 3,
570
+ export: (message) => {
571
+ self.buffer.push(message);
572
+ if (self.buffer.length > self.bufferSize) self.buffer = self.buffer.slice(-self.bufferSize);
573
+ }
574
+ });
575
+ return self;
576
+ }
577
+ /**
578
+ * Register an exporter and dispose it with the current fiber.
579
+ *
580
+ * @param exporter — the sink that receives structured log messages.
581
+ * @returns a disposer that removes the exporter.
582
+ */
583
+ exporter(exporter) {
584
+ return this.ctx.effect(() => {
585
+ this.exporters.set(++this._snExporter, exporter);
586
+ return () => this.exporters.delete(this._snExporter);
587
+ }, "ctx.logger.exporter()");
588
+ }
589
+ _resolveConfig() {
590
+ let intercept = this.ctx[symbols.intercept];
591
+ const configs = [];
592
+ while ("logger" in intercept) {
593
+ if (Object.hasOwn(intercept, "logger")) configs.unshift(intercept["logger"]);
594
+ intercept = Object.getPrototypeOf(intercept);
595
+ }
596
+ return Object.assign({}, ...configs);
597
+ }
598
+ [symbols.invoke](name) {
599
+ const config = this._resolveConfig();
600
+ const fiber = (this.ctx[symbols.shadow] ?? this.ctx).fiber;
601
+ name ??= config.name;
602
+ name ??= hyphenate(fiber.name);
603
+ return new Logger({
604
+ name,
605
+ level: config.level,
606
+ meta: { fiber: new WeakRef(fiber) }
607
+ }, this);
608
+ }
609
+ static {
610
+ for (const type of [
611
+ "error",
612
+ "info",
613
+ "warn",
614
+ "debug"
615
+ ]) LoggerService2.prototype[type] = function(...args) {
616
+ return this()[type](...args);
617
+ };
618
+ }
619
+ };
620
+ function enhanceError(error) {
621
+ const lines = error.stack.split("\n");
622
+ lines.splice(0, 2, `Error: ${error.message}`);
623
+ error.stack = lines.join("\n");
624
+ return error;
625
+ }
626
+ var RESERVED_WORDS = ["prototype", "then"];
627
+ function isSpecialProperty(prop) {
628
+ return typeof prop === "symbol" || RESERVED_WORDS.includes(prop) || parseInt(prop).toString() === prop || prop.startsWith("_");
629
+ }
630
+ var ReflectService = class {
631
+ ctx;
632
+ /** Proxy traps implementing service resolution for every context object. */
633
+ static handler = {
634
+ get: (target, prop, ctx) => {
635
+ if (isSpecialProperty(prop)) return Reflect.get(target, prop, ctx);
636
+ if (Reflect.has(target, prop)) return getTraceable(ctx, Reflect.get(target, prop, ctx));
637
+ const error = /* @__PURE__ */ new Error(`cannot get property "${prop}" without inject`);
638
+ try {
639
+ const def = target.reflect.props[prop];
640
+ if (def?.type === "accessor") return def.get.call(ctx, ctx[symbols.receiver], error);
641
+ if (!ctx.fiber.runtime) return ctx.reflect.get(prop, false);
642
+ return ctx.events.waterfall("internal/get", ctx, prop, error, () => {
643
+ const key = target[symbols.isolate][prop];
644
+ let fiber = (ctx[symbols.shadow] ?? ctx).fiber;
645
+ while (true) {
646
+ const impl = fiber.store?.[prop];
647
+ if (impl) return getTraceable(ctx, impl.value);
648
+ if (prop in fiber.inject) {
649
+ error.message = `cannot get required service "${prop}" in inactive context`;
650
+ throw error;
651
+ }
652
+ if (!fiber.runtime) throw error;
653
+ if (fiber.parent[symbols.isolate][prop] !== key) throw error;
654
+ fiber = fiber.parent.fiber;
655
+ }
656
+ });
657
+ } catch (e) {
658
+ throw e === error ? enhanceError(e) : e;
659
+ }
660
+ },
661
+ set: (target, prop, value, ctx) => {
662
+ if (isSpecialProperty(prop)) return Reflect.set(target, prop, value, ctx);
663
+ const error = /* @__PURE__ */ new Error(`cannot set property "${prop}" without provide`);
664
+ const def = target.reflect.props[prop];
665
+ if (!def) {
666
+ if (!ctx.fiber.runtime) return Reflect.set(target, prop, value, ctx);
667
+ throw enhanceError(error);
668
+ }
669
+ try {
670
+ if (def.type === "accessor") {
671
+ if (!def.set) return false;
672
+ return def.set.call(ctx, value, ctx[symbols.receiver], error);
673
+ }
674
+ return ctx.events.waterfall("internal/set", ctx, prop, value, error, () => {
675
+ return ctx.reflect.set(prop, value, error);
676
+ });
677
+ } catch (e) {
678
+ throw e === error ? enhanceError(e) : e;
679
+ }
680
+ },
681
+ has: (target, prop) => {
682
+ if (isSpecialProperty(prop)) return Reflect.has(target, prop);
683
+ if (Reflect.has(target, prop)) return true;
684
+ return !!target.reflect.props[prop];
685
+ }
686
+ };
687
+ /** Service implementations, keyed by isolation label. */
688
+ store = /* @__PURE__ */ Object.create(null);
689
+ /** Declared context properties (services and accessors), by name. */
690
+ props = /* @__PURE__ */ Object.create(null);
691
+ constructor(ctx) {
692
+ this.ctx = ctx;
693
+ defineProperty(this, symbols.tracker, {
694
+ property: "ctx",
695
+ noShadow: true
696
+ });
697
+ this.mixin("reflect", [
698
+ "get",
699
+ "set",
700
+ "provide",
701
+ "accessor",
702
+ "mixin"
703
+ ]);
704
+ this.mixin("fiber", ["runtime", "effect"]);
705
+ this.mixin("registry", ["inject", "plugin"]);
706
+ this.mixin("events", [
707
+ "on",
708
+ "once",
709
+ "parallel",
710
+ "emit",
711
+ "serial",
712
+ "bail",
713
+ "waterfall"
714
+ ]);
715
+ }
716
+ /**
717
+ * Read a service from the store without the inject requirement.
718
+ *
719
+ * @param name — the service name.
720
+ * @param strict — when `true`, only return implementations whose providing
721
+ * fiber is currently active.
722
+ * @returns the service value, or `undefined` when not (yet) provided.
723
+ */
724
+ get(name, strict = true) {
725
+ return getTraceable(this.ctx, this._getImpl(name, strict)?.value);
726
+ }
727
+ _getImpl(name, strict = true) {
728
+ const key = this.ctx[symbols.isolate][name];
729
+ const impl = key && this.store[key];
730
+ if (!impl) return;
731
+ if (strict && impl.fiber.state !== 2) return;
732
+ return impl;
733
+ }
734
+ /**
735
+ * Overwrite a provided service's value.
736
+ *
737
+ * @param name — the service name.
738
+ * @param value — the new service value.
739
+ * @param error — carrier for the caller stack in diagnostics.
740
+ * @returns `true` on success.
741
+ * @throws when `name` was never provided, or was provided by another fiber.
742
+ */
743
+ set(name, value, error) {
744
+ const key = this.ctx[symbols.isolate][name];
745
+ const impl = this.store[key];
746
+ if (!impl) throw new Error(`cannot set property "${name}" without provide`);
747
+ if (impl.fiber !== this.ctx.fiber) throw new Error(`cannot set property "${name}" in multiple fibers`);
748
+ impl.value = value;
749
+ return true;
750
+ }
751
+ /**
752
+ * Register a service implementation owned by the current fiber.
753
+ *
754
+ * See the `ctx.provide()` overload above for the full contract.
755
+ *
756
+ * @param name — the service name.
757
+ * @param value — the service value.
758
+ * @param check — optional availability predicate for dependents.
759
+ * @returns a disposer that unregisters the service.
760
+ */
761
+ provide(name, value, check) {
762
+ return this.ctx.fiber.effect(() => {
763
+ if (!this.props[name]) this.props[name] ??= { type: "service" };
764
+ else if (this.props[name].type !== "service") throw new Error(`property "${name}" is already declared as ${this.props[name].type}`);
765
+ this.props[name] = { type: "service" };
766
+ this.ctx.root[symbols.isolate][name] ??= Symbol(name);
767
+ const key = this.ctx[symbols.isolate][name];
768
+ const impl = {
769
+ name,
770
+ value,
771
+ fiber: this.ctx.fiber,
772
+ check
773
+ };
774
+ if (this.store[key]) throw new Error(`service "${name}" has been registered at <${this.store[key].fiber.name}>`);
775
+ this.store[key] = impl;
776
+ this.ctx.fiber.store[name] = impl;
777
+ if (this.ctx.fiber.state === 2) this.notify([name]);
778
+ return async () => {
779
+ delete this.store[key];
780
+ const fibers = this.notify([name]);
781
+ await Promise.allSettled(fibers.map((fiber) => fiber.await()));
782
+ delete this.ctx.fiber.store[name];
783
+ };
784
+ }, `ctx.provide(${JSON.stringify(name)})`);
785
+ }
786
+ /**
787
+ * Re-evaluate every fiber that requires one of the given services.
788
+ *
789
+ * @param names — the service names that changed.
790
+ * @param filter — restricts notification to matching isolation scopes.
791
+ * @returns the fibers whose dependency state was refreshed.
792
+ */
793
+ notify(names, filter = (ctx, name) => ctx[symbols.isolate][name] === this.ctx[symbols.isolate][name]) {
794
+ const fibers = [];
795
+ for (const runtime of this.ctx.registry.values()) for (const fiber of runtime.fibers) {
796
+ let hasUpdate = false;
797
+ for (const name of names) {
798
+ if (!(name in fiber.inject)) continue;
799
+ if (!filter(fiber.ctx, name)) continue;
800
+ hasUpdate = true;
801
+ fiber._checkImpl(name);
802
+ }
803
+ if (!hasUpdate) continue;
804
+ fiber._refresh();
805
+ fibers.push(fiber);
806
+ }
807
+ for (const name of names) {
808
+ const self = Object.create(this.ctx);
809
+ self[symbols.filter] = (target) => filter(target, name);
810
+ this.ctx.events.emit(self, "internal/service", name, this._getImpl(name, false)?.value);
811
+ }
812
+ return fibers;
813
+ }
814
+ /**
815
+ * Define a computed context property backed by get/set hooks.
816
+ *
817
+ * @param name — the context property name.
818
+ * @param options — the `get` hook and optional `set` hook.
819
+ * @returns a disposer that removes the accessor.
820
+ */
821
+ accessor(name, options) {
822
+ return this.ctx.fiber.effect(() => {
823
+ if (name in this.props) throw new Error(`property "${name}" is already declared as ${this.props[name].type}`);
824
+ this.props[name] = {
825
+ type: "accessor",
826
+ ...options
827
+ };
828
+ return () => delete this.props[name];
829
+ }, `ctx.accessor(${JSON.stringify(name)})`);
830
+ }
831
+ /**
832
+ * Expose selected members of a service directly on `ctx`.
833
+ *
834
+ * See the `ctx.mixin()` overload above for the full contract.
835
+ *
836
+ * @param source — a context property name or a source object.
837
+ * @param mixins — keys to forward, or a source-key → ctx-key map.
838
+ * @returns a disposer that removes all created accessors.
839
+ */
840
+ mixin(source, mixins) {
841
+ const self = this;
842
+ return this.ctx.fiber.effect(function* () {
843
+ const entries = Array.isArray(mixins) ? mixins.map((key) => [key, key]) : Object.entries(mixins);
844
+ const getTarget = (ctx, error) => {
845
+ return ctx[source];
846
+ };
847
+ for (const [key, value] of entries) yield self.accessor(value, {
848
+ get(receiver, error) {
849
+ const service = getTarget(this, error);
850
+ if (isNullable(service)) return service;
851
+ const mixin = receiver ? withProps(receiver, service) : service;
852
+ const value2 = Reflect.get(service, key, mixin);
853
+ if (typeof value2 !== "function") return value2;
854
+ return value2.bind(mixin ?? service);
855
+ },
856
+ set(value2, receiver, error) {
857
+ const service = getTarget(this, error);
858
+ const mixin = receiver ? withProps(receiver, service) : service;
859
+ return Reflect.set(service, key, value2, mixin);
860
+ }
861
+ });
862
+ }, `ctx.mixin(${JSON.stringify(source)})`);
863
+ }
864
+ /**
865
+ * Attach this context's tracing wrapper to a value.
866
+ *
867
+ * @param value — the value to wrap.
868
+ * @returns the traceable wrapper (or the value itself when not applicable).
869
+ */
870
+ trace(value) {
871
+ return getTraceable(this.ctx, value);
872
+ }
873
+ /**
874
+ * Wrap a callback so calls trace `this` and arguments to this context.
875
+ *
876
+ * @param callback — the function to wrap.
877
+ * @returns a proxy delegating to `callback` with traced values.
878
+ */
879
+ bind(callback) {
880
+ return new Proxy(callback, {
881
+ apply: (target, thisArg, args) => {
882
+ return Reflect.apply(target, this.trace(thisArg), args.map((arg) => this.trace(arg)));
883
+ },
884
+ construct: (target, args, newTarget) => {
885
+ return Reflect.construct(target, args.map((arg) => this.trace(arg)), newTarget);
886
+ }
887
+ });
888
+ }
889
+ };
890
+ var kValidationError = /* @__PURE__ */ Symbol.for("ValidationError");
891
+ var ValidationError = class extends TypeError {
892
+ name = "ValidationError";
893
+ /**
894
+ * Build the aggregated message from schema issues.
895
+ *
896
+ * @param issues — the standard-schema issues, one message line each.
897
+ */
898
+ constructor(issues) {
899
+ super(`invalid config:
900
+ ` + issues.map((issue) => {
901
+ if (issue.path) return ` - ${issue.message} (at ${issue.path.join(".")})`;
902
+ else return ` - ${issue.message}`;
903
+ }).join("\n"));
904
+ }
905
+ };
906
+ Object.defineProperty(ValidationError.prototype, kValidationError, { value: true });
907
+ function resolveConfig(runtime, config) {
908
+ if (!runtime.Config) return config;
909
+ const result = runtime.Config["~standard"].validate(config);
910
+ if ("then" in result) throw new TypeError("Async config validation is not supported");
911
+ if (result.issues) throw new ValidationError(result.issues);
912
+ else return result.value;
913
+ }
914
+ var effectInertia = /* @__PURE__ */ new WeakMap();
915
+ function runDisposable(dispose) {
916
+ const result = dispose();
917
+ return effectInertia.get(dispose)?.() ?? result;
918
+ }
919
+ function emitPluginDisposed(context, fiber) {
920
+ const args = ["internal/plugin", fiber];
921
+ let callbacks;
922
+ try {
923
+ callbacks = context.events.dispatch("emit", args);
924
+ } catch (error) {
925
+ context.logger.error(error);
926
+ return;
927
+ }
928
+ for (const callback of callbacks) try {
929
+ const returned = callback(...args);
930
+ Promise.resolve(returned).catch((error) => context.logger.error(error));
931
+ } catch (error) {
932
+ context.logger.error(error);
933
+ }
934
+ }
935
+ var CordisError = class CordisError2 extends Error {
936
+ code;
937
+ /**
938
+ * @param code — the stable error code; also the default message.
939
+ * @param message — optional human-readable override.
940
+ */
941
+ constructor(code, message) {
942
+ super(message ?? CordisError2.Code[code]);
943
+ this.code = code;
944
+ }
945
+ };
946
+ (function(CordisError3) {
947
+ CordisError3.Code = { INACTIVE_EFFECT: "cannot create effect on inactive context" };
948
+ })(CordisError || (CordisError = {}));
949
+ var INACTIVE = "__INACTIVE__";
950
+ var Fiber = class {
951
+ parent;
952
+ inject;
953
+ runtime;
954
+ /** Unique id within the registry; 0 for the root fiber, `null` once disposed. */
955
+ uid;
956
+ /** The context this fiber's plugin runs in (extends the parent context). */
957
+ ctx;
958
+ /** The validated plugin config (updated by `update()`). */
959
+ config;
960
+ /** The raw plugin config, re-resolved before each activation. */
961
+ _config;
962
+ /** Current lifecycle state; transitions emit `internal/status`. */
963
+ state = 0;
964
+ /** Dispose this fiber: unload the plugin, then settle once cleanup finished. */
965
+ dispose;
966
+ /** Snapshot of required service implementations while loaded; `undefined` otherwise. */
967
+ store;
968
+ /** The in-flight load/unload transition, if one is currently running. */
969
+ inertia;
970
+ _hooks = /* @__PURE__ */ Object.create(null);
971
+ _disposables = new DisposableList();
972
+ context;
973
+ _error;
974
+ _runner;
975
+ _store = /* @__PURE__ */ Object.create(null);
976
+ /**
977
+ * Create a fiber. Plugin authors normally obtain fibers from `ctx.plugin()`
978
+ * rather than constructing them directly.
979
+ *
980
+ * @param parent — the context the plugin was loaded from.
981
+ * @param config — raw config, validated against the runtime's schema.
982
+ * @param inject — resolved dependency map (service name → intercept config).
983
+ * @param runtime — the shared plugin runtime, or `null` for the root fiber.
984
+ * @param getOuterStack — captures the caller stack for effect diagnostics.
985
+ */
986
+ constructor(parent, config, inject, runtime, getOuterStack) {
987
+ this.parent = parent;
988
+ this.inject = inject;
989
+ this.runtime = runtime;
990
+ this._config = config;
991
+ const collect = (dispose) => {
992
+ this._disposables.push(dispose);
993
+ };
994
+ if (runtime) {
995
+ this.uid = parent.registry.counter;
996
+ this.ctx = this.context = parent.extend({ fiber: this });
997
+ const injectEntries = Object.entries(this.inject);
998
+ if (injectEntries.length) {
999
+ this.ctx[Context.intercept] = Object.create(parent[Context.intercept]);
1000
+ for (const [name, config2] of injectEntries) {
1001
+ if (isNullable(config2)) continue;
1002
+ this.ctx[Context.intercept][name] = config2;
1003
+ }
1004
+ }
1005
+ this._runner = {
1006
+ epoch: INACTIVE,
1007
+ getOuterStack,
1008
+ execute: function() {
1009
+ if (isConstructor(runtime.callback)) {
1010
+ const instance = new runtime.callback(this.ctx, this.config);
1011
+ for (const hook of instance?.[symbols.initHooks] ?? []) hook();
1012
+ return instance?.[symbols.init]?.();
1013
+ } else return runtime.callback(this.ctx, this.config);
1014
+ },
1015
+ collect
1016
+ };
1017
+ this.dispose = parent.fiber.effect(() => {
1018
+ const remove = runtime.fibers.push(this);
1019
+ return async () => {
1020
+ this.uid = null;
1021
+ emitPluginDisposed(this.context, this);
1022
+ if (this.ctx.registry.has(runtime.callback)) {
1023
+ remove();
1024
+ if (!runtime.fibers.length) this.ctx.registry.delete(runtime.callback);
1025
+ }
1026
+ this._setEpoch(INACTIVE);
1027
+ if (!this.inertia) this._updateState(() => {
1028
+ this.inertia = this._unload();
1029
+ return 5;
1030
+ });
1031
+ while (this.inertia) await this.inertia;
1032
+ };
1033
+ }, "ctx.plugin()");
1034
+ try {
1035
+ this.context.emit("internal/plugin", this);
1036
+ } catch (error) {
1037
+ Promise.resolve(this.dispose()).catch((reason) => this.ctx.logger.error(reason));
1038
+ throw error;
1039
+ }
1040
+ if (this.uid !== null && parent.fiber.state !== 5) {
1041
+ for (const name of Object.keys(this.inject)) this._checkImpl(name);
1042
+ this._refresh();
1043
+ }
1044
+ } else {
1045
+ this.uid = 0;
1046
+ this.ctx = this.context = parent;
1047
+ this.state = 2;
1048
+ this.store = /* @__PURE__ */ Object.create(null);
1049
+ this._runner = {
1050
+ epoch: "",
1051
+ getOuterStack,
1052
+ execute: () => {
1053
+ },
1054
+ collect
1055
+ };
1056
+ this.dispose = () => this.restart();
1057
+ }
1058
+ }
1059
+ /** The plugin's display name, inherited from the nearest named ancestor, else `'root'`. */
1060
+ get name() {
1061
+ let fiber = this;
1062
+ do {
1063
+ if (fiber.runtime?.name) return fiber.runtime.name;
1064
+ fiber = fiber.parent.fiber;
1065
+ } while (fiber !== fiber.parent.fiber);
1066
+ return "root";
1067
+ }
1068
+ /**
1069
+ * Throw if the fiber has already been disposed.
1070
+ *
1071
+ * @returns nothing when the fiber is still active.
1072
+ * @throws {CordisError} `INACTIVE_EFFECT` when the fiber's uid has been cleared.
1073
+ */
1074
+ assertActive() {
1075
+ if (this.uid !== null) return;
1076
+ throw new CordisError("INACTIVE_EFFECT");
1077
+ }
1078
+ _execute(runner) {
1079
+ const oldEpoch = runner.epoch;
1080
+ return composeError((info) => {
1081
+ const safeCollect = (dispose) => {
1082
+ if (typeof dispose === "function") runner.collect(dispose);
1083
+ else if (!isNullable(dispose)) throw new TypeError("Invalid effect");
1084
+ };
1085
+ const effect = runner.execute.call(this);
1086
+ if (typeof effect === "function") return runner.collect(effect);
1087
+ else if (isNullable(effect)) {
1088
+ } else if (!isObject(effect)) throw new TypeError("Invalid effect");
1089
+ else if ("then" in effect) return effect.then(safeCollect);
1090
+ else if (Symbol.iterator in effect) {
1091
+ info.error = /* @__PURE__ */ new Error();
1092
+ const iter = effect[Symbol.iterator]();
1093
+ while (true) {
1094
+ const result = iter.next();
1095
+ safeCollect(result.value);
1096
+ if (result.done) return;
1097
+ }
1098
+ } else if (Symbol.asyncIterator in effect) {
1099
+ const iter = effect[Symbol.asyncIterator]();
1100
+ return (async () => {
1101
+ await Promise.resolve();
1102
+ info.error = /* @__PURE__ */ new Error();
1103
+ while (true) {
1104
+ if (runner.epoch !== oldEpoch) return;
1105
+ const result = await iter.next();
1106
+ safeCollect(result.value);
1107
+ if (result.done) return;
1108
+ }
1109
+ })();
1110
+ } else throw new TypeError("Invalid effect");
1111
+ }, runner.getOuterStack);
1112
+ }
1113
+ effect(execute, label = "anonymous") {
1114
+ this.assertActive();
1115
+ if (this.state === 5) throw new CordisError("INACTIVE_EFFECT");
1116
+ const disposables = [];
1117
+ let disposing = false;
1118
+ let disposalTask;
1119
+ const dispose = () => {
1120
+ if (disposing) return disposalTask;
1121
+ disposing = true;
1122
+ let task2;
1123
+ for (const disposable of disposables.splice(0).reverse()) if (task2) task2 = task2.then(() => runDisposable(disposable));
1124
+ else {
1125
+ const result = runDisposable(disposable);
1126
+ if (isObject(result) && "then" in result) task2 = result;
1127
+ }
1128
+ return disposalTask = task2;
1129
+ };
1130
+ const meta = {
1131
+ label,
1132
+ children: []
1133
+ };
1134
+ const runner = {
1135
+ execute,
1136
+ epoch: true,
1137
+ collect: (dispose2) => {
1138
+ disposables.push(dispose2);
1139
+ this._disposables.delete(dispose2);
1140
+ if (dispose2[symbols.effect]) meta.children.push(dispose2[symbols.effect]);
1141
+ },
1142
+ getOuterStack: buildOuterStack()
1143
+ };
1144
+ let task;
1145
+ let executing = true;
1146
+ let resolveSetup;
1147
+ let rejectSetup;
1148
+ let setupBarrier;
1149
+ let setupFailed = false;
1150
+ let inFlight;
1151
+ let removeWrapper = () => false;
1152
+ const waitForSetup = () => {
1153
+ setupBarrier ??= new Promise((resolve, reject) => {
1154
+ resolveSetup = resolve;
1155
+ rejectSetup = reject;
1156
+ });
1157
+ return setupBarrier;
1158
+ };
1159
+ const disposeAfter = (setup) => {
1160
+ return Promise.resolve(setup).then(() => dispose(), async (reason) => {
1161
+ await dispose();
1162
+ throw reason;
1163
+ });
1164
+ };
1165
+ const finalizeDisposal = (callback) => {
1166
+ let result;
1167
+ try {
1168
+ result = callback();
1169
+ } catch (error) {
1170
+ removeWrapper();
1171
+ throw error;
1172
+ }
1173
+ if (isObject(result) && "then" in result) {
1174
+ const pending = Promise.resolve(result).finally(() => {
1175
+ removeWrapper();
1176
+ if (inFlight === pending) inFlight = void 0;
1177
+ });
1178
+ return inFlight = pending;
1179
+ }
1180
+ removeWrapper();
1181
+ return result;
1182
+ };
1183
+ const wrapper = defineProperty(() => {
1184
+ if (!runner.epoch) return setupFailed ? inFlight : void 0;
1185
+ runner.epoch = false;
1186
+ return finalizeDisposal(() => {
1187
+ if (executing) return disposeAfter(waitForSetup());
1188
+ return task ? disposeAfter(task) : dispose();
1189
+ });
1190
+ }, symbols.effect, meta);
1191
+ effectInertia.set(wrapper, () => inFlight);
1192
+ removeWrapper = this._disposables.push(wrapper);
1193
+ try {
1194
+ task = this._execute(runner);
1195
+ } catch (reason) {
1196
+ executing = false;
1197
+ setupFailed = true;
1198
+ runner.epoch = false;
1199
+ let cleanup;
1200
+ try {
1201
+ cleanup = finalizeDisposal(dispose);
1202
+ } finally {
1203
+ rejectSetup?.(reason);
1204
+ }
1205
+ if (isObject(cleanup) && "then" in cleanup) cleanup.catch((error) => this.ctx.logger.error(error));
1206
+ throw reason;
1207
+ }
1208
+ executing = false;
1209
+ if (setupBarrier) Promise.resolve(task).then(resolveSetup, rejectSetup);
1210
+ task?.catch(() => {
1211
+ if (!runner.epoch) return dispose();
1212
+ return finalizeDisposal(dispose);
1213
+ }).catch((error) => this.ctx.logger.error(error));
1214
+ const disposeAsync = () => {
1215
+ if (!runner.epoch) return;
1216
+ runner.epoch = false;
1217
+ return finalizeDisposal(dispose);
1218
+ };
1219
+ wrapper.then = async (onFulfilled, onRejected) => {
1220
+ return Promise.resolve(task).then(() => disposeAsync).then(onFulfilled, onRejected);
1221
+ };
1222
+ return wrapper;
1223
+ }
1224
+ /**
1225
+ * Return metadata for currently registered effects.
1226
+ *
1227
+ * @returns one {@link EffectMeta} tree per labeled live effect.
1228
+ */
1229
+ getEffects() {
1230
+ return [...this._disposables].map((dispose) => dispose[symbols.effect]).filter(Boolean);
1231
+ }
1232
+ _getState() {
1233
+ if (this.uid === null) return 4;
1234
+ if (this._error) return 3;
1235
+ if (this._runner.epoch !== INACTIVE) return 2;
1236
+ return 0;
1237
+ }
1238
+ _updateState(callback) {
1239
+ const oldState = this.state;
1240
+ this.state = callback() ?? this._getState();
1241
+ if (oldState === this.state) return;
1242
+ this.context.emit("internal/status", this, oldState);
1243
+ if (oldState !== 2 && this.state !== 2) return;
1244
+ for (const key of Reflect.ownKeys(this.ctx.reflect.store)) {
1245
+ const impl = this.ctx.reflect.store[key];
1246
+ if (impl.fiber !== this) continue;
1247
+ this.ctx.reflect.notify([impl.name]);
1248
+ }
1249
+ }
1250
+ _checkImpl(name) {
1251
+ const impl = this.ctx.reflect._getImpl(name, true);
1252
+ if (!impl) return delete this._store[name];
1253
+ try {
1254
+ if (impl.check && !impl.check.call(getTraceable(this.ctx, impl.value))) return delete this._store[name];
1255
+ } catch (error) {
1256
+ impl.fiber.ctx.logger.error(error);
1257
+ return delete this._store[name];
1258
+ }
1259
+ this._store[name] = impl;
1260
+ }
1261
+ _refresh() {
1262
+ let epoch = false;
1263
+ epoch = "";
1264
+ for (const name of Object.keys(this.inject)) {
1265
+ const impl = this._store[name];
1266
+ if (!impl) {
1267
+ epoch = INACTIVE;
1268
+ break;
1269
+ }
1270
+ epoch += ":" + impl.fiber.uid;
1271
+ }
1272
+ this._setEpoch(epoch);
1273
+ }
1274
+ _setEpoch(epoch) {
1275
+ const oldEpoch = this._runner.epoch;
1276
+ if (epoch === oldEpoch) return;
1277
+ this._runner.epoch = epoch;
1278
+ if (this.inertia) return;
1279
+ this._updateState(() => {
1280
+ if (epoch !== INACTIVE && oldEpoch === INACTIVE) {
1281
+ this.inertia = this._reload();
1282
+ return 1;
1283
+ } else {
1284
+ this.inertia = this._unload();
1285
+ return 5;
1286
+ }
1287
+ });
1288
+ }
1289
+ _resolveConfig(config) {
1290
+ config = this.context.waterfall(this, "internal/config", config, () => config);
1291
+ return this.runtime ? resolveConfig(this.runtime, config) : config;
1292
+ }
1293
+ async _reload() {
1294
+ this.store = { ...this._store };
1295
+ const oldEpoch = this._runner.epoch;
1296
+ try {
1297
+ await Promise.resolve();
1298
+ if (this._runner.epoch === oldEpoch) {
1299
+ this.config = this._resolveConfig(this._config);
1300
+ await this._execute(this._runner);
1301
+ this._error = void 0;
1302
+ }
1303
+ } catch (reason) {
1304
+ this.ctx.logger.error(reason);
1305
+ this._error = reason;
1306
+ this._runner.epoch = INACTIVE;
1307
+ }
1308
+ this._updateState(() => {
1309
+ if (this._runner.epoch === oldEpoch) this.inertia = void 0;
1310
+ else {
1311
+ this.inertia = this._unload();
1312
+ return 5;
1313
+ }
1314
+ });
1315
+ }
1316
+ async _unload() {
1317
+ await Promise.all(this._disposables.clear().map(async (dispose) => {
1318
+ try {
1319
+ await composeError(async (info) => {
1320
+ await Promise.resolve();
1321
+ info.error = /* @__PURE__ */ new Error();
1322
+ await runDisposable(dispose);
1323
+ }, this._runner.getOuterStack);
1324
+ } catch (reason) {
1325
+ this.ctx.logger.error(reason);
1326
+ }
1327
+ }));
1328
+ this.store = void 0;
1329
+ this._updateState(() => {
1330
+ if (this._runner.epoch === INACTIVE) this.inertia = void 0;
1331
+ else {
1332
+ this.inertia = this._reload();
1333
+ return 1;
1334
+ }
1335
+ });
1336
+ }
1337
+ /**
1338
+ * Wait for current lifecycle work and rethrow startup errors.
1339
+ *
1340
+ * @returns this fiber, once it has settled into a stable state.
1341
+ * @throws the config-validation or plugin-startup error, if any.
1342
+ */
1343
+ async await() {
1344
+ while (this.inertia) await this.inertia;
1345
+ if (this._error) throw this._error;
1346
+ return this;
1347
+ }
1348
+ /**
1349
+ * Dispose and immediately reload this plugin with its current config.
1350
+ *
1351
+ * @returns a promise resolving once the reload settled.
1352
+ * @throws {CordisError} `INACTIVE_EFFECT` when the fiber is already disposed.
1353
+ */
1354
+ async restart() {
1355
+ this.assertActive();
1356
+ this._setEpoch(INACTIVE);
1357
+ this._refresh();
1358
+ await this.await();
1359
+ }
1360
+ /**
1361
+ * Validate and apply new config, then restart the plugin.
1362
+ *
1363
+ * Runs the `internal/update` waterfall first, so update hooks (and HMR)
1364
+ * can veto or replace the restart.
1365
+ *
1366
+ * @param config — the new raw config; validated before anything restarts.
1367
+ * @param noSave — hint for persistence hooks not to write the change back.
1368
+ * @returns the update waterfall result; the default restart returns a promise.
1369
+ * @throws when validation, an update listener, or the restarted plugin fails.
1370
+ */
1371
+ update(config, noSave = false) {
1372
+ this.assertActive();
1373
+ this._config = config;
1374
+ if (this.state !== 2) {
1375
+ this._error = void 0;
1376
+ this._setEpoch(INACTIVE);
1377
+ this._refresh();
1378
+ return;
1379
+ }
1380
+ config = this._resolveConfig(config);
1381
+ return this.context.waterfall(this, "internal/update", config, noSave, () => {
1382
+ this.config = config;
1383
+ this._error = void 0;
1384
+ return this.restart();
1385
+ });
1386
+ }
1387
+ };
1388
+ function isApplicable(object) {
1389
+ return object && typeof object === "object" && typeof object.apply === "function";
1390
+ }
1391
+ function Inject(name, config) {
1392
+ return function(value, decorator) {
1393
+ if (decorator.kind === "class") {
1394
+ if (!Object.hasOwn(value, "inject")) {
1395
+ defineProperty(value, "inject", Object.create(Object.getPrototypeOf(value).inject ?? null));
1396
+ defineProperty(value.inject, symbols.checkProto, true);
1397
+ }
1398
+ value.inject[name] = config;
1399
+ } else if (decorator.kind === "method") {
1400
+ const inject = (value[symbols.metadata] ??= {}).inject ??= /* @__PURE__ */ Object.create(null);
1401
+ inject[name] = config;
1402
+ decorator.addInitializer(function() {
1403
+ const property = this[symbols.tracker]?.property;
1404
+ (this[symbols.initHooks] ??= []).push(() => {
1405
+ this.ctx.inject(inject, (ctx) => {
1406
+ return value.call(property ? withProps(this, { [property]: ctx }) : this);
1407
+ });
1408
+ });
1409
+ });
1410
+ } else throw new Error("@Inject() can only be used on class or class methods");
1411
+ };
1412
+ }
1413
+ (function(Inject2) {
1414
+ function resolve(inject, result = /* @__PURE__ */ Object.create(null)) {
1415
+ if (!inject) return result;
1416
+ if (Array.isArray(inject)) for (const name of inject) result[name] = null;
1417
+ else if (Reflect.has(inject, symbols.checkProto)) {
1418
+ Object.assign(result, resolve(Object.getPrototypeOf(inject)));
1419
+ for (const name of Object.keys(inject)) result[name] = inject[name] ?? null;
1420
+ } else for (const name of Object.keys(inject)) result[name] = inject[name] ?? null;
1421
+ return result;
1422
+ }
1423
+ Inject2.resolve = resolve;
1424
+ })(Inject || (Inject = {}));
1425
+ var RegistryService = class {
1426
+ ctx;
1427
+ _counter = 0;
1428
+ _internal = /* @__PURE__ */ new Map();
1429
+ constructor(ctx) {
1430
+ this.ctx = ctx;
1431
+ defineProperty(this, symbols.tracker, {
1432
+ property: "ctx",
1433
+ noShadow: true
1434
+ });
1435
+ }
1436
+ /** Allocate the next fiber uid (increments on every read). */
1437
+ get counter() {
1438
+ return ++this._counter;
1439
+ }
1440
+ /** Number of registered plugin runtimes. */
1441
+ get size() {
1442
+ return this._internal.size;
1443
+ }
1444
+ /**
1445
+ * Resolve a supported plugin shape to its executable callback.
1446
+ *
1447
+ * @param plugin — a function, class, or `{ apply }` object plugin.
1448
+ * @returns the callback identifying the plugin, or `undefined` if invalid.
1449
+ */
1450
+ resolve(plugin) {
1451
+ try {
1452
+ if (typeof plugin === "function") return plugin;
1453
+ if (isApplicable(plugin)) return plugin.apply;
1454
+ } catch {
1455
+ }
1456
+ }
1457
+ /**
1458
+ * Look up the runtime record for a plugin.
1459
+ *
1460
+ * @param plugin — any supported plugin shape.
1461
+ * @returns the runtime, or `undefined` when the plugin is not registered.
1462
+ */
1463
+ get(plugin) {
1464
+ const key = this.resolve(plugin);
1465
+ return key && this._internal.get(key);
1466
+ }
1467
+ /**
1468
+ * Check whether a plugin has a registered runtime.
1469
+ *
1470
+ * @param plugin — any supported plugin shape.
1471
+ * @returns `true` when at least one fiber of the plugin exists.
1472
+ */
1473
+ has(plugin) {
1474
+ const key = this.resolve(plugin);
1475
+ return !!key && this._internal.has(key);
1476
+ }
1477
+ /**
1478
+ * Dispose every running fiber for a plugin and remove its runtime record.
1479
+ *
1480
+ * @param plugin — any supported plugin shape.
1481
+ * @returns the removed runtime, or `undefined` when none was registered.
1482
+ */
1483
+ delete(plugin) {
1484
+ const key = this.resolve(plugin);
1485
+ const runtime = key && this._internal.get(key);
1486
+ if (!runtime) return;
1487
+ this._internal.delete(key);
1488
+ for (const fiber of runtime.fibers) fiber.dispose();
1489
+ return runtime;
1490
+ }
1491
+ /** Iterate the registered plugin callbacks. */
1492
+ keys() {
1493
+ return this._internal.keys();
1494
+ }
1495
+ /** Iterate the registered plugin runtimes. */
1496
+ values() {
1497
+ return this._internal.values();
1498
+ }
1499
+ /** Iterate `[callback, runtime]` pairs. */
1500
+ entries() {
1501
+ return this._internal.entries();
1502
+ }
1503
+ /**
1504
+ * Visit every registered runtime.
1505
+ *
1506
+ * @param callback — receives each runtime and its identifying callback.
1507
+ */
1508
+ forEach(callback) {
1509
+ return this._internal.forEach(callback);
1510
+ }
1511
+ /**
1512
+ * Start a callback once the requested dependencies are available.
1513
+ *
1514
+ * @param inject — required services, as an array or a name → config map.
1515
+ * @param callback — plugin body called with `(ctx, config)`.
1516
+ * @returns the fiber; awaiting it settles once loading finished.
1517
+ */
1518
+ inject(inject, callback) {
1519
+ return this.plugin({
1520
+ inject,
1521
+ apply: callback,
1522
+ name: callback.name
1523
+ });
1524
+ }
1525
+ /**
1526
+ * Start a plugin in the current context and return its fiber.
1527
+ *
1528
+ * Creates (or reuses) the plugin's runtime record, then starts a new fiber
1529
+ * under the current context. Throws if `plugin` is not a supported shape or
1530
+ * if the current fiber is already disposed.
1531
+ *
1532
+ * @param plugin — a function, class, or `{ apply }` object plugin.
1533
+ * @param config — the plugin config, validated against its `Config` schema.
1534
+ * @param getOuterStack — captures the caller stack for effect diagnostics.
1535
+ * @returns the fiber; awaiting it settles once loading finished.
1536
+ */
1537
+ plugin(plugin, config, getOuterStack = buildOuterStack()) {
1538
+ const callback = this.resolve(plugin);
1539
+ if (!callback) throw new Error('invalid plugin, expect function or object with an "apply" method, received ' + typeof plugin);
1540
+ this.ctx.fiber.assertActive();
1541
+ let runtime = this._internal.get(callback);
1542
+ if (!runtime) {
1543
+ let name = plugin.name;
1544
+ if (name === "apply") name = void 0;
1545
+ runtime = {
1546
+ name,
1547
+ callback,
1548
+ fibers: new DisposableList(),
1549
+ Config: plugin.Config
1550
+ };
1551
+ this._internal.set(callback, runtime);
1552
+ }
1553
+ const fiber = new Fiber(this.ctx, config, Inject.resolve(plugin.inject), runtime, getOuterStack);
1554
+ const wrapped = Object.create(fiber);
1555
+ wrapped.then = (onFulfilled, onRejected) => {
1556
+ return fiber.await().then(onFulfilled, onRejected);
1557
+ };
1558
+ return wrapped;
1559
+ }
1560
+ };
1561
+ var Context = class Context2 {
1562
+ /** Symbol key under which a disposer exposes its {@link EffectMeta} diagnostics tree. */
1563
+ static effect = symbols.effect;
1564
+ /** Symbol key for a context's listener filter, consulted on every event dispatch. */
1565
+ static filter = symbols.filter;
1566
+ /** Symbol key of the isolation map (see the `Context[symbols.isolate]` property). */
1567
+ static isolate = symbols.isolate;
1568
+ /** Symbol key of the intercept map (see the `Context[symbols.intercept]` property). */
1569
+ static intercept = symbols.intercept;
1570
+ /**
1571
+ * Returns true for Cordis context proxies and context prototypes.
1572
+ *
1573
+ * Works across realms and across multiple copies of cordis, because the
1574
+ * brand is keyed by a global symbol rather than by `instanceof`.
1575
+ *
1576
+ * @param value — the value to test.
1577
+ * @returns `true` if `value` is a Cordis context, narrowing its type.
1578
+ */
1579
+ static is(value) {
1580
+ return !!value?.[Context2.is];
1581
+ }
1582
+ static {
1583
+ Context2.is[Symbol.toPrimitive] = () => /* @__PURE__ */ Symbol.for("cordis.is");
1584
+ Context2.prototype[Context2.is] = true;
1585
+ }
1586
+ /** Create the root context and install the built-in services. */
1587
+ constructor() {
1588
+ this[symbols.isolate] = /* @__PURE__ */ Object.create(null);
1589
+ this[symbols.intercept] = /* @__PURE__ */ Object.create(null);
1590
+ const self = new Proxy(this, ReflectService.handler);
1591
+ this.root = self;
1592
+ this.baseUrl = void 0;
1593
+ this.fiber = new Fiber(self, {}, /* @__PURE__ */ Object.create(null), null, () => []);
1594
+ this.reflect = new ReflectService(self);
1595
+ this.registry = new RegistryService(self);
1596
+ this.events = new EventsService(self);
1597
+ this.logger = new LoggerService(self);
1598
+ this.fiber._disposables.clear();
1599
+ return self;
1600
+ }
1601
+ [/* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom")]() {
1602
+ return `Context <${this.fiber.name}>`;
1603
+ }
1604
+ /**
1605
+ * Create a child context with extra metadata on top of the current scope.
1606
+ *
1607
+ * The child prototypally inherits every property of this context; own
1608
+ * properties of `meta` shadow the inherited ones. The parent is not mutated.
1609
+ *
1610
+ * @param meta — own properties (including symbol keys) to define on the child.
1611
+ * @returns a child context inheriting from this one.
1612
+ */
1613
+ extend(meta = {}) {
1614
+ const shadow = Reflect.getOwnPropertyDescriptor(this, symbols.shadow)?.value;
1615
+ const self = Object.create(getTraceable(this, this));
1616
+ for (const prop of Reflect.ownKeys(meta)) Object.defineProperty(self, prop, Reflect.getOwnPropertyDescriptor(meta, prop));
1617
+ if (!shadow) return self;
1618
+ return Object.assign(Object.create(self), { [symbols.shadow]: shadow });
1619
+ }
1620
+ /**
1621
+ * Create a child context with an independent service scope for `name`.
1622
+ *
1623
+ * Below the returned context, reads and writes of the service `name`
1624
+ * resolve against the new label instead of the parent's, so a different
1625
+ * implementation can be provided without affecting the parent scope.
1626
+ * Passing the same `label` to two `isolate()` calls joins their scopes.
1627
+ *
1628
+ * @param name — the service name to isolate.
1629
+ * @param label — scope label to join; defaults to a fresh unique symbol.
1630
+ * @returns a child context whose `name` service resolves in the new scope.
1631
+ */
1632
+ isolate(name, label) {
1633
+ const shadow = Object.create(this[symbols.isolate]);
1634
+ shadow[name] = label ?? Symbol(name);
1635
+ return this.extend({ [symbols.isolate]: shadow });
1636
+ }
1637
+ intercept(name, config) {
1638
+ const intercept = Object.create(this[symbols.intercept]);
1639
+ intercept[name] = config;
1640
+ return this.extend({ [symbols.intercept]: intercept });
1641
+ }
1642
+ };
1643
+ var Service = class Service2 {
1644
+ ctx;
1645
+ /** Symbol key of an instance method run after construction (class plugins). */
1646
+ static init = symbols.init;
1647
+ /** Symbol key of the availability predicate passed to `ctx.provide()`. */
1648
+ static check = symbols.check;
1649
+ /** Symbol key of the phantom intercept-config type parameter. */
1650
+ static config = symbols.config;
1651
+ /** Symbol key of the call body making a service callable (e.g. `ctx.logger()`). */
1652
+ static invoke = symbols.invoke;
1653
+ /** Symbol key of the helper deriving an extended service instance. */
1654
+ static extend = symbols.extend;
1655
+ /** Symbol key of the tracker metadata used for context tracing. */
1656
+ static tracker = symbols.tracker;
1657
+ /** Symbol key of the intercept-config resolution helper below. */
1658
+ static resolveConfig = symbols.resolveConfig;
1659
+ /** The service name this instance is registered under. */
1660
+ name;
1661
+ /**
1662
+ * Register this instance as `name` in the current context.
1663
+ *
1664
+ * Calls `ctx.reflect.provide(name, this, this[Service.check])`, so the
1665
+ * service is unregistered automatically when the owning fiber unloads.
1666
+ * Services with a `[Service.invoke]` body return a callable instance.
1667
+ *
1668
+ * @param ctx — the context to register in (stored as `this.ctx`).
1669
+ * @param name — the service name; defaults to the static `provide` field.
1670
+ */
1671
+ constructor(ctx, name) {
1672
+ this.ctx = ctx;
1673
+ name ??= this.constructor["provide"];
1674
+ let self = this;
1675
+ const tracker = {
1676
+ associate: name,
1677
+ property: "ctx"
1678
+ };
1679
+ if (self[symbols.invoke]) self = createCallable(name, joinPrototype(Object.getPrototypeOf(this), Function.prototype), tracker);
1680
+ self.ctx = ctx;
1681
+ self.name = name;
1682
+ defineProperty(self, symbols.tracker, tracker);
1683
+ self.ctx.reflect.provide(name, self, this[symbols.check]);
1684
+ return self;
1685
+ }
1686
+ [symbols.filter](ctx) {
1687
+ return ctx[symbols.isolate][this.name] === this.ctx[symbols.isolate][this.name];
1688
+ }
1689
+ [symbols.extend](props) {
1690
+ let self;
1691
+ if (this[Service2.invoke]) self = createCallable(this.name, this, this[symbols.tracker]);
1692
+ else self = Object.create(this);
1693
+ return Object.assign(self, props);
1694
+ }
1695
+ /**
1696
+ * Merge intercept config from ancestors with optional base and head values.
1697
+ *
1698
+ * Entries added closer to the root apply first; `base` is prepended and
1699
+ * `head` appended. Uses `Config.merge` when the service declares one,
1700
+ * otherwise a shallow `Object.assign`.
1701
+ *
1702
+ * @param base — lowest-precedence config merged before all intercepts.
1703
+ * @param head — highest-precedence config merged after all intercepts.
1704
+ * @returns the merged config.
1705
+ */
1706
+ [symbols.resolveConfig](base, head) {
1707
+ let intercept = this.ctx[Context.intercept];
1708
+ const configs = [];
1709
+ while (this.name in intercept) {
1710
+ if (Object.hasOwn(intercept, this.name)) configs.unshift(intercept[this.name]);
1711
+ intercept = Object.getPrototypeOf(intercept);
1712
+ }
1713
+ if (base) configs.unshift(base);
1714
+ if (head) configs.push(head);
1715
+ if (this["Config"]?.merge) return this["Config"].merge(...configs);
1716
+ else return Object.assign({}, ...configs);
1717
+ }
1718
+ static [Symbol.hasInstance](instance) {
1719
+ if (!instance) return false;
1720
+ let constructor = instance.constructor;
1721
+ while (constructor) {
1722
+ constructor = constructor.prototype?.constructor;
1723
+ if (constructor === this) return true;
1724
+ constructor &&= Object.getPrototypeOf(constructor);
1725
+ }
1726
+ return false;
1727
+ }
1728
+ };
1729
+
1730
+ // node_modules/.pnpm/@deepseek-ai+dsh-settings@0_2dd31f709f91e7b96c62a2afe9d4c22c/node_modules/@deepseek-ai/dsh-settings/lib/index.js
1731
+ function isRecord(value) {
1732
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1733
+ }
1734
+ function walk(node, value, path, secrets) {
1735
+ if (node === void 0) return value;
1736
+ if (node.meta?.role === "secret") {
1737
+ secrets.push({
1738
+ path,
1739
+ set: value !== void 0
1740
+ });
1741
+ return;
1742
+ }
1743
+ switch (node.type) {
1744
+ case "object": {
1745
+ const properties = node.dict ?? {};
1746
+ const source = isRecord(value) ? value : void 0;
1747
+ const rebuilt = {};
1748
+ if (source !== void 0) for (const [key, entry] of Object.entries(source)) {
1749
+ if (key in properties) continue;
1750
+ rebuilt[key] = entry;
1751
+ }
1752
+ for (const [key, child] of Object.entries(properties)) {
1753
+ const stripped = walk(child, source?.[key], [...path, key], secrets);
1754
+ if (stripped !== void 0) rebuilt[key] = stripped;
1755
+ }
1756
+ return source === void 0 && Object.keys(rebuilt).length === 0 ? value : rebuilt;
1757
+ }
1758
+ case "dict": {
1759
+ if (!isRecord(value)) return value;
1760
+ const rebuilt = {};
1761
+ for (const [key, entry] of Object.entries(value)) {
1762
+ const stripped = walk(node.inner, entry, [...path, key], secrets);
1763
+ if (stripped !== void 0) rebuilt[key] = stripped;
1764
+ }
1765
+ return rebuilt;
1766
+ }
1767
+ case "array":
1768
+ if (!Array.isArray(value)) return value;
1769
+ return value.map((entry, index) => walk(node.inner, entry, [...path, String(index)], secrets));
1770
+ default:
1771
+ return value;
1772
+ }
1773
+ }
1774
+ function redactSecrets(schema, value) {
1775
+ const secrets = [];
1776
+ return {
1777
+ value: walk(schema, value, [], secrets),
1778
+ secrets
1779
+ };
1780
+ }
1781
+ var NAMESPACE_PATTERN = /^[a-z][a-z0-9-]*$/;
1782
+ function settingsNamespace(value) {
1783
+ if (!NAMESPACE_PATTERN.test(value)) throw new TypeError(`settings namespace "${value}" must match ${String(NAMESPACE_PATTERN)}`);
1784
+ return value;
1785
+ }
1786
+ function deepEqualJson(a, b) {
1787
+ if (a === b) return true;
1788
+ if (typeof a !== "object" || typeof b !== "object" || a === null || b === null) return false;
1789
+ if (Array.isArray(a) || Array.isArray(b)) {
1790
+ if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) return false;
1791
+ return a.every((entry, index) => deepEqualJson(entry, b[index]));
1792
+ }
1793
+ const left = a;
1794
+ const right = b;
1795
+ const keys = Object.keys(left);
1796
+ if (keys.length !== Object.keys(right).length) return false;
1797
+ return keys.every((key) => key in right && deepEqualJson(left[key], right[key]));
1798
+ }
1799
+ var SettingsConflictError = class extends Error {
1800
+ /** Stable machine code for wire layers mapping this to their own taxonomy. */
1801
+ code = "SETTINGS_CONFLICT";
1802
+ /** The revision the write expected. */
1803
+ expected;
1804
+ /** The revision the namespace actually stands at. */
1805
+ actual;
1806
+ /**
1807
+ * @param ns - the namespace whose write was refused.
1808
+ * @param expected - the revision the caller sent.
1809
+ * @param actual - the revision now stored.
1810
+ */
1811
+ constructor(ns, expected, actual) {
1812
+ super(`settings namespace "${ns}" changed since it was read (expected revision ${String(expected)}, now ${String(actual)})`);
1813
+ this.name = "SettingsConflictError";
1814
+ this.expected = expected;
1815
+ this.actual = actual;
1816
+ }
1817
+ };
1818
+ function isPlainObject(value) {
1819
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
1820
+ const proto = Object.getPrototypeOf(value);
1821
+ return proto === Object.prototype || proto === null;
1822
+ }
1823
+ function applyPathOp(section, op) {
1824
+ const [head, ...rest] = op.path;
1825
+ if (head === void 0) {
1826
+ if (op.op === "unset") return {};
1827
+ if (!isPlainObject(op.value)) throw new TypeError("settings mutate: setting the section root requires a plain object");
1828
+ return { ...op.value };
1829
+ }
1830
+ if (rest.length === 0) {
1831
+ if (op.op === "set") return {
1832
+ ...section,
1833
+ [head]: op.value
1834
+ };
1835
+ const { [head]: _removed, ...kept } = section;
1836
+ return kept;
1837
+ }
1838
+ const child = section[head];
1839
+ if (!isPlainObject(child)) {
1840
+ if (op.op === "unset") return section;
1841
+ return {
1842
+ ...section,
1843
+ [head]: applyPathOp({}, {
1844
+ ...op,
1845
+ path: rest
1846
+ })
1847
+ };
1848
+ }
1849
+ return {
1850
+ ...section,
1851
+ [head]: applyPathOp(child, {
1852
+ ...op,
1853
+ path: rest
1854
+ })
1855
+ };
1856
+ }
1857
+ function describeRejected(value) {
1858
+ if (value === void 0) return "undefined";
1859
+ if (typeof value === "object" && value !== null) {
1860
+ const name = Object.getPrototypeOf(value)?.constructor?.name;
1861
+ return name === void 0 || name === "Object" ? "a non-plain object" : `a ${name}`;
1862
+ }
1863
+ return `a ${typeof value}`;
1864
+ }
1865
+ function cloneJsonShaped(root, reject) {
1866
+ const visiting = /* @__PURE__ */ new WeakSet();
1867
+ const clone = (value, path) => {
1868
+ if (value === null || typeof value === "string" || typeof value === "boolean") return value;
1869
+ if (typeof value === "number") {
1870
+ if (!Number.isFinite(value)) throw reject("a non-finite number", path);
1871
+ return value;
1872
+ }
1873
+ if (Array.isArray(value)) {
1874
+ if (visiting.has(value)) throw reject("a circular reference", path);
1875
+ visiting.add(value);
1876
+ const entries = value.map((entry, index) => clone(entry, `${path}[${index}]`));
1877
+ visiting.delete(value);
1878
+ return entries;
1879
+ }
1880
+ if (isPlainObject(value)) {
1881
+ if (visiting.has(value)) throw reject("a circular reference", path);
1882
+ visiting.add(value);
1883
+ const out = {};
1884
+ for (const [key, entry] of Object.entries(value)) {
1885
+ if (entry === void 0) continue;
1886
+ out[key] = clone(entry, `${path}.${key}`);
1887
+ }
1888
+ visiting.delete(value);
1889
+ return out;
1890
+ }
1891
+ throw reject(describeRejected(value), path);
1892
+ };
1893
+ return clone(root, "$");
1894
+ }
1895
+ function mergeLayers(under, over) {
1896
+ if (over === void 0) return under;
1897
+ if (!isPlainObject(under) || !isPlainObject(over)) return over;
1898
+ const merged = { ...under };
1899
+ for (const [key, value] of Object.entries(over)) merged[key] = key in merged ? mergeLayers(merged[key], value) : value;
1900
+ return merged;
1901
+ }
1902
+ function deepFreeze(value) {
1903
+ if (typeof value !== "object" || value === null || Object.isFrozen(value)) return value;
1904
+ for (const entry of Object.values(value)) deepFreeze(entry);
1905
+ return Object.freeze(value);
1906
+ }
1907
+ var SettingsProvider = class extends Service {
1908
+ registrations = /* @__PURE__ */ new Map();
1909
+ /** Latest published raw document; empty until the provider's first publish. */
1910
+ document = {};
1911
+ /** Per-namespace write chains; settled tails, so a failure never poisons the queue. */
1912
+ writeQueues = /* @__PURE__ */ new Map();
1913
+ /** In-flight watcher invocation segments, drained by the dispose teardown. */
1914
+ pendingTails = /* @__PURE__ */ new Set();
1915
+ /** Set at service dispose: refuse new writes while queued ones drain. */
1916
+ stopped = false;
1917
+ /** Opaque read of {@link stopped}: control flow cannot narrow it across awaits. */
1918
+ isStopped() {
1919
+ return this.stopped;
1920
+ }
1921
+ constructor(ctx) {
1922
+ super(ctx, "settings");
1923
+ }
1924
+ /**
1925
+ * Load the provider's document once and publish it before the service
1926
+ * becomes injectable, and register the write-drain teardown. Providers with
1927
+ * their own init (watchers, connections) delegate here first via
1928
+ * `yield* super[Service.init]()`; their disposers then run before the drain.
1929
+ */
1930
+ async *[Service.init]() {
1931
+ yield async () => {
1932
+ this.stopped = true;
1933
+ await Promise.allSettled([...this.writeQueues.values(), ...this.pendingTails]);
1934
+ };
1935
+ this.publish(await this.load());
1936
+ }
1937
+ /**
1938
+ * Absolute path of the provider's user-editable document, when its storage
1939
+ * is one local file. Configuration surfaces use this only as availability
1940
+ * metadata; the guarded open operation resolves the path again Host-side.
1941
+ * Non-file providers leave it undefined and expose no open-document affordance.
1942
+ * @returns the absolute local document path, or undefined for non-file storage.
1943
+ */
1944
+ get documentPath() {
1945
+ }
1946
+ /**
1947
+ * Prepare the provider's user-editable document for a native editor. File
1948
+ * providers may materialize an absent document before returning its path;
1949
+ * non-file providers return undefined.
1950
+ * @returns the absolute local document path, or undefined for non-file storage.
1951
+ */
1952
+ prepareDocument() {
1953
+ return Promise.resolve(this.documentPath);
1954
+ }
1955
+ /**
1956
+ * Register a namespace schema and receive its owner scope. The registration
1957
+ * is an effect on the calling plugin's fiber: disposing that fiber removes
1958
+ * the namespace and its observers. An invalid stored section fails the
1959
+ * registration itself — the earliest point where the schema can judge it.
1960
+ * @param ns - unique namespace; duplicate registration fails loud.
1961
+ * @param schema - schemastery schema resolving this namespace's value.
1962
+ * @param options - composition `base` layer and effect timing.
1963
+ * @returns the owner scope for reads, observation, and updates.
1964
+ */
1965
+ register(ns, schema, options) {
1966
+ if (this.registrations.has(ns)) throw new Error(`settings namespace "${ns}" is already registered`);
1967
+ const registration = {
1968
+ ns,
1969
+ schema,
1970
+ base: options?.base,
1971
+ applies: options?.applies ?? "live",
1972
+ ...options?.validate === void 0 ? {} : { validate: options.validate },
1973
+ resolved: deepFreeze(this.resolve(schema, options?.base, this.section(ns), options?.validate)),
1974
+ revision: 0,
1975
+ watchers: /* @__PURE__ */ new Set()
1976
+ };
1977
+ this.ctx.effect(() => {
1978
+ this.registrations.set(ns, registration);
1979
+ return () => this.registrations.delete(ns);
1980
+ }, `settings.register(${JSON.stringify(String(ns))})`);
1981
+ return {
1982
+ get: () => registration.resolved,
1983
+ watch: (callback) => {
1984
+ const watcher = {
1985
+ callback,
1986
+ tail: Promise.resolve(),
1987
+ active: true
1988
+ };
1989
+ registration.watchers.add(watcher);
1990
+ return () => {
1991
+ watcher.active = false;
1992
+ registration.watchers.delete(watcher);
1993
+ };
1994
+ },
1995
+ update: (patch) => this.update(ns, patch),
1996
+ replace: (section) => this.replace(ns, section)
1997
+ };
1998
+ }
1999
+ /**
2000
+ * Describe every registered namespace for configuration surfaces, including
2001
+ * the composition `base` and raw user layers so a form can mark which fields
2002
+ * the user overrode (presence in `user`) and what a reset returns to.
2003
+ * @param options - redaction switch; wire surfaces must redact.
2004
+ * @returns one descriptor per registered namespace, in registration order.
2005
+ */
2006
+ describe(options) {
2007
+ return [...this.registrations.values()].map((registration) => {
2008
+ let user;
2009
+ try {
2010
+ user = this.section(registration.ns);
2011
+ } catch {
2012
+ user = void 0;
2013
+ }
2014
+ const base = registration.base === void 0 ? void 0 : structuredClone(registration.base);
2015
+ const detachedUser = user === void 0 ? void 0 : structuredClone(user);
2016
+ const descriptor = {
2017
+ ns: registration.ns,
2018
+ schema: registration.schema.toJSON(),
2019
+ value: registration.resolved,
2020
+ revision: registration.revision,
2021
+ ...base === void 0 ? {} : { base },
2022
+ ...detachedUser === void 0 ? {} : { user: detachedUser },
2023
+ applies: registration.applies
2024
+ };
2025
+ if (options?.redactSecrets !== true) return descriptor;
2026
+ const schema = registration.schema;
2027
+ const redacted = redactSecrets(schema, registration.resolved);
2028
+ return {
2029
+ ...descriptor,
2030
+ value: redacted.value,
2031
+ ...base === void 0 ? {} : { base: redactSecrets(schema, base).value },
2032
+ ...detachedUser === void 0 ? {} : { user: redactSecrets(schema, detachedUser).value },
2033
+ secrets: redacted.secrets
2034
+ };
2035
+ });
2036
+ }
2037
+ /**
2038
+ * Read one registered namespace's resolved value.
2039
+ * @param ns - the namespace to read.
2040
+ * @returns the resolved value, or `undefined` while unregistered.
2041
+ */
2042
+ get(ns) {
2043
+ return this.registrations.get(ns)?.resolved;
2044
+ }
2045
+ /**
2046
+ * Merge a patch into one registered namespace's user layer, validate the
2047
+ * resolved candidate, persist through the provider, then commit and emit.
2048
+ * A validation failure rejects before anything is persisted. Writes to one
2049
+ * namespace are serialized: concurrent updates apply in call order, each
2050
+ * merging over the previous write's committed section.
2051
+ * @param ns - the registered namespace to update.
2052
+ * @param patch - plain-object patch over the user section.
2053
+ * @param expectedRevision - the descriptor `revision` the caller read; a
2054
+ * namespace that moved past it rejects with {@link SettingsConflictError}.
2055
+ */
2056
+ async update(ns, patch, expectedRevision) {
2057
+ return this.write(ns, patch, "merge", expectedRevision);
2058
+ }
2059
+ /**
2060
+ * Replace one registered namespace's user section wholesale, validate,
2061
+ * persist, then commit and emit. Keys absent from `section` fall back to the
2062
+ * composition `base` and schema defaults — this is the removal/reset path a
2063
+ * merge-only patch cannot express (`replace({})` re-inherits everything).
2064
+ * @param ns - the registered namespace to replace.
2065
+ * @param section - the complete next user section.
2066
+ * @param expectedRevision - the descriptor `revision` the caller read; a
2067
+ * namespace that moved past it rejects with {@link SettingsConflictError}.
2068
+ */
2069
+ async replace(ns, section, expectedRevision) {
2070
+ return this.write(ns, section, "replace", expectedRevision);
2071
+ }
2072
+ /**
2073
+ * Apply path-addressed edits to one registered namespace's user section,
2074
+ * validate, persist, then commit and emit. The ops are applied to the
2075
+ * section as it stands when the write reaches the front of the queue, so a
2076
+ * caller never has to restate fields it did not touch — and, crucially,
2077
+ * cannot delete fields it never saw. This is the write path for any caller
2078
+ * holding a redacted view; `replace` remains the wholesale reset.
2079
+ * @param ns - the registered namespace to edit.
2080
+ * @param ops - ordered path edits; later ops observe earlier ones.
2081
+ * @param expectedRevision - the descriptor `revision` the caller read; a
2082
+ * namespace that moved past it rejects with {@link SettingsConflictError}.
2083
+ */
2084
+ async mutate(ns, ops, expectedRevision) {
2085
+ if (!Array.isArray(ops)) throw new TypeError(`settings mutate for "${ns}" must be an array of path ops`);
2086
+ for (const op of ops) {
2087
+ if (!isPlainObject(op) || op["op"] !== "set" && op["op"] !== "unset") throw new TypeError(`settings mutate for "${ns}" ops must be {op:'set'|'unset', path}`);
2088
+ if (!Array.isArray(op["path"]) || op["path"].some((part) => typeof part !== "string")) throw new TypeError(`settings mutate for "${ns}" op paths must be arrays of strings`);
2089
+ }
2090
+ return this.write(ns, ops, "mutate", expectedRevision);
2091
+ }
2092
+ /** Validate a write, then queue it on the namespace's serialized write chain. */
2093
+ write(ns, input, mode, expectedRevision) {
2094
+ const verb = mode === "merge" ? "update" : mode === "replace" ? "replace" : "mutate";
2095
+ const registration = this.registrations.get(ns);
2096
+ if (registration === void 0) throw new Error(`settings namespace "${ns}" is not registered`);
2097
+ if (this.isStopped()) throw new Error(`settings service is disposed: "${ns}" cannot be written`);
2098
+ if (!this.writable) throw new Error(`settings provider is read-only: "${ns}" cannot be updated in-process`);
2099
+ let payload;
2100
+ if (mode === "mutate") payload = { ops: input };
2101
+ else {
2102
+ if (!isPlainObject(input)) throw new TypeError(`settings ${verb} for "${ns}" must be a plain object`);
2103
+ payload = input;
2104
+ }
2105
+ const snapshot = cloneJsonShaped(payload, (label, path) => /* @__PURE__ */ new TypeError(`settings ${verb} for "${ns}" must contain only JSON-compatible data (found ${label} at ${path})`));
2106
+ const run = (this.writeQueues.get(ns) ?? Promise.resolve()).catch(() => void 0).then(async () => {
2107
+ if (this.isStopped()) throw new Error(`settings service was disposed before the queued "${ns}" ${verb} ran`);
2108
+ if (this.registrations.get(ns) !== registration) throw new Error(`settings namespace "${ns}" registration was disposed before the queued ${verb} ran`);
2109
+ const current = this.section(ns) ?? {};
2110
+ if (expectedRevision !== void 0 && expectedRevision !== registration.revision) throw new SettingsConflictError(ns, expectedRevision, registration.revision);
2111
+ const section = mode === "merge" ? mergeLayers(current, snapshot) : mode === "replace" ? snapshot : snapshot["ops"].reduce(applyPathOp, current);
2112
+ const next = deepFreeze(this.resolve(registration.schema, registration.base, section, registration.validate));
2113
+ await this.persist(ns, section);
2114
+ this.document[ns] = section;
2115
+ if (this.registrations.get(ns) === registration && !this.isStopped()) {
2116
+ this.bumpRevision(registration, current, section);
2117
+ this.commit(registration, next, "update");
2118
+ }
2119
+ });
2120
+ this.writeQueues.set(ns, run);
2121
+ return run;
2122
+ }
2123
+ /**
2124
+ * Provider hook: commit a complete raw document observed in storage. Each
2125
+ * registered namespace re-resolves; an invalid section keeps that
2126
+ * namespace's last good value and warns, other namespaces still commit.
2127
+ * @param doc - the detached raw document (unregistered sections preserved).
2128
+ * @param source - change origin; defaults to `provider`.
2129
+ */
2130
+ publish(doc, source = "provider") {
2131
+ const before = /* @__PURE__ */ new Map();
2132
+ for (const registration of this.registrations.values()) try {
2133
+ before.set(registration.ns, this.section(registration.ns));
2134
+ } catch {
2135
+ before.set(registration.ns, void 0);
2136
+ }
2137
+ this.document = doc;
2138
+ for (const registration of this.registrations.values()) {
2139
+ let next;
2140
+ try {
2141
+ next = deepFreeze(this.resolve(registration.schema, registration.base, this.section(registration.ns), registration.validate));
2142
+ } catch (error) {
2143
+ this.ctx.logger.warn('settings: keeping last good "%s" after invalid stored section', registration.ns);
2144
+ this.ctx.logger.warn(error);
2145
+ continue;
2146
+ }
2147
+ this.bumpRevision(registration, before.get(registration.ns), this.section(registration.ns));
2148
+ this.commit(registration, next, source);
2149
+ }
2150
+ }
2151
+ /** Read one namespace's raw user section, rejecting non-object sections. */
2152
+ section(ns) {
2153
+ const section = this.document[ns];
2154
+ if (section === void 0) return void 0;
2155
+ if (!isPlainObject(section)) throw new TypeError(`settings section "${ns}" must be an object of keys`);
2156
+ return section;
2157
+ }
2158
+ /** Resolve one namespace value: schema defaults, then `base`, then the user layer. */
2159
+ resolve(schema, base, section, validate) {
2160
+ const value = schema(mergeLayers(base, section));
2161
+ validate?.(value);
2162
+ return value;
2163
+ }
2164
+ /**
2165
+ * Advance a namespace's revision when its RAW section changed, and announce
2166
+ * it. Deliberately independent of {@link commit}'s resolved-value equality:
2167
+ * storing an override equal to the composition base leaves the resolved
2168
+ * value alone but changes what the document says, which is exactly what a
2169
+ * configuration surface must re-read.
2170
+ */
2171
+ bumpRevision(registration, before, after) {
2172
+ if (deepEqualJson(before, after)) return;
2173
+ registration.revision += 1;
2174
+ this.emitDocumentUpdated(registration.ns, registration.revision);
2175
+ }
2176
+ /** Contained fan-out of `settings/document-updated`, mirroring {@link commit}'s. */
2177
+ emitDocumentUpdated(ns, revision) {
2178
+ let invariantFailure;
2179
+ const args = [
2180
+ "settings/document-updated",
2181
+ ns,
2182
+ revision
2183
+ ];
2184
+ for (const listener of this.ctx.events.dispatch("emit", args)) try {
2185
+ const returned = listener(ns, revision);
2186
+ if (returned != null && typeof returned.then === "function") Promise.resolve(returned).then(void 0, (error) => {
2187
+ this.warnListenerFailure(ns, error);
2188
+ });
2189
+ } catch (error) {
2190
+ if (error?.code === "INVARIANT") {
2191
+ invariantFailure ??= error;
2192
+ continue;
2193
+ }
2194
+ this.warnListenerFailure(ns, error);
2195
+ }
2196
+ if (invariantFailure !== void 0) throw invariantFailure;
2197
+ }
2198
+ /** Commit a resolved value when changed: swap, notify watchers, emit the event. */
2199
+ commit(registration, next, source) {
2200
+ const prev = registration.resolved;
2201
+ if (deepEqualJson(next, prev)) return;
2202
+ registration.resolved = next;
2203
+ for (const watcher of [...registration.watchers]) {
2204
+ const segment = watcher.tail.then(() => {
2205
+ if (!watcher.active || this.isStopped()) return;
2206
+ return watcher.callback(next, prev);
2207
+ }).then(() => void 0, (error) => {
2208
+ this.warnWatcherFailure(registration.ns, error);
2209
+ });
2210
+ watcher.tail = segment;
2211
+ this.pendingTails.add(segment);
2212
+ segment.then(() => this.pendingTails.delete(segment));
2213
+ }
2214
+ let invariantFailure;
2215
+ const args = [
2216
+ "settings/updated",
2217
+ registration.ns,
2218
+ next,
2219
+ prev,
2220
+ source
2221
+ ];
2222
+ for (const listener of this.ctx.events.dispatch("emit", args)) try {
2223
+ const returned = listener(registration.ns, next, prev, source);
2224
+ if (returned != null && typeof returned.then === "function") Promise.resolve(returned).then(void 0, (error) => {
2225
+ this.warnListenerFailure(registration.ns, error);
2226
+ });
2227
+ } catch (error) {
2228
+ if (error?.code === "INVARIANT") {
2229
+ invariantFailure ??= error;
2230
+ continue;
2231
+ }
2232
+ this.warnListenerFailure(registration.ns, error);
2233
+ }
2234
+ if (invariantFailure !== void 0) throw invariantFailure;
2235
+ }
2236
+ /** Contained-watcher diagnostic shared by the sync and async failure paths. */
2237
+ warnWatcherFailure(ns, error) {
2238
+ this.ctx.logger.warn('settings: watcher for "%s" failed', ns);
2239
+ this.ctx.logger.warn(error);
2240
+ }
2241
+ /** Contained-listener diagnostic shared by the sync and async failure paths. */
2242
+ warnListenerFailure(ns, error) {
2243
+ this.ctx.logger.warn('settings: a settings/updated listener for "%s" failed', ns);
2244
+ this.ctx.logger.warn(error);
2245
+ }
2246
+ };
2247
+ var FIBER_DISPOSED = 4;
2248
+ var FIBER_UNLOADING = 5;
2249
+ function isUnloading(ctx) {
2250
+ const state = ctx.fiber.state;
2251
+ return state === FIBER_UNLOADING || state === FIBER_DISPOSED;
2252
+ }
2253
+ function installSettingsSection(ctx, ns, schema, entry, hooks) {
2254
+ ctx.inject(["settings"], (sctx) => {
2255
+ const scope = sctx.settings.register(ns, schema, {
2256
+ base: entry,
2257
+ ...hooks.validate === void 0 ? {} : { validate: hooks.validate }
2258
+ });
2259
+ hooks.setSource(() => scope.get());
2260
+ sctx.effect(() => () => {
2261
+ if (isUnloading(ctx)) return;
2262
+ hooks.setSource(() => entry);
2263
+ hooks.onChange();
2264
+ });
2265
+ hooks.onChange();
2266
+ scope.watch(() => {
2267
+ if (isUnloading(ctx)) return;
2268
+ hooks.onChange();
2269
+ });
2270
+ });
2271
+ }
2272
+ export {
2273
+ SettingsConflictError,
2274
+ SettingsProvider,
2275
+ deepEqualJson,
2276
+ SettingsProvider as default,
2277
+ installSettingsSection,
2278
+ redactSecrets,
2279
+ settingsNamespace
2280
+ };
2281
+ //# sourceMappingURL=lib-FJP7J4T6.js.map