UNPKG

graphquire

Version:

module graph builder and installer.

160 lines (142 loc) 5.02 kB
/* vim:set ts=2 sw=2 sts=2 expandtab */ /*jshint asi: true undef: true es5: true node: true devel: true forin: true latedef: false globalstrict: true */ /*global define: true */ 'use strict'; var fs = require('fs') var url = require('url') var http = require('http') var https = require('https') var path = require('path') var streamer = require('./streamer') function getGraph(options) { var descriptor = getDescriptorStream(options) var modules = getModules(descriptor) } function fileStream(path) { return function stream(next, stop) { fs.readFile(path, function onRead(error, content) { if (error) return stop(error) next(content) stop() }) } } function uriStream(uri) { var options = url.parse(uri) options.path = options.pathname options.followRedirect = true options.maxRedirects = 2 var get = options.protocol === 'http:' ? http.get : https.get return function stream(next, stop) { get(options, function onResponse(response) { response.on('error', stop) response.on('end', stop) response.on('data', function onData(content) { next(content) }) }).on('error', stop) } } function fallback(primary, secondary) { return function stream(next, stop) { primary(next, function onStop(error) { if (error) secondary(next, stop) else stop() }) } } function resourceStream(resource) { var uri = resource.uri var path = resource.path var isLocal = resource.isLocal return isLocal ? fileStream(path) : fallback(fileStream(path), uriStream(uri)) } function descriptor(resource) { return resourceStream(resource) } function requirements(content) { return function stream(next, stop) { content(function onContent(source) { var dependency, dependencies = [] // Removing comments to avoid capturing commented require statements. source = String(source).replace(COMMENT_PATTERN, '') // Push each found dependency into array. while ((dependency = REQUIRE_PATTERN.exec(source))) next(dependency[1]) stop() }, stop) } } function resolve(base) { return function descriptor(id) { return { id: url.resolve(base.id, id), uri: url.resolve(base.uri, id), path: url.resolve(base.path, id) } } } function module(descriptor) { return function stream(next, stop) { var content = resourceStream(descriptor) content(function onContent(source) { if (!descriptor.isLocal) descriptor.source = source var dependency, dependencies = requirements(source) if (dependencies.length) descriptor.requirements = {} while ((dependency = dependencies.shift())) descriptor.requirements[dependency] = resolve(dependency, descriptor.id) }, stop) } } function depends(module) { return function stream(next, stop) { module(function onModule(descriptor) { streamer.values(descriptor.dependencies)(next) }, stop) } } function isPluginID(id) { return id && ~id.indexOf('!') } function isRelativeID(id) { return id && id.charAt(0) === '.' } function isNativeID(id) { return !isRelativeID(id) && isPluginID(id) } function isInManifest(manifest, id) { return id in manifest } function nativeModule(id) { return { id: id } } function modules(manifest, descriptor) { var dependencies = depends(module(descriptor)) var unique = streamer.filter(dependencies, isInManifest.bind(null, manifest)) var absolute = streamer.filter(unique, isPluginID) var relative = streamer.filter(unique, isRelativeID) var native = streamer.filter(unique, isNativeID) var absolute = streamer.merge(absolute, streamer.map(relative, resolve.bind(null, descriptor))) var native = streamer.map(native, nativeModule.bind(manifest)) }), function map(id) { }) module(descriptor)(function onModule(descriptor) { var id, requirements = descriptor.requirements streamer.filter(streamer.values(requirements), function onRequirement() { }) }, function onStop(error) { if (error) stop(error) }) return streamer.join(streamer.merge(dependencies), streamer.list([descriptors])) var requirements = dependencies(base) var dependencies = requirements(base) var descriptors = streamer.map(dependencies, resolve(descriptor)) var moduleStreams = streamer.map(descriptors, modules) var module = streamer.map(streamer.zip(streamer(descriptor), content), function) return streamer.join(streamer.stream(descriptor), streamer.merge(moduleStreams)) re dependencies(function onDependency(id) { descriptor[id] = url.resolve(descriptor.id, id) }, next.bind(null, descriptor)) join(stream(descriptor), streamer.merge(modules)) zip(requirements, content)(next.bind(null, descriptor), end) var requirements = map(dependencies, requirement) next(module) map(requirements, modules)(next, end) } } function getModules(descriptor) { return function stream(next, done) { descriptor(function onDescriptor(next, metadata) { }) } }