Skip to content

t1k:cocos:migration:uuid-verify

FieldValue
Modulemigration
Version0.3.0
Efforthigh
Tools

Keywords: attach, cocos, isPlugin, meta, migration, prefab, re-point, uuid

/t1k:cocos:migration:uuid-verify

Sau khi t1k-cocos-migration-js2ts đã sinh .cv.ts (đã tsc-validate), dùng skill này để gắn TS component vào prefab/scene — tức làm cho bản TS chạy thật trong game — mà KHÔNG xóa JS (coexistence). Đây là bước uuid-verify / attach trong pipeline. Bước xóa-JS (cutover) là pha riêng (cutover.cjs trong t1k-cocos-migration-migrate).

Pipeline active: dep-graph → js2ts → tsc-validate → uuid-verify(attach).

KHÔNG dùng cho: xóa JS, chỉnh sửa logic.

  1. Prefab/scene = JSON thuần (verify trên project thật: 0 binary). Object liên kết qua {"__id__": idx}.
  2. Component class được tham chiếu qua compressed-uuid ở các field:
    • __type__ — instance của component trên 1 node
    • _componentId — component đích trong event-handler (Button click → method)
    • __uuid__ — asset-ref tới script (hiếm) Cả ba đều trỏ cùng class → đều phải re-point cùng. (fileId của PrefabInfo dài 22 ký tự → bị loại; compressed-uuid là 23 ký tự.)
  3. Codec compressed-uuid (Cocos 2.x, đã verify round-trip): 5 hex literal + (mỗi 3 hex → 2 base64)×9 = 18 base64 = 23 ký tự. BASE64 = A-Za-z0-9+/.
  4. @property serialize THEO TÊN (không theo thứ tự) → binding giữ nguyên IFF class TS có đủ @property cùng tên (own + inherited qua extends).
  5. cc.PrefabInfo (root/asset/fileId/sync) KHÔNG ref class → re-point trực giao, không đụng.

scripts/uuid-verify.cjs — Node, pure file-based, mặc định DRY-RUN:

LệnhViệc
reportTổng quan: liệt kê .cv.ts, JS-uuid khớp, số ref prefab/scene, có .meta chưa, cần re-point hay chỉ gen-meta
gen-meta [<file.cv.ts>] [--write]Sinh .cv.ts.meta (uuid mới) cho closure import của 1 file, HOẶC tất cả .cv.ts (không truyền file). Additive thuần — chỉ tạo .meta mới
attach <file.cv.ts> [--write](a) gen .cv.ts.meta cho target + TOÀN BỘ closure import (để runtime require resolve) → (b) gate completeness @property (serialized keys ⊆ TS chain) → (c) re-point mọi __type__/_componentId/__uuid__ trong prefab/.fire
verifyHealth-check toàn project: dangling (uuid resolve về .meta?) + isPlugin (mọi .cv.ts.meta=false?) + editor-compile-verify (mọi .cv đã attach có library/imports/<uuid>.js?)
verify --scene <path>Như verify nhưng scoped 1 prefab/scene: liệt kê đúng component của file đó — đã-TS (compiled? isPlugin?) / còn-JS (convert chưa?) / dangling. Exit 2 nếu có vấn đề. Dùng để xác nhận 1 prefab sau khi attach.

Gate FAIL (thiếu @property → mất binding) hoặc gặp key tham chiếu lạ → dừng (exit 2), trừ khi --force.

Terminal window
# Tổng quan (read-only):
node .claude/skills/t1k-cocos-migration-uuid-verify/scripts/uuid-verify.cjs report
# Sinh .meta cho TẤT CẢ .cv.ts (làm editor thấy + require closure resolve):
node .claude/skills/t1k-cocos-migration-uuid-verify/scripts/uuid-verify.cjs gen-meta --write
# Dry-run attach 1 component (KHÔNG ghi gì — xem trước):
node .claude/skills/t1k-cocos-migration-uuid-verify/scripts/uuid-verify.cjs attach <scriptRoot>/<Path>/<Component>.cv.ts
# Áp dụng thật (tạo .meta + ghi prefab/scene; JS vẫn nguyên):
node .claude/skills/t1k-cocos-migration-uuid-verify/scripts/uuid-verify.cjs attach <scriptRoot>/<Path>/<Component>.cv.ts --write
# Kiểm dangling toàn project:
node .claude/skills/t1k-cocos-migration-uuid-verify/scripts/uuid-verify.cjs verify

Flags: --registry · --script-root · --assets-root · --scene <path> (verify scoped 1 prefab/scene) · --write (bật ghi) · --force (bỏ qua gate-fail/key-lạ — DÙNG CẨN THẬN).

Đường dẫn (registry/script-root/assets-root) lấy từ .claude/cocos-migrate.json (SSOT dùng chung, KHÔNG hardcode); CLI flag > config > fallback. Xem t1k-cocos-migration-migrate § Config.

  • Chỉ subset component được đặt trong prefab/scene mới cần attach (re-point). Phần còn lại là logic-only / base-class / runtime-add → chỉ cần gen-meta (nếu muốn editor thấy), KHÔNG re-point.
  • VD: một page-controller có instance + nhiều event-handler ref trong scene cần re-point; component add-runtime / base-class / manager logic-only KHÔNG có ref prefab → chỉ gen-meta.
  1. Bề mặt tham chiếu KHÔNG chỉ __type__. _componentId (event-handler) cũng trỏ component class. Bỏ sót _componentId → handler trỏ component cũ → vỡ. Tool quét MỌI field compressed-uuid; report/attach in breakdown theo key để audit.
  2. Re-point bằng string-replace ("<compFrom>""<compTo>") — giữ format file y nguyên (diff tối thiểu). An toàn vì compressed-uuid là token 23-ký-tự duy nhất của đúng asset đó. Tránh JSON.parse→stringify (sẽ reformat cả file → diff khổng lồ).
  3. Gate completeness BẮT BUỘC trước re-point. Serialized @property key (own + inherited) phải ⊆ @property của TS chain. Thiếu → mất binding → dừng. Cần convert base chain trước (base .cv.ts trước subclass) để tsPropChain lấy đủ inherited.
  4. uuid mới persist trong .meta → idempotent: chạy lại không đổi uuid (chỉ tạo nếu .meta chưa có). Dry-run KHÔNG persist nên mỗi lần in uuid khác — bình thường.
  5. JS không bao giờ bị đụng — chỉ tạo .cv.ts.meta mới + sửa __type__/_componentId trong prefab/scene. Revert = git checkout các prefab/scene.
  6. Key tham chiếu lạ (không phải __type__/_componentId/__uuid__) → tool dừng, yêu cầu audit thủ công (--force để bỏ qua nếu chắc).
  7. __uuid__ với sub-asset ("uuid@sub", >23 ký tự) hiện bị isCompUuid bỏ qua — chưa gặp với script component; bổ sung nếu phát sinh.
  8. Closure import phải loadable. Khi Cocos load component TS, nó chạy require("./Dep.cv") cho mọi dep đã convert → mỗi .cv.ts trong closure phải có .meta mới resolve runtime. attach tự gen-meta cả closure (theo require/from/side-effect import, chỉ đệ quy .cv.ts); chạy gen-meta (all) trước khi attach hàng loạt là cách an toàn. Dep KHÔNG phải .cv (Plugin/.ts-sẵn/.js live) đã có .meta riêng → bỏ qua đúng.
  9. isPlugin:true = component CHẾT IM LẶNG (gotcha nguy hiểm nhất). Khi editor mở live tự auto-import .cv.ts, nó CÓ THỂ tạo .cv.ts.meta với "isPlugin": true + "loadPluginInEditor": false. Khi đó Cocos coi script là pluginKHÔNG compile như component, KHÔNG nạp trong editor → class không register → scene báo “Script … is missing or invalid / Error on compiling script” NHƯNG KHÔNG có dòng lỗi nào trong Console panel lẫn editor log (bị bỏ qua có chủ đích, không phải compile-fail). Đặc trưng nhận diện: tsc/transpileModule offline compile SẠCH, không sinh library/imports/<uuid>.js. FIX: sửa .meta thành "isPlugin": false rồi reimport (editor sẽ giữ false và compile như component → sinh library entry). Tool tự phát hiện + sửa (cần --write) trong attach/gen-meta; lệnh verify quét cảnh báo mọi .cv.ts.meta còn isPlugin:true. Cocos 2.4.x compile .ts bằng tsc bundled, compile .js bằng Babel — 2 đường khác nhau.
  10. Single-writer uuid — chạy pipeline với editor ĐÓNG (canonical). Để migration ĐỒNG BỘ (tái lập, sai-đồng-bộ/đúng-đồng-bộ), .cv.ts.meta chỉ được có MỘT người ghi. Cocos editor mở-live cũng auto-import .cv.ts + tự gán uuid (+ có thể isPlugin:true, xem gotcha 9) → nếu cả editor lẫn tool cùng ghi .meta, uuid mà prefab được re-point tới phụ thuộc TIMING import = BẤT ĐỊNH. Cocos KHÔNG có khái niệm “locked meta” nên không thể nhờ editor nhường ⇒ phương án “hybrid (tool gán + phát hiện lệch)” KHÔNG đạt đồng bộ thật. Protocol canonical (tool-owns): (1) ĐÓNG editor khi chạy gen-meta/attach; (2) tool ghi toàn bộ .cv.ts.meta (uuid + isPlugin:false); (3) MỞ editor SAU → Cocos tôn trọng .meta đã có (không gán lại uuid khi meta hợp lệ) → compile; (4) verify (editor-compile-verify) xác nhận. KHÔNG để editor mở lúc gắn uuid.
  • t1k-cocos-migration-js2ts — sinh .cv.ts (chạy trước).
  • t1k-cocos-migration-dep-graph — registry (JS-uuid + isComponent).
  • t1k-cocos-migration-migrate — orchestrator điều phối attach trong Phase 3.