bidi2pdf 0.1.1 → 0.1.2

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.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +3 -0
  3. data/CHANGELOG.md +29 -3
  4. data/README.md +10 -0
  5. data/Rakefile +2 -0
  6. data/cliff.toml +114 -0
  7. data/docker/Dockerfile.chromedriver +33 -0
  8. data/docker/docker-compose.yml +7 -0
  9. data/docker/entrypoint.sh +3 -0
  10. data/lib/bidi2pdf/bidi/add_headers_interceptor.rb +1 -1
  11. data/lib/bidi2pdf/bidi/auth_interceptor.rb +1 -1
  12. data/lib/bidi2pdf/bidi/client.rb +55 -140
  13. data/lib/bidi2pdf/bidi/command_manager.rb +82 -0
  14. data/lib/bidi2pdf/bidi/connection_manager.rb +34 -0
  15. data/lib/bidi2pdf/bidi/session.rb +26 -9
  16. data/lib/bidi2pdf/chromedriver_manager.rb +19 -4
  17. data/lib/bidi2pdf/cli.rb +147 -18
  18. data/lib/bidi2pdf/launcher.rb +19 -6
  19. data/lib/bidi2pdf/version.rb +1 -1
  20. data/sig/bidi2pdf/bidi/add_headers_interceptor.rbs +20 -0
  21. data/sig/bidi2pdf/bidi/auth_interceptor.rbs +17 -0
  22. data/sig/bidi2pdf/bidi/browser.rbs +38 -0
  23. data/sig/bidi2pdf/bidi/browser_tab.rbs +42 -0
  24. data/sig/bidi2pdf/bidi/client.rbs +72 -0
  25. data/sig/bidi2pdf/bidi/event_manager.rbs +29 -0
  26. data/sig/bidi2pdf/bidi/network_event.rbs +51 -0
  27. data/sig/bidi2pdf/bidi/network_events.rbs +55 -0
  28. data/sig/bidi2pdf/bidi/print_parameters_validator.rbs +44 -0
  29. data/sig/bidi2pdf/bidi/session.rbs +52 -0
  30. data/sig/bidi2pdf/bidi/user_context.rbs +50 -0
  31. data/sig/bidi2pdf/bidi/web_socket_dispatcher.rbs +53 -0
  32. data/sig/bidi2pdf/chromedriver_manager.rbs +42 -0
  33. data/sig/bidi2pdf/cli.rbs +21 -0
  34. data/sig/bidi2pdf/launcher.rbs +38 -0
  35. data/sig/bidi2pdf/process_tree.rbs +27 -0
  36. data/sig/bidi2pdf/session_runner.rbs +51 -0
  37. data/sig/bidi2pdf/utils.rbs +5 -0
  38. data/sig/vendor/thor.rbs +13 -0
  39. data/tasks/changelog.rake +29 -0
  40. data/tasks/generate_rbs.rake +64 -0
  41. metadata +48 -8
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bidi2pdf
4
+ module Bidi
5
+ class ConnectionManager
6
+ def initialize(logger:)
7
+ @logger = logger
8
+ @connected = false
9
+ @mutex = Mutex.new
10
+ @cv = ConditionVariable.new
11
+ end
12
+
13
+ def mark_connected
14
+ @mutex.synchronize do
15
+ @connected = true
16
+ @cv.broadcast
17
+ end
18
+ end
19
+
20
+ def wait_until_open(timeout:)
21
+ @mutex.synchronize do
22
+ unless @connected
23
+ @logger.debug "Waiting for WebSocket connection to open"
24
+ @cv.wait(@mutex, timeout)
25
+ end
26
+ end
27
+
28
+ raise "WebSocket connection did not open in time" unless @connected
29
+
30
+ @logger.debug "WebSocket connection is open"
31
+ end
32
+ end
33
+ end
34
+ end
@@ -25,22 +25,24 @@ module Bidi2pdf
25
25
  "goog:cdp.Page.screencastFrame"
26
26
  ].freeze
27
27
 
28
- attr_reader :port, :websocket_url
28
+ attr_reader :session_uri, :started
29
29
 
30
- def initialize(port, headless: true)
31
- @port = port
30
+ def initialize(session_url:, headless: true)
31
+ @session_uri = URI(session_url)
32
32
  @headless = headless
33
33
  @client = nil
34
34
  @browser = nil
35
35
  @websocket_url = nil
36
+ @started = false
36
37
  end
37
38
 
38
39
  def start
40
+ @started = true
39
41
  client
40
42
  end
41
43
 
42
44
  def client
43
- @client ||= create_client
45
+ @client ||= @started ? create_client : nil
44
46
  end
45
47
 
46
48
  def close
@@ -88,9 +90,19 @@ module Bidi2pdf
88
90
  Bidi::Browser.new(@client)
89
91
  end
90
92
 
91
- # rubocop: disable Metrics/AbcSize
92
93
  def create_client
93
- uri = URI("http://localhost:#{port}/session")
94
+ Bidi::Client.new(websocket_url).tap(&:start)
95
+ end
96
+
97
+ # rubocop:disable Metrics/AbcSize
98
+ def websocket_url
99
+ return @websocket_url if @websocket_url
100
+
101
+ if %w[ws wss].include?(session_uri.scheme)
102
+ @websocket_url = session_uri.to_s
103
+ return @websocket_url
104
+ end
105
+
94
106
  args = %w[
95
107
  --disable-gpu
96
108
  --disable-popup-blocking
@@ -115,7 +127,12 @@ module Bidi2pdf
115
127
  }
116
128
  }
117
129
  }
118
- response = Net::HTTP.post(uri, session_request.to_json, "Content-Type" => "application/json")
130
+
131
+ response = Net::HTTP.post(session_uri, session_request.to_json, "Content-Type" => "application/json")
132
+
133
+ Bidi2pdf.logger.debug "Response code: #{response.code}"
134
+ Bidi2pdf.logger.debug "Response body: #{response.body}"
135
+
119
136
  session_data = JSON.parse(response.body)
120
137
 
121
138
  Bidi2pdf.logger.debug "Session data: #{session_data}"
@@ -126,10 +143,10 @@ module Bidi2pdf
126
143
  Bidi2pdf.logger.info "Created session with ID: #{session_id}"
127
144
  Bidi2pdf.logger.info "WebSocket URL: #{@websocket_url}"
128
145
 
129
- Bidi::Client.new(@websocket_url).tap(&:start)
146
+ @websocket_url
130
147
  end
131
148
 
132
- # rubocop: enable Metrics/AbcSize
149
+ # rubocop:enable Metrics/AbcSize
133
150
  end
134
151
  end
135
152
  end
@@ -4,17 +4,20 @@ require "chromedriver/binary"
4
4
 
5
5
  module Bidi2pdf
6
6
  class ChromedriverManager
7
- attr_reader :port, :pid, :session
7
+ attr_reader :port, :pid, :started
8
8
 
9
9
  def initialize(port: 0, headless: true)
10
10
  @port = port
11
11
  @headless = headless
12
12
  @session = nil
13
+ @started = false
13
14
  end
14
15
 
15
16
  def start
16
17
  return @pid if @pid
17
18
 
19
+ @started = true
20
+
18
21
  update_chromedriver
19
22
  cmd = build_cmd
20
23
  Bidi2pdf.logger.info "Starting Chromedriver with command: #{cmd}"
@@ -30,14 +33,26 @@ module Bidi2pdf
30
33
 
31
34
  at_exit { stop }
32
35
 
33
- @session = Bidi::Session.new(@port, headless: @headless)
34
-
35
36
  @pid
36
37
  end
37
38
 
39
+ def session
40
+ return unless @started
41
+
42
+ @session ||= Bidi::Session.new(session_url: session_url, headless: @headless)
43
+ end
44
+
45
+ def session_url
46
+ return unless @started
47
+
48
+ "http://localhost:#{@port}/session"
49
+ end
50
+
38
51
  def stop(timeout: 5)
39
52
  return unless @pid
40
53
 
54
+ @started = false
55
+
41
56
  close_session
42
57
 
43
58
  term_chromedriver
@@ -83,7 +98,7 @@ module Bidi2pdf
83
98
  def close_session
84
99
  Bidi2pdf.logger.info "Closing session"
85
100
 
86
- @session.close
101
+ @session&.close
87
102
  @session = nil
88
103
  end
89
104
 
data/lib/bidi2pdf/cli.rb CHANGED
@@ -1,9 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "thor"
4
+ require "yaml"
4
5
 
5
6
  module Bidi2pdf
7
+ # rubocop:disable Metrics/AbcSize
6
8
  class CLI < Thor
9
+ class_option :config, type: :string, desc: "Load configuration from YAML file"
10
+
7
11
  desc "render", "Render a URL to PDF using Chrome BiDi"
8
12
  long_desc <<~USAGE, wrap: false
9
13
  Example:
@@ -26,11 +30,11 @@ module Bidi2pdf
26
30
  Set --port to 0 for a random ChromeDriver port.
27
31
  USAGE
28
32
 
29
- option :url, required: true, desc: "The URL to render"
30
- option :output, default: "output.pdf", desc: "Filename for the output PDF"
31
- option :cookie, type: :array, default: [], banner: "name=value", desc: "One or more cookies"
32
- option :header, type: :array, default: [], banner: "name=value", desc: "One or more custom headers"
33
- option :auth, type: :string, banner: "user:pass", desc: "Basic auth credentials"
33
+ option :url, desc: "The URL to render"
34
+ option :output, default: "output.pdf", desc: "Filename for the output PDF", aliases: "-o"
35
+ option :cookie, type: :array, default: [], banner: "name=value", desc: "One or more cookies", aliases: "-C"
36
+ option :header, type: :array, default: [], banner: "name=value", desc: "One or more custom headers", aliases: "-H"
37
+ option :auth, type: :string, banner: "user:pass", desc: "Basic auth credentials", aliases: "-a"
34
38
  option :headless, type: :boolean, default: true, desc: "Run Chrome in headless mode"
35
39
  option :port, type: :numeric, default: 0, desc: "Port to run ChromeDriver on (0 = auto)"
36
40
  option :wait_window_loaded,
@@ -39,36 +43,156 @@ module Bidi2pdf
39
43
  desc: "Wait for the window to be fully loaded (windoow.loaded set by your script)"
40
44
  option :wait_network_idle, type: :boolean, default: false, desc: "Wait for network to be idle"
41
45
  option :default_timeout, type: :numeric, default: 60, desc: "Default timeout for commands"
46
+ option :remote_browser_url, type: :string, desc: "Remote browser URL for ChromeDriver"
42
47
  option :log_level,
43
48
  type: :string,
44
49
  default: "info", enum: %w[debug info warn error fatal unknown], desc: "Set log level"
45
50
 
51
+ option :background, type: :boolean, default: true, desc: "Print background graphics"
52
+ option :margin_top, type: :numeric, default: 1.0, desc: "Top margin in inches"
53
+ option :margin_bottom, type: :numeric, default: 1.0, desc: "Bottom margin in inches"
54
+ option :margin_left, type: :numeric, default: 1.0, desc: "Left margin in inches"
55
+ option :margin_right, type: :numeric, default: 1.0, desc: "Right margin in inches"
56
+ option :orientation, type: :string, default: "portrait", enum: %w[portrait landscape], desc: "Page orientation"
57
+ option :page_width, type: :numeric, default: 21.59, desc: "Page width in cm (min 0.0352)"
58
+ option :page_height, type: :numeric, default: 27.94, desc: "Page height in cm (min 0.0352)"
59
+ option :page_ranges, type: :array, desc: "Page ranges to print (e.g., 1-2 4 6)"
60
+ option :scale, type: :numeric, default: 1.0, desc: "Scale between 0.1 and 2.0"
61
+ option :shrink_to_fit, type: :boolean, default: true, desc: "Shrink content to fit page"
62
+
46
63
  def render
64
+ load_config
65
+
66
+ validate_required_options! :url
67
+
47
68
  configure
48
69
 
49
- Bidi2pdf.logger.info "Rendering: #{options[:url]} -> #{options[:output]}"
70
+ Bidi2pdf.logger.info "Rendering: #{merged_options[:url]} -> #{merged_options[:output]}"
71
+ Bidi2pdf.logger.info "Print options: #{print_options.inspect}" if print_options
72
+
73
+ validate_print_options(print_options) if print_options
50
74
 
51
75
  launcher.launch
76
+ ensure
77
+ launcher.stop if defined?(@launcher) && @launcher
78
+ end
79
+
80
+ desc "version", "Show bidi2pdf version"
81
+
82
+ def version
83
+ puts "bidi2pdf #{Bidi2pdf::VERSION}"
84
+ end
85
+
86
+ desc "template", "Generate a config file template"
87
+ option :output, default: "bidi2pdf.yml", desc: "Output configuration filename"
88
+
89
+ def template
90
+ config = {
91
+ "url" => "https://example.com",
92
+ "output" => "output.pdf",
93
+ "headless" => true,
94
+ "print_options" => {
95
+ "background" => true,
96
+ "orientation" => "portrait",
97
+ "margin" => {
98
+ "top" => 1.0,
99
+ "bottom" => 1.0,
100
+ "left" => 1.0,
101
+ "right" => 1.0
102
+ }
103
+ }
104
+ }
105
+
106
+ File.write(merged_options[:output], config.to_yaml)
107
+ puts "Config template written to #{merged_options[:output]}"
52
108
  end
53
109
 
54
110
  private
55
111
 
56
- # rubocop:disable Metrics/AbcSize
112
+ def load_config
113
+ return unless options[:config] && File.exist?(options[:config])
114
+
115
+ YAML.load_file(options[:config]).transform_keys(&:to_sym)
116
+ end
117
+
118
+ def validate_required_options!(*keys)
119
+ keys.each do |key|
120
+ raise Thor::Error, "Missing required option: --#{key.to_s.tr("_", "-")}" unless merged_options[key]
121
+ end
122
+ end
123
+
124
+ def validate_print_options(opts)
125
+ Bidi2pdf::Bidi::PrintParametersValidator.validate!(opts)
126
+ rescue ArgumentError => e
127
+ raise Thor::Error, "Invalid print option: #{e.message}"
128
+ end
129
+
130
+ # rubocop:disable Metrics/CyclomaticComplexity
131
+ def print_options
132
+ opts = {}
133
+
134
+ assign_if_provided(opts, :background)
135
+ assign_if_provided(opts, :orientation)
136
+ opts[:pageRanges] = merged_options[:page_ranges] if merged_options[:page_ranges]
137
+
138
+ if option_provided?(:scale)
139
+ scale = merged_options[:scale]
140
+ raise ArgumentError, "Scale must be between 0.1 and 2.0" unless (0.1..2.0).include?(scale)
141
+
142
+ opts[:scale] = scale
143
+ end
144
+
145
+ assign_if_provided(opts, :shrinkToFit, :shrink_to_fit)
146
+
147
+ # Margins
148
+ margin_keys = {
149
+ top: :margin_top,
150
+ bottom: :margin_bottom,
151
+ left: :margin_left,
152
+ right: :margin_right
153
+ }
154
+ margins = {}
155
+ margin_keys.each do |short, full|
156
+ assign_if_provided(margins, short, full)
157
+ end
158
+ opts[:margin] = margins unless margins.empty?
159
+
160
+ # Page size
161
+ page = {}
162
+ assign_if_provided(page, :width, :page_width)
163
+ assign_if_provided(page, :height, :page_height)
164
+ opts[:page] = page unless page.empty?
165
+
166
+ opts.empty? ? nil : opts
167
+ end
168
+
169
+ # rubocop:enable Metrics/CyclomaticComplexity
170
+
171
+ def option_provided?(key)
172
+ ARGV.include?("--#{key.to_s.tr("_", "-")}") || ARGV.include?("--#{key}")
173
+ end
174
+
175
+ def assign_if_provided(hash, key, option_key = key)
176
+ hash[key] = merged_options[option_key] if option_provided?(option_key)
177
+ end
178
+
57
179
  def launcher
58
180
  # rubocop:disable Layout/BeginEndAlignment
59
181
  @launcher ||= begin
60
- username, password = parse_auth(options[:auth]) if options[:auth]
182
+ username, password = parse_auth(merged_options[:auth]) if merged_options[:auth]
61
183
 
62
184
  Bidi2pdf::Launcher.new(
63
- url: options[:url],
64
- output: options[:output],
65
- cookies: parse_key_values(options[:cookie]),
66
- headers: parse_key_values(options[:header]),
185
+ url: merged_options[:url],
186
+ output: merged_options[:output],
187
+ cookies: parse_key_values(merged_options[:cookie]),
188
+ headers: parse_key_values(merged_options[:header]),
67
189
  auth: { username: username, password: password },
68
- port: options[:port],
69
- headless: options[:headless],
70
- wait_window_loaded: options[:wait_window_loaded],
71
- wait_network_idle: options[:wait_network_idle]
190
+ port: merged_options[:port],
191
+ remote_browser_url: merged_options[:remote_browser_url],
192
+ headless: merged_options[:headless],
193
+ wait_window_loaded: merged_options[:wait_window_loaded],
194
+ wait_network_idle: merged_options[:wait_network_idle],
195
+ print_options: print_options
72
196
  )
73
197
  end
74
198
  # rubocop:enable Layout/BeginEndAlignment
@@ -79,7 +203,7 @@ module Bidi2pdf
79
203
  def configure
80
204
  Bidi2pdf.configure do |config|
81
205
  config.logger.level = log_level
82
- config.default_timeout = options[:default_timeout]
206
+ config.default_timeout = merged_options[:default_timeout]
83
207
 
84
208
  Chromedriver::Binary.configure do |c|
85
209
  c.logger.level = log_level
@@ -88,7 +212,7 @@ module Bidi2pdf
88
212
  end
89
213
 
90
214
  def log_level
91
- case options[:log_level]
215
+ case merged_options[:log_level]
92
216
  when "debug" then Logger::DEBUG
93
217
  when "warn" then Logger::WARN
94
218
  when "error" then Logger::ERROR
@@ -114,5 +238,10 @@ module Bidi2pdf
114
238
 
115
239
  [user, pass]
116
240
  end
241
+
242
+ def merged_options
243
+ defaults = load_config || {}
244
+ Thor::CoreExt::HashWithIndifferentAccess.new(defaults.merge(options))
245
+ end
117
246
  end
118
247
  end
@@ -6,8 +6,9 @@ require_relative "bidi/session"
6
6
 
7
7
  module Bidi2pdf
8
8
  class Launcher
9
+ # rubocop:disable Metrics/ParameterLists
9
10
  def initialize(url:, output:, cookies:, headers:, auth:, headless: true, port: 0, wait_window_loaded: false,
10
- wait_network_idle: false, print_options: {})
11
+ wait_network_idle: false, print_options: {}, remote_browser_url: nil)
11
12
  @url = url
12
13
  @port = port
13
14
  @headless = headless
@@ -19,14 +20,14 @@ module Bidi2pdf
19
20
  @wait_window_loaded = wait_window_loaded
20
21
  @wait_network_idle = wait_network_idle
21
22
  @print_options = print_options || {}
23
+ @remote_browser_url = remote_browser_url
22
24
  end
23
25
 
24
- def launch
25
- @manager = ChromedriverManager.new(port: @port, headless: @headless)
26
- @manager.start
26
+ # rubocop:enable Metrics/ParameterLists
27
27
 
28
+ def launch
28
29
  runner = SessionRunner.new(
29
- session: @manager.session,
30
+ session: session,
30
31
  url: @url,
31
32
  output: @output,
32
33
  cookies: @cookies,
@@ -40,7 +41,19 @@ module Bidi2pdf
40
41
  end
41
42
 
42
43
  def stop
43
- @manager.stop
44
+ @manager&.stop
45
+ end
46
+
47
+ private
48
+
49
+ def session
50
+ if @remote_browser_url
51
+ Bidi::Session.new(session_url: @remote_browser_url, headless: @headless)
52
+ else
53
+ @manager = ChromedriverManager.new(port: @port, headless: @headless)
54
+ @manager.start
55
+ @manager.session
56
+ end
44
57
  end
45
58
  end
46
59
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bidi2pdf
4
- VERSION = "0.1.1"
4
+ VERSION = "0.1.2"
5
5
  end
@@ -0,0 +1,20 @@
1
+ module Bidi2pdf
2
+ module Bidi
3
+ class AddHeadersInterceptor
4
+ @id: String
5
+ @client: untyped
6
+ @headers: Hash[String, String]
7
+
8
+ attr_reader id: String
9
+ attr_reader headers: Hash[String, String]
10
+
11
+ def initialize: (String id, Hash[String, String] headers, untyped client) -> void
12
+
13
+ def handle_event: (Hash[String, untyped] response) -> (nil | untyped)
14
+
15
+ private
16
+
17
+ attr_reader client: untyped
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,17 @@
1
+ module Bidi2pdf
2
+ module Bidi
3
+ class AuthInterceptor
4
+ @credentials: Hash[Symbol, String]?
5
+
6
+ def initialize: (?credentials: Hash[Symbol, String]?) -> void
7
+
8
+ def intercept: (untyped request) -> untyped
9
+
10
+ private
11
+
12
+ def add_auth_header: (untyped request) -> void
13
+
14
+ def auth_header_value: () -> String?
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,38 @@
1
+ module Bidi2pdf
2
+ module Bidi
3
+ class Browser
4
+ @url: String
5
+ @chromedriver_manager: Bidi2pdf::ChromedriverManager
6
+ @browser: untyped
7
+ @timeout: Integer
8
+ @debug: bool
9
+
10
+ attr_reader browser: untyped
11
+ attr_reader timeout: Integer
12
+
13
+ def initialize: (
14
+ url: String,
15
+ chromedriver_manager: Bidi2pdf::ChromedriverManager,
16
+ ?timeout: Integer,
17
+ ?debug: bool
18
+ ) -> void
19
+
20
+ def navigate: (?reload: bool) -> void
21
+
22
+ def current_url: -> String
23
+
24
+ def wait_until: [T] (
25
+ ?timeout: Integer,
26
+ ?message: String
27
+ ) { () -> T? } -> T
28
+
29
+ def close: () -> void
30
+
31
+ private
32
+
33
+ def connect: () -> untyped
34
+
35
+ def setup_browser: () -> untyped
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,42 @@
1
+ module Bidi2pdf
2
+ module Bidi
3
+ class BrowserTab
4
+ @browser: Bidi2pdf::Bidi::Browser
5
+ @tab_id: String?
6
+ @session_id: String?
7
+ @timeout: Integer
8
+
9
+ attr_reader browser: Bidi2pdf::Bidi::Browser
10
+ attr_reader tab_id: String?
11
+ attr_reader session_id: String?
12
+
13
+ def initialize: (
14
+ browser: Bidi2pdf::Bidi::Browser,
15
+ ?tab_id: String?,
16
+ ?timeout: Integer
17
+ ) -> void
18
+
19
+ def navigate_to: (String url) -> void
20
+
21
+ def execute_script: [T] (String script, *untyped args) -> T
22
+
23
+ def wait_for_navigation: (?timeout: Integer) -> void
24
+
25
+ def wait_for_element: (
26
+ selector: String,
27
+ ?visible: bool,
28
+ ?timeout: Integer
29
+ ) -> untyped
30
+
31
+ def capture_screenshot: (?path: String?) -> String
32
+
33
+ def close: () -> void
34
+
35
+ private
36
+
37
+ def ensure_tab_active: () -> void
38
+
39
+ def connect_to_tab: () -> String?
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,72 @@
1
+ module Bidi2pdf
2
+ module Bidi
3
+ class Client
4
+ @next_id_mutex: Mutex
5
+ @ws_url: untyped
6
+
7
+ @id: untyped
8
+
9
+ @pending_responses: Hash[String, Thread::Queue]
10
+
11
+ @connected: untyped
12
+
13
+ @connection_mutex: Mutex
14
+
15
+ @send_cmd_mutex: Mutex
16
+
17
+ @connection_cv: untyped
18
+
19
+ @started: untyped
20
+
21
+ @socket: untyped
22
+
23
+ @dispatcher: untyped
24
+
25
+ include Bidi2pdf::Utils
26
+
27
+ attr_reader ws_url: untyped
28
+
29
+ def initialize: (untyped ws_url) -> void
30
+
31
+ def start: () -> untyped
32
+
33
+ def started?: () -> untyped
34
+
35
+ def wait_until_open: (?timeout: untyped) -> untyped
36
+
37
+ def send_cmd: (untyped method, ?::Hash[untyped, untyped] params) -> untyped
38
+
39
+ # rubocop:disable Metrics/AbcSize
40
+ def send_cmd_and_wait: (untyped method, ?::Hash[untyped, untyped] params, ?timeout: untyped) ?{ (untyped) -> untyped } -> untyped
41
+
42
+ # Event API for external consumers
43
+ def on_message: () { () -> untyped } -> untyped
44
+
45
+ def on_open: () { () -> untyped } -> untyped
46
+
47
+ def on_close: () { () -> untyped } -> untyped
48
+
49
+ def on_error: () { () -> untyped } -> untyped
50
+
51
+ def on_event: (*untyped names) { () -> untyped } -> untyped
52
+
53
+ def remove_message_listener: (untyped block) -> untyped
54
+
55
+ def remove_event_listener: (*untyped names) { () -> untyped } -> untyped
56
+
57
+ def add_headers_interceptor: (context: untyped, url_patterns: untyped, headers: untyped) -> untyped
58
+
59
+ def add_auth_interceptor: (context: untyped, url_patterns: untyped, username: untyped, password: untyped) -> untyped
60
+
61
+ private
62
+
63
+ def next_id: () -> untyped
64
+
65
+ def handle_open: () -> untyped
66
+
67
+ def handle_response_to_cmd: (untyped data) -> untyped
68
+
69
+ def redact_sensitive_fields: (untyped obj, ?::Array[untyped] sensitive_keys) -> untyped
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,29 @@
1
+ module Bidi2pdf
2
+ module Bidi
3
+ class EventManager
4
+ @browser: Bidi2pdf::Bidi::Browser
5
+ @listeners: Hash[String, Array[Proc]]
6
+ @active: bool
7
+
8
+ def initialize: (browser: Bidi2pdf::Bidi::Browser) -> void
9
+
10
+ def on: (String event_name) { (Hash[String, untyped]) -> void } -> void
11
+
12
+ def off: (String event_name) -> void
13
+
14
+ def emit: (String event_name, Hash[String, untyped] params) -> void
15
+
16
+ def start_listening: () -> void
17
+
18
+ def stop_listening: () -> void
19
+
20
+ private
21
+
22
+ def register_browser_events: () -> void
23
+
24
+ def handle_event: (String event_name, Hash[String, untyped] params) -> void
25
+
26
+ def process_event: (String event_name, Hash[String, untyped] params) -> void
27
+ end
28
+ end
29
+ end