hmx_client 0.0.5 → 0.0.6

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.
@@ -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
@@ -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
+