flok 0.0.100 → 0.0.101

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/app/drivers/chrome/README.md +6 -0
  3. data/app/drivers/chrome/Rakefile +1 -0
  4. data/app/drivers/chrome/build_context.rb +1 -0
  5. data/app/drivers/chrome/config.yml +4 -0
  6. data/app/drivers/chrome/spec/spec/dlink_spec.js +15 -0
  7. data/app/drivers/chrome/spec/spec/hook_spec.js +24 -0
  8. data/app/drivers/chrome/src/dlink.js +28 -0
  9. data/app/drivers/chrome/src/hook.js +29 -0
  10. data/app/kern/mod/dlink.js +16 -0
  11. data/app/kern/mod/event.js +7 -0
  12. data/app/kern/mod/hook.js +1 -0
  13. data/app/kern/services/dlink.rb +25 -0
  14. data/bin/flok +12 -3
  15. data/docs/compilation.md +1 -1
  16. data/docs/kernel_api.md +1 -1
  17. data/docs/kernel_handbook/hooks.md +4 -0
  18. data/docs/mod/dlink.md +18 -0
  19. data/docs/mod/hook.md +9 -0
  20. data/docs/project.md +3 -2
  21. data/docs/services/dlink.md +8 -0
  22. data/docs/user_handbook/hooks.md +106 -0
  23. data/lib/flok.rb +1 -0
  24. data/lib/flok/hooks_compiler.rb +174 -0
  25. data/lib/flok/project_template/config/hooks.rb +1 -0
  26. data/lib/flok/user_compiler.rb +56 -6
  27. data/lib/flok/user_compiler_templates/ctable.js.erb +4 -0
  28. data/lib/flok/user_hook_generators/goto.rb +74 -0
  29. data/lib/flok/user_hook_generators/helpers.rb +46 -0
  30. data/lib/flok/version.rb +1 -1
  31. data/spec/env/kern.rb +32 -16
  32. data/spec/etc/transition_complier_spec.rb +4 -0
  33. data/spec/iface/driver/hook_spec.rb +33 -0
  34. data/spec/iface/kern/dlink_spec.rb +25 -0
  35. data/spec/kern/assets/dlink_service/config0.rb +2 -0
  36. data/spec/kern/assets/dlink_service/controller0.rb +16 -0
  37. data/spec/kern/assets/hook_entry_points/controller0.rb +58 -0
  38. data/spec/kern/assets/hook_entry_points/controller0a.rb +27 -0
  39. data/spec/kern/dlink_service_spec.rb +50 -0
  40. data/spec/kern/hook_entry_points_and_manifest_spec.rb +155 -0
  41. data/spec/kern/hook_user_generators_spec.rb +139 -0
  42. metadata +36 -3
  43. data/docs/mod/intercept.md +0 -26
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 114477d327897a115f580aa076cb7190f54e5640
4
- data.tar.gz: aa8d1cd9e4b91c02c9e53a7e111ff4d12bd08a63
3
+ metadata.gz: 1d6171c859ceb0102173aab274f388008d70a31a
4
+ data.tar.gz: a8a1e2a1039caa0157507720ca5991413404d43b
5
5
  SHA512:
6
- metadata.gz: 7279341e6bd55b6629e228b17c079f012136dac5fe70746d8162fc959d178dca173ab15908030e3302f1e0ee28156f0397095cc883c9b518f70ddc0570799d56
7
- data.tar.gz: 12d5b4834e74ccc6b9d6a6e277641703f1b2bcdebaf71b30961101b3d6b64ae684a11d65cd538b906d7e5149b9e22d22071a0884d16c0d73dc4151749f3a432b
6
+ metadata.gz: 9f90608d9d9272f1ab7bd6d2fc1731d6d812c5ac68fb359f8dcc4cf8d0e58ca1fb08f8d96ad5f91744b253b33ac3005f219da27850c47bce6311aafe2942f049
7
+ data.tar.gz: 40ff86e7e1ca0ac862a981e6a11d01d139958dbb1702de083276736505c1b97462fcbd8f7e77928318af61ddd91921c9a29fc22b807096788bd25d6e7598b935
@@ -64,8 +64,13 @@ var TestController = function() {
64
64
  $(document).ready(function() {
65
65
  regController("__test__", TestController);
66
66
  });
67
+
67
68
  ```
68
69
 
70
+ ### Handling hook events
71
+ onHookEvent("test", function(params) {
72
+ });
73
+
69
74
  ### DOM helpers
70
75
  ```html
71
76
  <!-- This will place the contents of context.foo into the divider -->
@@ -80,6 +85,7 @@ $(document).ready(function() {
80
85
  ### ERB Compliation
81
86
  The final `chrome.js` file is run through an `ERB` compiler that contains the variables:
82
87
  * `@debug` - True if `FLOK_ENV=DEBUG`
88
+ * `@spec` - True if you are running the spec task in the Rakefile
83
89
  * `@release` - True if `FLOK_ENV=RELEASE`
84
90
  * `@mods` - A list of active kernel modules listed from `config.yml`
85
91
 
@@ -40,6 +40,7 @@ task :spec do
40
40
  #Build the driver
41
41
  ENV['BUILD_PATH'] = "../../../products/chrome/drivers/"
42
42
  ENV['FLOK_ENV'] = 'DEBUG'
43
+ ENV['FLOK_CHROME_SPEC'] = 'TRUE'
43
44
  system('rake build')
44
45
 
45
46
  recipe = Cakery.new("./cakery/spec.js.erb") do |f|
@@ -5,6 +5,7 @@ module Chrome
5
5
  def initialize
6
6
  @debug = (ENV['FLOK_ENV'] == "DEBUG")
7
7
  @release = (ENV['FLOK_ENV'] == "RELEASE")
8
+ @spec = (ENV['FLOK_CHROME_SPEC'] == "TRUE")
8
9
  Dir.chdir File.join(File.dirname(__FILE__), "../../../") do
9
10
  @mods = Flok::Platform.mods(ENV['FLOK_ENV'])
10
11
  end
@@ -11,6 +11,8 @@ DEBUG:
11
11
  - persist
12
12
  - timer
13
13
  - rtc
14
+ - hook
15
+ - dlink
14
16
  defines:
15
17
  - mem_pager
16
18
  - sockio_pager
@@ -25,6 +27,8 @@ RELEASE:
25
27
  - persist
26
28
  - timer
27
29
  - rtc
30
+ - hook
31
+ - dlink
28
32
  defines:
29
33
  - mem_pager
30
34
  - sockio_pager
@@ -0,0 +1,15 @@
1
+ //Tests whether dlink_init will transmit the correct information
2
+
3
+ QUnit.test("dlink_init does notify the dlink system with the proper address", function(assert) {
4
+ var done = assert.async();
5
+
6
+ //Hijack the int event function
7
+ window.int_dispatch = function(q) {
8
+ int_dispatch_res = q;
9
+ }
10
+
11
+ dlink_init();
12
+
13
+ assert.equal(JSON.stringify(int_dispatch_res), JSON.stringify([2, "int_dlink_notify", "http://test.com:80/test", {"foo": "bar"}]), "Matches");
14
+ done();
15
+ });
@@ -0,0 +1,24 @@
1
+ QUnit.test("When a hook_event is received, it is relayed to the appropriate function handler if available", function(assert) {
2
+ //Register a hook event handler
3
+ onHookEvent("test", function(params) {
4
+ test_hook_fired = true;
5
+ test_hook_params = params;
6
+ });
7
+
8
+ onHookEvent("hello", function(params) {
9
+ hello_hook_fired = true;
10
+ hello_hook_params = params;
11
+ });
12
+
13
+ //Test two seperate hook events
14
+ if_hook_event("test", {foo: "bar"});
15
+ if_hook_event("hello", {hello: "world"});
16
+
17
+ //Test an event that has no handler
18
+ if_hook_event("no_such_handler", {test: "test"});
19
+
20
+ assert.equal(test_hook_fired, true, "test hook was fired, got: ", test_hook_fired);
21
+ assert.equal(JSON.stringify(test_hook_params), JSON.stringify({foo: "bar"}), "test hook was fired with params {foo: bar}, got: ", JSON.stringify(test_hook_params));
22
+ assert.equal(hello_hook_fired, true, "hello hook was fired, got: ", hello_hook_fired);
23
+ assert.equal(JSON.stringify(hello_hook_params), JSON.stringify({hello: "world"}), "hello hook was fired with params {foo: bar}, got: ", JSON.stringify(hello_hook_params));
24
+ });
@@ -0,0 +1,28 @@
1
+
2
+ //When the page first loads, send the current URL
3
+ function dlink_init() {
4
+ //Get parameters
5
+ var params = {};
6
+ var parts = <%= @spec ? "dlink_spec_window" : "window" %>.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) {
7
+ params[key] = value;
8
+ });
9
+
10
+ //Get URL portion
11
+ var url = <%= @spec ? "dlink_spec_window" : "window" %>.location.protocol + '//' + <%= @spec ? "dlink_spec_window" : "window" %>.location.host + <%= @spec ? "dlink_spec_window" : "window" %>.location.pathname;
12
+
13
+ //Notify dlink
14
+ int_dispatch([2, "int_dlink_notify", url, params]);
15
+ }
16
+
17
+ //The window.location struct does not work in phantomJS so we mock it during debugs
18
+ <% if @spec %>
19
+ dlink_spec_window = {
20
+ location: {
21
+ protocol: "http:",
22
+ host: "test.com:80",
23
+ pathname: "/test",
24
+ href: "http://test.com:80/test?foo=bar"
25
+ }
26
+ };
27
+ <% end %>
28
+
@@ -0,0 +1,29 @@
1
+ //Driver side interface
2
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////////
3
+ function if_hook_event(name, info) {
4
+ <% if @debug %>
5
+ if_hook_spec_dump_rcvd_events_log.push({name: name, info: info});
6
+ <% end %>
7
+
8
+ //Call the appropriate registered handler
9
+ if (hookEventHandlers[name] !== undefined) {
10
+ hookEventHandlers[name](info);
11
+ }
12
+ }
13
+
14
+ <% if @debug %>
15
+ //Track all events sent to if_hook_event
16
+ var if_hook_spec_dump_rcvd_events_log = []
17
+ function if_hook_spec_dump_rcvd_events() {
18
+ int_dispatch([1, "if_hook_spec_dump_rcvd_events_res", if_hook_spec_dump_rcvd_events_log]);
19
+ }
20
+ <% end %>
21
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////////
22
+
23
+ //User helpers
24
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////////
25
+ var hookEventHandlers = {};
26
+ function onHookEvent(eventName, handler) {
27
+ hookEventHandlers[eventName] = handler;
28
+ }
29
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -0,0 +1,16 @@
1
+ function int_dlink_notify(url, params) {
2
+ <% if @debug %>
3
+ int_dlink_spec_last_request = [url, params];
4
+ <% end %>
5
+
6
+ //Currently sends off to the sister dlink-service by default
7
+ dlink_notify_handler(url, params);
8
+ }
9
+
10
+ //Spec tracks the last given notify request
11
+ <% if @debug %>
12
+ int_dlink_spec_last_request = null;
13
+ function get_int_dlink_spec() {
14
+ SEND("main", "get_int_dlink_spec", int_dlink_spec_last_request);
15
+ }
16
+ <% end %>
@@ -5,6 +5,10 @@ evt = {};
5
5
  edefer_q = [];
6
6
 
7
7
  function int_event(ep, event_name, info) {
8
+ <% if @debug %>
9
+ if (ep.constructor !== String && ep.constructor !== Number) { throw "int_event was given either something that wasn't a string or number for ep: '" + (ep.constructor) + "' and the value was: '" + ep + "'"};
10
+ <% end %>
11
+
8
12
  var f = evt[ep];
9
13
  if (f != undefined) {
10
14
  f(ep, event_name, info);
@@ -23,6 +27,9 @@ function dereg_evt(ep) {
23
27
  }
24
28
 
25
29
  function int_event_defer(ep, ename, info) {
30
+ <% if @debug %>
31
+ if (ep.constructor !== String && ep.constructor !== Number) { throw "int_event_defer was given either something that wasn't a string or number for ep: '" + (ep.constructor) + "' and the value was: '" + ep + "'"};
32
+ <% end %>
26
33
  edefer_q.push(ep);
27
34
  edefer_q.push(ename);
28
35
  edefer_q.push(info);
@@ -0,0 +1 @@
1
+ //Stub
@@ -0,0 +1,25 @@
1
+ service :dlink do
2
+ global %{
3
+ //Static from the dlink module itself, this is a sister service
4
+ function dlink_notify_handler(url, params) {
5
+ //Notify all view controllers
6
+ var cbps = Object.keys(dlink_sessions);
7
+ var einfo = {url: url, params: params};
8
+ for (var i = 0; i < cbps.length; ++i) {
9
+ int_event_defer(parseInt(cbps[i]), "dlink_req", einfo);
10
+ }
11
+ }
12
+ }
13
+
14
+ on_wakeup %{
15
+ }
16
+
17
+ on_sleep %{
18
+ }
19
+
20
+ on_connect %{
21
+ }
22
+
23
+ on_disconnect %{
24
+ }
25
+ end
data/bin/flok CHANGED
@@ -54,6 +54,9 @@ class FlokCLI < Thor
54
54
  #4. Move ./app/scripts/*.js into `./products/$PLATFORM/./glob/scripts.js`
55
55
  Flok.src_glob("js", './app/scripts', File.join(local_products_path, platform, "./glob/scripts.js"))
56
56
 
57
+ #Save the current local user's project directory to reference
58
+ user_project_dir = Dir.pwd
59
+
57
60
  #We are now inside the platform folder
58
61
  Dir.chdir File.join(local_products_path, platform) do
59
62
  #3. Put user_compiler_js in glob folder and services into ./services/user_services.rb
@@ -70,15 +73,21 @@ class FlokCLI < Thor
70
73
  FileUtils.cp "application.js", "glob/application.js"
71
74
  FileUtils.rm "application.js"
72
75
 
73
- #7. Combine application.js and user_compiler.js.erb and services.js and scripts.js
74
- File.open "glob/application_user.js.erb", "w" do |f|
76
+ #7. The local project `./products/$PLATFORM/glob/application.js` and `./products/$PLATFORM/glob/user_compiler.js` and `./products/$PLATFORM/glob/services.js` and `./products/$PLATFORM/glob/scripts.js` are merged into `./products/$PLATFORM/glob/application_user.js.erb.hooks`.
77
+ File.open "glob/application_user.js.erb.hooks", "w" do |f|
75
78
  f.puts File.read("glob/application.js")
76
79
  f.puts File.read("glob/user_compiler.js")
77
80
  f.puts File.read("glob/services.js")
78
81
  f.puts File.read("glob/scripts.js")
79
82
  end
80
83
 
81
- #8. The `erb` files is then sent to `./products/$PLATFORM/glob/application_user.js` with the below `ERB` variables allowable.
84
+ #9. The `hooks` compiler then runs over the source injecting any necessary hook code into the special comments by going through `./config/hooks.rb` in the user's project.
85
+ erb_hooks_src = File.read "glob/application_user.js.erb.hooks"
86
+ manifest = Flok::UserHooksToManifestOrchestrator.convert_hooks_to_manifest File.read("#{user_project_dir}/config/hooks.rb")
87
+ erb_src = Flok::HooksCompiler.compile erb_hooks_src, manifest
88
+ File.write "glob/application_user.js.erb", erb_src
89
+
90
+ #9. The `erb` files is then sent to `./products/$PLATFORM/glob/application_user.js` with the below `ERB` variables allowable.
82
91
  erb_src = File.read "glob/application_user.js.erb"
83
92
  renderr = ERB.new(erb_src)
84
93
  context = ERBUserApplicationContext.new()
data/docs/compilation.md CHANGED
@@ -18,7 +18,7 @@ as necessary.*
18
18
  6. All js files are globbed from `./products/$PLATFORM/glob` and combined into `./products/$PLATFORM/glob/application.js.erb`
19
19
  7. Auto-generated code is placed at the end (like PLATFORM global)
20
20
  8. The module specific code in `./kern/mod/.*js` are added when the name of the file (without the js part) is mentioned in the `./app/drivers/$PLATFORM/config.yml` `mods` section and appended to `glob/application.js.erb`
21
- 9. The compiled `glob/application.js.erb` file is run through the ERB compiler and formed into `application.js`
21
+ 9. The compiled `glob/application.js.erb` file is run through the ERB compiler and formed into `application.js`. This adds things like static debug variables, and hooks.
22
22
 
23
23
  ##Erb variables
24
24
  All kernel source files support embedded ERB code like `<% if DEBUG %>Code<% end %>`. These files include:
data/docs/kernel_api.md CHANGED
@@ -27,7 +27,7 @@ instead.
27
27
  * `gen_id()` - Will return a random unique id (8 character string).
28
28
 
29
29
  ##Events
30
- * `reg_evt(ep, f)` - Register a function to be called when an event is processed by `int_event`. The function will receive `(ep, event_name, info)`.
30
+ * `reg_evt(ep, f)` - Register a function to be called when an event is processed by `int_event`. The function will receive `(ep, event_name, info)`. ep must be either a string or number.
31
31
 
32
32
  * `dereg_evt(ep)` - Do not do anything if ep is received as an `int_event`
33
33
 
@@ -0,0 +1,4 @@
1
+ # Hooks in the kernel
2
+
3
+ ## How user-generators work
4
+ As mentioned in the [User Handbook | Hooks](../user_handbook/hooks.md), user-generators are compiled into the kernel when the
data/docs/mod/dlink.md ADDED
@@ -0,0 +1,18 @@
1
+ #Deep Link Module (dlink)
2
+ The deep linking module allows your application to support start-up URL requests. Many mobile operating systems allow apps to intercept certain URL namespaces which force redirection to an app instead of the default behaviour of a web-browser. This URL on startup feature allows the app to dynamically respond to a URL request from an outside source.
3
+
4
+ #### Kernel
5
+ `int_dlink_notify(url, params)` - An inbound deep-link was intercepted and forwarded. The params are a javascript dictionary of the link parameters and
6
+ the url is the base url of the link. E.g. if the link was `http://google.com/test?my_param=foo` then the url would be `http://google.com/test` and the
7
+ `params` are `{my_param: foo}`. This function simple calls the `dlink_notify_handler(url, params)` with the same
8
+ parameters. This handler function is currently only ownedowned by the sister-service `dlink`. In the future, we would
9
+ like to support the full RFC specification for URI's, but at this time, all the URI libraries are too large to warrant adding the additional bloat especially when
10
+ most clients have native ways of decoding URI's.
11
+
12
+ #### Kernel Spec Interrupts
13
+ `get_int_dlink_spec()` - Sends [[0, 1, "get_int_dlink_cb_spec", [url, params]] with the last received request from `int_dlink_notify`.
14
+
15
+ #### Driver
16
+ There is no requests the driver must handle. However, the driver should dispatch the message for the `int_dlink_notify` off the main queue. It should never be dispatched
17
+ before the application has fully started up. It is internally asynchronously dispatched, but for safety's sake, it should be dispatched at the soonest, immediately after
18
+ the system has loaded.
data/docs/mod/hook.md ADDED
@@ -0,0 +1,9 @@
1
+ #Hook
2
+ The hook module allows the client to receive hook_event messages. This is a required module.
3
+
4
+ ###Driver messages
5
+ `if_hook_event(name, info)` - The name of the hook event and the information received.
6
+
7
+ ####Driver spec functions (only required in debug mode)
8
+ `if_hook_spec_dump_rcvd_events` - Schedules the event `if_hook_spec_dump_res` to be sent out with a message in the form of `[1, "if_hook_spec_dump_rcvd_events_res", [{name:name, info:info}, ...]}` where the array contains
9
+ the parameters to all the calls to `if_hook_event` with the example hash and in sequential order where the oldest is the greatest index.
data/docs/project.md CHANGED
@@ -35,8 +35,9 @@ You create and build projects via the `flok` command. You must set the `$FLOK_EN
35
35
  5. The service configuration in `./config/services.rb` is read and run through `services_compiler` and files from
36
36
  `./products/$PLATFORM/services/combined_services.rb`. The output of this file is moved to `./products/$PLATFORM/glob/services.js`
37
37
  6. `./products/$PLATFORM/application.js` is moved to `./products/$PLATFORM/glob/application.js`
38
- 7. The local project `./products/$PLATFORM/glob/application.js` and `./products/$PLATFORM/glob/user_compiler.js` and `./products/$PLATFORM/glob/services.js` and `./products/$PLATFORM/glob/scripts.js` are merged into `./products/$PLATFORM/glob/application_user.js.erb`.
39
- 8. The `erb` files is then sent to `./products/$PLATFORM/glob/application_user.js` with the below `ERB` variables allowable.
38
+ 7. The local project `./products/$PLATFORM/glob/application.js` and `./products/$PLATFORM/glob/user_compiler.js` and `./products/$PLATFORM/glob/services.js` and `./products/$PLATFORM/glob/scripts.js` are merged into `./products/$PLATFORM/glob/application_user.js.erb.hooks`.
39
+ 9. The `hooks` compiler then runs over the source injecting any necessary hook code into the special comments by going through `./config/hooks.rb` in the user's project. This file is saved to `./products/$PLATFORM/glob/application_user.js.erb`
40
+ 10. The `erb` files is then sent to `./products/$PLATFORM/glob/application_user.js` with the below `ERB` variables allowable.
40
41
 
41
42
  ####Supported variables
42
43
  * `@debug` - Set to `true` when FLOK_ENV=DEBUG
@@ -0,0 +1,8 @@
1
+ #dlink - Deep Link Service
2
+ The **deep_link** service requires the `dlink` module to function. It implements the function `dlink_notify_handler` which is called by the `dlink`
3
+ module. All controllers that include this service will receive the `dlink_req` event with the parameters `{url: url, params: params}` via a
4
+ asynchronous event. An example of the `url` and `params` in `http://google.com/test?foo=bar` would be `{url: "http://google.com/test", {foo: "bar"}}`
5
+
6
+ ##Spec behaviours
7
+ When a request is made to the `dlink` port, see the `dlink` module for the port, any controllers registered to
8
+ this service should receive the `dlink:reqeust` with the appropriate parameters
@@ -0,0 +1,106 @@
1
+ #Hooks (User Guide)
2
+
3
+ ## What problems do hooks solve?
4
+ ##### There are two questions that *Hooks* were designed to solve.
5
+
6
+ 1. Animation segues. When a controller switches actions, often time it is swapping out view controllers. Adding animations at this time would be the optimal time to do so. However, different clients, take blackberry and iOS, may either have fully-automated-animations, gesture controlled animations, cancelable-animations, synchronous-blocking, and the list goes on-and-on. Clearly, animations are handled differently on each platform, so how do we allow each platform to manage animation-segues?
7
+ 2. There are times when a client, e.g. chrome, need to support semantics that are platform dependent. *For example*, you may need the back button in your web client to trigger a view controller to go back a page. However, this semantic does not make much sense when you have multiple view controllers; e.g. What view controller receives the back clicked event?
8
+
9
+ ##### Additionally, these questions must be solved with these constraints
10
+ 1. Allowing the client to choose interception points at runtime would be prohibitively slow. Therefore, care should be taken to make sure hooks are as static as possible and do not add un-necessary runtime overhead.
11
+
12
+ -------
13
+
14
+ ##### How hooks solves these problems:
15
+ *Hooks* solves these questions and constraitns by allowing the user to define triggers in their project under `./config/hooks.rb` using a *DSL* which in-turn notifies the client. The client then handles each hook in an appropriate fashion.
16
+
17
+ ## Hooking by example with `./config/hooks.rb`
18
+
19
+ **Here is an example of a `./config/hooks.rb` which tells flok to notify the client that the `supports_back_clicked` hook triggered whenever a controller instance of a `"my_controller"` controller switches to an action via Goto that has an event handler defined with `back_clicked`:**
20
+
21
+ ```ruby
22
+ # $USER_POJECT_ROOT/config/hooks.rb
23
+ hook :goto => :supports_back_clicked do
24
+ #Selectors (Each selector reduces the toal search area, if you have no selectors, it's like SELECT *)
25
+ to_action_responds_to? "back_clicked"
26
+ controller_name "my_controller"
27
+
28
+ #Configuration methods
29
+ is_sync
30
+ end
31
+ ```
32
+
33
+ **The basic format of each hook looks like:**
34
+ ```ruby
35
+ hook :hook_generator_name => :hook_notification_name do
36
+ #Selector methods & Configuration specific to the hook generator
37
+ end
38
+ ```
39
+
40
+ Selectors for each hook generator create more specific requirements for a trigger. By convention, all hook generators, if supplied no selector arguments will select all possible. **For example, this would hook all Goto statements in all controllers**:
41
+ ```ruby
42
+ hook :hook_generator_name => :hook_notification_name do
43
+ end
44
+ ```
45
+
46
+ ## Handling hook notifications in the client
47
+ ---
48
+ The client, in-turn must handle the hook notification, in this example, the hook notification is named `supports_back_clicked`. The hook notifications typically includes a set of parameters, but the parameters are dependent on the *hook generator* used. In the above example, we are using the `goto` hook generator. See below for the different `hook generators` specifics.
49
+
50
+ ** See client docs for how to handle hook notifications, here is an example in pseudo code: **
51
+ ```ruby
52
+ handleHook("supports_back_clicked", function(hookInfo) {
53
+ var to_action_name = hookInfo.to_action_name;
54
+ });
55
+ ```
56
+
57
+ ## Hook generators
58
+
59
+ * `goto` - Intercept `Goto` transitions and when a controller first loads (by virtue that a controller runs `Goto` when it first is initialized)
60
+ * `DSL Selectors`
61
+ * `to_action_responds_to? "event_name"` - Whenever a controller switches **to** an action that contains an `on "event_name", %{...}` handler
62
+ * `from_action_responds_to? "event_name"` - Whenever a controller switches **from** an action that contains an `on "event_name", %{...}` handler
63
+ * `controller "controller_name"` - Only applies to controllers with the name `"controller_name"`
64
+
65
+ ## How the hook generators are defined & hooking internals
66
+ See [Kernel Handbook | Hooks](../kernel_handbook/hooks.md)
67
+
68
+ ##How hooks are compiled into the kernel
69
+ The user's `./config/hooks.rb` file is compiled and then evaluated statically to get a listing of all the controllers that the hooks can apply to. Then the compiler goes over each controller
70
+ and inserts code at particular hook detection points; the nature of the insertions is up to the particular hooking context.
71
+
72
+ ##Synchronous vs Asynchronous Hooks
73
+ Whether a hook is synchronous or not synchronous depends entirely on the type of hook in question. An example of a possible synchronous hook is a hook jkkkkkkkkkk..j
74
+
75
+ ##Hooking check points
76
+ Each controller has a plethora of functions that determine it's lifetime and behaviours. These functions include the actions of creation, destruction, embedding, pushing actions, talking to services, etc.
77
+ These functions are built into the ctable entry for each controller and possible controller related functions like _embed. Each controller entry point is marked with a special comment marker that has
78
+ the following JSON format:
79
+
80
+ ```ruby
81
+ //HOOK_ENTRY[my_name] {foo: "bar"}...
82
+ ```
83
+ The name is the hook name and the params is context specific inforamtion the compiler has embedded. Live variables that are in the context of the hook detection point are described in each hook detection point below.
84
+
85
+ * `controller_will_goto` - The controller is about to invoke the Goto macro and switch actions or it has just entered the first action from choose_action (which is a Goto).
86
+ * params (static generated)
87
+ * `controller_name` - The controller name that this entry effects
88
+ * `from_action` - The name of the action we are coming from
89
+ * `to_action` - The name of the action we are going to
90
+ * Useful (dynamic) variables
91
+ * `old_action` - The previous action, equal to `from_action` but in dynamic form. If there is no action, this is set to `choose_action`. Not sure why you would use this
92
+ * `__info__.action` - The name of the new action
93
+ * `${controller_name}_did_destroy` - The controller has *just* been destroyed
94
+
95
+ ##Hooks Compiler
96
+ The hooks compiler is able to take the hook entry points and inject code into them via a set of `HooksManifestEntries` which are bound togeather via a `HooksManifest`. The actual
97
+ compiler only takes the original source code, the `HooksManifest` and then spits out a version that no longer contains the special hook entry comments and contains any
98
+ injected hooking code.
99
+
100
+
101
+ ##User Hook Generators
102
+
103
+ ###./config/hooks.rb
104
+ The hooks configuration file contains the user's DSL hooks. This file is not compiled directly by `HooksManifest` but rather many intermediate `UserHookGenerator` are
105
+ used to parse the `./config/hooks.rb` and this conversion is orchestrated by the singleton `UserHooksToManifestOrchestrator`. Each `UserHook` is defined in the `./lib/user_hook_generators.rb`
106
+ and are never meant to directly be created by users.