Skip to content
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

fix renaming of page files, add handling of symlinked pages #68195

Merged
merged 2 commits into from
Jul 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 15 additions & 16 deletions crates/next-api/src/pages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,25 +104,25 @@ impl PagesProject {
async fn add_page_to_routes(
routes: &mut IndexMap<RcStr, Route>,
page: Vc<PagesStructureItem>,
make_route: impl Fn(Vc<RcStr>, Vc<RcStr>, Vc<FileSystemPath>) -> Route,
make_route: impl Fn(Vc<RcStr>, Vc<RcStr>, Vc<PagesStructureItem>) -> Route,
) -> Result<()> {
let PagesStructureItem {
next_router_path,
project_path,
original_path,
..
} = *page.await?;
let pathname: RcStr = format!("/{}", next_router_path.await?.path).into();
let pathname_vc = Vc::cell(pathname.clone());
let original_name = Vc::cell(format!("/{}", original_path.await?.path).into());
let route = make_route(pathname_vc, original_name, project_path);
let route = make_route(pathname_vc, original_name, page);
routes.insert(pathname, route);
Ok(())
}

async fn add_dir_to_routes(
routes: &mut IndexMap<RcStr, Route>,
dir: Vc<PagesDirectoryStructure>,
make_route: impl Fn(Vc<RcStr>, Vc<RcStr>, Vc<FileSystemPath>) -> Route,
make_route: impl Fn(Vc<RcStr>, Vc<RcStr>, Vc<PagesStructureItem>) -> Route,
) -> Result<()> {
let mut queue = vec![dir];
while let Some(dir) = queue.pop() {
Expand All @@ -143,36 +143,36 @@ impl PagesProject {
}

if let Some(api) = api {
add_dir_to_routes(&mut routes, *api, |pathname, original_name, path| {
add_dir_to_routes(&mut routes, *api, |pathname, original_name, page| {
Route::PageApi {
endpoint: Vc::upcast(PageEndpoint::new(
PageEndpointType::Api,
self,
pathname,
original_name,
path,
page,
pages_structure,
)),
}
})
.await?;
}

let make_page_route = |pathname, original_name, path| Route::Page {
let make_page_route = |pathname, original_name, page| Route::Page {
html_endpoint: Vc::upcast(PageEndpoint::new(
PageEndpointType::Html,
self,
pathname,
original_name,
path,
page,
pages_structure,
)),
data_endpoint: Vc::upcast(PageEndpoint::new(
PageEndpointType::Data,
self,
pathname,
original_name,
path,
page,
pages_structure,
)),
};
Expand All @@ -196,19 +196,18 @@ impl PagesProject {
) -> Result<Vc<Box<dyn Endpoint>>> {
let PagesStructureItem {
next_router_path,
project_path,
original_path,
..
} = *item.await?;
let pathname: RcStr = format!("/{}", next_router_path.await?.path).into();
let pathname_vc = Vc::cell(pathname.clone());
let original_name = Vc::cell(format!("/{}", original_path.await?.path).into());
let path = project_path;
let endpoint = Vc::upcast(PageEndpoint::new(
ty,
self,
pathname_vc,
original_name,
path,
item,
self.pages_structure(),
));
Ok(endpoint)
Expand Down Expand Up @@ -570,7 +569,7 @@ struct PageEndpoint {
pages_project: Vc<PagesProject>,
pathname: Vc<RcStr>,
original_name: Vc<RcStr>,
path: Vc<FileSystemPath>,
page: Vc<PagesStructureItem>,
pages_structure: Vc<PagesStructure>,
}

Expand Down Expand Up @@ -601,15 +600,15 @@ impl PageEndpoint {
pages_project: Vc<PagesProject>,
pathname: Vc<RcStr>,
original_name: Vc<RcStr>,
path: Vc<FileSystemPath>,
page: Vc<PagesStructureItem>,
pages_structure: Vc<PagesStructure>,
) -> Vc<Self> {
PageEndpoint {
ty,
pages_project,
pathname,
original_name,
path,
page,
pages_structure,
}
.cell()
Expand All @@ -618,7 +617,7 @@ impl PageEndpoint {
#[turbo_tasks::function]
async fn source(self: Vc<Self>) -> Result<Vc<Box<dyn Source>>> {
let this = self.await?;
Ok(Vc::upcast(FileSource::new(this.path)))
Ok(Vc::upcast(FileSource::new(this.page.project_path())))
}

#[turbo_tasks::function]
Expand Down
3 changes: 2 additions & 1 deletion crates/next-core/src/app_structure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,8 @@ async fn get_directory_tree_internal(
let mut metadata_twitter = Vec::new();

for (basename, entry) in entries {
match *entry {
let entry = entry.resolve_symlink().await?;
match entry {
DirectoryEntry::File(file) => {
let file = file.resolve().await?;
// Do not process .d.ts files as routes
Expand Down
125 changes: 69 additions & 56 deletions crates/next-core/src/pages_structure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ use crate::next_import_map::get_next_package;
/// A final route in the pages directory.
#[turbo_tasks::value]
pub struct PagesStructureItem {
pub project_path: Vc<FileSystemPath>,
pub base_path: Vc<FileSystemPath>,
pub extensions: Vc<Vec<RcStr>>,
pub fallback_path: Option<Vc<FileSystemPath>>,

/// Pathname of this item in the Next.js router.
pub next_router_path: Vc<FileSystemPath>,
/// Unique path corresponding to this item. This differs from
Expand All @@ -25,18 +28,38 @@ pub struct PagesStructureItem {
impl PagesStructureItem {
#[turbo_tasks::function]
async fn new(
project_path: Vc<FileSystemPath>,
base_path: Vc<FileSystemPath>,
extensions: Vc<Vec<RcStr>>,
fallback_path: Option<Vc<FileSystemPath>>,
next_router_path: Vc<FileSystemPath>,
original_path: Vc<FileSystemPath>,
) -> Result<Vc<Self>> {
Ok(PagesStructureItem {
project_path,
base_path,
extensions,
fallback_path,
next_router_path,
original_path,
}
.cell())
}

#[turbo_tasks::function]
pub async fn project_path(&self) -> Result<Vc<FileSystemPath>> {
for ext in self.extensions.await?.into_iter() {
let project_path = self.base_path.append(format!(".{ext}").into());
let ty = *project_path.get_type().await?;
if matches!(ty, FileSystemEntryType::File | FileSystemEntryType::Symlink) {
return Ok(project_path);
}
}
if let Some(fallback_path) = self.fallback_path {
Ok(fallback_path)
} else {
Ok(self.base_path)
}
}

/// Returns a completion that changes when any route in the whole tree
/// changes.
#[turbo_tasks::function]
Expand All @@ -45,11 +68,6 @@ impl PagesStructureItem {
this.next_router_path.await?;
Ok(Completion::new())
}

#[turbo_tasks::function]
pub fn project_path(&self) -> Vc<FileSystemPath> {
self.project_path
}
}

/// A (sub)directory in the pages directory with all analyzed routes and
Expand Down Expand Up @@ -148,12 +166,20 @@ pub async fn find_pages_structure(
next_router_root: Vc<FileSystemPath>,
page_extensions: Vc<Vec<RcStr>>,
) -> Result<Vc<PagesStructure>> {
let pages_root = project_root.join("pages".into());
let pages_root = project_root
.join("pages".into())
.realpath()
.resolve()
.await?;
let pages_root = Vc::<FileSystemPathOption>::cell(
if *pages_root.get_type().await? == FileSystemEntryType::Directory {
Some(pages_root)
} else {
let src_pages_root = project_root.join("src/pages".into());
let src_pages_root = project_root
.join("src/pages".into())
.realpath()
.resolve()
.await?;
if *src_pages_root.get_type().await? == FileSystemEntryType::Directory {
Some(src_pages_root)
} else {
Expand Down Expand Up @@ -185,61 +211,39 @@ async fn get_pages_structure_for_root_directory(
) -> Result<Vc<PagesStructure>> {
let page_extensions_raw = &*page_extensions.await?;

let mut app_item = None;
let mut document_item = None;
let mut error_item = None;
let mut api_directory = None;

let pages_directory = if let Some(project_path) = &*project_path.await? {
let project_path = project_path.await?;
let pages_directory = if let Some(project_path) = &*project_path {
let mut children = vec![];
let mut items = vec![];

let dir_content = project_path.read_dir().await?;
if let DirectoryContent::Entries(entries) = &*dir_content {
for (name, entry) in entries.iter() {
let entry = entry.resolve_symlink().await?;
match entry {
DirectoryEntry::File(file_project_path) => {
DirectoryEntry::File(_) => {
// Do not process .d.ts files as routes
if name.ends_with(".d.ts") {
continue;
}
let Some(basename) = page_basename(name, page_extensions_raw) else {
continue;
};
let base_path = project_path.join(basename.into());
match basename {
"_app" => {
let item_next_router_path = next_router_path.join("_app".into());
app_item = Some(PagesStructureItem::new(
*file_project_path,
item_next_router_path,
item_next_router_path,
));
}
"_document" => {
let item_next_router_path =
next_router_path.join("_document".into());
document_item = Some(PagesStructureItem::new(
*file_project_path,
item_next_router_path,
item_next_router_path,
));
}
"_error" => {
let item_next_router_path = next_router_path.join("_error".into());
error_item = Some(PagesStructureItem::new(
*file_project_path,
item_next_router_path,
item_next_router_path,
));
}
"_app" | "_document" | "_error" => {}
basename => {
let item_next_router_path =
next_router_path_for_basename(next_router_path, basename);
let item_original_path = next_router_path.join(basename.into());
items.push((
basename,
PagesStructureItem::new(
*file_project_path,
base_path,
page_extensions,
None,
item_next_router_path,
item_original_path,
),
Expand All @@ -250,7 +254,7 @@ async fn get_pages_structure_for_root_directory(
DirectoryEntry::Directory(dir_project_path) => match name.as_str() {
"api" => {
api_directory = Some(get_pages_structure_for_directory(
*dir_project_path,
dir_project_path,
next_router_path.join(name.clone()),
1,
page_extensions,
Expand All @@ -260,7 +264,7 @@ async fn get_pages_structure_for_root_directory(
children.push((
name,
get_pages_structure_for_directory(
*dir_project_path,
dir_project_path,
next_router_path.join(name.clone()),
1,
page_extensions,
Expand Down Expand Up @@ -290,34 +294,40 @@ async fn get_pages_structure_for_root_directory(
None
};

let app_item = if let Some(app_item) = app_item {
app_item
let pages_path = if let Some(project_path) = *project_path {
project_path
} else {
project_root.join("pages".into())
};

let app_item = {
let app_router_path = next_router_path.join("_app".into());
PagesStructureItem::new(
get_next_package(project_root).join("app.js".into()),
pages_path.join("_app".into()),
page_extensions,
Some(get_next_package(project_root).join("app.js".into())),
app_router_path,
app_router_path,
)
};

let document_item = if let Some(document_item) = document_item {
document_item
} else {
let document_item = {
let document_router_path = next_router_path.join("_document".into());
PagesStructureItem::new(
get_next_package(project_root).join("document.js".into()),
pages_path.join("_document".into()),
page_extensions,
Some(get_next_package(project_root).join("document.js".into())),
document_router_path,
document_router_path,
)
};

let error_item = if let Some(error_item) = error_item {
error_item
} else {
let error_item = {
let error_router_path = next_router_path.join("_error".into());
PagesStructureItem::new(
get_next_package(project_root).join("error.js".into()),
pages_path.join("_error".into()),
page_extensions,
Some(get_next_package(project_root).join("error.js".into())),
error_router_path,
error_router_path,
)
Expand Down Expand Up @@ -355,19 +365,22 @@ async fn get_pages_structure_for_directory(
if let DirectoryContent::Entries(entries) = &*dir_content {
for (name, entry) in entries.iter() {
match entry {
DirectoryEntry::File(file_project_path) => {
DirectoryEntry::File(_) => {
let Some(basename) = page_basename(name, page_extensions_raw) else {
continue;
};
let item_next_router_path = match basename {
"index" => next_router_path,
_ => next_router_path.join(basename.into()),
};
let base_path = project_path.join(name.clone());
let item_original_name = next_router_path.join(basename.into());
items.push((
basename,
PagesStructureItem::new(
*file_project_path,
base_path,
page_extensions,
None,
item_next_router_path,
item_original_name,
),
Expand Down
Loading