Skip to content

Commit 69102da

Browse files
feat: add env validation, update prompt
1 parent bb517ea commit 69102da

File tree

8 files changed

+95
-14
lines changed

8 files changed

+95
-14
lines changed

.env.example

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
OPENAI_API_KEY = ""
1+
OPENAI_API_KEY=""
22
UPSTASH_REDIS_REST_URL=""
33
UPSTASH_REDIS_REST_TOKEN=""
44
NEXT_PUBLIC_APP_URL="http://localhost:3000"

package-lock.json

Lines changed: 39 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"@radix-ui/react-dialog": "^1.0.3",
1919
"@radix-ui/react-label": "^2.0.1",
2020
"@radix-ui/react-select": "^1.2.1",
21+
"@t3-oss/env-nextjs": "^0.4.0",
2122
"@tanstack/react-query": "^4.29.5",
2223
"@tanstack/react-table": "^8.9.1",
2324
"@uiw/codemirror-theme-github": "^4.19.16",
@@ -40,7 +41,8 @@
4041
"react-hotkeys-hook": "^4.4.0",
4142
"react-resizable-panels": "^0.0.43",
4243
"react-use-clipboard": "^1.0.9",
43-
"tailwind-merge": "^1.12.0"
44+
"tailwind-merge": "^1.12.0",
45+
"zod": "^3.21.4"
4446
},
4547
"devDependencies": {
4648
"@tailwindcss/forms": "^0.5.3",

src/app/api/chat/route.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,6 @@ import { ratelimit } from '@/utils/ratelimit';
22
import { OpenAIStream, OpenAIStreamPayload } from '@/utils/stream';
33
import { NextRequest, NextResponse } from 'next/server';
44

5-
if (!process.env.OPENAI_API_KEY) {
6-
throw new Error('Missing env var from OpenAI');
7-
}
8-
95
export const runtime = 'edge';
106

117
export async function POST(req: NextRequest): Promise<Response> {
@@ -40,7 +36,7 @@ export async function POST(req: NextRequest): Promise<Response> {
4036
4137
--${prompt}
4238
43-
prefix the response with -- unless it is SQL code
39+
prefix the response before and after code with -- unless it is SQL code
4440
`,
4541
},
4642
],

src/app/layout.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@ import '../styles/globals.css';
44
import { Inter } from 'next/font/google';
55
import { cn } from '@/utils/cn';
66
import { Metadata } from 'next';
7+
import { env } from "@/env.mjs";
78

89
const inter = Inter({ subsets: ['latin'] });
910

1011
export const metadata: Metadata = {
11-
metadataBase: new URL(process.env.NEXT_PUBLIC_APP_URL ?? ''),
12+
metadataBase: new URL(env.NEXT_PUBLIC_APP_URL ?? ''),
1213
title: 'Postgres AI Playground',
1314
description:
1415
'Postgres playground where you can connect to your database and use AI to generate SQL queries',

src/components/command-palette.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import { PostgreSQL, sql } from '@codemirror/lang-sql';
2929
import { useTheme } from 'next-themes';
3030
import { githubDark, githubLight } from '@uiw/codemirror-theme-github';
3131
import { Spinner } from './shared/spinner';
32+
import {env} from "@/env.mjs";
3233

3334
type FormValues = {
3435
prompt: string;
@@ -54,7 +55,7 @@ export const CommandPalette = () => {
5455
setResponse('');
5556

5657
const response = await fetch(
57-
`${process.env.NEXT_PUBLIC_APP_URL}/api/chat`,
58+
`${env.NEXT_PUBLIC_APP_URL}/api/chat`,
5859
{
5960
method: 'POST',
6061
headers: {

src/env.mjs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { z } from 'zod'
2+
import { createEnv } from '@t3-oss/env-nextjs'
3+
4+
export const env = createEnv({
5+
/*
6+
* Serverside Environment variables, not available on the client.
7+
* Will throw if you access these variables on the client.
8+
*/
9+
server: {
10+
NODE_ENV: z.enum(['development', 'test', 'production']),
11+
12+
OPENAI_API_KEY: z.string().startsWith('sk-'),
13+
14+
UPSTASH_REDIS_REST_URL: z.string().url(),
15+
UPSTASH_REDIS_REST_TOKEN: z.string().min(1),
16+
},
17+
/*
18+
* Environment variables available on the client (and server).
19+
*
20+
* 💡 You'll get typeerrors if these are not prefixed with NEXT_PUBLIC_.
21+
*/
22+
client: {
23+
NEXT_PUBLIC_APP_URL: z.string().url(),
24+
},
25+
/*
26+
* Due to how Next.js bundles environment variables on Edge and Client,
27+
* we need to manually destructure them to make sure all are included in bundle.
28+
*
29+
* 💡 You'll get typeerrors if not all variables from `server` & `client` are included here.
30+
*/
31+
runtimeEnv: {
32+
NODE_ENV: process.env.NODE_ENV,
33+
34+
OPENAI_API_KEY: process.env.OPENAI_API_KEY,
35+
UPSTASH_REDIS_REST_URL: process.env.UPSTASH_REDIS_REST_URL,
36+
UPSTASH_REDIS_REST_TOKEN: process.env.UPSTASH_REDIS_REST_TOKEN,
37+
38+
NEXT_PUBLIC_APP_URL: process.env.NEXT_PUBLIC_APP_URL,
39+
},
40+
/**
41+
* Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation.
42+
* This is especially useful for Docker builds.
43+
*/
44+
skipValidation: !!process.env.SKIP_ENV_VALIDATION,
45+
})

src/utils/stream.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
ParsedEvent,
44
ReconnectInterval,
55
} from 'eventsource-parser';
6+
import { env } from "@/env.mjs";
67

78
export type ChatGPTAgent = 'user' | 'system';
89

@@ -32,7 +33,7 @@ export async function OpenAIStream(payload: OpenAIStreamPayload) {
3233
const res = await fetch('https://api.openai.com/v1/chat/completions', {
3334
headers: {
3435
'Content-Type': 'application/json',
35-
Authorization: `Bearer ${process.env.OPENAI_API_KEY ?? ''}`,
36+
Authorization: `Bearer ${env.OPENAI_API_KEY ?? ''}`,
3637
},
3738
method: 'POST',
3839
body: JSON.stringify(payload),

0 commit comments

Comments
 (0)