-
Notifications
You must be signed in to change notification settings - Fork 307
Remove dependency on async library #555
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
Changes from all commits
82af9ec
de7b93a
67a6b48
ace60c7
d54f958
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,7 +3,6 @@ module.exports = allow | |
| var ACL = require('../acl-checker') | ||
| var $rdf = require('rdflib') | ||
| var url = require('url') | ||
| var async = require('async') | ||
| var utils = require('../utils') | ||
|
|
||
| function allow (mode) { | ||
|
|
@@ -59,31 +58,30 @@ function allow (mode) { | |
| */ | ||
| function fetchDocument (host, ldp, baseUri) { | ||
| return function fetch (uri, callback) { | ||
| var graph = $rdf.graph() | ||
| async.waterfall([ | ||
| function readFile (cb) { | ||
| // If local request, slice off the initial baseUri | ||
| // S(uri).chompLeft(baseUri).s | ||
| var newPath = uri.startsWith(baseUri) | ||
| ? uri.slice(baseUri.length) | ||
| : uri | ||
| // Determine the root file system folder to look in | ||
| // TODO prettify this | ||
| var root = !ldp.idp ? ldp.root : ldp.root + host + '/' | ||
| // Derive the file path for the resource | ||
| var documentPath = utils.uriToFilename(newPath, root) | ||
| var documentUri = url.parse(documentPath) | ||
| documentPath = documentUri.pathname | ||
| return ldp.readFile(documentPath, cb) | ||
| }, | ||
| function parseFile (body, cb) { | ||
| try { | ||
| $rdf.parse(body, graph, uri, 'text/turtle') | ||
| } catch (err) { | ||
| return cb(err, graph) | ||
| } | ||
| return cb(null, graph) | ||
| } | ||
| ], callback) | ||
| readFile(uri, host, ldp, baseUri).then(body => { | ||
| const graph = $rdf.graph() | ||
| $rdf.parse(body, graph, uri, 'text/turtle') | ||
| return graph | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Mostly unrelated to this PR, but these 3 lines come up again and again when working with |
||
| }) | ||
| .then(graph => callback(null, graph), callback) | ||
| } | ||
| } | ||
|
|
||
| // Reads the given file, returning its contents | ||
| function readFile (uri, host, ldp, baseUri) { | ||
| return new Promise((resolve, reject) => { | ||
| // If local request, slice off the initial baseUri | ||
| // S(uri).chompLeft(baseUri).s | ||
| var newPath = uri.startsWith(baseUri) | ||
| ? uri.slice(baseUri.length) | ||
| : uri | ||
| // Determine the root file system folder to look in | ||
| // TODO prettify this | ||
| var root = !ldp.idp ? ldp.root : ldp.root + host + '/' | ||
| // Derive the file path for the resource | ||
| var documentPath = utils.uriToFilename(newPath, root) | ||
| var documentUri = url.parse(documentPath) | ||
| documentPath = documentUri.pathname | ||
| ldp.readFile(documentPath, (e, c) => e ? reject(e) : resolve(c)) | ||
| }) | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,7 +5,6 @@ var glob = require('glob') | |
| var _path = require('path') | ||
| var $rdf = require('rdflib') | ||
| var S = require('string') | ||
| var async = require('async') | ||
| var Negotiator = require('negotiator') | ||
| const url = require('url') | ||
| const mime = require('mime-types') | ||
|
|
@@ -161,35 +160,28 @@ function globHandler (req, res, next) { | |
| let reqOrigin = utils.getBaseUri(req) | ||
|
|
||
| debugGlob('found matches ' + matches) | ||
| async.each(matches, function (match, done) { | ||
| Promise.all(matches.map(match => new Promise((resolve, reject) => { | ||
| var baseUri = utils.filenameToBaseUri(match, reqOrigin, root) | ||
| fs.readFile(match, {encoding: 'utf8'}, function (err, fileData) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Again probably not in scope for the PR, but I'm confused as to why we need a
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, unsure. I just ported it. |
||
| if (err) { | ||
| debugGlob('error ' + err) | ||
| return done(null) | ||
| return resolve() | ||
| } | ||
| aclAllow(match, req, res, function (allowed) { | ||
| if (!S(match).endsWith('.ttl') || !allowed) { | ||
| return done(null) | ||
| return resolve() | ||
| } | ||
| try { | ||
| $rdf.parse( | ||
| fileData, | ||
| globGraph, | ||
| baseUri, | ||
| 'text/turtle') | ||
| $rdf.parse(fileData, globGraph, baseUri, 'text/turtle') | ||
| } catch (parseErr) { | ||
| debugGlob('error in parsing the files' + parseErr) | ||
| debugGlob(`error parsing ${match}: ${parseErr}`) | ||
| } | ||
| return done(null) | ||
| return resolve() | ||
| }) | ||
| }) | ||
| }, function () { | ||
| var data = $rdf.serialize( | ||
| undefined, | ||
| globGraph, | ||
| requestUri, | ||
| 'text/turtle') | ||
| }))) | ||
| .then(() => { | ||
| var data = $rdf.serialize(undefined, globGraph, requestUri, 'text/turtle') | ||
| // TODO this should be added as a middleware in the routes | ||
| res.setHeader('Content-Type', 'text/turtle') | ||
| debugGlob('returning turtle') | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,7 +3,6 @@ var path = require('path') | |
| const url = require('url') | ||
| var fs = require('fs') | ||
| var $rdf = require('rdflib') | ||
| var async = require('async') | ||
| // var url = require('url') | ||
| var mkdirp = require('fs-extra').mkdirp | ||
| var uuid = require('uuid') | ||
|
|
@@ -13,7 +12,6 @@ var error = require('./http-error') | |
| var stringToStream = require('./utils').stringToStream | ||
| var serialize = require('./utils').serialize | ||
| var extend = require('extend') | ||
| var doWhilst = require('async').doWhilst | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| var rimraf = require('rimraf') | ||
| var ldpContainer = require('./ldp-container') | ||
| var parse = require('./utils').parse | ||
|
|
@@ -156,42 +154,40 @@ class LDP { | |
| return callback(error(500, "Can't parse container")) | ||
| } | ||
|
|
||
| async.waterfall( | ||
| [ | ||
| // add container stats | ||
| function (next) { | ||
| ldpContainer.addContainerStats(ldp, reqUri, filename, resourceGraph, next) | ||
| }, | ||
| // reading directory | ||
| function (next) { | ||
| ldpContainer.readdir(filename, next) | ||
| }, | ||
| // Iterate through all the files | ||
| function (files, next) { | ||
| async.each( | ||
| files, | ||
| function (file, cb) { | ||
| let fileUri = url.resolve(reqUri, encodeURIComponent(file)) | ||
| ldpContainer.addFile(ldp, resourceGraph, reqUri, fileUri, uri, | ||
| filename, file, cb) | ||
| }, | ||
| next) | ||
| } | ||
| ], | ||
| function (err, data) { | ||
| // add container stats | ||
| new Promise((resolve, reject) => | ||
| ldpContainer.addContainerStats(ldp, reqUri, filename, resourceGraph, | ||
| err => err ? reject(err) : resolve()) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just a nitpick comment (don't need to address) but the indentation here through me off as to which expression the anonymous function was being passed off to.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can address this, as there are some other points as well. What indentation would you use here?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's definitely a matter of taste but this is how I generally like things: when breaking function arguments up into several lines, I like to keep the closing paren For example: ldpContainer.addContainerStats(
ldp, reqUri, filename, resourceGraph,
err => err ? reject(err) : resolve()
)I also see this a lot when using callback functions - breaking the line after the arguments to the callback: ldpContainer.addContainerStats(ldp, reqUri, filename, resourceGraph, err =>
err ? reject(err) : resolve()
)
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should really consider using a linter that goes beyond This particular instance can perhaps be solved with
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, fair point. A code formatter would be nice. I thought I saw you discussing prettier at some point in gitter. I'd be in favor of adding that, for no other reason than not having to think about style ever again :)
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Won't have been me 😄 I'm in favor of a strict .eslintrc (and really dislike
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm leaving this as-is, since other parts in the same file follow the same indentation.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's fine. Consistency is more important :) |
||
| ) | ||
| // read directory | ||
| .then(() => new Promise((resolve, reject) => | ||
| ldpContainer.readdir(filename, | ||
| (err, files) => err ? reject(err) : resolve(files)) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It seems like a node convention for pre-Promise API async functions to take callbacks which themselves take a possible error as the first argument and a successful value as the next argument. We could write a higher-order function to make these kinds of functions return promises: const promisify = (fn) =>
(...args) =>
new Promise((resolve, reject) =>
fn(...args, (err, success) =>
err
? reject(err)
: resolve(success)
)
)
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We could do that—and there are a couple of libraries that expose such a function (starting with Node 8 even in core). I've used that in other projects. I was hesitant to do this here and in other places of the Solid code, because callbacks are sometimes used inconsistently (they don't always have an error argument). So I could start using it here, but then it would perhaps be good to keep an eye on it in other places of the code as well. And eventually, we should migrate to an So, what do you think, should we start the promisify practice here?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good points!
Oof yeah that complicates things!
Sure thing. Though async/await is syntactic sugar on top of Promises, so I think that "promisifying" our interfaces goes hand-in-hand with async/await-ifying them :) I like your point that this change is more of an interface redesign than simply "promisifying" the existing APIs. How about we simply leave things as they are here, and I'll create a ticket for making the async APIs more consistent.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 I'll make the other changes and merge.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (created issue #557) |
||
| )) | ||
| // iterate through all the files | ||
| .then(files => { | ||
| return Promise.all(files.map(file => | ||
| new Promise((resolve, reject) => { | ||
| const fileUri = url.resolve(reqUri, encodeURIComponent(file)) | ||
| ldpContainer.addFile(ldp, resourceGraph, reqUri, fileUri, uri, | ||
| filename, file, err => err ? reject(err) : resolve()) | ||
| }) | ||
| )) | ||
| }) | ||
| .catch(() => { throw error(500, "Can't list container") }) | ||
| .then(() => new Promise((resolve, reject) => { | ||
| // TODO 'text/turtle' is fixed, should be contentType instead | ||
| // This forces one more translation turtle -> desired | ||
| serialize(resourceGraph, reqUri, 'text/turtle', function (err, result) { | ||
| if (err) { | ||
| return callback(error(500, "Can't list container")) | ||
| debug.handlers('GET -- Error serializing container: ' + err) | ||
| reject(error(500, "Can't serialize container")) | ||
| } else { | ||
| resolve(result) | ||
| } | ||
| // TODO 'text/turtle' is fixed, should be contentType instead | ||
| // This forces one more translation turtle -> desired | ||
| serialize(resourceGraph, reqUri, 'text/turtle', function (err, result) { | ||
| if (err) { | ||
| debug.handlers('GET -- Error serializing container: ' + err) | ||
| return callback(error(500, "Can't serialize container")) | ||
| } | ||
| return callback(null, result) | ||
| }) | ||
| }) | ||
| })) | ||
| .then(result => callback(null, result), callback) | ||
| } | ||
|
|
||
| post (hostname, containerPath, slug, stream, container, callback) { | ||
|
|
@@ -351,18 +347,10 @@ class LDP { | |
| var root = ldp.idp ? ldp.root + host + '/' : ldp.root | ||
| var filename = utils.uriToFilename(reqPath, root) | ||
|
|
||
| async.waterfall([ | ||
| // Read file | ||
| function (cb) { | ||
| return ldp.readFile(filename, cb) | ||
| }, | ||
| // Parse file | ||
| function (body, cb) { | ||
| parse(body, baseUri, contentType, function (err, graph) { | ||
| cb(err, graph) | ||
| }) | ||
| } | ||
| ], callback) | ||
| ldp.readFile(filename, (err, body) => { | ||
| if (err) return callback(err) | ||
| parse(body, baseUri, contentType, callback) | ||
| }) | ||
| } | ||
|
|
||
| get (options, callback) { | ||
|
|
@@ -395,7 +383,7 @@ class LDP { | |
| if (err) { | ||
| metaFile = '' | ||
| } | ||
| let absContainerUri = url.resolve(baseUri, reqPath) | ||
| let absContainerUri = baseUri + reqPath | ||
| ldp.listContainer(filename, absContainerUri, baseUri, metaFile, contentType, | ||
| function (err, data) { | ||
| if (err) { | ||
|
|
@@ -498,34 +486,25 @@ class LDP { | |
|
|
||
| getAvailablePath (host, containerURI, slug, callback) { | ||
| var self = this | ||
| var exists | ||
|
|
||
| if (!slug) { | ||
| slug = uuid.v1() | ||
| } | ||
| slug = slug || uuid.v1() | ||
|
|
||
| var newPath = path.join(containerURI, slug) | ||
|
|
||
| // TODO: maybe a nicer code | ||
| doWhilst( | ||
| function (next) { | ||
| function ensureNotExists (newPath) { | ||
| return new Promise(resolve => { | ||
| self.exists(host, newPath, function (err) { | ||
| exists = !err | ||
|
|
||
| if (exists) { | ||
| var id = uuid.v1().split('-')[ 0 ] + '-' | ||
| // If an error occurred, the resource does not exist yet | ||
| if (err) { | ||
| resolve(newPath) | ||
| // Otherwise, generate a new path | ||
| } else { | ||
| const id = uuid.v1().split('-')[ 0 ] + '-' | ||
| newPath = path.join(containerURI, id + slug) | ||
| resolve(ensureNotExists(newPath)) | ||
| } | ||
|
|
||
| next() | ||
| }) | ||
| }, | ||
| function () { | ||
| return exists === true | ||
| }, | ||
| function () { | ||
| callback(newPath) | ||
| }) | ||
| } | ||
|
|
||
| return ensureNotExists(path.join(containerURI, slug)).then(callback) | ||
| } | ||
| } | ||
| module.exports = LDP | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👏