Merge pull request #7 from johndoe6345789/copilot/create-weak-link-packages-folder

Commit packages folder to repository with on-demand package creation and merge conflict detection
This commit is contained in:
2025-12-24 02:08:55 +00:00
committed by GitHub
23 changed files with 469 additions and 17 deletions

View 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@v4
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

1
.gitignore vendored
View File

@@ -26,7 +26,6 @@ dist-ssr
.env
**/agent-eval-report*
packages
pids
.file-manifest
.devcontainer/

View File

@@ -13,11 +13,24 @@ A declarative admin panel generator that creates full-featured CRUD interfaces f
## Quick Start
1. Launch the app
2. Use the sidebar to navigate between models
3. Click "Create New" to add records
4. Edit or delete records using the action buttons
5. Click "Edit Schema" to customize your data models
1. Clone the repository
2. Install dependencies: `npm install`
3. Launch the app: `npm run dev`
4. Use the sidebar to navigate between models
5. Click "Create New" to add records
6. Edit or delete records using the action buttons
7. Click "Edit Schema" to customize your data models
## Packages
This project uses a modular package system. The `packages/` folder contains component packages that are committed to the repository.
If you need to add a new package, use:
```bash
npm run setup-packages <package-name>
```
This will create the required package structure with placeholder files.
## Schema Structure

13
package-lock.json generated
View File

@@ -7,6 +7,7 @@
"": {
"name": "spark-template",
"version": "0.0.0",
"hasInstallScript": true,
"dependencies": {
"@github/spark": ">=0.43.1 <1",
"@heroicons/react": "^2.2.0",
@@ -7106,6 +7107,8 @@
"resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.55.1.tgz",
"integrity": "sha512-jz4x+TJNFHwHtwuV9vA9rMujcZRb0CEilTEwG2rRSpe/A7Jdkuj8xPKttCgOh+v/lkHy7HsZ64oj+q3xoAFl9A==",
"license": "MIT",
"optional": true,
"peer": true,
"dependencies": {
"dompurify": "3.2.7",
"marked": "14.0.0"
@@ -7851,16 +7854,8 @@
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
"node": ">=0.10.0"
}
},
"node_modules/router/node_modules/ms": {

View File

@@ -9,7 +9,9 @@
"build": "tsc -b --noCheck && vite build",
"lint": "eslint .",
"optimize": "vite optimize",
"preview": "vite preview"
"preview": "vite preview",
"setup-packages": "node scripts/setup-packages.cjs",
"postinstall": "node scripts/setup-packages.cjs"
},
"dependencies": {
"@github/spark": ">=0.43.1 <1",

61
packages/README.md Normal file
View File

@@ -0,0 +1,61 @@
# Packages Folder
This folder contains modular packages for the MetaBuilder application. Each package is self-contained with its own components, metadata, and examples.
## Structure
Each package follows this structure:
```
packages/
├── package_name/
│ ├── seed/
│ │ ├── components.json # Component definitions
│ │ ├── metadata.json # Package metadata
│ │ └── scripts/ # Optional Lua scripts
│ └── static_content/
│ └── examples.json # Optional usage examples
```
## Available Packages
- **admin_dialog**: Admin dialog components for management interfaces
- **data_table**: Data table components for displaying tabular data
- **form_builder**: Form builder components for creating dynamic forms
- **nav_menu**: Navigation menu components
- **dashboard**: Dashboard layout components
- **notification_center**: Notification center components
## Package Metadata Format
Each `metadata.json` file should contain:
```json
{
"packageId": "package_name",
"name": "Display Name",
"version": "1.0.0",
"description": "Package description",
"author": "Author name",
"category": "ui",
"dependencies": [],
"exports": {
"components": []
}
}
```
## Components Format
Each `components.json` file should contain an array of component definitions.
## Development
The main application imports from these packages via relative paths in `src/lib/package-glue.ts`.
To add a new package:
1. Run `npm run setup-packages <package-name>` to create the package structure
2. Add optional `static_content/examples.json` if needed
3. Update `src/lib/package-glue.ts` to import the new package
4. Commit the new package files to the repository

View File

@@ -0,0 +1 @@
[]

View File

@@ -0,0 +1,12 @@
{
"packageId": "admin_dialog",
"name": "Admin Dialog",
"version": "1.0.0",
"description": "Admin dialog components",
"author": "MetaBuilder",
"category": "ui",
"dependencies": [],
"exports": {
"components": []
}
}

View File

@@ -0,0 +1 @@
{}

View File

@@ -0,0 +1 @@
[]

View File

@@ -0,0 +1,12 @@
{
"packageId": "dashboard",
"name": "Dashboard",
"version": "1.0.0",
"description": "Dashboard components",
"author": "MetaBuilder",
"category": "ui",
"dependencies": [],
"exports": {
"components": []
}
}

View File

@@ -0,0 +1 @@
[]

View File

@@ -0,0 +1,12 @@
{
"packageId": "data_table",
"name": "Data Table",
"version": "1.0.0",
"description": "Data table components",
"author": "MetaBuilder",
"category": "ui",
"dependencies": [],
"exports": {
"components": []
}
}

View File

@@ -0,0 +1 @@
{}

View File

@@ -0,0 +1 @@
[]

View File

@@ -0,0 +1,12 @@
{
"packageId": "form_builder",
"name": "Form Builder",
"version": "1.0.0",
"description": "Form builder components",
"author": "MetaBuilder",
"category": "ui",
"dependencies": [],
"exports": {
"components": []
}
}

View File

@@ -0,0 +1 @@
{}

View File

@@ -0,0 +1 @@
[]

View File

@@ -0,0 +1,12 @@
{
"packageId": "nav_menu",
"name": "Navigation Menu",
"version": "1.0.0",
"description": "Navigation menu components",
"author": "MetaBuilder",
"category": "ui",
"dependencies": [],
"exports": {
"components": []
}
}

View File

@@ -0,0 +1 @@
[]

View File

@@ -0,0 +1,12 @@
{
"packageId": "notification_center",
"name": "Notification Center",
"version": "1.0.0",
"description": "Notification center components",
"author": "MetaBuilder",
"category": "ui",
"dependencies": [],
"exports": {
"components": []
}
}

168
scripts/setup-packages.cjs Executable file
View File

@@ -0,0 +1,168 @@
#!/usr/bin/env node
'use strict';
/**
* Setup script for creating package folder structure
* Usage:
* node scripts/setup-packages.cjs <package-name> - Create a specific package
* node scripts/setup-packages.cjs - Verify all required packages exist
*/
const fs = require('fs');
const path = require('path');
const packagesDir = path.join(__dirname, '..', 'packages');
// Get package name from command line argument
const packageName = process.argv[2];
// Package definitions
const packageTemplates = {
'admin_dialog': {
id: 'admin_dialog',
name: 'Admin Dialog',
description: 'Admin dialog components',
hasExamples: true
},
'data_table': {
id: 'data_table',
name: 'Data Table',
description: 'Data table components',
hasExamples: true
},
'form_builder': {
id: 'form_builder',
name: 'Form Builder',
description: 'Form builder components',
hasExamples: true
},
'nav_menu': {
id: 'nav_menu',
name: 'Navigation Menu',
description: 'Navigation menu components',
hasExamples: false
},
'dashboard': {
id: 'dashboard',
name: 'Dashboard',
description: 'Dashboard components',
hasExamples: false
},
'notification_center': {
id: 'notification_center',
name: 'Notification Center',
description: 'Notification center components',
hasExamples: false
}
};
function createPackage(pkg) {
const pkgDir = path.join(packagesDir, pkg.id);
const seedDir = path.join(pkgDir, 'seed');
// Create directories
if (!fs.existsSync(packagesDir)) {
fs.mkdirSync(packagesDir, { recursive: true });
}
if (!fs.existsSync(seedDir)) {
fs.mkdirSync(seedDir, { recursive: true });
}
// Create components.json
const componentsPath = path.join(seedDir, 'components.json');
if (!fs.existsSync(componentsPath)) {
fs.writeFileSync(componentsPath, '[]', 'utf8');
}
// Create metadata.json
const metadataPath = path.join(seedDir, 'metadata.json');
if (!fs.existsSync(metadataPath)) {
const metadata = {
packageId: pkg.id,
name: pkg.name,
version: '1.0.0',
description: pkg.description,
author: 'MetaBuilder',
category: 'ui',
dependencies: [],
exports: {
components: []
}
};
fs.writeFileSync(metadataPath, JSON.stringify(metadata, null, 2), 'utf8');
}
// Create examples.json if needed
if (pkg.hasExamples) {
const staticDir = path.join(pkgDir, 'static_content');
if (!fs.existsSync(staticDir)) {
fs.mkdirSync(staticDir, { recursive: true });
}
const examplesPath = path.join(staticDir, 'examples.json');
if (!fs.existsSync(examplesPath)) {
fs.writeFileSync(examplesPath, '{}', 'utf8');
}
}
console.log(`✓ Created ${pkg.name} package`);
}
// If a specific package name is provided
if (packageName) {
const pkg = packageTemplates[packageName];
if (!pkg) {
console.error(`Error: Unknown package '${packageName}'`);
console.log('\nAvailable packages:');
Object.keys(packageTemplates).forEach(key => {
console.log(` - ${key}`);
});
process.exit(1);
}
// Check if package already exists
const pkgDir = path.join(packagesDir, pkg.id);
if (fs.existsSync(pkgDir)) {
console.log(`✓ Package '${pkg.name}' already exists`);
process.exit(0);
}
console.log(`Creating package: ${pkg.name}...\n`);
createPackage(pkg);
console.log('\n✅ Package created successfully!');
} else {
// No package name provided - verification mode (postinstall or manual check)
// Verify that all required packages exist
const requiredPackages = Object.keys(packageTemplates);
const missingPackages = [];
if (!fs.existsSync(packagesDir)) {
console.error('Error: packages folder does not exist!');
console.log('Run this script with a package name to create packages.');
process.exit(1);
}
for (const pkgId of requiredPackages) {
const componentsPath = path.join(packagesDir, pkgId, 'seed', 'components.json');
const metadataPath = path.join(packagesDir, pkgId, 'seed', 'metadata.json');
if (!fs.existsSync(componentsPath) || !fs.existsSync(metadataPath)) {
missingPackages.push(pkgId);
}
}
if (missingPackages.length > 0) {
console.error('Error: Missing required packages:', missingPackages.join(', '));
console.log('\nCreate missing packages with:');
missingPackages.forEach(pkg => {
console.log(` npm run setup-packages ${pkg}`);
});
process.exit(1);
}
console.log('✓ All required packages exist and are committed to the repository.');
}

View File

@@ -28,6 +28,7 @@
},
},
"include": [
"src"
"src",
"packages"
]
}