Migrate to monorepo using Turborepo#17
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughThis PR restructures the codebase into a monorepo using Turborepo and Bun workspaces, relocating the WASM package to Changes
Sequence Diagram(s)sequenceDiagram
actor User
participant Router as TanStack Router
participant FileRouteSync as FileRouteSync
participant FileTreeStore as File Tree Store
participant Share as Share Lib
participant LayeredFS as LayeredFS
participant ShareNotice as ShareNoticeDialog
User->>Router: Click shared link (/?share=encoded)
Router->>FileRouteSync: Route with share param
FileRouteSync->>Share: decodeSharePayload(share)
Share-->>FileRouteSync: FileNode root + openRelativePath
FileRouteSync->>FileTreeStore: loadSharedFiles(root, openRelativePath)
FileTreeStore->>LayeredFS: graftSharedTree(root, openRelativePath)
LayeredFS-->>FileTreeStore: file path to open
FileTreeStore->>FileTreeStore: openFile(path), expandAncestors(path)
FileTreeStore-->>FileRouteSync: active file updated
FileRouteSync->>ShareNotice: show()
ShareNotice-->>User: "This is a temporary shared file"
sequenceDiagram
actor User
participant Sidebar as App Sidebar
participant Dialog as File Tree Dialog
participant PathUtils as Path Utils
participant FileTreeStore as File Tree Store
participant FS as FileSystem
User->>Sidebar: Right-click shared file → Fork
Sidebar->>PathUtils: getForkTargetPath(sharedPath, newName)
PathUtils-->>Sidebar: localDestPath
Sidebar->>FS: stat(localDestPath)
alt Destination exists
FS-->>Sidebar: exists
Sidebar->>Dialog: open fork-file dialog
User->>Dialog: Confirm/rename
else Destination doesn't exist
FS-->>Sidebar: not found
Sidebar->>FileTreeStore: renameFile(sharedPath, localDestPath)
end
FileTreeStore->>FileTreeStore: expandDir(parent)
FileTreeStore-->>User: File forked to local
Estimated code review effort🎯 4 (Complex) | ⏱️ ~75 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 4❌ Failed checks (2 warnings, 2 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (1)
apps/web/package.json (1)
8-8: Cross-platform compatibility:cpcommand won't work on Windows.The
copy:wasmscript uses the Unixcpcommand, which will fail on Windows systems. Consider using a cross-platform solution.♻️ Suggested alternatives
Option 1: Use Node.js built-in
fs.cpvia a one-liner:- "copy:wasm": "cp ../../packages/wasm/dist/ballerina.wasm public/ballerina.wasm" + "copy:wasm": "node -e \"require('fs').cpSync('../../packages/wasm/dist/ballerina.wasm', 'public/ballerina.wasm')\""Option 2: Use
shxpackage for cross-platform shell commands:- "copy:wasm": "cp ../../packages/wasm/dist/ballerina.wasm public/ballerina.wasm" + "copy:wasm": "shx cp ../../packages/wasm/dist/ballerina.wasm public/ballerina.wasm"🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/web/package.json` at line 8, The npm script "copy:wasm" in package.json uses the Unix-only `cp` command which breaks on Windows; replace it with a cross-platform approach by either (a) changing the script to run a Node one-liner that uses fs.cp/fs.copyFile (e.g., a small node -e script) to copy ../../packages/wasm/dist/ballerina.wasm to public/ballerina.wasm, or (b) add a devDependency like "shx" or "cpy-cli" and update "copy:wasm" to use the cross-platform command provided by that package; update package.json's "copy:wasm" script accordingly and add the chosen package to devDependencies if needed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/web/biome.json`:
- Around line 4-13: The files.includes negation patterns use double-bang
prefixes (e.g., "!!**/dist", "!!src/main.tsx", "!!src/assets/**/*",
"!!src/wasm_exec.js", "!!src/types/wasm-types.d.ts", "!!**/routeTree.gen.ts")
but Biome expects single '!' negation; update the entries under files.includes
to use single '!' (e.g., "!**/dist", "!src/main.tsx", "!src/assets/**/*",
"!src/wasm_exec.js", "!src/types/wasm-types.d.ts", "!**/routeTree.gen.ts") and
for directory exclusions prefer the simpler "!dist" form where applicable to
improve performance.
In `@package.json`:
- Line 15: The root package.json "preview" script currently runs "vite preview"
but will fail because Vite config isn't at the repo root; remove or replace the
root "preview" script and instead add a "preview" script with the same command
to the web app's package.json (the package.json for the web app that contains
the vite.config), then register a "preview" pipeline entry in turbo.json so the
root task delegates to the app's preview task; update the root package.json to
either call turbo run preview or remove the invalid script.
In `@packages/wasm/package.json`:
- Around line 5-6: The build script fails when dist is missing because "clean"
deletes it and "build" (the npm script named build) invokes go build -o
dist/ballerina.wasm without creating the parent directory; update the build
script (the "build" npm script) to ensure the dist directory exists before
running go build (e.g., create the directory with mkdir -p dist or equivalent)
so go build can write dist/ballerina.wasm even on a clean workspace.
---
Nitpick comments:
In `@apps/web/package.json`:
- Line 8: The npm script "copy:wasm" in package.json uses the Unix-only `cp`
command which breaks on Windows; replace it with a cross-platform approach by
either (a) changing the script to run a Node one-liner that uses
fs.cp/fs.copyFile (e.g., a small node -e script) to copy
../../packages/wasm/dist/ballerina.wasm to public/ballerina.wasm, or (b) add a
devDependency like "shx" or "cpy-cli" and update "copy:wasm" to use the
cross-platform command provided by that package; update package.json's
"copy:wasm" script accordingly and add the chosen package to devDependencies if
needed.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 82cdc2c5-c559-4984-926f-f623e4563a9d
⛔ Files ignored due to path filters (3)
apps/web/public/ballerina.svgis excluded by!**/*.svgbun.lockis excluded by!**/*.lockpackages/wasm/go.sumis excluded by!**/*.sum
📒 Files selected for processing (63)
.gitignore.gitmodulesapps/web/.gitignoreapps/web/biome.jsonapps/web/components.jsonapps/web/index.htmlapps/web/package.jsonapps/web/src/assets/examples.jsonapps/web/src/components/ansi.tsxapps/web/src/components/app-sidebar.tsxapps/web/src/components/code-editor.tsxapps/web/src/components/editor.tsxapps/web/src/components/file-route-sync.tsxapps/web/src/components/file-tree-dialog.tsxapps/web/src/components/ui/button.tsxapps/web/src/components/ui/collapsible.tsxapps/web/src/components/ui/dialog.tsxapps/web/src/components/ui/dropdown-menu.tsxapps/web/src/components/ui/input.tsxapps/web/src/components/ui/progress.tsxapps/web/src/components/ui/separator.tsxapps/web/src/components/ui/sheet.tsxapps/web/src/components/ui/sidebar.tsxapps/web/src/components/ui/skeleton.tsxapps/web/src/components/ui/tooltip.tsxapps/web/src/hooks/use-ballerina.tsapps/web/src/hooks/use-mobile.tsapps/web/src/lib/fs/core/abstract-fs.tsapps/web/src/lib/fs/core/file-node.types.tsapps/web/src/lib/fs/core/fs.interface.tsapps/web/src/lib/fs/core/path-utils.tsapps/web/src/lib/fs/ephemeral-fs.tsapps/web/src/lib/fs/layered-fs.tsapps/web/src/lib/fs/local-storage-fs.tsapps/web/src/lib/router-utils.tsapps/web/src/lib/utils.tsapps/web/src/main.tsxapps/web/src/providers/fs-provider.tsxapps/web/src/routeTree.gen.tsapps/web/src/routes/$.tsxapps/web/src/routes/__root.tsxapps/web/src/stores/editor-store.tsapps/web/src/stores/file-tree-store.tsapps/web/src/styles.cssapps/web/src/types/wasm-types.d.tsapps/web/src/wasm_exec.jsapps/web/tsconfig.app.jsonapps/web/tsconfig.jsonapps/web/tsconfig.node.jsonapps/web/turbo.jsonapps/web/vite.config.tsbiome.jsonpackage.jsonpackages/wasm/.gitignorepackages/wasm/ballerina-lang-gopackages/wasm/biome.jsonpackages/wasm/diagnostics_printer.gopackages/wasm/go.modpackages/wasm/local_storage_fs.gopackages/wasm/main_wasm.gopackages/wasm/package.jsonpackages/wasm/turbo.jsonturbo.json
💤 Files with no reviewable changes (1)
- biome.json
01542b2 to
d1c650d
Compare
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (11)
apps/web/src/styles.css (1)
154-159: Prefer CSS inheritance over*selector forfont-family.Applying
font-sansvia the universal selector (*) directly sets the font on every element in the DOM, bypassing CSS inheritance. Sincebodyon line 158 already appliesfont-sans, child elements will naturally inherit this value.Using
*for inheritable properties likefont-familyis less efficient and can interfere with elements that intentionally use different fonts (browser defaults for<code>,<textarea>, etc.).Consider removing
font-sansfrom the*rule and relying on inheritance frombody:♻️ Suggested change
`@layer` base { * { - `@apply` border-border outline-ring/50 font-sans; + `@apply` border-border outline-ring/50; } body { `@apply` font-sans bg-background text-foreground; } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/web/src/styles.css` around lines 154 - 159, Remove the font-sans utility from the universal selector and rely on inheritance from the body rule: edit the "* { ... }" rule so it no longer applies font-sans (keep non-inheritable utilities like border-border and outline-ring/50), and ensure the "body { `@apply` font-sans ... }" rule remains as the single source for the font-family so child elements inherit it naturally.apps/web/src/components/ui/sonner.tsx (1)
14-19: Type cast for theme is acceptable but could be more defensive.The cast
theme as ToasterProps["theme"]works whennext-themesreturns standard values ("light","dark","system"), but custom theme names would pass through unchecked. This is low-risk since the app likely uses standard themes, but you could add validation if custom themes are supported.Optional: Add theme validation
const Toaster = ({ ...props }: ToasterProps) => { const { theme = "system" } = useTheme(); + const sonnerTheme: ToasterProps["theme"] = + theme === "light" || theme === "dark" ? theme : "system"; return ( <Sonner - theme={theme as ToasterProps["theme"]} + theme={sonnerTheme}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/web/src/components/ui/sonner.tsx` around lines 14 - 19, The Toaster component currently force-casts the value from useTheme into ToasterProps["theme"]; make this defensive by validating the theme returned by useTheme() before passing it to Sonner: inside Toaster, read const { theme } = useTheme(); check that theme is one of the allowed values ("light", "dark", "system") (or your app's supported theme names) and if not, set a safe fallback (e.g., "system" or the ToasterProps default), then pass that validated value to Sonner (still respecting ToasterProps["theme"]). This ensures Toaster, useTheme, Sonner and the ToasterProps["theme"] cast are safe without relying on unchecked values.apps/web/src/lib/fs/core/file-node-utils.ts (1)
38-48: Missing blank line before function declaration.Line 39 starts
getRelativePathInTreeimmediately after the closing brace oftoFileNode. Adding a blank line between functions improves readability.♻️ Add blank line
return { kind: "dir", name, children }; } + export function getRelativePathInTree(🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/web/src/lib/fs/core/file-node-utils.ts` around lines 38 - 48, Add a blank line between the end of the toFileNode function and the start of getRelativePathInTree to improve readability; specifically, insert one empty line before the "export function getRelativePathInTree(...)" declaration so it is separated from the previous closing brace.apps/web/src/components/share-notice-dialog.tsx (1)
51-56: Dialogkeyprop forces remount on every open/close cycle.Using
key={String(open)}causes React to unmount and remount theDialogcomponent wheneveropenchanges. This resets thepermanentcheckbox state tofalseeach time the dialog reopens, which appears intentional. However, this also destroys any enter/exit animations managed by the Dialog's internal state.If the checkbox reset is the goal, consider explicitly resetting the
permanentstate in auseEffector callback instead of relying on remounting.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/web/src/components/share-notice-dialog.tsx` around lines 51 - 56, The Dialog is being forced to remount via key={String(open)}, which breaks enter/exit animations; instead remove the key prop from the <Dialog> usage and explicitly reset the permanent checkbox state (the state variable controlling the checkbox) when the dialog closes or opens — e.g., in handleDismiss or a useEffect watching open, setPermanent(false) (or desired default) so the checkbox is reset without remounting; update references in the component to rely on Dialog's open prop and onOpenChange for lifecycle rather than the key.apps/web/src/components/file-route-sync.tsx (1)
46-79: Potential staleactiveFilePathRefread in effect.The effect at lines 53-79 reads
activeFilePathRef.current(line 56) but doesn't includeactiveFilePathin its dependency array. While this is intentional to avoid re-running on everyactiveFilePathchange, it means the effect may compare against a stale value whenfilePathFromUrlchanges.This should be safe in practice because the second effect (lines 81-92) handles
activeFilePathchanges separately. However, consider adding a brief comment explaining whyactiveFilePathis deliberately excluded from dependencies to clarify the intent for future maintainers.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/web/src/components/file-route-sync.tsx` around lines 46 - 79, The effect that reads activeFilePathRef.current inside the React.useEffect (the effect that checks filePathFromUrl, clearedByDeletionRef, and opens DEFAULT_FILE) intentionally omits activeFilePath from its dependency array to avoid re-running on every file switch; add a concise inline comment above the useEffect (and/or above activeFilePathRef/useLayoutEffect) explaining that activeFilePath is intentionally excluded because activeFilePathRef is kept up-to-date via useLayoutEffect and another effect handles activeFilePath changes, so this effect only reacts to ready, isProcessingShare, filePathFromUrl, existsFile, openFile, and navigate changes to avoid unnecessary re-renders.apps/web/src/lib/fs/layered-fs.ts (1)
72-74: Inconsistent use ofLOCAL_ROOTconstant.Line 69 uses
TEMP_ROOTconstant fortempTree(), but line 73 uses hardcoded"/local"forlocalTree(). For consistency, use the importedLOCAL_ROOTconstant.♻️ Use LOCAL_ROOT constant
localTree() { - return this.local.transformToTree("/local"); + return this.local.transformToTree(LOCAL_ROOT); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/web/src/lib/fs/layered-fs.ts` around lines 72 - 74, The localTree method uses a hardcoded string "/local" instead of the shared constant; update localTree() to call this.local.transformToTree(LOCAL_ROOT) using the imported LOCAL_ROOT (matching tempTree() which uses TEMP_ROOT) so both methods consistently rely on the same root constants (verify LOCAL_ROOT is imported at top if missing).apps/web/src/hooks/use-share.ts (1)
72-77:isProcessingSharereads ref during render, which may cause inconsistency.
isProcessingShareis computed by readingprocessed.currentduring the render phase (line 72). Sinceprocessed.currentis mutated asynchronously inside the effect, this can lead to inconsistent values between renders in React's concurrent mode—the ref might update after the component yields but before it commits.However, based on the context snippets showing how
FileRouteSyncuses this value, the practical impact is minimal since the guard only delays URL synchronization briefly. The current implementation appears safe for this use case.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/web/src/hooks/use-share.ts` around lines 72 - 77, isProcessingShare currently reads processed.current during render which can be inconsistent; replace this with a React state updated inside an effect: add a new useState (e.g. isProcessingShareState), initialize appropriately, then in the existing effect that mutates processed.current (or a new effect that depends on share) read processed.current and call setIsProcessingShare(processed.current !== share); finally return isProcessingShareState instead of the direct computed isProcessingShare. Reference symbols: isProcessingShare, processed.current, share, and the use-share hook.apps/web/src/components/app-sidebar.tsx (1)
433-440: Shared entries rendered under "Localspace" section.The
sharedEntriesare rendered within the "Localspace"SidebarGroup(lines 402-457). This may confuse users since shared files are temporary (stored in/tmp/shared) but appear alongside persistent local files.Consider whether shared entries should have their own labeled section or a visual separator to distinguish them from true local files.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/web/src/components/app-sidebar.tsx` around lines 433 - 440, The sharedEntries are being rendered inside the same SidebarGroup as local files causing UX confusion; update the sidebar to render sharedEntries in their own labeled group or visually separated section instead of inside the existing localspace SidebarGroup. Locate the mapping that renders sharedEntries into FileTreeNode (symbols: sharedEntries, FileTreeNode, isActiveOrAncestor, activeFilePath) and move that block out of the current SidebarGroup so it becomes a separate SidebarGroup (or add a divider and a label like "Shared" / "Temporary") and ensure the defaultOpen logic still uses isActiveOrAncestor(activeFilePath) for correct expansion.apps/web/src/lib/file-tree-utils.ts (1)
18-22: Minor: Redundantkindcheck afterfind.Line 19 finds a node where
n.kind === "dir", then line 20 checksdir.kind !== "dir"again. The second check is redundant sincefindalready ensureskind === "dir".This is harmless but could be simplified:
♻️ Simplified check
for (const seg of segments) { const dir = nodes.find((n) => n.kind === "dir" && n.name === seg); - if (!dir || dir.kind !== "dir") return { entries: [], basePath: rootPath }; + if (!dir) return { entries: [], basePath: rootPath }; nodes = dir.children ?? []; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/web/src/lib/file-tree-utils.ts` around lines 18 - 22, The loop currently does a redundant kind check: after finding dir with nodes.find((n) => n.kind === "dir" && n.name === seg) you again check dir.kind !== "dir"; remove the redundant check and simplify to: if (!dir) return { entries: [], basePath: rootPath }; then continue setting nodes = dir.children ?? []; Update the loop body referencing variables segments, nodes, dir, and rootPath accordingly.apps/web/src/lib/share.ts (1)
53-66: Consider adding a depth limit to prevent stack overflow on malicious payloads.The recursive validation has no depth bound. While typical file trees are shallow, a crafted payload with thousands of nested directories could exhaust the call stack during validation.
♻️ Suggested depth-limited validation
-function isFileNode(value: unknown): value is FileNode { +function isFileNode(value: unknown, depth = 0): value is FileNode { + if (depth > 100) return false; if (!value || typeof value !== "object") return false; const o = value as Record<string, unknown>; if (o.kind === "file") return isSafeNodeName(o.name) && typeof o.content === "string"; if (o.kind === "dir") { return ( isSafeNodeName(o.name) && Array.isArray(o.children) && - o.children.every(isFileNode) + o.children.every((c) => isFileNode(c, depth + 1)) ); } return false; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/web/src/lib/share.ts` around lines 53 - 66, The recursive validator is unbounded and can overflow the stack; update isFileNode to accept an optional depth/count parameter and enforce a MAX_DEPTH constant (e.g., 1000) so validation returns false when depth exceeds the limit. Modify all recursive calls (the children.every(...) invocation) to pass depth+1 and update the function signature (isFileNode(value: unknown, depth = 0): value is FileNode) and use isSafeNodeName and typeof checks unchanged; alternatively implement an iterative stack-based traversal within isFileNode that tracks depth per node and aborts when depth > MAX_DEPTH to prevent maliciously deep trees from causing stack overflow.apps/web/src/lib/fs/core/path-utils.ts (1)
43-47:isSafeRelativePathaccepts absolute paths (starting with/), creating semantic mismatch with its name.Due to
pathSegmentsfiltering empty strings, a path like/foo/barpasses validation and becomes["foo", "bar"]. While thejoin()function safely handles this (flattening all segments uniformly), allowing absolute paths in a function named "isSafeRelativePath" is misleading and poor API design. Explicitly rejecting leading slashes would clarify intent:♻️ Suggested fix to reject absolute paths
export function isSafeRelativePath(path: string): boolean { const trimmed = path.trim(); if (!trimmed) return false; + if (trimmed.startsWith("/")) return false; return pathSegments(trimmed).every((s) => s !== "." && s !== ".."); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/web/src/lib/fs/core/path-utils.ts` around lines 43 - 47, isSafeRelativePath currently accepts absolute paths because pathSegments strips empty segments, so update isSafeRelativePath to explicitly reject leading path separators before calling pathSegments: check the trimmed string for a leading '/' or '\\' (or any platform-specific root indicator) and return false if present, then proceed to call pathSegments(trimmed) and validate segments as before; reference the isSafeRelativePath function and pathSegments helper when making this change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/web/src/components/app-sidebar.tsx`:
- Around line 149-169: The fork action silently fails when renameFile(path,
dest) returns false (in the file sidebar fork branch using renameFile,
sharedToLocalDestination, exists, expandDir, setFileOperationDialog); update
that onClick handler to detect a false return and display a user-facing error
notification/toast (e.g., "Failed to fork <basename(path)>") including the path
or error context, and apply the same change to the corresponding folder fork
branch around the other block handling folders so both file and folder rename
failures surface clear feedback to the user.
In `@apps/web/src/lib/share.ts`:
- Around line 68-75: encodeSharePayload currently JSON.stringify's the full
FileNode payload (produced by toFileNode) without any size or depth safeguards,
risking large-memory use and oversized share URLs; before calling
compressAndEncode, compute the approximate payload size (e.g., JSON.stringify
length or a byte-size estimate) and enforce a configurable max (or return a
user-friendly error) and/or limit tree depth/entry count inside toFileNode (add
parameters like maxDepth/maxNodes) so the FileNode produced is bounded; if the
payload exceeds the limit, fail early with a clear error from encodeSharePayload
mentioning compressAndEncode and FileNode so callers can handle it.
In `@apps/web/src/routes/__root.tsx`:
- Line 12: The ThemeProvider is rendered without props so dark-mode Tailwind
`.dark` class variant never activates; update the ThemeProvider component (look
for the ThemeProvider instantiation in __root.tsx) to pass attribute="class" and
also include defaultTheme and enableSystem props (e.g., defaultTheme="system"
and enableSystem={true}) so the library uses a .dark class for styling and
provides sensible defaults and system-aware behavior.
---
Nitpick comments:
In `@apps/web/src/components/app-sidebar.tsx`:
- Around line 433-440: The sharedEntries are being rendered inside the same
SidebarGroup as local files causing UX confusion; update the sidebar to render
sharedEntries in their own labeled group or visually separated section instead
of inside the existing localspace SidebarGroup. Locate the mapping that renders
sharedEntries into FileTreeNode (symbols: sharedEntries, FileTreeNode,
isActiveOrAncestor, activeFilePath) and move that block out of the current
SidebarGroup so it becomes a separate SidebarGroup (or add a divider and a label
like "Shared" / "Temporary") and ensure the defaultOpen logic still uses
isActiveOrAncestor(activeFilePath) for correct expansion.
In `@apps/web/src/components/file-route-sync.tsx`:
- Around line 46-79: The effect that reads activeFilePathRef.current inside the
React.useEffect (the effect that checks filePathFromUrl, clearedByDeletionRef,
and opens DEFAULT_FILE) intentionally omits activeFilePath from its dependency
array to avoid re-running on every file switch; add a concise inline comment
above the useEffect (and/or above activeFilePathRef/useLayoutEffect) explaining
that activeFilePath is intentionally excluded because activeFilePathRef is kept
up-to-date via useLayoutEffect and another effect handles activeFilePath
changes, so this effect only reacts to ready, isProcessingShare,
filePathFromUrl, existsFile, openFile, and navigate changes to avoid unnecessary
re-renders.
In `@apps/web/src/components/share-notice-dialog.tsx`:
- Around line 51-56: The Dialog is being forced to remount via
key={String(open)}, which breaks enter/exit animations; instead remove the key
prop from the <Dialog> usage and explicitly reset the permanent checkbox state
(the state variable controlling the checkbox) when the dialog closes or opens —
e.g., in handleDismiss or a useEffect watching open, setPermanent(false) (or
desired default) so the checkbox is reset without remounting; update references
in the component to rely on Dialog's open prop and onOpenChange for lifecycle
rather than the key.
In `@apps/web/src/components/ui/sonner.tsx`:
- Around line 14-19: The Toaster component currently force-casts the value from
useTheme into ToasterProps["theme"]; make this defensive by validating the theme
returned by useTheme() before passing it to Sonner: inside Toaster, read const {
theme } = useTheme(); check that theme is one of the allowed values ("light",
"dark", "system") (or your app's supported theme names) and if not, set a safe
fallback (e.g., "system" or the ToasterProps default), then pass that validated
value to Sonner (still respecting ToasterProps["theme"]). This ensures Toaster,
useTheme, Sonner and the ToasterProps["theme"] cast are safe without relying on
unchecked values.
In `@apps/web/src/hooks/use-share.ts`:
- Around line 72-77: isProcessingShare currently reads processed.current during
render which can be inconsistent; replace this with a React state updated inside
an effect: add a new useState (e.g. isProcessingShareState), initialize
appropriately, then in the existing effect that mutates processed.current (or a
new effect that depends on share) read processed.current and call
setIsProcessingShare(processed.current !== share); finally return
isProcessingShareState instead of the direct computed isProcessingShare.
Reference symbols: isProcessingShare, processed.current, share, and the
use-share hook.
In `@apps/web/src/lib/file-tree-utils.ts`:
- Around line 18-22: The loop currently does a redundant kind check: after
finding dir with nodes.find((n) => n.kind === "dir" && n.name === seg) you again
check dir.kind !== "dir"; remove the redundant check and simplify to: if (!dir)
return { entries: [], basePath: rootPath }; then continue setting nodes =
dir.children ?? []; Update the loop body referencing variables segments, nodes,
dir, and rootPath accordingly.
In `@apps/web/src/lib/fs/core/file-node-utils.ts`:
- Around line 38-48: Add a blank line between the end of the toFileNode function
and the start of getRelativePathInTree to improve readability; specifically,
insert one empty line before the "export function getRelativePathInTree(...)"
declaration so it is separated from the previous closing brace.
In `@apps/web/src/lib/fs/core/path-utils.ts`:
- Around line 43-47: isSafeRelativePath currently accepts absolute paths because
pathSegments strips empty segments, so update isSafeRelativePath to explicitly
reject leading path separators before calling pathSegments: check the trimmed
string for a leading '/' or '\\' (or any platform-specific root indicator) and
return false if present, then proceed to call pathSegments(trimmed) and validate
segments as before; reference the isSafeRelativePath function and pathSegments
helper when making this change.
In `@apps/web/src/lib/fs/layered-fs.ts`:
- Around line 72-74: The localTree method uses a hardcoded string "/local"
instead of the shared constant; update localTree() to call
this.local.transformToTree(LOCAL_ROOT) using the imported LOCAL_ROOT (matching
tempTree() which uses TEMP_ROOT) so both methods consistently rely on the same
root constants (verify LOCAL_ROOT is imported at top if missing).
In `@apps/web/src/lib/share.ts`:
- Around line 53-66: The recursive validator is unbounded and can overflow the
stack; update isFileNode to accept an optional depth/count parameter and enforce
a MAX_DEPTH constant (e.g., 1000) so validation returns false when depth exceeds
the limit. Modify all recursive calls (the children.every(...) invocation) to
pass depth+1 and update the function signature (isFileNode(value: unknown, depth
= 0): value is FileNode) and use isSafeNodeName and typeof checks unchanged;
alternatively implement an iterative stack-based traversal within isFileNode
that tracks depth per node and aborts when depth > MAX_DEPTH to prevent
maliciously deep trees from causing stack overflow.
In `@apps/web/src/styles.css`:
- Around line 154-159: Remove the font-sans utility from the universal selector
and rely on inheritance from the body rule: edit the "* { ... }" rule so it no
longer applies font-sans (keep non-inheritable utilities like border-border and
outline-ring/50), and ensure the "body { `@apply` font-sans ... }" rule remains as
the single source for the font-family so child elements inherit it naturally.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: d967fa22-4ecb-47e4-b3df-24ba666b507c
⛔ Files ignored due to path filters (3)
apps/web/public/ballerina.svgis excluded by!**/*.svgbun.lockis excluded by!**/*.lockpackages/wasm/go.sumis excluded by!**/*.sum
📒 Files selected for processing (80)
.github/workflows/ci.yml.github/workflows/deploy.yml.gitignore.gitmodulesapps/web/.gitignoreapps/web/biome.jsonapps/web/components.jsonapps/web/index.htmlapps/web/package.jsonapps/web/src/assets/examples.jsonapps/web/src/components/ansi.tsxapps/web/src/components/app-sidebar.tsxapps/web/src/components/code-editor.tsxapps/web/src/components/editor.tsxapps/web/src/components/file-route-sync.tsxapps/web/src/components/file-tree-dialog.tsxapps/web/src/components/share-notice-dialog.tsxapps/web/src/components/ui/button.tsxapps/web/src/components/ui/checkbox.tsxapps/web/src/components/ui/collapsible.tsxapps/web/src/components/ui/dialog.tsxapps/web/src/components/ui/dropdown-menu.tsxapps/web/src/components/ui/input.tsxapps/web/src/components/ui/progress.tsxapps/web/src/components/ui/separator.tsxapps/web/src/components/ui/sheet.tsxapps/web/src/components/ui/sidebar.tsxapps/web/src/components/ui/skeleton.tsxapps/web/src/components/ui/sonner.tsxapps/web/src/components/ui/tooltip.tsxapps/web/src/hooks/use-ballerina.tsapps/web/src/hooks/use-copy-share-link.tsapps/web/src/hooks/use-mobile.tsapps/web/src/hooks/use-share-notice.tsapps/web/src/hooks/use-share.tsapps/web/src/lib/file-tree-utils.tsapps/web/src/lib/fs/core/abstract-fs.tsapps/web/src/lib/fs/core/file-node-utils.tsapps/web/src/lib/fs/core/file-node.types.tsapps/web/src/lib/fs/core/fs.interface.tsapps/web/src/lib/fs/core/path-utils.tsapps/web/src/lib/fs/ephemeral-fs.tsapps/web/src/lib/fs/fs-roots.tsapps/web/src/lib/fs/layered-fs.tsapps/web/src/lib/fs/local-storage-fs.tsapps/web/src/lib/router-utils.tsapps/web/src/lib/share.tsapps/web/src/lib/utils.tsapps/web/src/main.tsxapps/web/src/providers/fs-provider.tsxapps/web/src/routeTree.gen.tsapps/web/src/routes/$.tsxapps/web/src/routes/__root.tsxapps/web/src/stores/editor-store.tsapps/web/src/stores/file-tree-store.tsapps/web/src/styles.cssapps/web/src/types/wasm-types.d.tsapps/web/src/wasm_exec.jsapps/web/tsconfig.app.jsonapps/web/tsconfig.jsonapps/web/tsconfig.node.jsonapps/web/turbo.jsonapps/web/vite.config.tsbiome.jsonpackage.jsonpackages/wasm/.gitignorepackages/wasm/ballerina-lang-gopackages/wasm/biome.jsonpackages/wasm/diagnostics_printer.gopackages/wasm/go.modpackages/wasm/local_storage_fs.gopackages/wasm/main_wasm.gopackages/wasm/package.jsonpackages/wasm/turbo.jsonscripts/example_gen/main.goturbo.jsonweb/src/assets/examples.jsonweb/src/components/file-route-sync.tsxweb/src/lib/fs/core/path-utils.tsweb/src/routes/__root.tsx
💤 Files with no reviewable changes (5)
- biome.json
- web/src/routes/__root.tsx
- web/src/assets/examples.json
- web/src/components/file-route-sync.tsx
- web/src/lib/fs/core/path-utils.ts
✅ Files skipped from review due to trivial changes (10)
- apps/web/src/main.tsx
- packages/wasm/.gitignore
- turbo.json
- packages/wasm/package.json
- apps/web/turbo.json
- packages/wasm/turbo.json
- .gitmodules
- packages/wasm/biome.json
- apps/web/biome.json
- apps/web/src/assets/examples.json
🚧 Files skipped from review as they are similar to previous changes (3)
- .gitignore
- package.json
- apps/web/package.json
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/web/src/components/file-tree-dialog.tsx (1)
179-181:⚠️ Potential issue | 🟡 MinorDisable submit when
targetPathis invalid.For fork flows,
getForkTargetPathcan returnnull(e.g.,"."/".."), but the button can still be enabled at Line 179–Line 181, then submission silently returns at Line 203. Include!targetPathin the non-delete disable condition.Suggested fix
const isActionDisabled = isDelete ? false - : !name.trim() || hasPathSeparator || alreadyExists || isSamePath; + : !name.trim() || + hasPathSeparator || + !targetPath || + alreadyExists || + isSamePath;Also applies to: 203-203
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/web/src/components/file-tree-dialog.tsx` around lines 179 - 181, The current isActionDisabled ternary (involving isDelete, name, hasPathSeparator, alreadyExists, isSamePath) does not account for a null/invalid targetPath from getForkTargetPath, allowing the submit button to be enabled but submission to early-return; update the non-delete disable condition to include !targetPath (i.e., add a check for targetPath falsiness alongside !name.trim(), hasPathSeparator, alreadyExists, isSamePath) and also ensure the submit handler (the function that early-returns when targetPath is falsy) stays consistent with this guard so the button is disabled whenever targetPath is null.
🧹 Nitpick comments (2)
apps/web/src/lib/fs/layered-fs.ts (1)
68-74: Inconsistent use of constants.
tempTree()correctly uses theTEMP_ROOTconstant, butlocalTree()still uses a hardcoded"/local"string. For consistency and maintainability, useLOCAL_ROOThere as well.♻️ Suggested fix
localTree() { - return this.local.transformToTree("/local"); + return this.local.transformToTree(LOCAL_ROOT); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/web/src/lib/fs/layered-fs.ts` around lines 68 - 74, The localTree() method uses a hardcoded "/local" string instead of the LOCAL_ROOT constant; change localTree() to call this.local.transformToTree(LOCAL_ROOT) (mirroring tempTree() which uses TEMP_ROOT) so both methods consistently reference their respective root constants and avoid magic strings; update any imports/exports if LOCAL_ROOT is not yet available in layered-fs.ts and run tests.apps/web/src/hooks/use-share.ts (1)
53-62: Dead code:loadedis alwaystrueper currentloadSharedFilesimplementation.Based on the store implementation in
file-tree-store.ts(lines 299-309),loadSharedFilesalways returns{ loaded: true, openPath: ... }. The check at line 58 (if (!loaded)) and its toast message will never execute.Consider either:
- Simplifying by removing the
loadedcheck if failure isn't possible, or- Updating
loadSharedFilesto actually returnloaded: falseon failure if that's the intended contract.Option 1: Simplify by removing dead code
- const { loaded, openPath } = loadSharedFiles( + const { openPath } = loadSharedFiles( payload.root, payload.openRelativePath, ); - processed.current = loaded ? share : null; - if (!loaded) toast.error("Could not load shared files"); - else { - if (openPath !== null) openFile(openPath); - showNotice(); - } + processed.current = share; + if (openPath !== null) openFile(openPath); + showNotice();🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/web/src/hooks/use-share.ts` around lines 53 - 62, Remove the dead-path that checks the always-true `loaded` value: set `processed.current = share` unconditionally, remove the `if (!loaded) toast.error("Could not load shared files")` branch, and keep the existing handling for `openPath` and `showNotice` (i.e. call `openFile(openPath)` when `openPath !== null` and then `showNotice()`). Update the block around the `loadSharedFiles` call so you still destructure `{ loaded, openPath }` if desired but do not branch on `loaded`; leave callers/functions `loadSharedFiles`, `openFile`, `showNotice`, `processed.current`, and `share` unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/web/src/components/file-tree-dialog.tsx`:
- Around line 219-223: The fork handlers ("fork-file" and "fork-folder")
incorrectly call renameFile(path, targetPath) which uses LayeredFS.move()
(copy-then-remove) and thus deletes the shared source; change the handlers to
perform a copy-only operation instead: add or use a copy helper (e.g., implement
copyFile/copyFolder or LayeredFS.copy that duplicates content into the local
layer without removing the original) and call that from the fork handlers in
file-tree-dialog.tsx (and similarly in app-sidebar.tsx where renameFile is used
for forks); after the copy succeeds still call expandDir(dirname(targetPath)) to
update the UI.
---
Outside diff comments:
In `@apps/web/src/components/file-tree-dialog.tsx`:
- Around line 179-181: The current isActionDisabled ternary (involving isDelete,
name, hasPathSeparator, alreadyExists, isSamePath) does not account for a
null/invalid targetPath from getForkTargetPath, allowing the submit button to be
enabled but submission to early-return; update the non-delete disable condition
to include !targetPath (i.e., add a check for targetPath falsiness alongside
!name.trim(), hasPathSeparator, alreadyExists, isSamePath) and also ensure the
submit handler (the function that early-returns when targetPath is falsy) stays
consistent with this guard so the button is disabled whenever targetPath is
null.
---
Nitpick comments:
In `@apps/web/src/hooks/use-share.ts`:
- Around line 53-62: Remove the dead-path that checks the always-true `loaded`
value: set `processed.current = share` unconditionally, remove the `if (!loaded)
toast.error("Could not load shared files")` branch, and keep the existing
handling for `openPath` and `showNotice` (i.e. call `openFile(openPath)` when
`openPath !== null` and then `showNotice()`). Update the block around the
`loadSharedFiles` call so you still destructure `{ loaded, openPath }` if
desired but do not branch on `loaded`; leave callers/functions
`loadSharedFiles`, `openFile`, `showNotice`, `processed.current`, and `share`
unchanged.
In `@apps/web/src/lib/fs/layered-fs.ts`:
- Around line 68-74: The localTree() method uses a hardcoded "/local" string
instead of the LOCAL_ROOT constant; change localTree() to call
this.local.transformToTree(LOCAL_ROOT) (mirroring tempTree() which uses
TEMP_ROOT) so both methods consistently reference their respective root
constants and avoid magic strings; update any imports/exports if LOCAL_ROOT is
not yet available in layered-fs.ts and run tests.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 747fe616-ae1e-4185-8f66-a97db84562b1
⛔ Files ignored due to path filters (3)
apps/web/public/ballerina.svgis excluded by!**/*.svgbun.lockis excluded by!**/*.lockpackages/wasm/go.sumis excluded by!**/*.sum
📒 Files selected for processing (76)
.github/workflows/ci.yml.github/workflows/deploy.yml.gitignore.gitmodulesapps/web/.gitignoreapps/web/biome.jsonapps/web/components.jsonapps/web/index.htmlapps/web/package.jsonapps/web/src/assets/examples.jsonapps/web/src/components/ansi.tsxapps/web/src/components/app-sidebar.tsxapps/web/src/components/code-editor.tsxapps/web/src/components/editor.tsxapps/web/src/components/file-route-sync.tsxapps/web/src/components/file-tree-dialog.tsxapps/web/src/components/share-notice-dialog.tsxapps/web/src/components/ui/button.tsxapps/web/src/components/ui/checkbox.tsxapps/web/src/components/ui/collapsible.tsxapps/web/src/components/ui/dialog.tsxapps/web/src/components/ui/dropdown-menu.tsxapps/web/src/components/ui/input.tsxapps/web/src/components/ui/progress.tsxapps/web/src/components/ui/separator.tsxapps/web/src/components/ui/sheet.tsxapps/web/src/components/ui/sidebar.tsxapps/web/src/components/ui/skeleton.tsxapps/web/src/components/ui/sonner.tsxapps/web/src/components/ui/tooltip.tsxapps/web/src/hooks/use-ballerina.tsapps/web/src/hooks/use-copy-share-link.tsapps/web/src/hooks/use-mobile.tsapps/web/src/hooks/use-share-notice.tsapps/web/src/hooks/use-share.tsapps/web/src/lib/file-tree-utils.tsapps/web/src/lib/fs/core/abstract-fs.tsapps/web/src/lib/fs/core/file-node-utils.tsapps/web/src/lib/fs/core/file-node.types.tsapps/web/src/lib/fs/core/fs.interface.tsapps/web/src/lib/fs/core/path-utils.tsapps/web/src/lib/fs/ephemeral-fs.tsapps/web/src/lib/fs/fs-roots.tsapps/web/src/lib/fs/layered-fs.tsapps/web/src/lib/fs/local-storage-fs.tsapps/web/src/lib/router-utils.tsapps/web/src/lib/share.tsapps/web/src/lib/utils.tsapps/web/src/main.tsxapps/web/src/providers/fs-provider.tsxapps/web/src/routeTree.gen.tsapps/web/src/routes/$.tsxapps/web/src/routes/__root.tsxapps/web/src/stores/editor-store.tsapps/web/src/stores/file-tree-store.tsapps/web/src/styles.cssapps/web/src/types/wasm-types.d.tsapps/web/src/wasm_exec.jsapps/web/tsconfig.app.jsonapps/web/tsconfig.jsonapps/web/tsconfig.node.jsonapps/web/turbo.jsonapps/web/vite.config.tsbiome.jsonpackage.jsonpackages/wasm/.gitignorepackages/wasm/ballerina-lang-gopackages/wasm/biome.jsonpackages/wasm/diagnostics_printer.gopackages/wasm/go.modpackages/wasm/local_storage_fs.gopackages/wasm/main_wasm.gopackages/wasm/package.jsonpackages/wasm/turbo.jsonturbo.jsonweb/src/routes/__root.tsx
💤 Files with no reviewable changes (2)
- biome.json
- web/src/routes/__root.tsx
✅ Files skipped from review due to trivial changes (14)
- .gitmodules
- packages/wasm/.gitignore
- packages/wasm/turbo.json
- apps/web/src/main.tsx
- packages/wasm/biome.json
- apps/web/src/styles.css
- .gitignore
- turbo.json
- packages/wasm/package.json
- apps/web/biome.json
- apps/web/turbo.json
- apps/web/src/hooks/use-share-notice.ts
- apps/web/src/assets/examples.json
- apps/web/src/lib/fs/fs-roots.ts
🚧 Files skipped from review as they are similar to previous changes (15)
- apps/web/src/routes/__root.tsx
- apps/web/src/lib/fs/ephemeral-fs.ts
- apps/web/src/routes/$.tsx
- apps/web/src/components/ui/checkbox.tsx
- apps/web/src/hooks/use-copy-share-link.ts
- apps/web/src/components/ui/sonner.tsx
- apps/web/src/components/share-notice-dialog.tsx
- apps/web/src/lib/file-tree-utils.ts
- apps/web/package.json
- apps/web/src/lib/fs/core/file-node-utils.ts
- apps/web/src/stores/file-tree-store.ts
- package.json
- apps/web/src/lib/fs/core/path-utils.ts
- apps/web/src/lib/share.ts
- apps/web/src/components/app-sidebar.tsx
|
Shall we sync the pr with main branch. |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
apps/web/package.json (1)
8-9: Consider using a cross-platform copy utility forcopy:wasm.The
cpcommand is Unix-specific and will fail on Windows. If Windows development is supported, consider using a cross-platform alternative.♻️ Proposed fix using cpx or cpy-cli
- "copy:wasm": "cp ../../packages/wasm/dist/ballerina.wasm public/ballerina.wasm" + "copy:wasm": "cpy '../../packages/wasm/dist/ballerina.wasm' public --flat"This requires adding
cpy-clias a devDependency:"devDependencies": { + "cpy-cli": "^5.0.0", "@tanstack/router-plugin": "^1.167.1",Alternatively, if Windows support is not a priority, you can ignore this suggestion.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/web/package.json` around lines 8 - 9, The "copy:wasm" npm script uses the Unix-only "cp" command and will fail on Windows; replace it with a cross-platform copier (e.g., install a devDependency like "cpy-cli" or "cpx") and update the "copy:wasm" script to use that tool (for example use "cpy" or "cpx" to copy "../../packages/wasm/dist/ballerina.wasm" to "public/ballerina.wasm"); ensure you add the chosen package to devDependencies and update any related build scripts that call "copy:wasm".
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@apps/web/package.json`:
- Around line 8-9: The "copy:wasm" npm script uses the Unix-only "cp" command
and will fail on Windows; replace it with a cross-platform copier (e.g., install
a devDependency like "cpy-cli" or "cpx") and update the "copy:wasm" script to
use that tool (for example use "cpy" or "cpx" to copy
"../../packages/wasm/dist/ballerina.wasm" to "public/ballerina.wasm"); ensure
you add the chosen package to devDependencies and update any related build
scripts that call "copy:wasm".
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: bb2ef1f9-4ee0-40b6-8ea9-2c357e7fb56a
⛔ Files ignored due to path filters (3)
apps/web/public/ballerina.svgis excluded by!**/*.svgbun.lockis excluded by!**/*.lockpackages/wasm/go.sumis excluded by!**/*.sum
📒 Files selected for processing (75)
.github/workflows/ci.yml.github/workflows/deploy.yml.gitignore.gitmodulesapps/web/.gitignoreapps/web/biome.jsonapps/web/components.jsonapps/web/index.htmlapps/web/package.jsonapps/web/src/assets/examples.jsonapps/web/src/components/ansi.tsxapps/web/src/components/app-sidebar.tsxapps/web/src/components/code-editor.tsxapps/web/src/components/editor.tsxapps/web/src/components/file-route-sync.tsxapps/web/src/components/file-tree-dialog.tsxapps/web/src/components/share-notice-dialog.tsxapps/web/src/components/ui/button.tsxapps/web/src/components/ui/checkbox.tsxapps/web/src/components/ui/collapsible.tsxapps/web/src/components/ui/dialog.tsxapps/web/src/components/ui/dropdown-menu.tsxapps/web/src/components/ui/input.tsxapps/web/src/components/ui/progress.tsxapps/web/src/components/ui/separator.tsxapps/web/src/components/ui/sheet.tsxapps/web/src/components/ui/sidebar.tsxapps/web/src/components/ui/skeleton.tsxapps/web/src/components/ui/sonner.tsxapps/web/src/components/ui/tooltip.tsxapps/web/src/hooks/use-ballerina.tsapps/web/src/hooks/use-copy-share-link.tsapps/web/src/hooks/use-mobile.tsapps/web/src/hooks/use-share-notice.tsapps/web/src/hooks/use-share.tsapps/web/src/lib/file-tree-utils.tsapps/web/src/lib/fs/core/abstract-fs.tsapps/web/src/lib/fs/core/file-node-utils.tsapps/web/src/lib/fs/core/file-node.types.tsapps/web/src/lib/fs/core/fs.interface.tsapps/web/src/lib/fs/core/path-utils.tsapps/web/src/lib/fs/ephemeral-fs.tsapps/web/src/lib/fs/fs-roots.tsapps/web/src/lib/fs/layered-fs.tsapps/web/src/lib/fs/local-storage-fs.tsapps/web/src/lib/router-utils.tsapps/web/src/lib/share.tsapps/web/src/lib/utils.tsapps/web/src/main.tsxapps/web/src/providers/fs-provider.tsxapps/web/src/routeTree.gen.tsapps/web/src/routes/$.tsxapps/web/src/routes/__root.tsxapps/web/src/stores/editor-store.tsapps/web/src/stores/file-tree-store.tsapps/web/src/styles.cssapps/web/src/types/wasm-types.d.tsapps/web/src/wasm_exec.jsapps/web/tsconfig.app.jsonapps/web/tsconfig.jsonapps/web/tsconfig.node.jsonapps/web/turbo.jsonapps/web/vite.config.tsbiome.jsonpackage.jsonpackages/wasm/.gitignorepackages/wasm/ballerina-lang-gopackages/wasm/biome.jsonpackages/wasm/diagnostics_printer.gopackages/wasm/go.modpackages/wasm/local_storage_fs.gopackages/wasm/main_wasm.gopackages/wasm/package.jsonpackages/wasm/turbo.jsonturbo.json
💤 Files with no reviewable changes (1)
- biome.json
✅ Files skipped from review due to trivial changes (10)
- packages/wasm/.gitignore
- packages/wasm/biome.json
- .gitmodules
- turbo.json
- packages/wasm/turbo.json
- packages/wasm/package.json
- .gitignore
- apps/web/turbo.json
- apps/web/biome.json
- package.json
🚧 Files skipped from review as they are similar to previous changes (2)
- .github/workflows/deploy.yml
- .github/workflows/ci.yml
83ab388 to
f0157ef
Compare
Purpose
Resolves #10
Migration to Monorepo Using Turborepo
This pull request restructures the project into a monorepo architecture using Turborepo and npm workspaces, resolving issue #10.
Core Structural Changes
Directory Reorganization:
apps/webandpackages/wasmworkspaces.gitmodulesto relocate the wasm submodule fromwasm/topackages/wasm/ballerina-lang-goRoot Configuration:
package.jsondefining the@playground/monorepowith workspace declarations forapps/*andpackages/*bun@1.3.10for consistencyturbo run dev,turbo run build) and Biome for linting/formattingBuild System Integration
Turborepo Configuration:
turbo.jsonat root level withbuildanddevtask definitions including caching strategies and persistence settingsapps/web/turbo.jsonwith task pipeline dependency on@playground/wasm#buildand automatedcopy:wasmtaskpackages/wasm/turbo.jsonwith cache inputs (Go source files,go.mod,go.sum) and outputs for reproducible buildscopy:wasmtask to automatically copy compiled WASM output from packages into the web app public directoryPackage-Specific Updates:
apps/webpackage fromwebto@playground/web@playground/wasmpackage with Go-to-WebAssembly build automation via npm scriptsFile Sharing and Collaboration Features
Share Functionality:
apps/web/src/lib/share.ts)ShareNoticeDialogcomponent to inform users about temporary shared linksuseShare,useCopyShareLink, anduseShareNoticehooks to manage the sharing workflowEnhanced File System & UI:
FileRouteSynccomponent to synchronize TanStack Router URL parameters with active file paths in the storeLayeredFSwithgraftSharedTreemethod to load shared file hierarchiesFileTreeStorewithloadSharedFilesaction for managing shared file operationsCheckboxandToasterUI components for improved user interaction with share notices and notificationsData and Example Content:
apps/web/src/assets/examples.jsonwith three Ballerina code examples demonstrating various language featuressharequery parameterCI/CD Pipeline Updates
GitHub Actions Workflow Changes:
wasm/topackages/wasm/in both CI and deployment workflowsweb/directorybun run build --filter=@playground/webfor scoped package executionweb/disttoapps/web/distConfiguration Cleanup
.gitignoreto reflect monorepo structure (ignoringnode_modules,.bun,.turbo, and package-specificdistdirectories)biome.jsonfiles atapps/web/andpackages/wasm/for package-specific linting/formatting rulesDependency Updates
sonnerlibrary to web app dependencies for toast notifications@biomejs/biomefrom web app dependencies (now managed at root level)