@rechat/rets-client
Advanced tools
Comparing version 6.0.2 to 6.1.0
@@ -34,3 +34,3 @@ // Generated by CoffeeScript 2.5.1 | ||
var currEntry, result, retsContext; | ||
retsContext = retsParsing.getStreamParser({ | ||
retsContext = retsParsing.getSaxStreamParser({ | ||
retsMethod: 'getMetadata', | ||
@@ -37,0 +37,0 @@ queryOptions |
@@ -91,3 +91,3 @@ // Generated by CoffeeScript 2.5.1 | ||
queryOptions = queryOptionHelpers.normalizeOptions(mainOptions); | ||
retsContext = retsParsing.getStreamParser({ | ||
retsContext = retsParsing.getSaxStreamParser({ | ||
retsMethod: 'search', | ||
@@ -94,0 +94,0 @@ queryOptions |
@@ -6,6 +6,8 @@ // Generated by CoffeeScript 2.5.1 | ||
'use strict'; | ||
var errors, expat, getSimpleParser, getStreamParser, headersHelper, hex2a, replyCodes, through2; | ||
var _onceWrap, errors, expat, getSaxStreamParser, getSimpleParser, getStreamParser, headersHelper, hex2a, once, onceWrapper, replyCodes, sax, through2; | ||
expat = require('node-expat'); | ||
sax = require('sax'); | ||
through2 = require('through2'); | ||
@@ -69,2 +71,195 @@ | ||
_onceWrap = function(target, type, listener) { | ||
var state, wrapped; | ||
state = { | ||
fired: false, | ||
wrapFn: void 0, | ||
target: target, | ||
type: type, | ||
listener: listener | ||
}; | ||
wrapped = onceWrapper.bind(state); | ||
wrapped.listener = listener; | ||
state.wrapFn = wrapped; | ||
return wrapped; | ||
}; | ||
onceWrapper = function() { | ||
if (!this.fired) { | ||
this.target.removeListener(this.type, this.wrapFn); | ||
this.fired = true; | ||
if (arguments.length === 0) { | ||
return this.listener.call(this.target); | ||
} | ||
return this.listener.apply(this.target, arguments); | ||
} | ||
}; | ||
once = function(target, type, listener) { | ||
return target.on(type, _onceWrap(target, type, listener)); | ||
}; | ||
getSaxStreamParser = function(retsContext, metadataTag, rowData, parserEncoding = 'UTF-8') { | ||
var columnText, columns, currElementName, dataText, delimiter, errorHandler, finish, headers, parser, processStatus, rawData, responseHandler, result, retsStream, writeOutput; | ||
if (metadataTag) { | ||
rawData = false; | ||
result = { | ||
rowsReceived: 0, | ||
entriesReceived: 0 | ||
}; | ||
} else { | ||
result = { | ||
rowsReceived: 0, | ||
maxRowsExceeded: false | ||
}; | ||
} | ||
delimiter = '\t'; | ||
columnText = null; | ||
dataText = null; | ||
columns = null; | ||
currElementName = null; | ||
headers = null; | ||
parser = new sax.createStream(true); | ||
retsStream = through2.obj(); | ||
finish = function(type, payload) { | ||
parser.removeAllListeners(); | ||
// ignore errors after this point | ||
parser.on('error', function()/* noop */ {}); | ||
retsStream.write({ | ||
type: type, | ||
payload: payload | ||
}); | ||
return retsStream.end(); | ||
}; | ||
errorHandler = function(err) { | ||
return finish('error', err); | ||
}; | ||
writeOutput = function(type, payload) { | ||
return retsStream.write({ | ||
type: type, | ||
payload: payload | ||
}); | ||
}; | ||
responseHandler = function() { | ||
return writeOutput('headerInfo', retsContext.headerInfo); | ||
}; | ||
processStatus = function(attrs) { | ||
var status; | ||
if (attrs.ReplyCode !== '0' && attrs.ReplyCode !== '20208') { | ||
return errorHandler(new errors.RetsReplyError(retsContext, attrs.ReplyCode, attrs.ReplyText)); | ||
} | ||
status = { | ||
replyCode: attrs.ReplyCode, | ||
replyTag: replyCodes.tagMap[attrs.ReplyCode], | ||
replyText: attrs.ReplyText | ||
}; | ||
return writeOutput('status', status); | ||
}; | ||
once(parser, 'opentag', function({name, attributes}) { | ||
if (name !== 'RETS') { | ||
return errorHandler(new errors.RetsProcessingError(retsContext, 'Unexpected results. Please check the RETS URL.')); | ||
} | ||
processStatus(attributes); | ||
if (!retsStream.writable) { | ||
return; | ||
} | ||
// assume processStatus found a non-zero/20208 error code and ended the stream So, we don't want to add the startElement listener. | ||
return parser.on('opentag', function({ | ||
name, | ||
attributes: attrs | ||
}) { | ||
currElementName = name; | ||
switch (name) { | ||
case 'DATA': | ||
return dataText = ''; | ||
case 'COLUMNS': | ||
return columnText = ''; | ||
case metadataTag: | ||
writeOutput('metadataStart', attrs); | ||
return result.rowsReceived = 0; | ||
case 'COUNT': | ||
if (!retsStream.writable && parseInt(attrs.Records) === 0) { | ||
return false; | ||
} | ||
return writeOutput('count', parseInt(attrs.Records)); | ||
case 'MAXROWS': | ||
return result.maxRowsExceeded = true; | ||
case 'DELIMITER': | ||
delimiter = hex2a(attrs.value); | ||
return writeOutput('delimiter', delimiter); | ||
case 'RETS-STATUS': | ||
return processStatus(attrs); | ||
} | ||
}); | ||
}); | ||
parser.on('text', function(text) { | ||
switch (currElementName) { | ||
case 'DATA': | ||
return dataText += text; | ||
case 'COLUMNS': | ||
return columnText += text; | ||
} | ||
}); | ||
if (rawData) { | ||
parser.on('closetag', function(name) { | ||
currElementName = null; | ||
switch (name) { | ||
case 'DATA': | ||
writeOutput('data', dataText); | ||
return result.rowsReceived++; | ||
case 'COLUMNS': | ||
return writeOutput('columns', columnText); | ||
case 'RETS': | ||
return finish('done', result); | ||
} | ||
}); | ||
} else { | ||
parser.on('closetag', function(name) { | ||
var data, i, model; | ||
currElementName = null; | ||
switch (name) { | ||
case 'DATA': | ||
if (!columns) { | ||
return errorHandler(new errors.RetsProcessingError(retsContext, 'Failed to parse columns')); | ||
} | ||
data = dataText.split(delimiter); | ||
model = {}; | ||
i = 1; | ||
while (i < columns.length - 1) { | ||
model[columns[i]] = data[i]; | ||
i++; | ||
} | ||
writeOutput('data', model); | ||
return result.rowsReceived++; | ||
case 'COLUMNS': | ||
if (!delimiter) { | ||
return errorHandler(new errors.RetsProcessingError(retsContext, 'Failed to parse delimiter')); | ||
} | ||
columns = columnText.split(delimiter); | ||
return writeOutput('columns', columns); | ||
case metadataTag: | ||
result.entriesReceived++; | ||
return writeOutput('metadataEnd', result.rowsReceived); | ||
case 'RETS': | ||
if (metadataTag) { | ||
delete result.rowsReceived; | ||
} | ||
return finish('done', result); | ||
} | ||
}); | ||
} | ||
parser.on('error', function(err) { | ||
return errorHandler(new errors.RetsProcessingError(retsContext, `XML parsing error: ${errors.getErrorMessage(err)}`)); | ||
}); | ||
parser.on('end', function() { | ||
// we remove event listeners upon success, so getting here implies failure | ||
return errorHandler(new errors.RetsProcessingError(retsContext, "Unexpected end of xml stream.")); | ||
}); | ||
retsContext.parser = parser; | ||
retsContext.errorHandler = errorHandler; | ||
retsContext.responseHandler = responseHandler; | ||
retsContext.retsStream = retsStream; | ||
return retsContext; | ||
}; | ||
// parser that deals with column/data tags, as returned for metadata and search queries | ||
@@ -233,5 +428,6 @@ getStreamParser = function(retsContext, metadataTag, rawData, parserEncoding = 'UTF-8') { | ||
getSimpleParser: getSimpleParser, | ||
getStreamParser: getStreamParser | ||
getStreamParser: getStreamParser, | ||
getSaxStreamParser: getSaxStreamParser | ||
}; | ||
}).call(this); |
{ | ||
"name": "@rechat/rets-client", | ||
"version": "6.0.2", | ||
"version": "6.1.0", | ||
"description": "A RETS client (Real Estate Transaction Standard).", | ||
@@ -17,2 +17,3 @@ "main": "index.js", | ||
"request-promise-native": "^1.0.9", | ||
"sax": "^1.2.4", | ||
"stream-buffers": "^3.0.2", | ||
@@ -19,0 +20,0 @@ "through2": "^4.0.2" |
116740
2671
12
27
+ Addedsax@^1.2.4
+ Addedsax@1.4.1(transitive)