Files
supabase/studio/stores/pgmeta/MetaStore.ts
T
Alaister Young acf2ddb1c1 Squashed commit of the following:
commit 61f4c6e585
Merge: b7dabb368 2fc053d32
Author: Kevin Grüneberg <k.grueneberg1994@gmail.com>
Date:   Fri Jun 9 03:51:57 2023 -0700

    Merge pull request #14928 from supabase/hf/usage-v2

    Hotfix: Usage v2 improvements

commit 2fc053d323
Author: Kevin Grüneberg <k.grueneberg1994@gmail.com>
Date:   Fri Jun 9 10:58:39 2023 +0200

    chore(usage): add Realtime docs, improve timeframes, upsell

commit b7dabb368d
Merge: d9bbd6f37 bf807a9c7
Author: Terry Sutton <saltcod@gmail.com>
Date:   Thu Jun 8 12:47:46 2023 -0230

    Merge pull request #14908 from supabase/master

    prod deploy

commit d9bbd6f375
Merge: 2fff5f2cf e7c2bd61c
Author: Terry Sutton <saltcod@gmail.com>
Date:   Thu Jun 8 12:18:09 2023 -0230

    Merge pull request #14905 from supabase/master

    prod deploy

commit 2fff5f2cff
Merge: 814a745ef 90deee74b
Author: Alaister Young <alaister@users.noreply.github.com>
Date:   Thu Jun 8 21:59:42 2023 +1000

    Merge pull request #14891 from supabase/master

    Prod deploy dashboard

commit 814a745efc
Merge: 4c3735b68 fb7a35fff
Author: Jonathan Summers-Muir <MildTomato@users.noreply.github.com>
Date:   Tue Jun 6 11:24:34 2023 +0200

    Merge pull request #14835 from supabase/master

    Prod deploy (Studio)

commit 4c3735b687
Merge: c876cea30 b94f5464d
Author: Jonathan Summers-Muir <MildTomato@users.noreply.github.com>
Date:   Mon Jun 5 15:46:27 2023 +0200

    Merge pull request #14801 from supabase/master

    Prod deploy

commit c876cea306
Merge: aa640eee5 ef7060729
Author: Terry Sutton <saltcod@gmail.com>
Date:   Sun Jun 4 23:40:16 2023 -0230

    Merge pull request #14793 from supabase/hotfix/json-sidepanel-editor

    Check if value is an object before returning it

commit ef70607290
Author: Terry Sutton <saltcod@gmail.com>
Date:   Sun Jun 4 23:18:09 2023 -0230

    Check if value is an object before returning it

commit aa640eee5e
Merge: 02f18cbb5 f48ae5ac5
Author: Alaister Young <alaister@users.noreply.github.com>
Date:   Thu Jun 1 21:58:21 2023 +1000

    Merge pull request #14732 from supabase/master

    Prod deploy dashboard

commit 02f18cbb55
Merge: 3091a3749 6163981a0
Author: Alaister Young <alaister@users.noreply.github.com>
Date:   Tue May 30 17:02:58 2023 +1000

    Merge pull request #14681 from supabase/master

    Prod deploy dashboard

commit 3091a3749d
Merge: b5b2ce572 30d3b473d
Author: Alaister Young <alaister@users.noreply.github.com>
Date:   Thu May 25 17:19:48 2023 +1000

    Merge pull request #14589 from supabase/master

    Prod deploy dashboard

commit b5b2ce572a
Merge: fa3eacc36 c462bb582
Author: Terry Sutton <saltcod@gmail.com>
Date:   Tue May 23 11:16:49 2023 -0230

    Merge pull request #14535 from supabase/hotfix/webhooks-triggers-error

    chore: display triggers in the `net` schema if they're not webhooks; hide triggers in webhooks if they don't have at least an URL and method specified

commit c462bb582d
Author: Paul Cioanca <paul.cioanca@supabase.io>
Date:   Tue May 23 15:29:09 2023 +0300

    chore: display triggers in the `net` schema if they're not webhooks; hide triggers in webhooks if they don't have at least an URL and method specified

commit fa3eacc363
Merge: 199a18b8f 27fa8bfed
Author: Alaister Young <alaister@users.noreply.github.com>
Date:   Tue May 23 15:54:47 2023 +1000

    Merge pull request #14456 from supabase/master

    Prod deploy dashboard

commit 199a18b8f3
Merge: e73ecad8f 335b4c205
Author: Alaister Young <alaister@users.noreply.github.com>
Date:   Sat May 20 11:55:11 2023 +1000

    Merge pull request #14480 from supabase/hotfix/sql-name-updating

commit 335b4c205c
Author: Alaister Young <a@alaisteryoung.com>
Date:   Sat May 20 10:07:14 2023 +1000

    hotfix: sql name updating

commit e73ecad8fd
Merge: 77ce8e37a 8de91649b
Author: Terry Sutton <saltcod@gmail.com>
Date:   Thu May 18 23:43:48 2023 -0230

    Merge pull request #14462 from supabase/hotfix/webhooks-menu-item2

    fix: switch webhook availability to be conditional based on pg_net ex…

commit 8de91649b2
Author: Paul Cioanca <paul.cioanca@supabase.io>
Date:   Thu May 18 21:13:47 2023 +0300

    fix: switch webhook availability to be conditional based on pg_net existing

commit 77ce8e37a7
Merge: 5f4e87fc1 c809608dc
Author: Ziinc <Ziinc@users.noreply.github.com>
Date:   Thu May 18 11:14:28 2023 +0800

    Merge pull request #14442 from supabase/master

    Prod deploy dashboard

commit 5f4e87fc12
Merge: a2ae6bc66 0f1254252
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Wed May 17 15:23:55 2023 +0800

    Merge pull request #14418 from supabase/master

    Prod deploy dashboard

commit a2ae6bc669
Merge: 9b4a07124 eeb4846f4
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Tue May 16 15:14:30 2023 +0800

    Merge pull request #14386 from supabase/master

    Prod deploy dashboard

commit 9b4a071243
Merge: e3eac9610 bf3e02aa0
Author: Alaister Young <alaister@users.noreply.github.com>
Date:   Thu May 11 22:24:59 2023 +1000

    Merge pull request #14280 from supabase/master

    Prod deploy dashboard

commit e3eac96105
Merge: af8eb1ebc 24ef3577c
Author: Jonathan Summers-Muir <MildTomato@users.noreply.github.com>
Date:   Tue May 9 17:56:31 2023 +0800

    Merge pull request #14225 from supabase/master

    Studio deploy

commit af8eb1ebcc
Merge: f9358969e 8769f7c19
Author: Alaister Young <alaister@users.noreply.github.com>
Date:   Tue May 9 15:09:53 2023 +1000

    Merge pull request #14218 from supabase/master

    Prod deploy dashboard

commit f9358969ed
Merge: 78d2c2de7 b5c6a54d7
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Mon May 8 17:08:05 2023 +0800

    Merge pull request #14200 from supabase/master

    Prod deploy dashboard

commit 78d2c2de73
Merge: 0f52967b3 d730ea9ca
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Mon May 8 09:54:23 2023 +0800

    Merge pull request #14148 from supabase/master

    Prod deploy dashboard

commit 0f52967b3e
Merge: d8c07236b 4ce82e7a5
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Thu May 4 18:13:07 2023 +0800

    Merge pull request #14121 from supabase/master

    Prod deploy dashboard

commit d8c07236be
Merge: 0120c02a3 89827c208
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Tue May 2 13:14:48 2023 +0800

    Merge pull request #14067 from supabase/master

    Prod deploy dashboard

commit 0120c02a30
Merge: 745efc91a 4bfa94f7a
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Thu Apr 27 14:09:56 2023 +0800

    Merge pull request #13993 from supabase/master

    Prod deploy dashboard

commit 745efc91a7
Merge: ff6ea2ad4 fd82ab26b
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Tue Apr 25 14:25:45 2023 +0800

    Merge pull request #13948 from supabase/master

    Prod deploy dashboard

commit ff6ea2ad48
Merge: f4797757f c6ffaefb1
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Tue Apr 25 01:46:41 2023 +0800

    Merge pull request #13932 from supabase/fix/hitting-enter-in-table-editor-text-cell-sets-value-to-null-if-column-is-nullable

    Fix/hitting enter in table editor text cell sets value to null if column is nullable

commit c6ffaefb19
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Tue Apr 25 01:24:21 2023 +0800

    Remove log

commit 1067363578
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Tue Apr 25 01:20:46 2023 +0800

    Remove unnecessary prop

commit 9b9e6d7a43
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Tue Apr 25 01:18:46 2023 +0800

    Prevent setting value to NULL when hitting Enter while highlighting cell in table editor thats of text type and nullable

commit f4797757f3
Merge: fedf6a14b 6c1675129
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Thu Apr 20 19:00:42 2023 +0700

    Merge pull request #13853 from supabase/hotfix/fix-page-view

    Hotfix/fix page view

commit 6c1675129d
Author: phamhieu <phamhieu1998@gmail.com>
Date:   Thu Apr 20 18:35:41 2023 +0700

    fix: sanitizePageViewRoute to remove instead of replace

commit b08447b424
Author: phamhieu <phamhieu1998@gmail.com>
Date:   Thu Apr 20 17:13:44 2023 +0700

    fix: sanitize route before sending page_view event

commit 8245595ab3
Author: phamhieu <phamhieu1998@gmail.com>
Date:   Thu Apr 20 16:31:51 2023 +0700

    fix: page_view should use browser url

commit fedf6a14b0
Merge: 42a180f8d 9148c49cb
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Thu Apr 20 13:35:24 2023 +0700

    Merge pull request #13842 from supabase/master

    Prod deploy dashboard

commit 42a180f8d2
Merge: 01b9b4ae2 e7c4c734e
Author: Alaister Young <alaister@users.noreply.github.com>
Date:   Wed Apr 19 11:08:21 2023 +1000

    Merge pull request #13817 from supabase/fix/usage-endpoint-null-values

    hotfix: usage endpoint null values

commit e7c4c734e5
Author: Alaister Young <a@alaisteryoung.com>
Date:   Wed Apr 19 10:53:32 2023 +1000

    fix: usage endpoint null values

commit 01b9b4ae21
Merge: 8e0403422 d9f7d2982
Author: Alaister Young <alaister@users.noreply.github.com>
Date:   Tue Apr 18 19:20:17 2023 +1000

    Merge pull request #13797 from supabase/master

    Prod deploy studio

commit 8e04034221
Merge: eaffed8f2 e690e4557
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Sun Apr 16 15:46:50 2023 +0700

    Merge pull request #13753 from supabase/hotfix/sql-editor

    Hotfix/sql editor

commit e690e4557b
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Sun Apr 16 15:39:12 2023 +0700

    Fix sql editor stale content when switching tabs and clicking run button

commit eaffed8f20
Merge: 32ffce433 071d4db8a
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Fri Apr 14 18:29:42 2023 +0700

    Merge pull request #13721 from supabase/master

    Prod deploy dashboard

commit 32ffce433c
Merge: 8b5044e38 9e6b23983
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Fri Apr 14 11:09:50 2023 +0700

    Merge pull request #13706 from supabase/hotfix/remove-wrong-column-removal-in-catch-block

    Hotfix/remove wrong column removal in catch block

commit 9e6b239830
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Fri Apr 14 10:56:51 2023 +0700

    Remove wrong column removal at catch block

commit 8b5044e380
Merge: bddc3a1c7 0a0202477
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Thu Apr 13 15:00:19 2023 +0700

    Merge pull request #13668 from supabase/master

    Prod deploy dashboard

commit bddc3a1c79
Merge: ad60ad2e6 9fe16dba5
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Thu Apr 13 13:28:43 2023 +0700

    Merge pull request #13665 from supabase/master

    Prod deploy dashboard

commit ad60ad2e63
Merge: 71d8fabad 46bdcb4f7
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Wed Apr 12 14:50:32 2023 +0700

    Merge pull request #13633 from supabase/master

    Prod deploy dashboard

commit 71d8fabad4
Merge: 7b8a1d963 412e9d3dd
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Thu Apr 6 14:12:19 2023 +0800

    Merge pull request #13482 from supabase/master

    Prod deploy dashboard

commit 7b8a1d963c
Merge: 52cc456cc e1baff851
Author: Jonathan Summers-Muir <MildTomato@users.noreply.github.com>
Date:   Tue Apr 4 23:53:34 2023 +0800

    Merge pull request #13426 from supabase/hotfix/monaco-css

    [hotfix] fix selection issue in monaco editor

commit e1baff8517
Author: Jonathan Summers-Muir <MildTomato@users.noreply.github.com>
Date:   Tue Apr 4 23:01:54 2023 +0800

    Update _document.tsx

commit 52cc456ccb
Merge: 44993870f d41641405
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Tue Apr 4 15:35:41 2023 +0800

    Merge pull request #13415 from supabase/master

    Prod deploy dashboard

commit 44993870f5
Merge: c745deddb 0038f6312
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Tue Apr 4 14:34:07 2023 +0800

    Merge pull request #13413 from supabase/master

    Prod deploy dashboard

commit c745deddb6
Merge: 99fed3d93 09e2c21a7
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Thu Mar 30 21:28:26 2023 +0800

    Merge pull request #13320 from supabase/master

    Prod deploy dashboard

commit 99fed3d932
Merge: d697289cf eefa3bf6d
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Thu Mar 30 14:07:35 2023 +0800

    Merge pull request #13309 from supabase/master

    Prod deploy dashboard

commit d697289cf1
Merge: 13fdccb87 e3f09fe6a
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Wed Mar 29 18:31:17 2023 +0800

    Merge pull request #13291 from supabase/master

    Prod deploy dashboard

commit 13fdccb87d
Merge: dd42066be d441a0170
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Wed Mar 29 16:37:45 2023 +0800

    Merge pull request #13285 from supabase/master

    [On Hold] Studio prod deploy

commit dd42066bee
Merge: df64b1a25 c071ee624
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Wed Mar 29 13:15:18 2023 +0800

    Merge pull request #13282 from supabase/master

    Prod deploy dashboard

commit df64b1a251
Merge: 8bcdcca38 099cf9192
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Tue Mar 28 13:55:53 2023 +0800

    Merge pull request #13252 from supabase/master

    Prod deploy dashboard

commit 8bcdcca38f
Merge: 8108ba493 3b3598909
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Mon Mar 27 13:38:34 2023 +0800

    Merge pull request #13223 from supabase/master

    Prod deploy dashboard

commit 8108ba493f
Merge: 955e93087 de20ff2a3
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Thu Mar 23 15:13:51 2023 +0800

    Merge pull request #13159 from supabase/master

    Prod deploy dashboard

commit 955e930879
Merge: a0a0ef16d c1eca93c9
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Wed Mar 22 15:20:24 2023 +0800

    Merge pull request #13135 from supabase/master

    Prod deploy dashboard

commit a0a0ef16d1
Merge: 925a204bb a71e4f736
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Wed Mar 22 15:04:23 2023 +0800

    Merge pull request #13140 from supabase/hotfix/update-default-region-to-east-us

    Update default region to east us

commit a71e4f7361
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Wed Mar 22 14:37:52 2023 +0800

    Update default region to east us

commit 925a204bb3
Merge: 414190e27 71af49c7d
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Tue Mar 21 13:50:19 2023 +0800

    Merge pull request #13118 from supabase/master

    Prod deploy Studio

commit 414190e27d
Merge: f78a9add2 23678bc55
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Wed Mar 15 09:28:57 2023 +0800

    Merge pull request #13009 from supabase/da/enable-use1

    hotfix: re-enable support for use1

commit 23678bc55f
Author: Div Arora <root@darora.com>
Date:   Wed Mar 15 06:40:18 2023 +0800

    chore: re-enable support for use1

commit f78a9add2a
Merge: 03c6d296f ee3f09199
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Tue Mar 14 09:47:34 2023 +0800

    Merge pull request #12987 from supabase/hotfix/edge-functions-update-fix

    Hotfix changes from https://github.com/supabase/supabase/pull/12974

commit ee3f091996
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Tue Mar 14 09:39:03 2023 +0800

    Hotfix changes from https://github.com/supabase/supabase/pull/12974

commit 03c6d296f7
Merge: a5bce1226 6e32e836b
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Sun Mar 12 00:11:04 2023 +0800

    Merge pull request #12956 from supabase/hotfix/disable_east_us

    hotfix: temporarily disable East US region for project creation

commit 6e32e836b7
Author: dragarcia <angelico.delosreyes@gmail.com>
Date:   Sat Mar 11 23:57:30 2023 +0800

    hotfix: disable US east for project creation

commit a5bce1226c
Merge: c20a9b240 f3e3e0d00
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Thu Mar 9 15:32:56 2023 +0800

    Merge pull request #12904 from supabase/master

    Prod deploy dashboard

commit c20a9b2401
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Tue Mar 7 16:32:41 2023 +0800

    Add region field for edge function details

commit dabecd0c7b
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Tue Mar 7 16:31:14 2023 +0800

    Update import map field

commit 18ac80b6d4
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Tue Mar 7 16:23:08 2023 +0800

    Update route to use function slug and use singular function query instead of list functions query

commit 52bf4cff5b
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Thu Mar 2 17:19:47 2023 +0800

    Hook up PATCH, and allow users to update function name and jwt verification enforcement

commit ae003dd8f5
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Wed Mar 1 20:48:07 2023 +0800

    Add in additioanl configs for edge functions details

commit 8f1e96b222
Merge: 6c57994e7 c484fc841
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Tue Mar 7 17:05:34 2023 +0800

    Merge pull request #12851 from supabase/master

    Prod deploy dashboard

commit 6c57994e7e
Merge: 92e72bac9 b4244bf17
Author: Alaister Young <alaister@users.noreply.github.com>
Date:   Fri Mar 3 13:34:51 2023 +1100

    Merge pull request #12782 from supabase/fix/row-content-menu-react-query

commit b4244bf17d
Author: Alaister Young <a@alaisteryoung.com>
Date:   Fri Mar 3 12:35:37 2023 +1100

    fix: <RowContextMenu /> to use rows from react-query

commit 92e72bac9f
Merge: b6953ba9e 0befcd053
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Thu Mar 2 15:35:20 2023 +0800

    Merge pull request #12754 from supabase/master

    Prod deploy dashboard

commit b6953ba9e1
Merge: 029c7bd96 0600e76d2
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Wed Mar 1 12:26:12 2023 +0800

    Merge pull request #12731 from supabase/master

    Prod deploy dashboard

commit 029c7bd96d
Merge: 0b72dd38d dc29557ae
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Tue Feb 28 15:24:20 2023 +0800

    Merge pull request #12714 from supabase/master

    Prod deploy dashboard

commit 0b72dd38dc
Merge: 74011e80e 9c8cdc64d
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Thu Feb 23 14:51:53 2023 +0800

    Merge pull request #12620 from supabase/master

    Prod deploy dashboard

commit 74011e80ed
Merge: 3b03a446e 93c227556
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Wed Feb 22 16:37:52 2023 +0800

    Merge pull request #12597 from supabase/master

    Prod deploy

commit 3b03a446ed
Merge: e533c0d25 907933225
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Wed Feb 22 15:59:57 2023 +0800

    Merge pull request #12595 from supabase/master

    Prod deploy Dashboard

commit e533c0d25f
Merge: 91c7ea864 6a2ad6fcf
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Tue Feb 21 14:26:33 2023 +0800

    Merge pull request #12570 from supabase/master

    Prod deploy dashboard

commit 91c7ea864d
Merge: 6ed57849e 418a50a73
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Tue Feb 21 13:48:02 2023 +0800

    Merge pull request #12568 from supabase/master

    Prod deploy Dashboard

commit 6ed57849ea
Merge: e731b7716 bb5d57da5
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Mon Feb 20 15:17:37 2023 +0800

    Merge pull request #12548 from supabase/master

    Prod deploy dashboard

commit e731b7716a
Merge: 515b56562 ae3e1b89a
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Thu Feb 16 16:30:42 2023 +0800

    Merge pull request #12469 from supabase/master

    Prod deploy dashboard

commit 515b56562b
Merge: 49624c644 f8700ff5c
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Wed Feb 15 13:14:25 2023 +0800

    Merge pull request #12431 from supabase/master

    Prod deploy dashboard

commit 49624c644f
Merge: 452fb689f e33555c4d
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Tue Feb 14 15:22:30 2023 +0800

    Merge pull request #12406 from supabase/master

    Prod deploy dashboard

commit 452fb689fe
Merge: 74a75e39b e663e0be0
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Fri Feb 10 02:18:21 2023 +0800

    Merge pull request #12297 from supabase/master

    Prod deploy dashboard

commit 74a75e39bd
Merge: 2b8d81bd1 c6bcdc69c
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Thu Feb 9 14:30:44 2023 +0800

    Merge pull request #12280 from supabase/master

    Prod deploy dashboard

commit 2b8d81bd12
Merge: 77b356e59 e730d9c34
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Wed Feb 8 13:10:09 2023 +0800

    Merge pull request #12219 from supabase/master

    Prod deploy dashboard

commit 77b356e596
Merge: c20ed925a 9d866bc8f
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Tue Feb 7 14:54:48 2023 +0800

    Merge pull request #12217 from supabase/master

    Prod deploy dashboard

commit c20ed925ad
Merge: 57eb4a234 d8bc2a5f5
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Thu Feb 2 15:45:15 2023 +0800

    Merge pull request #12121 from supabase/master

    Prod deploy dashboard

commit 57eb4a2347
Merge: 08b4ce3cc 5e0ec008c
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Tue Jan 31 15:34:38 2023 +0800

    Merge pull request #12073 from supabase/revert-12066-revert-11987-master

    Revert "Revert "Studio deploy""

commit 5e0ec008c0
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Tue Jan 31 15:19:24 2023 +0800

    Update DisplayAPISettings

commit 372ac5ee75
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Tue Jan 31 15:18:06 2023 +0800

    Revert "Revert "Studio deploy""

commit 08b4ce3cc3
Merge: b0b953fcc f2e253df7
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Tue Jan 31 14:34:33 2023 +0800

    Merge pull request #12066 from supabase/revert-11987-master

    Revert "Studio deploy"

commit f2e253df7e
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Tue Jan 31 14:25:18 2023 +0800

    Revert "Studio deploy"

commit b0b953fcc8
Merge: fecb67faf d9846650e
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Tue Jan 31 13:33:55 2023 +0800

    Merge pull request #11987 from supabase/master

    Studio deploy

commit fecb67fafb
Merge: de0ab2458 624afc1f9
Author: Jonathan Summers-Muir <MildTomato@users.noreply.github.com>
Date:   Sat Jan 28 05:08:32 2023 +0800

    Merge pull request #11990 from supabase/hotfix/exit-survey-use-state-issue

    Hotfix/ fix useState issue on submit button

commit 624afc1f9a
Author: Jonathan Summers-Muir <MildTomato@users.noreply.github.com>
Date:   Sat Jan 28 04:57:55 2023 +0800

    Update ExitSurvey.tsx

commit de0ab24582
Merge: 6c1a5e16c a59f37482
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Thu Jan 26 14:39:38 2023 +0800

    Merge pull request #11933 from supabase/master

    Prod Deploy Dashboard

commit 6c1a5e16c2
Merge: 1d5ebd674 c019be2d1
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Tue Jan 24 14:51:39 2023 +0800

    Merge pull request #11754 from supabase/master

    Prod Deploy Dashboard

commit 1d5ebd6748
Merge: a2ba82792 09dce53d1
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Wed Jan 18 10:56:34 2023 +0800

    Merge pull request #11699 from supabase/master

    Prod deploy dashboard

commit a2ba827926
Merge: 1206b98cd 6ae28bdee
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Fri Jan 13 01:05:33 2023 +0800

    Merge pull request #11606 from supabase/master

    Prod deploy dashboard

commit 1206b98cde
Merge: 902aeb288 d08312124
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Wed Jan 11 14:29:50 2023 +0800

    Merge pull request #11553 from supabase/master

    Prod deploy dashboard

commit 902aeb2884
Merge: 6b98c0696 2aa6a4a69
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Tue Jan 3 13:05:47 2023 +0700

    Merge pull request #11292 from supabase/master

    Prod deploy dashboard

commit 6b98c06968
Merge: d31caddc3 e50d736b3
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Thu Dec 22 17:55:30 2022 +0700

    Merge pull request #11186 from supabase/master

    Prod deploy dashboard

commit d31caddc39
Merge: fddc4ceed b40e6216a
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Wed Dec 21 22:14:21 2022 +0700

    Merge pull request #11170 from supabase/master

    Prod deploy dashboard

commit fddc4ceede
Merge: 58fe3de07 ad300dfd3
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Wed Dec 21 14:15:04 2022 +0700

    Merge pull request #11110 from supabase/master

    Prod deploy dashboard

commit 58fe3de070
Merge: 4eecc9917 71a2888d0
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Thu Dec 15 02:42:58 2022 +0700

    Merge pull request #10983 from supabase/master

    Prod deploy dashboard

commit 4eecc99176
Merge: 94c499fe0 f091fa666
Author: Inian <inian1234@gmail.com>
Date:   Wed Dec 14 18:31:12 2022 +0800

    Merge pull request #10957 from supabase/master

commit 94c499fe08
Merge: fe5098842 a7c9f25ea
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Wed Dec 14 13:57:51 2022 +0700

    Merge pull request #10950 from supabase/master

    Prod deploy dashboard

commit fe50988422
Merge: 3505e9e91 744ee0d86
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Wed Dec 14 11:57:33 2022 +0700

    Merge pull request #10910 from supabase/master

    Prod deploy dashboard

commit 3505e9e915
Merge: b6d89178d cc3d379da
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Tue Dec 13 17:21:32 2022 +0700

    Merge pull request #10903 from supabase/master

    Prod deploy dashboard

commit b6d89178d4
Merge: 52aa28bf8 d93c85d7c
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Tue Dec 13 12:41:37 2022 +0700

    Merge pull request #10894 from supabase/master

    Prod deploy dashboard

commit 52aa28bf8b
Merge: df66ff2c5 c67b321ea
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Thu Dec 8 18:23:36 2022 +0800

    Merge pull request #10797 from supabase/master

    Prod deploy dashboard

commit df66ff2c56
Merge: d264d528c 61839099c
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Tue Dec 6 16:34:33 2022 +0800

    Merge pull request #10741 from supabase/master

    Prod deploy Dashboard

commit d264d528c0
Merge: d57120989 3aca10d35
Author: Alaister Young <alaister@users.noreply.github.com>
Date:   Sat Dec 3 01:55:29 2022 +1100

    Merge pull request #10687 from supabase/hotfix/key-functions-usage

    hotfix: key for functions usage

commit 3aca10d35e
Author: Alaister Young <a@alaisteryoung.com>
Date:   Fri Dec 2 14:38:49 2022 +0000

    hotfix: key for functions usage

commit d571209895
Merge: d0614755c 902039693
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Fri Dec 2 00:04:56 2022 +0800

    Merge pull request #10654 from supabase/master

    Prod deploy Dashboard

commit d0614755ca
Merge: 70069f86b 448c85a41
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Tue Nov 29 19:17:43 2022 +0800

    Merge pull request #10601 from supabase/master

    Prod deploy dashboard

commit 70069f86b3
Merge: a3c72a6ec 8c6ddaf6e
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Thu Nov 24 17:45:54 2022 +0800

    Merge pull request #10506 from supabase/master

    Prod deploy dashboard

commit a3c72a6ec0
Merge: a67f60a30 e281ce19b
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Wed Nov 23 17:06:39 2022 +0800

    Merge pull request #10476 from supabase/master

    Prod deploy Dashboard

commit a67f60a30b
Merge: 0094acc41 e7b0f5b82
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Tue Nov 22 16:49:25 2022 +0800

    Merge pull request #10454 from supabase/master

    Prod deploy Dashboard

commit 0094acc419
Merge: 3723e1feb a74d43f99
Author: Alaister Young <alaister@users.noreply.github.com>
Date:   Thu Nov 17 15:57:36 2022 +1100

    Merge pull request #10377 from supabase/master

    Prod deploy Dashboard

commit 3723e1feb4
Merge: e8ebf80f5 e3ac9e193
Author: Alaister Young <alaister@users.noreply.github.com>
Date:   Thu Nov 17 15:04:48 2022 +1100

    Merge pull request #10347 from supabase/master

    Prod deploy Dashboard

commit e8ebf80f55
Merge: b48bb12e7 a8aa06c0d
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Tue Nov 15 16:52:53 2022 +0800

    Merge pull request #10335 from supabase/master

    Prod deploy Dashboard

commit b48bb12e7b
Merge: ce5a8cd02 5836ba8a8
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Mon Nov 14 13:40:29 2022 +0800

    Merge pull request #10302 from supabase/master

    Prod deploy Dashboard

commit ce5a8cd023
Merge: 8f808477a 65bd1ccac
Author: Terry Sutton <saltcod@gmail.com>
Date:   Thu Nov 10 09:45:25 2022 -0330

    Merge pull request #10240 from supabase/master

    Fix project deletion survey

commit 8f808477a8
Merge: 0143b5124 81f2cb4cb
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Thu Nov 10 14:32:59 2022 +0800

    Merge pull request #10234 from supabase/master

    Prod deploy Dashboard

commit 0143b51247
Merge: a9be5e249 1c46c54e3
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Tue Nov 8 16:50:55 2022 +0800

    Merge pull request #10173 from supabase/master

    Prod deploy Dashboard

commit a9be5e2491
Merge: 1d92980f9 465d0de86
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Thu Nov 3 15:32:54 2022 +0700

    Merge pull request #10053 from supabase/master

    Prod deploy Dashboard

commit 1d92980f9a
Merge: ead80f150 3a1d8ab8e
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Wed Nov 2 11:53:35 2022 +0700

    Merge pull request #9998 from supabase/master

    Prod deploy dashboard

commit ead80f150c
Merge: e031dcc3c bd72dc459
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Tue Nov 1 16:05:48 2022 +0700

    Merge pull request #9995 from supabase/master

    Prod deploy Dashboard

commit e031dcc3cd
Merge: e00c98294 4f90176fb
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Thu Oct 27 13:07:33 2022 +0700

    Merge pull request #9885 from supabase/master

    Prod deploy Dashboard

commit e00c982946
Merge: fb59122c3 6c472fc31
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Tue Oct 25 13:10:20 2022 +0700

    Merge pull request #9797 from supabase/master

    Studio Prod Deploy

commit fb59122c3e
Merge: 96f7ccc32 09fa366e6
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Thu Oct 20 12:15:15 2022 +0700

    Merge pull request #9694 from supabase/master

    Prod deploy Dashboard

commit 96f7ccc322
Merge: 859327c81 37a116b5e
Author: Jonathan Summers-Muir <MildTomato@users.noreply.github.com>
Date:   Wed Oct 19 12:22:50 2022 +0800

    Merge pull request #9664 from supabase/master

    Prod deploy

commit 859327c816
Merge: e968cdf7a 477508d3d
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Tue Oct 18 13:39:39 2022 +0800

    Merge pull request #9635 from supabase/master

    Prod deploy for Dashboard

commit e968cdf7ae
Merge: aaceb4fb4 b5178bb90
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Mon Oct 17 16:38:24 2022 +0800

    Merge pull request #9610 from supabase/master

    Studio prod deploy

commit aaceb4fb4a
Merge: da8cf6f5e 9ca18cee9
Author: Alaister Young <alaister@users.noreply.github.com>
Date:   Thu Oct 13 20:08:31 2022 +1100

    Merge pull request #9521 from supabase/master

    Prod studio deploy

commit da8cf6f5ef
Merge: fac5397ac 465a84d8c
Author: Alaister Young <alaister@users.noreply.github.com>
Date:   Thu Oct 13 19:46:48 2022 +1100

    Merge pull request #9515 from supabase/master

    Prod studio deploy

commit fac5397acf
Merge: 29fb072c1 2d9ff657c
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Tue Oct 11 16:16:32 2022 +0800

    Merge pull request #9392 from supabase/master

    Studio deploy

commit 29fb072c17
Merge: 3f6a61ed1 f01616053
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Thu Oct 6 13:29:57 2022 +0800

    Merge pull request #9364 from supabase/master

    Prod deploy Studio

commit 3f6a61ed13
Merge: 60b095a08 c0d059e45
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Tue Oct 4 17:18:10 2022 +0800

    Merge pull request #9321 from supabase/master

    Prod deploy Studio

commit 60b095a08e
Merge: a7e9cf50b e96f6f472
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Tue Oct 4 13:04:25 2022 +0800

    Merge pull request #9316 from supabase/master

    Prod deploy Studio

commit a7e9cf50b2
Merge: d45bb7303 dcca02e4d
Author: Alaister Young <alaister@users.noreply.github.com>
Date:   Sun Oct 2 21:43:52 2022 +1100

    Merge pull request #9280 from supabase/master

    Prod deploy Studio

commit d45bb73031
Merge: b5f2259d0 1bf3e90b3
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Thu Sep 29 15:08:49 2022 +0800

    Merge pull request #9208 from supabase/master

    Prod deploy Studio

commit b5f2259d0f
Merge: ff192a2b1 8e6c30d1d
Author: Joshen Lim <joshenlimek@gmail.com>
Date:   Tue Sep 27 12:12:02 2022 +0800

    Merge pull request #9156 from supabase/master

    Prod deploy Studio
2023-06-13 17:05:04 +10:00

1030 lines
36 KiB
TypeScript

import Papa from 'papaparse'
import { makeObservable, observable } from 'mobx'
import { find, isUndefined, isEqual, isEmpty, chunk } from 'lodash'
import { Query } from 'components/grid/query/Query'
import type {
PostgresColumn,
PostgresTable,
PostgresRelationship,
PostgresPrimaryKey,
PostgresSchema,
} from '@supabase/postgres-meta'
import { IS_PLATFORM, API_URL } from 'lib/constants'
import { post } from 'lib/common/fetch'
import { timeout, tryParseJson } from 'lib/helpers'
import { ResponseError } from 'types'
import { IRootStore } from '../RootStore'
import ColumnStore from './ColumnStore'
import SchemaStore from './SchemaStore'
import TableStore, { ITableStore } from './TableStore'
import OpenApiStore, { IOpenApiStore } from './OpenApiStore'
import { IPostgresMetaInterface } from '../common/PostgresMetaInterface'
import {
ColumnField,
CreateColumnPayload,
ExtendedPostgresRelationship,
UpdateColumnPayload,
} from 'components/interfaces/TableGridEditor/SidePanelEditor/SidePanelEditor.types'
import {
generateCreateColumnPayload,
generateUpdateColumnPayload,
} from 'components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnEditor.utils'
import { ImportContent } from 'components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/TableEditor.types'
import RolesStore, { IRolesStore } from './RolesStore'
import PoliciesStore from './PoliciesStore'
import TriggersStore from './TriggersStore'
import PublicationStore from './PublicationStore'
import FunctionsStore from './FunctionsStore'
import HooksStore from './HooksStore'
import ExtensionsStore from './ExtensionsStore'
import TypesStore from './TypesStore'
import ForeignTableStore, { IForeignTableStore } from './ForeignTableStore'
import ViewStore, { IViewStore } from './ViewStore'
import MaterializedViewStore, { IMaterializedViewStore } from './MaterializedViewStore'
import { FOREIGN_KEY_DELETION_ACTION } from 'data/database/database-query-constants'
const BATCH_SIZE = 1000
const CHUNK_SIZE = 1024 * 1024 * 0.1 // 0.1MB
export interface IMetaStore {
excludedSchemas: string[]
openApi: IOpenApiStore
tables: ITableStore
columns: IPostgresMetaInterface<PostgresColumn>
schemas: IPostgresMetaInterface<PostgresSchema>
views: IViewStore
materializedViews: IMaterializedViewStore
foreignTables: IForeignTableStore
hooks: IPostgresMetaInterface<any>
roles: IRolesStore
policies: IPostgresMetaInterface<any>
triggers: IPostgresMetaInterface<any>
functions: IPostgresMetaInterface<any>
extensions: IPostgresMetaInterface<any>
publications: IPostgresMetaInterface<any>
types: IPostgresMetaInterface<any>
projectRef?: string
query: (value: string) => Promise<any | { error: ResponseError }>
validateQuery: (value: string) => Promise<any | { error: ResponseError }>
formatQuery: (value: string) => Promise<any | { error: ResponseError }>
/** The methods below are basically just queries but may be supported directly
* from the pg-meta library in the future */
addPrimaryKey: (
schema: string,
table: string,
columns: string[]
) => Promise<any | { error: ResponseError }>
removePrimaryKey: (schema: string, table: string) => Promise<any | { error: ResponseError }>
addForeignKey: (
relationship: ExtendedPostgresRelationship
) => Promise<any | { error: ResponseError }>
removeForeignKey: (
relationship: Partial<PostgresRelationship>
) => Promise<any | { error: ResponseError }>
/** The methods below involve several contexts due to the UI flow of the
* dashboard and hence do not sit within their own stores */
createColumn: (
payload: CreateColumnPayload,
selectedTable: PostgresTable,
foreignKey?: ExtendedPostgresRelationship,
securityConfiguration?: { isEncrypted: boolean; keyId?: string; keyName?: string }
) => any
updateColumn: (
id: string,
payload: UpdateColumnPayload,
selectedTable: PostgresTable,
foreignKey?: ExtendedPostgresRelationship,
skipPKCreation?: boolean,
skipSuccessMessage?: boolean
) => any
duplicateTable: (
payload: any,
metadata: {
duplicateTable: PostgresTable
isRLSEnabled: boolean
isRealtimeEnabled: boolean
isDuplicateRows: boolean
}
) => void
createTable: (
toastId: string,
payload: any,
columns: ColumnField[],
isRLSEnabled: boolean,
isRealtimeEnabled: boolean,
importContent?: ImportContent
) => any
updateTable: (
toastId: string,
table: PostgresTable,
payload: any,
columns: ColumnField[],
isRealtimeEnabled: boolean
) => any
insertRowsViaSpreadsheet: (
file: any,
table: PostgresTable,
selectedHeaders: string[],
onProgressUpdate: (progress: number) => void
) => void
insertTableRows: (
table: PostgresTable,
rows: any,
selectedHeaders: string[],
onProgressUpdate: (progress: number) => void
) => any
setProjectDetails: (details: { ref: string; connectionString?: string }) => void
}
export default class MetaStore implements IMetaStore {
rootStore: IRootStore
openApi: OpenApiStore
tables: TableStore
columns: ColumnStore
schemas: SchemaStore
views: ViewStore
materializedViews: MaterializedViewStore
foreignTables: ForeignTableStore
hooks: HooksStore
roles: RolesStore
policies: PoliciesStore
triggers: TriggersStore
functions: FunctionsStore
extensions: ExtensionsStore
publications: PublicationStore
types: TypesStore
projectRef?: string
connectionString?: string
baseUrl: string
headers: { [prop: string]: any }
// [Joshen] I'm going to treat this as a list of system schemas
excludedSchemas = [
'auth',
'extensions',
'information_schema',
'net',
'pgsodium',
'pgsodium_masks',
'pgbouncer',
'pgtle',
'realtime',
'storage',
'supabase_functions',
'supabase_migrations',
'vault',
'graphql',
'graphql_public',
]
constructor(rootStore: IRootStore, options: { projectRef: string; connectionString?: string }) {
const { projectRef, connectionString } = options
this.rootStore = rootStore
this.projectRef = projectRef
this.baseUrl = `${API_URL}/pg-meta/${projectRef}`
this.headers = {}
if (IS_PLATFORM && connectionString) {
this.connectionString = connectionString
this.headers['x-connection-encrypted'] = connectionString
}
this.openApi = new OpenApiStore(
this.rootStore,
`${API_URL}/projects/${this.projectRef}/api/rest`
)
this.tables = new TableStore(this.rootStore, `${this.baseUrl}/tables`, this.headers)
this.columns = new ColumnStore(this.rootStore, `${this.baseUrl}/columns`, this.headers)
this.schemas = new SchemaStore(this.rootStore, `${this.baseUrl}/schemas`, this.headers)
this.views = new ViewStore(this.rootStore, `${this.baseUrl}/views`, this.headers)
this.materializedViews = new MaterializedViewStore(
this.rootStore,
`${this.baseUrl}/materialized-views`,
this.headers
)
this.foreignTables = new ForeignTableStore(
this.rootStore,
`${this.baseUrl}/foreign-tables`,
this.headers
)
this.roles = new RolesStore(this.rootStore, `${this.baseUrl}/roles`, this.headers)
this.policies = new PoliciesStore(this.rootStore, `${this.baseUrl}/policies`, this.headers)
this.hooks = new HooksStore(this.rootStore, `${this.baseUrl}/triggers`, this.headers)
this.triggers = new TriggersStore(this.rootStore, `${this.baseUrl}/triggers`, this.headers)
this.functions = new FunctionsStore(this.rootStore, `${this.baseUrl}/functions`, this.headers)
this.extensions = new ExtensionsStore(
this.rootStore,
`${this.baseUrl}/extensions`,
this.headers,
{
identifier: 'name',
}
)
this.publications = new PublicationStore(
this.rootStore,
`${this.baseUrl}/publications`,
this.headers
)
this.types = new TypesStore(this.rootStore, `${this.baseUrl}/types`, this.headers)
makeObservable(this, {
excludedSchemas: observable,
})
}
/**
* Sends a database query
*/
async query(value: string) {
try {
const headers: any = { 'Content-Type': 'application/json' }
if (this.connectionString) headers['x-connection-encrypted'] = this.connectionString
const url = `${this.baseUrl}/query`
const response = await post(url, { query: value }, { headers })
if (response.error) throw response.error
return response
} catch (error: any) {
return { error }
}
}
async validateQuery(value: string) {
try {
const headers: any = { 'Content-Type': 'application/json' }
if (this.connectionString) headers['x-connection-encrypted'] = this.connectionString
const url = `${this.baseUrl}/query/validate`
const response = await post(url, { query: value }, { headers })
if (response.error) throw response.error
return response
} catch (error: any) {
return { error }
}
}
async formatQuery(value: string) {
try {
const headers: any = { 'Content-Type': 'application/json' }
if (this.connectionString) headers['x-connection-encrypted'] = this.connectionString
const url = `${this.baseUrl}/query/format`
const response = await post(url, { query: value }, { headers })
if (response.error) throw response.error
return response
} catch (error: any) {
return { error }
}
}
async addPrimaryKey(schema: string, table: string, columns: string[]) {
const primaryKeyColumns = columns.join('","')
const query = `ALTER TABLE "${schema}"."${table}" ADD PRIMARY KEY ("${primaryKeyColumns}")`
return await this.query(query)
}
async removePrimaryKey(schema: string, table: string) {
const query = `ALTER TABLE "${schema}"."${table}" DROP CONSTRAINT "${table}_pkey"`
return await this.query(query)
}
// [Joshen TODO] Eventually need to extend this to composite foreign keys
async addForeignKey(relationship: ExtendedPostgresRelationship) {
const { deletion_action } = relationship
const deletionAction =
deletion_action === FOREIGN_KEY_DELETION_ACTION.CASCADE
? 'ON DELETE CASCADE'
: deletion_action === FOREIGN_KEY_DELETION_ACTION.RESTRICT
? 'ON DELETE RESTRICT'
: deletion_action === FOREIGN_KEY_DELETION_ACTION.SET_DEFAULT
? 'ON DELETE SET DEFAULT'
: deletion_action === FOREIGN_KEY_DELETION_ACTION.SET_NULL
? 'ON DELETE SET NULL'
: ''
const query = `
ALTER TABLE "${relationship.source_schema}"."${relationship.source_table_name}"
ADD CONSTRAINT "${relationship.source_table_name}_${relationship.source_column_name}_fkey"
FOREIGN KEY ("${relationship.source_column_name}")
REFERENCES "${relationship.target_table_schema}"."${relationship.target_table_name}" ("${relationship.target_column_name}") ${deletionAction};
`
.replace(/\s+/g, ' ')
.trim()
return await this.query(query)
}
async removeForeignKey(relationship: Partial<PostgresRelationship>) {
const constraintName =
relationship.constraint_name ||
`${relationship.source_table_name}_${relationship.source_column_name}_fkey`
const query = `
ALTER TABLE "${relationship.source_schema}"."${relationship.source_table_name}"
DROP CONSTRAINT IF EXISTS "${constraintName}"
`
.replace(/\s+/g, ' ')
.trim()
return await this.query(query)
}
async updateTableRealtime(table: PostgresTable, enable: boolean) {
let publicationUpdateError
const publications = this.publications.list()
const publicTables = this.tables.list((table: PostgresTable) => table.schema === 'public')
let realtimePublication = publications.find((pub) => pub.name === 'supabase_realtime')
if (realtimePublication === undefined) {
const { data: publication, error: publicationCreateError } = await this.publications.create({
name: 'supabase_realtime',
publish_insert: true,
publish_update: true,
publish_delete: true,
tables: [],
})
if (publicationCreateError) throw publicationCreateError
realtimePublication = publication
}
const { id, tables: publicationTables } = realtimePublication
if (publicationTables === null) {
// UI doesn't have support for toggling realtime for ALL tables
// Switch it to individual tables via an array of strings
// Refer to PublicationStore for more information about this
const realtimeTables = enable
? publicTables.map((t: any) => `${t.schema}.${t.name}`)
: publicTables
.filter((t: any) => t.id !== table.id)
.map((t: any) => `${t.schema}.${t.name}`)
const { error } = await this.publications.update(id, { tables: realtimeTables })
publicationUpdateError = error
} else {
const isAlreadyEnabled = publicationTables.some((x: any) => x.id == table.id)
const realtimeTables =
isAlreadyEnabled && !enable
? // Toggle realtime off
publicationTables
.filter((t: any) => t.id !== table.id)
.map((t: any) => `${t.schema}.${t.name}`)
: !isAlreadyEnabled && enable
? // Toggle realtime on
[`${table.schema}.${table.name}`].concat(
publicationTables.map((t: any) => `${t.schema}.${t.name}`)
)
: null
if (realtimeTables === null) return
const payload = { id, tables: realtimeTables }
const { error } = await this.publications.update(id, payload)
publicationUpdateError = error
}
if (publicationUpdateError) throw publicationUpdateError
}
async createColumn(
payload: CreateColumnPayload,
selectedTable: PostgresTable,
foreignKey?: ExtendedPostgresRelationship,
securityConfiguration?: { isEncrypted: boolean; keyId?: string; keyName?: string }
) {
const toastId = this.rootStore.ui.setNotification({
category: 'loading',
message: `Creating column "${payload.name}"...`,
})
try {
// Once pg-meta supports composite keys, we can remove this logic
const { isPrimaryKey, ...formattedPayload } = payload
const column: any = await this.columns.create(formattedPayload)
if (column.error) throw column.error
// Firing createColumn in createTable will bypass this block
if (isPrimaryKey) {
this.rootStore.ui.setNotification({
id: toastId,
category: 'loading',
message: 'Assigning primary key to column...',
})
// Same logic in createTable: Remove any primary key constraints first (we'll add it back later)
// @ts-ignore
const existingPrimaryKeys = selectedTable.primary_keys.map((x) => x.name)
if (existingPrimaryKeys.length > 0) {
const removePK = await this.removePrimaryKey(column.schema, column.table)
if (removePK.error) throw removePK.error
}
const primaryKeyColumns = existingPrimaryKeys.concat([column.name])
const addPK = await this.addPrimaryKey(column.schema, column.table, primaryKeyColumns)
if (addPK.error) throw addPK.error
}
if (!isUndefined(foreignKey)) {
this.rootStore.ui.setNotification({
id: toastId,
category: 'loading',
message: 'Adding foreign key to column...',
})
const relation: any = await this.addForeignKey(foreignKey)
if (relation.error) throw relation.error
}
const { isEncrypted, keyId, keyName } = securityConfiguration || {}
if (isEncrypted) {
this.rootStore.ui.setNotification({
id: toastId,
category: 'loading',
message: 'Encrypting column...',
})
let encryptionKey = keyId
if (keyId === 'create-new') {
const addKeyRes = await this.rootStore.vault.addKey(keyName)
if (addKeyRes.error) throw addKeyRes.error
else encryptionKey = addKeyRes[0].id
}
if (encryptionKey !== undefined) {
const encryptColumnRes = await this.rootStore.vault.encryptColumn(column, encryptionKey)
if (encryptColumnRes.error) throw encryptColumnRes.error
}
}
this.rootStore.ui.setNotification({
id: toastId,
category: 'success',
message: `Successfully created column "${column.name}"`,
})
} catch (error: any) {
this.rootStore.ui.setNotification({
id: toastId,
category: 'error',
message: `An error occurred while creating the column "${payload.name}"`,
})
return { error }
}
}
async updateColumn(
id: string,
payload: UpdateColumnPayload,
selectedTable: PostgresTable,
foreignKey?: ExtendedPostgresRelationship,
skipPKCreation?: boolean,
skipSuccessMessage: boolean = false
) {
try {
const { isPrimaryKey, ...formattedPayload } = payload
const column: any = await this.columns.update(id, formattedPayload)
if (column.error) throw column.error
const originalColumn = find(selectedTable.columns, { id })
const existingForeignKey = find(selectedTable.relationships, {
source_column_name: originalColumn!.name,
})
if (!skipPKCreation && isPrimaryKey !== undefined) {
const existingPrimaryKeys = selectedTable.primary_keys.map((x) => x.name)
// Primary key is getting updated for the column
if (existingPrimaryKeys.length > 0) {
const removePK = await this.removePrimaryKey(column.schema, column.table)
if (removePK.error) throw removePK.error
}
const primaryKeyColumns = isPrimaryKey
? existingPrimaryKeys.concat([column.name])
: existingPrimaryKeys.filter((x) => x !== column.name)
if (primaryKeyColumns.length) {
const addPK = await this.addPrimaryKey(column.schema, column.table, primaryKeyColumns)
if (addPK.error) throw addPK.error
}
}
// For updating of foreign key relationship, we remove the original one by default
// Then just add whatever was in foreignKey - simplicity over trying to derive whether to update or not
if (existingForeignKey !== undefined) {
const relation: any = await this.removeForeignKey(existingForeignKey)
if (relation.error) throw relation.error
}
if (foreignKey !== undefined) {
const relation: any = await this.addForeignKey(foreignKey)
if (relation.error) throw relation.error
}
if (!skipSuccessMessage) {
this.rootStore.ui.setNotification({
category: 'success',
message: `Successfully updated column "${column.name}"`,
})
}
} catch (error: any) {
return { error }
}
}
async duplicateTable(
payload: any,
metadata: {
duplicateTable: PostgresTable
isRLSEnabled: boolean
isRealtimeEnabled: boolean
isDuplicateRows: boolean
}
) {
const { duplicateTable, isRLSEnabled, isRealtimeEnabled, isDuplicateRows } = metadata
const { name: sourceTableName, schema: sourceTableSchema } = duplicateTable
const duplicatedTableName = payload.name
// The following query will copy the structure of the table along with indexes, constraints and
// triggers. However, foreign key constraints are not duplicated over - has to be done separately
const table = await this.rootStore.meta.query(
`CREATE TABLE "${sourceTableSchema}"."${duplicatedTableName}" (LIKE "${sourceTableSchema}"."${sourceTableName}" INCLUDING ALL);`
)
if (table.error) throw table.error
// Duplicate foreign key constraints over
const relationships = duplicateTable.relationships
if (relationships.length > 0) {
// @ts-ignore
relationships.map(async (relationship: PostgresRelationship) => {
const relation = await this.rootStore.meta.addForeignKey({
...relationship,
source_table_name: duplicatedTableName,
deletion_action: FOREIGN_KEY_DELETION_ACTION.NO_ACTION,
})
if (relation.error) throw relation.error
})
}
// Duplicate rows if needed
if (isDuplicateRows) {
const rows = await this.rootStore.meta.query(
`INSERT INTO "${sourceTableSchema}"."${duplicatedTableName}" SELECT * FROM "${sourceTableSchema}"."${sourceTableName}";`
)
if (rows.error) throw rows.error
// Insert into does not copy over auto increment sequences, so we manually do it next if any
const columns = duplicateTable.columns
// @ts-ignore
const identityColumns = columns.filter((column) => column.identity_generation !== null)
identityColumns.map(async (column) => {
const identity = await this.rootStore.meta.query(
`SELECT setval('"${sourceTableSchema}"."${duplicatedTableName}_${column.name}_seq"', (SELECT MAX("${column.name}") FROM "${sourceTableSchema}"."${sourceTableName}"));`
)
if (identity.error) throw identity.error
})
}
await this.tables.load()
const tables = this.tables.list()
const duplicatedTable = find(tables, { schema: sourceTableSchema, name: duplicatedTableName })
if (isRLSEnabled) {
const updateTable: any = await this.tables.update(duplicatedTable!.id, {
rls_enabled: isRLSEnabled,
})
if (updateTable.error) throw updateTable.error
}
if (isRealtimeEnabled && duplicatedTable) await this.updateTableRealtime(duplicatedTable, true)
return duplicatedTable
}
async createTable(
toastId: string,
payload: any,
columns: ColumnField[] = [],
isRLSEnabled: boolean,
isRealtimeEnabled: boolean,
importContent?: ImportContent
) {
// Create the table first
const table: any = await this.tables.create(payload)
if (table.error) throw table.error
// If we face any errors during this process after the actual table creation
// We'll delete the table as a way to clean up and not leave behind bits that
// got through successfully. This is so that the user can continue editing in
// the table side panel editor conveniently
try {
// Toggle RLS if configured to be
if (isRLSEnabled) {
const updatedTable: any = await this.tables.update(table.id, {
rls_enabled: isRLSEnabled,
})
if (updatedTable.error) throw updatedTable.error
}
// Toggle Realtime if configured to be
if (isRealtimeEnabled) await this.updateTableRealtime(table, true)
// Then insert the columns - we don't do Promise.all as we want to keep the integrity
// of the column order during creation. Note that we add primary key constraints separately
// via the query endpoint to support composite primary keys as pg-meta does not support that OOB
this.rootStore.ui.setNotification({
id: toastId,
category: 'loading',
message: `Adding ${columns.length} columns to ${table.name}...`,
})
for (const column of columns) {
// We create all columns without primary keys first
const columnPayload = generateCreateColumnPayload(table.id, {
...column,
isPrimaryKey: false,
})
const newColumn: any = await this.columns.create(columnPayload)
if (newColumn.error) throw newColumn.error
}
// Then add the primary key constraints here to support composite keys
const primaryKeyColumns = columns
.filter((column: ColumnField) => column.isPrimaryKey)
.map((column: ColumnField) => column.name)
if (primaryKeyColumns.length > 0) {
const primaryKeys = await this.addPrimaryKey(table.schema, table.name, primaryKeyColumns)
if (primaryKeys.error) throw primaryKeys.error
}
// Then add the foreign key constraints here
for (const column of columns) {
if (!isUndefined(column.foreignKey)) {
const relationship = await this.addForeignKey(column.foreignKey)
if (relationship.error) throw relationship.error
}
}
// If the user is importing data via a spreadsheet
if (!isUndefined(importContent)) {
if (importContent.file && importContent.rowCount > 0) {
// Via a CSV file
const { error }: any = await this.insertRowsViaSpreadsheet(
importContent.file,
table,
importContent.selectedHeaders,
(progress: number) => {
this.rootStore.ui.setNotification({
id: toastId,
progress,
category: 'loading',
message: `Adding ${importContent.rowCount.toLocaleString()} rows to ${table.name}`,
})
}
)
// For identity columns, manually raise the sequences
const identityColumns = columns.filter((column) => column.isIdentity)
for (const column of identityColumns) {
const identity = await this.rootStore.meta.query(
`SELECT setval('${table.name}_${column.name}_seq', (SELECT MAX("${column.name}") FROM "${table.name}"));`
)
if (identity.error) throw identity.error
}
if (!isUndefined(error)) {
this.rootStore.ui.setNotification({
category: 'error',
message: 'Do check your spreadsheet if there are any discrepancies.',
})
this.rootStore.ui.setNotification({
category: 'error',
message: `Table ${table.name} has been created but we ran into an error while inserting rows:
${error.message}`,
error,
})
}
} else {
// Via text copy and paste
await this.insertTableRows(
table,
importContent.rows,
importContent.selectedHeaders,
(progress: number) => {
this.rootStore.ui.setNotification({
id: toastId,
progress,
category: 'loading',
message: `Adding ${importContent.rows.length.toLocaleString()} rows to ${
table.name
}`,
})
}
)
// For identity columns, manually raise the sequences
const identityColumns = columns.filter((column) => column.isIdentity)
for (const column of identityColumns) {
const identity = await this.rootStore.meta.query(
`SELECT setval('${table.name}_${column.name}_seq', (SELECT MAX("${column.name}") FROM "${table.name}"));`
)
if (identity.error) throw identity.error
}
}
}
// Finally, return the created table
return await this.tables.loadById(table.id)
} catch (error: any) {
this.tables.del(table.id)
throw error
}
}
async updateTable(
toastId: string,
table: PostgresTable,
payload: any,
columns: ColumnField[],
isRealtimeEnabled: boolean
) {
// Prepare a check to see if primary keys to the tables were updated or not
const primaryKeyColumns = columns
.filter((column) => column.isPrimaryKey)
.map((column) => column.name)
// @ts-ignore
const existingPrimaryKeyColumns = table.primary_keys.map((pk: PostgresPrimaryKey) => pk.name)
const isPrimaryKeyUpdated = !isEqual(primaryKeyColumns, existingPrimaryKeyColumns)
if (isPrimaryKeyUpdated) {
// Remove any primary key constraints first (we'll add it back later)
// If we do it later, and if the user deleted a PK column, we'd need to do
// an additional check when removing PK if the column in the PK was removed
// So doing this one step earlier, lets us skip that additional check.
if (table.primary_keys.length > 0) {
const removePK = await this.removePrimaryKey(table.schema, table.name)
if (removePK.error) throw removePK.error
}
}
// Update the table
const updatedTable: any = await this.tables.update(table.id, payload)
if (updatedTable.error) throw updatedTable.error
const originalColumns = table.columns
const columnIds = columns.map((column) => column.id)
// Delete any removed columns
// @ts-ignore
const columnsToRemove = originalColumns.filter((column) => !columnIds.includes(column.id))
for (const column of columnsToRemove) {
this.rootStore.ui.setNotification({
id: toastId,
category: 'loading',
message: `Removing column ${column.name} from ${updatedTable.name}`,
})
const deletedColumn: any = await this.columns.del(column.id)
if (deletedColumn.error) throw deletedColumn.error
}
// Add any new columns / Update any existing columns
let hasError = false
for (const column of columns) {
if (!column.id.includes(table.id.toString())) {
this.rootStore.ui.setNotification({
id: toastId,
category: 'loading',
message: `Adding column ${column.name} to ${updatedTable.name}`,
})
// Ensure that columns do not created as primary key first, cause the primary key will
// be added later on further down in the code
const columnPayload = generateCreateColumnPayload(updatedTable.id, {
...column,
isPrimaryKey: false,
})
await this.createColumn(columnPayload, updatedTable, column.foreignKey)
} else {
const originalColumn = find(originalColumns, { id: column.id })
if (originalColumn) {
const columnPayload = generateUpdateColumnPayload(originalColumn, updatedTable, column)
const originalForeignKey = find(table.relationships, {
source_schema: originalColumn.schema,
source_table_name: originalColumn.table,
source_column_name: originalColumn.name,
})
const hasForeignKeyUpdated = !isEqual(originalForeignKey, column.foreignKey)
if (!isEmpty(columnPayload) || hasForeignKeyUpdated) {
this.rootStore.ui.setNotification({
id: toastId,
category: 'loading',
message: `Updating column ${column.name} from ${updatedTable.name}`,
})
const skipPKCreation = true
const skipSuccessMessage = true
const res: any = await this.updateColumn(
column.id,
columnPayload,
updatedTable,
column.foreignKey,
skipPKCreation,
skipSuccessMessage
)
if (res?.error) {
hasError = true
this.rootStore.ui.setNotification({
category: 'error',
message: `Failed to update column "${column.name}": ${res.error.message}`,
})
}
}
}
}
}
// Then add back the primary keys again
if (isPrimaryKeyUpdated && primaryKeyColumns.length > 0) {
const primaryKeys = await this.addPrimaryKey(
updatedTable.schema,
updatedTable.name,
primaryKeyColumns
)
if (primaryKeys.error) throw primaryKeys.error
}
// Update table's realtime configuration
await this.updateTableRealtime(table, isRealtimeEnabled)
return { table: await this.tables.loadById(table.id), hasError }
}
async insertRowsViaSpreadsheet(
file: any,
table: PostgresTable,
selectedHeaders: string[],
onProgressUpdate: (progress: number) => void
) {
let chunkNumber = 0
let insertError: any = undefined
const t1: any = new Date()
return new Promise((resolve) => {
Papa.parse(file, {
header: true,
dynamicTyping: true,
skipEmptyLines: true,
chunkSize: CHUNK_SIZE,
quoteChar: file.type === 'text/tab-separated-values' ? '' : '"',
chunk: async (results: any, parser: any) => {
parser.pause()
const formattedData = results.data.map((row: any) => {
const formattedRow: any = {}
selectedHeaders.forEach((header) => {
const column = table.columns?.find((c) => c.name === header)
if (
(column?.data_type ?? '') === 'ARRAY' ||
(column?.format ?? '').includes('json')
) {
formattedRow[header] = tryParseJson(row[header])
} else {
formattedRow[header] = row[header]
}
})
return formattedRow
})
const insertQuery = new Query()
.from(table.name, table.schema)
.insert(formattedData)
.toSql()
const res = await this.query(insertQuery)
if (res.error) {
console.warn(res.error)
insertError = res.error
parser.abort()
} else {
chunkNumber += 1
const progress = (chunkNumber * CHUNK_SIZE) / file.size
const progressPercentage = progress > 1 ? 100 : progress * 100
onProgressUpdate(progressPercentage)
parser.resume()
}
},
complete: () => {
const t2: any = new Date()
console.log(`Total time taken for importing spreadsheet: ${(t2 - t1) / 1000} seconds`)
resolve({ error: insertError })
},
})
})
}
async insertTableRows(
table: PostgresTable,
rows: any,
selectedHeaders: string[],
onProgressUpdate: (progress: number) => void
) {
let insertError = undefined
let insertProgress = 0
const formattedRows = rows.map((row: any) => {
const formattedRow: any = {}
selectedHeaders.forEach((header) => {
const column = table.columns?.find((c) => c.name === header)
if ((column?.data_type ?? '') === 'ARRAY' || (column?.format ?? '').includes('json')) {
formattedRow[header] = tryParseJson(row[header])
} else {
formattedRow[header] = row[header]
}
})
return formattedRow
})
const batches = chunk(formattedRows, BATCH_SIZE)
const promises = batches.map((batch: any) => {
return () => {
return Promise.race([
new Promise(async (resolve, reject) => {
const insertQuery = new Query().from(table.name, table.schema).insert(batch).toSql()
const res = await this.query(insertQuery)
if (res.error) {
insertError = res.error
reject(res.error)
}
insertProgress = insertProgress + batch.length / rows.length
resolve({})
}),
timeout(30000),
])
}
})
const batchedPromises = chunk(promises, 10)
for (const batchedPromise of batchedPromises) {
const res = await Promise.allSettled(batchedPromise.map((batch) => batch()))
const hasFailedBatch = find(res, { status: 'rejected' })
if (hasFailedBatch) break
onProgressUpdate(insertProgress * 100)
}
return { error: insertError }
}
setProjectDetails({ ref, connectionString }: { ref: string; connectionString?: string }) {
this.projectRef = ref
this.baseUrl = `${API_URL}/pg-meta/${ref}`
if (IS_PLATFORM && connectionString) {
this.connectionString = connectionString
this.headers['x-connection-encrypted'] = connectionString
}
this.openApi.setUrl(`${API_URL}/projects/${this.projectRef}/api/rest`)
this.openApi.setHeaders(this.headers)
this.tables.setUrl(`${this.baseUrl}/tables`)
this.tables.setHeaders(this.headers)
this.columns.setUrl(`${this.baseUrl}/columns`)
this.columns.setHeaders(this.headers)
this.schemas.setUrl(`${this.baseUrl}/schemas`)
this.schemas.setHeaders(this.headers)
this.views.setUrl(`${this.baseUrl}/views`)
this.views.setHeaders(this.headers)
this.materializedViews.setUrl(`${this.baseUrl}/materialized-views`)
this.materializedViews.setHeaders(this.headers)
this.foreignTables.setUrl(`${this.baseUrl}/foreign-tables`)
this.foreignTables.setHeaders(this.headers)
this.roles.setUrl(`${this.baseUrl}/roles`)
this.roles.setHeaders(this.headers)
this.policies.setUrl(`${this.baseUrl}/policies`)
this.policies.setHeaders(this.headers)
this.hooks.setUrl(`${this.baseUrl}/triggers`)
this.hooks.setHeaders(this.headers)
this.triggers.setUrl(`${this.baseUrl}/triggers`)
this.triggers.setHeaders(this.headers)
this.functions.setUrl(`${this.baseUrl}/functions`)
this.functions.setHeaders(this.headers)
this.extensions.setUrl(`${this.baseUrl}/extensions`)
this.extensions.setHeaders(this.headers)
this.publications.setUrl(`${this.baseUrl}/publications`)
this.publications.setHeaders(this.headers)
this.types.setUrl(`${this.baseUrl}/types`)
this.types.setHeaders(this.headers)
}
}