functionsOutOfSyncProvider top-level property
final
Whether the Edge Function bundle deployed to the user's Supabase project is out of sync with the one the app currently ships.
Reads both _schema_meta.version and _schema_meta.functions_hash in
two sequential PostgREST calls (the second of which is guarded by the
version check, so we never hit the column-missing error on legacy
instances). Invalidate this provider after a successful redeploy in the
Settings banner so the banner disappears without a sign-out/sign-in.
Implementation
final functionsOutOfSyncProvider = FutureProvider<bool>((ref) async {
// Re-run when the Supabase auth state changes.
ref.watch(authStateProvider);
final client = Supabase.instance.client;
if (client.auth.currentUser == null) return false;
try {
final versionRow = await client
.from('_schema_meta')
.select('version')
.maybeSingle();
if (versionRow == null) return false;
final version = versionRow['version'];
final schemaVersion = version is int ? version : null;
if (schemaVersion == null || schemaVersion < _functionsHashMinVersion) {
// Pre-migration-059 schema. Wait for the incremental migration to
// add the column before we start nagging; otherwise the banner would
// open a dialog that hits 42703 on the hash write.
return false;
}
final hashRow = await client
.from('_schema_meta')
.select('functions_hash')
.maybeSingle();
final deployedHash = hashRow?['functions_hash'] as String?;
return functionsOutOfSyncFromMeta(
schemaVersion: schemaVersion,
deployedHash: deployedHash,
bundledHash: functionsBundleHash,
);
} on PostgrestException catch (e) {
// Table missing (42P01), column missing (42703), or schema cache miss
// (PGRST205): fall through to "no banner". Incremental migration will
// eventually catch them up, at which point the provider will re-run
// and the banner will appear.
if (e.code == '42P01' || e.code == '42703' || e.code == 'PGRST205') {
return false;
}
// Fail quiet on anything else — the banner is a nice-to-have, not a
// blocker for Settings rendering.
return false;
} catch (_) {
return false;
}
});