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

This document outlines a comprehensive architectural plan for a GraphQL schema, exemplified through a Project Management System. It details the schema definition, including types, queries, mutations, and subscriptions, along with conceptual resolver logic and client integration examples. Additionally, it provides a detailed study plan for individuals or teams looking to master GraphQL schema design.


GraphQL Schema Architecture Design: Project Management System

This section details the architectural design for a GraphQL API serving a Project Management System. This design focuses on clarity, extensibility, and best practices for defining a robust and intuitive API.

1. Introduction & Core Entities

The Project Management System will manage projects, tasks, users, and comments, facilitating collaboration and progress tracking.

Core Entities:

2. Schema Definition Language (SDL)

The following SDL defines the types, inputs, enums, queries, mutations, and subscriptions for our Project Management System.

2.1. Custom Scalars

text • 133 chars
*   **DateTime**: A custom scalar type to handle date and time values, typically represented as ISO 8601 strings.

#### 2.2. Enums

Sandboxed live preview

graphql

input CreateUserInput {

name: String!

email: String!

role: UserRole!

}

input UpdateUserInput {

name: String

email: String

role: UserRole

}

input CreateProjectInput {

name: String!

description: String

status: ProjectStatus

startDate: DateTime

endDate: DateTime

ownerId: ID! # ID of the user who owns the project

memberIds: [ID!] # Optional list of member IDs

tagIds: [ID!] # Optional list of tag IDs

}

input UpdateProjectInput {

name: String

description: String

status: ProjectStatus

startDate: DateTime

endDate: DateTime

ownerId: ID

addMemberIds: [ID!] # IDs of users to add as members

removeMemberIds: [

gemini Output

The following detailed GraphQL schema design provides a robust foundation for a Project Management System. It encompasses various types, queries, mutations, and subscriptions, along with conceptual resolver implementations and client integration examples. This design prioritizes clarity, scalability, and adherence to GraphQL best practices.


GraphQL Schema Designer: Project Management System

This document outlines a comprehensive GraphQL schema for a Project Management System. The system allows users to manage projects, tasks, and comments, with features for user roles, real-time updates, and structured data access.

1. Introduction

The goal of this deliverable is to provide a complete GraphQL schema definition (SDL) for a project management application. This schema will serve as the contract between the client and the server, defining all available data and operations. It includes:

  • Object Types: Representing the core entities (Users, Projects, Tasks, Comments).
  • Input Types: For structured data input to mutations.
  • Enum Types: For predefined sets of values (e.g., status, priority, roles).
  • Custom Scalars: For specialized data types (e.g., DateTime).
  • Queries: For fetching data.
  • Mutations: For modifying data.
  • Subscriptions: For real-time data updates.
  • Conceptual Resolvers: Explaining how data is fetched and manipulated.
  • Client Integration Examples: Demonstrating how clients interact with the API.

2. GraphQL Schema Definition Language (SDL)

Below is the complete GraphQL schema written in SDL, including all types, queries, mutations, and subscriptions.


# Custom Scalar for Date and Time
# Represents a date and time, typically in ISO 8601 format.
scalar DateTime

# Enums: Define a set of allowed values for a field.

# UserRole: Defines the different roles a user can have in the system.
enum UserRole {
  ADMIN       # Full administrative access
  MANAGER     # Can manage projects and tasks, assign users
  DEVELOPER   # Primarily works on tasks within projects
  VIEWER      # Read-only access to projects and tasks
}

# ProjectStatus: Defines the current state of a project.
enum ProjectStatus {
  NOT_STARTED # Project is planned but not yet active
  IN_PROGRESS # Project is actively being worked on
  ON_HOLD     # Project work is temporarily paused
  COMPLETED   # Project has been successfully finished
  CANCELLED   # Project has been terminated
}

# TaskStatus: Defines the current state of a task.
enum TaskStatus {
  OPEN        # Task is created and awaiting assignment/start
  IN_PROGRESS # Task is actively being worked on
  REVIEW      # Task is completed and awaiting review
  DONE        # Task has been completed and approved
  BLOCKED     # Task cannot proceed due to an impediment
}

# TaskPriority: Defines the urgency level of a task.
enum TaskPriority {
  LOW
  MEDIUM
  HIGH
  URGENT
}

# Object Types: Define the structure of data objects.

# User: Represents a user in the system.
type User {
  id: ID!
  username: String!
  email: String!
  firstName: String
  lastName: String
  role: UserRole!
  projects: [Project!]! # Projects where this user is a team member
  tasks: [Task!]!       # Tasks assigned to this user
  comments: [Comment!]! # Comments authored by this user
  createdAt: DateTime!
  updatedAt: DateTime!
}

# Project: Represents a project containing tasks.
type Project {
  id: ID!
  name: String!
  description: String
  status: ProjectStatus!
  startDate: DateTime
  endDate: DateTime
  owner: User! # The user responsible for the project
  teamMembers: [User!]! # Users assigned to this project
  tasks(
    status: TaskStatus # Filter tasks by status
    priority: TaskPriority # Filter tasks by priority
    assignedToId: ID # Filter tasks by assigned user
    limit: Int = 10 # Pagination: maximum number of tasks to return
    offset: Int = 0 # Pagination: number of tasks to skip
  ): [Task!]! # Tasks belonging to this project
  createdAt: DateTime!
  updatedAt: DateTime!
}

# Task: Represents an individual task within a project.
type Task {
  id: ID!
  title: String!
  description: String
  status: TaskStatus!
  priority: TaskPriority!
  dueDate: DateTime
  assignedTo: User # The user assigned to this task (can be null if unassigned)
  project: Project! # The project this task belongs to
  comments(
    limit: Int = 10 # Pagination: maximum number of comments to return
    offset: Int = 0 # Pagination: number of comments to skip
  ): [Comment!]! # Comments associated with this task
  createdAt: DateTime!
  updatedAt: DateTime!
}

# Comment: Represents a comment made on a task.
type Comment {
  id: ID!
  content: String!
  author: User! # The user who authored the comment
  task: Task! # The task the comment belongs to
  createdAt: DateTime!
  updatedAt: DateTime!
}

# Input Types: Used for passing structured arguments to mutations.

# CreateUserInput: Input for creating a new user.
input CreateUserInput {
  username: String!
  email: String!
  firstName: String
  lastName: String
  role: UserRole = DEVELOPER # Default role if not specified
}

# UpdateUserInput: Input for updating an existing user's details.
input UpdateUserInput {
  firstName: String
  lastName: String
  role: UserRole
}

# CreateProjectInput: Input for creating a new project.
input CreateProjectInput {
  name: String!
  description: String
  startDate: DateTime
  endDate: DateTime
  ownerId: ID! # ID of the user who will own this project
  teamMemberIds: [ID!] # Optional list of user IDs to add as team members
}

# UpdateProjectInput: Input for updating an existing project's details.
input UpdateProjectInput {
  name: String
  description: String
  status: ProjectStatus
  startDate: DateTime
  endDate: DateTime
  ownerId: ID # New owner ID
  teamMember
gemini Output

This document presents a comprehensive GraphQL Schema Design for a robust Project Management System. This design leverages GraphQL's powerful type system to create a flexible, efficient, and intuitive API for managing projects, tasks, users, and teams.


GraphQL Schema Design: Project Management System

1. Introduction to GraphQL

GraphQL is an open-source data query and manipulation language for APIs, and a runtime for fulfilling queries with existing data. It provides an efficient, powerful, and flexible approach to developing web APIs, allowing clients to request exactly the data they need, no more and no less. This reduces over-fetching and under-fetching, improving network efficiency and application performance.

Key Benefits of GraphQL:

  • Single Endpoint: All data is accessible via a single endpoint, simplifying client-side development.
  • Strongly Typed Schema: The schema defines all available data and operations, providing clarity and enabling powerful tooling (e.g., auto-completion, validation).
  • Client-Driven Data Fetching: Clients specify exactly what data they need, reducing unnecessary data transfer.
  • Real-time Capabilities: Subscriptions enable real-time updates for dynamic applications.

2. Schema Design Principles

The following principles guided the design of this GraphQL schema:

  • Clarity and Readability: The schema is designed to be self-documenting and easy to understand.
  • Granularity: Types are broken down into logical, reusable components.
  • Predictability: Operations (queries, mutations) are named consistently and behave as expected.
  • Extensibility: The schema can be easily extended with new types and fields without breaking existing clients.
  • Performance: Designed to allow efficient data fetching with minimal round trips.
  • Security: Input types are used for mutations to prevent mass assignment vulnerabilities, and authentication/authorization considerations are implicit in resolver design.

3. Data Model Overview

Our Project Management System revolves around the following core entities and their relationships:

  • User: Represents an individual user of the system.
  • Team: A collection of users, often associated with specific projects or departments.
  • Project: A high-level container for tasks, managed by specific teams or users.
  • Task: An individual unit of work within a project, assigned to a user, with a status and due date.
  • Comment: Textual feedback or discussion associated with a specific task.

Relationships:

  • A User can be a member of multiple Teams.
  • A Team can have multiple Users.
  • A Project belongs to a Team (or can be standalone, associated with an owner User).
  • A Project has multiple Tasks.
  • A Task belongs to a Project.
  • A Task is assignedTo one User.
  • A Task can have multiple Comments.
  • A Comment is authored by one User and belongs to one Task.

4. GraphQL Schema Definition Language (SDL)

This section details the GraphQL schema using the Schema Definition Language (SDL).

4.1. Scalar Types

Beyond the built-in String, Int, Float, Boolean, and ID, we define custom scalars for common patterns.


scalar DateTime
# Represents a date and time in ISO 8601 format (e.g., "2023-10-27T10:00:00Z")

scalar JSON
# Represents a generic JSON object

4.2. Enum Types

Enums define a set of allowed values for a field.


enum TaskStatus {
  TODO
  IN_PROGRESS
  DONE
  BLOCKED
}

enum Priority {
  LOW
  MEDIUM
  HIGH
  CRITICAL
}

4.3. Object Types

Object types represent the core data entities in our system.


type User {
  id: ID!
  username: String!
  email: String!
  firstName: String
  lastName: String
  teams: [Team!]! # Users can be part of multiple teams
  assignedTasks: [Task!]! # Tasks assigned to this user
  createdAt: DateTime!
  updatedAt: DateTime!
}

type Team {
  id: ID!
  name: String!
  description: String
  members: [User!]! # Users belonging to this team
  projects: [Project!]! # Projects managed by this team
  createdAt: DateTime!
  updatedAt: DateTime!
}

type Project {
  id: ID!
  name: String!
  description: String
  status: ProjectStatus! # Example enum for project status if needed
  owner: User! # The user who owns/created the project
  team: Team # The team responsible for the project (optional)
  tasks: [Task!]! # Tasks within this project
  startDate: DateTime
  endDate: DateTime
  createdAt: DateTime!
  updatedAt: DateTime!
}

enum ProjectStatus {
  ACTIVE
  ON_HOLD
  COMPLETED
  ARCHIVED
}

type Task {
  id: ID!
  title: String!
  description: String
  status: TaskStatus!
  priority: Priority!
  project: Project! # The project this task belongs to
  assignee: User # The user assigned to this task (nullable)
  dueDate: DateTime
  comments: [Comment!]! # Comments on this task
  createdAt: DateTime!
  updatedAt: DateTime!
}

type Comment {
  id: ID!
  content: String!
  author: User! # The user who wrote the comment
  task: Task! # The task this comment belongs to
  createdAt: DateTime!
  updatedAt: DateTime!
}

4.4. Input Types

Input types are used for arguments in mutations, providing structured input for creating or updating entities.


input CreateUserInput {
  username: String!
  email: String!
  firstName: String
  lastName: String
}

input UpdateUserInput {
  firstName: String
  lastName: String
  email: String
}

input CreateTeamInput {
  name: String!
  description: String
  memberIds: [ID!] # Optional: IDs of initial members
}

input UpdateTeamInput {
  name: String
  description: String
}

input CreateProjectInput {
  name: String!
  description: String
  ownerId: ID! # ID of the user who owns the project
  teamId: ID # Optional: ID of the team responsible
  startDate: DateTime
  endDate: DateTime
}

input UpdateProjectInput {
  name: String
  description: String
  status: ProjectStatus
  ownerId: ID
  teamId: ID
  startDate: DateTime
  endDate: DateTime
}

input CreateTaskInput {
  projectId: ID!
  title: String!
  description: String
  status: TaskStatus = TODO # Default value
  priority: Priority = MEDIUM # Default value
  assigneeId: ID
  dueDate: DateTime
}

input UpdateTaskInput {
  title: String
  description: String
  status: TaskStatus
  priority: Priority
  assigneeId: ID
  dueDate: DateTime
}

input CreateCommentInput {
  taskId: ID!
  authorId: ID!
  content: String!
}

4.5. Query Type

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


type Query {
  # User Queries
  user(id: ID!): User
  users(limit: Int = 10, offset: Int = 0): [User!]!

  # Team Queries
  team(id: ID!): Team
  teams(limit: Int = 10, offset: Int = 0): [Team!]!

  # Project Queries
  project(id: ID!): Project
  projects(
    teamId: ID
    ownerId: ID
    status: ProjectStatus
    limit: Int = 10
    offset: Int = 0
  ): [Project!]!

  # Task Queries
  task(id: ID!): Task
  tasks(
    projectId: ID!
    status: TaskStatus
    assigneeId: ID
    priority: Priority
    limit: Int = 10
    offset: Int = 0
  ): [Task!]!

  # Comment Queries
  comment(id: ID!): Comment
  comments(
    taskId: ID!
    authorId: ID
    limit: Int = 10
    offset: Int = 0
  ): [Comment!]!
}

4.6. Mutation Type

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


type Mutation {
  # User Mutations
  createUser(input: CreateUserInput!): User!
  updateUser(id: ID!, input: UpdateUserInput!): User
  deleteUser(id: ID!): Boolean!

  # Team Mutations
  createTeam(input: CreateTeamInput!): Team!
  updateTeam(id: ID!, input: UpdateTeamInput!): Team
  addUsersToTeam(teamId: ID!, userIds: [ID!]!): Team
  removeUsersFromTeam(teamId: ID!, userIds: [ID!]!): Team
  deleteTeam(id: ID!): Boolean!

  # Project Mutations
  createProject(input: CreateProjectInput!): Project!
  updateProject(id: ID!, input: UpdateProjectInput!): Project
  deleteProject(id: ID!): Boolean!

  # Task Mutations
  createTask(input: CreateTaskInput!): Task!
  updateTask(id: ID!, input: UpdateTaskInput!): Task
  assignTask(taskId: ID!, assigneeId: ID): Task # Assign or unassign (if assigneeId is null)
  deleteTask(id: ID!): Boolean!

  # Comment Mutations
  createComment(input: CreateCommentInput!): Comment!
  deleteComment(id: ID!): Boolean!
}

4.7. Subscription Type

The Subscription type defines real-time event streams, enabling clients to receive updates when data changes.


type Subscription {
  # Task Subscriptions
  taskUpdated(projectId: ID!): Task! # Triggered when a task in a specific project is updated
  newTask(projectId: ID!): Task! # Triggered when a new task is created in a specific project
  taskDeleted(projectId: ID!): ID! # Triggered when a task is deleted (returns ID of deleted task)

  # Comment Subscriptions
  newComment(taskId: ID!): Comment! # Triggered when a new comment is added to a specific task
}

5. Resolver Architecture

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

5.1. Resolver Map Structure

A typical resolver map in a GraphQL server (e.g., Apollo Server, GraphQL.js) looks like this:


const resolvers = {
  // Custom Scalar Resolvers
  DateTime: new GraphQLScalarType({ /* ... */ }),
  JSON: new GraphQLScalarType({ /* ... */ }),

  // Query Resolvers
  Query: {
    user: (parent, { id }, context, info) => /* Logic to fetch a single user by ID */,
    users: (parent, { limit, offset }, context, info) => /* Logic to fetch a list of users */,
    project: (parent, { id }, context, info) => /* Logic to fetch a single project by ID */,
    projects: (parent, args, context, info) => /* Logic to fetch a list of projects with filters */,
    // ... other query resolvers
  },

  // Mutation Resolvers
  Mutation: {
    createUser: (parent, { input }, context, info) => /* Logic to create a new user */,
    updateUser: (parent, { id, input }, context, info) => /* Logic to update an existing user */,
    createTask: (parent, { input }, context, info) => /* Logic to create a new task */,
    // ... other mutation resolvers
  },

  // Subscription Resolvers
  Subscription: {
    taskUpdated: {
      subscribe: (parent, { projectId }, context, info) => /* Logic to set up event listener for task updates */,
      resolve: (payload) => /* Logic to format the updated task from the event payload */
    },
    newComment: {
      subscribe: (parent, { taskId }, context, info) => /* Logic to set up event listener for new comments */,
      resolve: (payload) => /* Logic to format the new comment from the event payload */
    }
  },

  // Type Resolvers (for nested fields)
  User: {
    teams: (parent, args, context, info) => /* Logic to fetch teams for a given user (parent) */,
    assignedTasks: (parent, args, context, info) => /* Logic to fetch tasks assigned to a given user */
  },
  Project: {
    owner: (parent, args, context, info) => /* Logic to fetch the owner user for a given project */,
    team: (parent, args, context, info) => /* Logic to fetch the team for a given project */,
    tasks: (parent, args, context, info) => /* Logic to fetch tasks for a given project */
  },
  Task: {
    project: (parent, args, context, info) => /* Logic to fetch the project for a given task */,
    assignee: (parent, args, context, info) => /* Logic to fetch the assignee user for a given task */,
    comments: (parent, args, context, info) => /* Logic to fetch comments for a given task */
  },
  Comment: {
    author: (parent, args, context, info) => /* Logic to fetch the author user for a given comment */,
    task: (parent, args, context, info) => /* Logic to fetch the task for a given comment */
  },
  // ... other type resolvers
};

5.2. Context Object

The context object is crucial for resolvers. It's an object shared across all resolvers in a single GraphQL operation. It typically contains:

  • Authentication/Authorization: Current user information, roles, permissions.
  • Data Sources: Database connections, API clients, ORM instances.
  • PubSub: For subscriptions.

6. Example Data Source Integration (Conceptual)

Let's illustrate how a resolver might interact with a hypothetical data layer, assuming a dataSources object in the context.


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);}});}