brancusi 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +13 -0
- data/lib/assets/javascripts/brancusi/application/application.js.coffee +114 -0
- data/lib/assets/javascripts/brancusi/application/application_controller.js.coffee +17 -0
- data/lib/assets/javascripts/brancusi/application/application_module.js.coffee +29 -0
- data/lib/assets/javascripts/brancusi/application/bootstrapper.js.coffee +18 -0
- data/lib/assets/javascripts/brancusi/application/index.js.coffee +1 -0
- data/lib/assets/javascripts/brancusi/application/sandbox.js.coffee +14 -0
- data/lib/assets/javascripts/brancusi/container/container.js.coffee +139 -0
- data/lib/assets/javascripts/brancusi/container/dependent_module.js.coffee +30 -0
- data/lib/assets/javascripts/brancusi/container/dependent_object.js.coffee +9 -0
- data/lib/assets/javascripts/brancusi/container/index.js.coffee +1 -0
- data/lib/assets/javascripts/brancusi/events/event_object.js.coffee +10 -0
- data/lib/assets/javascripts/brancusi/events/events_module.js.coffee +14 -0
- data/lib/assets/javascripts/brancusi/events/index.js.coffee +1 -0
- data/lib/assets/javascripts/brancusi/events/mediator.js.coffee +70 -0
- data/lib/assets/javascripts/brancusi/index.js.coffee +2 -0
- data/lib/assets/javascripts/brancusi/namespace.js.coffee +13 -0
- data/lib/assets/javascripts/brancusi/object_model/base_object.js.coffee +27 -0
- data/lib/assets/javascripts/brancusi/object_model/decorate.js.coffee +14 -0
- data/lib/assets/javascripts/brancusi/object_model/extend.js.coffee +10 -0
- data/lib/assets/javascripts/brancusi/object_model/include.js.coffee +13 -0
- data/lib/assets/javascripts/brancusi/object_model/index.js.coffee +1 -0
- data/lib/assets/javascripts/brancusi/renderer/index.js.coffee +1 -0
- data/lib/assets/javascripts/brancusi/renderer/region_manager.js.coffee +30 -0
- data/lib/assets/javascripts/brancusi/renderer/renderer.js.coffee +41 -0
- data/lib/assets/javascripts/brancusi/renderer/template_manager.js.coffee +0 -0
- data/lib/assets/javascripts/brancusi/routes/dispatcher.js.coffee +10 -0
- data/lib/assets/javascripts/brancusi/routes/index.js.coffee +1 -0
- data/lib/assets/javascripts/brancusi/routes/mapper.js.coffee +41 -0
- data/lib/assets/javascripts/brancusi/routes/router.js.coffee +15 -0
- data/lib/assets/javascripts/brancusi/support/davis_router.js.coffee +19 -0
- data/lib/assets/javascripts/brancusi/support/knockout_renderer.js.coffee +12 -0
- data/lib/assets/javascripts/davis.js +1838 -0
- data/lib/assets/javascripts/knockout.js +3583 -0
- data/lib/assets/javascripts/underscore.js +1221 -0
- data/lib/assets/javascripts/underscore.string.js +600 -0
- data/lib/brancusi.rb +4 -0
- data/lib/brancusi/engine.rb +4 -0
- data/lib/brancusi/version.rb +3 -0
- metadata +282 -0
data/Rakefile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
|
3
|
+
require 'guard/jasmine/task'
|
4
|
+
|
5
|
+
Guard::JasmineTask.new('jasmine:specs') do |task|
|
6
|
+
task.options = "-s thin -p 3001"
|
7
|
+
end
|
8
|
+
|
9
|
+
Guard::JasmineTask.new('jasmine:stories') do |task|
|
10
|
+
task.options = "-s thin -p 3001 -u http://localhost:3001/jasmine-stories"
|
11
|
+
end
|
12
|
+
|
13
|
+
task 'jasmine:all' => ['guard:jasmine:specs', 'guard:jasmine:stories']
|
@@ -0,0 +1,114 @@
|
|
1
|
+
#= require brancusi/events
|
2
|
+
#= require brancusi/routes/mapper
|
3
|
+
|
4
|
+
namespace "brancusi"
|
5
|
+
|
6
|
+
class brancusi.Application extends brancusi.EventObject
|
7
|
+
|
8
|
+
@dependency mediator: "Mediator"
|
9
|
+
|
10
|
+
# Default configuration options, which may be overridden by instances
|
11
|
+
@config:
|
12
|
+
bootstrapper: brancusi.Bootstrapper
|
13
|
+
|
14
|
+
# Module classes for the application
|
15
|
+
@Modules: {}
|
16
|
+
|
17
|
+
# Module instances
|
18
|
+
modules: {}
|
19
|
+
|
20
|
+
# Controller classes for the application
|
21
|
+
@Controllers: {}
|
22
|
+
|
23
|
+
# Controller instances
|
24
|
+
controllers: {}
|
25
|
+
|
26
|
+
# Model classes for the application
|
27
|
+
@Models: {}
|
28
|
+
|
29
|
+
@routes: new brancusi.routes.Mapper
|
30
|
+
|
31
|
+
# Instantiates the application and bootstrapper, and resolves any dependencies, modules and controllers.
|
32
|
+
#
|
33
|
+
# @return [Application] an instance of the application.
|
34
|
+
#
|
35
|
+
@create: ->
|
36
|
+
@instance = new @
|
37
|
+
bootstrapper = new @Bootstrapper
|
38
|
+
@instance.resolve(bootstrapper)
|
39
|
+
|
40
|
+
# Resolves, initializes, and runs the application.
|
41
|
+
#
|
42
|
+
# @return [Application] an instance of the application.
|
43
|
+
#
|
44
|
+
@run: ->
|
45
|
+
@create().initialize().run()
|
46
|
+
|
47
|
+
# Creates and assigns the application container with the bootstrapper, then resolves dependencies, modules and controllers.
|
48
|
+
#
|
49
|
+
# @return [Application] the application instance.
|
50
|
+
#
|
51
|
+
resolve: (bootstrapper) ->
|
52
|
+
@container = bootstrapper.configure_container(@)
|
53
|
+
@container.resolve(@)
|
54
|
+
@_resolve_modules()
|
55
|
+
@_resolve_controllers()
|
56
|
+
@
|
57
|
+
|
58
|
+
# Binds event handlers on the modules and controllers, then publishes the application.initialize event.
|
59
|
+
#
|
60
|
+
# @return [Application] the application instance.
|
61
|
+
#
|
62
|
+
initialize: ->
|
63
|
+
@_bind_events()
|
64
|
+
@mediator.publish "application.initialize", @
|
65
|
+
@
|
66
|
+
|
67
|
+
# Publishes the application.ready event.
|
68
|
+
#
|
69
|
+
# @return [Application] the application instance.
|
70
|
+
#
|
71
|
+
run: (bootstrapper) ->
|
72
|
+
@mediator.publish "application.ready"
|
73
|
+
@
|
74
|
+
|
75
|
+
# @private
|
76
|
+
# Instantiates and resolves the application modules.
|
77
|
+
#
|
78
|
+
_resolve_modules: ->
|
79
|
+
# @modules.router = @router if @router?
|
80
|
+
# @modules.renderer = @renderer if @renderer?
|
81
|
+
module_regex = /(.*)Module/ # e.g. AuthModule
|
82
|
+
for klass_name, klass of @constructor.Modules when matches = module_regex.exec(klass_name)
|
83
|
+
module_name = _.string.underscored(matches[1]) # e.g. "auth"
|
84
|
+
module = @container.resolve(new klass(module_name))
|
85
|
+
# module.sandbox.bind_subscriptions(module)
|
86
|
+
@modules[module_name] = module
|
87
|
+
|
88
|
+
# @private
|
89
|
+
# Instantiates and resolves the application controllers.
|
90
|
+
#
|
91
|
+
_resolve_controllers: ->
|
92
|
+
controller_regex = /(.*)Controller/ # e.g. HomeController
|
93
|
+
for klass_name, klass of @constructor.Controllers when matches = controller_regex.exec(klass_name)
|
94
|
+
controller_name = _.string.underscored(matches[1]) # e.g. home
|
95
|
+
controller = @container.resolve(new klass(controller_name))
|
96
|
+
# controller.sandbox.bind_subscriptions(controller)
|
97
|
+
@controllers[controller_name] = controller
|
98
|
+
|
99
|
+
# @private
|
100
|
+
# Binds event handlers on the modules and controllers.
|
101
|
+
#
|
102
|
+
_bind_events: ->
|
103
|
+
@router.sandbox.bind_subscriptions(@router)
|
104
|
+
@renderer.sandbox.bind_subscriptions(@renderer)
|
105
|
+
|
106
|
+
for module_name, module of @modules
|
107
|
+
module.sandbox.bind_subscriptions(module)
|
108
|
+
|
109
|
+
for controller_name, controller of @controllers
|
110
|
+
controller.sandbox.bind_subscriptions(controller)
|
111
|
+
|
112
|
+
# route_mapper = new @container.resolve 'RouteMapper'
|
113
|
+
# route_mapper.draw(@constructor.routes.( config?.routes || -> )
|
114
|
+
# @router?.initialize?()
|
@@ -0,0 +1,17 @@
|
|
1
|
+
#= require ./application_module
|
2
|
+
|
3
|
+
namespace "brancusi"
|
4
|
+
|
5
|
+
class brancusi.ApplicationController extends brancusi.ApplicationModule
|
6
|
+
@dependency renderer: 'Renderer'
|
7
|
+
|
8
|
+
begin_request: (action_name) ->
|
9
|
+
@request =
|
10
|
+
action: action_name
|
11
|
+
|
12
|
+
render: (args...) ->
|
13
|
+
if args.length > 0
|
14
|
+
@renderer.render_page(args...)
|
15
|
+
else
|
16
|
+
@renderer.render_page("#{@name}/#{@request.action}")
|
17
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
#= require brancusi/events
|
2
|
+
|
3
|
+
namespace "brancusi"
|
4
|
+
|
5
|
+
class brancusi.ApplicationModule extends brancusi.EventObject
|
6
|
+
constructor: (@name) ->
|
7
|
+
|
8
|
+
@dependency sandbox: (container) ->
|
9
|
+
container.resolve "Sandbox", [@name]
|
10
|
+
|
11
|
+
@dependency container: (container) ->
|
12
|
+
container.child().register_instance "Sandbox", @sandbox
|
13
|
+
|
14
|
+
publish: (args...) ->
|
15
|
+
@sandbox.publish(args...)
|
16
|
+
|
17
|
+
# TODO: maybe bind subscriptions automatically after resolving any EventObject (or anything with subscriptions)
|
18
|
+
# e.g.
|
19
|
+
# resolve: (ref, opts) ->
|
20
|
+
# resolution = @container.resolve(ref, opts)
|
21
|
+
# @sandbox.bind_scriptions(resolution)
|
22
|
+
# resolution.publish = @sandbox.publish
|
23
|
+
# resolution
|
24
|
+
# bind_subscriptions: (target) ->
|
25
|
+
# @sandbox.bind_subscriptions.apply( @sandbox, [target] )
|
26
|
+
# target.publish = @sandbox.publish
|
27
|
+
|
28
|
+
# create_model: ( class_name, opts ) ->
|
29
|
+
# @env.create( class_name, opts )
|
@@ -0,0 +1,18 @@
|
|
1
|
+
#= require brancusi/container
|
2
|
+
|
3
|
+
namespace "brancusi"
|
4
|
+
|
5
|
+
class brancusi.Bootstrapper
|
6
|
+
|
7
|
+
configure_container: ( application ) ->
|
8
|
+
container = new brancusi.Container()
|
9
|
+
|
10
|
+
# TODO: do we need these?
|
11
|
+
container.register_instance "Application", application
|
12
|
+
container.register_instance "Container", container
|
13
|
+
|
14
|
+
container.register_class "Sandbox", brancusi.Sandbox
|
15
|
+
container.register_class "Mediator", brancusi.Mediator, singleton: true
|
16
|
+
container.register_class "RegionManager", brancusi.renderer.RegionManager, singleton: true
|
17
|
+
|
18
|
+
container
|
@@ -0,0 +1 @@
|
|
1
|
+
#= require_tree .
|
@@ -0,0 +1,14 @@
|
|
1
|
+
#= require brancusi/container
|
2
|
+
|
3
|
+
namespace "brancusi"
|
4
|
+
|
5
|
+
class brancusi.Sandbox extends brancusi.DependentObject
|
6
|
+
@dependency mediator: "Mediator"
|
7
|
+
|
8
|
+
constructor: (@scope) ->
|
9
|
+
|
10
|
+
publish: (event, args...) =>
|
11
|
+
@mediator.publish_scoped(event, @scope, args...)
|
12
|
+
|
13
|
+
bind_subscriptions: (target) =>
|
14
|
+
@mediator.bind_subscriptions(target, @scope)
|
@@ -0,0 +1,139 @@
|
|
1
|
+
namespace "brancusi"
|
2
|
+
|
3
|
+
# Implementation of a DI container.
|
4
|
+
#
|
5
|
+
class brancusi.Container
|
6
|
+
|
7
|
+
# Creates an instance of a container.
|
8
|
+
#
|
9
|
+
# @param parent [brancusi.Container] a parent container. When provided, if resolution of a dependency fails then resolution will be attempted with the parent container instead.
|
10
|
+
#
|
11
|
+
constructor: (@parent) ->
|
12
|
+
@_mappings = {}
|
13
|
+
|
14
|
+
# Registers a class mapping with the container.
|
15
|
+
#
|
16
|
+
# @param name [String] the name of the mapping to the class.
|
17
|
+
# @param klass [Class] the class the dependency should resolve with.
|
18
|
+
# @option opts [Boolean] singleton indicates whether the resolved dependency should be memoized.
|
19
|
+
# @return [Container] the container.
|
20
|
+
#
|
21
|
+
register_class: (name, klass, opts = {}) ->
|
22
|
+
@_register_mapping name, klass, "class", opts
|
23
|
+
@
|
24
|
+
|
25
|
+
|
26
|
+
# Registers an instance mapping with the container.
|
27
|
+
#
|
28
|
+
# @param name [String] the name of the mapping to the instance.
|
29
|
+
# @param obj [Object] the instance the dependency should resolve to.
|
30
|
+
# @return [Container] the container.
|
31
|
+
#
|
32
|
+
register_instance: (name, obj) ->
|
33
|
+
@_register_mapping name, obj, "instance"
|
34
|
+
@
|
35
|
+
|
36
|
+
|
37
|
+
# Registers a factory function for resolving dependencies
|
38
|
+
#
|
39
|
+
# @param name [String] the name of the mapping
|
40
|
+
# @param fn [Function] the factory function to resolve the mapping
|
41
|
+
# @return [Container] the container
|
42
|
+
#
|
43
|
+
register_factory: (name, fn) ->
|
44
|
+
@_register_mapping name, fn, "factory"
|
45
|
+
@
|
46
|
+
|
47
|
+
|
48
|
+
# Returns an instance of the given dependency, resolving any child dependencies.
|
49
|
+
#
|
50
|
+
# @overload resolve(name)
|
51
|
+
# Resolves the dependency according to the name of the mapping.
|
52
|
+
# @param name [String] the name of the dependency mapping.
|
53
|
+
# @return [Object] the fully resolved dependency.
|
54
|
+
#
|
55
|
+
# @overload resolve(target, opts)
|
56
|
+
# Resolves any unresolved dependencies on a given object.
|
57
|
+
# @param target [Object] the object to resolve dependencies for.
|
58
|
+
# @return [Object] target.
|
59
|
+
#
|
60
|
+
resolve: (ref, opts) ->
|
61
|
+
if typeof ref == "string"
|
62
|
+
resolution = @_resolve_string(ref, opts)
|
63
|
+
else if typeof ref == "function"
|
64
|
+
resolution = @_resolve_function(ref, opts)
|
65
|
+
else if typeof ref == "object"
|
66
|
+
resolution = @_resolve_object(ref)
|
67
|
+
|
68
|
+
if resolution?
|
69
|
+
resolution
|
70
|
+
else if @parent?
|
71
|
+
@parent.resolve ref, opts unless resolution?
|
72
|
+
else
|
73
|
+
throw new Error("Unable to resolve dependency: #{ref}") unless resolution?
|
74
|
+
|
75
|
+
|
76
|
+
# Creates a child container.
|
77
|
+
# @return [Container] a new child container.
|
78
|
+
#
|
79
|
+
child: ->
|
80
|
+
new Container(@)
|
81
|
+
|
82
|
+
|
83
|
+
# Helper method to set up a mapping. Merges in the given options to the definition.
|
84
|
+
#
|
85
|
+
# @private
|
86
|
+
# @param name [String] the name of the mapping
|
87
|
+
# @param [Class|Object|Function] the dependency to map too
|
88
|
+
# @param [String] the kind of mapping. Either 'class', 'object' or 'factory'
|
89
|
+
#
|
90
|
+
_register_mapping: (name, ref, kind, opts = {}) ->
|
91
|
+
@_mappings[name] = _.defaults({ kind: kind, ref: ref }, opts)
|
92
|
+
|
93
|
+
|
94
|
+
# Resolves a dependency by name, passing the given options (if provided) to the dependency when initialized.
|
95
|
+
#
|
96
|
+
# @private
|
97
|
+
# @param name [String] the name of the dependency.
|
98
|
+
# @param opts [Array] optional array of arguments to pass to the dependency
|
99
|
+
#
|
100
|
+
_resolve_string: (name, opts) ->
|
101
|
+
mapping = @_mappings[name]
|
102
|
+
return null unless mapping?
|
103
|
+
|
104
|
+
if mapping.kind == "instance"
|
105
|
+
mapping.ref
|
106
|
+
else if mapping.kind == "class" and mapping.singleton == true
|
107
|
+
mapping.instance = @resolve( mapping.ref, opts ) unless mapping.instance?
|
108
|
+
mapping.instance
|
109
|
+
else if mapping.kind == "factory"
|
110
|
+
mapping.ref.apply(null, opts)
|
111
|
+
else
|
112
|
+
@resolve(mapping.ref, opts)
|
113
|
+
|
114
|
+
|
115
|
+
# Resolves a dependency specified by a function.
|
116
|
+
#
|
117
|
+
# @private
|
118
|
+
# @param fn [Function] the function to invoke
|
119
|
+
# @param opts [Array] an optional array of arguments to pass to the function
|
120
|
+
#
|
121
|
+
_resolve_function: (fn, opts) ->
|
122
|
+
opts ?= []
|
123
|
+
obj = new fn(opts...)
|
124
|
+
@resolve obj
|
125
|
+
|
126
|
+
|
127
|
+
# Resolves dependencies on the given object.
|
128
|
+
#
|
129
|
+
# @private
|
130
|
+
# @param target [Object] the target object.
|
131
|
+
#
|
132
|
+
_resolve_object: (target) ->
|
133
|
+
for name, args of target.constructor.dependencies
|
134
|
+
[dependency, dependency_args] = args
|
135
|
+
if typeof dependency == "function"
|
136
|
+
target[name] = dependency.apply(target, [@])
|
137
|
+
else
|
138
|
+
target[name] = @resolve dependency, dependency_args
|
139
|
+
target
|
@@ -0,0 +1,30 @@
|
|
1
|
+
namespace "brancusi"
|
2
|
+
|
3
|
+
# A module to facilitate the specification of dependencies. Dependencies are defined on the
|
4
|
+
# 'dependencies' property of the target's prototype, in the format:
|
5
|
+
#
|
6
|
+
# {attr1: ['dep1', [<args1>]], attr2: ['dep2', [<args2>]]}
|
7
|
+
#
|
8
|
+
# @mixin
|
9
|
+
#
|
10
|
+
class brancusi.DependentModule
|
11
|
+
|
12
|
+
# Adds the named dependencies to the object's ::dependencies property
|
13
|
+
#
|
14
|
+
# @overload dependency(dependency, args...)
|
15
|
+
# Defines the given dependency on the subject class
|
16
|
+
# @param dependency [Object] an object with a single field in the format {<attribute>: '<dependency name>'}
|
17
|
+
# @param args [Array] optional an array of arguments to store with the dependency, to be passed as arguments on resolution
|
18
|
+
#
|
19
|
+
# @overload dependency(dependencies)
|
20
|
+
# Defines the given dependencies on the subject class
|
21
|
+
# @param dependencies [Object] an object naming a number of dependencies
|
22
|
+
#
|
23
|
+
@dependency: (dependencies, args...) ->
|
24
|
+
@dependencies ?= {}
|
25
|
+
|
26
|
+
if @__super__? and @__super__.constructor.dependencies == @dependencies
|
27
|
+
@dependencies = _.clone(@__super__.constructor.dependencies)
|
28
|
+
|
29
|
+
for dependency_name, dependency_type of dependencies
|
30
|
+
@dependencies[dependency_name] = [dependency_type, args]
|
@@ -0,0 +1 @@
|
|
1
|
+
#= require_tree .
|
@@ -0,0 +1,14 @@
|
|
1
|
+
namespace "brancusi"
|
2
|
+
|
3
|
+
# Provides convenience methods @on and publish for subscribing and publishing to application events with AER.
|
4
|
+
#
|
5
|
+
class brancusi.EventsModule
|
6
|
+
|
7
|
+
# Generates a named event handler for AER.
|
8
|
+
#
|
9
|
+
# @param event [String] the name of the event.
|
10
|
+
# @param handler [Function] the event handler.
|
11
|
+
#
|
12
|
+
@on: (event, handler) ->
|
13
|
+
@::["@#{event}"] = handler
|
14
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
#= require_tree .
|
@@ -0,0 +1,70 @@
|
|
1
|
+
namespace "brancusi"
|
2
|
+
|
3
|
+
# An implementation of the mediator pattern. This class should not be referred to directly, as the AER pattern is preferred.
|
4
|
+
#
|
5
|
+
class brancusi.Mediator
|
6
|
+
|
7
|
+
constructor: ->
|
8
|
+
@subscribers = {}
|
9
|
+
|
10
|
+
# Subscribes the given handler to the content for the specified event.
|
11
|
+
#
|
12
|
+
# @param event [String] the (fully qualified) name of the event.
|
13
|
+
# @param handler [Function] the event handler.
|
14
|
+
# @param context [Object] optional the context to invoke the handler against
|
15
|
+
#
|
16
|
+
subscribe: (event, handler, context) ->
|
17
|
+
@subscribers[event] ?= []
|
18
|
+
@subscribers[event].push(-> handler.apply(context, arguments))
|
19
|
+
|
20
|
+
# Invokes all handlers for the given event.
|
21
|
+
#
|
22
|
+
# @param event [String] the (fully qualified) name of the event.
|
23
|
+
# @param args... the arguments to forward to the handler.
|
24
|
+
#
|
25
|
+
publish: (event, args...) ->
|
26
|
+
@publish_scoped(event, null, args...)
|
27
|
+
|
28
|
+
# Invokes all handlers for the given event.
|
29
|
+
#
|
30
|
+
# @param event [String] the name of the event (either qualified or unqualified)
|
31
|
+
# @param scope [String] the name of the scope for unqualified event names.
|
32
|
+
# @param args... the arguments to forward to the handler.
|
33
|
+
#
|
34
|
+
publish_scoped: (event, scope, args...) ->
|
35
|
+
event = @_scoped_name(event, scope, true) if scope?
|
36
|
+
subscribers = (@subscribers?[event] || {})
|
37
|
+
for handler in subscribers
|
38
|
+
handler(args...)
|
39
|
+
|
40
|
+
# Binds all subscriptions on the target object (optionally using the given scope).
|
41
|
+
#
|
42
|
+
# @param target [Object] the target object.
|
43
|
+
# @param scope [String] optional the name of the scope of the object.
|
44
|
+
#
|
45
|
+
bind_subscriptions: (target, scope) ->
|
46
|
+
for name, handler of target when matches = /@(.*)/.exec(name)
|
47
|
+
event = matches[1]
|
48
|
+
event = @_scoped_name(event, scope) if scope?
|
49
|
+
@subscribe(event, handler, target)
|
50
|
+
|
51
|
+
# @private
|
52
|
+
# Returns the fully qualified name of the event, and optionally validates the inpute.
|
53
|
+
#
|
54
|
+
# @param input [String] the input to qualify (and maybe validate).
|
55
|
+
# @param scope [String] optional the name of the scope for unqualified event names.
|
56
|
+
# @param validate [Boolean] optional whether or not to error on invalid event names.
|
57
|
+
#
|
58
|
+
_scoped_name: (input, scope, validate) =>
|
59
|
+
regex = /^((\w+)\.)?(\w+)$/
|
60
|
+
|
61
|
+
if input.match(regex)
|
62
|
+
[_, _, event_scope, event] = regex.exec(input)
|
63
|
+
if scope?
|
64
|
+
event_scope ?= scope
|
65
|
+
"#{event_scope}.#{event}"
|
66
|
+
else
|
67
|
+
event
|
68
|
+
else if validate?
|
69
|
+
throw new Error("Invalid event name: #{input}")
|
70
|
+
|