From 36b4ff6639afb71c65fa1586b49941da86efab08 Mon Sep 17 00:00:00 2001 From: Marcus Schiesser <mail@marcusschiesser.de> Date: Wed, 25 Oct 2023 17:03:02 +0700 Subject: [PATCH] add test form for nextjs simple (and make generation work) --- index.ts | 4 +- templates/index.ts | 9 +- templates/simple/nextjs/app/api/llm/route.ts | 52 +++++++ templates/simple/nextjs/app/api/route/llm.ts | 52 ------- .../nextjs/app/components/message-form.tsx | 43 ++++++ templates/simple/nextjs/app/layout.tsx | 12 +- templates/simple/nextjs/app/page.tsx | 141 ++++-------------- templates/simple/nextjs/next.config.js | 6 +- 8 files changed, 145 insertions(+), 174 deletions(-) create mode 100644 templates/simple/nextjs/app/api/llm/route.ts delete mode 100644 templates/simple/nextjs/app/api/route/llm.ts create mode 100644 templates/simple/nextjs/app/components/message-form.tsx diff --git a/index.ts b/index.ts index fb0b89a1..6c5bafea 100644 --- a/index.ts +++ b/index.ts @@ -289,7 +289,7 @@ async function run(): Promise<void> { packageManager, example: example && example !== 'default' ? example : undefined, examplePath: program.examplePath, - tailwind: program.tailwind, + tailwind: true, eslint: program.eslint, srcDir: program.srcDir, importAlias: program.importAlias, @@ -316,7 +316,7 @@ async function run(): Promise<void> { appPath: resolvedProjectPath, packageManager, eslint: program.eslint, - tailwind: program.tailwind, + tailwind: true, srcDir: program.srcDir, importAlias: program.importAlias, }) diff --git a/templates/index.ts b/templates/index.ts index 9c2b0082..df407f7a 100644 --- a/templates/index.ts +++ b/templates/index.ts @@ -8,10 +8,11 @@ import fs from 'fs/promises' import path from 'path' import { cyan, bold } from 'picocolors' import { Sema } from 'async-sema' -import { version } from '../package.json' import { GetTemplateFileArgs, InstallTemplateArgs } from './types' +const NEXT_VERSION = '13.5.6'; + /** * Get the file path for a given file in a template, e.g. "next.config.js". */ @@ -184,7 +185,9 @@ export const installTemplate = async ({ dependencies: { react: '^18', 'react-dom': '^18', - next: process.env.NEXT_PRIVATE_TEST_VERSION ?? version, + next: NEXT_VERSION, + llamaindex: "0.0.0-20231018030303", + encoding: "^0.1.13" }, devDependencies: {}, } @@ -215,7 +218,7 @@ export const installTemplate = async ({ packageJson.devDependencies = { ...packageJson.devDependencies, eslint: '^8', - 'eslint-config-next': version, + 'eslint-config-next': NEXT_VERSION, } } diff --git a/templates/simple/nextjs/app/api/llm/route.ts b/templates/simple/nextjs/app/api/llm/route.ts new file mode 100644 index 00000000..bb3a1131 --- /dev/null +++ b/templates/simple/nextjs/app/api/llm/route.ts @@ -0,0 +1,52 @@ +import { ChatMessage, OpenAI, SimpleChatEngine } from "llamaindex"; +import { NextRequest, NextResponse } from "next/server"; + +export const runtime = "nodejs"; +export const dynamic = "force-dynamic"; + +export async function POST(request: NextRequest) { + try { + const body = await request.json(); + const { + message, + chatHistory, + }: { + message: string; + chatHistory: ChatMessage[]; + } = body; + if (!message || !chatHistory) { + return NextResponse.json( + { + error: "message, chatHistory are required in the request body", + }, + { status: 400 } + ); + } + + const llm = new OpenAI({ + model: "gpt-3.5-turbo", + }); + + const chatEngine = new SimpleChatEngine({ + llm, + }); + + const response = await chatEngine.chat(message, chatHistory); + const result: ChatMessage = { + role: "assistant", + content: response.response, + }; + + return NextResponse.json({ result }); + } catch (error) { + console.error("[LlamaIndex]", error); + return NextResponse.json( + { + error: (error as Error).message, + }, + { + status: 500, + } + ); + } +} diff --git a/templates/simple/nextjs/app/api/route/llm.ts b/templates/simple/nextjs/app/api/route/llm.ts deleted file mode 100644 index 5a56b184..00000000 --- a/templates/simple/nextjs/app/api/route/llm.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { ChatMessage, OpenAI, SimpleChatEngine } from "llamaindex"; -import { NextRequest, NextResponse } from "next/server"; - -export const runtime = "nodejs"; -export const dynamic = "force-dynamic"; - -export async function POST(request: NextRequest) { - try { - const body = await request.json(); - const { - message, - chatHistory, - }: { - message: string; - chatHistory: ChatMessage[]; - } = body; - if (!message || !chatHistory) { - return NextResponse.json( - { - error: "message, chatHistory are required in the request body", - }, - { status: 400 } - ); - } - - const llm = new OpenAI({ - model: "gpt-3.5-turbo", - }); - - const chatEngine = new SimpleChatEngine({ - llm, - }); - - const response = await chatEngine.chat(message, chatHistory); - const result: ChatMessage = { - role: "assistant", - content: response.response, - }; - - return NextResponse.json({ result }); - } catch (error) { - console.error("[LlamaIndex]", error); - return NextResponse.json( - { - error: (error as Error).message, - }, - { - status: 500, - } - ); - } -} diff --git a/templates/simple/nextjs/app/components/message-form.tsx b/templates/simple/nextjs/app/components/message-form.tsx new file mode 100644 index 00000000..0f67f43d --- /dev/null +++ b/templates/simple/nextjs/app/components/message-form.tsx @@ -0,0 +1,43 @@ +"use client"; +import { ChatMessage } from "llamaindex"; + +export default function MessageForm() { + const testSendMessage = async (message: string) => { + const chatHistory: ChatMessage[] = []; + const apiRoute = "/api/llm"; + const response = await fetch(apiRoute, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ message, chatHistory }), + }); + const data = await response.json(); + alert(JSON.stringify(data)); + }; + + return ( + <form + onSubmit={(e) => { + e.preventDefault(); + const message = e.currentTarget.message.value; + testSendMessage(message); + }} + className="flex flex-col items-center justify-center w-full max-w-5xl p-4 space-y-4 bg-white rounded-xl shadow-xl" + > + <input + autoFocus + type="text" + name="message" + placeholder="Type a message" + className="w-full p-4 rounded-xl shadow-inner" + /> + <button + type="submit" + className="p-4 text-white rounded-xl shadow-xl bg-gradient-to-r from-cyan-500 to-sky-500 dark:from-cyan-600 dark:to-sky-600" + > + Send message + </button> + </form> + ); +} diff --git a/templates/simple/nextjs/app/layout.tsx b/templates/simple/nextjs/app/layout.tsx index fb097706..444a7b6e 100644 --- a/templates/simple/nextjs/app/layout.tsx +++ b/templates/simple/nextjs/app/layout.tsx @@ -1,8 +1,8 @@ -import type { Metadata } from "next"; -import { Inter } from "next/font/google"; -import "./globals.css"; +import type { Metadata } from 'next' +import { Inter } from 'next/font/google' +import './globals.css' -const inter = Inter({ subsets: ["latin"] }); +const inter = Inter({ subsets: ['latin'] }) export const metadata: Metadata = { title: "Create Llama App", @@ -12,11 +12,11 @@ export const metadata: Metadata = { export default function RootLayout({ children, }: { - children: React.ReactNode; + children: React.ReactNode }) { return ( <html lang="en"> <body className={inter.className}>{children}</body> </html> - ); + ) } diff --git a/templates/simple/nextjs/app/page.tsx b/templates/simple/nextjs/app/page.tsx index 7a8286b5..1a73edb1 100644 --- a/templates/simple/nextjs/app/page.tsx +++ b/templates/simple/nextjs/app/page.tsx @@ -1,113 +1,34 @@ -import Image from 'next/image' +import MessageForm from "@/app/components/message-form"; +import Image from "next/image"; export default function Home() { - return ( - <main className="flex min-h-screen flex-col items-center justify-between p-24"> - <div className="z-10 max-w-5xl w-full items-center justify-between font-mono text-sm lg:flex"> - <p className="fixed left-0 top-0 flex w-full justify-center border-b border-gray-300 bg-gradient-to-b from-zinc-200 pb-6 pt-8 backdrop-blur-2xl dark:border-neutral-800 dark:bg-zinc-800/30 dark:from-inherit lg:static lg:w-auto lg:rounded-xl lg:border lg:bg-gray-200 lg:p-4 lg:dark:bg-zinc-800/30"> - Get started by editing - <code className="font-mono font-bold">app/page.tsx</code> - </p> - <div className="fixed bottom-0 left-0 flex h-48 w-full items-end justify-center bg-gradient-to-t from-white via-white dark:from-black dark:via-black lg:static lg:h-auto lg:w-auto lg:bg-none"> - <a - className="pointer-events-none flex place-items-center gap-2 p-8 lg:pointer-events-auto lg:p-0" - href="https://vercel.com?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app" - target="_blank" - rel="noopener noreferrer" - > - By{' '} - <Image - src="/vercel.svg" - alt="Vercel Logo" - className="dark:invert" - width={100} - height={24} - priority - /> - </a> - </div> - </div> - - <div className="relative flex place-items-center before:absolute before:h-[300px] before:w-[480px] before:-translate-x-1/2 before:rounded-full before:bg-gradient-radial before:from-white before:to-transparent before:blur-2xl before:content-[''] after:absolute after:-z-20 after:h-[180px] after:w-[240px] after:translate-x-1/3 after:bg-gradient-conic after:from-sky-200 after:via-blue-200 after:blur-2xl after:content-[''] before:dark:bg-gradient-to-br before:dark:from-transparent before:dark:to-blue-700 before:dark:opacity-10 after:dark:from-sky-900 after:dark:via-[#0141ff] after:dark:opacity-40 before:lg:h-[360px] z-[-1]"> - <Image - className="relative dark:drop-shadow-[0_0_0.3rem_#ffffff70] dark:invert" - src="/next.svg" - alt="Next.js Logo" - width={180} - height={37} - priority - /> - </div> - - <div className="mb-32 grid text-center lg:max-w-5xl lg:w-full lg:mb-0 lg:grid-cols-4 lg:text-left"> - <a - href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app" - className="group rounded-lg border border-transparent px-5 py-4 transition-colors hover:border-gray-300 hover:bg-gray-100 hover:dark:border-neutral-700 hover:dark:bg-neutral-800/30" - target="_blank" - rel="noopener noreferrer" - > - <h2 className={`mb-3 text-2xl font-semibold`}> - Docs{' '} - <span className="inline-block transition-transform group-hover:translate-x-1 motion-reduce:transform-none"> - -> - </span> - </h2> - <p className={`m-0 max-w-[30ch] text-sm opacity-50`}> - Find in-depth information about Next.js features and API. - </p> - </a> - - <a - href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app" - className="group rounded-lg border border-transparent px-5 py-4 transition-colors hover:border-gray-300 hover:bg-gray-100 hover:dark:border-neutral-700 hover:dark:bg-neutral-800/30" - target="_blank" - rel="noopener noreferrer" - > - <h2 className={`mb-3 text-2xl font-semibold`}> - Learn{' '} - <span className="inline-block transition-transform group-hover:translate-x-1 motion-reduce:transform-none"> - -> - </span> - </h2> - <p className={`m-0 max-w-[30ch] text-sm opacity-50`}> - Learn about Next.js in an interactive course with quizzes! - </p> - </a> - - <a - href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app" - className="group rounded-lg border border-transparent px-5 py-4 transition-colors hover:border-gray-300 hover:bg-gray-100 hover:dark:border-neutral-700 hover:dark:bg-neutral-800/30" - target="_blank" - rel="noopener noreferrer" - > - <h2 className={`mb-3 text-2xl font-semibold`}> - Templates{' '} - <span className="inline-block transition-transform group-hover:translate-x-1 motion-reduce:transform-none"> - -> - </span> - </h2> - <p className={`m-0 max-w-[30ch] text-sm opacity-50`}> - Explore the Next.js 13 playground. - </p> - </a> - - <a - href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app" - className="group rounded-lg border border-transparent px-5 py-4 transition-colors hover:border-gray-300 hover:bg-gray-100 hover:dark:border-neutral-700 hover:dark:bg-neutral-800/30" - target="_blank" - rel="noopener noreferrer" - > - <h2 className={`mb-3 text-2xl font-semibold`}> - Deploy{' '} - <span className="inline-block transition-transform group-hover:translate-x-1 motion-reduce:transform-none"> - -> - </span> - </h2> - <p className={`m-0 max-w-[30ch] text-sm opacity-50`}> - Instantly deploy your Next.js site to a shareable URL with Vercel. - </p> - </a> - </div> - </main> - ) + return ( + <main className="flex min-h-screen flex-col items-center gap-10 p-24"> + <div className="z-10 max-w-5xl w-full items-center justify-between font-mono text-sm lg:flex"> + <p className="fixed left-0 top-0 flex w-full justify-center border-b border-gray-300 bg-gradient-to-b from-zinc-200 pb-6 pt-8 backdrop-blur-2xl dark:border-neutral-800 dark:bg-zinc-800/30 dark:from-inherit lg:static lg:w-auto lg:rounded-xl lg:border lg:bg-gray-200 lg:p-4 lg:dark:bg-zinc-800/30"> + Get started by editing + <code className="font-mono font-bold">app/page.tsx</code> + </p> + <div className="fixed bottom-0 left-0 flex h-48 w-full items-end justify-center bg-gradient-to-t from-white via-white dark:from-black dark:via-black lg:static lg:h-auto lg:w-auto lg:bg-none"> + <a + className="pointer-events-none flex place-items-center gap-2 p-8 lg:pointer-events-auto lg:p-0" + href="https://vercel.com?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app" + target="_blank" + rel="noopener noreferrer" + > + By{" "} + <Image + src="/vercel.svg" + alt="Vercel Logo" + className="dark:invert" + width={100} + height={24} + priority + /> + </a> + </div> + </div> + <MessageForm /> + </main> + ); } diff --git a/templates/simple/nextjs/next.config.js b/templates/simple/nextjs/next.config.js index 767719fc..0b2c2bf1 100644 --- a/templates/simple/nextjs/next.config.js +++ b/templates/simple/nextjs/next.config.js @@ -1,4 +1,8 @@ /** @type {import('next').NextConfig} */ -const nextConfig = {} +const nextConfig = { + experimental: { + serverComponentsExternalPackages: ["llamaindex"], + }, +} module.exports = nextConfig -- GitLab