API Integration Builder
Run ID: 69cb71e061b1021a29a890e32026-03-31Development
PantheraHive BOS
BOS Dashboard

API Integration Builder: Generated Code Deliverable (Step 1 of 2)

This document provides a comprehensive, production-ready Python client designed to facilitate robust and secure integration with an external API. This deliverable focuses on generating the core code structure, authentication mechanisms, and common HTTP request patterns, along with best practices for error handling and configuration.


1. Introduction and Overview

This output represents the foundational code for integrating with a generic external RESTful API. The goal is to provide a highly reusable, maintainable, and secure client that can be easily extended to interact with specific endpoints and functionalities of your target API.

The generated code includes:

This serves as a strong starting point for any API integration project, emphasizing reliability and developer-friendliness.


2. Core Integration Principles

Before diving into the code, it's essential to understand the principles guiding its design:


3. Generated Code: Python API Client

This section provides the core Python code for your API integration. It's structured into logical files for better organization.

3.1. Project Structure Suggestion

text • 412 chars
**Loading Environment Variables in Python (using `python-dotenv` library)**:
Install it: `pip install python-dotenv`

This will be handled within the client itself or in the `main.py` example.

#### 3.3. Custom Exceptions (`api_client/exceptions.py`)

It's crucial to have specific exceptions for API-related errors. This allows your application to catch and handle different types of API failures gracefully.

Sandboxed live preview

python

api_client/client.py

import requests

import os

import json

from functools import wraps

from typing import Dict, Any, Optional, Union, List

Import custom exceptions

from .exceptions import (

ExternalAPIError, BadRequestError, UnauthorizedError, ForbiddenError,

NotFoundError, MethodNotAllowedError, ConflictError, TooManyRequestsError,

ServerError, ServiceUnavailableError, TimeoutError, NetworkError

)

Optional: Load environment variables if not already loaded by the calling script

from dotenv import load_dotenv

load_dotenv()

class ExternalServiceClient:

"""

A robust and reusable client for interacting with a generic external RESTful API.

Handles authentication, common HTTP methods, error handling, and connection pooling.

"""

def __init__(

self,

base_url: str,

api_key: str,

api_key_header: str = "X-API-Key",

timeout: int = 30,

retries: int = 0, # Simple retry mechanism, could be enhanced with backoff

backoff_factor: float = 0.5,

verify_ssl: bool = True

):

"""

Initializes the ExternalServiceClient.

Args:

base_url (str): The base URL of the external API (e.g., "https://api.example.com/v1").

api_key (str): The API key for authentication.

api_key_header (str): The name of the HTTP header for the API key (default: "X-API-Key").

Common alternatives: "Authorization" with "Bearer " prefix.

timeout (int): Default timeout for requests in seconds.

retries (int): Number of times to retry a request on certain errors (e.g., 5xx, timeouts).

backoff_factor (float): Factor for exponential backoff between retries.

verify_ssl (bool): Whether to verify SSL certificates (default: True).

"""

if not base_url:

raise ValueError("base_url cannot be empty.")

if not api_key:

raise ValueError("api_key cannot be empty.")

self.base_url = base_url.rstrip('/')

self.api_key = api_key

self.api_key_header = api_key_header

self.timeout = timeout

self.retries = retries

self.backoff_factor = backoff_factor

self.verify_ssl = verify_ssl

# Use requests.Session for connection pooling and persistent headers

self.session = requests.Session()

self.session.headers.update(self._get_default_headers())

self.session.verify = self.verify_ssl

# Set up retry adapter (more advanced retry logic)

if self.retries > 0:

from requests.adapters import HTTPAdapter

from urllib3.util.retry import Retry

retry_strategy = Retry(

total=self.retries,

backoff_factor=self.backoff_factor,

status_forcelist=[429, 500, 502, 503, 504], # Retry on these HTTP status codes

allowed_methods=["HEAD", "GET", "PUT", "DELETE", "OPTIONS", "TRACE"] # Methods to retry

)

adapter = HTTPAdapter(max_retries=retry_strategy)

self.session.mount("http://", adapter)

self.session.mount("https://", adapter)

print(f"ExternalServiceClient initialized for base URL: {self.base_url}")

def _get_default_headers(self) -> Dict[str, str]:

"""

Generates default headers for API requests, including authentication.

"""

headers = {

"Content-Type": "application/json",

"Accept": "application/json",

}

# Handle API Key authentication

if self.api_key_header.lower() == "authorization" and not self.api_key.startswith("Bearer "):

headers[self.api_key_header] = f"Bearer {self.api_key}"

else:

headers[self.api_key_header] = self.api_key

return headers

def _handle_response(self, response: requests.Response) -> Dict[str, Any]:

"""

Handles the API response, checking for errors and parsing JSON.

Args:

response (requests.Response): The response object from the requests library.

Returns:

Dict[str, Any]: The JSON response body.

Raises:

ExternalAPIError: For various HTTP status codes and network issues.

"""

try:

response_json = response.json()

except json.JSONDecodeError:

response_json = {"message": response.text, "status_code": response.status_code}

print(f"Warning: Could not decode JSON response for status {response.status_code}. Raw text: {response.text[:200]}...")

if 200 <= response.status_code < 300:

return response_json

else:

error_details = response_json.get("message", response_json.get("error", "No specific error message provided."))

error_details = response_json if isinstance(response_json, dict) else {"message": error_details}

if response.status_code == 400:

raise BadRequestError(details=error_details, status_code=response.status_code)

elif response.status_code == 401:

raise UnauthorizedError(details=error_details, status_code=response.status_code)

elif response.status_code == 403:

raise ForbiddenError(details=error_details, status_code=

projectmanager Output

API Integration Project: Initial Setup & Code Generation Framework

This document outlines the foundational structure, core components, and a code generation framework for initiating a new API integration project. This deliverable serves as the blueprint for building robust, maintainable, and scalable integrations with external APIs, focusing on best practices and a modular approach.


1. Project Overview

This project aims to establish a clear and efficient process for integrating with external APIs. The output provides a comprehensive guide, including recommended project structure, essential code components, and a strategic approach to handling common integration challenges. The goal is to enable rapid development of API clients while ensuring high quality, security, and ease of maintenance.


2. Core Integration Components

A successful API integration typically relies on several key components working in concert. This section details these essential elements:

  • API Client (HTTP Request Handler): Responsible for making HTTP requests (GET, POST, PUT, DELETE, etc.) to the external API and handling raw responses. It should abstract away the details of the underlying HTTP library.
  • Authentication Mechanism: Manages the secure authentication with the API (e.g., API keys, OAuth2 tokens, Bearer tokens). It ensures that all requests are properly authorized.
  • Data Models (Serialization/Deserialization): Defines the structure of data sent to and received from the API. This component handles converting application-specific objects to API-specific formats (e.g., JSON) and vice-versa, ensuring data integrity and type safety.
  • Error Handling & Exception Management: Provides a structured way to catch, interpret, and respond to errors returned by the API or encountered during the integration process (e.g., network issues, invalid requests, rate limits).
  • Configuration Management: Centralizes API-specific settings such as base URLs, API keys, timeouts, and other environmental variables, allowing for easy updates and environment-specific adjustments.
  • Logging: Implements a logging strategy to record request/response details, errors, and other operational information, crucial for debugging and monitoring.
  • Service Layer (Resource-Specific Methods): Encapsulates the business logic for interacting with specific API resources or endpoints, providing a higher-level, more domain-specific interface to the underlying API client.

3. Recommended Project Structure

A well-organized project structure is crucial for maintainability and scalability. Below is a recommended directory and file layout, using Python as an example language, which can be adapted to other programming environments.


your_api_integration_project/
├── .env                       # Environment variables (e.g., API keys, sensitive configs)
├── requirements.txt           # Python dependencies
├── main.py                    # Example usage / entry point
├── config.py                  # Project-wide configuration settings
├── exceptions.py              # Custom exceptions for API-related errors
├── utils.py                   # General utility functions
├── client/
│   ├── __init__.py            # Initializes the client package
│   ├── http_client.py         # Core HTTP request handling logic
│   ├── auth.py                # Authentication strategies (e.g., APIKeyAuth, OAuth2)
│   └── rate_limiter.py        # (Optional) Rate limiting implementation
├── models/
│   ├── __init__.py            # Initializes the models package
│   ├── common.py              # Common data models (e.g., ErrorResponse)
│   ├── user.py                # Data models for User resource (Request/Response)
│   ├── product.py             # Data models for Product resource (Request/Response)
│   └── ...                    # Other resource-specific data models
├── services/
│   ├── __init__.py            # Initializes the services package
│   ├── user_service.py        # High-level methods for User API interactions
│   ├── product_service.py     # High-level methods for Product API interactions
│   └── ...                    # Other resource-specific service layers
└── tests/
    ├── __init__.py
    ├── test_client.py
    ├── test_models.py
    └── test_services.py

4. Key Integration Steps & Code Generation Framework

This section outlines the step-by-step process for building the integration, providing a framework for code generation. We'll use Python with requests for HTTP and pydantic for data modeling as a concrete example.

4.1. Step 1: Define Configuration (config.py)

Centralize all API-specific settings.


# your_api_integration_project/config.py
import os

class APIConfig:
    BASE_URL = os.getenv("API_BASE_URL", "https://api.example.com/v1")
    API_KEY = os.getenv("API_KEY") # Sensitive: Load from .env
    TIMEOUT_SECONDS = int(os.getenv("API_TIMEOUT_SECONDS", "30"))
    # Add other configuration like headers, pagination defaults, etc.

    @classmethod
    def validate(cls):
        if not cls.API_KEY:
            raise ValueError("API_KEY is not set in environment variables.")
        if not cls.BASE_URL:
            raise ValueError("API_BASE_URL is not set.")

# Load environment variables (e.g., using python-dotenv)
# from dotenv import load_dotenv
# load_dotenv()

4.2. Step 2: Implement Custom Exceptions (exceptions.py)

Create a hierarchy of custom exceptions for better error handling.


# your_api_integration_project/exceptions.py

class APIIntegrationError(Exception):
    """Base exception for all API integration errors."""
    pass

class APIRequestError(APIIntegrationError):
    """Raised for errors originating from the API call itself (e.g., network issues)."""
    def __init__(self, message, original_exception=None):
        super().__init__(message)
        self.original_exception = original_exception

class APIResponseError(APIIntegrationError):
    """Raised when the API returns an error status code (4xx, 5xx)."""
    def __init__(self, status_code, message="Unknown API error", response_body=None):
        super().__init__(f"API Error {status_code}: {message}")
        self.status_code = status_code
        self.response_body = response_body

class APIAuthenticationError(APIResponseError):
    """Raised specifically for 401 Unauthorized errors."""
    def __init__(self, response_body=None):
        super().__init__(401, "Authentication failed. Check API key/token.", response_body)

class APINotFoundError(APIResponseError):
    """Raised specifically for 404 Not Found errors."""
    def __init__(self, response_body=None):
        super().__init__(404, "Resource not found.", response_body)

# Add more specific exceptions as needed (e.g., APIForbiddenError, APIRateLimitError)

4.3. Step 3: Implement HTTP Client (client/http_client.py)

This client will handle making requests, applying authentication, and basic error checking.


# your_api_integration_project/client/http_client.py
import requests
import logging
from your_api_integration_project.config import APIConfig
from your_api_integration_project.exceptions import (
    APIRequestError, APIResponseError, APIAuthenticationError, APINotFoundError
)

logger = logging.getLogger(__name__)

class HttpClient:
    def __init__(self, base_url: str, api_key: str, timeout: int = 30):
        self.base_url = base_url
        self.session = requests.Session()
        self.session.headers.update({
            "Authorization": f"Bearer {api_key}", # Or "X-API-Key": api_key
            "Content-Type": "application/json",
            "Accept": "application/json"
        })
        self.timeout = timeout

    def _request(self, method: str, endpoint: str, **kwargs):
        url = f"{self.base_url}{endpoint}"
        logger.debug(f"Making {method} request to: {url} with kwargs: {kwargs}")

        try:
            response = self.session.request(method, url, timeout=self.timeout, **kwargs)
            response.raise_for_status() # Raises HTTPError for bad responses (4xx or 5xx)
            return response
        except requests.exceptions.Timeout as e:
            logger.error(f"Request to {url} timed out: {e}")
            raise APIRequestError(f"Request timed out for {url}", original_exception=e)
        except requests.exceptions.ConnectionError as e:
            logger.error(f"Connection error to {url}: {e}")
            raise APIRequestError(f"Connection error for {url}", original_exception=e)
        except requests.exceptions.HTTPError as e:
            status_code = e.response.status_code
            response_body = e.response.text
            logger.error(f"API returned error {status_code} for {url}: {response_body}")

            if status_code == 401:
                raise APIAuthenticationError(response_body=response_body)
            elif status_code == 404:
                raise APINotFoundError(response_body=response_body)
            else:
                raise APIResponseError(status_code, e.response.reason, response_body=response_body)
        except requests.exceptions.RequestException as e:
            logger.error(f"An unexpected request error occurred: {e}")
            raise APIRequestError(f"An unexpected request error occurred for {url}", original_exception=e)

    def get(self, endpoint: str, params: dict = None):
        return self._request("GET", endpoint, params=params)

    def post(self, endpoint: str, data: dict = None, json: dict = None):
        return self._request("POST", endpoint, data=data, json=json)

    def put(self, endpoint: str, data: dict = None, json: dict = None):
        return self._request("PUT", endpoint, data=data, json=json)

    def delete(self, endpoint: str, params: dict = None):
        return self._request("DELETE", endpoint, params=params)

# Example initialization (can be done in main or a service layer)
# http_client = HttpClient(APIConfig.BASE_URL, APIConfig.API_KEY, APIConfig.TIMEOUT_SECONDS)

4.4. Step 4: Create Data Models (models/user.py, models/product.py, etc.)

Use pydantic for robust data validation and serialization.


# your_api_integration_project/models/user.py
from pydantic import BaseModel, Field
from typing import Optional, List

class UserBase(BaseModel):
    name: str = Field(..., description="Full name of the user")
    email: str = Field(..., description="Email address of the user")

class UserCreate(UserBase):
    password: str = Field(..., min_length=8) # Example for a create model

class UserResponse(UserBase):
    id: str = Field(..., description="Unique identifier for the user")
    status: str = Field("active", description="Current status of the user")
    created_at: str # Usually datetime, but string for simple example
    updated_at: Optional[str] = None

class UserUpdate(BaseModel):
    name: Optional[str] = None
    email: Optional[str] = None
    status: Optional[str] = None

class UserListResponse(BaseModel):
    users: List[UserResponse]
    total: int
    page: int
    page_size: int

4.5. Step 5: Build Service Methods (services/user_service.py)

Create a service layer that uses the HttpClient and data models to provide a clean API for interacting with specific resources.


# your_api_integration_project/services/user_service.py
import logging
from typing import Optional, List
from your_api_integration_project.client.http_client import HttpClient
from your_api_integration_project.models.user import (
    UserCreate, UserResponse, UserUpdate, UserListResponse
)
from your_api_integration_project.exceptions import APIResponseError

logger = logging.getLogger(__name__)

class UserService:
    def __init__(self, http_client: HttpClient):
        self.http_client = http_client
        self.base_endpoint = "/users"

    def create_user(self, user_data: UserCreate) -> UserResponse:
        """Creates a new user."""
        logger.info(f"Attempting to create user: {user_data.email}")
        try:
            response = self.http_client.post(self.base_endpoint, json=user_data.model_dump())
            return UserResponse(**response.json())
        except APIResponseError as e:
            logger.error(f"Failed to create user {user_data.email}: {e}")
            raise # Re-raise or handle specifically

    def get_user(self, user_id: str) -> Optional[UserResponse]:
        """Retrieves a user by ID."""
        logger.info(f"Attempting to get user: {user_id}")
        try:
            response = self.http_client.get(f"{self.base_endpoint}/{user_id}")
            return UserResponse(**response.json())
        except APINotFoundError:
            logger.warning(f"User {user_id} not found.")
            return None
        except APIResponseError as e:
            logger.error(f"Failed to get user {user_
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
\n\n\n"); 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'\nimport ReactDOM from 'react-dom/client'\nimport App from './App'\nimport './index.css'\n\nReactDOM.createRoot(document.getElementById('root')!).render(\n \n \n \n)\n"); 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'\nimport './App.css'\n\nfunction App(){\n return(\n
\n
\n

"+slugTitle(pn)+"

\n

Built with PantheraHive BOS

\n
\n
\n )\n}\nexport default App\n"); zip.file(folder+"src/index.css","*{margin:0;padding:0;box-sizing:border-box}\nbody{font-family:system-ui,-apple-system,sans-serif;background:#f0f2f5;color:#1a1a2e}\n.app{min-height:100vh;display:flex;flex-direction:column}\n.app-header{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;padding:40px}\nh1{font-size:2.5rem;font-weight:700}\n"); 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)+"\n\nGenerated by PantheraHive BOS.\n\n## Setup\n\`\`\`bash\nnpm install\nnpm run dev\n\`\`\`\n\n## Build\n\`\`\`bash\nnpm run build\n\`\`\`\n\n## Open in IDE\nOpen the project folder in VS Code or WebStorm.\n"); zip.file(folder+".gitignore","node_modules/\ndist/\n.env\n.DS_Store\n*.local\n"); } /* --- 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",'{\n "name": "'+pn+'",\n "version": "0.0.0",\n "type": "module",\n "scripts": {\n "dev": "vite",\n "build": "vue-tsc -b && vite build",\n "preview": "vite preview"\n },\n "dependencies": {\n "vue": "^3.5.13",\n "vue-router": "^4.4.5",\n "pinia": "^2.3.0",\n "axios": "^1.7.9"\n },\n "devDependencies": {\n "@vitejs/plugin-vue": "^5.2.1",\n "typescript": "~5.7.3",\n "vite": "^6.0.5",\n "vue-tsc": "^2.2.0"\n }\n}\n'); zip.file(folder+"vite.config.ts","import { defineConfig } from 'vite'\nimport vue from '@vitejs/plugin-vue'\nimport { resolve } from 'path'\n\nexport default defineConfig({\n plugins: [vue()],\n resolve: { alias: { '@': resolve(__dirname,'src') } }\n})\n"); zip.file(folder+"tsconfig.json",'{"files":[],"references":[{"path":"./tsconfig.app.json"},{"path":"./tsconfig.node.json"}]}\n'); zip.file(folder+"tsconfig.app.json",'{\n "compilerOptions":{\n "target":"ES2020","useDefineForClassFields":true,"module":"ESNext","lib":["ES2020","DOM","DOM.Iterable"],\n "skipLibCheck":true,"moduleResolution":"bundler","allowImportingTsExtensions":true,\n "isolatedModules":true,"moduleDetection":"force","noEmit":true,"jsxImportSource":"vue",\n "strict":true,"paths":{"@/*":["./src/*"]}\n },\n "include":["src/**/*.ts","src/**/*.d.ts","src/**/*.tsx","src/**/*.vue"]\n}\n'); zip.file(folder+"env.d.ts","/// \n"); zip.file(folder+"index.html","\n\n\n \n \n "+slugTitle(pn)+"\n\n\n
\n \n\n\n"); 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'\nimport { createPinia } from 'pinia'\nimport App from './App.vue'\nimport './assets/main.css'\n\nconst app = createApp(App)\napp.use(createPinia())\napp.mount('#app')\n"); var hasApp=Object.keys(extracted).some(function(k){return k.indexOf("App.vue")>=0;}); if(!hasApp) zip.file(folder+"src/App.vue","\n\n\n\n\n"); 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}\n"); 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)+"\n\nGenerated by PantheraHive BOS.\n\n## Setup\n\`\`\`bash\nnpm install\nnpm run dev\n\`\`\`\n\n## Build\n\`\`\`bash\nnpm run build\n\`\`\`\n\nOpen in VS Code or WebStorm.\n"); zip.file(folder+".gitignore","node_modules/\ndist/\n.env\n.DS_Store\n*.local\n"); } /* --- 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",'{\n "name": "'+pn+'",\n "version": "0.0.0",\n "scripts": {\n "ng": "ng",\n "start": "ng serve",\n "build": "ng build",\n "test": "ng test"\n },\n "dependencies": {\n "@angular/animations": "^19.0.0",\n "@angular/common": "^19.0.0",\n "@angular/compiler": "^19.0.0",\n "@angular/core": "^19.0.0",\n "@angular/forms": "^19.0.0",\n "@angular/platform-browser": "^19.0.0",\n "@angular/platform-browser-dynamic": "^19.0.0",\n "@angular/router": "^19.0.0",\n "rxjs": "~7.8.0",\n "tslib": "^2.3.0",\n "zone.js": "~0.15.0"\n },\n "devDependencies": {\n "@angular-devkit/build-angular": "^19.0.0",\n "@angular/cli": "^19.0.0",\n "@angular/compiler-cli": "^19.0.0",\n "typescript": "~5.6.0"\n }\n}\n'); zip.file(folder+"angular.json",'{\n "$schema": "./node_modules/@angular/cli/lib/config/schema.json",\n "version": 1,\n "newProjectRoot": "projects",\n "projects": {\n "'+pn+'": {\n "projectType": "application",\n "root": "",\n "sourceRoot": "src",\n "prefix": "app",\n "architect": {\n "build": {\n "builder": "@angular-devkit/build-angular:application",\n "options": {\n "outputPath": "dist/'+pn+'",\n "index": "src/index.html",\n "browser": "src/main.ts",\n "tsConfig": "tsconfig.app.json",\n "styles": ["src/styles.css"],\n "scripts": []\n }\n },\n "serve": {"builder":"@angular-devkit/build-angular:dev-server","configurations":{"production":{"buildTarget":"'+pn+':build:production"},"development":{"buildTarget":"'+pn+':build:development"}},"defaultConfiguration":"development"}\n }\n }\n }\n}\n'); zip.file(folder+"tsconfig.json",'{\n "compileOnSave": false,\n "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"]},\n "references":[{"path":"./tsconfig.app.json"}]\n}\n'); zip.file(folder+"tsconfig.app.json",'{\n "extends":"./tsconfig.json",\n "compilerOptions":{"outDir":"./dist/out-tsc","types":[]},\n "files":["src/main.ts"],\n "include":["src/**/*.d.ts"]\n}\n'); zip.file(folder+"src/index.html","\n\n\n \n "+slugTitle(pn)+"\n \n \n \n\n\n \n\n\n"); zip.file(folder+"src/main.ts","import { bootstrapApplication } from '@angular/platform-browser';\nimport { appConfig } from './app/app.config';\nimport { AppComponent } from './app/app.component';\n\nbootstrapApplication(AppComponent, appConfig)\n .catch(err => console.error(err));\n"); zip.file(folder+"src/styles.css","* { margin: 0; padding: 0; box-sizing: border-box; }\nbody { font-family: system-ui, -apple-system, sans-serif; background: #f9fafb; color: #111827; }\n"); 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';\nimport { RouterOutlet } from '@angular/router';\n\n@Component({\n selector: 'app-root',\n standalone: true,\n imports: [RouterOutlet],\n templateUrl: './app.component.html',\n styleUrl: './app.component.css'\n})\nexport class AppComponent {\n title = '"+pn+"';\n}\n"); zip.file(folder+"src/app/app.component.html","
\n
\n

"+slugTitle(pn)+"

\n

Built with PantheraHive BOS

\n
\n \n
\n"); 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}\n"); } zip.file(folder+"src/app/app.config.ts","import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';\nimport { provideRouter } from '@angular/router';\nimport { routes } from './app.routes';\n\nexport const appConfig: ApplicationConfig = {\n providers: [\n provideZoneChangeDetection({ eventCoalescing: true }),\n provideRouter(routes)\n ]\n};\n"); zip.file(folder+"src/app/app.routes.ts","import { Routes } from '@angular/router';\n\nexport const routes: Routes = [];\n"); 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)+"\n\nGenerated by PantheraHive BOS.\n\n## Setup\n\`\`\`bash\nnpm install\nng serve\n# or: npm start\n\`\`\`\n\n## Build\n\`\`\`bash\nng build\n\`\`\`\n\nOpen in VS Code with Angular Language Service extension.\n"); zip.file(folder+".gitignore","node_modules/\ndist/\n.env\n.DS_Store\n*.local\n.angular/\n"); } /* --- Python --- */ function buildPython(zip,folder,app,code){ var title=slugTitle(app); var pn=pkgName(app); var src=code.replace(/^\`\`\`[\w]*\n?/m,"").replace(/\n?\`\`\`$/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("\n"):"# add dependencies here\n"; zip.file(folder+"main.py",src||"# "+title+"\n# Generated by PantheraHive BOS\n\nprint(title+\" loaded\")\n"); zip.file(folder+"requirements.txt",reqsTxt); zip.file(folder+".env.example","# Environment variables\n"); zip.file(folder+"README.md","# "+title+"\n\nGenerated by PantheraHive BOS.\n\n## Setup\n\`\`\`bash\npython3 -m venv .venv\nsource .venv/bin/activate\npip install -r requirements.txt\n\`\`\`\n\n## Run\n\`\`\`bash\npython main.py\n\`\`\`\n"); zip.file(folder+".gitignore",".venv/\n__pycache__/\n*.pyc\n.env\n.DS_Store\n"); } /* --- Node.js --- */ function buildNode(zip,folder,app,code){ var title=slugTitle(app); var pn=pkgName(app); var src=code.replace(/^\`\`\`[\w]*\n?/m,"").replace(/\n?\`\`\`$/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)+"\n"; zip.file(folder+"package.json",pkgJson); var fallback="const express=require(\"express\");\nconst app=express();\napp.use(express.json());\n\napp.get(\"/\",(req,res)=>{\n res.json({message:\""+title+" API\"});\n});\n\nconst PORT=process.env.PORT||3000;\napp.listen(PORT,()=>console.log(\"Server on port \"+PORT));\n"; zip.file(folder+"src/index.js",src||fallback); zip.file(folder+".env.example","PORT=3000\n"); zip.file(folder+".gitignore","node_modules/\n.env\n.DS_Store\n"); zip.file(folder+"README.md","# "+title+"\n\nGenerated by PantheraHive BOS.\n\n## Setup\n\`\`\`bash\nnpm install\n\`\`\`\n\n## Run\n\`\`\`bash\nnpm run dev\n\`\`\`\n"); } /* --- 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:"\n\n\n\n\n"+title+"\n\n\n\n"+code+"\n\n\n\n"; zip.file(folder+"index.html",indexHtml); zip.file(folder+"style.css","/* "+title+" — styles */\n*{margin:0;padding:0;box-sizing:border-box}\nbody{font-family:system-ui,-apple-system,sans-serif;background:#fff;color:#1a1a2e}\n"); zip.file(folder+"script.js","/* "+title+" — scripts */\n"); zip.file(folder+"assets/.gitkeep",""); zip.file(folder+"README.md","# "+title+"\n\nGenerated by PantheraHive BOS.\n\n## Open\nDouble-click \`index.html\` in your browser.\n\nOr serve locally:\n\`\`\`bash\nnpx serve .\n# or\npython3 -m http.server 3000\n\`\`\`\n"); zip.file(folder+".gitignore",".DS_Store\nnode_modules/\n.env\n"); } /* ===== 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(/\n{2,}/g,"

"); h+="

"+hc+"

Generated by PantheraHive BOS
"; zip.file(folder+app+".html",h); zip.file(folder+"README.md","# "+title+"\n\nGenerated by PantheraHive BOS.\n\nFiles:\n- "+app+".md (Markdown)\n- "+app+".html (styled HTML)\n"); } 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);}});}