Repository navigation
feat(domains): add forge activation methods #262
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,7 @@ | ||
| PATH | ||
| remote: . | ||
| specs: | ||
| resend (1.19.0) | ||
| resend (1.20.0) | ||
| base64 | ||
| httparty (>= 0.22.0) | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| # frozen_string_literal: true | ||
|
|
||
| module Resend | ||
| module Domains | ||
| # Domain Forge API wrapper | ||
| module Forge | ||
| class << self | ||
| # | ||
| # Activate Forge on a domain. Returns the full domain, in the same shape | ||
| # as Resend::Domains.get. Enabling a domain that is already migrated is | ||
| # idempotent and returns its current state. | ||
| # | ||
| # @param params [Hash] the parameters | ||
| # @option params [String] :id the ID of the domain (required) | ||
| # @option params [String] :return_path subdomain for the Return-Path address. | ||
| # When omitted, the server picks a free DNS label. | ||
| # | ||
| # https://resend.com/docs/api-reference/domains/enable-forge | ||
| def enable(params) | ||
| path = "domains/#{params[:id]}/forge" | ||
| Resend::Request.new(path, params.slice(:return_path), "post").perform | ||
| end | ||
| end | ||
| end | ||
| end | ||
| end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,5 @@ | ||
| # frozen_string_literal: true | ||
|
|
||
| module Resend | ||
| VERSION = "1.19.0" | ||
| VERSION = "1.20.0" | ||
| end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,76 @@ | ||
| # frozen_string_literal: true | ||
|
|
||
| RSpec.describe "Domains::Forge" do | ||
| before do | ||
| Resend.configure do |config| | ||
| config.api_key = "re_123" | ||
| end | ||
| end | ||
|
|
||
| let(:domain_id) { "d91cd9bd-1176-453e-8fc1-35364d380206" } | ||
|
|
||
| let(:forge_domain) do | ||
| { | ||
| object: "domain", | ||
| id: "d91cd9bd-1176-453e-8fc1-35364d380206", | ||
| name: "example.com", | ||
| status: "pending", | ||
| created_at: "2026-11-11 10:00:00.000000+00", | ||
| region: "us-east-1", | ||
| capabilities: { | ||
| "sending" => "enabled", | ||
| "receiving" => "disabled" | ||
| }, | ||
| records: [ | ||
| { | ||
| "record" => "SPF", | ||
| "name" => "send", | ||
| "value" => "v=spf1 include:spf.resend.com ~all", | ||
| "type" => "TXT", | ||
| "ttl" => "Auto", | ||
| "status" => "pending" | ||
| }, | ||
| { | ||
| "record" => "DKIM", | ||
| "name" => "resend._domainkey", | ||
| "value" => "resend._domainkey.example.com.dkim.resend.com.", | ||
| "type" => "CNAME", | ||
| "ttl" => "Auto", | ||
| "status" => "pending" | ||
| } | ||
| ], | ||
| open_tracking: false, | ||
| click_tracking: false | ||
| } | ||
| end | ||
|
|
||
| describe "enable" do | ||
| it "activates Forge and returns the full domain" do | ||
| params = { id: domain_id, return_path: "send" } | ||
|
|
||
| expect(Resend::Request).to receive(:new) | ||
| .with("domains/#{domain_id}/forge", { return_path: "send" }, "post") | ||
| .and_call_original | ||
| allow_any_instance_of(Resend::Request).to receive(:perform).and_return(forge_domain) | ||
|
|
||
| domain = Resend::Domains::Forge.enable(params) | ||
|
|
||
| expect(domain[:object]).to eql("domain") | ||
| expect(domain[:id]).to eql(domain_id) | ||
| expect(domain[:status]).to eql("pending") | ||
| expect(domain[:records].first["record"]).to eql("SPF") | ||
| end | ||
|
|
||
| it "activates Forge without a return path" do | ||
| expect(Resend::Request).to receive(:new) | ||
| .with("domains/#{domain_id}/forge", {}, "post") | ||
| .and_call_original | ||
| allow_any_instance_of(Resend::Request).to receive(:perform).and_return(forge_domain) | ||
|
|
||
| domain = Resend::Domains::Forge.enable({ id: domain_id }) | ||
|
|
||
| expect(domain[:object]).to eql("domain") | ||
| expect(domain[:id]).to eql(domain_id) | ||
| end | ||
| end | ||
| end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -199,6 +199,27 @@ | |
| domain = Resend::Domains.update(update_params) | ||
| expect(domain[:id]).to eql("479e3145-dd38-476b-932c-529ceb705947") | ||
| end | ||
|
|
||
| it "updates the forge return path" do | ||
| resp = { | ||
| "object": "domain", | ||
| "id": "479e3145-dd38-476b-932c-529ceb705947" | ||
| } | ||
|
|
||
| update_params = { | ||
| id: "479e3145-dd38-476b-932c-529ceb705947", | ||
| forge_return_path: "outbound" | ||
| } | ||
|
|
||
| expect(Resend::Request).to receive(:new) | ||
| .with("domains/479e3145-dd38-476b-932c-529ceb705947", update_params, "patch") | ||
| .and_call_original | ||
| allow_any_instance_of(Resend::Request).to receive(:perform).and_return(resp) | ||
|
|
||
| domain = Resend::Domains.update(update_params) | ||
| expect(domain[:id]).to eql("479e3145-dd38-476b-932c-529ceb705947") | ||
| expect(domain[:object]).to eql("domain") | ||
| end | ||
| end | ||
|
|
||
| describe "get domain" do | ||
|
|
@@ -278,5 +299,21 @@ | |
| allow_any_instance_of(Resend::Request).to receive(:perform).and_return("") | ||
| expect { Resend::Domains.verify }.not_to raise_error | ||
| end | ||
|
|
||
| it "verifies only the Forge record when scoped" do | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: Custom agent: API Key Permission Check SDK Methods These tests exercise new Forge provider operations — PATCH Prompt for AI agents |
||
| resp = { | ||
| "object": "domain", | ||
| "id": "d91cd9bd-1176-453e-8fc1-35364d380206" | ||
| } | ||
|
|
||
| expect(Resend::Request).to receive(:new) | ||
| .with("domains/d91cd9bd-1176-453e-8fc1-35364d380206/verify", { scope: ["forge"] }, "post") | ||
| .and_call_original | ||
| allow_any_instance_of(Resend::Request).to receive(:perform).and_return(resp) | ||
|
|
||
| verified = Resend::Domains.verify("d91cd9bd-1176-453e-8fc1-35364d380206", scope: ["forge"]) | ||
| expect(verified[:object]).to eql("domain") | ||
| expect(verified[:id]).to eql("d91cd9bd-1176-453e-8fc1-35364d380206") | ||
| end | ||
| end | ||
| end | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P3: This example depends on API-key state left by earlier examples, so it fails when run by itself (for example, while debugging this line). Add a local
Resend.configuresetup for the verification examples, or move the configuration to the outerDomainsgroup.Prompt for AI agents