Przejdź do głównej zawartości

Klient TypeScript (@dustid/apid-client)

@dustid/apid-client to typowany klient TypeScript dla DUST API. Jest to ten sam klient, którego w środowisku produkcyjnym używa aplikacja internetowa DICE, a jego typy żądań i odpowiedzi są generowane bezpośrednio ze specyfikacji OpenAPI interfejsu API, dzięki czemu pozostaje on w pełni zsynchronizowany z serwerem.

Pakiet nie jest publikowany w publicznym rejestrze npm. Jest dystrybuowany przez DUST i udostępniany klientom realizującym integracje na żądanie (kontakt: support@dustidentity.com). Polecenie npm install @dustid/apid-client go nie znajdzie.

Jeśli wolisz nie dodawać tej zależności, możesz uzyskać takie samo bezpieczeństwo typów, generując typy ze specyfikacji OpenAPI — dokładnie w ten sposób powstają typy samego klienta — i wywołując API za pomocą zwykłego fetch. Szybki start stosuje właśnie to podejście, dzięki czemu działa bez instalowania czegokolwiek.

Wymagania wstępne, jeśli zdecydujesz się na klienta

Dział zatytułowany „Wymagania wstępne, jeśli zdecydujesz się na klienta”

Sprawdź je przed zaplanowaniem pracy z klientem:

WymaganieSzczegóły
Środowisko uruchomienioweGlobalny fetch: Node.js 18+, Bun lub Deno. Własną implementację można wstrzyknąć za pomocą opcji fetcher (serwery proxy, ponawianie, dublery testowe).
Narzędzia TypeScriptPunkty wejścia pakietu wskazują na kod źródłowy TypeScript, a nie skompilowany JavaScript. Twój bundler lub środowisko uruchomieniowe musi go transpilować — zwykłe node dist/app.js uruchomione na nietranspilowanym kodzie źródłowym nie zadziała.
Zależności środowiska uruchomieniowegoKlient nie jest wolny od zależności: deklaruje arktype (służący do walidacji ładunków błędów) oraz wewnętrzne pakiety pomocnicze DUST, które są dostarczane wraz z dystrybucją. Uwzględnij je przy dołączaniu zależności do repozytorium, przeglądzie licencji czy instalacji w środowisku odizolowanym od sieci.
Miejsce wykonywaniaWyłącznie po stronie serwera — zobacz ostrzeżenie na końcu tej strony.
import { ApidClient } from "@dustid/apid-client";
const client = new ApidClient({
baseUrl: "https://apid.dustid.io",
bearerToken: token, // Authorization: Bearer <token>
organizationId: orgId, // sent as Dust-Ctx-Org-Id
teamId: teamId, // sent as Dust-Ctx-Team-Id
});

Pełny typ opcji:

type ApidClientOptions = {
baseUrl: string;
bearerToken?: string;
organizationId?: string; // Dust-Ctx-Org-Id header
teamId?: string; // Dust-Ctx-Team-Id header
fetcher?: typeof globalThis.fetch; // custom fetch (proxies, testing)
defaultHeaders?: HeadersInit | (() => HeadersInit); // e.g. Dust-Ctx-Locale
logger?: Logger; // debug/error request logging
};

organizationId i teamId są mapowane na nagłówki kontekstu; gdy teamId zostanie pominięty, serwer domyślnie używa zespołu głównego organizacji. Za pomocą defaultHeaders możesz dodać do każdego żądania dowolne dodatkowe nagłówki — na przykład w celu uzyskania zlokalizowanych komunikatów o błędach:

const client = new ApidClient({
baseUrl,
bearerToken,
organizationId,
defaultHeaders: { "Dust-Ctx-Locale": "zh-CN" },
});

Klienty są niemutowalne; dwie metody pomocnicze zwracają kopię o zmienionej konfiguracji, co sprawia, że określanie zakresu dla poszczególnych żądań lub użytkowników jest tanie:

const asOtherTeam = client.withContext({ teamId: otherTeamId });
const asFreshToken = client.withToken(newBearerToken);

Klient grupuje punkty końcowe w zasoby: client.me, client.threads, client.bundles, client.files, client.tags (operacje na identyfikatorach — punkty końcowe /api/v1/tags/*), client.teams, client.sharing, client.templates, client.events, client.relations, client.threadLinks, client.assemblies, client.transfers, client.slices, client.imports, client.fabric, client.users, client.certificates i client.certificateForms.

Nazwy metod odzwierciedlają dokumentację API. Dwa rzeczywiste przykłady z rekordami:

// GET /api/v1/threads — cursor-paginated list
const page = await client.threads.list({ pageSize: 50, q: "tire" });
for (const thread of page.threads) {
console.log(thread.threadId, thread.name);
}
if (page.next) {
const nextPage = await client.threads.list({ pageSize: 50, cursor: page.next });
}
// POST /api/v1/threads — create, unwrapped to the single created record
const created = await client.threads.createOne({
type: "single",
thread: { name: "Tire SZ3J-11-ZJ17" },
data: [{ name: "Serial Number", type: "text", value: { text: "SZ3J-11-ZJ17" } }],
});
// GET /api/v1/threads/{thread_id}
const record = await client.threads.get(created.threadId);
console.log(record.thread.name, record.events.length);

threads.create zwraca surową odpowiedź zbiorczą ({ created, uploadResponses }); threads.createOne to metoda pomocnicza, która zwraca created[0] i zgłasza wyjątek, jeśli serwer niczego nie utworzył.

Wszystkie typy żądań i odpowiedzi są eksportowane z katalogu głównego pakietu (ThreadCreateRequest, ThreadQueryResponse, ThreadGetResponse, …) wraz z surowymi, wygenerowanymi ze specyfikacji typami paths / components / operations.

W przypadku powodzenia metody zwracają przeanalizowaną odpowiedź JSON, a przy każdym stanie innym niż 2xx zgłaszają ApiError. ApiError zawiera standardową treść błędu API:

import { ApiError } from "@dustid/apid-client";
try {
await client.threads.get(threadId);
} catch (error) {
if (error instanceof ApiError) {
// error.code stable error code, e.g. "NOT_FOUND", "UNAUTHORIZED"
// error.status HTTP status number
// error.message localized human-readable message
// error.detail optional extra context (validation issues, etc.)
// error.body the full { code, message, status, detail } payload
if (error.code === "UNAUTHORIZED") {
// token expired — re-exchange the API key and retry
}
} else {
throw error; // network failure or non-JSON response
}
}

Warto znać dwa zachowania brzegowe: odpowiedzi 204/205 są rozwiązywane do undefined, a odpowiedź, która nie jest prawidłowym kodem JSON, zgłasza zwykły Error (a nie ApiError). Jeśli przekażesz logger, każde nieudane żądanie zostanie zapisane w logu wraz z jego x-request-id, co ułatwia powiązanie go ze zgłoszeniem do pomocy technicznej.

API udostępnia swoją specyfikację OpenAPI 3 pod adresem https://apid.dustid.io/api/openapi.json. openapi-typescript przekształca ją w w pełni typowaną definicję paths/components, której można używać ze zwykłym fetch lub dowolną nakładką na fetch sterowaną specyfikacją:

Okno terminala
npx openapi-typescript@7 https://apid.dustid.io/api/openapi.json -o <generated-types-file>
import type { paths } from "./dust-api";
type ThreadList =
paths["/api/v1/threads"]["get"]["responses"]["200"]["content"]["application/json"];

Pamiętaj, aby samodzielnie ustawić nagłówki Authorization, Dust-Ctx-Org-Id i Dust-Ctx-Team-Id — zobacz Konwencje żądań. Generuj typy ponownie za każdym razem, gdy zaczynasz korzystać z nowych funkcji API; specyfikacja pod adresem /api/openapi.json jest zawsze aktualna dla serwera, z którego ją pobrano.