Add PocketBase collections, APIs & migration docs
Introduce PocketBase workflow support, migration tooling, server APIs and documentation. Adds a set of PocketBase collection JSONs (order_items, order_items_v2, collection_pool, delivery_notes, delivery_note_items, repairs) and a large import manifest for workflow collections; includes docs describing MCP/API layer, migration audit, order-item schema and rollout plans. Adds server-side agent/MCP endpoints and services (api/mcp, api/v1/orders, collection-pool, order-items status, health) plus helper modules (pocketbase-admin, orders-service, order-item-status, agent-auth) and a migration script to create order_items_v2/collection_pool. UI: new pages for collection-pool, delivery-notes, repairs and several updates to orders/quotes pages, sidebar, tooltip and pb helpers/types. Also updates package.json (migration script and related changes) and global styles. Required env vars and suggested migration command are documented (e.g. NEXT_PUBLIC_POCKETBASE_URL, PB_ADMIN_EMAIL, PB_ADMIN_PASSWORD, ORDER_ITEMS_COLLECTION; run npm run pb:migrate:orders-v2).
2026-05-25 16:39:33 +00:00
|
|
|
import PocketBase from "pocketbase";
|
|
|
|
|
|
2026-09-29 23:48:44 +00:00
|
|
|
import { resolveAuditHeaders } from "./audit-context";
|
|
|
|
|
|
Add PocketBase collections, APIs & migration docs
Introduce PocketBase workflow support, migration tooling, server APIs and documentation. Adds a set of PocketBase collection JSONs (order_items, order_items_v2, collection_pool, delivery_notes, delivery_note_items, repairs) and a large import manifest for workflow collections; includes docs describing MCP/API layer, migration audit, order-item schema and rollout plans. Adds server-side agent/MCP endpoints and services (api/mcp, api/v1/orders, collection-pool, order-items status, health) plus helper modules (pocketbase-admin, orders-service, order-item-status, agent-auth) and a migration script to create order_items_v2/collection_pool. UI: new pages for collection-pool, delivery-notes, repairs and several updates to orders/quotes pages, sidebar, tooltip and pb helpers/types. Also updates package.json (migration script and related changes) and global styles. Required env vars and suggested migration command are documented (e.g. NEXT_PUBLIC_POCKETBASE_URL, PB_ADMIN_EMAIL, PB_ADMIN_PASSWORD, ORDER_ITEMS_COLLECTION; run npm run pb:migrate:orders-v2).
2026-05-25 16:39:33 +00:00
|
|
|
const url = process.env.NEXT_PUBLIC_POCKETBASE_URL || "http://127.0.0.1:8090";
|
2026-08-05 21:00:54 +00:00
|
|
|
const ADMIN_TOKEN_REFRESH_BUFFER_MS = 60_000;
|
|
|
|
|
|
|
|
|
|
type CachedAdminAuth = {
|
|
|
|
|
token: string;
|
|
|
|
|
expiresAt: number;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let cachedAdminAuth: CachedAdminAuth | null = null;
|
|
|
|
|
|
|
|
|
|
function readJwtExpiryMs(token: string): number {
|
|
|
|
|
const parts = token.split(".");
|
|
|
|
|
if (parts.length < 2) return 0;
|
|
|
|
|
try {
|
|
|
|
|
const payload = JSON.parse(
|
|
|
|
|
Buffer.from(parts[1], "base64url").toString("utf8"),
|
|
|
|
|
) as { exp?: unknown };
|
|
|
|
|
if (typeof payload.exp !== "number" || !Number.isFinite(payload.exp)) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
return payload.exp * 1000;
|
|
|
|
|
} catch {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function buildPocketBaseWithCachedAuth(): PocketBase | null {
|
|
|
|
|
if (
|
|
|
|
|
!cachedAdminAuth ||
|
|
|
|
|
cachedAdminAuth.expiresAt <= Date.now() + ADMIN_TOKEN_REFRESH_BUFFER_MS
|
|
|
|
|
) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const pb = new PocketBase(url);
|
2026-08-09 14:17:29 +00:00
|
|
|
// Disable auto-cancellation. The PB SDK's default behaviour is to
|
|
|
|
|
// cancel every in-flight request whenever a new one starts — that
|
|
|
|
|
// works fine for sequential UI calls but breaks any service that
|
|
|
|
|
// fans out reads via Promise.all (e.g. `populateQuoteItemInsights`
|
|
|
|
|
// fires 8 PB queries in parallel and the SDK aborts the first 7 the
|
|
|
|
|
// moment the 8th starts). Safe for admin client: we don't have user
|
|
|
|
|
// cancellation semantics, and the requests are idempotent.
|
|
|
|
|
pb.autoCancellation(false);
|
2026-08-05 21:00:54 +00:00
|
|
|
if (pb.authStore && typeof pb.authStore.save === "function") {
|
|
|
|
|
pb.authStore.save(cachedAdminAuth.token);
|
|
|
|
|
return pb;
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function clearAdminPocketBaseAuthCache(): void {
|
|
|
|
|
cachedAdminAuth = null;
|
|
|
|
|
}
|
Add PocketBase collections, APIs & migration docs
Introduce PocketBase workflow support, migration tooling, server APIs and documentation. Adds a set of PocketBase collection JSONs (order_items, order_items_v2, collection_pool, delivery_notes, delivery_note_items, repairs) and a large import manifest for workflow collections; includes docs describing MCP/API layer, migration audit, order-item schema and rollout plans. Adds server-side agent/MCP endpoints and services (api/mcp, api/v1/orders, collection-pool, order-items status, health) plus helper modules (pocketbase-admin, orders-service, order-item-status, agent-auth) and a migration script to create order_items_v2/collection_pool. UI: new pages for collection-pool, delivery-notes, repairs and several updates to orders/quotes pages, sidebar, tooltip and pb helpers/types. Also updates package.json (migration script and related changes) and global styles. Required env vars and suggested migration command are documented (e.g. NEXT_PUBLIC_POCKETBASE_URL, PB_ADMIN_EMAIL, PB_ADMIN_PASSWORD, ORDER_ITEMS_COLLECTION; run npm run pb:migrate:orders-v2).
2026-05-25 16:39:33 +00:00
|
|
|
|
|
|
|
|
export async function getAdminPocketBase() {
|
|
|
|
|
const email = process.env.PB_ADMIN_EMAIL;
|
|
|
|
|
const password = process.env.PB_ADMIN_PASSWORD;
|
|
|
|
|
|
|
|
|
|
if (!email || !password) {
|
|
|
|
|
throw new Error("PB_ADMIN_EMAIL and PB_ADMIN_PASSWORD are required for server API operations.");
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-05 21:00:54 +00:00
|
|
|
const cachedPb = buildPocketBaseWithCachedAuth();
|
2026-09-29 23:48:44 +00:00
|
|
|
if (cachedPb) return withAuditHeaders(cachedPb);
|
2026-08-05 21:00:54 +00:00
|
|
|
|
Add PocketBase collections, APIs & migration docs
Introduce PocketBase workflow support, migration tooling, server APIs and documentation. Adds a set of PocketBase collection JSONs (order_items, order_items_v2, collection_pool, delivery_notes, delivery_note_items, repairs) and a large import manifest for workflow collections; includes docs describing MCP/API layer, migration audit, order-item schema and rollout plans. Adds server-side agent/MCP endpoints and services (api/mcp, api/v1/orders, collection-pool, order-items status, health) plus helper modules (pocketbase-admin, orders-service, order-item-status, agent-auth) and a migration script to create order_items_v2/collection_pool. UI: new pages for collection-pool, delivery-notes, repairs and several updates to orders/quotes pages, sidebar, tooltip and pb helpers/types. Also updates package.json (migration script and related changes) and global styles. Required env vars and suggested migration command are documented (e.g. NEXT_PUBLIC_POCKETBASE_URL, PB_ADMIN_EMAIL, PB_ADMIN_PASSWORD, ORDER_ITEMS_COLLECTION; run npm run pb:migrate:orders-v2).
2026-05-25 16:39:33 +00:00
|
|
|
const pb = new PocketBase(url);
|
2026-08-09 14:17:29 +00:00
|
|
|
// See buildPocketBaseWithCachedAuth — autoCancellation(false) so
|
|
|
|
|
// Promise.all fan-outs (e.g. populateQuoteItemInsights) don't get
|
|
|
|
|
// aborted mid-flight.
|
|
|
|
|
pb.autoCancellation(false);
|
2026-08-05 21:00:54 +00:00
|
|
|
const authData = await pb.collection("_superusers").authWithPassword(email, password);
|
|
|
|
|
cachedAdminAuth = {
|
|
|
|
|
token: authData.token,
|
|
|
|
|
expiresAt: readJwtExpiryMs(authData.token),
|
|
|
|
|
};
|
2026-09-29 23:48:44 +00:00
|
|
|
return withAuditHeaders(pb);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Stamp every PB request from this client with the X-Audit-* headers
|
|
|
|
|
* for the person the server is acting for, so the `audit_log` hook
|
|
|
|
|
* attributes admin-key writes to them. A fresh client is built per
|
|
|
|
|
* `getAdminPocketBase()` call, so the headers never leak across
|
|
|
|
|
* requests.
|
|
|
|
|
*/
|
|
|
|
|
async function withAuditHeaders(pb: PocketBase): Promise<PocketBase> {
|
|
|
|
|
let auditHeaders: Record<string, string> = {};
|
|
|
|
|
try {
|
|
|
|
|
auditHeaders = await resolveAuditHeaders();
|
|
|
|
|
} catch {
|
|
|
|
|
auditHeaders = {};
|
|
|
|
|
}
|
|
|
|
|
if (Object.keys(auditHeaders).length === 0) return pb;
|
|
|
|
|
pb.beforeSend = (url, options) => {
|
|
|
|
|
options.headers = { ...auditHeaders, ...(options.headers as Record<string, string> | undefined) };
|
|
|
|
|
return { url, options };
|
|
|
|
|
};
|
Add PocketBase collections, APIs & migration docs
Introduce PocketBase workflow support, migration tooling, server APIs and documentation. Adds a set of PocketBase collection JSONs (order_items, order_items_v2, collection_pool, delivery_notes, delivery_note_items, repairs) and a large import manifest for workflow collections; includes docs describing MCP/API layer, migration audit, order-item schema and rollout plans. Adds server-side agent/MCP endpoints and services (api/mcp, api/v1/orders, collection-pool, order-items status, health) plus helper modules (pocketbase-admin, orders-service, order-item-status, agent-auth) and a migration script to create order_items_v2/collection_pool. UI: new pages for collection-pool, delivery-notes, repairs and several updates to orders/quotes pages, sidebar, tooltip and pb helpers/types. Also updates package.json (migration script and related changes) and global styles. Required env vars and suggested migration command are documented (e.g. NEXT_PUBLIC_POCKETBASE_URL, PB_ADMIN_EMAIL, PB_ADMIN_PASSWORD, ORDER_ITEMS_COLLECTION; run npm run pb:migrate:orders-v2).
2026-05-25 16:39:33 +00:00
|
|
|
return pb;
|
2026-08-05 21:00:54 +00:00
|
|
|
}
|