lib/workato/connector/sdk/connector.rb in workato-connector-sdk-1.0.1 vs lib/workato/connector/sdk/connector.rb in workato-connector-sdk-1.0.2
- old
+ new
@@ -1,189 +1,253 @@
+# typed: strict
# frozen_string_literal: true
module Workato
module Connector
module Sdk
+ module SorbetTypes
+ SourceHash = T.type_alias { T.any(HashWithIndifferentAccess, T::Hash[T.any(Symbol, String), T.untyped]) }
+ end
+
class Connector
+ extend T::Sig
+
+ sig { returns(HashWithIndifferentAccess) }
attr_reader :source
+ sig { params(path_to_source_code: String, settings: SorbetTypes::SettingsHash).returns(Connector) }
def self.from_file(path_to_source_code = DEFAULT_CONNECTOR_PATH, settings = {})
new(eval(File.read(path_to_source_code), binding, path_to_source_code), settings) # rubocop:disable Security/Eval
end
+ sig { params(definition: SorbetTypes::SourceHash, settings: SorbetTypes::SettingsHash).void }
def initialize(definition, settings = {})
- @source = definition.with_indifferent_access
- @settings = settings.with_indifferent_access
- @connection_source = @source[:connection] || {}
- @methods_source = @source[:methods] || {}
+ @source = T.let(definition.with_indifferent_access, HashWithIndifferentAccess)
+ @settings = T.let(settings.with_indifferent_access, HashWithIndifferentAccess)
+ @connection_source = T.let(@source[:connection] || {}.with_indifferent_access, HashWithIndifferentAccess)
+ @methods_source = T.let(@source[:methods] || {}.with_indifferent_access, HashWithIndifferentAccess)
end
+ sig { params(path: String, params: T::Hash[Symbol, T.untyped]).returns(T.untyped) }
+ def invoke(path, params = {})
+ InvokePath.new(path: path, connector: self, params: params).call
+ end
+
+ sig { returns(T.nilable(String)) }
def title
@source[:title]
end
+ sig { returns(ActionsProxy) }
def actions
+ @actions = T.let(@actions, T.nilable(ActionsProxy))
@actions ||= ActionsProxy.new(
actions: source[:actions].presence || {},
methods: methods_source,
object_definitions: object_definitions,
- connection: connection,
- settings: settings
+ connection: connection
)
end
+ sig { returns(MethodsProxy) }
def methods
+ @methods = T.let(@methods, T.nilable(MethodsProxy))
@methods ||= MethodsProxy.new(
methods: methods_source,
- connection: connection,
- settings: settings
+ connection: connection
)
end
+ sig { params(settings: T.nilable(SorbetTypes::SettingsHash)).returns(T.untyped) }
def test(settings = nil)
+ @test = T.let(@test, T.nilable(Action))
@test ||= Action.new(
action: {
execute: source[:test]
},
methods: methods_source,
- connection: connection,
- settings: send(:settings)
- ).execute(settings)
+ connection: connection
+ )
+ @test.execute(settings)
end
+ sig { returns(TriggersProxy) }
def triggers
+ @triggers = T.let(@triggers, T.nilable(TriggersProxy))
@triggers ||= TriggersProxy.new(
triggers: source[:triggers].presence || {},
methods: methods_source,
connection: connection,
- object_definitions: object_definitions,
- settings: settings
+ object_definitions: object_definitions
)
end
+ sig { returns(ObjectDefinitions) }
def object_definitions
+ @object_definitions = T.let(@object_definitions, T.nilable(ObjectDefinitions))
@object_definitions ||= ObjectDefinitions.new(
object_definitions: source[:object_definitions].presence || {},
methods: methods_source,
- connection: connection,
- settings: settings
+ connection: connection
)
end
+ sig { returns(PickListsProxy) }
def pick_lists
+ @pick_lists = T.let(@pick_lists, T.nilable(PickListsProxy))
@pick_lists ||= PickListsProxy.new(
pick_lists: source[:pick_lists].presence || {},
methods: methods_source,
- connection: connection,
- settings: settings
+ connection: connection
)
end
+ sig { returns(Connection) }
def connection
+ @connection = T.let(@connection, T.nilable(Connection))
@connection ||= Connection.new(
methods: methods_source,
connection: connection_source,
settings: settings
)
end
private
- attr_reader :methods_source,
- :connection_source,
- :settings
+ sig { returns(HashWithIndifferentAccess) }
+ attr_reader :methods_source
+
+ sig { returns(HashWithIndifferentAccess) }
+ attr_reader :connection_source
+
+ sig { returns(SorbetTypes::SettingsHash) }
+ attr_reader :settings
end
class ActionsProxy
- def initialize(actions:, object_definitions:, methods:, connection:, settings:)
+ extend T::Sig
+
+ sig do
+ params(
+ actions: HashWithIndifferentAccess,
+ object_definitions: ObjectDefinitions,
+ methods: HashWithIndifferentAccess,
+ connection: Connection
+ ).void
+ end
+ def initialize(actions:, object_definitions:, methods:, connection:)
@methods = methods
@connection = connection
@object_definitions = object_definitions
- @settings = settings
+ @actions = T.let({}, T::Hash[T.any(Symbol, String), Action])
define_action_methods(actions)
end
+ sig { params(action: T.any(Symbol, String)).returns(T.untyped) }
def [](action)
public_send(action)
end
private
- attr_reader :methods,
- :connection,
- :object_definitions,
- :settings
+ sig { returns(HashWithIndifferentAccess) }
+ attr_reader :methods
- def define_action_methods(actions)
- actions.each do |action, definition|
+ sig { returns(Connection) }
+ attr_reader :connection
+
+ sig { returns(ObjectDefinitions) }
+ attr_reader :object_definitions
+
+ sig { params(actions_source: HashWithIndifferentAccess).void }
+ def define_action_methods(actions_source)
+ actions_source.each do |action, definition|
define_singleton_method(action) do |input_ = nil|
- @actions ||= {}
@actions[action] ||= Action.new(
action: definition,
object_definitions: object_definitions,
methods: methods,
- connection: connection,
- settings: settings
+ connection: connection
)
return @actions[action] if input_.nil?
- @actions[action].invoke(input_)
+ T.must(@actions[action]).invoke(input_)
end
end
end
end
class MethodsProxy
- def initialize(methods:, connection:, settings:)
+ extend T::Sig
+
+ sig do
+ params(
+ methods: HashWithIndifferentAccess,
+ connection: Connection
+ ).void
+ end
+ def initialize(methods:, connection:)
@methods = methods
@connection = connection
- @settings = settings
+ @actions = T.let({}, T::Hash[T.any(Symbol, String), Action])
define_action_methods
end
private
- attr_reader :methods,
- :connection,
- :settings
+ sig { returns(HashWithIndifferentAccess) }
+ attr_reader :methods
+ sig { returns(Connection) }
+ attr_reader :connection
+
+ sig { void }
def define_action_methods
methods.each do |method, _definition|
define_singleton_method(method) do |*args|
- @actions ||= {}
@actions[method] ||= Action.new(
action: {
- execute: -> { call(method, *args) }
+ execute: -> { T.unsafe(self).call(method, *args) }
},
methods: methods,
- connection: connection,
- settings: settings
+ connection: connection
)
- @actions[method].execute
+ T.must(@actions[method]).execute
end
end
end
end
class PickListsProxy
- def initialize(pick_lists:, methods:, connection:, settings:)
+ extend T::Sig
+
+ sig do
+ params(
+ pick_lists: HashWithIndifferentAccess,
+ methods: HashWithIndifferentAccess,
+ connection: Connection
+ ).void
+ end
+ def initialize(pick_lists:, methods:, connection:)
@methods = methods
@connection = connection
- @settings = settings
+ @actions = T.let({}, T::Hash[T.any(Symbol, String), Action])
define_action_methods(pick_lists)
end
private
- attr_reader :methods,
- :connection,
- :settings
+ sig { returns(HashWithIndifferentAccess) }
+ attr_reader :methods
- def define_action_methods(pick_lists)
- pick_lists.each do |pick_list, pick_list_proc|
+ sig { returns(Connection) }
+ attr_reader :connection
+
+ sig { params(pick_lists_source: HashWithIndifferentAccess).void }
+ def define_action_methods(pick_lists_source)
+ pick_lists_source.each do |pick_list, pick_list_proc|
define_singleton_method(pick_list) do |settings = nil, args = {}|
- @actions ||= {}
@actions[pick_list] ||= Action.new(
action: {
execute: lambda do |connection, input|
case pick_list_proc.parameters.length
when 0
@@ -194,52 +258,123 @@
instance_exec(connection, **input.symbolize_keys, &pick_list_proc)
end
end
},
methods: methods,
- connection: connection,
- settings: send(:settings)
+ connection: connection
)
- @actions[pick_list].execute(settings, args)
+ T.must(@actions[pick_list]).execute(settings, args)
end
end
end
end
class TriggersProxy
- def initialize(triggers:, object_definitions:, methods:, connection:, settings:)
+ extend T::Sig
+
+ sig do
+ params(
+ triggers: HashWithIndifferentAccess,
+ object_definitions: ObjectDefinitions,
+ methods: HashWithIndifferentAccess,
+ connection: Connection
+ ).void
+ end
+ def initialize(triggers:, object_definitions:, methods:, connection:)
@methods = methods
@connection = connection
@object_definitions = object_definitions
- @settings = settings
- @triggers = {}
+ @triggers = T.let({}, T::Hash[T.any(Symbol, String), Trigger])
define_trigger_methods(triggers)
end
private
- attr_reader :methods,
- :connection,
- :object_definitions,
- :settings
+ sig { returns(HashWithIndifferentAccess) }
+ attr_reader :methods
- def define_trigger_methods(triggers)
- triggers.each do |trigger, definition|
+ sig { returns(Connection) }
+ attr_reader :connection
+
+ sig { returns(ObjectDefinitions) }
+ attr_reader :object_definitions
+
+ sig { params(triggers_source: HashWithIndifferentAccess).void }
+ def define_trigger_methods(triggers_source)
+ triggers_source.each do |trigger, definition|
define_singleton_method(trigger) do |input_ = nil, payload = {}, headers = {}, params = {}|
@triggers[trigger] ||= Trigger.new(
trigger: definition,
object_definitions: object_definitions,
methods: methods,
- connection: connection,
- settings: settings
+ connection: connection
)
return @triggers[trigger] if input_.nil?
- @triggers[trigger].invoke(input_, payload, headers, params)
+ T.must(@triggers[trigger]).invoke(input_, payload, headers, params)
end
end
end
end
+
+ class InvokePath
+ extend T::Sig
+
+ sig do
+ params(
+ path: String,
+ connector: Connector,
+ params: T::Hash[Symbol, T.untyped]
+ ).void
+ end
+ def initialize(path:, connector:, params:)
+ @path = T.let(path, String)
+ @connector = T.let(connector, Connector)
+ @params = T.let(params, T::Hash[Symbol, T.untyped])
+ end
+
+ sig { returns(T.untyped) }
+ def call
+ invoke_path
+ end
+
+ private
+
+ sig { returns(String) }
+ attr_reader :path
+
+ sig { returns(Connector) }
+ attr_reader :connector
+
+ sig { returns(T::Hash[Symbol, T.untyped]) }
+ attr_reader :params
+
+ sig { returns(T.untyped) }
+ def invoke_path
+ methods = path.split('.')
+ method = methods.pop
+ raise ArgumentError, 'path is not found' unless method
+
+ object = methods.inject(connector) { |obj, m| obj.public_send(m) }
+ output = invoke_method(object, method)
+ if output.respond_to?(:invoke)
+ invoke_method(output, :invoke)
+ else
+ output
+ end
+ end
+
+ sig { params(object: T.untyped, method: T.any(Symbol, String)).returns(T.untyped) }
+ def invoke_method(object, method)
+ parameters = object.method(method).parameters.reject { |p| p[0] == :block }.map(&:second)
+ args = params.values_at(*parameters)
+ if parameters.last == :args
+ args = args.take(args.length - 1) + Array.wrap(args.last).flatten(1)
+ end
+ object.public_send(method, *args)
+ end
+ end
+ private_constant :InvokePath
end
end
end