การประกอบคำสั่ง ลำดับ และการตัดซ้ำ · Command composition, ordering & dedup
On this page
หน้านี้อธิบายตรรกะใน src/lib/composer.ts ซึ่งเปลี่ยน BuilderConfig เป็นรายการ ResolvedStep ที่พร้อมแสดงและส่งออก ตรรกะนี้ไม่ได้เปลี่ยนเลยตั้งแต่ v0.1.0 (commit a452dc5) และมี unit test ครอบคลุมใน tests/composer.test.ts
ขั้นตอนของ composeSteps()#
- normalizeConfig ทำ config ที่อาจไม่น่าเชื่อถือ (จากลิงก์แชร์หรือ AI) ให้ถูกต้อง: template ที่ไม่รู้จักกลับเป็น
nextjs-dashboard, เวอร์ชัน/ตัวจัดการที่ไม่รู้จักกลับเป็นค่าเริ่มต้น (lts,3.12,npm,pip), add-on กรองเหลือเฉพาะในADDON_IDS, ชื่อโปรเจกต์ผ่านsanitizeProjectName - buildContext สร้างตาราง placeholder จาก config + template เช่น
install,add,run,nextFlags(--ts --tailwind --eslint --app --src-dir --import-alias "@/*" --use-npm --yes),venv,pip - ขั้น runtime ถ้าเทมเพลตใช้ Node:
nvmStep(+pnpmStepหรือyarnStep) ถ้าใช้ Python:uvInstallStep+uvPythonStep(เมื่อเลือก uv) หรือpythonCheckStep - ขั้นของเทมเพลต กรองด้วย
when(matchesWhen: add-on ต้องทั้งถูกเลือกและเทมเพลตรองรับ) - ขั้นของ add-on (
addonSteps) ถูก แทรกก่อนขั้นแรกที่เป็น longRunning / publish / manual ของเทมเพลต - resolveStep แทนค่า placeholder ทุกฟิลด์ สร้างคำสั่ง Windows (ใช้
windowsoverride หรือadaptForPowerShell) และกำหนดsource(runtime / template / addon) - dedupeSteps ตัดซ้ำ
ทำไมแทรก add-on ก่อน dev server#
ลำดับที่ถูกคือ ติดตั้งทุกอย่าง → ตั้งค่า lint/test/Docker/CI → เริ่ม dev server ถ้าแทรก add-on ท้ายสุด ขั้นติดตั้ง Vitest จะอยู่หลัง npm run dev ซึ่งในสคริปต์ถูกคอมเมนต์ไว้ ผู้ใช้ที่รันตามลำดับในเอกสารจะติดอยู่ที่ dev server ก่อนติดตั้งเครื่องมือครบ
กฎการตัดซ้ำ (dedup)#
dedupeSteps เก็บขั้นแรกที่พบ และตัดขั้นหลังที่:
- มี id ซ้ำ หรือ
- มี signature ซ้ำ คือ JSON ของ
[commands, paths ของ files]เหมือนกัน (ขั้นที่ไม่มีทั้งคำสั่งและไฟล์ใช้ id เป็น signature)
เหตุผล: ขั้นเดียวกันอาจมาจากหลายแหล่ง เช่น เทมเพลตและ add-on ต่างก็ต้อง cd เข้าโปรเจกต์ หรือ AI เสนอขั้นที่ทำสิ่งเดียวกับเทมเพลตภายใต้ id อื่น การเทียบ signature จับกรณีหลังได้ นอกจากนี้ sanitizeAiPlan ยังตัดคำสั่งของ AI ที่ตรงกับคำสั่งเทมเพลตออกก่อนด้วย
การแก้ไขของผู้ใช้ (applyEdits)#
BuilderEdits มีสามส่วน: order (ลำดับ id ที่ผู้ใช้จัด), removed (id ที่ลบ) และ custom (ขั้นที่เพิ่มเอง / จาก AI)
- แทรก
customก่อนขั้นแรกที่ไม่ใช่ setup แล้ว dedup อีกรอบ ได้ลำดับ "ธรรมชาติ" - เริ่มจาก
orderที่ผู้ใช้จัด (ตัด id ที่ไม่มีอยู่แล้ว ที่ถูกลบ และที่ซ้ำ) - ขั้นที่ยังไม่อยู่ใน
order(เช่น เพิ่งเปิด add-on ใหม่) ถูกแทรก ต่อจากขั้นก่อนหน้าตามธรรมชาติที่อยู่ในผลลัพธ์แล้ว ไม่ใช่ท้ายสุด
ผลคือผู้ใช้จัดลำดับเองแล้วยังเปลี่ยน add-on ต่อได้โดยลำดับไม่พัง และลิงก์แชร์เก่าที่อ้าง id ซึ่งไม่มีแล้วก็ยังใช้ได้
ฟังก์ชันอื่นที่เกี่ยวข้อง#
moveStep(ids, id, ±1)สลับตำแหน่งสำหรับปุ่มขึ้น/ลงflattenCommands(steps, os)คำสั่งทั้งหมดแบบเรียบ สำหรับ "Copy all"configForTemplate(id, base)config ของเทมเพลตพร้อม add-on เริ่มต้นและชื่อเริ่มต้น
ข้อควรระวังเมื่อแก้ composer#
- ห้ามเปลี่ยนความหมายของ id เดิมโดยไม่จำเป็น เพราะลิงก์แชร์อ้าง id
- ทุกการเปลี่ยนต้องมี test ใน
tests/composer.test.tsและรันnpm run export -- <id>เพื่อดูสคริปต์จริง
ดูเพิ่ม#
Source: docs/concepts/composition.md · /docs/concepts/composition.md