UNPKG

node-eventstore-client

Version:

A port of the EventStore .Net ClientAPI to Node.js

1,502 lines (1,342 loc) 253 kB
/******/ (() => { // webpackBootstrap /******/ var __webpack_modules__ = ([ /* 0 */, /* 1 */ /***/ ((module) => { const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i; function isValidId(id) { if (typeof id !== 'string') return false; return uuidRegex.test(id); } /** * Create an EventData * @private * @param {string} eventId * @param {string} type * @param {boolean} [isJson] * @param {Buffer} [data] * @param {Buffer} [metadata] * @constructor */ function EventData(eventId, type, isJson, data, metadata) { if (!isValidId(eventId)) throw new TypeError("eventId must be a string containing a UUID."); if (typeof type !== 'string' || type === '') throw new TypeError("type must be a non-empty string."); if (isJson && typeof isJson !== 'boolean') throw new TypeError("isJson must be a boolean."); if (data && !Buffer.isBuffer(data)) throw new TypeError("data must be a Buffer."); if (metadata && !Buffer.isBuffer(metadata)) throw new TypeError("metadata must be a Buffer."); this.eventId = eventId; this.type = type; this.isJson = isJson || false; this.data = data || Buffer.alloc(0); this.metadata = metadata || Buffer.alloc(0); Object.freeze(this); } module.exports = EventData; /***/ }), /* 2 */ /***/ ((__unused_webpack_module, exports, __webpack_require__) => { var guidParse = __webpack_require__(3); var Long = __webpack_require__(4); var ensure = __webpack_require__(5); /** * @public * @param {!number|!Long} commitPosition * @param {!number|!Long} preparePosition * @constructor * @property {!Long} commitPosition * @property {!Long} preparePosition */ function Position(commitPosition, preparePosition) { ensure.notNull(commitPosition, "commitPosition"); ensure.notNull(preparePosition, "preparePosition"); this.commitPosition = Long.fromValue(commitPosition); this.preparePosition = Long.fromValue(preparePosition); Object.freeze(this); } Position.prototype.compareTo = function(other) { if (this.commitPosition.lt(other.commitPosition) || (this.commitPosition.eq(other.commitPosition)&& this.preparePosition.lt(other.preparePosition))) { return -1; } if (this.commitPosition.gt(other.commitPosition) || (this.commitPosition.eq(other.commitPosition) && this.preparePosition.gt(other.preparePosition))) { return 1; } return 0; }; Position.prototype.toString = function() { return [this.commitPosition.toString(), this.preparePosition.toString()].join("/"); }; Position.start = new Position(0,0); Position.end = new Position(-1,-1); const EventReadStatus = Object.freeze({ Success: 'success', NotFound: 'notFound', NoStream: 'noStream', StreamDeleted: 'streamDeleted' }); /** * @param {object} ev * @constructor * @property {string} eventStreamId * @property {string} eventId * @property {Long} eventNumber * @property {string} eventType * @property {Date} created * @property {number} createdEpoch * @property {?Buffer} data * @property {?Buffer} metadata * @property {boolean} isJson */ function RecordedEvent(ev) { this.eventStreamId = ev.eventStreamId; this.eventId = guidParse.unparse(ev.eventId); this.eventNumber = ev.eventNumber; this.eventType = ev.eventType; this.created = new Date(ev.createdEpoch ? ev.createdEpoch.toNumber() : 0); this.createdEpoch = ev.createdEpoch ? ev.createdEpoch.toNumber() : 0; this.data = ev.data ? ev.data : Buffer.alloc(0); this.metadata = ev.metadata ? ev.metadata : Buffer.alloc(0); this.isJson = ev.dataContentType === 1; Object.freeze(this); } /** * @param {object} ev * @constructor * @property {?RecordedEvent} event * @property {?RecordedEvent} link * @property {?RecordedEvent} originalEvent * @property {boolean} isResolved * @property {?Position} originalPosition * @property {string} originalStreamId * @property {Long} originalEventNumber */ function ResolvedEvent(ev) { this.event = ev.event === null ? null : new RecordedEvent(ev.event); this.link = ev.link === null ? null : new RecordedEvent(ev.link); this.originalEvent = this.link || this.event; this.isResolved = this.link !== null && this.event !== null; this.originalPosition = (ev.commitPosition && ev.preparePosition) ? new Position(ev.commitPosition, ev.preparePosition) : null; this.originalStreamId = this.originalEvent && this.originalEvent.eventStreamId; this.originalEventNumber = this.originalEvent && this.originalEvent.eventNumber; Object.freeze(this); } /** * * @param {string} status * @param {string} stream * @param {Long} eventNumber * @param {object} event * @constructor * @property {string} status * @property {string} stream * @property {Long} eventNumber * @property {ResolvedEvent} event */ function EventReadResult(status, stream, eventNumber, event) { this.status = status; this.stream = stream; this.eventNumber = eventNumber; this.event = status === EventReadStatus.Success ? new ResolvedEvent(event) : null; Object.freeze(this); } /** * @param {number} nextExpectedVersion * @param {Position} logPosition * @constructor * @property {Long} nextExpectedVersion * @property {Position} logPosition */ function WriteResult(nextExpectedVersion, logPosition) { this.nextExpectedVersion = nextExpectedVersion; this.logPosition = logPosition; Object.freeze(this); } /** * @param {string} status * @param {string} stream * @param {Long} fromEventNumber * @param {string} readDirection * @param {object[]} events * @param {Long} nextEventNumber * @param {Long} lastEventNumber * @param {boolean} isEndOfStream * @constructor * @property {string} status * @property {string} stream * @property {Long} fromEventNumber * @property {string} readDirection * @property {ResolvedEvent[]} events * @property {Long} nextEventNumber * @property {Long} lastEventNumber * @property {boolean} isEndOfStream */ function StreamEventsSlice( status, stream, fromEventNumber, readDirection, events, nextEventNumber, lastEventNumber, isEndOfStream ) { this.status = status; this.stream = stream; this.fromEventNumber = fromEventNumber; this.readDirection = readDirection; this.events = events ? events.map(function(ev) { return new ResolvedEvent(ev); }) : []; this.nextEventNumber = nextEventNumber; this.lastEventNumber = lastEventNumber; this.isEndOfStream = isEndOfStream; Object.freeze(this); } /** * @param {string} readDirection * @param {Position} fromPosition * @param {Position} nextPosition * @param {ResolvedEvent[]} events * @constructor * @property {string} readDirection * @property {Position} fromPosition * @property {Position} nextPosition * @property {ResolvedEvent[]} events */ function AllEventsSlice(readDirection, fromPosition, nextPosition, events) { this.readDirection = readDirection; this.fromPosition = fromPosition; this.nextPosition = nextPosition; this.events = events ? events.map(function(ev){ return new ResolvedEvent(ev); }) : []; this.isEndOfStream = events === null || events.length === 0; Object.freeze(this); } /** * @param {Position} logPosition * @constructor * @property {Position} logPosition */ function DeleteResult(logPosition) { this.logPosition = logPosition; Object.freeze(this); } /** * @param {string} stream * @param {boolean} isStreamDeleted * @param {Long} metastreamVersion * @param {object} streamMetadata * @constructor * @property {string} stream * @property {boolean} isStreamDeleted * @property {Long} metastreamVersion * @property {object} streamMetadata */ function RawStreamMetadataResult(stream, isStreamDeleted, metastreamVersion, streamMetadata) { ensure.notNullOrEmpty(stream); this.stream = stream; this.isStreamDeleted = isStreamDeleted; this.metastreamVersion = metastreamVersion; this.streamMetadata = streamMetadata; Object.freeze(this); } const PersistentSubscriptionCreateStatus = Object.freeze({ Success: 'success', NotFound: 'notFound', Failure: 'failure' }); /** * @param {string} status * @constructor * @property {string} status */ function PersistentSubscriptionCreateResult(status) { this.status = status; Object.freeze(this); } const PersistentSubscriptionUpdateStatus = Object.freeze({ Success: 'success', NotFound: 'notFound', Failure: 'failure', AccessDenied: 'accessDenied' }); /** * @param {string} status * @constructor * @property {string} status */ function PersistentSubscriptionUpdateResult(status) { this.status = status; Object.freeze(this); } const PersistentSubscriptionDeleteStatus = Object.freeze({ Success: 'success', Failure: 'failure' }); /** * @param {string} status * @constructor * @property {string} status */ function PersistentSubscriptionDeleteResult(status) { this.status = status; Object.freeze(this); } // Exports Constructors exports.Position = Position; exports.ResolvedEvent = ResolvedEvent; exports.EventReadStatus = EventReadStatus; exports.EventReadResult = EventReadResult; exports.WriteResult = WriteResult; exports.StreamEventsSlice = StreamEventsSlice; exports.AllEventsSlice = AllEventsSlice; exports.DeleteResult = DeleteResult; exports.RawStreamMetadataResult = RawStreamMetadataResult; exports.PersistentSubscriptionCreateResult = PersistentSubscriptionCreateResult; exports.PersistentSubscriptionCreateStatus = PersistentSubscriptionCreateStatus; exports.PersistentSubscriptionUpdateResult = PersistentSubscriptionUpdateResult; exports.PersistentSubscriptionUpdateStatus = PersistentSubscriptionUpdateStatus; exports.PersistentSubscriptionDeleteResult = PersistentSubscriptionDeleteResult; exports.PersistentSubscriptionDeleteStatus = PersistentSubscriptionDeleteStatus; /***/ }), /* 3 */ /***/ ((__unused_webpack_module, exports) => { "use strict"; // Maps for number <-> hex string conversion var _byteToHex = []; var _hexToByte = {}; for (var i = 0; i < 256; i++) { _byteToHex[i] = (i + 0x100).toString(16).substr(1); _hexToByte[_byteToHex[i]] = i; } // **`parse()` - Parse a UUID into it's component bytes** function parse(s, buf, offset) { const i = (buf && offset) || 0; var ii = 0; if (buf) buf.fill(0, i, i + 16); buf = buf || Buffer.alloc(16); s.toLowerCase().replace(/[0-9a-f]{2}/g, function(oct) { if (ii < 16) { // Don't overflow! buf[i + ii++] = _hexToByte[oct]; } }); var buf2 = Buffer.from(buf.slice(i, i + 16)); buf[i + 0] = buf2[3]; buf[i + 1] = buf2[2]; buf[i + 2] = buf2[1]; buf[i + 3] = buf2[0]; buf[i + 4] = buf2[5]; buf[i + 5] = buf2[4]; buf[i + 6] = buf2[7]; buf[i + 7] = buf2[6]; return buf; } // **`unparse()` - Convert UUID byte array (ala parse()) into a string** function unparse(buf, offset) { var i = offset || 0; return '03020100-0504-0706-0809-101112131415'.replace(/\d{2}/g, function (num) { var j = parseInt(num, 10); return _byteToHex[buf[i+j]]; }) } exports.parse = parse; exports.unparse = unparse; /***/ }), /* 4 */ /***/ ((module) => { "use strict"; module.exports = require("long"); /***/ }), /* 5 */ /***/ ((module, __unused_webpack_exports, __webpack_require__) => { var Long = __webpack_require__(4); module.exports.notNullOrEmpty = function(value, name) { if (value === null) throw new TypeError(name + " should not be null."); if (value === '') throw new Error(name + " should not be empty."); }; module.exports.notNull = function(value, name) { if (value === null) throw new TypeError(name + " should not be null."); }; function isInteger(value, name) { if (typeof value !== 'number' || value % 1 !== 0) throw new TypeError(name + " should be an integer."); } module.exports.isInteger = isInteger; module.exports.isLongOrInteger = function(value, name) { if (typeof value === 'number') { return isInteger(value, name); } else if (!Long.isLong(value)) { throw new TypeError(name + " should be a Long|number."); } }; module.exports.isArrayOf = function(expectedType, value, name) { if (!Array.isArray(value)) throw new TypeError(name + " should be an array."); if (!value.every(function(x) { return x instanceof expectedType; })) { throw new TypeError([name, " should be an array of ", expectedType.name, "."].join("")); } }; module.exports.isTypeOf = function(expectedType, value, name, nullAllowed) { if (nullAllowed && value === null) return; if (!(value instanceof expectedType)) { throw new TypeError([name, " should be of type '", expectedType.name, "'", nullAllowed ? " or null" : "", "."].join("")); } }; module.exports.positive = function(value, name) { if (value <= 0) throw new Error(name + " should be positive."); }; module.exports.nonNegative = function(value, name) { if (value < 0) throw new Error(name + " should be non-negative."); }; /***/ }), /* 6 */ /***/ ((module, __unused_webpack_exports, __webpack_require__) => { var ensure = __webpack_require__(5); /** * @param {string} username * @param {string} password * @constructor * @property {string} username * @property {string} password */ function UserCredentials(username, password) { ensure.notNullOrEmpty(username, 'username'); ensure.notNullOrEmpty(password, 'password'); this.username = username; this.password = password; Object.freeze(this); } module.exports = UserCredentials; /***/ }), /* 7 */ /***/ ((module, __unused_webpack_exports, __webpack_require__) => { var SystemConsumerStrategies = __webpack_require__(8); var ensure = __webpack_require__(5); var Long = __webpack_require__(4); function PersistentSubscriptionSettings( resolveLinkTos, startFrom, extraStatistics, messageTimeout, maxRetryCount, liveBufferSize, readBatchSize, historyBufferSize, checkPointAfter, minCheckPointCount, maxCheckPointCount, maxSubscriberCount, namedConsumerStrategy ) { ensure.isLongOrInteger(startFrom); startFrom = Long.fromValue(startFrom); this.resolveLinkTos = resolveLinkTos; this.startFrom = startFrom; this.extraStatistics = extraStatistics; this.messageTimeout = messageTimeout; this.maxRetryCount = maxRetryCount; this.liveBufferSize = liveBufferSize; this.readBatchSize = readBatchSize; this.historyBufferSize = historyBufferSize; this.checkPointAfter = checkPointAfter; this.minCheckPointCount = minCheckPointCount; this.maxCheckPointCount = maxCheckPointCount; this.maxSubscriberCount = maxSubscriberCount; this.namedConsumerStrategy = namedConsumerStrategy; } PersistentSubscriptionSettings.create = function() { return new PersistentSubscriptionSettings(false, -1, false, 30000, 500, 500, 10, 20, 2000, 10, 1000, 0, SystemConsumerStrategies.RoundRobin); }; module.exports = PersistentSubscriptionSettings; /***/ }), /* 8 */ /***/ ((module) => { const SystemConsumerStrategies = Object.freeze({ DispatchToSingle: 'DispatchToSingle', RoundRobin: 'RoundRobin', Pinned: 'Pinned' }); module.exports = SystemConsumerStrategies; /***/ }), /* 9 */ /***/ ((module) => { function GossipSeed(endPoint, hostName, hostHeader) { if (typeof endPoint !== 'object' || !endPoint.host || !endPoint.port) throw new TypeError('endPoint must be have host and port properties.'); this.endPoint = endPoint; this.hostName = hostName; this.hostHeader = hostHeader; Object.freeze(this); } module.exports = GossipSeed; /***/ }), /* 10 */ /***/ ((module, __unused_webpack_exports, __webpack_require__) => { var EventStoreNodeConnection = __webpack_require__(11); var StaticEndpointDiscoverer = __webpack_require__(69); var ClusterDiscoverer = __webpack_require__(70); var NoopLogger = __webpack_require__(75); var ensure = __webpack_require__(5); const util = __webpack_require__(12); const http = __webpack_require__(76); const https = __webpack_require__(77); const dns = __webpack_require__(78); const dnsService = { lookup : util.promisify(dns.lookup), ADDRCONFIG: dns.ADDRCONFIG, V4MAPPED: dns.V4MAPPED }; var defaultConnectionSettings = Object.freeze({ log: new NoopLogger(), verboseLogging: false, maxQueueSize: 5000, maxConcurrentItems: 5000, maxRetries: 10, maxReconnections: 10, requireMaster: true, reconnectionDelay: 100, operationTimeout: 7*1000, operationTimeoutCheckPeriod: 1000, defaultUserCredentials: null, useSslConnection: false, targetHost: null, validateServer: false, failOnNoServerResponse: false, heartbeatInterval: 750, heartbeatTimeout: 1500, clientConnectionTimeout: 1000, // Cluster Settings clusterDns: '', maxDiscoverAttempts: 10, discoverDelay: 500, externalGossipPort: 0, gossipTimeout: 1000 }); function merge(a,b) { var c = {}; Object.getOwnPropertyNames(a).forEach(function(k) { c[k] = a[k]; }); Object.getOwnPropertyNames(b).forEach(function(k) { c[k] = b[k]; }); return c; } function createFromTcpEndpoint(settings, tcpEndpoint, connectionName) { if (!tcpEndpoint.port || !tcpEndpoint.host) throw new TypeError('endPoint object must have host and port properties.'); var mergedSettings = merge(defaultConnectionSettings, settings || {}); var endpointDiscoverer = new StaticEndpointDiscoverer(tcpEndpoint, settings.useSslConnection); return new EventStoreNodeConnection(mergedSettings, null, endpointDiscoverer, connectionName || null); } function createFromStringEndpoint(settings, endPoint, connectionName) { var m = endPoint.match(/^(tcp|discover):\/\/([^:]+):?(\d+)?$/); if (!m) throw new Error('endPoint string must be tcp://hostname[:port] or discover://dns[:port]'); var scheme = m[1]; var host = m[2] || null; var port = m[3] ? parseInt(m[3]) : null; if (scheme === 'tcp') { var tcpEndpoint = { host: host, port: port || 1113 }; return createFromTcpEndpoint(settings, tcpEndpoint, connectionName); } if (scheme === 'discover') { return createFromClusterDns(settings, host, port || 2113, connectionName); } throw new Error('Invalid scheme for endPoint: ' + scheme); } function createFromClusterDns(connectionSettings, clusterDns, externalGossipPort, connectionName) { ensure.notNull(connectionSettings, "connectionSettings"); ensure.notNull(clusterDns, "clusterDns"); var mergedSettings = merge(defaultConnectionSettings, connectionSettings || {}); var clusterSettings = { clusterDns: clusterDns, seeds: null, managerExternalHttpPort: externalGossipPort, maxDiscoverAttempts: mergedSettings.maxDiscoverAttempts, discoverDelay: mergedSettings.discoverDelay, gossipTimeout: mergedSettings.gossipTimeout, rejectUnauthorized: connectionSettings.useSslConnection ? connectionSettings.validateServer : undefined }; var endPointDiscoverer = new ClusterDiscoverer( mergedSettings.log, clusterSettings, dnsService, connectionSettings.useSslConnection ? https : http ); return new EventStoreNodeConnection(mergedSettings, clusterSettings, endPointDiscoverer, connectionName); } function createFromGossipSeeds(connectionSettings, gossipSeeds, connectionName) { ensure.notNull(connectionSettings, "connectionSettings"); ensure.notNull(gossipSeeds, "gossipSeeds"); var mergedSettings = merge(defaultConnectionSettings, connectionSettings || {}); var clusterSettings = { clusterDns: '', seeds: gossipSeeds, externalGossipPort: 0, maxDiscoverAttempts: mergedSettings.maxDiscoverAttempts, discoverDelay: mergedSettings.discoverDelay, gossipTimeout: mergedSettings.gossipTimeout, rejectUnauthorized: connectionSettings.useSslConnection ? connectionSettings.validateServer : undefined }; var endPointDiscoverer = new ClusterDiscoverer( mergedSettings.log, clusterSettings, dnsService, connectionSettings.useSslConnection ? https : http ); return new EventStoreNodeConnection(mergedSettings, clusterSettings, endPointDiscoverer, connectionName); } /** * Create an EventStore connection * @public * @alias createConnection * @param {object} settings * @param {boolean} [settings.verboseLogging=false] * @param {number} [settings.maxQueueSize=5000] * @param {number} [settings.maxConcurrentItems=5000] * @param {number} [settings.maxRetries=10] * @param {number} [settings.maxReconnections=10] * @param {boolean} [settings.requireMaster=true] * @param {number} [settings.reconnectionDelay=100] * @param {number} [settings.operationTimeout=7000] * @param {number} [settings.operationTimeoutCheckPeriod=1000] * @param {object} [settings.defaultUserCredentials=null] - The default user credentials to use for requests * @param {boolean} [settings.useSslConnection=false] - Whether to use SSL or not * @param {object} [settings.targetHost=null] * @param {boolean} [settings.validateServer=false] * @param {boolean} [settings.failOnNoServerResponse=false] * @param {number} [settings.heartbeatInterval=750] * @param {number} [settings.heartbeatTimeout=1500] * @param {number} [settings.clientConnectionTimeout=1000] * @param {string} [settings.clusterDns=''] * @param {number} [settings.maxDiscoverAttempts=10] * @param {number} [settings.externalGossipPort=0] * @param {number} [settings.gossipTimeout=1000] * @param {string|object|array} endPointOrGossipSeeds * @param {string} [connectionName] * @returns {EventStoreNodeConnection} */ module.exports.create = function(settings, endPointOrGossipSeeds, connectionName) { if (Array.isArray(endPointOrGossipSeeds)) return createFromGossipSeeds(settings, endPointOrGossipSeeds, connectionName); if (typeof endPointOrGossipSeeds === 'object') return createFromTcpEndpoint(settings, endPointOrGossipSeeds, connectionName); if (typeof endPointOrGossipSeeds === 'string') return createFromStringEndpoint(settings, endPointOrGossipSeeds, connectionName); throw new TypeError('endPointOrGossipSeeds must be an object, a string or an array.'); }; /***/ }), /* 11 */ /***/ ((module, __unused_webpack_exports, __webpack_require__) => { var util = __webpack_require__(12); var uuid = __webpack_require__(13); var Long = __webpack_require__(4); var EventEmitter = (__webpack_require__(14).EventEmitter); var ensure = __webpack_require__(5); var messages = __webpack_require__(15); var EventStoreConnectionLogicHandler = __webpack_require__(16); var DeleteStreamOperation = __webpack_require__(40); var AppendToStreamOperation = __webpack_require__(45); var StartTransactionOperation = __webpack_require__(46); var TransactionalWriteOperation = __webpack_require__(48); var CommitTransactionOperation = __webpack_require__(49); var ReadEventOperation = __webpack_require__(50); var ReadStreamEventsForwardOperation = __webpack_require__(51); var ReadStreamEventsBackwardOperation = __webpack_require__(55); var ReadAllEventsForwardOperation = __webpack_require__(56); var ReadAllEventsBackwardOperation = __webpack_require__(57); var CreatePersistentSubscriptionOperation = __webpack_require__(58); var UpdatePersistentSubscriptionOperation = __webpack_require__(59); var DeletePersistentSubscriptionOperation = __webpack_require__(60); var EventStoreTransaction = __webpack_require__(47); var EventStoreStreamCatchUpSubscription = __webpack_require__(61); var EventStoreAllCatchUpSubscription = __webpack_require__(63); var EventStorePersistentSubscription = __webpack_require__(64); var results = __webpack_require__(2); var systemStreams = __webpack_require__(67); var systemEventTypes = __webpack_require__(68); var EventData = __webpack_require__(1); const MaxReadSize = 4096; /** * @protected * @constructor */ function EventStoreNodeConnection(settings, clusterSettings, endpointDiscoverer, connectionName) { EventEmitter.call(this); this._connectionName = connectionName || ['ES-', uuid.v4()].join(''); this._settings = settings; this._clusterSettings = clusterSettings; this._endpointDiscoverer = endpointDiscoverer; this._handler = new EventStoreConnectionLogicHandler(this, settings); var self = this; this._handler.on('connected', function(e) { self.emit('connected', e); }); this._handler.on('disconnected', function(e) { self.emit('disconnected', e); }); this._handler.on('reconnecting', function(e) { self.emit('reconnecting', e); }); this._handler.on('closed', function(e) { self.emit('closed', e); }); this._handler.on('error', function(e) { self.emit('error', e); }); this._handler.on('heartbeatInfo', function(e) { self.emit('heartbeatInfo', e); }); } util.inherits(EventStoreNodeConnection, EventEmitter); Object.defineProperty(EventStoreNodeConnection.prototype, 'connectionName', { get: function() { return this._connectionName; } }); /** * Start connection task * @public * @returns {Promise} */ EventStoreNodeConnection.prototype.connect = function() { var self = this; return new Promise(function(resolve, reject) { function cb(err) { if (err) return reject(err); resolve(); } var startConnectionMessage = new messages.StartConnectionMessage(cb, self._endpointDiscoverer); self._handler.enqueueMessage(startConnectionMessage); }); }; /** * Close connection * @public */ EventStoreNodeConnection.prototype.close = function() { this._handler.enqueueMessage(new messages.CloseConnectionMessage("Connection close requested by client.", null)); }; /** * Delete a stream (async) * @public * @param {string} stream * @param {Long|number} expectedVersion * @param {boolean} [hardDelete] * @param {UserCredentials} [userCredentials] * @returns {Promise.<DeleteResult>} */ EventStoreNodeConnection.prototype.deleteStream = function(stream, expectedVersion, hardDelete, userCredentials) { ensure.notNullOrEmpty(stream, "stream"); ensure.isLongOrInteger(expectedVersion, "expectedVersion"); expectedVersion = Long.fromValue(expectedVersion); hardDelete = Boolean(hardDelete); userCredentials = userCredentials || null; var self = this; return new Promise(function(resolve, reject) { function cb(err, result) { if (err) return reject(err); resolve(result); } var deleteStreamOperation = new DeleteStreamOperation( self._settings.log, cb, self._settings.requireMaster, stream, expectedVersion, hardDelete, userCredentials); self._enqueueOperation(deleteStreamOperation); }); }; /** * Append events to a stream (async) * @public * @param {string} stream The name of the stream to which to append. * @param {Long|number} expectedVersion The version at which we currently expect the stream to be in order that an optimistic concurrency check can be performed. * @param {EventData[]|EventData} events The event(s) to append. * @param {UserCredentials} [userCredentials] User credentials * @returns {Promise.<WriteResult>} */ EventStoreNodeConnection.prototype.appendToStream = function(stream, expectedVersion, events, userCredentials) { ensure.notNullOrEmpty(stream, "stream"); ensure.isLongOrInteger(expectedVersion, "expectedVersion"); expectedVersion = Long.fromValue(expectedVersion); if (!Array.isArray(events)) events = [events]; ensure.isArrayOf(EventData, events, "events"); userCredentials = userCredentials || null; var self = this; return new Promise(function(resolve, reject) { function cb(err, result) { if (err) return reject(err); resolve(result); } var operation = new AppendToStreamOperation(self._settings.log, cb, self._settings.requireMaster, stream, expectedVersion, events, userCredentials); self._enqueueOperation(operation); }); }; /** * Start a transaction (async) * @public * @param {string} stream * @param {Long|number} expectedVersion * @param {UserCredentials} [userCredentials] * @returns {Promise.<EventStoreTransaction>} */ EventStoreNodeConnection.prototype.startTransaction = function(stream, expectedVersion, userCredentials) { ensure.notNullOrEmpty(stream, "stream"); ensure.isLongOrInteger(expectedVersion, "expectedVersion"); expectedVersion = Long.fromValue(expectedVersion); userCredentials = userCredentials || null; var self = this; return new Promise(function(resolve, reject) { function cb(err, result) { if (err) return reject(err); resolve(result); } var operation = new StartTransactionOperation(self._settings.log, cb, self._settings.requireMaster, stream, expectedVersion, self, userCredentials); self._enqueueOperation(operation); }); }; /** * Continue a transaction * @public * @param {number} transactionId * @param {UserCredentials} userCredentials * @returns {EventStoreTransaction} */ EventStoreNodeConnection.prototype.continueTransaction = function(transactionId, userCredentials) { ensure.nonNegative(transactionId, "transactionId"); return new EventStoreTransaction(transactionId, userCredentials, this); }; EventStoreNodeConnection.prototype.transactionalWrite = function(transaction, events, userCredentials) { ensure.isTypeOf(EventStoreTransaction, transaction, "transaction"); ensure.isArrayOf(EventData, events, "events"); userCredentials = userCredentials || null; var self = this; return new Promise(function(resolve, reject) { function cb(err) { if (err) return reject(err); resolve(); } var operation = new TransactionalWriteOperation(self._settings.log, cb, self._settings.requireMaster, transaction.transactionId, events, userCredentials); self._enqueueOperation(operation); }); }; /** * Commit a transaction * @public * @param transaction * @param userCredentials * @returns {Promise.<WriteResult>} */ EventStoreNodeConnection.prototype.commitTransaction = function(transaction, userCredentials) { ensure.isTypeOf(EventStoreTransaction, transaction, "transaction"); var self = this; return new Promise(function(resolve, reject) { function cb(err, result) { if (err) return reject(err); resolve(result); } var operation = new CommitTransactionOperation(self._settings.log, cb, self._settings.requireMaster, transaction.transactionId, userCredentials); self._enqueueOperation(operation); }); }; /** * Read a single event (async) * @public * @param {string} stream * @param {Long|number} eventNumber * @param {boolean} [resolveLinkTos] * @param {UserCredentials} [userCredentials] * @returns {Promise.<EventReadResult>} */ EventStoreNodeConnection.prototype.readEvent = function(stream, eventNumber, resolveLinkTos, userCredentials) { ensure.notNullOrEmpty(stream, "stream"); ensure.isLongOrInteger(eventNumber, "eventNumber"); eventNumber = Long.fromValue(eventNumber); resolveLinkTos = Boolean(resolveLinkTos); userCredentials = userCredentials || null; if (typeof stream !== 'string' || stream === '') throw new TypeError("stream must be an non-empty string."); if (eventNumber.compare(-1) < 0) throw new Error("eventNumber out of range."); if (resolveLinkTos && typeof resolveLinkTos !== 'boolean') throw new TypeError("resolveLinkTos must be a boolean."); var self = this; return new Promise(function(resolve, reject){ function cb(err, result) { if (err) return reject(err); resolve(result); } var operation = new ReadEventOperation(self._settings.log, cb, stream, eventNumber, resolveLinkTos, self._settings.requireMaster, userCredentials); self._enqueueOperation(operation); }); }; /** * Reading a specific stream forwards (async) * @public * @param {string} stream * @param {Long|number} start * @param {number} count * @param {boolean} [resolveLinkTos] * @param {UserCredentials} [userCredentials] * @returns {Promise.<StreamEventsSlice>} */ EventStoreNodeConnection.prototype.readStreamEventsForward = function( stream, start, count, resolveLinkTos, userCredentials ) { ensure.notNullOrEmpty(stream, "stream"); ensure.isLongOrInteger(start, "start"); start = Long.fromValue(start); ensure.nonNegative(start, "start"); ensure.isInteger(count, "count"); ensure.positive(count, "count"); if (count > MaxReadSize) throw new Error(util.format("Count should be less than %d. For larger reads you should page.", MaxReadSize)); resolveLinkTos = Boolean(resolveLinkTos); userCredentials = userCredentials || null; var self = this; return new Promise(function(resolve, reject) { function cb(err, result) { if (err) return reject(err); resolve(result); } var operation = new ReadStreamEventsForwardOperation(self._settings.log, cb, stream, start, count, resolveLinkTos, self._settings.requireMaster, userCredentials); self._enqueueOperation(operation); }); }; /** * Reading a specific stream backwards (async) * @public * @param {string} stream * @param {Long|number} start * @param {number} count * @param {boolean} [resolveLinkTos] * @param {UserCredentials} [userCredentials] * @returns {Promise.<StreamEventsSlice>} */ EventStoreNodeConnection.prototype.readStreamEventsBackward = function( stream, start, count, resolveLinkTos, userCredentials ) { ensure.notNullOrEmpty(stream, "stream"); ensure.isLongOrInteger(start, "start"); start = Long.fromValue(start); ensure.isInteger(count, "count"); ensure.positive(count, "count"); if (count > MaxReadSize) throw new Error(util.format("Count should be less than %d. For larger reads you should page.", MaxReadSize)); resolveLinkTos = Boolean(resolveLinkTos); userCredentials = userCredentials || null; var self = this; return new Promise(function(resolve, reject) { function cb(err, result) { if (err) return reject(err); resolve(result); } var operation = new ReadStreamEventsBackwardOperation(self._settings.log, cb, stream, start, count, resolveLinkTos, self._settings.requireMaster, userCredentials); self._enqueueOperation(operation); }); }; /** * Reading all events forwards (async) * @public * @param {Position} position * @param {number} maxCount * @param {boolean} [resolveLinkTos] * @param {UserCredentials} [userCredentials] * @returns {Promise.<AllEventsSlice>} */ EventStoreNodeConnection.prototype.readAllEventsForward = function( position, maxCount, resolveLinkTos, userCredentials ) { ensure.isTypeOf(results.Position, position, "position"); ensure.isInteger(maxCount, "maxCount"); ensure.positive(maxCount, "maxCount"); if (maxCount > MaxReadSize) throw new Error(util.format("Count should be less than %d. For larger reads you should page.", MaxReadSize)); resolveLinkTos = Boolean(resolveLinkTos); userCredentials = userCredentials || null; var self = this; return new Promise(function(resolve, reject) { function cb(err, result) { if (err) return reject(err); resolve(result); } var operation = new ReadAllEventsForwardOperation(self._settings.log, cb, position, maxCount, resolveLinkTos, self._settings.requireMaster, userCredentials); self._enqueueOperation(operation); }); }; /** * Reading all events backwards (async) * @public * @param {Position} position * @param {number} maxCount * @param {boolean} [resolveLinkTos] * @param {UserCredentials} [userCredentials] * @returns {Promise.<AllEventsSlice>} */ EventStoreNodeConnection.prototype.readAllEventsBackward = function( position, maxCount, resolveLinkTos, userCredentials ) { ensure.isTypeOf(results.Position, position, "position"); ensure.isInteger(maxCount, "maxCount"); ensure.positive(maxCount, "maxCount"); if (maxCount > MaxReadSize) throw new Error(util.format("Count should be less than %d. For larger reads you should page.", MaxReadSize)); resolveLinkTos = Boolean(resolveLinkTos); userCredentials = userCredentials || null; var self = this; return new Promise(function(resolve, reject) { function cb(err, result) { if (err) return reject(err); resolve(result); } var operation = new ReadAllEventsBackwardOperation(self._settings.log, cb, position, maxCount, resolveLinkTos || false, self._settings.requireMaster, userCredentials || null); self._enqueueOperation(operation); }); }; /** * Subscribe to a stream (async) * @public * @param {!string} stream * @param {!boolean} resolveLinkTos * @param {function} eventAppeared * @param {function} [subscriptionDropped] * @param {UserCredentials} [userCredentials] * @returns {Promise.<EventStoreSubscription>} */ EventStoreNodeConnection.prototype.subscribeToStream = function( stream, resolveLinkTos, eventAppeared, subscriptionDropped, userCredentials ) { ensure.notNullOrEmpty(stream, "stream"); ensure.isTypeOf(Function, eventAppeared, "eventAppeared"); if (subscriptionDropped) ensure.isTypeOf(Function, subscriptionDropped, "subscriptionDropped"); var self = this; return new Promise(function(resolve,reject) { function cb(err, result) { if (err) return reject(err); resolve(result); } self._handler.enqueueMessage( new messages.StartSubscriptionMessage( cb, stream, !!resolveLinkTos, userCredentials || null, eventAppeared, subscriptionDropped || null, self._settings.maxRetries, self._settings.operationTimeout)); }); }; /** * Subscribe to a stream from position * @public * @param {!string} stream * @param {?number|Position} lastCheckpoint * @param {!boolean} resolveLinkTos * @param {!function} eventAppeared * @param {function} [liveProcessingStarted] * @param {function} [subscriptionDropped] * @param {UserCredentials} [userCredentials] * @param {!number} [readBatchSize] * @returns {EventStoreStreamCatchUpSubscription} */ EventStoreNodeConnection.prototype.subscribeToStreamFrom = function( stream, lastCheckpoint, resolveLinkTos, eventAppeared, liveProcessingStarted, subscriptionDropped, userCredentials, readBatchSize ) { if (typeof stream !== 'string' || stream === '') throw new TypeError("stream must be a non-empty string."); if (lastCheckpoint !== null) { ensure.isLongOrInteger(lastCheckpoint); lastCheckpoint = Long.fromValue(lastCheckpoint); } if (typeof eventAppeared !== 'function') throw new TypeError("eventAppeared must be a function."); var catchUpSubscription = new EventStoreStreamCatchUpSubscription(this, this._settings.log, stream, lastCheckpoint, resolveLinkTos, userCredentials || null, eventAppeared, liveProcessingStarted || null, subscriptionDropped || null, this._settings.verboseLogging, readBatchSize); catchUpSubscription.start(); return catchUpSubscription; }; /** * Subscribe to all (async) * @public * @param {!boolean} resolveLinkTos * @param {!function} eventAppeared * @param {function} [subscriptionDropped] * @param {UserCredentials} [userCredentials] * @returns {Promise.<EventStoreSubscription>} */ EventStoreNodeConnection.prototype.subscribeToAll = function( resolveLinkTos, eventAppeared, subscriptionDropped, userCredentials ) { if (typeof eventAppeared !== 'function') throw new TypeError("eventAppeared must be a function."); var self = this; return new Promise(function(resolve, reject) { function cb(err, result) { if (err) return reject(err); resolve(result); } self._handler.enqueueMessage( new messages.StartSubscriptionMessage( cb, '', resolveLinkTos, userCredentials || null, eventAppeared, subscriptionDropped || null, self._settings.maxRetries, self._settings.operationTimeout)); }); }; /** * Subscribe to all from * @public * @param {?Position} lastCheckpoint * @param {!boolean} resolveLinkTos * @param {!function} eventAppeared * @param {function} [liveProcessingStarted] * @param {function} [subscriptionDropped] * @param {UserCredentials} [userCredentials] * @param {!number} [readBatchSize] * @returns {EventStoreAllCatchUpSubscription} */ EventStoreNodeConnection.prototype.subscribeToAllFrom = function( lastCheckpoint, resolveLinkTos, eventAppeared, liveProcessingStarted, subscriptionDropped, userCredentials, readBatchSize ) { ensure.isTypeOf(results.Position, lastCheckpoint, "lastCheckpoint", true); ensure.isTypeOf(Function, eventAppeared, "eventAppeared", false); if (liveProcessingStarted) ensure.isTypeOf(Function, liveProcessingStarted, "liveProcessingStarted", false); if (subscriptionDropped) ensure.isTypeOf(Function, subscriptionDropped, "subscriptionDropped", false); var catchUpSubscription = new EventStoreAllCatchUpSubscription(this, this._settings.log, lastCheckpoint, resolveLinkTos, userCredentials || null, eventAppeared, liveProcessingStarted || null, subscriptionDropped || null, this._settings.verboseLogging, readBatchSize || 500); catchUpSubscription.start(); return catchUpSubscription; }; /** * Subscribe to a persistent subscription * @public * @param {string} stream * @param {string} groupName * @param {function} eventAppeared * @param {function} [subscriptionDropped] * @param {UserCredentials} [userCredentials] * @param {number} [bufferSize] * @param {boolean} [autoAck] * @return {Promise<EventStorePersistentSubscription>} */ EventStoreNodeConnection.prototype.connectToPersistentSubscription = function( stream, groupName, eventAppeared, subscriptionDropped, userCredentials, bufferSize, autoAck ) { ensure.notNullOrEmpty(groupName, "groupName"); ensure.notNullOrEmpty(stream, "stream"); ensure.notNull(eventAppeared, "eventAppeared"); subscriptionDropped = subscriptionDropped || null; userCredentials = userCredentials || null; bufferSize = bufferSize === undefined ? 10 : bufferSize; autoAck = autoAck === undefined ? true : Boolean(autoAck); var subscription = new EventStorePersistentSubscription( groupName, stream, eventAppeared, subscriptionDropped, userCredentials, this._settings.log, this._settings.verboseLogging, this._settings, this._handler, bufferSize, autoAck); return subscription.start(); }; /** * Create a persistent subscription * @public * @param {string} stream * @param {string} groupName * @param {PersistentSubscriptionSettings} settings * @param {UserCredentials} [userCredentials] * @returns {Promise.<PersistentSubscriptionCreateResult>} */ EventStoreNodeConnection.prototype.createPersistentSubscription = function(stream, groupName, settings, userCredentials) { ensure.notNullOrEmpty(stream, "stream"); ensure.notNullOrEmpty(groupName, "groupName"); ensure.notNull(settings, "settings"); var self = this; return new Promise(function(resolve, reject){ function cb(err, result) { if (err) return reject(err); resolve(result); } self._enqueueOperation( new CreatePersistentSubscriptionOperation(self._settings.log, cb, stream, groupName, settings, userCredentials || null)); }); }; /** * Update a persistent subscription * @public * @param {string} stream * @param {string} groupName * @param {PersistentSubscriptionSettings} settings * @param {UserCredentials} [userCredentials] * @returns {Promise.<PersistentSubscriptionUpdateResult>} */ EventStoreNodeConnection.prototype.updatePersistentSubscription = function(stream, groupName, settings, userCredentials) { ensure.notNullOrEmpty(stream, "stream"); ensure.notNullOrEmpty(groupName, "groupName"); ensure.notNull(settings, "settings"); var self = this; return new Promise(function(resolve, reject) { function cb(err, result) { if (err) return reject(err); resolve(result); } self._enqueueOperation( new UpdatePersistentSubscriptionOperation(self._settings.log, cb, stream, groupName, settings, userCredentials || null)); }); }; /** * Delete a persistent subscription * @public * @param {string} stream * @param {string} groupName * @param {UserCredentials} [userCredentials] * @returns {Promise.<PersistentSubscriptionDeleteResult>} */ EventStoreNodeConnection.prototype.deletePersistentSubscription = function(stream, groupName, userCredentials) { ensure.notNullOrEmpty(stream, "stream"); ensure.notNullOrEmpty(groupName, "groupName"); var self = this; return new Promise(function(resolve, reject) { function cb(err, result) { if (err) return reject(err); resolve(result); } self._enqueueOperation( new DeletePersistentSubscriptionOperation(self._settings.log, cb, stream, groupName, userCredentials || null)); }); }; /** * Set stream metadata * @private */ EventStoreNodeConnection.prototype.setStreamMetadata = function() { //TODO: set stream metadata (non-raw) throw new Error("Not implemented."); }; /** * Set stream metadata with raw object (async) * @public * @param {string} stream * @param {Long|number} expectedMetastreamVersion * @param {object} metadata * @param {UserCredentials} [userCredentials] * @returns {Promise.<WriteResult>} */ EventStoreNodeConnection.prototype.setStreamMetadataRaw = function( stream, expectedMetastreamVersion, metadata, userCredentials ) { ensure.notNullOrEmpty(stream, "stream"); if (systemStreams.isMetastream(stream)) { throw new Error(util.format("Setting metadata for metastream '%s' is not supported.", stream)); } ensure.isLongOrInteger(expectedMetastreamVersion, "expectedMetastreamVersion"); expectedMetastreamVersion = Long.fromValue(expectedMetastreamVersion); var self = this; return new Promise(function(resolve, reject) { function cb(err, result) { if (err) return reject(err); resolve(result); } var data = metadata ? Buffer.from(JSON.stringify(metadata)) : null; var metaevent = new EventData(uuid.v4(), systemEventTypes.StreamMetadata, true, data, null); self._enqueueOperation( new AppendToStreamOperation(self._settings.log, cb, self._settings.requireMaster, systemStreams.metastreamOf(stream), expectedMetastreamVersion, [metaevent], userCredentials)); }); }; /** * Get stream metadata * @private * @param stream * @param userCredentials */ EventStoreNodeConnection.prototype.getStreamMetadata = function(stream, userCredentials) { //TODO: get stream metadata (non-raw) throw new Error("Not implemented."); }; /** * Get stream metadata as raw object (async) * @public * @param {string} stream * @param {UserCredentials} [userCredentials] * @returns {Promise.<RawStreamMetadataResult>} */ EventStoreNodeConnection.prototype.getStreamMetadataRaw = function(stream, userCredentials) { return this.readEvent(systemStreams.metastreamOf(stream), -1, false, userCredentials) .then(function(res) { switch(res.status) { case results.EventReadStatus.Success: if (res.event === null) throw new Error("Event is null while operation result is Success."); var evnt = res.event.originalEvent; var version = evnt ? evnt.eventNumber : -1; var data = evnt ? JSON.parse(evnt.data.toString()) : null; return new results.RawStreamMetadataResult(stream, false, Long.fromValue(version), data); case results.EventReadStatus.NotFound: case results.EventReadStatus.NoStream: return new results.RawStreamMetadataResult(stream, false, Long.fromValue(-1), null); case results.EventReadStatus.StreamDeleted: return new results.RawStreamMetadataResult(stream, true, Long.fromValue(0x7fffffff), null); default: throw new Error(util.format("Unexpected ReadEventResult: %s.", res.status)); } }); }; /** * Set system settings * @private */ EventStoreNodeConnection.prototype.setSystemSettings = function() { //TODO: set system settings throw new Error("Not implemented."); }; EventStoreNodeConnection.prototype._enqueueOperation = function(operation) { var self = this; var message = new messages.StartOperationMessage(operation, self._settings.maxRetries, self._settings.operationTimeout); function tryEnqueue() { if (self._handler.totalOperationCount >= self._settings.maxQueueSize) { setTimeout(tryEnqueue, 0); return; } self._handler.enqueueMessage(message); } setImmediate(tryEnqueue) }; module.exports = EventStoreNodeConnection; /***/ }), /* 12 */ /***/ ((module) => { "use strict"; module.exports = require("util"); /***/ }), /* 13 */ /***/ ((module) => { "use strict"; module.exports = require("uuid"); /***/ }), /* 14 */ /***/ ((module) => { "use strict"; module.exports = require("events"); /***/ }), /* 15 */ /***/ ((module, __unused_webpack_exports, __webpack_require__) => { var util = __webpack_require__(12); function Message() { } Message.prototype.toString = function() { return this.constructor.name; }; function StartConnectionMessage(cb, endpointDiscoverer) { this.cb = cb; this.endpointDiscoverer = endpointDiscoverer; } util.inherits(StartConnectionMessage, Message); function CloseConnectionMessage(reason, error) { this.reason = reason; this.error = error; } util.inherits(CloseConnectionMessage, Message); function StartOperationMessage(operation, maxRetries, timeout) { this.operation = operation; this.maxRetries = maxRetries; this.timeout = timeout; } util.inherits(StartOperationMessage, Message); function StartSubscriptionMessage( cb, streamId, resolveLinkTos, userCredentials, eventAppeared, subscriptionDropped, maxRetries, timeout ) { this.cb = cb; this.streamId = streamId; this.resolveLinkTos = resolveLinkTos; this.userCredentials = userCredentials; this.eventAppeared = eventAppeared; this.subscriptionDropped = subscriptionDropped; this.maxRetries = maxRetries; this.timeout = timeout; } util.inherits(StartSubscriptionMessage, Message); /** * @private * @constructor * @property {object} endPoints * @property {object} endPoints.secureTcpEndPoint * @property {object} endPoints.tcpEndPoint */ function EstablishTcpConnectionMessage(endPoints) { this.endPoints = endPoints; } util.inherits(EstablishTcpConnectionMessage, Message); function HandleTcpPackageMessage(connection, pkg) { this.connection = connection; this.package = pkg; } util