bulletin-deploy 0.7.13 → 0.7.14-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { deploy, DEFAULT_BULLETIN_RPC, DEFAULT_POOL_SIZE, NonRetryableError, EXIT_CODE_NO_RETRY } from "../dist/deploy.js";
3
+ import { deploy, DEFAULT_BULLETIN_RPC, DEFAULT_POOL_SIZE, NonRetryableError, EXIT_CODE_NO_RETRY, isConnectionError } from "../dist/deploy.js";
4
4
  import { VERSION, setDeployAttribute, captureWarning, closeTelemetry, setRunStateActive, markRelaunchOomHintShown } from "../dist/telemetry.js";
5
5
  import { handleFailedDeploy, preReleaseWarning } from "../dist/version-check.js";
6
6
  import { setDeployContext, installLogCapture, buildCliFlagsSummary } from "../dist/bug-report.js";
@@ -162,6 +162,7 @@ if (!flags.help && !flags.version) {
162
162
  if (finalizing) return;
163
163
  finalizing = true;
164
164
  try {
165
+ setDeployAttribute("deploy.status", "killed");
165
166
  setDeployAttribute("deploy.killed", reason);
166
167
  setDeployAttribute("deploy.sad", "true");
167
168
  captureWarning(`deploy process terminated: ${reason}`);
@@ -173,15 +174,30 @@ if (!flags.help && !flags.version) {
173
174
  process.exit(exitCode);
174
175
  };
175
176
 
176
- process.on("uncaughtException", (e) => {
177
- try { setDeployAttribute("deploy.error", (e?.message ?? String(e)).slice(0, 200)); } catch {}
178
- finalize("uncaught", 2);
179
- });
180
- process.on("unhandledRejection", (e) => {
181
- const msg = e instanceof Error ? e.message : String(e);
182
- try { setDeployAttribute("deploy.error", msg.slice(0, 200)); } catch {}
183
- finalize("unhandled", 2);
184
- });
177
+ // Connection errors propagate from polkadot-api's internal subscriptions
178
+ // (chainHead etc.) when the WS halts mid-call. They're recoverable via
179
+ // storeChunkedContent's reconnect path; don't exit. The retry-budget
180
+ // circuit breaker (#271) bounds repeat occurrences — if too many fire in
181
+ // 30s, the deploy bails cleanly with "Retry budget exhausted" instead of
182
+ // looping forever. Issue #278 has the full diagnosis.
183
+ const handleUnhandled = (e, kind) => {
184
+ const msgStr = e instanceof Error ? (e.message ?? "") : String(e);
185
+ // Debug breadcrumb — gated by env so it doesn't add stderr noise in
186
+ // production but helps when running E2E fault-injection scenarios.
187
+ if (process.env.BULLETIN_DEPLOY_DEBUG_HANDLERS === "1") {
188
+ console.error(`[handleUnhandled ${kind}] match=${isConnectionError(e)} type=${e?.constructor?.name ?? typeof e} msg=${msgStr.slice(0, 200)}`);
189
+ }
190
+ if (isConnectionError(e)) {
191
+ try {
192
+ captureWarning(`Suppressed ${kind} connection error`, { msg: msgStr.slice(0, 200) });
193
+ } catch { /* telemetry best-effort */ }
194
+ return;
195
+ }
196
+ try { setDeployAttribute("deploy.error", msgStr.slice(0, 200)); } catch {}
197
+ finalize(kind, 2);
198
+ };
199
+ process.on("uncaughtException", (e) => handleUnhandled(e, "uncaught"));
200
+ process.on("unhandledRejection", (e) => handleUnhandled(e, "unhandled"));
185
201
  // POSIX exit codes: 128 + signal number. Matches shell conventions so
186
202
  // callers (e.g. consumer CI with EXIT_CODE_NO_RETRY=75) treat them as
187
203
  // retryable.
@@ -9,10 +9,10 @@ import {
9
9
  offerBugReport,
10
10
  scrubSecrets,
11
11
  setDeployContext
12
- } from "./chunk-Y54W6NVZ.js";
13
- import "./chunk-TTSFL3JB.js";
14
- import "./chunk-MRB5E7YM.js";
15
- import "./chunk-KU6N5DD3.js";
12
+ } from "./chunk-ZEEBDKYR.js";
13
+ import "./chunk-J3Q6PFPW.js";
14
+ import "./chunk-SHE6AKRK.js";
15
+ import "./chunk-HFXK72IC.js";
16
16
  import "./chunk-QGM4M3NI.js";
17
17
  export {
18
18
  buildCliFlagsSummary,
@@ -5,7 +5,7 @@ import {
5
5
  captureWarning,
6
6
  setDeployAttribute,
7
7
  withSpan
8
- } from "./chunk-MRB5E7YM.js";
8
+ } from "./chunk-SHE6AKRK.js";
9
9
 
10
10
  // src/dotns.ts
11
11
  import { spawn } from "child_process";
@@ -6,7 +6,7 @@ import * as path from "path";
6
6
  // package.json
7
7
  var package_default = {
8
8
  name: "bulletin-deploy",
9
- version: "0.7.13",
9
+ version: "0.7.14-rc.1",
10
10
  private: false,
11
11
  repository: {
12
12
  type: "git",
@@ -67,7 +67,8 @@ var package_default = {
67
67
  devDependencies: {
68
68
  "@types/node": "^22.0.0",
69
69
  tsup: "^8.5.0",
70
- typescript: "^5.9.3"
70
+ typescript: "^5.9.3",
71
+ ws: "^8.20.0"
71
72
  },
72
73
  minimumVersion: "0.5.6",
73
74
  engines: {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  VERSION
3
- } from "./chunk-MRB5E7YM.js";
3
+ } from "./chunk-SHE6AKRK.js";
4
4
 
5
5
  // src/version-check.ts
6
6
  import { execSync, execFileSync } from "child_process";
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-B7GUYYAN.js";
4
4
  import {
5
5
  setDeployContext
6
- } from "./chunk-Y54W6NVZ.js";
6
+ } from "./chunk-ZEEBDKYR.js";
7
7
  import {
8
8
  DotNS,
9
9
  TX_TIMEOUT_MS,
@@ -11,7 +11,7 @@ import {
11
11
  parseDomainName,
12
12
  popStatusName,
13
13
  verifyNonceAdvanced
14
- } from "./chunk-RBFXJVAG.js";
14
+ } from "./chunk-CIBGKXW5.js";
15
15
  import {
16
16
  derivePoolAccounts,
17
17
  detectTestnet,
@@ -46,7 +46,7 @@ import {
46
46
  truncateAddress,
47
47
  withDeploySpan,
48
48
  withSpan
49
- } from "./chunk-MRB5E7YM.js";
49
+ } from "./chunk-SHE6AKRK.js";
50
50
 
51
51
  // src/deploy.ts
52
52
  import { Buffer } from "buffer";
@@ -80,6 +80,10 @@ var DEFAULT_POOL_SIZE = 10;
80
80
  var BULLETIN_ENDPOINTS = [DEFAULT_BULLETIN_RPC];
81
81
  var POOL_SIZE = DEFAULT_POOL_SIZE;
82
82
  var _deployRpcFailedOver = false;
83
+ var _onWsHalt = null;
84
+ function setWsHaltCallback(cb) {
85
+ _onWsHalt = cb;
86
+ }
83
87
  function makeBulletinStatusHandler(primary) {
84
88
  return (s) => {
85
89
  if (s.type === WsEvent.CONNECTED && s.uri !== primary) {
@@ -87,6 +91,12 @@ function makeBulletinStatusHandler(primary) {
87
91
  setDeployAttribute("deploy.rpc.failed_over", "true");
88
92
  captureWarning("Bulletin RPC failover", { from: primary, to: s.uri });
89
93
  }
94
+ if (s.type === WsEvent.CLOSE || s.type === WsEvent.ERROR) {
95
+ try {
96
+ _onWsHalt?.();
97
+ } catch {
98
+ }
99
+ }
90
100
  };
91
101
  }
92
102
  var CHUNK_SIZE = 2 * 1024 * 1024;
@@ -97,9 +107,18 @@ var CHUNK_MORTALITY_PERIOD = 16;
97
107
  var RETRY_BASE_DELAY_MS = 2e3;
98
108
  var RETRY_MAX_DELAY_MS = 15e3;
99
109
  var WS_HEARTBEAT_TIMEOUT_MS = 3e5;
110
+ var RETRY_BUDGET_MAX_EVENTS = parseInt(process.env.BULLETIN_RETRY_BUDGET_MAX ?? "5", 10);
111
+ var RETRY_BUDGET_WINDOW_MS = parseInt(process.env.BULLETIN_RETRY_BUDGET_WINDOW_MS ?? "30000", 10);
112
+ function retryBudgetExhausted(history, maxEvents, windowMs, now = Date.now()) {
113
+ let inWindow = 0;
114
+ for (const t of history) {
115
+ if (now - t <= windowMs) inWindow++;
116
+ }
117
+ return inWindow > maxEvents;
118
+ }
100
119
  function isConnectionError(error) {
101
120
  const msg = error?.message || String(error);
102
- return /heartbeat timeout|WS halt|Unable to connect/i.test(msg);
121
+ return /heartbeat timeout|WS halt|Unable to connect|ChainHead disjointed/i.test(msg);
103
122
  }
104
123
  var CID_CONFIG = { version: 1, codec: 85, hashCode: 18, hashLength: 32 };
105
124
  function deriveRootSigner(mnemonic, path2 = "") {
@@ -364,10 +383,27 @@ async function storeChunkedContent(chunks, { client: existingClient, unsafeApi:
364
383
  }
365
384
  }
366
385
  let reconnectionsUsed = 0;
386
+ const recoveryHistory = [];
387
+ const recordRecoveryAndCheckBudget = (kind) => {
388
+ const now = Date.now();
389
+ recoveryHistory.push(now);
390
+ if (retryBudgetExhausted(recoveryHistory, RETRY_BUDGET_MAX_EVENTS, RETRY_BUDGET_WINDOW_MS, now)) {
391
+ captureWarning("Retry budget exhausted", {
392
+ kind,
393
+ events: recoveryHistory.length,
394
+ maxEvents: RETRY_BUDGET_MAX_EVENTS,
395
+ windowMs: RETRY_BUDGET_WINDOW_MS
396
+ });
397
+ throw new Error(
398
+ `Retry budget exhausted: more than ${RETRY_BUDGET_MAX_EVENTS} recovery attempts within ${Math.round(RETRY_BUDGET_WINDOW_MS / 1e3)}s. Chain RPC is unstable; bailing to bound peak memory.`
399
+ );
400
+ }
401
+ };
367
402
  async function doReconnect() {
368
403
  if (!reconnect || reconnectionsUsed >= MAX_RECONNECTIONS) {
369
404
  throw new Error(`Connection lost and max reconnections (${MAX_RECONNECTIONS}) exhausted`);
370
405
  }
406
+ recordRecoveryAndCheckBudget("reconnect");
371
407
  reconnectionsUsed++;
372
408
  setDeployAttribute("deploy.reconnects", reconnectionsUsed);
373
409
  const delay = Math.min(RETRY_BASE_DELAY_MS * Math.pow(2, reconnectionsUsed - 1), RETRY_MAX_DELAY_MS);
@@ -388,26 +424,44 @@ async function storeChunkedContent(chunks, { client: existingClient, unsafeApi:
388
424
  ownsClient = true;
389
425
  sampleMemory(`reconnect_${reconnectionsUsed}_after`);
390
426
  }
427
+ let wsHaltDetected = false;
428
+ setWsHaltCallback(() => {
429
+ wsHaltDetected = true;
430
+ try {
431
+ client.destroy();
432
+ } catch {
433
+ }
434
+ });
391
435
  try {
392
436
  let startNonce = await _fetchNonce(BULLETIN_ENDPOINTS, ss58);
393
437
  console.log(` Starting nonce: ${startNonce}`);
394
- const BATCH_SIZE = 2;
438
+ const BATCH_SIZE_INITIAL = 2;
439
+ const BATCH_SIZE_RECOVERY = 1;
395
440
  const MAX_CHUNK_RETRIES = 3;
396
441
  console.log(`
397
- Submitting ${chunks.length} chunks in batches of ${BATCH_SIZE}...`);
442
+ Submitting ${chunks.length} chunks in batches of up to ${BATCH_SIZE_INITIAL}...`);
398
443
  const stored = new Array(chunks.length).fill(null);
399
444
  const assignedNonces = /* @__PURE__ */ new Map();
400
- for (let b = 0; b < chunks.length; b += BATCH_SIZE) {
445
+ let b = 0;
446
+ while (b < chunks.length) {
447
+ if (wsHaltDetected && reconnect && reconnectionsUsed < MAX_RECONNECTIONS) {
448
+ wsHaltDetected = false;
449
+ await doReconnect();
450
+ }
451
+ const batchSize = reconnectionsUsed > 0 ? BATCH_SIZE_RECOVERY : BATCH_SIZE_INITIAL;
401
452
  const batchIndices = [];
402
453
  const batchChunks = [];
403
- for (let j = 0; j < BATCH_SIZE && b + j < chunks.length; j++) {
454
+ for (let j = 0; j < batchSize && b + j < chunks.length; j++) {
404
455
  const i = b + j;
405
456
  if (stored[i] === null) {
406
457
  batchIndices.push(i);
407
458
  batchChunks.push(chunks[i]);
408
459
  }
409
460
  }
410
- if (batchIndices.length === 0) continue;
461
+ if (batchIndices.length === 0) {
462
+ b += batchSize;
463
+ continue;
464
+ }
411
465
  const batchPromises = batchChunks.map((chunkData, j) => {
412
466
  const i = batchIndices[j];
413
467
  if (!assignedNonces.has(i)) {
@@ -439,7 +493,6 @@ async function storeChunkedContent(chunks, { client: existingClient, unsafeApi:
439
493
  }
440
494
  startNonce = Math.max(startNonce, currentNonce);
441
495
  if (failures.some((f) => stored[f.index] === null)) {
442
- b -= BATCH_SIZE;
443
496
  continue;
444
497
  }
445
498
  }
@@ -447,6 +500,7 @@ async function storeChunkedContent(chunks, { client: existingClient, unsafeApi:
447
500
  captureWarning("Chunk upload failed, retrying", { chunkIndex: fail.index + 1, maxRetries: MAX_CHUNK_RETRIES, error: fail.error?.message?.slice(0, 200) });
448
501
  let retried = false;
449
502
  for (let attempt = 1; attempt <= MAX_CHUNK_RETRIES; attempt++) {
503
+ recordRecoveryAndCheckBudget("chunk_retry");
450
504
  const retryDelay = Math.min(RETRY_BASE_DELAY_MS * Math.pow(2, attempt - 1), RETRY_MAX_DELAY_MS);
451
505
  console.log(` Retrying chunk ${fail.index + 1} (attempt ${attempt}/${MAX_CHUNK_RETRIES}) in ${(retryDelay / 1e3).toFixed(0)}s...`);
452
506
  await new Promise((r) => setTimeout(r, retryDelay));
@@ -489,6 +543,7 @@ async function storeChunkedContent(chunks, { client: existingClient, unsafeApi:
489
543
  throw new Error(`Chunk ${fail.index + 1} failed after ${MAX_CHUNK_RETRIES} retries: ${fail.error?.message?.slice(0, 100)}`);
490
544
  }
491
545
  }
546
+ b += batchSize;
492
547
  }
493
548
  setDeployAttribute("deploy.pool.account", truncateAddress(ss58));
494
549
  console.log(`
@@ -545,6 +600,8 @@ async function storeChunkedContent(chunks, { client: existingClient, unsafeApi:
545
600
  } catch (e) {
546
601
  if (ownsClient) client.destroy();
547
602
  throw e;
603
+ } finally {
604
+ setWsHaltCallback(null);
548
605
  }
549
606
  }
550
607
  function chunk(data, size = CHUNK_SIZE) {
@@ -852,7 +909,7 @@ async function deploy(content, domainName = null, options = {}) {
852
909
  console.log(`
853
910
  Mode: File`);
854
911
  console.log(` Path: ${contentPath}`);
855
- let fileContent = new Uint8Array(fs.readFileSync(contentPath));
912
+ let fileContent = fs.readFileSync(contentPath);
856
913
  if (options.password) {
857
914
  console.log(` Encrypting...`);
858
915
  fileContent = await encryptContent(fileContent, options.password);
@@ -980,7 +1037,9 @@ export {
980
1037
  friendlyChainError,
981
1038
  DEFAULT_BULLETIN_RPC,
982
1039
  DEFAULT_POOL_SIZE,
1040
+ setWsHaltCallback,
983
1041
  CHUNK_MORTALITY_PERIOD,
1042
+ retryBudgetExhausted,
984
1043
  isConnectionError,
985
1044
  deriveRootSigner,
986
1045
  createCID,
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  package_default,
3
3
  writeRunState
4
- } from "./chunk-KU6N5DD3.js";
4
+ } from "./chunk-HFXK72IC.js";
5
5
 
6
6
  // src/memory-report.ts
7
7
  import * as fs2 from "fs";
@@ -333,7 +333,9 @@ async function withDeploySpan(domain, fn) {
333
333
  if (!tagsToSet["deploy.host_app"]) delete tagsToSet["deploy.host_app"];
334
334
  Sentry.setTags(tagsToSet);
335
335
  try {
336
- return await fn();
336
+ const result = await fn();
337
+ span.setAttribute("deploy.status", "ok");
338
+ return result;
337
339
  } catch (error) {
338
340
  const msg = error.message;
339
341
  span.setAttribute("deploy.status", "error");
@@ -2,11 +2,11 @@ import {
2
2
  classifyErrorArea,
3
3
  isInteractive,
4
4
  promptYesNo
5
- } from "./chunk-TTSFL3JB.js";
5
+ } from "./chunk-J3Q6PFPW.js";
6
6
  import {
7
7
  VERSION,
8
8
  getCurrentSentryTraceId
9
- } from "./chunk-MRB5E7YM.js";
9
+ } from "./chunk-SHE6AKRK.js";
10
10
 
11
11
  // src/bug-report.ts
12
12
  import { execSync, execFileSync } from "child_process";
package/dist/deploy.d.ts CHANGED
@@ -27,7 +27,9 @@ interface ExistingProvider {
27
27
  }
28
28
  declare const DEFAULT_BULLETIN_RPC = "wss://paseo-bulletin-rpc.polkadot.io";
29
29
  declare const DEFAULT_POOL_SIZE = 10;
30
+ declare function setWsHaltCallback(cb: (() => void) | null): void;
30
31
  declare const CHUNK_MORTALITY_PERIOD = 16;
32
+ declare function retryBudgetExhausted(history: number[], maxEvents: number, windowMs: number, now?: number): boolean;
31
33
  declare function isConnectionError(error: any): boolean;
32
34
  declare function deriveRootSigner(mnemonic: string, path?: string): {
33
35
  signer: PolkadotSigner;
@@ -129,4 +131,4 @@ declare function resolveDotnsConnectOptions(options: Pick<DeployOptions, "mnemon
129
131
  declare function estimateUploadBytes(content: DeployContent): Promise<number | null>;
130
132
  declare function deploy(content: DeployContent, domainName?: string | null, options?: DeployOptions): Promise<DeployResult>;
131
133
 
132
- export { CHUNK_MORTALITY_PERIOD, DEFAULT_BULLETIN_RPC, DEFAULT_POOL_SIZE, type DeployContent, type DeployOptions, type DeployResult, ENCRYPT_KEY_LEN, ENCRYPT_MAGIC, ENCRYPT_NONCE_LEN, ENCRYPT_PBKDF2_ITERATIONS, ENCRYPT_SALT_LEN, ENCRYPT_TAG_LEN, type StoreDirectoryOptions, chunk, computeStorageCid, createCID, deploy, deriveRootSigner, encodeContenthash, encryptContent, estimateUploadBytes, friendlyChainError, hasIPFS, isConnectionError, merkleize, resolveDotnsConnectOptions, storeChunkedContent, storeDirectory, storeFile };
134
+ export { CHUNK_MORTALITY_PERIOD, DEFAULT_BULLETIN_RPC, DEFAULT_POOL_SIZE, type DeployContent, type DeployOptions, type DeployResult, ENCRYPT_KEY_LEN, ENCRYPT_MAGIC, ENCRYPT_NONCE_LEN, ENCRYPT_PBKDF2_ITERATIONS, ENCRYPT_SALT_LEN, ENCRYPT_TAG_LEN, type StoreDirectoryOptions, chunk, computeStorageCid, createCID, deploy, deriveRootSigner, encodeContenthash, encryptContent, estimateUploadBytes, friendlyChainError, hasIPFS, isConnectionError, merkleize, resolveDotnsConnectOptions, retryBudgetExhausted, setWsHaltCallback, storeChunkedContent, storeDirectory, storeFile };
package/dist/deploy.js CHANGED
@@ -21,14 +21,16 @@ import {
21
21
  isConnectionError,
22
22
  merkleize,
23
23
  resolveDotnsConnectOptions,
24
+ retryBudgetExhausted,
25
+ setWsHaltCallback,
24
26
  storeChunkedContent,
25
27
  storeDirectory,
26
28
  storeFile
27
- } from "./chunk-YX5USCHH.js";
29
+ } from "./chunk-KNIHHFFX.js";
28
30
  import "./chunk-B7GUYYAN.js";
29
- import "./chunk-Y54W6NVZ.js";
30
- import "./chunk-TTSFL3JB.js";
31
- import "./chunk-RBFXJVAG.js";
31
+ import "./chunk-ZEEBDKYR.js";
32
+ import "./chunk-J3Q6PFPW.js";
33
+ import "./chunk-CIBGKXW5.js";
32
34
  import "./chunk-VOEFHED3.js";
33
35
  import "./chunk-2VYG7NXN.js";
34
36
  import {
@@ -36,8 +38,8 @@ import {
36
38
  NonRetryableError
37
39
  } from "./chunk-ZOC4GITL.js";
38
40
  import "./chunk-HOTQDYHD.js";
39
- import "./chunk-MRB5E7YM.js";
40
- import "./chunk-KU6N5DD3.js";
41
+ import "./chunk-SHE6AKRK.js";
42
+ import "./chunk-HFXK72IC.js";
41
43
  import "./chunk-QGM4M3NI.js";
42
44
  export {
43
45
  CHUNK_MORTALITY_PERIOD,
@@ -64,6 +66,8 @@ export {
64
66
  isConnectionError,
65
67
  merkleize,
66
68
  resolveDotnsConnectOptions,
69
+ retryBudgetExhausted,
70
+ setWsHaltCallback,
67
71
  storeChunkedContent,
68
72
  storeDirectory,
69
73
  storeFile
package/dist/dotns.js CHANGED
@@ -36,10 +36,10 @@ import {
36
36
  stripTrailingDigits,
37
37
  validateDomainLabel,
38
38
  verifyNonceAdvanced
39
- } from "./chunk-RBFXJVAG.js";
39
+ } from "./chunk-CIBGKXW5.js";
40
40
  import "./chunk-VOEFHED3.js";
41
- import "./chunk-MRB5E7YM.js";
42
- import "./chunk-KU6N5DD3.js";
41
+ import "./chunk-SHE6AKRK.js";
42
+ import "./chunk-HFXK72IC.js";
43
43
  import "./chunk-QGM4M3NI.js";
44
44
  export {
45
45
  CONNECTION_TIMEOUT_MS,
package/dist/index.js CHANGED
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  deploy
3
- } from "./chunk-YX5USCHH.js";
3
+ } from "./chunk-KNIHHFFX.js";
4
4
  import {
5
5
  merkleizeJS
6
6
  } from "./chunk-B7GUYYAN.js";
7
- import "./chunk-Y54W6NVZ.js";
8
- import "./chunk-TTSFL3JB.js";
7
+ import "./chunk-ZEEBDKYR.js";
8
+ import "./chunk-J3Q6PFPW.js";
9
9
  import {
10
10
  DotNS,
11
11
  parseDomainName
12
- } from "./chunk-RBFXJVAG.js";
12
+ } from "./chunk-CIBGKXW5.js";
13
13
  import {
14
14
  bootstrapPool,
15
15
  derivePoolAccounts,
@@ -20,7 +20,7 @@ import {
20
20
  import "./chunk-2VYG7NXN.js";
21
21
  import "./chunk-ZOC4GITL.js";
22
22
  import "./chunk-HOTQDYHD.js";
23
- import "./chunk-MRB5E7YM.js";
23
+ import "./chunk-SHE6AKRK.js";
24
24
  import {
25
25
  VERSION,
26
26
  loadRunState,
@@ -30,7 +30,7 @@ import {
30
30
  shouldSkipStaleWarning,
31
31
  stateFilePath,
32
32
  writeRunState
33
- } from "./chunk-KU6N5DD3.js";
33
+ } from "./chunk-HFXK72IC.js";
34
34
  import "./chunk-QGM4M3NI.js";
35
35
  export {
36
36
  DotNS,
@@ -5,8 +5,8 @@ import {
5
5
  maybeWriteMemoryReport,
6
6
  safeHeap,
7
7
  sampleFromBytes
8
- } from "./chunk-MRB5E7YM.js";
9
- import "./chunk-KU6N5DD3.js";
8
+ } from "./chunk-SHE6AKRK.js";
9
+ import "./chunk-HFXK72IC.js";
10
10
  import "./chunk-QGM4M3NI.js";
11
11
  export {
12
12
  DEFAULT_THRESHOLD_MB,
package/dist/run-state.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  shouldSkipStaleWarning,
8
8
  stateFilePath,
9
9
  writeRunState
10
- } from "./chunk-KU6N5DD3.js";
10
+ } from "./chunk-HFXK72IC.js";
11
11
  import "./chunk-QGM4M3NI.js";
12
12
  export {
13
13
  VERSION,
package/dist/telemetry.js CHANGED
@@ -27,8 +27,8 @@ import {
27
27
  truncateAddress,
28
28
  withDeploySpan,
29
29
  withSpan
30
- } from "./chunk-MRB5E7YM.js";
31
- import "./chunk-KU6N5DD3.js";
30
+ } from "./chunk-SHE6AKRK.js";
31
+ import "./chunk-HFXK72IC.js";
32
32
  import "./chunk-QGM4M3NI.js";
33
33
  export {
34
34
  VERSION,
@@ -8,9 +8,9 @@ import {
8
8
  isPreReleaseVersion,
9
9
  preReleaseWarning,
10
10
  promptYesNo
11
- } from "./chunk-TTSFL3JB.js";
12
- import "./chunk-MRB5E7YM.js";
13
- import "./chunk-KU6N5DD3.js";
11
+ } from "./chunk-J3Q6PFPW.js";
12
+ import "./chunk-SHE6AKRK.js";
13
+ import "./chunk-HFXK72IC.js";
14
14
  import "./chunk-QGM4M3NI.js";
15
15
  export {
16
16
  assessVersion,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bulletin-deploy",
3
- "version": "0.7.13",
3
+ "version": "0.7.14-rc.1",
4
4
  "private": false,
5
5
  "repository": {
6
6
  "type": "git",
@@ -61,7 +61,8 @@
61
61
  "devDependencies": {
62
62
  "@types/node": "^22.0.0",
63
63
  "tsup": "^8.5.0",
64
- "typescript": "^5.9.3"
64
+ "typescript": "^5.9.3",
65
+ "ws": "^8.20.0"
65
66
  },
66
67
  "minimumVersion": "0.5.6",
67
68
  "engines": {