diff --git a/apps/picsa-apps/dashboard/src/app/modules/climate/climate-api.mapping.ts b/apps/picsa-apps/dashboard/src/app/modules/climate/climate-api.mapping.ts index 7105b3e1..560c779d 100644 --- a/apps/picsa-apps/dashboard/src/app/modules/climate/climate-api.mapping.ts +++ b/apps/picsa-apps/dashboard/src/app/modules/climate/climate-api.mapping.ts @@ -116,7 +116,7 @@ export const ApiMapping = ( // TODO - handle error if filename already exists const { error: dbError } = await supabaseService.db - .table('climate_forecasts') + .table('forecasts') .update({ storage_file: fullPath }) .eq('id', row.id); if (dbError) { diff --git a/apps/picsa-apps/dashboard/src/app/modules/climate/pages/forecast/forecast.component.ts b/apps/picsa-apps/dashboard/src/app/modules/climate/pages/forecast/forecast.component.ts index c11faa0b..8fba1bc9 100644 --- a/apps/picsa-apps/dashboard/src/app/modules/climate/pages/forecast/forecast.component.ts +++ b/apps/picsa-apps/dashboard/src/app/modules/climate/pages/forecast/forecast.component.ts @@ -2,9 +2,11 @@ import { CommonModule } from '@angular/common'; import { ChangeDetectionStrategy, Component, computed, effect, signal } from '@angular/core'; import { RouterModule } from '@angular/router'; import { RefreshSpinnerComponent } from '@picsa/components'; +import { FunctionResponses } from '@picsa/server-types'; import { IDataTableOptions, PicsaDataTableComponent } from '@picsa/shared/features'; import { PicsaNotificationService } from '@picsa/shared/services/core/notification.service'; import { SupabaseService } from '@picsa/shared/services/core/supabase'; +import { FunctionsHttpError } from '@supabase/supabase-js'; import { DashboardMaterialModule } from '../../../../material.module'; import { DeploymentDashboardService } from '../../../deployment/deployment.service'; @@ -16,6 +18,8 @@ interface IForecastTableRow extends IForecastRow { file_name: string; } +type IForecastDBAPIResponse = { data: FunctionResponses['Dashboard']['forecast-db']; error?: any }; + const DISPLAY_COLUMNS: (keyof IForecastTableRow)[] = [ 'country_code', 'forecast_type', @@ -61,7 +65,7 @@ export class ClimateForecastPageComponent { public activeDownloads = signal>({}); private get db() { - return this.supabase.db.table('climate_forecasts'); + return this.supabase.db.table('forecasts'); } constructor( @@ -116,29 +120,31 @@ export class ClimateForecastPageComponent { /** Invoke backend function that fetches forecasts from climate api and updates db */ private async refreshAPIData() { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const { country_code } = this.deploymentService.activeDeployment()!; - const formData = new FormData(); - formData.append('country_code', country_code); - formData.append('query_prefix', this.apiQueryPrefix()); - const { data, error } = await this.supabase.functions - .invoke('dashboard/climate-forecast-update', { - method: 'POST', - body: formData, - }) - .catch((error) => ({ data: [], error })); - if (error) { - console.error(error); + const country_code = this.countryCode() as string; + const query_prefix = this.apiQueryPrefix(); + + const { data, error } = await this.supabase.functions.invoke('dashboard/forecast-db', { + method: 'POST', + body: { country_code, query_prefix }, + }); + + // Errors thrown from functions in JS client need to wait for message + // https://github.com/supabase/functions-js/issues/45 + if (error && error instanceof FunctionsHttpError) { + const errorMessage = await error.context.json(); + console.error('refreshAPIData', JSON.parse(errorMessage)); this.notificationService.showErrorNotification('Forecast Update Failed. See console logs for details'); return []; } - if (data.length > 0) { - this.forecastData.update((v) => ([] as IForecastTableRow[]).concat(this.toTableData(data), v)); - } - console.log('[Api Data Updated]', data); - return data; + const forecasts = data?.[country_code] || []; + + this.forecastData.update((v) => ([] as IForecastTableRow[]).concat(this.toTableData(forecasts), v)); + console.log('[Api Data Updated]', { country_code, data, forecasts }); + + return forecasts; } - private toTableData(data: IForecastRow[]): IForecastTableRow[] { + private toTableData(data: IForecastRow[] = []): IForecastTableRow[] { return data .map((el) => { // compute file_name column from storage file path diff --git a/apps/picsa-apps/dashboard/src/app/modules/climate/types/db.d.ts b/apps/picsa-apps/dashboard/src/app/modules/climate/types/db.d.ts index 2b5a758d..f2b75ac8 100644 --- a/apps/picsa-apps/dashboard/src/app/modules/climate/types/db.d.ts +++ b/apps/picsa-apps/dashboard/src/app/modules/climate/types/db.d.ts @@ -10,9 +10,9 @@ export type IClimateSummaryRainfallRow = Database['public']['Tables']['climate_s }; export type IClimateSummaryRainfallInsert = Database['public']['Tables']['climate_summary_rainfall']['Insert']; -export type IForecastRow = Database['public']['Tables']['climate_forecasts']['Row']; -export type IForecastInsert = Database['public']['Tables']['climate_forecasts']['Insert']; -export type IForecastUpdate = Database['public']['Tables']['climate_forecasts']['Update']; +export type IForecastRow = Database['public']['Tables']['forecasts']['Row']; +export type IForecastInsert = Database['public']['Tables']['forecasts']['Insert']; +export type IForecastUpdate = Database['public']['Tables']['forecasts']['Update']; export type IStationRow = Database['public']['Tables']['climate_stations']['Row']; export type IStationInsert = Database['public']['Tables']['climate_stations']['Insert']; diff --git a/apps/picsa-server/project.json b/apps/picsa-server/project.json index 3ef36ecf..a96cb9e7 100644 --- a/apps/picsa-server/project.json +++ b/apps/picsa-server/project.json @@ -46,7 +46,7 @@ "dependsOn": [], "outputs": [], "options": { - "commands": ["npx supabase gen types typescript --local > supabase/types/index.ts"], + "commands": ["npx supabase gen types typescript --local > supabase/types/db.types.ts"], "cwd": "apps/picsa-server" } }, diff --git a/apps/picsa-server/supabase/functions/_shared/request.ts b/apps/picsa-server/supabase/functions/_shared/request.ts index a4bc5247..46d2cc36 100644 --- a/apps/picsa-server/supabase/functions/_shared/request.ts +++ b/apps/picsa-server/supabase/functions/_shared/request.ts @@ -9,11 +9,11 @@ export const getFormData = async (req: Request): Promise
=> { return { fields: {}, files: {} }; }; -export const getJsonData = async (req: Request): Promise> => { +export const getJsonData = async >(req: Request): Promise => { if (req.headers.has('content-type') && req.headers.get('content-type')?.startsWith('application/json')) { const json = await req.json(); - return json; + return json as T; } console.error('Request does not contain json body'); - return {}; + return {} as T; }; diff --git a/apps/picsa-server/supabase/functions/_shared/response.ts b/apps/picsa-server/supabase/functions/_shared/response.ts index bb2bcff4..29d74e30 100644 --- a/apps/picsa-server/supabase/functions/_shared/response.ts +++ b/apps/picsa-server/supabase/functions/_shared/response.ts @@ -1,7 +1,23 @@ import { corsHeaders } from './cors.ts'; -export function ErrorResponse(msg: string, status = 400) { - return new Response(JSON.stringify({ msg }), { +/** + * Return an erorr response + * + * Note - if reading from js-client need to await error context body for message + * https://github.com/supabase/functions-js/issues/45 + * + * @example + * ```ts + * const {dat, error} = await invokeFunction(...) + * if (error && error instanceof FunctionsHttpError) { + * const errorMessage = await error.context.json(); + * const errorJson = JSON.parse(errorMessage) + * console.error(errorJson) + * } + * ``` + */ +export function ErrorResponse(msg: any, status = 400) { + return new Response(JSON.stringify(msg), { status, headers: { ...corsHeaders, 'Content-Type': 'application/json' }, }); diff --git a/apps/picsa-server/supabase/functions/dashboard/climate-forecast-update.ts b/apps/picsa-server/supabase/functions/dashboard/forecast-db.ts similarity index 71% rename from apps/picsa-server/supabase/functions/dashboard/climate-forecast-update.ts rename to apps/picsa-server/supabase/functions/dashboard/forecast-db.ts index 0b93b4ce..38691bc5 100644 --- a/apps/picsa-server/supabase/functions/dashboard/climate-forecast-update.ts +++ b/apps/picsa-server/supabase/functions/dashboard/forecast-db.ts @@ -1,12 +1,15 @@ -import type { Database } from '../../types/index.ts'; -import type { - paths as climateApiPaths, - components as climateApiComponents, -} from '../../../../picsa-apps/dashboard/src/app/modules/climate/types/api.d.ts'; import { getClient } from '../_shared/client.ts'; import { getJsonData } from '../_shared/request.ts'; +import { ErrorResponse } from '../_shared/response.ts'; import { JSONResponse } from '../_shared/response.ts'; +import type { + climateApiPaths, + IApiClimateForecast, + IDBClimateForecastInsert, + IForecastDBAPIResponse, +} from './types.ts'; + /** * Read the endpoint from env. Note, if running climate api in local docker container update `.env` to: * ```env @@ -14,40 +17,43 @@ import { JSONResponse } from '../_shared/response.ts'; * ``` * https://github.com/orgs/supabase/discussions/9837 */ -const CLIMATE_API_ENDPOINT = Deno.env.get('CLIMATE_API_ENDPOINT') || 'https://api.epicsa.idems.international'; -const COUNTRY_CODES = ['mw', 'zm']; +export const CLIMATE_API_ENDPOINT = Deno.env.get('CLIMATE_API_ENDPOINT') || 'https://api.epicsa.idems.international'; +export const ALL_COUNTRY_CODES = ['mw', 'zm']; // Create typed fetch client from open-api definition exported by climate api import createClient from 'openapi-fetch'; -const apiClient = createClient({ baseUrl: CLIMATE_API_ENDPOINT, mode: 'cors' }); - -type IDBClimateForecast = Database['public']['Tables']['climate_forecasts']['Insert']; -type IApiClimateForecast = climateApiComponents['schemas']['DocumentMetadata']; +export const apiClient = createClient({ baseUrl: CLIMATE_API_ENDPOINT, mode: 'cors' }); /** - * Update + * Update cliamte forecast db rows */ -export const climateForecastUpdate = async (req: Request) => { - // Validate body formData +export const forecastDB = async (req: Request) => { // TODO - Improve validators and feedback - let { country_codes = COUNTRY_CODES, query_prefix } = await getJsonData(req); + let { country_code, query_prefix } = await getJsonData(req); + + // Retrieve single country if specified, default all + const country_codes = country_code ? [country_code] : ALL_COUNTRY_CODES; // Default query for documents stored in the current month, if (!query_prefix) { query_prefix = new Date().toISOString().replace(/-/, '').substring(0, 6); } - const responses = []; + const response: IForecastDBAPIResponse = {}; + const errors = []; for (const country_code of country_codes) { try { const data = await getCountryUpdates(country_code, query_prefix); - responses.push({ country_code, data }); + response[country_code] = data; } catch (error) { - responses.push({ country_code, error }); + errors.push(error); } } - return JSONResponse(responses); + if (errors.length > 0) { + return ErrorResponse(errors); + } + return JSONResponse(response); }; async function getCountryUpdates(country_code: string, query_prefix: string) { @@ -65,7 +71,7 @@ async function getCountryUpdates(country_code: string, query_prefix: string) { // map api forecasts to db format and update db const updates = mapApiForecastToDb(newForecasts, country_code); const supabaseClient = getClient(); - const { error } = await supabaseClient.from('climate_forecasts').insert(updates); + const { error } = await supabaseClient.from('forecasts').insert(updates); if (error) { throw error; } @@ -88,7 +94,7 @@ async function getDBForecasts(query: { country_code: string; query_prefix: strin const { country_code, query_prefix } = query; console.log('db query', query_prefix, country_code); const { data, error } = await supabaseClient - .from('climate_forecasts') + .from('forecasts') .select('*') .like('id', `${query_prefix}%`) .eq('country_code', country_code) @@ -100,7 +106,7 @@ async function getDBForecasts(query: { country_code: string; query_prefix: strin return data; } -function mapApiForecastToDb(apiForecasts: IApiClimateForecast[], country_code: string): IDBClimateForecast[] { +function mapApiForecastToDb(apiForecasts: IApiClimateForecast[], country_code: string): IDBClimateForecastInsert[] { return apiForecasts.map((v) => ({ country_code, id: v.name, diff --git a/apps/picsa-server/supabase/functions/dashboard/forecast-storage.ts b/apps/picsa-server/supabase/functions/dashboard/forecast-storage.ts new file mode 100644 index 00000000..187b2434 --- /dev/null +++ b/apps/picsa-server/supabase/functions/dashboard/forecast-storage.ts @@ -0,0 +1,100 @@ +import { getClient } from '../_shared/client.ts'; +import { getJsonData } from '../_shared/request.ts'; +import { JSONResponse } from '../_shared/response.ts'; +import { apiClient } from './forecast-db.ts'; +import { IDBClimateForecastRow } from './types.ts'; + +interface IReqParams { + /** + * Max number of documents to retrieve. As requests are run in parallel smaller number + * reduces server workload. Default 5 + */ + limit?: number; +} + +/** + * Handle downloading forecast files from api and populating to supabase storage entry + * Checks DB for any entries without storage files and attempts to update + */ +export const forecastStorage = async (req: Request) => { + // ensure api up and running before sending batched requests + await apiClient.GET('/v1/status/'); + const params = await getJsonData(req); + const res = await new ForecastStorageUpdate().populateStorageFiles(params); + return JSONResponse(res); +}; + +class ForecastStorageUpdate { + supabaseClient = getClient(); + + private get table() { + return this.supabaseClient.from('forecasts'); + } + + async populateStorageFiles(params: IReqParams) { + const { limit = 5 } = params; + const pending = await this.listPendingFiles(limit); + + const updates: IDBClimateForecastRow[] = []; + const errors: any[] = []; + // TODO - make parallel and allow failure + for (const { country_code, id } of pending) { + const { data, error } = await this.storeForecast(country_code, id); + if (error) { + errors.push(error); + } + if (data) { + updates.push(data); + } + } + return { data: updates, error: errors }; + } + + /** Check all climate forecast db entries for any that are missing corresponding storage files */ + private async listPendingFiles(limit = 5) { + const query = this.table.select('*').is('storage_file', null).order('id', { ascending: false }).limit(limit); + const { data, error } = await query; + if (error) { + throw error; + } + return data; + } + + /** Retrieve forecast data from API, store to supabase storage and update DB */ + private async storeForecast( + country_code: string, + id: string + ): Promise<{ data?: IDBClimateForecastRow; error?: any }> { + const supabaseClient = getClient(); + // download from api + const req = apiClient.GET('/v1/documents/{country}/{filepath}', { + params: { path: { country: country_code as any, filepath: id } }, + parseAs: 'blob', + }); + const { data: fileData, response: apiResponse, error: apiError } = await req; + if (apiError) { + return { error: apiError }; + } + if (fileData) { + // upload to supabase storage + const contentType = apiResponse.headers.get('content-type') as string; + const { data: uploadData, error: uploadError } = await supabaseClient.storage + .from(country_code) + .upload(`climate/forecasts/${id}`, fileData, { contentType, upsert: true }); + if (uploadError) { + return { error: uploadError }; + } + // update db entry + const { data: updateData, error: updateError } = await this.updateForecastDBStorageEntry(id, uploadData.fullPath); + if (updateError) { + return { error: updateError }; + } + return { data: updateData?.[0] }; + } + return { error: `No filedata found for ${id}` }; + } + + private updateForecastDBStorageEntry(id: string, storage_file: string) { + return this.table.update({ storage_file }).eq('id', id).select(); + } +} diff --git a/apps/picsa-server/supabase/functions/dashboard/index.ts b/apps/picsa-server/supabase/functions/dashboard/index.ts index a321407f..eb337ca2 100644 --- a/apps/picsa-server/supabase/functions/dashboard/index.ts +++ b/apps/picsa-server/supabase/functions/dashboard/index.ts @@ -3,7 +3,8 @@ // This enables autocomplete, go to definition, etc. import { serve } from 'https://deno.land/std@0.168.0/http/server.ts'; -import { climateForecastUpdate } from './climate-forecast-update.ts'; +import { forecastStorage } from './forecast-storage.ts'; +import { forecastDB } from './forecast-db.ts'; import { corsHeaders } from '../_shared/cors.ts'; serve((req) => { @@ -18,8 +19,10 @@ serve((req) => { const endpoint = req.url.split('/').pop(); switch (endpoint) { - case 'climate-forecast-update': - return climateForecastUpdate(req); + case 'forecast-db': + return forecastDB(req); + case 'forecast-storage': + return forecastStorage(req); default: return new Response(`Invalid endpoint: ${endpoint}`, { diff --git a/apps/picsa-server/supabase/functions/dashboard/types.ts b/apps/picsa-server/supabase/functions/dashboard/types.ts new file mode 100644 index 00000000..860d41c0 --- /dev/null +++ b/apps/picsa-server/supabase/functions/dashboard/types.ts @@ -0,0 +1,16 @@ +import type { Database } from '../../types/db.types.ts'; +import type { paths, components } from '../../../../picsa-apps/dashboard/src/app/modules/climate/types/api.d.ts'; + +export type climateApiPaths = paths; +export type climateApiComponents = components; + +export type IDBClimateForecastRow = Database['public']['Tables']['forecasts']['Row']; +export type IDBClimateForecastInsert = Database['public']['Tables']['forecasts']['Insert']; + +export type IApiClimateForecast = climateApiComponents['schemas']['DocumentMetadata']; + +/********* Api Responses ************/ + +export type IForecastDBAPIResponse = { + [country_code: string]: IDBClimateForecastInsert[]; +}; diff --git a/apps/picsa-server/supabase/migrations/20250115161100_climate_forecasts_update.sql b/apps/picsa-server/supabase/migrations/20250115161100_forecasts_update.sql similarity index 73% rename from apps/picsa-server/supabase/migrations/20250115161100_climate_forecasts_update.sql rename to apps/picsa-server/supabase/migrations/20250115161100_forecasts_update.sql index 9bcec4c0..86b2cfe2 100644 --- a/apps/picsa-server/supabase/migrations/20250115161100_climate_forecasts_update.sql +++ b/apps/picsa-server/supabase/migrations/20250115161100_forecasts_update.sql @@ -2,10 +2,10 @@ drop table if exists public.climate_forecasts; -- -- Custom types -create type public.forecast_type as enum ('daily','annual'); +create type public.forecast_type as enum ('daily','seasonal','downscaled'); create table - public.climate_forecasts ( + public.forecasts ( id character varying not null, created_at timestamp with time zone DEFAULT "now"() NOT NULL, updated_at timestamp with time zone DEFAULT "now"() NOT NULL, @@ -17,8 +17,8 @@ create table language_code text null, storage_file text null, mimetype text null, - constraint climate_forecasts_pkey primary key (id), - constraint climate_forecasts_storage_file_fkey foreign key (storage_file) references storage.objects (path) on delete cascade + constraint forecasts_pkey primary key (id), + constraint forecasts_storage_file_fkey foreign key (storage_file) references storage.objects (path) on delete cascade ) tablespace pg_default; @@ -27,5 +27,5 @@ create table CREATE EXTENSION IF NOT EXISTS "moddatetime" SCHEMA extensions; -- NOTE - required extensions - allow moddatetime -create trigger handle_updated_at before update on public.climate_forecasts +create trigger handle_updated_at before update on public.forecasts for each row execute procedure moddatetime (updated_at); \ No newline at end of file diff --git a/apps/picsa-server/supabase/migrations/20250127193000_forecast_update_cron.sql b/apps/picsa-server/supabase/migrations/20250127193000_forecast_update_cron.sql index 4b614c71..1d8350ff 100644 --- a/apps/picsa-server/supabase/migrations/20250127193000_forecast_update_cron.sql +++ b/apps/picsa-server/supabase/migrations/20250127193000_forecast_update_cron.sql @@ -1,18 +1,18 @@ --- enable pg_cron extension create extension if not exists pg_cron with schema pg_catalog; - grant usage on schema cron to postgres; grant all privileges on all tables in schema cron to postgres; -- Trigger backend edge function every 30 minutes -- Adapted from https://supabase.com/docs/guides/functions/schedule-functions -select cron.schedule('climate_forecasts_update', '30 * * * *', $$ select public.call_edge_function('dashboard/climate-forecast-update','{}'::jsonb); $$); +select cron.schedule('forecasts_db', '30 * * * *', $$ select public.call_edge_function('dashboard/forecast-db','{}'::jsonb); $$); + +select cron.schedule('forecasts_storage', '35 * * * *', $$ select public.call_edge_function('dashboard/forecast-storage','{}'::jsonb); $$); -- Alt implementation (intermediate function created to structure more complex requests, kept for future reference) --- create or replace function public.trigger_climate_forecast_update() +-- create or replace function public.trigger_forecast_update() -- returns void -- language plpgsql -- as $$ @@ -25,12 +25,9 @@ select cron.schedule('climate_forecasts_update', '30 * * * *', $$ select public. -- begin -- foreach country_code in array country_codes loop -- body = format('{"country_code": "%s"}',country_code)::jsonb; --- select (public.call_edge_function('dashboard/climate-forecast-update',body)) into request_id; +-- select (public.call_edge_function('dashboard/forecast-update',body)) into request_id; -- request_ids = request_ids || request_id; -- end loop; -- return 'request_ids'; --- end $$; - - - ^ +-- end $$; ^ diff --git a/apps/picsa-server/supabase/types/db.types.ts b/apps/picsa-server/supabase/types/db.types.ts new file mode 100644 index 00000000..0afaec5d --- /dev/null +++ b/apps/picsa-server/supabase/types/db.types.ts @@ -0,0 +1,1006 @@ +export type Json = string | number | boolean | null | { [key: string]: Json | undefined } | Json[]; + +export type Database = { + graphql_public: { + Tables: { + [_ in never]: never; + }; + Views: { + [_ in never]: never; + }; + Functions: { + graphql: { + Args: { + operationName?: string; + query?: string; + variables?: Json; + extensions?: Json; + }; + Returns: Json; + }; + }; + Enums: { + [_ in never]: never; + }; + CompositeTypes: { + [_ in never]: never; + }; + }; + public: { + Tables: { + climate_forecasts: { + Row: { + country_code: string | null; + date_modified: string; + district: string | null; + filename: string; + id: string; + language_code: string | null; + storage_file: string | null; + type: string | null; + }; + Insert: { + country_code?: string | null; + date_modified: string; + district?: string | null; + filename: string; + id: string; + language_code?: string | null; + storage_file?: string | null; + type?: string | null; + }; + Update: { + country_code?: string | null; + date_modified?: string; + district?: string | null; + filename?: string; + id?: string; + language_code?: string | null; + storage_file?: string | null; + type?: string | null; + }; + Relationships: [ + { + foreignKeyName: 'climate_forecasts_storage_file_fkey'; + columns: ['storage_file']; + isOneToOne: false; + referencedRelation: 'storage_objects'; + referencedColumns: ['id']; + } + ]; + }; + climate_stations: { + Row: { + country_code: string; + district: string | null; + elevation: number | null; + id: string | null; + latitude: number | null; + longitude: number | null; + station_id: string; + station_name: string | null; + }; + Insert: { + country_code: string; + district?: string | null; + elevation?: number | null; + id?: string | null; + latitude?: number | null; + longitude?: number | null; + station_id: string; + station_name?: string | null; + }; + Update: { + country_code?: string; + district?: string | null; + elevation?: number | null; + id?: string | null; + latitude?: number | null; + longitude?: number | null; + station_id?: string; + station_name?: string | null; + }; + Relationships: []; + }; + climate_summary_rainfall: { + Row: { + country_code: Database['public']['Enums']['country_code']; + created_at: string; + data: Json[]; + metadata: Json; + station_id: string; + updated_at: string; + }; + Insert: { + country_code: Database['public']['Enums']['country_code']; + created_at?: string; + data: Json[]; + metadata: Json; + station_id: string; + updated_at?: string; + }; + Update: { + country_code?: Database['public']['Enums']['country_code']; + created_at?: string; + data?: Json[]; + metadata?: Json; + station_id?: string; + updated_at?: string; + }; + Relationships: [ + { + foreignKeyName: 'climate_summary_rainfall_station_id_fkey'; + columns: ['station_id']; + isOneToOne: false; + referencedRelation: 'climate_stations'; + referencedColumns: ['id']; + } + ]; + }; + crop_data: { + Row: { + created_at: string; + crop: string; + id: string | null; + label: string | null; + variety: string; + }; + Insert: { + created_at?: string; + crop: string; + id?: string | null; + label?: string | null; + variety: string; + }; + Update: { + created_at?: string; + crop?: string; + id?: string | null; + label?: string | null; + variety?: string; + }; + Relationships: []; + }; + crop_station_data: { + Row: { + created_at: string; + crop_id: string; + days_lower: number; + days_upper: number; + probabilities: number[] | null; + station_id: string; + water_lower: number; + water_upper: number; + }; + Insert: { + created_at?: string; + crop_id: string; + days_lower: number; + days_upper: number; + probabilities?: number[] | null; + station_id: string; + water_lower: number; + water_upper: number; + }; + Update: { + created_at?: string; + crop_id?: string; + days_lower?: number; + days_upper?: number; + probabilities?: number[] | null; + station_id?: string; + water_lower?: number; + water_upper?: number; + }; + Relationships: [ + { + foreignKeyName: 'public_crop_station_data_crop_id_fkey'; + columns: ['crop_id']; + isOneToOne: false; + referencedRelation: 'crop_data'; + referencedColumns: ['id']; + }, + { + foreignKeyName: 'public_crop_station_data_station_id_fkey'; + columns: ['station_id']; + isOneToOne: false; + referencedRelation: 'climate_stations'; + referencedColumns: ['id']; + } + ]; + }; + deployments: { + Row: { + access_key_md5: string | null; + configuration: Json; + country_code: string; + icon_path: string | null; + id: string; + label: string; + public: boolean; + variant: string | null; + }; + Insert: { + access_key_md5?: string | null; + configuration?: Json; + country_code: string; + icon_path?: string | null; + id: string; + label: string; + public?: boolean; + variant?: string | null; + }; + Update: { + access_key_md5?: string | null; + configuration?: Json; + country_code?: string; + icon_path?: string | null; + id?: string; + label?: string; + public?: boolean; + variant?: string | null; + }; + Relationships: []; + }; + forecasts: { + Row: { + country_code: string; + created_at: string; + forecast_type: Database['public']['Enums']['forecast_type'] | null; + id: string; + language_code: string | null; + location: string[] | null; + mimetype: string | null; + storage_file: string | null; + updated_at: string; + }; + Insert: { + country_code: string; + created_at?: string; + forecast_type?: Database['public']['Enums']['forecast_type'] | null; + id: string; + language_code?: string | null; + location?: string[] | null; + mimetype?: string | null; + storage_file?: string | null; + updated_at?: string; + }; + Update: { + country_code?: string; + created_at?: string; + forecast_type?: Database['public']['Enums']['forecast_type'] | null; + id?: string; + language_code?: string | null; + location?: string[] | null; + mimetype?: string | null; + storage_file?: string | null; + updated_at?: string; + }; + Relationships: []; + }; + kobo_sync: { + Row: { + _created: string; + _id: string; + _modified: string; + enketo_entry: Json | null; + kobo_form_id: string | null; + kobo_sync_required: boolean | null; + kobo_sync_status: number | null; + kobo_sync_time: string | null; + kobo_uuid: string | null; + operation: string; + }; + Insert: { + _created?: string; + _id: string; + _modified?: string; + enketo_entry?: Json | null; + kobo_form_id?: string | null; + kobo_sync_required?: boolean | null; + kobo_sync_status?: number | null; + kobo_sync_time?: string | null; + kobo_uuid?: string | null; + operation: string; + }; + Update: { + _created?: string; + _id?: string; + _modified?: string; + enketo_entry?: Json | null; + kobo_form_id?: string | null; + kobo_sync_required?: boolean | null; + kobo_sync_status?: number | null; + kobo_sync_time?: string | null; + kobo_uuid?: string | null; + operation?: string; + }; + Relationships: []; + }; + monitoring_forms: { + Row: { + cover_image: string | null; + created_at: string; + description: string | null; + enketo_definition: Json | null; + enketo_form: string | null; + enketo_model: string | null; + form_xlsx: string | null; + id: string; + summary_fields: Json[] | null; + title: string; + }; + Insert: { + cover_image?: string | null; + created_at?: string; + description?: string | null; + enketo_definition?: Json | null; + enketo_form?: string | null; + enketo_model?: string | null; + form_xlsx?: string | null; + id: string; + summary_fields?: Json[] | null; + title: string; + }; + Update: { + cover_image?: string | null; + created_at?: string; + description?: string | null; + enketo_definition?: Json | null; + enketo_form?: string | null; + enketo_model?: string | null; + form_xlsx?: string | null; + id?: string; + summary_fields?: Json[] | null; + title?: string; + }; + Relationships: []; + }; + monitoring_tool_submissions: { + Row: { + _app_user_id: string; + _attachments: Json; + _created: string; + _deleted: boolean; + _id: string; + _modified: string; + enketoEntry: Json; + formId: string; + json: Json; + }; + Insert: { + _app_user_id: string; + _attachments: Json; + _created?: string; + _deleted?: boolean; + _id: string; + _modified?: string; + enketoEntry: Json; + formId: string; + json: Json; + }; + Update: { + _app_user_id?: string; + _attachments?: Json; + _created?: string; + _deleted?: boolean; + _id?: string; + _modified?: string; + enketoEntry?: Json; + formId?: string; + json?: Json; + }; + Relationships: []; + }; + resource_collections: { + Row: { + collection_parent: string | null; + cover_image: string | null; + created_at: string; + description: string | null; + id: string; + modified_at: string; + resource_collections: string[] | null; + resource_files: string[] | null; + resource_links: string[] | null; + sort_order: number; + title: string; + }; + Insert: { + collection_parent?: string | null; + cover_image?: string | null; + created_at?: string; + description?: string | null; + id?: string; + modified_at?: string; + resource_collections?: string[] | null; + resource_files?: string[] | null; + resource_links?: string[] | null; + sort_order?: number; + title: string; + }; + Update: { + collection_parent?: string | null; + cover_image?: string | null; + created_at?: string; + description?: string | null; + id?: string; + modified_at?: string; + resource_collections?: string[] | null; + resource_files?: string[] | null; + resource_links?: string[] | null; + sort_order?: number; + title?: string; + }; + Relationships: []; + }; + resource_files: { + Row: { + country_code: Database['public']['Enums']['country_code']; + cover_image: string | null; + created_at: string; + description: string | null; + external_url: string | null; + filename: string | null; + id: string; + language_code: string | null; + md5_checksum: string | null; + mimetype: string | null; + modified_at: string; + size_kb: number | null; + sort_order: number; + storage_file: string | null; + title: string | null; + }; + Insert: { + country_code?: Database['public']['Enums']['country_code']; + cover_image?: string | null; + created_at?: string; + description?: string | null; + external_url?: string | null; + filename?: string | null; + id?: string; + language_code?: string | null; + md5_checksum?: string | null; + mimetype?: string | null; + modified_at?: string; + size_kb?: number | null; + sort_order?: number; + storage_file?: string | null; + title?: string | null; + }; + Update: { + country_code?: Database['public']['Enums']['country_code']; + cover_image?: string | null; + created_at?: string; + description?: string | null; + external_url?: string | null; + filename?: string | null; + id?: string; + language_code?: string | null; + md5_checksum?: string | null; + mimetype?: string | null; + modified_at?: string; + size_kb?: number | null; + sort_order?: number; + storage_file?: string | null; + title?: string | null; + }; + Relationships: []; + }; + resource_files_child: { + Row: { + country_code: Database['public']['Enums']['country_code']; + cover_image: string | null; + created_at: string; + description: string | null; + external_url: string | null; + filename: string | null; + id: string; + language_code: string | null; + md5_checksum: string | null; + mimetype: string | null; + modified_at: string; + resource_file_id: string; + size_kb: number | null; + sort_order: number; + storage_file: string | null; + title: string | null; + }; + Insert: { + country_code?: Database['public']['Enums']['country_code']; + cover_image?: string | null; + created_at?: string; + description?: string | null; + external_url?: string | null; + filename?: string | null; + id?: string; + language_code?: string | null; + md5_checksum?: string | null; + mimetype?: string | null; + modified_at?: string; + resource_file_id: string; + size_kb?: number | null; + sort_order?: number; + storage_file?: string | null; + title?: string | null; + }; + Update: { + country_code?: Database['public']['Enums']['country_code']; + cover_image?: string | null; + created_at?: string; + description?: string | null; + external_url?: string | null; + filename?: string | null; + id?: string; + language_code?: string | null; + md5_checksum?: string | null; + mimetype?: string | null; + modified_at?: string; + resource_file_id?: string; + size_kb?: number | null; + sort_order?: number; + storage_file?: string | null; + title?: string | null; + }; + Relationships: [ + { + foreignKeyName: 'public_resource_files_child_resource_file_id_fkey'; + columns: ['resource_file_id']; + isOneToOne: false; + referencedRelation: 'resource_files'; + referencedColumns: ['id']; + } + ]; + }; + resource_links: { + Row: { + cover_image: string | null; + created_at: string; + description: string | null; + id: string; + modified_at: string; + sort_order: number; + title: string | null; + type: Database['public']['Enums']['resource_link_type']; + url: string; + }; + Insert: { + cover_image?: string | null; + created_at?: string; + description?: string | null; + id?: string; + modified_at?: string; + sort_order?: number; + title?: string | null; + type: Database['public']['Enums']['resource_link_type']; + url: string; + }; + Update: { + cover_image?: string | null; + created_at?: string; + description?: string | null; + id?: string; + modified_at?: string; + sort_order?: number; + title?: string | null; + type?: Database['public']['Enums']['resource_link_type']; + url?: string; + }; + Relationships: []; + }; + translations: { + Row: { + archived: boolean | null; + context: string | null; + created_at: string; + id: string; + ke_sw: string | null; + mw_ny: string | null; + text: string; + tj_tg: string | null; + tool: string; + zm_ny: string | null; + }; + Insert: { + archived?: boolean | null; + context?: string | null; + created_at?: string; + id: string; + ke_sw?: string | null; + mw_ny?: string | null; + text: string; + tj_tg?: string | null; + tool: string; + zm_ny?: string | null; + }; + Update: { + archived?: boolean | null; + context?: string | null; + created_at?: string; + id?: string; + ke_sw?: string | null; + mw_ny?: string | null; + text?: string; + tj_tg?: string | null; + tool?: string; + zm_ny?: string | null; + }; + Relationships: []; + }; + user_roles: { + Row: { + created_at: string; + deployment_id: string; + id: number; + roles: Database['public']['Enums']['app_role'][]; + user_id: string; + }; + Insert: { + created_at?: string; + deployment_id: string; + id?: number; + roles?: Database['public']['Enums']['app_role'][]; + user_id?: string; + }; + Update: { + created_at?: string; + deployment_id?: string; + id?: number; + roles?: Database['public']['Enums']['app_role'][]; + user_id?: string; + }; + Relationships: [ + { + foreignKeyName: 'public_user_roles_deployment_id_fkey'; + columns: ['deployment_id']; + isOneToOne: false; + referencedRelation: 'deployments'; + referencedColumns: ['id']; + } + ]; + }; + }; + Views: { + storage_objects: { + Row: { + bucket_id: string | null; + created_at: string | null; + id: string | null; + last_accessed_at: string | null; + metadata: Json | null; + name: string | null; + owner: string | null; + owner_id: string | null; + path_tokens: string[] | null; + updated_at: string | null; + version: string | null; + }; + Insert: { + bucket_id?: string | null; + created_at?: string | null; + id?: string | null; + last_accessed_at?: string | null; + metadata?: Json | null; + name?: string | null; + owner?: string | null; + owner_id?: string | null; + path_tokens?: string[] | null; + updated_at?: string | null; + version?: string | null; + }; + Update: { + bucket_id?: string | null; + created_at?: string | null; + id?: string | null; + last_accessed_at?: string | null; + metadata?: Json | null; + name?: string | null; + owner?: string | null; + owner_id?: string | null; + path_tokens?: string[] | null; + updated_at?: string | null; + version?: string | null; + }; + Relationships: []; + }; + }; + Functions: { + call_edge_function: { + Args: { + name: string; + body: Json; + }; + Returns: number; + }; + custom_access_token_hook: { + Args: { + event: Json; + }; + Returns: Json; + }; + }; + Enums: { + app_role: + | 'resources.viewer' + | 'resources.author' + | 'resources.admin' + | 'deployments.admin' + | 'translations.viewer'; + country_code: 'global' | 'mw' | 'zm' | 'tj'; + forecast_type: 'daily' | 'seasonal' | 'downscaled'; + locale_code: 'global_en' | 'mw_ny' | 'mw_tum' | 'zm_ny' | 'tj_tg'; + resource_link_type: 'app' | 'social' | 'web'; + }; + CompositeTypes: { + [_ in never]: never; + }; + }; + storage: { + Tables: { + buckets: { + Row: { + allowed_mime_types: string[] | null; + avif_autodetection: boolean | null; + created_at: string | null; + file_size_limit: number | null; + id: string; + name: string; + owner: string | null; + owner_id: string | null; + public: boolean | null; + updated_at: string | null; + }; + Insert: { + allowed_mime_types?: string[] | null; + avif_autodetection?: boolean | null; + created_at?: string | null; + file_size_limit?: number | null; + id: string; + name: string; + owner?: string | null; + owner_id?: string | null; + public?: boolean | null; + updated_at?: string | null; + }; + Update: { + allowed_mime_types?: string[] | null; + avif_autodetection?: boolean | null; + created_at?: string | null; + file_size_limit?: number | null; + id?: string; + name?: string; + owner?: string | null; + owner_id?: string | null; + public?: boolean | null; + updated_at?: string | null; + }; + Relationships: []; + }; + migrations: { + Row: { + executed_at: string | null; + hash: string; + id: number; + name: string; + }; + Insert: { + executed_at?: string | null; + hash: string; + id: number; + name: string; + }; + Update: { + executed_at?: string | null; + hash?: string; + id?: number; + name?: string; + }; + Relationships: []; + }; + objects: { + Row: { + bucket_id: string | null; + created_at: string | null; + id: string; + last_accessed_at: string | null; + metadata: Json | null; + name: string | null; + owner: string | null; + owner_id: string | null; + path: string | null; + path_tokens: string[] | null; + updated_at: string | null; + version: string | null; + }; + Insert: { + bucket_id?: string | null; + created_at?: string | null; + id?: string; + last_accessed_at?: string | null; + metadata?: Json | null; + name?: string | null; + owner?: string | null; + owner_id?: string | null; + path?: string | null; + path_tokens?: string[] | null; + updated_at?: string | null; + version?: string | null; + }; + Update: { + bucket_id?: string | null; + created_at?: string | null; + id?: string; + last_accessed_at?: string | null; + metadata?: Json | null; + name?: string | null; + owner?: string | null; + owner_id?: string | null; + path?: string | null; + path_tokens?: string[] | null; + updated_at?: string | null; + version?: string | null; + }; + Relationships: [ + { + foreignKeyName: 'objects_bucketId_fkey'; + columns: ['bucket_id']; + isOneToOne: false; + referencedRelation: 'buckets'; + referencedColumns: ['id']; + } + ]; + }; + }; + Views: { + [_ in never]: never; + }; + Functions: { + can_insert_object: { + Args: { + bucketid: string; + name: string; + owner: string; + metadata: Json; + }; + Returns: undefined; + }; + extension: { + Args: { + name: string; + }; + Returns: string; + }; + filename: { + Args: { + name: string; + }; + Returns: string; + }; + foldername: { + Args: { + name: string; + }; + Returns: string[]; + }; + get_size_by_bucket: { + Args: Record; + Returns: { + size: number; + bucket_id: string; + }[]; + }; + search: { + Args: { + prefix: string; + bucketname: string; + limits?: number; + levels?: number; + offsets?: number; + search?: string; + sortcolumn?: string; + sortorder?: string; + }; + Returns: { + name: string; + id: string; + updated_at: string; + created_at: string; + last_accessed_at: string; + metadata: Json; + }[]; + }; + }; + Enums: { + [_ in never]: never; + }; + CompositeTypes: { + [_ in never]: never; + }; + }; +}; + +type PublicSchema = Database[Extract]; + +export type Tables< + PublicTableNameOrOptions extends keyof (PublicSchema['Tables'] & PublicSchema['Views']) | { schema: keyof Database }, + TableName extends PublicTableNameOrOptions extends { schema: keyof Database } + ? keyof (Database[PublicTableNameOrOptions['schema']]['Tables'] & + Database[PublicTableNameOrOptions['schema']]['Views']) + : never = never +> = PublicTableNameOrOptions extends { schema: keyof Database } + ? (Database[PublicTableNameOrOptions['schema']]['Tables'] & + Database[PublicTableNameOrOptions['schema']]['Views'])[TableName] extends { + Row: infer R; + } + ? R + : never + : PublicTableNameOrOptions extends keyof (PublicSchema['Tables'] & PublicSchema['Views']) + ? (PublicSchema['Tables'] & PublicSchema['Views'])[PublicTableNameOrOptions] extends { + Row: infer R; + } + ? R + : never + : never; + +export type TablesInsert< + PublicTableNameOrOptions extends keyof PublicSchema['Tables'] | { schema: keyof Database }, + TableName extends PublicTableNameOrOptions extends { schema: keyof Database } + ? keyof Database[PublicTableNameOrOptions['schema']]['Tables'] + : never = never +> = PublicTableNameOrOptions extends { schema: keyof Database } + ? Database[PublicTableNameOrOptions['schema']]['Tables'][TableName] extends { + Insert: infer I; + } + ? I + : never + : PublicTableNameOrOptions extends keyof PublicSchema['Tables'] + ? PublicSchema['Tables'][PublicTableNameOrOptions] extends { + Insert: infer I; + } + ? I + : never + : never; + +export type TablesUpdate< + PublicTableNameOrOptions extends keyof PublicSchema['Tables'] | { schema: keyof Database }, + TableName extends PublicTableNameOrOptions extends { schema: keyof Database } + ? keyof Database[PublicTableNameOrOptions['schema']]['Tables'] + : never = never +> = PublicTableNameOrOptions extends { schema: keyof Database } + ? Database[PublicTableNameOrOptions['schema']]['Tables'][TableName] extends { + Update: infer U; + } + ? U + : never + : PublicTableNameOrOptions extends keyof PublicSchema['Tables'] + ? PublicSchema['Tables'][PublicTableNameOrOptions] extends { + Update: infer U; + } + ? U + : never + : never; + +export type Enums< + PublicEnumNameOrOptions extends keyof PublicSchema['Enums'] | { schema: keyof Database }, + EnumName extends PublicEnumNameOrOptions extends { schema: keyof Database } + ? keyof Database[PublicEnumNameOrOptions['schema']]['Enums'] + : never = never +> = PublicEnumNameOrOptions extends { schema: keyof Database } + ? Database[PublicEnumNameOrOptions['schema']]['Enums'][EnumName] + : PublicEnumNameOrOptions extends keyof PublicSchema['Enums'] + ? PublicSchema['Enums'][PublicEnumNameOrOptions] + : never; + +export type CompositeTypes< + PublicCompositeTypeNameOrOptions extends keyof PublicSchema['CompositeTypes'] | { schema: keyof Database }, + CompositeTypeName extends PublicCompositeTypeNameOrOptions extends { + schema: keyof Database; + } + ? keyof Database[PublicCompositeTypeNameOrOptions['schema']]['CompositeTypes'] + : never = never +> = PublicCompositeTypeNameOrOptions extends { schema: keyof Database } + ? Database[PublicCompositeTypeNameOrOptions['schema']]['CompositeTypes'][CompositeTypeName] + : PublicCompositeTypeNameOrOptions extends keyof PublicSchema['CompositeTypes'] + ? PublicSchema['CompositeTypes'][PublicCompositeTypeNameOrOptions] + : never; diff --git a/apps/picsa-server/supabase/types/functions.types.ts b/apps/picsa-server/supabase/types/functions.types.ts new file mode 100644 index 00000000..e6b348b8 --- /dev/null +++ b/apps/picsa-server/supabase/types/functions.types.ts @@ -0,0 +1,8 @@ +import type { IForecastDBAPIResponse } from '../functions/dashboard/types'; + +/** Manually generated list of supabase function responses */ +export type FunctionResponses = { + Dashboard: { + 'forecast-db': IForecastDBAPIResponse; + }; +}; diff --git a/apps/picsa-server/supabase/types/index.ts b/apps/picsa-server/supabase/types/index.ts index edb93c72..35c8f3dd 100644 --- a/apps/picsa-server/supabase/types/index.ts +++ b/apps/picsa-server/supabase/types/index.ts @@ -1,977 +1,2 @@ -export type Json = - | string - | number - | boolean - | null - | { [key: string]: Json | undefined } - | Json[] - -export type Database = { - graphql_public: { - Tables: { - [_ in never]: never - } - Views: { - [_ in never]: never - } - Functions: { - graphql: { - Args: { - operationName?: string - query?: string - variables?: Json - extensions?: Json - } - Returns: Json - } - } - Enums: { - [_ in never]: never - } - CompositeTypes: { - [_ in never]: never - } - } - public: { - Tables: { - climate_forecasts: { - Row: { - country_code: string - created_at: string - forecast_type: Database["public"]["Enums"]["forecast_type"] | null - id: string - language_code: string | null - location: string[] | null - mimetype: string | null - storage_file: string | null - updated_at: string - } - Insert: { - country_code: string - created_at?: string - forecast_type?: Database["public"]["Enums"]["forecast_type"] | null - id: string - language_code?: string | null - location?: string[] | null - mimetype?: string | null - storage_file?: string | null - updated_at?: string - } - Update: { - country_code?: string - created_at?: string - forecast_type?: Database["public"]["Enums"]["forecast_type"] | null - id?: string - language_code?: string | null - location?: string[] | null - mimetype?: string | null - storage_file?: string | null - updated_at?: string - } - Relationships: [] - } - climate_stations: { - Row: { - country_code: string - district: string | null - elevation: number | null - id: string | null - latitude: number | null - longitude: number | null - station_id: string - station_name: string | null - } - Insert: { - country_code: string - district?: string | null - elevation?: number | null - id?: string | null - latitude?: number | null - longitude?: number | null - station_id: string - station_name?: string | null - } - Update: { - country_code?: string - district?: string | null - elevation?: number | null - id?: string | null - latitude?: number | null - longitude?: number | null - station_id?: string - station_name?: string | null - } - Relationships: [] - } - climate_summary_rainfall: { - Row: { - country_code: Database["public"]["Enums"]["country_code"] - created_at: string - data: Json[] - metadata: Json - station_id: string - updated_at: string - } - Insert: { - country_code: Database["public"]["Enums"]["country_code"] - created_at?: string - data: Json[] - metadata: Json - station_id: string - updated_at?: string - } - Update: { - country_code?: Database["public"]["Enums"]["country_code"] - created_at?: string - data?: Json[] - metadata?: Json - station_id?: string - updated_at?: string - } - Relationships: [ - { - foreignKeyName: "climate_summary_rainfall_station_id_fkey" - columns: ["station_id"] - isOneToOne: false - referencedRelation: "climate_stations" - referencedColumns: ["id"] - }, - ] - } - crop_data: { - Row: { - created_at: string - crop: string - id: string | null - label: string | null - variety: string - } - Insert: { - created_at?: string - crop: string - id?: string | null - label?: string | null - variety: string - } - Update: { - created_at?: string - crop?: string - id?: string | null - label?: string | null - variety?: string - } - Relationships: [] - } - crop_station_data: { - Row: { - created_at: string - crop_id: string - days_lower: number - days_upper: number - probabilities: number[] | null - station_id: string - water_lower: number - water_upper: number - } - Insert: { - created_at?: string - crop_id: string - days_lower: number - days_upper: number - probabilities?: number[] | null - station_id: string - water_lower: number - water_upper: number - } - Update: { - created_at?: string - crop_id?: string - days_lower?: number - days_upper?: number - probabilities?: number[] | null - station_id?: string - water_lower?: number - water_upper?: number - } - Relationships: [ - { - foreignKeyName: "public_crop_station_data_crop_id_fkey" - columns: ["crop_id"] - isOneToOne: false - referencedRelation: "crop_data" - referencedColumns: ["id"] - }, - { - foreignKeyName: "public_crop_station_data_station_id_fkey" - columns: ["station_id"] - isOneToOne: false - referencedRelation: "climate_stations" - referencedColumns: ["id"] - }, - ] - } - deployments: { - Row: { - access_key_md5: string | null - configuration: Json - country_code: string - icon_path: string | null - id: string - label: string - public: boolean - variant: string | null - } - Insert: { - access_key_md5?: string | null - configuration?: Json - country_code: string - icon_path?: string | null - id: string - label: string - public?: boolean - variant?: string | null - } - Update: { - access_key_md5?: string | null - configuration?: Json - country_code?: string - icon_path?: string | null - id?: string - label?: string - public?: boolean - variant?: string | null - } - Relationships: [] - } - kobo_sync: { - Row: { - _created: string - _id: string - _modified: string - enketo_entry: Json | null - kobo_form_id: string | null - kobo_sync_required: boolean | null - kobo_sync_status: number | null - kobo_sync_time: string | null - kobo_uuid: string | null - operation: string - } - Insert: { - _created?: string - _id: string - _modified?: string - enketo_entry?: Json | null - kobo_form_id?: string | null - kobo_sync_required?: boolean | null - kobo_sync_status?: number | null - kobo_sync_time?: string | null - kobo_uuid?: string | null - operation: string - } - Update: { - _created?: string - _id?: string - _modified?: string - enketo_entry?: Json | null - kobo_form_id?: string | null - kobo_sync_required?: boolean | null - kobo_sync_status?: number | null - kobo_sync_time?: string | null - kobo_uuid?: string | null - operation?: string - } - Relationships: [] - } - monitoring_forms: { - Row: { - cover_image: string | null - created_at: string - description: string | null - enketo_definition: Json | null - enketo_form: string | null - enketo_model: string | null - form_xlsx: string | null - id: string - summary_fields: Json[] | null - title: string - } - Insert: { - cover_image?: string | null - created_at?: string - description?: string | null - enketo_definition?: Json | null - enketo_form?: string | null - enketo_model?: string | null - form_xlsx?: string | null - id: string - summary_fields?: Json[] | null - title: string - } - Update: { - cover_image?: string | null - created_at?: string - description?: string | null - enketo_definition?: Json | null - enketo_form?: string | null - enketo_model?: string | null - form_xlsx?: string | null - id?: string - summary_fields?: Json[] | null - title?: string - } - Relationships: [] - } - monitoring_tool_submissions: { - Row: { - _app_user_id: string - _attachments: Json - _created: string - _deleted: boolean - _id: string - _modified: string - enketoEntry: Json - formId: string - json: Json - } - Insert: { - _app_user_id: string - _attachments: Json - _created?: string - _deleted?: boolean - _id: string - _modified?: string - enketoEntry: Json - formId: string - json: Json - } - Update: { - _app_user_id?: string - _attachments?: Json - _created?: string - _deleted?: boolean - _id?: string - _modified?: string - enketoEntry?: Json - formId?: string - json?: Json - } - Relationships: [] - } - resource_collections: { - Row: { - collection_parent: string | null - cover_image: string | null - created_at: string - description: string | null - id: string - modified_at: string - resource_collections: string[] | null - resource_files: string[] | null - resource_links: string[] | null - sort_order: number - title: string - } - Insert: { - collection_parent?: string | null - cover_image?: string | null - created_at?: string - description?: string | null - id?: string - modified_at?: string - resource_collections?: string[] | null - resource_files?: string[] | null - resource_links?: string[] | null - sort_order?: number - title: string - } - Update: { - collection_parent?: string | null - cover_image?: string | null - created_at?: string - description?: string | null - id?: string - modified_at?: string - resource_collections?: string[] | null - resource_files?: string[] | null - resource_links?: string[] | null - sort_order?: number - title?: string - } - Relationships: [] - } - resource_files: { - Row: { - country_code: Database["public"]["Enums"]["country_code"] - cover_image: string | null - created_at: string - description: string | null - external_url: string | null - filename: string | null - id: string - language_code: string | null - md5_checksum: string | null - mimetype: string | null - modified_at: string - size_kb: number | null - sort_order: number - storage_file: string | null - title: string | null - } - Insert: { - country_code?: Database["public"]["Enums"]["country_code"] - cover_image?: string | null - created_at?: string - description?: string | null - external_url?: string | null - filename?: string | null - id?: string - language_code?: string | null - md5_checksum?: string | null - mimetype?: string | null - modified_at?: string - size_kb?: number | null - sort_order?: number - storage_file?: string | null - title?: string | null - } - Update: { - country_code?: Database["public"]["Enums"]["country_code"] - cover_image?: string | null - created_at?: string - description?: string | null - external_url?: string | null - filename?: string | null - id?: string - language_code?: string | null - md5_checksum?: string | null - mimetype?: string | null - modified_at?: string - size_kb?: number | null - sort_order?: number - storage_file?: string | null - title?: string | null - } - Relationships: [] - } - resource_files_child: { - Row: { - country_code: Database["public"]["Enums"]["country_code"] - cover_image: string | null - created_at: string - description: string | null - external_url: string | null - filename: string | null - id: string - language_code: string | null - md5_checksum: string | null - mimetype: string | null - modified_at: string - resource_file_id: string - size_kb: number | null - sort_order: number - storage_file: string | null - title: string | null - } - Insert: { - country_code?: Database["public"]["Enums"]["country_code"] - cover_image?: string | null - created_at?: string - description?: string | null - external_url?: string | null - filename?: string | null - id?: string - language_code?: string | null - md5_checksum?: string | null - mimetype?: string | null - modified_at?: string - resource_file_id: string - size_kb?: number | null - sort_order?: number - storage_file?: string | null - title?: string | null - } - Update: { - country_code?: Database["public"]["Enums"]["country_code"] - cover_image?: string | null - created_at?: string - description?: string | null - external_url?: string | null - filename?: string | null - id?: string - language_code?: string | null - md5_checksum?: string | null - mimetype?: string | null - modified_at?: string - resource_file_id?: string - size_kb?: number | null - sort_order?: number - storage_file?: string | null - title?: string | null - } - Relationships: [ - { - foreignKeyName: "public_resource_files_child_resource_file_id_fkey" - columns: ["resource_file_id"] - isOneToOne: false - referencedRelation: "resource_files" - referencedColumns: ["id"] - }, - ] - } - resource_links: { - Row: { - cover_image: string | null - created_at: string - description: string | null - id: string - modified_at: string - sort_order: number - title: string | null - type: Database["public"]["Enums"]["resource_link_type"] - url: string - } - Insert: { - cover_image?: string | null - created_at?: string - description?: string | null - id?: string - modified_at?: string - sort_order?: number - title?: string | null - type: Database["public"]["Enums"]["resource_link_type"] - url: string - } - Update: { - cover_image?: string | null - created_at?: string - description?: string | null - id?: string - modified_at?: string - sort_order?: number - title?: string | null - type?: Database["public"]["Enums"]["resource_link_type"] - url?: string - } - Relationships: [] - } - translations: { - Row: { - archived: boolean | null - context: string | null - created_at: string - id: string - ke_sw: string | null - mw_ny: string | null - text: string - tj_tg: string | null - tool: string - zm_ny: string | null - } - Insert: { - archived?: boolean | null - context?: string | null - created_at?: string - id: string - ke_sw?: string | null - mw_ny?: string | null - text: string - tj_tg?: string | null - tool: string - zm_ny?: string | null - } - Update: { - archived?: boolean | null - context?: string | null - created_at?: string - id?: string - ke_sw?: string | null - mw_ny?: string | null - text?: string - tj_tg?: string | null - tool?: string - zm_ny?: string | null - } - Relationships: [] - } - user_roles: { - Row: { - created_at: string - deployment_id: string - id: number - roles: Database["public"]["Enums"]["app_role"][] - user_id: string - } - Insert: { - created_at?: string - deployment_id: string - id?: number - roles?: Database["public"]["Enums"]["app_role"][] - user_id?: string - } - Update: { - created_at?: string - deployment_id?: string - id?: number - roles?: Database["public"]["Enums"]["app_role"][] - user_id?: string - } - Relationships: [ - { - foreignKeyName: "public_user_roles_deployment_id_fkey" - columns: ["deployment_id"] - isOneToOne: false - referencedRelation: "deployments" - referencedColumns: ["id"] - }, - ] - } - } - Views: { - storage_objects: { - Row: { - bucket_id: string | null - created_at: string | null - id: string | null - last_accessed_at: string | null - metadata: Json | null - name: string | null - owner: string | null - owner_id: string | null - path_tokens: string[] | null - updated_at: string | null - version: string | null - } - Insert: { - bucket_id?: string | null - created_at?: string | null - id?: string | null - last_accessed_at?: string | null - metadata?: Json | null - name?: string | null - owner?: string | null - owner_id?: string | null - path_tokens?: string[] | null - updated_at?: string | null - version?: string | null - } - Update: { - bucket_id?: string | null - created_at?: string | null - id?: string | null - last_accessed_at?: string | null - metadata?: Json | null - name?: string | null - owner?: string | null - owner_id?: string | null - path_tokens?: string[] | null - updated_at?: string | null - version?: string | null - } - Relationships: [] - } - } - Functions: { - custom_access_token_hook: { - Args: { - event: Json - } - Returns: Json - } - } - Enums: { - app_role: - | "resources.viewer" - | "resources.author" - | "resources.admin" - | "deployments.admin" - | "translations.viewer" - country_code: "global" | "mw" | "zm" | "tj" - forecast_type: "daily" | "annual" - locale_code: "global_en" | "mw_ny" | "mw_tum" | "zm_ny" | "tj_tg" - resource_link_type: "app" | "social" | "web" - } - CompositeTypes: { - [_ in never]: never - } - } - storage: { - Tables: { - buckets: { - Row: { - allowed_mime_types: string[] | null - avif_autodetection: boolean | null - created_at: string | null - file_size_limit: number | null - id: string - name: string - owner: string | null - owner_id: string | null - public: boolean | null - updated_at: string | null - } - Insert: { - allowed_mime_types?: string[] | null - avif_autodetection?: boolean | null - created_at?: string | null - file_size_limit?: number | null - id: string - name: string - owner?: string | null - owner_id?: string | null - public?: boolean | null - updated_at?: string | null - } - Update: { - allowed_mime_types?: string[] | null - avif_autodetection?: boolean | null - created_at?: string | null - file_size_limit?: number | null - id?: string - name?: string - owner?: string | null - owner_id?: string | null - public?: boolean | null - updated_at?: string | null - } - Relationships: [] - } - migrations: { - Row: { - executed_at: string | null - hash: string - id: number - name: string - } - Insert: { - executed_at?: string | null - hash: string - id: number - name: string - } - Update: { - executed_at?: string | null - hash?: string - id?: number - name?: string - } - Relationships: [] - } - objects: { - Row: { - bucket_id: string | null - created_at: string | null - id: string - last_accessed_at: string | null - metadata: Json | null - name: string | null - owner: string | null - owner_id: string | null - path: string | null - path_tokens: string[] | null - updated_at: string | null - version: string | null - } - Insert: { - bucket_id?: string | null - created_at?: string | null - id?: string - last_accessed_at?: string | null - metadata?: Json | null - name?: string | null - owner?: string | null - owner_id?: string | null - path?: string | null - path_tokens?: string[] | null - updated_at?: string | null - version?: string | null - } - Update: { - bucket_id?: string | null - created_at?: string | null - id?: string - last_accessed_at?: string | null - metadata?: Json | null - name?: string | null - owner?: string | null - owner_id?: string | null - path?: string | null - path_tokens?: string[] | null - updated_at?: string | null - version?: string | null - } - Relationships: [ - { - foreignKeyName: "objects_bucketId_fkey" - columns: ["bucket_id"] - isOneToOne: false - referencedRelation: "buckets" - referencedColumns: ["id"] - }, - ] - } - } - Views: { - [_ in never]: never - } - Functions: { - can_insert_object: { - Args: { - bucketid: string - name: string - owner: string - metadata: Json - } - Returns: undefined - } - extension: { - Args: { - name: string - } - Returns: string - } - filename: { - Args: { - name: string - } - Returns: string - } - foldername: { - Args: { - name: string - } - Returns: string[] - } - get_size_by_bucket: { - Args: Record - Returns: { - size: number - bucket_id: string - }[] - } - search: { - Args: { - prefix: string - bucketname: string - limits?: number - levels?: number - offsets?: number - search?: string - sortcolumn?: string - sortorder?: string - } - Returns: { - name: string - id: string - updated_at: string - created_at: string - last_accessed_at: string - metadata: Json - }[] - } - } - Enums: { - [_ in never]: never - } - CompositeTypes: { - [_ in never]: never - } - } -} - -type PublicSchema = Database[Extract] - -export type Tables< - PublicTableNameOrOptions extends - | keyof (PublicSchema["Tables"] & PublicSchema["Views"]) - | { schema: keyof Database }, - TableName extends PublicTableNameOrOptions extends { schema: keyof Database } - ? keyof (Database[PublicTableNameOrOptions["schema"]]["Tables"] & - Database[PublicTableNameOrOptions["schema"]]["Views"]) - : never = never, -> = PublicTableNameOrOptions extends { schema: keyof Database } - ? (Database[PublicTableNameOrOptions["schema"]]["Tables"] & - Database[PublicTableNameOrOptions["schema"]]["Views"])[TableName] extends { - Row: infer R - } - ? R - : never - : PublicTableNameOrOptions extends keyof (PublicSchema["Tables"] & - PublicSchema["Views"]) - ? (PublicSchema["Tables"] & - PublicSchema["Views"])[PublicTableNameOrOptions] extends { - Row: infer R - } - ? R - : never - : never - -export type TablesInsert< - PublicTableNameOrOptions extends - | keyof PublicSchema["Tables"] - | { schema: keyof Database }, - TableName extends PublicTableNameOrOptions extends { schema: keyof Database } - ? keyof Database[PublicTableNameOrOptions["schema"]]["Tables"] - : never = never, -> = PublicTableNameOrOptions extends { schema: keyof Database } - ? Database[PublicTableNameOrOptions["schema"]]["Tables"][TableName] extends { - Insert: infer I - } - ? I - : never - : PublicTableNameOrOptions extends keyof PublicSchema["Tables"] - ? PublicSchema["Tables"][PublicTableNameOrOptions] extends { - Insert: infer I - } - ? I - : never - : never - -export type TablesUpdate< - PublicTableNameOrOptions extends - | keyof PublicSchema["Tables"] - | { schema: keyof Database }, - TableName extends PublicTableNameOrOptions extends { schema: keyof Database } - ? keyof Database[PublicTableNameOrOptions["schema"]]["Tables"] - : never = never, -> = PublicTableNameOrOptions extends { schema: keyof Database } - ? Database[PublicTableNameOrOptions["schema"]]["Tables"][TableName] extends { - Update: infer U - } - ? U - : never - : PublicTableNameOrOptions extends keyof PublicSchema["Tables"] - ? PublicSchema["Tables"][PublicTableNameOrOptions] extends { - Update: infer U - } - ? U - : never - : never - -export type Enums< - PublicEnumNameOrOptions extends - | keyof PublicSchema["Enums"] - | { schema: keyof Database }, - EnumName extends PublicEnumNameOrOptions extends { schema: keyof Database } - ? keyof Database[PublicEnumNameOrOptions["schema"]]["Enums"] - : never = never, -> = PublicEnumNameOrOptions extends { schema: keyof Database } - ? Database[PublicEnumNameOrOptions["schema"]]["Enums"][EnumName] - : PublicEnumNameOrOptions extends keyof PublicSchema["Enums"] - ? PublicSchema["Enums"][PublicEnumNameOrOptions] - : never - -export type CompositeTypes< - PublicCompositeTypeNameOrOptions extends - | keyof PublicSchema["CompositeTypes"] - | { schema: keyof Database }, - CompositeTypeName extends PublicCompositeTypeNameOrOptions extends { - schema: keyof Database - } - ? keyof Database[PublicCompositeTypeNameOrOptions["schema"]]["CompositeTypes"] - : never = never, -> = PublicCompositeTypeNameOrOptions extends { schema: keyof Database } - ? Database[PublicCompositeTypeNameOrOptions["schema"]]["CompositeTypes"][CompositeTypeName] - : PublicCompositeTypeNameOrOptions extends keyof PublicSchema["CompositeTypes"] - ? PublicSchema["CompositeTypes"][PublicCompositeTypeNameOrOptions] - : never - +export * from './db.types' +export * from './functions.types' \ No newline at end of file