PhoenixKitDocumentCreator.GoogleDocsClient.DriveWalker (PhoenixKitDocumentCreator v0.2.8)

Copy Markdown View Source

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.

Summary

Functions

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

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 a folder tree starting at root_folder_id.

Types

folder_entry()

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

folder_index()

@type folder_index() :: %{optional(String.t()) => folder_entry()}

Functions

list_files(folder_id)

@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(folder_id)

@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(root_folder_id, opts \\ [])

@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).