diff --git a/apps/studio/components/layouts/ProjectLayout/NavigationBar/NavigationBar.tsx b/apps/studio/components/layouts/ProjectLayout/NavigationBar/NavigationBar.tsx
index 25e86d8e14f..71c6360b23d 100644
--- a/apps/studio/components/layouts/ProjectLayout/NavigationBar/NavigationBar.tsx
+++ b/apps/studio/components/layouts/ProjectLayout/NavigationBar/NavigationBar.tsx
@@ -6,7 +6,7 @@ import { Command, FileText, FlaskConical, Search, Settings } from 'lucide-react'
import { useTheme } from 'next-themes'
import Link from 'next/link'
import { useRouter } from 'next/router'
-import { MouseEvent, useState } from 'react'
+import { useState } from 'react'
import {
Button,
DropdownMenu,
@@ -26,6 +26,7 @@ import {
} from 'ui'
import { useIsAPIDocsSidePanelEnabled } from 'components/interfaces/App/FeaturePreview/FeaturePreviewContext'
+import { useSignOut } from 'lib/auth'
import { IS_PLATFORM } from 'lib/constants'
import { detectOS } from 'lib/helpers'
import { useProfile } from 'lib/profile'
@@ -39,7 +40,6 @@ import {
} from './NavigationBar.utils'
import { NavigationIconButton } from './NavigationIconButton'
import NavigationIconLink from './NavigationIconLink'
-import { useSignOut } from 'lib/auth'
export const ICON_SIZE = 20
export const ICON_STROKE_WIDTH = 1.5
@@ -333,17 +333,21 @@ const NavigationBar = () => {
))}
-
-
- {
- await signOut()
- await router.push('/sign-in')
- }}
- >
- Log out
-
-
+ {IS_PLATFORM && (
+ <>
+
+
+ {
+ await signOut()
+ await router.push('/sign-in')
+ }}
+ >
+ Log out
+
+
+ >
+ )}
diff --git a/apps/studio/data/config/project-upgrade-eligibility-query.ts b/apps/studio/data/config/project-upgrade-eligibility-query.ts
index 0cc5590b687..095b15566c1 100644
--- a/apps/studio/data/config/project-upgrade-eligibility-query.ts
+++ b/apps/studio/data/config/project-upgrade-eligibility-query.ts
@@ -1,10 +1,11 @@
import { useQuery, UseQueryOptions } from '@tanstack/react-query'
+import { IS_PLATFORM } from 'common'
import { get } from 'data/fetchers'
+import { useProjectByRef } from 'hooks'
+import { PROJECT_STATUS } from 'lib/constants/infrastructure'
import type { ResponseError } from 'types'
import { configKeys } from './keys'
-import { useProjectByRef } from 'hooks'
-import { PROJECT_STATUS } from 'lib/constants'
export type ProjectUpgradeEligibilityVariables = { projectRef?: string }
export type ProjectUpgradeEligibilityResponse = {
@@ -52,7 +53,8 @@ export const useProjectUpgradeEligibilityQuery = = {
+ data: T extends {
+ responses: any
+ }
+ ? NonNullable, MediaType>>
+ : unknown
+ error?: never
+ response: Response
+}
+
+/**
+ * Utility type to extract the type from a API definition in data/api file.
+ */
+export type extractResponse<
+ path extends keyof paths,
+ method extends keyof paths[path],
+> = FetchResponse['data']
diff --git a/apps/studio/pages/api/integrations/[slug].ts b/apps/studio/pages/api/integrations/[slug].ts
new file mode 100644
index 00000000000..1aa08d4e9a9
--- /dev/null
+++ b/apps/studio/pages/api/integrations/[slug].ts
@@ -0,0 +1,24 @@
+import { NextApiRequest, NextApiResponse } from 'next'
+
+import apiWrapper from 'lib/api/apiWrapper'
+import { extractResponse } from 'pages/api/constants'
+
+export default (req: NextApiRequest, res: NextApiResponse) => apiWrapper(req, res, handler)
+
+async function handler(req: NextApiRequest, res: NextApiResponse) {
+ const { method } = req
+
+ switch (method) {
+ case 'GET':
+ return handleGet(req, res)
+ default:
+ res.setHeader('Allow', ['GET'])
+ res.status(405).json({ data: null, error: { message: `Method ${method} Not Allowed` } })
+ }
+}
+
+type ResponseData = extractResponse<'/platform/integrations/{slug}', 'get'>
+
+const handleGet = async (req: NextApiRequest, res: NextApiResponse) => {
+ return res.status(200).json([])
+}
diff --git a/apps/studio/pages/api/integrations/github/authorization.ts b/apps/studio/pages/api/integrations/github/authorization.ts
new file mode 100644
index 00000000000..51c08af5575
--- /dev/null
+++ b/apps/studio/pages/api/integrations/github/authorization.ts
@@ -0,0 +1,24 @@
+import { NextApiRequest, NextApiResponse } from 'next'
+
+import apiWrapper from 'lib/api/apiWrapper'
+import { extractResponse } from 'pages/api/constants'
+
+export default (req: NextApiRequest, res: NextApiResponse) => apiWrapper(req, res, handler)
+
+async function handler(req: NextApiRequest, res: NextApiResponse) {
+ const { method } = req
+
+ switch (method) {
+ case 'GET':
+ return handleGet(req, res)
+ default:
+ res.setHeader('Allow', ['GET'])
+ res.status(405).json({ data: null, error: { message: `Method ${method} Not Allowed` } })
+ }
+}
+
+type ResponseData = extractResponse<'/platform/integrations/github/authorization', 'get'>
+
+const handleGet = async (req: NextApiRequest, res: NextApiResponse) => {
+ return res.status(200).json(null as any)
+}
diff --git a/apps/studio/pages/api/integrations/github/connections.ts b/apps/studio/pages/api/integrations/github/connections.ts
new file mode 100644
index 00000000000..376d2f01541
--- /dev/null
+++ b/apps/studio/pages/api/integrations/github/connections.ts
@@ -0,0 +1,24 @@
+import { NextApiRequest, NextApiResponse } from 'next'
+
+import apiWrapper from 'lib/api/apiWrapper'
+import { extractResponse } from 'pages/api/constants'
+
+export default (req: NextApiRequest, res: NextApiResponse) => apiWrapper(req, res, handler)
+
+async function handler(req: NextApiRequest, res: NextApiResponse) {
+ const { method } = req
+
+ switch (method) {
+ case 'GET':
+ return handleGet(req, res)
+ default:
+ res.setHeader('Allow', ['GET'])
+ res.status(405).json({ data: null, error: { message: `Method ${method} Not Allowed` } })
+ }
+}
+
+type ResponseData = extractResponse<'/platform/integrations/github/connections', 'get'>
+
+const handleGet = async (req: NextApiRequest, res: NextApiResponse) => {
+ return res.status(200).json({ connections: [] })
+}
diff --git a/apps/studio/pages/api/integrations/github/repositories.ts b/apps/studio/pages/api/integrations/github/repositories.ts
new file mode 100644
index 00000000000..18b5e1f0d85
--- /dev/null
+++ b/apps/studio/pages/api/integrations/github/repositories.ts
@@ -0,0 +1,24 @@
+import { NextApiRequest, NextApiResponse } from 'next'
+
+import apiWrapper from 'lib/api/apiWrapper'
+import { extractResponse } from 'pages/api/constants'
+
+export default (req: NextApiRequest, res: NextApiResponse) => apiWrapper(req, res, handler)
+
+async function handler(req: NextApiRequest, res: NextApiResponse) {
+ const { method } = req
+
+ switch (method) {
+ case 'GET':
+ return handleGet(req, res)
+ default:
+ res.setHeader('Allow', ['GET'])
+ res.status(405).json({ data: null, error: { message: `Method ${method} Not Allowed` } })
+ }
+}
+
+type ResponseData = extractResponse<'/platform/integrations/github/repositories', 'get'>
+
+const handleGet = async (req: NextApiRequest, res: NextApiResponse) => {
+ return res.status(200).json({ repositories: [] } as never)
+}
diff --git a/apps/studio/pages/api/organizations/[slug]/billing/subscription.ts b/apps/studio/pages/api/organizations/[slug]/billing/subscription.ts
new file mode 100644
index 00000000000..6a1dd829dd0
--- /dev/null
+++ b/apps/studio/pages/api/organizations/[slug]/billing/subscription.ts
@@ -0,0 +1,46 @@
+import { NextApiRequest, NextApiResponse } from 'next'
+
+import apiWrapper from 'lib/api/apiWrapper'
+import { extractResponse } from 'pages/api/constants'
+
+export default (req: NextApiRequest, res: NextApiResponse) => apiWrapper(req, res, handler)
+
+async function handler(req: NextApiRequest, res: NextApiResponse) {
+ const { method } = req
+
+ switch (method) {
+ case 'GET':
+ return handleGet(req, res)
+ default:
+ res.setHeader('Allow', ['GET'])
+ res.status(405).json({ data: null, error: { message: `Method ${method} Not Allowed` } })
+ }
+}
+
+type ResponseData = extractResponse<'/platform/organizations/{slug}/billing/subscription', 'get'>
+
+const handleGet = async (req: NextApiRequest, res: NextApiResponse) => {
+ const response: ResponseData = {
+ billing_cycle_anchor: 0,
+ current_period_end: 0,
+ current_period_start: 0,
+ next_invoice_at: 0,
+ usage_billing_enabled: false,
+ plan: {
+ id: 'enterprise',
+ name: '',
+ price: 0,
+ },
+ addons: [],
+ project_addons: [],
+ usage_fees: [],
+ payment_method_type: '',
+ billing_via_partner: false,
+ billing_partner: 'fly',
+ scheduled_plan_change: null,
+ customer_balance: 0,
+ nano_enabled: false,
+ }
+
+ return res.status(200).json(response)
+}
diff --git a/apps/studio/pages/api/projects/[ref]/billing/addons.ts b/apps/studio/pages/api/projects/[ref]/billing/addons.ts
new file mode 100644
index 00000000000..e2b466ea2f9
--- /dev/null
+++ b/apps/studio/pages/api/projects/[ref]/billing/addons.ts
@@ -0,0 +1,30 @@
+import { NextApiRequest, NextApiResponse } from 'next'
+
+import apiWrapper from 'lib/api/apiWrapper'
+import { extractResponse } from 'pages/api/constants'
+
+export default (req: NextApiRequest, res: NextApiResponse) => apiWrapper(req, res, handler)
+
+async function handler(req: NextApiRequest, res: NextApiResponse) {
+ const { method } = req
+
+ switch (method) {
+ case 'GET':
+ return handleGet(req, res)
+ default:
+ res.setHeader('Allow', ['GET'])
+ res.status(405).json({ data: null, error: { message: `Method ${method} Not Allowed` } })
+ }
+}
+
+type ResponseData = extractResponse<'/platform/projects/{ref}/billing/addons', 'get'>
+
+const handleGet = async (req: NextApiRequest, res: NextApiResponse) => {
+ const response: ResponseData = {
+ ref: '',
+ selected_addons: [],
+ available_addons: [],
+ }
+
+ return res.status(200).json(response)
+}
diff --git a/apps/studio/pages/api/projects/[ref]/databases.ts b/apps/studio/pages/api/projects/[ref]/databases.ts
new file mode 100644
index 00000000000..4e5185bcbe3
--- /dev/null
+++ b/apps/studio/pages/api/projects/[ref]/databases.ts
@@ -0,0 +1,24 @@
+import { NextApiRequest, NextApiResponse } from 'next'
+
+import apiWrapper from 'lib/api/apiWrapper'
+import { extractResponse } from 'pages/api/constants'
+
+export default (req: NextApiRequest, res: NextApiResponse) => apiWrapper(req, res, handler)
+
+async function handler(req: NextApiRequest, res: NextApiResponse) {
+ const { method } = req
+
+ switch (method) {
+ case 'GET':
+ return handleGet(req, res)
+ default:
+ res.setHeader('Allow', ['GET'])
+ res.status(405).json({ data: null, error: { message: `Method ${method} Not Allowed` } })
+ }
+}
+
+type ResponseData = extractResponse<'/platform/projects/{ref}/databases', 'get'>
+
+const handleGet = async (req: NextApiRequest, res: NextApiResponse) => {
+ return res.status(200).json([])
+}
diff --git a/apps/studio/pages/api/stripe/subscription.ts b/apps/studio/pages/api/stripe/subscription.ts
deleted file mode 100644
index 206e1186059..00000000000
--- a/apps/studio/pages/api/stripe/subscription.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-import { NextApiRequest, NextApiResponse } from 'next'
-import apiWrapper from 'lib/api/apiWrapper'
-
-export default (req: NextApiRequest, res: NextApiResponse) => apiWrapper(req, res, handler)
-
-async function handler(req: NextApiRequest, res: NextApiResponse) {
- const { method } = req
-
- switch (method) {
- case 'POST':
- return handlePost(req, res)
- default:
- res.setHeader('Allow', ['POST'])
- res.status(405).json({ data: null, error: { message: `Method ${method} Not Allowed` } })
- }
-}
-
-const handlePost = async (req: NextApiRequest, res: NextApiResponse) => {
- // Platform specific endpoint
- const response = {
- data: {
- tier: {
- name: 'Self Hosted',
- prod_id: '',
- unit_amount: 0,
- },
- addons: [],
- billing: {
- billing_cycle_anchor: undefined,
- current_period_end: undefined,
- current_period_start: undefined,
- },
- },
- }
- return res.status(200).json(response)
-}
diff --git a/apps/studio/public/monaco-editor/base/worker/workerMain.js b/apps/studio/public/monaco-editor/base/worker/workerMain.js
index ab244473378..8d534b033fb 100644
--- a/apps/studio/public/monaco-editor/base/worker/workerMain.js
+++ b/apps/studio/public/monaco-editor/base/worker/workerMain.js
@@ -62,7 +62,7 @@
'vs/editor/common/tokenizationRegistry',
'vs/editor/common/languages',
'vs/editor/common/services/editorBaseApi',
- 'vs/nls!vs/base/common/worker/simpleWorker',
+ 'vs/nls!monaco-editor/base/common/worker/simpleWorker',
'vs/base/common/worker/simpleWorker',
'vs/editor/common/services/editorSimpleWorker',
],