Bun.semver: เช็กช่วงเวอร์ชันก่อนเปิด Feature โดยไม่ดึง Package เพิ่ม
ระบบ plugin มักต้องถามว่า “เวอร์ชันนี้อยู่ในช่วงที่รองรับหรือไม่” การเปรียบเทียบ string ตรง ๆ ทำให้ 1.10.0 ดูน้อยกว่า 1.9.0 และการแยกจุดเองพลาดกติกา prerelease ได้ง่าย Bun มี Bun.semver ใน runtime จึงใช้กฎ Semantic Versioning ได้โดยไม่เพิ่ม dependency ครับ
function assert(condition: boolean, message: string): void {
if (!condition) throw new Error(message);
}
const supported = ">=1.4.0 <2.0.0";
assert(Bun.semver.satisfies("1.4.2", supported), "stable release should pass");
assert(!Bun.semver.satisfies("2.0.0-beta.1", ">=2.0.0"), "prerelease is not GA");
assert(Bun.semver.order("1.10.0", "1.9.0") > 0, "numeric segments must win");
console.log("semantic-version checks passed");
satisfies(version, range) เหมาะกับ compatibility gate เช่น plugin manifest ส่วน order(a, b) คืนค่าลบ ศูนย์ หรือบวกสำหรับ sorting และเลือกเวอร์ชันใหม่กว่า ข้อดีของการใช้ primitive เดียวกันทั้งระบบคือไม่ต้องมี parser คนละตัวใน installer, server และ test
Version gate ไม่ใช่ security gate
เวอร์ชันที่อยู่ในช่วงไม่ได้แปลว่า artifact มาจาก publisher จริงหรือไม่มีช่องโหว่ ควรตรวจ registry provenance, lockfile, checksum/signature และ advisory แยกกัน ถ้าใช้ version จาก input ภายนอก ให้ปฏิเสธค่าที่ parse ไม่ได้และบันทึกเหตุผล อย่า fallback เป็น “ล่าสุด” เงียบ ๆ
prerelease ต้องมี policy ชัด ช่วงที่ตั้งใจรับ stable อาจไม่รับ beta ตามที่หลายทีมคาด แต่ range ซับซ้อนและพฤติกรรมของ prerelease ควรมี test fixture ของจริง อย่าอาศัยความทรงจำจาก package manager อื่น เพราะ dialect ของ range อาจต่างกันบางมุม
สำหรับ feature flag ให้แยก “runtime รองรับ API” ออกจาก “เราเปิดใช้แล้ว” เช่น ผ่าน semver gate ก่อน แล้วจึงดู config/canary อีกชั้น วิธีนี้ rollback ได้โดยไม่โกหกเวอร์ชัน
Recap
- ใช้
satisfiesกับ compatibility range และorderกับการเรียง - เขียน test สำหรับ stable, prerelease และขอบ major
- ไม่ใช้ semver แทน checksum, provenance หรือ advisory
- ปฏิเสธเวอร์ชันที่ parse ไม่ได้แบบชัดเจนครับ