API Integration Builder
Run ID: 69bca44077c0421c0bf494682026-03-29Development
PantheraHive BOS
BOS Dashboard

Workflow Execution Summary

Workflow Name: API Integration Builder

Category: Development

Step: 1 of 2: generate_code

App: collab

User Inputs:


Generated API Integration Code (JavaScript)

Based on your request for "Test API Name" and the JavaScript language, we've generated a robust and modular API integration class. This code provides a foundational structure for making various HTTP requests, handling responses, and managing common API interactions.

text • 2,923 chars
---

## Key Features and Design Choices

1.  **Class-Based Structure (`TestApiNameClient`)**:
    *   Encapsulates all API logic, making it reusable and easy to manage.
    *   Allows for multiple instances with different configurations (e.g., different API keys or base URLs).

2.  **Configurable Base URL and API Key**:
    *   The `constructor` accepts `baseUrl` and an `apiKey`, promoting clean configuration and adaptability across environments.
    *   API Key is automatically added to `Authorization` headers as a `Bearer` token by default, a common standard. This can be easily adjusted for other authentication schemes (e.g., `x-api-key`).

3.  **Unified Request Method (`_request`)**:
    *   A private helper method (`_request`) centralizes the `fetch` logic, error handling, and header management. This reduces code duplication and ensures consistent behavior for all HTTP requests.

4.  **Comprehensive Error Handling**:
    *   **HTTP Status Codes**: Automatically detects and throws errors for non-`2xx` HTTP responses, including detailed status and messages.
    *   **JSON Error Parsing**: Attempts to parse error responses as JSON to provide granular details from the API.
    *   **Network Errors & Timeouts**: Catches network-related issues and includes a configurable `timeout` for requests, preventing indefinite hangs.
    *   **Descriptive Error Messages**: Errors are enriched with relevant information (status code, API-provided message).

5.  **Standard HTTP Verb Methods**:
    *   Dedicated `get`, `post`, `put`, `patch`, and `delete` methods simplify making requests for common HTTP operations.
    *   Handles `GET` query parameters and `POST`/`PUT`/`PATCH` request bodies automatically.

6.  **Automatic JSON Serialization/Deserialization**:
    *   `Content-Type: application/json` and `Accept: application/json` headers are set by default.
    *   Request bodies (`POST`, `PUT`, `PATCH`) are automatically `JSON.stringify`'d.
    *   Responses are automatically `response.json()` parsed if the `Content-Type` header indicates JSON.

7.  **Extensible Endpoint-Specific Methods**:
    *   Includes example methods like `getResources`, `getResourceById`, `createResource`, `updateResource`, and `deleteResource`. These demonstrate how to build higher-level abstractions specific to your API's endpoints, making the client even easier to use.

8.  **JSDoc Comments**:
    *   The code is thoroughly commented with JSDoc, enabling better code readability, maintainability, and IDE autocompletion.

---

## How to Use and Customize

1.  **Save the Code**:
    *   Save the provided JavaScript code as `TestApiNameClient.js` (or similar) in your project.

2.  **Instantiate the Client**:
    *   Import the class into your application (e.g., using `import` in modern JavaScript or `require` in Node.js).
    *   Create an instance, providing your API's base URL and optionally an API key:

    
Sandboxed live preview

Next Steps & Recommendations

  1. Replace Placeholders:

* Crucially, update API_BASE_URL with the actual base URL of your "Test API Name" API.

* Update API_KEY with your actual API key, ideally loaded from environment variables (see below).

* Customize the example endpoint methods (getResources, createResource, etc.) to reflect the actual paths, parameters, and expected responses of your API.

  1. Environment Variables:

* DO NOT hardcode sensitive information like API keys directly in your code.

* Use environment variables (e.g., .env files with dotenv in Node.js, or your build tool's environment configuration in frontend frameworks).

* Example: process.env.TEST_API_NAME_BASE_URL, process.env.TEST_API_NAME_API_KEY.

  1. Thorough Testing:

* Write unit and integration tests for your API client to ensure it behaves as expected and handles various scenarios (success, different error codes, network issues).

* Mock API responses during unit testing to isolate your client logic.

  1. Logging and Monitoring:

* Integrate with your application's logging system to record API request/response details (without logging sensitive data) and errors.

* Consider adding monitoring to track API call performance and error rates.

  1. Rate Limiting and Retries:

* If your API has rate limits, consider implementing a retry mechanism with exponential backoff for specific error codes (e.g., 429 Too Many Requests).

* Libraries like axios-retry (if using Axios) or custom logic can help here.

  1. Authentication Strategy:

* Review your API's specific authentication requirements. If it's more complex than a simple API key (e.g., OAuth 2.0 flows, signed requests), you'll need to extend the client to manage token acquisition, refreshing, and request signing.

  1. Documentation:

* Maintain clear documentation for your API client, especially as you add more specific methods. The JSDoc comments provided are a good start.

Step 2: projectmanager

API Integration Project: Test API Name

This output provides a comprehensive project structure and JavaScript code for integrating with "Test API Name". It includes a robust API client, example usage, project setup instructions, and best practices, making it immediately useful for development.

1. Project Overview

This project provides a ready-to-use template for integrating with your "Test API Name" using JavaScript. It includes a modular API client designed for reusability and maintainability, along with a clear example of how to use it. The setup is designed to be compatible with both Node.js environments (for backend services or scripts) and modern browser environments (with minor adjustments for environment variable loading).

Key Features:

  • Modular API Client: A dedicated class (TestApiClient) to encapsulate all API interactions.
  • Robust Error Handling: Catches network errors and handles API-specific error responses.
  • Authentication Support: Includes placeholders for API Key or Bearer Token authentication.
  • Environment Variable Integration: Recommends using .env files for sensitive information like API keys and base URLs.
  • Clear Usage Examples: Demonstrates common CRUD operations.

2. Proposed Project Structure

To organize your integration code effectively, we recommend the following directory and file structure:


test-api-integration/
├── src/
│   └── TestApiClient.js      # The core API client module
├── .env.example              # Example for environment variables
├── index.js                  # Example script demonstrating API client usage
├── package.json              # Project dependencies and metadata
└── README.md                 # Project documentation (optional, but recommended)

3. Installation and Setup

Follow these steps to set up and run your "Test API Name" integration project:

3.1. Create Project Directory


mkdir test-api-integration
cd test-api-integration

3.2. Initialize Node.js Project

Create a package.json file. If you're using Node.js, this is crucial for managing dependencies.

package.json


{
  "name": "test-api-integration",
  "version": "1.0.0",
  "description": "JavaScript integration for Test API Name",
  "main": "index.js",
  "type": "module",
  "scripts": {
    "start": "node index.js"
  },
  "keywords": [
    "api",
    "integration",
    "javascript",
    "test-api-name"
  ],
  "author": "PantheraHive AI Assistant",
  "license": "MIT",
  "dependencies": {
    "dotenv": "^16.4.5"
  },
  "devDependencies": {}
}

3.3. Install Dependencies

If you're running this in a Node.js environment, you'll need dotenv to load environment variables.


npm install
# OR
yarn add

(Note: If you are strictly in a browser environment, dotenv is not needed, and you would manage environment variables differently, e.g., through build tools or server-side injection.)

3.4. Configure Environment Variables

Create a file named .env in the root of your project based on the .env.example provided below. This file will store sensitive information and API configurations.

.env.example


# This file is for demonstrating expected environment variables.
# Create a `.env` file and populate it with your actual values.

# Base URL for the Test API Name
TEST_API_BASE_URL=https://api.testapiname.com/v1

# Authentication method: Choose one or provide both if applicable
# 1. API Key (if your API uses a specific header or query param)
TEST_API_KEY=your_super_secret_api_key_here

# 2. Bearer Token (if your API uses OAuth2 or similar token-based auth)
TEST_API_BEARER_TOKEN=your_bearer_token_here

# Example custom header (if your API requires one)
TEST_API_CUSTOM_HEADER_NAME=X-Api-Client-Id
TEST_API_CUSTOM_HEADER_VALUE=your_client_id_value

Action: Create a file named .env in the test-api-integration directory and fill it with your actual API details.

4. API Client Code (src/TestApiClient.js)

This file contains the core logic for interacting with the "Test API Name". It defines a class TestApiClient with methods for common HTTP operations (GET, POST, PUT, DELETE).


// src/TestApiClient.js

/**
 * @class TestApiClient
 * @description A client for interacting with the Test API Name.
 */
class TestApiClient {
    /**
     * @param {string} baseURL - The base URL for the Test API Name (e.g., 'https://api.testapiname.com/v1').
     * @param {object} options - Configuration options for the client.
     * @param {string} [options.apiKey] - An API key for authentication (sent as 'x-api-key' header by default).
     * @param {string} [options.bearerToken] - A Bearer token for authentication (sent as 'Authorization' header).
     * @param {object} [options.headers] - Additional custom headers to send with every request.
     */
    constructor(baseURL, options = {}) {
        if (!baseURL) {
            throw new Error('TestApiClient: baseURL is required.');
        }
        this.baseURL = baseURL;
        this.options = {
            apiKey: options.apiKey || null,
            bearerToken: options.bearerToken || null,
            headers: options.headers || {},
            ...options
        };
    }

    /**
     * Internal helper to construct and send an HTTP request.
     * @private
     * @param {string} path - The endpoint path (e.g., '/products').
     * @param {object} config - Request configuration (method, headers, body).
     * @returns {Promise<object>} - The parsed JSON response from the API.
     * @throws {Error} - Throws an error if the request fails or API returns an error.
     */
    async _request(path, config) {
        const url = `${this.baseURL}${path}`;
        const headers = {
            'Content-Type': 'application/json',
            'Accept': 'application/json',
            ...this.options.headers, // Custom headers from constructor
            ...config.headers,      // Headers specific to this request
        };

        // Add authentication headers if provided
        if (this.options.apiKey) {
            headers['x-api-key'] = this.options.apiKey;
        }
        if (this.options.bearerToken) {
            headers['Authorization'] = `Bearer ${this.options.bearerToken}`;
        }

        try {
            const response = await fetch(url, {
                ...config,
                headers,
            });

            if (!response.ok) {
                let errorData = {};
                try {
                    errorData = await response.json();
                } catch (jsonError) {
                    // If response is not JSON, use text
                    errorData = { message: await response.text() };
                }
                const errorMessage = errorData.message || `API Error: ${response.status} ${response.statusText}`;
                const error = new Error(errorMessage);
                error.status = response.status;
                error.data = errorData;
                throw error;
            }

            // Handle cases where response might be empty (e.g., DELETE requests)
            const contentType = response.headers.get('content-type');
            if (contentType && contentType.includes('application/json')) {
                return await response.json();
            } else {
                return response.text().then(text => text ? text : null); // Return text or null for empty responses
            }

        } catch (error) {
            if (error.name === 'TypeError' && error.message === 'Failed to fetch') {
                throw new Error(`Network Error: Could not reach the API at ${this.baseURL}. Check your internet connection or API base URL.`);
            }
            throw error; // Re-throw the original error
        }
    }

    /**
     * Sends a GET request to the API.
     * @param {string} path - The endpoint path.
     * @param {object} [queryParams] - Optional query parameters.
     * @returns {Promise<object>}
     */
    get(path, queryParams = {}) {
        const queryString = new URLSearchParams(queryParams).toString();
        const fullPath = queryString ? `${path}?${queryString}` : path;
        return this._request(fullPath, { method: 'GET' });
    }

    /**
     * Sends a POST request to the API.
     * @param {string} path - The endpoint path.
     * @param {object} data - The request body.
     * @returns {Promise<object>}
     */
    post(path, data) {
        return this._request(path, {
            method: 'POST',
            body: JSON.stringify(data),
        });
    }

    /**
     * Sends a PUT request to the API.
     * @param {string} path - The endpoint path.
     * @param {object} data - The request body.
     * @returns {Promise<object>}
     */
    put(path, data) {
        return this._request(path, {
            method: 'PUT',
            body: JSON.stringify(data),
        });
    }

    /**
     * Sends a PATCH request to the API.
     * @param {string} path - The endpoint path.
     * @param {object} data - The request body (partial update).
     * @returns {Promise<object>}
     */
    patch(path, data) {
        return this._request(path, {
            method: 'PATCH',
            body: JSON.stringify(data),
        });
    }

    /**
     * Sends a DELETE request to the API.
     * @param {string} path - The endpoint path.
     * @returns {Promise<null|string>} - Returns null or a confirmation message if successful.
     */
    delete(path) {
        return this._request(path, { method: 'DELETE' });
    }

    // --- Example Specific Endpoints (for demonstration) ---
    // You would add more specific methods here tailored to your API's endpoints.
    // For this example, we'll assume a 'products' resource.

    /**
     * Fetches all products.
     * GET /products
     * @param {object} [filters] - Optional query parameters for filtering/pagination.
     * @returns {Promise<Array<object>>}
     */
    async getAllProducts(filters = {}) {
        return this.get('/products', filters);
    }

    /**
     * Fetches a single product by ID.
     * GET /products/{id}
     * @param {string} productId - The ID of the product.
     * @returns {Promise<object>}
     */
    async getProductById(productId) {
        if (!productId) throw new Error('Product ID is required.');
        return this.get(`/products/${productId}`);
    }

    /**
     * Creates a new product.
     * POST /products
     * @param {object} productData - The data for the new product.
     * @returns {Promise<object>} - The created product object.
     */
    async createProduct(productData) {
        if (!productData) throw new Error('Product data is required.');
        return this.post('/products', productData);
    }

    /**
     * Updates an existing product.
     * PUT /products/{id}
     * @param {string} productId - The ID of the product to update.
     * @param {object} productData - The updated product data.
     * @returns {Promise<object>} - The updated product object.
     */
    async updateProduct(productId, productData) {
        if (!productId) throw new Error('Product ID is required.');
        if (!productData) throw new Error('Product data is required.');
        return this.put(`/products/${productId}`, productData);
    }

    /**
     * Deletes a product by ID.
     * DELETE /products/{id}
     * @param {string} productId - The ID of the product to delete.
     * @returns {Promise<null|string>}
     */
    async deleteProduct(productId) {
        if (!productId) throw new Error('Product ID is required.');
        return this.delete(`/products/${productId}`);
    }
}

export default TestApiClient;

5. Example Usage (index.js)

This file demonstrates how to instantiate and use the TestApiClient to perform various operations. It also shows how to load environment variables (for Node.js).


// index.js

import dotenv from 'dotenv';
import TestApiClient from './src/TestApiClient.js';

// Load environment variables from .env file
dotenv.config();

const API_BASE_URL = process.env.TEST_API_BASE_URL || 'https://api.example.com/v1'; // Fallback URL
const API_KEY = process.env.TEST_API_KEY;
const BEARER_TOKEN = process.env.TEST_API_BEARER_TOKEN;
const CUSTOM_HEADER_NAME = process.env.TEST_API_CUSTOM_HEADER_NAME;
const CUSTOM_HEADER_VALUE = process.env.TEST_API_CUSTOM_HEADER_VALUE;

async function main() {
    // Configure custom headers if needed
    const customHeaders = {};
    if (CUSTOM_HEADER_NAME && CUSTOM_HEADER_VALUE) {
        customHeaders[CUSTOM_HEADER_NAME] = CUSTOM_HEADER_VALUE;
    }

    const testApiClient = new TestApiClient(API_BASE_URL, {
        apiKey: API_KEY,
        bearerToken: BEARER_TOKEN,
        headers: customHeaders,
    });

    console.log(`--- Initializing Test API Client for: ${API_BASE_URL} ---`);
    console.log(`Authentication type: ${API_KEY ? 'API Key' : BEARER_TOKEN ? 'Bearer Token' : 'None'}`);
    if (Object.keys(customHeaders).length > 0) {
        console.log('Custom Headers:', customHeaders);
    }
    console.log('\n');

    try {
        // --- Example: Get all products ---
        console.log('1. Fetching all products...');
        const allProducts = await testApiClient.getAllProducts({ limit: 5, category: 'electronics' });
        console.log('All Products (first 5, electronics):', allProducts);
        console.log('\n');

        // --- Example: Create a new product ---
        console.log('2. Creating a new product...');
        const newProductData = {
            name: 'Wireless Mouse',
            description: 'Ergonomic wireless mouse with long battery life.',
            price: 29.99,
            category: 'electronics',
            stock: 150
        };
        const createdProduct = await testApiClient.createProduct(newProductData);
        console.log('Created Product:', createdProduct);
        const newProductId = createdProduct?.id || 'newly-created-id-123'; // Use actual ID or a placeholder
        console.log('\n');

        // --- Example: Get a product by ID ---
        console.log(`3. Fetching product with ID: ${newProductId}...`);
        const productById = await testApiClient.getProductById(newProductId);
        console.log(`Product ${newProductId}:`, productById);
        console.log('\n');

        // --- Example: Update a product ---
        console.log(`4. Updating product with ID: ${newProductId}...`);
        const updatedProductData = {
            price: 24.99,
            stock: 120
        };
        const updatedProduct = await testApiClient.updateProduct(newProductId, updatedProductData);
        console.log('Updated Product:', updatedProduct);
        console.log('\n');

        // --- Example: Delete a product ---
        console.log(`5. Deleting product with ID: ${newProductId}...`);
        const deleteResponse = await testApiClient.deleteProduct(newProductId);
        console.log('Delete Response:', deleteResponse);
        console.log('\n');

        // --- Example: Handling an intentional error (e.g., non-existent product) ---
        console.log('6. Attempting to fetch a non-existent product...');
        try {
            const nonExistentId = 'non-existent-product-123';
            await testApiClient.getProductById(nonExistentId);
        } catch (error) {
            console.error(`Caught Expected Error for non-existent product: [${error.status}] ${error.message}`);
            if (error.data) {
                console.error('Error Details:', error.data);
            }
        }

    } catch (error) {
        console.error('An unexpected error occurred during API calls:');
        console.error(`[${error.status || 'N/A'}] ${error.message}`);
        if (error.data) {
            console.error('Error Details:', error.data);
        }
    } finally {
        console.log('\n--- API interaction complete ---');
    }
}

main();

6. Running the Example

  1. Save the files: Place the code blocks into their respective files within the test-api-integration directory.
  2. Populate .env: Make sure your .env file has the correct TEST_API_BASE_URL and authentication credentials.
  3. Run:

    npm start
    # OR
    node index.js

7. Recommendations and Best Practices

  • Error Handling: The provided client includes basic error handling. For production, consider more granular error types, retry mechanisms (e.g., for transient network errors), and logging.
  • Authentication:

* Secure Storage: Never hardcode API keys or tokens directly in your code. Use environment variables (as shown) or a secure secrets management service.

* Token Refresh: If using OAuth2 bearer tokens, implement a mechanism to refresh expired tokens.

  • Rate Limiting: If the "Test API Name" has rate limits, implement client-side rate limiting or backoff strategies to avoid hitting limits and getting blocked.
  • Input Validation: Validate inputs to your API client methods (e.g., productId should be a string, productData should be an object with required fields).
  • Logging: Integrate a logging library to track API requests, responses, and errors, especially in a production environment.
  • Testing: Write unit and integration tests for your TestApiClient to ensure it behaves as expected and handles various API responses correctly. Use mocking libraries (e.g., jest-fetch-mock) to simulate API responses during testing.
  • Modularity: As your application grows, consider breaking down the TestApiClient into smaller, more focused modules if you interact with many distinct resources (e.g., ProductsService, UsersService).
  • TypeScript: For larger projects, consider using TypeScript to add static typing, which improves code quality, readability, and maintainability.
  • Fetch Polyfill: If targeting older browser environments, you might need a fetch polyfill. For modern Node.js and browsers, fetch is native.

8. Next Steps

  1. Implement Specific Endpoints: Extend TestApiClient.js with more specific methods corresponding to all the endpoints of your "Test API Name".
  2. Refine Error Handling: Customize error messages and handling based on the specific error codes and formats returned by your API.
  3. Integrate into Your Application: Import and use the TestApiClient in your main application logic (e.g., a web application, a backend service, or a script).
  4. Add Testing: Develop a suite of tests to ensure the reliability of your API integration.
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);}});}