--- title: "Code the Advanced I/O Function" url: https://docs.catalyst.zoho.com/en/tutorials/birthday-greetings/nodejs/code-advancedio/ description: "Build a birthday greetings application using the Job Scheduling service and automatically send out birthday greetings to the required person via their email." last_updated: 2026-08-17T12:16:04Z service: All Services type: tutorial related_links: - name: "Advanced I/O Functions" url: /en/serverless/help/functions/advanced-io/ - name: "Node.js SDK" url: /en/sdk/nodejs/v2/overview/ --- # Code the Advanced I/O Function Let's start configuring the Advanced I/O function. This function will be used to communicate with the client and will configure a [Dynamic Cron](https://docs.catalyst.zoho.com/en/job-scheduling/help/cron/key-concepts/#cron-types). The meta of the Cron will be obtained using the data inputted in the client with the help of the [Cron creation SDK](https://docs.catalyst.zoho.com/en/sdk/nodejs/v2/job-scheduling/cron/create-recurring-cron/). The Advanced I/O function present in the [functions directory](https://docs.catalyst.zoho.com/en/cli/v1/project-directory-structure/functions-directory/), `BirthdayGreetings/functions/advance_function/` contains: * The `index.js` main function file * The `catalyst-config.json` configuration file * Node modules * [`package.json`](https://docs.npmjs.com/files/package.json) and [`package-lock.json`](https://docs.npmjs.com/configuring-npm/package-lock-json.html) dependency files. You will be adding code in the `index.js` file. To code this function, you will be using the [Express Node.js framework](https://expressjs.com/). To import the Express package in the code, you must install the Express dependencies in your system. To install Express.js in your local machine, navigate to the `BirthdayGreetings/functions/advance_function/` in your terminal and execute the following command: ```sh npm install express --save ``` ![catalyst_tutorials_jobscheduling_advacned_func_express](https://catalyst-docs-development.zohostratus.in/images/tutorials/birthday-greetings/catalyst_tutorials_jobscheduling_advacned_func_express.webp) Copy the code given below and paste it in the `index.js` file. > **Note:** Please go through the code in this section to make sure you fully understand it. **index.js** ```javascript 'use strict'; const catalyst = require('zcatalyst-sdk-node'); const express = require('express'); const app = express(); app.use(express.json()); app.post('/insertReminder', async (req, res) => { console.log("Request body:", req.body); try { const catalystApp = catalyst.initialize(req); let userManagement = catalystApp.userManagement(); let userPromise = userManagement.getCurrentUser(); userPromise.then(async (currentUser) => { console.log(currentUser); const datastores = catalystApp.datastore(); const table = datastores.table('12096000001771061'); // Your Table ID await insertReminder(req.body, table, catalystApp); res.status(200).json({ status: 200, message: "Reminder added successfully" }); }); } catch (error) { console.error('Error adding reminder:', error); res.status(500).json({ Error: error.message }); } }); app.get('/getReminder', async (req, res) => { try { const catalystApp = catalyst.initialize(req); const datastores = catalystApp.datastore(); const table = datastores.table('12096000001771061'); // Your Table ID const reminders = await getReminders(catalystApp, table); res.status(200).json(reminders); } catch (error) { console.error('Error retrieving reminders:', error); res.status(500).json({ Error: error.message }); } }); app.put('/updateReminder', async (req, res) => { try { const catalystApp = catalyst.initialize(req); const datastores = catalystApp.datastore(); const table = datastores.table('12096000001771061'); // Your Table ID await updateReminder(req.body, table, catalystApp); res.status(200).json({ status: 200, message: "Reminder updated successfully" }); } catch (error) { console.error('Error updating reminder:', error); res.status(500).json({ Error: error.message }); } }); app.patch('/toggleAutoSend', async (req, res) => { try { const catalystApp = catalyst.initialize(req); const datastores = catalystApp.datastore(); const table = datastores.table('12096000001771061'); // Your Table ID await toggleAutoSend(req.body, table, catalystApp); res.status(200).json({ status: 200, message: "Auto send toggled status successfully" }); } catch (error) { console.error('Error toggling status:', error); res.status(500).json({ Error: error.message }); } }); app.delete('/deleteReminder/:id', async (req, res) => { try { const { id } = req.params; console.log("ID received:", id); const catalystApp = catalyst.initialize(req); const datastores = catalystApp.datastore(); const table = datastores.table('12096000001771061'); // Your Table ID await deleteReminder(id, table, catalystApp); res.status(200).json({ status: 200, message: "Reminder deleted successfully" }); } catch (error) { console.error('Error deleting reminder:', error); res.status(500).json({ Error: error.message }); } }); module.exports = app; async function toggleAutoSend(requestBody, table, catalystApp) { const { id, status } = requestBody; const enableStatus = status === 'enable'; const zcql = catalystApp.zcql(); const query = `SELECT * FROM BirthDayReminder WHERE ROWID = '${id}'`; const response = await zcql.executeZCQLQuery(query); if (!response || response.length === 0) throw new Error('Reminder not found.'); const row = response[0].BirthDayReminder; row.AutoSend = enableStatus; console.log("Row.autosend ", row.AutoSend); const jobScheduling = catalystApp.jobScheduling(); if (!enableStatus) { console.log("false"); await jobScheduling.CRON.deleteCron(`bday_${id.substring(10, 17)}`); } else { console.log("true"); await scheduleCronJob(row, catalystApp); } const updateQuery = `UPDATE BirthDayReminder SET AutoSend = ${enableStatus} WHERE ROWID = '${id}'`; await zcql.executeZCQLQuery(updateQuery); } async function insertReminder(requestBody, table, catalystApp) { const { name, birthday, message, email } = requestBody; if (!name || !birthday || !message || !email) throw new Error('Missing required fields.'); const row = { Name: name, BirthDay: birthday, Message: message, Email: email }; try { const insertedRow = await table.insertRow(row); await scheduleCronJob(insertedRow, catalystApp); } catch (error) { console.error('Error inserting reminder:', error); throw error; } } async function getReminders(catalystApp, table) { try { const zcql = catalystApp.zcql(); const query = 'SELECT * FROM BirthDayReminder'; const response = await zcql.executeZCQLQuery(query); if (!Array.isArray(response)) throw new Error('Invalid response from ZCQL query'); return response.map(row => { const reminder = row.BirthDayReminder; return { ID: reminder.ROWID || 'N/A', Name: reminder.Name || 'N/A', BirthDay: reminder.BirthDay || 'N/A', Message: reminder.Message || 'N/A', Email: reminder.Email || 'N/A', AutoSend: reminder.AutoSend || false }; }); } catch (error) { console.error('Error retrieving reminders:', error.message); throw error; } } async function updateReminder(requestBody, table, catalystApp) { const { ID, Name, BirthDay, Message, Email } = requestBody; const jobScheduling = catalystApp.jobScheduling(); if (!ID || !Name || !BirthDay || !Message || !Email) throw new Error('Missing required fields.'); const zcql = catalystApp.zcql(); const query = `SELECT AutoSend FROM BirthDayReminder WHERE ROWID = '${ID}'`; const response = await zcql.executeZCQLQuery(query); const AutoSend = response[0]?.BirthDayReminder?.AutoSend || false; const row = { ROWID: ID, Name: Name, BirthDay: BirthDay, Message: Message, Email: Email }; if (AutoSend) { await jobScheduling.CRON.deleteCron(`bday_${ID.substring(10, 17)}`); try { await table.updateRow(row); await scheduleCronJob(row, catalystApp); } catch (error) { console.error('Error updating reminder:', error); throw error; } } else { try { await table.updateRow(row); console.log('Row updated:', row); } catch (error) { console.error('Error updating reminder:', error); throw error; } } } async function deleteReminder(id, table, catalystApp) { if (!id) throw new Error('ID is missing.'); const zcql = catalystApp.zcql(); const query = `SELECT AutoSend FROM BirthDayReminder WHERE ROWID = '${id}'`; const response = await zcql.executeZCQLQuery(query); const AutoSend = response[0]?.BirthDayReminder?.AutoSend || false; const jobScheduling = catalystApp.jobScheduling(); if (AutoSend) { await jobScheduling.CRON.deleteCron(`bday_${id.substring(10, 17)}`); } await table.deleteRow(id); console.log('Reminder deleted:', id); } async function scheduleCronJob(row, catalystApp) { const jobScheduling = catalystApp.jobScheduling(); const { ROWID, BirthDay, Name, Email, Message } = row; const dob = new Date(BirthDay); const cronDetail = { cron_name: `bday_${ROWID.substring(10, 17)}`, description: `Birthday reminder for ${Name}`, cron_status: true, cron_type: 'CALENDAR', cron_detail: { hour: 0, minute: 0, second: 0, days: [dob.getDate()], months: [dob.getMonth()], repetition_type: 'YEARLY' }, job_meta: { job_name: `bday_${ROWID.substring(10, 17)}`, jobpool_name: 'Trigger_Message', // Your job pool name jobpool_id: '12096000001771827', // Your Job pool ID target_type: 'FUNCTION', target_name: 'dynamic_cron', // Your job function name job_service_identifier: 'default', retries: 2, retry_interval: 900, params: { id: ROWID, name: Name, email: Email, message: Message, birthday: BirthDay } } }; try { const yearlyCronDetails = await jobScheduling.CRON.createCron(cronDetail); console.log('Yearly cron created:', yearlyCronDetails); } catch (error) { console.error('Error scheduling cron job:', error); throw error; } } ``` > **Notes:** * Ensure that you provide your **Table ID** in lines `15`, `33`, `47`, `64`, and `85`. You can fetch this value for the table you created from the Data Store. * Ensure that you provide with your job meta details in lines `245`, `246`, and `248`. You can fetch these from the Job Pool section in Job Scheduling. Let's go over the APIs that were used to code the Advanced I/O function to handle the routing between the server, the Data Store, and the Job Scheduling service: * `POST /insertReminder`: Will add a new reminder to the Data Store with the details provided in the client. Will also schedule a dynamic cron job for the reminder using the Catalyst Job Scheduling service to automate tasks. * `GET /getReminder`: Will retrieve all of the reminders stored in the Data Store and return them as the response. * `PUT /updateReminder`: Will update an existing reminder in the Data Store with the details provided in the client. * `PATCH /toggleAutoSend`: Will toggle the auto-send status of a reminder based on the preference set by the user in the client side. * `DELETE /deleteReminder/:id`: Will delete a specific reminder from the Data Store and Cron using the provided `reminder ID`.