/** * @file * * Installs a demo vault's **injected community plugins** headlessly, by downloading * their published GitHub release assets straight into * `demo-vault/.obsidian/plugins//`. * * `buildDemoVaultPopulate` requires each injected plugin's `main.js` / * `manifest.json` to already be on disk, and throws when they are not. Until this * module existed the only documented remedy was a **GUI step** — open `demo-vault/` * in Obsidian once and let `demo-vault-helper` install the plugin at runtime. * `.obsidian/plugins/*` is gitignored in a plugin repo, so that state * exists on exactly the one machine that did it and is invisible to a fresh clone, * a new machine, or CI. Since a plugin repo's release preflight runs its * integration tests, that made *cutting a release from a clean clone* impossible * without a human opening a GUI. * * Downloading the release assets is the exact headless equivalent: the resulting * folder is what Obsidian itself would have installed, so the shipped * `*-demo-vault.zip` — which unzips into a single `*-demo-vault-` folder — * stays the standard demo-vault artifact. * * Two entry points, plus the `bootstrap-demo-vault` CLI subcommand: * * - {@link bootstrapDemoVaultPlugins} — install the missing ones, explicitly. * - {@link buildDemoVaultPopulateAsync} — do that and then build the populate map, * so a global setup self-heals with no manual step at all. * * The sync `buildDemoVaultPopulate` deliberately keeps throwing: `fetch` has no * synchronous form, so auto-healing can only live on an async sibling. Its message * now names both remedies above instead of the GUI step. */ import type { BuildDemoVaultPopulateParams, InjectPluginParams } from './demo-vault-populate.cjs'; import type { PopulateFilesParams } from './temporary-vault.cjs'; /** * Parameters for {@link bootstrapDemoVaultPlugins}. */ export interface BootstrapDemoVaultPluginsParams { /** Absolute path to the plugin repo's `demo-vault/` directory. */ readonly demoVaultPath: string; /** * The injected plugins to install — the same list passed to `buildDemoVaultPopulate`. Plugins whose * binaries are already present are skipped (unless {@link BootstrapDemoVaultPluginsParams.shouldForce}), * as are plugins carrying an explicit `sourceDirectory`. */ readonly injectPlugins: readonly InjectPluginParams[]; /** * Whether to re-download plugins that are already installed, replacing them with the current release. * Defaults to `false` — the normal path installs only what is missing, so a warm checkout does no * network I/O at all. */ readonly shouldForce?: boolean | undefined; } /** * The outcome of a {@link bootstrapDemoVaultPlugins} run. */ export interface BootstrapDemoVaultPluginsResult { /** The plugins that were downloaded and written, in the order they were installed. */ readonly installed: readonly InstalledPluginInfo[]; /** The ids of plugins left untouched — already installed, or opted out via an explicit `sourceDirectory`. */ readonly skippedPluginIds: readonly string[]; } /** * Parameters for {@link buildDemoVaultPopulateAsync} — the same bag {@link buildDemoVaultPopulate} takes, * under the name the asynchronous builder derives. * * One declaration serves both builders. It keeps the synchronous builder's name, and this alias gives the * asynchronous one its own, so neither has to be spelled after the other. */ export type BuildDemoVaultPopulateAsyncParams = BuildDemoVaultPopulateParams; /** * One plugin installed by {@link bootstrapDemoVaultPlugins}. */ export interface InstalledPluginInfo { /** The asset file names actually written, e.g. `['main.js', 'manifest.json', 'styles.css']`. */ readonly assetNames: readonly string[]; /** The plugin's id. */ readonly pluginId: string; /** The GitHub repository the assets came from, as `owner/name`. */ readonly repo: string; /** The release tag downloaded from, or `undefined` when the repository's latest release was used. */ readonly version: string | undefined; } /** * Installs every injected community plugin whose built files are missing from the demo vault, by * downloading its published release assets into `demo-vault/.obsidian/plugins//`. * * Each plugin's repository comes from its {@link InjectPluginParams.repo} when given, otherwise from * Obsidian's own community plugin registry — the same `id` → `repo` table the in-app community browser * installs from, so no plugin-specific mapping is hardcoded. * * @param params - The {@link BootstrapDemoVaultPluginsParams}. * @returns What was installed and what was skipped. * @throws Error if a plugin's repository cannot be resolved, or a required asset cannot be downloaded. */ export declare function bootstrapDemoVaultPlugins(params: BootstrapDemoVaultPluginsParams): Promise; /** * The self-healing counterpart of `buildDemoVaultPopulate`: installs any injected community plugin whose * binaries are missing (see {@link bootstrapDemoVaultPlugins}), then builds the populate map exactly as the * synchronous builder does. * * Use this from a global setup's `populate` thunk — both the Vitest and Jest adapters accept a thunk * returning a promise — so a fresh clone, a new machine, or CI needs no manual install step. * * @param params - The same bag the synchronous builder takes, as {@link BuildDemoVaultPopulateAsyncParams}. * @returns The populate map, ready to hand to a global setup's `populate` or `TemporaryVault.populate`. */ export declare function buildDemoVaultPopulateAsync(params: BuildDemoVaultPopulateAsyncParams): Promise;