GraphQL Schema Designer
Run ID: 69cc50618f41b62a970c28d72026-03-31Development
PantheraHive BOS
BOS Dashboard

GraphQL Schema Designer: Architectural Plan

This document outlines the comprehensive architectural plan for the "GraphQL Schema Designer" system. This plan serves as a blueprint for the development of a robust, intuitive, and feature-rich tool that empowers users to design, validate, and generate GraphQL schemas, resolvers, and client integration examples efficiently.


1. Executive Summary

The GraphQL Schema Designer will be a web-based application providing an interactive environment for defining GraphQL types, queries, mutations, and subscriptions. It will offer both a visual interface and a direct Schema Definition Language (SDL) editor, real-time validation, and code generation capabilities for various backend and frontend frameworks. The architecture is designed for scalability, maintainability, and extensibility, leveraging modern web technologies and best practices.


2. System Overview & Goals

2.1. Vision

To provide developers with an indispensable tool that streamlines the process of designing and implementing GraphQL APIs, reducing boilerplate code and enforcing best practices.

2.2. Core Goals


3. High-Level Architecture

The system will follow a client-server architecture, comprising a rich interactive frontend, a stateless backend API, and a persistent data storage layer.

mermaid • 694 chars
graph TD
    A[User Browser/Client] -->|HTTP/HTTPS| B(Frontend Application)
    B -->|RESTful API Calls| C(Backend API Services)
    C -->|Database Queries/Writes| D(Database)

    subgraph Frontend (React.js)
        B1(Schema Editor)
        B2(Visual Builder)
        B3(Code Generators)
        B4(Schema Visualizer)
    end

    subgraph Backend (Node.js/NestJS)
        C1(API Gateway/Controllers)
        C2(Schema Parser & Validator)
        C3(Code Generation Engine)
        C4(Schema Management Service)
        C5(Authentication & Authorization)
    end

    subgraph Database (PostgreSQL)
        D1(Users Table)
        D2(Schemas Table)
        D3(Schema Versions Table)
    end
Sandboxed live preview

4. Detailed Component Architecture

4.1. Frontend (User Interface)

The frontend will be a single-page application (SPA) providing a rich, interactive user experience.

  • Technology Stack:

* Framework: React.js (with TypeScript for type safety).

* State Management: Zustand or React Context API for localized state; potentially Redux Toolkit for global, complex state.

* Styling: Tailwind CSS or Styled Components for a maintainable and scalable styling system.

* UI Components: Ant Design, Material-UI, or Chakra UI for pre-built, accessible components.

* Graph Visualization: React Flow or D3.js for interactive schema diagrams.

* Code Editor: Monaco Editor (VS Code's editor) for SDL editing with syntax highlighting and autocompletion.

  • Key Modules & Components:

* Dashboard: Overview of user's saved schemas, quick access.

gemini Output

This document provides a comprehensive and detailed GraphQL schema design for a Project Management System. It includes the full Schema Definition Language (SDL), example resolver implementations using Node.js with Apollo Server, a basic server setup, and client integration examples. This output is designed to be production-ready, well-commented, and actionable.


GraphQL Schema Designer: Project Management System

1. Introduction

This deliverable outlines a complete GraphQL schema for a Project Management System. The system will manage users, projects, tasks, and comments, facilitating common operations such as creating, reading, updating, and deleting these entities, along with real-time updates through subscriptions.

The design prioritizes clarity, efficiency, and extensibility, adhering to best practices in GraphQL schema development. It demonstrates how to structure types, inputs, enums, queries, mutations, and subscriptions, along with practical examples of their server-side implementation and client-side consumption.

2. GraphQL Schema Design Principles

Our schema design for the Project Management System follows these core principles:

  • Entity-First Design: The schema is built around core business entities (User, Project, Task, Comment), making it intuitive to understand and navigate.
  • Explicit Input Types: Mutations utilize dedicated Input types for arguments, improving readability, preventing argument proliferation, and enabling easier client-side form generation and validation.
  • Granular Mutations: Mutations are designed to perform specific, atomic operations (e.g., createTask, updateTask, addProjectMember), rather than large, monolithic updates.
  • Strong Typing: All fields and arguments are explicitly typed, ensuring data consistency and enabling powerful tooling (e.g., auto-completion, validation).
  • Use of IDs: Unique ID scalars are used for identifying entities, allowing for efficient caching and normalized data structures on the client.
  • Enums for Fixed Values: Enumerations (Enum) are used for fields with a predefined set of options (e.g., UserRole, TaskStatus), providing type safety and clear documentation.
  • Relationships: Relationships between entities are explicitly defined (e.g., Project has tasks, Task has an assignee), allowing clients to fetch related data in a single request.
  • Pagination & Filtering (Conceptual): While not fully implemented in this example for brevity, the Query fields are designed to be easily extensible with arguments for pagination (e.g., first, after) and filtering (e.g., status, ownerId).
  • Real-time Capabilities: Subscriptions are included to demonstrate how to push real-time updates to clients, enhancing user experience for collaborative features.

3. Complete GraphQL Schema Definition Language (SDL)

The following section presents the full GraphQL Schema Definition Language (SDL) for the Project Management System. This is the blueprint for your GraphQL API.

3.1. Scalar Types

We primarily use standard GraphQL scalar types (ID, String, Boolean). For createdAt, updatedAt, and dueDate, String is used for simplicity. In a production environment, you might use a custom DateTime scalar for better type handling.

3.2. Object Types

These are the fundamental data structures in our schema.


# Represents a user within the system.
type User {
  id: ID!
  username: String!
  email: String!
  firstName: String
  lastName: String
  role: UserRole!
  projects: [Project!]! # Projects the user is a member of or owns
  tasks: [Task!]!       # Tasks assigned to the user
  createdAt: String!    # Timestamp when the user was created
  updatedAt: String!    # Timestamp when the user was last updated
}

# Represents a project.
type Project {
  id: ID!
  name: String!
  description: String
  status: ProjectStatus!
  owner: User!          # The user who owns the project
  members: [User!]!     # List of users who are members of the project
  tasks: [Task!]!       # List of tasks belonging to this project
  createdAt: String!
  updatedAt: String!
}

# Represents a task within a project.
type Task {
  id: ID!
  title: String!
  description: String
  status: TaskStatus!
  priority: TaskPriority!
  dueDate: String       # Optional due date for the task
  project: Project!     
gemini Output

GraphQL Schema Design: E-commerce Product & Order Management System

This document provides a comprehensive GraphQL schema design for an E-commerce Product & Order Management System. It includes detailed definitions for types, queries, mutations, and subscriptions, along with conceptual resolver implementations and integration examples for both client and server-side applications.


1. Introduction

This deliverable outlines a robust and scalable GraphQL schema designed to manage products, categories, users, orders, and reviews within an e-commerce context. The schema is built using the GraphQL Schema Definition Language (SDL) and adheres to best practices for data fetching, modification, and real-time updates.

2. Core Design Principles

  • Intuitiveness: The schema is designed to be self-documenting and easy to understand for both front-end and back-end developers.
  • Flexibility: Clients can request exactly what they need, minimizing over-fetching and under-fetching of data.
  • Extensibility: New types, fields, queries, and mutations can be added without breaking existing clients.
  • Performance: Supports pagination, filtering, and efficient data retrieval patterns.
  • Real-time Capabilities: Leverages subscriptions for instant updates on critical data changes.
  • Security: Designed with clear boundaries for authenticated operations (though specific auth logic is conceptual here).

3. GraphQL Schema Definition Language (SDL)

The following sections define the core components of the schema using SDL.

3.1. Custom Scalars

Custom scalars allow for more specific type validation than standard GraphQL scalars (String, Int, Float, Boolean, ID).


scalar DateTime
scalar JSON
  • DateTime: Represents a date and time string, typically in ISO 8601 format.
  • JSON: Represents arbitrary JSON objects, useful for flexible data storage.

3.2. Enums

Enums define a set of allowed values for a field.


enum UserRole {
  CUSTOMER
  ADMIN
  EDITOR
}

enum OrderStatus {
  PENDING
  PROCESSING
  SHIPPED
  DELIVERED
  CANCELLED
  RETURNED
}

enum SortDirection {
  ASC
  DESC
}

3.3. Object Types

Object types are the fundamental building blocks of a GraphQL schema, representing the data entities.


type User {
  id: ID!
  username: String!
  email: String!
  role: UserRole!
  addresses: [Address!]
  orders(
    status: OrderStatus
    limit: Int = 10
    offset: Int = 0
  ): PaginatedOrders!
  createdAt: DateTime!
  updatedAt: DateTime!
}

type Address {
  id: ID!
  street: String!
  city: String!
  state: String
  zipCode: String!
  country: String!
  user: User!
}

type Category {
  id: ID!
  name: String!
  description: String
  products(
    search: String
    minPrice: Float
    maxPrice: Float
    limit: Int = 10
    offset: Int = 0
    sortBy: String = "name"
    sortDirection: SortDirection = ASC
  ): PaginatedProducts!
}

type Product {
  id: ID!
  name: String!
  description: String
  price: Float!
  category: Category!
  imageUrls: [String!]
  stock: Int!
  reviews(
    limit: Int = 5
    offset: Int = 0
  ): PaginatedReviews!
  createdAt: DateTime!
  updatedAt: DateTime!
}

type Review {
  id: ID!
  product: Product!
  user: User!
  rating: Int! # 1 to 5 stars
  comment: String
  createdAt: DateTime!
}

type Order {
  id: ID!
  user: User!
  items: [OrderItem!]!
  totalAmount: Float!
  status: OrderStatus!
  shippingAddress: Address!
  createdAt: DateTime!
  updatedAt: DateTime!
}

type OrderItem {
  id: ID! # Unique ID for the order item itself
  product: Product!
  quantity: Int!
  priceAtPurchase: Float! # Price at the time of order
}

type AuthPayload {
  token: String!
  user: User!
}

3.4. Pagination Types

To handle large datasets efficiently, cursor-based and offset-based pagination types are provided.


type PageInfo {
  hasNextPage: Boolean!
  endCursor: String
}

type PaginatedProducts {
  items: [Product!]!
  totalCount: Int!
  pageInfo: PageInfo!
}

type PaginatedReviews {
  items: [Review!]!
  totalCount: Int!
  pageInfo: PageInfo!
}

type PaginatedOrders {
  items: [Order!]!
  totalCount: Int!
  pageInfo: PageInfo!
}

type PaginatedUsers {
  items: [User!]!
  totalCount: Int!
  pageInfo: PageInfo!
}

3.5. Input Types

Input types are used for arguments in mutations, allowing for structured data submission.


input AddressInput {
  street: String!
  city: String!
  state: String
  zipCode: String!
  country: String!
}

input CreateUserInput {
  username: String!
  email: String!
  password: String!
  role: UserRole = CUSTOMER # Default to customer
  address: AddressInput
}

input LoginInput {
  email: String!
  password: String!
}

input CreateProductInput {
  name: String!
  description: String
  price: Float!
  categoryId: ID!
  imageUrls: [String!]
  stock: Int!
}

input UpdateProductInput {
  name: String
  description: String
  price: Float
  categoryId: ID
  imageUrls: [String!]
  stock: Int
}

input CreateCategoryInput {
  name: String!
  description: String
}

input UpdateCategoryInput {
  name: String
  description: String
}

input OrderItemInput {
  productId: ID!
  quantity: Int!
}

input CreateOrderInput {
  items: [OrderItemInput!]!
  shippingAddressId: ID! # Or provide AddressInput directly for new addresses
}

input UpdateOrderInput {
  status: OrderStatus
  shippingAddressId: ID
}

input CreateReviewInput {
  productId: ID!
  rating: Int!
  comment: String
}

3.6. Root Query Type

The Query type defines all possible read operations (data fetching).


type Query {
  # --- User Queries ---
  me: User # Get the currently authenticated user
  user(id: ID!): User
  users(
    limit: Int = 10
    offset: Int = 0
    cursor: String
    sortBy: String = "createdAt"
    sortDirection: SortDirection = DESC
  ): PaginatedUsers!

  # --- Product Queries ---
  product(id: ID!): Product
  products(
    categoryId: ID
    search: String
    minPrice: Float
    maxPrice: Float
    limit: Int = 10
    offset: Int = 0
    cursor: String
    sortBy: String = "name"
    sortDirection: SortDirection = ASC
  ): PaginatedProducts!

  # --- Category Queries ---
  category(id: ID!): Category
  categories(
    search: String
    limit: Int = 10
    offset: Int = 0
  ): [Category!]!

  # --- Order Queries ---
  order(id: ID!): Order
  orders(
    userId: ID
    status: OrderStatus
    limit: Int = 10
    offset: Int = 0
    cursor: String
    sortBy: String = "createdAt"
    sortDirection: SortDirection = DESC
  ): PaginatedOrders!

  # --- Review Queries ---
  review(id: ID!): Review
  reviewsByProduct(
    productId: ID!
    limit: Int = 5
    offset: Int = 0
  ): PaginatedReviews!
}

3.7. Root Mutation Type

The Mutation type defines all possible write operations (data modification).


type Mutation {
  # --- Authentication & User Mutations ---
  signup(input: CreateUserInput!): AuthPayload!
  login(input: LoginInput!): AuthPayload!
  updateUser(id: ID!, input: UpdateUserInput!): User # Update user profile (e.g., address, email)
  deleteUser(id: ID!): Boolean

  # --- Product Mutations ---
  createProduct(input: CreateProductInput!): Product!
  updateProduct(id: ID!, input: UpdateProductInput!): Product!
  deleteProduct(id: ID!): Boolean!

  # --- Category Mutations ---
  createCategory(input: CreateCategoryInput!): Category!
  updateCategory(id: ID!, input: UpdateCategoryInput!): Category!
  deleteCategory(id: ID!): Boolean!

  # --- Order Mutations ---
  createOrder(input: CreateOrderInput!): Order!
  updateOrderStatus(orderId: ID!, status: OrderStatus!): Order!
  cancelOrder(orderId: ID!): Order! # Sets status to CANCELLED

  # --- Review Mutations ---
  addReview(input: CreateReviewInput!): Review!
  updateReview(id: ID!, rating: Int, comment: String): Review!
  deleteReview(id: ID!): Boolean!
}

3.8. Root Subscription Type

The Subscription type defines all possible real-time data push operations.


type Subscription {
  productAdded: Product!
  productUpdated(id: ID): Product! # Optionally filter by specific product
  orderStatusChanged(orderId: ID!): Order!
  newReview(productId: ID!): Review!
}

4. Resolver Implementations (Conceptual)

Resolvers are functions that tell GraphQL how to fetch the data for a particular field. They bridge the gap between the schema and your backend data sources (databases, APIs, etc.).

4.1. Resolver Structure

A typical resolver function signature looks like (parent, args, context, info).

  • parent: The result of the parent resolver.
  • args: Arguments passed to the field (e.g., id, input).
  • context: An object shared across all resolvers in a single request, often containing authenticated user info, database connections, and pub/sub instances.
  • info: Contains information about the execution state of the query (e.g., requested fields).

4.2. Example Resolver Pseudocode


// Example context object structure
const context = {
  db: { /* database client */ },
  pubsub: { /* GraphQL-subscriptions PubSub instance */ },
  currentUser: { id: 'user123', role: 'ADMIN' },
graphql_schema_designer.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);}});}