mirror of
https://github.com/supabase/agent-skills.git
synced 2026-01-26 19:09:51 +08:00
refactor: generic skills build system with auto-discovery (#8)
* refactor: generic skills build system with auto-discovery - Rename postgres-best-practices-build → skills-build - Add auto-discovery: scans skills/ for subdirectories with metadata.json - Build/validate all skills or specific skill with -- argument - Update root AGENTS.md and CONTRIBUTING.md with new structure - No configuration needed to add new skills Usage: npm run build # Build all skills npm run build -- skill-name # Build specific skill npm run validate # Validate all skills Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix ci * more generic impact levels --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
20
.github/workflows/ci.yml
vendored
20
.github/workflows/ci.yml
vendored
@@ -1,4 +1,4 @@
|
||||
name: Postgres Best Practices CI
|
||||
name: Skills CI
|
||||
|
||||
on:
|
||||
push:
|
||||
@@ -23,7 +23,7 @@ jobs:
|
||||
run: npm run ci:check
|
||||
|
||||
validate-and-build:
|
||||
name: Validate and Build
|
||||
name: Validate and Build Skills
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@@ -33,22 +33,22 @@ jobs:
|
||||
node-version: '20'
|
||||
|
||||
- name: Install dependencies
|
||||
working-directory: packages/postgres-best-practices-build
|
||||
working-directory: packages/skills-build
|
||||
run: npm install
|
||||
|
||||
- name: Validate rule files
|
||||
working-directory: packages/postgres-best-practices-build
|
||||
- name: Validate all skills
|
||||
working-directory: packages/skills-build
|
||||
run: npm run validate
|
||||
|
||||
- name: Build AGENTS.md
|
||||
working-directory: packages/postgres-best-practices-build
|
||||
- name: Build all skills
|
||||
working-directory: packages/skills-build
|
||||
run: npm run build
|
||||
|
||||
- name: Check for uncommitted changes
|
||||
run: |
|
||||
if [[ -n $(git status --porcelain skills/postgres-best-practices/AGENTS.md) ]]; then
|
||||
echo "Error: AGENTS.md is not up to date"
|
||||
if [[ -n $(git status --porcelain 'skills/*/AGENTS.md') ]]; then
|
||||
echo "Error: AGENTS.md files are not up to date"
|
||||
echo "Run 'npm run build' and commit the changes"
|
||||
git diff skills/postgres-best-practices/AGENTS.md
|
||||
git diff skills/*/AGENTS.md
|
||||
exit 1
|
||||
fi
|
||||
|
||||
151
AGENTS.md
151
AGENTS.md
@@ -1,120 +1,71 @@
|
||||
# AGENTS.md
|
||||
|
||||
This file provides guidance to AI coding agents (Claude Code, Cursor, Copilot,
|
||||
etc.) when working with code in this repository.
|
||||
Guidance for AI coding agents working with this repository.
|
||||
|
||||
## Repository Overview
|
||||
|
||||
A collection of Postgres best practices skills for AI coding agents, maintained
|
||||
by Supabase. Skills are packaged instructions that extend agent capabilities for
|
||||
database optimization.
|
||||
|
||||
## Creating a New Rule
|
||||
|
||||
### Directory Structure
|
||||
## Repository Structure
|
||||
|
||||
```
|
||||
skills/
|
||||
postgres-best-practices/
|
||||
SKILL.md # Required: skill definition
|
||||
{skill-name}/
|
||||
metadata.json # Required: skill metadata
|
||||
AGENTS.md # Generated: compiled rules
|
||||
metadata.json # Required: version and metadata
|
||||
rules/
|
||||
_template.md # Template for new rules
|
||||
_sections.md # Section definitions
|
||||
_contributing.md # Writing guidelines
|
||||
{prefix}-{name}.md # Individual rule files
|
||||
_sections.md # Required: section definitions
|
||||
{prefix}-{name}.md # Rule files
|
||||
|
||||
packages/
|
||||
postgres-best-practices-build/
|
||||
src/ # Build system source
|
||||
package.json # NPM scripts
|
||||
skills-build/ # Generic build system for all skills
|
||||
```
|
||||
|
||||
### Naming Conventions
|
||||
|
||||
- **Rule files**: `{prefix}-{kebab-case-name}.md` (e.g.,
|
||||
`query-missing-indexes.md`)
|
||||
- **Prefixes determine section**: `query-`, `conn-`, `schema-`, `lock-`,
|
||||
`security-`, `data-`, `monitor-`, `advanced-`
|
||||
- **Special files**: Prefixed with `_` (e.g., `_template.md`, `_sections.md`)
|
||||
|
||||
### Rule File Format
|
||||
|
||||
````markdown
|
||||
---
|
||||
title: Clear, Action-Oriented Title
|
||||
impact: CRITICAL|HIGH|MEDIUM-HIGH|MEDIUM|LOW-MEDIUM|LOW
|
||||
impactDescription: Quantified benefit (e.g., "10-100x faster")
|
||||
tags: relevant, keywords
|
||||
---
|
||||
|
||||
## [Title]
|
||||
|
||||
[1-2 sentence explanation]
|
||||
|
||||
**Incorrect (description):**
|
||||
|
||||
```sql
|
||||
-- Comment explaining what's wrong
|
||||
[Bad SQL example]
|
||||
```
|
||||
|
||||
**Correct (description):**
|
||||
|
||||
```sql
|
||||
-- Comment explaining why this is better
|
||||
[Good SQL example]
|
||||
```
|
||||
````
|
||||
|
||||
### Best Practices for Context Efficiency
|
||||
|
||||
Skills are loaded on-demand. To minimize context usage:
|
||||
|
||||
- **Keep rules focused** - One optimization pattern per rule
|
||||
- **Write specific titles** - Helps the agent know exactly when to apply
|
||||
- **Use progressive disclosure** - Reference supporting files when needed
|
||||
- **Self-contained examples** - Complete, runnable SQL
|
||||
- **Quantify impact** - Include specific metrics (10x faster, 50% smaller)
|
||||
|
||||
### Build System
|
||||
|
||||
After creating or updating rules:
|
||||
## Commands
|
||||
|
||||
```bash
|
||||
cd packages/postgres-best-practices-build
|
||||
npm install
|
||||
npm run validate # Check rule format
|
||||
npm run build # Generate AGENTS.md
|
||||
npm run build # Build all skills
|
||||
npm run build -- {skill-name} # Build specific skill
|
||||
npm run validate # Validate all skills
|
||||
npm run validate -- {skill-name} # Validate specific skill
|
||||
```
|
||||
|
||||
**Automatic Section Ordering**: The build system automatically reads section order
|
||||
from `_sections.md`. To reorder sections (e.g., promoting Security from MEDIUM-HIGH
|
||||
to CRITICAL priority), simply edit the section numbers in `_sections.md` and
|
||||
rebuild. The section mapping is generated dynamically, so manual updates to
|
||||
`config.ts` are no longer needed.
|
||||
## Creating a New Skill
|
||||
|
||||
### Impact Levels
|
||||
1. Create directory: `mkdir -p skills/{name}/rules`
|
||||
2. Add `metadata.json` with version, organization, abstract
|
||||
3. Add `rules/_sections.md` defining sections
|
||||
4. Add rule files: `{prefix}-{rule-name}.md`
|
||||
5. Run `npm run build`
|
||||
|
||||
| Level | Improvement | Examples |
|
||||
| ----------- | ----------- | -------------------------------------- |
|
||||
| CRITICAL | 10-100x | Missing indexes, connection exhaustion |
|
||||
| HIGH | 5-20x | Wrong index types, poor partitioning |
|
||||
| MEDIUM-HIGH | 2-5x | N+1 queries, RLS optimization |
|
||||
| MEDIUM | 1.5-3x | Redundant indexes, stale statistics |
|
||||
| LOW-MEDIUM | 1.2-2x | VACUUM tuning, config tweaks |
|
||||
| LOW | Incremental | Advanced patterns, edge cases |
|
||||
## Rule File Format
|
||||
|
||||
### File Prefix to Section Mapping
|
||||
```markdown
|
||||
---
|
||||
title: Action-Oriented Title
|
||||
impact: CRITICAL|HIGH|MEDIUM-HIGH|MEDIUM|LOW-MEDIUM|LOW
|
||||
impactDescription: Quantified benefit
|
||||
tags: keywords
|
||||
---
|
||||
|
||||
| Prefix | Section | Priority |
|
||||
| ----------- | ------------------------ | --------------- |
|
||||
| `query-` | Query Performance | 1 (CRITICAL) |
|
||||
| `conn-` | Connection Management | 2 (CRITICAL) |
|
||||
| `security-` | Security & RLS | 3 (CRITICAL) |
|
||||
| `schema-` | Schema Design | 4 (HIGH) |
|
||||
| `lock-` | Concurrency & Locking | 5 (MEDIUM-HIGH) |
|
||||
| `data-` | Data Access Patterns | 6 (MEDIUM) |
|
||||
| `monitor-` | Monitoring & Diagnostics | 7 (LOW-MEDIUM) |
|
||||
| `advanced-` | Advanced Features | 8 (LOW) |
|
||||
## Title
|
||||
|
||||
1-2 sentence explanation.
|
||||
|
||||
**Incorrect:**
|
||||
\`\`\`sql
|
||||
-- bad example
|
||||
\`\`\`
|
||||
|
||||
**Correct:**
|
||||
\`\`\`sql
|
||||
-- good example
|
||||
\`\`\`
|
||||
```
|
||||
|
||||
## Impact Levels
|
||||
|
||||
| Level | Improvement | Use For |
|
||||
| ----------- | ----------------------------- | ---------------------------------------------------------- |
|
||||
| CRITICAL | 10-100x or prevents failure | Security vulnerabilities, data loss, breaking changes |
|
||||
| HIGH | 5-20x or major quality gain | Architecture decisions, core functionality, scalability |
|
||||
| MEDIUM-HIGH | 2-5x or significant benefit | Design patterns, common anti-patterns, reliability |
|
||||
| MEDIUM | 1.5-3x or noticeable gain | Optimization, best practices, maintainability |
|
||||
| LOW-MEDIUM | 1.2-2x or minor benefit | Configuration, tooling, code organization |
|
||||
| LOW | Incremental or edge cases | Advanced techniques, rare scenarios, polish |
|
||||
|
||||
@@ -2,10 +2,9 @@
|
||||
|
||||
Thank you for contributing to Supabase Agent Skills! Here's how to get started:
|
||||
|
||||
[1. Getting Started](#getting-started) [2. Issues](#issues)
|
||||
[3. Pull Requests](#pull-requests)
|
||||
[4. Contributing New Rules](#contributing-new-rules)
|
||||
[5. Extending Existing Skills](#extending-existing-skills)
|
||||
[1. Getting Started](#getting-started) | [2. Issues](#issues) |
|
||||
[3. Pull Requests](#pull-requests) | [4. Contributing New Rules](#contributing-new-rules) |
|
||||
[5. Creating a New Skill](#creating-a-new-skill)
|
||||
|
||||
## Getting Started
|
||||
|
||||
@@ -49,6 +48,68 @@ npm run build # Generate AGENTS.md from rules
|
||||
|
||||
Both commands must complete successfully.
|
||||
|
||||
## Contributing New Rules
|
||||
|
||||
To add a rule to an existing skill:
|
||||
|
||||
1. Navigate to `skills/{skill-name}/rules/`
|
||||
2. Copy `_template.md` to `{prefix}-{your-rule-name}.md`
|
||||
3. Fill in the frontmatter (title, impact, tags)
|
||||
4. Write explanation and examples (Incorrect/Correct)
|
||||
5. Run validation and build:
|
||||
|
||||
```bash
|
||||
npm run validate
|
||||
npm run build
|
||||
```
|
||||
|
||||
## Creating a New Skill
|
||||
|
||||
To create an entirely new skill:
|
||||
|
||||
### 1. Create the directory structure
|
||||
|
||||
```bash
|
||||
mkdir -p skills/my-skill/rules
|
||||
```
|
||||
|
||||
### 2. Create metadata.json
|
||||
|
||||
```json
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"organization": "Your Org",
|
||||
"date": "January 2026",
|
||||
"abstract": "Brief description of this skill."
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Create rules/_sections.md
|
||||
|
||||
```markdown
|
||||
## 1. First Category (first)
|
||||
**Impact:** HIGH
|
||||
**Description:** What this category covers.
|
||||
|
||||
## 2. Second Category (second)
|
||||
**Impact:** MEDIUM
|
||||
**Description:** What this category covers.
|
||||
```
|
||||
|
||||
### 4. Create rule files
|
||||
|
||||
Name files as `{prefix}-{rule-name}.md` where prefix matches a section.
|
||||
|
||||
Example: `first-example-rule.md` for section "First Category"
|
||||
|
||||
### 5. Build
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
The build system auto-discovers skills. No configuration needed.
|
||||
|
||||
## Questions or Feedback?
|
||||
|
||||
- Open an Issue for bugs or suggestions
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
"license": "MIT",
|
||||
"description": "Official Supabase agent skills",
|
||||
"scripts": {
|
||||
"build": "npm --prefix packages/postgres-best-practices-build run build",
|
||||
"validate": "npm --prefix packages/postgres-best-practices-build run validate",
|
||||
"build": "npm --prefix packages/skills-build run build",
|
||||
"validate": "npm --prefix packages/skills-build run validate",
|
||||
"format": "biome format --write .",
|
||||
"format:check": "biome format .",
|
||||
"lint": "biome lint --write .",
|
||||
|
||||
590
packages/postgres-best-practices-build/package-lock.json
generated
590
packages/postgres-best-practices-build/package-lock.json
generated
@@ -1,590 +0,0 @@
|
||||
{
|
||||
"name": "postgresql-best-practices-build",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "postgresql-best-practices-build",
|
||||
"version": "1.0.0",
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.10.0",
|
||||
"tsx": "^4.7.0",
|
||||
"typescript": "^5.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/aix-ppc64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz",
|
||||
"integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"aix"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-arm": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.2.tgz",
|
||||
"integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-arm64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz",
|
||||
"integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-x64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.2.tgz",
|
||||
"integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/darwin-arm64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz",
|
||||
"integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/darwin-x64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz",
|
||||
"integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/freebsd-arm64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz",
|
||||
"integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/freebsd-x64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz",
|
||||
"integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-arm": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz",
|
||||
"integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-arm64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz",
|
||||
"integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-ia32": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz",
|
||||
"integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-loong64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz",
|
||||
"integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==",
|
||||
"cpu": [
|
||||
"loong64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-mips64el": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz",
|
||||
"integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==",
|
||||
"cpu": [
|
||||
"mips64el"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-ppc64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz",
|
||||
"integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-riscv64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz",
|
||||
"integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-s390x": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz",
|
||||
"integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-x64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz",
|
||||
"integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/netbsd-arm64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz",
|
||||
"integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"netbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/netbsd-x64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz",
|
||||
"integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"netbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/openbsd-arm64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz",
|
||||
"integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/openbsd-x64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz",
|
||||
"integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/openharmony-arm64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz",
|
||||
"integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openharmony"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/sunos-x64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz",
|
||||
"integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"sunos"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-arm64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz",
|
||||
"integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-ia32": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz",
|
||||
"integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-x64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz",
|
||||
"integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "20.19.30",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.30.tgz",
|
||||
"integrity": "sha512-WJtwWJu7UdlvzEAUm484QNg5eAoq5QR08KDNx7g45Usrs2NtOPiX8ugDqmKdXkyL03rBqU5dYNYVQetEpBHq2g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~6.21.0"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz",
|
||||
"integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"esbuild": "bin/esbuild"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@esbuild/aix-ppc64": "0.27.2",
|
||||
"@esbuild/android-arm": "0.27.2",
|
||||
"@esbuild/android-arm64": "0.27.2",
|
||||
"@esbuild/android-x64": "0.27.2",
|
||||
"@esbuild/darwin-arm64": "0.27.2",
|
||||
"@esbuild/darwin-x64": "0.27.2",
|
||||
"@esbuild/freebsd-arm64": "0.27.2",
|
||||
"@esbuild/freebsd-x64": "0.27.2",
|
||||
"@esbuild/linux-arm": "0.27.2",
|
||||
"@esbuild/linux-arm64": "0.27.2",
|
||||
"@esbuild/linux-ia32": "0.27.2",
|
||||
"@esbuild/linux-loong64": "0.27.2",
|
||||
"@esbuild/linux-mips64el": "0.27.2",
|
||||
"@esbuild/linux-ppc64": "0.27.2",
|
||||
"@esbuild/linux-riscv64": "0.27.2",
|
||||
"@esbuild/linux-s390x": "0.27.2",
|
||||
"@esbuild/linux-x64": "0.27.2",
|
||||
"@esbuild/netbsd-arm64": "0.27.2",
|
||||
"@esbuild/netbsd-x64": "0.27.2",
|
||||
"@esbuild/openbsd-arm64": "0.27.2",
|
||||
"@esbuild/openbsd-x64": "0.27.2",
|
||||
"@esbuild/openharmony-arm64": "0.27.2",
|
||||
"@esbuild/sunos-x64": "0.27.2",
|
||||
"@esbuild/win32-arm64": "0.27.2",
|
||||
"@esbuild/win32-ia32": "0.27.2",
|
||||
"@esbuild/win32-x64": "0.27.2"
|
||||
}
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
||||
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/get-tsconfig": {
|
||||
"version": "4.13.0",
|
||||
"resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz",
|
||||
"integrity": "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"resolve-pkg-maps": "^1.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/resolve-pkg-maps": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
|
||||
"integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/tsx": {
|
||||
"version": "4.21.0",
|
||||
"resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz",
|
||||
"integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"esbuild": "~0.27.0",
|
||||
"get-tsconfig": "^4.7.5"
|
||||
},
|
||||
"bin": {
|
||||
"tsx": "dist/cli.mjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"fsevents": "~2.3.3"
|
||||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "5.9.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
|
||||
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "6.21.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
|
||||
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
import { dirname, join } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
|
||||
// Build package directory
|
||||
export const BUILD_DIR = join(__dirname, "..");
|
||||
|
||||
// Skill directory (relative to build package)
|
||||
export const SKILL_DIR = join(
|
||||
BUILD_DIR,
|
||||
"../../skills/postgres-best-practices",
|
||||
);
|
||||
|
||||
// Rules directory
|
||||
export const RULES_DIR = join(SKILL_DIR, "rules");
|
||||
|
||||
// Output files
|
||||
export const AGENTS_OUTPUT = join(SKILL_DIR, "AGENTS.md");
|
||||
export const METADATA_FILE = join(SKILL_DIR, "metadata.json");
|
||||
|
||||
// Section prefix to number mapping (DEPRECATED)
|
||||
// This is kept as a fallback, but the build system now generates
|
||||
// the section map dynamically from _sections.md.
|
||||
// To reorder sections, simply change the order in _sections.md.
|
||||
export const SECTION_MAP: Record<string, number> = {
|
||||
query: 1,
|
||||
conn: 2,
|
||||
connection: 2,
|
||||
security: 3,
|
||||
schema: 4,
|
||||
lock: 5,
|
||||
data: 6,
|
||||
monitor: 7,
|
||||
advanced: 8,
|
||||
};
|
||||
|
||||
// Valid impact levels in priority order
|
||||
export const IMPACT_LEVELS = [
|
||||
"CRITICAL",
|
||||
"HIGH",
|
||||
"MEDIUM-HIGH",
|
||||
"MEDIUM",
|
||||
"LOW-MEDIUM",
|
||||
"LOW",
|
||||
] as const;
|
||||
591
packages/skills-build/package-lock.json
generated
Normal file
591
packages/skills-build/package-lock.json
generated
Normal file
@@ -0,0 +1,591 @@
|
||||
{
|
||||
"name": "skills-build",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "skills-build",
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.10.0",
|
||||
"tsx": "^4.7.0",
|
||||
"typescript": "^5.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/aix-ppc64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz",
|
||||
"integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"aix"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-arm": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.2.tgz",
|
||||
"integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-arm64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz",
|
||||
"integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-x64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.2.tgz",
|
||||
"integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/darwin-arm64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz",
|
||||
"integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/darwin-x64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz",
|
||||
"integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/freebsd-arm64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz",
|
||||
"integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/freebsd-x64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz",
|
||||
"integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-arm": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz",
|
||||
"integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-arm64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz",
|
||||
"integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-ia32": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz",
|
||||
"integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-loong64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz",
|
||||
"integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==",
|
||||
"cpu": [
|
||||
"loong64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-mips64el": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz",
|
||||
"integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==",
|
||||
"cpu": [
|
||||
"mips64el"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-ppc64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz",
|
||||
"integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-riscv64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz",
|
||||
"integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-s390x": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz",
|
||||
"integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-x64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz",
|
||||
"integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/netbsd-arm64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz",
|
||||
"integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"netbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/netbsd-x64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz",
|
||||
"integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"netbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/openbsd-arm64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz",
|
||||
"integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/openbsd-x64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz",
|
||||
"integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/openharmony-arm64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz",
|
||||
"integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openharmony"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/sunos-x64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz",
|
||||
"integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"sunos"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-arm64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz",
|
||||
"integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-ia32": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz",
|
||||
"integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-x64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz",
|
||||
"integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "20.19.30",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.30.tgz",
|
||||
"integrity": "sha512-WJtwWJu7UdlvzEAUm484QNg5eAoq5QR08KDNx7g45Usrs2NtOPiX8ugDqmKdXkyL03rBqU5dYNYVQetEpBHq2g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~6.21.0"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz",
|
||||
"integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"esbuild": "bin/esbuild"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@esbuild/aix-ppc64": "0.27.2",
|
||||
"@esbuild/android-arm": "0.27.2",
|
||||
"@esbuild/android-arm64": "0.27.2",
|
||||
"@esbuild/android-x64": "0.27.2",
|
||||
"@esbuild/darwin-arm64": "0.27.2",
|
||||
"@esbuild/darwin-x64": "0.27.2",
|
||||
"@esbuild/freebsd-arm64": "0.27.2",
|
||||
"@esbuild/freebsd-x64": "0.27.2",
|
||||
"@esbuild/linux-arm": "0.27.2",
|
||||
"@esbuild/linux-arm64": "0.27.2",
|
||||
"@esbuild/linux-ia32": "0.27.2",
|
||||
"@esbuild/linux-loong64": "0.27.2",
|
||||
"@esbuild/linux-mips64el": "0.27.2",
|
||||
"@esbuild/linux-ppc64": "0.27.2",
|
||||
"@esbuild/linux-riscv64": "0.27.2",
|
||||
"@esbuild/linux-s390x": "0.27.2",
|
||||
"@esbuild/linux-x64": "0.27.2",
|
||||
"@esbuild/netbsd-arm64": "0.27.2",
|
||||
"@esbuild/netbsd-x64": "0.27.2",
|
||||
"@esbuild/openbsd-arm64": "0.27.2",
|
||||
"@esbuild/openbsd-x64": "0.27.2",
|
||||
"@esbuild/openharmony-arm64": "0.27.2",
|
||||
"@esbuild/sunos-x64": "0.27.2",
|
||||
"@esbuild/win32-arm64": "0.27.2",
|
||||
"@esbuild/win32-ia32": "0.27.2",
|
||||
"@esbuild/win32-x64": "0.27.2"
|
||||
}
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
||||
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/get-tsconfig": {
|
||||
"version": "4.13.0",
|
||||
"resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz",
|
||||
"integrity": "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"resolve-pkg-maps": "^1.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/resolve-pkg-maps": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
|
||||
"integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/tsx": {
|
||||
"version": "4.21.0",
|
||||
"resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz",
|
||||
"integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"esbuild": "~0.27.0",
|
||||
"get-tsconfig": "^4.7.5"
|
||||
},
|
||||
"bin": {
|
||||
"tsx": "dist/cli.mjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"fsevents": "~2.3.3"
|
||||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "5.9.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
|
||||
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "6.21.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
|
||||
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"name": "postgres-best-practices-build",
|
||||
"name": "skills-build",
|
||||
"version": "1.0.0",
|
||||
"type": "module",
|
||||
"author": "Supabase",
|
||||
"license": "MIT",
|
||||
"description": "Build system for Supabase agent skills",
|
||||
"description": "Generic build system for Supabase agent skills",
|
||||
"scripts": {
|
||||
"build": "tsx src/build.ts",
|
||||
"validate": "tsx src/validate.ts",
|
||||
@@ -1,6 +1,11 @@
|
||||
import { existsSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
|
||||
import { basename, join } from "node:path";
|
||||
import { AGENTS_OUTPUT, METADATA_FILE, RULES_DIR } from "./config.js";
|
||||
import {
|
||||
discoverSkills,
|
||||
getSkillPaths,
|
||||
type SkillPaths,
|
||||
validateSkillExists,
|
||||
} from "./config.js";
|
||||
import { parseRuleFile } from "./parser.js";
|
||||
import type { Metadata, Rule, Section } from "./types.js";
|
||||
import { validateRuleFile } from "./validate.js";
|
||||
@@ -8,11 +13,11 @@ import { validateRuleFile } from "./validate.js";
|
||||
/**
|
||||
* Parse section definitions from _sections.md
|
||||
*/
|
||||
function parseSections(): Section[] {
|
||||
const sectionsFile = join(RULES_DIR, "_sections.md");
|
||||
function parseSections(rulesDir: string): Section[] {
|
||||
const sectionsFile = join(rulesDir, "_sections.md");
|
||||
if (!existsSync(sectionsFile)) {
|
||||
console.warn("Warning: _sections.md not found, using default sections");
|
||||
return getDefaultSections();
|
||||
console.warn("Warning: _sections.md not found, using empty sections");
|
||||
return [];
|
||||
}
|
||||
|
||||
const content = readFileSync(sectionsFile, "utf-8");
|
||||
@@ -36,78 +41,14 @@ function parseSections(): Section[] {
|
||||
});
|
||||
}
|
||||
|
||||
return sections.length > 0 ? sections : getDefaultSections();
|
||||
}
|
||||
|
||||
/**
|
||||
* Default sections if _sections.md is missing or unparseable
|
||||
*/
|
||||
function getDefaultSections(): Section[] {
|
||||
return [
|
||||
{
|
||||
number: 1,
|
||||
title: "Query Performance",
|
||||
prefix: "query",
|
||||
impact: "CRITICAL",
|
||||
description: "Slow queries, missing indexes, inefficient plans",
|
||||
},
|
||||
{
|
||||
number: 2,
|
||||
title: "Connection Management",
|
||||
prefix: "conn",
|
||||
impact: "CRITICAL",
|
||||
description: "Pooling, limits, serverless strategies",
|
||||
},
|
||||
{
|
||||
number: 3,
|
||||
title: "Security & RLS",
|
||||
prefix: "security",
|
||||
impact: "CRITICAL",
|
||||
description: "Row-Level Security, privileges, auth patterns",
|
||||
},
|
||||
{
|
||||
number: 4,
|
||||
title: "Schema Design",
|
||||
prefix: "schema",
|
||||
impact: "HIGH",
|
||||
description: "Table design, indexes, partitioning, data types",
|
||||
},
|
||||
{
|
||||
number: 5,
|
||||
title: "Concurrency & Locking",
|
||||
prefix: "lock",
|
||||
impact: "MEDIUM-HIGH",
|
||||
description: "Transactions, isolation, deadlocks",
|
||||
},
|
||||
{
|
||||
number: 6,
|
||||
title: "Data Access Patterns",
|
||||
prefix: "data",
|
||||
impact: "MEDIUM",
|
||||
description: "N+1 queries, batch operations, pagination",
|
||||
},
|
||||
{
|
||||
number: 7,
|
||||
title: "Monitoring & Diagnostics",
|
||||
prefix: "monitor",
|
||||
impact: "LOW-MEDIUM",
|
||||
description: "pg_stat_statements, EXPLAIN, metrics",
|
||||
},
|
||||
{
|
||||
number: 8,
|
||||
title: "Advanced Features",
|
||||
prefix: "advanced",
|
||||
impact: "LOW",
|
||||
description: "Full-text search, JSONB, extensions",
|
||||
},
|
||||
];
|
||||
return sections;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load metadata from metadata.json
|
||||
*/
|
||||
function loadMetadata(): Metadata {
|
||||
if (!existsSync(METADATA_FILE)) {
|
||||
function loadMetadata(metadataFile: string, skillName: string): Metadata {
|
||||
if (!existsSync(metadataFile)) {
|
||||
return {
|
||||
version: "1.0.0",
|
||||
organization: "Supabase",
|
||||
@@ -115,12 +56,12 @@ function loadMetadata(): Metadata {
|
||||
month: "long",
|
||||
year: "numeric",
|
||||
}),
|
||||
abstract: "Postgres performance optimization guide for developers.",
|
||||
abstract: `${skillName} guide for developers.`,
|
||||
references: [],
|
||||
};
|
||||
}
|
||||
|
||||
return JSON.parse(readFileSync(METADATA_FILE, "utf-8"));
|
||||
return JSON.parse(readFileSync(metadataFile, "utf-8"));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -133,6 +74,16 @@ function toAnchor(text: string): string {
|
||||
.replace(/\s+/g, "-");
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert skill name to title (e.g., "postgres-best-practices" -> "Postgres Best Practices")
|
||||
*/
|
||||
function skillNameToTitle(skillName: string): string {
|
||||
return skillName
|
||||
.split("-")
|
||||
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
||||
.join(" ");
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate SECTION_MAP from parsed sections
|
||||
*/
|
||||
@@ -147,23 +98,34 @@ export function generateSectionMap(
|
||||
}
|
||||
|
||||
/**
|
||||
* Build AGENTS.md from all rule files
|
||||
* Build AGENTS.md for a specific skill
|
||||
*/
|
||||
function buildAgents(): void {
|
||||
console.log("Building AGENTS.md...\n");
|
||||
function buildSkill(paths: SkillPaths): void {
|
||||
console.log(`[${paths.name}] Building AGENTS.md...`);
|
||||
|
||||
// Load metadata and sections
|
||||
const metadata = loadMetadata();
|
||||
const sections = parseSections();
|
||||
const metadata = loadMetadata(paths.metadataFile, paths.name);
|
||||
const sections = parseSections(paths.rulesDir);
|
||||
const sectionMap = generateSectionMap(sections);
|
||||
const skillTitle = skillNameToTitle(paths.name);
|
||||
|
||||
// Check if rules directory exists
|
||||
if (!existsSync(paths.rulesDir)) {
|
||||
console.log(` No rules directory found. Generating empty AGENTS.md.`);
|
||||
writeFileSync(
|
||||
paths.agentsOutput,
|
||||
`# ${skillTitle}\n\nNo rules defined yet.\n`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get all rule files
|
||||
const ruleFiles = readdirSync(RULES_DIR)
|
||||
const ruleFiles = readdirSync(paths.rulesDir)
|
||||
.filter((f) => f.endsWith(".md") && !f.startsWith("_"))
|
||||
.map((f) => join(RULES_DIR, f));
|
||||
.map((f) => join(paths.rulesDir, f));
|
||||
|
||||
if (ruleFiles.length === 0) {
|
||||
console.log("No rule files found. Generating empty AGENTS.md template.");
|
||||
console.log(` No rule files found. Generating empty AGENTS.md.`);
|
||||
}
|
||||
|
||||
// Parse and validate all rules
|
||||
@@ -206,7 +168,7 @@ function buildAgents(): void {
|
||||
const output: string[] = [];
|
||||
|
||||
// Header
|
||||
output.push("# Postgres Best Practices\n");
|
||||
output.push(`# ${skillTitle}\n`);
|
||||
output.push(`**Version ${metadata.version}**`);
|
||||
output.push(`${metadata.organization}`);
|
||||
output.push(`${metadata.date}\n`);
|
||||
@@ -307,8 +269,8 @@ function buildAgents(): void {
|
||||
}
|
||||
|
||||
// Write output
|
||||
writeFileSync(AGENTS_OUTPUT, output.join("\n"));
|
||||
console.log(`Generated: ${AGENTS_OUTPUT}`);
|
||||
writeFileSync(paths.agentsOutput, output.join("\n"));
|
||||
console.log(` Generated: ${paths.agentsOutput}`);
|
||||
console.log(` Total rules: ${rules.length}`);
|
||||
}
|
||||
|
||||
@@ -318,7 +280,35 @@ const isMainModule =
|
||||
process.argv[1]?.endsWith("build.js");
|
||||
|
||||
if (isMainModule) {
|
||||
buildAgents();
|
||||
const targetSkill = process.argv[2];
|
||||
|
||||
if (targetSkill) {
|
||||
// Build specific skill
|
||||
if (!validateSkillExists(targetSkill)) {
|
||||
console.error(`Error: Skill "${targetSkill}" not found in skills/`);
|
||||
const available = discoverSkills();
|
||||
if (available.length > 0) {
|
||||
console.error(`Available skills: ${available.join(", ")}`);
|
||||
}
|
||||
process.exit(1);
|
||||
}
|
||||
buildSkill(getSkillPaths(targetSkill));
|
||||
} else {
|
||||
// Build all skills
|
||||
const skills = discoverSkills();
|
||||
if (skills.length === 0) {
|
||||
console.log("No skills found in skills/ directory.");
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
export { buildAgents, parseSections };
|
||||
console.log(`Found ${skills.length} skill(s): ${skills.join(", ")}\n`);
|
||||
for (const skill of skills) {
|
||||
buildSkill(getSkillPaths(skill));
|
||||
console.log("");
|
||||
}
|
||||
}
|
||||
|
||||
console.log("✅ Done!");
|
||||
}
|
||||
|
||||
export { buildSkill, parseSections };
|
||||
59
packages/skills-build/src/config.ts
Normal file
59
packages/skills-build/src/config.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
import { existsSync, readdirSync } from "node:fs";
|
||||
import { dirname, join } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
|
||||
// Build package directory
|
||||
export const BUILD_DIR = join(__dirname, "..");
|
||||
|
||||
// Skills root directory
|
||||
export const SKILLS_ROOT = join(BUILD_DIR, "../../skills");
|
||||
|
||||
// Skill paths interface
|
||||
export interface SkillPaths {
|
||||
name: string;
|
||||
skillDir: string;
|
||||
rulesDir: string;
|
||||
agentsOutput: string;
|
||||
metadataFile: string;
|
||||
}
|
||||
|
||||
// Discover all valid skills (directories with metadata.json)
|
||||
export function discoverSkills(): string[] {
|
||||
if (!existsSync(SKILLS_ROOT)) return [];
|
||||
|
||||
return readdirSync(SKILLS_ROOT, { withFileTypes: true })
|
||||
.filter((d) => d.isDirectory())
|
||||
.filter((d) => existsSync(join(SKILLS_ROOT, d.name, "metadata.json")))
|
||||
.map((d) => d.name);
|
||||
}
|
||||
|
||||
// Get paths for a specific skill
|
||||
export function getSkillPaths(skillName: string): SkillPaths {
|
||||
const skillDir = join(SKILLS_ROOT, skillName);
|
||||
return {
|
||||
name: skillName,
|
||||
skillDir,
|
||||
rulesDir: join(skillDir, "rules"),
|
||||
agentsOutput: join(skillDir, "AGENTS.md"),
|
||||
metadataFile: join(skillDir, "metadata.json"),
|
||||
};
|
||||
}
|
||||
|
||||
// Validate skill exists
|
||||
export function validateSkillExists(skillName: string): boolean {
|
||||
const paths = getSkillPaths(skillName);
|
||||
return existsSync(paths.metadataFile);
|
||||
}
|
||||
|
||||
// Valid impact levels in priority order
|
||||
export const IMPACT_LEVELS = [
|
||||
"CRITICAL",
|
||||
"HIGH",
|
||||
"MEDIUM-HIGH",
|
||||
"MEDIUM",
|
||||
"LOW-MEDIUM",
|
||||
"LOW",
|
||||
] as const;
|
||||
@@ -1,7 +1,13 @@
|
||||
import { readdirSync } from "node:fs";
|
||||
import { existsSync, readdirSync } from "node:fs";
|
||||
import { basename, join } from "node:path";
|
||||
import { generateSectionMap, parseSections } from "./build.js";
|
||||
import { IMPACT_LEVELS, RULES_DIR } from "./config.js";
|
||||
import {
|
||||
discoverSkills,
|
||||
getSkillPaths,
|
||||
IMPACT_LEVELS,
|
||||
type SkillPaths,
|
||||
validateSkillExists,
|
||||
} from "./config.js";
|
||||
import { parseRuleFile } from "./parser.js";
|
||||
import type { ValidationResult } from "./types.js";
|
||||
|
||||
@@ -38,14 +44,17 @@ function isGoodExample(label: string): boolean {
|
||||
export function validateRuleFile(
|
||||
filePath: string,
|
||||
sectionMap?: Record<string, number>,
|
||||
rulesDir?: string,
|
||||
): ValidationResult {
|
||||
const errors: string[] = [];
|
||||
const warnings: string[] = [];
|
||||
|
||||
// Generate section map if not provided
|
||||
if (!sectionMap) {
|
||||
const sections = parseSections();
|
||||
if (!sectionMap && rulesDir) {
|
||||
const sections = parseSections(rulesDir);
|
||||
sectionMap = generateSectionMap(sections);
|
||||
} else if (!sectionMap) {
|
||||
sectionMap = {};
|
||||
}
|
||||
|
||||
const result = parseRuleFile(filePath, sectionMap);
|
||||
@@ -129,62 +138,45 @@ export function validateRuleFile(
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate all rule files in the rules directory
|
||||
* Validate all rule files for a skill
|
||||
*/
|
||||
export function validateAllRules(): {
|
||||
totalFiles: number;
|
||||
validFiles: number;
|
||||
invalidFiles: number;
|
||||
results: Map<string, ValidationResult>;
|
||||
} {
|
||||
const results = new Map<string, ValidationResult>();
|
||||
let validFiles = 0;
|
||||
let invalidFiles = 0;
|
||||
function validateSkill(paths: SkillPaths): boolean {
|
||||
console.log(`[${paths.name}] Validating...`);
|
||||
|
||||
// Check if rules directory exists
|
||||
if (!existsSync(paths.rulesDir)) {
|
||||
console.log(` No rules directory found.`);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get section map
|
||||
const sections = parseSections(paths.rulesDir);
|
||||
const sectionMap = generateSectionMap(sections);
|
||||
|
||||
// Get all markdown files (excluding _ prefixed files)
|
||||
const files = readdirSync(RULES_DIR)
|
||||
const files = readdirSync(paths.rulesDir)
|
||||
.filter((f) => f.endsWith(".md") && !f.startsWith("_"))
|
||||
.map((f) => join(RULES_DIR, f));
|
||||
.map((f) => join(paths.rulesDir, f));
|
||||
|
||||
if (files.length === 0) {
|
||||
console.log(` No rule files found.`);
|
||||
return true;
|
||||
}
|
||||
|
||||
let validFiles = 0;
|
||||
let invalidFiles = 0;
|
||||
let hasErrors = false;
|
||||
|
||||
for (const file of files) {
|
||||
const result = validateRuleFile(file);
|
||||
results.set(basename(file), result);
|
||||
const result = validateRuleFile(file, sectionMap, paths.rulesDir);
|
||||
const filename = basename(file);
|
||||
|
||||
if (result.valid) {
|
||||
validFiles++;
|
||||
} else {
|
||||
invalidFiles++;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
totalFiles: files.length,
|
||||
validFiles,
|
||||
invalidFiles,
|
||||
results,
|
||||
};
|
||||
}
|
||||
|
||||
// Run validation when executed directly
|
||||
const isMainModule =
|
||||
process.argv[1]?.endsWith("validate.ts") ||
|
||||
process.argv[1]?.endsWith("validate.js");
|
||||
|
||||
if (isMainModule) {
|
||||
console.log("Validating Postgres best practices rules...\n");
|
||||
|
||||
const { totalFiles, validFiles, invalidFiles, results } = validateAllRules();
|
||||
|
||||
if (totalFiles === 0) {
|
||||
console.log("No rule files found (this is expected for initial setup).");
|
||||
console.log("Create rule files in: skills/postgres-best-practices/rules/");
|
||||
console.log("Use the _template.md as a starting point.\n");
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
let hasErrors = false;
|
||||
|
||||
for (const [filename, result] of results) {
|
||||
if (!result.valid || result.warnings.length > 0) {
|
||||
console.log(`\n ${filename}:`);
|
||||
|
||||
@@ -199,16 +191,58 @@ if (isMainModule) {
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`\n${"=".repeat(50)}`);
|
||||
console.log(
|
||||
`Total: ${totalFiles} files | Valid: ${validFiles} | Invalid: ${invalidFiles}`,
|
||||
`\n Total: ${files.length} | Valid: ${validFiles} | Invalid: ${invalidFiles}`,
|
||||
);
|
||||
|
||||
if (hasErrors) {
|
||||
console.log("\nValidation failed. Please fix the errors above.");
|
||||
return !hasErrors;
|
||||
}
|
||||
|
||||
// Run validation when executed directly
|
||||
const isMainModule =
|
||||
process.argv[1]?.endsWith("validate.ts") ||
|
||||
process.argv[1]?.endsWith("validate.js");
|
||||
|
||||
if (isMainModule) {
|
||||
const targetSkill = process.argv[2];
|
||||
|
||||
if (targetSkill) {
|
||||
// Validate specific skill
|
||||
if (!validateSkillExists(targetSkill)) {
|
||||
console.error(`Error: Skill "${targetSkill}" not found in skills/`);
|
||||
const available = discoverSkills();
|
||||
if (available.length > 0) {
|
||||
console.error(`Available skills: ${available.join(", ")}`);
|
||||
}
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const valid = validateSkill(getSkillPaths(targetSkill));
|
||||
console.log(valid ? "\n✅ Validation passed!" : "\n❌ Validation failed.");
|
||||
process.exit(valid ? 0 : 1);
|
||||
} else {
|
||||
console.log("\nValidation passed!");
|
||||
// Validate all skills
|
||||
const skills = discoverSkills();
|
||||
if (skills.length === 0) {
|
||||
console.log("No skills found in skills/ directory.");
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
console.log(`Found ${skills.length} skill(s): ${skills.join(", ")}\n`);
|
||||
|
||||
let allValid = true;
|
||||
for (const skill of skills) {
|
||||
if (!validateSkill(getSkillPaths(skill))) {
|
||||
allValid = false;
|
||||
}
|
||||
console.log("");
|
||||
}
|
||||
|
||||
console.log(
|
||||
allValid ? "✅ All validations passed!" : "❌ Some validations failed.",
|
||||
);
|
||||
process.exit(allValid ? 0 : 1);
|
||||
}
|
||||
}
|
||||
|
||||
export { validateSkill };
|
||||
@@ -6,8 +6,7 @@ AI agents and LLMs.
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
# Install dependencies
|
||||
cd packages/postgres-best-practices-build
|
||||
# From repository root
|
||||
npm install
|
||||
|
||||
# Validate existing rules
|
||||
@@ -58,8 +57,8 @@ skills/postgres-best-practices/
|
||||
├── _contributing.md # Writing guidelines
|
||||
└── *.md # Individual rules
|
||||
|
||||
packages/postgres-best-practices-build/
|
||||
├── src/ # Build system source
|
||||
packages/skills-build/
|
||||
├── src/ # Generic build system source
|
||||
├── package.json # NPM scripts
|
||||
└── test-cases.json # [GENERATED] Test artifacts
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user