Skip to content

Commit

Permalink
feat(templates): offer retry on templater errors
Browse files Browse the repository at this point in the history
  • Loading branch information
danielo515 committed Dec 17, 2024
1 parent e42809a commit 64dae86
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 38 deletions.
27 changes: 18 additions & 9 deletions src/core/template/TemplaterService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,22 @@ export class TemplaterService implements TemplateService {
filename: string,
openNewNote: boolean,
): TE.TaskEither<TemplateError, void> =>
TE.tryCatch(async () => {
const title = filename;
await this.templaterApi.create_new_note_from_template(
templateContent,
targetFolder,
title,
openNewNote,
);
}, TemplateError.of("Error creating note from template"));
TE.tryCatch(
async () => {
const title = filename;
const result = await this.templaterApi.create_new_note_from_template(
templateContent,
targetFolder,
title,
openNewNote,
);
if (result === undefined) {
throw new Error("Templater API returned undefined, probably a parsing error");
}
},
(e) =>
e instanceof Error
? TemplateError.of(e.message)(e)
: TemplateError.of("Unknown error")(e),
);
}
29 changes: 29 additions & 0 deletions src/core/template/retryForm.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { FormDefinition } from "../formDefinition";

export const retryForm: FormDefinition = {
title: "Templater error",
name: "retry-temlate",
version: "1",
fields: [
{
name: "title",
label: "",
description: "",
input: {
type: "markdown_block",
body: "return `\n==Templater reported an error==\nWe are not sure about what it is, but is very likely a parse error.\nPlease try to fix the templater code below and submit it to retry\n`",
},
isRequired: false,
},
{
name: "template",
label: "Code",
description: "Fix the template below and try to submit again",
input: {
type: "textarea",
hidden: false,
},
isRequired: false,
},
],
};
77 changes: 48 additions & 29 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { A, E, O, pipe, TE } from "@std";
import { Platform, Plugin, WorkspaceLeaf } from "obsidian";
import { API } from "src/API";
import { ModalFormSettingTab } from "src/ModalFormSettingTab";
import FormResult from "src/core/FormResult";
import { FormWithTemplate, type FormDefinition } from "src/core/formDefinition";
import {
getDefaultSettings,
Expand All @@ -22,6 +21,7 @@ import {
} from "./core/formDefinitionSchema";
import { TemplateService } from "./core/template/TemplateService";
import { getTemplateService } from "./core/template/getTemplateService";
import { retryForm } from "./core/template/retryForm";
import { executeTemplate } from "./core/template/templateParser";
import { settingsStore } from "./store/store";
import { FormPickerModal } from "./suggesters/FormPickerModal";
Expand All @@ -36,12 +36,6 @@ import { makeModel } from "./views/components/TemplateBuilder";

type ViewType = typeof EDIT_FORM_VIEW | typeof MANAGE_FORMS_VIEW | typeof TEMPLATE_BUILDER_VIEW;

// Define functions and properties you want to make available to other plugins, or templater templates, etc
export interface PublicAPI {
exampleForm(): Promise<FormResult>;
openForm(formReference: string | FormDefinition): Promise<FormResult>;
}

function notifyParsingErrors(errors: InvalidData[]) {
if (errors.length === 0) {
return;
Expand All @@ -68,7 +62,7 @@ export default class ModalFormPlugin extends Plugin {
public settings: ModalFormSettings | undefined;
private unsubscribeSettingsStore: () => void = () => {};
// This things will be setup in the onload function rather than constructor
public api!: PublicAPI;
public api!: API;
private templateService!: TemplateService;

manageForms() {
Expand Down Expand Up @@ -352,6 +346,51 @@ export default class ModalFormPlugin extends Plugin {
);
}

createNoteFromTemplate(
noteName: string,
noteContent: string,
destinationFolder: string,
): TE.TaskEither<Error, void> {
// Use template service instead of directly creating the file
return pipe(
this.templateService.createNoteFromTemplate(
noteContent,
destinationFolder,
noteName,
false, // don't open the new note
),
TE.orElse((error) => {
logger.error(error);
return pipe(
TE.tryCatch(
() =>
this.api.openForm(retryForm, {
values: {
title: error.message,
template: noteContent,
},
}),
E.toError,
),
TE.map((result) => result.get("template")),
TE.chain((template) => {
if (typeof template !== "string") {
notifyWarning("Failed while retrying")("Template is not a string");
return TE.left(new Error("Template is not a string"));
}
return this.createNoteFromTemplate(noteName, template, destinationFolder);
}),
);
}),
TE.tapIO(() => () => {
log_notice(
"Note created successfully",
`Note "${noteName}" created in ${destinationFolder}`,
);
}),
);
}

/**
* Checks if there are forms with templates, and presents a prompt
* to select a form, then opens the forms, and creates a new note
Expand All @@ -367,27 +406,7 @@ export default class ModalFormPlugin extends Plugin {
const formData = await this.api.openForm(form);
const noteContent = executeTemplate(form.template.parsedTemplate, formData.getData());

// Use template service instead of directly creating the file
await pipe(
this.templateService.createNoteFromTemplate(
noteContent,
destinationFolder,
noteName,
false, // don't open the new note
),
TE.match(
(error) => {
log_error(error);
notifyWarning("Failed to create note from template");
},
() => {
log_notice(
"Note created successfully",
`Note ${noteName} created in ${destinationFolder}`,
);
},
),
)();
await this.createNoteFromTemplate(noteName, noteContent, destinationFolder)();
};

const picker = new NewNoteModal(
Expand Down

0 comments on commit 64dae86

Please sign in to comment.