Class: Datastar::ServerSentEventGenerator

Inherits:
Object
  • Object
show all
Defined in:
lib/datastar/server_sent_event_generator.rb

Constant Summary collapse

MSG_END =
"\n"
SSE_OPTION_MAPPING =
{
  'eventId' => 'id',
  'retryDuration' => 'retry',
  'id' => 'id',
  'retry' => 'retry',
}.freeze
OPTION_DEFAULTS =
{
  'retry' => Consts::DEFAULT_SSE_RETRY_DURATION,
  Consts::MODE_DATALINE_LITERAL => Consts::DEFAULT_ELEMENT_PATCH_MODE,
  Consts::USE_VIEW_TRANSITION_DATALINE_LITERAL => Consts::DEFAULT_ELEMENTS_USE_VIEW_TRANSITIONS,
  Consts::ONLY_IF_MISSING_DATALINE_LITERAL => Consts::DEFAULT_PATCH_SIGNALS_ONLY_IF_MISSING,
}.freeze
SIGNAL_SEPARATOR =
'.'

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(stream, signals:, view_context: nil) ⇒ ServerSentEventGenerator

Returns a new instance of ServerSentEventGenerator.



27
28
29
30
31
# File 'lib/datastar/server_sent_event_generator.rb', line 27

def initialize(stream, signals:, view_context: nil)
  @stream = stream
  @signals = signals
  @view_context = view_context
end

Instance Attribute Details

#signalsObject (readonly)

Returns the value of attribute signals.



25
26
27
# File 'lib/datastar/server_sent_event_generator.rb', line 25

def signals
  @signals
end

Instance Method Details

#check_connection!Object

Sometimes we’ll want to run periodic checks to ensure the connection is still alive ie. the browser hasn’t disconnected For example when idle listening on an event bus.



36
37
38
# File 'lib/datastar/server_sent_event_generator.rb', line 36

def check_connection!
  @stream << MSG_END
end

#execute_script(script, options = BLANK_OPTIONS) ⇒ Object



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/datastar/server_sent_event_generator.rb', line 90

def execute_script(script, options = BLANK_OPTIONS)
  options = camelize_keys(options)
  auto_remove = options.key?('autoRemove') ? options.delete('autoRemove') : true
  attributes = options.delete('attributes') || BLANK_OPTIONS
  script_tag = +"<script"
  attributes.each do |k, v|
    script_tag << %( #{camelize(k)}="#{v}")
  end
  script_tag << %( data-effect="el.remove()") if auto_remove
  script_tag << ">#{script}</script>"

  options[Consts::SELECTOR_DATALINE_LITERAL] = 'body'
  options[Consts::MODE_DATALINE_LITERAL] = Consts::ElementPatchMode::APPEND

  patch_elements(script_tag, options)
end

#patch_elements(elements, options = BLANK_OPTIONS) ⇒ Object



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/datastar/server_sent_event_generator.rb', line 40

def patch_elements(elements, options = BLANK_OPTIONS)
  elements = Array(elements).compact
  rendered_elements = elements.map do |element|
    render_element(element)
  end

  element_lines = rendered_elements.flat_map do |el|
    el.to_s.split("\n")
  end

  buffer = +"event: datastar-patch-elements\n"
  build_options(options, buffer)
  element_lines.each { |line| buffer << "data: #{Consts::ELEMENTS_DATALINE_LITERAL} #{line}\n" }

  write(buffer)
end

#patch_signals(signals, options = BLANK_OPTIONS) ⇒ Object



67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/datastar/server_sent_event_generator.rb', line 67

def patch_signals(signals, options = BLANK_OPTIONS)
  buffer = +"event: datastar-patch-signals\n"
  build_options(options, buffer)
  case signals
  when Hash
    signals = JSON.dump(signals)
    buffer << "data: signals #{signals}\n"
  when String
    multi_data_lines(signals, buffer, Consts::SIGNALS_DATALINE_LITERAL)
  end
  write(buffer)
end

#redirect(url) ⇒ Object



107
108
109
# File 'lib/datastar/server_sent_event_generator.rb', line 107

def redirect(url)
  execute_script %(setTimeout(() => { window.location = '#{url}' }))
end

#remove_elements(selector, options = BLANK_OPTIONS) ⇒ Object



57
58
59
60
61
62
63
64
65
# File 'lib/datastar/server_sent_event_generator.rb', line 57

def remove_elements(selector, options = BLANK_OPTIONS)
  patch_elements(
    nil, 
    options.merge(
      Consts::MODE_DATALINE_LITERAL => Consts::ElementPatchMode::REMOVE,
      selector:
    )
  )
end

#remove_signals(paths, options = BLANK_OPTIONS) ⇒ Object



80
81
82
83
84
85
86
87
88
# File 'lib/datastar/server_sent_event_generator.rb', line 80

def remove_signals(paths, options = BLANK_OPTIONS)
  paths = [paths].flatten
  signals = paths.each.with_object({}) do |path, acc|
    parts = path.split(SIGNAL_SEPARATOR)
    set_nested_value(acc, parts, nil)
  end

  patch_signals(signals, options)
end

#write(buffer) ⇒ Object



111
112
113
114
# File 'lib/datastar/server_sent_event_generator.rb', line 111

def write(buffer)
  buffer << MSG_END
  @stream << buffer
end