start-local.mjs 1.7 KB

123456789101112131415161718192021222324252627282930
  1. import * as fs from 'node:fs'
  2. import * as path from 'node:path'
  3. import { fileURLToPath, pathToFileURL } from 'node:url'
  4. import { spawn } from 'node:child_process'
  5. import { createServer } from 'node:net'
  6. const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..')
  7. const cli = process.argv[2] ?? process.env.DSH_CLI_ENTRY
  8. const port = Number(process.argv[3] ?? 6095)
  9. if (!cli || !fs.existsSync(cli)) throw new Error('Supply the installed DSH lib/bin.js path or set DSH_CLI_ENTRY')
  10. if (!Number.isInteger(port) || port < 1024 || port > 65535) throw new Error('Invalid port')
  11. await new Promise((resolve, reject) => {
  12. const probe = createServer()
  13. probe.once('error', reject)
  14. probe.listen(port, '127.0.0.1', () => probe.close(resolve))
  15. })
  16. const root = path.join(packageRoot, '.webnovel', 'local-server')
  17. fs.mkdirSync(root, { recursive: true })
  18. const patch = path.join(root, 'cordis.patch.yml')
  19. fs.writeFileSync(patch, JSON.stringify([{ insert: [{ id: 'webnovel', name: pathToFileURL(path.join(packageRoot, 'lib/index.js')).href }] }], null, 2) + '\n')
  20. const stdout = fs.openSync(path.join(root, 'stdout.log'), 'w')
  21. const stderr = fs.openSync(path.join(root, 'stderr.log'), 'w')
  22. const child = spawn(process.execPath, [path.resolve(cli), '--profile', 'web', '--patch', patch, '--host', '127.0.0.1', '--port', String(port), '--no-open'], {
  23. cwd: path.resolve(packageRoot, '../..'),
  24. env: { ...process.env },
  25. detached: true, windowsHide: true, stdio: ['ignore', stdout, stderr],
  26. })
  27. child.unref(); fs.closeSync(stdout); fs.closeSync(stderr)
  28. fs.writeFileSync(path.join(root, 'runtime.json'), JSON.stringify({ root, processId: child.pid, port }, null, 2) + '\n')
  29. console.log(`DSH local process ${child.pid}; URL http://127.0.0.1:${port}/; logs ${root}`)