Skip to content

Commit

Permalink
feat: add new methods for WebjsContext interface
Browse files Browse the repository at this point in the history
These methods available to DOM features will help with debugging.
More specifically, `context.warn`, `context.info`, ...
  • Loading branch information
jsamr committed Sep 25, 2020
1 parent ce265d5 commit bfdc409
Showing 1 changed file with 314 additions and 0 deletions.
314 changes: 314 additions & 0 deletions packages/core/src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,314 @@
import type {
ComponentType,
ForwardRefExoticComponent,
RefAttributes,
ElementRef,
ComponentPropsWithoutRef
} from 'react';
import type {
Feature,
FeatureConstructor,
FeatureInstanceOf,
PropsFromFeature
} from './Feature';

// CONCRETE TYPES

/**
* A `Webshell` component type derived from its features.
*
* @public
*/
export type WebshellComponent<
C extends ComponentType<any>,
F extends Feature<any, any>[]
> = ForwardRefExoticComponent<
WebshellProps<ComponentPropsWithoutRef<C>, F> & RefAttributes<ElementRef<C>>
>;

/**
* A lookup type to get the webshell component from WebView and feature classes.
*
* @public
*/
export type WebshellComponentOf<
C extends ComponentType<any>,
F extends FeatureConstructor<any, any>[]
> = WebshellComponent<C, FeatureInstanceOf<F[number]>[]>;

/**
* A minimal set of attributes to define a feature.
*
* @public
*/
export type FeatureDefinition<O extends {}> = {
/**
* The string containing valid ECMAScript 5 to be run in the WebView.
*
* @remarks
* The script must define a single function which only argument is of the
* type {@link WebjsContext}.
*
* It is recommended that you use eslint to validate this script syntax, and
* event better, unit-test the script. See our repository home page for more
* information.
*/
readonly script: string;
/**
* A unique identifier of the feature. The convention is to use a reverse
* namespace domain ending with the feature name.
*
* @example
* org.formidable-webview/webshell.link-press
*/
readonly featureIdentifier: string;
/**
* These options will be shallow-merged with the options provided to the {@link FeatureConstructor}.
*/
readonly defaultOptions: O;
};

/**
* @public
*/
export type PropDefinition<P extends Partial<Record<string, any>>> = {
type: 'handler' | 'inert';
featureIdentifier: string;
name: string;
signature?: P;
};

/**
* @public
*/
export type PropsFromSpecs<S> = S extends PropsSpecs<any>
? S[number]['signature']
: never;

/**
* @public
*/
export type PropsSpecs<P = {}> = PropDefinition<P>[];

/**
* An object which keys are event handler names, and values are event handler
* functions.
*
* @typeparam H - The event handler name.
* @typeparam P - The shape of the payload received by the handler function.
*
* @public
*/
export type EventHandlerProps<H extends string, P> = {
[k in H]?: (e: P) => void;
};

/**
* Props any Webshell component will support.
*
* @public
*/
export interface WebshellInvariantProps {
/**
* Triggered when a feature script throws.
*/
onDOMError?: (featureIdentifier: string, error: string) => void;
/**
* Report DOM error messages from features in the console.
*
* @defaultvalue `__DEV__`
*/
webshellDebug?: boolean;
}

/**
* Props of the Webshell produced by {@link makeWebshell}.
*
* @public
*/
export type WebshellProps<
W extends MinimalWebViewProps,
F extends Feature<any, any>[]
> = WebshellInvariantProps &
W &
(F[number] extends never ? {} : PropsFromFeature<F[number]>);

/**
* A high-compatibility type expressing minimal requirements for the
* WebView Component's props.
*
* @public
*/
export interface MinimalWebViewProps {
readonly onMessage?: unknown;
readonly onError?: unknown;
readonly injectedJavaScript?: unknown;
readonly javaScriptEnabled?: unknown;
readonly source?: Record<string, any>;
readonly style?: unknown;
readonly onNavigationStateChange?: unknown;
readonly scalesPageToFit?: unknown;
readonly showsVerticalScrollIndicator?: unknown;
readonly disableScrollViewPanResponder?: unknown;
}

// DOM TYPES

/**
* This type specifies the shape of the object passed to DOM features scripts.
*
* @typeparam O - The shape of the JSON-serializable object that will be passed to the DOM script.
* @typeparam P - The type of the argument which will be passed to the event handler prop.
* @public
*/
export interface WebjsContext<O extends {}, P> {
/**
* The options to customize the script behavior.
*/
readonly options: O;
/**
* When invoked, the webshell will call the handler associated with this script.
*
* @param payload - The value which will be passed to the handler.
*/
postMessage(payload: P): void;
/**
* Create a function which execute a callback in a try-catch block that will
* grab errors en send them to the `Webshell` component.
*
* @param callback - The callback to try-catch.
*/
makeCallbackSafe<T extends Function>(callback: T): T;
/**
* Safely post a warn message to the console.
*/
warn(message: string): void;
/**
* Safely post an error message to the console.
*/
error(message: string): void;
/**
* Get one element in the DOM from a request.
*
* @returns An {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement | HTMLElement} or `null`.
*/
getDOMSelection(
selector: DOMElementRequest,
multiple: false
): HTMLElement | null;
/**
* Get a collection of live elements in the DOM from a query request.
*
* @param selector - Which elements should be returned?
* @returns A live {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLCollection | HTMLCollection}.
*/
getDOMSelection(
selector: DOMElementQueryRequest | string,
multiple: true
): any;
/**
* Get a collection of static elements in the DOM from a class or tag-name request.
*
* @param selector - Which elements should be returned?
* @returns A static {@link https://developer.mozilla.org/en-US/docs/Web/API/NodeList | NodeList}.
*/
getDOMSelection(
selector: DOMElementClassNameRequest | DOMElementTagNameRequest,
multiple: true
): any;
/**
* @param style - The style to parse, e.g. `'18px'`
*
* @returns Numeric value in CSS pixels.
*/
numericFromPxString(style: string): number;
}

/**
* See {@link https://developer.mozilla.org/en-US/docs/Web/API/DOMRect | DOMRect}.
*
* @public
*/
export interface DOMRect {
top: number;
left: number;
right: number;
bottom: number;
width: number;
height: number;
}

/**
* A request to select one element in the DOM.
*
* @remarks
* A string will be interpreted as a “query” request.
* See {@link https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector | Document.querySelector() } and {@link DOMElementQueryRequest}.
*
* @public
*/
export type DOMElementRequest =
| DOMElementQueryRequest
| DOMElementClassNameRequest
| DOMElementIdRequest
| DOMElementTagNameRequest
| string;

/**
* A request to select a collection of elements in the DOM.
*
* @remarks
* A string will be interpreted as a “query” request.
* See {@link https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll | Document.querySelectorAll() } and {@link DOMElementQueryRequest}.
*
* @public
*/
export type DOMCollectionRequest =
| DOMElementQueryRequest
| DOMElementClassNameRequest
| DOMElementTagNameRequest
| string;

/**
* A request by query string.
* See {@link https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll | Document.querySelectorAll() }
* and {@link https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector | Document.querySelector() }
*
* @public
*/
export type DOMElementQueryRequest = {
query: string;
};

/**
* A request by id (case-insensitive);
* See {@link https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById | Document.getElementById() }
*
* @public
*/
export type DOMElementIdRequest = {
id: string;
};

/**
* A request by one or many case-sensitive class names, separated by spaces.
* See {@link https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementsByClassName | Document.getElementsByClassName() }
*
* @public
*/
export type DOMElementClassNameRequest = {
className: string;
};

/**
* A query by tag name.
* See {@link https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementsByClassName | Document.getElementsByTagName() }
*
* @remarks
* `'html'` will select `document.documentElement`.
*
* @public
*/
export type DOMElementTagNameRequest = {
tagName: string;
};

0 comments on commit bfdc409

Please sign in to comment.