dayvan 0.0.0 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []