-
Notifications
You must be signed in to change notification settings - Fork 189
support eject to fully customize next folder #653
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
marcusschiesser
merged 67 commits into
main
from
tp/eject-to-fully-support-custom-next-server
May 28, 2025
Merged
Changes from all commits
Commits
Show all changes
67 commits
Select commit
Hold shift + click to select a range
9f86770
add script to copy server folder
thucpn 9a35242
change command
thucpn 07578f8
clean up before copy
thucpn 3e8ec67
copy route handler folder
thucpn 009858e
fix lint
thucpn 254ab1c
add eject options
thucpn ffe836a
use EJECT from env
thucpn 65864e5
update import workflow path
thucpn 60afca8
init settings in chat route
thucpn 20c662e
refactor: move prompts & events to chat utils folder
thucpn f32e971
copy utils for chat route
thucpn b66cebb
update config.js file in eject mode
thucpn 7c338b3
pass suggestNextQuestions as query params to chat route handler
thucpn 5be6a60
enable/disable suggestNextQuestions in route handler
thucpn 9dce7f5
Merge branch 'main' into tp/eject-to-fully-support-custom-next-server
thucpn 9e021b0
remove todo
thucpn d8b6390
add document about eject mode
thucpn d12b7a4
Create many-knives-warn.md
thucpn 5841c44
ignore ejected next/ folder
thucpn 1310352
wrong doc
thucpn e35f9bd
fix: doc
thucpn 172bacf
revert server
thucpn 9eb0ea6
keep server options
thucpn 80e7267
use config from .env for route handler
thucpn 18b0722
prepare nextjs project
thucpn 1135931
fix: scripts
thucpn b56e589
Merge branch 'main' into tp/eject-to-fully-support-custom-next-server
thucpn 77146a1
update script
thucpn f7a0871
fix eject output argument
thucpn d418603
Merge branch 'main' into tp/eject-to-fully-support-custom-next-server
thucpn a5ecc74
update doc
thucpn a846adc
update route imports
thucpn 7efd227
update package.json
thucpn 7279545
update gitignore
thucpn e8f899b
copy other files
thucpn 2fed965
nextjs project config files
thucpn d4fc315
update eject script
thucpn 8f01f37
update package.json
thucpn 83c8203
missing eslint packages
thucpn fdcd776
bump react-day-picker to fix peer deps issue with date-fns
thucpn cf8678c
missing dotenv
thucpn 13ee73a
update ignore
thucpn cdfbf95
copy env
thucpn 2c0fbdc
update frontend config.js file
thucpn 4c92335
fix: config path
thucpn d7082b7
enable llamacloud
thucpn f8a4275
no need layout for normal nextjs
thucpn fffae76
Merge branch 'main' into tp/eject-to-fully-support-custom-next-server
thucpn 27994c9
remove LAYOUT_DIR from env
thucpn 81b0fc9
don't use LAYOUT_DIR
thucpn 9875737
update document
thucpn a8d78c2
update imports in workflow file
thucpn 541cdd3
update document
thucpn 9bcd6f3
use NEXT_PUBLIC for frontend config
thucpn 1811957
fix: update workflow file path for ejected project
thucpn b011630
fix: path
thucpn 91d1cb9
fix: eject dest path
thucpn 3f553ef
use single entry point for utils
thucpn bd167c1
update imports for generate.ts
thucpn adbd671
use argument after eject
thucpn 97bdf67
fix path
thucpn 76cad7e
fix: starter questions
thucpn 9b81778
remove config.js instead of making it empty
thucpn ebea495
update document
thucpn 65937c5
add eject to e2e
thucpn aba3879
import { OpenAI } from "@llamaindex/openai";
thucpn 763bc23
disable eject test for llamacloud
thucpn File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
--- | ||
"create-llama": patch | ||
"@llamaindex/server": patch | ||
--- | ||
|
||
support eject to fully customize next folder |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
3 changes: 2 additions & 1 deletion
3
...e-llama/templates/components/vectordbs/llamaindexserver/llamacloud/typescript/generate.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,8 @@ | ||
# server contains Nextjs frontend code (not compiled) | ||
server/ | ||
|
||
# the ejected nextjs project | ||
project/ | ||
|
||
# temp is the copy of next folder but without API folder, used to build frontend static files | ||
temp/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
#!/usr/bin/env node | ||
|
||
const fs = require("fs").promises; | ||
const path = require("path"); | ||
|
||
// Resolve the project directory in node_modules/@llamaindex/server/project | ||
// This is the template that used to construct the nextjs project | ||
const projectDir = path.resolve(__dirname, "../project"); | ||
|
||
// Resolve the src directory that contains workflow & setting files | ||
const srcDir = path.join(process.cwd(), "src"); | ||
const srcAppDir = path.join(srcDir, "app"); | ||
const generateFile = path.join(srcDir, "generate.ts"); | ||
const envFile = path.join(process.cwd(), ".env"); | ||
|
||
// The environment variables that are used as LlamaIndexServer configs | ||
const SERVER_CONFIG_VARS = [ | ||
{ | ||
key: "OPENAI_API_KEY", | ||
defaultValue: "<your-openai-api-key>", | ||
description: "OpenAI API key", | ||
}, | ||
{ | ||
key: "SUGGEST_NEXT_QUESTIONS", | ||
defaultValue: "true", | ||
description: "Whether to suggest next questions (`suggestNextQuestions`)", | ||
}, | ||
{ | ||
key: "COMPONENTS_DIR", | ||
defaultValue: "components", | ||
description: "Directory for custom components (`componentsDir`)", | ||
}, | ||
{ | ||
key: "WORKFLOW_FILE_PATH", | ||
defaultValue: "app/api/chat/app/workflow.ts", | ||
description: "The path to the workflow file (will be updated in dev mode)", | ||
}, | ||
{ | ||
key: "NEXT_PUBLIC_USE_COMPONENTS_DIR", | ||
defaultValue: "true", | ||
description: "Whether to enable components directory feature on frontend", | ||
}, | ||
{ | ||
key: "NEXT_PUBLIC_DEV_MODE", | ||
defaultValue: "true", | ||
description: "Whether to enable dev mode (`devMode`)", | ||
}, | ||
{ | ||
key: "NEXT_PUBLIC_STARTER_QUESTIONS", | ||
defaultValue: '["Summarize the document", "What are the key points?"]', | ||
description: | ||
"Initial questions to display in the chat (`starterQuestions`)", | ||
}, | ||
{ | ||
key: "NEXT_PUBLIC_SHOW_LLAMACLOUD_SELECTOR", | ||
defaultValue: "false", | ||
description: | ||
"Whether to show LlamaCloud selector for frontend (`llamaCloudIndexSelector`)", | ||
}, | ||
]; | ||
|
||
async function eject() { | ||
try { | ||
// validate required directories (nextjs project template, src directory, src/app directory) | ||
const requiredDirs = [projectDir, srcDir, srcAppDir]; | ||
for (const dir of requiredDirs) { | ||
const exists = await fs | ||
.access(dir) | ||
.then(() => true) | ||
.catch(() => false); | ||
if (!exists) { | ||
console.error("Error: directory does not exist at", dir); | ||
process.exit(1); | ||
} | ||
} | ||
|
||
// Get destination directory from command line arguments (pnpm eject <path>) | ||
const args = process.argv; | ||
const outputIndex = args.indexOf("eject"); | ||
const destDir = | ||
outputIndex !== -1 && args[outputIndex + 1] | ||
? path.resolve(args[outputIndex + 1]) // Use provided path after eject | ||
: path.join(process.cwd(), "next"); // Default to "next" folder in the current working directory | ||
|
||
// remove destination directory if it exists | ||
await fs.rm(destDir, { recursive: true, force: true }); | ||
|
||
// create destination directory | ||
await fs.mkdir(destDir, { recursive: true }); | ||
|
||
// Copy the nextjs project template to the destination directory | ||
await fs.cp(projectDir, destDir, { recursive: true }); | ||
|
||
// copy src/app/* to destDir/app/api/chat | ||
const chatRouteDir = path.join(destDir, "app", "api", "chat"); | ||
await fs.cp(srcAppDir, path.join(chatRouteDir, "app"), { recursive: true }); | ||
|
||
// nextjs project doesn't depend on @llamaindex/server anymore, we need to update the imports in workflow file | ||
const workflowFile = path.join(chatRouteDir, "app", "workflow.ts"); | ||
let workflowContent = await fs.readFile(workflowFile, "utf-8"); | ||
workflowContent = workflowContent.replace("@llamaindex/server", "../utils"); | ||
await fs.writeFile(workflowFile, workflowContent); | ||
|
||
// copy generate.ts if it exists | ||
const genFilePath = path.join(chatRouteDir, "generate.ts"); | ||
const genFileExists = await copy(generateFile, genFilePath); | ||
if (genFileExists) { | ||
// update the import @llamaindex/server in generate.ts | ||
let genContent = await fs.readFile(genFilePath, "utf-8"); | ||
genContent = genContent.replace("@llamaindex/server", "./utils"); | ||
await fs.writeFile(genFilePath, genContent); | ||
} | ||
|
||
// copy folders in root directory if exists | ||
const rootFolders = ["components", "data", "output", "storage"]; | ||
for (const folder of rootFolders) { | ||
await copy(path.join(process.cwd(), folder), path.join(destDir, folder)); | ||
} | ||
|
||
// copy .env if it exists or create a new one | ||
const envFileExists = await copy(envFile, path.join(destDir, ".env")); | ||
if (!envFileExists) { | ||
await fs.writeFile(path.join(destDir, ".env"), ""); | ||
} | ||
|
||
// update .env file with more server configs | ||
let envFileContent = await fs.readFile(path.join(destDir, ".env"), "utf-8"); | ||
for (const envVar of SERVER_CONFIG_VARS) { | ||
const { key, defaultValue, description } = envVar; | ||
if (!envFileContent.includes(key)) { | ||
// if the key is not exists in the env file, add it | ||
envFileContent += `\n# ${description}\n${key}=${defaultValue}\n`; | ||
} | ||
} | ||
await fs.writeFile(path.join(destDir, ".env"), envFileContent); | ||
|
||
// rename gitignore -> .gitignore | ||
await fs.rename( | ||
path.join(destDir, "gitignore"), | ||
path.join(destDir, ".gitignore"), | ||
); | ||
thucpn marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// user can customize layout directory in nextjs project, remove layout api | ||
await fs.rm(path.join(destDir, "app", "api", "layout"), { | ||
recursive: true, | ||
force: true, | ||
}); | ||
|
||
// remove no-needed files | ||
await fs.unlink(path.join(destDir, "public", "config.js")); | ||
await fs.unlink(path.join(destDir, "next-build.config.ts")); | ||
|
||
console.log("Successfully ejected @llamaindex/server to", destDir); | ||
} catch (error) { | ||
console.error("Error during eject:", error.message); | ||
process.exit(1); | ||
} | ||
} | ||
|
||
// copy src to dest if src exists, return true if src exists | ||
async function copy(src, dest) { | ||
const srcExists = await fs | ||
.access(src) | ||
.then(() => true) | ||
.catch(() => false); | ||
if (srcExists) { | ||
await fs.cp(src, dest, { recursive: true }); | ||
} | ||
return srcExists; | ||
} | ||
|
||
eject(); |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.