@stacksjs/dns 0.64.6 → 0.65.0
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/index.js +15 -15
- package/dist/index.js.map +249 -243
- package/package.json +15 -21
- package/src/drivers/aws.ts +70 -44
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stacksjs/dns",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.65.0",
|
|
5
5
|
"description": "Easily manage your DNS.",
|
|
6
6
|
"author": "Chris Breuer",
|
|
7
|
+
"contributors": ["Chris Breuer <chris@stacksjs.org>"],
|
|
7
8
|
"license": "MIT",
|
|
8
9
|
"funding": "https://github.com/sponsors/chrisbbreuer",
|
|
9
10
|
"homepage": "https://github.com/stacksjs/stacks/tree/main/storage/framework/core/dns#readme",
|
|
@@ -37,31 +38,24 @@
|
|
|
37
38
|
"import": "./dist/*"
|
|
38
39
|
}
|
|
39
40
|
},
|
|
40
|
-
"
|
|
41
|
-
"Chris Breuer <chris@stacksjs.org>"
|
|
42
|
-
],
|
|
43
|
-
"files": [
|
|
44
|
-
"README.md",
|
|
45
|
-
"dist",
|
|
46
|
-
"src"
|
|
47
|
-
],
|
|
41
|
+
"files": ["README.md", "dist", "src"],
|
|
48
42
|
"scripts": {
|
|
49
|
-
"build": "bun
|
|
50
|
-
"typecheck": "bun
|
|
43
|
+
"build": "bun build.ts",
|
|
44
|
+
"typecheck": "bun tsc --noEmit",
|
|
51
45
|
"prepublishOnly": "bun run build"
|
|
52
46
|
},
|
|
53
47
|
"dependencies": {
|
|
54
|
-
"@aws-sdk/client-route-53": "^3.
|
|
55
|
-
"@stacksjs/actions": "
|
|
56
|
-
"@stacksjs/error-handling": "
|
|
57
|
-
"@stacksjs/path": "
|
|
58
|
-
"@stacksjs/storage": "
|
|
59
|
-
"@stacksjs/strings": "
|
|
60
|
-
"@stacksjs/whois": "
|
|
61
|
-
"aws-cdk-lib": "^2.
|
|
48
|
+
"@aws-sdk/client-route-53": "^3.668.0",
|
|
49
|
+
"@stacksjs/actions": "0.64.6",
|
|
50
|
+
"@stacksjs/error-handling": "0.64.6",
|
|
51
|
+
"@stacksjs/path": "0.64.6",
|
|
52
|
+
"@stacksjs/storage": "0.64.6",
|
|
53
|
+
"@stacksjs/strings": "0.64.6",
|
|
54
|
+
"@stacksjs/whois": "0.64.6",
|
|
55
|
+
"aws-cdk-lib": "^2.161.1"
|
|
62
56
|
},
|
|
63
57
|
"devDependencies": {
|
|
64
|
-
"@stacksjs/development": "
|
|
65
|
-
"aws-cdk-lib": "^2.
|
|
58
|
+
"@stacksjs/development": "0.64.6",
|
|
59
|
+
"aws-cdk-lib": "^2.161.1"
|
|
66
60
|
}
|
|
67
61
|
}
|
package/src/drivers/aws.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import type { CreateHostedZoneCommandOutput, HostedZone } from '@aws-sdk/client-route-53'
|
|
2
|
+
import type { Result } from '@stacksjs/error-handling'
|
|
3
|
+
import type { CommandError, DeployOptions, Subprocess } from '@stacksjs/types'
|
|
1
4
|
import { Route53 } from '@aws-sdk/client-route-53'
|
|
2
5
|
import { Route53Domains } from '@aws-sdk/client-route-53-domains'
|
|
3
6
|
import { runAction } from '@stacksjs/actions'
|
|
@@ -7,25 +10,27 @@ import { err, handleError, ok } from '@stacksjs/error-handling'
|
|
|
7
10
|
import { log } from '@stacksjs/logging'
|
|
8
11
|
import { path as p } from '@stacksjs/path'
|
|
9
12
|
import { fs } from '@stacksjs/storage'
|
|
10
|
-
import type { DeployOptions } from '@stacksjs/types'
|
|
11
13
|
|
|
12
|
-
export async function deleteHostedZone(domainName: string) {
|
|
14
|
+
export async function deleteHostedZone(domainName: string): Promise<Result<string, Error>> {
|
|
13
15
|
const route53 = new Route53()
|
|
14
16
|
|
|
15
17
|
// First, we need to get the Hosted Zone ID using the domain name
|
|
16
18
|
const hostedZones = await route53.listHostedZonesByName({
|
|
17
19
|
DNSName: domainName,
|
|
18
20
|
})
|
|
19
|
-
if (!hostedZones || !hostedZones.HostedZones)
|
|
21
|
+
if (!hostedZones || !hostedZones.HostedZones)
|
|
22
|
+
return err(handleError(`No hosted zones found for domain: ${domainName}`))
|
|
20
23
|
|
|
21
|
-
const hostedZone = hostedZones.HostedZones.find(
|
|
22
|
-
if (!hostedZone)
|
|
24
|
+
const hostedZone = hostedZones.HostedZones.find(zone => zone.Name === `${domainName}.`)
|
|
25
|
+
if (!hostedZone)
|
|
26
|
+
return err(handleError(`Hosted Zone not found for domain: ${domainName}`))
|
|
23
27
|
|
|
24
28
|
// Delete all record sets
|
|
25
29
|
const recordSets = await route53.listResourceRecordSets({
|
|
26
30
|
HostedZoneId: hostedZone.Id,
|
|
27
31
|
})
|
|
28
|
-
if (!recordSets || !recordSets.ResourceRecordSets)
|
|
32
|
+
if (!recordSets || !recordSets.ResourceRecordSets)
|
|
33
|
+
return err(handleError(`No DNS records found for domain: ${domainName}`))
|
|
29
34
|
|
|
30
35
|
for (const recordSet of recordSets.ResourceRecordSets) {
|
|
31
36
|
if (recordSet.Type !== 'NS' && recordSet.Type !== 'SOA') {
|
|
@@ -53,23 +58,26 @@ export async function deleteHostedZone(domainName: string) {
|
|
|
53
58
|
|
|
54
59
|
// sometimes it’s useful to delete all records but keep the hosted zone
|
|
55
60
|
// for example, if you want to keep the nameservers
|
|
56
|
-
export async function deleteHostedZoneRecords(domainName: string) {
|
|
61
|
+
export async function deleteHostedZoneRecords(domainName: string): Promise<Result<string, Error>> {
|
|
57
62
|
const route53 = new Route53()
|
|
58
63
|
|
|
59
64
|
// First, we need to get the Hosted Zone ID using the domain name
|
|
60
65
|
const hostedZones = await route53.listHostedZonesByName({
|
|
61
66
|
DNSName: domainName,
|
|
62
67
|
})
|
|
63
|
-
if (!hostedZones || !hostedZones.HostedZones)
|
|
68
|
+
if (!hostedZones || !hostedZones.HostedZones)
|
|
69
|
+
return err(handleError(`No hosted zones found for domain: ${domainName}`))
|
|
64
70
|
|
|
65
|
-
const hostedZone = hostedZones.HostedZones.find(
|
|
66
|
-
if (!hostedZone)
|
|
71
|
+
const hostedZone = hostedZones.HostedZones.find(zone => zone.Name === `${domainName}.`)
|
|
72
|
+
if (!hostedZone)
|
|
73
|
+
return err(handleError(`Hosted Zone not found for domain: ${domainName}`))
|
|
67
74
|
|
|
68
75
|
// Delete all record sets
|
|
69
76
|
const recordSets = await route53.listResourceRecordSets({
|
|
70
77
|
HostedZoneId: hostedZone.Id,
|
|
71
78
|
})
|
|
72
|
-
if (!recordSets || !recordSets.ResourceRecordSets)
|
|
79
|
+
if (!recordSets || !recordSets.ResourceRecordSets)
|
|
80
|
+
return err(handleError(`No DNS records found for domain: ${domainName}`))
|
|
73
81
|
|
|
74
82
|
for (const recordSet of recordSets.ResourceRecordSets) {
|
|
75
83
|
if (recordSet.Type !== 'NS' && recordSet.Type !== 'SOA') {
|
|
@@ -92,17 +100,20 @@ export async function deleteHostedZoneRecords(domainName: string) {
|
|
|
92
100
|
return ok('success')
|
|
93
101
|
}
|
|
94
102
|
|
|
95
|
-
export async function createHostedZone(
|
|
103
|
+
export async function createHostedZone(
|
|
104
|
+
domainName: string,
|
|
105
|
+
): Promise<Result<HostedZone | CreateHostedZoneCommandOutput | string | null, Error>> {
|
|
96
106
|
const route53 = new Route53()
|
|
97
107
|
|
|
98
108
|
// Check if the hosted zone already exists
|
|
99
109
|
const existingHostedZones = await route53.listHostedZonesByName({
|
|
100
110
|
DNSName: domainName,
|
|
101
111
|
})
|
|
102
|
-
const existingHostedZone = existingHostedZones.HostedZones?.find(
|
|
112
|
+
const existingHostedZone = existingHostedZones.HostedZones?.find(zone => zone.Name === `${domainName}.`)
|
|
103
113
|
|
|
104
114
|
// if the hosted zone already exists, then we want to
|
|
105
|
-
if (existingHostedZone)
|
|
115
|
+
if (existingHostedZone)
|
|
116
|
+
return ok(existingHostedZone)
|
|
106
117
|
|
|
107
118
|
// Create the hosted zone
|
|
108
119
|
const createHostedZoneOutput = await route53.createHostedZone({
|
|
@@ -110,51 +121,57 @@ export async function createHostedZone(domainName: string) {
|
|
|
110
121
|
CallerReference: `${Date.now()}`,
|
|
111
122
|
})
|
|
112
123
|
|
|
113
|
-
if (!createHostedZoneOutput.HostedZone)
|
|
124
|
+
if (!createHostedZoneOutput.HostedZone)
|
|
125
|
+
return err(handleError('Failed to create hosted zone'))
|
|
114
126
|
|
|
115
127
|
return ok(createHostedZoneOutput)
|
|
116
128
|
}
|
|
117
129
|
|
|
118
|
-
export function writeNameserversToConfig(nameservers: string[]) {
|
|
130
|
+
export function writeNameserversToConfig(nameservers: string[]): void {
|
|
119
131
|
try {
|
|
120
132
|
const path = p.projectConfigPath('dns.ts')
|
|
121
133
|
const fileContent = fs.readFileSync(path, 'utf-8')
|
|
122
134
|
const modifiedContent = fileContent.replace(
|
|
123
135
|
/nameservers: \[.*?\]/s,
|
|
124
|
-
`nameservers: [${nameservers.map(
|
|
136
|
+
`nameservers: [${nameservers.map(ns => `'${ns}'`).join(', ')}]`,
|
|
125
137
|
)
|
|
126
138
|
fs.writeFileSync(path, modifiedContent, 'utf-8')
|
|
127
139
|
|
|
128
140
|
log.info('Nameservers have been set.')
|
|
129
|
-
}
|
|
141
|
+
}
|
|
142
|
+
catch (err) {
|
|
130
143
|
console.error('Error updating nameservers:', err)
|
|
131
144
|
}
|
|
132
145
|
}
|
|
133
146
|
|
|
134
|
-
export async function findHostedZone(domain: string) {
|
|
147
|
+
export async function findHostedZone(domain: string): Promise<Result<string | null | undefined, Error>> {
|
|
135
148
|
try {
|
|
136
149
|
const route53 = new Route53()
|
|
137
150
|
const { HostedZones } = await route53.listHostedZonesByName({
|
|
138
151
|
DNSName: domain,
|
|
139
152
|
})
|
|
140
153
|
|
|
141
|
-
if (!HostedZones)
|
|
154
|
+
if (!HostedZones)
|
|
155
|
+
return err(handleError(`No hosted zones found for domain ${domain}`))
|
|
142
156
|
|
|
143
157
|
// The API returns hosted zones sorted by name in ASCII order,
|
|
144
158
|
// so the desired hosted zone (if it exists) should be the first one in the list
|
|
145
159
|
const hostedZone = HostedZones[0]
|
|
146
160
|
|
|
147
|
-
if (hostedZone && hostedZone.Name === `${domain}.`)
|
|
161
|
+
if (hostedZone && hostedZone.Name === `${domain}.`)
|
|
162
|
+
return ok(hostedZone.Id)
|
|
148
163
|
|
|
149
164
|
return ok(null)
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
return handleError(`Failed to find hosted zone for domain ${domain}
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
return err(handleError(`Failed to find hosted zone for domain ${domain}`, error))
|
|
153
168
|
}
|
|
154
169
|
}
|
|
155
170
|
|
|
156
|
-
export async function getNameservers(domainName?: string) {
|
|
157
|
-
|
|
171
|
+
export async function getNameservers(domainName?: string): Promise<string[] | undefined> {
|
|
172
|
+
log.debug('Getting nameservers for domain:', domainName)
|
|
173
|
+
if (!domainName)
|
|
174
|
+
return []
|
|
158
175
|
|
|
159
176
|
try {
|
|
160
177
|
const route53Domains = new Route53Domains()
|
|
@@ -162,22 +179,25 @@ export async function getNameservers(domainName?: string) {
|
|
|
162
179
|
DomainName: domainName,
|
|
163
180
|
})
|
|
164
181
|
|
|
165
|
-
return domainDetail?.Nameservers?.map(
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
handleError('Error getting domain detail')
|
|
182
|
+
return domainDetail?.Nameservers?.map(ns => ns.Name as string) || []
|
|
183
|
+
}
|
|
184
|
+
catch (error) {
|
|
185
|
+
handleError('Error getting domain detail', error)
|
|
169
186
|
}
|
|
170
187
|
}
|
|
171
188
|
|
|
172
|
-
export async function updateNameservers(
|
|
173
|
-
|
|
189
|
+
export async function updateNameservers(
|
|
190
|
+
hostedZoneNameservers: string[],
|
|
191
|
+
domainName?: string,
|
|
192
|
+
): Promise<boolean | undefined> {
|
|
193
|
+
if (!domainName)
|
|
194
|
+
domainName = config.app.url
|
|
174
195
|
|
|
175
196
|
const domainNameservers = await getNameservers(domainName)
|
|
176
|
-
|
|
177
197
|
if (
|
|
178
|
-
domainNameservers
|
|
179
|
-
hostedZoneNameservers
|
|
180
|
-
JSON.stringify(domainNameservers.sort()) !== JSON.stringify(hostedZoneNameservers.sort())
|
|
198
|
+
domainNameservers
|
|
199
|
+
&& hostedZoneNameservers
|
|
200
|
+
&& JSON.stringify(domainNameservers.sort()) !== JSON.stringify(hostedZoneNameservers.sort())
|
|
181
201
|
) {
|
|
182
202
|
log.info('Updating your domain nameservers to match the ones in your hosted zone...')
|
|
183
203
|
log.debug('Hosted zone nameservers:', hostedZoneNameservers)
|
|
@@ -186,7 +206,7 @@ export async function updateNameservers(hostedZoneNameservers: string[], domainN
|
|
|
186
206
|
|
|
187
207
|
await route53Domains.updateDomainNameservers({
|
|
188
208
|
DomainName: domainName,
|
|
189
|
-
Nameservers: hostedZoneNameservers.map(
|
|
209
|
+
Nameservers: hostedZoneNameservers.map(ns => ({ Name: ns })),
|
|
190
210
|
})
|
|
191
211
|
|
|
192
212
|
writeNameserversToConfig(hostedZoneNameservers)
|
|
@@ -199,21 +219,27 @@ export async function updateNameservers(hostedZoneNameservers: string[], domainN
|
|
|
199
219
|
}
|
|
200
220
|
|
|
201
221
|
// please note, this function also updates the user's nameservers if they are out of date
|
|
202
|
-
export async function hasUserDomainBeenAddedToCloud(domainName?: string) {
|
|
203
|
-
if
|
|
204
|
-
|
|
205
|
-
|
|
222
|
+
export async function hasUserDomainBeenAddedToCloud(domainName?: string): Promise<boolean> {
|
|
223
|
+
log.debug('Checking if domain has been added to cloud...')
|
|
224
|
+
if (!domainName)
|
|
225
|
+
domainName = config.app.url
|
|
226
|
+
log.debug('domainName:', domainName)
|
|
206
227
|
|
|
207
228
|
// check if the hosted zone already exists
|
|
229
|
+
const route53 = new Route53()
|
|
208
230
|
const existingHostedZones = await route53.listHostedZonesByName({
|
|
209
231
|
DNSName: domainName,
|
|
210
232
|
})
|
|
233
|
+
log.debug('Existing hosted zones:', existingHostedZones)
|
|
211
234
|
|
|
212
|
-
if (!existingHostedZones || !existingHostedZones.HostedZones)
|
|
235
|
+
if (!existingHostedZones || !existingHostedZones.HostedZones)
|
|
236
|
+
return false
|
|
213
237
|
|
|
214
|
-
const existingHostedZone = existingHostedZones.HostedZones.find(
|
|
238
|
+
const existingHostedZone = existingHostedZones.HostedZones.find(zone => zone.Name === `${domainName}.`)
|
|
215
239
|
|
|
216
240
|
if (existingHostedZone) {
|
|
241
|
+
log.debug('Hosted zone found:', existingHostedZone)
|
|
242
|
+
|
|
217
243
|
const hostedZoneDetail = await route53.getHostedZone({
|
|
218
244
|
Id: existingHostedZone.Id,
|
|
219
245
|
})
|
|
@@ -229,6 +255,6 @@ export async function hasUserDomainBeenAddedToCloud(domainName?: string) {
|
|
|
229
255
|
return false
|
|
230
256
|
}
|
|
231
257
|
|
|
232
|
-
export async function addDomain(options: DeployOptions) {
|
|
258
|
+
export async function addDomain(options: DeployOptions): Promise<Result<Subprocess, CommandError>> {
|
|
233
259
|
return await runAction(Action.DomainsAdd, options)
|
|
234
260
|
}
|