123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- var path = require('path'),
- url = require('url'),
- _ = require('lodash'),
- findit = require('findit2'),
- fs = require('fs');
- function eachConfigFile (root, callback) {
- var files = {};
- var dirs = {};
- var dirNames = {};
- var find = findit(root, {followSymlinks: true});
- var loopingOn = null;
- find.on('file', function (file, stat, linkPath) {
- if (file.match(/\.amd\.json$/)) {
- files[linkPath || file] = stat;
- }
- });
- find.on('error', function (err) {
- if (err.code === 'ELOOP') loopingOn = err.path;
- else {
- console.log(err);
- find.stop();
- }
- });
- find.on('directory', function (dir, stat, stop, linkPath) {
- var name = linkPath || dir;
- if (dir === loopingOn && !isLessDeep(name, dirNames[dir])) {
- stop();
- name = dirNames[dir];
- }
- loopingOn = null;
- dirNames[dir] = name;
- dirs[name] = stat;
- });
- find.on('end', function () {
- callback(null, {files: files, dirs: dirs});
- });
- }
- function transformShimDeps (json) {
- var shimmedList = json.shim && Object.keys(json.shim);
- if (!shimmedList) return;
- for (var i = 0; i < shimmedList.length; i++) {
- var shim = json.shim[shimmedList[i]];
- if (Array.isArray(shim)) {
- json.shim[shimmedList[i]] = {deps: shim};
- }
- }
- }
- function transformPaths (json, root, file, dirs) {
- if (json.paths) {
- var specifier = path.basename(file).replace(/\.amd\.json$/, "");
- var modulePath = specifier === "local" ? path.dirname(file) : dirs[specifier];
- var dir = (path.relative(root, modulePath).split(path.sep).join('/') || ".") + '/';
- transformPathArray(json.paths);
- }
- function transformPathArray (array) {
- var paths = Object.keys(array);
- for (var i = 0; i < paths.length; i++) {
- var key = paths[i];
- var pathValue = array[key];
- switch (typeof pathValue) {
- case "string":
- array[key] = url.resolve(dir, pathValue) || ".";
- if (array[key].slice(-1) === "/") array[key] = array[key].slice(0, -1);
- break;
- case "object":
- Array.isArray(pathValue) && transformPathArray(pathValue);
- break;
- }
- }
- }
- }
- function isLessDeep (a, b) {
- var bDepth = b ? b.split(path.sep).length : Infinity;
- var aDepth = a ? a.split(path.sep).length : Infinity;
- return aDepth < bDepth;
- }
- function constructDirMap (dirs) {
- var result = {};
- for (var i = 0; i < dirs.length; i++) {
- var dir = dirs[i];
- var basename = path.basename(dir);
- if (isLessDeep(dir, result[basename])) {
- result[basename] = dir;
- }
- }
- return result;
- }
- function queoeOfFilesToProcess (files, dirMap) {
- var firstPass = [], secondPass = [];
- for (var i = 0; i < files.length; i++) {
- var file = files[i];
- var basename = path.basename(file);
- var specifier = basename.replace(/\.amd\.json$/, "");
- if (specifier == "" || specifier[0] == ".") {
- continue;
- } else if (specifier == "local") {
- firstPass.push(file);
- } else if (dirMap[specifier]) {
- secondPass.push(file);
- } else {
- throw new Error("No location for " + file);
- }
- }
- return firstPass.concat(secondPass).reverse();
- }
- exports.produceConfigObject = function (root, callback) {
- root = path.resolve(root);
- eachConfigFile(root, function (err, filesAndDirs) {
- if (err) {
- callback(err);
- return;
- }
- var dirMap = constructDirMap(Object.keys(filesAndDirs.dirs));
- var queue;
- try {
- queue = queoeOfFilesToProcess(Object.keys(filesAndDirs.files), dirMap);
- } catch (e) {
- callback(e);
- return;
- }
- if (!queue.length) {
- callback(new Error("No .amd.json-type file found"));
- return;
- }
- var result = {};
- for (var i = 0; i < queue.length; i++) {
- var file = queue[i];
- var json = JSON.parse(JSON.stringify(require(file)));
- transformShimDeps(json);
- transformPaths(json, root, file, dirMap);
- _.mergeWith(result, json, function (a, b) {
- return _.isArray(a) ? b.concat(a) : undefined;
- });
- }
- callback(null, result);
- })
- };
|