How can I access files within my plugin folder

I am trying to access a file within my plugin folder. It looks like I’m getting the correct filePath as the console spits out filePath: .obsidian/plugins/obsidian-sample-plugin/data.json

However, when I try to see the file, it returns null

Here is my code

let basePath;
  let path;

  if (this.app.vault.adapter instanceof FileSystemAdapter) {
    basePath = this.app.vault.adapter.getBasePath();
  } else {
    throw new Error(`Cannot determine base path`);
  }

  // path to data
  path = `${this.app.vault.configDir}/plugins/obsidian-sample-plugin/data.json`;

  let file = this.app.vault.getAbstractFileByPath(path);
  console.log(`filePath: ${path}`)
  console.log(`file: ${file}`);

The end goal is to be able to access my data.json. Is there a different way to be able to access this file?

Additionally, I have been able to access the file if I put the data.json file in the Vault, updating the path, then using getAbstractFileByPath. But I don’t love this workaround.

Moved to “Developers & API”

There is the loadData function for accessing the data.json file.
Take a look at the code of the sample plugin.

I am using the following method to read the file :

	dataFilePath = path.join(
		(window as any).app.vault.adapter.basePath,
		".obsidian",
		"plugins",
		"sample-plugin",
		"data.json"
	);

	export const loadGlobalSettings = () => {
		try {
			const settingsData = fs.readFileSync(dataFilePath, "utf8");
			return JSON.parse(settingsData);
		} catch (error) {
			console.error("Error loading globalSettings:", error);
			return {};
		}
	};

	const data = loadGlobalSettings();

I guess getAbstractFileByPath is only for reading markdown file or files within the vault.

Your code has a couple of problems:

  • as any cast
  • Accessing the app variable from window instead of using the plugin instance.
  • Using the path and fs libraries, these are desktop only.
  • Hardcoding .obsidian, the folder path can be changed in the settings of Obsidian.

And using / is correct when using Obsidian API’s, it’s the same on all platforms.

All of the above can be avoided if you just take a look at the same plugin and the loadSettings and saveSettings functions.
Those save the settings object data into the data.json file.

Ohh ! My bad for overlooking at the mistakes. I used the window long back and forgot to change them in few places in my codebase, ill pass the plugin instance from now on.

About the .obsidian hardcoded folder path, I wasnt aware of such a setting in the Obisidian for changing the name of the config folder. Thank you for mentioning that. Same with the feature that / works on all platforms.

And for the fs and path libraries, I am using my custom hidden folders, hence used them. Will there be any problem if i use those libraries to read data from this hidden folder?

Now coming to the last issue of using the libraries instead of the prebuilt functions. The prebuilt function loadSettings, i am using this in my code, but it seems to be only running when Obsidian Starts, after that, if user makes any changes in my plugin’s SettingsTab and if i try to access the setting using plugin.settings.value, i only get the older values of setting which was loaded at the start of Obsidian. I have elaborated this in detail in my following question : Best Method to access the latest plugin setting values

To access hidden folders across different systems use the Adapter class:
this.app.vault.adapter.read(yourFolderPath)

For the last one, that’s not how it’s supposed to work, I answered in that thread.

1 Like

Hi.

I would like to use yaml config files to make my plugin scalable so I can add easily new providers and fix provider structure when required (AI chats providers).

I created a bunch of yaml files in .obsidian/nexus-ai-chat-provider/providers folder.

What I’m trying to achieve is:

  1. List the yaml files in that folder (to create the list of providers)
  2. read the yaml files to identify the provider based on file uploaded by user.

So my question is simpler than all that:

I get correct value for ${this.manifest.dir}/providers: .obisidian/nexus-ai-chat-importer/providers

But I’m unable to list and read the yaml files.

How can I do that ?

this.app.vault.adapter.read(yourFolderPath) returns "EISDIR: Illegal operation on a directory, read

The value you are showing is not the correct one, looks like you made a few typos in this part: .obisidian/nexus-ai-chat-importer/providers, it should be : .obsidian/plugins/nexus-ai-chat-importer/providers

Those files won’t be downloaded when installing / updating your plugin anyway, so you need to bundle that information into your main.js

read() is the wrong operation. You need list()

Indeed it’s a typo.

I have found a solution. What I understand on what you say is the yaml files need to be created by main.js. ok I’ll do that. Tx for the heads up.

As per the solution, this is what works:

    async getProvidersFiles(folderPath: string): Promise<string[]> {
        const folderContent = await this.app.vault.adapter.list(folderPath);

        try {
            const filesInFolder = folderContent.files;

            // Check if filesInFolder is valid
            if (Array.isArray(filesInFolder)) {
                // Filter for YAML files and map to return only their names
                return filesInFolder.filter((file) => file.endsWith(".yaml"));
            } else {
                throw new Error(
                    `The result from the FileSystemAdapter is not valid for folder path '${folderPath}'.`
                );
            }
        } catch (error) {
            // Handle errors from adapter.list and any other unexpected errors
            throw new Error(
                `Failed to retrieve files from '${folderPath}': ${error.message}`
            );
        }

This will get the list of files in the plugin folder, and then remove any entry which is not a yaml file.

exactly what I was looking for.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.