mirror of
https://github.com/callumalpass/tasknotes.git
synced 2026-07-22 12:50:26 +00:00
improve: add detailed error logging for webhook transform failures
- Add comprehensive error messages for transform file loading failures - Include file path validation and existence checking - Add function validation warnings for missing transform functions - Provide step-by-step logging for transform execution - Add minimal transform examples for Discord and Slack Fixes silent failures that made debugging transform issues difficult. Addresses issue #719 where users couldn't identify why transform scripts weren't loading.
This commit is contained in:
parent
849433fa6a
commit
0fb618b539
3 changed files with 110 additions and 17 deletions
28
docs/examples/webhook-transforms/minimal-discord.js
Normal file
28
docs/examples/webhook-transforms/minimal-discord.js
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* Minimal Discord Webhook Transform for TaskNotes
|
||||
* This is the simplest possible transform for Discord webhooks
|
||||
*/
|
||||
|
||||
console.log("🔥 transform file loaded");
|
||||
|
||||
function transform(payload) {
|
||||
const { event, data } = payload;
|
||||
|
||||
// Simple Discord message format
|
||||
if (event === 'task.created') {
|
||||
return {
|
||||
content: `📝 New task: **${data.task.title}**`
|
||||
};
|
||||
}
|
||||
|
||||
if (event === 'task.completed') {
|
||||
return {
|
||||
content: `✅ Completed: **${data.task.title}**`
|
||||
};
|
||||
}
|
||||
|
||||
// For all other events, return a generic message
|
||||
return {
|
||||
content: `TaskNotes: ${event} event triggered`
|
||||
};
|
||||
}
|
||||
14
docs/examples/webhook-transforms/minimal-slack.json
Normal file
14
docs/examples/webhook-transforms/minimal-slack.json
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"task.created": {
|
||||
"text": "📝 New task: ${data.task.title}",
|
||||
"channel": "#tasks"
|
||||
},
|
||||
"task.completed": {
|
||||
"text": "✅ Completed: ${data.task.title}",
|
||||
"channel": "#tasks"
|
||||
},
|
||||
"default": {
|
||||
"text": "TaskNotes: ${event} event triggered",
|
||||
"channel": "#general"
|
||||
}
|
||||
}
|
||||
|
|
@ -286,58 +286,109 @@ export class WebhookController extends BaseController {
|
|||
|
||||
private async applyTransformation(transformFile: string, payload: WebhookPayload): Promise<any> {
|
||||
try {
|
||||
console.log(`🔧 Applying transformation: ${transformFile}`);
|
||||
|
||||
if (transformFile.endsWith('.js')) {
|
||||
return await this.applyJSTransformation(transformFile, payload);
|
||||
} else if (transformFile.endsWith('.json')) {
|
||||
return await this.applyJSONTransformation(transformFile, payload);
|
||||
}
|
||||
|
||||
|
||||
// Unknown file type, return original payload
|
||||
console.warn(`⚠️ Unknown transform file type for ${transformFile}, using original payload`);
|
||||
return payload;
|
||||
} catch (error) {
|
||||
console.error(`Transformation failed for ${transformFile}:`, error);
|
||||
console.error(`❌ Transformation failed for ${transformFile}:`, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
private async applyJSTransformation(transformFile: string, payload: WebhookPayload): Promise<any> {
|
||||
try {
|
||||
console.log(`📂 Reading transform file: ${transformFile}`);
|
||||
|
||||
// Read transformation file from vault
|
||||
const transformCode = await this.plugin.app.vault.adapter.read(transformFile);
|
||||
|
||||
let transformCode: string;
|
||||
try {
|
||||
transformCode = await this.plugin.app.vault.adapter.read(transformFile);
|
||||
console.log(`✅ Transform file loaded successfully (${transformCode.length} characters)`);
|
||||
} catch (readError: any) {
|
||||
throw new Error(`Failed to read transform file '${transformFile}': ${readError.message}. Please check the file path and ensure it exists in your vault.`);
|
||||
}
|
||||
|
||||
// Validate file has content
|
||||
if (!transformCode.trim()) {
|
||||
throw new Error(`Transform file '${transformFile}' is empty. Please add a transform function.`);
|
||||
}
|
||||
|
||||
// Check for transform function in the code
|
||||
if (!transformCode.includes('function transform')) {
|
||||
console.warn(`⚠️ Transform file '${transformFile}' may not contain a 'transform' function`);
|
||||
}
|
||||
|
||||
console.log(`🔧 Executing transform function for event: ${payload.event}`);
|
||||
|
||||
// Create a safe execution context
|
||||
const transform = new Function('payload', `
|
||||
${transformCode}
|
||||
if (typeof transform === 'function') {
|
||||
console.log("🔥 transform file loaded");
|
||||
return transform(payload);
|
||||
} else {
|
||||
throw new Error('Transform file must export a transform function');
|
||||
throw new Error('Transform file must export a transform function. Expected: function transform(payload) { ... }');
|
||||
}
|
||||
`);
|
||||
|
||||
return transform(payload);
|
||||
} catch (error) {
|
||||
console.error(`JS transformation error:`, error);
|
||||
|
||||
const result = transform(payload);
|
||||
console.log(`✅ Transform completed successfully for ${transformFile}`);
|
||||
return result;
|
||||
} catch (error: any) {
|
||||
console.error(`❌ JS transformation error for '${transformFile}':`, error.message);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
private async applyJSONTransformation(transformFile: string, payload: WebhookPayload): Promise<any> {
|
||||
try {
|
||||
console.log(`📂 Reading JSON template file: ${transformFile}`);
|
||||
|
||||
// Read template file from vault
|
||||
const templateContent = await this.plugin.app.vault.adapter.read(transformFile);
|
||||
const templates = JSON.parse(templateContent);
|
||||
|
||||
let templateContent: string;
|
||||
try {
|
||||
templateContent = await this.plugin.app.vault.adapter.read(transformFile);
|
||||
console.log(`✅ JSON template file loaded successfully (${templateContent.length} characters)`);
|
||||
} catch (readError: any) {
|
||||
throw new Error(`Failed to read template file '${transformFile}': ${readError.message}. Please check the file path and ensure it exists in your vault.`);
|
||||
}
|
||||
|
||||
// Validate file has content
|
||||
if (!templateContent.trim()) {
|
||||
throw new Error(`Template file '${transformFile}' is empty. Please add JSON template content.`);
|
||||
}
|
||||
|
||||
// Parse JSON template
|
||||
let templates: any;
|
||||
try {
|
||||
templates = JSON.parse(templateContent);
|
||||
} catch (parseError: any) {
|
||||
throw new Error(`Invalid JSON in template file '${transformFile}': ${parseError.message}`);
|
||||
}
|
||||
|
||||
console.log(`🔧 Applying JSON template for event: ${payload.event}`);
|
||||
|
||||
// Get template for this event or use default
|
||||
const template = templates[payload.event] || templates.default;
|
||||
if (!template) {
|
||||
throw new Error(`No template found for event ${payload.event} and no default template`);
|
||||
const availableEvents = Object.keys(templates).filter(key => key !== 'default');
|
||||
throw new Error(`No template found for event '${payload.event}' and no default template. Available templates: ${availableEvents.join(', ')}`);
|
||||
}
|
||||
|
||||
|
||||
// Apply template variable substitution
|
||||
return this.interpolateTemplate(template, payload);
|
||||
} catch (error) {
|
||||
console.error(`JSON transformation error:`, error);
|
||||
const result = this.interpolateTemplate(template, payload);
|
||||
console.log(`✅ JSON template applied successfully for ${transformFile}`);
|
||||
return result;
|
||||
} catch (error: any) {
|
||||
console.error(`❌ JSON transformation error for '${transformFile}':`, error.message);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue