Files
supabase/apps/ui-library/scripts/clean-registry.ts
Tiago Antunes b79a64e301 feat: add Realtime Flow component (#44273)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

Feature, docs update

## What is the new behavior?

This PR introduces a new `RealtimeFlow` component and hook to the UI
library for building collaborative React Flow with Supabase Realtime:
- keeps nodes and edges in sync across multiple connected clients in
real time
- uses Yjs with `@supabase-labs/y-supabase` to propagate flow updates
- supports optional persistence, so a flow can be restored from
previously saved shared state

## Additional context


https://github.com/user-attachments/assets/90d3a381-6f9c-427f-a493-5d91c2141462



<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Collaborative "Realtime Flow" diagram editor with syncing overlays and
a dual-view demo component
* Interactive demo page and registry example for live editing
(add/remove/rename nodes)
* Framework-ready registry packages for Next.js, React, React Router,
and TanStack

* **Documentation**
* Comprehensive docs added for Next.js, React, React Router, and
TanStack (usage, persistence, hook API)

* **Chores**
  * Added runtime dependency for the flow component package

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/44273)
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-26 13:28:52 +03:00

77 lines
2.4 KiB
TypeScript

import * as fs from 'fs'
import * as path from 'path'
function processJsonFile(filePath: string) {
try {
// Read the file
const content = fs.readFileSync(filePath, 'utf8')
const json = JSON.parse(content)
// Convert to string to do replacement
let stringified = JSON.stringify(json, null, 2)
// Perform the replacement
stringified = stringified
.replace(/\/ui\/example\/password-based-auth/g, '')
.replace(/\/example\/password-based-auth/g, '')
.replaceAll(
"import { Link } from '@/registry/default/components/ui/link'",
"import Link from 'next/link'"
)
// Replace the file origin path to exclude the monorepo structure
.replaceAll('node_modules/@supabase/vue-blocks/', '')
// Blocks that combine() across all client variants hard-code the nextjs
// client path in their source. Rewrite that import per-variant so each
// generated artifact points at the client file it actually bundles.
const variantClientMap: Record<string, string> = {
react: 'react',
'react-router': 'react-router',
tanstack: 'tanstack',
}
const baseName = path.basename(filePath, '.json')
for (const [suffix, clientDir] of Object.entries(variantClientMap)) {
if (baseName.endsWith(`-${suffix}`)) {
stringified = stringified.replaceAll(
'@/registry/default/clients/nextjs/lib/supabase/client',
`@/registry/default/clients/${clientDir}/lib/supabase/client`
)
break
}
}
// Write back to file
fs.writeFileSync(filePath, stringified)
console.log(`✓ Updated ${filePath}`)
} catch (error) {
console.error(`Error processing ${filePath}:`, error)
}
}
function processDirectory(directoryPath: string) {
const files = fs.readdirSync(directoryPath)
files.forEach((file) => {
const fullPath = path.join(directoryPath, file)
const stat = fs.statSync(fullPath)
if (stat.isDirectory()) {
processDirectory(fullPath)
} else if (path.extname(file) === '.json') {
processJsonFile(fullPath)
}
})
}
// Start processing from the specified directory
const targetDir = path.join(process.cwd(), 'public/r')
if (!fs.existsSync(targetDir)) {
console.error('Target directory does not exist:', targetDir)
process.exit(1)
}
console.log('Starting JSON file processing...')
processDirectory(targetDir)
console.log('Processing complete!')