@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
JavaScript
;
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