From d4848c0379e5cfa3932310b4a9e4c284ea652a79 Mon Sep 17 00:00:00 2001 From: impinball Date: Thu, 9 Jul 2015 03:34:41 -0400 Subject: [PATCH 1/2] Remove trailing whitespace --- docs/mithril.render.md | 2 +- mithril.d.ts | 2 +- modulator-test.html | 110 ++++++++++++++++++++--------------------- 3 files changed, 57 insertions(+), 57 deletions(-) diff --git a/docs/mithril.render.md b/docs/mithril.render.md index 0b4c6beb..39b0a808 100644 --- a/docs/mithril.render.md +++ b/docs/mithril.render.md @@ -122,4 +122,4 @@ where: - **Boolean forceRecreation** - If set to true, rendering a new virtual tree will completely overwrite an existing one without attempting to diff against it \ No newline at end of file + If set to true, rendering a new virtual tree will completely overwrite an existing one without attempting to diff against it diff --git a/mithril.d.ts b/mithril.d.ts index c9763a96..ba006753 100644 --- a/mithril.d.ts +++ b/mithril.d.ts @@ -17,7 +17,7 @@ declare module _mithril { mount(rootElement: Node): T; component(component: MithrilComponent, ...args: Array): MithrilComponent - + trust(html: string): string; render(rootElement: Element|HTMLDocument): void; diff --git a/modulator-test.html b/modulator-test.html index 761573ac..a4349ceb 100644 --- a/modulator-test.html +++ b/modulator-test.html @@ -7,10 +7,10 @@ var mod = ( function initModulator(){ var Map = shim; var WeakMap = shim; } - + // Garbage collection flag mod.cleanup = true; - + // Registry of instantiation contexts var contexts = new WeakMap(); // All automated counts @@ -20,36 +20,36 @@ var mod = ( function initModulator(){ var snapRedraw = m.redraw; var redraw; var forced; - + for( var key in m.redraw ){ queueRedraw[ key ] = snapRedraw[ key ] = m.redraw[ key ]; } - + return function pause(){ m.redraw = queueRedraw; - + setTimeout( function unpause(){ m.redraw = snapRedraw; - + if( redraw ) m.redraw( forced ); - + redraw = forced = false; } ); } - + function queueRedraw( force ){ redraw = true; - + if( force ) forced = true; } }() ); var unique = {}; - + // Clear counts at the begninning of every redraw m.module( document.createElement( 'x' ), { view : counts.clear.bind( counts ) } ); - + // Shorthand for a component which will always return the same instance mod.unique = function( component ){ return mod( component, unique, unique ); @@ -58,80 +58,80 @@ var mod = ( function initModulator(){ mod.global = function( x ){ return mod( x, unique ); }; - + // Extend controllers with extra utility functions mod.extend = true; - + return mod; - + function mod( component, context, key ){ // Stand in for m.module, eg mod( document.body, component, context ); if( component instanceof HTMLElement ){ // Stand in for m.route if( !component.controller && !component.view ){ var routes = {}; - + for( var route in context ){ routes[ route ].controller = mod.unique( { controller : context[ route ].controller || noop } ).bind(); } - + return m.route( component, routes ); } - + return m.module( component, mod.apply( undefined, [].slice.call( arguments, 1 ) ) )(); } - + var components = register( contexts, context || unique, WeakMap ); var keys = register( components, component, WeakMap ); - + return function identify( key ){ var count = key === undefined && register( counts, keys, m.prop.bind( undefined, 0 ) ); // eg. ctrl.mod( profile ).mapWith( users(), 'username' ); apply.mapWith = function( collection ){ var path = [].slice.call( arguments, 1 ); - + return Object.keys( collection ).map( function getItemIdentifier( index ){ var key; - + if( path.length ){ key = path.reduce( function getKeyValue( source, segment ){ var node = source[ segment ]; - + if( node instanceof Function ) node = node.call( source ); - + return node; }, collection[ index ] ); } else { key = index; } - + return identify( key )( collection[ index ] ); } ); }; - + return apply; - + function apply(){ var args = [].slice.call( arguments ); var view; - + if( count ){ key = count( count() + 1 ); } - + var ctrl = register( keys, key, function newController(){ pauseRedraw(); - + var controller = component.controller || noop; var instance = new ( controller.bind.apply( controller, [ controller ].concat( args ) ) )(); - + if( mod.cleanup ){ garbageCollect( instance ); } - + if( mod.extend ){ // Shorthand for instantiatin sub-modules instance.mod = function( component, key ){ @@ -145,14 +145,14 @@ var mod = ( function initModulator(){ instance.refresh = function(){ args = [].slice.call( arguments ); ctrl = register( keys, key, newController, true ); - + return m.redraw; }; } - + return instance; } ); - + // Return the controller instance if the component is view-less. if( component.view ){ if( args.length ){ @@ -161,31 +161,31 @@ var mod = ( function initModulator(){ else { view = component.view( ctrl ); } - + if( view instanceof Object ){ view.ctrl = ctrl; } - + return view; } - + return ctrl; } }( key ); - + // Performance: when controllers succesfully unload, destroy their associated maps function garbageCollect( ctrl ){ onunload = ctrl.onunload; - + if( onunload === teardown ){ return; } - + ctrl.onunload = teardown; - + function teardown( e ){ var go = true; - + if( onunload ){ onunload( { preventDefault : function(){ @@ -193,39 +193,39 @@ var mod = ( function initModulator(){ } } ); } - + if( go ){ contexts.delete( context ); } } } } - + // Convenience map method: retrieve key from map. If it's not registered, set it first with Constructor. function register( map, key, Constructor, force ){ return !force && map.has( key ) ? map.get( key ) : map.set( key, new Constructor() ).get( key ); } - + function shim(){ var keys = []; var values = []; var map = { get : function( key ){ var index = keys.indexOf( key ); - + return values[ index ]; }, has : function( key ){ var index = keys.indexOf( key ); - + return index > -1; }, set : function( key, value ){ var index = map.has( key ) ? keys.indexOf( key ) : keys.length; - + keys[ index ] = key; values[ index ] = value; - + return map; }, clear : function(){ @@ -234,21 +234,21 @@ var mod = ( function initModulator(){ }, delete : function( key ){ var index = keys.indexOf( key ); - + if( index > -1 ){ keys.splice( index, 1 ); values.splice( index, 1 ); - + return true; } - + return false; } }; - + return map; } - + function noop(){} }() ); @@ -271,4 +271,4 @@ b.view = function(ctrl, count) { return m("li", count) } -m.module(document.body, a) \ No newline at end of file +m.module(document.body, a) From 51f59419b2b16e39d921ff06eec717f6d25d66be Mon Sep 17 00:00:00 2001 From: impinball Date: Thu, 9 Jul 2015 09:41:15 -0400 Subject: [PATCH 2/2] Strengthen types, describe API in TypeScript file --- mithril.d.ts | 858 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 788 insertions(+), 70 deletions(-) diff --git a/mithril.d.ts b/mithril.d.ts index ba006753..3db03036 100644 --- a/mithril.d.ts +++ b/mithril.d.ts @@ -1,166 +1,884 @@ -//Mithril type definitions for Typescript +// Mithril type definitions for Typescript + +/** +* This is the module containing all the types/declarations/etc. for Mithril +*/ declare module _mithril { interface MithrilStatic { + /** + * Creates a virtual element for use with m.render, m.mount, etc. + * + * @param selector A simple CSS selector. May include SVG tags. Nested + * selectors are not supported. + * @param attributes Attributes to add. Any DOM attribute may be used + * as an attribute, although innerHTML and the like may be overwritten + * silently. + * @param children Child elements, components, and text to add. + * @return A virtual element. + * + * @see m.render + * @see m.mount + * @see m.component + */ + ( + selector: string, + attributes: MithrilAttributes, + ...children: Array | + MithrilComponent> + ): MithrilVirtualElement; - (selector: string, attributes: MithrilAttributes, ...children: Array>): MithrilVirtualElement; - (selector: string, ...children: Array>): MithrilVirtualElement; + /** + * Creates a virtual element for use with m.render, m.mount, etc. + * + * @param selector A simple CSS selector. Nested selectors are not + * supported. + * @param children Child elements, components, and text to add. + * @return A virtual element. + * + * @see m.render + * @see m.mount + * @see m.component + */ + ( + selector: string, + ...children: Array | + MithrilComponent> + ): MithrilVirtualElement; - prop(promise: MithrilPromise) : MithrilPromiseProperty; - prop(value: T): MithrilProperty; - prop(): MithrilProperty; // might be that this should be Property + /** + * Initializes a component for use with m.render, m.mount, etc. + * Shorthand for m.component. + * + * @param selector A component. + * @param args Arguments to optionally pass to the component. + * @return A component. + * + * @see m.render + * @see m.mount + * @see m.component + */ + ( + component: MithrilComponent, + ...args: any[] + ): MithrilComponent; - withAttr(property: string, callback: (value: any) => void): (e: MithrilEvent) => any; + /** + * Creates a getter-setter function that wraps a Mithril promise. Useful + * for uniform data access, m.withAttr, etc. + * + * @param promise A thennable to initialize the property with. It may + * optionally be a Mithril promise. + * @return A getter-setter function wrapping the promise. + * + * @see m.withAttr + */ + prop(promise: Thennable) : MithrilPromiseProperty; - module(rootElement: Node, component: MithrilComponent): T; - module(rootElement: Node): T; - mount(rootElement: Node, component: MithrilComponent): T; - mount(rootElement: Node): T; + /** + * Creates a getter-setter function that wraps a simple value. Useful + * for uniform data access, m.withAttr, etc. + * + * @param value A value to initialize the property with + * @return A getter-setter function wrapping the value. + * + * @see m.withAttr + */ + prop(value: T): MithrilBasicProperty; - component(component: MithrilComponent, ...args: Array): MithrilComponent + /** + * Creates a getter-setter function that wraps a simple value. Useful + * for uniform data access, m.withAttr, etc. + * + * @return A getter-setter function wrapping the value. + * + * @see m.withAttr + */ + prop(): MithrilBasicProperty; - trust(html: string): string; + /** + * Returns a event handler that can be bound to an element, firing with + * the specified property. + * + * @param property The property to get from the event. + * @param callback The handler to use the value from the event. + * @return A function suitable for listening to an event. + */ + withAttr( + property: string, + callback: (value: any) => void + ): (e: Event) => any; - render(rootElement: Element|HTMLDocument): void; - render(rootElement: Element|HTMLDocument, children: MithrilVirtualElement, forceRecreation?: boolean): void; - render(rootElement: Element|HTMLDocument, children: MithrilVirtualElement[], forceRecreation?: boolean): void; + /** + * @deprecated Use m.mount instead + */ + module( + rootElement: Node, + component: MithrilComponent + ): T; + + /** + * Mounts a component to a base DOM node. + * + * @param rootElement The base node. + * @param component The component to mount. + * @return An instance of the top-level component's controller + */ + mount( + rootElement: Node, + component: MithrilComponent + ): T; + + /** + * Initializes a component for use with m.render, m.mount, etc. + * + * @param selector A component. + * @param args Arguments to optionally pass to the component. + * @return A component. + * + * @see m.render + * @see m.mount + * @see m + */ + component( + component: MithrilComponent, + ...args: any[] + ): MithrilComponent; + + /** + * Trust this string of HTML. + * + * @param html The HTML to trust + * @return A String object instance with an added internal flag to mark + * it as trusted. + */ + trust(html: string): MithrilTrustedString; + + /** + * Render a virtual DOM tree. + * + * @param rootElement The base element/node to render the tree from. + * @param children One or more child nodes to add to the tree. + * @param forceRecreation If true, overwrite the entire tree without + * diffing against it. + */ + render( + rootElement: Element, + children: MithrilVirtualElement|MithrilVirtualElement[], + forceRecreation?: boolean + ): void; redraw: { + /** + * Force a redraw the active component. It redraws asynchronously by + * default to allow for simultaneous events to run before redrawing, + * such as the event combination keypress + input frequently used for + * input. + * + * @param force If true, redraw synchronously. + */ (force?: boolean): void; - strategy: MithrilProperty; + + strategy: { + /** + * Gets the current redraw strategy, which returns one of the + * following: + * + * "all" - recreates the DOM tree from scratch + * "diff" - recreates the DOM tree from scratch + * "none" - leaves the DOM tree intact + * + * This is useful for event handlers, which may want to cancel + * the next redraw if the event doesn't update the UI. + * + * @return The current strategy + */ + (): string; + + /** + * Sets the current redraw strategy. The parameter must be one of + * the following values: + * + * "all" - recreates the DOM tree from scratch + * "diff" - recreates the DOM tree from scratch + * "none" - leaves the DOM tree intact + * + * This is useful for event handlers, which may want to cancel + * the next redraw if the event doesn't update the UI. + * + * @param value The value to set + * @return The new strategy + */ + (value: string): string; + + /** + * @private + * Implementation detail - it's a MithrilBasicProperty instance + */ + toJSON(): string; + } } route: { - (rootElement: HTMLDocument, defaultRoute: string, routes: MithrilRoutes): void; - (rootElement: Element, defaultRoute: string, routes: MithrilRoutes): void; + /** + * Enable routing, mounting a controller based on the route. It + * automatically mounts the components for you, starting with the one + * specified by the default route. + * + * @param rootElement The element to mount the active controller to. + * @param defaultRoute The route to start with. + * @param routes A key-value mapping of pathname to controller. + */ + ( + rootElement: Element, + defaultRoute: string, + routes: MithrilRoutes + ): void; - (element: Element, isInitialized: boolean, context: Object, vdom: Object): void; + /** + * This allows m.route to be used as the `config` attribute for a + * virtual element, particularly useful for cases like this: + * + * ```ts + * // Note that the '#' is not required in `href`, thanks to the + * `config` setting. + * m("a[href='/dashboard/alicesmith']", {config: m.route}); + * ``` + */ + ( + element: Element, + isInitialized: boolean, + context?: MithrilContext, + vdom?: MithrilVirtualElement + ): void; + + /** + * Programmatically redirect to another route. + * + * @param path The route to go to. + * @param params Parameters to pass as a query string. + * @param shouldReplaceHistory Whether to replace the current history + * instead of adding a new one. + */ (path: string, params?: any, shouldReplaceHistory?: boolean): void; + + /** + * Gets the current route. + * + * @return The current route. + */ (): string; + /** + * Gets a route parameter. + * + * @param key The key to get. + * @return The value associated with the parameter key. + */ param(key: string): string; + + /** + * The current routing mode. This may be changed before calling + * m.route to change the part of the URL used to perform the routing. + * + * The value can be set to one of the following, defaulting to + * "hash": + * + * "search" - Uses the query string. This allows for named anchors to + * work on the page, but changes cause IE8 and lower to refresh the + * page. + * + * "hash" - Uses the hash. This is the only routing mode that does + * not cause page refreshes on any browser, but it does not support + * named anchors. + * + * "pathname" - Uses the URL pathname. This requires server-side + * setup to support bookmarking and page refreshes. It always causes + * page refreshes on IE8 and lower. Note that this requires that the + * application to be run from the root of the URL. + */ mode: string; + + /** + * Serialize an object into a query string. + * + * @param data The data to serialize. + * @return The serialized string. + */ buildQueryString(data: Object): String + + /** + * Parse a query string into an object. + * + * @param data The data to parse. + * @return The parsed object data. + */ parseQueryString(data: String): Object } - request(options: MithrilXHROptions): MithrilPromise; + /** + * Send a request to a server to server. Note that the `url` option is + * required. + * + * @param options The options to use + * @return A promise to the returned data for "GET" requests, or a void + * promise for any other request type. + * + * @see MithrilXHROptions for the available options. + */ + request(options: MithrilXHROptions): MithrilPromise; deferred: { - onerror(e: Error): void; + /** + * Create a Mithril deferred object. It behaves synchronously if + * possible, an intentional deviation from Promises/A+. Note that + * deferreds are completely separate from the redrawing system, and + * never trigger a redraw on their own. + * + * @return A new Mithril deferred instance. + * + * @see m.deferred.onerror for the error callback called for Error + * subclasses + */ (): MithrilDeferred; + + /** + * A callback for all uncaught native Error subclasses in deferreds. + * This defaults to synchronously rethrowing all errors, a deviation + * from Promises/A+, but the behavior is configurable. To restore + * Promises/A+-compatible behavior. simply set this to a no-op. + */ + onerror(e: Error): void; } - sync(promises: MithrilPromise[]): MithrilPromise; + /** + * Takes a list of promises or thennables and returns a Mithril promise + * that resolves once all in the list are resolved, or rejects if any of + * them reject. + * + * @param promises A list of promises to try to resolve. + * @return A promise that resolves to all the promises if all resolve, or + * rejects with the error contained in the first rejection. + */ + sync(promises: Thennable[]): MithrilPromise; + /** + * Use this and endComputation if your views aren't redrawing after + * calls to third-party libraries. For integrating asynchronous code, + * this should be called before any asynchronous work is done. For + * synchronous code, this should be called at the beginning of the + * problematic segment. Note that these calls must be balanced, much like + * braces and parentheses. This is mostly used internally. Prefer + * m.redraw where possible, especially when making repeated calls. + * + * @see endComputation + * @see m.render + */ startComputation(): void; + + /** + * Use startComputation and this if your views aren't redrawing after + * calls to third-party libraries. For integrating asynchronous code, + * this should be called after all asynchronous work completes. For + * synchronous code, this should be called at the end of the problematic + * segment. Note that these calls must be balanced, much like braces and + * parentheses. This is mostly used internally. Prefer m.redraw where + * possible, especially when making repeated calls. + * + * @see startComputation + * @see m.render + */ endComputation(): void; - // For test suite - deps: { - (mockWindow: Window): Window; - factory: Object; - } - + /** + * This overwrites the internal version of window used by Mithril. + * It's mostly useful for testing, and is also used internally by + * Mithril to test itself. By default Mithril uses `window` for the + * dependency. + * + * @param mockWindow The mock to use for the window. + * @return The mock that was passed in. + */ + deps(mockWindow: Window): Window; } - interface MithrilVirtualElement { + interface MithrilTrustedString extends String { + /** @private Implementation detail. Don't depend on it. */ + $trusted: boolean; + } + + /** + * The interface for a virtual element. It's best to consider this immutable + * for most use cases. + * + * @see m + */ + interface MithrilVirtualElement { + /** + * A key to optionally associate with this element. + */ key?: number; + + /** + * The tag name of this element. + */ tag?: string; + + /** + * The attributes of this element. + */ attrs?: MithrilAttributes; - children?: any[]; + + /** + * The children of this element. + */ + children?: Array|MithrilComponent>; } - // Configuration function for an element + /** + * An event passed by Mithril to unload event handlers. + */ + interface MithrilEvent { + /** + * Prevent the default behavior of scrolling the page and updating the + * URL on next route change. + */ + preventDefault(): void; + } + + /** + * A context object for configuration functions. + * + * @see MithrilElementConfig + */ + interface MithrilContext { + /** + * A function to call when the node is unloaded. Useful for cleanup. + */ + onunload?(): any; + + /** + * Set true if the backing DOM node needs to be retained between route + * changes if possible. Set false if this node needs to be recreated + * every single time, regardless of how "different" it is. + */ + retain?: boolean; + } + + /** + * This represents a callback function for a virtual element's config + * attribute. It's a low-level function useful for extra cleanup after + * removal from the tree, storing instances of third-party classes that + * need to be associated with the DOM, etc. + * + * @see MithrilAttributes + * @see MithrilContext + */ interface MithrilElementConfig { - (element: Element, isInitialized: boolean, context?: any, vdom?: MithrilVirtualElement): void; + /** + * A callback function for a virtual element's config attribute. + * + * @param element The associated DOM element. + * @param isInitialized Whether this is the first call for the virtual + * element or not. + * @param context The associated context for this element. + * @param vdom The associated virtual element. + */ + ( + element: Element, + isInitialized: boolean, + context: MithrilContext, + vdom: MithrilVirtualElement + ): void; } - // Attributes on a virtual element + /** + * This represents the attributes available for configuring virtual elements, + * beyond the applicable DOM attributes. + * + * @see m + */ interface MithrilAttributes { - title?: string; + /** + * The class name(s) for this virtual element, as a space-separated list. + */ className?: string; + + /** + * The class name(s) for this virtual element, as a space-separated list. + */ class?: string; + + /** + * A custom, low-level configuration in case this element needs special + * cleanup after removal from the tree. + * + * @see MithrilElementConfig + */ config?: MithrilElementConfig; } - // Defines the subset of Event that Mithril needs - interface MithrilEvent { - currentTarget: Element; - } - + /** + * The basis of a Mithril controller instance. + */ interface MithrilController { - onunload?(evt: Event): any; + /** + * An optional handler to call when the associated virtual element is + * destroyed. + * + * @param evt An associated event. + */ + onunload?(evt: MithrilEvent): any; } - interface MithrilControllerFunction extends MithrilController { - (): any; + /** + * This represents a controller function. + * + * @see MithrilControllerConstructor + */ + interface MithrilControllerFunction { + (): T; } + /** + * This represents a controller constructor. + * + * @see MithrilControllerFunction + */ + interface MithrilControllerConstructor { + new(): T; + } + + /** + * This represents a view factory. + */ interface MithrilView { - (ctrl: T): string|MithrilVirtualElement; + /** + * Creates a view out of virtual elements. + */ + (ctrl: T): MithrilVirtualElement; } + /** + * This represents a Mithril component. + * + * @see m + * @see m.component + */ interface MithrilComponent { - controller: MithrilControllerFunction|{ new(): T }; - view: MithrilView; + /** + * The component's controller. + * + * @see m.component + */ + controller: MithrilControllerFunction | + MithrilControllerConstructor; + + /** + * Creates a view out of virtual elements. + * + * @see m.component + */ + view(ctrl: T): MithrilVirtualElement; } + /** + * This is the base interface for property getter-setters + * + * @see m.prop + */ interface MithrilProperty { + /** + * Gets the contained value. + * + * @return The contained value. + */ (): T; + + /** + * Sets the contained value. + * + * @param value The new value to set. + * @return The newly set value. + */ (value: T): T; + } + + /** + * This represents a non-promise getter-setter functions. + * + * @see m.prop which returns objects that implement this interface. + */ + interface MithrilBasicProperty extends MithrilProperty { + /** + * Makes this serializable to JSON. + */ toJSON(): T; } - interface MithrilPromiseProperty extends MithrilPromise { - (): T; - (value: T): T; - toJSON(): T; + /** + * This represents a promise getter-setter function. + * + * @see m.prop which returns objects that implement this interface. + */ + interface MithrilPromiseProperty extends MithrilPromise, + MithrilProperty> { + /** + * Gets the contained promise. + * + * @return The contained value. + */ + (): MithrilPromise; + + /** + * Sets the contained promise. + * + * @param value The new value to set. + * @return The newly set value. + */ + (value: MithrilPromise): MithrilPromise; + + /** + * Sets the contained wrapped value. + * + * @param value The new value to set. + * @return The newly set value. + */ + (value: T): MithrilPromise; } + /** + * This represents a key-value mapping linking routes to components. + */ interface MithrilRoutes { + /** + * The key represents the route. The value represents the corresponding + * component. + */ [key: string]: MithrilComponent; } - + /** + * This represents a Mithril deferred object. + */ interface MithrilDeferred { + /** + * Resolve this deferred's promise with a value. + * + * @param value The value to resolve the promise with. + */ resolve(value?: T): void; - reject(value?: any): void; + + /** + * Reject this deferred with an error. + * + * @param value The reason for rejecting the promise. + */ + reject(reason?: any): void; + + /** + * The backing promise. + * + * @see MithrilPromise + */ promise: MithrilPromise; } + /** + * This represents a thennable success callback. + */ interface MithrilSuccessCallback { - (value: T): U; - (value: T): MithrilPromise; + (value: T): U | Thennable; } - interface MithrilErrorCallback { - (value: Error): U; - (value: string): U; + /** + * This represents a thennable error callback. + */ + interface MithrilErrorCallback { + (value: Error): T | Thennable; } - interface MithrilPromise { - (): T; - (value: T): T; - then(success: (value: T) => U): MithrilPromise; - then(success: (value: T) => MithrilPromise): MithrilPromise; - then(success: (value: T) => U, error: (value: Error) => V): MithrilPromise|MithrilPromise; - then(success: (value: T) => MithrilPromise, error: (value: Error) => V): MithrilPromise|MithrilPromise; + /** + * This represents a thennable. + */ + interface Thennable { + then(success: (value: T) => U): Thennable; + then(success: (value: T) => U, error: (value: Error) => V): Thennable|Thennable; + catch?: (error: (value: Error) => U) => Thennable; } - interface MithrilXHROptions { + + /** + * This represents a Mithril promise object. + */ + interface MithrilPromise extends Thennable, MithrilProperty> { + /** + * Chain this promise with a simple success callback, propogating + * rejections. + * + * @param success The callback to call when the promise is resolved. + * @return The chained promise. + */ + then(success: MithrilSuccessCallback): MithrilPromise; + + /** + * Chain this promise with a success callback and error callback, without + * propogating rejections. + * + * @param success The callback to call when the promise is resolved. + * @param error The callback to call when the promise is rejected. + * @return The chained promise. + */ + then( + success: MithrilSuccessCallback, + error: MithrilErrorCallback + ): MithrilPromise | MithrilPromise; + + /** + * Chain this promise with a single error callback, without propogating + * rejections. + * + * @param error The callback to call when the promise is rejected. + * @return The chained promise. + */ + catch(error: MithrilErrorCallback): MithrilPromise | + MithrilPromise; + } + + /** + * This represents the available options for configuring m.request. + * + * @see m.request + */ + interface MithrilXHROptions { + /** + * This represents the HTTP method used, one of the following: + * + * - "GET" (default) + * - "POST" + * - "PUT" + * - "DELETE" + * - "HEAD" + * - "OPTIONS" + */ method?: string; + + /** + * The URL to send the request to. + */ url: string; + + /** + * The username for HTTP authentication. + */ user?: string; + + /** + * The password for HTTP authentication. + */ password?: string; + + /** + * The data to be sent. It's automatically serialized in the right format + * depending on the method (with exception of HTML5 FormData), and put in + * the appropriate section of the request. + */ data?: any; + + /** + * Whether to run it in the background, i.e. true if it doesn't affect + * template rendering. + */ background?: boolean; - unwrapSuccess?(data: any): any; - unwrapError?(data: any): any; + + /** + * Set an initial value while the request is working, to populate the + * promise getter-setter. + */ + initialValue?: T; + + /** + * An optional preprocessor function to unwrap a successful response, in + * case the response contains metadata wrapping the data. + * + * @param data The data to unwrap. + * @return The unwrapped result. + */ + unwrapSuccess?(data: any): T; + + /** + * An optional preprocessor function to unwrap an unsuccessful response, + * in case the response contains metadata wrapping the data. + * + * @param data The data to unwrap. + * @return The unwrapped result. + */ + unwrapError?(data: any): T; + + /** + * An optional function to serialize the data. This defaults to + * `JSON.stringify`. + * + * @param dataToSerialize The data to serialize. + * @return The serialized form as a string. + */ serialize?(dataToSerialize: any): string; + + /** + * An optional function to deserialize the data. This defaults to + * `JSON.parse`. + * + * @param dataToSerialize The data to parse. + * @return The parsed form. + */ deserialize?(dataToDeserialize: string): any; - extract?(xhr: XMLHttpRequest, options: MithrilXHROptions): string; - type?(data: Object): void; - config?(xhr: XMLHttpRequest, options: MithrilXHROptions): XMLHttpRequest; + + /** + * An optional function to extract the data from a raw XMLHttpRequest, + * useful if the relevant data is in a response header or the status + * field. + * + * @param xhr The associated XMLHttpRequest. + * @param options The options passed to this request. + * @return string The serialized format. + */ + extract?(xhr: XMLHttpRequest, options: MithrilXHROptions): string; + + /** + * The parsed data, or its children if it's an array, will be passed to + * this class constructor if it's given, to parse it into classes. + * + * @param data The data to parse. + * @return The new instance for the list. + */ + type?: new (data: Object) => any; + + /** + * An optional function to run between `open` and `send`, useful for + * adding request headers or using XHR2 features such as the `upload` + * property. It is even possible to override the XHR altogether with a + * similar object, such as an XDomainRequest instance. + * + * @param xhr The associated XMLHttpRequest. + * @param options The options passed to this request. + * @return The new XMLHttpRequest, or nothing if the same one is kept. + */ + config?(xhr: XMLHttpRequest, options: MithrilXHROptions): any; + + /** + * For JSONP requests, this must be the string "jsonp". Otherwise, it's + * ignored. + */ dataType?: string; + + /** + * For JSONP requests, this is the query string key for the JSONP + * request. This is useful for APIs that don't use common conventions, + * such as `www.example.com/?jsonpCallback=doSomething`. It defaults to + * `callback` for JSONP requests, and is ignored for any other kind of + * request. + */ + callbackKey?: string; } }