@theia/filesystem
Version:
Theia - FileSystem Extension
192 lines • 7.74 kB
TypeScript
/// <reference types="node" />
import { IMinimatch } from 'minimatch';
import { FileChangeType, FileSystemWatcherService, FileSystemWatcherServiceClient, WatchOptions } from '../../common/filesystem-watcher-protocol';
import { FileChangeCollection } from '../file-change-collection';
import { Deferred } from '@theia/core/lib/common/promise-util';
import { Options, AsyncSubscription, Event } from '@theia/core/shared/@parcel/watcher';
export interface ParcelWatcherOptions {
ignored: IMinimatch[];
}
export declare const ParcelFileSystemWatcherServerOptions: unique symbol;
export interface ParcelFileSystemWatcherServerOptions {
verbose: boolean;
info: (message: string, ...args: any[]) => void;
error: (message: string, ...args: any[]) => void;
parcelOptions: Options;
}
/**
* This is a flag value passed around upon disposal.
*/
export declare const WatcherDisposal: unique symbol;
/**
* Because URIs can be watched by different clients, we'll track
* how many are listening for a given URI.
*
* This component wraps the whole start/stop process given some
* reference count.
*
* Once there are no more references the handle
* will wait for some time before destroying its resources.
*/
export declare class ParcelWatcher {
/** Filesystem path to be watched. */
readonly fsPath: string;
/** Watcher-specific options */
readonly watcherOptions: ParcelWatcherOptions;
/** Logging and parcel watcher options */
protected readonly parcelFileSystemWatchServerOptions: ParcelFileSystemWatcherServerOptions;
/** The client to forward events to. */
protected readonly fileSystemWatcherClient: FileSystemWatcherServiceClient;
/** Amount of time in ms to wait once this handle is not referenced anymore. */
protected readonly deferredDisposalTimeout: number;
protected static debugIdSequence: number;
protected disposed: boolean;
/**
* Used for debugging to keep track of the watchers.
*/
protected debugId: number;
/**
* When this field is set, it means the watcher instance was successfully started.
*/
protected watcher: AsyncSubscription | undefined;
/**
* When the ref count hits zero, we schedule this watch handle to be disposed.
*/
protected deferredDisposalTimer: NodeJS.Timeout | undefined;
/**
* This deferred only rejects with `WatcherDisposal` and never resolves.
*/
protected readonly deferredDisposalDeferred: Deferred<never>;
/**
* We count each reference made to this watcher, per client.
*
* We do this to know where to send events via the network.
*
* An entry should be removed when its value hits zero.
*/
protected readonly refsPerClient: Map<number, {
value: number;
}>;
/**
* Ensures that events are processed in the order they are emitted,
* despite being processed async.
*/
protected parcelEventProcessingQueue: Promise<void>;
/**
* Resolves once this handle disposed itself and its resources. Never throws.
*/
readonly whenDisposed: Promise<void>;
/**
* Promise that resolves when the watcher is fully started, or got disposed.
*
* Will reject if an error occurred while starting.
*
* @returns `true` if successfully started, `false` if disposed early.
*/
readonly whenStarted: Promise<boolean>;
constructor(
/** Initial reference to this handle. */
initialClientId: number,
/** Filesystem path to be watched. */
fsPath: string,
/** Watcher-specific options */
watcherOptions: ParcelWatcherOptions,
/** Logging and parcel watcher options */
parcelFileSystemWatchServerOptions: ParcelFileSystemWatcherServerOptions,
/** The client to forward events to. */
fileSystemWatcherClient: FileSystemWatcherServiceClient,
/** Amount of time in ms to wait once this handle is not referenced anymore. */
deferredDisposalTimeout?: number);
addRef(clientId: number): void;
removeRef(clientId: number): void;
/**
* All clients with at least one active reference.
*/
getClientIds(): number[];
/**
* Add the references for each client together.
*/
getTotalReferences(): number;
/**
* Returns true if at least one client listens to this handle.
*/
isInUse(): boolean;
/**
* @throws with {@link WatcherDisposal} if this instance is disposed.
*/
protected assertNotDisposed(): void;
/**
* When starting a watcher, we'll first check and wait for the path to exists
* before running a parcel watcher.
*/
protected start(): Promise<void>;
/**
* Given a started parcel watcher instance, gracefully shut it down.
*/
protected stopWatcher(watcher: AsyncSubscription): Promise<void>;
protected createWatcher(): Promise<AsyncSubscription>;
protected handleWatcherEvents(events: Event[]): void;
protected resolveEventPath(directory: string, file: string): Promise<string>;
protected pushFileChange(changes: FileChangeCollection, type: FileChangeType, filePath: string): void;
protected fireError(): void;
/**
* When references hit zero, we'll schedule disposal for a bit later.
*
* This allows new references to reuse this watcher instead of creating a new one.
*
* e.g. A frontend disconnects for a few milliseconds before reconnecting again.
*/
protected onRefsReachZero(): void;
/**
* If we get new references after hitting zero, let's unschedule our disposal and keep watching.
*/
protected onRefsRevive(): void;
protected isIgnored(filePath: string): boolean;
/**
* Internal disposal mechanism.
*/
protected _dispose(): Promise<void>;
protected info(prefix: string, ...params: any[]): void;
protected debug(prefix: string, ...params: any[]): void;
}
/**
* Each time a client makes a watchRequest, we generate a unique watcherId for it.
*
* This watcherId will map to this handle type which keeps track of the clientId that made the request.
*/
export interface PacelWatcherHandle {
clientId: number;
watcher: ParcelWatcher;
}
export declare class ParcelFileSystemWatcherService implements FileSystemWatcherService {
protected client: FileSystemWatcherServiceClient | undefined;
protected watcherId: number;
protected readonly watchers: Map<string, ParcelWatcher>;
protected readonly watcherHandles: Map<number, PacelWatcherHandle>;
protected readonly options: ParcelFileSystemWatcherServerOptions;
/**
* `this.client` is undefined until someone sets it.
*/
protected readonly maybeClient: FileSystemWatcherServiceClient;
constructor(options?: Partial<ParcelFileSystemWatcherServerOptions>);
setClient(client: FileSystemWatcherServiceClient | undefined): void;
/**
* A specific client requests us to watch a given `uri` according to some `options`.
*
* We internally re-use all the same `(uri, options)` pairs.
*/
watchFileChanges(clientId: number, uri: string, options?: WatchOptions): Promise<number>;
protected createWatcher(clientId: number, fsPath: string, options: WatchOptions): ParcelWatcher;
unwatchFileChanges(watcherId: number): Promise<void>;
/**
* Given some `URI` and some `WatchOptions`, generate a unique key.
*/
protected getWatcherKey(uri: string, options: WatchOptions): string;
/**
* Return fully qualified options.
*/
protected resolveWatchOptions(options?: WatchOptions): WatchOptions;
protected debug(message: string, ...params: any[]): void;
dispose(): void;
}
//# sourceMappingURL=parcel-filesystem-service.d.ts.map