mirror of
https://github.com/supabase/supabase.git
synced 2026-06-16 02:26:42 +08:00
* infinite list * infinite list block * registration * add missing supportedFrameworks * Add tables to the supabase project. Generate the types for it. * Refactor the infinite list query to be just a hook. * Clean up the block. Add comments. * Regenerate the registry. * Fix the docs, the block is not framework-dependent. * Set the package versions to * to be defined by other packages. * Minor fixes to the block. * Fix the examples. * Fix the docs for the new hook. * Fix the demo. * Add more migrations to the db. * Fix various issues with the query. Rewrote it to useSyncExternalStore. * Fix the SSR for the hook. * More fixes. * Try initializing the store in a useEffect. * Fix the pnpm-lock file. * Minor fixes in the docs. * Put the infinite list under a reusable components section. * Update apps/ui-library/registry/default/blocks/infinite-query-hook/hooks/use-infinite-query.ts * Change the example DB to use todos. * Update the docs to be about Todos quickstart. * List edits * Fix link * Regenerate the registry. * Add query hook to the landing page. --------- Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com> Co-authored-by: Terry Sutton <saltcod@gmail.com>
87 lines
2.4 KiB
TypeScript
87 lines
2.4 KiB
TypeScript
import * as fs from 'fs'
|
|
|
|
export interface RegistryNode {
|
|
name: string
|
|
path: string
|
|
originalPath: string
|
|
type: 'directory' | 'file'
|
|
children?: RegistryNode[]
|
|
content?: string
|
|
}
|
|
|
|
interface RegistryFile {
|
|
path: string
|
|
target?: string
|
|
type: string
|
|
content: string
|
|
}
|
|
|
|
const DEFAULT_PATHS = {
|
|
component: '/components',
|
|
hook: '/hooks',
|
|
util: '/lib',
|
|
} as const
|
|
|
|
/**
|
|
* Converts a flat registry array into a hierarchical file tree structure
|
|
*/
|
|
export function generateRegistryTree(registryPath: string): RegistryNode[] {
|
|
const registry = JSON.parse(fs.readFileSync(registryPath, 'utf-8')) as { files: RegistryFile[] }
|
|
const tree: RegistryNode[] = []
|
|
|
|
const sortedRegistry = [...registry.files].sort((a, b) => a.path.localeCompare(b.path))
|
|
|
|
for (const file of sortedRegistry) {
|
|
const itemPath = file.target || getDefaultPath(file)
|
|
const pathParts = itemPath.split('/').filter(Boolean)
|
|
let currentLevel = tree
|
|
|
|
for (let i = 0; i < pathParts.length; i++) {
|
|
const part = pathParts[i]
|
|
const isLast = i === pathParts.length - 1
|
|
const path = '/' + pathParts.slice(0, i + 1).join('/')
|
|
|
|
let node = currentLevel.find((n) => n.name === part)
|
|
|
|
// Remove any paths in the file content that point to the block directory.
|
|
const content = file.content
|
|
.replaceAll(/@\/registry\/default\/blocks\/.+?\//gi, '@/')
|
|
.replaceAll(/@\/registry\/default\/fixtures\//gi, '@/')
|
|
.replaceAll(/@\/registry\/default\//gi, '@/')
|
|
.replaceAll(/@\/clients\/.+?\//gi, '@/')
|
|
|
|
if (!node) {
|
|
node = {
|
|
name: part,
|
|
path,
|
|
originalPath: file.path,
|
|
type: isLast ? 'file' : 'directory',
|
|
...(isLast ? { content } : { children: [] }),
|
|
}
|
|
currentLevel.push(node)
|
|
}
|
|
|
|
if (!isLast) {
|
|
node.children = node.children || []
|
|
currentLevel = node.children
|
|
}
|
|
}
|
|
}
|
|
|
|
return tree
|
|
}
|
|
|
|
/**
|
|
* Determines the default path for an item based on its type
|
|
*/
|
|
function getDefaultPath(item: RegistryFile): string {
|
|
const type = item.type.toLowerCase() || ''
|
|
const basePath = DEFAULT_PATHS[type as keyof typeof DEFAULT_PATHS] || ''
|
|
// clean all paths that start with paths specific to this repo organization
|
|
const filePath = item.path
|
|
.replace(/registry\/default\/blocks\/.+?\//, '')
|
|
.replace(/registry\/default\/clients\/.+?\//, '')
|
|
|
|
return `${basePath}/${filePath}`
|
|
}
|