fix(type-checker): remove as casts hiding type-errors thus bugs. Solve subsequent found bugs

This commit is contained in:
Jakob Schlanstedt 2025-10-30 18:07:21 +01:00
parent aada631c0f
commit 470d7eee31
11 changed files with 60 additions and 39 deletions

View File

@ -26,7 +26,7 @@ export default class Entrypoints extends Component {
async createNoteIntoInboxCommand() { async createNoteIntoInboxCommand() {
await noteCreateService.createNote( await noteCreateService.createNote(
{ target: "inbox" } as CreateNoteIntoInboxOpts { target: "inbox" }
); );
} }

View File

@ -55,7 +55,7 @@ export default class MainTreeExecutors extends Component {
isProtected: activeNoteContext.note.isProtected, isProtected: activeNoteContext.note.isProtected,
saveSelection: false, saveSelection: false,
promptForType: false, promptForType: false,
} as CreateNoteWithUrlOpts }
); );
} }
@ -84,7 +84,7 @@ export default class MainTreeExecutors extends Component {
targetBranchId: node.data.branchId, targetBranchId: node.data.branchId,
isProtected: isProtected, isProtected: isProtected,
saveSelection: false saveSelection: false
} as CreateNoteWithUrlOpts }
); );
} }
} }

View File

@ -250,7 +250,7 @@ export default class RootCommandExecutor extends Component {
messages: [], messages: [],
title: "New AI Chat" title: "New AI Chat"
}), }),
} as CreateNoteWithUrlOpts }
); );
if (!result.note) { if (!result.note) {

View File

@ -293,7 +293,7 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
isProtected: isProtected, isProtected: isProtected,
templateNoteId: templateNoteId, templateNoteId: templateNoteId,
promptForType: false, promptForType: false,
} as CreateNoteWithUrlOpts }
); );
} else if (command === "insertChildNote") { } else if (command === "insertChildNote") {
const parentNotePath = treeService.getNotePath(this.node); const parentNotePath = treeService.getNotePath(this.node);
@ -306,7 +306,7 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
isProtected: this.node.data.isProtected, isProtected: this.node.data.isProtected,
templateNoteId: templateNoteId, templateNoteId: templateNoteId,
promptForType: false, promptForType: false,
} as CreateNoteWithUrlOpts }
); );
} else if (command === "openNoteInSplit") { } else if (command === "openNoteInSplit") {
const subContexts = appContext.tabManager.getActiveContext()?.getSubContexts(); const subContexts = appContext.tabManager.getActiveContext()?.getSubContexts();

View File

@ -48,7 +48,14 @@ type PromptingRule = {
type?: never; type?: never;
} | { } | {
promptForType?: false; promptForType?: false;
type: string; /**
* The note type (e.g. "text", "code", "image", "mermaid", etc.).
*
* If omitted, the server will automatically default to `"text"`.
* TypeScript still enforces explicit typing unless `promptForType` is true,
* to encourage clarity at the call site.
*/
type?: string;
}; };
@ -120,16 +127,15 @@ async function createNote(
resolvedOptions = maybeResolvedOptions; resolvedOptions = maybeResolvedOptions;
} }
if (resolvedOptions.target === "inbox") {
return createNoteIntoInbox(resolvedOptions);
}
// Only "into" | "before" | "after". the possibility of "inbox" was resolved switch(resolvedOptions.target) {
// a line above case "inbox":
return createNoteWithUrl( return createNoteIntoInbox(resolvedOptions);
resolvedOptions.target as "into" | "before" | "after", case "into":
resolvedOptions case "before":
); case "after":
return createNoteWithUrl(resolvedOptions.target, resolvedOptions);
}
} }
async function promptForType( async function promptForType(
@ -141,12 +147,12 @@ async function promptForType(
return null; return null;
} }
let resolvedOptions = { let resolvedOptions: CreateNoteOpts = {
...options, ...options,
promptForType: false, promptForType: false,
type: noteType, type: noteType,
templateNoteId, templateNoteId,
} as CreateNoteOpts; };
if (notePath) { if (notePath) {
resolvedOptions = resolvedOptions as CreateNoteWithUrlOpts; resolvedOptions = resolvedOptions as CreateNoteWithUrlOpts;
@ -154,7 +160,7 @@ async function promptForType(
...resolvedOptions, ...resolvedOptions,
target: "into", target: "into",
parentNoteUrl: notePath, parentNoteUrl: notePath,
} as CreateNoteWithUrlOpts; };
} }
return resolvedOptions; return resolvedOptions;
@ -269,7 +275,7 @@ async function createNoteIntoInbox(
...options, ...options,
target: "into", target: "into",
parentNoteUrl: inboxNote.noteId, parentNoteUrl: inboxNote.noteId,
} as CreateNoteWithUrlOpts }
); );
return result; return result;

View File

@ -44,7 +44,7 @@ export default class BoardApi {
parentNoteUrl: parentNotePath, parentNoteUrl: parentNotePath,
activate: false, activate: false,
title, title,
} as CreateNoteWithUrlOpts); });
if (newNote && newBranch) { if (newNote && newBranch) {
await this.changeColumn(newNote.noteId, column); await this.changeColumn(newNote.noteId, column);
@ -150,7 +150,7 @@ export default class BoardApi {
activate: false, activate: false,
targetBranchId: relativeToBranchId, targetBranchId: relativeToBranchId,
title: t("board_view.new-item"), title: t("board_view.new-item"),
} as CreateNoteWithUrlOpts }
); );
if (!note || !branch) { if (!note || !branch) {

View File

@ -184,9 +184,10 @@ export function showRowContextMenu(parentComponent: Component, e: MouseEvent, ro
handler: () => parentComponent?.triggerCommand("addNewRow", { handler: () => parentComponent?.triggerCommand("addNewRow", {
parentNotePath: parentNoteId, parentNotePath: parentNoteId,
customOpts: { customOpts: {
parentNoteUrl: parentNoteId,
target: "before", target: "before",
targetBranchId: rowData.branchId, targetBranchId: rowData.branchId,
} as CreateNoteWithUrlOpts }
}) })
}, },
{ {
@ -195,12 +196,16 @@ export function showRowContextMenu(parentComponent: Component, e: MouseEvent, ro
handler: async () => { handler: async () => {
const branchId = row.getData().branchId; const branchId = row.getData().branchId;
const note = await froca.getBranch(branchId)?.getNote(); const note = await froca.getBranch(branchId)?.getNote();
if (!note) {
return;
}
parentComponent?.triggerCommand("addNewRow", { parentComponent?.triggerCommand("addNewRow", {
parentNotePath: note?.noteId, parentNotePath: note.noteId,
customOpts: { customOpts: {
parentNoteUrl: note.noteId,
target: "after", target: "after",
targetBranchId: branchId, targetBranchId: branchId,
} as CreateNoteWithUrlOpts }
}); });
} }
}, },
@ -211,9 +216,10 @@ export function showRowContextMenu(parentComponent: Component, e: MouseEvent, ro
handler: () => parentComponent?.triggerCommand("addNewRow", { handler: () => parentComponent?.triggerCommand("addNewRow", {
parentNotePath: parentNoteId, parentNotePath: parentNoteId,
customOpts: { customOpts: {
parentNoteUrl: parentNoteId,
target: "after", target: "after",
targetBranchId: rowData.branchId, targetBranchId: rowData.branchId,
} as CreateNoteWithUrlOpts }
}) })
}, },
{ kind: "separator" }, { kind: "separator" },

View File

@ -19,11 +19,18 @@ export default function useRowTableEditing(api: RefObject<Tabulator>, attributeD
activate: false, activate: false,
...customOpts ...customOpts
} }
// Normalize "inbox" targets into standard path-based creation.
// When adding a new row, we always have a concrete parent path (`notePath`),
// so even if the originating command requested an "inbox" creation,
// it should instead behave as "into" under the current note.
const normalizedOpts: CreateNoteWithUrlOpts =
opts.target === "inbox"
? { ...opts, target: "into", parentNoteUrl: notePath }
: { ...opts, parentNoteUrl: notePath };
note_create.createNote( note_create.createNote(
{ normalizedOpts
parentNoteUrl: notePath,
...opts
} as CreateNoteWithUrlOpts
).then(({ branch }) => { ).then(({ branch }) => {
if (branch) { if (branch) {
setTimeout(() => { setTimeout(() => {

View File

@ -29,12 +29,14 @@ export default function MobileDetailMenu() {
], ],
selectMenuItemHandler: async ({ command }) => { selectMenuItemHandler: async ({ command }) => {
if (command === "insertChildNote") { if (command === "insertChildNote") {
note_create.createNote( const parentNoteUrl = appContext.tabManager.getActiveContextNotePath();
{
if (parentNoteUrl) {
note_create.createNote({
target: "into", target: "into",
parentNoteUrl: appContext.tabManager.getActiveContextNotePath() ?? undefined parentNoteUrl,
} as CreateNoteWithUrlOpts });
); }
} else if (command === "delete") { } else if (command === "delete") {
const notePath = appContext.tabManager.getActiveContextNotePath(); const notePath = appContext.tabManager.getActiveContextNotePath();
if (!notePath) { if (!notePath) {

View File

@ -229,7 +229,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
target: "into", target: "into",
parentNoteUrl: parentNotePath, parentNoteUrl: parentNotePath,
isProtected: node.data.isProtected isProtected: node.data.isProtected
} as CreateNoteWithUrlOpts, },
); );
} else if (target.classList.contains("enter-workspace-button")) { } else if (target.classList.contains("enter-workspace-button")) {
const node = $.ui.fancytree.getNode(e as unknown as Event); const node = $.ui.fancytree.getNode(e as unknown as Event);
@ -1847,7 +1847,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
target: "into", target: "into",
parentNoteUrl: notePath, parentNoteUrl: notePath,
isProtected: node.data.isProtected isProtected: node.data.isProtected
} as CreateNoteWithUrlOpts }
) )
} }
}), }),

View File

@ -266,7 +266,7 @@ export default function AttributeEditor({ api, note, componentId, notePath, ntxI
target: "inbox", target: "inbox",
title, title,
activate: false activate: false
} as CreateNoteIntoInboxOpts }
); );
return note?.getBestNotePathString() ?? ""; return note?.getBestNotePathString() ?? "";
} }
@ -280,7 +280,7 @@ export default function AttributeEditor({ api, note, componentId, notePath, ntxI
title, title,
activate: false, activate: false,
promptForType: true, promptForType: true,
} as CreateNoteWithUrlOpts, },
) )
return resp?.note?.getBestNotePathString() ?? ""; return resp?.note?.getBestNotePathString() ?? "";
} }