@@ -11,8 +11,16 @@ import { getAppInfo } from '../delegatee/get-app-info';
1111 * If they match, it will return the existing appVersion without registering a new one.
1212 *
1313 * @param abilityIpfsCids - Array of ability IPFS CIDs to register
14- * @param abilityPolicies - Array of policy IPFS CIDs for each ability
14+ * @param abilityPolicies - Array of policy IPFS CIDs for each ability (must be parallel to abilityIpfsCids)
1515 * @param registerNewVersionOverride - Whether to register a new version even if the latest version already has the same abilities and policies
16+ *
17+ * @remarks
18+ * Assumptions:
19+ * - `abilityIpfsCids` and `abilityPolicies` are parallel arrays where `abilityPolicies[i]` contains
20+ * the policy CIDs for the ability at `abilityIpfsCids[i]`
21+ * - The comparison is order-independent for both abilities and policies within each ability
22+ * - Two app versions are considered equivalent if they have the same set of abilities (regardless of order)
23+ * and each ability has the same set of policies (regardless of order)
1624 */
1725export async function registerNewAppVersion ( {
1826 abilityIpfsCids,
@@ -45,34 +53,39 @@ export async function registerNewAppVersion({
4553 } ) ;
4654
4755 if ( existingAppVersion ) {
48- // Extract existing abilities and policies
49- const existingAbilityIpfsCids = existingAppVersion . appVersion . abilities . map (
50- ( ability ) => ability . abilityIpfsCid ,
51- ) ;
52- const existingAbilityPolicies = existingAppVersion . appVersion . abilities . map (
53- ( ability ) => ability . policyIpfsCids ,
54- ) ;
55-
56- // Compare arrays (order matters for abilities and policies)
57- const abilitiesMatch =
58- existingAbilityIpfsCids . length === abilityIpfsCids . length &&
59- existingAbilityIpfsCids . every ( ( cid , index ) => cid === abilityIpfsCids [ index ] ) ;
60-
61- const policiesMatch =
62- existingAbilityPolicies . length === abilityPolicies . length &&
63- existingAbilityPolicies . every ( ( policies , index ) => {
56+ // Create a map from ability CID to its policies for easy lookup
57+ const existingAbilityMap = new Map < string , string [ ] > ( ) ;
58+ existingAppVersion . appVersion . abilities . forEach ( ( ability ) => {
59+ existingAbilityMap . set ( ability . abilityIpfsCid , ability . policyIpfsCids ) ;
60+ } ) ;
61+
62+ // Check if we have the same number of abilities
63+ if ( existingAbilityMap . size !== abilityIpfsCids . length ) {
64+ // Different number of abilities, need to register new version; fall through to register new version
65+ } else {
66+ // For each ability in the new version, check if it exists with the same policies
67+ const allMatch = abilityIpfsCids . every ( ( abilityId , index ) => {
68+ const existingPolicies = existingAbilityMap . get ( abilityId ) ;
69+ if ( ! existingPolicies ) return false ; // Ability doesn't exist in current version
70+
6471 const newPolicies = abilityPolicies [ index ] ;
65- return (
66- policies . length === newPolicies . length &&
67- policies . every ( ( policy , policyIndex ) => policy === newPolicies [ policyIndex ] )
68- ) ;
72+ if ( ! newPolicies ) return false ; // Handle undefined policies
73+
74+ // Compare policy arrays (order-independent)
75+ if ( existingPolicies . length !== newPolicies . length ) return false ;
76+
77+ const sortedExisting = [ ...existingPolicies ] . sort ( ) ;
78+ const sortedNew = [ ...newPolicies ] . sort ( ) ;
79+
80+ return sortedExisting . every ( ( policy , i ) => policy === sortedNew [ i ] ) ;
6981 } ) ;
7082
71- if ( abilitiesMatch && policiesMatch ) {
72- console . log (
73- `App version ${ latestVersion } already has the same abilities and policies. Skipping registration.` ,
74- ) ;
75- return { appId, appVersion : latestVersion } ;
83+ if ( allMatch ) {
84+ console . log (
85+ `App version ${ latestVersion } already has the same abilities and policies. Skipping registration.` ,
86+ ) ;
87+ return { appId, appVersion : latestVersion } ;
88+ }
7689 }
7790 }
7891 }
0 commit comments