Skip to content

Commit

Permalink
Core Data: Fixes necessary for converting to TypeScript
Browse files Browse the repository at this point in the history
  • Loading branch information
dmsnell authored and adamziel committed Mar 17, 2022
1 parent c04262b commit 7215537
Show file tree
Hide file tree
Showing 16 changed files with 136 additions and 60 deletions.
2 changes: 1 addition & 1 deletion docs/reference-guides/data/data-core.md
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ _Parameters_
- _state_ `Object`: State tree.
- _kind_ `string`: Entity kind.
- _name_ `string`: Entity name.
- _recordId_ `number`: Record ID.
- _recordId_ `number|string`: Record ID.

_Returns_

Expand Down
2 changes: 1 addition & 1 deletion packages/core-data/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -646,7 +646,7 @@ _Parameters_
- _state_ `Object`: State tree.
- _kind_ `string`: Entity kind.
- _name_ `string`: Entity name.
- _recordId_ `number`: Record ID.
- _recordId_ `number|string`: Record ID.

_Returns_

Expand Down
1 change: 1 addition & 0 deletions packages/core-data/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"main": "build/index.js",
"module": "build-module/index.js",
"react-native": "src/index",
"types": "build-types",
"sideEffects": [
"{src,build,build-module}/index.js"
],
Expand Down
5 changes: 3 additions & 2 deletions packages/core-data/src/batch/default-processor.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import apiFetch from '@wordpress/api-fetch';
* Maximum number of requests to place in a single batch request. Obtained by
* sending a preflight OPTIONS request to /batch/v1/.
*
* @type {number?}
* @type {number|null}
* @default 25 (set by Core)
*/
let maxItems = null;

Expand All @@ -36,7 +37,7 @@ export default async function defaultProcessor( requests ) {

const results = [];

for ( const batchRequests of chunk( requests, maxItems ) ) {
for ( const batchRequests of chunk( requests, maxItems ?? 25 ) ) {
const batchResponse = await apiFetch( {
path: '/batch/v1',
method: 'POST',
Expand Down
1 change: 0 additions & 1 deletion packages/core-data/src/entities.js
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,6 @@ export const getMethodName = (
* Loads the kind entities into the store.
*
* @param {string} kind Kind
*
* @return {(thunkArgs: object) => Promise<Array>} Entities
*/
export const getOrLoadEntitiesConfig = ( kind ) => async ( {
Expand Down
2 changes: 2 additions & 0 deletions packages/core-data/src/entity-provider.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ const EMPTY_ARRAY = [];
*/
import { rootEntitiesConfig, additionalEntityConfigLoaders } from './entities';

/** @typedef {import('@wordpress/blocks').WPBlock} WPBlock */

const entityContexts = {
...rootEntitiesConfig.reduce( ( acc, loader ) => {
if ( ! acc[ loader.kind ] ) {
Expand Down
8 changes: 4 additions & 4 deletions packages/core-data/src/hooks/use-entity-records.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ interface Options {
/**
* Resolves the specified entity records.
*
* @param kind Kind of the requested entities.
* @param name Name of the requested entities.
* @param queryArgs HTTP query for the requested entities.
* @param options Hook options.
* @param kind Kind of the requested entities.
* @param name Name of the requested entities.
* @param queryArgs HTTP query for the requested entities.
* @param options Hook options.
* @example
* ```js
* import { useEntityRecord } from '@wordpress/core-data';
Expand Down
23 changes: 14 additions & 9 deletions packages/core-data/src/hooks/use-query-select.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ export const META_SELECTORS = [
'getCachedResolvers',
];

interface QuerySelectResponse {
interface QuerySelectResponse< Data > {
/** the requested selector return value */
data: Object;
data: Data;

/** is the record still being resolved? Via the `getIsResolving` meta-selector */
isResolving: boolean;
Expand Down Expand Up @@ -78,19 +78,24 @@ export default function __experimentalUseQuerySelect( mapQuerySelect, deps ) {
}, deps );
}

type QuerySelector = ( ...args ) => QuerySelectResponse;
interface EnrichedSelectors {
[ key: string ]: QuerySelector;
interface EnrichSelectors {
< Selectors extends Record< string, ( ...args: any ) => any > >(
selectors: Selectors
): {
[ Selector in keyof Selectors ]: (
...args: Parameters< Selectors[ Selector ] >
) => QuerySelectResponse< ReturnType< Selectors[ Selector ] > >;
};
}

/**
* Transform simple selectors into ones that return an object with the
* original return value AND the resolution info.
*
* @param {Object} selectors Selectors to enrich
* @return {EnrichedSelectors} Enriched selectors
* @param selectors Selectors to enrich
* @return Enriched selectors
*/
const enrichSelectors = memoize( ( selectors ) => {
const enrichSelectors = memoize( ( ( selectors ) => {
const resolvers = {};
for ( const selectorName in selectors ) {
if ( META_SELECTORS.includes( selectorName ) ) {
Expand Down Expand Up @@ -128,4 +133,4 @@ const enrichSelectors = memoize( ( selectors ) => {
} );
}
return resolvers;
} );
} ) as EnrichSelectors );
Original file line number Diff line number Diff line change
Expand Up @@ -330,12 +330,15 @@ function entity( entityConfig ) {
/**
* Reducer keeping track of the registered entities.
*
* @param {Object} state Current state.
* @param {Object} action Dispatched action.
* @param state Current state.
* @param action Dispatched action.
*
* @return {Object} Updated state.
* @return Updated state.
*/
export function entitiesConfig( state = rootEntitiesConfig, action ) {
export function entitiesConfig(
state = rootEntitiesConfig as EntityConfig[],
action
): EntityConfig[] {
switch ( action.type ) {
case 'ADD_ENTITIES':
return [ ...state, ...action.entities ];
Expand All @@ -345,14 +348,40 @@ export function entitiesConfig( state = rootEntitiesConfig, action ) {
}

/**
* Reducer keeping track of the registered entities config and data.
* Placeholder for an entity config record.
*
* @param {Object} state Current state.
* @param {Object} action Dispatched action.
* TODO: Replace once we have an official type for this.
*
* @return {Object} Updated state.
* @see #39481
*/
export const entities = ( state = {}, action ) => {
interface EntityConfig extends Record< string, any > {
baseURL?: string;
baseURLParams?: Record< string, string | number >;
getTitle?(): ( record: unknown ) => string;
key?: string;
kind: string;
label?: string;
name: string;
plural?: string;
rawAttributes?: string[];
title?: string;
transientEdits?: { blocks: boolean };
}

interface EntityState {
config: EntityConfig[];
records: Record< string, any >;
reducer< State >( state: State, action: Record< string, any > ): State;
}

/**
* Reducer keeping track of the registered entities config and data.
*
* @param state Current state.
* @param action Dispatched action.
* @return Updated state.
*/
export const entities = ( state = {} as EntityState, action ): EntityState => {
const newConfig = entitiesConfig( state.config, action );

// Generates a dynamic reducer for the entities.
Expand Down Expand Up @@ -397,18 +426,26 @@ export const entities = ( state = {}, action ) => {
};
};

interface UndoState extends Array< object > {
offset: number;
flattenedUndo?: object;
}

const UNDO_INITIAL_STATE: UndoState = Object.assign( [], { offset: 0 } );
let lastEditAction;

/**
* Reducer keeping track of entity edit undo history.
*
* @param {Object} state Current state.
* @param {Object} action Dispatched action.
* @param state Current state.
* @param action Dispatched action.
*
* @return {Object} Updated state.
* @return Updated state.
*/
const UNDO_INITIAL_STATE = [];
UNDO_INITIAL_STATE.offset = 0;
let lastEditAction;
export function undo( state = UNDO_INITIAL_STATE, action ) {
export function undo(
state = UNDO_INITIAL_STATE,
action: Record< string, any >
): UndoState {
switch ( action.type ) {
case 'EDIT_ENTITY_RECORD':
case 'CREATE_UNDO_LEVEL':
Expand Down
9 changes: 5 additions & 4 deletions packages/core-data/src/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ export const getEntityRecord = createSelector(
if ( item && query._fields ) {
const filteredItem = {};
const fields = getNormalizedCommaSeparable( query._fields ) ?? [];

for ( let f = 0; f < fields.length; f++ ) {
const field = fields[ f ].split( '.' );
const value = get( item, field );
Expand Down Expand Up @@ -501,10 +502,10 @@ export const getEntityRecordNonTransientEdits = createSelector(
* Returns true if the specified entity record has edits,
* and false otherwise.
*
* @param {Object} state State tree.
* @param {string} kind Entity kind.
* @param {string} name Entity name.
* @param {number} recordId Record ID.
* @param {Object} state State tree.
* @param {string} kind Entity kind.
* @param {string} name Entity name.
* @param {number|string} recordId Record ID.
*
* @return {boolean} Whether the entity record has edits or not.
*/
Expand Down
18 changes: 0 additions & 18 deletions packages/core-data/src/utils/if-matching-action.js

This file was deleted.

28 changes: 28 additions & 0 deletions packages/core-data/src/utils/if-matching-action.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
interface Action extends Record< string, any > {
type: string;
}

/**
* A higher-order reducer creator which invokes the original reducer only if
* the dispatching action matches the given predicate, **OR** if state is
* initializing (undefined).
*
* @param isMatch Function predicate for allowing reducer call.
* @return Higher-order reducer.
*/
const ifMatchingAction = <
Matcher extends ( action: Action ) => boolean,
State,
Reducer extends ( state: State, action: Action ) => State
>(
isMatch: Matcher
) => ( reducer: Reducer ) =>
( ( state, action ) => {
if ( state === undefined || isMatch( action ) ) {
return reducer( state, action );
}

return state;
} ) as Reducer;

export default ifMatchingAction;
2 changes: 1 addition & 1 deletion packages/core-data/src/utils/on-sub-key.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*
* @param {string} actionProperty Action property by which to key object.
*
* @return {Function} Higher-order reducer.
* @return {(...args: any[]) => any} Higher-order reducer.
*/
export const onSubKey = ( actionProperty ) => ( reducer ) => (
state = {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@
* Higher-order reducer creator which substitutes the action object before
* passing to the original reducer.
*
* @param {Function} replacer Function mapping original action to replacement.
*
* @return {Function} Higher-order reducer.
* @param replacer Function mapping original action to replacement.
* @return Higher-order reducer.
*/
const replaceAction = ( replacer ) => ( reducer ) => ( state, action ) => {
return reducer( state, replacer( action ) );
Expand Down
20 changes: 20 additions & 0 deletions packages/core-data/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"rootDir": "src",
"declarationDir": "build-types",
"noUnusedParameters": false,
"noImplicitAny": false
},
"references": [
{ "path": "../compose" },
{ "path": "../deprecated" },
{ "path": "../data" },
{ "path": "../element" },
{ "path": "../is-shallow-equal" },
{ "path": "../priority-queue" },
{ "path": "../redux-routine" },
{ "path": "../url" }
],
"include": [ "src/**/*.js", "src/**/*.tsx", "src/**/*.ts" ]
}
1 change: 1 addition & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
{ "path": "packages/block-editor" },
{ "path": "packages/components" },
{ "path": "packages/compose" },
{ "path": "packages/core-data" },
{ "path": "packages/data" },
{ "path": "packages/date" },
{ "path": "packages/deprecated" },
Expand Down

0 comments on commit 7215537

Please sign in to comment.