@ttmg/cli 0.0.12-beta.7 → 0.0.12-beta.8

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../src/h5/config/index.js","../src/h5/init/inject.js","../src/h5/init/index.js","../src/h5/dev/index.js","../src/h5/bundle/manifest.js","../src/h5/bundle/index.js","../src/libs/openUrl.ts","../src/libs/getLocalIP.ts","../src/native/dev/config/index.ts","../src/native/dev/utils/devServer.ts","../src/native/dev/utils/getClientKey.ts","../src/native/dev/utils/compileUpload.ts","../src/native/dev/utils/showSchema.ts","../src/libs/centerQRCode.ts","../src/native/dev/index.ts","../src/native/dev/utils/watchChange.ts","../src/index.ts"],"sourcesContent":["module.exports = {\n CONFIG_FILE_NAME: 'minigame.config.json',\n SDK_URL: 'https://connect.tiktok-minis.com/game/sdk.js',\n VCONSOLE_URL: 'https://connect.tiktok-minis.com/libs/vConsole.js',\n VCONSOLE_INIT: `\n if(typeof VConsole === 'function') {\n window.vConsole = new VConsole();\n }\n `,\n MINIS_MANIFEST_FILE_NAME: 'minis.manifest.json',\n MINIS_RUNTIME_URL: 'https://www.tiktok.com/minigames/runtime',\n};\n","const fs = require('fs');\nconst jsdom = require('jsdom');\nconst prettier = require('prettier');\nconst chalk = require('chalk');\nconst { JSDOM } = jsdom;\nconst {\n CONFIG_FILE_NAME,\n SDK_URL,\n VCONSOLE_URL,\n VCONSOLE_INIT,\n} = require('../config');\nconst CONFIG_PATH = `${process.cwd()}/${CONFIG_FILE_NAME}`;\nconst INDEX_HTML_PATH = `${process.cwd()}/index.html`;\n\nfunction isSandbox(clientKey) {\n /**\n * sb 开头的 clientKey 都是 sandbox 环境\n */\n return clientKey.startsWith('sb');\n}\n// 判断是否是 TTMinis.game.init 的初始化脚本\nfunction isTTMinisInitScript(script, clientKey) {\n if (!script.innerHTML) return false;\n return (\n script.innerHTML.includes('TTMinis.game.init') &&\n script.innerHTML.includes(clientKey)\n );\n}\n\nasync function injectScripts({ config, clientKey }) {\n // 1. 检查 config 文件是否已存在\n fs.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2));\n\n // 2. 读取 index.html\n if (!fs.existsSync(INDEX_HTML_PATH)) {\n console.error('index.html does not exist');\n return;\n }\n const indexHtml = fs.readFileSync(INDEX_HTML_PATH, 'utf8');\n const dom = new JSDOM(indexHtml);\n const { document } = dom.window;\n\n // 3. head 标签\n let head = document.querySelector('head');\n if (!head) {\n head = document.createElement('head');\n document.documentElement.insertBefore(head, document.body);\n }\n\n // 4. 检查是否已注入 SDK\n const scriptList = Array.from(document.querySelectorAll('script'));\n const hasSDK = scriptList.some(\n script => script.src && script.src.includes(SDK_URL),\n );\n\n // 5. 检查是否已注入 vConsole\n const hasVConsole = scriptList.some(\n script => script.src && script.src.includes('vConsole.js'),\n );\n\n let lastInitScript = null;\n if (!hasSDK) {\n // 插入 SDK 脚本\n const sdkScript = document.createElement('script');\n sdkScript.src = SDK_URL;\n head.insertBefore(sdkScript, head.firstChild);\n\n // 插入 SDK init 脚本\n const initScript = document.createElement('script');\n initScript.innerHTML = `\n window.TTMinis = TTMinis;\n TTMinis.game.init({\n clientKey: \"${clientKey}\",\n });\n `;\n head.insertBefore(initScript, sdkScript.nextSibling);\n lastInitScript = initScript;\n } else {\n // 已经有 SDK,查找 TTMinis.game.init 脚本\n const headScripts = Array.from(head.querySelectorAll('script'));\n lastInitScript = headScripts.find(script =>\n isTTMinisInitScript(script, clientKey),\n );\n if (lastInitScript) {\n console.log('JS SDK 已接入,跳过 SDK 相关脚本注入');\n } else {\n // 没有 TTMinis.game.init,则查找最后一个 SDK 脚本\n const sdkScripts = headScripts.filter(\n script => script.src && script.src.includes(SDK_URL),\n );\n if (sdkScripts.length > 0) {\n lastInitScript = sdkScripts[sdkScripts.length - 1];\n }\n }\n }\n\n /**\n * 只有 Sandbox 环境才需要注入 vConsole\n */\n if (isSandbox(clientKey)) {\n console.log('Sandbox 环境,跳过 vConsole 相关脚本注入');\n // 8. 插入 vConsole 相关脚本(如果需要)\n if (!hasVConsole) {\n // vConsole 相关脚本的插入点\n let insertAfterNode = lastInitScript;\n if (insertAfterNode) {\n insertAfterNode = insertAfterNode.nextSibling;\n } else {\n insertAfterNode = head.firstChild;\n }\n\n // vConsole 源码\n const vconsoleSourceScript = document.createElement('script');\n vconsoleSourceScript.src = VCONSOLE_URL;\n // vConsole 初始化\n const vconsoleInitScript = document.createElement('script');\n vconsoleInitScript.innerHTML = VCONSOLE_INIT;\n\n head.insertBefore(vconsoleSourceScript, insertAfterNode);\n head.insertBefore(vconsoleInitScript, insertAfterNode);\n }\n }\n\n // 9. 格式化并写回 index.html\n const formattedHtml = await prettier.format(dom.serialize(), {\n parser: 'html',\n });\n fs.writeFileSync(INDEX_HTML_PATH, formattedHtml);\n console.log(\n chalk.green.bold(\n 'TikTok H5 Mini Game initialization has been completed...',\n ),\n );\n}\n\nmodule.exports = injectScripts;\n","const inquirer = require('inquirer');\nconst inject = require('./inject');\n\nmodule.exports = function init() {\n const promptModule = inquirer.createPromptModule();\n promptModule([\n {\n type: 'input',\n name: 'clientKey',\n message: 'Please input client key',\n },\n {\n type: 'input',\n name: 'devPort',\n message: 'Please input dev port',\n default: 9527,\n },\n ]).then(async answers => {\n const { clientKey, devPort } = answers;\n const config = {\n _comment: `orientation is the orientation of the game. It can be either 'VERTICAL' or 'HORIZONTAL'.our game default is VERTICAL; minigame.config.json dev is a configuration file for minigame development. You can use it to configure the minigame.`,\n orientation: 'VERTICAL',\n dev: {\n port: devPort,\n },\n };\n\n inject({ clientKey, config });\n });\n};\n","const express = require('express');\nconst path = require('path');\nconst fs = require('fs');\nconst chalk = require('chalk');\nconst cheerio = require('cheerio');\nconst app = express();\nconst crypto = require('crypto');\n// const open = require('open'); // 引入 open 包\nconst { CONFIG_FILE_NAME, MINIS_RUNTIME_URL } = require('../config');\n\n// 1. 检查配置文件是否存在\nmodule.exports = function dev() {\n const configPath = path.join(process.cwd(), CONFIG_FILE_NAME);\n if (!fs.existsSync(configPath)) {\n console.log(\n chalk.red.bold(\n `${CONFIG_FILE_NAME} is not exist, please run minis game init first`,\n ),\n );\n return;\n }\n\n // 2. 读取配置\n const gameConfig = JSON.parse(fs.readFileSync(configPath, 'utf8'));\n const devPort = gameConfig.dev?.port || 9527;\n\n // 3. 打印开发前提示\n console.log(\n chalk.yellow.bold(\n `⚠️ Before dev, please ensure:\\n 1. The account used to login www.tiktok.com is in the sandbox target user range of Minis developer platform, otherwise login authorization will throw an error.\\n 2. The browser allows www.tiktok.com <popup and redirect>, because the authorization login linkage needs to open a new tab popup for operation, otherwise the authorization login linkage will not be able to debug normally.`,\n ),\n );\n console.log(\n chalk.bold.blue(\n '\\n \\n============== start dev your game, it will take a few seconds ============ \\n \\n',\n ),\n );\n\n /**\n * 支持 .br 文件, 支持 gzip\n */\n\n app.use((req, res, next) => {\n if (req.url.endsWith('.br')) {\n res.setHeader('Content-Encoding', 'br');\n } else if (req.url.endsWith('.gz')) {\n res.setHeader('Content-Encoding', 'gzip');\n }\n next();\n });\n\n /**\n * 给所有的请求返回设置 CSP\n */\n app.use((req, res, next) => {\n /**\n * 计算 HTML 中的内联脚本生成 hash 插入 CSP 中\n */\n try {\n // 1. 读取 HTML 文件内容\n const htmlPath = path.join(process.cwd(), 'index.html');\n const html = fs.readFileSync(htmlPath, 'utf8');\n\n // 2. 用 cheerio 解析 HTML\n const $ = cheerio.load(html);\n\n // 3. 提取所有无 src 属性的内联 <script> 内容\n const scripts = [];\n $('script:not([src])').each((i, elem) => {\n const content = $(elem).html();\n if (content && content.trim()) {\n scripts.push(content);\n }\n });\n\n // 4. 计算每段脚本的 SHA-256 hash 并 base64 编码\n const hashes = scripts.map(script => {\n const hash = crypto\n .createHash('sha256')\n .update(script, 'utf8')\n .digest('base64');\n return `'sha256-${hash}'`;\n });\n\n // 开发者本地调试,信任的域名默认为 * 便于调试\n const devTrustedDomain = '*';\n\n res.setHeader(\n 'Content-Security-Policy',\n `default-src 'self';script-src 'self' data: blob: 'unsafe-eval' 'unsafe-inline' connect.tiktok-minis.com sf-connect.tiktokminis.us;img-src 'self' ${devTrustedDomain} data: blob: *; connect-src 'self' ${devTrustedDomain} data: blob: ; style-src 'self' ${devTrustedDomain} 'unsafe-inline' fonts.googleapis.com data: blob: *; font-src 'self' fonts.gstatic.com blob: data: *; media-src 'self' ${devTrustedDomain} data: blob: *; frame-src 'none'; base-uri 'self'; worker-src 'self' blob: data: ;`,\n );\n } catch (e) {\n // 如果 index.html 不存在或有异常,CSP 头就不设置\n console.warn(chalk.red('Failed to set CSP header:'), e.message);\n }\n next();\n });\n\n // 4. 静态资源服务\n app.use(express.static(path.join(process.cwd())));\n\n // 5. 启动服务并自动打开浏览器\n app.listen(devPort, () => {\n const gameUrl = `http://localhost:${devPort}`;\n const devUrl = `${MINIS_RUNTIME_URL}?minis_url=${gameUrl}&enable_log=1`;\n\n console.log(\n `you can access ${chalk.green.underline.bold(\n devUrl,\n )} to debug your game in browser...`,\n );\n try {\n //TODO\n // 自动打开浏览器,跨平台\n open(devUrl);\n } catch (e) {\n console.warn(\n chalk.red('Failed to open browser, you can access it manually'),\n e.message,\n );\n }\n });\n};\n","const chalk = require('chalk');\nconst fs = require('fs');\nconst path = require('path');\nconst { MINIS_MANIFEST_FILE_NAME } = require('../config');\nasync function buildMinisManifest() {\n try {\n const buildPath = path.join(process.cwd());\n const resourceList = [];\n const allFiles = collectAllFiles(buildPath);\n\n Object.keys(allFiles)\n .filter(file => !file.endsWith('.map'))\n .forEach(file => {\n const relativeFilePath = allFiles[file];\n const filePathArr = relativeFilePath.split('/').filter(Boolean); // Split filename\n const fileName = filePathArr.pop() || ''; // Get filename\n if (filePathArr.length === 0) {\n resourceList.push({ type: 'file', name: fileName });\n } else {\n const folder = findOrCreateFolder(filePathArr, resourceList);\n folder.children.push({ type: 'file', name: fileName });\n }\n });\n\n fs.writeFileSync(\n path.join(buildPath, MINIS_MANIFEST_FILE_NAME),\n JSON.stringify(\n { name: MINIS_MANIFEST_FILE_NAME, resource_list: resourceList },\n null,\n 2,\n ),\n );\n } catch (error) {\n console.error(chalk.red(`Error during debug process: ${error.message}`));\n if (error instanceof Error && error.stack) {\n console.error(chalk.red(`Stack trace: ${error.stack}`));\n }\n process.exit(1);\n }\n}\n\nfunction findOrCreateFolder(pathArray, currentFolder) {\n let folder = currentFolder.find(\n item => item.type === 'folder' && item.name === pathArray[0],\n );\n if (!folder) {\n folder = { type: 'folder', name: pathArray[0], children: [] };\n currentFolder.push(folder);\n }\n if (pathArray.length > 1) {\n return findOrCreateFolder(pathArray.slice(1), folder.children);\n }\n return folder;\n}\n\nfunction collectAllFiles(dir, baseDir = dir) {\n const files = {};\n fs.readdirSync(dir).forEach(file => {\n const filePath = path.join(dir, file);\n const fileStat = fs.statSync(filePath);\n if (fileStat.isDirectory()) {\n // Process subdirectories recursively\n const subFiles = collectAllFiles(filePath, baseDir);\n Object.assign(files, subFiles);\n } else if (path.extname(file) !== '' && file) {\n const relativePath =\n '/' + path.relative(baseDir, filePath).replace(/\\\\/g, '/');\n files[filePath] = relativePath;\n }\n });\n return files;\n}\n\nmodule.exports = {\n buildMinisManifest,\n};\n","const fs = require('fs');\nconst os = require('os');\nconst path = require('path');\nconst inquirer = require('inquirer');\nconst chalk = require('chalk');\nconst archiver = require('archiver');\nconst promptModule = inquirer.createPromptModule();\nconst { buildMinisManifest } = require('./manifest');\n\nmodule.exports = async function build() {\n try {\n /**\n * 用户输入打包后的游戏压缩包名称\n */\n const { zipName: zipNameInput } = await promptModule({\n type: 'input',\n name: 'zipName',\n default: 'game',\n message: 'Please input zip name',\n });\n\n const startTime = Date.now();\n console.log(\n chalk.bold.blue('start build your game, it will take a few minutes...'),\n );\n\n /**\n * 移除掉当前根目录下的文件包\n */\n\n const files = fs.readdirSync(process.cwd());\n files.forEach(file => {\n if (file.endsWith('.zip')) {\n fs.unlinkSync(path.join(process.cwd(), file));\n }\n });\n\n await buildMinisManifest();\n const archive = archiver('zip', {\n zlib: { level: 9 }, // Sets the compression level.\n });\n\n archive.on('error', function (err) {\n throw err;\n });\n\n /**\n * 把当前文件压缩成 game-${dateStr}.zip,并添加在桌面\n */\n const desktopPath = getDesktopPath();\n const zipPath = path.join(desktopPath, `${zipNameInput}.zip`);\n\n await archive.pipe(fs.createWriteStream(zipPath));\n\n await archive.directory(path.resolve(process.cwd()), false);\n\n await archive.finalize();\n console.log(\n chalk.yellow.bold(\n `build ${zipNameInput}.zip success, you can find it in desktop, use time ${\n Date.now() - startTime\n } ms`,\n ),\n );\n\n return new Promise((resolve, reject) => {\n archive.on('end', resolve);\n archive.on('error', reject);\n });\n } catch (error) {\n console.log(\n chalk.red(\n `auto build ${zipNameInput}.zip failed: ${error.message}, you should zip it manually`,\n ),\n );\n }\n};\n\nfunction getDesktopPath() {\n const homeDir = os.homedir();\n // 常见桌面文件夹名\n const desktopNames = ['Desktop', '桌面'];\n for (const name of desktopNames) {\n const possiblePath = path.join(homeDir, name);\n if (fs.existsSync(possiblePath)) {\n return possiblePath;\n }\n }\n // 如果都没有,默认用 Desktop\n return path.join(homeDir, 'Desktop');\n}\n","const { exec } = require('child_process');\nexport function openUrl(url) {\n const platform = process.platform;\n if (platform === 'win32') {\n exec(`start ${url}`);\n }\n else if (platform === 'darwin') {\n exec(`open ${url}`);\n }\n else if (platform === 'linux') {\n exec(`xdg-open ${url}`);\n }\n else {\n console.error('Unsupported OS');\n }\n}\n","import os from 'os';\nexport function getLocalIP() {\n const networkInterfaces = os.networkInterfaces();\n for (const interfaceName in networkInterfaces) {\n const interfaceInfo = networkInterfaces[interfaceName];\n if (!interfaceInfo)\n continue;\n for (const addressInfo of interfaceInfo) {\n if (addressInfo.family === 'IPv4' && !addressInfo.internal) {\n return addressInfo.address;\n }\n }\n }\n}\n","export const DEV_PORT = 9528;\n","import express from 'express';\nimport chalk from 'chalk';\nimport multer from 'multer';\nimport { getLocalIP } from '@libs';\nimport { DEV_PORT } from '../config';\nconst app = express();\nconst port = DEV_PORT; // 你可以自定义端口\nconst upload = multer({ dest: 'uploads/' }); // 上传到 uploads 目录\n/**\n * 支持 Post 请求\n * 1. /game/env 路由\n * 2. /game/upload 路由\n * 3. /game/debug 路由\n */\nexport async function createServer() {\n console.log('Start local dev server...');\n // 解析 JSON body\n app.use(express.json());\n // 解析 FormData body\n app.use(express.urlencoded({ extended: true }));\n // POST /game/env 路由\n app.post('/game/env', async (req, res) => {\n // 获取请求体\n const body = req.body;\n const { host, port } = body;\n // 响应内容(可以根据实际业务返回需要的数据)\n const devUrl = `http://${host}:${port}`;\n console.log('devUrl:', devUrl);\n // await openUrl(devUrl);\n console.log(chalk.bold.yellow(`Game debug is ready! Visit ${devUrl} in your browser.`));\n res.json({\n code: 0,\n msg: 'ok',\n data: {\n devUrl,\n },\n });\n });\n app.post('/game/upload', upload.single('file'), async (req, res) => {\n // 文件信息在 req.file\n console.log('Upload resource to client:', req.file);\n res.json({\n code: 0,\n msg: 'ok',\n filename: req.file.filename, // multer生成的临时文件名\n originalname: req.file.originalname, // 上传时的原始文件名\n size: req.file.size,\n path: req.file.path,\n });\n });\n // 启动服务\n app.listen(port, () => {\n console.log(`Dev server is running on port ${port}`);\n });\n return {\n port,\n host: getLocalIP(),\n };\n}\nexport function closeServer() {\n app.close();\n}\n","import inquirer from 'inquirer';\nimport fs from 'fs';\nimport os from 'os';\nimport path from 'path';\nimport chalk from 'chalk';\nconst CONFIG_DIR = path.join(os.homedir(), '.ttmg-cli');\nconst CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');\n/**\n * 读取本地 clientKeys 列表\n */\nfunction readClientKeys() {\n if (!fs.existsSync(CONFIG_FILE))\n return [];\n try {\n const data = JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf-8'));\n return Array.isArray(data.clientKeys) ? data.clientKeys : [];\n }\n catch (e) {\n return [];\n }\n}\n/**\n * 保存新的 Client Key 到本地\n */\nfunction saveClientKey(newKey) {\n let keys = [];\n if (fs.existsSync(CONFIG_FILE)) {\n try {\n const data = JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf-8'));\n keys = Array.isArray(data.clientKeys) ? data.clientKeys : [];\n }\n catch (e) {\n keys = [];\n }\n }\n if (!keys.includes(newKey)) {\n keys.push(newKey);\n // 确保目录存在\n if (!fs.existsSync(CONFIG_DIR)) {\n fs.mkdirSync(CONFIG_DIR, { recursive: true });\n }\n fs.writeFileSync(CONFIG_FILE, JSON.stringify({ clientKeys: keys }, null, 2), { encoding: 'utf-8' });\n }\n}\n/**\n * 获取 Client Key(选择或输入)\n */\nexport async function getClientKey() {\n /**\n * 读取 project.config.json 中的 appid/appId\n */\n const projectConfigPath = path.join(process.cwd(), 'project.config.json');\n let clientKey;\n try {\n const projectConfig = JSON.parse(fs.readFileSync(projectConfigPath, 'utf-8'));\n clientKey = projectConfig.appid || projectConfig.appId;\n }\n catch (e) {\n clientKey = '';\n }\n if (clientKey) {\n return clientKey;\n }\n else {\n console.log(chalk.red.bold('No appid found in project.config.json, you should provide it in project.config.json'));\n process.exit(1);\n }\n const keys = readClientKeys();\n if (keys.length > 0) {\n // 有历史 key,展示选择框\n const { selectedKey } = await inquirer.prompt([\n {\n type: 'list',\n name: 'selectedKey',\n message: 'Please select your game id(client_key):',\n choices: [...keys, new inquirer.Separator(), 'Add new game id'],\n },\n ]);\n if (selectedKey === 'Add new game id') {\n // 输入新 key\n const { newKey } = await inquirer.prompt([\n {\n type: 'input',\n name: 'newKey',\n message: 'Please input your new game id(client_key):',\n validate: (input) => (input ? true : 'Please input game id'),\n },\n ]);\n saveClientKey(newKey);\n clientKey = newKey;\n }\n else {\n clientKey = selectedKey;\n }\n }\n else {\n // 没有历史 key,让用户输入\n const { newKey } = await inquirer.prompt([\n {\n type: 'input',\n name: 'newKey',\n message: 'Please input your game id(client_key):',\n validate: (input) => (input ? true : 'Please input game id'),\n },\n ]);\n saveClientKey(newKey);\n clientKey = newKey;\n }\n return clientKey;\n}\n","import { debugPkgs } from 'ttmg-pack';\nimport { getClientKey } from './getClientKey';\nimport fs from 'fs';\nimport os from 'os';\nimport path from 'path';\nimport chalk from 'chalk';\nimport archiver from 'archiver';\nimport axios from 'axios';\nimport FormData from 'form-data';\nexport async function compileUpload() {\n /**\n * 输入你要调试的游戏 ID(client_key)\n */\n const clientKey = await getClientKey();\n /**\n * 读取当前游戏\n */\n const entryDir = process.cwd();\n /**\n * 输出路径,我需要把输出产物进行压缩\n */\n const outputDir = path.join(os.homedir(), '__TTMG__', clientKey);\n if (fs.existsSync(outputDir)) {\n console.log('Remove old output dir');\n fs.rmSync(outputDir, { recursive: true, force: true });\n console.log('Create new output dir');\n }\n const buildResult = await debugPkgs({\n entry: entryDir,\n output: outputDir,\n rules: {\n mainPackageSizeLimit: 200 * 1024 * 1024,\n projectSizeLimit: 200 * 1024 * 1024,\n },\n });\n if (!(buildResult === null || buildResult === void 0 ? void 0 : buildResult.isSuccess)) {\n console.log(chalk.redBright('Build game package failed, Please check the error message below:'));\n console.log(chalk.redBright(buildResult === null || buildResult === void 0 ? void 0 : buildResult.errorMsg));\n return;\n }\n else {\n console.log('Build game package success');\n }\n await upload(outputDir, path.join(os.homedir(), '__TTMG__', 'pack.zip'));\n return {\n clientKey,\n outputDir,\n };\n}\n/**\n * 压缩指定目录为 zip 文件\n * @param sourceDir 要压缩的目录\n * @param outPath 输出 zip 文件路径\n */\n/**\n * 压缩指定目录为 zip 文件\n * @param sourceDir 要压缩的目录\n * @param outPath 输出 zip 文件路径\n */\nfunction zipDirectory(sourceDir, outPath) {\n return new Promise((resolve, reject) => {\n const output = fs.createWriteStream(outPath); // 修正:传入输出路径\n const archive = archiver('zip', { zlib: { level: 9 } });\n output.on('close', () => {\n console.log('Compress directory done');\n resolve();\n });\n output.on('error', err => {\n reject(err);\n });\n archive.on('error', err => {\n reject(err);\n });\n archive.pipe(output);\n archive.directory(sourceDir, false); // 修正:第一个参数是源目录\n archive.finalize();\n });\n}\n/**\n * 上传 zip 文件到指定接口\n * @param zipFilePath zip 文件路径\n * @param uploadUrl 上传接口\n */\nexport async function upload(sourceUrl, zipPath) {\n if (!fs.existsSync(sourceUrl)) {\n throw new Error(`目录不存在: ${sourceUrl}`);\n }\n console.log('Start compress directory');\n await zipDirectory(sourceUrl, zipPath);\n const form = new FormData();\n form.append('file', fs.createReadStream(zipPath), 'upload.zip');\n try {\n console.log('Start upload resource to client');\n const response = await axios.post('http://localhost:9528/game/upload', form, {\n headers: form.getHeaders(),\n });\n console.log('Upload resource to client success');\n }\n catch (err) {\n console.error('Upload resource to client failed:', err.message);\n }\n}\n","import chalk from 'chalk';\nimport axios from 'axios';\nimport { centerQRCode } from '@libs';\nimport qrcode from 'qrcode-terminal';\n// (https://www.tiktok.com/ttmg/dev/{clientKey})\nfunction getSchema({ clientKey, host, port, }) {\n const schema = `https://www.tiktok.com/ttmg/dev/${clientKey}?host=${host}&port=${port}`;\n return schema;\n}\nexport async function showSchema(context) {\n const { clientKey, outputDir, host, port } = context;\n console.log(chalk.yellow('Tips:'));\n console.log(` 1. ${chalk.blue('Scan the QR code to start the client devServer.')}`);\n console.log(` 2. ${chalk.blue('Will auto upload compiled resource to client.')} ${chalk.bold(outputDir)}`);\n console.log(` 3. ${chalk.blue('Debug your game in the browser.')}\\n`);\n const schema = getSchema({\n clientKey,\n host,\n port,\n });\n qrcode.generate(schema, {\n small: true,\n }, qr => {\n console.log(centerQRCode(qr));\n });\n console.log('Schema:', schema);\n setTimeout(() => {\n axios\n .post(`http://${host}:${port}/game/env`, {\n host: 'localhost',\n port: '4001',\n })\n .then(res => {\n console.log('Client debug config:', res.data);\n })\n .catch(err => {\n console.log('Client debug config error:', err);\n });\n }, 3000);\n}\n","export function centerQRCode(qrString) {\n const terminalWidth = process.stdout.columns || 80; // 获取终端宽度,默认80\n const lines = qrString.split('\\n');\n const qrWidth = lines.reduce((max, line) => Math.max(max, line.length), 0);\n const padding = Math.floor((terminalWidth - qrWidth) / 3);\n const padStr = ' '.repeat(padding > 0 ? padding : 0);\n return lines.map(line => padStr + line).join('\\n');\n}\n","import { compileUpload, watchChange, showSchema, createServer } from './utils';\nasync function dev() {\n /**\n * 1. 创建本地调试服务\n */\n const { host, port } = await createServer();\n /**\n * 2. 游戏资源编译上传\n */\n const { clientKey, outputDir } = await compileUpload();\n /**\n * 3. 显示调试二维码信息\n */\n await showSchema({\n clientKey,\n outputDir,\n host,\n port,\n });\n /**\n * 4. 监听游戏资源变化\n */\n await watchChange();\n}\nexport default dev;\n","import fs from 'fs';\nimport chalk from 'chalk';\nimport { compileUpload } from './compileUpload';\nexport async function watchChange() {\n let debounceTimer = null;\n fs.watch(process.cwd(), (eventType, filename) => {\n console.log(chalk.yellow('game resource change, restart to upload'));\n // 清除之前的定时器\n if (debounceTimer)\n clearTimeout(debounceTimer);\n // 重新设置定时器\n debounceTimer = setTimeout(async () => {\n await compileUpload();\n debounceTimer = null;\n }, 500); // 500ms内只执行一次\n });\n}\n","#!/usr/bin/env node\nimport { Command } from 'commander';\nimport * as H5 from './h5';\nimport * as Native from './native';\nconst program = new Command();\nprogram\n .name('ttmg')\n .description('TikTok Mini Game Command Line Tool')\n .version('0.0.1');\nprogram\n .command('init')\n .option('--h5', 'H5 Mini Game')\n .description('Initialize project')\n .action(options => {\n if (options.h5) {\n H5.init();\n }\n else {\n console.log('Native Mini Game initialize');\n }\n});\n/**\n * ttmg dev 命令\n */\nprogram\n .command('dev')\n .description('Open browser dev environment')\n .option('--h5', 'H5 Mini Game')\n .action(options => {\n if (options.h5) {\n H5.dev();\n }\n else {\n Native.dev();\n }\n});\n/**\n * ttmg build 命令\n */\nprogram\n .command('build')\n .option('--h5', 'H5 Mini Game')\n .description('Bundle project')\n .action(async (options) => {\n if (options.h5) {\n H5.bundle();\n }\n else {\n console.log('Native Mini Game bundle');\n }\n});\nprogram.parse(process.argv);\n"],"names":["config","CONFIG_FILE_NAME","SDK_URL","VCONSOLE_URL","VCONSOLE_INIT","MINIS_MANIFEST_FILE_NAME","MINIS_RUNTIME_URL","fs","require$$0","jsdom","require$$1","prettier","require$$2","chalk","require$$3","JSDOM","require$$4","CONFIG_PATH","process","cwd","INDEX_HTML_PATH","inject","async","clientKey","writeFileSync","JSON","stringify","existsSync","console","error","indexHtml","readFileSync","dom","document","window","head","querySelector","createElement","documentElement","insertBefore","body","scriptList","Array","from","querySelectorAll","hasSDK","some","script","src","includes","hasVConsole","lastInitScript","headScripts","find","innerHTML","isTTMinisInitScript","log","sdkScripts","filter","length","sdkScript","firstChild","initScript","nextSibling","startsWith","isSandbox","insertAfterNode","vconsoleSourceScript","vconsoleInitScript","formattedHtml","format","serialize","parser","green","bold","inquirer","init","createPromptModule","promptModule","type","name","message","default","then","devPort","answers","_comment","orientation","dev","port","express","path","cheerio","app","crypto","require$$5","require$$6","configPath","join","red","gameConfig","parse","yellow","blue","use","req","res","next","url","endsWith","setHeader","htmlPath","html","$","load","scripts","each","i","elem","content","trim","push","map","createHash","update","digest","devTrustedDomain","e","warn","static","listen","devUrl","underline","open","findOrCreateFolder","pathArray","currentFolder","folder","item","children","slice","collectAllFiles","dir","baseDir","files","readdirSync","forEach","file","filePath","statSync","isDirectory","subFiles","Object","assign","extname","relativePath","relative","replace","manifest","buildMinisManifest","buildPath","resourceList","allFiles","keys","filePathArr","split","Boolean","fileName","pop","resource_list","Error","stack","exit","os","archiver","bundle","zipName","zipNameInput","startTime","Date","now","unlinkSync","archive","zlib","level","on","err","desktopPath","homeDir","homedir","desktopNames","possiblePath","getDesktopPath","zipPath","pipe","createWriteStream","directory","resolve","finalize","Promise","reject","exec","require","getLocalIP","networkInterfaces","interfaceName","interfaceInfo","addressInfo","family","internal","address","upload","multer","dest","createServer","json","urlencoded","extended","post","host","code","msg","data","single","filename","originalname","size","CONFIG_DIR","CONFIG_FILE","saveClientKey","newKey","isArray","clientKeys","mkdirSync","recursive","encoding","getClientKey","projectConfigPath","projectConfig","appid","appId","readClientKeys","selectedKey","prompt","choices","Separator","validate","input","compileUpload","entryDir","outputDir","rmSync","force","buildResult","debugPkgs","entry","output","rules","mainPackageSizeLimit","projectSizeLimit","isSuccess","sourceUrl","sourceDir","outPath","form","FormData","append","createReadStream","axios","headers","getHeaders","redBright","errorMsg","showSchema","context","schema","getSchema","qrcode","generate","small","qr","qrString","terminalWidth","stdout","columns","lines","qrWidth","reduce","max","line","Math","padding","floor","padStr","repeat","centerQRCode","setTimeout","catch","debounceTimer","watch","eventType","clearTimeout","watchChange","program","Command","description","version","command","option","action","options","h5","H5.init","H5.dev","Native.dev","H5.bundle","argv"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ttmg/cli",
3
- "version": "0.0.12-beta.7",
3
+ "version": "0.0.12-beta.8",
4
4
  "description": "TikTok Mini Game Command Line Tool",
5
5
  "license": "ISC",
6
6
  "bin": {
@@ -13,7 +13,7 @@
13
13
  "prepublish": "npm run build",
14
14
  "build": "rollup -c",
15
15
  "watch": "rollup -c -w",
16
- "analyze": "node ./src/h5/analyze/index.js ./src/h5/analyze/demo"
16
+ "perf": "rollup -c --perf"
17
17
  },
18
18
  "keywords": [
19
19
  "TTMG",
@@ -24,18 +24,21 @@
24
24
  "dependencies": {
25
25
  "acorn": "^8.15.0",
26
26
  "archiver": "^7.0.1",
27
+ "axios": "^1.11.0",
27
28
  "boxen": "^6.2.1",
28
29
  "chalk": "^4.1.2",
29
30
  "cheerio": "^1.1.1",
30
31
  "commander": "^10.0.0",
31
32
  "estraverse": "^5.3.0",
32
33
  "express": "^5.1.0",
34
+ "form-data": "^4.0.4",
33
35
  "inquirer": "^12.7.0",
34
36
  "jsdom": "^26.1.0",
35
- "open": "^10.2.0",
37
+ "multer": "^2.0.2",
36
38
  "prettier": "^3.6.2",
37
39
  "qrcode-terminal": "^0.12.0",
38
- "ttmg-pack": "^0.0.13"
40
+ "ttmg-pack": "^0.0.13",
41
+ "ws": "^8.18.3"
39
42
  },
40
43
  "devDependencies": {
41
44
  "@babel/core": "^7.28.3",
@@ -51,6 +54,7 @@
51
54
  "@types/node": "^24.2.0",
52
55
  "eslint": "^9.31.0",
53
56
  "rollup": "^4.46.4",
57
+ "rollup-plugin-visualizer": "^6.0.3",
54
58
  "typescript": "^5.9.2"
55
59
  },
56
60
  "engines": {