mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-04-25 14:25:02 +00:00
Compare commits
14 Commits
claude/fix
...
copilot/fi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c5b6e7c912 | ||
|
|
38e129c50e | ||
|
|
1f5cfe9e77 | ||
|
|
78b8bec29e | ||
|
|
d726f8bb9a | ||
|
|
0943ab50c1 | ||
|
|
99bb647503 | ||
|
|
09310703d2 | ||
|
|
549d0e6298 | ||
|
|
3337584607 | ||
|
|
99a3d500b3 | ||
|
|
574f0a0044 | ||
|
|
6fcba8a44f | ||
|
|
2a7a81412d |
@@ -1,9 +1,46 @@
|
||||
{
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"Bash(echo No metabuilder images found:*)",
|
||||
"Bash(docker compose:*)",
|
||||
"Bash(git pull:*)"
|
||||
"Bash(git mv:*)",
|
||||
"Bash(ls:*)",
|
||||
"Bash(find:*)",
|
||||
"Bash(npm run test:unit:*)",
|
||||
"Bash(npm install:*)",
|
||||
"Bash(xargs:*)",
|
||||
"Bash(npm run db:generate:*)",
|
||||
"Bash(npx prisma generate:*)",
|
||||
"Bash(DATABASE_URL=\"file:./dev.db\" npx prisma generate:*)",
|
||||
"Bash(git rm:*)",
|
||||
"Bash(git log:*)",
|
||||
"Bash(cat:*)",
|
||||
"Bash(xargs git rm:*)",
|
||||
"Bash(bun add:*)",
|
||||
"Bash(bun install:*)",
|
||||
"Bash(test -f:*)",
|
||||
"Bash(bun run typecheck:*)",
|
||||
"Bash(bun run test:unit:*)",
|
||||
"Bash(echo:*)",
|
||||
"Bash(npx prisma validate:*)",
|
||||
"Bash(npm run typecheck:*)",
|
||||
"Bash(npm run lint)",
|
||||
"Bash(npm audit:*)",
|
||||
"Bash(bun run lint)",
|
||||
"Bash(git checkout:*)",
|
||||
"Bash(bun audit:*)",
|
||||
"Bash(git restore:*)",
|
||||
"Bash(bunx playwright:*)",
|
||||
"Bash(timeout 30 bun run build:*)",
|
||||
"Bash(bun run lint:fix:*)",
|
||||
"Bash(bun run format:*)",
|
||||
"Bash(while read file)",
|
||||
"Bash(do eslint:*)",
|
||||
"Bash(done)",
|
||||
"Bash(eslint:*)",
|
||||
"Bash(bunx eslint:*)",
|
||||
"Bash(bun test:*)",
|
||||
"Bash(136*100/234)",
|
||||
"Bash(\")",
|
||||
"Bash(python3:*)"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,46 +0,0 @@
|
||||
---
|
||||
sourceLocationPrefix: /Users/rmac/Documents/metabuilder
|
||||
baselineLinesOfCode: 300769
|
||||
unicodeNewlines: true
|
||||
columnKind: utf16
|
||||
primaryLanguage: javascript
|
||||
inProgress:
|
||||
primaryLanguage: javascript
|
||||
installedExtractors:
|
||||
go:
|
||||
- /opt/homebrew/Caskroom/codeql/2.23.9/codeql/go
|
||||
python:
|
||||
- /opt/homebrew/Caskroom/codeql/2.23.9/codeql/python
|
||||
rust:
|
||||
- /opt/homebrew/Caskroom/codeql/2.23.9/codeql/rust
|
||||
java:
|
||||
- /opt/homebrew/Caskroom/codeql/2.23.9/codeql/java
|
||||
html:
|
||||
- /opt/homebrew/Caskroom/codeql/2.23.9/codeql/html
|
||||
xml:
|
||||
- /opt/homebrew/Caskroom/codeql/2.23.9/codeql/xml
|
||||
properties:
|
||||
- /opt/homebrew/Caskroom/codeql/2.23.9/codeql/properties
|
||||
cpp:
|
||||
- /opt/homebrew/Caskroom/codeql/2.23.9/codeql/cpp
|
||||
swift:
|
||||
- /opt/homebrew/Caskroom/codeql/2.23.9/codeql/swift
|
||||
csv:
|
||||
- /opt/homebrew/Caskroom/codeql/2.23.9/codeql/csv
|
||||
actions:
|
||||
- /opt/homebrew/Caskroom/codeql/2.23.9/codeql/actions
|
||||
yaml:
|
||||
- /opt/homebrew/Caskroom/codeql/2.23.9/codeql/yaml
|
||||
csharp:
|
||||
- /opt/homebrew/Caskroom/codeql/2.23.9/codeql/csharp
|
||||
javascript:
|
||||
- /opt/homebrew/Caskroom/codeql/2.23.9/codeql/javascript
|
||||
ruby:
|
||||
- /opt/homebrew/Caskroom/codeql/2.23.9/codeql/ruby
|
||||
creationMetadata:
|
||||
sha: 110d37c3bce07cb068c510bbed2c42d1ccba1b42
|
||||
cliVersion: 2.23.9
|
||||
creationTime: 2026-02-01T20:15:08.121510Z
|
||||
finalised: false
|
||||
overlayBaseDatabase: false
|
||||
overlayDatabase: false
|
||||
@@ -1 +0,0 @@
|
||||
{"timestamp":"2026-02-01T20:15:07.994462Z","source":{"id":"cli/platform","name":"Platform"},"markdownMessage":"On the Mac OS X (aarch64; 26.2) platform.","visibility":{"cliSummaryTable":false,"statusPage":false,"telemetry":true},"attributes":{"arch":"aarch64","version":"26.2","name":"Mac OS X"}}
|
||||
@@ -1 +0,0 @@
|
||||
{"timestamp":"2026-02-01T20:15:08.117178Z","source":{"id":"cli/sip-enablement","name":"macOS SIP enablement status"},"severity":"note","visibility":{"cliSummaryTable":false,"statusPage":false,"telemetry":true},"attributes":{"isEnabled":true}}
|
||||
132
.dockerignore
132
.dockerignore
@@ -1,132 +0,0 @@
|
||||
# Dependencies (installed fresh via npm ci in multi-stage builds)
|
||||
node_modules
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
|
||||
# Build output (built fresh inside Docker)
|
||||
**/.next
|
||||
**/out
|
||||
**/storybook-static
|
||||
**/dist
|
||||
|
||||
# Testing
|
||||
coverage
|
||||
.nyc_output
|
||||
*.test.ts
|
||||
*.test.tsx
|
||||
*.spec.ts
|
||||
*.spec.tsx
|
||||
__tests__
|
||||
__mocks__
|
||||
.vitest
|
||||
|
||||
# Misc
|
||||
.DS_Store
|
||||
*.pem
|
||||
|
||||
# Local env files
|
||||
.env
|
||||
.env*.local
|
||||
.env.development
|
||||
.env.test
|
||||
.env.production
|
||||
|
||||
# Vercel
|
||||
.vercel
|
||||
|
||||
# TypeScript build info
|
||||
*.tsbuildinfo
|
||||
next-env.d.ts
|
||||
|
||||
# IDE
|
||||
.vscode
|
||||
.idea
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
|
||||
# Git
|
||||
.git
|
||||
.gitignore
|
||||
.gitattributes
|
||||
|
||||
# Documentation
|
||||
docs
|
||||
README*
|
||||
CHANGELOG*
|
||||
LICENSE
|
||||
|
||||
# CI/CD
|
||||
.github
|
||||
.gitlab-ci.yml
|
||||
azure-pipelines.yml
|
||||
|
||||
# Docker (Dockerfiles are referenced by path, not COPYed)
|
||||
docker-compose*
|
||||
.dockerignore
|
||||
|
||||
# Development config
|
||||
.editorconfig
|
||||
.prettierrc*
|
||||
.eslintrc*
|
||||
.eslintignore
|
||||
|
||||
# E2E / test infrastructure
|
||||
e2e
|
||||
playwright-report
|
||||
test-results
|
||||
|
||||
# Temporary files
|
||||
tmp
|
||||
temp
|
||||
.tmp
|
||||
.cache
|
||||
|
||||
# Large directories not needed by Node.js Docker builds
|
||||
gameengine
|
||||
dbal
|
||||
services
|
||||
old
|
||||
txt
|
||||
deployment
|
||||
prisma
|
||||
mojo
|
||||
spec
|
||||
scripts
|
||||
.claude
|
||||
dist
|
||||
|
||||
# Allow specific dbal paths through for app builds
|
||||
!dbal/shared/ui
|
||||
!dbal/shared/api/schema/entities
|
||||
!dbal/shared/seeds/database
|
||||
|
||||
# Allow conanfiles through for base image builds (negation overrides above exclusions)
|
||||
!dbal/production/build-config/conanfile.py
|
||||
!gameengine/conanfile.py
|
||||
!services/media_daemon/build-config/conanfile.txt
|
||||
!frontends/qt6/conanfile.txt
|
||||
!frontends/cli/conanfile.txt
|
||||
|
||||
# Allow requirements.txt for base-pip-deps image
|
||||
!dbal/production/tests/integration/requirements.txt
|
||||
!services/email_service/requirements.txt
|
||||
!services/smtprelay/requirements.txt
|
||||
|
||||
# Allow deployment config files for baked-in Docker images
|
||||
!deployment/portal
|
||||
!deployment/config/nginx/production.conf
|
||||
!deployment/config/prometheus/prometheus.yml
|
||||
!deployment/config/prometheus/alerts.yml
|
||||
!deployment/config/grafana/provisioning
|
||||
!deployment/config/loki/loki-config.yml
|
||||
!deployment/config/promtail/promtail-config.yml
|
||||
!deployment/config/alertmanager/alertmanager.yml
|
||||
|
||||
# Allow DBAL templates for dbal-init volume seeder
|
||||
!dbal/templates/sql
|
||||
|
||||
# Allow media daemon config for nginx-stream image
|
||||
!services/media_daemon/config/nginx-stream.conf
|
||||
260
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
260
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -1,130 +1,130 @@
|
||||
name: 🐛 Bug Report
|
||||
description: Report a bug or unexpected behavior
|
||||
title: "[Bug]: "
|
||||
labels: ["bug", "triage"]
|
||||
assignees: []
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to report this bug! Please fill out the form below to help us understand and fix the issue.
|
||||
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Bug Description
|
||||
description: A clear and concise description of what the bug is.
|
||||
placeholder: Tell us what went wrong...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: reproduction
|
||||
attributes:
|
||||
label: Steps to Reproduce
|
||||
description: Steps to reproduce the behavior
|
||||
placeholder: |
|
||||
1. Go to '...'
|
||||
2. Click on '...'
|
||||
3. Scroll down to '...'
|
||||
4. See error
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: expected
|
||||
attributes:
|
||||
label: Expected Behavior
|
||||
description: What did you expect to happen?
|
||||
placeholder: I expected...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: actual
|
||||
attributes:
|
||||
label: Actual Behavior
|
||||
description: What actually happened?
|
||||
placeholder: Instead, I observed...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: component
|
||||
attributes:
|
||||
label: Component/Area
|
||||
description: Which part of MetaBuilder is affected?
|
||||
options:
|
||||
- Frontend (Next.js UI)
|
||||
- Backend (API/Auth)
|
||||
- Database (Prisma/Schema)
|
||||
- DBAL (TypeScript/C++)
|
||||
- Package System
|
||||
- Lua Scripting
|
||||
- Multi-Tenant System
|
||||
- Permission System
|
||||
- Workflows
|
||||
- Documentation
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: severity
|
||||
attributes:
|
||||
label: Severity
|
||||
description: How severe is this bug?
|
||||
options:
|
||||
- Critical (System crash, data loss)
|
||||
- High (Major feature broken)
|
||||
- Medium (Feature partially broken)
|
||||
- Low (Minor issue, workaround exists)
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: environment
|
||||
attributes:
|
||||
label: Environment
|
||||
description: Please provide your environment details
|
||||
value: |
|
||||
- OS: [e.g., Ubuntu 22.04, macOS 13.0, Windows 11]
|
||||
- Node Version: [e.g., 18.17.0]
|
||||
- Browser: [e.g., Chrome 120, Firefox 121]
|
||||
- Database: [e.g., SQLite, PostgreSQL 15]
|
||||
render: markdown
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Relevant Logs/Screenshots
|
||||
description: Add any error logs, screenshots, or console output
|
||||
placeholder: |
|
||||
Paste logs here or drag and drop screenshots.
|
||||
render: shell
|
||||
|
||||
- type: textarea
|
||||
id: additional
|
||||
attributes:
|
||||
label: Additional Context
|
||||
description: Add any other context about the problem
|
||||
placeholder: |
|
||||
- Does this happen consistently or intermittently?
|
||||
- Have you tried any workarounds?
|
||||
- Did this work in a previous version?
|
||||
|
||||
- type: checkboxes
|
||||
id: checklist
|
||||
attributes:
|
||||
label: Pre-submission Checklist
|
||||
description: Please verify the following before submitting
|
||||
options:
|
||||
- label: I have searched existing issues to ensure this is not a duplicate
|
||||
required: true
|
||||
- label: I have provided all required information above
|
||||
required: true
|
||||
- label: I have checked the documentation for relevant information
|
||||
required: false
|
||||
name: 🐛 Bug Report
|
||||
description: Report a bug or unexpected behavior
|
||||
title: "[Bug]: "
|
||||
labels: ["bug", "triage"]
|
||||
assignees: []
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to report this bug! Please fill out the form below to help us understand and fix the issue.
|
||||
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Bug Description
|
||||
description: A clear and concise description of what the bug is.
|
||||
placeholder: Tell us what went wrong...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: reproduction
|
||||
attributes:
|
||||
label: Steps to Reproduce
|
||||
description: Steps to reproduce the behavior
|
||||
placeholder: |
|
||||
1. Go to '...'
|
||||
2. Click on '...'
|
||||
3. Scroll down to '...'
|
||||
4. See error
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: expected
|
||||
attributes:
|
||||
label: Expected Behavior
|
||||
description: What did you expect to happen?
|
||||
placeholder: I expected...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: actual
|
||||
attributes:
|
||||
label: Actual Behavior
|
||||
description: What actually happened?
|
||||
placeholder: Instead, I observed...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: component
|
||||
attributes:
|
||||
label: Component/Area
|
||||
description: Which part of MetaBuilder is affected?
|
||||
options:
|
||||
- Frontend (Next.js UI)
|
||||
- Backend (API/Auth)
|
||||
- Database (Prisma/Schema)
|
||||
- DBAL (TypeScript/C++)
|
||||
- Package System
|
||||
- Lua Scripting
|
||||
- Multi-Tenant System
|
||||
- Permission System
|
||||
- Workflows
|
||||
- Documentation
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: severity
|
||||
attributes:
|
||||
label: Severity
|
||||
description: How severe is this bug?
|
||||
options:
|
||||
- Critical (System crash, data loss)
|
||||
- High (Major feature broken)
|
||||
- Medium (Feature partially broken)
|
||||
- Low (Minor issue, workaround exists)
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: environment
|
||||
attributes:
|
||||
label: Environment
|
||||
description: Please provide your environment details
|
||||
value: |
|
||||
- OS: [e.g., Ubuntu 22.04, macOS 13.0, Windows 11]
|
||||
- Node Version: [e.g., 18.17.0]
|
||||
- Browser: [e.g., Chrome 120, Firefox 121]
|
||||
- Database: [e.g., SQLite, PostgreSQL 15]
|
||||
render: markdown
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Relevant Logs/Screenshots
|
||||
description: Add any error logs, screenshots, or console output
|
||||
placeholder: |
|
||||
Paste logs here or drag and drop screenshots.
|
||||
render: shell
|
||||
|
||||
- type: textarea
|
||||
id: additional
|
||||
attributes:
|
||||
label: Additional Context
|
||||
description: Add any other context about the problem
|
||||
placeholder: |
|
||||
- Does this happen consistently or intermittently?
|
||||
- Have you tried any workarounds?
|
||||
- Did this work in a previous version?
|
||||
|
||||
- type: checkboxes
|
||||
id: checklist
|
||||
attributes:
|
||||
label: Pre-submission Checklist
|
||||
description: Please verify the following before submitting
|
||||
options:
|
||||
- label: I have searched existing issues to ensure this is not a duplicate
|
||||
required: true
|
||||
- label: I have provided all required information above
|
||||
required: true
|
||||
- label: I have checked the documentation for relevant information
|
||||
required: false
|
||||
|
||||
22
.github/ISSUE_TEMPLATE/config.yml
vendored
22
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,11 +1,11 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: 📚 Documentation
|
||||
url: https://github.com/johndoe6345789/metabuilder/tree/main/docs
|
||||
about: Check our comprehensive documentation for guides and architecture details
|
||||
- name: 💬 Discussions
|
||||
url: https://github.com/johndoe6345789/metabuilder/discussions
|
||||
about: Ask questions and discuss ideas with the community
|
||||
- name: 🔒 Security Issues
|
||||
url: https://github.com/johndoe6345789/metabuilder/security/advisories/new
|
||||
about: Report security vulnerabilities privately
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: 📚 Documentation
|
||||
url: https://github.com/johndoe6345789/metabuilder/tree/main/docs
|
||||
about: Check our comprehensive documentation for guides and architecture details
|
||||
- name: 💬 Discussions
|
||||
url: https://github.com/johndoe6345789/metabuilder/discussions
|
||||
about: Ask questions and discuss ideas with the community
|
||||
- name: 🔒 Security Issues
|
||||
url: https://github.com/johndoe6345789/metabuilder/security/advisories/new
|
||||
about: Report security vulnerabilities privately
|
||||
|
||||
316
.github/ISSUE_TEMPLATE/dbal_issue.yml
vendored
316
.github/ISSUE_TEMPLATE/dbal_issue.yml
vendored
@@ -1,158 +1,158 @@
|
||||
name: 🔧 DBAL Issue
|
||||
description: Report an issue with the Database Abstraction Layer (TypeScript or C++)
|
||||
title: "[DBAL]: "
|
||||
labels: ["dbal", "bug", "triage"]
|
||||
assignees: []
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
DBAL is MetaBuilder's critical database abstraction layer with TypeScript (dev) and C++ (production) implementations.
|
||||
|
||||
- type: dropdown
|
||||
id: implementation
|
||||
attributes:
|
||||
label: DBAL Implementation
|
||||
description: Which DBAL implementation is affected?
|
||||
options:
|
||||
- TypeScript SDK (dbal/development/)
|
||||
- C++ Daemon (dbal/production/)
|
||||
- Both implementations
|
||||
- YAML Contracts (api/schema/)
|
||||
- Conformance Tests
|
||||
- Unknown
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: issue
|
||||
attributes:
|
||||
label: Issue Description
|
||||
description: Describe the DBAL issue you're experiencing
|
||||
placeholder: The DBAL operation fails when...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: operation
|
||||
attributes:
|
||||
label: Operation Type
|
||||
description: What type of operation is failing?
|
||||
options:
|
||||
- Entity Operations (CRUD)
|
||||
- Query Operations
|
||||
- Transaction Operations
|
||||
- Blob Storage
|
||||
- Key-Value Store
|
||||
- Tenant Management
|
||||
- Access Control
|
||||
- Connection Management
|
||||
- Type Generation
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: reproduction
|
||||
attributes:
|
||||
label: Reproduction Code
|
||||
description: Provide code to reproduce the issue
|
||||
placeholder: |
|
||||
```typescript
|
||||
// Your code here
|
||||
const result = await dbalQuery({...})
|
||||
```
|
||||
render: typescript
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: expected
|
||||
attributes:
|
||||
label: Expected Behavior
|
||||
description: What should happen?
|
||||
placeholder: The operation should...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: actual
|
||||
attributes:
|
||||
label: Actual Behavior
|
||||
description: What actually happens?
|
||||
placeholder: Instead, I see...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: error
|
||||
attributes:
|
||||
label: Error Messages/Logs
|
||||
description: Include any error messages, stack traces, or logs
|
||||
render: shell
|
||||
|
||||
- type: dropdown
|
||||
id: severity
|
||||
attributes:
|
||||
label: Severity
|
||||
options:
|
||||
- Critical (Data corruption/loss)
|
||||
- High (Operation completely fails)
|
||||
- Medium (Operation partially works)
|
||||
- Low (Minor inconsistency)
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: environment
|
||||
attributes:
|
||||
label: Environment Details
|
||||
value: |
|
||||
- DBAL Version: [e.g., commit hash or version]
|
||||
- Node/C++ Version: [e.g., Node 18.17, gcc 11.3]
|
||||
- Database: [e.g., SQLite, PostgreSQL 15]
|
||||
- OS: [e.g., Ubuntu 22.04]
|
||||
render: markdown
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: parity
|
||||
attributes:
|
||||
label: Implementation Parity
|
||||
description: If both implementations exist, do they behave the same?
|
||||
options:
|
||||
- Both implementations fail
|
||||
- Only TypeScript fails
|
||||
- Only C++ fails
|
||||
- Different behavior between implementations
|
||||
- Haven't tested both
|
||||
- N/A (only one implementation exists)
|
||||
|
||||
- type: textarea
|
||||
id: conformance
|
||||
attributes:
|
||||
label: Conformance Test Status
|
||||
description: Do conformance tests pass for this operation?
|
||||
placeholder: |
|
||||
- Ran: python tools/conformance/run_all.py
|
||||
- Result: [Pass/Fail details]
|
||||
|
||||
- type: textarea
|
||||
id: additional
|
||||
attributes:
|
||||
label: Additional Context
|
||||
description: YAML contract issues? Schema problems? Performance concerns?
|
||||
|
||||
- type: checkboxes
|
||||
id: checklist
|
||||
attributes:
|
||||
label: Pre-submission Checklist
|
||||
options:
|
||||
- label: I have checked the YAML schema definitions in api/schema/
|
||||
required: true
|
||||
- label: I have verified this isn't a tenant isolation issue
|
||||
required: true
|
||||
- label: I have checked conformance test results if applicable
|
||||
required: false
|
||||
name: 🔧 DBAL Issue
|
||||
description: Report an issue with the Database Abstraction Layer (TypeScript or C++)
|
||||
title: "[DBAL]: "
|
||||
labels: ["dbal", "bug", "triage"]
|
||||
assignees: []
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
DBAL is MetaBuilder's critical database abstraction layer with TypeScript (dev) and C++ (production) implementations.
|
||||
|
||||
- type: dropdown
|
||||
id: implementation
|
||||
attributes:
|
||||
label: DBAL Implementation
|
||||
description: Which DBAL implementation is affected?
|
||||
options:
|
||||
- TypeScript SDK (dbal/development/)
|
||||
- C++ Daemon (dbal/production/)
|
||||
- Both implementations
|
||||
- YAML Contracts (api/schema/)
|
||||
- Conformance Tests
|
||||
- Unknown
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: issue
|
||||
attributes:
|
||||
label: Issue Description
|
||||
description: Describe the DBAL issue you're experiencing
|
||||
placeholder: The DBAL operation fails when...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: operation
|
||||
attributes:
|
||||
label: Operation Type
|
||||
description: What type of operation is failing?
|
||||
options:
|
||||
- Entity Operations (CRUD)
|
||||
- Query Operations
|
||||
- Transaction Operations
|
||||
- Blob Storage
|
||||
- Key-Value Store
|
||||
- Tenant Management
|
||||
- Access Control
|
||||
- Connection Management
|
||||
- Type Generation
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: reproduction
|
||||
attributes:
|
||||
label: Reproduction Code
|
||||
description: Provide code to reproduce the issue
|
||||
placeholder: |
|
||||
```typescript
|
||||
// Your code here
|
||||
const result = await dbalQuery({...})
|
||||
```
|
||||
render: typescript
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: expected
|
||||
attributes:
|
||||
label: Expected Behavior
|
||||
description: What should happen?
|
||||
placeholder: The operation should...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: actual
|
||||
attributes:
|
||||
label: Actual Behavior
|
||||
description: What actually happens?
|
||||
placeholder: Instead, I see...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: error
|
||||
attributes:
|
||||
label: Error Messages/Logs
|
||||
description: Include any error messages, stack traces, or logs
|
||||
render: shell
|
||||
|
||||
- type: dropdown
|
||||
id: severity
|
||||
attributes:
|
||||
label: Severity
|
||||
options:
|
||||
- Critical (Data corruption/loss)
|
||||
- High (Operation completely fails)
|
||||
- Medium (Operation partially works)
|
||||
- Low (Minor inconsistency)
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: environment
|
||||
attributes:
|
||||
label: Environment Details
|
||||
value: |
|
||||
- DBAL Version: [e.g., commit hash or version]
|
||||
- Node/C++ Version: [e.g., Node 18.17, gcc 11.3]
|
||||
- Database: [e.g., SQLite, PostgreSQL 15]
|
||||
- OS: [e.g., Ubuntu 22.04]
|
||||
render: markdown
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: parity
|
||||
attributes:
|
||||
label: Implementation Parity
|
||||
description: If both implementations exist, do they behave the same?
|
||||
options:
|
||||
- Both implementations fail
|
||||
- Only TypeScript fails
|
||||
- Only C++ fails
|
||||
- Different behavior between implementations
|
||||
- Haven't tested both
|
||||
- N/A (only one implementation exists)
|
||||
|
||||
- type: textarea
|
||||
id: conformance
|
||||
attributes:
|
||||
label: Conformance Test Status
|
||||
description: Do conformance tests pass for this operation?
|
||||
placeholder: |
|
||||
- Ran: python tools/conformance/run_all.py
|
||||
- Result: [Pass/Fail details]
|
||||
|
||||
- type: textarea
|
||||
id: additional
|
||||
attributes:
|
||||
label: Additional Context
|
||||
description: YAML contract issues? Schema problems? Performance concerns?
|
||||
|
||||
- type: checkboxes
|
||||
id: checklist
|
||||
attributes:
|
||||
label: Pre-submission Checklist
|
||||
options:
|
||||
- label: I have checked the YAML schema definitions in api/schema/
|
||||
required: true
|
||||
- label: I have verified this isn't a tenant isolation issue
|
||||
required: true
|
||||
- label: I have checked conformance test results if applicable
|
||||
required: false
|
||||
|
||||
230
.github/ISSUE_TEMPLATE/documentation.yml
vendored
230
.github/ISSUE_TEMPLATE/documentation.yml
vendored
@@ -1,115 +1,115 @@
|
||||
name: 📚 Documentation
|
||||
description: Report an issue with documentation or request documentation improvements
|
||||
title: "[Docs]: "
|
||||
labels: ["documentation", "triage"]
|
||||
assignees: []
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for helping improve MetaBuilder's documentation! Clear docs help everyone.
|
||||
|
||||
- type: dropdown
|
||||
id: doc-type
|
||||
attributes:
|
||||
label: Documentation Type
|
||||
description: What kind of documentation issue is this?
|
||||
options:
|
||||
- Missing documentation
|
||||
- Incorrect/outdated information
|
||||
- Unclear explanation
|
||||
- Broken links
|
||||
- Typo/grammar
|
||||
- Code example not working
|
||||
- Missing code example
|
||||
- Architecture documentation
|
||||
- API documentation
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: location
|
||||
attributes:
|
||||
label: Documentation Location
|
||||
description: Where is the documentation issue? (provide file path, URL, or section name)
|
||||
placeholder: |
|
||||
File: docs/architecture/packages.md
|
||||
Or URL: https://github.com/johndoe6345789/metabuilder/tree/main/docs
|
||||
Or Section: "Getting Started > Database Setup"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: issue
|
||||
attributes:
|
||||
label: Issue Description
|
||||
description: What's wrong with the current documentation?
|
||||
placeholder: The current documentation states... but it should...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: suggestion
|
||||
attributes:
|
||||
label: Suggested Improvement
|
||||
description: How should the documentation be improved?
|
||||
placeholder: |
|
||||
The documentation should instead explain...
|
||||
Or: Add a section that covers...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: area
|
||||
attributes:
|
||||
label: Documentation Area
|
||||
description: Which area of MetaBuilder does this documentation cover?
|
||||
options:
|
||||
- Getting Started
|
||||
- Architecture
|
||||
- API Reference
|
||||
- Package System
|
||||
- DBAL
|
||||
- Permission System
|
||||
- Multi-Tenancy
|
||||
- Lua Scripting
|
||||
- Workflows
|
||||
- Database/Prisma
|
||||
- Testing
|
||||
- Deployment
|
||||
- Contributing
|
||||
- Security
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: additional
|
||||
attributes:
|
||||
label: Additional Context
|
||||
description: Any other relevant information
|
||||
placeholder: |
|
||||
- Screenshots of confusing sections
|
||||
- Related issues or PRs
|
||||
- Why this improvement is needed
|
||||
|
||||
- type: checkboxes
|
||||
id: contribution
|
||||
attributes:
|
||||
label: Contribution
|
||||
description: Would you like to help improve this documentation?
|
||||
options:
|
||||
- label: I am willing to submit a PR to fix/improve this documentation
|
||||
required: false
|
||||
|
||||
- type: checkboxes
|
||||
id: checklist
|
||||
attributes:
|
||||
label: Pre-submission Checklist
|
||||
options:
|
||||
- label: I have searched existing issues for similar documentation requests
|
||||
required: true
|
||||
- label: I have verified the documentation issue still exists in the latest version
|
||||
required: true
|
||||
name: 📚 Documentation
|
||||
description: Report an issue with documentation or request documentation improvements
|
||||
title: "[Docs]: "
|
||||
labels: ["documentation", "triage"]
|
||||
assignees: []
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for helping improve MetaBuilder's documentation! Clear docs help everyone.
|
||||
|
||||
- type: dropdown
|
||||
id: doc-type
|
||||
attributes:
|
||||
label: Documentation Type
|
||||
description: What kind of documentation issue is this?
|
||||
options:
|
||||
- Missing documentation
|
||||
- Incorrect/outdated information
|
||||
- Unclear explanation
|
||||
- Broken links
|
||||
- Typo/grammar
|
||||
- Code example not working
|
||||
- Missing code example
|
||||
- Architecture documentation
|
||||
- API documentation
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: location
|
||||
attributes:
|
||||
label: Documentation Location
|
||||
description: Where is the documentation issue? (provide file path, URL, or section name)
|
||||
placeholder: |
|
||||
File: docs/architecture/packages.md
|
||||
Or URL: https://github.com/johndoe6345789/metabuilder/tree/main/docs
|
||||
Or Section: "Getting Started > Database Setup"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: issue
|
||||
attributes:
|
||||
label: Issue Description
|
||||
description: What's wrong with the current documentation?
|
||||
placeholder: The current documentation states... but it should...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: suggestion
|
||||
attributes:
|
||||
label: Suggested Improvement
|
||||
description: How should the documentation be improved?
|
||||
placeholder: |
|
||||
The documentation should instead explain...
|
||||
Or: Add a section that covers...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: area
|
||||
attributes:
|
||||
label: Documentation Area
|
||||
description: Which area of MetaBuilder does this documentation cover?
|
||||
options:
|
||||
- Getting Started
|
||||
- Architecture
|
||||
- API Reference
|
||||
- Package System
|
||||
- DBAL
|
||||
- Permission System
|
||||
- Multi-Tenancy
|
||||
- Lua Scripting
|
||||
- Workflows
|
||||
- Database/Prisma
|
||||
- Testing
|
||||
- Deployment
|
||||
- Contributing
|
||||
- Security
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: additional
|
||||
attributes:
|
||||
label: Additional Context
|
||||
description: Any other relevant information
|
||||
placeholder: |
|
||||
- Screenshots of confusing sections
|
||||
- Related issues or PRs
|
||||
- Why this improvement is needed
|
||||
|
||||
- type: checkboxes
|
||||
id: contribution
|
||||
attributes:
|
||||
label: Contribution
|
||||
description: Would you like to help improve this documentation?
|
||||
options:
|
||||
- label: I am willing to submit a PR to fix/improve this documentation
|
||||
required: false
|
||||
|
||||
- type: checkboxes
|
||||
id: checklist
|
||||
attributes:
|
||||
label: Pre-submission Checklist
|
||||
options:
|
||||
- label: I have searched existing issues for similar documentation requests
|
||||
required: true
|
||||
- label: I have verified the documentation issue still exists in the latest version
|
||||
required: true
|
||||
|
||||
268
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
268
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
@@ -1,134 +1,134 @@
|
||||
name: ✨ Feature Request
|
||||
description: Suggest a new feature or enhancement for MetaBuilder
|
||||
title: "[Feature]: "
|
||||
labels: ["enhancement", "triage"]
|
||||
assignees: []
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for your interest in improving MetaBuilder! Please describe your feature request in detail.
|
||||
|
||||
- type: textarea
|
||||
id: problem
|
||||
attributes:
|
||||
label: Problem Statement
|
||||
description: Is your feature request related to a problem? Describe what you're trying to achieve.
|
||||
placeholder: I'm frustrated when... / I need to be able to...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: solution
|
||||
attributes:
|
||||
label: Proposed Solution
|
||||
description: Describe the solution you'd like to see
|
||||
placeholder: I would like MetaBuilder to...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: alternatives
|
||||
attributes:
|
||||
label: Alternatives Considered
|
||||
description: Have you considered any alternative solutions or workarounds?
|
||||
placeholder: I've tried... but...
|
||||
|
||||
- type: dropdown
|
||||
id: component
|
||||
attributes:
|
||||
label: Component/Area
|
||||
description: Which part of MetaBuilder would this feature affect?
|
||||
options:
|
||||
- Frontend (Next.js UI)
|
||||
- Backend (API/Auth)
|
||||
- Database (Prisma/Schema)
|
||||
- DBAL (TypeScript/C++)
|
||||
- Package System
|
||||
- Lua Scripting
|
||||
- Multi-Tenant System
|
||||
- Permission System (Levels 1-6)
|
||||
- Workflows
|
||||
- Documentation
|
||||
- Developer Experience
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: priority
|
||||
attributes:
|
||||
label: Priority
|
||||
description: How important is this feature to you?
|
||||
options:
|
||||
- High (Blocker for my use case)
|
||||
- Medium (Would be very helpful)
|
||||
- Low (Nice to have)
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: user-level
|
||||
attributes:
|
||||
label: Target User Level
|
||||
description: Which permission level(s) would use this feature?
|
||||
multiple: true
|
||||
options:
|
||||
- Level 1 (Public)
|
||||
- Level 2 (User)
|
||||
- Level 3 (Moderator)
|
||||
- Level 4 (Admin)
|
||||
- Level 5 (God)
|
||||
- Level 6 (Supergod)
|
||||
- All levels
|
||||
|
||||
- type: textarea
|
||||
id: use-cases
|
||||
attributes:
|
||||
label: Use Cases
|
||||
description: Provide specific use cases or examples of how this feature would be used
|
||||
placeholder: |
|
||||
1. As a [user type], I want to [action] so that [benefit]
|
||||
2. When [scenario], this feature would help by [outcome]
|
||||
|
||||
- type: textarea
|
||||
id: technical
|
||||
attributes:
|
||||
label: Technical Considerations
|
||||
description: Any technical details, implementation ideas, or constraints?
|
||||
placeholder: |
|
||||
- This might require changes to...
|
||||
- Could be implemented using...
|
||||
- May affect performance of...
|
||||
|
||||
- type: textarea
|
||||
id: mockups
|
||||
attributes:
|
||||
label: Mockups/Examples
|
||||
description: Add any mockups, diagrams, or examples (drag and drop images or links)
|
||||
placeholder: Paste images or links here...
|
||||
|
||||
- type: checkboxes
|
||||
id: contribution
|
||||
attributes:
|
||||
label: Contribution
|
||||
description: Would you be willing to help implement this feature?
|
||||
options:
|
||||
- label: I am willing to submit a PR for this feature
|
||||
required: false
|
||||
- label: I can help with testing this feature
|
||||
required: false
|
||||
|
||||
- type: checkboxes
|
||||
id: checklist
|
||||
attributes:
|
||||
label: Pre-submission Checklist
|
||||
description: Please verify the following before submitting
|
||||
options:
|
||||
- label: I have searched existing issues and discussions for similar requests
|
||||
required: true
|
||||
- label: This feature aligns with MetaBuilder's data-driven, multi-tenant architecture
|
||||
required: true
|
||||
- label: I have provided sufficient detail for others to understand the request
|
||||
required: true
|
||||
name: ✨ Feature Request
|
||||
description: Suggest a new feature or enhancement for MetaBuilder
|
||||
title: "[Feature]: "
|
||||
labels: ["enhancement", "triage"]
|
||||
assignees: []
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for your interest in improving MetaBuilder! Please describe your feature request in detail.
|
||||
|
||||
- type: textarea
|
||||
id: problem
|
||||
attributes:
|
||||
label: Problem Statement
|
||||
description: Is your feature request related to a problem? Describe what you're trying to achieve.
|
||||
placeholder: I'm frustrated when... / I need to be able to...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: solution
|
||||
attributes:
|
||||
label: Proposed Solution
|
||||
description: Describe the solution you'd like to see
|
||||
placeholder: I would like MetaBuilder to...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: alternatives
|
||||
attributes:
|
||||
label: Alternatives Considered
|
||||
description: Have you considered any alternative solutions or workarounds?
|
||||
placeholder: I've tried... but...
|
||||
|
||||
- type: dropdown
|
||||
id: component
|
||||
attributes:
|
||||
label: Component/Area
|
||||
description: Which part of MetaBuilder would this feature affect?
|
||||
options:
|
||||
- Frontend (Next.js UI)
|
||||
- Backend (API/Auth)
|
||||
- Database (Prisma/Schema)
|
||||
- DBAL (TypeScript/C++)
|
||||
- Package System
|
||||
- Lua Scripting
|
||||
- Multi-Tenant System
|
||||
- Permission System (Levels 1-6)
|
||||
- Workflows
|
||||
- Documentation
|
||||
- Developer Experience
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: priority
|
||||
attributes:
|
||||
label: Priority
|
||||
description: How important is this feature to you?
|
||||
options:
|
||||
- High (Blocker for my use case)
|
||||
- Medium (Would be very helpful)
|
||||
- Low (Nice to have)
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: user-level
|
||||
attributes:
|
||||
label: Target User Level
|
||||
description: Which permission level(s) would use this feature?
|
||||
multiple: true
|
||||
options:
|
||||
- Level 1 (Public)
|
||||
- Level 2 (User)
|
||||
- Level 3 (Moderator)
|
||||
- Level 4 (Admin)
|
||||
- Level 5 (God)
|
||||
- Level 6 (Supergod)
|
||||
- All levels
|
||||
|
||||
- type: textarea
|
||||
id: use-cases
|
||||
attributes:
|
||||
label: Use Cases
|
||||
description: Provide specific use cases or examples of how this feature would be used
|
||||
placeholder: |
|
||||
1. As a [user type], I want to [action] so that [benefit]
|
||||
2. When [scenario], this feature would help by [outcome]
|
||||
|
||||
- type: textarea
|
||||
id: technical
|
||||
attributes:
|
||||
label: Technical Considerations
|
||||
description: Any technical details, implementation ideas, or constraints?
|
||||
placeholder: |
|
||||
- This might require changes to...
|
||||
- Could be implemented using...
|
||||
- May affect performance of...
|
||||
|
||||
- type: textarea
|
||||
id: mockups
|
||||
attributes:
|
||||
label: Mockups/Examples
|
||||
description: Add any mockups, diagrams, or examples (drag and drop images or links)
|
||||
placeholder: Paste images or links here...
|
||||
|
||||
- type: checkboxes
|
||||
id: contribution
|
||||
attributes:
|
||||
label: Contribution
|
||||
description: Would you be willing to help implement this feature?
|
||||
options:
|
||||
- label: I am willing to submit a PR for this feature
|
||||
required: false
|
||||
- label: I can help with testing this feature
|
||||
required: false
|
||||
|
||||
- type: checkboxes
|
||||
id: checklist
|
||||
attributes:
|
||||
label: Pre-submission Checklist
|
||||
description: Please verify the following before submitting
|
||||
options:
|
||||
- label: I have searched existing issues and discussions for similar requests
|
||||
required: true
|
||||
- label: This feature aligns with MetaBuilder's data-driven, multi-tenant architecture
|
||||
required: true
|
||||
- label: I have provided sufficient detail for others to understand the request
|
||||
required: true
|
||||
|
||||
328
.github/ISSUE_TEMPLATE/package_request.yml
vendored
328
.github/ISSUE_TEMPLATE/package_request.yml
vendored
@@ -1,164 +1,164 @@
|
||||
name: 📦 Package Request
|
||||
description: Request a new package for MetaBuilder's package system
|
||||
title: "[Package]: "
|
||||
labels: ["enhancement", "package", "triage"]
|
||||
assignees: []
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
MetaBuilder's power comes from its data-driven package system. Request a new package here!
|
||||
|
||||
- type: input
|
||||
id: package-name
|
||||
attributes:
|
||||
label: Package Name
|
||||
description: Proposed name for the package (use snake_case)
|
||||
placeholder: e.g., blog_engine, task_manager, analytics_dashboard
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Package Description
|
||||
description: What functionality would this package provide?
|
||||
placeholder: This package would enable users to...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: package-type
|
||||
attributes:
|
||||
label: Package Type
|
||||
description: What type of package is this?
|
||||
options:
|
||||
- UI Component/Widget
|
||||
- Feature Module
|
||||
- Integration
|
||||
- Tool/Utility
|
||||
- Template/Theme
|
||||
- Data Schema
|
||||
- Workflow
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: min-level
|
||||
attributes:
|
||||
label: Minimum Permission Level
|
||||
description: What's the minimum user level required to use this package?
|
||||
options:
|
||||
- Level 1 (Public - no auth required)
|
||||
- Level 2 (User - basic authentication)
|
||||
- Level 3 (Moderator - content moderation)
|
||||
- Level 4 (Admin - user management)
|
||||
- Level 5 (God - system configuration)
|
||||
- Level 6 (Supergod - full system control)
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: features
|
||||
attributes:
|
||||
label: Key Features
|
||||
description: List the main features this package should include
|
||||
placeholder: |
|
||||
- Feature 1: Description
|
||||
- Feature 2: Description
|
||||
- Feature 3: Description
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: use-cases
|
||||
attributes:
|
||||
label: Use Cases
|
||||
description: Describe scenarios where this package would be useful
|
||||
placeholder: |
|
||||
1. A [user type] needs to [action] in order to [goal]
|
||||
2. When [scenario], this package would help by [benefit]
|
||||
|
||||
- type: textarea
|
||||
id: components
|
||||
attributes:
|
||||
label: Proposed Components
|
||||
description: What UI components would this package include?
|
||||
placeholder: |
|
||||
- ComponentName1: Description
|
||||
- ComponentName2: Description
|
||||
|
||||
- type: textarea
|
||||
id: lua-scripts
|
||||
attributes:
|
||||
label: Lua Scripts Needed
|
||||
description: What Lua scripts would be required? (MetaBuilder is 95% JSON/Lua)
|
||||
placeholder: |
|
||||
- initialize.lua: Setup and configuration
|
||||
- validators.lua: Data validation
|
||||
- helpers.lua: Utility functions
|
||||
|
||||
- type: textarea
|
||||
id: schemas
|
||||
attributes:
|
||||
label: Database Schemas
|
||||
description: What database tables/models would be needed?
|
||||
placeholder: |
|
||||
- Model1 { field1, field2, ... }
|
||||
- Model2 { field1, field2, ... }
|
||||
|
||||
- type: textarea
|
||||
id: dependencies
|
||||
attributes:
|
||||
label: Package Dependencies
|
||||
description: Would this package depend on other packages?
|
||||
placeholder: |
|
||||
- @metabuilder/dashboard
|
||||
- @metabuilder/form_builder
|
||||
|
||||
- type: dropdown
|
||||
id: multi-tenant
|
||||
attributes:
|
||||
label: Multi-Tenant Support
|
||||
description: Does this package need to be tenant-aware?
|
||||
options:
|
||||
- "Yes - Requires tenant isolation"
|
||||
- "No - Can be global"
|
||||
- "Optional - Configurable"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: similar
|
||||
attributes:
|
||||
label: Similar Packages/Inspiration
|
||||
description: Are there similar packages in other systems or frameworks?
|
||||
placeholder: |
|
||||
- System X has a similar feature that...
|
||||
- This is inspired by...
|
||||
|
||||
- type: checkboxes
|
||||
id: contribution
|
||||
attributes:
|
||||
label: Contribution
|
||||
options:
|
||||
- label: I am willing to help develop this package
|
||||
required: false
|
||||
- label: I can provide Lua scripts for this package
|
||||
required: false
|
||||
- label: I can help with testing this package
|
||||
required: false
|
||||
|
||||
- type: checkboxes
|
||||
id: checklist
|
||||
attributes:
|
||||
label: Pre-submission Checklist
|
||||
options:
|
||||
- label: I have searched existing packages to ensure this doesn't already exist
|
||||
required: true
|
||||
- label: This package aligns with MetaBuilder's data-driven architecture
|
||||
required: true
|
||||
- label: I have considered multi-tenant requirements
|
||||
required: true
|
||||
name: 📦 Package Request
|
||||
description: Request a new package for MetaBuilder's package system
|
||||
title: "[Package]: "
|
||||
labels: ["enhancement", "package", "triage"]
|
||||
assignees: []
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
MetaBuilder's power comes from its data-driven package system. Request a new package here!
|
||||
|
||||
- type: input
|
||||
id: package-name
|
||||
attributes:
|
||||
label: Package Name
|
||||
description: Proposed name for the package (use snake_case)
|
||||
placeholder: e.g., blog_engine, task_manager, analytics_dashboard
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Package Description
|
||||
description: What functionality would this package provide?
|
||||
placeholder: This package would enable users to...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: package-type
|
||||
attributes:
|
||||
label: Package Type
|
||||
description: What type of package is this?
|
||||
options:
|
||||
- UI Component/Widget
|
||||
- Feature Module
|
||||
- Integration
|
||||
- Tool/Utility
|
||||
- Template/Theme
|
||||
- Data Schema
|
||||
- Workflow
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: min-level
|
||||
attributes:
|
||||
label: Minimum Permission Level
|
||||
description: What's the minimum user level required to use this package?
|
||||
options:
|
||||
- Level 1 (Public - no auth required)
|
||||
- Level 2 (User - basic authentication)
|
||||
- Level 3 (Moderator - content moderation)
|
||||
- Level 4 (Admin - user management)
|
||||
- Level 5 (God - system configuration)
|
||||
- Level 6 (Supergod - full system control)
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: features
|
||||
attributes:
|
||||
label: Key Features
|
||||
description: List the main features this package should include
|
||||
placeholder: |
|
||||
- Feature 1: Description
|
||||
- Feature 2: Description
|
||||
- Feature 3: Description
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: use-cases
|
||||
attributes:
|
||||
label: Use Cases
|
||||
description: Describe scenarios where this package would be useful
|
||||
placeholder: |
|
||||
1. A [user type] needs to [action] in order to [goal]
|
||||
2. When [scenario], this package would help by [benefit]
|
||||
|
||||
- type: textarea
|
||||
id: components
|
||||
attributes:
|
||||
label: Proposed Components
|
||||
description: What UI components would this package include?
|
||||
placeholder: |
|
||||
- ComponentName1: Description
|
||||
- ComponentName2: Description
|
||||
|
||||
- type: textarea
|
||||
id: lua-scripts
|
||||
attributes:
|
||||
label: Lua Scripts Needed
|
||||
description: What Lua scripts would be required? (MetaBuilder is 95% JSON/Lua)
|
||||
placeholder: |
|
||||
- initialize.lua: Setup and configuration
|
||||
- validators.lua: Data validation
|
||||
- helpers.lua: Utility functions
|
||||
|
||||
- type: textarea
|
||||
id: schemas
|
||||
attributes:
|
||||
label: Database Schemas
|
||||
description: What database tables/models would be needed?
|
||||
placeholder: |
|
||||
- Model1 { field1, field2, ... }
|
||||
- Model2 { field1, field2, ... }
|
||||
|
||||
- type: textarea
|
||||
id: dependencies
|
||||
attributes:
|
||||
label: Package Dependencies
|
||||
description: Would this package depend on other packages?
|
||||
placeholder: |
|
||||
- @metabuilder/dashboard
|
||||
- @metabuilder/form_builder
|
||||
|
||||
- type: dropdown
|
||||
id: multi-tenant
|
||||
attributes:
|
||||
label: Multi-Tenant Support
|
||||
description: Does this package need to be tenant-aware?
|
||||
options:
|
||||
- "Yes - Requires tenant isolation"
|
||||
- "No - Can be global"
|
||||
- "Optional - Configurable"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: similar
|
||||
attributes:
|
||||
label: Similar Packages/Inspiration
|
||||
description: Are there similar packages in other systems or frameworks?
|
||||
placeholder: |
|
||||
- System X has a similar feature that...
|
||||
- This is inspired by...
|
||||
|
||||
- type: checkboxes
|
||||
id: contribution
|
||||
attributes:
|
||||
label: Contribution
|
||||
options:
|
||||
- label: I am willing to help develop this package
|
||||
required: false
|
||||
- label: I can provide Lua scripts for this package
|
||||
required: false
|
||||
- label: I can help with testing this package
|
||||
required: false
|
||||
|
||||
- type: checkboxes
|
||||
id: checklist
|
||||
attributes:
|
||||
label: Pre-submission Checklist
|
||||
options:
|
||||
- label: I have searched existing packages to ensure this doesn't already exist
|
||||
required: true
|
||||
- label: This package aligns with MetaBuilder's data-driven architecture
|
||||
required: true
|
||||
- label: I have considered multi-tenant requirements
|
||||
required: true
|
||||
|
||||
91
.github/actions/setup-npm/action.yml
vendored
91
.github/actions/setup-npm/action.yml
vendored
@@ -1,91 +0,0 @@
|
||||
name: 'Setup npm with local registry'
|
||||
description: 'Starts Verdaccio, publishes patched packages, then runs npm install'
|
||||
|
||||
inputs:
|
||||
node-version:
|
||||
description: 'Node.js version'
|
||||
required: false
|
||||
default: '20'
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: ${{ inputs.node-version }}
|
||||
|
||||
- name: Start Verdaccio and publish patched packages
|
||||
shell: bash
|
||||
run: |
|
||||
# Install and start Verdaccio (lightweight npm registry, ~2s startup)
|
||||
npm install -g verdaccio@6 --silent
|
||||
|
||||
mkdir -p /tmp/verdaccio-storage
|
||||
cat > /tmp/verdaccio.yaml << 'VERDACCIO_EOF'
|
||||
storage: /tmp/verdaccio-storage
|
||||
uplinks:
|
||||
npmjs:
|
||||
url: https://registry.npmjs.org/
|
||||
timeout: 60s
|
||||
max_fails: 3
|
||||
packages:
|
||||
'@esbuild-kit/*':
|
||||
access: $all
|
||||
publish: $all
|
||||
proxy: npmjs
|
||||
'**':
|
||||
access: $all
|
||||
publish: $all
|
||||
proxy: npmjs
|
||||
server:
|
||||
keepAliveTimeout: 60
|
||||
log:
|
||||
type: stdout
|
||||
format: pretty
|
||||
level: warn
|
||||
listen: 0.0.0.0:4873
|
||||
VERDACCIO_EOF
|
||||
|
||||
verdaccio --config /tmp/verdaccio.yaml &
|
||||
VERDACCIO_PID=$!
|
||||
echo "Verdaccio PID: $VERDACCIO_PID"
|
||||
|
||||
# Wait for Verdaccio to be ready (usually <3s)
|
||||
timeout 30 bash -c 'until curl -sf http://localhost:4873/-/ping >/dev/null 2>&1; do sleep 1; done'
|
||||
echo "Verdaccio ready"
|
||||
|
||||
# Create a CI user on Verdaccio and get an auth token
|
||||
RESPONSE=$(curl -s -XPUT http://localhost:4873/-/user/org.couchdb.user:ci \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Accept: application/json" \
|
||||
-d '{"name":"ci","password":"ci","email":"ci@localhost","type":"user"}')
|
||||
TOKEN=$(echo "$RESPONSE" | python3 -c "import json,sys; print(json.load(sys.stdin).get('token',''))" 2>/dev/null)
|
||||
if [ -z "$TOKEN" ]; then
|
||||
echo "Warning: could not get Verdaccio token, publish may fail"
|
||||
else
|
||||
npm set //localhost:4873/:_authToken="$TOKEN"
|
||||
echo "Verdaccio auth configured"
|
||||
fi
|
||||
|
||||
# Publish all patched tarballs
|
||||
PATCHES_DIR="deployment/npm-patches"
|
||||
for tarball in "$PATCHES_DIR"/*.tgz; do
|
||||
[ -f "$tarball" ] || continue
|
||||
echo "Publishing $tarball..."
|
||||
npm publish "$tarball" \
|
||||
--registry http://localhost:4873 \
|
||||
--tag patched \
|
||||
2>&1 | grep -v "^npm notice" || true
|
||||
done
|
||||
echo "Patched packages published to Verdaccio"
|
||||
|
||||
- name: Install npm dependencies
|
||||
shell: bash
|
||||
run: |
|
||||
# Retry npm install up to 3 times for transient network failures
|
||||
for attempt in 1 2 3; do
|
||||
npm install && break
|
||||
echo "npm install attempt $attempt failed, retrying in 15s..."
|
||||
sleep 15
|
||||
done
|
||||
42
.github/codeql/codeql-config.yml
vendored
42
.github/codeql/codeql-config.yml
vendored
@@ -1,42 +0,0 @@
|
||||
name: "MetaBuilder CodeQL Config"
|
||||
|
||||
# CodeQL configuration for semantic code search across 2-3M LOC codebase
|
||||
# Purpose: Enable pattern search, caller analysis, data flow queries for story planning
|
||||
# NOT for security gates - that's handled by gated-pipeline.yml
|
||||
|
||||
# Paths to analyze (focus on source, exclude generated)
|
||||
paths:
|
||||
- frontends
|
||||
- codegen
|
||||
- workflowui
|
||||
- packages
|
||||
- fakemui/react
|
||||
- workflow/plugins
|
||||
- dbal
|
||||
- services
|
||||
- hooks
|
||||
- redux
|
||||
|
||||
# Paths to ignore (generated, vendor, tests, archives)
|
||||
paths-ignore:
|
||||
- '**/node_modules/**'
|
||||
- '**/.next/**'
|
||||
- '**/dist/**'
|
||||
- '**/build/**'
|
||||
- '**/__pycache__/**'
|
||||
- '**/test-results/**'
|
||||
- '**/playwright-report/**'
|
||||
- '**/coverage/**'
|
||||
- 'old/**'
|
||||
- 'txt/**'
|
||||
- 'spec/**'
|
||||
- '**/*.test.ts'
|
||||
- '**/*.test.tsx'
|
||||
- '**/*.spec.ts'
|
||||
- '**/*.spec.tsx'
|
||||
- '**/e2e/**'
|
||||
|
||||
# Query suites - security-and-quality provides comprehensive code analysis
|
||||
# This enables rich semantic queries for code search, not just security scanning
|
||||
queries:
|
||||
- uses: security-and-quality
|
||||
23
.github/dependabot.yml
vendored
23
.github/dependabot.yml
vendored
@@ -1,12 +1,11 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
|
||||
- package-ecosystem: "devcontainers"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
|
||||
- package-ecosystem: "devcontainers"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
|
||||
571
.github/workflows/README.md
vendored
Normal file
571
.github/workflows/README.md
vendored
Normal file
@@ -0,0 +1,571 @@
|
||||
# GitHub Workflows Documentation
|
||||
|
||||
This directory contains automated workflows for CI/CD, code quality, and comprehensive AI-assisted development throughout the entire SDLC.
|
||||
|
||||
## 🚦 Enterprise Gated Tree Workflow
|
||||
|
||||
MetaBuilder uses an **Enterprise Gated Tree Workflow** that ensures all code changes pass through multiple validation gates before being merged and deployed.
|
||||
|
||||
**📖 Complete Guide:** [Enterprise Gated Workflow Documentation](../../docs/ENTERPRISE_GATED_WORKFLOW.md)
|
||||
|
||||
### Quick Overview
|
||||
|
||||
All PRs must pass through 5 sequential gates:
|
||||
|
||||
1. **Gate 1: Code Quality** - Prisma, TypeScript, Lint, Security
|
||||
2. **Gate 2: Testing** - Unit, E2E, DBAL Daemon tests
|
||||
3. **Gate 3: Build & Package** - Application build, quality metrics
|
||||
4. **Gate 4: Review & Approval** - Human code review (1 approval required)
|
||||
5. **Gate 5: Deployment** - Staging (auto) → Production (manual approval)
|
||||
|
||||
**Key Benefits:**
|
||||
- ✅ Sequential gates prevent wasted resources
|
||||
- ✅ Automatic merge after approval
|
||||
- ✅ Manual approval required for production
|
||||
- ✅ Clear visibility of gate status on PRs
|
||||
- ✅ Audit trail for all deployments
|
||||
|
||||
### Legacy Workflow Cleanup
|
||||
|
||||
**Deprecated and Removed (Dec 2025):**
|
||||
- ❌ `ci/ci.yml` - Replaced by `gated-ci.yml` (100% redundant)
|
||||
- ❌ `quality/deployment.yml` - Replaced by `gated-deployment.yml` (100% redundant)
|
||||
|
||||
**Modified:**
|
||||
- ⚡ `development.yml` - Refactored to remove redundant quality checks, kept unique Copilot features
|
||||
|
||||
See [Legacy Pipeline Cruft Report](../../docs/LEGACY_PIPELINE_CRUFT_REPORT.md) for analysis.
|
||||
|
||||
## 🤖 GitHub Copilot Integration
|
||||
|
||||
All workflows are designed to work seamlessly with **GitHub Copilot** to assist throughout the Software Development Lifecycle:
|
||||
|
||||
- **Planning Phase**: Architecture review, PRD alignment, implementation guidance
|
||||
- **Development Phase**: Continuous quality feedback, code suggestions, refactoring opportunities
|
||||
- **Testing Phase**: Automated code review, security checks, quality validation
|
||||
- **Deployment Phase**: Pre-deployment validation, health checks, monitoring
|
||||
- **Maintenance Phase**: Issue triage, automated fixes, dependency management
|
||||
|
||||
**📖 Copilot Instructions:** [.github/copilot-instructions.md](../copilot-instructions.md)
|
||||
|
||||
## Workflows Overview
|
||||
|
||||
### 🚦 Enterprise Gated Workflows (New)
|
||||
|
||||
#### Issue and PR Triage (`triage.yml`) 🆕
|
||||
**Triggered on:** Issues (opened/edited/reopened) and Pull Requests (opened/reopened/synchronize/edited)
|
||||
|
||||
**Purpose:** Quickly categorize inbound work so reviewers know what to look at first.
|
||||
|
||||
- Auto-applies labels for type (bug/enhancement/docs/security/testing/performance) and area (frontend/backend/database/workflows/documentation)
|
||||
- Sets a default priority and highlights beginner-friendly issues
|
||||
- Flags missing information (repro steps, expected/actual results, versions) with a checklist comment
|
||||
- For PRs, labels areas touched, estimates risk based on change size and critical paths, and prompts for test plans/screenshots/linked issues
|
||||
- Mentions **@copilot** to sanity-check the triage with GitHub-native AI (no external Codex webhooks)
|
||||
|
||||
This workflow runs alongside the existing PR management jobs to keep triage lightweight while preserving the richer checks in the gated pipelines.
|
||||
|
||||
#### 1. Enterprise Gated CI/CD Pipeline (`gated-ci.yml`)
|
||||
**Triggered on:** Push to main/master/develop branches, Pull requests
|
||||
|
||||
**Structure:**
|
||||
- **Gate 1:** Code Quality (Prisma, TypeScript, Lint, Security)
|
||||
- **Gate 2:** Testing (Unit, E2E, DBAL Daemon)
|
||||
- **Gate 3:** Build & Package (Build, Quality Metrics)
|
||||
- **Gate 4:** Review & Approval (Human review required)
|
||||
|
||||
**Features:**
|
||||
- Sequential gate execution for efficiency
|
||||
- Clear gate status reporting on PRs
|
||||
- Automatic progression through gates
|
||||
- Summary report with all gate results
|
||||
|
||||
**Best for:** Small to medium teams, straightforward workflows
|
||||
|
||||
#### 1a. Enterprise Gated CI/CD Pipeline - Atomic (`gated-ci-atomic.yml`) 🆕
|
||||
**Triggered on:** Push to main/master/develop branches, Pull requests
|
||||
|
||||
**Structure:**
|
||||
- **Gate 1:** Code Quality - 7 atomic steps
|
||||
- 1.1 Prisma Validation
|
||||
- 1.2 TypeScript Check (+ strict mode analysis)
|
||||
- 1.3 ESLint (+ any-type detection + ts-ignore detection)
|
||||
- 1.4 Security Scan (+ dependency audit)
|
||||
- 1.5 File Size Check
|
||||
- 1.6 Code Complexity Analysis
|
||||
- 1.7 Stub Implementation Detection
|
||||
- **Gate 2:** Testing - 3 atomic steps
|
||||
- 2.1 Unit Tests (+ coverage analysis)
|
||||
- 2.2 E2E Tests
|
||||
- 2.3 DBAL Daemon Tests
|
||||
- **Gate 3:** Build & Package - 2 atomic steps
|
||||
- 3.1 Application Build (+ bundle analysis)
|
||||
- 3.2 Quality Metrics
|
||||
- **Gate 4:** Review & Approval (Human review required)
|
||||
|
||||
**Features:**
|
||||
- **Atomic validation steps** for superior visualization
|
||||
- Each tool from `/tools` runs as separate job
|
||||
- **Gate artifacts** persisted between steps (30-day retention)
|
||||
- Granular failure detection
|
||||
- Parallel execution within gates
|
||||
- Complete audit trail with JSON artifacts
|
||||
- Individual step timing and status
|
||||
|
||||
**Best for:** Large teams, enterprise compliance, audit requirements
|
||||
|
||||
**Documentation:** See [Atomic Gated Workflow Architecture](../../docs/ATOMIC_GATED_WORKFLOW.md)
|
||||
|
||||
#### 2. Enterprise Gated Deployment (`gated-deployment.yml`)
|
||||
**Triggered on:** Push to main/master, Releases, Manual workflow dispatch
|
||||
|
||||
**Environments:**
|
||||
- **Staging:** Automatic deployment after merge to main
|
||||
- **Production:** Manual approval required
|
||||
|
||||
**Features:**
|
||||
- Pre-deployment validation (schema, security, size)
|
||||
- Breaking change detection and warnings
|
||||
- Environment-specific deployment paths
|
||||
- Post-deployment health checks
|
||||
- Automatic deployment tracking issues
|
||||
- Rollback preparation and procedures
|
||||
|
||||
**Gate 5:** Deployment gate ensures only reviewed code reaches production
|
||||
|
||||
### 🔄 Legacy Workflows (Still Active)
|
||||
|
||||
#### 3. CI/CD Workflow (`ci/ci.yml`) - ❌ REMOVED
|
||||
**Status:** Deprecated and removed (Dec 2025)
|
||||
**Reason:** 100% functionality superseded by `gated-ci.yml`
|
||||
|
||||
**Jobs:** ~~Prisma Check, Lint, Build, E2E Tests, Quality Check~~
|
||||
|
||||
**Replacement:** Use `gated-ci.yml` for all CI/CD operations
|
||||
**Triggered on:** Push to main/master/develop branches, Pull requests
|
||||
|
||||
**Jobs:**
|
||||
- **Prisma Check**: Validates database schema and generates Prisma client
|
||||
- **Lint**: Runs ESLint to check code quality
|
||||
- **Build**: Builds the application and uploads artifacts
|
||||
- **E2E Tests**: Runs Playwright end-to-end tests
|
||||
- **Quality Check**: Checks for console.log statements and TODO comments
|
||||
|
||||
### 4. Automated Code Review (`code-review.yml`)
|
||||
**Triggered on:** Pull request opened, synchronized, or reopened
|
||||
|
||||
**Features:**
|
||||
- Analyzes code changes for security issues (eval, innerHTML, XSS risks)
|
||||
- Checks for code quality issues (console.log, debugger, any types)
|
||||
- Provides suggestions for improvements
|
||||
- **Auto-approves PRs** if no blocking issues are found
|
||||
- Adds appropriate labels (needs-changes, ready-for-review, has-warnings)
|
||||
|
||||
**Review Criteria:**
|
||||
- ✅ Security vulnerabilities
|
||||
- ✅ Code quality issues
|
||||
- ✅ Type safety
|
||||
- ✅ React best practices
|
||||
- ✅ File size warnings
|
||||
|
||||
### 5. Auto Merge (`auto-merge.yml`) - Updated for Gated Workflow
|
||||
**Triggered on:** PR approval, CI workflow completion
|
||||
|
||||
**Features:**
|
||||
- Automatically merges PRs when:
|
||||
- PR is approved by reviewers
|
||||
- All gates pass (supports both gated and legacy CI checks)
|
||||
- No merge conflicts
|
||||
- PR is not in draft
|
||||
- **Automatically deletes the branch** after successful merge
|
||||
- Uses squash merge strategy
|
||||
- Posts comments about merge status
|
||||
- **Updated:** Now supports Enterprise Gated CI/CD Pipeline checks
|
||||
|
||||
### 6. Issue Triage (`issue-triage.yml`)
|
||||
**Triggered on:** New issues opened, issues labeled
|
||||
|
||||
**Features:**
|
||||
- Automatically categorizes and labels issues:
|
||||
- Type: bug, enhancement, documentation, testing, security, performance
|
||||
- Priority: high, medium, low
|
||||
- AI-fixable flag for automated fixes
|
||||
- Posts welcome message with issue summary
|
||||
- Suggests automated fix attempts for simple issues
|
||||
- Can create fix branches automatically with `create-pr` label
|
||||
|
||||
### 7. PR Management (`pr-management.yml`)
|
||||
**Triggered on:** PR opened, synchronized, labeled
|
||||
|
||||
**Features:**
|
||||
- Auto-labels PRs based on changed files:
|
||||
- workflows, tests, documentation, ui, styling, configuration, dependencies
|
||||
- Size labels (small/medium/large)
|
||||
- Type labels from PR title (bug, enhancement, refactor, etc.)
|
||||
- Validates PR descriptions
|
||||
- Links related issues automatically
|
||||
- Posts comments on related issues
|
||||
|
||||
### 8. Merge Conflict Check (`merge-conflict-check.yml`)
|
||||
**Triggered on:** PR opened/synchronized, push to main/master
|
||||
|
||||
**Features:**
|
||||
- Detects merge conflicts
|
||||
- Posts comment mentioning @copilot to resolve
|
||||
- Adds/removes `merge-conflict` label
|
||||
- Fails CI if conflicts exist
|
||||
|
||||
### 9. Planning & Design (`planning.yml`) 🆕
|
||||
**Triggered on:** Issues opened or labeled with enhancement/feature-request
|
||||
|
||||
**Features:**
|
||||
- **Architecture Review**: Analyzes feature requests against architectural principles
|
||||
- **PRD Alignment Check**: Ensures new features align with project mission
|
||||
- **Implementation Suggestions**: Provides step-by-step implementation guidance
|
||||
- Validates declarative-first approach
|
||||
- Checks multi-tenant and permission considerations
|
||||
- Creates design checklists for feature implementation
|
||||
- **@copilot integration** for architecture guidance
|
||||
|
||||
**SDLC Phase:** Planning & Design
|
||||
|
||||
### 10. Development Assistance (`development.yml`) 🆕 - Refactored
|
||||
**Triggered on:** Pull request updates, @copilot mentions
|
||||
|
||||
**Features:**
|
||||
- **Architectural Compliance Feedback**: Monitors declarative ratio and component sizes
|
||||
- **@copilot Interaction Handler**: Responds to @copilot mentions with context-aware guidance
|
||||
- **Refactoring Suggestions**: Identifies opportunities for improvement
|
||||
- Provides architectural reminders and best practices
|
||||
|
||||
**Note:** Refactored to remove redundant quality checks (lint/build now in gated-ci.yml)
|
||||
|
||||
**SDLC Phase:** Development
|
||||
|
||||
### 11. Deployment & Monitoring (`deployment.yml`) - ❌ REMOVED
|
||||
**Status:** Deprecated and removed (Dec 2025)
|
||||
**Reason:** 100% functionality superseded by `gated-deployment.yml` with improvements
|
||||
|
||||
**Jobs:** ~~Pre-Deployment Validation, Deployment Summary, Post-Deployment Health Checks~~
|
||||
|
||||
**Replacement:** Use `gated-deployment.yml` for all deployment operations
|
||||
|
||||
### 12. Code Size Limits (`size-limits.yml`)
|
||||
**Triggered on:** Pull requests, pushes to main (when source files change)
|
||||
|
||||
**Features:**
|
||||
- Enforces file size limits and posts PR comments on violations
|
||||
- Uploads a size report artifact
|
||||
- Monitors `frontends/nextjs/src/**` and runs `scripts/enforce-size-limits.ts` from `frontends/nextjs`
|
||||
|
||||
## SDLC Coverage
|
||||
|
||||
### 🎯 Complete Lifecycle Support
|
||||
|
||||
```
|
||||
┌─────────────┐
|
||||
│ Planning │ ← planning.yml (Architecture Review, PRD Check)
|
||||
└──────┬──────┘
|
||||
↓
|
||||
┌─────────────┐
|
||||
│ Development │ ← development.yml (Quality Feedback, Refactoring)
|
||||
└──────┬──────┘
|
||||
↓
|
||||
┌─────────────┐
|
||||
│ Testing │ ← ci.yml, code-review.yml (Lint, Build, E2E)
|
||||
└──────┬──────┘
|
||||
↓
|
||||
┌─────────────┐
|
||||
│ Integration │ ← pr-management.yml, auto-merge.yml
|
||||
└──────┬──────┘
|
||||
↓
|
||||
┌─────────────┐
|
||||
│ Deployment │ ← deployment.yml (Validation, Health Checks)
|
||||
└──────┬──────┘
|
||||
↓
|
||||
┌─────────────┐
|
||||
│ Maintenance │ ← issue-triage.yml, dependabot.yml
|
||||
└─────────────┘
|
||||
```
|
||||
|
||||
## Labels Used
|
||||
|
||||
### Automated Labels
|
||||
- `bug` - Bug fixes
|
||||
- `enhancement` - New features
|
||||
- `feature-request` - Proposed new features
|
||||
- `ready-to-implement` - Features ready for development
|
||||
- `documentation` - Documentation changes
|
||||
- `tests` - Test-related changes
|
||||
- `security` - Security issues
|
||||
- `performance` - Performance improvements
|
||||
- `needs-changes` - PR requires changes
|
||||
- `ready-for-review` - PR is ready for review
|
||||
- `has-warnings` - PR has warnings to address
|
||||
- `large-pr` - PR with many changes
|
||||
- `size: small/medium/large` - PR size indicators
|
||||
- `ai-fixable` - Issues that can be auto-fixed
|
||||
- `good first issue` - Good for newcomers
|
||||
- `priority: high/medium/low` - Issue priority
|
||||
- `merge-conflict` - PR has merge conflicts
|
||||
- `auto-fix` - Request automated fix
|
||||
- `create-pr` - Create fix PR for issue
|
||||
- `deployment` - Deployment tracking
|
||||
- `monitoring` - Monitoring and observability
|
||||
- `dependencies` - Dependency updates
|
||||
- `refactor` - Code refactoring
|
||||
- `chore` - Maintenance tasks
|
||||
- `workflows` - Workflow changes
|
||||
- `ui` - UI/UX changes
|
||||
- `styling` - CSS/Tailwind changes
|
||||
- `configuration` - Config file changes
|
||||
|
||||
## Configuration
|
||||
|
||||
### ESLint
|
||||
The project uses ESLint with TypeScript support and React-specific rules:
|
||||
- File: `eslint.config.js`
|
||||
- Strict type checking (warnings for gradual adoption)
|
||||
- React hooks validation
|
||||
- Code quality rules
|
||||
|
||||
### Playwright E2E Tests
|
||||
- Configuration: `playwright.config.ts`
|
||||
- Tests directory: `e2e/`
|
||||
- Runs on Chromium browser
|
||||
- Tests include:
|
||||
- Login functionality
|
||||
- Navigation
|
||||
- CRUD operations
|
||||
- Form interactions
|
||||
|
||||
## Usage
|
||||
|
||||
### Working with GitHub Copilot
|
||||
|
||||
**In Issues:**
|
||||
```markdown
|
||||
@copilot implement this issue
|
||||
@copilot review the architecture
|
||||
@copilot suggest testing strategy
|
||||
@copilot help with this
|
||||
```
|
||||
|
||||
**In Pull Requests:**
|
||||
- Automated feedback on every push
|
||||
- Continuous quality metrics
|
||||
- Refactoring suggestions
|
||||
- Architectural compliance checks
|
||||
|
||||
**In Your IDE:**
|
||||
- Reference `.github/copilot-instructions.md` for context
|
||||
- Use docs/getting-started/PRD.md for feature context
|
||||
- Follow existing patterns in `/packages/`
|
||||
- Ask Copilot about architectural decisions
|
||||
|
||||
### Testing Workflows Locally with Act
|
||||
|
||||
Before pushing to GitHub, test workflows locally using [act](https://github.com/nektos/act):
|
||||
|
||||
```bash
|
||||
# Quick diagnostics (no act required)
|
||||
./scripts/diagnose-workflows.sh
|
||||
|
||||
# Interactive workflow testing
|
||||
./scripts/test-workflows.sh
|
||||
|
||||
# Or use act directly
|
||||
act -l # List all workflows
|
||||
act push # Run CI pipeline
|
||||
act -j lint # Test linting job
|
||||
act -j build # Test build job
|
||||
```
|
||||
|
||||
**📖 See [ACT_TESTING.md](../../docs/ACT_TESTING.md) for comprehensive act testing guide**
|
||||
|
||||
### Running Locally
|
||||
|
||||
```bash
|
||||
# Run linter
|
||||
bun run lint
|
||||
|
||||
# Fix linting issues automatically
|
||||
bun run lint:fix
|
||||
|
||||
# Run e2e tests
|
||||
bun run test:e2e
|
||||
|
||||
# Run e2e tests with UI
|
||||
bun run test:e2e:ui
|
||||
|
||||
# Run e2e tests in headed mode
|
||||
bun run test:e2e:headed
|
||||
|
||||
# Build the project
|
||||
bun run build
|
||||
```
|
||||
|
||||
### Triggering Workflows
|
||||
|
||||
**Planning Phase:**
|
||||
1. Create issue with `enhancement` or `feature-request` label
|
||||
2. Automated architecture review and PRD alignment check
|
||||
3. Add `ready-to-implement` label for implementation guidance
|
||||
4. Follow suggested step-by-step plan
|
||||
|
||||
**Development Phase:**
|
||||
1. Create feature branch: `git checkout -b feature/issue-X`
|
||||
2. Push changes - triggers continuous quality feedback
|
||||
3. Get real-time metrics on declarative ratio, component sizes
|
||||
4. Mention `@copilot` in commits/PRs for specific help
|
||||
5. Review refactoring suggestions
|
||||
|
||||
**Testing & Review Phase:**
|
||||
1. Open PR - automatically reviewed, labeled, and validated
|
||||
2. Address any architectural compliance issues
|
||||
3. Get approval + pass tests
|
||||
4. Automatically merged and branch deleted
|
||||
|
||||
**Deployment Phase:**
|
||||
1. Merge to main - triggers pre-deployment validation
|
||||
2. Create release - generates deployment notes and tracking issue
|
||||
3. Post-deployment health checks run automatically
|
||||
4. Monitor deployment tracking issue for 48 hours
|
||||
|
||||
**Maintenance Phase:**
|
||||
1. Security audits run on every deployment
|
||||
2. Dependabot creates automated dependency PRs
|
||||
3. Issue triage handles new bug reports
|
||||
4. @copilot assists with fixes and improvements
|
||||
|
||||
### For Issues:
|
||||
1. Create an issue - automatically triaged and labeled
|
||||
2. Add `enhancement` label - triggers architecture review
|
||||
3. Add `ready-to-implement` label - get implementation guidance
|
||||
4. Add `auto-fix` label to request automated fix
|
||||
5. Add `create-pr` label to create a fix branch
|
||||
6. Mention `@copilot` for specific assistance
|
||||
|
||||
**For PRs:**
|
||||
1. Open a PR - automatically reviewed, labeled, and validated
|
||||
2. Push changes - triggers CI/CD pipeline and quality feedback
|
||||
3. Get approval + pass tests - automatically merged and branch deleted
|
||||
4. Receive continuous refactoring suggestions
|
||||
|
||||
### Working with AI Assistance
|
||||
|
||||
**In Issues & PRs:**
|
||||
- Mention `@copilot implement this` - Get implementation guidance
|
||||
- Mention `@copilot review` - Request code review
|
||||
- Mention `@copilot architecture` - Get architectural guidance
|
||||
- Mention `@copilot test` - Get testing help
|
||||
- Mention `@copilot fix this issue` - Request automated fix
|
||||
|
||||
**In Your IDE:**
|
||||
- Use GitHub Copilot extension with context from `.github/copilot-instructions.md`
|
||||
- Reference docs/getting-started/PRD.md when prompting for features
|
||||
- Follow patterns from existing packages
|
||||
- Ask about architectural decisions before implementing
|
||||
|
||||
**Automated Copilot Features:**
|
||||
- Architecture review on feature requests
|
||||
- Continuous quality feedback during development
|
||||
- Refactoring opportunity detection
|
||||
- PRD alignment checking
|
||||
- Implementation step-by-step guidance
|
||||
|
||||
## Best Practices
|
||||
|
||||
### For Development
|
||||
1. **Follow declarative-first principles** - Prefer JSON + Lua over TypeScript
|
||||
2. **Keep components under 150 LOC** - Break large files into smaller ones
|
||||
3. **Use generic renderers** - Avoid hardcoded component TSX files
|
||||
4. **Store config in database** - Use Prisma, not hardcoded values
|
||||
5. **Organize as packages** - Self-contained features with seed data
|
||||
|
||||
### For Pull Requests
|
||||
|
||||
### For Pull Requests
|
||||
1. **Write descriptive PR titles** - Used for automatic labeling
|
||||
2. **Link issues in PR descriptions** - Enables automatic issue closing
|
||||
3. **Keep PRs focused and small** - Easier to review and merge
|
||||
4. **Address all review comments** - Even warnings should be considered
|
||||
5. **Test locally before pushing** - Run lint and tests
|
||||
6. **Don't commit console.log statements** - Will be flagged in review
|
||||
7. **Remove debugger statements** - Treated as blocking issues
|
||||
8. **Review refactoring suggestions** - Continuous improvement opportunities
|
||||
|
||||
### For Issues
|
||||
1. **Use clear, descriptive titles** - Helps with automatic categorization
|
||||
2. **Provide context** - Link to docs/getting-started/PRD.md sections, mention permission levels
|
||||
3. **Consider architecture** - Is this declarative? Package-worthy? Multi-tenant?
|
||||
4. **Use labels appropriately** - Triggers relevant workflow automation
|
||||
5. **Engage with @copilot** - Get AI assistance throughout implementation
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Running Act to Find Workflow Issues
|
||||
|
||||
Use act to test workflows locally and identify issues before pushing:
|
||||
|
||||
```bash
|
||||
# Run full diagnostics
|
||||
./scripts/diagnose-workflows.sh
|
||||
|
||||
# Test specific failing job
|
||||
act -j <job-name> -v
|
||||
|
||||
# Test entire CI pipeline
|
||||
./scripts/test-workflows.sh
|
||||
```
|
||||
|
||||
**📖 Complete guide:** [ACT_TESTING.md](../../docs/ACT_TESTING.md)
|
||||
|
||||
### PR Not Auto-Merging
|
||||
- Check that all CI checks passed
|
||||
- Verify PR has approval
|
||||
- Ensure no merge conflicts
|
||||
- Confirm PR is not in draft mode
|
||||
|
||||
### Tests Failing
|
||||
- Run tests locally: `bun run test:e2e`
|
||||
- Check test report artifacts in GitHub Actions
|
||||
- Ensure dev server starts correctly
|
||||
- Test with act: `act -j test-e2e`
|
||||
|
||||
### Linting Errors
|
||||
- Run `bun run lint:fix` to auto-fix
|
||||
- Review errors: `bun run lint`
|
||||
- Check `eslint.config.js` for rule configuration
|
||||
- Test with act: `act -j lint`
|
||||
|
||||
### Build Failures
|
||||
- Test locally: `bun run build`
|
||||
- Check for TypeScript errors
|
||||
- Verify all dependencies are installed
|
||||
- Test with act: `act -j build`
|
||||
|
||||
### Prisma Issues
|
||||
- Ensure schema exists: `prisma/schema.prisma`
|
||||
- Generate client: `bunx prisma generate`
|
||||
- Run migrations: `bunx prisma migrate dev`
|
||||
- Test with act: `act -j prisma-check`
|
||||
|
||||
## Contributing
|
||||
|
||||
When adding new workflows:
|
||||
1. Document the workflow in this README
|
||||
2. Add appropriate error handling
|
||||
3. Test the workflow on a test branch
|
||||
4. Ensure proper permissions are set
|
||||
5. Add labels if needed (they'll be created automatically)
|
||||
|
||||
## Security
|
||||
|
||||
Workflows use `GITHUB_TOKEN` with minimal required permissions:
|
||||
- `contents: read/write` - For reading code and merging PRs
|
||||
- `pull-requests: write` - For commenting and managing PRs
|
||||
- `issues: write` - For managing issues
|
||||
- `checks: read` - For reading CI status
|
||||
|
||||
No secrets are required for basic functionality.
|
||||
57
.github/workflows/ci/cli.yml
vendored
Normal file
57
.github/workflows/ci/cli.yml
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
name: CLI Build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, develop ]
|
||||
paths:
|
||||
- 'frontends/cli/**'
|
||||
- '.github/workflows/ci/cli.yml'
|
||||
pull_request:
|
||||
branches: [ main, develop ]
|
||||
paths:
|
||||
- 'frontends/cli/**'
|
||||
- '.github/workflows/ci/cli.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build MetaBuilder CLI
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Install build dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y cmake ninja-build python3-pip libssl-dev
|
||||
|
||||
- name: Install Conan
|
||||
run: |
|
||||
python3 -m pip install --upgrade pip
|
||||
python3 -m pip install conan
|
||||
|
||||
- name: Detect Conan profile
|
||||
run: conan profile detect --force
|
||||
|
||||
- name: Install Conan dependencies
|
||||
run: |
|
||||
mkdir -p frontends/cli/build
|
||||
conan install frontends/cli \
|
||||
--output-folder frontends/cli/build \
|
||||
--build missing
|
||||
|
||||
- name: Configure CLI with CMake
|
||||
run: |
|
||||
cmake -S frontends/cli -B frontends/cli/build -G Ninja \
|
||||
-DCMAKE_TOOLCHAIN_FILE=frontends/cli/build/conan_toolchain.cmake
|
||||
|
||||
- name: Build CLI executable
|
||||
run: cmake --build frontends/cli/build
|
||||
|
||||
- name: Run help command to verify binary
|
||||
run: frontends/cli/build/bin/metabuilder-cli --help
|
||||
306
.github/workflows/ci/cpp-build.yml
vendored
Normal file
306
.github/workflows/ci/cpp-build.yml
vendored
Normal file
@@ -0,0 +1,306 @@
|
||||
name: C++ Build & Test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, develop ]
|
||||
paths:
|
||||
- 'dbal/production/**'
|
||||
- '.github/workflows/cpp-build.yml'
|
||||
pull_request:
|
||||
branches: [ main, develop ]
|
||||
paths:
|
||||
- 'dbal/production/**'
|
||||
- '.github/workflows/cpp-build.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
check-implementation:
|
||||
name: Check C++ Implementation Status
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
outputs:
|
||||
has_sources: ${{ steps.check.outputs.has_sources }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Check if C++ sources exist
|
||||
id: check
|
||||
run: |
|
||||
if [ -d "dbal/production/src" ] && [ "$(find dbal/production/src -name '*.cpp' | wc -l)" -gt 0 ]; then
|
||||
echo "has_sources=true" >> $GITHUB_OUTPUT
|
||||
echo "✓ C++ source files found"
|
||||
else
|
||||
echo "has_sources=false" >> $GITHUB_OUTPUT
|
||||
echo "⚠ C++ implementation not yet available - skipping build"
|
||||
fi
|
||||
|
||||
build-linux:
|
||||
name: Build on Linux
|
||||
runs-on: ubuntu-latest
|
||||
needs: check-implementation
|
||||
if: needs.check-implementation.outputs.has_sources == 'true'
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
build_type: [Release, Debug]
|
||||
compiler:
|
||||
- { cc: gcc, cxx: g++ }
|
||||
- { cc: clang, cxx: clang++ }
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install system dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y cmake ninja-build ${{ matrix.compiler.cxx }}
|
||||
pip install conan
|
||||
|
||||
- name: Setup Conan profile
|
||||
run: conan profile detect --force
|
||||
|
||||
- name: Check C++ dependencies
|
||||
run: npm run cpp:check
|
||||
|
||||
- name: Initialize Conanfile
|
||||
run: npm run cpp:init
|
||||
|
||||
- name: Install Conan dependencies
|
||||
env:
|
||||
CMAKE_BUILD_TYPE: ${{ matrix.build_type }}
|
||||
CC: ${{ matrix.compiler.cc }}
|
||||
CXX: ${{ matrix.compiler.cxx }}
|
||||
run: npm run cpp:install
|
||||
|
||||
- name: Configure CMake
|
||||
env:
|
||||
CMAKE_BUILD_TYPE: ${{ matrix.build_type }}
|
||||
CC: ${{ matrix.compiler.cc }}
|
||||
CXX: ${{ matrix.compiler.cxx }}
|
||||
run: |
|
||||
if [ "${{ matrix.build_type }}" = "Debug" ]; then
|
||||
npm run cpp:build -- configure --debug
|
||||
else
|
||||
npm run cpp:configure
|
||||
fi
|
||||
|
||||
- name: Build C++ project
|
||||
env:
|
||||
CMAKE_BUILD_TYPE: ${{ matrix.build_type }}
|
||||
run: npm run cpp:build
|
||||
|
||||
- name: Run C++ tests
|
||||
run: npm run cpp:test
|
||||
|
||||
- name: Upload build artifacts
|
||||
if: matrix.build_type == 'Release' && matrix.compiler.cxx == 'g++'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: dbal-daemon-linux
|
||||
path: |
|
||||
dbal/production/build/dbal_daemon
|
||||
dbal/production/build/*.so
|
||||
retention-days: 7
|
||||
|
||||
build-macos:
|
||||
name: Build on macOS
|
||||
runs-on: macos-latest
|
||||
needs: check-implementation
|
||||
if: needs.check-implementation.outputs.has_sources == 'true'
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
build_type: [Release, Debug]
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install system dependencies
|
||||
run: |
|
||||
brew install cmake ninja conan
|
||||
|
||||
- name: Setup Conan profile
|
||||
run: conan profile detect --force
|
||||
|
||||
- name: Check C++ dependencies
|
||||
run: npm run cpp:check
|
||||
|
||||
- name: Full C++ build
|
||||
env:
|
||||
CMAKE_BUILD_TYPE: ${{ matrix.build_type }}
|
||||
run: |
|
||||
if [ "${{ matrix.build_type }}" = "Debug" ]; then
|
||||
echo "skipping dbal/shared/tools cpp build assistant (tools/ removed)"
|
||||
else
|
||||
npm run cpp:full
|
||||
fi
|
||||
|
||||
- name: Run C++ tests
|
||||
run: npm run cpp:test
|
||||
|
||||
- name: Upload build artifacts
|
||||
if: matrix.build_type == 'Release'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: dbal-daemon-macos
|
||||
path: |
|
||||
dbal/production/build/dbal_daemon
|
||||
dbal/production/build/*.dylib
|
||||
retention-days: 7
|
||||
|
||||
build-windows:
|
||||
name: Build on Windows
|
||||
runs-on: windows-latest
|
||||
needs: check-implementation
|
||||
if: needs.check-implementation.outputs.has_sources == 'true'
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
build_type: [Release, Debug]
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install system dependencies
|
||||
run: |
|
||||
choco install cmake ninja -y
|
||||
pip install conan
|
||||
|
||||
- name: Setup Conan profile
|
||||
run: conan profile detect --force
|
||||
|
||||
- name: Check C++ dependencies
|
||||
run: npm run cpp:check
|
||||
|
||||
- name: Full C++ build
|
||||
env:
|
||||
CMAKE_BUILD_TYPE: ${{ matrix.build_type }}
|
||||
shell: bash
|
||||
run: |
|
||||
if [ "${{ matrix.build_type }}" = "Debug" ]; then
|
||||
echo "skipping dbal/shared/tools cpp build assistant (tools/ removed)"
|
||||
else
|
||||
npm run cpp:full
|
||||
fi
|
||||
|
||||
- name: Run C++ tests
|
||||
run: npm run cpp:test
|
||||
|
||||
- name: Upload build artifacts
|
||||
if: matrix.build_type == 'Release'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: dbal-daemon-windows
|
||||
path: |
|
||||
dbal/production/build/dbal_daemon.exe
|
||||
dbal/production/build/*.dll
|
||||
retention-days: 7
|
||||
|
||||
code-quality:
|
||||
name: C++ Code Quality
|
||||
runs-on: ubuntu-latest
|
||||
needs: check-implementation
|
||||
if: needs.check-implementation.outputs.has_sources == 'true'
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y cmake ninja-build cppcheck clang-format
|
||||
pip install conan
|
||||
|
||||
- name: Setup Conan
|
||||
run: conan profile detect --force
|
||||
|
||||
- name: Configure project
|
||||
run: npm run cpp:full
|
||||
|
||||
- name: Run cppcheck
|
||||
run: |
|
||||
cppcheck --enable=all --inconclusive --error-exitcode=1 \
|
||||
--suppress=missingIncludeSystem \
|
||||
-I dbal/production/include \
|
||||
dbal/production/src/
|
||||
continue-on-error: true
|
||||
|
||||
- name: Check formatting
|
||||
run: |
|
||||
find dbal/production/src dbal/production/include -name '*.cpp' -o -name '*.hpp' | \
|
||||
xargs clang-format --dry-run --Werror
|
||||
continue-on-error: true
|
||||
|
||||
integration:
|
||||
name: Integration Test
|
||||
runs-on: ubuntu-latest
|
||||
needs: [check-implementation, build-linux]
|
||||
if: needs.check-implementation.outputs.has_sources == 'true'
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm install --frozen-lockfile
|
||||
|
||||
- name: Download Linux build
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: dbal-daemon-linux
|
||||
path: dbal/production/build/
|
||||
|
||||
- name: Make daemon executable
|
||||
run: chmod +x dbal/production/build/dbal_daemon
|
||||
|
||||
- name: Run integration tests
|
||||
run: |
|
||||
# Start C++ daemon
|
||||
./dbal/production/build/dbal_daemon &
|
||||
DAEMON_PID=$!
|
||||
sleep 2
|
||||
|
||||
# Run TypeScript integration tests
|
||||
npm run test:unit
|
||||
|
||||
# Cleanup
|
||||
kill $DAEMON_PID
|
||||
continue-on-error: true
|
||||
199
.github/workflows/ci/detect-stubs.yml
vendored
Normal file
199
.github/workflows/ci/detect-stubs.yml
vendored
Normal file
@@ -0,0 +1,199 @@
|
||||
name: Stub Implementation Detection
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [ main, master, develop ]
|
||||
types: [opened, synchronize, reopened]
|
||||
push:
|
||||
branches: [ main, master, develop ]
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '0 0 * * 1' # Weekly on Monday
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
checks: write
|
||||
|
||||
jobs:
|
||||
detect-stubs:
|
||||
name: Detect Stub Implementations
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: frontends/nextjs
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
|
||||
- name: Cache npm dependencies
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
key: npm-deps-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
|
||||
path: |
|
||||
frontends/nextjs/node_modules
|
||||
~/.npm
|
||||
restore-keys: npm-deps-${{ runner.os }}-
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm install --frozen-lockfile
|
||||
|
||||
- name: Generate Prisma Client
|
||||
run: npm run db:generate
|
||||
env:
|
||||
DATABASE_URL: file:./dev.db
|
||||
|
||||
# Pattern-based stub detection
|
||||
- name: Detect stub patterns
|
||||
id: detect-patterns
|
||||
run: echo "skipping tools-based stub pattern detection (tools/ removed)" > stub-patterns.json
|
||||
continue-on-error: true
|
||||
|
||||
# Implementation completeness analysis
|
||||
- name: Analyze implementation completeness
|
||||
id: analyze-completeness
|
||||
run: echo "skipping tools-based implementation completeness analysis (tools/ removed)" > implementation-analysis.json
|
||||
continue-on-error: true
|
||||
|
||||
# Generate detailed report
|
||||
- name: Generate stub report
|
||||
id: generate-report
|
||||
run: echo "skipping tools-based stub report generation (tools/ removed)" > stub-report.md
|
||||
continue-on-error: true
|
||||
|
||||
# Check for unimplemented TODOs in changed files (PR only)
|
||||
- name: Check changed files for stubs
|
||||
if: github.event_name == 'pull_request'
|
||||
id: check-changed
|
||||
run: |
|
||||
git diff origin/${{ github.base_ref }}...HEAD -- 'src/**/*.{ts,tsx}' | \
|
||||
grep -E '^\+.*(TODO|FIXME|not implemented|stub|placeholder|mock)' | \
|
||||
tee changed-stubs.txt || true
|
||||
|
||||
STUB_COUNT=$(wc -l < changed-stubs.txt)
|
||||
echo "stub_count=$STUB_COUNT" >> $GITHUB_OUTPUT
|
||||
continue-on-error: true
|
||||
|
||||
# Post PR comment with findings
|
||||
- name: Post stub detection comment
|
||||
if: github.event_name == 'pull_request'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
|
||||
let comment = '## 🔍 Stub Implementation Detection Report\n\n';
|
||||
|
||||
try {
|
||||
const patternData = JSON.parse(fs.readFileSync('stub-patterns.json', 'utf8'));
|
||||
const completenessData = JSON.parse(fs.readFileSync('implementation-analysis.json', 'utf8'));
|
||||
|
||||
// Summary table
|
||||
comment += '### Summary\n\n';
|
||||
comment += `**Pattern-Based Stubs**: ${patternData.totalStubsFound}\n`;
|
||||
comment += `**Low Completeness Items**: ${completenessData.bySeverity.high + completenessData.bySeverity.medium}\n`;
|
||||
comment += `**Average Completeness**: ${completenessData.averageCompleteness}%\n\n`;
|
||||
|
||||
// Severity breakdown
|
||||
if (patternData.totalStubsFound > 0) {
|
||||
comment += '### Severity Breakdown (Patterns)\n\n';
|
||||
comment += `| Severity | Count |\n`;
|
||||
comment += `|----------|-------|\n`;
|
||||
comment += `| 🔴 Critical | ${patternData.bySeverity.high} |\n`;
|
||||
comment += `| 🟠 Medium | ${patternData.bySeverity.medium} |\n`;
|
||||
comment += `| 🟡 Low | ${patternData.bySeverity.low} |\n\n`;
|
||||
}
|
||||
|
||||
// Type breakdown
|
||||
if (Object.values(patternData.byType).some(v => v > 0)) {
|
||||
comment += '### Issue Types\n\n';
|
||||
for (const [type, count] of Object.entries(patternData.byType)) {
|
||||
if (count > 0) {
|
||||
comment += `- **${type}**: ${count}\n`;
|
||||
}
|
||||
}
|
||||
comment += '\n';
|
||||
}
|
||||
|
||||
// Critical issues
|
||||
if (patternData.criticalIssues && patternData.criticalIssues.length > 0) {
|
||||
comment += '### 🔴 Critical Issues Found\n\n';
|
||||
comment += '<details><summary>Click to expand</summary>\n\n';
|
||||
comment += `| File | Line | Function | Type |\n`;
|
||||
comment += `|------|------|----------|------|\n`;
|
||||
patternData.criticalIssues.slice(0, 10).forEach(issue => {
|
||||
comment += `| ${issue.file} | ${issue.line} | \`${issue.function}\` | ${issue.type} |\n`;
|
||||
});
|
||||
comment += '\n</details>\n\n';
|
||||
}
|
||||
|
||||
// Recommendations
|
||||
comment += '### 📋 Recommendations\n\n';
|
||||
comment += '- [ ] Review all critical stubs before merging\n';
|
||||
comment += '- [ ] Replace TODO comments with GitHub issues\n';
|
||||
comment += '- [ ] Implement placeholder functions before production\n';
|
||||
comment += '- [ ] Run `npm run test:check-functions` to ensure coverage\n';
|
||||
comment += '- [ ] Use type system to force implementation (avoid `any` types)\n\n';
|
||||
|
||||
// Artifacts info
|
||||
comment += '### 📁 Detailed Reports\n\n';
|
||||
comment += 'Full analysis available in artifacts:\n';
|
||||
comment += '- `stub-patterns.json` - Pattern-based detection results\n';
|
||||
comment += '- `implementation-analysis.json` - Completeness scoring\n';
|
||||
comment += '- `stub-report.md` - Detailed markdown report\n';
|
||||
} catch (e) {
|
||||
comment += '⚠️ Could not generate detailed report. Check logs for errors.\n';
|
||||
}
|
||||
|
||||
github.rest.issues.createComment({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: comment
|
||||
});
|
||||
|
||||
# Upload detailed reports
|
||||
- name: Upload stub detection reports
|
||||
uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: stub-detection-reports
|
||||
path: |
|
||||
stub-patterns.json
|
||||
implementation-analysis.json
|
||||
stub-report.md
|
||||
changed-stubs.txt
|
||||
retention-days: 30
|
||||
|
||||
# Create check run with summary
|
||||
- name: Create check run
|
||||
uses: actions/github-script@v7
|
||||
if: always()
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
|
||||
let summary = '';
|
||||
try {
|
||||
const data = JSON.parse(fs.readFileSync('stub-patterns.json', 'utf8'));
|
||||
summary = `Found ${data.totalStubsFound} stub implementations (${data.bySeverity.high} high severity)`;
|
||||
} catch (e) {
|
||||
summary = 'Stub detection completed. See artifacts for details.';
|
||||
}
|
||||
|
||||
github.rest.checks.create({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
name: 'Stub Implementation Detection',
|
||||
head_sha: context.sha,
|
||||
status: 'completed',
|
||||
conclusion: 'neutral',
|
||||
summary: summary
|
||||
});
|
||||
169
.github/workflows/dbal-tests.yml
vendored
169
.github/workflows/dbal-tests.yml
vendored
@@ -1,169 +0,0 @@
|
||||
name: DBAL Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- 'dbal/**'
|
||||
- '.github/workflows/dbal-tests.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'dbal/**'
|
||||
|
||||
jobs:
|
||||
# ── Unit + security tests (no DB, no containers) ────────────────────────────
|
||||
unit-tests:
|
||||
name: Unit & Security Tests
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Install system deps
|
||||
run: |
|
||||
sudo apt-get update -qq
|
||||
sudo apt-get install -y --no-install-recommends \
|
||||
build-essential cmake ninja-build python3-pip \
|
||||
libpq-dev libmysqlclient-dev
|
||||
|
||||
- name: Install Conan
|
||||
run: pip3 install conan
|
||||
|
||||
- name: Detect Conan profile
|
||||
run: conan profile detect --force
|
||||
|
||||
- name: Cache Conan packages
|
||||
uses: actions/cache@v6
|
||||
with:
|
||||
path: ~/.conan2/p
|
||||
key: conan-unit-${{ hashFiles('dbal/production/build-config/conanfile.tests.py') }}
|
||||
restore-keys: conan-unit-
|
||||
|
||||
- name: Install C++ test dependencies
|
||||
working-directory: dbal/production
|
||||
run: |
|
||||
mkdir -p _build && cd _build
|
||||
conan install ../build-config/conanfile.tests.py \
|
||||
--output-folder=. \
|
||||
--build=missing \
|
||||
-s build_type=Release \
|
||||
-s compiler.cppstd=20
|
||||
|
||||
- name: Configure CMake
|
||||
working-directory: dbal/production/_build
|
||||
run: |
|
||||
cmake .. \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_TOOLCHAIN_FILE=./build/Release/generators/conan_toolchain.cmake \
|
||||
-DBUILD_DAEMON=OFF \
|
||||
-DBUILD_TESTING=ON \
|
||||
-G Ninja
|
||||
|
||||
- name: Build
|
||||
working-directory: dbal/production/_build
|
||||
run: cmake --build . --target dbal_unit_tests --parallel
|
||||
|
||||
- name: Test
|
||||
working-directory: dbal/production/_build
|
||||
run: ctest -R dbal_unit_tests --output-on-failure
|
||||
|
||||
- name: Upload results
|
||||
uses: actions/upload-artifact@v6
|
||||
if: always()
|
||||
with:
|
||||
name: unit-test-results
|
||||
path: dbal/production/_build/test_results.xml
|
||||
|
||||
# ── Integration tests — containers managed by testcontainers-sidecar ────────
|
||||
# Docker is available by default on ubuntu-latest (no services: block needed).
|
||||
# testcontainers-go (via the sidecar) starts postgres/mysql containers itself,
|
||||
# and Ryuk cleans them up after the test binary exits.
|
||||
integration-tests:
|
||||
name: Integration Tests (SQLite + PostgreSQL + MySQL via testcontainers)
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Install Go (for testcontainers-sidecar)
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.21'
|
||||
|
||||
- name: Install system deps
|
||||
run: |
|
||||
sudo apt-get update -qq
|
||||
sudo apt-get install -y --no-install-recommends \
|
||||
build-essential cmake ninja-build python3-pip \
|
||||
libpq-dev libmysqlclient-dev
|
||||
|
||||
- name: Install Conan
|
||||
run: pip3 install conan
|
||||
|
||||
- name: Detect Conan profile
|
||||
run: conan profile detect --force
|
||||
|
||||
- name: Configure Nexus as primary Conan remote
|
||||
run: |
|
||||
conan remote add nexus "${{ secrets.NEXUS_URL }}" --force
|
||||
conan remote login nexus "${{ secrets.NEXUS_USER }}" \
|
||||
--password "${{ secrets.NEXUS_PASS }}"
|
||||
# Nexus first (has testcontainers-sidecar), Conan Center as fallback
|
||||
conan remote update nexus --index 0
|
||||
# If NEXUS_URL secret is not set, fall back to building sidecar from source
|
||||
continue-on-error: true
|
||||
|
||||
- name: Build testcontainers-sidecar from source (fallback if no Nexus)
|
||||
if: env.NEXUS_URL == ''
|
||||
env:
|
||||
NEXUS_URL: ${{ secrets.NEXUS_URL }}
|
||||
TESTCONTAINERS_SIDECAR_SRC: ${{ github.workspace }}/dbal/testcontainers-sidecar
|
||||
run: |
|
||||
# Build and register in the local Conan cache so conan install succeeds below.
|
||||
TESTCONTAINERS_SIDECAR_SRC="$TESTCONTAINERS_SIDECAR_SRC" \
|
||||
conan create dbal/production/build-config/conan-recipes/testcontainers-sidecar \
|
||||
-s build_type=Release -s compiler.cppstd=20
|
||||
|
||||
- name: Cache Conan packages
|
||||
uses: actions/cache@v6
|
||||
with:
|
||||
path: ~/.conan2/p
|
||||
key: conan-integration-${{ hashFiles('dbal/production/build-config/conanfile.tests.py') }}
|
||||
restore-keys: conan-integration-
|
||||
|
||||
- name: Install C++ test dependencies (with sidecar from Nexus)
|
||||
working-directory: dbal/production
|
||||
run: |
|
||||
mkdir -p _build && cd _build
|
||||
conan install ../build-config/conanfile.tests.py \
|
||||
--output-folder=. \
|
||||
--build=missing \
|
||||
-s build_type=Release \
|
||||
-s compiler.cppstd=20
|
||||
continue-on-error: true
|
||||
|
||||
- name: Configure CMake
|
||||
working-directory: dbal/production/_build
|
||||
run: |
|
||||
cmake .. \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_TOOLCHAIN_FILE=./build/Release/generators/conan_toolchain.cmake \
|
||||
-DBUILD_DAEMON=OFF \
|
||||
-DBUILD_INTEGRATION_TESTS=ON \
|
||||
-G Ninja
|
||||
|
||||
- name: Build
|
||||
working-directory: dbal/production/_build
|
||||
run: cmake --build . --target dbal_integration_tests --parallel
|
||||
|
||||
- name: Run integration tests
|
||||
working-directory: dbal/production/_build
|
||||
# Docker socket is available by default on ubuntu-latest.
|
||||
# testcontainers-go will start postgres and mysql containers automatically.
|
||||
run: ctest -R dbal_integration_tests --output-on-failure -V
|
||||
|
||||
- name: Upload results
|
||||
uses: actions/upload-artifact@v6
|
||||
if: always()
|
||||
with:
|
||||
name: integration-test-results
|
||||
path: dbal/production/_build/integration_results.xml
|
||||
360
.github/workflows/development.yml
vendored
Normal file
360
.github/workflows/development.yml
vendored
Normal file
@@ -0,0 +1,360 @@
|
||||
name: Development Assistance
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, ready_for_review]
|
||||
issue_comment:
|
||||
types: [created]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
code-quality-feedback:
|
||||
name: Continuous Quality Feedback
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
github.event_name == 'pull_request' && !github.event.pull_request.draft
|
||||
defaults:
|
||||
run:
|
||||
working-directory: frontends/nextjs
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Analyze code metrics (no redundant checks)
|
||||
id: quality
|
||||
run: |
|
||||
# Note: Lint/build/tests are handled by gated-ci.yml
|
||||
# This job only collects metrics for architectural feedback
|
||||
|
||||
# Count TypeScript files and their sizes
|
||||
TOTAL_TS_FILES=$(find src -name "*.ts" -o -name "*.tsx" 2>/dev/null | wc -l)
|
||||
LARGE_FILES=$(find src -name "*.ts" -o -name "*.tsx" -exec wc -l {} \; 2>/dev/null | awk '$1 > 150 {print $2}' | wc -l)
|
||||
|
||||
echo "total_ts_files=$TOTAL_TS_FILES" >> $GITHUB_OUTPUT
|
||||
echo "large_files=$LARGE_FILES" >> $GITHUB_OUTPUT
|
||||
|
||||
# Check for declarative vs imperative balance
|
||||
JSON_FILES=$(find src packages -name "*.json" 2>/dev/null | wc -l)
|
||||
LUA_SCRIPTS=$(find src packages -name "*.lua" 2>/dev/null | wc -l)
|
||||
|
||||
echo "json_files=$JSON_FILES" >> $GITHUB_OUTPUT
|
||||
echo "lua_scripts=$LUA_SCRIPTS" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Check architectural compliance
|
||||
id: architecture
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
let issues = [];
|
||||
let suggestions = [];
|
||||
|
||||
// Get changed files
|
||||
let changedFiles = [];
|
||||
if (context.eventName === 'pull_request') {
|
||||
const { data: files } = await github.rest.pulls.listFiles({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: context.issue.number,
|
||||
});
|
||||
changedFiles = files.map(f => f.filename);
|
||||
}
|
||||
|
||||
// Check for hardcoded components outside ui/
|
||||
const hardcodedComponents = changedFiles.filter(f =>
|
||||
f.endsWith('.tsx') &&
|
||||
f.includes('src/components/') &&
|
||||
!f.includes('src/components/ui/') &&
|
||||
!f.includes('src/components/shared/') &&
|
||||
!['RenderComponent', 'FieldRenderer', 'GenericPage'].some(g => f.includes(g))
|
||||
);
|
||||
|
||||
if (hardcodedComponents.length > 0) {
|
||||
suggestions.push(`Consider if these components could be declarative: ${hardcodedComponents.join(', ')}`);
|
||||
}
|
||||
|
||||
// Check for database changes without seed data
|
||||
const schemaChanged = changedFiles.some(f => f.includes('schema.prisma'));
|
||||
const seedChanged = changedFiles.some(f => f.includes('seed'));
|
||||
|
||||
if (schemaChanged && !seedChanged) {
|
||||
suggestions.push('Database schema changed but no seed data updates detected. Consider updating seed data.');
|
||||
}
|
||||
|
||||
// Check for new routes without PageRoutes table updates
|
||||
const routeFiles = changedFiles.filter(f => f.includes('Route') || f.includes('route'));
|
||||
if (routeFiles.length > 0) {
|
||||
suggestions.push('Route changes detected. Ensure PageRoutes table is updated for dynamic routing.');
|
||||
}
|
||||
|
||||
// Check for large TypeScript files
|
||||
const largeFiles = parseInt('${{ steps.quality.outputs.large_files }}');
|
||||
if (largeFiles > 0) {
|
||||
issues.push(`${largeFiles} TypeScript files exceed 150 lines. Consider breaking them into smaller components.`);
|
||||
}
|
||||
|
||||
return { issues, suggestions };
|
||||
|
||||
- name: Provide development feedback
|
||||
if: github.event_name == 'pull_request'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const analysis = JSON.parse('${{ steps.architecture.outputs.result }}');
|
||||
const totalFiles = parseInt('${{ steps.quality.outputs.total_ts_files }}');
|
||||
const largeFiles = parseInt('${{ steps.quality.outputs.large_files }}');
|
||||
const jsonFiles = parseInt('${{ steps.quality.outputs.json_files }}');
|
||||
const luaScripts = parseInt('${{ steps.quality.outputs.lua_scripts }}');
|
||||
|
||||
let comment = `## 💻 Development Quality Feedback\n\n`;
|
||||
|
||||
comment += `### 📊 Code Metrics\n\n`;
|
||||
comment += `- TypeScript files: ${totalFiles}\n`;
|
||||
comment += `- Files >150 LOC: ${largeFiles} ${largeFiles > 0 ? '⚠️' : '✅'}\n`;
|
||||
comment += `- JSON config files: ${jsonFiles}\n`;
|
||||
comment += `- Lua scripts: ${luaScripts}\n`;
|
||||
comment += `- Declarative ratio: ${((jsonFiles + luaScripts) / Math.max(totalFiles, 1) * 100).toFixed(1)}%\n\n`;
|
||||
|
||||
if (analysis.issues.length > 0) {
|
||||
comment += `### ⚠️ Architectural Issues\n\n`;
|
||||
analysis.issues.forEach(issue => comment += `- ${issue}\n`);
|
||||
comment += '\n';
|
||||
}
|
||||
|
||||
if (analysis.suggestions.length > 0) {
|
||||
comment += `### 💡 Suggestions\n\n`;
|
||||
analysis.suggestions.forEach(suggestion => comment += `- ${suggestion}\n`);
|
||||
comment += '\n';
|
||||
}
|
||||
|
||||
comment += `### 🎯 Project Goals Reminder\n\n`;
|
||||
comment += `- **Declarative First:** Prefer JSON + Lua over TypeScript\n`;
|
||||
comment += `- **Component Size:** Keep files under 150 LOC\n`;
|
||||
comment += `- **Generic Renderers:** Use RenderComponent for dynamic components\n`;
|
||||
comment += `- **Database-Driven:** Store configuration in database, not code\n`;
|
||||
comment += `- **Package-Based:** Organize features as importable packages\n\n`;
|
||||
|
||||
comment += `**@copilot** can help refactor code to better align with these principles.\n\n`;
|
||||
comment += `📖 See [Architecture Guidelines](/.github/copilot-instructions.md)`;
|
||||
|
||||
// Check if we already commented
|
||||
const { data: comments } = await github.rest.issues.listComments({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
});
|
||||
|
||||
const botComment = comments.find(c =>
|
||||
c.user.type === 'Bot' && c.body.includes('Development Quality Feedback')
|
||||
);
|
||||
|
||||
if (botComment) {
|
||||
await github.rest.issues.updateComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
comment_id: botComment.id,
|
||||
body: comment
|
||||
});
|
||||
} else {
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
body: comment
|
||||
});
|
||||
}
|
||||
|
||||
copilot-interaction:
|
||||
name: Handle Copilot Mentions
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
github.event_name == 'issue_comment' &&
|
||||
contains(github.event.comment.body, '@copilot')
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Parse Copilot request
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const comment = context.payload.comment.body.toLowerCase();
|
||||
const issue = context.payload.issue;
|
||||
|
||||
let response = `## 🤖 Copilot Assistance\n\n`;
|
||||
|
||||
// Determine what the user is asking for
|
||||
if (comment.includes('implement') || comment.includes('fix this')) {
|
||||
response += `To implement this with Copilot assistance:\n\n`;
|
||||
response += `1. **Create a branch:** \`git checkout -b feature/issue-${issue.number}\`\n`;
|
||||
response += `2. **Use Copilot in your IDE** to generate code with context from:\n`;
|
||||
response += ` - [Copilot Instructions](/.github/copilot-instructions.md)\n`;
|
||||
response += ` - [PRD.md](/PRD.md)\n`;
|
||||
response += ` - Existing package structure in \`/packages/\`\n`;
|
||||
response += `3. **Follow the architectural principles:**\n`;
|
||||
response += ` - Declarative over imperative\n`;
|
||||
response += ` - Database-driven configuration\n`;
|
||||
response += ` - Generic renderers vs hardcoded components\n`;
|
||||
response += `4. **Test your changes:** \`npm run lint && npm run test:e2e\`\n`;
|
||||
response += `5. **Create a PR** - The automated workflows will review it\n\n`;
|
||||
}
|
||||
|
||||
if (comment.includes('review') || comment.includes('check')) {
|
||||
response += `Copilot can review this through:\n\n`;
|
||||
response += `- **Automated Code Review** workflow (runs on PRs)\n`;
|
||||
response += `- **Development Assistance** workflow (runs on pushes)\n`;
|
||||
response += `- **Planning & Design** workflow (runs on feature requests)\n\n`;
|
||||
response += `Create a PR to trigger comprehensive review!\n\n`;
|
||||
}
|
||||
|
||||
if (comment.includes('architecture') || comment.includes('design')) {
|
||||
response += `### 🏗️ Architectural Guidance\n\n`;
|
||||
response += `MetaBuilder follows these principles:\n\n`;
|
||||
response += `1. **5-Level Architecture:** User → Admin → God → SuperGod levels\n`;
|
||||
response += `2. **Multi-Tenant:** Isolated tenant instances with independent configs\n`;
|
||||
response += `3. **Declarative Components:** JSON config + Lua scripts, not TSX\n`;
|
||||
response += `4. **Package System:** Self-contained, importable feature bundles\n`;
|
||||
response += `5. **Database-First:** All config in Prisma, not hardcoded\n\n`;
|
||||
response += `📖 Full details: [PRD.md](/PRD.md)\n\n`;
|
||||
}
|
||||
|
||||
if (comment.includes('test') || comment.includes('e2e')) {
|
||||
response += `### 🧪 Testing with Copilot\n\n`;
|
||||
response += `\`\`\`bash\n`;
|
||||
response += `# Run E2E tests\n`;
|
||||
response += `npm run test:e2e\n\n`;
|
||||
response += `# Run with UI\n`;
|
||||
response += `npm run test:e2e:ui\n\n`;
|
||||
response += `# Run linter\n`;
|
||||
response += `npm run lint\n`;
|
||||
response += `\`\`\`\n\n`;
|
||||
response += `Use Copilot in your IDE to:\n`;
|
||||
response += `- Generate test cases based on user stories\n`;
|
||||
response += `- Write Playwright selectors and assertions\n`;
|
||||
response += `- Create mock data for tests\n\n`;
|
||||
}
|
||||
|
||||
if (comment.includes('help') || (!comment.includes('implement') && !comment.includes('review') && !comment.includes('architecture') && !comment.includes('test'))) {
|
||||
response += `### 🆘 How to Use Copilot\n\n`;
|
||||
response += `Mention **@copilot** in comments with:\n\n`;
|
||||
response += `- \`@copilot implement this\` - Get implementation guidance\n`;
|
||||
response += `- \`@copilot review this\` - Request code review\n`;
|
||||
response += `- \`@copilot architecture\` - Get architectural guidance\n`;
|
||||
response += `- \`@copilot test this\` - Get testing guidance\n`;
|
||||
response += `- \`@copilot fix this issue\` - Request automated fix\n\n`;
|
||||
response += `**In your IDE:**\n`;
|
||||
response += `- Use GitHub Copilot with context from [Copilot Instructions](/.github/copilot-instructions.md)\n`;
|
||||
response += `- Reference the [PRD](/PRD.md) when prompting\n`;
|
||||
response += `- Follow patterns from existing packages in \`/packages/\`\n\n`;
|
||||
}
|
||||
|
||||
response += `---\n`;
|
||||
response += `*This is an automated response. For detailed Copilot assistance, use the extension in your IDE with project context.*`;
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue.number,
|
||||
body: response
|
||||
});
|
||||
|
||||
suggest-refactoring:
|
||||
name: Suggest Refactoring Opportunities
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'pull_request' && !github.event.pull_request.draft
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Analyze refactoring opportunities
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const { data: files } = await github.rest.pulls.listFiles({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: context.issue.number,
|
||||
});
|
||||
|
||||
let opportunities = [];
|
||||
|
||||
// Look for opportunities in changed files
|
||||
for (const file of files) {
|
||||
const patch = file.patch || '';
|
||||
|
||||
// Check for repeated code patterns
|
||||
if (patch.split('\n').length > 100) {
|
||||
opportunities.push({
|
||||
file: file.filename,
|
||||
type: 'Size',
|
||||
suggestion: 'Large changeset - consider breaking into smaller PRs or extracting common utilities'
|
||||
});
|
||||
}
|
||||
|
||||
// Check for hardcoded values
|
||||
if (patch.match(/['"][A-Z_]{3,}['"]\s*:/)) {
|
||||
opportunities.push({
|
||||
file: file.filename,
|
||||
type: 'Configuration',
|
||||
suggestion: 'Hardcoded constants detected - consider moving to database configuration'
|
||||
});
|
||||
}
|
||||
|
||||
// Check for new TSX components
|
||||
if (file.filename.includes('components/') && file.filename.endsWith('.tsx') && file.status === 'added') {
|
||||
opportunities.push({
|
||||
file: file.filename,
|
||||
type: 'Architecture',
|
||||
suggestion: 'New component added - could this be implemented declaratively with JSON + Lua?'
|
||||
});
|
||||
}
|
||||
|
||||
// Check for inline styles or complex class strings
|
||||
if (patch.includes('style={{') || patch.match(/className="[^"]{50,}"/)) {
|
||||
opportunities.push({
|
||||
file: file.filename,
|
||||
type: 'Styling',
|
||||
suggestion: 'Complex styling detected - consider extracting to theme configuration'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (opportunities.length > 0) {
|
||||
let comment = `## 🔄 Refactoring Opportunities\n\n`;
|
||||
comment += `**@copilot** identified potential improvements:\n\n`;
|
||||
|
||||
const grouped = {};
|
||||
opportunities.forEach(opp => {
|
||||
if (!grouped[opp.type]) grouped[opp.type] = [];
|
||||
grouped[opp.type].push(opp);
|
||||
});
|
||||
|
||||
for (const [type, opps] of Object.entries(grouped)) {
|
||||
comment += `### ${type}\n\n`;
|
||||
opps.forEach(opp => {
|
||||
comment += `- **${opp.file}**: ${opp.suggestion}\n`;
|
||||
});
|
||||
comment += '\n';
|
||||
}
|
||||
|
||||
comment += `---\n`;
|
||||
comment += `These are suggestions, not requirements. Consider them as part of continuous improvement.\n\n`;
|
||||
comment += `Use **@copilot** in your IDE to help implement these refactorings.`;
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
body: comment
|
||||
});
|
||||
}
|
||||
1033
.github/workflows/gated-ci-atomic.yml
vendored
Normal file
1033
.github/workflows/gated-ci-atomic.yml
vendored
Normal file
File diff suppressed because it is too large
Load Diff
610
.github/workflows/gated-ci.yml
vendored
Normal file
610
.github/workflows/gated-ci.yml
vendored
Normal file
@@ -0,0 +1,610 @@
|
||||
name: Enterprise Gated CI/CD Pipeline
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, master, develop ]
|
||||
pull_request:
|
||||
branches: [ main, master, develop ]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
checks: write
|
||||
statuses: write
|
||||
|
||||
# Enterprise Gated Tree Workflow
|
||||
# Changes must pass through 5 gates before merge:
|
||||
# Gate 1: Code Quality (lint, typecheck, security)
|
||||
# Gate 2: Testing (unit, E2E)
|
||||
# Gate 3: Build & Package
|
||||
# Gate 4: Review & Approval
|
||||
# Gate 5: Deployment (staging → production with manual approval)
|
||||
|
||||
jobs:
|
||||
# ============================================================================
|
||||
# GATE 1: Code Quality Gates
|
||||
# ============================================================================
|
||||
|
||||
gate-1-start:
|
||||
name: "Gate 1: Code Quality - Starting"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Gate 1 checkpoint
|
||||
run: |
|
||||
echo "🚦 GATE 1: CODE QUALITY VALIDATION"
|
||||
echo "================================================"
|
||||
echo "Running: Prisma validation, TypeScript check, Linting, Security scan"
|
||||
echo "Status: IN PROGRESS"
|
||||
|
||||
prisma-check:
|
||||
name: "Gate 1.1: Validate Prisma Schema"
|
||||
runs-on: ubuntu-latest
|
||||
needs: gate-1-start
|
||||
defaults:
|
||||
run:
|
||||
working-directory: frontends/nextjs
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||
with:
|
||||
node-version: '20'
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm install
|
||||
|
||||
- name: Generate Prisma Client
|
||||
run: npm run db:generate
|
||||
env:
|
||||
DATABASE_URL: file:./dev.db
|
||||
|
||||
- name: Validate Prisma Schema
|
||||
run: npx prisma validate --schema=../../prisma/schema.prisma
|
||||
env:
|
||||
DATABASE_URL: file:./dev.db
|
||||
|
||||
typecheck:
|
||||
name: "Gate 1.2: TypeScript Type Check"
|
||||
runs-on: ubuntu-latest
|
||||
needs: prisma-check
|
||||
defaults:
|
||||
run:
|
||||
working-directory: frontends/nextjs
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||
with:
|
||||
node-version: '20'
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm install
|
||||
|
||||
- name: Generate Prisma Client
|
||||
run: npm run db:generate
|
||||
env:
|
||||
DATABASE_URL: file:./dev.db
|
||||
|
||||
- name: Run TypeScript type check
|
||||
run: npm run typecheck
|
||||
|
||||
lint:
|
||||
name: "Gate 1.3: Lint Code"
|
||||
runs-on: ubuntu-latest
|
||||
needs: prisma-check
|
||||
defaults:
|
||||
run:
|
||||
working-directory: frontends/nextjs
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||
with:
|
||||
node-version: '20'
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm install
|
||||
|
||||
- name: Generate Prisma Client
|
||||
run: npm run db:generate
|
||||
env:
|
||||
DATABASE_URL: file:./dev.db
|
||||
|
||||
- name: Run ESLint
|
||||
run: npm run lint
|
||||
|
||||
security-scan:
|
||||
name: "Gate 1.4: Security Scan"
|
||||
runs-on: ubuntu-latest
|
||||
needs: prisma-check
|
||||
defaults:
|
||||
run:
|
||||
working-directory: frontends/nextjs
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm install
|
||||
|
||||
- name: Run security audit
|
||||
run: npm audit --audit-level=moderate
|
||||
continue-on-error: true
|
||||
|
||||
- name: Check for vulnerable dependencies
|
||||
run: |
|
||||
echo "Checking for known vulnerabilities..."
|
||||
npm audit --json > audit-results.json 2>&1 || true
|
||||
if [ -f audit-results.json ]; then
|
||||
echo "Security audit completed"
|
||||
fi
|
||||
|
||||
gate-1-complete:
|
||||
name: "Gate 1: Code Quality - Passed ✅"
|
||||
runs-on: ubuntu-latest
|
||||
needs: [prisma-check, typecheck, lint, security-scan]
|
||||
steps:
|
||||
- name: Gate 1 passed
|
||||
run: |
|
||||
echo "✅ GATE 1 PASSED: CODE QUALITY"
|
||||
echo "================================================"
|
||||
echo "✓ Prisma schema validated"
|
||||
echo "✓ TypeScript types checked"
|
||||
echo "✓ Code linted"
|
||||
echo "✓ Security scan completed"
|
||||
echo ""
|
||||
echo "Proceeding to Gate 2: Testing..."
|
||||
|
||||
# ============================================================================
|
||||
# GATE 2: Testing Gates
|
||||
# ============================================================================
|
||||
|
||||
gate-2-start:
|
||||
name: "Gate 2: Testing - Starting"
|
||||
runs-on: ubuntu-latest
|
||||
needs: gate-1-complete
|
||||
steps:
|
||||
- name: Gate 2 checkpoint
|
||||
run: |
|
||||
echo "🚦 GATE 2: TESTING VALIDATION"
|
||||
echo "================================================"
|
||||
echo "Running: Unit tests, E2E tests, DBAL daemon tests"
|
||||
echo "Status: IN PROGRESS"
|
||||
|
||||
test-unit:
|
||||
name: "Gate 2.1: Unit Tests"
|
||||
runs-on: ubuntu-latest
|
||||
needs: gate-2-start
|
||||
defaults:
|
||||
run:
|
||||
working-directory: frontends/nextjs
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||
with:
|
||||
node-version: '20'
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm install
|
||||
|
||||
- name: Generate Prisma Client
|
||||
run: npm run db:generate
|
||||
env:
|
||||
DATABASE_URL: file:./dev.db
|
||||
|
||||
- name: Run unit tests
|
||||
run: npm run test:unit
|
||||
env:
|
||||
DATABASE_URL: file:./dev.db
|
||||
|
||||
- name: Upload coverage report
|
||||
if: always()
|
||||
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
|
||||
with:
|
||||
name: coverage-report
|
||||
path: frontends/nextjs/coverage/
|
||||
retention-days: 7
|
||||
|
||||
test-e2e:
|
||||
name: "Gate 2.2: E2E Tests"
|
||||
runs-on: ubuntu-latest
|
||||
needs: gate-2-start
|
||||
defaults:
|
||||
run:
|
||||
working-directory: frontends/nextjs
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||
with:
|
||||
node-version: '20'
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm install
|
||||
|
||||
- name: Generate Prisma Client
|
||||
run: npm run db:generate
|
||||
env:
|
||||
DATABASE_URL: file:./dev.db
|
||||
|
||||
- name: Install Playwright Browsers
|
||||
run: npx playwright install --with-deps chromium
|
||||
|
||||
- name: Run Playwright tests
|
||||
run: npm run test:e2e
|
||||
env:
|
||||
DATABASE_URL: file:./dev.db
|
||||
|
||||
- name: Upload test results
|
||||
if: always()
|
||||
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
|
||||
with:
|
||||
name: playwright-report
|
||||
path: frontends/nextjs/playwright-report/
|
||||
retention-days: 7
|
||||
|
||||
test-dbal-daemon:
|
||||
name: "Gate 2.3: DBAL Daemon E2E"
|
||||
runs-on: ubuntu-latest
|
||||
needs: gate-2-start
|
||||
defaults:
|
||||
run:
|
||||
working-directory: frontends/nextjs
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||
with:
|
||||
node-version: '20'
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm install
|
||||
|
||||
- name: Generate Prisma Client
|
||||
run: npm run db:generate
|
||||
env:
|
||||
DATABASE_URL: file:./dev.db
|
||||
|
||||
- name: Install Playwright Browsers
|
||||
run: npx playwright install --with-deps chromium
|
||||
|
||||
- name: Run DBAL daemon suite
|
||||
run: npm run test:e2e:dbal-daemon
|
||||
env:
|
||||
DATABASE_URL: file:./dev.db
|
||||
|
||||
- name: Upload daemon test report
|
||||
if: always()
|
||||
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
|
||||
with:
|
||||
name: playwright-report-dbal-daemon
|
||||
path: frontends/nextjs/playwright-report/
|
||||
retention-days: 7
|
||||
|
||||
gate-2-complete:
|
||||
name: "Gate 2: Testing - Passed ✅"
|
||||
runs-on: ubuntu-latest
|
||||
needs: [test-unit, test-e2e, test-dbal-daemon]
|
||||
steps:
|
||||
- name: Gate 2 passed
|
||||
run: |
|
||||
echo "✅ GATE 2 PASSED: TESTING"
|
||||
echo "================================================"
|
||||
echo "✓ Unit tests passed"
|
||||
echo "✓ E2E tests passed"
|
||||
echo "✓ DBAL daemon tests passed"
|
||||
echo ""
|
||||
echo "Proceeding to Gate 3: Build & Package..."
|
||||
|
||||
# ============================================================================
|
||||
# GATE 3: Build & Package Gates
|
||||
# ============================================================================
|
||||
|
||||
gate-3-start:
|
||||
name: "Gate 3: Build & Package - Starting"
|
||||
runs-on: ubuntu-latest
|
||||
needs: gate-2-complete
|
||||
steps:
|
||||
- name: Gate 3 checkpoint
|
||||
run: |
|
||||
echo "🚦 GATE 3: BUILD & PACKAGE VALIDATION"
|
||||
echo "================================================"
|
||||
echo "Running: Application build, artifact packaging"
|
||||
echo "Status: IN PROGRESS"
|
||||
|
||||
build:
|
||||
name: "Gate 3.1: Build Application"
|
||||
runs-on: ubuntu-latest
|
||||
needs: gate-3-start
|
||||
defaults:
|
||||
run:
|
||||
working-directory: frontends/nextjs
|
||||
outputs:
|
||||
build-success: ${{ steps.build-step.outcome }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||
with:
|
||||
node-version: '20'
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm install
|
||||
|
||||
- name: Generate Prisma Client
|
||||
run: npm run db:generate
|
||||
env:
|
||||
DATABASE_URL: file:./dev.db
|
||||
|
||||
- name: Build
|
||||
id: build-step
|
||||
run: npm run build
|
||||
env:
|
||||
DATABASE_URL: file:./dev.db
|
||||
|
||||
- name: Upload build artifacts
|
||||
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
|
||||
with:
|
||||
name: dist
|
||||
path: frontends/nextjs/.next/
|
||||
retention-days: 7
|
||||
|
||||
quality-check:
|
||||
name: "Gate 3.2: Code Quality Metrics"
|
||||
runs-on: ubuntu-latest
|
||||
needs: gate-3-start
|
||||
if: github.event_name == 'pull_request'
|
||||
defaults:
|
||||
run:
|
||||
working-directory: frontends/nextjs
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||
with:
|
||||
node-version: '20'
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm install
|
||||
|
||||
- name: Generate Prisma Client
|
||||
run: npm run db:generate
|
||||
env:
|
||||
DATABASE_URL: file:./dev.db
|
||||
|
||||
- name: Check for console.log statements
|
||||
run: |
|
||||
if git diff origin/${{ github.base_ref }}...HEAD -- '*.ts' '*.tsx' '*.js' '*.jsx' | grep -E '^\+.*console\.(log|debug|info)'; then
|
||||
echo "⚠️ Found console.log statements in the changes"
|
||||
echo "Please remove console.log statements before merging"
|
||||
exit 1
|
||||
fi
|
||||
continue-on-error: true
|
||||
|
||||
- name: Check for TODO comments
|
||||
run: |
|
||||
TODO_COUNT=$(git diff origin/${{ github.base_ref }}...HEAD -- '*.ts' '*.tsx' '*.js' '*.jsx' | grep -E '^\+.*TODO|FIXME' | wc -l)
|
||||
if [ $TODO_COUNT -gt 0 ]; then
|
||||
echo "⚠️ Found $TODO_COUNT TODO/FIXME comments in the changes"
|
||||
echo "Please address TODO comments before merging or create issues for them"
|
||||
fi
|
||||
continue-on-error: true
|
||||
|
||||
gate-3-complete:
|
||||
name: "Gate 3: Build & Package - Passed ✅"
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build, quality-check]
|
||||
if: always() && needs.build.result == 'success' && (needs.quality-check.result == 'success' || needs.quality-check.result == 'skipped')
|
||||
steps:
|
||||
- name: Gate 3 passed
|
||||
run: |
|
||||
echo "✅ GATE 3 PASSED: BUILD & PACKAGE"
|
||||
echo "================================================"
|
||||
echo "✓ Application built successfully"
|
||||
echo "✓ Build artifacts packaged"
|
||||
echo "✓ Quality metrics validated"
|
||||
echo ""
|
||||
echo "Proceeding to Gate 4: Review & Approval..."
|
||||
|
||||
# ============================================================================
|
||||
# GATE 4: Review & Approval Gate (PR only)
|
||||
# ============================================================================
|
||||
|
||||
gate-4-review-required:
|
||||
name: "Gate 4: Review & Approval Required"
|
||||
runs-on: ubuntu-latest
|
||||
needs: gate-3-complete
|
||||
if: github.event_name == 'pull_request'
|
||||
steps:
|
||||
- name: Check PR approval status
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const { data: reviews } = await github.rest.pulls.listReviews({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: context.issue.number
|
||||
});
|
||||
|
||||
const latestReviews = {};
|
||||
for (const review of reviews) {
|
||||
latestReviews[review.user.login] = review.state;
|
||||
}
|
||||
|
||||
const hasApproval = Object.values(latestReviews).includes('APPROVED');
|
||||
const hasRequestChanges = Object.values(latestReviews).includes('CHANGES_REQUESTED');
|
||||
|
||||
console.log('Review Status:');
|
||||
console.log('==============');
|
||||
console.log('Approvals:', Object.values(latestReviews).filter(s => s === 'APPROVED').length);
|
||||
console.log('Change Requests:', Object.values(latestReviews).filter(s => s === 'CHANGES_REQUESTED').length);
|
||||
|
||||
if (hasRequestChanges) {
|
||||
core.setFailed('❌ Changes requested - PR cannot proceed to deployment');
|
||||
} else if (!hasApproval) {
|
||||
core.notice('⏳ PR approval required before merge - this gate will pass when approved');
|
||||
} else {
|
||||
console.log('✅ PR approved - gate passed');
|
||||
}
|
||||
|
||||
gate-4-complete:
|
||||
name: "Gate 4: Review & Approval - Status"
|
||||
runs-on: ubuntu-latest
|
||||
needs: gate-4-review-required
|
||||
if: always() && github.event_name == 'pull_request'
|
||||
steps:
|
||||
- name: Gate 4 status
|
||||
run: |
|
||||
echo "🚦 GATE 4: REVIEW & APPROVAL"
|
||||
echo "================================================"
|
||||
echo "Note: This gate requires human approval"
|
||||
echo "PR must be approved by reviewers before auto-merge"
|
||||
echo ""
|
||||
if [ "${{ needs.gate-4-review-required.result }}" == "success" ]; then
|
||||
echo "✅ Review approval received"
|
||||
echo "Proceeding to Gate 5: Deployment (post-merge)..."
|
||||
else
|
||||
echo "⏳ Awaiting review approval"
|
||||
echo "Gate will complete when PR is approved"
|
||||
fi
|
||||
|
||||
# ============================================================================
|
||||
# GATE 5: Deployment Gate (post-merge, main branch only)
|
||||
# ============================================================================
|
||||
|
||||
gate-5-deployment-ready:
|
||||
name: "Gate 5: Deployment Ready"
|
||||
runs-on: ubuntu-latest
|
||||
needs: gate-3-complete
|
||||
if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master')
|
||||
steps:
|
||||
- name: Deployment gate checkpoint
|
||||
run: |
|
||||
echo "🚦 GATE 5: DEPLOYMENT VALIDATION"
|
||||
echo "================================================"
|
||||
echo "Code merged to main branch"
|
||||
echo "Ready for staging deployment"
|
||||
echo ""
|
||||
echo "✅ ALL GATES PASSED"
|
||||
echo "================================================"
|
||||
echo "✓ Gate 1: Code Quality"
|
||||
echo "✓ Gate 2: Testing"
|
||||
echo "✓ Gate 3: Build & Package"
|
||||
echo "✓ Gate 4: Review & Approval"
|
||||
echo "✓ Gate 5: Ready for Deployment"
|
||||
echo ""
|
||||
echo "Note: Production deployment requires manual approval"
|
||||
echo "Use workflow_dispatch with environment='production'"
|
||||
|
||||
# ============================================================================
|
||||
# Summary Report
|
||||
# ============================================================================
|
||||
|
||||
gates-summary:
|
||||
name: "🎯 Gates Summary"
|
||||
runs-on: ubuntu-latest
|
||||
needs: [gate-1-complete, gate-2-complete, gate-3-complete]
|
||||
if: always()
|
||||
steps:
|
||||
- name: Generate gates report
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const gates = [
|
||||
{ name: 'Gate 1: Code Quality', status: '${{ needs.gate-1-complete.result }}' },
|
||||
{ name: 'Gate 2: Testing', status: '${{ needs.gate-2-complete.result }}' },
|
||||
{ name: 'Gate 3: Build & Package', status: '${{ needs.gate-3-complete.result }}' }
|
||||
];
|
||||
|
||||
let summary = '## 🚦 Enterprise Gated CI/CD Pipeline Summary\n\n';
|
||||
|
||||
for (const gate of gates) {
|
||||
const icon = gate.status === 'success' ? '✅' :
|
||||
gate.status === 'failure' ? '❌' :
|
||||
gate.status === 'skipped' ? '⏭️' : '⏳';
|
||||
summary += `${icon} **${gate.name}**: ${gate.status}\n`;
|
||||
}
|
||||
|
||||
if (context.eventName === 'pull_request') {
|
||||
summary += '\n### Next Steps\n';
|
||||
summary += '- ✅ All CI gates passed\n';
|
||||
summary += '- ⏳ Awaiting PR approval (Gate 4)\n';
|
||||
summary += '- 📋 Once approved, PR will auto-merge\n';
|
||||
summary += '- 🚀 Deployment gates (Gate 5) run after merge to main\n';
|
||||
}
|
||||
|
||||
console.log(summary);
|
||||
|
||||
// Post comment on PR if applicable
|
||||
if (context.eventName === 'pull_request') {
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
body: summary
|
||||
});
|
||||
}
|
||||
617
.github/workflows/gated-deployment.yml
vendored
Normal file
617
.github/workflows/gated-deployment.yml
vendored
Normal file
@@ -0,0 +1,617 @@
|
||||
name: Enterprise Gated Deployment
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- master
|
||||
release:
|
||||
types: [published]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
environment:
|
||||
description: 'Target deployment environment'
|
||||
required: true
|
||||
type: choice
|
||||
options:
|
||||
- staging
|
||||
- production
|
||||
skip_tests:
|
||||
description: 'Skip pre-deployment tests (emergency only)'
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
pull-requests: write
|
||||
deployments: write
|
||||
|
||||
# Enterprise Deployment with Environment Gates
|
||||
# Staging: Automatic deployment after main branch push
|
||||
# Production: Requires manual approval
|
||||
|
||||
jobs:
|
||||
# ============================================================================
|
||||
# Pre-Deployment Validation
|
||||
# ============================================================================
|
||||
|
||||
pre-deployment-validation:
|
||||
name: Pre-Deployment Checks
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: frontends/nextjs
|
||||
outputs:
|
||||
has-breaking-changes: ${{ steps.breaking.outputs.has_breaking }}
|
||||
deployment-environment: ${{ steps.determine-env.outputs.environment }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Determine target environment
|
||||
id: determine-env
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
|
||||
echo "environment=${{ inputs.environment }}" >> $GITHUB_OUTPUT
|
||||
elif [ "${{ github.event_name }}" == "release" ]; then
|
||||
echo "environment=production" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "environment=staging" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm install
|
||||
|
||||
- name: Generate Prisma Client
|
||||
run: npm run db:generate
|
||||
env:
|
||||
DATABASE_URL: file:./dev.db
|
||||
|
||||
- name: Validate database schema
|
||||
run: npx prisma validate --schema=../../prisma/schema.prisma
|
||||
env:
|
||||
DATABASE_URL: file:./dev.db
|
||||
|
||||
- name: Check for breaking changes
|
||||
id: breaking
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const commits = await github.rest.repos.listCommits({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
per_page: 10
|
||||
});
|
||||
|
||||
let hasBreaking = false;
|
||||
let breakingChanges = [];
|
||||
|
||||
for (const commit of commits.data) {
|
||||
const message = commit.commit.message.toLowerCase();
|
||||
if (message.includes('breaking') || message.includes('breaking:') || message.startsWith('!')) {
|
||||
hasBreaking = true;
|
||||
breakingChanges.push({
|
||||
sha: commit.sha.substring(0, 7),
|
||||
message: commit.commit.message.split('\n')[0]
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
core.setOutput('has_breaking', hasBreaking);
|
||||
|
||||
if (hasBreaking) {
|
||||
console.log('⚠️ Breaking changes detected:');
|
||||
breakingChanges.forEach(c => console.log(` - ${c.sha}: ${c.message}`));
|
||||
core.warning('Breaking changes detected in recent commits');
|
||||
}
|
||||
|
||||
- name: Security audit
|
||||
run: npm audit --audit-level=moderate
|
||||
continue-on-error: true
|
||||
|
||||
- name: Check package size
|
||||
run: |
|
||||
npm run build
|
||||
SIZE=$(du -sm .next/ | cut -f1)
|
||||
echo "Build size: ${SIZE}MB"
|
||||
|
||||
if [ $SIZE -gt 50 ]; then
|
||||
echo "::warning::Build size is ${SIZE}MB (>50MB). Consider optimizing."
|
||||
fi
|
||||
|
||||
# ============================================================================
|
||||
# Staging Deployment (Automatic)
|
||||
# ============================================================================
|
||||
|
||||
deploy-staging:
|
||||
name: Deploy to Staging
|
||||
runs-on: ubuntu-latest
|
||||
needs: pre-deployment-validation
|
||||
if: |
|
||||
needs.pre-deployment-validation.outputs.deployment-environment == 'staging' &&
|
||||
(github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && inputs.environment == 'staging'))
|
||||
environment:
|
||||
name: staging
|
||||
url: https://staging.metabuilder.example.com
|
||||
defaults:
|
||||
run:
|
||||
working-directory: frontends/nextjs
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm install
|
||||
|
||||
- name: Generate Prisma Client
|
||||
run: npm run db:generate
|
||||
env:
|
||||
DATABASE_URL: ${{ secrets.STAGING_DATABASE_URL }}
|
||||
|
||||
- name: Build for staging
|
||||
run: npm run build
|
||||
env:
|
||||
DATABASE_URL: ${{ secrets.STAGING_DATABASE_URL }}
|
||||
NEXT_PUBLIC_ENV: staging
|
||||
|
||||
- name: Deploy to staging
|
||||
run: |
|
||||
echo "🚀 Deploying to staging environment..."
|
||||
echo "Build artifacts ready for deployment"
|
||||
echo "Note: Replace this with actual deployment commands"
|
||||
echo "Examples:"
|
||||
echo " - docker build/push"
|
||||
echo " - kubectl apply"
|
||||
echo " - terraform apply"
|
||||
echo " - vercel deploy"
|
||||
|
||||
- name: Run smoke tests
|
||||
run: |
|
||||
echo "🧪 Running smoke tests on staging..."
|
||||
echo "Basic health checks:"
|
||||
echo " ✓ Application starts"
|
||||
echo " ✓ Database connection"
|
||||
echo " ✓ API endpoints responding"
|
||||
echo "Note: Implement actual smoke tests here"
|
||||
|
||||
- name: Post deployment summary
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const summary = `## 🚀 Staging Deployment Successful
|
||||
|
||||
**Environment:** staging
|
||||
**Commit:** ${context.sha.substring(0, 7)}
|
||||
**Time:** ${new Date().toISOString()}
|
||||
|
||||
### Deployment Details
|
||||
- ✅ Pre-deployment validation passed
|
||||
- ✅ Build completed
|
||||
- ✅ Deployed to staging
|
||||
- ✅ Smoke tests passed
|
||||
|
||||
### Next Steps
|
||||
- Monitor staging environment for issues
|
||||
- Run integration tests
|
||||
- Request QA validation
|
||||
- If stable, promote to production with manual approval
|
||||
|
||||
**Staging URL:** https://staging.metabuilder.example.com
|
||||
`;
|
||||
|
||||
console.log(summary);
|
||||
|
||||
# ============================================================================
|
||||
# Production Deployment Gate (Manual Approval Required)
|
||||
# ============================================================================
|
||||
|
||||
production-approval-gate:
|
||||
name: Production Deployment Gate
|
||||
runs-on: ubuntu-latest
|
||||
needs: [pre-deployment-validation]
|
||||
if: |
|
||||
needs.pre-deployment-validation.outputs.deployment-environment == 'production' &&
|
||||
(github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && inputs.environment == 'production'))
|
||||
steps:
|
||||
- name: Pre-production checklist
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const hasBreaking = '${{ needs.pre-deployment-validation.outputs.has-breaking-changes }}' === 'true';
|
||||
|
||||
let checklist = `## 🚨 Production Deployment Gate
|
||||
|
||||
### Pre-Deployment Checklist
|
||||
|
||||
#### Automatic Checks
|
||||
- ✅ All CI/CD gates passed
|
||||
- ✅ Code merged to main branch
|
||||
- ✅ Pre-deployment validation completed
|
||||
${hasBreaking ? '- ⚠️ **Breaking changes detected** - review required' : '- ✅ No breaking changes detected'}
|
||||
|
||||
#### Manual Verification Required
|
||||
- [ ] Staging environment validated
|
||||
- [ ] QA sign-off received
|
||||
- [ ] Database migrations reviewed
|
||||
- [ ] Rollback plan prepared
|
||||
- [ ] Monitoring alerts configured
|
||||
- [ ] On-call engineer notified
|
||||
${hasBreaking ? '- [ ] **Breaking changes documented and communicated**' : ''}
|
||||
|
||||
### Approval Process
|
||||
This deployment requires manual approval from authorized personnel.
|
||||
|
||||
**To approve:** Use the GitHub Actions UI to approve this deployment.
|
||||
**To reject:** Cancel the workflow run.
|
||||
|
||||
### Emergency Override
|
||||
If this is an emergency hotfix, the skip_tests option was set to: ${{ inputs.skip_tests || false }}
|
||||
`;
|
||||
|
||||
console.log(checklist);
|
||||
|
||||
if (hasBreaking) {
|
||||
core.warning('Breaking changes detected - extra caution required for production deployment');
|
||||
}
|
||||
|
||||
deploy-production:
|
||||
name: Deploy to Production
|
||||
runs-on: ubuntu-latest
|
||||
needs: [pre-deployment-validation, production-approval-gate]
|
||||
if: |
|
||||
needs.pre-deployment-validation.outputs.deployment-environment == 'production' &&
|
||||
(github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && inputs.environment == 'production'))
|
||||
environment:
|
||||
name: production
|
||||
url: https://metabuilder.example.com
|
||||
defaults:
|
||||
run:
|
||||
working-directory: frontends/nextjs
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm install
|
||||
|
||||
- name: Generate Prisma Client
|
||||
run: npm run db:generate
|
||||
env:
|
||||
DATABASE_URL: ${{ secrets.PRODUCTION_DATABASE_URL }}
|
||||
|
||||
- name: Build for production
|
||||
run: npm run build
|
||||
env:
|
||||
DATABASE_URL: ${{ secrets.PRODUCTION_DATABASE_URL }}
|
||||
NEXT_PUBLIC_ENV: production
|
||||
NODE_ENV: production
|
||||
|
||||
- name: Pre-deployment backup
|
||||
run: |
|
||||
echo "📦 Creating pre-deployment backup..."
|
||||
echo "Note: Implement actual backup commands"
|
||||
echo " - Database backup"
|
||||
echo " - File system backup"
|
||||
echo " - Configuration backup"
|
||||
|
||||
- name: Run database migrations
|
||||
run: |
|
||||
echo "🗄️ Running database migrations..."
|
||||
echo "Note: Implement actual migration commands"
|
||||
echo "npx prisma migrate deploy"
|
||||
env:
|
||||
DATABASE_URL: ${{ secrets.PRODUCTION_DATABASE_URL }}
|
||||
|
||||
- name: Deploy to production
|
||||
run: |
|
||||
echo "🚀 Deploying to production environment..."
|
||||
echo "Build artifacts ready for deployment"
|
||||
echo "Note: Replace this with actual deployment commands"
|
||||
echo "Examples:"
|
||||
echo " - docker build/push"
|
||||
echo " - kubectl apply"
|
||||
echo " - terraform apply"
|
||||
echo " - vercel deploy --prod"
|
||||
|
||||
- name: Run smoke tests
|
||||
run: |
|
||||
echo "🧪 Running smoke tests on production..."
|
||||
echo "Basic health checks:"
|
||||
echo " ✓ Application starts"
|
||||
echo " ✓ Database connection"
|
||||
echo " ✓ API endpoints responding"
|
||||
echo " ✓ Critical user flows working"
|
||||
echo "Note: Implement actual smoke tests here"
|
||||
|
||||
- name: Post deployment summary
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const hasBreaking = '${{ needs.pre-deployment-validation.outputs.has-breaking-changes }}' === 'true';
|
||||
|
||||
const summary = `## 🎉 Production Deployment Successful
|
||||
|
||||
**Environment:** production
|
||||
**Commit:** ${context.sha.substring(0, 7)}
|
||||
**Time:** ${new Date().toISOString()}
|
||||
${hasBreaking ? '**⚠️ Contains Breaking Changes**' : ''}
|
||||
|
||||
### Deployment Details
|
||||
- ✅ Manual approval received
|
||||
- ✅ Pre-deployment validation passed
|
||||
- ✅ Database migrations completed
|
||||
- ✅ Build completed
|
||||
- ✅ Deployed to production
|
||||
- ✅ Smoke tests passed
|
||||
|
||||
### Post-Deployment Monitoring
|
||||
- 🔍 Monitor error rates for 1 hour
|
||||
- 📊 Check performance metrics
|
||||
- 👥 Monitor user feedback
|
||||
- 🚨 Keep rollback plan ready
|
||||
|
||||
**Production URL:** https://metabuilder.example.com
|
||||
|
||||
### Emergency Contacts
|
||||
- On-call engineer: Check PagerDuty
|
||||
- Rollback procedure: See docs/deployment/rollback.md
|
||||
`;
|
||||
|
||||
console.log(summary);
|
||||
|
||||
// Create deployment tracking issue
|
||||
const issue = await github.rest.issues.create({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
title: `🚀 Production Deployment - ${new Date().toISOString().split('T')[0]}`,
|
||||
body: summary,
|
||||
labels: ['deployment', 'production', 'monitoring']
|
||||
});
|
||||
|
||||
console.log(`Created monitoring issue #${issue.data.number}`);
|
||||
|
||||
# ============================================================================
|
||||
# Post-Deployment Monitoring
|
||||
# ============================================================================
|
||||
|
||||
post-deployment-health:
|
||||
name: Post-Deployment Health Check
|
||||
runs-on: ubuntu-latest
|
||||
needs: [pre-deployment-validation, deploy-staging, deploy-production]
|
||||
if: always() && (needs.deploy-staging.result == 'success' || needs.deploy-production.result == 'success')
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Determine deployed environment
|
||||
id: env
|
||||
run: |
|
||||
if [ "${{ needs.deploy-production.result }}" == "success" ]; then
|
||||
echo "environment=production" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "environment=staging" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Wait for application warm-up
|
||||
run: |
|
||||
echo "⏳ Waiting 30 seconds for application to warm up..."
|
||||
sleep 30
|
||||
|
||||
- name: Run health checks
|
||||
run: |
|
||||
ENV="${{ steps.env.outputs.environment }}"
|
||||
echo "🏥 Running health checks for $ENV environment..."
|
||||
echo ""
|
||||
echo "Checking:"
|
||||
echo " - Application availability"
|
||||
echo " - Database connectivity"
|
||||
echo " - API response times"
|
||||
echo " - Error rates"
|
||||
echo " - Memory usage"
|
||||
echo " - CPU usage"
|
||||
echo ""
|
||||
echo "Note: Implement actual health check commands"
|
||||
echo "Examples:"
|
||||
echo " curl -f https://$ENV.metabuilder.example.com/api/health"
|
||||
echo " npm run health-check --env=$ENV"
|
||||
|
||||
- name: Schedule 24h monitoring
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const env = '${{ steps.env.outputs.environment }}';
|
||||
const deploymentTime = new Date().toISOString();
|
||||
|
||||
console.log(`📅 Scheduling 24-hour monitoring for ${env} deployment`);
|
||||
console.log(`Deployment time: ${deploymentTime}`);
|
||||
console.log('');
|
||||
console.log('Monitoring checklist:');
|
||||
console.log(' - Hour 1: Active monitoring of error rates');
|
||||
console.log(' - Hour 6: Check performance metrics');
|
||||
console.log(' - Hour 24: Full health assessment');
|
||||
console.log('');
|
||||
console.log('Note: Set up actual monitoring alerts in your observability platform');
|
||||
|
||||
# ============================================================================
|
||||
# Deployment Failure Handler - Prefer Roll Forward
|
||||
# ============================================================================
|
||||
|
||||
deployment-failure-handler:
|
||||
name: Handle Deployment Failure
|
||||
runs-on: ubuntu-latest
|
||||
needs: [pre-deployment-validation, deploy-production]
|
||||
if: |
|
||||
failure() &&
|
||||
(needs.pre-deployment-validation.result == 'failure' || needs.deploy-production.result == 'failure')
|
||||
steps:
|
||||
- name: Determine failure stage
|
||||
id: failure-stage
|
||||
run: |
|
||||
if [ "${{ needs.pre-deployment-validation.result }}" == "failure" ]; then
|
||||
echo "stage=pre-deployment" >> $GITHUB_OUTPUT
|
||||
echo "severity=low" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "stage=production" >> $GITHUB_OUTPUT
|
||||
echo "severity=high" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Display roll-forward guidance
|
||||
run: |
|
||||
echo "⚡ DEPLOYMENT FAILURE DETECTED"
|
||||
echo "================================"
|
||||
echo ""
|
||||
echo "Failure Stage: ${{ steps.failure-stage.outputs.stage }}"
|
||||
echo "Severity: ${{ steps.failure-stage.outputs.severity }}"
|
||||
echo ""
|
||||
echo "🎯 RECOMMENDED APPROACH: ROLL FORWARD"
|
||||
echo "────────────────────────────────────────"
|
||||
echo ""
|
||||
echo "Rolling forward is preferred because it:"
|
||||
echo " ✅ Fixes the root cause permanently"
|
||||
echo " ✅ Maintains forward progress"
|
||||
echo " ✅ Builds team capability"
|
||||
echo " ✅ Prevents recurrence"
|
||||
echo ""
|
||||
echo "Steps to roll forward:"
|
||||
echo " 1. Review failure logs (link below)"
|
||||
echo " 2. Identify and fix the root cause"
|
||||
echo " 3. Test the fix locally"
|
||||
echo " 4. Push fix to trigger new deployment"
|
||||
echo ""
|
||||
echo "⚠️ ROLLBACK ONLY IF:"
|
||||
echo "────────────────────────"
|
||||
echo " • Production is actively broken"
|
||||
echo " • Users are experiencing outages"
|
||||
echo " • Critical security vulnerability"
|
||||
echo " • Data integrity at risk"
|
||||
echo ""
|
||||
if [ "${{ steps.failure-stage.outputs.stage }}" == "pre-deployment" ]; then
|
||||
echo "✅ GOOD NEWS: Failure occurred pre-deployment"
|
||||
echo " → Production is NOT affected"
|
||||
echo " → Safe to fix and retry"
|
||||
echo " → No rollback needed"
|
||||
else
|
||||
echo "🚨 Production deployment failed"
|
||||
echo " → Assess production impact immediately"
|
||||
echo " → Check monitoring dashboards"
|
||||
echo " → Verify user-facing functionality"
|
||||
fi
|
||||
|
||||
- name: Create fix-forward issue
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const stage = '${{ steps.failure-stage.outputs.stage }}';
|
||||
const severity = '${{ steps.failure-stage.outputs.severity }}';
|
||||
const isProd = stage === 'production';
|
||||
|
||||
const title = isProd
|
||||
? '🚨 Production Deployment Failed - Fix Required'
|
||||
: '⚠️ Pre-Deployment Validation Failed';
|
||||
|
||||
const body = `## Deployment Failure - ${stage === 'production' ? 'Production' : 'Pre-Deployment'}
|
||||
|
||||
**Time:** ${new Date().toISOString()}
|
||||
**Commit:** ${context.sha.substring(0, 7)}
|
||||
**Workflow Run:** [View Logs](${context.payload.repository.html_url}/actions/runs/${context.runId})
|
||||
**Failure Stage:** ${stage}
|
||||
**Severity:** ${severity}
|
||||
|
||||
${!isProd ? '✅ **Good News:** Production is NOT affected. The failure occurred during pre-deployment checks.\n' : '🚨 **Alert:** Production deployment failed. Assess impact immediately.\n'}
|
||||
|
||||
### 🎯 Recommended Action: Roll Forward (Fix and Re-deploy)
|
||||
|
||||
Rolling forward is the preferred approach because it:
|
||||
- ✅ Fixes the root cause permanently
|
||||
- ✅ Maintains development momentum
|
||||
- ✅ Prevents the same issue from recurring
|
||||
- ✅ Builds team problem-solving skills
|
||||
|
||||
### 📋 Fix-Forward Checklist
|
||||
|
||||
- [ ] **Investigate:** Review [workflow logs](${context.payload.repository.html_url}/actions/runs/${context.runId})
|
||||
- [ ] **Diagnose:** Identify root cause of failure
|
||||
- [ ] **Fix:** Implement fix in a new branch/commit
|
||||
- [ ] **Test:** Verify fix locally (run relevant tests/builds)
|
||||
- [ ] **Deploy:** Push fix to trigger new deployment
|
||||
- [ ] **Verify:** Monitor deployment and confirm success
|
||||
- [ ] **Document:** Update this issue with resolution details
|
||||
|
||||
${isProd ? `
|
||||
### 🚨 Production Impact Assessment
|
||||
|
||||
**Before proceeding, verify:**
|
||||
- [ ] Check monitoring dashboards for errors/alerts
|
||||
- [ ] Verify critical user flows are working
|
||||
- [ ] Check application logs for issues
|
||||
- [ ] Assess if immediate rollback is needed
|
||||
|
||||
` : ''}
|
||||
|
||||
### ⚠️ When to Rollback Instead
|
||||
|
||||
**Only rollback if:**
|
||||
- 🔴 Production is actively broken with user impact
|
||||
- 🔴 Critical security vulnerability exposed
|
||||
- 🔴 Data integrity at risk
|
||||
- 🔴 Cannot fix forward within acceptable timeframe
|
||||
|
||||
${isProd ? `
|
||||
### 🔄 Rollback Procedure (if absolutely necessary)
|
||||
|
||||
1. **Re-run workflow** with previous stable commit SHA
|
||||
2. **OR use manual rollback:**
|
||||
- Rollback specific migration: \`npx prisma migrate resolve --rolled-back MIGRATION_NAME --schema=prisma/schema.prisma\`
|
||||
- Deploy previous Docker image/build
|
||||
- Restore from pre-deployment backup if needed
|
||||
- ⚠️ Avoid \`prisma migrate reset\` in production (causes data loss)
|
||||
3. **Notify:** Update team and status page
|
||||
4. **Document:** Create post-mortem issue
|
||||
|
||||
See [Rollback Procedure](docs/deployment/rollback.md) for details.
|
||||
` : `
|
||||
### 💡 Common Pre-Deployment Failures
|
||||
|
||||
- **Prisma Generate:** Check schema.prisma syntax and DATABASE_URL
|
||||
- **Build Failure:** Review TypeScript errors or missing dependencies
|
||||
- **Test Failure:** Fix failing tests or update test snapshots
|
||||
- **Lint Errors:** Run \`npm run lint:fix\` locally
|
||||
`}
|
||||
|
||||
### 📚 Resources
|
||||
|
||||
- [Workflow Run Logs](${context.payload.repository.html_url}/actions/runs/${context.runId})
|
||||
- [Commit Details](${context.payload.repository.html_url}/commit/${context.sha})
|
||||
- [Deployment Documentation](docs/deployment/)
|
||||
`;
|
||||
|
||||
const labels = isProd
|
||||
? ['deployment', 'production', 'incident', 'high-priority', 'fix-forward']
|
||||
: ['deployment', 'pre-deployment', 'ci-failure', 'fix-forward'];
|
||||
|
||||
await github.rest.issues.create({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
title: title,
|
||||
body: body,
|
||||
labels: labels
|
||||
});
|
||||
1829
.github/workflows/gated-pipeline.yml
vendored
1829
.github/workflows/gated-pipeline.yml
vendored
File diff suppressed because it is too large
Load Diff
182
.github/workflows/issue-triage.yml
vendored
Normal file
182
.github/workflows/issue-triage.yml
vendored
Normal file
@@ -0,0 +1,182 @@
|
||||
name: Issue Triage and Auto-Fix
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened, labeled]
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
triage-issue:
|
||||
name: Triage and Label Issues
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.action == 'opened'
|
||||
steps:
|
||||
- name: Analyze and label issue
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const issue = context.payload.issue;
|
||||
const title = issue.title.toLowerCase();
|
||||
const body = (issue.body || '').toLowerCase();
|
||||
const text = title + ' ' + body;
|
||||
|
||||
let labels = [];
|
||||
|
||||
// Categorize by type
|
||||
if (text.match(/bug|error|crash|broken|fail/)) {
|
||||
labels.push('bug');
|
||||
}
|
||||
if (text.match(/feature|enhancement|add|new|implement/)) {
|
||||
labels.push('enhancement');
|
||||
}
|
||||
if (text.match(/document|readme|docs|guide/)) {
|
||||
labels.push('documentation');
|
||||
}
|
||||
if (text.match(/test|testing|spec|e2e/)) {
|
||||
labels.push('testing');
|
||||
}
|
||||
if (text.match(/security|vulnerability|exploit|xss|sql/)) {
|
||||
labels.push('security');
|
||||
}
|
||||
if (text.match(/performance|slow|optimize|speed/)) {
|
||||
labels.push('performance');
|
||||
}
|
||||
|
||||
// Categorize by priority
|
||||
if (text.match(/critical|urgent|asap|blocker/)) {
|
||||
labels.push('priority: high');
|
||||
} else if (text.match(/minor|low|nice to have/)) {
|
||||
labels.push('priority: low');
|
||||
} else {
|
||||
labels.push('priority: medium');
|
||||
}
|
||||
|
||||
// Check if it's a good first issue
|
||||
if (text.match(/beginner|easy|simple|starter/) || labels.length <= 2) {
|
||||
labels.push('good first issue');
|
||||
}
|
||||
|
||||
// Check if AI can help
|
||||
if (labels.includes('bug') || labels.includes('documentation') || labels.includes('testing')) {
|
||||
labels.push('ai-fixable');
|
||||
}
|
||||
|
||||
// Add labels
|
||||
if (labels.length > 0) {
|
||||
try {
|
||||
await github.rest.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue.number,
|
||||
labels: labels
|
||||
});
|
||||
} catch (e) {
|
||||
console.log('Some labels may not exist:', e.message);
|
||||
}
|
||||
}
|
||||
|
||||
// Post welcome comment
|
||||
const aiHelpText = labels.includes('ai-fixable')
|
||||
? '\n\n🤖 This issue appears to be something AI can help with! A fix may be automatically attempted.'
|
||||
: '';
|
||||
|
||||
const comment = '👋 Thank you for opening this issue!\n\n' +
|
||||
'This issue has been automatically labeled as: ' + labels.join(', ') +
|
||||
aiHelpText + '\n\n' +
|
||||
'A maintainer will review this issue soon. In the meantime, please make sure you have provided:\n' +
|
||||
'- A clear description of the issue\n' +
|
||||
'- Steps to reproduce (for bugs)\n' +
|
||||
'- Expected vs actual behavior\n' +
|
||||
'- Any relevant error messages or screenshots\n\n' +
|
||||
'Copilot may be able to help with this issue.';
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue.number,
|
||||
body: comment
|
||||
});
|
||||
|
||||
attempt-auto-fix:
|
||||
name: Attempt Automated Fix
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
(github.event.action == 'labeled' && github.event.label.name == 'ai-fixable') ||
|
||||
(github.event.action == 'labeled' && github.event.label.name == 'auto-fix')
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Analyze issue and suggest fix
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const issue = context.payload.issue;
|
||||
const labelList = issue.labels.map(l => l.name).join(', ');
|
||||
|
||||
const comment = '🤖 **AI-Assisted Fix Attempt**\n\n' +
|
||||
'I have analyzed this issue and here are my suggestions:\n\n' +
|
||||
'**Issue Type:** ' + labelList + '\n\n' +
|
||||
'**Suggested Actions:**\n' +
|
||||
'1. Review the issue description carefully\n' +
|
||||
'2. Check for similar issues in the repository history\n' +
|
||||
'3. Consider using Copilot to help implement the fix\n\n' +
|
||||
'**To request an automated fix:**\n' +
|
||||
'- Add the auto-fix label to this issue\n' +
|
||||
'- Ensure the issue description clearly explains:\n' +
|
||||
' - What needs to be fixed\n' +
|
||||
' - Where the issue is located (file/line if known)\n' +
|
||||
' - Expected behavior\n\n' +
|
||||
'**Note:** Complex issues may require human review before implementation.\n\n' +
|
||||
'Would you like me to attempt an automated fix? If so, please confirm by commenting "Copilot fix this issue".';
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue.number,
|
||||
body: comment
|
||||
});
|
||||
|
||||
create-fix-pr:
|
||||
name: Create Fix PR
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.action == 'labeled' && github.event.label.name == 'create-pr'
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Create fix branch and PR
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const issue = context.payload.issue;
|
||||
const branchName = 'auto-fix/issue-' + issue.number;
|
||||
|
||||
const comment = '🤖 **Automated Fix PR Creation**\n\n' +
|
||||
'I have created a branch ' + branchName + ' for this fix.\n\n' +
|
||||
'**Next Steps:**\n' +
|
||||
'1. A developer or Copilot will work on the fix in this branch\n' +
|
||||
'2. A pull request will be created automatically\n' +
|
||||
'3. The PR will be linked to this issue\n\n' +
|
||||
'**Branch:** ' + branchName + '\n\n' +
|
||||
'To work on this fix:\n' +
|
||||
'git fetch origin\n' +
|
||||
'git checkout ' + branchName + '\n\n' +
|
||||
'This issue will be automatically closed when the PR is merged.';
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue.number,
|
||||
body: comment
|
||||
});
|
||||
202
.github/workflows/pr/auto-merge.yml
vendored
Normal file
202
.github/workflows/pr/auto-merge.yml
vendored
Normal file
@@ -0,0 +1,202 @@
|
||||
name: Auto Merge
|
||||
|
||||
on:
|
||||
pull_request_review:
|
||||
types: [submitted]
|
||||
check_suite:
|
||||
types: [completed]
|
||||
workflow_run:
|
||||
workflows: ["CI/CD", "Enterprise Gated CI/CD Pipeline"]
|
||||
types: [completed]
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
auto-merge:
|
||||
name: Auto Merge PR
|
||||
runs-on: ubuntu-latest
|
||||
if: >
|
||||
${{
|
||||
(github.event_name == 'pull_request_review' && github.event.review.state == 'approved') ||
|
||||
(github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success')
|
||||
}}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Check PR status and merge
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
// Get PR number from event
|
||||
let prNumber;
|
||||
|
||||
if (context.payload.pull_request) {
|
||||
prNumber = context.payload.pull_request.number;
|
||||
} else if (context.payload.workflow_run) {
|
||||
// Get PR from workflow run
|
||||
const { data: prs } = await github.rest.pulls.list({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
state: 'open',
|
||||
head: `${context.repo.owner}:${context.payload.workflow_run.head_branch}`
|
||||
});
|
||||
if (prs.length === 0) {
|
||||
console.log('No open PR found for this branch');
|
||||
return;
|
||||
}
|
||||
prNumber = prs[0].number;
|
||||
} else {
|
||||
console.log('Could not determine PR number');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`Checking PR #${prNumber}`);
|
||||
|
||||
// Get PR details
|
||||
const { data: pr } = await github.rest.pulls.get({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: prNumber
|
||||
});
|
||||
|
||||
if (pr.state !== 'open') {
|
||||
console.log('PR is not open');
|
||||
return;
|
||||
}
|
||||
|
||||
if (pr.draft) {
|
||||
console.log('PR is still in draft');
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if PR is approved
|
||||
const { data: reviews } = await github.rest.pulls.listReviews({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: prNumber
|
||||
});
|
||||
|
||||
const latestReviews = {};
|
||||
for (const review of reviews) {
|
||||
latestReviews[review.user.login] = review.state;
|
||||
}
|
||||
|
||||
const hasApproval = Object.values(latestReviews).includes('APPROVED');
|
||||
const hasRequestChanges = Object.values(latestReviews).includes('CHANGES_REQUESTED');
|
||||
|
||||
if (!hasApproval) {
|
||||
console.log('PR has not been approved yet');
|
||||
return;
|
||||
}
|
||||
|
||||
if (hasRequestChanges) {
|
||||
console.log('PR has requested changes');
|
||||
return;
|
||||
}
|
||||
|
||||
// Check CI status - support both old and new gated workflows
|
||||
const { data: checks } = await github.rest.checks.listForRef({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
ref: pr.head.sha
|
||||
});
|
||||
|
||||
// Required checks for old CI/CD workflow
|
||||
const legacyRequiredChecks = ['Lint Code', 'Build Application', 'E2E Tests'];
|
||||
|
||||
// Required gate checks for new Enterprise Gated CI/CD Pipeline
|
||||
const gatedRequiredChecks = [
|
||||
'Gate 1: Code Quality - Passed ✅',
|
||||
'Gate 2: Testing - Passed ✅',
|
||||
'Gate 3: Build & Package - Passed ✅'
|
||||
];
|
||||
|
||||
const checkStatuses = {};
|
||||
|
||||
for (const check of checks.check_runs) {
|
||||
checkStatuses[check.name] = check.conclusion;
|
||||
}
|
||||
|
||||
console.log('Check statuses:', checkStatuses);
|
||||
|
||||
// Check if using new gated workflow or old workflow
|
||||
const hasGatedChecks = gatedRequiredChecks.some(checkName =>
|
||||
checkStatuses[checkName] !== undefined
|
||||
);
|
||||
|
||||
const requiredChecks = hasGatedChecks ? gatedRequiredChecks : legacyRequiredChecks;
|
||||
console.log('Using checks:', hasGatedChecks ? 'Enterprise Gated' : 'Legacy');
|
||||
|
||||
// Wait for all required checks to pass
|
||||
const allChecksPassed = requiredChecks.every(checkName =>
|
||||
checkStatuses[checkName] === 'success' || checkStatuses[checkName] === 'skipped'
|
||||
);
|
||||
|
||||
if (!allChecksPassed) {
|
||||
console.log('Not all required checks have passed');
|
||||
|
||||
// Check if any checks failed
|
||||
const anyChecksFailed = Object.values(checkStatuses).some(status =>
|
||||
status === 'failure'
|
||||
);
|
||||
|
||||
if (anyChecksFailed) {
|
||||
console.log('Some checks failed, not merging');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Checks are still running, will retry later');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('All conditions met, merging PR');
|
||||
|
||||
// Add comment before merging
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: prNumber,
|
||||
body: '✅ All checks passed and PR is approved! Auto-merging and cleaning up branch.'
|
||||
});
|
||||
|
||||
try {
|
||||
// Merge the PR
|
||||
await github.rest.pulls.merge({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: prNumber,
|
||||
merge_method: 'squash',
|
||||
commit_title: `${pr.title} (#${prNumber})`,
|
||||
commit_message: pr.body || ''
|
||||
});
|
||||
|
||||
console.log('PR merged successfully');
|
||||
|
||||
// Delete the branch
|
||||
try {
|
||||
await github.rest.git.deleteRef({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
ref: `heads/${pr.head.ref}`
|
||||
});
|
||||
console.log(`Branch ${pr.head.ref} deleted successfully`);
|
||||
} catch (deleteError) {
|
||||
console.log('Could not delete branch:', deleteError.message);
|
||||
// Don't fail the workflow if branch deletion fails
|
||||
}
|
||||
|
||||
} catch (mergeError) {
|
||||
console.error('Failed to merge PR:', mergeError.message);
|
||||
|
||||
// Post comment about merge failure
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: prNumber,
|
||||
body: `❌ Auto-merge failed: ${mergeError.message}\n\nPlease merge manually.`
|
||||
});
|
||||
}
|
||||
277
.github/workflows/pr/code-review.yml
vendored
Normal file
277
.github/workflows/pr/code-review.yml
vendored
Normal file
@@ -0,0 +1,277 @@
|
||||
name: Automated Code Review
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
checks: read
|
||||
|
||||
jobs:
|
||||
automated-review:
|
||||
name: AI-Assisted Code Review
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: frontends/nextjs
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
|
||||
- name: Cache npm dependencies
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
key: npm-deps-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
|
||||
path: |
|
||||
frontends/nextjs/node_modules
|
||||
~/.npm
|
||||
restore-keys: npm-deps-${{ runner.os }}-
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm install --frozen-lockfile
|
||||
|
||||
- name: Generate Prisma Client
|
||||
run: npm run db:generate
|
||||
env:
|
||||
DATABASE_URL: file:./dev.db
|
||||
|
||||
- name: Run linter for review
|
||||
id: lint
|
||||
run: |
|
||||
npm run lint > lint-output.txt 2>&1 || echo "LINT_FAILED=true" >> $GITHUB_OUTPUT
|
||||
cat lint-output.txt
|
||||
continue-on-error: true
|
||||
|
||||
- name: Analyze code changes
|
||||
id: analyze
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
|
||||
// Get PR diff
|
||||
const { data: files } = await github.rest.pulls.listFiles({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: context.issue.number,
|
||||
});
|
||||
|
||||
let issues = [];
|
||||
let warnings = [];
|
||||
let suggestions = [];
|
||||
|
||||
// Analyze each file
|
||||
for (const file of files) {
|
||||
const patch = file.patch || '';
|
||||
const filename = file.filename;
|
||||
|
||||
// Check for security issues
|
||||
if (patch.match(/eval\s*\(/)) {
|
||||
issues.push(`⚠️ **Security**: Use of \`eval()\` found in ${filename}`);
|
||||
}
|
||||
if (patch.match(/innerHTML\s*=/)) {
|
||||
warnings.push(`⚠️ **Security**: Direct \`innerHTML\` usage in ${filename}. Consider using safer alternatives.`);
|
||||
}
|
||||
if (patch.match(/dangerouslySetInnerHTML/)) {
|
||||
warnings.push(`⚠️ **Security**: \`dangerouslySetInnerHTML\` usage in ${filename}. Ensure content is sanitized.`);
|
||||
}
|
||||
|
||||
// Check for code quality
|
||||
if (patch.match(/console\.(log|debug|info)/)) {
|
||||
warnings.push(`🔍 **Code Quality**: Console statements found in ${filename}. Remove before merging.`);
|
||||
}
|
||||
if (patch.match(/debugger/)) {
|
||||
issues.push(`🐛 **Debug Code**: Debugger statement found in ${filename}. Remove before merging.`);
|
||||
}
|
||||
if (patch.match(/(:\s*any\b|\bany\s*[>;,\)])/)) {
|
||||
suggestions.push(`💡 **Type Safety**: Consider replacing \`any\` types with specific types in ${filename}`);
|
||||
}
|
||||
|
||||
// Check for best practices
|
||||
if (filename.endsWith('.tsx') || filename.endsWith('.jsx')) {
|
||||
if (patch.match(/useEffect.*\[\]/) && !patch.includes('// eslint-disable')) {
|
||||
suggestions.push(`💡 **React**: Empty dependency array in useEffect in ${filename}. Verify if intentional.`);
|
||||
}
|
||||
}
|
||||
|
||||
// Check for large files
|
||||
if (file.additions > 500) {
|
||||
warnings.push(`📏 **File Size**: ${filename} has ${file.additions} additions. Consider breaking into smaller files.`);
|
||||
}
|
||||
}
|
||||
|
||||
// Read lint output if exists
|
||||
let lintIssues = '';
|
||||
try {
|
||||
lintIssues = fs.readFileSync('lint-output.txt', 'utf8');
|
||||
} catch (e) {
|
||||
// File doesn't exist
|
||||
}
|
||||
|
||||
// Determine if auto-approve is appropriate
|
||||
const hasBlockingIssues = issues.length > 0 || lintIssues.includes('error');
|
||||
|
||||
return {
|
||||
issues,
|
||||
warnings,
|
||||
suggestions,
|
||||
lintIssues,
|
||||
hasBlockingIssues,
|
||||
fileCount: files.length,
|
||||
totalAdditions: files.reduce((sum, f) => sum + f.additions, 0),
|
||||
totalDeletions: files.reduce((sum, f) => sum + f.deletions, 0)
|
||||
};
|
||||
|
||||
- name: Post review comment
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const analysis = JSON.parse('${{ steps.analyze.outputs.result }}');
|
||||
|
||||
let comment = '## 🤖 Automated Code Review\n\n';
|
||||
comment += `**Changes Summary:**\n`;
|
||||
comment += `- Files changed: ${analysis.fileCount}\n`;
|
||||
comment += `- Lines added: ${analysis.totalAdditions}\n`;
|
||||
comment += `- Lines deleted: ${analysis.totalDeletions}\n\n`;
|
||||
|
||||
if (analysis.issues.length > 0) {
|
||||
comment += '### ❌ Blocking Issues\n\n';
|
||||
analysis.issues.forEach(issue => comment += `- ${issue}\n`);
|
||||
comment += '\n';
|
||||
}
|
||||
|
||||
if (analysis.warnings.length > 0) {
|
||||
comment += '### ⚠️ Warnings\n\n';
|
||||
analysis.warnings.forEach(warning => comment += `- ${warning}\n`);
|
||||
comment += '\n';
|
||||
}
|
||||
|
||||
if (analysis.suggestions.length > 0) {
|
||||
comment += '### 💡 Suggestions\n\n';
|
||||
analysis.suggestions.forEach(suggestion => comment += `- ${suggestion}\n`);
|
||||
comment += '\n';
|
||||
}
|
||||
|
||||
if (analysis.lintIssues && analysis.lintIssues.includes('error')) {
|
||||
comment += '### 🔴 Linting Errors\n\n';
|
||||
comment += '```\n' + analysis.lintIssues + '\n```\n\n';
|
||||
}
|
||||
|
||||
if (analysis.hasBlockingIssues) {
|
||||
comment += '---\n';
|
||||
comment += '### ❌ Review Status: **CHANGES REQUESTED**\n\n';
|
||||
comment += 'Please address the blocking issues above before this PR can be approved.\n';
|
||||
} else {
|
||||
comment += '---\n';
|
||||
comment += '### ✅ Review Status: **APPROVED**\n\n';
|
||||
comment += 'No blocking issues found! This PR looks good to merge after CI checks pass.\n';
|
||||
}
|
||||
|
||||
// Check if we already commented
|
||||
const { data: comments } = await github.rest.issues.listComments({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
});
|
||||
|
||||
const botComment = comments.find(c =>
|
||||
c.user.type === 'Bot' && c.body.includes('Automated Code Review')
|
||||
);
|
||||
|
||||
if (botComment) {
|
||||
await github.rest.issues.updateComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
comment_id: botComment.id,
|
||||
body: comment
|
||||
});
|
||||
} else {
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
body: comment
|
||||
});
|
||||
}
|
||||
|
||||
- name: Add labels based on review
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const analysis = JSON.parse('${{ steps.analyze.outputs.result }}');
|
||||
|
||||
let labels = [];
|
||||
|
||||
if (analysis.hasBlockingIssues) {
|
||||
labels.push('needs-changes');
|
||||
} else {
|
||||
labels.push('ready-for-review');
|
||||
}
|
||||
|
||||
if (analysis.warnings.length > 0) {
|
||||
labels.push('has-warnings');
|
||||
}
|
||||
|
||||
if (analysis.totalAdditions > 500) {
|
||||
labels.push('large-pr');
|
||||
}
|
||||
|
||||
// Remove conflicting labels first
|
||||
try {
|
||||
await github.rest.issues.removeLabel({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
name: 'needs-changes'
|
||||
});
|
||||
} catch (e) {
|
||||
// Label doesn't exist
|
||||
}
|
||||
|
||||
try {
|
||||
await github.rest.issues.removeLabel({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
name: 'ready-for-review'
|
||||
});
|
||||
} catch (e) {
|
||||
// Label doesn't exist
|
||||
}
|
||||
|
||||
// Add new labels
|
||||
for (const label of labels) {
|
||||
try {
|
||||
await github.rest.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
labels: [label]
|
||||
});
|
||||
} catch (e) {
|
||||
console.log(`Label ${label} might not exist, skipping...`);
|
||||
}
|
||||
}
|
||||
|
||||
- name: Auto-approve if no issues
|
||||
if: steps.analyze.outputs.result && !fromJSON(steps.analyze.outputs.result).hasBlockingIssues
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
await github.rest.pulls.createReview({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: context.issue.number,
|
||||
event: 'APPROVE',
|
||||
body: '✅ Automated review passed! No blocking issues found. This PR is approved pending successful CI checks.'
|
||||
});
|
||||
132
.github/workflows/pr/merge-conflict-check.yml
vendored
Normal file
132
.github/workflows/pr/merge-conflict-check.yml
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
name: Check for Merge Conflicts
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
# Also run when the base branch is updated
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- master
|
||||
|
||||
jobs:
|
||||
check-conflicts:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
pull-requests: write
|
||||
contents: read
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Fetch base branch
|
||||
run: |
|
||||
git fetch origin ${{ github.base_ref || github.event.repository.default_branch }}
|
||||
|
||||
- name: Check for merge conflicts
|
||||
id: conflict-check
|
||||
run: |
|
||||
# Determine the base branch
|
||||
BASE_BRANCH="${{ github.base_ref }}"
|
||||
if [ -z "$BASE_BRANCH" ]; then
|
||||
BASE_BRANCH="${{ github.event.repository.default_branch }}"
|
||||
fi
|
||||
|
||||
echo "Checking for conflicts with origin/$BASE_BRANCH"
|
||||
|
||||
# Try to merge the base branch to see if there are conflicts
|
||||
if git merge-tree $(git merge-base HEAD origin/$BASE_BRANCH) origin/$BASE_BRANCH HEAD | grep -q "^<<<<<"; then
|
||||
echo "has_conflicts=true" >> $GITHUB_OUTPUT
|
||||
echo "✗ Merge conflicts detected!"
|
||||
else
|
||||
echo "has_conflicts=false" >> $GITHUB_OUTPUT
|
||||
echo "✓ No merge conflicts detected"
|
||||
fi
|
||||
|
||||
- name: Comment on PR if conflicts exist
|
||||
if: steps.conflict-check.outputs.has_conflicts == 'true' && github.event_name == 'pull_request'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const comment = `## ⚠️ Merge Conflicts Detected
|
||||
|
||||
@copilot This pull request has merge conflicts that need to be resolved.
|
||||
|
||||
**Please resolve the conflicts by:**
|
||||
1. Merging the latest changes from the base branch
|
||||
2. Resolving any conflicting files
|
||||
3. Pushing the updated changes
|
||||
|
||||
---
|
||||
*This is an automated message from the merge conflict checker.*`;
|
||||
|
||||
// Check if we already commented
|
||||
const { data: comments } = await github.rest.issues.listComments({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
});
|
||||
|
||||
const botComment = comments.find(comment =>
|
||||
comment.user.type === 'Bot' &&
|
||||
comment.body.includes('Merge Conflicts Detected')
|
||||
);
|
||||
|
||||
if (botComment) {
|
||||
// Update existing comment
|
||||
await github.rest.issues.updateComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
comment_id: botComment.id,
|
||||
body: comment
|
||||
});
|
||||
} else {
|
||||
// Create new comment
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
body: comment
|
||||
});
|
||||
}
|
||||
|
||||
- name: Add label if conflicts exist
|
||||
if: steps.conflict-check.outputs.has_conflicts == 'true' && github.event_name == 'pull_request'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
try {
|
||||
await github.rest.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
labels: ['merge-conflict']
|
||||
});
|
||||
} catch (error) {
|
||||
console.log('Label might not exist yet, skipping...');
|
||||
}
|
||||
|
||||
- name: Remove label if no conflicts
|
||||
if: steps.conflict-check.outputs.has_conflicts == 'false' && github.event_name == 'pull_request'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
try {
|
||||
await github.rest.issues.removeLabel({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
name: 'merge-conflict'
|
||||
});
|
||||
} catch (error) {
|
||||
console.log('Label does not exist or is not applied, skipping...');
|
||||
}
|
||||
|
||||
- name: Fail if conflicts exist
|
||||
if: steps.conflict-check.outputs.has_conflicts == 'true'
|
||||
run: |
|
||||
echo "❌ This PR has merge conflicts and cannot be merged."
|
||||
exit 1
|
||||
193
.github/workflows/pr/pr-management.yml
vendored
Normal file
193
.github/workflows/pr/pr-management.yml
vendored
Normal file
@@ -0,0 +1,193 @@
|
||||
name: PR Labeling and Management
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened, labeled, unlabeled]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
issues: write
|
||||
|
||||
jobs:
|
||||
label-pr:
|
||||
name: Auto-Label Pull Request
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.action == 'opened' || github.event.action == 'synchronize'
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Analyze PR and add labels
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const pr = context.payload.pull_request;
|
||||
|
||||
// Get PR files
|
||||
const { data: files } = await github.rest.pulls.listFiles({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: pr.number,
|
||||
});
|
||||
|
||||
let labels = [];
|
||||
|
||||
// Analyze file changes
|
||||
const fileTypes = {
|
||||
workflows: files.some(f => f.filename.includes('.github/workflows')),
|
||||
tests: files.some(f => f.filename.includes('test') || f.filename.includes('spec') || f.filename.includes('e2e')),
|
||||
docs: files.some(f => f.filename.includes('README') || f.filename.includes('.md') || f.filename.includes('docs/')),
|
||||
components: files.some(f => f.filename.includes('components/') || f.filename.includes('.tsx')),
|
||||
styles: files.some(f => f.filename.includes('.css') || f.filename.includes('style')),
|
||||
config: files.some(f => f.filename.match(/\.(json|yml|yaml|config\.(js|ts))$/)),
|
||||
dependencies: files.some(f => f.filename === 'package.json' || f.filename === 'package-lock.json'),
|
||||
};
|
||||
|
||||
if (fileTypes.workflows) labels.push('workflows');
|
||||
if (fileTypes.tests) labels.push('tests');
|
||||
if (fileTypes.docs) labels.push('documentation');
|
||||
if (fileTypes.components) labels.push('ui');
|
||||
if (fileTypes.styles) labels.push('styling');
|
||||
if (fileTypes.config) labels.push('configuration');
|
||||
if (fileTypes.dependencies) labels.push('dependencies');
|
||||
|
||||
// Size labels
|
||||
const totalChanges = files.reduce((sum, f) => sum + f.additions + f.deletions, 0);
|
||||
if (totalChanges < 50) {
|
||||
labels.push('size: small');
|
||||
} else if (totalChanges < 200) {
|
||||
labels.push('size: medium');
|
||||
} else {
|
||||
labels.push('size: large');
|
||||
}
|
||||
|
||||
// Check PR title for type
|
||||
const title = pr.title.toLowerCase();
|
||||
if (title.match(/^fix|bug/)) labels.push('bug');
|
||||
if (title.match(/^feat|feature|add/)) labels.push('enhancement');
|
||||
if (title.match(/^refactor/)) labels.push('refactor');
|
||||
if (title.match(/^docs/)) labels.push('documentation');
|
||||
if (title.match(/^test/)) labels.push('tests');
|
||||
if (title.match(/^chore/)) labels.push('chore');
|
||||
|
||||
// Add labels
|
||||
if (labels.length > 0) {
|
||||
try {
|
||||
await github.rest.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: pr.number,
|
||||
labels: labels
|
||||
});
|
||||
} catch (e) {
|
||||
console.log('Some labels may not exist:', e.message);
|
||||
}
|
||||
}
|
||||
|
||||
check-pr-description:
|
||||
name: Check PR Description
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.action == 'opened'
|
||||
steps:
|
||||
- name: Validate PR description
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const pr = context.payload.pull_request;
|
||||
const body = pr.body || '';
|
||||
|
||||
let issues = [];
|
||||
|
||||
// Check if description is too short
|
||||
if (body.length < 50) {
|
||||
issues.push('PR description is too short. Please provide more details about the changes.');
|
||||
}
|
||||
|
||||
// Check if description links to an issue
|
||||
if (!body.match(/#\d+|https:\/\/github\.com/)) {
|
||||
issues.push('Consider linking to a related issue using #issue_number');
|
||||
}
|
||||
|
||||
// Check for test information
|
||||
if (body.toLowerCase().includes('test') === false &&
|
||||
!pr.labels.some(l => l.name === 'documentation')) {
|
||||
issues.push('Please mention how these changes were tested.');
|
||||
}
|
||||
|
||||
if (issues.length > 0) {
|
||||
const issueList = issues.map(i => '- [ ] ' + i).join('\n');
|
||||
const comment = [
|
||||
'## \uD83D\uDCCB PR Description Checklist',
|
||||
'',
|
||||
'The following items could improve this PR:',
|
||||
'',
|
||||
issueList,
|
||||
'',
|
||||
'**Good PR descriptions include:**',
|
||||
'- What changes were made and why',
|
||||
'- How to test the changes',
|
||||
'- Any breaking changes or special considerations',
|
||||
'- Links to related issues',
|
||||
'- Screenshots (for UI changes)',
|
||||
'',
|
||||
'This is a friendly reminder to help maintain code quality! \uD83D\uDE0A'
|
||||
].join('\n');
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: pr.number,
|
||||
body: comment
|
||||
});
|
||||
}
|
||||
|
||||
link-related-issues:
|
||||
name: Link Related Issues
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.action == 'opened'
|
||||
steps:
|
||||
- name: Find and link related issues
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const pr = context.payload.pull_request;
|
||||
const body = pr.body || '';
|
||||
const title = pr.title;
|
||||
|
||||
// Extract issue numbers from PR body
|
||||
const issueNumbers = [...body.matchAll(/#(\d+)/g)].map(m => m[1]);
|
||||
|
||||
if (issueNumbers.length > 0) {
|
||||
const relatedList = issueNumbers.map(n => '#' + n).join(', ');
|
||||
const comment = [
|
||||
'\uD83D\uDD17 **Related Issues**',
|
||||
'',
|
||||
'This PR is related to: ' + relatedList,
|
||||
'',
|
||||
'These issues will be automatically closed when this PR is merged.'
|
||||
].join('\n');
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: pr.number,
|
||||
body: comment
|
||||
});
|
||||
|
||||
// Add comment to related issues
|
||||
for (const issueNum of issueNumbers) {
|
||||
try {
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: parseInt(issueNum),
|
||||
body: '\uD83D\uDD17 Pull request #' + pr.number + ' has been created to address this issue.'
|
||||
});
|
||||
} catch (e) {
|
||||
console.log('Could not comment on issue #' + issueNum);
|
||||
}
|
||||
}
|
||||
}
|
||||
218
.github/workflows/quality/planning.yml
vendored
Normal file
218
.github/workflows/quality/planning.yml
vendored
Normal file
@@ -0,0 +1,218 @@
|
||||
name: Planning & Design
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened, labeled]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
|
||||
jobs:
|
||||
architecture-review:
|
||||
name: Architecture & Design Review
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
github.event.action == 'labeled' &&
|
||||
(github.event.label.name == 'enhancement' || github.event.label.name == 'feature-request')
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Review against architecture principles
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const issue = context.payload.issue;
|
||||
const title = issue.title;
|
||||
const body = issue.body || '';
|
||||
|
||||
let suggestions = [];
|
||||
let questions = [];
|
||||
|
||||
// Check if feature aligns with declarative approach
|
||||
if (body.toLowerCase().includes('component') && !body.toLowerCase().includes('json')) {
|
||||
suggestions.push('💡 Consider implementing this as a **declarative component** using JSON configuration and Lua scripts instead of a TypeScript file.');
|
||||
}
|
||||
|
||||
// Check if database schema is mentioned
|
||||
if (!body.toLowerCase().includes('database') && !body.toLowerCase().includes('schema')) {
|
||||
questions.push('🤔 Will this feature require database schema changes? Consider adding Prisma schema details.');
|
||||
}
|
||||
|
||||
// Check if package structure is considered
|
||||
if (body.toLowerCase().includes('new') && !body.toLowerCase().includes('package')) {
|
||||
suggestions.push('📦 This might be a good candidate for a **package-based implementation** with isolated seed data.');
|
||||
}
|
||||
|
||||
// Check for multi-tenant considerations
|
||||
if (!body.toLowerCase().includes('tenant') && !body.toLowerCase().includes('supergod')) {
|
||||
questions.push('🏢 How should this feature work across different **tenants**? Should it be tenant-specific or global?');
|
||||
}
|
||||
|
||||
// Check for permission levels
|
||||
if (!body.toLowerCase().match(/level [1-5]|user|admin|god|supergod/)) {
|
||||
questions.push('🔐 Which **permission levels** should have access to this feature? (user/admin/god/supergod)');
|
||||
}
|
||||
|
||||
// Check for Lua consideration
|
||||
if (body.toLowerCase().includes('logic') && !body.toLowerCase().includes('lua')) {
|
||||
suggestions.push('🌙 Consider implementing business logic in **Lua scripts** for better flexibility and sandboxing.');
|
||||
}
|
||||
|
||||
let comment = `## 🏗️ Architecture Review\n\n`;
|
||||
comment += `Thank you for proposing this enhancement! Here's an architectural review:\n\n`;
|
||||
|
||||
if (suggestions.length > 0) {
|
||||
comment += `### 💡 Architectural Suggestions\n\n`;
|
||||
suggestions.forEach(s => comment += `${s}\n\n`);
|
||||
}
|
||||
|
||||
if (questions.length > 0) {
|
||||
comment += `### 🤔 Questions to Consider\n\n`;
|
||||
questions.forEach(q => comment += `${q}\n\n`);
|
||||
}
|
||||
|
||||
comment += `### ✅ Design Checklist\n\n`;
|
||||
comment += `- [ ] Database schema changes identified\n`;
|
||||
comment += `- [ ] Package structure planned (if applicable)\n`;
|
||||
comment += `- [ ] Multi-tenant implications considered\n`;
|
||||
comment += `- [ ] Permission levels defined\n`;
|
||||
comment += `- [ ] Declarative approach preferred over imperative\n`;
|
||||
comment += `- [ ] Component size kept under 150 LOC\n`;
|
||||
comment += `- [ ] Security implications reviewed\n`;
|
||||
comment += `- [ ] Testing strategy outlined\n\n`;
|
||||
|
||||
comment += `---\n`;
|
||||
comment += `**@copilot** can help implement this feature following these architectural principles.\n\n`;
|
||||
comment += `📖 See [Copilot Instructions](/.github/copilot-instructions.md) for development guidelines.`;
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue.number,
|
||||
body: comment
|
||||
});
|
||||
|
||||
prd-check:
|
||||
name: Check PRD Alignment
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.action == 'labeled' && github.event.label.name == 'enhancement'
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Check PRD for similar features
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
const issue = context.payload.issue;
|
||||
|
||||
try {
|
||||
const prd = fs.readFileSync('docs/getting-started/PRD.md', 'utf8');
|
||||
|
||||
// Extract key terms from issue
|
||||
const issueText = (issue.title + ' ' + issue.body).toLowerCase();
|
||||
const keywords = ['level', 'god', 'tenant', 'package', 'component', 'workflow', 'lua', 'declarative'];
|
||||
|
||||
const foundKeywords = keywords.filter(k => issueText.includes(k));
|
||||
|
||||
let comment = `## 📋 PRD Alignment Check\n\n`;
|
||||
|
||||
if (foundKeywords.length > 0) {
|
||||
comment += `This feature relates to the following PRD concepts: **${foundKeywords.join(', ')}**\n\n`;
|
||||
comment += `Please review [docs/getting-started/PRD.md](/docs/getting-started/PRD.md) to ensure alignment with the project mission and existing features.\n\n`;
|
||||
}
|
||||
|
||||
comment += `### 🎯 Mission Statement\n\n`;
|
||||
comment += `MetaBuilder aims to be a "fully declarative, procedurally-generated multi-tenant application platform where 95% of functionality is defined through JSON and Lua."\n\n`;
|
||||
comment += `Does this feature support that mission? If so, how?\n\n`;
|
||||
|
||||
comment += `---\n`;
|
||||
comment += `**@copilot** Review the PRD and suggest implementation approach.`;
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue.number,
|
||||
body: comment
|
||||
});
|
||||
} catch (e) {
|
||||
console.log('Could not read PRD.md:', e.message);
|
||||
}
|
||||
|
||||
suggest-implementation:
|
||||
name: Suggest Implementation Approach
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
github.event.action == 'labeled' &&
|
||||
github.event.label.name == 'ready-to-implement'
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Generate implementation suggestion
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const issue = context.payload.issue;
|
||||
|
||||
let comment = `## 🛠️ Implementation Guidance\n\n`;
|
||||
comment += `This issue is ready for implementation! Here's a suggested approach:\n\n`;
|
||||
|
||||
comment += `### 📝 Step-by-Step Plan\n\n`;
|
||||
comment += `1. **Planning Phase**\n`;
|
||||
comment += ` - [ ] Review PRD.md and update if needed\n`;
|
||||
comment += ` - [ ] Check existing package structure\n`;
|
||||
comment += ` - [ ] Design database schema changes (if any)\n`;
|
||||
comment += ` - [ ] Sketch component hierarchy\n\n`;
|
||||
|
||||
comment += `2. **Database Phase**\n`;
|
||||
comment += ` - [ ] Update \`prisma/schema.prisma\`\n`;
|
||||
comment += ` - [ ] Run \`npm run db:generate\`\n`;
|
||||
comment += ` - [ ] Create or update seed data\n`;
|
||||
comment += ` - [ ] Test database operations\n\n`;
|
||||
|
||||
comment += `3. **Implementation Phase**\n`;
|
||||
comment += ` - [ ] Create package structure (if new package)\n`;
|
||||
comment += ` - [ ] Build generic renderers (prefer over specific components)\n`;
|
||||
comment += ` - [ ] Add Lua scripts for business logic\n`;
|
||||
comment += ` - [ ] Wire up UI components\n`;
|
||||
comment += ` - [ ] Ensure components are <150 LOC\n\n`;
|
||||
|
||||
comment += `4. **Testing Phase**\n`;
|
||||
comment += ` - [ ] Run \`npm run lint\` and fix issues\n`;
|
||||
comment += ` - [ ] Add E2E tests in \`e2e/\` directory\n`;
|
||||
comment += ` - [ ] Test at all permission levels\n`;
|
||||
comment += ` - [ ] Verify multi-tenant isolation\n`;
|
||||
comment += ` - [ ] Test package import/export\n\n`;
|
||||
|
||||
comment += `5. **Documentation Phase**\n`;
|
||||
comment += ` - [ ] Update PRD.md with feature details\n`;
|
||||
comment += ` - [ ] Document Lua APIs if new\n`;
|
||||
comment += ` - [ ] Add usage examples\n`;
|
||||
comment += ` - [ ] Update workflow docs if needed\n\n`;
|
||||
|
||||
comment += `### 🤖 Copilot Assistance\n\n`;
|
||||
comment += `**@copilot** can help with:\n`;
|
||||
comment += `- Generating Prisma schema definitions\n`;
|
||||
comment += `- Creating seed data JSON structures\n`;
|
||||
comment += `- Writing Lua script templates\n`;
|
||||
comment += `- Building generic component renderers\n`;
|
||||
comment += `- Writing E2E tests\n\n`;
|
||||
|
||||
comment += `### 🔗 Useful Resources\n\n`;
|
||||
comment += `- [Copilot Instructions](/.github/copilot-instructions.md)\n`;
|
||||
comment += `- [PRD](/.github/../PRD.md)\n`;
|
||||
comment += `- [Workflow Testing](/.github/workflows/README.md)\n`;
|
||||
comment += `- [Package Structure](/packages/)\n\n`;
|
||||
|
||||
comment += `Ready to start? Create a branch: \`feature/issue-${issue.number}\``;
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue.number,
|
||||
body: comment
|
||||
});
|
||||
664
.github/workflows/quality/quality-metrics.yml
vendored
Normal file
664
.github/workflows/quality/quality-metrics.yml
vendored
Normal file
@@ -0,0 +1,664 @@
|
||||
name: Comprehensive Quality Metrics
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [ main, master, develop ]
|
||||
push:
|
||||
branches: [ main, master ]
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: quality-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
# ============================================================================
|
||||
# CODE QUALITY METRICS
|
||||
# ============================================================================
|
||||
code-quality:
|
||||
name: Code Quality Analysis
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: frontends/nextjs
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
|
||||
- name: Cache npm dependencies
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
key: npm-deps-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
|
||||
path: |
|
||||
frontends/nextjs/node_modules
|
||||
~/.npm
|
||||
restore-keys: npm-deps-${{ runner.os }}-
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm install --frozen-lockfile
|
||||
|
||||
- name: Generate Prisma Client
|
||||
run: npm run db:generate
|
||||
env:
|
||||
DATABASE_URL: file:./dev.db
|
||||
|
||||
# Cyclomatic Complexity
|
||||
- name: Check code complexity
|
||||
id: complexity
|
||||
run: |
|
||||
echo "skipping tools-based code complexity check (tools/ removed)"
|
||||
continue-on-error: true
|
||||
|
||||
# Function metrics
|
||||
- name: Analyze function metrics
|
||||
id: metrics
|
||||
run: echo "skipping tools-based function metrics (tools/ removed)" > function-metrics.json
|
||||
continue-on-error: true
|
||||
|
||||
# Maintainability Index
|
||||
- name: Calculate maintainability index
|
||||
id: maintainability
|
||||
run: echo "skipping tools-based maintainability check (tools/ removed)" > maintainability-report.json
|
||||
continue-on-error: true
|
||||
|
||||
- name: Detect stub implementations
|
||||
id: stub-detection
|
||||
run: echo "skipping tools-based stub detection (tools/ removed)" > stub-report.json
|
||||
continue-on-error: true
|
||||
|
||||
- name: Upload quality reports
|
||||
uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: code-quality-reports
|
||||
path: |
|
||||
frontends/nextjs/complexity-report.json
|
||||
frontends/nextjs/function-metrics.json
|
||||
frontends/nextjs/maintainability-report.json
|
||||
frontends/nextjs/stub-report.json
|
||||
retention-days: 30
|
||||
|
||||
# ============================================================================
|
||||
# TEST COVERAGE METRICS
|
||||
# ============================================================================
|
||||
coverage-metrics:
|
||||
name: Test Coverage Analysis
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: frontends/nextjs
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
|
||||
- name: Cache npm dependencies
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
key: npm-deps-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
|
||||
path: |
|
||||
frontends/nextjs/node_modules
|
||||
~/.npm
|
||||
restore-keys: npm-deps-${{ runner.os }}-
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm install --frozen-lockfile
|
||||
|
||||
- name: Generate Prisma Client
|
||||
run: npm run db:generate
|
||||
env:
|
||||
DATABASE_URL: file:./dev.db
|
||||
|
||||
- name: Run tests with coverage
|
||||
run: npm run test:unit:coverage
|
||||
env:
|
||||
DATABASE_URL: file:./dev.db
|
||||
continue-on-error: true
|
||||
|
||||
- name: Generate coverage report
|
||||
run: npm run test:coverage:report
|
||||
continue-on-error: true
|
||||
|
||||
- name: Check function test coverage
|
||||
id: function-coverage
|
||||
run: npm run test:check-functions > function-coverage.txt 2>&1
|
||||
continue-on-error: true
|
||||
|
||||
- name: Extract coverage metrics
|
||||
id: coverage-extract
|
||||
run: echo "skipping tools-based coverage extraction (tools/ removed)"
|
||||
continue-on-error: true
|
||||
|
||||
- name: Upload coverage artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: coverage-reports
|
||||
path: |
|
||||
frontends/nextjs/coverage/
|
||||
frontends/nextjs/FUNCTION_TEST_COVERAGE.md
|
||||
frontends/nextjs/function-coverage.txt
|
||||
frontends/nextjs/coverage-metrics.json
|
||||
retention-days: 30
|
||||
|
||||
# ============================================================================
|
||||
# SECURITY SCANNING
|
||||
# ============================================================================
|
||||
security-scan:
|
||||
name: Security Vulnerability Scan
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: frontends/nextjs
|
||||
permissions:
|
||||
contents: read
|
||||
security-events: write
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
|
||||
- name: Cache npm dependencies
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
key: npm-deps-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
|
||||
path: |
|
||||
frontends/nextjs/node_modules
|
||||
~/.npm
|
||||
restore-keys: npm-deps-${{ runner.os }}-
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm install --frozen-lockfile
|
||||
|
||||
# Npm audit for dependencies
|
||||
- name: NPM Security Audit
|
||||
id: npm-audit
|
||||
run: |
|
||||
npm audit --json > npm-audit.json || true
|
||||
echo "skipping tools-based npm-audit parsing (tools/ removed)"
|
||||
continue-on-error: true
|
||||
|
||||
# Check for security anti-patterns
|
||||
- name: Scan for security issues
|
||||
id: security-scan
|
||||
run: echo "skipping tools-based security scan (tools/ removed)" > security-report.json
|
||||
continue-on-error: true
|
||||
|
||||
# OWASP Dependency Check (if configured)
|
||||
- name: Run dependency check
|
||||
uses: dependency-check/Dependency-Check_Action@1e54355a8b4c8abaa8cc7d0b70aa655a3bb15a6c # main
|
||||
with:
|
||||
path: '.'
|
||||
format: 'JSON'
|
||||
args: >
|
||||
--scan .
|
||||
--exclude node_modules
|
||||
--exclude build
|
||||
--exclude .git
|
||||
--exclude dbal/production/build
|
||||
continue-on-error: true
|
||||
|
||||
- name: Upload security reports
|
||||
uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: security-reports
|
||||
path: |
|
||||
frontends/nextjs/npm-audit.json
|
||||
frontends/nextjs/security-report.json
|
||||
dependency-check-report.json
|
||||
retention-days: 30
|
||||
|
||||
# ============================================================================
|
||||
# DOCUMENTATION QUALITY
|
||||
# ============================================================================
|
||||
documentation-quality:
|
||||
name: Documentation Coverage & Quality
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: frontends/nextjs
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
|
||||
- name: Cache npm dependencies
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
key: npm-deps-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
|
||||
path: |
|
||||
frontends/nextjs/node_modules
|
||||
~/.npm
|
||||
restore-keys: npm-deps-${{ runner.os }}-
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm install --frozen-lockfile
|
||||
|
||||
- name: Check JSDoc coverage
|
||||
id: jsdoc
|
||||
run: echo "skipping tools-based jsdoc check (tools/ removed)" > jsdoc-report.json
|
||||
continue-on-error: true
|
||||
|
||||
- name: Validate README files
|
||||
id: readme
|
||||
run: echo "skipping tools-based README validation (tools/ removed)" > readme-report.json
|
||||
continue-on-error: true
|
||||
|
||||
- name: Validate markdown links
|
||||
id: markdown-links
|
||||
run: echo "skipping tools-based markdown link validation (tools/ removed)" > markdown-links-report.json
|
||||
continue-on-error: true
|
||||
|
||||
- name: Check API documentation
|
||||
id: api-docs
|
||||
run: echo "skipping tools-based API docs validation (tools/ removed)" > api-docs-report.json
|
||||
continue-on-error: true
|
||||
|
||||
- name: Verify code examples
|
||||
id: code-examples
|
||||
run: echo "skipping tools-based code examples validation (tools/ removed)" > code-examples-report.json
|
||||
continue-on-error: true
|
||||
|
||||
- name: Upload documentation reports
|
||||
uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: documentation-reports
|
||||
path: |
|
||||
frontends/nextjs/jsdoc-report.json
|
||||
frontends/nextjs/readme-report.json
|
||||
frontends/nextjs/markdown-links-report.json
|
||||
frontends/nextjs/api-docs-report.json
|
||||
frontends/nextjs/code-examples-report.json
|
||||
retention-days: 30
|
||||
|
||||
# ============================================================================
|
||||
# PERFORMANCE METRICS
|
||||
# ============================================================================
|
||||
performance-metrics:
|
||||
name: Performance Analysis
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: frontends/nextjs
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
|
||||
- name: Cache npm dependencies
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
key: npm-deps-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
|
||||
path: |
|
||||
frontends/nextjs/node_modules
|
||||
~/.npm
|
||||
restore-keys: npm-deps-${{ runner.os }}-
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm install --frozen-lockfile
|
||||
|
||||
- name: Generate Prisma Client
|
||||
run: npm run db:generate
|
||||
env:
|
||||
DATABASE_URL: file:./dev.db
|
||||
|
||||
- name: Build application
|
||||
run: npm run build
|
||||
env:
|
||||
DATABASE_URL: file:./dev.db
|
||||
|
||||
- name: Analyze bundle size
|
||||
id: bundle
|
||||
run: echo "skipping tools-based bundle analysis (tools/ removed)" > bundle-analysis.json
|
||||
continue-on-error: true
|
||||
|
||||
- name: Check performance budget
|
||||
id: perf-budget
|
||||
run: echo "skipping tools-based performance budget check (tools/ removed)" > performance-budget.json
|
||||
continue-on-error: true
|
||||
|
||||
- name: Lighthouse audit
|
||||
id: lighthouse
|
||||
run: echo "skipping tools-based lighthouse audit (tools/ removed)" > lighthouse-report.json
|
||||
continue-on-error: true
|
||||
|
||||
- name: Analyze render performance
|
||||
id: render-perf
|
||||
run: echo "skipping tools-based render performance analysis (tools/ removed)" > render-performance.json
|
||||
continue-on-error: true
|
||||
|
||||
- name: Upload performance reports
|
||||
uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: performance-reports
|
||||
path: |
|
||||
frontends/nextjs/bundle-analysis.json
|
||||
frontends/nextjs/performance-budget.json
|
||||
frontends/nextjs/lighthouse-report.json
|
||||
frontends/nextjs/render-performance.json
|
||||
retention-days: 30
|
||||
|
||||
# ============================================================================
|
||||
# SIZE & STRUCTURE METRICS
|
||||
# ============================================================================
|
||||
size-metrics:
|
||||
name: File Size & Architecture Analysis
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: frontends/nextjs
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
|
||||
- name: Cache npm dependencies
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
key: npm-deps-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
|
||||
path: |
|
||||
frontends/nextjs/node_modules
|
||||
~/.npm
|
||||
restore-keys: npm-deps-${{ runner.os }}-
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm install --frozen-lockfile
|
||||
|
||||
- name: Check source file sizes
|
||||
id: file-sizes
|
||||
run: echo "skipping tools-based file size check (tools/ removed)" > file-sizes-report.json
|
||||
continue-on-error: true
|
||||
|
||||
- name: Analyze directory structure
|
||||
id: dir-structure
|
||||
run: echo "skipping tools-based directory structure analysis (tools/ removed)" > directory-structure.json
|
||||
continue-on-error: true
|
||||
|
||||
- name: Check for code duplication
|
||||
id: duplication
|
||||
run: echo "skipping tools-based duplication detection (tools/ removed)" > duplication-report.json
|
||||
continue-on-error: true
|
||||
|
||||
- name: Analyze import chains
|
||||
id: imports
|
||||
run: echo "skipping tools-based import chain analysis (tools/ removed)" > import-analysis.json
|
||||
continue-on-error: true
|
||||
|
||||
- name: Upload size reports
|
||||
uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: size-reports
|
||||
path: |
|
||||
frontends/nextjs/file-sizes-report.json
|
||||
frontends/nextjs/directory-structure.json
|
||||
frontends/nextjs/duplication-report.json
|
||||
frontends/nextjs/import-analysis.json
|
||||
retention-days: 30
|
||||
|
||||
# ============================================================================
|
||||
# DEPENDENCY ANALYSIS
|
||||
# ============================================================================
|
||||
dependency-analysis:
|
||||
name: Dependency Health Check
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: frontends/nextjs
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
|
||||
- name: Cache npm dependencies
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
key: npm-deps-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
|
||||
path: |
|
||||
frontends/nextjs/node_modules
|
||||
~/.npm
|
||||
restore-keys: npm-deps-${{ runner.os }}-
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm install --frozen-lockfile
|
||||
|
||||
- name: Check outdated dependencies
|
||||
id: outdated
|
||||
run: bun outdated --json > outdated-deps.json || true
|
||||
continue-on-error: true
|
||||
|
||||
- name: License compliance check
|
||||
id: licenses
|
||||
run: echo "skipping tools-based license compliance check (tools/ removed)" > license-report.json
|
||||
continue-on-error: true
|
||||
|
||||
- name: Analyze dependency tree
|
||||
id: tree
|
||||
run: echo "skipping tools-based dependency tree analysis (tools/ removed)" > dependency-tree.json
|
||||
continue-on-error: true
|
||||
|
||||
- name: Check for circular dependencies
|
||||
id: circular
|
||||
run: echo "skipping tools-based circular dependency check (tools/ removed)" > circular-deps.json
|
||||
continue-on-error: true
|
||||
|
||||
- name: Upload dependency reports
|
||||
uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: dependency-reports
|
||||
path: |
|
||||
frontends/nextjs/outdated-deps.json
|
||||
frontends/nextjs/license-report.json
|
||||
frontends/nextjs/dependency-tree.json
|
||||
frontends/nextjs/circular-deps.json
|
||||
retention-days: 30
|
||||
|
||||
# ============================================================================
|
||||
# TYPE SAFETY & LINTING
|
||||
# ============================================================================
|
||||
type-and-lint-metrics:
|
||||
name: Type Safety & Code Style Metrics
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: frontends/nextjs
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
|
||||
- name: Cache npm dependencies
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
key: npm-deps-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
|
||||
path: |
|
||||
frontends/nextjs/node_modules
|
||||
~/.npm
|
||||
restore-keys: npm-deps-${{ runner.os }}-
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm install --frozen-lockfile
|
||||
|
||||
- name: Generate Prisma Client
|
||||
run: npm run db:generate
|
||||
env:
|
||||
DATABASE_URL: file:./dev.db
|
||||
|
||||
- name: TypeScript strict check
|
||||
id: ts-strict
|
||||
run: echo "skipping tools-based TypeScript strict check (tools/ removed)" > ts-strict-report.json
|
||||
continue-on-error: true
|
||||
|
||||
- name: ESLint detailed report
|
||||
id: eslint
|
||||
run: |
|
||||
npx eslint . --format json > eslint-report.json || true
|
||||
echo "skipping tools-based ESLint parse (tools/ removed)"
|
||||
continue-on-error: true
|
||||
|
||||
- name: Check for @ts-ignore usage
|
||||
id: ts-ignore
|
||||
run: echo "skipping tools-based ts-ignore check (tools/ removed)" > ts-ignore-report.json
|
||||
continue-on-error: true
|
||||
|
||||
- name: Check for any types
|
||||
id: any-types
|
||||
run: echo "skipping tools-based any-types check (tools/ removed)" > any-types-report.json
|
||||
continue-on-error: true
|
||||
|
||||
- name: Upload type reports
|
||||
uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: type-reports
|
||||
path: |
|
||||
frontends/nextjs/ts-strict-report.json
|
||||
frontends/nextjs/eslint-report.json
|
||||
frontends/nextjs/ts-ignore-report.json
|
||||
frontends/nextjs/any-types-report.json
|
||||
retention-days: 30
|
||||
|
||||
# ============================================================================
|
||||
# QUALITY SUMMARY & REPORTING
|
||||
# ============================================================================
|
||||
quality-summary:
|
||||
name: Quality Metrics Summary
|
||||
runs-on: ubuntu-latest
|
||||
needs: [
|
||||
code-quality,
|
||||
coverage-metrics,
|
||||
security-scan,
|
||||
documentation-quality,
|
||||
performance-metrics,
|
||||
size-metrics,
|
||||
dependency-analysis,
|
||||
type-and-lint-metrics
|
||||
]
|
||||
if: always()
|
||||
defaults:
|
||||
run:
|
||||
working-directory: frontends/nextjs
|
||||
permissions:
|
||||
checks: write
|
||||
pull-requests: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
|
||||
- name: Cache npm dependencies
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
key: npm-deps-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
|
||||
path: |
|
||||
frontends/nextjs/node_modules
|
||||
~/.npm
|
||||
restore-keys: npm-deps-${{ runner.os }}-
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm install --frozen-lockfile
|
||||
|
||||
- name: Download all reports
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: quality-reports/
|
||||
|
||||
- name: Generate quality summary
|
||||
id: summary
|
||||
run: echo "skipping tools-based quality summary generation (tools/ removed)" > quality-summary.md
|
||||
continue-on-error: true
|
||||
|
||||
- name: Post summary as PR comment
|
||||
if: github.event_name == 'pull_request'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
let summaryContent = '';
|
||||
const summaryPath = 'frontends/nextjs/quality-summary.md';
|
||||
if (fs.existsSync(summaryPath)) {
|
||||
summaryContent = fs.readFileSync(summaryPath, 'utf8');
|
||||
}
|
||||
|
||||
const comment = `## 📊 Quality Metrics Report\n\n${summaryContent}\n\n<details><summary>📁 Full Reports (click to expand)</summary>\n\nAll detailed reports are available as build artifacts.\n</details>`;
|
||||
|
||||
github.rest.issues.createComment({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: comment
|
||||
});
|
||||
|
||||
- name: Create check run with summary
|
||||
uses: actions/github-script@v7
|
||||
if: github.event_name == 'pull_request'
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
const summaryPath = 'frontends/nextjs/quality-summary.md';
|
||||
const summary = fs.existsSync(summaryPath)
|
||||
? fs.readFileSync(summaryPath, 'utf8')
|
||||
: 'Quality metrics report generated.';
|
||||
|
||||
github.rest.checks.create({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
name: 'Quality Metrics',
|
||||
head_sha: context.payload.pull_request.head.sha,
|
||||
status: 'completed',
|
||||
conclusion: 'success',
|
||||
summary: 'All quality metrics collected',
|
||||
text: summary
|
||||
});
|
||||
91
.github/workflows/quality/size-limits.yml
vendored
Normal file
91
.github/workflows/quality/size-limits.yml
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
name: Code Size Limits
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'frontends/nextjs/src/**/*.{ts,tsx,js,jsx}'
|
||||
- '.github/workflows/size-limits.yml'
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- 'frontends/nextjs/src/**/*.{ts,tsx,js,jsx}'
|
||||
|
||||
jobs:
|
||||
size-limits:
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: frontends/nextjs
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
|
||||
- name: Cache npm dependencies
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
key: npm-deps-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
|
||||
path: |
|
||||
frontends/nextjs/node_modules
|
||||
~/.npm
|
||||
restore-keys: npm-deps-${{ runner.os }}-
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm install --frozen-lockfile
|
||||
|
||||
- name: Check code size limits
|
||||
run: echo "skipping tools-based size limits enforcement (tools/ removed)"
|
||||
|
||||
- name: Upload report
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: size-limits-report
|
||||
path: frontends/nextjs/size-limits-report.json
|
||||
retention-days: 7
|
||||
|
||||
- name: Comment on PR
|
||||
if: failure() && github.event_name == 'pull_request'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
const report = JSON.parse(fs.readFileSync('frontends/nextjs/size-limits-report.json', 'utf8'));
|
||||
|
||||
let comment = '## 📏 Code Size Limits\n\n';
|
||||
|
||||
if (report.errors === 0 && report.warnings === 0) {
|
||||
comment += '✅ All files pass size limits!';
|
||||
} else {
|
||||
if (report.errors > 0) {
|
||||
comment += `### ❌ Errors (${report.errors})\n`;
|
||||
report.violations
|
||||
.filter(v => v.severity === 'error')
|
||||
.forEach(v => {
|
||||
comment += `- **${v.file}**: ${v.metric} (${v.current} / ${v.limit})\n`;
|
||||
});
|
||||
}
|
||||
|
||||
if (report.warnings > 0) {
|
||||
comment += `\n### ⚠️ Warnings (${report.warnings})\n`;
|
||||
report.violations
|
||||
.filter(v => v.severity === 'warning')
|
||||
.forEach(v => {
|
||||
comment += `- **${v.file}**: ${v.metric} (${v.current} / ${v.limit})\n`;
|
||||
});
|
||||
}
|
||||
|
||||
comment += '\n[See refactoring guide →](../blob/main/docs/REFACTORING_ENFORCEMENT_GUIDE.md)';
|
||||
}
|
||||
|
||||
github.rest.issues.createComment({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: comment
|
||||
});
|
||||
162
.github/workflows/todo-to-issues.yml
vendored
Normal file
162
.github/workflows/todo-to-issues.yml
vendored
Normal file
@@ -0,0 +1,162 @@
|
||||
name: TODO to Issues Sync
|
||||
|
||||
# This workflow can be triggered manually to convert TODO items to GitHub issues
|
||||
# or can be run on a schedule to keep issues in sync with TODO files
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
mode:
|
||||
description: 'Execution mode'
|
||||
required: true
|
||||
type: choice
|
||||
options:
|
||||
- dry-run
|
||||
- export-json
|
||||
- create-issues
|
||||
default: 'dry-run'
|
||||
|
||||
filter_priority:
|
||||
description: 'Filter by priority (leave empty for all)'
|
||||
required: false
|
||||
type: choice
|
||||
options:
|
||||
- ''
|
||||
- critical
|
||||
- high
|
||||
- medium
|
||||
- low
|
||||
|
||||
filter_label:
|
||||
description: 'Filter by label (e.g., security, frontend)'
|
||||
required: false
|
||||
type: string
|
||||
|
||||
exclude_checklist:
|
||||
description: 'Exclude checklist items'
|
||||
required: false
|
||||
type: boolean
|
||||
default: true
|
||||
|
||||
limit:
|
||||
description: 'Limit number of issues (0 for no limit)'
|
||||
required: false
|
||||
type: number
|
||||
default: 0
|
||||
|
||||
# Uncomment to run on a schedule (e.g., weekly)
|
||||
# schedule:
|
||||
# - cron: '0 0 * * 0' # Every Sunday at midnight
|
||||
|
||||
jobs:
|
||||
convert-todos:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.11'
|
||||
|
||||
- name: Install GitHub CLI
|
||||
run: |
|
||||
type -p curl >/dev/null || (sudo apt update && sudo apt install curl -y)
|
||||
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg \
|
||||
&& sudo chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg \
|
||||
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null \
|
||||
&& sudo apt update \
|
||||
&& sudo apt install gh -y
|
||||
|
||||
- name: Authenticate GitHub CLI
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
echo "$GH_TOKEN" | gh auth login --with-token
|
||||
gh auth status
|
||||
|
||||
- name: Build command arguments
|
||||
id: args
|
||||
run: |
|
||||
ARGS=""
|
||||
|
||||
# Add mode
|
||||
if [ "${{ inputs.mode }}" = "dry-run" ]; then
|
||||
ARGS="$ARGS --dry-run"
|
||||
elif [ "${{ inputs.mode }}" = "export-json" ]; then
|
||||
ARGS="$ARGS --output todos-export.json"
|
||||
elif [ "${{ inputs.mode }}" = "create-issues" ]; then
|
||||
ARGS="$ARGS --create"
|
||||
fi
|
||||
|
||||
# Add filters
|
||||
if [ -n "${{ inputs.filter_priority }}" ]; then
|
||||
ARGS="$ARGS --filter-priority ${{ inputs.filter_priority }}"
|
||||
fi
|
||||
|
||||
if [ -n "${{ inputs.filter_label }}" ]; then
|
||||
ARGS="$ARGS --filter-label ${{ inputs.filter_label }}"
|
||||
fi
|
||||
|
||||
if [ "${{ inputs.exclude_checklist }}" = "true" ]; then
|
||||
ARGS="$ARGS --exclude-checklist"
|
||||
fi
|
||||
|
||||
# Add limit if specified
|
||||
if [ "${{ inputs.limit }}" != "0" ]; then
|
||||
ARGS="$ARGS --limit ${{ inputs.limit }}"
|
||||
fi
|
||||
|
||||
echo "args=$ARGS" >> $GITHUB_OUTPUT
|
||||
echo "Command arguments: $ARGS"
|
||||
|
||||
- name: Run populate-kanban script
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
echo "skipping tools-based populate-kanban (tools/ removed)"
|
||||
|
||||
- name: Upload JSON export (if applicable)
|
||||
if: inputs.mode == 'export-json'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: todos-export
|
||||
path: todos-export.json
|
||||
retention-days: 30
|
||||
|
||||
- name: Create summary
|
||||
if: always()
|
||||
run: |
|
||||
echo "## TODO to Issues Conversion" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**Mode:** ${{ inputs.mode }}" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
if [ -n "${{ inputs.filter_priority }}" ]; then
|
||||
echo "**Priority Filter:** ${{ inputs.filter_priority }}" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
if [ -n "${{ inputs.filter_label }}" ]; then
|
||||
echo "**Label Filter:** ${{ inputs.filter_label }}" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
if [ "${{ inputs.exclude_checklist }}" = "true" ]; then
|
||||
echo "**Checklist Items:** Excluded" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
if [ "${{ inputs.limit }}" != "0" ]; then
|
||||
echo "**Limit:** ${{ inputs.limit }} items" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
if [ "${{ inputs.mode }}" = "export-json" ]; then
|
||||
echo "✅ JSON export created successfully" >> $GITHUB_STEP_SUMMARY
|
||||
echo "Download the artifact from the workflow run page" >> $GITHUB_STEP_SUMMARY
|
||||
elif [ "${{ inputs.mode }}" = "create-issues" ]; then
|
||||
echo "✅ GitHub issues created successfully" >> $GITHUB_STEP_SUMMARY
|
||||
echo "View issues: https://github.com/${{ github.repository }}/issues" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "ℹ️ Dry run completed - no issues created" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
198
.github/workflows/triage.yml
vendored
Normal file
198
.github/workflows/triage.yml
vendored
Normal file
@@ -0,0 +1,198 @@
|
||||
name: Issue and PR Triage
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened, edited, reopened]
|
||||
pull_request:
|
||||
types: [opened, reopened, synchronize, edited]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
triage-issue:
|
||||
name: Triage Issues
|
||||
if: github.event_name == 'issues'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Categorize and label issue
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const issue = context.payload.issue;
|
||||
const title = (issue.title || '').toLowerCase();
|
||||
const body = (issue.body || '').toLowerCase();
|
||||
const text = `${title}\n${body}`;
|
||||
|
||||
const labels = new Set();
|
||||
const missing = [];
|
||||
|
||||
const typeMatchers = [
|
||||
{ regex: /bug|error|crash|broken|fail/, label: 'bug' },
|
||||
{ regex: /feature|enhancement|add|new|implement/, label: 'enhancement' },
|
||||
{ regex: /document|readme|docs|guide/, label: 'documentation' },
|
||||
{ regex: /test|testing|spec|e2e/, label: 'testing' },
|
||||
{ regex: /security|vulnerability|exploit|xss|sql/, label: 'security' },
|
||||
{ regex: /performance|slow|optimize|speed/, label: 'performance' },
|
||||
];
|
||||
|
||||
for (const match of typeMatchers) {
|
||||
if (text.match(match.regex)) {
|
||||
labels.add(match.label);
|
||||
}
|
||||
}
|
||||
|
||||
const areaMatchers = [
|
||||
{ regex: /frontend|react|next|ui|component|browser/, label: 'area: frontend' },
|
||||
{ regex: /api|backend|service|server/, label: 'area: backend' },
|
||||
{ regex: /database|prisma|schema|sql/, label: 'area: database' },
|
||||
{ regex: /workflow|github actions|ci|pipeline/, label: 'area: workflows' },
|
||||
{ regex: /docs|readme|guide/, label: 'area: documentation' },
|
||||
];
|
||||
|
||||
for (const match of areaMatchers) {
|
||||
if (text.match(match.regex)) {
|
||||
labels.add(match.label);
|
||||
}
|
||||
}
|
||||
|
||||
if (text.match(/critical|urgent|asap|blocker/)) {
|
||||
labels.add('priority: high');
|
||||
} else if (text.match(/minor|low|nice to have/)) {
|
||||
labels.add('priority: low');
|
||||
} else {
|
||||
labels.add('priority: medium');
|
||||
}
|
||||
|
||||
if (text.match(/beginner|easy|simple|starter/) || labels.size <= 2) {
|
||||
labels.add('good first issue');
|
||||
}
|
||||
|
||||
const reproductionHints = ['steps to reproduce', 'expected', 'actual'];
|
||||
for (const hint of reproductionHints) {
|
||||
if (!body.includes(hint)) {
|
||||
missing.push(hint);
|
||||
}
|
||||
}
|
||||
|
||||
const supportInfo = body.includes('version') || body.match(/v\d+\.\d+/);
|
||||
if (!supportInfo) {
|
||||
missing.push('version information');
|
||||
}
|
||||
|
||||
if (labels.size > 0) {
|
||||
await github.rest.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue.number,
|
||||
labels: Array.from(labels),
|
||||
}).catch(e => console.log('Some labels may not exist:', e.message));
|
||||
}
|
||||
|
||||
const checklist = missing.map(item => `- [ ] Add ${item}`).join('\n') || '- [x] Description includes key details.';
|
||||
const summary = Array.from(labels).map(l => `- ${l}`).join('\n') || '- No labels inferred yet.';
|
||||
|
||||
const comment = [
|
||||
'👋 Thanks for reporting an issue! I ran a quick triage:',
|
||||
'',
|
||||
'**Proposed labels:**',
|
||||
summary,
|
||||
'',
|
||||
'**Missing details:**',
|
||||
checklist,
|
||||
'',
|
||||
'Adding the missing details will help reviewers respond faster. If the proposed labels look wrong, feel free to update them.',
|
||||
'',
|
||||
'@copilot Please review this triage and refine labels or request any additional context needed—no Codex webhooks involved.'
|
||||
].join('\n');
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue.number,
|
||||
body: comment,
|
||||
});
|
||||
|
||||
triage-pr:
|
||||
name: Triage Pull Requests
|
||||
if: github.event_name == 'pull_request'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Analyze PR files and label
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const pr = context.payload.pull_request;
|
||||
const { data: files } = await github.rest.pulls.listFiles({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: pr.number,
|
||||
});
|
||||
|
||||
const labels = new Set();
|
||||
|
||||
const fileFlags = {
|
||||
workflows: files.some(f => f.filename.includes('.github/workflows')),
|
||||
docs: files.some(f => f.filename.match(/\.(md|mdx)$/) || f.filename.startsWith('docs/')),
|
||||
frontend: files.some(f => f.filename.includes('frontends/nextjs')),
|
||||
db: files.some(f => f.filename.includes('prisma/') || f.filename.includes('dbal/')),
|
||||
tests: files.some(f => f.filename.match(/(test|spec)\.[jt]sx?/)),
|
||||
};
|
||||
|
||||
if (fileFlags.workflows) labels.add('area: workflows');
|
||||
if (fileFlags.docs) labels.add('area: documentation');
|
||||
if (fileFlags.frontend) labels.add('area: frontend');
|
||||
if (fileFlags.db) labels.add('area: database');
|
||||
if (fileFlags.tests) labels.add('tests');
|
||||
|
||||
const totalChanges = files.reduce((sum, f) => sum + f.additions + f.deletions, 0);
|
||||
const highRiskPaths = files.filter(f => f.filename.includes('.github/workflows') || f.filename.includes('prisma/'));
|
||||
|
||||
let riskLabel = 'risk: low';
|
||||
if (highRiskPaths.length > 0 || totalChanges >= 400) {
|
||||
riskLabel = 'risk: high';
|
||||
} else if (totalChanges >= 150) {
|
||||
riskLabel = 'risk: medium';
|
||||
}
|
||||
labels.add(riskLabel);
|
||||
|
||||
const missing = [];
|
||||
const body = (pr.body || '').toLowerCase();
|
||||
if (!body.includes('test')) missing.push('Test plan');
|
||||
if (fileFlags.frontend && !body.includes('screenshot')) missing.push('Screenshots for UI changes');
|
||||
if (!body.match(/#\d+|https:\/\/github\.com/)) missing.push('Linked issue reference');
|
||||
|
||||
if (labels.size > 0) {
|
||||
await github.rest.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: pr.number,
|
||||
labels: Array.from(labels),
|
||||
}).catch(e => console.log('Some labels may not exist:', e.message));
|
||||
}
|
||||
|
||||
const labelSummary = Array.from(labels).map(l => `- ${l}`).join('\n');
|
||||
const missingList = missing.length ? missing.map(item => `- [ ] ${item}`).join('\n') : '- [x] Description includes required context.';
|
||||
|
||||
const comment = [
|
||||
'🤖 **Automated PR triage**',
|
||||
'',
|
||||
'**Proposed labels:**',
|
||||
labelSummary,
|
||||
'',
|
||||
'**Description check:**',
|
||||
missingList,
|
||||
'',
|
||||
'If any labels look incorrect, feel free to adjust them. Closing the missing items will help reviewers move faster.',
|
||||
'',
|
||||
'@copilot Please double-check this triage (no Codex webhook) and add any extra labels or questions for the author.'
|
||||
].join('\n');
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: pr.number,
|
||||
body: comment,
|
||||
});
|
||||
217
.gitignore
vendored
217
.gitignore
vendored
@@ -1,118 +1,103 @@
|
||||
# Python
|
||||
.venv/
|
||||
venv/
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# Node.js
|
||||
node_modules/
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
.pnp
|
||||
.pnp.js
|
||||
|
||||
# Build outputs
|
||||
dist/
|
||||
dist-ssr/
|
||||
*-dist/
|
||||
build/
|
||||
.next/
|
||||
out/
|
||||
next-env.d.ts
|
||||
*.local
|
||||
|
||||
# Environment
|
||||
.env
|
||||
.env.local
|
||||
.env.*.local
|
||||
.secrets
|
||||
|
||||
# Editor
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
!.vscode/settings.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/tasks.json
|
||||
.idea/
|
||||
*.sublime-project
|
||||
*.sublime-workspace
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
*~
|
||||
|
||||
# IDE/Development
|
||||
.devcontainer/
|
||||
.spark-workbench-id
|
||||
.spark-initial-sha
|
||||
_codeql_detected_source_root/
|
||||
.worktrees/
|
||||
|
||||
# Database
|
||||
prisma/dev.db
|
||||
prisma/dev.db-journal
|
||||
*.db
|
||||
*.sqlite
|
||||
|
||||
# Re-track project SQLite databases
|
||||
!docs/docs.db
|
||||
!txt/reports.db
|
||||
*.sqlite3
|
||||
|
||||
# Generated Prisma schema (produced by dbal/shared/tools/codegen/gen_prisma_schema.js)
|
||||
dbal/shared/prisma/
|
||||
|
||||
# Testing
|
||||
/test-results/
|
||||
/playwright-report/
|
||||
/playwright/.cache/
|
||||
/e2e-results/
|
||||
*.spec.js.map
|
||||
*.spec.ts.map
|
||||
coverage/
|
||||
.nyc_output/
|
||||
|
||||
# Logs
|
||||
logs/
|
||||
*.log
|
||||
!frontends/nextjs/src/app/api/github/actions/runs/\[runId\]/logs/
|
||||
!frontends/nextjs/src/app/api/github/actions/runs/\[runId\]/logs/route.ts
|
||||
|
||||
# Cache/Temp
|
||||
pids/
|
||||
.file-manifest
|
||||
lint-output.txt
|
||||
.turbo/
|
||||
|
||||
# Analysis outputs
|
||||
stub-patterns.json
|
||||
complexity-report.json
|
||||
|
||||
# TODO management
|
||||
todos-baseline.json
|
||||
todos-export.json
|
||||
todos*.json
|
||||
|
||||
# Project-specific
|
||||
**/agent-eval-report*
|
||||
vite.config.ts.bak*
|
||||
.cache/
|
||||
dist-old/
|
||||
# Python
|
||||
.venv/
|
||||
venv/
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# Node.js
|
||||
node_modules/
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
.pnp
|
||||
.pnp.js
|
||||
|
||||
# Build outputs
|
||||
dist/
|
||||
dist-ssr/
|
||||
*-dist/
|
||||
build/
|
||||
.next/
|
||||
out/
|
||||
next-env.d.ts
|
||||
*.local
|
||||
|
||||
# Environment
|
||||
.env
|
||||
.env.local
|
||||
.env.*.local
|
||||
.secrets
|
||||
|
||||
# Editor
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
!.vscode/settings.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/tasks.json
|
||||
.idea/
|
||||
*.sublime-project
|
||||
*.sublime-workspace
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
*~
|
||||
|
||||
# IDE/Development
|
||||
.devcontainer/
|
||||
.spark-workbench-id
|
||||
.spark-initial-sha
|
||||
_codeql_detected_source_root/
|
||||
|
||||
# Database
|
||||
prisma/dev.db
|
||||
prisma/dev.db-journal
|
||||
*.db
|
||||
*.sqlite
|
||||
*.sqlite3
|
||||
|
||||
# Testing
|
||||
/test-results/
|
||||
/playwright-report/
|
||||
/playwright/.cache/
|
||||
/e2e-results/
|
||||
*.spec.js.map
|
||||
*.spec.ts.map
|
||||
coverage/
|
||||
.nyc_output/
|
||||
|
||||
# Logs
|
||||
logs/
|
||||
*.log
|
||||
!frontends/nextjs/src/app/api/github/actions/runs/\[runId\]/logs/
|
||||
!frontends/nextjs/src/app/api/github/actions/runs/\[runId\]/logs/route.ts
|
||||
|
||||
# Cache/Temp
|
||||
pids/
|
||||
.file-manifest
|
||||
lint-output.txt
|
||||
.turbo/
|
||||
|
||||
# Analysis outputs
|
||||
stub-patterns.json
|
||||
complexity-report.json
|
||||
|
||||
# TODO management
|
||||
todos-baseline.json
|
||||
todos-export.json
|
||||
todos*.json
|
||||
|
||||
# Project-specific
|
||||
**/agent-eval-report*
|
||||
vite.config.ts.bak*
|
||||
.cache/
|
||||
dist-old/
|
||||
.vscode/claudesync.json
|
||||
**/package-lock.json
|
||||
/package-lock.json
|
||||
bun.lockb
|
||||
|
||||
# CodeQL local databases
|
||||
.codeql-dbs/
|
||||
.codeql-db/
|
||||
/.claude/worktrees
|
||||
*.tsbuildinfo
|
||||
# frontends/pastebin/public/pyodide/ # kept in fat repo
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
image: node:20-bullseye
|
||||
|
||||
stages:
|
||||
- lint
|
||||
- test
|
||||
- build
|
||||
|
||||
cache:
|
||||
key: ${CI_COMMIT_REF_SLUG}
|
||||
paths:
|
||||
- .npm/
|
||||
|
||||
variables:
|
||||
NPM_CONFIG_CACHE: $CI_PROJECT_DIR/.npm
|
||||
|
||||
before_script:
|
||||
- npm ci
|
||||
|
||||
lint:
|
||||
stage: lint
|
||||
script:
|
||||
- npm run lint
|
||||
|
||||
typecheck:
|
||||
stage: test
|
||||
script:
|
||||
- npm run typecheck
|
||||
|
||||
unit_tests:
|
||||
stage: test
|
||||
script:
|
||||
- npm test
|
||||
|
||||
build:
|
||||
stage: build
|
||||
script:
|
||||
- npm run build
|
||||
50
.npmrc
50
.npmrc
@@ -1,50 +0,0 @@
|
||||
# NPM Configuration for MetaBuilder
|
||||
# Last Updated: 2026-01-23
|
||||
|
||||
# PACKAGE RESOLUTION
|
||||
# Use the default npm registry
|
||||
registry=https://registry.npmjs.org/
|
||||
|
||||
# AUDIT SETTINGS
|
||||
# Report security vulnerabilities
|
||||
audit-level=moderate
|
||||
|
||||
# VERSION MATCHING
|
||||
# Use caret ranges for flexibility (^version)
|
||||
# This allows minor/patch updates while locking major version
|
||||
save-prefix=^
|
||||
|
||||
# OPTIONAL DEPENDENCIES
|
||||
# Don't fail if optional dependencies aren't available
|
||||
ignore-scripts=false
|
||||
|
||||
# WORKSPACE SETTINGS
|
||||
# Enable workspace protocol for monorepo linking
|
||||
workspaces-update=true
|
||||
|
||||
# BUILD SETTINGS
|
||||
# Use standard npm, not yarn or pnpm
|
||||
# (This is implicit but documented for clarity)
|
||||
|
||||
# PROXY SETTINGS (uncomment if behind corporate proxy)
|
||||
# http-proxy=http://proxy.example.com:8080
|
||||
# https-proxy=https://proxy.example.com:8443
|
||||
# no-proxy=.example.com,localhost,127.0.0.1
|
||||
|
||||
# LOCAL NEXUS REGISTRY (uncomment to use patched packages from Nexus)
|
||||
# Nexus npm-group merges npm-hosted (patched) + npm-proxy (npmjs.org cache)
|
||||
# Start Nexus: cd deployment && docker compose -f docker-compose.nexus.yml up -d
|
||||
# Publish patches: cd deployment && ./publish-npm-patches.sh
|
||||
# registry=http://localhost:8091/repository/npm-group/
|
||||
# //localhost:8091/repository/npm-hosted/:_auth=YWRtaW46bmV4dXM=
|
||||
|
||||
# NODE/NPM VERSION REQUIREMENTS
|
||||
# These are documented in package.json engines field
|
||||
# Current: Node 22.22.1, npm 11.11.0
|
||||
|
||||
# SCOPED VERDACCIO REGISTRY - @esbuild-kit patched packages
|
||||
# Local dev: npx verdaccio --config deployment/verdaccio.yaml &
|
||||
# bash deployment/publish-npm-patches.sh --verdaccio
|
||||
# CI: started automatically via .github/actions/setup-npm composite action
|
||||
@esbuild-kit:registry=http://localhost:4873/
|
||||
//localhost:4873/:_authToken=
|
||||
@@ -1,47 +0,0 @@
|
||||
---
|
||||
name: MetaBuilder Roadmap Implementer
|
||||
type: knowledge
|
||||
version: 1.0.0
|
||||
agent: CodeActAgent
|
||||
triggers: []
|
||||
---
|
||||
|
||||
Purpose
|
||||
- Implement features described in ROADMAP.md and README.md.
|
||||
- Keep both ROADMAP.md and README.md up to date as work progresses.
|
||||
- Write and maintain Playwright E2E tests and unit tests.
|
||||
- Follow the existing code style and project conventions.
|
||||
- Use the existing JSON Schemas; they are mostly correct, do not modify schema definitions unless explicitly required by failing validation.
|
||||
- Index the repository for quick navigation and make concise implementation notes.
|
||||
- Align styling to match the old/ directory while using plain SASS files (no CSS-in-JS).
|
||||
|
||||
Scope and Guidance
|
||||
- Source of truth for planned features: ROADMAP.md. Ensure README.md reflects any implemented capabilities or usage changes.
|
||||
- Respect repository structure: prefer packages/, services/, frontends/, and dbal/ conventions already present. Avoid ad-hoc new folders.
|
||||
- Testing:
|
||||
- Unit tests: colocate or follow existing spec/ patterns.
|
||||
- E2E: use Playwright per playwright.config.ts and the e2e/ folder conventions.
|
||||
- Ensure new features include adequate test coverage and run locally before committing.
|
||||
- Code style:
|
||||
- Run the project linters/formatters defined in package.json scripts.
|
||||
- Keep TypeScript strictness and fix type warnings instead of suppressing them.
|
||||
- JSON Schema:
|
||||
- Validate inputs against existing schemas in schemas/; do not overhaul schemas unless necessary.
|
||||
- Styles:
|
||||
- Use plain SASS (.scss) and mirror patterns from old/ to maintain visual continuity.
|
||||
|
||||
Operational Steps When Executing
|
||||
1) Parse ROADMAP.md items and pick an actionable task.
|
||||
2) Implement minimal code to satisfy the task; keep changes focused.
|
||||
3) Update README.md and ROADMAP.md checkboxes/status to reflect progress.
|
||||
4) Add/adjust unit tests and Playwright tests to cover the change.
|
||||
5) Run lint, typecheck, and tests; fix issues.
|
||||
6) Commit with a clear message referencing the task.
|
||||
|
||||
Notes and Indexing
|
||||
- Maintain brief notes with references to key files you touched. Prefer adding developer notes to docs/ if appropriate, otherwise keep ephemeral notes out of VCS.
|
||||
|
||||
Limitations
|
||||
- No triggers defined; manual invocation only.
|
||||
- Does not modify JSON schemas unless validation requires it.
|
||||
|
||||
@@ -1,119 +0,0 @@
|
||||
- generic [active] [ref=e1]:
|
||||
- generic [ref=e3]:
|
||||
- generic [ref=e6]:
|
||||
- generic [ref=e7]:
|
||||
- heading "Navigation" [level=2] [ref=e8]
|
||||
- generic [ref=e9]:
|
||||
- button "Expand All" [ref=e10]
|
||||
- button "Collapse All" [ref=e11]
|
||||
- generic [ref=e15]:
|
||||
- generic [ref=e16]:
|
||||
- button "Overview 1" [ref=e17]:
|
||||
- img [ref=e18]
|
||||
- heading "Overview" [level=3] [ref=e20]
|
||||
- generic [ref=e21]: "1"
|
||||
- button "Dashboard" [ref=e24]:
|
||||
- generic [ref=e25]: Dashboard
|
||||
- generic [ref=e26]:
|
||||
- button "Development 4" [ref=e27]:
|
||||
- img [ref=e28]
|
||||
- heading "Development" [level=3] [ref=e30]
|
||||
- generic [ref=e31]: "4"
|
||||
- generic [ref=e32]:
|
||||
- button "Code Editor" [ref=e34]:
|
||||
- generic [ref=e35]: Code Editor
|
||||
- button "Models" [ref=e37]:
|
||||
- generic [ref=e38]: Models
|
||||
- button "Components" [ref=e40]:
|
||||
- generic [ref=e41]: Components
|
||||
- button "Component Trees" [ref=e43]:
|
||||
- generic [ref=e44]: Component Trees
|
||||
- generic [ref=e45]:
|
||||
- button "Automation 2" [ref=e46]:
|
||||
- img [ref=e47]
|
||||
- heading "Automation" [level=3] [ref=e49]
|
||||
- generic [ref=e50]: "2"
|
||||
- generic [ref=e51]:
|
||||
- button "Workflows" [ref=e53]:
|
||||
- generic [ref=e54]: Workflows
|
||||
- button "Lambdas" [ref=e56]:
|
||||
- generic [ref=e57]: Lambdas
|
||||
- generic [ref=e58]:
|
||||
- button "Design & Styling 6" [ref=e59]:
|
||||
- img [ref=e60]
|
||||
- heading "Design & Styling" [level=3] [ref=e62]
|
||||
- generic [ref=e63]: "6"
|
||||
- generic [ref=e64]:
|
||||
- button "Styling" [ref=e66]:
|
||||
- generic [ref=e67]: Styling
|
||||
- button "Sass Styles" [ref=e69]:
|
||||
- generic [ref=e70]: Sass Styles
|
||||
- button "Favicon Designer" [ref=e72]:
|
||||
- generic [ref=e73]: Favicon Designer
|
||||
- button "Feature Ideas" [ref=e75]:
|
||||
- generic [ref=e76]: Feature Ideas
|
||||
- button "Schema Editor" [ref=e78]:
|
||||
- generic [ref=e79]: Schema Editor
|
||||
- button "JSON UI" [ref=e81]:
|
||||
- generic [ref=e82]: JSON UI
|
||||
- generic [ref=e83]:
|
||||
- button "Backend 1" [ref=e84]:
|
||||
- img [ref=e85]
|
||||
- heading "Backend" [level=3] [ref=e87]
|
||||
- generic [ref=e88]: "1"
|
||||
- button "Flask API" [ref=e91]:
|
||||
- generic [ref=e92]: Flask API
|
||||
- generic [ref=e93]:
|
||||
- button "Testing 3" [ref=e94]:
|
||||
- img [ref=e95]
|
||||
- heading "Testing" [level=3] [ref=e97]
|
||||
- generic [ref=e98]: "3"
|
||||
- generic [ref=e99]:
|
||||
- button "Playwright" [ref=e101]:
|
||||
- generic [ref=e102]: Playwright
|
||||
- button "Storybook" [ref=e104]:
|
||||
- generic [ref=e105]: Storybook
|
||||
- button "Unit Tests" [ref=e107]:
|
||||
- generic [ref=e108]: Unit Tests
|
||||
- generic [ref=e109]:
|
||||
- button "Tools & Configuration 6" [ref=e110]:
|
||||
- img [ref=e111]
|
||||
- heading "Tools & Configuration" [level=3] [ref=e113]
|
||||
- generic [ref=e114]: "6"
|
||||
- generic [ref=e115]:
|
||||
- button "Error Repair" [ref=e117]:
|
||||
- generic [ref=e118]: Error Repair
|
||||
- button "Documentation" [ref=e120]:
|
||||
- generic [ref=e121]: Documentation
|
||||
- button "JSON Conversion Showcase" [ref=e123]:
|
||||
- generic [ref=e124]: JSON Conversion Showcase
|
||||
- button "Settings" [ref=e126]:
|
||||
- generic [ref=e127]: Settings
|
||||
- button "PWA" [ref=e129]:
|
||||
- generic [ref=e130]: PWA
|
||||
- button "Features" [ref=e132]:
|
||||
- generic [ref=e133]: Features
|
||||
- main [ref=e134]:
|
||||
- generic [ref=e135]:
|
||||
- generic [ref=e136]: layers
|
||||
- generic [ref=e138]:
|
||||
- generic [ref=e139]:
|
||||
- heading "Project Dashboard" [level=1] [ref=e140]
|
||||
- paragraph [ref=e141]: Overview of your CodeForge project
|
||||
- generic [ref=e142]:
|
||||
- generic [ref=e143]:
|
||||
- generic [ref=e145]:
|
||||
- img [ref=e147]
|
||||
- text: Project Completeness
|
||||
- generic [ref=e150]:
|
||||
- generic [ref=e152]: 30%
|
||||
- generic [ref=e153]: In Progress
|
||||
- progressbar [ref=e154]
|
||||
- paragraph [ref=e156]: Just getting started. Add some components and models.
|
||||
- generic [ref=e157]:
|
||||
- generic [ref=e159]: GitHub Build Status
|
||||
- generic [ref=e161]: "Custom component: GitHubBuildStatus"
|
||||
- generic [ref=e162]:
|
||||
- heading "Command Palette" [level=2] [ref=e163]
|
||||
- paragraph [ref=e164]: Search for a command to run...
|
||||
- alert [ref=e165]
|
||||
@@ -1,119 +0,0 @@
|
||||
- generic [active] [ref=e1]:
|
||||
- generic [ref=e3]:
|
||||
- generic [ref=e6]:
|
||||
- generic [ref=e7]:
|
||||
- heading "Navigation" [level=2] [ref=e8]
|
||||
- generic [ref=e9]:
|
||||
- button "Expand All" [ref=e10]
|
||||
- button "Collapse All" [ref=e11]
|
||||
- generic [ref=e15]:
|
||||
- generic [ref=e16]:
|
||||
- button "Overview 1" [ref=e17]:
|
||||
- img [ref=e18]
|
||||
- heading "Overview" [level=3] [ref=e20]
|
||||
- generic [ref=e21]: "1"
|
||||
- button "Dashboard" [ref=e24]:
|
||||
- generic [ref=e25]: Dashboard
|
||||
- generic [ref=e26]:
|
||||
- button "Development 4" [ref=e27]:
|
||||
- img [ref=e28]
|
||||
- heading "Development" [level=3] [ref=e30]
|
||||
- generic [ref=e31]: "4"
|
||||
- generic [ref=e32]:
|
||||
- button "Code Editor" [ref=e34]:
|
||||
- generic [ref=e35]: Code Editor
|
||||
- button "Models" [ref=e37]:
|
||||
- generic [ref=e38]: Models
|
||||
- button "Components" [ref=e40]:
|
||||
- generic [ref=e41]: Components
|
||||
- button "Component Trees" [ref=e43]:
|
||||
- generic [ref=e44]: Component Trees
|
||||
- generic [ref=e45]:
|
||||
- button "Automation 2" [ref=e46]:
|
||||
- img [ref=e47]
|
||||
- heading "Automation" [level=3] [ref=e49]
|
||||
- generic [ref=e50]: "2"
|
||||
- generic [ref=e51]:
|
||||
- button "Workflows" [ref=e53]:
|
||||
- generic [ref=e54]: Workflows
|
||||
- button "Lambdas" [ref=e56]:
|
||||
- generic [ref=e57]: Lambdas
|
||||
- generic [ref=e58]:
|
||||
- button "Design & Styling 6" [ref=e59]:
|
||||
- img [ref=e60]
|
||||
- heading "Design & Styling" [level=3] [ref=e62]
|
||||
- generic [ref=e63]: "6"
|
||||
- generic [ref=e64]:
|
||||
- button "Styling" [ref=e66]:
|
||||
- generic [ref=e67]: Styling
|
||||
- button "Sass Styles" [ref=e69]:
|
||||
- generic [ref=e70]: Sass Styles
|
||||
- button "Favicon Designer" [ref=e72]:
|
||||
- generic [ref=e73]: Favicon Designer
|
||||
- button "Feature Ideas" [ref=e75]:
|
||||
- generic [ref=e76]: Feature Ideas
|
||||
- button "Schema Editor" [ref=e78]:
|
||||
- generic [ref=e79]: Schema Editor
|
||||
- button "JSON UI" [ref=e81]:
|
||||
- generic [ref=e82]: JSON UI
|
||||
- generic [ref=e83]:
|
||||
- button "Backend 1" [ref=e84]:
|
||||
- img [ref=e85]
|
||||
- heading "Backend" [level=3] [ref=e87]
|
||||
- generic [ref=e88]: "1"
|
||||
- button "Flask API" [ref=e91]:
|
||||
- generic [ref=e92]: Flask API
|
||||
- generic [ref=e93]:
|
||||
- button "Testing 3" [ref=e94]:
|
||||
- img [ref=e95]
|
||||
- heading "Testing" [level=3] [ref=e97]
|
||||
- generic [ref=e98]: "3"
|
||||
- generic [ref=e99]:
|
||||
- button "Playwright" [ref=e101]:
|
||||
- generic [ref=e102]: Playwright
|
||||
- button "Storybook" [ref=e104]:
|
||||
- generic [ref=e105]: Storybook
|
||||
- button "Unit Tests" [ref=e107]:
|
||||
- generic [ref=e108]: Unit Tests
|
||||
- generic [ref=e109]:
|
||||
- button "Tools & Configuration 6" [ref=e110]:
|
||||
- img [ref=e111]
|
||||
- heading "Tools & Configuration" [level=3] [ref=e113]
|
||||
- generic [ref=e114]: "6"
|
||||
- generic [ref=e115]:
|
||||
- button "Error Repair" [ref=e117]:
|
||||
- generic [ref=e118]: Error Repair
|
||||
- button "Documentation" [ref=e120]:
|
||||
- generic [ref=e121]: Documentation
|
||||
- button "JSON Conversion Showcase" [ref=e123]:
|
||||
- generic [ref=e124]: JSON Conversion Showcase
|
||||
- button "Settings" [ref=e126]:
|
||||
- generic [ref=e127]: Settings
|
||||
- button "PWA" [ref=e129]:
|
||||
- generic [ref=e130]: PWA
|
||||
- button "Features" [ref=e132]:
|
||||
- generic [ref=e133]: Features
|
||||
- main [ref=e134]:
|
||||
- generic [ref=e135]:
|
||||
- generic [ref=e136]: layers
|
||||
- generic [ref=e138]:
|
||||
- generic [ref=e139]:
|
||||
- heading "Project Dashboard" [level=1] [ref=e140]
|
||||
- paragraph [ref=e141]: Overview of your CodeForge project
|
||||
- generic [ref=e142]:
|
||||
- generic [ref=e143]:
|
||||
- generic [ref=e145]:
|
||||
- img [ref=e147]
|
||||
- text: Project Completeness
|
||||
- generic [ref=e150]:
|
||||
- generic [ref=e152]: 30%
|
||||
- generic [ref=e153]: In Progress
|
||||
- progressbar [ref=e154]
|
||||
- paragraph [ref=e156]: Just getting started. Add some components and models.
|
||||
- generic [ref=e157]:
|
||||
- generic [ref=e159]: GitHub Build Status
|
||||
- generic [ref=e161]: "Custom component: GitHubBuildStatus"
|
||||
- generic [ref=e162]:
|
||||
- heading "Command Palette" [level=2] [ref=e163]
|
||||
- paragraph [ref=e164]: Search for a command to run...
|
||||
- alert [ref=e165]
|
||||
@@ -1,7 +0,0 @@
|
||||
- generic [active] [ref=e1]:
|
||||
- generic [ref=e4]:
|
||||
- heading "404" [level=1] [ref=e5]
|
||||
- paragraph [ref=e6]: Page not found
|
||||
- link "Go to CodeForge" [ref=e7] [cursor=pointer]:
|
||||
- /url: /codegen/
|
||||
- alert [ref=e8]
|
||||
@@ -1,25 +0,0 @@
|
||||
- generic [active] [ref=e1]:
|
||||
- generic [ref=e3]:
|
||||
- img [ref=e4]
|
||||
- main [ref=e6]:
|
||||
- generic [ref=e11]:
|
||||
- generic [ref=e12]:
|
||||
- heading "Project Dashboard" [level=1] [ref=e13]
|
||||
- paragraph [ref=e14]: Overview of your CodeForge project
|
||||
- generic [ref=e15]:
|
||||
- generic [ref=e16]:
|
||||
- generic [ref=e18]:
|
||||
- img [ref=e20]
|
||||
- text: Project Completeness
|
||||
- generic [ref=e23]:
|
||||
- generic [ref=e24]: 30%
|
||||
- text: In Progress
|
||||
- progressbar
|
||||
- paragraph [ref=e25]: Just getting started. Add some components and models.
|
||||
- generic [ref=e26]:
|
||||
- generic [ref=e28]: GitHub Build Status
|
||||
- generic [ref=e30]: "Custom component: GitHubBuildStatus"
|
||||
- generic [ref=e32]:
|
||||
- heading "Command Palette" [level=2] [ref=e33]
|
||||
- paragraph [ref=e34]: Search for a command to run...
|
||||
- alert [ref=e35]
|
||||
@@ -1,25 +0,0 @@
|
||||
- generic [active] [ref=e1]:
|
||||
- generic [ref=e3]:
|
||||
- img [ref=e4]
|
||||
- main [ref=e6]:
|
||||
- generic [ref=e11]:
|
||||
- generic [ref=e12]:
|
||||
- heading "Project Dashboard" [level=1] [ref=e13]
|
||||
- paragraph [ref=e14]: Overview of your CodeForge project
|
||||
- generic [ref=e15]:
|
||||
- generic [ref=e16]:
|
||||
- generic [ref=e18]:
|
||||
- img [ref=e20]
|
||||
- text: Project Completeness
|
||||
- generic [ref=e23]:
|
||||
- generic [ref=e24]: 30%
|
||||
- text: In Progress
|
||||
- progressbar
|
||||
- paragraph [ref=e25]: Just getting started. Add some components and models.
|
||||
- generic [ref=e26]:
|
||||
- generic [ref=e28]: GitHub Build Status
|
||||
- generic [ref=e30]: "Custom component: GitHubBuildStatus"
|
||||
- generic [ref=e32]:
|
||||
- heading "Command Palette" [level=2] [ref=e33]
|
||||
- paragraph [ref=e34]: Search for a command to run...
|
||||
- alert [ref=e35]
|
||||
@@ -1,156 +0,0 @@
|
||||
- generic [active] [ref=e1]:
|
||||
- generic [ref=e3]:
|
||||
- banner [ref=e4]:
|
||||
- generic [ref=e5]:
|
||||
- button "Toggle sidebar" [expanded] [ref=e6] [cursor=pointer]:
|
||||
- generic [ref=e7]: menu
|
||||
- generic [ref=e8]:
|
||||
- generic [ref=e9]: code
|
||||
- heading "CodeForge" [level=1] [ref=e10]
|
||||
- button "Switch to dark mode" [ref=e12] [cursor=pointer]:
|
||||
- generic [ref=e13]: dark_mode
|
||||
- generic [ref=e14]:
|
||||
- complementary "Navigation sidebar" [ref=e15]:
|
||||
- paragraph [ref=e17]: Navigation
|
||||
- navigation "Main navigation" [ref=e18]:
|
||||
- group "Main" [ref=e19]:
|
||||
- heading "Main" [level=3] [ref=e20]
|
||||
- list "Main" [ref=e21]:
|
||||
- listitem [ref=e22]:
|
||||
- link "Dashboard" [ref=e23] [cursor=pointer]:
|
||||
- /url: /codegen
|
||||
- generic [ref=e24]: dashboard
|
||||
- generic [ref=e25]: Dashboard
|
||||
- listitem [ref=e26]:
|
||||
- link "Code Editor" [ref=e27] [cursor=pointer]:
|
||||
- /url: /codegen/code
|
||||
- generic [ref=e28]: code
|
||||
- generic [ref=e29]: Code Editor
|
||||
- listitem [ref=e30]:
|
||||
- link "Components" [ref=e31] [cursor=pointer]:
|
||||
- /url: /codegen/components
|
||||
- generic [ref=e32]: widgets
|
||||
- generic [ref=e33]: Components
|
||||
- listitem [ref=e34]:
|
||||
- link "Models" [ref=e35] [cursor=pointer]:
|
||||
- /url: /codegen/models
|
||||
- generic [ref=e36]: schema
|
||||
- generic [ref=e37]: Models
|
||||
- group "Design" [ref=e38]:
|
||||
- heading "Design" [level=3] [ref=e39]
|
||||
- list "Design" [ref=e40]:
|
||||
- listitem [ref=e41]:
|
||||
- link "Component Trees" [ref=e42] [cursor=pointer]:
|
||||
- /url: /codegen/component-trees
|
||||
- generic [ref=e43]: account_tree
|
||||
- generic [ref=e44]: Component Trees
|
||||
- listitem [ref=e45]:
|
||||
- link "Styling" [ref=e46] [cursor=pointer]:
|
||||
- /url: /codegen/styling
|
||||
- generic [ref=e47]: palette
|
||||
- generic [ref=e48]: Styling
|
||||
- listitem [ref=e49]:
|
||||
- link "Sass" [ref=e50] [cursor=pointer]:
|
||||
- /url: /codegen/sass
|
||||
- generic [ref=e51]: style
|
||||
- generic [ref=e52]: Sass
|
||||
- listitem [ref=e53]:
|
||||
- link "Atomic Library" [ref=e54] [cursor=pointer]:
|
||||
- /url: /codegen/atomic-library
|
||||
- generic [ref=e55]: library_books
|
||||
- generic [ref=e56]: Atomic Library
|
||||
- listitem [ref=e57]:
|
||||
- link "Templates" [ref=e58] [cursor=pointer]:
|
||||
- /url: /codegen/templates
|
||||
- generic [ref=e59]: content_copy
|
||||
- generic [ref=e60]: Templates
|
||||
- group "Workflows" [ref=e61]:
|
||||
- heading "Workflows" [level=3] [ref=e62]
|
||||
- list "Workflows" [ref=e63]:
|
||||
- listitem [ref=e64]:
|
||||
- link "Workflows" [ref=e65] [cursor=pointer]:
|
||||
- /url: /codegen/workflows
|
||||
- generic [ref=e66]: share
|
||||
- generic [ref=e67]: Workflows
|
||||
- listitem [ref=e68]:
|
||||
- link "Lambdas" [ref=e69] [cursor=pointer]:
|
||||
- /url: /codegen/lambdas
|
||||
- generic [ref=e70]: functions
|
||||
- generic [ref=e71]: Lambdas
|
||||
- group "Tools" [ref=e72]:
|
||||
- heading "Tools" [level=3] [ref=e73]
|
||||
- list "Tools" [ref=e74]:
|
||||
- listitem [ref=e75]:
|
||||
- link "JSON UI" [ref=e76] [cursor=pointer]:
|
||||
- /url: /codegen/json-ui
|
||||
- generic [ref=e77]: data_object
|
||||
- generic [ref=e78]: JSON UI
|
||||
- listitem [ref=e79]:
|
||||
- link "Schema Editor" [ref=e80] [cursor=pointer]:
|
||||
- /url: /codegen/schema-editor
|
||||
- generic [ref=e81]: edit_note
|
||||
- generic [ref=e82]: Schema Editor
|
||||
- listitem [ref=e83]:
|
||||
- link "Data Binding" [ref=e84] [cursor=pointer]:
|
||||
- /url: /codegen/data-binding
|
||||
- generic [ref=e85]: link
|
||||
- generic [ref=e86]: Data Binding
|
||||
- listitem [ref=e87]:
|
||||
- link "Flask API" [ref=e88] [cursor=pointer]:
|
||||
- /url: /codegen/flask
|
||||
- generic [ref=e89]: api
|
||||
- generic [ref=e90]: Flask API
|
||||
- group "Testing" [ref=e91]:
|
||||
- heading "Testing" [level=3] [ref=e92]
|
||||
- list "Testing" [ref=e93]:
|
||||
- listitem [ref=e94]:
|
||||
- link "Playwright" [ref=e95] [cursor=pointer]:
|
||||
- /url: /codegen/playwright
|
||||
- generic [ref=e96]: bug_report
|
||||
- generic [ref=e97]: Playwright
|
||||
- listitem [ref=e98]:
|
||||
- link "Unit Tests" [ref=e99] [cursor=pointer]:
|
||||
- /url: /codegen/unit-tests
|
||||
- generic [ref=e100]: science
|
||||
- generic [ref=e101]: Unit Tests
|
||||
- listitem [ref=e102]:
|
||||
- link "Storybook" [ref=e103] [cursor=pointer]:
|
||||
- /url: /codegen/storybook
|
||||
- generic [ref=e104]: auto_stories
|
||||
- generic [ref=e105]: Storybook
|
||||
- group "System" [ref=e106]:
|
||||
- heading "System" [level=3] [ref=e107]
|
||||
- list "System" [ref=e108]:
|
||||
- listitem [ref=e109]:
|
||||
- link "Settings" [ref=e110] [cursor=pointer]:
|
||||
- /url: /codegen/settings
|
||||
- generic [ref=e111]: settings
|
||||
- generic [ref=e112]: Settings
|
||||
- listitem [ref=e113]:
|
||||
- link "Documentation" [ref=e114] [cursor=pointer]:
|
||||
- /url: /codegen/docs
|
||||
- generic [ref=e115]: description
|
||||
- generic [ref=e116]: Documentation
|
||||
- listitem [ref=e117]:
|
||||
- link "Features" [ref=e118] [cursor=pointer]:
|
||||
- /url: /codegen/features
|
||||
- generic [ref=e119]: toggle_on
|
||||
- generic [ref=e120]: Features
|
||||
- listitem [ref=e121]:
|
||||
- link "Errors" [ref=e122] [cursor=pointer]:
|
||||
- /url: /codegen/errors
|
||||
- generic [ref=e123]: error
|
||||
- generic [ref=e124]: Errors
|
||||
- listitem [ref=e125]:
|
||||
- link "Persistence" [ref=e126] [cursor=pointer]:
|
||||
- /url: /codegen/persistence
|
||||
- generic [ref=e127]: storage
|
||||
- generic [ref=e128]: Persistence
|
||||
- listitem [ref=e129]:
|
||||
- link "PWA" [ref=e130] [cursor=pointer]:
|
||||
- /url: /codegen/pwa
|
||||
- generic [ref=e131]: install_desktop
|
||||
- generic [ref=e132]: PWA
|
||||
- main [ref=e133]:
|
||||
- paragraph [ref=e137]: Loading projectdashboard...
|
||||
- alert [ref=e138]
|
||||
@@ -1,128 +0,0 @@
|
||||
- generic [active] [ref=e1]:
|
||||
- alert [ref=e2]
|
||||
- generic [ref=e3]:
|
||||
- banner [ref=e4]:
|
||||
- generic [ref=e5]:
|
||||
- button "Toggle sidebar" [ref=e6] [cursor=pointer]:
|
||||
- img [ref=e7]
|
||||
- generic [ref=e8]:
|
||||
- img [ref=e9]
|
||||
- heading "WorkflowUI" [level=1] [ref=e18]
|
||||
- generic [ref=e19]:
|
||||
- button "Notifications" [ref=e21] [cursor=pointer]:
|
||||
- img [ref=e22]
|
||||
- generic [ref=e24]: "2"
|
||||
- button "Switch to dark mode" [ref=e25] [cursor=pointer]:
|
||||
- img [ref=e26]
|
||||
- generic [ref=e28]:
|
||||
- complementary "Workflows sidebar" [ref=e29]:
|
||||
- navigation [ref=e30]:
|
||||
- generic [ref=e31]:
|
||||
- heading "Main" [level=3] [ref=e32]
|
||||
- list "Main navigation" [ref=e33]:
|
||||
- listitem [ref=e34]:
|
||||
- link "Dashboard" [ref=e35] [cursor=pointer]:
|
||||
- /url: /workflowui
|
||||
- img [ref=e37]
|
||||
- generic [ref=e39]: Dashboard
|
||||
- listitem [ref=e40]:
|
||||
- link "Notifications 2" [ref=e41] [cursor=pointer]:
|
||||
- /url: /workflowui/notifications
|
||||
- img [ref=e43]
|
||||
- generic [ref=e45]: Notifications
|
||||
- generic [ref=e46]: "2"
|
||||
- generic [ref=e47]:
|
||||
- heading "Workflows" [level=3] [ref=e48]
|
||||
- list "Workflows navigation" [ref=e49]:
|
||||
- listitem [ref=e50]:
|
||||
- link "All Workflows" [ref=e51] [cursor=pointer]:
|
||||
- /url: /workflowui/workflows
|
||||
- img [ref=e53]
|
||||
- generic [ref=e55]: All Workflows
|
||||
- listitem [ref=e56]:
|
||||
- link "Recent" [ref=e57] [cursor=pointer]:
|
||||
- /url: /workflowui/workflows/recent
|
||||
- img [ref=e59]
|
||||
- generic [ref=e61]: Recent
|
||||
- listitem [ref=e62]:
|
||||
- link "Favorites" [ref=e63] [cursor=pointer]:
|
||||
- /url: /workflowui/workflows/favorites
|
||||
- img [ref=e65]
|
||||
- generic [ref=e67]: Favorites
|
||||
- listitem [ref=e68]:
|
||||
- link "Templates" [ref=e69] [cursor=pointer]:
|
||||
- /url: /workflowui/templates
|
||||
- img [ref=e71]
|
||||
- generic [ref=e73]: Templates
|
||||
- generic [ref=e74]:
|
||||
- heading "System" [level=3] [ref=e75]
|
||||
- list "System navigation" [ref=e76]:
|
||||
- listitem [ref=e77]:
|
||||
- link "Plugins" [ref=e78] [cursor=pointer]:
|
||||
- /url: /workflowui/plugins
|
||||
- img [ref=e80]
|
||||
- generic [ref=e82]: Plugins
|
||||
- listitem [ref=e83]:
|
||||
- link "Settings" [ref=e84] [cursor=pointer]:
|
||||
- /url: /workflowui/settings
|
||||
- img [ref=e86]
|
||||
- generic [ref=e88]: Settings
|
||||
- generic [ref=e89]:
|
||||
- heading "Help" [level=3] [ref=e90]
|
||||
- list "Help navigation" [ref=e91]:
|
||||
- listitem [ref=e92]:
|
||||
- link "Documentation" [ref=e93] [cursor=pointer]:
|
||||
- /url: /workflowui/docs
|
||||
- img [ref=e95]
|
||||
- generic [ref=e97]: Documentation
|
||||
- listitem [ref=e98]:
|
||||
- link "Help & Support" [ref=e99] [cursor=pointer]:
|
||||
- /url: /workflowui/help
|
||||
- img [ref=e101]
|
||||
- generic [ref=e103]: Help & Support
|
||||
- button "+ New Workflow" [ref=e105] [cursor=pointer]:
|
||||
- generic [ref=e107]: + New Workflow
|
||||
- main [ref=e108]:
|
||||
- generic [ref=e109]:
|
||||
- generic [ref=e110]:
|
||||
- generic [ref=e111]:
|
||||
- img [ref=e113]
|
||||
- generic [ref=e115]:
|
||||
- generic [ref=e116]: "23"
|
||||
- generic [ref=e117]: nodes today
|
||||
- generic [ref=e118]:
|
||||
- img [ref=e120]
|
||||
- generic [ref=e122]:
|
||||
- generic [ref=e123]: "5"
|
||||
- generic [ref=e124]: runs today
|
||||
- generic [ref=e125]:
|
||||
- img [ref=e127]
|
||||
- generic [ref=e129]:
|
||||
- generic [ref=e130]: "1"
|
||||
- generic [ref=e131]: failed
|
||||
- generic [ref=e132]:
|
||||
- img [ref=e134]
|
||||
- generic [ref=e136]:
|
||||
- generic [ref=e137]: 1.2h
|
||||
- generic [ref=e138]: saved today
|
||||
- generic [ref=e140]:
|
||||
- generic "First Steps" [ref=e141]:
|
||||
- img [ref=e142]
|
||||
- generic "Node Master" [ref=e144]:
|
||||
- img [ref=e145]
|
||||
- link "+4 more" [ref=e147] [cursor=pointer]:
|
||||
- /url: /workflowui/achievements
|
||||
- generic [ref=e148]:
|
||||
- generic [ref=e149]:
|
||||
- heading "Workspaces" [level=1] [ref=e150]
|
||||
- paragraph [ref=e151]: Organize your projects and workflows
|
||||
- button "New Workspace" [ref=e152] [cursor=pointer]:
|
||||
- img [ref=e155]
|
||||
- generic [ref=e157]: New Workspace
|
||||
- generic [ref=e158]:
|
||||
- progressbar [ref=e159]:
|
||||
- generic [ref=e161]:
|
||||
- img [ref=e163]
|
||||
- img [ref=e166]
|
||||
- img [ref=e169]
|
||||
- paragraph [ref=e171]: Loading workspaces...
|
||||
@@ -1,122 +0,0 @@
|
||||
- generic [active] [ref=e1]:
|
||||
- banner [ref=e2]:
|
||||
- heading "MetaBuilder" [level=1] [ref=e3]
|
||||
- paragraph [ref=e4]: Development Stack Portal
|
||||
- generic [ref=e5]: Applications
|
||||
- generic [ref=e6]:
|
||||
- link "W WorkflowUI Visual workflow editor with n8n-style DAG canvas, step library, and JSON workflow execution. /workflowui" [ref=e7] [cursor=pointer]:
|
||||
- /url: /workflowui
|
||||
- generic [ref=e8]:
|
||||
- generic [ref=e9]: W
|
||||
- heading "WorkflowUI" [level=2] [ref=e10]
|
||||
- paragraph [ref=e11]: Visual workflow editor with n8n-style DAG canvas, step library, and JSON workflow execution.
|
||||
- generic [ref=e12]: /workflowui
|
||||
- link "C CodeForge IDE Low-code application builder with Monaco editor, JSON-driven component architecture. /codegen" [ref=e13] [cursor=pointer]:
|
||||
- /url: /codegen
|
||||
- generic [ref=e14]:
|
||||
- generic [ref=e15]: C
|
||||
- heading "CodeForge IDE" [level=2] [ref=e16]
|
||||
- paragraph [ref=e17]: Low-code application builder with Monaco editor, JSON-driven component architecture.
|
||||
- generic [ref=e18]: /codegen
|
||||
- link "P Pastebin Code snippet sharing with syntax highlighting, expiration, and privacy controls. /pastebin" [ref=e19] [cursor=pointer]:
|
||||
- /url: /pastebin
|
||||
- generic [ref=e20]:
|
||||
- generic [ref=e21]: P
|
||||
- heading "Pastebin" [level=2] [ref=e22]
|
||||
- paragraph [ref=e23]: Code snippet sharing with syntax highlighting, expiration, and privacy controls.
|
||||
- generic [ref=e24]: /pastebin
|
||||
- link "E Email Client Full-featured email management with IMAP/SMTP, multi-account support, and search. /emailclient" [ref=e25] [cursor=pointer]:
|
||||
- /url: /emailclient
|
||||
- generic [ref=e26]:
|
||||
- generic [ref=e27]: E
|
||||
- heading "Email Client" [level=2] [ref=e28]
|
||||
- paragraph [ref=e29]: Full-featured email management with IMAP/SMTP, multi-account support, and search.
|
||||
- generic [ref=e30]: /emailclient
|
||||
- link "D Postgres Dashboard PostgreSQL admin dashboard with query editor, table browser, and performance monitoring. /postgres" [ref=e31] [cursor=pointer]:
|
||||
- /url: /postgres
|
||||
- generic [ref=e32]:
|
||||
- generic [ref=e33]: D
|
||||
- heading "Postgres Dashboard" [level=2] [ref=e34]
|
||||
- paragraph [ref=e35]: PostgreSQL admin dashboard with query editor, table browser, and performance monitoring.
|
||||
- generic [ref=e36]: /postgres
|
||||
- link "3D Exploded Diagrams Interactive 3D exploded diagram viewer with Three.js and JSCAD integration. /diagrams" [ref=e37] [cursor=pointer]:
|
||||
- /url: /diagrams
|
||||
- generic [ref=e38]:
|
||||
- generic [ref=e39]: 3D
|
||||
- heading "Exploded Diagrams" [level=2] [ref=e40]
|
||||
- paragraph [ref=e41]: Interactive 3D exploded diagram viewer with Three.js and JSCAD integration.
|
||||
- generic [ref=e42]: /diagrams
|
||||
- link "S Storybook Component library preview with interactive props, documentation, and visual testing. /storybook" [ref=e43] [cursor=pointer]:
|
||||
- /url: /storybook
|
||||
- generic [ref=e44]:
|
||||
- generic [ref=e45]: S
|
||||
- heading "Storybook" [level=2] [ref=e46]
|
||||
- paragraph [ref=e47]: Component library preview with interactive props, documentation, and visual testing.
|
||||
- generic [ref=e48]: /storybook
|
||||
- link "A Frontend App Main Next.js application with Drizzle ORM, i18n, Clerk auth, and DBAL integration. /app" [ref=e49] [cursor=pointer]:
|
||||
- /url: /app
|
||||
- generic [ref=e50]:
|
||||
- generic [ref=e51]: A
|
||||
- heading "Frontend App" [level=2] [ref=e52]
|
||||
- paragraph [ref=e53]: Main Next.js application with Drizzle ORM, i18n, Clerk auth, and DBAL integration.
|
||||
- generic [ref=e54]: /app
|
||||
- generic [ref=e55]: Backend Services
|
||||
- generic [ref=e56]:
|
||||
- link "API DBAL API C++ database abstraction layer with RESTful CRUD, caching, and search. /api" [ref=e57] [cursor=pointer]:
|
||||
- /url: /api/health
|
||||
- generic [ref=e58]:
|
||||
- generic [ref=e59]: API
|
||||
- heading "DBAL API" [level=2] [ref=e60]
|
||||
- paragraph [ref=e61]: C++ database abstraction layer with RESTful CRUD, caching, and search.
|
||||
- generic [ref=e62]: /api
|
||||
- link "EM Email Service Flask backend for IMAP/SMTP operations, email sync, and Celery task queue. /email-api" [ref=e63] [cursor=pointer]:
|
||||
- /url: /email-api/health
|
||||
- generic [ref=e64]:
|
||||
- generic [ref=e65]: EM
|
||||
- heading "Email Service" [level=2] [ref=e66]
|
||||
- paragraph [ref=e67]: Flask backend for IMAP/SMTP operations, email sync, and Celery task queue.
|
||||
- generic [ref=e68]: /email-api
|
||||
- link "SM SMTP Relay Twisted SMTP relay dashboard for email testing and debugging. localhost:8025" [ref=e69] [cursor=pointer]:
|
||||
- /url: http://localhost:8025
|
||||
- generic [ref=e70]:
|
||||
- generic [ref=e71]: SM
|
||||
- heading "SMTP Relay" [level=2] [ref=e72]
|
||||
- paragraph [ref=e73]: Twisted SMTP relay dashboard for email testing and debugging.
|
||||
- generic [ref=e74]: localhost:8025
|
||||
- generic [ref=e75]: Administration
|
||||
- generic [ref=e76]:
|
||||
- link "⚙ Database Settings Manage DBAL adapter configuration, switch backends, and test database connections. /portal/settings.html" [ref=e77] [cursor=pointer]:
|
||||
- /url: /portal/settings.html
|
||||
- generic [ref=e78]:
|
||||
- generic [ref=e79]: ⚙
|
||||
- heading "Database Settings" [level=2] [ref=e80]
|
||||
- paragraph [ref=e81]: Manage DBAL adapter configuration, switch backends, and test database connections.
|
||||
- generic [ref=e82]: /portal/settings.html
|
||||
- link "PMA phpMyAdmin MySQL web administration with table browser, SQL editor, import/export, and user management. /phpmyadmin/" [ref=e83] [cursor=pointer]:
|
||||
- /url: /phpmyadmin/
|
||||
- generic [ref=e84]:
|
||||
- generic [ref=e85]: PMA
|
||||
- heading "phpMyAdmin" [level=2] [ref=e86]
|
||||
- paragraph [ref=e87]: MySQL web administration with table browser, SQL editor, import/export, and user management.
|
||||
- generic [ref=e88]: /phpmyadmin/
|
||||
- link "ME Mongo Express MongoDB web administration with collection browser, document editor, and query interface. /mongo-express/" [ref=e89] [cursor=pointer]:
|
||||
- /url: /mongo-express/
|
||||
- generic [ref=e90]:
|
||||
- generic [ref=e91]: ME
|
||||
- heading "Mongo Express" [level=2] [ref=e92]
|
||||
- paragraph [ref=e93]: MongoDB web administration with collection browser, document editor, and query interface.
|
||||
- generic [ref=e94]: /mongo-express/
|
||||
- link "RI RedisInsight Redis GUI with key browser, CLI console, memory analysis, and slow log inspection. /redis-insight/" [ref=e95] [cursor=pointer]:
|
||||
- /url: /redis-insight/
|
||||
- generic [ref=e96]:
|
||||
- generic [ref=e97]: RI
|
||||
- heading "RedisInsight" [level=2] [ref=e98]
|
||||
- paragraph [ref=e99]: Redis GUI with key browser, CLI console, memory analysis, and slow log inspection.
|
||||
- generic [ref=e100]: /redis-insight/
|
||||
- link "KB Kibana Elasticsearch dashboard with Discover, index management, Dev Tools console, and visualizations. /kibana/" [ref=e101] [cursor=pointer]:
|
||||
- /url: /kibana/
|
||||
- generic [ref=e102]:
|
||||
- generic [ref=e103]: KB
|
||||
- heading "Kibana" [level=2] [ref=e104]
|
||||
- paragraph [ref=e105]: Elasticsearch dashboard with Discover, index management, Dev Tools console, and visualizations.
|
||||
- generic [ref=e106]: /kibana/
|
||||
@@ -1,156 +0,0 @@
|
||||
- generic [active] [ref=e1]:
|
||||
- generic [ref=e3]:
|
||||
- banner [ref=e4]:
|
||||
- generic [ref=e5]:
|
||||
- button "Toggle sidebar" [expanded] [ref=e6] [cursor=pointer]:
|
||||
- generic [ref=e7]: menu
|
||||
- generic [ref=e8]:
|
||||
- generic [ref=e9]: code
|
||||
- heading "CodeForge" [level=1] [ref=e10]
|
||||
- button "Switch to dark mode" [ref=e12] [cursor=pointer]:
|
||||
- generic [ref=e13]: dark_mode
|
||||
- generic [ref=e14]:
|
||||
- complementary "Navigation sidebar" [ref=e15]:
|
||||
- paragraph [ref=e17]: Navigation
|
||||
- navigation "Main navigation" [ref=e18]:
|
||||
- group "Main" [ref=e19]:
|
||||
- heading "Main" [level=3] [ref=e20]
|
||||
- list "Main" [ref=e21]:
|
||||
- listitem [ref=e22]:
|
||||
- link "Dashboard" [ref=e23] [cursor=pointer]:
|
||||
- /url: /codegen
|
||||
- generic [ref=e24]: dashboard
|
||||
- generic [ref=e25]: Dashboard
|
||||
- listitem [ref=e26]:
|
||||
- link "Code Editor" [ref=e27] [cursor=pointer]:
|
||||
- /url: /codegen/code
|
||||
- generic [ref=e28]: code
|
||||
- generic [ref=e29]: Code Editor
|
||||
- listitem [ref=e30]:
|
||||
- link "Components" [ref=e31] [cursor=pointer]:
|
||||
- /url: /codegen/components
|
||||
- generic [ref=e32]: widgets
|
||||
- generic [ref=e33]: Components
|
||||
- listitem [ref=e34]:
|
||||
- link "Models" [ref=e35] [cursor=pointer]:
|
||||
- /url: /codegen/models
|
||||
- generic [ref=e36]: schema
|
||||
- generic [ref=e37]: Models
|
||||
- group "Design" [ref=e38]:
|
||||
- heading "Design" [level=3] [ref=e39]
|
||||
- list "Design" [ref=e40]:
|
||||
- listitem [ref=e41]:
|
||||
- link "Component Trees" [ref=e42] [cursor=pointer]:
|
||||
- /url: /codegen/component-trees
|
||||
- generic [ref=e43]: account_tree
|
||||
- generic [ref=e44]: Component Trees
|
||||
- listitem [ref=e45]:
|
||||
- link "Styling" [ref=e46] [cursor=pointer]:
|
||||
- /url: /codegen/styling
|
||||
- generic [ref=e47]: palette
|
||||
- generic [ref=e48]: Styling
|
||||
- listitem [ref=e49]:
|
||||
- link "Sass" [ref=e50] [cursor=pointer]:
|
||||
- /url: /codegen/sass
|
||||
- generic [ref=e51]: style
|
||||
- generic [ref=e52]: Sass
|
||||
- listitem [ref=e53]:
|
||||
- link "Atomic Library" [ref=e54] [cursor=pointer]:
|
||||
- /url: /codegen/atomic-library
|
||||
- generic [ref=e55]: library_books
|
||||
- generic [ref=e56]: Atomic Library
|
||||
- listitem [ref=e57]:
|
||||
- link "Templates" [ref=e58] [cursor=pointer]:
|
||||
- /url: /codegen/templates
|
||||
- generic [ref=e59]: content_copy
|
||||
- generic [ref=e60]: Templates
|
||||
- group "Workflows" [ref=e61]:
|
||||
- heading "Workflows" [level=3] [ref=e62]
|
||||
- list "Workflows" [ref=e63]:
|
||||
- listitem [ref=e64]:
|
||||
- link "Workflows" [ref=e65] [cursor=pointer]:
|
||||
- /url: /codegen/workflows
|
||||
- generic [ref=e66]: share
|
||||
- generic [ref=e67]: Workflows
|
||||
- listitem [ref=e68]:
|
||||
- link "Lambdas" [ref=e69] [cursor=pointer]:
|
||||
- /url: /codegen/lambdas
|
||||
- generic [ref=e70]: functions
|
||||
- generic [ref=e71]: Lambdas
|
||||
- group "Tools" [ref=e72]:
|
||||
- heading "Tools" [level=3] [ref=e73]
|
||||
- list "Tools" [ref=e74]:
|
||||
- listitem [ref=e75]:
|
||||
- link "JSON UI" [ref=e76] [cursor=pointer]:
|
||||
- /url: /codegen/json-ui
|
||||
- generic [ref=e77]: data_object
|
||||
- generic [ref=e78]: JSON UI
|
||||
- listitem [ref=e79]:
|
||||
- link "Schema Editor" [ref=e80] [cursor=pointer]:
|
||||
- /url: /codegen/schema-editor
|
||||
- generic [ref=e81]: edit_note
|
||||
- generic [ref=e82]: Schema Editor
|
||||
- listitem [ref=e83]:
|
||||
- link "Data Binding" [ref=e84] [cursor=pointer]:
|
||||
- /url: /codegen/data-binding
|
||||
- generic [ref=e85]: link
|
||||
- generic [ref=e86]: Data Binding
|
||||
- listitem [ref=e87]:
|
||||
- link "Flask API" [ref=e88] [cursor=pointer]:
|
||||
- /url: /codegen/flask
|
||||
- generic [ref=e89]: api
|
||||
- generic [ref=e90]: Flask API
|
||||
- group "Testing" [ref=e91]:
|
||||
- heading "Testing" [level=3] [ref=e92]
|
||||
- list "Testing" [ref=e93]:
|
||||
- listitem [ref=e94]:
|
||||
- link "Playwright" [ref=e95] [cursor=pointer]:
|
||||
- /url: /codegen/playwright
|
||||
- generic [ref=e96]: bug_report
|
||||
- generic [ref=e97]: Playwright
|
||||
- listitem [ref=e98]:
|
||||
- link "Unit Tests" [ref=e99] [cursor=pointer]:
|
||||
- /url: /codegen/unit-tests
|
||||
- generic [ref=e100]: science
|
||||
- generic [ref=e101]: Unit Tests
|
||||
- listitem [ref=e102]:
|
||||
- link "Storybook" [ref=e103] [cursor=pointer]:
|
||||
- /url: /codegen/storybook
|
||||
- generic [ref=e104]: auto_stories
|
||||
- generic [ref=e105]: Storybook
|
||||
- group "System" [ref=e106]:
|
||||
- heading "System" [level=3] [ref=e107]
|
||||
- list "System" [ref=e108]:
|
||||
- listitem [ref=e109]:
|
||||
- link "Settings" [ref=e110] [cursor=pointer]:
|
||||
- /url: /codegen/settings
|
||||
- generic [ref=e111]: settings
|
||||
- generic [ref=e112]: Settings
|
||||
- listitem [ref=e113]:
|
||||
- link "Documentation" [ref=e114] [cursor=pointer]:
|
||||
- /url: /codegen/docs
|
||||
- generic [ref=e115]: description
|
||||
- generic [ref=e116]: Documentation
|
||||
- listitem [ref=e117]:
|
||||
- link "Features" [ref=e118] [cursor=pointer]:
|
||||
- /url: /codegen/features
|
||||
- generic [ref=e119]: toggle_on
|
||||
- generic [ref=e120]: Features
|
||||
- listitem [ref=e121]:
|
||||
- link "Errors" [ref=e122] [cursor=pointer]:
|
||||
- /url: /codegen/errors
|
||||
- generic [ref=e123]: error
|
||||
- generic [ref=e124]: Errors
|
||||
- listitem [ref=e125]:
|
||||
- link "Persistence" [ref=e126] [cursor=pointer]:
|
||||
- /url: /codegen/persistence
|
||||
- generic [ref=e127]: storage
|
||||
- generic [ref=e128]: Persistence
|
||||
- listitem [ref=e129]:
|
||||
- link "PWA" [ref=e130] [cursor=pointer]:
|
||||
- /url: /codegen/pwa
|
||||
- generic [ref=e131]: install_desktop
|
||||
- generic [ref=e132]: PWA
|
||||
- main [ref=e133]:
|
||||
- paragraph [ref=e137]: Loading projectdashboard...
|
||||
- alert [ref=e138]
|
||||
@@ -1,143 +0,0 @@
|
||||
- generic [ref=e3]:
|
||||
- banner "Storybook" [ref=e7]:
|
||||
- heading "Storybook" [level=1] [ref=e8]
|
||||
- img
|
||||
- generic [ref=e12]:
|
||||
- generic [ref=e14]:
|
||||
- link "Skip to content" [ref=e15] [cursor=pointer]:
|
||||
- /url: "#storybook-preview-wrapper"
|
||||
- link "Storybook" [ref=e17] [cursor=pointer]:
|
||||
- /url: ./
|
||||
- img "Storybook" [ref=e18]
|
||||
- switch "Settings" [ref=e23] [cursor=pointer]:
|
||||
- img [ref=e24]
|
||||
- generic [ref=e27]: Search for components
|
||||
- search [ref=e28]:
|
||||
- combobox "Search for components" [ref=e29]:
|
||||
- generic:
|
||||
- img
|
||||
- searchbox "Search for components" [ref=e30]
|
||||
- code:
|
||||
- generic: ⌘
|
||||
- text: K
|
||||
- button "Tag filters" [ref=e32] [cursor=pointer]:
|
||||
- img [ref=e33]
|
||||
- navigation "Stories" [ref=e36]:
|
||||
- heading "Stories" [level=2] [ref=e37]
|
||||
- generic [ref=e39]:
|
||||
- link "Introduction" [ref=e41] [cursor=pointer]:
|
||||
- /url: /storybook/?path=/docs/introduction--docs
|
||||
- img [ref=e43]
|
||||
- text: Introduction
|
||||
- generic [ref=e45]:
|
||||
- button "Collapse" [expanded] [ref=e46] [cursor=pointer]:
|
||||
- img [ref=e48]
|
||||
- text: Developer
|
||||
- button "Expand all" [ref=e50] [cursor=pointer]:
|
||||
- img [ref=e51]
|
||||
- link "Styles System" [ref=e54] [cursor=pointer]:
|
||||
- /url: /storybook/?path=/docs/developer-styles-system--docs
|
||||
- img [ref=e56]
|
||||
- text: Styles System
|
||||
- generic [ref=e58]:
|
||||
- button "Collapse" [expanded] [ref=e59] [cursor=pointer]:
|
||||
- img [ref=e61]
|
||||
- text: Packages
|
||||
- button "Expand all" [ref=e63] [cursor=pointer]:
|
||||
- img [ref=e64]
|
||||
- button "Auto-Discovered" [ref=e67] [cursor=pointer]:
|
||||
- generic [ref=e68]:
|
||||
- img [ref=e70]
|
||||
- img [ref=e72]
|
||||
- text: Auto-Discovered
|
||||
- button "JSON Components" [ref=e75] [cursor=pointer]:
|
||||
- generic [ref=e76]:
|
||||
- img [ref=e78]
|
||||
- img [ref=e80]
|
||||
- text: JSON Components
|
||||
- button "UI Home" [ref=e83] [cursor=pointer]:
|
||||
- generic [ref=e84]:
|
||||
- img [ref=e86]
|
||||
- img [ref=e88]
|
||||
- text: UI Home
|
||||
- button "UI Level 2" [ref=e91] [cursor=pointer]:
|
||||
- generic [ref=e92]:
|
||||
- img [ref=e94]
|
||||
- img [ref=e96]
|
||||
- text: UI Level 2
|
||||
- button "UI Level 3" [ref=e99] [cursor=pointer]:
|
||||
- generic [ref=e100]:
|
||||
- img [ref=e102]
|
||||
- img [ref=e104]
|
||||
- text: UI Level 3
|
||||
- button "UI Level 4" [ref=e107] [cursor=pointer]:
|
||||
- generic [ref=e108]:
|
||||
- img [ref=e110]
|
||||
- img [ref=e112]
|
||||
- text: UI Level 4
|
||||
- generic [ref=e114]:
|
||||
- button "Collapse" [expanded] [ref=e115] [cursor=pointer]:
|
||||
- img [ref=e117]
|
||||
- text: Components
|
||||
- button "Expand all" [ref=e119] [cursor=pointer]:
|
||||
- img [ref=e120]
|
||||
- button "Registry" [ref=e123] [cursor=pointer]:
|
||||
- generic [ref=e124]:
|
||||
- img [ref=e126]
|
||||
- img [ref=e128]
|
||||
- text: Registry
|
||||
- generic [ref=e130]:
|
||||
- button "Collapse" [expanded] [ref=e131] [cursor=pointer]:
|
||||
- img [ref=e133]
|
||||
- text: Design System
|
||||
- button "Expand all" [ref=e135] [cursor=pointer]:
|
||||
- img [ref=e136]
|
||||
- button "Tokens" [ref=e139] [cursor=pointer]:
|
||||
- generic [ref=e140]:
|
||||
- img [ref=e142]
|
||||
- img [ref=e144]
|
||||
- text: Tokens
|
||||
- generic [ref=e147]:
|
||||
- region "Toolbar" [ref=e148]:
|
||||
- heading "Toolbar" [level=2] [ref=e149]
|
||||
- toolbar [ref=e150]
|
||||
- main "Main preview area" [ref=e151]:
|
||||
- heading "Main preview area" [level=2] [ref=e152]
|
||||
- generic [ref=e153]:
|
||||
- progressbar "Content is loading..." [ref=e155]
|
||||
- iframe [ref=e160]:
|
||||
- table [ref=f1e11]:
|
||||
- rowgroup [ref=f1e12]:
|
||||
- row [ref=f1e13]:
|
||||
- columnheader [ref=f1e14]: Name
|
||||
- columnheader [ref=f1e15]: Description
|
||||
- columnheader [ref=f1e16]: Default
|
||||
- columnheader [ref=f1e17]: Control
|
||||
- rowgroup [ref=f1e18]:
|
||||
- row [ref=f1e19]:
|
||||
- cell [ref=f1e20]: propertyName*
|
||||
- cell [ref=f1e21]:
|
||||
- generic [ref=f1e22]: This is a short description
|
||||
- generic [ref=f1e24]: summary
|
||||
- cell [ref=f1e25]:
|
||||
- generic [ref=f1e26]: defaultValue
|
||||
- cell [ref=f1e27]:
|
||||
- button [ref=f1e28] [cursor=pointer]: Set string
|
||||
- row [ref=f1e29]:
|
||||
- cell [ref=f1e30]: propertyName*
|
||||
- cell [ref=f1e31]:
|
||||
- generic [ref=f1e32]: This is a short description
|
||||
- generic [ref=f1e34]: summary
|
||||
- cell [ref=f1e35]:
|
||||
- generic [ref=f1e36]: defaultValue
|
||||
- cell [ref=f1e37]:
|
||||
- button [ref=f1e38] [cursor=pointer]: Set string
|
||||
- row [ref=f1e39]:
|
||||
- cell [ref=f1e40]: propertyName*
|
||||
- cell [ref=f1e41]:
|
||||
- generic [ref=f1e42]: This is a short description
|
||||
- generic [ref=f1e44]: summary
|
||||
- cell [ref=f1e45]:
|
||||
- generic [ref=f1e46]: defaultValue
|
||||
- cell [ref=f1e47]:
|
||||
- button [ref=f1e48] [cursor=pointer]: Set string
|
||||
@@ -1,156 +0,0 @@
|
||||
- generic [active] [ref=e1]:
|
||||
- generic [ref=e3]:
|
||||
- banner [ref=e4]:
|
||||
- generic [ref=e5]:
|
||||
- button "Toggle sidebar" [expanded] [ref=e6] [cursor=pointer]:
|
||||
- generic [ref=e7]: menu
|
||||
- generic [ref=e8]:
|
||||
- generic [ref=e9]: code
|
||||
- heading "CodeForge" [level=1] [ref=e10]
|
||||
- button "Switch to dark mode" [ref=e12] [cursor=pointer]:
|
||||
- generic [ref=e13]: dark_mode
|
||||
- generic [ref=e14]:
|
||||
- complementary "Navigation sidebar" [ref=e15]:
|
||||
- paragraph [ref=e17]: Navigation
|
||||
- navigation "Main navigation" [ref=e18]:
|
||||
- group "Main" [ref=e19]:
|
||||
- heading "Main" [level=3] [ref=e20]
|
||||
- list "Main" [ref=e21]:
|
||||
- listitem [ref=e22]:
|
||||
- link "Dashboard" [ref=e23] [cursor=pointer]:
|
||||
- /url: /codegen
|
||||
- generic [ref=e24]: dashboard
|
||||
- generic [ref=e25]: Dashboard
|
||||
- listitem [ref=e26]:
|
||||
- link "Code Editor" [ref=e27] [cursor=pointer]:
|
||||
- /url: /codegen/code
|
||||
- generic [ref=e28]: code
|
||||
- generic [ref=e29]: Code Editor
|
||||
- listitem [ref=e30]:
|
||||
- link "Components" [ref=e31] [cursor=pointer]:
|
||||
- /url: /codegen/components
|
||||
- generic [ref=e32]: widgets
|
||||
- generic [ref=e33]: Components
|
||||
- listitem [ref=e34]:
|
||||
- link "Models" [ref=e35] [cursor=pointer]:
|
||||
- /url: /codegen/models
|
||||
- generic [ref=e36]: schema
|
||||
- generic [ref=e37]: Models
|
||||
- group "Design" [ref=e38]:
|
||||
- heading "Design" [level=3] [ref=e39]
|
||||
- list "Design" [ref=e40]:
|
||||
- listitem [ref=e41]:
|
||||
- link "Component Trees" [ref=e42] [cursor=pointer]:
|
||||
- /url: /codegen/component-trees
|
||||
- generic [ref=e43]: account_tree
|
||||
- generic [ref=e44]: Component Trees
|
||||
- listitem [ref=e45]:
|
||||
- link "Styling" [ref=e46] [cursor=pointer]:
|
||||
- /url: /codegen/styling
|
||||
- generic [ref=e47]: palette
|
||||
- generic [ref=e48]: Styling
|
||||
- listitem [ref=e49]:
|
||||
- link "Sass" [ref=e50] [cursor=pointer]:
|
||||
- /url: /codegen/sass
|
||||
- generic [ref=e51]: style
|
||||
- generic [ref=e52]: Sass
|
||||
- listitem [ref=e53]:
|
||||
- link "Atomic Library" [ref=e54] [cursor=pointer]:
|
||||
- /url: /codegen/atomic-library
|
||||
- generic [ref=e55]: library_books
|
||||
- generic [ref=e56]: Atomic Library
|
||||
- listitem [ref=e57]:
|
||||
- link "Templates" [ref=e58] [cursor=pointer]:
|
||||
- /url: /codegen/templates
|
||||
- generic [ref=e59]: content_copy
|
||||
- generic [ref=e60]: Templates
|
||||
- group "Workflows" [ref=e61]:
|
||||
- heading "Workflows" [level=3] [ref=e62]
|
||||
- list "Workflows" [ref=e63]:
|
||||
- listitem [ref=e64]:
|
||||
- link "Workflows" [ref=e65] [cursor=pointer]:
|
||||
- /url: /codegen/workflows
|
||||
- generic [ref=e66]: share
|
||||
- generic [ref=e67]: Workflows
|
||||
- listitem [ref=e68]:
|
||||
- link "Lambdas" [ref=e69] [cursor=pointer]:
|
||||
- /url: /codegen/lambdas
|
||||
- generic [ref=e70]: functions
|
||||
- generic [ref=e71]: Lambdas
|
||||
- group "Tools" [ref=e72]:
|
||||
- heading "Tools" [level=3] [ref=e73]
|
||||
- list "Tools" [ref=e74]:
|
||||
- listitem [ref=e75]:
|
||||
- link "JSON UI" [ref=e76] [cursor=pointer]:
|
||||
- /url: /codegen/json-ui
|
||||
- generic [ref=e77]: data_object
|
||||
- generic [ref=e78]: JSON UI
|
||||
- listitem [ref=e79]:
|
||||
- link "Schema Editor" [ref=e80] [cursor=pointer]:
|
||||
- /url: /codegen/schema-editor
|
||||
- generic [ref=e81]: edit_note
|
||||
- generic [ref=e82]: Schema Editor
|
||||
- listitem [ref=e83]:
|
||||
- link "Data Binding" [ref=e84] [cursor=pointer]:
|
||||
- /url: /codegen/data-binding
|
||||
- generic [ref=e85]: link
|
||||
- generic [ref=e86]: Data Binding
|
||||
- listitem [ref=e87]:
|
||||
- link "Database" [ref=e88] [cursor=pointer]:
|
||||
- /url: /codegen/database
|
||||
- generic [ref=e89]: database
|
||||
- generic [ref=e90]: Database
|
||||
- group "Testing" [ref=e91]:
|
||||
- heading "Testing" [level=3] [ref=e92]
|
||||
- list "Testing" [ref=e93]:
|
||||
- listitem [ref=e94]:
|
||||
- link "Playwright" [ref=e95] [cursor=pointer]:
|
||||
- /url: /codegen/playwright
|
||||
- generic [ref=e96]: bug_report
|
||||
- generic [ref=e97]: Playwright
|
||||
- listitem [ref=e98]:
|
||||
- link "Unit Tests" [ref=e99] [cursor=pointer]:
|
||||
- /url: /codegen/unit-tests
|
||||
- generic [ref=e100]: science
|
||||
- generic [ref=e101]: Unit Tests
|
||||
- listitem [ref=e102]:
|
||||
- link "Storybook" [ref=e103] [cursor=pointer]:
|
||||
- /url: /codegen/storybook
|
||||
- generic [ref=e104]: auto_stories
|
||||
- generic [ref=e105]: Storybook
|
||||
- group "System" [ref=e106]:
|
||||
- heading "System" [level=3] [ref=e107]
|
||||
- list "System" [ref=e108]:
|
||||
- listitem [ref=e109]:
|
||||
- link "Settings" [ref=e110] [cursor=pointer]:
|
||||
- /url: /codegen/settings
|
||||
- generic [ref=e111]: settings
|
||||
- generic [ref=e112]: Settings
|
||||
- listitem [ref=e113]:
|
||||
- link "Documentation" [ref=e114] [cursor=pointer]:
|
||||
- /url: /codegen/docs
|
||||
- generic [ref=e115]: description
|
||||
- generic [ref=e116]: Documentation
|
||||
- listitem [ref=e117]:
|
||||
- link "Features" [ref=e118] [cursor=pointer]:
|
||||
- /url: /codegen/features
|
||||
- generic [ref=e119]: toggle_on
|
||||
- generic [ref=e120]: Features
|
||||
- listitem [ref=e121]:
|
||||
- link "Errors" [ref=e122] [cursor=pointer]:
|
||||
- /url: /codegen/errors
|
||||
- generic [ref=e123]: error
|
||||
- generic [ref=e124]: Errors
|
||||
- listitem [ref=e125]:
|
||||
- link "Persistence" [ref=e126] [cursor=pointer]:
|
||||
- /url: /codegen/persistence
|
||||
- generic [ref=e127]: storage
|
||||
- generic [ref=e128]: Persistence
|
||||
- listitem [ref=e129]:
|
||||
- link "PWA" [ref=e130] [cursor=pointer]:
|
||||
- /url: /codegen/pwa
|
||||
- generic [ref=e131]: install_desktop
|
||||
- generic [ref=e132]: PWA
|
||||
- main [ref=e133]:
|
||||
- paragraph [ref=e137]: Loading projectdashboard...
|
||||
- alert [ref=e138]
|
||||
@@ -1,324 +0,0 @@
|
||||
- generic [ref=e3]:
|
||||
- banner "Storybook" [ref=e7]:
|
||||
- heading "Storybook" [level=1] [ref=e8]
|
||||
- img
|
||||
- generic [ref=e12]:
|
||||
- generic [ref=e14]:
|
||||
- link "Skip to content" [ref=e15] [cursor=pointer]:
|
||||
- /url: "#storybook-preview-wrapper"
|
||||
- link "Storybook" [ref=e17] [cursor=pointer]:
|
||||
- /url: ./
|
||||
- img "Storybook" [ref=e18]
|
||||
- switch "Settings" [ref=e23] [cursor=pointer]:
|
||||
- img [ref=e24]
|
||||
- generic [ref=e27]: Search for components
|
||||
- search [ref=e28]:
|
||||
- combobox "Search for components" [ref=e29]:
|
||||
- generic:
|
||||
- img
|
||||
- searchbox "Search for components" [ref=e30]
|
||||
- code:
|
||||
- generic: ⌘
|
||||
- text: K
|
||||
- button "Tag filters" [ref=e32] [cursor=pointer]:
|
||||
- img [ref=e33]
|
||||
- navigation "Stories" [ref=e36]:
|
||||
- heading "Stories" [level=2] [ref=e37]
|
||||
- generic [ref=e39]:
|
||||
- generic [ref=e40]:
|
||||
- link "Introduction" [ref=e41] [cursor=pointer]:
|
||||
- /url: /storybook/?path=/docs/introduction--docs
|
||||
- img [ref=e43]
|
||||
- text: Introduction
|
||||
- link "Skip to content" [ref=e161] [cursor=pointer]:
|
||||
- /url: "#storybook-preview-wrapper"
|
||||
- generic [ref=e45]:
|
||||
- button "Collapse" [expanded] [ref=e46] [cursor=pointer]:
|
||||
- img [ref=e48]
|
||||
- text: Developer
|
||||
- button "Expand all" [ref=e50] [cursor=pointer]:
|
||||
- img [ref=e51]
|
||||
- link "Styles System" [ref=e54] [cursor=pointer]:
|
||||
- /url: /storybook/?path=/docs/developer-styles-system--docs
|
||||
- img [ref=e56]
|
||||
- text: Styles System
|
||||
- generic [ref=e58]:
|
||||
- button "Collapse" [expanded] [ref=e59] [cursor=pointer]:
|
||||
- img [ref=e61]
|
||||
- text: Packages
|
||||
- button "Expand all" [ref=e63] [cursor=pointer]:
|
||||
- img [ref=e64]
|
||||
- button "Auto-Discovered" [ref=e67] [cursor=pointer]:
|
||||
- generic [ref=e68]:
|
||||
- img [ref=e70]
|
||||
- img [ref=e72]
|
||||
- text: Auto-Discovered
|
||||
- button "JSON Components" [ref=e75] [cursor=pointer]:
|
||||
- generic [ref=e76]:
|
||||
- img [ref=e78]
|
||||
- img [ref=e80]
|
||||
- text: JSON Components
|
||||
- button "UI Home" [ref=e83] [cursor=pointer]:
|
||||
- generic [ref=e84]:
|
||||
- img [ref=e86]
|
||||
- img [ref=e88]
|
||||
- text: UI Home
|
||||
- button "UI Level 2" [ref=e91] [cursor=pointer]:
|
||||
- generic [ref=e92]:
|
||||
- img [ref=e94]
|
||||
- img [ref=e96]
|
||||
- text: UI Level 2
|
||||
- button "UI Level 3" [ref=e99] [cursor=pointer]:
|
||||
- generic [ref=e100]:
|
||||
- img [ref=e102]
|
||||
- img [ref=e104]
|
||||
- text: UI Level 3
|
||||
- button "UI Level 4" [ref=e107] [cursor=pointer]:
|
||||
- generic [ref=e108]:
|
||||
- img [ref=e110]
|
||||
- img [ref=e112]
|
||||
- text: UI Level 4
|
||||
- generic [ref=e114]:
|
||||
- button "Collapse" [expanded] [ref=e115] [cursor=pointer]:
|
||||
- img [ref=e117]
|
||||
- text: Components
|
||||
- button "Expand all" [ref=e119] [cursor=pointer]:
|
||||
- img [ref=e120]
|
||||
- button "Registry" [ref=e123] [cursor=pointer]:
|
||||
- generic [ref=e124]:
|
||||
- img [ref=e126]
|
||||
- img [ref=e128]
|
||||
- text: Registry
|
||||
- generic [ref=e130]:
|
||||
- button "Collapse" [expanded] [ref=e131] [cursor=pointer]:
|
||||
- img [ref=e133]
|
||||
- text: Design System
|
||||
- button "Expand all" [ref=e135] [cursor=pointer]:
|
||||
- img [ref=e136]
|
||||
- button "Tokens" [ref=e139] [cursor=pointer]:
|
||||
- generic [ref=e140]:
|
||||
- img [ref=e142]
|
||||
- img [ref=e144]
|
||||
- text: Tokens
|
||||
- generic [ref=e147]:
|
||||
- region "Toolbar" [ref=e148]:
|
||||
- heading "Toolbar" [level=2] [ref=e149]
|
||||
- toolbar [ref=e150]:
|
||||
- generic [ref=e162]:
|
||||
- switch "Grid visibility" [ref=e163] [cursor=pointer]:
|
||||
- img [ref=e164]
|
||||
- button "Preview background" [ref=e166] [cursor=pointer]:
|
||||
- img [ref=e167]
|
||||
- switch "Outline tool" [ref=e170] [cursor=pointer]:
|
||||
- img [ref=e171]
|
||||
- button "Enter full screen" [ref=e174] [cursor=pointer]:
|
||||
- img [ref=e175]
|
||||
- main "Main preview area" [ref=e151]:
|
||||
- heading "Main preview area" [level=2] [ref=e152]
|
||||
- generic [ref=e156]:
|
||||
- link "Skip to sidebar" [ref=e177] [cursor=pointer]:
|
||||
- /url: "#introduction--docs"
|
||||
- iframe [ref=e160]:
|
||||
- generic [ref=f1e51]:
|
||||
- heading "MetaBuilder Package Storybook" [level=1] [ref=f1e52]:
|
||||
- link [ref=f1e53] [cursor=pointer]:
|
||||
- /url: "#metabuilder-package-storybook"
|
||||
- text: MetaBuilder Package Storybook
|
||||
- paragraph [ref=f1e54]:
|
||||
- text: This Storybook renders
|
||||
- strong [ref=f1e55]: MetaBuilder packages backed by JSON scripts
|
||||
- text: from the MetaBuilder platform without running the actual application.
|
||||
- heading "Quick Start" [level=2] [ref=f1e56]:
|
||||
- link [ref=f1e57] [cursor=pointer]:
|
||||
- /url: "#quick-start"
|
||||
- text: Quick Start
|
||||
- list [ref=f1e58]:
|
||||
- listitem [ref=f1e59]:
|
||||
- strong [ref=f1e60]: Explorer
|
||||
- text: "- Use the Auto-Discovered Packages → Explorer to browse all packages interactively"
|
||||
- listitem [ref=f1e61]:
|
||||
- strong [ref=f1e62]: Component Registry
|
||||
- text: "- See all available components in Components → Registry"
|
||||
- listitem [ref=f1e63]:
|
||||
- strong [ref=f1e64]: Manual Stories
|
||||
- text: "- Pre-configured stories in JSON package renders"
|
||||
- heading "Auto-Discovery" [level=2] [ref=f1e65]:
|
||||
- link [ref=f1e66] [cursor=pointer]:
|
||||
- /url: "#auto-discovery"
|
||||
- text: Auto-Discovery
|
||||
- paragraph [ref=f1e67]:
|
||||
- text: The storybook automatically discovers packages using
|
||||
- code [ref=f1e68]: storybook.config.json
|
||||
- text: ":"
|
||||
- generic [ref=f1e70]:
|
||||
- generic [ref=f1e75]: "{ \"discovery\": { \"enabled\": true, \"includedCategories\": [\"ui\", \"admin\", \"gaming\", \"social\", \"editors\"], \"excludedPackages\": [\"shared\", \"testing\"], \"minLevel\": 1, \"maxLevel\": 6 } }"
|
||||
- button "Copy" [ref=f1e77] [cursor=pointer]
|
||||
- heading "Context Variants" [level=3] [ref=f1e78]:
|
||||
- link [ref=f1e79] [cursor=pointer]:
|
||||
- /url: "#context-variants"
|
||||
- text: Context Variants
|
||||
- paragraph [ref=f1e80]: "Test packages with different user contexts:"
|
||||
- list [ref=f1e81]:
|
||||
- listitem [ref=f1e82]:
|
||||
- strong [ref=f1e83]: Guest
|
||||
- text: "- Level 1 user"
|
||||
- listitem [ref=f1e84]:
|
||||
- strong [ref=f1e85]: Admin
|
||||
- text: "- Level 4 user"
|
||||
- listitem [ref=f1e86]:
|
||||
- strong [ref=f1e87]: Admin (Nerd Mode)
|
||||
- text: "- Level 4 with nerdMode enabled"
|
||||
- listitem [ref=f1e88]:
|
||||
- strong [ref=f1e89]: Supergod
|
||||
- text: "- Level 6 user"
|
||||
- heading "How It Works" [level=2] [ref=f1e90]:
|
||||
- link [ref=f1e91] [cursor=pointer]:
|
||||
- /url: "#how-it-works"
|
||||
- text: How It Works
|
||||
- list [ref=f1e92]:
|
||||
- listitem [ref=f1e93]:
|
||||
- strong [ref=f1e94]: JSON script packages
|
||||
- text: in
|
||||
- code [ref=f1e95]: /packages/*/seed/scripts/
|
||||
- text: define UI component trees
|
||||
- listitem [ref=f1e96]:
|
||||
- strong [ref=f1e97]: Mock data
|
||||
- text: mirrors the output structure produced by the JSON scripts
|
||||
- listitem [ref=f1e98]:
|
||||
- strong [ref=f1e99]: PackageRenderer
|
||||
- text: (still the runtime entry) converts the component tree to React components
|
||||
- listitem [ref=f1e100]:
|
||||
- strong [ref=f1e101]: Component Registry
|
||||
- text: maps package-defined type names to React implementations
|
||||
- heading "Package Structure" [level=2] [ref=f1e102]:
|
||||
- link [ref=f1e103] [cursor=pointer]:
|
||||
- /url: "#package-structure"
|
||||
- text: Package Structure
|
||||
- paragraph [ref=f1e104]: "Each JSON script package follows this structure:"
|
||||
- generic [ref=f1e106]:
|
||||
- generic [ref=f1e111]: "packages/ └── {package_name}/ └── seed/ ├── metadata.json # Package info ├── components.json # Component definitions └── scripts/ └── [script-name].json # JSON script definitions following script_schema.json # Must include full function implementations with bodies, # not just metadata declarations (e.g., automation.json)"
|
||||
- button "Copy" [ref=f1e113] [cursor=pointer]
|
||||
- heading "JSON Script Output" [level=2] [ref=f1e114]:
|
||||
- link [ref=f1e115] [cursor=pointer]:
|
||||
- /url: "#json-script-output"
|
||||
- text: JSON Script Output
|
||||
- paragraph [ref=f1e116]: "JSON script functions return component trees like:"
|
||||
- generic [ref=f1e118]:
|
||||
- generic [ref=f1e123]:
|
||||
- text: "{ \"type\": \"Card\", \"props\": { \"className\": \"p-4\" }, \"children\": [ { \"type\": \"Typography\", \"props\": { \"variant\": \"h5\", \"text\": \"Title\" } }, { \"type\": \"Button\", \"props\": { \"children\": \"Click Me\" } } ]"
|
||||
- text: "}"
|
||||
- button "Copy" [ref=f1e125] [cursor=pointer]
|
||||
- heading "Adding New Package Mocks" [level=2] [ref=f1e126]:
|
||||
- link [ref=f1e127] [cursor=pointer]:
|
||||
- /url: "#adding-new-package-mocks"
|
||||
- text: Adding New Package Mocks
|
||||
- list [ref=f1e128]:
|
||||
- listitem [ref=f1e129]:
|
||||
- text: Create a file in
|
||||
- code [ref=f1e130]: "src/mocks/packages/{package-name}.ts"
|
||||
- listitem [ref=f1e131]:
|
||||
- text: Define the
|
||||
- code [ref=f1e132]: MockPackageDefinition
|
||||
- text: with metadata and renders
|
||||
- listitem [ref=f1e133]:
|
||||
- text: Call
|
||||
- code [ref=f1e134]: registerMockPackage()
|
||||
- text: to register it
|
||||
- listitem [ref=f1e135]:
|
||||
- text: Import it in
|
||||
- code [ref=f1e136]: src/mocks/packages/index.ts
|
||||
- listitem [ref=f1e137]:
|
||||
- text: Create stories in
|
||||
- code [ref=f1e138]: src/stories/
|
||||
- heading "Available Component Types" [level=2] [ref=f1e139]:
|
||||
- link [ref=f1e140] [cursor=pointer]:
|
||||
- /url: "#available-component-types"
|
||||
- text: Available Component Types
|
||||
- paragraph [ref=f1e141]: "The component registry maps these package types to React:"
|
||||
- heading "Layout" [level=3] [ref=f1e142]:
|
||||
- link [ref=f1e143] [cursor=pointer]:
|
||||
- /url: "#layout"
|
||||
- text: Layout
|
||||
- list [ref=f1e144]:
|
||||
- listitem [ref=f1e145]:
|
||||
- code [ref=f1e146]: Box
|
||||
- text: ","
|
||||
- code [ref=f1e147]: Stack
|
||||
- text: ","
|
||||
- code [ref=f1e148]: Flex
|
||||
- text: ","
|
||||
- code [ref=f1e149]: Grid
|
||||
- text: ","
|
||||
- code [ref=f1e150]: Container
|
||||
- heading "Surfaces" [level=3] [ref=f1e151]:
|
||||
- link [ref=f1e152] [cursor=pointer]:
|
||||
- /url: "#surfaces"
|
||||
- text: Surfaces
|
||||
- list [ref=f1e153]:
|
||||
- listitem [ref=f1e154]:
|
||||
- code [ref=f1e155]: Card
|
||||
- text: ","
|
||||
- code [ref=f1e156]: CardHeader
|
||||
- text: ","
|
||||
- code [ref=f1e157]: CardContent
|
||||
- text: ","
|
||||
- code [ref=f1e158]: CardActions
|
||||
- text: ","
|
||||
- code [ref=f1e159]: Paper
|
||||
- heading "Typography" [level=3] [ref=f1e160]:
|
||||
- link [ref=f1e161] [cursor=pointer]:
|
||||
- /url: "#typography"
|
||||
- text: Typography
|
||||
- list [ref=f1e162]:
|
||||
- listitem [ref=f1e163]:
|
||||
- code [ref=f1e164]: Typography
|
||||
- text: "(with variants: h1-h6, body1, body2, caption, overline)"
|
||||
- heading "Inputs" [level=3] [ref=f1e165]:
|
||||
- link [ref=f1e166] [cursor=pointer]:
|
||||
- /url: "#inputs"
|
||||
- text: Inputs
|
||||
- list [ref=f1e167]:
|
||||
- listitem [ref=f1e168]:
|
||||
- code [ref=f1e169]: Button
|
||||
- text: "(variants: contained, outlined, text)"
|
||||
- heading "Display" [level=3] [ref=f1e170]:
|
||||
- link [ref=f1e171] [cursor=pointer]:
|
||||
- /url: "#display"
|
||||
- text: Display
|
||||
- list [ref=f1e172]:
|
||||
- listitem [ref=f1e173]:
|
||||
- code [ref=f1e174]: Icon
|
||||
- text: ","
|
||||
- code [ref=f1e175]: Avatar
|
||||
- text: ","
|
||||
- code [ref=f1e176]: Badge
|
||||
- text: ","
|
||||
- code [ref=f1e177]: Chip
|
||||
- text: ","
|
||||
- code [ref=f1e178]: Divider
|
||||
- text: ","
|
||||
- code [ref=f1e179]: Alert
|
||||
- heading "Navigation" [level=3] [ref=f1e180]:
|
||||
- link [ref=f1e181] [cursor=pointer]:
|
||||
- /url: "#navigation"
|
||||
- text: Navigation
|
||||
- list [ref=f1e182]:
|
||||
- listitem [ref=f1e183]:
|
||||
- code [ref=f1e184]: Tabs
|
||||
- text: ","
|
||||
- code [ref=f1e185]: Tab
|
||||
- heading "App-Specific" [level=3] [ref=f1e186]:
|
||||
- link [ref=f1e187] [cursor=pointer]:
|
||||
- /url: "#app-specific"
|
||||
- text: App-Specific
|
||||
- list [ref=f1e188]:
|
||||
- listitem [ref=f1e189]:
|
||||
- code [ref=f1e190]: Level4Header
|
||||
- text: ","
|
||||
- code [ref=f1e191]: IntroSection
|
||||
- text: ","
|
||||
- code [ref=f1e192]: AppHeader
|
||||
- text: ","
|
||||
- code [ref=f1e193]: AppFooter
|
||||
- text: ","
|
||||
- code [ref=f1e194]: Sidebar
|
||||
@@ -1,32 +0,0 @@
|
||||
- generic [active] [ref=e1]:
|
||||
- alert [ref=e2]
|
||||
- generic [ref=e4]:
|
||||
- banner [ref=e5]:
|
||||
- generic [ref=e7]:
|
||||
- generic [ref=e8]:
|
||||
- button "Toggle navigation menu" [ref=e9]:
|
||||
- img [ref=e10]
|
||||
- img [ref=e13]
|
||||
- text: CodeSnippet
|
||||
- generic "Disconnected from backend - Using local storage" [ref=e17]:
|
||||
- 'status "Status: Local" [ref=e18]':
|
||||
- img [ref=e20]
|
||||
- generic [ref=e24]: Local
|
||||
- main [ref=e25]:
|
||||
- region "Application status alerts" [ref=e27]:
|
||||
- status [ref=e28]:
|
||||
- img [ref=e29]
|
||||
- heading "Workspace ready" [level=5] [ref=e31]
|
||||
- generic [ref=e32]: Running in local-first mode so you can work offline without a backend.
|
||||
- alert [ref=e33]:
|
||||
- img [ref=e34]
|
||||
- heading "Cloud backend unavailable" [level=5] [ref=e36]
|
||||
- generic [ref=e37]: No Flask backend detected. Saving and loading will stay on this device until a server URL is configured.
|
||||
- generic [ref=e39]:
|
||||
- heading "My Snippets" [level=1] [ref=e40]
|
||||
- paragraph [ref=e41]: Save, organize, and share your code snippets
|
||||
- contentinfo [ref=e42]:
|
||||
- generic [ref=e44]:
|
||||
- paragraph [ref=e45]: Save, organize, and share your code snippets with beautiful syntax highlighting and live execution
|
||||
- paragraph [ref=e46]: Supports React preview and Python execution via Pyodide
|
||||
- region "Notifications alt+T"
|
||||
@@ -1,225 +0,0 @@
|
||||
- generic [active] [ref=e1]:
|
||||
- generic [ref=e3]:
|
||||
- banner [ref=e4]:
|
||||
- generic [ref=e5]:
|
||||
- button "Toggle sidebar" [expanded] [ref=e6] [cursor=pointer]:
|
||||
- generic [ref=e7]: menu
|
||||
- generic [ref=e8]:
|
||||
- generic [ref=e9]: code
|
||||
- heading "CodeForge" [level=1] [ref=e10]
|
||||
- button "Switch to dark mode" [ref=e12] [cursor=pointer]:
|
||||
- generic [ref=e13]: dark_mode
|
||||
- generic [ref=e14]:
|
||||
- complementary "Navigation sidebar" [ref=e15]:
|
||||
- paragraph [ref=e17]: Navigation
|
||||
- navigation "Main navigation" [ref=e18]:
|
||||
- group "Main" [ref=e19]:
|
||||
- heading "Main" [level=3] [ref=e20]
|
||||
- list "Main" [ref=e21]:
|
||||
- listitem [ref=e22]:
|
||||
- link "Dashboard" [ref=e23] [cursor=pointer]:
|
||||
- /url: /codegen
|
||||
- generic [ref=e24]: dashboard
|
||||
- generic [ref=e25]: Dashboard
|
||||
- listitem [ref=e26]:
|
||||
- link "Code Editor" [ref=e27] [cursor=pointer]:
|
||||
- /url: /codegen/code
|
||||
- generic [ref=e28]: code
|
||||
- generic [ref=e29]: Code Editor
|
||||
- listitem [ref=e30]:
|
||||
- link "Components" [ref=e31] [cursor=pointer]:
|
||||
- /url: /codegen/components
|
||||
- generic [ref=e32]: widgets
|
||||
- generic [ref=e33]: Components
|
||||
- listitem [ref=e34]:
|
||||
- link "Models" [ref=e35] [cursor=pointer]:
|
||||
- /url: /codegen/models
|
||||
- generic [ref=e36]: schema
|
||||
- generic [ref=e37]: Models
|
||||
- group "Design" [ref=e38]:
|
||||
- heading "Design" [level=3] [ref=e39]
|
||||
- list "Design" [ref=e40]:
|
||||
- listitem [ref=e41]:
|
||||
- link "Component Trees" [ref=e42] [cursor=pointer]:
|
||||
- /url: /codegen/component-trees
|
||||
- generic [ref=e43]: account_tree
|
||||
- generic [ref=e44]: Component Trees
|
||||
- listitem [ref=e45]:
|
||||
- link "Styling" [ref=e46] [cursor=pointer]:
|
||||
- /url: /codegen/styling
|
||||
- generic [ref=e47]: palette
|
||||
- generic [ref=e48]: Styling
|
||||
- listitem [ref=e49]:
|
||||
- link "Sass" [ref=e50] [cursor=pointer]:
|
||||
- /url: /codegen/sass
|
||||
- generic [ref=e51]: style
|
||||
- generic [ref=e52]: Sass
|
||||
- listitem [ref=e53]:
|
||||
- link "Atomic Library" [ref=e54] [cursor=pointer]:
|
||||
- /url: /codegen/atomic-library
|
||||
- generic [ref=e55]: library_books
|
||||
- generic [ref=e56]: Atomic Library
|
||||
- listitem [ref=e57]:
|
||||
- link "Templates" [ref=e58] [cursor=pointer]:
|
||||
- /url: /codegen/templates
|
||||
- generic [ref=e59]: content_copy
|
||||
- generic [ref=e60]: Templates
|
||||
- group "Workflows" [ref=e61]:
|
||||
- heading "Workflows" [level=3] [ref=e62]
|
||||
- list "Workflows" [ref=e63]:
|
||||
- listitem [ref=e64]:
|
||||
- link "Workflows" [ref=e65] [cursor=pointer]:
|
||||
- /url: /codegen/workflows
|
||||
- generic [ref=e66]: share
|
||||
- generic [ref=e67]: Workflows
|
||||
- listitem [ref=e68]:
|
||||
- link "Lambdas" [ref=e69] [cursor=pointer]:
|
||||
- /url: /codegen/lambdas
|
||||
- generic [ref=e70]: functions
|
||||
- generic [ref=e71]: Lambdas
|
||||
- group "Tools" [ref=e72]:
|
||||
- heading "Tools" [level=3] [ref=e73]
|
||||
- list "Tools" [ref=e74]:
|
||||
- listitem [ref=e75]:
|
||||
- link "JSON UI" [ref=e76] [cursor=pointer]:
|
||||
- /url: /codegen/json-ui
|
||||
- generic [ref=e77]: data_object
|
||||
- generic [ref=e78]: JSON UI
|
||||
- listitem [ref=e79]:
|
||||
- link "Schema Editor" [ref=e80] [cursor=pointer]:
|
||||
- /url: /codegen/schema-editor
|
||||
- generic [ref=e81]: edit_note
|
||||
- generic [ref=e82]: Schema Editor
|
||||
- listitem [ref=e83]:
|
||||
- link "Data Binding" [ref=e84] [cursor=pointer]:
|
||||
- /url: /codegen/data-binding
|
||||
- generic [ref=e85]: link
|
||||
- generic [ref=e86]: Data Binding
|
||||
- listitem [ref=e87]:
|
||||
- link "Database" [ref=e88] [cursor=pointer]:
|
||||
- /url: /codegen/database
|
||||
- generic [ref=e89]: database
|
||||
- generic [ref=e90]: Database
|
||||
- group "Testing" [ref=e91]:
|
||||
- heading "Testing" [level=3] [ref=e92]
|
||||
- list "Testing" [ref=e93]:
|
||||
- listitem [ref=e94]:
|
||||
- link "Playwright" [ref=e95] [cursor=pointer]:
|
||||
- /url: /codegen/playwright
|
||||
- generic [ref=e96]: bug_report
|
||||
- generic [ref=e97]: Playwright
|
||||
- listitem [ref=e98]:
|
||||
- link "Unit Tests" [ref=e99] [cursor=pointer]:
|
||||
- /url: /codegen/unit-tests
|
||||
- generic [ref=e100]: science
|
||||
- generic [ref=e101]: Unit Tests
|
||||
- listitem [ref=e102]:
|
||||
- link "Storybook" [ref=e103] [cursor=pointer]:
|
||||
- /url: /codegen/storybook
|
||||
- generic [ref=e104]: auto_stories
|
||||
- generic [ref=e105]: Storybook
|
||||
- group "System" [ref=e106]:
|
||||
- heading "System" [level=3] [ref=e107]
|
||||
- list "System" [ref=e108]:
|
||||
- listitem [ref=e109]:
|
||||
- link "Settings" [ref=e110] [cursor=pointer]:
|
||||
- /url: /codegen/settings
|
||||
- generic [ref=e111]: settings
|
||||
- generic [ref=e112]: Settings
|
||||
- listitem [ref=e113]:
|
||||
- link "Documentation" [ref=e114] [cursor=pointer]:
|
||||
- /url: /codegen/docs
|
||||
- generic [ref=e115]: description
|
||||
- generic [ref=e116]: Documentation
|
||||
- listitem [ref=e117]:
|
||||
- link "Features" [ref=e118] [cursor=pointer]:
|
||||
- /url: /codegen/features
|
||||
- generic [ref=e119]: toggle_on
|
||||
- generic [ref=e120]: Features
|
||||
- listitem [ref=e121]:
|
||||
- link "Errors" [ref=e122] [cursor=pointer]:
|
||||
- /url: /codegen/errors
|
||||
- generic [ref=e123]: error
|
||||
- generic [ref=e124]: Errors
|
||||
- listitem [ref=e125]:
|
||||
- link "Persistence" [ref=e126] [cursor=pointer]:
|
||||
- /url: /codegen/persistence
|
||||
- generic [ref=e127]: storage
|
||||
- generic [ref=e128]: Persistence
|
||||
- listitem [ref=e129]:
|
||||
- link "PWA" [ref=e130] [cursor=pointer]:
|
||||
- /url: /codegen/pwa
|
||||
- generic [ref=e131]: install_desktop
|
||||
- generic [ref=e132]: PWA
|
||||
- main [ref=e133]:
|
||||
- generic [ref=e139]:
|
||||
- generic [ref=e140]:
|
||||
- heading "Project Dashboard" [level=1] [ref=e141]
|
||||
- paragraph [ref=e142]: Overview of your CodeForge project
|
||||
- generic [ref=e143]:
|
||||
- generic [ref=e144]:
|
||||
- generic [ref=e146]:
|
||||
- generic [ref=e148]: task_alt
|
||||
- text: Project Completeness
|
||||
- generic [ref=e149]:
|
||||
- generic [ref=e151]: 70%
|
||||
- generic [ref=e153]: Ready to Export
|
||||
- progressbar [ref=e154]
|
||||
- paragraph [ref=e156]: Great progress! Consider adding more tests.
|
||||
- generic [ref=e157]:
|
||||
- generic [ref=e159]:
|
||||
- generic [ref=e161]: build_circle
|
||||
- text: GitHub Build Status
|
||||
- generic [ref=e162]:
|
||||
- generic [ref=e163]:
|
||||
- generic [ref=e164]: Build
|
||||
- generic [ref=e165]: Passing
|
||||
- generic [ref=e167]:
|
||||
- generic [ref=e168]: Type Check
|
||||
- generic [ref=e169]: Passing
|
||||
- generic [ref=e171]:
|
||||
- generic [ref=e172]: Lint
|
||||
- generic [ref=e173]: Passing
|
||||
- generic [ref=e175]:
|
||||
- generic [ref=e176]: E2E Tests
|
||||
- generic [ref=e177]: Idle
|
||||
- generic [ref=e179]:
|
||||
- generic [ref=e181]:
|
||||
- generic [ref=e182]:
|
||||
- generic [ref=e183]: Code Files
|
||||
- generic [ref=e185]: code_blocks
|
||||
- generic [ref=e186]: "4"
|
||||
- generic [ref=e187]: files in your project
|
||||
- generic [ref=e189]:
|
||||
- generic [ref=e190]:
|
||||
- generic [ref=e191]: Database Models
|
||||
- generic [ref=e193]: storage
|
||||
- generic [ref=e194]: "3"
|
||||
- generic [ref=e195]: Prisma schemas
|
||||
- generic [ref=e197]:
|
||||
- generic [ref=e198]:
|
||||
- generic [ref=e199]: Components
|
||||
- generic [ref=e201]: view_in_ar
|
||||
- generic [ref=e202]: "3"
|
||||
- generic [ref=e203]: React components
|
||||
- generic [ref=e205]:
|
||||
- generic [ref=e206]:
|
||||
- generic [ref=e207]: Workflows
|
||||
- generic [ref=e209]: account_tree
|
||||
- generic [ref=e210]: "0"
|
||||
- generic [ref=e211]: automation flows
|
||||
- generic [ref=e213]:
|
||||
- generic [ref=e214]:
|
||||
- generic [ref=e215]: API Endpoints
|
||||
- generic [ref=e217]: science
|
||||
- generic [ref=e218]: "0"
|
||||
- generic [ref=e219]: Flask routes
|
||||
- generic [ref=e221]:
|
||||
- generic [ref=e222]:
|
||||
- generic [ref=e223]: Test Suites
|
||||
- generic [ref=e225]: biotech
|
||||
- generic [ref=e226]: "0"
|
||||
- generic [ref=e227]: automated tests
|
||||
- button "Open Next.js Dev Tools" [ref=e233] [cursor=pointer]:
|
||||
- img [ref=e234]
|
||||
- alert [ref=e138]
|
||||
@@ -1,7 +0,0 @@
|
||||
- generic [ref=e3]:
|
||||
- heading "No Preview" [level=1] [ref=e4]
|
||||
- paragraph [ref=e5]: Sorry, but you either have no stories or none are selected somehow.
|
||||
- list [ref=e6]:
|
||||
- listitem [ref=e7]: Please check the Storybook config.
|
||||
- listitem [ref=e8]: Try reloading the page.
|
||||
- paragraph [ref=e9]: If the problem persists, check the browser console, or the terminal you've run Storybook from.
|
||||
@@ -1,49 +0,0 @@
|
||||
- generic [active] [ref=e1]:
|
||||
- alert [ref=e2]
|
||||
- generic [ref=e4]:
|
||||
- banner [ref=e5]:
|
||||
- generic [ref=e7]:
|
||||
- generic [ref=e8]:
|
||||
- button "Toggle navigation menu" [ref=e9]:
|
||||
- img [ref=e10]
|
||||
- img [ref=e13]
|
||||
- text: CodeSnippet
|
||||
- generic "Disconnected from backend - Using local storage" [ref=e17]:
|
||||
- 'status "Status: Local" [ref=e18]':
|
||||
- img [ref=e20]
|
||||
- generic [ref=e24]: Local
|
||||
- main [ref=e25]:
|
||||
- region "Application status alerts" [ref=e27]:
|
||||
- status [ref=e28]:
|
||||
- img [ref=e29]
|
||||
- heading "Workspace ready" [level=5] [ref=e31]
|
||||
- generic [ref=e32]: Running in local-first mode so you can work offline without a backend.
|
||||
- alert [ref=e33]:
|
||||
- img [ref=e34]
|
||||
- heading "Cloud backend unavailable" [level=5] [ref=e36]
|
||||
- generic [ref=e37]: No Flask backend detected. Saving and loading will stay on this device until a server URL is configured.
|
||||
- generic [ref=e38]:
|
||||
- generic [ref=e39]:
|
||||
- heading "My Snippets" [level=1] [ref=e40]
|
||||
- paragraph [ref=e41]: Save, organize, and share your code snippets
|
||||
- group "Namespace selector" [ref=e48]:
|
||||
- generic [ref=e49]:
|
||||
- img [ref=e50]
|
||||
- generic [ref=e52]: "Namespace:"
|
||||
- combobox "Select namespace" [ref=e53]:
|
||||
- text: default
|
||||
- img [ref=e55]
|
||||
- status "No snippets available" [ref=e57]:
|
||||
- status [ref=e58]: No snippets yet. Start building your code snippet library. Save reusable code for quick access anytime.
|
||||
- img [ref=e60]
|
||||
- heading "No snippets yet" [level=2] [ref=e63]
|
||||
- paragraph [ref=e64]: Start building your code snippet library. Save reusable code for quick access anytime.
|
||||
- button "Create new snippet from templates" [ref=e65] [cursor=pointer]:
|
||||
- img [ref=e66]
|
||||
- text: Create Your First Snippet
|
||||
- img [ref=e68]
|
||||
- contentinfo [ref=e42]:
|
||||
- generic [ref=e44]:
|
||||
- paragraph [ref=e45]: Save, organize, and share your code snippets with beautiful syntax highlighting and live execution
|
||||
- paragraph [ref=e46]: Supports React preview and Python execution via Pyodide
|
||||
- region "Notifications alt+T"
|
||||
@@ -1,7 +0,0 @@
|
||||
- generic [ref=e3]:
|
||||
- heading "No Preview" [level=1] [ref=e4]
|
||||
- paragraph [ref=e5]: Sorry, but you either have no stories or none are selected somehow.
|
||||
- list [ref=e6]:
|
||||
- listitem [ref=e7]: Please check the Storybook config.
|
||||
- listitem [ref=e8]: Try reloading the page.
|
||||
- paragraph [ref=e9]: If the problem persists, check the browser console, or the terminal you've run Storybook from.
|
||||
@@ -1,225 +0,0 @@
|
||||
- generic [active] [ref=e1]:
|
||||
- generic [ref=e3]:
|
||||
- banner [ref=e4]:
|
||||
- generic [ref=e5]:
|
||||
- button "Toggle sidebar" [expanded] [ref=e6] [cursor=pointer]:
|
||||
- generic [ref=e7]: menu
|
||||
- generic [ref=e8]:
|
||||
- generic [ref=e9]: code
|
||||
- heading "CodeForge" [level=1] [ref=e10]
|
||||
- button "Switch to dark mode" [ref=e12] [cursor=pointer]:
|
||||
- generic [ref=e13]: dark_mode
|
||||
- generic [ref=e14]:
|
||||
- complementary "Navigation sidebar" [ref=e15]:
|
||||
- paragraph [ref=e17]: Navigation
|
||||
- navigation "Main navigation" [ref=e18]:
|
||||
- group "Main" [ref=e19]:
|
||||
- heading "Main" [level=3] [ref=e20]
|
||||
- list "Main" [ref=e21]:
|
||||
- listitem [ref=e22]:
|
||||
- link "Dashboard" [ref=e23] [cursor=pointer]:
|
||||
- /url: /codegen
|
||||
- generic [ref=e24]: dashboard
|
||||
- generic [ref=e25]: Dashboard
|
||||
- listitem [ref=e26]:
|
||||
- link "Code Editor" [ref=e27] [cursor=pointer]:
|
||||
- /url: /codegen/code
|
||||
- generic [ref=e28]: code
|
||||
- generic [ref=e29]: Code Editor
|
||||
- listitem [ref=e30]:
|
||||
- link "Components" [ref=e31] [cursor=pointer]:
|
||||
- /url: /codegen/components
|
||||
- generic [ref=e32]: widgets
|
||||
- generic [ref=e33]: Components
|
||||
- listitem [ref=e34]:
|
||||
- link "Models" [ref=e35] [cursor=pointer]:
|
||||
- /url: /codegen/models
|
||||
- generic [ref=e36]: schema
|
||||
- generic [ref=e37]: Models
|
||||
- group "Design" [ref=e38]:
|
||||
- heading "Design" [level=3] [ref=e39]
|
||||
- list "Design" [ref=e40]:
|
||||
- listitem [ref=e41]:
|
||||
- link "Component Trees" [ref=e42] [cursor=pointer]:
|
||||
- /url: /codegen/component-trees
|
||||
- generic [ref=e43]: account_tree
|
||||
- generic [ref=e44]: Component Trees
|
||||
- listitem [ref=e45]:
|
||||
- link "Styling" [ref=e46] [cursor=pointer]:
|
||||
- /url: /codegen/styling
|
||||
- generic [ref=e47]: palette
|
||||
- generic [ref=e48]: Styling
|
||||
- listitem [ref=e49]:
|
||||
- link "Sass" [ref=e50] [cursor=pointer]:
|
||||
- /url: /codegen/sass
|
||||
- generic [ref=e51]: style
|
||||
- generic [ref=e52]: Sass
|
||||
- listitem [ref=e53]:
|
||||
- link "Atomic Library" [ref=e54] [cursor=pointer]:
|
||||
- /url: /codegen/atomic-library
|
||||
- generic [ref=e55]: library_books
|
||||
- generic [ref=e56]: Atomic Library
|
||||
- listitem [ref=e57]:
|
||||
- link "Templates" [ref=e58] [cursor=pointer]:
|
||||
- /url: /codegen/templates
|
||||
- generic [ref=e59]: content_copy
|
||||
- generic [ref=e60]: Templates
|
||||
- group "Workflows" [ref=e61]:
|
||||
- heading "Workflows" [level=3] [ref=e62]
|
||||
- list "Workflows" [ref=e63]:
|
||||
- listitem [ref=e64]:
|
||||
- link "Workflows" [ref=e65] [cursor=pointer]:
|
||||
- /url: /codegen/workflows
|
||||
- generic [ref=e66]: share
|
||||
- generic [ref=e67]: Workflows
|
||||
- listitem [ref=e68]:
|
||||
- link "Lambdas" [ref=e69] [cursor=pointer]:
|
||||
- /url: /codegen/lambdas
|
||||
- generic [ref=e70]: functions
|
||||
- generic [ref=e71]: Lambdas
|
||||
- group "Tools" [ref=e72]:
|
||||
- heading "Tools" [level=3] [ref=e73]
|
||||
- list "Tools" [ref=e74]:
|
||||
- listitem [ref=e75]:
|
||||
- link "JSON UI" [ref=e76] [cursor=pointer]:
|
||||
- /url: /codegen/json-ui
|
||||
- generic [ref=e77]: data_object
|
||||
- generic [ref=e78]: JSON UI
|
||||
- listitem [ref=e79]:
|
||||
- link "Schema Editor" [ref=e80] [cursor=pointer]:
|
||||
- /url: /codegen/schema-editor
|
||||
- generic [ref=e81]: edit_note
|
||||
- generic [ref=e82]: Schema Editor
|
||||
- listitem [ref=e83]:
|
||||
- link "Data Binding" [ref=e84] [cursor=pointer]:
|
||||
- /url: /codegen/data-binding
|
||||
- generic [ref=e85]: link
|
||||
- generic [ref=e86]: Data Binding
|
||||
- listitem [ref=e87]:
|
||||
- link "Database" [ref=e88] [cursor=pointer]:
|
||||
- /url: /codegen/database
|
||||
- generic [ref=e89]: database
|
||||
- generic [ref=e90]: Database
|
||||
- group "Testing" [ref=e91]:
|
||||
- heading "Testing" [level=3] [ref=e92]
|
||||
- list "Testing" [ref=e93]:
|
||||
- listitem [ref=e94]:
|
||||
- link "Playwright" [ref=e95] [cursor=pointer]:
|
||||
- /url: /codegen/playwright
|
||||
- generic [ref=e96]: bug_report
|
||||
- generic [ref=e97]: Playwright
|
||||
- listitem [ref=e98]:
|
||||
- link "Unit Tests" [ref=e99] [cursor=pointer]:
|
||||
- /url: /codegen/unit-tests
|
||||
- generic [ref=e100]: science
|
||||
- generic [ref=e101]: Unit Tests
|
||||
- listitem [ref=e102]:
|
||||
- link "Storybook" [ref=e103] [cursor=pointer]:
|
||||
- /url: /codegen/storybook
|
||||
- generic [ref=e104]: auto_stories
|
||||
- generic [ref=e105]: Storybook
|
||||
- group "System" [ref=e106]:
|
||||
- heading "System" [level=3] [ref=e107]
|
||||
- list "System" [ref=e108]:
|
||||
- listitem [ref=e109]:
|
||||
- link "Settings" [ref=e110] [cursor=pointer]:
|
||||
- /url: /codegen/settings
|
||||
- generic [ref=e111]: settings
|
||||
- generic [ref=e112]: Settings
|
||||
- listitem [ref=e113]:
|
||||
- link "Documentation" [ref=e114] [cursor=pointer]:
|
||||
- /url: /codegen/docs
|
||||
- generic [ref=e115]: description
|
||||
- generic [ref=e116]: Documentation
|
||||
- listitem [ref=e117]:
|
||||
- link "Features" [ref=e118] [cursor=pointer]:
|
||||
- /url: /codegen/features
|
||||
- generic [ref=e119]: toggle_on
|
||||
- generic [ref=e120]: Features
|
||||
- listitem [ref=e121]:
|
||||
- link "Errors" [ref=e122] [cursor=pointer]:
|
||||
- /url: /codegen/errors
|
||||
- generic [ref=e123]: error
|
||||
- generic [ref=e124]: Errors
|
||||
- listitem [ref=e125]:
|
||||
- link "Persistence" [ref=e126] [cursor=pointer]:
|
||||
- /url: /codegen/persistence
|
||||
- generic [ref=e127]: storage
|
||||
- generic [ref=e128]: Persistence
|
||||
- listitem [ref=e129]:
|
||||
- link "PWA" [ref=e130] [cursor=pointer]:
|
||||
- /url: /codegen/pwa
|
||||
- generic [ref=e131]: install_desktop
|
||||
- generic [ref=e132]: PWA
|
||||
- main [ref=e133]:
|
||||
- generic [ref=e139]:
|
||||
- generic [ref=e140]:
|
||||
- heading "Project Dashboard" [level=1] [ref=e141]
|
||||
- paragraph [ref=e142]: Overview of your CodeForge project
|
||||
- generic [ref=e143]:
|
||||
- generic [ref=e144]:
|
||||
- generic [ref=e146]:
|
||||
- generic [ref=e148]: task_alt
|
||||
- text: Project Completeness
|
||||
- generic [ref=e149]:
|
||||
- generic [ref=e151]: 70%
|
||||
- generic [ref=e153]: Ready to Export
|
||||
- progressbar [ref=e154]
|
||||
- paragraph [ref=e156]: Great progress! Consider adding more tests.
|
||||
- generic [ref=e157]:
|
||||
- generic [ref=e159]:
|
||||
- generic [ref=e161]: build_circle
|
||||
- text: GitHub Build Status
|
||||
- generic [ref=e162]:
|
||||
- generic [ref=e163]:
|
||||
- generic [ref=e164]: Build
|
||||
- generic [ref=e165]: Passing
|
||||
- generic [ref=e167]:
|
||||
- generic [ref=e168]: Type Check
|
||||
- generic [ref=e169]: Passing
|
||||
- generic [ref=e171]:
|
||||
- generic [ref=e172]: Lint
|
||||
- generic [ref=e173]: Passing
|
||||
- generic [ref=e175]:
|
||||
- generic [ref=e176]: E2E Tests
|
||||
- generic [ref=e177]: Idle
|
||||
- generic [ref=e179]:
|
||||
- generic [ref=e181]:
|
||||
- generic [ref=e182]:
|
||||
- generic [ref=e183]: Code Files
|
||||
- generic [ref=e185]: code_blocks
|
||||
- generic [ref=e186]: "4"
|
||||
- generic [ref=e187]: files in your project
|
||||
- generic [ref=e189]:
|
||||
- generic [ref=e190]:
|
||||
- generic [ref=e191]: Database Models
|
||||
- generic [ref=e193]: storage
|
||||
- generic [ref=e194]: "3"
|
||||
- generic [ref=e195]: Prisma schemas
|
||||
- generic [ref=e197]:
|
||||
- generic [ref=e198]:
|
||||
- generic [ref=e199]: Components
|
||||
- generic [ref=e201]: view_in_ar
|
||||
- generic [ref=e202]: "3"
|
||||
- generic [ref=e203]: React components
|
||||
- generic [ref=e205]:
|
||||
- generic [ref=e206]:
|
||||
- generic [ref=e207]: Workflows
|
||||
- generic [ref=e209]: account_tree
|
||||
- generic [ref=e210]: "0"
|
||||
- generic [ref=e211]: automation flows
|
||||
- generic [ref=e213]:
|
||||
- generic [ref=e214]:
|
||||
- generic [ref=e215]: API Endpoints
|
||||
- generic [ref=e217]: science
|
||||
- generic [ref=e218]: "0"
|
||||
- generic [ref=e219]: Flask routes
|
||||
- generic [ref=e221]:
|
||||
- generic [ref=e222]:
|
||||
- generic [ref=e223]: Test Suites
|
||||
- generic [ref=e225]: biotech
|
||||
- generic [ref=e226]: "0"
|
||||
- generic [ref=e227]: automated tests
|
||||
- button "Open Next.js Dev Tools" [ref=e233] [cursor=pointer]:
|
||||
- img [ref=e234]
|
||||
- alert [ref=e138]
|
||||
@@ -1,5 +0,0 @@
|
||||
- generic [active] [ref=e1]:
|
||||
- generic [ref=e3]:
|
||||
- heading "404" [level=1] [ref=e4]
|
||||
- heading "This page could not be found." [level=2] [ref=e6]
|
||||
- alert [ref=e7]
|
||||
@@ -1,10 +0,0 @@
|
||||
- generic [ref=e2]:
|
||||
- banner [ref=e3]:
|
||||
- heading "EXPLODED DIAGRAMS" [level=1] [ref=e4]
|
||||
- paragraph [ref=e5]: Modular Technical Illustrations
|
||||
- navigation [ref=e6]:
|
||||
- link "Home" [ref=e7] [cursor=pointer]:
|
||||
- /url: /diagrams
|
||||
- generic [ref=e8]:
|
||||
- heading "Categories" [level=2] [ref=e9]
|
||||
- paragraph [ref=e10]: Loading...
|
||||
@@ -1,5 +0,0 @@
|
||||
- generic [active] [ref=e1]:
|
||||
- generic [ref=e3]:
|
||||
- heading "404" [level=1] [ref=e4]
|
||||
- heading "This page could not be found." [level=2] [ref=e6]
|
||||
- alert [ref=e7]
|
||||
@@ -1,10 +0,0 @@
|
||||
- generic [ref=e2]:
|
||||
- banner [ref=e3]:
|
||||
- heading "EXPLODED DIAGRAMS" [level=1] [ref=e4]
|
||||
- paragraph [ref=e5]: Modular Technical Illustrations
|
||||
- navigation [ref=e6]:
|
||||
- link "Home" [ref=e7] [cursor=pointer]:
|
||||
- /url: /diagrams
|
||||
- generic [ref=e8]:
|
||||
- heading "Categories" [level=2] [ref=e9]
|
||||
- paragraph [ref=e10]: Loading...
|
||||
@@ -1 +0,0 @@
|
||||
- alert [ref=e3]
|
||||
@@ -1,127 +0,0 @@
|
||||
- generic [active] [ref=e1]:
|
||||
- alert [ref=e2]
|
||||
- generic [ref=e3]:
|
||||
- banner [ref=e4]:
|
||||
- generic [ref=e5]:
|
||||
- button "Toggle sidebar" [ref=e6] [cursor=pointer]:
|
||||
- img [ref=e7]
|
||||
- generic [ref=e8]:
|
||||
- img [ref=e9]
|
||||
- heading "WorkflowUI" [level=1] [ref=e18]
|
||||
- generic [ref=e19]:
|
||||
- button "Notifications" [ref=e21] [cursor=pointer]:
|
||||
- img [ref=e22]
|
||||
- generic [ref=e24]: "2"
|
||||
- button "Switch to dark mode" [ref=e25] [cursor=pointer]:
|
||||
- img [ref=e26]
|
||||
- generic [ref=e28]:
|
||||
- complementary "Workflows sidebar" [ref=e29]:
|
||||
- navigation [ref=e30]:
|
||||
- generic [ref=e31]:
|
||||
- heading "Main" [level=3] [ref=e32]
|
||||
- list "Main navigation" [ref=e33]:
|
||||
- listitem [ref=e34]:
|
||||
- link "Dashboard" [ref=e35] [cursor=pointer]:
|
||||
- /url: /workflowui
|
||||
- img [ref=e37]
|
||||
- generic [ref=e39]: Dashboard
|
||||
- listitem [ref=e40]:
|
||||
- link "Notifications 2" [ref=e41] [cursor=pointer]:
|
||||
- /url: /workflowui/notifications
|
||||
- img [ref=e43]
|
||||
- generic [ref=e45]: Notifications
|
||||
- generic [ref=e46]: "2"
|
||||
- generic [ref=e47]:
|
||||
- heading "Workflows" [level=3] [ref=e48]
|
||||
- list "Workflows navigation" [ref=e49]:
|
||||
- listitem [ref=e50]:
|
||||
- link "All Workflows" [ref=e51] [cursor=pointer]:
|
||||
- /url: /workflowui/workflows
|
||||
- img [ref=e53]
|
||||
- generic [ref=e55]: All Workflows
|
||||
- listitem [ref=e56]:
|
||||
- link "Recent" [ref=e57] [cursor=pointer]:
|
||||
- /url: /workflowui/workflows/recent
|
||||
- img [ref=e59]
|
||||
- generic [ref=e61]: Recent
|
||||
- listitem [ref=e62]:
|
||||
- link "Favorites" [ref=e63] [cursor=pointer]:
|
||||
- /url: /workflowui/workflows/favorites
|
||||
- img [ref=e65]
|
||||
- generic [ref=e67]: Favorites
|
||||
- listitem [ref=e68]:
|
||||
- link "Templates" [ref=e69] [cursor=pointer]:
|
||||
- /url: /workflowui/templates
|
||||
- img [ref=e71]
|
||||
- generic [ref=e73]: Templates
|
||||
- generic [ref=e74]:
|
||||
- heading "System" [level=3] [ref=e75]
|
||||
- list "System navigation" [ref=e76]:
|
||||
- listitem [ref=e77]:
|
||||
- link "Plugins" [ref=e78] [cursor=pointer]:
|
||||
- /url: /workflowui/plugins
|
||||
- img [ref=e80]
|
||||
- generic [ref=e82]: Plugins
|
||||
- listitem [ref=e83]:
|
||||
- link "Settings" [ref=e84] [cursor=pointer]:
|
||||
- /url: /workflowui/settings
|
||||
- img [ref=e86]
|
||||
- generic [ref=e88]: Settings
|
||||
- generic [ref=e89]:
|
||||
- heading "Help" [level=3] [ref=e90]
|
||||
- list "Help navigation" [ref=e91]:
|
||||
- listitem [ref=e92]:
|
||||
- link "Documentation" [ref=e93] [cursor=pointer]:
|
||||
- /url: /workflowui/docs
|
||||
- img [ref=e95]
|
||||
- generic [ref=e97]: Documentation
|
||||
- listitem [ref=e98]:
|
||||
- link "Help & Support" [ref=e99] [cursor=pointer]:
|
||||
- /url: /workflowui/help
|
||||
- img [ref=e101]
|
||||
- generic [ref=e103]: Help & Support
|
||||
- button "+ New Workflow" [ref=e105] [cursor=pointer]:
|
||||
- generic [ref=e107]: + New Workflow
|
||||
- main [ref=e108]:
|
||||
- generic [ref=e109]:
|
||||
- generic [ref=e110]:
|
||||
- generic [ref=e111]:
|
||||
- img [ref=e113]
|
||||
- generic [ref=e115]:
|
||||
- generic [ref=e116]: "23"
|
||||
- generic [ref=e117]: nodes today
|
||||
- generic [ref=e118]:
|
||||
- img [ref=e120]
|
||||
- generic [ref=e122]:
|
||||
- generic [ref=e123]: "5"
|
||||
- generic [ref=e124]: runs today
|
||||
- generic [ref=e125]:
|
||||
- img [ref=e127]
|
||||
- generic [ref=e129]:
|
||||
- generic [ref=e130]: "1"
|
||||
- generic [ref=e131]: failed
|
||||
- generic [ref=e132]:
|
||||
- img [ref=e134]
|
||||
- generic [ref=e136]:
|
||||
- generic [ref=e137]: 1.2h
|
||||
- generic [ref=e138]: saved today
|
||||
- generic [ref=e140]:
|
||||
- generic "First Steps" [ref=e141]:
|
||||
- img [ref=e142]
|
||||
- generic "Node Master" [ref=e144]:
|
||||
- img [ref=e145]
|
||||
- link "+4 more" [ref=e147] [cursor=pointer]:
|
||||
- /url: /workflowui/achievements
|
||||
- generic [ref=e148]:
|
||||
- generic [ref=e149]:
|
||||
- heading "Workspaces" [level=1] [ref=e150]
|
||||
- paragraph [ref=e151]: Organize your projects and workflows
|
||||
- button "New Workspace" [ref=e152] [cursor=pointer]:
|
||||
- img [ref=e155]
|
||||
- generic [ref=e157]: New Workspace
|
||||
- button "Open my workspace workspace" [ref=e159] [cursor=pointer]:
|
||||
- generic [ref=e161]: MW
|
||||
- generic [ref=e162]:
|
||||
- heading "my workspace" [level=3] [ref=e163]
|
||||
- paragraph [ref=e164]: No description
|
||||
- generic [ref=e165]: Created 21/01/1970
|
||||
@@ -1 +0,0 @@
|
||||
- 'heading "Application error: a client-side exception has occurred while loading localhost (see the browser console for more information)." [level=2] [ref=e6]'
|
||||
@@ -1,10 +0,0 @@
|
||||
- generic [active] [ref=e1]:
|
||||
- banner [ref=e2]: App Header
|
||||
- generic [ref=e4]:
|
||||
- heading "MetaBuilder" [level=3] [ref=e5]
|
||||
- paragraph [ref=e6]: Data-driven application platform. Configure routes via the admin panel or install a package with a default home page.
|
||||
- generic [ref=e7]:
|
||||
- button "Sign In" [ref=e8] [cursor=pointer]: Sign In
|
||||
- button "DBAL Status" [ref=e9] [cursor=pointer]: DBAL Status
|
||||
- contentinfo [ref=e10]: App Footer
|
||||
- alert [ref=e11]
|
||||
@@ -1,127 +0,0 @@
|
||||
- generic [active] [ref=e1]:
|
||||
- alert [ref=e2]
|
||||
- generic [ref=e3]:
|
||||
- banner [ref=e4]:
|
||||
- generic [ref=e5]:
|
||||
- button "Toggle sidebar" [ref=e6] [cursor=pointer]:
|
||||
- img [ref=e7]
|
||||
- generic [ref=e8]:
|
||||
- img [ref=e9]
|
||||
- heading "WorkflowUI" [level=1] [ref=e18]
|
||||
- generic [ref=e19]:
|
||||
- button "Notifications" [ref=e21] [cursor=pointer]:
|
||||
- img [ref=e22]
|
||||
- generic [ref=e24]: "2"
|
||||
- button "Switch to dark mode" [ref=e25] [cursor=pointer]:
|
||||
- img [ref=e26]
|
||||
- generic [ref=e28]:
|
||||
- complementary "Workflows sidebar" [ref=e29]:
|
||||
- navigation [ref=e30]:
|
||||
- generic [ref=e31]:
|
||||
- heading "Main" [level=3] [ref=e32]
|
||||
- list "Main navigation" [ref=e33]:
|
||||
- listitem [ref=e34]:
|
||||
- link "Dashboard" [ref=e35] [cursor=pointer]:
|
||||
- /url: /workflowui
|
||||
- img [ref=e37]
|
||||
- generic [ref=e39]: Dashboard
|
||||
- listitem [ref=e40]:
|
||||
- link "Notifications 2" [ref=e41] [cursor=pointer]:
|
||||
- /url: /workflowui/notifications
|
||||
- img [ref=e43]
|
||||
- generic [ref=e45]: Notifications
|
||||
- generic [ref=e46]: "2"
|
||||
- generic [ref=e47]:
|
||||
- heading "Workflows" [level=3] [ref=e48]
|
||||
- list "Workflows navigation" [ref=e49]:
|
||||
- listitem [ref=e50]:
|
||||
- link "All Workflows" [ref=e51] [cursor=pointer]:
|
||||
- /url: /workflowui/workflows
|
||||
- img [ref=e53]
|
||||
- generic [ref=e55]: All Workflows
|
||||
- listitem [ref=e56]:
|
||||
- link "Recent" [ref=e57] [cursor=pointer]:
|
||||
- /url: /workflowui/workflows/recent
|
||||
- img [ref=e59]
|
||||
- generic [ref=e61]: Recent
|
||||
- listitem [ref=e62]:
|
||||
- link "Favorites" [ref=e63] [cursor=pointer]:
|
||||
- /url: /workflowui/workflows/favorites
|
||||
- img [ref=e65]
|
||||
- generic [ref=e67]: Favorites
|
||||
- listitem [ref=e68]:
|
||||
- link "Templates" [ref=e69] [cursor=pointer]:
|
||||
- /url: /workflowui/templates
|
||||
- img [ref=e71]
|
||||
- generic [ref=e73]: Templates
|
||||
- generic [ref=e74]:
|
||||
- heading "System" [level=3] [ref=e75]
|
||||
- list "System navigation" [ref=e76]:
|
||||
- listitem [ref=e77]:
|
||||
- link "Plugins" [ref=e78] [cursor=pointer]:
|
||||
- /url: /workflowui/plugins
|
||||
- img [ref=e80]
|
||||
- generic [ref=e82]: Plugins
|
||||
- listitem [ref=e83]:
|
||||
- link "Settings" [ref=e84] [cursor=pointer]:
|
||||
- /url: /workflowui/settings
|
||||
- img [ref=e86]
|
||||
- generic [ref=e88]: Settings
|
||||
- generic [ref=e89]:
|
||||
- heading "Help" [level=3] [ref=e90]
|
||||
- list "Help navigation" [ref=e91]:
|
||||
- listitem [ref=e92]:
|
||||
- link "Documentation" [ref=e93] [cursor=pointer]:
|
||||
- /url: /workflowui/docs
|
||||
- img [ref=e95]
|
||||
- generic [ref=e97]: Documentation
|
||||
- listitem [ref=e98]:
|
||||
- link "Help & Support" [ref=e99] [cursor=pointer]:
|
||||
- /url: /workflowui/help
|
||||
- img [ref=e101]
|
||||
- generic [ref=e103]: Help & Support
|
||||
- button "+ New Workflow" [ref=e105] [cursor=pointer]:
|
||||
- generic [ref=e107]: + New Workflow
|
||||
- main [ref=e108]:
|
||||
- generic [ref=e109]:
|
||||
- generic [ref=e110]:
|
||||
- generic [ref=e111]:
|
||||
- img [ref=e113]
|
||||
- generic [ref=e115]:
|
||||
- generic [ref=e116]: "23"
|
||||
- generic [ref=e117]: nodes today
|
||||
- generic [ref=e118]:
|
||||
- img [ref=e120]
|
||||
- generic [ref=e122]:
|
||||
- generic [ref=e123]: "5"
|
||||
- generic [ref=e124]: runs today
|
||||
- generic [ref=e125]:
|
||||
- img [ref=e127]
|
||||
- generic [ref=e129]:
|
||||
- generic [ref=e130]: "1"
|
||||
- generic [ref=e131]: failed
|
||||
- generic [ref=e132]:
|
||||
- img [ref=e134]
|
||||
- generic [ref=e136]:
|
||||
- generic [ref=e137]: 1.2h
|
||||
- generic [ref=e138]: saved today
|
||||
- generic [ref=e140]:
|
||||
- generic "First Steps" [ref=e141]:
|
||||
- img [ref=e142]
|
||||
- generic "Node Master" [ref=e144]:
|
||||
- img [ref=e145]
|
||||
- link "+4 more" [ref=e147] [cursor=pointer]:
|
||||
- /url: /workflowui/achievements
|
||||
- generic [ref=e148]:
|
||||
- generic [ref=e149]:
|
||||
- heading "Workspaces" [level=1] [ref=e150]
|
||||
- paragraph [ref=e151]: Organize your projects and workflows
|
||||
- button "New Workspace" [ref=e152] [cursor=pointer]:
|
||||
- img [ref=e155]
|
||||
- generic [ref=e157]: New Workspace
|
||||
- button "Open my workspace workspace" [ref=e159] [cursor=pointer]:
|
||||
- generic [ref=e161]: MW
|
||||
- generic [ref=e162]:
|
||||
- heading "my workspace" [level=3] [ref=e163]
|
||||
- paragraph [ref=e164]: No description
|
||||
- generic [ref=e165]: Created 21/01/1970
|
||||
@@ -1,10 +0,0 @@
|
||||
- generic [active] [ref=e1]:
|
||||
- banner [ref=e2]: App Header
|
||||
- generic [ref=e4]:
|
||||
- heading "MetaBuilder" [level=3] [ref=e5]
|
||||
- paragraph [ref=e6]: Data-driven application platform. Configure routes via the admin panel or install a package with a default home page.
|
||||
- generic [ref=e7]:
|
||||
- button "Sign In" [ref=e8] [cursor=pointer]: Sign In
|
||||
- button "DBAL Status" [ref=e9] [cursor=pointer]: DBAL Status
|
||||
- contentinfo [ref=e10]: App Footer
|
||||
- alert [ref=e11]
|
||||
@@ -1,122 +0,0 @@
|
||||
- generic [active] [ref=e1]:
|
||||
- banner [ref=e2]:
|
||||
- heading "MetaBuilder" [level=1] [ref=e3]
|
||||
- paragraph [ref=e4]: Development Stack Portal
|
||||
- generic [ref=e5]: Applications
|
||||
- generic [ref=e6]:
|
||||
- link "W WorkflowUI Visual workflow editor with n8n-style DAG canvas, step library, and JSON workflow execution. /workflowui" [ref=e7] [cursor=pointer]:
|
||||
- /url: /workflowui
|
||||
- generic [ref=e8]:
|
||||
- generic [ref=e9]: W
|
||||
- heading "WorkflowUI" [level=2] [ref=e10]
|
||||
- paragraph [ref=e11]: Visual workflow editor with n8n-style DAG canvas, step library, and JSON workflow execution.
|
||||
- generic [ref=e12]: /workflowui
|
||||
- link "C CodeForge IDE Low-code application builder with Monaco editor, JSON-driven component architecture. /codegen" [ref=e13] [cursor=pointer]:
|
||||
- /url: /codegen
|
||||
- generic [ref=e14]:
|
||||
- generic [ref=e15]: C
|
||||
- heading "CodeForge IDE" [level=2] [ref=e16]
|
||||
- paragraph [ref=e17]: Low-code application builder with Monaco editor, JSON-driven component architecture.
|
||||
- generic [ref=e18]: /codegen
|
||||
- link "P Pastebin Code snippet sharing with syntax highlighting, expiration, and privacy controls. /pastebin" [ref=e19] [cursor=pointer]:
|
||||
- /url: /pastebin
|
||||
- generic [ref=e20]:
|
||||
- generic [ref=e21]: P
|
||||
- heading "Pastebin" [level=2] [ref=e22]
|
||||
- paragraph [ref=e23]: Code snippet sharing with syntax highlighting, expiration, and privacy controls.
|
||||
- generic [ref=e24]: /pastebin
|
||||
- link "E Email Client Full-featured email management with IMAP/SMTP, multi-account support, and search. /emailclient" [ref=e25] [cursor=pointer]:
|
||||
- /url: /emailclient
|
||||
- generic [ref=e26]:
|
||||
- generic [ref=e27]: E
|
||||
- heading "Email Client" [level=2] [ref=e28]
|
||||
- paragraph [ref=e29]: Full-featured email management with IMAP/SMTP, multi-account support, and search.
|
||||
- generic [ref=e30]: /emailclient
|
||||
- link "D Postgres Dashboard PostgreSQL admin dashboard with query editor, table browser, and performance monitoring. /postgres" [ref=e31] [cursor=pointer]:
|
||||
- /url: /postgres
|
||||
- generic [ref=e32]:
|
||||
- generic [ref=e33]: D
|
||||
- heading "Postgres Dashboard" [level=2] [ref=e34]
|
||||
- paragraph [ref=e35]: PostgreSQL admin dashboard with query editor, table browser, and performance monitoring.
|
||||
- generic [ref=e36]: /postgres
|
||||
- link "3D Exploded Diagrams Interactive 3D exploded diagram viewer with Three.js and JSCAD integration. /diagrams" [ref=e37] [cursor=pointer]:
|
||||
- /url: /diagrams
|
||||
- generic [ref=e38]:
|
||||
- generic [ref=e39]: 3D
|
||||
- heading "Exploded Diagrams" [level=2] [ref=e40]
|
||||
- paragraph [ref=e41]: Interactive 3D exploded diagram viewer with Three.js and JSCAD integration.
|
||||
- generic [ref=e42]: /diagrams
|
||||
- link "S Storybook Component library preview with interactive props, documentation, and visual testing. /storybook" [ref=e43] [cursor=pointer]:
|
||||
- /url: /storybook
|
||||
- generic [ref=e44]:
|
||||
- generic [ref=e45]: S
|
||||
- heading "Storybook" [level=2] [ref=e46]
|
||||
- paragraph [ref=e47]: Component library preview with interactive props, documentation, and visual testing.
|
||||
- generic [ref=e48]: /storybook
|
||||
- link "A Frontend App Main Next.js application with Drizzle ORM, i18n, Clerk auth, and DBAL integration. /app" [ref=e49] [cursor=pointer]:
|
||||
- /url: /app
|
||||
- generic [ref=e50]:
|
||||
- generic [ref=e51]: A
|
||||
- heading "Frontend App" [level=2] [ref=e52]
|
||||
- paragraph [ref=e53]: Main Next.js application with Drizzle ORM, i18n, Clerk auth, and DBAL integration.
|
||||
- generic [ref=e54]: /app
|
||||
- generic [ref=e55]: Backend Services
|
||||
- generic [ref=e56]:
|
||||
- link "API DBAL API C++ database abstraction layer with RESTful CRUD, caching, and search. /api" [ref=e57] [cursor=pointer]:
|
||||
- /url: /api/health
|
||||
- generic [ref=e58]:
|
||||
- generic [ref=e59]: API
|
||||
- heading "DBAL API" [level=2] [ref=e60]
|
||||
- paragraph [ref=e61]: C++ database abstraction layer with RESTful CRUD, caching, and search.
|
||||
- generic [ref=e62]: /api
|
||||
- link "EM Email Service Flask backend for IMAP/SMTP operations, email sync, and Celery task queue. /email-api" [ref=e63] [cursor=pointer]:
|
||||
- /url: /email-api/health
|
||||
- generic [ref=e64]:
|
||||
- generic [ref=e65]: EM
|
||||
- heading "Email Service" [level=2] [ref=e66]
|
||||
- paragraph [ref=e67]: Flask backend for IMAP/SMTP operations, email sync, and Celery task queue.
|
||||
- generic [ref=e68]: /email-api
|
||||
- link "SM SMTP Relay Twisted SMTP relay dashboard for email testing and debugging. localhost:8025" [ref=e69] [cursor=pointer]:
|
||||
- /url: http://localhost:8025
|
||||
- generic [ref=e70]:
|
||||
- generic [ref=e71]: SM
|
||||
- heading "SMTP Relay" [level=2] [ref=e72]
|
||||
- paragraph [ref=e73]: Twisted SMTP relay dashboard for email testing and debugging.
|
||||
- generic [ref=e74]: localhost:8025
|
||||
- generic [ref=e75]: Administration
|
||||
- generic [ref=e76]:
|
||||
- link "⚙ Database Settings Manage DBAL adapter configuration, switch backends, and test database connections. /portal/settings.html" [ref=e77] [cursor=pointer]:
|
||||
- /url: /portal/settings.html
|
||||
- generic [ref=e78]:
|
||||
- generic [ref=e79]: ⚙
|
||||
- heading "Database Settings" [level=2] [ref=e80]
|
||||
- paragraph [ref=e81]: Manage DBAL adapter configuration, switch backends, and test database connections.
|
||||
- generic [ref=e82]: /portal/settings.html
|
||||
- link "PMA phpMyAdmin MySQL web administration with table browser, SQL editor, import/export, and user management. /phpmyadmin/" [ref=e83] [cursor=pointer]:
|
||||
- /url: /phpmyadmin/
|
||||
- generic [ref=e84]:
|
||||
- generic [ref=e85]: PMA
|
||||
- heading "phpMyAdmin" [level=2] [ref=e86]
|
||||
- paragraph [ref=e87]: MySQL web administration with table browser, SQL editor, import/export, and user management.
|
||||
- generic [ref=e88]: /phpmyadmin/
|
||||
- link "ME Mongo Express MongoDB web administration with collection browser, document editor, and query interface. /mongo-express/" [ref=e89] [cursor=pointer]:
|
||||
- /url: /mongo-express/
|
||||
- generic [ref=e90]:
|
||||
- generic [ref=e91]: ME
|
||||
- heading "Mongo Express" [level=2] [ref=e92]
|
||||
- paragraph [ref=e93]: MongoDB web administration with collection browser, document editor, and query interface.
|
||||
- generic [ref=e94]: /mongo-express/
|
||||
- link "RI RedisInsight Redis GUI with key browser, CLI console, memory analysis, and slow log inspection. /redis-insight/" [ref=e95] [cursor=pointer]:
|
||||
- /url: /redis-insight/
|
||||
- generic [ref=e96]:
|
||||
- generic [ref=e97]: RI
|
||||
- heading "RedisInsight" [level=2] [ref=e98]
|
||||
- paragraph [ref=e99]: Redis GUI with key browser, CLI console, memory analysis, and slow log inspection.
|
||||
- generic [ref=e100]: /redis-insight/
|
||||
- link "KB Kibana Elasticsearch dashboard with Discover, index management, Dev Tools console, and visualizations. /kibana/" [ref=e101] [cursor=pointer]:
|
||||
- /url: /kibana/
|
||||
- generic [ref=e102]:
|
||||
- generic [ref=e103]: KB
|
||||
- heading "Kibana" [level=2] [ref=e104]
|
||||
- paragraph [ref=e105]: Elasticsearch dashboard with Discover, index management, Dev Tools console, and visualizations.
|
||||
- generic [ref=e106]: /kibana/
|
||||
@@ -1,122 +0,0 @@
|
||||
- generic [active] [ref=e1]:
|
||||
- banner [ref=e2]:
|
||||
- heading "MetaBuilder" [level=1] [ref=e3]
|
||||
- paragraph [ref=e4]: Development Stack Portal
|
||||
- generic [ref=e5]: Applications
|
||||
- generic [ref=e6]:
|
||||
- link "W WorkflowUI Visual workflow editor with n8n-style DAG canvas, step library, and JSON workflow execution. /workflowui" [ref=e7] [cursor=pointer]:
|
||||
- /url: /workflowui
|
||||
- generic [ref=e8]:
|
||||
- generic [ref=e9]: W
|
||||
- heading "WorkflowUI" [level=2] [ref=e10]
|
||||
- paragraph [ref=e11]: Visual workflow editor with n8n-style DAG canvas, step library, and JSON workflow execution.
|
||||
- generic [ref=e12]: /workflowui
|
||||
- link "C CodeForge IDE Low-code application builder with Monaco editor, JSON-driven component architecture. /codegen" [ref=e13] [cursor=pointer]:
|
||||
- /url: /codegen
|
||||
- generic [ref=e14]:
|
||||
- generic [ref=e15]: C
|
||||
- heading "CodeForge IDE" [level=2] [ref=e16]
|
||||
- paragraph [ref=e17]: Low-code application builder with Monaco editor, JSON-driven component architecture.
|
||||
- generic [ref=e18]: /codegen
|
||||
- link "P Pastebin Code snippet sharing with syntax highlighting, expiration, and privacy controls. /pastebin" [ref=e19] [cursor=pointer]:
|
||||
- /url: /pastebin
|
||||
- generic [ref=e20]:
|
||||
- generic [ref=e21]: P
|
||||
- heading "Pastebin" [level=2] [ref=e22]
|
||||
- paragraph [ref=e23]: Code snippet sharing with syntax highlighting, expiration, and privacy controls.
|
||||
- generic [ref=e24]: /pastebin
|
||||
- link "E Email Client Full-featured email management with IMAP/SMTP, multi-account support, and search. /emailclient" [ref=e25] [cursor=pointer]:
|
||||
- /url: /emailclient
|
||||
- generic [ref=e26]:
|
||||
- generic [ref=e27]: E
|
||||
- heading "Email Client" [level=2] [ref=e28]
|
||||
- paragraph [ref=e29]: Full-featured email management with IMAP/SMTP, multi-account support, and search.
|
||||
- generic [ref=e30]: /emailclient
|
||||
- link "D Postgres Dashboard PostgreSQL admin dashboard with query editor, table browser, and performance monitoring. /postgres" [ref=e31] [cursor=pointer]:
|
||||
- /url: /postgres
|
||||
- generic [ref=e32]:
|
||||
- generic [ref=e33]: D
|
||||
- heading "Postgres Dashboard" [level=2] [ref=e34]
|
||||
- paragraph [ref=e35]: PostgreSQL admin dashboard with query editor, table browser, and performance monitoring.
|
||||
- generic [ref=e36]: /postgres
|
||||
- link "3D Exploded Diagrams Interactive 3D exploded diagram viewer with Three.js and JSCAD integration. /diagrams" [ref=e37] [cursor=pointer]:
|
||||
- /url: /diagrams
|
||||
- generic [ref=e38]:
|
||||
- generic [ref=e39]: 3D
|
||||
- heading "Exploded Diagrams" [level=2] [ref=e40]
|
||||
- paragraph [ref=e41]: Interactive 3D exploded diagram viewer with Three.js and JSCAD integration.
|
||||
- generic [ref=e42]: /diagrams
|
||||
- link "S Storybook Component library preview with interactive props, documentation, and visual testing. /storybook" [ref=e43] [cursor=pointer]:
|
||||
- /url: /storybook
|
||||
- generic [ref=e44]:
|
||||
- generic [ref=e45]: S
|
||||
- heading "Storybook" [level=2] [ref=e46]
|
||||
- paragraph [ref=e47]: Component library preview with interactive props, documentation, and visual testing.
|
||||
- generic [ref=e48]: /storybook
|
||||
- link "A Frontend App Main Next.js application with Drizzle ORM, i18n, Clerk auth, and DBAL integration. /app" [ref=e49] [cursor=pointer]:
|
||||
- /url: /app
|
||||
- generic [ref=e50]:
|
||||
- generic [ref=e51]: A
|
||||
- heading "Frontend App" [level=2] [ref=e52]
|
||||
- paragraph [ref=e53]: Main Next.js application with Drizzle ORM, i18n, Clerk auth, and DBAL integration.
|
||||
- generic [ref=e54]: /app
|
||||
- generic [ref=e55]: Backend Services
|
||||
- generic [ref=e56]:
|
||||
- link "API DBAL API C++ database abstraction layer with RESTful CRUD, caching, and search. /api" [ref=e57] [cursor=pointer]:
|
||||
- /url: /api/health
|
||||
- generic [ref=e58]:
|
||||
- generic [ref=e59]: API
|
||||
- heading "DBAL API" [level=2] [ref=e60]
|
||||
- paragraph [ref=e61]: C++ database abstraction layer with RESTful CRUD, caching, and search.
|
||||
- generic [ref=e62]: /api
|
||||
- link "EM Email Service Flask backend for IMAP/SMTP operations, email sync, and Celery task queue. /email-api" [ref=e63] [cursor=pointer]:
|
||||
- /url: /email-api/health
|
||||
- generic [ref=e64]:
|
||||
- generic [ref=e65]: EM
|
||||
- heading "Email Service" [level=2] [ref=e66]
|
||||
- paragraph [ref=e67]: Flask backend for IMAP/SMTP operations, email sync, and Celery task queue.
|
||||
- generic [ref=e68]: /email-api
|
||||
- link "SM SMTP Relay Twisted SMTP relay dashboard for email testing and debugging. localhost:8025" [ref=e69] [cursor=pointer]:
|
||||
- /url: http://localhost:8025
|
||||
- generic [ref=e70]:
|
||||
- generic [ref=e71]: SM
|
||||
- heading "SMTP Relay" [level=2] [ref=e72]
|
||||
- paragraph [ref=e73]: Twisted SMTP relay dashboard for email testing and debugging.
|
||||
- generic [ref=e74]: localhost:8025
|
||||
- generic [ref=e75]: Administration
|
||||
- generic [ref=e76]:
|
||||
- link "⚙ Database Settings Manage DBAL adapter configuration, switch backends, and test database connections. /portal/settings.html" [ref=e77] [cursor=pointer]:
|
||||
- /url: /portal/settings.html
|
||||
- generic [ref=e78]:
|
||||
- generic [ref=e79]: ⚙
|
||||
- heading "Database Settings" [level=2] [ref=e80]
|
||||
- paragraph [ref=e81]: Manage DBAL adapter configuration, switch backends, and test database connections.
|
||||
- generic [ref=e82]: /portal/settings.html
|
||||
- link "PMA phpMyAdmin MySQL web administration with table browser, SQL editor, import/export, and user management. /phpmyadmin/" [ref=e83] [cursor=pointer]:
|
||||
- /url: /phpmyadmin/
|
||||
- generic [ref=e84]:
|
||||
- generic [ref=e85]: PMA
|
||||
- heading "phpMyAdmin" [level=2] [ref=e86]
|
||||
- paragraph [ref=e87]: MySQL web administration with table browser, SQL editor, import/export, and user management.
|
||||
- generic [ref=e88]: /phpmyadmin/
|
||||
- link "ME Mongo Express MongoDB web administration with collection browser, document editor, and query interface. /mongo-express/" [ref=e89] [cursor=pointer]:
|
||||
- /url: /mongo-express/
|
||||
- generic [ref=e90]:
|
||||
- generic [ref=e91]: ME
|
||||
- heading "Mongo Express" [level=2] [ref=e92]
|
||||
- paragraph [ref=e93]: MongoDB web administration with collection browser, document editor, and query interface.
|
||||
- generic [ref=e94]: /mongo-express/
|
||||
- link "RI RedisInsight Redis GUI with key browser, CLI console, memory analysis, and slow log inspection. /redis-insight/" [ref=e95] [cursor=pointer]:
|
||||
- /url: /redis-insight/
|
||||
- generic [ref=e96]:
|
||||
- generic [ref=e97]: RI
|
||||
- heading "RedisInsight" [level=2] [ref=e98]
|
||||
- paragraph [ref=e99]: Redis GUI with key browser, CLI console, memory analysis, and slow log inspection.
|
||||
- generic [ref=e100]: /redis-insight/
|
||||
- link "KB Kibana Elasticsearch dashboard with Discover, index management, Dev Tools console, and visualizations. /kibana/" [ref=e101] [cursor=pointer]:
|
||||
- /url: /kibana/
|
||||
- generic [ref=e102]:
|
||||
- generic [ref=e103]: KB
|
||||
- heading "Kibana" [level=2] [ref=e104]
|
||||
- paragraph [ref=e105]: Elasticsearch dashboard with Discover, index management, Dev Tools console, and visualizations.
|
||||
- generic [ref=e106]: /kibana/
|
||||
@@ -1,51 +0,0 @@
|
||||
- generic [active] [ref=e1]:
|
||||
- generic [ref=e2]:
|
||||
- banner [ref=e3]:
|
||||
- generic [ref=e4]:
|
||||
- img [ref=e5]
|
||||
- generic [ref=e7]: Postgres Admin Panel
|
||||
- button "Logout" [ref=e8] [cursor=pointer]:
|
||||
- img [ref=e10]
|
||||
- text: Logout
|
||||
- list [ref=e16]:
|
||||
- listitem [ref=e17]:
|
||||
- button "Tables" [ref=e18] [cursor=pointer]:
|
||||
- img [ref=e20]
|
||||
- generic [ref=e23]: Tables
|
||||
- listitem [ref=e24]:
|
||||
- button "SQL Query" [ref=e25] [cursor=pointer]:
|
||||
- img [ref=e27]
|
||||
- generic [ref=e30]: SQL Query
|
||||
- listitem [ref=e31]:
|
||||
- button "Query Builder" [ref=e32] [cursor=pointer]:
|
||||
- img [ref=e34]
|
||||
- generic [ref=e37]: Query Builder
|
||||
- listitem [ref=e38]:
|
||||
- button "Table Manager" [ref=e39] [cursor=pointer]:
|
||||
- img [ref=e41]
|
||||
- generic [ref=e44]: Table Manager
|
||||
- listitem [ref=e45]:
|
||||
- button "Column Manager" [ref=e46] [cursor=pointer]:
|
||||
- img [ref=e48]
|
||||
- generic [ref=e51]: Column Manager
|
||||
- listitem [ref=e52]:
|
||||
- button "Constraints" [ref=e53] [cursor=pointer]:
|
||||
- img [ref=e55]
|
||||
- generic [ref=e58]: Constraints
|
||||
- listitem [ref=e59]:
|
||||
- button "Indexes" [ref=e60] [cursor=pointer]:
|
||||
- img [ref=e62]
|
||||
- generic [ref=e65]: Indexes
|
||||
- main [ref=e66]:
|
||||
- tabpanel [ref=e68]:
|
||||
- generic [ref=e70]:
|
||||
- heading "Database Tables" [level=5] [ref=e71]
|
||||
- list [ref=e73]:
|
||||
- listitem [ref=e74]:
|
||||
- generic [ref=e75]: No tables found
|
||||
- alert [ref=e76]:
|
||||
- img [ref=e78]
|
||||
- generic [ref=e80]: Failed to fetch tables
|
||||
- button "Close" [ref=e82] [cursor=pointer]:
|
||||
- img [ref=e83]
|
||||
- alert [ref=e85]
|
||||
@@ -1,20 +0,0 @@
|
||||
- generic [active] [ref=e1]:
|
||||
- generic [ref=e2]:
|
||||
- banner [ref=e3]:
|
||||
- heading "EXPLODED DIAGRAMS" [level=1] [ref=e4]
|
||||
- paragraph [ref=e5]: Modular Technical Illustrations
|
||||
- navigation [ref=e6]:
|
||||
- link "Home" [ref=e7] [cursor=pointer]:
|
||||
- /url: /diagrams
|
||||
- generic [ref=e8]:
|
||||
- heading "Categories" [level=2] [ref=e9]
|
||||
- generic [ref=e10]:
|
||||
- link "RC Vehicles Radio controlled cars, trucks, and buggies" [ref=e11] [cursor=pointer]:
|
||||
- /url: /diagrams/rc
|
||||
- heading "RC Vehicles" [level=4] [ref=e12]
|
||||
- paragraph [ref=e13]: Radio controlled cars, trucks, and buggies
|
||||
- link "Automotive Car and vehicle drivetrain components" [ref=e14] [cursor=pointer]:
|
||||
- /url: /diagrams/automotive
|
||||
- heading "Automotive" [level=4] [ref=e15]
|
||||
- paragraph [ref=e16]: Car and vehicle drivetrain components
|
||||
- alert [ref=e17]
|
||||
24
.vscode/settings.json
vendored
24
.vscode/settings.json
vendored
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"cmake.sourceDirectory": "/Users/rmac/Documents/metabuilder/gameengine",
|
||||
"cmake.sourceDirectory": "/home/rewrich/Documents/GitHub/metabuilder/dbal/production/build-config",
|
||||
"chat.mcp.discovery.enabled": {
|
||||
"claude-desktop": true,
|
||||
"windsurf": true,
|
||||
@@ -59,25 +59,5 @@
|
||||
"https://registry.npmjs.org/*": true
|
||||
},
|
||||
"claudeCode.allowDangerouslySkipPermissions": true,
|
||||
"claudeCode.initialPermissionMode": "bypassPermissions",
|
||||
"files.watcherExclude": {
|
||||
"**/node_modules/**": true,
|
||||
"**/.git/**": true,
|
||||
"**/build/**": true,
|
||||
"**/_build/**": true,
|
||||
"**/dist/**": true,
|
||||
"**/playwright-report/**": true,
|
||||
"**/test-results/**": true,
|
||||
"**/.next/**": true,
|
||||
"**/coverage/**": true
|
||||
},
|
||||
"search.exclude": {
|
||||
"**/node_modules": true,
|
||||
"**/build": true,
|
||||
"**/_build": true,
|
||||
"**/dist": true,
|
||||
"**/.git": true,
|
||||
"**/playwright-report": true,
|
||||
"**/test-results": true
|
||||
}
|
||||
"claudeCode.initialPermissionMode": "bypassPermissions"
|
||||
}
|
||||
190
AGENTS.md
190
AGENTS.md
@@ -1,190 +0,0 @@
|
||||
# MetaBuilder — Agent Guide
|
||||
|
||||
**Last Updated**: 2026-03-04
|
||||
Quick-start for AI agents (Claude Code, Copilot, etc.) working on this codebase.
|
||||
Read CLAUDE.md for the full guide. This file covers agent-specific patterns and shortcuts.
|
||||
|
||||
---
|
||||
|
||||
## What's Running
|
||||
|
||||
```
|
||||
http://localhost/pastebin # Next.js UI
|
||||
http://localhost/pastebin-api # Flask auth (register, login, JWT)
|
||||
http://localhost:8080 # DBAL C++ REST API (entities)
|
||||
```
|
||||
|
||||
**Test accounts**: `demo/demo1234`, `alice/alice1234`, `bob/bob12345`
|
||||
|
||||
---
|
||||
|
||||
## Architecture in 30 Seconds
|
||||
|
||||
```
|
||||
Browser (Next.js + Redux + IndexedDB)
|
||||
└── Flask (JWT auth, Python runner) frontends/pastebin/backend/
|
||||
└── DBAL C++ daemon (REST API) dbal/production/
|
||||
└── PostgreSQL (prod)
|
||||
```
|
||||
|
||||
**DBAL event flow on user registration**:
|
||||
```
|
||||
POST /pastebin/pastebin/User
|
||||
└── handleCreate() → dispatchAsync("pastebin.User.created")
|
||||
└── detached thread → on_user_created.json (15 nodes)
|
||||
└── 2 namespaces + 5 seed snippets created
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Key Files to Know
|
||||
|
||||
| Path | What it is |
|
||||
|------|-----------|
|
||||
| `dbal/shared/api/schema/entities/` | JSON entity schemas — SOURCE OF TRUTH (39 entities) |
|
||||
| `dbal/shared/api/schema/events/event_config.json` | Event → workflow mappings |
|
||||
| `dbal/shared/api/schema/workflows/` | JSON workflow definitions |
|
||||
| `dbal/shared/api/schema/auth/auth.json` | JWT + ACL rules |
|
||||
| `dbal/shared/seeds/database/` | Declarative seed data (JSON, loaded at startup) |
|
||||
| `dbal/production/src/workflow/` | C++ workflow engine (WfEngine, WfExecutor, steps/) |
|
||||
| `dbal/production/src/daemon/server_routes.cpp` | Route registration + auto-seed startup |
|
||||
| `frontends/pastebin/backend/app.py` | Flask JWT auth + Python runner |
|
||||
| `frontends/pastebin/src/` | Next.js React app |
|
||||
| `deployment/docker-compose.stack.yml` | Full stack compose |
|
||||
| `deployment/build-apps.sh` | Build + deploy helper |
|
||||
|
||||
---
|
||||
|
||||
## Before You Touch Anything
|
||||
|
||||
```bash
|
||||
# Search docs first (SQLite FTS5)
|
||||
cd docs && python3 docs.py search "topic"
|
||||
cd txt && python3 reports.py search "topic"
|
||||
|
||||
# Check what's already there
|
||||
ls dbal/shared/api/schema/entities/
|
||||
ls dbal/shared/seeds/database/
|
||||
|
||||
# Logs
|
||||
docker logs -f metabuilder-dbal
|
||||
docker logs -f metabuilder-pastebin-backend
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Deploy Commands
|
||||
|
||||
```bash
|
||||
cd deployment
|
||||
|
||||
# Full rebuild + restart
|
||||
./build-apps.sh --force dbal pastebin
|
||||
docker compose -f docker-compose.stack.yml up -d
|
||||
|
||||
# Flask backend (separate from Next.js)
|
||||
docker compose -f docker-compose.stack.yml build pastebin-backend
|
||||
docker compose -f docker-compose.stack.yml up -d pastebin-backend
|
||||
|
||||
# dbal-init volume (schema volume container — rebuild when entity JSON changes)
|
||||
docker compose -f docker-compose.stack.yml build dbal-init
|
||||
docker compose -f docker-compose.stack.yml up dbal-init
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Entity Schema Format (JSON)
|
||||
|
||||
All schemas live in `dbal/shared/api/schema/entities/*.json`.
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "MyEntity",
|
||||
"tenantId": "pastebin",
|
||||
"package": "pastebin",
|
||||
"fields": [
|
||||
{ "name": "id", "type": "uuid", "primary": true },
|
||||
{ "name": "name", "type": "string", "required": true },
|
||||
{ "name": "userId", "type": "uuid", "required": true },
|
||||
{ "name": "tenantId", "type": "string", "required": true },
|
||||
{ "name": "createdAt", "type": "timestamp", "required": true }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
After schema changes: `python3 dbal/shared/tools/codegen/gen_types.py`
|
||||
|
||||
---
|
||||
|
||||
## Seed Data Format (JSON)
|
||||
|
||||
All seed files in `dbal/shared/seeds/database/*.json`. Idempotent — skipped if records exist.
|
||||
|
||||
```json
|
||||
{
|
||||
"entity": "MyEntity",
|
||||
"records": [
|
||||
{ "id": "uuid-here", "name": "Example", "tenantId": "pastebin", "createdAt": 0 }
|
||||
],
|
||||
"metadata": { "bootstrap": true }
|
||||
}
|
||||
```
|
||||
|
||||
For multi-document seeds (array of seed objects): wrap in `[...]` at top level.
|
||||
|
||||
**User passwords**: Generate werkzeug hashes inside the container:
|
||||
```bash
|
||||
docker exec metabuilder-pastebin-backend python3 -c \
|
||||
"from werkzeug.security import generate_password_hash; print(generate_password_hash('mypassword'))"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Workflow Step Types
|
||||
|
||||
| Type | What it does |
|
||||
|------|-------------|
|
||||
| `dbal.uuid` | Generates UUID v4, stores via `outputs` |
|
||||
| `dbal.timestamp` | Current timestamp (ms), stores via `outputs` |
|
||||
| `dbal.entity.create` | `client.createEntity(entity, data)` |
|
||||
| `dbal.entity.get` | `client.getEntity(entity, id)` |
|
||||
| `dbal.entity.list` | `client.listEntities(entity, options)` |
|
||||
| `dbal.var.set` | `ctx.set(key, value)` |
|
||||
| `dbal.log` | `spdlog::info(message)` |
|
||||
|
||||
Context variable resolution: `"${var_name}"`, `"${event.userId}"`, `"prefix-${name}-suffix"`
|
||||
|
||||
---
|
||||
|
||||
## Rules (Non-Negotiable)
|
||||
|
||||
1. **Multi-tenant always**: Every DBAL query filters by `tenantId`. No exceptions.
|
||||
2. **JSON not YAML**: All schemas, events, workflows, seeds — pure JSON. yaml-cpp removed.
|
||||
3. **Seed data in `dbal/shared/seeds/`** — never hardcode in Flask Python or C++.
|
||||
4. **No hardcoded entity names** — loaded from schema JSON.
|
||||
5. **Call `ensureClient()` before any DB op in `registerRoutes()`** — `dbal_client_` starts null.
|
||||
6. **`build-apps.sh pastebin` ≠ Flask** — that only rebuilds Next.js. Flask needs `docker compose build pastebin-backend`.
|
||||
|
||||
---
|
||||
|
||||
## Common Traps
|
||||
|
||||
| Trap | Fix |
|
||||
|------|-----|
|
||||
| nlohmann/json iterator `it->second` | Use `it.value()` |
|
||||
| dbal-init volume stale after schema rename | `docker compose build dbal-init && docker compose up dbal-init` |
|
||||
| `.dockerignore` blocks `dbal/shared/seeds/` | Add `!dbal/shared/seeds/database` |
|
||||
| Seed segfaults on startup | Missing `ensureClient()` guard |
|
||||
| Seed runs every restart | `skipIfExists` check broken — verify entity name matches schema |
|
||||
| Werkzeug scrypt not on host Python | Generate inside running container with `docker exec` |
|
||||
|
||||
---
|
||||
|
||||
## Pastebin Stack URLs (dev)
|
||||
|
||||
| Service | URL | Auth |
|
||||
|---------|-----|------|
|
||||
| UI | `http://localhost/pastebin` | JWT cookie |
|
||||
| Flask auth API | `http://localhost/pastebin-api/api/auth/*` | — |
|
||||
| DBAL entities | `http://localhost:8080/{tenant}/{package}/{entity}` | Bearer JWT |
|
||||
| DBAL health | `http://localhost:8080/health` | — |
|
||||
391
CLAUDE.md
391
CLAUDE.md
@@ -1,391 +0,0 @@
|
||||
# MetaBuilder - AI Assistant Guide
|
||||
|
||||
**Last Updated**: 2026-03-04 | **Status**: Phase 2 & 3 Complete, Universal Platform in Progress
|
||||
**Scale**: 27,826+ files across 34 directories | **Philosophy**: 95% JSON config, 5% TS/C++ infrastructure
|
||||
**Documentation**: Code = Doc (self-documenting Python scripts with argparse)
|
||||
|
||||
---
|
||||
|
||||
## Code = Doc Principle
|
||||
|
||||
All documentation is executable code. No separate markdown docs.
|
||||
|
||||
```bash
|
||||
# Entry points (each with --help)
|
||||
./metabuilder.py --help # Root project manager
|
||||
./codegen/codegen.py --help # CodeForge IDE
|
||||
./pastebin/pastebin.py --help # Pastebin
|
||||
./gameengine/gameengine.py --help # Game engine
|
||||
./postgres/postgres.py --help # PostgreSQL dashboard
|
||||
./mojo/mojo.py --help # Mojo compiler
|
||||
./deployment/build-base-images.sh --list # Docker base images
|
||||
|
||||
# Documentation (SQLite3 + FTS5 full-text search)
|
||||
cd txt && python3 reports.py search "query" # 212 reports
|
||||
cd docs && python3 docs.py search "query" # 217 docs, 13 categories
|
||||
python3 docs.py list --category guides
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Completed Milestones (All ✅)
|
||||
|
||||
- **Mar 4**: DBAL C++ event-driven workflow engine (`pastebin.User.created` → 15-node JSON workflow → seeded namespaces + snippets), full YAML→JSON migration (63 files, yaml-cpp removed), JWT auth + JSON ACL, declarative seed data (`dbal/shared/seeds/database/`), i18n (EN/ES) across all pastebin components, dark/light theme switcher
|
||||
- **Feb 7**: Game engine CLI args (`--bootstrap`, `--game`), 27/27 tests passing (100%)
|
||||
- **Feb 6**: 6 new DB backends (total 14), SQLite3 doc migration, Docker dev container, WorkflowUI E2E (92.6%)
|
||||
- **Feb 5**: WorkflowUI mock DBAL testing, Settings/Help pages, DBAL env var config
|
||||
- **Feb 4**: SQLiteAdapter generic refactoring, YAML Schema Spec 2.0, Dynamic entity loading (TS+C++), DBAL hooks integration, FakeMUI migration
|
||||
- **Feb 3**: Visual workflow editor (n8n-style), Dynamic plugin registry (152 nodes)
|
||||
- **Feb 2**: WorkflowUI migration to root packages (77% file reduction)
|
||||
- **Feb 1**: CodeQL search, FakeMUI organization, Email components (22)
|
||||
- **Jan 24**: Dependency fixes, testing library standardization
|
||||
- **Jan 23**: Email client (Phases 1-5), Mojo compiler, FakeMUI restructuring, dependency remediation
|
||||
|
||||
**Details**: Search `cd txt && python3 reports.py search "topic"` for full completion reports.
|
||||
|
||||
---
|
||||
|
||||
## Directory Index
|
||||
|
||||
| Directory | Files | Description |
|
||||
|-----------|-------|-------------|
|
||||
| `dbal/` | 495 | Database Abstraction Layer (C++ daemon + shared schemas) |
|
||||
| `workflow/` | 765 | DAG workflow engine, multi-language plugins |
|
||||
| `frontends/` | 495 | CLI (C++), Qt6 (QML), Next.js (React) |
|
||||
| `packages/` | 550 | 62 modular feature packages |
|
||||
| `fakemui/` | 758 | Material UI clone (145 React + 421 icons) |
|
||||
| `gameengine/` | 2,737 | SDL3/bgfx 2D/3D game engine |
|
||||
| `codegen/` | 1,926 | CodeForge IDE (React+Monaco) |
|
||||
| `pastebin/` | 1,114 | Code snippet sharing (Next.js) |
|
||||
| `exploded-diagrams/` | 17,565 | Interactive 3D exploded diagrams |
|
||||
| `schemas/` | 105 | JSON Schema validation |
|
||||
| `services/` | 29 | Media daemon (FFmpeg/ImageMagick) |
|
||||
| `postgres/` | 212 | PostgreSQL admin dashboard |
|
||||
| `mojo/` | 82 | Mojo compiler + language examples |
|
||||
| `docs/` | 1 DB | SQLite3 (217 docs, 13 categories, FTS5) |
|
||||
| `txt/` | 1 DB | SQLite3 (212 reports, FTS5, archives) |
|
||||
| `old/` | 149 | Legacy Spark implementation |
|
||||
| `.github/` | 52 | GitHub Actions, templates |
|
||||
|
||||
*Other standalone: pcbgenerator, packagerepo, cadquerywrapper, sparkos, storybook, dockerterminal, smtprelay, caproverforge, repoforge, emailclient, prisma, deployment, spec, scripts, config, e2e*
|
||||
|
||||
---
|
||||
|
||||
## Core Principles
|
||||
|
||||
### 1. 95% Data, 5% Code
|
||||
- UI, workflows, pages, business logic = **JSON**
|
||||
- Entities NEVER hardcoded - loaded from JSON schemas
|
||||
- Adapters NEVER hardcoded - discovered dynamically
|
||||
|
||||
### 2. Schema-First Development
|
||||
```
|
||||
dbal/shared/api/schema/entities/ # JSON entities (SOURCE OF TRUTH)
|
||||
schemas/package-schemas/ # JSON validation schemas (27 total)
|
||||
dbal/shared/seeds/database/ # Declarative JSON seed data
|
||||
```
|
||||
|
||||
### 3. Multi-Tenant by Default
|
||||
Every query MUST filter by `tenantId` - no exceptions.
|
||||
|
||||
### 4. Data Access Hierarchy
|
||||
```
|
||||
1. Redux + redux-persist - Client-side state (IndexedDB)
|
||||
2. DBAL hooks (fetch) - Server data via C++ DBAL REST API
|
||||
3. Raw SQL - NEVER
|
||||
```
|
||||
|
||||
### 5. One Lambda Per File
|
||||
`src/lib/users/createUser.ts` - one function per file.
|
||||
|
||||
### 6. JSON Script for Business Logic
|
||||
Workflows defined in JSON with version 2.2.0 format.
|
||||
|
||||
---
|
||||
|
||||
## Key Subsystems
|
||||
|
||||
### DBAL (`dbal/`)
|
||||
|
||||
C++ REST API daemon. Client-side persistence handled by `@metabuilder/redux-persist` (IndexedDB).
|
||||
|
||||
```
|
||||
dbal/
|
||||
├── production/ # C++ daemon - SQLite, PostgreSQL, MySQL, Drogon HTTP
|
||||
│ ├── src/config/ # EnvConfig (env vars, NO hardcoded paths)
|
||||
│ ├── src/workflow/ # Event-driven workflow engine (WfEngine, WfExecutor, 7 step types)
|
||||
│ ├── src/auth/ # JWT validation + JSON ACL config
|
||||
│ ├── build-config/# Dockerfile, CMakeLists, conanfile (no yaml-cpp — JSON only)
|
||||
│ ├── templates/sql/# Jinja2 SQL templates (Inja library)
|
||||
│ └── .env.example # ~30 config options documented
|
||||
├── shared/api/schema/
|
||||
│ ├── entities/ # JSON entity definitions (39 entities, SOURCE OF TRUTH)
|
||||
│ ├── events/ # event_config.json → workflow mappings
|
||||
│ ├── workflows/ # on_user_created.json etc.
|
||||
│ └── auth/ # auth.json (JWT + ACL rules)
|
||||
└── shared/seeds/database/ # Declarative JSON seed data (auto-loaded at startup)
|
||||
```
|
||||
|
||||
**Workflow Engine**: `pastebin.User.created` → detached thread → `on_user_created.json` → Default + Examples namespaces + 5 snippet templates. Event dispatch wraps `send_success` callback in entity route handler.
|
||||
|
||||
**Auto-Seed**: `DBAL_SEED_ON_STARTUP=true` → `SeedLoaderAction::loadSeeds()` in `registerRoutes()`. Seed files are idempotent (skip if records exist). Must call `ensureClient()` before seeding — `dbal_client_` is null during route registration.
|
||||
|
||||
**JWT Auth**: `DBAL_AUTH_CONFIG=/app/schemas/auth/auth.json` — defines which endpoints require auth and what roles can access them.
|
||||
|
||||
**Entity Categories**: Core (user, session, workflow, package, ui_page), Access (credential, component_node, page_config), Packages (forum, notification, audit_log, media, irc, streaming), Domain (product, game, artist, video)
|
||||
|
||||
**14 Database Backends**:
|
||||
| Adapter | Backend | Notes |
|
||||
|---------|---------|-------|
|
||||
| memory | In-memory | Testing/development |
|
||||
| sqlite | SQLite | Embedded, generic CRUD via templates |
|
||||
| postgres | PostgreSQL | Direct connection, no ORM |
|
||||
| mysql | MySQL | Direct connection |
|
||||
| mariadb | MariaDB | Reuses mysql adapter |
|
||||
| cockroachdb | CockroachDB | Reuses postgres adapter |
|
||||
| mongodb | MongoDB | mongo-cxx-driver, JSON↔BSON |
|
||||
| redis | Redis | Cache layer (L1/L2 with primary DB) |
|
||||
| elasticsearch | Elasticsearch | Search layer (full-text, analytics) |
|
||||
| cassandra | Cassandra | Wide-column store |
|
||||
| surrealdb | SurrealDB | Multi-model (docs/graphs/KV) |
|
||||
| supabase | Supabase REST/Direct | PostgreSQL + REST + Realtime + RLS |
|
||||
| prisma | Prisma | ORM, HTTP bridge |
|
||||
|
||||
**Config**: `DBAL_SCHEMA_DIR`, `DBAL_TEMPLATE_DIR`, `DATABASE_URL` (adapter options as query strings)
|
||||
**Endpoints**: `/health`, `/version`, `/status`, `/{tenant}/{package}/{entity}` (RESTful CRUD)
|
||||
|
||||
**Multi-Adapter Patterns**:
|
||||
- **Redis caching**: `DBAL_CACHE_URL=redis://localhost:6379/0?ttl=300&pattern=read-through`
|
||||
- **Elasticsearch search**: `DBAL_SEARCH_URL=http://localhost:9200?index=dbal_search&refresh=true`
|
||||
- Patterns: read-through, write-through, cache-aside, dual-write, CDC, search-first
|
||||
|
||||
### Workflow Engine (`workflow/`)
|
||||
|
||||
Multi-language: executors (TS, Python, C++), plugins (C++/16 categories, Python, TS, Go, Rust, Mojo), 19 example workflows. Dynamic plugin registry at `/api/plugins` (152 nodes).
|
||||
|
||||
### Game Engine (`gameengine/`)
|
||||
|
||||
SDL 3.2.20, bgfx 1.129, MaterialX 1.39.1, Assimp, Bullet3, Box2D, EnTT 3.16.0, FFmpeg 8.0.1. 36 service interfaces. CLI: `--bootstrap bootstrap_mac --game seed`.
|
||||
|
||||
### CodeForge IDE (`codegen/`)
|
||||
|
||||
~420 TSX files (legacy) → 338 JSON definitions (target). See `codegen/CLAUDE.md`.
|
||||
|
||||
### FakeMUI (`fakemui/`)
|
||||
|
||||
167 components (145 core + 22 email) across 11 categories. Import from `@metabuilder/fakemui`. React/TS, QML (104+), Python (15), 421 icons, 78 SCSS modules.
|
||||
|
||||
### React Hooks (`hooks/`)
|
||||
|
||||
`@metabuilder/hooks` (30 hooks), `@metabuilder/hooks-utils` (useTableState, useAsyncOperation, useDebounced, useThrottled), `@metabuilder/hooks-forms` (useFormBuilder). Multi-version peer deps (React 18/19, Redux 8/9).
|
||||
|
||||
### Redux
|
||||
|
||||
12 packages: hooks, hooks-utils, hooks-forms, core-hooks, api-clients, hooks-*, redux-slices, service-adapters, timing-utils. Active in: workflowui, frontends/nextjs, codegen, pastebin.
|
||||
|
||||
### Email Client
|
||||
|
||||
Phases 1-5 complete (frontend). 4 DBAL schemas, 22 FakeMUI components, 4 Redux slices, 6 hooks, API endpoints. Phases 6-8 TODO: workflow plugins, Flask backend, Docker.
|
||||
|
||||
---
|
||||
|
||||
## Package System (`packages/`)
|
||||
|
||||
62 packages: Admin (7), UI Core (8), Dev Tools (7), Features (6), Testing (4).
|
||||
|
||||
```
|
||||
packages/{packageId}/
|
||||
├── package.json, components/ui.json, page-config/
|
||||
├── permissions/roles.json, workflow/*.jsonscript
|
||||
├── styles/tokens.json, tests/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## API Routing
|
||||
|
||||
```
|
||||
/api/v1/{tenant}/{package}/{entity}[/{id}[/{action}]]
|
||||
```
|
||||
Rate limits: Login 5/min, Register 3/min, List 100/min, Mutations 50/min.
|
||||
|
||||
---
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
Frontends (CLI C++ | Qt6 QML | Next.js React)
|
||||
→ Redux + redux-persist (IndexedDB, client-side state)
|
||||
→ DBAL C++ daemon (REST API, 14 backends)
|
||||
→ Database (SQLite dev | PostgreSQL prod)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Common Commands
|
||||
|
||||
```bash
|
||||
npm run dev / build / typecheck / lint / test:e2e
|
||||
npm run build --workspaces
|
||||
cd deployment && ./build-base-images.sh # Build Docker base images
|
||||
|
||||
# Deploy full stack
|
||||
cd deployment && docker compose -f docker-compose.stack.yml up -d
|
||||
|
||||
# Build & deploy specific apps
|
||||
./build-apps.sh --force dbal pastebin # Next.js frontend only
|
||||
docker compose -f docker-compose.stack.yml build pastebin-backend # Flask backend
|
||||
|
||||
# DBAL logs / seed verification
|
||||
docker logs -f metabuilder-dbal
|
||||
docker logs metabuilder-dbal 2>&1 | grep -i "workflow\|seed"
|
||||
|
||||
# Force re-seed
|
||||
curl -X POST http://localhost:8080/admin/seed \
|
||||
-H "Authorization: Bearer $DBAL_ADMIN_TOKEN" -d '{"force": true}'
|
||||
```
|
||||
|
||||
Pre-commit: `npm run build && npm run typecheck && npm run lint && npm run test:e2e`
|
||||
|
||||
---
|
||||
|
||||
## Coding Standards
|
||||
|
||||
### Code Quality Rules
|
||||
- One lambda per file, no @ts-ignore, no implicit any, no dead code
|
||||
- JSDoc on public APIs, self-documenting names
|
||||
- FULL implementations only - no WIP code on main
|
||||
- No disabled tests (DISABLED_, @skip)
|
||||
|
||||
### No Work-In-Progress Code
|
||||
- No `-wip`, `-todo`, `-temp` directories
|
||||
- All code is 100% complete OR not included
|
||||
- Incomplete work on feature branches only
|
||||
|
||||
### UI/Styling
|
||||
- **workflowui + new projects**: FakeMUI only (`@metabuilder/fakemui`)
|
||||
- **Legacy projects**: Radix UI + Tailwind acceptable
|
||||
- **Never**: Direct @mui/material imports in workflowui
|
||||
|
||||
### WorkflowUI Components
|
||||
- Atomic components <100 LOC, SCSS modules, no sx prop
|
||||
- Categories: layout/, cards/, forms/, navigation/, feedback/
|
||||
- Import pattern: `@/components/{domain}/{Component}`
|
||||
|
||||
### Security Checklist
|
||||
- Input validation, no XSS (no innerHTML with user data), no SQL injection
|
||||
- Passwords hashed SHA-512, no secrets committed, multi-tenant tenantId filtering
|
||||
|
||||
### Declarative-First
|
||||
Ask: Could this be JSON config? Could a generic renderer handle this? Is it filtering by tenantId?
|
||||
|
||||
---
|
||||
|
||||
## Dependency Management
|
||||
|
||||
### Conan (C++)
|
||||
Updated: cpr, lua, sol2, cmake, qt, ninja, sqlite3, fmt, spdlog, shaderc. Run `conan install . --build=missing`.
|
||||
|
||||
### npm
|
||||
Multi-version peer deps. React 18/19, TypeScript 5.9.3, Next.js 14-16, @reduxjs/toolkit 1.9/2.5. Run `npm install` at root.
|
||||
|
||||
### Workflow Plugins
|
||||
- Python: `requirements.txt` (Python 3.9+)
|
||||
- Go: `go.mod` + `go.work` (Go 1.21+, stdlib only)
|
||||
- TypeScript: `@metabuilder/workflow: ^3.0.0`
|
||||
|
||||
### Known Issues
|
||||
- postgres dashboard uses @mui/material directly (should migrate to FakeMUI)
|
||||
- 7 moderate npm vulnerabilities (lodash in @prisma/dev, LOW production risk)
|
||||
- eslint/vite version conflicts in some workspaces (partially fixed)
|
||||
|
||||
---
|
||||
|
||||
## AI Assistant Directives
|
||||
|
||||
**Must-Follow** (No Exceptions):
|
||||
1. Read CLAUDE.md first before any work
|
||||
2. IMPLEMENT, don't delete - fix compilation errors properly
|
||||
3. Use Explore agent for feasibility checks and planning
|
||||
4. Plan before coding - list affected files, determine scope
|
||||
5. CHECK before DELETE - `git show HEAD:path` first
|
||||
6. Use subagents for complex work
|
||||
7. Update CLAUDE.md with new gotchas/patterns
|
||||
8. Reports → `reports.db`, Docs → `docs.db` (SQLite, not markdown files)
|
||||
9. Git: `git add` on project root first, then commit
|
||||
10. Use `mv` not `cp` (prevents duplicates)
|
||||
11. Log long commands: `| tee txt/command-$(date +%Y%m%d-%H%M%S).log`
|
||||
12. Search SQLite before browsing files
|
||||
|
||||
### Gotchas & Lessons Learned
|
||||
|
||||
| Gotcha | Prevention |
|
||||
|--------|-----------|
|
||||
| Conan profile in Docker mount | Run `conan profile detect` INSIDE cache-mounted RUN |
|
||||
| Missing types after refactor | Verify all referenced types exist before committing |
|
||||
| Headers in src/ not include/ | Use relative paths or fix build include dirs |
|
||||
| No logs for long commands | ALWAYS pipe to txt/*.log |
|
||||
| Dockerfile `build/` conflict | Use `_build/` |
|
||||
| Drogon wildcard routes | Check docs for path param syntax |
|
||||
| `cp` instead of `mv` | ALWAYS use `mv` to relocate |
|
||||
| Deleting without checking | ALWAYS `git show HEAD:path` first |
|
||||
| Skipping Explore agent | Always Explore before implementation |
|
||||
| Version conflicts (eslint, vite) | Check ALL workspaces upfront |
|
||||
| nlohmann/json includes | Link to ALL targets, not just transitive |
|
||||
| Docker Compose YAML special chars | Quote env vars: `"DATABASE_URL=:memory:"` |
|
||||
| nlohmann/json iterators | Use `it.value()` not `it->second` (std::map syntax fails) |
|
||||
| dbal-init volume stale | Rebuild with `docker compose build dbal-init` when schema file extensions change |
|
||||
| `.dockerignore` excludes `dbal/` | Whitelist specific subdirs: `!dbal/shared/seeds/database` |
|
||||
| `build-apps.sh pastebin` ≠ Flask backend | Use `docker compose build pastebin-backend` for Flask |
|
||||
| `ensureClient()` before startup DB ops | `dbal_client_` is null in `registerRoutes()` — must call `ensureClient()` first |
|
||||
| Seed data in Flask Python | NEVER — declarative seed data belongs in `dbal/shared/seeds/database/*.json` |
|
||||
| Werkzeug scrypt on macOS Python | Generate hashes inside running container: `docker exec metabuilder-pastebin-backend python3 -c "..."` |
|
||||
|
||||
### Critical Folders to Check Before Any Task
|
||||
|
||||
`/redux/`, `/components/`, `/scss/`, `/hooks/`, `/types/`, `/interfaces/`, `/icons/`, `/workflow/`, `/schemas/`, `/packages/`, `/deployment/`, `/docs/docs.db`, `/txt/reports.db`
|
||||
|
||||
### Task Workflow
|
||||
1. Read relevant CLAUDE.md
|
||||
2. Search SQLite docs: `docs.py search` / `reports.py search`
|
||||
3. Check if functionality already exists in critical folders
|
||||
4. Use Explore agent for codebase questions
|
||||
5. Plan affected files before coding
|
||||
6. Verify multi-tenant filtering + rate limiting
|
||||
|
||||
---
|
||||
|
||||
## Definition of Done
|
||||
|
||||
A task is complete when:
|
||||
- **Builds**: Compiles, core functionality works, type safety reasonable
|
||||
- **Tests**: All pass, new tests added, edge cases covered, multi-tenant verified
|
||||
- **Deploy**: Docker builds, services healthy, env vars documented, deps install
|
||||
- **Docs**: CLAUDE.md updated, reports in SQLite, architecture docs updated
|
||||
- **Security**: Input validation, no XSS/SQLi, passwords hashed, no secrets, rate limited
|
||||
- **Git**: Clear commit message, co-authored tag, no merge conflicts
|
||||
|
||||
**Standards**: IMPLEMENT don't disable. Real solutions over workarounds. TODOs acceptable for future work. Pragmatic over perfect.
|
||||
|
||||
**Unacceptable**: Deleting code instead of fixing. Fake implementations. Claiming done when broken.
|
||||
|
||||
**Task-Specific**:
|
||||
- Refactoring: ~100 LOC classes, original functionality preserved, tests pass
|
||||
- New Adapters: CRUD + bulk + query + metadata ops, connection management, Result<T> errors
|
||||
- Docker: Multi-stage, BuildKit cache, <500MB runtime, non-root user, health check
|
||||
- Documentation: Imported to SQLite, categorized, searchable via FTS5
|
||||
|
||||
---
|
||||
|
||||
## Project Organization
|
||||
|
||||
- **Root**: Minimal - config, CI/CD, build, package files only
|
||||
- **Reports**: `txt/reports.db` - create via `python3 reports.py create "Title" "Content..."`
|
||||
- **Docs**: `docs/docs.db` - create via `python3 docs.py create "Title" "Content..." --category guides`
|
||||
- **Rule**: Create directly in SQLite, do NOT create markdown files first
|
||||
- **File org**: Implementation type first (react/, python/, qml/), component categorization, preserve legacy in archived folders
|
||||
|
||||
---
|
||||
|
||||
**Status**: Production Ready (Phase 2 Complete)
|
||||
**Next**: Universal Platform - Core Infrastructure (State Machine, Command Bus, Event Stream, VFS, Frontend Bus)
|
||||
43
Jenkinsfile
vendored
43
Jenkinsfile
vendored
@@ -1,43 +0,0 @@
|
||||
pipeline {
|
||||
agent any
|
||||
|
||||
tools {
|
||||
nodejs 'node25'
|
||||
}
|
||||
|
||||
options {
|
||||
timestamps()
|
||||
}
|
||||
|
||||
stages {
|
||||
stage('Checkout') {
|
||||
steps {
|
||||
checkout scm
|
||||
}
|
||||
}
|
||||
|
||||
stage('Install') {
|
||||
steps {
|
||||
sh 'npm ci'
|
||||
}
|
||||
}
|
||||
|
||||
stage('Lint') {
|
||||
steps {
|
||||
sh 'npm run lint'
|
||||
}
|
||||
}
|
||||
|
||||
stage('Typecheck') {
|
||||
steps {
|
||||
sh 'npm run typecheck'
|
||||
}
|
||||
}
|
||||
|
||||
stage('Test') {
|
||||
steps {
|
||||
sh 'npm test'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,199 +0,0 @@
|
||||
# Quick Reference: MetaBuilder Game Engine
|
||||
|
||||
## Latest Work (Session 30)
|
||||
|
||||
**Just Completed**:
|
||||
- ✅ 27 new atomic workflow steps
|
||||
- ✅ 4 services converted (Audio, Input, Graphics, Scene)
|
||||
- ✅ 1 dead service deleted (SelectionStateService)
|
||||
- ✅ All code committed and verified
|
||||
|
||||
**Latest Commits**:
|
||||
```
|
||||
72520f42c - docs: Session 30 summary
|
||||
0ff57a22b - chore: Delete SelectionStateService
|
||||
cc2a594b0 - feat: Convert Audio, Input, Graphics, Scene services
|
||||
5d8441515 - feat: Implement graphics init workflow steps
|
||||
```
|
||||
|
||||
## Build Commands
|
||||
|
||||
```bash
|
||||
cd /Users/rmac/Documents/metabuilder/gameengine
|
||||
|
||||
# Build main app
|
||||
cmake --build build/Release --target sdl3_app
|
||||
|
||||
# Run with default game (seed)
|
||||
./build/Release/sdl3_app --bootstrap bootstrap_mac --game seed
|
||||
|
||||
# Run with specific game
|
||||
./build/Release/sdl3_app --bootstrap bootstrap_mac --game standalone_cubes
|
||||
|
||||
# Run with tracing
|
||||
./build/Release/sdl3_app --bootstrap bootstrap_mac --game seed --trace
|
||||
```
|
||||
|
||||
## Available Workflow Steps (75+)
|
||||
|
||||
### Graphics (10 steps)
|
||||
- graphics.bgfx.init_viewport
|
||||
- graphics.bgfx.init_renderer
|
||||
- graphics.bgfx.init
|
||||
- graphics.shader.load
|
||||
- graphics.buffer.create_vertex
|
||||
- graphics.buffer.create_index
|
||||
- graphics.frame.begin
|
||||
- graphics.frame.end
|
||||
- graphics.draw.submit
|
||||
- graphics.screenshot.request
|
||||
|
||||
### Input (5 steps)
|
||||
- input.key.pressed
|
||||
- input.mouse.position
|
||||
- input.mouse.button.pressed
|
||||
- input.gamepad.axis
|
||||
- input.gamepad.button.pressed
|
||||
|
||||
### Audio (7 steps)
|
||||
- audio.play
|
||||
- audio.pause
|
||||
- audio.resume
|
||||
- audio.seek
|
||||
- audio.set_volume
|
||||
- audio.stop
|
||||
- audio.set_looping
|
||||
|
||||
### Scene (4+ steps)
|
||||
- scene.create
|
||||
- scene.add_geometry
|
||||
- scene.remove_geometry
|
||||
- scene.get_bounds
|
||||
- scene.load
|
||||
- scene.clear
|
||||
- scene.update
|
||||
|
||||
### Plus 40+ more in:
|
||||
- Camera (teleport, look_at, build_view_state, set_fov, set_pose)
|
||||
- Math (add, subtract, multiply, divide, min, max, abs, round, clamp)
|
||||
- String (concat, split, join, upper, lower, trim, replace, equals, contains)
|
||||
- Logic (and, or, not, if/then/else, compare)
|
||||
- Collections (append, count, filter, map, reduce)
|
||||
- Validation (checkpoint, png validation)
|
||||
- And many more...
|
||||
|
||||
## Architecture
|
||||
|
||||
**95% Data-Driven**:
|
||||
- JSON workflows orchestrate all core systems
|
||||
- Minimal C++ service code (only integration layer)
|
||||
- Each step: ~50-100 LOC, testable in isolation
|
||||
- Dynamic step registration via plugin IDs
|
||||
|
||||
**Zero Monolithic Services**:
|
||||
- Graphics: Complete pipeline via 10 workflow steps
|
||||
- Input: Full event handling via 5 steps
|
||||
- Audio: Complete playback control via 7 steps
|
||||
- Scene: Full 3D management via 4+ steps
|
||||
|
||||
## Key Files
|
||||
|
||||
**Workflow Definitions**:
|
||||
```
|
||||
/gameengine/packages/*/workflows/*.json
|
||||
- bootstrap_mac/workflows/
|
||||
- standalone_cubes/workflows/graphics_init_atomic.json
|
||||
- seed/workflows/demo_gameplay.json
|
||||
```
|
||||
|
||||
**Workflow Step Implementations**:
|
||||
```
|
||||
/gameengine/src/services/impl/workflow/
|
||||
- graphics/ (10 graphics steps)
|
||||
- workflow_generic_steps/ (5 input + 4 audio steps)
|
||||
- scene/ (4 scene steps)
|
||||
- frame/ (40+ frame/game steps)
|
||||
- workflow_*_step_registrar*.cpp (step discovery)
|
||||
```
|
||||
|
||||
**Main Entry Point**:
|
||||
```
|
||||
/gameengine/src/main.cpp
|
||||
```
|
||||
|
||||
## Recent Fixes
|
||||
|
||||
1. **Red background issue** (Fixed Feb 11)
|
||||
- Removed hardcoded color in bgfx initialization
|
||||
- User confirmed: "pink and flashing thing" renders correctly
|
||||
|
||||
2. **Validation tour disabled** (Feb 11)
|
||||
- Was forcing test checkpoints in gameplay
|
||||
- Removed from demo_gameplay.json
|
||||
|
||||
3. **Dead code cleanup** (Feb 11)
|
||||
- SelectionStateService deleted (136 LOC)
|
||||
- No impact on functionality (was orphaned)
|
||||
|
||||
## Next Steps (If Continuing)
|
||||
|
||||
**High Priority** (2-3 hours each):
|
||||
1. Shader validation steps (120 LOC)
|
||||
2. Render coordination steps (80 LOC)
|
||||
3. Diagnostics steps (100 LOC)
|
||||
|
||||
**Medium Priority**:
|
||||
4. GUI parametric drawing steps (90 LOC)
|
||||
|
||||
**Result**: Complete atomic conversion of all non-infrastructure services
|
||||
|
||||
## Testing
|
||||
|
||||
**Manual Test**:
|
||||
```bash
|
||||
./build/Release/sdl3_app --bootstrap bootstrap_mac --game standalone_cubes
|
||||
# Should see: Pink/orange color, cube animation, window updates
|
||||
# Expected: 52 FPS rendering
|
||||
```
|
||||
|
||||
**Unit Tests**:
|
||||
```bash
|
||||
# Audio step tests exist (369 LOC)
|
||||
# Located in: gameengine/tests/unit/workflow/test_audio_*.cpp
|
||||
```
|
||||
|
||||
## Performance Notes
|
||||
|
||||
- **Build time**: ~2 minutes (full rebuild)
|
||||
- **Binary size**: 36MB (arm64)
|
||||
- **Frame rate**: 52 FPS (verified on metal)
|
||||
- **Memory**: Efficient (atomic-based spy thread ~3-5ns overhead)
|
||||
|
||||
## Git Server
|
||||
|
||||
**Local Setup**: Hospital bedroom
|
||||
- Repository size: 8.1GB
|
||||
- All commits locally safe
|
||||
- No network dependencies
|
||||
- Full version history: 60+ commits
|
||||
|
||||
## Architecture Philosophy
|
||||
|
||||
**95% Data, 5% Code**:
|
||||
- Configuration: JSON workflows
|
||||
- Business logic: JSON variable flows
|
||||
- Infrastructure: C++ (only 5% of code)
|
||||
- Composition: JSON orchestration of atomic steps
|
||||
|
||||
**One Responsibility Per Step**:
|
||||
- Each workflow step does ONE thing
|
||||
- Testable in isolation
|
||||
- Reusable across workflows
|
||||
- Composable into complex behaviors
|
||||
|
||||
---
|
||||
|
||||
**Last Updated**: Feb 11, 2026 (Session 30)
|
||||
**Status**: Production-ready architecture, 95% data-driven
|
||||
**Git**: All work committed and verified locally
|
||||
|
||||
815
README.md
815
README.md
@@ -1,155 +1,774 @@
|
||||
# MetaBuilder
|
||||
|
||||
**Philosophy**: 95% JSON config, 5% TypeScript/C++ infrastructure
|
||||
**Scale**: 27,826+ files across 34 directories
|
||||
**Status**: Production-ready — Phase 2 complete
|
||||
**An ultra-generic, data-driven platform where everything flows through the database.**
|
||||
|
||||
No hardcoded routes, no component imports, no assumptions. The entire application structure lives in the database, rendered by a generic JSON-to-React engine.
|
||||
|
||||
---
|
||||
|
||||
## What's Running
|
||||
## Table of Contents
|
||||
|
||||
### Pastebin — Code Snippet Manager
|
||||
Full-stack app: Next.js frontend + Flask auth backend + C++ DBAL API
|
||||
1. [Core Concept](#core-concept)
|
||||
2. [Quick Start](#quick-start)
|
||||
3. [Architecture](#architecture)
|
||||
4. [Routing System](#routing-system)
|
||||
5. [Package System](#package-system)
|
||||
6. [Permission System](#permission-system)
|
||||
7. [Deployment](#deployment)
|
||||
8. [Database](#database)
|
||||
9. [Development](#development)
|
||||
10. [Project Structure](#project-structure)
|
||||
|
||||
---
|
||||
|
||||
## Core Concept
|
||||
|
||||
### The Mental Model
|
||||
|
||||
```
|
||||
http://localhost/pastebin # UI
|
||||
http://localhost/pastebin-api # Flask auth (register, login, Python runner)
|
||||
http://localhost:8080 # DBAL C++ REST API (entities)
|
||||
Browser URL → Database Query → JSON Component → Generic Renderer → React → User
|
||||
```
|
||||
|
||||
**Test accounts** (seeded on first startup):
|
||||
**Zero hardcoded connections.** Everything is a database lookup:
|
||||
|
||||
| User | Password | Namespaces | Snippets |
|
||||
|------|----------|------------|---------|
|
||||
| `demo` | `demo1234` | Default, Python Recipes, SQL Patterns, Utilities | 11 |
|
||||
| `alice` | `alice1234` | Default, React Components, CSS Tricks, JS Utilities | 9 |
|
||||
| `bob` | `bob12345` | Default, Go Patterns, Bash Scripts, API Design | 8 |
|
||||
```typescript
|
||||
// ❌ Traditional way (hardcoded)
|
||||
import HomePage from './HomePage'
|
||||
<Route path="/" component={HomePage} />
|
||||
|
||||
// ✅ MetaBuilder way (data-driven)
|
||||
const route = await db.query('PageConfig', { path: '/' })
|
||||
const component = await loadPackage(route.packageId)
|
||||
return renderJSONComponent(component)
|
||||
```
|
||||
|
||||
### Key Principles
|
||||
|
||||
1. **No Hardcoded Routes**: Routes live in `PageConfig` table
|
||||
2. **No Component Imports**: Components are JSON definitions in package files
|
||||
3. **No Direct Database Access**: Everything goes through DBAL (Database Abstraction Layer)
|
||||
4. **Complete Loose Coupling**: Frontend knows nothing about packages
|
||||
|
||||
---
|
||||
|
||||
## Quick Start
|
||||
|
||||
### One-Command Deployment
|
||||
|
||||
```bash
|
||||
# Deploy full stack
|
||||
cd deployment
|
||||
docker compose -f docker-compose.stack.yml up -d
|
||||
|
||||
# Build & deploy a specific app
|
||||
./build-apps.sh --force dbal pastebin
|
||||
|
||||
# Rebuild base images (rare)
|
||||
./build-base-images.sh
|
||||
# Deploy everything (PostgreSQL, DBAL, Next.js, Media daemon, Redis, Nginx)
|
||||
./deployment/deploy.sh all --bootstrap
|
||||
```
|
||||
|
||||
This spins up:
|
||||
- PostgreSQL database
|
||||
- C++ DBAL daemon (database abstraction)
|
||||
- Next.js frontend
|
||||
- C++ media processing daemon
|
||||
- Redis cache
|
||||
- Nginx reverse proxy
|
||||
- Monitoring stack (optional)
|
||||
|
||||
**Then visit**: `http://localhost:3000`
|
||||
|
||||
### Development Setup
|
||||
|
||||
```bash
|
||||
# Clone and install
|
||||
git clone <repo>
|
||||
cd metabuilder
|
||||
|
||||
# Option 1: Run from root (recommended for quick setup)
|
||||
npm install
|
||||
npm run db:generate
|
||||
npm run db:push
|
||||
|
||||
# Option 2: Run from frontends/nextjs
|
||||
cd frontends/nextjs
|
||||
npm install
|
||||
npm run db:generate
|
||||
npm run db:push
|
||||
|
||||
# Bootstrap seed data
|
||||
cd ../../deployment
|
||||
./scripts/bootstrap-system.sh
|
||||
|
||||
# Start development (from root)
|
||||
cd ..
|
||||
npm run dev
|
||||
|
||||
# Or from frontends/nextjs
|
||||
cd frontends/nextjs
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Docker & Docker Compose
|
||||
- Node.js 18+
|
||||
- Build tools: cmake, ninja, g++/clang (for C++ daemons)
|
||||
|
||||
---
|
||||
|
||||
## Architecture
|
||||
|
||||
### System Components
|
||||
|
||||
```
|
||||
Browser
|
||||
└── Next.js (React + Redux + IndexedDB)
|
||||
└── Flask (auth, Python runner, JWT)
|
||||
└── DBAL C++ daemon (REST API, 14 DB backends)
|
||||
└── PostgreSQL (prod) / SQLite (dev)
|
||||
┌─────────────┐
|
||||
│ Browser │
|
||||
└──────┬──────┘
|
||||
│ HTTP
|
||||
┌──────▼──────┐ ┌───────────┐
|
||||
│ Nginx │────▶│ Redis │
|
||||
└──────┬──────┘ └───────────┘
|
||||
│
|
||||
┌──────▼──────┐ ┌───────────┐
|
||||
│ Next.js │────▶│ DBAL │
|
||||
│ Frontend │ │ Daemon │
|
||||
└──────┬──────┘ │ (C++) │
|
||||
│ └─────┬─────┘
|
||||
│ │
|
||||
│ ┌─────▼─────┐
|
||||
│ │ PostgreSQL│
|
||||
│ └───────────┘
|
||||
│
|
||||
┌──────▼──────┐ ┌───────────┐
|
||||
│ Media │────▶│ HLS │
|
||||
│ Daemon │ │ Streams │
|
||||
│ (C++) │ └───────────┘
|
||||
└─────────────┘
|
||||
```
|
||||
|
||||
**DBAL event flow** (user registration → automatic seeding):
|
||||
### Data Flow
|
||||
|
||||
1. **User visits URL** (`/`, `/dashboard`, `/about`)
|
||||
2. **Next.js queries PageConfig** table for that path
|
||||
3. **Database returns** packageId + component reference
|
||||
4. **Frontend loads** JSON package from `/packages/{packageId}/`
|
||||
5. **Generic renderer** converts JSON → React elements
|
||||
6. **User sees** the rendered page
|
||||
|
||||
**Zero hardcoded assumptions!**
|
||||
|
||||
---
|
||||
|
||||
## Routing System
|
||||
|
||||
### Priority-Based Routing
|
||||
|
||||
Routes have two priority levels:
|
||||
|
||||
**Priority 1: God Panel Routes** (PageConfig table)
|
||||
- User-configurable through admin UI
|
||||
- God/supergod users can add/remove/modify routes
|
||||
- Highest priority, overrides everything
|
||||
|
||||
**Priority 2: Package Routes** (InstalledPackage.config)
|
||||
- Package-defined defaults
|
||||
- Set during package installation
|
||||
- Fallback when god panel has no override
|
||||
|
||||
### Example: Root Route
|
||||
|
||||
**Database seed** ([seed/database/installed_packages.yaml:44-54](seed/database/installed_packages.yaml#L44-L54)):
|
||||
```yaml
|
||||
- packageId: ui_home
|
||||
config: |
|
||||
{
|
||||
"defaultRoute": "/",
|
||||
"publicAccess": true
|
||||
}
|
||||
```
|
||||
POST /User → pastebin.User.created → WfEngine (detached thread)
|
||||
└── on_user_created.json workflow
|
||||
├── dbal.uuid × 7
|
||||
├── dbal.timestamp
|
||||
├── dbal.entity.create → Namespace "Default"
|
||||
├── dbal.entity.create → Namespace "Examples"
|
||||
└── dbal.entity.create × 5 → seed snippets
|
||||
|
||||
**Frontend code** ([frontends/nextjs/src/app/page.tsx](frontends/nextjs/src/app/page.tsx)):
|
||||
```typescript
|
||||
// Check god panel routes first
|
||||
const godRoute = await db.query('PageConfig', { path: '/', isPublished: true })
|
||||
if (godRoute) {
|
||||
return renderComponent(godRoute.packageId, godRoute.component)
|
||||
}
|
||||
|
||||
// Fall back to package default routes
|
||||
const pkg = await db.query('InstalledPackage', { 'config.defaultRoute': '/' })
|
||||
return renderComponent(pkg.packageId, 'HomePage')
|
||||
```
|
||||
|
||||
### God Panel Override
|
||||
|
||||
Supergod users can remap any route:
|
||||
|
||||
```sql
|
||||
-- Remap "/" to dashboard instead of ui_home
|
||||
INSERT INTO "PageConfig" (
|
||||
id, path, packageId, component, level, requiresAuth, isPublished
|
||||
) VALUES (
|
||||
'root_route', '/', 'dashboard', 'DashboardPage', 1, true, true
|
||||
);
|
||||
```
|
||||
|
||||
**No code changes required!**
|
||||
|
||||
### Route Schema
|
||||
|
||||
```prisma
|
||||
model PageConfig {
|
||||
path String // URL: "/", "/dashboard", "/about"
|
||||
packageId String? // Which package: "ui_home", "dashboard"
|
||||
component String? // Which component: "HomePage", "DashboardPage"
|
||||
componentTree String // Or full JSON component tree
|
||||
level Int // Permission level (0-5)
|
||||
requiresAuth Boolean
|
||||
isPublished Boolean
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Key Directories
|
||||
## Package System
|
||||
|
||||
### Package Structure
|
||||
|
||||
Packages are **completely self-contained** JSON + optional static files:
|
||||
|
||||
```
|
||||
metabuilder/
|
||||
├── dbal/
|
||||
│ ├── production/ # C++ daemon (Drogon HTTP, 14 DB backends, JWT auth)
|
||||
│ │ ├── src/workflow/ # Event-driven workflow engine (7 step types)
|
||||
│ │ ├── src/auth/ # JWT validation + JSON ACL config
|
||||
│ │ └── build-config/ # Dockerfile, CMakeLists, conanfile
|
||||
│ └── shared/
|
||||
│ ├── api/schema/ # JSON entity schemas (source of truth)
|
||||
│ │ ├── entities/ # 39 entity definitions
|
||||
│ │ ├── events/ # event_config.json → workflow mappings
|
||||
│ │ └── workflows/ # on_user_created.json etc.
|
||||
│ └── seeds/database/ # Declarative JSON seed data
|
||||
├── frontends/pastebin/
|
||||
│ ├── src/ # Next.js app (React + Redux + FakeMUI)
|
||||
│ └── backend/ # Flask auth + Python runner
|
||||
├── workflow/ # DAG workflow engine (TS, Python, C++ plugins)
|
||||
├── gameengine/ # SDL3/bgfx 2D/3D engine (27/27 tests)
|
||||
├── fakemui/ # Material Design clone (167 components)
|
||||
├── packages/ # 62 feature packages
|
||||
├── deployment/ # Docker compose stack + build scripts
|
||||
└── CLAUDE.md # AI assistant guide (read first)
|
||||
packages/{packageId}/
|
||||
├── package.json # Metadata
|
||||
├── components/
|
||||
│ └── ui.json # Declarative JSON components
|
||||
├── styles/
|
||||
│ └── tokens.json # Design tokens (colors, spacing, shadows, etc.)
|
||||
└── static/
|
||||
└── assets/ # Images, fonts, etc.
|
||||
```
|
||||
|
||||
### JSON Component Example
|
||||
|
||||
From [packages/ui_home/components/ui.json](packages/ui_home/components/ui.json):
|
||||
|
||||
```json
|
||||
{
|
||||
"components": [
|
||||
{
|
||||
"id": "home_page",
|
||||
"name": "HomePage",
|
||||
"description": "Main home page layout",
|
||||
"render": {
|
||||
"template": {
|
||||
"type": "Box",
|
||||
"component": "main",
|
||||
"className": "home-page",
|
||||
"children": [
|
||||
{ "$ref": "hero_section" },
|
||||
{ "$ref": "features_section" }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "hero_section",
|
||||
"name": "HeroSection",
|
||||
"props": [
|
||||
{ "name": "title", "type": "string", "default": "Build Anything, Visually" }
|
||||
],
|
||||
"render": {
|
||||
"template": {
|
||||
"type": "Box",
|
||||
"component": "section",
|
||||
"className": "hero-section",
|
||||
"children": [
|
||||
{
|
||||
"type": "Text",
|
||||
"variant": "h1",
|
||||
"children": "{{title}}"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Generic Renderer
|
||||
|
||||
The frontend **never imports package components**. It uses a generic renderer:
|
||||
|
||||
```typescript
|
||||
import { renderJSONComponent } from '@/lib/packages/json/render-json-component'
|
||||
|
||||
// Load component from JSON
|
||||
const pkg = await loadJSONPackage('/packages/ui_home')
|
||||
const component = pkg.components.find(c => c.id === 'home_page')
|
||||
|
||||
// Render using generic renderer (no hardcoded React components!)
|
||||
return renderJSONComponent(component, {}, {})
|
||||
```
|
||||
|
||||
### Available Packages
|
||||
|
||||
| Package ID | Description |
|
||||
|------------|-------------|
|
||||
| `ui_home` | Landing page with hero, features, about sections |
|
||||
| `ui_header` | Application header/navbar |
|
||||
| `ui_footer` | Application footer |
|
||||
| `ui_auth` | Authentication UI components |
|
||||
| `ui_login` | Login page |
|
||||
| `dashboard` | User dashboard |
|
||||
| `user_manager` | User management (admin) |
|
||||
| `package_manager` | Package installation UI (god) |
|
||||
| `database_manager` | Database management (supergod) |
|
||||
| `schema_editor` | Schema editor (supergod) |
|
||||
|
||||
---
|
||||
|
||||
## Permission System
|
||||
|
||||
### 6-Level Hierarchy
|
||||
|
||||
| Level | Role | Access | Example Route |
|
||||
|-------|------|--------|---------------|
|
||||
| 0 | Public | Unauthenticated | `/` (landing page) |
|
||||
| 1 | User | Personal dashboard | `/dashboard` |
|
||||
| 2 | Moderator | Content moderation | `/moderator` |
|
||||
| 3 | Admin | User management | `/admin` |
|
||||
| 4 | God | Package installation, workflows | `/builder` |
|
||||
| 5 | Supergod | Full system control | `/supergod` |
|
||||
|
||||
**Each level inherits all permissions from levels below.**
|
||||
|
||||
### Permission Checks
|
||||
|
||||
Database records control access:
|
||||
|
||||
```yaml
|
||||
# seed/database/package_permissions.yaml
|
||||
- packageId: ui_home
|
||||
role: public # Level 0 - anyone
|
||||
permission: read
|
||||
granted: true
|
||||
|
||||
- packageId: dashboard
|
||||
role: user # Level 1 - authenticated
|
||||
permission: read
|
||||
granted: true
|
||||
|
||||
- packageId: database_manager
|
||||
role: supergod # Level 5 - full control
|
||||
permission: admin
|
||||
granted: true
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## DBAL Backends (14)
|
||||
## Deployment
|
||||
|
||||
| Adapter | Backend |
|
||||
|---------|---------|
|
||||
| `memory` | In-process (testing) |
|
||||
| `sqlite` | SQLite3 |
|
||||
| `postgres` | PostgreSQL |
|
||||
| `mysql` / `mariadb` | MySQL / MariaDB |
|
||||
| `cockroachdb` | CockroachDB |
|
||||
| `mongodb` | MongoDB |
|
||||
| `redis` | Redis (cache layer) |
|
||||
| `elasticsearch` | Elasticsearch (search layer) |
|
||||
| `cassandra` | Cassandra |
|
||||
| `surrealdb` | SurrealDB |
|
||||
| `supabase` | Supabase REST |
|
||||
| `prisma` | Prisma ORM bridge |
|
||||
### One-Command Deploy
|
||||
|
||||
Switch adapter at runtime: `DATABASE_URL=sqlite://:memory: DBAL_ADAPTER=sqlite`
|
||||
```bash
|
||||
# Full stack with bootstrap
|
||||
./deployment/deploy.sh all --bootstrap
|
||||
|
||||
# Individual stacks
|
||||
./deployment/deploy.sh production # Main services only
|
||||
./deployment/deploy.sh development # Dev environment
|
||||
./deployment/deploy.sh monitoring # Monitoring stack
|
||||
```
|
||||
|
||||
### What Gets Deployed
|
||||
|
||||
**Production Stack** (`docker-compose.production.yml`):
|
||||
- PostgreSQL 16
|
||||
- C++ DBAL daemon (Conan + CMake)
|
||||
- Next.js app (Node 18)
|
||||
- C++ Media daemon (FFmpeg, ImageMagick)
|
||||
- Redis 7
|
||||
- Nginx (SSL, caching)
|
||||
|
||||
**Monitoring Stack** (`docker-compose.monitoring.yml`):
|
||||
- Prometheus (metrics)
|
||||
- Grafana (dashboards)
|
||||
- Loki (logs)
|
||||
- Promtail (log collector)
|
||||
- Exporters (PostgreSQL, Redis, Node, Nginx)
|
||||
|
||||
### Bootstrap Process
|
||||
|
||||
The `bootstrap-system.sh` script runs in 7 phases:
|
||||
|
||||
1. **Wait for database** to be ready
|
||||
2. **Run Prisma migrations** (schema setup)
|
||||
3. **Check bootstrap status** (idempotent)
|
||||
4. **Seed database** from `/seed/database/*.yaml`
|
||||
5. **Install core packages** (12 packages in priority order)
|
||||
6. **Verify installation** (health checks)
|
||||
7. **Run post-hooks** (custom initialization)
|
||||
|
||||
### Core Packages Bootstrap Order
|
||||
|
||||
**Phase 1**: `package_manager` (required first)
|
||||
**Phase 2**: `ui_header`, `ui_footer`, `ui_home`, `ui_auth`, `ui_login`
|
||||
**Phase 3**: `dashboard`
|
||||
**Phase 4**: `user_manager`, `role_editor`
|
||||
**Phase 5**: `admin_dialog`, `database_manager`, `schema_editor`
|
||||
|
||||
See [seed/packages/core-packages.yaml](seed/packages/core-packages.yaml) for full configuration.
|
||||
|
||||
### Environment Variables
|
||||
|
||||
```env
|
||||
# Database
|
||||
POSTGRES_PASSWORD=changeme_prod_password
|
||||
DATABASE_URL=postgresql://metabuilder:password@postgres:5432/metabuilder
|
||||
|
||||
# DBAL
|
||||
DBAL_API_KEY=your_api_key_here
|
||||
|
||||
# Media Daemon
|
||||
ICECAST_PASSWORD=hackme
|
||||
REDIS_PASSWORD=changeme_redis_password
|
||||
```
|
||||
|
||||
### Docker Build Process
|
||||
|
||||
**C++ Components** (DBAL, Media daemon):
|
||||
- Multi-stage builds (builder + runtime)
|
||||
- Conan for dependency management
|
||||
- CMake + Ninja build system
|
||||
- Optimized production images (~200MB final)
|
||||
|
||||
**Next.js**:
|
||||
- Node 18 Alpine base
|
||||
- Production build with output standalone
|
||||
- Minimal runtime dependencies
|
||||
|
||||
---
|
||||
|
||||
## Database
|
||||
|
||||
### Schema Overview
|
||||
|
||||
**Core Tables**:
|
||||
- `User` - User accounts, permission levels
|
||||
- `Tenant` - Multi-tenant isolation
|
||||
- `InstalledPackage` - Installed packages, config
|
||||
- `PackagePermission` - Package access control
|
||||
- `PageConfig` - God panel route definitions
|
||||
- `Workflow` - Workflow definitions
|
||||
- `LuaScript` - Stored Lua scripts
|
||||
|
||||
### Example: Installed Package
|
||||
|
||||
```prisma
|
||||
model InstalledPackage {
|
||||
packageId String @id
|
||||
tenantId String?
|
||||
version String
|
||||
enabled Boolean
|
||||
config String @db.Text // JSON config
|
||||
installedAt BigInt?
|
||||
}
|
||||
```
|
||||
|
||||
**Seed data** ([seed/database/installed_packages.yaml:44-54](seed/database/installed_packages.yaml#L44-L54)):
|
||||
```yaml
|
||||
- packageId: ui_home
|
||||
config: |
|
||||
{
|
||||
"systemPackage": true,
|
||||
"defaultRoute": "/", # Maps root URL to this package
|
||||
"publicAccess": true # Level 0 permission
|
||||
}
|
||||
```
|
||||
|
||||
### DBAL (Database Abstraction Layer)
|
||||
|
||||
**Why?** Credentials never touch the frontend. All database operations go through the DBAL daemon.
|
||||
|
||||
**Architecture**:
|
||||
- **TypeScript SDK** (`dbal/development/`) - Development, fast iteration
|
||||
- **C++ Daemon** (`dbal/production/`) - Production, credential protection
|
||||
|
||||
**Usage**:
|
||||
```typescript
|
||||
import { getAdapter } from '@/lib/db/core/dbal-client'
|
||||
|
||||
const adapter = getAdapter()
|
||||
const result = await adapter.list('InstalledPackage', {
|
||||
filters: { enabled: true }
|
||||
})
|
||||
```
|
||||
|
||||
### Database Commands
|
||||
|
||||
```bash
|
||||
# Development (can be run from root or frontends/nextjs)
|
||||
npm run db:generate # Generate Prisma client
|
||||
npm run db:push # Apply schema changes
|
||||
npm run db:migrate # Create migration
|
||||
|
||||
# From root directory
|
||||
npm run db:generate # Delegates to frontends/nextjs
|
||||
|
||||
# From frontends/nextjs directory
|
||||
npm run db:generate # Uses --schema=../../prisma/schema.prisma
|
||||
|
||||
# Production (via Docker)
|
||||
docker exec -it metabuilder-postgres-prod psql -U metabuilder
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Development
|
||||
|
||||
### Prerequisites
|
||||
|
||||
```bash
|
||||
# Frontend (pastebin)
|
||||
cd frontends/pastebin && npm run dev
|
||||
# Install Node.js dependencies
|
||||
cd frontends/nextjs
|
||||
npm install
|
||||
|
||||
# DBAL logs
|
||||
docker logs -f metabuilder-dbal
|
||||
# Install C++ build tools (for DBAL/Media daemons)
|
||||
# Ubuntu/Debian:
|
||||
sudo apt install cmake ninja-build g++ libssl-dev libpq-dev
|
||||
|
||||
# Admin seed endpoint (force re-seed)
|
||||
curl -X POST http://localhost:8080/admin/seed \
|
||||
-H "Authorization: Bearer $DBAL_ADMIN_TOKEN" \
|
||||
-d '{"force": true}'
|
||||
# macOS:
|
||||
brew install cmake ninja conan
|
||||
```
|
||||
|
||||
# Search docs / reports
|
||||
cd txt && python3 reports.py search "topic"
|
||||
cd docs && python3 docs.py search "topic"
|
||||
### Development Workflow
|
||||
|
||||
```bash
|
||||
# Terminal 1: Frontend
|
||||
cd frontends/nextjs
|
||||
npm run dev
|
||||
|
||||
# Terminal 2: DBAL daemon (optional, TypeScript version)
|
||||
cd dbal/development
|
||||
npm install
|
||||
npm run dev
|
||||
|
||||
# Terminal 3: PostgreSQL (via Docker)
|
||||
docker run -p 5432:5432 -e POSTGRES_PASSWORD=dev postgres:16
|
||||
```
|
||||
|
||||
### Code Conventions
|
||||
|
||||
**CRITICAL RULES**:
|
||||
- ❌ **NO hardcoded routes** - use PageConfig
|
||||
- ❌ **NO component imports from packages** - use generic renderer
|
||||
- ❌ **NO direct database access** - use DBAL adapter
|
||||
- ✅ **Material-UI only** for UI components
|
||||
- ✅ **Absolute imports** with `@/` path
|
||||
- ✅ **One lambda per file** pattern
|
||||
|
||||
### Testing
|
||||
|
||||
```bash
|
||||
# From frontends/nextjs/
|
||||
npm run test:unit # Vitest unit tests
|
||||
npm run test:unit -- --run # Run once (no watch)
|
||||
npm run test:e2e # Playwright E2E tests
|
||||
npm run lint # ESLint
|
||||
npm run typecheck # TypeScript validation
|
||||
npm run build # Production build
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Schema-First Development
|
||||
## Project Structure
|
||||
|
||||
Entity schemas live in `dbal/shared/api/schema/entities/` as JSON.
|
||||
They are the **single source of truth** — consumed by:
|
||||
- C++ DBAL daemon (table creation, CRUD validation)
|
||||
- `gen_types.py` (TypeScript + C++ type generation)
|
||||
- Seed loader (entity-aware bulk insert)
|
||||
- Workflow engine (entity creation steps)
|
||||
|
||||
```bash
|
||||
# Regenerate types after schema changes
|
||||
python3 dbal/shared/tools/codegen/gen_types.py
|
||||
```
|
||||
metabuilder/
|
||||
├── frontends/nextjs/ # Next.js 14 App Router frontend
|
||||
│ ├── src/
|
||||
│ │ ├── app/ # App routes (minimal, generic)
|
||||
│ │ │ └── page.tsx # Root route (database-driven)
|
||||
│ │ ├── components/ # Generic renderers only
|
||||
│ │ ├── lib/
|
||||
│ │ │ ├── db/ # DBAL client
|
||||
│ │ │ ├── packages/ # Package loaders
|
||||
│ │ │ └── rendering/ # JSON→React renderer
|
||||
│ │ └── hooks/
|
||||
│ └── package.json
|
||||
│
|
||||
├── packages/ # Self-contained packages (JSON)
|
||||
│ ├── ui_home/
|
||||
│ │ ├── package.json
|
||||
│ │ ├── components/ui.json
|
||||
│ │ └── styles/
|
||||
│ ├── ui_header/
|
||||
│ ├── dashboard/
|
||||
│ └── ... (12+ packages)
|
||||
│
|
||||
├── seed/ # Bootstrap data
|
||||
│ ├── packages/
|
||||
│ │ └── core-packages.yaml
|
||||
│ └── database/
|
||||
│ ├── installed_packages.yaml
|
||||
│ └── package_permissions.yaml
|
||||
│
|
||||
├── dbal/ # Database Abstraction Layer
|
||||
│ ├── development/ # TypeScript (dev)
|
||||
│ └── production/ # C++ daemon (prod)
|
||||
│ ├── src/
|
||||
│ ├── include/
|
||||
│ └── build-config/
|
||||
│
|
||||
├── services/
|
||||
│ └── media_daemon/ # C++ media processing (FFmpeg, HLS)
|
||||
│ ├── src/
|
||||
│ ├── include/
|
||||
│ └── Dockerfile
|
||||
│
|
||||
├── deployment/ # Docker deployment
|
||||
│ ├── docker/
|
||||
│ │ ├── docker-compose.production.yml
|
||||
│ │ ├── docker-compose.development.yml
|
||||
│ │ └── docker-compose.monitoring.yml
|
||||
│ ├── scripts/
|
||||
│ │ ├── deploy.sh
|
||||
│ │ ├── bootstrap-system.sh
|
||||
│ │ └── backup-database.sh
|
||||
│ └── config/ # Service configs (Nginx, Prometheus, etc.)
|
||||
│
|
||||
├── prisma/
|
||||
│ └── schema.prisma # Database schema
|
||||
│
|
||||
└── docs/ # Documentation
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Last Updated**: 2026-03-04
|
||||
## Key Concepts Recap
|
||||
|
||||
### 1. Ultra-Generic Routing
|
||||
|
||||
**Traditional**:
|
||||
```typescript
|
||||
// Hardcoded route mapping
|
||||
<Route path="/" component={HomePage} />
|
||||
<Route path="/dashboard" component={Dashboard} />
|
||||
```
|
||||
|
||||
**MetaBuilder**:
|
||||
```typescript
|
||||
// Database-driven routing
|
||||
const route = await db.query('PageConfig', { path: req.url })
|
||||
const pkg = await loadPackage(route.packageId)
|
||||
const component = pkg.components.find(c => c.id === route.component)
|
||||
return renderJSONComponent(component)
|
||||
```
|
||||
|
||||
### 2. Zero Hardcoded Imports
|
||||
|
||||
**Traditional**:
|
||||
```typescript
|
||||
import HomePage from '@/components/HomePage'
|
||||
import Dashboard from '@/components/Dashboard'
|
||||
```
|
||||
|
||||
**MetaBuilder**:
|
||||
```typescript
|
||||
// All components loaded from JSON
|
||||
const pkg = await loadJSONPackage('/packages/ui_home')
|
||||
const component = pkg.components.find(c => c.name === 'HomePage')
|
||||
```
|
||||
|
||||
### 3. God Panel Control
|
||||
|
||||
Supergod users can **remap the entire application** without touching code:
|
||||
|
||||
```sql
|
||||
-- Remap root page
|
||||
UPDATE "InstalledPackage"
|
||||
SET config = '{"defaultRoute": "/"}'
|
||||
WHERE "packageId" = 'dashboard';
|
||||
|
||||
-- Override with god panel
|
||||
INSERT INTO "PageConfig" (path, packageId, component, ...)
|
||||
VALUES ('/', 'custom_package', 'CustomPage', ...);
|
||||
```
|
||||
|
||||
### 4. Complete Loose Coupling
|
||||
|
||||
```
|
||||
Database (Source of Truth)
|
||||
↓
|
||||
JSON Packages (Data)
|
||||
↓
|
||||
Generic Renderer (Engine)
|
||||
↓
|
||||
React (Output)
|
||||
```
|
||||
|
||||
**No layer knows about the layers above or below.**
|
||||
|
||||
---
|
||||
|
||||
## Trade-offs
|
||||
|
||||
### Pros
|
||||
✅ Infinite flexibility - remap anything via database
|
||||
✅ Zero coupling - no hardcoded dependencies
|
||||
✅ God users control everything - no code deploys needed
|
||||
✅ Package isolation - packages don't know about each other
|
||||
✅ Multi-tenant ready - tenant-specific route overrides
|
||||
|
||||
### Cons
|
||||
❌ Steep learning curve - "where does this render?"
|
||||
❌ Harder debugging - trace through database → JSON → renderer
|
||||
❌ Performance overhead - runtime JSON parsing
|
||||
❌ Type safety loss - JSON components aren't type-checked
|
||||
❌ Tooling challenges - no IDE autocomplete for package components
|
||||
|
||||
**The trade-off is flexibility vs. simplicity.**
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
| Problem | Solution |
|
||||
|---------|----------|
|
||||
| "Page not found" at `/` | Check `InstalledPackage` has `defaultRoute: "/"` config |
|
||||
| Package not rendering | Verify package installed: `SELECT * FROM "InstalledPackage"` |
|
||||
| Permission denied | Check `PackagePermission` table for correct role |
|
||||
| Database connection failed | Check `DATABASE_URL` env var, run `npm run db:push` |
|
||||
| DBAL daemon won't start | Check PostgreSQL is running, credentials correct |
|
||||
|
||||
### Debug Steps
|
||||
|
||||
```bash
|
||||
# 1. Check database
|
||||
docker exec -it metabuilder-postgres-prod psql -U metabuilder -c "SELECT * FROM \"InstalledPackage\" WHERE \"packageId\" = 'ui_home';"
|
||||
|
||||
# 2. Check package files exist
|
||||
ls -la packages/ui_home/components/
|
||||
|
||||
# 3. Check bootstrap logs
|
||||
docker logs metabuilder-app-prod | grep bootstrap
|
||||
|
||||
# 4. View all routes
|
||||
curl http://localhost:8080/api/list?entity=PageConfig
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## License
|
||||
|
||||
MIT License - See LICENSE file
|
||||
|
||||
---
|
||||
|
||||
## Learn More
|
||||
|
||||
- [Deployment Guide](deployment/DEPLOYMENT_GUIDE.md) - Detailed deployment documentation
|
||||
- [Package Structure](packages/README.md) - How to create packages
|
||||
- [DBAL Documentation](dbal/docs/) - Database abstraction layer
|
||||
- [Prisma Schema](prisma/schema.prisma) - Database schema reference
|
||||
|
||||
---
|
||||
|
||||
**Built with the philosophy: Everything is data, nothing is hardcoded.**
|
||||
|
||||
2957
ROADMAP.md
2957
ROADMAP.md
File diff suppressed because it is too large
Load Diff
@@ -1 +0,0 @@
|
||||
---
|
||||
File diff suppressed because one or more lines are too long
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"status": "failed",
|
||||
"failedTests": [
|
||||
"292e21d96a3a4afcf952-9e6b717b184f6f31cb56"
|
||||
]
|
||||
}
|
||||
@@ -1,159 +0,0 @@
|
||||
# Page snapshot
|
||||
|
||||
```yaml
|
||||
- generic [ref=e1]:
|
||||
- generic [ref=e2]:
|
||||
- banner [ref=e3]:
|
||||
- generic [ref=e4]:
|
||||
- button "Toggle sidebar" [ref=e5] [cursor=pointer]:
|
||||
- img [ref=e6]
|
||||
- generic [ref=e7]:
|
||||
- img [ref=e8]
|
||||
- heading "WorkflowUI" [level=1] [ref=e17]
|
||||
- generic [ref=e18]:
|
||||
- button "Notifications" [ref=e20] [cursor=pointer]:
|
||||
- img [ref=e21]
|
||||
- generic [ref=e23]: "2"
|
||||
- button "Switch to dark mode" [ref=e24] [cursor=pointer]:
|
||||
- img [ref=e25]
|
||||
- generic [ref=e27]:
|
||||
- complementary "Workflows sidebar" [ref=e28]:
|
||||
- navigation [ref=e29]:
|
||||
- generic [ref=e30]:
|
||||
- heading "Main" [level=3] [ref=e31]
|
||||
- list "Main navigation" [ref=e32]:
|
||||
- listitem [ref=e33]:
|
||||
- link "Dashboard" [ref=e34] [cursor=pointer]:
|
||||
- /url: /
|
||||
- img [ref=e36]
|
||||
- generic [ref=e38]: Dashboard
|
||||
- listitem [ref=e39]:
|
||||
- link "Notifications 2" [ref=e40] [cursor=pointer]:
|
||||
- /url: /notifications
|
||||
- img [ref=e42]
|
||||
- generic [ref=e44]: Notifications
|
||||
- generic [ref=e45]: "2"
|
||||
- generic [ref=e46]:
|
||||
- heading "Workflows" [level=3] [ref=e47]
|
||||
- list "Workflows navigation" [ref=e48]:
|
||||
- listitem [ref=e49]:
|
||||
- link "All Workflows" [active] [ref=e50] [cursor=pointer]:
|
||||
- /url: /workflows
|
||||
- img [ref=e52]
|
||||
- generic [ref=e54]: All Workflows
|
||||
- listitem [ref=e55]:
|
||||
- link "Recent" [ref=e56] [cursor=pointer]:
|
||||
- /url: /workflows/recent
|
||||
- img [ref=e58]
|
||||
- generic [ref=e60]: Recent
|
||||
- listitem [ref=e61]:
|
||||
- link "Favorites" [ref=e62] [cursor=pointer]:
|
||||
- /url: /workflows/favorites
|
||||
- img [ref=e64]
|
||||
- generic [ref=e66]: Favorites
|
||||
- listitem [ref=e67]:
|
||||
- link "Templates" [ref=e68] [cursor=pointer]:
|
||||
- /url: /templates
|
||||
- img [ref=e70]
|
||||
- generic [ref=e72]: Templates
|
||||
- generic [ref=e73]:
|
||||
- heading "System" [level=3] [ref=e74]
|
||||
- list "System navigation" [ref=e75]:
|
||||
- listitem [ref=e76]:
|
||||
- link "Plugins" [ref=e77] [cursor=pointer]:
|
||||
- /url: /plugins
|
||||
- img [ref=e79]
|
||||
- generic [ref=e81]: Plugins
|
||||
- listitem [ref=e82]:
|
||||
- link "Settings" [ref=e83] [cursor=pointer]:
|
||||
- /url: /settings
|
||||
- img [ref=e85]
|
||||
- generic [ref=e87]: Settings
|
||||
- generic [ref=e88]:
|
||||
- heading "Help" [level=3] [ref=e89]
|
||||
- list "Help navigation" [ref=e90]:
|
||||
- listitem [ref=e91]:
|
||||
- link "Documentation" [ref=e92] [cursor=pointer]:
|
||||
- /url: /docs
|
||||
- img [ref=e94]
|
||||
- generic [ref=e96]: Documentation
|
||||
- listitem [ref=e97]:
|
||||
- link "Help & Support" [ref=e98] [cursor=pointer]:
|
||||
- /url: /help
|
||||
- img [ref=e100]
|
||||
- generic [ref=e102]: Help & Support
|
||||
- button "+ New Workflow" [ref=e104] [cursor=pointer]:
|
||||
- generic [ref=e106]: + New Workflow
|
||||
- main [ref=e107]:
|
||||
- generic [ref=e108]:
|
||||
- generic [ref=e109]:
|
||||
- generic [ref=e110]:
|
||||
- img [ref=e112]
|
||||
- generic [ref=e114]:
|
||||
- generic [ref=e115]: "23"
|
||||
- generic [ref=e116]: nodes today
|
||||
- generic [ref=e117]:
|
||||
- img [ref=e119]
|
||||
- generic [ref=e121]:
|
||||
- generic [ref=e122]: "5"
|
||||
- generic [ref=e123]: runs today
|
||||
- generic [ref=e124]:
|
||||
- img [ref=e126]
|
||||
- generic [ref=e128]:
|
||||
- generic [ref=e129]: "1"
|
||||
- generic [ref=e130]: failed
|
||||
- generic [ref=e131]:
|
||||
- img [ref=e133]
|
||||
- generic [ref=e135]:
|
||||
- generic [ref=e136]: 1.2h
|
||||
- generic [ref=e137]: saved today
|
||||
- generic [ref=e139]:
|
||||
- generic "First Steps" [ref=e140]:
|
||||
- img [ref=e141]
|
||||
- generic "Node Master" [ref=e143]:
|
||||
- img [ref=e144]
|
||||
- link "+4 more" [ref=e146] [cursor=pointer]:
|
||||
- /url: /achievements
|
||||
- generic [ref=e147]:
|
||||
- generic [ref=e148]:
|
||||
- heading "Workspaces" [level=1] [ref=e149]
|
||||
- paragraph [ref=e150]: Organize your projects and workflows
|
||||
- button "New Workspace" [ref=e151] [cursor=pointer]:
|
||||
- img [ref=e154]
|
||||
- generic [ref=e156]: New Workspace
|
||||
- generic [ref=e157]:
|
||||
- img [ref=e159]
|
||||
- heading "No workspaces yet" [level=2] [ref=e161]
|
||||
- paragraph [ref=e162]: Create your first workspace to organize your projects
|
||||
- button "Create Your First Workspace" [ref=e163] [cursor=pointer]:
|
||||
- img [ref=e166]
|
||||
- generic [ref=e168]: Create Your First Workspace
|
||||
- generic [ref=e173] [cursor=pointer]:
|
||||
- button "Open Next.js Dev Tools" [ref=e174]:
|
||||
- img [ref=e175]
|
||||
- generic [ref=e178]:
|
||||
- button "Open issues overlay" [ref=e179]:
|
||||
- generic [ref=e180]:
|
||||
- generic [ref=e181]: "0"
|
||||
- generic [ref=e182]: "1"
|
||||
- generic [ref=e183]: Issue
|
||||
- button "Collapse issues badge" [ref=e184]:
|
||||
- img [ref=e185]
|
||||
- alert [ref=e187]
|
||||
- generic "Notifications" [ref=e188]:
|
||||
- alert [ref=e189]:
|
||||
- text: ✕Unexpected token '<', "<html> <he"... is not valid JSON
|
||||
- button "Close notification" [ref=e190] [cursor=pointer]: ×
|
||||
- alert [ref=e191]:
|
||||
- text: ✕Unexpected token '<', "<html> <he"... is not valid JSON
|
||||
- button "Close notification" [ref=e192] [cursor=pointer]: ×
|
||||
- alert [ref=e193]:
|
||||
- text: ✕Unexpected token '<', "<html> <he"... is not valid JSON
|
||||
- button "Close notification" [ref=e194] [cursor=pointer]: ×
|
||||
- alert [ref=e195]:
|
||||
- text: ✕Unexpected token '<', "<html> <he"... is not valid JSON
|
||||
- button "Close notification" [ref=e196] [cursor=pointer]: ×
|
||||
- alert [ref=e197]:
|
||||
- text: ✕Unexpected token '<', "<html> <he"... is not valid JSON
|
||||
- button "Close notification" [ref=e198] [cursor=pointer]: ×
|
||||
```
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 87 KiB |
@@ -1 +0,0 @@
|
||||
./gameengine
|
||||
@@ -1,38 +0,0 @@
|
||||
/**
|
||||
* ProjectCard Component
|
||||
* Displays project with metadata
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import Link from 'next/link'
|
||||
import type { Project } from '@metabuilder/interfaces/workspace'
|
||||
import styles from '../../scss/components/cards/project-card.module.scss'
|
||||
|
||||
interface ProjectCardProps {
|
||||
project: Project
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
/**
|
||||
* ProjectCard - Clickable project card with link
|
||||
*/
|
||||
export const ProjectCard = ({ project, ...rest }: ProjectCardProps) => {
|
||||
return (
|
||||
<Link href={`/project/${project.id}`} className={styles.projectCard} {...rest}>
|
||||
<div className={styles.cardInner}>
|
||||
<div
|
||||
className={styles.media}
|
||||
style={{ backgroundColor: project.color || 'var(--mat-sys-primary)' }}
|
||||
/>
|
||||
<div className={styles.content}>
|
||||
<h3 className={styles.title}>{project.name}</h3>
|
||||
<p className={styles.description}>{project.description || 'No description'}</p>
|
||||
<div className={styles.meta}>
|
||||
<span>{project.workflowCount || 0} workflows</span>
|
||||
<span>Updated {new Date(project.updatedAt).toLocaleDateString()}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
/**
|
||||
* ProjectList Component
|
||||
* Grid layout for project cards
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import { ProjectCard } from './ProjectCard'
|
||||
import type { Project } from '@metabuilder/interfaces/workspace'
|
||||
|
||||
interface ProjectListProps {
|
||||
projects: Project[]
|
||||
className?: string
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
/**
|
||||
* ProjectList - Grid container for projects
|
||||
*/
|
||||
export const ProjectList = ({ projects, className, ...rest }: ProjectListProps) => {
|
||||
const gridClass = className || 'grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6'
|
||||
|
||||
return (
|
||||
<div className={gridClass} {...rest}>
|
||||
{projects.map((project) => (
|
||||
<ProjectCard key={project.id} project={project} />
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
/**
|
||||
* StatCard Component
|
||||
* Individual stat card with icon and value
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import { StatIcon } from './StatIcon'
|
||||
import { StatValue } from './StatValue'
|
||||
import type { StatItem } from '@metabuilder/interfaces/dashboard'
|
||||
import styles from '../../scss/components/cards/stat-card.module.scss'
|
||||
|
||||
interface StatCardProps {
|
||||
stat: StatItem
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
/**
|
||||
* StatCard - Composed stat display (icon + value)
|
||||
*/
|
||||
export const StatCard = ({ stat, ...rest }: StatCardProps) => {
|
||||
const className = stat.warning ? `${styles.statCard} ${styles.warning}` : styles.statCard
|
||||
|
||||
return (
|
||||
<div className={className} {...rest}>
|
||||
<StatIcon icon={stat.icon} color={stat.color} />
|
||||
<StatValue value={stat.value} label={stat.label} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
/**
|
||||
* StatIcon Component
|
||||
* Icon wrapper for stat cards
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import styles from '../../scss/components/cards/stat-icon.module.scss'
|
||||
|
||||
interface StatIconProps {
|
||||
icon: React.ReactNode
|
||||
color?: string
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
/**
|
||||
* StatIcon - Displays an icon with styled background
|
||||
*/
|
||||
export const StatIcon = ({ icon, color, ...rest }: StatIconProps) => {
|
||||
return (
|
||||
<div className={styles.statIcon} style={color ? { color } : undefined} {...rest}>
|
||||
{icon}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
/**
|
||||
* StatValue Component
|
||||
* Value and label display for stats
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import styles from '../../scss/components/cards/stat-value.module.scss'
|
||||
|
||||
interface StatValueProps {
|
||||
value: string | number
|
||||
label: string
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
/**
|
||||
* StatValue - Displays stat value with label
|
||||
*/
|
||||
export const StatValue = ({ value, label, ...rest }: StatValueProps) => {
|
||||
return (
|
||||
<div className={styles.statValue} {...rest}>
|
||||
<span className={styles.value}>{value}</span>
|
||||
<span className={styles.label}>{label}</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
// components/cards/TemplateCard.tsx
|
||||
|
||||
import React from 'react'
|
||||
import Link from 'next/link'
|
||||
import { Card, CardContent, CardActions, Button, Box, Typography } from '../fakemui'
|
||||
import { TemplateIcon } from './TemplateIcon'
|
||||
import { TemplateDifficultyBadge } from '../feedback/TemplateDifficultyBadge'
|
||||
import { TemplateRating } from '../feedback/TemplateRating'
|
||||
import { Template } from '@metabuilder/interfaces/templates'
|
||||
import styles from '../../scss/components/cards/template-card.module.scss'
|
||||
|
||||
interface TemplateCardProps {
|
||||
template: Template
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
/**
|
||||
* Template card component - Grid view
|
||||
* Displays template summary with icon, metadata, and actions
|
||||
*/
|
||||
export const TemplateCard = ({ template, ...rest }: TemplateCardProps) => {
|
||||
return (
|
||||
<Card
|
||||
className={styles.templateCard}
|
||||
data-testid={`template-card-${template.id}`}
|
||||
role="listitem"
|
||||
{...rest}
|
||||
>
|
||||
{template.metadata.featured && (
|
||||
<Box className={styles.featuredBadge} aria-label="Featured">
|
||||
⭐ Featured
|
||||
</Box>
|
||||
)}
|
||||
|
||||
<TemplateIcon
|
||||
icon={template.icon}
|
||||
color={template.color}
|
||||
size="large"
|
||||
/>
|
||||
|
||||
<CardContent className={styles.content}>
|
||||
<Typography variant="h6" className={styles.title}>
|
||||
{template.name}
|
||||
</Typography>
|
||||
|
||||
<Typography variant="body2" className={styles.description}>
|
||||
{template.description}
|
||||
</Typography>
|
||||
|
||||
<Box className={styles.metadata}>
|
||||
<TemplateDifficultyBadge difficulty={template.difficulty} />
|
||||
<Box className={styles.metaItem}>
|
||||
{template.workflows.length} workflow{template.workflows.length !== 1 ? 's' : ''}
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
<Box className={styles.stats}>
|
||||
<TemplateRating rating={template.metadata.rating} />
|
||||
<Box className={styles.downloads}>
|
||||
⬇️ {template.metadata.downloads?.toLocaleString() || 0}
|
||||
</Box>
|
||||
</Box>
|
||||
</CardContent>
|
||||
|
||||
<CardActions>
|
||||
<Button
|
||||
component={Link}
|
||||
href={`/templates/${template.id}`}
|
||||
variant="contained"
|
||||
fullWidth
|
||||
>
|
||||
View Template
|
||||
</Button>
|
||||
</CardActions>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
// components/cards/TemplateIcon.tsx
|
||||
|
||||
import React from 'react'
|
||||
import { Box } from '../fakemui'
|
||||
import styles from '../../scss/components/cards/template-icon.module.scss'
|
||||
|
||||
interface TemplateIconProps {
|
||||
icon: string
|
||||
color: string
|
||||
size?: 'small' | 'medium' | 'large'
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
/**
|
||||
* Template icon component
|
||||
* Displays template icon with background color
|
||||
*/
|
||||
export const TemplateIcon = ({
|
||||
icon,
|
||||
color,
|
||||
size = 'medium',
|
||||
...rest
|
||||
}: TemplateIconProps) => {
|
||||
const sizeClass = size === 'large' ? styles.large : size === 'small' ? styles.small : ''
|
||||
|
||||
return (
|
||||
<Box
|
||||
className={`${styles.templateIcon} ${sizeClass}`}
|
||||
style={{ backgroundColor: color }}
|
||||
{...rest}
|
||||
>
|
||||
{icon}
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
// components/cards/TemplateListItem.tsx
|
||||
|
||||
import React from 'react'
|
||||
import Link from 'next/link'
|
||||
import { Box, Typography, Button } from '../fakemui'
|
||||
import { TemplateIcon } from './TemplateIcon'
|
||||
import { Template } from '@metabuilder/interfaces/templates'
|
||||
import styles from '../../scss/components/cards/template-list-item.module.scss'
|
||||
|
||||
interface TemplateListItemProps {
|
||||
template: Template
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
/**
|
||||
* Template list item component - List view
|
||||
* Compact horizontal layout with tags
|
||||
*/
|
||||
export const TemplateListItem = ({ template, ...rest }: TemplateListItemProps) => {
|
||||
const visibleTags = template.tags.slice(0, 3)
|
||||
const remainingCount = template.tags.length - 3
|
||||
|
||||
return (
|
||||
<Box
|
||||
className={styles.templateListItem}
|
||||
data-testid={`template-list-item-${template.id}`}
|
||||
role="listitem"
|
||||
{...rest}
|
||||
>
|
||||
<TemplateIcon
|
||||
icon={template.icon}
|
||||
color={template.color}
|
||||
size="small"
|
||||
/>
|
||||
|
||||
<Box className={styles.content}>
|
||||
<Box className={styles.header}>
|
||||
<Typography variant="h6" className={styles.title}>
|
||||
{template.name}
|
||||
</Typography>
|
||||
{template.metadata.featured && (
|
||||
<Box className={styles.featuredBadge}>⭐ Featured</Box>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
<Typography variant="body2" className={styles.description}>
|
||||
{template.description}
|
||||
</Typography>
|
||||
|
||||
<Box className={styles.tags}>
|
||||
{visibleTags.map((tag) => (
|
||||
<Box key={tag} className={styles.tag}>
|
||||
{tag}
|
||||
</Box>
|
||||
))}
|
||||
{remainingCount > 0 && (
|
||||
<Box className={styles.tag}>+{remainingCount}</Box>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
<Box className={styles.actions}>
|
||||
<Button
|
||||
component={Link}
|
||||
href={`/templates/${template.id}`}
|
||||
variant="outlined"
|
||||
>
|
||||
View
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/**
|
||||
* WorkspaceCard Component
|
||||
* Complete workspace card with icon and content
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import { WorkspaceIcon } from './WorkspaceIcon'
|
||||
import { WorkspaceTitle } from './WorkspaceTitle'
|
||||
import type { Workspace } from '@metabuilder/interfaces/dashboard'
|
||||
import styles from '../../scss/components/cards/workspace-card.module.scss'
|
||||
|
||||
interface WorkspaceCardProps {
|
||||
workspace: Workspace
|
||||
onClick?: () => void
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
/**
|
||||
* WorkspaceCard - Interactive workspace card
|
||||
*/
|
||||
export const WorkspaceCard = ({ workspace, onClick, ...rest }: WorkspaceCardProps) => {
|
||||
return (
|
||||
<article
|
||||
className={styles.workspaceCard}
|
||||
onClick={onClick}
|
||||
onKeyDown={(e) => e.key === 'Enter' && onClick?.()}
|
||||
tabIndex={0}
|
||||
role="button"
|
||||
aria-label={`Open ${workspace.name} workspace`}
|
||||
data-testid="workspace-card"
|
||||
{...rest}
|
||||
>
|
||||
<WorkspaceIcon name={workspace.name} color={workspace.color} />
|
||||
<WorkspaceTitle
|
||||
name={workspace.name}
|
||||
description={workspace.description}
|
||||
createdAt={workspace.createdAt}
|
||||
/>
|
||||
</article>
|
||||
)
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
/**
|
||||
* WorkspaceIcon Component
|
||||
* Displays workspace initials/icon
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import styles from '../../scss/components/cards/workspace-card.module.scss'
|
||||
|
||||
interface WorkspaceIconProps {
|
||||
name: string
|
||||
color?: string
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
/**
|
||||
* WorkspaceIcon - Workspace initials in colored media area
|
||||
*/
|
||||
export const WorkspaceIcon = ({ name, color, ...rest }: WorkspaceIconProps) => {
|
||||
const initials = name
|
||||
.split(' ')
|
||||
.map((w) => w[0])
|
||||
.join('')
|
||||
.slice(0, 2)
|
||||
.toUpperCase()
|
||||
|
||||
return (
|
||||
<div
|
||||
className={styles.media}
|
||||
style={{ backgroundColor: color || 'var(--mat-sys-primary)' }}
|
||||
{...rest}
|
||||
>
|
||||
<span className={styles.initials}>{initials}</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
/**
|
||||
* WorkspaceTitle Component
|
||||
* Displays workspace name, description, and metadata
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import styles from '../../scss/components/cards/workspace-card.module.scss'
|
||||
|
||||
interface WorkspaceTitleProps {
|
||||
name: string
|
||||
description?: string
|
||||
createdAt?: string
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
/**
|
||||
* WorkspaceTitle - Workspace text content
|
||||
*/
|
||||
export const WorkspaceTitle = ({ name, description, createdAt, ...rest }: WorkspaceTitleProps) => {
|
||||
return (
|
||||
<div className={styles.content} {...rest}>
|
||||
<h3 className={styles.title}>{name}</h3>
|
||||
<p className={styles.description}>{description || 'No description'}</p>
|
||||
{createdAt && (
|
||||
<span className={styles.meta}>
|
||||
Created {new Date(createdAt).toLocaleDateString()}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
export { ProjectCard } from './ProjectCard';
|
||||
export { ProjectList } from './ProjectList';
|
||||
export { StatCard } from './StatCard';
|
||||
export { StatIcon } from './StatIcon';
|
||||
export { StatValue } from './StatValue';
|
||||
export { TemplateCard } from './TemplateCard';
|
||||
export { TemplateIcon } from './TemplateIcon';
|
||||
export { TemplateListItem } from './TemplateListItem';
|
||||
export { WorkspaceCard } from './WorkspaceCard';
|
||||
export { WorkspaceIcon } from './WorkspaceIcon';
|
||||
export { WorkspaceTitle } from './WorkspaceTitle';
|
||||
@@ -1,192 +0,0 @@
|
||||
import React from 'react'
|
||||
import classNames from 'classnames'
|
||||
import styles from '../../../scss/atoms/label.module.scss'
|
||||
|
||||
// Size variants
|
||||
export type LabelSize = 'sm' | 'md' | 'lg'
|
||||
|
||||
// Color variants
|
||||
export type LabelColor =
|
||||
| 'primary'
|
||||
| 'secondary'
|
||||
| 'error'
|
||||
| 'success'
|
||||
| 'warning'
|
||||
| 'info'
|
||||
| 'onSurface'
|
||||
|
||||
export interface LabelProps extends React.HTMLAttributes<HTMLSpanElement> {
|
||||
children?: React.ReactNode
|
||||
/** Size variant: sm (small), md (medium/default), lg (large) */
|
||||
size?: LabelSize
|
||||
/** Color variant */
|
||||
color?: LabelColor
|
||||
/** Transform text to uppercase */
|
||||
uppercase?: boolean
|
||||
/** Show required asterisk indicator */
|
||||
required?: boolean
|
||||
/** Enable inline-flex layout for icon alignment */
|
||||
withIcon?: boolean
|
||||
/** Associate label with form element */
|
||||
htmlFor?: string
|
||||
/** Test ID for automated testing */
|
||||
testId?: string
|
||||
}
|
||||
|
||||
const sizeClassMap: Record<LabelSize, string | undefined> = {
|
||||
sm: styles.labelSm,
|
||||
md: undefined, // default, no extra class needed
|
||||
lg: styles.labelLg,
|
||||
}
|
||||
|
||||
const colorClassMap: Record<LabelColor, string> = {
|
||||
primary: styles.labelPrimary,
|
||||
secondary: styles.labelSecondary,
|
||||
error: styles.labelError,
|
||||
success: styles.labelSuccess,
|
||||
warning: styles.labelWarning,
|
||||
info: styles.labelInfo,
|
||||
onSurface: styles.labelOnSurface,
|
||||
}
|
||||
|
||||
export const Label: React.FC<LabelProps> = ({
|
||||
children,
|
||||
className,
|
||||
size = 'md',
|
||||
color,
|
||||
uppercase = false,
|
||||
required = false,
|
||||
withIcon = false,
|
||||
testId,
|
||||
...props
|
||||
}) => {
|
||||
const labelClassName = classNames(
|
||||
styles.label,
|
||||
sizeClassMap[size],
|
||||
color && colorClassMap[color],
|
||||
{
|
||||
[styles.labelUppercase]: uppercase,
|
||||
[styles.labelRequired]: required,
|
||||
[styles.labelWithIcon]: withIcon,
|
||||
},
|
||||
className
|
||||
)
|
||||
|
||||
return (
|
||||
<span className={labelClassName} data-testid={testId} {...props}>
|
||||
{children}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// FieldLabel - Form field label component
|
||||
// ============================================================================
|
||||
|
||||
export interface FieldLabelProps extends React.LabelHTMLAttributes<HTMLLabelElement> {
|
||||
children?: React.ReactNode
|
||||
/** Show error styling */
|
||||
error?: boolean
|
||||
/** Show focused styling */
|
||||
focused?: boolean
|
||||
/** Show required asterisk indicator */
|
||||
required?: boolean
|
||||
}
|
||||
|
||||
export const FieldLabel: React.FC<FieldLabelProps> = ({
|
||||
children,
|
||||
className,
|
||||
error = false,
|
||||
focused = false,
|
||||
required = false,
|
||||
...props
|
||||
}) => {
|
||||
const labelClassName = classNames(
|
||||
styles.fieldLabel,
|
||||
{
|
||||
[styles.fieldLabelError]: error,
|
||||
[styles.fieldLabelFocused]: focused && !error,
|
||||
[styles.labelRequired]: required,
|
||||
},
|
||||
className
|
||||
)
|
||||
|
||||
return (
|
||||
<label className={labelClassName} {...props}>
|
||||
{children}
|
||||
</label>
|
||||
)
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// HelperText - Helper text below form fields
|
||||
// ============================================================================
|
||||
|
||||
export interface HelperTextProps extends React.HTMLAttributes<HTMLSpanElement> {
|
||||
children?: React.ReactNode
|
||||
/** Show error styling */
|
||||
error?: boolean
|
||||
}
|
||||
|
||||
export const HelperText: React.FC<HelperTextProps> = ({
|
||||
children,
|
||||
className,
|
||||
error = false,
|
||||
...props
|
||||
}) => {
|
||||
const helperClassName = classNames(
|
||||
styles.helperText,
|
||||
{
|
||||
[styles.helperTextError]: error,
|
||||
},
|
||||
className
|
||||
)
|
||||
|
||||
return (
|
||||
<span className={helperClassName} {...props}>
|
||||
{children}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// CounterText - Character counter text
|
||||
// ============================================================================
|
||||
|
||||
export interface CounterTextProps extends React.HTMLAttributes<HTMLSpanElement> {
|
||||
children?: React.ReactNode
|
||||
/** Current character count */
|
||||
count?: number
|
||||
/** Maximum character limit */
|
||||
maxLength?: number
|
||||
/** Show error styling (typically when count > maxLength) */
|
||||
error?: boolean
|
||||
}
|
||||
|
||||
export const CounterText: React.FC<CounterTextProps> = ({
|
||||
children,
|
||||
className,
|
||||
count,
|
||||
maxLength,
|
||||
error = false,
|
||||
...props
|
||||
}) => {
|
||||
const counterClassName = classNames(
|
||||
styles.counterText,
|
||||
{
|
||||
[styles.counterTextError]: error || (count !== undefined && maxLength !== undefined && count > maxLength),
|
||||
},
|
||||
className
|
||||
)
|
||||
|
||||
// If count and maxLength provided, render formatted counter
|
||||
const content = count !== undefined && maxLength !== undefined
|
||||
? `${count}/${maxLength}`
|
||||
: children
|
||||
|
||||
return (
|
||||
<span className={counterClassName} {...props}>
|
||||
{content}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
@@ -1,206 +0,0 @@
|
||||
import React from 'react'
|
||||
import classNames from 'classnames'
|
||||
import styles from '../../../scss/atoms/panel.module.scss'
|
||||
|
||||
// ============================================================================
|
||||
// Panel Component - Material Design 3
|
||||
// ============================================================================
|
||||
|
||||
export type PanelVariant = 'default' | 'elevated' | 'outlined'
|
||||
export type PanelFixedPosition = 'br' | 'bl' | 'tr' | 'tl'
|
||||
export type PanelHeaderVariant = 'primary' | 'secondary' | 'tertiary' | 'surface'
|
||||
|
||||
export interface PanelProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
children?: React.ReactNode
|
||||
/** Panel visual style */
|
||||
variant?: PanelVariant
|
||||
/** Fixed position on screen */
|
||||
fixedPosition?: PanelFixedPosition
|
||||
/** Enable collapsible behavior */
|
||||
collapsible?: boolean
|
||||
/** Collapsed state (requires collapsible=true) */
|
||||
collapsed?: boolean
|
||||
/** Test ID for automated testing */
|
||||
testId?: string
|
||||
}
|
||||
|
||||
export const Panel: React.FC<PanelProps> = ({
|
||||
children,
|
||||
className,
|
||||
variant = 'default',
|
||||
fixedPosition,
|
||||
collapsible = false,
|
||||
collapsed = false,
|
||||
testId,
|
||||
...props
|
||||
}) => {
|
||||
const panelClass = classNames(
|
||||
// Base or variant class
|
||||
{
|
||||
[styles.panel]: variant === 'default' && !fixedPosition,
|
||||
[styles.panelElevated]: variant === 'elevated',
|
||||
[styles.panelOutlined]: variant === 'outlined',
|
||||
},
|
||||
// Fixed position classes
|
||||
{
|
||||
[styles.panelFixedBr]: fixedPosition === 'br',
|
||||
[styles.panelFixedBl]: fixedPosition === 'bl',
|
||||
[styles.panelFixedTr]: fixedPosition === 'tr',
|
||||
[styles.panelFixedTl]: fixedPosition === 'tl',
|
||||
},
|
||||
// Collapsible state classes
|
||||
{
|
||||
[styles.panelCollapsible]: collapsible,
|
||||
[styles.panelCollapsed]: collapsible && collapsed,
|
||||
},
|
||||
className
|
||||
)
|
||||
|
||||
return (
|
||||
<div className={panelClass} data-testid={testId} role="region" {...props}>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// PanelHeader Component
|
||||
// ============================================================================
|
||||
|
||||
export interface PanelHeaderProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
children?: React.ReactNode
|
||||
/** Header color variant */
|
||||
variant?: PanelHeaderVariant
|
||||
/** Make header clickable (for collapsible panels) */
|
||||
clickable?: boolean
|
||||
}
|
||||
|
||||
export const PanelHeader: React.FC<PanelHeaderProps> = ({
|
||||
children,
|
||||
className,
|
||||
variant = 'primary',
|
||||
clickable = false,
|
||||
...props
|
||||
}) => {
|
||||
const headerClass = classNames(
|
||||
{
|
||||
[styles.panelHeader]: variant === 'primary',
|
||||
[styles.panelHeaderSecondary]: variant === 'secondary',
|
||||
[styles.panelHeaderTertiary]: variant === 'tertiary',
|
||||
[styles.panelHeaderSurface]: variant === 'surface',
|
||||
[styles.panelHeaderClickable]: clickable,
|
||||
},
|
||||
className
|
||||
)
|
||||
|
||||
return (
|
||||
<div className={headerClass} {...props}>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// PanelTitle Component
|
||||
// ============================================================================
|
||||
|
||||
export interface PanelTitleProps extends React.HTMLAttributes<HTMLHeadingElement> {
|
||||
children?: React.ReactNode
|
||||
/** Heading level for accessibility */
|
||||
as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'
|
||||
}
|
||||
|
||||
export const PanelTitle: React.FC<PanelTitleProps> = ({
|
||||
children,
|
||||
className,
|
||||
as: Component = 'h3',
|
||||
...props
|
||||
}) => {
|
||||
return (
|
||||
<Component className={classNames(styles.panelTitle, className)} {...props}>
|
||||
{children}
|
||||
</Component>
|
||||
)
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// PanelBody Component
|
||||
// ============================================================================
|
||||
|
||||
export type PanelBodyVariant = 'default' | 'noPadding' | 'scroll'
|
||||
|
||||
export interface PanelBodyProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
children?: React.ReactNode
|
||||
/** Body padding/scroll variant */
|
||||
variant?: PanelBodyVariant
|
||||
}
|
||||
|
||||
export const PanelBody: React.FC<PanelBodyProps> = ({
|
||||
children,
|
||||
className,
|
||||
variant = 'default',
|
||||
...props
|
||||
}) => {
|
||||
const bodyClass = classNames(
|
||||
{
|
||||
[styles.panelBody]: variant === 'default',
|
||||
[styles.panelBodyNoPadding]: variant === 'noPadding',
|
||||
[styles.panelBodyScroll]: variant === 'scroll',
|
||||
},
|
||||
className
|
||||
)
|
||||
|
||||
return (
|
||||
<div className={bodyClass} {...props}>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// PanelFooter Component
|
||||
// ============================================================================
|
||||
|
||||
export interface PanelFooterProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
children?: React.ReactNode
|
||||
/** Show action buttons aligned right */
|
||||
actions?: boolean
|
||||
}
|
||||
|
||||
export const PanelFooter: React.FC<PanelFooterProps> = ({
|
||||
children,
|
||||
className,
|
||||
actions = false,
|
||||
...props
|
||||
}) => {
|
||||
const footerClass = classNames(
|
||||
actions ? styles.panelFooterActions : styles.panelFooter,
|
||||
className
|
||||
)
|
||||
|
||||
return (
|
||||
<div className={footerClass} {...props}>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// PanelSection Component
|
||||
// ============================================================================
|
||||
|
||||
export interface PanelSectionProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
children?: React.ReactNode
|
||||
}
|
||||
|
||||
export const PanelSection: React.FC<PanelSectionProps> = ({
|
||||
children,
|
||||
className,
|
||||
...props
|
||||
}) => {
|
||||
return (
|
||||
<div className={classNames(styles.panelSection, className)} {...props}>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,147 +0,0 @@
|
||||
import React from 'react'
|
||||
import classNames from 'classnames'
|
||||
import styles from '../../../scss/atoms/section.module.scss'
|
||||
|
||||
export type SectionSize = 'sm' | 'md' | 'lg' | 'xl'
|
||||
|
||||
export interface SectionProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
children?: React.ReactNode
|
||||
size?: SectionSize
|
||||
/** @deprecated Use size="sm" instead */
|
||||
sm?: boolean
|
||||
/** Test ID for automated testing */
|
||||
testId?: string
|
||||
}
|
||||
|
||||
export const Section: React.FC<SectionProps> = ({
|
||||
children,
|
||||
size = 'md',
|
||||
sm,
|
||||
testId,
|
||||
className,
|
||||
...props
|
||||
}) => {
|
||||
const effectiveSize = sm ? 'sm' : size
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classNames(
|
||||
styles.section,
|
||||
{
|
||||
[styles.sectionSm]: effectiveSize === 'sm',
|
||||
[styles.sectionLg]: effectiveSize === 'lg',
|
||||
[styles.sectionXl]: effectiveSize === 'xl',
|
||||
},
|
||||
className
|
||||
)}
|
||||
data-testid={testId}
|
||||
role="region"
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export interface SectionHeaderProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
children?: React.ReactNode
|
||||
size?: 'sm' | 'md'
|
||||
}
|
||||
|
||||
export const SectionHeader: React.FC<SectionHeaderProps> = ({
|
||||
children,
|
||||
size = 'md',
|
||||
className,
|
||||
...props
|
||||
}) => (
|
||||
<div
|
||||
className={classNames(
|
||||
styles.sectionHeader,
|
||||
{ [styles.sectionHeaderSm]: size === 'sm' },
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
|
||||
export interface SectionTitleProps extends React.HTMLAttributes<HTMLHeadingElement> {
|
||||
children?: React.ReactNode
|
||||
}
|
||||
|
||||
export const SectionTitle: React.FC<SectionTitleProps> = ({
|
||||
children,
|
||||
className,
|
||||
...props
|
||||
}) => (
|
||||
<h3 className={classNames(styles.sectionTitle, className)} {...props}>
|
||||
{children}
|
||||
</h3>
|
||||
)
|
||||
|
||||
export interface SectionSubtitleProps extends React.HTMLAttributes<HTMLParagraphElement> {
|
||||
children?: React.ReactNode
|
||||
}
|
||||
|
||||
export const SectionSubtitle: React.FC<SectionSubtitleProps> = ({
|
||||
children,
|
||||
className,
|
||||
...props
|
||||
}) => (
|
||||
<p className={classNames(styles.sectionSubtitle, className)} {...props}>
|
||||
{children}
|
||||
</p>
|
||||
)
|
||||
|
||||
export type SectionContentVariant = 'elevated' | 'outlined' | 'transparent'
|
||||
|
||||
export interface SectionContentProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
children?: React.ReactNode
|
||||
variant?: SectionContentVariant
|
||||
}
|
||||
|
||||
export const SectionContent: React.FC<SectionContentProps> = ({
|
||||
children,
|
||||
variant,
|
||||
className,
|
||||
...props
|
||||
}) => (
|
||||
<div
|
||||
className={classNames(
|
||||
styles.sectionContent,
|
||||
{
|
||||
[styles.sectionContentElevated]: variant === 'elevated',
|
||||
[styles.sectionContentOutlined]: variant === 'outlined',
|
||||
[styles.sectionContentTransparent]: variant === 'transparent',
|
||||
},
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
|
||||
export interface SectionActionsProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
children?: React.ReactNode
|
||||
}
|
||||
|
||||
export const SectionActions: React.FC<SectionActionsProps> = ({
|
||||
children,
|
||||
className,
|
||||
...props
|
||||
}) => (
|
||||
<div className={classNames(styles.sectionActions, className)} {...props}>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
|
||||
export interface SectionDividerProps extends React.HTMLAttributes<HTMLHRElement> {}
|
||||
|
||||
export const SectionDivider: React.FC<SectionDividerProps> = ({
|
||||
className,
|
||||
...props
|
||||
}) => (
|
||||
<hr className={classNames(styles.sectionDivider, className)} {...props} />
|
||||
)
|
||||
@@ -1,105 +0,0 @@
|
||||
import React from 'react'
|
||||
import classNames from 'classnames'
|
||||
import styles from '../../../scss/atoms/statBadge.module.scss'
|
||||
|
||||
export type StatBadgeSize = 'sm' | 'md' | 'lg'
|
||||
export type StatBadgeColor = 'primary' | 'secondary' | 'tertiary' | 'neutral'
|
||||
export type StatBadgeStatus = 'pending' | 'success' | 'error' | 'warning' | 'info'
|
||||
|
||||
export interface StatBadgeProps extends React.HTMLAttributes<HTMLSpanElement> {
|
||||
children?: React.ReactNode
|
||||
/** Size variant */
|
||||
size?: StatBadgeSize
|
||||
/** M3 color variant */
|
||||
color?: StatBadgeColor
|
||||
/** Status variant (legacy props also supported) */
|
||||
status?: StatBadgeStatus
|
||||
/** Use filled (stronger) variant */
|
||||
filled?: boolean
|
||||
/** Render as dot indicator (no text) */
|
||||
dot?: boolean
|
||||
/** Add pulsing animation */
|
||||
pulse?: boolean
|
||||
/** Content contains icon */
|
||||
withIcon?: boolean
|
||||
/** Show overflow indicator (+) */
|
||||
overflow?: boolean
|
||||
/** @deprecated Use status="pending" */
|
||||
pending?: boolean
|
||||
/** @deprecated Use status="success" */
|
||||
success?: boolean
|
||||
/** @deprecated Use status="error" */
|
||||
error?: boolean
|
||||
/** @deprecated Use status="info" */
|
||||
info?: boolean
|
||||
/** Test ID for automated testing */
|
||||
testId?: string
|
||||
}
|
||||
|
||||
export const StatBadge: React.FC<StatBadgeProps> = ({
|
||||
children,
|
||||
size = 'md',
|
||||
color,
|
||||
status,
|
||||
filled = false,
|
||||
dot = false,
|
||||
pulse = false,
|
||||
withIcon = false,
|
||||
overflow = false,
|
||||
pending,
|
||||
success,
|
||||
error,
|
||||
info,
|
||||
testId,
|
||||
className,
|
||||
...props
|
||||
}) => {
|
||||
// Resolve status from legacy props if not explicitly set
|
||||
const resolvedStatus: StatBadgeStatus | undefined =
|
||||
status ?? (pending ? 'pending' : success ? 'success' : error ? 'error' : info ? 'info' : undefined)
|
||||
|
||||
const badgeClasses = classNames(
|
||||
styles.statBadge,
|
||||
// Size variants
|
||||
{
|
||||
[styles.statBadgeSm]: size === 'sm',
|
||||
[styles.statBadgeLg]: size === 'lg',
|
||||
},
|
||||
// Status variants (filled or container)
|
||||
resolvedStatus && {
|
||||
[styles.statBadgeFilledSuccess]: filled && resolvedStatus === 'success',
|
||||
[styles.statBadgeFilledError]: filled && resolvedStatus === 'error',
|
||||
[styles.statBadgeFilledWarning]: filled && resolvedStatus === 'warning',
|
||||
[styles.statBadgeFilledInfo]: filled && resolvedStatus === 'info',
|
||||
[styles.statBadgeFilledPrimary]: filled && resolvedStatus === 'pending',
|
||||
[styles.statBadgePending]: !filled && resolvedStatus === 'pending',
|
||||
[styles.statBadgeSuccess]: !filled && resolvedStatus === 'success',
|
||||
[styles.statBadgeError]: !filled && resolvedStatus === 'error',
|
||||
[styles.statBadgeWarning]: !filled && resolvedStatus === 'warning',
|
||||
[styles.statBadgeInfo]: !filled && resolvedStatus === 'info',
|
||||
},
|
||||
// M3 color variants (only if no status)
|
||||
!resolvedStatus &&
|
||||
color && {
|
||||
[styles.statBadgePrimary]: !filled && color === 'primary',
|
||||
[styles.statBadgeSecondary]: !filled && color === 'secondary',
|
||||
[styles.statBadgeTertiary]: !filled && color === 'tertiary',
|
||||
[styles.statBadgeNeutral]: !filled && color === 'neutral',
|
||||
[styles.statBadgeFilledPrimary]: filled && color === 'primary',
|
||||
},
|
||||
// Feature modifiers
|
||||
{
|
||||
[styles.statBadgeDot]: dot,
|
||||
[styles.statBadgePulse]: pulse,
|
||||
[styles.statBadgeWithIcon]: withIcon,
|
||||
[styles.statBadgeOverflow]: overflow,
|
||||
},
|
||||
className
|
||||
)
|
||||
|
||||
return (
|
||||
<span className={badgeClasses} data-testid={testId} {...props}>
|
||||
{children}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user