@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/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "@stacksjs/dns",
3
3
  "type": "module",
4
- "version": "0.64.6",
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
- "contributors": [
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 --bun build.ts",
50
- "typecheck": "bun --bun tsc --noEmit",
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.637.0",
55
- "@stacksjs/actions": "latest",
56
- "@stacksjs/error-handling": "latest",
57
- "@stacksjs/path": "latest",
58
- "@stacksjs/storage": "latest",
59
- "@stacksjs/strings": "latest",
60
- "@stacksjs/whois": "latest",
61
- "aws-cdk-lib": "^2.154.1"
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": "latest",
65
- "aws-cdk-lib": "^2.154.1"
58
+ "@stacksjs/development": "0.64.6",
59
+ "aws-cdk-lib": "^2.161.1"
66
60
  }
67
61
  }
@@ -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) return err(`No hosted zones found for domain: ${domainName}`)
21
+ if (!hostedZones || !hostedZones.HostedZones)
22
+ return err(handleError(`No hosted zones found for domain: ${domainName}`))
20
23
 
21
- const hostedZone = hostedZones.HostedZones.find((zone) => zone.Name === `${domainName}.`)
22
- if (!hostedZone) return err(`Hosted Zone not found for domain: ${domainName}`)
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) return err(`No DNS records found for domain: ${domainName}`)
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) return err(`No hosted zones found for domain: ${domainName}`)
68
+ if (!hostedZones || !hostedZones.HostedZones)
69
+ return err(handleError(`No hosted zones found for domain: ${domainName}`))
64
70
 
65
- const hostedZone = hostedZones.HostedZones.find((zone) => zone.Name === `${domainName}.`)
66
- if (!hostedZone) return err(`Hosted Zone not found for domain: ${domainName}`)
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) return err(`No DNS records found for domain: ${domainName}`)
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(domainName: string) {
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((zone) => zone.Name === `${domainName}.`)
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) return ok(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) return err('Failed to create hosted zone')
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((ns) => `'${ns}'`).join(', ')}]`,
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
- } catch (err) {
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) return handleError(`No hosted zones found for domain ${domain}`)
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}.`) return ok(hostedZone.Id)
161
+ if (hostedZone && hostedZone.Name === `${domain}.`)
162
+ return ok(hostedZone.Id)
148
163
 
149
164
  return ok(null)
150
- } catch (error) {
151
- console.error(error)
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
- if (!domainName) return []
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((ns) => ns.Name as string) || []
166
- } catch (error) {
167
- console.error(error)
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(hostedZoneNameservers: string[], domainName?: string) {
173
- if (!domainName) domainName = config.app.url
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((ns) => ({ Name: ns })),
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 (!domainName) domainName = config.app.url
204
-
205
- const route53 = new Route53()
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) return false
235
+ if (!existingHostedZones || !existingHostedZones.HostedZones)
236
+ return false
213
237
 
214
- const existingHostedZone = existingHostedZones.HostedZones.find((zone) => zone.Name === `${domainName}.`)
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
  }