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,51 @@
1
+ module Bidi2pdf
2
+ module Bidi
3
+ class NetworkEvent
4
+ # Request data
5
+ @request_id: String
6
+ @url: String
7
+ @method: String
8
+ @headers: Hash[String, String]
9
+ @post_data: String?
10
+
11
+ # Response data
12
+ @response_status: Integer?
13
+ @response_headers: Hash[String, String]?
14
+ @response_body: String?
15
+
16
+ # Timing information
17
+ @timestamp: Float
18
+ @timing: Hash[Symbol, Float]?
19
+
20
+ attr_reader request_id: String
21
+ attr_reader url: String
22
+ attr_reader method: String
23
+ attr_reader headers: Hash[String, String]
24
+ attr_reader post_data: String?
25
+ attr_reader response_status: Integer?
26
+ attr_reader response_headers: Hash[String, String]?
27
+ attr_reader response_body: String?
28
+ attr_reader timestamp: Float
29
+ attr_reader timing: Hash[Symbol, Float]?
30
+
31
+ def initialize: (
32
+ request_id: String,
33
+ url: String,
34
+ method: String,
35
+ headers: Hash[String, String],
36
+ ?post_data: String?,
37
+ ?timestamp: Float?
38
+ ) -> void
39
+
40
+ def add_response: (
41
+ status: Integer,
42
+ headers: Hash[String, String],
43
+ ?body: String?
44
+ ) -> void
45
+
46
+ def add_timing: (Hash[Symbol, Float] timing_data) -> void
47
+
48
+ def completed?: () -> bool
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,55 @@
1
+ module Bidi2pdf
2
+ module Bidi
3
+ class NetworkEvents
4
+ include Enumerable[NetworkEvent]
5
+
6
+ @events: Hash[String, NetworkEvent]
7
+ @browser: Bidi2pdf::Bidi::Browser?
8
+ @event_manager: Bidi2pdf::Bidi::EventManager?
9
+ @recording: bool
10
+ @filters: Array[Proc]
11
+
12
+ attr_reader events: Hash[String, NetworkEvent]
13
+ attr_reader recording: bool
14
+
15
+ def initialize: (?browser: Bidi2pdf::Bidi::Browser?) -> void
16
+
17
+ def start_recording: (?browser: Bidi2pdf::Bidi::Browser?) -> void
18
+
19
+ def stop_recording: () -> void
20
+
21
+ def add_filter: () { (NetworkEvent) -> bool } -> void
22
+
23
+ def clear_filters: () -> void
24
+
25
+ def clear: () -> void
26
+
27
+ def size: () -> Integer
28
+
29
+ def []: (String request_id) -> NetworkEvent?
30
+
31
+ def each: () { (NetworkEvent) -> void } -> self
32
+ | () -> Enumerator[NetworkEvent, self]
33
+
34
+ def find_by_url: (String url_pattern) -> Array[NetworkEvent]
35
+
36
+ def find_by_method: (String method) -> Array[NetworkEvent]
37
+
38
+ def completed_requests: () -> Array[NetworkEvent]
39
+
40
+ def pending_requests: () -> Array[NetworkEvent]
41
+
42
+ def to_a: () -> Array[NetworkEvent]
43
+
44
+ private
45
+
46
+ def setup_event_listeners: () -> void
47
+
48
+ def handle_request_event: (Hash[String, untyped] params) -> void
49
+
50
+ def handle_response_event: (Hash[String, untyped] params) -> void
51
+
52
+ def handle_loading_finished_event: (Hash[String, untyped] params) -> void
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,44 @@
1
+ module Bidi2pdf
2
+ module Bidi
3
+ class PrintParametersValidator
4
+ # Valid print parameter configurations
5
+ DEFAULT_PARAMETERS: Hash[Symbol, untyped]
6
+ ALLOWED_PAGE_RANGES_FORMATS: Array[String]
7
+ ALLOWED_MARGIN_UNITS: Array[String]
8
+ ALLOWED_PAPER_FORMATS: Array[String]
9
+ ALLOWED_ORIENTATIONS: Array[String]
10
+
11
+ @parameters: Hash[Symbol, untyped]
12
+ @errors: Array[String]
13
+
14
+ attr_reader errors: Array[String]
15
+ attr_reader parameters: Hash[Symbol, untyped]
16
+
17
+ def initialize: (Hash[Symbol, untyped] parameters) -> void
18
+
19
+ def validate: () -> bool
20
+
21
+ def valid?: () -> bool
22
+
23
+ private
24
+
25
+ def validate_boolean: (Symbol key) -> void
26
+
27
+ def validate_number: (Symbol key, ?min: Numeric?, ?max: Numeric?) -> void
28
+
29
+ def validate_string: (Symbol key) -> void
30
+
31
+ def validate_enum: (Symbol key, Array[String] allowed_values) -> void
32
+
33
+ def validate_margins: () -> void
34
+
35
+ def validate_page_ranges: () -> void
36
+
37
+ def validate_paper_size: () -> void
38
+
39
+ def normalize_parameters: () -> void
40
+
41
+ def add_error: (String message) -> void
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,52 @@
1
+ module Bidi2pdf
2
+ module Bidi
3
+ class Session
4
+ @browser: Bidi2pdf::Bidi::Browser
5
+ @session_id: String?
6
+ @contexts: Array[String]
7
+ @timeout: Integer
8
+ @event_manager: Bidi2pdf::Bidi::EventManager?
9
+ @network_events: Bidi2pdf::Bidi::NetworkEvents?
10
+
11
+ attr_reader browser: Bidi2pdf::Bidi::Browser
12
+ attr_reader session_id: String?
13
+ attr_reader contexts: Array[String]
14
+
15
+ def initialize: (
16
+ browser: Bidi2pdf::Bidi::Browser,
17
+ ?session_id: String?,
18
+ ?timeout: Integer
19
+ ) -> void
20
+
21
+ def create: () -> String
22
+
23
+ def attach: (session_id: String) -> String
24
+
25
+ def detach: () -> void
26
+
27
+ def execute_command: [T] (String method, ?Hash[Symbol, untyped] params) -> T
28
+
29
+ def navigate_to: (String url) -> void
30
+
31
+ def evaluate: [T] (String script) -> T
32
+
33
+ def wait_for_load: (?timeout: Integer?) -> void
34
+
35
+ def network_events: () -> Bidi2pdf::Bidi::NetworkEvents
36
+
37
+ def capture_screenshot: (?path: String?) -> String
38
+
39
+ def print_to_pdf: (
40
+ ?Hash[Symbol, untyped] parameters
41
+ ) -> String
42
+
43
+ def close: () -> void
44
+
45
+ private
46
+
47
+ def ensure_session: () -> String
48
+
49
+ def setup_event_listeners: () -> void
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,50 @@
1
+ module Bidi2pdf
2
+ module Bidi
3
+ class UserContext
4
+ @browser: Bidi2pdf::Bidi::Browser
5
+ @context_id: String
6
+ @session_id: String?
7
+ @event_manager: Bidi2pdf::Bidi::EventManager?
8
+ @network_events: Bidi2pdf::Bidi::NetworkEvents?
9
+ @closed: bool
10
+
11
+ attr_reader context_id: String
12
+ attr_reader browser: Bidi2pdf::Bidi::Browser
13
+ attr_reader session_id: String?
14
+
15
+ def initialize: (
16
+ browser: Bidi2pdf::Bidi::Browser,
17
+ context_id: String,
18
+ ?session_id: String?
19
+ ) -> void
20
+
21
+ def create_session: () -> String
22
+
23
+ def attach_session: (session_id: String) -> String
24
+
25
+ def execute_command: [T] (String method, ?Hash[Symbol, untyped] params) -> T
26
+
27
+ def navigate_to: (String url) -> void
28
+
29
+ def evaluate: [T] (String script) -> T
30
+
31
+ def wait_for_load: (?timeout: Integer?) -> void
32
+
33
+ def network_events: () -> Bidi2pdf::Bidi::NetworkEvents
34
+
35
+ def capture_screenshot: (?path: String?) -> String
36
+
37
+ def print_to_pdf: (?Hash[Symbol, untyped] parameters) -> String
38
+
39
+ def close: () -> void
40
+
41
+ def closed?: () -> bool
42
+
43
+ private
44
+
45
+ def ensure_open: () -> void
46
+
47
+ def setup_event_listeners: () -> void
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,53 @@
1
+ module Bidi2pdf
2
+ module Bidi
3
+ class WebSocketDispatcher
4
+ @url: String
5
+ @socket: WebSocket::Driver
6
+ @connection: TCPSocket
7
+ @pending_requests: Hash[Integer, Concurrent::Promises::ResolvableFuture]
8
+ @message_id: Integer
9
+ @listeners: Hash[String, Array[Proc]]
10
+ @thread: Thread?
11
+ @mutex: Mutex
12
+ @connected: bool
13
+ @logger: Logger?
14
+
15
+ attr_reader url: String
16
+ attr_reader connected: bool
17
+
18
+ def initialize: (String url, ?logger: Logger?) -> void
19
+
20
+ def connect: () -> bool
21
+
22
+ def disconnect: () -> void
23
+
24
+ def send_command: [T] (String method, ?Hash[Symbol, untyped] params) -> T
25
+
26
+ def send_message: (Hash[Symbol, untyped] message) -> Integer
27
+
28
+ def add_event_listener: (String event_name) { (Hash[String, untyped]) -> void } -> void
29
+
30
+ def remove_event_listener: (String event_name, ?Proc? callback) -> void
31
+
32
+ def connected?: () -> bool
33
+
34
+ private
35
+
36
+ def generate_message_id: () -> Integer
37
+
38
+ def create_socket: () -> WebSocket::Driver
39
+
40
+ def handle_open: () -> void
41
+
42
+ def handle_message: (String data) -> void
43
+
44
+ def handle_close: () -> void
45
+
46
+ def handle_error: (Exception error) -> void
47
+
48
+ def dispatch_event: (String event_name, Hash[String, untyped] params) -> void
49
+
50
+ def listen_for_messages: () -> void
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,42 @@
1
+ module Bidi2pdf
2
+ class ChromedriverManager
3
+ @port: Integer
4
+ @headless: bool
5
+ @session: untyped
6
+ @pid: Integer?
7
+
8
+ attr_reader port: Integer
9
+ attr_reader pid: Integer?
10
+ attr_reader session: untyped
11
+
12
+ def initialize: (?port: Integer, ?headless: bool) -> void
13
+
14
+ def start: () -> self
15
+
16
+ def stop: (?timeout: Integer) -> bool
17
+
18
+ private
19
+
20
+ # rubocop:disable Metrics/AbcSize
21
+ def detect_zombie_processes: () -> Array[Integer]?
22
+
23
+ def debug_show_all_children: () -> void
24
+
25
+ def close_session: () -> void
26
+
27
+ def term_chromedriver: () -> bool
28
+
29
+ def kill_chromedriver: (?timeout: Integer) -> bool
30
+
31
+ def build_cmd: () -> Array[String]
32
+
33
+ def update_chromedriver: () -> void
34
+
35
+ # rubocop:disable Metrics/AbcSize
36
+ def parse_port_from_output: (IO io, ?timeout: Integer) -> Integer?
37
+
38
+ def process_alive?: (?pid: Integer?) -> bool
39
+
40
+ def wait_until_chromedriver_ready: (?timeout: Integer) -> bool
41
+ end
42
+ end
@@ -0,0 +1,21 @@
1
+ module Bidi2pdf
2
+ class CLI < Thor
3
+ # rubocop:disable Layout/BeginEndAlignment
4
+ @launcher: untyped
5
+
6
+ def render: () -> untyped
7
+
8
+ private
9
+
10
+ # rubocop:disable Metrics/AbcSize
11
+ def launcher: () -> untyped
12
+
13
+ def configure: () -> untyped
14
+
15
+ def log_level: () -> untyped
16
+
17
+ def parse_key_values: (untyped pairs) -> untyped
18
+
19
+ def parse_auth: (untyped auth_string) -> ::Array[untyped]
20
+ end
21
+ end
@@ -0,0 +1,38 @@
1
+ module Bidi2pdf
2
+ class Launcher
3
+ @url: untyped
4
+
5
+ @port: untyped
6
+
7
+ @headless: untyped
8
+
9
+ @output: untyped
10
+
11
+ @cookies: untyped
12
+
13
+ @headers: untyped
14
+
15
+ @auth: untyped
16
+
17
+ @manager: untyped
18
+
19
+ @wait_window_loaded: untyped
20
+
21
+ @wait_network_idle: untyped
22
+
23
+ @print_options: untyped
24
+
25
+ @remote_browser_url: untyped
26
+
27
+ # rubocop:disable Metrics/ParameterLists
28
+ def initialize: (url: untyped, output: untyped, cookies: untyped, headers: untyped, auth: untyped, ?headless: bool, ?port: ::Integer, ?wait_window_loaded: bool, ?wait_network_idle: bool, ?print_options: ::Hash[untyped, untyped], ?remote_browser_url: untyped?) -> void
29
+
30
+ def launch: () -> untyped
31
+
32
+ def stop: () -> untyped
33
+
34
+ private
35
+
36
+ def session: () -> untyped
37
+ end
38
+ end
@@ -0,0 +1,27 @@
1
+ module Bidi2pdf
2
+ class ProcessTree
3
+ @root_pid: untyped
4
+
5
+ @process_map: untyped
6
+
7
+ include Sys
8
+
9
+ def initialize: (?untyped? root_pid) -> void
10
+
11
+ def children: (untyped of_pid) -> (::Array[untyped] | untyped)
12
+
13
+ def traverse: () { () -> untyped } -> untyped
14
+
15
+ private
16
+
17
+ def print_handler: (untyped process, untyped level) -> untyped
18
+
19
+ def build_process_map: () -> untyped
20
+
21
+ def connect_children: () -> untyped
22
+
23
+ def root_pids: () -> (::Array[untyped] | untyped)
24
+
25
+ def traverse_branch: (untyped pid, ?::Integer level) { () -> untyped } -> (nil | untyped)
26
+ end
27
+ end
@@ -0,0 +1,51 @@
1
+ module Bidi2pdf
2
+ class SessionRunner
3
+ @session: untyped
4
+
5
+ @url: untyped
6
+
7
+ @output: untyped
8
+
9
+ @cookies: untyped
10
+
11
+ @headers: untyped
12
+
13
+ @auth: untyped
14
+
15
+ @wait_window_loaded: untyped
16
+
17
+ @wait_network_idle: untyped
18
+
19
+ @print_options: untyped
20
+
21
+ @window: untyped
22
+
23
+ @tab: untyped
24
+
25
+ @uri: untyped
26
+
27
+ def initialize: (session: untyped, url: untyped, output: untyped, ?cookies: ::Hash[untyped, untyped], ?headers: ::Hash[untyped, untyped], ?auth: ::Hash[untyped, untyped], ?wait_window_loaded: bool, ?wait_network_idle: bool, ?print_options: ::Hash[untyped, untyped]) -> void
28
+
29
+ def run: () -> untyped
30
+
31
+ private
32
+
33
+ def setup_browser: () -> untyped
34
+
35
+ def add_cookies: (untyped tab) -> untyped
36
+
37
+ def add_headers: () -> untyped
38
+
39
+ def add_basic_auth: () -> (nil | untyped)
40
+
41
+ def run_flow: () -> untyped
42
+
43
+ def uri: () -> untyped
44
+
45
+ def domain: () -> untyped
46
+
47
+ def source_origin: () -> untyped
48
+
49
+ def url_patterns: () -> ::Array[{ type: "pattern", protocol: untyped, hostname: untyped, port: untyped }]
50
+ end
51
+ end
@@ -0,0 +1,5 @@
1
+ module Bidi2pdf
2
+ module Utils
3
+ def self?.timed: (untyped operation_name) { () -> untyped } -> untyped
4
+ end
5
+ end
@@ -0,0 +1,13 @@
1
+ class Thor
2
+ def self.desc: (String name, String description) -> void
3
+
4
+ def self.option: (Symbol name, ?Hash[Symbol, untyped] options) -> void
5
+
6
+ def self.long_desc: (String description, ?Hash[Symbol, untyped] options) -> void
7
+
8
+ interface _Command
9
+ def execute: (*untyped) -> untyped
10
+ end
11
+
12
+ def initialize: (?Hash[Symbol, untyped] options) -> void
13
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ def cliff_installed?
4
+ system("which git-cliff > /dev/null 2>&1")
5
+ end
6
+
7
+ namespace :changelog do
8
+ desc "Generate unreleased section in CHANGELOG.md (requires git-cliff)"
9
+ task :update_unreleased do
10
+ unless cliff_installed?
11
+ puts "๐Ÿšซ git-cliff is not installed!"
12
+ puts "๐Ÿ‘‰ Install it here: https://git-cliff.org/docs/installation/"
13
+ exit 1
14
+ end
15
+
16
+ generated = `git cliff --unreleased`
17
+
18
+ changelog_path = "CHANGELOG.md"
19
+ changelog = File.read(changelog_path)
20
+
21
+ updated = changelog.sub(
22
+ /<!--.*generated\s+by\s+git-cliff\s+start\s+-->(.*?)<!--\s+generated\s+by\s+git-cliff\s+end\s+-->/m,
23
+ generated.strip
24
+ )
25
+
26
+ File.write(changelog_path, updated)
27
+ puts "โœ… Replaced generated section in CHANGELOG.md"
28
+ end
29
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "fileutils"
4
+ require "rbs"
5
+
6
+ SOURCE_DIR = "lib"
7
+ OUTPUT_DIR = "sig"
8
+
9
+ # rubocop:disable Metrics/BlockLength
10
+ namespace :rbs do
11
+ file_list = FileList["#{SOURCE_DIR}/**/*.rb"]
12
+
13
+ desc "Generate all RBS files"
14
+ task generate_rbs: :rbs_targets
15
+
16
+ rbs_map = file_list.to_h do |rb|
17
+ relative = rb.sub(%r{^#{SOURCE_DIR}/}, "")
18
+ rbs = File.join(OUTPUT_DIR, relative.sub(/\.rb$/, ".rbs"))
19
+ [rbs, rb]
20
+ end
21
+
22
+ rbs_map.each do |rbs_path, rb_path|
23
+ file rbs_path => rb_path do
24
+ puts "๐Ÿ”ง Generating: #{rbs_path} (from #{rb_path})"
25
+
26
+ FileUtils.mkdir_p(File.dirname(rbs_path))
27
+
28
+ begin
29
+ input = Pathname(rb_path)
30
+ output = Pathname(rbs_path)
31
+
32
+ parser = RBS::Prototype::RB.new
33
+ parser.parse input.read
34
+
35
+ if output.file?
36
+ puts "โš ๏ธ RBS file already exists: #{rbs_path}"
37
+ else
38
+ puts "๐Ÿ“ Writing RBS file: #{rbs_path}"
39
+
40
+ output.open("w") do |io|
41
+ writer = RBS::Writer.new(out: io)
42
+ writer.write(parser.decls)
43
+ end
44
+ end
45
+ rescue StandardError => e
46
+ puts "โŒ Error generating RBS for #{rb_path}: #{e.message}"
47
+ end
48
+ end
49
+ end
50
+
51
+ desc "Generate RBS files for all Ruby files"
52
+ task rbs_targets: rbs_map.keys do
53
+ puts "โœ… RBS generation complete!"
54
+ end
55
+
56
+ desc "Clean all generated RBS files"
57
+ task :clean_rbs do
58
+ FileList["#{OUTPUT_DIR}/**/*.rbs"].each do |file|
59
+ FileUtils.rm_f(file)
60
+ end
61
+ puts "๐Ÿงน Cleaned up all RBS files"
62
+ end
63
+ end
64
+ # rubocop:enable Metrics/BlockLength