UNPKG

@ankimcp/anki-mcp-server

Version:

Model Context Protocol server for Anki - enables AI assistants to interact with your Anki flashcards

112 lines • 3.97 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.createDeck = createDeck; async function createDeck(params, client) { const { deckName } = params; const parts = deckName.split("::"); if (parts.length > 2) { throw new Error("Deck name can have maximum 2 levels (parent::child)"); } const normalizedParts = normalizeDeckName(deckName).split("::"); if (normalizedParts.some((part) => part === "")) { throw new Error("Deck name parts cannot be empty"); } const existingDecks = await client.invoke("deckNamesAndIds"); const findExisting = (name) => { const key = deckNameKey(name); return Object.entries(existingDecks).find(([existingName]) => deckNameKey(existingName) === key); }; const existingResult = ([storedName, storedId]) => { const result = { success: true, deckId: storedId, deckName: storedName, message: `Deck "${storedName}" already exists; nothing was created`, created: false, exists: true, }; if (parts.length === 2) { const [storedParent, storedChild] = storedName.split("::"); result.parentDeck = storedParent; result.childDeck = storedChild; result.parentExisted = true; } return result; }; const existingDeck = findExisting(deckName); if (existingDeck) { return existingResult(existingDeck); } const deckId = await client.invoke("createDeck", { deck: deckName, }); if (!deckId) { throw new Error("Failed to create deck - unknown error"); } const existingById = Object.entries(existingDecks).find(([, id]) => id === deckId); if (existingById) { return existingResult(existingById); } const storedName = await lookupStoredName(client, deckId); let parentName; let childName; let parentExisted; let resolvedName; if (storedName !== undefined) { resolvedName = storedName; if (parts.length === 2) { [parentName, childName] = storedName.split("::"); parentExisted = Object.hasOwn(existingDecks, parentName); } } else { const existingParent = parts.length === 2 ? findExisting(parts[0]) : undefined; if (parts.length === 2) { parentName = existingParent ? existingParent[0] : normalizedParts[0]; childName = normalizedParts[1]; parentExisted = existingParent !== undefined; } resolvedName = parentName !== undefined ? `${parentName}::${childName}` : normalizedParts[0]; } const result = { success: true, deckId: deckId, deckName: resolvedName, message: `Successfully created deck "${resolvedName}"`, created: true, }; if (parentName !== undefined && childName !== undefined) { result.parentDeck = parentName; result.childDeck = childName; result.parentExisted = parentExisted; result.message = parentExisted ? `Found existing parent deck "${parentName}"; created child deck "${childName}"` : `Created parent deck "${parentName}" and child deck "${childName}"`; } return result; } async function lookupStoredName(client, deckId) { try { const decks = await client.invoke("deckNamesAndIds"); return Object.entries(decks ?? {}).find(([, id]) => id === deckId)?.[0]; } catch { return undefined; } } function normalizeDeckName(name) { return name .split("::") .map((part) => part .normalize("NFC") .replace(/[\u0000-\u001f\u007f]/gu, "") .replace(/^[\s:]+|[\s:]+$/gu, "")) .join("::"); } function deckNameKey(name) { return normalizeDeckName(name).toLowerCase(); } //# sourceMappingURL=createDeck.action.js.map