wechat-md-publisher 0.8.7 → 0.8.9
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.
- package/dist/{Logger-mgxqCI3-.js → Logger-CRPQmRrm.js} +14 -23
- package/dist/{Logger-mgxqCI3-.js.map → Logger-CRPQmRrm.js.map} +1 -1
- package/dist/cli.js +28 -35
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
- package/themes/builtin/blackink.css +4 -2
- package/themes/builtin/default.css +4 -2
- package/themes/builtin/greenmint.css +4 -2
- package/themes/builtin/orangesun.css +4 -2
- package/themes/builtin/purplerain.css +4 -2
- package/themes/builtin/redruby.css +5 -2
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
var __defProp = Object.defineProperty;
|
|
2
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
-
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
1
|
import { readFile } from "fs/promises";
|
|
5
2
|
import axios from "axios";
|
|
6
3
|
import { dirname, join } from "path";
|
|
@@ -349,10 +346,6 @@ class MaterialAPI {
|
|
|
349
346
|
}
|
|
350
347
|
class WechatClient {
|
|
351
348
|
constructor(appId, appSecret, httpClient, tokenCache, logger) {
|
|
352
|
-
__publicField(this, "token");
|
|
353
|
-
__publicField(this, "draft");
|
|
354
|
-
__publicField(this, "publish");
|
|
355
|
-
__publicField(this, "material");
|
|
356
349
|
this.appId = appId;
|
|
357
350
|
this.token = new TokenAPI(appId, appSecret, httpClient, tokenCache, logger);
|
|
358
351
|
const getAccessToken = () => this.token.getAccessToken();
|
|
@@ -360,6 +353,10 @@ class WechatClient {
|
|
|
360
353
|
this.publish = new PublishAPI(getAccessToken, httpClient, logger);
|
|
361
354
|
this.material = new MaterialAPI(getAccessToken, httpClient, logger);
|
|
362
355
|
}
|
|
356
|
+
token;
|
|
357
|
+
draft;
|
|
358
|
+
publish;
|
|
359
|
+
material;
|
|
363
360
|
async getAccessToken() {
|
|
364
361
|
return await this.token.getAccessToken();
|
|
365
362
|
}
|
|
@@ -402,9 +399,7 @@ class LocalLoader {
|
|
|
402
399
|
}
|
|
403
400
|
}
|
|
404
401
|
class RemoteLoader {
|
|
405
|
-
|
|
406
|
-
__publicField(this, "configs", /* @__PURE__ */ new Map());
|
|
407
|
-
}
|
|
402
|
+
configs = /* @__PURE__ */ new Map();
|
|
408
403
|
async addAPI(name, apiUrl, apiKey) {
|
|
409
404
|
this.configs.set(name, {
|
|
410
405
|
name,
|
|
@@ -515,9 +510,7 @@ class BuiltinLoader {
|
|
|
515
510
|
}
|
|
516
511
|
}
|
|
517
512
|
class ThemeRegistry {
|
|
518
|
-
|
|
519
|
-
__publicField(this, "themes", /* @__PURE__ */ new Map());
|
|
520
|
-
}
|
|
513
|
+
themes = /* @__PURE__ */ new Map();
|
|
521
514
|
register(theme) {
|
|
522
515
|
this.themes.set(theme.id, theme);
|
|
523
516
|
}
|
|
@@ -546,11 +539,11 @@ class ThemeRegistry {
|
|
|
546
539
|
}
|
|
547
540
|
}
|
|
548
541
|
class ThemeEngine {
|
|
542
|
+
registry;
|
|
543
|
+
localLoader;
|
|
544
|
+
remoteLoader;
|
|
545
|
+
builtinLoader;
|
|
549
546
|
constructor() {
|
|
550
|
-
__publicField(this, "registry");
|
|
551
|
-
__publicField(this, "localLoader");
|
|
552
|
-
__publicField(this, "remoteLoader");
|
|
553
|
-
__publicField(this, "builtinLoader");
|
|
554
547
|
this.registry = new ThemeRegistry();
|
|
555
548
|
this.localLoader = new LocalLoader();
|
|
556
549
|
this.remoteLoader = new RemoteLoader();
|
|
@@ -597,9 +590,7 @@ class ThemeEngine {
|
|
|
597
590
|
}
|
|
598
591
|
}
|
|
599
592
|
class MarkdownRenderer {
|
|
600
|
-
|
|
601
|
-
__publicField(this, "wenyan");
|
|
602
|
-
}
|
|
593
|
+
wenyan;
|
|
603
594
|
async initialize() {
|
|
604
595
|
this.wenyan = await createWenyanCore({
|
|
605
596
|
isConvertMathJax: true,
|
|
@@ -643,8 +634,8 @@ const AccountSchema = z.object({
|
|
|
643
634
|
updatedAt: z.date().optional()
|
|
644
635
|
});
|
|
645
636
|
class ConfigStore {
|
|
637
|
+
store;
|
|
646
638
|
constructor() {
|
|
647
|
-
__publicField(this, "store");
|
|
648
639
|
this.store = new Conf({
|
|
649
640
|
projectName: "wechat-md-publisher"
|
|
650
641
|
});
|
|
@@ -675,8 +666,8 @@ class ConfigStore {
|
|
|
675
666
|
}
|
|
676
667
|
}
|
|
677
668
|
class Logger {
|
|
669
|
+
logger;
|
|
678
670
|
constructor() {
|
|
679
|
-
__publicField(this, "logger");
|
|
680
671
|
this.logger = winston.createLogger({
|
|
681
672
|
level: process.env.LOG_LEVEL || "info",
|
|
682
673
|
format: winston.format.combine(
|
|
@@ -724,4 +715,4 @@ export {
|
|
|
724
715
|
WechatError as e,
|
|
725
716
|
WechatRateLimitError as f
|
|
726
717
|
};
|
|
727
|
-
//# sourceMappingURL=Logger-
|
|
718
|
+
//# sourceMappingURL=Logger-CRPQmRrm.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Logger-mgxqCI3-.js","sources":["../src/errors/BaseError.ts","../src/errors/WechatError.ts","../src/core/wechat/constants.ts","../src/core/wechat/api/TokenAPI.ts","../src/core/wechat/api/DraftAPI.ts","../src/core/wechat/api/PublishAPI.ts","../src/core/wechat/api/MaterialAPI.ts","../src/core/wechat/WechatClient.ts","../src/errors/ThemeError.ts","../src/core/theme/loaders/LocalLoader.ts","../src/core/theme/loaders/RemoteLoader.ts","../src/core/theme/loaders/BuiltinLoader.ts","../src/core/theme/registry.ts","../src/core/theme/ThemeEngine.ts","../src/core/renderer/MarkdownRenderer.ts","../src/infrastructure/config/ConfigStore.ts","../src/infrastructure/logger/Logger.ts"],"sourcesContent":["export class BaseError extends Error {\n constructor(\n message: string,\n public code: string,\n public statusCode: number = 500,\n public details?: any\n ) {\n super(message);\n this.name = this.constructor.name;\n Error.captureStackTrace(this, this.constructor);\n }\n\n toJSON() {\n return {\n name: this.name,\n message: this.message,\n code: this.code,\n statusCode: this.statusCode,\n details: this.details,\n };\n }\n}\n","import { BaseError } from './BaseError';\n\nexport class WechatError extends BaseError {\n constructor(\n message: string,\n public errcode: number,\n public errmsg: string\n ) {\n super(message, 'WECHAT_API_ERROR', 500, { errcode, errmsg });\n }\n\n static fromResponse(data: { errcode: number; errmsg: string }): WechatError {\n return new WechatError(\n `微信 API 错误: ${data.errmsg} (${data.errcode})`,\n data.errcode,\n data.errmsg\n );\n }\n}\n\nexport class WechatAuthError extends BaseError {\n constructor(message: string) {\n super(message, 'WECHAT_AUTH_ERROR', 401);\n }\n}\n\nexport class WechatRateLimitError extends BaseError {\n constructor(message: string) {\n super(message, 'WECHAT_RATE_LIMIT_ERROR', 429);\n }\n}\n","export const WECHAT_API_BASE = 'https://api.weixin.qq.com';\n\nexport const WECHAT_API_ENDPOINTS = {\n TOKEN: '/cgi-bin/token',\n DRAFT_ADD: '/cgi-bin/draft/add',\n DRAFT_GET: '/cgi-bin/draft/get',\n DRAFT_DELETE: '/cgi-bin/draft/delete',\n DRAFT_UPDATE: '/cgi-bin/draft/update',\n DRAFT_BATCH_GET: '/cgi-bin/draft/batchget',\n DRAFT_COUNT: '/cgi-bin/draft/count',\n PUBLISH_SUBMIT: '/cgi-bin/freepublish/submit',\n PUBLISH_GET: '/cgi-bin/freepublish/get',\n PUBLISH_DELETE: '/cgi-bin/freepublish/delete',\n PUBLISH_BATCH_GET: '/cgi-bin/freepublish/batchget',\n PUBLISH_GET_STATUS: '/cgi-bin/freepublish/get',\n MATERIAL_ADD: '/cgi-bin/material/add_material',\n MATERIAL_GET: '/cgi-bin/material/get_material',\n MATERIAL_DELETE: '/cgi-bin/material/del_material',\n MATERIAL_BATCH_GET: '/cgi-bin/material/batchget_material',\n MATERIAL_COUNT: '/cgi-bin/material/get_materialcount',\n} as const;\n\nexport const WECHAT_ERROR_CODES = {\n SUCCESS: 0,\n INVALID_CREDENTIAL: 40001,\n ACCESS_TOKEN_EXPIRED: 42001,\n RATE_LIMIT_EXCEEDED: 45009,\n API_UNAUTHORIZED: 48001,\n} as const;\n","import { HttpClient } from '../../../infrastructure/http/HttpClient';\nimport { TokenCache } from '../../../infrastructure/cache/TokenCache';\nimport { Logger } from '../../../infrastructure/logger/Logger';\nimport { WechatError } from '../../../errors/WechatError';\nimport { WECHAT_API_BASE, WECHAT_API_ENDPOINTS } from '../constants';\n\nexport class TokenAPI {\n constructor(\n private appId: string,\n private appSecret: string,\n private httpClient: HttpClient,\n private tokenCache: TokenCache,\n private logger: Logger\n ) {}\n\n async getAccessToken(): Promise<string> {\n const cached = await this.tokenCache.getToken(this.appId);\n if (cached) {\n this.logger.debug('使用缓存的 Access Token', { appId: this.appId });\n return cached;\n }\n\n return await this.refreshAccessToken();\n }\n\n async refreshAccessToken(): Promise<string> {\n this.logger.info('刷新 Access Token', { appId: this.appId });\n\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.TOKEN}`;\n const response = await this.httpClient.get(url, {\n params: {\n grant_type: 'client_credential',\n appid: this.appId,\n secret: this.appSecret,\n },\n });\n\n const data = response.data;\n\n if (data.errcode) {\n throw WechatError.fromResponse(data);\n }\n\n await this.tokenCache.setToken(\n this.appId,\n data.access_token,\n data.expires_in\n );\n\n this.logger.info('Access Token 刷新成功', {\n appId: this.appId,\n expiresIn: data.expires_in,\n });\n\n return data.access_token;\n }\n}\n","import { HttpClient } from '../../../infrastructure/http/HttpClient';\nimport { Logger } from '../../../infrastructure/logger/Logger';\nimport { WechatError } from '../../../errors/WechatError';\nimport { WECHAT_API_BASE, WECHAT_API_ENDPOINTS } from '../constants';\nimport type { Draft, DraftList, DraftArticle } from '../../../types/draft';\n\nexport class DraftAPI {\n constructor(\n private getAccessToken: () => Promise<string>,\n private httpClient: HttpClient,\n private logger: Logger\n ) {}\n\n async create(article: DraftArticle): Promise<{ media_id: string }> {\n this.logger.info('创建草稿', { title: article.title });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.DRAFT_ADD}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n articles: [article],\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n this.logger.info('草稿创建成功', { media_id: data.media_id });\n return { media_id: data.media_id };\n }\n\n async get(mediaId: string): Promise<Draft> {\n this.logger.info('获取草稿详情', { media_id: mediaId });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.DRAFT_GET}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n media_id: mediaId,\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n return data;\n }\n\n async list(offset: number = 0, count: number = 20): Promise<DraftList> {\n this.logger.info('获取草稿列表', { offset, count });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.DRAFT_BATCH_GET}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n offset,\n count,\n no_content: 0,\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n return data;\n }\n\n async delete(mediaId: string): Promise<void> {\n this.logger.info('删除草稿', { media_id: mediaId });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.DRAFT_DELETE}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n media_id: mediaId,\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n this.logger.info('草稿删除成功');\n }\n\n async update(mediaId: string, article: DraftArticle, index: number = 0): Promise<void> {\n this.logger.info('更新草稿', { media_id: mediaId, index });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.DRAFT_UPDATE}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n media_id: mediaId,\n index,\n articles: article,\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n this.logger.info('草稿更新成功');\n }\n\n async count(): Promise<number> {\n this.logger.info('获取草稿总数');\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.DRAFT_COUNT}?access_token=${accessToken}`;\n\n const response = await this.httpClient.get(url);\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n return data.total_count || 0;\n }\n}\n","import { HttpClient } from '../../../infrastructure/http/HttpClient';\nimport { Logger } from '../../../infrastructure/logger/Logger';\nimport { WechatError } from '../../../errors/WechatError';\nimport { WECHAT_API_BASE, WECHAT_API_ENDPOINTS } from '../constants';\nimport type { PublishResult, PublishedArticle, PublishList, PublishStatus } from '../../../types/publish';\n\nexport class PublishAPI {\n constructor(\n private getAccessToken: () => Promise<string>,\n private httpClient: HttpClient,\n private logger: Logger\n ) {}\n\n async submit(mediaId: string): Promise<PublishResult> {\n this.logger.info('发布草稿', { media_id: mediaId });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.PUBLISH_SUBMIT}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n media_id: mediaId,\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n this.logger.info('发布任务提交成功', { publish_id: data.publish_id });\n return {\n publish_id: data.publish_id,\n msg_data_id: data.msg_data_id,\n };\n }\n\n async get(articleId: string): Promise<PublishedArticle> {\n this.logger.info('获取已发布文章详情', { article_id: articleId });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.PUBLISH_GET}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n article_id: articleId,\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n return data;\n }\n\n async list(offset: number = 0, count: number = 20): Promise<PublishList> {\n this.logger.info('获取已发布文章列表', { offset, count });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.PUBLISH_BATCH_GET}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n offset,\n count,\n no_content: 0,\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n return data;\n }\n\n async delete(articleId: string, index: number = 0): Promise<void> {\n this.logger.info('删除已发布文章', { article_id: articleId, index });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.PUBLISH_DELETE}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n article_id: articleId,\n index,\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n this.logger.info('已发布文章删除成功');\n }\n\n async getStatus(publishId: string): Promise<PublishStatus> {\n this.logger.info('获取发布状态', { publish_id: publishId });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.PUBLISH_GET_STATUS}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n publish_id: publishId,\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n return data;\n }\n}\n","import { HttpClient } from '../../../infrastructure/http/HttpClient';\nimport { Logger } from '../../../infrastructure/logger/Logger';\nimport { WechatError } from '../../../errors/WechatError';\nimport { WECHAT_API_BASE, WECHAT_API_ENDPOINTS } from '../constants';\n\nexport interface UploadResult {\n media_id: string;\n url: string;\n}\n\nexport class MaterialAPI {\n constructor(\n private getAccessToken: () => Promise<string>,\n private httpClient: HttpClient,\n private logger: Logger\n ) {}\n\n async uploadImage(file: Buffer, filename: string): Promise<UploadResult> {\n this.logger.info('上传图片', { filename });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.MATERIAL_ADD}?access_token=${accessToken}&type=image`;\n\n const formData = new FormData();\n const blob = new Blob([file]);\n formData.append('media', blob, filename);\n\n const response = await this.httpClient.post(url, formData, {\n headers: {\n 'Content-Type': 'multipart/form-data',\n },\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n if (data.url && data.url.startsWith('http://')) {\n data.url = data.url.replace(/^http:\\/\\//i, 'https://');\n }\n\n this.logger.info('图片上传成功', { media_id: data.media_id });\n return {\n media_id: data.media_id,\n url: data.url,\n };\n }\n\n async uploadThumb(file: Buffer, filename: string): Promise<UploadResult> {\n this.logger.info('上传封面图', { filename });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.MATERIAL_ADD}?access_token=${accessToken}&type=thumb`;\n\n const formData = new FormData();\n const blob = new Blob([file]);\n formData.append('media', blob, filename);\n\n const response = await this.httpClient.post(url, formData, {\n headers: {\n 'Content-Type': 'multipart/form-data',\n },\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n if (data.url && data.url.startsWith('http://')) {\n data.url = data.url.replace(/^http:\\/\\//i, 'https://');\n }\n\n this.logger.info('封面图上传成功', { media_id: data.media_id });\n return {\n media_id: data.media_id,\n url: data.url,\n };\n }\n\n async getMaterialCount(): Promise<{ voice_count: number; video_count: number; image_count: number; news_count: number }> {\n this.logger.info('获取素材总数');\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.MATERIAL_COUNT}?access_token=${accessToken}`;\n\n const response = await this.httpClient.get(url);\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n return data;\n }\n}\n","import { TokenAPI } from './api/TokenAPI';\nimport { DraftAPI } from './api/DraftAPI';\nimport { PublishAPI } from './api/PublishAPI';\nimport { MaterialAPI } from './api/MaterialAPI';\nimport { HttpClient } from '../../infrastructure/http/HttpClient';\nimport { TokenCache } from '../../infrastructure/cache/TokenCache';\nimport { Logger } from '../../infrastructure/logger/Logger';\n\nexport class WechatClient {\n public readonly token: TokenAPI;\n public readonly draft: DraftAPI;\n public readonly publish: PublishAPI;\n public readonly material: MaterialAPI;\n\n constructor(\n private appId: string,\n appSecret: string,\n httpClient: HttpClient,\n tokenCache: TokenCache,\n logger: Logger\n ) {\n this.token = new TokenAPI(appId, appSecret, httpClient, tokenCache, logger);\n \n const getAccessToken = () => this.token.getAccessToken();\n \n this.draft = new DraftAPI(getAccessToken, httpClient, logger);\n this.publish = new PublishAPI(getAccessToken, httpClient, logger);\n this.material = new MaterialAPI(getAccessToken, httpClient, logger);\n }\n\n async getAccessToken(): Promise<string> {\n return await this.token.getAccessToken();\n }\n\n async refreshAccessToken(): Promise<string> {\n return await this.token.refreshAccessToken();\n }\n\n getAppId(): string {\n return this.appId;\n }\n}\n","import { BaseError } from './BaseError';\n\nexport class ThemeError extends BaseError {\n constructor(message: string, details?: any) {\n super(message, 'THEME_ERROR', 500, details);\n }\n}\n\nexport class ThemeNotFoundError extends BaseError {\n constructor(themeId: string) {\n super(`主题不存在: ${themeId}`, 'THEME_NOT_FOUND', 404, { themeId });\n }\n}\n\nexport class ThemeLoadError extends BaseError {\n constructor(themeId: string, reason: string) {\n super(`主题加载失败: ${themeId} - ${reason}`, 'THEME_LOAD_ERROR', 500, { themeId, reason });\n }\n}\n","import { readFile } from 'fs/promises';\nimport type { Theme } from '../../../types/theme';\nimport { ThemeLoadError } from '../../../errors/ThemeError';\n\nexport class LocalLoader {\n async load(name: string, path: string): Promise<Theme> {\n try {\n const css = await readFile(path, 'utf-8');\n \n return {\n id: name,\n name,\n type: 'local',\n description: `本地主题: ${path}`,\n getCss: async () => css,\n };\n } catch (error) {\n throw new ThemeLoadError(name, `无法读取文件: ${path}`);\n }\n }\n}\n","import axios from 'axios';\nimport type { Theme, ThemeSource, RemoteThemeConfig } from '../../../types/theme';\nimport { ThemeLoadError } from '../../../errors/ThemeError';\n\nexport class RemoteLoader {\n private configs: Map<string, RemoteThemeConfig> = new Map();\n\n async addAPI(name: string, apiUrl: string, apiKey: string): Promise<void> {\n this.configs.set(name, {\n name,\n apiUrl,\n apiKey,\n enabled: true,\n });\n }\n\n async load(themeId: string): Promise<Theme | null> {\n for (const [name, config] of this.configs) {\n if (!config.enabled) continue;\n\n try {\n const css = await this.fetchThemeCSS(config.apiUrl, config.apiKey, themeId);\n if (css) {\n return {\n id: themeId,\n name: `${name}:${themeId}`,\n type: 'remote',\n description: `远程主题来自 ${name}`,\n getCss: async () => css,\n };\n }\n } catch (error) {\n continue;\n }\n }\n\n return null;\n }\n\n async list(): Promise<ThemeSource[]> {\n const themes: ThemeSource[] = [];\n\n for (const [name, config] of this.configs) {\n if (!config.enabled) continue;\n\n try {\n const themeList = await this.fetchThemeList(config.apiUrl, config.apiKey);\n for (const themeId of themeList) {\n themes.push({\n type: 'remote',\n id: themeId,\n name: `${name}:${themeId}`,\n description: `远程主题来自 ${name}`,\n });\n }\n } catch (error) {\n continue;\n }\n }\n\n return themes;\n }\n\n getConfig(): RemoteThemeConfig[] {\n return Array.from(this.configs.values());\n }\n\n private async fetchThemeList(apiUrl: string, apiKey: string): Promise<string[]> {\n try {\n const response = await axios.get(`${apiUrl}/themes`, {\n headers: {\n 'X-API-Key': apiKey,\n },\n });\n return response.data.themes || [];\n } catch (error) {\n throw new ThemeLoadError('remote', '无法获取远程主题列表');\n }\n }\n\n private async fetchThemeCSS(apiUrl: string, apiKey: string, themeId: string): Promise<string | null> {\n try {\n const response = await axios.get(`${apiUrl}/themes/${themeId}`, {\n headers: {\n 'X-API-Key': apiKey,\n },\n });\n return response.data.css || null;\n } catch (error) {\n return null;\n }\n }\n}\n","import { readFile } from 'fs/promises';\nimport { join, dirname } from 'path';\nimport { createRequire } from 'module';\nimport type { Theme } from '../../../types/theme';\n\n// Use require to get the package's directory at runtime\nconst require = createRequire(import.meta.url);\n// require.resolve points to dist/index.js, so we need to go up to package root\nconst packageRoot = dirname(dirname(require.resolve('wechat-md-publisher')));\n\nconsole.log('[BuiltinLoader] packageRoot:', packageRoot);\n\n// Only use the 6 themes in themes/builtin/ folder\nconst LOCAL_THEMES = [\n { id: 'default', name: '默认主题', description: '简洁清爽的默认样式,适合各类文章' },\n { id: 'orangesun', name: 'Orange Sun', description: 'A warm and bright theme with orange sunshine vibes.' },\n { id: 'redruby', name: 'Red Ruby', description: 'An elegant theme with bold ruby red accents.' },\n { id: 'greenmint', name: 'Green Mint', description: 'A fresh and calming mint green theme.' },\n { id: 'purplerain', name: 'Purple Rain', description: 'A dreamy purple theme with soft gradients.' },\n { id: 'blackink', name: 'Black Ink', description: 'A dark mode theme with indigo accents for night reading.' },\n];\n\nexport class BuiltinLoader {\n async loadAll(): Promise<Theme[]> {\n const themes: Theme[] = [];\n\n // FIXED: Only load LOCAL_THEMES that have matching CSS files\n for (const themeInfo of LOCAL_THEMES) {\n try {\n const themePath = join(packageRoot, 'themes', 'builtin', `${themeInfo.id}.css`);\n const css = await readFile(themePath, 'utf-8');\n\n themes.push({\n id: themeInfo.id,\n name: themeInfo.name,\n type: 'builtin',\n description: themeInfo.description,\n getCss: async () => css,\n });\n } catch (error) {\n console.warn(`[BuiltinLoader] Failed to load theme \"${themeInfo.id}\":`, error instanceof Error ? error.message : error);\n continue;\n }\n }\n\n return themes;\n }\n}\n","import type { Theme, ThemeSource } from '../../types/theme';\n\nexport class ThemeRegistry {\n private themes: Map<string, Theme> = new Map();\n\n register(theme: Theme): void {\n this.themes.set(theme.id, theme);\n }\n\n get(id: string): Theme | undefined {\n return this.themes.get(id);\n }\n\n has(id: string): boolean {\n return this.themes.has(id);\n }\n\n remove(id: string): void {\n this.themes.delete(id);\n }\n\n list(): ThemeSource[] {\n return Array.from(this.themes.values()).map(theme => ({\n type: theme.type,\n id: theme.id,\n name: theme.name,\n description: theme.description,\n }));\n }\n\n getLocalThemes(): ThemeSource[] {\n return this.list().filter(t => t.type === 'local');\n }\n\n clear(): void {\n this.themes.clear();\n }\n}\n","import { LocalLoader } from './loaders/LocalLoader';\nimport { RemoteLoader } from './loaders/RemoteLoader';\nimport { BuiltinLoader } from './loaders/BuiltinLoader';\nimport { ThemeRegistry } from './registry';\nimport { ThemeNotFoundError } from '../../errors/ThemeError';\nimport type { ThemeSource } from '../../types/theme';\n\nexport class ThemeEngine {\n private registry: ThemeRegistry;\n private localLoader: LocalLoader;\n private remoteLoader: RemoteLoader;\n private builtinLoader: BuiltinLoader;\n\n constructor() {\n this.registry = new ThemeRegistry();\n this.localLoader = new LocalLoader();\n this.remoteLoader = new RemoteLoader();\n this.builtinLoader = new BuiltinLoader();\n }\n\n async loadBuiltinThemes(): Promise<void> {\n const themes = await this.builtinLoader.loadAll();\n for (const theme of themes) {\n this.registry.register(theme);\n }\n }\n\n async addLocalTheme(name: string, path: string): Promise<void> {\n const theme = await this.localLoader.load(name, path);\n this.registry.register(theme);\n }\n\n async addRemoteAPI(name: string, apiUrl: string, apiKey: string): Promise<void> {\n await this.remoteLoader.addAPI(name, apiUrl, apiKey);\n }\n\n async getThemeCSS(themeId: string): Promise<string> {\n const theme = this.registry.get(themeId);\n if (theme) {\n return await theme.getCss();\n }\n\n const remoteTheme = await this.remoteLoader.load(themeId);\n if (remoteTheme) {\n return await remoteTheme.getCss();\n }\n\n throw new ThemeNotFoundError(themeId);\n }\n\n async listThemes(): Promise<ThemeSource[]> {\n const themes: ThemeSource[] = [];\n \n themes.push(...this.registry.list());\n \n themes.push(...await this.remoteLoader.list());\n\n return themes;\n }\n\n async removeTheme(themeId: string): Promise<void> {\n this.registry.remove(themeId);\n }\n\n async getConfig(): Promise<any> {\n return {\n local: this.registry.getLocalThemes(),\n remote: this.remoteLoader.getConfig(),\n };\n }\n}\n","import { createWenyanCore } from '@wenyan-md/core';\nimport type { ApplyStylesOptions } from '@wenyan-md/core';\nimport { JSDOM } from 'jsdom';\n\nexport interface RenderResult {\n title: string;\n content: string;\n cover?: string;\n}\n\nexport class MarkdownRenderer {\n private wenyan: any;\n\n async initialize(): Promise<void> {\n this.wenyan = await createWenyanCore({\n isConvertMathJax: true,\n isWechat: true,\n });\n }\n\n async render(markdown: string, themeCss?: string): Promise<RenderResult> {\n if (!this.wenyan) {\n await this.initialize();\n }\n\n const result = await this.wenyan.handleFrontMatter(markdown);\n \n if (!result || !result.body) {\n throw new Error('Invalid markdown: handleFrontMatter returned empty data');\n }\n \n const html = await this.wenyan.renderMarkdown(result.body);\n\n const dom = new JSDOM(html);\n const document = dom.window.document;\n const wenyanElement = document.createElement('div');\n wenyanElement.id = 'wenyan';\n wenyanElement.innerHTML = html;\n\n const options: ApplyStylesOptions = {\n themeCss,\n isMacStyle: true,\n isAddFootnote: false,\n };\n\n const styledHtml = await this.wenyan.applyStylesWithTheme(wenyanElement, options);\n\n return {\n title: result.title || '',\n content: styledHtml,\n cover: result.cover,\n };\n }\n}\n","import Conf from 'conf';\nimport { z } from 'zod';\nimport type { Config } from '../../types/config';\n\nconst AccountSchema = z.object({\n id: z.string(),\n name: z.string(),\n appId: z.string().regex(/^wx[a-zA-Z0-9]{16}$/, '无效的 AppID 格式'),\n appSecret: z.string().min(32, 'AppSecret 长度不足'),\n isDefault: z.boolean().optional(),\n createdAt: z.date().optional(),\n updatedAt: z.date().optional(),\n});\n\nexport class ConfigStore {\n private store: Conf<Config>;\n\n constructor() {\n this.store = new Conf<Config>({\n projectName: 'wechat-md-publisher',\n });\n }\n\n get<K extends keyof Config>(key: K): Config[K] | undefined;\n get<K extends keyof Config>(key: K, defaultValue: Config[K]): Config[K];\n get<K extends keyof Config>(key: K, defaultValue?: Config[K]): Config[K] | undefined {\n return this.store.get(key, defaultValue as any);\n }\n\n set<K extends keyof Config>(key: K, value: Config[K]): void {\n if (key === 'accounts') {\n z.array(AccountSchema).parse(value);\n }\n this.store.set(key, value);\n }\n\n has(key: keyof Config): boolean {\n return this.store.has(key);\n }\n\n delete(key: keyof Config): void {\n this.store.delete(key);\n }\n\n clear(): void {\n this.store.clear();\n }\n\n getAll(): Config {\n return this.store.store;\n }\n\n getPath(): string {\n return this.store.path;\n }\n}\n","import winston from 'winston';\n\nexport class Logger {\n private logger: winston.Logger;\n\n constructor() {\n this.logger = winston.createLogger({\n level: process.env.LOG_LEVEL || 'info',\n format: winston.format.combine(\n winston.format.timestamp(),\n winston.format.errors({ stack: true }),\n winston.format.json()\n ),\n transports: [\n new winston.transports.Console({\n format: winston.format.combine(\n winston.format.colorize(),\n winston.format.printf(({ level, message, timestamp, ...meta }) => {\n const metaStr = Object.keys(meta).length ? JSON.stringify(meta) : '';\n return `${timestamp} [${level}]: ${message} ${metaStr}`;\n })\n ),\n }),\n ],\n });\n }\n\n debug(message: string, meta?: any): void {\n this.logger.debug(message, meta);\n }\n\n info(message: string, meta?: any): void {\n this.logger.info(message, meta);\n }\n\n warn(message: string, meta?: any): void {\n this.logger.warn(message, meta);\n }\n\n error(message: string, meta?: any): void {\n this.logger.error(message, meta);\n }\n}\n"],"names":["require"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Logger-CRPQmRrm.js","sources":["../src/errors/BaseError.ts","../src/errors/WechatError.ts","../src/core/wechat/constants.ts","../src/core/wechat/api/TokenAPI.ts","../src/core/wechat/api/DraftAPI.ts","../src/core/wechat/api/PublishAPI.ts","../src/core/wechat/api/MaterialAPI.ts","../src/core/wechat/WechatClient.ts","../src/errors/ThemeError.ts","../src/core/theme/loaders/LocalLoader.ts","../src/core/theme/loaders/RemoteLoader.ts","../src/core/theme/loaders/BuiltinLoader.ts","../src/core/theme/registry.ts","../src/core/theme/ThemeEngine.ts","../src/core/renderer/MarkdownRenderer.ts","../src/infrastructure/config/ConfigStore.ts","../src/infrastructure/logger/Logger.ts"],"sourcesContent":["export class BaseError extends Error {\n constructor(\n message: string,\n public code: string,\n public statusCode: number = 500,\n public details?: any\n ) {\n super(message);\n this.name = this.constructor.name;\n Error.captureStackTrace(this, this.constructor);\n }\n\n toJSON() {\n return {\n name: this.name,\n message: this.message,\n code: this.code,\n statusCode: this.statusCode,\n details: this.details,\n };\n }\n}\n","import { BaseError } from './BaseError';\n\nexport class WechatError extends BaseError {\n constructor(\n message: string,\n public errcode: number,\n public errmsg: string\n ) {\n super(message, 'WECHAT_API_ERROR', 500, { errcode, errmsg });\n }\n\n static fromResponse(data: { errcode: number; errmsg: string }): WechatError {\n return new WechatError(\n `微信 API 错误: ${data.errmsg} (${data.errcode})`,\n data.errcode,\n data.errmsg\n );\n }\n}\n\nexport class WechatAuthError extends BaseError {\n constructor(message: string) {\n super(message, 'WECHAT_AUTH_ERROR', 401);\n }\n}\n\nexport class WechatRateLimitError extends BaseError {\n constructor(message: string) {\n super(message, 'WECHAT_RATE_LIMIT_ERROR', 429);\n }\n}\n","export const WECHAT_API_BASE = 'https://api.weixin.qq.com';\n\nexport const WECHAT_API_ENDPOINTS = {\n TOKEN: '/cgi-bin/token',\n DRAFT_ADD: '/cgi-bin/draft/add',\n DRAFT_GET: '/cgi-bin/draft/get',\n DRAFT_DELETE: '/cgi-bin/draft/delete',\n DRAFT_UPDATE: '/cgi-bin/draft/update',\n DRAFT_BATCH_GET: '/cgi-bin/draft/batchget',\n DRAFT_COUNT: '/cgi-bin/draft/count',\n PUBLISH_SUBMIT: '/cgi-bin/freepublish/submit',\n PUBLISH_GET: '/cgi-bin/freepublish/get',\n PUBLISH_DELETE: '/cgi-bin/freepublish/delete',\n PUBLISH_BATCH_GET: '/cgi-bin/freepublish/batchget',\n PUBLISH_GET_STATUS: '/cgi-bin/freepublish/get',\n MATERIAL_ADD: '/cgi-bin/material/add_material',\n MATERIAL_GET: '/cgi-bin/material/get_material',\n MATERIAL_DELETE: '/cgi-bin/material/del_material',\n MATERIAL_BATCH_GET: '/cgi-bin/material/batchget_material',\n MATERIAL_COUNT: '/cgi-bin/material/get_materialcount',\n} as const;\n\nexport const WECHAT_ERROR_CODES = {\n SUCCESS: 0,\n INVALID_CREDENTIAL: 40001,\n ACCESS_TOKEN_EXPIRED: 42001,\n RATE_LIMIT_EXCEEDED: 45009,\n API_UNAUTHORIZED: 48001,\n} as const;\n","import { HttpClient } from '../../../infrastructure/http/HttpClient';\nimport { TokenCache } from '../../../infrastructure/cache/TokenCache';\nimport { Logger } from '../../../infrastructure/logger/Logger';\nimport { WechatError } from '../../../errors/WechatError';\nimport { WECHAT_API_BASE, WECHAT_API_ENDPOINTS } from '../constants';\n\nexport class TokenAPI {\n constructor(\n private appId: string,\n private appSecret: string,\n private httpClient: HttpClient,\n private tokenCache: TokenCache,\n private logger: Logger\n ) {}\n\n async getAccessToken(): Promise<string> {\n const cached = await this.tokenCache.getToken(this.appId);\n if (cached) {\n this.logger.debug('使用缓存的 Access Token', { appId: this.appId });\n return cached;\n }\n\n return await this.refreshAccessToken();\n }\n\n async refreshAccessToken(): Promise<string> {\n this.logger.info('刷新 Access Token', { appId: this.appId });\n\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.TOKEN}`;\n const response = await this.httpClient.get(url, {\n params: {\n grant_type: 'client_credential',\n appid: this.appId,\n secret: this.appSecret,\n },\n });\n\n const data = response.data;\n\n if (data.errcode) {\n throw WechatError.fromResponse(data);\n }\n\n await this.tokenCache.setToken(\n this.appId,\n data.access_token,\n data.expires_in\n );\n\n this.logger.info('Access Token 刷新成功', {\n appId: this.appId,\n expiresIn: data.expires_in,\n });\n\n return data.access_token;\n }\n}\n","import { HttpClient } from '../../../infrastructure/http/HttpClient';\nimport { Logger } from '../../../infrastructure/logger/Logger';\nimport { WechatError } from '../../../errors/WechatError';\nimport { WECHAT_API_BASE, WECHAT_API_ENDPOINTS } from '../constants';\nimport type { Draft, DraftList, DraftArticle } from '../../../types/draft';\n\nexport class DraftAPI {\n constructor(\n private getAccessToken: () => Promise<string>,\n private httpClient: HttpClient,\n private logger: Logger\n ) {}\n\n async create(article: DraftArticle): Promise<{ media_id: string }> {\n this.logger.info('创建草稿', { title: article.title });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.DRAFT_ADD}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n articles: [article],\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n this.logger.info('草稿创建成功', { media_id: data.media_id });\n return { media_id: data.media_id };\n }\n\n async get(mediaId: string): Promise<Draft> {\n this.logger.info('获取草稿详情', { media_id: mediaId });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.DRAFT_GET}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n media_id: mediaId,\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n return data;\n }\n\n async list(offset: number = 0, count: number = 20): Promise<DraftList> {\n this.logger.info('获取草稿列表', { offset, count });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.DRAFT_BATCH_GET}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n offset,\n count,\n no_content: 0,\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n return data;\n }\n\n async delete(mediaId: string): Promise<void> {\n this.logger.info('删除草稿', { media_id: mediaId });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.DRAFT_DELETE}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n media_id: mediaId,\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n this.logger.info('草稿删除成功');\n }\n\n async update(mediaId: string, article: DraftArticle, index: number = 0): Promise<void> {\n this.logger.info('更新草稿', { media_id: mediaId, index });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.DRAFT_UPDATE}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n media_id: mediaId,\n index,\n articles: article,\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n this.logger.info('草稿更新成功');\n }\n\n async count(): Promise<number> {\n this.logger.info('获取草稿总数');\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.DRAFT_COUNT}?access_token=${accessToken}`;\n\n const response = await this.httpClient.get(url);\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n return data.total_count || 0;\n }\n}\n","import { HttpClient } from '../../../infrastructure/http/HttpClient';\nimport { Logger } from '../../../infrastructure/logger/Logger';\nimport { WechatError } from '../../../errors/WechatError';\nimport { WECHAT_API_BASE, WECHAT_API_ENDPOINTS } from '../constants';\nimport type { PublishResult, PublishedArticle, PublishList, PublishStatus } from '../../../types/publish';\n\nexport class PublishAPI {\n constructor(\n private getAccessToken: () => Promise<string>,\n private httpClient: HttpClient,\n private logger: Logger\n ) {}\n\n async submit(mediaId: string): Promise<PublishResult> {\n this.logger.info('发布草稿', { media_id: mediaId });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.PUBLISH_SUBMIT}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n media_id: mediaId,\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n this.logger.info('发布任务提交成功', { publish_id: data.publish_id });\n return {\n publish_id: data.publish_id,\n msg_data_id: data.msg_data_id,\n };\n }\n\n async get(articleId: string): Promise<PublishedArticle> {\n this.logger.info('获取已发布文章详情', { article_id: articleId });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.PUBLISH_GET}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n article_id: articleId,\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n return data;\n }\n\n async list(offset: number = 0, count: number = 20): Promise<PublishList> {\n this.logger.info('获取已发布文章列表', { offset, count });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.PUBLISH_BATCH_GET}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n offset,\n count,\n no_content: 0,\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n return data;\n }\n\n async delete(articleId: string, index: number = 0): Promise<void> {\n this.logger.info('删除已发布文章', { article_id: articleId, index });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.PUBLISH_DELETE}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n article_id: articleId,\n index,\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n this.logger.info('已发布文章删除成功');\n }\n\n async getStatus(publishId: string): Promise<PublishStatus> {\n this.logger.info('获取发布状态', { publish_id: publishId });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.PUBLISH_GET_STATUS}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n publish_id: publishId,\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n return data;\n }\n}\n","import { HttpClient } from '../../../infrastructure/http/HttpClient';\nimport { Logger } from '../../../infrastructure/logger/Logger';\nimport { WechatError } from '../../../errors/WechatError';\nimport { WECHAT_API_BASE, WECHAT_API_ENDPOINTS } from '../constants';\n\nexport interface UploadResult {\n media_id: string;\n url: string;\n}\n\nexport class MaterialAPI {\n constructor(\n private getAccessToken: () => Promise<string>,\n private httpClient: HttpClient,\n private logger: Logger\n ) {}\n\n async uploadImage(file: Buffer, filename: string): Promise<UploadResult> {\n this.logger.info('上传图片', { filename });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.MATERIAL_ADD}?access_token=${accessToken}&type=image`;\n\n const formData = new FormData();\n const blob = new Blob([file]);\n formData.append('media', blob, filename);\n\n const response = await this.httpClient.post(url, formData, {\n headers: {\n 'Content-Type': 'multipart/form-data',\n },\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n if (data.url && data.url.startsWith('http://')) {\n data.url = data.url.replace(/^http:\\/\\//i, 'https://');\n }\n\n this.logger.info('图片上传成功', { media_id: data.media_id });\n return {\n media_id: data.media_id,\n url: data.url,\n };\n }\n\n async uploadThumb(file: Buffer, filename: string): Promise<UploadResult> {\n this.logger.info('上传封面图', { filename });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.MATERIAL_ADD}?access_token=${accessToken}&type=thumb`;\n\n const formData = new FormData();\n const blob = new Blob([file]);\n formData.append('media', blob, filename);\n\n const response = await this.httpClient.post(url, formData, {\n headers: {\n 'Content-Type': 'multipart/form-data',\n },\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n if (data.url && data.url.startsWith('http://')) {\n data.url = data.url.replace(/^http:\\/\\//i, 'https://');\n }\n\n this.logger.info('封面图上传成功', { media_id: data.media_id });\n return {\n media_id: data.media_id,\n url: data.url,\n };\n }\n\n async getMaterialCount(): Promise<{ voice_count: number; video_count: number; image_count: number; news_count: number }> {\n this.logger.info('获取素材总数');\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.MATERIAL_COUNT}?access_token=${accessToken}`;\n\n const response = await this.httpClient.get(url);\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n return data;\n }\n}\n","import { TokenAPI } from './api/TokenAPI';\nimport { DraftAPI } from './api/DraftAPI';\nimport { PublishAPI } from './api/PublishAPI';\nimport { MaterialAPI } from './api/MaterialAPI';\nimport { HttpClient } from '../../infrastructure/http/HttpClient';\nimport { TokenCache } from '../../infrastructure/cache/TokenCache';\nimport { Logger } from '../../infrastructure/logger/Logger';\n\nexport class WechatClient {\n public readonly token: TokenAPI;\n public readonly draft: DraftAPI;\n public readonly publish: PublishAPI;\n public readonly material: MaterialAPI;\n\n constructor(\n private appId: string,\n appSecret: string,\n httpClient: HttpClient,\n tokenCache: TokenCache,\n logger: Logger\n ) {\n this.token = new TokenAPI(appId, appSecret, httpClient, tokenCache, logger);\n \n const getAccessToken = () => this.token.getAccessToken();\n \n this.draft = new DraftAPI(getAccessToken, httpClient, logger);\n this.publish = new PublishAPI(getAccessToken, httpClient, logger);\n this.material = new MaterialAPI(getAccessToken, httpClient, logger);\n }\n\n async getAccessToken(): Promise<string> {\n return await this.token.getAccessToken();\n }\n\n async refreshAccessToken(): Promise<string> {\n return await this.token.refreshAccessToken();\n }\n\n getAppId(): string {\n return this.appId;\n }\n}\n","import { BaseError } from './BaseError';\n\nexport class ThemeError extends BaseError {\n constructor(message: string, details?: any) {\n super(message, 'THEME_ERROR', 500, details);\n }\n}\n\nexport class ThemeNotFoundError extends BaseError {\n constructor(themeId: string) {\n super(`主题不存在: ${themeId}`, 'THEME_NOT_FOUND', 404, { themeId });\n }\n}\n\nexport class ThemeLoadError extends BaseError {\n constructor(themeId: string, reason: string) {\n super(`主题加载失败: ${themeId} - ${reason}`, 'THEME_LOAD_ERROR', 500, { themeId, reason });\n }\n}\n","import { readFile } from 'fs/promises';\nimport type { Theme } from '../../../types/theme';\nimport { ThemeLoadError } from '../../../errors/ThemeError';\n\nexport class LocalLoader {\n async load(name: string, path: string): Promise<Theme> {\n try {\n const css = await readFile(path, 'utf-8');\n \n return {\n id: name,\n name,\n type: 'local',\n description: `本地主题: ${path}`,\n getCss: async () => css,\n };\n } catch (error) {\n throw new ThemeLoadError(name, `无法读取文件: ${path}`);\n }\n }\n}\n","import axios from 'axios';\nimport type { Theme, ThemeSource, RemoteThemeConfig } from '../../../types/theme';\nimport { ThemeLoadError } from '../../../errors/ThemeError';\n\nexport class RemoteLoader {\n private configs: Map<string, RemoteThemeConfig> = new Map();\n\n async addAPI(name: string, apiUrl: string, apiKey: string): Promise<void> {\n this.configs.set(name, {\n name,\n apiUrl,\n apiKey,\n enabled: true,\n });\n }\n\n async load(themeId: string): Promise<Theme | null> {\n for (const [name, config] of this.configs) {\n if (!config.enabled) continue;\n\n try {\n const css = await this.fetchThemeCSS(config.apiUrl, config.apiKey, themeId);\n if (css) {\n return {\n id: themeId,\n name: `${name}:${themeId}`,\n type: 'remote',\n description: `远程主题来自 ${name}`,\n getCss: async () => css,\n };\n }\n } catch (error) {\n continue;\n }\n }\n\n return null;\n }\n\n async list(): Promise<ThemeSource[]> {\n const themes: ThemeSource[] = [];\n\n for (const [name, config] of this.configs) {\n if (!config.enabled) continue;\n\n try {\n const themeList = await this.fetchThemeList(config.apiUrl, config.apiKey);\n for (const themeId of themeList) {\n themes.push({\n type: 'remote',\n id: themeId,\n name: `${name}:${themeId}`,\n description: `远程主题来自 ${name}`,\n });\n }\n } catch (error) {\n continue;\n }\n }\n\n return themes;\n }\n\n getConfig(): RemoteThemeConfig[] {\n return Array.from(this.configs.values());\n }\n\n private async fetchThemeList(apiUrl: string, apiKey: string): Promise<string[]> {\n try {\n const response = await axios.get(`${apiUrl}/themes`, {\n headers: {\n 'X-API-Key': apiKey,\n },\n });\n return response.data.themes || [];\n } catch (error) {\n throw new ThemeLoadError('remote', '无法获取远程主题列表');\n }\n }\n\n private async fetchThemeCSS(apiUrl: string, apiKey: string, themeId: string): Promise<string | null> {\n try {\n const response = await axios.get(`${apiUrl}/themes/${themeId}`, {\n headers: {\n 'X-API-Key': apiKey,\n },\n });\n return response.data.css || null;\n } catch (error) {\n return null;\n }\n }\n}\n","import { readFile } from 'fs/promises';\nimport { join, dirname } from 'path';\nimport { createRequire } from 'module';\nimport type { Theme } from '../../../types/theme';\n\n// Use require to get the package's directory at runtime\nconst require = createRequire(import.meta.url);\n// require.resolve points to dist/index.js, so we need to go up to package root\nconst packageRoot = dirname(dirname(require.resolve('wechat-md-publisher')));\n\nconsole.log('[BuiltinLoader] packageRoot:', packageRoot);\n\n// Only use the 6 themes in themes/builtin/ folder\nconst LOCAL_THEMES = [\n { id: 'default', name: '默认主题', description: '简洁清爽的默认样式,适合各类文章' },\n { id: 'orangesun', name: 'Orange Sun', description: 'A warm and bright theme with orange sunshine vibes.' },\n { id: 'redruby', name: 'Red Ruby', description: 'An elegant theme with bold ruby red accents.' },\n { id: 'greenmint', name: 'Green Mint', description: 'A fresh and calming mint green theme.' },\n { id: 'purplerain', name: 'Purple Rain', description: 'A dreamy purple theme with soft gradients.' },\n { id: 'blackink', name: 'Black Ink', description: 'A dark mode theme with indigo accents for night reading.' },\n];\n\nexport class BuiltinLoader {\n async loadAll(): Promise<Theme[]> {\n const themes: Theme[] = [];\n\n // FIXED: Only load LOCAL_THEMES that have matching CSS files\n for (const themeInfo of LOCAL_THEMES) {\n try {\n const themePath = join(packageRoot, 'themes', 'builtin', `${themeInfo.id}.css`);\n const css = await readFile(themePath, 'utf-8');\n\n themes.push({\n id: themeInfo.id,\n name: themeInfo.name,\n type: 'builtin',\n description: themeInfo.description,\n getCss: async () => css,\n });\n } catch (error) {\n console.warn(`[BuiltinLoader] Failed to load theme \"${themeInfo.id}\":`, error instanceof Error ? error.message : error);\n continue;\n }\n }\n\n return themes;\n }\n}\n","import type { Theme, ThemeSource } from '../../types/theme';\n\nexport class ThemeRegistry {\n private themes: Map<string, Theme> = new Map();\n\n register(theme: Theme): void {\n this.themes.set(theme.id, theme);\n }\n\n get(id: string): Theme | undefined {\n return this.themes.get(id);\n }\n\n has(id: string): boolean {\n return this.themes.has(id);\n }\n\n remove(id: string): void {\n this.themes.delete(id);\n }\n\n list(): ThemeSource[] {\n return Array.from(this.themes.values()).map(theme => ({\n type: theme.type,\n id: theme.id,\n name: theme.name,\n description: theme.description,\n }));\n }\n\n getLocalThemes(): ThemeSource[] {\n return this.list().filter(t => t.type === 'local');\n }\n\n clear(): void {\n this.themes.clear();\n }\n}\n","import { LocalLoader } from './loaders/LocalLoader';\nimport { RemoteLoader } from './loaders/RemoteLoader';\nimport { BuiltinLoader } from './loaders/BuiltinLoader';\nimport { ThemeRegistry } from './registry';\nimport { ThemeNotFoundError } from '../../errors/ThemeError';\nimport type { ThemeSource } from '../../types/theme';\n\nexport class ThemeEngine {\n private registry: ThemeRegistry;\n private localLoader: LocalLoader;\n private remoteLoader: RemoteLoader;\n private builtinLoader: BuiltinLoader;\n\n constructor() {\n this.registry = new ThemeRegistry();\n this.localLoader = new LocalLoader();\n this.remoteLoader = new RemoteLoader();\n this.builtinLoader = new BuiltinLoader();\n }\n\n async loadBuiltinThemes(): Promise<void> {\n const themes = await this.builtinLoader.loadAll();\n for (const theme of themes) {\n this.registry.register(theme);\n }\n }\n\n async addLocalTheme(name: string, path: string): Promise<void> {\n const theme = await this.localLoader.load(name, path);\n this.registry.register(theme);\n }\n\n async addRemoteAPI(name: string, apiUrl: string, apiKey: string): Promise<void> {\n await this.remoteLoader.addAPI(name, apiUrl, apiKey);\n }\n\n async getThemeCSS(themeId: string): Promise<string> {\n const theme = this.registry.get(themeId);\n if (theme) {\n return await theme.getCss();\n }\n\n const remoteTheme = await this.remoteLoader.load(themeId);\n if (remoteTheme) {\n return await remoteTheme.getCss();\n }\n\n throw new ThemeNotFoundError(themeId);\n }\n\n async listThemes(): Promise<ThemeSource[]> {\n const themes: ThemeSource[] = [];\n \n themes.push(...this.registry.list());\n \n themes.push(...await this.remoteLoader.list());\n\n return themes;\n }\n\n async removeTheme(themeId: string): Promise<void> {\n this.registry.remove(themeId);\n }\n\n async getConfig(): Promise<any> {\n return {\n local: this.registry.getLocalThemes(),\n remote: this.remoteLoader.getConfig(),\n };\n }\n}\n","import { createWenyanCore } from '@wenyan-md/core';\nimport type { ApplyStylesOptions } from '@wenyan-md/core';\nimport { JSDOM } from 'jsdom';\n\nexport interface RenderResult {\n title: string;\n content: string;\n cover?: string;\n}\n\nexport class MarkdownRenderer {\n private wenyan: any;\n\n async initialize(): Promise<void> {\n this.wenyan = await createWenyanCore({\n isConvertMathJax: true,\n isWechat: true,\n });\n }\n\n async render(markdown: string, themeCss?: string): Promise<RenderResult> {\n if (!this.wenyan) {\n await this.initialize();\n }\n\n const result = await this.wenyan.handleFrontMatter(markdown);\n \n if (!result || !result.body) {\n throw new Error('Invalid markdown: handleFrontMatter returned empty data');\n }\n \n const html = await this.wenyan.renderMarkdown(result.body);\n\n const dom = new JSDOM(html);\n const document = dom.window.document;\n const wenyanElement = document.createElement('div');\n wenyanElement.id = 'wenyan';\n wenyanElement.innerHTML = html;\n\n const options: ApplyStylesOptions = {\n themeCss,\n isMacStyle: true,\n isAddFootnote: false,\n };\n\n const styledHtml = await this.wenyan.applyStylesWithTheme(wenyanElement, options);\n\n return {\n title: result.title || '',\n content: styledHtml,\n cover: result.cover,\n };\n }\n}\n","import Conf from 'conf';\nimport { z } from 'zod';\nimport type { Config } from '../../types/config';\n\nconst AccountSchema = z.object({\n id: z.string(),\n name: z.string(),\n appId: z.string().regex(/^wx[a-zA-Z0-9]{16}$/, '无效的 AppID 格式'),\n appSecret: z.string().min(32, 'AppSecret 长度不足'),\n isDefault: z.boolean().optional(),\n createdAt: z.date().optional(),\n updatedAt: z.date().optional(),\n});\n\nexport class ConfigStore {\n private store: Conf<Config>;\n\n constructor() {\n this.store = new Conf<Config>({\n projectName: 'wechat-md-publisher',\n });\n }\n\n get<K extends keyof Config>(key: K): Config[K] | undefined;\n get<K extends keyof Config>(key: K, defaultValue: Config[K]): Config[K];\n get<K extends keyof Config>(key: K, defaultValue?: Config[K]): Config[K] | undefined {\n return this.store.get(key, defaultValue as any);\n }\n\n set<K extends keyof Config>(key: K, value: Config[K]): void {\n if (key === 'accounts') {\n z.array(AccountSchema).parse(value);\n }\n this.store.set(key, value);\n }\n\n has(key: keyof Config): boolean {\n return this.store.has(key);\n }\n\n delete(key: keyof Config): void {\n this.store.delete(key);\n }\n\n clear(): void {\n this.store.clear();\n }\n\n getAll(): Config {\n return this.store.store;\n }\n\n getPath(): string {\n return this.store.path;\n }\n}\n","import winston from 'winston';\n\nexport class Logger {\n private logger: winston.Logger;\n\n constructor() {\n this.logger = winston.createLogger({\n level: process.env.LOG_LEVEL || 'info',\n format: winston.format.combine(\n winston.format.timestamp(),\n winston.format.errors({ stack: true }),\n winston.format.json()\n ),\n transports: [\n new winston.transports.Console({\n format: winston.format.combine(\n winston.format.colorize(),\n winston.format.printf(({ level, message, timestamp, ...meta }) => {\n const metaStr = Object.keys(meta).length ? JSON.stringify(meta) : '';\n return `${timestamp} [${level}]: ${message} ${metaStr}`;\n })\n ),\n }),\n ],\n });\n }\n\n debug(message: string, meta?: any): void {\n this.logger.debug(message, meta);\n }\n\n info(message: string, meta?: any): void {\n this.logger.info(message, meta);\n }\n\n warn(message: string, meta?: any): void {\n this.logger.warn(message, meta);\n }\n\n error(message: string, meta?: any): void {\n this.logger.error(message, meta);\n }\n}\n"],"names":["require"],"mappings":";;;;;;;;;AAAO,MAAM,kBAAkB,MAAM;AAAA,EACjC,YACI,SACO,MACA,aAAqB,KACrB,SACT;AACE,UAAM,OAAO;AAJN,SAAA,OAAA;AACA,SAAA,aAAA;AACA,SAAA,UAAA;AAGP,SAAK,OAAO,KAAK,YAAY;AAC7B,UAAM,kBAAkB,MAAM,KAAK,WAAW;AAAA,EAClD;AAAA,EAEA,SAAS;AACL,WAAO;AAAA,MACH,MAAM,KAAK;AAAA,MACX,SAAS,KAAK;AAAA,MACd,MAAM,KAAK;AAAA,MACX,YAAY,KAAK;AAAA,MACjB,SAAS,KAAK;AAAA,IAAA;AAAA,EAEtB;AACJ;ACnBO,MAAM,oBAAoB,UAAU;AAAA,EACvC,YACI,SACO,SACA,QACT;AACE,UAAM,SAAS,oBAAoB,KAAK,EAAE,SAAS,QAAQ;AAHpD,SAAA,UAAA;AACA,SAAA,SAAA;AAAA,EAGX;AAAA,EAEA,OAAO,aAAa,MAAwD;AACxE,WAAO,IAAI;AAAA,MACP,cAAc,KAAK,MAAM,KAAK,KAAK,OAAO;AAAA,MAC1C,KAAK;AAAA,MACL,KAAK;AAAA,IAAA;AAAA,EAEb;AACJ;AAEO,MAAM,wBAAwB,UAAU;AAAA,EAC3C,YAAY,SAAiB;AACzB,UAAM,SAAS,qBAAqB,GAAG;AAAA,EAC3C;AACJ;AAEO,MAAM,6BAA6B,UAAU;AAAA,EAChD,YAAY,SAAiB;AACzB,UAAM,SAAS,2BAA2B,GAAG;AAAA,EACjD;AACJ;AC9BO,MAAM,kBAAkB;AAExB,MAAM,uBAAuB;AAAA,EAChC,OAAO;AAAA,EACP,WAAW;AAAA,EACX,WAAW;AAAA,EACX,cAAc;AAAA,EACd,cAAc;AAAA,EACd,iBAAiB;AAAA,EACjB,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,mBAAmB;AAAA,EACnB,oBAAoB;AAAA,EACpB,cAAc;AAAA,EAId,gBAAgB;AACpB;ACdO,MAAM,SAAS;AAAA,EAClB,YACY,OACA,WACA,YACA,YACA,QACV;AALU,SAAA,QAAA;AACA,SAAA,YAAA;AACA,SAAA,aAAA;AACA,SAAA,aAAA;AACA,SAAA,SAAA;AAAA,EACT;AAAA,EAEH,MAAM,iBAAkC;AACpC,UAAM,SAAS,MAAM,KAAK,WAAW,SAAS,KAAK,KAAK;AACxD,QAAI,QAAQ;AACR,WAAK,OAAO,MAAM,sBAAsB,EAAE,OAAO,KAAK,OAAO;AAC7D,aAAO;AAAA,IACX;AAEA,WAAO,MAAM,KAAK,mBAAA;AAAA,EACtB;AAAA,EAEA,MAAM,qBAAsC;AACxC,SAAK,OAAO,KAAK,mBAAmB,EAAE,OAAO,KAAK,OAAO;AAEzD,UAAM,MAAM,GAAG,eAAe,GAAG,qBAAqB,KAAK;AAC3D,UAAM,WAAW,MAAM,KAAK,WAAW,IAAI,KAAK;AAAA,MAC5C,QAAQ;AAAA,QACJ,YAAY;AAAA,QACZ,OAAO,KAAK;AAAA,QACZ,QAAQ,KAAK;AAAA,MAAA;AAAA,IACjB,CACH;AAED,UAAM,OAAO,SAAS;AAEtB,QAAI,KAAK,SAAS;AACd,YAAM,YAAY,aAAa,IAAI;AAAA,IACvC;AAEA,UAAM,KAAK,WAAW;AAAA,MAClB,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,IAAA;AAGT,SAAK,OAAO,KAAK,qBAAqB;AAAA,MAClC,OAAO,KAAK;AAAA,MACZ,WAAW,KAAK;AAAA,IAAA,CACnB;AAED,WAAO,KAAK;AAAA,EAChB;AACJ;AClDO,MAAM,SAAS;AAAA,EAClB,YACY,gBACA,YACA,QACV;AAHU,SAAA,iBAAA;AACA,SAAA,aAAA;AACA,SAAA,SAAA;AAAA,EACT;AAAA,EAEH,MAAM,OAAO,SAAsD;AAC/D,SAAK,OAAO,KAAK,QAAQ,EAAE,OAAO,QAAQ,OAAO;AAEjD,UAAM,cAAc,MAAM,KAAK,eAAA;AAC/B,UAAM,MAAM,GAAG,eAAe,GAAG,qBAAqB,SAAS,iBAAiB,WAAW;AAE3F,UAAM,WAAW,MAAM,KAAK,WAAW,KAAK,KAAK;AAAA,MAC7C,UAAU,CAAC,OAAO;AAAA,IAAA,CACrB;AAED,UAAM,OAAO,SAAS;AAEtB,QAAI,KAAK,WAAW,KAAK,YAAY,GAAG;AACpC,YAAM,YAAY,aAAa,IAAI;AAAA,IACvC;AAEA,SAAK,OAAO,KAAK,UAAU,EAAE,UAAU,KAAK,UAAU;AACtD,WAAO,EAAE,UAAU,KAAK,SAAA;AAAA,EAC5B;AAAA,EAEA,MAAM,IAAI,SAAiC;AACvC,SAAK,OAAO,KAAK,UAAU,EAAE,UAAU,SAAS;AAEhD,UAAM,cAAc,MAAM,KAAK,eAAA;AAC/B,UAAM,MAAM,GAAG,eAAe,GAAG,qBAAqB,SAAS,iBAAiB,WAAW;AAE3F,UAAM,WAAW,MAAM,KAAK,WAAW,KAAK,KAAK;AAAA,MAC7C,UAAU;AAAA,IAAA,CACb;AAED,UAAM,OAAO,SAAS;AAEtB,QAAI,KAAK,WAAW,KAAK,YAAY,GAAG;AACpC,YAAM,YAAY,aAAa,IAAI;AAAA,IACvC;AAEA,WAAO;AAAA,EACX;AAAA,EAEA,MAAM,KAAK,SAAiB,GAAG,QAAgB,IAAwB;AACnE,SAAK,OAAO,KAAK,UAAU,EAAE,QAAQ,OAAO;AAE5C,UAAM,cAAc,MAAM,KAAK,eAAA;AAC/B,UAAM,MAAM,GAAG,eAAe,GAAG,qBAAqB,eAAe,iBAAiB,WAAW;AAEjG,UAAM,WAAW,MAAM,KAAK,WAAW,KAAK,KAAK;AAAA,MAC7C;AAAA,MACA;AAAA,MACA,YAAY;AAAA,IAAA,CACf;AAED,UAAM,OAAO,SAAS;AAEtB,QAAI,KAAK,WAAW,KAAK,YAAY,GAAG;AACpC,YAAM,YAAY,aAAa,IAAI;AAAA,IACvC;AAEA,WAAO;AAAA,EACX;AAAA,EAEA,MAAM,OAAO,SAAgC;AACzC,SAAK,OAAO,KAAK,QAAQ,EAAE,UAAU,SAAS;AAE9C,UAAM,cAAc,MAAM,KAAK,eAAA;AAC/B,UAAM,MAAM,GAAG,eAAe,GAAG,qBAAqB,YAAY,iBAAiB,WAAW;AAE9F,UAAM,WAAW,MAAM,KAAK,WAAW,KAAK,KAAK;AAAA,MAC7C,UAAU;AAAA,IAAA,CACb;AAED,UAAM,OAAO,SAAS;AAEtB,QAAI,KAAK,WAAW,KAAK,YAAY,GAAG;AACpC,YAAM,YAAY,aAAa,IAAI;AAAA,IACvC;AAEA,SAAK,OAAO,KAAK,QAAQ;AAAA,EAC7B;AAAA,EAEA,MAAM,OAAO,SAAiB,SAAuB,QAAgB,GAAkB;AACnF,SAAK,OAAO,KAAK,QAAQ,EAAE,UAAU,SAAS,OAAO;AAErD,UAAM,cAAc,MAAM,KAAK,eAAA;AAC/B,UAAM,MAAM,GAAG,eAAe,GAAG,qBAAqB,YAAY,iBAAiB,WAAW;AAE9F,UAAM,WAAW,MAAM,KAAK,WAAW,KAAK,KAAK;AAAA,MAC7C,UAAU;AAAA,MACV;AAAA,MACA,UAAU;AAAA,IAAA,CACb;AAED,UAAM,OAAO,SAAS;AAEtB,QAAI,KAAK,WAAW,KAAK,YAAY,GAAG;AACpC,YAAM,YAAY,aAAa,IAAI;AAAA,IACvC;AAEA,SAAK,OAAO,KAAK,QAAQ;AAAA,EAC7B;AAAA,EAEA,MAAM,QAAyB;AAC3B,SAAK,OAAO,KAAK,QAAQ;AAEzB,UAAM,cAAc,MAAM,KAAK,eAAA;AAC/B,UAAM,MAAM,GAAG,eAAe,GAAG,qBAAqB,WAAW,iBAAiB,WAAW;AAE7F,UAAM,WAAW,MAAM,KAAK,WAAW,IAAI,GAAG;AAE9C,UAAM,OAAO,SAAS;AAEtB,QAAI,KAAK,WAAW,KAAK,YAAY,GAAG;AACpC,YAAM,YAAY,aAAa,IAAI;AAAA,IACvC;AAEA,WAAO,KAAK,eAAe;AAAA,EAC/B;AACJ;AC3HO,MAAM,WAAW;AAAA,EACpB,YACY,gBACA,YACA,QACV;AAHU,SAAA,iBAAA;AACA,SAAA,aAAA;AACA,SAAA,SAAA;AAAA,EACT;AAAA,EAEH,MAAM,OAAO,SAAyC;AAClD,SAAK,OAAO,KAAK,QAAQ,EAAE,UAAU,SAAS;AAE9C,UAAM,cAAc,MAAM,KAAK,eAAA;AAC/B,UAAM,MAAM,GAAG,eAAe,GAAG,qBAAqB,cAAc,iBAAiB,WAAW;AAEhG,UAAM,WAAW,MAAM,KAAK,WAAW,KAAK,KAAK;AAAA,MAC7C,UAAU;AAAA,IAAA,CACb;AAED,UAAM,OAAO,SAAS;AAEtB,QAAI,KAAK,WAAW,KAAK,YAAY,GAAG;AACpC,YAAM,YAAY,aAAa,IAAI;AAAA,IACvC;AAEA,SAAK,OAAO,KAAK,YAAY,EAAE,YAAY,KAAK,YAAY;AAC5D,WAAO;AAAA,MACH,YAAY,KAAK;AAAA,MACjB,aAAa,KAAK;AAAA,IAAA;AAAA,EAE1B;AAAA,EAEA,MAAM,IAAI,WAA8C;AACpD,SAAK,OAAO,KAAK,aAAa,EAAE,YAAY,WAAW;AAEvD,UAAM,cAAc,MAAM,KAAK,eAAA;AAC/B,UAAM,MAAM,GAAG,eAAe,GAAG,qBAAqB,WAAW,iBAAiB,WAAW;AAE7F,UAAM,WAAW,MAAM,KAAK,WAAW,KAAK,KAAK;AAAA,MAC7C,YAAY;AAAA,IAAA,CACf;AAED,UAAM,OAAO,SAAS;AAEtB,QAAI,KAAK,WAAW,KAAK,YAAY,GAAG;AACpC,YAAM,YAAY,aAAa,IAAI;AAAA,IACvC;AAEA,WAAO;AAAA,EACX;AAAA,EAEA,MAAM,KAAK,SAAiB,GAAG,QAAgB,IAA0B;AACrE,SAAK,OAAO,KAAK,aAAa,EAAE,QAAQ,OAAO;AAE/C,UAAM,cAAc,MAAM,KAAK,eAAA;AAC/B,UAAM,MAAM,GAAG,eAAe,GAAG,qBAAqB,iBAAiB,iBAAiB,WAAW;AAEnG,UAAM,WAAW,MAAM,KAAK,WAAW,KAAK,KAAK;AAAA,MAC7C;AAAA,MACA;AAAA,MACA,YAAY;AAAA,IAAA,CACf;AAED,UAAM,OAAO,SAAS;AAEtB,QAAI,KAAK,WAAW,KAAK,YAAY,GAAG;AACpC,YAAM,YAAY,aAAa,IAAI;AAAA,IACvC;AAEA,WAAO;AAAA,EACX;AAAA,EAEA,MAAM,OAAO,WAAmB,QAAgB,GAAkB;AAC9D,SAAK,OAAO,KAAK,WAAW,EAAE,YAAY,WAAW,OAAO;AAE5D,UAAM,cAAc,MAAM,KAAK,eAAA;AAC/B,UAAM,MAAM,GAAG,eAAe,GAAG,qBAAqB,cAAc,iBAAiB,WAAW;AAEhG,UAAM,WAAW,MAAM,KAAK,WAAW,KAAK,KAAK;AAAA,MAC7C,YAAY;AAAA,MACZ;AAAA,IAAA,CACH;AAED,UAAM,OAAO,SAAS;AAEtB,QAAI,KAAK,WAAW,KAAK,YAAY,GAAG;AACpC,YAAM,YAAY,aAAa,IAAI;AAAA,IACvC;AAEA,SAAK,OAAO,KAAK,WAAW;AAAA,EAChC;AAAA,EAEA,MAAM,UAAU,WAA2C;AACvD,SAAK,OAAO,KAAK,UAAU,EAAE,YAAY,WAAW;AAEpD,UAAM,cAAc,MAAM,KAAK,eAAA;AAC/B,UAAM,MAAM,GAAG,eAAe,GAAG,qBAAqB,kBAAkB,iBAAiB,WAAW;AAEpG,UAAM,WAAW,MAAM,KAAK,WAAW,KAAK,KAAK;AAAA,MAC7C,YAAY;AAAA,IAAA,CACf;AAED,UAAM,OAAO,SAAS;AAEtB,QAAI,KAAK,WAAW,KAAK,YAAY,GAAG;AACpC,YAAM,YAAY,aAAa,IAAI;AAAA,IACvC;AAEA,WAAO;AAAA,EACX;AACJ;ACxGO,MAAM,YAAY;AAAA,EACrB,YACY,gBACA,YACA,QACV;AAHU,SAAA,iBAAA;AACA,SAAA,aAAA;AACA,SAAA,SAAA;AAAA,EACT;AAAA,EAEH,MAAM,YAAY,MAAc,UAAyC;AACrE,SAAK,OAAO,KAAK,QAAQ,EAAE,UAAU;AAErC,UAAM,cAAc,MAAM,KAAK,eAAA;AAC/B,UAAM,MAAM,GAAG,eAAe,GAAG,qBAAqB,YAAY,iBAAiB,WAAW;AAE9F,UAAM,WAAW,IAAI,SAAA;AACrB,UAAM,OAAO,IAAI,KAAK,CAAC,IAAI,CAAC;AAC5B,aAAS,OAAO,SAAS,MAAM,QAAQ;AAEvC,UAAM,WAAW,MAAM,KAAK,WAAW,KAAK,KAAK,UAAU;AAAA,MACvD,SAAS;AAAA,QACL,gBAAgB;AAAA,MAAA;AAAA,IACpB,CACH;AAED,UAAM,OAAO,SAAS;AAEtB,QAAI,KAAK,WAAW,KAAK,YAAY,GAAG;AACpC,YAAM,YAAY,aAAa,IAAI;AAAA,IACvC;AAEA,QAAI,KAAK,OAAO,KAAK,IAAI,WAAW,SAAS,GAAG;AAC5C,WAAK,MAAM,KAAK,IAAI,QAAQ,eAAe,UAAU;AAAA,IACzD;AAEA,SAAK,OAAO,KAAK,UAAU,EAAE,UAAU,KAAK,UAAU;AACtD,WAAO;AAAA,MACH,UAAU,KAAK;AAAA,MACf,KAAK,KAAK;AAAA,IAAA;AAAA,EAElB;AAAA,EAEA,MAAM,YAAY,MAAc,UAAyC;AACrE,SAAK,OAAO,KAAK,SAAS,EAAE,UAAU;AAEtC,UAAM,cAAc,MAAM,KAAK,eAAA;AAC/B,UAAM,MAAM,GAAG,eAAe,GAAG,qBAAqB,YAAY,iBAAiB,WAAW;AAE9F,UAAM,WAAW,IAAI,SAAA;AACrB,UAAM,OAAO,IAAI,KAAK,CAAC,IAAI,CAAC;AAC5B,aAAS,OAAO,SAAS,MAAM,QAAQ;AAEvC,UAAM,WAAW,MAAM,KAAK,WAAW,KAAK,KAAK,UAAU;AAAA,MACvD,SAAS;AAAA,QACL,gBAAgB;AAAA,MAAA;AAAA,IACpB,CACH;AAED,UAAM,OAAO,SAAS;AAEtB,QAAI,KAAK,WAAW,KAAK,YAAY,GAAG;AACpC,YAAM,YAAY,aAAa,IAAI;AAAA,IACvC;AAEA,QAAI,KAAK,OAAO,KAAK,IAAI,WAAW,SAAS,GAAG;AAC5C,WAAK,MAAM,KAAK,IAAI,QAAQ,eAAe,UAAU;AAAA,IACzD;AAEA,SAAK,OAAO,KAAK,WAAW,EAAE,UAAU,KAAK,UAAU;AACvD,WAAO;AAAA,MACH,UAAU,KAAK;AAAA,MACf,KAAK,KAAK;AAAA,IAAA;AAAA,EAElB;AAAA,EAEA,MAAM,mBAAmH;AACrH,SAAK,OAAO,KAAK,QAAQ;AAEzB,UAAM,cAAc,MAAM,KAAK,eAAA;AAC/B,UAAM,MAAM,GAAG,eAAe,GAAG,qBAAqB,cAAc,iBAAiB,WAAW;AAEhG,UAAM,WAAW,MAAM,KAAK,WAAW,IAAI,GAAG;AAE9C,UAAM,OAAO,SAAS;AAEtB,QAAI,KAAK,WAAW,KAAK,YAAY,GAAG;AACpC,YAAM,YAAY,aAAa,IAAI;AAAA,IACvC;AAEA,WAAO;AAAA,EACX;AACJ;AC3FO,MAAM,aAAa;AAAA,EAMtB,YACY,OACR,WACA,YACA,YACA,QACF;AALU,SAAA,QAAA;AAMR,SAAK,QAAQ,IAAI,SAAS,OAAO,WAAW,YAAY,YAAY,MAAM;AAE1E,UAAM,iBAAiB,MAAM,KAAK,MAAM,eAAA;AAExC,SAAK,QAAQ,IAAI,SAAS,gBAAgB,YAAY,MAAM;AAC5D,SAAK,UAAU,IAAI,WAAW,gBAAgB,YAAY,MAAM;AAChE,SAAK,WAAW,IAAI,YAAY,gBAAgB,YAAY,MAAM;AAAA,EACtE;AAAA,EAnBgB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAkBhB,MAAM,iBAAkC;AACpC,WAAO,MAAM,KAAK,MAAM,eAAA;AAAA,EAC5B;AAAA,EAEA,MAAM,qBAAsC;AACxC,WAAO,MAAM,KAAK,MAAM,mBAAA;AAAA,EAC5B;AAAA,EAEA,WAAmB;AACf,WAAO,KAAK;AAAA,EAChB;AACJ;ACvCO,MAAM,mBAAmB,UAAU;AAAA,EACtC,YAAY,SAAiB,SAAe;AACxC,UAAM,SAAS,eAAe,KAAK,OAAO;AAAA,EAC9C;AACJ;AAEO,MAAM,2BAA2B,UAAU;AAAA,EAC9C,YAAY,SAAiB;AACzB,UAAM,UAAU,OAAO,IAAI,mBAAmB,KAAK,EAAE,SAAS;AAAA,EAClE;AACJ;AAEO,MAAM,uBAAuB,UAAU;AAAA,EAC1C,YAAY,SAAiB,QAAgB;AACzC,UAAM,WAAW,OAAO,MAAM,MAAM,IAAI,oBAAoB,KAAK,EAAE,SAAS,OAAA,CAAQ;AAAA,EACxF;AACJ;ACdO,MAAM,YAAY;AAAA,EACrB,MAAM,KAAK,MAAc,MAA8B;AACnD,QAAI;AACA,YAAM,MAAM,MAAM,SAAS,MAAM,OAAO;AAExC,aAAO;AAAA,QACH,IAAI;AAAA,QACJ;AAAA,QACA,MAAM;AAAA,QACN,aAAa,SAAS,IAAI;AAAA,QAC1B,QAAQ,YAAY;AAAA,MAAA;AAAA,IAE5B,SAAS,OAAO;AACZ,YAAM,IAAI,eAAe,MAAM,WAAW,IAAI,EAAE;AAAA,IACpD;AAAA,EACJ;AACJ;AChBO,MAAM,aAAa;AAAA,EACd,8BAA8C,IAAA;AAAA,EAEtD,MAAM,OAAO,MAAc,QAAgB,QAA+B;AACtE,SAAK,QAAQ,IAAI,MAAM;AAAA,MACnB;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS;AAAA,IAAA,CACZ;AAAA,EACL;AAAA,EAEA,MAAM,KAAK,SAAwC;AAC/C,eAAW,CAAC,MAAM,MAAM,KAAK,KAAK,SAAS;AACvC,UAAI,CAAC,OAAO,QAAS;AAErB,UAAI;AACA,cAAM,MAAM,MAAM,KAAK,cAAc,OAAO,QAAQ,OAAO,QAAQ,OAAO;AAC1E,YAAI,KAAK;AACL,iBAAO;AAAA,YACH,IAAI;AAAA,YACJ,MAAM,GAAG,IAAI,IAAI,OAAO;AAAA,YACxB,MAAM;AAAA,YACN,aAAa,UAAU,IAAI;AAAA,YAC3B,QAAQ,YAAY;AAAA,UAAA;AAAA,QAE5B;AAAA,MACJ,SAAS,OAAO;AACZ;AAAA,MACJ;AAAA,IACJ;AAEA,WAAO;AAAA,EACX;AAAA,EAEA,MAAM,OAA+B;AACjC,UAAM,SAAwB,CAAA;AAE9B,eAAW,CAAC,MAAM,MAAM,KAAK,KAAK,SAAS;AACvC,UAAI,CAAC,OAAO,QAAS;AAErB,UAAI;AACA,cAAM,YAAY,MAAM,KAAK,eAAe,OAAO,QAAQ,OAAO,MAAM;AACxE,mBAAW,WAAW,WAAW;AAC7B,iBAAO,KAAK;AAAA,YACR,MAAM;AAAA,YACN,IAAI;AAAA,YACJ,MAAM,GAAG,IAAI,IAAI,OAAO;AAAA,YACxB,aAAa,UAAU,IAAI;AAAA,UAAA,CAC9B;AAAA,QACL;AAAA,MACJ,SAAS,OAAO;AACZ;AAAA,MACJ;AAAA,IACJ;AAEA,WAAO;AAAA,EACX;AAAA,EAEA,YAAiC;AAC7B,WAAO,MAAM,KAAK,KAAK,QAAQ,QAAQ;AAAA,EAC3C;AAAA,EAEA,MAAc,eAAe,QAAgB,QAAmC;AAC5E,QAAI;AACA,YAAM,WAAW,MAAM,MAAM,IAAI,GAAG,MAAM,WAAW;AAAA,QACjD,SAAS;AAAA,UACL,aAAa;AAAA,QAAA;AAAA,MACjB,CACH;AACD,aAAO,SAAS,KAAK,UAAU,CAAA;AAAA,IACnC,SAAS,OAAO;AACZ,YAAM,IAAI,eAAe,UAAU,YAAY;AAAA,IACnD;AAAA,EACJ;AAAA,EAEA,MAAc,cAAc,QAAgB,QAAgB,SAAyC;AACjG,QAAI;AACA,YAAM,WAAW,MAAM,MAAM,IAAI,GAAG,MAAM,WAAW,OAAO,IAAI;AAAA,QAC5D,SAAS;AAAA,UACL,aAAa;AAAA,QAAA;AAAA,MACjB,CACH;AACD,aAAO,SAAS,KAAK,OAAO;AAAA,IAChC,SAAS,OAAO;AACZ,aAAO;AAAA,IACX;AAAA,EACJ;AACJ;ACtFA,MAAMA,YAAU,cAAc,YAAY,GAAG;AAE7C,MAAM,cAAc,QAAQ,QAAQA,UAAQ,QAAQ,qBAAqB,CAAC,CAAC;AAE3E,QAAQ,IAAI,gCAAgC,WAAW;AAGvD,MAAM,eAAe;AAAA,EACjB,EAAE,IAAI,WAAW,MAAM,QAAQ,aAAa,mBAAA;AAAA,EAC5C,EAAE,IAAI,aAAa,MAAM,cAAc,aAAa,sDAAA;AAAA,EACpD,EAAE,IAAI,WAAW,MAAM,YAAY,aAAa,+CAAA;AAAA,EAChD,EAAE,IAAI,aAAa,MAAM,cAAc,aAAa,wCAAA;AAAA,EACpD,EAAE,IAAI,cAAc,MAAM,eAAe,aAAa,6CAAA;AAAA,EACtD,EAAE,IAAI,YAAY,MAAM,aAAa,aAAa,2DAAA;AACtD;AAEO,MAAM,cAAc;AAAA,EACvB,MAAM,UAA4B;AAC9B,UAAM,SAAkB,CAAA;AAGxB,eAAW,aAAa,cAAc;AAClC,UAAI;AACA,cAAM,YAAY,KAAK,aAAa,UAAU,WAAW,GAAG,UAAU,EAAE,MAAM;AAC9E,cAAM,MAAM,MAAM,SAAS,WAAW,OAAO;AAE7C,eAAO,KAAK;AAAA,UACR,IAAI,UAAU;AAAA,UACd,MAAM,UAAU;AAAA,UAChB,MAAM;AAAA,UACN,aAAa,UAAU;AAAA,UACvB,QAAQ,YAAY;AAAA,QAAA,CACvB;AAAA,MACL,SAAS,OAAO;AACZ,gBAAQ,KAAK,yCAAyC,UAAU,EAAE,MAAM,iBAAiB,QAAQ,MAAM,UAAU,KAAK;AACtH;AAAA,MACJ;AAAA,IACJ;AAEA,WAAO;AAAA,EACX;AACJ;AC7CO,MAAM,cAAc;AAAA,EACf,6BAAiC,IAAA;AAAA,EAEzC,SAAS,OAAoB;AACzB,SAAK,OAAO,IAAI,MAAM,IAAI,KAAK;AAAA,EACnC;AAAA,EAEA,IAAI,IAA+B;AAC/B,WAAO,KAAK,OAAO,IAAI,EAAE;AAAA,EAC7B;AAAA,EAEA,IAAI,IAAqB;AACrB,WAAO,KAAK,OAAO,IAAI,EAAE;AAAA,EAC7B;AAAA,EAEA,OAAO,IAAkB;AACrB,SAAK,OAAO,OAAO,EAAE;AAAA,EACzB;AAAA,EAEA,OAAsB;AAClB,WAAO,MAAM,KAAK,KAAK,OAAO,QAAQ,EAAE,IAAI,CAAA,WAAU;AAAA,MAClD,MAAM,MAAM;AAAA,MACZ,IAAI,MAAM;AAAA,MACV,MAAM,MAAM;AAAA,MACZ,aAAa,MAAM;AAAA,IAAA,EACrB;AAAA,EACN;AAAA,EAEA,iBAAgC;AAC5B,WAAO,KAAK,KAAA,EAAO,OAAO,CAAA,MAAK,EAAE,SAAS,OAAO;AAAA,EACrD;AAAA,EAEA,QAAc;AACV,SAAK,OAAO,MAAA;AAAA,EAChB;AACJ;AC9BO,MAAM,YAAY;AAAA,EACb;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAER,cAAc;AACV,SAAK,WAAW,IAAI,cAAA;AACpB,SAAK,cAAc,IAAI,YAAA;AACvB,SAAK,eAAe,IAAI,aAAA;AACxB,SAAK,gBAAgB,IAAI,cAAA;AAAA,EAC7B;AAAA,EAEA,MAAM,oBAAmC;AACrC,UAAM,SAAS,MAAM,KAAK,cAAc,QAAA;AACxC,eAAW,SAAS,QAAQ;AACxB,WAAK,SAAS,SAAS,KAAK;AAAA,IAChC;AAAA,EACJ;AAAA,EAEA,MAAM,cAAc,MAAc,MAA6B;AAC3D,UAAM,QAAQ,MAAM,KAAK,YAAY,KAAK,MAAM,IAAI;AACpD,SAAK,SAAS,SAAS,KAAK;AAAA,EAChC;AAAA,EAEA,MAAM,aAAa,MAAc,QAAgB,QAA+B;AAC5E,UAAM,KAAK,aAAa,OAAO,MAAM,QAAQ,MAAM;AAAA,EACvD;AAAA,EAEA,MAAM,YAAY,SAAkC;AAChD,UAAM,QAAQ,KAAK,SAAS,IAAI,OAAO;AACvC,QAAI,OAAO;AACP,aAAO,MAAM,MAAM,OAAA;AAAA,IACvB;AAEA,UAAM,cAAc,MAAM,KAAK,aAAa,KAAK,OAAO;AACxD,QAAI,aAAa;AACb,aAAO,MAAM,YAAY,OAAA;AAAA,IAC7B;AAEA,UAAM,IAAI,mBAAmB,OAAO;AAAA,EACxC;AAAA,EAEA,MAAM,aAAqC;AACvC,UAAM,SAAwB,CAAA;AAE9B,WAAO,KAAK,GAAG,KAAK,SAAS,MAAM;AAEnC,WAAO,KAAK,GAAG,MAAM,KAAK,aAAa,MAAM;AAE7C,WAAO;AAAA,EACX;AAAA,EAEA,MAAM,YAAY,SAAgC;AAC9C,SAAK,SAAS,OAAO,OAAO;AAAA,EAChC;AAAA,EAEA,MAAM,YAA0B;AAC5B,WAAO;AAAA,MACH,OAAO,KAAK,SAAS,eAAA;AAAA,MACrB,QAAQ,KAAK,aAAa,UAAA;AAAA,IAAU;AAAA,EAE5C;AACJ;AC5DO,MAAM,iBAAiB;AAAA,EAClB;AAAA,EAER,MAAM,aAA4B;AAC9B,SAAK,SAAS,MAAM,iBAAiB;AAAA,MACjC,kBAAkB;AAAA,MAClB,UAAU;AAAA,IAAA,CACb;AAAA,EACL;AAAA,EAEA,MAAM,OAAO,UAAkB,UAA0C;AACrE,QAAI,CAAC,KAAK,QAAQ;AACd,YAAM,KAAK,WAAA;AAAA,IACf;AAEA,UAAM,SAAS,MAAM,KAAK,OAAO,kBAAkB,QAAQ;AAE3D,QAAI,CAAC,UAAU,CAAC,OAAO,MAAM;AACzB,YAAM,IAAI,MAAM,yDAAyD;AAAA,IAC7E;AAEA,UAAM,OAAO,MAAM,KAAK,OAAO,eAAe,OAAO,IAAI;AAEzD,UAAM,MAAM,IAAI,MAAM,IAAI;AAC1B,UAAM,WAAW,IAAI,OAAO;AAC5B,UAAM,gBAAgB,SAAS,cAAc,KAAK;AAClD,kBAAc,KAAK;AACnB,kBAAc,YAAY;AAE1B,UAAM,UAA8B;AAAA,MAChC;AAAA,MACA,YAAY;AAAA,MACZ,eAAe;AAAA,IAAA;AAGnB,UAAM,aAAa,MAAM,KAAK,OAAO,qBAAqB,eAAe,OAAO;AAEhF,WAAO;AAAA,MACH,OAAO,OAAO,SAAS;AAAA,MACvB,SAAS;AAAA,MACT,OAAO,OAAO;AAAA,IAAA;AAAA,EAEtB;AACJ;ACjDA,MAAM,gBAAgB,EAAE,OAAO;AAAA,EAC3B,IAAI,EAAE,OAAA;AAAA,EACN,MAAM,EAAE,OAAA;AAAA,EACR,OAAO,EAAE,OAAA,EAAS,MAAM,uBAAuB,cAAc;AAAA,EAC7D,WAAW,EAAE,OAAA,EAAS,IAAI,IAAI,gBAAgB;AAAA,EAC9C,WAAW,EAAE,QAAA,EAAU,SAAA;AAAA,EACvB,WAAW,EAAE,KAAA,EAAO,SAAA;AAAA,EACpB,WAAW,EAAE,KAAA,EAAO,SAAA;AACxB,CAAC;AAEM,MAAM,YAAY;AAAA,EACb;AAAA,EAER,cAAc;AACV,SAAK,QAAQ,IAAI,KAAa;AAAA,MAC1B,aAAa;AAAA,IAAA,CAChB;AAAA,EACL;AAAA,EAIA,IAA4B,KAAQ,cAAiD;AACjF,WAAO,KAAK,MAAM,IAAI,KAAK,YAAmB;AAAA,EAClD;AAAA,EAEA,IAA4B,KAAQ,OAAwB;AACxD,QAAI,QAAQ,YAAY;AACpB,QAAE,MAAM,aAAa,EAAE,MAAM,KAAK;AAAA,IACtC;AACA,SAAK,MAAM,IAAI,KAAK,KAAK;AAAA,EAC7B;AAAA,EAEA,IAAI,KAA4B;AAC5B,WAAO,KAAK,MAAM,IAAI,GAAG;AAAA,EAC7B;AAAA,EAEA,OAAO,KAAyB;AAC5B,SAAK,MAAM,OAAO,GAAG;AAAA,EACzB;AAAA,EAEA,QAAc;AACV,SAAK,MAAM,MAAA;AAAA,EACf;AAAA,EAEA,SAAiB;AACb,WAAO,KAAK,MAAM;AAAA,EACtB;AAAA,EAEA,UAAkB;AACd,WAAO,KAAK,MAAM;AAAA,EACtB;AACJ;ACrDO,MAAM,OAAO;AAAA,EACR;AAAA,EAER,cAAc;AACV,SAAK,SAAS,QAAQ,aAAa;AAAA,MAC/B,OAAO,QAAQ,IAAI,aAAa;AAAA,MAChC,QAAQ,QAAQ,OAAO;AAAA,QACnB,QAAQ,OAAO,UAAA;AAAA,QACf,QAAQ,OAAO,OAAO,EAAE,OAAO,MAAM;AAAA,QACrC,QAAQ,OAAO,KAAA;AAAA,MAAK;AAAA,MAExB,YAAY;AAAA,QACR,IAAI,QAAQ,WAAW,QAAQ;AAAA,UAC3B,QAAQ,QAAQ,OAAO;AAAA,YACnB,QAAQ,OAAO,SAAA;AAAA,YACf,QAAQ,OAAO,OAAO,CAAC,EAAE,OAAO,SAAS,WAAW,GAAG,WAAW;AAC9D,oBAAM,UAAU,OAAO,KAAK,IAAI,EAAE,SAAS,KAAK,UAAU,IAAI,IAAI;AAClE,qBAAO,GAAG,SAAS,KAAK,KAAK,MAAM,OAAO,IAAI,OAAO;AAAA,YACzD,CAAC;AAAA,UAAA;AAAA,QACL,CACH;AAAA,MAAA;AAAA,IACL,CACH;AAAA,EACL;AAAA,EAEA,MAAM,SAAiB,MAAkB;AACrC,SAAK,OAAO,MAAM,SAAS,IAAI;AAAA,EACnC;AAAA,EAEA,KAAK,SAAiB,MAAkB;AACpC,SAAK,OAAO,KAAK,SAAS,IAAI;AAAA,EAClC;AAAA,EAEA,KAAK,SAAiB,MAAkB;AACpC,SAAK,OAAO,KAAK,SAAS,IAAI;AAAA,EAClC;AAAA,EAEA,MAAM,SAAiB,MAAkB;AACrC,SAAK,OAAO,MAAM,SAAS,IAAI;AAAA,EACnC;AACJ;"}
|
package/dist/cli.js
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
4
|
-
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
5
2
|
import { Command } from "commander";
|
|
6
3
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
7
4
|
import { resolve, isAbsolute, dirname, join } from "path";
|
|
8
5
|
import { fileURLToPath } from "url";
|
|
9
|
-
import { C as ConfigStore, L as Logger, T as ThemeEngine, M as MarkdownRenderer, d as WechatClient } from "./Logger-
|
|
6
|
+
import { C as ConfigStore, L as Logger, T as ThemeEngine, M as MarkdownRenderer, d as WechatClient } from "./Logger-CRPQmRrm.js";
|
|
10
7
|
import axios from "axios";
|
|
11
8
|
import initSqlJs from "sql.js";
|
|
12
9
|
import { JSDOM } from "jsdom";
|
|
@@ -16,9 +13,9 @@ import chalk from "chalk";
|
|
|
16
13
|
import Table from "cli-table3";
|
|
17
14
|
import ora from "ora";
|
|
18
15
|
class CacheStore {
|
|
16
|
+
cache = /* @__PURE__ */ new Map();
|
|
17
|
+
maxSize;
|
|
19
18
|
constructor(maxSize = 100) {
|
|
20
|
-
__publicField(this, "cache", /* @__PURE__ */ new Map());
|
|
21
|
-
__publicField(this, "maxSize");
|
|
22
19
|
this.maxSize = maxSize;
|
|
23
20
|
}
|
|
24
21
|
async get(key) {
|
|
@@ -109,7 +106,6 @@ class ThemeCache extends CacheStore {
|
|
|
109
106
|
}
|
|
110
107
|
class HttpClient {
|
|
111
108
|
constructor(logger) {
|
|
112
|
-
__publicField(this, "client");
|
|
113
109
|
this.logger = logger;
|
|
114
110
|
this.client = axios.create({
|
|
115
111
|
timeout: 3e4,
|
|
@@ -119,6 +115,7 @@ class HttpClient {
|
|
|
119
115
|
});
|
|
120
116
|
this.setupInterceptors();
|
|
121
117
|
}
|
|
118
|
+
client;
|
|
122
119
|
setupInterceptors() {
|
|
123
120
|
this.client.interceptors.request.use(
|
|
124
121
|
(config) => {
|
|
@@ -142,9 +139,8 @@ class HttpClient {
|
|
|
142
139
|
return response;
|
|
143
140
|
},
|
|
144
141
|
(error) => {
|
|
145
|
-
var _a;
|
|
146
142
|
this.logger.error("HTTP Response Error", {
|
|
147
|
-
status:
|
|
143
|
+
status: error.response?.status,
|
|
148
144
|
message: error.message
|
|
149
145
|
});
|
|
150
146
|
return Promise.reject(error);
|
|
@@ -165,10 +161,10 @@ class HttpClient {
|
|
|
165
161
|
}
|
|
166
162
|
}
|
|
167
163
|
class DatabaseManager {
|
|
164
|
+
db;
|
|
165
|
+
logger;
|
|
166
|
+
dbPath;
|
|
168
167
|
constructor(logger) {
|
|
169
|
-
__publicField(this, "db");
|
|
170
|
-
__publicField(this, "logger");
|
|
171
|
-
__publicField(this, "dbPath");
|
|
172
168
|
this.logger = logger;
|
|
173
169
|
}
|
|
174
170
|
async initialize(dbPath) {
|
|
@@ -329,8 +325,8 @@ class ImageProcessor {
|
|
|
329
325
|
const results = (await Promise.all(uploadPromises)).filter(Boolean);
|
|
330
326
|
const validResults = results.filter((r) => !isWechatImageUrl(r.media_id));
|
|
331
327
|
const firstImage = validResults[0];
|
|
332
|
-
const firstImageMediaId =
|
|
333
|
-
const firstImageUrl =
|
|
328
|
+
const firstImageMediaId = firstImage?.media_id || "";
|
|
329
|
+
const firstImageUrl = firstImage?.url || "";
|
|
334
330
|
return {
|
|
335
331
|
content: dom.serialize(),
|
|
336
332
|
firstImageMediaId,
|
|
@@ -347,7 +343,7 @@ class ImageProcessor {
|
|
|
347
343
|
try {
|
|
348
344
|
const dom = new JSDOM(content);
|
|
349
345
|
const firstImg = dom.window.document.querySelector("img");
|
|
350
|
-
return
|
|
346
|
+
return firstImg?.getAttribute("src") || null;
|
|
351
347
|
} catch (error) {
|
|
352
348
|
this.logger.warn("提取第一张图片失败", { error });
|
|
353
349
|
return null;
|
|
@@ -744,9 +740,9 @@ class PublishService {
|
|
|
744
740
|
const __filename$2 = fileURLToPath(import.meta.url);
|
|
745
741
|
const __dirname$2 = dirname(__filename$2);
|
|
746
742
|
class WrapperService {
|
|
743
|
+
dbManager;
|
|
744
|
+
logger;
|
|
747
745
|
constructor(dbManager, logger) {
|
|
748
|
-
__publicField(this, "dbManager");
|
|
749
|
-
__publicField(this, "logger");
|
|
750
746
|
this.dbManager = dbManager;
|
|
751
747
|
this.logger = logger;
|
|
752
748
|
}
|
|
@@ -754,7 +750,6 @@ class WrapperService {
|
|
|
754
750
|
* 加载默认配置
|
|
755
751
|
*/
|
|
756
752
|
loadDefaultConfig() {
|
|
757
|
-
var _a, _b;
|
|
758
753
|
try {
|
|
759
754
|
const distServicesDir = __dirname$2;
|
|
760
755
|
const possiblePaths = [
|
|
@@ -769,8 +764,8 @@ class WrapperService {
|
|
|
769
764
|
const config = JSON.parse(content);
|
|
770
765
|
this.logger.debug("成功加载默认配置", {
|
|
771
766
|
configPath,
|
|
772
|
-
headerLength:
|
|
773
|
-
footerLength:
|
|
767
|
+
headerLength: config.header?.length || 0,
|
|
768
|
+
footerLength: config.footer?.length || 0
|
|
774
769
|
});
|
|
775
770
|
return config;
|
|
776
771
|
}
|
|
@@ -958,21 +953,19 @@ class WrapperService {
|
|
|
958
953
|
}
|
|
959
954
|
}
|
|
960
955
|
class Container {
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
__publicField(this, "wrapperService");
|
|
975
|
-
}
|
|
956
|
+
configStore;
|
|
957
|
+
logger;
|
|
958
|
+
httpClient;
|
|
959
|
+
dbManager;
|
|
960
|
+
tokenCache;
|
|
961
|
+
imageCache;
|
|
962
|
+
themeCache;
|
|
963
|
+
themeEngine;
|
|
964
|
+
renderer;
|
|
965
|
+
accountService;
|
|
966
|
+
themeService;
|
|
967
|
+
renderService;
|
|
968
|
+
wrapperService;
|
|
976
969
|
async initialize() {
|
|
977
970
|
this.configStore = new ConfigStore();
|
|
978
971
|
this.logger = new Logger();
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sources":["../src/infrastructure/cache/CacheStore.ts","../src/infrastructure/cache/TokenCache.ts","../src/infrastructure/cache/ImageCache.ts","../src/infrastructure/cache/ThemeCache.ts","../src/infrastructure/http/HttpClient.ts","../src/infrastructure/database/DatabaseManager.ts","../src/utils/image.ts","../src/utils/crypto.ts","../src/utils/file.ts","../src/core/renderer/ImageProcessor.ts","../src/services/AccountService.ts","../src/services/ThemeService.ts","../src/services/RenderService.ts","../src/services/DraftService.ts","../src/services/PublishService.ts","../src/services/WrapperService.ts","../src/container.ts","../src/cli/commands/account.ts","../src/cli/commands/theme.ts","../src/cli/commands/draft.ts","../src/cli/commands/publish.ts","../src/cli/commands/wrapper.ts","../src/cli/index.ts"],"sourcesContent":["export interface CacheEntry<T> {\n value: T;\n expireAt: number;\n}\n\nexport class CacheStore<T = any> {\n private cache: Map<string, CacheEntry<T>> = new Map();\n private maxSize: number;\n\n constructor(maxSize: number = 100) {\n this.maxSize = maxSize;\n }\n\n async get(key: string): Promise<T | null> {\n const entry = this.cache.get(key);\n \n if (!entry) {\n return null;\n }\n\n if (Date.now() > entry.expireAt) {\n this.cache.delete(key);\n return null;\n }\n\n return entry.value;\n }\n\n async set(key: string, value: T, ttl: number = 3600): Promise<void> {\n if (this.cache.size >= this.maxSize) {\n const firstKey = this.cache.keys().next().value;\n if (firstKey) {\n this.cache.delete(firstKey);\n }\n }\n\n this.cache.set(key, {\n value,\n expireAt: Date.now() + ttl * 1000,\n });\n }\n\n async has(key: string): Promise<boolean> {\n const value = await this.get(key);\n return value !== null;\n }\n\n async delete(key: string): Promise<void> {\n this.cache.delete(key);\n }\n\n async clear(): Promise<void> {\n this.cache.clear();\n }\n\n async size(): Promise<number> {\n return this.cache.size;\n }\n}\n","import { CacheStore } from './CacheStore';\n\nexport interface TokenCacheEntry {\n access_token: string;\n expires_in: number;\n}\n\nexport class TokenCache extends CacheStore<TokenCacheEntry> {\n constructor() {\n super(10);\n }\n\n async getToken(appId: string): Promise<string | null> {\n const entry = await this.get(appId);\n return entry ? entry.access_token : null;\n }\n\n async setToken(appId: string, accessToken: string, expiresIn: number): Promise<void> {\n await this.set(\n appId,\n {\n access_token: accessToken,\n expires_in: expiresIn,\n },\n expiresIn - 200\n );\n }\n}\n","import { CacheStore } from './CacheStore';\n\nexport interface ImageCacheEntry {\n media_id: string;\n url: string;\n}\n\nexport class ImageCache extends CacheStore<ImageCacheEntry> {\n constructor() {\n super(500);\n }\n\n async getMediaId(md5: string): Promise<string | null> {\n const entry = await this.get(md5);\n return entry ? entry.media_id : null;\n }\n\n async setImage(md5: string, mediaId: string, url: string, ttl: number = 86400): Promise<void> {\n await this.set(\n md5,\n {\n media_id: mediaId,\n url,\n },\n ttl\n );\n }\n}\n","import { CacheStore } from './CacheStore';\n\nexport class ThemeCache extends CacheStore<string> {\n constructor() {\n super(50);\n }\n\n async getThemeCSS(themeId: string): Promise<string | null> {\n return await this.get(themeId);\n }\n\n async setThemeCSS(themeId: string, css: string, ttl: number = 3600): Promise<void> {\n await this.set(themeId, css, ttl);\n }\n}\n","import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';\nimport { Logger } from '../logger/Logger';\n\nexport class HttpClient {\n private client: AxiosInstance;\n\n constructor(private logger: Logger) {\n this.client = axios.create({\n timeout: 30000,\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n this.setupInterceptors();\n }\n\n private setupInterceptors(): void {\n this.client.interceptors.request.use(\n (config) => {\n this.logger.debug('HTTP Request', {\n method: config.method,\n url: config.url,\n });\n return config;\n },\n (error) => {\n this.logger.error('HTTP Request Error', { error: error.message });\n return Promise.reject(error);\n }\n );\n\n this.client.interceptors.response.use(\n (response) => {\n this.logger.debug('HTTP Response', {\n status: response.status,\n url: response.config.url,\n });\n return response;\n },\n (error) => {\n this.logger.error('HTTP Response Error', {\n status: error.response?.status,\n message: error.message,\n });\n return Promise.reject(error);\n }\n );\n }\n\n async get<T = any>(url: string, config?: AxiosRequestConfig): Promise<AxiosResponse<T>> {\n return this.client.get<T>(url, config);\n }\n\n async post<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<AxiosResponse<T>> {\n return this.client.post<T>(url, data, config);\n }\n\n async put<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<AxiosResponse<T>> {\n return this.client.put<T>(url, data, config);\n }\n\n async delete<T = any>(url: string, config?: AxiosRequestConfig): Promise<AxiosResponse<T>> {\n return this.client.delete<T>(url, config);\n }\n}\n","import initSqlJs, { Database } from 'sql.js';\nimport { Logger } from '../logger/Logger';\nimport { resolve } from 'path';\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';\n\nexport class DatabaseManager {\n private db!: Database;\n private logger: Logger;\n private dbPath!: string;\n\n constructor(logger: Logger) {\n this.logger = logger;\n }\n\n async initialize(dbPath?: string): Promise<void> {\n const dataDir = resolve(process.cwd(), 'data');\n \n // 确保 data 目录存在\n if (!existsSync(dataDir)) {\n mkdirSync(dataDir, { recursive: true });\n }\n\n this.dbPath = dbPath || resolve(dataDir, 'wmp.db');\n this.logger.info('初始化数据库', { path: this.dbPath });\n\n // 初始化 SQL.js\n const SQL = await initSqlJs();\n\n // 加载已存在的数据库或创建新的\n if (existsSync(this.dbPath)) {\n const fileBuffer = readFileSync(this.dbPath);\n this.db = new SQL.Database(fileBuffer);\n } else {\n this.db = new SQL.Database();\n }\n \n this.initTables();\n this.save();\n }\n\n private initTables(): void {\n // Wrapper 版本表\n this.db.run(`\n CREATE TABLE IF NOT EXISTS wrapper_versions (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n version INTEGER NOT NULL,\n enabled INTEGER DEFAULT 0,\n header TEXT,\n footer TEXT,\n author TEXT,\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP\n )\n `);\n\n // 发布的文章记录表\n this.db.run(`\n CREATE TABLE IF NOT EXISTS published_articles (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n title TEXT NOT NULL,\n url TEXT,\n author TEXT,\n published_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n article_id TEXT,\n media_id TEXT\n )\n `);\n\n // 配置表\n this.db.run(`\n CREATE TABLE IF NOT EXISTS config (\n key TEXT PRIMARY KEY,\n value TEXT\n )\n `);\n\n this.logger.info('数据库表初始化完成');\n }\n\n save(): void {\n const data = this.db.export();\n const buffer = Buffer.from(data);\n writeFileSync(this.dbPath, buffer);\n }\n\n getDatabase(): Database {\n return this.db;\n }\n\n close(): void {\n if (this.db) {\n this.save();\n this.db.close();\n }\n }\n}\n","import { readFile } from 'fs/promises';\nimport axios from 'axios';\n\nexport async function downloadImage(url: string): Promise<Buffer> {\n try {\n const response = await axios.get(url, {\n responseType: 'arraybuffer',\n timeout: 30000,\n });\n \n if (!response.data || response.data.byteLength === 0) {\n throw new Error('下载的图片大小为 0');\n }\n \n return Buffer.from(response.data);\n } catch (error) {\n throw new Error(`下载图片失败: ${url}`);\n }\n}\n\nexport async function readImageFile(filePath: string): Promise<Buffer> {\n try {\n const buffer = await readFile(filePath);\n \n if (buffer.length === 0) {\n throw new Error('图片文件大小为 0');\n }\n \n return buffer;\n } catch (error) {\n throw new Error(`读取图片文件失败: ${filePath}`);\n }\n}\n\nexport function isRemoteUrl(url: string): boolean {\n return url.startsWith('http://') || url.startsWith('https://');\n}\n\nexport function isWechatImageUrl(url: string): boolean {\n return url.startsWith('https://mmbiz.qpic.cn');\n}\n\nexport function getImageFilename(url: string): string {\n const urlWithoutQuery = url.split('?')[0];\n const parts = urlWithoutQuery.split('/');\n const filename = parts[parts.length - 1];\n \n const ext = filename.match(/\\.(jpg|jpeg|png|gif|webp|bmp)$/i);\n if (!ext) {\n return `${filename}.jpg`;\n }\n \n return filename;\n}\n","import { createHash } from 'crypto';\nimport { readFile } from 'fs/promises';\n\nexport function md5FromBuffer(buffer: Buffer): string {\n return createHash('md5').update(buffer).digest('hex');\n}\n\nexport function md5FromString(str: string): string {\n return createHash('md5').update(str).digest('hex');\n}\n\nexport async function md5FromFile(filePath: string): Promise<string> {\n const buffer = await readFile(filePath);\n return md5FromBuffer(buffer);\n}\n\nexport function generateId(prefix: string = ''): string {\n const timestamp = Date.now();\n const random = Math.random().toString(36).substring(2, 11);\n return prefix ? `${prefix}_${timestamp}_${random}` : `${timestamp}_${random}`;\n}\n","import { readFile, writeFile, access, mkdir } from 'fs/promises';\nimport { dirname, resolve, isAbsolute } from 'path';\nimport { constants } from 'fs';\n\nexport async function readFileContent(filePath: string): Promise<string> {\n try {\n return await readFile(filePath, 'utf-8');\n } catch (error) {\n throw new Error(`无法读取文件: ${filePath}`);\n }\n}\n\nexport async function writeFileContent(filePath: string, content: string): Promise<void> {\n try {\n const dir = dirname(filePath);\n await mkdir(dir, { recursive: true });\n await writeFile(filePath, content, 'utf-8');\n } catch (error) {\n throw new Error(`无法写入文件: ${filePath}`);\n }\n}\n\nexport async function fileExists(filePath: string): Promise<boolean> {\n try {\n await access(filePath, constants.F_OK);\n return true;\n } catch {\n return false;\n }\n}\n\nexport function resolvePath(filePath: string, basePath?: string): string {\n if (isAbsolute(filePath)) {\n return filePath;\n }\n \n if (basePath) {\n return resolve(basePath, filePath);\n }\n \n return resolve(process.cwd(), filePath);\n}\n\nexport function getFileExtension(filePath: string): string {\n const match = filePath.match(/\\.([^.]+)$/);\n return match ? match[1].toLowerCase() : '';\n}\n\nexport function isImageFile(filePath: string): boolean {\n const ext = getFileExtension(filePath);\n return ['jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp', 'svg'].includes(ext);\n}\n","import { JSDOM } from 'jsdom';\nimport { MaterialAPI } from '../wechat/api/MaterialAPI';\nimport { ImageCache } from '../../infrastructure/cache/ImageCache';\nimport { Logger } from '../../infrastructure/logger/Logger';\nimport { downloadImage, readImageFile, isRemoteUrl, isWechatImageUrl, getImageFilename } from '../../utils/image';\nimport { md5FromBuffer } from '../../utils/crypto';\nimport { resolvePath } from '../../utils/file';\n\nexport interface ProcessImagesResult {\n content: string;\n firstImageMediaId: string;\n firstImageUrl: string;\n}\n\nexport class ImageProcessor {\n constructor(\n private materialAPI: MaterialAPI,\n private imageCache: ImageCache,\n private logger: Logger\n ) {}\n\n async processImages(content: string, relativePath?: string): Promise<ProcessImagesResult> {\n if (!content.includes('<img')) {\n return { content, firstImageMediaId: '', firstImageUrl: '' };\n }\n\n const dom = new JSDOM(content);\n const images = dom.window.document.querySelectorAll('img');\n \n const uploadPromises = Array.from(images).map(async (element: any) => {\n const src = element.getAttribute('src');\n if (!src) return null;\n\n if (isWechatImageUrl(src)) {\n return { media_id: src, url: src };\n }\n\n try {\n const result = await this.uploadImage(src, relativePath);\n element.setAttribute('src', result.url);\n return result;\n } catch (error) {\n this.logger.warn('图片上传失败', { src, error });\n return null;\n }\n });\n\n const results = (await Promise.all(uploadPromises)).filter(Boolean) as { media_id: string; url: string }[];\n \n // 过滤掉微信图片(URL 不能作为 media_id)\n const validResults = results.filter(r => !isWechatImageUrl(r.media_id));\n \n const firstImage = validResults[0];\n const firstImageMediaId = firstImage?.media_id || '';\n const firstImageUrl = firstImage?.url || '';\n\n return {\n content: dom.serialize(),\n firstImageMediaId,\n firstImageUrl,\n };\n }\n\n /**\n * 从 HTML 内容中提取第一张图片\n */\n extractFirstImageFromContent(content: string): string | null {\n if (!content || !content.includes('<img')) {\n return null;\n }\n\n try {\n const dom = new JSDOM(content);\n const firstImg = dom.window.document.querySelector('img');\n return firstImg?.getAttribute('src') || null;\n } catch (error) {\n this.logger.warn('提取第一张图片失败', { error });\n return null;\n }\n }\n\n async uploadImage(imagePath: string, relativePath?: string): Promise<{ media_id: string; url: string }> {\n let buffer: Buffer;\n let filename: string;\n\n if (isRemoteUrl(imagePath)) {\n this.logger.info('下载远程图片', { url: imagePath });\n buffer = await downloadImage(imagePath);\n filename = getImageFilename(imagePath);\n } else {\n const resolvedPath = resolvePath(imagePath, relativePath);\n this.logger.info('读取本地图片', { path: resolvedPath });\n buffer = await readImageFile(resolvedPath);\n filename = getImageFilename(resolvedPath);\n }\n\n const md5 = md5FromBuffer(buffer);\n const cached = await this.imageCache.getMediaId(md5);\n if (cached) {\n this.logger.debug('使用缓存的图片', { md5 });\n const cachedEntry = await this.imageCache.get(md5);\n return { media_id: cached, url: cachedEntry!.url };\n }\n\n const result = await this.materialAPI.uploadImage(buffer, filename);\n await this.imageCache.setImage(md5, result.media_id, result.url);\n\n this.logger.info('图片上传成功', { media_id: result.media_id });\n return result;\n }\n\n /**\n * 上传封面图\n * 优先级:\n * 1. coverPath(显式指定的封面)\n * 2. fallbackMediaId(从正文第一张图片传来的 media_id)\n * 3. 从 content 中提取第一张图片并上传\n */\n async uploadCover(\n coverPath: string | undefined, \n relativePath: string | undefined, \n fallbackMediaId: string | undefined,\n content?: string\n ): Promise<string> {\n this.logger.debug('开始处理封面', { \n hasCoverPath: !!coverPath, \n hasFallbackMediaId: !!fallbackMediaId,\n hasContent: !!content \n });\n\n // 优先级 1: 显式指定的封面\n if (coverPath) {\n try {\n if (isWechatImageUrl(coverPath)) {\n // 微信图片不能直接作为封面,跳过\n this.logger.info('微信图片不能直接作为封面,跳过', { coverPath });\n } else {\n const result = await this.uploadImage(coverPath, relativePath);\n this.logger.info('封面上传成功(显式指定)', { media_id: result.media_id });\n return result.media_id;\n }\n } catch (error) {\n this.logger.warn('显式封面图上传失败,继续尝试 fallback', { coverPath, error });\n }\n }\n\n // 优先级 2: fallback media_id(正文第一张图片)\n if (fallbackMediaId) {\n this.logger.info('使用正文第一张图片作为封面', { media_id: fallbackMediaId });\n return fallbackMediaId;\n }\n\n // 优先级 3: 从 content 中提取第一张图片\n if (content) {\n const firstImageSrc = this.extractFirstImageFromContent(content);\n if (firstImageSrc) {\n try {\n this.logger.info('尝试从正文提取第一张图片作为封面', { src: firstImageSrc });\n const result = await this.uploadImage(firstImageSrc, relativePath);\n this.logger.info('封面上传成功(从正文提取)', { media_id: result.media_id });\n return result.media_id;\n } catch (error) {\n this.logger.warn('从正文提取封面上传失败', { src: firstImageSrc, error });\n }\n }\n }\n\n // 所有尝试都失败\n throw new Error('无法获取封面图:请在 Markdown 中添加 cover: 图片路径,或确保正文中包含图片');\n }\n}\n","import { ConfigStore } from '../infrastructure/config/ConfigStore';\nimport { Logger } from '../infrastructure/logger/Logger';\nimport type { Account, AccountCreateOptions } from '../types/account';\nimport { generateId } from '../utils/crypto';\n\nexport class AccountService {\n constructor(\n private configStore: ConfigStore,\n private logger: Logger\n ) {}\n\n async addAccount(options: AccountCreateOptions): Promise<Account> {\n this.logger.info('添加账号', { name: options.name });\n\n const accounts = await this.listAccounts();\n \n const existingAccount = accounts.find(a => a.appId === options.appId);\n if (existingAccount) {\n throw new Error(`账号已存在: ${existingAccount.name}`);\n }\n\n const account: Account = {\n id: generateId('acc'),\n name: options.name,\n appId: options.appId,\n appSecret: options.appSecret,\n isDefault: options.isDefault || accounts.length === 0,\n createdAt: new Date(),\n updatedAt: new Date(),\n };\n\n if (account.isDefault) {\n accounts.forEach(a => a.isDefault = false);\n }\n\n accounts.push(account);\n this.configStore.set('accounts', accounts);\n\n this.logger.info('账号添加成功', { id: account.id, name: account.name });\n return account;\n }\n\n async listAccounts(): Promise<Account[]> {\n return this.configStore.get('accounts', []);\n }\n\n async getAccount(id: string): Promise<Account | null> {\n const accounts = await this.listAccounts();\n return accounts.find(a => a.id === id) || null;\n }\n\n async getCurrentAccount(): Promise<Account> {\n const accounts = await this.listAccounts();\n \n if (accounts.length === 0) {\n throw new Error('未配置账号,请先使用 account add 命令添加账号');\n }\n\n const defaultAccount = accounts.find(a => a.isDefault);\n if (defaultAccount) {\n return defaultAccount;\n }\n\n return accounts[0];\n }\n\n async setDefaultAccount(id: string): Promise<void> {\n this.logger.info('设置默认账号', { id });\n\n const accounts = await this.listAccounts();\n const account = accounts.find(a => a.id === id);\n\n if (!account) {\n throw new Error(`账号不存在: ${id}`);\n }\n\n accounts.forEach(a => {\n a.isDefault = a.id === id;\n if (a.id === id) {\n a.updatedAt = new Date();\n }\n });\n\n this.configStore.set('accounts', accounts);\n this.logger.info('默认账号设置成功', { name: account.name });\n }\n\n async removeAccount(id: string): Promise<void> {\n this.logger.info('删除账号', { id });\n\n const accounts = await this.listAccounts();\n const account = accounts.find(a => a.id === id);\n\n if (!account) {\n throw new Error(`账号不存在: ${id}`);\n }\n\n const filtered = accounts.filter(a => a.id !== id);\n\n if (account.isDefault && filtered.length > 0) {\n filtered[0].isDefault = true;\n }\n\n this.configStore.set('accounts', filtered);\n this.logger.info('账号删除成功', { name: account.name });\n }\n\n async updateAccount(id: string, updates: Partial<Account>): Promise<Account> {\n this.logger.info('更新账号', { id });\n\n const accounts = await this.listAccounts();\n const account = accounts.find(a => a.id === id);\n\n if (!account) {\n throw new Error(`账号不存在: ${id}`);\n }\n\n Object.assign(account, updates, { updatedAt: new Date() });\n this.configStore.set('accounts', accounts);\n\n this.logger.info('账号更新成功', { name: account.name });\n return account;\n }\n}\n","import { ThemeEngine } from '../core/theme/ThemeEngine';\nimport { ConfigStore } from '../infrastructure/config/ConfigStore';\nimport { ThemeCache } from '../infrastructure/cache/ThemeCache';\nimport { Logger } from '../infrastructure/logger/Logger';\nimport type { ThemeSource } from '../types/theme';\n\nexport class ThemeService {\n constructor(\n private themeEngine: ThemeEngine,\n private configStore: ConfigStore,\n private themeCache: ThemeCache,\n private logger: Logger\n ) {}\n\n async initialize(): Promise<void> {\n this.logger.info('初始化主题系统');\n\n await this.themeEngine.loadBuiltinThemes();\n\n const config = this.configStore.get('themes');\n if (!config) {\n return;\n }\n\n if (config.local) {\n for (const theme of config.local) {\n try {\n await this.themeEngine.addLocalTheme(theme.name, theme.path);\n } catch (error) {\n this.logger.warn('加载本地主题失败', { name: theme.name, error });\n }\n }\n }\n\n if (config.remote) {\n for (const remote of config.remote) {\n if (remote.enabled) {\n try {\n await this.themeEngine.addRemoteAPI(remote.name, remote.apiUrl, remote.apiKey);\n } catch (error) {\n this.logger.warn('添加远程主题 API 失败', { name: remote.name, error });\n }\n }\n }\n }\n\n this.logger.info('主题系统初始化完成');\n }\n\n async listThemes(): Promise<ThemeSource[]> {\n return await this.themeEngine.listThemes();\n }\n\n async getThemeCSS(themeId: string): Promise<string> {\n const cached = await this.themeCache.getThemeCSS(themeId);\n if (cached) {\n this.logger.debug('使用缓存的主题', { themeId });\n return cached;\n }\n\n const css = await this.themeEngine.getThemeCSS(themeId);\n await this.themeCache.setThemeCSS(themeId, css);\n\n return css;\n }\n\n async addLocalTheme(name: string, path: string): Promise<void> {\n this.logger.info('添加本地主题', { name, path });\n\n await this.themeEngine.addLocalTheme(name, path);\n\n const config = this.configStore.get('themes') || {};\n if (!config.local) {\n config.local = [];\n }\n\n const existing = config.local.find(t => t.name === name);\n if (existing) {\n existing.path = path;\n } else {\n config.local.push({ name, path });\n }\n\n this.configStore.set('themes', config);\n this.logger.info('本地主题添加成功');\n }\n\n async addRemoteAPI(name: string, apiUrl: string, apiKey: string): Promise<void> {\n this.logger.info('添加远程主题 API', { name, apiUrl });\n\n await this.themeEngine.addRemoteAPI(name, apiUrl, apiKey);\n\n const config = this.configStore.get('themes') || {};\n if (!config.remote) {\n config.remote = [];\n }\n\n const existing = config.remote.find(r => r.name === name);\n if (existing) {\n existing.apiUrl = apiUrl;\n existing.apiKey = apiKey;\n existing.enabled = true;\n } else {\n config.remote.push({ name, apiUrl, apiKey, enabled: true });\n }\n\n this.configStore.set('themes', config);\n this.logger.info('远程主题 API 添加成功');\n }\n\n async removeTheme(themeId: string): Promise<void> {\n this.logger.info('删除主题', { themeId });\n\n await this.themeEngine.removeTheme(themeId);\n await this.themeCache.delete(themeId);\n\n const config = this.configStore.get('themes') || {};\n if (config.local) {\n config.local = config.local.filter(t => t.name !== themeId);\n }\n\n this.configStore.set('themes', config);\n this.logger.info('主题删除成功');\n }\n}\n","import { MarkdownRenderer, RenderResult } from '../core/renderer/MarkdownRenderer';\nimport { ThemeService } from './ThemeService';\nimport { Logger } from '../infrastructure/logger/Logger';\nimport { readFileContent } from '../utils/file';\n\nexport interface RenderOptions {\n markdown?: string;\n file?: string;\n theme?: string;\n}\n\nexport class RenderService {\n constructor(\n private renderer: MarkdownRenderer,\n private themeService: ThemeService,\n private logger: Logger\n ) {}\n\n async initialize(): Promise<void> {\n await this.renderer.initialize();\n }\n\n async render(options: RenderOptions): Promise<RenderResult> {\n let markdown: string;\n\n if (options.file) {\n this.logger.info('读取 Markdown 文件', { file: options.file });\n markdown = await readFileContent(options.file);\n } else if (options.markdown) {\n markdown = options.markdown;\n } else {\n throw new Error('必须提供 markdown 内容或 file 路径');\n }\n\n let themeCss: string | undefined;\n if (options.theme) {\n this.logger.info('加载主题', { theme: options.theme });\n themeCss = await this.themeService.getThemeCSS(options.theme);\n }\n\n this.logger.info('开始渲染 Markdown');\n const result = await this.renderer.render(markdown, themeCss);\n this.logger.info('Markdown 渲染完成', { title: result.title });\n\n return result;\n }\n}\n","import { WechatClient } from '../core/wechat/WechatClient';\nimport { RenderService } from './RenderService';\nimport { ImageProcessor } from '../core/renderer/ImageProcessor';\nimport { WrapperService } from './WrapperService';\nimport { Logger } from '../infrastructure/logger/Logger';\nimport type { DraftCreateOptions, Draft, DraftList } from '../types/draft';\nimport { dirname } from 'path';\n\nexport class DraftService {\n constructor(\n private wechatClient: WechatClient,\n private renderService: RenderService,\n private imageProcessor: ImageProcessor,\n private wrapperService: WrapperService,\n private logger: Logger\n ) {}\n\n async create(options: DraftCreateOptions): Promise<{ media_id: string }> {\n this.logger.info('开始创建草稿', { file: options.file });\n\n const rendered = await this.renderService.render({\n markdown: options.markdown,\n file: options.file,\n theme: options.theme,\n });\n\n // 使用 Wrapper 包装内容\n let content = this.wrapperService.wrapContent(rendered.content);\n\n const relativePath = options.relativePath || (options.file ? dirname(options.file) : undefined);\n\n const { content: processedContent, firstImageMediaId } = await this.imageProcessor.processImages(\n content,\n relativePath\n );\n\n const thumbMediaId = await this.imageProcessor.uploadCover(\n rendered.cover,\n relativePath,\n firstImageMediaId,\n processedContent\n );\n\n // 检查正文是否为空\n const textContent = processedContent.replace(/<[^>]+>/g, '').trim();\n if (!textContent) {\n throw new Error('正文内容为空,无法创建草稿。请确保文章包含文字内容。');\n }\n\n const result = await this.wechatClient.draft.create({\n title: rendered.title,\n content: processedContent,\n thumb_media_id: thumbMediaId,\n });\n\n this.logger.info('草稿创建成功', { media_id: result.media_id });\n return result;\n }\n\n async list(page: number = 1, pageSize: number = 20): Promise<DraftList> {\n const offset = (page - 1) * pageSize;\n return await this.wechatClient.draft.list(offset, pageSize);\n }\n\n async get(mediaId: string): Promise<Draft> {\n return await this.wechatClient.draft.get(mediaId);\n }\n\n async delete(mediaId: string): Promise<void> {\n this.logger.info('删除草稿', { media_id: mediaId });\n await this.wechatClient.draft.delete(mediaId);\n this.logger.info('草稿删除成功');\n }\n\n async batchDelete(mediaIds: string[]): Promise<void> {\n this.logger.info('批量删除草稿', { count: mediaIds.length });\n\n const results = await Promise.allSettled(\n mediaIds.map(id => this.delete(id))\n );\n\n const failed = results.filter(r => r.status === 'rejected');\n if (failed.length > 0) {\n this.logger.warn('部分草稿删除失败', {\n failed: failed.length,\n total: mediaIds.length,\n });\n }\n }\n\n async count(): Promise<number> {\n return await this.wechatClient.draft.count();\n }\n}\n","import { WechatClient } from '../core/wechat/WechatClient';\nimport { DraftService } from './DraftService';\nimport { Logger } from '../infrastructure/logger/Logger';\nimport type { PublishResult, PublishedArticle, PublishList, PublishStatus } from '../types/publish';\nimport type { DraftCreateOptions } from '../types/draft';\n\nexport class PublishService {\n constructor(\n private wechatClient: WechatClient,\n private draftService: DraftService,\n private logger: Logger\n ) {}\n\n async submit(mediaId: string): Promise<PublishResult> {\n this.logger.info('发布草稿', { media_id: mediaId });\n const result = await this.wechatClient.publish.submit(mediaId);\n this.logger.info('发布任务提交成功', { publish_id: result.publish_id });\n return result;\n }\n\n async createAndPublish(options: DraftCreateOptions): Promise<PublishResult> {\n this.logger.info('创建并发布文章');\n\n const { media_id } = await this.draftService.create(options);\n const result = await this.submit(media_id);\n\n return result;\n }\n\n async list(page: number = 1, pageSize: number = 20): Promise<PublishList> {\n const offset = (page - 1) * pageSize;\n return await this.wechatClient.publish.list(offset, pageSize);\n }\n\n async get(articleId: string): Promise<PublishedArticle> {\n return await this.wechatClient.publish.get(articleId);\n }\n\n async delete(articleId: string, index: number = 0): Promise<void> {\n this.logger.info('删除已发布文章', { article_id: articleId, index });\n await this.wechatClient.publish.delete(articleId, index);\n this.logger.info('已发布文章删除成功');\n }\n\n async getStatus(publishId: string): Promise<PublishStatus> {\n return await this.wechatClient.publish.getStatus(publishId);\n }\n}\n","import { DatabaseManager } from '../infrastructure/database/DatabaseManager';\nimport { Logger } from '../infrastructure/logger/Logger';\nimport { readFileSync, existsSync } from 'fs';\nimport { resolve, dirname } from 'path';\nimport { fileURLToPath } from 'url';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nexport interface WrapperConfig {\n enabled: boolean;\n header: string;\n footer: string;\n version: number;\n}\n\nexport interface WrapperVersion {\n id: number;\n version: number;\n enabled: number;\n header: string;\n footer: string;\n author: string;\n created_at: string;\n}\n\nexport class WrapperService {\n private dbManager: DatabaseManager;\n private logger: Logger;\n\n constructor(dbManager: DatabaseManager, logger: Logger) {\n this.dbManager = dbManager;\n this.logger = logger;\n }\n\n /**\n * 加载默认配置\n */\n private loadDefaultConfig(): { enabled: boolean; header: string; footer: string } | null {\n try {\n // __dirname 在打包后是 dist/services,需要计算正确路径\n // 全局安装时: /usr/local/lib/node_modules/wechat-md-publisher/dist/services\n // 相对路径到 config: ../config/default-wrapper.json\n const distServicesDir = __dirname;\n const possiblePaths = [\n // 全局安装: node_modules/wechat-md-publisher/dist/services -> node_modules/wechat-md-publisher/config/\n resolve(distServicesDir, '../config/default-wrapper.json'),\n // 本地开发/项目内: 项目根目录/config/\n resolve(process.cwd(), 'config/default-wrapper.json'),\n ];\n \n for (const configPath of possiblePaths) {\n if (existsSync(configPath)) {\n const content = readFileSync(configPath, 'utf-8');\n const config = JSON.parse(content);\n this.logger.debug('成功加载默认配置', { \n configPath,\n headerLength: config.header?.length || 0,\n footerLength: config.footer?.length || 0\n });\n return config;\n }\n }\n \n this.logger.warn('默认配置文件不存在', { \n triedPaths: possiblePaths,\n __dirname: distServicesDir\n });\n } catch (error) {\n this.logger.warn('无法加载默认 wrapper 配置', { error });\n }\n return null;\n }\n\n /**\n * 初始化默认内容(如果数据库为空)\n * 注意:首次使用时会自动插入默认配置(默认为关闭状态)\n */\n private initializeDefaultIfNeeded(): void {\n const db = this.dbManager.getDatabase();\n const result = db.exec('SELECT COUNT(*) as count FROM wrapper_versions');\n \n if (result.length > 0 && result[0].values[0][0] === 0) {\n // 数据库为空,加载默认配置(默认为关闭状态)\n const defaultConfig = this.loadDefaultConfig();\n if (!defaultConfig) {\n throw new Error('无法加载默认 wrapper 配置文件,请确保 config/default-wrapper.json 存在');\n }\n \n db.run(`\n INSERT INTO wrapper_versions (version, enabled, header, footer, author)\n VALUES (1, 0, ?, ?, 'system')\n `, [\n defaultConfig.header,\n defaultConfig.footer\n ]);\n this.dbManager.save();\n this.logger.info('已初始化默认 wrapper 配置(关闭状态)', {\n headerLength: defaultConfig.header.length,\n footerLength: defaultConfig.footer.length\n });\n }\n }\n\n /**\n * 获取当前 Wrapper 配置\n */\n get(): WrapperConfig {\n this.initializeDefaultIfNeeded();\n const db = this.dbManager.getDatabase();\n const result = db.exec(`\n SELECT version, enabled, header, footer \n FROM wrapper_versions \n ORDER BY version DESC \n LIMIT 1\n `);\n\n if (!result.length || !result[0].values.length) {\n return {\n enabled: false,\n header: '',\n footer: '',\n version: 0\n };\n }\n\n const row = result[0].values[0];\n return {\n enabled: row[1] === 1,\n header: row[2] || '',\n footer: row[3] || '',\n version: row[0] as number\n };\n }\n\n /**\n * 开启 Wrapper\n */\n enable(): void {\n const config = this.get();\n if (config.enabled) {\n this.logger.info('Wrapper 已经开启');\n return;\n }\n\n const db = this.dbManager.getDatabase();\n // 直接更新状态为 enabled(get() 已经确保数据存在)\n if (config.version > 0) {\n db.run(`\n UPDATE wrapper_versions \n SET enabled = 1 \n WHERE version = ?\n `, [config.version]);\n } else {\n // 理论上不应该走到这里,因为 get() 会调用 initializeDefaultIfNeeded()\n throw new Error('无法开启 Wrapper:数据库未初始化');\n }\n\n this.dbManager.save();\n this.logger.info('Wrapper 已开启');\n }\n\n /**\n * 关闭 Wrapper\n */\n disable(): void {\n const config = this.get();\n if (!config.enabled) {\n this.logger.info('Wrapper 已经关闭');\n return;\n }\n\n const db = this.dbManager.getDatabase();\n db.run(`\n UPDATE wrapper_versions \n SET enabled = 0 \n WHERE version = ?\n `, [config.version]);\n\n this.dbManager.save();\n this.logger.info('Wrapper 已关闭');\n }\n\n /**\n * 更新 Wrapper 内容(创建新版本)\n */\n update(header: string, footer: string, author: string = 'system'): void {\n const db = this.dbManager.getDatabase();\n const current = this.get();\n const newVersion = current.version + 1;\n\n db.run(`\n INSERT INTO wrapper_versions (version, enabled, header, footer, author)\n VALUES (?, ?, ?, ?, ?)\n `, [newVersion, current.enabled ? 1 : 0, header, footer, author]);\n\n this.dbManager.save();\n this.logger.info('Wrapper 内容已更新', { version: newVersion });\n }\n\n /**\n * 获取历史版本\n */\n history(): WrapperVersion[] {\n const db = this.dbManager.getDatabase();\n const result = db.exec(`\n SELECT * FROM wrapper_versions \n ORDER BY version DESC\n `);\n\n if (!result.length || !result[0].values.length) {\n return [];\n }\n\n return result[0].values.map(row => ({\n id: row[0] as number,\n version: row[1] as number,\n enabled: row[2] as number,\n header: row[3] as string,\n footer: row[4] as string,\n author: row[5] as string,\n created_at: row[6] as string\n }));\n }\n\n /**\n * 回滚到指定版本\n */\n rollback(targetVersion: number, author: string = 'system'): void {\n const db = this.dbManager.getDatabase();\n const current = this.get();\n \n const result = db.exec(`\n SELECT * FROM wrapper_versions WHERE version = ?\n `, [targetVersion]);\n\n if (!result.length || !result[0].values.length) {\n throw new Error(`版本 ${targetVersion} 不存在`);\n }\n\n const target = result[0].values[0];\n const newVersion = current.version + 1;\n\n db.run(`\n INSERT INTO wrapper_versions (version, enabled, header, footer, author)\n VALUES (?, ?, ?, ?, ?)\n `, [newVersion, target[2], target[3], target[4], author]);\n\n this.dbManager.save();\n this.logger.info('已回滚到指定版本', { \n from: current.version, \n to: targetVersion,\n newVersion \n });\n }\n\n /**\n * 将内容包装到文章中\n */\n wrapContent(content: string): string {\n const config = this.get();\n \n if (!config.enabled) {\n return content;\n }\n\n let result = content;\n\n // 插入头部\n if (config.header) {\n result = config.header + '\\n' + result;\n }\n\n // 插入尾部\n if (config.footer) {\n result = result + '\\n' + config.footer;\n }\n\n return result;\n }\n}\n","import { ConfigStore } from './infrastructure/config/ConfigStore';\nimport { TokenCache } from './infrastructure/cache/TokenCache';\nimport { ImageCache } from './infrastructure/cache/ImageCache';\nimport { ThemeCache } from './infrastructure/cache/ThemeCache';\nimport { Logger } from './infrastructure/logger/Logger';\nimport { HttpClient } from './infrastructure/http/HttpClient';\nimport { DatabaseManager } from './infrastructure/database/DatabaseManager';\nimport { WechatClient } from './core/wechat/WechatClient';\nimport { ThemeEngine } from './core/theme/ThemeEngine';\nimport { MarkdownRenderer } from './core/renderer/MarkdownRenderer';\nimport { ImageProcessor } from './core/renderer/ImageProcessor';\nimport { AccountService } from './services/AccountService';\nimport { ThemeService } from './services/ThemeService';\nimport { RenderService } from './services/RenderService';\nimport { DraftService } from './services/DraftService';\nimport { PublishService } from './services/PublishService';\nimport { WrapperService } from './services/WrapperService';\n\nclass Container {\n\n private configStore!: ConfigStore;\n private logger!: Logger;\n private httpClient!: HttpClient;\n private dbManager!: DatabaseManager;\n private tokenCache!: TokenCache;\n private imageCache!: ImageCache;\n private themeCache!: ThemeCache;\n private themeEngine!: ThemeEngine;\n private renderer!: MarkdownRenderer;\n private accountService!: AccountService;\n private themeService!: ThemeService;\n private renderService!: RenderService;\n private wrapperService!: WrapperService;\n\n async initialize(): Promise<void> {\n this.configStore = new ConfigStore();\n this.logger = new Logger();\n this.httpClient = new HttpClient(this.logger);\n this.dbManager = new DatabaseManager(this.logger);\n await this.dbManager.initialize();\n this.tokenCache = new TokenCache();\n this.imageCache = new ImageCache();\n this.themeCache = new ThemeCache();\n this.themeEngine = new ThemeEngine();\n this.renderer = new MarkdownRenderer();\n \n this.accountService = new AccountService(this.configStore, this.logger);\n this.themeService = new ThemeService(\n this.themeEngine,\n this.configStore,\n this.themeCache,\n this.logger\n );\n this.renderService = new RenderService(\n this.renderer,\n this.themeService,\n this.logger\n );\n this.wrapperService = new WrapperService(this.dbManager, this.logger);\n\n await this.themeService.initialize();\n await this.renderService.initialize();\n }\n\n getAccountService(): AccountService {\n return this.accountService;\n }\n\n getThemeService(): ThemeService {\n return this.themeService;\n }\n\n getRenderService(): RenderService {\n return this.renderService;\n }\n\n getWrapperService(): WrapperService {\n return this.wrapperService;\n }\n\n getDatabaseManager(): DatabaseManager {\n return this.dbManager;\n }\n\n async getDraftService(): Promise<DraftService> {\n const account = await this.accountService.getCurrentAccount();\n const wechatClient = new WechatClient(\n account.appId,\n account.appSecret,\n this.httpClient,\n this.tokenCache,\n this.logger\n );\n\n const imageProcessor = new ImageProcessor(\n wechatClient.material,\n this.imageCache,\n this.logger\n );\n\n return new DraftService(\n wechatClient,\n this.renderService,\n imageProcessor,\n this.wrapperService,\n this.logger\n );\n }\n\n async getPublishService(): Promise<PublishService> {\n const draftService = await this.getDraftService();\n const account = await this.accountService.getCurrentAccount();\n const wechatClient = new WechatClient(\n account.appId,\n account.appSecret,\n this.httpClient,\n this.tokenCache,\n this.logger\n );\n\n return new PublishService(\n wechatClient,\n draftService,\n this.logger\n );\n }\n}\n\nexport const container = new Container();\n","import { Command } from 'commander';\nimport { container } from '../../container';\nimport chalk from 'chalk';\nimport Table from 'cli-table3';\n\nexport function createAccountCommand(): Command {\n const cmd = new Command('account')\n .description('账号管理');\n\n cmd.command('add')\n .description('添加微信公众号账号')\n .requiredOption('--name <name>', '账号名称')\n .requiredOption('--app-id <appId>', '微信公众号 AppID')\n .requiredOption('--app-secret <appSecret>', '微信公众号 AppSecret')\n .option('--default', '设为默认账号')\n .action(async (options) => {\n try {\n await container.initialize();\n const accountService = container.getAccountService();\n\n const account = await accountService.addAccount({\n name: options.name,\n appId: options.appId,\n appSecret: options.appSecret,\n isDefault: options.default,\n });\n\n console.log(chalk.green('✓ 账号添加成功'));\n console.log(` ID: ${account.id}`);\n console.log(` 名称: ${account.name}`);\n console.log(` AppID: ${account.appId}`);\n console.log(` 默认账号: ${account.isDefault ? '是' : '否'}`);\n } catch (error: any) {\n console.error(chalk.red('✗ 添加账号失败:'), error.message);\n process.exit(1);\n }\n });\n\n cmd.command('list')\n .description('列出所有账号')\n .action(async () => {\n try {\n await container.initialize();\n const accountService = container.getAccountService();\n const accounts = await accountService.listAccounts();\n\n if (accounts.length === 0) {\n console.log(chalk.yellow('未配置账号'));\n console.log('使用 account add 命令添加账号');\n return;\n }\n\n const table = new Table({\n head: ['ID', '名称', 'AppID', '默认'],\n colWidths: [25, 20, 20, 8],\n });\n\n accounts.forEach(account => {\n table.push([\n account.id,\n account.name,\n account.appId,\n account.isDefault ? chalk.green('是') : '否',\n ]);\n });\n\n console.log(table.toString());\n } catch (error: any) {\n console.error(chalk.red('✗ 获取账号列表失败:'), error.message);\n process.exit(1);\n }\n });\n\n cmd.command('switch <id>')\n .description('切换默认账号')\n .action(async (id) => {\n try {\n await container.initialize();\n const accountService = container.getAccountService();\n await accountService.setDefaultAccount(id);\n console.log(chalk.green('✓ 默认账号切换成功'));\n } catch (error: any) {\n console.error(chalk.red('✗ 切换账号失败:'), error.message);\n process.exit(1);\n }\n });\n\n cmd.command('remove <id>')\n .description('删除账号')\n .action(async (id) => {\n try {\n await container.initialize();\n const accountService = container.getAccountService();\n await accountService.removeAccount(id);\n console.log(chalk.green('✓ 账号删除成功'));\n } catch (error: any) {\n console.error(chalk.red('✗ 删除账号失败:'), error.message);\n process.exit(1);\n }\n });\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { container } from '../../container';\nimport chalk from 'chalk';\nimport Table from 'cli-table3';\n\nexport function createThemeCommand(): Command {\n const cmd = new Command('theme')\n .description('主题管理');\n\n cmd.command('list')\n .description('列出所有可用主题')\n .action(async () => {\n try {\n await container.initialize();\n const themeService = container.getThemeService();\n const themes = await themeService.listThemes();\n\n if (themes.length === 0) {\n console.log(chalk.yellow('未找到主题'));\n return;\n }\n\n const table = new Table({\n head: ['ID', '名称', '类型', '描述'],\n colWidths: [20, 25, 12, 40],\n });\n\n themes.forEach(theme => {\n const typeColor = theme.type === 'builtin' ? chalk.green :\n theme.type === 'local' ? chalk.blue :\n theme.type === 'remote' ? chalk.magenta : chalk.gray;\n \n table.push([\n theme.id,\n theme.name,\n typeColor(theme.type),\n theme.description || '-',\n ]);\n });\n\n console.log(table.toString());\n console.log(`\\n总计: ${themes.length} 个主题`);\n } catch (error: any) {\n console.error(chalk.red('✗ 获取主题列表失败:'), error.message);\n process.exit(1);\n }\n });\n\n cmd.command('add-local')\n .description('添加本地主题')\n .requiredOption('--name <name>', '主题名称')\n .requiredOption('--path <path>', '主题 CSS 文件路径')\n .action(async (options) => {\n try {\n await container.initialize();\n const themeService = container.getThemeService();\n \n await themeService.addLocalTheme(options.name, options.path);\n \n console.log(chalk.green('✓ 本地主题添加成功'));\n console.log(` 名称: ${options.name}`);\n console.log(` 路径: ${options.path}`);\n } catch (error: any) {\n console.error(chalk.red('✗ 添加本地主题失败:'), error.message);\n process.exit(1);\n }\n });\n\n cmd.command('add-remote')\n .description('添加远程主题 API')\n .requiredOption('--name <name>', 'API 名称')\n .requiredOption('--url <url>', 'API URL')\n .requiredOption('--key <key>', 'API Key')\n .action(async (options) => {\n try {\n await container.initialize();\n const themeService = container.getThemeService();\n \n await themeService.addRemoteAPI(options.name, options.url, options.key);\n \n console.log(chalk.green('✓ 远程主题 API 添加成功'));\n console.log(` 名称: ${options.name}`);\n console.log(` URL: ${options.url}`);\n } catch (error: any) {\n console.error(chalk.red('✗ 添加远程主题 API 失败:'), error.message);\n process.exit(1);\n }\n });\n\n cmd.command('remove <theme-id>')\n .description('删除主题')\n .action(async (themeId) => {\n try {\n await container.initialize();\n const themeService = container.getThemeService();\n \n await themeService.removeTheme(themeId);\n \n console.log(chalk.green('✓ 主题删除成功'));\n } catch (error: any) {\n console.error(chalk.red('✗ 删除主题失败:'), error.message);\n process.exit(1);\n }\n });\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { container } from '../../container';\nimport chalk from 'chalk';\nimport Table from 'cli-table3';\nimport ora from 'ora';\n\nexport function createDraftCommand(): Command {\n const cmd = new Command('draft')\n .description('草稿管理');\n\n cmd.command('create')\n .description('创建草稿')\n .requiredOption('-f, --file <file>', 'Markdown 文件路径')\n .option('-t, --theme <theme>', '主题 ID')\n .action(async (options) => {\n const spinner = ora('正在创建草稿...').start();\n \n try {\n await container.initialize();\n const draftService = await container.getDraftService();\n \n const result = await draftService.create({\n file: options.file,\n theme: options.theme,\n });\n \n spinner.succeed('草稿创建成功');\n console.log(chalk.green(` Media ID: ${result.media_id}`));\n console.log(chalk.gray(' 提示: 使用 publish 命令发布此草稿'));\n } catch (error: any) {\n spinner.fail('创建草稿失败');\n console.error(chalk.red(error.message));\n process.exit(1);\n }\n });\n\n cmd.command('list')\n .description('列出草稿')\n .option('-p, --page <page>', '页码', '1')\n .option('-s, --size <size>', '每页数量', '20')\n .action(async (options) => {\n const spinner = ora('正在获取草稿列表...').start();\n \n try {\n await container.initialize();\n const draftService = await container.getDraftService();\n \n const page = parseInt(options.page);\n const size = parseInt(options.size);\n const result = await draftService.list(page, size);\n \n spinner.stop();\n \n if (!result.item || result.item.length === 0) {\n console.log(chalk.yellow('暂无草稿'));\n return;\n }\n\n const table = new Table({\n head: ['Media ID', '标题', '更新时间'],\n colWidths: [35, 40, 20],\n });\n\n result.item.forEach(draft => {\n const article = draft.content.news_item[0];\n const updateTime = new Date(draft.update_time * 1000).toLocaleString('zh-CN');\n \n table.push([\n draft.media_id,\n article.title || '-',\n updateTime,\n ]);\n });\n\n console.log(table.toString());\n console.log(`\\n总计: ${result.total_count} 个草稿 (第 ${page} 页)`);\n } catch (error: any) {\n spinner.fail('获取草稿列表失败');\n console.error(chalk.red(error.message));\n process.exit(1);\n }\n });\n\n cmd.command('delete <media-id>')\n .description('删除草稿')\n .action(async (mediaId) => {\n const spinner = ora('正在删除草稿...').start();\n \n try {\n await container.initialize();\n const draftService = await container.getDraftService();\n \n await draftService.delete(mediaId);\n \n spinner.succeed('草稿删除成功');\n } catch (error: any) {\n spinner.fail('删除草稿失败');\n console.error(chalk.red(error.message));\n process.exit(1);\n }\n });\n\n cmd.command('count')\n .description('获取草稿总数')\n .action(async () => {\n try {\n await container.initialize();\n const draftService = await container.getDraftService();\n \n const count = await draftService.count();\n \n console.log(chalk.green(`草稿总数: ${count}`));\n } catch (error: any) {\n console.error(chalk.red('✗ 获取草稿总数失败:'), error.message);\n process.exit(1);\n }\n });\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { container } from '../../container';\nimport chalk from 'chalk';\nimport Table from 'cli-table3';\nimport ora from 'ora';\n\nexport function createPublishCommand(): Command {\n const cmd = new Command('publish')\n .description('发布管理');\n\n cmd.command('submit <media-id>')\n .description('发布草稿')\n .action(async (mediaId) => {\n const spinner = ora('正在发布草稿...').start();\n \n try {\n await container.initialize();\n const publishService = await container.getPublishService();\n \n const result = await publishService.submit(mediaId);\n \n spinner.succeed('发布任务提交成功');\n console.log(chalk.green(` Publish ID: ${result.publish_id}`));\n console.log(chalk.gray(' 提示: 使用 publish status 命令查看发布状态'));\n } catch (error: any) {\n spinner.fail('发布失败');\n console.error(chalk.red(error.message));\n process.exit(1);\n }\n });\n\n cmd.command('create')\n .description('创建并发布文章')\n .requiredOption('-f, --file <file>', 'Markdown 文件路径')\n .option('-t, --theme <theme>', '主题 ID')\n .action(async (options) => {\n const spinner = ora('正在创建并发布文章...').start();\n \n try {\n await container.initialize();\n const publishService = await container.getPublishService();\n \n const result = await publishService.createAndPublish({\n file: options.file,\n theme: options.theme,\n });\n \n spinner.succeed('文章创建并发布成功');\n console.log(chalk.green(` Publish ID: ${result.publish_id}`));\n } catch (error: any) {\n spinner.fail('创建并发布失败');\n console.error(chalk.red(error.message));\n process.exit(1);\n }\n });\n\n cmd.command('list')\n .description('列出已发布文章')\n .option('-p, --page <page>', '页码', '1')\n .option('-s, --size <size>', '每页数量', '20')\n .action(async (options) => {\n const spinner = ora('正在获取已发布文章列表...').start();\n \n try {\n await container.initialize();\n const publishService = await container.getPublishService();\n \n const page = parseInt(options.page);\n const size = parseInt(options.size);\n const result = await publishService.list(page, size);\n \n spinner.stop();\n \n if (!result.item || result.item.length === 0) {\n console.log(chalk.yellow('暂无已发布文章'));\n return;\n }\n\n const table = new Table({\n head: ['Article ID', '标题', '更新时间'],\n colWidths: [35, 40, 20],\n });\n\n result.item.forEach(article => {\n const newsItem = article.content.news_item[0];\n const updateTime = new Date(article.update_time * 1000).toLocaleString('zh-CN');\n \n table.push([\n article.article_id,\n newsItem.title || '-',\n updateTime,\n ]);\n });\n\n console.log(table.toString());\n console.log(`\\n总计: ${result.total_count} 篇文章 (第 ${page} 页)`);\n } catch (error: any) {\n spinner.fail('获取已发布文章列表失败');\n console.error(chalk.red(error.message));\n process.exit(1);\n }\n });\n\n cmd.command('delete <article-id>')\n .description('删除已发布文章')\n .option('-i, --index <index>', '文章索引', '0')\n .action(async (articleId, options) => {\n const spinner = ora('正在删除已发布文章...').start();\n \n try {\n await container.initialize();\n const publishService = await container.getPublishService();\n \n const index = parseInt(options.index);\n await publishService.delete(articleId, index);\n \n spinner.succeed('已发布文章删除成功');\n } catch (error: any) {\n spinner.fail('删除已发布文章失败');\n console.error(chalk.red(error.message));\n process.exit(1);\n }\n });\n\n cmd.command('status <publish-id>')\n .description('查询发布状态')\n .action(async (publishId) => {\n try {\n await container.initialize();\n const publishService = await container.getPublishService();\n \n const status = await publishService.getStatus(publishId);\n \n console.log(chalk.green('发布状态:'));\n console.log(` Publish ID: ${status.publish_id}`);\n console.log(` 状态: ${status.publish_status === 0 ? '成功' : '失败'}`);\n \n if (status.article_id) {\n console.log(` Article ID: ${status.article_id}`);\n }\n \n if (status.article_detail) {\n console.log(` 文章数量: ${status.article_detail.count}`);\n }\n } catch (error: any) {\n console.error(chalk.red('✗ 查询发布状态失败:'), error.message);\n process.exit(1);\n }\n });\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { container } from '../../container';\nimport chalk from 'chalk';\nimport Table from 'cli-table3';\n\nexport function createWrapperCommand(): Command {\n const cmd = new Command('wrapper')\n .description('文章包装功能管理(开头/结尾固定图文)');\n\n // 获取当前状态\n cmd.command('status')\n .description('查看当前 Wrapper 状态')\n .action(async () => {\n try {\n await container.initialize();\n const wrapperService = await container.getWrapperService();\n const config = wrapperService.get();\n\n console.log(chalk.green('当前状态:'));\n console.log(` 开关: ${config.enabled ? chalk.green('开启') : chalk.red('关闭')}`);\n console.log(` 版本: ${config.version}`);\n \n if (config.header) {\n console.log(chalk.cyan('\\n 头部内容:'));\n console.log(chalk.gray(' ' + config.header.substring(0, 100) + (config.header.length > 100 ? '...' : '')));\n }\n \n if (config.footer) {\n console.log(chalk.cyan('\\n 尾部内容:'));\n console.log(chalk.gray(' ' + config.footer.substring(0, 100) + (config.footer.length > 100 ? '...' : '')));\n }\n } catch (error: any) {\n console.error(chalk.red('✗ 获取状态失败:'), error.message);\n process.exit(1);\n }\n });\n\n // 开启\n cmd.command('on')\n .description('开启 Wrapper 功能')\n .action(async () => {\n try {\n await container.initialize();\n const wrapperService = await container.getWrapperService();\n wrapperService.enable();\n console.log(chalk.green('✓ Wrapper 已开启'));\n } catch (error: any) {\n console.error(chalk.red('✗ 开启失败:'), error.message);\n process.exit(1);\n }\n });\n\n // 关闭\n cmd.command('off')\n .description('关闭 Wrapper 功能')\n .action(async () => {\n try {\n await container.initialize();\n const wrapperService = await container.getWrapperService();\n wrapperService.disable();\n console.log(chalk.green('✓ Wrapper 已关闭'));\n } catch (error: any) {\n console.error(chalk.red('✗ 关闭失败:'), error.message);\n process.exit(1);\n }\n });\n\n // 设置内容\n cmd.command('set')\n .description('更新 Wrapper 内容')\n .option('-h, --header <text>', '头部 HTML 内容')\n .option('-f, --footer <text>', '尾部 HTML 内容')\n .option('-a, --author <name>', '作者名称', 'system')\n .action(async (options) => {\n try {\n await container.initialize();\n const wrapperService = await container.getWrapperService();\n \n wrapperService.update(\n options.header || '', \n options.footer || '',\n options.author\n );\n \n console.log(chalk.green('✓ Wrapper 内容已更新(创建新版本)'));\n } catch (error: any) {\n console.error(chalk.red('✗ 更新失败:'), error.message);\n process.exit(1);\n }\n });\n\n // 查看历史\n cmd.command('history')\n .description('查看历史版本')\n .action(async () => {\n try {\n await container.initialize();\n const wrapperService = await container.getWrapperService();\n const versions = wrapperService.history();\n\n if (versions.length === 0) {\n console.log(chalk.yellow('暂无历史版本'));\n return;\n }\n\n const table = new Table({\n head: ['版本', '状态', '作者', '创建时间'],\n colWidths: [10, 10, 15, 20],\n });\n\n versions.forEach(v => {\n table.push([\n `v${v.version}`,\n v.enabled ? chalk.green('开启') : chalk.red('关闭'),\n v.author,\n new Date(v.created_at).toLocaleString('zh-CN'),\n ]);\n });\n\n console.log(table.toString());\n } catch (error: any) {\n console.error(chalk.red('✗ 获取历史失败:'), error.message);\n process.exit(1);\n }\n });\n\n // 回滚\n cmd.command('rollback <version>')\n .description('回滚到指定版本')\n .option('-a, --author <name>', '作者名称', 'system')\n .action(async (versionStr, options) => {\n try {\n await container.initialize();\n const wrapperService = await container.getWrapperService();\n \n const version = parseInt(versionStr);\n wrapperService.rollback(version, options.author);\n \n console.log(chalk.green(`✓ 已回滚到 v${version}`));\n } catch (error: any) {\n console.error(chalk.red('✗ 回滚失败:'), error.message);\n process.exit(1);\n }\n });\n\n return cmd;\n}\n","#!/usr/bin/env node\nimport { Command } from 'commander';\nimport { readFileSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport { createAccountCommand } from './commands/account';\nimport { createThemeCommand } from './commands/theme';\nimport { createDraftCommand } from './commands/draft';\nimport { createPublishCommand } from './commands/publish';\nimport { createWrapperCommand } from './commands/wrapper';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nconst packageJson = JSON.parse(\n readFileSync(join(__dirname, '../package.json'), 'utf-8')\n);\n\nconst program = new Command();\n\nprogram\n .name('wechat-pub')\n .description('全功能微信公众号 Markdown 发布工具')\n .version(packageJson.version);\n\nprogram.addCommand(createAccountCommand());\nprogram.addCommand(createThemeCommand());\nprogram.addCommand(createDraftCommand());\nprogram.addCommand(createPublishCommand());\nprogram.addCommand(createWrapperCommand());\n\nprogram.parse();\n"],"names":["__filename","__dirname"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cli.js","sources":["../src/infrastructure/cache/CacheStore.ts","../src/infrastructure/cache/TokenCache.ts","../src/infrastructure/cache/ImageCache.ts","../src/infrastructure/cache/ThemeCache.ts","../src/infrastructure/http/HttpClient.ts","../src/infrastructure/database/DatabaseManager.ts","../src/utils/image.ts","../src/utils/crypto.ts","../src/utils/file.ts","../src/core/renderer/ImageProcessor.ts","../src/services/AccountService.ts","../src/services/ThemeService.ts","../src/services/RenderService.ts","../src/services/DraftService.ts","../src/services/PublishService.ts","../src/services/WrapperService.ts","../src/container.ts","../src/cli/commands/account.ts","../src/cli/commands/theme.ts","../src/cli/commands/draft.ts","../src/cli/commands/publish.ts","../src/cli/commands/wrapper.ts","../src/cli/index.ts"],"sourcesContent":["export interface CacheEntry<T> {\n value: T;\n expireAt: number;\n}\n\nexport class CacheStore<T = any> {\n private cache: Map<string, CacheEntry<T>> = new Map();\n private maxSize: number;\n\n constructor(maxSize: number = 100) {\n this.maxSize = maxSize;\n }\n\n async get(key: string): Promise<T | null> {\n const entry = this.cache.get(key);\n \n if (!entry) {\n return null;\n }\n\n if (Date.now() > entry.expireAt) {\n this.cache.delete(key);\n return null;\n }\n\n return entry.value;\n }\n\n async set(key: string, value: T, ttl: number = 3600): Promise<void> {\n if (this.cache.size >= this.maxSize) {\n const firstKey = this.cache.keys().next().value;\n if (firstKey) {\n this.cache.delete(firstKey);\n }\n }\n\n this.cache.set(key, {\n value,\n expireAt: Date.now() + ttl * 1000,\n });\n }\n\n async has(key: string): Promise<boolean> {\n const value = await this.get(key);\n return value !== null;\n }\n\n async delete(key: string): Promise<void> {\n this.cache.delete(key);\n }\n\n async clear(): Promise<void> {\n this.cache.clear();\n }\n\n async size(): Promise<number> {\n return this.cache.size;\n }\n}\n","import { CacheStore } from './CacheStore';\n\nexport interface TokenCacheEntry {\n access_token: string;\n expires_in: number;\n}\n\nexport class TokenCache extends CacheStore<TokenCacheEntry> {\n constructor() {\n super(10);\n }\n\n async getToken(appId: string): Promise<string | null> {\n const entry = await this.get(appId);\n return entry ? entry.access_token : null;\n }\n\n async setToken(appId: string, accessToken: string, expiresIn: number): Promise<void> {\n await this.set(\n appId,\n {\n access_token: accessToken,\n expires_in: expiresIn,\n },\n expiresIn - 200\n );\n }\n}\n","import { CacheStore } from './CacheStore';\n\nexport interface ImageCacheEntry {\n media_id: string;\n url: string;\n}\n\nexport class ImageCache extends CacheStore<ImageCacheEntry> {\n constructor() {\n super(500);\n }\n\n async getMediaId(md5: string): Promise<string | null> {\n const entry = await this.get(md5);\n return entry ? entry.media_id : null;\n }\n\n async setImage(md5: string, mediaId: string, url: string, ttl: number = 86400): Promise<void> {\n await this.set(\n md5,\n {\n media_id: mediaId,\n url,\n },\n ttl\n );\n }\n}\n","import { CacheStore } from './CacheStore';\n\nexport class ThemeCache extends CacheStore<string> {\n constructor() {\n super(50);\n }\n\n async getThemeCSS(themeId: string): Promise<string | null> {\n return await this.get(themeId);\n }\n\n async setThemeCSS(themeId: string, css: string, ttl: number = 3600): Promise<void> {\n await this.set(themeId, css, ttl);\n }\n}\n","import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';\nimport { Logger } from '../logger/Logger';\n\nexport class HttpClient {\n private client: AxiosInstance;\n\n constructor(private logger: Logger) {\n this.client = axios.create({\n timeout: 30000,\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n this.setupInterceptors();\n }\n\n private setupInterceptors(): void {\n this.client.interceptors.request.use(\n (config) => {\n this.logger.debug('HTTP Request', {\n method: config.method,\n url: config.url,\n });\n return config;\n },\n (error) => {\n this.logger.error('HTTP Request Error', { error: error.message });\n return Promise.reject(error);\n }\n );\n\n this.client.interceptors.response.use(\n (response) => {\n this.logger.debug('HTTP Response', {\n status: response.status,\n url: response.config.url,\n });\n return response;\n },\n (error) => {\n this.logger.error('HTTP Response Error', {\n status: error.response?.status,\n message: error.message,\n });\n return Promise.reject(error);\n }\n );\n }\n\n async get<T = any>(url: string, config?: AxiosRequestConfig): Promise<AxiosResponse<T>> {\n return this.client.get<T>(url, config);\n }\n\n async post<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<AxiosResponse<T>> {\n return this.client.post<T>(url, data, config);\n }\n\n async put<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<AxiosResponse<T>> {\n return this.client.put<T>(url, data, config);\n }\n\n async delete<T = any>(url: string, config?: AxiosRequestConfig): Promise<AxiosResponse<T>> {\n return this.client.delete<T>(url, config);\n }\n}\n","import initSqlJs, { Database } from 'sql.js';\nimport { Logger } from '../logger/Logger';\nimport { resolve } from 'path';\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';\n\nexport class DatabaseManager {\n private db!: Database;\n private logger: Logger;\n private dbPath!: string;\n\n constructor(logger: Logger) {\n this.logger = logger;\n }\n\n async initialize(dbPath?: string): Promise<void> {\n const dataDir = resolve(process.cwd(), 'data');\n \n // 确保 data 目录存在\n if (!existsSync(dataDir)) {\n mkdirSync(dataDir, { recursive: true });\n }\n\n this.dbPath = dbPath || resolve(dataDir, 'wmp.db');\n this.logger.info('初始化数据库', { path: this.dbPath });\n\n // 初始化 SQL.js\n const SQL = await initSqlJs();\n\n // 加载已存在的数据库或创建新的\n if (existsSync(this.dbPath)) {\n const fileBuffer = readFileSync(this.dbPath);\n this.db = new SQL.Database(fileBuffer);\n } else {\n this.db = new SQL.Database();\n }\n \n this.initTables();\n this.save();\n }\n\n private initTables(): void {\n // Wrapper 版本表\n this.db.run(`\n CREATE TABLE IF NOT EXISTS wrapper_versions (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n version INTEGER NOT NULL,\n enabled INTEGER DEFAULT 0,\n header TEXT,\n footer TEXT,\n author TEXT,\n created_at DATETIME DEFAULT CURRENT_TIMESTAMP\n )\n `);\n\n // 发布的文章记录表\n this.db.run(`\n CREATE TABLE IF NOT EXISTS published_articles (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n title TEXT NOT NULL,\n url TEXT,\n author TEXT,\n published_at DATETIME DEFAULT CURRENT_TIMESTAMP,\n article_id TEXT,\n media_id TEXT\n )\n `);\n\n // 配置表\n this.db.run(`\n CREATE TABLE IF NOT EXISTS config (\n key TEXT PRIMARY KEY,\n value TEXT\n )\n `);\n\n this.logger.info('数据库表初始化完成');\n }\n\n save(): void {\n const data = this.db.export();\n const buffer = Buffer.from(data);\n writeFileSync(this.dbPath, buffer);\n }\n\n getDatabase(): Database {\n return this.db;\n }\n\n close(): void {\n if (this.db) {\n this.save();\n this.db.close();\n }\n }\n}\n","import { readFile } from 'fs/promises';\nimport axios from 'axios';\n\nexport async function downloadImage(url: string): Promise<Buffer> {\n try {\n const response = await axios.get(url, {\n responseType: 'arraybuffer',\n timeout: 30000,\n });\n \n if (!response.data || response.data.byteLength === 0) {\n throw new Error('下载的图片大小为 0');\n }\n \n return Buffer.from(response.data);\n } catch (error) {\n throw new Error(`下载图片失败: ${url}`);\n }\n}\n\nexport async function readImageFile(filePath: string): Promise<Buffer> {\n try {\n const buffer = await readFile(filePath);\n \n if (buffer.length === 0) {\n throw new Error('图片文件大小为 0');\n }\n \n return buffer;\n } catch (error) {\n throw new Error(`读取图片文件失败: ${filePath}`);\n }\n}\n\nexport function isRemoteUrl(url: string): boolean {\n return url.startsWith('http://') || url.startsWith('https://');\n}\n\nexport function isWechatImageUrl(url: string): boolean {\n return url.startsWith('https://mmbiz.qpic.cn');\n}\n\nexport function getImageFilename(url: string): string {\n const urlWithoutQuery = url.split('?')[0];\n const parts = urlWithoutQuery.split('/');\n const filename = parts[parts.length - 1];\n \n const ext = filename.match(/\\.(jpg|jpeg|png|gif|webp|bmp)$/i);\n if (!ext) {\n return `${filename}.jpg`;\n }\n \n return filename;\n}\n","import { createHash } from 'crypto';\nimport { readFile } from 'fs/promises';\n\nexport function md5FromBuffer(buffer: Buffer): string {\n return createHash('md5').update(buffer).digest('hex');\n}\n\nexport function md5FromString(str: string): string {\n return createHash('md5').update(str).digest('hex');\n}\n\nexport async function md5FromFile(filePath: string): Promise<string> {\n const buffer = await readFile(filePath);\n return md5FromBuffer(buffer);\n}\n\nexport function generateId(prefix: string = ''): string {\n const timestamp = Date.now();\n const random = Math.random().toString(36).substring(2, 11);\n return prefix ? `${prefix}_${timestamp}_${random}` : `${timestamp}_${random}`;\n}\n","import { readFile, writeFile, access, mkdir } from 'fs/promises';\nimport { dirname, resolve, isAbsolute } from 'path';\nimport { constants } from 'fs';\n\nexport async function readFileContent(filePath: string): Promise<string> {\n try {\n return await readFile(filePath, 'utf-8');\n } catch (error) {\n throw new Error(`无法读取文件: ${filePath}`);\n }\n}\n\nexport async function writeFileContent(filePath: string, content: string): Promise<void> {\n try {\n const dir = dirname(filePath);\n await mkdir(dir, { recursive: true });\n await writeFile(filePath, content, 'utf-8');\n } catch (error) {\n throw new Error(`无法写入文件: ${filePath}`);\n }\n}\n\nexport async function fileExists(filePath: string): Promise<boolean> {\n try {\n await access(filePath, constants.F_OK);\n return true;\n } catch {\n return false;\n }\n}\n\nexport function resolvePath(filePath: string, basePath?: string): string {\n if (isAbsolute(filePath)) {\n return filePath;\n }\n \n if (basePath) {\n return resolve(basePath, filePath);\n }\n \n return resolve(process.cwd(), filePath);\n}\n\nexport function getFileExtension(filePath: string): string {\n const match = filePath.match(/\\.([^.]+)$/);\n return match ? match[1].toLowerCase() : '';\n}\n\nexport function isImageFile(filePath: string): boolean {\n const ext = getFileExtension(filePath);\n return ['jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp', 'svg'].includes(ext);\n}\n","import { JSDOM } from 'jsdom';\nimport { MaterialAPI } from '../wechat/api/MaterialAPI';\nimport { ImageCache } from '../../infrastructure/cache/ImageCache';\nimport { Logger } from '../../infrastructure/logger/Logger';\nimport { downloadImage, readImageFile, isRemoteUrl, isWechatImageUrl, getImageFilename } from '../../utils/image';\nimport { md5FromBuffer } from '../../utils/crypto';\nimport { resolvePath } from '../../utils/file';\n\nexport interface ProcessImagesResult {\n content: string;\n firstImageMediaId: string;\n firstImageUrl: string;\n}\n\nexport class ImageProcessor {\n constructor(\n private materialAPI: MaterialAPI,\n private imageCache: ImageCache,\n private logger: Logger\n ) {}\n\n async processImages(content: string, relativePath?: string): Promise<ProcessImagesResult> {\n if (!content.includes('<img')) {\n return { content, firstImageMediaId: '', firstImageUrl: '' };\n }\n\n const dom = new JSDOM(content);\n const images = dom.window.document.querySelectorAll('img');\n \n const uploadPromises = Array.from(images).map(async (element: any) => {\n const src = element.getAttribute('src');\n if (!src) return null;\n\n if (isWechatImageUrl(src)) {\n return { media_id: src, url: src };\n }\n\n try {\n const result = await this.uploadImage(src, relativePath);\n element.setAttribute('src', result.url);\n return result;\n } catch (error) {\n this.logger.warn('图片上传失败', { src, error });\n return null;\n }\n });\n\n const results = (await Promise.all(uploadPromises)).filter(Boolean) as { media_id: string; url: string }[];\n \n // 过滤掉微信图片(URL 不能作为 media_id)\n const validResults = results.filter(r => !isWechatImageUrl(r.media_id));\n \n const firstImage = validResults[0];\n const firstImageMediaId = firstImage?.media_id || '';\n const firstImageUrl = firstImage?.url || '';\n\n return {\n content: dom.serialize(),\n firstImageMediaId,\n firstImageUrl,\n };\n }\n\n /**\n * 从 HTML 内容中提取第一张图片\n */\n extractFirstImageFromContent(content: string): string | null {\n if (!content || !content.includes('<img')) {\n return null;\n }\n\n try {\n const dom = new JSDOM(content);\n const firstImg = dom.window.document.querySelector('img');\n return firstImg?.getAttribute('src') || null;\n } catch (error) {\n this.logger.warn('提取第一张图片失败', { error });\n return null;\n }\n }\n\n async uploadImage(imagePath: string, relativePath?: string): Promise<{ media_id: string; url: string }> {\n let buffer: Buffer;\n let filename: string;\n\n if (isRemoteUrl(imagePath)) {\n this.logger.info('下载远程图片', { url: imagePath });\n buffer = await downloadImage(imagePath);\n filename = getImageFilename(imagePath);\n } else {\n const resolvedPath = resolvePath(imagePath, relativePath);\n this.logger.info('读取本地图片', { path: resolvedPath });\n buffer = await readImageFile(resolvedPath);\n filename = getImageFilename(resolvedPath);\n }\n\n const md5 = md5FromBuffer(buffer);\n const cached = await this.imageCache.getMediaId(md5);\n if (cached) {\n this.logger.debug('使用缓存的图片', { md5 });\n const cachedEntry = await this.imageCache.get(md5);\n return { media_id: cached, url: cachedEntry!.url };\n }\n\n const result = await this.materialAPI.uploadImage(buffer, filename);\n await this.imageCache.setImage(md5, result.media_id, result.url);\n\n this.logger.info('图片上传成功', { media_id: result.media_id });\n return result;\n }\n\n /**\n * 上传封面图\n * 优先级:\n * 1. coverPath(显式指定的封面)\n * 2. fallbackMediaId(从正文第一张图片传来的 media_id)\n * 3. 从 content 中提取第一张图片并上传\n */\n async uploadCover(\n coverPath: string | undefined, \n relativePath: string | undefined, \n fallbackMediaId: string | undefined,\n content?: string\n ): Promise<string> {\n this.logger.debug('开始处理封面', { \n hasCoverPath: !!coverPath, \n hasFallbackMediaId: !!fallbackMediaId,\n hasContent: !!content \n });\n\n // 优先级 1: 显式指定的封面\n if (coverPath) {\n try {\n if (isWechatImageUrl(coverPath)) {\n // 微信图片不能直接作为封面,跳过\n this.logger.info('微信图片不能直接作为封面,跳过', { coverPath });\n } else {\n const result = await this.uploadImage(coverPath, relativePath);\n this.logger.info('封面上传成功(显式指定)', { media_id: result.media_id });\n return result.media_id;\n }\n } catch (error) {\n this.logger.warn('显式封面图上传失败,继续尝试 fallback', { coverPath, error });\n }\n }\n\n // 优先级 2: fallback media_id(正文第一张图片)\n if (fallbackMediaId) {\n this.logger.info('使用正文第一张图片作为封面', { media_id: fallbackMediaId });\n return fallbackMediaId;\n }\n\n // 优先级 3: 从 content 中提取第一张图片\n if (content) {\n const firstImageSrc = this.extractFirstImageFromContent(content);\n if (firstImageSrc) {\n try {\n this.logger.info('尝试从正文提取第一张图片作为封面', { src: firstImageSrc });\n const result = await this.uploadImage(firstImageSrc, relativePath);\n this.logger.info('封面上传成功(从正文提取)', { media_id: result.media_id });\n return result.media_id;\n } catch (error) {\n this.logger.warn('从正文提取封面上传失败', { src: firstImageSrc, error });\n }\n }\n }\n\n // 所有尝试都失败\n throw new Error('无法获取封面图:请在 Markdown 中添加 cover: 图片路径,或确保正文中包含图片');\n }\n}\n","import { ConfigStore } from '../infrastructure/config/ConfigStore';\nimport { Logger } from '../infrastructure/logger/Logger';\nimport type { Account, AccountCreateOptions } from '../types/account';\nimport { generateId } from '../utils/crypto';\n\nexport class AccountService {\n constructor(\n private configStore: ConfigStore,\n private logger: Logger\n ) {}\n\n async addAccount(options: AccountCreateOptions): Promise<Account> {\n this.logger.info('添加账号', { name: options.name });\n\n const accounts = await this.listAccounts();\n \n const existingAccount = accounts.find(a => a.appId === options.appId);\n if (existingAccount) {\n throw new Error(`账号已存在: ${existingAccount.name}`);\n }\n\n const account: Account = {\n id: generateId('acc'),\n name: options.name,\n appId: options.appId,\n appSecret: options.appSecret,\n isDefault: options.isDefault || accounts.length === 0,\n createdAt: new Date(),\n updatedAt: new Date(),\n };\n\n if (account.isDefault) {\n accounts.forEach(a => a.isDefault = false);\n }\n\n accounts.push(account);\n this.configStore.set('accounts', accounts);\n\n this.logger.info('账号添加成功', { id: account.id, name: account.name });\n return account;\n }\n\n async listAccounts(): Promise<Account[]> {\n return this.configStore.get('accounts', []);\n }\n\n async getAccount(id: string): Promise<Account | null> {\n const accounts = await this.listAccounts();\n return accounts.find(a => a.id === id) || null;\n }\n\n async getCurrentAccount(): Promise<Account> {\n const accounts = await this.listAccounts();\n \n if (accounts.length === 0) {\n throw new Error('未配置账号,请先使用 account add 命令添加账号');\n }\n\n const defaultAccount = accounts.find(a => a.isDefault);\n if (defaultAccount) {\n return defaultAccount;\n }\n\n return accounts[0];\n }\n\n async setDefaultAccount(id: string): Promise<void> {\n this.logger.info('设置默认账号', { id });\n\n const accounts = await this.listAccounts();\n const account = accounts.find(a => a.id === id);\n\n if (!account) {\n throw new Error(`账号不存在: ${id}`);\n }\n\n accounts.forEach(a => {\n a.isDefault = a.id === id;\n if (a.id === id) {\n a.updatedAt = new Date();\n }\n });\n\n this.configStore.set('accounts', accounts);\n this.logger.info('默认账号设置成功', { name: account.name });\n }\n\n async removeAccount(id: string): Promise<void> {\n this.logger.info('删除账号', { id });\n\n const accounts = await this.listAccounts();\n const account = accounts.find(a => a.id === id);\n\n if (!account) {\n throw new Error(`账号不存在: ${id}`);\n }\n\n const filtered = accounts.filter(a => a.id !== id);\n\n if (account.isDefault && filtered.length > 0) {\n filtered[0].isDefault = true;\n }\n\n this.configStore.set('accounts', filtered);\n this.logger.info('账号删除成功', { name: account.name });\n }\n\n async updateAccount(id: string, updates: Partial<Account>): Promise<Account> {\n this.logger.info('更新账号', { id });\n\n const accounts = await this.listAccounts();\n const account = accounts.find(a => a.id === id);\n\n if (!account) {\n throw new Error(`账号不存在: ${id}`);\n }\n\n Object.assign(account, updates, { updatedAt: new Date() });\n this.configStore.set('accounts', accounts);\n\n this.logger.info('账号更新成功', { name: account.name });\n return account;\n }\n}\n","import { ThemeEngine } from '../core/theme/ThemeEngine';\nimport { ConfigStore } from '../infrastructure/config/ConfigStore';\nimport { ThemeCache } from '../infrastructure/cache/ThemeCache';\nimport { Logger } from '../infrastructure/logger/Logger';\nimport type { ThemeSource } from '../types/theme';\n\nexport class ThemeService {\n constructor(\n private themeEngine: ThemeEngine,\n private configStore: ConfigStore,\n private themeCache: ThemeCache,\n private logger: Logger\n ) {}\n\n async initialize(): Promise<void> {\n this.logger.info('初始化主题系统');\n\n await this.themeEngine.loadBuiltinThemes();\n\n const config = this.configStore.get('themes');\n if (!config) {\n return;\n }\n\n if (config.local) {\n for (const theme of config.local) {\n try {\n await this.themeEngine.addLocalTheme(theme.name, theme.path);\n } catch (error) {\n this.logger.warn('加载本地主题失败', { name: theme.name, error });\n }\n }\n }\n\n if (config.remote) {\n for (const remote of config.remote) {\n if (remote.enabled) {\n try {\n await this.themeEngine.addRemoteAPI(remote.name, remote.apiUrl, remote.apiKey);\n } catch (error) {\n this.logger.warn('添加远程主题 API 失败', { name: remote.name, error });\n }\n }\n }\n }\n\n this.logger.info('主题系统初始化完成');\n }\n\n async listThemes(): Promise<ThemeSource[]> {\n return await this.themeEngine.listThemes();\n }\n\n async getThemeCSS(themeId: string): Promise<string> {\n const cached = await this.themeCache.getThemeCSS(themeId);\n if (cached) {\n this.logger.debug('使用缓存的主题', { themeId });\n return cached;\n }\n\n const css = await this.themeEngine.getThemeCSS(themeId);\n await this.themeCache.setThemeCSS(themeId, css);\n\n return css;\n }\n\n async addLocalTheme(name: string, path: string): Promise<void> {\n this.logger.info('添加本地主题', { name, path });\n\n await this.themeEngine.addLocalTheme(name, path);\n\n const config = this.configStore.get('themes') || {};\n if (!config.local) {\n config.local = [];\n }\n\n const existing = config.local.find(t => t.name === name);\n if (existing) {\n existing.path = path;\n } else {\n config.local.push({ name, path });\n }\n\n this.configStore.set('themes', config);\n this.logger.info('本地主题添加成功');\n }\n\n async addRemoteAPI(name: string, apiUrl: string, apiKey: string): Promise<void> {\n this.logger.info('添加远程主题 API', { name, apiUrl });\n\n await this.themeEngine.addRemoteAPI(name, apiUrl, apiKey);\n\n const config = this.configStore.get('themes') || {};\n if (!config.remote) {\n config.remote = [];\n }\n\n const existing = config.remote.find(r => r.name === name);\n if (existing) {\n existing.apiUrl = apiUrl;\n existing.apiKey = apiKey;\n existing.enabled = true;\n } else {\n config.remote.push({ name, apiUrl, apiKey, enabled: true });\n }\n\n this.configStore.set('themes', config);\n this.logger.info('远程主题 API 添加成功');\n }\n\n async removeTheme(themeId: string): Promise<void> {\n this.logger.info('删除主题', { themeId });\n\n await this.themeEngine.removeTheme(themeId);\n await this.themeCache.delete(themeId);\n\n const config = this.configStore.get('themes') || {};\n if (config.local) {\n config.local = config.local.filter(t => t.name !== themeId);\n }\n\n this.configStore.set('themes', config);\n this.logger.info('主题删除成功');\n }\n}\n","import { MarkdownRenderer, RenderResult } from '../core/renderer/MarkdownRenderer';\nimport { ThemeService } from './ThemeService';\nimport { Logger } from '../infrastructure/logger/Logger';\nimport { readFileContent } from '../utils/file';\n\nexport interface RenderOptions {\n markdown?: string;\n file?: string;\n theme?: string;\n}\n\nexport class RenderService {\n constructor(\n private renderer: MarkdownRenderer,\n private themeService: ThemeService,\n private logger: Logger\n ) {}\n\n async initialize(): Promise<void> {\n await this.renderer.initialize();\n }\n\n async render(options: RenderOptions): Promise<RenderResult> {\n let markdown: string;\n\n if (options.file) {\n this.logger.info('读取 Markdown 文件', { file: options.file });\n markdown = await readFileContent(options.file);\n } else if (options.markdown) {\n markdown = options.markdown;\n } else {\n throw new Error('必须提供 markdown 内容或 file 路径');\n }\n\n let themeCss: string | undefined;\n if (options.theme) {\n this.logger.info('加载主题', { theme: options.theme });\n themeCss = await this.themeService.getThemeCSS(options.theme);\n }\n\n this.logger.info('开始渲染 Markdown');\n const result = await this.renderer.render(markdown, themeCss);\n this.logger.info('Markdown 渲染完成', { title: result.title });\n\n return result;\n }\n}\n","import { WechatClient } from '../core/wechat/WechatClient';\nimport { RenderService } from './RenderService';\nimport { ImageProcessor } from '../core/renderer/ImageProcessor';\nimport { WrapperService } from './WrapperService';\nimport { Logger } from '../infrastructure/logger/Logger';\nimport type { DraftCreateOptions, Draft, DraftList } from '../types/draft';\nimport { dirname } from 'path';\n\nexport class DraftService {\n constructor(\n private wechatClient: WechatClient,\n private renderService: RenderService,\n private imageProcessor: ImageProcessor,\n private wrapperService: WrapperService,\n private logger: Logger\n ) {}\n\n async create(options: DraftCreateOptions): Promise<{ media_id: string }> {\n this.logger.info('开始创建草稿', { file: options.file });\n\n const rendered = await this.renderService.render({\n markdown: options.markdown,\n file: options.file,\n theme: options.theme,\n });\n\n // 使用 Wrapper 包装内容\n let content = this.wrapperService.wrapContent(rendered.content);\n\n const relativePath = options.relativePath || (options.file ? dirname(options.file) : undefined);\n\n const { content: processedContent, firstImageMediaId } = await this.imageProcessor.processImages(\n content,\n relativePath\n );\n\n const thumbMediaId = await this.imageProcessor.uploadCover(\n rendered.cover,\n relativePath,\n firstImageMediaId,\n processedContent\n );\n\n // 检查正文是否为空\n const textContent = processedContent.replace(/<[^>]+>/g, '').trim();\n if (!textContent) {\n throw new Error('正文内容为空,无法创建草稿。请确保文章包含文字内容。');\n }\n\n const result = await this.wechatClient.draft.create({\n title: rendered.title,\n content: processedContent,\n thumb_media_id: thumbMediaId,\n });\n\n this.logger.info('草稿创建成功', { media_id: result.media_id });\n return result;\n }\n\n async list(page: number = 1, pageSize: number = 20): Promise<DraftList> {\n const offset = (page - 1) * pageSize;\n return await this.wechatClient.draft.list(offset, pageSize);\n }\n\n async get(mediaId: string): Promise<Draft> {\n return await this.wechatClient.draft.get(mediaId);\n }\n\n async delete(mediaId: string): Promise<void> {\n this.logger.info('删除草稿', { media_id: mediaId });\n await this.wechatClient.draft.delete(mediaId);\n this.logger.info('草稿删除成功');\n }\n\n async batchDelete(mediaIds: string[]): Promise<void> {\n this.logger.info('批量删除草稿', { count: mediaIds.length });\n\n const results = await Promise.allSettled(\n mediaIds.map(id => this.delete(id))\n );\n\n const failed = results.filter(r => r.status === 'rejected');\n if (failed.length > 0) {\n this.logger.warn('部分草稿删除失败', {\n failed: failed.length,\n total: mediaIds.length,\n });\n }\n }\n\n async count(): Promise<number> {\n return await this.wechatClient.draft.count();\n }\n}\n","import { WechatClient } from '../core/wechat/WechatClient';\nimport { DraftService } from './DraftService';\nimport { Logger } from '../infrastructure/logger/Logger';\nimport type { PublishResult, PublishedArticle, PublishList, PublishStatus } from '../types/publish';\nimport type { DraftCreateOptions } from '../types/draft';\n\nexport class PublishService {\n constructor(\n private wechatClient: WechatClient,\n private draftService: DraftService,\n private logger: Logger\n ) {}\n\n async submit(mediaId: string): Promise<PublishResult> {\n this.logger.info('发布草稿', { media_id: mediaId });\n const result = await this.wechatClient.publish.submit(mediaId);\n this.logger.info('发布任务提交成功', { publish_id: result.publish_id });\n return result;\n }\n\n async createAndPublish(options: DraftCreateOptions): Promise<PublishResult> {\n this.logger.info('创建并发布文章');\n\n const { media_id } = await this.draftService.create(options);\n const result = await this.submit(media_id);\n\n return result;\n }\n\n async list(page: number = 1, pageSize: number = 20): Promise<PublishList> {\n const offset = (page - 1) * pageSize;\n return await this.wechatClient.publish.list(offset, pageSize);\n }\n\n async get(articleId: string): Promise<PublishedArticle> {\n return await this.wechatClient.publish.get(articleId);\n }\n\n async delete(articleId: string, index: number = 0): Promise<void> {\n this.logger.info('删除已发布文章', { article_id: articleId, index });\n await this.wechatClient.publish.delete(articleId, index);\n this.logger.info('已发布文章删除成功');\n }\n\n async getStatus(publishId: string): Promise<PublishStatus> {\n return await this.wechatClient.publish.getStatus(publishId);\n }\n}\n","import { DatabaseManager } from '../infrastructure/database/DatabaseManager';\nimport { Logger } from '../infrastructure/logger/Logger';\nimport { readFileSync, existsSync } from 'fs';\nimport { resolve, dirname } from 'path';\nimport { fileURLToPath } from 'url';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nexport interface WrapperConfig {\n enabled: boolean;\n header: string;\n footer: string;\n version: number;\n}\n\nexport interface WrapperVersion {\n id: number;\n version: number;\n enabled: number;\n header: string;\n footer: string;\n author: string;\n created_at: string;\n}\n\nexport class WrapperService {\n private dbManager: DatabaseManager;\n private logger: Logger;\n\n constructor(dbManager: DatabaseManager, logger: Logger) {\n this.dbManager = dbManager;\n this.logger = logger;\n }\n\n /**\n * 加载默认配置\n */\n private loadDefaultConfig(): { enabled: boolean; header: string; footer: string } | null {\n try {\n // __dirname 在打包后是 dist/services,需要计算正确路径\n // 全局安装时: /usr/local/lib/node_modules/wechat-md-publisher/dist/services\n // 相对路径到 config: ../config/default-wrapper.json\n const distServicesDir = __dirname;\n const possiblePaths = [\n // 全局安装: node_modules/wechat-md-publisher/dist/services -> node_modules/wechat-md-publisher/config/\n resolve(distServicesDir, '../config/default-wrapper.json'),\n // 本地开发/项目内: 项目根目录/config/\n resolve(process.cwd(), 'config/default-wrapper.json'),\n ];\n \n for (const configPath of possiblePaths) {\n if (existsSync(configPath)) {\n const content = readFileSync(configPath, 'utf-8');\n const config = JSON.parse(content);\n this.logger.debug('成功加载默认配置', { \n configPath,\n headerLength: config.header?.length || 0,\n footerLength: config.footer?.length || 0\n });\n return config;\n }\n }\n \n this.logger.warn('默认配置文件不存在', { \n triedPaths: possiblePaths,\n __dirname: distServicesDir\n });\n } catch (error) {\n this.logger.warn('无法加载默认 wrapper 配置', { error });\n }\n return null;\n }\n\n /**\n * 初始化默认内容(如果数据库为空)\n * 注意:首次使用时会自动插入默认配置(默认为关闭状态)\n */\n private initializeDefaultIfNeeded(): void {\n const db = this.dbManager.getDatabase();\n const result = db.exec('SELECT COUNT(*) as count FROM wrapper_versions');\n \n if (result.length > 0 && result[0].values[0][0] === 0) {\n // 数据库为空,加载默认配置(默认为关闭状态)\n const defaultConfig = this.loadDefaultConfig();\n if (!defaultConfig) {\n throw new Error('无法加载默认 wrapper 配置文件,请确保 config/default-wrapper.json 存在');\n }\n \n db.run(`\n INSERT INTO wrapper_versions (version, enabled, header, footer, author)\n VALUES (1, 0, ?, ?, 'system')\n `, [\n defaultConfig.header,\n defaultConfig.footer\n ]);\n this.dbManager.save();\n this.logger.info('已初始化默认 wrapper 配置(关闭状态)', {\n headerLength: defaultConfig.header.length,\n footerLength: defaultConfig.footer.length\n });\n }\n }\n\n /**\n * 获取当前 Wrapper 配置\n */\n get(): WrapperConfig {\n this.initializeDefaultIfNeeded();\n const db = this.dbManager.getDatabase();\n const result = db.exec(`\n SELECT version, enabled, header, footer \n FROM wrapper_versions \n ORDER BY version DESC \n LIMIT 1\n `);\n\n if (!result.length || !result[0].values.length) {\n return {\n enabled: false,\n header: '',\n footer: '',\n version: 0\n };\n }\n\n const row = result[0].values[0];\n return {\n enabled: row[1] === 1,\n header: row[2] || '',\n footer: row[3] || '',\n version: row[0] as number\n };\n }\n\n /**\n * 开启 Wrapper\n */\n enable(): void {\n const config = this.get();\n if (config.enabled) {\n this.logger.info('Wrapper 已经开启');\n return;\n }\n\n const db = this.dbManager.getDatabase();\n // 直接更新状态为 enabled(get() 已经确保数据存在)\n if (config.version > 0) {\n db.run(`\n UPDATE wrapper_versions \n SET enabled = 1 \n WHERE version = ?\n `, [config.version]);\n } else {\n // 理论上不应该走到这里,因为 get() 会调用 initializeDefaultIfNeeded()\n throw new Error('无法开启 Wrapper:数据库未初始化');\n }\n\n this.dbManager.save();\n this.logger.info('Wrapper 已开启');\n }\n\n /**\n * 关闭 Wrapper\n */\n disable(): void {\n const config = this.get();\n if (!config.enabled) {\n this.logger.info('Wrapper 已经关闭');\n return;\n }\n\n const db = this.dbManager.getDatabase();\n db.run(`\n UPDATE wrapper_versions \n SET enabled = 0 \n WHERE version = ?\n `, [config.version]);\n\n this.dbManager.save();\n this.logger.info('Wrapper 已关闭');\n }\n\n /**\n * 更新 Wrapper 内容(创建新版本)\n */\n update(header: string, footer: string, author: string = 'system'): void {\n const db = this.dbManager.getDatabase();\n const current = this.get();\n const newVersion = current.version + 1;\n\n db.run(`\n INSERT INTO wrapper_versions (version, enabled, header, footer, author)\n VALUES (?, ?, ?, ?, ?)\n `, [newVersion, current.enabled ? 1 : 0, header, footer, author]);\n\n this.dbManager.save();\n this.logger.info('Wrapper 内容已更新', { version: newVersion });\n }\n\n /**\n * 获取历史版本\n */\n history(): WrapperVersion[] {\n const db = this.dbManager.getDatabase();\n const result = db.exec(`\n SELECT * FROM wrapper_versions \n ORDER BY version DESC\n `);\n\n if (!result.length || !result[0].values.length) {\n return [];\n }\n\n return result[0].values.map(row => ({\n id: row[0] as number,\n version: row[1] as number,\n enabled: row[2] as number,\n header: row[3] as string,\n footer: row[4] as string,\n author: row[5] as string,\n created_at: row[6] as string\n }));\n }\n\n /**\n * 回滚到指定版本\n */\n rollback(targetVersion: number, author: string = 'system'): void {\n const db = this.dbManager.getDatabase();\n const current = this.get();\n \n const result = db.exec(`\n SELECT * FROM wrapper_versions WHERE version = ?\n `, [targetVersion]);\n\n if (!result.length || !result[0].values.length) {\n throw new Error(`版本 ${targetVersion} 不存在`);\n }\n\n const target = result[0].values[0];\n const newVersion = current.version + 1;\n\n db.run(`\n INSERT INTO wrapper_versions (version, enabled, header, footer, author)\n VALUES (?, ?, ?, ?, ?)\n `, [newVersion, target[2], target[3], target[4], author]);\n\n this.dbManager.save();\n this.logger.info('已回滚到指定版本', { \n from: current.version, \n to: targetVersion,\n newVersion \n });\n }\n\n /**\n * 将内容包装到文章中\n */\n wrapContent(content: string): string {\n const config = this.get();\n \n if (!config.enabled) {\n return content;\n }\n\n let result = content;\n\n // 插入头部\n if (config.header) {\n result = config.header + '\\n' + result;\n }\n\n // 插入尾部\n if (config.footer) {\n result = result + '\\n' + config.footer;\n }\n\n return result;\n }\n}\n","import { ConfigStore } from './infrastructure/config/ConfigStore';\nimport { TokenCache } from './infrastructure/cache/TokenCache';\nimport { ImageCache } from './infrastructure/cache/ImageCache';\nimport { ThemeCache } from './infrastructure/cache/ThemeCache';\nimport { Logger } from './infrastructure/logger/Logger';\nimport { HttpClient } from './infrastructure/http/HttpClient';\nimport { DatabaseManager } from './infrastructure/database/DatabaseManager';\nimport { WechatClient } from './core/wechat/WechatClient';\nimport { ThemeEngine } from './core/theme/ThemeEngine';\nimport { MarkdownRenderer } from './core/renderer/MarkdownRenderer';\nimport { ImageProcessor } from './core/renderer/ImageProcessor';\nimport { AccountService } from './services/AccountService';\nimport { ThemeService } from './services/ThemeService';\nimport { RenderService } from './services/RenderService';\nimport { DraftService } from './services/DraftService';\nimport { PublishService } from './services/PublishService';\nimport { WrapperService } from './services/WrapperService';\n\nclass Container {\n\n private configStore!: ConfigStore;\n private logger!: Logger;\n private httpClient!: HttpClient;\n private dbManager!: DatabaseManager;\n private tokenCache!: TokenCache;\n private imageCache!: ImageCache;\n private themeCache!: ThemeCache;\n private themeEngine!: ThemeEngine;\n private renderer!: MarkdownRenderer;\n private accountService!: AccountService;\n private themeService!: ThemeService;\n private renderService!: RenderService;\n private wrapperService!: WrapperService;\n\n async initialize(): Promise<void> {\n this.configStore = new ConfigStore();\n this.logger = new Logger();\n this.httpClient = new HttpClient(this.logger);\n this.dbManager = new DatabaseManager(this.logger);\n await this.dbManager.initialize();\n this.tokenCache = new TokenCache();\n this.imageCache = new ImageCache();\n this.themeCache = new ThemeCache();\n this.themeEngine = new ThemeEngine();\n this.renderer = new MarkdownRenderer();\n \n this.accountService = new AccountService(this.configStore, this.logger);\n this.themeService = new ThemeService(\n this.themeEngine,\n this.configStore,\n this.themeCache,\n this.logger\n );\n this.renderService = new RenderService(\n this.renderer,\n this.themeService,\n this.logger\n );\n this.wrapperService = new WrapperService(this.dbManager, this.logger);\n\n await this.themeService.initialize();\n await this.renderService.initialize();\n }\n\n getAccountService(): AccountService {\n return this.accountService;\n }\n\n getThemeService(): ThemeService {\n return this.themeService;\n }\n\n getRenderService(): RenderService {\n return this.renderService;\n }\n\n getWrapperService(): WrapperService {\n return this.wrapperService;\n }\n\n getDatabaseManager(): DatabaseManager {\n return this.dbManager;\n }\n\n async getDraftService(): Promise<DraftService> {\n const account = await this.accountService.getCurrentAccount();\n const wechatClient = new WechatClient(\n account.appId,\n account.appSecret,\n this.httpClient,\n this.tokenCache,\n this.logger\n );\n\n const imageProcessor = new ImageProcessor(\n wechatClient.material,\n this.imageCache,\n this.logger\n );\n\n return new DraftService(\n wechatClient,\n this.renderService,\n imageProcessor,\n this.wrapperService,\n this.logger\n );\n }\n\n async getPublishService(): Promise<PublishService> {\n const draftService = await this.getDraftService();\n const account = await this.accountService.getCurrentAccount();\n const wechatClient = new WechatClient(\n account.appId,\n account.appSecret,\n this.httpClient,\n this.tokenCache,\n this.logger\n );\n\n return new PublishService(\n wechatClient,\n draftService,\n this.logger\n );\n }\n}\n\nexport const container = new Container();\n","import { Command } from 'commander';\nimport { container } from '../../container';\nimport chalk from 'chalk';\nimport Table from 'cli-table3';\n\nexport function createAccountCommand(): Command {\n const cmd = new Command('account')\n .description('账号管理');\n\n cmd.command('add')\n .description('添加微信公众号账号')\n .requiredOption('--name <name>', '账号名称')\n .requiredOption('--app-id <appId>', '微信公众号 AppID')\n .requiredOption('--app-secret <appSecret>', '微信公众号 AppSecret')\n .option('--default', '设为默认账号')\n .action(async (options) => {\n try {\n await container.initialize();\n const accountService = container.getAccountService();\n\n const account = await accountService.addAccount({\n name: options.name,\n appId: options.appId,\n appSecret: options.appSecret,\n isDefault: options.default,\n });\n\n console.log(chalk.green('✓ 账号添加成功'));\n console.log(` ID: ${account.id}`);\n console.log(` 名称: ${account.name}`);\n console.log(` AppID: ${account.appId}`);\n console.log(` 默认账号: ${account.isDefault ? '是' : '否'}`);\n } catch (error: any) {\n console.error(chalk.red('✗ 添加账号失败:'), error.message);\n process.exit(1);\n }\n });\n\n cmd.command('list')\n .description('列出所有账号')\n .action(async () => {\n try {\n await container.initialize();\n const accountService = container.getAccountService();\n const accounts = await accountService.listAccounts();\n\n if (accounts.length === 0) {\n console.log(chalk.yellow('未配置账号'));\n console.log('使用 account add 命令添加账号');\n return;\n }\n\n const table = new Table({\n head: ['ID', '名称', 'AppID', '默认'],\n colWidths: [25, 20, 20, 8],\n });\n\n accounts.forEach(account => {\n table.push([\n account.id,\n account.name,\n account.appId,\n account.isDefault ? chalk.green('是') : '否',\n ]);\n });\n\n console.log(table.toString());\n } catch (error: any) {\n console.error(chalk.red('✗ 获取账号列表失败:'), error.message);\n process.exit(1);\n }\n });\n\n cmd.command('switch <id>')\n .description('切换默认账号')\n .action(async (id) => {\n try {\n await container.initialize();\n const accountService = container.getAccountService();\n await accountService.setDefaultAccount(id);\n console.log(chalk.green('✓ 默认账号切换成功'));\n } catch (error: any) {\n console.error(chalk.red('✗ 切换账号失败:'), error.message);\n process.exit(1);\n }\n });\n\n cmd.command('remove <id>')\n .description('删除账号')\n .action(async (id) => {\n try {\n await container.initialize();\n const accountService = container.getAccountService();\n await accountService.removeAccount(id);\n console.log(chalk.green('✓ 账号删除成功'));\n } catch (error: any) {\n console.error(chalk.red('✗ 删除账号失败:'), error.message);\n process.exit(1);\n }\n });\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { container } from '../../container';\nimport chalk from 'chalk';\nimport Table from 'cli-table3';\n\nexport function createThemeCommand(): Command {\n const cmd = new Command('theme')\n .description('主题管理');\n\n cmd.command('list')\n .description('列出所有可用主题')\n .action(async () => {\n try {\n await container.initialize();\n const themeService = container.getThemeService();\n const themes = await themeService.listThemes();\n\n if (themes.length === 0) {\n console.log(chalk.yellow('未找到主题'));\n return;\n }\n\n const table = new Table({\n head: ['ID', '名称', '类型', '描述'],\n colWidths: [20, 25, 12, 40],\n });\n\n themes.forEach(theme => {\n const typeColor = theme.type === 'builtin' ? chalk.green :\n theme.type === 'local' ? chalk.blue :\n theme.type === 'remote' ? chalk.magenta : chalk.gray;\n \n table.push([\n theme.id,\n theme.name,\n typeColor(theme.type),\n theme.description || '-',\n ]);\n });\n\n console.log(table.toString());\n console.log(`\\n总计: ${themes.length} 个主题`);\n } catch (error: any) {\n console.error(chalk.red('✗ 获取主题列表失败:'), error.message);\n process.exit(1);\n }\n });\n\n cmd.command('add-local')\n .description('添加本地主题')\n .requiredOption('--name <name>', '主题名称')\n .requiredOption('--path <path>', '主题 CSS 文件路径')\n .action(async (options) => {\n try {\n await container.initialize();\n const themeService = container.getThemeService();\n \n await themeService.addLocalTheme(options.name, options.path);\n \n console.log(chalk.green('✓ 本地主题添加成功'));\n console.log(` 名称: ${options.name}`);\n console.log(` 路径: ${options.path}`);\n } catch (error: any) {\n console.error(chalk.red('✗ 添加本地主题失败:'), error.message);\n process.exit(1);\n }\n });\n\n cmd.command('add-remote')\n .description('添加远程主题 API')\n .requiredOption('--name <name>', 'API 名称')\n .requiredOption('--url <url>', 'API URL')\n .requiredOption('--key <key>', 'API Key')\n .action(async (options) => {\n try {\n await container.initialize();\n const themeService = container.getThemeService();\n \n await themeService.addRemoteAPI(options.name, options.url, options.key);\n \n console.log(chalk.green('✓ 远程主题 API 添加成功'));\n console.log(` 名称: ${options.name}`);\n console.log(` URL: ${options.url}`);\n } catch (error: any) {\n console.error(chalk.red('✗ 添加远程主题 API 失败:'), error.message);\n process.exit(1);\n }\n });\n\n cmd.command('remove <theme-id>')\n .description('删除主题')\n .action(async (themeId) => {\n try {\n await container.initialize();\n const themeService = container.getThemeService();\n \n await themeService.removeTheme(themeId);\n \n console.log(chalk.green('✓ 主题删除成功'));\n } catch (error: any) {\n console.error(chalk.red('✗ 删除主题失败:'), error.message);\n process.exit(1);\n }\n });\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { container } from '../../container';\nimport chalk from 'chalk';\nimport Table from 'cli-table3';\nimport ora from 'ora';\n\nexport function createDraftCommand(): Command {\n const cmd = new Command('draft')\n .description('草稿管理');\n\n cmd.command('create')\n .description('创建草稿')\n .requiredOption('-f, --file <file>', 'Markdown 文件路径')\n .option('-t, --theme <theme>', '主题 ID')\n .action(async (options) => {\n const spinner = ora('正在创建草稿...').start();\n \n try {\n await container.initialize();\n const draftService = await container.getDraftService();\n \n const result = await draftService.create({\n file: options.file,\n theme: options.theme,\n });\n \n spinner.succeed('草稿创建成功');\n console.log(chalk.green(` Media ID: ${result.media_id}`));\n console.log(chalk.gray(' 提示: 使用 publish 命令发布此草稿'));\n } catch (error: any) {\n spinner.fail('创建草稿失败');\n console.error(chalk.red(error.message));\n process.exit(1);\n }\n });\n\n cmd.command('list')\n .description('列出草稿')\n .option('-p, --page <page>', '页码', '1')\n .option('-s, --size <size>', '每页数量', '20')\n .action(async (options) => {\n const spinner = ora('正在获取草稿列表...').start();\n \n try {\n await container.initialize();\n const draftService = await container.getDraftService();\n \n const page = parseInt(options.page);\n const size = parseInt(options.size);\n const result = await draftService.list(page, size);\n \n spinner.stop();\n \n if (!result.item || result.item.length === 0) {\n console.log(chalk.yellow('暂无草稿'));\n return;\n }\n\n const table = new Table({\n head: ['Media ID', '标题', '更新时间'],\n colWidths: [35, 40, 20],\n });\n\n result.item.forEach(draft => {\n const article = draft.content.news_item[0];\n const updateTime = new Date(draft.update_time * 1000).toLocaleString('zh-CN');\n \n table.push([\n draft.media_id,\n article.title || '-',\n updateTime,\n ]);\n });\n\n console.log(table.toString());\n console.log(`\\n总计: ${result.total_count} 个草稿 (第 ${page} 页)`);\n } catch (error: any) {\n spinner.fail('获取草稿列表失败');\n console.error(chalk.red(error.message));\n process.exit(1);\n }\n });\n\n cmd.command('delete <media-id>')\n .description('删除草稿')\n .action(async (mediaId) => {\n const spinner = ora('正在删除草稿...').start();\n \n try {\n await container.initialize();\n const draftService = await container.getDraftService();\n \n await draftService.delete(mediaId);\n \n spinner.succeed('草稿删除成功');\n } catch (error: any) {\n spinner.fail('删除草稿失败');\n console.error(chalk.red(error.message));\n process.exit(1);\n }\n });\n\n cmd.command('count')\n .description('获取草稿总数')\n .action(async () => {\n try {\n await container.initialize();\n const draftService = await container.getDraftService();\n \n const count = await draftService.count();\n \n console.log(chalk.green(`草稿总数: ${count}`));\n } catch (error: any) {\n console.error(chalk.red('✗ 获取草稿总数失败:'), error.message);\n process.exit(1);\n }\n });\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { container } from '../../container';\nimport chalk from 'chalk';\nimport Table from 'cli-table3';\nimport ora from 'ora';\n\nexport function createPublishCommand(): Command {\n const cmd = new Command('publish')\n .description('发布管理');\n\n cmd.command('submit <media-id>')\n .description('发布草稿')\n .action(async (mediaId) => {\n const spinner = ora('正在发布草稿...').start();\n \n try {\n await container.initialize();\n const publishService = await container.getPublishService();\n \n const result = await publishService.submit(mediaId);\n \n spinner.succeed('发布任务提交成功');\n console.log(chalk.green(` Publish ID: ${result.publish_id}`));\n console.log(chalk.gray(' 提示: 使用 publish status 命令查看发布状态'));\n } catch (error: any) {\n spinner.fail('发布失败');\n console.error(chalk.red(error.message));\n process.exit(1);\n }\n });\n\n cmd.command('create')\n .description('创建并发布文章')\n .requiredOption('-f, --file <file>', 'Markdown 文件路径')\n .option('-t, --theme <theme>', '主题 ID')\n .action(async (options) => {\n const spinner = ora('正在创建并发布文章...').start();\n \n try {\n await container.initialize();\n const publishService = await container.getPublishService();\n \n const result = await publishService.createAndPublish({\n file: options.file,\n theme: options.theme,\n });\n \n spinner.succeed('文章创建并发布成功');\n console.log(chalk.green(` Publish ID: ${result.publish_id}`));\n } catch (error: any) {\n spinner.fail('创建并发布失败');\n console.error(chalk.red(error.message));\n process.exit(1);\n }\n });\n\n cmd.command('list')\n .description('列出已发布文章')\n .option('-p, --page <page>', '页码', '1')\n .option('-s, --size <size>', '每页数量', '20')\n .action(async (options) => {\n const spinner = ora('正在获取已发布文章列表...').start();\n \n try {\n await container.initialize();\n const publishService = await container.getPublishService();\n \n const page = parseInt(options.page);\n const size = parseInt(options.size);\n const result = await publishService.list(page, size);\n \n spinner.stop();\n \n if (!result.item || result.item.length === 0) {\n console.log(chalk.yellow('暂无已发布文章'));\n return;\n }\n\n const table = new Table({\n head: ['Article ID', '标题', '更新时间'],\n colWidths: [35, 40, 20],\n });\n\n result.item.forEach(article => {\n const newsItem = article.content.news_item[0];\n const updateTime = new Date(article.update_time * 1000).toLocaleString('zh-CN');\n \n table.push([\n article.article_id,\n newsItem.title || '-',\n updateTime,\n ]);\n });\n\n console.log(table.toString());\n console.log(`\\n总计: ${result.total_count} 篇文章 (第 ${page} 页)`);\n } catch (error: any) {\n spinner.fail('获取已发布文章列表失败');\n console.error(chalk.red(error.message));\n process.exit(1);\n }\n });\n\n cmd.command('delete <article-id>')\n .description('删除已发布文章')\n .option('-i, --index <index>', '文章索引', '0')\n .action(async (articleId, options) => {\n const spinner = ora('正在删除已发布文章...').start();\n \n try {\n await container.initialize();\n const publishService = await container.getPublishService();\n \n const index = parseInt(options.index);\n await publishService.delete(articleId, index);\n \n spinner.succeed('已发布文章删除成功');\n } catch (error: any) {\n spinner.fail('删除已发布文章失败');\n console.error(chalk.red(error.message));\n process.exit(1);\n }\n });\n\n cmd.command('status <publish-id>')\n .description('查询发布状态')\n .action(async (publishId) => {\n try {\n await container.initialize();\n const publishService = await container.getPublishService();\n \n const status = await publishService.getStatus(publishId);\n \n console.log(chalk.green('发布状态:'));\n console.log(` Publish ID: ${status.publish_id}`);\n console.log(` 状态: ${status.publish_status === 0 ? '成功' : '失败'}`);\n \n if (status.article_id) {\n console.log(` Article ID: ${status.article_id}`);\n }\n \n if (status.article_detail) {\n console.log(` 文章数量: ${status.article_detail.count}`);\n }\n } catch (error: any) {\n console.error(chalk.red('✗ 查询发布状态失败:'), error.message);\n process.exit(1);\n }\n });\n\n return cmd;\n}\n","import { Command } from 'commander';\nimport { container } from '../../container';\nimport chalk from 'chalk';\nimport Table from 'cli-table3';\n\nexport function createWrapperCommand(): Command {\n const cmd = new Command('wrapper')\n .description('文章包装功能管理(开头/结尾固定图文)');\n\n // 获取当前状态\n cmd.command('status')\n .description('查看当前 Wrapper 状态')\n .action(async () => {\n try {\n await container.initialize();\n const wrapperService = await container.getWrapperService();\n const config = wrapperService.get();\n\n console.log(chalk.green('当前状态:'));\n console.log(` 开关: ${config.enabled ? chalk.green('开启') : chalk.red('关闭')}`);\n console.log(` 版本: ${config.version}`);\n \n if (config.header) {\n console.log(chalk.cyan('\\n 头部内容:'));\n console.log(chalk.gray(' ' + config.header.substring(0, 100) + (config.header.length > 100 ? '...' : '')));\n }\n \n if (config.footer) {\n console.log(chalk.cyan('\\n 尾部内容:'));\n console.log(chalk.gray(' ' + config.footer.substring(0, 100) + (config.footer.length > 100 ? '...' : '')));\n }\n } catch (error: any) {\n console.error(chalk.red('✗ 获取状态失败:'), error.message);\n process.exit(1);\n }\n });\n\n // 开启\n cmd.command('on')\n .description('开启 Wrapper 功能')\n .action(async () => {\n try {\n await container.initialize();\n const wrapperService = await container.getWrapperService();\n wrapperService.enable();\n console.log(chalk.green('✓ Wrapper 已开启'));\n } catch (error: any) {\n console.error(chalk.red('✗ 开启失败:'), error.message);\n process.exit(1);\n }\n });\n\n // 关闭\n cmd.command('off')\n .description('关闭 Wrapper 功能')\n .action(async () => {\n try {\n await container.initialize();\n const wrapperService = await container.getWrapperService();\n wrapperService.disable();\n console.log(chalk.green('✓ Wrapper 已关闭'));\n } catch (error: any) {\n console.error(chalk.red('✗ 关闭失败:'), error.message);\n process.exit(1);\n }\n });\n\n // 设置内容\n cmd.command('set')\n .description('更新 Wrapper 内容')\n .option('-h, --header <text>', '头部 HTML 内容')\n .option('-f, --footer <text>', '尾部 HTML 内容')\n .option('-a, --author <name>', '作者名称', 'system')\n .action(async (options) => {\n try {\n await container.initialize();\n const wrapperService = await container.getWrapperService();\n \n wrapperService.update(\n options.header || '', \n options.footer || '',\n options.author\n );\n \n console.log(chalk.green('✓ Wrapper 内容已更新(创建新版本)'));\n } catch (error: any) {\n console.error(chalk.red('✗ 更新失败:'), error.message);\n process.exit(1);\n }\n });\n\n // 查看历史\n cmd.command('history')\n .description('查看历史版本')\n .action(async () => {\n try {\n await container.initialize();\n const wrapperService = await container.getWrapperService();\n const versions = wrapperService.history();\n\n if (versions.length === 0) {\n console.log(chalk.yellow('暂无历史版本'));\n return;\n }\n\n const table = new Table({\n head: ['版本', '状态', '作者', '创建时间'],\n colWidths: [10, 10, 15, 20],\n });\n\n versions.forEach(v => {\n table.push([\n `v${v.version}`,\n v.enabled ? chalk.green('开启') : chalk.red('关闭'),\n v.author,\n new Date(v.created_at).toLocaleString('zh-CN'),\n ]);\n });\n\n console.log(table.toString());\n } catch (error: any) {\n console.error(chalk.red('✗ 获取历史失败:'), error.message);\n process.exit(1);\n }\n });\n\n // 回滚\n cmd.command('rollback <version>')\n .description('回滚到指定版本')\n .option('-a, --author <name>', '作者名称', 'system')\n .action(async (versionStr, options) => {\n try {\n await container.initialize();\n const wrapperService = await container.getWrapperService();\n \n const version = parseInt(versionStr);\n wrapperService.rollback(version, options.author);\n \n console.log(chalk.green(`✓ 已回滚到 v${version}`));\n } catch (error: any) {\n console.error(chalk.red('✗ 回滚失败:'), error.message);\n process.exit(1);\n }\n });\n\n return cmd;\n}\n","#!/usr/bin/env node\nimport { Command } from 'commander';\nimport { readFileSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport { createAccountCommand } from './commands/account';\nimport { createThemeCommand } from './commands/theme';\nimport { createDraftCommand } from './commands/draft';\nimport { createPublishCommand } from './commands/publish';\nimport { createWrapperCommand } from './commands/wrapper';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nconst packageJson = JSON.parse(\n readFileSync(join(__dirname, '../package.json'), 'utf-8')\n);\n\nconst program = new Command();\n\nprogram\n .name('wechat-pub')\n .description('全功能微信公众号 Markdown 发布工具')\n .version(packageJson.version);\n\nprogram.addCommand(createAccountCommand());\nprogram.addCommand(createThemeCommand());\nprogram.addCommand(createDraftCommand());\nprogram.addCommand(createPublishCommand());\nprogram.addCommand(createWrapperCommand());\n\nprogram.parse();\n"],"names":["__filename","__dirname"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
#wenyan h1 {
|
|
19
|
-
font-size:
|
|
19
|
+
font-size: 20px;
|
|
20
20
|
font-weight: 700;
|
|
21
21
|
margin: 1.5em 0 1em;
|
|
22
22
|
padding-bottom: 0.3em;
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
#wenyan h2 {
|
|
29
|
-
font-size:
|
|
29
|
+
font-size: 18px;
|
|
30
30
|
font-weight: 600;
|
|
31
31
|
margin: 1.3em 0 0.8em;
|
|
32
32
|
padding-left: 10px;
|
|
@@ -116,11 +116,13 @@
|
|
|
116
116
|
text-align: left;
|
|
117
117
|
font-weight: 600;
|
|
118
118
|
border: 1px solid var(--border-color);
|
|
119
|
+
background-color: var(--border-color);
|
|
119
120
|
}
|
|
120
121
|
|
|
121
122
|
#wenyan table td {
|
|
122
123
|
padding: 12px;
|
|
123
124
|
border: 1px solid var(--border-color);
|
|
125
|
+
text-align: left;
|
|
124
126
|
}
|
|
125
127
|
|
|
126
128
|
#wenyan hr {
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
#wenyan h1 {
|
|
19
|
-
font-size:
|
|
19
|
+
font-size: 20px;
|
|
20
20
|
font-weight: 700;
|
|
21
21
|
margin: 1.5em 0 1em;
|
|
22
22
|
padding-bottom: 0.3em;
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
#wenyan h2 {
|
|
29
|
-
font-size:
|
|
29
|
+
font-size: 18px;
|
|
30
30
|
font-weight: 600;
|
|
31
31
|
margin: 1.3em 0 0.8em;
|
|
32
32
|
padding-left: 10px;
|
|
@@ -116,11 +116,13 @@
|
|
|
116
116
|
text-align: left;
|
|
117
117
|
font-weight: 600;
|
|
118
118
|
border: 1px solid var(--border-color);
|
|
119
|
+
background-color: var(--border-color);
|
|
119
120
|
}
|
|
120
121
|
|
|
121
122
|
#wenyan table td {
|
|
122
123
|
padding: 12px;
|
|
123
124
|
border: 1px solid var(--border-color);
|
|
125
|
+
text-align: left;
|
|
124
126
|
}
|
|
125
127
|
|
|
126
128
|
#wenyan hr {
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
#wenyan h1 {
|
|
19
|
-
font-size:
|
|
19
|
+
font-size: 20px;
|
|
20
20
|
font-weight: 700;
|
|
21
21
|
margin: 1.5em 0 1em;
|
|
22
22
|
padding-bottom: 0.3em;
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
#wenyan h2 {
|
|
29
|
-
font-size:
|
|
29
|
+
font-size: 18px;
|
|
30
30
|
font-weight: 600;
|
|
31
31
|
margin: 1.3em 0 0.8em;
|
|
32
32
|
padding-left: 10px;
|
|
@@ -116,11 +116,13 @@
|
|
|
116
116
|
text-align: left;
|
|
117
117
|
font-weight: 600;
|
|
118
118
|
border: 1px solid var(--border-color);
|
|
119
|
+
background-color: var(--border-color);
|
|
119
120
|
}
|
|
120
121
|
|
|
121
122
|
#wenyan table td {
|
|
122
123
|
padding: 12px;
|
|
123
124
|
border: 1px solid var(--border-color);
|
|
125
|
+
text-align: left;
|
|
124
126
|
}
|
|
125
127
|
|
|
126
128
|
#wenyan hr {
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
#wenyan h1 {
|
|
19
|
-
font-size:
|
|
19
|
+
font-size: 20px;
|
|
20
20
|
font-weight: 700;
|
|
21
21
|
margin: 1.5em 0 1em;
|
|
22
22
|
padding-bottom: 0.3em;
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
#wenyan h2 {
|
|
29
|
-
font-size:
|
|
29
|
+
font-size: 18px;
|
|
30
30
|
font-weight: 600;
|
|
31
31
|
margin: 1.3em 0 0.8em;
|
|
32
32
|
padding-left: 10px;
|
|
@@ -116,11 +116,13 @@
|
|
|
116
116
|
text-align: left;
|
|
117
117
|
font-weight: 600;
|
|
118
118
|
border: 1px solid var(--border-color);
|
|
119
|
+
background-color: var(--border-color);
|
|
119
120
|
}
|
|
120
121
|
|
|
121
122
|
#wenyan table td {
|
|
122
123
|
padding: 12px;
|
|
123
124
|
border: 1px solid var(--border-color);
|
|
125
|
+
text-align: left;
|
|
124
126
|
}
|
|
125
127
|
|
|
126
128
|
#wenyan hr {
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
#wenyan h1 {
|
|
19
|
-
font-size:
|
|
19
|
+
font-size: 20px;
|
|
20
20
|
font-weight: 700;
|
|
21
21
|
margin: 1.5em 0 1em;
|
|
22
22
|
padding-bottom: 0.3em;
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
#wenyan h2 {
|
|
29
|
-
font-size:
|
|
29
|
+
font-size: 18px;
|
|
30
30
|
font-weight: 600;
|
|
31
31
|
margin: 1.3em 0 0.8em;
|
|
32
32
|
padding-left: 10px;
|
|
@@ -116,11 +116,13 @@
|
|
|
116
116
|
text-align: left;
|
|
117
117
|
font-weight: 600;
|
|
118
118
|
border: 1px solid var(--border-color);
|
|
119
|
+
background-color: var(--border-color);
|
|
119
120
|
}
|
|
120
121
|
|
|
121
122
|
#wenyan table td {
|
|
122
123
|
padding: 12px;
|
|
123
124
|
border: 1px solid var(--border-color);
|
|
125
|
+
text-align: left;
|
|
124
126
|
}
|
|
125
127
|
|
|
126
128
|
#wenyan hr {
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
#wenyan h1 {
|
|
19
|
-
font-size:
|
|
19
|
+
font-size: 20px;
|
|
20
20
|
font-weight: 700;
|
|
21
21
|
margin: 1.5em 0 1em;
|
|
22
22
|
padding-bottom: 0.3em;
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
#wenyan h2 {
|
|
29
|
-
font-size:
|
|
29
|
+
font-size: 18px;
|
|
30
30
|
font-weight: 600;
|
|
31
31
|
margin: 1.3em 0 0.8em;
|
|
32
32
|
padding-left: 10px;
|
|
@@ -109,6 +109,7 @@
|
|
|
109
109
|
width: 100%;
|
|
110
110
|
border-collapse: collapse;
|
|
111
111
|
margin: 1.5em 0;
|
|
112
|
+
font-size: 14px;
|
|
112
113
|
}
|
|
113
114
|
|
|
114
115
|
#wenyan table th {
|
|
@@ -116,11 +117,13 @@
|
|
|
116
117
|
text-align: left;
|
|
117
118
|
font-weight: 600;
|
|
118
119
|
border: 1px solid var(--border-color);
|
|
120
|
+
background-color: var(--border-color);
|
|
119
121
|
}
|
|
120
122
|
|
|
121
123
|
#wenyan table td {
|
|
122
124
|
padding: 12px;
|
|
123
125
|
border: 1px solid var(--border-color);
|
|
126
|
+
text-align: left;
|
|
124
127
|
}
|
|
125
128
|
|
|
126
129
|
#wenyan hr {
|