diff --git a/CHANGELOG.md b/CHANGELOG.md index 71ef701..63c538f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,20 @@ All notable changes to Shade are documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [4.11.2] — 2026-07-10 — Files pull-mode startup hotfix + +**`@shade/files`** + +- Fix a construction race in HTTP pull-mode clients: an immediate streamed + read/write now awaits asynchronous stream-bridge registration instead of + treating the not-yet-created queue drainer as proof that the client is + inline-only. +- Add a deterministic integration test that holds incoming-transfer + registration, starts a 512 KiB write immediately, and verifies that it + remains pending until streaming is ready. +- Add `publish-all.ts --only ` so isolated package hotfixes do not publish + unrelated workspace packages. + ## [4.11.0] — 2026-05-15 — Streaming Double-Ratchet sub-sessions Answers Vyvern FR `shade-ws-streaming-ratchet.md` (the last Phase-2 diff --git a/packages/shade-files/package.json b/packages/shade-files/package.json index e9c0f8e..ceee454 100644 --- a/packages/shade-files/package.json +++ b/packages/shade-files/package.json @@ -1,6 +1,6 @@ { "name": "@shade/files", - "version": "4.11.1", + "version": "4.11.2", "type": "module", "main": "src/index.ts", "types": "src/index.ts", diff --git a/scripts/publish-all.ts b/scripts/publish-all.ts index 09ba6f5..b103a98 100644 --- a/scripts/publish-all.ts +++ b/scripts/publish-all.ts @@ -13,6 +13,7 @@ * * Optional: * DRY_RUN=1 — pack tarballs but do not publish (no token required) + * --only — publish one package (e.g. shade-files or @shade/files) */ import { readFileSync, writeFileSync, existsSync } from 'fs'; import { join } from 'path'; @@ -51,10 +52,27 @@ const PACKAGES = [ const REGISTRY_HOST = 'gt.zyon.no'; const ROOT = join(import.meta.dir, '..'); +function selectedPackages(argv: string[]): string[] { + const onlyIndex = argv.indexOf('--only'); + if (onlyIndex === -1) return PACKAGES; + const requested = argv[onlyIndex + 1]; + if (!requested) throw new Error('Usage: publish-all.ts --only '); + const normalized = requested.startsWith('@shade/') + ? `shade-${requested.slice('@shade/'.length)}` + : requested.startsWith('shade-') + ? requested + : `shade-${requested}`; + if (!PACKAGES.includes(normalized)) { + throw new Error(`Unknown Shade package: ${requested}`); + } + return [normalized]; +} + async function main() { const token = process.env.GITEA_TOKEN; const user = process.env.GITEA_USER ?? 'Stian'; const dryRun = process.env.DRY_RUN === '1'; + const packagesToPublish = selectedPackages(process.argv.slice(2)); if (!token && !dryRun) { console.error('GITEA_TOKEN is required (or set DRY_RUN=1)'); @@ -64,6 +82,7 @@ async function main() { const registryUrl = `https://${REGISTRY_HOST}/api/packages/${user}/npm/`; console.log(`Target registry: ${registryUrl}`); console.log(`Dry run: ${dryRun ? 'yes' : 'no'}`); + console.log(`Packages: ${packagesToPublish.join(', ')}`); console.log(); const npmrcPath = join(ROOT, '.npmrc.publish'); @@ -86,7 +105,7 @@ async function main() { let alreadyPublished = 0; let failed = 0; - for (const pkg of PACKAGES) { + for (const pkg of packagesToPublish) { const pkgDir = join(ROOT, 'packages', pkg); const pkgJsonPath = join(pkgDir, 'package.json'); if (!existsSync(pkgJsonPath)) {