feat(skills): add SQLite/SQL detection, SQL optimization pack, and Redis pack
- Scan project root for *.sqlite/*.sqlite3/*.db files → synthetic *.sqlite marker - Scan for *.sql files (migrations, schemas, seeds) → synthetic *.sql marker - Add SQL Optimization & Review pack (github/awesome-copilot): sql-optimization (7.8K installs) and sql-code-review (7.6K installs) — covers SQL injection prevention, parameterized queries, index strategy, anti-patterns. Triggers on *.sql, *.sqlite, or any database ORM config (Prisma, Supabase, Drizzle). - Add Redis pack (redis/agent-skills): redis-development. Triggers on redis.conf. - Add redis.conf to PROJECT_FILES. - 4 new detection tests for SQLite/SQL file scanning.
This commit is contained in:
parent
e48538b70d
commit
a30b125020
3 changed files with 88 additions and 0 deletions
|
|
@ -104,12 +104,19 @@ export const PROJECT_FILES = [
|
|||
"supabase/config.toml",
|
||||
"drizzle.config.ts",
|
||||
"drizzle.config.js",
|
||||
"redis.conf",
|
||||
// React Native markers
|
||||
"metro.config.js",
|
||||
"metro.config.ts",
|
||||
"react-native.config.js",
|
||||
] as const;
|
||||
|
||||
/** File extensions that indicate SQLite databases in the project. */
|
||||
const SQLITE_EXTENSIONS = [".sqlite", ".sqlite3", ".db"] as const;
|
||||
|
||||
/** File extensions that indicate SQL usage (migrations, schemas, seeds). */
|
||||
const SQL_EXTENSIONS = [".sql"] as const;
|
||||
|
||||
const LANGUAGE_MAP: Record<string, string> = {
|
||||
"package.json": "javascript/typescript",
|
||||
"Cargo.toml": "rust",
|
||||
|
|
@ -282,6 +289,21 @@ export function detectProjectSignals(basePath: string): ProjectSignals {
|
|||
}
|
||||
}
|
||||
|
||||
// SQLite / SQL file detection — scan root entries for database file extensions.
|
||||
// Adds synthetic markers (e.g. "*.sqlite", "*.sql") to detectedFiles so
|
||||
// skill catalog matchFiles can reference them.
|
||||
try {
|
||||
const rootEntries = readdirSync(basePath);
|
||||
if (rootEntries.some((e) => SQLITE_EXTENSIONS.some((ext) => e.endsWith(ext)))) {
|
||||
detectedFiles.push("*.sqlite");
|
||||
}
|
||||
if (rootEntries.some((e) => SQL_EXTENSIONS.some((ext) => e.endsWith(ext)))) {
|
||||
detectedFiles.push("*.sql");
|
||||
}
|
||||
} catch {
|
||||
// unreadable root — skip extension scan
|
||||
}
|
||||
|
||||
// Git repo detection
|
||||
const isGitRepo = existsSync(join(basePath, ".git"));
|
||||
|
||||
|
|
|
|||
|
|
@ -248,6 +248,27 @@ export const SKILL_CATALOG: SkillPack[] = [
|
|||
skills: ["supabase-postgres-best-practices"],
|
||||
matchFiles: ["supabase/config.toml"],
|
||||
},
|
||||
{
|
||||
label: "SQL Optimization & Review",
|
||||
description: "Universal SQL performance optimization, security (injection prevention), and code review",
|
||||
repo: "github/awesome-copilot",
|
||||
skills: ["sql-optimization", "sql-code-review"],
|
||||
matchFiles: [
|
||||
"*.sql",
|
||||
"*.sqlite",
|
||||
"prisma/schema.prisma",
|
||||
"supabase/config.toml",
|
||||
"drizzle.config.ts",
|
||||
"drizzle.config.js",
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "Redis",
|
||||
description: "Redis development patterns and best practices",
|
||||
repo: "redis/agent-skills",
|
||||
skills: ["redis-development"],
|
||||
matchFiles: ["redis.conf"],
|
||||
},
|
||||
// ── Cloud Platforms ────────────────────────────────────────────────────────
|
||||
{
|
||||
label: "Firebase",
|
||||
|
|
|
|||
|
|
@ -396,3 +396,48 @@ test("detectProjectSignals: Makefile with test target", () => {
|
|||
cleanup(dir);
|
||||
}
|
||||
});
|
||||
|
||||
test("detectProjectSignals: SQLite file detection via extensions", () => {
|
||||
const dir = makeTempDir("signals-sqlite");
|
||||
try {
|
||||
writeFileSync(join(dir, "app.sqlite3"), "", "utf-8");
|
||||
const signals = detectProjectSignals(dir);
|
||||
assert.ok(signals.detectedFiles.includes("*.sqlite"), "should add synthetic *.sqlite marker");
|
||||
} finally {
|
||||
cleanup(dir);
|
||||
}
|
||||
});
|
||||
|
||||
test("detectProjectSignals: SQL file detection", () => {
|
||||
const dir = makeTempDir("signals-sql");
|
||||
try {
|
||||
writeFileSync(join(dir, "migrations.sql"), "", "utf-8");
|
||||
const signals = detectProjectSignals(dir);
|
||||
assert.ok(signals.detectedFiles.includes("*.sql"), "should add synthetic *.sql marker");
|
||||
} finally {
|
||||
cleanup(dir);
|
||||
}
|
||||
});
|
||||
|
||||
test("detectProjectSignals: .db file triggers SQLite detection", () => {
|
||||
const dir = makeTempDir("signals-db");
|
||||
try {
|
||||
writeFileSync(join(dir, "data.db"), "", "utf-8");
|
||||
const signals = detectProjectSignals(dir);
|
||||
assert.ok(signals.detectedFiles.includes("*.sqlite"), "should add synthetic *.sqlite marker for .db files");
|
||||
} finally {
|
||||
cleanup(dir);
|
||||
}
|
||||
});
|
||||
|
||||
test("detectProjectSignals: no SQLite markers without matching files", () => {
|
||||
const dir = makeTempDir("signals-no-sqlite");
|
||||
try {
|
||||
writeFileSync(join(dir, "package.json"), "{}", "utf-8");
|
||||
const signals = detectProjectSignals(dir);
|
||||
assert.ok(!signals.detectedFiles.includes("*.sqlite"), "should not have *.sqlite marker");
|
||||
assert.ok(!signals.detectedFiles.includes("*.sql"), "should not have *.sql marker");
|
||||
} finally {
|
||||
cleanup(dir);
|
||||
}
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue