API Integration Builder
Run ID: 69cd02a53e7fb09ff16a71532026-04-01Development
PantheraHive BOS
BOS Dashboard

API Integration Builder: Project Creation (Step 2 of 2)

Workflow & Step Confirmation

This document represents the completion of Step 2 of 2 in the "API Integration Builder" workflow.

Specifically, this output addresses the projectmanager → create_project action, providing the foundational code and structure required to initiate a new project via an external API.

Purpose of this Deliverable

This deliverable provides a comprehensive, professional, and actionable code scaffold and project structure for integrating with an external API to perform a create_project operation. It covers essential aspects such as project setup, configuration management, API client implementation, error handling, and basic logging, enabling your team to quickly establish and customize this integration.

The goal is to provide a robust starting point that can be extended and adapted to your specific external API and project management system requirements.

Core Components of the New API Integration Project

Below, you will find the recommended project structure and initial code scaffolding designed for a typical API integration focusing on project creation.

1. Recommended Project Structure

A well-organized project structure is crucial for maintainability and scalability. We recommend the following layout:

text • 795 chars
project_api_integration/
├── config/
│   └── settings.py             # Configuration loading (API keys, endpoints)
├── src/
│   ├── api_client/
│   │   ├── __init__.py
│   │   └── project_manager_api.py # Main API client for project operations
│   ├── models/
│   │   ├── __init__.py
│   │   └── project.py          # Data models for project entities
│   └── utils/
│       ├── __init__.py
│       └── logger.py           # Centralized logging utility
├── tests/
│   ├── __init__.py
│   └── test_project_creation.py # Unit/integration tests
├── main.py                     # Entry point for executing the integration
├── .env.example                # Example for environment variables
├── requirements.txt            # Python dependencies
└── README.md                   # Project documentation
Sandboxed live preview

API Integration Builder: Code Generation for Robust API Client

This document provides a comprehensive, detailed, and professional output for the "generate_code" step of the "API Integration Builder" workflow. The goal is to deliver a production-ready, well-commented, and highly customizable Python template for integrating with external RESTful APIs.

Given the generic nature of the request ("API Integration Builder") without specific API details (e.g., API name, endpoints, authentication type, data models), this output focuses on providing a robust, extensible, and best-practice-driven framework. This framework will serve as a strong foundation that can be easily adapted to any specific API.


1. Introduction to the Generated API Client

This output provides a Python-based API client template designed for reliability, maintainability, and security. It incorporates essential features required for production environments, such as:

  • Configurable Base URL and Authentication: Easy setup for different environments and authentication types.
  • Standard HTTP Methods: Support for GET, POST, PUT, DELETE.
  • Robust Error Handling: Custom exceptions for clear error identification (e.g., network issues, authentication failures, rate limiting, server errors).
  • Automatic Retry Mechanism: Implements exponential backoff for transient network issues or temporary service unavailability.
  • Comprehensive Logging: Integrates standard Python logging for monitoring and debugging.
  • Secure Configuration: Encourages the use of environment variables for sensitive credentials.

This template is designed to be a starting point. You will need to customize it with specific API endpoints, request/response data models, and detailed authentication specifics for your target API.


2. Core Concepts for Robust API Integration

Before diving into the code, understanding the underlying principles is crucial for building reliable integrations:

  • Authentication & Authorization: Securely identify your application to the API. Common types include API Keys (header, query param), OAuth 2.0 (client credentials, authorization code), JWTs, etc.
  • Error Handling: Anticipate and gracefully handle various errors:

* Network Errors: Connection issues, timeouts.

* Client Errors (4xx): Bad requests (400), unauthorized (401), forbidden (403), not found (404), rate limited (429).

* Server Errors (5xx): Internal server errors (500), service unavailable (503).

  • Retry Mechanisms: Implement strategies (like exponential backoff) for transient errors (e.g., network glitches, temporary service overload, rate limits) to improve resilience without overwhelming the API.
  • Logging: Crucial for debugging, monitoring API usage, and identifying issues in production. Log request/response details (sanitized), errors, and retry attempts.
  • Configuration Management: Separate sensitive credentials (API keys, secrets) and environment-specific settings (base URLs) from your codebase. Use environment variables or secure configuration files.
  • Rate Limiting Awareness: Understand and respect the API's rate limits. The retry mechanism can help, but for sustained high-volume requests, consider queuing or token bucket algorithms.
  • Idempotency: For non-GET requests (POST, PUT, DELETE), understand if the API operations are idempotent. If not, retrying a failed request might have unintended side effects (e.g., creating duplicate resources).

3. Generated Code: Python API Client Template

The following Python code provides a flexible and production-ready GenericAPIClient class. It uses the popular requests library for HTTP communication.


import os
import requests
import time
import logging
from typing import Dict, Any, Optional, Union

# --- 1. Configure Logging ---
# It's recommended to configure logging at the application level.
# This setup provides a basic console logger.
logging.basicConfig(level=os.environ.get("LOG_LEVEL", "INFO").upper(),
                    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

# --- 2. Custom Exception Classes ---
# Define custom exceptions for clearer error handling
class APIError(Exception):
    """Base exception for API-related errors."""
    def __init__(self, message: str, status_code: Optional[int] = None, response_data: Optional[Any] = None):
        super().__init__(message)
        self.status_code = status_code
        self.response_data = response_data
        logger.error(f"APIError: {message} | Status: {status_code} | Response: {response_data}")

class AuthenticationError(APIError):
    """Raised for 401 Unauthorized errors."""
    pass

class ForbiddenError(APIError):
    """Raised for 403 Forbidden errors."""
    pass

class NotFoundError(APIError):
    """Raised for 404 Not Found errors."""
    pass

class RateLimitError(APIError):
    """Raised for 429 Too Many Requests errors."""
    pass

class ClientError(APIError):
    """Raised for other 4xx client errors."""
    pass

class ServerError(APIError):
    """Raised for 5xx server errors."""
    pass

class NetworkError(APIError):
    """Raised for network-related issues (e.g., connection errors, timeouts)."""
    pass

# --- 3. Generic API Client Class ---
class GenericAPIClient:
    """
    A generic and robust client for interacting with RESTful APIs.

    Features:
    - Configurable base URL and authentication.
    - Automatic retry mechanism with exponential backoff for transient errors.
    - Comprehensive error handling with custom exceptions.
    - Integrated logging for requests, responses, and errors.
    """

    def __init__(self,
                 base_url: str,
                 api_key: Optional[str] = None,
                 auth_header_name: str = "Authorization",
                 auth_header_prefix: str = "Bearer",
                 timeout: int = 30,
                 max_retries: int = 3,
                 backoff_factor: float = 0.5,
                 initial_delay: float = 1.0,
                 custom_headers: Optional[Dict[str, str]] = None):
        """
        Initializes the API client.

        Args:
            base_url (str): The base URL of the API (e.g., "https://api.example.com/v1").
            api_key (Optional[str]): The API key or token for authentication.
                                     If None, no API key header will be sent.
            auth_header_name (str): The name of the header for API key/token (default: "Authorization").
            auth_header_prefix (str): Prefix for the API key/token (e.g., "Bearer", "Token"). Set to "" if no prefix.
            timeout (int): Default timeout for HTTP requests in seconds.
            max_retries (int): Maximum number of retries for transient errors.
            backoff_factor (float): Factor for exponential backoff (delay = backoff_factor * (2 ** (retry_num - 1))).
            initial_delay (float): Initial delay before the first retry attempt.
            custom_headers (Optional[Dict[str, str]]): A dictionary of additional headers to send with every request.
        """
        if not base_url:
            raise ValueError("Base URL cannot be empty.")
        self.base_url = base_url.rstrip('/')
        self.timeout = timeout
        self.max_retries = max_retries
        self.backoff_factor = backoff_factor
        self.initial_delay = initial_delay
        self.session = requests.Session() # Use a session for connection pooling and header persistence

        # Set default headers, including authentication
        self.session.headers.update({
            "Content-Type": "application/json",
            "Accept": "application/json"
        })

        if api_key:
            auth_value = f"{auth_header_prefix} {api_key}" if auth_header_prefix else api_key
            self.session.headers.update({auth_header_name: auth_value})
            logger.info(f"API Client initialized with {auth_header_name} authentication.")
        else:
            logger.warning("API Client initialized without an API key. Ensure the target API does not require authentication or uses another method.")

        if custom_headers:
            self.session.headers.update(custom_headers)
            logger.info(f"Custom headers added: {custom_headers}")

        logger.info(f"GenericAPIClient initialized for base URL: {self.base_url}")

    def _handle_response(self, response: requests.Response) -> Any:
        """
        Handles the API response, raising custom exceptions for errors.
        """
        try:
            response_data = response.json()
        except requests.exceptions.JSONDecodeError:
            response_data = response.text # Fallback to text if not JSON

        if response.ok: # status_code is 2xx
            return response_data
        else:
            error_message = f"API request failed with status {response.status_code}: {response.reason}"
            if response_data:
                error_message += f" | Details: {response_data}"

            if response.status_code == 401:
                raise AuthenticationError(error_message, response.status_code, response_data)
            elif response.status_code == 403:
                raise ForbiddenError(error_message, response.status_code, response_data)
            elif response.status_code == 404:
                raise NotFoundError(error_message, response.status_code, response_data)
            elif response.status_code == 429:
                # Optionally, parse 'Retry-After' header here
                retry_after = response.headers.get("Retry-After")
                logger.warning(f"Rate limit hit. Retry-After: {retry_after} seconds.")
                raise RateLimitError(error_message, response.status_code, response_data)
            elif 400 <= response.status_code < 500:
                raise ClientError(error_message, response.status_code, response_data)
            elif 500 <= response.status_code < 600:
                raise ServerError(error_message, response.status_code, response_data)
            else:
                raise APIError(error_message, response.status_code, response_data)

    def _request(self,
                 method: str,
                 endpoint: str,
                 params: Optional[Dict[str, Any]] = None,
                 data: Optional[Union[Dict[str, Any], str]] = None,
                 json: Optional[Dict[str, Any]] = None,
                 headers: Optional[Dict[str, str]] = None,
                 **kwargs) -> Any:
        """
        Internal method to make an HTTP request with retry logic.
        """
        url = f"{self.base_url}/{endpoint.lstrip('/')}"
        logger.debug(f"Attempting {method} request to {url}")
        logger.debug(f"Params: {params}, Data: {data}, JSON: {json}")

        combined_headers = {**self.session.headers, **(headers or {})}

        for retry_num in range(self.max_retries + 1):
            try:
                response = self.session.request(
                    method=method,
                    url=url,
                    params=params,
                    data=data,
                    json=json,
                    headers=combined_headers,
                    timeout=self.timeout,
                    **kwargs
                )
                logger.debug(f"Received response for {method} {url} with status {response.status_code}")
                return self._handle_response(response)

            except (requests.exceptions.ConnectionError, requests.exceptions.Timeout) as e:
                if retry_num < self.max_retries:
                    delay = self.initial_delay * (self.backoff_factor ** retry_num)
                    logger.warning(f"Network error during {method} {url}: {e}. Retrying in {delay:.2f} seconds (attempt {retry_num + 1}/{self.max_retries}).")
                    time.sleep(delay)
                else:
                    raise NetworkError(f"Failed to connect to {url} after {self.max_retries} retries: {e}") from e
            except requests.exceptions.RequestException as e:
                # Catch other requests library exceptions (e.g., TooManyRedirects)
                raise APIError(f"An unexpected request error occurred:
  1. Configure Environment Variables:

* Rename .env.example to .env.

* Edit .env and replace your_secret_api_key_here with your actual API key and https://api.yourprojectmanager.com/v1 with the correct base URL for your external Project Manager API.

  1. Review and Customize:

* API Endpoint: Verify and adjust the endpoint = "/projects" in src/api_client/project_manager_api.py to match your external API's documentation for project creation.

* Authentication: If your API uses a different authentication method (e.g., X-API-Key header, OAuth 2.0), modify the self.headers in src/api_client/project_manager_api.py accordingly.

* Payload Fields: Update src/models/project.py (ProjectCreatePayload) to precisely match the

api_integration_builder.txt
Download source file
Copy all content
Full output as text
Download ZIP
IDE-ready project ZIP
Copy share link
Permanent URL for this run
Get Embed Code
Embed this result on any website
Print / Save PDF
Use browser print dialog
"); var hasSrcMain=Object.keys(extracted).some(function(k){return k.indexOf("src/main")>=0;}); if(!hasSrcMain) zip.file(folder+"src/main."+ext,"import React from 'react' import ReactDOM from 'react-dom/client' import App from './App' import './index.css' ReactDOM.createRoot(document.getElementById('root')!).render( ) "); var hasSrcApp=Object.keys(extracted).some(function(k){return k==="src/App."+ext||k==="App."+ext;}); if(!hasSrcApp) zip.file(folder+"src/App."+ext,"import React from 'react' import './App.css' function App(){ return(

"+slugTitle(pn)+"

Built with PantheraHive BOS

) } export default App "); zip.file(folder+"src/index.css","*{margin:0;padding:0;box-sizing:border-box} body{font-family:system-ui,-apple-system,sans-serif;background:#f0f2f5;color:#1a1a2e} .app{min-height:100vh;display:flex;flex-direction:column} .app-header{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;padding:40px} h1{font-size:2.5rem;font-weight:700} "); zip.file(folder+"src/App.css",""); zip.file(folder+"src/components/.gitkeep",""); zip.file(folder+"src/pages/.gitkeep",""); zip.file(folder+"src/hooks/.gitkeep",""); Object.keys(extracted).forEach(function(p){ var fp=p.startsWith("src/")?p:"src/"+p; zip.file(folder+fp,extracted[p]); }); zip.file(folder+"README.md","# "+slugTitle(pn)+" Generated by PantheraHive BOS. ## Setup ```bash npm install npm run dev ``` ## Build ```bash npm run build ``` ## Open in IDE Open the project folder in VS Code or WebStorm. "); zip.file(folder+".gitignore","node_modules/ dist/ .env .DS_Store *.local "); } /* --- Vue (Vite + Composition API + TypeScript) --- */ function buildVue(zip,folder,app,code,panelTxt){ var pn=pkgName(app); var C=cc(pn); var extracted=extractCode(panelTxt); zip.file(folder+"package.json",'{ "name": "'+pn+'", "version": "0.0.0", "type": "module", "scripts": { "dev": "vite", "build": "vue-tsc -b && vite build", "preview": "vite preview" }, "dependencies": { "vue": "^3.5.13", "vue-router": "^4.4.5", "pinia": "^2.3.0", "axios": "^1.7.9" }, "devDependencies": { "@vitejs/plugin-vue": "^5.2.1", "typescript": "~5.7.3", "vite": "^6.0.5", "vue-tsc": "^2.2.0" } } '); zip.file(folder+"vite.config.ts","import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import { resolve } from 'path' export default defineConfig({ plugins: [vue()], resolve: { alias: { '@': resolve(__dirname,'src') } } }) "); zip.file(folder+"tsconfig.json",'{"files":[],"references":[{"path":"./tsconfig.app.json"},{"path":"./tsconfig.node.json"}]} '); zip.file(folder+"tsconfig.app.json",'{ "compilerOptions":{ "target":"ES2020","useDefineForClassFields":true,"module":"ESNext","lib":["ES2020","DOM","DOM.Iterable"], "skipLibCheck":true,"moduleResolution":"bundler","allowImportingTsExtensions":true, "isolatedModules":true,"moduleDetection":"force","noEmit":true,"jsxImportSource":"vue", "strict":true,"paths":{"@/*":["./src/*"]} }, "include":["src/**/*.ts","src/**/*.d.ts","src/**/*.tsx","src/**/*.vue"] } '); zip.file(folder+"env.d.ts","/// "); zip.file(folder+"index.html"," "+slugTitle(pn)+"
"); var hasMain=Object.keys(extracted).some(function(k){return k==="src/main.ts"||k==="main.ts";}); if(!hasMain) zip.file(folder+"src/main.ts","import { createApp } from 'vue' import { createPinia } from 'pinia' import App from './App.vue' import './assets/main.css' const app = createApp(App) app.use(createPinia()) app.mount('#app') "); var hasApp=Object.keys(extracted).some(function(k){return k.indexOf("App.vue")>=0;}); if(!hasApp) zip.file(folder+"src/App.vue"," "); zip.file(folder+"src/assets/main.css","*{margin:0;padding:0;box-sizing:border-box}body{font-family:system-ui,sans-serif;background:#fff;color:#213547} "); zip.file(folder+"src/components/.gitkeep",""); zip.file(folder+"src/views/.gitkeep",""); zip.file(folder+"src/stores/.gitkeep",""); Object.keys(extracted).forEach(function(p){ var fp=p.startsWith("src/")?p:"src/"+p; zip.file(folder+fp,extracted[p]); }); zip.file(folder+"README.md","# "+slugTitle(pn)+" Generated by PantheraHive BOS. ## Setup ```bash npm install npm run dev ``` ## Build ```bash npm run build ``` Open in VS Code or WebStorm. "); zip.file(folder+".gitignore","node_modules/ dist/ .env .DS_Store *.local "); } /* --- Angular (v19 standalone) --- */ function buildAngular(zip,folder,app,code,panelTxt){ var pn=pkgName(app); var C=cc(pn); var sel=pn.replace(/_/g,"-"); var extracted=extractCode(panelTxt); zip.file(folder+"package.json",'{ "name": "'+pn+'", "version": "0.0.0", "scripts": { "ng": "ng", "start": "ng serve", "build": "ng build", "test": "ng test" }, "dependencies": { "@angular/animations": "^19.0.0", "@angular/common": "^19.0.0", "@angular/compiler": "^19.0.0", "@angular/core": "^19.0.0", "@angular/forms": "^19.0.0", "@angular/platform-browser": "^19.0.0", "@angular/platform-browser-dynamic": "^19.0.0", "@angular/router": "^19.0.0", "rxjs": "~7.8.0", "tslib": "^2.3.0", "zone.js": "~0.15.0" }, "devDependencies": { "@angular-devkit/build-angular": "^19.0.0", "@angular/cli": "^19.0.0", "@angular/compiler-cli": "^19.0.0", "typescript": "~5.6.0" } } '); zip.file(folder+"angular.json",'{ "$schema": "./node_modules/@angular/cli/lib/config/schema.json", "version": 1, "newProjectRoot": "projects", "projects": { "'+pn+'": { "projectType": "application", "root": "", "sourceRoot": "src", "prefix": "app", "architect": { "build": { "builder": "@angular-devkit/build-angular:application", "options": { "outputPath": "dist/'+pn+'", "index": "src/index.html", "browser": "src/main.ts", "tsConfig": "tsconfig.app.json", "styles": ["src/styles.css"], "scripts": [] } }, "serve": {"builder":"@angular-devkit/build-angular:dev-server","configurations":{"production":{"buildTarget":"'+pn+':build:production"},"development":{"buildTarget":"'+pn+':build:development"}},"defaultConfiguration":"development"} } } } } '); zip.file(folder+"tsconfig.json",'{ "compileOnSave": false, "compilerOptions": {"baseUrl":"./","outDir":"./dist/out-tsc","forceConsistentCasingInFileNames":true,"strict":true,"noImplicitOverride":true,"noPropertyAccessFromIndexSignature":true,"noImplicitReturns":true,"noFallthroughCasesInSwitch":true,"paths":{"@/*":["src/*"]},"skipLibCheck":true,"esModuleInterop":true,"sourceMap":true,"declaration":false,"experimentalDecorators":true,"moduleResolution":"bundler","importHelpers":true,"target":"ES2022","module":"ES2022","useDefineForClassFields":false,"lib":["ES2022","dom"]}, "references":[{"path":"./tsconfig.app.json"}] } '); zip.file(folder+"tsconfig.app.json",'{ "extends":"./tsconfig.json", "compilerOptions":{"outDir":"./dist/out-tsc","types":[]}, "files":["src/main.ts"], "include":["src/**/*.d.ts"] } '); zip.file(folder+"src/index.html"," "+slugTitle(pn)+" "); zip.file(folder+"src/main.ts","import { bootstrapApplication } from '@angular/platform-browser'; import { appConfig } from './app/app.config'; import { AppComponent } from './app/app.component'; bootstrapApplication(AppComponent, appConfig) .catch(err => console.error(err)); "); zip.file(folder+"src/styles.css","* { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: system-ui, -apple-system, sans-serif; background: #f9fafb; color: #111827; } "); var hasComp=Object.keys(extracted).some(function(k){return k.indexOf("app.component")>=0;}); if(!hasComp){ zip.file(folder+"src/app/app.component.ts","import { Component } from '@angular/core'; import { RouterOutlet } from '@angular/router'; @Component({ selector: 'app-root', standalone: true, imports: [RouterOutlet], templateUrl: './app.component.html', styleUrl: './app.component.css' }) export class AppComponent { title = '"+pn+"'; } "); zip.file(folder+"src/app/app.component.html","

"+slugTitle(pn)+"

Built with PantheraHive BOS

"); zip.file(folder+"src/app/app.component.css",".app-header{display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:60vh;gap:16px}h1{font-size:2.5rem;font-weight:700;color:#6366f1} "); } zip.file(folder+"src/app/app.config.ts","import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core'; import { provideRouter } from '@angular/router'; import { routes } from './app.routes'; export const appConfig: ApplicationConfig = { providers: [ provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes) ] }; "); zip.file(folder+"src/app/app.routes.ts","import { Routes } from '@angular/router'; export const routes: Routes = []; "); Object.keys(extracted).forEach(function(p){ var fp=p.startsWith("src/")?p:"src/"+p; zip.file(folder+fp,extracted[p]); }); zip.file(folder+"README.md","# "+slugTitle(pn)+" Generated by PantheraHive BOS. ## Setup ```bash npm install ng serve # or: npm start ``` ## Build ```bash ng build ``` Open in VS Code with Angular Language Service extension. "); zip.file(folder+".gitignore","node_modules/ dist/ .env .DS_Store *.local .angular/ "); } /* --- Python --- */ function buildPython(zip,folder,app,code){ var title=slugTitle(app); var pn=pkgName(app); var src=code.replace(/^```[w]* ?/m,"").replace(/ ?```$/m,"").trim(); var reqMap={"numpy":"numpy","pandas":"pandas","sklearn":"scikit-learn","tensorflow":"tensorflow","torch":"torch","flask":"flask","fastapi":"fastapi","uvicorn":"uvicorn","requests":"requests","sqlalchemy":"sqlalchemy","pydantic":"pydantic","dotenv":"python-dotenv","PIL":"Pillow","cv2":"opencv-python","matplotlib":"matplotlib","seaborn":"seaborn","scipy":"scipy"}; var reqs=[]; Object.keys(reqMap).forEach(function(k){if(src.indexOf("import "+k)>=0||src.indexOf("from "+k)>=0)reqs.push(reqMap[k]);}); var reqsTxt=reqs.length?reqs.join(" "):"# add dependencies here "; zip.file(folder+"main.py",src||"# "+title+" # Generated by PantheraHive BOS print(title+" loaded") "); zip.file(folder+"requirements.txt",reqsTxt); zip.file(folder+".env.example","# Environment variables "); zip.file(folder+"README.md","# "+title+" Generated by PantheraHive BOS. ## Setup ```bash python3 -m venv .venv source .venv/bin/activate pip install -r requirements.txt ``` ## Run ```bash python main.py ``` "); zip.file(folder+".gitignore",".venv/ __pycache__/ *.pyc .env .DS_Store "); } /* --- Node.js --- */ function buildNode(zip,folder,app,code){ var title=slugTitle(app); var pn=pkgName(app); var src=code.replace(/^```[w]* ?/m,"").replace(/ ?```$/m,"").trim(); var depMap={"mongoose":"^8.0.0","dotenv":"^16.4.5","axios":"^1.7.9","cors":"^2.8.5","bcryptjs":"^2.4.3","jsonwebtoken":"^9.0.2","socket.io":"^4.7.4","uuid":"^9.0.1","zod":"^3.22.4","express":"^4.18.2"}; var deps={}; Object.keys(depMap).forEach(function(k){if(src.indexOf(k)>=0)deps[k]=depMap[k];}); if(!deps["express"])deps["express"]="^4.18.2"; var pkgJson=JSON.stringify({"name":pn,"version":"1.0.0","main":"src/index.js","scripts":{"start":"node src/index.js","dev":"nodemon src/index.js"},"dependencies":deps,"devDependencies":{"nodemon":"^3.0.3"}},null,2)+" "; zip.file(folder+"package.json",pkgJson); var fallback="const express=require("express"); const app=express(); app.use(express.json()); app.get("/",(req,res)=>{ res.json({message:""+title+" API"}); }); const PORT=process.env.PORT||3000; app.listen(PORT,()=>console.log("Server on port "+PORT)); "; zip.file(folder+"src/index.js",src||fallback); zip.file(folder+".env.example","PORT=3000 "); zip.file(folder+".gitignore","node_modules/ .env .DS_Store "); zip.file(folder+"README.md","# "+title+" Generated by PantheraHive BOS. ## Setup ```bash npm install ``` ## Run ```bash npm run dev ``` "); } /* --- Vanilla HTML --- */ function buildVanillaHtml(zip,folder,app,code){ var title=slugTitle(app); var isFullDoc=code.trim().toLowerCase().indexOf("=0||code.trim().toLowerCase().indexOf("=0; var indexHtml=isFullDoc?code:" "+title+" "+code+" "; zip.file(folder+"index.html",indexHtml); zip.file(folder+"style.css","/* "+title+" — styles */ *{margin:0;padding:0;box-sizing:border-box} body{font-family:system-ui,-apple-system,sans-serif;background:#fff;color:#1a1a2e} "); zip.file(folder+"script.js","/* "+title+" — scripts */ "); zip.file(folder+"assets/.gitkeep",""); zip.file(folder+"README.md","# "+title+" Generated by PantheraHive BOS. ## Open Double-click `index.html` in your browser. Or serve locally: ```bash npx serve . # or python3 -m http.server 3000 ``` "); zip.file(folder+".gitignore",".DS_Store node_modules/ .env "); } /* ===== MAIN ===== */ var sc=document.createElement("script"); sc.src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js"; sc.onerror=function(){ if(lbl)lbl.textContent="Download ZIP"; alert("JSZip load failed — check connection."); }; sc.onload=function(){ var zip=new JSZip(); var base=(_phFname||"output").replace(/.[^.]+$/,""); var app=base.toLowerCase().replace(/[^a-z0-9]+/g,"_").replace(/^_+|_+$/g,"")||"my_app"; var folder=app+"/"; var vc=document.getElementById("panel-content"); var panelTxt=vc?(vc.innerText||vc.textContent||""):""; var lang=detectLang(_phCode,panelTxt); if(_phIsHtml){ buildVanillaHtml(zip,folder,app,_phCode); } else if(lang==="flutter"){ buildFlutter(zip,folder,app,_phCode,panelTxt); } else if(lang==="react-native"){ buildReactNative(zip,folder,app,_phCode,panelTxt); } else if(lang==="swift"){ buildSwift(zip,folder,app,_phCode,panelTxt); } else if(lang==="kotlin"){ buildKotlin(zip,folder,app,_phCode,panelTxt); } else if(lang==="react"){ buildReact(zip,folder,app,_phCode,panelTxt); } else if(lang==="vue"){ buildVue(zip,folder,app,_phCode,panelTxt); } else if(lang==="angular"){ buildAngular(zip,folder,app,_phCode,panelTxt); } else if(lang==="python"){ buildPython(zip,folder,app,_phCode); } else if(lang==="node"){ buildNode(zip,folder,app,_phCode); } else { /* Document/content workflow */ var title=app.replace(/_/g," "); var md=_phAll||_phCode||panelTxt||"No content"; zip.file(folder+app+".md",md); var h=""+title+""; h+="

"+title+"

"; var hc=md.replace(/&/g,"&").replace(//g,">"); hc=hc.replace(/^### (.+)$/gm,"

$1

"); hc=hc.replace(/^## (.+)$/gm,"

$1

"); hc=hc.replace(/^# (.+)$/gm,"

$1

"); hc=hc.replace(/**(.+?)**/g,"$1"); hc=hc.replace(/ {2,}/g,"

"); h+="

"+hc+"

Generated by PantheraHive BOS
"; zip.file(folder+app+".html",h); zip.file(folder+"README.md","# "+title+" Generated by PantheraHive BOS. Files: - "+app+".md (Markdown) - "+app+".html (styled HTML) "); } zip.generateAsync({type:"blob"}).then(function(blob){ var a=document.createElement("a"); a.href=URL.createObjectURL(blob); a.download=app+".zip"; a.click(); URL.revokeObjectURL(a.href); if(lbl)lbl.textContent="Download ZIP"; }); }; document.head.appendChild(sc); }function phShare(){navigator.clipboard.writeText(window.location.href).then(function(){var el=document.getElementById("ph-share-lbl");if(el){el.textContent="Link copied!";setTimeout(function(){el.textContent="Copy share link";},2500);}});}function phEmbed(){var runId=window.location.pathname.split("/").pop().replace(".html","");var embedUrl="https://pantherahive.com/embed/"+runId;var code='';navigator.clipboard.writeText(code).then(function(){var el=document.getElementById("ph-embed-lbl");if(el){el.textContent="Embed code copied!";setTimeout(function(){el.textContent="Get Embed Code";},2500);}});}