spade 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -24,7 +24,7 @@ require 'thor'
24
24
  require 'v8'
25
25
 
26
26
  module Spade
27
- SPADE_DIR = '.spade'
27
+ SPADE_DIR = '.spade' # Would be nice to share this with node.js loader
28
28
 
29
29
  # find the current path with a package.json or .packages or cur_path
30
30
  def self.discover_root(cur_path)
@@ -6,7 +6,6 @@
6
6
 
7
7
  module Spade
8
8
  BOOT_PATH = File.expand_path(File.join(File.dirname(__FILE__), '..'));
9
- BUILTIN_PACKAGES = File.join File.dirname(BOOT_PATH), 'packages'
10
9
 
11
10
  module Bundle
12
11
  class << self
@@ -24,48 +23,44 @@ module Spade
24
23
 
25
24
  installed = []
26
25
 
26
+ # Do this to get the Gem.dir right
27
+ env = Spade::Environment.new
27
28
 
28
- #TODO: Clean up duplication here
29
+ # In reverse order of precedence
30
+ package_dirs = [File.join(env.spade_dir, 'gems')]
31
+ package_dirs += %w[vendor/cache vendor/packages packages].map{|p| File.join(rootdir, p.split('/')) }
29
32
 
30
- Dir.glob(File.join(BUILTIN_PACKAGES, '*')).each do |path|
31
- next unless File.exists? File.join(path, 'package.json')
33
+ for package_dir in package_dirs
34
+ Dir.glob(File.join(package_dir, '*')).each do |path|
35
+ json_file = File.join(path, 'package.json')
36
+ next unless File.exists?(json_file)
32
37
 
33
- next if installed.include? path
34
- installed << path
38
+ # How would this happen?
39
+ next if installed.include? path
40
+ installed << path
35
41
 
36
- new_path = File.join(spade_path, 'packages', File.basename(path))
37
- FileUtils.ln_s path, new_path, :force => true
38
- puts "Installing built-in package #{File.basename(path)}" if verbose
39
- end
42
+ json = JSON.load File.read(json_file)
43
+ package_name = json['name']
44
+ package_version = json['version']
40
45
 
41
- # Do this to get the Gem.dir right
42
- env = Spade::Environment.new
43
- Dir.glob(File.join(env.spade_dir, 'gems', '*')).each do |path|
44
- package_def = File.join(path, 'package.json')
45
- next unless File.exists?(package_def)
46
-
47
- next if installed.include? path
48
- installed << path
49
-
50
- json = JSON.load File.read(package_def)
51
- package_name = json['name']
52
- new_path = File.join(spade_path, 'packages', package_name)
53
- FileUtils.ln_s path, new_path, :force => true
54
- puts "Installing system package #{File.basename(path)}" if verbose
55
- end
46
+ local = path.index(rootdir) == 0
56
47
 
48
+ # Use relative paths if embedded
49
+ old_path = if local
50
+ # Figure out how many levels deep the spade_path is in the project
51
+ levels = spade_path.sub(rootdir, '').split(File::SEPARATOR).reject{|p| p.empty? }.count
52
+ # Build relative path
53
+ File.join(['..'] * levels, path.sub(rootdir, ''))
54
+ else
55
+ path
56
+ end
57
57
 
58
- Dir.glob(File.join(rootdir, 'packages', '*')).each do |path|
59
- next unless File.exists? File.join(path, 'package.json')
58
+ new_path = File.join(spade_path, 'packages', package_name)
60
59
 
61
- next if installed.include? path
62
- installed << path
60
+ FileUtils.ln_s old_path, new_path, :force => true
63
61
 
64
- package_name = File.basename(path)
65
- old_path = File.join('..','..','packages', package_name)
66
- new_path = File.join(spade_path, 'packages', File.basename(path))
67
- FileUtils.ln_s old_path, new_path, :force => true
68
- puts "Installing local package #{File.basename(path)}" if verbose
62
+ puts "Installing #{local ? "local" : "remote"} package #{package_name}" if verbose
63
+ end
69
64
  end
70
65
 
71
66
  File.open(File.join(rootdir, 'spade-boot.js'), 'w+') do |fp|
@@ -8,6 +8,7 @@ module Spade
8
8
  module CLI
9
9
  require 'spade/cli/owner'
10
10
  require 'spade/cli/base'
11
+ require 'spade/cli/project_generator'
11
12
 
12
13
  LOGIN_MESSAGE = "Please login first with `spade login`."
13
14
  end
@@ -1,5 +1,8 @@
1
1
  module Spade::CLI
2
2
  class Base < Thor
3
+ include Thor::Actions
4
+
5
+ source_root File.expand_path('../../templates', __FILE__)
3
6
 
4
7
  desc "owner", "Manage users for a package"
5
8
  subcommand "owner", Owner
@@ -228,6 +231,12 @@ module Spade::CLI
228
231
  print_specs(packages, index)
229
232
  end
230
233
 
234
+ desc "new [NAME]", "Generate a new project skeleton"
235
+ def new(name)
236
+ ProjectGenerator.new(self,
237
+ name, File.expand_path(name)).run
238
+ end
239
+
231
240
  desc "build", "Build a spade package from a package.json"
232
241
  def build
233
242
  local = Spade::Local.new
@@ -0,0 +1,58 @@
1
+ module Spade::CLI
2
+ class ProjectGenerator
3
+ include Thor::Actions
4
+
5
+ source_root File.expand_path('../../templates/project', __FILE__)
6
+
7
+ attr_reader :name
8
+
9
+ def initialize(thor, name, root)
10
+ @thor, @name, @root = thor, name, root
11
+
12
+ self.destination_root = root
13
+ end
14
+
15
+ def run
16
+ empty_directory '.'
17
+ FileUtils.cd(destination_root)
18
+
19
+ template "LICENSE"
20
+ template "README.md"
21
+ template "project.json"
22
+
23
+ empty_directory "lib"
24
+ empty_directory "tests"
25
+
26
+ inside "lib" do
27
+ template "main.js"
28
+ end
29
+
30
+ inside "tests" do
31
+ template "main-test.js"
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ def app_const
38
+ name.gsub(/\W|-/, '_').squeeze('_').gsub(/(?:^|_)(.)/) { $1.upcase }
39
+ end
40
+
41
+ def current_year
42
+ Time.now.year
43
+ end
44
+
45
+ def source_paths
46
+ [File.expand_path('../../templates/project', __FILE__)] +
47
+ @thor.source_paths
48
+ end
49
+
50
+ def respond_to?(*args)
51
+ super || @thor.respond_to?(*args)
52
+ end
53
+
54
+ def method_missing(name, *args, &blk)
55
+ @thor.send(name, *args, &blk)
56
+ end
57
+ end
58
+ end
@@ -10,7 +10,7 @@ require 'spade/compiler'
10
10
  require 'spade/console'
11
11
  require 'spade/reactor'
12
12
 
13
- TIKIJS_PATH = File.expand_path File.join(File.dirname(__FILE__), '..', 'spade.js')
13
+ SPADEJS_PATH = File.expand_path File.join(File.dirname(__FILE__), '..', 'spade.js')
14
14
 
15
15
  module Spade
16
16
 
@@ -86,7 +86,7 @@ module Spade
86
86
  ctx['ARGV'] = opts[:argv] || ARGV
87
87
 
88
88
  # Load spade and patch in compiler and loader plugins
89
- ctx.load(TIKIJS_PATH)
89
+ ctx.load(SPADEJS_PATH)
90
90
  ctx['rubyLoader'] = Loader.new(self)
91
91
  ctx['rubyCompiler'] = Compiler.new(self)
92
92
 
@@ -178,11 +178,6 @@ module Spade
178
178
  @packages unless @packages.nil?
179
179
  @packages = {}
180
180
 
181
- # add global packages in spade project
182
- # globals = File.expand_path(File.join(__FILE__, '..', '..', '..', 'packages'))
183
- # package_paths = Dir.glob File.join(globals,'*')
184
- # package_paths.each { |path| add_package(path) }
185
-
186
181
  # Do this to get the Gem.dir right
187
182
  env = Spade::Environment.new
188
183
 
@@ -1,17 +1,10 @@
1
1
  module Spade
2
2
  class Local < Repository
3
3
  def uninstall(package)
4
- index = Gem::SourceIndex.from_gems_in(env.spade_dir("specifications"))
5
- index.refresh!
6
- specs = index.find_name package
7
-
8
- if specs.first
9
- uninstaller = Gem::Uninstaller.new(package, :ignore => true)
10
- uninstaller.uninstall_gem(specs.first, specs)
11
- true
12
- else
13
- false
14
- end
4
+ Gem::Uninstaller.new(package).uninstall
5
+ true
6
+ rescue Gem::InstallError
7
+ false
15
8
  end
16
9
 
17
10
  def pack(path)
@@ -57,6 +57,7 @@ module Spade
57
57
  [500, {}, error]
58
58
  end
59
59
  else
60
+ env['PATH_INFO'] == '/index.html' if env['PATH_INFO'] == '/'
60
61
  @app.call(env)
61
62
  end
62
63
  end
@@ -0,0 +1,19 @@
1
+ Copyright (c) <%= current_year %> YOUR NAME
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
@@ -0,0 +1,21 @@
1
+ # <%= name %>
2
+
3
+ ### Description:
4
+
5
+ FIX (describe your package)
6
+
7
+ ### Features / Problems:
8
+
9
+ * FIX (list of features or problems)
10
+
11
+ ### Synopsis:
12
+
13
+ FIX (code sample of usage)
14
+
15
+ ### Requirements:
16
+
17
+ * FIX (list of requirements)
18
+
19
+ ### Install:
20
+
21
+ * FIX (describe how to install)
@@ -0,0 +1,9 @@
1
+ <%= app_const %> = {
2
+
3
+ // TODO: Write amazing code...
4
+ replaceMe: function() {
5
+ return "OMG you're so awesome!!!";
6
+ }
7
+ }
8
+
9
+ return <%= app_const %>;
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "<%= name %>",
3
+ "description": "DESCRIPTION HERE",
4
+ "summary": "SUMMARY HERE",
5
+ "keywords": ["javascript"],
6
+ "author": "YOUR NAME HERE",
7
+ "homepage": "URL",
8
+ "version": "0.0.1",
9
+ "licenses": [{
10
+ "type": "MIT",
11
+ "url": "http://www.opensource.org/licenses/mit-license.php"
12
+ }],
13
+
14
+ "engines": ["browser", "all"],
15
+
16
+ "directories": {
17
+ "lib": "./lib",
18
+ "test": "./tests"
19
+ },
20
+
21
+ "main": "./lib/main",
22
+
23
+ "bin": {
24
+ "cot": "./bin/cot"
25
+ },
26
+
27
+ "dependencies": {
28
+ "ivory": "= 0.0.1",
29
+ "optparse": "= 1.0.1"
30
+ }
31
+ }
@@ -0,0 +1,8 @@
1
+ Ct.module('<%= app_const %> tests');
2
+
3
+ // TODO: Write real tests
4
+ Ct.test('truth', function(t){
5
+ t.ok(true, 'should be true');
6
+ });
7
+
8
+ Ct.run();
@@ -1,3 +1,3 @@
1
1
  module Spade
2
- VERSION = '0.0.6'
2
+ VERSION = '0.0.7'
3
3
  end
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spade",
3
- "version": "0.0.6",
3
+ "version": "0.0.7",
4
4
  "description": "CommonJS Microkernel for Browser and Command Line",
5
5
 
6
6
  "maintainers": [
@@ -0,0 +1,5 @@
1
+ require "spec_helper"
2
+
3
+ describe "spade new" do
4
+ it "should be speced"
5
+ end
@@ -9,37 +9,37 @@ var Ct = require('core-test/sync'),
9
9
 
10
10
  // ..........................................................
11
11
  // BASIC REQUIRE
12
- //
12
+ //
13
13
 
14
14
  Ct.module('spade: basic require');
15
15
 
16
16
  Ct.setup(function(t) {
17
- t.spade = new Spade();
17
+ t.spade = new Spade();
18
18
  });
19
19
 
20
- Ct.teardown(function(t) {
20
+ Ct.teardown(function(t) {
21
21
  delete t.spade;
22
22
  });
23
23
 
24
24
 
25
25
  Ct.test('register then require a module', function(t) {
26
26
  var spade = t.spade;
27
-
28
- spade.register('foo/bar', function(require, exports) {
27
+
28
+ spade.register('foo/bar', function(require, exports) {
29
29
  exports.foo = 'bar';
30
30
  });
31
-
31
+
32
32
  var exp = spade.require('foo/bar');
33
- t.equal(exp.foo, 'bar', 'exports.foo == bar - means require succeeded');
33
+ t.equal(exp.foo, 'bar', 'exports.foo == bar - means require succeeded');
34
34
  });
35
35
 
36
36
  Ct.test('register a string factory then require', function(t) {
37
37
  var spade = t.spade;
38
-
38
+
39
39
  spade.register('foo/bar', "exports.foo = 'bar';");
40
-
40
+
41
41
  var exp = spade.require('foo/bar');
42
- t.equal(exp.foo, 'bar', 'exports.foo == bar - means require succeeded');
42
+ t.equal(exp.foo, 'bar', 'exports.foo == bar - means require succeeded');
43
43
  });
44
44
 
45
45
  Ct.test('require a non-existant module will throw an exception', function(t) {
@@ -56,3 +56,62 @@ Ct.test('require a module that was just registered symbolically. This is for co
56
56
  });
57
57
 
58
58
  Ct.test('require system installed packages');
59
+
60
+
61
+ // ..........................................................
62
+ // BASIC REQUIRE
63
+ //
64
+
65
+ Ct.module('spade: extension require');
66
+
67
+ Ct.setup(function(t) {
68
+ t.spade = new Spade();
69
+
70
+ t.spade.register('foo', {
71
+ 'plugin:formats': {
72
+ 'css': 'foo/format',
73
+ 'txt': 'foo/format'
74
+ }
75
+ });
76
+ t.spade.register('foo/format', "exports.compileFormat = function(code){ return code; };");
77
+ t.spade.register('foo/bar', "exports.foo = 'bar.js';", { format: 'js' });
78
+ t.spade.register('foo/bar', "exports.foo = 'bar.css';", { format: 'css' });
79
+ });
80
+
81
+ Ct.teardown(function(t) {
82
+ delete t.spade;
83
+ });
84
+
85
+
86
+ Ct.test('valid extension', function(t) {
87
+ var exp = t.spade.require('foo/bar.js');
88
+ t.equal(exp.foo, 'bar.js', 'exports.foo == bar.js - means require succeeded');
89
+ });
90
+
91
+ Ct.test('same name different extensions', function(t){
92
+ var spade = t.spade,
93
+ jsExp = spade.require('foo/bar.js'),
94
+ cssExp = spade.require('foo/bar.css');
95
+
96
+ t.equal(jsExp.foo, 'bar.js', 'exports.foo == bar.js - means require succeeded');
97
+ t.equal(cssExp.foo, 'bar.css', 'exports.foo == bar.css - means require succeeded');
98
+ });
99
+
100
+ Ct.test("don't load file for different extension", function(t){
101
+ t.throws(function(){ t.spade.require('foo/bar.txt'); }, Error, 'adfaff');
102
+ });
103
+
104
+ Ct.test("defaults to js", function(t){
105
+ var exp = t.spade.require('foo/bar');
106
+ t.equal(exp.foo, 'bar.js', 'exports.foo == bar.js - means required js as default');
107
+ });
108
+
109
+ Ct.test("defaults to first registered if no js", function(t){
110
+ var spade = t.spade;
111
+
112
+ spade.register('foo/baz', "exports.foo = 'baz.css';", { format: 'css' });
113
+ spade.register('foo/baz', "exports.foo = 'baz.txt';", { format: 'txt' });
114
+
115
+ var exp = spade.require('foo/baz');
116
+ t.equal(exp.foo, 'baz.css', 'exports.foo == baz.css - means required last registered');
117
+ });