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

ApiFetch: Script module #60952

Draft
wants to merge 5 commits into
base: trunk
Choose a base branch
from
Draft
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
Original file line number Diff line number Diff line change
Expand Up @@ -191,12 +191,12 @@ public function register_script_modules() {

wp_register_script_module(
'@wordpress/interactivity',
includes_url( "js/dist/interactivity$suffix.js" )
includes_url( "js/dist/script-modules/interactivity$suffix.js" )
);

wp_register_script_module(
'@wordpress/interactivity-router',
includes_url( "js/dist/interactivity-router$suffix.js" ),
includes_url( "js/dist/script-modules/interactivity-router$suffix.js" ),
array( '@wordpress/interactivity' )
);
}
Expand Down
22 changes: 22 additions & 0 deletions lib/experimental/script-modules.php
Original file line number Diff line number Diff line change
Expand Up @@ -197,3 +197,25 @@
_deprecated_function( __FUNCTION__, 'Gutenberg 17.6.0', 'wp_dequeue_script_module' );
wp_script_modules()->dequeue( $module_identifier );
}

add_action(
'init',
function () {
wp_register_script_module( '@wordpress/api-fetch', gutenberg_url( 'build/script-modules/apiFetch.min.js' ) );

// add_filter(
// 'scriptmoduleconfig_@wordpress/api-fetch',

Check failure on line 207 in lib/experimental/script-modules.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Spaces must be used for mid-line alignment; tabs are not allowed
Copy link
Member Author

Choose a reason for hiding this comment

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

This should be restored with the correct filter name:

$data = apply_filters( "script_module_data_{$module_id}", array() );

// function ( $data ) {

Check failure on line 208 in lib/experimental/script-modules.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Spaces must be used for mid-line alignment; tabs are not allowed
// return array_merge(

Check failure on line 209 in lib/experimental/script-modules.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Spaces must be used for mid-line alignment; tabs are not allowed
// $data,

Check failure on line 210 in lib/experimental/script-modules.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Spaces must be used for mid-line alignment; tabs are not allowed
// array(

Check failure on line 211 in lib/experimental/script-modules.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Spaces must be used for mid-line alignment; tabs are not allowed
// 'rootURL' => sanitize_url( get_rest_url() ),

Check failure on line 212 in lib/experimental/script-modules.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Spaces must be used for mid-line alignment; tabs are not allowed
// 'nonce' => wp_installing() ? '' : wp_create_nonce( 'wp_rest' ),

Check failure on line 213 in lib/experimental/script-modules.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Spaces must be used for mid-line alignment; tabs are not allowed
// 'shouldRegisterMediaUploadMiddleware' => true,

Check failure on line 214 in lib/experimental/script-modules.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Spaces must be used for mid-line alignment; tabs are not allowed
// 'nonceEndpoint' => admin_url( 'admin-ajax.php?action=rest-nonce' ),

Check failure on line 215 in lib/experimental/script-modules.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Spaces must be used for mid-line alignment; tabs are not allowed
// )

Check failure on line 216 in lib/experimental/script-modules.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Spaces must be used for mid-line alignment; tabs are not allowed
// );
// }
// );
}
);
4 changes: 2 additions & 2 deletions lib/interactivity-api.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ function gutenberg_reregister_interactivity_script_modules() {

wp_register_script_module(
'@wordpress/interactivity',
gutenberg_url( '/build/interactivity/' . ( SCRIPT_DEBUG ? 'debug.min.js' : 'index.min.js' ) ),
gutenberg_url( '/build/script-modules/interactivity/' . ( SCRIPT_DEBUG ? 'debug.min.js' : 'index.min.js' ) ),
array(),
$default_version
);

wp_register_script_module(
'@wordpress/interactivity-router',
gutenberg_url( '/build/interactivity/router.min.js' ),
gutenberg_url( '/build/script-modules/interactivity/router.min.js' ),
array( '@wordpress/interactivity' ),
$default_version
);
Expand Down
1 change: 1 addition & 0 deletions packages/api-fetch/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
},
"main": "build/index.js",
"module": "build-module/index.js",
"wp-module": "build-module/wp-module.js",
"react-native": "src/index",
"types": "build-types",
"dependencies": {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,11 @@
/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
//import { __ } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import createNonceMiddleware from './middlewares/nonce';
import createRootURLMiddleware from './middlewares/root-url';
import createPreloadingMiddleware from './middlewares/preloading';
import fetchAllMiddleware from './middlewares/fetch-all-middleware';
import namespaceEndpointMiddleware from './middlewares/namespace-endpoint';
import httpV1Middleware from './middlewares/http-v1';
import userLocaleMiddleware from './middlewares/user-locale';
import mediaUploadMiddleware from './middlewares/media-upload';
import createThemePreviewMiddleware from './middlewares/theme-preview';
import {
parseResponseAndNormalizeError,
parseAndThrowError,
Expand Down Expand Up @@ -44,28 +35,6 @@ const DEFAULT_OPTIONS = {
credentials: 'include',
};

/** @typedef {import('./types').APIFetchMiddleware} APIFetchMiddleware */
/** @typedef {import('./types').APIFetchOptions} APIFetchOptions */

/**
* @type {import('./types').APIFetchMiddleware[]}
*/
const middlewares = [
userLocaleMiddleware,
namespaceEndpointMiddleware,
httpV1Middleware,
fetchAllMiddleware,
];

/**
* Register a middleware
*
* @param {import('./types').APIFetchMiddleware} middleware
*/
function registerMiddleware( middleware ) {
middlewares.unshift( middleware );
}

/**
* Checks the status of a response, throwing the Response as an error if
* it is outside the 200 range.
Expand Down Expand Up @@ -128,7 +97,7 @@ const defaultFetchHandler = ( nextOptions ) => {
// Unfortunately the message might depend on the browser.
throw {
code: 'fetch_error',
message: __( 'You are probably offline.' ),
message: 'You are probably offline.',
};
}
);
Expand All @@ -143,16 +112,23 @@ let fetchHandler = defaultFetchHandler;
*
* @param {FetchHandler} newFetchHandler The new fetch handler
*/
function setFetchHandler( newFetchHandler ) {
export function setFetchHandler( newFetchHandler ) {
fetchHandler = newFetchHandler;
}

/** @type { typeof import('./middlewares/singleton').middlewares } */
let middlewares;

/**
* @template T
* @param {import('./types').APIFetchOptions} options
* @return {Promise<T>} A promise representing the request processed via the registered middlewares.
*/
function apiFetch( options ) {
export async function apiFetch( options ) {
if ( ! middlewares ) {
middlewares = ( await import( './middlewares/singleton' ) ).middlewares;
}

// creates a nested function chain that calls all middlewares and finally the `fetchHandler`,
// converting `middlewares = [ m1, m2, m3 ]` into:
// ```
Expand Down Expand Up @@ -185,15 +161,3 @@ function apiFetch( options ) {
);
} );
}

apiFetch.use = registerMiddleware;
apiFetch.setFetchHandler = setFetchHandler;

apiFetch.createNonceMiddleware = createNonceMiddleware;
apiFetch.createPreloadingMiddleware = createPreloadingMiddleware;
apiFetch.createRootURLMiddleware = createRootURLMiddleware;
apiFetch.fetchAllMiddleware = fetchAllMiddleware;
apiFetch.mediaUploadMiddleware = mediaUploadMiddleware;
apiFetch.createThemePreviewMiddleware = createThemePreviewMiddleware;

export default apiFetch;
39 changes: 39 additions & 0 deletions packages/api-fetch/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/**
* Internal dependencies
*/
import { createNonceMiddleware } from './middlewares/nonce';
import { createRootURLMiddleware } from './middlewares/root-url';
import { createPreloadingMiddleware } from './middlewares/preloading';
import { fetchAllMiddleware } from './middlewares/fetch-all-middleware';
import { mediaUploadMiddleware } from './middlewares/media-upload';
import { createThemePreviewMiddleware } from './middlewares/theme-preview';
import * as ApiFetchCore from './core';
import { type APIFetchOptions } from './types';
import { registerMiddleware } from './middlewares/singleton';

export interface ApiFetch {
< T >( options: APIFetchOptions ): Promise< T >;
use: typeof registerMiddleware;
setFetchHandler: typeof ApiFetchCore.setFetchHandler;
createNonceMiddleware: typeof createNonceMiddleware;
createPreloadingMiddleware: typeof createPreloadingMiddleware;
createRootURLMiddleware: typeof createRootURLMiddleware;
fetchAllMiddleware: typeof fetchAllMiddleware;
mediaUploadMiddleware: typeof mediaUploadMiddleware;
createThemePreviewMiddleware: typeof createThemePreviewMiddleware;
}

// @ts-expect-error This is an incomplete type we'll add properties to.
const apiFetch: ApiFetch = ApiFetchCore.apiFetch;

apiFetch.use = registerMiddleware;
apiFetch.setFetchHandler = ApiFetchCore.setFetchHandler;
apiFetch.createNonceMiddleware = createNonceMiddleware;
apiFetch.createPreloadingMiddleware = createPreloadingMiddleware;
apiFetch.createRootURLMiddleware = createRootURLMiddleware;
apiFetch.fetchAllMiddleware = fetchAllMiddleware;
apiFetch.mediaUploadMiddleware = mediaUploadMiddleware;
apiFetch.createThemePreviewMiddleware = createThemePreviewMiddleware;

export { apiFetch as default };
export type { APIFetchOptions };
50 changes: 36 additions & 14 deletions packages/api-fetch/src/middlewares/fetch-all-middleware.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
/**
* WordPress dependencies
*/
import { addQueryArgs } from '@wordpress/url';

/**
* Internal dependencies
*/
import apiFetch from '..';
import { apiFetch } from '../core';

/**
* Apply query arguments to both URL and Path, whichever is present.
Expand All @@ -15,11 +10,40 @@ import apiFetch from '..';
* @param {Record<string, string | number>} queryArgs
* @return {import('../types').APIFetchOptions} The request with the modified query args
*/
const modifyQuery = ( { path, url, ...options }, queryArgs ) => ( {
...options,
url: url && addQueryArgs( url, queryArgs ),
path: path && addQueryArgs( path, queryArgs ),
} );
const modifyQuery = ( { path, url, ...options }, queryArgs ) => {
/** @type {import('../types').APIFetchOptions} */
const result = {
...options,
};

if ( url ) {
try {
const u = new URL( url );
for ( const [ key, value ] of Object.entries( queryArgs ) ) {
u.searchParams.set( key, String( value ) );
}
console.log( { url, href: u.href } );
result.url = u.href;
} catch {
const u = new URL( url, 'invalid://__placeholder__' );
for ( const [ key, value ] of Object.entries( queryArgs ) ) {
u.searchParams.set( key, String( value ) );
}
console.log( { url, pathname: u.pathname } );
result.url = u.pathname;
}
}

if ( path ) {
const u = new URL( path, 'invalid://__placeholder__' );
for ( const [ key, value ] of Object.entries( queryArgs ) ) {
u.searchParams.set( key, String( value ) );
}
result.path = u.pathname;
}

return result;
};

/**
* Duplicates parsing functionality from apiFetch.
Expand Down Expand Up @@ -74,7 +98,7 @@ const requestContainsUnboundedQuery = ( options ) => {
*
* @type {import('../types').APIFetchMiddleware}
*/
const fetchAllMiddleware = async ( options, next ) => {
export const fetchAllMiddleware = async ( options, next ) => {
if ( options.parse === false ) {
// If a consumer has opted out of parsing, do not apply middleware.
return next( options );
Expand Down Expand Up @@ -124,5 +148,3 @@ const fetchAllMiddleware = async ( options, next ) => {
}
return mergedResults;
};

export default fetchAllMiddleware;
4 changes: 1 addition & 3 deletions packages/api-fetch/src/middlewares/http-v1.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const DEFAULT_METHOD = 'GET';
*
* @type {import('../types').APIFetchMiddleware}
*/
const httpV1Middleware = ( options, next ) => {
export const httpV1Middleware = ( options, next ) => {
const { method = DEFAULT_METHOD } = options;
if ( OVERRIDE_METHODS.has( method.toUpperCase() ) ) {
options = {
Expand All @@ -39,5 +39,3 @@ const httpV1Middleware = ( options, next ) => {

return next( options );
};

export default httpV1Middleware;
11 changes: 4 additions & 7 deletions packages/api-fetch/src/middlewares/media-upload.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
//import { __ } from '@wordpress/i18n';

/**
* Internal dependencies
Expand Down Expand Up @@ -29,7 +29,7 @@ function isMediaUploadRequest( options ) {
*
* @type {import('../types').APIFetchMiddleware}
*/
const mediaUploadMiddleware = ( options, next ) => {
export const mediaUploadMiddleware = ( options, next ) => {
if ( ! isMediaUploadRequest( options ) ) {
return next( options );
}
Expand Down Expand Up @@ -75,9 +75,8 @@ const mediaUploadMiddleware = ( options, next ) => {
if ( options.parse !== false ) {
return Promise.reject( {
code: 'post_process',
message: __(
'Media upload failed. If this is a photo or a large image, please scale it down and try again.'
),
message:
'Media upload failed. If this is a photo or a large image, please scale it down and try again.',
} );
}

Expand All @@ -90,5 +89,3 @@ const mediaUploadMiddleware = ( options, next ) => {
parseResponseAndNormalizeError( response, options.parse )
);
};

export default mediaUploadMiddleware;
4 changes: 1 addition & 3 deletions packages/api-fetch/src/middlewares/namespace-endpoint.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* @type {import('../types').APIFetchMiddleware}
*/
const namespaceAndEndpointMiddleware = ( options, next ) => {
export const namespaceEndpointMiddleware = ( options, next ) => {
let path = options.path;
let namespaceTrimmed, endpointTrimmed;

Expand All @@ -26,5 +26,3 @@ const namespaceAndEndpointMiddleware = ( options, next ) => {
path,
} );
};

export default namespaceAndEndpointMiddleware;
4 changes: 1 addition & 3 deletions packages/api-fetch/src/middlewares/nonce.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* @param {string} nonce
* @return {import('../types').APIFetchMiddleware & { nonce: string }} A middleware to enhance a request with a nonce.
*/
function createNonceMiddleware( nonce ) {
export function createNonceMiddleware( nonce ) {
/**
* @type {import('../types').APIFetchMiddleware & { nonce: string }}
*/
Expand Down Expand Up @@ -33,5 +33,3 @@ function createNonceMiddleware( nonce ) {

return middleware;
}

export default createNonceMiddleware;
Loading
Loading