Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Implementing simple dependency linker.

  • Loading branch information...
commit 3fd35fb781ec90bf1514de50f2d98dad0b5b92eb 1 parent 3f6fa8a
@Gozala authored
View
1  .gitignore
@@ -0,0 +1 @@
+/node_modules
View
13 bin/graphquire.coffee
@@ -1,13 +0,0 @@
-#!/usr/bin/env coffee
-### vim:set ts=2 sw=2 sts=2 et autoread: ###
-
-graphquire = require '../graphquire'
-fs = require 'fs'
-path = require 'path'
-
-program = path.join process.cwd(), process.argv[2]
-
-console.log "Creating require graph for -> #{program}"
-
-fs.readFile program, (error, source) ->
- console.log(graphquire.depends(source))
View
26 bin/graphquire.js 100644 → 100755
@@ -1,11 +1,15 @@
-(function() {
- /* vim:set ts=2 sw=2 sts=2 et autoread: */ var fs, graphquire, path, program;
- graphquire = require('../graphquire');
- fs = require('fs');
- path = require('path');
- program = path.join(process.cwd(), process.argv[2]);
- console.log("Creating require graph for -> " + program);
- fs.readFile(program, function(error, source) {
- return console.log(graphquire.depends(source));
- });
-}).call(this);
+#!/usr/bin/env node
+
+/* 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 graphquire = require('../graphquire')
+
+graphquire.getGraph(process.argv[2], function(error, graph) {
+ if (error) console.error(error)
+ else console.log(JSON.stringify(graph, '', ' '))
+})
View
46 graphquire.coffee
@@ -1,46 +0,0 @@
-### vim:set ts=2 sw=2 sts=2 et autoread: ###
-
-define ?= ($)-> $(require, exports, module)
-
-define (require, exports, module)->
- 'use strict'
-
- COMMENT_PATTERN = ///
- ( # matching multi-line comment blocks.
- /\* # opening of the multi-line comment block: "/*".
- [\s\S]*? # matching anything but in a non-greedy way to make
- # sure that we don't also match things between
- # first and last multi-line comment blocks.
- \*/ # closing of the multi-line comment block: "*/".
- ) | ( # and single line comments.
- # Match from the beginning of line or an input
- (^|\n)
- # Match any symbols except quotes and line breaks, as quoted '//' is not
- # comment and if we have a line break we need to start over.
- # Please note that comments like following will not be stripped out:
- # var foo = "bar"; // something here
- # Still we ignore as it's pretty unlikely to have module imports in such
- # comments.
- [^('|"|\n)]*
- # Match a single line comment string '//'
- //
- # Till a nearest line break
- [^\n]*
- )
- ///g
-
- REQUIRE_PATTERN = ///
- require # require function call.
- \s*\(['"] # Any number of white-spaces followed by `("` or `('`
- ([\w\W]*?) # Any combination alphanumeric chars -> module id
- ['"]\s*\) # Any number of white-spaces followed by `')` or `")`
- ///g
-
- exports.depends = (source)->
- dependencies = []
- source = String(source).replace COMMENT_PATTERN, ''
- while dependency = REQUIRE_PATTERN.exec source
- dependencies.push dependency[1]
- dependencies
-
- exports
View
130 graphquire.js
@@ -1,20 +1,112 @@
-(function() {
- /* vim:set ts=2 sw=2 sts=2 et autoread: */ typeof define != "undefined" && define !== null ? define : define = function($) {
- return $(require, exports, module);
- };
- define(function(require, exports, module) {
- 'use strict'; var COMMENT_PATTERN, REQUIRE_PATTERN;
- COMMENT_PATTERN = /(\/\*[\s\S]*?\*\/)|((^|\n)[^('|"|\n)]*\/\/[^\n]*)/g;
- REQUIRE_PATTERN = /require\s*\(['"]([\w\W]*?)['"]\s*\)/g;
- exports.depends = function(source) {
- var dependencies, dependency;
- dependencies = [];
- source = String(source).replace(COMMENT_PATTERN, '');
- while (dependency = REQUIRE_PATTERN.exec(source)) {
- dependencies.push(dependency[1]);
+/* 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 path = require('path')
+var fs = require('fs')
+
+var COMMENT_PATTERN = /(\/\*[\s\S]*?\*\/)|((^|\n)[^('|"|\n)]*\/\/[^\n]*)/g
+var REQUIRE_PATTERN = /require\s*\(['"]([\w\W]*?)['"]\s*\)/g
+
+function extractDependencies(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)))
+ dependencies.push(dependency[1])
+
+ return dependencies
+}
+
+function isPluginURI(uri) { return ~uri.indexOf('!') }
+function isRelativeURI(id) { return id.charAt(0) === '.' }
+function normalizeURI(uri) { return path.extname(uri) ? uri : uri + '.js' }
+function extractURI(uri) {
+ var index = uri.indexOf('!')
+ return ~index ? uri.substr(++index) : uri
+}
+function extractPluginName(id) {
+ var index = id.indexOf('!')
+ return index > 0 ? id.substr(0, index) : ''
+}
+function resolve(id, base) {
+ return isRelativeURI(id) ? path.join(path.dirname(base), id) : id
+}
+function resolveID(id, base) {
+ if (isPluginURI(id))
+ id = extractPluginName(id) + '!' + resolve(extractURI(id), base)
+ else
+ id = resolve(id, base)
+ return id
+}
+function resolveURI(uri, base) {
+ return normalizeURI(resolveID(uri, base))
+}
+
+
+function resolveRequirements(module, callback, program) {
+ program = program || module
+ fs.readFile(module.uri, function(error, source) {
+ if (error) return callback(error)
+
+ // Searching for dependencies.
+ var dependencies = extractDependencies(source)
+
+ // Dependency resolution tracker that will call a callback once all the
+ // dependencies are resolved.
+ function next(error) {
+ if (error) return callback(error)
+ if (Object.keys(module.requirements).length === dependencies.length)
+ callback(null, program)
+ }
+
+ next()
+
+ dependencies.forEach(function onDependency(dependencyID) {
+ var id = resolveID(dependencyID, module.id)
+ var dependency = {
+ id: id,
+ uri: isPluginURI(id) ? normalizeURI(path.join(program.cacheURI, id))
+ : resolveURI(id, module.uri),
+ requirements: {}
}
- return dependencies;
- };
- return exports;
- });
-}).call(this);
+ module.requirements[dependencyID] = dependency.id
+ program.dependencies[dependency.id] = dependency
+ resolveRequirements(dependency, next, program)
+ })
+ })
+}
+exports.resolveRequirements = resolveRequirements
+
+function getMetadata(uri, callback) {
+ fs.readFile(uri, function onRead(error, data) {
+ if (error) return callback(error)
+ try {
+ callback(null, JSON.parse(data))
+ } catch (exception) {
+ callback(exception)
+ }
+ })
+}
+exports.getMetadata = getMetadata
+
+function getGraph(uri, callback) {
+ getMetadata(uri, function onMetadata(error, metadata) {
+ if (error) return callback(error)
+
+ resolveRequirements({
+ name: metadata.name,
+ version: metadata.version,
+ description: metadata.description,
+ uri: normalizeURI(metadata.main || "./index.js", uri),
+ cacheURI: path.join(path.dirname(uri), 'node_modules'),
+ requirements: {},
+ dependencies: {}
+ }, callback)
+ })
+}
+exports.getGraph = getGraph
View
16 package.json
@@ -1,7 +1,9 @@
-{ "name": "graphquire",
+{
+ "name": "graphquire",
+ "id": "graphquire",
"version": "0.0.1",
"description": "Require graph builder.",
- "keywords": [],
+ "keywords": [ "dependencies", "graph", "modules", "require" ],
"author": "Irakli Gozalishvili <rfobic@gmail.com>",
"repository": {
"type": "git",
@@ -24,12 +26,12 @@
"node": "0.4.x",
"teleport": ">=0.2.0"
},
- "bin": { "graphquire" : "./bin/graphquire.coffee" },
+ "bin": { "graphquire" : "./bin/graphquire.js" },
"scripts": {
"test": "node test/test-graphquire.js"
},
- "licenses": [ { "type" : "MPL 1.1/LGPL 2.1/GPL 2.0"
- , "url" : "http://www.mozilla.org/MPL/"
- }
- ]
+ "licenses": [{
+ "type": "MIT",
+ "url": "http://jeditoolkit.com/LICENSE"
+ }]
}
View
2  test/fixtures/pckg1/index.js
@@ -0,0 +1,2 @@
+exports.name = "main";
+exports.dependency = require("http!foo.org/a");
View
1  test/fixtures/pckg1/node_modules/http!bar.org/c.js
@@ -0,0 +1 @@
+exports.name = "c";
View
2  test/fixtures/pckg1/node_modules/http!foo.org/a.js
@@ -0,0 +1,2 @@
+exports.b = require("./nested/b");
+exports.name = "a";
View
2  test/fixtures/pckg1/node_modules/http!foo.org/nested/b.js
@@ -0,0 +1,2 @@
+exports.c = require("http!bar.org/c");
+exports.name = "b";
View
1  test/fixtures/pckg1/package.json
@@ -0,0 +1 @@
+{ "name": "pckg1" }
Please sign in to comment.
Something went wrong with that request. Please try again.