mirror of
https://github.com/supabase/supabase.git
synced 2026-10-13 21:29:08 +03:00
commit61f4c6e585Merge:b7dabb3682fc053d32Author: 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 commit2fc053d323Author: Kevin Grüneberg <k.grueneberg1994@gmail.com> Date: Fri Jun 9 10:58:39 2023 +0200 chore(usage): add Realtime docs, improve timeframes, upsell commitb7dabb368dMerge:d9bbd6f37bf807a9c7Author: Terry Sutton <saltcod@gmail.com> Date: Thu Jun 8 12:47:46 2023 -0230 Merge pull request #14908 from supabase/master prod deploy commitd9bbd6f375Merge:2fff5f2cfe7c2bd61cAuthor: Terry Sutton <saltcod@gmail.com> Date: Thu Jun 8 12:18:09 2023 -0230 Merge pull request #14905 from supabase/master prod deploy commit2fff5f2cffMerge:814a745ef90deee74bAuthor: 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 commit814a745efcMerge:4c3735b68fb7a35fffAuthor: 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) commit4c3735b687Merge:c876cea30b94f5464dAuthor: 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 commitc876cea306Merge:aa640eee5ef7060729Author: 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 commitef70607290Author: Terry Sutton <saltcod@gmail.com> Date: Sun Jun 4 23:18:09 2023 -0230 Check if value is an object before returning it commitaa640eee5eMerge:02f18cbb5f48ae5ac5Author: 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 commit02f18cbb55Merge:3091a37496163981a0Author: 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 commit3091a3749dMerge:b5b2ce57230d3b473dAuthor: 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 commitb5b2ce572aMerge:fa3eacc36c462bb582Author: 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 commitc462bb582dAuthor: 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 commitfa3eacc363Merge:199a18b8f27fa8bfedAuthor: 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 commit199a18b8f3Merge:e73ecad8f335b4c205Author: 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 commit335b4c205cAuthor: Alaister Young <a@alaisteryoung.com> Date: Sat May 20 10:07:14 2023 +1000 hotfix: sql name updating commite73ecad8fdMerge:77ce8e37a8de91649bAuthor: 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… commit8de91649b2Author: 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 commit77ce8e37a7Merge:5f4e87fc1c809608dcAuthor: 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 commit5f4e87fc12Merge:a2ae6bc660f1254252Author: Joshen Lim <joshenlimek@gmail.com> Date: Wed May 17 15:23:55 2023 +0800 Merge pull request #14418 from supabase/master Prod deploy dashboard commita2ae6bc669Merge:9b4a07124eeb4846f4Author: Joshen Lim <joshenlimek@gmail.com> Date: Tue May 16 15:14:30 2023 +0800 Merge pull request #14386 from supabase/master Prod deploy dashboard commit9b4a071243Merge:e3eac9610bf3e02aa0Author: 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 commite3eac96105Merge:af8eb1ebc24ef3577cAuthor: 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 commitaf8eb1ebccMerge:f9358969e8769f7c19Author: 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 commitf9358969edMerge:78d2c2de7b5c6a54d7Author: Joshen Lim <joshenlimek@gmail.com> Date: Mon May 8 17:08:05 2023 +0800 Merge pull request #14200 from supabase/master Prod deploy dashboard commit78d2c2de73Merge:0f52967b3d730ea9caAuthor: Joshen Lim <joshenlimek@gmail.com> Date: Mon May 8 09:54:23 2023 +0800 Merge pull request #14148 from supabase/master Prod deploy dashboard commit0f52967b3eMerge:d8c07236b4ce82e7a5Author: Joshen Lim <joshenlimek@gmail.com> Date: Thu May 4 18:13:07 2023 +0800 Merge pull request #14121 from supabase/master Prod deploy dashboard commitd8c07236beMerge:0120c02a389827c208Author: Joshen Lim <joshenlimek@gmail.com> Date: Tue May 2 13:14:48 2023 +0800 Merge pull request #14067 from supabase/master Prod deploy dashboard commit0120c02a30Merge:745efc91a4bfa94f7aAuthor: Joshen Lim <joshenlimek@gmail.com> Date: Thu Apr 27 14:09:56 2023 +0800 Merge pull request #13993 from supabase/master Prod deploy dashboard commit745efc91a7Merge:ff6ea2ad4fd82ab26bAuthor: Joshen Lim <joshenlimek@gmail.com> Date: Tue Apr 25 14:25:45 2023 +0800 Merge pull request #13948 from supabase/master Prod deploy dashboard commitff6ea2ad48Merge:f4797757fc6ffaefb1Author: 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 commitc6ffaefb19Author: Joshen Lim <joshenlimek@gmail.com> Date: Tue Apr 25 01:24:21 2023 +0800 Remove log commit1067363578Author: Joshen Lim <joshenlimek@gmail.com> Date: Tue Apr 25 01:20:46 2023 +0800 Remove unnecessary prop commit9b9e6d7a43Author: 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 commitf4797757f3Merge:fedf6a14b6c1675129Author: 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 commit6c1675129dAuthor: phamhieu <phamhieu1998@gmail.com> Date: Thu Apr 20 18:35:41 2023 +0700 fix: sanitizePageViewRoute to remove instead of replace commitb08447b424Author: phamhieu <phamhieu1998@gmail.com> Date: Thu Apr 20 17:13:44 2023 +0700 fix: sanitize route before sending page_view event commit8245595ab3Author: phamhieu <phamhieu1998@gmail.com> Date: Thu Apr 20 16:31:51 2023 +0700 fix: page_view should use browser url commitfedf6a14b0Merge:42a180f8d9148c49cbAuthor: Joshen Lim <joshenlimek@gmail.com> Date: Thu Apr 20 13:35:24 2023 +0700 Merge pull request #13842 from supabase/master Prod deploy dashboard commit42a180f8d2Merge:01b9b4ae2e7c4c734eAuthor: 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 commite7c4c734e5Author: Alaister Young <a@alaisteryoung.com> Date: Wed Apr 19 10:53:32 2023 +1000 fix: usage endpoint null values commit01b9b4ae21Merge:8e0403422d9f7d2982Author: 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 commit8e04034221Merge:eaffed8f2e690e4557Author: 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 commite690e4557bAuthor: 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 commiteaffed8f20Merge:32ffce433071d4db8aAuthor: Joshen Lim <joshenlimek@gmail.com> Date: Fri Apr 14 18:29:42 2023 +0700 Merge pull request #13721 from supabase/master Prod deploy dashboard commit32ffce433cMerge:8b5044e389e6b23983Author: 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 commit9e6b239830Author: Joshen Lim <joshenlimek@gmail.com> Date: Fri Apr 14 10:56:51 2023 +0700 Remove wrong column removal at catch block commit8b5044e380Merge:bddc3a1c70a0202477Author: Joshen Lim <joshenlimek@gmail.com> Date: Thu Apr 13 15:00:19 2023 +0700 Merge pull request #13668 from supabase/master Prod deploy dashboard commitbddc3a1c79Merge:ad60ad2e69fe16dba5Author: Joshen Lim <joshenlimek@gmail.com> Date: Thu Apr 13 13:28:43 2023 +0700 Merge pull request #13665 from supabase/master Prod deploy dashboard commitad60ad2e63Merge:71d8fabad46bdcb4f7Author: Joshen Lim <joshenlimek@gmail.com> Date: Wed Apr 12 14:50:32 2023 +0700 Merge pull request #13633 from supabase/master Prod deploy dashboard commit71d8fabad4Merge:7b8a1d963412e9d3ddAuthor: Joshen Lim <joshenlimek@gmail.com> Date: Thu Apr 6 14:12:19 2023 +0800 Merge pull request #13482 from supabase/master Prod deploy dashboard commit7b8a1d963cMerge:52cc456cce1baff851Author: 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 commite1baff8517Author: Jonathan Summers-Muir <MildTomato@users.noreply.github.com> Date: Tue Apr 4 23:01:54 2023 +0800 Update _document.tsx commit52cc456ccbMerge:44993870fd41641405Author: Joshen Lim <joshenlimek@gmail.com> Date: Tue Apr 4 15:35:41 2023 +0800 Merge pull request #13415 from supabase/master Prod deploy dashboard commit44993870f5Merge:c745deddb0038f6312Author: Joshen Lim <joshenlimek@gmail.com> Date: Tue Apr 4 14:34:07 2023 +0800 Merge pull request #13413 from supabase/master Prod deploy dashboard commitc745deddb6Merge:99fed3d9309e2c21a7Author: Joshen Lim <joshenlimek@gmail.com> Date: Thu Mar 30 21:28:26 2023 +0800 Merge pull request #13320 from supabase/master Prod deploy dashboard commit99fed3d932Merge:d697289cfeefa3bf6dAuthor: Joshen Lim <joshenlimek@gmail.com> Date: Thu Mar 30 14:07:35 2023 +0800 Merge pull request #13309 from supabase/master Prod deploy dashboard commitd697289cf1Merge:13fdccb87e3f09fe6aAuthor: Joshen Lim <joshenlimek@gmail.com> Date: Wed Mar 29 18:31:17 2023 +0800 Merge pull request #13291 from supabase/master Prod deploy dashboard commit13fdccb87dMerge:dd42066bed441a0170Author: 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 commitdd42066beeMerge:df64b1a25c071ee624Author: Joshen Lim <joshenlimek@gmail.com> Date: Wed Mar 29 13:15:18 2023 +0800 Merge pull request #13282 from supabase/master Prod deploy dashboard commitdf64b1a251Merge:8bcdcca38099cf9192Author: Joshen Lim <joshenlimek@gmail.com> Date: Tue Mar 28 13:55:53 2023 +0800 Merge pull request #13252 from supabase/master Prod deploy dashboard commit8bcdcca38fMerge:8108ba4933b3598909Author: Joshen Lim <joshenlimek@gmail.com> Date: Mon Mar 27 13:38:34 2023 +0800 Merge pull request #13223 from supabase/master Prod deploy dashboard commit8108ba493fMerge:955e93087de20ff2a3Author: Joshen Lim <joshenlimek@gmail.com> Date: Thu Mar 23 15:13:51 2023 +0800 Merge pull request #13159 from supabase/master Prod deploy dashboard commit955e930879Merge:a0a0ef16dc1eca93c9Author: Joshen Lim <joshenlimek@gmail.com> Date: Wed Mar 22 15:20:24 2023 +0800 Merge pull request #13135 from supabase/master Prod deploy dashboard commita0a0ef16d1Merge:925a204bba71e4f736Author: 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 commita71e4f7361Author: Joshen Lim <joshenlimek@gmail.com> Date: Wed Mar 22 14:37:52 2023 +0800 Update default region to east us commit925a204bb3Merge:414190e2771af49c7dAuthor: Joshen Lim <joshenlimek@gmail.com> Date: Tue Mar 21 13:50:19 2023 +0800 Merge pull request #13118 from supabase/master Prod deploy Studio commit414190e27dMerge:f78a9add223678bc55Author: 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 commit23678bc55fAuthor: Div Arora <root@darora.com> Date: Wed Mar 15 06:40:18 2023 +0800 chore: re-enable support for use1 commitf78a9add2aMerge:03c6d296fee3f09199Author: 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 commitee3f091996Author: Joshen Lim <joshenlimek@gmail.com> Date: Tue Mar 14 09:39:03 2023 +0800 Hotfix changes from https://github.com/supabase/supabase/pull/12974 commit03c6d296f7Merge:a5bce12266e32e836bAuthor: 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 commit6e32e836b7Author: dragarcia <angelico.delosreyes@gmail.com> Date: Sat Mar 11 23:57:30 2023 +0800 hotfix: disable US east for project creation commita5bce1226cMerge:c20a9b240f3e3e0d00Author: Joshen Lim <joshenlimek@gmail.com> Date: Thu Mar 9 15:32:56 2023 +0800 Merge pull request #12904 from supabase/master Prod deploy dashboard commitc20a9b2401Author: Joshen Lim <joshenlimek@gmail.com> Date: Tue Mar 7 16:32:41 2023 +0800 Add region field for edge function details commitdabecd0c7bAuthor: Joshen Lim <joshenlimek@gmail.com> Date: Tue Mar 7 16:31:14 2023 +0800 Update import map field commit18ac80b6d4Author: 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 commit52bf4cff5bAuthor: 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 commitae003dd8f5Author: Joshen Lim <joshenlimek@gmail.com> Date: Wed Mar 1 20:48:07 2023 +0800 Add in additioanl configs for edge functions details commit8f1e96b222Merge:6c57994e7c484fc841Author: Joshen Lim <joshenlimek@gmail.com> Date: Tue Mar 7 17:05:34 2023 +0800 Merge pull request #12851 from supabase/master Prod deploy dashboard commit6c57994e7eMerge:92e72bac9b4244bf17Author: 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 commitb4244bf17dAuthor: Alaister Young <a@alaisteryoung.com> Date: Fri Mar 3 12:35:37 2023 +1100 fix: <RowContextMenu /> to use rows from react-query commit92e72bac9fMerge:b6953ba9e0befcd053Author: Joshen Lim <joshenlimek@gmail.com> Date: Thu Mar 2 15:35:20 2023 +0800 Merge pull request #12754 from supabase/master Prod deploy dashboard commitb6953ba9e1Merge:029c7bd960600e76d2Author: Joshen Lim <joshenlimek@gmail.com> Date: Wed Mar 1 12:26:12 2023 +0800 Merge pull request #12731 from supabase/master Prod deploy dashboard commit029c7bd96dMerge:0b72dd38ddc29557aeAuthor: Joshen Lim <joshenlimek@gmail.com> Date: Tue Feb 28 15:24:20 2023 +0800 Merge pull request #12714 from supabase/master Prod deploy dashboard commit0b72dd38dcMerge:74011e80e9c8cdc64dAuthor: Joshen Lim <joshenlimek@gmail.com> Date: Thu Feb 23 14:51:53 2023 +0800 Merge pull request #12620 from supabase/master Prod deploy dashboard commit74011e80edMerge:3b03a446e93c227556Author: Joshen Lim <joshenlimek@gmail.com> Date: Wed Feb 22 16:37:52 2023 +0800 Merge pull request #12597 from supabase/master Prod deploy commit3b03a446edMerge:e533c0d25907933225Author: Joshen Lim <joshenlimek@gmail.com> Date: Wed Feb 22 15:59:57 2023 +0800 Merge pull request #12595 from supabase/master Prod deploy Dashboard commite533c0d25fMerge:91c7ea8646a2ad6fcfAuthor: Joshen Lim <joshenlimek@gmail.com> Date: Tue Feb 21 14:26:33 2023 +0800 Merge pull request #12570 from supabase/master Prod deploy dashboard commit91c7ea864dMerge:6ed57849e418a50a73Author: Joshen Lim <joshenlimek@gmail.com> Date: Tue Feb 21 13:48:02 2023 +0800 Merge pull request #12568 from supabase/master Prod deploy Dashboard commit6ed57849eaMerge:e731b7716bb5d57da5Author: Joshen Lim <joshenlimek@gmail.com> Date: Mon Feb 20 15:17:37 2023 +0800 Merge pull request #12548 from supabase/master Prod deploy dashboard commite731b7716aMerge:515b56562ae3e1b89aAuthor: Joshen Lim <joshenlimek@gmail.com> Date: Thu Feb 16 16:30:42 2023 +0800 Merge pull request #12469 from supabase/master Prod deploy dashboard commit515b56562bMerge:49624c644f8700ff5cAuthor: Joshen Lim <joshenlimek@gmail.com> Date: Wed Feb 15 13:14:25 2023 +0800 Merge pull request #12431 from supabase/master Prod deploy dashboard commit49624c644fMerge:452fb689fe33555c4dAuthor: Joshen Lim <joshenlimek@gmail.com> Date: Tue Feb 14 15:22:30 2023 +0800 Merge pull request #12406 from supabase/master Prod deploy dashboard commit452fb689feMerge:74a75e39be663e0be0Author: Joshen Lim <joshenlimek@gmail.com> Date: Fri Feb 10 02:18:21 2023 +0800 Merge pull request #12297 from supabase/master Prod deploy dashboard commit74a75e39bdMerge:2b8d81bd1c6bcdc69cAuthor: Joshen Lim <joshenlimek@gmail.com> Date: Thu Feb 9 14:30:44 2023 +0800 Merge pull request #12280 from supabase/master Prod deploy dashboard commit2b8d81bd12Merge:77b356e59e730d9c34Author: Joshen Lim <joshenlimek@gmail.com> Date: Wed Feb 8 13:10:09 2023 +0800 Merge pull request #12219 from supabase/master Prod deploy dashboard commit77b356e596Merge:c20ed925a9d866bc8fAuthor: Joshen Lim <joshenlimek@gmail.com> Date: Tue Feb 7 14:54:48 2023 +0800 Merge pull request #12217 from supabase/master Prod deploy dashboard commitc20ed925adMerge:57eb4a234d8bc2a5f5Author: Joshen Lim <joshenlimek@gmail.com> Date: Thu Feb 2 15:45:15 2023 +0800 Merge pull request #12121 from supabase/master Prod deploy dashboard commit57eb4a2347Merge:08b4ce3cc5e0ec008cAuthor: 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"" commit5e0ec008c0Author: Joshen Lim <joshenlimek@gmail.com> Date: Tue Jan 31 15:19:24 2023 +0800 Update DisplayAPISettings commit372ac5ee75Author: Joshen Lim <joshenlimek@gmail.com> Date: Tue Jan 31 15:18:06 2023 +0800 Revert "Revert "Studio deploy"" commit08b4ce3cc3Merge:b0b953fccf2e253df7Author: 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" commitf2e253df7eAuthor: Joshen Lim <joshenlimek@gmail.com> Date: Tue Jan 31 14:25:18 2023 +0800 Revert "Studio deploy" commitb0b953fcc8Merge:fecb67fafd9846650eAuthor: Joshen Lim <joshenlimek@gmail.com> Date: Tue Jan 31 13:33:55 2023 +0800 Merge pull request #11987 from supabase/master Studio deploy commitfecb67fafbMerge:de0ab2458624afc1f9Author: 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 commit624afc1f9aAuthor: Jonathan Summers-Muir <MildTomato@users.noreply.github.com> Date: Sat Jan 28 04:57:55 2023 +0800 Update ExitSurvey.tsx commitde0ab24582Merge:6c1a5e16ca59f37482Author: Joshen Lim <joshenlimek@gmail.com> Date: Thu Jan 26 14:39:38 2023 +0800 Merge pull request #11933 from supabase/master Prod Deploy Dashboard commit6c1a5e16c2Merge:1d5ebd674c019be2d1Author: Joshen Lim <joshenlimek@gmail.com> Date: Tue Jan 24 14:51:39 2023 +0800 Merge pull request #11754 from supabase/master Prod Deploy Dashboard commit1d5ebd6748Merge:a2ba8279209dce53d1Author: Joshen Lim <joshenlimek@gmail.com> Date: Wed Jan 18 10:56:34 2023 +0800 Merge pull request #11699 from supabase/master Prod deploy dashboard commita2ba827926Merge:1206b98cd6ae28bdeeAuthor: Joshen Lim <joshenlimek@gmail.com> Date: Fri Jan 13 01:05:33 2023 +0800 Merge pull request #11606 from supabase/master Prod deploy dashboard commit1206b98cdeMerge:902aeb288d08312124Author: Joshen Lim <joshenlimek@gmail.com> Date: Wed Jan 11 14:29:50 2023 +0800 Merge pull request #11553 from supabase/master Prod deploy dashboard commit902aeb2884Merge:6b98c06962aa6a4a69Author: Joshen Lim <joshenlimek@gmail.com> Date: Tue Jan 3 13:05:47 2023 +0700 Merge pull request #11292 from supabase/master Prod deploy dashboard commit6b98c06968Merge:d31caddc3e50d736b3Author: Joshen Lim <joshenlimek@gmail.com> Date: Thu Dec 22 17:55:30 2022 +0700 Merge pull request #11186 from supabase/master Prod deploy dashboard commitd31caddc39Merge:fddc4ceedb40e6216aAuthor: Joshen Lim <joshenlimek@gmail.com> Date: Wed Dec 21 22:14:21 2022 +0700 Merge pull request #11170 from supabase/master Prod deploy dashboard commitfddc4ceedeMerge:58fe3de07ad300dfd3Author: Joshen Lim <joshenlimek@gmail.com> Date: Wed Dec 21 14:15:04 2022 +0700 Merge pull request #11110 from supabase/master Prod deploy dashboard commit58fe3de070Merge:4eecc991771a2888d0Author: Joshen Lim <joshenlimek@gmail.com> Date: Thu Dec 15 02:42:58 2022 +0700 Merge pull request #10983 from supabase/master Prod deploy dashboard commit4eecc99176Merge:94c499fe0f091fa666Author: Inian <inian1234@gmail.com> Date: Wed Dec 14 18:31:12 2022 +0800 Merge pull request #10957 from supabase/master commit94c499fe08Merge:fe5098842a7c9f25eaAuthor: Joshen Lim <joshenlimek@gmail.com> Date: Wed Dec 14 13:57:51 2022 +0700 Merge pull request #10950 from supabase/master Prod deploy dashboard commitfe50988422Merge:3505e9e91744ee0d86Author: Joshen Lim <joshenlimek@gmail.com> Date: Wed Dec 14 11:57:33 2022 +0700 Merge pull request #10910 from supabase/master Prod deploy dashboard commit3505e9e915Merge:b6d89178dcc3d379daAuthor: Joshen Lim <joshenlimek@gmail.com> Date: Tue Dec 13 17:21:32 2022 +0700 Merge pull request #10903 from supabase/master Prod deploy dashboard commitb6d89178d4Merge:52aa28bf8d93c85d7cAuthor: Joshen Lim <joshenlimek@gmail.com> Date: Tue Dec 13 12:41:37 2022 +0700 Merge pull request #10894 from supabase/master Prod deploy dashboard commit52aa28bf8bMerge:df66ff2c5c67b321eaAuthor: Joshen Lim <joshenlimek@gmail.com> Date: Thu Dec 8 18:23:36 2022 +0800 Merge pull request #10797 from supabase/master Prod deploy dashboard commitdf66ff2c56Merge:d264d528c61839099cAuthor: Joshen Lim <joshenlimek@gmail.com> Date: Tue Dec 6 16:34:33 2022 +0800 Merge pull request #10741 from supabase/master Prod deploy Dashboard commitd264d528c0Merge:d571209893aca10d35Author: 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 commit3aca10d35eAuthor: Alaister Young <a@alaisteryoung.com> Date: Fri Dec 2 14:38:49 2022 +0000 hotfix: key for functions usage commitd571209895Merge:d0614755c902039693Author: Joshen Lim <joshenlimek@gmail.com> Date: Fri Dec 2 00:04:56 2022 +0800 Merge pull request #10654 from supabase/master Prod deploy Dashboard commitd0614755caMerge:70069f86b448c85a41Author: Joshen Lim <joshenlimek@gmail.com> Date: Tue Nov 29 19:17:43 2022 +0800 Merge pull request #10601 from supabase/master Prod deploy dashboard commit70069f86b3Merge:a3c72a6ec8c6ddaf6eAuthor: Joshen Lim <joshenlimek@gmail.com> Date: Thu Nov 24 17:45:54 2022 +0800 Merge pull request #10506 from supabase/master Prod deploy dashboard commita3c72a6ec0Merge:a67f60a30e281ce19bAuthor: Joshen Lim <joshenlimek@gmail.com> Date: Wed Nov 23 17:06:39 2022 +0800 Merge pull request #10476 from supabase/master Prod deploy Dashboard commita67f60a30bMerge:0094acc41e7b0f5b82Author: Joshen Lim <joshenlimek@gmail.com> Date: Tue Nov 22 16:49:25 2022 +0800 Merge pull request #10454 from supabase/master Prod deploy Dashboard commit0094acc419Merge:3723e1feba74d43f99Author: 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 commit3723e1feb4Merge:e8ebf80f5e3ac9e193Author: 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 commite8ebf80f55Merge:b48bb12e7a8aa06c0dAuthor: Joshen Lim <joshenlimek@gmail.com> Date: Tue Nov 15 16:52:53 2022 +0800 Merge pull request #10335 from supabase/master Prod deploy Dashboard commitb48bb12e7bMerge:ce5a8cd025836ba8a8Author: Joshen Lim <joshenlimek@gmail.com> Date: Mon Nov 14 13:40:29 2022 +0800 Merge pull request #10302 from supabase/master Prod deploy Dashboard commitce5a8cd023Merge:8f808477a65bd1ccacAuthor: 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 commit8f808477a8Merge:0143b512481f2cb4cbAuthor: Joshen Lim <joshenlimek@gmail.com> Date: Thu Nov 10 14:32:59 2022 +0800 Merge pull request #10234 from supabase/master Prod deploy Dashboard commit0143b51247Merge:a9be5e2491c46c54e3Author: Joshen Lim <joshenlimek@gmail.com> Date: Tue Nov 8 16:50:55 2022 +0800 Merge pull request #10173 from supabase/master Prod deploy Dashboard commita9be5e2491Merge:1d92980f9465d0de86Author: Joshen Lim <joshenlimek@gmail.com> Date: Thu Nov 3 15:32:54 2022 +0700 Merge pull request #10053 from supabase/master Prod deploy Dashboard commit1d92980f9aMerge:ead80f1503a1d8ab8eAuthor: Joshen Lim <joshenlimek@gmail.com> Date: Wed Nov 2 11:53:35 2022 +0700 Merge pull request #9998 from supabase/master Prod deploy dashboard commitead80f150cMerge:e031dcc3cbd72dc459Author: Joshen Lim <joshenlimek@gmail.com> Date: Tue Nov 1 16:05:48 2022 +0700 Merge pull request #9995 from supabase/master Prod deploy Dashboard commite031dcc3cdMerge:e00c982944f90176fbAuthor: Joshen Lim <joshenlimek@gmail.com> Date: Thu Oct 27 13:07:33 2022 +0700 Merge pull request #9885 from supabase/master Prod deploy Dashboard commite00c982946Merge:fb59122c36c472fc31Author: Joshen Lim <joshenlimek@gmail.com> Date: Tue Oct 25 13:10:20 2022 +0700 Merge pull request #9797 from supabase/master Studio Prod Deploy commitfb59122c3eMerge:96f7ccc3209fa366e6Author: Joshen Lim <joshenlimek@gmail.com> Date: Thu Oct 20 12:15:15 2022 +0700 Merge pull request #9694 from supabase/master Prod deploy Dashboard commit96f7ccc322Merge:859327c8137a116b5eAuthor: 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 commit859327c816Merge:e968cdf7a477508d3dAuthor: 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 commite968cdf7aeMerge:aaceb4fb4b5178bb90Author: Joshen Lim <joshenlimek@gmail.com> Date: Mon Oct 17 16:38:24 2022 +0800 Merge pull request #9610 from supabase/master Studio prod deploy commitaaceb4fb4aMerge:da8cf6f5e9ca18cee9Author: 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 commitda8cf6f5efMerge:fac5397ac465a84d8cAuthor: 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 commitfac5397acfMerge:29fb072c12d9ff657cAuthor: Joshen Lim <joshenlimek@gmail.com> Date: Tue Oct 11 16:16:32 2022 +0800 Merge pull request #9392 from supabase/master Studio deploy commit29fb072c17Merge:3f6a61ed1f01616053Author: Joshen Lim <joshenlimek@gmail.com> Date: Thu Oct 6 13:29:57 2022 +0800 Merge pull request #9364 from supabase/master Prod deploy Studio commit3f6a61ed13Merge:60b095a08c0d059e45Author: Joshen Lim <joshenlimek@gmail.com> Date: Tue Oct 4 17:18:10 2022 +0800 Merge pull request #9321 from supabase/master Prod deploy Studio commit60b095a08eMerge:a7e9cf50be96f6f472Author: Joshen Lim <joshenlimek@gmail.com> Date: Tue Oct 4 13:04:25 2022 +0800 Merge pull request #9316 from supabase/master Prod deploy Studio commita7e9cf50b2Merge:d45bb7303dcca02e4dAuthor: 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 commitd45bb73031Merge:b5f2259d01bf3e90b3Author: Joshen Lim <joshenlimek@gmail.com> Date: Thu Sep 29 15:08:49 2022 +0800 Merge pull request #9208 from supabase/master Prod deploy Studio commitb5f2259d0fMerge:ff192a2b18e6c30d1dAuthor: Joshen Lim <joshenlimek@gmail.com> Date: Tue Sep 27 12:12:02 2022 +0800 Merge pull request #9156 from supabase/master Prod deploy Studio
1030 lines
36 KiB
TypeScript
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)
|
|
}
|
|
}
|