Files
wehub-resource-sync 409e92d6ae
Build and Push Docker Images / Build Docker Image (push) Has been cancelled
Build and Push Docker Images / Build Railway Docker Image (push) Has been cancelled
Build and Publish n8n Docker Image / test-image (push) Has been cancelled
Dependency Compatibility Check / Fresh Install Dependency Check (push) Has been cancelled
Build and Publish n8n Docker Image / build-and-push (push) Has been cancelled
Build and Publish n8n Docker Image / create-release (push) Has been cancelled
Automated Release / Detect Version Change (push) Has been cancelled
Automated Release / Generate Release Notes (push) Has been cancelled
Automated Release / Create GitHub Release (push) Has been cancelled
Automated Release / Package MCPB Bundle (push) Has been cancelled
Automated Release / Build and Verify (push) Has been cancelled
Automated Release / Publish to NPM (push) Has been cancelled
Automated Release / Build and Push Docker Images (push) Has been cancelled
Automated Release / Update Documentation (push) Has been cancelled
Automated Release / Notify Release Completion (push) Has been cancelled
Secret Scan / secretlint (push) Has been cancelled
Test Suite / test (push) Has been cancelled
Test Suite / cjs-runtime (push) Has been cancelled
Test Suite / publish-results (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:41:06 +08:00

75 lines
2.5 KiB
TypeScript

#!/usr/bin/env npx tsx
/**
* Copy markdown skill files from the sibling n8n-skills repo into
* data/skills/ so they ship inside the n8n-mcp npm/Docker artifacts.
*
* Source defaults to ../n8n-skills/skills relative to this repo root.
* Override with N8N_SKILLS_SOURCE.
*/
import { promises as fs } from 'fs';
import { existsSync } from 'fs';
import path from 'path';
const REPO_ROOT = path.resolve(__dirname, '..');
const CANDIDATE_SOURCES = [
path.resolve(REPO_ROOT, '..', 'n8n-skills', 'skills'),
path.resolve(REPO_ROOT, '..', '..', 'n8n-skills', 'skills'),
];
const SOURCE = process.env.N8N_SKILLS_SOURCE
? path.resolve(process.env.N8N_SKILLS_SOURCE)
: CANDIDATE_SOURCES.find((p) => existsSync(p)) ?? CANDIDATE_SOURCES[0];
const DEST = path.join(REPO_ROOT, 'data', 'skills');
async function copyMarkdownTree(src: string, dst: string): Promise<number> {
const entries = await fs.readdir(src, { withFileTypes: true });
let copied = 0;
await fs.mkdir(dst, { recursive: true });
for (const entry of entries) {
const srcPath = path.join(src, entry.name);
const dstPath = path.join(dst, entry.name);
if (entry.isDirectory()) {
// Skill-creator eval workspaces (skills/*-workspace/) are local debris,
// untracked in n8n-skills and excluded from its dist builds — skip them.
if (entry.name.endsWith('-workspace')) continue;
copied += await copyMarkdownTree(srcPath, dstPath);
} else if (entry.isFile() && entry.name.endsWith('.md')) {
await fs.copyFile(srcPath, dstPath);
copied++;
}
}
return copied;
}
async function clearDestination(dir: string): Promise<void> {
if (!existsSync(dir)) return;
for (const entry of await fs.readdir(dir, { withFileTypes: true })) {
if (entry.isDirectory()) {
await fs.rm(path.join(dir, entry.name), { recursive: true, force: true });
}
}
}
async function main(): Promise<void> {
console.log(`Syncing skills from: ${SOURCE}`);
console.log(` into: ${DEST}`);
if (!existsSync(SOURCE)) {
if (existsSync(DEST)) {
console.warn(`Source not found, keeping existing ${DEST} unchanged.`);
return;
}
console.error(`Source directory not found: ${SOURCE}`);
console.error('Set N8N_SKILLS_SOURCE or clone n8n-skills next to n8n-mcp.');
process.exit(1);
}
await clearDestination(DEST);
const count = await copyMarkdownTree(SOURCE, DEST);
console.log(`Synced ${count} markdown files.`);
}
main().catch((err) => {
console.error('sync-skills failed:', err);
process.exit(1);
});