From bb25e59dc5e1d852a132f85aee0d6559ff0459b2 Mon Sep 17 00:00:00 2001 From: Daniel Diaz <39510674+IslandRhythms@users.noreply.github.com> Date: Fri, 16 Jan 2026 14:51:26 -0500 Subject: [PATCH 1/3] slack webhooks --- .env.development | 1 + .env.local | 1 + config.js | 13 ++++++- index.js | 2 ++ package.json | 2 ++ src/actions/notifySlack.js | 74 ++++++++++++++++++++++++++++++++++++++ src/db/workspace.js | 21 ++++++++++- src/integrations/slack.js | 15 ++++++++ 8 files changed, 127 insertions(+), 2 deletions(-) create mode 100644 .env.development create mode 100644 .env.local create mode 100644 src/actions/notifySlack.js diff --git a/.env.development b/.env.development new file mode 100644 index 0000000..7434fb5 --- /dev/null +++ b/.env.development @@ -0,0 +1 @@ +MONGODB_CONNECTION_STRING=mongodb://127.0.0.1:27017/mongoose_test \ No newline at end of file diff --git a/.env.local b/.env.local new file mode 100644 index 0000000..7434fb5 --- /dev/null +++ b/.env.local @@ -0,0 +1 @@ +MONGODB_CONNECTION_STRING=mongodb://127.0.0.1:27017/mongoose_test \ No newline at end of file diff --git a/config.js b/config.js index 8cb3dd1..d8ca5c0 100644 --- a/config.js +++ b/config.js @@ -1,5 +1,7 @@ 'use strict'; +console.log('Config file is loading...'); + if (!process.env.NODE_ENV) { process.env.NODE_ENV = 'local'; } @@ -11,7 +13,16 @@ const path = require('path'); console.log('NODE_ENV =', env); if (!['development', 'production'].includes(process.env.NODE_ENV)) { - dotenv.config({ + const result = dotenv.config({ path: path.resolve(__dirname, `.env.${env.toLocaleLowerCase()}`) }); + if (result.error) { + console.error('Error loading .env file:', result.error); + } else { + console.log('Loaded .env file:', path.resolve(__dirname, `.env.${env.toLocaleLowerCase()}`)); + console.log('Environment variables:', { + MONGODB_CONNECTION_STRING: process.env.MONGODB_CONNECTION_STRING ? '[SET]' : '[NOT SET]', + NODE_ENV: process.env.NODE_ENV + }); + } } diff --git a/index.js b/index.js index 11abb89..287419e 100644 --- a/index.js +++ b/index.js @@ -2,6 +2,8 @@ require('dotenv').config(); +require('./config'); + const cors = require('cors'); const connect = require('./src/db'); const express = require('express'); diff --git a/package.json b/package.json index b18f2a2..07236da 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,8 @@ "scripts": { "seed": "env NODE_ENV=development node ./seed", "start": "node .", + "start:local": "env NODE_ENV=local node .", + "start:development": "env NODE_ENV=development node .", "test": "env NODE_ENV=test mocha -r ./config test/*.test.js", "lint": "eslint ." } diff --git a/src/actions/notifySlack.js b/src/actions/notifySlack.js new file mode 100644 index 0000000..a63e74b --- /dev/null +++ b/src/actions/notifySlack.js @@ -0,0 +1,74 @@ +'use strict'; + +const Archetype = require('archetype'); +const connect = require('../../src/db'); +const slack = require('../integrations/slack'); + +const NotifySlackPayload = new Archetype({ + modelName: { + $type: 'string', + $required: true + }, + documentId: { + $type: 'string', + $required: true + }, + purpose: { + $type: 'string', + $required: true + } +}).compile('NotifySlackPayload'); + +module.exports = async function notifySlack(params) { + const db = await connect(); + const { Workspace } = db.models; + + const workspace = await Workspace.findById(params.workspaceId).orFail(); + + if (!workspace.slackWebhooks || workspace.slackWebhooks.length === 0) { + throw new Error('Workspace does not have any Slack webhook URLs configured'); + } + + const { modelName, documentId, purpose } = new NotifySlackPayload(params.payload || {}); + + const blocks = [ + { + type: 'section', + text: { + type: 'mrkdwn', + text: `A new document was created in the *${modelName}* model.\n*Document ID:* \`${documentId}\`` + } + } + ]; + + if (workspace.baseUrl) { + const url = `${workspace.baseUrl}/model/${modelName}/document/${documentId}`; + blocks.push({ + type: 'section', + text: { + type: 'mrkdwn', + text: `<${url}|View Document>` + } + }); + } + + const messagePayload = { + blocks + }; + + const matchingWebhooks = workspace.slackWebhooks.filter(webhook => { + return webhook.enabled !== false && + webhook.purposes && + webhook.purposes.includes(purpose); + }); + + if (matchingWebhooks.length === 0) { + throw new Error(`No enabled webhooks found for purpose: ${purpose}`); + } + + await Promise.all( + matchingWebhooks.map(webhook => slack.sendWebhook(webhook.url, messagePayload)) + ); + + return { success: true }; +}; diff --git a/src/db/workspace.js b/src/db/workspace.js index 7718536..6510424 100644 --- a/src/db/workspace.js +++ b/src/db/workspace.js @@ -41,7 +41,26 @@ const workspaceSchema = new mongoose.Schema({ subscriptionTier: { type: String, enum: ['', 'free', 'pro'] - } + }, + slackWebhooks: [{ + _id: false, + url: { + type: String, + required: true + }, + name: { + type: String + }, + purposes: [{ + type: String, + required: true, + enum: ['documentCreated'] + }], + enabled: { + type: Boolean, + default: true + } + }] }, { timestamps: true, id: false }); workspaceSchema.index({ apiKey: 1 }, { unique: true }); diff --git a/src/integrations/slack.js b/src/integrations/slack.js index 1a240dc..cf3c881 100644 --- a/src/integrations/slack.js +++ b/src/integrations/slack.js @@ -8,5 +8,20 @@ module.exports = { const url = 'https://slack.com/api/chat.postMessage'; // Send to Slack await axios.post(url, jobs, { headers: { authorization: `Bearer ${config.slackToken}` } }); + }, + async sendWebhook(webhookUrl, payload) { + const response = await fetch(webhookUrl, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(payload) + }); + + if (!response.ok) { + throw new Error(`Slack webhook request failed with status ${response.status}`); + } + + return response; } }; \ No newline at end of file From 97a9cd6b1f3c3e3758541a38ae130c9831607d70 Mon Sep 17 00:00:00 2001 From: Daniel Diaz <39510674+IslandRhythms@users.noreply.github.com> Date: Fri, 16 Jan 2026 17:28:52 -0500 Subject: [PATCH 2/3] successful test run --- .config | 0 netlify/functions/notifySlack.js | 5 +++++ src/actions/notifySlack.js | 14 +++++++++----- 3 files changed, 14 insertions(+), 5 deletions(-) create mode 100644 .config create mode 100644 netlify/functions/notifySlack.js diff --git a/.config b/.config new file mode 100644 index 0000000..e69de29 diff --git a/netlify/functions/notifySlack.js b/netlify/functions/notifySlack.js new file mode 100644 index 0000000..34ed209 --- /dev/null +++ b/netlify/functions/notifySlack.js @@ -0,0 +1,5 @@ +'use strict'; + +const extrovert = require('extrovert'); + +module.exports = extrovert.toNetlifyFunction(require('../../src/actions/notifySlack')); diff --git a/src/actions/notifySlack.js b/src/actions/notifySlack.js index a63e74b..f1b470e 100644 --- a/src/actions/notifySlack.js +++ b/src/actions/notifySlack.js @@ -4,7 +4,11 @@ const Archetype = require('archetype'); const connect = require('../../src/db'); const slack = require('../integrations/slack'); -const NotifySlackPayload = new Archetype({ +const NotifySlackParams = new Archetype({ + workspaceId: { + $type: 'string', + $required: true + }, modelName: { $type: 'string', $required: true @@ -17,20 +21,20 @@ const NotifySlackPayload = new Archetype({ $type: 'string', $required: true } -}).compile('NotifySlackPayload'); +}).compile('NotifySlackParams'); module.exports = async function notifySlack(params) { + const { workspaceId, modelName, documentId, purpose } = new NotifySlackParams(params); + const db = await connect(); const { Workspace } = db.models; - const workspace = await Workspace.findById(params.workspaceId).orFail(); + const workspace = await Workspace.findById(workspaceId).orFail(); if (!workspace.slackWebhooks || workspace.slackWebhooks.length === 0) { throw new Error('Workspace does not have any Slack webhook URLs configured'); } - const { modelName, documentId, purpose } = new NotifySlackPayload(params.payload || {}); - const blocks = [ { type: 'section', From 59560b6df4b3f6287f779d640bef0da16653982d Mon Sep 17 00:00:00 2001 From: Daniel Diaz <39510674+IslandRhythms@users.noreply.github.com> Date: Tue, 20 Jan 2026 17:43:21 -0500 Subject: [PATCH 3/3] Update workspace.js --- src/db/workspace.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/db/workspace.js b/src/db/workspace.js index 6510424..be0bbea 100644 --- a/src/db/workspace.js +++ b/src/db/workspace.js @@ -60,6 +60,25 @@ const workspaceSchema = new mongoose.Schema({ type: Boolean, default: true } + }], + discordWebhooks: [{ + _id: false, + url: { + type: String, + required: true + }, + name: { + type: String + }, + purposes: [{ + type: String, + required: true, + enum: ['documentCreated'] + }], + enabled: { + type: Boolean, + default: true + } }] }, { timestamps: true, id: false });