Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add generic type for watchdog data. #13697

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 22 additions & 12 deletions packages/ckeditor5-watchdog/src/contextwatchdog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import type {
} from 'ckeditor5/src/utils';

import Watchdog, { type WatchdogConfig, type WatchdogState } from './watchdog';
import EditorWatchdog, { type EditorCreatorFunction } from './editorwatchdog';
import EditorWatchdog, { type WatchdogData, type EditorCreatorFunction } from './editorwatchdog';
import areConnectedThroughProperties from './utils/areconnectedthroughproperties';
import getSubNodes from './utils/getsubnodes';

Expand All @@ -36,11 +36,14 @@ const mainQueueId = Symbol( 'MainQueueId' );
* See the {@glink features/watchdog Watchdog feature guide} to learn the rationale behind it and
* how to use it.
*/
export default class ContextWatchdog<TContext extends Context = Context> extends Watchdog {
export default class ContextWatchdog<
TContext extends Context = Context,
TData extends HTMLElement | string = HTMLElement | string
> extends Watchdog {
/**
* A map of internal watchdogs for added items.
*/
protected _watchdogs = new Map<string, EditorWatchdog>();
protected _watchdogs = new Map<string, EditorWatchdog<Editor, TData>>();

/**
* The watchdog configuration.
Expand Down Expand Up @@ -194,10 +197,15 @@ export default class ContextWatchdog<TContext extends Context = Context> extends
* @param itemId The item ID.
* @returns The item instance or `undefined` if an item with a given ID has not been found.
*/
public getItem( itemId: string ): unknown {
const watchdog = this._getWatchdog( itemId );
public getItem( itemId: string ): unknown | undefined {
try {
const watchdog = this._getWatchdog( itemId );

return watchdog._item;
return watchdog._item;
}
catch {
return undefined;
}
Comment on lines -197 to +208
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if this change is valid, but docs say it should return undefined if not found but it was throwing error instead. If it's valid change, then tests should be adjusted.

}

/**
Expand Down Expand Up @@ -260,7 +268,7 @@ export default class ContextWatchdog<TContext extends Context = Context> extends
*
* @param itemConfigurationOrItemConfigurations An item configuration object or an array of item configurations.
*/
public add( itemConfigurationOrItemConfigurations: ArrayOrItem<WatchdogItemConfiguration> ): Promise<unknown> {
public add( itemConfigurationOrItemConfigurations: ArrayOrItem<WatchdogItemConfiguration<WatchdogData<TData>>> ): Promise<unknown> {
const itemConfigurations = toArray( itemConfigurationOrItemConfigurations );

return Promise.all( itemConfigurations.map( item => {
Expand All @@ -273,14 +281,14 @@ export default class ContextWatchdog<TContext extends Context = Context> extends
throw new Error( 'Context was not created yet. You should call the `ContextWatchdog#create()` method first.' );
}

let watchdog: EditorWatchdog;
let watchdog: EditorWatchdog<Editor, TData>;

if ( this._watchdogs.has( item.id ) ) {
throw new Error( `Item with the given id is already added: '${ item.id }'.` );
}

if ( item.type === 'editor' ) {
watchdog = new EditorWatchdog( null, this._watchdogConfig );
watchdog = new EditorWatchdog<Editor, TData>( null, this._watchdogConfig );
watchdog.setCreator( item.creator );
watchdog._setExcludedProperties( this._contextProps );

Expand Down Expand Up @@ -599,7 +607,9 @@ function toArray<T>( elementOrArray: ArrayOrItem<T> ): Array<T> {
/**
* The watchdog item configuration interface.
*/
export interface WatchdogItemConfiguration {
export interface WatchdogItemConfiguration<
TData extends HTMLElement | string | Record<string, string> = HTMLElement | string | Record<string, string>
> {

/**
* id A unique item identificator.
Expand All @@ -615,7 +625,7 @@ export interface WatchdogItemConfiguration {
* A function that initializes the item (the editor). The function takes editor initialization arguments
* and should return a promise. For example: `( el, config ) => ClassicEditor.create( el, config )`.
*/
creator: EditorCreatorFunction;
creator: EditorCreatorFunction<Editor, TData>;

/**
* A function that destroys the item instance (the editor). The function
Expand All @@ -627,7 +637,7 @@ export interface WatchdogItemConfiguration {
* The source element or data that will be passed
* as the first argument to the `Editor.create()` method.
*/
sourceElementOrData: string | HTMLElement;
sourceElementOrData: TData;

/**
* An editor configuration.
Expand Down
27 changes: 16 additions & 11 deletions packages/ckeditor5-watchdog/src/editorwatchdog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,18 @@ import Watchdog, { type WatchdogConfig } from './watchdog';

import { throttle, cloneDeepWith, isElement, type DebouncedFunc } from 'lodash-es';

export type WatchdogData<TData> = TData extends HTMLElement ? TData : TData | Record<string, string>;

/**
* A watchdog for CKEditor 5 editors.
*
* See the {@glink features/watchdog Watchdog feature guide} to learn the rationale behind it and
* how to use it.
*/
export default class EditorWatchdog<TEditor extends Editor = Editor> extends Watchdog {
export default class EditorWatchdog<
TEditor extends Editor = Editor,
TData extends HTMLElement | string = HTMLElement | string
> extends Watchdog {
/**
* The current editor instance.
*/
Expand All @@ -45,7 +50,7 @@ export default class EditorWatchdog<TEditor extends Editor = Editor> extends Wat
/**
* The latest saved editor data represented as a root name -> root data object.
*/
private _data?: Record<string, string>;
protected _data?: Record<string, string>;

/**
* The last document version.
Expand All @@ -55,19 +60,19 @@ export default class EditorWatchdog<TEditor extends Editor = Editor> extends Wat
/**
* The editor source element or data.
*/
private _elementOrData?: HTMLElement | string | Record<string, string>;
protected _elementOrData?: WatchdogData<TData>;

/**
* The editor configuration.
*/
private _config?: EditorConfig;
protected _config?: EditorConfig;

/**
* The creation method.
*
* @see #setCreator
*/
declare protected _creator: EditorCreatorFunction<TEditor>;
declare protected _creator: EditorCreatorFunction<TEditor, WatchdogData<TData>>;

/**
* The destruction method.
Expand Down Expand Up @@ -122,7 +127,7 @@ export default class EditorWatchdog<TEditor extends Editor = Editor> extends Wat
* watchdog.setCreator( ( element, config ) => ClassicEditor.create( element, config ) );
* ```
*/
public setCreator( creator: EditorCreatorFunction<TEditor> ): void {
public setCreator( creator: EditorCreatorFunction<TEditor, WatchdogData<TData>> ): void {
this._creator = creator;
}

Expand Down Expand Up @@ -166,7 +171,7 @@ export default class EditorWatchdog<TEditor extends Editor = Editor> extends Wat
} )
.then( () => {
if ( typeof this._elementOrData === 'string' ) {
return this.create( this._data, this._config, this._config!.context );
return this.create( this._data as any, this._config, this._config!.context );
} else {
const updatedConfig = Object.assign( {}, this._config, {
initialData: this._data
Expand All @@ -188,7 +193,7 @@ export default class EditorWatchdog<TEditor extends Editor = Editor> extends Wat
* @param context A context for the editor.
*/
public create(
elementOrData: HTMLElement | string | Record<string, string> = this._elementOrData!,
elementOrData: WatchdogData<TData> = this._elementOrData!,
config: EditorConfig = this._config!,
context?: Context
): Promise<unknown> {
Expand Down Expand Up @@ -236,7 +241,7 @@ export default class EditorWatchdog<TEditor extends Editor = Editor> extends Wat
} );
}

private _destroy(): Promise<unknown> {
protected _destroy(): Promise<unknown> {
return Promise.resolve()
.then( () => {
this._stopErrorHandling();
Expand Down Expand Up @@ -334,7 +339,7 @@ export type EditorWatchdogRestartEvent = {
return: undefined;
};

export type EditorCreatorFunction<TEditor = Editor> = (
elementOrData: HTMLElement | string | Record<string, string>,
export type EditorCreatorFunction<TEditor = Editor, TData = HTMLElement | string | Record<string, string>> = (
elementOrData: TData,
config: EditorConfig
) => Promise<TEditor>;