Skip to content

Commit 3bcc18f

Browse files
committed
chore: wip
chore: wip chore: wip
1 parent 325aa34 commit 3bcc18f

File tree

8 files changed

+131
-82
lines changed

8 files changed

+131
-82
lines changed
Lines changed: 50 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,81 +1,77 @@
11
import process from 'node:process'
22
import { handleError } from '@stacksjs/error-handling'
3-
import { log, parseOptions } from '@stacksjs/cli'
3+
import { dd, log, parseOptions } from '@stacksjs/cli'
44
import { ExitCode } from '@stacksjs/types'
5+
import { config } from '@stacksjs/config'
56
import type { PurchaseOptions } from '@stacksjs/cloud'
67
import { purchaseDomain } from '@stacksjs/cloud'
78

9+
const c = config.dns.contactInfo
10+
if (!c) {
11+
handleError('You must provide contact info in your config file.')
12+
process.exit(ExitCode.FatalError)
13+
}
14+
815
const defaultOptions: PurchaseOptions = {
916
domain: '',
1017
years: 1,
1118
privacy: true,
1219
autoRenew: true,
13-
registrantFirstName: config.dns.contactInfo.firstName,
14-
registrantLastName: config.dns.contactInfo?.lastName,
15-
registrantOrganizationName: config.dns.contactInfo?.organizationName,
16-
registrantAddressLine1: config.dns.contactInfo?.addressLine1,
17-
registrantAddressLine2: config.dns.contactInfo?.addressLine2,
18-
registrantCity: config.dns.contactInfo?.city,
19-
registrantState: config.dns.contactInfo?.state,
20-
registrantCountryCode: config.dns.contactInfo?.countryCode,
21-
registrantZip: config.dns.contactInfo?.zip,
22-
registrantPhoneNumber: config.dns.contactInfo?.phoneNumber,
23-
registrantEmail: config.dns.contactInfo?.email,
24-
admin: {
25-
firstName: config.dns.contactInfo?.admin?.firstName || config.dns.contactInfo?.firstName,
26-
lastName: config.dns.contactInfo?.admin?.lastName || config.dns.contactInfo?.lastName,
27-
organizationName: config.dns.contactInfo?.admin?.organizationName || config.dns.contactInfo?.organizationName,
28-
addressLine1: config.dns.contactInfo?.admin?.addressLine1 || config.dns.contactInfo?.addressLine1,
29-
addressLine2: config.dns.contactInfo?.admin?.addressLine2 || config.dns.contactInfo?.addressLine2,
30-
city: config.dns.contactInfo?.admin?.city || config.dns.contactInfo?.city,
31-
state: config.dns.contactInfo?.admin?.state || config.dns.contactInfo?.state,
32-
countryCode: config.dns.contactInfo?.admin?.countryCode || config.dns.contactInfo?.countryCode,
33-
zip: config.dns.contactInfo?.admin?.zip || config.dns.contactInfo?.zip,
34-
phoneNumber: config.dns.contactInfo?.admin?.phoneNumber || config.dns.contactInfo?.phoneNumber,
35-
email: config.dns.contactInfo?.admin?.email || config.dns.contactInfo?.email,
36-
},
37-
tech: {
38-
firstName: config.dns.contactInfo?.tech?.firstName || config.dns.contactInfo?.firstName,
39-
lastName: config.dns.contactInfo?.tech?.lastName || config.dns.contactInfo?.lastName,
40-
organizationName: config.dns.contactInfo?.tech?.organizationName || config.dns.contactInfo?.organizationName,
41-
addressLine1: config.dns.contactInfo?.tech?.addressLine1 || config.dns.contactInfo?.addressLine1,
42-
addressLine2: config.dns.contactInfo?.tech?.addressLine2 || config.dns.contactInfo?.addressLine2,
43-
city: config.dns.contactInfo?.tech?.city || config.dns.contactInfo?.city,
44-
state: config.dns.contactInfo?.tech?.state || config.dns.contactInfo?.state,
45-
countryCode: config.dns.contactInfo?.tech?.countryCode || config.dns.contactInfo?.countryCode,
46-
zip: config.dns.contactInfo?.tech?.zip || config.dns.contactInfo?.zip,
47-
phoneNumber: config.dns.contactInfo?.tech?.phoneNumber || config.dns.contactInfo?.phoneNumber,
48-
email: config.dns.contactInfo?.tech?.email || config.dns.contactInfo?.email,
49-
},
50-
privacyAdmin: config.dns.contactInfo?.privacyAdmin || config.dns.contactInfo?.privacy || true,
51-
privacyTech: config.dns.contactInfo?.privacyTech || config.dns.contactInfo?.privacy || true,
52-
privacyRegistrant: config.dns.contactInfo?.privacyRegistrant || config.dns.contactInfo?.privacy || true,
53-
contactType: 'person',
54-
},
55-
56-
]
57-
58-
// ... add the rest of the 38 properties here with their default values
20+
registrantFirstName: c.firstName as string,
21+
registrantLastName: c.lastName as string,
22+
registrantOrganization: c.organizationName as string,
23+
registrantAddressLine1: c.addressLine1 as string,
24+
registrantAddressLine2: c.addressLine2 as string,
25+
registrantCity: c.city as string,
26+
registrantState: c.state as string,
27+
registrantCountry: c.countryCode as string,
28+
registrantZip: c.zip as string,
29+
registrantPhone: c.phoneNumber as string,
30+
registrantEmail: c.email as string,
31+
adminFirstName: c.admin?.firstName || c.firstName as string,
32+
adminLastName: c.admin?.lastName || c.lastName as string,
33+
adminOrganization: c.admin?.organizationName || c.organizationName as string,
34+
adminAddressLine1: c.admin?.addressLine1 || c.addressLine1 as string,
35+
adminAddressLine2: c.admin?.addressLine2 || c.addressLine2 as string,
36+
adminCity: c.admin?.city || c.city as string,
37+
adminState: c.admin?.state || c.state as string,
38+
adminCountry: c.admin?.countryCode || c.countryCode as string,
39+
adminZip: c.admin?.zip || c.zip as string,
40+
adminPhone: c.admin?.phoneNumber as string || c.phoneNumber as string,
41+
adminEmail: c.admin?.email || c.email as string,
42+
techFirstName: c.tech?.firstName || c.firstName as string,
43+
techLastName: c.tech?.lastName || c.lastName as string,
44+
techOrganization: c.tech?.organizationName || c.organizationName as string,
45+
techAddressLine1: c.tech?.addressLine1 || c.addressLine1 as string,
46+
techAddressLine2: c.tech?.addressLine2 || c.addressLine2 as string,
47+
techCity: c.tech?.city || c.city as string,
48+
techState: c.tech?.state || c.state as string,
49+
techCountry: c.tech?.countryCode || c.countryCode as string,
50+
techZip: c.tech?.zip || c.zip as string,
51+
techPhone: c.tech?.phoneNumber as string || c.phoneNumber as string,
52+
techEmail: c.tech?.email || c.email as string,
53+
privacyAdmin: c.privacyAdmin || c.privacy || true,
54+
privacyTech: c.privacyTech || c.privacy || true,
55+
privacyRegistrant: c.privacyRegistrant || c.privacy || true,
56+
contactType: 'person',
57+
verbose: false,
5958
}
6059

6160
const options: PurchaseOptions = { ...defaultOptions, ...parseOptions() }
6261

63-
const options: PurchaseOptions = parseOptions()
64-
65-
log.info('options is', options)
66-
log.dd('domain is', options.domain)
67-
6862
if (!options.domain) {
6963
handleError('You must provide a domain name to purchase.')
7064
process.exit(ExitCode.FatalError)
7165
}
7266

73-
const result = purchaseDomain(options.domain, options)
67+
const result = await purchaseDomain(options.domain, options)
7468

7569
if (result.isErr()) {
70+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
7671
handleError(result.error)
7772
process.exit(ExitCode.FatalError)
7873
}
7974

80-
log.info(result.value)
75+
log.info('Domain purchased successfully.')
76+
8177
process.exit(ExitCode.Success)

.stacks/core/actions/src/helpers/utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ function parseOptions(options?: ActionOptions) {
1616
if (typeof value === 'boolean' && value) // if the value is `true`, just return the key
1717
return `--${key}`
1818

19-
return `--${key}=${value}`
19+
return `--${key}=${typeof value === 'string' && value.includes(' ') ? `"${value}"` : value}`
2020
})
2121

2222
// filter out undefined values and join the array

.stacks/core/buddy/src/commands/domains.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,19 @@ export function domains(buddy: CLI) {
7878
})
7979

8080
if (!confirm) {
81-
await outro(`Alrighty! Your domain ${domain} has been purchased & is added to your account.`, { startTime, useSeconds: true, type: 'success' })
81+
await outro(`Alrighty! ${italic(domain)} was added to your account.`, { startTime, useSeconds: true, type: 'success' })
82+
log.info(`Please note, you may need to validate your email address. Check your ${italic(options.registrantEmail as string)} inbox.`)
8283
process.exit(ExitCode.Success)
8384
}
8485

85-
let message = `Great! Your domain ${domain} has been purchased.`
86-
message += `\n\nAnd your APP_URL has been set to ${domain}.
87-
\nThis change has not been applied deployed yet.
88-
\nThe next time you run ${bgCyan(italic(bold(' buddy deploy ')))}, your app will deploy to ${domain}.`
86+
// set .env APP_URL to domain
87+
const { writeEnv } = await import('@stacksjs/env')
88+
writeEnv('APP_URL', domain)
89+
90+
let message = `Great! ${italic(domain)} was added to your account.`
91+
message += `\n\nAnd your APP_URL has been set to ${italic(domain)}.
92+
\nPlease note, this change has not been deployed yet.
93+
\nThe next time you run ${bgCyan(italic(bold(' buddy deploy ')))}, your app will deploy to ${italic(domain)}.`
8994

9095
await outro(message, { startTime, useSeconds: true, type: 'info' })
9196
process.exit(ExitCode.Success)

.stacks/core/cli/src/cli.ts

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22
import cac from 'cac'
33
import { version } from '../package.json'
44

5+
interface ParsedArgv {
6+
args: ReadonlyArray<string>
7+
options: {
8+
[k: string]: any
9+
}
10+
}
11+
512
interface CliOptions {
613
name?: string
714
version: string
@@ -16,13 +23,20 @@ export function cli(name?: string | CliOptions, options?: CliOptions) {
1623

1724
const cli = cac(name)
1825

19-
// cli.on('command:*', () => {
20-
// console.error('Invalid command: %s\nSee --help for a list of available commands.', cli.args.join(' '))
21-
// process.exit(1)
22-
// })
23-
2426
cli.help()
2527
cli.version(options?.version || version)
2628

2729
return cli
2830
}
31+
32+
export function command(name: string, description: string, options?: CliOptions) {
33+
return cli(options).command(name, description)
34+
}
35+
36+
export function parseArgs() {
37+
return cli().parse().args
38+
}
39+
40+
export function parseOptions(): ParsedArgv['options'] {
41+
return cli().parse().options
42+
}

.stacks/core/cli/src/exec.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,15 @@ import { type Result, err, handleError, ok } from '@stacksjs/error-handling'
2424
* ```
2525
*/
2626
export async function exec(command: string | string[], options?: CliOptions): Promise<Result<Subprocess, StacksError>> {
27-
const cmd: string[] = Array.isArray(command) ? command : command.split(' ')
27+
const cmd = Array.isArray(command) ? command : command.match(/(?:[^\s"]+|"[^"]*")+/g)
28+
29+
if (!cmd)
30+
return err(handleError(`Failed to parse command: ${cmd}`))
31+
32+
if (options?.verbose)
33+
// eslint-disable-next-line no-console
34+
console.log('exec', { command, cmd, options })
35+
2836
const proc = Bun.spawn(cmd, {
2937
...options,
3038
stdout: options?.stdout || 'inherit',

.stacks/core/cloud/src/cloud.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -333,13 +333,13 @@ export class StacksCloud extends Stack {
333333
encrypted: true,
334334
})
335335

336-
const role = new iam.Role(this, 'InstanceRole', {
336+
const role = new iam.Role(this, 'JumpBoxInstanceRole', {
337337
assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com'),
338338
})
339339

340340
role.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonSSMManagedInstanceCore'))
341341

342-
this.ec2Instance = new ec2.Instance(this, 'Instance', {
342+
this.ec2Instance = new ec2.Instance(this, 'JumpBoxInstance', {
343343
vpc: this.vpc,
344344
instanceType: ec2.InstanceType.of(ec2.InstanceClass.T2, ec2.InstanceSize.MICRO),
345345
machineImage: new ec2.AmazonLinuxImage(),
@@ -531,7 +531,7 @@ export class StacksCloud extends Stack {
531531
})
532532
}
533533

534-
new Output(this, 'CloudInstanceId', {
534+
new Output(this, 'JumpBoxInstanceId', {
535535
value: this.ec2Instance.instanceId,
536536
})
537537

.stacks/core/cloud/src/index.ts

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { log } from '@stacksjs/cli'
21
import { err, ok } from '@stacksjs/error-handling'
32
import { Route53Domains } from '@aws-sdk/client-route-53-domains'
43

@@ -58,40 +57,43 @@ export async function purchaseDomain(domain: string, options: PurchaseOptions) {
5857
AdminContact: {
5958
FirstName: options.adminFirstName,
6059
LastName: options.adminLastName,
61-
ContactType: 'PERSON',
60+
ContactType: options.contactType.toUpperCase() || 'PERSON',
6261
OrganizationName: options.adminOrganization,
63-
AddressLine1: options.adminAddress,
62+
AddressLine1: options.adminAddressLine1,
63+
AddressLine2: options.adminAddressLine2,
6464
City: options.adminCity,
6565
State: options.adminState,
6666
CountryCode: options.adminCountry,
67-
ZipCode: options.adminZip,
68-
PhoneNumber: options.adminPhone,
67+
ZipCode: options.adminZip.toString(),
68+
PhoneNumber: options.adminPhone.toString().includes('+') ? options.adminPhone.toString() : `+${options.adminPhone.toString()}`,
6969
Email: options.adminEmail,
7070
},
7171
RegistrantContact: {
7272
FirstName: options.registrantFirstName,
7373
LastName: options.registrantLastName,
74-
ContactType: 'PERSON',
74+
ContactType: options.contactType.toUpperCase() || 'PERSON',
7575
OrganizationName: options.registrantOrganization,
76-
AddressLine1: options.registrantAddress,
76+
AddressLine1: options.registrantAddressLine1,
77+
AddressLine2: options.registrantAddressLine2,
7778
City: options.registrantCity,
7879
State: options.registrantState,
7980
CountryCode: options.registrantCountry,
80-
ZipCode: options.registrantZip,
81-
PhoneNumber: options.registrantPhone,
81+
ZipCode: options.registrantZip.toString(),
82+
PhoneNumber: options.registrantPhone.toString().includes('+') ? options.registrantPhone.toString() : `+${options.registrantPhone.toString()}`,
8283
Email: options.registrantEmail,
8384
},
8485
TechContact: {
8586
FirstName: options.techFirstName,
8687
LastName: options.techLastName,
87-
ContactType: 'PERSON',
88+
ContactType: options.contactType.toUpperCase() || 'PERSON',
8889
OrganizationName: options.techOrganization,
89-
AddressLine1: options.techAddress,
90+
AddressLine1: options.techAddressLine1,
91+
AddressLine2: options.techAddressLine2,
9092
City: options.techCity,
9193
State: options.techState,
9294
CountryCode: options.techCountry,
93-
ZipCode: options.techZip,
94-
PhoneNumber: options.techPhone,
95+
ZipCode: options.techZip.toString(),
96+
PhoneNumber: options.techPhone.toString().includes('+') ? options.techPhone.toString() : `+${options.techPhone.toString()}`,
9597
Email: options.techEmail,
9698
},
9799
PrivacyProtectAdminContact: options.privacyAdmin || options.privacy || true,

.stacks/core/env/src/index.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import p from 'node:process'
2+
import { readFileSync, writeFileSync } from 'node:fs'
3+
import { projectPath } from '@stacksjs/path'
24
import { ValidationBoolean, ValidationEnum, ValidationNumber } from '@stacksjs/validation'
35
import type { Env } from '@stacksjs/env'
46
import type { EnvKey } from '~/storage/framework/stacks/env'
@@ -41,4 +43,26 @@ export function process() {
4143

4244
export const env: Env = new Proxy(process(), handler)
4345

46+
export function writeEnv(key: EnvKey, value: string, options?: { path: string }) {
47+
const envPath = options?.path || projectPath('.env')
48+
const env = readFileSync(envPath, 'utf-8')
49+
50+
// Split the file into lines
51+
const lines = env.split('\n')
52+
53+
// Find the line with the variable we want to update
54+
const index = lines.findIndex(line => line.startsWith(`${key}=`))
55+
56+
// If the variable exists, update it
57+
if (index !== -1)
58+
lines[index] = `${key}=${value}`
59+
60+
// Otherwise, add a new line
61+
else
62+
lines.push(`${key}=${value}`)
63+
64+
// Join the lines back into a string and write it to the .env file
65+
writeFileSync(envPath, lines.join('\n'))
66+
}
67+
4468
export * from './types'

0 commit comments

Comments
 (0)