diff --git a/packages/taro-plugin-mini-ci/package.json b/packages/taro-plugin-mini-ci/package.json index 3e751adbc791..447fedf38c1b 100644 --- a/packages/taro-plugin-mini-ci/package.json +++ b/packages/taro-plugin-mini-ci/package.json @@ -49,7 +49,8 @@ "jd-miniprogram-ci": "^1.0.5", "minidev": "^2.1.5", "miniprogram-ci": "^1.9.15", - "tt-ide-cli": "^0.1.25" + "tt-ide-cli": "^0.1.25", + "xhs-mp-cli": ">=1.9.6" }, "peerDependenciesMeta": { "dingtalk-miniapp-opensdk": { @@ -63,6 +64,9 @@ }, "tt-ide-cli": { "optional": true + }, + "xhs-mp-cli": { + "optional": true } } } diff --git a/packages/taro-plugin-mini-ci/src/BaseCi.ts b/packages/taro-plugin-mini-ci/src/BaseCi.ts index e9ed166b003c..dd930cbae33f 100644 --- a/packages/taro-plugin-mini-ci/src/BaseCi.ts +++ b/packages/taro-plugin-mini-ci/src/BaseCi.ts @@ -126,6 +126,13 @@ export interface JdConfig { ignores?: string[] } +export interface XhsConfig { + /** 小红书小程序appid */ + appid: string + /** 秘钥信息 */ + token?: string +} + export interface CIOptions { /** 发布版本号,默认取 package.json 文件的 taroConfig.version 字段 */ version?: string @@ -145,6 +152,8 @@ export interface CIOptions { swan?: SwanConfig /** 京东小程序配置, 官方文档地址:https://mp-docs.jd.com/doc/dev/devtools/1597 */ jd?: JdConfig + /** 小程序配置, 官方文档地址:https://miniapp.xiaohongshu.com/docs?path=/docs/ide/xhs-mp-cli */ + xhs?: XhsConfig } export default abstract class BaseCI { diff --git a/packages/taro-plugin-mini-ci/src/XhsCI.ts b/packages/taro-plugin-mini-ci/src/XhsCI.ts new file mode 100644 index 000000000000..511e8bb34082 --- /dev/null +++ b/packages/taro-plugin-mini-ci/src/XhsCI.ts @@ -0,0 +1,137 @@ +/* eslint-disable no-console */ +import * as path from 'node:path' + +import BaseCI from './BaseCi' +import { getNpmPkgSync } from './utils/npm' +import { printQrcode2Terminal } from './utils/qrcode' + +export default class XhsCI extends BaseCI { + xhs + + init() { + if (this.pluginOpts.xhs == null) { + throw new Error('请为"@tarojs/plugin-mini-ci"插件配置 "xhs" 选项') + } + const { printLog, processTypeEnum, chalk } = this.ctx.helper + const { token, appid } = this.pluginOpts.xhs! + try { + // 调试使用版本是: xhs-mp-cli@1.9.6 + this.xhs = getNpmPkgSync('xhs-mp-cli', process.cwd()).default + } catch (error) { + printLog(processTypeEnum.ERROR, chalk.red('请安装依赖:xhs-mp-cli')) + process.exit(1) + } + + try { + this.xhs.setAppConfig({ + appId: appid, + config: { + token: token, + }, + }) + } catch (error) { + printLog( + processTypeEnum.ERROR, + chalk.red('请检查小红书小程序 appid 和 token 是否正确') + ) + process.exit(1) + } + } + + async open() { + const { printLog, processTypeEnum } = this.ctx.helper + printLog( + processTypeEnum.WARNING, + '小红书小程序不支持 "--open" 参数打开开发者工具' + ) + } + + async preview() { + const { chalk, printLog, processTypeEnum } = this.ctx.helper + try { + printLog(processTypeEnum.START, '预览小红书小程序') + const result = await this.xhs.preview({ + project: { + projectPath: this.projectPath, + }, + }) + const qrContent = result.qrcodeUrl + await printQrcode2Terminal(qrContent) + const previewQrcodePath = path.join(this.projectPath, 'preview.png') + printLog( + processTypeEnum.REMIND, + `预览二维码已生成,存储在:"${previewQrcodePath}",二维码内容是:${qrContent}` + ) + this.triggerPreviewHooks({ + success: true, + data: { + platform: 'xhs', + qrCodeContent: qrContent, + qrCodeLocalPath: previewQrcodePath, + }, + }) + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } catch (error: any) { + printLog( + processTypeEnum.ERROR, + chalk.red(`上传失败 ${new Date().toLocaleString()} \n${error}`) + ) + + this.triggerPreviewHooks({ + success: false, + data: { + platform: 'xhs', + qrCodeContent: '', + qrCodeLocalPath: '', + }, + error: new Error(error), + }) + } + } + + async upload() { + const { chalk, printLog, processTypeEnum } = this.ctx.helper + try { + printLog(processTypeEnum.START, '上传代码到小红书开放平台') + printLog( + processTypeEnum.REMIND, + `本次上传版本号为:"${this.version}",上传描述为:“${this.desc}”` + ) + const uploadQrcodePath = path.join(this.projectPath, 'upload.png') + await this.xhs.upload({ + project: { + projectPath: this.projectPath, + }, + version: this.version, + desc: this.desc, + }) + console.log( + chalk.green(`体验版上传成功 ${new Date().toLocaleString()}\n`) + ) + this.triggerUploadHooks({ + success: true, + data: { + platform: 'xhs', + qrCodeContent: '', + qrCodeLocalPath: uploadQrcodePath, + }, + }) + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } catch (error: any) { + printLog( + processTypeEnum.ERROR, + chalk.red(`上传失败 ${new Date().toLocaleString()} \n${error}`) + ) + + this.triggerUploadHooks({ + success: false, + data: { + platform: 'xhs', + qrCodeContent: '', + qrCodeLocalPath: '', + }, + error: new Error(error), + }) + } + } +} diff --git a/packages/taro-plugin-mini-ci/src/index.ts b/packages/taro-plugin-mini-ci/src/index.ts index 7a660f9425f0..aef9941501d4 100644 --- a/packages/taro-plugin-mini-ci/src/index.ts +++ b/packages/taro-plugin-mini-ci/src/index.ts @@ -9,6 +9,7 @@ import JdCI from './JdCI' import SwanCI from './SwanCI' import TTCI from './TTCI' import WeappCI from './WeappCI' +import XhsCI from './XhsCI' import type { IPluginContext } from '@tarojs/service' @@ -141,6 +142,9 @@ export default (ctx: IPluginContext, _pluginOpts: CIOptions | (() => CIOptions)) case 'jd': ci = new JdCI(ctx, pluginOpts) break + case 'xhs': + ci = new XhsCI(ctx, pluginOpts) + break default: break }