(
stationId: Principal,
opts: { redirectIfIncompatible?: boolean } = {},
)
| 132 | fetchCompatFile: (versionPath?: string) => fetchCompatFile(versionPath), |
| 133 | fetchStationApiVersion: (stationId: Principal) => fetchCanisterVersion(agent, stationId), |
| 134 | async checkCompatibility( |
| 135 | stationId: Principal, |
| 136 | opts: { redirectIfIncompatible?: boolean } = {}, |
| 137 | ): Promise<URL | undefined | false> { |
| 138 | const url = new URL(window.location.href); |
| 139 | const pathParts = url.pathname.split('/').filter(Boolean); // Remove empty strings |
| 140 | const requestedVersion = isSemanticVersion(pathParts?.[0] ?? '', 'v') |
| 141 | ? pathParts[0] |
| 142 | : undefined; |
| 143 | |
| 144 | const [stationApiVersion, compat, rootCompat] = requestedVersion |
| 145 | ? await Promise.all([ |
| 146 | this.fetchStationApiVersion(stationId), |
| 147 | this.fetchCompatFile(requestedVersion), |
| 148 | // Also fetch the root compatibility file to get the latest supported version of the UI. |
| 149 | this.fetchCompatFile(), |
| 150 | ]) |
| 151 | : await Promise.all([this.fetchStationApiVersion(stationId), this.fetchCompatFile(), null]); |
| 152 | |
| 153 | const currentLoadedUIVersion = getCurrentlyLoadedUIVersion(); |
| 154 | |
| 155 | // If the requested version is the latest version supported by the UI, then the user gets redirected to |
| 156 | // the unversioned path, the same applies if the user is already in the versioned path but the ui build version |
| 157 | // differs, which shows that the index.html loaded is not the correct one. |
| 158 | if ( |
| 159 | requestedVersion && |
| 160 | (rootCompat?.api.latest === stationApiVersion || |
| 161 | currentLoadedUIVersion !== requestedVersion.slice(1)) |
| 162 | ) { |
| 163 | const parts = pathParts.filter(part => !isSemanticVersion(part, 'v')); |
| 164 | url.pathname = '/' + parts.join('/'); |
| 165 | |
| 166 | if (opts.redirectIfIncompatible) { |
| 167 | this.redirectToURL(url); |
| 168 | } |
| 169 | |
| 170 | return url; |
| 171 | } |
| 172 | |
| 173 | // If the latest version of the API supported by the ui is the same as the |
| 174 | // station API version, then it is compatible. |
| 175 | if (compat.api.latest === stationApiVersion) { |
| 176 | return; |
| 177 | } |
| 178 | |
| 179 | const compatibility = compat.api.compatibility; |
| 180 | |
| 181 | const stationApiSemver = SemanticVersion.parse(stationApiVersion); |
| 182 | const latestCompatApiSemver = SemanticVersion.parse(compat.api.latest); |
| 183 | |
| 184 | // If the station API version is newer than the latest supported version, then we treat it as incompatible |
| 185 | // and redirect to the unversioned path to avoid breaking the UI. It will also get redirected |
| 186 | // if the compatibility file does not have the station API version. |
| 187 | if ( |
| 188 | stationApiSemver.isGreaterThan(latestCompatApiSemver) || |
| 189 | !compatibility?.[stationApiVersion]?.ui || |
| 190 | compatibility[stationApiVersion].ui.length === 0 |
| 191 | ) { |
nothing calls this directly
no test coverage detected