/**
 * Module-data data store
 *
 * Site Kit by Google, Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * External dependencies
 */
import invariant from 'invariant';

/**
 * Internal dependencies
 */
import Data from 'googlesitekit-data';
import { MODULES_IDEA_HUB } from './constants';

const { createRegistrySelector } = Data;

function getIdeaHubDataProperty( propName ) {
	return createRegistrySelector( ( select ) => () => {
		const ideaHubData = select( MODULES_IDEA_HUB ).getIdeaHubData() || {};
		return ideaHubData[ propName ];
	} );
}

const RECEIVE_IDEA_HUB_DATA = 'RECEIVE_IDEA_HUB_DATA';

const initialState = {
	ideaHubData: undefined,
};

export const actions = {
	/**
	 * Stores module data in the datastore.
	 *
	 * Because we need to keep track of changes (e.g. to the
	 * state of Idea Hub posts) from the back end, this data
	 * is sourced from a PHP-to-JS global `_googlesitekitIdeaHub`.
	 * For an example see `on_idea_hub_post_status_transition` in
	 * `includes/Modules/Idea_Hub.php`.
	 *
	 * @since n.e.x.t
	 *
	 * @param {Object} ideaHubData Module data, via a PHP-to-JS global.
	 * @return {Object} Redux-style action.
	 */
	receiveIdeaHubData( ideaHubData ) {
		invariant( ideaHubData, 'Idea Hub data is required.' );
		return {
			payload: ideaHubData,
			type: RECEIVE_IDEA_HUB_DATA,
		};
	},
};

export const controls = {};

export const reducer = ( state, { type, payload } ) => {
	switch ( type ) {
		case RECEIVE_IDEA_HUB_DATA: {
			const { lastIdeaPostUpdatedAt } = payload;
			return {
				...state,
				ideaHubData: {
					lastIdeaPostUpdatedAt,
				},
			};
		}
		default: {
			return state;
		}
	}
};

export const resolvers = {
	*getIdeaHubData() {
		const { select } = yield Data.commonActions.getRegistry();

		if ( select( MODULES_IDEA_HUB ).getIdeaHubData() !== undefined ) {
			return;
		}

		if ( ! global._googlesitekitIdeaHub ) {
			global.console.error( ' Could not load modules/idea-hub data.' );
			return;
		}

		const { lastIdeaPostUpdatedAt } = global._googlesitekitIdeaHub;

		yield actions.receiveIdeaHubData( {
			lastIdeaPostUpdatedAt,
		} );
	},
};

export const selectors = {
	/**
	 * Gets all Idea Hub data.
	 *
	 * @since n.e.x.t
	 *
	 * @param {Object} state Data store's state.
	 * @return {Object} Idea Hub data object.
	 */
	getIdeaHubData( state ) {
		return state.ideaHubData;
	},
	/**
	 * Gets the timestamp of the last state update to an Idea Hub post.
	 *
	 * @since n.e.x.t
	 *
	 * @param {Object} state Data store's state.
	 * @return {string} Last updated timestamp.
	 */
	getLastIdeaPostUpdatedAt: getIdeaHubDataProperty( 'lastIdeaPostUpdatedAt' ),
};

export default {
	initialState,
	actions,
	controls,
	reducer,
	resolvers,
	selectors,
};

@@ -706,16 +706,66 @@
 ariant';
+%0Aimport isPlainObject from 'lodash/isPlainObject';
 %0A%0A/**%0A *
@@ -1791,16 +1791,31 @@
 variant(
+ isPlainObject(
  ideaHub
@@ -1818,16 +1818,18 @@
 aHubData
+ )
 , 'Idea 

Validate ideaHubData with isPlainObject.