MuranoCLI 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (151) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +28 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +21 -0
  5. data/Gemfile +27 -0
  6. data/LICENSE.txt +19 -0
  7. data/MuranoCLI.gemspec +50 -0
  8. data/MuranoCLI.iss +50 -0
  9. data/README.markdown +208 -0
  10. data/Rakefile +188 -0
  11. data/TODO.taskpaper +122 -0
  12. data/bin/mr +8 -0
  13. data/bin/murano +84 -0
  14. data/docs/demo.md +109 -0
  15. data/lib/MrMurano/Account.rb +211 -0
  16. data/lib/MrMurano/Config-Migrate.rb +47 -0
  17. data/lib/MrMurano/Config.rb +286 -0
  18. data/lib/MrMurano/Mock.rb +63 -0
  19. data/lib/MrMurano/Product-1P-Device.rb +145 -0
  20. data/lib/MrMurano/Product-Resources.rb +195 -0
  21. data/lib/MrMurano/Product.rb +358 -0
  22. data/lib/MrMurano/ProjectFile.rb +349 -0
  23. data/lib/MrMurano/Solution-Cors.rb +46 -0
  24. data/lib/MrMurano/Solution-Endpoint.rb +177 -0
  25. data/lib/MrMurano/Solution-File.rb +150 -0
  26. data/lib/MrMurano/Solution-ServiceConfig.rb +140 -0
  27. data/lib/MrMurano/Solution-Services.rb +326 -0
  28. data/lib/MrMurano/Solution-Users.rb +129 -0
  29. data/lib/MrMurano/Solution.rb +59 -0
  30. data/lib/MrMurano/SubCmdGroupContext.rb +49 -0
  31. data/lib/MrMurano/SyncUpDown.rb +565 -0
  32. data/lib/MrMurano/commands/assign.rb +57 -0
  33. data/lib/MrMurano/commands/businessList.rb +45 -0
  34. data/lib/MrMurano/commands/completion.rb +152 -0
  35. data/lib/MrMurano/commands/config.rb +67 -0
  36. data/lib/MrMurano/commands/content.rb +130 -0
  37. data/lib/MrMurano/commands/cors.rb +30 -0
  38. data/lib/MrMurano/commands/domain.rb +17 -0
  39. data/lib/MrMurano/commands/gb.rb +33 -0
  40. data/lib/MrMurano/commands/init.rb +138 -0
  41. data/lib/MrMurano/commands/keystore.rb +157 -0
  42. data/lib/MrMurano/commands/logs.rb +78 -0
  43. data/lib/MrMurano/commands/mock.rb +63 -0
  44. data/lib/MrMurano/commands/password.rb +88 -0
  45. data/lib/MrMurano/commands/postgresql.rb +41 -0
  46. data/lib/MrMurano/commands/product.rb +14 -0
  47. data/lib/MrMurano/commands/productCreate.rb +39 -0
  48. data/lib/MrMurano/commands/productDelete.rb +33 -0
  49. data/lib/MrMurano/commands/productDevice.rb +84 -0
  50. data/lib/MrMurano/commands/productDeviceIdCmds.rb +86 -0
  51. data/lib/MrMurano/commands/productList.rb +45 -0
  52. data/lib/MrMurano/commands/productWrite.rb +27 -0
  53. data/lib/MrMurano/commands/show.rb +80 -0
  54. data/lib/MrMurano/commands/solution.rb +14 -0
  55. data/lib/MrMurano/commands/solutionCreate.rb +39 -0
  56. data/lib/MrMurano/commands/solutionDelete.rb +34 -0
  57. data/lib/MrMurano/commands/solutionList.rb +45 -0
  58. data/lib/MrMurano/commands/status.rb +92 -0
  59. data/lib/MrMurano/commands/sync.rb +60 -0
  60. data/lib/MrMurano/commands/timeseries.rb +115 -0
  61. data/lib/MrMurano/commands/tsdb.rb +271 -0
  62. data/lib/MrMurano/commands/usage.rb +23 -0
  63. data/lib/MrMurano/commands/zshcomplete.erb +112 -0
  64. data/lib/MrMurano/commands.rb +32 -0
  65. data/lib/MrMurano/hash.rb +20 -0
  66. data/lib/MrMurano/http.rb +153 -0
  67. data/lib/MrMurano/makePretty.rb +75 -0
  68. data/lib/MrMurano/schema/pf-v1.0.0.yaml +114 -0
  69. data/lib/MrMurano/schema/sf-v0.2.0.yaml +77 -0
  70. data/lib/MrMurano/schema/sf-v0.3.0.yaml +78 -0
  71. data/lib/MrMurano/template/mock.erb +9 -0
  72. data/lib/MrMurano/template/projectFile.murano.erb +81 -0
  73. data/lib/MrMurano/verbosing.rb +99 -0
  74. data/lib/MrMurano/version.rb +4 -0
  75. data/lib/MrMurano.rb +20 -0
  76. data/spec/Account-Passwords_spec.rb +242 -0
  77. data/spec/Account_spec.rb +272 -0
  78. data/spec/ConfigFile_spec.rb +50 -0
  79. data/spec/ConfigMigrate_spec.rb +89 -0
  80. data/spec/Config_spec.rb +409 -0
  81. data/spec/Http_spec.rb +204 -0
  82. data/spec/MakePretties_spec.rb +118 -0
  83. data/spec/Mock_spec.rb +53 -0
  84. data/spec/ProductBase_spec.rb +113 -0
  85. data/spec/ProductContent_spec.rb +162 -0
  86. data/spec/ProductResources_spec.rb +329 -0
  87. data/spec/Product_1P_Device_spec.rb +202 -0
  88. data/spec/Product_1P_RPC_spec.rb +175 -0
  89. data/spec/Product_spec.rb +153 -0
  90. data/spec/ProjectFile_spec.rb +324 -0
  91. data/spec/Solution-Cors_spec.rb +164 -0
  92. data/spec/Solution-Endpoint_spec.rb +581 -0
  93. data/spec/Solution-File_spec.rb +212 -0
  94. data/spec/Solution-ServiceConfig_spec.rb +202 -0
  95. data/spec/Solution-ServiceDevice_spec.rb +176 -0
  96. data/spec/Solution-ServiceEventHandler_spec.rb +385 -0
  97. data/spec/Solution-ServiceModules_spec.rb +465 -0
  98. data/spec/Solution-UsersRoles_spec.rb +207 -0
  99. data/spec/Solution_spec.rb +92 -0
  100. data/spec/SyncRoot_spec.rb +83 -0
  101. data/spec/SyncUpDown_spec.rb +495 -0
  102. data/spec/Verbosing_spec.rb +279 -0
  103. data/spec/_workspace.rb +27 -0
  104. data/spec/cmd_assign_spec.rb +51 -0
  105. data/spec/cmd_business_spec.rb +59 -0
  106. data/spec/cmd_common.rb +72 -0
  107. data/spec/cmd_config_spec.rb +68 -0
  108. data/spec/cmd_content_spec.rb +71 -0
  109. data/spec/cmd_cors_spec.rb +50 -0
  110. data/spec/cmd_device_spec.rb +96 -0
  111. data/spec/cmd_domain_spec.rb +32 -0
  112. data/spec/cmd_init_spec.rb +30 -0
  113. data/spec/cmd_keystore_spec.rb +97 -0
  114. data/spec/cmd_password_spec.rb +62 -0
  115. data/spec/cmd_status_spec.rb +239 -0
  116. data/spec/cmd_syncdown_spec.rb +86 -0
  117. data/spec/cmd_syncup_spec.rb +62 -0
  118. data/spec/cmd_usage_spec.rb +36 -0
  119. data/spec/fixtures/.mrmuranorc +9 -0
  120. data/spec/fixtures/ProjectFiles/invalid.yaml +9 -0
  121. data/spec/fixtures/ProjectFiles/only_meta.yaml +24 -0
  122. data/spec/fixtures/ProjectFiles/with_routes.yaml +27 -0
  123. data/spec/fixtures/SolutionFiles/0.2.0.json +20 -0
  124. data/spec/fixtures/SolutionFiles/0.2.0_invalid.json +18 -0
  125. data/spec/fixtures/SolutionFiles/0.2.json +21 -0
  126. data/spec/fixtures/SolutionFiles/0.3.0.json +20 -0
  127. data/spec/fixtures/SolutionFiles/0.3.0_invalid.json +19 -0
  128. data/spec/fixtures/SolutionFiles/0.3.json +20 -0
  129. data/spec/fixtures/SolutionFiles/basic.json +20 -0
  130. data/spec/fixtures/SolutionFiles/secret.json +6 -0
  131. data/spec/fixtures/configfile +9 -0
  132. data/spec/fixtures/dumped_config +42 -0
  133. data/spec/fixtures/mrmuranorc_deleted_bob +8 -0
  134. data/spec/fixtures/mrmuranorc_tool_bob +3 -0
  135. data/spec/fixtures/product_spec_files/example.exoline.spec.yaml +116 -0
  136. data/spec/fixtures/product_spec_files/example.murano.spec.yaml +14 -0
  137. data/spec/fixtures/product_spec_files/gwe.exoline.spec.yaml +21 -0
  138. data/spec/fixtures/product_spec_files/gwe.murano.spec.yaml +16 -0
  139. data/spec/fixtures/product_spec_files/lightbulb-no-state.yaml +11 -0
  140. data/spec/fixtures/product_spec_files/lightbulb.yaml +14 -0
  141. data/spec/fixtures/roles-three.yaml +11 -0
  142. data/spec/fixtures/syncable_content/assets/icon.png +0 -0
  143. data/spec/fixtures/syncable_content/assets/index.html +0 -0
  144. data/spec/fixtures/syncable_content/assets/js/script.js +0 -0
  145. data/spec/fixtures/syncable_content/modules/table_util.lua +58 -0
  146. data/spec/fixtures/syncable_content/routes/manyRoutes.lua +11 -0
  147. data/spec/fixtures/syncable_content/routes/singleRoute.lua +5 -0
  148. data/spec/fixtures/syncable_content/services/devdata.lua +18 -0
  149. data/spec/fixtures/syncable_content/services/timers.lua +4 -0
  150. data/spec/spec_helper.rb +119 -0
  151. metadata +498 -0
@@ -0,0 +1,32 @@
1
+ require 'MrMurano/commands/assign'
2
+ require 'MrMurano/commands/businessList'
3
+ require 'MrMurano/commands/config'
4
+ require 'MrMurano/commands/content'
5
+ require 'MrMurano/commands/cors'
6
+ require 'MrMurano/commands/domain'
7
+ require 'MrMurano/commands/init'
8
+ require 'MrMurano/commands/keystore'
9
+ require 'MrMurano/commands/logs'
10
+ require 'MrMurano/commands/mock'
11
+ require 'MrMurano/commands/postgresql'
12
+ require 'MrMurano/commands/password'
13
+ require 'MrMurano/commands/product'
14
+ require 'MrMurano/commands/productCreate'
15
+ require 'MrMurano/commands/productDelete'
16
+ require 'MrMurano/commands/productDevice'
17
+ require 'MrMurano/commands/productDeviceIdCmds'
18
+ require 'MrMurano/commands/productList'
19
+ require 'MrMurano/commands/productWrite'
20
+ require 'MrMurano/commands/show'
21
+ require 'MrMurano/commands/solution'
22
+ require 'MrMurano/commands/solutionCreate'
23
+ require 'MrMurano/commands/solutionDelete'
24
+ require 'MrMurano/commands/solutionList'
25
+ require 'MrMurano/commands/status'
26
+ require 'MrMurano/commands/sync'
27
+ require 'MrMurano/commands/timeseries'
28
+ require 'MrMurano/commands/tsdb'
29
+ require 'MrMurano/commands/usage'
30
+
31
+ require 'MrMurano/commands/completion'
32
+
@@ -0,0 +1,20 @@
1
+
2
+ # from: http://www.any-where.de/blog/ruby-hash-convert-string-keys-to-symbols/
3
+ class Hash
4
+ #take keys of hash and transform those to a symbols
5
+ def self.transform_keys_to_symbols(value)
6
+ return value.map{|v| Hash.transform_keys_to_symbols(v)} if value.is_a?(Array)
7
+ return value if not value.is_a?(Hash)
8
+ hash = value.inject({}){|memo,(k,v)| memo[k.to_sym] = Hash.transform_keys_to_symbols(v); memo}
9
+ return hash
10
+ end
11
+ #take keys of hash and transform those to strings
12
+ def self.transform_keys_to_strings(value)
13
+ return value.map{|v| Hash.transform_keys_to_strings(v)} if value.is_a?(Array)
14
+ return value if not value.is_a?(Hash)
15
+ hash = value.inject({}){|memo,(k,v)| memo[k.to_s] = Hash.transform_keys_to_strings(v); memo}
16
+ return hash
17
+ end
18
+ end
19
+
20
+ # vim: set ai et sw=2 ts=2 :
@@ -0,0 +1,153 @@
1
+ require 'uri'
2
+ require 'net/http'
3
+ require 'json'
4
+ require('certified') if Gem.win_platform?
5
+
6
+ module MrMurano
7
+ module Http
8
+ def token
9
+ return @token unless @token.nil?
10
+ @token = Account.new.token
11
+ raise "Not logged in!" if @token.nil?
12
+ @token
13
+ end
14
+
15
+ def json_opts
16
+ return @json_opts unless not defined?(@json_opts) or @json_opts.nil?
17
+ @json_opts = {
18
+ :allow_nan => true,
19
+ :symbolize_names => true,
20
+ :create_additions => false
21
+ }
22
+ end
23
+
24
+ def curldebug(request)
25
+ if $cfg['tool.curldebug'] then
26
+ a = []
27
+ a << %{curl -s }
28
+ if request.key?('Authorization') then
29
+ a << %{-H 'Authorization: #{request['Authorization']}'}
30
+ end
31
+ a << %{-H 'User-Agent: #{request['User-Agent']}'}
32
+ a << %{-H 'Content-Type: #{request.content_type}'}
33
+ a << %{-X #{request.method}}
34
+ a << %{'#{request.uri.to_s}'}
35
+ a << %{-d '#{request.body}'} unless request.body.nil?
36
+ puts a.join(' ')
37
+ end
38
+ end
39
+
40
+ def http
41
+ uri = URI('https://' + $cfg['net.host'])
42
+ if not defined?(@http) or @http.nil? then
43
+ @http = Net::HTTP.new(uri.host, uri.port)
44
+ @http.use_ssl = true
45
+ @http.start
46
+ end
47
+ @http
48
+ end
49
+ def http_reset
50
+ @http = nil
51
+ end
52
+
53
+ def set_def_headers(request)
54
+ request.content_type = 'application/json'
55
+ request['Authorization'] = 'token ' + token
56
+ request['User-Agent'] = "MrMurano/#{MrMurano::VERSION}"
57
+ request
58
+ end
59
+
60
+ def isJSON(data)
61
+ begin
62
+ return true, JSON.parse(data, json_opts)
63
+ rescue
64
+ return false, data
65
+ end
66
+ end
67
+
68
+ def showHttpError(request, response)
69
+ if $cfg['tool.debug'] then
70
+ puts "Sent #{request.method} #{request.uri.to_s}"
71
+ request.each_capitalized{|k,v| puts "> #{k}: #{v}"}
72
+ if request.body.nil? then
73
+ else
74
+ puts ">> #{request.body[0..156]}"
75
+ end
76
+ puts "Got #{response.code} #{response.message}"
77
+ response.each_capitalized{|k,v| puts "< #{k}: #{v}"}
78
+ end
79
+ isj, jsn = isJSON(response.body)
80
+ resp = "Request Failed: #{response.code}: "
81
+ if isj then
82
+ if $cfg['tool.fullerror'] then
83
+ resp << JSON.pretty_generate(jsn)
84
+ else
85
+ resp << "[#{jsn[:statusCode]}] " if jsn.has_key? :statusCode
86
+ resp << jsn[:message] if jsn.has_key? :message
87
+ end
88
+ else
89
+ resp << jsn
90
+ end
91
+ # assuming verbosing was included.
92
+ error resp
93
+ end
94
+
95
+ def workit(request, &block)
96
+ curldebug(request)
97
+ if block_given? then
98
+ return yield request, http()
99
+ else
100
+ response = http().request(request)
101
+ case response
102
+ when Net::HTTPSuccess
103
+ return {} if response.body.nil?
104
+ begin
105
+ return JSON.parse(response.body, json_opts)
106
+ rescue
107
+ return response.body
108
+ end
109
+ else
110
+ showHttpError(request, response)
111
+ end
112
+ end
113
+ end
114
+
115
+ def get(path='', query=nil, &block)
116
+ uri = endPoint(path)
117
+ uri.query = URI.encode_www_form(query) unless query.nil?
118
+ workit(set_def_headers(Net::HTTP::Get.new(uri)), &block)
119
+ end
120
+
121
+ def post(path='', body={}, &block)
122
+ uri = endPoint(path)
123
+ req = Net::HTTP::Post.new(uri)
124
+ set_def_headers(req)
125
+ req.body = JSON.generate(body)
126
+ workit(req, &block)
127
+ end
128
+
129
+ def postf(path='', form={}, &block)
130
+ uri = endPoint(path)
131
+ req = Net::HTTP::Post.new(uri)
132
+ set_def_headers(req)
133
+ req.content_type = 'application/x-www-form-urlencoded; charset=utf-8'
134
+ req.form_data = form
135
+ workit(req, &block)
136
+ end
137
+
138
+ def put(path='', body={}, &block)
139
+ uri = endPoint(path)
140
+ req = Net::HTTP::Put.new(uri)
141
+ set_def_headers(req)
142
+ req.body = JSON.generate(body)
143
+ workit(req, &block)
144
+ end
145
+
146
+ def delete(path='', &block)
147
+ uri = endPoint(path)
148
+ workit(set_def_headers(Net::HTTP::Delete.new(uri)), &block)
149
+ end
150
+
151
+ end
152
+ end
153
+ # vim: set ai et sw=2 ts=2 :
@@ -0,0 +1,75 @@
1
+ require 'date'
2
+ require 'json'
3
+ require 'highline'
4
+
5
+ module MrMurano
6
+ module Pretties
7
+
8
+ HighLine::Style.new(:name=>:on_aliceblue, :code=>"\e[48;5;231m", :rgb=>[240, 248, 255])
9
+ PRETTIES_COLORSCHEME = HighLine::ColorScheme.new do |cs|
10
+ cs[:subject] = [:red, :on_aliceblue]
11
+ cs[:timestamp] = [:blue]
12
+ cs[:json] = [:magenta]
13
+ end
14
+ HighLine.color_scheme = PRETTIES_COLORSCHEME
15
+
16
+ def self.makeJsonPretty(data, options)
17
+ if options.pretty then
18
+ ret = JSON.pretty_generate(data).to_s
19
+ ret[0] = HighLine.color(ret[0], :json)
20
+ ret[-1] = HighLine.color(ret[-1], :json)
21
+ ret
22
+ else
23
+ data.to_json
24
+ end
25
+ end
26
+
27
+ def self.makePretty(line, options)
28
+ out=''
29
+ out << HighLine.color("#{line[:type] || '--'} ".upcase, :subject)
30
+ out << HighLine.color("[#{line[:subject] || ''}]", :subject)
31
+ out << " "
32
+ if line.has_key?(:timestamp) then
33
+ if line[:timestamp].kind_of? Numeric then
34
+ if options.localtime then
35
+ curtime = Time.at(line[:timestamp]).localtime.to_datetime.iso8601(3)
36
+ else
37
+ curtime = Time.at(line[:timestamp]).gmtime.to_datetime.iso8601(3)
38
+ end
39
+ else
40
+ curtime = line[:timestamp]
41
+ end
42
+ else
43
+ curtime = "<no timestamp>"
44
+ end
45
+ out << HighLine.color(curtime, :timestamp)
46
+ out << ":\n"
47
+ if line.has_key?(:data) then
48
+ data = line[:data]
49
+
50
+ if data.kind_of?(Hash) then
51
+ if data.has_key?(:request) and data.has_key?(:response) then
52
+ out << "---------\nrequest:"
53
+ out << makeJsonPretty(data[:request], options)
54
+
55
+ out << "\n---------\nresponse:"
56
+ out << makeJsonPretty(data[:response], options)
57
+ else
58
+ out << makeJsonPretty(data, options)
59
+ end
60
+ else
61
+ out << data.to_s
62
+ end
63
+
64
+ else
65
+ line.delete :type
66
+ line.delete :timestamp
67
+ line.delete :subject
68
+ out << makeJsonPretty(line, options)
69
+ end
70
+ out
71
+ end
72
+
73
+ end
74
+ end
75
+ # vim: set ai et sw=2 ts=2 :
@@ -0,0 +1,114 @@
1
+ ---
2
+ type: object
3
+ description: |-
4
+ A Project File. "*.murano"
5
+ This describes all of the bits and bobs that go into a Murano Solution.
6
+
7
+ additionalProperties: false
8
+ required: [info, formatversion]
9
+ properties:
10
+ formatversion:
11
+ type: string
12
+ description: The version of the format of this file
13
+ pattern: '1.0.0'
14
+
15
+ info:
16
+ type: object
17
+ description: Meta data about this Project.
18
+ properties:
19
+ name:
20
+ type: string
21
+ pattern: '^([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$'
22
+ description: |-
23
+ The name of this Project. This needs to be domain name safe, since it
24
+ will be used to construct the the app domain.
25
+ summary:
26
+ type: string
27
+ description: Short, one line descript of this project
28
+ description:
29
+ type: string
30
+ description: A longer, multiple paragraph explaination of this project
31
+ authors:
32
+ type: array
33
+ description: Who contributed to building this project.
34
+ minItems: 1
35
+ items:
36
+ type: string
37
+ version:
38
+ type: string
39
+ description: Version of this project. Use Semantic Versioning. http://semver.org/
40
+ pattern: '^(\d+\.)?(\d+\.)?(\*|\d+)$'
41
+ required:
42
+ - name
43
+ - summary
44
+ - description
45
+ - authors
46
+ additionalProperties: false
47
+
48
+ assets:
49
+ type: object
50
+ description: How to find the static assests for this project.
51
+ properties:
52
+ default_page:
53
+ type: string
54
+ "$ref": "#/definitions/common"
55
+
56
+ modules:
57
+ type: object
58
+ description: How to find the modules for this project.
59
+ properties:
60
+ "$ref": "#/definitions/common"
61
+
62
+ routes:
63
+ type: object
64
+ description: How to find the endpoint routes for this project.
65
+ properties:
66
+ "$ref": "#/definitions/common"
67
+ cors:
68
+ oneOf:
69
+ - type: string
70
+ - type: object
71
+ properties:
72
+ origin:
73
+ type: array
74
+ methods:
75
+ type: array
76
+ headers:
77
+ type: array
78
+ credentials:
79
+ type: boolean
80
+
81
+ services:
82
+ type: object
83
+ description: How to find the service event handlers for this project.
84
+ properties:
85
+ "$ref": "#/definitions/common"
86
+
87
+ resources:
88
+ type: object
89
+ description: Which aliases will exist on connected devices.
90
+ properties:
91
+ "$ref": "#/definitions/common"
92
+
93
+ definitions:
94
+ globSet:
95
+ anyOf:
96
+ - type: null
97
+ - type: string
98
+ - type: array
99
+ items:
100
+ type: string
101
+
102
+ common:
103
+ include:
104
+ description: Glob patterns to specify which files to include
105
+ "$ref": "#/definitions/globSet"
106
+ exclude:
107
+ description: Glob pattern to remove files from the included list
108
+ "$ref": "#/definitions/globSet"
109
+ location:
110
+ description: Directory prefix all include globs with
111
+ type: string
112
+
113
+
114
+ # vim: set et sw=2 ts=2 :
@@ -0,0 +1,77 @@
1
+ ---
2
+ type: object
3
+ description: |
4
+ A Solutionfile.json
5
+ This describes all of the bits and bobs that go into a Murano Solution.
6
+
7
+ properties:
8
+ version:
9
+ type: string
10
+ pattern: "0\\.2(\\.0)?"
11
+ description: Version format of the config
12
+
13
+ default_page:
14
+ type: string
15
+ description: The local file name to upload as /
16
+
17
+ file_dir:
18
+ type: string
19
+ description: Relative path to directory of static assets
20
+
21
+ custom_api:
22
+ type: string
23
+ description: Relative path of file containing endpoints (or routes)
24
+
25
+ custom_api_hook:
26
+ type: string
27
+ description: URL path to call at end of deploy
28
+
29
+ modules:
30
+ type: object
31
+ description: Additional lua chunks to load with endpoints and event handlers
32
+ patternProperties:
33
+ "[a-z]+":
34
+ type: string
35
+ description: Relative path to module script
36
+
37
+ event_handler:
38
+ type: object
39
+ description: Event handler scripts
40
+ properties:
41
+ device:
42
+ type: object
43
+ description: Device (Product) event handlers
44
+ properties:
45
+ datapoint:
46
+ type: string
47
+ description: Relative path to device.datapoint event script
48
+ required: [datapoint]
49
+ timer:
50
+ type: object
51
+ description: Timer event handlers
52
+ properties:
53
+ timer:
54
+ type: string
55
+ description: Relative path to timer.timer event script
56
+ required: [timer]
57
+ additionalProperties: false
58
+
59
+ cors:
60
+ type: object
61
+ properties:
62
+ origin:
63
+ type: array
64
+ methods:
65
+ type: array
66
+ headers:
67
+ type: array
68
+ credentials:
69
+ type: boolean
70
+
71
+ required:
72
+ - default_page
73
+ - file_dir
74
+ - custom_api
75
+ - event_handler
76
+ additionalProperties: false
77
+