@hasna/domains
Version:
Domain portfolio, registrar, marketplace, and DNS management for AI agents — CLI + MCP + HTTP API + SDK, shared account API and PostgreSQL
257 lines • 9.6 kB
TypeScript
/**
* Domain record types and CRUD operations
*/
export interface Domain {
id: string;
name: string;
registrar: string | null;
status: DomainStatus;
registered_at: string | null;
expires_at: string | null;
auto_renew: boolean;
is_premium: boolean;
premium_price: number | null;
standard_price: number | null;
purchase_price: number | null;
purchase_date: string | null;
nameservers: string[];
whois: Record<string, unknown>;
ssl_expires_at: string | null;
ssl_issuer: string | null;
notes: string | null;
metadata: Record<string, unknown>;
created_at: string;
updated_at: string;
/**
* When the registrar facts on this row (expiry, status, auto_renew) were last
* confirmed against the registrar. NOT `updated_at`, which moves on any edit
* and stays still when a sync re-confirms an unchanged value.
*/
expiry_synced_at: string | null;
}
interface DomainRow {
id: string;
name: string;
registrar: string | null;
status: string;
registered_at: string | null;
expires_at: string | null;
auto_renew: number;
is_premium: number;
premium_price: number | null;
standard_price: number | null;
purchase_price: number | null;
purchase_date: string | null;
nameservers: string;
whois: string;
ssl_expires_at: string | null;
ssl_issuer: string | null;
notes: string | null;
metadata: string;
created_at: string;
updated_at: string;
expiry_synced_at: string | null;
}
export declare const DOMAIN_STATUSES: readonly ["discovered", "researching", "offered", "negotiating", "purchased", "active", "not_available", "premium_only", "declined", "expired", "transferring", "redemption"];
export type DomainStatus = (typeof DOMAIN_STATUSES)[number];
export declare const DOMAIN_OFFER_STATUSES: readonly ["pending", "accepted", "rejected", "countered"];
export type DomainOfferStatus = (typeof DOMAIN_OFFER_STATUSES)[number];
export declare const DOMAIN_EMAIL_TYPES: readonly ["inquiry", "offer", "counter_offer", "confirmation", "renewal_notice", "transfer"];
export type DomainEmailType = (typeof DOMAIN_EMAIL_TYPES)[number];
export declare function rowToDomain(row: DomainRow): Domain;
export interface CreateDomainInput {
name: string;
registrar?: string | null;
status?: DomainStatus;
registered_at?: string;
expires_at?: string;
auto_renew?: boolean;
is_premium?: boolean;
premium_price?: number;
standard_price?: number;
purchase_price?: number;
purchase_date?: string;
nameservers?: string[];
whois?: Record<string, unknown>;
ssl_expires_at?: string;
ssl_issuer?: string;
notes?: string;
metadata?: Record<string, unknown>;
/** Set only by a path that actually read the registrar. */
expiry_synced_at?: string | null;
}
export declare function createDomain(input: CreateDomainInput): Domain;
export declare function getDomain(id: string): Domain | null;
export declare function getDomainByIdentifier(identifier: string): Domain | null;
export interface ListDomainsOptions {
search?: string;
status?: DomainStatus;
registrar?: string;
is_premium?: boolean;
limit?: number;
offset?: number;
}
export declare function listDomains(options?: ListDomainsOptions): Domain[];
export interface UpdateDomainInput {
name?: string;
registrar?: string | null;
status?: DomainStatus;
registered_at?: string;
expires_at?: string;
auto_renew?: boolean;
is_premium?: boolean;
premium_price?: number | null;
standard_price?: number | null;
purchase_price?: number | null;
purchase_date?: string | null;
nameservers?: string[];
whois?: Record<string, unknown>;
ssl_expires_at?: string;
ssl_issuer?: string;
notes?: string;
metadata?: Record<string, unknown>;
/** Set only by a path that actually read the registrar. */
expiry_synced_at?: string | null;
}
export declare function updateDomain(id: string, input: UpdateDomainInput): Domain | null;
export declare function deleteDomain(id: string): boolean;
export declare function countDomains(): number;
export declare function searchDomains(query: string): Domain[];
export declare function getByRegistrar(registrar: string): Domain[];
/**
* Domains ALREADY PAST their recorded expiry while still claiming to be active.
*
* This is the set the forward-only window could never return: `expiring --days N`
* floored its comparison at `now`, so a name one day over the line was invisible
* to the exact command built to surface it. A countdown that stops at zero is not
* an early warning.
*
* The status filter mirrors `listExpiringWindow` exactly, so the two halves differ
* only in the direction of the date comparison. A row already labelled `expired`
* is a known state, not a surprise, and is deliberately not reported here.
*/
export declare function listPastExpiry(): Domain[];
/**
* Domains expiring within the next `days`, EXCLUDING those already lapsed.
*
* This is the original forward-only behaviour, kept under an explicit name so
* the `expiring_30_days` statistic keeps meaning exactly what it always meant.
* Changing that number's meaning silently would trade one wrong reading for
* another.
*/
export declare function listExpiringWindow(days: number): Domain[];
/**
* Two-sided expiry: everything already lapsed, plus everything due within
* `days`. Lapsed names sort first because their dates are earliest.
*
* `includeLapsed: false` recovers the old forward-only set for a caller that
* genuinely wants a forward window.
*/
export declare function listExpiring(days: number, options?: {
includeLapsed?: boolean;
}): Domain[];
/** SSL certificates already past their recorded expiry. Mirror of `listPastExpiry`. */
export declare function listSslPastExpiry(): Domain[];
/** SSL certificates expiring within `days`, excluding those already lapsed. */
export declare function listSslExpiringWindow(days: number): Domain[];
/**
* Two-sided SSL expiry. The same blind spot existed here and would have been
* left behind by a fix that only touched the domain-expiry path.
*/
export declare function listSslExpiring(days: number, options?: {
includeLapsed?: boolean;
}): Domain[];
export interface DomainStats {
total: number;
active: number;
expired: number;
transferring: number;
redemption: number;
auto_renew_enabled: number;
/** Forward window only, excluding lapsed names. Meaning unchanged. */
expiring_30_days: number;
ssl_expiring_30_days: number;
/** Past recorded expiry while still status=active — invisible before this fix. */
past_expiry: number;
/** Past recorded SSL expiry. */
ssl_past_expiry: number;
/** Rows whose registrar facts have never been confirmed against a registrar. */
never_synced: number;
}
export declare function getDomainStats(): DomainStats;
export declare function getDomainByName(name: string): Domain | null;
export interface DomainOffer {
id: string;
domain_id: string;
our_offer: number | null;
their_ask: number | null;
status: DomainOfferStatus;
notes: string | null;
created_at: string;
}
interface DomainOfferRow {
id: string;
domain_id: string;
our_offer: number | null;
their_ask: number | null;
status: string;
notes: string | null;
created_at: string;
}
export interface CreateDomainOfferInput {
domain_id: string;
our_offer?: number;
their_ask?: number;
status?: DomainOfferStatus;
notes?: string;
}
export declare function rowToDomainOffer(row: DomainOfferRow): DomainOffer;
export declare function createDomainOffer(input: CreateDomainOfferInput): DomainOffer;
export declare function getDomainOffer(id: string): DomainOffer | null;
export declare function listDomainOffers(domainId: string): DomainOffer[];
export interface DomainEmailLink {
id: string;
domain_id: string;
email_id: string;
thread_id: string | null;
type: DomainEmailType;
created_at: string;
}
interface DomainEmailLinkRow {
id: string;
domain_id: string;
email_id: string;
thread_id: string | null;
type: string;
created_at: string;
}
export interface CreateDomainEmailLinkInput {
domain_id: string;
email_id: string;
thread_id?: string;
type: DomainEmailType;
}
export declare function rowToDomainEmailLink(row: DomainEmailLinkRow): DomainEmailLink;
export declare function linkDomainEmail(input: CreateDomainEmailLinkInput): DomainEmailLink;
export declare function getDomainEmailLink(id: string): DomainEmailLink | null;
export declare function listDomainEmailLinks(domainId: string): DomainEmailLink[];
export interface DomainDetails {
domain: Domain;
offers: DomainOffer[];
emails: DomainEmailLink[];
}
export declare function getDomainDetails(identifier: string): DomainDetails | null;
export declare function markDomainPremium(identifier: string, premiumPrice: number, standardPrice?: number): Domain | null;
export declare function updateDomainLifecycleStatus(identifier: string, status: DomainStatus, notes?: string): Domain | null;
export interface RecordDomainPurchaseInput {
price: number;
registrar: string;
purchase_date?: string;
expires_at?: string;
auto_renew?: boolean;
notes?: string;
standard_price?: number;
}
export declare function recordDomainPurchase(identifier: string, input: RecordDomainPurchaseInput): Domain | null;
export {};
//# sourceMappingURL=domain-records.d.ts.map