Răsfoiți Sursa

Automate_Bun_Install_in_Dev_Orchestrator

Updated `dev.py` to automatically execute `bun install` prior to running the frontend build command.

        PURPOSE:
        To completely remove developer friction caused by missing JavaScript dependencies. A contributor encountered a module resolution error (`Could not resolve: "d3"`) during the `bun run build` step because their local workspace lacked a `node_modules/` directory. By embedding the package installation step directly into the orchestrator, we ensure parity with how `uv` handles Python dependencies natively.

        IMPLEMENTATION DETAILS:
        - Inserted a new `subprocess.run(["bun", "install"], check=True)` routine immediately following the Python backend generation.
        - Shifted the `FileNotFoundError` check (which verifies Bun's presence on the system) up to this new step so it gracefully errors out earlier in the chain.
        - Re-numbered the printed stdout messages from `[X/3]` to `[X/4]` to reflect the adjusted pipeline.
Thomas Knott 2 săptămâni în urmă
părinte
comite
6d59a71e12

BIN
__pycache__/cache.cpython-314.pyc


BIN
cache/api.prunplanner.org/data%2Fbuildings%2F.json.xz


BIN
cache/api.prunplanner.org/data%2Fmaterials%2F.json.xz


BIN
cache/api.prunplanner.org/data%2Frecipes%2F.json.xz


BIN
cache/refined-prun.github.io/refined-prices%2Fall.json.json.xz


+ 28 - 39
dev.py

@@ -1,11 +1,15 @@
 """
 dev.py
 ======
-This script acts as a local development orchestrator.
-It performs three main actions sequentially:
+This script acts as a local development orchestrator. Instead of recreating the frontend
+in Python, which would violate the "Don't Repeat Yourself" (DRY) principle and introduce
+massive technical debt, this script leverages the existing architecture.
+
+It performs four main actions sequentially:
 1. Executes `roi.py` to fetch the latest market data and generate the frontend JSON files.
-2. Executes the `bun run build` command to compile the TypeScript frontend into browser-ready JavaScript.
-3. Spawns a local Python HTTP server pointing to the `www/` directory so you can view the changes in your browser.
+2. Executes `bun install` to ensure frontend JS dependencies are present.
+3. Executes `bun run build` to compile the TypeScript frontend into browser-ready JavaScript.
+4. Spawns a local Python HTTP server pointing to the `www/` directory.
 """
 
 import os           # Required for changing working directories and checking paths.
@@ -21,74 +25,59 @@ def main() -> None:
     # -------------------------------------------------------------------------
     # STEP 1: GENERATE BACKEND DATA
     # -------------------------------------------------------------------------
-    # We first need to ensure that the JSON data files that the frontend consumes
-    # actually exist and are up to date. We do this by calling the existing `roi.py` script.
-    print(">>> [1/3] Running roi.py to generate updated JSON data...")
+    print(">>> [1/4] Running roi.py to generate updated JSON data...")
     try:
-        # sys.executable ensures we use the exact same Python interpreter currently running this script.
-        # check=True ensures that if roi.py crashes, this script will also halt and raise a CalledProcessError.
         subprocess.run([sys.executable, "roi.py"], check=True)
     except subprocess.CalledProcessError as e:
-        # If roi.py fails, we catch the error, print a helpful message, and exit the program gracefully
-        # instead of spitting out a massive unhandled stack trace.
         sys.exit(f"!!! Error: Failed to execute roi.py. Process exited with code {e.returncode}")
 
     # -------------------------------------------------------------------------
-    # STEP 2: BUILD THE FRONTEND
+    # STEP 2: INSTALL FRONTEND DEPENDENCIES
     # -------------------------------------------------------------------------
-    # The frontend is written in TypeScript (inside the ts/ folder). Browsers cannot natively
-    # execute TypeScript in the way this project is structured. As outlined in `package.json`,
-    # 'bun' is used as the bundler to compile these files into the 'www/' directory.
-    print(">>> [2/3] Building the TypeScript frontend using Bun...")
+    # Unlike 'uv run', 'bun run' does not automatically install missing dependencies 
+    # defined in package.json. We must explicitly invoke 'bun install' first to 
+    # populate the node_modules/ directory.
+    print(">>> [2/4] Installing frontend dependencies via Bun...")
     try:
-        # We invoke the 'build' script defined in package.json.
-        # This corresponds to: "bun build ts/buy.ts ... --outdir www --target browser --sourcemap=external"
-        subprocess.run(["bun", "run", "build"], check=True)
+        subprocess.run(["bun", "install"], check=True)
     except FileNotFoundError:
-        # If 'bun' is not installed or not in the system's PATH, a FileNotFoundError is raised.
-        # We must alert the user that this system dependency is missing.
+        # We catch the FileNotFoundError here because this is the first time 'bun' is invoked.
         sys.exit("!!! Error: 'bun' command not found. Please ensure Bun is installed (https://bun.sh/) and in your PATH.")
     except subprocess.CalledProcessError as e:
-        # Catch compilation errors in the TypeScript code itself.
+        sys.exit(f"!!! Error: Frontend dependency installation failed. Bun exited with code {e.returncode}")
+
+    # -------------------------------------------------------------------------
+    # STEP 3: BUILD THE FRONTEND
+    # -------------------------------------------------------------------------
+    # Compiles the TypeScript inside ts/ to JavaScript inside www/
+    print(">>> [3/4] Building the TypeScript frontend using Bun...")
+    try:
+        subprocess.run(["bun", "run", "build"], check=True)
+    except subprocess.CalledProcessError as e:
         sys.exit(f"!!! Error: Frontend build failed. Bun exited with code {e.returncode}")
 
     # -------------------------------------------------------------------------
-    # STEP 3: SERVE THE FRONTEND LOCALLY
+    # STEP 4: SERVE THE FRONTEND LOCALLY
     # -------------------------------------------------------------------------
-    # We must serve the compiled files via an HTTP server because opening local HTML files
-    # directly (via file:// protocol) often causes CORS (Cross-Origin Resource Sharing) errors
-    # when the JavaScript attempts to fetch the local JSON files generated in Step 1.
-    print(">>> [3/3] Starting local development server...")
+    print(">>> [4/4] Starting local development server...")
     
-    # Define the port we want to host the site on. 8000 is a standard web development port.
     PORT = 8000
-    # Define the directory we want to serve. The bun build step outputs to 'www'.
     WEB_DIR = "www"
 
-    # We must ensure the 'www' directory exists before attempting to switch into it.
     if not os.path.isdir(WEB_DIR):
         sys.exit(f"!!! Error: Directory '{WEB_DIR}' does not exist. The build step may have failed silently.")
 
-    # Change the current working directory to 'www'. This ensures the HTTP server roots itself here,
-    # making the index.html inside 'www' the default page, and allowing relative path resolutions to work.
     os.chdir(WEB_DIR)
 
-    # http.server.SimpleHTTPRequestHandler is a built-in handler that serves files from the current directory.
     Handler = http.server.SimpleHTTPRequestHandler
 
-    # socketserver.TCPServer creates a TCP server that listens on the specified port and binds our handler to it.
-    # We use a 'with' block to ensure the network socket is properly released and cleaned up when the server stops.
     with socketserver.TCPServer(("", PORT), Handler) as httpd:
         print(f">>> Serving at http://localhost:{PORT}")
         print(">>> Press Ctrl+C to stop the server.")
         try:
-            # serve_forever() puts the script into an infinite loop, constantly listening for and fulfilling HTTP requests.
             httpd.serve_forever()
         except KeyboardInterrupt:
-            # Catch the Ctrl+C command from the user to gracefully shut down the server.
             print("\n>>> Shutting down development server gracefully. Goodbye!")
 
 if __name__ == '__main__':
-    # This standard Python idiom ensures that the main() function is only called if this script
-    # is executed directly from the command line (e.g., `python dev.py`), rather than imported as a module.
     main()

+ 0 - 34
uv.lock

@@ -14,38 +14,6 @@ wheels = [
     { url = "https://files.pythonhosted.org/packages/da/42/e921fccf5015463e32a3cf6ee7f980a6ed0f395ceeaa45060b61d86486c2/anyio-4.13.0-py3-none-any.whl", hash = "sha256:08b310f9e24a9594186fd75b4f73f4a4152069e3853f1ed8bfbf58369f4ad708", size = 114353, upload-time = "2026-03-24T12:59:08.246Z" },
 ]
 
-[[package]]
-name = "cbor2"
-version = "6.1.1"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/be/db/810437bcfe13cf5e09b68bad1ce57c8fa04ca9272c68946bbf2f4fa522c8/cbor2-6.1.1.tar.gz", hash = "sha256:6f0644869e0fdcd6f3874330b8f1cebd009f33191de43acf609dc2409cd362c4", size = 86297, upload-time = "2026-05-14T10:57:42.231Z" }
-wheels = [
-    { url = "https://files.pythonhosted.org/packages/a0/ec/30a52d7f6844cefd37601311a226d091268564a47b0dac56bc0469573681/cbor2-6.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0f027e077345ba7d1a88cbed9168196e77f5ce8e8c816305bb1c7a2e4894bddf", size = 409070, upload-time = "2026-05-14T10:57:05.843Z" },
-    { url = "https://files.pythonhosted.org/packages/b7/a5/653193249a64ca46def52798e8f10ddbc918f11818a977b2aa7248062520/cbor2-6.1.1-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:559025ad8e1f9f5d019a40dc8f14f43c111c11207b4dde852e943a3002b43ec0", size = 453218, upload-time = "2026-05-14T10:57:07.6Z" },
-    { url = "https://files.pythonhosted.org/packages/9f/79/bdcb9d43ed537abaa89e662d6340244207ec85b6e66e3bd7f40856c3a5d4/cbor2-6.1.1-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:a6690f7df210386866e120475183132df98f77bf6df624097f66e3214e775084", size = 466244, upload-time = "2026-05-14T10:57:09.297Z" },
-    { url = "https://files.pythonhosted.org/packages/9c/44/fe0543996d53538c074f8ee18f7391b5458c528b1717740d750a9e472e1d/cbor2-6.1.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f4898b5463a567775a05310407dbea5b4a8d7ae8e81337ae9084f5fe226938ff", size = 520804, upload-time = "2026-05-14T10:57:10.682Z" },
-    { url = "https://files.pythonhosted.org/packages/cd/83/577bbafef3bc887d654a73f3f4ab11e1bd5320abd9108bfc51fbea1498a8/cbor2-6.1.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bf3ef1fae6f14081a15f178e933ab846d3181f059ee4090975518b71f58bb09f", size = 533598, upload-time = "2026-05-14T10:57:12.098Z" },
-    { url = "https://files.pythonhosted.org/packages/57/32/c1c9f435b109ded86ef2e90ff73b95624c84c6edf01489941363a6069725/cbor2-6.1.1-cp313-cp313-win32.whl", hash = "sha256:4642780d27c0b411f4669fcb82e0d7a6b93a0c41c03a0c51296fd6f6858f63fa", size = 281738, upload-time = "2026-05-14T10:57:13.614Z" },
-    { url = "https://files.pythonhosted.org/packages/4d/39/9232731f161b2dfe2dc28b06bbacfc2b6a85f1255bf58ebc578ae760ef38/cbor2-6.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:616bc0538095860fe5607cc06d7b2de3e261a6caccd01ff3f1d4a4a9ad29adbf", size = 300018, upload-time = "2026-05-14T10:57:15.021Z" },
-    { url = "https://files.pythonhosted.org/packages/b9/c2/67f2e3a83acfcecad947784bb1590d1978662b5472fcbf7d73e219813456/cbor2-6.1.1-cp313-cp313-win_arm64.whl", hash = "sha256:7b193d2d024bb5d037e613272f5e436d53f02301101f0ce3916117688643181f", size = 287823, upload-time = "2026-05-14T10:57:16.525Z" },
-    { url = "https://files.pythonhosted.org/packages/aa/74/d2d6e0e3da305a625d710a932080bf70f390c867dce73bd35ca6cd5a8d10/cbor2-6.1.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:86c65976e9e69154700ea5a447013f37ff8cb76431adf9df3ebbabe341b68b06", size = 407425, upload-time = "2026-05-14T10:57:17.814Z" },
-    { url = "https://files.pythonhosted.org/packages/c3/7d/08644318380306e0809ecc4756e67fb684b5e78a938ca9ff1c8c7f57fe73/cbor2-6.1.1-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:350beaac7a6049fe0a48309d7acd24611ab1176b4db1515f7fbcad20f5c09821", size = 453010, upload-time = "2026-05-14T10:57:19.593Z" },
-    { url = "https://files.pythonhosted.org/packages/81/ff/43ef5f16a1a97ef4575c407d077d9355c01dfc54b1b1b8c5329b793c436b/cbor2-6.1.1-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:74bf0c3f48d215d49a99eb253fef6c00c19033339da22da4c29b53fe854093b8", size = 465110, upload-time = "2026-05-14T10:57:20.981Z" },
-    { url = "https://files.pythonhosted.org/packages/c8/61/3069cee66bc4bedb95dce49b5e90d07e6c1ddf712435facf84ce0353da4a/cbor2-6.1.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a731277d123cee9c87e649077376f694892e4a2c3b0b1cb97132205c620947d8", size = 520269, upload-time = "2026-05-14T10:57:22.514Z" },
-    { url = "https://files.pythonhosted.org/packages/f0/70/4b2ac02e0aa09419c13c434ce535cf508f08d5c411c6912d760c480ed8e6/cbor2-6.1.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:16e6df5a4971c2006805669be472a43bb382d0f3464c2236634b4e93095d7dd6", size = 532515, upload-time = "2026-05-14T10:57:24.289Z" },
-    { url = "https://files.pythonhosted.org/packages/73/94/ab4ad4fd5929c1df56899c1135cc6957239a74a5b418e760502c9aadfb17/cbor2-6.1.1-cp314-cp314-win32.whl", hash = "sha256:0d0831b449567ee27afa25ff2756ac8719f11491f700396edb1dc1647ece7111", size = 285433, upload-time = "2026-05-14T10:57:25.665Z" },
-    { url = "https://files.pythonhosted.org/packages/4f/ed/995a3830ce4429be1ffeb57d2f11b2f06987573c04a4ea4112bd5d7de643/cbor2-6.1.1-cp314-cp314-win_amd64.whl", hash = "sha256:91dac40fc0b8e0592a3e8d766377af3186e2736448c684465cca8606486e58ae", size = 308923, upload-time = "2026-05-14T10:57:27.019Z" },
-    { url = "https://files.pythonhosted.org/packages/ea/88/1797af54eca15bca2d963cd2d3a7337758961a31fd03438f2e82ec94ea87/cbor2-6.1.1-cp314-cp314-win_arm64.whl", hash = "sha256:be5ccd594ea6f1998cd83afb53b47e383e5efd7661a316a528216412109221c7", size = 299687, upload-time = "2026-05-14T10:57:28.656Z" },
-    { url = "https://files.pythonhosted.org/packages/53/dc/ecc0797db8b627f889389d8ea8a4af389bdff7500685e56969a6c4449c01/cbor2-6.1.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:47d2616d30212bd3db8c2897b453176401569e0e4ec3434b770e9652604d74c5", size = 403186, upload-time = "2026-05-14T10:57:30.111Z" },
-    { url = "https://files.pythonhosted.org/packages/c6/28/780af53231e1a6afc36f2b922ff587a9e1a25df7756628101a6070a9312f/cbor2-6.1.1-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:fd9d300ad983b860fbfb0ab148ddd3a379be25430bb141ad41344adc1c0792c1", size = 446311, upload-time = "2026-05-14T10:57:31.507Z" },
-    { url = "https://files.pythonhosted.org/packages/a1/5d/cc298ed16745995cf21caeec52213d157be8d5bfb405ee8ed420ffb5e038/cbor2-6.1.1-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:b8594563ccfd56f2bb56cdd8445f7a1f00d3065d84ea06f8e361da765abee08f", size = 459640, upload-time = "2026-05-14T10:57:32.967Z" },
-    { url = "https://files.pythonhosted.org/packages/f1/37/e4d95459d48e8a739c086249884b27458541df5a7fc149debdb0e0c7becb/cbor2-6.1.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8df2a530b45c7769ed43c02e3f7c9841ed4990887e1c29858b08363a35067bf5", size = 511667, upload-time = "2026-05-14T10:57:34.465Z" },
-    { url = "https://files.pythonhosted.org/packages/40/e8/32e529bd938c71456d38d7c6a62d0d75399e720553d6514a467fee9b004d/cbor2-6.1.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:d63181b5b213ab72eed01e62bfa4c994fe7de68433d12548d54156411ba0aac4", size = 527195, upload-time = "2026-05-14T10:57:36.09Z" },
-    { url = "https://files.pythonhosted.org/packages/be/96/42275a7d34baa8457a686c5e5a3bf5240e753595a6bd79c2c419347a2083/cbor2-6.1.1-cp314-cp314t-win32.whl", hash = "sha256:cba9a9ebc031267b76c2bdfd4a5a491874c27339d6ec9d0895fc4fde8f519565", size = 279851, upload-time = "2026-05-14T10:57:37.443Z" },
-    { url = "https://files.pythonhosted.org/packages/e3/97/09053af3e4825aa3b83b1ec2306c9228efe665fbfb90229e441b9c1b3cd5/cbor2-6.1.1-cp314-cp314t-win_amd64.whl", hash = "sha256:81af6e3a031191b483ca42b16d152627c6a9dc61c1fbef270403820ab587fc86", size = 302537, upload-time = "2026-05-14T10:57:39.143Z" },
-    { url = "https://files.pythonhosted.org/packages/4f/29/e257a381d494615348c7266fc173a36edce142533a5befe3c0967fd45ab4/cbor2-6.1.1-cp314-cp314t-win_arm64.whl", hash = "sha256:f0bc04543c562bd0b35fc79a29528017fe63104757c1b421d8c1ddfbe6761eca", size = 290270, upload-time = "2026-05-14T10:57:40.597Z" },
-]
-
 [[package]]
 name = "certifi"
 version = "2026.5.20"
@@ -146,7 +114,6 @@ name = "pruncalc"
 version = "0"
 source = { virtual = "." }
 dependencies = [
-    { name = "cbor2" },
     { name = "h2" },
     { name = "httpx" },
     { name = "typed-argument-parser" },
@@ -154,7 +121,6 @@ dependencies = [
 
 [package.metadata]
 requires-dist = [
-    { name = "cbor2" },
     { name = "h2" },
     { name = "httpx" },
     { name = "typed-argument-parser" },