# `PhoenixKitDocumentCreator.GoogleDocsClient.DriveWalker`
[🔗](https://github.com/BeamLabEU/phoenix_kit_document_creator/blob/0.2.8/lib/phoenix_kit_document_creator/google_docs_client/drive_walker.ex#L1)

Paginated + recursive Google Drive traversal.

Canonical primitive for listing files and folders. The parent
`PhoenixKitDocumentCreator.GoogleDocsClient` delegates `list_folder_files/1`
and `list_subfolders/1` here so that pagination logic lives in exactly one
place.

The core entry point is `walk_tree/2`, which performs a BFS over a folder
tree and returns:

  * every descendant folder indexed by ID (with its name and human-readable
    path, relative to the root caller supplied), and
  * every Google Doc found in any of those folders, annotated with the
    `folder_id` that contains it and the `path` of that folder.

The walker uses Drive's `in parents` OR-batching for **both** folder
discovery and file listing — one batched request per BFS level instead
of one request per folder, chunked at 40 parent IDs per query to stay
under Drive's query-length limit. All pages are streamed via
`nextPageToken` (the old `pageSize: 100` listing silently dropped data
past the first page). Folder ownership is resolved from each returned
folder's `parents` field.

# `folder_entry`

```elixir
@type folder_entry() :: %{name: String.t(), path: String.t()}
```

# `folder_index`

```elixir
@type folder_index() :: %{optional(String.t()) =&gt; folder_entry()}
```

# `list_files`

```elixir
@spec list_files(String.t()) :: {:ok, [map()]} | {:error, term()}
```

List Google Docs directly in a folder (non-recursive), fully paginated.

Each file map has at minimum `"id"`, `"name"`, `"modifiedTime"`,
`"thumbnailLink"`, and `"parents"`.

# `list_folders`

```elixir
@spec list_folders(String.t()) :: {:ok, [map()]} | {:error, term()}
```

List subfolders of a folder (non-recursive), fully paginated.
Each entry has `"id"` and `"name"`. Results are ordered alphabetically
by name to preserve the folder browser's existing UX.

# `walk_tree`

```elixir
@spec walk_tree(
  String.t(),
  keyword()
) :: {:ok, %{folders: folder_index(), files: [map()]}} | {:error, term()}
```

Walk a folder tree starting at `root_folder_id`.

## Options

  * `:root_path` (string, default `""`) — human-readable path representing
    the root. Descendants get paths computed as `root_path/sub/subsub`.
  * `:max_depth` (int, default `20`) — defensive cap against cycles or
    excessively deep structures. The root is depth 0; children of the root
    are depth 1.

## Return value

    {:ok, %{
      folders: %{folder_id => %{name: name, path: path}, ...},
      files:   [%{"id" => ..., "name" => ..., "folder_id" => parent_id,
                  "path" => folder_path, ...}, ...]
    }}

The returned `folders` index always includes the root folder itself
(with the `:root_path` you supplied as its path).

---

*Consult [api-reference.md](api-reference.md) for complete listing*
