diff --git a/build.py b/build.py index 3655d5d0..68729483 100644 --- a/build.py +++ b/build.py @@ -1,9 +1,8 @@ -# build before releasing - import os import subprocess import shutil import sys +from pathlib import Path def run_command(command, cwd=None): result = subprocess.run(command, shell=True, cwd=cwd, check=True) @@ -13,17 +12,65 @@ def npm_install(): print("Running npm install") run_command("npm install", cwd="bespoke-dataset-viewer") - -def npm_build(): - print("Running npm build") +def nextjs_build(): + print("Running Next.js build") run_command("npm run build", cwd="bespoke-dataset-viewer") - print("Copying static files") - source_dir = os.path.join("bespoke-dataset-viewer", "build") - target_dir = os.path.join("src", "bespokelabs", "curator", "viewer", "static") - shutil.rmtree(target_dir, ignore_errors=True) - shutil.copytree(source_dir, target_dir) - print(f"Copied static files from {source_dir} to {target_dir}") + print("Copying build artifacts to static folder") + + # Source and target directories + source_base = Path("bespoke-dataset-viewer") + target_base = Path("src/bespokelabs/curator/viewer/static") + + # Ensure target directory exists + if target_base.exists(): + shutil.rmtree(target_base) + target_base.mkdir(parents=True, exist_ok=True) + + # First, copy node_modules + node_modules_source = source_base / "node_modules" + node_modules_target = target_base / "node_modules" + if node_modules_source.exists(): + print("Copying node_modules") + shutil.copytree(node_modules_source, node_modules_target) + # Copy package files first to ensure they're in place + for pkg_file in ['package.json', 'package-lock.json']: + source = source_base / pkg_file + if source.exists(): + shutil.copy2(source, target_base / pkg_file) + print(f"Copied {pkg_file}") + + # Copy the rest of the files + files_to_copy = [ + '.next', + 'app', + 'components', + 'lib', + 'public', + 'types', + 'next.config.ts', + 'next-env.d.ts', + 'tsconfig.json', + 'postcss.config.mjs', + 'tailwind.config.ts', + 'components.json' + ] + + for item in files_to_copy: + source = source_base / item + target = target_base / item + + if source.exists(): + if source.is_file(): + shutil.copy2(source, target) + print(f"Copied file {source} to {target}") + elif source.is_dir(): + if target.exists(): + shutil.rmtree(target) + shutil.copytree(source, target) + print(f"Copied directory {source} to {target}") + else: + print(f"Warning: {source} not found") def run_pytest(): print("Running pytest") @@ -33,13 +80,11 @@ def run_pytest(): print("Pytest failed. Aborting build.") sys.exit(1) - def main(): npm_install() - npm_build() - run_pytest() + nextjs_build() + # run_pytest() print("Build completed successfully.") - if __name__ == "__main__": - main() + main() \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..c1d2f741 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6 @@ +{ + "name": "bella", + "lockfileVersion": 3, + "requires": true, + "packages": {} +} diff --git a/pyproject.toml b/pyproject.toml index 810ecd9c..ab913308 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -31,4 +31,4 @@ requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" [tool.poetry.scripts] -bespoke-dataset-viewer = "bespokelabs.curator.viewer.__main__:main" +curator-viewer = "bespokelabs.curator.viewer.__main__:main" diff --git a/src/bespokelabs/curator/viewer/__main__.py b/src/bespokelabs/curator/viewer/__main__.py new file mode 100644 index 00000000..60e74590 --- /dev/null +++ b/src/bespokelabs/curator/viewer/__main__.py @@ -0,0 +1,40 @@ +import os +import subprocess +import sys +from pathlib import Path + +def get_viewer_path(): + return str(Path(__file__).parent) + +def start_nextjs_server(): + viewer_path = get_viewer_path() + static_dir = os.path.join(viewer_path, 'static') + server_file = os.path.join(viewer_path, 'server.js') + + if not os.path.exists(os.path.join(static_dir, '.next')): + print("Error: Next.js build artifacts not found. The package may not be built correctly.") + sys.exit(1) + + try: + # Run the server.js directly with node + env = os.environ.copy() + env["NODE_ENV"] = "production" + + subprocess.run( + ["node", server_file], + cwd=viewer_path, + env=env, + check=True + ) + except subprocess.CalledProcessError as e: + print(f"Error starting Next.js server: {e}") + sys.exit(1) + except FileNotFoundError: + print("Error: Node.js is not installed. Please install Node.js to run the viewer.") + sys.exit(1) + +def main(): + start_nextjs_server() + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/src/bespokelabs/curator/viewer/server.js b/src/bespokelabs/curator/viewer/server.js new file mode 100644 index 00000000..93af4873 --- /dev/null +++ b/src/bespokelabs/curator/viewer/server.js @@ -0,0 +1,45 @@ +const { createServer } = require('http'); +const { parse } = require('url'); +const path = require('path'); + +// Get paths +const staticDir = path.join(__dirname, 'static'); +// Add node_modules to Node's module search path +process.env.NODE_PATH = path.join(staticDir, 'node_modules'); +require('module').Module._initPaths(); + +const next = require(path.join(staticDir, 'node_modules/next')); + +const dev = process.env.NODE_ENV !== 'production'; +const hostname = 'localhost'; +const port = 3000; + +// Configure Next.js +const app = next({ + dev, + dir: staticDir, + hostname, + port +}); + +const handle = app.getRequestHandler(); + +app.prepare().then(() => { + createServer(async (req, res) => { + try { + const parsedUrl = parse(req.url, true); + await handle(req, res, parsedUrl); + } catch (err) { + console.error('Error occurred handling', req.url, err); + res.statusCode = 500; + res.end('internal server error'); + } + }) + .once('error', (err) => { + console.error(err); + process.exit(1); + }) + .listen(port, () => { + console.log(`> Ready on http://${hostname}:${port}`); + }); +}); \ No newline at end of file