@playcraft/devkit 1.0.13 → 1.0.14
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/core/batch-build.js +1 -1
- package/core/cos-uploader.js +7 -18
- package/package.json +1 -1
package/core/batch-build.js
CHANGED
|
@@ -20,7 +20,7 @@ const currentThemeLinks=previewLinks.filter(link=>link.theme===currentTheme);cur
|
|
|
20
20
|
updatedPreviewData[fileName]={url:link.url,update_time:currentTime}});// 将更新后的数据写入临时文件
|
|
21
21
|
const tempDir=path.join(os.tmpdir(),"playable-preview");if(!fs.existsSync(tempDir)){fs.mkdirSync(tempDir,{recursive:true})}const tempPreviewPath=path.join(tempDir,"preview.json");fs.writeFileSync(tempPreviewPath,JSON.stringify(updatedPreviewData,null,2),"utf8");// 上传更新后的 preview.json 文件
|
|
22
22
|
await uploadFileToCOS(null,tempPreviewPath,previewJsonKey,credentials);// 刷新 CDN 缓存
|
|
23
|
-
const cdnDomain="static.aix.intlgame.com";const previewJsonUrl=`https://${cdnDomain}/${previewJsonKey}`;try{await purgeCDNCache(null,[previewJsonUrl],credentials);log(`✓ CDN 缓存已刷新: ${previewJsonUrl}`,"success")}catch(error){log(`⚠️ CDN
|
|
23
|
+
const cdnDomain="static.aix.intlgame.com";const previewJsonUrl=`https://${cdnDomain}/${previewJsonKey}`;try{await purgeCDNCache(null,[previewJsonUrl],credentials);log(`✓ CDN 缓存已刷新: ${previewJsonUrl}`,"success")}catch(error){log(`⚠️ CDN 缓存刷新失败 (preview.json): ${error.message}`,"warn")}// 清理临时文件
|
|
24
24
|
fs.unlinkSync(tempPreviewPath);log(`✓ preview.json 文件已更新并上传`,"success")}// ==================== 默认配置 ====================
|
|
25
25
|
/**
|
|
26
26
|
* 计算默认并发数
|
package/core/cos-uploader.js
CHANGED
|
@@ -13,26 +13,15 @@
|
|
|
13
13
|
if(cosConfig&&cosConfig.SecretId&&cosConfig.SecretKey){return new COS({SecretId:cosConfig.SecretId,SecretKey:cosConfig.SecretKey})}// 使用已传入的凭证,或重新获取
|
|
14
14
|
if(!credentials){credentials=await fetchTemporaryCredentials()}return new COS({getAuthorization:(options,callback)=>{callback({TmpSecretId:credentials.credentials.tmpSecretId,TmpSecretKey:credentials.credentials.tmpSecretKey,SecurityToken:credentials.credentials.sessionToken,StartTime:credentials.startTime,ExpiredTime:credentials.expiredTime})}})}/**
|
|
15
15
|
* 刷新 CDN 缓存
|
|
16
|
+
* 通过服务端 API 代理执行(STS 临时凭证无法携带 CDN 权限,需由服务端使用主账号凭证刷新)
|
|
16
17
|
*
|
|
17
|
-
* @param {Object} cosConfig - COS
|
|
18
|
+
* @param {Object} cosConfig - COS 配置(如有 SecretId/SecretKey 则本地直接刷新)
|
|
18
19
|
* @param {Array<string>} urls - 需要刷新的 URL 列表
|
|
19
|
-
* @param {Object} credentials -
|
|
20
|
+
* @param {Object} credentials - 未使用,保留参数兼容性
|
|
20
21
|
* @returns {Promise<void>}
|
|
21
|
-
*/async function purgeCDNCache(cosConfig,urls,credentials=null){if(!urls||urls.length===0){return}
|
|
22
|
-
const
|
|
23
|
-
const
|
|
24
|
-
let secretId,secretKey;if(cosConfig&&cosConfig.SecretId&&cosConfig.SecretKey){// 使用配置中的凭证
|
|
25
|
-
secretId=cosConfig.SecretId;secretKey=cosConfig.SecretKey}else{// 使用临时凭证(优先使用传入的凭证,否则重新获取)
|
|
26
|
-
if(!credentials){credentials=await fetchTemporaryCredentials()}secretId=credentials.credentials.tmpSecretId;secretKey=credentials.credentials.tmpSecretKey}const clientConfig={credential:{secretId,secretKey,// 临时凭证必须携带 token,否则腾讯云认证会报 The SecretId is not found
|
|
27
|
-
...(credentials?{token:credentials.credentials.sessionToken}:{})},region:"",// CDN 是全球服务,不需要指定 region
|
|
28
|
-
profile:{httpProfile:{endpoint:"cdn.tencentcloudapi.com"}}};const client=new CdnClient(clientConfig);// CDN 刷新区域(从配置中读取,默认为 overseas)
|
|
29
|
-
// mainland: 中国境内
|
|
30
|
-
// overseas: 中国境外
|
|
31
|
-
// global: 全球
|
|
32
|
-
const area=(cosConfig===null||cosConfig===void 0?void 0:cosConfig.CdnArea)||"overseas";// 每次最多刷新 1000 个 URL(腾讯云限制)
|
|
33
|
-
const batchSize=1000;for(let i=0;i<urls.length;i+=batchSize){const batch=urls.slice(i,i+batchSize);const params={Urls:batch,Area:area};await client.PurgeUrlsCache(params);console.log(`✓ 已刷新 ${batch.length} 个 URL 的 CDN 缓存 (区域: ${area})`)}}catch(error){// 如果没有安装 CDN SDK,给出提示
|
|
34
|
-
if(error.code==="MODULE_NOT_FOUND"){console.warn("\u26A0\uFE0F \u672A\u5B89\u88C5 tencentcloud-sdk-nodejs-cdn\uFF0C\u8DF3\u8FC7 CDN \u5237\u65B0");console.warn(" \u5B89\u88C5\u547D\u4EE4: npm install tencentcloud-sdk-nodejs-cdn --save-dev")}else{console.error(`CDN 刷新失败: ${error.message}`);// 不抛出错误,避免影响上传流程
|
|
35
|
-
}}}/**
|
|
22
|
+
*/async function purgeCDNCache(cosConfig,urls,credentials=null){if(!urls||urls.length===0){return}const area=(cosConfig===null||cosConfig===void 0?void 0:cosConfig.CdnArea)||"overseas";// 如果配置中有 SecretId/SecretKey,本地直接刷新
|
|
23
|
+
if(cosConfig&&cosConfig.SecretId&&cosConfig.SecretKey){try{const tencentcloud=require("tencentcloud-sdk-nodejs-cdn");const client=new tencentcloud.cdn.v20180606.Client({credential:{secretId:cosConfig.SecretId,secretKey:cosConfig.SecretKey},region:"",profile:{httpProfile:{endpoint:"cdn.tencentcloudapi.com"}}});const batchSize=1000;for(let i=0;i<urls.length;i+=batchSize){const batch=urls.slice(i,i+batchSize);await client.PurgeUrlsCache({Urls:batch,Area:area});console.log(`✓ CDN 缓存已刷新 ${batch.length} 个 URL (区域: ${area})`)}}catch(error){if(error.code==="MODULE_NOT_FOUND"){console.warn("\u26A0\uFE0F \u672A\u5B89\u88C5 tencentcloud-sdk-nodejs-cdn\uFF0C\u8DF3\u8FC7 CDN \u5237\u65B0")}else{throw error}}return}// 否则通过服务端 API 代理刷新
|
|
24
|
+
const https=require("https");const purgeUrl="https://wd-act.woa.com/aix/playable/api/cdn/purge";const postData=JSON.stringify({urls,area});return new Promise((resolve,reject)=>{const req=https.request(purgeUrl,{method:"POST",headers:{"Content-Type":"application/json","Content-Length":Buffer.byteLength(postData)}},response=>{let data="";response.on("data",chunk=>data+=chunk);response.on("end",()=>{try{const result=JSON.parse(data);if(result.code==="SUCCESS"){console.log(`✓ CDN 缓存已刷新 ${urls.length} 个 URL (区域: ${area})`);resolve()}else{reject(new Error(result.message||"CDN purge failed"))}}catch(error){reject(new Error(`Failed to parse CDN purge response: ${error.message}`))}})});req.on("error",reject);req.setTimeout(30000,function(){this.destroy();reject(new Error("CDN purge request timeout"))});req.write(postData);req.end()})}/**
|
|
36
25
|
* 上传单个文件到 COS
|
|
37
26
|
*
|
|
38
27
|
* @param {Object} cosConfig - COS 配置
|
|
@@ -57,4 +46,4 @@ const pathParts=cosKey.split("/");const encodedPath=pathParts.map(part=>encodeUR
|
|
|
57
46
|
if(!credentials&&(!cosConfig||!cosConfig.Bucket||!cosConfig.Region)){try{credentials=await fetchTemporaryCredentials();console.log("\u2713 \u83B7\u53D6\u4E34\u65F6\u51ED\u8BC1\u6210\u529F")}catch(error){throw new Error(`获取临时凭证失败: ${error.message}`)}}const files=fs.readdirSync(localDir);const results=[];const uploadedUrls=[];for(const file of files){const filePath=path.join(localDir,file);const stat=fs.statSync(filePath);if(stat.isFile()){// 去掉文件名中的 -preview 或 _preview 后缀
|
|
58
47
|
let cleanFileName=file;cleanFileName=cleanFileName.replace(/-preview\./i,".");cleanFileName=cleanFileName.replace(/_preview\./i,".");const cosKey=cosPrefix?`${cosPrefix}/${cleanFileName}`:cleanFileName;// 传入凭证,避免重复获取
|
|
59
48
|
const url=await uploadFileToCOS(cosConfig,filePath,cosKey,credentials);results.push({file:cleanFileName,url});uploadedUrls.push(url)}}// 上传完成后刷新 CDN 缓存,传入凭证
|
|
60
|
-
if(uploadedUrls.length>0){await purgeCDNCache(cosConfig,uploadedUrls,credentials)}return results}module.exports={fetchTemporaryCredentials,createCOSClient,uploadFileToCOS,uploadDirectoryToCOS,purgeCDNCache};
|
|
49
|
+
if(uploadedUrls.length>0){try{await purgeCDNCache(cosConfig,uploadedUrls,credentials);console.log(`✓ CDN 缓存刷新成功 (${uploadedUrls.length} 个文件)`)}catch(error){console.warn(`⚠️ CDN 刷新失败: ${error.message}`)}}return results}module.exports={fetchTemporaryCredentials,createCOSClient,uploadFileToCOS,uploadDirectoryToCOS,purgeCDNCache};
|