|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251 |
- const fs = require('fs');
- const fetch = require('node-fetch');
-
- const ical = require('./ical.js');
-
- /**
- * ICal event object.
- *
- * These two fields are always present:
- * - type
- * - params
- *
- * The rest of the fields may or may not be present depending on the input.
- * Do not assume any of these fields are valid and check them before using.
- * Most types are simply there as a general guide for IDEs and users.
- *
- * @typedef iCalEvent
- * @type {object}
- *
- * @property {string} type - Type of event.
- * @property {Array} params - Extra event parameters.
- *
- * @property {?object} start - When this event starts.
- * @property {?object} end - When this event ends.
- *
- * @property {?string} summary - Event summary string.
- * @property {?string} description - Event description.
- *
- * @property {?object} dtstamp - DTSTAMP field of this event.
- *
- * @property {?object} created - When this event was created.
- * @property {?object} lastmodified - When this event was last modified.
- *
- * @property {?string} uid - Unique event identifier.
- *
- * @property {?string} status - Event status.
- *
- * @property {?string} sequence - Event sequence.
- *
- * @property {?string} url - URL of this event.
- *
- * @property {?string} location - Where this event occurs.
- * @property {?{
- * lat: number, lon: number
- * }} geo - Lat/lon location of this event.
- *
- * @property {?Array.<string>} - Array of event catagories.
- */
- /**
- * Object containing iCal events.
- * @typedef {Object.<string, iCalEvent>} iCalData
- */
- /**
- * Callback for iCal parsing functions with error and iCal data as a JavaScript object.
- * @callback icsCallback
- * @param {Error} err
- * @param {iCalData} ics
- */
- /**
- * A Promise that is undefined if a compatible callback is passed.
- * @typedef {(Promise.<iCalData>|undefined)} optionalPromise
- */
-
- // utility to allow callbacks to be used for promises
- function promiseCallback(fn, cb) {
- const promise = new Promise(fn);
- if (!cb) {
- return promise;
- }
-
- promise
- .then(returnValue => {
- cb(null, returnValue);
- })
- .catch(error => {
- cb(error, null);
- });
- }
-
- // Sync functions
- const sync = {};
- // Async functions
- const async = {};
- // Auto-detect functions for backwards compatibility.
- const autodetect = {};
-
- /**
- * Download an iCal file from the web and parse it.
- *
- * @param {string} url - URL of file to request.
- * @param {Object|icsCallback} [opts] - Options to pass to fetch() from npm:node-fetch.
- * Alternatively you can pass the callback function directly.
- * If no callback is provided a promise will be returned.
- * @param {icsCallback} [cb] - Callback function.
- * If no callback is provided a promise will be returned.
- *
- * @returns {optionalPromise} Promise is returned if no callback is passed.
- */
- async.fromURL = function (url, options, cb) {
- return promiseCallback((resolve, reject) => {
- fetch(url, options)
- .then(response => {
- // If (response.status !== 200) {
- // all ok status codes should be accepted (any 2XX code)
- if (Math.floor(response.status / 100) !== 2) {
- reject(new Error(`${response.status} ${response.statusText}`));
- return;
- }
-
- return response;
- })
- .then(response => response.text())
- .then(data => {
- ical.parseICS(data, (error, ics) => {
- if (error) {
- reject(error);
- return;
- }
-
- resolve(ics);
- });
- })
- .catch(error => {
- reject(error);
- });
- }, cb);
- };
-
- /**
- * Load iCal data from a file and parse it.
- *
- * @param {string} filename - File path to load.
- * @param {icsCallback} [cb] - Callback function.
- * If no callback is provided a promise will be returned.
- *
- * @returns {optionalPromise} Promise is returned if no callback is passed.
- */
- async.parseFile = function (filename, cb) {
- return promiseCallback((resolve, reject) => {
- fs.readFile(filename, 'utf8', (error, data) => {
- if (error) {
- reject(error);
- return;
- }
-
- ical.parseICS(data, (error, ics) => {
- if (error) {
- reject(error);
- return;
- }
-
- resolve(ics);
- });
- });
- }, cb);
- };
-
- /**
- * Parse iCal data from a string.
- *
- * @param {string} data - String containing iCal data.
- * @param {icsCallback} [cb] - Callback function.
- * If no callback is provided a promise will be returned.
- *
- * @returns {optionalPromise} Promise is returned if no callback is passed.
- */
- async.parseICS = function (data, cb) {
- return promiseCallback((resolve, reject) => {
- ical.parseICS(data, (error, ics) => {
- if (error) {
- reject(error);
- return;
- }
-
- resolve(ics);
- });
- }, cb);
- };
-
- /**
- * Load iCal data from a file and parse it.
- *
- * @param {string} filename - File path to load.
- *
- * @returns {iCalData} Parsed iCal data.
- */
- sync.parseFile = function (filename) {
- const data = fs.readFileSync(filename, 'utf8');
- return ical.parseICS(data);
- };
-
- /**
- * Parse iCal data from a string.
- *
- * @param {string} data - String containing iCal data.
- *
- * @returns {iCalData} Parsed iCal data.
- */
- sync.parseICS = function (data) {
- return ical.parseICS(data);
- };
-
- /**
- * Load iCal data from a file and parse it.
- *
- * @param {string} filename - File path to load.
- * @param {icsCallback} [cb] - Callback function.
- * If no callback is provided this function runs synchronously.
- *
- * @returns {iCalData|undefined} Parsed iCal data or undefined if a callback is being used.
- */
- autodetect.parseFile = function (filename, cb) {
- if (!cb) {
- return sync.parseFile(filename);
- }
-
- async.parseFile(filename, cb);
- };
-
- /**
- * Parse iCal data from a string.
- *
- * @param {string} data - String containing iCal data.
- * @param {icsCallback} [cb] - Callback function.
- * If no callback is provided this function runs synchronously.
- *
- * @returns {iCalData|undefined} Parsed iCal data or undefined if a callback is being used.
- */
- autodetect.parseICS = function (data, cb) {
- if (!cb) {
- return sync.parseICS(data);
- }
-
- async.parseICS(data, cb);
- };
-
- // Export api functions
- module.exports = {
- // Autodetect
- fromURL: async.fromURL,
- parseFile: autodetect.parseFile,
- parseICS: autodetect.parseICS,
- // Sync
- sync,
- // Async
- async,
- // Other backwards compat things
- objectHandlers: ical.objectHandlers,
- handleObject: ical.handleObject,
- parseLines: ical.parseLines
- };
|