版博士V2.0程序
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 

93 строки
2.6 KiB

  1. import { existsSync, readFileSync, writeFileSync } from 'node:fs';
  2. import { resolve } from 'node:path';
  3. import { homedir } from 'node:os';
  4. import destr from 'destr';
  5. import flat from 'flat';
  6. import { defu } from 'defu';
  7. const RE_KEY_VAL = /^\s*([^\s=]+)\s*=\s*(.*)?\s*$/;
  8. const RE_LINES = /\n|\r|\r\n/;
  9. const defaults = {
  10. name: ".conf",
  11. dir: process.cwd(),
  12. flat: false
  13. };
  14. function withDefaults(options) {
  15. if (typeof options === "string") {
  16. options = { name: options };
  17. }
  18. return { ...defaults, ...options };
  19. }
  20. function parse(contents, options = {}) {
  21. const config = {};
  22. const lines = contents.split(RE_LINES);
  23. for (const line of lines) {
  24. const match = line.match(RE_KEY_VAL);
  25. if (!match) {
  26. continue;
  27. }
  28. const key = match[1];
  29. if (!key || key === "__proto__" || key === "constructor") {
  30. continue;
  31. }
  32. const value = destr(
  33. match[2].trim()
  34. /* val */
  35. );
  36. if (key.endsWith("[]")) {
  37. const nkey = key.slice(0, Math.max(0, key.length - 2));
  38. config[nkey] = (config[nkey] || []).concat(value);
  39. continue;
  40. }
  41. config[key] = value;
  42. }
  43. return options.flat ? config : flat.unflatten(config, { overwrite: true });
  44. }
  45. function parseFile(path, options) {
  46. if (!existsSync(path)) {
  47. return {};
  48. }
  49. return parse(readFileSync(path, "utf8"), options);
  50. }
  51. function read(options) {
  52. options = withDefaults(options);
  53. return parseFile(resolve(options.dir, options.name), options);
  54. }
  55. function readUser(options) {
  56. options = withDefaults(options);
  57. options.dir = process.env.XDG_CONFIG_HOME || homedir();
  58. return read(options);
  59. }
  60. function serialize(config) {
  61. return Object.entries(flat.flatten(config)).map(
  62. ([key, value]) => `${key}=${typeof value === "string" ? value : JSON.stringify(value)}`
  63. ).join("\n");
  64. }
  65. function write(config, options) {
  66. options = withDefaults(options);
  67. writeFileSync(resolve(options.dir, options.name), serialize(config), {
  68. encoding: "utf8"
  69. });
  70. }
  71. function writeUser(config, options) {
  72. options = withDefaults(options);
  73. options.dir = process.env.XDG_CONFIG_HOME || homedir();
  74. write(config, options);
  75. }
  76. function update(config, options) {
  77. options = withDefaults(options);
  78. if (!options.flat) {
  79. config = flat.unflatten(config, { overwrite: true });
  80. }
  81. const newConfig = defu(config, read(options));
  82. write(newConfig, options);
  83. return newConfig;
  84. }
  85. function updateUser(config, options) {
  86. options = withDefaults(options);
  87. options.dir = process.env.XDG_CONFIG_HOME || homedir();
  88. return update(config, options);
  89. }
  90. export { defaults, parse, parseFile, read, readUser, serialize, update, updateUser, write, writeUser };