@camstack/server 1.2.611 → 1.2.612
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.
|
@@ -11068,15 +11068,6 @@ function createCapRouter_storageAdmin(getProvider, createRemoteProxy) {
|
|
|
11068
11068
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument
|
|
11069
11069
|
return p.listTables(methodInput);
|
|
11070
11070
|
}),
|
|
11071
|
-
dropCollection: trpc_middleware_js_1.adminProcedure
|
|
11072
|
-
.input(types_125.storageAdminCapability.methods.dropCollection.input.loose())
|
|
11073
|
-
.output(types_125.storageAdminCapability.methods.dropCollection.output)
|
|
11074
|
-
.mutation(async ({ input, ctx }) => {
|
|
11075
|
-
const { nodeId, ...methodInput } = input;
|
|
11076
|
-
const p = resolveProvider('storage-admin', nodeId, () => getProvider(ctx), createRemoteProxy);
|
|
11077
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument
|
|
11078
|
-
return p.dropCollection(methodInput);
|
|
11079
|
-
}),
|
|
11080
11071
|
listKinds: trpc_middleware_js_1.adminProcedure
|
|
11081
11072
|
.input(types_125.storageAdminCapability.methods.listKinds.input.loose())
|
|
11082
11073
|
.output(types_125.storageAdminCapability.methods.listKinds.output)
|
|
@@ -3400,10 +3400,6 @@ class AddonRegistryService {
|
|
|
3400
3400
|
plannedRunnerIds() {
|
|
3401
3401
|
return [...this.buildAddonGroupPlan([...this.addonEntries.keys()]).keys()];
|
|
3402
3402
|
}
|
|
3403
|
-
/** The forked addon ids (the ones whose Init the D870 guard gates). */
|
|
3404
|
-
forkedAddonIds() {
|
|
3405
|
-
return [...this.buildAddonGroupPlan([...this.addonEntries.keys()]).values()].flatMap((roster) => roster.map((r) => r.addonId));
|
|
3406
|
-
}
|
|
3407
3403
|
/**
|
|
3408
3404
|
* Snapshot of the live runner subprocesses (`$process.list`), reduced to the
|
|
3409
3405
|
* `{ runnerId, addonIds }` shape the convergence planner needs. Returns `[]`
|
|
@@ -22,27 +22,11 @@ const DescriptorSchema = zod_1.z.object({
|
|
|
22
22
|
.readonly()
|
|
23
23
|
.optional(),
|
|
24
24
|
});
|
|
25
|
-
/**
|
|
25
|
+
/** A row as the store reads it: `at` as `lastActive`, plus the descriptor. */
|
|
26
26
|
const RowDataSchema = zod_1.z.object({
|
|
27
27
|
lastActive: zod_1.z.number(),
|
|
28
28
|
descriptor: DescriptorSchema,
|
|
29
29
|
});
|
|
30
|
-
/**
|
|
31
|
-
* @durable class=ledger owner=cluster-agent
|
|
32
|
-
* write="one row per node the hub has ever seen online, GATED BY A READ-BACK.
|
|
33
|
-
* `snapshot()` runs on every 30 s topology pass but commits only when there is no
|
|
34
|
-
* existing row, when the descriptor differs field-by-field, or when the stored
|
|
35
|
-
* `lastActive` has aged past LAST_ACTIVE_HEARTBEAT_MS (5 min) — an unchanged online
|
|
36
|
-
* node therefore writes 288 times a day instead of 2,880, ~864/day for three rows
|
|
37
|
-
* (D131). Off that gate: `touch()` on `$node.disconnected` (the offline edge, always
|
|
38
|
-
* written), `recordPackages` on a node's own declaration (grow-only merge) and
|
|
39
|
-
* `prunePackages` on an explicit undeploy"
|
|
40
|
-
* retention="none — nothing ages a row out; the only deletion is the operator's
|
|
41
|
-
* `forget(nodeId)` behind the inline Forget-node action. Losing the table makes every
|
|
42
|
-
* node that is not in the live Moleculer window vanish from the topology instead of
|
|
43
|
-
* rendering OFFLINE, and empties the package roster the addon back-fill converges to."
|
|
44
|
-
*/
|
|
45
|
-
const COLLECTION = 'cluster-node-history';
|
|
46
30
|
/**
|
|
47
31
|
* How stale `lastActive` may get on an ONLINE node before an otherwise
|
|
48
32
|
* unchanged snapshot is written anyway. Five minutes turns the 30 s topology
|
|
@@ -81,12 +65,9 @@ function samePackages(a, b) {
|
|
|
81
65
|
return (a.length === b.length && a.every((p, i) => p.name === b[i]?.name && p.version === b[i]?.version));
|
|
82
66
|
}
|
|
83
67
|
class ClusterNodeHistoryStore {
|
|
84
|
-
resolveSettingsStore;
|
|
85
68
|
logger;
|
|
86
|
-
declared = false;
|
|
87
69
|
resolveKind;
|
|
88
|
-
constructor(
|
|
89
|
-
this.resolveSettingsStore = resolveSettingsStore;
|
|
70
|
+
constructor(logger, resolveKind = () => null) {
|
|
90
71
|
this.logger = logger;
|
|
91
72
|
this.resolveKind = resolveKind;
|
|
92
73
|
}
|
|
@@ -94,38 +75,6 @@ class ClusterNodeHistoryStore {
|
|
|
94
75
|
bindRecordsKind(resolver) {
|
|
95
76
|
this.resolveKind = resolver;
|
|
96
77
|
}
|
|
97
|
-
/**
|
|
98
|
-
* Idempotently declare the typed collection. Returns the resolved provider
|
|
99
|
-
* or null if the settings-store isn't available yet (early boot / hub
|
|
100
|
-
* unreachable) — callers treat null as "skip, best-effort".
|
|
101
|
-
*/
|
|
102
|
-
async ensureDeclared() {
|
|
103
|
-
if (this.resolveKind() !== null)
|
|
104
|
-
return this.resolveSettingsStore();
|
|
105
|
-
const store = this.resolveSettingsStore();
|
|
106
|
-
if (!store)
|
|
107
|
-
return null;
|
|
108
|
-
if (this.declared)
|
|
109
|
-
return store;
|
|
110
|
-
try {
|
|
111
|
-
await store.declareCollection({
|
|
112
|
-
collection: COLLECTION,
|
|
113
|
-
columns: [
|
|
114
|
-
{ name: 'id', type: 'TEXT', primaryKey: true, notNull: true },
|
|
115
|
-
{ name: 'lastActive', type: 'INTEGER', notNull: true },
|
|
116
|
-
{ name: 'descriptor', type: 'JSON', notNull: true },
|
|
117
|
-
],
|
|
118
|
-
});
|
|
119
|
-
this.declared = true;
|
|
120
|
-
return store;
|
|
121
|
-
}
|
|
122
|
-
catch (err) {
|
|
123
|
-
this.logger.warn('declareCollection failed (best-effort)', {
|
|
124
|
-
meta: { error: (0, types_1.errMsg)(err) },
|
|
125
|
-
});
|
|
126
|
-
return null;
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
78
|
/**
|
|
130
79
|
* Upsert a node's descriptor + addon roster while it is ONLINE, stamping
|
|
131
80
|
* `lastActive = Date.now()`. Called on each `listNodes()` refresh for every
|
|
@@ -145,19 +94,19 @@ class ClusterNodeHistoryStore {
|
|
|
145
94
|
* `$node.disconnected`, and buys 288 writes/day/node instead of 2,880.
|
|
146
95
|
*/
|
|
147
96
|
async snapshot(descriptor) {
|
|
148
|
-
const
|
|
149
|
-
if (
|
|
97
|
+
const kind = this.resolveKind();
|
|
98
|
+
if (kind === null)
|
|
150
99
|
return;
|
|
151
100
|
try {
|
|
152
101
|
// Carry the package roster forward. `listNodes()` does not resolve it
|
|
153
102
|
// (only the reconcile does), so writing this descriptor blind would erase
|
|
154
103
|
// the back-fill's intended set on the very next topology poll.
|
|
155
|
-
const existing = await this.readStored(descriptor.id);
|
|
104
|
+
const existing = await this.readStored(kind, descriptor.id);
|
|
156
105
|
const packages = descriptor.packages ?? existing?.descriptor.packages;
|
|
157
106
|
const next = packages === undefined ? descriptor : { ...descriptor, packages };
|
|
158
107
|
if (existing !== null && !this.worthWriting(existing, next))
|
|
159
108
|
return;
|
|
160
|
-
await this.writeStored(descriptor.id, Date.now(), next);
|
|
109
|
+
await this.writeStored(kind, descriptor.id, Date.now(), next);
|
|
161
110
|
}
|
|
162
111
|
catch (err) {
|
|
163
112
|
this.logger.warn('snapshot upsert failed (best-effort)', {
|
|
@@ -177,47 +126,21 @@ class ClusterNodeHistoryStore {
|
|
|
177
126
|
return !descriptorsEqual(existing.descriptor, next);
|
|
178
127
|
}
|
|
179
128
|
/** Read one node's row, validated. `null` when absent or malformed. */
|
|
180
|
-
async readStored(nodeId) {
|
|
181
|
-
const
|
|
182
|
-
if (
|
|
183
|
-
const row = await kind.get(nodeId);
|
|
184
|
-
if (row === null)
|
|
185
|
-
return null;
|
|
186
|
-
const parsed = RowDataSchema.safeParse({
|
|
187
|
-
lastActive: row.at ?? 0,
|
|
188
|
-
descriptor: row.data.descriptor,
|
|
189
|
-
});
|
|
190
|
-
return parsed.success ? parsed.data : null;
|
|
191
|
-
}
|
|
192
|
-
const store = this.resolveSettingsStore();
|
|
193
|
-
if (!store)
|
|
129
|
+
async readStored(kind, nodeId) {
|
|
130
|
+
const row = await kind.get(nodeId);
|
|
131
|
+
if (row === null)
|
|
194
132
|
return null;
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
if (raw === null || raw === undefined)
|
|
200
|
-
return null;
|
|
201
|
-
const parsed = RowDataSchema.safeParse(raw);
|
|
133
|
+
const parsed = RowDataSchema.safeParse({
|
|
134
|
+
lastActive: row.at ?? 0,
|
|
135
|
+
descriptor: row.data.descriptor,
|
|
136
|
+
});
|
|
202
137
|
return parsed.success ? parsed.data : null;
|
|
203
138
|
}
|
|
204
|
-
async writeStored(nodeId, lastActive, descriptor) {
|
|
205
|
-
const
|
|
206
|
-
if (
|
|
207
|
-
const body = system_1.ClusterNodeHistoryBodySchema.safeParse({ descriptor });
|
|
208
|
-
if (!body.success)
|
|
209
|
-
return;
|
|
210
|
-
await kind.put({ id: nodeId, at: lastActive, data: body.data });
|
|
139
|
+
async writeStored(kind, nodeId, lastActive, descriptor) {
|
|
140
|
+
const body = system_1.ClusterNodeHistoryBodySchema.safeParse({ descriptor });
|
|
141
|
+
if (!body.success)
|
|
211
142
|
return;
|
|
212
|
-
}
|
|
213
|
-
const store = this.resolveSettingsStore();
|
|
214
|
-
if (!store)
|
|
215
|
-
return;
|
|
216
|
-
await store.set({
|
|
217
|
-
collection: COLLECTION,
|
|
218
|
-
key: nodeId,
|
|
219
|
-
value: { lastActive, descriptor },
|
|
220
|
-
});
|
|
143
|
+
await kind.put({ id: nodeId, at: lastActive, data: body.data });
|
|
221
144
|
}
|
|
222
145
|
/** A placeholder descriptor for a node the topology pass has not seen yet. */
|
|
223
146
|
static placeholderDescriptor(nodeId) {
|
|
@@ -242,11 +165,11 @@ class ClusterNodeHistoryStore {
|
|
|
242
165
|
* nothing is delivered rather than something guessed.
|
|
243
166
|
*/
|
|
244
167
|
async getPackages(nodeId) {
|
|
245
|
-
const
|
|
246
|
-
if (
|
|
168
|
+
const kind = this.resolveKind();
|
|
169
|
+
if (kind === null)
|
|
247
170
|
return [];
|
|
248
171
|
try {
|
|
249
|
-
return (await this.readStored(nodeId))?.descriptor.packages ?? [];
|
|
172
|
+
return (await this.readStored(kind, nodeId))?.descriptor.packages ?? [];
|
|
250
173
|
}
|
|
251
174
|
catch (err) {
|
|
252
175
|
this.logger.warn('getPackages failed (best-effort)', {
|
|
@@ -267,11 +190,11 @@ class ClusterNodeHistoryStore {
|
|
|
267
190
|
async recordPackages(nodeId, packages) {
|
|
268
191
|
if (packages.length === 0)
|
|
269
192
|
return;
|
|
270
|
-
const
|
|
271
|
-
if (
|
|
193
|
+
const kind = this.resolveKind();
|
|
194
|
+
if (kind === null)
|
|
272
195
|
return;
|
|
273
196
|
try {
|
|
274
|
-
const existing = await this.readStored(nodeId);
|
|
197
|
+
const existing = await this.readStored(kind, nodeId);
|
|
275
198
|
const merged = new Map((existing?.descriptor.packages ?? []).map((p) => [p.name, p]));
|
|
276
199
|
// The node's current declaration wins on version — it is the authority on
|
|
277
200
|
// what it is actually running.
|
|
@@ -281,7 +204,7 @@ class ClusterNodeHistoryStore {
|
|
|
281
204
|
...(existing?.descriptor ?? ClusterNodeHistoryStore.placeholderDescriptor(nodeId)),
|
|
282
205
|
packages: [...merged.values()],
|
|
283
206
|
};
|
|
284
|
-
await this.writeStored(nodeId, existing?.lastActive ?? Date.now(), descriptor);
|
|
207
|
+
await this.writeStored(kind, nodeId, existing?.lastActive ?? Date.now(), descriptor);
|
|
285
208
|
}
|
|
286
209
|
catch (err) {
|
|
287
210
|
this.logger.warn('recordPackages failed (best-effort)', {
|
|
@@ -298,11 +221,11 @@ class ClusterNodeHistoryStore {
|
|
|
298
221
|
async prunePackages(nodeId, names) {
|
|
299
222
|
if (names.length === 0)
|
|
300
223
|
return;
|
|
301
|
-
const
|
|
302
|
-
if (
|
|
224
|
+
const kind = this.resolveKind();
|
|
225
|
+
if (kind === null)
|
|
303
226
|
return;
|
|
304
227
|
try {
|
|
305
|
-
const existing = await this.readStored(nodeId);
|
|
228
|
+
const existing = await this.readStored(kind, nodeId);
|
|
306
229
|
if (existing === null)
|
|
307
230
|
return;
|
|
308
231
|
const current = existing.descriptor.packages;
|
|
@@ -312,7 +235,7 @@ class ClusterNodeHistoryStore {
|
|
|
312
235
|
const remaining = current.filter((p) => !drop.has(p.name));
|
|
313
236
|
if (remaining.length === current.length)
|
|
314
237
|
return;
|
|
315
|
-
await this.writeStored(nodeId, existing.lastActive, {
|
|
238
|
+
await this.writeStored(kind, nodeId, existing.lastActive, {
|
|
316
239
|
...existing.descriptor,
|
|
317
240
|
packages: remaining,
|
|
318
241
|
});
|
|
@@ -334,27 +257,14 @@ class ClusterNodeHistoryStore {
|
|
|
334
257
|
* time. A no-op if the node was never snapshotted (nothing to update).
|
|
335
258
|
*/
|
|
336
259
|
async touch(nodeId) {
|
|
337
|
-
const
|
|
338
|
-
if (
|
|
260
|
+
const kind = this.resolveKind();
|
|
261
|
+
if (kind === null)
|
|
339
262
|
return;
|
|
340
263
|
try {
|
|
341
|
-
const existing = await this.readStored(nodeId);
|
|
264
|
+
const existing = await this.readStored(kind, nodeId);
|
|
342
265
|
if (existing === null)
|
|
343
266
|
return;
|
|
344
|
-
|
|
345
|
-
if (kind !== null) {
|
|
346
|
-
await kind.put({
|
|
347
|
-
id: nodeId,
|
|
348
|
-
at: Date.now(),
|
|
349
|
-
data: { descriptor: existing.descriptor },
|
|
350
|
-
});
|
|
351
|
-
return;
|
|
352
|
-
}
|
|
353
|
-
await store.update({
|
|
354
|
-
collection: COLLECTION,
|
|
355
|
-
id: nodeId,
|
|
356
|
-
data: { lastActive: Date.now() },
|
|
357
|
-
});
|
|
267
|
+
await this.writeStored(kind, nodeId, Date.now(), existing.descriptor);
|
|
358
268
|
}
|
|
359
269
|
catch (err) {
|
|
360
270
|
this.logger.warn('touch failed (best-effort)', {
|
|
@@ -369,27 +279,21 @@ class ClusterNodeHistoryStore {
|
|
|
369
279
|
}
|
|
370
280
|
/**
|
|
371
281
|
* Read the full persisted history, validated, or `null` when the store did
|
|
372
|
-
* not ANSWER (
|
|
282
|
+
* not ANSWER (the kind is not bound yet, or the read threw). A caller that must not claim
|
|
373
283
|
* a node absent from an unanswered read (D315) uses this; `getAll` folds the
|
|
374
284
|
* `null` into `[]` for the callers that only render what exists. Malformed
|
|
375
285
|
* rows are dropped (and logged) — the rest of the answer still stands.
|
|
376
286
|
*/
|
|
377
287
|
async tryGetAll() {
|
|
378
|
-
const
|
|
379
|
-
if (
|
|
288
|
+
const kind = this.resolveKind();
|
|
289
|
+
if (kind === null)
|
|
380
290
|
return null;
|
|
381
291
|
try {
|
|
382
|
-
const kind = this.resolveKind();
|
|
383
292
|
const result = [];
|
|
384
|
-
const rows = kind
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
}))
|
|
389
|
-
: (await store.query({ collection: COLLECTION })).map((row) => ({
|
|
390
|
-
id: row.id,
|
|
391
|
-
data: row.data,
|
|
392
|
-
}));
|
|
293
|
+
const rows = (await (0, system_1.readAllRows)(kind)).map((row) => ({
|
|
294
|
+
id: row.id,
|
|
295
|
+
data: { lastActive: row.at ?? 0, descriptor: row.data.descriptor },
|
|
296
|
+
}));
|
|
393
297
|
for (const row of rows) {
|
|
394
298
|
const parsed = RowDataSchema.safeParse(row.data);
|
|
395
299
|
if (!parsed.success) {
|
|
@@ -416,21 +320,15 @@ class ClusterNodeHistoryStore {
|
|
|
416
320
|
* 2026-09-01 all three reached the UI as `{"success": true}`.
|
|
417
321
|
*/
|
|
418
322
|
async forget(nodeId) {
|
|
419
|
-
const
|
|
420
|
-
if (
|
|
323
|
+
const kind = this.resolveKind();
|
|
324
|
+
if (kind === null)
|
|
421
325
|
return 'store-unavailable';
|
|
422
326
|
try {
|
|
423
327
|
// Read first: `delete` on this provider is idempotent and cannot tell a
|
|
424
328
|
// removal from a no-op, and "there was nothing to remove" is the answer
|
|
425
329
|
// that stops an operator repeating a working action forever.
|
|
426
|
-
const existed = (await this.readStored(nodeId)) !== null;
|
|
427
|
-
|
|
428
|
-
if (kind !== null) {
|
|
429
|
-
await kind.delete(nodeId);
|
|
430
|
-
}
|
|
431
|
-
else {
|
|
432
|
-
await store.delete({ collection: COLLECTION, key: nodeId });
|
|
433
|
-
}
|
|
330
|
+
const existed = (await this.readStored(kind, nodeId)) !== null;
|
|
331
|
+
await kind.delete(nodeId);
|
|
434
332
|
if (!existed) {
|
|
435
333
|
this.logger.info('cluster node had no history row to forget', { tags: { nodeId } });
|
|
436
334
|
return 'not-found';
|
package/dist/manual-boot.js
CHANGED
|
@@ -76,7 +76,6 @@ const toast_wrapper_service_1 = require("./core/notification/toast-wrapper.servi
|
|
|
76
76
|
const repl_engine_service_1 = require("./core/repl/repl-engine.service");
|
|
77
77
|
const server_update_service_1 = require("./core/server-update/server-update.service");
|
|
78
78
|
const runner_boot_check_1 = require("./core/runner-health/runner-boot-check");
|
|
79
|
-
const update_preflight_1 = require("./core/runner-health/update-preflight");
|
|
80
79
|
const storage_service_1 = require("./core/storage/storage.service");
|
|
81
80
|
const stream_probe_service_1 = require("./core/streaming/stream-probe.service");
|
|
82
81
|
const topology_emitter_service_1 = require("./core/topology/topology-emitter.service");
|
|
@@ -163,11 +162,11 @@ async function bootManual(opts) {
|
|
|
163
162
|
// Same post-construction reason: the cluster-node lifecycle (forget, catalog
|
|
164
163
|
// removal) must leave a per-node line, and `console.log` is not a log store.
|
|
165
164
|
agentRegistryService.setLogger(loggingService.createLogger('ClusterNodes'));
|
|
166
|
-
// A1: durable, routing-blind offline-node history —
|
|
167
|
-
//
|
|
168
|
-
// Wired post-construction so the service's
|
|
169
|
-
|
|
170
|
-
|
|
165
|
+
// A1: durable, routing-blind offline-node history — the `cluster-agent`
|
|
166
|
+
// records kind, bound by the addon registry once the records provider is up
|
|
167
|
+
// (unavailable until then, D902). Wired post-construction so the service's
|
|
168
|
+
// 3-arg constructor stays intact.
|
|
169
|
+
const clusterNodeHistoryStore = new cluster_node_history_store_1.ClusterNodeHistoryStore(loggingService.createLogger('cluster-node-history'));
|
|
171
170
|
agentRegistryService.setClusterNodeHistoryStore(clusterNodeHistoryStore);
|
|
172
171
|
addonRegistryService.setClusterNodeHistoryStore(clusterNodeHistoryStore);
|
|
173
172
|
// ---- Layer 4: need AddonRegistry ---------------------------------------
|
|
@@ -287,16 +286,7 @@ async function bootManual(opts) {
|
|
|
287
286
|
});
|
|
288
287
|
},
|
|
289
288
|
});
|
|
290
|
-
const settingsStoreOrNull = () => capabilityService.getRegistry()?.getSingleton('settings-store') ?? null;
|
|
291
289
|
const serverUpdateService = new server_update_service_1.ServerUpdateService({
|
|
292
|
-
updatePreflight: (0, update_preflight_1.buildUpdatePreflight)({
|
|
293
|
-
logger: loggingService.createLogger('UpdatePreflight'),
|
|
294
|
-
forkedAddonIds: () => addonRegistryService.forkedAddonIds(),
|
|
295
|
-
store: () => {
|
|
296
|
-
const store = settingsStoreOrNull();
|
|
297
|
-
return store === null ? null : (0, update_preflight_1.legacyGuardClientOf)(store);
|
|
298
|
-
},
|
|
299
|
-
}),
|
|
300
290
|
runnerBootCheck: () => hubRunnerBootCheck.current(),
|
|
301
291
|
logger: loggingService.createLogger('ServerUpdate'),
|
|
302
292
|
restartServer: (requestedBy, update) => addonPackageService.restartServer(requestedBy, update),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/server",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.612",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"private": false,
|
|
6
6
|
"files": [
|
|
@@ -38,19 +38,19 @@
|
|
|
38
38
|
]
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@camstack/addon-admin-ui": "1.2.
|
|
42
|
-
"@camstack/addon-agent-ui": "1.2.
|
|
43
|
-
"@camstack/addon-auth": "1.2.
|
|
44
|
-
"@camstack/addon-decoder-nodeav": "1.2.
|
|
45
|
-
"@camstack/addon-notifiers": "1.2.
|
|
46
|
-
"@camstack/addon-pipeline": "1.2.
|
|
47
|
-
"@camstack/addon-pipeline-orchestrator": "1.2.
|
|
48
|
-
"@camstack/addon-post-analysis": "1.2.
|
|
49
|
-
"@camstack/develop": "0.1.
|
|
50
|
-
"@camstack/sdk": "1.2.
|
|
51
|
-
"@camstack/system": "1.2.
|
|
52
|
-
"@camstack/types": "1.2.
|
|
53
|
-
"@camstack/ui-library": "1.2.
|
|
41
|
+
"@camstack/addon-admin-ui": "1.2.448",
|
|
42
|
+
"@camstack/addon-agent-ui": "1.2.254",
|
|
43
|
+
"@camstack/addon-auth": "1.2.159",
|
|
44
|
+
"@camstack/addon-decoder-nodeav": "1.2.134",
|
|
45
|
+
"@camstack/addon-notifiers": "1.2.612",
|
|
46
|
+
"@camstack/addon-pipeline": "1.2.612",
|
|
47
|
+
"@camstack/addon-pipeline-orchestrator": "1.2.614",
|
|
48
|
+
"@camstack/addon-post-analysis": "1.2.619",
|
|
49
|
+
"@camstack/develop": "0.1.24",
|
|
50
|
+
"@camstack/sdk": "1.2.144",
|
|
51
|
+
"@camstack/system": "1.2.462",
|
|
52
|
+
"@camstack/types": "1.2.394",
|
|
53
|
+
"@camstack/ui-library": "1.2.311",
|
|
54
54
|
"@fastify/compress": "^9.0.0",
|
|
55
55
|
"@fastify/cookie": "^11.0.2",
|
|
56
56
|
"@fastify/cors": "^11.2.0",
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.LEGACY_BLOB_GUARD_SINCE = void 0;
|
|
4
|
-
exports.buildUpdatePreflight = buildUpdatePreflight;
|
|
5
|
-
exports.legacyGuardClientOf = legacyGuardClientOf;
|
|
6
|
-
/**
|
|
7
|
-
* The `applyServerUpdate` pre-flight (D877).
|
|
8
|
-
*
|
|
9
|
-
* Question: would the TARGET version refuse to start any addon on THIS node's
|
|
10
|
-
* live data? Today there is one deterministic Init refusal the framework can
|
|
11
|
-
* pre-check: the D870 legacy-blob guard (`assertLegacyBlobsMigrated`) - an addon
|
|
12
|
-
* whose settings still sit in its per-addon blob tables while the standard store
|
|
13
|
-
* holds none.
|
|
14
|
-
*
|
|
15
|
-
* The store-shape check is deliberately version-independent: the live store is
|
|
16
|
-
* what it is, so the only version question is "does the target contain the
|
|
17
|
-
* guard?" - answered by {@link LEGACY_BLOB_GUARD_SINCE}. The honest limit: it
|
|
18
|
-
* runs inside the version that ships it, so it protects updates FROM this
|
|
19
|
-
* version onwards; an update from an older hub never ran it. And it knows only
|
|
20
|
-
* the refusals listed here - a new deterministic Init refusal has to be added
|
|
21
|
-
* to this module to be pre-checked.
|
|
22
|
-
*/
|
|
23
|
-
const system_1 = require("@camstack/system");
|
|
24
|
-
const index_js_1 = require("../../server-root/index.js");
|
|
25
|
-
/** The first server version whose addons run `assertLegacyBlobsMigrated` at Init. */
|
|
26
|
-
exports.LEGACY_BLOB_GUARD_SINCE = '1.2.585';
|
|
27
|
-
function buildUpdatePreflight(deps) {
|
|
28
|
-
return async (targetVersion) => {
|
|
29
|
-
if ((0, index_js_1.compareSemver)(targetVersion, exports.LEGACY_BLOB_GUARD_SINCE) < 0)
|
|
30
|
-
return [];
|
|
31
|
-
const store = deps.store();
|
|
32
|
-
if (store === null) {
|
|
33
|
-
throw new Error('the settings store is not available to pre-check the update');
|
|
34
|
-
}
|
|
35
|
-
const blockers = [];
|
|
36
|
-
for (const addonId of deps.forkedAddonIds()) {
|
|
37
|
-
try {
|
|
38
|
-
await (0, system_1.assertLegacyBlobsMigrated)(store, addonId, deps.logger);
|
|
39
|
-
}
|
|
40
|
-
catch (err) {
|
|
41
|
-
// A refusal is the finding; any other error is "could not ask" and the
|
|
42
|
-
// caller treats a throw as exactly that (it never blocks on it).
|
|
43
|
-
if (!(err instanceof system_1.UnmigratedSettingsError))
|
|
44
|
-
throw err;
|
|
45
|
-
blockers.push({
|
|
46
|
-
addonId,
|
|
47
|
-
reason: err.message,
|
|
48
|
-
remedy: system_1.UNMIGRATED_SETTINGS_REMEDY,
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
return blockers;
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
/** The three store calls the guard makes, over the hub's `settings-store` provider. */
|
|
56
|
-
function legacyGuardClientOf(store) {
|
|
57
|
-
return {
|
|
58
|
-
query: { query: (input) => store.query(input) },
|
|
59
|
-
get: { query: (input) => store.get(input) },
|
|
60
|
-
count: { query: (input) => store.count(input) },
|
|
61
|
-
};
|
|
62
|
-
}
|