Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 18 additions & 24 deletions src/bundle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@
import { checkLockFiles } from './utils/check-lockfile';
import { addGitIgnore } from './utils/add-gitignore';

let bsdiff;

Check failure on line 19 in src/bundle.ts

View workflow job for this annotation

GitHub Actions / lint (20.x)

Variable 'bsdiff' implicitly has type 'any' in some locations where its type cannot be determined.
let hdiff;

Check failure on line 20 in src/bundle.ts

View workflow job for this annotation

GitHub Actions / lint (20.x)

Variable 'hdiff' implicitly has type 'any' in some locations where its type cannot be determined.
let diff;

Check failure on line 21 in src/bundle.ts

View workflow job for this annotation

GitHub Actions / lint (20.x)

Variable 'diff' implicitly has type 'any' in some locations where its type cannot be determined.
try {
bsdiff = require('node-bsdiff').diff;
} catch (e) {}
Expand Down Expand Up @@ -214,17 +214,13 @@

reactNativeBundleProcess.on('close', async (exitCode) => {
if (exitCode) {
reject(
new Error(
`"react-native bundle" command exited with code ${exitCode}.`,
),
);
reject(new Error(t('bundleCommandError', { code: exitCode })));
} else {
let hermesEnabled: boolean | undefined = false;

if (disableHermes) {
hermesEnabled = false;
console.log('Hermes disabled');
console.log(t('hermesDisabled'));
} else if (platform === 'android') {
const gradlePropeties = await new Promise<{
hermesEnabled?: boolean;
Expand Down Expand Up @@ -283,8 +279,8 @@
await fs.ensureDir(outputFolder);
await fs.copy(harmonyRawPath, outputFolder);
} catch (error: any) {
console.error('copyHarmonyBundle 错误:', error);
throw new Error(`复制文件失败: ${error.message}`);
console.error(t('copyHarmonyBundleError', { error }));
throw new Error(t('copyFileFailed', { error: error.message }));
}
}

Expand Down Expand Up @@ -355,7 +351,7 @@
);
args.push('-output-source-map');
}
console.log(`Running hermesc: ${hermesCommand} ${args.join(' ')}`);
console.log(t('runningHermesc', { command: hermesCommand, args: args.join(' ') }));
spawnSync(hermesCommand, args, {
stdio: 'ignore',
});
Expand All @@ -365,7 +361,7 @@
if (!fs.existsSync(composerPath)) {
return;
}
console.log('Composing source map');
console.log(t('composingSourceMap'));
spawnSync(
'node',
[
Expand Down Expand Up @@ -400,16 +396,14 @@
},
);
} catch (error) {
console.error(
'无法找到 Sentry copy-debugid.js 脚本文件,请确保已正确安装 @sentry/react-native',
);
console.error(t('sentryCliNotFound'));
return;
}

if (!fs.existsSync(copyDebugidPath)) {
return;
}
console.log('Copying debugid');
console.log(t('copyingDebugId'));
spawnSync(
'node',
[
Expand Down Expand Up @@ -453,9 +447,9 @@
stdio: 'inherit',
},
);
console.log(`Sentry release created for version: ${version}`);
console.log(t('sentryReleaseCreated', { version }));

console.log('Uploading sourcemap');
console.log(t('uploadingSourcemap'));
spawnSync(
'node',
[
Expand All @@ -479,7 +473,7 @@
const ignorePackingFileNames = ['.', '..', 'index.bundlejs.map'];
const ignorePackingExtensions = ['DS_Store','txt.map'];
async function pack(dir: string, output: string) {
console.log('Packing');
console.log(t('packing'));
fs.ensureDirSync(path.dirname(output));
await new Promise<void>((resolve, reject) => {
const zipfile = new ZipFile();
Expand Down Expand Up @@ -516,7 +510,7 @@
});
zipfile.end();
});
console.log(t('ppkPackageGenerated', { output }));
console.log(t('fileGenerated', { file: output }));
}

export function readEntire(entry: string, zipFile: ZipFile) {
Expand All @@ -524,7 +518,7 @@
return new Promise((resolve, reject) => {
zipFile.openReadStream(entry, (err: any, stream: any) => {
stream.pipe({
write(chunk: Buffer) {

Check failure on line 521 in src/bundle.ts

View workflow job for this annotation

GitHub Actions / lint (20.x)

Property 'openReadStream' does not exist on type 'ZipFile'.
buffers.push(chunk);
},
end() {
Expand Down Expand Up @@ -552,13 +546,13 @@

let originSource;

await enumZipEntries(origin, (entry, zipFile) => {

Check failure on line 549 in src/bundle.ts

View workflow job for this annotation

GitHub Actions / lint (20.x)

Variable 'originSource' implicitly has type 'any' in some locations where its type cannot be determined.
originEntries[entry.fileName] = entry;
if (!/\/$/.test(entry.fileName)) {
// isFile

Check failure on line 552 in src/bundle.ts

View workflow job for this annotation

GitHub Actions / lint (20.x)

Element implicitly has an 'any' type because expression of type 'any' can't be used to index type '{}'.
originMap[entry.crc32] = entry.fileName;

if (

Check failure on line 555 in src/bundle.ts

View workflow job for this annotation

GitHub Actions / lint (20.x)

Element implicitly has an 'any' type because expression of type 'any' can't be used to index type '{}'.
entry.fileName === 'index.bundlejs' ||
entry.fileName === 'bundle.harmony.js'
) {
Expand All @@ -585,7 +579,7 @@
zipfile.outputStream.pipe(fs.createWriteStream(output)).on('close', () => {
resolve();
});
});

Check failure on line 582 in src/bundle.ts

View workflow job for this annotation

GitHub Actions / lint (20.x)

Expected 1 arguments, but got 0. Did you forget to include 'void' in your type argument to 'Promise'?

const addedEntry = {};

Expand Down Expand Up @@ -671,7 +665,7 @@

for (const k in originEntries) {
if (!newEntries[k]) {
console.log(`Delete ${k}`);
console.log(t('deleteFile', { file: k }));
deletes[k] = 1;
}
}
Expand Down Expand Up @@ -844,7 +838,7 @@
await result;
}
} catch (error) {
console.error('处理文件时出错:', error);
console.error(t('processingError', { error }));
}

zipfile.readEntry();
Expand All @@ -860,7 +854,7 @@
const [origin, next] = args;

if (!origin || !next) {
console.error(`Usage: pushy ${diffFn} <origin> <next>`);
console.error(t('usageDiff', { command: diffFn }));
process.exit(1);
}

Expand Down Expand Up @@ -927,7 +921,7 @@
const realOutput = output.replace(/\$\{time\}/g, `${Date.now()}`);

if (!platform) {
throw new Error('Platform must be specified.');
throw new Error(t('platformRequired'));
}

console.log(`Bundling with react-native: ${depVersions['react-native']}`);
Expand Down Expand Up @@ -972,14 +966,14 @@
async diff({ args, options }) {
const { origin, next, realOutput } = diffArgsCheck(args, options, 'diff');

await diffFromPPK(origin, next, realOutput, 'index.bundlejs');
await diffFromPPK(origin, next, realOutput);
console.log(`${realOutput} generated.`);
},

async hdiff({ args, options }) {
const { origin, next, realOutput } = diffArgsCheck(args, options, 'hdiff');

await diffFromPPK(origin, next, realOutput, 'index.bundlejs');
await diffFromPPK(origin, next, realOutput);
console.log(`${realOutput} generated.`);
},

Expand Down
48 changes: 48 additions & 0 deletions src/locales/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,52 @@ This can reduce the risk of inconsistent dependencies and supply chain attacks.
operationSuccess: 'Operation successful',
failedToParseUpdateJson: 'Failed to parse file `update.json`. Try to remove it manually.',
ppkPackageGenerated: 'ppk package generated and saved to: {{- output}}',
Message: 'Welcome to Cresc hot update service, {{name}}.',
loggedOut: 'Logged out',
usageUnderDevelopment: 'Usage is under development now.',
hermesDisabled: 'Hermes disabled',
hermesEnabled: 'Hermes enabled, now compiling to hermes bytecode:\n',
runningHermesc: 'Running hermesc: {{command}} {{args}}',
composingSourceMap: 'Composing source map',
copyingDebugId: 'Copying debugid',
sentryCliNotFound: 'Cannot find Sentry CLI tool, please make sure @sentry/cli is properly installed',
sentryReleaseCreated: 'Sentry release created for version: {{version}}',
uploadingSourcemap: 'Uploading sourcemap',
packing: 'Packing',
deletingFile: 'Delete {{file}}',
bundlingWithRN: 'Bundling with react-native: {{version}}',
fileGenerated: '{{file}} generated.',
processingError: 'Error processing file: {{error}}',
usageDiff: 'Usage: cresc {{command}} <origin> <next>',
pluginDetected: 'detected {{name}} plugin',
pluginDetectionError: 'error while detecting {{name}} plugin: {{error}}',
addedToGitignore: 'Added {{line}} to .gitignore',
processingStringPool: 'Processing the string pool ...',
processingPackage: 'Processing the package {{count}} ...',
typeStrings: 'Type strings:',
keyStrings: 'Key strings:',
failedToParseIcon: '[Warning] failed to parse icon: {{error}}',
errorInHarmonyApp: 'Error in getEntryFromHarmonyApp: {{error}}',
totalPackages: 'Total {{count}} packages',
usageUploadIpa: 'Usage: cresc uploadIpa <ipa file>',
usageUploadApk: 'Usage: cresc uploadApk <apk file>',
usageUploadApp: 'Usage: cresc uploadApp <app file>',
usageParseApp: 'Usage: cresc parseApp <app file>',
usageParseIpa: 'Usage: cresc parseIpa <ipa file>',
usageParseApk: 'Usage: cresc parseApk <apk file>',
offset: 'Offset {{offset}}',
packageUploadSuccess: 'Successfully uploaded new hot update package (id: {{id}})',
rolloutRangeError: 'rollout must be an integer between 1-100',
nativeVersionNotFound: 'No native version found >= {{version}}',
nativeVersionNotFoundLess: 'No native version found <= {{version}}',
nativeVersionNotFoundMatch: 'No matching native version found: {{version}}',
packageIdRequired: 'Please provide packageId or packageVersion parameter',
operationComplete: 'Operation complete, bound to {{count}} native versions',
platformRequired: 'Platform must be specified.',
bundleCommandError: '"react-native bundle" command exited with code {{code}}.',
copyHarmonyBundleError: 'Error copying Harmony bundle: {{error}}',
copyFileFailed: 'Failed to copy file: {{error}}',
deleteFile: 'Delete {{file}}',
rolloutConfigSet: 'Set {{rollout}}% rollout for version {{version}} on native version(s) {{versions}}',
versionBind: 'Bound version {{version}} to native version {{nativeVersion}} (id: {{id}})',
};
48 changes: 48 additions & 0 deletions src/locales/zh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,52 @@ export default {
operationSuccess: '操作成功',
failedToParseUpdateJson: '无法解析文件 `update.json`。请手动删除它。',
ppkPackageGenerated: 'ppk 热更包已生成并保存到: {{- output}}',
welcomeMessage: '欢迎使用 pushy 热更新服务,{{name}}。',
loggedOut: '已退出登录',
usageUnderDevelopment: '使用说明正在开发中。',
hermesDisabled: 'Hermes 已禁用',
hermesEnabled: 'Hermes 已启用,正在编译为 hermes 字节码:\n',
runningHermesc: '运行 hermesc:{{command}} {{args}}',
composingSourceMap: '正在生成 source map',
copyingDebugId: '正在复制 debugid',
sentryCliNotFound: '无法找到 Sentry CLI 工具,请确保已正确安装 @sentry/cli',
sentryReleaseCreated: '已为版本 {{version}} 创建 Sentry release',
uploadingSourcemap: '正在上传 sourcemap',
packing: '正在打包',
deletingFile: '删除 {{file}}',
bundlingWithRN: '正在使用 react-native {{version}} 打包',
fileGenerated: '已生成 {{file}}。',
processingError: '处理文件时出错:{{error}}',
usageDiff: '用法:pushy {{command}} <origin> <next>',
pluginDetected: '检测到 {{name}} 插件',
pluginDetectionError: '检测 {{name}} 插件时出错:{{error}}',
addedToGitignore: '已将 {{line}} 添加到 .gitignore',
processingStringPool: '正在处理字符串池...',
processingPackage: '正在处理包 {{count}}...',
typeStrings: '类型字符串:',
keyStrings: '键字符串:',
failedToParseIcon: '[警告] 解析图标失败:{{error}}',
errorInHarmonyApp: '获取 Harmony 应用入口时出错:{{error}}',
totalPackages: '共 {{count}} 个包',
usageUploadIpa: '使用方法: pushy uploadIpa ipa后缀文件',
usageUploadApk: '使用方法: pushy uploadApk apk后缀文件',
usageUploadApp: '使用方法: pushy uploadApp app后缀文件',
usageParseApp: '使用方法: pushy parseApp app后缀文件',
usageParseIpa: '使用方法: pushy parseIpa ipa后缀文件',
usageParseApk: '使用方法: pushy parseApk apk后缀文件',
offset: '偏移量 {{offset}}',
packageUploadSuccess: '已成功上传新热更包(id: {{id}})',
rolloutRangeError: 'rollout 必须是 1-100 的整数',
nativeVersionNotFound: '未查询到 >= {{version}} 的原生版本',
nativeVersionNotFoundLess: '未查询到 <= {{version}} 的原生版本',
nativeVersionNotFoundMatch: '未查询到匹配原生版本:{{version}}',
packageIdRequired: '请提供 packageId 或 packageVersion 参数',
operationComplete: '操作完成,共已绑定 {{count}} 个原生版本',
platformRequired: '必须指定平台。',
bundleCommandError: '"react-native bundle" 命令退出,代码为 {{code}}。',
copyHarmonyBundleError: '复制 Harmony bundle 错误:{{error}}',
copyFileFailed: '复制文件失败:{{error}}',
deleteFile: '删除 {{file}}',
rolloutConfigSet: '已在原生版本 {{versions}} 上设置灰度发布 {{rollout}}% 热更版本 {{version}}',
versionBind: '已将热更版本 {{version}} 绑定到原生版本 {{nativeVersion}} (id: {{id}})',
};
15 changes: 8 additions & 7 deletions src/package.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { get, post, uploadFile } from './api';
import { question, saveToLocal } from './utils';
import { t } from './utils/i18n';

import { checkPlatform, getSelectedApp } from './app';

Expand Down Expand Up @@ -34,7 +35,7 @@ export async function listPackage(appId: string) {
}

console.log(Table(header, rows).render());
console.log(`\n共 ${data.length} 个包`);
console.log(t('totalPackages', { count: data.length }));
return data;
}

Expand All @@ -54,7 +55,7 @@ export const commands = {
uploadIpa: async ({ args }: { args: string[] }) => {
const fn = args[0];
if (!fn || !fn.endsWith('.ipa')) {
throw new Error('使用方法: pushy uploadIpa ipa后缀文件');
throw new Error(t('usageUploadIpa'));
}
const {
versionName,
Expand Down Expand Up @@ -93,7 +94,7 @@ export const commands = {
uploadApk: async ({ args }: { args: string[] }) => {
const fn = args[0];
if (!fn || !fn.endsWith('.apk')) {
throw new Error('使用方法: pushy uploadApk apk后缀文件');
throw new Error(t('usageUploadApk'));
}
const {
versionName,
Expand Down Expand Up @@ -132,7 +133,7 @@ export const commands = {
uploadApp: async ({ args }: { args: string[] }) => {
const fn = args[0];
if (!fn || !fn.endsWith('.app')) {
throw new Error('使用方法: pushy uploadApp app后缀文件');
throw new Error(t('usageUploadApp'));
}
const {
versionName,
Expand Down Expand Up @@ -171,21 +172,21 @@ export const commands = {
parseApp: async ({ args }: { args: string[] }) => {
const fn = args[0];
if (!fn || !fn.endsWith('.app')) {
throw new Error('使用方法: pushy parseApp app后缀文件');
throw new Error(t('usageParseApp'));
}
console.log(await getAppInfo(fn));
},
parseIpa: async ({ args }: { args: string[] }) => {
const fn = args[0];
if (!fn || !fn.endsWith('.ipa')) {
throw new Error('使用方法: pushy parseIpa ipa后缀文件');
throw new Error(t('usageParseIpa'));
}
console.log(await getIpaInfo(fn));
},
parseApk: async ({ args }: { args: string[] }) => {
const fn = args[0];
if (!fn || !fn.endsWith('.apk')) {
throw new Error('使用方法: pushy parseApk apk后缀文件');
throw new Error(t('usageParseApk'));
}
console.log(await getApkInfo(fn));
},
Expand Down
5 changes: 3 additions & 2 deletions src/user.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { question } from './utils';
import { post, get, replaceSession, saveSession, closeSession } from './api';
import crypto from 'node:crypto';
import { t } from './utils/i18n';

function md5(str: string) {
return crypto.createHash('md5').update(str).digest('hex');
Expand All @@ -16,11 +17,11 @@ export const commands = {
});
replaceSession({ token });
await saveSession();
console.log(`欢迎使用 pushy 热更新服务, ${info.name}.`);
console.log(t('welcomeMessage', { name: info.name }));
},
logout: async () => {
await closeSession();
console.log('已退出登录');
console.log(t('loggedOut'));
},
me: async () => {
const me = await get('/user/me');
Expand Down
3 changes: 2 additions & 1 deletion src/utils/add-gitignore.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import fs from 'node:fs';
// import path from 'node:path';
import { credentialFile, tempDir } from './constants';
import { t } from './i18n';

export function addGitIgnore() {
const shouldIgnore = [credentialFile, tempDir];
Expand All @@ -26,7 +27,7 @@ export function addGitIgnore() {
gitignoreLines.push('# react-native-update');
for (const line of shouldIgnore) {
gitignoreLines.push(line);
console.log(`Added ${line} to .gitignore`);
console.log(t('addedToGitignore', { line }));
}

fs.writeFileSync(gitignorePath, gitignoreLines.join('\n'));
Expand Down
5 changes: 3 additions & 2 deletions src/utils/check-plugin.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { plugins } from './plugin-config';
import { t } from './i18n';

interface BundleParams {
sentry: boolean;
Expand All @@ -17,10 +18,10 @@ export async function checkPlugins(): Promise<BundleParams> {
const isEnabled = await plugin.detect();
if (isEnabled && plugin.bundleParams) {
Object.assign(params, plugin.bundleParams);
console.log(`detected ${plugin.name} plugin`);
console.log(t('pluginDetected', { name: plugin.name }));
}
} catch (err) {
console.warn(`error while detecting ${plugin.name} plugin:`, err);
console.warn(t('pluginDetectionError', { name: plugin.name, error: err }));
}
}

Expand Down
Loading
Loading