Skip to content

Commit 24c15ff

Browse files
authored
refactor: reusable utility for getting api keys (#54)
* chore * up * Update utils.ts
1 parent 9d3483d commit 24c15ff

2 files changed

Lines changed: 63 additions & 48 deletions

File tree

packages/cali/src/cli.ts

Lines changed: 3 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
import 'dotenv/config'
44

5-
import { execSync } from 'node:child_process'
6-
75
import { createOpenAI } from '@ai-sdk/openai'
86
import { confirm, outro, select, spinner, text } from '@clack/prompts'
97
import { CoreMessage, generateText } from 'ai'
@@ -14,6 +12,7 @@ import { retro } from 'gradient-string'
1412
import { z } from 'zod'
1513

1614
import { reactNativePrompt } from './prompt.js'
15+
import { getApiKey } from './utils.js'
1716

1817
const MessageSchema = z.union([
1918
z.object({ type: z.literal('select'), content: z.string(), options: z.array(z.string()) }),
@@ -48,56 +47,12 @@ console.log(
4847
`)
4948
)
5049

51-
const OPENAI_API_KEY =
52-
process.env.OPENAI_API_KEY ||
53-
(await (async () => {
54-
const apiKey = await text({
55-
message: dedent`
56-
${chalk.bold('Please provide your OpenAI API key.')}
57-
58-
To skip this message, set ${chalk.bold('OPENAI_API_KEY')} env variable, and run again.
59-
60-
You can do it in three ways:
61-
- by creating an ${chalk.bold('.env.local')} file (make sure to ${chalk.bold('.gitignore')} it)
62-
${chalk.gray(`\`\`\`
63-
OPENAI_API_KEY=<your-key>
64-
\`\`\`
65-
`)}
66-
- by passing it inline:
67-
${chalk.gray(`\`\`\`
68-
OPENAI_API_KEY=<your-key> npx cali
69-
\`\`\`
70-
`)}
71-
- by setting it as an env variable in your shell (e.g. in ~/.zshrc or ~/.bashrc):
72-
${chalk.gray(`\`\`\`
73-
export OPENAI_API_KEY=<your-key>
74-
\`\`\`
75-
`)},
76-
`,
77-
validate: (value) => (value.length > 0 ? undefined : 'Please provide a valid answer.'),
78-
})
79-
80-
if (typeof apiKey === 'symbol') {
81-
outro(chalk.gray('Bye!'))
82-
process.exit(0)
83-
}
84-
85-
const save = await confirm({
86-
message: 'Do you want to save it for future runs in `.env.local`?',
87-
})
88-
89-
if (save) {
90-
execSync(`echo "OPENAI_API_KEY=${apiKey}" >> .env.local`)
91-
execSync(`echo ".env.local" >> .gitignore`)
92-
}
93-
94-
return apiKey
95-
})())
50+
console.log()
9651

9752
const AI_MODEL = process.env.AI_MODEL || 'gpt-4o'
9853

9954
const openai = createOpenAI({
100-
apiKey: OPENAI_API_KEY,
55+
apiKey: await getApiKey('OpenAI', 'OPENAI_API_K2EY'),
10156
})
10257

10358
async function startSession(): Promise<CoreMessage[]> {

packages/cali/src/utils.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { execSync } from 'node:child_process'
2+
3+
import { confirm, text } from '@clack/prompts'
4+
import chalk from 'chalk'
5+
import dedent from 'dedent'
6+
7+
/**
8+
* Get API key from environment variables or prompt user for it.
9+
*/
10+
export async function getApiKey(name: string, key: string) {
11+
if (key in process.env) {
12+
return process.env[key]
13+
}
14+
return (async () => {
15+
let apiKey: string | symbol
16+
do {
17+
apiKey = await text({
18+
message: dedent`
19+
${chalk.bold(`Please provide your ${name} API key.`)}
20+
21+
To skip this message, set ${chalk.bold(key)} env variable, and run again.
22+
23+
You can do it in three ways:
24+
- by creating an ${chalk.bold('.env.local')} file (make sure to ${chalk.bold('.gitignore')} it)
25+
${chalk.gray(`\`\`\`
26+
${key}=<your-key>
27+
\`\`\`
28+
`)}
29+
- by passing it inline:
30+
${chalk.gray(`\`\`\`
31+
${key}=<your-key> npx cali
32+
\`\`\`
33+
`)}
34+
- by setting it as an env variable in your shell (e.g. in ~/.zshrc or ~/.bashrc):
35+
${chalk.gray(`\`\`\`
36+
export ${key}=<your-key>
37+
\`\`\`
38+
`)},
39+
`,
40+
validate: (value) => (value.length > 0 ? undefined : `Please provide a valid ${key}.`),
41+
})
42+
} while (typeof apiKey === 'undefined')
43+
44+
if (typeof apiKey === 'symbol') {
45+
outro(chalk.gray('Bye!'))
46+
process.exit(0)
47+
}
48+
49+
const save = await confirm({
50+
message: `Do you want to save it for future runs in .env.local?`,
51+
})
52+
53+
if (save) {
54+
execSync(`echo "${key}=${apiKey}" >> .env.local`)
55+
execSync(`echo ".env.local" >> .gitignore`)
56+
}
57+
58+
return apiKey
59+
})()
60+
}

0 commit comments

Comments
 (0)