refactor: simplify reference docs nav menu & code split
This commit is contained in:
@@ -3,177 +3,261 @@ import { memo, useEffect } from 'react'
|
||||
import { menuState, useMenuLevelId } from '~/hooks/useMenuState'
|
||||
import NavigationMenuGuideList from './NavigationMenuGuideList'
|
||||
import NavigationMenuRefList from './NavigationMenuRefList'
|
||||
|
||||
import spec_js_v2 from '~/../../spec/supabase_js_v2.yml' assert { type: 'yml' }
|
||||
import spec_js_v1 from '~/../../spec/supabase_js_v1.yml' assert { type: 'yml' }
|
||||
import spec_dart_v1 from '~/../../spec/supabase_dart_v1.yml' assert { type: 'yml' }
|
||||
import spec_dart_v0 from '~/../../spec/supabase_dart_v0.yml' assert { type: 'yml' }
|
||||
import spec_csharp_v0 from '~/../../spec/supabase_csharp_v0.yml' assert { type: 'yml' }
|
||||
import spec_python_v2 from '~/../../spec/supabase_py_v2.yml' assert { type: 'yml' }
|
||||
import spec_swift_v0 from '~/../../spec/supabase_swift_v0.yml' assert { type: 'yml' }
|
||||
|
||||
// import { gen_v3 } from '~/lib/refGenerator/helpers'
|
||||
import apiCommonSections from '~/../../spec/common-api-sections.json'
|
||||
import cliCommonSections from '~/../../spec/common-cli-sections.json'
|
||||
import libCommonSections from '~/../../spec/common-client-libs-sections.json'
|
||||
import authServerCommonSections from '~/../../spec/common-self-hosting-auth-sections.json'
|
||||
import realtimeServerCommonSections from '~/../../spec/common-self-hosting-realtime-sections.json'
|
||||
import analyticsServerCommonSections from '~/../../spec/common-self-hosting-analytics-sections.json'
|
||||
import functionsServerCommonSections from '~/../../spec/common-self-hosting-functions-sections.json'
|
||||
import storageServerCommonSections from '~/../../spec/common-self-hosting-storage-sections.json'
|
||||
import { flattenSections } from '~/lib/helpers'
|
||||
import NavigationMenuHome from './HomeMenu'
|
||||
import { Json } from '~/types'
|
||||
import { ICommonBase } from '~/components/reference/Reference.types'
|
||||
|
||||
// Filter libCommonSections for just the relevant sections in the current library
|
||||
export function generateAllowedClientLibKeys(sections, spec) {
|
||||
// Filter parent sections first
|
||||
|
||||
const specIds = spec.functions.map((func) => {
|
||||
return func.id
|
||||
})
|
||||
|
||||
const newShape = flattenSections(sections).filter((section) => {
|
||||
if (specIds.includes(section.id)) {
|
||||
return section
|
||||
}
|
||||
})
|
||||
|
||||
const final = newShape.map((func) => {
|
||||
return func.id
|
||||
})
|
||||
|
||||
return final
|
||||
// Import dynamically to code split / reduce app bundle size
|
||||
const specImports = {
|
||||
specJsV1: async () => (await import('~/../../spec/supabase_js_v1.yml')).default,
|
||||
specJsV2: async () => (await import('~/../../spec/supabase_js_v2.yml')).default,
|
||||
specDartV0: async () => (await import('~/../../spec/supabase_dart_v0.yml')).default,
|
||||
specDartV1: async () => (await import('~/../../spec/supabase_dart_v1.yml')).default,
|
||||
specPythonV2: async () => (await import('~/../../spec/supabase_py_v2.yml')).default,
|
||||
specCSharpV0: async () => (await import('~/../../spec/supabase_csharp_v0.yml')).default,
|
||||
specSwiftV0: async () => (await import('~/../../spec/supabase_swift_v0.yml')).default,
|
||||
}
|
||||
|
||||
export type RefIdOptions =
|
||||
| 'reference_javascript_v1'
|
||||
| 'reference_javascript_v2'
|
||||
| 'reference_dart_v0'
|
||||
| 'reference_dart_v1'
|
||||
| 'reference_csharp_v0'
|
||||
| 'reference_python_v2'
|
||||
| 'reference_swift_v0'
|
||||
| 'reference_cli'
|
||||
| 'reference_api'
|
||||
| 'reference_self_hosting_auth'
|
||||
| 'reference_self_hosting_storage'
|
||||
| 'reference_self_hosting_realtime'
|
||||
| 'reference_self_hosting_analytics'
|
||||
| 'reference_self_hosting_functions'
|
||||
const commonSectionImports = {
|
||||
apiCommonSections: async () => (await import('~/../../spec/common-api-sections.json')).default,
|
||||
cliCommonSections: async () => (await import('~/../../spec/common-cli-sections.json')).default,
|
||||
libCommonSections: async () =>
|
||||
(await import('~/../../spec/common-client-libs-sections.json')).default,
|
||||
analyticsServerCommonSections: async () =>
|
||||
(await import('~/../../spec/common-self-hosting-analytics-sections.json')).default,
|
||||
authServerCommonSections: async () =>
|
||||
(await import('~/../../spec/common-self-hosting-auth-sections.json')).default,
|
||||
functionsServerCommonSections: async () =>
|
||||
(await import('~/../../spec/common-self-hosting-functions-sections.json')).default,
|
||||
realtimeServerCommonSections: async () =>
|
||||
(await import('~/../../spec/common-self-hosting-realtime-sections.json')).default,
|
||||
storageServerCommonSections: async () =>
|
||||
(await import('~/../../spec/common-self-hosting-storage-sections.json')).default,
|
||||
}
|
||||
|
||||
export type RefKeyOptions =
|
||||
| 'javascript'
|
||||
| 'dart'
|
||||
| 'csharp'
|
||||
| 'python'
|
||||
| 'swift'
|
||||
| 'cli'
|
||||
| 'api'
|
||||
| 'self-hosting-auth'
|
||||
| 'self-hosting-storage'
|
||||
| 'self-hosting-realtime'
|
||||
| 'self-hosting-analytics'
|
||||
| 'self-hosting-functions'
|
||||
interface BaseMenu {
|
||||
id: string
|
||||
path: string
|
||||
type: string
|
||||
}
|
||||
|
||||
interface HomeMenu extends BaseMenu {
|
||||
type: 'home'
|
||||
}
|
||||
|
||||
interface GuideMenu extends BaseMenu {
|
||||
type: 'guide'
|
||||
}
|
||||
|
||||
interface ReferenceMenu extends BaseMenu {
|
||||
type: 'reference'
|
||||
commonSectionImport: () => Promise<ICommonBase[]>
|
||||
specImport?: () => Promise<Json>
|
||||
}
|
||||
|
||||
type Menu = HomeMenu | GuideMenu | ReferenceMenu
|
||||
|
||||
const menus: Menu[] = [
|
||||
{
|
||||
id: 'home',
|
||||
path: '/',
|
||||
type: 'home',
|
||||
},
|
||||
{
|
||||
id: 'gettingstarted',
|
||||
path: '/guides/getting-started',
|
||||
type: 'guide',
|
||||
},
|
||||
{
|
||||
id: 'database',
|
||||
path: '/guides/database',
|
||||
type: 'guide',
|
||||
},
|
||||
{
|
||||
id: 'api',
|
||||
path: '/guides/api',
|
||||
type: 'guide',
|
||||
},
|
||||
{
|
||||
id: 'auth',
|
||||
path: '/guides/auth',
|
||||
type: 'guide',
|
||||
},
|
||||
{
|
||||
id: 'functions',
|
||||
path: '/guides/functions',
|
||||
type: 'guide',
|
||||
},
|
||||
{
|
||||
id: 'realtime',
|
||||
path: '/guides/realtime',
|
||||
type: 'guide',
|
||||
},
|
||||
{
|
||||
id: 'storage',
|
||||
path: '/guides/storage',
|
||||
type: 'guide',
|
||||
},
|
||||
{
|
||||
id: 'platform',
|
||||
path: '/guides/platform',
|
||||
type: 'guide',
|
||||
},
|
||||
{
|
||||
id: 'resources',
|
||||
path: '/guides/resources',
|
||||
type: 'guide',
|
||||
},
|
||||
{
|
||||
id: 'self_hosting',
|
||||
path: '/guides/self-hosting',
|
||||
type: 'guide',
|
||||
},
|
||||
{
|
||||
id: 'integrations',
|
||||
path: '/guides/integrations',
|
||||
type: 'guide',
|
||||
},
|
||||
{
|
||||
id: 'supabase_cli',
|
||||
// TODO: Add path '/reference/cli/config'
|
||||
path: '/guides/cli',
|
||||
type: 'guide',
|
||||
},
|
||||
{
|
||||
id: 'reference_javascript_v1',
|
||||
path: '/reference/javascript/v1',
|
||||
commonSectionImport: commonSectionImports.libCommonSections,
|
||||
specImport: specImports.specJsV1,
|
||||
type: 'reference',
|
||||
},
|
||||
{
|
||||
id: 'reference_javascript_v2',
|
||||
path: '/reference/javascript',
|
||||
commonSectionImport: commonSectionImports.libCommonSections,
|
||||
specImport: specImports.specJsV2,
|
||||
type: 'reference',
|
||||
},
|
||||
{
|
||||
id: 'reference_dart_v0',
|
||||
path: '/reference/dart/v0',
|
||||
commonSectionImport: commonSectionImports.libCommonSections,
|
||||
specImport: specImports.specDartV0,
|
||||
type: 'reference',
|
||||
},
|
||||
{
|
||||
id: 'reference_dart_v1',
|
||||
path: '/reference/dart',
|
||||
commonSectionImport: commonSectionImports.libCommonSections,
|
||||
specImport: specImports.specDartV1,
|
||||
type: 'reference',
|
||||
},
|
||||
{
|
||||
id: 'reference_csharp_v0',
|
||||
path: '/reference/csharp',
|
||||
commonSectionImport: commonSectionImports.libCommonSections,
|
||||
specImport: specImports.specCSharpV0,
|
||||
type: 'reference',
|
||||
},
|
||||
{
|
||||
id: 'reference_python_v2',
|
||||
path: '/reference/python',
|
||||
commonSectionImport: commonSectionImports.libCommonSections,
|
||||
specImport: specImports.specPythonV2,
|
||||
type: 'reference',
|
||||
},
|
||||
{
|
||||
id: 'reference_swift_v0',
|
||||
path: '/reference/swift',
|
||||
commonSectionImport: commonSectionImports.libCommonSections,
|
||||
specImport: specImports.specSwiftV0,
|
||||
type: 'reference',
|
||||
},
|
||||
{
|
||||
id: 'reference_cli',
|
||||
path: '/reference/cli',
|
||||
commonSectionImport: commonSectionImports.cliCommonSections,
|
||||
type: 'reference',
|
||||
},
|
||||
{
|
||||
id: 'reference_api',
|
||||
path: '/reference/api',
|
||||
commonSectionImport: commonSectionImports.apiCommonSections,
|
||||
type: 'reference',
|
||||
},
|
||||
{
|
||||
id: 'reference_self_hosting_auth',
|
||||
path: '/reference/self-hosting-auth',
|
||||
commonSectionImport: commonSectionImports.authServerCommonSections,
|
||||
type: 'reference',
|
||||
},
|
||||
{
|
||||
id: 'reference_self_hosting_storage',
|
||||
path: '/reference/self-hosting-storage',
|
||||
commonSectionImport: commonSectionImports.storageServerCommonSections,
|
||||
type: 'reference',
|
||||
},
|
||||
{
|
||||
id: 'reference_self_hosting_realtime',
|
||||
path: '/reference/self-hosting-realtime',
|
||||
commonSectionImport: commonSectionImports.realtimeServerCommonSections,
|
||||
type: 'reference',
|
||||
},
|
||||
{
|
||||
id: 'reference_self_hosting_analytics',
|
||||
path: '/reference/self-hosting-analytics',
|
||||
commonSectionImport: commonSectionImports.analyticsServerCommonSections,
|
||||
type: 'reference',
|
||||
},
|
||||
{
|
||||
id: 'reference_self_hosting_functions',
|
||||
path: '/reference/self-hosting-functions',
|
||||
commonSectionImport: commonSectionImports.functionsServerCommonSections,
|
||||
type: 'reference',
|
||||
},
|
||||
]
|
||||
|
||||
function getMenuById(id: string) {
|
||||
return menus.find((menu) => menu.id === id)
|
||||
}
|
||||
|
||||
function getMenuByUrl(basePath: string, url: string) {
|
||||
// If multiple matches, choose the menu with the longest path
|
||||
const [menu] = menus
|
||||
.filter(({ path }) => url.startsWith(`${basePath}${path}`))
|
||||
.sort((a, b) => b.path.length - a.path.length)
|
||||
|
||||
return menu
|
||||
}
|
||||
|
||||
function getMenuElement(menu: Menu) {
|
||||
const menuType = menu.type
|
||||
switch (menuType) {
|
||||
case 'home':
|
||||
return <NavigationMenuHome active />
|
||||
case 'guide':
|
||||
return <NavigationMenuGuideList id={menu.id} active />
|
||||
case 'reference':
|
||||
return (
|
||||
<NavigationMenuRefList
|
||||
id={menu.id}
|
||||
basePath={menu.path}
|
||||
commonSectionsImport={menu.commonSectionImport}
|
||||
specImport={menu.specImport}
|
||||
/>
|
||||
)
|
||||
default:
|
||||
throw new Error(`Unknown menu type '${menuType}'`)
|
||||
}
|
||||
}
|
||||
|
||||
const NavigationMenu = () => {
|
||||
const router = useRouter()
|
||||
|
||||
function handleRouteChange(url: string) {
|
||||
switch (url) {
|
||||
case `/docs`:
|
||||
menuState.setMenuLevelId('home')
|
||||
break
|
||||
case url.includes(`/docs/guides/getting-started`) && url:
|
||||
menuState.setMenuLevelId('gettingstarted')
|
||||
break
|
||||
case url.includes(`/docs/guides/database`) && url:
|
||||
menuState.setMenuLevelId('database')
|
||||
break
|
||||
case url.includes(`/docs/guides/api`) && url:
|
||||
menuState.setMenuLevelId('api')
|
||||
break
|
||||
case url.includes(`/docs/guides/auth`) && url:
|
||||
menuState.setMenuLevelId('auth')
|
||||
break
|
||||
case url.includes(`/docs/guides/functions`) && url:
|
||||
menuState.setMenuLevelId('functions')
|
||||
break
|
||||
case url.includes(`/docs/guides/realtime`) && url:
|
||||
menuState.setMenuLevelId('realtime')
|
||||
break
|
||||
case url.includes(`/docs/guides/storage`) && url:
|
||||
menuState.setMenuLevelId('storage')
|
||||
break
|
||||
case url.includes(`/docs/guides/platform`) && url:
|
||||
menuState.setMenuLevelId('platform')
|
||||
break
|
||||
case url.includes(`/docs/guides/resources`) && url:
|
||||
menuState.setMenuLevelId('resources')
|
||||
break
|
||||
case url.includes(`/docs/guides/self-hosting`) && url:
|
||||
menuState.setMenuLevelId('self_hosting')
|
||||
break
|
||||
case url.includes(`/docs/guides/integrations`) && url:
|
||||
menuState.setMenuLevelId('integrations')
|
||||
break
|
||||
case url.includes(`/docs/guides/cli`) && url:
|
||||
menuState.setMenuLevelId('supabase_cli')
|
||||
break
|
||||
// JS v1
|
||||
case url.includes(`/docs/reference/javascript/v1`) && url:
|
||||
menuState.setMenuLevelId('reference_javascript_v1')
|
||||
break
|
||||
// JS v2 (latest)
|
||||
case url.includes(`/docs/reference/javascript`) && url:
|
||||
menuState.setMenuLevelId('reference_javascript_v2')
|
||||
break
|
||||
// dart v0
|
||||
case url.includes(`/docs/reference/dart/v0`) && url:
|
||||
menuState.setMenuLevelId('reference_dart_v0')
|
||||
break
|
||||
// dart v1 (latest)
|
||||
case url.includes(`/docs/reference/dart`) && url:
|
||||
menuState.setMenuLevelId('reference_dart_v1')
|
||||
break
|
||||
// C# v0 (latest)
|
||||
case url.includes(`/docs/reference/csharp`) && url:
|
||||
menuState.setMenuLevelId('reference_csharp_v0')
|
||||
break
|
||||
// python v2 (latest)
|
||||
case url.includes(`/docs/reference/python`) && url:
|
||||
menuState.setMenuLevelId('reference_python_v2')
|
||||
break
|
||||
// swift v1 (latest)
|
||||
case url.includes(`/docs/reference/swift`) && url:
|
||||
menuState.setMenuLevelId('reference_swift_v0')
|
||||
break
|
||||
case url.includes(`/docs/reference/cli/config`) && url:
|
||||
menuState.setMenuLevelId('supabase_cli')
|
||||
break
|
||||
case url.includes(`/docs/reference/cli`) && url:
|
||||
menuState.setMenuLevelId('reference_cli')
|
||||
break
|
||||
case url.includes(`/docs/reference/api`) && url:
|
||||
menuState.setMenuLevelId('reference_api')
|
||||
break
|
||||
case url.includes(`/docs/reference/self-hosting-auth`) && url:
|
||||
menuState.setMenuLevelId('reference_self_hosting_auth')
|
||||
break
|
||||
case url.includes(`/docs/reference/self-hosting-storage`) && url:
|
||||
menuState.setMenuLevelId('reference_self_hosting_storage')
|
||||
break
|
||||
case url.includes(`/docs/reference/self-hosting-realtime`) && url:
|
||||
menuState.setMenuLevelId('reference_self_hosting_realtime')
|
||||
break
|
||||
case url.includes(`/docs/reference/self-hosting-analytics`) && url:
|
||||
menuState.setMenuLevelId('reference_self_hosting_analytics')
|
||||
break
|
||||
case url.includes(`/docs/reference/self-hosting-functions`) && url:
|
||||
menuState.setMenuLevelId('reference_self_hosting_functions')
|
||||
break
|
||||
|
||||
default:
|
||||
break
|
||||
const menu = getMenuByUrl(router.basePath, url)
|
||||
if (menu) {
|
||||
menuState.setMenuLevelId(menu.id)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,168 +271,9 @@ const NavigationMenu = () => {
|
||||
}, [router.events])
|
||||
|
||||
const level = useMenuLevelId()
|
||||
const menu = getMenuById(level)
|
||||
|
||||
const isHomeActive = 'home' === level
|
||||
const isGettingStartedActive = 'gettingstarted' === level
|
||||
const isDatabaseActive = 'database' === level
|
||||
const isApiActive = 'api' === level
|
||||
const isAuthActive = 'auth' === level
|
||||
const isFunctionsActive = 'functions' === level
|
||||
const isRealtimeActive = 'realtime' === level
|
||||
const isStorageActive = 'storage' === level
|
||||
const issupabase_cliActive = 'supabase_cli' === level
|
||||
const isPlatformActive = 'platform' === level
|
||||
const isResourcesActive = 'resources' === level
|
||||
const isSelfHosting = 'self_hosting' === level
|
||||
const isIntegrationsActive = 'integrations' === level
|
||||
const isReferenceActive = 'reference' === level
|
||||
|
||||
const isReference_Javascript_V1 = 'reference_javascript_v1' === level
|
||||
const isReference_Javascript_V2 = 'reference_javascript_v2' === level
|
||||
const isReference_Dart_V0 = 'reference_dart_v0' === level
|
||||
const isReference_Dart_V1 = 'reference_dart_v1' === level
|
||||
const isReference_Csharp_V0 = 'reference_csharp_v0' === level
|
||||
const isReference_Python_V2 = 'reference_python_v2' === level
|
||||
const isReference_Swift_V0 = 'reference_swift_v0' === level
|
||||
const isReference_Cli = 'reference_cli' === level
|
||||
const isReference_Api = 'reference_api' === level
|
||||
const isReference_Self_Hosting_Auth = 'reference_self_hosting_auth' === level
|
||||
const isReference_Self_Hosting_Storage = 'reference_self_hosting_storage' === level
|
||||
const isReference_Self_Hosting_Realtime = 'reference_self_hosting_realtime' === level
|
||||
const isReference_Self_Hosting_Analytics = 'reference_self_hosting_analytics' === level
|
||||
const isReference_Self_Hosting_Functions = 'reference_self_hosting_functions' === level
|
||||
|
||||
return (
|
||||
<div className={['flex relative', 'justify-center lg:justify-start'].join(' ')}>
|
||||
{/* // main menu */}
|
||||
<NavigationMenuHome active={isHomeActive} />
|
||||
<NavigationMenuGuideList id={'gettingstarted'} active={isGettingStartedActive} />
|
||||
<NavigationMenuGuideList id={'database'} active={isDatabaseActive} />
|
||||
<NavigationMenuGuideList id={'api'} active={isApiActive} />
|
||||
<NavigationMenuGuideList id={'auth'} active={isAuthActive} />
|
||||
<NavigationMenuGuideList id={'functions'} active={isFunctionsActive} />
|
||||
<NavigationMenuGuideList
|
||||
id={'realtime'}
|
||||
active={isRealtimeActive}
|
||||
value={['/guides/realtime/extensions']}
|
||||
/>
|
||||
<NavigationMenuGuideList id={'storage'} active={isStorageActive} />
|
||||
<NavigationMenuGuideList id={'supabase_cli'} active={issupabase_cliActive} />
|
||||
<NavigationMenuGuideList id={'platform'} active={isPlatformActive} />
|
||||
<NavigationMenuGuideList id={'resources'} active={isResourcesActive} />
|
||||
<NavigationMenuGuideList id={'self_hosting'} active={isSelfHosting} />
|
||||
<NavigationMenuGuideList id={'integrations'} active={isIntegrationsActive} />
|
||||
<NavigationMenuGuideList id={'reference'} active={isReferenceActive} />
|
||||
{/* // Client Libs */}
|
||||
<NavigationMenuRefList
|
||||
key={'reference-js-menu-v1'}
|
||||
id={'reference_javascript_v1'}
|
||||
active={isReference_Javascript_V1}
|
||||
commonSections={libCommonSections}
|
||||
lib="javascript"
|
||||
spec={spec_js_v1}
|
||||
/>
|
||||
<NavigationMenuRefList
|
||||
key={'reference-js-menu'}
|
||||
id={'reference_javascript_v2'}
|
||||
active={isReference_Javascript_V2}
|
||||
commonSections={libCommonSections}
|
||||
lib="javascript"
|
||||
spec={spec_js_v2}
|
||||
/>
|
||||
<NavigationMenuRefList
|
||||
key={'reference-dart-menu'}
|
||||
id={'reference_dart_v0'}
|
||||
active={isReference_Dart_V0}
|
||||
commonSections={libCommonSections}
|
||||
lib="dart"
|
||||
spec={spec_dart_v0}
|
||||
/>
|
||||
<NavigationMenuRefList
|
||||
key={'reference-dart-menu-v1'}
|
||||
id={'reference_dart_v1'}
|
||||
active={isReference_Dart_V1}
|
||||
commonSections={libCommonSections}
|
||||
lib="dart"
|
||||
spec={spec_dart_v1}
|
||||
/>
|
||||
<NavigationMenuRefList
|
||||
key={'reference-csharp-menu-v0'}
|
||||
id={'reference_csharp_v0'}
|
||||
active={isReference_Csharp_V0}
|
||||
commonSections={libCommonSections}
|
||||
lib="csharp"
|
||||
spec={spec_csharp_v0}
|
||||
/>
|
||||
<NavigationMenuRefList
|
||||
key={'reference-swift-menu-v1'}
|
||||
id={'reference_swift_v0'}
|
||||
active={isReference_Swift_V0}
|
||||
commonSections={libCommonSections}
|
||||
lib="swift"
|
||||
spec={spec_swift_v0}
|
||||
/>
|
||||
<NavigationMenuRefList
|
||||
key={'reference-python-menu-v2'}
|
||||
id={'reference_python_v2'}
|
||||
active={isReference_Python_V2}
|
||||
commonSections={libCommonSections}
|
||||
lib="python"
|
||||
spec={spec_python_v2}
|
||||
/>
|
||||
{/* // Tools */}
|
||||
<NavigationMenuRefList
|
||||
key={'reference-cli-menu'}
|
||||
id={'reference_cli'}
|
||||
active={isReference_Cli}
|
||||
commonSections={cliCommonSections}
|
||||
lib="cli"
|
||||
/>
|
||||
<NavigationMenuRefList
|
||||
key={'reference-api-menu'}
|
||||
id={'reference_api'}
|
||||
active={isReference_Api}
|
||||
commonSections={apiCommonSections}
|
||||
lib="api"
|
||||
/>
|
||||
{/* // Self Hosting Server */}
|
||||
<NavigationMenuRefList
|
||||
key={'reference-self-hosting-auth-menu'}
|
||||
id={'reference_self_hosting_auth'}
|
||||
active={isReference_Self_Hosting_Auth}
|
||||
commonSections={authServerCommonSections}
|
||||
lib="self-hosting-auth"
|
||||
/>
|
||||
<NavigationMenuRefList
|
||||
key={'reference-self-hosting-storage-menu'}
|
||||
id={'reference_self_hosting_storage'}
|
||||
active={isReference_Self_Hosting_Storage}
|
||||
commonSections={storageServerCommonSections}
|
||||
lib="self-hosting-storage"
|
||||
/>
|
||||
<NavigationMenuRefList
|
||||
key={'reference-self-hosting-realtime-menu'}
|
||||
id={'reference_self_hosting_realtime'}
|
||||
active={isReference_Self_Hosting_Realtime}
|
||||
commonSections={realtimeServerCommonSections}
|
||||
lib="self-hosting-realtime"
|
||||
/>
|
||||
<NavigationMenuRefList
|
||||
key={'reference-self-hosting-analytics-menu'}
|
||||
id={'reference_self_hosting_analytics'}
|
||||
active={isReference_Self_Hosting_Analytics}
|
||||
commonSections={analyticsServerCommonSections}
|
||||
lib="self-hosting-analytics"
|
||||
/>
|
||||
<NavigationMenuRefList
|
||||
key={'reference-self-hosting-functions-menu'}
|
||||
id={'reference_self_hosting_functions'}
|
||||
active={isReference_Self_Hosting_Functions}
|
||||
commonSections={functionsServerCommonSections}
|
||||
lib="self-hosting-functions"
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
return getMenuElement(menu)
|
||||
}
|
||||
|
||||
export default memo(NavigationMenu)
|
||||
|
||||
@@ -1,6 +1,31 @@
|
||||
import { ICommonItem } from '~/components/reference/Reference.types'
|
||||
|
||||
// check if the link is allowed to be displayed
|
||||
export function isFuncNotInLibraryOrVersion(id, type, allowedKeys) {
|
||||
if (id && allowedKeys && !allowedKeys.includes(id) && type !== 'markdown') {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively filter common sections and their sub items based on
|
||||
* what is available in their spec
|
||||
*/
|
||||
export function deepFilterSections(sections: ICommonItem[], specFunctionIds: string[]) {
|
||||
return sections
|
||||
.filter(
|
||||
(section) =>
|
||||
section.type === 'category' ||
|
||||
section.type === 'markdown' ||
|
||||
specFunctionIds.includes(section.id)
|
||||
)
|
||||
.map((section) => {
|
||||
if ('items' in section) {
|
||||
return {
|
||||
...section,
|
||||
items: deepFilterSections(section.items, specFunctionIds),
|
||||
}
|
||||
}
|
||||
return section
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,31 +1,51 @@
|
||||
// import apiCommonSections from '~/../../spec/common-client-libs-sections.json'
|
||||
|
||||
import { RefIdOptions, RefKeyOptions } from './NavigationMenu'
|
||||
import { Json } from '~/types'
|
||||
import NavigationMenuRefListItems from './NavigationMenuRefListItems'
|
||||
|
||||
import React from 'react'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { ICommonBase, ICommonItem } from '~/components/reference/Reference.types'
|
||||
|
||||
interface INavigationMenuRefList {
|
||||
id: RefIdOptions
|
||||
lib: RefKeyOptions
|
||||
commonSections: any[] // to do type up
|
||||
|
||||
// the keys of menu items that are allowed to be shown on the side menu
|
||||
// if undefined, we show all the menu items
|
||||
allowedClientKeys?: string[]
|
||||
active: boolean
|
||||
spec?: any
|
||||
interface NavigationMenuRefListProps {
|
||||
id: string
|
||||
basePath: string
|
||||
commonSectionsImport: () => Promise<ICommonBase[]>
|
||||
specImport?: () => Promise<Json>
|
||||
}
|
||||
|
||||
const NavigationMenuRefList: React.FC<INavigationMenuRefList> = ({
|
||||
const NavigationMenuRefList = ({
|
||||
id,
|
||||
lib,
|
||||
commonSections,
|
||||
basePath,
|
||||
commonSectionsImport,
|
||||
specImport,
|
||||
}: NavigationMenuRefListProps) => {
|
||||
const [commonSections, setCommonSections] = useState<ICommonItem[]>()
|
||||
const [spec, setSpec] = useState<Json>()
|
||||
|
||||
active,
|
||||
spec,
|
||||
}) => {
|
||||
if (!active) {
|
||||
// Dynamic imports allow for code splitting which
|
||||
// dramatically reduces app bundle size
|
||||
useEffect(() => {
|
||||
async function fetchCommonSections() {
|
||||
const commonSections = await commonSectionsImport()
|
||||
setCommonSections(commonSections as ICommonItem[])
|
||||
}
|
||||
fetchCommonSections()
|
||||
}, [commonSectionsImport])
|
||||
|
||||
useEffect(() => {
|
||||
if (!specImport) {
|
||||
return
|
||||
}
|
||||
async function fetchSpec() {
|
||||
const spec = await specImport()
|
||||
setSpec(spec)
|
||||
}
|
||||
fetchSpec()
|
||||
}, [specImport])
|
||||
|
||||
if (!commonSections) {
|
||||
return null
|
||||
}
|
||||
|
||||
if (specImport && !spec) {
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -34,19 +54,13 @@ const NavigationMenuRefList: React.FC<INavigationMenuRefList> = ({
|
||||
})
|
||||
|
||||
return (
|
||||
<div
|
||||
className={[
|
||||
'transition-all duration-150 ease-out',
|
||||
// enabled
|
||||
active && 'opacity-100 ml-0 delay-150 h-auto',
|
||||
// move menu back to margin-left
|
||||
// level === 'home' && 'ml-12',
|
||||
// disabled
|
||||
// level !== 'home' && level !== id ? '-ml-8' : '',
|
||||
!active ? 'opacity-0 invisible absolute h-0 overflow-hidden' : '',
|
||||
].join(' ')}
|
||||
>
|
||||
<NavigationMenuRefListItems id={id} lib={lib} commonSections={filteredSections} spec={spec} />
|
||||
<div className="transition-all duration-150 ease-out opacity-100 ml-0 delay-150 h-auto">
|
||||
<NavigationMenuRefListItems
|
||||
id={id}
|
||||
commonSections={filteredSections}
|
||||
spec={spec}
|
||||
basePath={basePath}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -4,17 +4,15 @@ import { useRouter } from 'next/router'
|
||||
import { IconChevronLeft } from 'ui'
|
||||
import * as NavItems from './NavigationMenu.constants'
|
||||
|
||||
import { find } from 'lodash'
|
||||
import Image from 'next/image'
|
||||
import { useTheme } from 'common/Providers'
|
||||
import Image from 'next/image'
|
||||
|
||||
import RevVersionDropdown from '~/components/RefVersionDropdown'
|
||||
import { useMenuActiveRefId } from '~/hooks/useMenuState'
|
||||
import { RefIdOptions, RefKeyOptions } from './NavigationMenu'
|
||||
|
||||
import React, { Fragment } from 'react'
|
||||
import { generateAllowedClientLibKeys } from '~/lib/refGenerator/helpers'
|
||||
import { isFuncNotInLibraryOrVersion } from './NavigationMenu.utils'
|
||||
import { ICommonItem, ICommonSection } from '~/components/reference/Reference.types'
|
||||
import { deepFilterSections } from './NavigationMenu.utils'
|
||||
|
||||
const HeaderImage = React.memo(function HeaderImage(props: any) {
|
||||
const router = useRouter()
|
||||
@@ -40,38 +38,29 @@ const HeaderLink = React.memo(function HeaderLink(props: any) {
|
||||
)
|
||||
})
|
||||
|
||||
const FunctionLink = React.memo(function FunctionLink({
|
||||
title,
|
||||
id,
|
||||
icon,
|
||||
library,
|
||||
slug,
|
||||
}: {
|
||||
interface FunctionLinkProps {
|
||||
title: string
|
||||
name?: string
|
||||
id: string
|
||||
icon?: string
|
||||
product?: string
|
||||
library: string
|
||||
basePath: string
|
||||
slug: string
|
||||
}) {
|
||||
}
|
||||
|
||||
const FunctionLink = React.memo(function FunctionLink({
|
||||
title,
|
||||
id,
|
||||
icon,
|
||||
basePath,
|
||||
slug,
|
||||
}: FunctionLinkProps) {
|
||||
const router = useRouter()
|
||||
const activeAccordianItem = useMenuActiveRefId()
|
||||
const activeAccordionItem = useMenuActiveRefId()
|
||||
|
||||
// check if we're on a versioned page
|
||||
let version = ''
|
||||
if (router.asPath.includes('v1')) {
|
||||
version = 'v1'
|
||||
}
|
||||
|
||||
if (router.asPath.includes('v0')) {
|
||||
version = 'v0'
|
||||
}
|
||||
|
||||
const active = activeAccordianItem === id
|
||||
const active = activeAccordionItem === id
|
||||
return (
|
||||
<li key={id} className="function-link-item">
|
||||
<Link href={`/reference/${library}/${version ? version + '/' : ''}${slug}`} passHref>
|
||||
<li className="function-link-item">
|
||||
<Link href={`${basePath}/${slug}`} passHref>
|
||||
<a
|
||||
className={[
|
||||
'cursor-pointer transition text-sm hover:text-brand-900 flex gap-3',
|
||||
@@ -86,63 +75,43 @@ const FunctionLink = React.memo(function FunctionLink({
|
||||
)
|
||||
})
|
||||
|
||||
const RenderLink = React.memo(function RenderLink(props: any) {
|
||||
const activeAccordianItem = useMenuActiveRefId()
|
||||
let active = false
|
||||
export interface RenderLinkProps {
|
||||
section: ICommonSection
|
||||
basePath: string
|
||||
}
|
||||
|
||||
const isFilter = props.filterIds?.includes(activeAccordianItem)
|
||||
const isModifier = props.modifierIds?.includes(activeAccordianItem)
|
||||
const isAuthServer = props.authServerIds?.includes(activeAccordianItem)
|
||||
const RenderLink = React.memo(function RenderLink({ section, basePath }: RenderLinkProps) {
|
||||
const activeAccordionItem = useMenuActiveRefId()
|
||||
|
||||
if (
|
||||
(isFilter && props.id === 'using-filters') ||
|
||||
(activeAccordianItem === 'using-filters' && props.id === 'using-filters')
|
||||
) {
|
||||
active = true
|
||||
} else if (
|
||||
(isModifier && props.id === 'using-modifiers') ||
|
||||
(activeAccordianItem === 'using-modifiers' && props.id === 'using-modifiers')
|
||||
) {
|
||||
active = true
|
||||
} else if (
|
||||
(isAuthServer && props.id === 'admin-api') ||
|
||||
(activeAccordianItem === 'admin-api' && props.id === 'admin-api')
|
||||
) {
|
||||
active = true
|
||||
} else {
|
||||
active = false
|
||||
if (!('items' in section)) {
|
||||
return (
|
||||
<FunctionLink title={section.title} id={section.id} slug={section.slug} basePath={basePath} />
|
||||
)
|
||||
}
|
||||
|
||||
let active = section.items.some((item) => item.id === activeAccordionItem)
|
||||
|
||||
return (
|
||||
<Accordion.Root
|
||||
collapsible
|
||||
key={props.id + '-accordian-root-for-func-' + props.index}
|
||||
type="single"
|
||||
value={active ? props.id : ''}
|
||||
>
|
||||
<Accordion.Item key={props.id + '-accordian-item'} value={props.id}>
|
||||
<FunctionLink library={props.lib} title={props.title} id={props.id} slug={props.slug} />
|
||||
<Accordion.Content
|
||||
key={props.id + '-sub-items-accordion-container'}
|
||||
className="transition data-open:animate-slide-down data-closed:animate-slide-up ml-2"
|
||||
>
|
||||
{props.items &&
|
||||
props.items
|
||||
.filter((item) => props.allowedKeys.includes(item.id))
|
||||
.map((item) => {
|
||||
return (
|
||||
<FunctionLink
|
||||
key={item.title}
|
||||
library={props.lib}
|
||||
title={item.title}
|
||||
id={item.id}
|
||||
slug={item.slug}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</Accordion.Content>
|
||||
</Accordion.Item>
|
||||
</Accordion.Root>
|
||||
<>
|
||||
<FunctionLink title={section.title} id={section.id} slug={section.slug} basePath={basePath} />
|
||||
<Accordion.Root collapsible type="single" value={active ? section.id : ''}>
|
||||
<Accordion.Item value={section.id}>
|
||||
<Accordion.Content className="transition data-open:animate-slide-down data-closed:animate-slide-up ml-2">
|
||||
{section.items.map((item) => {
|
||||
return (
|
||||
<FunctionLink
|
||||
key={item.id}
|
||||
title={item.title}
|
||||
id={item.id}
|
||||
slug={item.slug}
|
||||
basePath={basePath}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</Accordion.Content>
|
||||
</Accordion.Item>
|
||||
</Accordion.Root>
|
||||
</>
|
||||
)
|
||||
})
|
||||
|
||||
@@ -158,67 +127,25 @@ const Divider = () => {
|
||||
return <div className="h-px w-full bg-blackA-300 dark:bg-whiteA-300 my-3"></div>
|
||||
}
|
||||
|
||||
interface INavigationMenuRefList {
|
||||
id: RefIdOptions
|
||||
lib: RefKeyOptions
|
||||
commonSections: any[] // to do type up
|
||||
|
||||
// the keys of menu items that are allowed to be shown on the side menu
|
||||
// if undefined, we show all the menu items
|
||||
allowedClientKeys?: string[]
|
||||
interface NavigationMenuRefListItemsProps {
|
||||
id: string
|
||||
basePath: string
|
||||
commonSections: ICommonItem[]
|
||||
spec?: any
|
||||
}
|
||||
|
||||
const Content: React.FC<INavigationMenuRefList> = ({ id, lib, commonSections, spec }) => {
|
||||
const allowedClientKeys = spec ? generateAllowedClientLibKeys(commonSections, spec) : undefined
|
||||
|
||||
let sections = commonSections
|
||||
|
||||
const allowedKeys = allowedClientKeys
|
||||
|
||||
if (!sections) console.error('no common sections imported')
|
||||
|
||||
const NavigationMenuRefListItems = ({
|
||||
id,
|
||||
basePath,
|
||||
commonSections,
|
||||
spec,
|
||||
}: NavigationMenuRefListItemsProps) => {
|
||||
const menu = NavItems[id]
|
||||
const databaseFunctions = find(sections, { title: 'Database' })
|
||||
? find(sections, { title: 'Database' }).items
|
||||
: []
|
||||
|
||||
const authFunctions = find(sections, { title: 'Auth' })
|
||||
? find(sections, { title: 'Auth' }).items
|
||||
: []
|
||||
|
||||
const filterIds =
|
||||
databaseFunctions.length > 0
|
||||
? find(databaseFunctions, {
|
||||
id: 'using-filters',
|
||||
}) &&
|
||||
find(databaseFunctions, {
|
||||
id: 'using-filters',
|
||||
})
|
||||
.items.filter((x) => allowedKeys.includes(x.id))
|
||||
.map((x) => x.id)
|
||||
: []
|
||||
const modifierIds =
|
||||
databaseFunctions.length > 0
|
||||
? find(databaseFunctions, {
|
||||
id: 'using-modifiers',
|
||||
}) &&
|
||||
find(databaseFunctions, {
|
||||
id: 'using-modifiers',
|
||||
})
|
||||
.items.filter((x) => allowedKeys.includes(x.id))
|
||||
.map((x) => x.id)
|
||||
: []
|
||||
|
||||
const authServerIds =
|
||||
databaseFunctions.length > 0
|
||||
? find(authFunctions, {
|
||||
id: 'admin-api',
|
||||
}) &&
|
||||
find(authFunctions, {
|
||||
id: 'admin-api',
|
||||
}).items.map((x) => x.id)
|
||||
: []
|
||||
const specFunctionIds = spec?.functions.map(({ id }) => id)
|
||||
const filteredSections = spec
|
||||
? deepFilterSections(commonSections, specFunctionIds)
|
||||
: commonSections
|
||||
|
||||
return (
|
||||
<div className={'w-full flex flex-col gap-0 sticky top-8'}>
|
||||
@@ -237,61 +164,26 @@ const Content: React.FC<INavigationMenuRefList> = ({ id, lib, commonSections, sp
|
||||
<span>Back to Main Menu</span>
|
||||
</a>
|
||||
</Link>
|
||||
|
||||
<div className="flex items-center gap-3 my-3">
|
||||
<HeaderImage icon={menu.icon} />
|
||||
<HeaderLink title={menu.title} url={menu.url} id={id} />
|
||||
<RevVersionDropdown />
|
||||
</div>
|
||||
|
||||
<ul className="function-link-list flex flex-col gap-1">
|
||||
{sections.map((fn: any, fnIndex) => {
|
||||
// run allow check
|
||||
if (isFuncNotInLibraryOrVersion(fn.id, fn.type, allowedKeys)) {
|
||||
return <Fragment key={fn.id}></Fragment>
|
||||
}
|
||||
|
||||
// handle subtitles with subitems
|
||||
return fn.id ? (
|
||||
<Fragment key={fn.id}>
|
||||
<RenderLink {...fn} lib={lib} />
|
||||
{fn.items &&
|
||||
fn.items.map((item) => (
|
||||
<RenderLink
|
||||
{...item}
|
||||
library={menu.title}
|
||||
index={fnIndex}
|
||||
modifierIds={modifierIds}
|
||||
filterIds={filterIds}
|
||||
authServerIds={authServerIds}
|
||||
lib={lib}
|
||||
allowedKeys={allowedKeys}
|
||||
/>
|
||||
))}
|
||||
</Fragment>
|
||||
) : (
|
||||
<Fragment key={fn.title}>
|
||||
<Divider />
|
||||
<SideMenuTitle title={fn.title} />
|
||||
{fn.items &&
|
||||
fn.items.map((item, i) => {
|
||||
// run allow check
|
||||
if (isFuncNotInLibraryOrVersion(item.id, item.type, allowedKeys))
|
||||
return <Fragment key={item.id + i}></Fragment>
|
||||
return (
|
||||
<RenderLink
|
||||
{...item}
|
||||
key={item.id + i}
|
||||
library={menu.title}
|
||||
index={fnIndex}
|
||||
modifierIds={modifierIds}
|
||||
filterIds={filterIds}
|
||||
authServerIds={authServerIds}
|
||||
lib={lib}
|
||||
allowedKeys={allowedKeys}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
{filteredSections.map((section) => {
|
||||
return (
|
||||
<Fragment key={section.title}>
|
||||
{section.type === 'category' ? (
|
||||
<>
|
||||
<Divider />
|
||||
<SideMenuTitle title={section.title} />
|
||||
{section.items.map((item) => (
|
||||
<RenderLink section={item} basePath={basePath} />
|
||||
))}
|
||||
</>
|
||||
) : (
|
||||
<RenderLink section={section} basePath={basePath} />
|
||||
)}
|
||||
</Fragment>
|
||||
)
|
||||
})}
|
||||
@@ -300,4 +192,4 @@ const Content: React.FC<INavigationMenuRefList> = ({ id, lib, commonSections, sp
|
||||
)
|
||||
}
|
||||
|
||||
export default React.memo(Content)
|
||||
export default React.memo(NavigationMenuRefListItems)
|
||||
|
||||
@@ -8,10 +8,10 @@ import RefFunctionSection from '~/components/reference/RefFunctionSection'
|
||||
import RefSubLayout from '~/layouts/ref/RefSubLayout'
|
||||
import ApiOperationSection from './ApiOperationSection'
|
||||
import CliCommandSection from './CLICommandSection'
|
||||
import { IAPISpec, ICommonFunc, IRefStaticDoc, ISpec, TypeSpec } from './Reference.types'
|
||||
import { IAPISpec, ICommonSection, IRefStaticDoc, ISpec, TypeSpec } from './Reference.types'
|
||||
|
||||
interface RefSectionHandlerProps {
|
||||
sections: ICommonFunc[]
|
||||
sections: ICommonSection[]
|
||||
spec?: ISpec | IAPISpec
|
||||
typeSpec?: TypeSpec
|
||||
pageProps: { docs: IRefStaticDoc[] }
|
||||
@@ -59,46 +59,48 @@ const RefSectionHandler = (props: RefSectionHandlerProps) => {
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
</Head>
|
||||
<RefSubLayout>
|
||||
{props.sections.map((x, i) => {
|
||||
switch (x.type) {
|
||||
{props.sections.map((section, i) => {
|
||||
const sectionType = section.type
|
||||
switch (sectionType) {
|
||||
case 'markdown':
|
||||
const markdownData = props.pageProps.docs.find((doc) => doc.id === x.id)
|
||||
const markdownData = props.pageProps.docs.find((doc) => doc.id === section.id)
|
||||
|
||||
return <RefEducationSection key={x.id + i} item={x} markdownContent={markdownData} />
|
||||
break
|
||||
return (
|
||||
<RefEducationSection
|
||||
key={section.id + i}
|
||||
item={section}
|
||||
markdownContent={markdownData}
|
||||
/>
|
||||
)
|
||||
case 'function':
|
||||
return (
|
||||
<RefFunctionSection
|
||||
key={x.id + i}
|
||||
funcData={x}
|
||||
commonFuncData={x}
|
||||
key={section.id + i}
|
||||
funcData={section}
|
||||
commonFuncData={section}
|
||||
spec={props.spec}
|
||||
typeSpec={props.typeSpec}
|
||||
/>
|
||||
)
|
||||
case 'cli-command':
|
||||
return <CliCommandSection key={x.id + i} funcData={x} commonFuncData={x} />
|
||||
break
|
||||
return (
|
||||
<CliCommandSection
|
||||
key={section.id + i}
|
||||
funcData={section}
|
||||
commonFuncData={section}
|
||||
/>
|
||||
)
|
||||
case 'operation':
|
||||
return (
|
||||
<ApiOperationSection
|
||||
key={x.id + i}
|
||||
funcData={x}
|
||||
commonFuncData={x}
|
||||
key={section.id + i}
|
||||
funcData={section}
|
||||
commonFuncData={section}
|
||||
spec={props.spec}
|
||||
/>
|
||||
)
|
||||
default:
|
||||
return (
|
||||
<RefFunctionSection
|
||||
key={x.id + i}
|
||||
funcData={x}
|
||||
commonFuncData={x}
|
||||
spec={props.spec}
|
||||
typeSpec={props.typeSpec}
|
||||
/>
|
||||
)
|
||||
break
|
||||
throw new Error(`Unknown common section type '${sectionType}'`)
|
||||
}
|
||||
})}
|
||||
</RefSubLayout>
|
||||
|
||||
@@ -33,19 +33,61 @@ export interface IFunctionDefinition {
|
||||
examples?: []
|
||||
}
|
||||
|
||||
export interface ICommonFunc {
|
||||
id?: string
|
||||
export interface ICommonBase {
|
||||
type: string
|
||||
title: string
|
||||
slug?: string
|
||||
product?: string
|
||||
type?: string
|
||||
parent?: string
|
||||
items?: ICommonFunc[]
|
||||
summary?: string
|
||||
}
|
||||
|
||||
export interface ICommonBaseSection extends ICommonBase {
|
||||
id: string
|
||||
slug: string
|
||||
excludes?: string[]
|
||||
}
|
||||
|
||||
export interface ICommonCategory extends ICommonBase {
|
||||
type: 'category'
|
||||
items: ICommonSection[]
|
||||
excludes?: string[]
|
||||
}
|
||||
|
||||
export interface ICommonMarkdown extends ICommonBaseSection {
|
||||
type: 'markdown'
|
||||
}
|
||||
|
||||
export interface ICommonFunctionGroup extends ICommonBaseSection {
|
||||
type: 'function'
|
||||
isFunc: false
|
||||
product: string
|
||||
items: ICommonFunction[]
|
||||
}
|
||||
|
||||
export interface ICommonFunction extends ICommonBaseSection {
|
||||
type: 'function'
|
||||
product: string
|
||||
parent?: string
|
||||
}
|
||||
|
||||
export interface ICommonCliCommand extends ICommonBaseSection {
|
||||
type: 'cli-command'
|
||||
}
|
||||
|
||||
export interface ICommonApiOperation extends ICommonBaseSection {
|
||||
type: 'operation'
|
||||
}
|
||||
|
||||
export type ICommonSection =
|
||||
| ICommonMarkdown
|
||||
| ICommonFunctionGroup
|
||||
| ICommonFunction
|
||||
| ICommonCliCommand
|
||||
| ICommonApiOperation
|
||||
|
||||
export type ICommonItem = ICommonCategory | ICommonSection
|
||||
|
||||
export interface IRefFunctionSection {
|
||||
funcData: any
|
||||
commonFuncData: ICommonFunc
|
||||
commonFuncData: ICommonFunction
|
||||
spec: any
|
||||
typeSpec?: TypeSpec
|
||||
}
|
||||
|
||||
@@ -4,10 +4,10 @@ import Link from 'next/link'
|
||||
import NavigationMenu from '~/components/Navigation/NavigationMenu/NavigationMenu'
|
||||
import TopNavBarRef from '~/components/Navigation/NavigationMenu/TopNavBarRef'
|
||||
|
||||
import { memo, useEffect } from 'react'
|
||||
import Head from 'next/head'
|
||||
import { PropsWithChildren, memo } from 'react'
|
||||
import Footer from '~/components/Navigation/Footer'
|
||||
import { menuState, useMenuLevelId, useMenuMobileOpen } from '~/hooks/useMenuState'
|
||||
import Head from 'next/head'
|
||||
|
||||
const levelsData = {
|
||||
home: {
|
||||
@@ -207,25 +207,6 @@ const MobileMenuBackdrop = memo(function MobileMenuBackdrop() {
|
||||
)
|
||||
})
|
||||
|
||||
const SideMenu = memo(function SideMenu() {
|
||||
return (
|
||||
<div
|
||||
className={[
|
||||
'transition-all ease-out duration-200',
|
||||
'absolute left-0 right-0 h-screen',
|
||||
'px-5 pl-5 py-16',
|
||||
'top-[0px]',
|
||||
'bg-scale-200',
|
||||
// desktop styles
|
||||
'lg:relative lg:top-0 lg:left-0 lg:pb-10 lg:px-10 lg:pt-0 lg:flex',
|
||||
'lg:opacity-100 lg:visible',
|
||||
].join(' ')}
|
||||
>
|
||||
<NavigationMenu />
|
||||
</div>
|
||||
)
|
||||
})
|
||||
|
||||
const HeaderLogo = memo(function HeaderLogo() {
|
||||
const { isDarkMode } = useTheme()
|
||||
return (
|
||||
@@ -311,13 +292,26 @@ const NavContainer = memo(function NavContainer() {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<SideMenu />
|
||||
<div
|
||||
className={[
|
||||
'transition-all ease-out duration-200',
|
||||
'absolute left-0 right-0 h-screen',
|
||||
'px-5 pl-5 py-16',
|
||||
'top-[0px]',
|
||||
'bg-scale-200',
|
||||
// desktop styles
|
||||
'lg:relative lg:top-0 lg:left-0 lg:pb-10 lg:px-10 lg:pt-0 lg:flex',
|
||||
'lg:opacity-100 lg:visible',
|
||||
].join(' ')}
|
||||
>
|
||||
<NavigationMenu />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
|
||||
const SiteLayout = ({ children }) => {
|
||||
const SiteLayout = ({ children }: PropsWithChildren<{}>) => {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
// [Joshen] I think this can be done better, as its mostly used to choose what
|
||||
|
||||
import { ICommonFunc } from '../components/reference/Reference.types'
|
||||
import { ICommonBase, ICommonItem, ICommonSection } from '../components/reference/Reference.types'
|
||||
|
||||
// menus to render in the SideBar.js (Ref Nav.constants.ts)
|
||||
export function getPageType(asPath: string) {
|
||||
@@ -36,18 +34,25 @@ export function getPageType(asPath: string) {
|
||||
return page
|
||||
}
|
||||
|
||||
export function flattenSections(sections: ICommonFunc[]) {
|
||||
let a: ICommonFunc[] = []
|
||||
for (let i = 0; i < sections.length; i++) {
|
||||
if (sections[i].id) {
|
||||
// only push a section that has an id
|
||||
// these are reserved for sidebar subtitles
|
||||
a.push(sections[i])
|
||||
/**
|
||||
* Flattens common sections recursively by their `items`.
|
||||
*
|
||||
* _Note:_ `sections` type set to `ICommonBase[]` instead of
|
||||
* `ICommonItem[]` until TypeScript supports JSON imports as const:
|
||||
* https://github.com/microsoft/TypeScript/issues/32063
|
||||
*/
|
||||
export function flattenSections(sections: ICommonBase[]): ICommonSection[] {
|
||||
return sections.reduce<ICommonSection[]>((acc, section: ICommonItem) => {
|
||||
// Flatten sub-items
|
||||
if ('items' in section) {
|
||||
let newSections = acc
|
||||
|
||||
if (section.type !== 'category') {
|
||||
newSections.push(section)
|
||||
}
|
||||
|
||||
return newSections.concat(flattenSections(section.items))
|
||||
}
|
||||
if (sections[i].items) {
|
||||
// if there are subitems, loop through
|
||||
a = a.concat(flattenSections(sections[i].items))
|
||||
}
|
||||
}
|
||||
return a
|
||||
return acc.concat(section)
|
||||
}, [])
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { TsDoc } from '../../generator/legacy/definitions'
|
||||
import { values, mapValues } from 'lodash'
|
||||
import { OpenAPIV3 } from 'openapi-types'
|
||||
import { flattenSections } from '../helpers'
|
||||
import { ICommonItem } from '~/components/reference/Reference.types'
|
||||
|
||||
export function extractTsDocNode(nodeToFind: string, definition: any) {
|
||||
const nodePath = nodeToFind.split('.')
|
||||
@@ -294,12 +295,13 @@ export const toArrayWithKey = (obj: object, keyAs: string) =>
|
||||
})
|
||||
)
|
||||
|
||||
export function generateAllowedClientLibKeys(sections, spec) {
|
||||
/**
|
||||
* Get a list of common section IDs that are available in this spec
|
||||
*/
|
||||
export function getAvailableSectionIds(sections: ICommonItem[], spec: any) {
|
||||
// Filter parent sections first
|
||||
|
||||
const specIds = spec.functions.map((func) => {
|
||||
return func.id
|
||||
})
|
||||
const specIds = spec.functions.map(({ id }) => id)
|
||||
|
||||
const newShape = flattenSections(sections).filter((section) => {
|
||||
if (specIds.includes(section.id)) {
|
||||
|
||||
@@ -3,7 +3,7 @@ import { readFile } from 'fs/promises'
|
||||
import yaml from 'js-yaml'
|
||||
import { OpenAPIV3 } from 'openapi-types'
|
||||
import {
|
||||
ICommonFunc,
|
||||
ICommonFunction,
|
||||
IFunctionDefinition,
|
||||
ISpec,
|
||||
} from '../../../components/reference/Reference.types'
|
||||
@@ -29,7 +29,7 @@ export abstract class ReferenceSource<SpecSection> extends BaseSource {
|
||||
const specContents = await readFile(this.specFilePath, 'utf8')
|
||||
const refSectionsContents = await readFile(this.sectionsFilePath, 'utf8')
|
||||
|
||||
const refSections: ICommonFunc[] = JSON.parse(refSectionsContents)
|
||||
const refSections: ICommonFunction[] = JSON.parse(refSectionsContents)
|
||||
const flattenedRefSections = flattenSections(refSections)
|
||||
|
||||
const checksum = createHash('sha256')
|
||||
@@ -69,7 +69,7 @@ export abstract class ReferenceSource<SpecSection> extends BaseSource {
|
||||
|
||||
abstract getSpecSections(specContents: string): SpecSection[]
|
||||
abstract matchSpecSection(specSections: SpecSection[], id: string): SpecSection
|
||||
abstract formatSection(specSection: SpecSection, refSection: ICommonFunc): string
|
||||
abstract formatSection(specSection: SpecSection, refSection: ICommonFunction): string
|
||||
}
|
||||
|
||||
export class OpenApiReferenceSource extends ReferenceSource<enrichedOperation> {
|
||||
@@ -106,7 +106,7 @@ export class ClientLibReferenceSource extends ReferenceSource<IFunctionDefinitio
|
||||
matchSpecSection(functionDefinitions: IFunctionDefinition[], id: string): IFunctionDefinition {
|
||||
return functionDefinitions.find((functionDefinition) => functionDefinition.id === id)
|
||||
}
|
||||
formatSection(functionDefinition: IFunctionDefinition, refSection: ICommonFunc): string {
|
||||
formatSection(functionDefinition: IFunctionDefinition, refSection: ICommonFunction): string {
|
||||
const { title } = refSection
|
||||
const { description, title: functionName } = functionDefinition
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
"type": "markdown"
|
||||
},
|
||||
{
|
||||
"type": "category",
|
||||
"title": "Projects",
|
||||
"items": [
|
||||
{
|
||||
@@ -35,6 +36,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "category",
|
||||
"title": "Secrets",
|
||||
"items": [
|
||||
{
|
||||
@@ -58,6 +60,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "category",
|
||||
"title": "Typescript",
|
||||
"items": [
|
||||
{
|
||||
@@ -69,6 +72,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "category",
|
||||
"title": "Functions",
|
||||
"items": [
|
||||
{
|
||||
@@ -109,8 +113,8 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"type": "category",
|
||||
"title": "Custom Hostname",
|
||||
"items": [
|
||||
{
|
||||
@@ -146,6 +150,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "category",
|
||||
"title": "pgsodium",
|
||||
"items": [
|
||||
{
|
||||
@@ -163,6 +168,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "category",
|
||||
"title": "Network",
|
||||
"items": [
|
||||
{
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
"type": "markdown"
|
||||
},
|
||||
{
|
||||
"type": "category",
|
||||
"title": "General",
|
||||
"items": [
|
||||
{
|
||||
@@ -55,6 +56,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "category",
|
||||
"title": "Testing",
|
||||
"items": [
|
||||
{
|
||||
@@ -72,6 +74,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "category",
|
||||
"title": "Generate Types",
|
||||
"items": [
|
||||
{
|
||||
@@ -95,6 +98,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "category",
|
||||
"title": "Database",
|
||||
"items": [
|
||||
{
|
||||
@@ -148,6 +152,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "category",
|
||||
"title": "Migrations",
|
||||
"items": [
|
||||
{
|
||||
@@ -177,6 +182,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "category",
|
||||
"title": "Projects",
|
||||
"items": [
|
||||
{
|
||||
@@ -200,6 +206,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "category",
|
||||
"title": "Organizations",
|
||||
"items": [
|
||||
{
|
||||
@@ -217,6 +224,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "category",
|
||||
"title": "Edge Functions",
|
||||
"items": [
|
||||
{
|
||||
@@ -258,6 +266,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "category",
|
||||
"title": "Secrets",
|
||||
"items": [
|
||||
{
|
||||
@@ -287,6 +296,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "category",
|
||||
"title": "Authentication",
|
||||
"items": [
|
||||
{
|
||||
@@ -334,6 +344,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "category",
|
||||
"title": "Custom Domains",
|
||||
"items": [
|
||||
{
|
||||
@@ -375,6 +386,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "category",
|
||||
"title": "Vanity Subdomains",
|
||||
"items": [
|
||||
{
|
||||
@@ -410,6 +422,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "category",
|
||||
"title": "Network Bans",
|
||||
"items": [
|
||||
{
|
||||
@@ -433,6 +446,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "category",
|
||||
"title": "Network Restrictions",
|
||||
"items": [
|
||||
{
|
||||
@@ -456,6 +470,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "category",
|
||||
"title": "SSL Enforcement",
|
||||
"items": [
|
||||
{
|
||||
@@ -479,6 +494,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "category",
|
||||
"title": "Autocompletion Scripts",
|
||||
"items": [
|
||||
{
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "category",
|
||||
"title": "Database",
|
||||
"items": [
|
||||
{
|
||||
@@ -375,6 +376,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "category",
|
||||
"title": "Auth",
|
||||
"items": [
|
||||
{
|
||||
@@ -688,6 +690,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "category",
|
||||
"title": "Functions",
|
||||
"items": [
|
||||
{
|
||||
@@ -700,6 +703,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "category",
|
||||
"title": "Realtime",
|
||||
"items": [
|
||||
{
|
||||
@@ -761,6 +765,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "category",
|
||||
"title": "Storage",
|
||||
"items": [
|
||||
{
|
||||
@@ -892,6 +897,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "category",
|
||||
"title": "Misc",
|
||||
"excludes": [
|
||||
"reference_dart_v1",
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
"type": "markdown"
|
||||
},
|
||||
{
|
||||
"type": "category",
|
||||
"title": "Management API",
|
||||
"items": [
|
||||
{
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
"type": "markdown"
|
||||
},
|
||||
{
|
||||
"type": "category",
|
||||
"title": "Usage",
|
||||
"items": [
|
||||
{
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
"type": "markdown"
|
||||
},
|
||||
{
|
||||
"type": "category",
|
||||
"title": "Usage",
|
||||
"items": [
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user