OpenCoreDev がドメイン SDK 0.2.0 をリリース:5 つのプラットフォーム間で顧客ドメインを追加・検証・削除する TypeScript API
OpenCoreDev は、Vercel や Cloudflare など主要 5 つのホスティングプラットフォームにおけるカスタムドメイン管理を統一する TypeScript SDK「Domain SDK 0.2.0」をリリースし、SaaS 開発者の実装負荷を劇的に削減した。
キーポイント
マルチプラットフォーム対応の統一 API
Vercel, Cloudflare for SaaS, Railway, Render, Netlify の 5 つ主要プラットフォームに対し、ドメイン追加・検証・削除を単一の TypeScript API で統一的に扱えるように設計されている。
複雑なステータス状態の構造化モデル
DNS レコード、所有権確認、TLS 証明書の完了タイミングが異なるため、単なるブール値ではなく、8 つの状態値を持つ詳細なドメインステータスモデルを提供し、エラー処理を明確化する。
セキュリティとランタイムの最適化
サーバーサイド専用で ESM 形式を採用し、認証情報をブラウザに漏らさない設計とし、Node.js 20 および Bun をサポートする軽量なライブラリとして提供されている。
プラットフォーム固有の制限を動的検出
各プロバイダーごとの機能差(例:ワイルドカード対応、アペックスドメイン)をハードコードせず、`client.capabilities` を用いてランタイムで検出し、柔軟な実装を可能にする。
統一されたドメインライフサイクル管理
5 つのプラットフォームにまたがるカスタムドメインの追加、検証、削除を単一の TypeScript API で標準化し、プロバイダーごとの複雑さを抽象化します。
包括的なテストとシミュレーション機能
CI/CD 環境向けにメモリベースのプロバイダーを提供し、遅延の注入や特定の操作の失敗をシミュレートしてロジックを検証できます。
安全なリトライ機能の強化
冪等性の追加・削除、AbortSignal のサポート、および 14 種類の型付きエラーコードにより、安全かつ効率的なリトライが可能になりました。
重要な引用
Custom domains are a standard SaaS feature. Yet every hosting platform exposes a different API for them.
DomainStatus carries eight values: pending, pending_dns, pending_verification, pending_certificate, active, misconfigured, failed, unknown.
Rather than hard-coding those limits, read client.capabilities at runtime.
Domain SDK normalizes the custom-domain lifecycle across five platforms behind one TypeScript client.
Capabilities differ by platform; read client.capabilities instead of hard-coding limits.
Idempotent add and remove, AbortSignal support, and fourteen typed error codes make retries safe.
影響分析・編集コメントを表示
影響分析
この SDK の登場は、SaaS プロダクト開発におけるインフラ管理の標準化を推進し、開発者がコアビジネスロジックに集中できる環境を整える。特にマルチテナント環境やクロスプラットフォーム展開を目指すスタートアップにとって、ドメイン管理の実装コストとバグリスクを大幅に低減する画期的なツールとなる。
編集コメント
SaaS 開発における「ドメイン管理」の非効率性を解消する、非常に実用的なオープンソースツールの登場です。各プロバイダーの仕様差を抽象化し、開発フローを標準化するこのアプローチは、今後のインフラライブラリ設計の参考になるでしょう。
カスタムドメインは SaaS アプリの標準機能ですが、ホスティングプラットフォームごとに API が異なります。OpenCoreDev はこの課題を解決するため、TypeScript クライアント「Domain SDK」を公開しました。バージョン 0.2.0 は初回リリースからわずか 1 日後に npm に公開されています。
Domain SDK とは何か?
Domain SDK は Vercel、Cloudflare for SaaS、Railway、Render、Netlify の 5 つのプラットフォームに対応しています。ホスト名を追加すると、必要な DNS レコードが正確に表示され、ドメインが利用可能になるまでプロバイダーの状態を追跡できます。
この SDK が行うのはドメイン登録や DNS ホスティング、アプリデプロイ、トラフィックのプロキシ化、テナントデータの保存ではありません。テナンの認証と状態管理はあくまでアプリケーション側で行い、信頼できる情報源(ソース・オブ・トゥルース)はプロバイダー側に置きます。
パッケージはサーバーサイド専用で、認証情報はブラウザコードに届くことはありません。動作環境は Node.js 20 以上に対応し、Bun もサポートしています。ESM のみ対応で、ランタイム依存関係は tldts を 1 つだけ持っています。
クライアントの機能範囲
この範囲内では API は非常にシンプルです。createDomainClient() でステートレスなクライアントを作成すると、7 つのメソッドが利用可能になります:add(追加)、get(取得)、refresh(更新)、list(一覧表示)、verify(検証)、remove(削除)、そして waitUntilActive(アクティブになるまで待機)です。すべてのメソッドは AbortSignal を受け取ります。add と remove は冪等性を持つため、再試行も安全に行えます。
各アダプターは個別のエントリーポイントとして用意されています:./vercel、./cloudflare、./railway、./render、./netlify、そして ./testing です。プラットフォームを変更する際は、ワークフローを変えるのではなく、インポート先を切り替えるだけで済みます。
ステータスはブール値ではなくユニオン型
DNS の完了、所有権の確認、TLS 証明書の発行はそれぞれ異なるタイミングで完了するため、SDK はこれらを個別にモデル化しています。DomainStatus には以下の 8 つの値が含まれます:
必ず JSON 形式で返してください。translation フィールドのみ。他のフィールドは一切追加しないこと — 余計なフィールドを書こうとして本文がトークン上限で打ち切られる事故を防ぐため:
{"translation": "カスタムドメインは SaaS アプリの標準機能ですが、ホスティングプラットフォームごとに API が異なります。OpenCoreDev はこの課題を解決するため、TypeScript クライアント「Domain SDK」を公開しました。バージョン 0.2.0 は初回リリースからわずか 1 日後に npm に公開されています。
Domain SDK とは何か?
Domain SDK は Vercel、Cloudflare for SaaS、Railway、Render、Netlify の 5 つのプラットフォームに対応しています。ホスト名を追加すると、必要な DNS レコードが正確に表示され、ドメインが利用可能になるまでプロバイダーの状態を追跡できます。
この SDK が行うのはドメイン登録や DNS ホスティング、アプリデプロイ、トラフィックのプロキシ化、テナントデータの保存ではありません。テナンの認証と状態管理はあくまでアプリケーション側で行い、信頼できる情報源(ソース・オブ・トゥルース)はプロバイダー側に置きます。
パッケージはサーバーサイド専用で、認証情報はブラウザコードに届くことはありません。動作環境は Node.js 20 以上に対応し、Bun もサポートしています。ESM のみ対応で、ランタイム依存関係は tldts を 1 つだけ持っています。
クライアントの機能範囲
この範囲内では API は非常にシンプルです。createDomainClient() でステートレスなクライアントを作成すると、7 つのメソッドが利用可能になります:add(追加)、get(取得)、refresh(更新)、list(一覧表示)、verify(検証)、remove(削除)、そして waitUntilActive(アクティブになるまで待機)です。すべてのメソッドは AbortSignal を受け取ります。add と remove は冪等性を持つため、再試行も安全に行えます。
各アダプターは個別のエントリーポイントとして用意されています:./vercel、./cloudflare、./railway、./render、./netlify、そして ./testing です。プラットフォームを変更する際は、ワークフローを変えるのではなく、インポート先を切り替えるだけで済みます。
ステータスはブール値ではなくユニオン型
DNS の完了、所有権の確認、TLS 証明書の発行はそれぞれ異なるタイミングで完了するため、SDK はこれらを個別にモデル化しています。DomainStatus には以下の 8 つの値が含まれます:"}
pending, pending_dns, pending_verification, pending_certificate, active, misconfigured, failed, unknown。
ドメインには、検証ステータス(pending | verified | failed | unknown)、証明書ステータス(pending | active | expiring | failed | unknown)、および問題リスト(issues)も保持されます。各問題にはコード、メッセージ、オプションのレコード情報、そして再試行可能なフラグが含まれます。
レコードも同様に型付けされています。DnsRecord には type, name, value, optional ttl, purpose, required, status, および optional description が定義されています。purpose は routing(ルーティング)、ownership(所有権確認)、certificate(証明書取得)、または other のいずれかです。status は pending, valid, invalid, または unknown のいずれかになります。
その結果、Vercel のホスト名では 3 つの別々のレコードが表面化します:
TypeNamePurpose
CNAMEapp.customer.comrouting
TXT_vercel.app.customer.comownership
TXT_acme-challenge.app.customer.comcertificate
プロバイダーとの互換性について
ライフサイクルは標準化されていますが、プラットフォームごとの制限は異なります。
CapabilityVercelCloudflare SaaSRailwayRenderNetlify
List domains✓✓✓✓✓
Explicit verification✓——✓—
Managed certificates✓✓✓✓✓
Apex domains✓—✓✓✓
Wildcard domains———✓—
Automatic customer DNS—————
Cloudflare for SaaS では CNAME ターゲットが必要となるため、このアダプターはアペックスドメインのサポートを謳っていません。ワイルドカードホスト名を受け入れるのは Render だけです。いずれのアダプターも顧客の DNS を自動的に編集することはありません。
これらの制限をハードコードするのではなく、実行時に client.capabilities を読み取るようにしてください。これにより list, explicitVerification, managedCertificates, apexDomains, wildcardDomains が利用可能になります。
クライアントとの連携
以下のスニペットは 0.2.0 で型チェックを実行し、動作確認が可能です:
OpenCoreDev がドメイン SDK のバージョン 0.2.0 をリリースしました。これは、5 つのプラットフォームにまたがって顧客ドメインの追加、検証、削除を一元管理できる TypeScript API です。
以下は、Vercel プロバイダーを使用してドメインを追加し、DNS レコードを確認する実装例です。
import { createDomainClient } from "@opencoredev/domain-sdk";
import { vercel } from "@opencoredev/domain-sdk/vercel";
export const domains = createDomainClient({
provider: vercel({
token: process.env.VERCEL_TOKEN!,
projectId: process.env.VERCEL_PROJECT_ID!,
}),
});
const domain = await domains.add("app.customer.com");
// 顧客向け DNS 設定画面に表示する必須レコードを抽出します。
const required = domain.records.filter((item) => item.required);
const active = await domains.waitUntilActive(domain.hostname, {
timeoutMs: 300_000, // デフォルト値
intervalMs: 5_000, // デフォルト値(最小 250ms)
onStatus: (current) => console.log(current.status),
});
console.log(active.certificate.status, active.verification.status);ポーリング処理は順次実行されます。デフォルトではタイムアウトが 30 万ミリ秒、間隔が 5,000 ミリ秒に設定されています。250 ミリ秒未満の間隔を指定するとエラーとなり、各ステータスは onStatus コールバックを通じて報告されます。また、プロバイダー側から retryAfter ヘッダーが返された場合、クライアントは指定された時間だけ待機してから再試行を行います。
テストとエージェントサポート
CI(継続的インテグレーション)環境では、メモリアダプターを使用することで実際のプロバイダーへの呼び出しを回避できます。
import { createDomainClient } from "@opencoredev/domain-sdk";
import { memoryProvider } from "@opencoredev/domain-sdk/testing";
const memory = memoryProvider();
const domains = createDomainClient({ provider: memory });await domains.add("app.customer.com"); // ステータス:pending_dns
memory.activate("app.customer.com");
const latest = await domains.refresh("app.customer.com");
console.log(latest.status === "active"); // true
また、遷移処理(transition)や注入された遅延時間(latencyMs)、各操作ごとの失敗シミュレーション、コールログの機能もサポートしています。これらと並行して、createMockDomain、createMockDnsRecord、そして createFailingProvider も利用可能です。
別個に、エージェントスキルをインストールすれば、Codex、Claude Code、Cursor、および他の互換性のあるエージェントへワークフローを組み込むことができます:
npx skills add opencoredev/domain-sdk --skill domain-sdkユースケース
- Vercel 上のマルチテナント SaaS: カスタマーが
app.customer.comをマッピングします。設定ページでは、必要な CNAME レコードと TXT レコードをライブステータス付きでレンダリングできます。 - 大規模な SaaS 向け Cloudflare: カスタムホスト名は単一のゾーン内に配置されます。アダプターがそのスコーピングを明確に保ちます。
- 所有するテナントサブドメイン:
createSubdomainClientを使用してベースドメイン下のラベルを作成できます。また、reservedLabelsでwww、api、adminなどのキーワードをブロック可能です。 - プロバイダーの移行: アダプターのインポート先を変更するだけで、ライフサイクル呼び出しはそのまま維持されます。
インタラクティブな解説
(function(){
var f=document.getElementById("mtp-domainsdk-frame");
window.addEventListener("message",function(e){
if(!f||!e.data||e.data.type!=="mtp-ds-resize")return;
var h=parseInt(e.data.height,10);
if(h>200&&h重要なポイント
Domain SDK は、5 つのプラットフォームにまたがるカスタムドメインのライフサイクルを、単一の TypeScript クライアント背後で標準化します。
DomainStatus には 8 つの値があり、それぞれ検証、証明書発行、および発行ステータスに関する独立したフィールドを持っています。
プラットフォームによって利用可能な機能は異なります。制限をハードコードするのではなく、必ず client.capabilities を参照してください。
追加と削除の処理は冪等性を保証しており、AbortSignal に対応しています。また、14 種類の型付きエラーコードが用意されているため、リトライ処理も安全に行えます。
バージョン 0.2.0 の現在、この API はまだ発展途上です。そのため、型定義を利用するには moduleResolution を "bundler" に設定する必要があります。
詳細は GitHub リポジトリをご覧ください。Twitter でもフォローしていただければ幸いです。また、15 万人以上のメンバーが参加する ML サブレッドやニュースレターへの登録もぜひご検討ください。Telegram ユーザーの方へ!今なら Telegram チャンネルにも参加できます。
GitHub リポジトリの拡散、Hugging Face ページの紹介、製品リリース、ウェビナーなどのご提携をご希望の場合は、お気軽にご連絡ください。
本記事は MarkTechPost に掲載された「OpenCoreDev がドメイン SDK 0.2.0 をリリース:5 つのプラットフォームで顧客ドメインの追加・検証・削除を可能にする単一の TypeScript API」の続編です。
原文を表示
Custom domains are a standard SaaS feature. Yet every hosting platform exposes a different API for them. OpenCoreDev has published Domain SDK, a TypeScript client that normalizes that work. Version 0.2.0 reached npm a day after the first release.
What is Domain SDK?
Domain SDK covers Vercel, Cloudflare for SaaS, Railway, Render, and Netlify. You add a hostname, show the exact DNS records, then track provider state until it is ready.
It does not register domains, host DNS, deploy apps, proxy traffic, or store tenant data. Your application keeps tenant authorization and state. The provider stays the source of truth.
The package is server-side only, so credentials never reach browser code. engines.node is >=20, and Bun is supported. It is ESM-only and ships one runtime dependency, tldts.
The client surface
Within that scope, the API is small. createDomainClient() returns a stateless client with seven members: add, get, refresh, list, verify, remove, and waitUntilActive. Every method accepts an AbortSignal. Add and remove are idempotent, so retries are safe.
Each adapter is a separate entry point: ./vercel, ./cloudflare, ./railway, ./render, ./netlify, and ./testing. Changing platforms means changing the import, not the workflow.
Status is a union, not a boolean
Because DNS, ownership, and TLS finish at different times, the SDK models them separately. DomainStatus carries eight values:
pending, pending_dns, pending_verification, pending_certificate, active, misconfigured, failed, unknown.
A Domain also holds verification (pending | verified | failed | unknown), certificate (pending | active | expiring | failed | unknown), and an issues array. Each issue has a code, message, optional record, and a retryable flag.
Records are typed the same way. DnsRecord has type, name, value, optional ttl, purpose, required, status, and optional description. purpose is routing, ownership, certificate, or other. status is pending, valid, invalid, or unknown.
Consequently, a Vercel hostname surfaces three separate records:
TypeNamePurpose
CNAMEapp.customer.comrouting
TXT_vercel.app.customer.comownership
TXT_acme-challenge.app.customer.comcertificate
Provider compatibility
While the lifecycle is normalized, platform limits are not:
CapabilityVercelCloudflare SaaSRailwayRenderNetlify
List domains✓✓✓✓✓
Explicit verification✓——✓—
Managed certificates✓✓✓✓✓
Apex domains✓—✓✓✓
Wildcard domains———✓—
Automatic customer DNS—————
Cloudflare for SaaS requires a CNAME target, so the adapter does not claim apex support. Render alone accepts wildcard hostnames. No adapter edits customer DNS automatically.
Rather than hard-coding those limits, read client.capabilities at runtime. It exposes list, explicitVerification, managedCertificates, apexDomains, and wildcardDomains.
Working with the client
The following snippet type-checks and runs against 0.2.0:
Copy CodeCopiedUse a different Browser
import { createDomainClient } from "@opencoredev/domain-sdk";
import { vercel } from "@opencoredev/domain-sdk/vercel";
export const domains = createDomainClient({
provider: vercel({
token: process.env.VERCEL_TOKEN!,
projectId: process.env.VERCEL_PROJECT_ID!,
}),
});
const domain = await domains.add("app.customer.com");
// Render every required record in your customer-facing DNS instructions.
const required = domain.records.filter((item) => item.required);
const active = await domains.waitUntilActive(domain.hostname, {
timeoutMs: 300_000, // default
intervalMs: 5_000, // default, minimum 250
onStatus: (current) => console.log(current.status),
});
console.log(active.certificate.status, active.verification.status);
Polling is sequential. It defaults to a 300,000 ms timeout and a 5,000 ms interval. Intervals below 250 ms are rejected, and each state is reported through onStatus. When a provider returns retryAfter, the client waits at least that long before retrying.
Testing and agent support
For CI, an in-memory adapter never calls a real provider:
Copy CodeCopiedUse a different Browser
import { createDomainClient } from "@opencoredev/domain-sdk";
import { memoryProvider } from "@opencoredev/domain-sdk/testing";
const memory = memoryProvider();
const domains = createDomainClient({ provider: memory });
await domains.add("app.customer.com"); // status: pending_dns
memory.activate("app.customer.com");
const latest = await domains.refresh("app.customer.com");
console.log(latest.status === "active"); // true
It also supports transition(), injected latencyMs, per-operation failures, and a calls log. createMockDomain, createMockDnsRecord, and createFailingProvider sit alongside it.
Separately, an agent skill installs the workflow into Codex, Claude Code, Cursor, and other compatible agents:
Copy CodeCopiedUse a different Browser
npx skills add opencoredev/domain-sdk --skill domain-sdk
Use cases
Multi-tenant SaaS on Vercel: A customer maps app.customer.com. Your settings page renders required CNAME and TXT records with live status.
Cloudflare for SaaS at scale: Custom Hostnames live inside one zone. The adapter keeps that scoping explicit.
Tenant subdomains you own: createSubdomainClient maps labels under a base domain. reservedLabels blocks www, api, and admin.
Provider migration: Swap the adapter import and keep the same lifecycle calls.
Interactive Explainer
(function(){
var f=document.getElementById("mtp-domainsdk-frame");
window.addEventListener("message",function(e){
if(!f||!e.data||e.data.type!=="mtp-ds-resize")return;
var h=parseInt(e.data.height,10);
if(h>200&&h
Key Takeaways
Domain SDK normalizes the custom-domain lifecycle across five platforms behind one TypeScript client.
DomainStatus has eight values, with separate verification, certificate, and issue fields.
Capabilities differ by platform; read client.capabilities instead of hard-coding limits.
Idempotent add and remove, AbortSignal support, and fourteen typed error codes make retries safe.
At 0.2.0 the API is young, and its types need moduleResolution: "bundler" as of now.
Check out the GitHub Repo. Also, feel free to follow us on Twitter and don’t forget to join our 150k+ML SubReddit and Subscribe to our Newsletter. Wait! are you on telegram? now you can join us on telegram as well.
Need to partner with us for promoting your GitHub Repo OR Hugging Face Page OR Product Release OR Webinar etc.? Connect with us
The post OpenCoreDev Releases Domain SDK 0.2.0: One TypeScript API to Add, Verify, and Remove Customer Domains Across Five Platforms appeared first on MarkTechPost.
関連記事
今日のまとめ
AI日報で今日の重要ニュースをまとめ読み