@primitivedotdev/cli 0.31.3 → 0.31.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/oclif/index.js +866 -47
- package/package.json +2 -2
package/dist/oclif/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Args, Command, Errors, Flags } from "@oclif/core";
|
|
2
2
|
import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { randomUUID } from "node:crypto";
|
|
4
|
-
import { dirname, join, resolve } from "node:path";
|
|
4
|
+
import { basename, dirname, join, resolve } from "node:path";
|
|
5
5
|
import { spawn } from "node:child_process";
|
|
6
6
|
import { hostname } from "node:os";
|
|
7
7
|
import process$1 from "node:process";
|
|
@@ -645,6 +645,7 @@ var sdk_gen_exports = /* @__PURE__ */ __exportAll({
|
|
|
645
645
|
deleteFunctionSecret: () => deleteFunctionSecret,
|
|
646
646
|
discardEmailContent: () => discardEmailContent,
|
|
647
647
|
downloadAttachments: () => downloadAttachments,
|
|
648
|
+
downloadDomainZoneFile: () => downloadDomainZoneFile,
|
|
648
649
|
downloadRawEmail: () => downloadRawEmail,
|
|
649
650
|
getAccount: () => getAccount,
|
|
650
651
|
getEmail: () => getEmail,
|
|
@@ -941,9 +942,11 @@ const listDomains = (options) => (options?.client ?? client).get({
|
|
|
941
942
|
/**
|
|
942
943
|
* Claim a new domain
|
|
943
944
|
*
|
|
944
|
-
* Creates an unverified domain claim
|
|
945
|
-
*
|
|
946
|
-
* calling the verify endpoint.
|
|
945
|
+
* Creates an unverified domain claim and returns the exact
|
|
946
|
+
* DNS records to publish in `dns_records`. Publish those
|
|
947
|
+
* records before calling the verify endpoint. To give users
|
|
948
|
+
* an importable DNS file, call `downloadDomainZoneFile` or run
|
|
949
|
+
* `primitive domains zone-file --id <domain-id>`.
|
|
947
950
|
*
|
|
948
951
|
*/
|
|
949
952
|
const addDomain = (options) => (options.client ?? client).post({
|
|
@@ -993,9 +996,15 @@ const updateDomain = (options) => (options.client ?? client).patch({
|
|
|
993
996
|
/**
|
|
994
997
|
* Verify domain ownership
|
|
995
998
|
*
|
|
996
|
-
* Checks DNS records
|
|
999
|
+
* Checks DNS records required for inbound routing, ownership,
|
|
1000
|
+
* and outbound authentication: MX, ownership TXT, SPF, DKIM,
|
|
1001
|
+
* DMARC, and TLS-RPT.
|
|
997
1002
|
* On success, the domain is promoted from unverified to verified.
|
|
998
|
-
* On failure, returns which checks passed and which failed
|
|
1003
|
+
* On failure, returns which checks passed and which failed,
|
|
1004
|
+
* plus the exact DNS records still expected. To give users
|
|
1005
|
+
* an importable DNS file for missing records, call
|
|
1006
|
+
* `downloadDomainZoneFile` or run
|
|
1007
|
+
* `primitive domains zone-file --id <domain-id>`.
|
|
999
1008
|
*
|
|
1000
1009
|
*/
|
|
1001
1010
|
const verifyDomain = (options) => (options.client ?? client).post({
|
|
@@ -1007,6 +1016,23 @@ const verifyDomain = (options) => (options.client ?? client).post({
|
|
|
1007
1016
|
...options
|
|
1008
1017
|
});
|
|
1009
1018
|
/**
|
|
1019
|
+
* Download domain DNS zone file
|
|
1020
|
+
*
|
|
1021
|
+
* Downloads a BIND-format DNS zone file containing the DNS records
|
|
1022
|
+
* required for a domain claim. Agents should offer this after
|
|
1023
|
+
* `addDomain` when users want to import DNS records instead of
|
|
1024
|
+
* copying each record manually.
|
|
1025
|
+
*
|
|
1026
|
+
*/
|
|
1027
|
+
const downloadDomainZoneFile = (options) => (options.client ?? client).get({
|
|
1028
|
+
security: [{
|
|
1029
|
+
scheme: "bearer",
|
|
1030
|
+
type: "http"
|
|
1031
|
+
}],
|
|
1032
|
+
url: "/domains/{id}/zone-file",
|
|
1033
|
+
...options
|
|
1034
|
+
});
|
|
1035
|
+
/**
|
|
1010
1036
|
* List inbound emails
|
|
1011
1037
|
*
|
|
1012
1038
|
* Returns a paginated list of INBOUND emails received at your
|
|
@@ -2333,7 +2359,7 @@ const openapiDocument = {
|
|
|
2333
2359
|
"post": {
|
|
2334
2360
|
"operationId": "addDomain",
|
|
2335
2361
|
"summary": "Claim a new domain",
|
|
2336
|
-
"description": "Creates an unverified domain claim
|
|
2362
|
+
"description": "Creates an unverified domain claim and returns the exact\nDNS records to publish in `dns_records`. Publish those\nrecords before calling the verify endpoint. To give users\nan importable DNS file, call `downloadDomainZoneFile` or run\n`primitive domains zone-file --id <domain-id>`.\n",
|
|
2337
2363
|
"tags": ["Domains"],
|
|
2338
2364
|
"requestBody": {
|
|
2339
2365
|
"required": true,
|
|
@@ -2426,7 +2452,7 @@ const openapiDocument = {
|
|
|
2426
2452
|
"post": {
|
|
2427
2453
|
"operationId": "verifyDomain",
|
|
2428
2454
|
"summary": "Verify domain ownership",
|
|
2429
|
-
"description": "Checks DNS records
|
|
2455
|
+
"description": "Checks DNS records required for inbound routing, ownership,\nand outbound authentication: MX, ownership TXT, SPF, DKIM,\nDMARC, and TLS-RPT.\nOn success, the domain is promoted from unverified to verified.\nOn failure, returns which checks passed and which failed,\nplus the exact DNS records still expected. To give users\nan importable DNS file for missing records, call\n`downloadDomainZoneFile` or run\n`primitive domains zone-file --id <domain-id>`.\n",
|
|
2430
2456
|
"tags": ["Domains"],
|
|
2431
2457
|
"responses": {
|
|
2432
2458
|
"200": {
|
|
@@ -2442,6 +2468,38 @@ const openapiDocument = {
|
|
|
2442
2468
|
}
|
|
2443
2469
|
}
|
|
2444
2470
|
},
|
|
2471
|
+
"/domains/{id}/zone-file": {
|
|
2472
|
+
"parameters": [{ "$ref": "#/components/parameters/ResourceId" }],
|
|
2473
|
+
"get": {
|
|
2474
|
+
"operationId": "downloadDomainZoneFile",
|
|
2475
|
+
"summary": "Download domain DNS zone file",
|
|
2476
|
+
"description": "Downloads a BIND-format DNS zone file containing the DNS records\nrequired for a domain claim. Agents should offer this after\n`addDomain` when users want to import DNS records instead of\ncopying each record manually.\n",
|
|
2477
|
+
"tags": ["Domains"],
|
|
2478
|
+
"parameters": [{
|
|
2479
|
+
"name": "outbound_only",
|
|
2480
|
+
"in": "query",
|
|
2481
|
+
"schema": { "type": "boolean" },
|
|
2482
|
+
"description": "When true, include only outbound DNS records. Verified domains\ndefault to outbound-only; pending claims default to all required\nrecords.\n"
|
|
2483
|
+
}],
|
|
2484
|
+
"responses": {
|
|
2485
|
+
"200": {
|
|
2486
|
+
"description": "BIND-format zone file",
|
|
2487
|
+
"content": { "text/plain": { "schema": {
|
|
2488
|
+
"type": "string",
|
|
2489
|
+
"format": "binary"
|
|
2490
|
+
} } },
|
|
2491
|
+
"headers": { "Content-Disposition": { "schema": {
|
|
2492
|
+
"type": "string",
|
|
2493
|
+
"example": "attachment; filename=\"example.com.zone\""
|
|
2494
|
+
} } }
|
|
2495
|
+
},
|
|
2496
|
+
"400": { "$ref": "#/components/responses/ValidationError" },
|
|
2497
|
+
"401": { "$ref": "#/components/responses/Unauthorized" },
|
|
2498
|
+
"404": { "$ref": "#/components/responses/NotFound" },
|
|
2499
|
+
"429": { "$ref": "#/components/responses/RateLimited" }
|
|
2500
|
+
}
|
|
2501
|
+
}
|
|
2502
|
+
},
|
|
2445
2503
|
"/emails": { "get": {
|
|
2446
2504
|
"operationId": "listEmails",
|
|
2447
2505
|
"summary": "List inbound emails",
|
|
@@ -4731,7 +4789,7 @@ const openapiDocument = {
|
|
|
4731
4789
|
"required": ["secret"]
|
|
4732
4790
|
},
|
|
4733
4791
|
"Domain": {
|
|
4734
|
-
"description": "A domain can be either verified or unverified. Verified domains have\n`is_active` and `spam_threshold` fields. Unverified domains have a\n`verification_token` for DNS
|
|
4792
|
+
"description": "A domain can be either verified or unverified. Verified domains have\n`is_active` and `spam_threshold` fields. Unverified domains have a\n`verification_token` and `dns_records` for DNS setup.\n",
|
|
4735
4793
|
"oneOf": [{ "$ref": "#/components/schemas/VerifiedDomain" }, { "$ref": "#/components/schemas/UnverifiedDomain" }]
|
|
4736
4794
|
},
|
|
4737
4795
|
"VerifiedDomain": {
|
|
@@ -4771,6 +4829,74 @@ const openapiDocument = {
|
|
|
4771
4829
|
"created_at"
|
|
4772
4830
|
]
|
|
4773
4831
|
},
|
|
4832
|
+
"DomainDnsRecord": {
|
|
4833
|
+
"type": "object",
|
|
4834
|
+
"additionalProperties": false,
|
|
4835
|
+
"properties": {
|
|
4836
|
+
"type": {
|
|
4837
|
+
"type": "string",
|
|
4838
|
+
"enum": ["MX", "TXT"],
|
|
4839
|
+
"description": "DNS record type."
|
|
4840
|
+
},
|
|
4841
|
+
"name": {
|
|
4842
|
+
"type": "string",
|
|
4843
|
+
"description": "DNS-provider host/name value relative to the managed root zone."
|
|
4844
|
+
},
|
|
4845
|
+
"fqdn": {
|
|
4846
|
+
"type": "string",
|
|
4847
|
+
"description": "Fully-qualified DNS record name."
|
|
4848
|
+
},
|
|
4849
|
+
"value": {
|
|
4850
|
+
"type": "string",
|
|
4851
|
+
"description": "Exact value to publish."
|
|
4852
|
+
},
|
|
4853
|
+
"priority": {
|
|
4854
|
+
"type": "integer",
|
|
4855
|
+
"description": "MX priority. Present only for MX records."
|
|
4856
|
+
},
|
|
4857
|
+
"ttl": {
|
|
4858
|
+
"type": "integer",
|
|
4859
|
+
"description": "Suggested TTL in seconds when the API can provide one."
|
|
4860
|
+
},
|
|
4861
|
+
"required": {
|
|
4862
|
+
"type": "boolean",
|
|
4863
|
+
"const": true
|
|
4864
|
+
},
|
|
4865
|
+
"purpose": {
|
|
4866
|
+
"type": "string",
|
|
4867
|
+
"enum": [
|
|
4868
|
+
"inbound_mx",
|
|
4869
|
+
"ownership_verification",
|
|
4870
|
+
"spf",
|
|
4871
|
+
"dkim",
|
|
4872
|
+
"dmarc",
|
|
4873
|
+
"tls_reporting"
|
|
4874
|
+
]
|
|
4875
|
+
},
|
|
4876
|
+
"status": {
|
|
4877
|
+
"type": "string",
|
|
4878
|
+
"enum": [
|
|
4879
|
+
"pending",
|
|
4880
|
+
"found",
|
|
4881
|
+
"missing",
|
|
4882
|
+
"incorrect"
|
|
4883
|
+
]
|
|
4884
|
+
},
|
|
4885
|
+
"message": {
|
|
4886
|
+
"type": "string",
|
|
4887
|
+
"description": "Short explanation of why this record is needed."
|
|
4888
|
+
}
|
|
4889
|
+
},
|
|
4890
|
+
"required": [
|
|
4891
|
+
"type",
|
|
4892
|
+
"name",
|
|
4893
|
+
"fqdn",
|
|
4894
|
+
"value",
|
|
4895
|
+
"required",
|
|
4896
|
+
"purpose",
|
|
4897
|
+
"status"
|
|
4898
|
+
]
|
|
4899
|
+
},
|
|
4774
4900
|
"UnverifiedDomain": {
|
|
4775
4901
|
"type": "object",
|
|
4776
4902
|
"properties": {
|
|
@@ -4791,6 +4917,11 @@ const openapiDocument = {
|
|
|
4791
4917
|
"type": "string",
|
|
4792
4918
|
"description": "Add this value as a TXT record to verify ownership"
|
|
4793
4919
|
},
|
|
4920
|
+
"dns_records": {
|
|
4921
|
+
"type": "array",
|
|
4922
|
+
"description": "Exact DNS records to publish for this pending domain claim.",
|
|
4923
|
+
"items": { "$ref": "#/components/schemas/DomainDnsRecord" }
|
|
4924
|
+
},
|
|
4794
4925
|
"created_at": {
|
|
4795
4926
|
"type": "string",
|
|
4796
4927
|
"format": "date-time"
|
|
@@ -4808,12 +4939,23 @@ const openapiDocument = {
|
|
|
4808
4939
|
"AddDomainInput": {
|
|
4809
4940
|
"type": "object",
|
|
4810
4941
|
"additionalProperties": false,
|
|
4811
|
-
"properties": {
|
|
4812
|
-
"
|
|
4813
|
-
|
|
4814
|
-
|
|
4815
|
-
|
|
4816
|
-
|
|
4942
|
+
"properties": {
|
|
4943
|
+
"domain": {
|
|
4944
|
+
"type": "string",
|
|
4945
|
+
"minLength": 1,
|
|
4946
|
+
"maxLength": 253,
|
|
4947
|
+
"description": "The domain name to claim (e.g. \"example.com\")"
|
|
4948
|
+
},
|
|
4949
|
+
"confirmed": {
|
|
4950
|
+
"type": "boolean",
|
|
4951
|
+
"description": "Set to true to confirm replacing an existing mailbox provider after an mx_conflict response."
|
|
4952
|
+
},
|
|
4953
|
+
"outbound": {
|
|
4954
|
+
"type": "boolean",
|
|
4955
|
+
"deprecated": true,
|
|
4956
|
+
"description": "Deprecated and ignored. Outbound DNS is provisioned for every new domain claim."
|
|
4957
|
+
}
|
|
4958
|
+
},
|
|
4817
4959
|
"required": ["domain"]
|
|
4818
4960
|
},
|
|
4819
4961
|
"UpdateDomainInput": {
|
|
@@ -4835,10 +4977,17 @@ const openapiDocument = {
|
|
|
4835
4977
|
},
|
|
4836
4978
|
"DomainVerifyResult": { "oneOf": [{
|
|
4837
4979
|
"type": "object",
|
|
4838
|
-
"properties": {
|
|
4839
|
-
"
|
|
4840
|
-
|
|
4841
|
-
|
|
4980
|
+
"properties": {
|
|
4981
|
+
"verified": {
|
|
4982
|
+
"type": "boolean",
|
|
4983
|
+
"const": true
|
|
4984
|
+
},
|
|
4985
|
+
"dns_records": {
|
|
4986
|
+
"type": "array",
|
|
4987
|
+
"description": "Exact DNS records checked for this verification attempt.",
|
|
4988
|
+
"items": { "$ref": "#/components/schemas/DomainDnsRecord" }
|
|
4989
|
+
}
|
|
4990
|
+
},
|
|
4842
4991
|
"required": ["verified"]
|
|
4843
4992
|
}, {
|
|
4844
4993
|
"type": "object",
|
|
@@ -4855,6 +5004,27 @@ const openapiDocument = {
|
|
|
4855
5004
|
"type": "boolean",
|
|
4856
5005
|
"description": "Whether the TXT verification record was found"
|
|
4857
5006
|
},
|
|
5007
|
+
"spfFound": {
|
|
5008
|
+
"type": "boolean",
|
|
5009
|
+
"description": "Whether the SPF record includes Primitive."
|
|
5010
|
+
},
|
|
5011
|
+
"dkimFound": {
|
|
5012
|
+
"type": "boolean",
|
|
5013
|
+
"description": "Whether the DKIM public key record was found."
|
|
5014
|
+
},
|
|
5015
|
+
"dmarcFound": {
|
|
5016
|
+
"type": "boolean",
|
|
5017
|
+
"description": "Whether the DMARC record was found."
|
|
5018
|
+
},
|
|
5019
|
+
"tlsRptFound": {
|
|
5020
|
+
"type": "boolean",
|
|
5021
|
+
"description": "Whether the TLS-RPT record was found."
|
|
5022
|
+
},
|
|
5023
|
+
"dns_records": {
|
|
5024
|
+
"type": "array",
|
|
5025
|
+
"description": "Exact DNS records checked for this verification attempt.",
|
|
5026
|
+
"items": { "$ref": "#/components/schemas/DomainDnsRecord" }
|
|
5027
|
+
},
|
|
4858
5028
|
"error": {
|
|
4859
5029
|
"type": "string",
|
|
4860
5030
|
"description": "Human-readable verification failure reason"
|
|
@@ -5167,6 +5337,31 @@ const openapiDocument = {
|
|
|
5167
5337
|
"created_at"
|
|
5168
5338
|
]
|
|
5169
5339
|
},
|
|
5340
|
+
"SendMailAttachment": {
|
|
5341
|
+
"type": "object",
|
|
5342
|
+
"additionalProperties": false,
|
|
5343
|
+
"properties": {
|
|
5344
|
+
"filename": {
|
|
5345
|
+
"type": "string",
|
|
5346
|
+
"minLength": 1,
|
|
5347
|
+
"maxLength": 255,
|
|
5348
|
+
"description": "Attachment filename. Control characters are rejected."
|
|
5349
|
+
},
|
|
5350
|
+
"content_type": {
|
|
5351
|
+
"type": "string",
|
|
5352
|
+
"minLength": 1,
|
|
5353
|
+
"maxLength": 255,
|
|
5354
|
+
"description": "Optional MIME content type. Control characters are rejected."
|
|
5355
|
+
},
|
|
5356
|
+
"content_base64": {
|
|
5357
|
+
"type": "string",
|
|
5358
|
+
"minLength": 1,
|
|
5359
|
+
"maxLength": 44040192,
|
|
5360
|
+
"description": "Base64-encoded attachment bytes."
|
|
5361
|
+
}
|
|
5362
|
+
},
|
|
5363
|
+
"required": ["filename", "content_base64"]
|
|
5364
|
+
},
|
|
5170
5365
|
"SendMailInput": {
|
|
5171
5366
|
"type": "object",
|
|
5172
5367
|
"additionalProperties": false,
|
|
@@ -5215,6 +5410,12 @@ const openapiDocument = {
|
|
|
5215
5410
|
"pattern": "^[^\\x00-\\x1F\\x7F]+$"
|
|
5216
5411
|
}
|
|
5217
5412
|
},
|
|
5413
|
+
"attachments": {
|
|
5414
|
+
"type": "array",
|
|
5415
|
+
"maxItems": 100,
|
|
5416
|
+
"description": "Inline attachments. Send requests with attachments to https://api.primitive.dev/v1/send-mail. Combined raw decoded attachment bytes must be at most 31457280.",
|
|
5417
|
+
"items": { "$ref": "#/components/schemas/SendMailAttachment" }
|
|
5418
|
+
},
|
|
5218
5419
|
"wait": {
|
|
5219
5420
|
"type": "boolean",
|
|
5220
5421
|
"description": "When true, wait for the first downstream SMTP delivery outcome before returning."
|
|
@@ -7502,7 +7703,7 @@ const operationManifest = [
|
|
|
7502
7703
|
"binaryResponse": false,
|
|
7503
7704
|
"bodyRequired": true,
|
|
7504
7705
|
"command": "add-domain",
|
|
7505
|
-
"description": "Creates an unverified domain claim
|
|
7706
|
+
"description": "Creates an unverified domain claim and returns the exact\nDNS records to publish in `dns_records`. Publish those\nrecords before calling the verify endpoint. To give users\nan importable DNS file, call `downloadDomainZoneFile` or run\n`primitive domains zone-file --id <domain-id>`.\n",
|
|
7506
7707
|
"hasJsonBody": true,
|
|
7507
7708
|
"method": "POST",
|
|
7508
7709
|
"operationId": "addDomain",
|
|
@@ -7512,12 +7713,23 @@ const operationManifest = [
|
|
|
7512
7713
|
"requestSchema": {
|
|
7513
7714
|
"type": "object",
|
|
7514
7715
|
"additionalProperties": false,
|
|
7515
|
-
"properties": {
|
|
7516
|
-
"
|
|
7517
|
-
|
|
7518
|
-
|
|
7519
|
-
|
|
7520
|
-
|
|
7716
|
+
"properties": {
|
|
7717
|
+
"domain": {
|
|
7718
|
+
"type": "string",
|
|
7719
|
+
"minLength": 1,
|
|
7720
|
+
"maxLength": 253,
|
|
7721
|
+
"description": "The domain name to claim (e.g. \"example.com\")"
|
|
7722
|
+
},
|
|
7723
|
+
"confirmed": {
|
|
7724
|
+
"type": "boolean",
|
|
7725
|
+
"description": "Set to true to confirm replacing an existing mailbox provider after an mx_conflict response."
|
|
7726
|
+
},
|
|
7727
|
+
"outbound": {
|
|
7728
|
+
"type": "boolean",
|
|
7729
|
+
"deprecated": true,
|
|
7730
|
+
"description": "Deprecated and ignored. Outbound DNS is provisioned for every new domain claim."
|
|
7731
|
+
}
|
|
7732
|
+
},
|
|
7521
7733
|
"required": ["domain"]
|
|
7522
7734
|
},
|
|
7523
7735
|
"responseSchema": {
|
|
@@ -7540,6 +7752,78 @@ const operationManifest = [
|
|
|
7540
7752
|
"type": "string",
|
|
7541
7753
|
"description": "Add this value as a TXT record to verify ownership"
|
|
7542
7754
|
},
|
|
7755
|
+
"dns_records": {
|
|
7756
|
+
"type": "array",
|
|
7757
|
+
"description": "Exact DNS records to publish for this pending domain claim.",
|
|
7758
|
+
"items": {
|
|
7759
|
+
"type": "object",
|
|
7760
|
+
"additionalProperties": false,
|
|
7761
|
+
"properties": {
|
|
7762
|
+
"type": {
|
|
7763
|
+
"type": "string",
|
|
7764
|
+
"enum": ["MX", "TXT"],
|
|
7765
|
+
"description": "DNS record type."
|
|
7766
|
+
},
|
|
7767
|
+
"name": {
|
|
7768
|
+
"type": "string",
|
|
7769
|
+
"description": "DNS-provider host/name value relative to the managed root zone."
|
|
7770
|
+
},
|
|
7771
|
+
"fqdn": {
|
|
7772
|
+
"type": "string",
|
|
7773
|
+
"description": "Fully-qualified DNS record name."
|
|
7774
|
+
},
|
|
7775
|
+
"value": {
|
|
7776
|
+
"type": "string",
|
|
7777
|
+
"description": "Exact value to publish."
|
|
7778
|
+
},
|
|
7779
|
+
"priority": {
|
|
7780
|
+
"type": "integer",
|
|
7781
|
+
"description": "MX priority. Present only for MX records."
|
|
7782
|
+
},
|
|
7783
|
+
"ttl": {
|
|
7784
|
+
"type": "integer",
|
|
7785
|
+
"description": "Suggested TTL in seconds when the API can provide one."
|
|
7786
|
+
},
|
|
7787
|
+
"required": {
|
|
7788
|
+
"type": "boolean",
|
|
7789
|
+
"const": true
|
|
7790
|
+
},
|
|
7791
|
+
"purpose": {
|
|
7792
|
+
"type": "string",
|
|
7793
|
+
"enum": [
|
|
7794
|
+
"inbound_mx",
|
|
7795
|
+
"ownership_verification",
|
|
7796
|
+
"spf",
|
|
7797
|
+
"dkim",
|
|
7798
|
+
"dmarc",
|
|
7799
|
+
"tls_reporting"
|
|
7800
|
+
]
|
|
7801
|
+
},
|
|
7802
|
+
"status": {
|
|
7803
|
+
"type": "string",
|
|
7804
|
+
"enum": [
|
|
7805
|
+
"pending",
|
|
7806
|
+
"found",
|
|
7807
|
+
"missing",
|
|
7808
|
+
"incorrect"
|
|
7809
|
+
]
|
|
7810
|
+
},
|
|
7811
|
+
"message": {
|
|
7812
|
+
"type": "string",
|
|
7813
|
+
"description": "Short explanation of why this record is needed."
|
|
7814
|
+
}
|
|
7815
|
+
},
|
|
7816
|
+
"required": [
|
|
7817
|
+
"type",
|
|
7818
|
+
"name",
|
|
7819
|
+
"fqdn",
|
|
7820
|
+
"value",
|
|
7821
|
+
"required",
|
|
7822
|
+
"purpose",
|
|
7823
|
+
"status"
|
|
7824
|
+
]
|
|
7825
|
+
}
|
|
7826
|
+
},
|
|
7543
7827
|
"created_at": {
|
|
7544
7828
|
"type": "string",
|
|
7545
7829
|
"format": "date-time"
|
|
@@ -7583,6 +7867,36 @@ const operationManifest = [
|
|
|
7583
7867
|
"tag": "Domains",
|
|
7584
7868
|
"tagCommand": "domains"
|
|
7585
7869
|
},
|
|
7870
|
+
{
|
|
7871
|
+
"binaryResponse": true,
|
|
7872
|
+
"bodyRequired": false,
|
|
7873
|
+
"command": "download-domain-zone-file",
|
|
7874
|
+
"description": "Downloads a BIND-format DNS zone file containing the DNS records\nrequired for a domain claim. Agents should offer this after\n`addDomain` when users want to import DNS records instead of\ncopying each record manually.\n",
|
|
7875
|
+
"hasJsonBody": false,
|
|
7876
|
+
"method": "GET",
|
|
7877
|
+
"operationId": "downloadDomainZoneFile",
|
|
7878
|
+
"path": "/domains/{id}/zone-file",
|
|
7879
|
+
"pathParams": [{
|
|
7880
|
+
"description": "Resource UUID",
|
|
7881
|
+
"enum": null,
|
|
7882
|
+
"name": "id",
|
|
7883
|
+
"required": true,
|
|
7884
|
+
"type": "string"
|
|
7885
|
+
}],
|
|
7886
|
+
"queryParams": [{
|
|
7887
|
+
"description": "When true, include only outbound DNS records. Verified domains\ndefault to outbound-only; pending claims default to all required\nrecords.\n",
|
|
7888
|
+
"enum": null,
|
|
7889
|
+
"name": "outbound_only",
|
|
7890
|
+
"required": false,
|
|
7891
|
+
"type": "boolean"
|
|
7892
|
+
}],
|
|
7893
|
+
"requestSchema": null,
|
|
7894
|
+
"responseSchema": null,
|
|
7895
|
+
"sdkName": "downloadDomainZoneFile",
|
|
7896
|
+
"summary": "Download domain DNS zone file",
|
|
7897
|
+
"tag": "Domains",
|
|
7898
|
+
"tagCommand": "domains"
|
|
7899
|
+
},
|
|
7586
7900
|
{
|
|
7587
7901
|
"binaryResponse": false,
|
|
7588
7902
|
"bodyRequired": false,
|
|
@@ -7598,7 +7912,7 @@ const operationManifest = [
|
|
|
7598
7912
|
"responseSchema": {
|
|
7599
7913
|
"type": "array",
|
|
7600
7914
|
"items": {
|
|
7601
|
-
"description": "A domain can be either verified or unverified. Verified domains have\n`is_active` and `spam_threshold` fields. Unverified domains have a\n`verification_token` for DNS
|
|
7915
|
+
"description": "A domain can be either verified or unverified. Verified domains have\n`is_active` and `spam_threshold` fields. Unverified domains have a\n`verification_token` and `dns_records` for DNS setup.\n",
|
|
7602
7916
|
"oneOf": [{
|
|
7603
7917
|
"type": "object",
|
|
7604
7918
|
"properties": {
|
|
@@ -7655,6 +7969,78 @@ const operationManifest = [
|
|
|
7655
7969
|
"type": "string",
|
|
7656
7970
|
"description": "Add this value as a TXT record to verify ownership"
|
|
7657
7971
|
},
|
|
7972
|
+
"dns_records": {
|
|
7973
|
+
"type": "array",
|
|
7974
|
+
"description": "Exact DNS records to publish for this pending domain claim.",
|
|
7975
|
+
"items": {
|
|
7976
|
+
"type": "object",
|
|
7977
|
+
"additionalProperties": false,
|
|
7978
|
+
"properties": {
|
|
7979
|
+
"type": {
|
|
7980
|
+
"type": "string",
|
|
7981
|
+
"enum": ["MX", "TXT"],
|
|
7982
|
+
"description": "DNS record type."
|
|
7983
|
+
},
|
|
7984
|
+
"name": {
|
|
7985
|
+
"type": "string",
|
|
7986
|
+
"description": "DNS-provider host/name value relative to the managed root zone."
|
|
7987
|
+
},
|
|
7988
|
+
"fqdn": {
|
|
7989
|
+
"type": "string",
|
|
7990
|
+
"description": "Fully-qualified DNS record name."
|
|
7991
|
+
},
|
|
7992
|
+
"value": {
|
|
7993
|
+
"type": "string",
|
|
7994
|
+
"description": "Exact value to publish."
|
|
7995
|
+
},
|
|
7996
|
+
"priority": {
|
|
7997
|
+
"type": "integer",
|
|
7998
|
+
"description": "MX priority. Present only for MX records."
|
|
7999
|
+
},
|
|
8000
|
+
"ttl": {
|
|
8001
|
+
"type": "integer",
|
|
8002
|
+
"description": "Suggested TTL in seconds when the API can provide one."
|
|
8003
|
+
},
|
|
8004
|
+
"required": {
|
|
8005
|
+
"type": "boolean",
|
|
8006
|
+
"const": true
|
|
8007
|
+
},
|
|
8008
|
+
"purpose": {
|
|
8009
|
+
"type": "string",
|
|
8010
|
+
"enum": [
|
|
8011
|
+
"inbound_mx",
|
|
8012
|
+
"ownership_verification",
|
|
8013
|
+
"spf",
|
|
8014
|
+
"dkim",
|
|
8015
|
+
"dmarc",
|
|
8016
|
+
"tls_reporting"
|
|
8017
|
+
]
|
|
8018
|
+
},
|
|
8019
|
+
"status": {
|
|
8020
|
+
"type": "string",
|
|
8021
|
+
"enum": [
|
|
8022
|
+
"pending",
|
|
8023
|
+
"found",
|
|
8024
|
+
"missing",
|
|
8025
|
+
"incorrect"
|
|
8026
|
+
]
|
|
8027
|
+
},
|
|
8028
|
+
"message": {
|
|
8029
|
+
"type": "string",
|
|
8030
|
+
"description": "Short explanation of why this record is needed."
|
|
8031
|
+
}
|
|
8032
|
+
},
|
|
8033
|
+
"required": [
|
|
8034
|
+
"type",
|
|
8035
|
+
"name",
|
|
8036
|
+
"fqdn",
|
|
8037
|
+
"value",
|
|
8038
|
+
"required",
|
|
8039
|
+
"purpose",
|
|
8040
|
+
"status"
|
|
8041
|
+
]
|
|
8042
|
+
}
|
|
8043
|
+
},
|
|
7658
8044
|
"created_at": {
|
|
7659
8045
|
"type": "string",
|
|
7660
8046
|
"format": "date-time"
|
|
@@ -7756,7 +8142,7 @@ const operationManifest = [
|
|
|
7756
8142
|
"binaryResponse": false,
|
|
7757
8143
|
"bodyRequired": false,
|
|
7758
8144
|
"command": "verify-domain",
|
|
7759
|
-
"description": "Checks DNS records
|
|
8145
|
+
"description": "Checks DNS records required for inbound routing, ownership,\nand outbound authentication: MX, ownership TXT, SPF, DKIM,\nDMARC, and TLS-RPT.\nOn success, the domain is promoted from unverified to verified.\nOn failure, returns which checks passed and which failed,\nplus the exact DNS records still expected. To give users\nan importable DNS file for missing records, call\n`downloadDomainZoneFile` or run\n`primitive domains zone-file --id <domain-id>`.\n",
|
|
7760
8146
|
"hasJsonBody": false,
|
|
7761
8147
|
"method": "POST",
|
|
7762
8148
|
"operationId": "verifyDomain",
|
|
@@ -7772,10 +8158,84 @@ const operationManifest = [
|
|
|
7772
8158
|
"requestSchema": null,
|
|
7773
8159
|
"responseSchema": { "oneOf": [{
|
|
7774
8160
|
"type": "object",
|
|
7775
|
-
"properties": {
|
|
7776
|
-
"
|
|
7777
|
-
|
|
7778
|
-
|
|
8161
|
+
"properties": {
|
|
8162
|
+
"verified": {
|
|
8163
|
+
"type": "boolean",
|
|
8164
|
+
"const": true
|
|
8165
|
+
},
|
|
8166
|
+
"dns_records": {
|
|
8167
|
+
"type": "array",
|
|
8168
|
+
"description": "Exact DNS records checked for this verification attempt.",
|
|
8169
|
+
"items": {
|
|
8170
|
+
"type": "object",
|
|
8171
|
+
"additionalProperties": false,
|
|
8172
|
+
"properties": {
|
|
8173
|
+
"type": {
|
|
8174
|
+
"type": "string",
|
|
8175
|
+
"enum": ["MX", "TXT"],
|
|
8176
|
+
"description": "DNS record type."
|
|
8177
|
+
},
|
|
8178
|
+
"name": {
|
|
8179
|
+
"type": "string",
|
|
8180
|
+
"description": "DNS-provider host/name value relative to the managed root zone."
|
|
8181
|
+
},
|
|
8182
|
+
"fqdn": {
|
|
8183
|
+
"type": "string",
|
|
8184
|
+
"description": "Fully-qualified DNS record name."
|
|
8185
|
+
},
|
|
8186
|
+
"value": {
|
|
8187
|
+
"type": "string",
|
|
8188
|
+
"description": "Exact value to publish."
|
|
8189
|
+
},
|
|
8190
|
+
"priority": {
|
|
8191
|
+
"type": "integer",
|
|
8192
|
+
"description": "MX priority. Present only for MX records."
|
|
8193
|
+
},
|
|
8194
|
+
"ttl": {
|
|
8195
|
+
"type": "integer",
|
|
8196
|
+
"description": "Suggested TTL in seconds when the API can provide one."
|
|
8197
|
+
},
|
|
8198
|
+
"required": {
|
|
8199
|
+
"type": "boolean",
|
|
8200
|
+
"const": true
|
|
8201
|
+
},
|
|
8202
|
+
"purpose": {
|
|
8203
|
+
"type": "string",
|
|
8204
|
+
"enum": [
|
|
8205
|
+
"inbound_mx",
|
|
8206
|
+
"ownership_verification",
|
|
8207
|
+
"spf",
|
|
8208
|
+
"dkim",
|
|
8209
|
+
"dmarc",
|
|
8210
|
+
"tls_reporting"
|
|
8211
|
+
]
|
|
8212
|
+
},
|
|
8213
|
+
"status": {
|
|
8214
|
+
"type": "string",
|
|
8215
|
+
"enum": [
|
|
8216
|
+
"pending",
|
|
8217
|
+
"found",
|
|
8218
|
+
"missing",
|
|
8219
|
+
"incorrect"
|
|
8220
|
+
]
|
|
8221
|
+
},
|
|
8222
|
+
"message": {
|
|
8223
|
+
"type": "string",
|
|
8224
|
+
"description": "Short explanation of why this record is needed."
|
|
8225
|
+
}
|
|
8226
|
+
},
|
|
8227
|
+
"required": [
|
|
8228
|
+
"type",
|
|
8229
|
+
"name",
|
|
8230
|
+
"fqdn",
|
|
8231
|
+
"value",
|
|
8232
|
+
"required",
|
|
8233
|
+
"purpose",
|
|
8234
|
+
"status"
|
|
8235
|
+
]
|
|
8236
|
+
}
|
|
8237
|
+
}
|
|
8238
|
+
},
|
|
7779
8239
|
"required": ["verified"]
|
|
7780
8240
|
}, {
|
|
7781
8241
|
"type": "object",
|
|
@@ -7792,6 +8252,94 @@ const operationManifest = [
|
|
|
7792
8252
|
"type": "boolean",
|
|
7793
8253
|
"description": "Whether the TXT verification record was found"
|
|
7794
8254
|
},
|
|
8255
|
+
"spfFound": {
|
|
8256
|
+
"type": "boolean",
|
|
8257
|
+
"description": "Whether the SPF record includes Primitive."
|
|
8258
|
+
},
|
|
8259
|
+
"dkimFound": {
|
|
8260
|
+
"type": "boolean",
|
|
8261
|
+
"description": "Whether the DKIM public key record was found."
|
|
8262
|
+
},
|
|
8263
|
+
"dmarcFound": {
|
|
8264
|
+
"type": "boolean",
|
|
8265
|
+
"description": "Whether the DMARC record was found."
|
|
8266
|
+
},
|
|
8267
|
+
"tlsRptFound": {
|
|
8268
|
+
"type": "boolean",
|
|
8269
|
+
"description": "Whether the TLS-RPT record was found."
|
|
8270
|
+
},
|
|
8271
|
+
"dns_records": {
|
|
8272
|
+
"type": "array",
|
|
8273
|
+
"description": "Exact DNS records checked for this verification attempt.",
|
|
8274
|
+
"items": {
|
|
8275
|
+
"type": "object",
|
|
8276
|
+
"additionalProperties": false,
|
|
8277
|
+
"properties": {
|
|
8278
|
+
"type": {
|
|
8279
|
+
"type": "string",
|
|
8280
|
+
"enum": ["MX", "TXT"],
|
|
8281
|
+
"description": "DNS record type."
|
|
8282
|
+
},
|
|
8283
|
+
"name": {
|
|
8284
|
+
"type": "string",
|
|
8285
|
+
"description": "DNS-provider host/name value relative to the managed root zone."
|
|
8286
|
+
},
|
|
8287
|
+
"fqdn": {
|
|
8288
|
+
"type": "string",
|
|
8289
|
+
"description": "Fully-qualified DNS record name."
|
|
8290
|
+
},
|
|
8291
|
+
"value": {
|
|
8292
|
+
"type": "string",
|
|
8293
|
+
"description": "Exact value to publish."
|
|
8294
|
+
},
|
|
8295
|
+
"priority": {
|
|
8296
|
+
"type": "integer",
|
|
8297
|
+
"description": "MX priority. Present only for MX records."
|
|
8298
|
+
},
|
|
8299
|
+
"ttl": {
|
|
8300
|
+
"type": "integer",
|
|
8301
|
+
"description": "Suggested TTL in seconds when the API can provide one."
|
|
8302
|
+
},
|
|
8303
|
+
"required": {
|
|
8304
|
+
"type": "boolean",
|
|
8305
|
+
"const": true
|
|
8306
|
+
},
|
|
8307
|
+
"purpose": {
|
|
8308
|
+
"type": "string",
|
|
8309
|
+
"enum": [
|
|
8310
|
+
"inbound_mx",
|
|
8311
|
+
"ownership_verification",
|
|
8312
|
+
"spf",
|
|
8313
|
+
"dkim",
|
|
8314
|
+
"dmarc",
|
|
8315
|
+
"tls_reporting"
|
|
8316
|
+
]
|
|
8317
|
+
},
|
|
8318
|
+
"status": {
|
|
8319
|
+
"type": "string",
|
|
8320
|
+
"enum": [
|
|
8321
|
+
"pending",
|
|
8322
|
+
"found",
|
|
8323
|
+
"missing",
|
|
8324
|
+
"incorrect"
|
|
8325
|
+
]
|
|
8326
|
+
},
|
|
8327
|
+
"message": {
|
|
8328
|
+
"type": "string",
|
|
8329
|
+
"description": "Short explanation of why this record is needed."
|
|
8330
|
+
}
|
|
8331
|
+
},
|
|
8332
|
+
"required": [
|
|
8333
|
+
"type",
|
|
8334
|
+
"name",
|
|
8335
|
+
"fqdn",
|
|
8336
|
+
"value",
|
|
8337
|
+
"required",
|
|
8338
|
+
"purpose",
|
|
8339
|
+
"status"
|
|
8340
|
+
]
|
|
8341
|
+
}
|
|
8342
|
+
},
|
|
7795
8343
|
"error": {
|
|
7796
8344
|
"type": "string",
|
|
7797
8345
|
"description": "Human-readable verification failure reason"
|
|
@@ -11165,6 +11713,36 @@ const operationManifest = [
|
|
|
11165
11713
|
"pattern": "^[^\\x00-\\x1F\\x7F]+$"
|
|
11166
11714
|
}
|
|
11167
11715
|
},
|
|
11716
|
+
"attachments": {
|
|
11717
|
+
"type": "array",
|
|
11718
|
+
"maxItems": 100,
|
|
11719
|
+
"description": "Inline attachments. Send requests with attachments to https://api.primitive.dev/v1/send-mail. Combined raw decoded attachment bytes must be at most 31457280.",
|
|
11720
|
+
"items": {
|
|
11721
|
+
"type": "object",
|
|
11722
|
+
"additionalProperties": false,
|
|
11723
|
+
"properties": {
|
|
11724
|
+
"filename": {
|
|
11725
|
+
"type": "string",
|
|
11726
|
+
"minLength": 1,
|
|
11727
|
+
"maxLength": 255,
|
|
11728
|
+
"description": "Attachment filename. Control characters are rejected."
|
|
11729
|
+
},
|
|
11730
|
+
"content_type": {
|
|
11731
|
+
"type": "string",
|
|
11732
|
+
"minLength": 1,
|
|
11733
|
+
"maxLength": 255,
|
|
11734
|
+
"description": "Optional MIME content type. Control characters are rejected."
|
|
11735
|
+
},
|
|
11736
|
+
"content_base64": {
|
|
11737
|
+
"type": "string",
|
|
11738
|
+
"minLength": 1,
|
|
11739
|
+
"maxLength": 44040192,
|
|
11740
|
+
"description": "Base64-encoded attachment bytes."
|
|
11741
|
+
}
|
|
11742
|
+
},
|
|
11743
|
+
"required": ["filename", "content_base64"]
|
|
11744
|
+
}
|
|
11745
|
+
},
|
|
11168
11746
|
"wait": {
|
|
11169
11747
|
"type": "boolean",
|
|
11170
11748
|
"description": "When true, wait for the first downstream SMTP delivery outcome before returning."
|
|
@@ -12501,6 +13079,10 @@ function operationOutputPayload(envelope, includeEnvelope) {
|
|
|
12501
13079
|
return includeEnvelope ? envelope ?? null : envelope?.data ?? null;
|
|
12502
13080
|
}
|
|
12503
13081
|
const OPERATION_HINTS = {
|
|
13082
|
+
addDomain: "Tip: after this returns a domain id, run `primitive domains zone-file --id <domain-id> --output <domain>.zone` when the user wants an importable DNS zone file.",
|
|
13083
|
+
verifyDomain: "Tip: if DNS is still missing, run `primitive domains zone-file --id <domain-id> --output <domain>.zone` to give the user an importable DNS zone file.",
|
|
13084
|
+
downloadDomainZoneFile: "Tip: prefer `primitive domains zone-file --id <domain-id> --output <domain>.zone` for CLI-friendly file output.",
|
|
13085
|
+
sendEmail: "Tip: prefer `primitive send --to <address> --body <text> --attachment <file>` for file attachments. This raw command exists for callers passing JSON.",
|
|
12504
13086
|
createFunction: "Tip: prefer `primitive functions deploy --name <name> --file <bundle>` for file-input ergonomics. This raw command exists for callers passing JSON.",
|
|
12505
13087
|
updateFunction: "Tip: prefer `primitive functions redeploy --id <id> --file <bundle>` for file-input ergonomics. This raw command exists for callers passing JSON.",
|
|
12506
13088
|
createFunctionSecret: "Tip: prefer `primitive functions set-secret --id <id> --key <KEY> --value <value> [--redeploy]` for secret writes that also push the binding live. This raw command exists for callers passing JSON.",
|
|
@@ -12612,7 +13194,8 @@ const EMPTY_RESULT_HINTS = {
|
|
|
12612
13194
|
listEndpoints: "(no results) No webhook endpoints configured. Add one with `primitive endpoints create --url <your-url>`.",
|
|
12613
13195
|
listEmails: "(no results) No inbound emails received yet on this account. Send one to a verified domain to populate this list. For a compact view, prefer `primitive emails latest`.",
|
|
12614
13196
|
listDomains: "(no results) No domains on this account. Add one with `primitive domains add --domain <yourdomain.example>`.",
|
|
12615
|
-
listFilters: "(no results) No filter rules configured."
|
|
13197
|
+
listFilters: "(no results) No filter rules configured.",
|
|
13198
|
+
listFunctions: "(no results) No Functions configured yet. Start with `primitive functions templates`, then `primitive functions init --template <template>` and `primitive functions deploy --name <name> --file <bundle>`."
|
|
12616
13199
|
};
|
|
12617
13200
|
function canonicalizeCliReferences(description) {
|
|
12618
13201
|
return description.replaceAll("`primitive emails:latest`", "`primitive emails latest`").replaceAll("`primitive describe emails:get-email | jq '.responseSchema.properties'`", "`primitive describe emails:get | jq '.responseSchema.properties'`");
|
|
@@ -13379,6 +13962,144 @@ var DoctorCommand = class DoctorCommand extends Command {
|
|
|
13379
13962
|
}
|
|
13380
13963
|
};
|
|
13381
13964
|
//#endregion
|
|
13965
|
+
//#region src/oclif/commands/domains-zone-file.ts
|
|
13966
|
+
function zoneFileUrl(baseUrl, domainId, outboundOnly) {
|
|
13967
|
+
const url = new URL(`${baseUrl.replace(/\/$/, "")}/domains/${encodeURIComponent(domainId)}/zone-file`);
|
|
13968
|
+
if (outboundOnly) url.searchParams.set("outbound_only", "true");
|
|
13969
|
+
return url.toString();
|
|
13970
|
+
}
|
|
13971
|
+
function contentDispositionFilename(value) {
|
|
13972
|
+
if (!value) return null;
|
|
13973
|
+
const match = /filename\*=UTF-8''([^;]+)|filename="?([^";]+)"?/i.exec(value);
|
|
13974
|
+
const raw = match?.[1] ?? match?.[2];
|
|
13975
|
+
if (!raw) return null;
|
|
13976
|
+
try {
|
|
13977
|
+
return decodeURIComponent(raw);
|
|
13978
|
+
} catch {
|
|
13979
|
+
return raw;
|
|
13980
|
+
}
|
|
13981
|
+
}
|
|
13982
|
+
function findDomain(domains, domain) {
|
|
13983
|
+
const match = domains.find((entry) => entry.domain === domain);
|
|
13984
|
+
if (!match) throw new Errors.CLIError(`Domain ${domain} was not found.`, { exit: 1 });
|
|
13985
|
+
return match;
|
|
13986
|
+
}
|
|
13987
|
+
async function responseErrorPayload(response) {
|
|
13988
|
+
if ((response.headers.get("content-type")?.toLowerCase() ?? "").includes("application/json")) return response.json().catch(() => ({
|
|
13989
|
+
code: "http_error",
|
|
13990
|
+
message: `HTTP ${response.status} ${response.statusText}`.trim()
|
|
13991
|
+
}));
|
|
13992
|
+
return {
|
|
13993
|
+
code: "http_error",
|
|
13994
|
+
message: (await response.text().catch(() => "")).trim() || `HTTP ${response.status} ${response.statusText}`.trim()
|
|
13995
|
+
};
|
|
13996
|
+
}
|
|
13997
|
+
var DomainsZoneFileCommand = class DomainsZoneFileCommand extends Command {
|
|
13998
|
+
static description = `Download a BIND-format DNS zone file for a domain claim.
|
|
13999
|
+
|
|
14000
|
+
Use this when a DNS provider supports zone-file import and you want to publish all required records at once instead of copying each record manually. The file is generated by the Primitive API, matching the dashboard download flow.
|
|
14001
|
+
|
|
14002
|
+
Agents: after claiming a domain, tell users they can run \`primitive domains zone-file --id <domain-id> --output <domain>.zone\` to get an importable DNS zone file.`;
|
|
14003
|
+
static summary = "Download a DNS zone file for a domain";
|
|
14004
|
+
static examples = [
|
|
14005
|
+
"<%= config.bin %> domains zone-file --id <domain-id>",
|
|
14006
|
+
"<%= config.bin %> domains zone-file --id <domain-id> --output example.com.zone",
|
|
14007
|
+
"<%= config.bin %> domains zone-file --domain example.com --output example.com.zone",
|
|
14008
|
+
"<%= config.bin %> domains zone-file --id <domain-id> --outbound-only"
|
|
14009
|
+
];
|
|
14010
|
+
static flags = {
|
|
14011
|
+
"api-key": Flags.string({
|
|
14012
|
+
description: "Primitive API key override (defaults to PRIMITIVE_API_KEY or saved OAuth login credentials)",
|
|
14013
|
+
env: "PRIMITIVE_API_KEY"
|
|
14014
|
+
}),
|
|
14015
|
+
"api-base-url-1": Flags.string({
|
|
14016
|
+
description: "Override the primary API base URL. Internal testing only; not documented to customers.",
|
|
14017
|
+
env: "PRIMITIVE_API_BASE_URL_1",
|
|
14018
|
+
hidden: true
|
|
14019
|
+
}),
|
|
14020
|
+
"api-base-url-2": Flags.string({
|
|
14021
|
+
description: "Override the attachments-supporting send host base URL. Internal testing only; not documented to customers.",
|
|
14022
|
+
env: "PRIMITIVE_API_BASE_URL_2",
|
|
14023
|
+
hidden: true
|
|
14024
|
+
}),
|
|
14025
|
+
domain: Flags.string({ description: "Domain name to look up before downloading its zone file. Prefer --id when you have the domain id from `primitive domains add`." }),
|
|
14026
|
+
id: Flags.string({ description: "Domain id returned by `primitive domains add` or `primitive domains list`." }),
|
|
14027
|
+
output: Flags.string({
|
|
14028
|
+
char: "o",
|
|
14029
|
+
description: "Write the zone file to this path instead of stdout. Defaults to stdout."
|
|
14030
|
+
}),
|
|
14031
|
+
"outbound-only": Flags.boolean({ description: "Include only outbound DNS records. Verified domains default to outbound-only at the API; this flag is explicit for agents and scripts." }),
|
|
14032
|
+
time: Flags.boolean({ description: TIME_FLAG_DESCRIPTION })
|
|
14033
|
+
};
|
|
14034
|
+
async run() {
|
|
14035
|
+
const { flags } = await this.parse(DomainsZoneFileCommand);
|
|
14036
|
+
if (flags.id && flags.domain) throw new Errors.CLIError("Use only one of --id or --domain.", { exit: 1 });
|
|
14037
|
+
if (!flags.id && !flags.domain) throw new Errors.CLIError("Pass --id <domain-id> or --domain <domain>.", { exit: 1 });
|
|
14038
|
+
await runWithTiming(flags.time, async () => {
|
|
14039
|
+
const { apiClient, auth, baseUrlOverridden, requestConfig } = await createAuthenticatedCliApiClient({
|
|
14040
|
+
apiKey: flags["api-key"],
|
|
14041
|
+
apiBaseUrl1: flags["api-base-url-1"],
|
|
14042
|
+
apiBaseUrl2: flags["api-base-url-2"],
|
|
14043
|
+
configDir: this.config.configDir
|
|
14044
|
+
});
|
|
14045
|
+
let domainId = flags.id;
|
|
14046
|
+
if (!domainId && flags.domain) {
|
|
14047
|
+
const result = await listDomains({
|
|
14048
|
+
client: apiClient.client,
|
|
14049
|
+
responseStyle: "fields"
|
|
14050
|
+
});
|
|
14051
|
+
if (result.error) {
|
|
14052
|
+
const errorPayload = extractErrorPayload(result.error);
|
|
14053
|
+
writeErrorWithHints(errorPayload);
|
|
14054
|
+
surfaceUnauthorizedHint({
|
|
14055
|
+
auth,
|
|
14056
|
+
baseUrlOverridden,
|
|
14057
|
+
configDir: this.config.configDir,
|
|
14058
|
+
payload: errorPayload
|
|
14059
|
+
});
|
|
14060
|
+
process.exitCode = 1;
|
|
14061
|
+
return;
|
|
14062
|
+
}
|
|
14063
|
+
const envelope = result.data;
|
|
14064
|
+
domainId = findDomain(envelope?.data ?? [], flags.domain).id;
|
|
14065
|
+
}
|
|
14066
|
+
if (!domainId) throw new Errors.CLIError("Could not resolve a domain id.", { exit: 1 });
|
|
14067
|
+
let response;
|
|
14068
|
+
try {
|
|
14069
|
+
response = await fetch(zoneFileUrl(requestConfig.resolvedApiBaseUrl1, domainId, flags["outbound-only"]), { headers: {
|
|
14070
|
+
...requestConfig.headers ?? {},
|
|
14071
|
+
...auth.apiKey ? { authorization: `Bearer ${auth.apiKey}` } : {}
|
|
14072
|
+
} });
|
|
14073
|
+
} catch (error) {
|
|
14074
|
+
writeErrorWithHints(error);
|
|
14075
|
+
process.exitCode = 1;
|
|
14076
|
+
return;
|
|
14077
|
+
}
|
|
14078
|
+
if (!response.ok) {
|
|
14079
|
+
const errorPayload = extractErrorPayload(await responseErrorPayload(response));
|
|
14080
|
+
writeErrorWithHints(errorPayload);
|
|
14081
|
+
surfaceUnauthorizedHint({
|
|
14082
|
+
auth,
|
|
14083
|
+
baseUrlOverridden,
|
|
14084
|
+
configDir: this.config.configDir,
|
|
14085
|
+
payload: errorPayload
|
|
14086
|
+
});
|
|
14087
|
+
process.exitCode = 1;
|
|
14088
|
+
return;
|
|
14089
|
+
}
|
|
14090
|
+
const zoneFile = await response.text();
|
|
14091
|
+
const output = flags.output;
|
|
14092
|
+
if (output) {
|
|
14093
|
+
writeFileSync(output, zoneFile, "utf8");
|
|
14094
|
+
const filename = contentDispositionFilename(response.headers.get("content-disposition"));
|
|
14095
|
+
process.stderr.write(`Wrote ${filename ?? "zone file"} to ${output}\n`);
|
|
14096
|
+
return;
|
|
14097
|
+
}
|
|
14098
|
+
process.stdout.write(zoneFile);
|
|
14099
|
+
});
|
|
14100
|
+
}
|
|
14101
|
+
};
|
|
14102
|
+
//#endregion
|
|
13382
14103
|
//#region src/oclif/commands/emails-latest.ts
|
|
13383
14104
|
const DEFAULT_LIMIT = 10;
|
|
13384
14105
|
const MAX_LIMIT = 100;
|
|
@@ -16291,12 +17012,46 @@ var ReplyCommand = class ReplyCommand extends Command {
|
|
|
16291
17012
|
}
|
|
16292
17013
|
};
|
|
16293
17014
|
//#endregion
|
|
17015
|
+
//#region src/oclif/attachments.ts
|
|
17016
|
+
function readAttachmentBytes(path, readFile) {
|
|
17017
|
+
try {
|
|
17018
|
+
return Buffer.from(readFile(path));
|
|
17019
|
+
} catch (error) {
|
|
17020
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
17021
|
+
throw new Errors.CLIError(`Could not read --attachment ${path}: ${detail}`, { exit: 1 });
|
|
17022
|
+
}
|
|
17023
|
+
}
|
|
17024
|
+
function hasControlCharacter(value) {
|
|
17025
|
+
return Array.from(value).some((character) => {
|
|
17026
|
+
const code = character.charCodeAt(0);
|
|
17027
|
+
return code <= 31 || code >= 127 && code <= 159;
|
|
17028
|
+
});
|
|
17029
|
+
}
|
|
17030
|
+
function validateAttachmentFilename(path, filename) {
|
|
17031
|
+
if (!filename) throw new Errors.CLIError(`Could not derive an attachment filename from ${path}. Pass a file path.`, { exit: 1 });
|
|
17032
|
+
if (hasControlCharacter(filename)) throw new Errors.CLIError(`Attachment filename ${filename} contains control characters.`, { exit: 1 });
|
|
17033
|
+
}
|
|
17034
|
+
function readAttachmentFiles(paths, readFile = readFileSync) {
|
|
17035
|
+
if (!paths || paths.length === 0) return void 0;
|
|
17036
|
+
return paths.map((path) => {
|
|
17037
|
+
const filename = basename(path);
|
|
17038
|
+
validateAttachmentFilename(path, filename);
|
|
17039
|
+
const bytes = readAttachmentBytes(path, readFile);
|
|
17040
|
+
if (bytes.length === 0) throw new Errors.CLIError(`Attachment file ${path} is empty. Attachments must contain at least one byte.`, { exit: 1 });
|
|
17041
|
+
return {
|
|
17042
|
+
content_base64: bytes.toString("base64"),
|
|
17043
|
+
filename
|
|
17044
|
+
};
|
|
17045
|
+
});
|
|
17046
|
+
}
|
|
17047
|
+
//#endregion
|
|
16294
17048
|
//#region src/oclif/commands/send.ts
|
|
16295
17049
|
var SendCommand = class SendCommand extends Command {
|
|
16296
17050
|
static description = `Send an outbound email. Agent-grade shortcut for \`sending send\` with sensible defaults.
|
|
16297
17051
|
|
|
16298
17052
|
--from defaults to agent@<your-first-verified-outbound-domain> when omitted.
|
|
16299
17053
|
--subject defaults to the first line of the body when omitted.
|
|
17054
|
+
--attachment attaches a file; repeat it to attach multiple files.
|
|
16300
17055
|
|
|
16301
17056
|
For the full flag set (custom message-id threading on the wire,
|
|
16302
17057
|
references arrays, etc.), use \`primitive sending send\`.`;
|
|
@@ -16304,6 +17059,7 @@ var SendCommand = class SendCommand extends Command {
|
|
|
16304
17059
|
static examples = [
|
|
16305
17060
|
"<%= config.bin %> send --to alice@example.com --body 'Hi Alice!'",
|
|
16306
17061
|
"<%= config.bin %> send --to alice@example.com --body-file ./message.txt",
|
|
17062
|
+
"<%= config.bin %> send --to alice@example.com --body 'See attached.' --attachment ./report.pdf",
|
|
16307
17063
|
"<%= config.bin %> send --to alice@example.com --from support@yourcompany.com --subject 'Quick question' --body 'Are you free Thursday?'",
|
|
16308
17064
|
"<%= config.bin %> send --to alice@example.com --html '<p>Hello!</p>'",
|
|
16309
17065
|
"<%= config.bin %> send --to alice@example.com --body 'Confirmed' --wait",
|
|
@@ -16331,11 +17087,15 @@ var SendCommand = class SendCommand extends Command {
|
|
|
16331
17087
|
from: Flags.string({ description: "Sender address. Defaults to agent@<your-first-verified-outbound-domain>." }),
|
|
16332
17088
|
subject: Flags.string({ description: "Subject line. Defaults to the first line of --body / --html when omitted." }),
|
|
16333
17089
|
body: Flags.string({ description: "Plain-text message body. Either --body or --html (or both) is required." }),
|
|
16334
|
-
"body-file": Flags.string({ description: "Read the plain-text message body from a UTF-8 file. Mutually exclusive with --body and --body-stdin." }),
|
|
17090
|
+
"body-file": Flags.string({ description: "Read the plain-text message body from a UTF-8 file. This does not attach the file; use --attachment for file attachments. Mutually exclusive with --body and --body-stdin." }),
|
|
16335
17091
|
"body-stdin": Flags.boolean({ description: "Read the plain-text message body from stdin. Mutually exclusive with --body and --body-file. Stdin can only be consumed once." }),
|
|
16336
17092
|
html: Flags.string({ description: "HTML message body. Either --body or --html (or both) is required." }),
|
|
16337
17093
|
"html-file": Flags.string({ description: "Read the HTML message body from a UTF-8 file. Mutually exclusive with --html and --html-stdin." }),
|
|
16338
17094
|
"html-stdin": Flags.boolean({ description: "Read the HTML message body from stdin. Mutually exclusive with --html and --html-file. Stdin can only be consumed once." }),
|
|
17095
|
+
attachment: Flags.string({
|
|
17096
|
+
description: "Attach a file to the email. Repeatable. Sends file bytes as a MIME attachment; use --body-file only for message body text.",
|
|
17097
|
+
multiple: true
|
|
17098
|
+
}),
|
|
16339
17099
|
"in-reply-to": Flags.string({ description: "Message-Id of the parent email when threading a reply on the wire. For replying to an inbound message you received, prefer `primitive reply --id <inbound-id>`." }),
|
|
16340
17100
|
wait: Flags.boolean({ description: "Block until the receiving MTA returns an outcome. Without --wait, the call returns once Primitive has accepted the message for delivery." }),
|
|
16341
17101
|
"wait-timeout-ms": Flags.integer({ description: "Maximum time to wait when --wait is set. Defaults to 30000ms." }),
|
|
@@ -16352,6 +17112,7 @@ var SendCommand = class SendCommand extends Command {
|
|
|
16352
17112
|
htmlStdin: flags["html-stdin"]
|
|
16353
17113
|
});
|
|
16354
17114
|
if (bodies.kind === "error") throw new Errors.CLIError(bodies.message);
|
|
17115
|
+
const attachments = readAttachmentFiles(flags.attachment);
|
|
16355
17116
|
await runWithTiming(flags.time, async () => {
|
|
16356
17117
|
const { apiClient, auth, baseUrlOverridden } = await createAuthenticatedCliApiClient({
|
|
16357
17118
|
apiKey: flags["api-key"],
|
|
@@ -16373,6 +17134,7 @@ var SendCommand = class SendCommand extends Command {
|
|
|
16373
17134
|
subject,
|
|
16374
17135
|
...bodies.body !== void 0 ? { body_text: bodies.body } : {},
|
|
16375
17136
|
...bodies.html !== void 0 ? { body_html: bodies.html } : {},
|
|
17137
|
+
...attachments !== void 0 ? { attachments } : {},
|
|
16376
17138
|
...flags["in-reply-to"] !== void 0 ? { in_reply_to: flags["in-reply-to"] } : {},
|
|
16377
17139
|
...flags.wait !== void 0 ? { wait: flags.wait } : {},
|
|
16378
17140
|
...flags["wait-timeout-ms"] !== void 0 ? { wait_timeout_ms: flags["wait-timeout-ms"] } : {}
|
|
@@ -17283,36 +18045,88 @@ function renderFishCompletion(binName) {
|
|
|
17283
18045
|
//#endregion
|
|
17284
18046
|
//#region src/oclif/index.ts
|
|
17285
18047
|
var ListOperationsCommand = class extends Command {
|
|
17286
|
-
static description = "List all generated API operations as JSON. Useful for piping to `jq` to discover available commands, their request/response schemas, and per-field descriptions. For inspecting a single operation in detail, prefer `primitive describe <command>`.";
|
|
18048
|
+
static description = "List all generated API operations as JSON. Useful for piping to `jq` to discover available commands, their request/response schemas, and per-field descriptions. For inspecting a single operation in detail, prefer `primitive describe <command-or-operation-name>`.";
|
|
17287
18049
|
static summary = "List all generated API operations (JSON)";
|
|
17288
18050
|
async run() {
|
|
17289
18051
|
this.log(JSON.stringify(operationManifest, null, 2));
|
|
17290
18052
|
}
|
|
17291
18053
|
};
|
|
18054
|
+
function operationId(operation) {
|
|
18055
|
+
return `${operation.tagCommand}:${operation.command}`;
|
|
18056
|
+
}
|
|
18057
|
+
function normalizeLookupToken(value) {
|
|
18058
|
+
return value.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
18059
|
+
}
|
|
18060
|
+
function unique(values) {
|
|
18061
|
+
return [...new Set(values)];
|
|
18062
|
+
}
|
|
18063
|
+
function operationLookupTokens(operation) {
|
|
18064
|
+
return unique([
|
|
18065
|
+
operationId(operation),
|
|
18066
|
+
operation.command,
|
|
18067
|
+
operation.operationId,
|
|
18068
|
+
operation.sdkName,
|
|
18069
|
+
`${operation.tagCommand}:${operation.operationId}`,
|
|
18070
|
+
`${operation.tagCommand}:${operation.sdkName}`
|
|
18071
|
+
]);
|
|
18072
|
+
}
|
|
18073
|
+
function levenshteinDistance(left, right) {
|
|
18074
|
+
if (left === right) return 0;
|
|
18075
|
+
if (left.length === 0) return right.length;
|
|
18076
|
+
if (right.length === 0) return left.length;
|
|
18077
|
+
let previous = Array.from({ length: right.length + 1 }, (_, index) => index);
|
|
18078
|
+
for (let leftIndex = 0; leftIndex < left.length; leftIndex += 1) {
|
|
18079
|
+
const current = [leftIndex + 1];
|
|
18080
|
+
for (let rightIndex = 0; rightIndex < right.length; rightIndex += 1) {
|
|
18081
|
+
const substitutionCost = left[leftIndex] === right[rightIndex] ? 0 : 1;
|
|
18082
|
+
current[rightIndex + 1] = Math.min(current[rightIndex] + 1, previous[rightIndex + 1] + 1, previous[rightIndex] + substitutionCost);
|
|
18083
|
+
}
|
|
18084
|
+
previous = current;
|
|
18085
|
+
}
|
|
18086
|
+
return previous[right.length] ?? Number.POSITIVE_INFINITY;
|
|
18087
|
+
}
|
|
18088
|
+
function scoreLookupToken(query, token) {
|
|
18089
|
+
const normalizedQuery = normalizeLookupToken(query);
|
|
18090
|
+
const normalizedToken = normalizeLookupToken(token);
|
|
18091
|
+
if (!normalizedQuery || !normalizedToken) return 0;
|
|
18092
|
+
if (normalizedQuery === normalizedToken) return 100;
|
|
18093
|
+
if (normalizedToken.includes(normalizedQuery)) return Math.max(50, 90 - (normalizedToken.length - normalizedQuery.length));
|
|
18094
|
+
if (normalizedQuery.includes(normalizedToken)) return Math.max(45, 80 - (normalizedQuery.length - normalizedToken.length));
|
|
18095
|
+
const distance = levenshteinDistance(normalizedQuery, normalizedToken);
|
|
18096
|
+
const maxLength = Math.max(normalizedQuery.length, normalizedToken.length);
|
|
18097
|
+
return Math.round((1 - distance / maxLength) * 75);
|
|
18098
|
+
}
|
|
18099
|
+
function scoreOperation(query, operation) {
|
|
18100
|
+
return Math.max(...operationLookupTokens(operation).map((token) => scoreLookupToken(query, token)));
|
|
18101
|
+
}
|
|
17292
18102
|
function lookupOperation(id) {
|
|
17293
18103
|
const trimmed = resolveOperationAlias(id.trim());
|
|
17294
|
-
const
|
|
17295
|
-
const tag = sep === -1 ? "" : trimmed.slice(0, sep);
|
|
17296
|
-
const cmd = sep === -1 ? trimmed : trimmed.slice(sep + 1);
|
|
17297
|
-
const match = operationManifest.find((op) => op.command === cmd && op.tagCommand === tag) ?? null;
|
|
18104
|
+
const match = operationManifest.find((op) => operationLookupTokens(op).some((token) => token === trimmed || normalizeLookupToken(token) === normalizeLookupToken(trimmed))) ?? null;
|
|
17298
18105
|
if (match) return {
|
|
17299
18106
|
match,
|
|
17300
18107
|
candidates: []
|
|
17301
18108
|
};
|
|
17302
18109
|
return {
|
|
17303
18110
|
match: null,
|
|
17304
|
-
candidates: operationManifest.
|
|
18111
|
+
candidates: operationManifest.map((op) => ({
|
|
18112
|
+
id: operationId(op),
|
|
18113
|
+
score: scoreOperation(trimmed, op)
|
|
18114
|
+
})).filter(({ score }) => score >= 45).sort((left, right) => right.score - left.score || left.id.localeCompare(right.id)).slice(0, 5).map(({ id }) => id)
|
|
17305
18115
|
};
|
|
17306
18116
|
}
|
|
17307
18117
|
var DescribeCommand = class DescribeCommand extends Command {
|
|
17308
18118
|
static args = { command: Args.string({
|
|
17309
|
-
description: "Command id to describe, e.g. `emails:list
|
|
18119
|
+
description: "Command id, alias, or SDK operation name to describe, e.g. `emails:list`, `emails:get-email`, or `getEmail`. Run `primitive list-operations | jq -r '.[] | \"\\(.tagCommand):\\(.command) \\(.operationId)\"'` to enumerate generated operation ids.",
|
|
17310
18120
|
required: true
|
|
17311
18121
|
}) };
|
|
17312
18122
|
static description = `Print the full operation manifest entry for a single API command, including the path, request schema, response schema, and per-field descriptions sourced from the OpenAPI spec.
|
|
17313
18123
|
|
|
17314
18124
|
The manifest entry's \`responseSchema\` carries the inlined JSON Schema for the operation's 200/201 \`data\` envelope contents (\`$ref\`s resolved). Use it to look up what specific response fields mean. Examples:
|
|
17315
18125
|
|
|
18126
|
+
# Domain setup records returned by add/verify
|
|
18127
|
+
primitive describe domains:add
|
|
18128
|
+
primitive describe addDomain
|
|
18129
|
+
|
|
17316
18130
|
# Which of EmailDetail's sender-shaped fields is canonical?
|
|
17317
18131
|
primitive describe emails:get | jq '.responseSchema.properties | keys'
|
|
17318
18132
|
primitive describe emails:get | jq -r '.responseSchema.properties.from_email.description'
|
|
@@ -17322,7 +18136,12 @@ var DescribeCommand = class DescribeCommand extends Command {
|
|
|
17322
18136
|
|
|
17323
18137
|
\`requestSchema\` is the same shape for the request body when one exists. For a single field across many operations at once, use \`primitive list-operations | jq\` instead.`;
|
|
17324
18138
|
static summary = "Describe a single API operation in detail";
|
|
17325
|
-
static examples = [
|
|
18139
|
+
static examples = [
|
|
18140
|
+
"<%= config.bin %> describe addDomain",
|
|
18141
|
+
"<%= config.bin %> describe domains:add",
|
|
18142
|
+
"<%= config.bin %> describe emails:get",
|
|
18143
|
+
"<%= config.bin %> describe sent:get"
|
|
18144
|
+
];
|
|
17326
18145
|
async run() {
|
|
17327
18146
|
const { args } = await this.parse(DescribeCommand);
|
|
17328
18147
|
const { match, candidates } = lookupOperation(args.command);
|
|
@@ -17355,9 +18174,6 @@ var CompletionCommand = class CompletionCommand extends Command {
|
|
|
17355
18174
|
await this.config.runCommand("autocomplete", [args.shell]);
|
|
17356
18175
|
}
|
|
17357
18176
|
};
|
|
17358
|
-
function commandId(operation) {
|
|
17359
|
-
return `${operation.tagCommand}:${operation.command}`;
|
|
17360
|
-
}
|
|
17361
18177
|
const CANONICAL_OPERATION_ALIASES = {
|
|
17362
18178
|
"account:show": "account:get-account",
|
|
17363
18179
|
"account:storage": "account:get-storage-stats",
|
|
@@ -17402,14 +18218,15 @@ const CANONICAL_OPERATION_ALIASES = {
|
|
|
17402
18218
|
};
|
|
17403
18219
|
const DESCRIBE_OPERATION_ALIASES = {
|
|
17404
18220
|
...CANONICAL_OPERATION_ALIASES,
|
|
18221
|
+
"domains:zone-file": "domains:download-domain-zone-file",
|
|
17405
18222
|
"functions:logs": "functions:list-function-logs",
|
|
17406
18223
|
reply: "sending:reply-to-email"
|
|
17407
18224
|
};
|
|
17408
18225
|
function resolveOperationAlias(id) {
|
|
17409
18226
|
return DESCRIBE_OPERATION_ALIASES[id] ?? id;
|
|
17410
18227
|
}
|
|
17411
|
-
const OVERRIDDEN_OPERATION_IDS = new Set(["functions:test-function"]);
|
|
17412
|
-
const generatedCommands = Object.fromEntries(operationManifest.filter((operation) => !OVERRIDDEN_OPERATION_IDS.has(
|
|
18228
|
+
const OVERRIDDEN_OPERATION_IDS = new Set(["domains:download-domain-zone-file", "functions:test-function"]);
|
|
18229
|
+
const generatedCommands = Object.fromEntries(operationManifest.filter((operation) => !OVERRIDDEN_OPERATION_IDS.has(operationId(operation))).map((operation) => [operationId(operation), createOperationCommand(operation)]));
|
|
17413
18230
|
const COMMANDS = {
|
|
17414
18231
|
completion: CompletionCommand,
|
|
17415
18232
|
"list-operations": ListOperationsCommand,
|
|
@@ -17438,6 +18255,8 @@ const COMMANDS = {
|
|
|
17438
18255
|
"emails:latest": EmailsLatestCommand,
|
|
17439
18256
|
"emails:watch": EmailsWatchCommand,
|
|
17440
18257
|
"emails:wait": EmailsWaitCommand,
|
|
18258
|
+
"domains:zone-file": DomainsZoneFileCommand,
|
|
18259
|
+
"domains:download-domain-zone-file": DomainsZoneFileCommand,
|
|
17441
18260
|
"functions:init": FunctionsInitCommand,
|
|
17442
18261
|
"functions:templates": FunctionsTemplatesCommand,
|
|
17443
18262
|
"functions:deploy": FunctionsDeployCommand,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@primitivedotdev/cli",
|
|
3
|
-
"version": "0.31.
|
|
3
|
+
"version": "0.31.4",
|
|
4
4
|
"description": "Official Primitive CLI: deploy Primitive Functions, send and inspect mail, manage endpoints, all from the terminal. Wraps the @primitivedotdev/sdk runtime client with one-shot commands.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"description": "Agent signup and authentication API operations"
|
|
39
39
|
},
|
|
40
40
|
"domains": {
|
|
41
|
-
"description": "Claim, verify,
|
|
41
|
+
"description": "Claim, verify, manage email domains, and download DNS zone files"
|
|
42
42
|
},
|
|
43
43
|
"emails": {
|
|
44
44
|
"description": "List, inspect, and wait for received emails. Prefer task aliases like `primitive emails list`, `primitive emails get`, `primitive emails latest`, `primitive emails wait`, and `primitive emails watch`; generated API names remain available for compatibility."
|