@elench/testkit 0.1.149 → 0.1.151

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/README.md +29 -9
  2. package/lib/cli/assistant/view-model.mjs +1 -1
  3. package/lib/cli/components/blocks/run-tree.mjs +1 -1
  4. package/lib/cli/renderers/run/events.mjs +4 -3
  5. package/lib/cli/renderers/run/failure.mjs +2 -2
  6. package/lib/cli/renderers/run/inline-detail.mjs +2 -2
  7. package/lib/cli/renderers/run/interactive.mjs +2 -2
  8. package/lib/cli/renderers/run/text-reporter.mjs +9 -9
  9. package/lib/cli/state/run/model.mjs +7 -7
  10. package/lib/cli/state/run/state.mjs +3 -3
  11. package/lib/cli/terminal/colors.mjs +1 -1
  12. package/lib/config/database-materialization.mjs +25 -0
  13. package/lib/config/database.mjs +30 -0
  14. package/lib/config/index.mjs +47 -1
  15. package/lib/config/runtime.mjs +130 -0
  16. package/lib/config-api/index.d.ts +28 -0
  17. package/lib/config-api/index.mjs +6 -0
  18. package/lib/database/cleanup.mjs +76 -1
  19. package/lib/database/constants.mjs +3 -0
  20. package/lib/database/index.mjs +6 -0
  21. package/lib/database/local-postgres.mjs +123 -4
  22. package/lib/database/naming.mjs +7 -0
  23. package/lib/database/resource-postgres.mjs +13 -0
  24. package/lib/database/state-files.mjs +17 -0
  25. package/lib/docker-compat/matrix.mjs +5 -3
  26. package/lib/kiln/client.mjs +8 -0
  27. package/lib/local/kiln-driver.mjs +96 -68
  28. package/lib/ownership/docker.mjs +67 -1
  29. package/lib/regressions/github-transport.mjs +178 -4
  30. package/lib/regressions/github.mjs +52 -16
  31. package/lib/regressions/index.d.ts +58 -29
  32. package/lib/regressions/index.mjs +171 -58
  33. package/lib/regressions/workflow.mjs +266 -0
  34. package/lib/results/artifacts.mjs +8 -7
  35. package/lib/runner/formatting.mjs +17 -16
  36. package/lib/runner/orchestrator.mjs +6 -5
  37. package/lib/runner/planning.mjs +40 -0
  38. package/lib/runner/regressions.mjs +183 -33
  39. package/lib/runner/reporting.mjs +1 -1
  40. package/lib/runner/run-finalization.mjs +34 -4
  41. package/lib/runner/runtime-manager.mjs +91 -10
  42. package/lib/runner/scheduler/index.mjs +30 -1
  43. package/lib/runtime/index.d.ts +5 -5
  44. package/lib/runtime-src/k6/http.js +11 -11
  45. package/node_modules/@elench/next-analysis/package.json +1 -1
  46. package/node_modules/@elench/testkit-bridge/package.json +2 -2
  47. package/node_modules/@elench/testkit-protocol/package.json +1 -1
  48. package/node_modules/@elench/ts-analysis/package.json +1 -1
  49. package/node_modules/es-toolkit/CHANGELOG.md +801 -0
  50. package/node_modules/es-toolkit/src/compat/_internal/Equals.d.ts +1 -0
  51. package/node_modules/es-toolkit/src/compat/_internal/IsWritable.d.ts +3 -0
  52. package/node_modules/es-toolkit/src/compat/_internal/MutableList.d.ts +4 -0
  53. package/node_modules/es-toolkit/src/compat/_internal/RejectReadonly.d.ts +4 -0
  54. package/node_modules/esprima/ChangeLog +235 -0
  55. package/package.json +6 -5
  56. package/packages/testkit-bridge/node_modules/@elench/testkit-protocol/dist/index.d.ts +0 -188
  57. package/packages/testkit-bridge/node_modules/@elench/testkit-protocol/dist/index.d.ts.map +0 -1
  58. package/packages/testkit-bridge/node_modules/@elench/testkit-protocol/dist/index.js +0 -293
  59. package/packages/testkit-bridge/node_modules/@elench/testkit-protocol/dist/index.js.map +0 -1
  60. package/packages/testkit-bridge/node_modules/@elench/testkit-protocol/package.json +0 -25
@@ -12,6 +12,7 @@ export function createRuntimeManager({ productDir, graphs, lifecycle, hooks = {}
12
12
  const graphByKey = new Map(graphs.map((graph) => [graph.key, graph]));
13
13
  const pools = new Map();
14
14
  const locks = new Map();
15
+ const resourceBudgets = createResourceBudgetState(graphs);
15
16
  const failedGraphs = new Map();
16
17
  let nextLeaseCounter = 1;
17
18
  const runtimeHooks = {
@@ -32,7 +33,7 @@ export function createRuntimeManager({ productDir, graphs, lifecycle, hooks = {}
32
33
  if (!locksAvailable(locks, task.locks || [])) {
33
34
  return false;
34
35
  }
35
- return claimableRuntimeSlot(pool, task) !== null;
36
+ return claimableRuntimeSlot(pool, task, resourceBudgets) !== null;
36
37
  },
37
38
  async acquire(task) {
38
39
  const pool = getPool(pools, graphByKey, task, productDir, lifecycle);
@@ -47,7 +48,7 @@ export function createRuntimeManager({ productDir, graphs, lifecycle, hooks = {}
47
48
  throw new Error(`Task ${task.id} was claimed before its locks were available`);
48
49
  }
49
50
 
50
- const slot = claimRuntimeSlot(pool, task);
51
+ const slot = claimRuntimeSlot(pool, task, resourceBudgets);
51
52
  if (!slot) {
52
53
  releaseLocks(locks, task.locks || [], leaseId);
53
54
  throw new Error(`Task ${task.id} was claimed before runtime capacity was available`);
@@ -69,7 +70,8 @@ export function createRuntimeManager({ productDir, graphs, lifecycle, hooks = {}
69
70
  releaseRuntimeSlot(slot, task);
70
71
  releaseLocks(locks, task.locks || [], leaseId);
71
72
  cleanupLeaseDir({ leaseDir: path.join(slot.context?.runtimeDir || productDir, "leases", leaseId) });
72
- await drainRuntimeSlot(slot, lifecycle, runtimeHooks);
73
+ if (!slot.context) releaseSlotResources(slot, resourceBudgets);
74
+ await drainRuntimeSlot(slot, lifecycle, runtimeHooks, resourceBudgets);
73
75
  if (!lifecycle.isStopRequested()) {
74
76
  markGraphFailed(failedGraphs, task.graphKey, formatError(error));
75
77
  }
@@ -85,14 +87,14 @@ export function createRuntimeManager({ productDir, graphs, lifecycle, hooks = {}
85
87
  lease.slot.draining = true;
86
88
  }
87
89
  if (lease.slot.draining && lease.slot.activeLeaseCount === 0) {
88
- await drainRuntimeSlot(lease.slot, lifecycle, runtimeHooks);
90
+ await drainRuntimeSlot(lease.slot, lifecycle, runtimeHooks, resourceBudgets);
89
91
  }
90
92
  },
91
93
  async cleanupAll() {
92
94
  for (const pool of pools.values()) {
93
95
  for (const slot of pool.slots) {
94
96
  slot.draining = true;
95
- await drainRuntimeSlot(slot, lifecycle, runtimeHooks);
97
+ await drainRuntimeSlot(slot, lifecycle, runtimeHooks, resourceBudgets);
96
98
  }
97
99
  }
98
100
  },
@@ -109,7 +111,22 @@ export function createRuntimeManager({ productDir, graphs, lifecycle, hooks = {}
109
111
  runtimeId: slot.runtimeId,
110
112
  peakLeaseCount: slot.peakLeaseCount,
111
113
  peakResourceUnits: slot.peakResourceUnits,
114
+ resourceReservations: (slot.resourceReservations || []).map((reservation) => ({ ...reservation })),
112
115
  })),
116
+ resourceBudgets: [...resourceBudgets.values()]
117
+ .filter((budget) =>
118
+ pool.slots.some((slot) =>
119
+ (slot.graph.resourceReservations || []).some((reservation) => reservation.key === budget.key)
120
+ )
121
+ )
122
+ .map((budget) => ({
123
+ key: budget.key,
124
+ capacity: budget.capacity,
125
+ reserved: budget.reserved,
126
+ available: budget.available,
127
+ active: budget.active,
128
+ peakActive: budget.peakActive,
129
+ })),
113
130
  }))
114
131
  .sort((left, right) => String(left.graphKey).localeCompare(String(right.graphKey)));
115
132
  },
@@ -156,6 +173,7 @@ function getPool(pools, graphByKey, task, productDir, lifecycle) {
156
173
  contextPromise: null,
157
174
  activeLeaseCount: 0,
158
175
  activeResourceUnits: 0,
176
+ resourceReservations: [],
159
177
  peakLeaseCount: 0,
160
178
  peakResourceUnits: 0,
161
179
  draining: false,
@@ -165,13 +183,13 @@ function getPool(pools, graphByKey, task, productDir, lifecycle) {
165
183
  return pool;
166
184
  }
167
185
 
168
- function claimRuntimeSlot(pool, task) {
186
+ function claimRuntimeSlot(pool, task, resourceBudgets) {
169
187
  const resourceCost = task.resourceCost || 1;
170
188
  const available = pool.slots.filter((slot) => !slot.draining);
171
189
  if (available.length === 0) return null;
172
190
 
173
191
  const slot = [...available]
174
- .filter((candidate) => slotHasCapacity(candidate, resourceCost))
192
+ .filter((candidate) => slotHasCapacity(candidate, resourceCost) && slotResourceBudgetsAvailable(candidate, resourceBudgets))
175
193
  .sort(
176
194
  (left, right) =>
177
195
  left.activeResourceUnits - right.activeResourceUnits ||
@@ -179,6 +197,7 @@ function claimRuntimeSlot(pool, task) {
179
197
  left.runtimeId.localeCompare(right.runtimeId)
180
198
  )[0];
181
199
  if (!slot) return null;
200
+ reserveSlotResources(slot, resourceBudgets);
182
201
  slot.activeLeaseCount += 1;
183
202
  slot.activeResourceUnits += resourceCost;
184
203
  slot.peakLeaseCount = Math.max(slot.peakLeaseCount, slot.activeLeaseCount);
@@ -209,9 +228,10 @@ async function getReadyContext(slot, productDir, task, lifecycle, runtimeHooks)
209
228
  return slot.context;
210
229
  }
211
230
 
212
- async function drainRuntimeSlot(slot, lifecycle, runtimeHooks) {
231
+ async function drainRuntimeSlot(slot, lifecycle, runtimeHooks, resourceBudgets) {
213
232
  if (!slot.context || slot.activeLeaseCount > 0) return;
214
233
  await runtimeHooks.cleanupRuntimeInstanceContext(slot.context, lifecycle);
234
+ releaseSlotResources(slot, resourceBudgets);
215
235
  slot.context = null;
216
236
  slot.contextPromise = null;
217
237
  slot.draining = false;
@@ -234,10 +254,15 @@ function locksAvailable(lockMap, lockNames) {
234
254
  return [...new Set(lockNames)].every((lockName) => !lockMap.has(lockName));
235
255
  }
236
256
 
237
- function claimableRuntimeSlot(pool, task) {
257
+ function claimableRuntimeSlot(pool, task, resourceBudgets) {
238
258
  const resourceCost = task.resourceCost || 1;
239
259
  return (
240
- pool.slots.find((slot) => !slot.draining && slotHasCapacity(slot, resourceCost)) || null
260
+ pool.slots.find(
261
+ (slot) =>
262
+ !slot.draining &&
263
+ slotHasCapacity(slot, resourceCost) &&
264
+ slotResourceBudgetsAvailable(slot, resourceBudgets)
265
+ ) || null
241
266
  );
242
267
  }
243
268
 
@@ -245,6 +270,62 @@ function slotHasCapacity(slot, resourceCost) {
245
270
  return slot.activeResourceUnits + resourceCost <= slot.graph.maxConcurrentTasks;
246
271
  }
247
272
 
273
+ function createResourceBudgetState(graphs) {
274
+ const budgets = new Map();
275
+ for (const graph of graphs) {
276
+ for (const reservation of graph.resourceReservations || []) {
277
+ const existing = budgets.get(reservation.key) || {
278
+ key: reservation.key,
279
+ capacity: reservation.capacity || 0,
280
+ reserved: reservation.reserved || 0,
281
+ available: reservation.available || Math.max(0, (reservation.capacity || 0) - (reservation.reserved || 0)),
282
+ active: 0,
283
+ peakActive: 0,
284
+ };
285
+ existing.capacity = Math.max(existing.capacity, reservation.capacity || 0);
286
+ existing.reserved = Math.max(existing.reserved, reservation.reserved || 0);
287
+ existing.available = Math.max(0, existing.capacity - existing.reserved);
288
+ budgets.set(reservation.key, existing);
289
+ }
290
+ }
291
+ return budgets;
292
+ }
293
+
294
+ function slotResourceBudgetsAvailable(slot, resourceBudgets) {
295
+ if (slot.resourceReservations?.length > 0) return true;
296
+ return (slot.graph.resourceReservations || []).every((reservation) => {
297
+ const budget = resourceBudgets.get(reservation.key);
298
+ if (!budget) return true;
299
+ return budget.active + reservation.perRuntime <= budget.available;
300
+ });
301
+ }
302
+
303
+ function reserveSlotResources(slot, resourceBudgets) {
304
+ if (slot.resourceReservations?.length > 0) return;
305
+ const reservations = [];
306
+ for (const reservation of slot.graph.resourceReservations || []) {
307
+ const budget = resourceBudgets.get(reservation.key);
308
+ if (!budget) continue;
309
+ budget.active += reservation.perRuntime;
310
+ budget.peakActive = Math.max(budget.peakActive, budget.active);
311
+ reservations.push({
312
+ key: reservation.key,
313
+ units: reservation.perRuntime,
314
+ services: reservation.services || [],
315
+ });
316
+ }
317
+ slot.resourceReservations = reservations;
318
+ }
319
+
320
+ function releaseSlotResources(slot, resourceBudgets) {
321
+ for (const reservation of slot.resourceReservations || []) {
322
+ const budget = resourceBudgets.get(reservation.key);
323
+ if (!budget) continue;
324
+ budget.active = Math.max(0, budget.active - reservation.units);
325
+ }
326
+ slot.resourceReservations = [];
327
+ }
328
+
248
329
  function releaseLocks(lockMap, lockNames, leaseId) {
249
330
  for (const lockName of [...new Set(lockNames)].sort()) {
250
331
  if (lockMap.get(lockName) === leaseId) {
@@ -69,12 +69,13 @@ export function buildScheduledQueue(servicePlans, graphs, { timings, history } =
69
69
  }));
70
70
  }
71
71
 
72
- export function buildRunPlanningMetadata(queue) {
72
+ export function buildRunPlanningMetadata(queue, graphs = []) {
73
73
  return {
74
74
  scheduler: {
75
75
  policy: SCHEDULER_POLICY,
76
76
  version: SCHEDULER_VERSION,
77
77
  },
78
+ resourceBudgets: buildPlanningResourceBudgets(graphs),
78
79
  tasks: (queue || []).map((task) => ({
79
80
  rank: task.schedulerRank || null,
80
81
  id: task.id,
@@ -94,6 +95,34 @@ export function buildRunPlanningMetadata(queue) {
94
95
  };
95
96
  }
96
97
 
98
+ function buildPlanningResourceBudgets(graphs) {
99
+ const byKey = new Map();
100
+ for (const graph of graphs || []) {
101
+ for (const reservation of graph.resourceReservations || []) {
102
+ const existing = byKey.get(reservation.key) || {
103
+ key: reservation.key,
104
+ kind: reservation.kind,
105
+ scope: reservation.scope,
106
+ resourceName: reservation.resourceName,
107
+ capacity: reservation.capacity,
108
+ reserved: reservation.reserved,
109
+ available: reservation.available,
110
+ graphs: [],
111
+ };
112
+ existing.capacity = Math.max(existing.capacity || 0, reservation.capacity || 0);
113
+ existing.reserved = Math.max(existing.reserved || 0, reservation.reserved || 0);
114
+ existing.available = Math.max(0, existing.capacity - existing.reserved);
115
+ existing.graphs.push({
116
+ graphKey: graph.key,
117
+ services: reservation.services || [],
118
+ perRuntime: reservation.perRuntime,
119
+ });
120
+ byKey.set(reservation.key, existing);
121
+ }
122
+ }
123
+ return [...byKey.values()].sort((left, right) => left.key.localeCompare(right.key));
124
+ }
125
+
97
126
  export function compareScheduledTasks(a, b) {
98
127
  return (
99
128
  b.estimatedDurationMs - a.estimatedDurationMs ||
@@ -245,7 +245,7 @@ export interface RawRequestClient {
245
245
  extraHeaders?: RuntimeHeaders
246
246
  ): RuntimeResponse;
247
247
  as(actorName: string): RawRequestClient;
248
- delete(path: string, extraHeaders?: RuntimeHeaders): RuntimeResponse;
248
+ delete(path: string, body?: unknown, extraHeaders?: RuntimeHeaders): RuntimeResponse;
249
249
  get(path: string, extraHeaders?: RuntimeHeaders): RuntimeResponse;
250
250
  headers(extraHeaders?: RuntimeHeaders): RuntimeHeaders;
251
251
  multipart: MultipartRequestClient;
@@ -269,7 +269,7 @@ export interface ActorRequestClient {
269
269
  body?: unknown,
270
270
  extraHeaders?: RuntimeHeaders
271
271
  ): RuntimeResponse;
272
- rawDelete(path: string, extraHeaders?: RuntimeHeaders): RuntimeResponse;
272
+ rawDelete(path: string, body?: unknown, extraHeaders?: RuntimeHeaders): RuntimeResponse;
273
273
  rawGet(path: string, extraHeaders?: RuntimeHeaders): RuntimeResponse;
274
274
  rawHeaders(extraHeaders?: RuntimeHeaders): RuntimeHeaders;
275
275
  rawMultipart: MultipartRequestClient;
@@ -277,7 +277,7 @@ export interface ActorRequestClient {
277
277
  rawPost(path: string, body?: unknown, extraHeaders?: RuntimeHeaders): RuntimeResponse;
278
278
  rawPut(path: string, body?: unknown, extraHeaders?: RuntimeHeaders): RuntimeResponse;
279
279
  rawReq: RawRequestClient;
280
- delete(path: string, extraHeaders?: RuntimeHeaders): RuntimeResponse;
280
+ delete(path: string, body?: unknown, extraHeaders?: RuntimeHeaders): RuntimeResponse;
281
281
  get(path: string, extraHeaders?: RuntimeHeaders): RuntimeResponse;
282
282
  patch(path: string, body?: unknown, extraHeaders?: RuntimeHeaders): RuntimeResponse;
283
283
  post(path: string, body?: unknown, extraHeaders?: RuntimeHeaders): RuntimeResponse;
@@ -301,12 +301,12 @@ export interface HttpClient<TSetup = unknown> {
301
301
  as(actorName: string): ActorRequestClient;
302
302
  headers(extraHeaders?: RuntimeHeaders): RuntimeHeaders;
303
303
  multipart: MultipartRequestClient;
304
- delete(path: string, extraHeaders?: RuntimeHeaders): RuntimeResponse;
304
+ delete(path: string, body?: unknown, extraHeaders?: RuntimeHeaders): RuntimeResponse;
305
305
  get(path: string, extraHeaders?: RuntimeHeaders): RuntimeResponse;
306
306
  patch(path: string, body?: unknown, extraHeaders?: RuntimeHeaders): RuntimeResponse;
307
307
  post(path: string, body?: unknown, extraHeaders?: RuntimeHeaders): RuntimeResponse;
308
308
  put(path: string, body?: unknown, extraHeaders?: RuntimeHeaders): RuntimeResponse;
309
- rawDelete(path: string, extraHeaders?: RuntimeHeaders): RuntimeResponse;
309
+ rawDelete(path: string, body?: unknown, extraHeaders?: RuntimeHeaders): RuntimeResponse;
310
310
  rawGet(path: string, extraHeaders?: RuntimeHeaders): RuntimeResponse;
311
311
  rawHeaders(actorName?: string | null, extraHeaders?: RuntimeHeaders): RuntimeHeaders;
312
312
  rawMultipart: MultipartRequestClient;
@@ -137,8 +137,8 @@ export function createHttpClient(config) {
137
137
  return resolvedRawHeadersFor(actorName, extraHeaders);
138
138
  },
139
139
  rawReq: actorRawReq,
140
- delete(path, extraHeaders = {}) {
141
- return requestAs(actorName, "DELETE", path, null, extraHeaders);
140
+ delete(path, body = null, extraHeaders = {}) {
141
+ return requestAs(actorName, "DELETE", path, body, extraHeaders);
142
142
  },
143
143
  get(path, extraHeaders = {}) {
144
144
  return requestAs(actorName, "GET", path, null, extraHeaders);
@@ -158,8 +158,8 @@ export function createHttpClient(config) {
158
158
  raw(method, path, body, extraHeaders = {}) {
159
159
  return actorRawReq(method, path, body, extraHeaders);
160
160
  },
161
- rawDelete(path, extraHeaders = {}) {
162
- return actorRawReq.delete(path, extraHeaders);
161
+ rawDelete(path, body = null, extraHeaders = {}) {
162
+ return actorRawReq.delete(path, body, extraHeaders);
163
163
  },
164
164
  rawGet(path, extraHeaders = {}) {
165
165
  return actorRawReq.get(path, extraHeaders);
@@ -208,8 +208,8 @@ export function createHttpClient(config) {
208
208
  invoker.post = (path, body, extraHeaders = {}) => rawAs(defaultRawActor, "POST", path, body, extraHeaders);
209
209
  invoker.put = (path, body, extraHeaders = {}) => rawAs(defaultRawActor, "PUT", path, body, extraHeaders);
210
210
  invoker.patch = (path, body, extraHeaders = {}) => rawAs(defaultRawActor, "PATCH", path, body, extraHeaders);
211
- invoker.delete = (path, extraHeaders = {}) =>
212
- rawAs(defaultRawActor, "DELETE", path, null, extraHeaders);
211
+ invoker.delete = (path, body = null, extraHeaders = {}) =>
212
+ rawAs(defaultRawActor, "DELETE", path, body, extraHeaders);
213
213
  invoker.headers = (extraHeaders = {}) => resolvedRawHeadersFor(defaultRawActor, extraHeaders);
214
214
  invoker.as = (actorName) => {
215
215
  ensureKnownActor(actorName);
@@ -264,8 +264,8 @@ export function createHttpClient(config) {
264
264
  patch(path, body, extraHeaders = {}) {
265
265
  return defaultClient.patch(path, body, extraHeaders);
266
266
  },
267
- delete(path, extraHeaders = {}) {
268
- return defaultClient.delete(path, extraHeaders);
267
+ delete(path, body = null, extraHeaders = {}) {
268
+ return defaultClient.delete(path, body, extraHeaders);
269
269
  },
270
270
  rawGet(path, extraHeaders = {}) {
271
271
  return rawClient.get(path, extraHeaders);
@@ -279,8 +279,8 @@ export function createHttpClient(config) {
279
279
  rawPatch(path, body, extraHeaders = {}) {
280
280
  return rawClient.patch(path, body, extraHeaders);
281
281
  },
282
- rawDelete(path, extraHeaders = {}) {
283
- return rawClient.delete(path, extraHeaders);
282
+ rawDelete(path, body = null, extraHeaders = {}) {
283
+ return rawClient.delete(path, body, extraHeaders);
284
284
  },
285
285
  multipart: {
286
286
  post(path, payload, extraHeaders = {}) {
@@ -351,7 +351,7 @@ function runHttpRequest(method, path, url, body, headers, actorRecord = null, re
351
351
  else if (method === "PUT") rawResponse = http.put(url, requestBody, transportOptions);
352
352
  else if (method === "POST") rawResponse = http.post(url, requestBody, transportOptions);
353
353
  else if (method === "PATCH") rawResponse = http.patch(url, requestBody, transportOptions);
354
- else if (method === "DELETE") rawResponse = http.del(url, null, transportOptions);
354
+ else if (method === "DELETE") rawResponse = http.del(url, requestBody, transportOptions);
355
355
  else throw new Error(`unsupported method: ${method}`);
356
356
 
357
357
  finalizeTrace(trace, rawResponse);
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elench/next-analysis",
3
- "version": "0.1.149",
3
+ "version": "0.1.151",
4
4
  "description": "SWC-backed Next.js source analysis primitives for Erench tools",
5
5
  "type": "module",
6
6
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elench/testkit-bridge",
3
- "version": "0.1.149",
3
+ "version": "0.1.151",
4
4
  "description": "Browser bridge helpers for testkit",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -22,7 +22,7 @@
22
22
  "typecheck": "tsc -p tsconfig.json --noEmit"
23
23
  },
24
24
  "dependencies": {
25
- "@elench/testkit-protocol": "0.1.149"
25
+ "@elench/testkit-protocol": "0.1.151"
26
26
  },
27
27
  "private": false
28
28
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elench/testkit-protocol",
3
- "version": "0.1.149",
3
+ "version": "0.1.151",
4
4
  "description": "Shared browser protocol for testkit bridge and extension consumers",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elench/ts-analysis",
3
- "version": "0.1.149",
3
+ "version": "0.1.151",
4
4
  "description": "TypeScript compiler-backed source analysis primitives for Erench tools",
5
5
  "type": "module",
6
6
  "exports": {