Eigene Plugins entwickeln
Das SDK kann mit eigenen Content-Source und Auth-Plugins erweitert werden.
Content-Source-Plugin
Laedt Dateien aus einer externen Quelle (z.B. Confluence, S3, Datenbank).
Interface
interface ContentSourcePlugin {
name: string;
fetch(config: Record<string, unknown>): Promise<FetchResult>;
validate?(config: Record<string, unknown>): boolean;
}
interface FetchResult {
files: FetchedFile[];
stats: FetchStats;
}
interface FetchedFile {
path: string; // Relativer Pfad
content: string; // Datei-Inhalt
collection: string; // Ziel-Collection
metadata?: Record<string, unknown>;
}Beispiel: Confluence
import type { ContentSourcePlugin, FetchResult } from '@processcube-io/qmd-search';
export const confluenceSource: ContentSourcePlugin = {
name: 'confluence',
validate(config) {
return typeof config.baseUrl === 'string'
&& typeof config.spaceKey === 'string';
},
async fetch(config): Promise<FetchResult> {
const { baseUrl, spaceKey, token } = config as {
baseUrl: string; spaceKey: string; token: string;
};
const res = await fetch(
`${baseUrl}/rest/api/content?spaceKey=${spaceKey}&expand=body.storage`,
{ headers: { Authorization: `Bearer ${token}` } },
);
const data = await res.json();
return {
files: data.results.map((page: any) => ({
path: `${page.title.toLowerCase().replace(/\s+/g, '-')}.md`,
content: page.body.storage.value,
collection: spaceKey.toLowerCase(),
})),
stats: { fetched: data.results.length, failed: 0, skipped: 0 },
};
},
};Registrierung
import { createIndexer } from '@processcube-io/qmd-search';
import { confluenceSource } from './confluence-source';
const indexer = createIndexer({
dbPath: './data/index.sqlite',
collections: [
{ name: 'wiki', path: './wiki', pattern: '**/*.md', context: 'Wiki' },
],
contentSources: [
{ plugin: 'confluence', config: {
baseUrl: 'https://wiki.example.com',
spaceKey: 'DOCS',
token: process.env.CONFLUENCE_TOKEN,
}},
],
plugins: [confluenceSource],
});Auth-Plugin
Prueft API-Keys fuer den Standalone-Server.
Interface
interface AuthPlugin {
name: string;
resolve(req: Request): Promise<AuthResult>;
}
interface AuthResult {
valid: boolean;
customerId?: string;
scopes?: string[];
error?: string;
}Beispiel: JWT-Validierung
import type { AuthPlugin, AuthResult } from '@processcube-io/qmd-search';
export function createJwtAuth(secret: string): AuthPlugin {
return {
name: 'jwt',
async resolve(req: Request): Promise<AuthResult> {
const auth = req.headers.get('authorization');
if (!auth?.startsWith('Bearer ')) {
return { valid: false, error: 'Bearer Token erwartet' };
}
try {
// JWT verifizieren (z.B. mit jose)
const token = auth.slice(7);
const payload = await verifyJwt(token, secret);
return {
valid: true,
customerId: payload.sub,
scopes: payload.scopes,
};
} catch {
return { valid: false, error: 'Ungueltiger Token' };
}
},
};
}Verwendung
import { startServer } from '@processcube-io/qmd-search/adapters/standalone';
import { createJwtAuth } from './jwt-auth';
await startServer(store, {
auth: createJwtAuth(process.env.JWT_SECRET!),
});Beispiel: REST-API als Content-Source
Zeigt wie eine beliebige REST-API als Datenquelle angebunden werden kann:
import type { ContentSourcePlugin, FetchResult } from '@processcube-io/qmd-search';
export const restApiSource: ContentSourcePlugin = {
name: 'rest-api',
async fetch(config): Promise<FetchResult> {
const { baseUrl, endpoint, collection, headers } = config as {
baseUrl: string; endpoint: string; collection: string;
headers?: Record<string, string>;
};
const res = await fetch(`${baseUrl}${endpoint}`, { headers });
if (!res.ok) {
return { files: [], stats: { fetched: 0, failed: 1, skipped: 0 } };
}
const items = await res.json() as { id: string; title: string; content: string }[];
return {
files: items.map((item) => ({
path: `${item.id}.md`,
content: `# ${item.title}\n\n${item.content}`,
collection,
})),
stats: { fetched: items.length, failed: 0, skipped: 0 },
};
},
};
// Verwendung:
// { plugin: 'rest-api', config: {
// baseUrl: 'https://api.example.com',
// endpoint: '/articles',
// collection: 'articles',
// headers: { Authorization: 'Bearer ...' },
// }}Built-in Plugins
| Plugin | Typ | Import |
|---|---|---|
filesystemSource | Content-Source | @processcube-io/qmd-search |
githubSource | Content-Source | @processcube-io/qmd-search |
createEnvAuth() | Auth | @processcube-io/qmd-search/auth/env-auth |
createOdooAuth() | Auth | @processcube-io/qmd-search/auth/odoo-auth |