@wordpress/core-data 7.37.1-next.v.0 → 7.38.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2 -0
- package/build/actions.cjs +14 -2
- package/build/actions.cjs.map +2 -2
- package/build/entities.cjs +35 -45
- package/build/entities.cjs.map +2 -2
- package/build/private-selectors.cjs +2 -4
- package/build/private-selectors.cjs.map +2 -2
- package/build/resolvers.cjs +11 -2
- package/build/resolvers.cjs.map +2 -2
- package/build/types.cjs.map +1 -1
- package/build/utils/crdt-blocks.cjs +63 -41
- package/build/utils/crdt-blocks.cjs.map +2 -2
- package/build/utils/crdt-utils.cjs +44 -0
- package/build/utils/crdt-utils.cjs.map +7 -0
- package/build/utils/crdt.cjs +33 -37
- package/build/utils/crdt.cjs.map +2 -2
- package/build-module/actions.mjs +14 -2
- package/build-module/actions.mjs.map +2 -2
- package/build-module/entities.mjs +35 -47
- package/build-module/entities.mjs.map +2 -2
- package/build-module/private-selectors.mjs +2 -4
- package/build-module/private-selectors.mjs.map +2 -2
- package/build-module/resolvers.mjs +11 -2
- package/build-module/resolvers.mjs.map +2 -2
- package/build-module/utils/crdt-blocks.mjs +64 -42
- package/build-module/utils/crdt-blocks.mjs.map +2 -2
- package/build-module/utils/crdt-utils.mjs +17 -0
- package/build-module/utils/crdt-utils.mjs.map +7 -0
- package/build-module/utils/crdt.mjs +37 -37
- package/build-module/utils/crdt.mjs.map +2 -2
- package/build-types/actions.d.ts.map +1 -1
- package/build-types/entities.d.ts.map +1 -1
- package/build-types/index.d.ts.map +1 -1
- package/build-types/private-selectors.d.ts.map +1 -1
- package/build-types/resolvers.d.ts.map +1 -1
- package/build-types/types.d.ts +0 -5
- package/build-types/types.d.ts.map +1 -1
- package/build-types/utils/crdt-blocks.d.ts +14 -5
- package/build-types/utils/crdt-blocks.d.ts.map +1 -1
- package/build-types/utils/crdt-utils.d.ts +53 -0
- package/build-types/utils/crdt-utils.d.ts.map +1 -0
- package/build-types/utils/crdt.d.ts +19 -1
- package/build-types/utils/crdt.d.ts.map +1 -1
- package/package.json +18 -18
- package/src/actions.js +13 -2
- package/src/entities.js +38 -54
- package/src/private-selectors.ts +3 -4
- package/src/resolvers.js +15 -7
- package/src/test/entities.js +11 -9
- package/src/test/resolvers.js +3 -45
- package/src/types.ts +0 -6
- package/src/utils/crdt-blocks.ts +101 -99
- package/src/utils/crdt-utils.ts +77 -0
- package/src/utils/crdt.ts +76 -57
- package/src/utils/test/crdt.ts +28 -16
package/build/resolvers.cjs.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/resolvers.js"],
|
|
4
|
-
"sourcesContent": ["/**\n * External dependencies\n */\nimport { camelCase } from 'change-case';\n\n/**\n * WordPress dependencies\n */\nimport { addQueryArgs } from '@wordpress/url';\nimport { decodeEntities } from '@wordpress/html-entities';\nimport apiFetch from '@wordpress/api-fetch';\n\n/**\n * Internal dependencies\n */\nimport { STORE_NAME } from './name';\nimport { additionalEntityConfigLoaders, DEFAULT_ENTITY_KEY } from './entities';\nimport { getSyncManager } from './sync';\nimport {\n\tforwardResolver,\n\tgetNormalizedCommaSeparable,\n\tgetUserPermissionCacheKey,\n\tgetUserPermissionsFromAllowHeader,\n\tALLOWED_RESOURCE_ACTIONS,\n\tRECEIVE_INTERMEDIATE_RESULTS,\n\tisNumericID,\n} from './utils';\nimport { fetchBlockPatterns } from './fetch';\n\n/**\n * Requests authors from the REST API.\n *\n * @param {Object|undefined} query Optional object of query parameters to\n * include with request.\n */\nexport const getAuthors =\n\t( query ) =>\n\tasync ( { dispatch } ) => {\n\t\tconst path = addQueryArgs(\n\t\t\t'/wp/v2/users/?who=authors&per_page=100',\n\t\t\tquery\n\t\t);\n\t\tconst users = await apiFetch( { path } );\n\t\tdispatch.receiveUserQuery( path, users );\n\t};\n\n/**\n * Requests the current user from the REST API.\n */\nexport const getCurrentUser =\n\t() =>\n\tasync ( { dispatch } ) => {\n\t\tconst currentUser = await apiFetch( { path: '/wp/v2/users/me' } );\n\t\tdispatch.receiveCurrentUser( currentUser );\n\t};\n\n/**\n * Requests an entity's record from the REST API.\n *\n * @param {string} kind Entity kind.\n * @param {string} name Entity name.\n * @param {number|string} key Record's key\n * @param {Object|undefined} query Optional object of query parameters to\n * include with request. If requesting specific\n * fields, fields must always include the ID.\n */\nexport const getEntityRecord =\n\t( kind, name, key = '', query ) =>\n\tasync ( { select, dispatch, registry, resolveSelect } ) => {\n\t\tconst configs = await resolveSelect.getEntitiesConfig( kind );\n\t\tconst entityConfig = configs.find(\n\t\t\t( config ) => config.name === name && config.kind === kind\n\t\t);\n\t\tif ( ! entityConfig ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst lock = await dispatch.__unstableAcquireStoreLock(\n\t\t\tSTORE_NAME,\n\t\t\t[ 'entities', 'records', kind, name, key ],\n\t\t\t{ exclusive: false }\n\t\t);\n\n\t\ttry {\n\t\t\tif ( query !== undefined && query._fields ) {\n\t\t\t\t// If requesting specific fields, items and query association to said\n\t\t\t\t// records are stored by ID reference. Thus, fields must always include\n\t\t\t\t// the ID.\n\t\t\t\tquery = {\n\t\t\t\t\t...query,\n\t\t\t\t\t_fields: [\n\t\t\t\t\t\t...new Set( [\n\t\t\t\t\t\t\t...( getNormalizedCommaSeparable( query._fields ) ||\n\t\t\t\t\t\t\t\t[] ),\n\t\t\t\t\t\t\tentityConfig.key || DEFAULT_ENTITY_KEY,\n\t\t\t\t\t\t] ),\n\t\t\t\t\t].join(),\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tif ( query !== undefined && query._fields ) {\n\t\t\t\t// The resolution cache won't consider query as reusable based on the\n\t\t\t\t// fields, so it's tested here, prior to initiating the REST request,\n\t\t\t\t// and without causing `getEntityRecord` resolution to occur.\n\t\t\t\tconst hasRecord = select.hasEntityRecord(\n\t\t\t\t\tkind,\n\t\t\t\t\tname,\n\t\t\t\t\tkey,\n\t\t\t\t\tquery\n\t\t\t\t);\n\t\t\t\tif ( hasRecord ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlet { baseURL } = entityConfig;\n\n\t\t\t// For \"string\" IDs, use the old templates endpoint.\n\t\t\tif (\n\t\t\t\tkind === 'postType' &&\n\t\t\t\tname === 'wp_template' &&\n\t\t\t\t( ( key && typeof key === 'string' && ! /^\\d+$/.test( key ) ) ||\n\t\t\t\t\t! window?.__experimentalTemplateActivate )\n\t\t\t) {\n\t\t\t\tbaseURL =\n\t\t\t\t\tbaseURL.slice( 0, baseURL.lastIndexOf( '/' ) ) +\n\t\t\t\t\t'/templates';\n\t\t\t}\n\n\t\t\tconst path = addQueryArgs( baseURL + ( key ? '/' + key : '' ), {\n\t\t\t\t...entityConfig.baseURLParams,\n\t\t\t\t...query,\n\t\t\t} );\n\t\t\tconst response = await apiFetch( { path, parse: false } );\n\t\t\tconst record = await response.json();\n\t\t\tconst permissions = getUserPermissionsFromAllowHeader(\n\t\t\t\tresponse.headers?.get( 'allow' )\n\t\t\t);\n\n\t\t\tconst canUserResolutionsArgs = [];\n\t\t\tconst receiveUserPermissionArgs = {};\n\t\t\tfor ( const action of ALLOWED_RESOURCE_ACTIONS ) {\n\t\t\t\treceiveUserPermissionArgs[\n\t\t\t\t\tgetUserPermissionCacheKey( action, {\n\t\t\t\t\t\tkind,\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tid: key,\n\t\t\t\t\t} )\n\t\t\t\t] = permissions[ action ];\n\n\t\t\t\tcanUserResolutionsArgs.push( [\n\t\t\t\t\taction,\n\t\t\t\t\t{ kind, name, id: key },\n\t\t\t\t] );\n\t\t\t}\n\n\t\t\t// Entity supports syncing.\n\t\t\tif (\n\t\t\t\twindow.__experimentalEnableSync &&\n\t\t\t\tentityConfig.syncConfig &&\n\t\t\t\tisNumericID( key ) &&\n\t\t\t\t! query\n\t\t\t) {\n\t\t\t\tif ( globalThis.IS_GUTENBERG_PLUGIN ) {\n\t\t\t\t\tconst objectType = `${ kind }/${ name }`;\n\t\t\t\t\tconst objectId = key;\n\n\t\t\t\t\t// Use the new transient \"read/write\" config to compute transients for\n\t\t\t\t\t// the sync manager. Otherwise these transients are not available\n\t\t\t\t\t// if / until the record is edited. Use a copy of the record so that\n\t\t\t\t\t// it does not change the behavior outside this experimental flag.\n\t\t\t\t\tconst recordWithTransients = { ...record };\n\t\t\t\t\tObject.entries( entityConfig.transientEdits ?? {} )\n\t\t\t\t\t\t.filter(\n\t\t\t\t\t\t\t( [ propName, transientConfig ] ) =>\n\t\t\t\t\t\t\t\tundefined ===\n\t\t\t\t\t\t\t\t\trecordWithTransients[ propName ] &&\n\t\t\t\t\t\t\t\ttransientConfig &&\n\t\t\t\t\t\t\t\t'object' === typeof transientConfig &&\n\t\t\t\t\t\t\t\t'read' in transientConfig &&\n\t\t\t\t\t\t\t\t'function' === typeof transientConfig.read\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.forEach( ( [ propName, transientConfig ] ) => {\n\t\t\t\t\t\t\trecordWithTransients[ propName ] =\n\t\t\t\t\t\t\t\ttransientConfig.read( recordWithTransients );\n\t\t\t\t\t\t} );\n\n\t\t\t\t\t// Load the entity record for syncing.\n\t\t\t\t\tawait getSyncManager()?.load(\n\t\t\t\t\t\tentityConfig.syncConfig,\n\t\t\t\t\t\tobjectType,\n\t\t\t\t\t\tobjectId,\n\t\t\t\t\t\trecordWithTransients,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// Handle edits sourced from the sync manager.\n\t\t\t\t\t\t\teditRecord: ( edits ) => {\n\t\t\t\t\t\t\t\tif ( ! Object.keys( edits ).length ) {\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tdispatch( {\n\t\t\t\t\t\t\t\t\ttype: 'EDIT_ENTITY_RECORD',\n\t\t\t\t\t\t\t\t\tkind,\n\t\t\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\t\t\trecordId: key,\n\t\t\t\t\t\t\t\t\tedits,\n\t\t\t\t\t\t\t\t\tmeta: {\n\t\t\t\t\t\t\t\t\t\tundo: undefined,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t// Get the current entity record (with edits)\n\t\t\t\t\t\t\tgetEditedRecord: async () =>\n\t\t\t\t\t\t\t\tawait resolveSelect.getEditedEntityRecord(\n\t\t\t\t\t\t\t\t\tkind,\n\t\t\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\t\t\tkey\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t// Save the current entity record's unsaved edits.\n\t\t\t\t\t\t\tsaveRecord: () => {\n\t\t\t\t\t\t\t\tdispatch.saveEditedEntityRecord(\n\t\t\t\t\t\t\t\t\tkind,\n\t\t\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\t\t\tkey\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tregistry.batch( () => {\n\t\t\t\tdispatch.receiveEntityRecords( kind, name, record, query );\n\t\t\t\tdispatch.receiveUserPermissions( receiveUserPermissionArgs );\n\t\t\t\tdispatch.finishResolutions( 'canUser', canUserResolutionsArgs );\n\t\t\t} );\n\t\t} finally {\n\t\t\tdispatch.__unstableReleaseStoreLock( lock );\n\t\t}\n\t};\n\n// Whenever a template is saved, the active templates might be updated, so\n// invalidate the site settings when a template is updated or deleted.\ngetEntityRecord.shouldInvalidate = ( action, kind, name ) => {\n\treturn (\n\t\tkind === 'root' &&\n\t\tname === 'site' &&\n\t\t( ( action.type === 'RECEIVE_ITEMS' &&\n\t\t\t// Making sure persistedEdits is set seems to be the only way of\n\t\t\t// knowing whether it's an update or fetch. Only an update would\n\t\t\t// have persistedEdits.\n\t\t\taction.persistedEdits &&\n\t\t\taction.persistedEdits.status !== 'auto-draft' ) ||\n\t\t\taction.type === 'REMOVE_ITEMS' ) &&\n\t\taction.kind === 'postType' &&\n\t\taction.name === 'wp_template'\n\t);\n};\n\n/**\n * Requests an entity's record from the REST API.\n */\nexport const getRawEntityRecord = forwardResolver( 'getEntityRecord' );\n\n/**\n * Requests an entity's record from the REST API.\n */\nexport const getEditedEntityRecord = forwardResolver( 'getEntityRecord' );\n\n/**\n * Requests the entity's records from the REST API.\n *\n * @param {string} kind Entity kind.\n * @param {string} name Entity name.\n * @param {?Object} query Query Object. If requesting specific fields, fields\n * must always include the ID.\n */\nexport const getEntityRecords =\n\t( kind, name, query = {} ) =>\n\tasync ( { dispatch, registry, resolveSelect } ) => {\n\t\tconst configs = await resolveSelect.getEntitiesConfig( kind );\n\t\tconst entityConfig = configs.find(\n\t\t\t( config ) => config.name === name && config.kind === kind\n\t\t);\n\t\tif ( ! entityConfig ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst lock = await dispatch.__unstableAcquireStoreLock(\n\t\t\tSTORE_NAME,\n\t\t\t[ 'entities', 'records', kind, name ],\n\t\t\t{ exclusive: false }\n\t\t);\n\n\t\t// Keep a copy of the original query for later use in getResolutionsArgs.\n\t\t// The query object may be modified below (for example, when _fields is\n\t\t// specified), but we want to use the original query when marking\n\t\t// resolutions as finished.\n\t\tconst rawQuery = { ...query };\n\t\tconst key = entityConfig.key || DEFAULT_ENTITY_KEY;\n\n\t\tfunction getResolutionsArgs( records, recordsQuery ) {\n\t\t\tconst queryArgs = Object.fromEntries(\n\t\t\t\tObject.entries( recordsQuery ).filter( ( [ k, v ] ) => {\n\t\t\t\t\treturn [ 'context', '_fields' ].includes( k ) && !! v;\n\t\t\t\t} )\n\t\t\t);\n\t\t\treturn records\n\t\t\t\t.filter( ( record ) => record?.[ key ] )\n\t\t\t\t.map( ( record ) => [\n\t\t\t\t\tkind,\n\t\t\t\t\tname,\n\t\t\t\t\trecord[ key ],\n\t\t\t\t\tObject.keys( queryArgs ).length > 0 ? queryArgs : undefined,\n\t\t\t\t] );\n\t\t}\n\n\t\ttry {\n\t\t\tif ( query._fields ) {\n\t\t\t\t// If requesting specific fields, items and query association to said\n\t\t\t\t// records are stored by ID reference. Thus, fields must always include\n\t\t\t\t// the ID.\n\t\t\t\tquery = {\n\t\t\t\t\t...query,\n\t\t\t\t\t_fields: [\n\t\t\t\t\t\t...new Set( [\n\t\t\t\t\t\t\t...( getNormalizedCommaSeparable( query._fields ) ||\n\t\t\t\t\t\t\t\t[] ),\n\t\t\t\t\t\t\tkey,\n\t\t\t\t\t\t] ),\n\t\t\t\t\t].join(),\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tlet { baseURL } = entityConfig;\n\t\t\t// `combinedTemplates` means that we fetch templates from the \"old\"\n\t\t\t// /templates endpoint, which combines active user templates with\n\t\t\t// the registered templates and rewrites IDs in the form of\n\t\t\t// `theme-slug/template-slug`. When turned off, we only fetch\n\t\t\t// database templates (posts). To fetch registered templates without\n\t\t\t// edits applied, use the `registeredTemplate` entity.\n\t\t\tconst { combinedTemplates = true } = query;\n\n\t\t\tif (\n\t\t\t\tkind === 'postType' &&\n\t\t\t\tname === 'wp_template' &&\n\t\t\t\tcombinedTemplates\n\t\t\t) {\n\t\t\t\tbaseURL =\n\t\t\t\t\tbaseURL.slice( 0, baseURL.lastIndexOf( '/' ) ) +\n\t\t\t\t\t'/templates';\n\t\t\t}\n\n\t\t\tconst path = addQueryArgs( baseURL, {\n\t\t\t\t...entityConfig.baseURLParams,\n\t\t\t\t...query,\n\t\t\t} );\n\n\t\t\tlet records = [],\n\t\t\t\tmeta;\n\t\t\tif ( entityConfig.supportsPagination && query.per_page !== -1 ) {\n\t\t\t\tconst response = await apiFetch( { path, parse: false } );\n\t\t\t\trecords = Object.values( await response.json() );\n\t\t\t\tmeta = {\n\t\t\t\t\ttotalItems: parseInt(\n\t\t\t\t\t\tresponse.headers.get( 'X-WP-Total' )\n\t\t\t\t\t),\n\t\t\t\t\ttotalPages: parseInt(\n\t\t\t\t\t\tresponse.headers.get( 'X-WP-TotalPages' )\n\t\t\t\t\t),\n\t\t\t\t};\n\t\t\t} else if (\n\t\t\t\tquery.per_page === -1 &&\n\t\t\t\tquery[ RECEIVE_INTERMEDIATE_RESULTS ] === true\n\t\t\t) {\n\t\t\t\tlet page = 1;\n\t\t\t\tlet totalPages;\n\n\t\t\t\tdo {\n\t\t\t\t\tconst response = await apiFetch( {\n\t\t\t\t\t\tpath: addQueryArgs( path, { page, per_page: 100 } ),\n\t\t\t\t\t\tparse: false,\n\t\t\t\t\t} );\n\t\t\t\t\tconst pageRecords = Object.values( await response.json() );\n\n\t\t\t\t\ttotalPages = parseInt(\n\t\t\t\t\t\tresponse.headers.get( 'X-WP-TotalPages' )\n\t\t\t\t\t);\n\n\t\t\t\t\tif ( ! meta ) {\n\t\t\t\t\t\tmeta = {\n\t\t\t\t\t\t\ttotalItems: parseInt(\n\t\t\t\t\t\t\t\tresponse.headers.get( 'X-WP-Total' )\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\ttotalPages: 1,\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\n\t\t\t\t\trecords.push( ...pageRecords );\n\t\t\t\t\tregistry.batch( () => {\n\t\t\t\t\t\tdispatch.receiveEntityRecords(\n\t\t\t\t\t\t\tkind,\n\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\trecords,\n\t\t\t\t\t\t\tquery,\n\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\tmeta\n\t\t\t\t\t\t);\n\t\t\t\t\t\tdispatch.finishResolutions(\n\t\t\t\t\t\t\t'getEntityRecord',\n\t\t\t\t\t\t\tgetResolutionsArgs( pageRecords, rawQuery )\n\t\t\t\t\t\t);\n\t\t\t\t\t} );\n\t\t\t\t\tpage++;\n\t\t\t\t} while ( page <= totalPages );\n\t\t\t} else {\n\t\t\t\trecords = Object.values( await apiFetch( { path } ) );\n\t\t\t\tmeta = {\n\t\t\t\t\ttotalItems: records.length,\n\t\t\t\t\ttotalPages: 1,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// If we request fields but the result doesn't contain the fields,\n\t\t\t// explicitly set these fields as \"undefined\"\n\t\t\t// that way we consider the query \"fulfilled\".\n\t\t\tif ( query._fields ) {\n\t\t\t\trecords = records.map( ( record ) => {\n\t\t\t\t\tquery._fields.split( ',' ).forEach( ( field ) => {\n\t\t\t\t\t\tif ( ! record.hasOwnProperty( field ) ) {\n\t\t\t\t\t\t\trecord[ field ] = undefined;\n\t\t\t\t\t\t}\n\t\t\t\t\t} );\n\n\t\t\t\t\treturn record;\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\tregistry.batch( () => {\n\t\t\t\tdispatch.receiveEntityRecords(\n\t\t\t\t\tkind,\n\t\t\t\t\tname,\n\t\t\t\t\trecords,\n\t\t\t\t\tquery,\n\t\t\t\t\tfalse,\n\t\t\t\t\tundefined,\n\t\t\t\t\tmeta\n\t\t\t\t);\n\n\t\t\t\tconst targetHints = records\n\t\t\t\t\t.filter(\n\t\t\t\t\t\t( record ) =>\n\t\t\t\t\t\t\t!! record?.[ key ] &&\n\t\t\t\t\t\t\t!! record?._links?.self?.[ 0 ]?.targetHints?.allow\n\t\t\t\t\t)\n\t\t\t\t\t.map( ( record ) => ( {\n\t\t\t\t\t\tid: record[ key ],\n\t\t\t\t\t\tpermissions: getUserPermissionsFromAllowHeader(\n\t\t\t\t\t\t\trecord._links.self[ 0 ].targetHints.allow\n\t\t\t\t\t\t),\n\t\t\t\t\t} ) );\n\n\t\t\t\tconst canUserResolutionsArgs = [];\n\t\t\t\tconst receiveUserPermissionArgs = {};\n\t\t\t\tfor ( const targetHint of targetHints ) {\n\t\t\t\t\tfor ( const action of ALLOWED_RESOURCE_ACTIONS ) {\n\t\t\t\t\t\tcanUserResolutionsArgs.push( [\n\t\t\t\t\t\t\taction,\n\t\t\t\t\t\t\t{ kind, name, id: targetHint.id },\n\t\t\t\t\t\t] );\n\n\t\t\t\t\t\treceiveUserPermissionArgs[\n\t\t\t\t\t\t\tgetUserPermissionCacheKey( action, {\n\t\t\t\t\t\t\t\tkind,\n\t\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\t\tid: targetHint.id,\n\t\t\t\t\t\t\t} )\n\t\t\t\t\t\t] = targetHint.permissions[ action ];\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( targetHints.length > 0 ) {\n\t\t\t\t\tdispatch.receiveUserPermissions(\n\t\t\t\t\t\treceiveUserPermissionArgs\n\t\t\t\t\t);\n\t\t\t\t\tdispatch.finishResolutions(\n\t\t\t\t\t\t'canUser',\n\t\t\t\t\t\tcanUserResolutionsArgs\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tdispatch.finishResolutions(\n\t\t\t\t\t'getEntityRecord',\n\t\t\t\t\tgetResolutionsArgs( records, rawQuery )\n\t\t\t\t);\n\n\t\t\t\tdispatch.__unstableReleaseStoreLock( lock );\n\t\t\t} );\n\t\t} catch ( e ) {\n\t\t\tdispatch.__unstableReleaseStoreLock( lock );\n\t\t}\n\t};\n\ngetEntityRecords.shouldInvalidate = ( action, kind, name ) => {\n\treturn (\n\t\t( action.type === 'RECEIVE_ITEMS' || action.type === 'REMOVE_ITEMS' ) &&\n\t\taction.invalidateCache &&\n\t\tkind === action.kind &&\n\t\tname === action.name\n\t);\n};\n\n/**\n * Requests the total number of entity records.\n */\nexport const getEntityRecordsTotalItems = forwardResolver( 'getEntityRecords' );\n\n/**\n * Requests the number of available pages for the given query.\n */\nexport const getEntityRecordsTotalPages = forwardResolver( 'getEntityRecords' );\n\n/**\n * Requests the current theme.\n */\nexport const getCurrentTheme =\n\t() =>\n\tasync ( { dispatch, resolveSelect } ) => {\n\t\tconst activeThemes = await resolveSelect.getEntityRecords(\n\t\t\t'root',\n\t\t\t'theme',\n\t\t\t{ status: 'active' }\n\t\t);\n\n\t\tdispatch.receiveCurrentTheme( activeThemes[ 0 ] );\n\t};\n\n/**\n * Requests theme supports data from the index.\n */\nexport const getThemeSupports = forwardResolver( 'getCurrentTheme' );\n\n/**\n * Requests a preview from the Embed API.\n *\n * @param {string} url URL to get the preview for.\n */\nexport const getEmbedPreview =\n\t( url ) =>\n\tasync ( { dispatch } ) => {\n\t\ttry {\n\t\t\tconst embedProxyResponse = await apiFetch( {\n\t\t\t\tpath: addQueryArgs( '/oembed/1.0/proxy', { url } ),\n\t\t\t} );\n\t\t\tdispatch.receiveEmbedPreview( url, embedProxyResponse );\n\t\t} catch ( error ) {\n\t\t\t// Embed API 404s if the URL cannot be embedded, so we have to catch the error from the apiRequest here.\n\t\t\tdispatch.receiveEmbedPreview( url, false );\n\t\t}\n\t};\n\n/**\n * Checks whether the current user can perform the given action on the given\n * REST resource.\n *\n * @param {string} requestedAction Action to check. One of: 'create', 'read', 'update',\n * 'delete'.\n * @param {string|Object} resource Entity resource to check. Accepts entity object `{ kind: 'postType', name: 'attachment', id: 1 }`\n * or REST base as a string - `media`.\n * @param {?string} id ID of the rest resource to check.\n */\nexport const canUser =\n\t( requestedAction, resource, id ) =>\n\tasync ( { dispatch, registry, resolveSelect } ) => {\n\t\tif ( ! ALLOWED_RESOURCE_ACTIONS.includes( requestedAction ) ) {\n\t\t\tthrow new Error( `'${ requestedAction }' is not a valid action.` );\n\t\t}\n\n\t\tconst { hasStartedResolution } = registry.select( STORE_NAME );\n\n\t\t// Prevent resolving the same resource twice.\n\t\tfor ( const relatedAction of ALLOWED_RESOURCE_ACTIONS ) {\n\t\t\tif ( relatedAction === requestedAction ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst isAlreadyResolving = hasStartedResolution( 'canUser', [\n\t\t\t\trelatedAction,\n\t\t\t\tresource,\n\t\t\t\tid,\n\t\t\t] );\n\t\t\tif ( isAlreadyResolving ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tlet resourcePath = null;\n\t\tif ( typeof resource === 'object' ) {\n\t\t\tif ( ! resource.kind || ! resource.name ) {\n\t\t\t\tthrow new Error( 'The entity resource object is not valid.' );\n\t\t\t}\n\n\t\t\tconst configs = await resolveSelect.getEntitiesConfig(\n\t\t\t\tresource.kind\n\t\t\t);\n\t\t\tconst entityConfig = configs.find(\n\t\t\t\t( config ) =>\n\t\t\t\t\tconfig.name === resource.name &&\n\t\t\t\t\tconfig.kind === resource.kind\n\t\t\t);\n\t\t\tif ( ! entityConfig ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tresourcePath =\n\t\t\t\tentityConfig.baseURL + ( resource.id ? '/' + resource.id : '' );\n\t\t} else {\n\t\t\tresourcePath = `/wp/v2/${ resource }` + ( id ? '/' + id : '' );\n\t\t}\n\n\t\tlet response;\n\t\ttry {\n\t\t\tresponse = await apiFetch( {\n\t\t\t\tpath: resourcePath,\n\t\t\t\tmethod: 'OPTIONS',\n\t\t\t\tparse: false,\n\t\t\t} );\n\t\t} catch ( error ) {\n\t\t\t// Do nothing if our OPTIONS request comes back with an API error (4xx or\n\t\t\t// 5xx). The previously determined isAllowed value will remain in the store.\n\t\t\treturn;\n\t\t}\n\n\t\t// Optional chaining operator is used here because the API requests don't\n\t\t// return the expected result in the React native version. Instead, API requests\n\t\t// only return the result, without including response properties like the headers.\n\t\tconst permissions = getUserPermissionsFromAllowHeader(\n\t\t\tresponse.headers?.get( 'allow' )\n\t\t);\n\t\tregistry.batch( () => {\n\t\t\tfor ( const action of ALLOWED_RESOURCE_ACTIONS ) {\n\t\t\t\tconst key = getUserPermissionCacheKey( action, resource, id );\n\n\t\t\t\tdispatch.receiveUserPermission( key, permissions[ action ] );\n\n\t\t\t\t// Mark related action resolutions as finished.\n\t\t\t\tif ( action !== requestedAction ) {\n\t\t\t\t\tdispatch.finishResolution( 'canUser', [\n\t\t\t\t\t\taction,\n\t\t\t\t\t\tresource,\n\t\t\t\t\t\tid,\n\t\t\t\t\t] );\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t};\n\n/**\n * Checks whether the current user can perform the given action on the given\n * REST resource.\n *\n * @param {string} kind Entity kind.\n * @param {string} name Entity name.\n * @param {number|string} recordId Record's id.\n */\nexport const canUserEditEntityRecord =\n\t( kind, name, recordId ) =>\n\tasync ( { dispatch } ) => {\n\t\tawait dispatch( canUser( 'update', { kind, name, id: recordId } ) );\n\t};\n\n/**\n * Request autosave data from the REST API.\n *\n * @param {string} postType The type of the parent post.\n * @param {number} postId The id of the parent post.\n */\nexport const getAutosaves =\n\t( postType, postId ) =>\n\tasync ( { dispatch, resolveSelect } ) => {\n\t\tconst {\n\t\t\trest_base: restBase,\n\t\t\trest_namespace: restNamespace = 'wp/v2',\n\t\t\tsupports,\n\t\t} = await resolveSelect.getPostType( postType );\n\t\tif ( ! supports?.autosave ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst autosaves = await apiFetch( {\n\t\t\tpath: `/${ restNamespace }/${ restBase }/${ postId }/autosaves?context=edit`,\n\t\t} );\n\n\t\tif ( autosaves && autosaves.length ) {\n\t\t\tdispatch.receiveAutosaves( postId, autosaves );\n\t\t}\n\t};\n\n/**\n * Request autosave data from the REST API.\n *\n * This resolver exists to ensure the underlying autosaves are fetched via\n * `getAutosaves` when a call to the `getAutosave` selector is made.\n *\n * @param {string} postType The type of the parent post.\n * @param {number} postId The id of the parent post.\n */\nexport const getAutosave =\n\t( postType, postId ) =>\n\tasync ( { resolveSelect } ) => {\n\t\tawait resolveSelect.getAutosaves( postType, postId );\n\t};\n\nexport const __experimentalGetCurrentGlobalStylesId =\n\t() =>\n\tasync ( { dispatch, resolveSelect } ) => {\n\t\tconst activeThemes = await resolveSelect.getEntityRecords(\n\t\t\t'root',\n\t\t\t'theme',\n\t\t\t{ status: 'active' }\n\t\t);\n\t\tconst globalStylesURL =\n\t\t\tactiveThemes?.[ 0 ]?._links?.[ 'wp:user-global-styles' ]?.[ 0 ]\n\t\t\t\t?.href;\n\t\tif ( ! globalStylesURL ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Regex matches the ID at the end of a URL or immediately before\n\t\t// the query string.\n\t\tconst matches = globalStylesURL.match( /\\/(\\d+)(?:\\?|$)/ );\n\t\tconst id = matches ? Number( matches[ 1 ] ) : null;\n\n\t\tif ( id ) {\n\t\t\tdispatch.__experimentalReceiveCurrentGlobalStylesId( id );\n\t\t}\n\t};\n\nexport const __experimentalGetCurrentThemeBaseGlobalStyles =\n\t() =>\n\tasync ( { resolveSelect, dispatch } ) => {\n\t\tconst currentTheme = await resolveSelect.getCurrentTheme();\n\t\t// Please adjust the preloaded requests if this changes!\n\t\tconst themeGlobalStyles = await apiFetch( {\n\t\t\tpath: `/wp/v2/global-styles/themes/${ currentTheme.stylesheet }?context=view`,\n\t\t} );\n\t\tdispatch.__experimentalReceiveThemeBaseGlobalStyles(\n\t\t\tcurrentTheme.stylesheet,\n\t\t\tthemeGlobalStyles\n\t\t);\n\t};\n\nexport const __experimentalGetCurrentThemeGlobalStylesVariations =\n\t() =>\n\tasync ( { resolveSelect, dispatch } ) => {\n\t\tconst currentTheme = await resolveSelect.getCurrentTheme();\n\t\t// Please adjust the preloaded requests if this changes!\n\t\tconst variations = await apiFetch( {\n\t\t\tpath: `/wp/v2/global-styles/themes/${ currentTheme.stylesheet }/variations?context=view`,\n\t\t} );\n\t\tdispatch.__experimentalReceiveThemeGlobalStyleVariations(\n\t\t\tcurrentTheme.stylesheet,\n\t\t\tvariations\n\t\t);\n\t};\n\n/**\n * Fetches and returns the revisions of the current global styles theme.\n */\nexport const getCurrentThemeGlobalStylesRevisions =\n\t() =>\n\tasync ( { resolveSelect, dispatch } ) => {\n\t\tconst globalStylesId =\n\t\t\tawait resolveSelect.__experimentalGetCurrentGlobalStylesId();\n\t\tconst record = globalStylesId\n\t\t\t? await resolveSelect.getEntityRecord(\n\t\t\t\t\t'root',\n\t\t\t\t\t'globalStyles',\n\t\t\t\t\tglobalStylesId\n\t\t\t )\n\t\t\t: undefined;\n\t\tconst revisionsURL = record?._links?.[ 'version-history' ]?.[ 0 ]?.href;\n\n\t\tif ( revisionsURL ) {\n\t\t\tconst resetRevisions = await apiFetch( {\n\t\t\t\turl: revisionsURL,\n\t\t\t} );\n\t\t\tconst revisions = resetRevisions?.map( ( revision ) =>\n\t\t\t\tObject.fromEntries(\n\t\t\t\t\tObject.entries( revision ).map( ( [ key, value ] ) => [\n\t\t\t\t\t\tcamelCase( key ),\n\t\t\t\t\t\tvalue,\n\t\t\t\t\t] )\n\t\t\t\t)\n\t\t\t);\n\t\t\tdispatch.receiveThemeGlobalStyleRevisions(\n\t\t\t\tglobalStylesId,\n\t\t\t\trevisions\n\t\t\t);\n\t\t}\n\t};\n\ngetCurrentThemeGlobalStylesRevisions.shouldInvalidate = ( action ) => {\n\treturn (\n\t\taction.type === 'SAVE_ENTITY_RECORD_FINISH' &&\n\t\taction.kind === 'root' &&\n\t\t! action.error &&\n\t\taction.name === 'globalStyles'\n\t);\n};\n\nexport const getBlockPatterns =\n\t() =>\n\tasync ( { dispatch } ) => {\n\t\tconst patterns = await fetchBlockPatterns();\n\t\tdispatch( { type: 'RECEIVE_BLOCK_PATTERNS', patterns } );\n\t};\n\nexport const getBlockPatternCategories =\n\t() =>\n\tasync ( { dispatch } ) => {\n\t\tconst categories = await apiFetch( {\n\t\t\tpath: '/wp/v2/block-patterns/categories',\n\t\t} );\n\t\tdispatch( { type: 'RECEIVE_BLOCK_PATTERN_CATEGORIES', categories } );\n\t};\n\nexport const getUserPatternCategories =\n\t() =>\n\tasync ( { dispatch, resolveSelect } ) => {\n\t\tconst patternCategories = await resolveSelect.getEntityRecords(\n\t\t\t'taxonomy',\n\t\t\t'wp_pattern_category',\n\t\t\t{\n\t\t\t\tper_page: -1,\n\t\t\t\t_fields: 'id,name,description,slug',\n\t\t\t\tcontext: 'view',\n\t\t\t}\n\t\t);\n\n\t\tconst mappedPatternCategories =\n\t\t\tpatternCategories?.map( ( userCategory ) => ( {\n\t\t\t\t...userCategory,\n\t\t\t\tlabel: decodeEntities( userCategory.name ),\n\t\t\t\tname: userCategory.slug,\n\t\t\t} ) ) || [];\n\n\t\tdispatch( {\n\t\t\ttype: 'RECEIVE_USER_PATTERN_CATEGORIES',\n\t\t\tpatternCategories: mappedPatternCategories,\n\t\t} );\n\t};\n\nexport const getNavigationFallbackId =\n\t() =>\n\tasync ( { dispatch, select, registry } ) => {\n\t\tconst fallback = await apiFetch( {\n\t\t\tpath: addQueryArgs( '/wp-block-editor/v1/navigation-fallback', {\n\t\t\t\t_embed: true,\n\t\t\t} ),\n\t\t} );\n\n\t\tconst record = fallback?._embedded?.self;\n\n\t\tregistry.batch( () => {\n\t\t\tdispatch.receiveNavigationFallbackId( fallback?.id );\n\n\t\t\tif ( ! record ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If the fallback is already in the store, don't invalidate navigation queries.\n\t\t\t// Otherwise, invalidate the cache for the scenario where there were no Navigation\n\t\t\t// posts in the state and the fallback created one.\n\t\t\tconst existingFallbackEntityRecord = select.getEntityRecord(\n\t\t\t\t'postType',\n\t\t\t\t'wp_navigation',\n\t\t\t\tfallback.id\n\t\t\t);\n\t\t\tconst invalidateNavigationQueries = ! existingFallbackEntityRecord;\n\t\t\tdispatch.receiveEntityRecords(\n\t\t\t\t'postType',\n\t\t\t\t'wp_navigation',\n\t\t\t\trecord,\n\t\t\t\tundefined,\n\t\t\t\tinvalidateNavigationQueries\n\t\t\t);\n\n\t\t\t// Resolve to avoid further network requests.\n\t\t\tdispatch.finishResolution( 'getEntityRecord', [\n\t\t\t\t'postType',\n\t\t\t\t'wp_navigation',\n\t\t\t\tfallback.id,\n\t\t\t] );\n\t\t} );\n\t};\n\nexport const getDefaultTemplateId =\n\t( query ) =>\n\tasync ( { dispatch, registry, resolveSelect } ) => {\n\t\tconst template = await apiFetch( {\n\t\t\tpath: addQueryArgs( '/wp/v2/templates/lookup', query ),\n\t\t} );\n\t\t// Wait for the the entities config to be loaded, otherwise receiving\n\t\t// the template as an entity will not work.\n\t\tawait resolveSelect.getEntitiesConfig( 'postType' );\n\t\t// When active_templates experiment is enabled, use numeric wp_id if it\n\t\t// exists, otherwise fall back to string ID format (theme//slug) as the\n\t\t// frontend expects string IDs for templates.\n\t\tconst id = window?.__experimentalTemplateActivate\n\t\t\t? template?.wp_id || template?.id\n\t\t\t: template?.id;\n\t\t// Endpoint may return an empty object if no template is found.\n\t\tif ( id ) {\n\t\t\ttemplate.id = id;\n\t\t\tregistry.batch( () => {\n\t\t\t\tdispatch.receiveDefaultTemplateId( query, id );\n\t\t\t\tdispatch.receiveEntityRecords( 'postType', template.type, [\n\t\t\t\t\ttemplate,\n\t\t\t\t] );\n\t\t\t\t// Avoid further network requests.\n\t\t\t\tdispatch.finishResolution( 'getEntityRecord', [\n\t\t\t\t\t'postType',\n\t\t\t\t\ttemplate.type,\n\t\t\t\t\tid,\n\t\t\t\t] );\n\t\t\t} );\n\t\t}\n\t};\n\ngetDefaultTemplateId.shouldInvalidate = ( action ) => {\n\treturn (\n\t\taction.type === 'RECEIVE_ITEMS' &&\n\t\taction.kind === 'root' &&\n\t\taction.name === 'site'\n\t);\n};\n\n/**\n * Requests an entity's revisions from the REST API.\n *\n * @param {string} kind Entity kind.\n * @param {string} name Entity name.\n * @param {number|string} recordKey The key of the entity record whose revisions you want to fetch.\n * @param {Object|undefined} query Optional object of query parameters to\n * include with request. If requesting specific\n * fields, fields must always include the ID.\n */\nexport const getRevisions =\n\t( kind, name, recordKey, query = {} ) =>\n\tasync ( { dispatch, registry, resolveSelect } ) => {\n\t\tconst configs = await resolveSelect.getEntitiesConfig( kind );\n\t\tconst entityConfig = configs.find(\n\t\t\t( config ) => config.name === name && config.kind === kind\n\t\t);\n\n\t\tif ( ! entityConfig ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( query._fields ) {\n\t\t\t// If requesting specific fields, items and query association to said\n\t\t\t// records are stored by ID reference. Thus, fields must always include\n\t\t\t// the ID.\n\t\t\tquery = {\n\t\t\t\t...query,\n\t\t\t\t_fields: [\n\t\t\t\t\t...new Set( [\n\t\t\t\t\t\t...( getNormalizedCommaSeparable( query._fields ) ||\n\t\t\t\t\t\t\t[] ),\n\t\t\t\t\t\tentityConfig.revisionKey || DEFAULT_ENTITY_KEY,\n\t\t\t\t\t] ),\n\t\t\t\t].join(),\n\t\t\t};\n\t\t}\n\n\t\tconst path = addQueryArgs(\n\t\t\tentityConfig.getRevisionsUrl( recordKey ),\n\t\t\tquery\n\t\t);\n\n\t\tlet records, response;\n\t\tconst meta = {};\n\t\tconst isPaginated =\n\t\t\tentityConfig.supportsPagination && query.per_page !== -1;\n\t\ttry {\n\t\t\tresponse = await apiFetch( { path, parse: ! isPaginated } );\n\t\t} catch ( error ) {\n\t\t\t// Do nothing if our request comes back with an API error.\n\t\t\treturn;\n\t\t}\n\n\t\tif ( response ) {\n\t\t\tif ( isPaginated ) {\n\t\t\t\trecords = Object.values( await response.json() );\n\t\t\t\tmeta.totalItems = parseInt(\n\t\t\t\t\tresponse.headers.get( 'X-WP-Total' )\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\trecords = Object.values( response );\n\t\t\t}\n\n\t\t\t// If we request fields but the result doesn't contain the fields,\n\t\t\t// explicitly set these fields as \"undefined\"\n\t\t\t// that way we consider the query \"fulfilled\".\n\t\t\tif ( query._fields ) {\n\t\t\t\trecords = records.map( ( record ) => {\n\t\t\t\t\tquery._fields.split( ',' ).forEach( ( field ) => {\n\t\t\t\t\t\tif ( ! record.hasOwnProperty( field ) ) {\n\t\t\t\t\t\t\trecord[ field ] = undefined;\n\t\t\t\t\t\t}\n\t\t\t\t\t} );\n\n\t\t\t\t\treturn record;\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\tregistry.batch( () => {\n\t\t\t\tdispatch.receiveRevisions(\n\t\t\t\t\tkind,\n\t\t\t\t\tname,\n\t\t\t\t\trecordKey,\n\t\t\t\t\trecords,\n\t\t\t\t\tquery,\n\t\t\t\t\tfalse,\n\t\t\t\t\tmeta\n\t\t\t\t);\n\n\t\t\t\t// When requesting all fields, the list of results can be used to\n\t\t\t\t// resolve the `getRevision` selector in addition to `getRevisions`.\n\t\t\t\tif ( ! query?._fields && ! query.context ) {\n\t\t\t\t\tconst key = entityConfig.key || DEFAULT_ENTITY_KEY;\n\t\t\t\t\tconst resolutionsArgs = records\n\t\t\t\t\t\t.filter( ( record ) => record[ key ] )\n\t\t\t\t\t\t.map( ( record ) => [\n\t\t\t\t\t\t\tkind,\n\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\trecordKey,\n\t\t\t\t\t\t\trecord[ key ],\n\t\t\t\t\t\t] );\n\n\t\t\t\t\tdispatch.finishResolutions(\n\t\t\t\t\t\t'getRevision',\n\t\t\t\t\t\tresolutionsArgs\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\t};\n\n// Invalidate cache when a new revision is created.\ngetRevisions.shouldInvalidate = ( action, kind, name, recordKey ) =>\n\taction.type === 'SAVE_ENTITY_RECORD_FINISH' &&\n\tname === action.name &&\n\tkind === action.kind &&\n\t! action.error &&\n\trecordKey === action.recordId;\n\n/**\n * Requests a specific Entity revision from the REST API.\n *\n * @param {string} kind Entity kind.\n * @param {string} name Entity name.\n * @param {number|string} recordKey The key of the entity record whose revisions you want to fetch.\n * @param {number|string} revisionKey The revision's key.\n * @param {Object|undefined} query Optional object of query parameters to\n * include with request. If requesting specific\n * fields, fields must always include the ID.\n */\nexport const getRevision =\n\t( kind, name, recordKey, revisionKey, query ) =>\n\tasync ( { dispatch, resolveSelect } ) => {\n\t\tconst configs = await resolveSelect.getEntitiesConfig( kind );\n\t\tconst entityConfig = configs.find(\n\t\t\t( config ) => config.name === name && config.kind === kind\n\t\t);\n\n\t\tif ( ! entityConfig ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( query !== undefined && query._fields ) {\n\t\t\t// If requesting specific fields, items and query association to said\n\t\t\t// records are stored by ID reference. Thus, fields must always include\n\t\t\t// the ID.\n\t\t\tquery = {\n\t\t\t\t...query,\n\t\t\t\t_fields: [\n\t\t\t\t\t...new Set( [\n\t\t\t\t\t\t...( getNormalizedCommaSeparable( query._fields ) ||\n\t\t\t\t\t\t\t[] ),\n\t\t\t\t\t\tentityConfig.revisionKey || DEFAULT_ENTITY_KEY,\n\t\t\t\t\t] ),\n\t\t\t\t].join(),\n\t\t\t};\n\t\t}\n\t\tconst path = addQueryArgs(\n\t\t\tentityConfig.getRevisionsUrl( recordKey, revisionKey ),\n\t\t\tquery\n\t\t);\n\n\t\tlet record;\n\t\ttry {\n\t\t\trecord = await apiFetch( { path } );\n\t\t} catch ( error ) {\n\t\t\t// Do nothing if our request comes back with an API error.\n\t\t\treturn;\n\t\t}\n\n\t\tif ( record ) {\n\t\t\tdispatch.receiveRevisions( kind, name, recordKey, record, query );\n\t\t}\n\t};\n\n/**\n * Requests a specific post type options from the REST API.\n *\n * @param {string} postType Post type slug.\n */\nexport const getRegisteredPostMeta =\n\t( postType ) =>\n\tasync ( { dispatch, resolveSelect } ) => {\n\t\tlet options;\n\t\ttry {\n\t\t\tconst {\n\t\t\t\trest_namespace: restNamespace = 'wp/v2',\n\t\t\t\trest_base: restBase,\n\t\t\t} = ( await resolveSelect.getPostType( postType ) ) || {};\n\t\t\toptions = await apiFetch( {\n\t\t\t\tpath: `${ restNamespace }/${ restBase }/?context=edit`,\n\t\t\t\tmethod: 'OPTIONS',\n\t\t\t} );\n\t\t} catch ( error ) {\n\t\t\t// Do nothing if the request comes back with an API error.\n\t\t\treturn;\n\t\t}\n\n\t\tif ( options ) {\n\t\t\tdispatch.receiveRegisteredPostMeta(\n\t\t\t\tpostType,\n\t\t\t\toptions?.schema?.properties?.meta?.properties\n\t\t\t);\n\t\t}\n\t};\n\n/**\n * Requests entity configs for the given kind from the REST API.\n *\n * @param {string} kind Entity kind.\n */\nexport const getEntitiesConfig =\n\t( kind ) =>\n\tasync ( { dispatch } ) => {\n\t\tconst loader = additionalEntityConfigLoaders.find(\n\t\t\t( l ) => l.kind === kind\n\t\t);\n\n\t\tif ( ! loader ) {\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tconst configs = await loader.loadEntities();\n\t\t\tif ( ! configs.length ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tdispatch.addEntities( configs );\n\t\t} catch {\n\t\t\t// Do nothing if the request comes back with an API error.\n\t\t}\n\t};\n\n/**\n * Requests editor settings from the REST API.\n */\nexport const getEditorSettings =\n\t() =>\n\tasync ( { dispatch } ) => {\n\t\tconst settings = await apiFetch( {\n\t\t\tpath: '/wp-block-editor/v1/settings',\n\t\t} );\n\t\tdispatch.receiveEditorSettings( settings );\n\t};\n\n/**\n * Requests editor assets from the REST API.\n */\nexport const getEditorAssets =\n\t() =>\n\tasync ( { dispatch } ) => {\n\t\tconst assets = await apiFetch( {\n\t\t\tpath: '/wp-block-editor/v1/assets',\n\t\t} );\n\t\tdispatch.receiveEditorAssets( assets );\n\t};\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["/**\n * External dependencies\n */\nimport { camelCase } from 'change-case';\n\n/**\n * WordPress dependencies\n */\nimport { addQueryArgs } from '@wordpress/url';\nimport { decodeEntities } from '@wordpress/html-entities';\nimport apiFetch from '@wordpress/api-fetch';\n\n/**\n * Internal dependencies\n */\nimport { STORE_NAME } from './name';\nimport { additionalEntityConfigLoaders, DEFAULT_ENTITY_KEY } from './entities';\nimport { getSyncManager } from './sync';\nimport {\n\tforwardResolver,\n\tgetNormalizedCommaSeparable,\n\tgetUserPermissionCacheKey,\n\tgetUserPermissionsFromAllowHeader,\n\tALLOWED_RESOURCE_ACTIONS,\n\tRECEIVE_INTERMEDIATE_RESULTS,\n\tisNumericID,\n} from './utils';\nimport { fetchBlockPatterns } from './fetch';\n\n/**\n * Requests authors from the REST API.\n *\n * @param {Object|undefined} query Optional object of query parameters to\n * include with request.\n */\nexport const getAuthors =\n\t( query ) =>\n\tasync ( { dispatch } ) => {\n\t\tconst path = addQueryArgs(\n\t\t\t'/wp/v2/users/?who=authors&per_page=100',\n\t\t\tquery\n\t\t);\n\t\tconst users = await apiFetch( { path } );\n\t\tdispatch.receiveUserQuery( path, users );\n\t};\n\n/**\n * Requests the current user from the REST API.\n */\nexport const getCurrentUser =\n\t() =>\n\tasync ( { dispatch } ) => {\n\t\tconst currentUser = await apiFetch( { path: '/wp/v2/users/me' } );\n\t\tdispatch.receiveCurrentUser( currentUser );\n\t};\n\n/**\n * Requests an entity's record from the REST API.\n *\n * @param {string} kind Entity kind.\n * @param {string} name Entity name.\n * @param {number|string} key Record's key\n * @param {Object|undefined} query Optional object of query parameters to\n * include with request. If requesting specific\n * fields, fields must always include the ID.\n */\nexport const getEntityRecord =\n\t( kind, name, key = '', query ) =>\n\tasync ( { select, dispatch, registry, resolveSelect } ) => {\n\t\tconst configs = await resolveSelect.getEntitiesConfig( kind );\n\t\tconst entityConfig = configs.find(\n\t\t\t( config ) => config.name === name && config.kind === kind\n\t\t);\n\t\tif ( ! entityConfig ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst lock = await dispatch.__unstableAcquireStoreLock(\n\t\t\tSTORE_NAME,\n\t\t\t[ 'entities', 'records', kind, name, key ],\n\t\t\t{ exclusive: false }\n\t\t);\n\n\t\ttry {\n\t\t\tif ( query !== undefined && query._fields ) {\n\t\t\t\t// If requesting specific fields, items and query association to said\n\t\t\t\t// records are stored by ID reference. Thus, fields must always include\n\t\t\t\t// the ID.\n\t\t\t\tquery = {\n\t\t\t\t\t...query,\n\t\t\t\t\t_fields: [\n\t\t\t\t\t\t...new Set( [\n\t\t\t\t\t\t\t...( getNormalizedCommaSeparable( query._fields ) ||\n\t\t\t\t\t\t\t\t[] ),\n\t\t\t\t\t\t\tentityConfig.key || DEFAULT_ENTITY_KEY,\n\t\t\t\t\t\t] ),\n\t\t\t\t\t].join(),\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tif ( query !== undefined && query._fields ) {\n\t\t\t\t// The resolution cache won't consider query as reusable based on the\n\t\t\t\t// fields, so it's tested here, prior to initiating the REST request,\n\t\t\t\t// and without causing `getEntityRecord` resolution to occur.\n\t\t\t\tconst hasRecord = select.hasEntityRecord(\n\t\t\t\t\tkind,\n\t\t\t\t\tname,\n\t\t\t\t\tkey,\n\t\t\t\t\tquery\n\t\t\t\t);\n\t\t\t\tif ( hasRecord ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlet { baseURL } = entityConfig;\n\n\t\t\t// For \"string\" IDs, use the old templates endpoint.\n\t\t\tif (\n\t\t\t\tkind === 'postType' &&\n\t\t\t\tname === 'wp_template' &&\n\t\t\t\t( ( key && typeof key === 'string' && ! /^\\d+$/.test( key ) ) ||\n\t\t\t\t\t! window?.__experimentalTemplateActivate )\n\t\t\t) {\n\t\t\t\tbaseURL =\n\t\t\t\t\tbaseURL.slice( 0, baseURL.lastIndexOf( '/' ) ) +\n\t\t\t\t\t'/templates';\n\t\t\t}\n\n\t\t\tconst path = addQueryArgs( baseURL + ( key ? '/' + key : '' ), {\n\t\t\t\t...entityConfig.baseURLParams,\n\t\t\t\t...query,\n\t\t\t} );\n\t\t\tconst response = await apiFetch( { path, parse: false } );\n\t\t\tconst record = await response.json();\n\t\t\tconst permissions = getUserPermissionsFromAllowHeader(\n\t\t\t\tresponse.headers?.get( 'allow' )\n\t\t\t);\n\n\t\t\tconst canUserResolutionsArgs = [];\n\t\t\tconst receiveUserPermissionArgs = {};\n\t\t\tfor ( const action of ALLOWED_RESOURCE_ACTIONS ) {\n\t\t\t\treceiveUserPermissionArgs[\n\t\t\t\t\tgetUserPermissionCacheKey( action, {\n\t\t\t\t\t\tkind,\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tid: key,\n\t\t\t\t\t} )\n\t\t\t\t] = permissions[ action ];\n\n\t\t\t\tcanUserResolutionsArgs.push( [\n\t\t\t\t\taction,\n\t\t\t\t\t{ kind, name, id: key },\n\t\t\t\t] );\n\t\t\t}\n\n\t\t\t// Entity supports syncing.\n\t\t\tif ( globalThis.IS_GUTENBERG_PLUGIN ) {\n\t\t\t\tif (\n\t\t\t\t\tentityConfig.syncConfig &&\n\t\t\t\t\tisNumericID( key ) &&\n\t\t\t\t\t! query\n\t\t\t\t) {\n\t\t\t\t\tconst objectType = `${ kind }/${ name }`;\n\t\t\t\t\tconst objectId = key;\n\n\t\t\t\t\t// Use the new transient \"read/write\" config to compute transients for\n\t\t\t\t\t// the sync manager. Otherwise these transients are not available\n\t\t\t\t\t// if / until the record is edited. Use a copy of the record so that\n\t\t\t\t\t// it does not change the behavior outside this experimental flag.\n\t\t\t\t\tconst recordWithTransients = { ...record };\n\t\t\t\t\tObject.entries( entityConfig.transientEdits ?? {} )\n\t\t\t\t\t\t.filter(\n\t\t\t\t\t\t\t( [ propName, transientConfig ] ) =>\n\t\t\t\t\t\t\t\tundefined ===\n\t\t\t\t\t\t\t\t\trecordWithTransients[ propName ] &&\n\t\t\t\t\t\t\t\ttransientConfig &&\n\t\t\t\t\t\t\t\t'object' === typeof transientConfig &&\n\t\t\t\t\t\t\t\t'read' in transientConfig &&\n\t\t\t\t\t\t\t\t'function' === typeof transientConfig.read\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.forEach( ( [ propName, transientConfig ] ) => {\n\t\t\t\t\t\t\trecordWithTransients[ propName ] =\n\t\t\t\t\t\t\t\ttransientConfig.read( recordWithTransients );\n\t\t\t\t\t\t} );\n\n\t\t\t\t\t// Load the entity record for syncing.\n\t\t\t\t\tawait getSyncManager()?.load(\n\t\t\t\t\t\tentityConfig.syncConfig,\n\t\t\t\t\t\tobjectType,\n\t\t\t\t\t\tobjectId,\n\t\t\t\t\t\trecordWithTransients,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// Handle edits sourced from the sync manager.\n\t\t\t\t\t\t\teditRecord: ( edits ) => {\n\t\t\t\t\t\t\t\tif ( ! Object.keys( edits ).length ) {\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tdispatch( {\n\t\t\t\t\t\t\t\t\ttype: 'EDIT_ENTITY_RECORD',\n\t\t\t\t\t\t\t\t\tkind,\n\t\t\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\t\t\trecordId: key,\n\t\t\t\t\t\t\t\t\tedits,\n\t\t\t\t\t\t\t\t\tmeta: {\n\t\t\t\t\t\t\t\t\t\tundo: undefined,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t// Get the current entity record (with edits)\n\t\t\t\t\t\t\tgetEditedRecord: async () =>\n\t\t\t\t\t\t\t\tawait resolveSelect.getEditedEntityRecord(\n\t\t\t\t\t\t\t\t\tkind,\n\t\t\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\t\t\tkey\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t// Refetch the current entity record from the database.\n\t\t\t\t\t\t\trefetchRecord: async () => {\n\t\t\t\t\t\t\t\tdispatch.receiveEntityRecords(\n\t\t\t\t\t\t\t\t\tkind,\n\t\t\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\t\t\tawait apiFetch( { path, parse: true } ),\n\t\t\t\t\t\t\t\t\tquery\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t// Save the current entity record's unsaved edits.\n\t\t\t\t\t\t\tsaveRecord: () => {\n\t\t\t\t\t\t\t\tdispatch.saveEditedEntityRecord(\n\t\t\t\t\t\t\t\t\tkind,\n\t\t\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\t\t\tkey\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tregistry.batch( () => {\n\t\t\t\tdispatch.receiveEntityRecords( kind, name, record, query );\n\t\t\t\tdispatch.receiveUserPermissions( receiveUserPermissionArgs );\n\t\t\t\tdispatch.finishResolutions( 'canUser', canUserResolutionsArgs );\n\t\t\t} );\n\t\t} finally {\n\t\t\tdispatch.__unstableReleaseStoreLock( lock );\n\t\t}\n\t};\n\n// Whenever a template is saved, the active templates might be updated, so\n// invalidate the site settings when a template is updated or deleted.\ngetEntityRecord.shouldInvalidate = ( action, kind, name ) => {\n\treturn (\n\t\tkind === 'root' &&\n\t\tname === 'site' &&\n\t\t( ( action.type === 'RECEIVE_ITEMS' &&\n\t\t\t// Making sure persistedEdits is set seems to be the only way of\n\t\t\t// knowing whether it's an update or fetch. Only an update would\n\t\t\t// have persistedEdits.\n\t\t\taction.persistedEdits &&\n\t\t\taction.persistedEdits.status !== 'auto-draft' ) ||\n\t\t\taction.type === 'REMOVE_ITEMS' ) &&\n\t\taction.kind === 'postType' &&\n\t\taction.name === 'wp_template'\n\t);\n};\n\n/**\n * Requests an entity's record from the REST API.\n */\nexport const getRawEntityRecord = forwardResolver( 'getEntityRecord' );\n\n/**\n * Requests an entity's record from the REST API.\n */\nexport const getEditedEntityRecord = forwardResolver( 'getEntityRecord' );\n\n/**\n * Requests the entity's records from the REST API.\n *\n * @param {string} kind Entity kind.\n * @param {string} name Entity name.\n * @param {?Object} query Query Object. If requesting specific fields, fields\n * must always include the ID.\n */\nexport const getEntityRecords =\n\t( kind, name, query = {} ) =>\n\tasync ( { dispatch, registry, resolveSelect } ) => {\n\t\tconst configs = await resolveSelect.getEntitiesConfig( kind );\n\t\tconst entityConfig = configs.find(\n\t\t\t( config ) => config.name === name && config.kind === kind\n\t\t);\n\t\tif ( ! entityConfig ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst lock = await dispatch.__unstableAcquireStoreLock(\n\t\t\tSTORE_NAME,\n\t\t\t[ 'entities', 'records', kind, name ],\n\t\t\t{ exclusive: false }\n\t\t);\n\n\t\t// Keep a copy of the original query for later use in getResolutionsArgs.\n\t\t// The query object may be modified below (for example, when _fields is\n\t\t// specified), but we want to use the original query when marking\n\t\t// resolutions as finished.\n\t\tconst rawQuery = { ...query };\n\t\tconst key = entityConfig.key || DEFAULT_ENTITY_KEY;\n\n\t\tfunction getResolutionsArgs( records, recordsQuery ) {\n\t\t\tconst queryArgs = Object.fromEntries(\n\t\t\t\tObject.entries( recordsQuery ).filter( ( [ k, v ] ) => {\n\t\t\t\t\treturn [ 'context', '_fields' ].includes( k ) && !! v;\n\t\t\t\t} )\n\t\t\t);\n\t\t\treturn records\n\t\t\t\t.filter( ( record ) => record?.[ key ] )\n\t\t\t\t.map( ( record ) => [\n\t\t\t\t\tkind,\n\t\t\t\t\tname,\n\t\t\t\t\trecord[ key ],\n\t\t\t\t\tObject.keys( queryArgs ).length > 0 ? queryArgs : undefined,\n\t\t\t\t] );\n\t\t}\n\n\t\ttry {\n\t\t\tif ( query._fields ) {\n\t\t\t\t// If requesting specific fields, items and query association to said\n\t\t\t\t// records are stored by ID reference. Thus, fields must always include\n\t\t\t\t// the ID.\n\t\t\t\tquery = {\n\t\t\t\t\t...query,\n\t\t\t\t\t_fields: [\n\t\t\t\t\t\t...new Set( [\n\t\t\t\t\t\t\t...( getNormalizedCommaSeparable( query._fields ) ||\n\t\t\t\t\t\t\t\t[] ),\n\t\t\t\t\t\t\tkey,\n\t\t\t\t\t\t] ),\n\t\t\t\t\t].join(),\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tlet { baseURL } = entityConfig;\n\t\t\t// `combinedTemplates` means that we fetch templates from the \"old\"\n\t\t\t// /templates endpoint, which combines active user templates with\n\t\t\t// the registered templates and rewrites IDs in the form of\n\t\t\t// `theme-slug/template-slug`. When turned off, we only fetch\n\t\t\t// database templates (posts). To fetch registered templates without\n\t\t\t// edits applied, use the `registeredTemplate` entity.\n\t\t\tconst { combinedTemplates = true } = query;\n\n\t\t\tif (\n\t\t\t\tkind === 'postType' &&\n\t\t\t\tname === 'wp_template' &&\n\t\t\t\tcombinedTemplates\n\t\t\t) {\n\t\t\t\tbaseURL =\n\t\t\t\t\tbaseURL.slice( 0, baseURL.lastIndexOf( '/' ) ) +\n\t\t\t\t\t'/templates';\n\t\t\t}\n\n\t\t\tconst path = addQueryArgs( baseURL, {\n\t\t\t\t...entityConfig.baseURLParams,\n\t\t\t\t...query,\n\t\t\t} );\n\n\t\t\tlet records = [],\n\t\t\t\tmeta;\n\t\t\tif ( entityConfig.supportsPagination && query.per_page !== -1 ) {\n\t\t\t\tconst response = await apiFetch( { path, parse: false } );\n\t\t\t\trecords = Object.values( await response.json() );\n\t\t\t\tmeta = {\n\t\t\t\t\ttotalItems: parseInt(\n\t\t\t\t\t\tresponse.headers.get( 'X-WP-Total' )\n\t\t\t\t\t),\n\t\t\t\t\ttotalPages: parseInt(\n\t\t\t\t\t\tresponse.headers.get( 'X-WP-TotalPages' )\n\t\t\t\t\t),\n\t\t\t\t};\n\t\t\t} else if (\n\t\t\t\tquery.per_page === -1 &&\n\t\t\t\tquery[ RECEIVE_INTERMEDIATE_RESULTS ] === true\n\t\t\t) {\n\t\t\t\tlet page = 1;\n\t\t\t\tlet totalPages;\n\n\t\t\t\tdo {\n\t\t\t\t\tconst response = await apiFetch( {\n\t\t\t\t\t\tpath: addQueryArgs( path, { page, per_page: 100 } ),\n\t\t\t\t\t\tparse: false,\n\t\t\t\t\t} );\n\t\t\t\t\tconst pageRecords = Object.values( await response.json() );\n\n\t\t\t\t\ttotalPages = parseInt(\n\t\t\t\t\t\tresponse.headers.get( 'X-WP-TotalPages' )\n\t\t\t\t\t);\n\n\t\t\t\t\tif ( ! meta ) {\n\t\t\t\t\t\tmeta = {\n\t\t\t\t\t\t\ttotalItems: parseInt(\n\t\t\t\t\t\t\t\tresponse.headers.get( 'X-WP-Total' )\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\ttotalPages: 1,\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\n\t\t\t\t\trecords.push( ...pageRecords );\n\t\t\t\t\tregistry.batch( () => {\n\t\t\t\t\t\tdispatch.receiveEntityRecords(\n\t\t\t\t\t\t\tkind,\n\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\trecords,\n\t\t\t\t\t\t\tquery,\n\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\tmeta\n\t\t\t\t\t\t);\n\t\t\t\t\t\tdispatch.finishResolutions(\n\t\t\t\t\t\t\t'getEntityRecord',\n\t\t\t\t\t\t\tgetResolutionsArgs( pageRecords, rawQuery )\n\t\t\t\t\t\t);\n\t\t\t\t\t} );\n\t\t\t\t\tpage++;\n\t\t\t\t} while ( page <= totalPages );\n\t\t\t} else {\n\t\t\t\trecords = Object.values( await apiFetch( { path } ) );\n\t\t\t\tmeta = {\n\t\t\t\t\ttotalItems: records.length,\n\t\t\t\t\ttotalPages: 1,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// If we request fields but the result doesn't contain the fields,\n\t\t\t// explicitly set these fields as \"undefined\"\n\t\t\t// that way we consider the query \"fulfilled\".\n\t\t\tif ( query._fields ) {\n\t\t\t\trecords = records.map( ( record ) => {\n\t\t\t\t\tquery._fields.split( ',' ).forEach( ( field ) => {\n\t\t\t\t\t\tif ( ! record.hasOwnProperty( field ) ) {\n\t\t\t\t\t\t\trecord[ field ] = undefined;\n\t\t\t\t\t\t}\n\t\t\t\t\t} );\n\n\t\t\t\t\treturn record;\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\tregistry.batch( () => {\n\t\t\t\tdispatch.receiveEntityRecords(\n\t\t\t\t\tkind,\n\t\t\t\t\tname,\n\t\t\t\t\trecords,\n\t\t\t\t\tquery,\n\t\t\t\t\tfalse,\n\t\t\t\t\tundefined,\n\t\t\t\t\tmeta\n\t\t\t\t);\n\n\t\t\t\tconst targetHints = records\n\t\t\t\t\t.filter(\n\t\t\t\t\t\t( record ) =>\n\t\t\t\t\t\t\t!! record?.[ key ] &&\n\t\t\t\t\t\t\t!! record?._links?.self?.[ 0 ]?.targetHints?.allow\n\t\t\t\t\t)\n\t\t\t\t\t.map( ( record ) => ( {\n\t\t\t\t\t\tid: record[ key ],\n\t\t\t\t\t\tpermissions: getUserPermissionsFromAllowHeader(\n\t\t\t\t\t\t\trecord._links.self[ 0 ].targetHints.allow\n\t\t\t\t\t\t),\n\t\t\t\t\t} ) );\n\n\t\t\t\tconst canUserResolutionsArgs = [];\n\t\t\t\tconst receiveUserPermissionArgs = {};\n\t\t\t\tfor ( const targetHint of targetHints ) {\n\t\t\t\t\tfor ( const action of ALLOWED_RESOURCE_ACTIONS ) {\n\t\t\t\t\t\tcanUserResolutionsArgs.push( [\n\t\t\t\t\t\t\taction,\n\t\t\t\t\t\t\t{ kind, name, id: targetHint.id },\n\t\t\t\t\t\t] );\n\n\t\t\t\t\t\treceiveUserPermissionArgs[\n\t\t\t\t\t\t\tgetUserPermissionCacheKey( action, {\n\t\t\t\t\t\t\t\tkind,\n\t\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\t\tid: targetHint.id,\n\t\t\t\t\t\t\t} )\n\t\t\t\t\t\t] = targetHint.permissions[ action ];\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( targetHints.length > 0 ) {\n\t\t\t\t\tdispatch.receiveUserPermissions(\n\t\t\t\t\t\treceiveUserPermissionArgs\n\t\t\t\t\t);\n\t\t\t\t\tdispatch.finishResolutions(\n\t\t\t\t\t\t'canUser',\n\t\t\t\t\t\tcanUserResolutionsArgs\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tdispatch.finishResolutions(\n\t\t\t\t\t'getEntityRecord',\n\t\t\t\t\tgetResolutionsArgs( records, rawQuery )\n\t\t\t\t);\n\n\t\t\t\tdispatch.__unstableReleaseStoreLock( lock );\n\t\t\t} );\n\t\t} catch ( e ) {\n\t\t\tdispatch.__unstableReleaseStoreLock( lock );\n\t\t}\n\t};\n\ngetEntityRecords.shouldInvalidate = ( action, kind, name ) => {\n\treturn (\n\t\t( action.type === 'RECEIVE_ITEMS' || action.type === 'REMOVE_ITEMS' ) &&\n\t\taction.invalidateCache &&\n\t\tkind === action.kind &&\n\t\tname === action.name\n\t);\n};\n\n/**\n * Requests the total number of entity records.\n */\nexport const getEntityRecordsTotalItems = forwardResolver( 'getEntityRecords' );\n\n/**\n * Requests the number of available pages for the given query.\n */\nexport const getEntityRecordsTotalPages = forwardResolver( 'getEntityRecords' );\n\n/**\n * Requests the current theme.\n */\nexport const getCurrentTheme =\n\t() =>\n\tasync ( { dispatch, resolveSelect } ) => {\n\t\tconst activeThemes = await resolveSelect.getEntityRecords(\n\t\t\t'root',\n\t\t\t'theme',\n\t\t\t{ status: 'active' }\n\t\t);\n\n\t\tdispatch.receiveCurrentTheme( activeThemes[ 0 ] );\n\t};\n\n/**\n * Requests theme supports data from the index.\n */\nexport const getThemeSupports = forwardResolver( 'getCurrentTheme' );\n\n/**\n * Requests a preview from the Embed API.\n *\n * @param {string} url URL to get the preview for.\n */\nexport const getEmbedPreview =\n\t( url ) =>\n\tasync ( { dispatch } ) => {\n\t\ttry {\n\t\t\tconst embedProxyResponse = await apiFetch( {\n\t\t\t\tpath: addQueryArgs( '/oembed/1.0/proxy', { url } ),\n\t\t\t} );\n\t\t\tdispatch.receiveEmbedPreview( url, embedProxyResponse );\n\t\t} catch ( error ) {\n\t\t\t// Embed API 404s if the URL cannot be embedded, so we have to catch the error from the apiRequest here.\n\t\t\tdispatch.receiveEmbedPreview( url, false );\n\t\t}\n\t};\n\n/**\n * Checks whether the current user can perform the given action on the given\n * REST resource.\n *\n * @param {string} requestedAction Action to check. One of: 'create', 'read', 'update',\n * 'delete'.\n * @param {string|Object} resource Entity resource to check. Accepts entity object `{ kind: 'postType', name: 'attachment', id: 1 }`\n * or REST base as a string - `media`.\n * @param {?string} id ID of the rest resource to check.\n */\nexport const canUser =\n\t( requestedAction, resource, id ) =>\n\tasync ( { dispatch, registry, resolveSelect } ) => {\n\t\tif ( ! ALLOWED_RESOURCE_ACTIONS.includes( requestedAction ) ) {\n\t\t\tthrow new Error( `'${ requestedAction }' is not a valid action.` );\n\t\t}\n\n\t\tconst { hasStartedResolution } = registry.select( STORE_NAME );\n\n\t\t// Prevent resolving the same resource twice.\n\t\tfor ( const relatedAction of ALLOWED_RESOURCE_ACTIONS ) {\n\t\t\tif ( relatedAction === requestedAction ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst isAlreadyResolving = hasStartedResolution( 'canUser', [\n\t\t\t\trelatedAction,\n\t\t\t\tresource,\n\t\t\t\tid,\n\t\t\t] );\n\t\t\tif ( isAlreadyResolving ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tlet resourcePath = null;\n\t\tif ( typeof resource === 'object' ) {\n\t\t\tif ( ! resource.kind || ! resource.name ) {\n\t\t\t\tthrow new Error( 'The entity resource object is not valid.' );\n\t\t\t}\n\n\t\t\tconst configs = await resolveSelect.getEntitiesConfig(\n\t\t\t\tresource.kind\n\t\t\t);\n\t\t\tconst entityConfig = configs.find(\n\t\t\t\t( config ) =>\n\t\t\t\t\tconfig.name === resource.name &&\n\t\t\t\t\tconfig.kind === resource.kind\n\t\t\t);\n\t\t\tif ( ! entityConfig ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tresourcePath =\n\t\t\t\tentityConfig.baseURL + ( resource.id ? '/' + resource.id : '' );\n\t\t} else {\n\t\t\tresourcePath = `/wp/v2/${ resource }` + ( id ? '/' + id : '' );\n\t\t}\n\n\t\tlet response;\n\t\ttry {\n\t\t\tresponse = await apiFetch( {\n\t\t\t\tpath: resourcePath,\n\t\t\t\tmethod: 'OPTIONS',\n\t\t\t\tparse: false,\n\t\t\t} );\n\t\t} catch ( error ) {\n\t\t\t// Do nothing if our OPTIONS request comes back with an API error (4xx or\n\t\t\t// 5xx). The previously determined isAllowed value will remain in the store.\n\t\t\treturn;\n\t\t}\n\n\t\t// Optional chaining operator is used here because the API requests don't\n\t\t// return the expected result in the React native version. Instead, API requests\n\t\t// only return the result, without including response properties like the headers.\n\t\tconst permissions = getUserPermissionsFromAllowHeader(\n\t\t\tresponse.headers?.get( 'allow' )\n\t\t);\n\t\tregistry.batch( () => {\n\t\t\tfor ( const action of ALLOWED_RESOURCE_ACTIONS ) {\n\t\t\t\tconst key = getUserPermissionCacheKey( action, resource, id );\n\n\t\t\t\tdispatch.receiveUserPermission( key, permissions[ action ] );\n\n\t\t\t\t// Mark related action resolutions as finished.\n\t\t\t\tif ( action !== requestedAction ) {\n\t\t\t\t\tdispatch.finishResolution( 'canUser', [\n\t\t\t\t\t\taction,\n\t\t\t\t\t\tresource,\n\t\t\t\t\t\tid,\n\t\t\t\t\t] );\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t};\n\n/**\n * Checks whether the current user can perform the given action on the given\n * REST resource.\n *\n * @param {string} kind Entity kind.\n * @param {string} name Entity name.\n * @param {number|string} recordId Record's id.\n */\nexport const canUserEditEntityRecord =\n\t( kind, name, recordId ) =>\n\tasync ( { dispatch } ) => {\n\t\tawait dispatch( canUser( 'update', { kind, name, id: recordId } ) );\n\t};\n\n/**\n * Request autosave data from the REST API.\n *\n * @param {string} postType The type of the parent post.\n * @param {number} postId The id of the parent post.\n */\nexport const getAutosaves =\n\t( postType, postId ) =>\n\tasync ( { dispatch, resolveSelect } ) => {\n\t\tconst {\n\t\t\trest_base: restBase,\n\t\t\trest_namespace: restNamespace = 'wp/v2',\n\t\t\tsupports,\n\t\t} = await resolveSelect.getPostType( postType );\n\t\tif ( ! supports?.autosave ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst autosaves = await apiFetch( {\n\t\t\tpath: `/${ restNamespace }/${ restBase }/${ postId }/autosaves?context=edit`,\n\t\t} );\n\n\t\tif ( autosaves && autosaves.length ) {\n\t\t\tdispatch.receiveAutosaves( postId, autosaves );\n\t\t}\n\t};\n\n/**\n * Request autosave data from the REST API.\n *\n * This resolver exists to ensure the underlying autosaves are fetched via\n * `getAutosaves` when a call to the `getAutosave` selector is made.\n *\n * @param {string} postType The type of the parent post.\n * @param {number} postId The id of the parent post.\n */\nexport const getAutosave =\n\t( postType, postId ) =>\n\tasync ( { resolveSelect } ) => {\n\t\tawait resolveSelect.getAutosaves( postType, postId );\n\t};\n\nexport const __experimentalGetCurrentGlobalStylesId =\n\t() =>\n\tasync ( { dispatch, resolveSelect } ) => {\n\t\tconst activeThemes = await resolveSelect.getEntityRecords(\n\t\t\t'root',\n\t\t\t'theme',\n\t\t\t{ status: 'active' }\n\t\t);\n\t\tconst globalStylesURL =\n\t\t\tactiveThemes?.[ 0 ]?._links?.[ 'wp:user-global-styles' ]?.[ 0 ]\n\t\t\t\t?.href;\n\t\tif ( ! globalStylesURL ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Regex matches the ID at the end of a URL or immediately before\n\t\t// the query string.\n\t\tconst matches = globalStylesURL.match( /\\/(\\d+)(?:\\?|$)/ );\n\t\tconst id = matches ? Number( matches[ 1 ] ) : null;\n\n\t\tif ( id ) {\n\t\t\tdispatch.__experimentalReceiveCurrentGlobalStylesId( id );\n\t\t}\n\t};\n\nexport const __experimentalGetCurrentThemeBaseGlobalStyles =\n\t() =>\n\tasync ( { resolveSelect, dispatch } ) => {\n\t\tconst currentTheme = await resolveSelect.getCurrentTheme();\n\t\t// Please adjust the preloaded requests if this changes!\n\t\tconst themeGlobalStyles = await apiFetch( {\n\t\t\tpath: `/wp/v2/global-styles/themes/${ currentTheme.stylesheet }?context=view`,\n\t\t} );\n\t\tdispatch.__experimentalReceiveThemeBaseGlobalStyles(\n\t\t\tcurrentTheme.stylesheet,\n\t\t\tthemeGlobalStyles\n\t\t);\n\t};\n\nexport const __experimentalGetCurrentThemeGlobalStylesVariations =\n\t() =>\n\tasync ( { resolveSelect, dispatch } ) => {\n\t\tconst currentTheme = await resolveSelect.getCurrentTheme();\n\t\t// Please adjust the preloaded requests if this changes!\n\t\tconst variations = await apiFetch( {\n\t\t\tpath: `/wp/v2/global-styles/themes/${ currentTheme.stylesheet }/variations?context=view`,\n\t\t} );\n\t\tdispatch.__experimentalReceiveThemeGlobalStyleVariations(\n\t\t\tcurrentTheme.stylesheet,\n\t\t\tvariations\n\t\t);\n\t};\n\n/**\n * Fetches and returns the revisions of the current global styles theme.\n */\nexport const getCurrentThemeGlobalStylesRevisions =\n\t() =>\n\tasync ( { resolveSelect, dispatch } ) => {\n\t\tconst globalStylesId =\n\t\t\tawait resolveSelect.__experimentalGetCurrentGlobalStylesId();\n\t\tconst record = globalStylesId\n\t\t\t? await resolveSelect.getEntityRecord(\n\t\t\t\t\t'root',\n\t\t\t\t\t'globalStyles',\n\t\t\t\t\tglobalStylesId\n\t\t\t )\n\t\t\t: undefined;\n\t\tconst revisionsURL = record?._links?.[ 'version-history' ]?.[ 0 ]?.href;\n\n\t\tif ( revisionsURL ) {\n\t\t\tconst resetRevisions = await apiFetch( {\n\t\t\t\turl: revisionsURL,\n\t\t\t} );\n\t\t\tconst revisions = resetRevisions?.map( ( revision ) =>\n\t\t\t\tObject.fromEntries(\n\t\t\t\t\tObject.entries( revision ).map( ( [ key, value ] ) => [\n\t\t\t\t\t\tcamelCase( key ),\n\t\t\t\t\t\tvalue,\n\t\t\t\t\t] )\n\t\t\t\t)\n\t\t\t);\n\t\t\tdispatch.receiveThemeGlobalStyleRevisions(\n\t\t\t\tglobalStylesId,\n\t\t\t\trevisions\n\t\t\t);\n\t\t}\n\t};\n\ngetCurrentThemeGlobalStylesRevisions.shouldInvalidate = ( action ) => {\n\treturn (\n\t\taction.type === 'SAVE_ENTITY_RECORD_FINISH' &&\n\t\taction.kind === 'root' &&\n\t\t! action.error &&\n\t\taction.name === 'globalStyles'\n\t);\n};\n\nexport const getBlockPatterns =\n\t() =>\n\tasync ( { dispatch } ) => {\n\t\tconst patterns = await fetchBlockPatterns();\n\t\tdispatch( { type: 'RECEIVE_BLOCK_PATTERNS', patterns } );\n\t};\n\nexport const getBlockPatternCategories =\n\t() =>\n\tasync ( { dispatch } ) => {\n\t\tconst categories = await apiFetch( {\n\t\t\tpath: '/wp/v2/block-patterns/categories',\n\t\t} );\n\t\tdispatch( { type: 'RECEIVE_BLOCK_PATTERN_CATEGORIES', categories } );\n\t};\n\nexport const getUserPatternCategories =\n\t() =>\n\tasync ( { dispatch, resolveSelect } ) => {\n\t\tconst patternCategories = await resolveSelect.getEntityRecords(\n\t\t\t'taxonomy',\n\t\t\t'wp_pattern_category',\n\t\t\t{\n\t\t\t\tper_page: -1,\n\t\t\t\t_fields: 'id,name,description,slug',\n\t\t\t\tcontext: 'view',\n\t\t\t}\n\t\t);\n\n\t\tconst mappedPatternCategories =\n\t\t\tpatternCategories?.map( ( userCategory ) => ( {\n\t\t\t\t...userCategory,\n\t\t\t\tlabel: decodeEntities( userCategory.name ),\n\t\t\t\tname: userCategory.slug,\n\t\t\t} ) ) || [];\n\n\t\tdispatch( {\n\t\t\ttype: 'RECEIVE_USER_PATTERN_CATEGORIES',\n\t\t\tpatternCategories: mappedPatternCategories,\n\t\t} );\n\t};\n\nexport const getNavigationFallbackId =\n\t() =>\n\tasync ( { dispatch, select, registry } ) => {\n\t\tconst fallback = await apiFetch( {\n\t\t\tpath: addQueryArgs( '/wp-block-editor/v1/navigation-fallback', {\n\t\t\t\t_embed: true,\n\t\t\t} ),\n\t\t} );\n\n\t\tconst record = fallback?._embedded?.self;\n\n\t\tregistry.batch( () => {\n\t\t\tdispatch.receiveNavigationFallbackId( fallback?.id );\n\n\t\t\tif ( ! record ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If the fallback is already in the store, don't invalidate navigation queries.\n\t\t\t// Otherwise, invalidate the cache for the scenario where there were no Navigation\n\t\t\t// posts in the state and the fallback created one.\n\t\t\tconst existingFallbackEntityRecord = select.getEntityRecord(\n\t\t\t\t'postType',\n\t\t\t\t'wp_navigation',\n\t\t\t\tfallback.id\n\t\t\t);\n\t\t\tconst invalidateNavigationQueries = ! existingFallbackEntityRecord;\n\t\t\tdispatch.receiveEntityRecords(\n\t\t\t\t'postType',\n\t\t\t\t'wp_navigation',\n\t\t\t\trecord,\n\t\t\t\tundefined,\n\t\t\t\tinvalidateNavigationQueries\n\t\t\t);\n\n\t\t\t// Resolve to avoid further network requests.\n\t\t\tdispatch.finishResolution( 'getEntityRecord', [\n\t\t\t\t'postType',\n\t\t\t\t'wp_navigation',\n\t\t\t\tfallback.id,\n\t\t\t] );\n\t\t} );\n\t};\n\nexport const getDefaultTemplateId =\n\t( query ) =>\n\tasync ( { dispatch, registry, resolveSelect } ) => {\n\t\tconst template = await apiFetch( {\n\t\t\tpath: addQueryArgs( '/wp/v2/templates/lookup', query ),\n\t\t} );\n\t\t// Wait for the the entities config to be loaded, otherwise receiving\n\t\t// the template as an entity will not work.\n\t\tawait resolveSelect.getEntitiesConfig( 'postType' );\n\t\t// When active_templates experiment is enabled, use numeric wp_id if it\n\t\t// exists, otherwise fall back to string ID format (theme//slug) as the\n\t\t// frontend expects string IDs for templates.\n\t\tconst id = window?.__experimentalTemplateActivate\n\t\t\t? template?.wp_id || template?.id\n\t\t\t: template?.id;\n\t\t// Endpoint may return an empty object if no template is found.\n\t\tif ( id ) {\n\t\t\ttemplate.id = id;\n\t\t\tregistry.batch( () => {\n\t\t\t\tdispatch.receiveDefaultTemplateId( query, id );\n\t\t\t\tdispatch.receiveEntityRecords( 'postType', template.type, [\n\t\t\t\t\ttemplate,\n\t\t\t\t] );\n\t\t\t\t// Avoid further network requests.\n\t\t\t\tdispatch.finishResolution( 'getEntityRecord', [\n\t\t\t\t\t'postType',\n\t\t\t\t\ttemplate.type,\n\t\t\t\t\tid,\n\t\t\t\t] );\n\t\t\t} );\n\t\t}\n\t};\n\ngetDefaultTemplateId.shouldInvalidate = ( action ) => {\n\treturn (\n\t\taction.type === 'RECEIVE_ITEMS' &&\n\t\taction.kind === 'root' &&\n\t\taction.name === 'site'\n\t);\n};\n\n/**\n * Requests an entity's revisions from the REST API.\n *\n * @param {string} kind Entity kind.\n * @param {string} name Entity name.\n * @param {number|string} recordKey The key of the entity record whose revisions you want to fetch.\n * @param {Object|undefined} query Optional object of query parameters to\n * include with request. If requesting specific\n * fields, fields must always include the ID.\n */\nexport const getRevisions =\n\t( kind, name, recordKey, query = {} ) =>\n\tasync ( { dispatch, registry, resolveSelect } ) => {\n\t\tconst configs = await resolveSelect.getEntitiesConfig( kind );\n\t\tconst entityConfig = configs.find(\n\t\t\t( config ) => config.name === name && config.kind === kind\n\t\t);\n\n\t\tif ( ! entityConfig ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( query._fields ) {\n\t\t\t// If requesting specific fields, items and query association to said\n\t\t\t// records are stored by ID reference. Thus, fields must always include\n\t\t\t// the ID.\n\t\t\tquery = {\n\t\t\t\t...query,\n\t\t\t\t_fields: [\n\t\t\t\t\t...new Set( [\n\t\t\t\t\t\t...( getNormalizedCommaSeparable( query._fields ) ||\n\t\t\t\t\t\t\t[] ),\n\t\t\t\t\t\tentityConfig.revisionKey || DEFAULT_ENTITY_KEY,\n\t\t\t\t\t] ),\n\t\t\t\t].join(),\n\t\t\t};\n\t\t}\n\n\t\tconst path = addQueryArgs(\n\t\t\tentityConfig.getRevisionsUrl( recordKey ),\n\t\t\tquery\n\t\t);\n\n\t\tlet records, response;\n\t\tconst meta = {};\n\t\tconst isPaginated =\n\t\t\tentityConfig.supportsPagination && query.per_page !== -1;\n\t\ttry {\n\t\t\tresponse = await apiFetch( { path, parse: ! isPaginated } );\n\t\t} catch ( error ) {\n\t\t\t// Do nothing if our request comes back with an API error.\n\t\t\treturn;\n\t\t}\n\n\t\tif ( response ) {\n\t\t\tif ( isPaginated ) {\n\t\t\t\trecords = Object.values( await response.json() );\n\t\t\t\tmeta.totalItems = parseInt(\n\t\t\t\t\tresponse.headers.get( 'X-WP-Total' )\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\trecords = Object.values( response );\n\t\t\t}\n\n\t\t\t// If we request fields but the result doesn't contain the fields,\n\t\t\t// explicitly set these fields as \"undefined\"\n\t\t\t// that way we consider the query \"fulfilled\".\n\t\t\tif ( query._fields ) {\n\t\t\t\trecords = records.map( ( record ) => {\n\t\t\t\t\tquery._fields.split( ',' ).forEach( ( field ) => {\n\t\t\t\t\t\tif ( ! record.hasOwnProperty( field ) ) {\n\t\t\t\t\t\t\trecord[ field ] = undefined;\n\t\t\t\t\t\t}\n\t\t\t\t\t} );\n\n\t\t\t\t\treturn record;\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\tregistry.batch( () => {\n\t\t\t\tdispatch.receiveRevisions(\n\t\t\t\t\tkind,\n\t\t\t\t\tname,\n\t\t\t\t\trecordKey,\n\t\t\t\t\trecords,\n\t\t\t\t\tquery,\n\t\t\t\t\tfalse,\n\t\t\t\t\tmeta\n\t\t\t\t);\n\n\t\t\t\t// When requesting all fields, the list of results can be used to\n\t\t\t\t// resolve the `getRevision` selector in addition to `getRevisions`.\n\t\t\t\tif ( ! query?._fields && ! query.context ) {\n\t\t\t\t\tconst key = entityConfig.key || DEFAULT_ENTITY_KEY;\n\t\t\t\t\tconst resolutionsArgs = records\n\t\t\t\t\t\t.filter( ( record ) => record[ key ] )\n\t\t\t\t\t\t.map( ( record ) => [\n\t\t\t\t\t\t\tkind,\n\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\trecordKey,\n\t\t\t\t\t\t\trecord[ key ],\n\t\t\t\t\t\t] );\n\n\t\t\t\t\tdispatch.finishResolutions(\n\t\t\t\t\t\t'getRevision',\n\t\t\t\t\t\tresolutionsArgs\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\t};\n\n// Invalidate cache when a new revision is created.\ngetRevisions.shouldInvalidate = ( action, kind, name, recordKey ) =>\n\taction.type === 'SAVE_ENTITY_RECORD_FINISH' &&\n\tname === action.name &&\n\tkind === action.kind &&\n\t! action.error &&\n\trecordKey === action.recordId;\n\n/**\n * Requests a specific Entity revision from the REST API.\n *\n * @param {string} kind Entity kind.\n * @param {string} name Entity name.\n * @param {number|string} recordKey The key of the entity record whose revisions you want to fetch.\n * @param {number|string} revisionKey The revision's key.\n * @param {Object|undefined} query Optional object of query parameters to\n * include with request. If requesting specific\n * fields, fields must always include the ID.\n */\nexport const getRevision =\n\t( kind, name, recordKey, revisionKey, query ) =>\n\tasync ( { dispatch, resolveSelect } ) => {\n\t\tconst configs = await resolveSelect.getEntitiesConfig( kind );\n\t\tconst entityConfig = configs.find(\n\t\t\t( config ) => config.name === name && config.kind === kind\n\t\t);\n\n\t\tif ( ! entityConfig ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( query !== undefined && query._fields ) {\n\t\t\t// If requesting specific fields, items and query association to said\n\t\t\t// records are stored by ID reference. Thus, fields must always include\n\t\t\t// the ID.\n\t\t\tquery = {\n\t\t\t\t...query,\n\t\t\t\t_fields: [\n\t\t\t\t\t...new Set( [\n\t\t\t\t\t\t...( getNormalizedCommaSeparable( query._fields ) ||\n\t\t\t\t\t\t\t[] ),\n\t\t\t\t\t\tentityConfig.revisionKey || DEFAULT_ENTITY_KEY,\n\t\t\t\t\t] ),\n\t\t\t\t].join(),\n\t\t\t};\n\t\t}\n\t\tconst path = addQueryArgs(\n\t\t\tentityConfig.getRevisionsUrl( recordKey, revisionKey ),\n\t\t\tquery\n\t\t);\n\n\t\tlet record;\n\t\ttry {\n\t\t\trecord = await apiFetch( { path } );\n\t\t} catch ( error ) {\n\t\t\t// Do nothing if our request comes back with an API error.\n\t\t\treturn;\n\t\t}\n\n\t\tif ( record ) {\n\t\t\tdispatch.receiveRevisions( kind, name, recordKey, record, query );\n\t\t}\n\t};\n\n/**\n * Requests a specific post type options from the REST API.\n *\n * @param {string} postType Post type slug.\n */\nexport const getRegisteredPostMeta =\n\t( postType ) =>\n\tasync ( { dispatch, resolveSelect } ) => {\n\t\tlet options;\n\t\ttry {\n\t\t\tconst {\n\t\t\t\trest_namespace: restNamespace = 'wp/v2',\n\t\t\t\trest_base: restBase,\n\t\t\t} = ( await resolveSelect.getPostType( postType ) ) || {};\n\t\t\toptions = await apiFetch( {\n\t\t\t\tpath: `${ restNamespace }/${ restBase }/?context=edit`,\n\t\t\t\tmethod: 'OPTIONS',\n\t\t\t} );\n\t\t} catch ( error ) {\n\t\t\t// Do nothing if the request comes back with an API error.\n\t\t\treturn;\n\t\t}\n\n\t\tif ( options ) {\n\t\t\tdispatch.receiveRegisteredPostMeta(\n\t\t\t\tpostType,\n\t\t\t\toptions?.schema?.properties?.meta?.properties\n\t\t\t);\n\t\t}\n\t};\n\n/**\n * Requests entity configs for the given kind from the REST API.\n *\n * @param {string} kind Entity kind.\n */\nexport const getEntitiesConfig =\n\t( kind ) =>\n\tasync ( { dispatch } ) => {\n\t\tconst loader = additionalEntityConfigLoaders.find(\n\t\t\t( l ) => l.kind === kind\n\t\t);\n\n\t\tif ( ! loader ) {\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tconst configs = await loader.loadEntities();\n\t\t\tif ( ! configs.length ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tdispatch.addEntities( configs );\n\t\t} catch {\n\t\t\t// Do nothing if the request comes back with an API error.\n\t\t}\n\t};\n\n/**\n * Requests editor settings from the REST API.\n */\nexport const getEditorSettings =\n\t() =>\n\tasync ( { dispatch } ) => {\n\t\tconst settings = await apiFetch( {\n\t\t\tpath: '/wp-block-editor/v1/settings',\n\t\t} );\n\t\tdispatch.receiveEditorSettings( settings );\n\t};\n\n/**\n * Requests editor assets from the REST API.\n */\nexport const getEditorAssets =\n\t() =>\n\tasync ( { dispatch } ) => {\n\t\tconst assets = await apiFetch( {\n\t\t\tpath: '/wp-block-editor/v1/assets',\n\t\t} );\n\t\tdispatch.receiveEditorAssets( assets );\n\t};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["apiFetch"]
|
|
7
7
|
}
|
package/build/types.cjs.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/types.ts"],
|
|
4
|
-
"sourcesContent": ["
|
|
4
|
+
"sourcesContent": ["export interface AnyFunction {\n\t( ...args: any[] ): any;\n}\n\n// Avoid a circular dependency with @wordpress/editor\nexport interface WPBlockSelection {\n\tclientId: string;\n\tattributeKey: string;\n\toffset: number;\n}\n\nexport interface WPSelection {\n\tselectionEnd: WPBlockSelection;\n\tselectionStart: WPBlockSelection;\n}\n"],
|
|
5
5
|
"mappings": ";;;;;;;;;;;;;;;;AAAA;AAAA;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -35,9 +35,10 @@ __export(crdt_blocks_exports, {
|
|
|
35
35
|
module.exports = __toCommonJS(crdt_blocks_exports);
|
|
36
36
|
var import_uuid = require("uuid");
|
|
37
37
|
var import_es6 = __toESM(require("fast-deep-equal/es6/index.js"));
|
|
38
|
+
var import_blocks = require("@wordpress/blocks");
|
|
38
39
|
var import_rich_text = require("@wordpress/rich-text");
|
|
39
40
|
var import_sync = require("@wordpress/sync");
|
|
40
|
-
var
|
|
41
|
+
var import_crdt_utils = require("./crdt-utils.cjs");
|
|
41
42
|
var serializableBlocksCache = /* @__PURE__ */ new WeakMap();
|
|
42
43
|
function makeBlockAttributesSerializable(attributes) {
|
|
43
44
|
const newAttributes = { ...attributes };
|
|
@@ -50,10 +51,8 @@ function makeBlockAttributesSerializable(attributes) {
|
|
|
50
51
|
}
|
|
51
52
|
function makeBlocksSerializable(blocks) {
|
|
52
53
|
return blocks.map((block) => {
|
|
53
|
-
const
|
|
54
|
-
const { name, innerBlocks, attributes, ...rest } = blockAsJson;
|
|
54
|
+
const { name, innerBlocks, attributes, ...rest } = block;
|
|
55
55
|
delete rest.validationIssues;
|
|
56
|
-
delete rest.originalContent;
|
|
57
56
|
return {
|
|
58
57
|
...rest,
|
|
59
58
|
name,
|
|
@@ -74,7 +73,7 @@ function areBlocksEqual(gblock, yblock) {
|
|
|
74
73
|
);
|
|
75
74
|
const inners = gblock.innerBlocks || [];
|
|
76
75
|
const yinners = yblock.get("innerBlocks");
|
|
77
|
-
return res && inners.length === yinners
|
|
76
|
+
return res && inners.length === yinners?.length && inners.every(
|
|
78
77
|
(block, i) => areBlocksEqual(block, yinners.get(i))
|
|
79
78
|
);
|
|
80
79
|
}
|
|
@@ -102,32 +101,37 @@ function createNewYAttributeValue(blockName, attributeName, attributeValue) {
|
|
|
102
101
|
return attributeValue;
|
|
103
102
|
}
|
|
104
103
|
function createNewYBlock(block) {
|
|
105
|
-
return
|
|
106
|
-
Object.
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
104
|
+
return (0, import_crdt_utils.createYMap)(
|
|
105
|
+
Object.fromEntries(
|
|
106
|
+
Object.entries(block).map(([key, value]) => {
|
|
107
|
+
switch (key) {
|
|
108
|
+
case "attributes": {
|
|
109
|
+
return [
|
|
110
|
+
key,
|
|
111
|
+
createNewYAttributeMap(block.name, value)
|
|
112
|
+
];
|
|
113
|
+
}
|
|
114
|
+
case "innerBlocks": {
|
|
115
|
+
const innerBlocks = new import_sync.Y.Array();
|
|
116
|
+
if (!Array.isArray(value)) {
|
|
117
|
+
return [key, innerBlocks];
|
|
118
|
+
}
|
|
119
|
+
innerBlocks.insert(
|
|
120
|
+
0,
|
|
121
|
+
value.map(
|
|
122
|
+
(innerBlock) => createNewYBlock(innerBlock)
|
|
123
|
+
)
|
|
124
|
+
);
|
|
114
125
|
return [key, innerBlocks];
|
|
115
126
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
value.map(
|
|
119
|
-
(innerBlock) => createNewYBlock(innerBlock)
|
|
120
|
-
)
|
|
121
|
-
);
|
|
122
|
-
return [key, innerBlocks];
|
|
127
|
+
default:
|
|
128
|
+
return [key, value];
|
|
123
129
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
}
|
|
127
|
-
})
|
|
130
|
+
})
|
|
131
|
+
)
|
|
128
132
|
);
|
|
129
133
|
}
|
|
130
|
-
function mergeCrdtBlocks(yblocks, incomingBlocks,
|
|
134
|
+
function mergeCrdtBlocks(yblocks, incomingBlocks, cursorPosition) {
|
|
131
135
|
if (!serializableBlocksCache.has(incomingBlocks)) {
|
|
132
136
|
serializableBlocksCache.set(
|
|
133
137
|
incomingBlocks,
|
|
@@ -166,9 +170,7 @@ function mergeCrdtBlocks(yblocks, incomingBlocks, lastSelection) {
|
|
|
166
170
|
Object.entries(block).forEach(([key, value]) => {
|
|
167
171
|
switch (key) {
|
|
168
172
|
case "attributes": {
|
|
169
|
-
const currentAttributes = yblock.get(
|
|
170
|
-
key
|
|
171
|
-
);
|
|
173
|
+
const currentAttributes = yblock.get(key);
|
|
172
174
|
if (!currentAttributes) {
|
|
173
175
|
yblock.set(
|
|
174
176
|
key,
|
|
@@ -184,19 +186,16 @@ function mergeCrdtBlocks(yblocks, incomingBlocks, lastSelection) {
|
|
|
184
186
|
)) {
|
|
185
187
|
return;
|
|
186
188
|
}
|
|
189
|
+
const currentAttribute = currentAttributes.get(attributeName);
|
|
187
190
|
const isRichText = isRichTextAttribute(
|
|
188
191
|
block.name,
|
|
189
192
|
attributeName
|
|
190
193
|
);
|
|
191
|
-
if (isRichText && "string" === typeof attributeValue && currentAttributes.has(attributeName) &&
|
|
192
|
-
attributeName
|
|
193
|
-
) instanceof import_sync.Y.Text) {
|
|
194
|
+
if (isRichText && "string" === typeof attributeValue && currentAttributes.has(attributeName) && currentAttribute instanceof import_sync.Y.Text) {
|
|
194
195
|
mergeRichTextUpdate(
|
|
195
|
-
|
|
196
|
-
attributeName
|
|
197
|
-
),
|
|
196
|
+
currentAttribute,
|
|
198
197
|
attributeValue,
|
|
199
|
-
|
|
198
|
+
cursorPosition
|
|
200
199
|
);
|
|
201
200
|
} else {
|
|
202
201
|
currentAttributes.set(
|
|
@@ -220,8 +219,16 @@ function mergeCrdtBlocks(yblocks, incomingBlocks, lastSelection) {
|
|
|
220
219
|
break;
|
|
221
220
|
}
|
|
222
221
|
case "innerBlocks": {
|
|
223
|
-
|
|
224
|
-
|
|
222
|
+
let yInnerBlocks = yblock.get(key);
|
|
223
|
+
if (!(yInnerBlocks instanceof import_sync.Y.Array)) {
|
|
224
|
+
yInnerBlocks = new import_sync.Y.Array();
|
|
225
|
+
yblock.set(key, yInnerBlocks);
|
|
226
|
+
}
|
|
227
|
+
mergeCrdtBlocks(
|
|
228
|
+
yInnerBlocks,
|
|
229
|
+
value ?? [],
|
|
230
|
+
cursorPosition
|
|
231
|
+
);
|
|
225
232
|
break;
|
|
226
233
|
}
|
|
227
234
|
default:
|
|
@@ -245,6 +252,9 @@ function mergeCrdtBlocks(yblocks, incomingBlocks, lastSelection) {
|
|
|
245
252
|
for (let j = 0; j < yblocks.length; j++) {
|
|
246
253
|
const yblock = yblocks.get(j);
|
|
247
254
|
let clientId = yblock.get("clientId");
|
|
255
|
+
if (!clientId) {
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
248
258
|
if (knownClientIds.has(clientId)) {
|
|
249
259
|
clientId = (0, import_uuid.v4)();
|
|
250
260
|
yblock.set("clientId", clientId);
|
|
@@ -281,9 +291,21 @@ function isRichTextAttribute(blockName, attributeName) {
|
|
|
281
291
|
}
|
|
282
292
|
return cachedRichTextAttributes.get(blockName)?.has(attributeName) ?? false;
|
|
283
293
|
}
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
294
|
+
var localDoc;
|
|
295
|
+
function mergeRichTextUpdate(blockYText, updatedValue, cursorPosition) {
|
|
296
|
+
if (!localDoc) {
|
|
297
|
+
localDoc = new import_sync.Y.Doc();
|
|
298
|
+
}
|
|
299
|
+
const localYText = localDoc.getText("temporary-text");
|
|
300
|
+
localYText.delete(0, localYText.length);
|
|
301
|
+
localYText.insert(0, updatedValue);
|
|
302
|
+
const currentValueAsDelta = new import_sync.Delta(blockYText.toDelta());
|
|
303
|
+
const updatedValueAsDelta = new import_sync.Delta(localYText.toDelta());
|
|
304
|
+
const deltaDiff = currentValueAsDelta.diffWithCursor(
|
|
305
|
+
updatedValueAsDelta,
|
|
306
|
+
cursorPosition
|
|
307
|
+
);
|
|
308
|
+
blockYText.applyDelta(deltaDiff.ops);
|
|
287
309
|
}
|
|
288
310
|
// Annotate the CommonJS export names for ESM import in node:
|
|
289
311
|
0 && (module.exports = {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/utils/crdt-blocks.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * External dependencies\n */\nimport { v4 as uuidv4 } from 'uuid';\nimport fastDeepEqual from 'fast-deep-equal/es6/index.js';\n\n/**\n * WordPress dependencies\n */\nimport { RichTextData } from '@wordpress/rich-text';\nimport { Y } from '@wordpress/sync';\n\n// @ts-expect-error No exported types.\nimport { getBlockTypes } from '@wordpress/blocks';\n\n/**\n * Internal dependencies\n */\nimport type { WPBlockSelection } from '../types';\n\ninterface BlockAttributes {\n\t[ key: string ]: unknown;\n}\n\ninterface BlockType {\n\tname: string;\n\tattributes?: Record< string, { type?: string } >;\n}\n\nexport interface Block {\n\tattributes: BlockAttributes;\n\tclientId?: string;\n\tinnerBlocks: Block[];\n\toriginalContent?: string; // unserializable\n\tvalidationIssues?: string[]; // unserializable\n\tname: string;\n}\n\nexport type YBlock = Y.Map<\n\t/* name, clientId, and originalContent are strings. */\n\t| string\n\t/* validationIssues? is an array of strings. */\n\t| string[]\n\t/* attributes is a Y.Map< unknown >. */\n\t| YBlockAttributes\n\t/* innerBlocks is a Y.Array< YBlock >. */\n\t| YBlocks\n>;\n\nexport type YBlocks = Y.Array< YBlock >;\nexport type YBlockAttributes = Y.Map< Y.Text | unknown >;\n\n// The Y.Map type is not easy to work with. The generic type it accepts represents\n// the possible values of the map, which are varied in our case. This type is\n// accurate, but will require aggressive type narrowing when the map values are\n// accessed -- or type casting with `as`.\n// export type YBlock = Y.Map< Block[ keyof Block ] >;\n\nconst serializableBlocksCache = new WeakMap< WeakKey, Block[] >();\n\nfunction makeBlockAttributesSerializable(\n\tattributes: BlockAttributes\n): BlockAttributes {\n\tconst newAttributes = { ...attributes };\n\tfor ( const [ key, value ] of Object.entries( attributes ) ) {\n\t\tif ( value instanceof RichTextData ) {\n\t\t\tnewAttributes[ key ] = value.valueOf();\n\t\t}\n\t}\n\treturn newAttributes;\n}\n\nfunction makeBlocksSerializable( blocks: Block[] | YBlocks ): Block[] {\n\treturn blocks.map( ( block: Block | YBlock ) => {\n\t\tconst blockAsJson = block instanceof Y.Map ? block.toJSON() : block;\n\t\tconst { name, innerBlocks, attributes, ...rest } = blockAsJson;\n\t\tdelete rest.validationIssues;\n\t\tdelete rest.originalContent;\n\t\t// delete rest.isValid\n\t\treturn {\n\t\t\t...rest,\n\t\t\tname,\n\t\t\tattributes: makeBlockAttributesSerializable( attributes ),\n\t\t\tinnerBlocks: makeBlocksSerializable( innerBlocks ),\n\t\t};\n\t} );\n}\n\n/**\n * @param {any} gblock\n * @param {Y.Map} yblock\n */\nfunction areBlocksEqual( gblock: Block, yblock: YBlock ): boolean {\n\tconst yblockAsJson = yblock.toJSON();\n\n\t// we must not sync clientId, as this can't be generated consistently and\n\t// hence will lead to merge conflicts.\n\tconst overwrites = {\n\t\tinnerBlocks: null,\n\t\tclientId: null,\n\t};\n\tconst res = fastDeepEqual(\n\t\tObject.assign( {}, gblock, overwrites ),\n\t\tObject.assign( {}, yblockAsJson, overwrites )\n\t);\n\tconst inners = gblock.innerBlocks || [];\n\tconst yinners = yblock.get( 'innerBlocks' ) as YBlocks;\n\treturn (\n\t\tres &&\n\t\tinners.length === yinners.length &&\n\t\tinners.every( ( block: Block, i: number ) =>\n\t\t\tareBlocksEqual( block, yinners.get( i ) )\n\t\t)\n\t);\n}\n\nfunction createNewYAttributeMap(\n\tblockName: string,\n\tattributes: BlockAttributes\n): YBlockAttributes {\n\treturn new Y.Map(\n\t\tObject.entries( attributes ).map(\n\t\t\t( [ attributeName, attributeValue ] ) => {\n\t\t\t\treturn [\n\t\t\t\t\tattributeName,\n\t\t\t\t\tcreateNewYAttributeValue(\n\t\t\t\t\t\tblockName,\n\t\t\t\t\t\tattributeName,\n\t\t\t\t\t\tattributeValue\n\t\t\t\t\t),\n\t\t\t\t];\n\t\t\t}\n\t\t)\n\t);\n}\n\nfunction createNewYAttributeValue(\n\tblockName: string,\n\tattributeName: string,\n\tattributeValue: unknown\n): Y.Text | unknown {\n\tconst isRichText = isRichTextAttribute( blockName, attributeName );\n\n\tif ( isRichText ) {\n\t\treturn new Y.Text( attributeValue?.toString() ?? '' );\n\t}\n\n\treturn attributeValue;\n}\n\nfunction createNewYBlock( block: Block ): YBlock {\n\treturn new Y.Map(\n\t\tObject.entries( block ).map( ( [ key, value ] ) => {\n\t\t\tswitch ( key ) {\n\t\t\t\tcase 'attributes': {\n\t\t\t\t\treturn [ key, createNewYAttributeMap( block.name, value ) ];\n\t\t\t\t}\n\n\t\t\t\tcase 'innerBlocks': {\n\t\t\t\t\tconst innerBlocks = new Y.Array();\n\n\t\t\t\t\t// If not an array, set to empty Y.Array.\n\t\t\t\t\tif ( ! Array.isArray( value ) ) {\n\t\t\t\t\t\treturn [ key, innerBlocks ];\n\t\t\t\t\t}\n\n\t\t\t\t\tinnerBlocks.insert(\n\t\t\t\t\t\t0,\n\t\t\t\t\t\tvalue.map( ( innerBlock: Block ) =>\n\t\t\t\t\t\t\tcreateNewYBlock( innerBlock )\n\t\t\t\t\t\t)\n\t\t\t\t\t);\n\n\t\t\t\t\treturn [ key, innerBlocks ];\n\t\t\t\t}\n\n\t\t\t\tdefault:\n\t\t\t\t\treturn [ key, value ];\n\t\t\t}\n\t\t} )\n\t);\n}\n\n/**\n * Merge incoming block data into the local Y.Doc.\n * This function is called to sync local block changes to a shared Y.Doc.\n *\n * @param yblocks The blocks in the local Y.Doc.\n * @param incomingBlocks Gutenberg blocks being synced, either from a peer or from the local editor.\n * @param lastSelection The last cursor position, used for hinting the diff algorithm.\n */\nexport function mergeCrdtBlocks(\n\tyblocks: YBlocks,\n\tincomingBlocks: Block[],\n\tlastSelection: WPBlockSelection | null\n): void {\n\t// Ensure we are working with serializable block data.\n\tif ( ! serializableBlocksCache.has( incomingBlocks ) ) {\n\t\tserializableBlocksCache.set(\n\t\t\tincomingBlocks,\n\t\t\tmakeBlocksSerializable( incomingBlocks )\n\t\t);\n\t}\n\tconst allBlocks = serializableBlocksCache.get( incomingBlocks ) ?? [];\n\n\t// Ensure we skip blocks that we don't want to sync at the moment\n\tconst blocksToSync = allBlocks.filter( ( block ) =>\n\t\tshouldBlockBeSynced( block )\n\t);\n\n\t// This is a rudimentary diff implementation similar to the y-prosemirror diffing\n\t// approach.\n\t// A better implementation would also diff the textual content and represent it\n\t// using a Y.Text type.\n\t// However, at this time it makes more sense to keep this algorithm generic to\n\t// support all kinds of block types.\n\t// Ideally, we ensure that block data structure have a consistent data format.\n\t// E.g.:\n\t// - textual content (using rich-text formatting?) may always be stored under `block.text`\n\t// - local information that shouldn't be shared (e.g. clientId or isDragging) is stored under `block.private`\n\t//\n\t// @credit Kevin Jahns (dmonad)\n\t// @link https://github.com/WordPress/gutenberg/pull/68483\n\tconst numOfCommonEntries = Math.min(\n\t\tblocksToSync.length ?? 0,\n\t\tyblocks.length\n\t);\n\n\tlet left = 0;\n\tlet right = 0;\n\n\t// skip equal blocks from left\n\tfor (\n\t\t;\n\t\tleft < numOfCommonEntries &&\n\t\tareBlocksEqual( blocksToSync[ left ], yblocks.get( left ) );\n\t\tleft++\n\t) {\n\t\t/* nop */\n\t}\n\n\t// skip equal blocks from right\n\tfor (\n\t\t;\n\t\tright < numOfCommonEntries - left &&\n\t\tareBlocksEqual(\n\t\t\tblocksToSync[ blocksToSync.length - right - 1 ],\n\t\t\tyblocks.get( yblocks.length - right - 1 )\n\t\t);\n\t\tright++\n\t) {\n\t\t/* nop */\n\t}\n\n\tconst numOfUpdatesNeeded = numOfCommonEntries - left - right;\n\tconst numOfInsertionsNeeded = Math.max(\n\t\t0,\n\t\tblocksToSync.length - yblocks.length\n\t);\n\tconst numOfDeletionsNeeded = Math.max(\n\t\t0,\n\t\tyblocks.length - blocksToSync.length\n\t);\n\n\t// updates\n\tfor ( let i = 0; i < numOfUpdatesNeeded; i++, left++ ) {\n\t\tconst block = blocksToSync[ left ];\n\t\tconst yblock = yblocks.get( left );\n\t\tObject.entries( block ).forEach( ( [ key, value ] ) => {\n\t\t\tswitch ( key ) {\n\t\t\t\tcase 'attributes': {\n\t\t\t\t\tconst currentAttributes = yblock.get(\n\t\t\t\t\t\tkey\n\t\t\t\t\t) as YBlockAttributes;\n\n\t\t\t\t\t// If attributes are not set on the yblock, use the new values.\n\t\t\t\t\tif ( ! currentAttributes ) {\n\t\t\t\t\t\tyblock.set(\n\t\t\t\t\t\t\tkey,\n\t\t\t\t\t\t\tcreateNewYAttributeMap( block.name, value )\n\t\t\t\t\t\t);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tObject.entries( value ).forEach(\n\t\t\t\t\t\t( [ attributeName, attributeValue ] ) => {\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\tfastDeepEqual(\n\t\t\t\t\t\t\t\t\tcurrentAttributes?.get( attributeName ),\n\t\t\t\t\t\t\t\t\tattributeValue\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tconst isRichText = isRichTextAttribute(\n\t\t\t\t\t\t\t\tblock.name,\n\t\t\t\t\t\t\t\tattributeName\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\tisRichText &&\n\t\t\t\t\t\t\t\t'string' === typeof attributeValue &&\n\t\t\t\t\t\t\t\tcurrentAttributes.has( attributeName ) &&\n\t\t\t\t\t\t\t\tcurrentAttributes.get(\n\t\t\t\t\t\t\t\t\tattributeName\n\t\t\t\t\t\t\t\t) instanceof Y.Text\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t// Rich text values are stored as persistent Y.Text instances.\n\t\t\t\t\t\t\t\t// Update the value with a delta in place.\n\t\t\t\t\t\t\t\tmergeRichTextUpdate(\n\t\t\t\t\t\t\t\t\tcurrentAttributes.get(\n\t\t\t\t\t\t\t\t\t\tattributeName\n\t\t\t\t\t\t\t\t\t) as Y.Text,\n\t\t\t\t\t\t\t\t\tattributeValue,\n\t\t\t\t\t\t\t\t\tlastSelection\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tcurrentAttributes.set(\n\t\t\t\t\t\t\t\t\tattributeName,\n\t\t\t\t\t\t\t\t\tcreateNewYAttributeValue(\n\t\t\t\t\t\t\t\t\t\tblock.name,\n\t\t\t\t\t\t\t\t\t\tattributeName,\n\t\t\t\t\t\t\t\t\t\tattributeValue\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\n\t\t\t\t\t// Delete any attributes that are no longer present.\n\t\t\t\t\tcurrentAttributes.forEach(\n\t\t\t\t\t\t( _attrValue: unknown, attrName: string ) => {\n\t\t\t\t\t\t\tif ( ! value.hasOwnProperty( attrName ) ) {\n\t\t\t\t\t\t\t\tcurrentAttributes.delete( attrName );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase 'innerBlocks': {\n\t\t\t\t\t// Recursively merge innerBlocks\n\t\t\t\t\tconst yInnerBlocks = yblock.get( key ) as Y.Array< YBlock >;\n\t\t\t\t\tmergeCrdtBlocks( yInnerBlocks, value ?? [], lastSelection );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tdefault:\n\t\t\t\t\tif ( ! fastDeepEqual( block[ key ], yblock.get( key ) ) ) {\n\t\t\t\t\t\tyblock.set( key, value );\n\t\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t\tyblock.forEach( ( _v, k ) => {\n\t\t\tif ( ! block.hasOwnProperty( k ) ) {\n\t\t\t\tyblock.delete( k );\n\t\t\t}\n\t\t} );\n\t}\n\n\t// deletes\n\tyblocks.delete( left, numOfDeletionsNeeded );\n\n\t// inserts\n\tfor ( let i = 0; i < numOfInsertionsNeeded; i++, left++ ) {\n\t\tconst newBlock = [ createNewYBlock( blocksToSync[ left ] ) ];\n\n\t\tyblocks.insert( left, newBlock );\n\t}\n\n\t// remove duplicate clientids\n\tconst knownClientIds = new Set< string >();\n\tfor ( let j = 0; j < yblocks.length; j++ ) {\n\t\tconst yblock: YBlock = yblocks.get( j );\n\n\t\tlet clientId: string = yblock.get( 'clientId' ) as string;\n\n\t\tif ( knownClientIds.has( clientId ) ) {\n\t\t\tclientId = uuidv4();\n\t\t\tyblock.set( 'clientId', clientId );\n\t\t}\n\t\tknownClientIds.add( clientId );\n\t}\n}\n\n/**\n * Determine if a block should be synced.\n *\n * Ex: A gallery block should not be synced until the images have been\n * uploaded to WordPress, and their url is available. Before that,\n * it's not possible to access the blobs on a client as those are\n * local.\n *\n * @param block The block to check.\n * @return True if the block should be synced, false otherwise.\n */\nfunction shouldBlockBeSynced( block: Block ): boolean {\n\t// Verify that the gallery block is ready to be synced.\n\t// This means that, all images have had their blobs converted to full URLs.\n\t// Checking for only the blobs ensures that blocks that have just been inserted work as well.\n\tif ( 'core/gallery' === block.name ) {\n\t\treturn ! block.innerBlocks.some(\n\t\t\t( innerBlock ) =>\n\t\t\t\tinnerBlock.attributes && innerBlock.attributes.blob\n\t\t);\n\t}\n\n\t// Allow all other blocks to be synced.\n\treturn true;\n}\n\n// Cache rich-text attributes for all block types.\nlet cachedRichTextAttributes: Map< string, Map< string, true > >;\n\n/**\n * Given a block name and attribute key, return true if the attribute is rich-text typed.\n *\n * @param blockName The name of the block, e.g. 'core/paragraph'.\n * @param attributeName The name of the attribute to check, e.g. 'content'.\n * @return True if the attribute is rich-text typed, false otherwise.\n */\nfunction isRichTextAttribute(\n\tblockName: string,\n\tattributeName: string\n): boolean {\n\tif ( ! cachedRichTextAttributes ) {\n\t\t// Parse the attributes for all blocks once.\n\t\tcachedRichTextAttributes = new Map< string, Map< string, true > >();\n\n\t\tfor ( const blockType of getBlockTypes() as BlockType[] ) {\n\t\t\tconst richTextAttributeMap = new Map< string, true >();\n\n\t\t\tfor ( const [ name, definition ] of Object.entries(\n\t\t\t\tblockType.attributes ?? {}\n\t\t\t) ) {\n\t\t\t\tif ( 'rich-text' === definition.type ) {\n\t\t\t\t\trichTextAttributeMap.set( name, true );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tcachedRichTextAttributes.set(\n\t\t\t\tblockType.name,\n\t\t\t\trichTextAttributeMap\n\t\t\t);\n\t\t}\n\t}\n\n\treturn (\n\t\tcachedRichTextAttributes.get( blockName )?.has( attributeName ) ?? false\n\t);\n}\n\n/**\n * Given a Y.Text object and an updated string value, diff the new value and\n * apply the delta to the Y.Text.\n *\n * @param blockYText The Y.Text to update.\n * @param updatedValue The updated value.\n * @param lastSelection The last cursor position before this update, used to hint the diff algorithm.\n */\nfunction mergeRichTextUpdate(\n\tblockYText: Y.Text,\n\tupdatedValue: string,\n\t// eslint-disable-next-line @typescript-eslint/no-unused-vars\n\tlastSelection: WPBlockSelection | null\n): void {\n\t// TODO\n\t// ====\n\t// Gutenberg does not use Yjs shared types natively, so we can only subscribe\n\t// to changes from store and apply them to Yjs types that we create and\n\t// manage. Crucially, for rich-text attributes, we do not receive granular\n\t// string updates; we get the new full string value on each change, even when\n\t// only a single character changed.\n\t//\n\t// The code below allows us to compute a delta between the current and new\n\t// value, then apply it to the Y.Text. However, it relies on a library\n\t// (quill-delta) with a licensing issue that we are working to resolve.\n\t//\n\t// For now, we simply replace the full text content on each change.\n\t//\n\t// if ( ! localDoc ) {\n\t// \t// Y.Text must be attached to a Y.Doc to be able to do operations on it.\n\t// \t// Create a temporary Y.Text attached to a local Y.Doc for delta computation.\n\t// \tlocalDoc = new Y.Doc();\n\t// }\n\n\t// const localYText = localDoc.getText( 'temporary-text' );\n\t// localYText.delete( 0, localYText.length );\n\t// localYText.insert( 0, updatedValue );\n\n\t// const currentValueAsDelta = new Delta( blockYText.toDelta() );\n\t// const updatedValueAsDelta = new Delta( localYText.toDelta() );\n\n\t// const deltaDiff = currentValueAsDelta.diff(\n\t// \tupdatedValueAsDelta,\n\t// \tlastSelection?.offset\n\t// );\n\n\t// blockYText.applyDelta( deltaDiff.ops );\n\n\tblockYText.delete( 0, blockYText.toString().length );\n\tblockYText.insert( 0, updatedValue );\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,kBAA6B;AAC7B,iBAA0B;
|
|
4
|
+
"sourcesContent": ["/**\n * External dependencies\n */\nimport { v4 as uuidv4 } from 'uuid';\nimport fastDeepEqual from 'fast-deep-equal/es6/index.js';\n\n/**\n * WordPress dependencies\n */\n// @ts-expect-error No exported types.\nimport { getBlockTypes } from '@wordpress/blocks';\nimport { RichTextData } from '@wordpress/rich-text';\nimport { Y, Delta } from '@wordpress/sync';\n\n/**\n * Internal dependencies\n */\nimport { createYMap, type YMapRecord, type YMapWrap } from './crdt-utils';\n\ninterface BlockAttributes {\n\t[ key: string ]: unknown;\n}\n\ninterface BlockType {\n\tname: string;\n\tattributes?: Record< string, { type?: string } >;\n}\n\n// A block as represented in Gutenberg's data store.\nexport interface Block {\n\tattributes: BlockAttributes;\n\tclientId?: string;\n\tinnerBlocks: Block[];\n\tisValid?: boolean;\n\tname: string;\n\toriginalContent?: string;\n\tvalidationIssues?: string[]; // unserializable\n}\n\n// A block as represented in the CRDT document (Y.Map).\ninterface YBlockRecord extends YMapRecord {\n\tattributes: YBlockAttributes;\n\tclientId: string;\n\tinnerBlocks: YBlocks;\n\tisValid?: boolean;\n\toriginalContent?: string;\n\tname: string;\n}\n\nexport type YBlock = YMapWrap< YBlockRecord >;\nexport type YBlocks = Y.Array< YBlock >;\n\n// Block attribute schema cannot be known at compile time, so we use Y.Map.\n// Attribute values will be typed as the union of `Y.Text` and `unknown`.\nexport type YBlockAttributes = Y.Map< Y.Text | unknown >;\n\nconst serializableBlocksCache = new WeakMap< WeakKey, Block[] >();\n\nfunction makeBlockAttributesSerializable(\n\tattributes: BlockAttributes\n): BlockAttributes {\n\tconst newAttributes = { ...attributes };\n\tfor ( const [ key, value ] of Object.entries( attributes ) ) {\n\t\tif ( value instanceof RichTextData ) {\n\t\t\tnewAttributes[ key ] = value.valueOf();\n\t\t}\n\t}\n\treturn newAttributes;\n}\n\nfunction makeBlocksSerializable( blocks: Block[] ): Block[] {\n\treturn blocks.map( ( block: Block ) => {\n\t\tconst { name, innerBlocks, attributes, ...rest } = block;\n\t\tdelete rest.validationIssues;\n\t\treturn {\n\t\t\t...rest,\n\t\t\tname,\n\t\t\tattributes: makeBlockAttributesSerializable( attributes ),\n\t\t\tinnerBlocks: makeBlocksSerializable( innerBlocks ),\n\t\t};\n\t} );\n}\n\n/**\n * @param {any} gblock\n * @param {Y.Map} yblock\n */\nfunction areBlocksEqual( gblock: Block, yblock: YBlock ): boolean {\n\tconst yblockAsJson = yblock.toJSON();\n\n\t// we must not sync clientId, as this can't be generated consistently and\n\t// hence will lead to merge conflicts.\n\tconst overwrites = {\n\t\tinnerBlocks: null,\n\t\tclientId: null,\n\t};\n\tconst res = fastDeepEqual(\n\t\tObject.assign( {}, gblock, overwrites ),\n\t\tObject.assign( {}, yblockAsJson, overwrites )\n\t);\n\tconst inners = gblock.innerBlocks || [];\n\tconst yinners = yblock.get( 'innerBlocks' );\n\treturn (\n\t\tres &&\n\t\tinners.length === yinners?.length &&\n\t\tinners.every( ( block: Block, i: number ) =>\n\t\t\tareBlocksEqual( block, yinners.get( i ) )\n\t\t)\n\t);\n}\n\nfunction createNewYAttributeMap(\n\tblockName: string,\n\tattributes: BlockAttributes\n): YBlockAttributes {\n\treturn new Y.Map(\n\t\tObject.entries( attributes ).map(\n\t\t\t( [ attributeName, attributeValue ] ) => {\n\t\t\t\treturn [\n\t\t\t\t\tattributeName,\n\t\t\t\t\tcreateNewYAttributeValue(\n\t\t\t\t\t\tblockName,\n\t\t\t\t\t\tattributeName,\n\t\t\t\t\t\tattributeValue\n\t\t\t\t\t),\n\t\t\t\t];\n\t\t\t}\n\t\t)\n\t);\n}\n\nfunction createNewYAttributeValue(\n\tblockName: string,\n\tattributeName: string,\n\tattributeValue: unknown\n): Y.Text | unknown {\n\tconst isRichText = isRichTextAttribute( blockName, attributeName );\n\n\tif ( isRichText ) {\n\t\treturn new Y.Text( attributeValue?.toString() ?? '' );\n\t}\n\n\treturn attributeValue;\n}\n\nfunction createNewYBlock( block: Block ): YBlock {\n\treturn createYMap< YBlockRecord >(\n\t\tObject.fromEntries(\n\t\t\tObject.entries( block ).map( ( [ key, value ] ) => {\n\t\t\t\tswitch ( key ) {\n\t\t\t\t\tcase 'attributes': {\n\t\t\t\t\t\treturn [\n\t\t\t\t\t\t\tkey,\n\t\t\t\t\t\t\tcreateNewYAttributeMap( block.name, value ),\n\t\t\t\t\t\t];\n\t\t\t\t\t}\n\n\t\t\t\t\tcase 'innerBlocks': {\n\t\t\t\t\t\tconst innerBlocks = new Y.Array();\n\n\t\t\t\t\t\t// If not an array, set to empty Y.Array.\n\t\t\t\t\t\tif ( ! Array.isArray( value ) ) {\n\t\t\t\t\t\t\treturn [ key, innerBlocks ];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tinnerBlocks.insert(\n\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\tvalue.map( ( innerBlock: Block ) =>\n\t\t\t\t\t\t\t\tcreateNewYBlock( innerBlock )\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\treturn [ key, innerBlocks ];\n\t\t\t\t\t}\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\treturn [ key, value ];\n\t\t\t\t}\n\t\t\t} )\n\t\t)\n\t);\n}\n\n/**\n * Merge incoming block data into the local Y.Doc.\n * This function is called to sync local block changes to a shared Y.Doc.\n *\n * @param yblocks The blocks in the local Y.Doc.\n * @param incomingBlocks Gutenberg blocks being synced.\n * @param cursorPosition The position of the cursor after the change occurs.\n */\nexport function mergeCrdtBlocks(\n\tyblocks: YBlocks,\n\tincomingBlocks: Block[],\n\tcursorPosition: number | null\n): void {\n\t// Ensure we are working with serializable block data.\n\tif ( ! serializableBlocksCache.has( incomingBlocks ) ) {\n\t\tserializableBlocksCache.set(\n\t\t\tincomingBlocks,\n\t\t\tmakeBlocksSerializable( incomingBlocks )\n\t\t);\n\t}\n\tconst allBlocks = serializableBlocksCache.get( incomingBlocks ) ?? [];\n\n\t// Ensure we skip blocks that we don't want to sync at the moment\n\tconst blocksToSync = allBlocks.filter( ( block ) =>\n\t\tshouldBlockBeSynced( block )\n\t);\n\n\t// This is a rudimentary diff implementation similar to the y-prosemirror diffing\n\t// approach.\n\t// A better implementation would also diff the textual content and represent it\n\t// using a Y.Text type.\n\t// However, at this time it makes more sense to keep this algorithm generic to\n\t// support all kinds of block types.\n\t// Ideally, we ensure that block data structure have a consistent data format.\n\t// E.g.:\n\t// - textual content (using rich-text formatting?) may always be stored under `block.text`\n\t// - local information that shouldn't be shared (e.g. clientId or isDragging) is stored under `block.private`\n\t//\n\t// @credit Kevin Jahns (dmonad)\n\t// @link https://github.com/WordPress/gutenberg/pull/68483\n\tconst numOfCommonEntries = Math.min(\n\t\tblocksToSync.length ?? 0,\n\t\tyblocks.length\n\t);\n\n\tlet left = 0;\n\tlet right = 0;\n\n\t// skip equal blocks from left\n\tfor (\n\t\t;\n\t\tleft < numOfCommonEntries &&\n\t\tareBlocksEqual( blocksToSync[ left ], yblocks.get( left ) );\n\t\tleft++\n\t) {\n\t\t/* nop */\n\t}\n\n\t// skip equal blocks from right\n\tfor (\n\t\t;\n\t\tright < numOfCommonEntries - left &&\n\t\tareBlocksEqual(\n\t\t\tblocksToSync[ blocksToSync.length - right - 1 ],\n\t\t\tyblocks.get( yblocks.length - right - 1 )\n\t\t);\n\t\tright++\n\t) {\n\t\t/* nop */\n\t}\n\n\tconst numOfUpdatesNeeded = numOfCommonEntries - left - right;\n\tconst numOfInsertionsNeeded = Math.max(\n\t\t0,\n\t\tblocksToSync.length - yblocks.length\n\t);\n\tconst numOfDeletionsNeeded = Math.max(\n\t\t0,\n\t\tyblocks.length - blocksToSync.length\n\t);\n\n\t// updates\n\tfor ( let i = 0; i < numOfUpdatesNeeded; i++, left++ ) {\n\t\tconst block = blocksToSync[ left ];\n\t\tconst yblock = yblocks.get( left );\n\t\tObject.entries( block ).forEach( ( [ key, value ] ) => {\n\t\t\tswitch ( key ) {\n\t\t\t\tcase 'attributes': {\n\t\t\t\t\tconst currentAttributes = yblock.get( key );\n\n\t\t\t\t\t// If attributes are not set on the yblock, use the new values.\n\t\t\t\t\tif ( ! currentAttributes ) {\n\t\t\t\t\t\tyblock.set(\n\t\t\t\t\t\t\tkey,\n\t\t\t\t\t\t\tcreateNewYAttributeMap( block.name, value )\n\t\t\t\t\t\t);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tObject.entries( value ).forEach(\n\t\t\t\t\t\t( [ attributeName, attributeValue ] ) => {\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\tfastDeepEqual(\n\t\t\t\t\t\t\t\t\tcurrentAttributes?.get( attributeName ),\n\t\t\t\t\t\t\t\t\tattributeValue\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tconst currentAttribute =\n\t\t\t\t\t\t\t\tcurrentAttributes.get( attributeName );\n\t\t\t\t\t\t\tconst isRichText = isRichTextAttribute(\n\t\t\t\t\t\t\t\tblock.name,\n\t\t\t\t\t\t\t\tattributeName\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\tisRichText &&\n\t\t\t\t\t\t\t\t'string' === typeof attributeValue &&\n\t\t\t\t\t\t\t\tcurrentAttributes.has( attributeName ) &&\n\t\t\t\t\t\t\t\tcurrentAttribute instanceof Y.Text\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t// Rich text values are stored as persistent Y.Text instances.\n\t\t\t\t\t\t\t\t// Update the value with a delta in place.\n\t\t\t\t\t\t\t\tmergeRichTextUpdate(\n\t\t\t\t\t\t\t\t\tcurrentAttribute,\n\t\t\t\t\t\t\t\t\tattributeValue,\n\t\t\t\t\t\t\t\t\tcursorPosition\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tcurrentAttributes.set(\n\t\t\t\t\t\t\t\t\tattributeName,\n\t\t\t\t\t\t\t\t\tcreateNewYAttributeValue(\n\t\t\t\t\t\t\t\t\t\tblock.name,\n\t\t\t\t\t\t\t\t\t\tattributeName,\n\t\t\t\t\t\t\t\t\t\tattributeValue\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\n\t\t\t\t\t// Delete any attributes that are no longer present.\n\t\t\t\t\tcurrentAttributes.forEach(\n\t\t\t\t\t\t( _attrValue: unknown, attrName: string ) => {\n\t\t\t\t\t\t\tif ( ! value.hasOwnProperty( attrName ) ) {\n\t\t\t\t\t\t\t\tcurrentAttributes.delete( attrName );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase 'innerBlocks': {\n\t\t\t\t\t// Recursively merge innerBlocks\n\t\t\t\t\tlet yInnerBlocks = yblock.get( key );\n\n\t\t\t\t\tif ( ! ( yInnerBlocks instanceof Y.Array ) ) {\n\t\t\t\t\t\tyInnerBlocks = new Y.Array< YBlock >();\n\t\t\t\t\t\tyblock.set( key, yInnerBlocks );\n\t\t\t\t\t}\n\n\t\t\t\t\tmergeCrdtBlocks(\n\t\t\t\t\t\tyInnerBlocks,\n\t\t\t\t\t\tvalue ?? [],\n\t\t\t\t\t\tcursorPosition\n\t\t\t\t\t);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tdefault:\n\t\t\t\t\tif ( ! fastDeepEqual( block[ key ], yblock.get( key ) ) ) {\n\t\t\t\t\t\tyblock.set( key, value );\n\t\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t\tyblock.forEach( ( _v, k ) => {\n\t\t\tif ( ! block.hasOwnProperty( k ) ) {\n\t\t\t\tyblock.delete( k );\n\t\t\t}\n\t\t} );\n\t}\n\n\t// deletes\n\tyblocks.delete( left, numOfDeletionsNeeded );\n\n\t// inserts\n\tfor ( let i = 0; i < numOfInsertionsNeeded; i++, left++ ) {\n\t\tconst newBlock = [ createNewYBlock( blocksToSync[ left ] ) ];\n\n\t\tyblocks.insert( left, newBlock );\n\t}\n\n\t// remove duplicate clientids\n\tconst knownClientIds = new Set< string >();\n\tfor ( let j = 0; j < yblocks.length; j++ ) {\n\t\tconst yblock: YBlock = yblocks.get( j );\n\n\t\tlet clientId = yblock.get( 'clientId' );\n\n\t\tif ( ! clientId ) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif ( knownClientIds.has( clientId ) ) {\n\t\t\tclientId = uuidv4();\n\t\t\tyblock.set( 'clientId', clientId );\n\t\t}\n\t\tknownClientIds.add( clientId );\n\t}\n}\n\n/**\n * Determine if a block should be synced.\n *\n * Ex: A gallery block should not be synced until the images have been\n * uploaded to WordPress, and their url is available. Before that,\n * it's not possible to access the blobs on a client as those are\n * local.\n *\n * @param block The block to check.\n * @return True if the block should be synced, false otherwise.\n */\nfunction shouldBlockBeSynced( block: Block ): boolean {\n\t// Verify that the gallery block is ready to be synced.\n\t// This means that, all images have had their blobs converted to full URLs.\n\t// Checking for only the blobs ensures that blocks that have just been inserted work as well.\n\tif ( 'core/gallery' === block.name ) {\n\t\treturn ! block.innerBlocks.some(\n\t\t\t( innerBlock ) =>\n\t\t\t\tinnerBlock.attributes && innerBlock.attributes.blob\n\t\t);\n\t}\n\n\t// Allow all other blocks to be synced.\n\treturn true;\n}\n\n// Cache rich-text attributes for all block types.\nlet cachedRichTextAttributes: Map< string, Map< string, true > >;\n\n/**\n * Given a block name and attribute key, return true if the attribute is rich-text typed.\n *\n * @param blockName The name of the block, e.g. 'core/paragraph'.\n * @param attributeName The name of the attribute to check, e.g. 'content'.\n * @return True if the attribute is rich-text typed, false otherwise.\n */\nfunction isRichTextAttribute(\n\tblockName: string,\n\tattributeName: string\n): boolean {\n\tif ( ! cachedRichTextAttributes ) {\n\t\t// Parse the attributes for all blocks once.\n\t\tcachedRichTextAttributes = new Map< string, Map< string, true > >();\n\n\t\tfor ( const blockType of getBlockTypes() as BlockType[] ) {\n\t\t\tconst richTextAttributeMap = new Map< string, true >();\n\n\t\t\tfor ( const [ name, definition ] of Object.entries(\n\t\t\t\tblockType.attributes ?? {}\n\t\t\t) ) {\n\t\t\t\tif ( 'rich-text' === definition.type ) {\n\t\t\t\t\trichTextAttributeMap.set( name, true );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tcachedRichTextAttributes.set(\n\t\t\t\tblockType.name,\n\t\t\t\trichTextAttributeMap\n\t\t\t);\n\t\t}\n\t}\n\n\treturn (\n\t\tcachedRichTextAttributes.get( blockName )?.has( attributeName ) ?? false\n\t);\n}\n\nlet localDoc: Y.Doc;\n\n/**\n * Given a Y.Text object and an updated string value, diff the new value and\n * apply the delta to the Y.Text.\n *\n * @param blockYText The Y.Text to update.\n * @param updatedValue The updated value.\n * @param cursorPosition The position of the cursor after the change occurs.\n */\nfunction mergeRichTextUpdate(\n\tblockYText: Y.Text,\n\tupdatedValue: string,\n\tcursorPosition: number | null\n): void {\n\t// Gutenberg does not use Yjs shared types natively, so we can only subscribe\n\t// to changes from store and apply them to Yjs types that we create and\n\t// manage. Crucially, for rich-text attributes, we do not receive granular\n\t// string updates; we get the new full string value on each change, even when\n\t// only a single character changed.\n\t//\n\t// The code below allows us to compute a delta between the current and new\n\t// value, then apply it to the Y.Text.\n\n\tif ( ! localDoc ) {\n\t\t// Y.Text must be attached to a Y.Doc to be able to do operations on it.\n\t\t// Create a temporary Y.Text attached to a local Y.Doc for delta computation.\n\t\tlocalDoc = new Y.Doc();\n\t}\n\n\tconst localYText = localDoc.getText( 'temporary-text' );\n\tlocalYText.delete( 0, localYText.length );\n\tlocalYText.insert( 0, updatedValue );\n\n\tconst currentValueAsDelta = new Delta( blockYText.toDelta() );\n\tconst updatedValueAsDelta = new Delta( localYText.toDelta() );\n\tconst deltaDiff = currentValueAsDelta.diffWithCursor(\n\t\tupdatedValueAsDelta,\n\t\tcursorPosition\n\t);\n\n\tblockYText.applyDelta( deltaDiff.ops );\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["fastDeepEqual", "uuidv4"]
|
|
7
7
|
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// packages/core-data/src/utils/crdt-utils.ts
|
|
21
|
+
var crdt_utils_exports = {};
|
|
22
|
+
__export(crdt_utils_exports, {
|
|
23
|
+
createYMap: () => createYMap,
|
|
24
|
+
getRootMap: () => getRootMap,
|
|
25
|
+
isYMap: () => isYMap
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(crdt_utils_exports);
|
|
28
|
+
var import_sync = require("@wordpress/sync");
|
|
29
|
+
function getRootMap(doc, key) {
|
|
30
|
+
return doc.getMap(key);
|
|
31
|
+
}
|
|
32
|
+
function createYMap(partial = {}) {
|
|
33
|
+
return new import_sync.Y.Map(Object.entries(partial));
|
|
34
|
+
}
|
|
35
|
+
function isYMap(value) {
|
|
36
|
+
return value instanceof import_sync.Y.Map;
|
|
37
|
+
}
|
|
38
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
39
|
+
0 && (module.exports = {
|
|
40
|
+
createYMap,
|
|
41
|
+
getRootMap,
|
|
42
|
+
isYMap
|
|
43
|
+
});
|
|
44
|
+
//# sourceMappingURL=crdt-utils.cjs.map
|