( root: string, csvRel: string, newTitle: string )
| 333 | * data, schema, and pages all live inside, nothing else needs rewriting. |
| 334 | */ |
| 335 | export async function renameDatabase( |
| 336 | root: string, |
| 337 | csvRel: string, |
| 338 | newTitle: string |
| 339 | ): Promise<string> { |
| 340 | const formDir = formDirFromCsvPath(toPosix(csvRel)) |
| 341 | if (!formDir) throw new Error(`Not a database folder: ${csvRel}`) |
| 342 | const parentRel = formDir.includes('/') ? formDir.slice(0, formDir.lastIndexOf('/')) : '' |
| 343 | const safeName = (newTitle.trim() || 'Untitled Database').replace(/[\\/:*?"<>|]/g, '-') |
| 344 | const makeFormDir = (name: string): string => |
| 345 | parentRel ? `${parentRel}/${name}${FORM_DIR_SUFFIX}` : `${name}${FORM_DIR_SUFFIX}` |
| 346 | let targetRel = makeFormDir(safeName) |
| 347 | if (toPosix(targetRel) === toPosix(formDir)) return csvRel |
| 348 | let n = 2 |
| 349 | for (;;) { |
| 350 | try { |
| 351 | await fs.access(databaseDataPath(root, targetRel)) |
| 352 | targetRel = makeFormDir(`${safeName} ${n++}`) |
| 353 | } catch { |
| 354 | break |
| 355 | } |
| 356 | } |
| 357 | await fs.rename(databaseDataPath(root, formDir), databaseDataPath(root, targetRel)) |
| 358 | return csvPathForFormDir(targetRel) |
| 359 | } |
| 360 | |
| 361 | /** |
| 362 | * List databases in the vault: each `<Name>.base` folder (surfaced as its |
no test coverage detected