@o/cli 0.16.19 → 0.16.20

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.
@@ -0,0 +1,164 @@
1
+ /**
2
+ * docs command group - read the current repository's documentation
3
+ */
4
+
5
+ import { existsSync, readdirSync, readFileSync } from 'node:fs'
6
+ import { join } from 'node:path'
7
+
8
+ import { defineCommand } from 'citty'
9
+ import pc from 'picocolors'
10
+
11
+ function resolveDocsDir(cwd = process.cwd()): string {
12
+ const skillsDir = join(cwd, 'skills')
13
+ if (existsSync(skillsDir)) return skillsDir
14
+
15
+ const docsDir = join(cwd, 'docs')
16
+ if (existsSync(docsDir)) return docsDir
17
+
18
+ throw new Error(`No docs or skills directory found in ${cwd}`)
19
+ }
20
+
21
+ const listCommand = defineCommand({
22
+ meta: {
23
+ name: 'list',
24
+ description: 'List repository documentation files',
25
+ },
26
+ async run() {
27
+ let docsDir: string
28
+ try {
29
+ docsDir = resolveDocsDir()
30
+ } catch (error) {
31
+ console.error(pc.red(`āœ— ${error instanceof Error ? error.message : String(error)}`))
32
+ process.exit(1)
33
+ }
34
+
35
+ const files = readdirSync(docsDir)
36
+ .filter((file) => file.endsWith('.md'))
37
+ .sort()
38
+
39
+ console.info()
40
+ console.info(pc.bold(pc.cyan('šŸ“š Available Documentation')))
41
+ console.info()
42
+
43
+ for (const file of files) {
44
+ const name = file.replace(/\.md$/, '')
45
+ const content = readFileSync(join(docsDir, file), 'utf-8')
46
+ const heading = content.match(/^#\s+(.+)$/m)?.[1]
47
+
48
+ console.info(` ${pc.green(name)}`)
49
+ if (heading) console.info(` ${pc.dim(heading)}`)
50
+ }
51
+
52
+ console.info()
53
+ console.info(pc.dim(`Use 'takeout docs get <name>' to view a document`))
54
+ console.info()
55
+ },
56
+ })
57
+
58
+ const getCommand = defineCommand({
59
+ meta: {
60
+ name: 'get',
61
+ description: 'Get the content of one or more repository documentation files',
62
+ },
63
+ args: {
64
+ name: {
65
+ type: 'positional',
66
+ description: 'Name(s) of the doc files (without .md extension)',
67
+ required: true,
68
+ valueHint: 'name...',
69
+ },
70
+ },
71
+ async run({ args }) {
72
+ let docsDir: string
73
+ try {
74
+ docsDir = resolveDocsDir()
75
+ } catch (error) {
76
+ console.error(pc.red(`āœ— ${error instanceof Error ? error.message : String(error)}`))
77
+ process.exit(1)
78
+ }
79
+
80
+ const names = args._.length > 0 ? args._ : [args.name]
81
+ const results: Array<{ name: string; content: string }> = []
82
+
83
+ for (const name of names) {
84
+ const fileName = name.endsWith('.md') ? name : `${name}.md`
85
+ const filePath = join(docsDir, fileName)
86
+
87
+ if (!existsSync(filePath)) {
88
+ console.error(pc.red(`āœ— Doc file not found: ${name}`))
89
+ continue
90
+ }
91
+
92
+ results.push({ name, content: readFileSync(filePath, 'utf-8') })
93
+ }
94
+
95
+ if (results.length === 0) {
96
+ console.info()
97
+ console.info(pc.dim(`Use 'takeout docs list' to see available docs`))
98
+ process.exit(1)
99
+ }
100
+
101
+ for (let index = 0; index < results.length; index++) {
102
+ const result = results[index]!
103
+ console.info(`# ${result.name}`)
104
+ console.info()
105
+ console.info(result.content)
106
+
107
+ if (index < results.length - 1) {
108
+ console.info()
109
+ console.info('---')
110
+ console.info()
111
+ }
112
+ }
113
+ },
114
+ })
115
+
116
+ const pathCommand = defineCommand({
117
+ meta: {
118
+ name: 'path',
119
+ description: 'Get the absolute path to repository documentation',
120
+ },
121
+ args: {
122
+ name: {
123
+ type: 'positional',
124
+ description: 'Name of the doc file (without .md extension)',
125
+ required: false,
126
+ },
127
+ },
128
+ async run({ args }) {
129
+ let docsDir: string
130
+ try {
131
+ docsDir = resolveDocsDir()
132
+ } catch (error) {
133
+ console.error(pc.red(`āœ— ${error instanceof Error ? error.message : String(error)}`))
134
+ process.exit(1)
135
+ }
136
+
137
+ if (!args.name) {
138
+ console.info(docsDir)
139
+ return
140
+ }
141
+
142
+ const fileName = args.name.endsWith('.md') ? args.name : `${args.name}.md`
143
+ const filePath = join(docsDir, fileName)
144
+
145
+ if (!existsSync(filePath)) {
146
+ console.error(pc.red(`āœ— Doc file not found: ${args.name}`))
147
+ process.exit(1)
148
+ }
149
+
150
+ console.info(filePath)
151
+ },
152
+ })
153
+
154
+ export const docsCommand = defineCommand({
155
+ meta: {
156
+ name: 'docs',
157
+ description: 'List and retrieve repository documentation',
158
+ },
159
+ subCommands: {
160
+ list: listCommand,
161
+ get: getCommand,
162
+ path: pathCommand,
163
+ },
164
+ })
@@ -0,0 +1,69 @@
1
+ import { defineCommand } from 'citty'
2
+ import pc from 'picocolors'
3
+
4
+ import { setupProductionEnv, listCategories } from '../utils/env-setup'
5
+
6
+ export const envSetupCommand = defineCommand({
7
+ meta: {
8
+ name: 'env:setup',
9
+ description: 'Configure production environment variables',
10
+ },
11
+ args: {
12
+ category: {
13
+ type: 'string',
14
+ description: 'Setup only a specific category (e.g., aws, apple, storage)',
15
+ alias: 'c',
16
+ },
17
+ file: {
18
+ type: 'string',
19
+ description: 'Environment file to update',
20
+ default: '.env.production',
21
+ alias: 'f',
22
+ },
23
+ list: {
24
+ type: 'boolean',
25
+ description: 'List all available categories',
26
+ alias: 'l',
27
+ default: false,
28
+ },
29
+ 'skip-optional': {
30
+ type: 'boolean',
31
+ description: 'Skip optional categories',
32
+ default: false,
33
+ },
34
+ },
35
+ async run({ args }) {
36
+ try {
37
+ const cwd = process.cwd()
38
+
39
+ // list categories if requested
40
+ if (args.list) {
41
+ listCategories()
42
+ return
43
+ }
44
+
45
+ console.info('')
46
+ console.info(pc.bold('šŸš€ Takeout Production Environment Setup'))
47
+ console.info(pc.gray('Configure your production deployment settings'))
48
+ console.info('')
49
+
50
+ const success = await setupProductionEnv(cwd, {
51
+ skipOptional: args['skip-optional'],
52
+ envFile: args.file,
53
+ onlyCategory: args.category,
54
+ interactive: true,
55
+ })
56
+
57
+ if (!success) {
58
+ console.info(pc.yellow('\n⚠ Environment setup was cancelled'))
59
+ console.info(pc.gray('You can resume anytime with:'))
60
+ console.info(pc.cyan(' bun takeout env:setup'))
61
+ process.exit(1)
62
+ }
63
+ } catch (error) {
64
+ console.error(pc.red('\nāœ– Environment setup failed:'))
65
+ console.error(error)
66
+ process.exit(1)
67
+ }
68
+ },
69
+ })