export-community-seed.js 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. #!/usr/bin/env node
  2. import { existsSync, mkdirSync, readdirSync, copyFileSync, rmSync, writeFileSync } from 'node:fs'
  3. import { dirname, join, resolve } from 'node:path'
  4. import { fileURLToPath } from 'node:url'
  5. const scriptDir = dirname(fileURLToPath(import.meta.url))
  6. const config = await readConfig()
  7. const seedDir = resolve(scriptDir, config.seedDir)
  8. const exportDir = resolve(scriptDir, config.exportDir, 'seed')
  9. const dryRun = process.argv.includes('--dry-run')
  10. const allowedPrefixes = ['R__', 'D__', 'O__']
  11. if (!existsSync(seedDir)) {
  12. fail(`seed directory not found: ${seedDir}`)
  13. }
  14. const files = listSqlFiles(seedDir)
  15. const invalidFiles = files.filter(file => !allowedPrefixes.some(prefix => file.name.startsWith(prefix)))
  16. if (invalidFiles.length > 0) {
  17. fail(`invalid seed file names:\n${invalidFiles.map(file => `- ${file.relativePath}`).join('\n')}`)
  18. }
  19. if (!dryRun) {
  20. rmSync(exportDir, { recursive: true, force: true })
  21. mkdirSync(exportDir, { recursive: true })
  22. for (const file of files) {
  23. const target = join(exportDir, file.relativePath)
  24. mkdirSync(dirname(target), { recursive: true })
  25. copyFileSync(file.absolutePath, target)
  26. }
  27. }
  28. const summary = {
  29. type: 'seed',
  30. dryRun,
  31. source: seedDir,
  32. target: exportDir,
  33. allowTables: config.allowTables,
  34. denyTables: config.denyTables,
  35. files: files.map(file => file.relativePath)
  36. }
  37. writeFileSync(resolve(scriptDir, config.exportDir, 'seed-summary.json'), `${JSON.stringify(summary, null, 2)}\n`)
  38. console.log(JSON.stringify(summary, null, 2))
  39. function listSqlFiles(root, base = root) {
  40. return readdirSync(root, { withFileTypes: true }).flatMap((entry) => {
  41. const absolutePath = join(root, entry.name)
  42. if (entry.isDirectory()) {
  43. return listSqlFiles(absolutePath, base)
  44. }
  45. if (!entry.name.endsWith('.sql')) {
  46. return []
  47. }
  48. return [{
  49. name: entry.name,
  50. absolutePath,
  51. relativePath: absolutePath.slice(base.length + 1)
  52. }]
  53. }).sort((a, b) => a.relativePath.localeCompare(b.relativePath))
  54. }
  55. async function readConfig() {
  56. const configPath = resolve(scriptDir, 'community-db.config.json')
  57. return JSON.parse(await import('node:fs/promises').then(fs => fs.readFile(configPath, 'utf8')))
  58. }
  59. function fail(message) {
  60. console.error(message)
  61. process.exit(1)
  62. }