toc_doc 1.0.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.
data/README.md ADDED
@@ -0,0 +1,370 @@
1
+ # TocDoc
2
+
3
+ A Ruby gem for interacting with the (unofficial) Doctolib API. A thin, Faraday-based client with modular resource endpoints, configurable defaults, optional auto-pagination, and a clean error hierarchy.
4
+
5
+ > **Heads-up:** Doctolib™ does not publish a public API. This gem reverse-engineers
6
+ > the endpoints used by the Doctolib™ website. Behaviour may change at any time
7
+ > without notice. This project is for entertainment purposes only.
8
+ > Doctolib is a trademark of Doctolib. This project is not affiliated with,
9
+ > endorsed by, or sponsored by Doctolib.
10
+
11
+ ---
12
+
13
+ ## Contents
14
+
15
+ 1. [Installation](#installation)
16
+ 2. [Quick start](#quick-start)
17
+ 3. [Configuration](#configuration)
18
+ - [Module-level](#module-level-configuration)
19
+ - [Per-client](#per-client-configuration)
20
+ - [All options](#all-configuration-options)
21
+ - [ENV variables](#environment-variable-overrides)
22
+ 4. [Endpoints](#endpoints)
23
+ - [Availabilities](#availabilities)
24
+ 5. [Response objects](#response-objects)
25
+ 6. [Pagination](#pagination)
26
+ 7. [Error handling](#error-handling)
27
+ 8. [Development](#development)
28
+ - [Generating documentation](#generating-documentation)
29
+ 9. [Contributing](#contributing)
30
+ 10. [Code of Conduct](#code-of-conduct)
31
+ 11. [License](#license)
32
+
33
+ ---
34
+
35
+ ## Installation
36
+
37
+ Add the gem to your `Gemfile`:
38
+
39
+ ```ruby
40
+ gem 'toc_doc'
41
+ ```
42
+
43
+ then run:
44
+
45
+ ```bash
46
+ bundle install
47
+ ```
48
+
49
+ or install it directly:
50
+
51
+ ```bash
52
+ gem install toc_doc
53
+ ```
54
+
55
+ ---
56
+
57
+ ## Quick start
58
+
59
+ ```ruby
60
+ require 'toc_doc'
61
+
62
+ # Use the pre-configured module-level client …
63
+ response = TocDoc.availabilities(
64
+ visit_motive_ids: 7_767_829,
65
+ agenda_ids: 1_101_600,
66
+ practice_ids: 377_272,
67
+ telehealth: false
68
+ )
69
+
70
+ response.total # => 5
71
+ response.next_slot # => "2026-02-28T10:00:00.000+01:00"
72
+
73
+ response.availabilities.each do |avail|
74
+ puts "#{avail.date}: #{avail.slots.join(', ')}"
75
+ end
76
+ ```
77
+
78
+ ---
79
+
80
+ ## Configuration
81
+
82
+ ### Module-level configuration
83
+
84
+ Set options once at startup and every subsequent call will share them:
85
+
86
+ ```ruby
87
+ TocDoc.configure do |config|
88
+ config.api_endpoint = 'https://www.doctolib.de' # target country
89
+ config.per_page = 10
90
+ end
91
+
92
+ TocDoc.availabilities(visit_motive_ids: 123, agenda_ids: 456)
93
+ ```
94
+
95
+ Calling `TocDoc.reset!` restores all options to their defaults.
96
+ Use `TocDoc.options` to inspect the current configuration hash.
97
+
98
+ ### Per-client configuration
99
+
100
+ Instantiate independent clients with different options:
101
+
102
+ ```ruby
103
+ de_client = TocDoc::Client.new(api_endpoint: 'https://www.doctolib.de')
104
+ it_client = TocDoc::Client.new(api_endpoint: 'https://www.doctolib.it', per_page: 3)
105
+
106
+ de_client.availabilities(visit_motive_ids: 123, agenda_ids: 456)
107
+ it_client.availabilities(visit_motive_ids: 789, agenda_ids: 101)
108
+ ```
109
+
110
+ ### All configuration options
111
+
112
+ | Option | Default | Description |
113
+ |---|---|---|
114
+ | `api_endpoint` | `https://www.doctolib.fr` | Base URL. Change to `.de` / `.it` for other countries. |
115
+ | `user_agent` | `TocDoc Ruby Gem 0.1.0` | `User-Agent` header sent with every request. |
116
+ | `default_media_type` | `application/json` | `Accept` and `Content-Type` headers. |
117
+ | `per_page` | `5` | Default number of results returned per request, platform's max is currently at `15`. |
118
+ | `auto_paginate` | `false` | When `true`, automatically fetches all pages and merges results. |
119
+ | `middleware` | Retry + RaiseError + JSON + adapter | Full Faraday middleware stack. Override to customise completely. |
120
+ | `connection_options` | `{}` | Options passed directly to `Faraday.new`. |
121
+
122
+ ### Environment variable overrides
123
+
124
+ All primary options can be set via environment variables before the gem is loaded:
125
+
126
+ | Variable | Option |
127
+ |---|---|
128
+ | `TOCDOC_API_ENDPOINT` | `api_endpoint` |
129
+ | `TOCDOC_USER_AGENT` | `user_agent` |
130
+ | `TOCDOC_MEDIA_TYPE` | `default_media_type` |
131
+ | `TOCDOC_PER_PAGE` | `per_page` |
132
+ | `TOCDOC_AUTO_PAGINATE` | `auto_paginate` (`"true"` / anything else) |
133
+ | `TOCDOC_RETRY_MAX` | Maximum Faraday retry attempts (default `3`) |
134
+
135
+ ---
136
+
137
+ ## Endpoints
138
+
139
+ ### Availabilities
140
+
141
+ Retrieve open appointment slots for a given visit motive and agenda.
142
+
143
+ ```ruby
144
+ client.availabilities(
145
+ visit_motive_ids: visit_motive_id, # Integer, String, or Array
146
+ agenda_ids: agenda_id, # Integer, String, or Array
147
+ start_date: Date.today, # Date or String (default: today)
148
+ limit: 5, # override per_page for this call
149
+ # any extra keyword args are forwarded verbatim as query params:
150
+ practice_ids: 377_272,
151
+ telehealth: false
152
+ )
153
+ ```
154
+
155
+ **Multiple IDs** are accepted as arrays; the gem serialises them with the
156
+ dash-separated format Doctolib expects:
157
+
158
+ ```ruby
159
+ client.availabilities(
160
+ visit_motive_ids: [7_767_829, 7_767_830],
161
+ agenda_ids: [1_101_600, 1_101_601]
162
+ )
163
+ # → GET /availabilities.json?visit_motive_ids=7767829-7767830&agenda_ids=1101600-1101601&…
164
+ ```
165
+
166
+ **Return value:** a `TocDoc::Response::Availability` (see [Response objects](#response-objects)).
167
+
168
+ ---
169
+
170
+ ## Response objects
171
+
172
+ All API responses are wrapped in lightweight Ruby objects that provide
173
+ dot-notation access and a `#to_h` round-trip helper.
174
+
175
+ ### `TocDoc::Response::Availability`
176
+
177
+ Returned by `#availabilities`.
178
+
179
+ | Method | Type | Description |
180
+ |---|---|---|
181
+ | `#total` | `Integer` | Total number of available slots across all dates. |
182
+ | `#next_slot` | `String \| nil` | ISO 8601 datetime of the nearest available slot. `nil` when none remain. |
183
+ | `#availabilities` | `Array<TocDoc::Availability>` | One entry per date. |
184
+ | `#to_h` | `Hash` | Plain-hash representation including expanded availability entries. |
185
+
186
+ ### `TocDoc::Availability`
187
+
188
+ Each element of `Response::Availability#availabilities`.
189
+
190
+ | Method | Type | Description |
191
+ |---|---|---|
192
+ | `#date` | `String` | Date in `YYYY-MM-DD` format. |
193
+ | `#slots` | `Array<String>` | ISO 8601 datetimes for each bookable slot on that date. |
194
+ | `#to_h` | `Hash` | Plain-hash representation. |
195
+
196
+ **Example:**
197
+
198
+ ```ruby
199
+ response = TocDoc.availabilities(visit_motive_ids: 123, agenda_ids: 456)
200
+
201
+ response.total # => 5
202
+ response.next_slot # => "2026-02-28T10:00:00.000+01:00"
203
+
204
+ response.availabilities.first.date # => "2026-02-28"
205
+ response.availabilities.first.slots # => ["2026-02-28T10:00:00.000+01:00", ...]
206
+
207
+ response.to_h
208
+ # => {
209
+ # "total" => 5,
210
+ # "next_slot" => "2026-02-28T10:00:00.000+01:00",
211
+ # "availabilities" => [{ "date" => "2026-02-28", "slots" => [...] }, ...]
212
+ # }
213
+ ```
214
+
215
+ ---
216
+
217
+ ## Pagination
218
+
219
+ The Doctolib availability endpoint is paginated by `start_date` and `limit`.
220
+ TocDoc can manage this automatically.
221
+
222
+ ### Automatic pagination
223
+
224
+ Set `auto_paginate: true` on the client (or at module level) to fetch all pages
225
+ and have results merged into a single `Response::Availability` object:
226
+
227
+ ```ruby
228
+ client = TocDoc::Client.new(auto_paginate: true, per_page: 5)
229
+
230
+ all_slots = client.availabilities(
231
+ visit_motive_ids: 7_767_829,
232
+ agenda_ids: 1_101_600,
233
+ start_date: Date.today
234
+ )
235
+
236
+ all_slots.total # total across every page
237
+ all_slots.availabilities # every date entry, concatenated
238
+ ```
239
+
240
+ Pagination stops automatically when the API returns `next_slot: null`.
241
+
242
+ ### Module-level toggle
243
+
244
+ ```ruby
245
+ TocDoc.configure { |c| c.auto_paginate = true }
246
+
247
+ TocDoc.availabilities(visit_motive_ids: 123, agenda_ids: 456)
248
+ ```
249
+
250
+ ---
251
+
252
+ ## Error handling
253
+
254
+ All errors raised by TocDoc inherit from `TocDoc::Error < StandardError`,
255
+ so you can rescue the whole hierarchy with a single clause:
256
+
257
+ ```ruby
258
+ begin
259
+ TocDoc.availabilities(visit_motive_ids: 0, agenda_ids: 0)
260
+ rescue TocDoc::Error => e
261
+ puts "Doctolib error: #{e.message}"
262
+ end
263
+ ```
264
+
265
+ The default middleware stack also includes `Faraday::Response::RaiseError` for
266
+ HTTP-level failures, and a `Faraday::Retry::Middleware` that automatically
267
+ retries (up to 3 times, with exponential back-off) on:
268
+
269
+ - `429 Too Many Requests`
270
+ - `500 Internal Server Error`
271
+ - `502 Bad Gateway`
272
+ - `503 Service Unavailable`
273
+ - `504 Gateway Timeout`
274
+ - network timeouts
275
+
276
+ ---
277
+
278
+ ## Development
279
+
280
+ Clone the repository and install dependencies:
281
+
282
+ ```bash
283
+ git clone https://github.com/01max/toc_doc.git
284
+ cd toc_doc
285
+ bin/setup
286
+ ```
287
+
288
+ Run the test suite:
289
+
290
+ ```bash
291
+ bundle exec rake spec
292
+ # or
293
+ bundle exec rspec
294
+ ```
295
+
296
+ Run the linter:
297
+
298
+ ```bash
299
+ bundle exec rubocop
300
+ ```
301
+
302
+ Open an interactive console with the gem loaded:
303
+
304
+ ```bash
305
+ bin/console
306
+ ```
307
+
308
+ Install the gem locally:
309
+
310
+ ```bash
311
+ bundle exec rake install
312
+ ```
313
+
314
+ ### Adding new endpoints
315
+
316
+ 1. Create `lib/toc_doc/client/<resource>.rb` and define a module
317
+ `TocDoc::Client::<Resource>` with your endpoint methods.
318
+ 2. Call `get`/`post`/`paginate` (from `TocDoc::Connection`) to issue requests.
319
+ 3. Create `lib/toc_doc/models/response/<resource>.rb` (and any model classes)
320
+ inheriting from `TocDoc::Resource`.
321
+ 4. Include the new module in `TocDoc::Client` (`lib/toc_doc/client.rb`).
322
+ 5. Add corresponding specs under `spec/toc_doc/client/`.
323
+
324
+ ### Generating documentation
325
+
326
+ The codebase uses [YARD](https://yardoc.org/) for API documentation. All public
327
+ methods are annotated with `@param`, `@return`, and `@example` tags.
328
+
329
+ Generate the HTML docs:
330
+
331
+ ```bash
332
+ bundle exec yard doc
333
+ ```
334
+
335
+ The output is written to `doc/`. To browse it locally:
336
+
337
+ ```bash
338
+ bundle exec yard server
339
+ # → http://localhost:8808
340
+ ```
341
+
342
+ To check documentation coverage without generating files:
343
+
344
+ ```bash
345
+ bundle exec yard stats
346
+ ```
347
+
348
+ ---
349
+
350
+ ## Contributing
351
+
352
+ Bug reports and pull requests are welcome on GitHub at
353
+ <https://github.com/01max/toc_doc>. This project is intended to be a safe,
354
+ welcoming space for collaboration, and contributors are expected to adhere to
355
+ the [code of conduct](https://github.com/01max/toc_doc/blob/main/CODE_OF_CONDUCT.md).
356
+
357
+ ---
358
+
359
+ ## Code of Conduct
360
+
361
+ Everyone interacting in the TocDoc project's codebases, issue trackers, chat
362
+ rooms and mailing lists is expected to follow the
363
+ [code of conduct](https://github.com/01max/toc_doc/blob/main/CODE_OF_CONDUCT.md).
364
+
365
+ ---
366
+
367
+ ## License
368
+
369
+ The gem is available as open source under the terms of the
370
+ [GNU General Public v3 License](LICENSE.md).
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ require 'rubocop/rake_task'
9
+
10
+ RuboCop::RakeTask.new
11
+
12
+ task default: %i[spec rubocop]
data/TODO.md ADDED
@@ -0,0 +1,77 @@
1
+ # 1.0
2
+
3
+ ## 1 – Skeleton & Tooling
4
+ - [x] Scaffold gem & layout
5
+ - [x] Gem spec metadata & deps
6
+ - [x] Lib structure (default/config/client/etc.)
7
+ - [x] CI workflow (RSpec + RuboCop)
8
+ - [x] RSpec + WebMock + VCR setup
9
+
10
+ ## 2 – Configuration
11
+ - [x] Default options & ENV fallbacks
12
+ - [x] Configurable module (keys, reset, options)
13
+ - [x] Top-level TocDoc wiring (client, setup, delegation)
14
+ - [x] Config specs (module + client)
15
+
16
+ ## 3 – Connection & HTTP
17
+ - [x] Connection module (agent, request helpers)
18
+ - [x] ~Faraday middleware~
19
+ - [x] URL building helpers
20
+ - [x] Connection specs
21
+
22
+ ## 4 – Error Handling
23
+ - [x] Error base class & factory
24
+ - [x] Error subclasses (4xx/5xx)
25
+ - [x] RaiseError middleware
26
+ - [x] Error mapping specs
27
+
28
+ ## 5 – Client & Availabilities
29
+ - [x] Client includes config + connection
30
+ - [x] Availabilities endpoint module
31
+ - [x] TocDoc.availabilities delegation
32
+ - [x] Availabilities specs (stubs/VCR)
33
+
34
+ ## 6 – Response Objects
35
+ - [x] Resource wrapper
36
+ - [x] Availability objects
37
+ - [x] Client mapping to response objects
38
+ - [x] Response specs
39
+
40
+ ## 8 – Pagination
41
+ - [x] Analyze pagination model
42
+ - [x] Implement Connection#paginate
43
+ - [x] Pagination config & specs
44
+
45
+ ## 9 – Docs & Release
46
+ - [x] README
47
+ - [x] YARD docs
48
+ - [x] CHANGELOG
49
+ - [x] FIX GH CI
50
+ - [ ] Build & publish gem
51
+ - [ ] on rubygem
52
+ - [ ] gem.coop ?
53
+
54
+ # 1.1
55
+
56
+ ## Parse raw API data
57
+ - [ ] Parse date / datetime
58
+ - [ ] ?
59
+
60
+ ## Better API usage
61
+ - [ ] Rate limiting
62
+ - [ ] Caching
63
+ - [ ] Logging
64
+ - [ ] Better multi-region support ?
65
+ - [ ] Async support ?
66
+
67
+ ## Extra Endpoints
68
+ - [ ] Identify additional endpoints
69
+ - [ ] Implement resource modules
70
+ - [ ] Specs per endpoint
71
+
72
+ # 1.2
73
+
74
+ ## Auth / User-based actions
75
+ - [ ] Research auth scheme
76
+ - [ ] Authentication module + headers
77
+ - [ ] Auth specs
@@ -0,0 +1,118 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'date'
4
+
5
+ module TocDoc
6
+ class Client
7
+ # Endpoint module for the Doctolib availabilities API.
8
+ #
9
+ # Included into {TocDoc::Client}; methods delegate to
10
+ # {TocDoc::Connection#get} via the enclosing client instance.
11
+ #
12
+ # @see https://www.doctolib.fr/availabilities.json Doctolib availability endpoint
13
+ module Availabilities
14
+ # Returns available appointment slots for the given visit motives and
15
+ # agendas.
16
+ #
17
+ # When +auto_paginate+ is enabled, all pages of results are
18
+ # fetched and merged automatically.
19
+ #
20
+ # @param visit_motive_ids [Integer, String, Array<Integer>]
21
+ # one or more visit-motive IDs (dash-joined for the API)
22
+ # @param agenda_ids [Integer, String, Array<Integer>]
23
+ # one or more agenda IDs (dash-joined for the API)
24
+ # @param start_date [Date, String]
25
+ # earliest date to search from (default: +Date.today+)
26
+ # @param limit [Integer]
27
+ # maximum number of availability dates per page
28
+ # (default: +per_page+ config)
29
+ # @param options [Hash]
30
+ # additional query params forwarded verbatim to the API
31
+ # (e.g. +practice_ids:+, +telehealth:+)
32
+ # @return [TocDoc::Response::Availability] structured response object
33
+ #
34
+ # @example Fetch availabilities for a single practitioner
35
+ # client.availabilities(
36
+ # visit_motive_ids: 7_767_829,
37
+ # agenda_ids: [1_101_600],
38
+ # practice_ids: 377_272,
39
+ # telehealth: false
40
+ # )
41
+ #
42
+ # @example Via the module-level shortcut
43
+ # TocDoc.availabilities(visit_motive_ids: 123, agenda_ids: 456)
44
+ def availabilities(visit_motive_ids:, agenda_ids:, start_date: Date.today, limit: per_page, **options)
45
+ base_query = build_availability_query(visit_motive_ids, agenda_ids, start_date, limit, options)
46
+
47
+ response = paginate('/availabilities.json', query: base_query) do |acc, last_resp|
48
+ paginate_availability_page(acc, last_resp, base_query)
49
+ end
50
+
51
+ TocDoc::Response::Availability.new(response)
52
+ end
53
+
54
+ private
55
+
56
+ # Builds the query hash sent to the availabilities endpoint.
57
+ #
58
+ # @param visit_motive_ids [Integer, String, Array] raw motive IDs
59
+ # @param agenda_ids [Integer, String, Array] raw agenda IDs
60
+ # @param start_date [Date, String] earliest search date
61
+ # @param limit [Integer] page size
62
+ # @param extra [Hash] additional query params
63
+ # @return [Hash{Symbol => Object}] ready-to-send query hash
64
+ def build_availability_query(visit_motive_ids, agenda_ids, start_date, limit, extra)
65
+ {
66
+ visit_motive_ids: dashed_ids(visit_motive_ids),
67
+ agenda_ids: dashed_ids(agenda_ids),
68
+ start_date: start_date.to_s,
69
+ limit: [limit.to_i, TocDoc::Default::MAX_PER_PAGE].min,
70
+ **extra
71
+ }
72
+ end
73
+
74
+ # Merges the latest page body into the accumulator and returns options
75
+ # for the next page, or +nil+ to halt pagination.
76
+ #
77
+ # On the first yield +acc+ *is* the first-page body (identical object),
78
+ # so the merge step is skipped.
79
+ #
80
+ # @param acc [Hash] growing accumulator
81
+ # @param last_resp [Faraday::Response] the most-recent raw response
82
+ # @param base_query [Hash] the original query hash
83
+ # @return [Hash, nil] options for the next page, or +nil+ to stop
84
+ def paginate_availability_page(acc, last_resp, base_query)
85
+ latest = last_resp.body
86
+
87
+ merge_availability_page(acc, latest) unless acc.equal?(latest)
88
+ availability_next_page_options(latest, base_query)
89
+ end
90
+
91
+ # Merges a new page body into the running accumulator.
92
+ #
93
+ # @param acc [Hash] the accumulator hash
94
+ # @param latest [Hash] the most-recent page body
95
+ # @return [void]
96
+ def merge_availability_page(acc, latest)
97
+ acc['availabilities'] = (acc['availabilities'] || []) + (latest['availabilities'] || [])
98
+ acc['total'] = (acc['total'] || 0) + (latest['total'] || 0)
99
+ acc['next_slot'] = latest['next_slot']
100
+ end
101
+
102
+ # Determines the options for the next page of availabilities, or +nil+
103
+ # if pagination should stop.
104
+ #
105
+ # @param latest [Hash] the most-recent page body
106
+ # @param base_query [Hash] the original query hash
107
+ # @return [Hash, nil] next-page options, or +nil+ to halt
108
+ def availability_next_page_options(latest, base_query)
109
+ avails = latest['availabilities'] || []
110
+ last_date_str = avails.last&.dig('date')
111
+ return unless last_date_str && latest['next_slot']
112
+
113
+ next_start = (Date.parse(last_date_str) + 1).to_s
114
+ { query: base_query.merge(start_date: next_start) }
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'toc_doc/core/configurable'
4
+ require 'toc_doc/core/connection'
5
+ require 'toc_doc/core/uri_utils'
6
+ require 'toc_doc/client/availabilities'
7
+
8
+ module TocDoc
9
+ # The main entry-point for interacting with the Doctolib API.
10
+ #
11
+ # A +Client+ inherits the {TocDoc::Configurable} defaults set at the
12
+ # module level and can override any option per-instance.
13
+ #
14
+ # @example Creating a client with custom options
15
+ # client = TocDoc::Client.new(
16
+ # api_endpoint: 'https://www.doctolib.de',
17
+ # per_page: 5
18
+ # )
19
+ # client.availabilities(visit_motive_ids: 123, agenda_ids: 456)
20
+ #
21
+ # @see TocDoc::Configurable
22
+ # @see TocDoc::Connection
23
+ # @see TocDoc::Client::Availabilities
24
+ class Client
25
+ include TocDoc::Configurable
26
+ include TocDoc::Connection
27
+ include TocDoc::UriUtils
28
+
29
+ include TocDoc::Client::Availabilities
30
+
31
+ # Creates a new client instance.
32
+ #
33
+ # Options are merged on top of the module-level {TocDoc::Default} values.
34
+ # Only keys present in {TocDoc::Configurable.keys} are accepted;
35
+ # unknown keys are silently ignored.
36
+ #
37
+ # @param options [Hash{Symbol => Object}] configuration overrides
38
+ # @option options [String] :api_endpoint Base URL for API requests
39
+ # @option options [String] :user_agent User-Agent header value
40
+ # @option options [String] :default_media_type Accept / Content-Type header
41
+ # @option options [Integer] :per_page Results per page
42
+ # @option options [Boolean] :auto_paginate Follow pagination automatically
43
+ # @option options [Faraday::RackBuilder] :middleware Custom Faraday middleware
44
+ # @option options [Hash] :connection_options Additional Faraday options
45
+ #
46
+ # @example
47
+ # TocDoc::Client.new(api_endpoint: 'https://www.doctolib.it')
48
+ def initialize(options = {})
49
+ reset!
50
+ options.each do |key, value|
51
+ public_send("#{key}=", value) if TocDoc::Configurable.keys.include?(key.to_sym)
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TocDoc
4
+ # Authentication helpers for Doctolib API requests.
5
+ #
6
+ # This module is a placeholder for future authentication support.
7
+ # Doctolib's public availability endpoint does not require authentication;
8
+ # other endpoints (booking, patient data) may need OAuth2 or token-based
9
+ # auth, which will be implemented here.
10
+ #
11
+ # @see TocDoc::Client
12
+ module Authentication
13
+ # Authentication helpers will be implemented in later phases.
14
+ end
15
+ end