ResourceLockComponent
A per-plugin handle for path-scoped resource locking (editor read-only, optional vault-mutation blocking, and external-change detection — see the file overview). Add it as a child of your plugin (this.addChild(new ResourceLockComponent(this.app))) so that any locks it still holds are released automatically when the plugin unloads — a resource can never be left stuck locked because the plugin that locked it was disabled or reloaded mid-operation.
Locks are reference-counted and attributed to this plugin, so the lock indicators’ tooltip names it among the plugins currently holding a lock.
Import:
import { ResourceLockComponent } from 'obsidian-dev-utils/obsidian/resource-lock';Signature:
export class ResourceLockComponent extends ComponentExExtends: ComponentEx
Constructor
new ResourceLockComponent(app: App, pluginId: string)Creates an resource-lock handle owned by a plugin.
Properties
| Property | Type | Description |
|---|---|---|
| app | App | The Obsidian app instance. |
| pluginId | string | The id of the owning plugin (e.g. its manifest.id). Locks are attributed to it for reference-counting and the indicators' "locked by" tooltip. |
Methods
| Method | Returns | Description |
|---|---|---|
| [Symbol.dispose]() | void | Disposes of the component. (Inherited from ComponentEx) |
| addChild(component) | TComponent | Adds a child component. Mirrors the native Component.addChild contract: if this component is already loaded, the child is loaded immediately, so child._loaded is set before this method returns even when this component has async load logic. The child's async tail (if any) is sequenced into the load promise so a later loadWithPromises call awaits it.(Inherited from ComponentEx) |
| bypassBlockedMutations(pathsOrFiles) | Disposable | Opens an **ambient bypass scope**: while the returned Disposable is not disposed, this plugin's own mutations of the given paths (and, for a folder, its whole subtree) pass through the mutation blocker instead of throwing ResourceLockedError. Any mutation of a blocked path NOT covered by an active bypass scope is still rejected. Use it with a using declaration around the operation that legitimately mutates resources it has locked with ResourceLockComponentLockForPathParams.shouldBlockMutations:`` ts`` |
| ensureLoaded() | void | Ensures the component is loaded, throwing if it is not. Use this to guard public methods that register teardown-bearing resources (via Component.register, Component.registerEvent, Component.registerDomEvent, etc.). Registering before load is unsafe: Component.unload is a no-op while the component is not loaded, so any teardown registered beforehand would never run if the component is unloaded without first being loaded.(Inherited from ComponentEx) |
| isLockedByAncestorForPath(pathOrFile) | boolean | Checks whether the path is locked directly or lies under a subtree-locked ancestor folder. |
| isLockedForPath(pathOrFile) | boolean | Checks whether the note at the given path is currently locked by any plugin. |
| isMutationBlockedByAncestorForPath(pathOrFile) | boolean | Checks whether a vault mutation of the path is currently blocked by a shouldBlockMutations lock on the path itself or on a subtree-locked ancestor folder. |
| load() | void | Loads the component. (Inherited from ComponentEx) |
| loadWithPromises() | null | Promise<void> | Loads the component with promises. Unlike load, this method never rejects with an individual error: every failure raised by onloadAsync or a child's load is collected, and once everything settles the returned Promise rejects with a single AggregateError holding all of them. Non-Error throwables are normalized via ErrorWrapper.create.(Inherited from ComponentEx) |
| lockForPath(params) | Disposable | Locks the note at the given path on behalf of this plugin, making it read-only in every current and future MarkdownView until the lock is released. Reference-counted: balance each call with a dispose of the returned Disposable (ideally via using) or unlockForPath. |
| onloadAsync() | Promise<void> | Asynchronously loads the component. Override to add async load logic, which is executed after Component.onload.(Inherited from ComponentEx) |
| onunload() | void | Releases every lock still held by this plugin when the component (and thus the plugin) unloads, so no note is left stuck read-only by an operation that never completed. |
| registerDisposable(disposable) | TDisposable | Registers a Disposable so it is disposed when this component unloads, and returns it unchanged.The recurring "tie a disposable to the component's lifecycle, then keep using it" idiom: the disposable is disposed on Component.unload (or earlier, if the caller disposes it directly — dispose is expected to be idempotent). Guard with ensureLoaded at the call site when registering before load would be unsafe.(Inherited from ComponentEx) |
| removeChild(component) | TComponent | Removes a child component. (Inherited from ComponentEx) |
| requestUnlockForPath(pathOrFile) | void | Fully unlocks the note at the given path: resolves the lock covering it (the path itself when directly locked, otherwise a subtree-locked ancestor folder), cancels the operation(s) that took the lock by aborting their AbortControllers, and releases the lock so the note becomes editable — regardless of which plugin holds the lock. Powers the "Unlock active note" command. A no-op when nothing covers the path. |
| unlockForPath(pathOrFile) | void | Releases one lock previously acquired for the note at the given path via lockForPath. |
Links to this page: