رفتن به محتوا
cloudhostمستندات
شروع

SDK تایپ‌اسکریپت

همهٔ API در یک کلاینت تایپ‌شده. SDK از روی توصیف API ایجاد می‌شود، پس هر مسیر، پارامتر و پاسخ همان است که در مرجع API می‌بینید، و فقط از APIهای استاندارد وب استفاده می‌کند تا در Node، مرورگر و فانکشن‌های cloudhost یکسان کار کند.

نصب#

npm install @cloudhost/sdk

Node 18 یا جدیدتر، هر مرورگر امروزی، و فانکشن‌های cloudhost. وابستگی ندارد.

شروع#

یک کلید API در داشبورد (تنظیمات، کلیدهای API) یا با cloudhost keys create ایجاد کنید. کلاینت کلید را از CLOUDHOST_API_KEY می‌خواند، یا آن را به سازنده بدهید.

شروع
import { Cloudhost } from "@cloudhost/sdk";

// the key from CLOUDHOST_API_KEY, or: new Cloudhost({ apiKey: "chk_live_..." })
const client = new Cloudhost();

const me = await client.account.whoami();
console.log(me.team, me.role);
گزینهپیش‌فرضکار
apiKeyCLOUDHOST_API_KEYکلید API
baseUrlCLOUDHOST_API_URL · https://api.ibel.aiآدرس API
envprocess.envدر فانکشن، env خود فانکشن را بدهید
maxRetries3تلاش دوباره پس از ۴۲۹ و ۵۰۳
maxRetryDelay60000بیشترین صبر پیش از تلاش دوباره (میلی‌ثانیه)؛ Retry-After بلندتر فوراً خطا می‌دهد
timeout60000میلی‌ثانیه برای هر تلاش
fetchfetch سراسریfetch خودتان (آزمون، پراکسی)

شکل متدها#

برای هر بخش API یک فضای نام هست: functions، apps، databases، caches، storage، queues، flags، domains، billing، teams، account و بقیه. اول پارامترهای مسیر می‌آیند، بعد بدنهٔ JSON، بعد پارامترهای کوئری و در آخر گزینه‌های درخواست (signal، timeout، maxRetries، headers). نام فیلدها همان نام‌های API است (snake_case)، پس مرجع API همان‌طور خوانده می‌شود.

نمونه
import { Cloudhost } from "@cloudhost/sdk";
const client = new Cloudhost();

await client.functions.get("my-api"); // GET /v1/functions/my-api
await client.functions.deploy("my-api", { version: 12 }); // a JSON body
await client.functions.getLogs("my-api", { since: "1h", level: "error" }); // query parameters
await client.flags.functions.list("my-api"); // a product's part of another namespace

خطاها#

هر پاسخ خطا یک زیرکلاس ApiError است که از روی وضعیت HTTP انتخاب می‌شود، با code پایدار API (مثلاً not_found)، message و details (فیلدهای اضافهٔ آن کد). code تایپ دارد: همهٔ کدهایی که API مستند کرده.

نمونه
import { Cloudhost, ApiError, ConflictError, RateLimitError } from "@cloudhost/sdk";
const client = new Cloudhost();

try {
  await client.databases.create({ name: "shop" });
} catch (err) {
  if (err instanceof ConflictError && err.is("name_taken")) console.log("the name is taken");
  else if (err instanceof RateLimitError) console.log("try again in", err.retryAfter, "s");
  else if (err instanceof ApiError) console.log(err.status, err.code, err.message);
  else throw err;
}
کلاسوضعیت
BadRequestError400
AuthenticationError401
PaymentRequiredError402
PermissionDeniedError403
NotFoundError404
ConflictError409
PayloadTooLargeError413
RateLimitError429
InternalServerError · BadGatewayError · ServiceUnavailableError500 · 502 · 503
ConnectionError · TimeoutErrorپاسخی نیامد
ConfigurationErrorکلید API نیست، پیش از هر درخواست

تلاش دوباره#

پاسخ ۴۲۹ (محدودیت درخواست) یا ۵۰۳ (موقتاً در دسترس نیست) تا maxRetries بار دوباره فرستاده می‌شود. صبر همان Retry-After پاسخ است، وگرنه ۰٫۵، ۱، ۲ ... تا ۸ ثانیه با کمی تصادف. قطع اتصال فقط در خواندن‌ها دوباره امتحان می‌شود، چون نوشتن شاید انجام شده باشد؛ درخواستی که بدنه‌اش stream است هرگز دوباره فرستاده نمی‌شود.

نمونه
import { Cloudhost } from "@cloudhost/sdk";
const client = new Cloudhost({ maxRetries: 5, timeout: 30_000 });
client.transport.onRetry = ({ attempt, delayMs, error }) => console.warn("retry", attempt, "in", delayMs, "ms:", error.message);

// per call: a signal, a timeout, retries, headers
const ctl = new AbortController();
await client.functions.list({ signal: ctl.signal, maxRetries: 0 });

صفحه‌بندی#

فهرستی که صفحه دارد یک همزاد ...All() دارد: با for await روی همهٔ آیتم‌ها بچرخید، با .pages() روی صفحه‌ها، یا با .toArray({ max }) زودتر بایستید. لاگ‌ها، گزارش تغییرها، اعلان‌ها، تحویل‌های webhook، ردها، پیام‌های صف، پرونده‌های پشتیبانی و تاریخچهٔ فلگ‌ها.

نمونه
import { Cloudhost } from "@cloudhost/sdk";
const client = new Cloudhost();

for await (const event of client.account.listAuditAll({ type: "deploy" })) {
  console.log(event.at, event.action);
}
const errors = await client.functions.getLogsAll("my-api", { since: "24h", level: "error" }).toArray({ max: 500 });
for await (const page of client.support.listAll({ status: "active" }).pages()) console.log(page.total);

هر محصول#

import { Cloudhost } from "@cloudhost/sdk";
const client = new Cloudhost();

await client.functions.create({ name: "my-api" });
const v = await client.functions.uploadVersion("my-api", {
  main_module: "index.js",
  modules: { "index.js": `export default { fetch: () => new Response("hello") }` },
});
const live = await client.functions.deploy("my-api", { version: v.version });
await client.functions.putSecret("my-api", "PAYMENT_KEY", { value: "..." });

const tail = await client.functions.tail("my-api"); // the live log
for await (const entry of tail) {
  console.log(entry.level, entry.msg);
  if (entry.level === "error") break;
}

دامنه‌ها، بیلد‌ها، پیش‌نمایش‌ها، هشدارها، webhookها، تیم و صورت‌حساب هم همین شکل را دارند؛ README بسته نمونهٔ هر کدام را دارد.

داخل فانکشن#

کلید را متغیر محیطی حساس فانکشن کنید و env فانکشن را به کلاینت بدهید.

فانکشن
import { Cloudhost } from "@cloudhost/sdk";

export default {
  async fetch(request: Request, env: Record<string, string>) {
    const client = new Cloudhost({ env }); // reads CLOUDHOST_API_KEY from the function's env
    const { functions } = await client.functions.list();
    return Response.json(functions.map((f) => f.name));
  },
};

در مرورگر#

بسته کد مخصوص Node ندارد و با هر bundler کار می‌کند.

کلید API در صفحهٔ وب را هر کسی که صفحه را باز کند می‌خواند. API را از سرور یا یک فانکشن صدا بزنید، یا به صفحه کلیدی با کمترین نقش (viewer) و انقضای کوتاه بدهید. API فعلاً فقط روی مسیرهای عمومی‌اش به درخواست‌های origin دیگر پاسخ می‌دهد، پس صفحه‌ای روی origin دیگر از راه سرور خودتان صدا می‌زند.

نسخه‌ها#

هر نسخهٔ SDK برای یک نسخهٔ API ایجاد شده و آن را در هدر cloudhost-version می‌فرستد. مسیرهای جدید API در نسخهٔ بعدی SDK می‌آیند؛ تا آن موقع client.transport.request() هر مسیری را صدا می‌زند.