charyf 0.1.1
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.
- checksums.yaml +7 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +154 -0
- data/LICENSE.txt +21 -0
- data/README.md +18 -0
- data/Rakefile +6 -0
- data/bin/charyf-debug +7 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/charyf.gemspec +48 -0
- data/exe/charyf +4 -0
- data/lib/charyf/deps.rb +9 -0
- data/lib/charyf/engine/all.rb +22 -0
- data/lib/charyf/engine/charyf.rb +5 -0
- data/lib/charyf/engine/context.rb +61 -0
- data/lib/charyf/engine/controller/actions.rb +29 -0
- data/lib/charyf/engine/controller/controller.rb +62 -0
- data/lib/charyf/engine/controller/conversation.rb +58 -0
- data/lib/charyf/engine/controller/helpers.rb +38 -0
- data/lib/charyf/engine/controller/renderers.rb +103 -0
- data/lib/charyf/engine/dispatcher/base.rb +121 -0
- data/lib/charyf/engine/dispatcher/default.rb +60 -0
- data/lib/charyf/engine/intent/intent.rb +54 -0
- data/lib/charyf/engine/intent/processors/dummy.rb +30 -0
- data/lib/charyf/engine/intent/processors/helpers.rb +32 -0
- data/lib/charyf/engine/intent/processors/processor.rb +56 -0
- data/lib/charyf/engine/interface/interface.rb +35 -0
- data/lib/charyf/engine/interface/program.rb +59 -0
- data/lib/charyf/engine/request.rb +32 -0
- data/lib/charyf/engine/response.rb +41 -0
- data/lib/charyf/engine/session/processors/default.rb +42 -0
- data/lib/charyf/engine/session/processors/processor.rb +39 -0
- data/lib/charyf/engine/session/session.rb +68 -0
- data/lib/charyf/engine/skill/info.rb +24 -0
- data/lib/charyf/engine/skill/routing.rb +57 -0
- data/lib/charyf/engine/skill/skill.rb +40 -0
- data/lib/charyf/engine.rb +3 -0
- data/lib/charyf/support/all.rb +4 -0
- data/lib/charyf/support/hash.rb +43 -0
- data/lib/charyf/support/object.rb +7 -0
- data/lib/charyf/support/string.rb +94 -0
- data/lib/charyf/support/string_inquirer.rb +17 -0
- data/lib/charyf/support.rb +1 -0
- data/lib/charyf/utils/all.rb +13 -0
- data/lib/charyf/utils/app_engine/extensions.rb +21 -0
- data/lib/charyf/utils/app_engine.rb +24 -0
- data/lib/charyf/utils/app_loader.rb +38 -0
- data/lib/charyf/utils/application/bootstrap.rb +176 -0
- data/lib/charyf/utils/application/configuration.rb +51 -0
- data/lib/charyf/utils/application.rb +131 -0
- data/lib/charyf/utils/charyf.rb +44 -0
- data/lib/charyf/utils/cli.rb +14 -0
- data/lib/charyf/utils/command/actions.rb +24 -0
- data/lib/charyf/utils/command/base.rb +138 -0
- data/lib/charyf/utils/command/behavior.rb +81 -0
- data/lib/charyf/utils/command/environment_argument.rb +40 -0
- data/lib/charyf/utils/command.rb +106 -0
- data/lib/charyf/utils/commands/all.rb +6 -0
- data/lib/charyf/utils/commands/application/application_command.rb +21 -0
- data/lib/charyf/utils/commands/cli/cli_command.rb +115 -0
- data/lib/charyf/utils/commands/console/console_command.rb +77 -0
- data/lib/charyf/utils/commands/destroy/destroy_command.rb +26 -0
- data/lib/charyf/utils/commands/generate/generate_command.rb +31 -0
- data/lib/charyf/utils/commands/help/USAGE +9 -0
- data/lib/charyf/utils/commands/help/help.rb +20 -0
- data/lib/charyf/utils/commands.rb +15 -0
- data/lib/charyf/utils/configuration.rb +36 -0
- data/lib/charyf/utils/error_handler.rb +26 -0
- data/lib/charyf/utils/extension/configurable.rb +41 -0
- data/lib/charyf/utils/extension/configuration.rb +63 -0
- data/lib/charyf/utils/extension.rb +129 -0
- data/lib/charyf/utils/generator/actions.rb +281 -0
- data/lib/charyf/utils/generator/base.rb +288 -0
- data/lib/charyf/utils/generators/app/USAGE +8 -0
- data/lib/charyf/utils/generators/app/app_generator.rb +274 -0
- data/lib/charyf/utils/generators/app/templates/Gemfile.erb +20 -0
- data/lib/charyf/utils/generators/app/templates/README.md +24 -0
- data/lib/charyf/utils/generators/app/templates/app/skill_controller.rb.tt +8 -0
- data/lib/charyf/utils/generators/app/templates/bin/charyf +5 -0
- data/lib/charyf/utils/generators/app/templates/config/application.rb.tt +32 -0
- data/lib/charyf/utils/generators/app/templates/config/boot.rb.tt +4 -0
- data/lib/charyf/utils/generators/app/templates/config/chapp.rb.tt +5 -0
- data/lib/charyf/utils/generators/app/templates/config/environments/development.rb.tt +2 -0
- data/lib/charyf/utils/generators/app/templates/config/environments/production.rb.tt +2 -0
- data/lib/charyf/utils/generators/app/templates/config/environments/test.rb.tt +2 -0
- data/lib/charyf/utils/generators/app/templates/config/load.rb.tt +17 -0
- data/lib/charyf/utils/generators/app/templates/gitignore +18 -0
- data/lib/charyf/utils/generators/app_base.rb +277 -0
- data/lib/charyf/utils/generators/defaults.rb +75 -0
- data/lib/charyf/utils/generators/intents/intents_generator.rb +41 -0
- data/lib/charyf/utils/generators/named_base.rb +73 -0
- data/lib/charyf/utils/generators/skill/skill_generator.rb +47 -0
- data/lib/charyf/utils/generators/skill/templates/controllers/skill_controller.rb.tt +10 -0
- data/lib/charyf/utils/generators/skill/templates/module.rb.tt +6 -0
- data/lib/charyf/utils/generators/skill/templates/skill.rb.tt +3 -0
- data/lib/charyf/utils/generators.rb +187 -0
- data/lib/charyf/utils/initializable.rb +95 -0
- data/lib/charyf/utils/logger.rb +26 -0
- data/lib/charyf/utils/machine.rb +129 -0
- data/lib/charyf/utils/parser/en_parser.rb +97 -0
- data/lib/charyf/utils/parser/parser.rb +37 -0
- data/lib/charyf/utils/ruby_version_check.rb +15 -0
- data/lib/charyf/utils/storage/provider.rb +44 -0
- data/lib/charyf/utils/strategy.rb +44 -0
- data/lib/charyf/utils/utils.rb +64 -0
- data/lib/charyf/utils.rb +2 -0
- data/lib/charyf/version.rb +19 -0
- data/lib/charyf.rb +18 -0
- data/lib/locale/en.yml +206 -0
- data/todo.md +3 -0
- metadata +272 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
require 'yaml'
|
|
2
|
+
|
|
3
|
+
module Charyf
|
|
4
|
+
module Engine
|
|
5
|
+
class Session
|
|
6
|
+
|
|
7
|
+
attr_reader :uuid, :skill, :controller, :action, :timestamp
|
|
8
|
+
|
|
9
|
+
# TODO - mention it could return nil
|
|
10
|
+
# TODO sig
|
|
11
|
+
def self.get(uuid)
|
|
12
|
+
yaml = _storage.get(uuid)
|
|
13
|
+
yaml ? YAML.load(yaml) : nil
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def self.init(uuid, skill_name)
|
|
17
|
+
session = self.new(uuid, skill_name)
|
|
18
|
+
|
|
19
|
+
_storage.store(uuid, YAML.dump(session))
|
|
20
|
+
|
|
21
|
+
session
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def route_to(controller, action)
|
|
25
|
+
@controller = controller
|
|
26
|
+
@action = action
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def storage
|
|
30
|
+
@storage ||= Charyf.application.storage_provider.get_for("#{self.class}_#{@uuid}")
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def keep!
|
|
34
|
+
@active = true
|
|
35
|
+
store!
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def invalidate!
|
|
39
|
+
@active = false
|
|
40
|
+
self.class._storage.remove(@uuid)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def store!
|
|
44
|
+
@timestamp = Time.now
|
|
45
|
+
self.class._storage.store(@uuid, YAML.dump(self))
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
sig [], ['Symbol', 'String', 'NilClass'],
|
|
49
|
+
def full_controller_name
|
|
50
|
+
@controller.blank? ? nil : @skill.camelize + '::' + @controller.camelize
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
private
|
|
54
|
+
|
|
55
|
+
def initialize(uuid, skill)
|
|
56
|
+
@uuid = uuid
|
|
57
|
+
@skill = skill
|
|
58
|
+
@active = true
|
|
59
|
+
@timestamp = Time.now
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def self._storage
|
|
63
|
+
@storage ||= Charyf.application.storage_provider.get_for(self)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module Charyf
|
|
2
|
+
module Skill
|
|
3
|
+
module Info
|
|
4
|
+
|
|
5
|
+
def self.included(base)
|
|
6
|
+
base.extend(ClassMethods)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
module ClassMethods
|
|
10
|
+
|
|
11
|
+
sig ['String', 'Symbol', 'NilClass'], ['Symbol'],
|
|
12
|
+
def skill_name(name = nil)
|
|
13
|
+
if name
|
|
14
|
+
@_name = name.to_sym
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
@_name || self.name.gsub('::', ' ')
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
module Charyf
|
|
2
|
+
module Skill
|
|
3
|
+
module Routing
|
|
4
|
+
|
|
5
|
+
def self.included(base)
|
|
6
|
+
base.extend(ClassMethods)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
module ClassMethods
|
|
10
|
+
|
|
11
|
+
sig ['Pathname'], ['Pathname'],
|
|
12
|
+
def routing_source_dir(abs_path = nil)
|
|
13
|
+
if abs_path
|
|
14
|
+
@_routing_source_dir = abs_path
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
@_routing_source_dir || skill_root.join('intents')
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def public_routing_for(processor_name)
|
|
21
|
+
_public_routing(processor_name) << Proc.new
|
|
22
|
+
|
|
23
|
+
nil
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def private_routing_for(processor_name)
|
|
27
|
+
_private_routing(processor_name) << Proc.new
|
|
28
|
+
|
|
29
|
+
nil
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _public_routing(processor)
|
|
34
|
+
processor = processor.to_sym
|
|
35
|
+
|
|
36
|
+
@_public_routing ||= Hash.new
|
|
37
|
+
|
|
38
|
+
@_public_routing[processor] ||= []
|
|
39
|
+
|
|
40
|
+
@_public_routing[processor]
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def _private_routing(processor)
|
|
44
|
+
processor = processor.to_sym
|
|
45
|
+
|
|
46
|
+
@_public_routing ||= Hash.new
|
|
47
|
+
|
|
48
|
+
@_public_routing[processor] ||= []
|
|
49
|
+
|
|
50
|
+
@_public_routing[processor]
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
end # End of ClassMethods
|
|
54
|
+
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
require_relative 'routing'
|
|
2
|
+
require_relative 'info'
|
|
3
|
+
|
|
4
|
+
module Charyf
|
|
5
|
+
module Skill
|
|
6
|
+
class Base
|
|
7
|
+
|
|
8
|
+
include Charyf::Skill::Routing
|
|
9
|
+
include Charyf::Skill::Info
|
|
10
|
+
|
|
11
|
+
class << self
|
|
12
|
+
attr_accessor :_file_path, :_file_name
|
|
13
|
+
|
|
14
|
+
def inherited(subclass)
|
|
15
|
+
Base._subclasses[subclass.name.demodulize] = subclass
|
|
16
|
+
|
|
17
|
+
# TODO this should be tested
|
|
18
|
+
subclass._file_path = Pathname.new(caller.first[/^[^:]+/]).dirname
|
|
19
|
+
subclass._file_name = Pathname.new(caller.first[/^[^:]+/]).basename
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def _subclasses
|
|
23
|
+
@_subclasses ||= Hash.new
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def self.skill_root
|
|
29
|
+
self._file_path.join(self._file_name.sub_ext(''))
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def self.list
|
|
36
|
+
Base._subclasses.values
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
class Hash
|
|
2
|
+
# Returns a new hash with +self+ and +other_hash+ merged recursively.
|
|
3
|
+
#
|
|
4
|
+
# h1 = { a: true, b: { c: [1, 2, 3] } }
|
|
5
|
+
# h2 = { a: false, b: { x: [3, 4, 5] } }
|
|
6
|
+
#
|
|
7
|
+
# h1.deep_merge(h2) # => { a: false, b: { c: [1, 2, 3], x: [3, 4, 5] } }
|
|
8
|
+
#
|
|
9
|
+
# Like with Hash#merge in the standard library, a block can be provided
|
|
10
|
+
# to merge values:
|
|
11
|
+
#
|
|
12
|
+
# h1 = { a: 100, b: 200, c: { c1: 100 } }
|
|
13
|
+
# h2 = { b: 250, c: { c1: 200 } }
|
|
14
|
+
# h1.deep_merge(h2) { |key, this_val, other_val| this_val + other_val }
|
|
15
|
+
# # => { a: 100, b: 450, c: { c1: 300 } }
|
|
16
|
+
def deep_merge(other_hash, options = {}, &block)
|
|
17
|
+
dup.deep_merge!(other_hash, options, &block)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Same as +deep_merge+, but modifies +self+.
|
|
21
|
+
def deep_merge!(other_hash, options = {}, &block)
|
|
22
|
+
other_hash.each_pair do |current_key, other_value|
|
|
23
|
+
this_value = self[current_key]
|
|
24
|
+
|
|
25
|
+
self[current_key] = if this_value.is_a?(Hash) && other_value.is_a?(Hash)
|
|
26
|
+
this_value.deep_merge(other_value, options, &block)
|
|
27
|
+
elsif options[:union_arrays] && (this_value.is_a?(Array) || other_value.is_a?(Array))
|
|
28
|
+
this_values = this_value.is_a?(Array) ? this_value : [this_value]
|
|
29
|
+
other_values = other_value.is_a?(Array) ? other_value : [other_value]
|
|
30
|
+
|
|
31
|
+
this_values | other_values
|
|
32
|
+
else
|
|
33
|
+
if block_given? && key?(current_key)
|
|
34
|
+
block.call(current_key, this_value, other_value)
|
|
35
|
+
else
|
|
36
|
+
other_value
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
self
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
class String
|
|
2
|
+
def camelize
|
|
3
|
+
self.split('_').collect(&:capitalize).join
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def underscore
|
|
7
|
+
self.gsub(/::/, '/').
|
|
8
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
|
9
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
|
10
|
+
tr("-", "_").
|
|
11
|
+
downcase
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def constantize
|
|
15
|
+
camel_cased_word = self
|
|
16
|
+
|
|
17
|
+
names = camel_cased_word.split('::')
|
|
18
|
+
|
|
19
|
+
# Trigger a built-in NameError exception including the ill-formed constant in the message.
|
|
20
|
+
Object.const_get(camel_cased_word) if names.empty?
|
|
21
|
+
|
|
22
|
+
# Remove the first blank element in case of '::ClassName' notation.
|
|
23
|
+
names.shift if names.size > 1 && names.first.empty?
|
|
24
|
+
|
|
25
|
+
names.inject(Object) do |constant, name|
|
|
26
|
+
if constant == Object
|
|
27
|
+
constant.const_get(name)
|
|
28
|
+
else
|
|
29
|
+
candidate = constant.const_get(name)
|
|
30
|
+
next candidate if constant.const_defined?(name, false)
|
|
31
|
+
next candidate unless Object.const_defined?(name)
|
|
32
|
+
|
|
33
|
+
# Go down the ancestors to check if it is owned directly. The check
|
|
34
|
+
# stops when we reach Object or the end of ancestors tree.
|
|
35
|
+
constant = constant.ancestors.inject do |const, ancestor|
|
|
36
|
+
break const if ancestor == Object
|
|
37
|
+
break ancestor if ancestor.const_defined?(name, false)
|
|
38
|
+
const
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# owner is in Object, so raise
|
|
42
|
+
constant.const_get(name, false)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def deconstantize
|
|
48
|
+
self.to_s[0, self.rindex("::") || 0]
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def demodulize
|
|
52
|
+
if (i = self.rindex("::"))
|
|
53
|
+
self[(i + 2)..-1]
|
|
54
|
+
else
|
|
55
|
+
self
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def squish
|
|
60
|
+
dup.squish!
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def squish!
|
|
64
|
+
gsub!(/\A[[:space:]]+/, '')
|
|
65
|
+
gsub!(/[[:space:]]+\z/, '')
|
|
66
|
+
gsub!(/[[:space:]]+/, ' ')
|
|
67
|
+
self
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def trim(str=nil)
|
|
71
|
+
return self.ltrim(str).rtrim(str)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def ltrim(str=nil)
|
|
75
|
+
if (!str)
|
|
76
|
+
return self.lstrip
|
|
77
|
+
else
|
|
78
|
+
escape = Regexp.escape(str)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
return self.gsub(/^#{escape}+/, "")
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def rtrim(str=nil)
|
|
85
|
+
if (!str)
|
|
86
|
+
return self.rstrip
|
|
87
|
+
else
|
|
88
|
+
escape = Regexp.escape(str)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
return self.gsub(/#{escape}+$/, "")
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module Charyf
|
|
2
|
+
class StringInquirer < String
|
|
3
|
+
private
|
|
4
|
+
|
|
5
|
+
def respond_to_missing?(method_name, include_private = false)
|
|
6
|
+
(method_name[-1] == "?") || super
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def method_missing(method_name, *arguments)
|
|
10
|
+
if method_name[-1] == "?"
|
|
11
|
+
self == method_name[0..-2]
|
|
12
|
+
else
|
|
13
|
+
super
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require_relative 'support/all'
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
require_relative 'parser/parser'
|
|
2
|
+
require_relative 'parser/en_parser'
|
|
3
|
+
|
|
4
|
+
require_relative 'storage/provider'
|
|
5
|
+
|
|
6
|
+
require_relative 'application'
|
|
7
|
+
require_relative 'charyf'
|
|
8
|
+
require_relative 'error_handler'
|
|
9
|
+
require_relative 'initializable'
|
|
10
|
+
require_relative 'logger'
|
|
11
|
+
require_relative 'machine'
|
|
12
|
+
require_relative 'strategy'
|
|
13
|
+
require_relative 'utils'
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module Charyf
|
|
2
|
+
class AppEngine < Extension
|
|
3
|
+
class Extensions
|
|
4
|
+
include Enumerable
|
|
5
|
+
attr_reader :_all
|
|
6
|
+
|
|
7
|
+
def initialize
|
|
8
|
+
@_all ||= ::Charyf::Extension.subclasses.map(&:instance) +
|
|
9
|
+
::Charyf::AppEngine.subclasses.map(&:instance)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def each(*args, &block)
|
|
13
|
+
_all.each(*args, &block)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def -(others)
|
|
17
|
+
_all - others
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'extension'
|
|
4
|
+
require_relative 'app_engine/extensions'
|
|
5
|
+
|
|
6
|
+
module Charyf
|
|
7
|
+
class AppEngine < Extension
|
|
8
|
+
|
|
9
|
+
# Load Charyf generators and invoke the registered hooks.
|
|
10
|
+
# Check <tt>Charyf::Extension.generators</tt> for more info.
|
|
11
|
+
def load_generators(app = self)
|
|
12
|
+
require_relative 'generators'
|
|
13
|
+
Charyf::Generators.configure!(app.config.generators)
|
|
14
|
+
|
|
15
|
+
require_relative 'generators/app/app_generator'
|
|
16
|
+
require_relative 'generators/skill/skill_generator'
|
|
17
|
+
require_relative 'generators/intents/intents_generator'
|
|
18
|
+
|
|
19
|
+
run_generators_blocks(app)
|
|
20
|
+
self
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'pathname'
|
|
4
|
+
|
|
5
|
+
module Charyf
|
|
6
|
+
module AppLoader # :nodoc:
|
|
7
|
+
extend self
|
|
8
|
+
|
|
9
|
+
RUBY = Gem.ruby
|
|
10
|
+
EXECUTABLES = %w(bin/charyf charyf/bin/charyf)
|
|
11
|
+
|
|
12
|
+
def exec_app
|
|
13
|
+
original_cwd = Dir.pwd
|
|
14
|
+
|
|
15
|
+
loop do
|
|
16
|
+
if exe = find_executable
|
|
17
|
+
contents = File.read(exe)
|
|
18
|
+
|
|
19
|
+
if contents =~ /(APP|ENGINE)_PATH/
|
|
20
|
+
exec RUBY, exe, *ARGV
|
|
21
|
+
break # non reachable, hack to be able to stub exec in the test suite
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# If we exhaust the search there is no executable, this could be a
|
|
26
|
+
# call to generate a new application, so restore the original cwd.
|
|
27
|
+
Dir.chdir(original_cwd) && return if Pathname.new(Dir.pwd).root?
|
|
28
|
+
|
|
29
|
+
# Otherwise keep moving upwards in search of an executable.
|
|
30
|
+
Dir.chdir("..")
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def find_executable
|
|
35
|
+
EXECUTABLES.find { |exe| File.file?(exe) }
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
require_relative '../app_engine'
|
|
2
|
+
require_relative '../initializable'
|
|
3
|
+
require_relative '../utils'
|
|
4
|
+
require 'i18n'
|
|
5
|
+
|
|
6
|
+
module Charyf
|
|
7
|
+
class Application < AppEngine
|
|
8
|
+
# noinspection RubyResolve
|
|
9
|
+
module Bootstrap
|
|
10
|
+
|
|
11
|
+
class SkillLoadError < StandardError
|
|
12
|
+
def initialize(e, skill_name, skill_path)
|
|
13
|
+
super(e)
|
|
14
|
+
|
|
15
|
+
@_name = skill_name
|
|
16
|
+
@_path = skill_path.dirname
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def message
|
|
20
|
+
_message + super
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def _message
|
|
24
|
+
<<-EOS
|
|
25
|
+
|
|
26
|
+
Unable to load skill #{@_name}
|
|
27
|
+
Expected to find: '#{@_name}.rb'
|
|
28
|
+
Located at: '#{@_path}'
|
|
29
|
+
|
|
30
|
+
EOS
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
include Charyf::Initializable
|
|
35
|
+
|
|
36
|
+
class InitializationError < StandardError; end
|
|
37
|
+
|
|
38
|
+
#
|
|
39
|
+
# Load app environment configuration files
|
|
40
|
+
# Default application configuration is when a command is triggered
|
|
41
|
+
# Nothing loaded unless environment file exists
|
|
42
|
+
#
|
|
43
|
+
initializer :load_environment, group: :all do
|
|
44
|
+
Charyf.logger.info "Charyf starting in #{Charyf.env} mode."
|
|
45
|
+
|
|
46
|
+
env_file = self.config.root.join('config', 'environments', "#{Charyf.env}.rb")
|
|
47
|
+
|
|
48
|
+
if FileTest.exists?(env_file)
|
|
49
|
+
require env_file
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
initializer :set_load_paths, group: :all do
|
|
54
|
+
libdir = File.expand_path(self.config.root.join('lib'))
|
|
55
|
+
$LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
#
|
|
59
|
+
# Loads I18N
|
|
60
|
+
#
|
|
61
|
+
initializer :load_i18n, group: :all do
|
|
62
|
+
I18n.load_path << Dir[Charyf._gem_source.join('locale', '**', '*.yml').to_s]
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
#
|
|
66
|
+
# Validates that all required strategies are fulfilled and the application can load
|
|
67
|
+
#
|
|
68
|
+
initializer :validate_strategies, group: :all do
|
|
69
|
+
Charyf.application.session_processor
|
|
70
|
+
Charyf.application.intent_processors
|
|
71
|
+
Charyf.application.dispatcher
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
#
|
|
75
|
+
# Load APP default files
|
|
76
|
+
#
|
|
77
|
+
initializer :load_defaults, group: :all do
|
|
78
|
+
require self.config.root.join('app', 'skill_controller.rb')
|
|
79
|
+
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
#
|
|
83
|
+
# Find all skills located in [YourApp]/app/skills/
|
|
84
|
+
#
|
|
85
|
+
initializer :load_skill_dir, group: :all do
|
|
86
|
+
# TODO revisit this
|
|
87
|
+
condition = lambda do |path|
|
|
88
|
+
in_root_dir = path.dirname.basename.to_s == 'skills'
|
|
89
|
+
contain_skill = Dir[path.dirname.join('**', '**')].any? { |p| p.include?('/controllers') } &&
|
|
90
|
+
Dir[path.dirname.join('**', '**')].any? { |p| p.include?('/intents') }
|
|
91
|
+
return in_root_dir || contain_skill
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Require skill level files
|
|
95
|
+
Charyf::Utils.require_recursive self.config.root.join('app', 'skills'),
|
|
96
|
+
condition: condition
|
|
97
|
+
|
|
98
|
+
# Require controllers
|
|
99
|
+
Charyf::Skill.list.each do |skill_klass|
|
|
100
|
+
# Load initializers
|
|
101
|
+
root = skill_klass.skill_root
|
|
102
|
+
|
|
103
|
+
Dir[root.join('controllers', '**', '*.rb')].each do |controller|
|
|
104
|
+
require controller
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
#
|
|
110
|
+
# Load all intents
|
|
111
|
+
#
|
|
112
|
+
initializer :load_skill_intents, groups: :all do
|
|
113
|
+
# Require Skill intents
|
|
114
|
+
Charyf::Skill.list.each do |skill_klass|
|
|
115
|
+
Dir[skill_klass.routing_source_dir.join('**', '*.rb')].each do |file|
|
|
116
|
+
require file
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
Charyf::Skill.list.each do |skill_klass|
|
|
121
|
+
skill_name = skill_klass.skill_name
|
|
122
|
+
|
|
123
|
+
Charyf.application.intent_processors.each do |processor|
|
|
124
|
+
# Public routing
|
|
125
|
+
skill_klass._public_routing(processor.strategy_name).each do |block|
|
|
126
|
+
processor.get_global.load skill_name, block
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Private routing
|
|
130
|
+
skill_klass._private_routing(processor.strategy_name).each do |block|
|
|
131
|
+
processor.get_for(skill_name).load skill_name, block
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
#
|
|
139
|
+
# Load all user skill files
|
|
140
|
+
# - controllers
|
|
141
|
+
#
|
|
142
|
+
initializer :load_skill_controllers, group: :all do
|
|
143
|
+
|
|
144
|
+
Charyf::Skill.list.each do |skill_klass|
|
|
145
|
+
|
|
146
|
+
# Load controllers
|
|
147
|
+
root = skill_klass.skill_root
|
|
148
|
+
|
|
149
|
+
Dir[root.join('controllers', '**', '*.rb')].each do |controller|
|
|
150
|
+
require controller
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
#
|
|
157
|
+
# Load user initializer files
|
|
158
|
+
#
|
|
159
|
+
initializer :run_initializers, group: :all do
|
|
160
|
+
Dir[self.config.root.join('config', 'initializers', '**', '**.rb')].each do |initializer|
|
|
161
|
+
require initializer
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
Charyf::Skill.list.each do |skill_klass|
|
|
165
|
+
# Load initializers
|
|
166
|
+
root = skill_klass.skill_root
|
|
167
|
+
|
|
168
|
+
Dir[root.join('initializers', '**', '*.rb')].each do |initializer|
|
|
169
|
+
require initializer
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
require_relative '../app_engine'
|
|
2
|
+
require_relative '../extension/configuration'
|
|
3
|
+
|
|
4
|
+
module Charyf
|
|
5
|
+
class Application < AppEngine
|
|
6
|
+
class Configuration < Extension::Configuration
|
|
7
|
+
|
|
8
|
+
attr_reader :root
|
|
9
|
+
|
|
10
|
+
attr_accessor :console
|
|
11
|
+
|
|
12
|
+
attr_accessor :session_processor, :storage_provider, :dispatcher
|
|
13
|
+
attr_accessor :enabled_intent_processors
|
|
14
|
+
|
|
15
|
+
def initialize(root)
|
|
16
|
+
|
|
17
|
+
@root = root
|
|
18
|
+
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def i18n
|
|
22
|
+
I18n
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def error_handlers
|
|
26
|
+
Charyf::ErrorHandlers
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
sig [], ['Symbol', 'NilClass'],
|
|
30
|
+
def dispatcher
|
|
31
|
+
(@dispatcher || 'default').to_sym
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
sig [], ['Symbol'],
|
|
35
|
+
def session_processor
|
|
36
|
+
(@session_processor || 'default').to_sym
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
sig [], [Array],
|
|
40
|
+
def enabled_intent_processors
|
|
41
|
+
(@enabled_intent_processors || []).map(&:to_sym)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
sig [], ['Symbol', 'NilClass'],
|
|
45
|
+
def storage_provider
|
|
46
|
+
@storage_provider ? @storage_provider.to_sym : nil
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|