Skip to content

Migration Guide

Mỗi major của @tasco/* có một mục migration. Các package @tasco/* đi lockstep (cùng version), nên nâng cấp đồng loạt.

Nguyên tắc nâng cấp

  1. Đọc mục migration của major đích (bên dưới).
  2. Bump @tasco/nuxt-layer-base (kéo theo ui/theme/composables cùng version).
  3. Chạy pnpm install, rồi pnpm typecheck để bắt breaking ở mức type trước.
  4. Test trên channel next/beta trước khi lên latest (xem Release).
bash
# thử bản beta
pnpm add @tasco/nuxt-layer-base@beta

Mẫu mục migration (cho core team)

Khi phát hành major Y, thêm một mục theo mẫu này.

vX → vY

Breaking changes

  • Mô tả thay đổi phá vỡ, lý do.

Hành động cần làm

  • Bước cụ thể team sản phẩm phải làm (đổi API, đổi config...).

Codemod / tự động hoá (nếu có)

  • Lệnh/script hỗ trợ.

v1 → v2

2.0.0 lên major vì @tasco/eslint-config chỉ còn hỗ trợ ESLint 10 (RFC 0001). Cùng đợt này (RFC 0002), CTable, token màu, useTable đổi hành vi và layer gỡ phần OIDC còn sót, nên trang, CSS riêng hoặc code auth của dự án có thể bị ảnh hưởng. @tasco/ai, @tasco/mcp, @tasco/tsconfig@tasco/utils không có breaking change riêng, chỉ lên 2.0.0 theo lockstep.

Breaking changes

  • ESLint 10

    • @tasco/eslint-config chỉ còn hỗ trợ ESLint 10 (eslint@^10). Yêu cầu Node tối thiểu nâng lên >= 20.19.0 (hoặc 22.13+ / 24).
    • Bộ rule đi kèm nâng major đồng bộ: @eslint/js 10, eslint-plugin-vue 10, vue-eslint-parser 10, typescript-eslint 8.69+ — recommended configs có thể báo thêm lỗi mới.
    • ESLint 10 tìm config bắt đầu từ thư mục của từng file linted (không còn chỉ theo cwd) — đảm bảo eslint.config.mjs của mỗi dự án/phân vùng vẫn được phát hiện đúng.
  • CTable là khung trang danh sách (bọc trong CCard)

    • class/style gắn vào khung ngoài .c-table, không còn gắn vào a-table.
    • Prop title (chuỗi) và slot #title hiển thị ở header khung, không còn forward xuống title của a-table.
    • Bảng không có tiêu đề hay toolbar vẫn có viền và bóng của khung.
    • Phân trang mặc định có "Tổng số dòng N" và bộ chọn số dòng/trang. pagination truyền vào ghi đè từng key, false để tắt.
  • Token màu đổi giá trị để đạt tương phản WCAG AA (≥ 4.5:1)

    TokenTheme1.x2.0
    errorsáng#ee0033#d71431
    linksáng#1576f4#1068d6
    primarytối#4f76d1#7090dc
    primaryHovertối#7b98df#94ade6
    gradientPrimarytối#35549e → #4f76d1#35549e → #4466b8
    gradientDangersáng#f43f5e → #ee0033#cf1444 → #d71431
    gradientDangertối#f43f5e → #f87171#cf1444 → #d71431
    • Theme tối: các nền primary có chữ trắng (header bảng, CCard type="primary", nút primary thuần antdv, ngày đang chọn của DatePicker) chuyển sang --tasco-color-primary-active.
    • CSideNav: item hover/đang chọn giữ nền cam, chữ và icon đổi từ trắng sang navy.
    • Interface ColorTokens có thêm field bắt buộc accentText, successText, warningText.
  • useTable gửi sắp xếp cho fetcher khác trước

    • Bỏ sắp xếp một cột → sortFieldsortOrder đều undefined. Bản 1.x vẫn gửi sortField.
    • Cột có dataIndex lồng (['owner', 'name']) → sortField'owner.name'. Bản 1.x truyền nguyên mảng.
    • Bảng sắp xếp nhiều cột (sorter.multiple) → lấy cột đầu tiên. Bản 1.x không gửi sắp xếp.
  • Layer

    • app.vue truyền locale vi_VN của antdv cho <a-config-provider>.
    • Gỡ phần OIDC còn sót (đăng nhập OIDC đã bỏ từ 1.2.0):
      • Xoá server/utils/oidc.ts: Nitro không còn auto-import getOidcMetadata, generatePkce, randomState, refreshAccessToken, mapUserInfo và các type Oidc*.
      • Xoá runtimeConfig.oidc, nên env NUXT_OIDC_* (kể cả NUXT_OIDC_MOCK) không còn tác dụng.
      • TascoSession bỏ field refreshToken. Access token hết hạn thì /api/** để backend trả 401, không thử refresh.
      • /auth/logout xoá session rồi về đường dẫn nội bộ, không chuyển tới IdP.

Hành động cần làm

  1. Nâng đồng loạt @tasco/* cùng ESLint, rồi lint lại:

    bash
    # template scaffold của @tasco/cli 2.x đã dùng sẵn các bản này
    pnpm add @tasco/nuxt-layer-base@^2 @tasco/ui@^2
    pnpm add -D @tasco/eslint-config@^2 @tasco/tsconfig@^2 eslint@^10
    
    # recommended rules thay đổi, có thể cần sửa code mới bị báo
    pnpm lint

    Chạy bằng Node >= 20.19.0, kể cả Node mà extension ESLint của editor dùng. Sửa lỗi mới từ eslint:recommended, đặc biệt no-unassigned-vars, no-useless-assignmentpreserve-caught-error; không hạ rule về ESLint 9 trừ khi có lý do riêng của dự án.

    Nếu đang dùng rule/plugin custom viết cho ESLint 9, kiểm tra với migration guide ESLint 10 (bỏ context.getSourceCode(), SourceCode.getTokenOrCommentBefore()...).

  2. Rà các trang dùng CTable:

    • CSS ghép class của bảng với class antdv (vd .orders-table.ant-table-wrapper) → đổi sang selector con (.orders-table .ant-table).
    • Đang dùng slot #title hoặc title dạng hàm làm dòng tiêu đề bên trong bảng → chuyển thành tiêu đề khung.
    • CTable nằm trong một card khác → thêm borderless để khỏi hai lớp viền.
    diff
      <CCard title="Tổng quan">
    -   <CTable :columns="columns" :data-source="rows" />
    +   <CTable borderless :columns="columns" :data-source="rows" />
      </CCard>
  3. Rà CSS riêng theo bảng cặp màu AA ở Màu & tương phản:

    Đang viếtĐổi thành
    Chữ trắng trên nền var(--tasco-color-primary)Nền var(--tasco-color-primary-active)
    Chữ var(--tasco-color-{accent,success,warning}) trên nền sángvar(--tasco-color-{accent,success,warning}-text)
    Chữ trắng trên nền var(--tasco-color-accent)Chữ var(--tasco-color-sidebar-bottom)
    Mã hex chép từ token cũ (bảng trên)Biến var(--tasco-color-*) tương ứng

    Dự án có test ảnh chụp giao diện thì cập nhật lại ảnh gốc.

  4. Kiểm tra API backend của các bảng nhận được request không có sortField/sortOrder, và sortField dạng a.b với cột lồng.

  5. Dự án tự override app.vue → thêm locale:

    diff
      <script setup lang="ts">
      import { theme } from 'ant-design-vue'
    + import viVN from 'ant-design-vue/es/locale/vi_VN'
    
      </script>
    
      <template>
    -   <a-config-provider :theme="antdTheme">
    +   <a-config-provider
    +     :theme="antdTheme"
    +     :locale="viVN"
    +   >
  6. Dự án dùng hàm OIDC auto-import, đọc useRuntimeConfig().oidc hoặc truyền refreshToken vào setTascoSession → bỏ phần đó và xoá env NUXT_OIDC_*. Bỏ qua đăng nhập khi dev bằng NUXT_AUTH_MOCK=true.

  7. App tạo từ template 1.x: chép pnpm-workspace.yaml (khối allowBuilds), field packageManager và dòng COPY package.json pnpm-lock.yaml pnpm-workspace.yaml .npmrc ./ trong Dockerfile từ template 2.x, rồi chạy pnpm install. Thiếu allowBuilds thì pnpm 11+ fail ERR_PNPM_IGNORED_BUILDS trong Docker/CI. App dùng Nuxt 4.5 đặt engines.node^22.19.0 || ^24.11.0 || >=26.0.0.

Tìm nhanh các chỗ cần rà ở gốc repo sản phẩm:

bash
grep -rnE '<CTable|NUXT_OIDC_|\.oidc\b|refreshToken|getOidcMetadata|generatePkce|refreshAccessToken|mapUserInfo|#ee0033|#1576f4|#4f76d1|#7b98df|#f43f5e|a-config-provider' \
  --include='*.vue' --include='*.ts' --include='*.css' --include='*.scss' --include='.env*' \
  --exclude-dir=node_modules --exclude-dir=.nuxt --exclude-dir=.output .

v0 → v1 (ví dụ)

Breaking changes

  • useApi trả về instance gọi trực tiếp thay vì object { get, post } (ví dụ minh hoạ).

Hành động cần làm

diff
- const { get } = useApi()
- const data = await get('/orders')
+ const api = useApi()
+ const data = await api('/orders')