All of the window[API_NAME] stuff looks unnecessary to me. You should be able to simply do:
// Access API with Method 1
import "your-package-name";
if (SomeAPIv0) SomeAPIv0.doSomething()
As that’s the whole point of making a global declaration. See Obsidian’s API typings, which include globals like this:
declare global {
function fish(selector: string): HTMLElement | null;
}
This is then exposed by Obsidian as:
window.fish = function(e) {
return document.querySelector(e)
}
Any plugin can call the fish function, and if you type fish into VSCode in a Typescript module that imports obsidian, you will see typings and completion for it.
This is literally all you have to do in order to access APIs exposed as globals.
With regard to the idea of adding an extra pluginAPI to the global namespace, I don’t really see the point, since “pollution” is trivial to avoid by convention. If every plugin doing this includes APIv and a number, then there can only be a collision if two plugins choose the same name for their API.
As a practical matter, though, if you want to have more stringent naming requirements, while still making your API easy to use, you can add an index.ts to your plugin like this:
declare global {
interface Window {
["my.api.v0"]?: MyAPI
}
}
export function getMyAPI() {
return window["my.api.v0"];
}
And others would use it like this:
import {getMyAPI} from "your-package-name";
const myAPI = getMyAPI();
if (myAPI) myAPI.doSomething();
…with the versioning being determined by the version of “your-package-name” they added to their project. (Though you could also expose multiple version-specific accessor functions, or wrapper functions that get the API and call methods on it or throw an exception if the API isn’t there, or aysnc wrapper functions that wait for the plugin to be loaded… any number of interfacing possibilities are possible here.)
The index.ts would be built using typescript to generate an index.js (which you would list as the main in package.json), and an index.d.ts with exposed typings. (So index.ts should also export type for any types needed to use the exposed API.)
The plugin would still place the object in window under a unique key, but other plugins don’t have to care about that.
In fact, with this approach, you can use any method you like for globally exposing and retrieving the API instance, since the method of access is provided by (and concealed in) the npm package.
Basically, though, the ideal state is to make it so others can consume your plugin’s API just by importing it from an npm package, without any special overhead or ceremony other than checking to make sure the API is actually available at the time of calling.
It just means you have to add an index.ts with any wrapper functions and type declarations, build index.js and index.d.ts from it, and list those in the package.json when you publish the project to npm. (And of course, take care with your API versioning, package versioning, etc. to keep disruption to a minimum.)