feat: support simultaneous Tailscale and LAN communication for Yahboom cameras
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
import { readdir, readFile, realpath } from 'fs/promises'
|
||||
import { resolve, sep } from 'path'
|
||||
import type { LocalGitModule } from '../shared/gitModuleImport'
|
||||
|
||||
export async function localGitModulePath(root: string, folder: string): Promise<string> {
|
||||
if (!/^\[lms-nav2-custom\][a-z][a-z0-9_]*_v[^/\\]+_ws$/.test(folder)) throw new Error('Invalid custom module folder')
|
||||
const base = await realpath(root)
|
||||
const target = await realpath(resolve(base, folder))
|
||||
if (!target.startsWith(base + sep)) throw new Error('Module is outside the local workspace')
|
||||
return target
|
||||
}
|
||||
|
||||
export async function listLocalGitModules(root: string): Promise<LocalGitModule[]> {
|
||||
const entries = await readdir(root, { withFileTypes: true }).catch((error: NodeJS.ErrnoException) => {
|
||||
if (error.code === 'ENOENT') return []
|
||||
throw error
|
||||
})
|
||||
const modules: LocalGitModule[] = []
|
||||
for (const entry of entries) {
|
||||
if (!entry.isDirectory() || !entry.name.startsWith('[lms-nav2-custom]')) continue
|
||||
try {
|
||||
const target = await localGitModulePath(root, entry.name)
|
||||
const data = JSON.parse(await readFile(resolve(target, '.autonomy-studio-module.json'), 'utf8'))
|
||||
if (data.sourceType !== 'CUSTOM' || !['name', 'category', 'packageName', 'launchFile'].every(key => typeof data[key] === 'string' && data[key])) continue
|
||||
modules.push({ name: data.name, category: data.category, packageName: data.packageName, launchFile: data.launchFile, folderName: entry.name })
|
||||
} catch { /* Ignore incomplete module folders. */ }
|
||||
}
|
||||
return modules.sort((a, b) => a.name.localeCompare(b.name))
|
||||
}
|
||||
|
||||
export function repositoryAddress(value: string): string {
|
||||
// Do not allow local paths, Git remote helpers, or credentials in the UI.
|
||||
const normalized = /^git@[^:]+:.+/.test(value) ? value.replace(/^git@([^:]+):(.+)$/, 'ssh://git@$1/$2') : value
|
||||
const url = new URL(normalized)
|
||||
if (!['https:', 'http:', 'ssh:'].includes(url.protocol)) throw new Error('Unsupported Git repository protocol')
|
||||
url.password = ''
|
||||
if (url.protocol !== 'ssh:') url.username = ''
|
||||
url.search = ''
|
||||
url.hash = ''
|
||||
return url.toString()
|
||||
}
|
||||
|
||||
export function remoteBranches(output: string): Array<{ name: string; commit: string }> {
|
||||
return output.split('\n').flatMap(line => {
|
||||
const match = line.trim().match(/^([a-f0-9]{40,64})\s+refs\/heads\/(.+)$/)
|
||||
return match ? [{ name: match[2], commit: match[1] }] : []
|
||||
}).sort((a, b) => a.name.localeCompare(b.name))
|
||||
}
|
||||
Reference in New Issue
Block a user