# This file generated by `dagger_codegen`. Please DO NOT EDIT.
defmodule Dagger.Directory do
  @moduledoc """
  A directory.
  """

  use Dagger.Core.Base, kind: :object, name: "Directory"

  alias Dagger.Core.Client
  alias Dagger.Core.QueryBuilder, as: QB

  @derive Dagger.ID
  @derive Dagger.Sync
  defstruct [:query_builder, :client]

  @type t() :: %__MODULE__{}

  @doc """
  Converts this directory to a local git repository
  """
  @spec as_git(t()) :: Dagger.GitRepository.t()
  def as_git(%__MODULE__{} = directory) do
    query_builder =
      directory.query_builder |> QB.select("asGit")

    %Dagger.GitRepository{
      query_builder: query_builder,
      client: directory.client
    }
  end

  @doc """
  Load the directory as a Dagger module source
  """
  @spec as_module(t(), [{:source_root_path, String.t() | nil}]) :: Dagger.Module.t()
  def as_module(%__MODULE__{} = directory, optional_args \\ []) do
    query_builder =
      directory.query_builder
      |> QB.select("asModule")
      |> QB.maybe_put_arg("sourceRootPath", optional_args[:source_root_path])

    %Dagger.Module{
      query_builder: query_builder,
      client: directory.client
    }
  end

  @doc """
  Load the directory as a Dagger module source
  """
  @spec as_module_source(t(), [{:source_root_path, String.t() | nil}]) :: Dagger.ModuleSource.t()
  def as_module_source(%__MODULE__{} = directory, optional_args \\ []) do
    query_builder =
      directory.query_builder
      |> QB.select("asModuleSource")
      |> QB.maybe_put_arg("sourceRootPath", optional_args[:source_root_path])

    %Dagger.ModuleSource{
      query_builder: query_builder,
      client: directory.client
    }
  end

  @doc """
  Return the difference between this directory and another directory, typically an older snapshot.

  The difference is encoded as a changeset, which also tracks removed files, and can be applied to other directories.
  """
  @spec changes(t(), Dagger.Directory.t()) :: Dagger.Changeset.t()
  def changes(%__MODULE__{} = directory, from) do
    query_builder =
      directory.query_builder |> QB.select("changes") |> QB.put_arg("from", Dagger.ID.id!(from))

    %Dagger.Changeset{
      query_builder: query_builder,
      client: directory.client
    }
  end

  @doc """
  Change the owner of the directory contents recursively.
  """
  @spec chown(t(), String.t(), String.t()) :: Dagger.Directory.t()
  def chown(%__MODULE__{} = directory, path, owner) do
    query_builder =
      directory.query_builder
      |> QB.select("chown")
      |> QB.put_arg("path", path)
      |> QB.put_arg("owner", owner)

    %Dagger.Directory{
      query_builder: query_builder,
      client: directory.client
    }
  end

  @doc """
  Return the difference between this directory and an another directory. The difference is encoded as a directory.
  """
  @spec diff(t(), Dagger.Directory.t()) :: Dagger.Directory.t()
  def diff(%__MODULE__{} = directory, other) do
    query_builder =
      directory.query_builder |> QB.select("diff") |> QB.put_arg("other", Dagger.ID.id!(other))

    %Dagger.Directory{
      query_builder: query_builder,
      client: directory.client
    }
  end

  @doc """
  Return the directory's digest. The format of the digest is not guaranteed to be stable between releases of Dagger. It is guaranteed to be stable between invocations of the same Dagger engine.
  """
  @spec digest(t()) :: {:ok, String.t()} | {:error, term()}
  def digest(%__MODULE__{} = directory) do
    query_builder =
      directory.query_builder |> QB.select("digest")

    Client.execute(directory.client, query_builder)
  end

  @doc """
  Retrieves a directory at the given path.
  """
  @spec directory(t(), String.t()) :: Dagger.Directory.t()
  def directory(%__MODULE__{} = directory, path) do
    query_builder =
      directory.query_builder |> QB.select("directory") |> QB.put_arg("path", path)

    %Dagger.Directory{
      query_builder: query_builder,
      client: directory.client
    }
  end

  @doc """
  Use Dockerfile compatibility to build a container from this directory. Only use this function for Dockerfile compatibility. Otherwise use the native Container type directly, it is feature-complete and supports all Dockerfile features.
  """
  @spec docker_build(t(), [
          {:dockerfile, String.t() | nil},
          {:platform, Dagger.Platform.t() | nil},
          {:build_args, [Dagger.BuildArg.t()]},
          {:target, String.t() | nil},
          {:secrets, [Dagger.SecretID.t()]},
          {:no_init, boolean() | nil}
        ]) :: Dagger.Container.t()
  def docker_build(%__MODULE__{} = directory, optional_args \\ []) do
    query_builder =
      directory.query_builder
      |> QB.select("dockerBuild")
      |> QB.maybe_put_arg("dockerfile", optional_args[:dockerfile])
      |> QB.maybe_put_arg("platform", optional_args[:platform])
      |> QB.maybe_put_arg("buildArgs", optional_args[:build_args])
      |> QB.maybe_put_arg("target", optional_args[:target])
      |> QB.maybe_put_arg(
        "secrets",
        if(optional_args[:secrets],
          do: Enum.map(optional_args[:secrets], &Dagger.ID.id!/1),
          else: nil
        )
      )
      |> QB.maybe_put_arg("noInit", optional_args[:no_init])

    %Dagger.Container{
      query_builder: query_builder,
      client: directory.client
    }
  end

  @doc """
  Returns a list of files and directories at the given path.
  """
  @spec entries(t(), [{:path, String.t() | nil}]) :: {:ok, [String.t()]} | {:error, term()}
  def entries(%__MODULE__{} = directory, optional_args \\ []) do
    query_builder =
      directory.query_builder
      |> QB.select("entries")
      |> QB.maybe_put_arg("path", optional_args[:path])

    Client.execute(directory.client, query_builder)
  end

  @doc """
  check if a file or directory exists
  """
  @spec exists(t(), String.t(), [
          {:expected_type, Dagger.ExistsType.t() | nil},
          {:do_not_follow_symlinks, boolean() | nil}
        ]) :: {:ok, boolean()} | {:error, term()}
  def exists(%__MODULE__{} = directory, path, optional_args \\ []) do
    query_builder =
      directory.query_builder
      |> QB.select("exists")
      |> QB.put_arg("path", path)
      |> QB.maybe_put_arg("expectedType", optional_args[:expected_type])
      |> QB.maybe_put_arg("doNotFollowSymlinks", optional_args[:do_not_follow_symlinks])

    Client.execute(directory.client, query_builder)
  end

  @doc """
  Writes the contents of the directory to a path on the host.
  """
  @spec export(t(), String.t(), [{:wipe, boolean() | nil}]) ::
          {:ok, String.t()} | {:error, term()}
  def export(%__MODULE__{} = directory, path, optional_args \\ []) do
    query_builder =
      directory.query_builder
      |> QB.select("export")
      |> QB.put_arg("path", path)
      |> QB.maybe_put_arg("wipe", optional_args[:wipe])

    Client.execute(directory.client, query_builder)
  end

  @doc """
  Retrieve a file at the given path.
  """
  @spec file(t(), String.t()) :: Dagger.File.t()
  def file(%__MODULE__{} = directory, path) do
    query_builder =
      directory.query_builder |> QB.select("file") |> QB.put_arg("path", path)

    %Dagger.File{
      query_builder: query_builder,
      client: directory.client
    }
  end

  @doc """
  Return a snapshot with some paths included or excluded
  """
  @spec filter(t(), [{:exclude, [String.t()]}, {:include, [String.t()]}]) :: Dagger.Directory.t()
  def filter(%__MODULE__{} = directory, optional_args \\ []) do
    query_builder =
      directory.query_builder
      |> QB.select("filter")
      |> QB.maybe_put_arg("exclude", optional_args[:exclude])
      |> QB.maybe_put_arg("include", optional_args[:include])

    %Dagger.Directory{
      query_builder: query_builder,
      client: directory.client
    }
  end

  @doc """
  Search up the directory tree for a file or directory, and return its path. If no match, return null
  """
  @spec find_up(t(), String.t(), String.t()) :: {:ok, String.t() | nil} | {:error, term()}
  def find_up(%__MODULE__{} = directory, name, start) do
    query_builder =
      directory.query_builder
      |> QB.select("findUp")
      |> QB.put_arg("name", name)
      |> QB.put_arg("start", start)

    Client.execute(directory.client, query_builder)
  end

  @doc """
  Returns a list of files and directories that matche the given pattern.
  """
  @spec glob(t(), String.t()) :: {:ok, [String.t()]} | {:error, term()}
  def glob(%__MODULE__{} = directory, pattern) do
    query_builder =
      directory.query_builder |> QB.select("glob") |> QB.put_arg("pattern", pattern)

    Client.execute(directory.client, query_builder)
  end

  @doc """
  A unique identifier for this Directory.
  """
  @spec id(t()) :: {:ok, Dagger.DirectoryID.t()} | {:error, term()}
  def id(%__MODULE__{} = directory) do
    query_builder =
      directory.query_builder |> QB.select("id")

    Client.execute(directory.client, query_builder)
  end

  @doc """
  Returns the name of the directory.
  """
  @spec name(t()) :: {:ok, String.t()} | {:error, term()}
  def name(%__MODULE__{} = directory) do
    query_builder =
      directory.query_builder |> QB.select("name")

    Client.execute(directory.client, query_builder)
  end

  @doc """
  Searches for content matching the given regular expression or literal string.

  Uses Rust regex syntax; escape literal ., [, ], {, }, | with backslashes.
  """
  @spec search(t(), String.t(), [
          {:paths, [String.t()]},
          {:globs, [String.t()]},
          {:literal, boolean() | nil},
          {:multiline, boolean() | nil},
          {:dotall, boolean() | nil},
          {:insensitive, boolean() | nil},
          {:skip_ignored, boolean() | nil},
          {:skip_hidden, boolean() | nil},
          {:files_only, boolean() | nil},
          {:limit, integer() | nil}
        ]) :: {:ok, [Dagger.SearchResult.t()]} | {:error, term()}
  def search(%__MODULE__{} = directory, pattern, optional_args \\ []) do
    query_builder =
      directory.query_builder
      |> QB.select("search")
      |> QB.put_arg("pattern", pattern)
      |> QB.maybe_put_arg("paths", optional_args[:paths])
      |> QB.maybe_put_arg("globs", optional_args[:globs])
      |> QB.maybe_put_arg("literal", optional_args[:literal])
      |> QB.maybe_put_arg("multiline", optional_args[:multiline])
      |> QB.maybe_put_arg("dotall", optional_args[:dotall])
      |> QB.maybe_put_arg("insensitive", optional_args[:insensitive])
      |> QB.maybe_put_arg("skipIgnored", optional_args[:skip_ignored])
      |> QB.maybe_put_arg("skipHidden", optional_args[:skip_hidden])
      |> QB.maybe_put_arg("filesOnly", optional_args[:files_only])
      |> QB.maybe_put_arg("limit", optional_args[:limit])
      |> QB.select("id")

    with {:ok, items} <- Client.execute(directory.client, query_builder) do
      {:ok,
       for %{"id" => id} <- items do
         %Dagger.SearchResult{
           query_builder:
             QB.query()
             |> QB.select("loadSearchResultFromID")
             |> QB.put_arg("id", id),
           client: directory.client
         }
       end}
    end
  end

  @doc """
  Force evaluation in the engine.
  """
  @spec sync(t()) :: {:ok, Dagger.Directory.t()} | {:error, term()}
  def sync(%__MODULE__{} = directory) do
    query_builder =
      directory.query_builder |> QB.select("sync")

    with {:ok, id} <- Client.execute(directory.client, query_builder) do
      {:ok,
       %Dagger.Directory{
         query_builder:
           QB.query()
           |> QB.select("loadDirectoryFromID")
           |> QB.put_arg("id", id),
         client: directory.client
       }}
    end
  end

  @doc """
  Opens an interactive terminal in new container with this directory mounted inside.
  """
  @spec terminal(t(), [
          {:container, Dagger.ContainerID.t() | nil},
          {:cmd, [String.t()]},
          {:experimental_privileged_nesting, boolean() | nil},
          {:insecure_root_capabilities, boolean() | nil}
        ]) :: Dagger.Directory.t()
  def terminal(%__MODULE__{} = directory, optional_args \\ []) do
    query_builder =
      directory.query_builder
      |> QB.select("terminal")
      |> QB.maybe_put_arg("container", optional_args[:container])
      |> QB.maybe_put_arg("cmd", optional_args[:cmd])
      |> QB.maybe_put_arg(
        "experimentalPrivilegedNesting",
        optional_args[:experimental_privileged_nesting]
      )
      |> QB.maybe_put_arg("insecureRootCapabilities", optional_args[:insecure_root_capabilities])

    %Dagger.Directory{
      query_builder: query_builder,
      client: directory.client
    }
  end

  @doc """
  Return a directory with changes from another directory applied to it.
  """
  @spec with_changes(t(), Dagger.Changeset.t()) :: Dagger.Directory.t()
  def with_changes(%__MODULE__{} = directory, changes) do
    query_builder =
      directory.query_builder
      |> QB.select("withChanges")
      |> QB.put_arg("changes", Dagger.ID.id!(changes))

    %Dagger.Directory{
      query_builder: query_builder,
      client: directory.client
    }
  end

  @doc """
  Return a snapshot with a directory added
  """
  @spec with_directory(t(), String.t(), Dagger.Directory.t(), [
          {:exclude, [String.t()]},
          {:include, [String.t()]},
          {:owner, String.t() | nil}
        ]) :: Dagger.Directory.t()
  def with_directory(%__MODULE__{} = directory, path, source, optional_args \\ []) do
    query_builder =
      directory.query_builder
      |> QB.select("withDirectory")
      |> QB.put_arg("path", path)
      |> QB.put_arg("source", Dagger.ID.id!(source))
      |> QB.maybe_put_arg("exclude", optional_args[:exclude])
      |> QB.maybe_put_arg("include", optional_args[:include])
      |> QB.maybe_put_arg("owner", optional_args[:owner])

    %Dagger.Directory{
      query_builder: query_builder,
      client: directory.client
    }
  end

  @doc """
  Retrieves this directory plus the contents of the given file copied to the given path.
  """
  @spec with_file(t(), String.t(), Dagger.File.t(), [
          {:permissions, integer() | nil},
          {:owner, String.t() | nil}
        ]) :: Dagger.Directory.t()
  def with_file(%__MODULE__{} = directory, path, source, optional_args \\ []) do
    query_builder =
      directory.query_builder
      |> QB.select("withFile")
      |> QB.put_arg("path", path)
      |> QB.put_arg("source", Dagger.ID.id!(source))
      |> QB.maybe_put_arg("permissions", optional_args[:permissions])
      |> QB.maybe_put_arg("owner", optional_args[:owner])

    %Dagger.Directory{
      query_builder: query_builder,
      client: directory.client
    }
  end

  @doc """
  Retrieves this directory plus the contents of the given files copied to the given path.
  """
  @spec with_files(t(), String.t(), [Dagger.FileID.t()], [{:permissions, integer() | nil}]) ::
          Dagger.Directory.t()
  def with_files(%__MODULE__{} = directory, path, sources, optional_args \\ []) do
    query_builder =
      directory.query_builder
      |> QB.select("withFiles")
      |> QB.put_arg("path", path)
      |> QB.put_arg("sources", sources)
      |> QB.maybe_put_arg("permissions", optional_args[:permissions])

    %Dagger.Directory{
      query_builder: query_builder,
      client: directory.client
    }
  end

  @doc """
  Retrieves this directory plus a new directory created at the given path.
  """
  @spec with_new_directory(t(), String.t(), [{:permissions, integer() | nil}]) ::
          Dagger.Directory.t()
  def with_new_directory(%__MODULE__{} = directory, path, optional_args \\ []) do
    query_builder =
      directory.query_builder
      |> QB.select("withNewDirectory")
      |> QB.put_arg("path", path)
      |> QB.maybe_put_arg("permissions", optional_args[:permissions])

    %Dagger.Directory{
      query_builder: query_builder,
      client: directory.client
    }
  end

  @doc """
  Return a snapshot with a new file added
  """
  @spec with_new_file(t(), String.t(), String.t(), [{:permissions, integer() | nil}]) ::
          Dagger.Directory.t()
  def with_new_file(%__MODULE__{} = directory, path, contents, optional_args \\ []) do
    query_builder =
      directory.query_builder
      |> QB.select("withNewFile")
      |> QB.put_arg("path", path)
      |> QB.put_arg("contents", contents)
      |> QB.maybe_put_arg("permissions", optional_args[:permissions])

    %Dagger.Directory{
      query_builder: query_builder,
      client: directory.client
    }
  end

  @doc """
  Retrieves this directory with the given Git-compatible patch applied.

  > #### Experimental {: .warning}
  >
  > "This API is highly experimental and may be removed or replaced entirely."
  """
  @spec with_patch(t(), String.t()) :: Dagger.Directory.t()
  def with_patch(%__MODULE__{} = directory, patch) do
    query_builder =
      directory.query_builder |> QB.select("withPatch") |> QB.put_arg("patch", patch)

    %Dagger.Directory{
      query_builder: query_builder,
      client: directory.client
    }
  end

  @doc """
  Retrieves this directory with the given Git-compatible patch file applied.

  > #### Experimental {: .warning}
  >
  > "This API is highly experimental and may be removed or replaced entirely."
  """
  @spec with_patch_file(t(), Dagger.File.t()) :: Dagger.Directory.t()
  def with_patch_file(%__MODULE__{} = directory, patch) do
    query_builder =
      directory.query_builder
      |> QB.select("withPatchFile")
      |> QB.put_arg("patch", Dagger.ID.id!(patch))

    %Dagger.Directory{
      query_builder: query_builder,
      client: directory.client
    }
  end

  @doc """
  Return a snapshot with a symlink
  """
  @spec with_symlink(t(), String.t(), String.t()) :: Dagger.Directory.t()
  def with_symlink(%__MODULE__{} = directory, target, link_name) do
    query_builder =
      directory.query_builder
      |> QB.select("withSymlink")
      |> QB.put_arg("target", target)
      |> QB.put_arg("linkName", link_name)

    %Dagger.Directory{
      query_builder: query_builder,
      client: directory.client
    }
  end

  @doc """
  Retrieves this directory with all file/dir timestamps set to the given time.
  """
  @spec with_timestamps(t(), integer()) :: Dagger.Directory.t()
  def with_timestamps(%__MODULE__{} = directory, timestamp) do
    query_builder =
      directory.query_builder |> QB.select("withTimestamps") |> QB.put_arg("timestamp", timestamp)

    %Dagger.Directory{
      query_builder: query_builder,
      client: directory.client
    }
  end

  @doc """
  Return a snapshot with a subdirectory removed
  """
  @spec without_directory(t(), String.t()) :: Dagger.Directory.t()
  def without_directory(%__MODULE__{} = directory, path) do
    query_builder =
      directory.query_builder |> QB.select("withoutDirectory") |> QB.put_arg("path", path)

    %Dagger.Directory{
      query_builder: query_builder,
      client: directory.client
    }
  end

  @doc """
  Return a snapshot with a file removed
  """
  @spec without_file(t(), String.t()) :: Dagger.Directory.t()
  def without_file(%__MODULE__{} = directory, path) do
    query_builder =
      directory.query_builder |> QB.select("withoutFile") |> QB.put_arg("path", path)

    %Dagger.Directory{
      query_builder: query_builder,
      client: directory.client
    }
  end

  @doc """
  Return a snapshot with files removed
  """
  @spec without_files(t(), [String.t()]) :: Dagger.Directory.t()
  def without_files(%__MODULE__{} = directory, paths) do
    query_builder =
      directory.query_builder |> QB.select("withoutFiles") |> QB.put_arg("paths", paths)

    %Dagger.Directory{
      query_builder: query_builder,
      client: directory.client
    }
  end
end

defimpl Jason.Encoder, for: Dagger.Directory do
  def encode(directory, opts) do
    {:ok, id} = Dagger.Directory.id(directory)
    Jason.Encode.string(id, opts)
  end
end

defimpl Nestru.Decoder, for: Dagger.Directory do
  def decode_fields_hint(_struct, _context, id) do
    {:ok, Dagger.Client.load_directory_from_id(Dagger.Global.dag(), id)}
  end
end
