@sfmc-bds/db-server 0.1.0 → 0.2.0-beta.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 (112) hide show
  1. package/README.md +1 -1
  2. package/dist/db-tables.js +16 -17
  3. package/dist/db-tables.js.map +7 -1
  4. package/dist/domain/bridge.js +54 -77
  5. package/dist/domain/bridge.js.map +7 -1
  6. package/dist/domain/economy.d.ts +83 -2
  7. package/dist/domain/economy.d.ts.map +1 -1
  8. package/dist/domain/economy.js +292 -281
  9. package/dist/domain/economy.js.map +7 -1
  10. package/dist/domain/schema.js +480 -426
  11. package/dist/domain/schema.js.map +7 -1
  12. package/dist/domain/transaction.js +32 -80
  13. package/dist/domain/transaction.js.map +7 -1
  14. package/dist/env.d.ts.map +1 -1
  15. package/dist/env.js +85 -84
  16. package/dist/env.js.map +7 -1
  17. package/dist/index.d.ts +1 -1
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +218 -240
  20. package/dist/index.js.map +7 -1
  21. package/dist/lib/http.js +30 -39
  22. package/dist/lib/http.js.map +7 -1
  23. package/dist/lib/idempotency-store.js +34 -47
  24. package/dist/lib/idempotency-store.js.map +7 -1
  25. package/dist/lib/idempotency.js +8 -13
  26. package/dist/lib/idempotency.js.map +7 -1
  27. package/dist/lib/identifiers.js +18 -14
  28. package/dist/lib/identifiers.js.map +7 -1
  29. package/dist/lib/log.d.ts +3 -6
  30. package/dist/lib/log.d.ts.map +1 -1
  31. package/dist/lib/log.js +13 -14
  32. package/dist/lib/log.js.map +7 -1
  33. package/dist/lib/module-state.d.ts.map +1 -1
  34. package/dist/lib/module-state.js +32 -21
  35. package/dist/lib/module-state.js.map +7 -1
  36. package/dist/lib/order-by.d.ts +17 -0
  37. package/dist/lib/order-by.d.ts.map +1 -0
  38. package/dist/lib/order-by.js +24 -0
  39. package/dist/lib/order-by.js.map +7 -0
  40. package/dist/lib/runtime.js +16 -31
  41. package/dist/lib/runtime.js.map +7 -1
  42. package/dist/lib/sql-helpers.js +9 -27
  43. package/dist/lib/sql-helpers.js.map +7 -1
  44. package/dist/lib/sqlite.js +40 -52
  45. package/dist/lib/sqlite.js.map +7 -1
  46. package/dist/manifest-loader.d.ts.map +1 -1
  47. package/dist/manifest-loader.js +154 -195
  48. package/dist/manifest-loader.js.map +7 -1
  49. package/dist/manifest.d.ts +3 -7
  50. package/dist/manifest.d.ts.map +1 -1
  51. package/dist/manifest.js +76 -115
  52. package/dist/manifest.js.map +7 -1
  53. package/dist/module-auth.d.ts +17 -6
  54. package/dist/module-auth.d.ts.map +1 -1
  55. package/dist/module-auth.js +93 -107
  56. package/dist/module-auth.js.map +7 -1
  57. package/dist/module-runtime-sync.d.ts +37 -0
  58. package/dist/module-runtime-sync.d.ts.map +1 -0
  59. package/dist/module-runtime-sync.js +54 -0
  60. package/dist/module-runtime-sync.js.map +7 -0
  61. package/dist/permission-gate.d.ts.map +1 -1
  62. package/dist/permission-gate.js +55 -86
  63. package/dist/permission-gate.js.map +7 -1
  64. package/dist/routes/_shared.d.ts +7 -2
  65. package/dist/routes/_shared.d.ts.map +1 -1
  66. package/dist/routes/_shared.js +16 -25
  67. package/dist/routes/_shared.js.map +7 -1
  68. package/dist/routes/config.d.ts +11 -1
  69. package/dist/routes/config.d.ts.map +1 -1
  70. package/dist/routes/config.js +167 -213
  71. package/dist/routes/config.js.map +7 -1
  72. package/dist/routes/db-routes.d.ts +6 -10
  73. package/dist/routes/db-routes.d.ts.map +1 -1
  74. package/dist/routes/db-routes.js +198 -172
  75. package/dist/routes/db-routes.js.map +7 -1
  76. package/dist/routes/health.js +15 -20
  77. package/dist/routes/health.js.map +7 -1
  78. package/dist/routes/messages.d.ts.map +1 -1
  79. package/dist/routes/messages.js +56 -63
  80. package/dist/routes/messages.js.map +7 -1
  81. package/dist/routes/module-config-routes.d.ts.map +1 -1
  82. package/dist/routes/module-config-routes.js +92 -111
  83. package/dist/routes/module-config-routes.js.map +7 -1
  84. package/dist/routes/modules.d.ts.map +1 -1
  85. package/dist/routes/modules.js +82 -88
  86. package/dist/routes/modules.js.map +7 -1
  87. package/dist/routes/service-routes.d.ts.map +1 -1
  88. package/dist/routes/service-routes.js +54 -61
  89. package/dist/routes/service-routes.js.map +7 -1
  90. package/dist/runtime.test.js +248 -49
  91. package/dist/runtime.test.js.map +7 -1
  92. package/dist/schema-registry.d.ts.map +1 -1
  93. package/dist/schema-registry.js +119 -160
  94. package/dist/schema-registry.js.map +7 -1
  95. package/dist/server.js +69 -72
  96. package/dist/server.js.map +7 -1
  97. package/dist/service-registry.d.ts.map +1 -1
  98. package/dist/service-registry.js +60 -67
  99. package/dist/service-registry.js.map +7 -1
  100. package/dist/services/builtin-handlers.d.ts +4 -0
  101. package/dist/services/builtin-handlers.d.ts.map +1 -1
  102. package/dist/services/builtin-handlers.js +34 -20
  103. package/dist/services/builtin-handlers.js.map +7 -1
  104. package/dist/services/economy-handlers.js +143 -132
  105. package/dist/services/economy-handlers.js.map +7 -1
  106. package/dist/tx-runner.d.ts +35 -11
  107. package/dist/tx-runner.d.ts.map +1 -1
  108. package/dist/tx-runner.js +293 -250
  109. package/dist/tx-runner.js.map +7 -1
  110. package/dist/where.js +71 -94
  111. package/dist/where.js.map +7 -1
  112. package/package.json +4 -4
@@ -1 +1,7 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/domain/schema.ts"],"names":[],"mappings":"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"}
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/domain/schema.ts"],
4
+ "sourcesContent": ["/**\n * domain/schema.ts \u2014 \u6570\u636E\u5E93 schema \u521D\u59CB\u5316(\u552F\u4E00\u771F\u6E90)\n *\n * \u6240\u6709 CREATE TABLE / CREATE INDEX \u8BED\u53E5\u96C6\u4E2D\u4E8E\u6B64\u3002\n * \u8C03\u7528\u65B9\u5F0F:initSchema(db) \u2014 \u5728 openDatabase \u4E4B\u540E\u3001createQuery \u4E4B\u524D\u6267\u884C\u3002\n *\n * \u4E8B\u52A1\u63CF\u8FF0:\n * - \u65E0\u4E1A\u52A1 Tx(\u672C\u6587\u4EF6\u53EA\u505A DDL,\u4E0D\u6D89\u53CA\u4E1A\u52A1\u4E8B\u52A1)\n *\n * \u4E1A\u52A1\u57DF(\u6309\u6587\u4EF6\u5185 db.exec \u5757\u7F16\u53F7):\n * (1) \u4E16\u754C\u5907\u4EFD (2) \u73A9\u5BB6\u5907\u4EFD (3) \u8BA1\u5206\u677F\n * (4) \u73A9\u5BB6\u884C\u4E3A\u65E5\u5FD7 (5) \u804A\u5929\u9891\u9053 (6) \u804A\u5929\u6D88\u606F\n * (7) \u7EA2\u5305 (8) \u5408\u4F5C\u793E\u4E3B\u4F53/\u6210\u5458/\u9080\u8BF7/\u8D26\u6237\n * (9) \u5408\u4F5C\u793E\u5546\u5E97\u9879/\u5546\u5E97\u7EC4 (10) \u5408\u4F5C\u793E\u8D26\u53D8\u6D41\u6C34/\u5BA1\u8BA1\n * (11) \u9886\u5730\u4E3B\u4F53/\u6210\u5458/\u6743\u9650 (12) \u9886\u5730\u9080\u8BF7/\u5BA1\u8BA1/\u8BF7\u6C42\u5E42\u7B49\n * (13) \u73A9\u5BB6\u6307\u4EE4\u7528\u91CF (14) \u4EF7\u683C\u6307\u6570\n * (15) \u6BCF\u65E5\u4EFB\u52A1/\u7EDF\u8BA1 (16) \u7ECF\u6D4E\u8D26\u6237/\u6D41\u6C34/\u5E42\u7B49\n *\n * \u5B8C\u6574\u8868\u540D\u4EE5 `sfmc_` \u524D\u7F00,\u5177\u4F53\u89C1\u4E0B\u65B9\u6BCF\u4E2A db.exec \u5757\u3002\n *\n * \u5907\u6CE8: ALTER / DROP \u4E0D\u5728\u6B64\u5904;\u5982\u9700\u8FC1\u79FB\u8BF7\u65B0\u5EFA tools/migrate-*.ts,\n * \u4FDD\u6301\u672C\u6587\u4EF6\u53EA\u505A\"\u5168\u65B0\u521D\u59CB\u5316\"\u3002\n */\n\nimport type { DatabaseSync } from \"node:sqlite\";\n\nexport function initSchema(db: DatabaseSync): void {\n // (1 \u4E16\u754C\u5907\u4EFD\u6570\u636E\n db.exec(/* sql */ `\n CREATE TABLE IF NOT EXISTS sfmc_world (\n allow_cheats INTEGER NOT NULL DEFAULT 0, -- \u5141\u8BB8\u4F5C\u5F0A\u7684\u9009\u9879\n game_rules TEXT NOT NULL DEFAULT '', -- \u4E16\u754C\u89C4\u5219(json)\n seed TEXT DEFAULT '', -- \u79CD\u5B50\n default_spawn_location TEXT NOT NULL DEFAULT '', -- \u9ED8\u8BA4\u51FA\u751F\u70B9\n difficulty TEXT NOT NULL DEFAULT '', -- \u96BE\u5EA6\n day INTEGER NOT NULL DEFAULT 0, -- \u6E38\u620F\u5929\u6570\uFF08\u4E16\u754C\uFF09\n ticking_areas_count INTEGER DEFAULT 0, -- \u5E38\u52A0\u8F7D\u533A\u57DF\u6570\u91CF\n absolute_time INTEGER NOT NULL DEFAULT 0, -- \u6E38\u620F\u5185\u65F6\u95F4\uFF08\u5F53\u524D\uFF09\n structures_from_addon TEXT DEFAULT '', -- \u6765\u81EA\u6A21\u7EC4\u7684\u7ED3\u6784\uFF08\u5728\u5BF9\u5E94\u884C\u4E3A\u5305\u5185\uFF09\n structures_from_world TEXT DEFAULT '', -- \u6765\u81EA\u4E16\u754C\u7684\u7ED3\u6784 \u5305\u542B\u4FDD\u5B58\u5728\u5185\u5B58\u4E0E\u78C1\u76D8\u4E2D\u7684\n dynamic_property_total_byte_count INTEGER DEFAULT 0, -- \u52A8\u6001\u6570\u636E\uFF08\u4E16\u754C\uFF09\u5B57\u8282\u6570\n moon_phase INTEGER NOT NULL DEFAULT 0, -- \u6708\u76F8\uFF08\u5F53\u524D\uFF09\n updated_at TEXT NOT NULL DEFAULT '' -- \u66F4\u65B0\u65F6\u95F4\u6233\n )`);\n\n // (2 \u73A9\u5BB6\u5907\u4EFD\u6570\u636E\n db.exec(/* sql */ `\n CREATE TABLE IF NOT EXISTS sfmc_players (\n id TEXT NOT NULL, -- \u5B9E\u4F53id\u6807\u8BC6\u7B26\n name TEXT NOT NULL, -- \u540D\u79F0\n permission INTEGER DEFAULT 0, -- \u6743\u9650\u7B49\u7EA7\uFF080=\u8BBF\u5BA2,1=\u6210\u5458,2=OP,3=\u7BA1\u7406\u5458\uFF09TODO: \u6682\u672A\u9002\u914D\u81EA\u5B9A\u4E49\u811A\u672C\u6743\u9650\n client_system_info_local TEXT DEFAULT '', -- \u5BA2\u6237\u7AEF\u7CFB\u7EDF\u4FE1\u606F->\u672C\u5730\u5316\u8BED\u8A00\n client_system_info_maxRenderDistance INTEGER DEFAULT 0, -- \u5BA2\u6237\u7AEF\u7CFB\u7EDF\u4FE1\u606F->\u6700\u5927\u6E32\u67D3\u8DDD\u79BB\n client_system_info_memoryTier_level TEXT DEFAULT '', -- \u5BA2\u6237\u7AEF\u4FE1\u606F->\u5185\u5B58\u7B49\u7EA7 \u8BE6\u7EC6\u8BF7\u67E5\u770B\u5B98\u65B9\u6587\u6863\n client_system_info_PlatformType TEXT DEFAULT '', -- \u5BA2\u6237\u7AEF\u7CFB\u7EDF\u4FE1\u606F->\u5E73\u53F0\u7C7B\u578B\n graphicsMode TEXT DEFAULT '', -- \u56FE\u5F62\u6A21\u5F0F\n dynamicPropertyTotalByteCount INTEGER DEFAULT 0, -- \u52A8\u6001\u5C5E\u6027\u603B\u5B57\u8282\u6570\n ping INTEGER DEFAULT 0, -- \u5EF6\u8FDF\uFF08ms\uFF09\n spawnPoint TEXT DEFAULT '', -- \u51FA\u751F\u70B9\u5750\u6807\n tags TEXT DEFAULT '', -- \u73A9\u5BB6\u6807\u7B7E\n level INTEGER DEFAULT 0, -- \u7B49\u7EA7\n totalXp INTEGER DEFAULT 0, -- \u603B\u7ECF\u9A8C\u503C\n afk_step INTEGER DEFAULT 0, -- AFK\u7D2F\u8BA1\u6B65\u6570\n afk_last_location TEXT DEFAULT '', -- AFK\u6700\u540E\u4F4D\u7F6E\n onlinetime_session INTEGER DEFAULT 0, -- \u5728\u7EBF\u65F6\u95F4->\u672C\u6B21\u4F1A\u8BDD\uFF08\u79D2\uFF09\n onlinetime_today INTEGER DEFAULT 0, -- \u5728\u7EBF\u65F6\u95F4->\u4ECA\u65E5\uFF08\u79D2\uFF09\n onlinetime_month INTEGER DEFAULT 0, -- \u5728\u7EBF\u65F6\u95F4->\u672C\u6708\uFF08\u79D2\uFF09\n onlinetime_total INTEGER DEFAULT 0, -- \u5728\u7EBF\u65F6\u95F4->\u7D2F\u8BA1\uFF08\u79D2\uFF09\n onlinetime_last_date INTEGER DEFAULT 0, -- \u5728\u7EBF\u65F6\u95F4->\u4E0A\u6B21\u8BB0\u5F55\u65E5\u671F\n onlinetime_last_month INTEGER DEFAULT 0, -- \u5728\u7EBF\u65F6\u95F4->\u4E0A\u6B21\u8BB0\u5F55\u6708\u4EFD\n active_channel TEXT NOT NULL DEFAULT '', -- \u5F53\u524D\u6D3B\u8DC3\u804A\u5929\u9891\u9053\n subscribed_channels TEXT DEFAULT '', -- \u8BA2\u9605\u7684\u9891\u9053\u5217\u8868\n updated_at INTEGER NOT NULL, -- \u73A9\u5BB6\u6570\u636E\u66F4\u65B0\u65F6\u95F4\u6233\n PRIMARY KEY (id, name) -- \u8054\u5408\u4E3B\u952E\uFF1A\u5B9E\u4F53id+\u540D\u79F0\n )`);\n // \u73A9\u5BB6\u8868\u7D22\u5F15\uFF1A\u6309id\u67E5\u3001\u6309name\u67E5\n db.exec(/* sql */ `\n CREATE INDEX IF NOT EXISTS idx_players_id ON sfmc_players(id);\n CREATE INDEX IF NOT EXISTS idx_players_name ON sfmc_players(name)`);\n\n // (3 \u8BA1\u5206\u677F\u6570\u636E\n db.exec(/* sql */ `\n CREATE TABLE IF NOT EXISTS sfmc_scoreboards (\n objective_id TEXT NOT NULL, -- \u8BA1\u5206\u677F\u76EE\u6807id\uFF08\u4E3B\u952E\uFF09\n objective_display TEXT NOT NULL DEFAULT '', -- \u8BA1\u5206\u677F\u663E\u793A\u540D\u79F0\n participants TEXT DEFAULT '', -- \u53C2\u4E0E\u8005\u5217\u8868\uFF08json\uFF09\n updated_at INTEGER NOT NULL, -- \u66F4\u65B0\u65F6\u95F4\u6233\n PRIMARY KEY (objective_id) -- \u4E3B\u952E\n )`);\n\n // (4 \u73A9\u5BB6\u884C\u4E3A\u65E5\u5FD7\n db.exec(/* sql */ `\n CREATE TABLE IF NOT EXISTS sfmc_activities (\n id TEXT PRIMARY KEY, -- \u552F\u4E00id\n timestamp INTEGER NOT NULL, -- \u4E8B\u4EF6\u53D1\u751F\u65F6\u95F4\u6233\n dimension TEXT NOT NULL DEFAULT '', -- \u7EF4\u5EA6\uFF08overworld/nether/end\uFF09\n source_type TEXT NOT NULL, -- \u4E8B\u4EF6\u6E90\u7C7B\u578B\uFF08\u5982player\u3001entity\u3001block\u7B49\uFF09\n source_id TEXT DEFAULT '', -- \u4E8B\u4EF6\u6E90\u5B9E\u4F53/\u65B9\u5757id\n source_name TEXT NOT NULL DEFAULT '', -- \u4E8B\u4EF6\u6E90\u540D\u79F0\n source_x REAL, -- \u4E8B\u4EF6\u6E90x\u5750\u6807\n source_y REAL, -- \u4E8B\u4EF6\u6E90y\u5750\u6807\n source_z REAL, -- \u4E8B\u4EF6\u6E90z\u5750\u6807\n event_type TEXT NOT NULL, -- \u4E8B\u4EF6\u7C7B\u578B\uFF08\u5982chat\u3001command\u3001death\u3001join\u7B49\uFF09\n target_type TEXT DEFAULT '', -- \u76EE\u6807\u7C7B\u578B\n target_id TEXT DEFAULT '', -- \u76EE\u6807\u5B9E\u4F53id\n target_name TEXT NOT NULL DEFAULT '', -- \u76EE\u6807\u540D\u79F0\n target_x REAL, -- \u76EE\u6807x\u5750\u6807\n target_y REAL, -- \u76EE\u6807y\u5750\u6807\n target_z REAL, -- \u76EE\u6807z\u5750\u6807\n detail TEXT DEFAULT '{}', -- \u4E8B\u4EF6\u8BE6\u7EC6\u4FE1\u606F\uFF08json\uFF09\n created_at INTEGER NOT NULL -- \u8BB0\u5F55\u521B\u5EFA\u65F6\u95F4\u6233\n )`);\n // \u6D3B\u52A8\u8868\u7D22\u5F15\uFF1A\u6309\u6E90id\u67E5\u3001\u6309\u4E8B\u4EF6\u7C7B\u578B\u67E5\u3001\u6309\u76EE\u6807id\u67E5\n db.exec(/* sql */ `\n CREATE INDEX IF NOT EXISTS idx_sfmc_act_source ON sfmc_activities(source_id, timestamp);\n CREATE INDEX IF NOT EXISTS idx_sfmc_act_event ON sfmc_activities(event_type, timestamp);\n CREATE INDEX IF NOT EXISTS idx_sfmc_act_target ON sfmc_activities(target_id, timestamp)`);\n\n // (5 \u804A\u5929\u9891\u9053\u914D\u7F6E\n db.exec(/* sql */ `\n CREATE TABLE IF NOT EXISTS sfmc_chat_channels (\n id TEXT NOT NULL, -- \u9891\u9053\u552F\u4E00id\n name TEXT NOT NULL, -- \u9891\u9053\u540D\u79F0\n type TEXT NOT NULL, -- \u9891\u9053\u7C7B\u578B\n prefix TEXT NOT NULL, -- \u9891\u9053\u524D\u7F00\u7B26\u53F7\n owner_id TEXT DEFAULT '', -- \u9891\u9053\u6240\u6709\u8005\u73A9\u5BB6id\n created_at INTEGER NOT NULL, -- \u9891\u9053\u521B\u5EFA\u65F6\u95F4\u6233\n config_allow_chat INTEGER NOT NULL DEFAULT 1, -- \u914D\u7F6E->\u662F\u5426\u5141\u8BB8\u804A\u5929\n config_slow_mode INTEGER NOT NULL DEFAULT 0, -- \u914D\u7F6E->\u6162\u6A21\u5F0F\u95F4\u9694\uFF08\u79D2\uFF09\n config_is_broadcast INTEGER NOT NULL DEFAULT 0, -- \u914D\u7F6E->\u662F\u5426\u4E3A\u5E7F\u64AD\u9891\u9053\n updated_at INTEGER NOT NULL, -- \u9891\u9053\u914D\u7F6E\u66F4\u65B0\u65F6\u95F4\u6233\n PRIMARY KEY (id, name) -- \u8054\u5408\u4E3B\u952E\n )`);\n // \u9891\u9053\u8868\u7D22\u5F15\uFF1A\u6309id\u67E5\u3001\u6309name+\u521B\u5EFA\u65F6\u95F4\u67E5\n db.exec(/* sql */ `\n CREATE INDEX IF NOT EXISTS idx_channels_id ON sfmc_chat_channels(id);\n CREATE INDEX IF NOT EXISTS idx_channels_name ON sfmc_chat_channels(name, created_at ASC)`);\n\n // (6 \u804A\u5929\u6D88\u606F\u8BB0\u5F55\n db.exec(/* sql */ `\n CREATE TABLE IF NOT EXISTS sfmc_chat_messages (\n id TEXT PRIMARY KEY, -- \u6D88\u606F\u552F\u4E00id\n channel_id TEXT NOT NULL, -- \u6240\u5C5E\u9891\u9053id\n from_id TEXT NOT NULL, -- \u53D1\u9001\u8005\u73A9\u5BB6id\n from_name TEXT NOT NULL, -- \u53D1\u9001\u8005\u540D\u79F0\n type TEXT NOT NULL DEFAULT 'text', -- \u6D88\u606F\u7C7B\u578B\n content TEXT NOT NULL, -- \u6D88\u606F\u5185\u5BB9\n attachment TEXT, -- \u9644\u4EF6\u4FE1\u606F\n show_timestamp INTEGER NOT NULL DEFAULT 0, -- \u662F\u5426\u5728\u6D88\u606F\u5217\u8868\u663E\u793A\u65F6\u95F4\u6233\n created_at INTEGER NOT NULL -- \u6D88\u606F\u53D1\u9001\u65F6\u95F4\u6233\n )`);\n // \u6D88\u606F\u8868\u7D22\u5F15\uFF1A\u6309\u9891\u9053+\u65F6\u95F4\u67E5\n db.exec(/* sql */ `\n CREATE INDEX IF NOT EXISTS idx_messages_channel ON sfmc_chat_messages(channel_id, created_at ASC)`);\n\n // (7 \u804A\u5929\u7EA2\u5305\u8BB0\u5F55\n db.exec(/* sql */ `\n CREATE TABLE IF NOT EXISTS sfmc_chat_redpackets (\n id TEXT PRIMARY KEY, -- \u7EA2\u5305\u552F\u4E00id\n sender_id TEXT NOT NULL, -- \u53D1\u7EA2\u5305\u73A9\u5BB6id\n sender_name TEXT NOT NULL, -- \u53D1\u7EA2\u5305\u73A9\u5BB6\u540D\u79F0\n total_amount REAL NOT NULL, -- \u7EA2\u5305\u603B\u91D1\u989D\n remaining_amount REAL NOT NULL, -- \u5269\u4F59\u91D1\u989D\n total_count INTEGER NOT NULL, -- \u7EA2\u5305\u603B\u4E2A\u6570\n remaining_count INTEGER NOT NULL, -- \u5269\u4F59\u4E2A\u6570\n receivers TEXT NOT NULL DEFAULT '[]', -- \u5DF2\u9886\u53D6\u73A9\u5BB6\u5217\u8868\uFF08json\uFF09\n target_type TEXT NOT NULL, -- \u7EA2\u5305\u76EE\u6807\u7C7B\u578B\uFF08all/channel/player\u7B49\uFF09\n target_id TEXT NOT NULL, -- \u7EA2\u5305\u76EE\u6807id\n created_at INTEGER NOT NULL, -- \u7EA2\u5305\u521B\u5EFA\u65F6\u95F4\u6233\n expires_at INTEGER NOT NULL -- \u7EA2\u5305\u8FC7\u671F\u65F6\u95F4\u6233\n )`);\n // \u7EA2\u5305\u8868\u7D22\u5F15\uFF1A\u6309id\u67E5\n db.exec(/* sql */ `\n CREATE INDEX IF NOT EXISTS idx_redpackets_id ON sfmc_chat_redpackets(id)`);\n\n // (8 \u5408\u4F5C\u793E\u6838\u5FC3\u8868\n db.exec(/* sql */ `\n CREATE TABLE IF NOT EXISTS sfmc_coops (\n cid TEXT PRIMARY KEY, -- \u5408\u4F5C\u793E\u552F\u4E00id\n name TEXT NOT NULL, -- \u5408\u4F5C\u793E\u540D\u79F0\n owner_player_id TEXT NOT NULL, -- \u793E\u957F\u73A9\u5BB6id\n owner_name_snapshot TEXT NOT NULL DEFAULT '', -- \u793E\u957F\u540D\u79F0\u5FEB\u7167\n status TEXT NOT NULL DEFAULT 'active', -- \u72B6\u6001\uFF08active/inactive/dissolved\uFF09\n notice TEXT DEFAULT '', -- \u5408\u4F5C\u793E\u516C\u544A\n created_at INTEGER NOT NULL, -- \u521B\u5EFA\u65F6\u95F4\u6233\n updated_at INTEGER NOT NULL, -- \u66F4\u65B0\u65F6\u95F4\u6233\n fee_bps INTEGER NOT NULL DEFAULT 500, -- \u7A0E\u7387\uFF08\u57FA\u70B9\uFF0C500=5%\uFF09\n version INTEGER NOT NULL DEFAULT 1 -- \u4E50\u89C2\u9501\u7248\u672C\u53F7\n )`);\n // \u5408\u4F5C\u793E\u6210\u5458\u8868\n db.exec(/* sql */ `\n CREATE TABLE IF NOT EXISTS sfmc_coop_members (\n cid TEXT NOT NULL, -- \u5408\u4F5C\u793Eid\n player_id TEXT NOT NULL, -- \u6210\u5458\u73A9\u5BB6id\n player_name_snapshot TEXT NOT NULL DEFAULT '', -- \u6210\u5458\u540D\u79F0\u5FEB\u7167\n role TEXT NOT NULL DEFAULT 'member', -- \u89D2\u8272\uFF08member/admin/owner\uFF09\n joined_at INTEGER NOT NULL, -- \u52A0\u5165\u65F6\u95F4\u6233\n expires_at INTEGER, -- \u6210\u5458\u8D44\u683C\u8FC7\u671F\u65F6\u95F4\u6233\uFF08null=\u6C38\u4E0D\u8FC7\u671F\uFF09\n status TEXT NOT NULL DEFAULT 'active', -- \u72B6\u6001\uFF08active/expired/kicked\uFF09\n version INTEGER NOT NULL DEFAULT 1, -- \u4E50\u89C2\u9501\u7248\u672C\u53F7\n PRIMARY KEY (cid, player_id), -- \u8054\u5408\u4E3B\u952E\n FOREIGN KEY (cid) REFERENCES sfmc_coops(cid) ON DELETE CASCADE -- \u7EA7\u8054\u5220\u9664\n )`);\n // \u786E\u4FDD\u6BCF\u4E2A\u73A9\u5BB6\u53EA\u6709\u4E00\u4E2Aactive\u5408\u4F5C\u793E\u6210\u5458\u8BB0\u5F55\n db.exec(/* sql */ `\n CREATE UNIQUE INDEX IF NOT EXISTS idx_sfmc_one_active_coop_member ON sfmc_coop_members(player_id) WHERE status='active'`);\n // \u5408\u4F5C\u793E\u9080\u8BF7\u8868\n db.exec(/* sql */ `\n CREATE TABLE IF NOT EXISTS sfmc_coop_invites (\n id TEXT PRIMARY KEY, -- \u9080\u8BF7\u552F\u4E00id\n cid TEXT NOT NULL, -- \u5408\u4F5C\u793Eid\n inviter_id TEXT NOT NULL, -- \u9080\u8BF7\u4EBA\u73A9\u5BB6id\n invitee_id TEXT NOT NULL, -- \u88AB\u9080\u8BF7\u4EBA\u73A9\u5BB6id\n invitee_name_snapshot TEXT NOT NULL DEFAULT '', -- \u88AB\u9080\u8BF7\u4EBA\u540D\u79F0\u5FEB\u7167\n role TEXT NOT NULL DEFAULT 'member', -- \u9080\u8BF7\u89D2\u8272\n status TEXT NOT NULL DEFAULT 'pending', -- \u72B6\u6001\uFF08pending/accepted/rejected/expired\uFF09\n expires_at INTEGER NOT NULL, -- \u9080\u8BF7\u8FC7\u671F\u65F6\u95F4\u6233\n created_at INTEGER NOT NULL, -- \u521B\u5EFA\u65F6\u95F4\u6233\n FOREIGN KEY (cid) REFERENCES sfmc_coops(cid) ON DELETE CASCADE -- \u7EA7\u8054\u5220\u9664\n )`);\n // \u9080\u8BF7\u8868\u7D22\u5F15\uFF1A\u6309\u88AB\u9080\u8BF7\u4EBA+\u72B6\u6001+\u8FC7\u671F\u65F6\u95F4\u67E5\n db.exec(/* sql */ `\n CREATE INDEX IF NOT EXISTS idx_sfmc_coop_invites_target ON sfmc_coop_invites(invitee_id,status,expires_at)`);\n // \u5408\u4F5C\u793E\u8D26\u6237\u8868\uFF08\u7ECF\u6D4E\u7CFB\u7EDF\uFF09\n db.exec(/* sql */ `\n CREATE TABLE IF NOT EXISTS sfmc_coop_accounts (\n cid TEXT PRIMARY KEY, -- \u5408\u4F5C\u793Eid\n balance INTEGER NOT NULL DEFAULT 0, -- \u8D26\u6237\u4F59\u989D\n version INTEGER NOT NULL DEFAULT 1, -- \u4E50\u89C2\u9501\u7248\u672C\u53F7\n updated_at INTEGER NOT NULL, -- \u8D26\u6237\u66F4\u65B0\u65F6\u95F4\u6233\n FOREIGN KEY (cid) REFERENCES sfmc_coops(cid) ON DELETE CASCADE -- \u7EA7\u8054\u5220\u9664\n )`);\n // \u5408\u4F5C\u793E\u5546\u5E97\u7269\u54C1\u8868\n db.exec(/* sql */ `\n CREATE TABLE IF NOT EXISTS sfmc_coop_shop_items (\n id TEXT PRIMARY KEY, -- \u7269\u54C1\u552F\u4E00id\n cid TEXT NOT NULL, -- \u6240\u5C5E\u5408\u4F5C\u793Eid\n name TEXT NOT NULL, -- \u7269\u54C1\u540D\u79F0\n item_type TEXT NOT NULL, -- \u7269\u54C1\u7C7B\u578B\u6807\u8BC6\u7B26\uFF08\u5982minecraft:diamond\uFF09\n item_aux INTEGER DEFAULT 0, -- \u7269\u54C1\u9644\u52A0\u503C/\u6570\u636E\u503C\n item_nbt TEXT DEFAULT '', -- \u7269\u54C1NBT\u6570\u636E\n type INTEGER NOT NULL, -- \u7269\u54C1\u4EA4\u6613\u7C7B\u578B\uFF080=\u6536\u8D2D,1=\u51FA\u552E,2=\u4EA4\u6362\uFF09\n groups TEXT DEFAULT '[]', -- \u6240\u5C5E\u5546\u54C1\u5206\u7EC4\n des TEXT DEFAULT '', -- \u7269\u54C1\u63CF\u8FF0\n num INTEGER DEFAULT 0, -- \u5F53\u524D\u5E93\u5B58\u6570\u91CF\n sv INTEGER DEFAULT 0, -- \u9500\u552E/\u6536\u8D2D\u9650\u5236\n money INTEGER DEFAULT 0, -- \u5355\u4EF7\n is_true INTEGER DEFAULT 1, -- \u662F\u5426\u4E0A\u67B6\uFF081=\u4E0A\u67B6,0=\u4E0B\u67B6\uFF09\n created_at INTEGER NOT NULL, -- \u521B\u5EFA\u65F6\u95F4\u6233\n updated_at INTEGER NOT NULL, -- \u66F4\u65B0\u65F6\u95F4\u6233\n FOREIGN KEY (cid) REFERENCES sfmc_coops(cid) ON DELETE CASCADE -- \u7EA7\u8054\u5220\u9664\n )`);\n // \u5408\u4F5C\u793E\u94F6\u884C\u6D41\u6C34\u8868\n db.exec(/* sql */ `\n CREATE TABLE IF NOT EXISTS sfmc_coop_bank_log (\n id INTEGER PRIMARY KEY AUTOINCREMENT, -- \u6D41\u6C34id\uFF08\u81EA\u589E\uFF09\n cid TEXT NOT NULL, -- \u5408\u4F5C\u793Eid\n actor_id TEXT NOT NULL, -- \u64CD\u4F5C\u4EBA\u73A9\u5BB6id\n actor_name_snapshot TEXT NOT NULL DEFAULT '', -- \u64CD\u4F5C\u4EBA\u540D\u79F0\u5FEB\u7167\n type INTEGER NOT NULL, -- \u6D41\u6C34\u7C7B\u578B\uFF080=\u5B58\u5165,1=\u53D6\u51FA,2=\u4EA4\u6613\u6536\u5165,3=\u4EA4\u6613\u652F\u51FA\uFF09\n amount INTEGER NOT NULL, -- \u53D8\u52A8\u91D1\u989D\n note TEXT DEFAULT '', -- \u5907\u6CE8\n transaction_id TEXT NOT NULL DEFAULT '', -- \u5173\u8054\u4E8B\u52A1id\n created_at INTEGER NOT NULL, -- \u521B\u5EFA\u65F6\u95F4\u6233\n FOREIGN KEY (cid) REFERENCES sfmc_coops(cid) ON DELETE CASCADE -- \u7EA7\u8054\u5220\u9664\n )`);\n // \u5408\u4F5C\u793E\u5BA1\u8BA1\u65E5\u5FD7\u8868\n db.exec(/* sql */ `\n CREATE TABLE IF NOT EXISTS sfmc_coop_audit_logs (\n id INTEGER PRIMARY KEY AUTOINCREMENT, -- \u65E5\u5FD7id\uFF08\u81EA\u589E\uFF09\n cid TEXT NOT NULL, -- \u5408\u4F5C\u793Eid\n actor_id TEXT NOT NULL, -- \u64CD\u4F5C\u8005id\n target_id TEXT NOT NULL DEFAULT '', -- \u88AB\u64CD\u4F5C\u76EE\u6807id\n action TEXT NOT NULL, -- \u64CD\u4F5C\u7C7B\u578B\uFF08\u5982create/update/delete/transfer\u7B49\uFF09\n before_state TEXT NOT NULL DEFAULT '{}', -- \u64CD\u4F5C\u524D\u72B6\u6001\uFF08json\uFF09\n after_state TEXT NOT NULL DEFAULT '{}', -- \u64CD\u4F5C\u540E\u72B6\u6001\uFF08json\uFF09\n transaction_id TEXT NOT NULL DEFAULT '', -- \u5173\u8054\u4E8B\u52A1id\n created_at INTEGER NOT NULL, -- \u65E5\u5FD7\u521B\u5EFA\u65F6\u95F4\u6233\n FOREIGN KEY (cid) REFERENCES sfmc_coops(cid) ON DELETE CASCADE -- \u7EA7\u8054\u5220\u9664\n )`);\n // \u5408\u4F5C\u793E\u5546\u5E97\u5206\u7EC4\u8868\n db.exec(/* sql */ `\n CREATE TABLE IF NOT EXISTS sfmc_coop_shop_groups (\n groupid TEXT PRIMARY KEY, -- \u5206\u7EC4\u552F\u4E00id\n displayname TEXT NOT NULL, -- \u5206\u7EC4\u663E\u793A\u540D\u79F0\n displaydescribe TEXT DEFAULT '', -- \u5206\u7EC4\u63CF\u8FF0\n icon TEXT DEFAULT '', -- \u5206\u7EC4\u56FE\u6807\n type_function TEXT DEFAULT '' -- \u5206\u7EC4\u529F\u80FD\u7C7B\u578B\n )`);\n\n // (9 \u9886\u5730\uFF08 LAND \uFF09\u6838\u5FC3\u8868\n db.exec(/* sql */ `\n CREATE TABLE IF NOT EXISTS sfmc_lands (\n id TEXT PRIMARY KEY, -- \u9886\u5730\u552F\u4E00id\n owner_player_id TEXT NOT NULL, -- \u9886\u5730\u6240\u6709\u8005\u73A9\u5BB6id\n owner_name_snapshot TEXT NOT NULL DEFAULT '', -- \u6240\u6709\u8005\u540D\u79F0\u5FEB\u7167\n dimension INTEGER NOT NULL, -- \u6240\u5728\u7EF4\u5EA6\uFF080=\u4E3B\u4E16\u754C,1=\u4E0B\u754C,2=\u672B\u5730\uFF09\n min_x INTEGER NOT NULL, -- \u9886\u5730\u8303\u56F4\u6700\u5C0Fx\u5750\u6807\n min_y INTEGER NOT NULL, -- \u9886\u5730\u8303\u56F4\u6700\u5C0Fy\u5750\u6807\n min_z INTEGER NOT NULL, -- \u9886\u5730\u8303\u56F4\u6700\u5C0Fz\u5750\u6807\n max_x INTEGER NOT NULL, -- \u9886\u5730\u8303\u56F4\u6700\u5927x\u5750\u6807\n max_y INTEGER NOT NULL, -- \u9886\u5730\u8303\u56F4\u6700\u5927y\u5750\u6807\n max_z INTEGER NOT NULL, -- \u9886\u5730\u8303\u56F4\u6700\u5927z\u5750\u6807\n name TEXT NOT NULL DEFAULT '', -- \u9886\u5730\u540D\u79F0\n status TEXT NOT NULL DEFAULT 'active', -- \u9886\u5730\u72B6\u6001\uFF08active/locked/expired/auction\uFF09\n created_at INTEGER NOT NULL, -- \u9886\u5730\u521B\u5EFA\u65F6\u95F4\u6233\n updated_at INTEGER NOT NULL, -- \u9886\u5730\u66F4\u65B0\u65F6\u95F4\u6233\n expires_at INTEGER, -- \u9886\u5730\u8FC7\u671F\u65F6\u95F4\u6233\uFF08null=\u6C38\u4E0D\u8FC7\u671F\uFF09\n protection_profile TEXT NOT NULL DEFAULT '{}', -- \u4FDD\u62A4\u914D\u7F6E\uFF08json\uFF09\n version INTEGER NOT NULL DEFAULT 1, -- \u4E50\u89C2\u9501\u7248\u672C\u53F7\n purchase_price INTEGER NOT NULL DEFAULT 0, -- \u8D2D\u4E70\u4EF7\u683C\n refund_rate REAL NOT NULL DEFAULT 0.7, -- \u9000\u6B3E\u6BD4\u4F8B\uFF080~1\uFF09\n tax_rate INTEGER NOT NULL DEFAULT 0, -- \u7A0E\u7387\uFF08\u767E\u5206\u6BD4\uFF09\n tax_due_at INTEGER, -- \u4E0B\u4E00\u4E2A\u7F34\u7A0E\u65F6\u95F4\u6233\n tax_frozen INTEGER NOT NULL DEFAULT 0 -- \u7A0E\u52A1\u51BB\u7ED3\u72B6\u6001\uFF080=\u6B63\u5E38,1=\u51BB\u7ED3\uFF09\n )`);\n // \u9886\u5730\u6210\u5458\u8868\n db.exec(/* sql */ `\n CREATE TABLE IF NOT EXISTS sfmc_land_members (\n land_id TEXT NOT NULL, -- \u9886\u5730id\n player_id TEXT NOT NULL, -- \u6210\u5458\u73A9\u5BB6id\n player_name_snapshot TEXT NOT NULL DEFAULT '', -- \u6210\u5458\u540D\u79F0\u5FEB\u7167\n role TEXT NOT NULL DEFAULT 'admin', -- \u6210\u5458\u89D2\u8272\uFF08member/trusted/admin/owner\uFF09\n created_at INTEGER NOT NULL, -- \u52A0\u5165\u65F6\u95F4\u6233\n expires_at INTEGER, -- \u6210\u5458\u8D44\u683C\u8FC7\u671F\u65F6\u95F4\u6233\n PRIMARY KEY (land_id, player_id), -- \u8054\u5408\u4E3B\u952E\n FOREIGN KEY (land_id) REFERENCES sfmc_lands(id) ON DELETE CASCADE -- \u7EA7\u8054\u5220\u9664\n )`);\n // \u9886\u5730\u6743\u9650\u8868\n db.exec(/* sql */ `\n CREATE TABLE IF NOT EXISTS sfmc_land_permissions (\n land_id TEXT NOT NULL, -- \u9886\u5730id\n permission_key TEXT NOT NULL, -- \u6743\u9650\u952E\uFF08\u5982 buildbreak.interact \u7B49\uFF09\n subject_type TEXT NOT NULL, -- \u6743\u9650\u4E3B\u4F53\u7C7B\u578B\uFF08player/group/role/all\uFF09\n subject_id TEXT NOT NULL, -- \u6743\u9650\u4E3B\u4F53id\n allowed INTEGER NOT NULL DEFAULT 0, -- \u662F\u5426\u5141\u8BB8\uFF081=\u5141\u8BB8,0=\u62D2\u7EDD,-1=\u672A\u8BBE\u7F6E\uFF09\n updated_at INTEGER NOT NULL, -- \u6743\u9650\u66F4\u65B0\u65F6\u95F4\u6233\n PRIMARY KEY (land_id, permission_key, subject_type, subject_id), -- \u8054\u5408\u4E3B\u952E\n FOREIGN KEY (land_id) REFERENCES sfmc_lands(id) ON DELETE CASCADE -- \u7EA7\u8054\u5220\u9664\n )`);\n // \u9886\u5730\u9080\u8BF7\u8868\n db.exec(/* sql */ `\n CREATE TABLE IF NOT EXISTS sfmc_land_invites (\n id TEXT PRIMARY KEY, -- \u9080\u8BF7\u552F\u4E00id\n land_id TEXT NOT NULL, -- \u9886\u5730id\n inviter_id TEXT NOT NULL, -- \u9080\u8BF7\u4EBAid\n invitee_id TEXT NOT NULL, -- \u88AB\u9080\u8BF7\u4EBAid\n role TEXT NOT NULL, -- \u9080\u8BF7\u89D2\u8272\n expires_at INTEGER NOT NULL, -- \u9080\u8BF7\u8FC7\u671F\u65F6\u95F4\u6233\n status TEXT NOT NULL DEFAULT 'pending', -- \u72B6\u6001\uFF08pending/accepted/rejected/expired\uFF09\n created_at INTEGER NOT NULL, -- \u521B\u5EFA\u65F6\u95F4\u6233\n FOREIGN KEY (land_id) REFERENCES sfmc_lands(id) ON DELETE CASCADE -- \u7EA7\u8054\u5220\u9664\n )`);\n // \u9886\u5730\u9080\u8BF7\u8868\u7D22\u5F15\uFF1A\u6309\u88AB\u9080\u8BF7\u4EBA+\u72B6\u6001+\u8FC7\u671F\u65F6\u95F4\u67E5\n db.exec(/* sql */ `\n CREATE INDEX IF NOT EXISTS idx_sfmc_land_invites_target ON sfmc_land_invites(invitee_id, status, expires_at)`);\n // \u9886\u5730\u64CD\u4F5C\u5BA1\u8BA1\u65E5\u5FD7\u8868\n db.exec(/* sql */ `\n CREATE TABLE IF NOT EXISTS sfmc_land_audit_logs (\n id INTEGER PRIMARY KEY AUTOINCREMENT, -- \u65E5\u5FD7id\uFF08\u81EA\u589E\uFF09\n land_id TEXT NOT NULL, -- \u9886\u5730id\n actor_id TEXT NOT NULL, -- \u64CD\u4F5C\u8005id\n action TEXT NOT NULL, -- \u64CD\u4F5C\u7C7B\u578B\uFF08\u5982 claim/release/transfer/updat \u7B49\uFF09\n payload TEXT NOT NULL DEFAULT '{}', -- \u64CD\u4F5C\u8F7D\u8377\uFF08json\uFF09\n created_at INTEGER NOT NULL, -- \u65E5\u5FD7\u521B\u5EFA\u65F6\u95F4\u6233\n FOREIGN KEY (land_id) REFERENCES sfmc_lands(id) ON DELETE CASCADE -- \u7EA7\u8054\u5220\u9664\n )`);\n // \u9886\u5730\u64CD\u4F5C\u8BF7\u6C42\u8868\uFF08\u5F02\u6B65\u64CD\u4F5C\uFF09\n db.exec(/* sql */ `\n CREATE TABLE IF NOT EXISTS sfmc_land_operations (\n request_id TEXT PRIMARY KEY, -- \u8BF7\u6C42\u552F\u4E00id\n operation_type TEXT NOT NULL, -- \u64CD\u4F5C\u7C7B\u578B\uFF08\u5982 claim/release/upgrade \u7B49\uFF09\n actor_id TEXT NOT NULL, -- \u64CD\u4F5C\u53D1\u8D77\u4EBAid\n land_id TEXT, -- \u5173\u8054\u9886\u5730id\uFF08\u53EF\u9009\uFF09\n status TEXT NOT NULL, -- \u8BF7\u6C42\u72B6\u6001\uFF08pending/processing/completed/failed\uFF09\n response_json TEXT NOT NULL, -- \u64CD\u4F5C\u54CD\u5E94\u7ED3\u679C\uFF08json\uFF09\n created_at INTEGER NOT NULL -- \u8BF7\u6C42\u521B\u5EFA\u65F6\u95F4\u6233\n )`);\n\n // (10 \u73A9\u5BB6\u547D\u4EE4\u4F7F\u7528\u7EDF\u8BA1\n db.exec(/* sql */ `\n CREATE TABLE IF NOT EXISTS sfmc_player_command_usage (\n id INTEGER PRIMARY KEY AUTOINCREMENT, -- \u8BB0\u5F55id\uFF08\u81EA\u589E\uFF09\n player_id TEXT NOT NULL, -- \u73A9\u5BB6id\n command TEXT NOT NULL, -- \u547D\u4EE4\u540D\u79F0\uFF08\u4E0D\u542B/\u524D\u7F00\uFF09\n date TEXT NOT NULL, -- \u7EDF\u8BA1\u65E5\u671F\uFF08YYYY-MM-DD\u683C\u5F0F\uFF09\n count INTEGER DEFAULT 0, -- \u5F53\u65E5\u8BE5\u547D\u4EE4\u4F7F\u7528\u6B21\u6570\n UNIQUE(player_id, command, date) -- \u552F\u4E00\u7EA6\u675F\uFF1A\u540C\u4E00\u73A9\u5BB6\u540C\u4E00\u547D\u4EE4\u540C\u4E00\u5929\n )`);\n\n // (11 \u7ECF\u6D4E\u7CFB\u7EDF\n db.exec(/* sql */ `\n CREATE TABLE IF NOT EXISTS sfmc_economy_price_index (\n item_type TEXT NOT NULL, -- \u7269\u54C1\u7C7B\u578B\u6807\u8BC6\u7B26\n item_aux INTEGER DEFAULT 0, -- \u7269\u54C1\u9644\u52A0\u503C/\u6570\u636E\u503C\n base_buy_price INTEGER NOT NULL DEFAULT 0, -- \u57FA\u7840\u6536\u8D2D\u4EF7\u683C\n base_sell_price INTEGER NOT NULL DEFAULT 0, -- \u57FA\u7840\u51FA\u552E\u4EF7\u683C\n current_buy_price INTEGER NOT NULL DEFAULT 0, -- \u5F53\u524D\u6536\u8D2D\u4EF7\u683C\n current_sell_price INTEGER NOT NULL DEFAULT 0, -- \u5F53\u524D\u51FA\u552E\u4EF7\u683C\n elasticity REAL DEFAULT 0.3, -- \u4EF7\u683C\u5F39\u6027\u7CFB\u6570\n weekly_acquisition_cap INTEGER, -- \u5468\u6536\u8D2D\u4E0A\u9650\n weekly_acquired INTEGER DEFAULT 0, -- \u672C\u5468\u5DF2\u6536\u8D2D\u6570\u91CF\n week_start INTEGER, -- \u672C\u5468\u5F00\u59CB\u65F6\u95F4\u6233\n rarity TEXT DEFAULT 'common', -- \u7A00\u6709\u5EA6\uFF08common/uncommon/rare/epic/legendary\uFF09\n is_renewable INTEGER DEFAULT 1, -- \u662F\u5426\u53EF\u518D\u751F\n updated_at INTEGER, -- \u7D22\u5F15\u66F4\u65B0\u65F6\u95F4\u6233\n PRIMARY KEY (item_type, item_aux) -- \u8054\u5408\u4E3B\u952E\n )`);\n // \u7ECF\u6D4E\u65E5\u5E38\u4EFB\u52A1\u8868\n db.exec(/* sql */ `\n CREATE TABLE IF NOT EXISTS sfmc_economy_daily_tasks (\n id TEXT PRIMARY KEY, -- \u4EFB\u52A1\u552F\u4E00id\n item_type TEXT NOT NULL, -- \u76EE\u6807\u7269\u54C1\u7C7B\u578B\n item_aux INTEGER DEFAULT 0, -- \u7269\u54C1\u9644\u52A0\u503C\n target_qty INTEGER NOT NULL, -- \u76EE\u6807\u6570\u91CF\n filled_qty INTEGER DEFAULT 0, -- \u5DF2\u5B8C\u6210\u6570\u91CF\n unit_reward INTEGER NOT NULL, -- \u5355\u4F4D\u5956\u52B1\u91D1\u989D\n created_at INTEGER, -- \u4EFB\u52A1\u521B\u5EFA\u65F6\u95F4\u6233\n expires_at INTEGER, -- \u4EFB\u52A1\u8FC7\u671F\u65F6\u95F4\u6233\n status TEXT DEFAULT 'active' -- \u4EFB\u52A1\u72B6\u6001\uFF08active/completed/expired\uFF09\n )`);\n // \u7ECF\u6D4E\u7CFB\u7EDF\u5168\u5C40\u7EDF\u8BA1\u8868\n db.exec(/* sql */ `\n CREATE TABLE IF NOT EXISTS sfmc_economy_stats (\n id TEXT PRIMARY KEY, -- \u7EDF\u8BA1\u9879id\uFF08\u76EE\u524D\u56FA\u5B9A\u4E3A'global'\uFF09\n total_issued INTEGER DEFAULT 0, -- \u7D2F\u8BA1\u53D1\u884C\u8D27\u5E01\u91CF\n total_destroyed INTEGER DEFAULT 0, -- \u7D2F\u8BA1\u9500\u6BC1\u8D27\u5E01\u91CF\n total_supply INTEGER DEFAULT 0, -- \u5F53\u524D\u603B\u4F9B\u5E94\u91CF\n active_accounts INTEGER DEFAULT 0, -- \u6D3B\u8DC3\u8D26\u6237\u6570\n computed_at INTEGER -- \u7EDF\u8BA1\u8BA1\u7B97\u65F6\u95F4\u6233\n )`);\n // \u7ECF\u6D4E\u8D26\u6237\u8868\n db.exec(/* sql */ `\n CREATE TABLE IF NOT EXISTS sfmc_economy_accounts (\n player_id TEXT PRIMARY KEY, -- \u73A9\u5BB6id\uFF08\u4E3B\u952E\uFF09\n player_name_snapshot TEXT NOT NULL DEFAULT '', -- \u73A9\u5BB6\u540D\u79F0\u5FEB\u7167\n balance INTEGER NOT NULL DEFAULT 0 CHECK(balance >= 0), -- \u8D26\u6237\u4F59\u989D\uFF08>=0\uFF09\n version INTEGER NOT NULL DEFAULT 1, -- \u4E50\u89C2\u9501\u7248\u672C\u53F7\n created_at INTEGER NOT NULL, -- \u8D26\u6237\u521B\u5EFA\u65F6\u95F4\u6233\n updated_at INTEGER NOT NULL -- \u8D26\u6237\u66F4\u65B0\u65F6\u95F4\u6233\n )`);\n // \u7ECF\u6D4E\u4EA4\u6613\u6D41\u6C34\u8868\n db.exec(/* sql */ `\n CREATE TABLE IF NOT EXISTS sfmc_economy_transactions (\n id TEXT PRIMARY KEY, -- \u4EA4\u6613\u552F\u4E00id\n transaction_type TEXT NOT NULL, -- \u4EA4\u6613\u7C7B\u578B\uFF08transfer/payment/reward/purchase\u7B49\uFF09\n actor_id TEXT NOT NULL, -- \u4EA4\u6613\u53D1\u8D77\u4EBAid\n source_player_id TEXT, -- \u6E90\u73A9\u5BB6id\uFF08\u4ED8\u6B3E\u65B9\uFF09\n target_player_id TEXT, -- \u76EE\u6807\u73A9\u5BB6id\uFF08\u6536\u6B3E\u65B9\uFF09\n amount INTEGER NOT NULL CHECK(amount > 0), -- \u4EA4\u6613\u91D1\u989D\uFF08>0\uFF09\n balance_before INTEGER, -- \u4EA4\u6613\u524D\u4F59\u989D\n balance_after INTEGER, -- \u4EA4\u6613\u540E\u4F59\u989D\n reference_type TEXT NOT NULL DEFAULT '', -- \u5173\u8054\u4E1A\u52A1\u7C7B\u578B\n reference_id TEXT NOT NULL DEFAULT '', -- \u5173\u8054\u4E1A\u52A1id\n reason TEXT NOT NULL DEFAULT '', -- \u4EA4\u6613\u539F\u56E0/\u5907\u6CE8\n created_at INTEGER NOT NULL -- \u4EA4\u6613\u65F6\u95F4\u6233\n )`);\n // \u7ECF\u6D4E\u5E42\u7B49\u8868\uFF08\u9632\u6B62\u91CD\u590D\u4EA4\u6613\uFF09\n db.exec(/* sql */ `\n CREATE TABLE IF NOT EXISTS sfmc_economy_idempotency (\n actor_id TEXT NOT NULL, -- \u64CD\u4F5C\u8005id\n idempotency_key TEXT NOT NULL, -- \u5E42\u7B49\u952E\n transaction_id TEXT NOT NULL, -- \u5DF2\u5904\u7406\u7684\u4EA4\u6613id\n response_json TEXT NOT NULL, -- \u5904\u7406\u7ED3\u679C\uFF08json\uFF09\n created_at INTEGER NOT NULL, -- \u8BB0\u5F55\u521B\u5EFA\u65F6\u95F4\u6233\n PRIMARY KEY (actor_id, idempotency_key) -- \u8054\u5408\u4E3B\u952E\n )`);\n // \u7ECF\u6D4E\u76F8\u5173\u7D22\u5F15\n db.exec(/* sql */ `\n CREATE INDEX IF NOT EXISTS idx_economy_transactions_player ON sfmc_economy_transactions(source_player_id, created_at DESC);\n CREATE INDEX IF NOT EXISTS idx_economy_transactions_target ON sfmc_economy_transactions(target_player_id, created_at DESC);\n CREATE INDEX IF NOT EXISTS idx_sfmc_lands_owner ON sfmc_lands(owner_player_id, status);\n CREATE INDEX IF NOT EXISTS idx_sfmc_lands_location ON sfmc_lands(dimension, min_x, max_x, min_z, max_z, status)`);\n}\n\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -1,85 +1,37 @@
1
- /**
2
- * domain/transaction.ts — SQLite 事务执行器 + 共享业务结果类型
3
- *
4
- * 事务描述:
5
- * - withTransaction(db, fn) IMMEDIATE 事务包裹器
6
- * 自动 BEGIN IMMEDIATE / COMMIT / ROLLBACK,
7
- * 异常时 ROLLBACK 并重新抛错;支持同步 + async 回调
8
- * - withResult(db, fn) withTransaction 的语义别名("业务失败但不抛错"
9
- * 的场景,函数返回 TxResult 自己判 ok)
10
- *
11
- * 共享类型:
12
- * - Transactional 事务执行器所需的最小接口(Pick<DatabaseSync, "exec">),
13
- * 让领域函数能接受 node:sqlite DatabaseSync 或 routes 注入的
14
- * 窄化包装
15
- * - TxResult<T> 领域事务统一结果类型:{ ok:true, data } | { ok:false, error, status, extra? }
16
- * 所有领域模块(land / coop / economy / redpacket)都从此处引用,
17
- * 避免跨域循环依赖
18
- *
19
- * 用法:
20
- * const result = withTransaction(db, () => {
21
- * const rows = query(SQL`SELECT 1`);
22
- * return rows[0];
23
- * });
24
- *
25
- * 行为约定:
26
- * - return value → COMMIT 后透传给调用方
27
- * - throw → ROLLBACK 后重新抛错
28
- * - return Promise → await 后再 COMMIT / ROLLBACK
29
- */
30
- /**
31
- * 在 IMMEDIATE 事务包裹下运行回调。回调内任何抛出都会触发 ROLLBACK 并重新抛错。
32
- *
33
- * 行为约定:
34
- * - return value → COMMIT 后透传给调用方
35
- * - throw → ROLLBACK 后重新抛错
36
- * - return Promise → await 后再 COMMIT / ROLLBACK
37
- */
38
- export function withTransaction(db, fn) {
39
- db.exec("BEGIN IMMEDIATE");
40
- try {
41
- const out = fn();
42
- if (out instanceof Promise) {
43
- // 同步/异步混合:等待 Promise 后决定提交
44
- return Promise.resolve(out).then((v) => {
45
- db.exec("COMMIT");
46
- return v;
47
- }, (err) => {
48
- try {
49
- db.exec("ROLLBACK");
50
- }
51
- catch {
52
- /* ignore secondary failures */
53
- }
54
- throw err;
55
- });
56
- }
57
- db.exec("COMMIT");
58
- return out;
59
- }
60
- catch (error) {
61
- try {
1
+ function withTransaction(db, fn) {
2
+ db.exec("BEGIN IMMEDIATE");
3
+ try {
4
+ const out = fn();
5
+ if (out instanceof Promise) {
6
+ return Promise.resolve(out).then(
7
+ (v) => {
8
+ db.exec("COMMIT");
9
+ return v;
10
+ },
11
+ (err) => {
12
+ try {
62
13
  db.exec("ROLLBACK");
14
+ } catch {
15
+ }
16
+ throw err;
63
17
  }
64
- catch {
65
- /* ignore rollback failures */
66
- }
67
- throw error;
18
+ );
19
+ }
20
+ db.exec("COMMIT");
21
+ return out;
22
+ } catch (error) {
23
+ try {
24
+ db.exec("ROLLBACK");
25
+ } catch {
68
26
  }
27
+ throw error;
28
+ }
69
29
  }
70
- /**
71
- * withTransaction 的结果封装版 —— 适合领域函数想表达“业务失败但不抛错”的场景。
72
- *
73
- * 用法:
74
- * const r = withResult(db, () => {
75
- * if (bad) return { ok: false, error: "x" };
76
- * return { ok: true, ... };
77
- * });
78
- * if (!r.ok) ...
79
- *
80
- * - 注意:仍由回调决定成功/失败;只在抛错时回滚。
81
- */
82
- export function withResult(db, fn) {
83
- return withTransaction(db, fn);
30
+ function withResult(db, fn) {
31
+ return withTransaction(db, fn);
84
32
  }
85
- //# sourceMappingURL=transaction.js.map
33
+ export {
34
+ withResult,
35
+ withTransaction
36
+ };
37
+ //# sourceMappingURL=transaction.js.map
@@ -1 +1,7 @@
1
- {"version":3,"file":"transaction.js","sourceRoot":"","sources":["../../src/domain/transaction.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAcH;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe,CAC7B,EAAiB,EACjB,EAAwB;IAExB,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IAC3B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,EAAE,EAAE,CAAC;QACjB,IAAI,GAAG,YAAY,OAAO,EAAE,CAAC;YAC3B,2BAA2B;YAC3B,OAAO,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,CAC9B,CAAC,CAAC,EAAE,EAAE;gBACJ,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAClB,OAAO,CAAC,CAAC;YACX,CAAC,EACD,CAAC,GAAG,EAAE,EAAE;gBACN,IAAI,CAAC;oBACH,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;gBACtB,CAAC;gBAAC,MAAM,CAAC;oBACP,+BAA+B;gBACjC,CAAC;gBACD,MAAM,GAAG,CAAC;YACZ,CAAC,CACG,CAAC;QACT,CAAC;QACD,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAClB,OAAO,GAAG,CAAC;IACb,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC;YACH,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACtB,CAAC;QAAC,MAAM,CAAC;YACP,8BAA8B;QAChC,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,UAAU,CACxB,EAAiB,EACjB,EAAwB;IAExB,OAAO,eAAe,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;AACjC,CAAC"}
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/domain/transaction.ts"],
4
+ "sourcesContent": ["/**\n * domain/transaction.ts \u2014 SQLite \u4E8B\u52A1\u6267\u884C\u5668 + \u5171\u4EAB\u4E1A\u52A1\u7ED3\u679C\u7C7B\u578B\n *\n * \u4E8B\u52A1\u63CF\u8FF0:\n * - withTransaction(db, fn) IMMEDIATE \u4E8B\u52A1\u5305\u88F9\u5668\n * \u81EA\u52A8 BEGIN IMMEDIATE / COMMIT / ROLLBACK,\n * \u5F02\u5E38\u65F6 ROLLBACK \u5E76\u91CD\u65B0\u629B\u9519;\u652F\u6301\u540C\u6B65 + async \u56DE\u8C03\n * - withResult(db, fn) withTransaction \u7684\u8BED\u4E49\u522B\u540D(\u4F9B\"\u4E1A\u52A1\u5931\u8D25\u4F46\u4E0D\u629B\u9519\"\n * \u7684\u573A\u666F,\u51FD\u6570\u8FD4\u56DE TxResult \u81EA\u5DF1\u5224 ok)\n *\n * \u5171\u4EAB\u7C7B\u578B:\n * - Transactional \u4E8B\u52A1\u6267\u884C\u5668\u6240\u9700\u7684\u6700\u5C0F\u63A5\u53E3(Pick<DatabaseSync, \"exec\">),\n * \u8BA9\u9886\u57DF\u51FD\u6570\u80FD\u63A5\u53D7 node:sqlite DatabaseSync \u6216 routes \u6CE8\u5165\u7684\n * \u7A84\u5316\u5305\u88C5\n * - TxResult<T> \u9886\u57DF\u4E8B\u52A1\u7EDF\u4E00\u7ED3\u679C\u7C7B\u578B:{ ok:true, data } | { ok:false, error, status, extra? }\n * \u6240\u6709\u9886\u57DF\u6A21\u5757(land / coop / economy / redpacket)\u90FD\u4ECE\u6B64\u5904\u5F15\u7528,\n * \u907F\u514D\u8DE8\u57DF\u5FAA\u73AF\u4F9D\u8D56\n *\n * \u7528\u6CD5:\n * const result = withTransaction(db, () => {\n * const rows = query(SQL`SELECT 1`);\n * return rows[0];\n * });\n *\n * \u884C\u4E3A\u7EA6\u5B9A:\n * - return value \u2192 COMMIT \u540E\u900F\u4F20\u7ED9\u8C03\u7528\u65B9\n * - throw \u2192 ROLLBACK \u540E\u91CD\u65B0\u629B\u9519\n * - return Promise \u2192 await \u540E\u518D COMMIT / ROLLBACK\n */\n\nimport type { DatabaseSync } from \"node:sqlite\";\n\n/** \u4E8B\u52A1\u6267\u884C\u5668\u6240\u9700\u7684\u6700\u5C0F\u63A5\u53E3 (db.exec)\uFF0C\u8BA9\u9886\u57DF\u51FD\u6570\u80FD\u63A5\u53D7 node:sqlite DatabaseSync\n * \u6216 routes \u6CE8\u5165\u7684\u7A84\u5316\u5305\u88C5 */\nexport type Transactional = Pick<DatabaseSync, \"exec\">;\n\n/** \u9886\u57DF\u4E8B\u52A1\u7EDF\u4E00\u7ED3\u679C\u7C7B\u578B\uFF1A\u6210\u529F\u643A\u5E26 data\uFF0C\u5931\u8D25\u643A\u5E26 error + HTTP status\u3002\n * \u53EF\u9009 extra \u5B57\u6BB5\u7528\u4E8E\u643A\u5E26\u9644\u52A0\u4E0A\u4E0B\u6587\uFF08\u5982\u5F53\u524D\u4F59\u989D\uFF09\u4F9B route \u5C42\u900F\u4F20\u3002 */\nexport type TxResult<T> =\n | { ok: true; data: T }\n | { ok: false; error: string; status: number; extra?: Record<string, unknown> };\n\n/**\n * \u5728 IMMEDIATE \u4E8B\u52A1\u5305\u88F9\u4E0B\u8FD0\u884C\u56DE\u8C03\u3002\u56DE\u8C03\u5185\u4EFB\u4F55\u629B\u51FA\u90FD\u4F1A\u89E6\u53D1 ROLLBACK \u5E76\u91CD\u65B0\u629B\u9519\u3002\n *\n * \u884C\u4E3A\u7EA6\u5B9A\uFF1A\n * - return value \u2192 COMMIT \u540E\u900F\u4F20\u7ED9\u8C03\u7528\u65B9\n * - throw \u2192 ROLLBACK \u540E\u91CD\u65B0\u629B\u9519\n * - return Promise \u2192 await \u540E\u518D COMMIT / ROLLBACK\n */\nexport function withTransaction<T>(\n db: Transactional,\n fn: () => T | Promise<T>\n): T {\n db.exec(\"BEGIN IMMEDIATE\");\n try {\n const out = fn();\n if (out instanceof Promise) {\n // \u540C\u6B65/\u5F02\u6B65\u6DF7\u5408\uFF1A\u7B49\u5F85 Promise \u540E\u51B3\u5B9A\u63D0\u4EA4\n return Promise.resolve(out).then(\n (v) => {\n db.exec(\"COMMIT\");\n return v;\n },\n (err) => {\n try {\n db.exec(\"ROLLBACK\");\n } catch {\n /* ignore secondary failures */\n }\n throw err;\n }\n ) as T;\n }\n db.exec(\"COMMIT\");\n return out;\n } catch (error) {\n try {\n db.exec(\"ROLLBACK\");\n } catch {\n /* ignore rollback failures */\n }\n throw error;\n }\n}\n\n/**\n * withTransaction \u7684\u7ED3\u679C\u5C01\u88C5\u7248 \u2014\u2014 \u9002\u5408\u9886\u57DF\u51FD\u6570\u60F3\u8868\u8FBE\u201C\u4E1A\u52A1\u5931\u8D25\u4F46\u4E0D\u629B\u9519\u201D\u7684\u573A\u666F\u3002\n *\n * \u7528\u6CD5:\n * const r = withResult(db, () => {\n * if (bad) return { ok: false, error: \"x\" };\n * return { ok: true, ... };\n * });\n * if (!r.ok) ...\n *\n * - \u6CE8\u610F\uFF1A\u4ECD\u7531\u56DE\u8C03\u51B3\u5B9A\u6210\u529F/\u5931\u8D25\uFF1B\u53EA\u5728\u629B\u9519\u65F6\u56DE\u6EDA\u3002\n */\nexport function withResult<T>(\n db: Transactional,\n fn: () => T | Promise<T>\n): T | Promise<T> {\n return withTransaction(db, fn);\n}\n"],
5
+ "mappings": "AAkDO,SAAS,gBACd,IACA,IACG;AACH,KAAG,KAAK,iBAAiB;AACzB,MAAI;AACF,UAAM,MAAM,GAAG;AACf,QAAI,eAAe,SAAS;AAE1B,aAAO,QAAQ,QAAQ,GAAG,EAAE;AAAA,QAC1B,CAAC,MAAM;AACL,aAAG,KAAK,QAAQ;AAChB,iBAAO;AAAA,QACT;AAAA,QACA,CAAC,QAAQ;AACP,cAAI;AACF,eAAG,KAAK,UAAU;AAAA,UACpB,QAAQ;AAAA,UAER;AACA,gBAAM;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,OAAG,KAAK,QAAQ;AAChB,WAAO;AAAA,EACT,SAAS,OAAO;AACd,QAAI;AACF,SAAG,KAAK,UAAU;AAAA,IACpB,QAAQ;AAAA,IAER;AACA,UAAM;AAAA,EACR;AACF;AAcO,SAAS,WACd,IACA,IACgB;AAChB,SAAO,gBAAgB,IAAI,EAAE;AAC/B;",
6
+ "names": []
7
+ }
package/dist/env.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAAA;;GAEG;AAyBH,MAAM,WAAW,SAAS;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IAEnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IAEpB,WAAW,EAAE,MAAM,CAAC;IACpB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,wBAAgB,OAAO,IAAI,SAAS,CA2FnC"}
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAAA;;GAEG;AAoBH,MAAM,WAAW,SAAS;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IAEnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IAEpB,WAAW,EAAE,MAAM,CAAC;IACpB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,wBAAgB,OAAO,IAAI,SAAS,CAyFnC"}
package/dist/env.js CHANGED
@@ -1,94 +1,95 @@
1
- /**
2
- * env.ts — 环境配置加载
3
- */
4
- import { ensureJsonConfig, modulePath, resolveRuntimeRoot } from "@sfmc-bds/sdk/node/config";
1
+ import {
2
+ ensureCoreConfigs,
3
+ loadEnsuredConfig,
4
+ modulePath,
5
+ resolveRuntimeRoot,
6
+ DEFAULT_DB_CONFIG,
7
+ DEFAULT_QQ_CONFIG
8
+ } from "@sfmc-bds/sdk/node/config";
5
9
  import { isAbsolute, join, resolve } from "node:path";
6
10
  import { fileURLToPath } from "node:url";
7
11
  import { log } from "./lib/log.js";
8
12
  import { dirname } from "node:path";
9
13
  const __filename = fileURLToPath(import.meta.url);
10
14
  const __dirname = dirname(__filename);
11
- const DEFAULT_DB_CONFIG = {
12
- db_port: 3001,
13
- dbDir: "data/sfmc_data.db",
14
- modulesDir: "modules",
15
- };
16
- const DEFAULT_QQ_CONFIG = {
17
- llbot_host: "127.0.0.1",
18
- llbot_port: 3004,
19
- llbot_token: "",
20
- };
21
- export function loadEnv() {
22
- const PROJECT_ROOT = resolveRuntimeRoot(resolve(__dirname, "..", ".."));
23
- /* 启动时确认 db/qq config 存在;不存在就写带默认值的骨架。
24
- * 不依赖 wizard:wizard 只填字段,骨架由服务自己 ensure。 */
25
- const dbconfig = ensureJsonConfig(PROJECT_ROOT, "db_config.json", DEFAULT_DB_CONFIG);
26
- const qqconfig = ensureJsonConfig(PROJECT_ROOT, "qq_config.json", DEFAULT_QQ_CONFIG);
27
- // ── 优先级:JSON > 系统环境变量 > 默认值 ───────────────────────
28
- const envBaseline = { ...process.env };
29
- // 元数据前缀:`_` 开头视为注释/说明(如 _comment / _comment_group),不写 env、不打日志
30
- const isMeta = (k) => String(k).startsWith("_");
31
- for (const [k, v] of Object.entries(dbconfig)) {
32
- if (isMeta(k))
33
- continue;
34
- const envKey = k.replace(/([A-Z])/g, "_$1").toUpperCase();
35
- process.env[envKey] = String(v);
36
- log.info(`db_config::${k} -> process.env.${envKey} = ${String(v)}`);
15
+ function loadEnv() {
16
+ const PROJECT_ROOT = resolveRuntimeRoot(resolve(__dirname, "..", ".."));
17
+ ensureCoreConfigs(PROJECT_ROOT, ["db_config", "qq_config", "permissions"]);
18
+ const dbconfig = loadEnsuredConfig(
19
+ PROJECT_ROOT,
20
+ "db_config.json",
21
+ "db_config",
22
+ { ...DEFAULT_DB_CONFIG }
23
+ );
24
+ const qqconfig = loadEnsuredConfig(
25
+ PROJECT_ROOT,
26
+ "qq_config.json",
27
+ "qq_config",
28
+ { ...DEFAULT_QQ_CONFIG }
29
+ );
30
+ const envBaseline = { ...process.env };
31
+ for (const [k, v] of Object.entries(dbconfig)) {
32
+ const envKey = k.replace(/([A-Z])/g, "_$1").toUpperCase();
33
+ process.env[envKey] = String(v);
34
+ log.info(`db_config::${k} -> process.env.${envKey} = ${String(v)}`);
35
+ }
36
+ for (const [k, v] of Object.entries(qqconfig)) {
37
+ const envKey = k.replace(/([A-Z])/g, "_$1").toUpperCase();
38
+ if (process.env[envKey] === void 0) {
39
+ process.env[envKey] = String(v);
40
+ log.info(`qq_config::${k} -> process.env.${envKey} = ${String(v)}`);
37
41
  }
38
- for (const [k, v] of Object.entries(qqconfig)) {
39
- if (isMeta(k))
40
- continue;
41
- const envKey = k.replace(/([A-Z])/g, "_$1").toUpperCase();
42
- if (process.env[envKey] === undefined) {
43
- process.env[envKey] = String(v);
44
- log.info(`qq_config::${k} -> process.env.${envKey} = ${String(v)}`);
45
- }
42
+ }
43
+ function pick(jsonVal, envKey, fallback, source) {
44
+ if (jsonVal !== void 0 && jsonVal !== null) {
45
+ return jsonVal;
46
46
  }
47
- // 工具:JSON > envBaseline(原 process.env) > default
48
- // 语义:JSON 里有这个键( undefined / null)就用 JSON;空串、0、false 都算"显式配置"
49
- // 只有 JSON 完全没这个键(或者显式 null)才 fall through 到 env
50
- function pick(jsonVal, envKey, fallback, source) {
51
- if (jsonVal !== undefined && jsonVal !== null) {
52
- return jsonVal;
53
- }
54
- const fromEnv = envBaseline[envKey];
55
- if (fromEnv !== undefined && fromEnv !== "") {
56
- log.info(`${source} 未在 JSON 中配置,使用系统环境变量 ${envKey} = ${fromEnv}`);
57
- return fromEnv;
58
- }
59
- return fallback;
47
+ const fromEnv = envBaseline[envKey];
48
+ if (fromEnv !== void 0 && fromEnv !== "") {
49
+ log.info(`${source} \u672A\u5728 JSON \u4E2D\u914D\u7F6E,\u4F7F\u7528\u7CFB\u7EDF\u73AF\u5883\u53D8\u91CF ${envKey} = ${fromEnv}`);
50
+ return fromEnv;
60
51
  }
61
- const PORT = parseInt(String(pick(dbconfig["db_port"], "DB_PORT", 3001, "db_port")), 10);
62
- const HOST = "127.0.0.1";
63
- const DB_PATH_RAW = String(pick(dbconfig["dbDir"], "DB_DIR", "data/sfmc_data.db", "dbDir"));
64
- const DB_PATH = isAbsolute(DB_PATH_RAW) ? DB_PATH_RAW : resolve(PROJECT_ROOT, DB_PATH_RAW);
65
- const LLBOT_HOST = String(pick(qqconfig["llbot_host"], "LLBOT_HOST", "127.0.0.1", "llbot_host"));
66
- const LLBOT_PORT = parseInt(String(pick(qqconfig["llbot_port"], "LLBOT_PORT", 3004, "llbot_port")), 10);
67
- const LLBOT_TOKEN = String(pick(qqconfig["llbot_token"], "LLBOT_TOKEN", "", "llbot_token"));
68
- const QQ_GROUP_ID = String(pick(qqconfig["qq_group_id"], "QQ_GROUP_ID", "", "qq_group_id"));
69
- const QQ_BRIDGE_CHANNEL_ID = String(pick(qqconfig["bridge_channel_id"], "BRIDGE_CHANNEL_ID", "", "bridge_channel_id"));
70
- const AUTH_TOKEN = String(pick(dbconfig["http_auth"], "HTTP_AUTH", "", "http_auth"));
71
- const MODULES_DIR = dbconfig["modulesDir"]
72
- ? resolve(PROJECT_ROOT, String(dbconfig["modulesDir"]))
73
- : join(PROJECT_ROOT, "modules");
74
- const MODULE_CATALOG_PATH = modulePath(MODULES_DIR, "catalog.json");
75
- const MODULE_LOCK_PATH = modulePath(MODULES_DIR, "module-lock.json");
76
- return {
77
- PROJECT_ROOT,
78
- PORT,
79
- HOST,
80
- DB_PATH,
81
- AUTH_TOKEN,
82
- LLBOT_HOST,
83
- LLBOT_PORT,
84
- LLBOT_TOKEN,
85
- QQ_GROUP_ID,
86
- QQ_BRIDGE_CHANNEL_ID,
87
- MODULES_DIR,
88
- MODULE_CATALOG_PATH,
89
- MODULE_LOCK_PATH,
90
- dbconfig,
91
- qqconfig,
92
- };
52
+ return fallback;
53
+ }
54
+ const PORT = parseInt(String(pick(dbconfig["db_port"], "DB_PORT", 3001, "db_port")), 10);
55
+ const HOST = "127.0.0.1";
56
+ const DB_PATH_RAW = String(pick(dbconfig["dbDir"], "DB_DIR", "data/sfmc_data.db", "dbDir"));
57
+ const DB_PATH = isAbsolute(DB_PATH_RAW) ? DB_PATH_RAW : resolve(PROJECT_ROOT, DB_PATH_RAW);
58
+ const LLBOT_HOST = String(
59
+ pick(qqconfig["llbot_host"], "LLBOT_HOST", "127.0.0.1", "llbot_host")
60
+ );
61
+ const LLBOT_PORT = parseInt(
62
+ String(pick(qqconfig["llbot_port"], "LLBOT_PORT", 3004, "llbot_port")),
63
+ 10
64
+ );
65
+ const LLBOT_TOKEN = String(pick(qqconfig["llbot_token"], "LLBOT_TOKEN", "", "llbot_token"));
66
+ const QQ_GROUP_ID = String(pick(qqconfig["qq_group_id"], "QQ_GROUP_ID", "", "qq_group_id"));
67
+ const QQ_BRIDGE_CHANNEL_ID = String(
68
+ pick(qqconfig["bridge_channel_id"], "BRIDGE_CHANNEL_ID", "", "bridge_channel_id")
69
+ );
70
+ const AUTH_TOKEN = String(pick(dbconfig["http_auth"], "HTTP_AUTH", "", "http_auth"));
71
+ const MODULES_DIR = dbconfig["modulesDir"] ? resolve(PROJECT_ROOT, String(dbconfig["modulesDir"])) : join(PROJECT_ROOT, "modules");
72
+ const MODULE_CATALOG_PATH = modulePath(MODULES_DIR, "catalog.json");
73
+ const MODULE_LOCK_PATH = modulePath(MODULES_DIR, "module-lock.json");
74
+ return {
75
+ PROJECT_ROOT,
76
+ PORT,
77
+ HOST,
78
+ DB_PATH,
79
+ AUTH_TOKEN,
80
+ LLBOT_HOST,
81
+ LLBOT_PORT,
82
+ LLBOT_TOKEN,
83
+ QQ_GROUP_ID,
84
+ QQ_BRIDGE_CHANNEL_ID,
85
+ MODULES_DIR,
86
+ MODULE_CATALOG_PATH,
87
+ MODULE_LOCK_PATH,
88
+ dbconfig,
89
+ qqconfig
90
+ };
93
91
  }
94
- //# sourceMappingURL=env.js.map
92
+ export {
93
+ loadEnv
94
+ };
95
+ //# sourceMappingURL=env.js.map
package/dist/env.js.map CHANGED
@@ -1 +1,7 @@
1
- {"version":3,"file":"env.js","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"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"}
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/env.ts"],
4
+ "sourcesContent": ["/**\n * env.ts \u2014 \u73AF\u5883\u914D\u7F6E\u52A0\u8F7D\n */\n\nimport {\n ensureCoreConfigs,\n loadEnsuredConfig,\n modulePath,\n resolveRuntimeRoot,\n DEFAULT_DB_CONFIG,\n DEFAULT_QQ_CONFIG,\n} from \"@sfmc-bds/sdk/node/config\";\nimport { isAbsolute, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport { log } from \"./lib/log.js\";\n\nimport { dirname } from \"node:path\";\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nexport interface EnvConfig {\n PROJECT_ROOT: string;\n PORT: number;\n HOST: string;\n DB_PATH: string;\n AUTH_TOKEN: string;\n // LLBot HTTP\n LLBOT_HOST: string;\n LLBOT_PORT: number;\n LLBOT_TOKEN: string;\n // QQ \u7FA4 / channel(\u4ECE qq_config.json \u900F\u51FA,\u7ED9 bridge / messages \u8DEF\u7531\u7528)\n QQ_GROUP_ID: string;\n QQ_BRIDGE_CHANNEL_ID: string;\n MODULES_DIR: string;\n MODULE_CATALOG_PATH: string;\n MODULE_LOCK_PATH: string;\n dbconfig: Record<string, unknown>;\n qqconfig: Record<string, unknown>;\n}\n\nexport function loadEnv(): EnvConfig {\n const PROJECT_ROOT = resolveRuntimeRoot(resolve(__dirname, \"..\", \"..\"));\n /* \u542F\u52A8\u65F6\u786E\u8BA4 db/qq/permissions \u5B58\u5728;\u4E0D\u5B58\u5728\u5C31\u5199\u5E26\u9ED8\u8BA4\u503C\u7684\u9AA8\u67B6\u3002\n * \u4E0D\u4F9D\u8D56 wizard:wizard \u53EA\u586B\u5B57\u6BB5,\u9AA8\u67B6\u7531\u670D\u52A1\u81EA\u5DF1 ensure\u3002 */\n ensureCoreConfigs(PROJECT_ROOT, [\"db_config\", \"qq_config\", \"permissions\"]);\n const dbconfig = loadEnsuredConfig(\n PROJECT_ROOT,\n \"db_config.json\",\n \"db_config\",\n { ...DEFAULT_DB_CONFIG } as Record<string, unknown>\n );\n const qqconfig = loadEnsuredConfig(\n PROJECT_ROOT,\n \"qq_config.json\",\n \"qq_config\",\n { ...DEFAULT_QQ_CONFIG } as Record<string, unknown>\n );\n\n // \u2500\u2500 \u4F18\u5148\u7EA7:JSON > \u7CFB\u7EDF\u73AF\u5883\u53D8\u91CF > \u9ED8\u8BA4\u503C \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const envBaseline = { ...process.env };\n\n for (const [k, v] of Object.entries(dbconfig)) {\n const envKey = k.replace(/([A-Z])/g, \"_$1\").toUpperCase();\n process.env[envKey] = String(v);\n log.info(`db_config::${k} -> process.env.${envKey} = ${String(v)}`);\n }\n for (const [k, v] of Object.entries(qqconfig)) {\n const envKey = k.replace(/([A-Z])/g, \"_$1\").toUpperCase();\n if (process.env[envKey] === undefined) {\n process.env[envKey] = String(v);\n log.info(`qq_config::${k} -> process.env.${envKey} = ${String(v)}`);\n }\n }\n\n // \u5DE5\u5177:JSON > envBaseline(\u539F process.env) > default\n // \u8BED\u4E49:JSON \u91CC\u6709\u8FD9\u4E2A\u952E(\u975E undefined / null)\u5C31\u7528 JSON;\u7A7A\u4E32\u30010\u3001false \u90FD\u7B97\"\u663E\u5F0F\u914D\u7F6E\"\n // \u53EA\u6709 JSON \u5B8C\u5168\u6CA1\u8FD9\u4E2A\u952E(\u6216\u8005\u663E\u5F0F null)\u624D fall through \u5230 env\n function pick<T>(jsonVal: T | undefined | null, envKey: string, fallback: T, source: string): T {\n if (jsonVal !== undefined && jsonVal !== null) {\n return jsonVal;\n }\n const fromEnv = envBaseline[envKey];\n if (fromEnv !== undefined && fromEnv !== \"\") {\n log.info(`${source} \u672A\u5728 JSON \u4E2D\u914D\u7F6E,\u4F7F\u7528\u7CFB\u7EDF\u73AF\u5883\u53D8\u91CF ${envKey} = ${fromEnv}`);\n return fromEnv as unknown as T;\n }\n return fallback;\n }\n\n const PORT = parseInt(String(pick(dbconfig[\"db_port\"] as number | undefined, \"DB_PORT\", 3001, \"db_port\")), 10);\n const HOST = \"127.0.0.1\";\n const DB_PATH_RAW = String(pick(dbconfig[\"dbDir\"] as string | undefined, \"DB_DIR\", \"data/sfmc_data.db\", \"dbDir\"));\n const DB_PATH = isAbsolute(DB_PATH_RAW) ? DB_PATH_RAW : resolve(PROJECT_ROOT, DB_PATH_RAW);\n const LLBOT_HOST = String(\n pick(qqconfig[\"llbot_host\"] as string | undefined, \"LLBOT_HOST\", \"127.0.0.1\", \"llbot_host\")\n );\n const LLBOT_PORT = parseInt(\n String(pick(qqconfig[\"llbot_port\"] as number | undefined, \"LLBOT_PORT\", 3004, \"llbot_port\")),\n 10\n );\n const LLBOT_TOKEN = String(pick(qqconfig[\"llbot_token\"] as string | undefined, \"LLBOT_TOKEN\", \"\", \"llbot_token\"));\n const QQ_GROUP_ID = String(pick(qqconfig[\"qq_group_id\"] as string | undefined, \"QQ_GROUP_ID\", \"\", \"qq_group_id\"));\n const QQ_BRIDGE_CHANNEL_ID = String(\n pick(qqconfig[\"bridge_channel_id\"] as string | undefined, \"BRIDGE_CHANNEL_ID\", \"\", \"bridge_channel_id\")\n );\n const AUTH_TOKEN = String(pick(dbconfig[\"http_auth\"] as string | undefined, \"HTTP_AUTH\", \"\", \"http_auth\"));\n const MODULES_DIR = dbconfig[\"modulesDir\"]\n ? resolve(PROJECT_ROOT, String(dbconfig[\"modulesDir\"]))\n : join(PROJECT_ROOT, \"modules\");\n const MODULE_CATALOG_PATH = modulePath(MODULES_DIR, \"catalog.json\");\n const MODULE_LOCK_PATH = modulePath(MODULES_DIR, \"module-lock.json\");\n\n return {\n PROJECT_ROOT,\n PORT,\n HOST,\n DB_PATH,\n AUTH_TOKEN,\n LLBOT_HOST,\n LLBOT_PORT,\n LLBOT_TOKEN,\n QQ_GROUP_ID,\n QQ_BRIDGE_CHANNEL_ID,\n MODULES_DIR,\n MODULE_CATALOG_PATH,\n MODULE_LOCK_PATH,\n dbconfig,\n qqconfig,\n };\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
package/dist/index.d.ts CHANGED
@@ -7,7 +7,7 @@
7
7
  * 3. openDatabase + createPlatformTables(sfmc__audit / sfmc__idempotent)
8
8
  * 4. loadManifestV2() — 失败 = 启动失败
9
9
  * 5. filterEnabled(loaded, lockFileEnabled)
10
- * 6. buildModuleAuth({auth_token, enabled_modules}) ← data/module-tokens.json
10
+ * 6. buildModuleAuth({auth_token, enabled_modules}) ← 与 DB 同目录 module-tokens.json
11
11
  * 7. 实例化:SchemaRegistry / ServiceRegistry / IdempotencyStore / TxRunner
12
12
  * 8. 装配 v2 路由 (/api/sfmc/db/* + /api/sfmc/services* + /api/sfmc/configs/:key/*)
13
13
  * 另保留 messages(qq-bridge) + config/modules/health 平台路由
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAcH,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAuB1C,QAAA,MAAM,GAAG,8BAAY,CAAC;AACtB,QAAA,MAAM,EAAE,oCAA4B,CAAC;AAGrC,QAAA,MAAM,KAAK,mCAAkB,CAAC;AA4B9B,QAAA,MAAM,gBAAgB,8DAAwE,CAAC;AAU/F,QAAA,MAAM,UAAU,0CAId,CAAC;AAGH,QAAA,MAAM,cAAc,gBAAyB,CAAC;AAC9C,QAAA,MAAM,eAAe,iBAAwB,CAAC;AAE9C,QAAA,MAAM,QAAQ,UAMZ,CAAC;AAyOH,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,QAAQ,EAAE,gBAAgB,EAAE,UAAU,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAcH,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAwB1C,QAAA,MAAM,GAAG,8BAAY,CAAC;AACtB,QAAA,MAAM,EAAE,oCAA4B,CAAC;AAGrC,QAAA,MAAM,KAAK,mCAAkB,CAAC;AA4B9B,QAAA,MAAM,gBAAgB,8DAAwE,CAAC;AAU/F,QAAA,MAAM,UAAU,0CAId,CAAC;AAGH,QAAA,MAAM,cAAc,gBAAyB,CAAC;AAC9C,QAAA,MAAM,eAAe,iBAAwB,CAAC;AAE9C,QAAA,MAAM,QAAQ,UAMZ,CAAC;AA4QH,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,QAAQ,EAAE,gBAAgB,EAAE,UAAU,EAAE,CAAC"}