Skip to content

Commit e108307

Browse files
committed
chore: wip
1 parent 02021ca commit e108307

File tree

17 files changed

+996
-112
lines changed

17 files changed

+996
-112
lines changed

app/Actions/BuddyAction.ts

Lines changed: 826 additions & 0 deletions
Large diffs are not rendered by default.

routes/api.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ route.get('/api/', () => 'hello world 2') // stacksjs.org/api/
55
route.get('/api/welcome', () => 'hello world 3') // stacksjs.org/api/welcome
66
route.get('/api/welcome/', () => 'hello world 4') // stacksjs.org/api/welcome/
77
route.get('/api/health', () => 'healthy')
8+
route.get('/api/buddy', 'BuddyAction')
89

910
// route.group({ prefix: '/users' }, () => {
1011
// route.before(async (params) => {
Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
1-
import { runCommand } from '@stacksjs/cli'
1+
import { parseOptions, runCommand } from '@stacksjs/cli'
22
import { path as p } from '@stacksjs/path'
33

4-
await runCommand('buddy changelog --quiet', {
4+
const options = parseOptions()
5+
const changelogCommand = options?.dryRun ? 'buddy changelog --quiet --dry-run' : 'buddy changelog --quiet'
6+
7+
await runCommand(changelogCommand, {
58
cwd: p.projectPath(),
69
})
710

11+
const bumpCommand = options?.dryRun ? 'bunx bumpp ./package.json ./core/**/package.json ./ide/vscode/package.json --no-push' : 'bunx bumpp ./package.json ./core/**/package.json ./ide/vscode/package.json --all'
12+
813
await runCommand(
9-
'bunx bumpp ./package.json ./core/**/package.json ./ide/vscode/package.json --all',
14+
bumpCommand,
1015
{ cwd: p.frameworkPath(), stdin: 'inherit' },
1116
)
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import { execSync, runCommand } from '@stacksjs/cli'
1+
import { execSync, parseOptions, runCommand } from '@stacksjs/cli'
22
import { projectPath } from '@stacksjs/path'
33

44
const fromRevision = await execSync('git describe --abbrev=0 --tags HEAD^')
5-
// console.log('fromRevision', fromRevision)
65
const toRevision = await execSync('git describe')
7-
// console.log('toRevision', toRevision)
6+
const options = parseOptions()
87

9-
await runCommand(`bunx changelogen --output CHANGELOG.md --from ${fromRevision} --to ${toRevision}`, {
8+
const command = options?.dryRun ? `bunx changelogen --no-output --from ${fromRevision} --to ${toRevision}` : `bunx changelogen --output CHANGELOG.md --from ${fromRevision} --to ${toRevision}`
9+
await runCommand(command, {
1010
cwd: projectPath(),
1111
})

storage/framework/core/actions/src/helpers/utils.ts

Lines changed: 19 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,10 @@
11
import * as storage from '@stacksjs/storage'
2-
import { italic, runCommand, runCommands, underline } from '@stacksjs/cli'
2+
import { buddyOptions, italic, parseOptions, runCommand, runCommands, underline } from '@stacksjs/cli'
33
import { log } from '@stacksjs/logging'
44
import * as p from '@stacksjs/path'
55
import type { ActionOptions, StacksError, Subprocess } from '@stacksjs/types'
6-
import { type Result, err, handleError } from '@stacksjs/error-handling'
7-
8-
function parseOptions(options?: ActionOptions) {
9-
if (!options)
10-
return ''
11-
12-
const parsedOptions = Object.entries(options).map(([key, value]) => {
13-
if (key.length === 1)
14-
return `-${key}=${value}`
15-
16-
if (typeof value === 'boolean' && value) // if the value is `true`, just return the key
17-
return `--${key}`
18-
19-
return `--${key}=${typeof value === 'string' && value.includes(' ') ? `"${value}"` : value}`
20-
})
21-
22-
// filter out undefined values and join the array
23-
return parsedOptions.filter(Boolean).join(' ').replace('----=', '')
24-
}
25-
26-
// export type ActionResult = CommandResult
6+
import type { Result } from '@stacksjs/error-handling'
7+
import { err, handleError } from '@stacksjs/error-handling'
278

289
/**
2910
* Run an Action the Stacks way.
@@ -36,21 +17,22 @@ export async function runAction(action: string, options?: ActionOptions): Promis
3617
if (!hasAction(action))
3718
return err(handleError(`The specified action "${action}" does not exist`))
3819

39-
const opts = parseOptions(options)
20+
const opts = buddyOptions()
4021
const path = p.relativeActionsPath(`${action}.ts`)
41-
const cmd = `bun --bun ${`${path} ${opts}`}`
42-
const o = {
22+
const cmd = `bun --bun ${path} ${opts}`
23+
const optionsWithCwd = {
4324
cwd: options?.cwd || p.projectPath(),
4425
...options,
4526
}
4627

4728
if (options?.verbose) {
29+
log.debug('Action command:', cmd)
4830
log.debug('Running cmd:', underline(italic(cmd)))
4931
log.debug('Running action:', underline(italic(`./actions/${action}.ts`)))
50-
log.debug('with action options of:', o)
32+
log.debug('With action options of:', optionsWithCwd)
5133
}
5234

53-
return await runCommand(cmd, o)
35+
return await runCommand(cmd, optionsWithCwd)
5436
}
5537

5638
/**
@@ -69,9 +51,17 @@ export async function runActions(actions: string[], options?: ActionOptions) {
6951
return err(`The specified action "${action}" does not exist`)
7052
}
7153

72-
const commands = actions.map(action => `bun --bun ${p.relativeActionsPath(`${action}.ts`)}`)
54+
// TODO: need to solve this error
55+
const opts = buddyOptions()
56+
57+
const o = {
58+
cwd: options?.cwd || p.projectPath(),
59+
...parseOptions(),
60+
}
61+
62+
const commands = actions.map(action => `bun --bun ${p.relativeActionsPath(`${action}.ts`)} ${opts}`)
7363

74-
return await runCommands(commands, options)
64+
return await runCommands(commands, o)
7565
}
7666

7767
export function hasAction(action: string) {
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
import { log, runCommands } from '@stacksjs/cli'
1+
import { log, parseOptions, runCommand } from '@stacksjs/cli'
22
import { projectPath } from '@stacksjs/path'
33
import { NpmScript } from '@stacksjs/enums'
44

55
log.info('Ensuring Code Style...')
6-
await runCommands([NpmScript.LintFix], { cwd: projectPath() })
6+
const options = parseOptions()
7+
await runCommand(NpmScript.LintFix, { cwd: projectPath() }, options)
78
log.success('Linted')

storage/framework/core/buddy/src/commands/changelog.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,15 @@ export function changelog(buddy: CLI) {
99
const descriptions = {
1010
changelog: 'Create a CHANGELOG.md file',
1111
quiet: 'Minimal output',
12+
dryRun: 'Do not write the file, just output the changes',
1213
project: 'Target a specific project',
1314
verbose: 'Enable verbose output',
1415
}
1516

1617
buddy
1718
.command('changelog', descriptions.changelog)
1819
.option('--quiet', descriptions.quiet, { default: false })
20+
.option('-d, --dry-run', descriptions.dryRun, { default: false })
1921
.option('-p, --project', descriptions.project, { default: false })
2022
.option('--verbose', descriptions.verbose, { default: false })
2123
.action(async (options: FreshOptions) => {

storage/framework/core/buddy/src/commands/release.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,20 @@ import { runAction } from '@stacksjs/actions'
88
const descriptions = {
99
release: 'Release a new version of your libraries/packages',
1010
project: 'Target a specific project',
11+
dryRun: 'Run the release without actually releasing',
1112
verbose: 'Enable verbose output',
1213
}
1314

1415
export function release(buddy: CLI) {
1516
buddy
1617
.command('release', descriptions.release)
18+
.option('--dry-run', descriptions.dryRun, { default: false })
1719
.option('-p, --project', descriptions.project, { default: false })
1820
.option('--verbose', descriptions.verbose, { default: false })
1921
.action(async (options: ReleaseOptions) => {
22+
if (options.dryRun)
23+
log.warn('Dry run enabled. No changes will be made.')
24+
2025
const startTime = await intro('buddy release')
2126
const result = await runAction(Action.Release, { ...options, stdin: 'inherit' })
2227

@@ -25,7 +30,7 @@ export function release(buddy: CLI) {
2530
process.exit(ExitCode.FatalError)
2631
}
2732

28-
await outro('Triggered your CI/CD release workflow', { startTime, useSeconds: true })
33+
await outro('Triggered CI/CD Release Workflow', { startTime, useSeconds: true })
2934
})
3035

3136
buddy.on('release:*', () => {

storage/framework/core/cli/src/cli.ts

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

5-
interface ParsedArgv {
5+
export interface ParsedArgv {
66
args: ReadonlyArray<string>
77
options: {
88
[k: string]: any
@@ -32,21 +32,3 @@ export function cli(name?: string | CliOptions, options?: CliOptions) {
3232
export function command(name: string, description: string, options?: CliOptions) {
3333
return cli(options).command(name, description)
3434
}
35-
36-
export function parseArgs() {
37-
return cli().parse().args
38-
}
39-
40-
export function parseOptions(): ParsedArgv['options'] {
41-
const options = cli().parse().options
42-
43-
// Iterate over the options and convert "true" and "false" strings to boolean
44-
for (const key in options) {
45-
if (options[key] === 'true')
46-
options[key] = true
47-
else if (options[key] === 'false')
48-
options[key] = false
49-
}
50-
51-
return options
52-
}

storage/framework/core/cli/src/parse.ts

Lines changed: 62 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -86,16 +86,71 @@ export function parseArgv(argv?: string[]): ParsedArgv {
8686
return { args, options }
8787
}
8888

89-
// export function parseOptions(argv?: string[]): { [k: string]: string | boolean | number } {
90-
// if (argv === undefined)
91-
// argv = process.argv.slice(2)
92-
93-
// return parseArgv(argv).options
94-
// }
95-
9689
export function parseArgs(argv?: string[]): string[] {
9790
if (argv === undefined)
9891
argv = process.argv.slice(2)
9992

10093
return parseArgv(argv).args
10194
}
95+
96+
interface CliOptions {
97+
dryRun?: boolean
98+
[k: string]: string | boolean | number | undefined
99+
}
100+
101+
export function parseOptions(options?: CliOptions): object {
102+
// If options are not provided, use command-line arguments
103+
if (!options) {
104+
options = {}
105+
const args = process.argv.slice(2)
106+
for (let i = 0; i < args.length; i++) {
107+
const arg = args[i]
108+
// Check if the argument is a flag (starts with --)
109+
if (arg.startsWith('--')) {
110+
const key = arg.substring(2) // Remove the -- prefix
111+
// Convert kebab-case to camelCase
112+
const camelCaseKey = key.replace(/-([a-z])/g, g => g[1].toUpperCase())
113+
// Check if the next argument is a boolean value or another flag
114+
if (i + 1 < args.length && (args[i + 1] === 'true' || args[i + 1] === 'false')) {
115+
options[camelCaseKey] = args[i + 1] === 'true'
116+
i++ // Skip the next argument since it's a value
117+
}
118+
else {
119+
// If there's no explicit true/false value, assume the flag is true
120+
options[camelCaseKey] = true
121+
}
122+
}
123+
}
124+
}
125+
else {
126+
// Normalize options: convert string "true"/"false" to boolean values
127+
Object.keys(options).forEach((key) => {
128+
const value = options[key]
129+
if (value === 'true')
130+
options[key] = true
131+
else if (value === 'false')
132+
options[key] = false
133+
})
134+
}
135+
136+
return options
137+
}
138+
139+
export function buddyOptions(options?: any): string {
140+
if (!options) {
141+
options = process.argv.slice(2)
142+
options = Array.from(new Set(options))
143+
// delete the 0 element if it does not start with a -
144+
// e.g. is used when buddy changelog --dry-run is used
145+
if (!options[0].startsWith('-'))
146+
options.shift()
147+
}
148+
149+
if (options?.verbose) {
150+
log.debug('process.argv', process.argv)
151+
log.debug('process.argv.slice(2)', process.argv.slice(2))
152+
log.debug('options inside buddyOptions', options)
153+
}
154+
155+
return options.join(' ')
156+
}

0 commit comments

Comments
 (0)