From 7253726dde39d6438bc7b216d5aa8d6adfb22174 Mon Sep 17 00:00:00 2001 From: Joshen Lim Date: Thu, 2 May 2024 12:26:26 +0800 Subject: [PATCH] More scaffolding --- .../interfaces/SQLEditor/SQLEditor.tsx | 8 +- .../layouts/SQLEditorLayout/SQLEditorMenu.tsx | 15 +-- .../SQLEditorLayout/SQLEditorNavV2.tsx | 82 ------------ .../SQLEditorNavV2/SQLEditorNav.tsx | 120 ++++++++++++++++++ .../SQLEditorNavV2/SQLEditorNav.utils.ts | 47 +++++++ .../SQLEditorNavV2/SQLEditorNavTreeItem.tsx | 3 + apps/studio/data/content/content-id-query.ts | 37 ++++++ .../data/content/content-insert-mutation.ts | 2 +- apps/studio/data/content/folders-query.ts | 29 +++-- apps/studio/data/content/keys.ts | 2 + apps/studio/pages/project/[ref]/sql/[id].tsx | 9 +- packages/api-types/types/api.d.ts | 115 +++++++++++++++-- 12 files changed, 346 insertions(+), 123 deletions(-) delete mode 100644 apps/studio/components/layouts/SQLEditorLayout/SQLEditorNavV2.tsx create mode 100644 apps/studio/components/layouts/SQLEditorLayout/SQLEditorNavV2/SQLEditorNav.tsx create mode 100644 apps/studio/components/layouts/SQLEditorLayout/SQLEditorNavV2/SQLEditorNav.utils.ts create mode 100644 apps/studio/components/layouts/SQLEditorLayout/SQLEditorNavV2/SQLEditorNavTreeItem.tsx create mode 100644 apps/studio/data/content/content-id-query.ts diff --git a/apps/studio/components/interfaces/SQLEditor/SQLEditor.tsx b/apps/studio/components/interfaces/SQLEditor/SQLEditor.tsx index eaea903d658..e6e1c09fa3d 100644 --- a/apps/studio/components/interfaces/SQLEditor/SQLEditor.tsx +++ b/apps/studio/components/interfaces/SQLEditor/SQLEditor.tsx @@ -62,6 +62,7 @@ import { createSqlSnippetSkeleton, } from './SQLEditor.utils' import UtilityPanel from './UtilityPanel/UtilityPanel' +import { Settings, X } from 'lucide-react' // Load the monaco editor client-side only (does not behave well server-side) const MonacoEditor = dynamic(() => import('./MonacoEditor'), { ssr: false }) @@ -248,6 +249,7 @@ const SQLEditor = () => { const snippet = id ? snap.snippets[id] : null const isLoading = urlId === 'new' ? false : !(id && ref && snap.loaded[ref]) + console.log({ isLoading }) /** * Sets the snippet title using AI. @@ -802,15 +804,15 @@ const SQLEditor = () => { setIsSchemaSuggestionDismissed(true) appSnap.setShowAiSettingsModal(true) }} - className="text-brand-600 hover:text-brand-600 transition" + className="text-brand-500 hover:text-brand-600 transition" > - + )} diff --git a/apps/studio/components/layouts/SQLEditorLayout/SQLEditorMenu.tsx b/apps/studio/components/layouts/SQLEditorLayout/SQLEditorMenu.tsx index ff73662e69a..c1f0aaea0eb 100644 --- a/apps/studio/components/layouts/SQLEditorLayout/SQLEditorMenu.tsx +++ b/apps/studio/components/layouts/SQLEditorLayout/SQLEditorMenu.tsx @@ -9,7 +9,6 @@ import { untitledSnippetTitle } from 'components/interfaces/SQLEditor/SQLEditor. import { createSqlSnippetSkeleton } from 'components/interfaces/SQLEditor/SQLEditor.utils' import { useContentDeleteMutation } from 'data/content/content-delete-mutation' import { useFolderCreateMutation } from 'data/content/folder-create-mutation' -import { useSQLSnippetFoldersQuery } from 'data/content/folders-query' import { SqlSnippet, useSqlSnippetsQuery } from 'data/content/sql-snippets-query' import { useCheckPermissions, useFlag, useSelectedProject } from 'hooks' import { uuidv4 } from 'lib/helpers' @@ -19,7 +18,7 @@ import { Button } from 'ui' import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' import { InnerSideMenuItem } from 'ui-patterns/InnerSideMenu' import { SQLEditorNavV1 } from './SQLEditorNavV1' -import SQLEditorNavV2 from './SQLEditorNavV2' +import { SQLEditorNav as SQLEditorNavV2 } from './SQLEditorNavV2/SQLEditorNav' const SideBarContent = () => { const router = useRouter() @@ -42,18 +41,6 @@ const SideBarContent = () => { }, }) - useSQLSnippetFoldersQuery( - { projectRef: ref }, - { - enabled: enableFolders, - refetchOnWindowFocus: false, - staleTime: 5 * 60 * 1000, // 5 minutes. - onSuccess(data) { - if (ref) console.log(data) - }, - } - ) - const { mutate: createFolder, isLoading: isCreating } = useFolderCreateMutation({ onSuccess: () => { toast.success('Done') diff --git a/apps/studio/components/layouts/SQLEditorLayout/SQLEditorNavV2.tsx b/apps/studio/components/layouts/SQLEditorLayout/SQLEditorNavV2.tsx deleted file mode 100644 index d7fcc784f43..00000000000 --- a/apps/studio/components/layouts/SQLEditorLayout/SQLEditorNavV2.tsx +++ /dev/null @@ -1,82 +0,0 @@ -import { - ContextMenu, - ContextMenuContent, - ContextMenuItem, - ContextMenuSeparator, - ContextMenuTrigger, - TreeView, - TreeViewItem, - flattenTree, -} from 'ui' - -export const SQLEditorNavV2 = () => { - const MOCK_DATA = { - name: '', - children: [ - { - name: 'Current batch', - }, - { - name: 'Older queries', - }, - { - name: 'query all users', - }, - { - name: 'users in last day', - }, - { - name: 'new users over time', - }, - ], - } - - return ( - ( - - - { - // let updatedTreeData = { ...treeData } - // const findNode = (node: any) => { - // if (node.id === element.id) { - // node.name = value - // node.metadata = { isEditing: false } - // } - // if (node.children) { - // node.children.forEach(findNode) - // } - // } - // updatedTreeData.children.forEach(findNode) - // setDataTreeState(updatedTreeData) - // }} - {...getNodeProps()} - /> - - e.stopPropagation()}> - {}} onFocusCapture={(e) => e.stopPropagation()}> - Rename - - Open in new tab - Share with team - - Delete - - - )} - /> - ) -} - -export default SQLEditorNavV2 diff --git a/apps/studio/components/layouts/SQLEditorLayout/SQLEditorNavV2/SQLEditorNav.tsx b/apps/studio/components/layouts/SQLEditorLayout/SQLEditorNavV2/SQLEditorNav.tsx new file mode 100644 index 00000000000..99e38a1acf8 --- /dev/null +++ b/apps/studio/components/layouts/SQLEditorLayout/SQLEditorNavV2/SQLEditorNav.tsx @@ -0,0 +1,120 @@ +import { useParams } from 'common' +import { useSQLSnippetFoldersQuery } from 'data/content/folders-query' +import { + CollapsibleContent_Shadcn_, + CollapsibleTrigger_Shadcn_, + Collapsible_Shadcn_, + ContextMenu, + ContextMenuContent, + ContextMenuItem, + ContextMenuSeparator, + ContextMenuTrigger, + Separator, + TreeView, + TreeViewItem, + flattenTree, +} from 'ui' +import { ROOT_NODE, TreeViewItemProps, formatFolderResponseForTreeView } from './SQLEditorNav.utils' +import { ChevronDown, ChevronRight, ChevronUp } from 'lucide-react' +import { useState } from 'react' +import { useRouter } from 'next/router' + +// Requirements +// - Asynchronous loading +// - Directory tree +// - Multi select +// - Context menu + +export const SQLEditorNav = () => { + const router = useRouter() + const { ref: projectRef } = useParams() + const [treeState, setTreeState] = useState([ROOT_NODE]) + const [showPrivateSnippets, setShowPrivateSnippets] = useState(true) + + useSQLSnippetFoldersQuery( + { projectRef }, + { + refetchOnWindowFocus: false, + staleTime: 5 * 60 * 1000, // 5 minutes + onSuccess: (data) => { + const entities = formatFolderResponseForTreeView(data) + setTreeState(entities) + }, + } + ) + + return ( + <> + + + + + + PRIVATE + + + ( + + + { + // let updatedTreeData = { ...treeData } + // const findNode = (node: any) => { + // if (node.id === element.id) { + // node.name = value + // node.metadata = { isEditing: false } + // } + // if (node.children) { + // node.children.forEach(findNode) + // } + // } + // updatedTreeData.children.forEach(findNode) + // setDataTreeState(updatedTreeData) + // }} + {...getNodeProps()} + onClick={() => { + if (!isBranch) router.push(`/project/${projectRef}/sql/${element.id}`) + }} + /> + + e.stopPropagation()}> + {isBranch ? ( + <> + New snippet + + ) : ( + <> + Open in new tab + Share with team + + )} + + {}} onFocusCapture={(e) => e.stopPropagation()}> + Rename + + Delete + + + )} + /> + + + + + + ) +} diff --git a/apps/studio/components/layouts/SQLEditorLayout/SQLEditorNavV2/SQLEditorNav.utils.ts b/apps/studio/components/layouts/SQLEditorLayout/SQLEditorNavV2/SQLEditorNav.utils.ts new file mode 100644 index 00000000000..acf9a34b516 --- /dev/null +++ b/apps/studio/components/layouts/SQLEditorLayout/SQLEditorNavV2/SQLEditorNav.utils.ts @@ -0,0 +1,47 @@ +import { SnippetFolderResponse } from 'data/content/folders-query' + +export interface TreeViewItemProps { + id: string | number + name: string + parent: number | null + children: any[] + metadata?: any +} + +export const ROOT_NODE = { id: 0, name: '', parent: null, children: [] } + +export const splitProjectPrivateSnippets = () => { + // TODO + + return { project: [], private: [] } +} + +export const formatFolderResponseForTreeView = ( + response?: SnippetFolderResponse +): TreeViewItemProps[] => { + if (response === undefined) return [ROOT_NODE] + + const { folders, contents } = response + const formattedFolders = + folders?.map((folder) => { + const { id, name, ...metadata } = folder + return { id, name, parent: 0, isBranch: true, children: [], metadata } + }) || [] + const formattedContents = + contents?.map((content) => { + const { id, name, ...metadata } = content + return { id, name, parent: 0, children: [], metadata } + }) || [] + + const root = { + id: 0, + name: '', + parent: null, + children: [ + ...(folders || [])?.map((folder) => folder.id), + ...(contents || [])?.map((content) => content.id), + ], + } + + return [root, ...formattedFolders, ...formattedContents] +} diff --git a/apps/studio/components/layouts/SQLEditorLayout/SQLEditorNavV2/SQLEditorNavTreeItem.tsx b/apps/studio/components/layouts/SQLEditorLayout/SQLEditorNavV2/SQLEditorNavTreeItem.tsx new file mode 100644 index 00000000000..6957623504d --- /dev/null +++ b/apps/studio/components/layouts/SQLEditorLayout/SQLEditorNavV2/SQLEditorNavTreeItem.tsx @@ -0,0 +1,3 @@ +export const SQLEditorNavTreeItem = () => { + return
+} diff --git a/apps/studio/data/content/content-id-query.ts b/apps/studio/data/content/content-id-query.ts new file mode 100644 index 00000000000..24332a90a79 --- /dev/null +++ b/apps/studio/data/content/content-id-query.ts @@ -0,0 +1,37 @@ +import { useQuery, UseQueryOptions } from '@tanstack/react-query' + +import { get, handleError } from 'data/fetchers' +import { ResponseError } from 'types' +import { contentKeys } from './keys' + +export async function getContentById( + { projectRef, id }: { projectRef?: string; id?: string }, + signal?: AbortSignal +) { + if (typeof projectRef === 'undefined') throw new Error('projectRef is required') + if (typeof id === 'undefined') throw new Error('Content ID is required') + + const { data, error } = await get('/platform/projects/{ref}/content/item/{id}', { + params: { path: { ref: projectRef, id } }, + signal, + }) + + if (error) throw handleError(error) + return data +} + +export type ContentIdData = Awaited> +export type ContentIdError = ResponseError + +export const useContentIdQuery = ( + { projectRef, id }: { projectRef?: string; id?: string }, + { enabled = true, ...options }: UseQueryOptions = {} +) => + useQuery( + contentKeys.resource(projectRef, id), + ({ signal }) => getContentById({ projectRef, id }, signal), + { + enabled: enabled && typeof projectRef !== 'undefined' && typeof id !== 'undefined', + ...options, + } + ) diff --git a/apps/studio/data/content/content-insert-mutation.ts b/apps/studio/data/content/content-insert-mutation.ts index c7bdfab3b3c..972c4c30480 100644 --- a/apps/studio/data/content/content-insert-mutation.ts +++ b/apps/studio/data/content/content-insert-mutation.ts @@ -7,7 +7,7 @@ import type { ResponseError } from 'types' import type { Content } from './content-query' import { contentKeys } from './keys' -export type InsertContentPayload = Omit & { +export type InsertContentPayload = Omit & { content: Content['content'] } diff --git a/apps/studio/data/content/folders-query.ts b/apps/studio/data/content/folders-query.ts index 3d2b361d094..6185da38b4f 100644 --- a/apps/studio/data/content/folders-query.ts +++ b/apps/studio/data/content/folders-query.ts @@ -10,32 +10,43 @@ export type SnippetFolder = components['schemas']['UserContentFolder'] export type Snippet = components['schemas']['UserContentObjectMeta'] export async function getSQLSnippetFolders( - { projectRef }: { projectRef: string | undefined }, + { projectRef, folderId }: { projectRef?: string; folderId?: string }, signal?: AbortSignal ) { if (typeof projectRef === 'undefined') throw new Error('projectRef is required') - const { data, error } = await get('/platform/projects/{ref}/content/folders', { - params: { path: { ref: projectRef } }, - signal, - }) + if (folderId) { + const { data, error } = await get('/platform/projects/{ref}/content/folders/{id}', { + params: { path: { ref: projectRef, id: folderId } }, + signal, + }) - if (error) throw handleError(error) - return data.data + if (error) throw handleError(error) + return data.data + } else { + const { data, error } = await get('/platform/projects/{ref}/content/folders', { + params: { path: { ref: projectRef }, query: { type: 'sql' } }, + signal, + }) + + if (error) throw handleError(error) + return data.data + } } export type SQLSnippetFoldersData = Awaited> export type SQLSnippetFoldersError = ResponseError export const useSQLSnippetFoldersQuery = ( - { projectRef }: { projectRef: string | undefined }, + { projectRef, folderId }: { projectRef?: string; folderId?: string }, { enabled = true, ...options }: UseQueryOptions = {} ) => useQuery( + // [Joshen] TODO: Need to think about how to store the query key contentKeys.folders(projectRef), - ({ signal }) => getSQLSnippetFolders({ projectRef }, signal), + ({ signal }) => getSQLSnippetFolders({ projectRef, folderId }, signal), { enabled: enabled && typeof projectRef !== 'undefined', ...options } ) diff --git a/apps/studio/data/content/keys.ts b/apps/studio/data/content/keys.ts index 16572e5b6fd..79052a10a86 100644 --- a/apps/studio/data/content/keys.ts +++ b/apps/studio/data/content/keys.ts @@ -2,4 +2,6 @@ export const contentKeys = { list: (projectRef: string | undefined) => ['projects', projectRef, 'content'] as const, folders: (projectRef: string | undefined) => ['projects', projectRef, 'content', 'folders'] as const, + resource: (projectRef: string | undefined, id: string | undefined) => + ['projects', projectRef, 'content', id] as const, } diff --git a/apps/studio/pages/project/[ref]/sql/[id].tsx b/apps/studio/pages/project/[ref]/sql/[id].tsx index 87f616494ce..01063280d8f 100644 --- a/apps/studio/pages/project/[ref]/sql/[id].tsx +++ b/apps/studio/pages/project/[ref]/sql/[id].tsx @@ -15,10 +15,11 @@ import { SQLEditorLayout } from 'components/layouts' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import getPgsqlCompletionProvider from 'components/ui/CodeEditor/Providers/PgSQLCompletionProvider' import getPgsqlSignatureHelpProvider from 'components/ui/CodeEditor/Providers/PgSQLSignatureHelpProvider' -import { useLocalStorageQuery } from 'hooks' +import { useFlag, useLocalStorageQuery } from 'hooks' import { LOCAL_STORAGE_KEYS } from 'lib/constants' import { useAppStateSnapshot } from 'state/app-state' import { useSnippets, useSqlEditorStateSnapshot } from 'state/sql-editor' +import { useContentIdQuery } from 'data/content/content-id-query' const SqlEditor: NextPageWithLayout = () => { const router = useRouter() @@ -28,10 +29,16 @@ const SqlEditor: NextPageWithLayout = () => { const { project } = useProjectContext() const snap = useSqlEditorStateSnapshot() const appSnap = useAppStateSnapshot() + const enableFolders = useFlag('sqlFolderOrganization') const snippets = useSnippets(ref) const { mutateAsync: formatQuery } = useFormatQueryMutation() + useContentIdQuery( + { projectRef: ref, id }, + { enabled: enableFolders, onSuccess: (data) => console.log(data) } + ) + const [intellisenseEnabled] = useLocalStorageQuery( LOCAL_STORAGE_KEYS.SQL_EDITOR_INTELLISENSE, true diff --git a/packages/api-types/types/api.d.ts b/packages/api-types/types/api.d.ts index 883273f1213..14f12cfc467 100644 --- a/packages/api-types/types/api.d.ts +++ b/packages/api-types/types/api.d.ts @@ -484,7 +484,7 @@ export interface paths { /** Deletes project's contents */ delete: operations['ContentController_deleteContents'] } - '/platform/projects/{ref}/content/{id}': { + '/platform/projects/{ref}/content/item/{id}': { /** Gets project's content by the given id */ get: operations['ContentController_getContentById'] } @@ -1359,7 +1359,7 @@ export interface paths { /** Deletes project's contents */ delete: operations['ContentController_deleteContents'] } - '/v0/projects/{ref}/content/{id}': { + '/v0/projects/{ref}/content/item/{id}': { /** Gets project's content by the given id */ get: operations['ContentController_getContentById'] } @@ -1937,17 +1937,21 @@ export interface paths { post: operations['ExtensionsController_provisionResource'] } '/partners/flyio/organizations/{organization_id}': { - /** Gets information about the organization */ + /** Gets details of the organization linked to the provided Fly organization id */ get: operations['OrganizationsController_getOrganization'] } '/partners/flyio/organizations/{organization_id}/extensions': { - /** Gets all databases that belong to the Fly organization */ + /** Gets all databases that belong to the given Fly organization id */ get: operations['OrganizationsController_getOrgExtensions'] } '/partners/flyio/organizations/{organization_id}/sso': { /** Starts Fly single sign on */ get: operations['OrganizationsController_startFlyioSSO'] } + '/partners/flyio/organizations/{organization_id}/subscription': { + /** Updates organization subscription linked to the provided Fly organization id */ + put: operations['OrganizationsController_updateOrganization'] + } '/partners/flyio/organizations/{organization_id}/billing': { /** Gets the organizations current unbilled charges */ get: operations['FlyBillingController_getResourceBilling'] @@ -2122,6 +2126,7 @@ export interface components { SECURITY_UPDATE_PASSWORD_REQUIRE_REAUTHENTICATION: boolean SECURITY_REFRESH_TOKEN_REUSE_INTERVAL: number MAILER_OTP_EXP: number + MAILER_OTP_LENGTH: number SMS_AUTOCONFIRM: boolean SMS_MAX_FREQUENCY: number SMS_OTP_EXP: number @@ -2276,6 +2281,7 @@ export interface components { SECURITY_UPDATE_PASSWORD_REQUIRE_REAUTHENTICATION?: boolean SECURITY_REFRESH_TOKEN_REUSE_INTERVAL?: number MAILER_OTP_EXP?: number + MAILER_OTP_LENGTH?: number SMS_AUTOCONFIRM?: boolean SMS_MAX_FREQUENCY?: number SMS_OTP_EXP?: number @@ -3637,7 +3643,10 @@ export interface components { GetProjectByFlyExtensionIdResponse: { ref: string } - /** @enum {string} */ + /** + * @description Desired instance size, will use default size if not defined. Paid plans only. + * @enum {string} + */ DesiredInstanceSize: | 'micro' | 'small' @@ -4149,10 +4158,11 @@ export interface components { db_schema?: string } V1PostgrestConfigResponse: { - max_rows: number | null + max_rows: number + /** @description If `null`, the value is automatically configured based on compute size. */ db_pool: number | null - db_schema: string | null - db_extra_search_path: string | null + db_schema: string + db_extra_search_path: string } PostgresConfigResponse: { statement_timeout?: string @@ -4163,6 +4173,8 @@ export interface components { max_parallel_maintenance_workers?: number max_parallel_workers?: number max_parallel_workers_per_gather?: number + max_standby_archive_delay?: string + max_standby_streaming_delay?: string max_worker_processes?: number shared_buffers?: string work_mem?: string @@ -4178,6 +4190,8 @@ export interface components { max_parallel_maintenance_workers?: number max_parallel_workers?: number max_parallel_workers_per_gather?: number + max_standby_archive_delay?: string + max_standby_streaming_delay?: string max_worker_processes?: number shared_buffers?: string work_mem?: string @@ -4832,6 +4846,7 @@ export interface components { /** @enum {string} */ tier: 'tier_payg' | 'tier_pro' | 'tier_free' | 'tier_team' | 'tier_enterprise' price_id?: string + skip_free_plan_validations?: boolean } RestrictionData: { grace_period_end?: string @@ -5072,10 +5087,11 @@ export interface components { root_key: string } PostgrestConfigWithJWTSecretResponse: { - max_rows: number | null + max_rows: number + /** @description If `null`, the value is automatically configured based on compute size. */ db_pool: number | null - db_schema: string | null - db_extra_search_path: string | null + db_schema: string + db_extra_search_path: string jwt_secret?: string } V1ProjectRefResponse: { @@ -5300,6 +5316,7 @@ export interface components { mailer_allow_unverified_email_sign_ins: boolean | null mailer_autoconfirm: boolean | null mailer_otp_exp: number | null + mailer_otp_length: number | null mailer_secure_email_change_enabled: boolean | null mailer_subjects_confirmation: string | null mailer_subjects_email_change: string | null @@ -5423,6 +5440,7 @@ export interface components { security_update_password_require_reauthentication?: boolean security_refresh_token_reuse_interval?: number mailer_otp_exp?: number + mailer_otp_length?: number sms_autoconfirm?: boolean sms_max_frequency?: number sms_otp_exp?: number @@ -5788,6 +5806,47 @@ export interface components { /** @description Supabase project services health status */ services: components['schemas']['ServiceHealthResponse'][] } + /** + * @description Organization subscription plan + * @enum {string} + */ + SelfServePlanId: 'free' | 'pro' | 'team' + FlyResourceProvisioningBody: { + /** @description A UNIX epoch timestamp value */ + timestamp: number + /** @description A random unique string identifying the individual request */ + nonce: string + /** @description The full request target URL */ + url: string + /** @description Name of the extension */ + name: string + /** @description Unique ID representing the extension */ + id: string + /** @description Unique ID representing an organization */ + organization_id: string + /** @description Display name for an organization */ + organization_name: string + /** @description Obfuscated email that routes to the provisioning user */ + user_email: string + /** @description Unique ID representing an user */ + user_id: string + /** @description The three-letter, primary Fly.io region where the target app intends to write from */ + primary_region: string + /** @description An IPv6 address on the customer network assigned to this extension */ + ip_address: string + /** + * @description An array of Fly.io region codes where read replicas should be provisioned + * @default [] + */ + read_regions: string[] + /** @description Database password (Optional, don't send to generate one) */ + db_pass?: string + /** @example large */ + desired_instance_size?: components['schemas']['DesiredInstanceSize'] + /** @example pro */ + organization_plan?: components['schemas']['SelfServePlanId'] + user_name: string + } ResourceProvisioningConfigResponse: { /** * @description PSQL connection string @@ -5855,6 +5914,10 @@ export interface components { */ supabase_org_id: string } + UpdateFlyOrganizationSubscriptionBody: { + /** @example pro */ + plan: components['schemas']['SelfServePlanId'] + } ResourceBillingItem: { /** * @description Non-Unique identifier of the item @@ -9477,6 +9540,9 @@ export interface operations { /** Gets project's content root folder */ ContentFoldersController_getRootFolder: { parameters: { + query?: { + type?: 'sql' | 'report' | 'log_sql' + } path: { /** @description Project ref */ ref: string @@ -14438,6 +14504,11 @@ export interface operations { } /** Creates a database */ ExtensionsController_provisionResource: { + requestBody: { + content: { + 'application/json': components['schemas']['FlyResourceProvisioningBody'] + } + } responses: { 201: { content: { @@ -14446,7 +14517,7 @@ export interface operations { } } } - /** Gets information about the organization */ + /** Gets details of the organization linked to the provided Fly organization id */ OrganizationsController_getOrganization: { parameters: { path: { @@ -14461,7 +14532,7 @@ export interface operations { } } } - /** Gets all databases that belong to the Fly organization */ + /** Gets all databases that belong to the given Fly organization id */ OrganizationsController_getOrgExtensions: { parameters: { path: { @@ -14489,6 +14560,24 @@ export interface operations { } } } + /** Updates organization subscription linked to the provided Fly organization id */ + OrganizationsController_updateOrganization: { + parameters: { + path: { + organization_id: string + } + } + requestBody: { + content: { + 'application/json': components['schemas']['UpdateFlyOrganizationSubscriptionBody'] + } + } + responses: { + 200: { + content: never + } + } + } /** Gets the organizations current unbilled charges */ FlyBillingController_getResourceBilling: { parameters: {