dayvan 0.0.0 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -1,8 +1,8 @@
1
- = ⚙ Dayvan
1
+ = ⚙ dayvan
2
2
 
3
3
 
4
4
 
5
- == Copyright
5
+ == copyright
6
6
 
7
7
  Copyright (c) 2010 Chris Lloyd.
8
8
 
data/Rakefile CHANGED
@@ -7,7 +7,7 @@ begin
7
7
  gem.email = 'christopher.lloyd@gmail.com'
8
8
  gem.homepage = 'http://github.com/chrislloyd/dayvan'
9
9
  gem.author = 'Chris Lloyd'
10
- gem.executable = 'dayvan'
10
+ gem.executable = 'dvn'
11
11
 
12
12
  gem.add_dependency 'thor', '>= 0.12.3'
13
13
  gem.add_dependency 'rest-client', '>= 1.2.0'
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.0
1
+ 0.1.0
data/bin/{dayvan → dvn} RENAMED
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'dayvan/cli'
3
+ require 'dayvan'
4
4
  Dayvan::Cli.start
@@ -0,0 +1,54 @@
1
+ require 'base64'
2
+ require 'digest/md5'
3
+ require 'mime/types'
4
+
5
+ class Dayvan::Attachment
6
+
7
+ def self.all(root)
8
+ Dir[root.join('**/**')].
9
+ reject {|f| File.directory?(f)}. # Allows symlinks
10
+ inject({}) {|all, f|
11
+ attachment = new(f)
12
+ all[attachment.path.relative_path_from(root)] = attachment
13
+ all
14
+ }
15
+ end
16
+
17
+ def self.signatures
18
+ all.inject({}) do |signatures, (path, attachment)|
19
+ signatures[path] = attachment.signature
20
+ signatures
21
+ end
22
+ end
23
+
24
+ attr_reader :path
25
+
26
+ def initialize(path)
27
+ self.path = path
28
+ end
29
+
30
+ def content_type
31
+ (MIME::Types.of(path.to_s).first || 'text/plain').to_s
32
+ end
33
+
34
+ def data
35
+ Base64.encode64(path.read).delete("\s\n")
36
+ end
37
+
38
+ def name
39
+ path.basename('*.*')
40
+ end
41
+
42
+ def path=(path)
43
+ @path = Pathname(path)
44
+ end
45
+
46
+ def signature
47
+ Digest::MD5.hexdigest(data)
48
+ end
49
+
50
+ def to_json
51
+ {:content_type => content_type, :data => data}.to_json
52
+ end
53
+
54
+ end
data/lib/dayvan/cli.rb ADDED
@@ -0,0 +1,57 @@
1
+ require 'pathname'
2
+ require 'thor'
3
+ require 'json'
4
+
5
+ class Dayvan::Cli < Thor
6
+ include Thor::Actions
7
+
8
+ source_paths << Pathname(__FILE__).dirname.join('..','..','templates').expand_path.to_s
9
+
10
+ desc 'init', 'Create a CouchApp template'
11
+ def init
12
+ destination_root = Pathname.pwd
13
+ source_path = Pathname(__FILE__).dirname.expand_path
14
+ name = destination_root.basename.to_s
15
+
16
+
17
+ empty_directory 'config'
18
+
19
+ create_file "config/#{name}.yaml" do
20
+ {'designs' => [name.to_s],
21
+ 'database' => {
22
+ 'url' => "http://localhost:5984/#{name}"
23
+ }
24
+ }.to_yaml.split("\n")[1..-1].join("\n") + "\n"
25
+ end
26
+
27
+ copy_file 'security.coffee.erb', 'config/security.coffee'
28
+
29
+ empty_directory 'views'
30
+ copy_file 'all.coffee.erb', 'views/all.coffee'
31
+ copy_file 'size.coffee.erb', 'views/size.coffee'
32
+
33
+ empty_directory 'public'
34
+ @name = name
35
+ @version = Dayvan.version
36
+ template 'welcome.html.erb', 'public/index.html'
37
+
38
+ puts "Initialized CouchApp in #{destination_root}"
39
+ end
40
+
41
+ desc 'push', 'Push your app to CouchDB'
42
+ def push
43
+ Dayvan.project.create_database!
44
+ Dayvan.project.push!
45
+ rescue Errno::ECONNREFUSED, RestClient::Unauthorized
46
+ abort "fatal: Couldn't connect to CouchDB at #{Dayvan.project.db.url}"
47
+ rescue Dayvan::ConfigError
48
+ abort "fatal: Not a Dayvan app"
49
+ end
50
+
51
+ private
52
+
53
+ def project
54
+ Dayvan.project
55
+ end
56
+
57
+ end
@@ -0,0 +1,77 @@
1
+ class Dayvan::Design
2
+
3
+ attr_accessor :name, :config
4
+ attr_writer :rev
5
+
6
+ def self.new_from_config(name, config={})
7
+ returning(new) do |d|
8
+ if name.is_a?(Hash)
9
+ d.name = name.delete('name')
10
+ d.config = name
11
+ else
12
+ d.name = name
13
+ d.config = config
14
+ end
15
+ end
16
+ end
17
+
18
+ def doc
19
+ Dayvan.project.db[id]
20
+ end
21
+
22
+ def id
23
+ "_design/#{name}"
24
+ end
25
+
26
+ def rev
27
+ @rev ||= JSON.parse(doc.get)['_rev']
28
+ rescue RestClient::ResourceNotFound
29
+ end
30
+
31
+ def attachments
32
+ Dayvan::Attachment.all(attachment_path)
33
+ end
34
+
35
+ def attachment_path
36
+ config['attachments'] ||
37
+ config['attachment'] ||
38
+ Dayvan.project.dir.join('public')
39
+ end
40
+
41
+ def views
42
+ Dayvan::View.all(view_path)
43
+ end
44
+
45
+ def view_path
46
+ config['views'] ||
47
+ config['view'] ||
48
+ Dayvan.project.dir.join('views')
49
+ end
50
+
51
+ def validate_doc_update
52
+ Dayvan::Security.new(validate_doc_update_path)
53
+ end
54
+
55
+ def validate_doc_update_path
56
+ config['security'] ||
57
+ Dayvan.project.dir.join('config','security.coffee')
58
+ end
59
+
60
+
61
+ def to_hash
62
+ hsh = { '_attachments' => attachments,
63
+ 'views' => views,
64
+ 'validate_doc_update' => validate_doc_update
65
+ }
66
+ rev ? hsh.merge('_rev' => rev) : hsh
67
+ end
68
+
69
+ def to_json
70
+ to_hash.to_json
71
+ end
72
+
73
+ def push
74
+ doc.put to_json
75
+ end
76
+
77
+ end
@@ -0,0 +1,55 @@
1
+ require 'pathname'
2
+ require 'yaml'
3
+ require 'restclient'
4
+ require 'json'
5
+
6
+ class Dayvan::ConfigError < StandardError; end
7
+
8
+ class Dayvan::Project
9
+
10
+ def dir
11
+ Pathname.pwd
12
+ end
13
+
14
+ def designs
15
+ config['designs'].
16
+ map {|design| Dayvan::Design.new_from_config(design)}
17
+ end
18
+
19
+ def config
20
+ @config ||= YAML.load(config_path.read)
21
+ end
22
+
23
+ def db
24
+ url, dbname = config['database']['url'], config['database']['name']
25
+ user, password = config['database']['user'], config['database']['password']
26
+ @db ||= RestClient::Resource.new(url,
27
+ :user => user,
28
+ :password => password
29
+ )[dbname]
30
+ end
31
+
32
+ def config_path
33
+ dirname = dir.expand_path.basename
34
+ ["#{dirname}.yaml", "#{dirname}.yml", 'divan.yaml', 'divan.yml'].
35
+ inject([]) {|dirs, f|
36
+ dirs << dir.join('config',f)
37
+ dirs << dir.join(f)
38
+ dirs
39
+ }.
40
+ find {|dir| dir.file? && dir.readable?} ||
41
+ raise(Dayvan::ConfigError)
42
+ end
43
+
44
+ def create_database!
45
+ db.put nil
46
+ rescue RestClient::RequestFailed
47
+ end
48
+
49
+ def push!
50
+ designs.each do |d|
51
+ d.push
52
+ end
53
+ end
54
+
55
+ end
@@ -0,0 +1,30 @@
1
+ require 'coffee-script'
2
+
3
+ class Dayvan::Security
4
+
5
+ def self.all
6
+ new(Dayvan.project.security_path)
7
+ end
8
+
9
+ attr_accessor :path
10
+
11
+ def initialize(path)
12
+ self.path = path
13
+ end
14
+
15
+ def src
16
+ path.read
17
+ end
18
+
19
+ def compile
20
+ CoffeeScript::Parser.new.parse(src).
21
+ children.
22
+ find {|node| node.is_a?(CoffeeScript::CodeNode)}.
23
+ compile(:indent => '')
24
+ end
25
+
26
+ def to_json
27
+ compile.to_json
28
+ end
29
+
30
+ end
@@ -0,0 +1,49 @@
1
+ require 'coffee-script'
2
+
3
+ class Dayvan::View
4
+ attr_accessor :path
5
+
6
+ def self.all(root)
7
+ Dir[root.join('**/*.coffee')].
8
+ reject {|f| File.directory?(f)}. # Allows symlinks
9
+ inject({}) {|all, f|
10
+ view = new(f)
11
+ all[view.name] = view
12
+ all
13
+ }
14
+ end
15
+
16
+
17
+ def initialize(path)
18
+ self.path = path
19
+ end
20
+
21
+ def name
22
+ File.basename(path, '.*')
23
+ end
24
+
25
+ def src
26
+ File.read(path)
27
+ end
28
+
29
+ def compile
30
+ parse_tree = CoffeeScript::Parser.new.parse(src)
31
+
32
+ ['map', 'reduce'].inject({}) do |memo, type|
33
+ # Finds tops level assignemnts whose bound variable is map/reduce.
34
+ assignment_node = parse_tree.children.find {|node|
35
+ node.is_a?(CoffeeScript::AssignNode) && node.variable.base == type
36
+ }
37
+
38
+ if assignment_node
39
+ memo[type] = assignment_node.value.compile(:indent => '')
40
+ end
41
+ memo
42
+ end
43
+ end
44
+
45
+ def to_json
46
+ compile.to_json
47
+ end
48
+
49
+ end
data/lib/dayvan.rb ADDED
@@ -0,0 +1,19 @@
1
+ require 'pathname'
2
+
3
+ def returning(val)
4
+ yield val
5
+ val
6
+ end unless respond_to?(:returning)
7
+
8
+ module Dayvan
9
+ def self.version
10
+ Pathname(__FILE__).dirname.join('..','VERSION').read.strip.freeze
11
+ end
12
+
13
+ def self.project
14
+ @project ||= Dayvan::Project.new
15
+ end
16
+ end
17
+
18
+ %w(attachment view security design project cli).
19
+ each {|lib| require "dayvan/#{lib}"}
@@ -0,0 +1,2 @@
1
+ map: (doc) ->
2
+ emit(doc.id, doc)
@@ -0,0 +1,2 @@
1
+ (new_doc, saved_doc, user_ctx) ->
2
+ # validate_doc_update
@@ -0,0 +1,5 @@
1
+ map: (doc) ->
2
+ emit(null, true)
3
+
4
+ reduce: (key, values, rereduce) ->
5
+ return values.length
@@ -0,0 +1,27 @@
1
+ <!DOCTYPE html>
2
+ <meta charset=utf-8>
3
+ <title>Welcome to Dayvan</title>
4
+ <style type=text/css>
5
+ body { font-family: Junction, Helvetica; margin: 40px auto; width: 360px; line-height: 20px; font-size: 14px; color: #666; }
6
+ #video { border-radius: 10px; -webkit-border-radius: 10px; -moz-border-radius: 10px; overflow: hidden; line-height: 0; display: block; margin: 0 -20px; }
7
+ #video, object, embed { background-color: #336; }
8
+ hgroup { display: block; clear: both; overflow: auto; margin-top: 10px; }
9
+ hgroup h1 { font-size: 18px; font-weight: normal; color: #336; float: left; }
10
+ hgroup h2 { float: right; color: #999; font-size: 14px; margin-top: 13px; font-weight: normal; }
11
+ code { font-family: Inconsolata, monospace; font-size: 16px; color: #333; }
12
+ .footer { font-size: 12px; margin-top: 20px; }
13
+ a { color: #69C; text-decoration: none; }
14
+ a:hover { color: #06C; }
15
+ </style>
16
+
17
+ <div id=video>
18
+ <object width="400" height="300"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=5125966&amp;server=vimeo.com&amp;show_title=0&amp;show_byline=0&amp;show_portrait=0&amp;color=ffffff&amp;fullscreen=1" /><embed src="http://vimeo.com/moogaloop.swf?clip_id=5125966&amp;server=vimeo.com&amp;show_title=0&amp;show_byline=0&amp;show_portrait=0&amp;color=ffffff&amp;fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="300"></embed></object>
19
+ </div>
20
+
21
+ <hgroup>
22
+ <h1>Thank you for using <b>Dayvan</b></h1>
23
+ <h2>v<%= @version %></h2>
24
+ </hgroup>
25
+ <p>Push new versions of your app again with <code>dvn push</code>.</p>
26
+ <p>Add attachments to <code>public</code> directory and views to the <code>views</code> directory. These settings can be changed in the <code>config/<%= @name %>.yaml</code> file.</p>
27
+ <p class=footer><a href=http://chrislloyd.github.com/dayvan>Reference</a> &middot; <a href=http://github.com/chrislloyd/dayvan>Code</a> &middot; <a href=http://thelincolnshirepoacher.com>The Poacher</a></p>
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dayvan
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Lloyd
@@ -9,8 +9,8 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-02-01 00:00:00 +11:00
13
- default_executable: dayvan
12
+ date: 2010-02-03 00:00:00 +11:00
13
+ default_executable: dvn
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: thor
@@ -65,7 +65,7 @@ dependencies:
65
65
  description: Dayvan is a framework for writing CouchApps.
66
66
  email: christopher.lloyd@gmail.com
67
67
  executables:
68
- - dayvan
68
+ - dvn
69
69
  extensions: []
70
70
 
71
71
  extra_rdoc_files:
@@ -75,6 +75,18 @@ files:
75
75
  - README.rdoc
76
76
  - Rakefile
77
77
  - VERSION
78
+ - bin/dvn
79
+ - lib/dayvan.rb
80
+ - lib/dayvan/attachment.rb
81
+ - lib/dayvan/cli.rb
82
+ - lib/dayvan/design.rb
83
+ - lib/dayvan/project.rb
84
+ - lib/dayvan/security.rb
85
+ - lib/dayvan/view.rb
86
+ - templates/all.coffee.erb
87
+ - templates/security.coffee.erb
88
+ - templates/size.coffee.erb
89
+ - templates/welcome.html.erb
78
90
  has_rdoc: true
79
91
  homepage: http://github.com/chrislloyd/dayvan
80
92
  licenses: []