freertc 0.1.20 → 0.1.21

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/README.md CHANGED
@@ -216,7 +216,7 @@ Quick checks:
216
216
  Expected `/health` response includes JSON like:
217
217
 
218
218
  ```json
219
- {"ok":true,"version":"0.1.20","protocol_version":"1.0","peers":0}
219
+ {"ok":true,"version":"0.1.21","protocol_version":"1.0","peers":0}
220
220
  ```
221
221
 
222
222
  ## Auto WebRTC two-tab test
package/bin/freertc.mjs CHANGED
@@ -107,6 +107,11 @@ function extractCurrentWorkerName(configText) {
107
107
  return match?.[1] || null;
108
108
  }
109
109
 
110
+ function extractDeployHost(configPath) {
111
+ const text = fs.readFileSync(configPath, 'utf8');
112
+ return extractRouteHost(text) || extractRelayUrlHost(text) || extractDatabaseDomainHost(text);
113
+ }
114
+
110
115
  function extractRelayUrlHost(configText) {
111
116
  const relayUrlMatch = configText.match(/"RELAY_URL"\s*:\s*"([^"]*)"/);
112
117
  if (!relayUrlMatch) return null;
@@ -350,25 +355,41 @@ function runDeployWithAutoRouteRecovery(wrangler, configPath, extraArgs = []) {
350
355
  if (result.stderr) process.stderr.write(result.stderr);
351
356
 
352
357
  if (typeof result.status === 'number' && result.status === 0) {
353
- process.exit(0);
358
+ return { ok: true, status: 0 };
354
359
  }
355
360
 
356
361
  const combinedOutput = `${result.stdout || ''}\n${result.stderr || ''}`;
357
362
  const conflictOwner = extractRouteConflictOwner(combinedOutput);
358
363
  if (!conflictOwner || attemptedOwners.has(conflictOwner)) {
359
- process.exit(typeof result.status === 'number' ? result.status : 1);
364
+ return { ok: false, status: typeof result.status === 'number' ? result.status : 1 };
360
365
  }
361
366
 
362
367
  attemptedOwners.add(conflictOwner);
363
368
  const patched = patchWranglerScriptName(configPath, conflictOwner);
364
369
  if (!patched) {
365
- process.exit(typeof result.status === 'number' ? result.status : 1);
370
+ return { ok: false, status: typeof result.status === 'number' ? result.status : 1 };
366
371
  }
367
372
 
368
373
  console.log(`Detected route owned by worker "${conflictOwner}". Retrying deploy with that worker name automatically.`);
369
374
  }
370
375
 
371
- process.exit(1);
376
+ return { ok: false, status: 1 };
377
+ }
378
+
379
+ async function fetchLiveHealthVersion(host) {
380
+ const normalizedHost = normalizeHost(host);
381
+ if (!normalizedHost) return null;
382
+ try {
383
+ const response = await fetch(`https://${normalizedHost}/health`, {
384
+ headers: { Accept: 'application/json' }
385
+ });
386
+ if (!response.ok) return null;
387
+ const payload = await response.json();
388
+ const version = payload?.version;
389
+ return typeof version === 'string' && version.trim() ? version.trim() : null;
390
+ } catch {
391
+ return null;
392
+ }
372
393
  }
373
394
 
374
395
  function compareVersions(left, right) {
@@ -496,7 +517,46 @@ async function main() {
496
517
  await maybeAlignWorkerNameToRouteOwner(configPath);
497
518
  validateWranglerConfigForDeploy(configPath);
498
519
  const wrangler = resolveWranglerCommand(PROJECT_ROOT);
499
- runDeployWithAutoRouteRecovery(wrangler, configPath, rest);
520
+ const firstDeploy = runDeployWithAutoRouteRecovery(wrangler, configPath, rest);
521
+ if (!firstDeploy.ok) {
522
+ process.exit(firstDeploy.status);
523
+ }
524
+
525
+ const deployHost = extractDeployHost(configPath);
526
+ if (!deployHost) {
527
+ process.exit(0);
528
+ }
529
+
530
+ let liveVersion = await fetchLiveHealthVersion(deployHost);
531
+ if (liveVersion && compareVersions(liveVersion, CLI_VERSION) >= 0) {
532
+ process.exit(0);
533
+ }
534
+
535
+ // If live version is still stale, force-resolve route owner and redeploy once.
536
+ const routeOwner = await findRouteOwnerForHost(deployHost);
537
+ if (routeOwner) {
538
+ const currentText = fs.readFileSync(configPath, 'utf8');
539
+ const currentName = extractCurrentWorkerName(currentText);
540
+ if (currentName !== routeOwner) {
541
+ patchWranglerScriptName(configPath, routeOwner);
542
+ console.log(`Live health still stale on ${deployHost}. Retrying deploy against route-owner worker "${routeOwner}".`);
543
+ } else {
544
+ console.log(`Live health still stale on ${deployHost}. Retrying deploy once for route-owner worker "${routeOwner}".`);
545
+ }
546
+
547
+ const secondDeploy = runDeployWithAutoRouteRecovery(wrangler, configPath, rest);
548
+ if (!secondDeploy.ok) {
549
+ process.exit(secondDeploy.status);
550
+ }
551
+ liveVersion = await fetchLiveHealthVersion(deployHost);
552
+ if (liveVersion && compareVersions(liveVersion, CLI_VERSION) >= 0) {
553
+ process.exit(0);
554
+ }
555
+ }
556
+
557
+ console.error(`Deploy completed but live health on https://${deployHost}/health is still stale (version=${liveVersion || 'unknown'}, expected>=${CLI_VERSION}).`);
558
+ console.error('Refusing silent success. Please rerun deploy after Cloudflare route cache settles.');
559
+ process.exit(1);
500
560
  }
501
561
 
502
562
  if (subcommand === 'dev') {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "freertc",
3
- "version": "0.1.20",
3
+ "version": "0.1.21",
4
4
  "description": "Cloudflare Worker signaling relay for WebRTC peers with D1 storage.",
5
5
  "keywords": [
6
6
  "webrtc",
@@ -7,7 +7,7 @@ import { fileURLToPath } from 'node:url';
7
7
  import { WebSocketServer } from 'ws';
8
8
 
9
9
  const PSP_VERSION = '1.0';
10
- const WORKER_VERSION = '0.1.20';
10
+ const WORKER_VERSION = '0.1.21';
11
11
  const DEFAULT_TTL_MS = 30_000;
12
12
  const MAX_TTL_MS = 120_000;
13
13
  const MAX_MESSAGE_SIZE = 64 * 1024;
package/src/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  const PSP_VERSION = "1.0";
2
- const WORKER_VERSION = "0.1.20";
2
+ const WORKER_VERSION = "0.1.21";
3
3
 
4
4
  const DISCOVERY_TYPES = new Set(["announce", "withdraw", "discover", "peer_list", "redirect"]);
5
5
  const NEGOTIATION_TYPES = new Set(["connect_request", "connect_accept", "connect_reject", "offer", "answer", "ice_candidate", "ice_end", "renegotiate"]);