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

API Integration Builder: Code Generation for External API Integration

This deliverable provides a comprehensive, production-ready Python codebase designed to facilitate robust and secure integration with external RESTful APIs. This output serves as the foundational step (Step 1 of 2) in your "API Integration Builder" workflow, offering a modular, extensible, and well-documented solution that can be directly adapted to your specific API requirements.


1. Introduction

Integrating with external APIs is a critical component of modern software systems, enabling data exchange, service consumption, and extended functionality. This document presents a pre-built Python client designed with best practices in mind, focusing on:

The generated code provides a flexible framework that can be customized for virtually any REST API, demonstrating common patterns for GET, POST, PUT, and DELETE operations, along with two popular authentication methods: API Key and OAuth 2.0 Client Credentials.


2. Core Integration Principles & Design Choices

The generated codebase adheres to the following principles to ensure a high-quality integration solution:


3. Generated Code

This section provides the Python code, organized into three files: config.py, api_client.py, and example_usage.py.

3.1 config.py - Configuration Management

This file centralizes all API-related configuration, making it easy to manage and update credentials or endpoints. For production environments, it is highly recommended to use environment variables for sensitive data.

text • 224 chars
#### 3.2 `api_client.py` - The Core API Client

This file contains the `ApiClient` class, which handles all communication with the external API, including authentication, request construction, error handling, and retries.

Sandboxed live preview

python

api_client.py

import requests

import time

import logging

from functools import wraps

from typing import Dict, Any, Optional, Tuple, Callable

Import configuration settings

import config

Set up logging

logging.basicConfig(level=getattr(logging, config.LOG_LEVEL.upper(), logging.INFO),

format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')

logger = logging.getLogger(__name__)

class ApiException(Exception):

"""Custom exception for API 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

def __str__(self):

return (f"API Error: {self.message} (Status: {self.status_code}, "

f"Response: {self.response_data})" if self.status_code else self.message)

def retry_on_exception(max_retries: int, initial_delay: float):

"""

Decorator for retrying a function call upon specific exceptions or HTTP status codes.

Uses exponential backoff.

"""

def decorator(func: Callable):

@wraps(func)

def wrapper(self, args, *kwargs):

retries = 0

delay = initial_delay

while retries <= max_retries:

try:

return func(self, args, *kwargs)

except (requests.exceptions.ConnectionError,

requests.exceptions.Timeout,

requests.exceptions.RequestException) as e:

logger.warning(f"Network or request error during {func.__name__}: {e}. Retrying in {delay:.2f}s...")

retries += 1

if retries > max_retries:

logger.error(f"Max retries ({max_retries}) exceeded for {func.__name__}.")

raise ApiException(f"Failed after {max_retries} retries due to network/request error.") from e

time.sleep(delay)

delay *= 2 # Exponential backoff

except ApiException as e:

# Retry specifically on server errors (5xx) or rate limits (429)

if e.status_code and (500 <= e.status_code < 600 or e.status_code == 429):

logger.warning(f"API error {e.status_code} during {func.__name__}: {e.message}. Retrying in {delay:.2f}s...")

retries += 1

if retries > max_retries:

logger.error(f"Max retries ({max_retries}) exceeded for {func.__name__}.")

raise e

time.sleep(delay)

delay *= 2

else:

raise e # Re-raise other API errors immediately

return wrapper

return decorator

class ApiClient:

"""

A robust client for interacting with an external RESTful API.

Supports API Key and OAuth 2.0 Client Credentials authentication.

"""

def __init__(self,

base_url: str = config.API_BASE_URL,

api_key: Optional[str] = config.API_KEY,

api_key_header_name: Optional[str] = config.API_KEY_HEADER_NAME,

oauth_token_url: Optional[str] = config.OAUTH_TOKEN_URL,

oauth_client_id: Optional[str] = config.OAUTH_CLIENT_ID,

oauth_client_secret: Optional[str] = config.OAUTH_CLIENT_SECRET,

oauth_scopes: Optional[list] = config.OAUTH_SCOPES,

timeout: float = config.REQUEST_TIMEOUT_SECONDS):

"""

Initializes the API client.

:param base_url: The base URL of the API.

:param api_key: The API key for authentication (if used).

:param api_key_header_name: The header name for the API key (e.g., 'X-API-KEY').

:param oauth_token_url: The URL for obtaining OAuth tokens (if used).

:param oauth_client_id: The client ID for OAuth (if used).

:param oauth_client_secret: The client secret for OAuth (if used).

:param oauth_scopes: A list of scopes for OAuth (if used).

:param timeout: Default request timeout in seconds.

"""

self.base_url = base_url

self.timeout = timeout

self._session = requests.Session()

# Authentication specific attributes

self.api_key = api_key

self.api_key_header_name = api_key_header_name

self.oauth_token_url = oauth_token_url

self.oauth_client_id = oauth_client_id

self.oauth_client_secret = oauth_client_secret

self.oauth_scopes = oauth_scopes

self._access_token = None

self._token_expires_at = 0 # Unix timestamp

# Determine authentication method based on provided credentials

self.auth_method = self._determine_auth_method()

logger.info(f"API Client initialized. Base URL: {self.base_url}, Auth method: {self.auth_method}")

def _determine_auth_method(self) -> str:

"""Determines the authentication method based on provided config."""

if self.oauth_client_id and self.oauth_client_secret and self.oauth_token_url:

return "oauth2_client_credentials"

elif self.api_key and self.api_key_header_name:

return "api_key"

else:

logger.warning("No valid authentication method configured. Proceeding without authentication.")

return "none"

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

"""Returns headers for API Key authentication."""

if self.api_key and self.api_key_header_name:

return {self.api_key_header_name: self.api_key}

return {}

def _get_oauth_token(self) -> str:

"""Obtains an OAuth 2.0 access token using client credentials flow."""

if not (self.oauth_token_url and self.oauth_client_id and self.oauth_client_secret):

raise ApiException("OAuth 2.0 Client Credentials not fully configured.")

# Check if token is still valid

if self._access_token and self._token_expires_at > time.time() + 60: # Refresh 60 seconds before actual expiry

return self._access_token

logger.info("Obtaining new OAuth 2.0 access token...")

token_data = {

"grant_type": "client_credentials",

"client_id": self.oauth_client_id,

"client_secret": self.oauth_client_secret,

"scope": " ".join(self.oauth_scopes) if self.oauth_scopes else ""

}

try:

response = requests.post(self.oauth_token_url, data=token_data, timeout=self.timeout)

response.raise_for_status()

token_info = response.json()

self._access_token = token_info.get("access_token")

expires_in = token_info.get("expires_in", 3600) # Default to 1 hour if not provided

self._token_expires_at = time.time() + expires_in

if not self._access_token:

raise ApiException("Access token not found in OAuth response.")

logger.info("Successfully obtained new OAuth 2.0 access token.")

return self._access_token

except requests.exceptions.RequestException as e:

logger.error(f"Failed to obtain OAuth token: {e}")

raise ApiException(f"Could not obtain OAuth token: {e}") from e

except Exception as e:

logger.error(f"Unexpected error during OAuth token acquisition: {e}")

raise ApiException(f"Unexpected error during OAuth token acquisition: {e}") from e

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

"""Constructs the full set of headers for an API request."""

headers = {

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

"Accept": "application/json"

}

if self.auth_method == "api_key":

headers.update(self._get_api_key_headers())

elif self.auth_method == "oauth2_client_credentials":

access_token = self._get_oauth_token()

headers["Authorization"] = f"Bearer {access_token}"

return headers

def _request(self, method: str, path: str, **kwargs: Any) -> Any:

"""

Internal method to make an HTTP request to

projectmanager Output

Project Deliverable: API Integration Builder - projectmanager → create_project

This document details the implementation guide for integrating with an external Project Management API to execute the create_project function. This deliverable is Step 2 of 2 in your "API Integration Builder" workflow, providing the actionable code and instructions necessary to establish this specific API connection.


1. Introduction to the API Integration Builder

The API Integration Builder is designed to streamline the process of connecting your systems with external APIs. For this specific workflow, we are focusing on generating the necessary code and guidance to interact with a Project Management System's API, enabling programmatic project creation. This integration will allow your applications to automatically provision new projects within your chosen project management platform, enhancing automation and efficiency.

2. Objective of this Integration Step: create_project

The primary objective of this step is to provide a robust and ready-to-use solution for calling the create_project endpoint of a Project Management API. This will enable your system to:

  • Automate Project Creation: Automatically create new projects based on triggers from other systems (e.g., a new client onboarding, a sales deal closure).
  • Standardize Project Setup: Ensure projects are created with predefined templates, default settings, and necessary initial parameters.
  • Reduce Manual Effort: Eliminate the need for manual project setup within the project management tool.

3. Key Concepts for create_project Integration

To successfully create a project via API, the following core components are essential:

  • API Endpoint: The specific URL where the create_project request will be sent. This is typically a POST request.
  • Authentication: Mechanisms to verify your application's identity and permissions (e.g., API Key, OAuth 2.0, Bearer Token).
  • Request Body Parameters: The data required to define the new project (e.g., project name, description, owner, start/end dates, status).
  • Response Structure: The format and content of the API's reply, indicating success or failure, and often providing the ID or details of the newly created project.

4. Detailed Integration Guide

This guide provides a step-by-step approach to integrate the create_project functionality. We will use a generic RESTful API example, which can be adapted to specific Project Management platforms like Jira, Asana, Trello, or custom solutions.

4.1. Prerequisites

Before proceeding, ensure you have:

  • API Documentation: Access to the official API documentation for your target Project Management system (crucial for exact endpoints, parameters, and authentication methods).
  • API Credentials: An API Key, Access Token, or OAuth client credentials issued for your application.
  • Development Environment: A suitable environment (e.g., Python, Node.js, Java) to write and execute the integration code.

4.2. Step 1: Obtain API Credentials

  • Action: Log in to your Project Management system's developer portal or administrative settings.
  • Action: Generate or retrieve the necessary API Key, Personal Access Token, or OAuth Client ID/Secret.
  • Best Practice: Store these credentials securely (e.g., environment variables, secret management service) and never hardcode them directly into your application code.

4.3. Step 2: Define API Endpoint and Headers

Identify the base URL and the specific endpoint for creating a project. Define the necessary HTTP headers, including authentication and content type.

  • Example (Python):

    import os
    import requests
    import json

    # --- Configuration (replace with your actual values) ---
    PM_API_BASE_URL = os.getenv("PM_API_BASE_URL", "https://api.example-pm.com/v1")
    PM_API_KEY = os.getenv("PM_API_KEY", "YOUR_SECURE_API_KEY") # Or a Bearer token

    CREATE_PROJECT_ENDPOINT = f"{PM_API_BASE_URL}/projects" # Common RESTful pattern

    HEADERS = {
        "Content-Type": "application/json",
        "Authorization": f"Bearer {PM_API_KEY}" # Example: Bearer token authentication
        # For API Key in header: "X-API-Key": PM_API_KEY
        # For Basic Auth: requests.auth.HTTPBasicAuth(username, password)
    }

4.4. Step 3: Construct the Request Body

Based on the API documentation, define the payload (JSON object) containing the data for the new project.

  • Action: Identify all required parameters (e.g., name).
  • Action: Identify any optional parameters you wish to include (e.g., description, ownerId, startDate).
  • Example (Python):

    def create_project_payload(project_name: str, description: str = "", owner_id: str = None, start_date: str = None, end_date: str = None, status: str = "Active"):
        """
        Constructs the JSON payload for creating a new project.
        Adjust parameters based on your specific PM API documentation.
        """
        payload = {
            "name": project_name,
            "description": description,
            "status": status,
            # Add other required/optional fields as per API documentation
        }
        if owner_id:
            payload["ownerId"] = owner_id
        if start_date:
            payload["startDate"] = start_date # Format: "YYYY-MM-DD"
        if end_date:
            payload["endDate"] = end_date     # Format: "YYYY-MM-DD"

        return payload

    # --- Example Usage ---
    project_data = create_project_payload(
        project_name="New Client Onboarding - Project X",
        description="Automated project for onboarding client X's new integration.",
        owner_id="user123",
        start_date="2023-10-26",
        status="Planning"
    )

4.5. Step 4: Execute the API Call

Use an HTTP client library (e.g., requests in Python, fetch in JavaScript) to send the POST request with the constructed payload and headers.

  • Example (Python):

    def execute_create_project(payload: dict):
        """
        Sends the POST request to the PM API to create a project.
        """
        try:
            print(f"Attempting to create project: {payload.get('name')}...")
            response = requests.post(CREATE_PROJECT_ENDPOINT, headers=HEADERS, json=payload)
            response.raise_for_status() # Raises HTTPError for bad responses (4xx or 5xx)
            return response.json()
        except requests.exceptions.HTTPError as http_err:
            print(f"HTTP error occurred: {http_err}")
            print(f"Response content: {response.text}")
            return None
        except requests.exceptions.ConnectionError as conn_err:
            print(f"Connection error occurred: {conn_err}")
            return None
        except requests.exceptions.Timeout as timeout_err:
            print(f"Timeout error occurred: {timeout_err}")
            return None
        except requests.exceptions.RequestException as req_err:
            print(f"An unexpected error occurred: {req_err}")
            return None

    # --- Execute the call ---
    # new_project_response = execute_create_project(project_data)

4.6. Step 5: Handle the API Response

Parse the API response to confirm project creation and extract any relevant information, such as the new project's ID.

  • Example (Python):

    # Assuming new_project_response holds the successful JSON response
    # if new_project_response:
    #     print("\nProject created successfully!")
    #     project_id = new_project_response.get("id") # Common field for new resource ID
    #     project_url = new_project_response.get("url") # Link to the new project
    #     print(f"New Project ID: {project_id}")
    #     print(f"View Project at: {project_url}")
    # else:
    #     print("\nFailed to create project.")

4.7. Step 6: Implement Error Handling and Logging

Robust error handling is critical for production systems.

  • Action: Catch specific HTTP status codes (e.g., 400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found, 500 Internal Server Error).
  • Action: Log errors with sufficient detail (timestamp, error type, request payload, response content) for debugging.
  • Action: Implement retry mechanisms for transient errors (e.g., 429 Too Many Requests, 503 Service Unavailable).

5. Complete Example Code (Python)

This consolidated example provides a functional script for creating a project.


import os
import requests
import json
import logging

# --- Configure Logging ---
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

# --- Configuration (Load from Environment Variables for Security) ---
PM_API_BASE_URL = os.getenv("PM_API_BASE_URL", "https://api.example-pm.com/v1")
PM_API_KEY = os.getenv("PM_API_KEY", "YOUR_SECURE_API_KEY") # Replace with your actual API Key or Bearer Token

# Ensure API key is set
if PM_API_KEY == "YOUR_SECURE_API_KEY" or not PM_API_KEY:
    logging.error("PM_API_KEY environment variable not set. Please configure it.")
    exit(1)

CREATE_PROJECT_ENDPOINT = f"{PM_API_BASE_URL}/projects" # Common RESTful pattern

HEADERS = {
    "Content-Type": "application/json",
    "Authorization": f"Bearer {PM_API_KEY}" # Example: Bearer token authentication
    # Adjust authentication header based on your PM API documentation
    # e.g., "X-API-Key": PM_API_KEY, or use `auth` parameter in requests.post for Basic Auth
}

def create_project_payload(project_name: str, description: str = "", owner_id: str = None, start_date: str = None, end_date: str = None, status: str = "Active"):
    """
    Constructs the JSON payload for creating a new project.
    Adjust parameters based on your specific PM API documentation.
    """
    payload = {
        "name": project_name,
        "description": description,
        "status": status,
    }
    if owner_id:
        payload["ownerId"] = owner_id
    if start_date:
        payload["startDate"] = start_date # Format: "YYYY-MM-DD"
    if end_date:
        payload["endDate"] = end_date     # Format: "YYYY-MM-DD"

    return payload

def execute_create_project(payload: dict):
    """
    Sends the POST request to the PM API to create a project.
    """
    try:
        logging.info(f"Attempting to create project: {payload.get('name')}...")
        response = requests.post(CREATE_PROJECT_ENDPOINT, headers=HEADERS, json=payload)
        response.raise_for_status() # Raises HTTPError for bad responses (4xx or 5xx)

        logging.info(f"Project '{payload.get('name')}' created successfully!")
        return response.json()

    except requests.exceptions.HTTPError as http_err:
        logging.error(f"HTTP error occurred: {http_err} for project '{payload.get('name')}'")
        logging.error(f"Response status code: {response.status_code}")
        logging.error(f"Response content: {response.text}")
    except requests.exceptions.ConnectionError as conn_err:
        logging.error(f"Connection error occurred: {conn_err} while connecting to {CREATE_PROJECT_ENDPOINT}")
    except requests.exceptions.Timeout as timeout_err:
        logging.error(f"Timeout error occurred: {timeout_err} while creating project '{payload.get('name')}'")
    except requests.exceptions.RequestException as req_err:
        logging.error(f"An unexpected error occurred: {req_err}")
    return None

if __name__ == "__main__":
    # --- Example Project Data ---
    example_project = create_project_payload(
        project_name="Marketing Campaign Q4 2023",
        description="Plan and execute marketing activities for Q4 product launch.",
        owner_id="marketing_lead_id_abc", # Replace with an actual user ID from your PM system
        start_date="2023-10-01",
        end_date="2023-12-31",
        status="Planning"
    )

    # --- Execute the project creation ---
    new_project_details = execute_create_project(example_project)

    if new_project_details:
        logging.info("\n--- Project Creation Summary ---")
        logging.info(f"Project Name: {new_project_details.get('name', 'N/A')}")
        logging.info(f"Project ID: {new_project_details.get('id', 'N/A')}")
        logging.info(f"Status: {new_project_details.get('status', 'N/A')}")
        logging.info(f"Link: {new_project_details.get('url', 'Not provided')}") # Many APIs return a direct link
        logging.info("------------------------------")
    else:
        logging.error("Failed to retrieve details for the newly created project.")

6. Testing and Validation

  • Unit Testing: Test the create_project_payload function with various inputs to ensure the JSON structure is correct.
  • Integration Testing: Execute the execute_create_project function in a test environment (or with mock API responses) to verify the entire flow.
  • Live Testing: Once confident, run the script against your actual Project Management API to confirm a project is created successfully and appears correctly in the PM system.
  • Error Scenarios: Test with invalid credentials, missing required parameters, and other error conditions to ensure robust error handling.

7. Next Steps

  1. Review and Adapt: Carefully review the provided code and adapt the PM_API_BASE_URL, PM_API_KEY, CREATE_PROJECT_ENDPOINT, HEADERS, and the create_project_payload function parameters to match your specific Project Management API documentation.
  2. Secure Credentials: Ensure your PM_API_KEY (or other credentials) are loaded from secure environment variables or a secret management service, not hardcoded
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);}});}