@dougongjs/core 0.4.0 → 0.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.
- package/dist/change-set.d.ts +6 -0
- package/dist/change-set.d.ts.map +1 -1
- package/dist/configuration.d.ts +12 -1
- package/dist/configuration.d.ts.map +1 -1
- package/dist/contract-registry.d.ts +2 -2
- package/dist/contract-registry.d.ts.map +1 -1
- package/dist/contracts.d.ts +27 -0
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contribution-store.d.ts +20 -1
- package/dist/contribution-store.d.ts.map +1 -1
- package/dist/diagnostics.d.ts +21 -3
- package/dist/diagnostics.d.ts.map +1 -1
- package/dist/engine.d.ts +28 -1
- package/dist/engine.d.ts.map +1 -1
- package/dist/errors.d.ts +44 -7
- package/dist/errors.d.ts.map +1 -1
- package/dist/event-hub.d.ts +12 -1
- package/dist/event-hub.d.ts.map +1 -1
- package/dist/group-configuration.d.ts +20 -0
- package/dist/group-configuration.d.ts.map +1 -0
- package/dist/group-coordinator.d.ts +20 -2
- package/dist/group-coordinator.d.ts.map +1 -1
- package/dist/group-lifecycle.d.ts +13 -0
- package/dist/group-lifecycle.d.ts.map +1 -1
- package/dist/group.d.ts +5 -11
- package/dist/group.d.ts.map +1 -1
- package/dist/host-api.d.ts +33 -0
- package/dist/host-api.d.ts.map +1 -1
- package/dist/host.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +905 -590
- package/dist/installation-graph.d.ts +8 -1
- package/dist/installation-graph.d.ts.map +1 -1
- package/dist/installation-registry.d.ts +6 -0
- package/dist/installation-registry.d.ts.map +1 -1
- package/dist/installation.d.ts +21 -3
- package/dist/installation.d.ts.map +1 -1
- package/dist/instance-coordinator.d.ts +32 -3
- package/dist/instance-coordinator.d.ts.map +1 -1
- package/dist/lifecycle-status.d.ts.map +1 -1
- package/dist/lifetime-diagnostics.d.ts +7 -1
- package/dist/lifetime-diagnostics.d.ts.map +1 -1
- package/dist/lifetime.d.ts +37 -1
- package/dist/lifetime.d.ts.map +1 -1
- package/dist/plugin.d.ts +28 -2
- package/dist/plugin.d.ts.map +1 -1
- package/dist/readonly-map.d.ts +8 -1
- package/dist/readonly-map.d.ts.map +1 -1
- package/dist/record.d.ts +16 -1
- package/dist/record.d.ts.map +1 -1
- package/dist/resource.d.ts +6 -0
- package/dist/resource.d.ts.map +1 -1
- package/dist/serial-queue.d.ts +7 -1
- package/dist/serial-queue.d.ts.map +1 -1
- package/dist/snapshot-view.d.ts +2 -0
- package/dist/snapshot-view.d.ts.map +1 -1
- package/dist/sync-result.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,42 +1,42 @@
|
|
|
1
|
-
function
|
|
1
|
+
function Ot(r, t) {
|
|
2
2
|
if (typeof t != "string" || !t.trim())
|
|
3
3
|
throw new TypeError(`${r} id must be a non-empty string`);
|
|
4
4
|
if (t !== t.trim())
|
|
5
5
|
throw new TypeError(`${r} id cannot start or end with whitespace`);
|
|
6
6
|
}
|
|
7
|
-
function
|
|
8
|
-
return
|
|
7
|
+
function Q(r, t) {
|
|
8
|
+
return Ot("Contract", t), Object.freeze({ id: t, kind: r });
|
|
9
9
|
}
|
|
10
|
-
function
|
|
10
|
+
function E(r, t) {
|
|
11
11
|
if (!r || typeof r != "object") return !1;
|
|
12
12
|
const e = r;
|
|
13
13
|
return typeof e.id == "string" && e.id.length > 0 && e.id === e.id.trim() && (e.kind === "service" || e.kind === "extensionPoint" || e.kind === "event") && (t === void 0 || e.kind === t);
|
|
14
14
|
}
|
|
15
|
-
function
|
|
16
|
-
if (!
|
|
17
|
-
throw new TypeError(t ? `Expected ${
|
|
15
|
+
function A(r, t) {
|
|
16
|
+
if (!E(r, t))
|
|
17
|
+
throw new TypeError(t ? `Expected ${At(t)}` : "Invalid contract");
|
|
18
18
|
}
|
|
19
|
-
function
|
|
19
|
+
function At(r) {
|
|
20
20
|
return r === "extensionPoint" ? "an ExtensionPoint" : r === "event" ? "an Event" : "a Service";
|
|
21
21
|
}
|
|
22
|
-
function
|
|
23
|
-
return
|
|
22
|
+
function It(r) {
|
|
23
|
+
return Q("service", r);
|
|
24
24
|
}
|
|
25
|
-
function
|
|
26
|
-
return
|
|
25
|
+
function Le(r) {
|
|
26
|
+
return Q("event", r);
|
|
27
27
|
}
|
|
28
|
-
function
|
|
29
|
-
return
|
|
28
|
+
function ze(r) {
|
|
29
|
+
return Q("extensionPoint", r);
|
|
30
30
|
}
|
|
31
|
-
function
|
|
32
|
-
if (!
|
|
31
|
+
function Re(r) {
|
|
32
|
+
if (!E(r, "service"))
|
|
33
33
|
throw new TypeError("optional() expects a Service");
|
|
34
|
-
return Object.freeze({ kind: "optional", service: r });
|
|
34
|
+
return Object.freeze({ kind: "optional", service: It(r.id) });
|
|
35
35
|
}
|
|
36
|
-
function
|
|
36
|
+
function jt(r) {
|
|
37
37
|
if (!r || typeof r != "object") return !1;
|
|
38
38
|
const t = r;
|
|
39
|
-
return t.kind === "optional" &&
|
|
39
|
+
return t.kind === "optional" && E(t.service, "service");
|
|
40
40
|
}
|
|
41
41
|
class u extends Error {
|
|
42
42
|
name = "DougongError";
|
|
@@ -48,62 +48,89 @@ class u extends Error {
|
|
|
48
48
|
super(e, i), this.code = t;
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
|
-
class
|
|
52
|
-
|
|
51
|
+
class J extends Error {
|
|
52
|
+
name = "RecordedFailure";
|
|
53
|
+
code;
|
|
54
|
+
snapshot;
|
|
53
55
|
constructor(t) {
|
|
54
|
-
if (!(t instanceof Error)) throw new TypeError("
|
|
55
|
-
const e =
|
|
56
|
-
this
|
|
57
|
-
s === void 0 ? {
|
|
58
|
-
category: t instanceof TypeError ? "typeError" : "error",
|
|
59
|
-
name: e,
|
|
60
|
-
message: i
|
|
61
|
-
} : {
|
|
62
|
-
category: "coded",
|
|
63
|
-
name: e,
|
|
64
|
-
message: i,
|
|
65
|
-
code: s
|
|
66
|
-
}
|
|
67
|
-
), Object.freeze(this);
|
|
68
|
-
}
|
|
69
|
-
restore(t = (e, i) => new u(e, i)) {
|
|
70
|
-
const e = this.#t, i = e.category === "coded" ? t(e.code, e.message) : e.category === "typeError" ? new TypeError(e.message) : new Error(e.message);
|
|
71
|
-
if (!(i instanceof Error))
|
|
72
|
-
throw new TypeError("ErrorSummary coded error factory must return an Error");
|
|
73
|
-
return i.name = e.name, i;
|
|
56
|
+
if (!(t instanceof Error)) throw new TypeError("RecordedFailure expects an Error");
|
|
57
|
+
const e = t instanceof J ? t.snapshot : kt(t);
|
|
58
|
+
super(e.message), this.code = e.code, this.snapshot = e, e.stack !== void 0 && (this.stack = e.stack), Object.freeze(this);
|
|
74
59
|
}
|
|
75
60
|
}
|
|
76
|
-
function
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
61
|
+
function kt(r) {
|
|
62
|
+
const t = /* @__PURE__ */ new Set();
|
|
63
|
+
let e = 32;
|
|
64
|
+
const i = (s, n) => {
|
|
65
|
+
if (n > 4 || e-- <= 0 || t.has(s))
|
|
66
|
+
return Object.freeze({
|
|
67
|
+
name: "TruncatedError",
|
|
68
|
+
message: "Error chain truncated",
|
|
69
|
+
truncated: !0
|
|
70
|
+
});
|
|
71
|
+
if (!(s instanceof Error)) {
|
|
72
|
+
const p = s === null || ["string", "number", "boolean", "undefined", "bigint", "symbol"].includes(typeof s) ? String(s).slice(0, 4096) : "Non-Error object omitted";
|
|
73
|
+
return Object.freeze({ name: "NonError", message: p });
|
|
74
|
+
}
|
|
75
|
+
t.add(s);
|
|
76
|
+
let o = !1;
|
|
77
|
+
const a = (p, w) => (p.length > w && (o = !0), p.slice(0, w)), h = (p, w) => {
|
|
78
|
+
const b = m(s, p);
|
|
79
|
+
return typeof b == "string" ? a(b, w) : void 0;
|
|
80
|
+
}, c = (p) => {
|
|
81
|
+
const w = m(s, p);
|
|
82
|
+
if (Array.isArray(w))
|
|
83
|
+
return w.length > 8 && (o = !0), Array.from(
|
|
84
|
+
{ length: Math.min(w.length, 8) },
|
|
85
|
+
(b, j) => m(w, j)
|
|
86
|
+
);
|
|
87
|
+
}, d = h("name", 256) ?? "Error", l = h("message", 4096) ?? "", f = h("stack", 16384), g = h("code", 256), I = m(s, "cause"), et = c("errors"), it = h("manifestName", 256), st = c("denied")?.filter((p) => typeof p == "string").map((p) => a(p, 256)), rt = c("issues")?.map((p) => {
|
|
88
|
+
const w = m(p, "message"), b = m(p, "path"), j = Array.isArray(b) ? Array.from({ length: Math.min(b.length, 16) }, (Pe, St) => {
|
|
89
|
+
const k = m(b, St), S = k && typeof k == "object" ? m(k, "key") : k;
|
|
90
|
+
return typeof S == "number" ? S : typeof S == "string" || typeof S == "symbol" ? a(String(S), 256) : "[omitted]";
|
|
91
|
+
}) : void 0;
|
|
92
|
+
return Array.isArray(b) && b.length > 16 && (o = !0), Object.freeze({
|
|
93
|
+
message: typeof w == "string" ? a(w, 4096) : "",
|
|
94
|
+
...j ? { path: Object.freeze(j) } : {}
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
return Object.freeze({
|
|
98
|
+
name: d,
|
|
99
|
+
message: l,
|
|
100
|
+
...g === void 0 ? {} : { code: g },
|
|
101
|
+
...f === void 0 ? {} : { stack: f },
|
|
102
|
+
...I === void 0 ? {} : { cause: i(I, n + 1) },
|
|
103
|
+
...et === void 0 ? {} : { errors: Object.freeze(et.map((p) => i(p, n + 1))) },
|
|
104
|
+
...it === void 0 ? {} : { manifestName: it },
|
|
105
|
+
...st === void 0 ? {} : { denied: Object.freeze(st) },
|
|
106
|
+
...rt === void 0 ? {} : { issues: Object.freeze(rt) },
|
|
107
|
+
...o ? { truncated: !0 } : {}
|
|
108
|
+
});
|
|
109
|
+
};
|
|
110
|
+
return i(r, 0);
|
|
83
111
|
}
|
|
84
|
-
function
|
|
112
|
+
function m(r, t) {
|
|
85
113
|
try {
|
|
86
|
-
|
|
87
|
-
return typeof t == "string" && t.trim() === t && t.length > 0 ? t : void 0;
|
|
114
|
+
return r && typeof r == "object" ? r[t] : void 0;
|
|
88
115
|
} catch {
|
|
89
116
|
return;
|
|
90
117
|
}
|
|
91
118
|
}
|
|
92
|
-
class
|
|
119
|
+
class G extends u {
|
|
93
120
|
}
|
|
94
|
-
function
|
|
95
|
-
return r instanceof
|
|
121
|
+
function V(r, t, e) {
|
|
122
|
+
return r instanceof G ? r.code === t ? r : new G(t, e, { cause: r.cause }) : r instanceof Error ? r : new G(t, e, { cause: r });
|
|
96
123
|
}
|
|
97
|
-
function
|
|
124
|
+
function wt(r, t) {
|
|
98
125
|
if (!r || typeof r != "object" || typeof r.aborted != "boolean" || typeof r.addEventListener != "function" || typeof r.removeEventListener != "function" || typeof r.throwIfAborted != "function")
|
|
99
126
|
throw new TypeError("Cancellation classifier expects an AbortSignal");
|
|
100
127
|
return r.aborted ? Object.is(t, r.reason) ? !0 : t instanceof Error && t.name === "AbortError" : !1;
|
|
101
128
|
}
|
|
102
|
-
class
|
|
129
|
+
class $t extends u {
|
|
103
130
|
name = "ConfigValidationError";
|
|
104
131
|
issues;
|
|
105
132
|
constructor(t) {
|
|
106
|
-
const e =
|
|
133
|
+
const e = Tt(t);
|
|
107
134
|
super(
|
|
108
135
|
"CONFIG_INVALID",
|
|
109
136
|
`Invalid Plugin config:
|
|
@@ -112,7 +139,7 @@ ${e.map((i) => ` - ${i.message}`).join(`
|
|
|
112
139
|
), this.issues = e;
|
|
113
140
|
}
|
|
114
141
|
}
|
|
115
|
-
function
|
|
142
|
+
function Tt(r) {
|
|
116
143
|
if (!Array.isArray(r))
|
|
117
144
|
throw new TypeError("Config validation issues must be an array");
|
|
118
145
|
return Object.freeze(
|
|
@@ -124,23 +151,23 @@ function ft(r) {
|
|
|
124
151
|
throw new TypeError(`Config validation issue at index ${e} message must be a string`);
|
|
125
152
|
return Object.freeze({
|
|
126
153
|
message: i.message,
|
|
127
|
-
...i.path === void 0 ? {} : { path:
|
|
154
|
+
...i.path === void 0 ? {} : { path: Pt(i.path, e) }
|
|
128
155
|
});
|
|
129
156
|
})
|
|
130
157
|
);
|
|
131
158
|
}
|
|
132
|
-
function
|
|
159
|
+
function Pt(r, t) {
|
|
133
160
|
if (!Array.isArray(r))
|
|
134
161
|
throw new TypeError(`Config validation issue at index ${t} path must be an array`);
|
|
135
162
|
return Object.freeze(
|
|
136
163
|
Array.from(r, (e, i) => {
|
|
137
|
-
if (
|
|
164
|
+
if (nt(e)) return e;
|
|
138
165
|
if (!e || typeof e != "object")
|
|
139
166
|
throw new TypeError(
|
|
140
167
|
`Config validation issue at index ${t} path segment ${i} must be a property key`
|
|
141
168
|
);
|
|
142
169
|
const s = e.key;
|
|
143
|
-
if (!
|
|
170
|
+
if (!nt(s))
|
|
144
171
|
throw new TypeError(
|
|
145
172
|
`Config validation issue at index ${t} path segment ${i} must contain a property key`
|
|
146
173
|
);
|
|
@@ -148,10 +175,10 @@ function pt(r, t) {
|
|
|
148
175
|
})
|
|
149
176
|
);
|
|
150
177
|
}
|
|
151
|
-
function
|
|
178
|
+
function nt(r) {
|
|
152
179
|
return typeof r == "string" || typeof r == "number" || typeof r == "symbol";
|
|
153
180
|
}
|
|
154
|
-
async function
|
|
181
|
+
async function Lt(r, t, e) {
|
|
155
182
|
if (!r) return t;
|
|
156
183
|
const i = await r["~standard"].validate(t);
|
|
157
184
|
if (!i || typeof i != "object")
|
|
@@ -160,7 +187,7 @@ async function et(r, t, e) {
|
|
|
160
187
|
);
|
|
161
188
|
const s = Object.hasOwn(i, "issues") ? i.issues : void 0;
|
|
162
189
|
if (s !== void 0)
|
|
163
|
-
throw Array.isArray(s) ? new
|
|
190
|
+
throw Array.isArray(s) ? new $t(s) : new TypeError(
|
|
164
191
|
`Installation '${e}' config validator returned non-array issues`
|
|
165
192
|
);
|
|
166
193
|
if (!Object.hasOwn(i, "value"))
|
|
@@ -169,29 +196,29 @@ async function et(r, t, e) {
|
|
|
169
196
|
);
|
|
170
197
|
return i.value;
|
|
171
198
|
}
|
|
172
|
-
class
|
|
199
|
+
class zt {
|
|
173
200
|
#t = /* @__PURE__ */ new Map();
|
|
174
201
|
get kinds() {
|
|
175
202
|
return this.#t;
|
|
176
203
|
}
|
|
177
204
|
assertCompatible(t) {
|
|
178
|
-
|
|
205
|
+
bt(this.#t, t);
|
|
179
206
|
}
|
|
180
207
|
remember(t) {
|
|
181
|
-
|
|
208
|
+
q(this.#t, t);
|
|
182
209
|
}
|
|
183
|
-
|
|
184
|
-
return new
|
|
210
|
+
writer(t) {
|
|
211
|
+
return new Rt(this, t);
|
|
185
212
|
}
|
|
186
213
|
commit(t) {
|
|
187
214
|
for (const [e, i] of t) this.assertCompatible({ id: e, kind: i });
|
|
188
215
|
for (const [e, i] of t) this.#t.set(e, i);
|
|
189
216
|
}
|
|
190
217
|
}
|
|
191
|
-
class
|
|
218
|
+
class Rt {
|
|
192
219
|
#t;
|
|
193
220
|
constructor(t, e) {
|
|
194
|
-
this.#t = { phase: "
|
|
221
|
+
this.#t = { phase: "staged", registry: t, pending: /* @__PURE__ */ new Map() };
|
|
195
222
|
for (const [i, s] of e) this.remember({ id: i, kind: s });
|
|
196
223
|
}
|
|
197
224
|
remember(t) {
|
|
@@ -201,21 +228,21 @@ class wt {
|
|
|
201
228
|
return;
|
|
202
229
|
}
|
|
203
230
|
if (e.phase === "discarded")
|
|
204
|
-
throw new Error("Contract registry
|
|
205
|
-
e.registry.assertCompatible(t), !e.registry.kinds.has(t.id) &&
|
|
231
|
+
throw new Error("Contract registry writer has been discarded");
|
|
232
|
+
e.registry.assertCompatible(t), !e.registry.kinds.has(t.id) && q(e.pending, t);
|
|
206
233
|
}
|
|
207
234
|
commit() {
|
|
208
235
|
const t = this.#t;
|
|
209
|
-
t.phase === "
|
|
236
|
+
t.phase === "staged" && (t.registry.commit(t.pending), this.#t = { phase: "committed", registry: t.registry });
|
|
210
237
|
}
|
|
211
238
|
discard() {
|
|
212
|
-
this.#t.phase === "
|
|
239
|
+
this.#t.phase === "staged" && (this.#t = { phase: "discarded" });
|
|
213
240
|
}
|
|
214
241
|
}
|
|
215
|
-
function
|
|
216
|
-
|
|
242
|
+
function q(r, t) {
|
|
243
|
+
bt(r, t), r.set(t.id, t.kind);
|
|
217
244
|
}
|
|
218
|
-
function
|
|
245
|
+
function bt(r, t) {
|
|
219
246
|
const e = r.get(t.id);
|
|
220
247
|
if (e && e !== t.kind)
|
|
221
248
|
throw new u(
|
|
@@ -223,9 +250,9 @@ function it(r, t) {
|
|
|
223
250
|
`Contract '${t.id}' is used as both '${e}' and '${t.kind}'`
|
|
224
251
|
);
|
|
225
252
|
}
|
|
226
|
-
class
|
|
227
|
-
constructor(t, e, i, s, n, o) {
|
|
228
|
-
this.order =
|
|
253
|
+
class X {
|
|
254
|
+
constructor(t, e, i, s, n, o, a) {
|
|
255
|
+
this.order = e, this.layers = i, this.providers = s, this.dependents = n, this.contractKinds = o, this.#t = t, this.#e = a;
|
|
229
256
|
}
|
|
230
257
|
order;
|
|
231
258
|
layers;
|
|
@@ -233,13 +260,15 @@ class M {
|
|
|
233
260
|
dependents;
|
|
234
261
|
contractKinds;
|
|
235
262
|
#t;
|
|
263
|
+
#e;
|
|
236
264
|
static build(t, e) {
|
|
237
|
-
const i = [...t].sort((c, d) => c.index - d.index), s = new Map(e), n =
|
|
265
|
+
const i = [...t].sort((c, d) => c.index - d.index), s = new Map(e), n = Nt(i, s), o = xt(i, n, s), { order: a, layers: h } = Mt(
|
|
238
266
|
i,
|
|
239
267
|
o.dependents,
|
|
240
268
|
o.indegree
|
|
241
269
|
);
|
|
242
|
-
return new
|
|
270
|
+
return new X(
|
|
271
|
+
new Map(i.map((c) => [c, c.declaration])),
|
|
243
272
|
Object.freeze(a),
|
|
244
273
|
Object.freeze(h.map((c) => Object.freeze(c))),
|
|
245
274
|
n,
|
|
@@ -248,17 +277,28 @@ class M {
|
|
|
248
277
|
o.resolvedProviders
|
|
249
278
|
);
|
|
250
279
|
}
|
|
280
|
+
declarationFor(t) {
|
|
281
|
+
const e = this.#t.get(t);
|
|
282
|
+
if (!e) throw new Error(`Installation '${t.id}' is not in this plan`);
|
|
283
|
+
return e;
|
|
284
|
+
}
|
|
251
285
|
providerFor(t, e) {
|
|
252
|
-
return this.#
|
|
286
|
+
return this.#e.get(t)?.get(e);
|
|
253
287
|
}
|
|
254
288
|
provider(t) {
|
|
255
289
|
return this.providers.get(t);
|
|
256
290
|
}
|
|
291
|
+
/**
|
|
292
|
+
* Transitive dependents in *both* plans. A Service being replaced has old
|
|
293
|
+
* consumers that must stop and new ones that must start, and only the union
|
|
294
|
+
* covers both — expanding in the current plan alone would leave an Instance
|
|
295
|
+
* running against a dependency that no longer exists.
|
|
296
|
+
*/
|
|
257
297
|
affectedByTransitionTo(t, e) {
|
|
258
298
|
const i = /* @__PURE__ */ new Set();
|
|
259
|
-
return this.#
|
|
299
|
+
return this.#i(e, i), t.#i(e, i), i;
|
|
260
300
|
}
|
|
261
|
-
#
|
|
301
|
+
#i(t, e) {
|
|
262
302
|
const i = [...t], s = /* @__PURE__ */ new Set();
|
|
263
303
|
for (let n = 0; n < i.length; n++) {
|
|
264
304
|
const o = i[n];
|
|
@@ -269,11 +309,11 @@ class M {
|
|
|
269
309
|
}
|
|
270
310
|
}
|
|
271
311
|
}
|
|
272
|
-
function
|
|
312
|
+
function Nt(r, t) {
|
|
273
313
|
const e = /* @__PURE__ */ new Map();
|
|
274
314
|
for (const i of r)
|
|
275
|
-
for (const s of Object.values(i.declaration.plugin.provides
|
|
276
|
-
|
|
315
|
+
for (const s of Object.values(i.declaration.plugin.provides)) {
|
|
316
|
+
q(t, s);
|
|
277
317
|
const n = e.get(s.id);
|
|
278
318
|
if (n)
|
|
279
319
|
throw new u(
|
|
@@ -284,12 +324,12 @@ function vt(r, t) {
|
|
|
284
324
|
}
|
|
285
325
|
return e;
|
|
286
326
|
}
|
|
287
|
-
function
|
|
327
|
+
function xt(r, t, e) {
|
|
288
328
|
const i = /* @__PURE__ */ new Map(), s = /* @__PURE__ */ new Map(), n = new Map(r.map((o) => [o, 0]));
|
|
289
329
|
for (const o of r)
|
|
290
|
-
for (const a of Object.values(o.declaration.plugin.requires
|
|
330
|
+
for (const a of Object.values(o.declaration.plugin.requires)) {
|
|
291
331
|
const h = a.kind === "optional" ? a.service : a;
|
|
292
|
-
if (
|
|
332
|
+
if (q(e, h), h.kind === "extensionPoint") continue;
|
|
293
333
|
const c = t.get(h.id);
|
|
294
334
|
if (!c) {
|
|
295
335
|
if (a.kind === "optional") continue;
|
|
@@ -310,7 +350,7 @@ function bt(r, t, e) {
|
|
|
310
350
|
}
|
|
311
351
|
return { resolvedProviders: i, dependents: s, indegree: n };
|
|
312
352
|
}
|
|
313
|
-
function
|
|
353
|
+
function Mt(r, t, e) {
|
|
314
354
|
let i = r.filter((o) => e.get(o) === 0);
|
|
315
355
|
const s = [], n = [];
|
|
316
356
|
for (; i.length; ) {
|
|
@@ -324,7 +364,7 @@ function mt(r, t, e) {
|
|
|
324
364
|
}
|
|
325
365
|
}
|
|
326
366
|
if (s.length !== r.length) {
|
|
327
|
-
const o =
|
|
367
|
+
const o = Dt(r, t);
|
|
328
368
|
throw new u(
|
|
329
369
|
"SERVICE_CYCLE",
|
|
330
370
|
`Installation dependency cycle: ${o.map((a) => a.id).join(" -> ")}`
|
|
@@ -332,7 +372,7 @@ function mt(r, t, e) {
|
|
|
332
372
|
}
|
|
333
373
|
return { order: s, layers: n };
|
|
334
374
|
}
|
|
335
|
-
function
|
|
375
|
+
function Dt(r, t) {
|
|
336
376
|
const e = /* @__PURE__ */ new Set(), i = /* @__PURE__ */ new Set(), s = [], n = (o) => {
|
|
337
377
|
i.add(o), s.push(o);
|
|
338
378
|
for (const a of t.get(o) ?? []) {
|
|
@@ -353,7 +393,7 @@ function yt(r, t) {
|
|
|
353
393
|
}
|
|
354
394
|
throw new Error("Dependency graph is cyclic but no cycle path was found");
|
|
355
395
|
}
|
|
356
|
-
class
|
|
396
|
+
class z {
|
|
357
397
|
#t;
|
|
358
398
|
constructor(t = []) {
|
|
359
399
|
if (!t || typeof t != "object" && typeof t != "function" || typeof t[Symbol.iterator] != "function")
|
|
@@ -385,31 +425,65 @@ class O {
|
|
|
385
425
|
return this.entries();
|
|
386
426
|
}
|
|
387
427
|
}
|
|
388
|
-
function
|
|
428
|
+
function Vt(r) {
|
|
389
429
|
if (typeof r != "function")
|
|
390
430
|
throw new Error("Unsupported JavaScript runtime: Promise.withResolvers is required");
|
|
391
431
|
}
|
|
392
|
-
function
|
|
432
|
+
function mt(r, t) {
|
|
393
433
|
return r ?? Symbol.for(t);
|
|
394
434
|
}
|
|
395
|
-
|
|
396
|
-
const
|
|
435
|
+
Vt(Promise.withResolvers);
|
|
436
|
+
const v = mt(
|
|
397
437
|
Symbol.dispose,
|
|
398
438
|
"Symbol.dispose"
|
|
399
|
-
),
|
|
439
|
+
), F = mt(
|
|
400
440
|
Symbol.asyncDispose,
|
|
401
441
|
"Symbol.asyncDispose"
|
|
402
442
|
);
|
|
403
|
-
function
|
|
404
|
-
if (
|
|
443
|
+
function R(r, t) {
|
|
444
|
+
if (qt(r))
|
|
405
445
|
throw Promise.resolve(r).catch(() => {
|
|
406
446
|
}), new TypeError(t);
|
|
407
447
|
}
|
|
408
|
-
function
|
|
448
|
+
function qt(r) {
|
|
409
449
|
return r === null || typeof r != "object" && typeof r != "function" ? !1 : typeof r.then == "function";
|
|
410
450
|
}
|
|
411
|
-
const
|
|
412
|
-
|
|
451
|
+
const N = /* @__PURE__ */ new WeakMap(), C = /* @__PURE__ */ new Set();
|
|
452
|
+
let T = 0, U = !1;
|
|
453
|
+
function Ft(r) {
|
|
454
|
+
T++;
|
|
455
|
+
const t = [];
|
|
456
|
+
try {
|
|
457
|
+
r();
|
|
458
|
+
} catch (e) {
|
|
459
|
+
t.push(e);
|
|
460
|
+
} finally {
|
|
461
|
+
if (T--, !T)
|
|
462
|
+
try {
|
|
463
|
+
vt();
|
|
464
|
+
} catch (e) {
|
|
465
|
+
t.push(e);
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
if (t.length === 1) throw t[0];
|
|
469
|
+
if (t.length > 1) throw new AggregateError(t, "Snapshot batch failed");
|
|
470
|
+
}
|
|
471
|
+
function vt() {
|
|
472
|
+
if (U) return;
|
|
473
|
+
U = !0;
|
|
474
|
+
const r = [];
|
|
475
|
+
try {
|
|
476
|
+
for (; C.size; ) {
|
|
477
|
+
const t = C.values().next().value;
|
|
478
|
+
C.delete(t), Gt(t, r);
|
|
479
|
+
}
|
|
480
|
+
} finally {
|
|
481
|
+
U = !1, C.clear();
|
|
482
|
+
}
|
|
483
|
+
if (r.length)
|
|
484
|
+
throw new AggregateError(r, "Snapshot error reporting failed");
|
|
485
|
+
}
|
|
486
|
+
class Z {
|
|
413
487
|
#t = /* @__PURE__ */ new Set();
|
|
414
488
|
#e;
|
|
415
489
|
#i;
|
|
@@ -425,24 +499,9 @@ class q {
|
|
|
425
499
|
subscribe: (t) => this.#a(t)
|
|
426
500
|
});
|
|
427
501
|
invalidate() {
|
|
428
|
-
|
|
429
|
-
this.#
|
|
430
|
-
|
|
431
|
-
for (const i of [...this.#t])
|
|
432
|
-
try {
|
|
433
|
-
Ot(i);
|
|
434
|
-
} catch (s) {
|
|
435
|
-
try {
|
|
436
|
-
P(
|
|
437
|
-
t(s),
|
|
438
|
-
"Snapshot error reporters must be synchronous"
|
|
439
|
-
);
|
|
440
|
-
} catch (n) {
|
|
441
|
-
e.push(s, n);
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
if (e.length)
|
|
445
|
-
throw new AggregateError(e, "Snapshot error reporting failed");
|
|
502
|
+
this.#o(), this.#s = !0;
|
|
503
|
+
for (const t of this.#t) C.add(t);
|
|
504
|
+
T || vt();
|
|
446
505
|
}
|
|
447
506
|
dispose() {
|
|
448
507
|
const t = this.#e;
|
|
@@ -454,11 +513,11 @@ class q {
|
|
|
454
513
|
this.#s = !1;
|
|
455
514
|
const e = [...this.#t];
|
|
456
515
|
this.#t.clear();
|
|
457
|
-
for (const i of e)
|
|
516
|
+
for (const i of e) yt(i);
|
|
458
517
|
}
|
|
459
518
|
}
|
|
460
519
|
}
|
|
461
|
-
[
|
|
520
|
+
[v]() {
|
|
462
521
|
this.dispose();
|
|
463
522
|
}
|
|
464
523
|
#n() {
|
|
@@ -467,11 +526,10 @@ class q {
|
|
|
467
526
|
}
|
|
468
527
|
#a(t) {
|
|
469
528
|
if (typeof t != "function") throw new TypeError("Subscriber must be a function");
|
|
470
|
-
this.#o()
|
|
471
|
-
|
|
472
|
-
this.#t.delete(i);
|
|
529
|
+
const { report: e } = this.#o(), i = new Bt(t, e, (s) => {
|
|
530
|
+
this.#t.delete(s);
|
|
473
531
|
});
|
|
474
|
-
return this.#t.add(
|
|
532
|
+
return this.#t.add(i), i;
|
|
475
533
|
}
|
|
476
534
|
#r(t) {
|
|
477
535
|
this.#s && (this.#i = t(), this.#s = !1);
|
|
@@ -482,26 +540,38 @@ class q {
|
|
|
482
540
|
return t;
|
|
483
541
|
}
|
|
484
542
|
}
|
|
485
|
-
class
|
|
486
|
-
constructor(t, e) {
|
|
487
|
-
|
|
543
|
+
class Bt {
|
|
544
|
+
constructor(t, e, i) {
|
|
545
|
+
N.set(this, { listener: t, report: e, detach: i }), Object.freeze(this);
|
|
488
546
|
}
|
|
489
547
|
dispose() {
|
|
490
|
-
const t =
|
|
491
|
-
t && (
|
|
548
|
+
const t = N.get(this);
|
|
549
|
+
t && (yt(this), t.detach(this));
|
|
492
550
|
}
|
|
493
|
-
[
|
|
551
|
+
[v]() {
|
|
494
552
|
this.dispose();
|
|
495
553
|
}
|
|
496
554
|
}
|
|
497
|
-
function
|
|
498
|
-
const
|
|
499
|
-
|
|
555
|
+
function Gt(r, t) {
|
|
556
|
+
const e = N.get(r);
|
|
557
|
+
if (e)
|
|
558
|
+
try {
|
|
559
|
+
R(e.listener(), "Snapshot subscribers must be synchronous");
|
|
560
|
+
} catch (i) {
|
|
561
|
+
try {
|
|
562
|
+
R(
|
|
563
|
+
e.report(i),
|
|
564
|
+
"Snapshot error reporters must be synchronous"
|
|
565
|
+
);
|
|
566
|
+
} catch (s) {
|
|
567
|
+
t.push(i, s);
|
|
568
|
+
}
|
|
569
|
+
}
|
|
500
570
|
}
|
|
501
|
-
function
|
|
502
|
-
|
|
571
|
+
function yt(r) {
|
|
572
|
+
C.delete(r), N.delete(r);
|
|
503
573
|
}
|
|
504
|
-
class
|
|
574
|
+
class Ut {
|
|
505
575
|
#t;
|
|
506
576
|
get;
|
|
507
577
|
subscribe;
|
|
@@ -523,7 +593,7 @@ class At {
|
|
|
523
593
|
return t;
|
|
524
594
|
}
|
|
525
595
|
}
|
|
526
|
-
class
|
|
596
|
+
class _t {
|
|
527
597
|
#t;
|
|
528
598
|
constructor(t) {
|
|
529
599
|
this.#t = t, Object.freeze(this);
|
|
@@ -534,16 +604,16 @@ class Tt {
|
|
|
534
604
|
dispose() {
|
|
535
605
|
this.#t.dispose();
|
|
536
606
|
}
|
|
537
|
-
[
|
|
607
|
+
[v]() {
|
|
538
608
|
this.dispose();
|
|
539
609
|
}
|
|
540
610
|
}
|
|
541
|
-
class
|
|
611
|
+
class Ht {
|
|
542
612
|
#t;
|
|
543
613
|
#e;
|
|
544
614
|
handle;
|
|
545
615
|
constructor(t, e, i, s) {
|
|
546
|
-
this.#e = e, this.#t = { phase: "staged", store: t, value: i, detachFromOwner: s }, this.handle = new
|
|
616
|
+
this.#e = e, this.#t = { phase: "staged", store: t, value: i, detachFromOwner: s }, this.handle = new _t(this);
|
|
547
617
|
}
|
|
548
618
|
publish() {
|
|
549
619
|
const t = this.#t;
|
|
@@ -572,55 +642,62 @@ class $t {
|
|
|
572
642
|
}
|
|
573
643
|
}
|
|
574
644
|
}
|
|
575
|
-
[
|
|
645
|
+
[v]() {
|
|
576
646
|
this.dispose();
|
|
577
647
|
}
|
|
578
648
|
}
|
|
579
|
-
class
|
|
649
|
+
class Kt {
|
|
580
650
|
#t;
|
|
581
651
|
#e;
|
|
582
652
|
#i = /* @__PURE__ */ new Map();
|
|
583
653
|
#s = /* @__PURE__ */ new Map();
|
|
584
654
|
#n;
|
|
585
|
-
#a = new
|
|
655
|
+
#a = new z();
|
|
586
656
|
#r = 0;
|
|
587
657
|
#o = 0;
|
|
588
|
-
#
|
|
589
|
-
#
|
|
658
|
+
#h = !1;
|
|
659
|
+
#p = !1;
|
|
590
660
|
constructor(t, e, i) {
|
|
591
|
-
this.#t = t, this.#e = i, this.#n = new
|
|
661
|
+
this.#t = t, this.#e = i, this.#n = new Z(() => this.#a, e);
|
|
592
662
|
}
|
|
593
663
|
stage(t, e, i, s) {
|
|
594
|
-
|
|
595
|
-
const n =
|
|
664
|
+
Jt(e);
|
|
665
|
+
const n = Xt(t, e);
|
|
596
666
|
if (this.#i.has(n))
|
|
597
667
|
throw new TypeError(`Duplicate contribution '${n}'`);
|
|
598
|
-
const o = new
|
|
668
|
+
const o = new Ht(this, n, i, s);
|
|
599
669
|
return this.#i.set(n, o), o;
|
|
600
670
|
}
|
|
601
671
|
view(t) {
|
|
602
672
|
this.#r++;
|
|
603
673
|
const e = { binding: { store: this, own: t } };
|
|
604
674
|
let i;
|
|
605
|
-
const s = new
|
|
675
|
+
const s = new Wt(e, () => {
|
|
606
676
|
const n = i;
|
|
607
677
|
i = void 0;
|
|
608
678
|
try {
|
|
609
679
|
n?.();
|
|
610
680
|
} finally {
|
|
611
|
-
this.#r--, this.#
|
|
681
|
+
this.#r--, this.#c();
|
|
612
682
|
}
|
|
613
683
|
});
|
|
614
684
|
try {
|
|
615
685
|
i = t(s, "view");
|
|
616
686
|
} catch (n) {
|
|
617
|
-
throw e.binding = void 0, this.#r--, this.#
|
|
687
|
+
throw e.binding = void 0, this.#r--, this.#c(), n;
|
|
618
688
|
}
|
|
619
|
-
return new
|
|
620
|
-
}
|
|
621
|
-
/**
|
|
689
|
+
return new Ut(e);
|
|
690
|
+
}
|
|
691
|
+
/**
|
|
692
|
+
* A stable view explicitly owned by the Host for graph-external consumers.
|
|
693
|
+
*
|
|
694
|
+
* Application code has no Lifetime to lease a view from, so this one is
|
|
695
|
+
* retained by the Host instead — which also pins the store open for as long as
|
|
696
|
+
* the Host lives. That is the trade: `host.contributions()` gives a handle that
|
|
697
|
+
* never goes stale, at the cost of a store that is no longer self-releasing.
|
|
698
|
+
*/
|
|
622
699
|
hostView() {
|
|
623
|
-
return this.#
|
|
700
|
+
return this.#h = !0, this.#n.view;
|
|
624
701
|
}
|
|
625
702
|
snapshot() {
|
|
626
703
|
return this.#n.view.get();
|
|
@@ -631,13 +708,13 @@ class jt {
|
|
|
631
708
|
const i = this.#n.view.subscribe(t);
|
|
632
709
|
this.#o++;
|
|
633
710
|
let s;
|
|
634
|
-
const n = new
|
|
711
|
+
const n = new Yt(i, () => {
|
|
635
712
|
const o = s;
|
|
636
713
|
s = void 0;
|
|
637
714
|
try {
|
|
638
715
|
o?.();
|
|
639
716
|
} finally {
|
|
640
|
-
this.#o--, this.#
|
|
717
|
+
this.#o--, this.#c();
|
|
641
718
|
}
|
|
642
719
|
});
|
|
643
720
|
try {
|
|
@@ -648,39 +725,50 @@ class jt {
|
|
|
648
725
|
return n;
|
|
649
726
|
}
|
|
650
727
|
insert(t, e, i) {
|
|
651
|
-
if (this.#
|
|
728
|
+
if (this.#u(t, e), this.#s.has(t))
|
|
652
729
|
throw new Error(`Contribution '${t}' is already published`);
|
|
653
730
|
e.commitPublication(), this.#s.set(t, { contribution: e, value: i }), this.#t(this);
|
|
654
731
|
}
|
|
655
732
|
update(t, e, i) {
|
|
656
|
-
const s = this.#
|
|
733
|
+
const s = this.#f(t, e);
|
|
657
734
|
s.value = i, this.#t(this);
|
|
658
735
|
}
|
|
659
736
|
removeContribution(t, e, i) {
|
|
660
|
-
this.#
|
|
737
|
+
this.#u(t, e), i === "published" && this.#f(t, e);
|
|
661
738
|
try {
|
|
662
739
|
this.#i.delete(t), i === "published" && (this.#s.delete(t), this.#t(this));
|
|
663
740
|
} finally {
|
|
664
|
-
this.#
|
|
741
|
+
this.#c();
|
|
665
742
|
}
|
|
666
743
|
}
|
|
744
|
+
/**
|
|
745
|
+
* Rebuilds the published snapshot, and does nothing when the result would be
|
|
746
|
+
* equal by identity per key. A change that adds and removes the same entry —
|
|
747
|
+
* an Instance restarting with an identical contribution — therefore notifies
|
|
748
|
+
* nobody, instead of waking every observer to hand them what they already had.
|
|
749
|
+
*/
|
|
667
750
|
publishSnapshot() {
|
|
668
751
|
const t = [...this.#s].map(([i, s]) => [i, s.value]);
|
|
669
|
-
t.length === this.#a.size && t.every(
|
|
752
|
+
t.length === this.#a.size && t.every(
|
|
753
|
+
([i, s]) => this.#a.has(i) && Object.is(this.#a.get(i), s)
|
|
754
|
+
) || (this.#a = new z(t), this.#n.invalidate());
|
|
670
755
|
}
|
|
671
|
-
#
|
|
756
|
+
#u(t, e) {
|
|
672
757
|
if (this.#i.get(t) !== e)
|
|
673
758
|
throw new Error(`Contribution '${t}' is not the current claim`);
|
|
674
759
|
}
|
|
675
|
-
#
|
|
760
|
+
#f(t, e) {
|
|
676
761
|
const i = this.#s.get(t);
|
|
677
762
|
if (i?.contribution !== e)
|
|
678
763
|
throw new Error(`Contribution '${t}' is not the published entry`);
|
|
679
764
|
return i;
|
|
680
765
|
}
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
766
|
+
// The self-release check. Every counter has to be at zero and the Host must
|
|
767
|
+
// not be holding a view; `#released` makes it run once, since disposing the
|
|
768
|
+
// publisher can re-enter through a subscription's own teardown.
|
|
769
|
+
#c() {
|
|
770
|
+
if (!(this.#p || this.#h || this.#i.size || this.#s.size || this.#o || this.#r)) {
|
|
771
|
+
this.#p = !0;
|
|
684
772
|
try {
|
|
685
773
|
this.#n.dispose();
|
|
686
774
|
} finally {
|
|
@@ -689,7 +777,7 @@ class jt {
|
|
|
689
777
|
}
|
|
690
778
|
}
|
|
691
779
|
}
|
|
692
|
-
class
|
|
780
|
+
class Wt {
|
|
693
781
|
#t;
|
|
694
782
|
constructor(t, e) {
|
|
695
783
|
this.#t = { state: t, release: e }, Object.freeze(this);
|
|
@@ -698,11 +786,11 @@ class kt {
|
|
|
698
786
|
const t = this.#t;
|
|
699
787
|
t && (this.#t = void 0, t.state.binding = void 0, t.release());
|
|
700
788
|
}
|
|
701
|
-
[
|
|
789
|
+
[v]() {
|
|
702
790
|
this.dispose();
|
|
703
791
|
}
|
|
704
792
|
}
|
|
705
|
-
class
|
|
793
|
+
class Yt {
|
|
706
794
|
#t;
|
|
707
795
|
constructor(t, e) {
|
|
708
796
|
this.#t = { subscription: t, release: e }, Object.freeze(this);
|
|
@@ -718,11 +806,11 @@ class Pt {
|
|
|
718
806
|
}
|
|
719
807
|
}
|
|
720
808
|
}
|
|
721
|
-
[
|
|
809
|
+
[v]() {
|
|
722
810
|
this.dispose();
|
|
723
811
|
}
|
|
724
812
|
}
|
|
725
|
-
class
|
|
813
|
+
class Qt {
|
|
726
814
|
#t = /* @__PURE__ */ new Map();
|
|
727
815
|
#e = /* @__PURE__ */ new Set();
|
|
728
816
|
#i;
|
|
@@ -733,7 +821,7 @@ class Lt {
|
|
|
733
821
|
get(t) {
|
|
734
822
|
const e = this.#t.get(t.id);
|
|
735
823
|
if (e) return e;
|
|
736
|
-
const i = new
|
|
824
|
+
const i = new Kt(
|
|
737
825
|
(s) => this.#n(s),
|
|
738
826
|
this.#i,
|
|
739
827
|
(s) => {
|
|
@@ -748,39 +836,44 @@ class Lt {
|
|
|
748
836
|
beginBatch() {
|
|
749
837
|
this.#s++;
|
|
750
838
|
}
|
|
839
|
+
// Depth-counted, so nested Host operations collapse into the outermost batch
|
|
840
|
+
// and publication happens exactly once. Every store's snapshot is attempted
|
|
841
|
+
// even if one of them throws, then the failures are aggregated — a single bad
|
|
842
|
+
// subscriber must not leave the remaining stores unpublished.
|
|
751
843
|
endBatch() {
|
|
752
844
|
if (!this.#s) throw new Error("Contribution batch is not active");
|
|
753
845
|
if (this.#s--, this.#s) return;
|
|
754
846
|
const t = [...this.#e];
|
|
755
|
-
this.#e.clear()
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
847
|
+
this.#e.clear(), Ft(() => {
|
|
848
|
+
const e = [];
|
|
849
|
+
for (const i of t)
|
|
850
|
+
try {
|
|
851
|
+
i.publishSnapshot();
|
|
852
|
+
} catch (s) {
|
|
853
|
+
e.push(s);
|
|
854
|
+
}
|
|
855
|
+
if (e.length === 1) throw e[0];
|
|
856
|
+
if (e.length > 1)
|
|
857
|
+
throw new AggregateError(e, "Contribution batch publication failed");
|
|
858
|
+
});
|
|
766
859
|
}
|
|
767
860
|
#n(t) {
|
|
768
861
|
this.#e.add(t), !this.#s && (this.#e.delete(t), t.publishSnapshot());
|
|
769
862
|
}
|
|
770
863
|
}
|
|
771
|
-
function
|
|
864
|
+
function Jt(r) {
|
|
772
865
|
if (typeof r != "string" || !r.trim())
|
|
773
866
|
throw new TypeError("Contribution key must be a non-empty string");
|
|
774
867
|
if (r !== r.trim())
|
|
775
868
|
throw new TypeError("Contribution key cannot start or end with whitespace");
|
|
776
869
|
}
|
|
777
|
-
function
|
|
778
|
-
return `${
|
|
870
|
+
function Xt(r, t) {
|
|
871
|
+
return `${ot(r)}/${ot(t)}`;
|
|
779
872
|
}
|
|
780
|
-
function
|
|
873
|
+
function ot(r) {
|
|
781
874
|
return r.replaceAll("%", "%25").replaceAll("/", "%2F");
|
|
782
875
|
}
|
|
783
|
-
class
|
|
876
|
+
class Zt {
|
|
784
877
|
#t;
|
|
785
878
|
constructor(t) {
|
|
786
879
|
this.#t = t, Object.freeze(this);
|
|
@@ -789,16 +882,16 @@ class Nt {
|
|
|
789
882
|
const t = this.#t;
|
|
790
883
|
this.#t = void 0, t?.dispose();
|
|
791
884
|
}
|
|
792
|
-
[
|
|
885
|
+
[v]() {
|
|
793
886
|
this.dispose();
|
|
794
887
|
}
|
|
795
888
|
}
|
|
796
|
-
class
|
|
889
|
+
class te {
|
|
797
890
|
#t;
|
|
798
891
|
#e;
|
|
799
892
|
handle;
|
|
800
893
|
constructor(t, e, i, s) {
|
|
801
|
-
this.#e = e, this.#t = { phase: "staged", hub: t, slot: { listener: i }, release: s }, this.handle = new
|
|
894
|
+
this.#e = e, this.#t = { phase: "staged", hub: t, slot: { listener: i }, release: s }, this.handle = new Zt(this);
|
|
802
895
|
}
|
|
803
896
|
publish() {
|
|
804
897
|
const t = this.#t;
|
|
@@ -807,7 +900,7 @@ class xt {
|
|
|
807
900
|
dispose() {
|
|
808
901
|
const t = this.#t;
|
|
809
902
|
if (t.phase !== "removed") {
|
|
810
|
-
this.#t = { phase: "removed" };
|
|
903
|
+
this.#t = { phase: "removed" }, t.slot.listener = void 0;
|
|
811
904
|
try {
|
|
812
905
|
t.phase === "published" && t.hub.delete(this.#e, t.slot);
|
|
813
906
|
} finally {
|
|
@@ -815,15 +908,15 @@ class xt {
|
|
|
815
908
|
}
|
|
816
909
|
}
|
|
817
910
|
}
|
|
818
|
-
[
|
|
911
|
+
[v]() {
|
|
819
912
|
this.dispose();
|
|
820
913
|
}
|
|
821
914
|
}
|
|
822
|
-
class
|
|
915
|
+
class ee {
|
|
823
916
|
#t = /* @__PURE__ */ new Map();
|
|
824
917
|
stage(t, e, i) {
|
|
825
918
|
if (typeof e != "function") throw new TypeError("Event listener must be a function");
|
|
826
|
-
return new
|
|
919
|
+
return new te(this, t, e, i);
|
|
827
920
|
}
|
|
828
921
|
add(t, e) {
|
|
829
922
|
const i = this.#t.get(t) ?? /* @__PURE__ */ new Set();
|
|
@@ -833,25 +926,34 @@ class Dt {
|
|
|
833
926
|
const i = this.#t.get(t);
|
|
834
927
|
i && (i.delete(e), i.size || this.#t.delete(t));
|
|
835
928
|
}
|
|
929
|
+
/**
|
|
930
|
+
* Every still-subscribed listener runs, then failures are aggregated. Three details, all
|
|
931
|
+
* deliberate:
|
|
932
|
+
*
|
|
933
|
+
* - the listener set is copied first; a new subscription does not join this
|
|
934
|
+
* emission. A disposed slot is skipped if its callback has not started;
|
|
935
|
+
* - each call is wrapped in a resolved promise, so a listener that throws
|
|
936
|
+
* synchronously is collected like one that rejects;
|
|
937
|
+
* - `allSettled`, so one broken listener cannot stop the others from being
|
|
938
|
+
* told. The emitter still learns about it — every error comes back.
|
|
939
|
+
*/
|
|
836
940
|
async emit(t, e) {
|
|
837
|
-
const i = [...this.#t.get(t) ?? []].
|
|
838
|
-
(o) => o.listener
|
|
839
|
-
), n = (await Promise.allSettled(
|
|
840
|
-
i.map((o) => Promise.resolve().then(() => o(e)))
|
|
941
|
+
const i = [...this.#t.get(t) ?? []], n = (await Promise.allSettled(
|
|
942
|
+
i.map((o) => Promise.resolve().then(() => o.listener?.(e)))
|
|
841
943
|
)).filter((o) => o.status === "rejected").map((o) => o.reason);
|
|
842
944
|
if (n.length)
|
|
843
945
|
throw new AggregateError(n, `Event '${t}' listeners failed`);
|
|
844
946
|
}
|
|
845
947
|
}
|
|
846
|
-
class
|
|
948
|
+
class ie {
|
|
847
949
|
#t;
|
|
848
950
|
root;
|
|
849
951
|
view;
|
|
850
952
|
constructor(t, e) {
|
|
851
|
-
this.root =
|
|
953
|
+
this.root = at(t), this.#t = new Z(() => Et(this.root), e), this.view = this.#t.view;
|
|
852
954
|
}
|
|
853
955
|
createNode(t) {
|
|
854
|
-
return
|
|
956
|
+
return at(t);
|
|
855
957
|
}
|
|
856
958
|
attach(t, e) {
|
|
857
959
|
if (t.children.has(e)) throw new Error("Lifetime diagnostic node is attached");
|
|
@@ -872,7 +974,7 @@ class Vt {
|
|
|
872
974
|
this.root.phase !== "disposed" && (this.root.phase = "disposed", this.#t.invalidate(), this.#t.dispose());
|
|
873
975
|
}
|
|
874
976
|
}
|
|
875
|
-
function
|
|
977
|
+
function at(r) {
|
|
876
978
|
return {
|
|
877
979
|
label: r,
|
|
878
980
|
phase: "active",
|
|
@@ -887,8 +989,8 @@ function _(r) {
|
|
|
887
989
|
children: /* @__PURE__ */ new Set()
|
|
888
990
|
};
|
|
889
991
|
}
|
|
890
|
-
function
|
|
891
|
-
const t = Object.freeze([...r.children].map(
|
|
992
|
+
function Et(r) {
|
|
993
|
+
const t = Object.freeze([...r.children].map(Et));
|
|
892
994
|
return Object.freeze({
|
|
893
995
|
label: r.label,
|
|
894
996
|
phase: r.phase,
|
|
@@ -896,7 +998,7 @@ function rt(r) {
|
|
|
896
998
|
children: t
|
|
897
999
|
});
|
|
898
1000
|
}
|
|
899
|
-
function
|
|
1001
|
+
function se(r) {
|
|
900
1002
|
if (!r || typeof r != "object" && typeof r != "function") return !1;
|
|
901
1003
|
try {
|
|
902
1004
|
const t = r;
|
|
@@ -907,8 +1009,8 @@ function Mt(r) {
|
|
|
907
1009
|
return !1;
|
|
908
1010
|
}
|
|
909
1011
|
}
|
|
910
|
-
const
|
|
911
|
-
class
|
|
1012
|
+
const W = Object.freeze(new DOMException("Resource disposed", "AbortError"));
|
|
1013
|
+
class y {
|
|
912
1014
|
#t = /* @__PURE__ */ new Set();
|
|
913
1015
|
#e;
|
|
914
1016
|
constructor(t) {
|
|
@@ -928,6 +1030,12 @@ class w {
|
|
|
928
1030
|
const e = this.#e;
|
|
929
1031
|
return e && e.diagnostics.change(e.node, e.kind, -1), !0;
|
|
930
1032
|
};
|
|
1033
|
+
/**
|
|
1034
|
+
* Disposes in reverse creation order, collecting failures rather than
|
|
1035
|
+
* throwing. Later resources may depend on earlier ones, and a resource that
|
|
1036
|
+
* refuses to shut down cleanly must not strand its siblings. The caller
|
|
1037
|
+
* aggregates the collected errors.
|
|
1038
|
+
*/
|
|
931
1039
|
async dispose(t) {
|
|
932
1040
|
try {
|
|
933
1041
|
for (const e of [...this.#t].reverse())
|
|
@@ -942,11 +1050,26 @@ class w {
|
|
|
942
1050
|
this.#e = void 0;
|
|
943
1051
|
}
|
|
944
1052
|
}
|
|
1053
|
+
/** Capability withdrawal must finish without yielding to callbacks or tasks. */
|
|
1054
|
+
disposeSynchronously(t) {
|
|
1055
|
+
try {
|
|
1056
|
+
for (const e of [...this.#t].reverse())
|
|
1057
|
+
try {
|
|
1058
|
+
e.dispose();
|
|
1059
|
+
} catch (i) {
|
|
1060
|
+
t.push(i);
|
|
1061
|
+
} finally {
|
|
1062
|
+
this.release(e);
|
|
1063
|
+
}
|
|
1064
|
+
} finally {
|
|
1065
|
+
this.#e = void 0;
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
945
1068
|
[Symbol.iterator]() {
|
|
946
1069
|
return this.#t[Symbol.iterator]();
|
|
947
1070
|
}
|
|
948
1071
|
}
|
|
949
|
-
class
|
|
1072
|
+
class re {
|
|
950
1073
|
#t;
|
|
951
1074
|
constructor(t, e) {
|
|
952
1075
|
this.#t = { phase: "active", cleanup: t, detachFromParent: e }, Object.freeze(this);
|
|
@@ -966,11 +1089,11 @@ class qt {
|
|
|
966
1089
|
});
|
|
967
1090
|
return this.#t = { phase: "disposing", completion: e }, e;
|
|
968
1091
|
}
|
|
969
|
-
[
|
|
1092
|
+
[F]() {
|
|
970
1093
|
return this.dispose();
|
|
971
1094
|
}
|
|
972
1095
|
}
|
|
973
|
-
class
|
|
1096
|
+
class ne {
|
|
974
1097
|
#t;
|
|
975
1098
|
#e;
|
|
976
1099
|
#i;
|
|
@@ -983,7 +1106,7 @@ class Bt {
|
|
|
983
1106
|
() => this.#s(),
|
|
984
1107
|
(a) => {
|
|
985
1108
|
try {
|
|
986
|
-
|
|
1109
|
+
wt(n.signal, a) || i(a);
|
|
987
1110
|
} finally {
|
|
988
1111
|
this.#s();
|
|
989
1112
|
}
|
|
@@ -1001,9 +1124,9 @@ class Bt {
|
|
|
1001
1124
|
() => {
|
|
1002
1125
|
}
|
|
1003
1126
|
);
|
|
1004
|
-
return this.#i = { phase: "disposing", completion: e }, t.controller.abort(
|
|
1127
|
+
return this.#i = { phase: "disposing", completion: e }, t.controller.abort(W), this.#n(), e;
|
|
1005
1128
|
}
|
|
1006
|
-
[
|
|
1129
|
+
[F]() {
|
|
1007
1130
|
return this.dispose();
|
|
1008
1131
|
}
|
|
1009
1132
|
#s() {
|
|
@@ -1017,7 +1140,7 @@ class Bt {
|
|
|
1017
1140
|
this.#t = void 0, t?.();
|
|
1018
1141
|
}
|
|
1019
1142
|
}
|
|
1020
|
-
class
|
|
1143
|
+
class tt {
|
|
1021
1144
|
#t;
|
|
1022
1145
|
#e;
|
|
1023
1146
|
#i;
|
|
@@ -1026,45 +1149,45 @@ class B {
|
|
|
1026
1149
|
#a;
|
|
1027
1150
|
#r;
|
|
1028
1151
|
#o;
|
|
1029
|
-
#
|
|
1030
|
-
#
|
|
1031
|
-
#l;
|
|
1152
|
+
#h;
|
|
1153
|
+
#p;
|
|
1032
1154
|
#u;
|
|
1155
|
+
#f;
|
|
1033
1156
|
handle;
|
|
1034
|
-
#
|
|
1157
|
+
#c;
|
|
1035
1158
|
constructor(t, e, i = {}) {
|
|
1036
|
-
this.#e = e, this.handle = new
|
|
1159
|
+
this.#e = e, this.handle = new oe(this);
|
|
1037
1160
|
const s = new AbortController();
|
|
1038
|
-
this.#
|
|
1161
|
+
this.#c = {
|
|
1039
1162
|
phase: "active",
|
|
1040
1163
|
controller: s,
|
|
1041
1164
|
declarations: i.declarations ?? "staged"
|
|
1042
1165
|
};
|
|
1043
1166
|
const n = i.parent;
|
|
1044
|
-
this.#
|
|
1045
|
-
const o = n?.diagnostics ?? new
|
|
1167
|
+
this.#f = n?.detach, this.#p = n ? "child" : "root";
|
|
1168
|
+
const o = n?.diagnostics ?? new ie(e, (l) => t.report(l)), a = n?.diagnosticNode ?? o.root;
|
|
1046
1169
|
this.#t = { port: t, diagnostics: o, diagnosticNode: a };
|
|
1047
1170
|
const h = (l) => ({
|
|
1048
1171
|
diagnostics: o,
|
|
1049
1172
|
node: a,
|
|
1050
1173
|
kind: l
|
|
1051
1174
|
});
|
|
1052
|
-
this.#i = new
|
|
1175
|
+
this.#i = new y(h("listeners")), this.#s = new y(h("contributions")), this.#n = new y(h("contributionViews")), this.#a = new y(h("subscriptions")), this.#r = new y(h("tasks")), this.#o = new y(), this.#h = new y(h("cleanups"));
|
|
1053
1176
|
const c = i.parentSignal;
|
|
1054
1177
|
if (!c) return;
|
|
1055
1178
|
const d = () => s.abort(c.reason);
|
|
1056
|
-
c.addEventListener("abort", d, { once: !0 }), this.#
|
|
1179
|
+
c.addEventListener("abort", d, { once: !0 }), this.#u = () => c.removeEventListener("abort", d), c.aborted && d();
|
|
1057
1180
|
}
|
|
1058
1181
|
get signal() {
|
|
1059
|
-
const t = this.#
|
|
1182
|
+
const t = this.#c;
|
|
1060
1183
|
return t.phase === "disposed" ? t.signal : t.controller.signal;
|
|
1061
1184
|
}
|
|
1062
1185
|
get diagnostics() {
|
|
1063
|
-
return this.#
|
|
1186
|
+
return this.#g().diagnostics.view;
|
|
1064
1187
|
}
|
|
1065
1188
|
/** A facade whose only InstanceCoordinator edge disappears when this Lifetime terminates. */
|
|
1066
1189
|
contextLogger(t) {
|
|
1067
|
-
const e = (i) => (s, ...n) => this.#
|
|
1190
|
+
const e = (i) => (s, ...n) => this.#g().port.writeLog(i, s, t, n);
|
|
1068
1191
|
return Object.freeze({
|
|
1069
1192
|
debug: e("debug"),
|
|
1070
1193
|
info: e("info"),
|
|
@@ -1073,16 +1196,25 @@ class B {
|
|
|
1073
1196
|
});
|
|
1074
1197
|
}
|
|
1075
1198
|
cleanup(t) {
|
|
1076
|
-
if (this.#
|
|
1077
|
-
const e = new
|
|
1078
|
-
return this.#
|
|
1079
|
-
}
|
|
1199
|
+
if (this.#d(), typeof t != "function") throw new TypeError("Cleanup must be a function");
|
|
1200
|
+
const e = new re(t, this.#h.release);
|
|
1201
|
+
return this.#h.add(e), e;
|
|
1202
|
+
}
|
|
1203
|
+
/**
|
|
1204
|
+
* A child scope. It inherits this Lifetime's signal, so cancellation flows
|
|
1205
|
+
* down, and its declaration phase, so a child created during `setup()` also
|
|
1206
|
+
* stages rather than publishing immediately.
|
|
1207
|
+
*
|
|
1208
|
+
* Disposing a child detaches it from both the resource set and the diagnostics
|
|
1209
|
+
* tree. A Plugin can therefore use child lifetimes as a unit of work — one per
|
|
1210
|
+
* open document, per connection — without the parent growing.
|
|
1211
|
+
*/
|
|
1080
1212
|
lifetime(t) {
|
|
1081
|
-
const { port: e, diagnostics: i, diagnosticNode: s } = this.#
|
|
1082
|
-
|
|
1083
|
-
const n = i.createNode(t), o = new
|
|
1213
|
+
const { port: e, diagnostics: i, diagnosticNode: s } = this.#d();
|
|
1214
|
+
ae(t);
|
|
1215
|
+
const n = i.createNode(t), o = new tt(e, this.#e, {
|
|
1084
1216
|
parentSignal: this.signal,
|
|
1085
|
-
declarations: this.#
|
|
1217
|
+
declarations: this.#w(),
|
|
1086
1218
|
parent: {
|
|
1087
1219
|
diagnostics: i,
|
|
1088
1220
|
diagnosticNode: n,
|
|
@@ -1094,9 +1226,9 @@ class B {
|
|
|
1094
1226
|
return this.#o.add(o), i.attach(s, n), o.handle;
|
|
1095
1227
|
}
|
|
1096
1228
|
spawn(t) {
|
|
1097
|
-
const { port: e } = this.#
|
|
1229
|
+
const { port: e } = this.#d();
|
|
1098
1230
|
if (typeof t != "function") throw new TypeError("Background task must be a function");
|
|
1099
|
-
const i = new
|
|
1231
|
+
const i = new ne(
|
|
1100
1232
|
this.signal,
|
|
1101
1233
|
t,
|
|
1102
1234
|
(s) => e.report(s),
|
|
@@ -1105,89 +1237,137 @@ class B {
|
|
|
1105
1237
|
return this.#r.add(i), i;
|
|
1106
1238
|
}
|
|
1107
1239
|
on(t, e) {
|
|
1108
|
-
const { port: i } = this.#
|
|
1240
|
+
const { port: i } = this.#d(), s = i.stageOn(
|
|
1109
1241
|
this.#e,
|
|
1110
1242
|
t,
|
|
1111
1243
|
e,
|
|
1112
1244
|
this.#i.release
|
|
1113
1245
|
);
|
|
1114
|
-
return this.#i.add(s), this.#
|
|
1246
|
+
return this.#i.add(s), this.#w() === "published" && s.publish(), s.handle;
|
|
1115
1247
|
}
|
|
1116
1248
|
async emit(t, ...e) {
|
|
1117
|
-
const { port: i } = this.#
|
|
1249
|
+
const { port: i } = this.#d();
|
|
1118
1250
|
await i.emit(this.#e, t, e[0]);
|
|
1119
1251
|
}
|
|
1120
1252
|
contribute(t, e, i) {
|
|
1121
|
-
const { port: s } = this.#
|
|
1253
|
+
const { port: s } = this.#d(), n = s.stageContribution(
|
|
1122
1254
|
this.#e,
|
|
1123
1255
|
t,
|
|
1124
1256
|
e,
|
|
1125
1257
|
i,
|
|
1126
1258
|
this.#s.release
|
|
1127
1259
|
);
|
|
1128
|
-
return this.#s.add(n), this.#
|
|
1260
|
+
return this.#s.add(n), this.#w() === "published" && n.publish(), n.handle;
|
|
1129
1261
|
}
|
|
1130
1262
|
/** Owns an internal live capability without exposing a second Context API. */
|
|
1131
1263
|
ownLease(t, e) {
|
|
1132
|
-
return this.#
|
|
1264
|
+
return this.#d(), (e === "view" ? this.#n : this.#a).own(t);
|
|
1133
1265
|
}
|
|
1134
1266
|
/** Releases a temporary startup cancellation edge after its layer commits. */
|
|
1135
1267
|
detachStartupSignal() {
|
|
1136
|
-
const t = this.#
|
|
1137
|
-
this.#
|
|
1138
|
-
}
|
|
1139
|
-
/**
|
|
1268
|
+
const t = this.#u;
|
|
1269
|
+
this.#u = void 0, t?.();
|
|
1270
|
+
}
|
|
1271
|
+
/**
|
|
1272
|
+
* Atomically makes all declarations staged during setup visible.
|
|
1273
|
+
*
|
|
1274
|
+
* Children publish too, recursively, so a Lifetime created inside `setup()`
|
|
1275
|
+
* becomes visible with its parent rather than being stranded staged. Called by
|
|
1276
|
+
* the InstanceCoordinator once the whole activation layer has succeeded —
|
|
1277
|
+
* which is what makes "no half-built Instance is observable" true.
|
|
1278
|
+
*/
|
|
1140
1279
|
publish() {
|
|
1141
|
-
const t = this.#
|
|
1142
|
-
if (t.phase !== "active") throw
|
|
1143
|
-
if (this.#
|
|
1280
|
+
const t = this.#c;
|
|
1281
|
+
if (t.phase !== "active") throw $();
|
|
1282
|
+
if (this.#d(), t.declarations !== "published") {
|
|
1144
1283
|
for (const e of this.#i) e.publish();
|
|
1145
1284
|
for (const e of this.#s) e.publish();
|
|
1146
1285
|
for (const e of this.#o) e.publish();
|
|
1147
|
-
this.#
|
|
1286
|
+
this.#c = { ...t, declarations: "published" };
|
|
1148
1287
|
}
|
|
1149
1288
|
}
|
|
1289
|
+
/**
|
|
1290
|
+
* Disposal is idempotent and joinable: concurrent callers share one completion
|
|
1291
|
+
* promise, so a Lifetime disposed by both its owner and a `using` block runs
|
|
1292
|
+
* its teardown once.
|
|
1293
|
+
*
|
|
1294
|
+
* The three-stage order is the module header's; see it for why. Errors from
|
|
1295
|
+
* every stage accumulate and are aggregated at the end, so one failing cleanup
|
|
1296
|
+
* neither hides the others nor prevents them from running.
|
|
1297
|
+
*/
|
|
1150
1298
|
dispose() {
|
|
1151
|
-
const t = this.#
|
|
1299
|
+
const t = this.#c;
|
|
1152
1300
|
if (t.phase === "disposing") return t.completion;
|
|
1153
1301
|
if (t.phase === "disposed") return Promise.resolve();
|
|
1154
|
-
const e =
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
s?.(this), this.#f === "root" && e.diagnostics.finishRoot();
|
|
1164
|
-
} finally {
|
|
1165
|
-
this.#t = void 0;
|
|
1166
|
-
}
|
|
1167
|
-
});
|
|
1168
|
-
return this.#h = { phase: "disposing", controller: t.controller, completion: i }, e.diagnostics.beginDisposing(e.diagnosticNode), i;
|
|
1302
|
+
const e = [], i = this.#l(e);
|
|
1303
|
+
for (const { lifetime: s, errors: n } of e)
|
|
1304
|
+
s.#i.disposeSynchronously(n), s.#a.disposeSynchronously(n), s.#n.disposeSynchronously(n);
|
|
1305
|
+
for (const { lifetime: s, errors: n } of e)
|
|
1306
|
+
s.#s.disposeSynchronously(n);
|
|
1307
|
+
for (const { lifetime: s, binding: n, controller: o } of e)
|
|
1308
|
+
n.diagnostics.beginDisposing(n.diagnosticNode), o.abort(W), s.detachStartupSignal();
|
|
1309
|
+
for (const s of e) s.finish();
|
|
1310
|
+
return i;
|
|
1169
1311
|
}
|
|
1170
|
-
|
|
1312
|
+
/** Stages joinable completions without running any externally observable work. */
|
|
1313
|
+
#l(t) {
|
|
1314
|
+
const e = this.#c;
|
|
1315
|
+
if (e.phase === "disposing") return e.completion;
|
|
1316
|
+
if (e.phase === "disposed") return Promise.resolve();
|
|
1317
|
+
const i = this.#g(), s = Promise.withResolvers(), n = [];
|
|
1318
|
+
this.#c = {
|
|
1319
|
+
phase: "disposing",
|
|
1320
|
+
controller: e.controller,
|
|
1321
|
+
completion: s.promise
|
|
1322
|
+
};
|
|
1323
|
+
const o = Promise.allSettled(
|
|
1324
|
+
[...this.#o].reverse().map((h) => h.#l(t))
|
|
1325
|
+
), a = () => {
|
|
1326
|
+
(async () => {
|
|
1327
|
+
try {
|
|
1328
|
+
await this.#r.dispose(n);
|
|
1329
|
+
for (const h of await o)
|
|
1330
|
+
h.status === "rejected" && n.push(h.reason);
|
|
1331
|
+
if (await this.#h.dispose(n), n.length === 1) throw n[0];
|
|
1332
|
+
if (n.length > 1) throw new AggregateError(n, "Lifetime cleanup failed");
|
|
1333
|
+
} finally {
|
|
1334
|
+
this.#c = { phase: "disposed", signal: AbortSignal.abort(W) };
|
|
1335
|
+
const h = this.#f;
|
|
1336
|
+
this.#f = void 0;
|
|
1337
|
+
try {
|
|
1338
|
+
h?.(this), this.#p === "root" && i.diagnostics.finishRoot();
|
|
1339
|
+
} finally {
|
|
1340
|
+
this.#t = void 0;
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
})().then(s.resolve, s.reject);
|
|
1344
|
+
};
|
|
1345
|
+
return t.push({ lifetime: this, errors: n, binding: i, controller: e.controller, finish: a }), s.promise;
|
|
1346
|
+
}
|
|
1347
|
+
[F]() {
|
|
1171
1348
|
return this.dispose();
|
|
1172
1349
|
}
|
|
1173
|
-
|
|
1350
|
+
// The gate on every operation that creates a resource. `signal.aborted` is
|
|
1351
|
+
// checked as well as the phase, because a parent's disposal aborts this signal
|
|
1352
|
+
// during startup cancellation as well as disposal. Both boundaries close work.
|
|
1353
|
+
#d() {
|
|
1174
1354
|
const t = this.#t;
|
|
1175
|
-
if (this.#
|
|
1176
|
-
throw
|
|
1355
|
+
if (this.#c.phase !== "active" || this.signal.aborted || !t)
|
|
1356
|
+
throw $();
|
|
1177
1357
|
return t;
|
|
1178
1358
|
}
|
|
1179
|
-
#
|
|
1359
|
+
#g() {
|
|
1180
1360
|
const t = this.#t;
|
|
1181
|
-
if (!t) throw
|
|
1361
|
+
if (!t) throw $();
|
|
1182
1362
|
return t;
|
|
1183
1363
|
}
|
|
1184
|
-
#
|
|
1185
|
-
const t = this.#
|
|
1186
|
-
if (t.phase !== "active") throw
|
|
1364
|
+
#w() {
|
|
1365
|
+
const t = this.#c;
|
|
1366
|
+
if (t.phase !== "active") throw $();
|
|
1187
1367
|
return t.declarations;
|
|
1188
1368
|
}
|
|
1189
1369
|
}
|
|
1190
|
-
class
|
|
1370
|
+
class oe {
|
|
1191
1371
|
#t;
|
|
1192
1372
|
constructor(t) {
|
|
1193
1373
|
this.#t = t, Object.freeze(this);
|
|
@@ -1216,32 +1396,32 @@ class Ft {
|
|
|
1216
1396
|
dispose() {
|
|
1217
1397
|
return this.#t.dispose();
|
|
1218
1398
|
}
|
|
1219
|
-
[
|
|
1399
|
+
[F]() {
|
|
1220
1400
|
return this.dispose();
|
|
1221
1401
|
}
|
|
1222
1402
|
}
|
|
1223
|
-
function
|
|
1403
|
+
function ae(r) {
|
|
1224
1404
|
if (typeof r != "string" || !r.trim())
|
|
1225
1405
|
throw new TypeError("Lifetime label must be a non-empty string");
|
|
1226
1406
|
if (r !== r.trim())
|
|
1227
1407
|
throw new TypeError("Lifetime label cannot start or end with whitespace");
|
|
1228
1408
|
}
|
|
1229
|
-
function
|
|
1409
|
+
function $() {
|
|
1230
1410
|
return new u("LIFETIME_DISPOSED", "Lifetime is disposing or has been disposed");
|
|
1231
1411
|
}
|
|
1232
|
-
class
|
|
1412
|
+
class Y extends AggregateError {
|
|
1233
1413
|
}
|
|
1234
|
-
class
|
|
1414
|
+
class ce {
|
|
1235
1415
|
#t;
|
|
1236
1416
|
#e;
|
|
1237
1417
|
#i;
|
|
1238
1418
|
#s;
|
|
1239
1419
|
#n = /* @__PURE__ */ new Map();
|
|
1240
|
-
#a = new
|
|
1420
|
+
#a = new ee();
|
|
1241
1421
|
#r;
|
|
1242
1422
|
#o = [];
|
|
1243
1423
|
constructor(t) {
|
|
1244
|
-
this.#t = t.hostName, this.#e = t.logger, this.#i = t.isInstalled, this.#s = t.report, this.#r = new
|
|
1424
|
+
this.#t = t.hostName, this.#e = t.logger, this.#i = t.isInstalled, this.#s = t.report, this.#r = new Qt(t.report);
|
|
1245
1425
|
}
|
|
1246
1426
|
readService(t, e) {
|
|
1247
1427
|
const i = this.#n.get(t);
|
|
@@ -1268,7 +1448,7 @@ class Ut {
|
|
|
1268
1448
|
return this.deactivate(new Set(this.#o));
|
|
1269
1449
|
}
|
|
1270
1450
|
async activate(t, e, i, s) {
|
|
1271
|
-
const n = this.#
|
|
1451
|
+
const n = this.#l(s);
|
|
1272
1452
|
for (const o of t.layers) {
|
|
1273
1453
|
const a = o.filter(
|
|
1274
1454
|
(f) => e.has(f) && !f.instance
|
|
@@ -1277,35 +1457,39 @@ class Ut {
|
|
|
1277
1457
|
const h = new AbortController(), c = await Promise.allSettled(
|
|
1278
1458
|
a.map(async (f) => {
|
|
1279
1459
|
try {
|
|
1280
|
-
|
|
1281
|
-
f.
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
);
|
|
1285
|
-
return await this.#d(
|
|
1460
|
+
if (!i.has(f))
|
|
1461
|
+
throw new Error(`Installation '${f.id}' has no prepared config`);
|
|
1462
|
+
const g = i.get(f);
|
|
1463
|
+
return await this.#h(
|
|
1286
1464
|
t,
|
|
1287
1465
|
f,
|
|
1288
|
-
|
|
1466
|
+
g,
|
|
1289
1467
|
h.signal,
|
|
1290
1468
|
n
|
|
1291
1469
|
);
|
|
1292
|
-
} catch (
|
|
1293
|
-
throw h.abort(
|
|
1470
|
+
} catch (g) {
|
|
1471
|
+
throw h.abort(g), g;
|
|
1294
1472
|
}
|
|
1295
1473
|
})
|
|
1296
|
-
), d =
|
|
1474
|
+
), d = he(c, h.signal), l = c.filter(
|
|
1297
1475
|
(f) => f.status === "fulfilled"
|
|
1298
1476
|
).map((f) => f.value);
|
|
1299
1477
|
if (d.length) {
|
|
1300
|
-
const f = await this.#
|
|
1301
|
-
throw f.length ? new
|
|
1302
|
-
[
|
|
1478
|
+
const f = await this.#u(l), g = d.length === 1 ? d[0] : new AggregateError(d, "Installation startup layer failed");
|
|
1479
|
+
throw f.length ? new Y(
|
|
1480
|
+
[g, ...f],
|
|
1303
1481
|
"Installation startup layer failed and could not be cleanly disposed"
|
|
1304
|
-
) :
|
|
1482
|
+
) : g;
|
|
1305
1483
|
}
|
|
1306
|
-
this.#
|
|
1484
|
+
this.#p(l);
|
|
1307
1485
|
}
|
|
1308
1486
|
}
|
|
1487
|
+
/**
|
|
1488
|
+
* Stops in reverse activation order, sequentially, and collects every failure
|
|
1489
|
+
* instead of stopping at the first. A dependent must be gone before the
|
|
1490
|
+
* Service it consumed, and one Instance that refuses to shut down cleanly must
|
|
1491
|
+
* not leave the rest running — its error is returned, not thrown.
|
|
1492
|
+
*/
|
|
1309
1493
|
async deactivate(t) {
|
|
1310
1494
|
const e = [], i = this.#o.filter((s) => t.has(s)).reverse();
|
|
1311
1495
|
this.#o = this.#o.filter(
|
|
@@ -1326,6 +1510,17 @@ class Ut {
|
|
|
1326
1510
|
}
|
|
1327
1511
|
return e;
|
|
1328
1512
|
}
|
|
1513
|
+
/**
|
|
1514
|
+
* Runs one operation with contribution publication deferred to its end, so a
|
|
1515
|
+
* change that withdraws and adds contributions is observed once rather than as
|
|
1516
|
+
* an intermediate state.
|
|
1517
|
+
*
|
|
1518
|
+
* Publication happens even when the operation failed, because contributions
|
|
1519
|
+
* withdrawn by Instances that did stop must not stay visible. If both the
|
|
1520
|
+
* operation and the publication fail, both errors are reported — the
|
|
1521
|
+
* publication failure must not hide the reason the change failed, and the
|
|
1522
|
+
* operation failure must not hide a store left inconsistent.
|
|
1523
|
+
*/
|
|
1329
1524
|
async withContributionBatch(t) {
|
|
1330
1525
|
this.#r.beginBatch();
|
|
1331
1526
|
let e;
|
|
@@ -1349,23 +1544,23 @@ class Ut {
|
|
|
1349
1544
|
if (!i.ok) throw i.error;
|
|
1350
1545
|
return e.value;
|
|
1351
1546
|
}
|
|
1352
|
-
async #
|
|
1547
|
+
async #h(t, e, i, s, n) {
|
|
1353
1548
|
e.deactivate();
|
|
1354
|
-
const o = e.
|
|
1549
|
+
const o = t.declarationFor(e).plugin, a = new tt(n, e.id, { parentSignal: s });
|
|
1355
1550
|
try {
|
|
1356
|
-
const h = this.#
|
|
1551
|
+
const h = this.#f(t, e, o, a), c = Object.freeze({
|
|
1357
1552
|
hostName: this.#t,
|
|
1358
1553
|
pluginName: o.name,
|
|
1359
1554
|
installationId: e.id,
|
|
1360
1555
|
groupId: e.groupId
|
|
1361
|
-
}), d = this.#
|
|
1362
|
-
for (const [
|
|
1363
|
-
if (typeof l != "object" || l === null || !Object.hasOwn(l,
|
|
1556
|
+
}), d = this.#c(a, c, h), l = await o.setup(d, i), f = /* @__PURE__ */ new Map();
|
|
1557
|
+
for (const [g, I] of Object.entries(o.provides)) {
|
|
1558
|
+
if (typeof l != "object" || l === null || !Object.hasOwn(l, g))
|
|
1364
1559
|
throw new u(
|
|
1365
1560
|
"SERVICE_NOT_RETURNED",
|
|
1366
|
-
`Installation '${e.id}' did not return provided Service '${
|
|
1561
|
+
`Installation '${e.id}' did not return provided Service '${g}'`
|
|
1367
1562
|
);
|
|
1368
|
-
f.set(
|
|
1563
|
+
f.set(I.id, l[g]);
|
|
1369
1564
|
}
|
|
1370
1565
|
return Object.freeze({
|
|
1371
1566
|
installation: e,
|
|
@@ -1377,7 +1572,7 @@ class Ut {
|
|
|
1377
1572
|
try {
|
|
1378
1573
|
await a.dispose();
|
|
1379
1574
|
} catch (d) {
|
|
1380
|
-
throw new
|
|
1575
|
+
throw new Y(
|
|
1381
1576
|
[c, d],
|
|
1382
1577
|
`Installation '${e.id}' failed to start and could not be cleanly disposed`
|
|
1383
1578
|
);
|
|
@@ -1385,13 +1580,13 @@ class Ut {
|
|
|
1385
1580
|
throw c;
|
|
1386
1581
|
}
|
|
1387
1582
|
}
|
|
1388
|
-
#
|
|
1583
|
+
#p(t) {
|
|
1389
1584
|
for (const { installation: e, instance: i, services: s } of t)
|
|
1390
1585
|
this.#n.set(e, s), e.activate(i), this.#o.push(e);
|
|
1391
1586
|
for (const { instance: e } of t)
|
|
1392
1587
|
e.lifetime.publish(), e.lifetime.detachStartupSignal();
|
|
1393
1588
|
}
|
|
1394
|
-
async #
|
|
1589
|
+
async #u(t) {
|
|
1395
1590
|
const e = [];
|
|
1396
1591
|
for (const i of [...t].reverse())
|
|
1397
1592
|
try {
|
|
@@ -1401,9 +1596,9 @@ class Ut {
|
|
|
1401
1596
|
}
|
|
1402
1597
|
return e;
|
|
1403
1598
|
}
|
|
1404
|
-
#
|
|
1599
|
+
#f(t, e, i, s) {
|
|
1405
1600
|
const n = /* @__PURE__ */ Object.create(null);
|
|
1406
|
-
for (const [o, a] of Object.entries(i.requires
|
|
1601
|
+
for (const [o, a] of Object.entries(i.requires))
|
|
1407
1602
|
if (a.kind === "optional") {
|
|
1408
1603
|
const h = t.providerFor(e, a.service.id);
|
|
1409
1604
|
if (!h) {
|
|
@@ -1426,10 +1621,10 @@ class Ut {
|
|
|
1426
1621
|
);
|
|
1427
1622
|
n[o] = c.get(a.id);
|
|
1428
1623
|
} else
|
|
1429
|
-
n[o] = this.#
|
|
1624
|
+
n[o] = this.#m(a, s);
|
|
1430
1625
|
return n;
|
|
1431
1626
|
}
|
|
1432
|
-
#
|
|
1627
|
+
#c(t, e, i) {
|
|
1433
1628
|
return Object.freeze({
|
|
1434
1629
|
...i,
|
|
1435
1630
|
get signal() {
|
|
@@ -1445,13 +1640,13 @@ class Ut {
|
|
|
1445
1640
|
contribute: t.contribute.bind(t)
|
|
1446
1641
|
});
|
|
1447
1642
|
}
|
|
1448
|
-
#
|
|
1643
|
+
#l(t) {
|
|
1449
1644
|
return {
|
|
1450
|
-
stageOn: (e, i, s, n) => this.#
|
|
1645
|
+
stageOn: (e, i, s, n) => this.#d(e, i, s, n, t),
|
|
1451
1646
|
emit: (e, i, s) => this.#g(e, i, s, t),
|
|
1452
|
-
stageContribution: (e, i, s, n, o) => this.#
|
|
1647
|
+
stageContribution: (e, i, s, n, o) => this.#w(e, i, s, n, o, t),
|
|
1453
1648
|
writeLog: (e, i, s, n) => {
|
|
1454
|
-
|
|
1649
|
+
R(
|
|
1455
1650
|
this.#e[e](i, s, ...n),
|
|
1456
1651
|
"Logger methods must be synchronous"
|
|
1457
1652
|
);
|
|
@@ -1459,43 +1654,43 @@ class Ut {
|
|
|
1459
1654
|
report: this.#s
|
|
1460
1655
|
};
|
|
1461
1656
|
}
|
|
1462
|
-
#
|
|
1463
|
-
return this.#
|
|
1657
|
+
#d(t, e, i, s, n) {
|
|
1658
|
+
return this.#b(t), A(e, "event"), n.remember(e), this.#a.stage(e.id, i, s);
|
|
1464
1659
|
}
|
|
1465
1660
|
#g(t, e, i, s) {
|
|
1466
|
-
return this.#
|
|
1661
|
+
return this.#b(t), A(e, "event"), s.remember(e), this.#a.emit(e.id, i);
|
|
1467
1662
|
}
|
|
1468
|
-
#
|
|
1469
|
-
return this.#
|
|
1663
|
+
#w(t, e, i, s, n, o) {
|
|
1664
|
+
return this.#b(t), A(e, "extensionPoint"), o.remember(e), this.#r.get(e).stage(t, i, s, n);
|
|
1470
1665
|
}
|
|
1471
|
-
#
|
|
1666
|
+
#m(t, e) {
|
|
1472
1667
|
return this.#r.get(t).view((i, s) => e.ownLease(i, s));
|
|
1473
1668
|
}
|
|
1474
|
-
#
|
|
1669
|
+
#b(t) {
|
|
1475
1670
|
if (!this.#i(t))
|
|
1476
1671
|
throw new Error(`Installation '${t}' is not installed`);
|
|
1477
1672
|
}
|
|
1478
1673
|
}
|
|
1479
|
-
function
|
|
1674
|
+
function he(r, t) {
|
|
1480
1675
|
const e = [];
|
|
1481
1676
|
let i = !1;
|
|
1482
1677
|
for (const s of r)
|
|
1483
|
-
s.status !== "fulfilled" && (Object.is(s.reason, t.reason) ? (i || e.push(s.reason), i = !0) :
|
|
1678
|
+
s.status !== "fulfilled" && (Object.is(s.reason, t.reason) ? (i || e.push(s.reason), i = !0) : wt(t, s.reason) || e.push(s.reason));
|
|
1484
1679
|
return e;
|
|
1485
1680
|
}
|
|
1486
|
-
class
|
|
1487
|
-
#t = new
|
|
1681
|
+
class de {
|
|
1682
|
+
#t = new zt();
|
|
1488
1683
|
#e;
|
|
1489
1684
|
#i;
|
|
1490
1685
|
constructor(t) {
|
|
1491
|
-
this.#e = new
|
|
1686
|
+
this.#e = new ce(t);
|
|
1492
1687
|
}
|
|
1493
1688
|
get hasCommittedPlan() {
|
|
1494
1689
|
return this.#i !== void 0;
|
|
1495
1690
|
}
|
|
1496
1691
|
get(t, e) {
|
|
1497
|
-
const i =
|
|
1498
|
-
if (
|
|
1692
|
+
const i = jt(t), s = i ? t.service : t;
|
|
1693
|
+
if (A(s, "service"), this.#t.assertCompatible(s), e === "unavailable") throw ct();
|
|
1499
1694
|
const n = this.#o().provider(s.id);
|
|
1500
1695
|
if (!n) {
|
|
1501
1696
|
if (i) return;
|
|
@@ -1509,13 +1704,13 @@ class Ht {
|
|
|
1509
1704
|
return o.value;
|
|
1510
1705
|
}
|
|
1511
1706
|
contributions(t) {
|
|
1512
|
-
return
|
|
1707
|
+
return A(t, "extensionPoint"), this.#t.remember(t), this.#e.contributions(t);
|
|
1513
1708
|
}
|
|
1514
1709
|
buildPlan(t) {
|
|
1515
|
-
return
|
|
1710
|
+
return X.build(t, this.#t.kinds);
|
|
1516
1711
|
}
|
|
1517
1712
|
async start(t) {
|
|
1518
|
-
const e = this.#t.
|
|
1713
|
+
const e = this.#t.writer(t.contractKinds);
|
|
1519
1714
|
try {
|
|
1520
1715
|
await this.#e.withContributionBatch(() => this.#s(t, e)), this.#i = t;
|
|
1521
1716
|
} catch (i) {
|
|
@@ -1528,14 +1723,29 @@ class Ht {
|
|
|
1528
1723
|
);
|
|
1529
1724
|
return this.#i = void 0, t;
|
|
1530
1725
|
}
|
|
1726
|
+
/**
|
|
1727
|
+
* The whole transaction, in the order the steps have to happen.
|
|
1728
|
+
*
|
|
1729
|
+
* Configs resolve and Contract identities draft *before* anything stops,
|
|
1730
|
+
* because those are the failures that can still be taken back for free — a
|
|
1731
|
+
* schema rejection at this point costs nothing. Once the affected Instances
|
|
1732
|
+
* are down, every remaining failure has a price, and the only question left is
|
|
1733
|
+
* whether the previous state can be restored.
|
|
1734
|
+
*
|
|
1735
|
+
* The whole body runs inside one contribution batch, so contributions
|
|
1736
|
+
* withdrawn by stopping Instances and added by starting ones become visible in
|
|
1737
|
+
* a single step. Without it, an ExtensionPoint observer would see the set
|
|
1738
|
+
* briefly empty in the middle of a successful change.
|
|
1739
|
+
*/
|
|
1531
1740
|
async transition(t, e, i) {
|
|
1532
1741
|
return this.#e.withContributionBatch(async () => {
|
|
1533
1742
|
const s = this.#o(), n = s.affectedByTransitionTo(t, e);
|
|
1534
1743
|
let o, a;
|
|
1535
1744
|
try {
|
|
1536
1745
|
o = await this.#r(
|
|
1746
|
+
t,
|
|
1537
1747
|
t.order.filter((d) => n.has(d))
|
|
1538
|
-
), a = this.#t.
|
|
1748
|
+
), a = this.#t.writer(t.contractKinds);
|
|
1539
1749
|
} catch (d) {
|
|
1540
1750
|
throw i(), d;
|
|
1541
1751
|
}
|
|
@@ -1550,7 +1760,7 @@ class Ht {
|
|
|
1550
1760
|
return await this.#e.activate(t, n, o, a), a.commit(), this.#e.commitActivationOrder(t.order), this.#i = t, Object.freeze({ kind: "committed", affected: n });
|
|
1551
1761
|
} catch (d) {
|
|
1552
1762
|
const l = await this.#e.deactivate(n);
|
|
1553
|
-
return a.discard(), d instanceof
|
|
1763
|
+
return a.discard(), d instanceof Y || l.length ? this.#n(
|
|
1554
1764
|
i,
|
|
1555
1765
|
[d, ...l],
|
|
1556
1766
|
"Installation change failed and its partial activation could not be cleanly disposed"
|
|
@@ -1562,7 +1772,7 @@ class Ht {
|
|
|
1562
1772
|
});
|
|
1563
1773
|
}
|
|
1564
1774
|
async #s(t, e) {
|
|
1565
|
-
const i = new Set(t.order), s = await this.#r(t.order);
|
|
1775
|
+
const i = new Set(t.order), s = await this.#r(t, t.order);
|
|
1566
1776
|
this.#e.resetActivationState();
|
|
1567
1777
|
try {
|
|
1568
1778
|
await this.#e.activate(t, i, s, e), e.commit(), this.#e.commitActivationOrder(t.order);
|
|
@@ -1571,14 +1781,30 @@ class Ht {
|
|
|
1571
1781
|
throw o.length ? new AggregateError([n, ...o], "Host startup failed") : n;
|
|
1572
1782
|
}
|
|
1573
1783
|
}
|
|
1784
|
+
/**
|
|
1785
|
+
* The last level: no consistent graph could be reached, so none is presented.
|
|
1786
|
+
*
|
|
1787
|
+
* Everything stops and `#plan` is cleared, which drops the Host to `idle` and
|
|
1788
|
+
* closes reads. The AggregateError carries every cause — the original failure
|
|
1789
|
+
* first, then whatever shutdown itself hit. Nothing is swallowed here; the
|
|
1790
|
+
* point of failing closed is that the report is complete.
|
|
1791
|
+
*/
|
|
1574
1792
|
async #n(t, e, i) {
|
|
1575
1793
|
t();
|
|
1576
1794
|
const s = await this.#e.deactivateAll();
|
|
1577
1795
|
throw this.#i = void 0, new AggregateError([...e, ...s], i);
|
|
1578
1796
|
}
|
|
1797
|
+
/**
|
|
1798
|
+
* Restores the previous plan using the configs captured before the change, not
|
|
1799
|
+
* mutable records. Declaration versions belong to the plan; re-validating
|
|
1800
|
+
* configs could fail for a second,
|
|
1801
|
+
* unrelated reason while trying to recover from the first.
|
|
1802
|
+
*
|
|
1803
|
+
* A rollback that itself fails escalates to fail-closed by throwing.
|
|
1804
|
+
*/
|
|
1579
1805
|
async #a(t, e, i, s, n) {
|
|
1580
1806
|
t();
|
|
1581
|
-
const o = this.#t.
|
|
1807
|
+
const o = this.#t.writer(e.contractKinds);
|
|
1582
1808
|
try {
|
|
1583
1809
|
await this.#e.activate(e, i, s, o), o.commit(), this.#e.commitActivationOrder(e.order), this.#i = e;
|
|
1584
1810
|
} catch (h) {
|
|
@@ -1591,48 +1817,47 @@ class Ht {
|
|
|
1591
1817
|
const a = n.length === 1 ? n[0] : new AggregateError(n, "Installation change failed");
|
|
1592
1818
|
return Object.freeze({ kind: "rolled-back", affected: i, error: a });
|
|
1593
1819
|
}
|
|
1594
|
-
async #r(t) {
|
|
1595
|
-
const
|
|
1596
|
-
for (const
|
|
1820
|
+
async #r(t, e) {
|
|
1821
|
+
const i = /* @__PURE__ */ new Map();
|
|
1822
|
+
for (const s of e)
|
|
1597
1823
|
try {
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
await et(
|
|
1601
|
-
i.declaration.plugin.config,
|
|
1602
|
-
i.declaration.config,
|
|
1603
|
-
i.id
|
|
1604
|
-
)
|
|
1605
|
-
);
|
|
1606
|
-
} catch (s) {
|
|
1607
|
-
throw $(
|
|
1824
|
+
const n = t.declarationFor(s);
|
|
1825
|
+
i.set(
|
|
1608
1826
|
s,
|
|
1827
|
+
await Lt(n.plugin.config, n.config, s.id)
|
|
1828
|
+
);
|
|
1829
|
+
} catch (n) {
|
|
1830
|
+
throw V(
|
|
1831
|
+
n,
|
|
1609
1832
|
"INSTALLATION_UNAVAILABLE",
|
|
1610
|
-
`Installation '${
|
|
1833
|
+
`Installation '${s.id}' failed with a non-Error value`
|
|
1611
1834
|
);
|
|
1612
1835
|
}
|
|
1613
|
-
return
|
|
1836
|
+
return i;
|
|
1614
1837
|
}
|
|
1615
1838
|
#o() {
|
|
1616
|
-
if (!this.#i) throw
|
|
1839
|
+
if (!this.#i) throw ct();
|
|
1617
1840
|
return this.#i;
|
|
1618
1841
|
}
|
|
1619
1842
|
}
|
|
1620
|
-
function
|
|
1843
|
+
function ct() {
|
|
1621
1844
|
return new u("SERVICE_UNAVAILABLE", "Host services are not active");
|
|
1622
1845
|
}
|
|
1623
|
-
class
|
|
1846
|
+
class le {
|
|
1624
1847
|
#t;
|
|
1625
1848
|
#e;
|
|
1626
|
-
#i;
|
|
1627
|
-
#s = 0;
|
|
1849
|
+
#i = 0;
|
|
1628
1850
|
view;
|
|
1629
1851
|
constructor(t, e, i) {
|
|
1630
|
-
this.#t = t, this.#
|
|
1852
|
+
this.#t = t, this.#e = new Z(() => {
|
|
1853
|
+
const { status: s, installations: n, groups: o } = e();
|
|
1854
|
+
return this.#s(s, n, o);
|
|
1855
|
+
}, i), this.view = this.#e.view;
|
|
1631
1856
|
}
|
|
1632
|
-
publish(
|
|
1633
|
-
this.#
|
|
1857
|
+
publish() {
|
|
1858
|
+
this.#i++, this.#e.invalidate();
|
|
1634
1859
|
}
|
|
1635
|
-
#
|
|
1860
|
+
#s(t, e, i) {
|
|
1636
1861
|
const s = /* @__PURE__ */ new Map();
|
|
1637
1862
|
for (const o of e) {
|
|
1638
1863
|
const a = {
|
|
@@ -1641,10 +1866,10 @@ class Kt {
|
|
|
1641
1866
|
groupId: o.groupId,
|
|
1642
1867
|
status: o.status,
|
|
1643
1868
|
requires: Object.freeze(
|
|
1644
|
-
Object.values(o.declaration.plugin.requires
|
|
1869
|
+
Object.values(o.declaration.plugin.requires).map((c) => c.kind === "optional" ? c.service.id : c.id)
|
|
1645
1870
|
),
|
|
1646
1871
|
provides: Object.freeze(
|
|
1647
|
-
Object.values(o.declaration.plugin.provides
|
|
1872
|
+
Object.values(o.declaration.plugin.provides).map((c) => c.id)
|
|
1648
1873
|
),
|
|
1649
1874
|
...o.instance ? { lifetime: o.instance.lifetime.diagnostics } : {}
|
|
1650
1875
|
}, h = o.error;
|
|
@@ -1664,32 +1889,32 @@ class Kt {
|
|
|
1664
1889
|
return Object.freeze({
|
|
1665
1890
|
name: this.#t,
|
|
1666
1891
|
status: t,
|
|
1667
|
-
revision: this.#
|
|
1668
|
-
installations: new
|
|
1669
|
-
groups: new
|
|
1892
|
+
revision: this.#i,
|
|
1893
|
+
installations: new z(s),
|
|
1894
|
+
groups: new z(n)
|
|
1670
1895
|
});
|
|
1671
1896
|
}
|
|
1672
1897
|
}
|
|
1673
|
-
function
|
|
1898
|
+
function B(r, t, e = {}) {
|
|
1674
1899
|
if (!r || typeof r != "object" || Array.isArray(r))
|
|
1675
|
-
throw
|
|
1900
|
+
throw O(e, `${t} must be a plain record`);
|
|
1676
1901
|
const i = Object.getPrototypeOf(r);
|
|
1677
1902
|
if (i !== Object.prototype && i !== null)
|
|
1678
|
-
throw
|
|
1903
|
+
throw O(e, `${t} must be a plain record`);
|
|
1679
1904
|
for (const s of Reflect.ownKeys(r)) {
|
|
1680
1905
|
const n = Reflect.getOwnPropertyDescriptor(r, s);
|
|
1681
1906
|
if (typeof s != "string" || !n?.enumerable)
|
|
1682
|
-
throw
|
|
1907
|
+
throw O(e, `${t} keys must be enumerable strings`);
|
|
1683
1908
|
if (!("value" in n))
|
|
1684
|
-
throw
|
|
1909
|
+
throw O(e, `${t} field '${s}' must be a data property`);
|
|
1685
1910
|
if (e.fields && !e.fields.has(s))
|
|
1686
|
-
throw
|
|
1911
|
+
throw O(e, `${t}: unknown field '${s}'`);
|
|
1687
1912
|
}
|
|
1688
1913
|
}
|
|
1689
|
-
function
|
|
1914
|
+
function O(r, t) {
|
|
1690
1915
|
return r.createError?.(t) ?? new TypeError(t);
|
|
1691
1916
|
}
|
|
1692
|
-
const
|
|
1917
|
+
const ue = /* @__PURE__ */ new Set([
|
|
1693
1918
|
"signal",
|
|
1694
1919
|
"meta",
|
|
1695
1920
|
"log",
|
|
@@ -1699,12 +1924,12 @@ const Wt = /* @__PURE__ */ new Set([
|
|
|
1699
1924
|
"on",
|
|
1700
1925
|
"emit",
|
|
1701
1926
|
"contribute"
|
|
1702
|
-
]),
|
|
1703
|
-
function
|
|
1704
|
-
return
|
|
1927
|
+
]), fe = /* @__PURE__ */ new Set(["name", "config", "requires", "provides", "setup"]);
|
|
1928
|
+
function Ne(r) {
|
|
1929
|
+
return Ct(r);
|
|
1705
1930
|
}
|
|
1706
|
-
function
|
|
1707
|
-
|
|
1931
|
+
function Ct(r) {
|
|
1932
|
+
pe(r);
|
|
1708
1933
|
const t = Object.hasOwn(r, "name") ? r.name : void 0, e = Object.hasOwn(r, "config") ? r.config : void 0, i = Object.hasOwn(r, "requires") ? r.requires : void 0, s = Object.hasOwn(r, "provides") ? r.provides : void 0, n = Object.hasOwn(r, "setup") ? r.setup : void 0;
|
|
1709
1934
|
if (typeof t != "string" || !t.trim())
|
|
1710
1935
|
throw new TypeError("Plugin name must be a non-empty string");
|
|
@@ -1712,24 +1937,27 @@ function nt(r) {
|
|
|
1712
1937
|
throw new TypeError("Plugin name cannot start or end with whitespace");
|
|
1713
1938
|
if (typeof n != "function")
|
|
1714
1939
|
throw new TypeError(`Plugin '${t}' must define setup()`);
|
|
1715
|
-
if (e !== void 0 && !
|
|
1940
|
+
if (e !== void 0 && !ge(e))
|
|
1716
1941
|
throw new TypeError(`Plugin '${t}' config must implement Standard Schema V1`);
|
|
1717
|
-
|
|
1718
|
-
const o =
|
|
1719
|
-
for (const [c, d] of Object.entries(
|
|
1942
|
+
ht(i, t, "requires"), ht(s, t, "provides");
|
|
1943
|
+
const o = /* @__PURE__ */ Object.create(null), a = /* @__PURE__ */ Object.create(null), h = /* @__PURE__ */ new Map();
|
|
1944
|
+
for (const [c, d] of Object.entries(i ?? {})) {
|
|
1720
1945
|
if (!c.trim()) throw new TypeError("Plugin requirement alias cannot be empty");
|
|
1721
1946
|
if (c !== c.trim())
|
|
1722
1947
|
throw new TypeError("Plugin requirement alias cannot start or end with whitespace");
|
|
1723
|
-
if (
|
|
1948
|
+
if (ue.has(c))
|
|
1724
1949
|
throw new TypeError(`Plugin requirement '${c}' conflicts with the context API`);
|
|
1725
1950
|
if (!d || typeof d != "object")
|
|
1726
1951
|
throw new TypeError(`Plugin requirement '${c}' is not a contract`);
|
|
1727
1952
|
if (d.kind === "optional") {
|
|
1728
|
-
if (!
|
|
1953
|
+
if (!E(d.service, "service"))
|
|
1729
1954
|
throw new TypeError(`Optional requirement '${c}' must wrap a Service`);
|
|
1730
|
-
} else if (!
|
|
1955
|
+
} else if (!E(d, "service") && !E(d, "extensionPoint"))
|
|
1731
1956
|
throw new TypeError(`Plugin requirement '${c}' must be a Service or ExtensionPoint`);
|
|
1732
|
-
|
|
1957
|
+
o[c] = d.kind === "optional" ? Object.freeze({
|
|
1958
|
+
kind: "optional",
|
|
1959
|
+
service: _(d.service)
|
|
1960
|
+
}) : _(d), dt(
|
|
1733
1961
|
t,
|
|
1734
1962
|
h,
|
|
1735
1963
|
"requirement",
|
|
@@ -1737,36 +1965,41 @@ function nt(r) {
|
|
|
1737
1965
|
d.kind === "optional" ? d.service : d
|
|
1738
1966
|
);
|
|
1739
1967
|
}
|
|
1740
|
-
for (const [c, d] of Object.entries(
|
|
1968
|
+
for (const [c, d] of Object.entries(s ?? {})) {
|
|
1741
1969
|
if (!c.trim()) throw new TypeError("Plugin provision alias cannot be empty");
|
|
1742
1970
|
if (c !== c.trim())
|
|
1743
1971
|
throw new TypeError("Plugin provision alias cannot start or end with whitespace");
|
|
1744
|
-
if (
|
|
1972
|
+
if (c === "then")
|
|
1973
|
+
throw new TypeError("Plugin provision alias 'then' conflicts with the Promise protocol");
|
|
1974
|
+
if (!E(d, "service"))
|
|
1745
1975
|
throw new TypeError(`Plugin provision '${c}' must be a Service`);
|
|
1746
|
-
|
|
1976
|
+
a[c] = _(d), dt(t, h, "provision", c, a[c]);
|
|
1747
1977
|
}
|
|
1748
1978
|
return Object.freeze({
|
|
1749
1979
|
name: t,
|
|
1750
1980
|
...e === void 0 ? {} : { config: e },
|
|
1751
|
-
|
|
1752
|
-
|
|
1981
|
+
requires: Object.freeze(o),
|
|
1982
|
+
provides: Object.freeze(a),
|
|
1753
1983
|
setup: n
|
|
1754
1984
|
});
|
|
1755
1985
|
}
|
|
1756
|
-
function
|
|
1757
|
-
|
|
1986
|
+
function _(r) {
|
|
1987
|
+
return Object.freeze({ id: r.id, kind: r.kind });
|
|
1758
1988
|
}
|
|
1759
|
-
function
|
|
1989
|
+
function pe(r) {
|
|
1990
|
+
B(r, "Plugin declaration", { fields: fe });
|
|
1991
|
+
}
|
|
1992
|
+
function ge(r) {
|
|
1760
1993
|
if (!r || typeof r != "object" && typeof r != "function") return !1;
|
|
1761
1994
|
const t = r["~standard"];
|
|
1762
1995
|
if (!t || typeof t != "object") return !1;
|
|
1763
1996
|
const e = t;
|
|
1764
1997
|
return e.version === 1 && typeof e.vendor == "string" && typeof e.validate == "function";
|
|
1765
1998
|
}
|
|
1766
|
-
function
|
|
1767
|
-
r !== void 0 &&
|
|
1999
|
+
function ht(r, t, e) {
|
|
2000
|
+
r !== void 0 && B(r, `Plugin '${t}' ${e}`);
|
|
1768
2001
|
}
|
|
1769
|
-
function
|
|
2002
|
+
function dt(r, t, e, i, s) {
|
|
1770
2003
|
const n = t.get(s.id);
|
|
1771
2004
|
if (!n) {
|
|
1772
2005
|
t.set(s.id, { alias: i, kind: s.kind, role: e });
|
|
@@ -1774,35 +2007,35 @@ function W(r, t, e, i, s) {
|
|
|
1774
2007
|
}
|
|
1775
2008
|
if (n.kind !== s.kind)
|
|
1776
2009
|
throw new TypeError(
|
|
1777
|
-
`Plugin '${r}' uses Contract '${s.id}' as both ${
|
|
2010
|
+
`Plugin '${r}' uses Contract '${s.id}' as both ${H(n.kind)} and ${H(s.kind)}`
|
|
1778
2011
|
);
|
|
1779
|
-
const o =
|
|
2012
|
+
const o = H(s.kind);
|
|
1780
2013
|
throw n.role !== e ? new TypeError(
|
|
1781
2014
|
`Plugin '${r}' cannot both require and provide ${o} '${s.id}'`
|
|
1782
2015
|
) : new TypeError(
|
|
1783
2016
|
`Plugin '${r}' ${e} aliases '${n.alias}' and '${i}' reference the same ${o} '${s.id}'`
|
|
1784
2017
|
);
|
|
1785
2018
|
}
|
|
1786
|
-
function
|
|
2019
|
+
function H(r) {
|
|
1787
2020
|
return r === "extensionPoint" ? "ExtensionPoint" : r === "event" ? "Event" : "Service";
|
|
1788
2021
|
}
|
|
1789
|
-
function
|
|
1790
|
-
return
|
|
2022
|
+
function lt(r) {
|
|
2023
|
+
return Ct(r);
|
|
1791
2024
|
}
|
|
1792
|
-
const
|
|
1793
|
-
function
|
|
1794
|
-
|
|
2025
|
+
const we = /* @__PURE__ */ new Set(["plugin", "config"]), x = /* @__PURE__ */ new WeakMap();
|
|
2026
|
+
function be(r, t) {
|
|
2027
|
+
x.get(r)?.discard(t);
|
|
1795
2028
|
}
|
|
1796
|
-
function
|
|
1797
|
-
const s =
|
|
2029
|
+
function me(r, t, e, i) {
|
|
2030
|
+
const s = x.get(r);
|
|
1798
2031
|
if (!s) throw new Error("ChangeSet draft control has been released");
|
|
1799
2032
|
return s.install(t, e, i);
|
|
1800
2033
|
}
|
|
1801
|
-
class
|
|
2034
|
+
class ve {
|
|
1802
2035
|
#t = /* @__PURE__ */ new Map();
|
|
1803
2036
|
#e;
|
|
1804
2037
|
constructor(t) {
|
|
1805
|
-
this.#e = { phase: "open", port: t },
|
|
2038
|
+
this.#e = { phase: "open", port: t }, x.set(this, {
|
|
1806
2039
|
discard: (e) => this.#s(e),
|
|
1807
2040
|
install: (e, i, s) => this.#i(e, i, s)
|
|
1808
2041
|
}), Object.freeze(this);
|
|
@@ -1811,12 +2044,12 @@ class ee {
|
|
|
1811
2044
|
return this.#i(t, e[0]);
|
|
1812
2045
|
}
|
|
1813
2046
|
#i(t, e, i) {
|
|
1814
|
-
const s = this.#a(), n =
|
|
2047
|
+
const s = this.#a(), n = lt(t), o = (i ?? s.create)(n, e);
|
|
1815
2048
|
return this.#n({ kind: "install", installation: o.record }), o.facade;
|
|
1816
2049
|
}
|
|
1817
2050
|
update(t, e) {
|
|
1818
2051
|
const i = this.#a();
|
|
1819
|
-
|
|
2052
|
+
B(e, "Installation update", { fields: we });
|
|
1820
2053
|
const s = Object.hasOwn(e, "plugin"), n = Object.hasOwn(e, "config");
|
|
1821
2054
|
if (!s && !n)
|
|
1822
2055
|
throw new TypeError("Installation update must include 'plugin' or 'config'");
|
|
@@ -1825,7 +2058,7 @@ class ee {
|
|
|
1825
2058
|
if (s) {
|
|
1826
2059
|
const d = e.plugin;
|
|
1827
2060
|
if (!d) throw new TypeError("Installation update 'plugin' must be a Plugin");
|
|
1828
|
-
a =
|
|
2061
|
+
a = lt(d);
|
|
1829
2062
|
}
|
|
1830
2063
|
let h;
|
|
1831
2064
|
a && n ? h = { kind: "plugin-and-config", plugin: a, config: e.config } : a ? h = { kind: "plugin", plugin: a } : h = { kind: "config", config: e.config };
|
|
@@ -1836,6 +2069,12 @@ class ee {
|
|
|
1836
2069
|
const e = this.#a();
|
|
1837
2070
|
this.#n({ kind: "remove", installation: e.resolve(t) });
|
|
1838
2071
|
}
|
|
2072
|
+
/**
|
|
2073
|
+
* Commit is idempotent by returning the same promise, so two callers awaiting
|
|
2074
|
+
* one draft get one transaction rather than two. `committing` exists to catch
|
|
2075
|
+
* the reentrant case — an `attach` hook that calls `commit()` again — which
|
|
2076
|
+
* would otherwise submit the operation list twice.
|
|
2077
|
+
*/
|
|
1839
2078
|
commit() {
|
|
1840
2079
|
const t = this.#e;
|
|
1841
2080
|
if (t.phase === "submitted") return t.promise;
|
|
@@ -1870,6 +2109,10 @@ class ee {
|
|
|
1870
2109
|
for (const s of i)
|
|
1871
2110
|
s.kind === "install" && e.port.discard(s.installation, t);
|
|
1872
2111
|
}
|
|
2112
|
+
// One operation per Installation per ChangeSet. Allowing two would make the
|
|
2113
|
+
// outcome depend on staging order — `update` then `remove` versus the reverse —
|
|
2114
|
+
// and there is no reading of "both" that is obviously right. The caller has to
|
|
2115
|
+
// say which one it meant.
|
|
1873
2116
|
#n(t) {
|
|
1874
2117
|
if (this.#t.has(t.installation))
|
|
1875
2118
|
throw new TypeError(
|
|
@@ -1887,55 +2130,10 @@ class ee {
|
|
|
1887
2130
|
return this.#e = { phase: "submitted", promise: t }, this.#o(), t;
|
|
1888
2131
|
}
|
|
1889
2132
|
#o() {
|
|
1890
|
-
this.#t.clear(),
|
|
2133
|
+
this.#t.clear(), x.delete(this);
|
|
1891
2134
|
}
|
|
1892
2135
|
}
|
|
1893
|
-
class
|
|
1894
|
-
#t;
|
|
1895
|
-
constructor(t, e, i) {
|
|
1896
|
-
this.#t = { phase: "open", draft: t, discard: e, normalize: i };
|
|
1897
|
-
}
|
|
1898
|
-
get failure() {
|
|
1899
|
-
return this.#t.phase === "failed" ? this.#t.error : void 0;
|
|
1900
|
-
}
|
|
1901
|
-
requireDraft() {
|
|
1902
|
-
const t = this.#t;
|
|
1903
|
-
if (t.phase === "failed") throw t.error;
|
|
1904
|
-
if (t.phase === "sealed") throw N();
|
|
1905
|
-
return t.draft;
|
|
1906
|
-
}
|
|
1907
|
-
assertOpen() {
|
|
1908
|
-
this.requireDraft();
|
|
1909
|
-
}
|
|
1910
|
-
fail(t) {
|
|
1911
|
-
const e = this.#t;
|
|
1912
|
-
if (e.phase === "failed") return e.error;
|
|
1913
|
-
if (e.phase === "sealed") throw N();
|
|
1914
|
-
const i = e.normalize(t);
|
|
1915
|
-
return this.#t = {
|
|
1916
|
-
phase: "failed",
|
|
1917
|
-
draft: e.draft,
|
|
1918
|
-
discard: e.discard,
|
|
1919
|
-
error: i
|
|
1920
|
-
}, i;
|
|
1921
|
-
}
|
|
1922
|
-
seal() {
|
|
1923
|
-
const t = this.#t;
|
|
1924
|
-
if (t.phase === "failed") throw t.error;
|
|
1925
|
-
if (t.phase === "sealed") throw N();
|
|
1926
|
-
return this.#t = { phase: "sealed" }, t.draft;
|
|
1927
|
-
}
|
|
1928
|
-
discard(t) {
|
|
1929
|
-
const e = this.#t;
|
|
1930
|
-
if (e.phase === "sealed") return;
|
|
1931
|
-
const i = e.phase === "failed" ? e.error : e.normalize(t);
|
|
1932
|
-
this.#t = { phase: "sealed" }, e.discard(e.draft, i);
|
|
1933
|
-
}
|
|
1934
|
-
}
|
|
1935
|
-
function N() {
|
|
1936
|
-
return new Error("Group configuration has been sealed");
|
|
1937
|
-
}
|
|
1938
|
-
class A {
|
|
2136
|
+
class M {
|
|
1939
2137
|
constructor(t, e, i) {
|
|
1940
2138
|
this.id = t, this.name = e, this.#e = { phase: "attached", parent: i };
|
|
1941
2139
|
}
|
|
@@ -1944,7 +2142,7 @@ class A {
|
|
|
1944
2142
|
#t = /* @__PURE__ */ new Map();
|
|
1945
2143
|
#e;
|
|
1946
2144
|
static root(t) {
|
|
1947
|
-
return new
|
|
2145
|
+
return new M("/", t, void 0);
|
|
1948
2146
|
}
|
|
1949
2147
|
get attached() {
|
|
1950
2148
|
return this.#e.phase !== "detached";
|
|
@@ -1957,21 +2155,24 @@ class A {
|
|
|
1957
2155
|
return t.phase === "detached" ? void 0 : t.parent;
|
|
1958
2156
|
}
|
|
1959
2157
|
create(t) {
|
|
1960
|
-
if (this.assertAttached(),
|
|
2158
|
+
if (this.assertAttached(), ye(t), this.#t.has(t))
|
|
1961
2159
|
throw new TypeError(`Group '${this.#i(t)}' already exists`);
|
|
1962
|
-
const e = new
|
|
2160
|
+
const e = new M(this.#i(t), t, this);
|
|
1963
2161
|
return this.#t.set(t, e), e;
|
|
1964
2162
|
}
|
|
1965
2163
|
contains(t) {
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
if (e.contains(t)) return !0;
|
|
2164
|
+
for (let e = t; e; e = e.parent)
|
|
2165
|
+
if (e === this) return !0;
|
|
1969
2166
|
return !1;
|
|
1970
2167
|
}
|
|
1971
2168
|
assertAttached() {
|
|
1972
2169
|
if (this.#e.phase === "detached")
|
|
1973
2170
|
throw new TypeError(`Group '${this.id}' has been removed`);
|
|
1974
2171
|
}
|
|
2172
|
+
// Depth-first, and children are detached before this node unlinks itself from
|
|
2173
|
+
// its parent. A node that unlinked first would leave its subtree unreachable
|
|
2174
|
+
// but still attached, so those groups would report themselves as live with no
|
|
2175
|
+
// path back to the root.
|
|
1975
2176
|
detach() {
|
|
1976
2177
|
const t = this.#e;
|
|
1977
2178
|
if (t.phase !== "detached") {
|
|
@@ -1991,14 +2192,59 @@ class A {
|
|
|
1991
2192
|
return this.id === "/" ? `/${t}` : `${this.id}/${t}`;
|
|
1992
2193
|
}
|
|
1993
2194
|
}
|
|
1994
|
-
function
|
|
2195
|
+
function ye(r) {
|
|
1995
2196
|
if (typeof r != "string" || !r.trim())
|
|
1996
2197
|
throw new TypeError("Group name must be a non-empty string");
|
|
1997
2198
|
if (r !== r.trim())
|
|
1998
2199
|
throw new TypeError("Group name cannot start or end with whitespace");
|
|
1999
2200
|
if (r.includes("/")) throw new TypeError("Group name cannot contain '/'");
|
|
2000
2201
|
}
|
|
2001
|
-
class
|
|
2202
|
+
class Ee {
|
|
2203
|
+
#t;
|
|
2204
|
+
constructor(t, e, i) {
|
|
2205
|
+
this.#t = { phase: "open", draft: t, discard: e, normalize: i };
|
|
2206
|
+
}
|
|
2207
|
+
get failure() {
|
|
2208
|
+
return this.#t.phase === "failed" ? this.#t.error : void 0;
|
|
2209
|
+
}
|
|
2210
|
+
requireDraft() {
|
|
2211
|
+
const t = this.#t;
|
|
2212
|
+
if (t.phase === "failed") throw t.error;
|
|
2213
|
+
if (t.phase === "sealed") throw K();
|
|
2214
|
+
return t.draft;
|
|
2215
|
+
}
|
|
2216
|
+
assertOpen() {
|
|
2217
|
+
this.requireDraft();
|
|
2218
|
+
}
|
|
2219
|
+
fail(t) {
|
|
2220
|
+
const e = this.#t;
|
|
2221
|
+
if (e.phase === "failed") return e.error;
|
|
2222
|
+
if (e.phase === "sealed") throw K();
|
|
2223
|
+
const i = e.normalize(t);
|
|
2224
|
+
return this.#t = {
|
|
2225
|
+
phase: "failed",
|
|
2226
|
+
draft: e.draft,
|
|
2227
|
+
discard: e.discard,
|
|
2228
|
+
error: i
|
|
2229
|
+
}, i;
|
|
2230
|
+
}
|
|
2231
|
+
seal() {
|
|
2232
|
+
const t = this.#t;
|
|
2233
|
+
if (t.phase === "failed") throw t.error;
|
|
2234
|
+
if (t.phase === "sealed") throw K();
|
|
2235
|
+
return this.#t = { phase: "sealed" }, t.draft;
|
|
2236
|
+
}
|
|
2237
|
+
discard(t) {
|
|
2238
|
+
const e = this.#t;
|
|
2239
|
+
if (e.phase === "sealed") return;
|
|
2240
|
+
const i = e.phase === "failed" ? e.error : e.normalize(t);
|
|
2241
|
+
this.#t = { phase: "sealed" }, e.discard(e.draft, i);
|
|
2242
|
+
}
|
|
2243
|
+
}
|
|
2244
|
+
function K() {
|
|
2245
|
+
return new Error("Group configuration has been sealed");
|
|
2246
|
+
}
|
|
2247
|
+
class ut {
|
|
2002
2248
|
constructor(t, e, i) {
|
|
2003
2249
|
this.node = t, this.#t = { phase: e }, this.#e = i;
|
|
2004
2250
|
}
|
|
@@ -2018,6 +2264,19 @@ class Q {
|
|
|
2018
2264
|
if (i.phase === "failed") throw i.error;
|
|
2019
2265
|
await t();
|
|
2020
2266
|
}
|
|
2267
|
+
/**
|
|
2268
|
+
* `preserveCommittedState` is the whole point of this class.
|
|
2269
|
+
*
|
|
2270
|
+
* A Group that has already committed something is established, and a later
|
|
2271
|
+
* failed change does not un-establish it — the transaction rolled back, so the
|
|
2272
|
+
* state the Group describes is still the one that was committed. Such a
|
|
2273
|
+
* failure leaves the phase at `established` and does not rethrow, because the
|
|
2274
|
+
* caller of the failed change already has the error.
|
|
2275
|
+
*
|
|
2276
|
+
* A Group whose *first* change fails never had a committed state, so it does
|
|
2277
|
+
* become `failed` and the failure propagates: there is nothing to report but
|
|
2278
|
+
* the failure.
|
|
2279
|
+
*/
|
|
2021
2280
|
track(t) {
|
|
2022
2281
|
this.node.assertAttached();
|
|
2023
2282
|
const e = this.#t, i = e.phase === "established" || e.phase === "pending" && e.baseline === "established", s = {}, n = t.then(
|
|
@@ -2025,7 +2284,7 @@ class Q {
|
|
|
2025
2284
|
this.#i(s) && (this.#t = { phase: "established" }, this.#e?.());
|
|
2026
2285
|
},
|
|
2027
2286
|
(o) => {
|
|
2028
|
-
const a =
|
|
2287
|
+
const a = V(
|
|
2029
2288
|
o,
|
|
2030
2289
|
"GROUP_UNAVAILABLE",
|
|
2031
2290
|
`Group '${this.node.id}' operation failed with a non-Error value`
|
|
@@ -2049,15 +2308,15 @@ class Q {
|
|
|
2049
2308
|
return e.phase === "pending" && e.attempt === t;
|
|
2050
2309
|
}
|
|
2051
2310
|
}
|
|
2052
|
-
function
|
|
2311
|
+
function D(r) {
|
|
2053
2312
|
return new u("GROUP_REMOVED", `Group '${r.id}' has been removed`);
|
|
2054
2313
|
}
|
|
2055
|
-
const
|
|
2056
|
-
class
|
|
2314
|
+
const P = /* @__PURE__ */ new WeakMap();
|
|
2315
|
+
class Ce {
|
|
2057
2316
|
#t;
|
|
2058
2317
|
#e;
|
|
2059
2318
|
constructor(t, e, i) {
|
|
2060
|
-
this.#t = e, this.#e = i ? { phase: "configuring", coordinator: t, configuration: i } : { phase: "attached", coordinator: t },
|
|
2319
|
+
this.#t = e, this.#e = i ? { phase: "configuring", coordinator: t, configuration: i } : { phase: "attached", coordinator: t }, P.set(this, {
|
|
2061
2320
|
finishConfiguration: () => {
|
|
2062
2321
|
const s = this.#e;
|
|
2063
2322
|
s.phase === "configuring" && (this.#e = { phase: "attached", coordinator: s.coordinator });
|
|
@@ -2079,7 +2338,7 @@ class re {
|
|
|
2079
2338
|
}
|
|
2080
2339
|
ready() {
|
|
2081
2340
|
const t = this.#e;
|
|
2082
|
-
return t.phase === "revoked" ? Promise.reject(
|
|
2341
|
+
return t.phase === "revoked" ? Promise.reject(D(this.#t)) : t.coordinator.ready(this.#t);
|
|
2083
2342
|
}
|
|
2084
2343
|
install(t, ...e) {
|
|
2085
2344
|
const i = this.#e;
|
|
@@ -2112,19 +2371,19 @@ class re {
|
|
|
2112
2371
|
}
|
|
2113
2372
|
#i() {
|
|
2114
2373
|
const t = this.#e;
|
|
2115
|
-
if (t.phase === "revoked") throw
|
|
2374
|
+
if (t.phase === "revoked") throw D(this.#t);
|
|
2116
2375
|
return t.coordinator;
|
|
2117
2376
|
}
|
|
2118
2377
|
}
|
|
2119
|
-
class
|
|
2378
|
+
class Se {
|
|
2120
2379
|
root;
|
|
2121
2380
|
#t;
|
|
2122
2381
|
#e = /* @__PURE__ */ new WeakMap();
|
|
2123
2382
|
#i = /* @__PURE__ */ new WeakMap();
|
|
2124
2383
|
constructor(t, e) {
|
|
2125
|
-
this.root =
|
|
2384
|
+
this.root = M.root(t), this.#t = e, this.#i.set(
|
|
2126
2385
|
this.root,
|
|
2127
|
-
new
|
|
2386
|
+
new ut(this.root, "established", () => e.notifyChanged())
|
|
2128
2387
|
);
|
|
2129
2388
|
}
|
|
2130
2389
|
nodes() {
|
|
@@ -2132,23 +2391,29 @@ class ne {
|
|
|
2132
2391
|
}
|
|
2133
2392
|
install(t, e, ...i) {
|
|
2134
2393
|
const s = this.change(t), n = s.install(e, ...i);
|
|
2135
|
-
return
|
|
2394
|
+
return ft(s.commit()), n;
|
|
2136
2395
|
}
|
|
2137
2396
|
stageConfigurationInstall(t, e, i, ...s) {
|
|
2138
|
-
return this.#r(t),
|
|
2397
|
+
return this.#r(t), me(
|
|
2139
2398
|
e.requireDraft(),
|
|
2140
2399
|
i,
|
|
2141
2400
|
s[0],
|
|
2142
2401
|
(n, o) => (this.#r(t), this.#t.createDraft(t, n, o))
|
|
2143
2402
|
);
|
|
2144
2403
|
}
|
|
2404
|
+
/**
|
|
2405
|
+
* `deferred` tracking exists for `create()`. A Group being configured must not
|
|
2406
|
+
* mark itself pending on each nested install, because the whole configuration
|
|
2407
|
+
* commits once; the coordinator attaches that single operation to every node in
|
|
2408
|
+
* the finished subtree instead.
|
|
2409
|
+
*/
|
|
2145
2410
|
change(t, e = "immediate") {
|
|
2146
|
-
return this.#r(t), new
|
|
2411
|
+
return this.#r(t), new ve({
|
|
2147
2412
|
create: (i, s) => (this.#r(t), this.#t.createDraft(t, i, s)),
|
|
2148
2413
|
resolve: (i) => {
|
|
2149
2414
|
this.#r(t);
|
|
2150
2415
|
const s = this.#t.resolveInstallation(i);
|
|
2151
|
-
if (!s.
|
|
2416
|
+
if (!s.hasAuthority) throw s.unavailableError();
|
|
2152
2417
|
if (!t.contains(s.group))
|
|
2153
2418
|
throw new TypeError(`Installation '${s.id}' is outside Group '${t.id}'`);
|
|
2154
2419
|
return s;
|
|
@@ -2168,20 +2433,20 @@ class ne {
|
|
|
2168
2433
|
create(t, e, i, s) {
|
|
2169
2434
|
if (typeof i != "function") throw new TypeError("Group configure must be a function");
|
|
2170
2435
|
const n = t.create(e);
|
|
2171
|
-
this.#i.set(n, new
|
|
2172
|
-
const o = s === void 0, a = s ?? new
|
|
2436
|
+
this.#i.set(n, new ut(n, "new", () => this.#t.notifyChanged()));
|
|
2437
|
+
const o = s === void 0, a = s ?? new Ee(
|
|
2173
2438
|
this.change(n, "deferred"),
|
|
2174
|
-
|
|
2175
|
-
(c) =>
|
|
2439
|
+
be,
|
|
2440
|
+
(c) => V(
|
|
2176
2441
|
c,
|
|
2177
2442
|
"GROUP_UNAVAILABLE",
|
|
2178
2443
|
`Group '${n.id}' configuration failed with a non-Error value`
|
|
2179
2444
|
)
|
|
2180
|
-
), h = new
|
|
2445
|
+
), h = new Ce(this, n, a);
|
|
2181
2446
|
this.#e.set(n, h);
|
|
2182
2447
|
try {
|
|
2183
2448
|
const c = i(h);
|
|
2184
|
-
|
|
2449
|
+
R(c, "Group configure must be synchronous");
|
|
2185
2450
|
const d = a.failure;
|
|
2186
2451
|
if (d) throw d;
|
|
2187
2452
|
} catch (c) {
|
|
@@ -2192,9 +2457,9 @@ class ne {
|
|
|
2192
2457
|
const c = a.seal().commit();
|
|
2193
2458
|
for (const d of n.walk()) {
|
|
2194
2459
|
const l = this.#e.get(d);
|
|
2195
|
-
l &&
|
|
2460
|
+
l && P.get(l)?.finishConfiguration(), this.#a(d, c);
|
|
2196
2461
|
}
|
|
2197
|
-
|
|
2462
|
+
ft(c);
|
|
2198
2463
|
}
|
|
2199
2464
|
return this.#t.notifyChanged(), h;
|
|
2200
2465
|
}
|
|
@@ -2225,6 +2490,10 @@ class ne {
|
|
|
2225
2490
|
(e) => t.contains(e.group)
|
|
2226
2491
|
);
|
|
2227
2492
|
}
|
|
2493
|
+
// A Group has no status of its own — it reports what its contents say, with
|
|
2494
|
+
// the worst news winning. The last line is the one that needs stating: an
|
|
2495
|
+
// empty Group is `active`, because a subtree that owns nothing has nothing
|
|
2496
|
+
// left to wait for.
|
|
2228
2497
|
#n(t) {
|
|
2229
2498
|
const e = this.#s(t);
|
|
2230
2499
|
return e.some((i) => i.status === "failed") ? "failed" : e.some((i) => i.status === "stopping") ? "stopping" : e.length && e.every((i) => i.status === "active") ? "active" : e.length ? "pending" : "active";
|
|
@@ -2234,25 +2503,25 @@ class ne {
|
|
|
2234
2503
|
}
|
|
2235
2504
|
#r(t) {
|
|
2236
2505
|
const e = this.#i.get(t);
|
|
2237
|
-
if (!t.attached || !e) throw
|
|
2506
|
+
if (!t.attached || !e) throw D(t);
|
|
2238
2507
|
return e;
|
|
2239
2508
|
}
|
|
2240
2509
|
#o(t) {
|
|
2241
2510
|
for (const e of t) {
|
|
2242
2511
|
this.#i.get(e)?.release(), this.#i.delete(e);
|
|
2243
2512
|
const i = this.#e.get(e);
|
|
2244
|
-
i && (
|
|
2513
|
+
i && (P.get(i)?.revoke(), P.delete(i)), this.#e.delete(e);
|
|
2245
2514
|
}
|
|
2246
2515
|
}
|
|
2247
2516
|
}
|
|
2248
|
-
function
|
|
2517
|
+
function ft(r) {
|
|
2249
2518
|
Promise.resolve(r).catch(() => {
|
|
2250
2519
|
});
|
|
2251
2520
|
}
|
|
2252
|
-
function
|
|
2521
|
+
function pt(r, t) {
|
|
2253
2522
|
return Object.freeze({ plugin: r, config: t });
|
|
2254
2523
|
}
|
|
2255
|
-
class
|
|
2524
|
+
class Oe {
|
|
2256
2525
|
constructor(t, e, i, s) {
|
|
2257
2526
|
this.id = t, this.index = e, this.groupId = i.id, this.#i = { declaration: s, group: i, notifyChanged: void 0 };
|
|
2258
2527
|
}
|
|
@@ -2264,7 +2533,7 @@ class oe {
|
|
|
2264
2533
|
groupId;
|
|
2265
2534
|
#s = /* @__PURE__ */ new Set();
|
|
2266
2535
|
attach(t) {
|
|
2267
|
-
const e = this.#
|
|
2536
|
+
const e = this.#h();
|
|
2268
2537
|
if (e.notifyChanged) throw new Error(`Installation '${this.id}' is already attached`);
|
|
2269
2538
|
e.notifyChanged = t;
|
|
2270
2539
|
}
|
|
@@ -2272,7 +2541,7 @@ class oe {
|
|
|
2272
2541
|
return this.#t.phase;
|
|
2273
2542
|
}
|
|
2274
2543
|
/** Whether the owning ChangeSet has granted this Installation Host authority. */
|
|
2275
|
-
get
|
|
2544
|
+
get hasAuthority() {
|
|
2276
2545
|
return this.#i?.notifyChanged !== void 0;
|
|
2277
2546
|
}
|
|
2278
2547
|
get instance() {
|
|
@@ -2282,18 +2551,18 @@ class oe {
|
|
|
2282
2551
|
get error() {
|
|
2283
2552
|
const t = this.#t;
|
|
2284
2553
|
if (t.phase === "failed")
|
|
2285
|
-
return t.
|
|
2554
|
+
return t.error;
|
|
2286
2555
|
if (t.phase === "removed")
|
|
2287
2556
|
return new u("INSTALLATION_REMOVED", `Installation '${this.id}' has been removed`);
|
|
2288
2557
|
}
|
|
2289
2558
|
get group() {
|
|
2290
|
-
return this.#
|
|
2559
|
+
return this.#h().group;
|
|
2291
2560
|
}
|
|
2292
2561
|
get declaration() {
|
|
2293
|
-
return this.#
|
|
2562
|
+
return this.#h().declaration;
|
|
2294
2563
|
}
|
|
2295
2564
|
replaceDeclaration(t) {
|
|
2296
|
-
this.#
|
|
2565
|
+
this.#h().declaration = t;
|
|
2297
2566
|
}
|
|
2298
2567
|
ready() {
|
|
2299
2568
|
const t = this.#e;
|
|
@@ -2305,18 +2574,34 @@ class oe {
|
|
|
2305
2574
|
`Installation '${this.id}' has not been committed`
|
|
2306
2575
|
);
|
|
2307
2576
|
}
|
|
2577
|
+
/**
|
|
2578
|
+
* Binds `ready()` to the change currently in flight.
|
|
2579
|
+
*
|
|
2580
|
+
* The `attempt` token is the point: a second change can start before the
|
|
2581
|
+
* first one's promise settles, and only the latest attempt is allowed to clear
|
|
2582
|
+
* the barrier. Without it, a stale resolution would report readiness for an
|
|
2583
|
+
* attempt that has already been superseded.
|
|
2584
|
+
*
|
|
2585
|
+
* A rejection is rethrown only when this Installation did not end up active.
|
|
2586
|
+
* A change that failed elsewhere in the batch but left this one running is not
|
|
2587
|
+
* this Installation's failure to report.
|
|
2588
|
+
*/
|
|
2308
2589
|
trackReadiness(t) {
|
|
2309
2590
|
const e = {}, i = t.then(
|
|
2310
2591
|
() => {
|
|
2311
2592
|
this.#e?.attempt === e && (this.#e = void 0);
|
|
2312
2593
|
},
|
|
2313
2594
|
(s) => {
|
|
2314
|
-
if (this.#e?.attempt === e && (this.#e = void 0), this.#t.phase !== "active") throw s;
|
|
2595
|
+
if (this.#e?.attempt === e && (this.#e = void 0), this.#t.phase !== "active") throw this.error ?? s;
|
|
2315
2596
|
}
|
|
2316
2597
|
);
|
|
2317
2598
|
this.#e = { attempt: e, barrier: i }, i.catch(() => {
|
|
2318
2599
|
});
|
|
2319
2600
|
}
|
|
2601
|
+
// A terminal state only answers `ready()` once its readiness has been settled.
|
|
2602
|
+
// Before that the outcome is still being decided by the change in flight, so
|
|
2603
|
+
// the caller joins the waiter set instead of being told a result that the
|
|
2604
|
+
// transaction might still roll back.
|
|
2320
2605
|
#n() {
|
|
2321
2606
|
const t = this.#t;
|
|
2322
2607
|
if ((t.phase === "active" || t.phase === "failed" || t.phase === "removed") && t.readiness === "settled") {
|
|
@@ -2357,11 +2642,17 @@ class oe {
|
|
|
2357
2642
|
fail(t) {
|
|
2358
2643
|
return this.#a(t);
|
|
2359
2644
|
}
|
|
2645
|
+
/**
|
|
2646
|
+
* For an Installation that never made it into the graph. Unlike `fail()`, this
|
|
2647
|
+
* is terminal: readiness settles immediately, the attachment is dropped, and
|
|
2648
|
+
* the reason is kept as a RecordedFailure rather than the live Error. The handle the
|
|
2649
|
+
* caller already holds stays usable and reports why it is dead.
|
|
2650
|
+
*/
|
|
2360
2651
|
discard(t) {
|
|
2361
|
-
const e = this.#o(t);
|
|
2652
|
+
const e = new J(this.#o(t));
|
|
2362
2653
|
this.#r({
|
|
2363
2654
|
phase: "failed",
|
|
2364
|
-
|
|
2655
|
+
error: e,
|
|
2365
2656
|
readiness: "settled"
|
|
2366
2657
|
});
|
|
2367
2658
|
for (const i of this.#s) i.reject(e);
|
|
@@ -2371,7 +2662,7 @@ class oe {
|
|
|
2371
2662
|
const e = this.#o(t);
|
|
2372
2663
|
return this.#r({
|
|
2373
2664
|
phase: "failed",
|
|
2374
|
-
|
|
2665
|
+
error: e,
|
|
2375
2666
|
readiness: "unsettled"
|
|
2376
2667
|
}), e;
|
|
2377
2668
|
}
|
|
@@ -2382,24 +2673,24 @@ class oe {
|
|
|
2382
2673
|
this.#t = t, this.#i?.notifyChanged?.();
|
|
2383
2674
|
}
|
|
2384
2675
|
#o(t) {
|
|
2385
|
-
return
|
|
2676
|
+
return V(
|
|
2386
2677
|
t,
|
|
2387
2678
|
"INSTALLATION_UNAVAILABLE",
|
|
2388
2679
|
`Installation '${this.id}' failed with a non-Error value`
|
|
2389
2680
|
);
|
|
2390
2681
|
}
|
|
2391
|
-
#
|
|
2682
|
+
#h() {
|
|
2392
2683
|
const t = this.#i;
|
|
2393
2684
|
if (!t) throw new Error(`Installation '${this.id}' is no longer installed`);
|
|
2394
2685
|
return t;
|
|
2395
2686
|
}
|
|
2396
2687
|
}
|
|
2397
|
-
const
|
|
2398
|
-
class
|
|
2688
|
+
const L = /* @__PURE__ */ new WeakMap();
|
|
2689
|
+
class Ae {
|
|
2399
2690
|
#t;
|
|
2400
2691
|
#e = { phase: "draft" };
|
|
2401
2692
|
constructor(t) {
|
|
2402
|
-
this.#t = t,
|
|
2693
|
+
this.#t = t, L.set(this, {
|
|
2403
2694
|
attach: (e, i) => {
|
|
2404
2695
|
if (this.#e.phase !== "draft")
|
|
2405
2696
|
throw new Error(`Installation '${this.#t.id}' control is already sealed`);
|
|
@@ -2444,7 +2735,7 @@ class ae {
|
|
|
2444
2735
|
);
|
|
2445
2736
|
}
|
|
2446
2737
|
}
|
|
2447
|
-
class
|
|
2738
|
+
class Ie {
|
|
2448
2739
|
#t = /* @__PURE__ */ new Map();
|
|
2449
2740
|
#e = /* @__PURE__ */ new WeakMap();
|
|
2450
2741
|
#i = /* @__PURE__ */ new WeakMap();
|
|
@@ -2464,12 +2755,12 @@ class ce {
|
|
|
2464
2755
|
}
|
|
2465
2756
|
create(t, e, i) {
|
|
2466
2757
|
t.assertAttached();
|
|
2467
|
-
const s = ++this.#n, n = new
|
|
2758
|
+
const s = ++this.#n, n = new Oe(
|
|
2468
2759
|
`${e.name}:${s}`,
|
|
2469
2760
|
s,
|
|
2470
2761
|
t,
|
|
2471
|
-
|
|
2472
|
-
), o = new
|
|
2762
|
+
pt(e, i)
|
|
2763
|
+
), o = new Ae(n);
|
|
2473
2764
|
return this.#e.set(o, n), this.#i.set(n, o), { record: n, facade: o };
|
|
2474
2765
|
}
|
|
2475
2766
|
resolve(t) {
|
|
@@ -2480,13 +2771,19 @@ class ce {
|
|
|
2480
2771
|
attach(t) {
|
|
2481
2772
|
const e = this.#i.get(t);
|
|
2482
2773
|
if (!e) throw new Error(`Installation '${t.id}' has no public facade`);
|
|
2483
|
-
const i =
|
|
2774
|
+
const i = L.get(e);
|
|
2484
2775
|
if (!i) throw new Error(`Installation '${t.id}' has no draft control`);
|
|
2485
2776
|
t.attach(this.#s.notifyChanged), i.attach(
|
|
2486
2777
|
(s) => this.#s.update(t, e, s),
|
|
2487
2778
|
() => this.#s.remove(t, e)
|
|
2488
2779
|
);
|
|
2489
2780
|
}
|
|
2781
|
+
/**
|
|
2782
|
+
* Validates the whole batch, then applies the whole batch. The two loops are
|
|
2783
|
+
* not a style choice: a rejected operation halfway through a single loop would
|
|
2784
|
+
* leave the earlier ones already written, and this method has no way to undo
|
|
2785
|
+
* them. Checking first means `apply` either changes everything or nothing.
|
|
2786
|
+
*/
|
|
2490
2787
|
apply(t) {
|
|
2491
2788
|
for (const e of t) {
|
|
2492
2789
|
if (e.kind === "install") {
|
|
@@ -2507,7 +2804,7 @@ class ce {
|
|
|
2507
2804
|
this.#t.set(e.installation.id, e.installation);
|
|
2508
2805
|
else if (e.kind === "update") {
|
|
2509
2806
|
const i = e.installation.declaration, s = e.declaration.kind === "config" ? i.plugin : e.declaration.plugin, n = e.declaration.kind === "plugin" ? i.config : e.declaration.config;
|
|
2510
|
-
e.installation.replaceDeclaration(
|
|
2807
|
+
e.installation.replaceDeclaration(pt(s, n));
|
|
2511
2808
|
} else this.contains(e.installation) && this.#t.delete(e.installation.id);
|
|
2512
2809
|
}
|
|
2513
2810
|
settleChanges(t, e) {
|
|
@@ -2520,6 +2817,9 @@ class ce {
|
|
|
2520
2817
|
discard(t, e) {
|
|
2521
2818
|
t.discard(e), this.#a(t);
|
|
2522
2819
|
}
|
|
2820
|
+
// Captures declarations only, since that is all a rollback restores. Instances
|
|
2821
|
+
// belong to the InstanceCoordinator and are rebuilt from the previous plan
|
|
2822
|
+
// rather than snapshotted — a live Instance is not a value that can be copied.
|
|
2523
2823
|
capture() {
|
|
2524
2824
|
return [...this.#t.values()].map((t) => ({
|
|
2525
2825
|
installation: t,
|
|
@@ -2533,10 +2833,10 @@ class ce {
|
|
|
2533
2833
|
}
|
|
2534
2834
|
#a(t) {
|
|
2535
2835
|
const e = this.#i.get(t);
|
|
2536
|
-
e && (
|
|
2836
|
+
e && (L.get(e)?.revoke(), L.delete(e)), this.#i.delete(t);
|
|
2537
2837
|
}
|
|
2538
2838
|
}
|
|
2539
|
-
class
|
|
2839
|
+
class je {
|
|
2540
2840
|
#t = Promise.resolve();
|
|
2541
2841
|
get settled() {
|
|
2542
2842
|
return this.#t;
|
|
@@ -2553,8 +2853,8 @@ class he {
|
|
|
2553
2853
|
), e;
|
|
2554
2854
|
}
|
|
2555
2855
|
}
|
|
2556
|
-
const
|
|
2557
|
-
class
|
|
2856
|
+
const ke = console, $e = /* @__PURE__ */ new Set(["name", "logger", "onError"]);
|
|
2857
|
+
class Te {
|
|
2558
2858
|
name;
|
|
2559
2859
|
diagnostics;
|
|
2560
2860
|
#t;
|
|
@@ -2564,9 +2864,9 @@ class ue {
|
|
|
2564
2864
|
#n;
|
|
2565
2865
|
#a;
|
|
2566
2866
|
#r = "idle";
|
|
2567
|
-
#o = new
|
|
2867
|
+
#o = new je();
|
|
2568
2868
|
constructor(t = {}) {
|
|
2569
|
-
|
|
2869
|
+
B(t, "Host options", { fields: $e });
|
|
2570
2870
|
const e = Object.hasOwn(t, "name") ? t.name : void 0, i = Object.hasOwn(t, "logger") ? t.logger : void 0, s = Object.hasOwn(t, "onError") ? t.onError : void 0, n = e ?? "host";
|
|
2571
2871
|
if (typeof n != "string" || !n.trim())
|
|
2572
2872
|
throw new TypeError("Host name must be a non-empty string");
|
|
@@ -2574,10 +2874,10 @@ class ue {
|
|
|
2574
2874
|
throw new TypeError("Host name cannot start or end with whitespace");
|
|
2575
2875
|
if (s !== void 0 && typeof s != "function")
|
|
2576
2876
|
throw new TypeError("Host onError must be a function");
|
|
2577
|
-
if (i !== void 0 && !
|
|
2877
|
+
if (i !== void 0 && !se(i))
|
|
2578
2878
|
throw new TypeError("Host logger must implement debug/info/warn/error");
|
|
2579
|
-
this.name = n, this.#i = i ??
|
|
2580
|
-
notifyChanged: () => this.#
|
|
2879
|
+
this.name = n, this.#i = i ?? ke, this.#n = s ?? ((o) => this.#i.error(o)), this.#t = new Ie({
|
|
2880
|
+
notifyChanged: () => this.#d(),
|
|
2581
2881
|
update: (o, a, h) => {
|
|
2582
2882
|
const c = this.#s.change(o.group);
|
|
2583
2883
|
return c.update(a, h), c.commit();
|
|
@@ -2586,25 +2886,29 @@ class ue {
|
|
|
2586
2886
|
const h = this.#s.change(o.group);
|
|
2587
2887
|
return h.remove(a), h.commit();
|
|
2588
2888
|
}
|
|
2589
|
-
}), this.#a = new
|
|
2889
|
+
}), this.#a = new de({
|
|
2590
2890
|
hostName: n,
|
|
2591
2891
|
logger: this.#i,
|
|
2592
2892
|
isInstalled: (o) => this.#t.has(o),
|
|
2593
|
-
report: (o) => this.#
|
|
2594
|
-
}), this.#s = new
|
|
2893
|
+
report: (o) => this.#c(o)
|
|
2894
|
+
}), this.#s = new Se(n, {
|
|
2595
2895
|
installations: () => this.#t.values(),
|
|
2596
2896
|
createDraft: (o, a, h) => this.#t.create(o, a, h),
|
|
2597
2897
|
resolveInstallation: (o) => this.#t.resolve(o),
|
|
2598
|
-
executeChanges: (o, a) => this.#
|
|
2898
|
+
executeChanges: (o, a) => this.#h(o, a),
|
|
2599
2899
|
attachInstallation: (o) => this.#t.attach(o),
|
|
2600
2900
|
discardInstallation: (o, a) => this.#t.discard(o, a),
|
|
2601
2901
|
runExclusive: (o) => this.#o.run(o),
|
|
2602
|
-
removeInstallations: (o) => this.#
|
|
2603
|
-
notifyChanged: () => this.#
|
|
2604
|
-
}), this.#e = new
|
|
2902
|
+
removeInstallations: (o) => this.#p(o),
|
|
2903
|
+
notifyChanged: () => this.#d()
|
|
2904
|
+
}), this.#e = new le(
|
|
2605
2905
|
n,
|
|
2606
|
-
|
|
2607
|
-
|
|
2906
|
+
() => ({
|
|
2907
|
+
status: this.#r,
|
|
2908
|
+
installations: this.#t.values(),
|
|
2909
|
+
groups: this.#s.nodes()
|
|
2910
|
+
}),
|
|
2911
|
+
(o) => this.#c(o)
|
|
2608
2912
|
), this.diagnostics = this.#e.view, Object.freeze(this);
|
|
2609
2913
|
}
|
|
2610
2914
|
get status() {
|
|
@@ -2629,12 +2933,12 @@ class ue {
|
|
|
2629
2933
|
start() {
|
|
2630
2934
|
return this.#o.run(async () => {
|
|
2631
2935
|
if (this.#r !== "active") {
|
|
2632
|
-
this.#
|
|
2936
|
+
this.#l("starting");
|
|
2633
2937
|
try {
|
|
2634
2938
|
const t = this.#a.buildPlan(this.#t.values());
|
|
2635
|
-
await this.#a.start(t), this.#
|
|
2939
|
+
await this.#a.start(t), this.#l("active"), this.#t.settleReadiness(t.order);
|
|
2636
2940
|
} catch (t) {
|
|
2637
|
-
this.#
|
|
2941
|
+
this.#l("idle");
|
|
2638
2942
|
for (const e of this.#t.values())
|
|
2639
2943
|
e.status !== "active" && e.fail(t);
|
|
2640
2944
|
throw this.#t.settleReadiness(this.#t.values()), t;
|
|
@@ -2645,19 +2949,19 @@ class ue {
|
|
|
2645
2949
|
stop() {
|
|
2646
2950
|
return this.#o.run(async () => {
|
|
2647
2951
|
if (this.#r === "idle") return;
|
|
2648
|
-
this.#
|
|
2952
|
+
this.#l("stopping");
|
|
2649
2953
|
const t = await this.#a.stop();
|
|
2650
|
-
if (this.#
|
|
2954
|
+
if (this.#l("idle"), t.length === 1) throw t[0];
|
|
2651
2955
|
if (t.length > 1) throw new AggregateError(t, "Host shutdown failed");
|
|
2652
2956
|
});
|
|
2653
2957
|
}
|
|
2654
|
-
#
|
|
2958
|
+
#h(t, e) {
|
|
2655
2959
|
const i = e.filter((s) => s.kind === "install").map((s) => s.installation);
|
|
2656
2960
|
return this.#o.run(async () => {
|
|
2657
2961
|
try {
|
|
2658
|
-
if (!t.attached) throw
|
|
2962
|
+
if (!t.attached) throw D(t);
|
|
2659
2963
|
if (!e.length) return;
|
|
2660
|
-
this.#r === "active" ? await this.#
|
|
2964
|
+
this.#r === "active" ? await this.#u(e) : (this.#t.apply(e), this.#t.settleChanges(e, !1)), this.#d();
|
|
2661
2965
|
} catch (s) {
|
|
2662
2966
|
for (const n of i)
|
|
2663
2967
|
this.#t.contains(n) || this.#t.discard(n, s);
|
|
@@ -2665,22 +2969,33 @@ class ue {
|
|
|
2665
2969
|
}
|
|
2666
2970
|
});
|
|
2667
2971
|
}
|
|
2668
|
-
async #
|
|
2669
|
-
t.length && this.#r === "active" ? await this.#
|
|
2972
|
+
async #p(t) {
|
|
2973
|
+
t.length && this.#r === "active" ? await this.#u(t) : (this.#t.apply(t), this.#t.settleChanges(t, !1));
|
|
2670
2974
|
}
|
|
2671
|
-
async #
|
|
2672
|
-
const e = await this.#
|
|
2975
|
+
async #u(t) {
|
|
2976
|
+
const e = await this.#f(t);
|
|
2673
2977
|
if (this.#t.settleReadiness(e.affected), e.kind === "rolled-back") throw e.error;
|
|
2674
2978
|
this.#t.settleChanges(t, !0);
|
|
2675
2979
|
}
|
|
2676
|
-
|
|
2980
|
+
// Three failure levels, in the order they are attempted:
|
|
2981
|
+
//
|
|
2982
|
+
// 1. the new plan does not even build restore declarations, stay active
|
|
2983
|
+
// 2. the plan builds but activation fails Engine rolls back to the previous
|
|
2984
|
+
// Instances and reports the cause
|
|
2985
|
+
// 3. rollback itself cannot complete fail closed: everything stops and
|
|
2986
|
+
// the Host reports `idle`
|
|
2987
|
+
//
|
|
2988
|
+
// Level 3 is the one worth stating out loud. A Host that cannot restore its
|
|
2989
|
+
// previous state is not healthy, so it refuses to present itself as active —
|
|
2990
|
+
// `hasCommittedPlan` is what distinguishes the two outcomes here.
|
|
2991
|
+
async #f(t) {
|
|
2677
2992
|
const e = this.#t.capture(), i = new Set(t.map((n) => n.installation));
|
|
2678
|
-
this.#
|
|
2993
|
+
this.#l("changing");
|
|
2679
2994
|
let s;
|
|
2680
2995
|
try {
|
|
2681
2996
|
this.#t.apply(t), s = this.#a.buildPlan(this.#t.values());
|
|
2682
2997
|
} catch (n) {
|
|
2683
|
-
throw this.#t.restore(e), this.#
|
|
2998
|
+
throw this.#t.restore(e), this.#l("active"), n;
|
|
2684
2999
|
}
|
|
2685
3000
|
try {
|
|
2686
3001
|
const n = await this.#a.transition(
|
|
@@ -2688,33 +3003,33 @@ class ue {
|
|
|
2688
3003
|
i,
|
|
2689
3004
|
() => this.#t.restore(e)
|
|
2690
3005
|
);
|
|
2691
|
-
return this.#
|
|
3006
|
+
return this.#l("active"), n;
|
|
2692
3007
|
} catch (n) {
|
|
2693
|
-
throw this.#
|
|
3008
|
+
throw this.#l(this.#a.hasCommittedPlan ? "active" : "idle"), n;
|
|
2694
3009
|
}
|
|
2695
3010
|
}
|
|
2696
|
-
#
|
|
3011
|
+
#c(t) {
|
|
2697
3012
|
const e = this.#i;
|
|
2698
3013
|
try {
|
|
2699
3014
|
const i = this.#n(t);
|
|
2700
3015
|
Promise.resolve(i).catch((s) => {
|
|
2701
|
-
|
|
3016
|
+
gt(e, t, s);
|
|
2702
3017
|
});
|
|
2703
3018
|
} catch (i) {
|
|
2704
|
-
|
|
3019
|
+
gt(e, t, i);
|
|
2705
3020
|
}
|
|
2706
3021
|
}
|
|
2707
|
-
#
|
|
2708
|
-
this.#r = t, this.#
|
|
3022
|
+
#l(t) {
|
|
3023
|
+
this.#r = t, this.#d();
|
|
2709
3024
|
}
|
|
2710
|
-
#
|
|
2711
|
-
this.#e.publish(
|
|
3025
|
+
#d() {
|
|
3026
|
+
this.#e.publish();
|
|
2712
3027
|
}
|
|
2713
3028
|
}
|
|
2714
|
-
function
|
|
2715
|
-
return new
|
|
3029
|
+
function xe(r) {
|
|
3030
|
+
return new Te(r);
|
|
2716
3031
|
}
|
|
2717
|
-
function
|
|
3032
|
+
function gt(r, t, e) {
|
|
2718
3033
|
try {
|
|
2719
3034
|
const i = r.error(
|
|
2720
3035
|
new AggregateError([t, e], "Host error reporter failed")
|
|
@@ -2725,21 +3040,21 @@ function Z(r, t, e) {
|
|
|
2725
3040
|
}
|
|
2726
3041
|
}
|
|
2727
3042
|
export {
|
|
2728
|
-
|
|
3043
|
+
$t as ConfigValidationError,
|
|
2729
3044
|
u as DougongError,
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
3045
|
+
z as ReadonlyMapSnapshot,
|
|
3046
|
+
J as RecordedFailure,
|
|
3047
|
+
je as SerialQueue,
|
|
3048
|
+
Z as SnapshotPublisher,
|
|
3049
|
+
B as assertPlainRecord,
|
|
3050
|
+
F as asyncDisposeSymbol,
|
|
3051
|
+
xe as createHost,
|
|
3052
|
+
Ne as definePlugin,
|
|
3053
|
+
v as disposeSymbol,
|
|
3054
|
+
Le as event,
|
|
3055
|
+
ze as extensionPoint,
|
|
3056
|
+
wt as isCancellationReason,
|
|
3057
|
+
se as isLogger,
|
|
3058
|
+
Re as optional,
|
|
3059
|
+
It as service
|
|
2745
3060
|
};
|