Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

V2 #32

Merged
merged 131 commits into from
Oct 1, 2017
Merged

V2 #32

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
131 commits
Select commit Hold shift + click to select a range
7151430
remove ex dir
adamgibbons Jul 28, 2017
f944f93
change entry point
adamgibbons Jul 28, 2017
f5d49b0
ignore dist dir
adamgibbons Jul 28, 2017
6e1df38
begin gulp build process
adamgibbons Jul 28, 2017
6d2b451
enable es6 compilation for tests
adamgibbons Aug 12, 2017
a8e6a8d
add watch flag to npm test command
adamgibbons Aug 12, 2017
2be1f69
begin v2!
adamgibbons Aug 12, 2017
33814de
create utc util; set timestamp on date obj
adamgibbons Aug 13, 2017
ab11302
add setDateWithLocalTime util
adamgibbons Aug 14, 2017
0261f09
rename util func
adamgibbons Aug 14, 2017
54c2d73
rename util func
adamgibbons Aug 14, 2017
de631cf
create buildEvent; stubt out formatEvent
adamgibbons Aug 16, 2017
c52b5dc
build out formatEvent func
adamgibbons Aug 16, 2017
9faef98
add notes on rfc 5545
adamgibbons Aug 17, 2017
c13d4c5
add notes
adamgibbons Aug 17, 2017
65b0d32
merge default with overwritten event props
adamgibbons Aug 17, 2017
9b6bb96
support custom uid param
adamgibbons Aug 17, 2017
4174d9b
support dtstart param; default for now to setting date-time in utc
adamgibbons Aug 17, 2017
848c673
support dtend param
adamgibbons Aug 17, 2017
d1d8d8f
support description param
adamgibbons Aug 17, 2017
80422b4
add notes
adamgibbons Aug 17, 2017
1af09ee
checks stuff off
adamgibbons Aug 17, 2017
f5a29b2
support url param
adamgibbons Aug 18, 2017
ea97781
support write for url param
adamgibbons Aug 18, 2017
a6cad5b
add failing test for buildEvent support for geolocation param
adamgibbons Aug 18, 2017
02d05dd
refactor build event with maybe util
adamgibbons Aug 18, 2017
6b3c0d2
support geo param
adamgibbons Aug 18, 2017
b814535
support location param
adamgibbons Aug 18, 2017
2f6273c
support status param
adamgibbons Aug 18, 2017
52a5ee0
support categories param
adamgibbons Aug 18, 2017
899bf63
support attendee param
adamgibbons Aug 19, 2017
54e8484
support organizer param
adamgibbons Aug 20, 2017
17fab4d
add calscale prop
adamgibbons Aug 20, 2017
869103c
support local, i.e. floating time for start, end params
adamgibbons Aug 22, 2017
64ca90e
add createEvent func
adamgibbons Aug 23, 2017
db50ebe
update readme
adamgibbons Aug 23, 2017
f0e2e09
use joi to validate isValidStatus func
adamgibbons Aug 29, 2017
bbd7d42
begin schema validation
adamgibbons Aug 29, 2017
7a78664
build out schema
adamgibbons Aug 29, 2017
ff5bfd6
validate organizer against joi schema
adamgibbons Aug 30, 2017
1fe1560
validate attendees against joi schema
adamgibbons Aug 30, 2017
14b1251
remove .only
adamgibbons Aug 30, 2017
6c8278a
move setGeolocation into utils
adamgibbons Aug 30, 2017
5b44e72
move setContact into utils
adamgibbons Aug 30, 2017
19e314b
move defaults into file
adamgibbons Aug 30, 2017
0810146
add note
adamgibbons Aug 30, 2017
d00689f
introduce pipeline; create validate function
adamgibbons Aug 31, 2017
6ffde07
move build function into pipeline
adamgibbons Aug 31, 2017
a464ab6
move format function into pipeline
adamgibbons Aug 31, 2017
f517473
remove schema validation logic from build stage
adamgibbons Aug 31, 2017
3ec9233
clean up
adamgibbons Aug 31, 2017
0951468
more cleanup
adamgibbons Aug 31, 2017
5546e8e
more cleanup
adamgibbons Aug 31, 2017
4630865
update travis node v
adamgibbons Sep 3, 2017
394e6f6
require mocha as dev dep
adamgibbons Sep 3, 2017
17b45fe
update readme
adamgibbons Sep 3, 2017
e7f9f98
comment out failing tests
adamgibbons Sep 3, 2017
239c062
validate alarm component
adamgibbons Sep 3, 2017
70a738b
begin build phase for alarm prop
adamgibbons Sep 4, 2017
d5f8554
build alarm component
adamgibbons Sep 4, 2017
b1c98cc
set alarm component in build phase
adamgibbons Sep 4, 2017
d8f3667
begin format phase of alarm component
adamgibbons Sep 4, 2017
99f708e
build out format phase of alarm event
adamgibbons Sep 4, 2017
026b732
set alarm duration
adamgibbons Sep 13, 2017
911be83
set alarm attachment
adamgibbons Sep 13, 2017
cabee27
suppoart alarm trigger, summary args
adamgibbons Sep 14, 2017
b6da609
resolve merge conflict
adamgibbons Sep 14, 2017
ec3e87a
merge stash
adamgibbons Sep 14, 2017
e613dda
clena up validate dependencies
adamgibbons Sep 15, 2017
5dd0443
fix alarm test
adamgibbons Sep 15, 2017
12efcdc
add test
adamgibbons Sep 16, 2017
edca1fd
fix set alarm
adamgibbons Sep 16, 2017
64e540f
straight out build, format alarm pipeline
adamgibbons Sep 16, 2017
c598e5f
ignore more
adamgibbons Sep 17, 2017
f66aaf3
add build command to npm
adamgibbons Sep 17, 2017
ba28ecb
remove logs
adamgibbons Sep 17, 2017
9f53ace
remove test
adamgibbons Sep 17, 2017
d43a349
ignore test file
adamgibbons Sep 17, 2017
493f7d7
remove legacy validation logic from build stage
adamgibbons Sep 17, 2017
5a8b5d9
begin testing create event more thoroughly; update geolocation format…
adamgibbons Sep 17, 2017
fb5f6b6
fix typo
adamgibbons Sep 17, 2017
5f03826
fix broken formatting tests
adamgibbons Sep 17, 2017
6b38fcc
complete pipeline reorder
adamgibbons Sep 19, 2017
4e2a31e
Merge branch 'v2-pipeline-reorder' into v2
adamgibbons Sep 19, 2017
d0eb9a7
move setDate from build to format
adamgibbons Sep 19, 2017
2cafcae
remove duplciate geolocation logic
adamgibbons Sep 19, 2017
02791ab
clean up alarm building, formatting
adamgibbons Sep 19, 2017
eda0356
rename createEvent to createEventSync
adamgibbons Sep 20, 2017
56c5803
add createEvent with callback pattern
adamgibbons Sep 20, 2017
da6e4e3
update readme
adamgibbons Sep 20, 2017
bf7cb76
udpate readme
adamgibbons Sep 20, 2017
3558f8e
continue improvign readme
adamgibbons Sep 20, 2017
b7ada5c
correct schema tests
adamgibbons Sep 20, 2017
791db79
un-require end from schema
adamgibbons Sep 21, 2017
c289ac5
update readme
adamgibbons Sep 21, 2017
2b12297
remove new
adamgibbons Sep 21, 2017
e4deb97
attempt codeclimate correction
adamgibbons Sep 21, 2017
c0e23db
fix codeclimate issue
adamgibbons Sep 21, 2017
d9796c9
remove console logs
adamgibbons Sep 21, 2017
a085458
loosen start val in test
adamgibbons Sep 22, 2017
be50d03
loosen start val test in pipeline.formatEvent
adamgibbons Sep 22, 2017
2763197
loosen start val test in setAlarm util
adamgibbons Sep 22, 2017
99621f0
set utc date test to pending
adamgibbons Sep 22, 2017
6c57691
set setDate test to pending
adamgibbons Sep 22, 2017
425fd53
remove maybe
adamgibbons Sep 23, 2017
1ac2b2d
set createEvent tests to pending
adamgibbons Sep 23, 2017
4bc7951
try moving done
adamgibbons Sep 23, 2017
06325cc
troubleshoot failing tests: comment out index spec
adamgibbons Sep 23, 2017
3ea3176
uncomments tests
adamgibbons Sep 23, 2017
fa3aed7
remove watch option from mocha test command
adamgibbons Sep 23, 2017
e242292
update readme
adamgibbons Sep 24, 2017
8fb4a12
update readme
adamgibbons Sep 24, 2017
8ac53fb
update readme
adamgibbons Sep 24, 2017
dabbf4c
add develop section to readme
adamgibbons Sep 24, 2017
a1c2c6b
remove legacy files
adamgibbons Sep 24, 2017
1170217
rename geolocation to geo
adamgibbons Sep 24, 2017
c6260d4
improve set-time apis
adamgibbons Sep 25, 2017
451d963
uppercase status
adamgibbons Sep 25, 2017
135a263
update readme
adamgibbons Sep 25, 2017
f8020f5
update readme
adamgibbons Sep 25, 2017
c981259
keep on updating that readme
adamgibbons Sep 25, 2017
93c2bea
update readme
adamgibbons Sep 25, 2017
94f34ab
comment out utils.setDate test
adamgibbons Sep 29, 2017
9076287
make cb arg optional in createEvent; remove createEventSync
adamgibbons Sep 30, 2017
dec02ae
move formatDuration into utils
adamgibbons Sep 30, 2017
a5a4d12
update gitignore
adamgibbons Sep 30, 2017
6f596f4
fix DTEND formatting, loosen some tests
adamgibbons Oct 1, 2017
82afc59
update geo
adamgibbons Oct 1, 2017
714ac7c
bump verion
adamgibbons Oct 1, 2017
3a467d4
don't ignore dist dir
adamgibbons Oct 1, 2017
5c9fa7a
add dist dir
adamgibbons Oct 1, 2017
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"presets": ["env"]
}
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
node_modules
node_modules
.DS_Store
write-event.js
output.ics
3 changes: 1 addition & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
language: node_js
node_js:
- '0.12'
- '0.11'
- '7'
deploy:
provider: npm
email: adam.d.gibbons+ics@gmail.com
Expand Down
190 changes: 104 additions & 86 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,122 +13,140 @@ The [iCalendar](http://tools.ietf.org/html/rfc5545) generator

## Example Usage

Generate an iCalendar event:
1. Create an iCalendar event:

```javascript
var ICS = require('ics');
import ics from 'ics'

var ics = new ICS();

ics.buildEvent({
uid: 'abc123', // (optional)
start: '2016-05-30 06:50',
end: '2016-05-30 15:00',
const event = {
start: [2018, 5, 30, 6, 30],
duration: [{ hours: 6, minutes: 30 }],
title: 'Bolder Boulder',
description: 'Annual 10-kilometer run in Boulder, Colorado',
location: 'Folsom Field, University of Colorado (finish line)',
url: 'http://www.bolderboulder.com/',
status: 'confirmed',
geo: { lat: 40.0095, lon: 105.2669 },
categories: ['10k races', 'Memorial Day Weekend', 'Boulder CO'],
status: 'CONFIRMED',
organizer: [{ name: 'Admin', email: 'Race@BolderBOULDER.com' }],
attendees: [
{ name: 'Adam Gibbons', email: 'adam@example.com' },
{ name: 'Brittany Seaton', email: 'brittany@example2.org' }
],
categories: ['10k races', 'Memorial Day Weekend', 'Boulder CO'],
alarms:[
{ action: 'DISPLAY', trigger: '-PT24H', description: 'Reminder', repeat: true, duration: 'PT15M' },
{ action: 'AUDIO', trigger: '-PT30M' }
]
});

}

ics.createEvent(event, (error, value) => {
if (err) {
console.log(err)
}

console.log(value)
// BEGIN:VCALENDAR
// VERSION:2.0
// CALSCALE:GREGORIAN
// PRODID:adamgibbons/ics
// BEGIN:VEVENT
// UID:4c897030-a1a9-11e7-8f07-f32dee16cf9b
// SUMMARY:Bolder Boulder
// DTSTAMP:20170925T102300Z
// DTSTART:20180530T123000Z
// DESCRIPTION:Annual 10-kilometer run in Boulder, Colorado
// URL:http://www.bolderboulder.com/
// LOCATION:Folsom Field, University of Colorado (finish line)
// STATUS:CONFIRMED
// CATEGORIES:10k races,Memorial Day Weekend,Boulder CO
// ATTENDEE;CN=Adam Gibbons:mailto:adam@example.com
// ATTENDEE;CN=Brittany Seaton:mailto:brittany@example2.org
// DURATION:PT1H
// END:VEVENT
// END:VCALENDAR

})
```

The above snippet will return this:

```
BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:-//Adam Gibbons//agibbons.com//ICS: iCalendar Generator
BEGIN:VEVENT
UID:2073c980-9545-11e6-99f9-791bff9883ed
DTSTAMP:20161018T151121Z
DTSTART:20160530T065000
DTEND:20160530T150000
SUMMARY:Bolder Boulder
DESCRIPTION:Annual 10-kilometer run in Boulder, Colorado
LOCATION:Folsom Field, University of Colorado (finish line)
URL:http://www.bolderboulder.com/
STATUS:confirmed
GEO:40.0095;105.2669
ATTENDEE;CN=Adam Gibbons:mailto:adam@example.com
ATTENDEE;CN=Brittany Seaton:mailto:brittany@example2.org
CATEGORIES:10k races,Memorial Day Weekend,Boulder CO
BEGIN:VALARM
ACTION:DISPLAY
TRIGGER:-PT24H
DESCRIPTION:Reminder
REPEAT:1
DURATION:PT15M
END:VALARM
BEGIN:VALARM
ACTION:AUDIO
TRIGGER:-PT30M
END:VALARM
END:VEVENT
END:VCALENDAR

Write an iCalendar file:
```javascript
import { writeFileSync } from 'fs'
import ics from 'ics'

ics.createEvent({
title: 'Dinner',
description: 'Nightly thing I do',
start: [2018, 1, 15, 6, 30],
duration: { minutes: 50 }
}, (error, value) => {
if (error) {
console.log(error)
}

fs.writeFileSync(`${__dirname}/event.ics`, value)
})
```

## API

### `buildEvent(attributes)`
### `createEvent(attributes, [callback])`

Returns an iCal-compliant text string.
If callback is provided, returns a Node-style callback.
If callback is not provided, returns an object with error and value properties.

#### `attributes`

Optional. Object literal attributes of the event. Accepts the following properties:
Object literal containing event information.
Only the `start` property is required.
The following properties are accepted:

| Property | Description | Default |
| ------------- | ------------- | ----------
| start | ISO 8601 date (`yyyymmdd`) or datetime (`yyyymmddThhmm`) string. | Today (as ISO 8601 date string)
| end | Event end date/time string. Must match `start` ISO 8601 value type. | If `start` value is date, next day; if value is datetime, same value as `start`.
| title | String. Title of event.
| description | String. Description of event.
| location | String. Intended venue, e.g. `Room 101`.
| geo | Object literal. Geographic coordinates (lat/lon) as floats, e.g. `{lat: 38.9072, lon: 77.0369}`.
| url | String. URL associated with event.
| status | String. Must be one of: `tentative`, `confirmed`, or `cancelled`.
| attendees | Array of object literals, e.g. `{name: 'Foo', email: 'foo@example.com'}`.
| categories | Array of string values.
| alarms | Array of object literals, e.g. `{ action: 'DISPLAY', trigger: '-PT30M' }`. For details on parameters, see the [spec](https://icalendar.org/iCalendar-RFC-5545/3-6-6-alarm-component.html).

### `createEvent(attributes[, options], cb)`

Asynchronously writes an iCal file. Returns a callback with the stringified event.

#### `options`
Optional. Object literal accepting the following properties:

| Property | Description | Default |
| Property | Description | Example |
| ------------- | ------------- | ----------
| filepath | Filename, relative path + filename, or absolute path + filename. | Absolute path to current working directory, plus `event.ics`. E.g. `/Users/gibber/my-project/event.ics`
| start | **Required**. Date and time in your timezone at which the event begins. | `[2000, 1, 5, 10, 0]` (January 5, 2000 at 10am in your timezone)
| end | Time at which event ends. *Either* `end` or `duration` is required, but *not* both. | `[2000, 1, 5, 13, 5]` (January 5, 2000 at 1pm)
| duration | How long the event lasts. Object literal having form `{ weeks, days, hours, minutes, seconds }` *Either* `end` or `duration` is required, but *not* both. | `{ hours: 1, minutes: 45 }` (1 hour and 45 minutes)
| title | Title of event. | `'Code review'`
| description | Description of event. | `'A constructive roasting of those seeking to merge into master branch'`
| location | Intended venue | `Mountain Sun Pub and Brewery`.
| geo | Geographic coordinates (lat/lon) | `{ lat: 38.9072, lon: 77.0369 }`
| url | URL associated with event | `'http://www.mountainsunpub.com/'`
| status | Three statuses are allowed: `tentative`, `confirmed`, or `cancelled` | `confirmed`
| organizer | Person organizing the event | `{name: 'Adam Gibbons', email: 'adam@example.com'}`
| attendees | Persons invited to the event | `[{ name: 'Mo', email: 'mo@foo.com'}, { name: 'Bo', email: 'bo@bar.biz' }]`
| categories | Categories associated with the event | `['hacknight', 'stout month']`
| alarms | Alerts that can be set to trigger before, during, or after the event | `{ action: 'DISPLAY', trigger: '-PT30M' }`

#### `callback`

Optional.
Node-style callback.

`filepath` accepts relative or absolute paths. For example, these
values resolve to `/Users/gibber/my-event.ics` when executed from `/Users/gibber`:
```
function (err, value) {
if (err) {
// if iCal generation fails, err is an object containing the reason
// if iCal generation succeeds, err is null
}

console.log(value) // iCal-compliant text string
}
```

- `my-event`
- `my-event.ics`
- `/Users/gibber/my-event`
- `/Users/gibber/my-event.ics`
## Develop

...and these will resolve to `/Users/my-event.ics` when executed from `/Users/gibber`:
Run mocha tests and watch for changes:
```
npm start
```

- `../my-event`
- `../my-event.ics`
Run tests once and exit:
```
npm test
```

Build the project, compiling all ES6 files within the `src` directory into vanilla JavaScript in the `dist` directory.
```
npm run build
```

## References

- [RFC 5545: Internet Calendaring and Scheduling Core Object Specification (iCalendar)](http://tools.ietf.org/html/rfc5545)
- [iCalendar Validator](http://icalendar.org/validator.html#results)
- [iCalendar Validator](http://icalendar.org/validator.html#results)
32 changes: 32 additions & 0 deletions dist/defaults.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
'use strict';

Object.defineProperty(exports, "__esModule", {
value: true
});

var _v = require('uuid/v1');

var _v2 = _interopRequireDefault(_v);

var _moment = require('moment');

var _moment2 = _interopRequireDefault(_moment);

var _utils = require('./utils');

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var now = (0, _moment2.default)().utc();

var defaults = {
title: 'Untitled event',
productId: 'adamgibbons/ics',
uid: (0, _v2.default)(),
timestamp: (0, _utils.setDateWithUTCtime)([now.get('year'), now.get('month') + 1, now.get('date'), now.get('hours'), now.get('minutes'), now.get('seconds')]),
start: (0, _utils.setDateWithUTCtime)(),
duration: {
hours: 1
}
};

exports.default = defaults;
49 changes: 49 additions & 0 deletions dist/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
'use strict';

Object.defineProperty(exports, "__esModule", {
value: true
});
exports.createEvent = createEvent;

var _lodash = require('lodash');

var _lodash2 = _interopRequireDefault(_lodash);

var _pipeline = require('./pipeline');

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function createEvent(attributes, cb) {
if (!attributes) {
Error('attributes argument is required');
}

if (!cb) {
// No callback, so return error or value in an object
var _validateEvent = (0, _pipeline.validateEvent)((0, _pipeline.buildEvent)(attributes)),
_error = _validateEvent.error,
_value = _validateEvent.value;

if (_error) return { error: _error, value: _value };

var event = '';

try {
event = (0, _pipeline.formatEvent)(_value);
} catch (error) {
return { error: error, value: null };
}

return { error: null, value: event };
}

// Return a node-style callback

var _validateEvent2 = (0, _pipeline.validateEvent)((0, _pipeline.buildEvent)(attributes)),
error = _validateEvent2.error,
value = _validateEvent2.value;

if (error) return cb(error);

return cb(null, (0, _pipeline.formatEvent)(value));
}
45 changes: 45 additions & 0 deletions dist/pipeline/build.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
'use strict';

Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = buildEvent;

var _lodash = require('lodash');

var _lodash2 = _interopRequireDefault(_lodash);

var _defaults = require('../defaults');

var _defaults2 = _interopRequireDefault(_defaults);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function buildEvent() {
var attributes = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var title = attributes.title,
productId = attributes.productId,
uid = attributes.uid,
start = attributes.start,
startType = attributes.startType,
duration = attributes.duration,
end = attributes.end,
description = attributes.description,
url = attributes.url,
geo = attributes.geo,
location = attributes.location,
status = attributes.status,
categories = attributes.categories,
organizer = attributes.organizer,
attendees = attributes.attendees,
alarms = attributes.alarms;

// fill in default values where necessary

var output = Object.assign({}, _defaults2.default, attributes);

// remove falsey values
var cleanOutput = _lodash2.default.pickBy(output, _lodash2.default.identity);

return cleanOutput;
}
Loading