diff --git a/.gitignore b/.gitignore index a048be2..0ee2c9b 100644 --- a/.gitignore +++ b/.gitignore @@ -37,3 +37,6 @@ node_modules .vscode lib/ +.eslintrc.json +jsconfig.json + diff --git a/README.md b/README.md index 861c7da..6d950ae 100644 --- a/README.md +++ b/README.md @@ -69,9 +69,21 @@ npm install eventstore-node node app.js ``` -## Porting .Net Task to Node.js +### Example: Subscribing to events -.Net Task have been replace with Promise. When executing an async command, i.e. appendToStream you can use then/catch to wait for result/error. +```cd samples``` + +To subscribe to all events from now on (includes example of a filter which ignores events which we aren't interested in): + +```node subscribe-all-events.js``` + +To catch up on all events ever and subscribe to all new ones from now on: + +```node subscribe-catchup-all-events.js``` + +To generate a test event, open a separate console and run: + +```node store-event.js``` ## Running the tests @@ -83,6 +95,10 @@ To execute the tests suites simply run npm test +## Porting .Net Task to Node.js + +.Net Task have been replace with Promise. When executing an async command, i.e. appendToStream you can use then/catch to wait for result/error. + ## License Ported code is released under the MIT license, see [LICENSE](https://github.com/nicdex/eventstore-node/blob/master/LICENSE). diff --git a/samples/store-event.js b/samples/store-event.js new file mode 100644 index 0000000..a648b6e --- /dev/null +++ b/samples/store-event.js @@ -0,0 +1,40 @@ +var esClient = require('../src/client'); // When running in 'eventstore-node/samples' folder. +// var esClient = require('eventstore-node'); // Otherwise +var uuid = require('uuid'); + +var esConnection = esClient.createConnection({}, {"hostname": "localhost", "port": 1113}); +esConnection.connect(); +esConnection.once('connected', function (tcpEndPoint) { + console.log('Connected to eventstore at ' + tcpEndPoint.hostname + ":" + tcpEndPoint.port); + var userId = uuid.v4(); + // This event could happen as a result of (e.g.) a 'CreateUser(id, username, password)' command. + var userCreatedEvent = { + id: userId, + username: "user" + uuid.v4().substring(0,6), // Hard-to-spell exotic username. + password: Math.random().toString() // Hard-to-guess password. + }; + var eventId = uuid.v4(); + var event = esClient.createJsonEventData(eventId, userCreatedEvent, null, "UserCreated"); + // Every user has her/his own stream of events: + var streamName = "user-" + userId; + console.log("Storing event. Look for it at http://localhost:2113/web/index.html#/streams/user-" + userId); + esConnection.appendToStream(streamName, esClient.expectedVersion.any, event) + .then(function(result) { + console.log("Event stored."); + process.exit(0); + }) + .catch(function(err) { + console.log(err); + process.exit(-1); + }); +}); + +esConnection.on('error', function (err) { + console.log('Error occurred on connection:', err); + process.exit(-1); +}); + +esConnection.on('closed', function (reason) { + console.log('Connection closed, reason:', reason); + process.exit(-1); +}); diff --git a/samples/subscribe-all-events.js b/samples/subscribe-all-events.js new file mode 100644 index 0000000..5f6b7d7 --- /dev/null +++ b/samples/subscribe-all-events.js @@ -0,0 +1,48 @@ +// Subscribe to all new events on the $all stream. Filter out any which aren't about "user" aggregates. + +var esClient = require('../src/client'); // When running in 'eventstore-node/samples' folder. +// var esClient = require('eventstore-node'); // Otherwise + +const credentialsForAllEventsStream = new esClient.UserCredentials("admin", "changeit"); +const resolveLinkTos = false; + +var esConnection = esClient.createConnection({}, {"hostname": "localhost", "port": 1113}); +esConnection.connect(); +esConnection.once('connected', function (tcpEndPoint) { + console.log('Connected to eventstore at ' + tcpEndPoint.hostname + ":" + tcpEndPoint.port); + esConnection.subscribeToAll(resolveLinkTos, eventAppeared, subscriptionDropped, credentialsForAllEventsStream) + .then(function(subscription) { + console.log("subscription.isSubscribedToAll: " + subscription.isSubscribedToAll); + console.log("(To generate a test event, try running 'node store-event.js' in a separate console.)") + }); +}); + +function belongsToAUserAggregate(event) { + return event.originalEvent.eventStreamId.startsWith("user-") +} + +function eventAppeared(subscription, event) { + // Ignore all events which aren't about users: + if(belongsToAUserAggregate(event)) { + var aggregateId = event.originalEvent.eventStreamId; + var eventId = event.originalEvent.eventId; + var eventType = event.originalEvent.eventType; + console.log(aggregateId, eventType, eventId); + console.log(event.originalEvent.data.toString() + "\n"); + } +} + +function subscriptionDropped(subscription, reason, error) { + if (error) { + console.log(error); + } + console.log('Subscription dropped.'); +} + +esConnection.on('error', function (err) { + console.log('Error occurred on connection:', err); +}); + +esConnection.on('closed', function (reason) { + console.log('Connection closed, reason:', reason); +}); diff --git a/samples/subscribe-catchup-all-events.js b/samples/subscribe-catchup-all-events.js new file mode 100644 index 0000000..dac2e30 --- /dev/null +++ b/samples/subscribe-catchup-all-events.js @@ -0,0 +1,51 @@ +// Subscribe to all events on the $all stream. Catch up from the beginning, then listen for any new events as they occur. +// This can be used (e.g.) for subscribers which populate read models. + +var esClient = require('../src/client'); // When running in 'eventstore-node/samples' folder. +// var esClient = require('eventstore-node'); // Otherwise + +const credentialsForAllEventsStream = new esClient.UserCredentials("admin", "changeit"); + +var esConnection = esClient.createConnection({}, {"hostname": "localhost", "port": 1113}); +esConnection.connect(); +esConnection.once('connected', function (tcpEndPoint) { + console.log('Connected to eventstore at ' + tcpEndPoint.hostname + ":" + tcpEndPoint.port); + var subscription = esConnection.subscribeToAllFrom(null, true, eventAppeared, liveProcessingStarted, subscriptionDropped, credentialsForAllEventsStream); + console.log("subscription.isSubscribedToAll: " + subscription.isSubscribedToAll); +}); + +function eventAppeared(subscription, event) { + // This is where to filter out events which the subscriber isn't interested in. + // For an example, see 'subscribe-all-events.js'. + console.log(event.originalEvent.eventStreamId); +} + +function subscriptionDropped(subscription, reason, error) { + if (error) { + console.log(error); + } + console.log('Subscription dropped.'); +} + +function liveProcessingStarted() { + console.log("Caught up with previously stored events. Listening for new events."); + console.log("(To generate a test event, try running 'node store-event.js' in a separate console.)") +} + +function eventAppeared(stream, event) { + console.log(event.originalEvent.eventStreamId, event.originalEvent.eventId, event.originalEvent.eventType); + // Data: + // console.log(event.originalEvent.data.toString()); + + // Position in the event stream. Can be persisted and used to catch up with missed events when re-starting subscribers instead of re-reading + // all events from the beginning. + // console.log(event.originalPosition); +} + +esConnection.on('error', function (err) { + console.log('Error occurred on connection:', err); +}); + +esConnection.on('closed', function (reason) { + console.log('Connection closed, reason:', reason); +});