Skip to content

Commit 3f94dc5

Browse files
committed
feat: migrate to gulp-exist as backend
1 parent 26c077a commit 3f94dc5

File tree

2 files changed

+197
-104
lines changed

2 files changed

+197
-104
lines changed

index.js

Lines changed: 196 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ var async = require("async");
99
var assign = require("lodash.assign");
1010
var File = require('vinyl');
1111
var Path = require("path");
12+
var exist = require("node-exist");
1213

1314
var defaultRPCoptions = {
1415
host: 'localhost',
@@ -47,15 +48,15 @@ var normalizePath = function (path) {
4748
return Path.normalize(isWin ? path.replace(/\\/g, "/") : path);
4849
};
4950

50-
function createCollection(client, collection, callback) {
51+
function createCollection(client, collection) {
5152
var normalizedCollectionPath = normalizePath(collection);
5253
gutil.log('Creating collection "' + normalizedCollectionPath + '"...');
53-
client.methodCall('createCollection', [normalizedCollectionPath], callback);
54+
return client.collections.create(normalizedCollectionPath);
5455
}
5556

5657
module.exports.createClient = function createClient(options) {
5758
// TODO sanity checks
58-
var client = xmlrpc.createClient(assign({}, defaultRPCoptions, options))
59+
var client = exist.connect(assign({}, defaultRPCoptions, options))
5960
return {
6061
dest: sendFilesWith(client),
6162
query: queryWith(client),
@@ -97,77 +98,133 @@ function sendFilesWith(client) {
9798

9899
var remotePath = normalizePath(conf.target + "/" + file.relative);
99100

100-
var uploadAndParse = function (file, remotePath, mimeType, callback) {
101+
var uploadAndParse = function (file, remotePath, mimeType) {
102+
103+
gutil.log('Storing "' + file.base + file.relative + '" as (' + mimeType + ')...');
104+
return client.documents.upload(file.contents)
105+
.then(function (result) {
106+
return client.documents.parseLocal(result, remotePath, true, mimeType)
107+
})
108+
.then(function(result) {
109+
gutil.log(' ✔ ︎' + remotePath + ' stored');
110+
return result
111+
}, function(e) {
112+
if (isSaxParserError(e) && conf.html5AsBinary && file.extname === '.html') {
113+
gutil.log(file.relative + " is not well-formed XML, storing as binary...");
114+
return uploadAndParse(file, remotePath, "application/octet-stream")
115+
} else {
116+
gutil.log(' ✖ ' + remotePath + ' was not stored');
117+
throw e;
118+
}
119+
})
120+
// .catch(function (e) {
121+
// console.log(e)
122+
// })
123+
// .done(function () {
124+
// gutil.log(' ✔ ︎' + remotePath + ' stored');
125+
// })
101126
// handle re-upload as octet stream if parsing failed and html5AsBinary is set
102-
function retryOnFail(error, result) {
103-
if (isSaxParserError(error) && conf.html5AsBinary && file.extname === '.html' ) {
104-
gutil.log(file.relative + " is not well-formed XML, storing as binary...");
105-
return uploadAndParse(file, remotePath, "application/octet-stream", callback);
106-
}
107-
if (isSaxParserError(error)) {
108-
gutil.log(' ✖ ' + remotePath + ' was not stored');
109-
return callback(error, null);
110-
}
111-
gutil.log(' ✔ ︎' + remotePath + ' stored');
112-
callback(error, result);
113-
}
114-
async.waterfall([
115-
// First upload file
116-
function (cb) {
117-
gutil.log('Storing "' + file.base + file.relative + '" as (' + mimeType + ')...');
118-
client.methodCall('upload', [file.contents, file.contents.length], cb);
119-
},
120-
121-
// Then parse file on server and store to specified destination path
122-
function (fileHandle, cb) {
123-
client.methodCall('parseLocal', [fileHandle, remotePath, true, mimeType], cb);
124-
}
125-
], retryOnFail);
127+
// function retryOnFail(error, result) {
128+
// if (isSaxParserError(error) && conf.html5AsBinary && file.extname === '.html' ) {
129+
// gutil.log(file.relative + " is not well-formed XML, storing as binary...");
130+
// return uploadAndParse(file, remotePath, "application/octet-stream", callback);
131+
// }
132+
// if (isSaxParserError(error)) {
133+
// gutil.log(' ✖ ' + remotePath + ' was not stored');
134+
// return callback(error, null);
135+
// }
136+
// gutil.log(' ✔ ︎' + remotePath + ' stored');
137+
// callback(error, result);
138+
// }
139+
// async.waterfall([
140+
// // First upload file
141+
// function (cb) {
142+
// gutil.log('Storing "' + file.base + file.relative + '" as (' + mimeType + ')...');
143+
// client.methodCall('upload', [file.contents, file.contents.length], cb);
144+
// },
145+
146+
// // Then parse file on server and store to specified destination path
147+
// function (fileHandle, cb) {
148+
// client.methodCall('parseLocal', [fileHandle, remotePath, true, mimeType], cb);
149+
// }
150+
// ], retryOnFail);
126151
};
127152

128-
async.waterfall([
129-
// check if the target collection / folder exists and create it if necessary
130-
function (callback) {
131-
var folder = file.relative.substring(0, file.relative.length - file.basename.length)
132-
client.methodCall('describeCollection', [Path.normalize(conf.target) + "/" + folder], function (error) {
133-
if (!error) { return callback(null, true) }
134-
createCollection(client, Path.normalize(conf.target) + "/" + folder, callback);
135-
});
136-
},
137-
138-
// Then upload and parse file
139-
function (result, callback) {
140-
var mimeType = mime.lookup(file.path);
141-
uploadAndParse(file, remotePath, mimeType, callback);
142-
},
143-
144-
// Then override permissions if specified in options
145-
function (result, callback) {
146-
if (!result || conf.permissions === null || !(file.relative in conf.permissions)) {
147-
return callback(null);
148-
}
149-
150-
gutil.log('Setting permissions for "' + normalizePath(file.relative) + '" (' + conf.permissions[file.relative] + ')...');
151-
client.methodCall('setPermissions', [remotePath, conf.permissions[file.relative]], callback);
152-
}
153-
],
154-
// Handle errors and proceed to next file
155-
function (error) {
156-
if (isSaxParserError(error)) {
157-
// Delete file on server on parse error. This is necessary because eXist modifies the
158-
// mtimes of existing files on a failed upload/parse-attempt which breaks
159-
// date comparisons in the newer-stream
160-
gutil.log("Removing " + remotePath + " due to parse error...");
161-
return client.methodCall('remove', [remotePath], function () {
162-
callback(error)
163-
});
164-
}
165-
if (error) {
166-
gutil.log("Error: " + error);
167-
return callback(error);
153+
var folder = file.relative.substring(0, file.relative.length - file.basename.length)
154+
var collection = Path.normalize(conf.target) + "/" + folder
155+
client.collections.describe(collection)
156+
.then(null, function(e) {
157+
return createCollection(client, collection)
158+
})
159+
.then(function(result) {
160+
gutil.log('Storing "' + file.base + file.relative + '" as (' + mime.lookup(file.path) + ')...');
161+
return client.documents.upload(file.contents)
162+
})
163+
.then(function (result) {
164+
return client.documents.parseLocal(result, remotePath, {mimetype: mime.lookup(file.path)})
165+
})
166+
.then(null, function(e) {
167+
if (isSaxParserError(e) && conf.html5AsBinary && file.extname === '.html') {
168+
gutil.log(file.relative + " is not well-formed XML, storing as binary...");
169+
return client.documents.upload(file.contents)
170+
.then(function(result) {
171+
return client.documents.parseLocal(result, remotePath, {mimetype: "application/octet-stream"})
172+
})
173+
} else {
174+
gutil.log(' ✖ ' + remotePath + ' was not stored');
175+
throw e;
168176
}
169-
callback();
170-
});
177+
})
178+
.then(function(result) {
179+
return callback(null, file)
180+
}, function(e) {
181+
return callback(e)
182+
})
183+
184+
185+
// async.waterfall([
186+
// // check if the target collection / folder exists and create it if necessary
187+
// function (callback) {
188+
// var folder = file.relative.substring(0, file.relative.length - file.basename.length)
189+
// client.methodCall('describeCollection', [Path.normalize(conf.target) + "/" + folder], function (error) {
190+
// if (!error) { return callback(null, true) }
191+
// createCollection(client, Path.normalize(conf.target) + "/" + folder, callback);
192+
// });
193+
// },
194+
195+
// // Then upload and parse file
196+
// function (result, callback) {
197+
// var mimeType = mime.lookup(file.path);
198+
// uploadAndParse(file, remotePath, mimeType, callback);
199+
// },
200+
201+
// // Then override permissions if specified in options
202+
// function (result, callback) {
203+
// if (!result || conf.permissions === null || !(file.relative in conf.permissions)) {
204+
// return callback(null);
205+
// }
206+
207+
// gutil.log('Setting permissions for "' + normalizePath(file.relative) + '" (' + conf.permissions[file.relative] + ')...');
208+
// client.methodCall('setPermissions', [remotePath, conf.permissions[file.relative]], callback);
209+
// }
210+
// ],
211+
// // Handle errors and proceed to next file
212+
// function (error) {
213+
// if (isSaxParserError(error)) {
214+
// // Delete file on server on parse error. This is necessary because eXist modifies the
215+
// // mtimes of existing files on a failed upload/parse-attempt which breaks
216+
// // date comparisons in the newer-stream
217+
// gutil.log("Removing " + remotePath + " due to parse error...");
218+
// return client.methodCall('remove', [remotePath], function () {
219+
// callback(error)
220+
// });
221+
// }
222+
// if (error) {
223+
// gutil.log("Error: " + error);
224+
// return callback(error);
225+
// }
226+
// callback();
227+
// });
171228
};
172229

173230
return through.obj(storeFile);
@@ -190,38 +247,57 @@ function queryWith(client) {
190247

191248
gutil.log('Running XQuery on server: ' + file.relative);
192249

193-
async.waterfall([
194-
function (callback) {
195-
client.methodCall('executeQuery', [file.contents, {}], callback);
196-
},
197-
function (resultHandle, callback) {
198-
client.methodCall('getHits', [resultHandle], function (error, hitCount) {
199-
callback(error, resultHandle, hitCount);
200-
});
201-
},
202-
function (resultHandle, hitCount, callback) {
203-
async.times(hitCount, function (n, next) {
204-
client.methodCall('retrieve', [resultHandle, n, {}], next);
205-
}, callback);
206-
}
207-
],
208-
function (error, results) {
209-
if (error) {
210-
var errorObject = new PluginError("gulp-exist", "Error running XQuery " + file.relative + ":\n" + error);
211-
return callback(errorObject);
212-
}
213-
214-
var result = Buffer.concat(results);
250+
client.queries.readAll(file.contents, {})
251+
.then(function (result) {
215252

253+
var resultBuffer = Buffer.concat(result.pages)
216254
if (conf.printXqlResults) {
217-
gutil.log(result.toString());
255+
gutil.log(resultBuffer.toString())
218256
}
219257

220-
file.path = gutil.replaceExtension(file.path, "." + new Date().toJSON() + "." + conf.xqlOutputExt);
221-
file.contents = result;
222258

223-
callback(null, file);
259+
file.path = gutil.replaceExtension(file.path, "." + new Date().toJSON() + "." + conf.xqlOutputExt)
260+
file.contents = resultBuffer
261+
262+
return callback(null, file)
263+
264+
})
265+
.catch(function (e) {
266+
return callback(new PluginError("gulp-exist", "Error running XQuery " + file.relative + ":\n" + error))
224267
});
268+
269+
// async.waterfall([
270+
// function (callback) {
271+
// client.methodCall('executeQuery', [file.contents, {}], callback);
272+
// },
273+
// function (resultHandle, callback) {
274+
// client.methodCall('getHits', [resultHandle], function (error, hitCount) {
275+
// callback(error, resultHandle, hitCount);
276+
// });
277+
// },
278+
// function (resultHandle, hitCount, callback) {
279+
// async.times(hitCount, function (n, next) {
280+
// client.methodCall('retrieve', [resultHandle, n, {}], next);
281+
// }, callback);
282+
// }
283+
// ],
284+
// function (error, results) {
285+
// if (error) {
286+
// var errorObject = new PluginError("gulp-exist", "Error running XQuery " + file.relative + ":\n" + error);
287+
// return callback(errorObject);
288+
// }
289+
290+
// var result = Buffer.concat(results);
291+
292+
// if (conf.printXqlResults) {
293+
// gutil.log(result.toString());
294+
// }
295+
296+
// file.path = gutil.replaceExtension(file.path, "." + new Date().toJSON() + "." + conf.xqlOutputExt);
297+
// file.contents = result;
298+
299+
// callback(null, file);
300+
// });
225301
}
226302

227303
return through.obj(executeQuery);
@@ -235,17 +311,33 @@ function checkForNewerWith(client) {
235311
function checkFile(file, enc, callback) {
236312
if (file.isDirectory()) {
237313
var collection = normalizePath(conf.target + "/" + file.relative);
238-
client.methodCall('describeCollection', [collection], function (error, result) {
239-
// Include directory if it does not exist as a collection on a server
240-
callback(null, result ? null : file);
241-
});
314+
client.collections.describe(collection)
315+
.then(function() {
316+
callback(null, file)
317+
}, function() {
318+
callback(null)
319+
})
320+
242321
return;
322+
// client.methodCall('describeCollection', [collection], function (error, result) {
323+
// // Include directory if it does not exist as a collection on a server
324+
// callback(null, result ? null : file);
325+
// });
326+
// return;
243327
}
244328

245-
client.methodCall('describeResource', [normalizePath(conf.target + "/" + file.relative)], function (error, resourceInfo) {
246-
var newer = !resourceInfo.hasOwnProperty("modified") || (Date.parse(file.stat.mtime) > Date.parse(resourceInfo.modified));
247-
callback(error, newer ? file : null);
248-
});
329+
client.resources.describe(normalizePath(conf.target + "/" + file.relative))
330+
.then(function (resourceInfo) {
331+
var newer = !resourceInfo.hasOwnProperty("modified") || (Date.parse(file.stat.mtime) > Date.parse(resourceInfo.modified));
332+
callback(null, newer ? file : null)
333+
})
334+
.catch(function (e) {
335+
callback(e)
336+
})
337+
// client.methodCall('describeResource', [normalizePath(conf.target + "/" + file.relative)], function (error, resourceInfo) {
338+
// var newer = !resourceInfo.hasOwnProperty("modified") || (Date.parse(file.stat.mtime) > Date.parse(resourceInfo.modified));
339+
// callback(error, newer ? file : null);
340+
// });
249341
}
250342

251343
return through.obj(checkFile);

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
"gulp-util": "^3.0.6",
3737
"lodash.assign": "^4.0.2",
3838
"mime": "^1.3.4",
39+
"node-exist": "^0.1.0",
3940
"through2": "^2.0.0",
4041
"vinyl": "^1.1.1",
4142
"xmlrpc": "^1.3.1"

0 commit comments

Comments
 (0)