UNPKG

@baruchiro/paperless-mcp

Version:

Model Context Protocol (MCP) server for interacting with Paperless-NGX document management system. Enables AI assistants to manage documents, tags, correspondents, and document types through the Paperless-NGX API.

165 lines (164 loc) 9.12 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const node_test_1 = require("node:test"); const strict_1 = __importDefault(require("node:assert/strict")); const selectFields_1 = require("./selectFields"); const LEGACY_SELECT_FIELD = { id: 2, name: "Retention period", data_type: "select", extra_data: { select_options: ["1 year", "7 years", "2 years"], default_currency: null }, document_count: 10, }; const OBJECT_SELECT_FIELD = { id: 3, name: "Priority", data_type: "select", extra_data: { select_options: [ { id: "abc123", label: "Low" }, { id: "def456", label: "High" }, ], }, document_count: 5, }; const STRING_FIELD = { id: 4, name: "Reference", data_type: "string", document_count: 1, }; (0, node_test_1.describe)("resolveSelectCustomFieldValue", () => { (0, node_test_1.test)("translates a label to its zero-based index (pre-2.17 string options)", () => { strict_1.default.equal((0, selectFields_1.resolveSelectCustomFieldValue)(LEGACY_SELECT_FIELD, "1 year"), 0); strict_1.default.equal((0, selectFields_1.resolveSelectCustomFieldValue)(LEGACY_SELECT_FIELD, "7 years"), 1); strict_1.default.equal((0, selectFields_1.resolveSelectCustomFieldValue)(LEGACY_SELECT_FIELD, "2 years"), 2); }); (0, node_test_1.test)("translates a label to its zero-based index (2.17+ object options)", () => { strict_1.default.equal((0, selectFields_1.resolveSelectCustomFieldValue)(OBJECT_SELECT_FIELD, "Low"), 0); strict_1.default.equal((0, selectFields_1.resolveSelectCustomFieldValue)(OBJECT_SELECT_FIELD, "High"), 1); }); (0, node_test_1.test)("passes through an already-encoded index (pre-2.17)", () => { strict_1.default.equal((0, selectFields_1.resolveSelectCustomFieldValue)(LEGACY_SELECT_FIELD, 1), 1); }); (0, node_test_1.test)("maps an option id back to its zero-based index (2.17+ round-trip)", () => { strict_1.default.equal((0, selectFields_1.resolveSelectCustomFieldValue)(OBJECT_SELECT_FIELD, "def456"), 1); }); (0, node_test_1.test)("resolves both the label and the option id to the same index", () => { strict_1.default.equal((0, selectFields_1.resolveSelectCustomFieldValue)(OBJECT_SELECT_FIELD, "Low"), 0); strict_1.default.equal((0, selectFields_1.resolveSelectCustomFieldValue)(OBJECT_SELECT_FIELD, "abc123"), 0); }); (0, node_test_1.test)("returns null unchanged so the field can be cleared", () => { strict_1.default.equal((0, selectFields_1.resolveSelectCustomFieldValue)(LEGACY_SELECT_FIELD, null), null); }); (0, node_test_1.test)("leaves non-select field values untouched", () => { strict_1.default.equal((0, selectFields_1.resolveSelectCustomFieldValue)(STRING_FIELD, "1 year"), "1 year"); }); (0, node_test_1.test)("throws an actionable error listing valid options for an unknown value", () => { strict_1.default.throws(() => (0, selectFields_1.resolveSelectCustomFieldValue)(LEGACY_SELECT_FIELD, "forever"), (err) => { strict_1.default.match(err.message, /forever/); strict_1.default.match(err.message, /Retention period/); strict_1.default.match(err.message, /1 year/); strict_1.default.match(err.message, /7 years/); return true; }); }); (0, node_test_1.test)("rejects an out-of-range index rather than forwarding it", () => { strict_1.default.throws(() => (0, selectFields_1.resolveSelectCustomFieldValue)(LEGACY_SELECT_FIELD, 9)); }); (0, node_test_1.test)("throws on a value that matches one option's label and another's id", () => { const collidingField = { id: 5, name: "Collision", data_type: "select", extra_data: { select_options: [ { id: "High", label: "Low" }, { id: "xyz789", label: "High" }, ], }, document_count: 0, }; strict_1.default.throws(() => (0, selectFields_1.resolveSelectCustomFieldValue)(collidingField, "High"), /Ambiguous/); }); }); (0, node_test_1.describe)("resolveSelectCustomFieldValue with stored encoding (bulk_edit path)", () => { (0, node_test_1.test)("translates a label to the option id on 2.17+ object options", () => { strict_1.default.equal((0, selectFields_1.resolveSelectCustomFieldValue)(OBJECT_SELECT_FIELD, "Low", "stored"), "abc123"); strict_1.default.equal((0, selectFields_1.resolveSelectCustomFieldValue)(OBJECT_SELECT_FIELD, "High", "stored"), "def456"); }); (0, node_test_1.test)("translates a label to the index on pre-2.17 string options (no id to store)", () => { strict_1.default.equal((0, selectFields_1.resolveSelectCustomFieldValue)(LEGACY_SELECT_FIELD, "7 years", "stored"), 1); }); (0, node_test_1.test)("passes an already-stored option id through unchanged", () => { strict_1.default.equal((0, selectFields_1.resolveSelectCustomFieldValue)(OBJECT_SELECT_FIELD, "def456", "stored"), "def456"); }); (0, node_test_1.test)("maps an option index to its stored id (2.17+)", () => { strict_1.default.equal((0, selectFields_1.resolveSelectCustomFieldValue)(OBJECT_SELECT_FIELD, 1, "stored"), "def456"); }); }); function apiReturning(fields) { const requestedIds = []; const fieldMap = new Map(fields.map((field) => [field.id, field])); const api = { getCustomField: (id) => __awaiter(this, void 0, void 0, function* () { requestedIds.push(id); const field = fieldMap.get(id); if (!field) throw new Error(`custom field ${id} not found`); return field; }), }; return { api, requestedIds }; } (0, node_test_1.describe)("resolveSelectCustomFieldValues", () => { (0, node_test_1.test)("returns undefined/empty input unchanged without fetching definitions", () => __awaiter(void 0, void 0, void 0, function* () { const { api, requestedIds } = apiReturning([]); strict_1.default.equal(yield (0, selectFields_1.resolveSelectCustomFieldValues)(api, undefined), undefined); strict_1.default.deepEqual(yield (0, selectFields_1.resolveSelectCustomFieldValues)(api, []), []); strict_1.default.deepEqual(requestedIds, []); })); (0, node_test_1.test)("resolves select labels and leaves other fields untouched", () => __awaiter(void 0, void 0, void 0, function* () { const { api } = apiReturning([LEGACY_SELECT_FIELD, STRING_FIELD]); const resolved = yield (0, selectFields_1.resolveSelectCustomFieldValues)(api, [ { field: 2, value: "2 years" }, { field: 4, value: "INV-001" }, ]); strict_1.default.deepEqual(resolved, [ { field: 2, value: 2 }, { field: 4, value: "INV-001" }, ]); })); (0, node_test_1.test)("applies the stored encoding (option id) when requested", () => __awaiter(void 0, void 0, void 0, function* () { const { api } = apiReturning([OBJECT_SELECT_FIELD]); const resolved = yield (0, selectFields_1.resolveSelectCustomFieldValues)(api, [{ field: 3, value: "High" }], "stored"); strict_1.default.deepEqual(resolved, [{ field: 3, value: "def456" }]); })); (0, node_test_1.test)("fetches each referenced field definition only once", () => __awaiter(void 0, void 0, void 0, function* () { const { api, requestedIds } = apiReturning([LEGACY_SELECT_FIELD]); yield (0, selectFields_1.resolveSelectCustomFieldValues)(api, [ { field: 2, value: "1 year" }, { field: 2, value: "7 years" }, ]); strict_1.default.deepEqual(requestedIds, [2]); })); (0, node_test_1.test)("passes the value through when the field definition cannot be fetched", () => __awaiter(void 0, void 0, void 0, function* () { const { api } = apiReturning([]); const resolved = yield (0, selectFields_1.resolveSelectCustomFieldValues)(api, [ { field: 99, value: "whatever" }, ]); strict_1.default.deepEqual(resolved, [{ field: 99, value: "whatever" }]); })); });