waves-ruby 0.1.0

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: ba842c75819ad196345a640bb058aaa398b5ed6ada2e7610ff15d080b0613d1b
4
+ data.tar.gz: 6ea6b97c6b33a6503dc9921761b23fb86d9a0851a307294d248134259038c00f
5
+ SHA512:
6
+ metadata.gz: 273137f5386f5fa57d420644e1c0e083f98d658957995023434ce8ae0acecf4897785e65319c72d3ef44e2d3d562c90a634a2b02879cd8a76575755b90a359e1
7
+ data.tar.gz: 64d920b54c4e272d2a334c51844aa912478e37e6e988f9bb982106262387beec817030c688882225c06c82285c08fa06cdd3a98e10e447c69c5eb21fb3797b5d
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,38 @@
1
+ # Contributing
2
+
3
+ ## Local Setup
4
+
5
+ ```bash
6
+ bundle install
7
+ bundle exec rspec
8
+ ```
9
+
10
+ Copy `.env.example` to `.env` if you want to run live API verification locally.
11
+
12
+ ## Testing Policy
13
+
14
+ - `.env` is for local development only and must never be committed.
15
+ - Use `WAVES_API_TOKEN` from `.env` for opt-in live verification only.
16
+ - Raw VCR recordings belong in `spec/cassettes/local/` and must stay untracked.
17
+ - Committed fixtures and example cassettes must be sanitized.
18
+ - Do not commit real meeting titles, summaries, snippets, notes, transcripts, or signed media URLs.
19
+
20
+ ## Live Verification Workflow
21
+
22
+ 1. Copy `.env.example` to `.env`.
23
+ 2. Set `WAVES_API_TOKEN` in `.env`.
24
+ 3. Run `WAVES_LIVE=1 bundle exec rspec spec/waves/live/client_live_spec.rb`.
25
+ 4. If you want to record local cassettes for the entire live suite, run `WAVES_LIVE=1 WAVES_RECORD_LIVE=1 bundle exec rspec spec/waves/live/client_live_spec.rb`.
26
+ 5. Keep any raw recordings in `spec/cassettes/local/`.
27
+ 6. Optionally set `WAVES_SESSION_ID` and `WAVES_SEARCH_QUERY` in `.env` if you want deterministic session and search coverage.
28
+ 7. Convert any useful example into a sanitized fixture under `spec/fixtures/waves/` or a scrubbed cassette under `spec/cassettes/examples/`.
29
+ 8. Commit only sanitized artifacts.
30
+
31
+ ## Sanitization Checklist
32
+
33
+ - Replace tokens and `Authorization` headers.
34
+ - Replace real meeting titles, snippets, summaries, notes, and transcript text.
35
+ - Replace signed or temporary media URLs.
36
+ - Replace participant emails and other personal identifiers.
37
+
38
+ The helper patterns in [spec/support/sanitizer.rb](/Users/avi/Development/code/waves-rubygem-cli-api/spec/support/sanitizer.rb) are intended to make that scrubbing repeatable, but contributors are still responsible for reviewing the final artifact before committing it.
data/README.md ADDED
@@ -0,0 +1,94 @@
1
+ # Waves Ruby
2
+
3
+ Ruby API client and CLI for the Wave API.
4
+
5
+ ## CLI
6
+
7
+ Available commands:
8
+
9
+ ```bash
10
+ waves login
11
+ waves account
12
+ waves list
13
+ waves search "meeting content"
14
+ waves show SESSION_ID
15
+ waves transcript SESSION_ID
16
+ ```
17
+
18
+ Use `--json` on any read command for machine-readable output:
19
+
20
+ ```bash
21
+ waves list --json
22
+ waves account --json
23
+ ```
24
+
25
+ You can provide credentials with `--token`, `WAVES_API_TOKEN`, or a token saved locally by `waves login`.
26
+
27
+ ## Ruby API
28
+
29
+ ```ruby
30
+ client = Waves::Client.new(token: ENV.fetch("WAVES_API_TOKEN"))
31
+
32
+ client.account
33
+ client.list_sessions(limit: 10)
34
+ client.search_sessions(query: "roadmap")
35
+ client.session("session_123")
36
+ client.transcript("session_123")
37
+ ```
38
+
39
+ ## Development
40
+
41
+ Install dependencies:
42
+
43
+ ```bash
44
+ bundle install
45
+ ```
46
+
47
+ Run the test suite:
48
+
49
+ ```bash
50
+ bundle exec rspec
51
+ ```
52
+
53
+ ## Live API Verification
54
+
55
+ Copy `.env.example` to `.env` and set a real token:
56
+
57
+ ```bash
58
+ cp .env.example .env
59
+ ```
60
+
61
+ Then set:
62
+
63
+ ```bash
64
+ WAVES_API_TOKEN=your_wave_api_token
65
+ ```
66
+
67
+ Live specs are opt-in and skipped by default. Run them locally with:
68
+
69
+ ```bash
70
+ WAVES_LIVE=1 bundle exec rspec spec/waves/live/client_live_spec.rb
71
+ ```
72
+
73
+ That exercises the current live coverage for:
74
+
75
+ - `account`
76
+ - `list_sessions`
77
+ - `stats`
78
+ - `session`
79
+ - `transcript`
80
+ - `search_sessions`
81
+
82
+ `session`, `transcript`, and `search_sessions` auto-discover test inputs from your first listed session. You can make them deterministic by setting `WAVES_SESSION_ID` and `WAVES_SEARCH_QUERY` in `.env`.
83
+
84
+ To record local-only cassettes for every live example in the gitignored directory:
85
+
86
+ ```bash
87
+ WAVES_LIVE=1 WAVES_RECORD_LIVE=1 bundle exec rspec spec/waves/live/client_live_spec.rb
88
+ ```
89
+
90
+ Those recordings stay under `spec/cassettes/local/` and must not be committed. If you want to keep an example response in the repo, convert it into a sanitized fixture under `spec/fixtures/waves/` or a scrubbed example cassette under `spec/cassettes/examples/`.
91
+
92
+ Use the sanitization patterns in [spec/support/sanitizer.rb](/Users/avi/Development/code/waves-rubygem-cli-api/spec/support/sanitizer.rb) before committing any captured API data.
93
+
94
+ See [CONTRIBUTING.md](/Users/avi/Development/code/waves-rubygem-cli-api/CONTRIBUTING.md) for the full policy.
data/exe/waves ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require_relative "../lib/waves"
5
+
6
+ exit Waves::CLI.start(ARGV)
@@ -0,0 +1,238 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "io/console"
4
+ require "optparse"
5
+
6
+ module Waves
7
+ module CLI
8
+ class CommandError < StandardError; end
9
+
10
+ class App
11
+ COMMANDS = %w[login account list search show transcript].freeze
12
+
13
+ def initialize(argv:, stdin:, stdout:, stderr:, env:, config:, client_class:)
14
+ @argv = argv.dup
15
+ @stdin = stdin
16
+ @stdout = stdout
17
+ @stderr = stderr
18
+ @env = env
19
+ @config = config
20
+ @client_class = client_class
21
+ @formatter = Formatter.new(stdout: stdout)
22
+ end
23
+
24
+ def start
25
+ options, args = parse_global_options(@argv)
26
+ command = args.shift
27
+
28
+ return print_help if command.nil?
29
+ return print_help(args.first) if command == "help"
30
+ return print_help(command) if options[:help]
31
+
32
+ dispatch(command, args, options)
33
+ rescue OptionParser::ParseError, CommandError, Waves::Error => error
34
+ print_error(error, json: options&.fetch(:json, false) || false)
35
+ end
36
+
37
+ private
38
+
39
+ def parse_global_options(argv)
40
+ options = {
41
+ help: false,
42
+ json: false,
43
+ token: nil
44
+ }
45
+
46
+ parser = OptionParser.new do |opts|
47
+ opts.on("--json") { options[:json] = true }
48
+ opts.on("--token TOKEN") { |token| options[:token] = token }
49
+ opts.on("-h", "--help") { options[:help] = true }
50
+ end
51
+
52
+ args = argv.dup
53
+ parser.permute!(args)
54
+
55
+ [options, args]
56
+ end
57
+
58
+ def dispatch(command, args, options)
59
+ case command
60
+ when "login"
61
+ run_login(args, options)
62
+ when "account"
63
+ ensure_no_arguments!("account", args)
64
+ render_payload(fetch_client(options).account, options) { |payload| @formatter.print_account(payload) }
65
+ when "list"
66
+ ensure_no_arguments!("list", args)
67
+ render_payload(fetch_client(options).list_sessions, options) { |payload| @formatter.print_list(payload) }
68
+ when "search"
69
+ run_search(args, options)
70
+ when "show"
71
+ run_show(args, options)
72
+ when "transcript"
73
+ run_transcript(args, options)
74
+ else
75
+ raise CommandError, "Unknown command: #{command}"
76
+ end
77
+ end
78
+
79
+ def run_login(args, options)
80
+ ensure_no_arguments!("login", args)
81
+
82
+ token = normalize_token(options[:token]) || normalize_token(prompt_for_token)
83
+ raise CommandError, "Token cannot be empty" if token.to_s.empty?
84
+
85
+ @config.save_token(token)
86
+
87
+ payload = {
88
+ "config_path" => @config.config_path,
89
+ "message" => "Token saved"
90
+ }
91
+
92
+ render_payload(payload, options) do
93
+ @stdout.puts "Saved Wave API token to #{@config.config_path}"
94
+ end
95
+ end
96
+
97
+ def run_search(args, options)
98
+ query = args.join(" ").strip
99
+ raise CommandError, "Usage: waves search QUERY" if query.empty?
100
+
101
+ render_payload(fetch_client(options).search_sessions(query: query), options) do |payload|
102
+ @formatter.print_search(payload)
103
+ end
104
+ end
105
+
106
+ def run_show(args, options)
107
+ session_id = require_single_argument!("show", "SESSION_ID", args)
108
+
109
+ render_payload(fetch_client(options).session(session_id), options) do |payload|
110
+ @formatter.print_session(payload)
111
+ end
112
+ end
113
+
114
+ def run_transcript(args, options)
115
+ session_id = require_single_argument!("transcript", "SESSION_ID", args)
116
+
117
+ render_payload(fetch_client(options).transcript(session_id), options) do |payload|
118
+ @formatter.print_transcript(payload)
119
+ end
120
+ end
121
+
122
+ def fetch_client(options)
123
+ @client_class.new(token: resolve_token(options[:token]))
124
+ end
125
+
126
+ def resolve_token(explicit_token)
127
+ normalize_token(explicit_token) ||
128
+ normalize_token(@env["WAVES_API_TOKEN"]) ||
129
+ normalize_token(@config.stored_token)
130
+ end
131
+
132
+ def render_payload(payload, options)
133
+ if options[:json]
134
+ @formatter.print_json(payload)
135
+ else
136
+ yield payload
137
+ end
138
+
139
+ 0
140
+ end
141
+
142
+ def print_error(error, json:)
143
+ if json
144
+ @stderr.puts JSON.pretty_generate(
145
+ "error" => {
146
+ "message" => error.message,
147
+ "type" => error.class.name.split("::").last.gsub(/([a-z])([A-Z])/, '\1_\2').downcase
148
+ }
149
+ )
150
+ else
151
+ @stderr.puts "Error: #{error.message}"
152
+ @stderr.puts
153
+ @stderr.puts help_text if error.is_a?(CommandError) && error.message.start_with?("Unknown command:")
154
+ end
155
+
156
+ 1
157
+ end
158
+
159
+ def print_help(command = nil)
160
+ text = command ? help_text(command) : help_text
161
+
162
+ if text.nil?
163
+ @stderr.puts "Error: Unknown command: #{command}"
164
+ @stderr.puts
165
+ @stderr.puts help_text
166
+ return 1
167
+ end
168
+
169
+ @stdout.puts text
170
+ 0
171
+ end
172
+
173
+ def help_text(command = nil)
174
+ return top_level_help if command.nil?
175
+
176
+ {
177
+ "login" => "Usage: waves login [--token TOKEN] [--json]",
178
+ "account" => "Usage: waves account [--token TOKEN] [--json]",
179
+ "list" => "Usage: waves list [--token TOKEN] [--json]",
180
+ "search" => "Usage: waves search QUERY [--token TOKEN] [--json]",
181
+ "show" => "Usage: waves show SESSION_ID [--token TOKEN] [--json]",
182
+ "transcript" => "Usage: waves transcript SESSION_ID [--token TOKEN] [--json]"
183
+ }[command]
184
+ end
185
+
186
+ def top_level_help
187
+ <<~TEXT
188
+ Usage: waves COMMAND [options]
189
+
190
+ Commands:
191
+ login
192
+ account
193
+ list
194
+ search QUERY
195
+ show SESSION_ID
196
+ transcript SESSION_ID
197
+
198
+ Global options:
199
+ --json
200
+ --token TOKEN
201
+ -h, --help
202
+ TEXT
203
+ end
204
+
205
+ def ensure_no_arguments!(command, args)
206
+ return if args.empty?
207
+
208
+ raise CommandError, help_text(command)
209
+ end
210
+
211
+ def require_single_argument!(command, argument_name, args)
212
+ return args.first if args.length == 1 && !args.first.to_s.empty?
213
+
214
+ raise CommandError, "Usage: waves #{command} #{argument_name}"
215
+ end
216
+
217
+ def prompt_for_token
218
+ @stderr.print "Wave API token: "
219
+
220
+ token = if @stdin.respond_to?(:noecho) && @stdin.tty?
221
+ @stdin.noecho(&:gets)
222
+ else
223
+ @stdin.gets
224
+ end
225
+
226
+ @stderr.puts if @stdin.tty?
227
+ token
228
+ end
229
+
230
+ def normalize_token(token)
231
+ value = token.to_s.strip
232
+ return if value.empty?
233
+
234
+ value
235
+ end
236
+ end
237
+ end
238
+ end
@@ -0,0 +1,149 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+
5
+ module Waves
6
+ module CLI
7
+ class Formatter
8
+ def initialize(stdout:)
9
+ @stdout = stdout
10
+ end
11
+
12
+ def print_json(payload)
13
+ @stdout.puts JSON.pretty_generate(payload)
14
+ end
15
+
16
+ def print_account(account)
17
+ print_record(account)
18
+ end
19
+
20
+ def print_list(response)
21
+ sessions = Array(response["sessions"])
22
+
23
+ if sessions.empty?
24
+ @stdout.puts "No sessions found"
25
+ return
26
+ end
27
+
28
+ print_collection(sessions)
29
+
30
+ return if response["next_cursor"].to_s.empty?
31
+
32
+ @stdout.puts
33
+ @stdout.puts "Next cursor: #{response["next_cursor"]}"
34
+ end
35
+
36
+ def print_search(response)
37
+ results = Array(response["results"])
38
+
39
+ if results.empty?
40
+ @stdout.puts "No results found"
41
+ return
42
+ end
43
+
44
+ print_collection(results, include_snippet: true)
45
+ end
46
+
47
+ def print_session(session)
48
+ print_record(session)
49
+ end
50
+
51
+ def print_transcript(response)
52
+ transcript = response["transcript"]
53
+
54
+ case transcript
55
+ when String
56
+ @stdout.puts transcript
57
+ when Array
58
+ transcript.each do |entry|
59
+ @stdout.puts transcript_line(entry)
60
+ end
61
+ else
62
+ print_record(response)
63
+ end
64
+ end
65
+
66
+ private
67
+
68
+ def print_collection(records, include_snippet: false)
69
+ records.each_with_index do |record, index|
70
+ @stdout.puts summary_line(record)
71
+
72
+ detail = detail_line(record)
73
+ @stdout.puts " #{detail}" unless detail.nil?
74
+
75
+ if include_snippet && !record["snippet"].to_s.empty?
76
+ @stdout.puts " #{record["snippet"]}"
77
+ end
78
+
79
+ @stdout.puts unless index == records.length - 1
80
+ end
81
+ end
82
+
83
+ def print_record(record)
84
+ record.each do |key, value|
85
+ label = humanize_key(key)
86
+
87
+ case value
88
+ when Hash, Array
89
+ @stdout.puts "#{label}:"
90
+ JSON.pretty_generate(value).each_line do |line|
91
+ @stdout.puts " #{line.rstrip}"
92
+ end
93
+ when String
94
+ if value.include?("\n")
95
+ @stdout.puts "#{label}:"
96
+ value.each_line do |line|
97
+ @stdout.puts " #{line.rstrip}"
98
+ end
99
+ else
100
+ @stdout.puts "#{label}: #{value}"
101
+ end
102
+ else
103
+ @stdout.puts "#{label}: #{value}"
104
+ end
105
+ end
106
+ end
107
+
108
+ def summary_line(record)
109
+ identifier = record["id"] || "(no id)"
110
+ title = record["title"] || record["name"]
111
+
112
+ return identifier if title.to_s.empty?
113
+
114
+ "#{identifier} #{title}"
115
+ end
116
+
117
+ def detail_line(record)
118
+ details = []
119
+ details << record["type"]
120
+ details << record["status"]
121
+ details << record["created_at"]
122
+ details << record["started_at"]
123
+ details << record["updated_at"]
124
+ details << "#{record["duration_seconds"]}s" if record["duration_seconds"]
125
+ details.reject! { |value| value.to_s.empty? }
126
+
127
+ return if details.empty?
128
+
129
+ details.join(" ")
130
+ end
131
+
132
+ def transcript_line(entry)
133
+ return entry unless entry.is_a?(Hash)
134
+
135
+ prefix = [entry["speaker"], entry["timestamp"]].reject { |value| value.to_s.empty? }.join(" @ ")
136
+ text = entry["text"].to_s
137
+
138
+ return text if prefix.empty?
139
+ return prefix if text.empty?
140
+
141
+ "#{prefix}: #{text}"
142
+ end
143
+
144
+ def humanize_key(key)
145
+ key.to_s.split("_").map(&:capitalize).join(" ")
146
+ end
147
+ end
148
+ end
149
+ end
data/lib/waves/cli.rb ADDED
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "cli/formatter"
4
+ require_relative "cli/app"
5
+
6
+ module Waves
7
+ module CLI
8
+ module_function
9
+
10
+ def start(argv, stdin: $stdin, stdout: $stdout, stderr: $stderr, env: ENV, config: Waves::Config, client_class: Waves::Client)
11
+ App.new(
12
+ argv: argv,
13
+ stdin: stdin,
14
+ stdout: stdout,
15
+ stderr: stderr,
16
+ env: env,
17
+ config: config,
18
+ client_class: client_class
19
+ ).start
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "httparty"
4
+ require "json"
5
+
6
+ module Waves
7
+ class Client
8
+ include HTTParty
9
+
10
+ base_uri "https://api.wave.co/v1"
11
+
12
+ def initialize(token: nil, timeout: Waves.timeout)
13
+ @token = token || Config.token
14
+ @timeout = timeout
15
+
16
+ raise InvalidConfigError, "Missing Wave API token" if @token.to_s.empty?
17
+ end
18
+
19
+ def list_sessions(limit: nil, cursor: nil, since: nil, type: nil)
20
+ request(:get, "/sessions", query: {
21
+ limit: limit,
22
+ cursor: cursor,
23
+ since: since,
24
+ type: type
25
+ })
26
+ end
27
+
28
+ def session(id)
29
+ request(:get, "/sessions/#{id}")
30
+ end
31
+
32
+ def search_sessions(query:, limit: nil)
33
+ request(:post, "/sessions/search", body: {
34
+ query: query,
35
+ limit: limit
36
+ })
37
+ end
38
+
39
+ def transcript(id)
40
+ request(:get, "/sessions/#{id}/transcript")
41
+ end
42
+
43
+ def stats(since: nil, until_time: nil, until_: nil)
44
+ request(:get, "/sessions/stats", query: {
45
+ since: since,
46
+ until: until_time || until_
47
+ })
48
+ end
49
+
50
+ def account
51
+ request(:get, "/account")
52
+ end
53
+
54
+ private
55
+
56
+ def request(method, path, query: nil, body: nil)
57
+ options = {
58
+ headers: headers,
59
+ timeout: @timeout
60
+ }
61
+ options[:query] = Request.compact_hash(query) if query
62
+ options[:body] = JSON.generate(Request.compact_hash(body)) if body
63
+
64
+ response = self.class.public_send(method, path, options)
65
+ parse_response(response)
66
+ rescue SocketError, HTTParty::Error, Net::OpenTimeout, Net::ReadTimeout, Errno::ECONNREFUSED => e
67
+ raise ConnectionError, e.message
68
+ end
69
+
70
+ def parse_response(response)
71
+ parsed = parse_body(response)
72
+ return parsed if response.success?
73
+
74
+ error = parsed.is_a?(Hash) ? parsed["error"] || {} : {}
75
+ message = error["message"] || response.body
76
+
77
+ case response.code.to_i
78
+ when 401
79
+ raise AuthenticationError, message
80
+ when 403
81
+ raise AuthorizationError, message
82
+ when 404
83
+ raise NotFoundError, message
84
+ when 429
85
+ raise RateLimitError, message
86
+ else
87
+ raise APIError, message
88
+ end
89
+ end
90
+
91
+ def parse_body(response)
92
+ return {} if response.body.to_s.empty?
93
+
94
+ JSON.parse(response.body)
95
+ rescue JSON::ParserError
96
+ response.body
97
+ end
98
+
99
+ def headers
100
+ {
101
+ "Accept" => "application/json",
102
+ "Authorization" => "Bearer #{@token}",
103
+ "Content-Type" => "application/json"
104
+ }
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+
5
+ module Waves
6
+ module Config
7
+ module_function
8
+
9
+ def config_dir
10
+ File.join(Dir.home, ".config", "waves")
11
+ end
12
+
13
+ def config_path
14
+ File.join(config_dir, "config.json")
15
+ end
16
+
17
+ def token
18
+ ENV["WAVES_API_TOKEN"] || stored_token
19
+ end
20
+
21
+ def stored_token
22
+ load["token"]
23
+ end
24
+
25
+ def save_token(token)
26
+ raise ArgumentError, "token is required" if token.to_s.empty?
27
+
28
+ FileUtils.mkdir_p(config_dir)
29
+ File.write(config_path, JSON.pretty_generate("token" => token))
30
+ File.chmod(0o600, config_path)
31
+ end
32
+
33
+ def clear
34
+ File.delete(config_path) if File.exist?(config_path)
35
+ end
36
+
37
+ def load
38
+ return {} unless File.exist?(config_path)
39
+
40
+ JSON.parse(File.read(config_path))
41
+ rescue JSON::ParserError
42
+ raise InvalidConfigError, "Invalid config file at #{config_path}"
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Waves
4
+ class Error < StandardError; end
5
+ class InvalidConfigError < Error; end
6
+ class AuthenticationError < Error; end
7
+ class AuthorizationError < Error; end
8
+ class NotFoundError < Error; end
9
+ class RateLimitError < Error; end
10
+ class APIError < Error; end
11
+ class ConnectionError < Error; end
12
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Waves
4
+ module Request
5
+ module_function
6
+
7
+ def compact_hash(hash)
8
+ hash.each_with_object({}) do |(key, value), compacted|
9
+ compacted[key] = value unless value.nil?
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Waves
4
+ VERSION = "0.1.0"
5
+ end
data/lib/waves.rb ADDED
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "fileutils"
4
+
5
+ require_relative "waves/config"
6
+ require_relative "waves/errors"
7
+ require_relative "waves/request"
8
+ require_relative "waves/version"
9
+ require_relative "waves/client"
10
+ require_relative "waves/cli"
11
+
12
+ module Waves
13
+ class << self
14
+ attr_accessor :timeout
15
+ end
16
+
17
+ self.timeout = 10
18
+ end
@@ -0,0 +1,23 @@
1
+ require_relative "lib/waves/version"
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "waves-ruby"
5
+ spec.version = Waves::VERSION
6
+ spec.authors = ["Avi Flombaum"]
7
+ spec.email = ["git@avi.nyc"]
8
+ spec.summary = "Ruby API client and CLI for the Wave API"
9
+ spec.description = "A small Ruby API client and CLI for working with the Wave API."
10
+ spec.homepage = "https://github.com/aviflombaum/waves-gems"
11
+ spec.license = "MIT"
12
+ spec.required_ruby_version = ">= 3.2"
13
+
14
+ spec.metadata["source_code_uri"] = spec.homepage
15
+ spec.metadata["changelog_uri"] = "#{spec.homepage}/releases/tag/v#{spec.version}"
16
+
17
+ spec.files = Dir["*.md", "*.gemspec", "exe/*", "lib/**/*.rb"]
18
+ spec.bindir = "exe"
19
+ spec.executables = ["waves"]
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_dependency "httparty"
23
+ end
metadata ADDED
@@ -0,0 +1,70 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: waves-ruby
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Avi Flombaum
8
+ bindir: exe
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: httparty
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '0'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '0'
26
+ description: A small Ruby API client and CLI for working with the Wave API.
27
+ email:
28
+ - git@avi.nyc
29
+ executables:
30
+ - waves
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - CONTRIBUTING.md
35
+ - README.md
36
+ - exe/waves
37
+ - lib/waves.rb
38
+ - lib/waves/cli.rb
39
+ - lib/waves/cli/app.rb
40
+ - lib/waves/cli/formatter.rb
41
+ - lib/waves/client.rb
42
+ - lib/waves/config.rb
43
+ - lib/waves/errors.rb
44
+ - lib/waves/request.rb
45
+ - lib/waves/version.rb
46
+ - waves-ruby.gemspec
47
+ homepage: https://github.com/aviflombaum/waves-gems
48
+ licenses:
49
+ - MIT
50
+ metadata:
51
+ source_code_uri: https://github.com/aviflombaum/waves-gems
52
+ changelog_uri: https://github.com/aviflombaum/waves-gems/releases/tag/v0.1.0
53
+ rdoc_options: []
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '3.2'
61
+ required_rubygems_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ requirements: []
67
+ rubygems_version: 4.0.6
68
+ specification_version: 4
69
+ summary: Ruby API client and CLI for the Wave API
70
+ test_files: []