import type { PluginManifest } from '@@/plugins/manifest'; /** * Invoices — your InvoiceShelf books, inside Officer. * * ── Why `invoices` and not `invoiceshelf` ── * * The appName is THE id: it drives the API prefix, the frontend route, the table prefix, the sidecar * suffix and the install key, all at once. Before extraction those had drifted apart — the API was * `/api/invoiceshelf` while the screen was `/invoices` — and a plugin cannot hold both. * * Named for what it shows rather than the daemon behind it, so the URL a person sees stays `/invoices`. * The cost was renaming `invoiceshelf_accounts` to `invoices_accounts` to satisfy the table-prefix rule, * which was free here because the table existed on no server. Had there been rows, keeping the vendor * name would have been the better trade. * * ── What this plugin is, and what it is not ── * * It does not install or supervise InvoiceShelf, and it holds no books. You point it at an instance and * it speaks that API on your behalf, holding the credentials server-side. * * ── Where the connection lives ── * * In this plugin's own `invoices_accounts` — a registry, like photos and jellyfin, because one person * really does keep more than one company's books. Label, URL, encrypted credential, one active. * * ── No `osDependencies` ── * * Nothing shells out. The sidecar speaks InvoiceShelf's HTTP API over `fetch`. */ export const manifest: PluginManifest = { publisher: 'officerdev', version: '2026.08.27.01', platform: '>=1.0.0', label: 'Invoices', summary: 'InvoiceShelf books — invoices, estimates, customers and payments', /** running your own affairs. */ tags: ['Personal'], icon: 'ReceiptText', color: '#0ea5e9', permissions: [ { key: 'invoices', label: 'Invoices', description: 'InvoiceShelf books', }, ], };