hmx_client 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/hmx +15 -23
- data/lib/hmx/client.rb +106 -17
- data/lib/hmx/command/base.rb +194 -0
- data/lib/hmx/command/bootstrap.rb +18 -0
- data/lib/hmx/command/clone.rb +77 -0
- data/lib/hmx/command/config.rb +67 -0
- data/lib/hmx/command/dump.rb +67 -0
- data/lib/hmx/command/fn.rb +43 -0
- data/lib/hmx/command/fountain.rb +46 -0
- data/lib/hmx/command/get.rb +20 -0
- data/lib/hmx/command/getContent.rb +20 -0
- data/lib/hmx/command/help.rb +114 -0
- data/lib/hmx/command/query.rb +22 -0
- data/lib/hmx/command/session.rb +35 -0
- data/lib/hmx/command/task.rb +32 -0
- data/lib/hmx/command/type.rb +45 -0
- data/lib/hmx/command/user.rb +68 -0
- data/lib/hmx/command/view.rb +155 -0
- data/lib/hmx/command.rb +140 -0
- data/lib/hmx/helpers.rb +61 -0
- data/lib/hmx/hmx.rb +125 -16
- data/lib/hmx/version.rb +1 -1
- data/lib/hmx_client.rb +1 -1
- metadata +24 -6
@@ -0,0 +1,46 @@
|
|
1
|
+
require "hmx/command/base"
|
2
|
+
require 'date'
|
3
|
+
|
4
|
+
module HmxClient::Command
|
5
|
+
|
6
|
+
# Manipulate hmx fountains (auto id generators)
|
7
|
+
#
|
8
|
+
class Fountain < Base
|
9
|
+
|
10
|
+
# fountain
|
11
|
+
#
|
12
|
+
# Lists all of the fountains and their values
|
13
|
+
def index
|
14
|
+
fountainState = hmx.getFountainState([])
|
15
|
+
# fountainState is a map of fountainName => value
|
16
|
+
# Flip this into an array of "name" => name, "value" => value
|
17
|
+
objs = []
|
18
|
+
fountainState.each_pair do | key, value |
|
19
|
+
objs << { "name" => key, "value" => value }
|
20
|
+
end
|
21
|
+
cols = [ 'name', 'value' ]
|
22
|
+
headers = [ 'Fountain', 'Value' ]
|
23
|
+
display_table(objs, cols, headers)
|
24
|
+
end
|
25
|
+
|
26
|
+
# fountain:set
|
27
|
+
#
|
28
|
+
# Sets the new id for the fountain
|
29
|
+
#
|
30
|
+
def set
|
31
|
+
unless args.size > 1
|
32
|
+
raise CommandFailed, "Usage: hmx fountain:set <fountainId> <newValue>"
|
33
|
+
end
|
34
|
+
hmx.setFountainId(args)
|
35
|
+
end
|
36
|
+
# fountain:get
|
37
|
+
#
|
38
|
+
# Increments and returns a fountain value
|
39
|
+
def get
|
40
|
+
unless args.size > 0
|
41
|
+
raise CommandFailed, "Usage: hmx fountain:get <fountainId>"
|
42
|
+
end
|
43
|
+
display hmx.getFountain(args)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require "hmx/command/base"
|
2
|
+
|
3
|
+
module HmxClient::Command
|
4
|
+
|
5
|
+
# Get full document from hmx
|
6
|
+
#
|
7
|
+
class Get < Base
|
8
|
+
|
9
|
+
# get
|
10
|
+
#
|
11
|
+
# get a document from hmx, given its display name
|
12
|
+
#
|
13
|
+
def index
|
14
|
+
unless args.size > 0
|
15
|
+
raise CommandFailed, "Usage: hmx get displayname"
|
16
|
+
end
|
17
|
+
dout JSON.pretty_generate(hmx.getData(args))
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require "hmx/command/base"
|
2
|
+
|
3
|
+
module HmxClient::Command
|
4
|
+
|
5
|
+
# Get document content from hmx
|
6
|
+
#
|
7
|
+
class GetContent < Base
|
8
|
+
|
9
|
+
# getContent
|
10
|
+
#
|
11
|
+
# get the data part of a document from hmx, given its display name
|
12
|
+
#
|
13
|
+
def index
|
14
|
+
unless args.size > 0
|
15
|
+
raise CommandFailed, "Usage: hmx getContent displayname"
|
16
|
+
end
|
17
|
+
dout hmx.getContent(args)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
require "hmx/command/base"
|
2
|
+
|
3
|
+
# list commands and display help
|
4
|
+
#
|
5
|
+
class HmxClient::Command::Help < HmxClient::Command::Base
|
6
|
+
|
7
|
+
PRIMARY_NAMESPACES = %w( config query get view)
|
8
|
+
|
9
|
+
# help [COMMAND]
|
10
|
+
#
|
11
|
+
# list available commands or display help for a specific command
|
12
|
+
#
|
13
|
+
def index
|
14
|
+
if command = args.shift
|
15
|
+
help_for_command(command)
|
16
|
+
else
|
17
|
+
help_for_root
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
alias_command "-h", "help"
|
22
|
+
alias_command "--help", "help"
|
23
|
+
|
24
|
+
def self.usage_for_command(command)
|
25
|
+
command = new.send(:commands)[command]
|
26
|
+
"Usage: hmx #{command[:banner]}" if command
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def commands_for_namespace(name)
|
32
|
+
HmxClient::Command.commands.values.select do |command|
|
33
|
+
command[:namespace] == name && command[:command] != name
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def namespaces
|
38
|
+
namespaces = HmxClient::Command.namespaces
|
39
|
+
namespaces
|
40
|
+
end
|
41
|
+
|
42
|
+
def commands
|
43
|
+
commands = HmxClient::Command.commands
|
44
|
+
HmxClient::Command.command_aliases.each do |new, old|
|
45
|
+
commands[new] = commands[old].dup
|
46
|
+
commands[new][:banner] = "#{new} #{commands[new][:banner].split(" ", 2)[1]}"
|
47
|
+
commands[new][:command] = new
|
48
|
+
commands[new][:namespace] = nil
|
49
|
+
end
|
50
|
+
commands
|
51
|
+
end
|
52
|
+
|
53
|
+
def primary_namespaces
|
54
|
+
PRIMARY_NAMESPACES.map { |name| namespaces[name] }.compact
|
55
|
+
end
|
56
|
+
|
57
|
+
def additional_namespaces
|
58
|
+
(namespaces.values - primary_namespaces).sort_by { |n| n[:name] }
|
59
|
+
end
|
60
|
+
|
61
|
+
def summary_for_namespaces(namespaces)
|
62
|
+
size = longest(namespaces.map { |n| n[:name] })
|
63
|
+
namespaces.each do |namespace|
|
64
|
+
name = namespace[:name]
|
65
|
+
namespace[:description] ||= legacy_help_for_namespace(name)
|
66
|
+
puts " %-#{size}s # %s" % [ name, namespace[:description] ]
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def help_for_root
|
71
|
+
puts "Usage: hmx COMMAND [command-specific-options]"
|
72
|
+
puts
|
73
|
+
puts "Primary help topics, type \"hmx help TOPIC\" for more details:"
|
74
|
+
puts
|
75
|
+
summary_for_namespaces(primary_namespaces)
|
76
|
+
puts
|
77
|
+
puts "Additional topics:"
|
78
|
+
puts
|
79
|
+
summary_for_namespaces(additional_namespaces)
|
80
|
+
puts
|
81
|
+
end
|
82
|
+
|
83
|
+
def help_for_namespace(name)
|
84
|
+
namespace_commands = commands_for_namespace(name)
|
85
|
+
|
86
|
+
unless namespace_commands.empty?
|
87
|
+
size = longest(namespace_commands.map { |c| c[:banner] })
|
88
|
+
namespace_commands.sort_by { |c| c[:banner].to_s }.each do |command|
|
89
|
+
next if command[:help] =~ /DEPRECATED/
|
90
|
+
command[:summary] ||= legacy_help_for_command(command[:command])
|
91
|
+
puts " %-#{size}s # %s" % [ command[:banner], command[:summary] ]
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def help_for_command(name)
|
97
|
+
command = commands[name]
|
98
|
+
|
99
|
+
if command
|
100
|
+
if command[:help].strip.length > 0
|
101
|
+
puts "Usage: hmx #{command[:banner]}"
|
102
|
+
puts command[:help].split("\n")[1..-1].join("\n")
|
103
|
+
puts
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
unless commands_for_namespace(name).empty?
|
108
|
+
puts "Additional commands, type \"hmx help COMMAND\" for more details:"
|
109
|
+
puts
|
110
|
+
help_for_namespace(name)
|
111
|
+
puts
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require "hmx/command/base"
|
2
|
+
|
3
|
+
module HmxClient::Command
|
4
|
+
|
5
|
+
# Perform queries against data in hmx
|
6
|
+
#
|
7
|
+
class Query < Base
|
8
|
+
|
9
|
+
# query
|
10
|
+
#
|
11
|
+
# query for documents in a type
|
12
|
+
#
|
13
|
+
# TYPENAME
|
14
|
+
#
|
15
|
+
def index
|
16
|
+
unless args.size > 0
|
17
|
+
raise CommandFailed, "Usage: hmx query <typeName> [<key>=<value>, [<key2>=<value2>...]]"
|
18
|
+
end
|
19
|
+
display hmx.query(args.shift, nil)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require "hmx/command/base"
|
2
|
+
require 'date'
|
3
|
+
|
4
|
+
module HmxClient::Command
|
5
|
+
|
6
|
+
# Display and manage session information for hmx
|
7
|
+
#
|
8
|
+
class Session < Base
|
9
|
+
|
10
|
+
# session
|
11
|
+
#
|
12
|
+
# List the sessions and their status on hmx
|
13
|
+
def index
|
14
|
+
displayNames = hmx.query('sys.session', nil)
|
15
|
+
objs = []
|
16
|
+
displayNames.each do | name |
|
17
|
+
data = hmx.getContent([name])
|
18
|
+
dval = JSON.parse(data)
|
19
|
+
dval["MXSession"]["validUntil"] = Time.at(dval["MXSession"]["validUntil"] / 1000).to_datetime.strftime
|
20
|
+
objs << dval["MXSession"]
|
21
|
+
end
|
22
|
+
cols = [ 'sessionId', 'userId', 'authenticated','validUntil' ]
|
23
|
+
headers = [ 'Session', 'Username', 'Authenticated', 'ValidUntil' ]
|
24
|
+
display_table(objs, cols, headers)
|
25
|
+
end
|
26
|
+
|
27
|
+
# session:expire
|
28
|
+
#
|
29
|
+
# Forces the expiry of any old sessions
|
30
|
+
#
|
31
|
+
def expire
|
32
|
+
display hmx.expireSessions([])
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require "hmx/command/base"
|
2
|
+
require 'date'
|
3
|
+
|
4
|
+
module HmxClient::Command
|
5
|
+
|
6
|
+
# Display and manage tasks in hmx
|
7
|
+
#
|
8
|
+
class Task < Base
|
9
|
+
|
10
|
+
# task
|
11
|
+
#
|
12
|
+
# List all of the tasks
|
13
|
+
def index
|
14
|
+
tasks = hmx.getAllTasks([])
|
15
|
+
objs = []
|
16
|
+
tasks.each do | t |
|
17
|
+
task = hmx.getTask([t])
|
18
|
+
objs << task
|
19
|
+
end
|
20
|
+
headers = [ "TaskId", "TaskType", "TaskState", "GroupId" ]
|
21
|
+
cols = [ "taskId", "taskType", "taskState", "group" ]
|
22
|
+
display_table(objs, cols, headers)
|
23
|
+
end
|
24
|
+
# task:purge
|
25
|
+
#
|
26
|
+
# Purge completed tasks
|
27
|
+
def purge
|
28
|
+
hmx.purgeTasks([])
|
29
|
+
display "Purge complete"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require "hmx/command/base"
|
2
|
+
require 'date'
|
3
|
+
|
4
|
+
module HmxClient::Command
|
5
|
+
|
6
|
+
# Display and manage type information in hmx
|
7
|
+
#
|
8
|
+
class Type < Base
|
9
|
+
|
10
|
+
# type
|
11
|
+
#
|
12
|
+
# Display information about a HMX type
|
13
|
+
def index
|
14
|
+
puts JSON.pretty_generate(hmx.getType(args.shift))
|
15
|
+
end
|
16
|
+
|
17
|
+
# type:create
|
18
|
+
#
|
19
|
+
# Create a type with default settings - no triggers, no entitlements
|
20
|
+
def create
|
21
|
+
typeInfo = { "name" => args.shift, "triggers" => [], "typeNature" => "CONTENT", "typeIndexScript" => "", "typeAspect" => "JSONDOCUMENT" }
|
22
|
+
hmx.updateType(typeInfo)
|
23
|
+
puts "Done..."
|
24
|
+
end
|
25
|
+
|
26
|
+
# type:clone-ent
|
27
|
+
#
|
28
|
+
# Clone the entitlements from one type to another
|
29
|
+
#
|
30
|
+
# <srcType> <targType>
|
31
|
+
def clone
|
32
|
+
# We basically load the documents for sys.ent/type/[source]/query and sys.ent/type/[source]/query and copy them to the target
|
33
|
+
sourceType = args.shift
|
34
|
+
targetType = args.shift
|
35
|
+
arr = JSON.parse(hmx.getContent(["sys.ent/type/#{ sourceType }/get"]))
|
36
|
+
arr["MXEntitlement"]["entitlementPath"] = "type/#{ targetType }/get"
|
37
|
+
hmx.putSimpleData([ "sys.ent/type/#{ targetType}/get", JSON.generate(arr)])
|
38
|
+
|
39
|
+
arr = JSON.parse(hmx.getContent(["sys.ent/type/#{ sourceType }/query"]))
|
40
|
+
arr["MXEntitlement"]["entitlementPath"] = "type/#{ targetType }/query"
|
41
|
+
hmx.putSimpleData([ "sys.ent/type/#{ targetType}/query", JSON.generate(arr)])
|
42
|
+
puts "Done..."
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require "hmx/command/base"
|
2
|
+
|
3
|
+
module HmxClient::Command
|
4
|
+
|
5
|
+
# Manipulate user entities in hmx
|
6
|
+
#
|
7
|
+
class User < Base
|
8
|
+
|
9
|
+
# user
|
10
|
+
#
|
11
|
+
# manipulate user enties in hMX
|
12
|
+
#
|
13
|
+
#
|
14
|
+
def index
|
15
|
+
unless args.size > 0
|
16
|
+
raise CommandFailed, "Usage: hmx user <userId>"
|
17
|
+
end
|
18
|
+
userName = args.shift
|
19
|
+
dout JSON.pretty_generate(hmx.getData(["sys.user/#{userName}"]))
|
20
|
+
end
|
21
|
+
|
22
|
+
# user:list
|
23
|
+
#
|
24
|
+
# Lists all of the users in the system
|
25
|
+
|
26
|
+
def list
|
27
|
+
views = hmx.query("sys.user", nil)
|
28
|
+
views.each { | v |
|
29
|
+
display v.rpartition('/')[2]
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
# user:get
|
34
|
+
#
|
35
|
+
# Retrieves the definition of a user
|
36
|
+
#
|
37
|
+
def get
|
38
|
+
index
|
39
|
+
end
|
40
|
+
|
41
|
+
# user:password
|
42
|
+
#
|
43
|
+
# Sets the password for a user
|
44
|
+
#
|
45
|
+
def password
|
46
|
+
unless args.size > 1
|
47
|
+
raise CommandFailed, "Usage: hmx user:password <userId> <newPassword>"
|
48
|
+
end
|
49
|
+
user = args.shift
|
50
|
+
userName = "sys.user/#{user}"
|
51
|
+
password = Digest::MD5.hexdigest(args.shift)
|
52
|
+
dataDocument = hmx.getData([userName])
|
53
|
+
dataDocument['document']['MXUser']['hashPassword'] = password
|
54
|
+
display hmx.putData([JSON.generate(dataDocument)])
|
55
|
+
end
|
56
|
+
|
57
|
+
# user:delete
|
58
|
+
#
|
59
|
+
# Removes a user
|
60
|
+
#
|
61
|
+
def delete
|
62
|
+
# We also need to remove the user reference from any groups they belong to (sys.entgroup)
|
63
|
+
# We should be clever and use a custom view for that purpose
|
64
|
+
# something like
|
65
|
+
# (fn[param] (fn[x] (contains (param "user" (.get x '(:document :MXEntitlementGroup :users ))))))
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,155 @@
|
|
1
|
+
require "hmx/command/base"
|
2
|
+
|
3
|
+
module HmxClient::Command
|
4
|
+
|
5
|
+
# Display the results of a view and list all views
|
6
|
+
#
|
7
|
+
class View < Base
|
8
|
+
|
9
|
+
# view
|
10
|
+
#
|
11
|
+
# run a view in hmx, passing in a view name and an input to the filter function
|
12
|
+
#
|
13
|
+
#
|
14
|
+
def index
|
15
|
+
unless args.size > 0
|
16
|
+
raise CommandFailed, "Usage: hmx view <viewName> <filterContext>"
|
17
|
+
end
|
18
|
+
viewData = hmx.runView(args.shift, JSON.parse(args.shift))
|
19
|
+
resp = ''
|
20
|
+
viewData.each { | line |
|
21
|
+
line.each { | cell | resp = resp + "%20.20s\t" % cell }
|
22
|
+
resp = resp + "\n"
|
23
|
+
}
|
24
|
+
dout resp
|
25
|
+
end
|
26
|
+
|
27
|
+
# view:list
|
28
|
+
#
|
29
|
+
# Lists all of the views in the system
|
30
|
+
|
31
|
+
def list
|
32
|
+
views = hmx.query("sys.view", nil)
|
33
|
+
views.each { | v |
|
34
|
+
display v.rpartition('/')[2]
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
# view:get
|
39
|
+
#
|
40
|
+
# Retrieves the definition of a view
|
41
|
+
#
|
42
|
+
def get
|
43
|
+
unless args.size > 0
|
44
|
+
raise CommandFailed, "Usage: hmx view:get <viewName>"
|
45
|
+
end
|
46
|
+
typeName = "sys.view/#{args.shift}"
|
47
|
+
display "Retrieving #{ typeName }"
|
48
|
+
dout JSON.pretty_generate(hmx.getData([typeName]))
|
49
|
+
end
|
50
|
+
|
51
|
+
# view:create
|
52
|
+
#
|
53
|
+
# Create a new (initially blank) view.
|
54
|
+
# You will then need to call update to set the filter function, map function, query params and
|
55
|
+
# result columns.
|
56
|
+
#
|
57
|
+
# Views are based on types, for create define a name and the type
|
58
|
+
def create
|
59
|
+
unless args.size > 1
|
60
|
+
raise CommanFailed, "Usage: hmx view:create <viewName> <typeName>"
|
61
|
+
end
|
62
|
+
view = args.shift
|
63
|
+
viewName = "sys.view/#{view}"
|
64
|
+
typeName = args.shift
|
65
|
+
|
66
|
+
dataDocument = {
|
67
|
+
"MXView" => {
|
68
|
+
:typeName => typeName,
|
69
|
+
:parameterNames => [],
|
70
|
+
:filterFn => "",
|
71
|
+
:mappingFn => "",
|
72
|
+
:resultColumns => [],
|
73
|
+
:viewName => view
|
74
|
+
}
|
75
|
+
}
|
76
|
+
|
77
|
+
dout JSON.pretty_generate(hmx.putSimpleData([viewName, JSON.generate(dataDocument)]))
|
78
|
+
end
|
79
|
+
|
80
|
+
# view:updateFilter
|
81
|
+
#
|
82
|
+
# Set the filter function for a view
|
83
|
+
#
|
84
|
+
def updateFilter
|
85
|
+
unless args.size > 1
|
86
|
+
raise CommandFailed, "Usage: hmx view:updateFilter <viewName> <filterFn>"
|
87
|
+
end
|
88
|
+
view = args.shift
|
89
|
+
viewName = "sys.view/#{view}"
|
90
|
+
filterFn = args.shift
|
91
|
+
|
92
|
+
dataDocument = hmx.getData([viewName])
|
93
|
+
puts dataDocument
|
94
|
+
dataDocument['document']['MXView']['filterFn'] = filterFn
|
95
|
+
display hmx.putData([JSON.generate(dataDocument)])
|
96
|
+
end
|
97
|
+
# view:updateMap
|
98
|
+
#
|
99
|
+
# Set the map function for a view
|
100
|
+
#
|
101
|
+
def updateMap
|
102
|
+
unless args.size > 1
|
103
|
+
raise CommandFailed, "Usage: hmx view:updateMap <viewName> <filterFn>"
|
104
|
+
end
|
105
|
+
view = args.shift
|
106
|
+
viewName = "sys.view/#{view}"
|
107
|
+
mapFn = args.shift
|
108
|
+
dataDocument = hmx.getData([viewName])
|
109
|
+
dataDocument['document']['MXView']['mappingFn'] = mapFn
|
110
|
+
display hmx.putData([JSON.generate(dataDocument)])
|
111
|
+
end
|
112
|
+
# view:updateParam
|
113
|
+
#
|
114
|
+
# Set the parameter names for a view
|
115
|
+
#
|
116
|
+
def updateParam
|
117
|
+
unless args.size > 1
|
118
|
+
raise CommandFailed, "Usage: hmx view:updateParam <viewName> <param> [<param2> ...]"
|
119
|
+
end
|
120
|
+
view = args.shift
|
121
|
+
viewName = "sys.view/#{view}"
|
122
|
+
dataDocument = hmx.getData([viewName])
|
123
|
+
dataDocument['document']['MXView']['parameterNames'] = args
|
124
|
+
display hmx.putData([JSON.generate(dataDocument)])
|
125
|
+
end
|
126
|
+
# view:updateResult
|
127
|
+
#
|
128
|
+
# Set the result names for a view
|
129
|
+
#
|
130
|
+
def updateResult
|
131
|
+
unless args.size > 1
|
132
|
+
raise CommandFailed, "Usage: hmx view:updateResult <viewName> <param> [<param2> ...]"
|
133
|
+
end
|
134
|
+
view = args.shift
|
135
|
+
viewName = "sys.view/#{view}"
|
136
|
+
|
137
|
+
dataDocument = hmx.getData([viewName])
|
138
|
+
dataDocument['document']['MXView']['resultColumns'] = args
|
139
|
+
display hmx.putData([JSON.generate(dataDocument)])
|
140
|
+
end
|
141
|
+
# view:delete
|
142
|
+
#
|
143
|
+
# Delete a view definition
|
144
|
+
#
|
145
|
+
def delete
|
146
|
+
unless args.size >0
|
147
|
+
raise CommandFailed, "Usage: hmx view:delete <viewName>"
|
148
|
+
end
|
149
|
+
view = args.shift
|
150
|
+
viewName = "sys.view/#{view}"
|
151
|
+
display hmx.deleteData(viewName)
|
152
|
+
end
|
153
|
+
|
154
|
+
end
|
155
|
+
end
|
data/lib/hmx/command.rb
ADDED
@@ -0,0 +1,140 @@
|
|
1
|
+
require "optparse"
|
2
|
+
require "hmx/helpers"
|
3
|
+
|
4
|
+
module HmxClient
|
5
|
+
module Command
|
6
|
+
class InvalidCommand < RuntimeError; end
|
7
|
+
class CommandFailed < RuntimeError; end
|
8
|
+
|
9
|
+
extend HmxClient::Helpers
|
10
|
+
|
11
|
+
def self.load
|
12
|
+
Dir[File.join(File.dirname(__FILE__), "command", "*.rb")].each do | file |
|
13
|
+
require file
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.commands
|
18
|
+
@@command ||= {}
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.command_aliases
|
22
|
+
@@command_aliases ||= {}
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.namespaces
|
26
|
+
@@namespaces ||= {}
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.register_command(command)
|
30
|
+
commands[command[:command]] = command
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.register_namespace(namespace)
|
34
|
+
namespaces[namespace[:name]] = namespace
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.current_command
|
38
|
+
@current_command
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.current_args
|
42
|
+
@current_args
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.current_options
|
46
|
+
@current_options
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.global_options
|
50
|
+
@global_options ||= []
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.global_option(name, *args)
|
54
|
+
global_options << { :name => name, :args => args }
|
55
|
+
end
|
56
|
+
|
57
|
+
global_option :debug, "--debug", "-d"
|
58
|
+
global_option :fileIn, "--file-in FILE", "-i"
|
59
|
+
global_option :fileOut, "--file-out FILE", "-o"
|
60
|
+
|
61
|
+
def self.prepare_run(cmd, args=[])
|
62
|
+
command = parse(cmd)
|
63
|
+
|
64
|
+
unless command
|
65
|
+
error " ! #{cmd} is not a hmx command. See 'hmx help'."
|
66
|
+
return
|
67
|
+
end
|
68
|
+
|
69
|
+
@current_command = cmd
|
70
|
+
opts = {}
|
71
|
+
invalid_options = []
|
72
|
+
|
73
|
+
parser = OptionParser.new do | parser |
|
74
|
+
global_options.each do | global_option |
|
75
|
+
parser.on(*global_option[:args]) do | value |
|
76
|
+
opts[global_option[:name]] = value
|
77
|
+
end
|
78
|
+
end
|
79
|
+
command[:options].each do | name, option |
|
80
|
+
parser.on("-#{option[:short]}", "--#{option[:long]}", option[:desc]) do | value |
|
81
|
+
opts[name.gsub("-","_").to_sym] = value
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
begin
|
87
|
+
parser.order!(args) do |nonopt|
|
88
|
+
invalid_options << nonopt
|
89
|
+
end
|
90
|
+
rescue OptionParser::InvalidOption => ex
|
91
|
+
invalid_options << ex.args.first
|
92
|
+
retry
|
93
|
+
end
|
94
|
+
|
95
|
+
raise OptionParser::ParseError if opts[:help]
|
96
|
+
|
97
|
+
args.concat(invalid_options)
|
98
|
+
|
99
|
+
@current_args = args
|
100
|
+
@current_options = opts
|
101
|
+
|
102
|
+
[ command[:klass].new(args.dup, opts.dup), command[:method] ]
|
103
|
+
end
|
104
|
+
|
105
|
+
def self.debug?
|
106
|
+
@current_options.has_key?(:debug)
|
107
|
+
end
|
108
|
+
|
109
|
+
def self.fileIn
|
110
|
+
@current_options[:fileIn]
|
111
|
+
end
|
112
|
+
|
113
|
+
def self.fileOut
|
114
|
+
@current_options[:fileOut]
|
115
|
+
end
|
116
|
+
|
117
|
+
def self.run(cmd, arguments=[])
|
118
|
+
object, method = prepare_run(cmd, arguments.dup)
|
119
|
+
object.send(method)
|
120
|
+
rescue InvalidCommand
|
121
|
+
error "Unknown command. Run 'hmx help' for usage information."
|
122
|
+
rescue CommandFailed => e
|
123
|
+
error e.message
|
124
|
+
rescue OptionParser::ParseError => ex
|
125
|
+
commands[cmd] ? run("help", [cmd]) : run("help")
|
126
|
+
rescue Interrupt => e
|
127
|
+
error "\n[cancelled]"
|
128
|
+
end
|
129
|
+
|
130
|
+
def self.parse(cmd)
|
131
|
+
commands[cmd] || commands[command_aliases[cmd]]
|
132
|
+
end
|
133
|
+
|
134
|
+
def self.extract_error(body, options={})
|
135
|
+
default_error = block_given ? yield : "Internal server error"
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
|