set-dms-token.mjs 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. /**
  2. * 写入 DMS token(本机开发用),配套 `vite.config.ts` 的「每请求现读 `.dms-token`」。
  3. *
  4. * 为什么要有它:DMS token 是外部 OAuth 签发的 JWT,**约 24 小时就过期**;
  5. * 以前只能手改 `.env.development.local` 再**重启 dev server**,麻烦且容易忘。
  6. * 现在 token 放在单行文件 `.dms-token`(gitignore),代理每个请求现读 —— 换 token 不用重启。
  7. *
  8. * 用法:
  9. * npm run dms:token # 从**剪贴板**读(浏览器里复制完直接跑,最省事)
  10. * npm run dms:token -- <token> # 显式传(注意 -- 不能省)
  11. * npm run dms:token -- --check # 只看当前 token 的状态,不写
  12. *
  13. * ⚠️ token 落在**被 gitignore 的本机文件**里,与 `.env.*.local` 同一性质:不随仓库分发。
  14. * DMS 的文档要求「token 不写进任何文件」,本仓库的落地口径是
  15. * **不写进任何会入库的文件**(见 harness/docs/reference/DMS_API.md 的鉴权节)。
  16. */
  17. import { readFileSync, writeFileSync, existsSync } from 'node:fs';
  18. import { execFileSync } from 'node:child_process';
  19. import { DMS_TOKEN_FILE, readDmsToken, parseJwtPayload, describeDmsToken } from './dms-token.mjs';
  20. const args = process.argv.slice(2);
  21. const explicit = args.find((a) => !a.startsWith('--'));
  22. const checkOnly = args.includes('--check');
  23. if (checkOnly) {
  24. const token = readDmsToken();
  25. if (!token) {
  26. console.error(`当前没有可用的 token:文件 ${DMS_TOKEN_FILE} 不存在或为空。`);
  27. process.exit(1);
  28. }
  29. console.log(`${DMS_TOKEN_FILE}\n ${describeDmsToken(token)}`);
  30. process.exit(0);
  31. }
  32. /** 从剪贴板取(Windows / macOS / Linux 各一条命令;取不到返回空串) */
  33. const readClipboard = () => {
  34. const cmds =
  35. process.platform === 'win32'
  36. ? [['powershell', ['-NoProfile', '-Command', 'Get-Clipboard']]]
  37. : process.platform === 'darwin'
  38. ? [['pbpaste', []]]
  39. : [
  40. ['xclip', ['-selection', 'clipboard', '-o']],
  41. ['xsel', ['--clipboard', '--output']],
  42. ];
  43. for (const [cmd, cmdArgs] of cmds) {
  44. try {
  45. return execFileSync(cmd, cmdArgs, { encoding: 'utf8' }).trim();
  46. } catch {
  47. /* 换下一条命令 */
  48. }
  49. }
  50. return '';
  51. };
  52. const token = String(explicit || readClipboard() || '').trim();
  53. if (!token) {
  54. console.error('没拿到 token:既没有参数,剪贴板也是空的。');
  55. console.error('用法:npm run dms:token -- <token> (或先把 token 复制到剪贴板,再跑 npm run dms:token)');
  56. process.exit(1);
  57. }
  58. const summary = describeDmsToken(token);
  59. if (!parseJwtPayload(token)) {
  60. console.error(summary);
  61. console.error('已中止,没有写入 —— 写进去也只会让 DMS 静默失败。');
  62. process.exit(1);
  63. }
  64. writeFileSync(DMS_TOKEN_FILE, `${token}\n`, 'utf8');
  65. console.log(`已写入 ${DMS_TOKEN_FILE}`);
  66. console.log(` ${summary}`);
  67. console.log('dev server **不用重启**(代理每个请求现读这个文件)。');