lib/wp-register-route.js
function registerRoute( namespace, restBase, options = {} ) {
	// Support all methods until requested to do otherwise
	let supportedMethods = [ 'head', 'get', 'patch', 'put', 'post', 'delete' ];

	if ( Array.isArray( options.methods ) ) {
		// Permit supported methods to be specified as an array
		supportedMethods = options.methods.map( method => method.trim().toLowerCase() );
	} else if ( typeof options.methods === 'string' ) {
		// Permit a supported method to be specified as a string
		supportedMethods = [ options.methods.trim().toLowerCase() ];
	}

	// Ensure that if GET is supported, then HEAD is as well, and vice-versa
	if ( supportedMethods.indexOf( 'get' ) !== -1 && supportedMethods.indexOf( 'head' ) === -1 ) {
		supportedMethods.push( 'head' );
	} else if ( supportedMethods.indexOf( 'head' ) !== -1 && supportedMethods.indexOf( 'get' ) === -1 ) {
		supportedMethods.push( 'get' );
	}

	const fullRoute = namespace
		// Route should always have preceding slash
		.replace( /^[\s/]*/, '/' )
		// Route should always be joined to namespace with a single slash
		.replace( /[\s/]*$/, '/' ) + restBase.replace( /^[\s/]*/, '' );

	const routeObj = {};
	routeObj[ fullRoute ] = {
		namespace: namespace,
		methods: supportedMethods,
	};

	// Go through the same steps used to bootstrap the client to parse the
	// provided route out into a handler request method
	const routeTree = buildRouteTree( routeObj );
	// Parse the mock route object into endpoint factories
	const endpointFactories = generateEndpointFactories( routeTree )[ namespace ];
	const EndpointRequest = endpointFactories[ Object.keys( endpointFactories )[ 0 ] ].Ctor;

	if ( options && options.params ) {
		options.params.forEach( ( param ) => {
			// Only accept string parameters
			if ( typeof param !== 'string' ) {
				return;
			}

			// If the parameter can be mapped to a mixin, apply that mixin
			if ( typeof mixins[ param ] === 'object' ) {
				Object.keys( mixins[ param ] ).forEach( ( key ) => {
					applyMixin( EndpointRequest.prototype, key, mixins[ param ][ key ] );
				} );
				return;
			}

			// Attempt to create a simple setter for any parameters for which
			// we do not already have a custom mixin
			applyMixin( EndpointRequest.prototype, param, paramSetter( param ) );
		} );
	}

	// Set any explicitly-provided object mixins
	if ( options && typeof options.mixins === 'object' ) {

		// Set any specified mixin functions on the response
		Object.keys( options.mixins ).forEach( ( key ) => {
			applyMixin( EndpointRequest.prototype, key, options.mixins[ key ] );
		} );
	}

	function endpointFactory( options = {} ) {
		return new EndpointRequest( {
			...options,
			...( this ? this._options : {} ),
		} );
	}
	endpointFactory.Ctor = EndpointRequest;

	return endpointFactory;
}
function registerRoute( namespace, restBase, options = {} ) {
	// Support all methods until requested to do otherwise
	let supportedMethods = [ 'head', 'get', 'patch', 'put', 'post', 'delete' ];

	if ( Array.isArray( options.methods ) ) {
		// Permit supported methods to be specified as an array
		supportedMethods = options.methods.map( method => method.trim().toLowerCase() );
	} else if ( typeof options.methods === 'string' ) {
		// Permit a supported method to be specified as a string
		supportedMethods = [ options.methods.trim().toLowerCase() ];
	}

	// Ensure that if GET is supported, then HEAD is as well, and vice-versa
	if ( supportedMethods.indexOf( 'get' ) !== -1 && supportedMethods.indexOf( 'head' ) === -1 ) {
		supportedMethods.push( 'head' );
	} else if ( supportedMethods.indexOf( 'head' ) !== -1 && supportedMethods.indexOf( 'get' ) === -1 ) {
		supportedMethods.push( 'get' );
	}

	const fullRoute = namespace
		// Route should always have preceding slash
		.replace( /^[\s/]*/, '/' )
		// Route should always be joined to namespace with a single slash
		.replace( /[\s/]*$/, '/' ) + restBase.replace( /^[\s/]*/, '' );

	const routeObj = {};
	routeObj[ fullRoute ] = {
		namespace: namespace,
		methods: supportedMethods,
	};

	// Go through the same steps used to bootstrap the client to parse the
	// provided route out into a handler request method
	const routeTree = buildRouteTree( routeObj );
	// Parse the mock route object into endpoint factories
	const endpointFactories = generateEndpointFactories( routeTree )[ namespace ];
	const EndpointRequest = endpointFactories[ Object.keys( endpointFactories )[ 0 ] ].Ctor;

	if ( options && options.params ) {
		options.params.forEach( ( param ) => {
			// Only accept string parameters
			if ( typeof param !== 'string' ) {
				return;
			}

			// If the parameter can be mapped to a mixin, apply that mixin
			if ( typeof mixins[ param ] === 'object' ) {
				Object.keys( mixins[ param ] ).forEach( ( key ) => {
					applyMixin( EndpointRequest.prototype, key, mixins[ param ][ key ] );
				} );
				return;
			}

			// Attempt to create a simple setter for any parameters for which
			// we do not already have a custom mixin
			applyMixin( EndpointRequest.prototype, param, paramSetter( param ) );
		} );
	}

	// Set any explicitly-provided object mixins
	if ( options && typeof options.mixins === 'object' ) {

		// Set any specified mixin functions on the response
		Object.keys( options.mixins ).forEach( ( key ) => {
			applyMixin( EndpointRequest.prototype, key, options.mixins[ key ] );
		} );
	}

	function endpointFactory( options = {} ) {
		return new EndpointRequest( {
			...options,
			...( this ? this._options : {} ),
		} );
	}
	endpointFactory.Ctor = EndpointRequest;

	return endpointFactory;
}
function registerRoute ( namespace , restBase , options = { } ) { // Support all methods until requested to do otherwise let supportedMethods = [ 'head' , 'get' , 'patch' , 'put' , 'post' , 'delete' ] ; if ( Array . isArray ( options . methods ) ) { // Permit supported methods to be specified as an array supportedMethods = options . methods . map ( method => method . trim ( ) . toLowerCase ( ) ) ; } else if ( typeof options . methods === 'string' ) { // Permit a supported method to be specified as a string supportedMethods = [ options . methods . trim ( ) . toLowerCase ( ) ] ; } // Ensure that if GET is supported, then HEAD is as well, and vice-versa if ( supportedMethods . indexOf ( 'get' ) !== - 1 && supportedMethods . indexOf ( 'head' ) === - 1 ) { supportedMethods . push ( 'head' ) ; } else if ( supportedMethods . indexOf ( 'head' ) !== - 1 && supportedMethods . indexOf ( 'get' ) === - 1 ) { supportedMethods . push ( 'get' ) ; } const fullRoute = namespace // Route should always have preceding slash . replace ( / ^[\s/]* / , '/' ) // Route should always be joined to namespace with a single slash . replace ( / [\s/]*$ / , '/' ) + restBase . replace ( / ^[\s/]* / , '' ) ; const routeObj = { } ; routeObj [ fullRoute ] = { namespace : namespace , methods : supportedMethods , } ; // Go through the same steps used to bootstrap the client to parse the // provided route out into a handler request method const routeTree = buildRouteTree ( routeObj ) ; // Parse the mock route object into endpoint factories const endpointFactories = generateEndpointFactories ( routeTree ) [ namespace ] ; const EndpointRequest = endpointFactories [ Object . keys ( endpointFactories ) [ 0 ] ] . Ctor ; if ( options && options . params ) { options . params . forEach ( ( param ) => { // Only accept string parameters if ( typeof param !== 'string' ) { return ; } // If the parameter can be mapped to a mixin, apply that mixin if ( typeof mixins [ param ] === 'object' ) { Object . keys ( mixins [ param ] ) . forEach ( ( key ) => { applyMixin ( EndpointRequest . prototype , key , mixins [ param ] [ key ] ) ; } ) ; return ; } // Attempt to create a simple setter for any parameters for which // we do not already have a custom mixin applyMixin ( EndpointRequest . prototype , param , paramSetter ( param ) ) ; } ) ; } // Set any explicitly-provided object mixins if ( options && typeof options . mixins === 'object' ) { // Set any specified mixin functions on the response Object . keys ( options . mixins ) . forEach ( ( key ) => { applyMixin ( EndpointRequest . prototype , key , options . mixins [ key ] ) ; } ) ; } function endpointFactory ( options = { } ) { return new EndpointRequest ( { ... options , ... ( this ? this . _options : { } ) , } ) ; } endpointFactory . Ctor = EndpointRequest ; return endpointFactory ; }
Create and return a handler for an arbitrary WP REST API endpoint.

The first two parameters mirror `register_rest_route` in the REST API
codebase:

@memberof! WPAPI#
@param {string}   namespace         A namespace string, e.g. 'myplugin/v1'
@param {string}   restBase          A REST route string, e.g. '/author/(?P<id>\d+)'
@param {object}   [options]         An (optional) options object
@param {object}   [options.mixins]  A hash of functions to apply as mixins
@param {string[]} [options.methods] An array of methods to whitelist (on the leaf node only)
@returns {Function} An endpoint handler factory function for the specified route
Create and return a handler for an arbitrary WP REST API endpoint .