@sfmc-bds/bds-tools 0.2.0-beta.9 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/LICENSE +663 -0
  2. package/README.md +1 -1
  3. package/dist/bds-manager.d.ts +16 -6
  4. package/dist/bds-manager.d.ts.map +1 -1
  5. package/dist/bds-manager.js +22 -4
  6. package/dist/bds-manager.js.map +2 -2
  7. package/dist/changelog.d.ts +11 -7
  8. package/dist/changelog.d.ts.map +1 -1
  9. package/dist/changelog.js +60 -34
  10. package/dist/changelog.js.map +2 -2
  11. package/dist/check-update.d.ts.map +1 -1
  12. package/dist/check-update.js +56 -18
  13. package/dist/check-update.js.map +2 -2
  14. package/dist/cli-pack-manager.js +11 -1
  15. package/dist/cli-pack-manager.js.map +2 -2
  16. package/dist/dependency-negotiator.d.ts +73 -0
  17. package/dist/dependency-negotiator.d.ts.map +1 -0
  18. package/dist/dependency-negotiator.js +151 -0
  19. package/dist/dependency-negotiator.js.map +7 -0
  20. package/dist/fsx.d.ts +15 -7
  21. package/dist/fsx.d.ts.map +1 -1
  22. package/dist/fsx.js +67 -8
  23. package/dist/fsx.js.map +2 -2
  24. package/dist/http.d.ts +49 -11
  25. package/dist/http.d.ts.map +1 -1
  26. package/dist/http.js.map +2 -2
  27. package/dist/level-dat.d.ts +105 -0
  28. package/dist/level-dat.d.ts.map +1 -0
  29. package/dist/level-dat.js +490 -0
  30. package/dist/level-dat.js.map +7 -0
  31. package/dist/pack-manager.d.ts +41 -34
  32. package/dist/pack-manager.d.ts.map +1 -1
  33. package/dist/pack-manager.js +73 -24
  34. package/dist/pack-manager.js.map +2 -2
  35. package/dist/qq-events-notify.d.ts +1 -1
  36. package/dist/qq-events-notify.d.ts.map +1 -1
  37. package/dist/qq-events-notify.js.map +1 -1
  38. package/dist/qqutil.d.ts +10 -6
  39. package/dist/qqutil.d.ts.map +1 -1
  40. package/dist/qqutil.js +14 -12
  41. package/dist/qqutil.js.map +2 -2
  42. package/dist/rollback.d.ts.map +1 -1
  43. package/dist/rollback.js +2 -2
  44. package/dist/rollback.js.map +2 -2
  45. package/dist/server-properties-i18n.d.ts +17 -0
  46. package/dist/server-properties-i18n.d.ts.map +1 -0
  47. package/dist/server-properties-i18n.js +201 -0
  48. package/dist/server-properties-i18n.js.map +7 -0
  49. package/dist/server-properties.d.ts +25 -0
  50. package/dist/server-properties.d.ts.map +1 -1
  51. package/dist/server-properties.js +141 -1
  52. package/dist/server-properties.js.map +2 -2
  53. package/dist/types.d.ts +1 -3
  54. package/dist/types.d.ts.map +1 -1
  55. package/dist/upstream.d.ts +14 -6
  56. package/dist/upstream.d.ts.map +1 -1
  57. package/dist/upstream.js.map +2 -2
  58. package/dist/world-packs.d.ts +106 -3
  59. package/dist/world-packs.d.ts.map +1 -1
  60. package/dist/world-packs.js +245 -10
  61. package/dist/world-packs.js.map +3 -3
  62. package/package.json +19 -14
  63. package/dist/qq-events-notify.test.d.ts +0 -5
  64. package/dist/qq-events-notify.test.d.ts.map +0 -1
  65. package/dist/qq-events-notify.test.js +0 -41
  66. package/dist/qq-events-notify.test.js.map +0 -7
package/dist/qqutil.js CHANGED
@@ -25,7 +25,7 @@ function isOfficialBackend(cfg) {
25
25
  }
26
26
  function sendToLLBot(payload, timeoutMs = 5e3) {
27
27
  const cfg = getConfig();
28
- const url = new URL(cfg.llbot_http || "http://127.0.0.1:3004");
28
+ const url = new URL(cfg.llbot?.http || `http://${cfg.llbot?.host || "127.0.0.1"}:${cfg.llbot?.port || 3004}`);
29
29
  const data = JSON.stringify(payload);
30
30
  return new Promise((resolve, reject) => {
31
31
  const req = http.request(
@@ -66,14 +66,14 @@ async function safeSend(label, fn) {
66
66
  }
67
67
  async function sendOfficialText(text) {
68
68
  const cfg = getConfig();
69
- const appId = String(cfg.qq_app_id ?? "");
70
- const appSecret = String(cfg.qq_app_secret ?? "");
71
- const groupOpenid = String(cfg.qq_group_openid ?? "");
69
+ const appId = String(cfg.official?.app_id ?? "");
70
+ const appSecret = String(cfg.official?.app_secret ?? "");
71
+ const groupOpenid = String(cfg.official?.group_openid ?? "");
72
72
  if (!appId || !appSecret || !groupOpenid) {
73
- throw new Error("\u5B98\u65B9\u540E\u7AEF\u7F3A\u5C11 qq_app_id / qq_app_secret / qq_group_openid");
73
+ throw new Error("\u5B98\u65B9\u540E\u7AEF\u7F3A\u5C11 official.app_id / official.app_secret / official.group_openid");
74
74
  }
75
75
  const result = await sendGroupTextMessage(
76
- { appId, appSecret, sandbox: cfg.qq_sandbox === true },
76
+ { appId, appSecret, sandbox: cfg.official?.sandbox === true },
77
77
  { groupOpenid, content: text }
78
78
  );
79
79
  if (!result.ok) throw new Error(result.error);
@@ -88,14 +88,15 @@ async function sendText(text) {
88
88
  await safeSend("sendText(official)", () => sendOfficialText(text));
89
89
  return;
90
90
  }
91
- if (!cfg.qq_group_id) {
92
- log.warn("[QQ] qq_group_id \u7F3A\u5931");
91
+ const groupId = cfg.llbot?.group_id;
92
+ if (!groupId) {
93
+ log.warn("[QQ] llbot.group_id \u7F3A\u5931");
93
94
  return;
94
95
  }
95
96
  await safeSend(
96
97
  "sendText(llbot)",
97
98
  () => sendToLLBot({
98
- group_id: parseInt(cfg.qq_group_id ?? "0", 10),
99
+ group_id: parseInt(groupId, 10),
99
100
  message: [{ type: "text", data: { text } }]
100
101
  })
101
102
  );
@@ -117,14 +118,15 @@ async function sendMixed(segments) {
117
118
  await safeSend("sendMixed(official)", () => sendOfficialText(text));
118
119
  return;
119
120
  }
120
- if (!cfg.qq_group_id) {
121
- log.warn("[QQ] qq_group_id \u7F3A\u5931");
121
+ const groupId = cfg.llbot?.group_id;
122
+ if (!groupId) {
123
+ log.warn("[QQ] llbot.group_id \u7F3A\u5931");
122
124
  return;
123
125
  }
124
126
  await safeSend(
125
127
  "sendMixed(llbot)",
126
128
  () => sendToLLBot({
127
- group_id: parseInt(cfg.qq_group_id ?? "0", 10),
129
+ group_id: parseInt(groupId, 10),
128
130
  message: segments
129
131
  })
130
132
  );
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/qqutil.ts"],
4
- "sourcesContent": ["/**\r\n * qqutil.ts \u2014 QQ \u901A\u77E5\u5DE5\u5177\uFF08\u5B98\u65B9 Bot / LLBot \u53CC\u540E\u7AEF\uFF09\r\n *\r\n * \u6539\u8FDB:\r\n * - sendTimeout \u63D0\u4F9B\u603B\u8D85\u65F6\uFF0C\u907F\u514D\u901A\u77E5\u53D1\u9001\u6302\u6B7B\u4E3B\u6D41\u7A0B\r\n * - \u9759\u9ED8\u6A21\u5F0F (\u5931\u8D25\u4E0D\u629B\u51FA)\uFF0C\u4FDD\u8BC1\u4E3B\u6D41\u7A0B\u4E0D\u88AB\u901A\u77E5\u5E72\u6270\r\n * - qq_backend=official \u65F6\u8D70 SDK \u53D1\u7FA4\uFF1Bllbot \u4ECD\u8D70 OneBot HTTP\r\n */\r\n\r\nimport {\r\n configPath,\r\n modulePath,\r\n readJson,\r\n type Catalog,\r\n type ModuleLock,\r\n type QQBridgeConfig,\r\n} from \"@sfmc-bds/sdk/node/config\";\r\nimport { sendGroupTextMessage } from \"@sfmc-bds/sdk/node/qq-official\";\r\nimport http from \"node:http\";\r\nimport { log } from \"./log.js\";\r\nimport { ROOT_DIR } from \"./paths.js\";\r\n\r\ntype QqConfig = Pick<\r\n QQBridgeConfig,\r\n | \"llbot_http\"\r\n | \"qq_group_id\"\r\n | \"qq_backend\"\r\n | \"qq_app_id\"\r\n | \"qq_app_secret\"\r\n | \"qq_sandbox\"\r\n | \"qq_group_openid\"\r\n>;\r\n\r\nlet cachedCfg: QqConfig | null = null;\r\nfunction getConfig(): QqConfig {\r\n if (cachedCfg) return cachedCfg;\r\n cachedCfg = (readJson<QQBridgeConfig>(configPath(ROOT_DIR, \"qq_config.json\")) ?? {}) as QqConfig;\r\n return cachedCfg;\r\n}\r\n\r\n/** \u68C0\u67E5 qq-bridge \u6A21\u5757\u662F\u5426\u542F\u7528 */\r\nexport function isQqBridgeEnabled(): boolean {\r\n const catalog = readJson<Catalog>(modulePath(ROOT_DIR, \"catalog.json\"));\r\n const lock = readJson<ModuleLock>(modulePath(ROOT_DIR, \"module-lock.json\"));\r\n if (!catalog || !lock) return true; // \u6A21\u5757\u76EE\u5F55\u7F3A\u5931\u5219\u4FDD\u5B88\u89C6\u4E3A\u53EF\u7528\r\n const mod = catalog.modules?.find((m) => m.id === \"qq-bridge\" || m.configKey === \"qq_bridge\") as\r\n | { id?: string }\r\n | undefined;\r\n return mod ? lock.modules?.[mod.id ?? \"\"]?.enabled === true : false;\r\n}\r\n\r\nfunction isOfficialBackend(cfg: QqConfig): boolean {\r\n return (cfg.qq_backend ?? \"official\") === \"official\";\r\n}\r\n\r\nfunction sendToLLBot(payload: unknown, timeoutMs = 5_000): Promise<void> {\r\n const cfg = getConfig();\r\n const url = new URL(cfg.llbot_http || \"http://127.0.0.1:3004\");\r\n const data = JSON.stringify(payload);\r\n return new Promise((resolve, reject) => {\r\n const req = http.request(\r\n {\r\n hostname: url.hostname,\r\n port: url.port || 3004,\r\n path: \"/send_group_msg\",\r\n method: \"POST\",\r\n headers: {\r\n \"Content-Type\": \"application/json\",\r\n \"Content-Length\": Buffer.byteLength(data),\r\n },\r\n timeout: timeoutMs,\r\n },\r\n (res) => {\r\n let body = \"\";\r\n res.on(\"data\", (c) => (body += c));\r\n res.on(\"end\", () => {\r\n if (res.statusCode === 200) resolve();\r\n else reject(new Error(`LLBot HTTP ${res.statusCode}: ${body.slice(0, 200)}`));\r\n });\r\n }\r\n );\r\n req.on(\"timeout\", () => {\r\n req.destroy(new Error(`LLBot \u8D85\u65F6 ${timeoutMs}ms`));\r\n });\r\n req.on(\"error\", reject);\r\n req.write(data);\r\n req.end();\r\n });\r\n}\r\n\r\nasync function safeSend(label: string, fn: () => Promise<void>): Promise<void> {\r\n try {\r\n await fn();\r\n } catch (e) {\r\n log.warn(`[QQ] ${label} \u5931\u8D25: ${(e as Error).message}`);\r\n }\r\n}\r\n\r\nasync function sendOfficialText(text: string): Promise<void> {\r\n const cfg = getConfig();\r\n const appId = String(cfg.qq_app_id ?? \"\");\r\n const appSecret = String(cfg.qq_app_secret ?? \"\");\r\n const groupOpenid = String(cfg.qq_group_openid ?? \"\");\r\n if (!appId || !appSecret || !groupOpenid) {\r\n throw new Error(\"\u5B98\u65B9\u540E\u7AEF\u7F3A\u5C11 qq_app_id / qq_app_secret / qq_group_openid\");\r\n }\r\n const result = await sendGroupTextMessage(\r\n { appId, appSecret, sandbox: cfg.qq_sandbox === true },\r\n { groupOpenid, content: text }\r\n );\r\n if (!result.ok) throw new Error(result.error);\r\n}\r\n\r\nexport async function sendText(text: string): Promise<void> {\r\n const cfg = getConfig();\r\n if (!isQqBridgeEnabled()) {\r\n log.warn(\"[QQ] qq-bridge \u672A\u542F\u7528\");\r\n return;\r\n }\r\n if (isOfficialBackend(cfg)) {\r\n await safeSend(\"sendText(official)\", () => sendOfficialText(text));\r\n return;\r\n }\r\n if (!cfg.qq_group_id) {\r\n log.warn(\"[QQ] qq_group_id \u7F3A\u5931\");\r\n return;\r\n }\r\n await safeSend(\"sendText(llbot)\", () =>\r\n sendToLLBot({\r\n group_id: parseInt(cfg.qq_group_id ?? \"0\", 10),\r\n message: [{ type: \"text\", data: { text } }],\r\n })\r\n );\r\n}\r\n\r\nexport async function sendMixed(segments: unknown[]): Promise<void> {\r\n const cfg = getConfig();\r\n if (!isQqBridgeEnabled()) {\r\n log.warn(\"[QQ] qq-bridge \u672A\u542F\u7528\");\r\n return;\r\n }\r\n if (isOfficialBackend(cfg)) {\r\n // \u5B98\u65B9\u8DEF\u5F84\u4EC5\u62FC\u7EAF\u6587\u672C\uFF1B\u56FE\u7247\u6BB5\u964D\u7EA7\u4E3A [\u56FE\u7247]\r\n const text = segments\r\n .map((seg) => {\r\n const s = seg as { type?: string; data?: { text?: string } };\r\n if (s?.type === \"text\") return String(s.data?.text ?? \"\");\r\n if (s?.type === \"image\") return \"[\u56FE\u7247]\";\r\n return \"\";\r\n })\r\n .join(\"\")\r\n .trim();\r\n if (!text) return;\r\n await safeSend(\"sendMixed(official)\", () => sendOfficialText(text));\r\n return;\r\n }\r\n if (!cfg.qq_group_id) {\r\n log.warn(\"[QQ] qq_group_id \u7F3A\u5931\");\r\n return;\r\n }\r\n await safeSend(\"sendMixed(llbot)\", () =>\r\n sendToLLBot({\r\n group_id: parseInt(cfg.qq_group_id ?? \"0\", 10),\r\n message: segments,\r\n })\r\n );\r\n}\r\n\r\nexport async function sendWithImage(text: string, base64Img: string): Promise<void> {\r\n const segments: unknown[] = [];\r\n if (text) segments.push({ type: \"text\", data: { text } });\r\n if (base64Img) segments.push({ type: \"image\", data: { file: `base64://${base64Img}` } });\r\n if (segments.length === 0) return;\r\n await sendMixed(segments);\r\n}\r\n\r"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * qqutil.ts \u2014 BDS \u8FD0\u7EF4\u4E0E\u66F4\u65B0\u901A\u77E5\u63A8\u9001\u5DE5\u5177\uFF08\u652F\u6301\u5B98\u65B9 Bot \u4E0E LLBot \u53CC\u540E\u7AEF\uFF09\n *\n * \u6838\u5FC3\u673A\u5236\uFF1A\n * - \u53CC\u540E\u7AEF\u9002\u914D\uFF1A\u6839\u636E `qq_backend` \u914D\u7F6E\u81EA\u52A8\u5206\u53D1\u81F3\u5B98\u65B9\u5F00\u653E\u5E73\u53F0\u53D1\u7FA4\u63A5\u53E3\u6216 LLBot OneBot HTTP \u63A5\u53E3\n * - \u6545\u969C\u9694\u79BB\uFF1A\u901A\u77E5\u53D1\u9001\u5931\u8D25\u4EC5\u8BB0\u5F55\u544A\u8B66\u65E5\u5FD7\u5E76\u4E0D\u4E2D\u65AD\u4E3B\u6D41\u7A0B\uFF0C\u786E\u4FDD\u4E3B\u670D\u52A1\u8FD0\u7EF4\u6B63\u5E38\u6267\u884C\n * - \u53D1\u9001\u8D85\u65F6\u7194\u65AD\uFF1A\u8BBE\u7F6E\u8BF7\u6C42\u8D85\u65F6\u65F6\u95F4\uFF0C\u9632\u6B62\u5916\u90E8\u7F51\u7EDC\u54CD\u5E94\u5EF6\u8FDF\u5835\u585E BDS \u542F\u52A8\u4E0E\u66F4\u65B0\n */\n\nimport {\n configPath,\n modulePath,\n readJson,\n type Catalog,\n type ModuleLock,\n type QQBridgeConfig,\n} from \"@sfmc-bds/sdk/node/config\";\nimport { sendGroupTextMessage } from \"@sfmc-bds/sdk/node/qq-official\";\nimport http from \"node:http\";\nimport { log } from \"./log.js\";\nimport { ROOT_DIR } from \"./paths.js\";\n\ntype QqConfig = Pick<QQBridgeConfig, \"qq_backend\" | \"official\" | \"llbot\">;\n\nlet cachedCfg: QqConfig | null = null;\nfunction getConfig(): QqConfig {\n if (cachedCfg) return cachedCfg;\n cachedCfg = (readJson<QQBridgeConfig>(configPath(ROOT_DIR, \"qq_config.json\")) ?? {}) as QqConfig;\n return cachedCfg;\n}\n\n/**\n * \u68C0\u67E5\u5E73\u53F0\u4E2D `qq-bridge` \u6A21\u5757\u662F\u5426\u5904\u4E8E\u542F\u7528\u72B6\u6001\u3002\n *\n * @returns \u82E5\u542F\u7528\u8FD4\u56DE `true`\uFF0C\u5426\u5219\u8FD4\u56DE `false`\u3002\n */\nexport function isQqBridgeEnabled(): boolean {\n\n const catalog = readJson<Catalog>(modulePath(ROOT_DIR, \"catalog.json\"));\n const lock = readJson<ModuleLock>(modulePath(ROOT_DIR, \"module-lock.json\"));\n if (!catalog || !lock) return true; // \u6A21\u5757\u76EE\u5F55\u7F3A\u5931\u5219\u4FDD\u5B88\u89C6\u4E3A\u53EF\u7528\n const mod = catalog.modules?.find((m) => m.id === \"qq-bridge\" || m.configKey === \"qq_bridge\");\n return mod ? lock.modules?.[mod.id ?? \"\"]?.enabled === true : false;\n}\n\nfunction isOfficialBackend(cfg: QqConfig): boolean {\n return (cfg.qq_backend ?? \"official\") === \"official\";\n}\n\nfunction sendToLLBot(payload: unknown, timeoutMs = 5_000): Promise<void> {\n const cfg = getConfig();\n const url = new URL(cfg.llbot?.http || `http://${cfg.llbot?.host || \"127.0.0.1\"}:${cfg.llbot?.port || 3004}`);\n const data = JSON.stringify(payload);\n return new Promise((resolve, reject) => {\n const req = http.request(\n {\n hostname: url.hostname,\n port: url.port || 3004,\n path: \"/send_group_msg\",\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"Content-Length\": Buffer.byteLength(data),\n },\n timeout: timeoutMs,\n },\n (res) => {\n let body = \"\";\n res.on(\"data\", (c) => (body += c));\n res.on(\"end\", () => {\n if (res.statusCode === 200) resolve();\n else reject(new Error(`LLBot HTTP ${res.statusCode}: ${body.slice(0, 200)}`));\n });\n }\n );\n req.on(\"timeout\", () => {\n req.destroy(new Error(`LLBot \u8D85\u65F6 ${timeoutMs}ms`));\n });\n req.on(\"error\", reject);\n req.write(data);\n req.end();\n });\n}\n\nasync function safeSend(label: string, fn: () => Promise<void>): Promise<void> {\n try {\n await fn();\n } catch (e) {\n log.warn(`[QQ] ${label} \u5931\u8D25: ${(e as Error).message}`);\n }\n}\n\nasync function sendOfficialText(text: string): Promise<void> {\n const cfg = getConfig();\n const appId = String(cfg.official?.app_id ?? \"\");\n const appSecret = String(cfg.official?.app_secret ?? \"\");\n const groupOpenid = String(cfg.official?.group_openid ?? \"\");\n if (!appId || !appSecret || !groupOpenid) {\n throw new Error(\"\u5B98\u65B9\u540E\u7AEF\u7F3A\u5C11 official.app_id / official.app_secret / official.group_openid\");\n }\n const result = await sendGroupTextMessage(\n { appId, appSecret, sandbox: cfg.official?.sandbox === true },\n { groupOpenid, content: text }\n );\n if (!result.ok) throw new Error(result.error);\n}\n\nexport async function sendText(text: string): Promise<void> {\n const cfg = getConfig();\n if (!isQqBridgeEnabled()) {\n log.warn(\"[QQ] qq-bridge \u672A\u542F\u7528\");\n return;\n }\n if (isOfficialBackend(cfg)) {\n await safeSend(\"sendText(official)\", () => sendOfficialText(text));\n return;\n }\n const groupId = cfg.llbot?.group_id;\n if (!groupId) {\n log.warn(\"[QQ] llbot.group_id \u7F3A\u5931\");\n return;\n }\n await safeSend(\"sendText(llbot)\", () =>\n sendToLLBot({\n group_id: parseInt(groupId, 10),\n message: [{ type: \"text\", data: { text } }],\n })\n );\n}\n\nexport async function sendMixed(segments: unknown[]): Promise<void> {\n const cfg = getConfig();\n if (!isQqBridgeEnabled()) {\n log.warn(\"[QQ] qq-bridge \u672A\u542F\u7528\");\n return;\n }\n if (isOfficialBackend(cfg)) {\n // \u5B98\u65B9\u8DEF\u5F84\u4EC5\u62FC\u7EAF\u6587\u672C\uFF1B\u56FE\u7247\u6BB5\u964D\u7EA7\u4E3A [\u56FE\u7247]\n const text = segments\n .map((seg) => {\n const s = seg as { type?: string; data?: { text?: string } };\n if (s?.type === \"text\") return String(s.data?.text ?? \"\");\n if (s?.type === \"image\") return \"[\u56FE\u7247]\";\n return \"\";\n })\n .join(\"\")\n .trim();\n if (!text) return;\n await safeSend(\"sendMixed(official)\", () => sendOfficialText(text));\n return;\n }\n const groupId = cfg.llbot?.group_id;\n if (!groupId) {\n log.warn(\"[QQ] llbot.group_id \u7F3A\u5931\");\n return;\n }\n await safeSend(\"sendMixed(llbot)\", () =>\n sendToLLBot({\n group_id: parseInt(groupId, 10),\n message: segments,\n })\n );\n}\n\nexport async function sendWithImage(text: string, base64Img: string): Promise<void> {\n const segments: unknown[] = [];\n if (text) segments.push({ type: \"text\", data: { text } });\n if (base64Img) segments.push({ type: \"image\", data: { file: `base64://${base64Img}` } });\n if (segments.length === 0) return;\n await sendMixed(segments);\n}\n\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1 +1 @@
1
- {"version":3,"file":"rollback.d.ts","sourceRoot":"","sources":["../src/rollback.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,OAAO,EAAe,UAAU,EAAgB,MAAM,UAAU,CAAC;AAGjE,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,yBAAyB;AACzB,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,CAOhE;AAED,wBAAgB,mBAAmB,IAAI,IAAI,CAM1C;AAED,wBAAgB,kBAAkB,IAAI,cAAc,GAAG,IAAI,CAE1D;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,cAAc,GAAG;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CA8B3F;AAED,mDAAmD;AACnD,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAMzG;AAED,OAAO,EAAE,UAAU,EAAE,CAAC"}
1
+ {"version":3,"file":"rollback.d.ts","sourceRoot":"","sources":["../src/rollback.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,OAAO,EAAiC,UAAU,EAAgB,MAAM,UAAU,CAAC;AAGnF,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,yBAAyB;AACzB,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,CAOhE;AAED,wBAAgB,mBAAmB,IAAI,IAAI,CAM1C;AAED,wBAAgB,kBAAkB,IAAI,cAAc,GAAG,IAAI,CAE1D;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,cAAc,GAAG;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CA8B3F;AAED,mDAAmD;AACnD,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAMzG;AAED,OAAO,EAAE,UAAU,EAAE,CAAC"}
package/dist/rollback.js CHANGED
@@ -2,7 +2,7 @@ import { readJson, writeJson } from "@sfmc-bds/sdk/node/config";
2
2
  import fs from "node:fs";
3
3
  import path from "node:path";
4
4
  import { ROLLBACK_MARKER } from "./paths.js";
5
- import { copyDirSync, getDirSize, emptyDirSync } from "./fsx.js";
5
+ import { copyDirSync, copyFileSyncSafe, getDirSize, emptyDirSync } from "./fsx.js";
6
6
  import { log } from "./log.js";
7
7
  function writeRollbackMarker(marker) {
8
8
  try {
@@ -41,7 +41,7 @@ function rollbackFromBackup(marker) {
41
41
  if (fs.existsSync(dest)) emptyDirSync(dest);
42
42
  copyDirSync(src, dest);
43
43
  } else {
44
- fs.copyFileSync(src, dest);
44
+ copyFileSyncSafe(src, dest);
45
45
  }
46
46
  log.info(`[\u56DE\u6EDA] \u5DF2\u6062\u590D: ${item}`);
47
47
  } catch (e) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/rollback.ts"],
4
- "sourcesContent": ["/**\n * rollback.ts \u2014 \u56DE\u6EDA\u652F\u6301\n *\n * \u5728\u66F4\u65B0\u5F00\u59CB\u524D\u8BB0\u5F55: \u5F53\u524D BDS \u76EE\u5F55 + \u5907\u4EFD\u76EE\u5F55\u3002\n * \u4E3B\u6D41\u7A0B\u4EFB\u610F\u9636\u6BB5\u5931\u8D25\u65F6\uFF0C\u5C1D\u8BD5\u53CD\u5411\u6062\u590D preserves \u5230 BDS_PATH\uFF0C\n * \u7136\u540E\u4ECE\u5907\u4EFD\u91CD\u65B0\u653E\u56DE preserve \u5185\u5BB9\uFF0C\u6062\u590D\u65E7\u914D\u7F6E\u3002\n *\n * \u6301\u4E45\u5316: <SFMC_ROOT>/.sfmc/last_update_rollback.json \u7528\u4E8E\u8DE8\u8FDB\u7A0B\u8BB0\u5F55\u3002\n */\n\nimport { readJson, writeJson } from \"@sfmc-bds/sdk/node/config\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { ROLLBACK_MARKER } from \"./paths.js\";\nimport { copyDirSync, getDirSize, emptyDirSync } from \"./fsx.js\";\nimport { log } from \"./log.js\";\n\nexport interface RollbackMarker {\n timestamp: number;\n bds_path: string;\n backup_dir: string;\n preserve: string[];\n previous_version: string;\n}\n\n/** \u5728\u5907\u4EFD\u5B8C\u6210\u540E\u8C03\u7528: \u8BB0\u5F55\u5FEB\u7167\u6307\u793A\u7B26\u3002 */\nexport function writeRollbackMarker(marker: RollbackMarker): void {\n try {\n writeJson(ROLLBACK_MARKER, marker);\n log.info(`[\u56DE\u6EDA] \u5DF2\u8BB0\u5F55\u56DE\u6EDA\u6807\u8BB0 -> ${ROLLBACK_MARKER}`);\n } catch (e) {\n log.warn(`[\u56DE\u6EDA] \u65E0\u6CD5\u5199\u5165\u6807\u8BB0: ${(e as Error).message}`);\n }\n}\n\nexport function clearRollbackMarker(): void {\n try {\n if (fs.existsSync(ROLLBACK_MARKER)) fs.unlinkSync(ROLLBACK_MARKER);\n } catch {\n /* ignore */\n }\n}\n\nexport function readRollbackMarker(): RollbackMarker | null {\n return readJson<RollbackMarker>(ROLLBACK_MARKER) ?? null;\n}\n\n/**\n * \u7D27\u6025\u56DE\u6EDA: \u628A preserve \u9879\u4ECE backup_dir \u62F7\u56DE bds_path\u3002\n * \u7528\u6CD5: \u5728 catch \u5206\u652F\u8C03\u7528\uFF0C\u5982\u679C\u4E3B\u6D41\u7A0B\u5931\u8D25\u5BFC\u81F4 BDS \u76EE\u5F55\u7834\u574F\u3002\n */\nexport function rollbackFromBackup(marker: RollbackMarker): { ok: boolean; reason?: string } {\n const { bds_path, backup_dir, preserve } = marker;\n if (!fs.existsSync(backup_dir)) {\n return { ok: false, reason: `\u5907\u4EFD\u76EE\u5F55\u4E0D\u5B58\u5728: ${backup_dir}` };\n }\n log.warn(`[\u56DE\u6EDA] \u5F00\u59CB\u6062\u590D ${preserve.length} \u9879\u5230 ${bds_path}`);\n for (const item of preserve) {\n const src = path.join(backup_dir, item);\n const dest = path.join(bds_path, item);\n if (!fs.existsSync(src)) {\n log.warn(`[\u56DE\u6EDA] \u8DF3\u8FC7 (\u5907\u4EFD\u4E2D\u4E0D\u5B58\u5728): ${item}`);\n continue;\n }\n try {\n // \u5148\u786E\u4FDD\u76EE\u6807\u76EE\u5F55\u5B58\u5728 (BDS \u76EE\u5F55\u53EF\u80FD\u5DF2\u88AB\u89E3\u538B\u8986\u76D6\u4E3A\u7A7A)\n const destDir = path.dirname(dest);\n if (!fs.existsSync(destDir)) fs.mkdirSync(destDir, { recursive: true });\n if (fs.statSync(src).isDirectory()) {\n // \u5148\u5220\u9664\u76EE\u6807\uFF0C\u518D\u590D\u5236\u76EE\u5F55\n if (fs.existsSync(dest)) emptyDirSync(dest);\n copyDirSync(src, dest);\n } else {\n fs.copyFileSync(src, dest);\n }\n log.info(`[\u56DE\u6EDA] \u5DF2\u6062\u590D: ${item}`);\n } catch (e) {\n log.warn(`[\u56DE\u6EDA] \u6062\u590D\u5931\u8D25 ${item}: ${(e as Error).message}`);\n }\n }\n return { ok: true };\n}\n\n/** \u68C0\u67E5 BDS_PATH \u4E2D\u5173\u952E\u6587\u4EF6\u662F\u5426\u90FD\u8FD8\u5728 (\u66F4\u65B0\u540E\u5B8C\u6574\u6027 sanity check) */\nexport function verifyBdsInstall(bds_path: string, expected: string[]): { ok: boolean; missing: string[] } {\n const missing: string[] = [];\n for (const f of expected) {\n if (!fs.existsSync(path.join(bds_path, f))) missing.push(f);\n }\n return { ok: missing.length === 0, missing };\n}\n\nexport { getDirSize };\n"],
5
- "mappings": "AAUA,SAAS,UAAU,iBAAiB;AACpC,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,SAAS,uBAAuB;AAChC,SAAS,aAAa,YAAY,oBAAoB;AACtD,SAAS,WAAW;AAWb,SAAS,oBAAoB,QAA8B;AAChE,MAAI;AACF,cAAU,iBAAiB,MAAM;AACjC,QAAI,KAAK,gEAAmB,eAAe,EAAE;AAAA,EAC/C,SAAS,GAAG;AACV,QAAI,KAAK,wDAAiB,EAAY,OAAO,EAAE;AAAA,EACjD;AACF;AAEO,SAAS,sBAA4B;AAC1C,MAAI;AACF,QAAI,GAAG,WAAW,eAAe,EAAG,IAAG,WAAW,eAAe;AAAA,EACnE,QAAQ;AAAA,EAER;AACF;AAEO,SAAS,qBAA4C;AAC1D,SAAO,SAAyB,eAAe,KAAK;AACtD;AAMO,SAAS,mBAAmB,QAA0D;AAC3F,QAAM,EAAE,UAAU,YAAY,SAAS,IAAI;AAC3C,MAAI,CAAC,GAAG,WAAW,UAAU,GAAG;AAC9B,WAAO,EAAE,IAAI,OAAO,QAAQ,+CAAY,UAAU,GAAG;AAAA,EACvD;AACA,MAAI,KAAK,2CAAa,SAAS,MAAM,iBAAO,QAAQ,EAAE;AACtD,aAAW,QAAQ,UAAU;AAC3B,UAAM,MAAM,KAAK,KAAK,YAAY,IAAI;AACtC,UAAM,OAAO,KAAK,KAAK,UAAU,IAAI;AACrC,QAAI,CAAC,GAAG,WAAW,GAAG,GAAG;AACvB,UAAI,KAAK,uEAAqB,IAAI,EAAE;AACpC;AAAA,IACF;AACA,QAAI;AAEF,YAAM,UAAU,KAAK,QAAQ,IAAI;AACjC,UAAI,CAAC,GAAG,WAAW,OAAO,EAAG,IAAG,UAAU,SAAS,EAAE,WAAW,KAAK,CAAC;AACtE,UAAI,GAAG,SAAS,GAAG,EAAE,YAAY,GAAG;AAElC,YAAI,GAAG,WAAW,IAAI,EAAG,cAAa,IAAI;AAC1C,oBAAY,KAAK,IAAI;AAAA,MACvB,OAAO;AACL,WAAG,aAAa,KAAK,IAAI;AAAA,MAC3B;AACA,UAAI,KAAK,sCAAa,IAAI,EAAE;AAAA,IAC9B,SAAS,GAAG;AACV,UAAI,KAAK,2CAAa,IAAI,KAAM,EAAY,OAAO,EAAE;AAAA,IACvD;AAAA,EACF;AACA,SAAO,EAAE,IAAI,KAAK;AACpB;AAGO,SAAS,iBAAiB,UAAkB,UAAwD;AACzG,QAAM,UAAoB,CAAC;AAC3B,aAAW,KAAK,UAAU;AACxB,QAAI,CAAC,GAAG,WAAW,KAAK,KAAK,UAAU,CAAC,CAAC,EAAG,SAAQ,KAAK,CAAC;AAAA,EAC5D;AACA,SAAO,EAAE,IAAI,QAAQ,WAAW,GAAG,QAAQ;AAC7C;",
4
+ "sourcesContent": ["/**\n * rollback.ts \u2014 \u56DE\u6EDA\u652F\u6301\n *\n * \u5728\u66F4\u65B0\u5F00\u59CB\u524D\u8BB0\u5F55: \u5F53\u524D BDS \u76EE\u5F55 + \u5907\u4EFD\u76EE\u5F55\u3002\n * \u4E3B\u6D41\u7A0B\u4EFB\u610F\u9636\u6BB5\u5931\u8D25\u65F6\uFF0C\u5C1D\u8BD5\u53CD\u5411\u6062\u590D preserves \u5230 BDS_PATH\uFF0C\n * \u7136\u540E\u4ECE\u5907\u4EFD\u91CD\u65B0\u653E\u56DE preserve \u5185\u5BB9\uFF0C\u6062\u590D\u65E7\u914D\u7F6E\u3002\n *\n * \u6301\u4E45\u5316: <SFMC_ROOT>/.sfmc/last_update_rollback.json \u7528\u4E8E\u8DE8\u8FDB\u7A0B\u8BB0\u5F55\u3002\n */\n\nimport { readJson, writeJson } from \"@sfmc-bds/sdk/node/config\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { ROLLBACK_MARKER } from \"./paths.js\";\nimport { copyDirSync, copyFileSyncSafe, getDirSize, emptyDirSync } from \"./fsx.js\";\nimport { log } from \"./log.js\";\n\nexport interface RollbackMarker {\n timestamp: number;\n bds_path: string;\n backup_dir: string;\n preserve: string[];\n previous_version: string;\n}\n\n/** \u5728\u5907\u4EFD\u5B8C\u6210\u540E\u8C03\u7528: \u8BB0\u5F55\u5FEB\u7167\u6307\u793A\u7B26\u3002 */\nexport function writeRollbackMarker(marker: RollbackMarker): void {\n try {\n writeJson(ROLLBACK_MARKER, marker);\n log.info(`[\u56DE\u6EDA] \u5DF2\u8BB0\u5F55\u56DE\u6EDA\u6807\u8BB0 -> ${ROLLBACK_MARKER}`);\n } catch (e) {\n log.warn(`[\u56DE\u6EDA] \u65E0\u6CD5\u5199\u5165\u6807\u8BB0: ${(e as Error).message}`);\n }\n}\n\nexport function clearRollbackMarker(): void {\n try {\n if (fs.existsSync(ROLLBACK_MARKER)) fs.unlinkSync(ROLLBACK_MARKER);\n } catch {\n /* ignore */\n }\n}\n\nexport function readRollbackMarker(): RollbackMarker | null {\n return readJson<RollbackMarker>(ROLLBACK_MARKER) ?? null;\n}\n\n/**\n * \u7D27\u6025\u56DE\u6EDA: \u628A preserve \u9879\u4ECE backup_dir \u62F7\u56DE bds_path\u3002\n * \u7528\u6CD5: \u5728 catch \u5206\u652F\u8C03\u7528\uFF0C\u5982\u679C\u4E3B\u6D41\u7A0B\u5931\u8D25\u5BFC\u81F4 BDS \u76EE\u5F55\u7834\u574F\u3002\n */\nexport function rollbackFromBackup(marker: RollbackMarker): { ok: boolean; reason?: string } {\n const { bds_path, backup_dir, preserve } = marker;\n if (!fs.existsSync(backup_dir)) {\n return { ok: false, reason: `\u5907\u4EFD\u76EE\u5F55\u4E0D\u5B58\u5728: ${backup_dir}` };\n }\n log.warn(`[\u56DE\u6EDA] \u5F00\u59CB\u6062\u590D ${preserve.length} \u9879\u5230 ${bds_path}`);\n for (const item of preserve) {\n const src = path.join(backup_dir, item);\n const dest = path.join(bds_path, item);\n if (!fs.existsSync(src)) {\n log.warn(`[\u56DE\u6EDA] \u8DF3\u8FC7 (\u5907\u4EFD\u4E2D\u4E0D\u5B58\u5728): ${item}`);\n continue;\n }\n try {\n // \u5148\u786E\u4FDD\u76EE\u6807\u76EE\u5F55\u5B58\u5728 (BDS \u76EE\u5F55\u53EF\u80FD\u5DF2\u88AB\u89E3\u538B\u8986\u76D6\u4E3A\u7A7A)\n const destDir = path.dirname(dest);\n if (!fs.existsSync(destDir)) fs.mkdirSync(destDir, { recursive: true });\n if (fs.statSync(src).isDirectory()) {\n // \u5148\u5220\u9664\u76EE\u6807\uFF0C\u518D\u590D\u5236\u76EE\u5F55\n if (fs.existsSync(dest)) emptyDirSync(dest);\n copyDirSync(src, dest);\n } else {\n copyFileSyncSafe(src, dest);\n }\n log.info(`[\u56DE\u6EDA] \u5DF2\u6062\u590D: ${item}`);\n } catch (e) {\n log.warn(`[\u56DE\u6EDA] \u6062\u590D\u5931\u8D25 ${item}: ${(e as Error).message}`);\n }\n }\n return { ok: true };\n}\n\n/** \u68C0\u67E5 BDS_PATH \u4E2D\u5173\u952E\u6587\u4EF6\u662F\u5426\u90FD\u8FD8\u5728 (\u66F4\u65B0\u540E\u5B8C\u6574\u6027 sanity check) */\nexport function verifyBdsInstall(bds_path: string, expected: string[]): { ok: boolean; missing: string[] } {\n const missing: string[] = [];\n for (const f of expected) {\n if (!fs.existsSync(path.join(bds_path, f))) missing.push(f);\n }\n return { ok: missing.length === 0, missing };\n}\n\nexport { getDirSize };\n"],
5
+ "mappings": "AAUA,SAAS,UAAU,iBAAiB;AACpC,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,SAAS,uBAAuB;AAChC,SAAS,aAAa,kBAAkB,YAAY,oBAAoB;AACxE,SAAS,WAAW;AAWb,SAAS,oBAAoB,QAA8B;AAChE,MAAI;AACF,cAAU,iBAAiB,MAAM;AACjC,QAAI,KAAK,gEAAmB,eAAe,EAAE;AAAA,EAC/C,SAAS,GAAG;AACV,QAAI,KAAK,wDAAiB,EAAY,OAAO,EAAE;AAAA,EACjD;AACF;AAEO,SAAS,sBAA4B;AAC1C,MAAI;AACF,QAAI,GAAG,WAAW,eAAe,EAAG,IAAG,WAAW,eAAe;AAAA,EACnE,QAAQ;AAAA,EAER;AACF;AAEO,SAAS,qBAA4C;AAC1D,SAAO,SAAyB,eAAe,KAAK;AACtD;AAMO,SAAS,mBAAmB,QAA0D;AAC3F,QAAM,EAAE,UAAU,YAAY,SAAS,IAAI;AAC3C,MAAI,CAAC,GAAG,WAAW,UAAU,GAAG;AAC9B,WAAO,EAAE,IAAI,OAAO,QAAQ,+CAAY,UAAU,GAAG;AAAA,EACvD;AACA,MAAI,KAAK,2CAAa,SAAS,MAAM,iBAAO,QAAQ,EAAE;AACtD,aAAW,QAAQ,UAAU;AAC3B,UAAM,MAAM,KAAK,KAAK,YAAY,IAAI;AACtC,UAAM,OAAO,KAAK,KAAK,UAAU,IAAI;AACrC,QAAI,CAAC,GAAG,WAAW,GAAG,GAAG;AACvB,UAAI,KAAK,uEAAqB,IAAI,EAAE;AACpC;AAAA,IACF;AACA,QAAI;AAEF,YAAM,UAAU,KAAK,QAAQ,IAAI;AACjC,UAAI,CAAC,GAAG,WAAW,OAAO,EAAG,IAAG,UAAU,SAAS,EAAE,WAAW,KAAK,CAAC;AACtE,UAAI,GAAG,SAAS,GAAG,EAAE,YAAY,GAAG;AAElC,YAAI,GAAG,WAAW,IAAI,EAAG,cAAa,IAAI;AAC1C,oBAAY,KAAK,IAAI;AAAA,MACvB,OAAO;AACL,yBAAiB,KAAK,IAAI;AAAA,MAC5B;AACA,UAAI,KAAK,sCAAa,IAAI,EAAE;AAAA,IAC9B,SAAS,GAAG;AACV,UAAI,KAAK,2CAAa,IAAI,KAAM,EAAY,OAAO,EAAE;AAAA,IACvD;AAAA,EACF;AACA,SAAO,EAAE,IAAI,KAAK;AACpB;AAGO,SAAS,iBAAiB,UAAkB,UAAwD;AACzG,QAAM,UAAoB,CAAC;AAC3B,aAAW,KAAK,UAAU;AACxB,QAAI,CAAC,GAAG,WAAW,KAAK,KAAK,UAAU,CAAC,CAAC,EAAG,SAAQ,KAAK,CAAC;AAAA,EAC5D;AACA,SAAO,EAAE,IAAI,QAAQ,WAAW,GAAG,QAAQ;AAC7C;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * server-properties-i18n.ts — BDS server.properties 多语言注释字典
3
+ */
4
+ export interface ServerPropertyDoc {
5
+ /** 中文功能概述 */
6
+ desc: string;
7
+ /** 合法取值与枚举说明 */
8
+ values?: string;
9
+ /** 避坑、性能或安全性提示 */
10
+ tip?: string;
11
+ }
12
+ export declare const SERVER_PROPERTIES_DOCS_ZH_CN: Record<string, ServerPropertyDoc>;
13
+ /**
14
+ * 根据属性 key 和目标语言获取说明文档
15
+ */
16
+ export declare function getServerPropertyDoc(key: string, locale?: string): ServerPropertyDoc | undefined;
17
+ //# sourceMappingURL=server-properties-i18n.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-properties-i18n.d.ts","sourceRoot":"","sources":["../src/server-properties-i18n.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,iBAAiB;IAChC,aAAa;IACb,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kBAAkB;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,eAAO,MAAM,4BAA4B,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CA2L1E,CAAC;AAEF;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,MAAgB,GAAG,iBAAiB,GAAG,SAAS,CAQzG"}
@@ -0,0 +1,201 @@
1
+ const SERVER_PROPERTIES_DOCS_ZH_CN = {
2
+ "transport": {
3
+ desc: "\u73A9\u5BB6\u4E0E\u670D\u52A1\u5668\u8FDE\u63A5\u6240\u7528\u7684\u7F51\u7EDC\u4F20\u8F93\u65B9\u5F0F",
4
+ values: "nethernet\uFF08\u5F53\u524D BDS \u7248\u672C\u652F\u6301\u7684\u4F20\u8F93\u65B9\u5F0F\uFF09"
5
+ },
6
+ "server-name": {
7
+ desc: "\u670D\u52A1\u5668\u540D\u79F0\uFF08\u663E\u793A\u5728\u5BA2\u6237\u7AEF\u5C40\u57DF\u7F51/\u597D\u53CB\u5217\u8868\u4E2D\uFF09",
8
+ values: "\u4EFB\u610F\u5B57\u7B26\u4E32\uFF08\u8BF7\u52FF\u5305\u542B\u5206\u53F7 ;\uFF09"
9
+ },
10
+ "gamemode": {
11
+ desc: "\u65B0\u73A9\u5BB6\u9996\u6B21\u52A0\u5165\u4E16\u754C\u65F6\u7684\u9ED8\u8BA4\u6E38\u620F\u6A21\u5F0F",
12
+ values: "survival (\u751F\u5B58) | creative (\u521B\u9020) | adventure (\u5192\u9669)"
13
+ },
14
+ "force-gamemode": {
15
+ desc: "\u662F\u5426\u5F3A\u5236\u73A9\u5BB6\u6BCF\u6B21\u91CD\u65B0\u8FDE\u63A5\u65F6\u90FD\u91CD\u7F6E\u4E3A\u9ED8\u8BA4\u6E38\u620F\u6A21\u5F0F",
16
+ values: "true (\u6BCF\u6B21\u8FDB\u670D\u5F3A\u5236\u8F6C\u4E3A\u9ED8\u8BA4\u6A21\u5F0F) | false (\u4FDD\u7559\u73A9\u5BB6\u4E0A\u6B21\u79BB\u7EBF\u65F6\u7684\u6A21\u5F0F)"
17
+ },
18
+ "difficulty": {
19
+ desc: "\u6E38\u620F\u4E16\u754C\u7684\u9ED8\u8BA4\u96BE\u5EA6",
20
+ values: "peaceful (\u548C\u5E73) | easy (\u7B80\u5355) | normal (\u666E\u901A) | hard (\u56F0\u96BE)"
21
+ },
22
+ "allow-cheats": {
23
+ desc: "\u662F\u5426\u5141\u8BB8\u5728\u63A7\u5236\u53F0\u6216\u6E38\u620F\u5185\u4F7F\u7528\u7BA1\u7406\u5458\u6307\u4EE4\uFF08\u4F5C\u5F0A\u6A21\u5F0F\uFF09",
24
+ values: "true | false",
25
+ tip: "\u82E5\u5F00\u542F\u6B64\u9879\uFF0C\u52A0\u5165\u8BE5\u4E16\u754C\u7684\u73A9\u5BB6\u5C06\u65E0\u6CD5\u83B7\u5F97 Xbox \u6210\u5C31"
26
+ },
27
+ "max-players": {
28
+ desc: "\u5141\u8BB8\u540C\u65F6\u5728\u7EBF\u7684\u6700\u5927\u73A9\u5BB6\u6570\u91CF\u9650\u5236",
29
+ values: "\u6B63\u6574\u6570\uFF08\u5982 10\u300120\uFF09"
30
+ },
31
+ "online-mode": {
32
+ desc: "\u662F\u5426\u5F00\u542F\u5FAE\u8F6F Xbox Live \u6B63\u7248\u8EAB\u4EFD\u9A8C\u8BC1",
33
+ values: "true (\u4EC5\u5141\u8BB8\u6B63\u7248\u5FAE\u8F6F\u8D26\u53F7\u767B\u5F55) | false (\u5141\u8BB8\u79BB\u7EBF\u514D\u767B\u5F55\u8FDE\u63A5\uFF0C\u4F46\u6613\u53D7\u5047\u4EBA\u653B\u51FB)",
34
+ tip: "\u516C\u7F51\u670D\u52A1\u5668\u5F3A\u70C8\u5EFA\u8BAE\u8BBE\u4E3A true \u4EE5\u9632\u6B62\u6076\u610F\u4F2A\u9020\u8EAB\u4EFD"
35
+ },
36
+ "white-list": {
37
+ desc: "\u662F\u5426\u5F00\u542F\u51C6\u5165\u767D\u540D\u5355\u9A8C\u8BC1\uFF08\u90E8\u5206\u7248\u672C\u5BF9\u5E94 allow-list\uFF09",
38
+ values: "true (\u4EC5\u5141\u8BB8\u767D\u540D\u5355\u4E2D\u7684\u73A9\u5BB6\u8FDB\u5165) | false (\u6240\u6709\u73A9\u5BB6\u5747\u53EF\u8FDB\u5165)"
39
+ },
40
+ "allow-list": {
41
+ desc: "\u662F\u5426\u5F00\u542F\u51C6\u5165\u767D\u540D\u5355\u9A8C\u8BC1\uFF08\u9700\u914D\u5408 allowlist.json \u4F7F\u7528\uFF09",
42
+ values: "true (\u4EC5\u5141\u8BB8\u767D\u540D\u5355\u4E2D\u7684\u73A9\u5BB6\u8FDB\u5165) | false (\u6240\u6709\u73A9\u5BB6\u5747\u53EF\u8FDB\u5165)"
43
+ },
44
+ "server-port": {
45
+ desc: "\u670D\u52A1\u7AEF\u76D1\u542C\u7684 IPv4 UDP \u7F51\u7EDC\u901A\u4FE1\u7AEF\u53E3",
46
+ values: "1 ~ 65535\uFF08\u9ED8\u8BA4\uFF1A19132\uFF09"
47
+ },
48
+ "server-portv6": {
49
+ desc: "\u670D\u52A1\u7AEF\u76D1\u542C\u7684 IPv6 UDP \u7F51\u7EDC\u901A\u4FE1\u7AEF\u53E3",
50
+ values: "1 ~ 65535\uFF08\u9ED8\u8BA4\uFF1A19133\uFF09"
51
+ },
52
+ "enable-lan-visibility": {
53
+ desc: "\u662F\u5426\u5411\u5C40\u57DF\u7F51\u5E7F\u64AD\u672C\u670D\u52A1\u5668\uFF08\u4F7F\u540C\u5C40\u57DF\u7F51\u73A9\u5BB6\u80FD\u5728\u5BA2\u6237\u7AEF\u300C\u597D\u53CB\u300D\u5217\u8868\u4E2D\u76F4\u63A5\u53D1\u73B0\uFF09",
54
+ values: "true | false"
55
+ },
56
+ "view-distance": {
57
+ desc: "\u670D\u52A1\u7AEF\u5411\u5BA2\u6237\u7AEF\u53D1\u9001\u5730\u56FE\u533A\u5757\u7684\u6700\u5927\u89C6\u8DDD\uFF08\u5355\u4F4D\uFF1A\u533A\u5757\uFF09",
58
+ values: "\u6B63\u6574\u6570\uFF08\u5EFA\u8BAE 12 ~ 32\uFF0C\u6570\u503C\u8D8A\u5927\u7F51\u7EDC\u4E0E\u5185\u5B58\u6D88\u8017\u8D8A\u9AD8\uFF09"
59
+ },
60
+ "tick-distance": {
61
+ desc: "\u4E16\u754C\u5B9E\u4F53\u903B\u8F91\u4E0E\u65B9\u5757\u66F4\u65B0\u7684\u6A21\u62DF\u8BA1\u7B97\u8DDD\u79BB\uFF08\u5355\u4F4D\uFF1A\u533A\u5757\uFF09",
62
+ values: "4 ~ 12\uFF08\u6570\u503C\u8D8A\u5C0F\u670D\u52A1\u5668\u6027\u80FD\u8D8A\u597D\uFF0C\u4F4E\u914D\u673A\u578B\u63A8\u8350 4\uFF09"
63
+ },
64
+ "player-idle-timeout": {
65
+ desc: "\u73A9\u5BB6\u6302\u673A\u65E0\u64CD\u4F5C\u81EA\u52A8\u8E22\u51FA\u8D85\u65F6\u65F6\u95F4\uFF08\u5355\u4F4D\uFF1A\u5206\u949F\uFF09",
66
+ values: "0 (\u6C38\u4E0D\u8E22\u51FA) \u6216\u5927\u4E8E 0 \u7684\u6574\u6570"
67
+ },
68
+ "max-threads": {
69
+ desc: "BDS \u8FD0\u884C\u53EF\u4F7F\u7528\u7684\u6700\u5927\u5DE5\u4F5C\u7EBF\u7A0B\u6570",
70
+ values: "0 (\u7531\u670D\u52A1\u7AEF\u6839\u636E CPU \u6838\u5FC3\u6570\u81EA\u52A8\u5206\u914D) \u6216\u6307\u5B9A\u7EBF\u7A0B\u6570"
71
+ },
72
+ "level-name": {
73
+ desc: "\u8981\u52A0\u8F7D\u7684\u4E16\u754C\u5B58\u6863\u6587\u4EF6\u5939\u540D\u79F0\uFF08\u5BF9\u5E94 worlds/ \u76EE\u5F55\u4E0B\u7684\u5B50\u6587\u4EF6\u5939\uFF09",
74
+ values: "\u6587\u4EF6\u5939\u540D\u79F0\uFF08\u9ED8\u8BA4\uFF1ABedrock level\uFF09"
75
+ },
76
+ "level-seed": {
77
+ desc: "\u5168\u65B0\u4E16\u754C\u751F\u6210\u65F6\u7684\u968F\u673A\u79CD\u5B50",
78
+ values: "\u4EFB\u610F\u6570\u5B57\u6216\u6587\u672C\uFF08\u7559\u7A7A\u5219\u6BCF\u6B21\u65B0\u5EFA\u4E16\u754C\u968F\u673A\u751F\u6210\uFF09"
79
+ },
80
+ "default-player-permission-level": {
81
+ desc: "\u65B0\u73A9\u5BB6\u9996\u6B21\u52A0\u5165\u65F6\u7684\u9ED8\u8BA4\u6743\u9650\u7EA7\u522B",
82
+ values: "visitor (\u8BBF\u5BA2\uFF0C\u4E0D\u53EF\u7834\u574F\u6216\u4EA4\u4E92) | member (\u666E\u901A\u6210\u5458) | operator (\u64CD\u4F5C\u5458)"
83
+ },
84
+ "texturepack-required": {
85
+ desc: "\u662F\u5426\u5F3A\u5236\u73A9\u5BB6\u4E0B\u8F7D\u670D\u52A1\u5668\u6307\u5B9A\u7684\u6750\u8D28\u8D44\u6E90\u5305\u540E\u624D\u80FD\u52A0\u5165",
86
+ values: "true (\u5FC5\u987B\u4E0B\u8F7D) | false (\u53EF\u9009\u4E0B\u8F7D)"
87
+ },
88
+ "content-log-console-output-enabled": {
89
+ desc: "\u662F\u5426\u5C06\u5185\u5BB9\u65E5\u5FD7\uFF08\u6A21\u7EC4/\u884C\u4E3A\u5305\u89E3\u6790\u8B66\u544A\u3001SAPI \u811A\u672C\u62A5\u9519\u4E0E console.log\uFF09\u5B9E\u65F6\u8F93\u51FA\u5230\u63A7\u5236\u53F0",
90
+ values: "true | false",
91
+ tip: "\u5F00\u53D1\u6216\u8C03\u8BD5\u6A21\u7EC4\u65F6\u5F3A\u70C8\u5EFA\u8BAE\u8BBE\u4E3A true\uFF0C\u4EE5\u4FBF\u5373\u65F6\u67E5\u770B\u9519\u8BEF"
92
+ },
93
+ "compression-threshold": {
94
+ desc: "\u7F51\u7EDC\u6570\u636E\u5305\u542F\u7528\u538B\u7F29\u7684\u6700\u5C0F\u5B57\u8282\u9608\u503C",
95
+ values: "0 (\u5168\u90E8\u538B\u7F29) ~ 65535 \u5B57\u8282\uFF081.20+ \u9ED8\u8BA4\u901A\u5E38\u4E3A 1\uFF09"
96
+ },
97
+ "compression-algorithm": {
98
+ desc: "\u7F51\u7EDC\u4F20\u8F93\u6570\u636E\u5305\u7684\u538B\u7F29\u7B97\u6CD5",
99
+ values: "zlib (\u6807\u51C6\u9AD8\u538B\u7F29\u6BD4) | snappy (\u9AD8\u6027\u80FD\u4F4E\u5EF6\u8FDF\uFF0CCPU \u5F00\u9500\u5C0F)"
100
+ },
101
+ "server-authoritative-movement": {
102
+ desc: "\u73A9\u5BB6\u79FB\u52A8\u9A8C\u8BC1\u6743\u5A01\u6A21\u5F0F",
103
+ values: "server-auth (\u670D\u52A1\u7AEF\u6743\u5A01\u5224\u5B9A) | client-auth (\u5BA2\u6237\u7AEF\u6743\u5A01)"
104
+ },
105
+ "player-movement-score-threshold": {
106
+ desc: "\u73A9\u5BB6\u79FB\u52A8\u5F02\u5E38\u88AB\u5224\u5B9A\u4E3A\u4F5C\u5F0A\u7684\u7D2F\u8BA1\u5F02\u5E38\u5206\u9608\u503C",
107
+ values: "\u6574\u6570\uFF08\u9ED8\u8BA4 20\uFF09"
108
+ },
109
+ "player-movement-action-direction-threshold": {
110
+ desc: "\u73A9\u5BB6\u653B\u51FB\u6216\u7834\u574F\u52A8\u4F5C\u4E0E\u89C6\u7EBF\u671D\u5411\u5939\u89D2\u504F\u5DEE\u7684\u5224\u5B9A\u9608\u503C",
111
+ values: "\u6D6E\u70B9\u6570\uFF08\u9ED8\u8BA4 0.85\uFF09"
112
+ },
113
+ "player-movement-distance-threshold": {
114
+ desc: "\u73A9\u5BB6\u5355\u6B21\u4F4D\u79FB\u8D85\u51FA\u6B63\u5E38\u8303\u56F4\u7684\u5224\u5B9A\u9608\u503C",
115
+ values: "\u6D6E\u70B9\u6570\uFF08\u9ED8\u8BA4 0.3\uFF09"
116
+ },
117
+ "player-movement-duration-threshold-in-ms": {
118
+ desc: "\u79FB\u52A8\u5F02\u5E38\u5224\u5B9A\u91C7\u6837\u7684\u6ED1\u52A8\u65F6\u95F4\u7A97\u53E3\uFF08\u5355\u4F4D\uFF1A\u6BEB\u79D2\uFF09",
119
+ values: "\u6574\u6570\uFF08\u9ED8\u8BA4 500\uFF09"
120
+ },
121
+ "correct-player-movement": {
122
+ desc: "\u5F53\u68C0\u6D4B\u5230\u73A9\u5BB6\u79FB\u52A8\u4F5C\u5F0A\u6216\u8D85\u6807\u65F6\uFF0C\u662F\u5426\u5F3A\u5236\u5C06\u5176\u62C9\u56DE\u5408\u6CD5\u4F4D\u7F6E\uFF08\u9632\u98DE\u5929/\u52A0\u901F\uFF09",
123
+ values: "true (\u5F3A\u5236\u56DE\u62C9\u7EA0\u6B63) | false (\u4EC5\u5728\u540E\u53F0\u8BB0\u5F55\u8B66\u544A)"
124
+ },
125
+ "server-authoritative-block-breaking": {
126
+ desc: "\u65B9\u5757\u7834\u574F\u52A8\u4F5C\u662F\u5426\u7531\u670D\u52A1\u7AEF\u6743\u5A01\u5224\u5B9A\uFF08\u9632\u6B62\u53D8\u901F\u5237\u65B9\u5757\u7B49\u4F5C\u5F0A\u884C\u4E3A\uFF09",
127
+ values: "client-auth | server-auth"
128
+ },
129
+ "chat-restriction": {
130
+ desc: "\u804A\u5929\u8FC7\u6EE4\u9650\u5236\u7B56\u7565",
131
+ values: "None (\u65E0\u9650\u5236) | Dropped (\u9759\u9ED8\u4E22\u5F03\u8FDD\u89C4\u5185\u5BB9) | Disabled (\u5B8C\u5168\u7981\u7528\u804A\u5929)"
132
+ },
133
+ "disable-player-interaction": {
134
+ desc: "\u662F\u5426\u7981\u7528\u9759\u9ED8\u4EA4\u4E92\u68C0\u6D4B\uFF08\u7528\u4E8E\u6392\u67E5\u7F51\u7EDC\u5EF6\u8FDF\u6216\u9632\u5FEB\u901F\u4EA4\u4E92\uFF09",
135
+ values: "true | false"
136
+ },
137
+ "client-side-chunk-generation-enabled": {
138
+ desc: "\u662F\u5426\u5141\u8BB8\u5BA2\u6237\u7AEF\u5728\u672C\u5730\u751F\u6210\u5C1A\u672A\u52A0\u8F7D\u7684\u5730\u5F62\u533A\u5757\uFF08\u52A0\u5FEB\u957F\u8DDD\u79BB\u63A2\u7D22\u65F6\u7684\u89C6\u89C9\u52A0\u8F7D\u901F\u5EA6\uFF09",
139
+ values: "true (\u5141\u8BB8\u5BA2\u6237\u7AEF\u672C\u5730\u9884\u751F\u6210) | false (\u5168\u90E8\u7531\u670D\u52A1\u7AEF\u751F\u6210\u5E76\u4F20\u8F93)"
140
+ },
141
+ "block-network-ids-are-hashes": {
142
+ desc: "\u65B9\u5757\u5728\u7F51\u7EDC\u4F20\u8F93\u4E2D\u7684\u552F\u4E00\u6807\u8BC6\u662F\u5426\u91C7\u7528\u54C8\u5E0C\u503C",
143
+ values: "true | false"
144
+ },
145
+ "disable-persona": {
146
+ desc: "\u662F\u5426\u7981\u7528\u4E2A\u6027\u5316\u88C5\u626E/\u89D2\u8272\u521B\u5EFA\u5668\uFF08Persona \u76AE\u80A4\uFF09",
147
+ values: "true (\u5F3A\u5236\u4F7F\u7528\u7ECF\u5178\u76AE\u80A4) | false (\u5141\u8BB8\u4F7F\u7528\u5B98\u65B9\u634F\u8138\u89D2\u8272)"
148
+ },
149
+ "disable-custom-skins": {
150
+ desc: "\u662F\u5426\u7981\u7528\u73A9\u5BB6\u4E0A\u4F20\u7684\u81EA\u5B9A\u4E49\u7ECF\u5178\u76AE\u80A4\uFF08\u9632\u6B62\u6076\u610F\u6216\u900F\u660E\u76AE\u80A4\uFF09",
151
+ values: "true (\u7981\u7528\u81EA\u5B9A\u4E49\u76AE\u80A4) | false (\u5141\u8BB8\u81EA\u5B9A\u4E49\u76AE\u80A4)"
152
+ },
153
+ "emit-server-telemetry": {
154
+ desc: "\u662F\u5426\u5411 Mojang \u53D1\u9001\u670D\u52A1\u5668\u9065\u6D4B\u4E0E\u8FD0\u884C\u5065\u5EB7\u8BCA\u65AD\u6570\u636E",
155
+ values: "true | false",
156
+ tip: "\u4F7F\u7528\u672C\u5E73\u53F0\u65F6\u56E0\u60A8\u5DF2\u540C\u610F Mojang EULA \u534F\u8BAE\uFF0C\u6309\u534F\u8BAE\u4FDD\u6301\u542F\u7528"
157
+ },
158
+ "server-build-radius-ratio": {
159
+ desc: "\u5141\u8BB8\u73A9\u5BB6\u5EFA\u9020\u548C\u4EA4\u4E92\u7684\u4E16\u754C\u533A\u57DF\u534A\u5F84\u6BD4\u4F8B",
160
+ values: "Disabled (\u65E0\u9650\u5236) \u6216 0.0 ~ 1.0 \u7684\u6D6E\u70B9\u6570"
161
+ },
162
+ "allow-outbound-script-debugging": {
163
+ desc: "\u662F\u5426\u5141\u8BB8\u670D\u52A1\u7AEF\u811A\u672C\u4E3B\u52A8\u8FDE\u63A5\u5916\u90E8\u8C03\u8BD5\u5668\uFF08\u5141\u8BB8 /script debugger connect \u6307\u4EE4\uFF09",
164
+ values: "true | false",
165
+ tip: "\u4EC5\u5728\u901A\u8FC7 VS Code \u8C03\u8BD5 SAPI \u6A21\u7EC4\u65F6\u5F00\u542F\uFF0C\u751F\u4EA7\u73AF\u5883\u5EFA\u8BAE\u5173\u95ED"
166
+ },
167
+ "allow-inbound-script-debugging": {
168
+ desc: "\u662F\u5426\u5141\u8BB8\u5916\u90E8\u811A\u672C\u8C03\u8BD5\u5668\u4E3B\u52A8\u8FDE\u63A5\u670D\u52A1\u7AEF\uFF08\u5141\u8BB8 /script debugger listen \u6307\u4EE4\uFF09",
169
+ values: "true | false",
170
+ tip: "\u4EC5\u5728\u901A\u8FC7 VS Code \u8C03\u8BD5 SAPI \u6A21\u7EC4\u65F6\u5F00\u542F\uFF0C\u751F\u4EA7\u73AF\u5883\u5EFA\u8BAE\u5173\u95ED"
171
+ },
172
+ "force-inbound-debug-port": {
173
+ desc: "\u811A\u672C\u8C03\u8BD5\u5668\u76D1\u542C\u7684\u4E13\u5C5E\u7F51\u7EDC\u7AEF\u53E3",
174
+ values: "1 ~ 65535\uFF08\u9ED8\u8BA4\uFF1A19144\uFF09"
175
+ },
176
+ "script-debugger-auto-attach": {
177
+ desc: "\u4E16\u754C\u52A0\u8F7D\u65F6\uFF0C\u662F\u5426\u81EA\u52A8\u8FDE\u63A5\u6216\u76D1\u542C\u5916\u90E8\u811A\u672C\u8C03\u8BD5\u5668",
178
+ values: "disabled (\u4E0D\u81EA\u52A8\u9644\u52A0) | connect (\u81EA\u52A8\u5411\u5916\u8FDE\u63A5) | listen (\u81EA\u52A8\u5F00\u542F\u7AEF\u53E3\u76D1\u542C)"
179
+ },
180
+ "script-debugger-auto-attach-connect-address": {
181
+ desc: "\u5F53 auto-attach \u8BBE\u4E3A connect \u65F6\uFF0C\u5C1D\u8BD5\u8FDE\u63A5\u7684\u76EE\u6807\u8C03\u8BD5\u5668\u4E3B\u673A\u4E0E\u7AEF\u53E3",
182
+ values: "ip:port\uFF08\u4F8B\u5982 localhost:19144\uFF09"
183
+ },
184
+ "websocket-retry-time": {
185
+ desc: "\u8FDE\u63A5\u5916\u90E8 WebSocket \u670D\u52A1\u5668\u65AD\u5F00\u540E\u7684\u81EA\u52A8\u91CD\u8BD5\u95F4\u9694\uFF08\u5355\u4F4D\uFF1A\u79D2\uFF09",
186
+ values: "\u6B63\u6574\u6570\uFF08\u9ED8\u8BA4 20\uFF09"
187
+ }
188
+ };
189
+ function getServerPropertyDoc(key, locale = "zh-CN") {
190
+ const normalizedKey = key.trim().toLowerCase();
191
+ const normalizedLocale = locale.toLowerCase();
192
+ if (normalizedLocale === "zh" || normalizedLocale.startsWith("zh-")) {
193
+ return SERVER_PROPERTIES_DOCS_ZH_CN[normalizedKey];
194
+ }
195
+ return void 0;
196
+ }
197
+ export {
198
+ SERVER_PROPERTIES_DOCS_ZH_CN,
199
+ getServerPropertyDoc
200
+ };
201
+ //# sourceMappingURL=server-properties-i18n.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/server-properties-i18n.ts"],
4
+ "sourcesContent": ["/**\n * server-properties-i18n.ts \u2014 BDS server.properties \u591A\u8BED\u8A00\u6CE8\u91CA\u5B57\u5178\n */\n\nexport interface ServerPropertyDoc {\n /** \u4E2D\u6587\u529F\u80FD\u6982\u8FF0 */\n desc: string;\n /** \u5408\u6CD5\u53D6\u503C\u4E0E\u679A\u4E3E\u8BF4\u660E */\n values?: string;\n /** \u907F\u5751\u3001\u6027\u80FD\u6216\u5B89\u5168\u6027\u63D0\u793A */\n tip?: string;\n}\n\nexport const SERVER_PROPERTIES_DOCS_ZH_CN: Record<string, ServerPropertyDoc> = {\n \"transport\": {\n desc: \"\u73A9\u5BB6\u4E0E\u670D\u52A1\u5668\u8FDE\u63A5\u6240\u7528\u7684\u7F51\u7EDC\u4F20\u8F93\u65B9\u5F0F\",\n values: \"nethernet\uFF08\u5F53\u524D BDS \u7248\u672C\u652F\u6301\u7684\u4F20\u8F93\u65B9\u5F0F\uFF09\",\n },\n \"server-name\": {\n desc: \"\u670D\u52A1\u5668\u540D\u79F0\uFF08\u663E\u793A\u5728\u5BA2\u6237\u7AEF\u5C40\u57DF\u7F51/\u597D\u53CB\u5217\u8868\u4E2D\uFF09\",\n values: \"\u4EFB\u610F\u5B57\u7B26\u4E32\uFF08\u8BF7\u52FF\u5305\u542B\u5206\u53F7 ;\uFF09\",\n },\n \"gamemode\": {\n desc: \"\u65B0\u73A9\u5BB6\u9996\u6B21\u52A0\u5165\u4E16\u754C\u65F6\u7684\u9ED8\u8BA4\u6E38\u620F\u6A21\u5F0F\",\n values: \"survival (\u751F\u5B58) | creative (\u521B\u9020) | adventure (\u5192\u9669)\",\n },\n \"force-gamemode\": {\n desc: \"\u662F\u5426\u5F3A\u5236\u73A9\u5BB6\u6BCF\u6B21\u91CD\u65B0\u8FDE\u63A5\u65F6\u90FD\u91CD\u7F6E\u4E3A\u9ED8\u8BA4\u6E38\u620F\u6A21\u5F0F\",\n values: \"true (\u6BCF\u6B21\u8FDB\u670D\u5F3A\u5236\u8F6C\u4E3A\u9ED8\u8BA4\u6A21\u5F0F) | false (\u4FDD\u7559\u73A9\u5BB6\u4E0A\u6B21\u79BB\u7EBF\u65F6\u7684\u6A21\u5F0F)\",\n },\n \"difficulty\": {\n desc: \"\u6E38\u620F\u4E16\u754C\u7684\u9ED8\u8BA4\u96BE\u5EA6\",\n values: \"peaceful (\u548C\u5E73) | easy (\u7B80\u5355) | normal (\u666E\u901A) | hard (\u56F0\u96BE)\",\n },\n \"allow-cheats\": {\n desc: \"\u662F\u5426\u5141\u8BB8\u5728\u63A7\u5236\u53F0\u6216\u6E38\u620F\u5185\u4F7F\u7528\u7BA1\u7406\u5458\u6307\u4EE4\uFF08\u4F5C\u5F0A\u6A21\u5F0F\uFF09\",\n values: \"true | false\",\n tip: \"\u82E5\u5F00\u542F\u6B64\u9879\uFF0C\u52A0\u5165\u8BE5\u4E16\u754C\u7684\u73A9\u5BB6\u5C06\u65E0\u6CD5\u83B7\u5F97 Xbox \u6210\u5C31\",\n },\n \"max-players\": {\n desc: \"\u5141\u8BB8\u540C\u65F6\u5728\u7EBF\u7684\u6700\u5927\u73A9\u5BB6\u6570\u91CF\u9650\u5236\",\n values: \"\u6B63\u6574\u6570\uFF08\u5982 10\u300120\uFF09\",\n },\n \"online-mode\": {\n desc: \"\u662F\u5426\u5F00\u542F\u5FAE\u8F6F Xbox Live \u6B63\u7248\u8EAB\u4EFD\u9A8C\u8BC1\",\n values: \"true (\u4EC5\u5141\u8BB8\u6B63\u7248\u5FAE\u8F6F\u8D26\u53F7\u767B\u5F55) | false (\u5141\u8BB8\u79BB\u7EBF\u514D\u767B\u5F55\u8FDE\u63A5\uFF0C\u4F46\u6613\u53D7\u5047\u4EBA\u653B\u51FB)\",\n tip: \"\u516C\u7F51\u670D\u52A1\u5668\u5F3A\u70C8\u5EFA\u8BAE\u8BBE\u4E3A true \u4EE5\u9632\u6B62\u6076\u610F\u4F2A\u9020\u8EAB\u4EFD\",\n },\n \"white-list\": {\n desc: \"\u662F\u5426\u5F00\u542F\u51C6\u5165\u767D\u540D\u5355\u9A8C\u8BC1\uFF08\u90E8\u5206\u7248\u672C\u5BF9\u5E94 allow-list\uFF09\",\n values: \"true (\u4EC5\u5141\u8BB8\u767D\u540D\u5355\u4E2D\u7684\u73A9\u5BB6\u8FDB\u5165) | false (\u6240\u6709\u73A9\u5BB6\u5747\u53EF\u8FDB\u5165)\",\n },\n \"allow-list\": {\n desc: \"\u662F\u5426\u5F00\u542F\u51C6\u5165\u767D\u540D\u5355\u9A8C\u8BC1\uFF08\u9700\u914D\u5408 allowlist.json \u4F7F\u7528\uFF09\",\n values: \"true (\u4EC5\u5141\u8BB8\u767D\u540D\u5355\u4E2D\u7684\u73A9\u5BB6\u8FDB\u5165) | false (\u6240\u6709\u73A9\u5BB6\u5747\u53EF\u8FDB\u5165)\",\n },\n \"server-port\": {\n desc: \"\u670D\u52A1\u7AEF\u76D1\u542C\u7684 IPv4 UDP \u7F51\u7EDC\u901A\u4FE1\u7AEF\u53E3\",\n values: \"1 ~ 65535\uFF08\u9ED8\u8BA4\uFF1A19132\uFF09\",\n },\n \"server-portv6\": {\n desc: \"\u670D\u52A1\u7AEF\u76D1\u542C\u7684 IPv6 UDP \u7F51\u7EDC\u901A\u4FE1\u7AEF\u53E3\",\n values: \"1 ~ 65535\uFF08\u9ED8\u8BA4\uFF1A19133\uFF09\",\n },\n \"enable-lan-visibility\": {\n desc: \"\u662F\u5426\u5411\u5C40\u57DF\u7F51\u5E7F\u64AD\u672C\u670D\u52A1\u5668\uFF08\u4F7F\u540C\u5C40\u57DF\u7F51\u73A9\u5BB6\u80FD\u5728\u5BA2\u6237\u7AEF\u300C\u597D\u53CB\u300D\u5217\u8868\u4E2D\u76F4\u63A5\u53D1\u73B0\uFF09\",\n values: \"true | false\",\n },\n \"view-distance\": {\n desc: \"\u670D\u52A1\u7AEF\u5411\u5BA2\u6237\u7AEF\u53D1\u9001\u5730\u56FE\u533A\u5757\u7684\u6700\u5927\u89C6\u8DDD\uFF08\u5355\u4F4D\uFF1A\u533A\u5757\uFF09\",\n values: \"\u6B63\u6574\u6570\uFF08\u5EFA\u8BAE 12 ~ 32\uFF0C\u6570\u503C\u8D8A\u5927\u7F51\u7EDC\u4E0E\u5185\u5B58\u6D88\u8017\u8D8A\u9AD8\uFF09\",\n },\n \"tick-distance\": {\n desc: \"\u4E16\u754C\u5B9E\u4F53\u903B\u8F91\u4E0E\u65B9\u5757\u66F4\u65B0\u7684\u6A21\u62DF\u8BA1\u7B97\u8DDD\u79BB\uFF08\u5355\u4F4D\uFF1A\u533A\u5757\uFF09\",\n values: \"4 ~ 12\uFF08\u6570\u503C\u8D8A\u5C0F\u670D\u52A1\u5668\u6027\u80FD\u8D8A\u597D\uFF0C\u4F4E\u914D\u673A\u578B\u63A8\u8350 4\uFF09\",\n },\n \"player-idle-timeout\": {\n desc: \"\u73A9\u5BB6\u6302\u673A\u65E0\u64CD\u4F5C\u81EA\u52A8\u8E22\u51FA\u8D85\u65F6\u65F6\u95F4\uFF08\u5355\u4F4D\uFF1A\u5206\u949F\uFF09\",\n values: \"0 (\u6C38\u4E0D\u8E22\u51FA) \u6216\u5927\u4E8E 0 \u7684\u6574\u6570\",\n },\n \"max-threads\": {\n desc: \"BDS \u8FD0\u884C\u53EF\u4F7F\u7528\u7684\u6700\u5927\u5DE5\u4F5C\u7EBF\u7A0B\u6570\",\n values: \"0 (\u7531\u670D\u52A1\u7AEF\u6839\u636E CPU \u6838\u5FC3\u6570\u81EA\u52A8\u5206\u914D) \u6216\u6307\u5B9A\u7EBF\u7A0B\u6570\",\n },\n \"level-name\": {\n desc: \"\u8981\u52A0\u8F7D\u7684\u4E16\u754C\u5B58\u6863\u6587\u4EF6\u5939\u540D\u79F0\uFF08\u5BF9\u5E94 worlds/ \u76EE\u5F55\u4E0B\u7684\u5B50\u6587\u4EF6\u5939\uFF09\",\n values: \"\u6587\u4EF6\u5939\u540D\u79F0\uFF08\u9ED8\u8BA4\uFF1ABedrock level\uFF09\",\n },\n \"level-seed\": {\n desc: \"\u5168\u65B0\u4E16\u754C\u751F\u6210\u65F6\u7684\u968F\u673A\u79CD\u5B50\",\n values: \"\u4EFB\u610F\u6570\u5B57\u6216\u6587\u672C\uFF08\u7559\u7A7A\u5219\u6BCF\u6B21\u65B0\u5EFA\u4E16\u754C\u968F\u673A\u751F\u6210\uFF09\",\n },\n \"default-player-permission-level\": {\n desc: \"\u65B0\u73A9\u5BB6\u9996\u6B21\u52A0\u5165\u65F6\u7684\u9ED8\u8BA4\u6743\u9650\u7EA7\u522B\",\n values: \"visitor (\u8BBF\u5BA2\uFF0C\u4E0D\u53EF\u7834\u574F\u6216\u4EA4\u4E92) | member (\u666E\u901A\u6210\u5458) | operator (\u64CD\u4F5C\u5458)\",\n },\n \"texturepack-required\": {\n desc: \"\u662F\u5426\u5F3A\u5236\u73A9\u5BB6\u4E0B\u8F7D\u670D\u52A1\u5668\u6307\u5B9A\u7684\u6750\u8D28\u8D44\u6E90\u5305\u540E\u624D\u80FD\u52A0\u5165\",\n values: \"true (\u5FC5\u987B\u4E0B\u8F7D) | false (\u53EF\u9009\u4E0B\u8F7D)\",\n },\n \"content-log-console-output-enabled\": {\n desc: \"\u662F\u5426\u5C06\u5185\u5BB9\u65E5\u5FD7\uFF08\u6A21\u7EC4/\u884C\u4E3A\u5305\u89E3\u6790\u8B66\u544A\u3001SAPI \u811A\u672C\u62A5\u9519\u4E0E console.log\uFF09\u5B9E\u65F6\u8F93\u51FA\u5230\u63A7\u5236\u53F0\",\n values: \"true | false\",\n tip: \"\u5F00\u53D1\u6216\u8C03\u8BD5\u6A21\u7EC4\u65F6\u5F3A\u70C8\u5EFA\u8BAE\u8BBE\u4E3A true\uFF0C\u4EE5\u4FBF\u5373\u65F6\u67E5\u770B\u9519\u8BEF\",\n },\n \"compression-threshold\": {\n desc: \"\u7F51\u7EDC\u6570\u636E\u5305\u542F\u7528\u538B\u7F29\u7684\u6700\u5C0F\u5B57\u8282\u9608\u503C\",\n values: \"0 (\u5168\u90E8\u538B\u7F29) ~ 65535 \u5B57\u8282\uFF081.20+ \u9ED8\u8BA4\u901A\u5E38\u4E3A 1\uFF09\",\n },\n \"compression-algorithm\": {\n desc: \"\u7F51\u7EDC\u4F20\u8F93\u6570\u636E\u5305\u7684\u538B\u7F29\u7B97\u6CD5\",\n values: \"zlib (\u6807\u51C6\u9AD8\u538B\u7F29\u6BD4) | snappy (\u9AD8\u6027\u80FD\u4F4E\u5EF6\u8FDF\uFF0CCPU \u5F00\u9500\u5C0F)\",\n },\n \"server-authoritative-movement\": {\n desc: \"\u73A9\u5BB6\u79FB\u52A8\u9A8C\u8BC1\u6743\u5A01\u6A21\u5F0F\",\n values: \"server-auth (\u670D\u52A1\u7AEF\u6743\u5A01\u5224\u5B9A) | client-auth (\u5BA2\u6237\u7AEF\u6743\u5A01)\",\n },\n \"player-movement-score-threshold\": {\n desc: \"\u73A9\u5BB6\u79FB\u52A8\u5F02\u5E38\u88AB\u5224\u5B9A\u4E3A\u4F5C\u5F0A\u7684\u7D2F\u8BA1\u5F02\u5E38\u5206\u9608\u503C\",\n values: \"\u6574\u6570\uFF08\u9ED8\u8BA4 20\uFF09\",\n },\n \"player-movement-action-direction-threshold\": {\n desc: \"\u73A9\u5BB6\u653B\u51FB\u6216\u7834\u574F\u52A8\u4F5C\u4E0E\u89C6\u7EBF\u671D\u5411\u5939\u89D2\u504F\u5DEE\u7684\u5224\u5B9A\u9608\u503C\",\n values: \"\u6D6E\u70B9\u6570\uFF08\u9ED8\u8BA4 0.85\uFF09\",\n },\n \"player-movement-distance-threshold\": {\n desc: \"\u73A9\u5BB6\u5355\u6B21\u4F4D\u79FB\u8D85\u51FA\u6B63\u5E38\u8303\u56F4\u7684\u5224\u5B9A\u9608\u503C\",\n values: \"\u6D6E\u70B9\u6570\uFF08\u9ED8\u8BA4 0.3\uFF09\",\n },\n \"player-movement-duration-threshold-in-ms\": {\n desc: \"\u79FB\u52A8\u5F02\u5E38\u5224\u5B9A\u91C7\u6837\u7684\u6ED1\u52A8\u65F6\u95F4\u7A97\u53E3\uFF08\u5355\u4F4D\uFF1A\u6BEB\u79D2\uFF09\",\n values: \"\u6574\u6570\uFF08\u9ED8\u8BA4 500\uFF09\",\n },\n \"correct-player-movement\": {\n desc: \"\u5F53\u68C0\u6D4B\u5230\u73A9\u5BB6\u79FB\u52A8\u4F5C\u5F0A\u6216\u8D85\u6807\u65F6\uFF0C\u662F\u5426\u5F3A\u5236\u5C06\u5176\u62C9\u56DE\u5408\u6CD5\u4F4D\u7F6E\uFF08\u9632\u98DE\u5929/\u52A0\u901F\uFF09\",\n values: \"true (\u5F3A\u5236\u56DE\u62C9\u7EA0\u6B63) | false (\u4EC5\u5728\u540E\u53F0\u8BB0\u5F55\u8B66\u544A)\",\n },\n \"server-authoritative-block-breaking\": {\n desc: \"\u65B9\u5757\u7834\u574F\u52A8\u4F5C\u662F\u5426\u7531\u670D\u52A1\u7AEF\u6743\u5A01\u5224\u5B9A\uFF08\u9632\u6B62\u53D8\u901F\u5237\u65B9\u5757\u7B49\u4F5C\u5F0A\u884C\u4E3A\uFF09\",\n values: \"client-auth | server-auth\",\n },\n \"chat-restriction\": {\n desc: \"\u804A\u5929\u8FC7\u6EE4\u9650\u5236\u7B56\u7565\",\n values: \"None (\u65E0\u9650\u5236) | Dropped (\u9759\u9ED8\u4E22\u5F03\u8FDD\u89C4\u5185\u5BB9) | Disabled (\u5B8C\u5168\u7981\u7528\u804A\u5929)\",\n },\n \"disable-player-interaction\": {\n desc: \"\u662F\u5426\u7981\u7528\u9759\u9ED8\u4EA4\u4E92\u68C0\u6D4B\uFF08\u7528\u4E8E\u6392\u67E5\u7F51\u7EDC\u5EF6\u8FDF\u6216\u9632\u5FEB\u901F\u4EA4\u4E92\uFF09\",\n values: \"true | false\",\n },\n \"client-side-chunk-generation-enabled\": {\n desc: \"\u662F\u5426\u5141\u8BB8\u5BA2\u6237\u7AEF\u5728\u672C\u5730\u751F\u6210\u5C1A\u672A\u52A0\u8F7D\u7684\u5730\u5F62\u533A\u5757\uFF08\u52A0\u5FEB\u957F\u8DDD\u79BB\u63A2\u7D22\u65F6\u7684\u89C6\u89C9\u52A0\u8F7D\u901F\u5EA6\uFF09\",\n values: \"true (\u5141\u8BB8\u5BA2\u6237\u7AEF\u672C\u5730\u9884\u751F\u6210) | false (\u5168\u90E8\u7531\u670D\u52A1\u7AEF\u751F\u6210\u5E76\u4F20\u8F93)\",\n },\n \"block-network-ids-are-hashes\": {\n desc: \"\u65B9\u5757\u5728\u7F51\u7EDC\u4F20\u8F93\u4E2D\u7684\u552F\u4E00\u6807\u8BC6\u662F\u5426\u91C7\u7528\u54C8\u5E0C\u503C\",\n values: \"true | false\",\n },\n \"disable-persona\": {\n desc: \"\u662F\u5426\u7981\u7528\u4E2A\u6027\u5316\u88C5\u626E/\u89D2\u8272\u521B\u5EFA\u5668\uFF08Persona \u76AE\u80A4\uFF09\",\n values: \"true (\u5F3A\u5236\u4F7F\u7528\u7ECF\u5178\u76AE\u80A4) | false (\u5141\u8BB8\u4F7F\u7528\u5B98\u65B9\u634F\u8138\u89D2\u8272)\",\n },\n \"disable-custom-skins\": {\n desc: \"\u662F\u5426\u7981\u7528\u73A9\u5BB6\u4E0A\u4F20\u7684\u81EA\u5B9A\u4E49\u7ECF\u5178\u76AE\u80A4\uFF08\u9632\u6B62\u6076\u610F\u6216\u900F\u660E\u76AE\u80A4\uFF09\",\n values: \"true (\u7981\u7528\u81EA\u5B9A\u4E49\u76AE\u80A4) | false (\u5141\u8BB8\u81EA\u5B9A\u4E49\u76AE\u80A4)\",\n },\n \"emit-server-telemetry\": {\n desc: \"\u662F\u5426\u5411 Mojang \u53D1\u9001\u670D\u52A1\u5668\u9065\u6D4B\u4E0E\u8FD0\u884C\u5065\u5EB7\u8BCA\u65AD\u6570\u636E\",\n values: \"true | false\",\n tip: \"\u4F7F\u7528\u672C\u5E73\u53F0\u65F6\u56E0\u60A8\u5DF2\u540C\u610F Mojang EULA \u534F\u8BAE\uFF0C\u6309\u534F\u8BAE\u4FDD\u6301\u542F\u7528\",\n },\n \"server-build-radius-ratio\": {\n desc: \"\u5141\u8BB8\u73A9\u5BB6\u5EFA\u9020\u548C\u4EA4\u4E92\u7684\u4E16\u754C\u533A\u57DF\u534A\u5F84\u6BD4\u4F8B\",\n values: \"Disabled (\u65E0\u9650\u5236) \u6216 0.0 ~ 1.0 \u7684\u6D6E\u70B9\u6570\",\n },\n \"allow-outbound-script-debugging\": {\n desc: \"\u662F\u5426\u5141\u8BB8\u670D\u52A1\u7AEF\u811A\u672C\u4E3B\u52A8\u8FDE\u63A5\u5916\u90E8\u8C03\u8BD5\u5668\uFF08\u5141\u8BB8 /script debugger connect \u6307\u4EE4\uFF09\",\n values: \"true | false\",\n tip: \"\u4EC5\u5728\u901A\u8FC7 VS Code \u8C03\u8BD5 SAPI \u6A21\u7EC4\u65F6\u5F00\u542F\uFF0C\u751F\u4EA7\u73AF\u5883\u5EFA\u8BAE\u5173\u95ED\",\n },\n \"allow-inbound-script-debugging\": {\n desc: \"\u662F\u5426\u5141\u8BB8\u5916\u90E8\u811A\u672C\u8C03\u8BD5\u5668\u4E3B\u52A8\u8FDE\u63A5\u670D\u52A1\u7AEF\uFF08\u5141\u8BB8 /script debugger listen \u6307\u4EE4\uFF09\",\n values: \"true | false\",\n tip: \"\u4EC5\u5728\u901A\u8FC7 VS Code \u8C03\u8BD5 SAPI \u6A21\u7EC4\u65F6\u5F00\u542F\uFF0C\u751F\u4EA7\u73AF\u5883\u5EFA\u8BAE\u5173\u95ED\",\n },\n \"force-inbound-debug-port\": {\n desc: \"\u811A\u672C\u8C03\u8BD5\u5668\u76D1\u542C\u7684\u4E13\u5C5E\u7F51\u7EDC\u7AEF\u53E3\",\n values: \"1 ~ 65535\uFF08\u9ED8\u8BA4\uFF1A19144\uFF09\",\n },\n \"script-debugger-auto-attach\": {\n desc: \"\u4E16\u754C\u52A0\u8F7D\u65F6\uFF0C\u662F\u5426\u81EA\u52A8\u8FDE\u63A5\u6216\u76D1\u542C\u5916\u90E8\u811A\u672C\u8C03\u8BD5\u5668\",\n values: \"disabled (\u4E0D\u81EA\u52A8\u9644\u52A0) | connect (\u81EA\u52A8\u5411\u5916\u8FDE\u63A5) | listen (\u81EA\u52A8\u5F00\u542F\u7AEF\u53E3\u76D1\u542C)\",\n },\n \"script-debugger-auto-attach-connect-address\": {\n desc: \"\u5F53 auto-attach \u8BBE\u4E3A connect \u65F6\uFF0C\u5C1D\u8BD5\u8FDE\u63A5\u7684\u76EE\u6807\u8C03\u8BD5\u5668\u4E3B\u673A\u4E0E\u7AEF\u53E3\",\n values: \"ip:port\uFF08\u4F8B\u5982 localhost:19144\uFF09\",\n },\n \"websocket-retry-time\": {\n desc: \"\u8FDE\u63A5\u5916\u90E8 WebSocket \u670D\u52A1\u5668\u65AD\u5F00\u540E\u7684\u81EA\u52A8\u91CD\u8BD5\u95F4\u9694\uFF08\u5355\u4F4D\uFF1A\u79D2\uFF09\",\n values: \"\u6B63\u6574\u6570\uFF08\u9ED8\u8BA4 20\uFF09\",\n },\n};\n\n/**\n * \u6839\u636E\u5C5E\u6027 key \u548C\u76EE\u6807\u8BED\u8A00\u83B7\u53D6\u8BF4\u660E\u6587\u6863\n */\nexport function getServerPropertyDoc(key: string, locale: string = \"zh-CN\"): ServerPropertyDoc | undefined {\n const normalizedKey = key.trim().toLowerCase();\n const normalizedLocale = locale.toLowerCase();\n\n if (normalizedLocale === \"zh\" || normalizedLocale.startsWith(\"zh-\")) {\n return SERVER_PROPERTIES_DOCS_ZH_CN[normalizedKey];\n }\n return undefined;\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -1,5 +1,6 @@
1
1
  export declare const EMIT_SERVER_TELEMETRY_KEY = "emit-server-telemetry";
2
2
  export declare const EMIT_SERVER_TELEMETRY_LINE = "emit-server-telemetry=true";
3
+ export declare const NETHERNET_TRANSPORT_LINE = "transport=nethernet";
3
4
  export type ServerPropertiesLogger = {
4
5
  info: (msg: string) => void;
5
6
  };
@@ -9,4 +10,28 @@ export type ServerPropertiesLogger = {
9
10
  * @returns true = 本次新追加;false = 跳过
10
11
  */
11
12
  export declare function ensureEmitServerTelemetry(bdsRoot: string, logger?: ServerPropertiesLogger): boolean;
13
+ /** 缺少传输方式时补上当前 BDS 所需的 NetherNet,保留服主已有设置。 */
14
+ export declare function ensureNetherNetTransport(bdsRoot: string, logger?: ServerPropertiesLogger): boolean;
15
+ /**
16
+ * 解析并探测当前应当采用的 BDS 本地化语言代码(例如 zh-CN 或 en)。
17
+ */
18
+ export declare function resolveBdsLocale(rootDir?: string): string;
19
+ /**
20
+ * 纯函数:将 server.properties 文本中的注释替换为目标语言的结构化中文说明。
21
+ * 严格保留配置项的 key 与当前生效的 value。若遇到未收录的键或纯注释块,原样保留。
22
+ */
23
+ export declare function localizeServerPropertiesContent(text: string, locale?: string): {
24
+ content: string;
25
+ modified: boolean;
26
+ };
27
+ export interface LocalizeServerPropertiesOptions {
28
+ locale?: string;
29
+ rootDir?: string;
30
+ logger?: ServerPropertiesLogger;
31
+ }
32
+ /**
33
+ * 对 `<bdsRoot>/server.properties` 中的注释执行本地化重写。
34
+ * @returns true = 本次成功重写并保存;false = 跳过或无改动
35
+ */
36
+ export declare function localizeServerProperties(bdsRoot: string, options?: LocalizeServerPropertiesOptions): boolean;
12
37
  //# sourceMappingURL=server-properties.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"server-properties.d.ts","sourceRoot":"","sources":["../src/server-properties.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,yBAAyB,0BAA0B,CAAC;AACjE,eAAO,MAAM,0BAA0B,+BAA+B,CAAC;AAEvE,MAAM,MAAM,sBAAsB,GAAG;IACnC,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7B,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,sBAAsB,GAC9B,OAAO,CAmBT"}
1
+ {"version":3,"file":"server-properties.d.ts","sourceRoot":"","sources":["../src/server-properties.ts"],"names":[],"mappings":"AAcA,eAAO,MAAM,yBAAyB,0BAA0B,CAAC;AACjE,eAAO,MAAM,0BAA0B,+BAA+B,CAAC;AACvE,eAAO,MAAM,wBAAwB,wBAAwB,CAAC;AAE9D,MAAM,MAAM,sBAAsB,GAAG;IACnC,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7B,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,sBAAsB,GAC9B,OAAO,CAmBT;AAED,8CAA8C;AAC9C,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,sBAAsB,GAC9B,OAAO,CAYT;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CA4BzD;AAED;;;GAGG;AACH,wBAAgB,+BAA+B,CAC7C,IAAI,EAAE,MAAM,EACZ,MAAM,GAAE,MAAgB,GACvB;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CAgGxC;AAED,MAAM,WAAW,+BAA+B;IAC9C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,sBAAsB,CAAC;CACjC;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,+BAA+B,GACxC,OAAO,CAmBT"}