본문으로 건너뛰기
cccskills
무료GitHub에 공개

frontend-api

Frontend API integration — generated SDK, apiCallWithLoading, blockUi, wrapped responses, toOpenApiError. Use when calling the generated backend API from the frontend.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

nerds-odd-e/doughnut스타 50(GitHub 50 + cccskills 0)

실행 점수 미검증

설치 방법 보기

포함된 파일(1)

  • SKILL.md4.7 KB

SKILL.md(원문)

설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.

Frontend API Rules

API Integration

  • Import services from @generated/donut-backend-api/sdk.gen.
  • Wrapped response: { data, error, request, response }.
  • User-initiated actions: apiCallWithLoading (loading bar + error toasts).
  • Direct SDK calls are silent: no loading bar and no error toasts.
import { UserController } from "@generated/donut-backend-api/sdk.gen"
import { apiCallWithLoading } from "@/managedApi/clientSetup"

const { data: newUser, error } = await apiCallWithLoading(() =>
  UserController.createUser({ body: formData })
)

const { data: users, error: loadError } = await UserController.getUserProfile()

Loading indicators

apiCallWithLoading drives two global surfaces from DonutApp.vue:

  • Thin loading bar — any wrapped call in flight.
  • Whole-UI blocking modal — { blockUi: true }. Native <dialog showModal()>, so it paints above other top-layer dialogs.

Use { blockUi: true, message?: string } when the rest of the UI must wait (view transition, or a mutation where partial interaction would confuse state). Show the blocker only after any confirmation. Do not add component-local LoadingModal refs.

const { data, error } = await apiCallWithLoading(
  () => AssimilationController.next({ query: { timezone: timezoneParam() } }),
  { blockUi: true, message: "Loading next note..." }
)

Keep local loading (inline spinner, disabled control) when the user should still use the rest of the page. Those calls can still use apiCallWithLoading without blockUi.

Cancelable blocking calls

For safe read-only blockers, pass { blockUi: true, cancelable: true, message?: string }. Returns CancelableApiResult<T> ({ status: "completed"; result } | { status: "cancelled" }). Narrow on status before using result; do not treat cancel as an API error.

const outcome = await apiCallWithLoading(
  (signal) =>
    AiController.generateRefinementSuggestions({
      path: { note: noteId },
      signal,
    }),
  {
    blockUi: true,
    cancelable: true,
    message: "AI is generating refinement layout...",
  }
)

if (outcome.status === "cancelled") {
  return
}

const { data, error } = outcome.result

Accepted cancel is silent (no toast). Abort is client-only. Do not opt mutations or irreversible writes into cancelable: true. Do not invent AbortError-name matching or a cancelable runWithBlockingApiLoading.

cancelable: true is allowlisted in frontend/tests/managedApi/cancelableAllowlist.spec.ts (ALLOWED_CANCELABLE_FILES). Add a site there when introducing a new cancelable call; do not add cancelable: true outside that set.

For one continuous blocker across multiple calls, wrap them in runWithBlockingApiLoading(operation, message) (noncancelable). Inner apiCallWithLoading calls keep thin bar + toasts only.

Blocking classification

Every new { blockUi: true } or runWithBlockingApiLoading site is cancelable, intentionally noncancelable, or nonblocking. Classify it; do not leave it unclassified.

  • Cancelable — only allowlisted read-only opt-ins (cancelableAllowlist.spec.ts).
  • Intentionally noncancelable — mutations, view transitions that must finish, AI reads with no defined post-cancel UX.
  • Nonblocking — thin-bar apiCallWithLoading without blockUi, or a direct SDK call.

Loading UI that means unfinished work marks data-app-busy (LoadingThinBar, ContentLoader, LoadingModal; gated by frontend/tests/components/commons/AppBusyMarker.contract.spec.ts). E2E: waitUntilAppIsNotBusy() from e2e_test/start/pageBase.ts. The wait means busy UI cleared, not success.

API Return Value Usage

The global client uses responseStyle: "fields" and throwOnError: false.

  1. Destructure with meaningful names: const { data: updatedUser, error } = await updateUser(...).
  2. Check !error before using data; no separate data check.
  3. When error is undefined, TypeScript types data as the success shape.
  4. Do not add runtime property checks for required typed properties.
  5. Do not add else if (data) after checking error.

Validation Errors

For 400 field errors, toOpenApiError(error) ({ errors?: Record<string, string>; message?: string }). apiCallWithLoading already toasts; extract errors only for form fields.

import { toOpenApiError } from "@/managedApi/openApiError"

if (error) {
  errors.value = toOpenApiError(error).errors || {}
} else {
  errors.value = {}
  user.value = updatedUser
}

리뷰

아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.

댓글

로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.

아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.

보내면 바로 공개됩니다. 이메일 주소나 전화번호 같은 개인 정보는 쓰지 마세요. URL은 2개까지입니다.

0 / 1,000자

이 양식은 reCAPTCHA로 보호되며 Google 개인정보처리방침 및 서비스 약관이 적용됩니다.

같은 저장소의 스킬

backend

무료

Backend Java — Spring Boot controllers/services, JUnit controller tests, MakeMe. Read this first for any backend work. Use when working on the Java Spring backend.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

nerds-odd-e/doughnut502026년 10월 26일 업데이트

Backend Java production code, Spring Boot controllers/services/repositories, controller return values, imports, schema ERD pointer. Use when editing backend production Java.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

nerds-odd-e/doughnut502026년 10월 26일 업데이트

Backend Java tests, controller-level stable-boundary tests, JUnit, @Nested, MakeMe builders, @Transactional, parameterized tests. Use when writing or changing backend JUnit tests.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

nerds-odd-e/doughnut502026년 10월 26일 업데이트

cli

무료

related to donut CLI. Use when working on donut-cli.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

nerds-odd-e/doughnut502026년 10월 26일 업데이트

Set up and run the Donut dev environment on Cursor Cloud VM (no Nix). Use when working on Cloud VM, running tests on Cloud VM, or encountering command errors related to missing nix. Triggers on: cloud VM, cloud agent, no nix available, /workspace path.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

nerds-odd-e/doughnut502026년 10월 26일 업데이트

Regenerate docs/database-erd.md from MySQL information_schema (Mermaid ERD: foreign keys and key columns). Use after Flyway schema changes, new migrations, or when the diagram is stale. Triggers on: database ERD, database-erd.md, export_database_erd, schema diagram, ER diagram after migration.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

nerds-odd-e/doughnut502026년 10월 26일 업데이트

nerds-odd-e의 스킬 모두 보기

이 스킬의 문제 신고