@oniroproject/core 0.6.2 → 0.8.0
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/README.md +267 -7
- package/dist/index.cjs +2088 -416
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1074 -24
- package/dist/index.d.ts +1074 -24
- package/dist/index.js +2013 -417
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/ports/logger.ts","../src/ports/progress.ts","../src/ports/config.ts","../src/ports/prompter.ts","../src/ports/errors.ts","../src/ports/context.ts","../src/sdk/constants.ts","../src/sdk/platform.ts","../src/sdk/paths.ts","../src/sdk/detectProjectSdk.ts","../src/sdk/download.ts","../src/sdk/extract.ts","../src/sdk/list.ts","../src/sdk/remove.ts","../src/sdk/install.ts","../src/cmdTools/install.ts","../src/sign/encryptKey.ts","../src/sign/generateSigningConfigs.ts","../src/sign/applicationCert.ts","../src/emulator/install.ts","../src/emulator/lifecycle.ts","../src/hdc/project.ts","../src/hdc/app.ts","../src/hdc/hilog.ts","../src/build/runHvigorw.ts","../src/project/validators.ts","../src/project/templates.ts","../src/project/createScaffold.ts","../src/project/jsonHelpers.ts"],"sourcesContent":["declare const __PKG_VERSION__: string;\nexport const VERSION = __PKG_VERSION__;\n\nexport * from './ports/index.js';\nexport * from './sdk/index.js';\nexport * from './cmdTools/index.js';\nexport * from './sign/index.js';\nexport * from './emulator/index.js';\nexport * from './hdc/index.js';\nexport * from './build/index.js';\nexport * from './project/index.js';\n","export interface Logger {\n debug(message: string): void;\n info(message: string): void;\n warn(message: string): void;\n error(message: string): void;\n}\n\nexport const noopLogger: Logger = {\n debug() {},\n info() {},\n warn() {},\n error() {},\n};\n\nexport const consoleLogger: Logger = {\n debug: (m) => console.debug(m),\n info: (m) => console.log(m),\n warn: (m) => console.warn(m),\n error: (m) => console.error(m),\n};\n","export interface ProgressUpdate {\n message?: string;\n increment?: number;\n}\n\nexport interface ProgressReporter {\n report(update: ProgressUpdate): void;\n}\n\nexport const noopProgress: ProgressReporter = {\n report() {},\n};\n","import * as os from 'node:os';\nimport * as path from 'node:path';\n\n/**\n * Keys read from the ConfigProvider by core. Frontends (CLI, VS Code extension)\n * implement the provider however they like (env vars, settings.json, etc.).\n */\nexport type ConfigKey =\n | 'sdkRootDir'\n | 'cmdToolsPath'\n | 'emulatorDir'\n | 'hapPath'\n | 'cmdToolsUrlLinux'\n | 'cmdToolsUrlWindows'\n | 'cmdToolsUrlMac'\n | 'emulatorUrl';\n\nexport interface ConfigProvider {\n /**\n * Get the configured value for `key`, or `fallback` if unset/empty.\n * Implementations should expand the literal `${userHome}` to the user's home dir.\n */\n get<T extends string | number | boolean>(key: ConfigKey, fallback: T): T;\n}\n\n/**\n * Default config values used when a ConfigProvider returns the fallback.\n * These match the historical paths used by the bash CLI and the extension.\n */\nexport const defaultPaths = {\n sdkRootDir: () => path.join(os.homedir(), 'setup-ohos-sdk'),\n cmdToolsPath: () => path.join(os.homedir(), 'command-line-tools'),\n emulatorDir: () => path.join(os.homedir(), 'oniro-emulator'),\n hapPath: 'entry/build/default/outputs/default/entry-default-signed.hap',\n emulatorUrl:\n 'https://github.com/eclipse-oniro4openharmony/device_board_oniro/releases/latest/download/oniro_emulator.zip',\n // The Huawei mirror only hosts a public Linux build of the command-line tools.\n // Windows and macOS require a manual download from the Huawei developer portal\n // (https://developer.huawei.com/...); pass the resulting ZIP to `cmdtools install --from-zip <path>`\n // or set ONIRO_CMD_TOOLS_URL_WINDOWS / ONIRO_CMD_TOOLS_URL_MAC to a self-hosted URL.\n cmdToolsUrlLinux:\n 'https://repo.huaweicloud.com/harmonyos/ohpm/5.1.0/commandline-tools-linux-x64-5.1.0.840.zip',\n} as const;\n\n/**\n * A simple in-memory ConfigProvider, useful for tests and as a base for CLI/extension impls.\n */\nexport function staticConfig(values: Partial<Record<ConfigKey, string>> = {}): ConfigProvider {\n return {\n get<T extends string | number | boolean>(key: ConfigKey, fallback: T): T {\n const v = values[key];\n if (v === undefined || v === '') {\n return fallback;\n }\n // Expand ${userHome} like the extension does.\n if (typeof v === 'string' && v.includes('${userHome}')) {\n return v.replace(/\\$\\{userHome\\}/g, os.homedir()) as unknown as T;\n }\n return v as unknown as T;\n },\n };\n}\n","/**\n * Interactive prompts. Frontends implement these — CLI uses @inquirer/prompts,\n * the extension uses `vscode.window.show*`. Core never assumes a TTY.\n */\nexport interface Prompter {\n /** Ask the user to confirm an action. */\n confirm(message: string, defaultValue?: boolean): Promise<boolean>;\n /** Ask the user for a single line of text. */\n input(message: string, defaultValue?: string): Promise<string>;\n /** Ask the user to pick a directory on disk; resolves to an absolute path or null if cancelled. */\n selectDirectory(message: string, defaultPath?: string): Promise<string | null>;\n /** Ask the user to pick a file on disk; resolves to an absolute path or null if cancelled. */\n selectFile(message: string, filters?: { extensions?: string[] }): Promise<string | null>;\n}\n\n/**\n * Throws on any prompt — used in non-interactive contexts where all answers must come from flags.\n */\nexport const nonInteractivePrompter: Prompter = {\n async confirm(message) {\n throw new Error(`Non-interactive mode: cannot confirm \"${message}\"`);\n },\n async input(message) {\n throw new Error(`Non-interactive mode: cannot ask \"${message}\"`);\n },\n async selectDirectory(message) {\n throw new Error(`Non-interactive mode: cannot prompt for directory \"${message}\"`);\n },\n async selectFile(message) {\n throw new Error(`Non-interactive mode: cannot prompt for file \"${message}\"`);\n },\n};\n","export class OniroError extends Error {\n constructor(message: string, public override readonly cause?: unknown) {\n super(message);\n this.name = 'OniroError';\n }\n}\n\nexport class SdkNotInstalledError extends OniroError {\n constructor(public readonly api: string, public readonly expectedPath: string) {\n super(`SDK API ${api} is not installed at ${expectedPath}.`);\n this.name = 'SdkNotInstalledError';\n }\n}\n\nexport class CmdToolsNotInstalledError extends OniroError {\n constructor(public readonly expectedPath: string) {\n super(`OpenHarmony command-line tools are not installed at ${expectedPath}.`);\n this.name = 'CmdToolsNotInstalledError';\n }\n}\n\nexport class UnsupportedPlatformError extends OniroError {\n constructor(public readonly platform: string) {\n super(`Unsupported platform: ${platform}.`);\n this.name = 'UnsupportedPlatformError';\n }\n}\n\nexport class ChecksumMismatchError extends OniroError {\n constructor(public readonly expected: string, public readonly actual: string) {\n super(`SHA256 mismatch: expected ${expected}, got ${actual}.`);\n this.name = 'ChecksumMismatchError';\n }\n}\n\nexport class CancelledError extends OniroError {\n constructor(message = 'Operation cancelled.') {\n super(message);\n this.name = 'CancelledError';\n }\n}\n","import { Logger, noopLogger } from './logger.js';\nimport { ConfigProvider, staticConfig } from './config.js';\n\n/**\n * Carries the cross-cutting dependencies most core functions need: a Logger and a ConfigProvider.\n * Functions that report progress or prompt the user take those as additional parameters.\n */\nexport interface OniroContext {\n logger: Logger;\n config: ConfigProvider;\n}\n\nexport function defaultContext(overrides: Partial<OniroContext> = {}): OniroContext {\n return {\n logger: overrides.logger ?? noopLogger,\n config: overrides.config ?? staticConfig(),\n };\n}\n","export interface SdkRelease {\n version: string;\n api: string;\n}\n\n/**\n * Known OpenHarmony SDK releases. Kept in sync with the bash CLI / extension.\n * Update when a new SDK ships.\n */\nexport const ALL_SDKS: readonly SdkRelease[] = [\n { version: '4.0', api: '10' },\n { version: '4.1', api: '11' },\n { version: '5.0.0', api: '12' },\n { version: '5.0.1', api: '13' },\n { version: '5.0.2', api: '14' },\n { version: '5.0.3', api: '15' },\n { version: '5.1.0', api: '18' },\n { version: '6.0', api: '20' },\n { version: '6.1', api: '23' },\n];\n\nexport const OHOS_URL_BASE = 'https://repo.huaweicloud.com/openharmony/os';\n","import * as os from 'node:os';\nimport { ALL_SDKS } from './constants.js';\nimport { UnsupportedPlatformError } from '../ports/errors.js';\n\nexport type OsFolder = 'linux' | 'darwin' | 'windows';\n\n/**\n * Map Node's `os.platform()` to the OS folder name used in the SDK install layout\n * and the SDK release tarballs.\n */\nexport function getOsFolder(): OsFolder {\n const platform = os.platform();\n if (platform === 'linux') return 'linux';\n if (platform === 'darwin') return 'darwin';\n if (platform === 'win32') return 'windows';\n throw new UnsupportedPlatformError(platform);\n}\n\nexport interface SdkArchiveInfo {\n filename: string;\n osFolder: OsFolder;\n /** Number of leading path components to strip when extracting the tarball. */\n strip: number;\n}\n\n/**\n * Resolve the SDK archive filename, OS folder, and tar strip count for the current platform.\n *\n * The Huawei mirror packages Linux and Windows together in one tarball with `linux/` and\n * `windows/` subfolders. For 5.0.0/5.0.1/6.0 the tarball has no extra top-level wrapper\n * (strip=0); newer/older releases wrap the OS folders in a single top-level directory (strip=1).\n * macOS tarballs have a deeper layout (strip=3).\n */\nexport function getSdkFilename(version?: string): SdkArchiveInfo {\n const platform = os.platform();\n const v = version ?? ALL_SDKS[ALL_SDKS.length - 1]!.version;\n\n if (platform === 'linux') {\n const strip = v === '5.0.0' || v === '5.0.1' || v === '6.0' || v === '6.1' ? 0 : 1;\n return { filename: 'ohos-sdk-windows_linux-public.tar.gz', osFolder: 'linux', strip };\n }\n if (platform === 'darwin') {\n if (os.arch() === 'arm64') {\n return { filename: 'L2-SDK-MAC-M1-PUBLIC.tar.gz', osFolder: 'darwin', strip: 3 };\n }\n return { filename: 'ohos-sdk-mac-public.tar.gz', osFolder: 'darwin', strip: 3 };\n }\n if (platform === 'win32') {\n const strip = v === '5.0.0' || v === '5.0.1' || v === '6.0' || v === '6.1' ? 0 : 1;\n return { filename: 'ohos-sdk-windows_linux-public.tar.gz', osFolder: 'windows', strip };\n }\n throw new UnsupportedPlatformError(platform);\n}\n","import * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport { ConfigProvider, defaultPaths } from '../ports/config.js';\nimport { getOsFolder } from './platform.js';\n\nexport function getSdkRootDir(config: ConfigProvider): string {\n return config.get('sdkRootDir', defaultPaths.sdkRootDir());\n}\n\n/**\n * Base SDK home for the current OS: `<sdkRootDir>/<linux|darwin|windows>`.\n * SDK API folders (e.g. `12`, `18`, `20`) live inside this directory.\n */\nexport function getOhosBaseSdkHome(config: ConfigProvider): string {\n return path.join(getSdkRootDir(config), getOsFolder());\n}\n\nexport function getCmdToolsPath(config: ConfigProvider): string {\n return config.get('cmdToolsPath', defaultPaths.cmdToolsPath());\n}\n\nexport function getEmulatorDir(config: ConfigProvider): string {\n return config.get('emulatorDir', defaultPaths.emulatorDir());\n}\n\nfunction pickExisting(candidates: string[]): string {\n for (const c of candidates) {\n if (fs.existsSync(c)) return c;\n }\n return candidates[0]!;\n}\n\n/**\n * Resolve the OHPM binary path inside the command-line tools install.\n * On Windows tries common executable suffixes (.exe, .cmd, .bat) before the POSIX name.\n */\nexport function getCmdToolsBin(config: ConfigProvider): string {\n const binDir = path.join(getCmdToolsPath(config), 'bin');\n if (os.platform() === 'win32') {\n return pickExisting([\n path.join(binDir, 'ohpm.exe'),\n path.join(binDir, 'ohpm.cmd'),\n path.join(binDir, 'ohpm.bat'),\n path.join(binDir, 'ohpm'),\n ]);\n }\n return path.join(binDir, 'ohpm');\n}\n\n/**\n * Resolve the hdc binary path inside the SDK toolchains tree.\n */\nexport function getHdcPath(config: ConfigProvider): string {\n const base = path.join(getCmdToolsPath(config), 'sdk', 'default', 'openharmony', 'toolchains');\n if (os.platform() === 'win32') {\n return pickExisting([\n path.join(base, 'hdc.exe'),\n path.join(base, 'hdc.bat'),\n path.join(base, 'hdc.cmd'),\n path.join(base, 'hdc'),\n ]);\n }\n return path.join(base, 'hdc');\n}\n\n/**\n * Resolve the hvigorw wrapper for a project, preferring the project-local copy\n * (which carries the project's pinned hvigor version) and falling back to the\n * one shipped with the command-line tools.\n */\nexport function getHvigorwPath(config: ConfigProvider, projectDir: string): string {\n const cmdToolsBin = path.join(getCmdToolsPath(config), 'bin');\n return pickExisting([\n path.join(projectDir, 'hvigorw'),\n path.join(projectDir, 'hvigorw.bat'),\n path.join(projectDir, 'hvigorw.cmd'),\n path.join(cmdToolsBin, 'hvigorw'),\n path.join(cmdToolsBin, 'hvigorw.bat'),\n path.join(cmdToolsBin, 'hvigorw.cmd'),\n ]);\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport JSON5 from 'json5';\nimport { Logger, noopLogger } from '../ports/logger.js';\n\n/**\n * Detect the SDK API a project targets by reading `build-profile.json5`.\n * Returns the `compileSdkVersion` of the first declared product, or undefined\n * if the file is missing/malformed or no product declares one.\n */\nexport function detectProjectSdkVersion(projectRoot: string, logger: Logger = noopLogger): number | undefined {\n const buildProfilePath = path.join(projectRoot, 'build-profile.json5');\n if (!fs.existsSync(buildProfilePath)) {\n logger.warn(`build-profile.json5 not found at ${projectRoot}`);\n return undefined;\n }\n try {\n const content = fs.readFileSync(buildProfilePath, 'utf-8');\n const config = JSON5.parse(content) as { app?: { products?: Array<{ compileSdkVersion?: unknown }> } };\n const product = config.app?.products?.[0];\n const v = product?.compileSdkVersion;\n return typeof v === 'number' ? v : undefined;\n } catch (err) {\n logger.error(`Error reading build-profile.json5 at ${projectRoot}: ${String(err)}`);\n return undefined;\n }\n}\n","import * as fs from 'node:fs';\nimport * as crypto from 'node:crypto';\nimport { pipeline } from 'node:stream';\nimport { promisify } from 'node:util';\nimport followRedirects from 'follow-redirects';\nimport type { ProgressReporter } from '../ports/progress.js';\nimport { CancelledError, ChecksumMismatchError, OniroError } from '../ports/errors.js';\n\nconst { http, https } = followRedirects;\nconst pipelineAsync = promisify(pipeline);\n\nexport interface DownloadOptions {\n url: string;\n dest: string;\n progress?: ProgressReporter;\n abortSignal?: AbortSignal;\n /** Overall progress start offset (0..100). Default 0. */\n start?: number;\n /** Overall progress range to consume (0..100). Default 100. */\n range?: number;\n}\n\n/**\n * Stream a remote file to disk with optional progress reporting and cancellation.\n * Follows redirects via the `follow-redirects` library.\n */\nexport async function downloadFile(opts: DownloadOptions): Promise<void> {\n const { url, dest, progress, abortSignal } = opts;\n const proto = url.startsWith('https') ? https : http;\n\n return new Promise((resolve, reject) => {\n const s = Math.max(0, Math.min(100, opts.start ?? 0));\n const r = Math.max(0, Math.min(100 - s, opts.range ?? 100));\n\n let settled = false;\n const done = (err?: unknown) => {\n if (settled) return;\n settled = true;\n err ? reject(err) : resolve();\n };\n\n if (abortSignal?.aborted) {\n done(new CancelledError('Download cancelled before start.'));\n return;\n }\n\n const file = fs.createWriteStream(dest);\n\n const req = proto.get(url, (response) => {\n if (response.statusCode !== 200) {\n try { response.destroy(); } catch {}\n try { file.close(); } catch {}\n fs.unlink(dest, () => {});\n done(new OniroError(`Failed to download '${url}' (HTTP ${response.statusCode})`));\n return;\n }\n\n const total = parseInt(response.headers['content-length'] || '0', 10);\n let downloaded = 0;\n let lastOverall = Math.round(s);\n\n response.on('data', (chunk: Buffer) => {\n downloaded += chunk.length;\n if (progress && total) {\n const localPercent = Math.min(100, Math.round((downloaded / total) * 100));\n const overall = Math.min(100, Math.round(s + (downloaded / total) * r));\n const inc = overall - lastOverall;\n if (inc > 0) {\n progress.report({ message: `Downloading: ${localPercent}%`, increment: inc });\n lastOverall = overall;\n } else {\n progress.report({ message: `Downloading: ${localPercent}%`, increment: 0 });\n }\n }\n });\n\n response.pipe(file);\n\n file.on('finish', () => {\n if (progress) {\n const endOverall = Math.min(100, Math.round(s + r));\n const inc = endOverall - lastOverall;\n if (inc > 0) progress.report({ message: 'Downloading: 100%', increment: inc });\n }\n file.close((err) => (err ? done(err) : done()));\n });\n\n abortSignal?.addEventListener('abort', () => {\n response.destroy();\n file.close();\n fs.unlink(dest, () => {});\n done(new CancelledError('Download cancelled.'));\n });\n });\n\n req.on('error', (err) => {\n try { file.close(); } catch {}\n fs.unlink(dest, () => {});\n done(new OniroError(`Error downloading '${url}': ${err.message}`, err));\n });\n\n abortSignal?.addEventListener('abort', () => {\n req.destroy();\n file.close();\n fs.unlink(dest, () => {});\n done(new CancelledError('Download cancelled.'));\n });\n });\n}\n\n/**\n * Verify the SHA-256 checksum of a file against an on-disk .sha256 file.\n * The .sha256 file is expected to contain the hex digest as its first whitespace-delimited token.\n */\nexport async function verifySha256(filePath: string, sha256Path: string): Promise<void> {\n const expected = fs.readFileSync(sha256Path, 'utf8').split(/\\s+/)[0]!;\n const hash = crypto.createHash('sha256');\n await pipelineAsync(fs.createReadStream(filePath), hash);\n const actual = hash.digest('hex');\n if (actual !== expected) {\n throw new ChecksumMismatchError(expected, actual);\n }\n}\n","import * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport { pipeline } from 'node:stream';\nimport { promisify } from 'node:util';\nimport * as tar from 'tar';\nimport StreamZip from 'node-stream-zip';\nimport type { ProgressReporter } from '../ports/progress.js';\nimport type { Logger } from '../ports/logger.js';\nimport { noopLogger } from '../ports/logger.js';\nimport { OniroError } from '../ports/errors.js';\n\nconst pipelineAsync = promisify(pipeline);\n\nexport interface ExtractZipOptions {\n zipPath: string;\n dest: string;\n progress?: ProgressReporter;\n /** Overall progress start offset (0..100). Default 0. */\n start?: number;\n /** Overall progress range to consume (0..100). Default 100. */\n range?: number;\n logger?: Logger;\n}\n\n/**\n * Extract a ZIP to a destination directory, preserving file permissions and following\n * symlinks defensively. Protects against Zip Slip (entries whose paths escape `dest`).\n */\nexport async function extractZipWithProgress(opts: ExtractZipOptions): Promise<void> {\n const { zipPath, dest, progress } = opts;\n const logger = opts.logger ?? noopLogger;\n\n const zip = new (StreamZip as unknown as { async: new (cfg: { file: string }) => StreamZipAsync }).async({ file: zipPath });\n const entries = await zip.entries();\n const files = Object.values(entries);\n const total = files.length || 1;\n\n const s = Math.max(0, Math.min(100, opts.start ?? 0));\n const r = Math.max(0, Math.min(100 - s, opts.range ?? 100));\n\n let processed = 0;\n let lastOverall = Math.round(s);\n\n await fs.promises.mkdir(dest, { recursive: true });\n const destRoot = path.resolve(dest);\n\n const safeResolveTarget = (entryName: string): string => {\n const resolved = path.resolve(destRoot, entryName);\n const rel = path.relative(destRoot, resolved);\n if (rel.startsWith('..') || path.isAbsolute(rel)) {\n throw new OniroError(`Blocked ZIP entry with illegal path: ${entryName}`);\n }\n return resolved;\n };\n\n try {\n for (const file of files) {\n const entryName = file.name;\n const targetPath = safeResolveTarget(entryName);\n const attr = file.attr ? (file.attr >>> 16) : 0;\n const isSymlink = 'isSymbolicLink' in file\n ? Boolean(file.isSymbolicLink)\n : (attr & 0o170000) === 0o120000;\n\n if (file.isDirectory) {\n await fs.promises.mkdir(targetPath, { recursive: true });\n } else if (isSymlink) {\n await fs.promises.mkdir(path.dirname(targetPath), { recursive: true });\n const linkTargetBuffer = await zip.entryData(file);\n const linkTarget = linkTargetBuffer.toString('utf8');\n try {\n const isWin = os.platform() === 'win32';\n await fs.promises.symlink(linkTarget, targetPath, isWin ? 'file' : undefined);\n } catch (e) {\n logger.warn(`Failed to create symlink at ${targetPath}: ${String(e)}`);\n }\n } else {\n await fs.promises.mkdir(path.dirname(targetPath), { recursive: true });\n const readStream = await zip.stream(file);\n const writeStream = fs.createWriteStream(targetPath);\n await pipelineAsync(readStream, writeStream);\n if (attr > 0) {\n try {\n await fs.promises.chmod(targetPath, attr & 0o777);\n } catch {\n // Best-effort: Windows or filesystems without POSIX perms — ignore.\n }\n }\n }\n\n processed++;\n if (progress) {\n const localPercent = Math.min(100, Math.round((processed / total) * 100));\n const overall = Math.min(100, Math.round(s + (processed / total) * r));\n const inc = overall - lastOverall;\n if (inc > 0) {\n progress.report({ message: `Extracting: ${localPercent}%`, increment: inc });\n lastOverall = overall;\n } else {\n progress.report({ message: `Extracting: ${localPercent}%`, increment: 0 });\n }\n }\n }\n } finally {\n await zip.close();\n }\n\n if (progress) {\n const endOverall = Math.min(100, Math.round(s + r));\n const inc = endOverall - lastOverall;\n if (inc > 0) progress.report({ message: 'Extracting: 100%', increment: inc });\n }\n}\n\n/**\n * Extract a tar/tar.gz/tar.bz2 archive. Wraps `tar.x`.\n */\nexport async function extractTarball(tarPath: string, dest: string, strip = 0): Promise<void> {\n await tar.x({ file: tarPath, cwd: dest, strip });\n}\n\n// node-stream-zip's TypeScript types aren't great; this is the minimal shape we use.\ninterface ZipEntry {\n name: string;\n isDirectory: boolean;\n isSymbolicLink?: boolean;\n attr?: number;\n}\ninterface StreamZipAsync {\n entries(): Promise<Record<string, ZipEntry>>;\n entryData(entry: ZipEntry): Promise<Buffer>;\n stream(entry: ZipEntry): Promise<NodeJS.ReadableStream>;\n close(): Promise<void>;\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { ALL_SDKS } from './constants.js';\nimport { getSdkRootDir } from './paths.js';\nimport { getOsFolder } from './platform.js';\nimport type { ConfigProvider } from '../ports/config.js';\n\nexport interface SdkInfo {\n version: string;\n api: string;\n installed: boolean;\n}\n\n/**\n * List supported SDKs annotated with whether they are installed for the current OS.\n * Sorted by API descending (newest first).\n */\nexport function getSupportedSdksForUi(config: ConfigProvider): SdkInfo[] {\n const base = path.join(getSdkRootDir(config), getOsFolder());\n return ALL_SDKS.map((sdk) => ({\n version: sdk.version,\n api: sdk.api,\n installed: fs.existsSync(path.join(base, sdk.api)),\n })).sort((a, b) => Number(b.api) - Number(a.api));\n}\n\n/**\n * Return the SDK versions that have at least one OS-folder install in `sdkRootDir`.\n * Scans `linux`, `darwin`, `windows` so the list is consistent across machines that\n * share an SDK root over a network mount.\n */\nexport function getInstalledSdks(config: ConfigProvider): string[] {\n const sdkRoot = getSdkRootDir(config);\n const versions = new Set<string>();\n if (!fs.existsSync(sdkRoot)) return [];\n\n for (const osFolder of ['linux', 'darwin', 'windows'] as const) {\n const osPath = path.join(sdkRoot, osFolder);\n if (!fs.existsSync(osPath) || !fs.statSync(osPath).isDirectory()) continue;\n for (const api of fs.readdirSync(osPath)) {\n const apiPath = path.join(osPath, api);\n if (fs.statSync(apiPath).isDirectory()) versions.add(api);\n }\n }\n return ALL_SDKS.filter((sdk) => versions.has(sdk.api)).map((sdk) => sdk.version);\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { getSdkRootDir } from './paths.js';\nimport type { ConfigProvider } from '../ports/config.js';\n\n/**\n * Remove an installed SDK for a given API level, across all OS folders.\n * Returns true if at least one folder was deleted.\n */\nexport function removeSdk(config: ConfigProvider, api: string): boolean {\n const sdkRoot = getSdkRootDir(config);\n let removed = false;\n for (const osFolder of ['linux', 'darwin', 'windows']) {\n const sdkPath = path.join(sdkRoot, osFolder, api);\n if (fs.existsSync(sdkPath)) {\n fs.rmSync(sdkPath, { recursive: true, force: true });\n removed = true;\n }\n }\n return removed;\n}\n","import * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport type { ConfigProvider } from '../ports/config.js';\nimport type { ProgressReporter } from '../ports/progress.js';\nimport type { Logger } from '../ports/logger.js';\nimport { noopLogger } from '../ports/logger.js';\nimport { CancelledError, OniroError } from '../ports/errors.js';\nimport { OHOS_URL_BASE } from './constants.js';\nimport { getSdkFilename } from './platform.js';\nimport { getSdkRootDir } from './paths.js';\nimport { downloadFile, verifySha256 } from './download.js';\nimport { extractTarball, extractZipWithProgress } from './extract.js';\n\nexport interface InstallSdkOptions {\n config: ConfigProvider;\n version: string;\n api: string;\n progress?: ProgressReporter;\n abortSignal?: AbortSignal;\n logger?: Logger;\n}\n\n/**\n * Download and install an OpenHarmony SDK release into `<sdkRootDir>/<osFolder>/<api>`.\n *\n * Progress budget (overall 0..100):\n * 0..35 SDK archive download\n * 35..45 Checksum download\n * 45..50 Checksum verify\n * 50..60 Tarball extract\n * 60..95 Component ZIP extracts\n * 95..100 Finalize + cleanup\n */\nexport async function downloadAndInstallSdk(opts: InstallSdkOptions): Promise<void> {\n const { config, version, api, progress, abortSignal } = opts;\n const logger = opts.logger ?? noopLogger;\n\n const { filename, osFolder, strip } = getSdkFilename(version);\n const downloadUrl = `${OHOS_URL_BASE}/${version}-Release/${filename}`;\n const sha256Url = `${downloadUrl}.sha256`;\n\n const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'oniro-sdk-'));\n const tarPath = path.join(tmpDir, filename);\n const sha256Path = path.join(tmpDir, `${filename}.sha256`);\n const extractDir = path.join(tmpDir, 'extract');\n fs.mkdirSync(extractDir);\n\n const sdkInstallDir = path.join(getSdkRootDir(config), osFolder, api);\n fs.mkdirSync(path.dirname(sdkInstallDir), { recursive: true });\n\n const checkCancelled = () => {\n if (abortSignal?.aborted) throw new CancelledError();\n };\n\n try {\n progress?.report({ message: 'Downloading SDK archive...', increment: 0 });\n await downloadFile({ url: downloadUrl, dest: tarPath, progress, abortSignal, start: 0, range: 35 });\n\n progress?.report({ message: 'Downloading checksum...', increment: 0 });\n await downloadFile({ url: sha256Url, dest: sha256Path, progress, abortSignal, start: 35, range: 10 });\n\n progress?.report({ message: 'Verifying checksum...', increment: 0 });\n await verifySha256(tarPath, sha256Path);\n progress?.report({ message: 'Verifying checksum...', increment: 5 });\n\n checkCancelled();\n\n progress?.report({ message: 'Extracting SDK (this may take a while)...', increment: 0 });\n await extractTarball(tarPath, extractDir, strip);\n progress?.report({ message: 'Extracting SDK (this may take a while)...', increment: 10 });\n\n checkCancelled();\n\n const osContentPath = path.join(extractDir, osFolder);\n if (!fs.existsSync(osContentPath)) {\n throw new OniroError(\n `Expected folder '${osFolder}' not found in extracted SDK. Tarball layout may have changed.`,\n );\n }\n const zipFiles = fs.readdirSync(osContentPath).filter((n) => n.endsWith('.zip'));\n\n const componentsStart = 60;\n const componentsBudget = 35;\n const n = zipFiles.length;\n if (n === 0) {\n progress?.report({ message: 'No SDK component ZIPs found.', increment: componentsBudget });\n } else {\n progress?.report({ message: 'Extracting SDK components...', increment: 0 });\n }\n\n const base = n > 0 ? Math.floor(componentsBudget / n) : 0;\n let rem = n > 0 ? componentsBudget % n : 0;\n let cursor = componentsStart;\n\n for (const zipFile of zipFiles) {\n checkCancelled();\n logger.info(`Extracting component ${zipFile}`);\n const zipPath = path.join(osContentPath, zipFile);\n const thisBudget = base + (rem > 0 ? 1 : 0);\n if (rem > 0) rem--;\n await extractZipWithProgress({ zipPath, dest: osContentPath, progress, start: cursor, range: thisBudget, logger });\n cursor += thisBudget;\n fs.unlinkSync(zipPath);\n }\n\n progress?.report({ message: 'Finalizing installation...', increment: 0 });\n if (fs.existsSync(sdkInstallDir)) {\n fs.rmSync(sdkInstallDir, { recursive: true, force: true });\n }\n fs.renameSync(osContentPath, sdkInstallDir);\n progress?.report({ message: 'Finalizing installation...', increment: 3 });\n\n progress?.report({ message: 'Cleaning up...', increment: 0 });\n fs.rmSync(tmpDir, { recursive: true, force: true });\n progress?.report({ message: 'Cleaning up...', increment: 2 });\n } catch (err) {\n logger.error(`SDK install failed: ${err instanceof Error ? err.message : String(err)}`);\n fs.rmSync(tmpDir, { recursive: true, force: true });\n throw err;\n }\n}\n","import * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport { execFileSync } from 'node:child_process';\nimport type { ConfigProvider } from '../ports/config.js';\nimport { defaultPaths } from '../ports/config.js';\nimport type { ProgressReporter } from '../ports/progress.js';\nimport type { Logger } from '../ports/logger.js';\nimport { noopLogger } from '../ports/logger.js';\nimport { OniroError, UnsupportedPlatformError } from '../ports/errors.js';\nimport { getCmdToolsPath } from '../sdk/paths.js';\nimport { downloadFile } from '../sdk/download.js';\nimport { extractZipWithProgress } from '../sdk/extract.js';\n\n/**\n * Resolve the per-platform download URL for the OpenHarmony command-line tools.\n *\n * Only Linux has a public download URL on the Huawei mirror. Windows and macOS\n * builds are gated behind the Huawei developer portal: users must download the\n * ZIP manually and pass it via `--from-zip`, or self-host the archive and point\n * `cmdToolsUrlWindows` / `cmdToolsUrlMac` at it.\n *\n * @param platform Defaults to the current host. Override for testing.\n */\nexport function getCmdToolsDownloadUrl(config: ConfigProvider, platform: NodeJS.Platform = os.platform()): string {\n if (platform === 'linux') {\n return config.get('cmdToolsUrlLinux', defaultPaths.cmdToolsUrlLinux);\n }\n if (platform === 'win32') {\n const url = config.get('cmdToolsUrlWindows', '');\n if (!url) {\n throw new OniroError(\n 'No Windows command-line tools URL configured. The Huawei mirror does not host a public Windows build; ' +\n 'download the ZIP from the Huawei developer portal and run `oniro-app cmdtools install --from-zip <path>`, ' +\n 'or set ONIRO_CMD_TOOLS_URL_WINDOWS to a self-hosted URL.',\n );\n }\n return url;\n }\n if (platform === 'darwin') {\n const url = config.get('cmdToolsUrlMac', '');\n if (!url) {\n throw new OniroError(\n 'No macOS command-line tools URL configured. The Huawei mirror does not host a public macOS build; ' +\n 'download the ZIP from the Huawei developer portal and run `oniro-app cmdtools install --from-zip <path>`, ' +\n 'or set ONIRO_CMD_TOOLS_URL_MAC to a self-hosted URL.',\n );\n }\n return url;\n }\n throw new UnsupportedPlatformError(platform);\n}\n\n/**\n * Locate the extracted command-line tools' source root within a temp extraction folder.\n * Tries known top-level names, then any subdirectory containing a `bin/` folder.\n */\nexport function findCmdToolsSourceDir(extractPath: string): string {\n const known = [\n path.join(extractPath, 'command-line-tools'),\n path.join(extractPath, 'oh-command-line-tools'),\n path.join(extractPath, 'commandline-tools'),\n ];\n for (const c of known) {\n if (fs.existsSync(c)) return c;\n }\n const entries = fs\n .readdirSync(extractPath, { withFileTypes: true })\n .filter((e) => e.isDirectory())\n .map((e) => path.join(extractPath, e.name));\n for (const dir of entries) {\n if (fs.existsSync(path.join(dir, 'bin'))) return dir;\n }\n throw new OniroError('Could not locate command line tools folder in the extracted archive.');\n}\n\nexport interface InstallCmdToolsOptions {\n config: ConfigProvider;\n progress?: ProgressReporter;\n abortSignal?: AbortSignal;\n logger?: Logger;\n /** Skip download and install from a local zip the caller already has. */\n localZipPath?: string;\n}\n\n/**\n * Install the OpenHarmony command-line tools into `<cmdToolsPath>`.\n * Either downloads from the platform-specific URL or installs from a caller-supplied ZIP.\n */\nexport async function installCmdTools(opts: InstallCmdToolsOptions): Promise<void> {\n const { config, progress, abortSignal } = opts;\n const logger = opts.logger ?? noopLogger;\n const CMD_PATH = getCmdToolsPath(config);\n\n const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'oniro-cmdtools-'));\n const zipPath = opts.localZipPath ?? path.join(tmpDir, 'oh-command-line-tools.zip');\n const extractPath = path.join(tmpDir, 'oh-command-line-tools');\n\n try {\n if (!opts.localZipPath) {\n const url = getCmdToolsDownloadUrl(config);\n progress?.report({ message: 'Downloading command line tools...', increment: 0 });\n await downloadFile({ url, dest: zipPath, progress, abortSignal, start: 0, range: 50 });\n }\n\n progress?.report({ message: 'Extracting tools...', increment: 0 });\n await extractZipWithProgress({ zipPath, dest: extractPath, progress, start: 50, range: 45, logger });\n\n fs.mkdirSync(CMD_PATH, { recursive: true });\n const srcDir = findCmdToolsSourceDir(extractPath);\n\n for (const entry of fs.readdirSync(srcDir)) {\n const src = path.join(srcDir, entry);\n const dest = path.join(CMD_PATH, entry);\n if (fs.statSync(src).isDirectory()) {\n if (fs.existsSync(dest)) fs.rmSync(dest, { recursive: true, force: true });\n fs.renameSync(src, dest);\n } else {\n fs.copyFileSync(src, dest);\n }\n }\n\n const binDir = path.join(CMD_PATH, 'bin');\n if (fs.existsSync(binDir) && os.platform() !== 'win32') {\n for (const file of fs.readdirSync(binDir)) {\n fs.chmodSync(path.join(binDir, file), 0o755);\n }\n }\n\n progress?.report({ message: 'Finalizing installation...', increment: 5 });\n progress?.report({ message: 'Cleaning up...', increment: 0 });\n } finally {\n fs.rmSync(tmpDir, { recursive: true, force: true });\n }\n}\n\nexport interface CmdToolsStatus {\n installed: boolean;\n status: string;\n}\n\n/**\n * Reports whether ohpm is present at the configured path, and if so its version.\n * Prefers reading `version.txt` (`# Version: x.y.z`) before falling back to executing\n * the binary with `-v`.\n */\nexport function getCmdToolsStatus(config: ConfigProvider): CmdToolsStatus {\n const cmdPath = getCmdToolsPath(config);\n const binDir = path.join(cmdPath, 'bin');\n const candidates = os.platform() === 'win32'\n ? ['ohpm.exe', 'ohpm.cmd', 'ohpm.bat', 'ohpm']\n : ['ohpm'];\n const bin = candidates.map((c) => path.join(binDir, c)).find((p) => fs.existsSync(p));\n if (!bin) {\n return { installed: false, status: 'Not installed' };\n }\n\n // Prefer version.txt.\n try {\n const versionFile = path.join(cmdPath, 'version.txt');\n if (fs.existsSync(versionFile)) {\n const content = fs.readFileSync(versionFile, 'utf8');\n for (const line of content.split(/\\r?\\n/)) {\n const m = line.match(/^\\s*#\\s*Version:\\s*(.+)$/);\n if (m?.[1]) return { installed: true, status: `Installed (${m[1].trim()})` };\n }\n }\n } catch {\n // Fall through to exec.\n }\n\n try {\n const version = execFileSync(bin, ['-v'], { encoding: 'utf8' }).trim();\n return { installed: true, status: `Installed (${version})` };\n } catch {\n return { installed: true, status: 'Installed (version unknown)' };\n }\n}\n\nexport function isCmdToolsInstalled(config: ConfigProvider): boolean {\n return getCmdToolsStatus(config).installed;\n}\n\nexport function removeCmdTools(config: ConfigProvider): void {\n const cmdPath = getCmdToolsPath(config);\n if (fs.existsSync(cmdPath)) {\n fs.rmSync(cmdPath, { recursive: true, force: true });\n }\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport * as crypto from 'node:crypto';\n\nconst DAEMON_ROOT_KEY_COMPONENT_LENGTH = 16;\nconst DAEMON_SALT_KEY_LENGTH = 16;\nconst DAEMON_WORK_KEY_LENGTH = 16;\nconst KEY_FILE_DIRECTORY_PERMISSIONS = 0o755;\nconst KEY_FILE_PERMISSIONS = 0o600;\n\nconst COMPONENT = Buffer.from([\n 49, 243, 9, 115, 214, 175, 91, 184, 211, 190, 177, 88, 101, 131, 192, 119,\n]);\n\n/**\n * Encrypts data using AES-128-GCM.\n * Output layout: [4-byte BE length][12-byte IV][ciphertext][16-byte auth tag].\n */\nfunction encrypt(key: Buffer, data: Buffer): Buffer {\n const iv = crypto.randomBytes(12);\n const cipher = crypto.createCipheriv('aes-128-gcm', key, iv);\n const ciphertext = Buffer.concat([cipher.update(data), cipher.final()]);\n const authTag = cipher.getAuthTag();\n const totalLength = ciphertext.length + authTag.length;\n const out = Buffer.alloc(4 + iv.length + ciphertext.length + authTag.length);\n out.writeUInt32BE(totalLength, 0);\n iv.copy(out, 4);\n ciphertext.copy(out, 16);\n authTag.copy(out, 16 + ciphertext.length);\n return out;\n}\n\nfunction decrypt(key: Buffer, data: Buffer): Buffer {\n const totalLength = data.readUInt32BE(0);\n const iv = data.subarray(4, 16);\n const ciphertextLength = totalLength - 16;\n const ciphertext = data.subarray(16, 16 + ciphertextLength);\n const authTag = data.subarray(16 + ciphertextLength);\n const decipher = crypto.createDecipheriv('aes-128-gcm', key, iv);\n decipher.setAuthTag(authTag);\n return Buffer.concat([decipher.update(ciphertext), decipher.final()]);\n}\n\nfunction xorBuffers(buffers: Buffer[]): Buffer {\n if (buffers.length === 0) {\n throw new Error('No buffers provided for XOR.');\n }\n const result = Buffer.from(buffers[0]!);\n for (let i = 1; i < buffers.length; i++) {\n const buf = buffers[i]!;\n if (buf.length !== result.length) {\n throw new Error('Buffers have different lengths in XOR.');\n }\n for (let j = 0; j < result.length; j++) {\n result[j] = result[j]! ^ buf[j]!;\n }\n }\n return result;\n}\n\nfunction getRootKey(fdComponents: Buffer[], salt: Buffer): Buffer {\n const components = fdComponents.concat([COMPONENT]);\n const xored = xorBuffers(components);\n return crypto.pbkdf2Sync(xored.toString(), salt, 10000, 16, 'sha256');\n}\n\nfunction createAndStoreKey(dir: string, keyLength: number): Buffer {\n const key = crypto.randomBytes(keyLength);\n const hash = crypto.createHash('sha256').update(key).digest('hex');\n const filePath = path.join(dir, hash);\n fs.writeFileSync(filePath, key);\n fs.chmodSync(filePath, KEY_FILE_PERMISSIONS);\n return key;\n}\n\nfunction createAndStoreEnKey(rootKey: Buffer, ceDir: string): void {\n const workKey = crypto.randomBytes(DAEMON_WORK_KEY_LENGTH);\n const encrypted = encrypt(rootKey, workKey);\n const hash = crypto.createHash('sha256').update(encrypted).digest('hex');\n const filePath = path.join(ceDir, hash);\n fs.writeFileSync(filePath, encrypted);\n fs.chmodSync(filePath, KEY_FILE_PERMISSIONS);\n}\n\n/**\n * Generates the signing-material directory tree: fd/{0,1,2}, ac, ce.\n * Each subfolder contains a randomly-named keyfile derived as described in\n * the OpenHarmony hap-sign-tool reference implementation.\n */\nexport function createMaterial(materialPath: string): void {\n fs.mkdirSync(materialPath, { recursive: true });\n fs.chmodSync(materialPath, KEY_FILE_DIRECTORY_PERMISSIONS);\n\n const fdDir = path.join(materialPath, 'fd');\n const acDir = path.join(materialPath, 'ac');\n const ceDir = path.join(materialPath, 'ce');\n\n fs.mkdirSync(fdDir, { recursive: true });\n fs.mkdirSync(acDir, { recursive: true });\n fs.mkdirSync(ceDir, { recursive: true });\n\n const fdSubDirs = ['0', '1', '2'];\n const fdComponents: Buffer[] = [];\n for (const sub of fdSubDirs) {\n const subDir = path.join(fdDir, sub);\n fs.mkdirSync(subDir, { recursive: true });\n const comp = createAndStoreKey(subDir, DAEMON_ROOT_KEY_COMPONENT_LENGTH);\n fdComponents.push(comp);\n }\n\n const salt = createAndStoreKey(acDir, DAEMON_SALT_KEY_LENGTH);\n const rootKey = getRootKey(fdComponents, salt);\n createAndStoreEnKey(rootKey, ceDir);\n}\n\nfunction readSingleFile(dir: string): Buffer {\n if (!fs.existsSync(dir) || !fs.statSync(dir).isDirectory()) {\n throw new Error(`Missing signing material directory: ${dir}`);\n }\n const files = fs.readdirSync(dir).filter((f) => f !== '.DS_Store');\n if (files.length !== 1) {\n throw new Error(`Signing material in ${dir} is illegal (expected exactly one file).`);\n }\n return fs.readFileSync(path.join(dir, files[0]!));\n}\n\n/**\n * Re-derives the work key from an existing material directory.\n */\nexport function getKey(materialPath: string): Buffer {\n if (!fs.existsSync(materialPath) || !fs.statSync(materialPath).isDirectory()) {\n throw new Error('Material directory does not exist.');\n }\n\n const fdDir = path.join(materialPath, 'fd');\n const fdComponents = ['0', '1', '2'].map((sub) => readSingleFile(path.join(fdDir, sub)));\n const salt = readSingleFile(path.join(materialPath, 'ac'));\n const rootKey = getRootKey(fdComponents, salt);\n const workMaterial = readSingleFile(path.join(materialPath, 'ce'));\n return decrypt(rootKey, workMaterial);\n}\n\n/**\n * Encrypts a password using the work key derived from `materialPath`.\n * Returns the encrypted blob as a hex string (the format expected in build-profile.json5).\n */\nexport function encryptPwd(password: string, materialPath: string): string {\n const key = getKey(materialPath);\n const pwdBuffer = Buffer.from(password, 'utf-8');\n return encrypt(key, pwdBuffer).toString('hex');\n}\n\n/**\n * Inverse of `encryptPwd`. Exposed for parity with the original CLI.\n */\nexport function decryptPwd(encryptedHex: string, materialPath: string): string {\n const key = getKey(materialPath);\n const encryptedBuffer = Buffer.from(encryptedHex, 'hex');\n return decrypt(key, encryptedBuffer).toString('utf-8');\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { execFileSync } from 'node:child_process';\nimport JSON5 from 'json5';\nimport { encryptPwd, createMaterial } from './encryptKey.js';\nimport { OPEN_HARMONY_APPLICATION_CERT } from './applicationCert.js';\nimport { detectProjectSdkVersion } from '../sdk/detectProjectSdk.js';\nimport type { Logger } from '../ports/logger.js';\nimport { noopLogger } from '../ports/logger.js';\nimport { OniroError } from '../ports/errors.js';\n\n/** Ability Privilege Level written into the profile's `bundle-info.apl`. */\nexport type Apl = 'normal' | 'system_basic' | 'system_core';\n\n/** App feature written into the profile's `bundle-info.app-feature`. */\nexport type AppFeature = 'hos_normal_app' | 'hos_system_app';\n\nexport const APL_VALUES: readonly Apl[] = ['normal', 'system_basic', 'system_core'];\nexport const APP_FEATURE_VALUES: readonly AppFeature[] = ['hos_normal_app', 'hos_system_app'];\n\n/**\n * Which signing key pairs with the chosen `apl`.\n *\n * - `'profile-release'` — the **OpenHarmony Application Profile Release** key.\n * Default for apl=normal. Matches the cert chain that ships with the SDK\n * (`OpenHarmonyProfileRelease.pem`). What `hvigor` uses for ordinary apps.\n *\n * - `'application-release'` — the **OpenHarmony Application Release** key.\n * Required for apl=system_basic|system_core. BMS's parse-profile-prop check\n * rejects HAPs whose `distribution-certificate` subject is \"Application\n * Profile Release\" when the HAP requests permissions above its apl. The\n * matching cert chain (`OpenHarmonyApplication.cer`) is not shipped in the\n * SDK, so we ship it ourselves under `applicationCert.ts`.\n */\nexport type SigningKind = 'profile-release' | 'application-release';\n\n/** @internal exposed for tests. */\nexport function pickSigningKind(apl: Apl): SigningKind {\n return apl === 'normal' ? 'profile-release' : 'application-release';\n}\n\ninterface SigningKindConfig {\n /** keystore alias used by hvigor's SignHap task. */\n hapKeyAlias: string;\n /** filename of the cert chain inside `signatures/` referenced by build-profile.json5 `certpath`. */\n certBasename: string;\n}\n\nconst SIGNING_KIND_CONFIG: Record<SigningKind, SigningKindConfig> = {\n 'profile-release': {\n hapKeyAlias: 'openharmony application profile release',\n certBasename: 'OpenHarmonyProfileRelease.pem',\n },\n 'application-release': {\n hapKeyAlias: 'OpenHarmony Application Release',\n certBasename: 'OpenHarmonyApplication.cer',\n },\n};\n\nexport interface GenerateSigningConfigsOptions {\n /** Absolute path to the OpenHarmony project (the folder containing build-profile.json5). */\n projectDir: string;\n /** Absolute path to the OS-specific SDK home (the folder containing API-version subfolders). */\n sdkHome: string;\n /**\n * APL level to write into the profile's `bundle-info.apl`. Defaults to `'normal'`.\n * Apps requesting permissions above `normal` (e.g. `ohos.permission.GET_WIFI_INFO_INTERNAL`)\n * need `system_basic` or `system_core` — otherwise `bm install` fails with\n * `grant request permissions failed`.\n */\n apl?: Apl;\n /**\n * App feature to write into `bundle-info.app-feature`. Defaults to `'hos_normal_app'`\n * when `apl='normal'`, otherwise `'hos_system_app'`.\n */\n appFeature?: AppFeature;\n /**\n * Permission names to write into the profile's `acls.allowed-acls`. Required for\n * apps that request permissions above their `apl` (e.g. a system_basic app\n * requesting `ohos.permission.CAPTURE_SCREEN`). When omitted, the template's\n * existing `allowed-acls` is left alone.\n */\n acls?: string[];\n /** Optional logger; defaults to no-op. */\n logger?: Logger;\n}\n\nfunction copyFilesToProject(\n projectDir: string,\n paths: { keystore: string; profileCert: string; unsignedProfileTemplate: string },\n kind: SigningKind,\n logger: Logger,\n): void {\n logger.info('[sign] Copying signing material into project...');\n const signaturesDir = path.join(projectDir, 'signatures');\n fs.mkdirSync(signaturesDir, { recursive: true });\n\n fs.copyFileSync(paths.keystore, path.join(signaturesDir, 'OpenHarmony.p12'));\n fs.copyFileSync(paths.profileCert, path.join(signaturesDir, 'OpenHarmonyProfileRelease.pem'));\n fs.copyFileSync(paths.unsignedProfileTemplate, path.join(signaturesDir, 'UnsgnedReleasedProfileTemplate.json'));\n\n if (kind === 'application-release') {\n fs.writeFileSync(\n path.join(signaturesDir, 'OpenHarmonyApplication.cer'),\n OPEN_HARMONY_APPLICATION_CERT,\n );\n }\n}\n\n/**\n * Pick the app-feature value: explicit override wins; otherwise `hos_normal_app` for\n * apl=normal, `hos_system_app` for system_basic/system_core.\n * @internal exposed for tests.\n */\nexport function resolveAppFeature(apl: Apl, override?: AppFeature): AppFeature {\n if (override) return override;\n return apl === 'normal' ? 'hos_normal_app' : 'hos_system_app';\n}\n\n/**\n * Read the third certificate (the leaf) from a 3-cert PEM chain. The chain is\n * stored root → intermediate → leaf, so the distribution-certificate we want\n * is the third block.\n */\nfunction extractLeafCertificate(chainPath: string): string {\n const certContent = fs.readFileSync(chainPath, 'utf-8');\n const parts = certContent.split('-----END CERTIFICATE-----');\n if (parts.length < 3) {\n throw new OniroError(`${chainPath} does not contain enough certificates.`);\n }\n return parts[2]!.trim() + '\\n-----END CERTIFICATE-----\\n';\n}\n\n/** @internal exposed for tests. */\nexport function modifyProfileTemplate(\n projectDir: string,\n apl: Apl,\n appFeature: AppFeature,\n logger: Logger,\n options: { kind?: SigningKind; acls?: string[] } = {},\n): void {\n const kind = options.kind ?? pickSigningKind(apl);\n logger.info(`[sign] Modifying profile template (apl=${apl}, app-feature=${appFeature}, kind=${kind})...`);\n const appJsonPath = path.join(projectDir, 'AppScope/app.json5');\n const profileTemplatePath = path.join(projectDir, 'signatures/UnsgnedReleasedProfileTemplate.json');\n\n if (!fs.existsSync(appJsonPath)) {\n throw new OniroError(`${appJsonPath} does not exist.`);\n }\n\n let appJson: { app?: { bundleName?: string } };\n try {\n appJson = JSON5.parse(fs.readFileSync(appJsonPath, 'utf-8'));\n } catch (e) {\n throw new OniroError(`Error parsing ${appJsonPath}: ${(e as Error).message}`, e);\n }\n\n let profileTemplate: {\n 'bundle-info'?: {\n 'bundle-name'?: string;\n 'distribution-certificate'?: string;\n apl?: string;\n 'app-feature'?: string;\n };\n acls?: { 'allowed-acls'?: string[] };\n };\n try {\n profileTemplate = JSON.parse(fs.readFileSync(profileTemplatePath, 'utf-8'));\n } catch (e) {\n throw new OniroError(`Error parsing ${profileTemplatePath}: ${(e as Error).message}`, e);\n }\n\n if (!appJson.app?.bundleName) {\n throw new OniroError('app.json5 does not contain app.bundleName.');\n }\n if (!profileTemplate['bundle-info']) {\n throw new OniroError('UnsgnedReleasedProfileTemplate.json is missing the bundle-info section.');\n }\n\n profileTemplate['bundle-info']['bundle-name'] = appJson.app.bundleName;\n profileTemplate['bundle-info']['apl'] = apl;\n profileTemplate['bundle-info']['app-feature'] = appFeature;\n\n const distCertChainPath = path.join(\n projectDir,\n 'signatures',\n SIGNING_KIND_CONFIG[kind].certBasename,\n );\n profileTemplate['bundle-info']['distribution-certificate'] = extractLeafCertificate(distCertChainPath);\n\n if (options.acls !== undefined) {\n profileTemplate.acls = profileTemplate.acls ?? {};\n profileTemplate.acls['allowed-acls'] = options.acls;\n }\n\n fs.writeFileSync(profileTemplatePath, JSON.stringify(profileTemplate, null, 2));\n}\n\nfunction generateP7bFile(\n projectDir: string,\n paths: { signTool: string; profileCert: string; keystore: string },\n logger: Logger,\n): void {\n logger.info('[sign] Generating P7b profile via hap-sign-tool...');\n const signaturesDir = path.join(projectDir, 'signatures');\n const profileTemplatePath = path.join(signaturesDir, 'UnsgnedReleasedProfileTemplate.json');\n const outputProfilePath = path.join(signaturesDir, 'app1-profile.p7b');\n\n // The profile itself is always signed by the Profile Release key, regardless\n // of the HAP signing kind. The profile's `distribution-certificate` field\n // (set by modifyProfileTemplate) is what tells BMS which cert will sign the HAP.\n const args = [\n '-jar', paths.signTool,\n 'sign-profile',\n '-keyAlias', 'openharmony application profile release',\n '-signAlg', 'SHA256withECDSA',\n '-mode', 'localSign',\n '-profileCertFile', paths.profileCert,\n '-inFile', profileTemplatePath,\n '-keystoreFile', paths.keystore,\n '-outFile', outputProfilePath,\n '-keyPwd', '123456',\n '-keystorePwd', '123456',\n ];\n\n try {\n execFileSync('java', args, { stdio: 'inherit' });\n } catch (e) {\n throw new OniroError(\n `hap-sign-tool failed. Ensure a JDK (with keytool/java) is on PATH. Underlying error: ${(e as Error).message}`,\n e,\n );\n }\n}\n\n/**\n * Read all `products[*].signingConfig` names from the project's build-profile.json5.\n * Returns the unique names in declaration order. Falls back to `['default']` when\n * the file is missing or has no products.\n * @internal exposed for tests.\n */\nexport function detectSigningConfigNames(projectDir: string): string[] {\n const buildProfilePath = path.join(projectDir, 'build-profile.json5');\n if (!fs.existsSync(buildProfilePath)) return ['default'];\n\n let parsed: { app?: { products?: Array<{ signingConfig?: unknown }> } };\n try {\n parsed = JSON5.parse(fs.readFileSync(buildProfilePath, 'utf-8'));\n } catch {\n return ['default'];\n }\n\n const products = parsed.app?.products;\n if (!Array.isArray(products) || products.length === 0) return ['default'];\n\n const names: string[] = [];\n for (const product of products) {\n const name = product.signingConfig;\n if (typeof name === 'string' && name.length > 0 && !names.includes(name)) {\n names.push(name);\n }\n }\n return names.length > 0 ? names : ['default'];\n}\n\nfunction updateBuildProfile(projectDir: string, kind: SigningKind, logger: Logger): void {\n logger.info('[sign] Writing signing configs into build-profile.json5...');\n const materialDir = path.join(projectDir, 'signatures', 'material');\n const buildProfilePath = path.join(projectDir, 'build-profile.json5');\n\n const encryptedStorePassword = encryptPwd('123456', materialDir);\n const encryptedKeyPassword = encryptPwd('123456', materialDir);\n\n let buildProfile: { app?: { signingConfigs?: unknown[] } } = { app: {} };\n if (fs.existsSync(buildProfilePath)) {\n try {\n buildProfile = JSON5.parse(fs.readFileSync(buildProfilePath, 'utf-8'));\n } catch (e) {\n throw new OniroError(`Error parsing ${buildProfilePath}: ${(e as Error).message}`, e);\n }\n }\n\n const { hapKeyAlias, certBasename } = SIGNING_KIND_CONFIG[kind];\n const configNames = detectSigningConfigNames(projectDir);\n logger.info(`[sign] Writing signingConfigs entries: ${configNames.join(', ')}`);\n\n buildProfile.app = buildProfile.app ?? {};\n buildProfile.app.signingConfigs = configNames.map((name) => ({\n name,\n material: {\n certpath: `./signatures/${certBasename}`,\n storePassword: encryptedStorePassword,\n keyAlias: hapKeyAlias,\n keyPassword: encryptedKeyPassword,\n profile: './signatures/app1-profile.p7b',\n signAlg: 'SHA256withECDSA',\n storeFile: './signatures/OpenHarmony.p12',\n },\n }));\n\n // Intentionally strict JSON (not JSON5) — keeps the file readable by VS Code's JSON parser.\n fs.writeFileSync(buildProfilePath, JSON.stringify(buildProfile, null, 2));\n}\n\nfunction prepareMaterialDirectory(projectDir: string, logger: Logger): void {\n logger.info('[sign] Generating fresh signing material...');\n const materialDir = path.join(projectDir, 'signatures', 'material');\n if (fs.existsSync(materialDir)) {\n fs.rmSync(materialDir, { recursive: true, force: true });\n }\n createMaterial(materialDir);\n}\n\n/**\n * Generate signing configs for an OpenHarmony project: copies certs, signs the profile,\n * generates the signing material, and writes the resulting `signingConfigs` entry into\n * `build-profile.json5`.\n *\n * Requires `java` on PATH (the OpenHarmony hap-sign-tool ships as a .jar).\n */\nexport function generateSigningConfigs(options: GenerateSigningConfigsOptions): void {\n const { projectDir, sdkHome } = options;\n const logger = options.logger ?? noopLogger;\n const apl: Apl = options.apl ?? 'normal';\n if (!APL_VALUES.includes(apl)) {\n throw new OniroError(`Invalid apl '${apl}'. Expected one of: ${APL_VALUES.join(', ')}.`);\n }\n const appFeature: AppFeature = resolveAppFeature(apl, options.appFeature);\n if (!APP_FEATURE_VALUES.includes(appFeature)) {\n throw new OniroError(\n `Invalid appFeature '${appFeature}'. Expected one of: ${APP_FEATURE_VALUES.join(', ')}.`,\n );\n }\n\n const sdkVersion = detectProjectSdkVersion(projectDir, logger);\n if (!sdkVersion) {\n throw new OniroError(\n 'Could not detect project SDK version (compileSdkVersion missing in build-profile.json5).',\n );\n }\n\n const sdkPath = path.join(sdkHome, String(sdkVersion));\n if (!fs.existsSync(sdkPath)) {\n throw new OniroError(`SDK path does not exist: ${sdkPath}`);\n }\n\n const paths = {\n signTool: path.join(sdkPath, 'toolchains/lib/hap-sign-tool.jar'),\n keystore: path.join(sdkPath, 'toolchains/lib/OpenHarmony.p12'),\n profileCert: path.join(sdkPath, 'toolchains/lib/OpenHarmonyProfileRelease.pem'),\n unsignedProfileTemplate: path.join(sdkPath, 'toolchains/lib/UnsgnedReleasedProfileTemplate.json'),\n };\n\n const kind = pickSigningKind(apl);\n\n logger.info('[sign] Starting signing configuration generation...');\n copyFilesToProject(projectDir, paths, kind, logger);\n modifyProfileTemplate(projectDir, apl, appFeature, logger, { kind, acls: options.acls });\n generateP7bFile(projectDir, paths, logger);\n prepareMaterialDirectory(projectDir, logger);\n updateBuildProfile(projectDir, kind, logger);\n logger.info('[sign] Signing configuration generated successfully.');\n}\n","/**\n * PEM-encoded certificate chain for the OpenHarmony Application Release key.\n *\n * Root-CA → Application-CA → Application-Release leaf. This is the public\n * OpenHarmony test PKI that ships with system app source trees (e.g.\n * `applications/standard/launcher/signature/OpenHarmonyApplication.cer`). It\n * pairs with the private key stored under alias `OpenHarmony Application Release`\n * in the SDK's `OpenHarmony.p12` keystore.\n *\n * Used to sign HAPs that request privileged permissions (apl >= system_basic).\n * For apl=normal the existing `OpenHarmonyProfileRelease.pem` chain — already\n * shipped in the SDK — is used instead.\n */\nexport const OPEN_HARMONY_APPLICATION_CERT = `-----BEGIN CERTIFICATE-----\nMIICRDCCAcmgAwIBAgIED+E4izAMBggqhkjOPQQDAwUAMGgxCzAJBgNVBAYTAkNO\nMRQwEgYDVQQKEwtPcGVuSGFybW9ueTEZMBcGA1UECxMQT3Blbkhhcm1vbnkgVGVh\nbTEoMCYGA1UEAxMfT3Blbkhhcm1vbnkgQXBwbGljYXRpb24gUm9vdCBDQTAeFw0y\nMTAyMDIxMjE0MThaFw00OTEyMzExMjE0MThaMGgxCzAJBgNVBAYTAkNOMRQwEgYD\nVQQKEwtPcGVuSGFybW9ueTEZMBcGA1UECxMQT3Blbkhhcm1vbnkgVGVhbTEoMCYG\nA1UEAxMfT3Blbkhhcm1vbnkgQXBwbGljYXRpb24gUm9vdCBDQTB2MBAGByqGSM49\nAgEGBSuBBAAiA2IABE023XmRaw2DnO8NSsb+KG/uY0FtS3u5LQucdr3qWVnRW5ui\nQIL6ttNZBEeLTUeYcJZCpayg9Llf+1SmDA7dY4iP2EcRo4UN3rilovtfFfsmH4ty\n3SApHVFzWUl+NwdH8KNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC\nAQYwHQYDVR0OBBYEFBc6EKGrGXzlAE+s0Zgnsphadw7NMAwGCCqGSM49BAMDBQAD\nZwAwZAIwd1p3JzHN93eoPped1li0j64npgqNzwy4OrkehYAqNXpcpaEcLZ7UxW8E\nI2lZJ3SbAjAkqySHb12sIwdSFKSN9KCMMEo/eUT5dUXlcKR2nZz0MJdxT5F51qcX\n1CumzkcYhgU=\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICYTCCAeWgAwIBAgIEHmXAPTAMBggqhkjOPQQDAwUAMGgxCzAJBgNVBAYTAkNO\nMRQwEgYDVQQKEwtPcGVuSGFybW9ueTEZMBcGA1UECxMQT3Blbkhhcm1vbnkgVGVh\nbTEoMCYGA1UEAxMfT3Blbkhhcm1vbnkgQXBwbGljYXRpb24gUm9vdCBDQTAeFw0y\nMTAyMDIxMjE1MzJaFw00OTEyMzExMjE1MzJaMGMxCzAJBgNVBAYTAkNOMRQwEgYD\nVQQKEwtPcGVuSGFybW9ueTEZMBcGA1UECxMQT3Blbkhhcm1vbnkgVGVhbTEjMCEG\nA1UEAxMaT3Blbkhhcm1vbnkgQXBwbGljYXRpb24gQ0EwdjAQBgcqhkjOPQIBBgUr\ngQQAIgNiAAQhnu7Hna8XNa2KyqRf5+lBJScE4xqf89N0g0OuqAb2re8nGsvWkw26\nuDekfnBYicd+G3Cydqa2zFIwV7Talyg2ULW3r8KbGpyl84mJEPPRmCGJ+H9gtCsf\n+OrJ4Y76LVWjYzBhMB8GA1UdIwQYMBaAFBc6EKGrGXzlAE+s0Zgnsphadw7NMA8G\nA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTbhrciFtUL\noUu33SV7ufEFfaItRzAMBggqhkjOPQQDAwUAA2gAMGUCMG3cXjiDmXTvf7D4Omhf\nqcc2nuO+EMfWE+N9ZhBP5UhV34mAGWi3SfLU6rcV0urWEQIxAMYIb3epOnKhUrcm\nLfu1WKzFlpYQwmw73RaCHP2I3k6NcuWOYeNwWXSNZ8o0nzvaLg==\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICMzCCAbegAwIBAgIEaOC/zDAMBggqhkjOPQQDAwUAMGMxCzAJBgNVBAYTAkNO\nMRQwEgYDVQQKEwtPcGVuSGFybW9ueTEZMBcGA1UECxMQT3Blbkhhcm1vbnkgVGVh\nbTEjMCEGA1UEAxMaT3Blbkhhcm1vbnkgQXBwbGljYXRpb24gQ0EwHhcNMjEwMjAy\nMTIxOTMxWhcNNDkxMjMxMTIxOTMxWjBoMQswCQYDVQQGEwJDTjEUMBIGA1UEChML\nT3Blbkhhcm1vbnkxGTAXBgNVBAsTEE9wZW5IYXJtb255IFRlYW0xKDAmBgNVBAMT\nH09wZW5IYXJtb255IEFwcGxpY2F0aW9uIFJlbGVhc2UwWTATBgcqhkjOPQIBBggq\nhkjOPQMBBwNCAATbYOCQQpW5fdkYHN45v0X3AHax12jPBdEDosFRIZ1eXmxOYzSG\nJwMfsHhUU90E8lI0TXYZnNmgM1sovubeQqATo1IwUDAfBgNVHSMEGDAWgBTbhrci\nFtULoUu33SV7ufEFfaItRzAOBgNVHQ8BAf8EBAMCB4AwHQYDVR0OBBYEFPtxruhl\ncRBQsJdwcZqLu9oNUVgaMAwGCCqGSM49BAMDBQADaAAwZQIxAJta0PQ2p4DIu/ps\nLMdLCDgQ5UH1l0B4PGhBlMgdi2zf8nk9spazEQI/0XNwpft8QAIwHSuA2WelVi/o\nzAlF08DnbJrOOtOnQq5wHOPlDYB4OtUzOYJk9scotrEnJxJzGsh/\n-----END CERTIFICATE-----\n`;\n","import * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport type { ConfigProvider } from '../ports/config.js';\nimport { defaultPaths } from '../ports/config.js';\nimport type { ProgressReporter } from '../ports/progress.js';\nimport type { Logger } from '../ports/logger.js';\nimport { noopLogger } from '../ports/logger.js';\nimport { getEmulatorDir } from '../sdk/paths.js';\nimport { downloadFile } from '../sdk/download.js';\nimport { extractZipWithProgress } from '../sdk/extract.js';\n\nexport interface InstallEmulatorOptions {\n config: ConfigProvider;\n progress?: ProgressReporter;\n abortSignal?: AbortSignal;\n logger?: Logger;\n}\n\n/**\n * Download and extract the Oniro emulator into the configured `emulatorDir`.\n */\nexport async function installEmulator(opts: InstallEmulatorOptions): Promise<void> {\n const { config, progress, abortSignal } = opts;\n const logger = opts.logger ?? noopLogger;\n\n const url = config.get('emulatorUrl', defaultPaths.emulatorUrl);\n const emulatorDir = getEmulatorDir(config);\n const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'oniro-emulator-'));\n const tmpZip = path.join(tmpDir, 'oniro_emulator.zip');\n\n try {\n fs.mkdirSync(emulatorDir, { recursive: true });\n\n progress?.report({ message: 'Downloading emulator...', increment: 0 });\n await downloadFile({ url, dest: tmpZip, progress, abortSignal, start: 0, range: 50 });\n\n progress?.report({ message: 'Extracting emulator...', increment: 0 });\n await extractZipWithProgress({ zipPath: tmpZip, dest: emulatorDir, progress, start: 50, range: 45, logger });\n\n const runSh = path.join(emulatorDir, 'images', 'run.sh');\n if (fs.existsSync(runSh)) {\n fs.chmodSync(runSh, 0o755);\n }\n progress?.report({ message: 'Finalizing installation...', increment: 5 });\n } finally {\n fs.rmSync(tmpDir, { recursive: true, force: true });\n }\n}\n\n/**\n * Heuristic: emulator is considered installed if `images/run.sh` is present.\n * On Windows-only emulator builds (when they exist) this may not apply.\n */\nexport function isEmulatorInstalled(config: ConfigProvider): boolean {\n return fs.existsSync(path.join(getEmulatorDir(config), 'images', 'run.sh'));\n}\n\nexport function removeEmulator(config: ConfigProvider): void {\n const emulatorDir = getEmulatorDir(config);\n if (fs.existsSync(emulatorDir)) {\n fs.rmSync(emulatorDir, { recursive: true, force: true });\n }\n}\n","import * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport { exec, spawn } from 'node:child_process';\nimport type { ConfigProvider } from '../ports/config.js';\nimport type { Logger } from '../ports/logger.js';\nimport { noopLogger } from '../ports/logger.js';\nimport { CancelledError, OniroError } from '../ports/errors.js';\nimport { getEmulatorDir, getHdcPath } from '../sdk/paths.js';\n\nconst PID_FILE = path.join(os.tmpdir(), 'oniro_emulator.pid');\n\nfunction execPromise(cmd: string, cwd: string | undefined, logger: Logger): Promise<void> {\n return new Promise((resolve, reject) => {\n exec(cmd, { cwd }, (error, stdout, stderr) => {\n if (stdout?.trim()) logger.info(`[emulator] ${stdout.trim()}`);\n if (stderr?.trim()) logger.warn(`[emulator] ${stderr.trim()}`);\n if (error) {\n logger.error(`[emulator] ${error.message}`);\n reject(error);\n } else {\n resolve();\n }\n });\n });\n}\n\n/**\n * Try to connect hdc to the emulator. Resolves true on success, false otherwise.\n */\nexport async function attemptHdcConnection(\n config: ConfigProvider,\n address = '127.0.0.1:55555',\n logger: Logger = noopLogger,\n): Promise<boolean> {\n const hdc = getHdcPath(config);\n try {\n await execPromise(`\"${hdc}\" start -r`, undefined, logger);\n await execPromise(`\"${hdc}\" tconn ${address}`, undefined, logger);\n return await new Promise<boolean>((resolve) => {\n exec(`\"${hdc}\" list targets`, (_error, stdout) => {\n resolve(stdout?.includes(address) ?? false);\n });\n });\n } catch (err) {\n logger.warn(`hdc connection attempt failed: ${(err as Error).message}`);\n return false;\n }\n}\n\ninterface LauncherSpec {\n /** Executable to spawn (e.g. `bash` on POSIX, `cmd.exe` on Windows). */\n command: string;\n /** Args, including the launcher script path. */\n args: readonly string[];\n /** Working directory (images dir). */\n cwd: string;\n}\n\n/**\n * Pick the right bundled launcher for the current OS. Prefers run.bat on Windows\n * and run.sh elsewhere; falls back to the other if only one is present.\n */\nfunction resolveLauncher(\n imagesPath: string,\n headless: boolean,\n connect: string | undefined,\n): LauncherSpec {\n const runSh = path.join(imagesPath, 'run.sh');\n const runBat = path.join(imagesPath, 'run.bat');\n const extra: string[] = [];\n if (headless) extra.push('--headless');\n if (connect) extra.push('--connect', connect);\n\n if (os.platform() === 'win32') {\n if (fs.existsSync(runBat)) {\n return { command: 'cmd.exe', args: ['/c', runBat, ...extra], cwd: imagesPath };\n }\n if (fs.existsSync(runSh)) {\n return { command: 'bash', args: [runSh, ...extra], cwd: imagesPath };\n }\n throw new OniroError(`No emulator launcher (run.bat or run.sh) found in ${imagesPath}.`);\n }\n\n if (fs.existsSync(runSh)) {\n return { command: 'bash', args: [runSh, ...extra], cwd: imagesPath };\n }\n if (fs.existsSync(runBat)) {\n return { command: 'bash', args: [runBat, ...extra], cwd: imagesPath };\n }\n throw new OniroError(`No emulator launcher (run.sh or run.bat) found in ${imagesPath}.`);\n}\n\nexport interface StartEmulatorOptions {\n config: ConfigProvider;\n logger?: Logger;\n /** Pass --headless to the bundled launcher (VNC + telnet serial, no local window). */\n headless?: boolean;\n /**\n * Override the launcher's host:port for hdc port forwarding. Defaults to the\n * launcher's own default (typically `127.0.0.1:55555`). Use `0.0.0.0:55555`\n * on hosts where QEMU refuses to bind the hostfwd to 127.0.0.1 (e.g. some\n * CI runners with restricted loopback bindings).\n */\n connect?: string;\n /**\n * Redirect launcher stdout/stderr to this file. Default: discard\n * (/dev/null on POSIX, NUL on Windows). Use a real path in CI so you can\n * surface qemu output on failure.\n */\n logFile?: string;\n /**\n * If > 0, block until hdc connects to the running emulator, up to this many\n * seconds. 0 (default) returns as soon as the launcher process is spawned.\n */\n waitForHdcSeconds?: number;\n /** Poll interval for the hdc wait, ms. Default 5000. */\n hdcPollIntervalMs?: number;\n abortSignal?: AbortSignal;\n}\n\n/**\n * Launch the Oniro emulator in the background via the bundled run.sh/run.bat.\n *\n * The launcher process is detached + unref'd so callers can exit while the\n * emulator keeps running. A PID file is written to the OS temp dir so\n * `stopEmulator` and rerun-detection logic can find the process later.\n */\nexport async function startEmulator(opts: StartEmulatorOptions): Promise<void> {\n const { config } = opts;\n const logger = opts.logger ?? noopLogger;\n\n // Detect a still-running emulator from a previous run (POSIX only — Windows\n // PID semantics with process groups make this unreliable to check by hand).\n if (os.platform() !== 'win32' && fs.existsSync(PID_FILE)) {\n try {\n const pid = Number(fs.readFileSync(PID_FILE, 'utf8').trim());\n if (Number.isFinite(pid) && pid > 0) {\n try {\n process.kill(pid, 0);\n logger.info(`Emulator already running (PID ${pid}); not starting another.`);\n if (opts.waitForHdcSeconds && opts.waitForHdcSeconds > 0) {\n await waitForHdc(config, opts.waitForHdcSeconds, opts.hdcPollIntervalMs ?? 5000, logger, opts.abortSignal);\n }\n return;\n } catch {\n // Stale PID file — fall through and launch a fresh one.\n }\n }\n } catch (err) {\n logger.warn(`Could not read PID file: ${(err as Error).message}`);\n }\n }\n\n const imagesPath = path.join(getEmulatorDir(config), 'images');\n if (!fs.existsSync(imagesPath)) {\n throw new OniroError(`Emulator images directory not found at ${imagesPath}. Run \\`oniro-app emulator install\\` first.`);\n }\n const launcher = resolveLauncher(imagesPath, opts.headless === true, opts.connect);\n\n // Open the log target. Default to OS-level null sink so the child process\n // doesn't keep the parent's stdout/stderr file descriptors alive.\n const logPath = opts.logFile ?? (os.platform() === 'win32' ? 'NUL' : '/dev/null');\n const logFd = fs.openSync(logPath, 'a');\n\n let child;\n try {\n child = spawn(launcher.command, [...launcher.args], {\n cwd: launcher.cwd,\n detached: true,\n stdio: ['ignore', logFd, logFd],\n windowsHide: true,\n });\n } finally {\n fs.closeSync(logFd);\n }\n\n // Catch synchronous spawn failures (e.g. bash not found on PATH).\n if (!child.pid) {\n throw new OniroError(`Failed to spawn launcher (${launcher.command} ${launcher.args.join(' ')}).`);\n }\n\n // Record PID + detach. The launcher script `exec`s into qemu so this PID\n // remains valid for the whole emulator lifetime.\n fs.writeFileSync(PID_FILE, String(child.pid));\n child.unref();\n logger.info(`Emulator launched (PID ${child.pid}). Logs: ${logPath}`);\n\n // Watch for an immediate failure (e.g. KVM unavailable → run.sh exits ~instantly\n // with a friendly error). We hold a reference to the exit event but won't await\n // it if the child stays alive.\n const earlyExit = new Promise<number | null>((resolve) => {\n child.once('exit', (code) => resolve(code));\n child.once('error', () => resolve(-1));\n });\n const liveness = new Promise<'alive'>((resolve) => setTimeout(() => resolve('alive'), 2000));\n const outcome = await Promise.race([earlyExit, liveness]);\n if (outcome !== 'alive') {\n const tail = readTail(logPath, 4000);\n throw new OniroError(\n `Emulator launcher exited with code ${outcome} before reaching steady state. Tail of ${logPath}:\\n${tail}`,\n );\n }\n\n if (opts.waitForHdcSeconds && opts.waitForHdcSeconds > 0) {\n await waitForHdc(config, opts.waitForHdcSeconds, opts.hdcPollIntervalMs ?? 5000, logger, opts.abortSignal, logPath);\n }\n}\n\nasync function waitForHdc(\n config: ConfigProvider,\n timeoutSeconds: number,\n pollIntervalMs: number,\n logger: Logger,\n abortSignal?: AbortSignal,\n logPathForDiagnostics?: string,\n): Promise<void> {\n const deadline = Date.now() + timeoutSeconds * 1000;\n let attempt = 0;\n while (Date.now() < deadline) {\n if (abortSignal?.aborted) throw new CancelledError('hdc wait cancelled.');\n attempt++;\n if (await attemptHdcConnection(config, undefined, noopLogger)) {\n logger.info(`hdc connected on attempt ${attempt}.`);\n return;\n }\n // Every ~6 attempts, log a heartbeat with the latest emulator log tail so\n // a hung guest is debuggable from a single command's output stream.\n if (attempt % 6 === 0) {\n logger.info(`hdc not yet ready (attempt ${attempt}, ${Math.max(0, deadline - Date.now()) / 1000 | 0}s remaining).`);\n if (logPathForDiagnostics) {\n const tail = readTail(logPathForDiagnostics, 1200);\n if (tail.trim()) logger.debug(`emulator log tail:\\n${tail}`);\n }\n }\n await new Promise((r) => setTimeout(r, pollIntervalMs));\n }\n const tail = logPathForDiagnostics ? readTail(logPathForDiagnostics, 4000) : '';\n throw new OniroError(`hdc did not connect within ${timeoutSeconds}s.${tail ? `\\nTail of emulator log:\\n${tail}` : ''}`);\n}\n\nfunction readTail(filePath: string, bytes: number): string {\n try {\n const stat = fs.statSync(filePath);\n const start = Math.max(0, stat.size - bytes);\n const fd = fs.openSync(filePath, 'r');\n try {\n const buf = Buffer.alloc(stat.size - start);\n fs.readSync(fd, buf, 0, buf.length, start);\n return buf.toString('utf8');\n } finally {\n fs.closeSync(fd);\n }\n } catch {\n return '';\n }\n}\n\nexport async function stopEmulator(logger: Logger = noopLogger): Promise<void> {\n // Prefer killing the recorded PID; fall back to a broad kill for stragglers.\n if (fs.existsSync(PID_FILE)) {\n try {\n const pid = Number(fs.readFileSync(PID_FILE, 'utf8').trim());\n if (Number.isFinite(pid) && pid > 0) {\n try {\n process.kill(pid, 'SIGTERM');\n logger.info(`Sent SIGTERM to emulator PID ${pid}.`);\n } catch (err) {\n logger.warn(`Could not signal PID ${pid}: ${(err as Error).message}`);\n }\n }\n } catch (err) {\n logger.warn(`Could not read PID file: ${(err as Error).message}`);\n }\n }\n\n const killCmd = os.platform() === 'win32'\n ? 'taskkill /IM qemu-system-x86_64.exe /F'\n : 'pkill -f qemu-system-x86_64';\n try {\n await execPromise(killCmd, undefined, logger);\n } catch {\n // pkill / taskkill return non-zero when nothing matched — that's fine.\n }\n\n fs.rm(PID_FILE, { force: true }, (err) => {\n if (err) logger.warn(`Could not remove PID file: ${err.message}`);\n });\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport JSON5 from 'json5';\nimport { OniroError } from '../ports/errors.js';\n\nfunction readJson5<T>(filePath: string): T {\n const content = fs.readFileSync(filePath, 'utf-8');\n return JSON5.parse(content) as T;\n}\n\n/**\n * Read the project's bundle name from `AppScope/app.json5`.\n */\nexport function getBundleName(projectDir: string): string {\n const appJsonPath = path.join(projectDir, 'AppScope', 'app.json5');\n if (!fs.existsSync(appJsonPath)) {\n throw new OniroError(`Could not find app.json5 at ${appJsonPath}`);\n }\n const appJson = readJson5<{ app?: { bundleName?: string } }>(appJsonPath);\n if (!appJson.app?.bundleName) {\n throw new OniroError('bundleName not found in app.json5');\n }\n return appJson.app.bundleName;\n}\n\n/**\n * Read the main ability from `<module>/src/main/module.json5`. Defaults to `entry`\n * for the module folder name if not provided — projects with custom module names\n * should pass it explicitly.\n */\nexport function getMainAbility(projectDir: string, moduleName = 'entry'): string {\n const moduleJsonPath = path.join(projectDir, moduleName, 'src', 'main', 'module.json5');\n if (!fs.existsSync(moduleJsonPath)) {\n throw new OniroError(`Could not find module.json5 at ${moduleJsonPath}`);\n }\n const moduleJson = readJson5<{ module?: { mainElement?: string } }>(moduleJsonPath);\n if (!moduleJson.module?.mainElement) {\n throw new OniroError('mainElement not found in module.json5');\n }\n return moduleJson.module.mainElement;\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { exec, spawn } from 'node:child_process';\nimport type { ConfigProvider } from '../ports/config.js';\nimport { defaultPaths } from '../ports/config.js';\nimport type { Logger } from '../ports/logger.js';\nimport { noopLogger } from '../ports/logger.js';\nimport { OniroError } from '../ports/errors.js';\nimport { getHdcPath } from '../sdk/paths.js';\nimport { getBundleName, getMainAbility } from './project.js';\n\nfunction execPromise(cmd: string, logger: Logger): Promise<void> {\n return new Promise((resolve, reject) => {\n exec(cmd, (error, stdout, stderr) => {\n if (stdout?.trim()) logger.info(`[hdc] ${stdout.trim()}`);\n if (stderr?.trim()) logger.warn(`[hdc] ${stderr.trim()}`);\n if (error) {\n logger.error(`[hdc] ${error.message}`);\n reject(error);\n } else {\n resolve();\n }\n });\n });\n}\n\nexport interface InstallAppOptions {\n config: ConfigProvider;\n projectDir: string;\n /**\n * Explicit path (absolute, or relative to projectDir) to the signed `.hap`.\n * Falls back to the `hapPath` config key, then to the well-known default.\n */\n hapPath?: string;\n logger?: Logger;\n}\n\nexport async function installApp(opts: InstallAppOptions): Promise<void> {\n const logger = opts.logger ?? noopLogger;\n const relativeHapPath = opts.hapPath ?? opts.config.get('hapPath', defaultPaths.hapPath);\n const hapPath = path.isAbsolute(relativeHapPath) ? relativeHapPath : path.join(opts.projectDir, relativeHapPath);\n\n if (!fs.existsSync(hapPath)) {\n throw new OniroError(`HAP file not found at: ${hapPath}. Build and sign the app first.`);\n }\n\n const hdc = getHdcPath(opts.config);\n await execPromise(`\"${hdc}\" install \"${hapPath}\"`, logger);\n}\n\nexport interface LaunchAppOptions {\n config: ConfigProvider;\n projectDir: string;\n /** Override the module name if it isn't the default `entry`. */\n moduleName?: string;\n logger?: Logger;\n}\n\nexport async function launchApp(opts: LaunchAppOptions): Promise<void> {\n const logger = opts.logger ?? noopLogger;\n const bundleName = getBundleName(opts.projectDir);\n const mainAbility = getMainAbility(opts.projectDir, opts.moduleName);\n const hdc = getHdcPath(opts.config);\n await execPromise(`\"${hdc}\" shell aa start -a ${mainAbility} -b ${bundleName}`, logger);\n}\n\nexport interface RunningProcess {\n pid: string;\n name: string;\n}\n\n/**\n * List running processes via `hdc track-jpid`. Times out after `timeoutMs`.\n * When `targetProcessName` is set, resolves to that process's PID early; otherwise\n * resolves to the full list collected within the timeout window.\n */\nexport function listRunningProcesses(\n config: ConfigProvider,\n options: { targetProcessName?: string; timeoutMs?: number; logger?: Logger } = {},\n): Promise<RunningProcess[] | string> {\n const logger = options.logger ?? noopLogger;\n const timeoutMs = options.timeoutMs ?? 1000;\n const hdc = getHdcPath(config);\n\n return new Promise((resolve, reject) => {\n const proc = spawn(hdc, ['track-jpid']);\n const processes: RunningProcess[] = [];\n let resolved = false;\n\n proc.stdout.on('data', (data: Buffer) => {\n for (const line of data.toString().split('\\n').filter(Boolean)) {\n const match = line.match(/^(\\d+)\\s+(.+)$/);\n if (!match) continue;\n const pid = match[1]!;\n const name = match[2]!;\n processes.push({ pid, name });\n if (options.targetProcessName && name === options.targetProcessName && !resolved) {\n resolved = true;\n proc.kill();\n resolve(pid);\n return;\n }\n }\n });\n\n proc.stderr.on('data', (data: Buffer) => {\n logger.warn(`[hdc track-jpid] ${data.toString()}`);\n });\n\n proc.on('error', (err) => {\n if (!resolved) {\n resolved = true;\n reject(err);\n }\n });\n\n const timeout = setTimeout(() => {\n if (resolved) return;\n resolved = true;\n proc.kill();\n if (options.targetProcessName) {\n reject(new OniroError(`Could not find process for bundle: ${options.targetProcessName}`));\n } else {\n resolve(processes);\n }\n }, timeoutMs);\n\n proc.on('close', () => {\n clearTimeout(timeout);\n if (resolved) return;\n resolved = true;\n if (options.targetProcessName) {\n reject(new OniroError(`Could not find process for bundle: ${options.targetProcessName}`));\n } else {\n resolve(processes);\n }\n });\n });\n}\n\nexport async function findAppProcessId(config: ConfigProvider, projectDir: string, logger?: Logger): Promise<string> {\n const bundleName = getBundleName(projectDir);\n const result = await listRunningProcesses(config, { targetProcessName: bundleName, logger });\n return result as string;\n}\n","import { spawn, type ChildProcessWithoutNullStreams } from 'node:child_process';\nimport type { ConfigProvider } from '../ports/config.js';\nimport type { Logger } from '../ports/logger.js';\nimport { noopLogger } from '../ports/logger.js';\nimport { getHdcPath } from '../sdk/paths.js';\n\nexport type HilogLevel = 'DEBUG' | 'INFO' | 'WARN' | 'ERROR' | 'FATAL';\n\n/** A parsed line of `hdc shell hilog` output. */\nexport interface HilogEntry {\n /** \"MM-DD HH:MM:SS.mmm\". The device timestamp; no year. */\n time: string;\n pid: string;\n tid: string;\n /** Short level letter as printed by hilog: D, I, W, E (F is rare). */\n level: 'D' | 'I' | 'W' | 'E' | 'F';\n tag: string;\n message: string;\n}\n\nexport interface SetHilogLevelOptions {\n config: ConfigProvider;\n level: HilogLevel;\n logger?: Logger;\n}\n\n/**\n * Set the hilog buffer level on the connected device. Resolves when the\n * underlying `hdc shell hilog -b <LEVEL>` exits successfully; rejects with\n * the stderr text if the command fails.\n */\nexport function setHilogLevel(opts: SetHilogLevelOptions): Promise<void> {\n const logger = opts.logger ?? noopLogger;\n const hdc = getHdcPath(opts.config);\n return new Promise((resolve, reject) => {\n const child = spawn(hdc, ['shell', 'hilog', '-b', opts.level]);\n let stderr = '';\n child.stderr.on('data', (chunk: Buffer) => {\n stderr += chunk.toString();\n });\n child.once('error', (err) => {\n logger.error(`[hilog] failed to spawn hdc: ${err.message}`);\n reject(err);\n });\n child.once('close', (code) => {\n if (code === 0) {\n resolve();\n } else {\n const msg = stderr.trim() || `hdc shell hilog -b ${opts.level} exited with code ${code}`;\n logger.error(`[hilog] ${msg}`);\n reject(new Error(msg));\n }\n });\n });\n}\n\nexport interface StreamHilogOptions {\n config: ConfigProvider;\n /** Restrict the stream to a single process id (passed as `-P <pid>`). */\n processId?: string;\n}\n\n/**\n * Spawn `hdc shell hilog [-P <pid>]` and return the child process. The caller\n * owns the stdout/stderr streams (typically wired through `parseHilogLine`) and\n * is responsible for killing the process when streaming should stop.\n */\nexport function streamHilog(opts: StreamHilogOptions): ChildProcessWithoutNullStreams {\n const hdc = getHdcPath(opts.config);\n const args = ['shell', 'hilog'];\n if (opts.processId && opts.processId.trim() !== '') {\n args.push('-P', opts.processId.trim());\n }\n return spawn(hdc, args);\n}\n\n// `\\S+` is greedy on the tag so values like `C01406/OHOS::RS` aren't split at\n// the first internal colon — the regex backtracks to the last `:` followed by\n// whitespace, which is the actual tag/message separator hilog emits.\nconst HILOG_LINE_RE = /^(\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}\\.\\d{3})\\s+(\\d+)\\s+(\\d+)\\s+([DIWEF])\\s+(\\S+):\\s+(.*)$/;\n\n/**\n * Parse a single line of `hdc shell hilog` output into structured fields.\n * Returns null when the line doesn't match the expected hilog format (e.g.\n * banners, blank lines, or partial chunks).\n */\nexport function parseHilogLine(line: string): HilogEntry | null {\n const match = HILOG_LINE_RE.exec(line);\n if (!match) return null;\n return {\n time: match[1]!,\n pid: match[2]!,\n tid: match[3]!,\n level: match[4]! as HilogEntry['level'],\n tag: match[5]!.trim(),\n message: match[6]!,\n };\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { spawn } from 'node:child_process';\nimport type { ConfigProvider } from '../ports/config.js';\nimport type { Logger } from '../ports/logger.js';\nimport { noopLogger } from '../ports/logger.js';\nimport { CmdToolsNotInstalledError, OniroError } from '../ports/errors.js';\nimport { getHvigorwPath, getOhosBaseSdkHome, getCmdToolsPath } from '../sdk/paths.js';\n\nexport interface RunHvigorwOptions {\n config: ConfigProvider;\n projectDir: string;\n /** Forwarded as `-p product=<product>`. Default `default`. */\n product?: string;\n /** Forwarded as `-p module=<module>` when set. */\n module?: string;\n /** Forwarded as `-p buildMode=<mode>` when set. */\n buildMode?: string;\n /** hvigor task to run. Default `assembleHap`. */\n task?: string;\n /** Extra raw args appended after the standard ones. */\n extraArgs?: readonly string[];\n logger?: Logger;\n /**\n * Optional callback for each stdout/stderr chunk, lets callers stream output\n * to a terminal or webview without buffering. Lines also flow through `logger`.\n */\n onOutput?: (chunk: string, stream: 'stdout' | 'stderr') => void;\n}\n\nexport interface RunHvigorwResult {\n exitCode: number;\n}\n\n/**\n * Run the project's `hvigorw` wrapper. Replaces the extension's vscode-tasks indirection\n * and the bash CLI's chained `clean` + `assembleHap` calls with a single direct spawn.\n */\nexport function runHvigorw(opts: RunHvigorwOptions): Promise<RunHvigorwResult> {\n const { config, projectDir } = opts;\n const logger = opts.logger ?? noopLogger;\n\n if (!fs.existsSync(path.join(projectDir, 'build-profile.json5'))) {\n throw new OniroError(`Not an OpenHarmony project: ${projectDir} (build-profile.json5 not found).`);\n }\n if (!fs.existsSync(getCmdToolsPath(config))) {\n throw new CmdToolsNotInstalledError(getCmdToolsPath(config));\n }\n\n const hvigorw = getHvigorwPath(config, projectDir);\n const args: string[] = [opts.task ?? 'assembleHap', '--mode', 'module'];\n args.push('-p', `product=${opts.product ?? 'default'}`);\n if (opts.module) args.push('-p', `module=${opts.module}`);\n if (opts.buildMode) args.push('-p', `buildMode=${opts.buildMode}`);\n args.push('--stacktrace', '--no-parallel', '--no-daemon');\n if (opts.extraArgs?.length) args.push(...opts.extraArgs);\n\n // Ensure hvigorw is executable on POSIX (project-local copies often aren't after a fresh clone).\n if (process.platform !== 'win32') {\n try { fs.chmodSync(hvigorw, 0o755); } catch { /* best effort */ }\n }\n\n const env: NodeJS.ProcessEnv = {\n ...process.env,\n OHOS_BASE_SDK_HOME: getOhosBaseSdkHome(config),\n };\n\n return new Promise((resolve, reject) => {\n logger.info(`[build] ${hvigorw} ${args.join(' ')}`);\n const child = spawn(hvigorw, args, { cwd: projectDir, env, shell: false });\n child.stdout.on('data', (chunk: Buffer) => {\n const text = chunk.toString();\n opts.onOutput?.(text, 'stdout');\n logger.info(text.trimEnd());\n });\n child.stderr.on('data', (chunk: Buffer) => {\n const text = chunk.toString();\n opts.onOutput?.(text, 'stderr');\n logger.warn(text.trimEnd());\n });\n child.on('error', (err) => reject(new OniroError(`Failed to start hvigorw: ${err.message}`, err)));\n child.on('close', (code) => {\n const exitCode = code ?? 1;\n if (exitCode === 0) resolve({ exitCode });\n else reject(new OniroError(`hvigorw exited with code ${exitCode}`));\n });\n });\n}\n","/**\n * Conservative project-folder-name validator (no path separators, conservative charset).\n */\nexport function isValidProjectName(name: string): boolean {\n if (!name) return false;\n if (name.includes('/') || name.includes('\\\\')) return false;\n return /^[A-Za-z0-9._-]+$/.test(name);\n}\n\n/**\n * Bundle-name validator. Allows reverse-DNS style identifiers like `com.example.myapp`.\n */\nexport function isValidBundleName(bundleName: string): boolean {\n return /^[A-Za-z][A-Za-z0-9_]*(\\.[A-Za-z][A-Za-z0-9_]*)+$/.test(bundleName);\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nexport interface TemplateOption {\n id: string;\n label: string;\n description: string;\n defaultModuleName: string;\n}\n\ninterface TemplateMeta {\n id?: string;\n label?: string;\n description?: string;\n defaultModuleName?: string;\n}\n\nfunction toHumanTemplateName(folderName: string): string {\n return folderName.replace(/([a-z])([A-Z])/g, '$1 $2');\n}\n\n/**\n * Enumerate templates inside `templateRoot`. Each direct subfolder is a template;\n * per-template metadata (label/description/defaultModuleName) may live in a\n * `template.json` file alongside the template content.\n *\n * Callers own the template root — the CLI ships its own under\n * `<cli-package>/templates/`, the VS Code extension uses `extensionPath/template`.\n */\nexport function listTemplates(templateRoot: string): TemplateOption[] {\n if (!fs.existsSync(templateRoot)) return [];\n const entries = fs.readdirSync(templateRoot, { withFileTypes: true });\n return entries\n .filter((e) => e.isDirectory())\n .map((e) => {\n const dir = path.join(templateRoot, e.name);\n const metaPath = path.join(dir, 'template.json');\n let meta: TemplateMeta = {};\n if (fs.existsSync(metaPath)) {\n try {\n meta = JSON.parse(fs.readFileSync(metaPath, 'utf8')) as TemplateMeta;\n } catch {\n // Ignore malformed template metadata.\n }\n }\n return {\n id: e.name,\n label: meta.label ?? toHumanTemplateName(e.name),\n description: meta.description ?? '',\n defaultModuleName: (meta.defaultModuleName ?? 'entry').trim() || 'entry',\n };\n })\n .sort((a, b) => a.label.localeCompare(b.label));\n}\n\n/**\n * Verify that a template directory contains the files required by the scaffold pipeline.\n * Returns the list of missing relative paths, or [] if the template is complete.\n */\nexport function validateTemplateLayout(templateDir: string, defaultModuleName: string): string[] {\n const required = [\n 'build-profile.json5',\n path.join('AppScope', 'app.json5'),\n path.join(defaultModuleName, 'src', 'main', 'module.json5'),\n path.join(defaultModuleName, 'oh-package.json5'),\n 'hvigorfile.ts',\n ];\n return required.filter((rel) => !fs.existsSync(path.join(templateDir, rel)));\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport type { ConfigProvider } from '../ports/config.js';\nimport type { Logger } from '../ports/logger.js';\nimport { noopLogger } from '../ports/logger.js';\nimport { OniroError } from '../ports/errors.js';\nimport { getOhosBaseSdkHome } from '../sdk/paths.js';\nimport { listTemplates, validateTemplateLayout } from './templates.js';\nimport { isValidBundleName, isValidProjectName } from './validators.js';\nimport { readJson5File, readJsonFile, writeJson5File, writeJsonFile } from './jsonHelpers.js';\n\nconst IGNORED_DIRS = new Set(['oh_modules', 'node_modules', 'build', '.hvigor']);\n\nexport interface CreateScaffoldOptions {\n config: ConfigProvider;\n templateId: string;\n projectName: string;\n bundleName: string;\n /** Parent directory that will contain the new project folder. */\n location: string;\n sdkApi: number;\n /** Module folder name. Defaults to the template's `defaultModuleName`. */\n moduleName?: string;\n /** Absolute path to the directory containing template subfolders. */\n templateRoot: string;\n /** If the destination exists, remove it before scaffolding instead of throwing. */\n overwrite?: boolean;\n logger?: Logger;\n}\n\nexport interface CreateScaffoldResult {\n projectDir: string;\n}\n\n/**\n * Async existence check.\n */\nasync function pathExists(p: string): Promise<boolean> {\n try {\n await fs.promises.access(p);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Recursively copy a template directory, skipping symlinks and template metadata.\n */\nasync function copyDirRecursive(srcDir: string, destDir: string): Promise<void> {\n await fs.promises.mkdir(destDir, { recursive: true });\n const entries = await fs.promises.readdir(srcDir, { withFileTypes: true });\n for (const entry of entries) {\n const src = path.join(srcDir, entry.name);\n const dest = path.join(destDir, entry.name);\n if (entry.isDirectory()) {\n await copyDirRecursive(src, dest);\n } else if (entry.isSymbolicLink()) {\n continue;\n } else if (entry.isFile()) {\n if (entry.name === 'template.json') continue;\n await fs.promises.copyFile(src, dest);\n }\n }\n}\n\n/**\n * Normalize every .json5 file in `projectDir` to strict JSON formatting (quoted keys).\n * Keeps JSON5 parsers happy while letting VS Code's built-in JSON parser handle them.\n */\nasync function normalizeJson5ToJson(projectDir: string, logger: Logger): Promise<void> {\n const stack: string[] = [projectDir];\n while (stack.length > 0) {\n const currentDir = stack.pop()!;\n const entries = await fs.promises.readdir(currentDir, { withFileTypes: true });\n for (const entry of entries) {\n const fullPath = path.join(currentDir, entry.name);\n if (entry.isDirectory()) {\n if (IGNORED_DIRS.has(entry.name)) continue;\n stack.push(fullPath);\n continue;\n }\n if (!entry.isFile() || !entry.name.endsWith('.json5')) continue;\n try {\n const parsed = readJson5File<unknown>(fullPath);\n writeJson5File(fullPath, parsed);\n } catch (err) {\n logger.warn(`Failed to normalize ${fullPath}: ${String(err)}`);\n }\n }\n }\n}\n\nfunction toJavaPropertiesPath(p: string): string {\n return process.platform === 'win32' ? p.replace(/\\\\/g, '\\\\\\\\') : p;\n}\n\nfunction createOrUpdateLocalProperties(projectDir: string, sdkDir: string): void {\n const content = `sdk.dir=${toJavaPropertiesPath(sdkDir)}\\n`;\n fs.writeFileSync(path.join(projectDir, 'local.properties'), content, 'utf8');\n}\n\nfunction renameIfExists(fromPath: string, toPath: string): void {\n if (fs.existsSync(fromPath) && fromPath !== toPath) {\n fs.renameSync(fromPath, toPath);\n }\n}\n\n/**\n * Apply user-selected names/versions to template files. Mirrors the writes done by\n * the extension's `updateTemplateConfigs` so a scaffold is identical regardless of\n * which frontend produced it.\n */\nfunction updateTemplateConfigs(\n projectDir: string,\n args: {\n projectName: string;\n bundleName: string;\n sdkApi: number;\n moduleName: string;\n },\n sdkBaseDir: string,\n): void {\n // 1) AppScope/app.json5 -> bundleName\n const appJsonPath = path.join(projectDir, 'AppScope', 'app.json5');\n if (fs.existsSync(appJsonPath)) {\n const appJson = readJson5File<{ app?: { bundleName?: string } }>(appJsonPath);\n appJson.app = appJson.app ?? {};\n appJson.app.bundleName = args.bundleName;\n writeJson5File(appJsonPath, appJson);\n }\n\n // 2) AppScope/resources/base/element/string.json -> app_name = projectName\n const stringsPath = path.join(projectDir, 'AppScope', 'resources', 'base', 'element', 'string.json');\n if (fs.existsSync(stringsPath)) {\n const strings = readJsonFile<{ string?: Array<{ name?: string; value?: string }> }>(stringsPath);\n if (Array.isArray(strings.string)) {\n const appName = strings.string.find((s) => s.name === 'app_name');\n if (appName) appName.value = args.projectName;\n }\n writeJsonFile(stringsPath, strings);\n }\n\n // 3) build-profile.json5 -> sdk + module name + srcPath\n const buildProfilePath = path.join(projectDir, 'build-profile.json5');\n if (fs.existsSync(buildProfilePath)) {\n const buildProfile = readJson5File<{\n app?: { products?: Array<{ compileSdkVersion?: number; compatibleSdkVersion?: number }> };\n modules?: Array<{ name?: string; srcPath?: string }>;\n }>(buildProfilePath);\n buildProfile.app = buildProfile.app ?? {};\n if (Array.isArray(buildProfile.app.products) && buildProfile.app.products.length > 0) {\n buildProfile.app.products[0]!.compileSdkVersion = args.sdkApi;\n buildProfile.app.products[0]!.compatibleSdkVersion = args.sdkApi;\n }\n if (Array.isArray(buildProfile.modules) && buildProfile.modules.length > 0) {\n buildProfile.modules[0]!.name = args.moduleName;\n buildProfile.modules[0]!.srcPath = `./${args.moduleName}`;\n }\n writeJson5File(buildProfilePath, buildProfile);\n }\n\n // 4) <module>/src/main/module.json5 -> module.name\n const moduleJsonPath = path.join(projectDir, args.moduleName, 'src', 'main', 'module.json5');\n if (fs.existsSync(moduleJsonPath)) {\n const moduleJson = readJson5File<{ module?: { name?: string } }>(moduleJsonPath);\n moduleJson.module = moduleJson.module ?? {};\n moduleJson.module.name = args.moduleName;\n writeJson5File(moduleJsonPath, moduleJson);\n }\n\n // 5) <module>/oh-package.json5 -> name\n const moduleOhPackagePath = path.join(projectDir, args.moduleName, 'oh-package.json5');\n if (fs.existsSync(moduleOhPackagePath)) {\n const pkg = readJson5File<{ name?: string }>(moduleOhPackagePath);\n pkg.name = args.moduleName;\n writeJson5File(moduleOhPackagePath, pkg);\n }\n\n // 6) .vscode/settings.json — useful for users who do open the project in VS Code.\n const vscodeDir = path.join(projectDir, '.vscode');\n fs.mkdirSync(vscodeDir, { recursive: true });\n const hapPath = `${args.moduleName}/build/default/outputs/default/${args.moduleName}-default-signed.hap`;\n writeJsonFile(path.join(vscodeDir, 'settings.json'), {\n 'oniro.hapPath': hapPath,\n 'files.associations': { '*.json5': 'jsonc' },\n });\n\n // 7) local.properties — sdk.dir must point at the OS base SDK home (containing API folders),\n // NOT a specific API folder, otherwise hvigor double-nests the lookup.\n createOrUpdateLocalProperties(projectDir, sdkBaseDir);\n}\n\n/**\n * Scaffold a new Oniro/OpenHarmony project from a template. Returns the absolute path\n * to the created project directory.\n */\nexport async function createScaffold(opts: CreateScaffoldOptions): Promise<CreateScaffoldResult> {\n const logger = opts.logger ?? noopLogger;\n\n if (!isValidProjectName(opts.projectName)) {\n throw new OniroError(`Invalid project name '${opts.projectName}'. Use letters/numbers/._- and no slashes.`);\n }\n if (!isValidBundleName(opts.bundleName)) {\n throw new OniroError(`Invalid bundle name '${opts.bundleName}'. Example: com.example.myapplication`);\n }\n if (!opts.location || !(await pathExists(opts.location))) {\n throw new OniroError(`Location does not exist: ${opts.location}`);\n }\n\n const templateDir = path.join(opts.templateRoot, opts.templateId);\n if (!(await pathExists(templateDir))) {\n throw new OniroError(`Template not found: ${templateDir}`);\n }\n\n const templates = listTemplates(opts.templateRoot);\n const selected = templates.find((t) => t.id === opts.templateId);\n const defaultModuleName = selected?.defaultModuleName ?? 'entry';\n const moduleName = (opts.moduleName ?? defaultModuleName).trim() || defaultModuleName;\n\n const missing = validateTemplateLayout(templateDir, defaultModuleName);\n if (missing.length > 0) {\n throw new OniroError(`Template '${opts.templateId}' is missing required files:\\n- ${missing.join('\\n- ')}`);\n }\n\n const projectDir = path.join(opts.location, opts.projectName);\n if (await pathExists(projectDir)) {\n if (!opts.overwrite) {\n throw new OniroError(`Destination already exists: ${projectDir}. Pass overwrite: true to replace it.`);\n }\n await fs.promises.rm(projectDir, { recursive: true, force: true });\n }\n\n logger.info(`[create] Scaffolding ${opts.templateId} at ${projectDir}`);\n await copyDirRecursive(templateDir, projectDir);\n\n if (moduleName !== defaultModuleName) {\n renameIfExists(path.join(projectDir, defaultModuleName), path.join(projectDir, moduleName));\n }\n\n updateTemplateConfigs(\n projectDir,\n {\n projectName: opts.projectName,\n bundleName: opts.bundleName,\n sdkApi: opts.sdkApi,\n moduleName,\n },\n getOhosBaseSdkHome(opts.config),\n );\n\n await normalizeJson5ToJson(projectDir, logger);\n\n return { projectDir };\n}\n","import * as fs from 'node:fs';\nimport JSON5 from 'json5';\n\nexport function readJson5File<T>(filePath: string): T {\n return JSON5.parse(fs.readFileSync(filePath, 'utf8')) as T;\n}\n\n/**\n * Write strict JSON content (quoted keys) to a `.json5` file. Keeps the file\n * compatible with VS Code's JSON parser while remaining valid JSON5.\n */\nexport function writeJson5File(filePath: string, value: unknown): void {\n fs.writeFileSync(filePath, JSON.stringify(value, null, 2) + '\\n', 'utf8');\n}\n\nexport function readJsonFile<T>(filePath: string): T {\n return JSON.parse(fs.readFileSync(filePath, 'utf8')) as T;\n}\n\nexport function writeJsonFile(filePath: string, value: unknown): void {\n fs.writeFileSync(filePath, JSON.stringify(value, null, 2) + '\\n', 'utf8');\n}\n"],"mappings":"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","names":["platform","os","platform","os","path","fs","path","JSON5","fs","followRedirects","resolve","fs","os","path","import_node_stream","import_node_util","pipelineAsync","StreamZip","fs","path","fs","path","fs","os","path","n","fs","os","path","platform","fs","path","crypto","fs","path","import_node_child_process","import_json5","JSON5","fs","os","path","fs","os","path","import_node_child_process","resolve","tail","fs","path","import_json5","JSON5","fs","path","import_node_child_process","execPromise","resolve","import_node_child_process","resolve","fs","path","import_node_child_process","resolve","fs","path","fs","path","fs","import_json5","JSON5"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/ports/logger.ts","../src/ports/progress.ts","../src/ports/config.ts","../src/ports/prompter.ts","../src/ports/errors.ts","../src/ports/context.ts","../src/sdk/constants.ts","../src/sdk/platform.ts","../src/sdk/paths.ts","../src/sdk/detectProjectSdk.ts","../src/sdk/tmp.ts","../src/sdk/download.ts","../src/sdk/extract.ts","../src/sdk/list.ts","../src/sdk/remove.ts","../src/sdk/install.ts","../src/sdk/move.ts","../src/cmdTools/install.ts","../src/sign/encryptKey.ts","../src/sign/generateSigningConfigs.ts","../src/sign/applicationCert.ts","../src/emulator/install.ts","../src/emulator/lifecycle.ts","../src/hdc/exec.ts","../src/hdc/devices.ts","../src/hdc/param.ts","../src/hdc/files.ts","../src/hdc/display.ts","../src/hdc/wait.ts","../src/hdc/app.ts","../src/hdc/project.ts","../src/hdc/lifecycle.ts","../src/hdc/screen.ts","../src/hdc/input.ts","../src/hdc/dump.ts","../src/hdc/hilog.ts","../src/build/runHvigorw.ts","../src/build/discoverHaps.ts","../src/build/ohpm.ts","../src/build/codelinter.ts","../src/build/buildHap.ts","../src/project/validators.ts","../src/project/templates.ts","../src/project/createScaffold.ts","../src/project/jsonHelpers.ts","../src/project/listModules.ts","../src/project/abilities.ts","../src/project/prepareSigning.ts","../src/device/hidumper.ts","../src/device/info.ts","../src/install/diffHapAssets.ts","../src/install/apply.ts"],"sourcesContent":["declare const __PKG_VERSION__: string;\nexport const VERSION = __PKG_VERSION__;\n\nexport * from './ports/index.js';\nexport * from './sdk/index.js';\nexport * from './cmdTools/index.js';\nexport * from './sign/index.js';\nexport * from './emulator/index.js';\nexport * from './hdc/index.js';\nexport * from './build/index.js';\nexport * from './project/index.js';\nexport * from './device/index.js';\nexport * from './install/index.js';\n","export interface Logger {\n debug(message: string): void;\n info(message: string): void;\n warn(message: string): void;\n error(message: string): void;\n}\n\nexport const noopLogger: Logger = {\n debug() {},\n info() {},\n warn() {},\n error() {},\n};\n\nexport const consoleLogger: Logger = {\n debug: (m) => console.debug(m),\n info: (m) => console.log(m),\n warn: (m) => console.warn(m),\n error: (m) => console.error(m),\n};\n\n/**\n * Wrap a Logger so every message is prefixed with `[<scope>] `. Standardizes the\n * ad-hoc `[hdc]` / `[build]` / `[sign]` / `[hilog]` / `[emulator]` prefixes that\n * were previously hand-written at each call site.\n */\nexport function scopedLogger(logger: Logger, scope: string): Logger {\n const prefix = `[${scope}] `;\n return {\n debug: (m) => logger.debug(prefix + m),\n info: (m) => logger.info(prefix + m),\n warn: (m) => logger.warn(prefix + m),\n error: (m) => logger.error(prefix + m),\n };\n}\n","export interface ProgressUpdate {\n message?: string;\n increment?: number;\n}\n\nexport interface ProgressReporter {\n report(update: ProgressUpdate): void;\n}\n\nexport const noopProgress: ProgressReporter = {\n report() {},\n};\n","import * as os from 'node:os';\nimport * as path from 'node:path';\n\n/**\n * Keys read from the ConfigProvider by core. Frontends (CLI, VS Code extension)\n * implement the provider however they like (env vars, settings.json, etc.).\n */\nexport type ConfigKey =\n | 'sdkRootDir'\n | 'cmdToolsPath'\n | 'hdcPath'\n | 'emulatorDir'\n | 'hapPath'\n | 'cmdToolsUrlLinux'\n | 'cmdToolsUrlWindows'\n | 'cmdToolsUrlMac'\n | 'emulatorUrl'\n // Scratch directory for download/extract temporaries. Defaults to the system temp\n // dir, which is often a RAM-backed tmpfs too small for multi-GB archives; point\n // this at a disk-backed directory when that bites.\n | 'tmpDir'\n // Base URL for OpenHarmony SDK release downloads. Defaults to the Huawei mirror\n // (`OHOS_URL_BASE`); override to point at a private/CI mirror.\n | 'sdkUrlBase'\n // Optional path to an external application-cert chain that overrides the bundled\n // `OpenHarmonyApplication.cer` during signing. Empty/unset → use the bundled cert.\n | 'applicationCertPath';\n\nexport interface ConfigProvider {\n /**\n * Get the configured value for `key`, or `fallback` if unset/empty.\n * Implementations should expand the literal `${userHome}` to the user's home dir.\n */\n get<T extends string | number | boolean>(key: ConfigKey, fallback: T): T;\n}\n\n/**\n * Default config values used when a ConfigProvider returns the fallback.\n * These match the historical paths used by the bash CLI and the extension.\n */\nexport const defaultPaths = {\n sdkRootDir: () => path.join(os.homedir(), 'setup-ohos-sdk'),\n cmdToolsPath: () => path.join(os.homedir(), 'command-line-tools'),\n emulatorDir: () => path.join(os.homedir(), 'oniro-emulator'),\n hapPath: 'entry/build/default/outputs/default/entry-default-signed.hap',\n emulatorUrl:\n 'https://github.com/eclipse-oniro4openharmony/device_board_oniro/releases/latest/download/oniro_emulator.zip',\n // The Huawei mirror only hosts a public Linux build of the command-line tools.\n // Windows and macOS require a manual download from the Huawei developer portal\n // (https://developer.huawei.com/...); pass the resulting ZIP to `cmdtools install --from-zip <path>`\n // or set ONIRO_CMD_TOOLS_URL_WINDOWS / ONIRO_CMD_TOOLS_URL_MAC to a self-hosted URL.\n cmdToolsUrlLinux:\n 'https://repo.huaweicloud.com/harmonyos/ohpm/5.1.0/commandline-tools-linux-x64-5.1.0.840.zip',\n} as const;\n\n/**\n * A simple in-memory ConfigProvider, useful for tests and as a base for CLI/extension impls.\n */\nexport function staticConfig(values: Partial<Record<ConfigKey, string>> = {}): ConfigProvider {\n return {\n get<T extends string | number | boolean>(key: ConfigKey, fallback: T): T {\n const v = values[key];\n if (v === undefined || v === '') {\n return fallback;\n }\n // Expand ${userHome} like the extension does.\n if (typeof v === 'string' && v.includes('${userHome}')) {\n return v.replace(/\\$\\{userHome\\}/g, os.homedir()) as unknown as T;\n }\n return v as unknown as T;\n },\n };\n}\n","/**\n * Interactive prompts. Frontends implement these — CLI uses @inquirer/prompts,\n * the extension uses `vscode.window.show*`. Core never assumes a TTY.\n */\nexport interface Prompter {\n /** Ask the user to confirm an action. */\n confirm(message: string, defaultValue?: boolean): Promise<boolean>;\n /** Ask the user for a single line of text. */\n input(message: string, defaultValue?: string): Promise<string>;\n /** Ask the user to pick a directory on disk; resolves to an absolute path or null if cancelled. */\n selectDirectory(message: string, defaultPath?: string): Promise<string | null>;\n /** Ask the user to pick a file on disk; resolves to an absolute path or null if cancelled. */\n selectFile(message: string, filters?: { extensions?: string[] }): Promise<string | null>;\n}\n\n/**\n * Throws on any prompt — used in non-interactive contexts where all answers must come from flags.\n */\nexport const nonInteractivePrompter: Prompter = {\n async confirm(message) {\n throw new Error(`Non-interactive mode: cannot confirm \"${message}\"`);\n },\n async input(message) {\n throw new Error(`Non-interactive mode: cannot ask \"${message}\"`);\n },\n async selectDirectory(message) {\n throw new Error(`Non-interactive mode: cannot prompt for directory \"${message}\"`);\n },\n async selectFile(message) {\n throw new Error(`Non-interactive mode: cannot prompt for file \"${message}\"`);\n },\n};\n","export class OniroError extends Error {\n constructor(message: string, public override readonly cause?: unknown) {\n super(message);\n this.name = 'OniroError';\n }\n}\n\nexport class SdkNotInstalledError extends OniroError {\n constructor(public readonly api: string, public readonly expectedPath: string) {\n super(`SDK API ${api} is not installed at ${expectedPath}.`);\n this.name = 'SdkNotInstalledError';\n }\n}\n\nexport class CmdToolsNotInstalledError extends OniroError {\n constructor(public readonly expectedPath: string) {\n super(`OpenHarmony command-line tools are not installed at ${expectedPath}.`);\n this.name = 'CmdToolsNotInstalledError';\n }\n}\n\nexport class UnsupportedPlatformError extends OniroError {\n constructor(public readonly platform: string) {\n super(`Unsupported platform: ${platform}.`);\n this.name = 'UnsupportedPlatformError';\n }\n}\n\nexport class ChecksumMismatchError extends OniroError {\n constructor(public readonly expected: string, public readonly actual: string) {\n super(`SHA256 mismatch: expected ${expected}, got ${actual}.`);\n this.name = 'ChecksumMismatchError';\n }\n}\n\n/**\n * A download/extract ran out of room on the filesystem holding its scratch\n * directory. The message is built by the caller (see `sdk/tmp.ts`) so it can name\n * the directory, whether it is RAM-backed, and how to point elsewhere.\n */\nexport class InsufficientSpaceError extends OniroError {\n constructor(message: string, public readonly dir: string, cause?: unknown) {\n super(message, cause);\n this.name = 'InsufficientSpaceError';\n }\n}\n\nexport class CancelledError extends OniroError {\n constructor(message = 'Operation cancelled.') {\n super(message);\n this.name = 'CancelledError';\n }\n}\n\n/**\n * A spawned command ran to completion but exited non-zero. Lets callers\n * distinguish \"the tool ran and failed\" from \"the tool could not be spawned\"\n * (a missing binary surfaces as an OniroError / CmdToolsNotInstalledError).\n */\nexport class CommandFailedError extends OniroError {\n constructor(\n public readonly command: string,\n public readonly exitCode: number,\n public readonly stderr: string,\n ) {\n super(`Command failed (exit ${exitCode}): ${command}${stderr ? `\\n${stderr}` : ''}`);\n this.name = 'CommandFailedError';\n }\n}\n","import { Logger, noopLogger } from './logger.js';\nimport { ConfigProvider, staticConfig } from './config.js';\n\n/**\n * Carries the cross-cutting dependencies most core functions need: a Logger and a ConfigProvider.\n * Functions that report progress or prompt the user take those as additional parameters.\n */\nexport interface OniroContext {\n logger: Logger;\n config: ConfigProvider;\n}\n\nexport function defaultContext(overrides: Partial<OniroContext> = {}): OniroContext {\n return {\n logger: overrides.logger ?? noopLogger,\n config: overrides.config ?? staticConfig(),\n };\n}\n","export interface SdkRelease {\n version: string;\n api: string;\n /**\n * Number of leading path components to strip when extracting the release\n * tarball, per OS family. The Huawei mirror packs linux+windows in one\n * tarball (no top-level wrapper for some releases → 0, else 1); macOS\n * tarballs have a deeper layout (3). This table is the single source of\n * truth read by `getSdkFilename()`.\n */\n tarballStrip: { linuxWindows: number; darwin: number };\n}\n\n/**\n * Known OpenHarmony SDK releases. Kept in sync with the bash CLI / extension.\n * Update when a new SDK ships.\n */\nexport const ALL_SDKS: readonly SdkRelease[] = [\n { version: '4.0', api: '10', tarballStrip: { linuxWindows: 1, darwin: 3 } },\n { version: '4.1', api: '11', tarballStrip: { linuxWindows: 1, darwin: 3 } },\n { version: '5.0.0', api: '12', tarballStrip: { linuxWindows: 0, darwin: 3 } },\n { version: '5.0.1', api: '13', tarballStrip: { linuxWindows: 0, darwin: 3 } },\n { version: '5.0.2', api: '14', tarballStrip: { linuxWindows: 1, darwin: 3 } },\n { version: '5.0.3', api: '15', tarballStrip: { linuxWindows: 1, darwin: 3 } },\n { version: '5.1.0', api: '18', tarballStrip: { linuxWindows: 1, darwin: 3 } },\n { version: '5.1.1', api: '19', tarballStrip: { linuxWindows: 1, darwin: 3 } },\n { version: '6.0', api: '20', tarballStrip: { linuxWindows: 0, darwin: 3 } },\n { version: '6.1', api: '23', tarballStrip: { linuxWindows: 0, darwin: 3 } },\n];\n\nexport const OHOS_URL_BASE = 'https://repo.huaweicloud.com/openharmony/os';\n","import * as os from 'node:os';\nimport { ALL_SDKS } from './constants.js';\nimport { UnsupportedPlatformError } from '../ports/errors.js';\n\nexport type OsFolder = 'linux' | 'darwin' | 'windows';\n\n/**\n * Map Node's `os.platform()` to the OS folder name used in the SDK install layout\n * and the SDK release tarballs.\n */\nexport function getOsFolder(): OsFolder {\n const platform = os.platform();\n if (platform === 'linux') return 'linux';\n if (platform === 'darwin') return 'darwin';\n if (platform === 'win32') return 'windows';\n throw new UnsupportedPlatformError(platform);\n}\n\nexport interface SdkArchiveInfo {\n filename: string;\n osFolder: OsFolder;\n /** Number of leading path components to strip when extracting the tarball. */\n strip: number;\n}\n\n/**\n * Resolve the SDK archive filename, OS folder, and tar strip count for the current platform.\n *\n * The Huawei mirror packages Linux and Windows together in one tarball with `linux/` and\n * `windows/` subfolders; macOS tarballs have a deeper layout. The per-release strip counts\n * live in {@link ALL_SDKS} (`tarballStrip`). An unrecognized version falls back to the\n * historical default (linux/windows=1, darwin=3).\n */\nexport function getSdkFilename(version?: string): SdkArchiveInfo {\n const platform = os.platform();\n const v = version ?? ALL_SDKS[ALL_SDKS.length - 1]!.version;\n const strips = ALL_SDKS.find((r) => r.version === v)?.tarballStrip ?? { linuxWindows: 1, darwin: 3 };\n\n if (platform === 'linux') {\n return { filename: 'ohos-sdk-windows_linux-public.tar.gz', osFolder: 'linux', strip: strips.linuxWindows };\n }\n if (platform === 'darwin') {\n if (os.arch() === 'arm64') {\n return { filename: 'L2-SDK-MAC-M1-PUBLIC.tar.gz', osFolder: 'darwin', strip: strips.darwin };\n }\n return { filename: 'ohos-sdk-mac-public.tar.gz', osFolder: 'darwin', strip: strips.darwin };\n }\n if (platform === 'win32') {\n return { filename: 'ohos-sdk-windows_linux-public.tar.gz', osFolder: 'windows', strip: strips.linuxWindows };\n }\n throw new UnsupportedPlatformError(platform);\n}\n","import * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport { ConfigProvider, defaultPaths } from '../ports/config.js';\nimport { getOsFolder } from './platform.js';\n\nexport function getSdkRootDir(config: ConfigProvider): string {\n return config.get('sdkRootDir', defaultPaths.sdkRootDir());\n}\n\n/**\n * Base SDK home for the current OS: `<sdkRootDir>/<linux|darwin|windows>`.\n * SDK API folders (e.g. `12`, `18`, `20`) live inside this directory.\n */\nexport function getOhosBaseSdkHome(config: ConfigProvider): string {\n return path.join(getSdkRootDir(config), getOsFolder());\n}\n\nexport function getCmdToolsPath(config: ConfigProvider): string {\n return config.get('cmdToolsPath', defaultPaths.cmdToolsPath());\n}\n\nexport function getEmulatorDir(config: ConfigProvider): string {\n return config.get('emulatorDir', defaultPaths.emulatorDir());\n}\n\nfunction pickExisting(candidates: string[]): string {\n for (const c of candidates) {\n if (fs.existsSync(c)) return c;\n }\n return candidates[0]!;\n}\n\n/**\n * Resolve a binary inside the command-line tools `bin/` directory by name\n * (e.g. `'ohpm'`, `'hvigorw'`, `'codelinter'`). On Windows tries common\n * executable suffixes (.exe, .cmd, .bat) before the POSIX name.\n */\nexport function getCmdToolsBin(config: ConfigProvider, name = 'ohpm'): string {\n const binDir = path.join(getCmdToolsPath(config), 'bin');\n if (os.platform() === 'win32') {\n return pickExisting([\n path.join(binDir, `${name}.exe`),\n path.join(binDir, `${name}.cmd`),\n path.join(binDir, `${name}.bat`),\n path.join(binDir, name),\n ]);\n }\n return path.join(binDir, name);\n}\n\n/** Resolve the OHPM binary path inside the command-line tools install. */\nexport function getOhpmPath(config: ConfigProvider): string {\n return getCmdToolsBin(config, 'ohpm');\n}\n\n/**\n * Resolve the hdc binary. An explicit `hdcPath` override (config key / `ONIRO_HDC`\n * env var) wins — point it at a wrapper/proxy hdc when the device is not directly\n * attached here (e.g. a remote device behind an SSH-tunnel `hdc` wrapper). When\n * unset, fall back to the hdc bundled in the SDK toolchains tree.\n */\nexport function getHdcPath(config: ConfigProvider): string {\n const override = config.get('hdcPath', '');\n if (override) return override;\n const base = path.join(getCmdToolsPath(config), 'sdk', 'default', 'openharmony', 'toolchains');\n if (os.platform() === 'win32') {\n return pickExisting([\n path.join(base, 'hdc.exe'),\n path.join(base, 'hdc.bat'),\n path.join(base, 'hdc.cmd'),\n path.join(base, 'hdc'),\n ]);\n }\n return path.join(base, 'hdc');\n}\n\n/**\n * Resolve the hvigorw wrapper for a project. Prefers the project-local copy\n * (which carries the project's pinned hvigor version) — but ONLY when that\n * wrapper is structurally complete. HMOS-vendored projects (systemui, launcher)\n * ship a project-local `hvigorw` whose `hvigor/` install is absent, so the\n * wrapper crashes on startup; in that case we fall back to the hvigorw bundled\n * with the command-line tools, which is always installed.\n */\nexport function getHvigorwPath(config: ConfigProvider, projectDir: string): string {\n const local = pickExisting([\n path.join(projectDir, 'hvigorw'),\n path.join(projectDir, 'hvigorw.bat'),\n path.join(projectDir, 'hvigorw.cmd'),\n ]);\n if (fs.existsSync(local) && isProjectLocalHvigorwWorking(projectDir)) {\n return local;\n }\n return getCmdToolsBin(config, 'hvigorw');\n}\n\n/**\n * A project-local hvigorw wrapper only works when the project also has a\n * populated `hvigor/` install. The structural check (wrapper script + its\n * node_modules) is fast and avoids spawning `hvigorw --version` for the common,\n * working case.\n */\nfunction isProjectLocalHvigorwWorking(projectDir: string): boolean {\n const wrapper = path.join(projectDir, 'hvigor', 'hvigor-wrapper.js');\n const nodeModules = path.join(projectDir, 'hvigor', 'node_modules');\n return fs.existsSync(wrapper) && fs.existsSync(nodeModules);\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport JSON5 from 'json5';\nimport { Logger, noopLogger } from '../ports/logger.js';\n\n/**\n * Detect the SDK API a project targets by reading `build-profile.json5`.\n * Returns the `compileSdkVersion` of the first declared product, or undefined\n * if the file is missing/malformed or no product declares one.\n */\nexport function detectProjectSdkVersion(projectRoot: string, logger: Logger = noopLogger): number | undefined {\n const buildProfilePath = path.join(projectRoot, 'build-profile.json5');\n if (!fs.existsSync(buildProfilePath)) {\n logger.warn(`build-profile.json5 not found at ${projectRoot}`);\n return undefined;\n }\n try {\n const content = fs.readFileSync(buildProfilePath, 'utf-8');\n const config = JSON5.parse(content) as { app?: { products?: Array<{ compileSdkVersion?: unknown }> } };\n const product = config.app?.products?.[0];\n const v = product?.compileSdkVersion;\n return typeof v === 'number' ? v : undefined;\n } catch (err) {\n logger.error(`Error reading build-profile.json5 at ${projectRoot}: ${String(err)}`);\n return undefined;\n }\n}\n","import * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport type { ConfigProvider } from '../ports/config.js';\nimport type { Logger } from '../ports/logger.js';\nimport { noopLogger } from '../ports/logger.js';\nimport { InsufficientSpaceError, OniroError } from '../ports/errors.js';\n\n/** Name of the scratch folder created next to an install target. */\nexport const INSTALL_TMP_DIRNAME = '.oniro-tmp';\n\n/** `statfs` type magics for the Linux filesystems whose capacity comes out of RAM. */\nconst TMPFS_MAGIC = 0x01021994;\nconst RAMFS_MAGIC = 0x858458f6;\n\nconst HINT_EXAMPLE = os.platform() === 'win32' ? 'D:\\\\oniro-tmp' : '~/.cache/oniro-tmp';\n\n/** Advice appended to out-of-space failures in the scratch directory. */\nexport const TMP_DIR_HINT =\n 'Point the scratch directory at a filesystem with more room using --tmp-dir <path> ' +\n `(or the ONIRO_TMP_DIR environment variable), e.g. --tmp-dir ${HINT_EXAMPLE}.`;\n\n/**\n * Resolve the directory that download/extract scratch space is created in.\n *\n * Precedence: explicit override (CLI `--tmp-dir`) → `tmpDir` config key\n * (`ONIRO_TMP_DIR`) → `<installRoot>/.oniro-tmp` → the system temp dir.\n *\n * The default sits next to the install target so that the unpacked tree is renamed\n * into place rather than copied across a device boundary, and so the system temp dir\n * — a RAM-backed `tmpfs` on most Linux systems, and far smaller than a multi-GB\n * archive — is never in the picture.\n */\nexport function resolveTmpRoot(config: ConfigProvider, override?: string, installRoot?: string): string {\n const explicit = (override ?? '').trim();\n if (explicit) return path.resolve(explicit);\n const configured = config.get('tmpDir', '').trim();\n if (configured) return path.resolve(configured);\n if (installRoot) return path.join(path.resolve(installRoot), INSTALL_TMP_DIRNAME);\n return os.tmpdir();\n}\n\n/** Create a private scratch directory under `root`, creating `root` if needed. */\nexport function createTempWorkDir(root: string, prefix: string): string {\n try {\n fs.mkdirSync(root, { recursive: true });\n return fs.mkdtempSync(path.join(root, prefix));\n } catch (err) {\n if (isOutOfSpaceError(err)) throw toSpaceError(err, root, 'a temporary directory');\n throw new OniroError(\n `Cannot create a temporary directory in '${root}': ${err instanceof Error ? err.message : String(err)}\\n${TMP_DIR_HINT}`,\n err,\n );\n }\n}\n\n/**\n * Remove a scratch directory once an install is done, taking the `.oniro-tmp` root\n * with it when that leaves it empty. A root the caller named explicitly is left alone,\n * as are roots another install is still using (the rmdir simply fails).\n */\nexport function removeTempWorkDir(dir: string, root?: string): void {\n fs.rmSync(dir, { recursive: true, force: true });\n if (!root || path.basename(root) !== INSTALL_TMP_DIRNAME) return;\n try {\n fs.rmdirSync(root);\n } catch {\n // Not empty (a concurrent install) or already gone — nothing to do.\n }\n}\n\nexport interface InstallTempDirOptions {\n config: ConfigProvider;\n /** Explicit scratch directory (CLI `--tmp-dir`). */\n override?: string;\n /** Directory the install lands in; the default scratch root is created inside it. */\n installRoot: string;\n prefix: string;\n logger?: Logger;\n}\n\nexport interface InstallTempDir {\n /** The private per-run scratch directory. Remove it when the install finishes. */\n dir: string;\n /** The configurable root it was created under, for out-of-space messages. */\n root: string;\n}\n\n/**\n * Create the scratch directory for an install, defaulting to `<installRoot>/.oniro-tmp`.\n *\n * When that default is unusable — a read-only or root-owned install parent, say — the\n * system temp dir is used instead. A directory the caller asked for explicitly is never\n * swapped out silently, and a full filesystem is reported rather than papered over.\n */\nexport function createInstallTempDir(opts: InstallTempDirOptions): InstallTempDir {\n const requested =\n (opts.override ?? '').trim() || opts.config.get('tmpDir', '').trim();\n const root = resolveTmpRoot(opts.config, opts.override, opts.installRoot);\n\n try {\n return { dir: createTempWorkDir(root, opts.prefix), root };\n } catch (err) {\n const fallback = os.tmpdir();\n if (requested || isOutOfSpaceError(err) || path.resolve(fallback) === path.resolve(root)) throw err;\n const reason = err instanceof Error ? err.message.split('\\n')[0] : String(err);\n (opts.logger ?? noopLogger).warn(`${reason} Falling back to '${fallback}'.`);\n return { dir: createTempWorkDir(fallback, opts.prefix), root: fallback };\n }\n}\n\n/** Nearest existing ancestor of `dir` (or null if even the root is unreadable). */\nfunction nearestExisting(dir: string): string | null {\n let current = path.resolve(dir);\n for (;;) {\n if (fs.existsSync(current)) return current;\n const parent = path.dirname(current);\n if (parent === current) return null;\n current = parent;\n }\n}\n\n/**\n * Bytes available to an unprivileged user on the filesystem holding `dir`.\n * Returns null when the platform cannot report it.\n */\nexport function getFreeSpaceBytes(dir: string): number | null {\n const target = nearestExisting(dir);\n if (!target) return null;\n try {\n const stats = fs.statfsSync(target);\n return Number(stats.bsize) * Number(stats.bavail);\n } catch {\n return null;\n }\n}\n\n/**\n * Whether `dir` lives on a RAM-backed filesystem (`tmpfs`/`ramfs`), i.e. one whose\n * capacity comes out of memory rather than disk.\n */\nexport function isRamBackedPath(dir: string): boolean {\n const target = nearestExisting(dir);\n if (!target) return false;\n try {\n const type = Number(fs.statfsSync(target).type);\n return type === TMPFS_MAGIC || type === RAMFS_MAGIC;\n } catch {\n return false;\n }\n}\n\nexport function formatBytes(bytes: number): string {\n const units = ['B', 'KiB', 'MiB', 'GiB', 'TiB'];\n let value = Math.max(0, bytes);\n let unit = 0;\n while (value >= 1024 && unit < units.length - 1) {\n value /= 1024;\n unit++;\n }\n return `${value >= 10 || unit === 0 ? Math.round(value) : value.toFixed(1)} ${units[unit]}`;\n}\n\n/** Recognise an out-of-disk-space failure from fs/stream errors and their wrappers. */\nexport function isOutOfSpaceError(err: unknown): boolean {\n if (err instanceof InsufficientSpaceError) return true;\n const seen = new Set<unknown>();\n let current: unknown = err;\n while (current && typeof current === 'object' && !seen.has(current)) {\n seen.add(current);\n const e = current as { code?: unknown; message?: unknown; cause?: unknown };\n if (e.code === 'ENOSPC' || e.code === 'EDQUOT') return true;\n if (typeof e.message === 'string' && /ENOSPC|EDQUOT|no space left on device/i.test(e.message)) return true;\n current = e.cause;\n }\n return false;\n}\n\n/** The user-facing \"no room\" explanation, with a way out when the temp dir is to blame. */\nfunction spaceMessage(\n dir: string,\n what: string,\n opts: { requiredBytes?: number | null; freeBytes?: number | null; tmpDirHint: boolean },\n): string {\n const need = typeof opts.requiredBytes === 'number' ? `needs about ${formatBytes(opts.requiredBytes)}` : null;\n const free = typeof opts.freeBytes === 'number' ? `${formatBytes(opts.freeBytes)} available` : null;\n const amounts = [need, free].filter(Boolean).join(', ');\n\n const lines = [`Not enough free space in '${dir}' for ${what}${amounts ? ` (${amounts})` : ''}.`];\n if (isRamBackedPath(dir)) {\n lines.push(\n `'${dir}' is on a RAM-backed filesystem (tmpfs), so its capacity is limited by free memory, not by free disk.`,\n );\n }\n if (opts.tmpDirHint) lines.push(TMP_DIR_HINT);\n return lines.join('\\n');\n}\n\n/**\n * Fail before writing a byte when the filesystem holding `dir` cannot take\n * `requiredBytes`. A no-op when free space cannot be determined.\n */\nexport function ensureFreeSpace(dir: string, requiredBytes: number, what: string): void {\n if (!Number.isFinite(requiredBytes) || requiredBytes <= 0) return;\n const freeBytes = getFreeSpaceBytes(dir);\n if (freeBytes === null || freeBytes >= requiredBytes) return;\n throw new InsufficientSpaceError(\n spaceMessage(dir, what, { requiredBytes, freeBytes, tmpDirHint: true }),\n dir,\n );\n}\n\n/** The filesystem path an fs error refers to, from anywhere in its cause chain. */\nfunction errorPath(err: unknown): string | null {\n const seen = new Set<unknown>();\n let current: unknown = err;\n while (current && typeof current === 'object' && !seen.has(current)) {\n seen.add(current);\n const e = current as { path?: unknown; dest?: unknown; cause?: unknown };\n if (typeof e.path === 'string' && e.path) return e.path;\n if (typeof e.dest === 'string' && e.dest) return e.dest;\n current = e.cause;\n }\n return null;\n}\n\nfunction isInside(child: string, parent: string): boolean {\n const rel = path.relative(path.resolve(parent), path.resolve(child));\n return rel === '' || (!rel.startsWith('..') && !path.isAbsolute(rel));\n}\n\n/**\n * Convert an out-of-space failure into an {@link InsufficientSpaceError}; any other\n * error is returned unchanged, so callers can `throw toSpaceError(err, ...)`.\n *\n * `tmpRoot` is the scratch directory the operation was using. Failures under it are\n * reported against it (not the per-run subdirectory the user cannot configure) and get\n * the `--tmp-dir` remedy; failures elsewhere — an install target that is full — name\n * their own directory and skip the remedy, which would not help.\n */\nexport function toSpaceError(err: unknown, tmpRoot: string, what: string): unknown {\n if (err instanceof InsufficientSpaceError) return err;\n if (!isOutOfSpaceError(err)) return err;\n\n const failed = errorPath(err);\n const failedDir = failed ? path.dirname(path.resolve(failed)) : path.resolve(tmpRoot);\n const inTmp = isInside(failedDir, tmpRoot);\n const dir = inTmp ? path.resolve(tmpRoot) : failedDir;\n return new InsufficientSpaceError(\n spaceMessage(dir, what, { freeBytes: getFreeSpaceBytes(dir), tmpDirHint: inTmp }),\n dir,\n err,\n );\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport * as crypto from 'node:crypto';\nimport { pipeline } from 'node:stream';\nimport { promisify } from 'node:util';\nimport followRedirects from 'follow-redirects';\nimport type { ProgressReporter } from '../ports/progress.js';\nimport { CancelledError, ChecksumMismatchError, OniroError } from '../ports/errors.js';\nimport { ensureFreeSpace, isOutOfSpaceError, toSpaceError } from './tmp.js';\n\nconst { http, https } = followRedirects;\nconst pipelineAsync = promisify(pipeline);\n\nexport interface DownloadOptions {\n url: string;\n dest: string;\n progress?: ProgressReporter;\n abortSignal?: AbortSignal;\n /** Overall progress start offset (0..100). Default 0. */\n start?: number;\n /** Overall progress range to consume (0..100). Default 100. */\n range?: number;\n /** What the download is for, used in out-of-space messages. */\n what?: string;\n /**\n * Configurable scratch root that `dest` lives under, if any. Out-of-space messages\n * name it instead of the per-run subdirectory, since that is what the user can change.\n */\n tmpRoot?: string;\n}\n\n/**\n * Stream a remote file to disk with optional progress reporting and cancellation.\n * Follows redirects via the `follow-redirects` library.\n *\n * Fails fast with an `InsufficientSpaceError` when the destination filesystem cannot\n * hold the advertised `content-length` — the common case being a system temp dir on a\n * RAM-backed tmpfs that is far smaller than the SDK/tools archives.\n */\nexport async function downloadFile(opts: DownloadOptions): Promise<void> {\n const { url, dest, progress, abortSignal } = opts;\n const proto = url.startsWith('https') ? https : http;\n\n return new Promise((resolve, reject) => {\n const s = Math.max(0, Math.min(100, opts.start ?? 0));\n const r = Math.max(0, Math.min(100 - s, opts.range ?? 100));\n\n let settled = false;\n const done = (err?: unknown) => {\n if (settled) return;\n settled = true;\n err ? reject(err) : resolve();\n };\n\n if (abortSignal?.aborted) {\n done(new CancelledError('Download cancelled before start.'));\n return;\n }\n\n const destDir = path.dirname(path.resolve(dest));\n const what = opts.what ?? `the download of '${url}'`;\n\n // Out of space gets the directory-aware explanation; anything else (a bad path,\n // a permission problem) still surfaces as a typed error rather than a raw fs one.\n const writeFailed = (err: unknown): unknown =>\n isOutOfSpaceError(err)\n ? toSpaceError(err, opts.tmpRoot ?? destDir, what)\n : new OniroError(`Error writing '${dest}': ${err instanceof Error ? err.message : String(err)}`, err);\n\n const file = fs.createWriteStream(dest);\n let activeResponse: NodeJS.ReadableStream | undefined;\n\n // Settle only once the partial file is gone, so a caller that retries — or a test\n // that checks — never observes the leftover. Closing before removing keeps Windows\n // happy, where an open file cannot be deleted.\n const failWith = (err: unknown) => {\n file.close(() => fs.rm(dest, { force: true }, () => done(err)));\n };\n\n // A write-stream failure (most often ENOSPC) has no other listener; without this\n // it would surface as an unhandled 'error' event and take the process down.\n file.on('error', (err) => {\n try { (activeResponse as { destroy?: () => void } | undefined)?.destroy?.(); } catch {}\n failWith(writeFailed(err));\n });\n\n const req = proto.get(url, (response) => {\n activeResponse = response;\n if (response.statusCode !== 200) {\n try { response.destroy(); } catch {}\n failWith(new OniroError(`Failed to download '${url}' (HTTP ${response.statusCode})`));\n return;\n }\n\n const total = parseInt(response.headers['content-length'] || '0', 10);\n\n // Refuse to start rather than filling the filesystem (or RAM, on tmpfs) first.\n if (total > 0) {\n try {\n ensureFreeSpace(opts.tmpRoot ?? destDir, total, what);\n } catch (err) {\n try { response.destroy(); } catch {}\n failWith(err);\n return;\n }\n }\n\n let downloaded = 0;\n let lastOverall = Math.round(s);\n\n response.on('data', (chunk: Buffer) => {\n downloaded += chunk.length;\n if (progress && total) {\n const localPercent = Math.min(100, Math.round((downloaded / total) * 100));\n const overall = Math.min(100, Math.round(s + (downloaded / total) * r));\n const inc = overall - lastOverall;\n if (inc > 0) {\n progress.report({ message: `Downloading: ${localPercent}%`, increment: inc });\n lastOverall = overall;\n } else {\n progress.report({ message: `Downloading: ${localPercent}%`, increment: 0 });\n }\n }\n });\n\n response.pipe(file);\n\n file.on('finish', () => {\n if (progress) {\n const endOverall = Math.min(100, Math.round(s + r));\n const inc = endOverall - lastOverall;\n if (inc > 0) progress.report({ message: 'Downloading: 100%', increment: inc });\n }\n file.close((err) => (err ? done(writeFailed(err)) : done()));\n });\n\n abortSignal?.addEventListener('abort', () => {\n response.destroy();\n failWith(new CancelledError('Download cancelled.'));\n });\n });\n\n req.on('error', (err) => {\n failWith(new OniroError(`Error downloading '${url}': ${err.message}`, err));\n });\n\n abortSignal?.addEventListener('abort', () => {\n req.destroy();\n failWith(new CancelledError('Download cancelled.'));\n });\n });\n}\n\n/**\n * Verify the SHA-256 checksum of a file against an on-disk .sha256 file.\n * The .sha256 file is expected to contain the hex digest as its first whitespace-delimited token.\n */\nexport async function verifySha256(filePath: string, sha256Path: string): Promise<void> {\n const expected = fs.readFileSync(sha256Path, 'utf8').split(/\\s+/)[0]!;\n const hash = crypto.createHash('sha256');\n await pipelineAsync(fs.createReadStream(filePath), hash);\n const actual = hash.digest('hex');\n if (actual !== expected) {\n throw new ChecksumMismatchError(expected, actual);\n }\n}\n","import * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport { pipeline } from 'node:stream';\nimport { promisify } from 'node:util';\nimport * as tar from 'tar';\nimport StreamZip from 'node-stream-zip';\nimport type { ProgressReporter } from '../ports/progress.js';\nimport type { Logger } from '../ports/logger.js';\nimport { noopLogger } from '../ports/logger.js';\nimport { OniroError } from '../ports/errors.js';\n\nconst pipelineAsync = promisify(pipeline);\n\nexport interface ExtractZipOptions {\n zipPath: string;\n dest: string;\n progress?: ProgressReporter;\n /** Overall progress start offset (0..100). Default 0. */\n start?: number;\n /** Overall progress range to consume (0..100). Default 100. */\n range?: number;\n logger?: Logger;\n}\n\n/**\n * Extract a ZIP to a destination directory, preserving file permissions and following\n * symlinks defensively. Protects against Zip Slip (entries whose paths escape `dest`).\n */\nexport async function extractZipWithProgress(opts: ExtractZipOptions): Promise<void> {\n const { zipPath, dest, progress } = opts;\n const logger = opts.logger ?? noopLogger;\n\n const zip = new (StreamZip as unknown as { async: new (cfg: { file: string }) => StreamZipAsync }).async({ file: zipPath });\n const entries = await zip.entries();\n const files = Object.values(entries);\n const total = files.length || 1;\n\n const s = Math.max(0, Math.min(100, opts.start ?? 0));\n const r = Math.max(0, Math.min(100 - s, opts.range ?? 100));\n\n let processed = 0;\n let lastOverall = Math.round(s);\n\n await fs.promises.mkdir(dest, { recursive: true });\n const destRoot = path.resolve(dest);\n\n const safeResolveTarget = (entryName: string): string => {\n const resolved = path.resolve(destRoot, entryName);\n const rel = path.relative(destRoot, resolved);\n if (rel.startsWith('..') || path.isAbsolute(rel)) {\n throw new OniroError(`Blocked ZIP entry with illegal path: ${entryName}`);\n }\n return resolved;\n };\n\n try {\n for (const file of files) {\n const entryName = file.name;\n const targetPath = safeResolveTarget(entryName);\n const attr = file.attr ? (file.attr >>> 16) : 0;\n const isSymlink = 'isSymbolicLink' in file\n ? Boolean(file.isSymbolicLink)\n : (attr & 0o170000) === 0o120000;\n\n if (file.isDirectory) {\n await fs.promises.mkdir(targetPath, { recursive: true });\n } else if (isSymlink) {\n await fs.promises.mkdir(path.dirname(targetPath), { recursive: true });\n const linkTargetBuffer = await zip.entryData(file);\n const linkTarget = linkTargetBuffer.toString('utf8');\n try {\n const isWin = os.platform() === 'win32';\n await fs.promises.symlink(linkTarget, targetPath, isWin ? 'file' : undefined);\n } catch (e) {\n logger.warn(`Failed to create symlink at ${targetPath}: ${String(e)}`);\n }\n } else {\n await fs.promises.mkdir(path.dirname(targetPath), { recursive: true });\n const readStream = await zip.stream(file);\n const writeStream = fs.createWriteStream(targetPath);\n await pipelineAsync(readStream, writeStream);\n if (attr > 0) {\n try {\n await fs.promises.chmod(targetPath, attr & 0o777);\n } catch {\n // Best-effort: Windows or filesystems without POSIX perms — ignore.\n }\n }\n }\n\n processed++;\n if (progress) {\n const localPercent = Math.min(100, Math.round((processed / total) * 100));\n const overall = Math.min(100, Math.round(s + (processed / total) * r));\n const inc = overall - lastOverall;\n if (inc > 0) {\n progress.report({ message: `Extracting: ${localPercent}%`, increment: inc });\n lastOverall = overall;\n } else {\n progress.report({ message: `Extracting: ${localPercent}%`, increment: 0 });\n }\n }\n }\n } finally {\n await zip.close();\n }\n\n if (progress) {\n const endOverall = Math.min(100, Math.round(s + r));\n const inc = endOverall - lastOverall;\n if (inc > 0) progress.report({ message: 'Extracting: 100%', increment: inc });\n }\n}\n\n/**\n * Extract a tar/tar.gz/tar.bz2 archive. Wraps `tar.x`.\n */\nexport async function extractTarball(tarPath: string, dest: string, strip = 0): Promise<void> {\n await tar.x({ file: tarPath, cwd: dest, strip });\n}\n\n// node-stream-zip's TypeScript types aren't great; this is the minimal shape we use.\ninterface ZipEntry {\n name: string;\n isDirectory: boolean;\n isSymbolicLink?: boolean;\n attr?: number;\n}\ninterface StreamZipAsync {\n entries(): Promise<Record<string, ZipEntry>>;\n entryData(entry: ZipEntry): Promise<Buffer>;\n stream(entry: ZipEntry): Promise<NodeJS.ReadableStream>;\n close(): Promise<void>;\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { ALL_SDKS } from './constants.js';\nimport { getSdkRootDir } from './paths.js';\nimport { getOsFolder } from './platform.js';\nimport type { ConfigProvider } from '../ports/config.js';\n\nexport interface SdkInfo {\n version: string;\n api: string;\n installed: boolean;\n}\n\n/**\n * List supported SDKs annotated with whether they are installed for the current OS.\n * Sorted by API descending (newest first).\n */\nexport function getSupportedSdksForUi(config: ConfigProvider): SdkInfo[] {\n const base = path.join(getSdkRootDir(config), getOsFolder());\n return ALL_SDKS.map((sdk) => ({\n version: sdk.version,\n api: sdk.api,\n installed: fs.existsSync(path.join(base, sdk.api)),\n })).sort((a, b) => Number(b.api) - Number(a.api));\n}\n\n/**\n * Return the SDK versions that have at least one OS-folder install in `sdkRootDir`.\n * Scans `linux`, `darwin`, `windows` so the list is consistent across machines that\n * share an SDK root over a network mount.\n */\nexport function getInstalledSdks(config: ConfigProvider): string[] {\n const sdkRoot = getSdkRootDir(config);\n const versions = new Set<string>();\n if (!fs.existsSync(sdkRoot)) return [];\n\n for (const osFolder of ['linux', 'darwin', 'windows'] as const) {\n const osPath = path.join(sdkRoot, osFolder);\n if (!fs.existsSync(osPath) || !fs.statSync(osPath).isDirectory()) continue;\n for (const api of fs.readdirSync(osPath)) {\n const apiPath = path.join(osPath, api);\n if (fs.statSync(apiPath).isDirectory()) versions.add(api);\n }\n }\n return ALL_SDKS.filter((sdk) => versions.has(sdk.api)).map((sdk) => sdk.version);\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { getSdkRootDir } from './paths.js';\nimport type { ConfigProvider } from '../ports/config.js';\n\n/**\n * Remove an installed SDK for a given API level, across all OS folders.\n * Returns true if at least one folder was deleted.\n */\nexport function removeSdk(config: ConfigProvider, api: string): boolean {\n const sdkRoot = getSdkRootDir(config);\n let removed = false;\n for (const osFolder of ['linux', 'darwin', 'windows']) {\n const sdkPath = path.join(sdkRoot, osFolder, api);\n if (fs.existsSync(sdkPath)) {\n fs.rmSync(sdkPath, { recursive: true, force: true });\n removed = true;\n }\n }\n return removed;\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport type { ConfigProvider } from '../ports/config.js';\nimport type { ProgressReporter } from '../ports/progress.js';\nimport type { Logger } from '../ports/logger.js';\nimport { noopLogger } from '../ports/logger.js';\nimport { CancelledError, OniroError } from '../ports/errors.js';\nimport { OHOS_URL_BASE } from './constants.js';\nimport { getSdkFilename } from './platform.js';\nimport { getSdkRootDir } from './paths.js';\nimport { downloadFile, verifySha256 } from './download.js';\nimport { extractTarball, extractZipWithProgress } from './extract.js';\nimport { movePath } from './move.js';\nimport { createInstallTempDir, removeTempWorkDir, toSpaceError } from './tmp.js';\n\nexport interface InstallSdkOptions {\n config: ConfigProvider;\n version: string;\n api: string;\n progress?: ProgressReporter;\n abortSignal?: AbortSignal;\n logger?: Logger;\n /**\n * Scratch directory for the download/extract temporaries. Overrides the `tmpDir`\n * config key and the default location next to the install target.\n */\n tmpDir?: string;\n}\n\n/**\n * Download and install an OpenHarmony SDK release into `<sdkRootDir>/<osFolder>/<api>`.\n *\n * Progress budget (overall 0..100):\n * 0..35 SDK archive download\n * 35..45 Checksum download\n * 45..50 Checksum verify\n * 50..60 Tarball extract\n * 60..95 Component ZIP extracts\n * 95..100 Finalize + cleanup\n */\nexport async function downloadAndInstallSdk(opts: InstallSdkOptions): Promise<void> {\n const { config, version, api, progress, abortSignal } = opts;\n const logger = opts.logger ?? noopLogger;\n\n const { filename, osFolder, strip } = getSdkFilename(version);\n const urlBase = config.get('sdkUrlBase', OHOS_URL_BASE);\n const downloadUrl = `${urlBase}/${version}-Release/${filename}`;\n const sha256Url = `${downloadUrl}.sha256`;\n\n const what = `the SDK ${version} install`;\n const sdkRoot = getSdkRootDir(config);\n const { dir: tmpDir, root: tmpRoot } = createInstallTempDir({\n config,\n override: opts.tmpDir,\n installRoot: sdkRoot,\n prefix: 'oniro-sdk-',\n logger,\n });\n const tarPath = path.join(tmpDir, filename);\n const sha256Path = path.join(tmpDir, `${filename}.sha256`);\n const extractDir = path.join(tmpDir, 'extract');\n fs.mkdirSync(extractDir);\n\n const sdkInstallDir = path.join(sdkRoot, osFolder, api);\n fs.mkdirSync(path.dirname(sdkInstallDir), { recursive: true });\n\n const checkCancelled = () => {\n if (abortSignal?.aborted) throw new CancelledError();\n };\n\n try {\n progress?.report({ message: 'Downloading SDK archive...', increment: 0 });\n await downloadFile({ url: downloadUrl, dest: tarPath, progress, abortSignal, start: 0, range: 35, what, tmpRoot });\n\n progress?.report({ message: 'Downloading checksum...', increment: 0 });\n await downloadFile({ url: sha256Url, dest: sha256Path, progress, abortSignal, start: 35, range: 10, what, tmpRoot });\n\n progress?.report({ message: 'Verifying checksum...', increment: 0 });\n await verifySha256(tarPath, sha256Path);\n progress?.report({ message: 'Verifying checksum...', increment: 5 });\n\n checkCancelled();\n\n progress?.report({ message: 'Extracting SDK (this may take a while)...', increment: 0 });\n await extractTarball(tarPath, extractDir, strip);\n progress?.report({ message: 'Extracting SDK (this may take a while)...', increment: 10 });\n\n checkCancelled();\n\n const osContentPath = path.join(extractDir, osFolder);\n if (!fs.existsSync(osContentPath)) {\n throw new OniroError(\n `Expected folder '${osFolder}' not found in extracted SDK. Tarball layout may have changed.`,\n );\n }\n const zipFiles = fs.readdirSync(osContentPath).filter((n) => n.endsWith('.zip'));\n\n const componentsStart = 60;\n const componentsBudget = 35;\n const n = zipFiles.length;\n if (n === 0) {\n progress?.report({ message: 'No SDK component ZIPs found.', increment: componentsBudget });\n } else {\n progress?.report({ message: 'Extracting SDK components...', increment: 0 });\n }\n\n const base = n > 0 ? Math.floor(componentsBudget / n) : 0;\n let rem = n > 0 ? componentsBudget % n : 0;\n let cursor = componentsStart;\n\n for (const zipFile of zipFiles) {\n checkCancelled();\n logger.info(`Extracting component ${zipFile}`);\n const zipPath = path.join(osContentPath, zipFile);\n const thisBudget = base + (rem > 0 ? 1 : 0);\n if (rem > 0) rem--;\n await extractZipWithProgress({ zipPath, dest: osContentPath, progress, start: cursor, range: thisBudget, logger });\n cursor += thisBudget;\n fs.unlinkSync(zipPath);\n }\n\n progress?.report({ message: 'Finalizing installation...', increment: 0 });\n if (fs.existsSync(sdkInstallDir)) {\n fs.rmSync(sdkInstallDir, { recursive: true, force: true });\n }\n movePath(osContentPath, sdkInstallDir);\n progress?.report({ message: 'Finalizing installation...', increment: 3 });\n\n progress?.report({ message: 'Cleaning up...', increment: 0 });\n removeTempWorkDir(tmpDir, tmpRoot);\n progress?.report({ message: 'Cleaning up...', increment: 2 });\n } catch (err) {\n const wrapped = toSpaceError(err, tmpRoot, what);\n logger.error(`SDK install failed: ${wrapped instanceof Error ? wrapped.message : String(wrapped)}`);\n removeTempWorkDir(tmpDir, tmpRoot);\n throw wrapped;\n }\n}\n","import * as fs from 'node:fs';\n\n/**\n * Move a file or directory from `src` to `dest`.\n *\n * Prefers an atomic `rename`, but transparently falls back to a recursive\n * copy-then-remove when the two paths live on different filesystems. `rename(2)`\n * fails with `EXDEV` across mount boundaries, which happens routinely during\n * install: the OS temp dir (where archives are extracted) and the install target\n * are frequently separate devices — a `tmpfs` `/tmp` with an on-disk home, a Docker\n * volume or bind mount at the install path, an overlay vs. a mounted cache, etc.\n *\n * Callers are expected to have already cleared `dest` if it must be replaced\n * (both current callers `rmSync` first). The copy preserves file modes and\n * symlinks (Node's default `cp` behavior), which the SDK/toolchains rely on.\n */\nexport function movePath(src: string, dest: string): void {\n try {\n fs.renameSync(src, dest);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'EXDEV') throw err;\n // Cross-device move: copy the tree, then drop the source.\n fs.cpSync(src, dest, { recursive: true });\n fs.rmSync(src, { recursive: true, force: true });\n }\n}\n","import * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport { execFileSync } from 'node:child_process';\nimport type { ConfigProvider } from '../ports/config.js';\nimport { defaultPaths } from '../ports/config.js';\nimport type { ProgressReporter } from '../ports/progress.js';\nimport type { Logger } from '../ports/logger.js';\nimport { noopLogger } from '../ports/logger.js';\nimport { OniroError, UnsupportedPlatformError } from '../ports/errors.js';\nimport { getCmdToolsPath } from '../sdk/paths.js';\nimport { downloadFile } from '../sdk/download.js';\nimport { extractZipWithProgress } from '../sdk/extract.js';\nimport { movePath } from '../sdk/move.js';\nimport { createInstallTempDir, removeTempWorkDir, toSpaceError } from '../sdk/tmp.js';\n\n/**\n * Resolve the per-platform download URL for the OpenHarmony command-line tools.\n *\n * Only Linux has a public download URL on the Huawei mirror. Windows and macOS\n * builds are gated behind the Huawei developer portal: users must download the\n * ZIP manually and pass it via `--from-zip`, or self-host the archive and point\n * `cmdToolsUrlWindows` / `cmdToolsUrlMac` at it.\n *\n * @param platform Defaults to the current host. Override for testing.\n */\nexport function getCmdToolsDownloadUrl(config: ConfigProvider, platform: NodeJS.Platform = os.platform()): string {\n if (platform === 'linux') {\n return config.get('cmdToolsUrlLinux', defaultPaths.cmdToolsUrlLinux);\n }\n if (platform === 'win32') {\n const url = config.get('cmdToolsUrlWindows', '');\n if (!url) {\n throw new OniroError(\n 'No Windows command-line tools URL configured. The Huawei mirror does not host a public Windows build; ' +\n 'download the ZIP from the Huawei developer portal and run `oniro-app cmdtools install --from-zip <path>`, ' +\n 'or set ONIRO_CMD_TOOLS_URL_WINDOWS to a self-hosted URL.',\n );\n }\n return url;\n }\n if (platform === 'darwin') {\n const url = config.get('cmdToolsUrlMac', '');\n if (!url) {\n throw new OniroError(\n 'No macOS command-line tools URL configured. The Huawei mirror does not host a public macOS build; ' +\n 'download the ZIP from the Huawei developer portal and run `oniro-app cmdtools install --from-zip <path>`, ' +\n 'or set ONIRO_CMD_TOOLS_URL_MAC to a self-hosted URL.',\n );\n }\n return url;\n }\n throw new UnsupportedPlatformError(platform);\n}\n\n/**\n * Locate the extracted command-line tools' source root within a temp extraction folder.\n * Tries known top-level names, then any subdirectory containing a `bin/` folder.\n */\nexport function findCmdToolsSourceDir(extractPath: string): string {\n const known = [\n path.join(extractPath, 'command-line-tools'),\n path.join(extractPath, 'oh-command-line-tools'),\n path.join(extractPath, 'commandline-tools'),\n ];\n for (const c of known) {\n if (fs.existsSync(c)) return c;\n }\n const entries = fs\n .readdirSync(extractPath, { withFileTypes: true })\n .filter((e) => e.isDirectory())\n .map((e) => path.join(extractPath, e.name));\n for (const dir of entries) {\n if (fs.existsSync(path.join(dir, 'bin'))) return dir;\n }\n throw new OniroError('Could not locate command line tools folder in the extracted archive.');\n}\n\nexport interface InstallCmdToolsOptions {\n config: ConfigProvider;\n progress?: ProgressReporter;\n abortSignal?: AbortSignal;\n logger?: Logger;\n /** Skip download and install from a local zip the caller already has. */\n localZipPath?: string;\n /**\n * Scratch directory for the download/extract temporaries. Overrides the `tmpDir`\n * config key and the default location next to the install target.\n */\n tmpDir?: string;\n}\n\n/**\n * Install the OpenHarmony command-line tools into `<cmdToolsPath>`.\n * Either downloads from the platform-specific URL or installs from a caller-supplied ZIP.\n */\nexport async function installCmdTools(opts: InstallCmdToolsOptions): Promise<void> {\n const { config, progress, abortSignal } = opts;\n const logger = opts.logger ?? noopLogger;\n const CMD_PATH = getCmdToolsPath(config);\n const what = 'the command-line tools install';\n\n const { dir: tmpDir, root: tmpRoot } = createInstallTempDir({\n config,\n override: opts.tmpDir,\n installRoot: path.dirname(CMD_PATH),\n prefix: 'oniro-cmdtools-',\n logger,\n });\n const zipPath = opts.localZipPath ?? path.join(tmpDir, 'oh-command-line-tools.zip');\n const extractPath = path.join(tmpDir, 'oh-command-line-tools');\n\n try {\n if (!opts.localZipPath) {\n const url = getCmdToolsDownloadUrl(config);\n progress?.report({ message: 'Downloading command line tools...', increment: 0 });\n await downloadFile({ url, dest: zipPath, progress, abortSignal, start: 0, range: 50, what, tmpRoot });\n }\n\n progress?.report({ message: 'Extracting tools...', increment: 0 });\n await extractZipWithProgress({ zipPath, dest: extractPath, progress, start: 50, range: 45, logger });\n\n fs.mkdirSync(CMD_PATH, { recursive: true });\n const srcDir = findCmdToolsSourceDir(extractPath);\n\n for (const entry of fs.readdirSync(srcDir)) {\n const src = path.join(srcDir, entry);\n const dest = path.join(CMD_PATH, entry);\n if (fs.statSync(src).isDirectory()) {\n if (fs.existsSync(dest)) fs.rmSync(dest, { recursive: true, force: true });\n movePath(src, dest);\n } else {\n fs.copyFileSync(src, dest);\n }\n }\n\n const binDir = path.join(CMD_PATH, 'bin');\n if (fs.existsSync(binDir) && os.platform() !== 'win32') {\n for (const file of fs.readdirSync(binDir)) {\n fs.chmodSync(path.join(binDir, file), 0o755);\n }\n }\n\n progress?.report({ message: 'Finalizing installation...', increment: 5 });\n progress?.report({ message: 'Cleaning up...', increment: 0 });\n } catch (err) {\n throw toSpaceError(err, tmpRoot, what);\n } finally {\n removeTempWorkDir(tmpDir, tmpRoot);\n }\n}\n\nexport interface CmdToolsStatus {\n installed: boolean;\n status: string;\n}\n\n/**\n * Reports whether ohpm is present at the configured path, and if so its version.\n * Prefers reading `version.txt` (`# Version: x.y.z`) before falling back to executing\n * the binary with `-v`.\n */\nexport function getCmdToolsStatus(config: ConfigProvider): CmdToolsStatus {\n const cmdPath = getCmdToolsPath(config);\n const binDir = path.join(cmdPath, 'bin');\n const candidates = os.platform() === 'win32'\n ? ['ohpm.exe', 'ohpm.cmd', 'ohpm.bat', 'ohpm']\n : ['ohpm'];\n const bin = candidates.map((c) => path.join(binDir, c)).find((p) => fs.existsSync(p));\n if (!bin) {\n return { installed: false, status: 'Not installed' };\n }\n\n // Prefer version.txt.\n try {\n const versionFile = path.join(cmdPath, 'version.txt');\n if (fs.existsSync(versionFile)) {\n const content = fs.readFileSync(versionFile, 'utf8');\n for (const line of content.split(/\\r?\\n/)) {\n const m = line.match(/^\\s*#\\s*Version:\\s*(.+)$/);\n if (m?.[1]) return { installed: true, status: `Installed (${m[1].trim()})` };\n }\n }\n } catch {\n // Fall through to exec.\n }\n\n try {\n const version = execFileSync(bin, ['-v'], { encoding: 'utf8' }).trim();\n return { installed: true, status: `Installed (${version})` };\n } catch {\n return { installed: true, status: 'Installed (version unknown)' };\n }\n}\n\nexport function isCmdToolsInstalled(config: ConfigProvider): boolean {\n return getCmdToolsStatus(config).installed;\n}\n\nexport function removeCmdTools(config: ConfigProvider): void {\n const cmdPath = getCmdToolsPath(config);\n if (fs.existsSync(cmdPath)) {\n fs.rmSync(cmdPath, { recursive: true, force: true });\n }\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport * as crypto from 'node:crypto';\n\nconst DAEMON_ROOT_KEY_COMPONENT_LENGTH = 16;\nconst DAEMON_SALT_KEY_LENGTH = 16;\nconst DAEMON_WORK_KEY_LENGTH = 16;\nconst KEY_FILE_DIRECTORY_PERMISSIONS = 0o755;\nconst KEY_FILE_PERMISSIONS = 0o600;\n\nconst COMPONENT = Buffer.from([\n 49, 243, 9, 115, 214, 175, 91, 184, 211, 190, 177, 88, 101, 131, 192, 119,\n]);\n\n/**\n * Encrypts data using AES-128-GCM.\n * Output layout: [4-byte BE length][12-byte IV][ciphertext][16-byte auth tag].\n */\nfunction encrypt(key: Buffer, data: Buffer): Buffer {\n const iv = crypto.randomBytes(12);\n const cipher = crypto.createCipheriv('aes-128-gcm', key, iv);\n const ciphertext = Buffer.concat([cipher.update(data), cipher.final()]);\n const authTag = cipher.getAuthTag();\n const totalLength = ciphertext.length + authTag.length;\n const out = Buffer.alloc(4 + iv.length + ciphertext.length + authTag.length);\n out.writeUInt32BE(totalLength, 0);\n iv.copy(out, 4);\n ciphertext.copy(out, 16);\n authTag.copy(out, 16 + ciphertext.length);\n return out;\n}\n\nfunction decrypt(key: Buffer, data: Buffer): Buffer {\n const totalLength = data.readUInt32BE(0);\n const iv = data.subarray(4, 16);\n const ciphertextLength = totalLength - 16;\n const ciphertext = data.subarray(16, 16 + ciphertextLength);\n const authTag = data.subarray(16 + ciphertextLength);\n const decipher = crypto.createDecipheriv('aes-128-gcm', key, iv);\n decipher.setAuthTag(authTag);\n return Buffer.concat([decipher.update(ciphertext), decipher.final()]);\n}\n\nfunction xorBuffers(buffers: Buffer[]): Buffer {\n if (buffers.length === 0) {\n throw new Error('No buffers provided for XOR.');\n }\n const result = Buffer.from(buffers[0]!);\n for (let i = 1; i < buffers.length; i++) {\n const buf = buffers[i]!;\n if (buf.length !== result.length) {\n throw new Error('Buffers have different lengths in XOR.');\n }\n for (let j = 0; j < result.length; j++) {\n result[j] = result[j]! ^ buf[j]!;\n }\n }\n return result;\n}\n\nfunction getRootKey(fdComponents: Buffer[], salt: Buffer): Buffer {\n const components = fdComponents.concat([COMPONENT]);\n const xored = xorBuffers(components);\n return crypto.pbkdf2Sync(xored.toString(), salt, 10000, 16, 'sha256');\n}\n\nfunction createAndStoreKey(dir: string, keyLength: number): Buffer {\n const key = crypto.randomBytes(keyLength);\n const hash = crypto.createHash('sha256').update(key).digest('hex');\n const filePath = path.join(dir, hash);\n fs.writeFileSync(filePath, key);\n fs.chmodSync(filePath, KEY_FILE_PERMISSIONS);\n return key;\n}\n\nfunction createAndStoreEnKey(rootKey: Buffer, ceDir: string): void {\n const workKey = crypto.randomBytes(DAEMON_WORK_KEY_LENGTH);\n const encrypted = encrypt(rootKey, workKey);\n const hash = crypto.createHash('sha256').update(encrypted).digest('hex');\n const filePath = path.join(ceDir, hash);\n fs.writeFileSync(filePath, encrypted);\n fs.chmodSync(filePath, KEY_FILE_PERMISSIONS);\n}\n\n/**\n * Generates the signing-material directory tree: fd/{0,1,2}, ac, ce.\n * Each subfolder contains a randomly-named keyfile derived as described in\n * the OpenHarmony hap-sign-tool reference implementation.\n */\nexport function createMaterial(materialPath: string): void {\n fs.mkdirSync(materialPath, { recursive: true });\n fs.chmodSync(materialPath, KEY_FILE_DIRECTORY_PERMISSIONS);\n\n const fdDir = path.join(materialPath, 'fd');\n const acDir = path.join(materialPath, 'ac');\n const ceDir = path.join(materialPath, 'ce');\n\n fs.mkdirSync(fdDir, { recursive: true });\n fs.mkdirSync(acDir, { recursive: true });\n fs.mkdirSync(ceDir, { recursive: true });\n\n const fdSubDirs = ['0', '1', '2'];\n const fdComponents: Buffer[] = [];\n for (const sub of fdSubDirs) {\n const subDir = path.join(fdDir, sub);\n fs.mkdirSync(subDir, { recursive: true });\n const comp = createAndStoreKey(subDir, DAEMON_ROOT_KEY_COMPONENT_LENGTH);\n fdComponents.push(comp);\n }\n\n const salt = createAndStoreKey(acDir, DAEMON_SALT_KEY_LENGTH);\n const rootKey = getRootKey(fdComponents, salt);\n createAndStoreEnKey(rootKey, ceDir);\n}\n\nfunction readSingleFile(dir: string): Buffer {\n if (!fs.existsSync(dir) || !fs.statSync(dir).isDirectory()) {\n throw new Error(`Missing signing material directory: ${dir}`);\n }\n const files = fs.readdirSync(dir).filter((f) => f !== '.DS_Store');\n if (files.length !== 1) {\n throw new Error(`Signing material in ${dir} is illegal (expected exactly one file).`);\n }\n return fs.readFileSync(path.join(dir, files[0]!));\n}\n\n/**\n * Re-derives the work key from an existing material directory.\n */\nexport function getKey(materialPath: string): Buffer {\n if (!fs.existsSync(materialPath) || !fs.statSync(materialPath).isDirectory()) {\n throw new Error('Material directory does not exist.');\n }\n\n const fdDir = path.join(materialPath, 'fd');\n const fdComponents = ['0', '1', '2'].map((sub) => readSingleFile(path.join(fdDir, sub)));\n const salt = readSingleFile(path.join(materialPath, 'ac'));\n const rootKey = getRootKey(fdComponents, salt);\n const workMaterial = readSingleFile(path.join(materialPath, 'ce'));\n return decrypt(rootKey, workMaterial);\n}\n\n/**\n * Encrypts a password using the work key derived from `materialPath`.\n * Returns the encrypted blob as a hex string (the format expected in build-profile.json5).\n */\nexport function encryptPwd(password: string, materialPath: string): string {\n const key = getKey(materialPath);\n const pwdBuffer = Buffer.from(password, 'utf-8');\n return encrypt(key, pwdBuffer).toString('hex');\n}\n\n/**\n * Inverse of `encryptPwd`. Exposed for parity with the original CLI.\n */\nexport function decryptPwd(encryptedHex: string, materialPath: string): string {\n const key = getKey(materialPath);\n const encryptedBuffer = Buffer.from(encryptedHex, 'hex');\n return decrypt(key, encryptedBuffer).toString('utf-8');\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { execFileSync } from 'node:child_process';\nimport JSON5 from 'json5';\nimport { encryptPwd, createMaterial } from './encryptKey.js';\nimport { OPEN_HARMONY_APPLICATION_CERT } from './applicationCert.js';\nimport { detectProjectSdkVersion } from '../sdk/detectProjectSdk.js';\nimport type { Logger } from '../ports/logger.js';\nimport { noopLogger } from '../ports/logger.js';\nimport { OniroError } from '../ports/errors.js';\n\n/** Ability Privilege Level written into the profile's `bundle-info.apl`. */\nexport type Apl = 'normal' | 'system_basic' | 'system_core';\n\n/** App feature written into the profile's `bundle-info.app-feature`. */\nexport type AppFeature = 'hos_normal_app' | 'hos_system_app';\n\nexport const APL_VALUES: readonly Apl[] = ['normal', 'system_basic', 'system_core'];\nexport const APP_FEATURE_VALUES: readonly AppFeature[] = ['hos_normal_app', 'hos_system_app'];\n\n/** Keystore passwords. These must match the keystore in use. */\nexport interface SigningPasswords {\n store: string;\n key: string;\n}\n\nconst DEFAULT_PASSWORDS: SigningPasswords = { store: '123456', key: '123456' };\n\n/**\n * Which signing key pairs with the chosen `apl`.\n *\n * - `'profile-release'` — the **OpenHarmony Application Profile Release** key.\n * Default for apl=normal. Matches the cert chain that ships with the SDK\n * (`OpenHarmonyProfileRelease.pem`). What `hvigor` uses for ordinary apps.\n *\n * - `'application-release'` — the **OpenHarmony Application Release** key.\n * Required for apl=system_basic|system_core. BMS's parse-profile-prop check\n * rejects HAPs whose `distribution-certificate` subject is \"Application\n * Profile Release\" when the HAP requests permissions above its apl. The\n * matching cert chain (`OpenHarmonyApplication.cer`) is not shipped in the\n * SDK, so we ship it ourselves under `applicationCert.ts`.\n */\nexport type SigningKind = 'profile-release' | 'application-release';\n\n/** @internal exposed for tests. */\nexport function pickSigningKind(apl: Apl): SigningKind {\n return apl === 'normal' ? 'profile-release' : 'application-release';\n}\n\ninterface SigningKindConfig {\n /** keystore alias used by hvigor's SignHap task. */\n hapKeyAlias: string;\n /** filename of the cert chain inside `signatures/` referenced by build-profile.json5 `certpath`. */\n certBasename: string;\n}\n\nconst SIGNING_KIND_CONFIG: Record<SigningKind, SigningKindConfig> = {\n 'profile-release': {\n hapKeyAlias: 'openharmony application profile release',\n certBasename: 'OpenHarmonyProfileRelease.pem',\n },\n 'application-release': {\n hapKeyAlias: 'OpenHarmony Application Release',\n certBasename: 'OpenHarmonyApplication.cer',\n },\n};\n\nexport interface GenerateSigningConfigsOptions {\n /** Absolute path to the OpenHarmony project (the folder containing build-profile.json5). */\n projectDir: string;\n /** Absolute path to the OS-specific SDK home (the folder containing API-version subfolders). */\n sdkHome: string;\n /**\n * APL level to write into the profile's `bundle-info.apl`. Defaults to `'normal'`.\n * Apps requesting permissions above `normal` (e.g. `ohos.permission.GET_WIFI_INFO_INTERNAL`)\n * need `system_basic` or `system_core` — otherwise `bm install` fails with\n * `grant request permissions failed`.\n */\n apl?: Apl;\n /**\n * App feature to write into `bundle-info.app-feature`. Defaults to `'hos_normal_app'`\n * when `apl='normal'`, otherwise `'hos_system_app'`.\n */\n appFeature?: AppFeature;\n /**\n * Permission names to write into the profile's `acls.allowed-acls`. Required for\n * apps that request permissions above their `apl` (e.g. a system_basic app\n * requesting `ohos.permission.CAPTURE_SCREEN`). When omitted, the template's\n * existing `allowed-acls` is left alone.\n */\n acls?: string[];\n /**\n * Keystore passwords written into the profile sign step and the build-profile\n * signingConfigs. Defaults to `'123456'` (the SDK's bundled OpenHarmony.p12\n * password). Only override when supplying a matching custom keystore.\n */\n passwords?: SigningPasswords;\n /**\n * Override the bundled application cert chain (application-release kind only).\n * When set, this file is copied to `signatures/OpenHarmonyApplication.cer`\n * instead of the inlined cert. May also be sourced from `config.applicationCertPath`.\n */\n applicationCertPath?: string;\n /** Optional logger; defaults to no-op. */\n logger?: Logger;\n}\n\nfunction copyFilesToProject(\n projectDir: string,\n paths: { keystore: string; profileCert: string; unsignedProfileTemplate: string },\n kind: SigningKind,\n logger: Logger,\n applicationCertPath?: string,\n): void {\n logger.info('[sign] Copying signing material into project...');\n const signaturesDir = path.join(projectDir, 'signatures');\n fs.mkdirSync(signaturesDir, { recursive: true });\n\n fs.copyFileSync(paths.keystore, path.join(signaturesDir, 'OpenHarmony.p12'));\n fs.copyFileSync(paths.profileCert, path.join(signaturesDir, 'OpenHarmonyProfileRelease.pem'));\n fs.copyFileSync(paths.unsignedProfileTemplate, path.join(signaturesDir, 'UnsgnedReleasedProfileTemplate.json'));\n\n if (kind === 'application-release') {\n const dest = path.join(signaturesDir, 'OpenHarmonyApplication.cer');\n if (applicationCertPath) {\n fs.copyFileSync(applicationCertPath, dest);\n } else {\n fs.writeFileSync(dest, OPEN_HARMONY_APPLICATION_CERT);\n }\n }\n}\n\n/**\n * Pick the app-feature value: explicit override wins; otherwise `hos_normal_app` for\n * apl=normal, `hos_system_app` for system_basic/system_core.\n * @internal exposed for tests.\n */\nexport function resolveAppFeature(apl: Apl, override?: AppFeature): AppFeature {\n if (override) return override;\n return apl === 'normal' ? 'hos_normal_app' : 'hos_system_app';\n}\n\n/**\n * Read the third certificate (the leaf) from a 3-cert PEM chain. The chain is\n * stored root → intermediate → leaf, so the distribution-certificate we want\n * is the third block.\n */\nfunction extractLeafCertificate(chainPath: string): string {\n const certContent = fs.readFileSync(chainPath, 'utf-8');\n const parts = certContent.split('-----END CERTIFICATE-----');\n if (parts.length < 3) {\n throw new OniroError(`${chainPath} does not contain enough certificates.`);\n }\n return parts[2]!.trim() + '\\n-----END CERTIFICATE-----\\n';\n}\n\n/** @internal exposed for tests. */\nexport function modifyProfileTemplate(\n projectDir: string,\n apl: Apl,\n appFeature: AppFeature,\n logger: Logger,\n options: { kind?: SigningKind; acls?: string[] } = {},\n): void {\n const kind = options.kind ?? pickSigningKind(apl);\n logger.info(`[sign] Modifying profile template (apl=${apl}, app-feature=${appFeature}, kind=${kind})...`);\n const appJsonPath = path.join(projectDir, 'AppScope/app.json5');\n const profileTemplatePath = path.join(projectDir, 'signatures/UnsgnedReleasedProfileTemplate.json');\n\n if (!fs.existsSync(appJsonPath)) {\n throw new OniroError(`${appJsonPath} does not exist.`);\n }\n\n let appJson: { app?: { bundleName?: string } };\n try {\n appJson = JSON5.parse(fs.readFileSync(appJsonPath, 'utf-8'));\n } catch (e) {\n throw new OniroError(`Error parsing ${appJsonPath}: ${(e as Error).message}`, e);\n }\n\n let profileTemplate: {\n 'bundle-info'?: {\n 'bundle-name'?: string;\n 'distribution-certificate'?: string;\n apl?: string;\n 'app-feature'?: string;\n };\n acls?: { 'allowed-acls'?: string[] };\n };\n try {\n profileTemplate = JSON.parse(fs.readFileSync(profileTemplatePath, 'utf-8'));\n } catch (e) {\n throw new OniroError(`Error parsing ${profileTemplatePath}: ${(e as Error).message}`, e);\n }\n\n if (!appJson.app?.bundleName) {\n throw new OniroError('app.json5 does not contain app.bundleName.');\n }\n if (!profileTemplate['bundle-info']) {\n throw new OniroError('UnsgnedReleasedProfileTemplate.json is missing the bundle-info section.');\n }\n\n profileTemplate['bundle-info']['bundle-name'] = appJson.app.bundleName;\n profileTemplate['bundle-info']['apl'] = apl;\n profileTemplate['bundle-info']['app-feature'] = appFeature;\n\n const distCertChainPath = path.join(\n projectDir,\n 'signatures',\n SIGNING_KIND_CONFIG[kind].certBasename,\n );\n profileTemplate['bundle-info']['distribution-certificate'] = extractLeafCertificate(distCertChainPath);\n\n if (options.acls !== undefined) {\n profileTemplate.acls = profileTemplate.acls ?? {};\n profileTemplate.acls['allowed-acls'] = options.acls;\n }\n\n fs.writeFileSync(profileTemplatePath, JSON.stringify(profileTemplate, null, 2));\n}\n\nfunction generateP7bFile(\n projectDir: string,\n paths: { signTool: string; profileCert: string; keystore: string },\n logger: Logger,\n passwords: SigningPasswords,\n): void {\n logger.info('[sign] Generating P7b profile via hap-sign-tool...');\n const signaturesDir = path.join(projectDir, 'signatures');\n const profileTemplatePath = path.join(signaturesDir, 'UnsgnedReleasedProfileTemplate.json');\n const outputProfilePath = path.join(signaturesDir, 'app1-profile.p7b');\n\n // The profile itself is always signed by the Profile Release key, regardless\n // of the HAP signing kind. The profile's `distribution-certificate` field\n // (set by modifyProfileTemplate) is what tells BMS which cert will sign the HAP.\n const args = [\n '-jar', paths.signTool,\n 'sign-profile',\n '-keyAlias', 'openharmony application profile release',\n '-signAlg', 'SHA256withECDSA',\n '-mode', 'localSign',\n '-profileCertFile', paths.profileCert,\n '-inFile', profileTemplatePath,\n '-keystoreFile', paths.keystore,\n '-outFile', outputProfilePath,\n '-keyPwd', passwords.key,\n '-keystorePwd', passwords.store,\n ];\n\n try {\n execFileSync('java', args, { stdio: 'inherit' });\n } catch (e) {\n throw new OniroError(\n `hap-sign-tool failed. Ensure a JDK (with keytool/java) is on PATH. Underlying error: ${(e as Error).message}`,\n e,\n );\n }\n}\n\n/**\n * Read all `products[*].signingConfig` names from the project's build-profile.json5.\n * Returns the unique names in declaration order. Falls back to `['default']` when\n * the file is missing or has no products.\n * @internal exposed for tests.\n */\nexport function detectSigningConfigNames(projectDir: string): string[] {\n const buildProfilePath = path.join(projectDir, 'build-profile.json5');\n if (!fs.existsSync(buildProfilePath)) return ['default'];\n\n let parsed: { app?: { products?: Array<{ signingConfig?: unknown }> } };\n try {\n parsed = JSON5.parse(fs.readFileSync(buildProfilePath, 'utf-8'));\n } catch {\n return ['default'];\n }\n\n const products = parsed.app?.products;\n if (!Array.isArray(products) || products.length === 0) return ['default'];\n\n const names: string[] = [];\n for (const product of products) {\n const name = product.signingConfig;\n if (typeof name === 'string' && name.length > 0 && !names.includes(name)) {\n names.push(name);\n }\n }\n return names.length > 0 ? names : ['default'];\n}\n\nfunction updateBuildProfile(projectDir: string, kind: SigningKind, logger: Logger, passwords: SigningPasswords): void {\n logger.info('[sign] Writing signing configs into build-profile.json5...');\n const materialDir = path.join(projectDir, 'signatures', 'material');\n const buildProfilePath = path.join(projectDir, 'build-profile.json5');\n\n const encryptedStorePassword = encryptPwd(passwords.store, materialDir);\n const encryptedKeyPassword = encryptPwd(passwords.key, materialDir);\n\n let buildProfile: { app?: { signingConfigs?: unknown[] } } = { app: {} };\n if (fs.existsSync(buildProfilePath)) {\n try {\n buildProfile = JSON5.parse(fs.readFileSync(buildProfilePath, 'utf-8'));\n } catch (e) {\n throw new OniroError(`Error parsing ${buildProfilePath}: ${(e as Error).message}`, e);\n }\n }\n\n const { hapKeyAlias, certBasename } = SIGNING_KIND_CONFIG[kind];\n const configNames = detectSigningConfigNames(projectDir);\n logger.info(`[sign] Writing signingConfigs entries: ${configNames.join(', ')}`);\n\n buildProfile.app = buildProfile.app ?? {};\n buildProfile.app.signingConfigs = configNames.map((name) => ({\n name,\n material: {\n certpath: `./signatures/${certBasename}`,\n storePassword: encryptedStorePassword,\n keyAlias: hapKeyAlias,\n keyPassword: encryptedKeyPassword,\n profile: './signatures/app1-profile.p7b',\n signAlg: 'SHA256withECDSA',\n storeFile: './signatures/OpenHarmony.p12',\n },\n }));\n\n // Intentionally strict JSON (not JSON5) — keeps the file readable by VS Code's JSON parser.\n fs.writeFileSync(buildProfilePath, JSON.stringify(buildProfile, null, 2));\n}\n\nfunction prepareMaterialDirectory(projectDir: string, logger: Logger): void {\n logger.info('[sign] Generating fresh signing material...');\n const materialDir = path.join(projectDir, 'signatures', 'material');\n if (fs.existsSync(materialDir)) {\n fs.rmSync(materialDir, { recursive: true, force: true });\n }\n createMaterial(materialDir);\n}\n\n/**\n * Generate signing configs for an OpenHarmony project: copies certs, signs the profile,\n * generates the signing material, and writes the resulting `signingConfigs` entry into\n * `build-profile.json5`.\n *\n * Requires `java` on PATH (the OpenHarmony hap-sign-tool ships as a .jar).\n */\nexport function generateSigningConfigs(options: GenerateSigningConfigsOptions): void {\n const { projectDir, sdkHome } = options;\n const logger = options.logger ?? noopLogger;\n const apl: Apl = options.apl ?? 'normal';\n if (!APL_VALUES.includes(apl)) {\n throw new OniroError(`Invalid apl '${apl}'. Expected one of: ${APL_VALUES.join(', ')}.`);\n }\n const appFeature: AppFeature = resolveAppFeature(apl, options.appFeature);\n if (!APP_FEATURE_VALUES.includes(appFeature)) {\n throw new OniroError(\n `Invalid appFeature '${appFeature}'. Expected one of: ${APP_FEATURE_VALUES.join(', ')}.`,\n );\n }\n\n const sdkVersion = detectProjectSdkVersion(projectDir, logger);\n if (!sdkVersion) {\n throw new OniroError(\n 'Could not detect project SDK version (compileSdkVersion missing in build-profile.json5).',\n );\n }\n\n const sdkPath = path.join(sdkHome, String(sdkVersion));\n if (!fs.existsSync(sdkPath)) {\n throw new OniroError(`SDK path does not exist: ${sdkPath}`);\n }\n\n const paths = {\n signTool: path.join(sdkPath, 'toolchains/lib/hap-sign-tool.jar'),\n keystore: path.join(sdkPath, 'toolchains/lib/OpenHarmony.p12'),\n profileCert: path.join(sdkPath, 'toolchains/lib/OpenHarmonyProfileRelease.pem'),\n unsignedProfileTemplate: path.join(sdkPath, 'toolchains/lib/UnsgnedReleasedProfileTemplate.json'),\n };\n\n const kind = pickSigningKind(apl);\n const passwords = options.passwords ?? DEFAULT_PASSWORDS;\n\n logger.info('[sign] Starting signing configuration generation...');\n copyFilesToProject(projectDir, paths, kind, logger, options.applicationCertPath);\n modifyProfileTemplate(projectDir, apl, appFeature, logger, { kind, acls: options.acls });\n generateP7bFile(projectDir, paths, logger, passwords);\n prepareMaterialDirectory(projectDir, logger);\n updateBuildProfile(projectDir, kind, logger, passwords);\n logger.info('[sign] Signing configuration generated successfully.');\n}\n","/**\n * PEM-encoded certificate chain for the OpenHarmony Application Release key.\n *\n * Root-CA → Application-CA → Application-Release leaf. This is the public\n * OpenHarmony test PKI that ships with system app source trees (e.g.\n * `applications/standard/launcher/signature/OpenHarmonyApplication.cer`). It\n * pairs with the private key stored under alias `OpenHarmony Application Release`\n * in the SDK's `OpenHarmony.p12` keystore.\n *\n * Used to sign HAPs that request privileged permissions (apl >= system_basic).\n * For apl=normal the existing `OpenHarmonyProfileRelease.pem` chain — already\n * shipped in the SDK — is used instead.\n */\nexport const OPEN_HARMONY_APPLICATION_CERT = `-----BEGIN CERTIFICATE-----\nMIICRDCCAcmgAwIBAgIED+E4izAMBggqhkjOPQQDAwUAMGgxCzAJBgNVBAYTAkNO\nMRQwEgYDVQQKEwtPcGVuSGFybW9ueTEZMBcGA1UECxMQT3Blbkhhcm1vbnkgVGVh\nbTEoMCYGA1UEAxMfT3Blbkhhcm1vbnkgQXBwbGljYXRpb24gUm9vdCBDQTAeFw0y\nMTAyMDIxMjE0MThaFw00OTEyMzExMjE0MThaMGgxCzAJBgNVBAYTAkNOMRQwEgYD\nVQQKEwtPcGVuSGFybW9ueTEZMBcGA1UECxMQT3Blbkhhcm1vbnkgVGVhbTEoMCYG\nA1UEAxMfT3Blbkhhcm1vbnkgQXBwbGljYXRpb24gUm9vdCBDQTB2MBAGByqGSM49\nAgEGBSuBBAAiA2IABE023XmRaw2DnO8NSsb+KG/uY0FtS3u5LQucdr3qWVnRW5ui\nQIL6ttNZBEeLTUeYcJZCpayg9Llf+1SmDA7dY4iP2EcRo4UN3rilovtfFfsmH4ty\n3SApHVFzWUl+NwdH8KNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC\nAQYwHQYDVR0OBBYEFBc6EKGrGXzlAE+s0Zgnsphadw7NMAwGCCqGSM49BAMDBQAD\nZwAwZAIwd1p3JzHN93eoPped1li0j64npgqNzwy4OrkehYAqNXpcpaEcLZ7UxW8E\nI2lZJ3SbAjAkqySHb12sIwdSFKSN9KCMMEo/eUT5dUXlcKR2nZz0MJdxT5F51qcX\n1CumzkcYhgU=\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICYTCCAeWgAwIBAgIEHmXAPTAMBggqhkjOPQQDAwUAMGgxCzAJBgNVBAYTAkNO\nMRQwEgYDVQQKEwtPcGVuSGFybW9ueTEZMBcGA1UECxMQT3Blbkhhcm1vbnkgVGVh\nbTEoMCYGA1UEAxMfT3Blbkhhcm1vbnkgQXBwbGljYXRpb24gUm9vdCBDQTAeFw0y\nMTAyMDIxMjE1MzJaFw00OTEyMzExMjE1MzJaMGMxCzAJBgNVBAYTAkNOMRQwEgYD\nVQQKEwtPcGVuSGFybW9ueTEZMBcGA1UECxMQT3Blbkhhcm1vbnkgVGVhbTEjMCEG\nA1UEAxMaT3Blbkhhcm1vbnkgQXBwbGljYXRpb24gQ0EwdjAQBgcqhkjOPQIBBgUr\ngQQAIgNiAAQhnu7Hna8XNa2KyqRf5+lBJScE4xqf89N0g0OuqAb2re8nGsvWkw26\nuDekfnBYicd+G3Cydqa2zFIwV7Talyg2ULW3r8KbGpyl84mJEPPRmCGJ+H9gtCsf\n+OrJ4Y76LVWjYzBhMB8GA1UdIwQYMBaAFBc6EKGrGXzlAE+s0Zgnsphadw7NMA8G\nA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTbhrciFtUL\noUu33SV7ufEFfaItRzAMBggqhkjOPQQDAwUAA2gAMGUCMG3cXjiDmXTvf7D4Omhf\nqcc2nuO+EMfWE+N9ZhBP5UhV34mAGWi3SfLU6rcV0urWEQIxAMYIb3epOnKhUrcm\nLfu1WKzFlpYQwmw73RaCHP2I3k6NcuWOYeNwWXSNZ8o0nzvaLg==\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICMzCCAbegAwIBAgIEaOC/zDAMBggqhkjOPQQDAwUAMGMxCzAJBgNVBAYTAkNO\nMRQwEgYDVQQKEwtPcGVuSGFybW9ueTEZMBcGA1UECxMQT3Blbkhhcm1vbnkgVGVh\nbTEjMCEGA1UEAxMaT3Blbkhhcm1vbnkgQXBwbGljYXRpb24gQ0EwHhcNMjEwMjAy\nMTIxOTMxWhcNNDkxMjMxMTIxOTMxWjBoMQswCQYDVQQGEwJDTjEUMBIGA1UEChML\nT3Blbkhhcm1vbnkxGTAXBgNVBAsTEE9wZW5IYXJtb255IFRlYW0xKDAmBgNVBAMT\nH09wZW5IYXJtb255IEFwcGxpY2F0aW9uIFJlbGVhc2UwWTATBgcqhkjOPQIBBggq\nhkjOPQMBBwNCAATbYOCQQpW5fdkYHN45v0X3AHax12jPBdEDosFRIZ1eXmxOYzSG\nJwMfsHhUU90E8lI0TXYZnNmgM1sovubeQqATo1IwUDAfBgNVHSMEGDAWgBTbhrci\nFtULoUu33SV7ufEFfaItRzAOBgNVHQ8BAf8EBAMCB4AwHQYDVR0OBBYEFPtxruhl\ncRBQsJdwcZqLu9oNUVgaMAwGCCqGSM49BAMDBQADaAAwZQIxAJta0PQ2p4DIu/ps\nLMdLCDgQ5UH1l0B4PGhBlMgdi2zf8nk9spazEQI/0XNwpft8QAIwHSuA2WelVi/o\nzAlF08DnbJrOOtOnQq5wHOPlDYB4OtUzOYJk9scotrEnJxJzGsh/\n-----END CERTIFICATE-----\n`;\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport type { ConfigProvider } from '../ports/config.js';\nimport { defaultPaths } from '../ports/config.js';\nimport type { ProgressReporter } from '../ports/progress.js';\nimport type { Logger } from '../ports/logger.js';\nimport { noopLogger } from '../ports/logger.js';\nimport { getEmulatorDir } from '../sdk/paths.js';\nimport { downloadFile } from '../sdk/download.js';\nimport { extractZipWithProgress } from '../sdk/extract.js';\nimport { createInstallTempDir, removeTempWorkDir, toSpaceError } from '../sdk/tmp.js';\n\nexport interface InstallEmulatorOptions {\n config: ConfigProvider;\n progress?: ProgressReporter;\n abortSignal?: AbortSignal;\n logger?: Logger;\n /**\n * Scratch directory for the downloaded ZIP. Overrides the `tmpDir` config key and\n * the default location next to the install target.\n */\n tmpDir?: string;\n}\n\n/**\n * Download and extract the Oniro emulator into the configured `emulatorDir`.\n */\nexport async function installEmulator(opts: InstallEmulatorOptions): Promise<void> {\n const { config, progress, abortSignal } = opts;\n const logger = opts.logger ?? noopLogger;\n\n const url = config.get('emulatorUrl', defaultPaths.emulatorUrl);\n const emulatorDir = getEmulatorDir(config);\n const what = 'the emulator install';\n const { dir: tmpDir, root: tmpRoot } = createInstallTempDir({\n config,\n override: opts.tmpDir,\n installRoot: path.dirname(emulatorDir),\n prefix: 'oniro-emulator-',\n logger,\n });\n const tmpZip = path.join(tmpDir, 'oniro_emulator.zip');\n\n try {\n fs.mkdirSync(emulatorDir, { recursive: true });\n\n progress?.report({ message: 'Downloading emulator...', increment: 0 });\n await downloadFile({ url, dest: tmpZip, progress, abortSignal, start: 0, range: 50, what, tmpRoot });\n\n progress?.report({ message: 'Extracting emulator...', increment: 0 });\n await extractZipWithProgress({ zipPath: tmpZip, dest: emulatorDir, progress, start: 50, range: 45, logger });\n\n const runSh = path.join(emulatorDir, 'images', 'run.sh');\n if (fs.existsSync(runSh)) {\n fs.chmodSync(runSh, 0o755);\n }\n progress?.report({ message: 'Finalizing installation...', increment: 5 });\n } catch (err) {\n throw toSpaceError(err, tmpRoot, what);\n } finally {\n removeTempWorkDir(tmpDir, tmpRoot);\n }\n}\n\n/**\n * Heuristic: the emulator is considered installed if either bundled launcher\n * (`images/run.sh` or `images/run.bat`) is present, so a Windows-only build is\n * detected too.\n */\nexport function isEmulatorInstalled(config: ConfigProvider): boolean {\n const imagesDir = path.join(getEmulatorDir(config), 'images');\n return fs.existsSync(path.join(imagesDir, 'run.sh')) || fs.existsSync(path.join(imagesDir, 'run.bat'));\n}\n\nexport function removeEmulator(config: ConfigProvider): void {\n const emulatorDir = getEmulatorDir(config);\n if (fs.existsSync(emulatorDir)) {\n fs.rmSync(emulatorDir, { recursive: true, force: true });\n }\n}\n","import * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport { spawn } from 'node:child_process';\nimport type { ConfigProvider } from '../ports/config.js';\nimport type { Logger } from '../ports/logger.js';\nimport { noopLogger } from '../ports/logger.js';\nimport { CancelledError, OniroError } from '../ports/errors.js';\nimport { getEmulatorDir } from '../sdk/paths.js';\nimport { hdcExec, runProcess } from '../hdc/exec.js';\n\nconst PID_FILE = path.join(os.tmpdir(), 'oniro_emulator.pid');\n\n/**\n * Try to connect hdc to the emulator. Resolves true on success, false otherwise.\n */\nexport async function attemptHdcConnection(\n config: ConfigProvider,\n address = '127.0.0.1:55555',\n logger: Logger = noopLogger,\n): Promise<boolean> {\n try {\n await hdcExec({ config, args: ['start', '-r'], logger });\n await hdcExec({ config, args: ['tconn', address], logger });\n const targets = await hdcExec({ config, args: ['list', 'targets'], logger });\n return targets.stdout.includes(address);\n } catch (err) {\n logger.warn(`hdc connection attempt failed: ${(err as Error).message}`);\n return false;\n }\n}\n\ninterface LauncherSpec {\n /** Executable to spawn (e.g. `bash` on POSIX, `cmd.exe` on Windows). */\n command: string;\n /** Args, including the launcher script path. */\n args: readonly string[];\n /** Working directory (images dir). */\n cwd: string;\n}\n\n/**\n * Pick the right bundled launcher for the current OS. Prefers run.bat on Windows\n * and run.sh elsewhere; falls back to the other if only one is present.\n */\nfunction resolveLauncher(\n imagesPath: string,\n headless: boolean,\n connect: string | undefined,\n): LauncherSpec {\n const runSh = path.join(imagesPath, 'run.sh');\n const runBat = path.join(imagesPath, 'run.bat');\n const extra: string[] = [];\n if (headless) extra.push('--headless');\n if (connect) extra.push('--connect', connect);\n\n if (os.platform() === 'win32') {\n if (fs.existsSync(runBat)) {\n return { command: 'cmd.exe', args: ['/c', runBat, ...extra], cwd: imagesPath };\n }\n if (fs.existsSync(runSh)) {\n return { command: 'bash', args: [runSh, ...extra], cwd: imagesPath };\n }\n throw new OniroError(`No emulator launcher (run.bat or run.sh) found in ${imagesPath}.`);\n }\n\n if (fs.existsSync(runSh)) {\n return { command: 'bash', args: [runSh, ...extra], cwd: imagesPath };\n }\n if (fs.existsSync(runBat)) {\n return { command: 'bash', args: [runBat, ...extra], cwd: imagesPath };\n }\n throw new OniroError(`No emulator launcher (run.sh or run.bat) found in ${imagesPath}.`);\n}\n\nexport interface StartEmulatorOptions {\n config: ConfigProvider;\n logger?: Logger;\n /** Pass --headless to the bundled launcher (VNC + telnet serial, no local window). */\n headless?: boolean;\n /**\n * Override the launcher's host:port for hdc port forwarding. Defaults to the\n * launcher's own default (typically `127.0.0.1:55555`). Use `0.0.0.0:55555`\n * on hosts where QEMU refuses to bind the hostfwd to 127.0.0.1 (e.g. some\n * CI runners with restricted loopback bindings).\n */\n connect?: string;\n /**\n * Redirect launcher stdout/stderr to this file. Default: discard\n * (/dev/null on POSIX, NUL on Windows). Use a real path in CI so you can\n * surface qemu output on failure.\n */\n logFile?: string;\n /**\n * If > 0, block until hdc connects to the running emulator, up to this many\n * seconds. 0 (default) returns as soon as the launcher process is spawned.\n */\n waitForHdcSeconds?: number;\n /** Poll interval for the hdc wait, ms. Default 5000. */\n hdcPollIntervalMs?: number;\n abortSignal?: AbortSignal;\n}\n\n/**\n * Launch the Oniro emulator in the background via the bundled run.sh/run.bat.\n *\n * The launcher process is detached + unref'd so callers can exit while the\n * emulator keeps running. A PID file is written to the OS temp dir so\n * `stopEmulator` and rerun-detection logic can find the process later.\n */\nexport async function startEmulator(opts: StartEmulatorOptions): Promise<void> {\n const { config } = opts;\n const logger = opts.logger ?? noopLogger;\n\n // Detect a still-running emulator from a previous run (POSIX only — Windows\n // PID semantics with process groups make this unreliable to check by hand).\n if (os.platform() !== 'win32' && fs.existsSync(PID_FILE)) {\n try {\n const pid = Number(fs.readFileSync(PID_FILE, 'utf8').trim());\n if (Number.isFinite(pid) && pid > 0) {\n try {\n process.kill(pid, 0);\n logger.info(`Emulator already running (PID ${pid}); not starting another.`);\n if (opts.waitForHdcSeconds && opts.waitForHdcSeconds > 0) {\n await waitForHdc(config, opts.waitForHdcSeconds, opts.hdcPollIntervalMs ?? 5000, logger, opts.abortSignal);\n }\n return;\n } catch {\n // Stale PID file — fall through and launch a fresh one.\n }\n }\n } catch (err) {\n logger.warn(`Could not read PID file: ${(err as Error).message}`);\n }\n }\n\n const imagesPath = path.join(getEmulatorDir(config), 'images');\n if (!fs.existsSync(imagesPath)) {\n throw new OniroError(`Emulator images directory not found at ${imagesPath}. Run \\`oniro-app emulator install\\` first.`);\n }\n const launcher = resolveLauncher(imagesPath, opts.headless === true, opts.connect);\n\n // Open the log target. Default to OS-level null sink so the child process\n // doesn't keep the parent's stdout/stderr file descriptors alive.\n const logPath = opts.logFile ?? (os.platform() === 'win32' ? 'NUL' : '/dev/null');\n const logFd = fs.openSync(logPath, 'a');\n\n let child;\n try {\n child = spawn(launcher.command, [...launcher.args], {\n cwd: launcher.cwd,\n detached: true,\n stdio: ['ignore', logFd, logFd],\n windowsHide: true,\n });\n } finally {\n fs.closeSync(logFd);\n }\n\n // Catch synchronous spawn failures (e.g. bash not found on PATH).\n if (!child.pid) {\n throw new OniroError(`Failed to spawn launcher (${launcher.command} ${launcher.args.join(' ')}).`);\n }\n\n // Record PID + detach. The launcher script `exec`s into qemu so this PID\n // remains valid for the whole emulator lifetime.\n fs.writeFileSync(PID_FILE, String(child.pid));\n child.unref();\n logger.info(`Emulator launched (PID ${child.pid}). Logs: ${logPath}`);\n\n // Watch for an immediate failure (e.g. KVM unavailable → run.sh exits ~instantly\n // with a friendly error). We hold a reference to the exit event but won't await\n // it if the child stays alive.\n const earlyExit = new Promise<number | null>((resolve) => {\n child.once('exit', (code) => resolve(code));\n child.once('error', () => resolve(-1));\n });\n const liveness = new Promise<'alive'>((resolve) => setTimeout(() => resolve('alive'), 2000));\n const outcome = await Promise.race([earlyExit, liveness]);\n if (outcome !== 'alive') {\n const tail = readTail(logPath, 4000);\n throw new OniroError(\n `Emulator launcher exited with code ${outcome} before reaching steady state. Tail of ${logPath}:\\n${tail}`,\n );\n }\n\n if (opts.waitForHdcSeconds && opts.waitForHdcSeconds > 0) {\n await waitForHdc(config, opts.waitForHdcSeconds, opts.hdcPollIntervalMs ?? 5000, logger, opts.abortSignal, logPath);\n }\n}\n\nasync function waitForHdc(\n config: ConfigProvider,\n timeoutSeconds: number,\n pollIntervalMs: number,\n logger: Logger,\n abortSignal?: AbortSignal,\n logPathForDiagnostics?: string,\n): Promise<void> {\n const deadline = Date.now() + timeoutSeconds * 1000;\n let attempt = 0;\n while (Date.now() < deadline) {\n if (abortSignal?.aborted) throw new CancelledError('hdc wait cancelled.');\n attempt++;\n if (await attemptHdcConnection(config, undefined, noopLogger)) {\n logger.info(`hdc connected on attempt ${attempt}.`);\n return;\n }\n // Every ~6 attempts, log a heartbeat with the latest emulator log tail so\n // a hung guest is debuggable from a single command's output stream.\n if (attempt % 6 === 0) {\n logger.info(`hdc not yet ready (attempt ${attempt}, ${Math.max(0, deadline - Date.now()) / 1000 | 0}s remaining).`);\n if (logPathForDiagnostics) {\n const tail = readTail(logPathForDiagnostics, 1200);\n if (tail.trim()) logger.debug(`emulator log tail:\\n${tail}`);\n }\n }\n await new Promise((r) => setTimeout(r, pollIntervalMs));\n }\n const tail = logPathForDiagnostics ? readTail(logPathForDiagnostics, 4000) : '';\n throw new OniroError(`hdc did not connect within ${timeoutSeconds}s.${tail ? `\\nTail of emulator log:\\n${tail}` : ''}`);\n}\n\nfunction readTail(filePath: string, bytes: number): string {\n try {\n const stat = fs.statSync(filePath);\n const start = Math.max(0, stat.size - bytes);\n const fd = fs.openSync(filePath, 'r');\n try {\n const buf = Buffer.alloc(stat.size - start);\n fs.readSync(fd, buf, 0, buf.length, start);\n return buf.toString('utf8');\n } finally {\n fs.closeSync(fd);\n }\n } catch {\n return '';\n }\n}\n\nexport async function stopEmulator(logger: Logger = noopLogger): Promise<void> {\n // Prefer killing the recorded PID; fall back to a broad kill for stragglers.\n if (fs.existsSync(PID_FILE)) {\n try {\n const pid = Number(fs.readFileSync(PID_FILE, 'utf8').trim());\n if (Number.isFinite(pid) && pid > 0) {\n try {\n process.kill(pid, 'SIGTERM');\n logger.info(`Sent SIGTERM to emulator PID ${pid}.`);\n } catch (err) {\n logger.warn(`Could not signal PID ${pid}: ${(err as Error).message}`);\n }\n }\n } catch (err) {\n logger.warn(`Could not read PID file: ${(err as Error).message}`);\n }\n }\n\n // pkill / taskkill exit non-zero when nothing matched — runProcess resolves on any\n // exit code, so we simply ignore that. The try/catch only guards a missing binary.\n const [killCmd, ...killArgs] = os.platform() === 'win32'\n ? ['taskkill', '/IM', 'qemu-system-x86_64.exe', '/F']\n : ['pkill', '-f', 'qemu-system-x86_64'];\n try {\n await runProcess({ command: killCmd!, args: killArgs, logger });\n } catch (err) {\n logger.warn(`[emulator] could not run ${killCmd}: ${(err as Error).message}`);\n }\n\n fs.rm(PID_FILE, { force: true }, (err) => {\n if (err) logger.warn(`Could not remove PID file: ${err.message}`);\n });\n}\n","import { spawn } from 'node:child_process';\nimport type { ConfigProvider } from '../ports/config.js';\nimport type { Logger } from '../ports/logger.js';\nimport { CancelledError, CommandFailedError, OniroError } from '../ports/errors.js';\nimport { getHdcPath } from '../sdk/paths.js';\n\n/** Result of a spawned command. `code` is the process exit code (-1 if it was killed). */\nexport interface HdcExecResult {\n code: number;\n stdout: string;\n stderr: string;\n}\n\n/** Streamed output callback, invoked per stdout/stderr chunk as it arrives. */\nexport type OutputSink = (chunk: string, stream: 'stdout' | 'stderr') => void;\n\nexport interface RunProcessOptions {\n /** Executable to spawn. */\n command: string;\n /** Args passed verbatim (spawn runs with `shell: false`, so no shell parsing). */\n args: readonly string[];\n cwd?: string;\n env?: NodeJS.ProcessEnv;\n /** Kill the process after this many ms and reject. Default 60_000. */\n timeoutMs?: number;\n /** Abort the process; rejects with CancelledError. */\n abortSignal?: AbortSignal;\n /** Receive stdout/stderr chunks as they arrive (in addition to the buffered result). */\n onOutput?: OutputSink;\n /** Reserved for future scoped diagnostics; the buffered result is returned regardless. */\n logger?: Logger;\n}\n\n/**\n * Spawn an arbitrary process with `shell: false` and collect its output. The\n * single low-level primitive every other command in the package builds on —\n * because args are passed as an array and never interpolated into a shell\n * string, command construction is injection-safe by construction.\n *\n * Resolves with `{ code, stdout, stderr }` for ANY exit code (callers opt into\n * throw-on-non-zero via {@link ensureOk}). Rejects only on spawn failure\n * (e.g. missing binary), timeout, or abort.\n */\nexport function runProcess(opts: RunProcessOptions): Promise<HdcExecResult> {\n const { command, args, cwd, env, onOutput } = opts;\n const timeoutMs = opts.timeoutMs ?? 60_000;\n const { abortSignal } = opts;\n\n return new Promise<HdcExecResult>((resolve, reject) => {\n if (abortSignal?.aborted) {\n reject(new CancelledError(`Command aborted before start: ${command}`));\n return;\n }\n\n const child = spawn(command, [...args], { cwd, env, shell: false });\n let stdout = '';\n let stderr = '';\n let settled = false;\n let timedOut = false;\n\n const cleanup = (): void => {\n clearTimeout(timer);\n abortSignal?.removeEventListener('abort', onAbort);\n };\n\n const onAbort = (): void => {\n if (settled) return;\n settled = true;\n cleanup();\n try {\n child.kill('SIGKILL');\n } catch {\n /* already gone */\n }\n reject(new CancelledError(`Command aborted: ${command} ${args.join(' ')}`));\n };\n\n const timer = setTimeout(() => {\n timedOut = true;\n try {\n child.kill('SIGKILL');\n } catch {\n /* already gone */\n }\n }, timeoutMs);\n\n abortSignal?.addEventListener('abort', onAbort, { once: true });\n\n child.stdout.on('data', (d: Buffer) => {\n const s = d.toString();\n stdout += s;\n onOutput?.(s, 'stdout');\n });\n child.stderr.on('data', (d: Buffer) => {\n const s = d.toString();\n stderr += s;\n onOutput?.(s, 'stderr');\n });\n\n child.on('error', (err) => {\n if (settled) return;\n settled = true;\n cleanup();\n reject(new OniroError(`Failed to spawn ${command}: ${err.message}`, err));\n });\n\n child.on('close', (code) => {\n if (settled) return;\n settled = true;\n cleanup();\n if (timedOut) {\n reject(\n new OniroError(\n `Command timed out after ${timeoutMs}ms: ${command} ${args.join(' ')}` +\n (stderr.trim() ? `\\n${stderr.trim()}` : ''),\n ),\n );\n return;\n }\n resolve({ code: code ?? -1, stdout, stderr });\n });\n });\n}\n\nexport interface HdcExecOptions {\n config: ConfigProvider;\n /** Args passed to hdc verbatim, e.g. `['shell','aa','start','-a',ability,'-b',bundle]`. */\n args: readonly string[];\n /** Device serial; when set, prepends `['-t', serial]`. */\n deviceSerial?: string;\n /** Default 60_000. */\n timeoutMs?: number;\n abortSignal?: AbortSignal;\n onOutput?: OutputSink;\n logger?: Logger;\n}\n\n/**\n * Run `hdc [-t <serial>] <args...>`. Resolves with `{ code, stdout, stderr }`\n * for any exit code; use {@link ensureOk} to throw on non-zero.\n */\nexport function hdcExec(opts: HdcExecOptions): Promise<HdcExecResult> {\n const hdc = getHdcPath(opts.config);\n const argv = opts.deviceSerial ? ['-t', opts.deviceSerial, ...opts.args] : [...opts.args];\n return runProcess({\n command: hdc,\n args: argv,\n timeoutMs: opts.timeoutMs,\n abortSignal: opts.abortSignal,\n onOutput: opts.onOutput,\n logger: opts.logger,\n });\n}\n\nexport interface HdcShellOptions extends Omit<HdcExecOptions, 'args'> {\n /** A single shell command, run as `hdc shell <command>` (one argv element — not host word-split). */\n command: string;\n}\n\n/** Convenience wrapper for `hdc shell <command>`. */\nexport function shell(opts: HdcShellOptions): Promise<HdcExecResult> {\n const { command, ...rest } = opts;\n return hdcExec({ ...rest, args: ['shell', command] });\n}\n\n/**\n * Throw a typed {@link CommandFailedError} when `result.code !== 0`, otherwise\n * return the result unchanged. Lets callers opt into throw-semantics.\n */\nexport function ensureOk(result: HdcExecResult, command: string): HdcExecResult {\n if (result.code !== 0) {\n throw new CommandFailedError(command, result.code, result.stderr.trim());\n }\n return result;\n}\n\n/** Matches the exit-code marker {@link shellChecked} appends. */\nconst REMOTE_RC_RE = /__ONIRO_RC=(-?\\d+)__/g;\n\n/**\n * Parse the exit-code marker appended by {@link shellChecked}. Pure/testable.\n * Returns the remote exit code plus stdout with every marker occurrence\n * stripped, or `null` when no marker is present (the command was killed/timed\n * out, or the device shell never reached the trailing `echo`).\n */\nexport function parseRemoteExit(stdout: string): { code: number; stdout: string } | null {\n let code: number | null = null;\n for (const m of stdout.matchAll(REMOTE_RC_RE)) code = Number(m[1]);\n if (code === null) return null;\n return { code, stdout: stdout.replace(REMOTE_RC_RE, '').replace(/[ \\t\\r\\n]+$/, '') };\n}\n\n/**\n * Like {@link shell}, but recovers the REMOTE command's exit status.\n *\n * `hdc shell \"<cmd>\"` reports hdc's OWN exit code (≈ always 0) regardless of\n * whether `<cmd>` succeeded on the device — so on-device failures (`uinput`\n * rejecting its args, a `bm install` error, a missing binary) otherwise look\n * like success. We append an exit-code marker, parse it back out, and report\n * it as `code`, with the marker stripped from stdout. Pair with\n * {@link ensureRemoteOk} to throw on a non-zero remote exit.\n */\nexport async function shellChecked(opts: HdcShellOptions): Promise<HdcExecResult> {\n const { command, ...rest } = opts;\n const res = await hdcExec({ ...rest, args: ['shell', `${command}; echo \"__ONIRO_RC=$?__\"`] });\n const parsed = parseRemoteExit(res.stdout);\n if (!parsed) return res; // marker missing — fall back to hdc's own exit code\n return { code: parsed.code, stdout: parsed.stdout, stderr: res.stderr };\n}\n\n/**\n * Throw a typed {@link CommandFailedError} on a non-zero result, preferring\n * stderr but falling back to stdout for the detail — device tools like\n * `uinput`/`uitest` print their errors to stdout, not stderr.\n */\nexport function ensureRemoteOk(result: HdcExecResult, command: string): HdcExecResult {\n if (result.code !== 0) {\n throw new CommandFailedError(command, result.code, result.stderr.trim() || result.stdout.trim());\n }\n return result;\n}\n","import type { ConfigProvider } from '../ports/config.js';\nimport type { Logger } from '../ports/logger.js';\nimport { OniroError } from '../ports/errors.js';\nimport { hdcExec } from './exec.js';\n\nexport interface DeviceInfo {\n /** Connect key — a USB serial or a `host:port` for a TCP target. */\n serial: string;\n /** 'Connected' | 'Offline' | 'Unauthorized' | … | 'Unknown' when not reported. */\n status: string;\n /** 'USB' | 'TCP' | … when reported by `-v`. */\n connection?: string;\n /** Device model, populated by getDeviceInfo (not by the bare target list). */\n model?: string;\n}\n\n// Recognised tokens in `hdc list targets -v` rows. Parsing is positional-agnostic\n// (we scan the row's tokens) so it tolerates hdc version differences in column order.\nconst STATUS_TOKENS = new Set([\n 'Connected',\n 'Offline',\n 'Unauthorized',\n 'Authorizing',\n 'Disconnected',\n 'Recovery',\n]);\nconst CONNECTION_TOKENS = new Set(['USB', 'TCP', 'UART', 'BT', 'UNKNOWN']);\n\n/**\n * Parse the output of `hdc list targets -v` into structured rows. The first token\n * of each non-empty row is the connect key (serial); connection/status are matched\n * by keyword among the remaining tokens. `[Empty]` (no devices) yields `[]`.\n */\nexport function parseDeviceList(stdout: string): DeviceInfo[] {\n const devices: DeviceInfo[] = [];\n for (const line of stdout.split('\\n')) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('[Empty]')) continue;\n const cols = trimmed.split(/\\s+/);\n const serial = cols[0];\n if (!serial) continue;\n const rest = cols.slice(1);\n const connection = rest.find((c) => CONNECTION_TOKENS.has(c));\n const status = rest.find((c) => STATUS_TOKENS.has(c)) ?? 'Unknown';\n const info: DeviceInfo = { serial, status };\n if (connection) info.connection = connection;\n devices.push(info);\n }\n return devices;\n}\n\n/** List connected hdc targets via `hdc list targets -v`. Empty list when none. */\nexport async function listDevices(\n config: ConfigProvider,\n opts: { timeoutMs?: number; logger?: Logger } = {},\n): Promise<DeviceInfo[]> {\n const res = await hdcExec({\n config,\n args: ['list', 'targets', '-v'],\n timeoutMs: opts.timeoutMs ?? 10_000,\n logger: opts.logger,\n });\n return parseDeviceList(res.stdout);\n}\n\n/**\n * Resolve which device serial to address: an explicit `serial` wins, then the\n * `ONIRO_DEVICE_SERIAL` / `DEVICE_SERIAL` env vars, then the single connected\n * device. Throws when none or more than one is connected and nothing was specified.\n */\nexport async function selectDevice(\n config: ConfigProvider,\n serial?: string,\n opts: { timeoutMs?: number; logger?: Logger } = {},\n): Promise<string> {\n if (serial && serial !== 'auto') return serial;\n const envSerial = process.env.ONIRO_DEVICE_SERIAL || process.env.DEVICE_SERIAL;\n if (envSerial && envSerial !== 'auto') return envSerial;\n\n const usable = (await listDevices(config, opts)).filter(\n (d) => d.status === 'Connected' || d.status === 'Unknown',\n );\n if (usable.length === 1) return usable[0]!.serial;\n if (usable.length === 0) {\n throw new OniroError('No connected device found. Connect a device/emulator or set ONIRO_DEVICE_SERIAL.');\n }\n throw new OniroError(\n `Multiple devices connected (${usable.map((d) => d.serial).join(', ')}). ` +\n 'Set ONIRO_DEVICE_SERIAL to choose one.',\n );\n}\n","import type { ConfigProvider } from '../ports/config.js';\nimport type { Logger } from '../ports/logger.js';\nimport { shell, ensureOk } from './exec.js';\n\nexport interface ParamOptions {\n deviceSerial?: string;\n timeoutMs?: number;\n logger?: Logger;\n}\n\n/** Read a system property via `hdc shell param get <key>`. Returns the trimmed value. */\nexport async function paramGet(config: ConfigProvider, key: string, opts: ParamOptions = {}): Promise<string> {\n const res = await shell({\n config,\n command: `param get ${key}`,\n deviceSerial: opts.deviceSerial,\n timeoutMs: opts.timeoutMs ?? 10_000,\n logger: opts.logger,\n });\n ensureOk(res, `hdc shell param get ${key}`);\n return res.stdout.trim();\n}\n\n/**\n * Set a system property via `hdc shell param set <key> <value>`. The canonical\n * reboot path is `paramSet(config, 'ohos.startup.powerctrl', 'reboot')`.\n */\nexport async function paramSet(\n config: ConfigProvider,\n key: string,\n value: string,\n opts: ParamOptions = {},\n): Promise<void> {\n const res = await shell({\n config,\n command: `param set ${key} ${value}`,\n deviceSerial: opts.deviceSerial,\n timeoutMs: opts.timeoutMs ?? 10_000,\n logger: opts.logger,\n });\n ensureOk(res, `hdc shell param set ${key} ${value}`);\n}\n","import type { ConfigProvider } from '../ports/config.js';\nimport type { Logger } from '../ports/logger.js';\nimport { hdcExec, ensureOk, type OutputSink } from './exec.js';\n\nexport interface SendFileOptions {\n config: ConfigProvider;\n /** Local source path. */\n local: string;\n /** Remote destination path on the device. */\n remote: string;\n deviceSerial?: string;\n timeoutMs?: number;\n abortSignal?: AbortSignal;\n onOutput?: OutputSink;\n logger?: Logger;\n}\n\n/** Push a local file to the device via `hdc file send <local> <remote>`. */\nexport async function sendFile(opts: SendFileOptions): Promise<void> {\n const res = await hdcExec({\n config: opts.config,\n args: ['file', 'send', opts.local, opts.remote],\n deviceSerial: opts.deviceSerial,\n timeoutMs: opts.timeoutMs ?? 600_000,\n abortSignal: opts.abortSignal,\n onOutput: opts.onOutput,\n logger: opts.logger,\n });\n ensureOk(res, `hdc file send ${opts.local} ${opts.remote}`);\n}\n\nexport interface RecvFileOptions {\n config: ConfigProvider;\n /** Remote source path on the device. */\n remote: string;\n /** Local destination path. */\n local: string;\n deviceSerial?: string;\n timeoutMs?: number;\n abortSignal?: AbortSignal;\n onOutput?: OutputSink;\n logger?: Logger;\n}\n\n/** Pull a file from the device via `hdc file recv <remote> <local>`. */\nexport async function recvFile(opts: RecvFileOptions): Promise<void> {\n const res = await hdcExec({\n config: opts.config,\n args: ['file', 'recv', opts.remote, opts.local],\n deviceSerial: opts.deviceSerial,\n timeoutMs: opts.timeoutMs ?? 600_000,\n abortSignal: opts.abortSignal,\n onOutput: opts.onOutput,\n logger: opts.logger,\n });\n ensureOk(res, `hdc file recv ${opts.remote} ${opts.local}`);\n}\n","import type { ConfigProvider } from '../ports/config.js';\nimport type { Logger } from '../ports/logger.js';\nimport { shell } from './exec.js';\n\nexport interface DisplaySize {\n width: number;\n height: number;\n}\n\nexport interface DisplaySizeOptions {\n deviceSerial?: string;\n timeoutMs?: number;\n logger?: Logger;\n}\n\n/**\n * Resolve the device's render resolution from `hidumper -s 10 -a screen`\n * (`render resolution=WxH`). Returns null when unavailable. This is the W/H\n * source for screenshots and the 0–1 normalization of layout bounds — no image\n * decoding is involved.\n */\nexport async function getDisplaySize(config: ConfigProvider, opts: DisplaySizeOptions = {}): Promise<DisplaySize | null> {\n const res = await shell({\n config,\n command: 'hidumper -s 10 -a screen',\n deviceSerial: opts.deviceSerial,\n timeoutMs: opts.timeoutMs ?? 10_000,\n logger: opts.logger,\n });\n if (res.code !== 0) return null;\n const m = res.stdout.match(/render resolution=(\\d+)x(\\d+)/);\n if (!m) return null;\n return { width: Number(m[1]), height: Number(m[2]) };\n}\n","import type { Logger } from '../ports/logger.js';\nimport { CancelledError, OniroError } from '../ports/errors.js';\n\nexport interface WaitForConditionOptions {\n /** Resolves true when the condition is satisfied. Called once per poll. */\n probe: () => Promise<boolean>;\n /** Overall deadline. */\n timeoutMs: number;\n /** Poll interval. Default 2000. */\n pollMs?: number;\n /** Abort the wait; rejects with CancelledError. */\n abortSignal?: AbortSignal;\n /** Called every `heartbeatEvery` attempts (default 6) with progress info. */\n onHeartbeat?: (attempt: number, remainingMs: number) => void;\n heartbeatEvery?: number;\n logger?: Logger;\n /** Message for the timeout error. */\n timeoutMessage?: string;\n}\n\n/** Sleep `ms`, rejecting early (CancelledError) if `signal` aborts. */\nfunction delay(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n if (signal?.aborted) {\n reject(new CancelledError('Wait cancelled.'));\n return;\n }\n const onAbort = (): void => {\n cleanup();\n reject(new CancelledError('Wait cancelled.'));\n };\n const cleanup = (): void => {\n clearTimeout(timer);\n signal?.removeEventListener('abort', onAbort);\n };\n const timer = setTimeout(() => {\n cleanup();\n resolve();\n }, ms);\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n}\n\n/**\n * Generic deadline + poll + heartbeat loop. Calls `probe()` every `pollMs` until\n * it resolves true (→ resolve) or the deadline passes (→ throw OniroError).\n * A probe that throws is treated as \"not yet\" (the loop keeps polling) — this is\n * what lets device waits tolerate transient hdc disconnects mid-reboot. Aborting\n * the signal rejects with CancelledError.\n *\n * Extracted from the emulator hdc-wait loop so device lifecycle helpers share it.\n */\nexport async function waitForCondition(opts: WaitForConditionOptions): Promise<void> {\n const pollMs = opts.pollMs ?? 2000;\n const heartbeatEvery = opts.heartbeatEvery ?? 6;\n const deadline = Date.now() + opts.timeoutMs;\n let attempt = 0;\n\n while (Date.now() < deadline) {\n if (opts.abortSignal?.aborted) throw new CancelledError('Wait cancelled.');\n attempt++;\n\n let ok = false;\n try {\n ok = await opts.probe();\n } catch {\n ok = false; // transient failure (e.g. hdc disconnect) — keep polling\n }\n if (ok) return;\n\n if (opts.onHeartbeat && attempt % heartbeatEvery === 0) {\n opts.onHeartbeat(attempt, Math.max(0, deadline - Date.now()));\n }\n await delay(pollMs, opts.abortSignal);\n }\n\n throw new OniroError(opts.timeoutMessage ?? `Condition not met within ${opts.timeoutMs}ms.`);\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { spawn } from 'node:child_process';\nimport type { ConfigProvider } from '../ports/config.js';\nimport { defaultPaths } from '../ports/config.js';\nimport type { Logger } from '../ports/logger.js';\nimport { noopLogger, scopedLogger } from '../ports/logger.js';\nimport { OniroError } from '../ports/errors.js';\nimport { getHdcPath } from '../sdk/paths.js';\nimport { hdcExec, shell, ensureOk } from './exec.js';\nimport { getBundleName, getMainAbility } from './project.js';\n\nexport interface InstallAppOptions {\n config: ConfigProvider;\n projectDir: string;\n /**\n * Explicit path (absolute, or relative to projectDir) to the signed `.hap`.\n * Falls back to the `hapPath` config key, then to the well-known default.\n */\n hapPath?: string;\n logger?: Logger;\n}\n\nexport interface InstallAppResult {\n installed: boolean;\n /** Bundle name read from the project's AppScope/app.json5, or '' if unavailable. */\n bundleName: string;\n /** The resolved absolute HAP path that was installed. */\n hapPath: string;\n /** Combined stdout+stderr from the install, trimmed. */\n output: string;\n}\n\nexport async function installApp(opts: InstallAppOptions): Promise<InstallAppResult> {\n const logger = scopedLogger(opts.logger ?? noopLogger, 'hdc');\n const relativeHapPath = opts.hapPath ?? opts.config.get('hapPath', defaultPaths.hapPath);\n const hapPath = path.isAbsolute(relativeHapPath) ? relativeHapPath : path.join(opts.projectDir, relativeHapPath);\n\n if (!fs.existsSync(hapPath)) {\n throw new OniroError(`HAP file not found at: ${hapPath}. Build and sign the app first.`);\n }\n\n const result = await hdcExec({ config: opts.config, args: ['install', hapPath], timeoutMs: 300_000 });\n if (result.stdout.trim()) logger.info(result.stdout.trim());\n if (result.stderr.trim()) logger.warn(result.stderr.trim());\n ensureOk(result, `hdc install ${hapPath}`);\n\n let bundleName = '';\n try {\n bundleName = getBundleName(opts.projectDir);\n } catch {\n // bundleName is informational; a HAP from a project without AppScope still installs.\n }\n return { installed: true, bundleName, hapPath, output: `${result.stdout}${result.stderr}`.trim() };\n}\n\nexport interface LaunchAppOptions {\n config: ConfigProvider;\n /** Project mode: resolve bundle + main ability from the project. Required unless `bundleName` is given. */\n projectDir?: string;\n /**\n * Bundle mode: launch an already-installed app directly by bundle name (no\n * project needed). When set, `projectDir` is ignored. If `abilityName` is\n * omitted, the main ability is resolved from the device via `bm dump -n`.\n */\n bundleName?: string;\n /** Override the module name if it isn't the default `entry` (project mode). */\n moduleName?: string;\n /** Explicit ability to launch; defaults to the module's mainElement / first visible ability (project mode) or the installed bundle's main ability (bundle mode). */\n abilityName?: string;\n deviceSerial?: string;\n logger?: Logger;\n}\n\n/**\n * `aa start` exits 0 even when the launch is refused — a locked screen\n * (`Error Code:10106102`), a missing ability, a permission denial, etc. The failure\n * only shows up in its output. Returns the offending text when the output indicates a\n * failed launch, or null when it looks like a success.\n */\nexport function detectAaStartFailure(output: string): string | null {\n return /failed to start ability|Error Code:\\s*\\d|Error Message:/i.test(output) ? output.trim() : null;\n}\n\n/**\n * Parse the main ability of an installed bundle from `bm dump -n <bundle>`\n * output. Pure/testable. The output is a bundle-name prefix line followed by a\n * JSON blob; we take the entry module's `mainElementName` (fallback\n * `mainAbility`), or the first module that declares one. Returns null when the\n * bundle isn't installed or the output is unparseable.\n */\nexport function parseMainAbilityFromBmDump(stdout: string): string | null {\n const start = stdout.indexOf('{');\n if (start < 0) return null;\n let info: { hapModuleInfos?: Array<{ mainElementName?: string; mainAbility?: string; moduleType?: number | string }> };\n try {\n info = JSON.parse(stdout.slice(start));\n } catch {\n return null;\n }\n const mods = Array.isArray(info?.hapModuleInfos) ? info.hapModuleInfos : [];\n const abilityOf = (m: { mainElementName?: string; mainAbility?: string }): string | undefined =>\n (m?.mainElementName || m?.mainAbility) || undefined;\n const isEntry = (m: { moduleType?: number | string }): boolean =>\n m?.moduleType === 1 || m?.moduleType === '1' || m?.moduleType === 'entry';\n const entry = mods.find((m) => isEntry(m) && abilityOf(m));\n const any = mods.find((m) => abilityOf(m));\n return (entry && abilityOf(entry)) || (any && abilityOf(any)) || null;\n}\n\n/** Resolve an installed bundle's main ability off the device via `bm dump -n`. */\nasync function resolveInstalledMainAbility(opts: {\n config: ConfigProvider;\n bundle: string;\n deviceSerial?: string;\n logger?: Logger;\n}): Promise<string> {\n const res = await shell({\n config: opts.config,\n command: `bm dump -n ${opts.bundle}`,\n deviceSerial: opts.deviceSerial,\n timeoutMs: 15_000,\n logger: opts.logger,\n });\n const ability = parseMainAbilityFromBmDump(res.stdout);\n if (!ability) {\n throw new OniroError(\n `Could not determine the main ability for installed bundle ${opts.bundle} ` +\n `(is it installed?). Pass an explicit ability instead.`,\n );\n }\n return ability;\n}\n\nexport async function launchApp(opts: LaunchAppOptions): Promise<void> {\n const logger = scopedLogger(opts.logger ?? noopLogger, 'hdc');\n let bundleName: string;\n let mainAbility: string;\n if (opts.bundleName) {\n // Bundle mode: launch an already-installed app directly (no project).\n bundleName = opts.bundleName;\n mainAbility =\n opts.abilityName ??\n (await resolveInstalledMainAbility({\n config: opts.config,\n bundle: bundleName,\n deviceSerial: opts.deviceSerial,\n logger: opts.logger,\n }));\n } else {\n if (!opts.projectDir) throw new OniroError('launchApp requires either bundleName or projectDir.');\n bundleName = getBundleName(opts.projectDir);\n mainAbility = getMainAbility(opts.projectDir, opts.moduleName, opts.abilityName);\n }\n // Pass ability/bundle as discrete argv elements (shell:false), never interpolated\n // into a host shell string — this is the injection fix vs the old `aa start -a ${x}`.\n const result = await hdcExec({\n config: opts.config,\n args: ['shell', 'aa', 'start', '-a', mainAbility, '-b', bundleName],\n deviceSerial: opts.deviceSerial,\n });\n if (result.stdout.trim()) logger.info(result.stdout.trim());\n if (result.stderr.trim()) logger.warn(result.stderr.trim());\n ensureOk(result, `hdc shell aa start -a ${mainAbility} -b ${bundleName}`);\n // `aa start` reports launch failures in its output, not its exit code — surface them\n // instead of silently reporting success.\n const failure = detectAaStartFailure(`${result.stdout}\\n${result.stderr}`);\n if (failure) {\n throw new OniroError(`Failed to launch ${bundleName} (${mainAbility}): ${failure}`);\n }\n}\n\nexport interface RunningProcess {\n pid: string;\n name: string;\n}\n\n/**\n * List running processes via `hdc track-jpid`. Times out after `timeoutMs`.\n * When `targetProcessName` is set, resolves to that process's PID early; otherwise\n * resolves to the full list collected within the timeout window.\n */\nexport function listRunningProcesses(\n config: ConfigProvider,\n options: { targetProcessName?: string; timeoutMs?: number; logger?: Logger } = {},\n): Promise<RunningProcess[] | string> {\n const logger = options.logger ?? noopLogger;\n const timeoutMs = options.timeoutMs ?? 1000;\n const hdc = getHdcPath(config);\n\n return new Promise((resolve, reject) => {\n const proc = spawn(hdc, ['track-jpid']);\n const processes: RunningProcess[] = [];\n let resolved = false;\n\n proc.stdout.on('data', (data: Buffer) => {\n for (const line of data.toString().split('\\n').filter(Boolean)) {\n const match = line.match(/^(\\d+)\\s+(.+)$/);\n if (!match) continue;\n const pid = match[1]!;\n const name = match[2]!;\n processes.push({ pid, name });\n if (options.targetProcessName && name === options.targetProcessName && !resolved) {\n resolved = true;\n proc.kill();\n resolve(pid);\n return;\n }\n }\n });\n\n proc.stderr.on('data', (data: Buffer) => {\n logger.warn(`[hdc track-jpid] ${data.toString()}`);\n });\n\n proc.on('error', (err) => {\n if (!resolved) {\n resolved = true;\n reject(err);\n }\n });\n\n const timeout = setTimeout(() => {\n if (resolved) return;\n resolved = true;\n proc.kill();\n if (options.targetProcessName) {\n reject(new OniroError(`Could not find process for bundle: ${options.targetProcessName}`));\n } else {\n resolve(processes);\n }\n }, timeoutMs);\n\n proc.on('close', () => {\n clearTimeout(timeout);\n if (resolved) return;\n resolved = true;\n if (options.targetProcessName) {\n reject(new OniroError(`Could not find process for bundle: ${options.targetProcessName}`));\n } else {\n resolve(processes);\n }\n });\n });\n}\n\nexport async function findAppProcessId(config: ConfigProvider, projectDir: string, logger?: Logger): Promise<string> {\n const bundleName = getBundleName(projectDir);\n const result = await listRunningProcesses(config, { targetProcessName: bundleName, logger });\n return result as string;\n}\n\nexport interface BundleOptions {\n config: ConfigProvider;\n bundle: string;\n deviceSerial?: string;\n timeoutMs?: number;\n logger?: Logger;\n}\n\n/**\n * Non-throwing companion to {@link listRunningProcesses}: resolve a running\n * process for a bundle, or `null` when it isn't running. Suitable for \"is X\n * running?\" checks (e.g. the pre/post-install pid comparison in applyChanges).\n *\n * `pidof` matches the bundle's main (UIAbility) process. When that isn't found,\n * we fall back to `track-jpid` to also catch **extension-ability** processes,\n * which run under a separate process name `\"<bundle>:<ext>\"` (e.g. a\n * ServiceExtension, FormExtension, UIExtension or input method). Without this,\n * \"verify the running process took the change\" silently reported nothing for an\n * app whose only live process is an extension.\n */\nexport async function findRunningProcess(opts: BundleOptions): Promise<RunningProcess | null> {\n const safe = opts.bundle.replace(/'/g, `'\\\\''`);\n const res = await shell({\n config: opts.config,\n command: `pidof '${safe}'`,\n deviceSerial: opts.deviceSerial,\n timeoutMs: opts.timeoutMs ?? 10_000,\n logger: opts.logger,\n });\n const pid = res.stdout.trim().split(/\\s+/).filter(Boolean)[0];\n if (res.code === 0 && pid && /^\\d+$/.test(pid)) return { pid, name: opts.bundle };\n\n // Fallback: the bundle may only be alive as an extension process. track-jpid\n // names them \"<bundle>/<bundle>:<ext>\" (vs bare \"<bundle>\" for the main).\n try {\n const list = await listRunningProcesses(opts.config, { timeoutMs: 1200, logger: opts.logger });\n if (Array.isArray(list)) {\n const mine = (name: string): boolean =>\n name === opts.bundle || name.startsWith(`${opts.bundle}/`) || name.startsWith(`${opts.bundle}:`);\n const match = list.find((p) => p.name === opts.bundle) ?? list.find((p) => mine(p.name));\n if (match) return match;\n }\n } catch {\n // best-effort; fall through to \"not running\"\n }\n return null;\n}\n\n/** Uninstall an app by bundle name (`hdc uninstall <bundle>`). */\nexport async function uninstallApp(opts: BundleOptions): Promise<void> {\n const logger = scopedLogger(opts.logger ?? noopLogger, 'hdc');\n const res = await hdcExec({\n config: opts.config,\n args: ['uninstall', opts.bundle],\n deviceSerial: opts.deviceSerial,\n timeoutMs: opts.timeoutMs ?? 120_000,\n });\n if (res.stdout.trim()) logger.info(res.stdout.trim());\n if (res.stderr.trim()) logger.warn(res.stderr.trim());\n ensureOk(res, `hdc uninstall ${opts.bundle}`);\n}\n\n/** Force-stop an app (`hdc shell aa force-stop <bundle>`). */\nexport async function forceStop(opts: BundleOptions): Promise<void> {\n const res = await shell({\n config: opts.config,\n command: `aa force-stop ${opts.bundle}`,\n deviceSerial: opts.deviceSerial,\n timeoutMs: opts.timeoutMs ?? 30_000,\n logger: opts.logger,\n });\n ensureOk(res, `hdc shell aa force-stop ${opts.bundle}`);\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport JSON5 from 'json5';\nimport { OniroError } from '../ports/errors.js';\n\nfunction readJson5<T>(filePath: string): T {\n const content = fs.readFileSync(filePath, 'utf-8');\n return JSON5.parse(content) as T;\n}\n\n/**\n * Read the project's bundle name from `AppScope/app.json5`.\n */\nexport function getBundleName(projectDir: string): string {\n const appJsonPath = path.join(projectDir, 'AppScope', 'app.json5');\n if (!fs.existsSync(appJsonPath)) {\n throw new OniroError(`Could not find app.json5 at ${appJsonPath}`);\n }\n const appJson = readJson5<{ app?: { bundleName?: string } }>(appJsonPath);\n if (!appJson.app?.bundleName) {\n throw new OniroError('bundleName not found in app.json5');\n }\n return appJson.app.bundleName;\n}\n\n/**\n * Read the ability to launch from `<module>/src/main/module.json5`. Defaults to\n * `entry` for the module folder name. Resolution order:\n * 1. `abilityName`, if given and present in `module.abilities[]`.\n * 2. `module.mainElement`.\n * 3. The first `visible` ability, then the first ability, from `module.abilities[]`.\n * Modules with multiple abilities can be targeted explicitly via `abilityName`.\n */\nexport function getMainAbility(projectDir: string, moduleName = 'entry', abilityName?: string): string {\n const moduleJsonPath = path.join(projectDir, moduleName, 'src', 'main', 'module.json5');\n if (!fs.existsSync(moduleJsonPath)) {\n throw new OniroError(`Could not find module.json5 at ${moduleJsonPath}`);\n }\n const moduleJson = readJson5<{\n module?: { mainElement?: string; abilities?: Array<{ name?: string; visible?: boolean }> };\n }>(moduleJsonPath);\n const module = moduleJson.module ?? {};\n\n if (abilityName) {\n const match = module.abilities?.find((a) => a.name === abilityName);\n if (match?.name) return match.name;\n throw new OniroError(`Ability \"${abilityName}\" not found in module.json5 at ${moduleJsonPath}`);\n }\n\n if (module.mainElement) return module.mainElement;\n\n const abilities = module.abilities ?? [];\n const visible = abilities.find((a) => a.visible && a.name);\n if (visible?.name) return visible.name;\n const first = abilities.find((a) => a.name);\n if (first?.name) return first.name;\n\n throw new OniroError('mainElement not found in module.json5');\n}\n","import type { ConfigProvider } from '../ports/config.js';\nimport type { Logger } from '../ports/logger.js';\nimport { noopLogger, scopedLogger } from '../ports/logger.js';\nimport { hdcExec, shell } from './exec.js';\nimport { paramSet } from './param.js';\nimport { findRunningProcess } from './app.js';\nimport { waitForCondition } from './wait.js';\n\n/** Probe whether the device responds to a trivial shell command. */\nasync function isReachable(config: ConfigProvider, deviceSerial?: string): Promise<boolean> {\n try {\n const res = await shell({ config, command: 'echo oniro_ping', deviceSerial, timeoutMs: 5_000 });\n return res.code === 0 && res.stdout.includes('oniro_ping');\n } catch {\n return false;\n }\n}\n\n/**\n * A TCP/network hdc target — \"host:port\", e.g. the emulator's `127.0.0.1:55555`.\n * USB serials (e.g. `emulator-5554`) have no `:port` suffix.\n */\nconst TCP_SERIAL_RE = /^.+:\\d+$/;\n\n/**\n * Re-establish the hdc connection to a TCP target, best-effort. hdc auto-reconnects\n * a USB device when it re-enumerates, but a TCP target must be reconnected explicitly\n * with `hdc tconn` after the session drops — which is exactly what a reboot does, so\n * without this a post-reboot `waitForBundle`/`waitForBoot` polls a dead socket until it\n * times out. A no-op for USB serials or when no serial is given, so it is safe to call\n * before every poll; failure is swallowed (the device may still be down, and the probe\n * that follows reports not-ready so we simply poll again).\n */\nasync function reconnectIfTcp(config: ConfigProvider, deviceSerial: string | undefined, logger: Logger): Promise<void> {\n if (!deviceSerial || !TCP_SERIAL_RE.test(deviceSerial)) return;\n try {\n await hdcExec({ config, args: ['tconn', deviceSerial], timeoutMs: 5_000, logger });\n } catch {\n /* still down — the following probe reports not-ready and we poll again */\n }\n}\n\nexport interface WaitForBundleOptions {\n config: ConfigProvider;\n bundle: string;\n deviceSerial?: string;\n timeoutMs?: number;\n abortSignal?: AbortSignal;\n logger?: Logger;\n}\n\n/**\n * Poll `pidof <bundle>` until the bundle has a clean numeric pid. Empty/failed\n * pidof responses (including while the device is unreachable) do NOT count.\n */\nexport async function waitForBundle(opts: WaitForBundleOptions): Promise<void> {\n const logger = scopedLogger(opts.logger ?? noopLogger, 'hdc');\n const timeoutMs = opts.timeoutMs ?? 180_000;\n await waitForCondition({\n probe: async () => {\n await reconnectIfTcp(opts.config, opts.deviceSerial, logger);\n return (\n (await findRunningProcess({ config: opts.config, bundle: opts.bundle, deviceSerial: opts.deviceSerial, timeoutMs: 8_000 })) !== null\n );\n },\n timeoutMs,\n pollMs: 2_000,\n abortSignal: opts.abortSignal,\n onHeartbeat: (attempt, remaining) =>\n logger.info(`waiting for ${opts.bundle} (attempt ${attempt}, ${Math.floor(remaining / 1000)}s left)`),\n timeoutMessage: `Bundle ${opts.bundle} did not start within ${timeoutMs}ms.`,\n });\n}\n\nexport interface WaitForBootOptions {\n config: ConfigProvider;\n /** Require a clean numeric pid for this process/bundle name before returning. */\n untilPidOf?: string;\n deviceSerial?: string;\n timeoutMs?: number;\n abortSignal?: AbortSignal;\n logger?: Logger;\n}\n\n/**\n * Poll until the device responds AND (when `untilPidOf` is set) that process has\n * a clean numeric pid. Tolerates the transient hdc disconnect during a reboot.\n */\nexport async function waitForBoot(opts: WaitForBootOptions): Promise<void> {\n const logger = scopedLogger(opts.logger ?? noopLogger, 'hdc');\n const timeoutMs = opts.timeoutMs ?? 180_000;\n await waitForCondition({\n probe: async () => {\n await reconnectIfTcp(opts.config, opts.deviceSerial, logger);\n if (!(await isReachable(opts.config, opts.deviceSerial))) return false;\n if (!opts.untilPidOf) return true;\n return (\n (await findRunningProcess({ config: opts.config, bundle: opts.untilPidOf, deviceSerial: opts.deviceSerial, timeoutMs: 8_000 })) !== null\n );\n },\n timeoutMs,\n pollMs: 2_000,\n abortSignal: opts.abortSignal,\n onHeartbeat: (attempt, remaining) =>\n logger.info(`waiting for boot (attempt ${attempt}, ${Math.floor(remaining / 1000)}s left)`),\n timeoutMessage: `Device did not boot within ${timeoutMs}ms.`,\n });\n}\n\nexport interface RebootOptions {\n config: ConfigProvider;\n /** 'system' (default) reboots via param set; bootloader/recovery via `reboot <mode>`. */\n mode?: 'system' | 'bootloader' | 'recovery';\n /** When set (system mode), block until this bundle has a clean numeric pid after the reboot. */\n waitForBundle?: string;\n deviceSerial?: string;\n timeoutMs?: number;\n abortSignal?: AbortSignal;\n logger?: Logger;\n}\n\n/**\n * Reboot the device. System reboots use `param set ohos.startup.powerctrl reboot`\n * (the path that works when force-stopping systemui is blocked); bootloader/\n * recovery use `hdc shell reboot <mode>`. A reboot frequently tears down the hdc\n * connection before the command returns, so command failure here is tolerated.\n *\n * When `waitForBundle` is set (system mode), waits for the device to drop and\n * come back with the bundle running — so it doesn't return on the pre-reboot pid.\n * A TCP target (e.g. an emulator at `127.0.0.1:55555`) is reconnected via\n * `hdc tconn` during that wait, since hdc does not auto-reconnect TCP sessions\n * across a reboot the way it does USB devices — pass the address as `deviceSerial`.\n */\nexport async function reboot(opts: RebootOptions): Promise<void> {\n const logger = scopedLogger(opts.logger ?? noopLogger, 'hdc');\n const mode = opts.mode ?? 'system';\n const timeoutMs = opts.timeoutMs ?? 180_000;\n\n logger.info(`Rebooting device (${mode})...`);\n try {\n if (mode === 'system') {\n await paramSet(opts.config, 'ohos.startup.powerctrl', 'reboot', {\n deviceSerial: opts.deviceSerial,\n timeoutMs: 15_000,\n logger: opts.logger,\n });\n } else {\n await shell({ config: opts.config, command: `reboot ${mode}`, deviceSerial: opts.deviceSerial, timeoutMs: 15_000 });\n }\n } catch (err) {\n // Expected: the reboot tore down hdc before the command returned cleanly.\n logger.debug(`reboot command did not return cleanly: ${(err as Error).message}`);\n }\n\n if (mode !== 'system' || !opts.waitForBundle) return;\n\n // Wait for the device to actually go down first (best-effort) so the subsequent\n // bundle wait can't match the pre-reboot process, then wait for it to return.\n try {\n await waitForCondition({\n probe: async () => !(await isReachable(opts.config, opts.deviceSerial)),\n timeoutMs: Math.min(timeoutMs, 30_000),\n pollMs: 1_500,\n abortSignal: opts.abortSignal,\n timeoutMessage: 'device did not become unreachable',\n });\n } catch {\n // Device may reboot too fast to observe the down state — proceed to wait for it.\n }\n\n await waitForBundle({\n config: opts.config,\n bundle: opts.waitForBundle,\n deviceSerial: opts.deviceSerial,\n timeoutMs,\n abortSignal: opts.abortSignal,\n logger: opts.logger,\n });\n}\n","import * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport { randomBytes } from 'node:crypto';\nimport type { ConfigProvider } from '../ports/config.js';\nimport type { Logger } from '../ports/logger.js';\nimport { shell, ensureOk } from './exec.js';\nimport { recvFile } from './files.js';\nimport { getDisplaySize } from './display.js';\n\nexport interface Screenshot {\n /** Raw JPEG bytes, exactly as `snapshot_display` wrote them (no decode/resize). */\n pixels: Buffer;\n /** Device render width/height from hidumper; 0 when it couldn't be resolved. */\n width: number;\n height: number;\n}\n\nexport interface ScreenshotOptions {\n config: ConfigProvider;\n deviceSerial?: string;\n timeoutMs?: number;\n logger?: Logger;\n}\n\nfunction tmpName(ext: string): string {\n return path.join(os.tmpdir(), `oniro_screen_${randomBytes(6).toString('hex')}.${ext}`);\n}\n\n/**\n * Capture the screen via on-device `snapshot_display`, pull the JPEG bytes back,\n * and return them raw alongside the device resolution. The agent-facing grid\n * overlay / downscale / base64 encoding stays in the MCP — core does no image\n * decoding and adds no image dependency.\n */\nexport async function takeScreenshot(opts: ScreenshotOptions): Promise<Screenshot> {\n const remote = '/data/local/tmp/oniro_screenshot.jpeg';\n const timeoutMs = opts.timeoutMs ?? 30_000;\n\n const cap = await shell({ config: opts.config, command: `snapshot_display -f ${remote}`, deviceSerial: opts.deviceSerial, timeoutMs });\n ensureOk(cap, `snapshot_display -f ${remote}`);\n\n const local = tmpName('jpeg');\n try {\n await recvFile({ config: opts.config, remote, local, deviceSerial: opts.deviceSerial, timeoutMs });\n const pixels = await fs.promises.readFile(local);\n const size = (await getDisplaySize(opts.config, { deviceSerial: opts.deviceSerial })) ?? { width: 0, height: 0 };\n return { pixels, width: size.width, height: size.height };\n } finally {\n fs.promises.unlink(local).catch(() => {});\n void shell({ config: opts.config, command: `rm -f ${remote}`, deviceSerial: opts.deviceSerial }).catch(() => {});\n }\n}\n\nexport interface CaptureBurstOptions {\n config: ConfigProvider;\n count: number;\n /** Delay between device-side captures, ms. */\n intervalMs: number;\n deviceSerial?: string;\n timeoutMs?: number;\n logger?: Logger;\n}\n\n/**\n * Capture `count` frames `intervalMs` apart in a single device-side loop, then\n * pull each frame back. Returns the raw JPEG buffers in order. The MCP composites\n * these into a contact sheet + per-frame diff; core just returns the frames.\n */\nexport async function captureBurst(opts: CaptureBurstOptions): Promise<Buffer[]> {\n const count = Math.max(1, Math.floor(opts.count));\n const remoteDir = `/data/local/tmp/oniro_burst_${randomBytes(6).toString('hex')}`;\n const sleepSec = opts.intervalMs > 0 ? (opts.intervalMs / 1000).toFixed(3) : '0';\n // One device-side loop so the frames are device-timed, not gated on host roundtrips.\n const loop =\n `mkdir -p ${remoteDir}; i=0; while [ $i -lt ${count} ]; do ` +\n `snapshot_display -f ${remoteDir}/f$i.jpeg; ` +\n `[ ${count} -gt 1 ] && sleep ${sleepSec}; i=$((i+1)); done`;\n const cap = await shell({ config: opts.config, command: loop, deviceSerial: opts.deviceSerial, timeoutMs: opts.timeoutMs ?? 120_000 });\n ensureOk(cap, 'snapshot_display burst');\n\n const frames: Buffer[] = [];\n try {\n for (let i = 0; i < count; i++) {\n const local = tmpName(`burst_${i}.jpeg`);\n try {\n await recvFile({ config: opts.config, remote: `${remoteDir}/f${i}.jpeg`, local, deviceSerial: opts.deviceSerial });\n frames.push(await fs.promises.readFile(local));\n } finally {\n fs.promises.unlink(local).catch(() => {});\n }\n }\n } finally {\n void shell({ config: opts.config, command: `rm -rf ${remoteDir}`, deviceSerial: opts.deviceSerial }).catch(() => {});\n }\n return frames;\n}\n","import type { ConfigProvider } from '../ports/config.js';\nimport type { Logger } from '../ports/logger.js';\nimport { OniroError } from '../ports/errors.js';\nimport { shellChecked, ensureRemoteOk } from './exec.js';\n\nexport type InputType =\n | 'click'\n | 'doubleClick'\n | 'longClick'\n | 'swipe'\n | 'drag'\n | 'fling'\n | 'keyEvent'\n | 'inputText';\n\nexport interface SendInputOptions {\n config: ConfigProvider;\n type: InputType;\n /** Pixel coordinates. The %→px conversion lives in the MCP, not core. */\n pxX?: number;\n pxY?: number;\n pxX2?: number;\n pxY2?: number;\n /** Velocity for swipe/drag/fling. */\n speed?: number;\n /** Key id or symbolic name (Back/Home/Power) for keyEvent. */\n key?: string | number;\n /** Text for inputText. */\n text?: string;\n deviceSerial?: string;\n logger?: Logger;\n}\n\nfunction reqNum(value: number | undefined, name: string, type: string): number {\n if (value === undefined || Number.isNaN(value)) {\n throw new OniroError(`send input \"${type}\" requires a numeric ${name}.`);\n }\n return value;\n}\n\n/**\n * Build the `uitest uiInput …` command for an input action, in pixel space.\n * Pure (no I/O) so it is unit-testable. Mirrors the proven MCP construction\n * minus the percentage→pixel step.\n */\nexport function buildInputCommand(opts: SendInputOptions): string {\n switch (opts.type) {\n case 'click':\n case 'doubleClick':\n case 'longClick':\n return `uitest uiInput ${opts.type} ${reqNum(opts.pxX, 'pxX', opts.type)} ${reqNum(opts.pxY, 'pxY', opts.type)}`;\n case 'swipe':\n case 'drag':\n case 'fling': {\n const base =\n `uitest uiInput ${opts.type} ${reqNum(opts.pxX, 'pxX', opts.type)} ${reqNum(opts.pxY, 'pxY', opts.type)} ` +\n `${reqNum(opts.pxX2, 'pxX2', opts.type)} ${reqNum(opts.pxY2, 'pxY2', opts.type)}`;\n return opts.speed !== undefined ? `${base} ${opts.speed}` : base;\n }\n case 'keyEvent':\n if (opts.key === undefined || opts.key === '') throw new OniroError('send input \"keyEvent\" requires a key.');\n return `uitest uiInput keyEvent ${opts.key}`;\n case 'inputText': {\n const t = String(opts.text ?? '').replace(/'/g, `'\\\\''`);\n if (opts.pxX !== undefined && opts.pxY !== undefined) {\n return `uitest uiInput inputText ${opts.pxX} ${opts.pxY} '${t}'`;\n }\n return `uitest uiInput text '${t}'`;\n }\n }\n}\n\n/** Inject a UI input action via `uitest uiInput` (pixel coordinates). */\nexport async function sendInput(opts: SendInputOptions): Promise<void> {\n const cmd = buildInputCommand(opts);\n const res = await shellChecked({ config: opts.config, command: cmd, deviceSerial: opts.deviceSerial, timeoutMs: 30_000, logger: opts.logger });\n ensureRemoteOk(res, `hdc shell ${cmd}`);\n}\n\nexport interface Waypoint {\n /** Pixel x. */\n x: number;\n /** Pixel y. */\n y: number;\n /** Time in ms relative to the gesture start. */\n t: number;\n}\n\nexport interface SendGestureOptions {\n config: ConfigProvider;\n waypoints: Waypoint[];\n /** Hold at the first point before moving (ms). Honored via the raw-touch path. */\n holdStartMs?: number;\n /** Hold at the last point before lifting (ms). Honored via the raw-touch path. */\n holdEndMs?: number;\n deviceSerial?: string;\n logger?: Logger;\n}\n\n/**\n * Build the chained `uitest uiInput drag` commands for a multi-segment path.\n * Per segment, speed is derived from the waypoint time deltas (px/s). Pure.\n */\nexport function buildGestureCommands(waypoints: Waypoint[]): string[] {\n if (waypoints.length < 2) {\n throw new OniroError('sendGesture requires at least two waypoints.');\n }\n const cmds: string[] = [];\n for (let i = 1; i < waypoints.length; i++) {\n const a = waypoints[i - 1]!;\n const b = waypoints[i]!;\n const dt = b.t - a.t;\n const dist = Math.hypot(b.x - a.x, b.y - a.y);\n let cmd = `uitest uiInput drag ${a.x} ${a.y} ${b.x} ${b.y}`;\n if (dt > 0 && dist > 0) cmd += ` ${Math.round(dist / (dt / 1000))}`;\n cmds.push(cmd);\n }\n return cmds;\n}\n\nexport interface RawTouchEvent {\n type: 'down' | 'move' | 'up';\n x: number;\n y: number;\n /** Time in ms relative to the gesture start. */\n t: number;\n}\n\nexport interface SendRawTouchOptions {\n config: ConfigProvider;\n events: RawTouchEvent[];\n deviceSerial?: string;\n logger?: Logger;\n}\n\n/**\n * Build a single `uinput -T` touch operation sequence from down/move/up events,\n * interleaving `-i <ms>` intervals from the event time deltas. Pure.\n */\nexport function buildRawTouchCommand(events: RawTouchEvent[]): string {\n if (events.length === 0) throw new OniroError('sendRawTouch requires at least one event.');\n const ops: string[] = [];\n let prev: RawTouchEvent | null = null;\n for (const ev of events) {\n if (prev && ev.t > prev.t) ops.push(`-i ${ev.t - prev.t}`);\n if (ev.type === 'down') ops.push(`-d ${ev.x} ${ev.y}`);\n else if (ev.type === 'up') ops.push(`-u ${ev.x} ${ev.y}`);\n else ops.push(`-m ${prev ? `${prev.x} ${prev.y} ` : ''}${ev.x} ${ev.y}`);\n prev = ev;\n }\n return `uinput -T ${ops.join(' ')}`;\n}\n\n/** Expand a waypoint path (+ optional holds) into raw down/move/up events for\n * the `uinput` escape hatch ({@link sendRawTouch} / {@link buildRawTouchCommand}). */\nexport function waypointsToRawEvents(waypoints: Waypoint[], holdStartMs = 0, holdEndMs = 0): RawTouchEvent[] {\n if (waypoints.length < 2) throw new OniroError('sendGesture requires at least two waypoints.');\n const first = waypoints[0]!;\n const events: RawTouchEvent[] = [{ type: 'down', x: first.x, y: first.y, t: 0 }];\n for (let i = 1; i < waypoints.length; i++) {\n const w = waypoints[i]!;\n events.push({ type: 'move', x: w.x, y: w.y, t: w.t + holdStartMs });\n }\n const last = waypoints[waypoints.length - 1]!;\n events.push({ type: 'up', x: last.x, y: last.y, t: last.t + holdStartMs + holdEndMs });\n return events;\n}\n\n// `uitest uiInput swipe/drag` accepts a velocity in [200, 40000] px/s.\nconst UITEST_VELOCITY_MIN = 200;\nconst UITEST_VELOCITY_MAX = 40000;\n\nexport interface GestureUitestOptions {\n /** A leading press-hold; when > 0 the stroke uses `drag` (press-and-hold,\n * then move) instead of `swipe`. uitest has no arbitrary hold duration. */\n holdStartMs?: number;\n}\n\n/**\n * Build a single continuous `uitest uiInput` stroke for a waypoint path. Pure.\n *\n * uitest has no polyline or stationary-hold primitive, so the path is collapsed\n * to first→last (gesture-nav strokes are straight lines) with the velocity\n * derived from the total elapsed time and clamped to uitest's range. A\n * requested `holdStartMs` maps to `drag` (which presses-and-holds before\n * moving — uitest's nearest equivalent to a leading hold); otherwise `swipe`.\n */\nexport function buildGestureUitestCommand(waypoints: Waypoint[], opts: GestureUitestOptions = {}): string {\n if (waypoints.length < 2) throw new OniroError('sendGesture requires at least two waypoints.');\n const a = waypoints[0]!;\n const b = waypoints[waypoints.length - 1]!;\n const dist = Math.hypot(b.x - a.x, b.y - a.y);\n const dtMs = b.t - a.t;\n const op = (opts.holdStartMs ?? 0) > 0 ? 'drag' : 'swipe';\n let cmd = `uitest uiInput ${op} ${a.x} ${a.y} ${b.x} ${b.y}`;\n if (dtMs > 0 && dist > 0) {\n const v = Math.round(dist / (dtMs / 1000));\n cmd += ` ${Math.max(UITEST_VELOCITY_MIN, Math.min(UITEST_VELOCITY_MAX, v))}`;\n }\n return cmd;\n}\n\n/**\n * Drive a swipe-style gesture via a single continuous `uitest uiInput` stroke —\n * the MMI-injection path that `inputMonitor`-based services (gesture-nav,\n * systemui overlays) actually observe. Preferred over raw `uinput`, whose\n * kernel virtual-device events do not reach `inputMonitor` on some native-boot\n * devices (and whose multi-op form some on-device `uinput` builds reject).\n *\n * uitest has no polyline or stationary-hold primitive: a multi-waypoint path is\n * collapsed to first→last, `holdStartMs` maps to `drag` (press-hold-then-move),\n * and `holdEndMs` has no equivalent (ignored). For true press-time control use\n * {@link sendRawTouch} (raw `uinput`) — accepting the device caveats above.\n */\nexport async function sendGesture(opts: SendGestureOptions): Promise<void> {\n if ((opts.holdEndMs ?? 0) > 0) {\n opts.logger?.warn(\n 'sendGesture: hold-end has no uitest equivalent and is ignored; use sendRawTouch for a trailing hold.',\n );\n }\n if (opts.waypoints.length > 2) {\n opts.logger?.debug(\n `sendGesture: ${opts.waypoints.length} waypoints collapsed to first→last (uitest has no polyline path).`,\n );\n }\n const cmd = buildGestureUitestCommand(opts.waypoints, { holdStartMs: opts.holdStartMs });\n const res = await shellChecked({ config: opts.config, command: cmd, deviceSerial: opts.deviceSerial, timeoutMs: 30_000, logger: opts.logger });\n ensureRemoteOk(res, `hdc shell ${cmd}`);\n}\n\n/**\n * Low-level touch injection via `uinput -T`. The escape hatch when press timing\n * matters (e.g. Quickstep motion-pause), which `uitest uiInput` can't express.\n *\n * WARNING: uinput's gesture form `uinput -T -g x1 y1 x2 y2 [press] [total]`\n * silently no-ops if `press < 500ms` or `total - press < 500ms` (\"press time is\n * out of range\" — it runs nothing). Keep press and post-press windows ≥ 500ms.\n *\n * DEVICE CAVEAT: on some native-boot devices these kernel-`uinput` events never\n * reach MMI `inputMonitor` services (gesture-nav, systemui), and some on-device\n * `uinput` builds reject the multi-op `-d/-m/-u` form with \"wrong number of\n * parameters\". Prefer {@link sendGesture} (uitest) for those; this path now\n * surfaces such failures instead of silently succeeding.\n */\nexport async function sendRawTouch(opts: SendRawTouchOptions): Promise<void> {\n const cmd = buildRawTouchCommand(opts.events);\n const res = await shellChecked({ config: opts.config, command: cmd, deviceSerial: opts.deviceSerial, timeoutMs: 30_000, logger: opts.logger });\n ensureRemoteOk(res, `hdc shell ${cmd}`);\n}\n","import * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport { randomBytes } from 'node:crypto';\nimport type { ConfigProvider } from '../ports/config.js';\nimport type { Logger } from '../ports/logger.js';\nimport { OniroError } from '../ports/errors.js';\nimport { shell, ensureOk } from './exec.js';\nimport { recvFile } from './files.js';\nimport { getDisplaySize, type DisplaySize } from './display.js';\n\n/** A raw `uitest dumpLayout` node (attributes are strings). */\nexport interface RawLayoutNode {\n attributes?: Record<string, string>;\n children?: RawLayoutNode[];\n}\n\n/** A pruned, 0–1-normalized layout node. */\nexport interface LayoutNode {\n /** bounds [x1,y1,x2,y2] normalized to 0–1 of the display. */\n b?: [number, number, number, number];\n /** center [x,y] normalized to 0–1. */\n c?: [number, number];\n type?: string;\n text?: string;\n desc?: string;\n id?: string;\n key?: string;\n bundle?: string;\n click?: boolean;\n check?: boolean;\n checked?: boolean;\n sel?: boolean;\n focus?: boolean;\n scroll?: boolean;\n longClick?: boolean;\n children?: LayoutNode[];\n}\n\nexport interface DumpLayoutResult {\n display: DisplaySize | null;\n tree: LayoutNode;\n}\n\n/** Parse a uitest bounds string `\"[x1,y1][x2,y2]\"` into a tuple, or null. */\nexport function parseBounds(s: string | undefined): [number, number, number, number] | null {\n const m = /^\\[(-?\\d+),(-?\\d+)\\]\\[(-?\\d+),(-?\\d+)\\]$/.exec(s ?? '');\n if (!m) return null;\n return [Number(m[1]), Number(m[2]), Number(m[3]), Number(m[4])];\n}\n\n// Container types that almost never carry useful info on their own.\nconst STRUCTURAL_TYPES = new Set([\n 'Stack', 'Column', 'Row', 'Flex', '__Common__', 'Grid', 'GridItem',\n 'List', 'ListItem', 'Scroll', 'Swiper', 'SwiperContent', 'Navigator',\n 'Tabs', 'TabContent', 'RelativeContainer', 'WaterFlow', 'FlowItem',\n]);\n\nconst FLAG_MAP: ReadonlyArray<[string, keyof LayoutNode]> = [\n ['clickable', 'click'],\n ['checkable', 'check'],\n ['checked', 'checked'],\n ['selected', 'sel'],\n ['focused', 'focus'],\n ['scrollable', 'scroll'],\n ['longClickable', 'longClick'],\n];\n\n/**\n * Prune a raw `uitest dumpLayout` tree into a compact, signal-bearing tree with\n * bounds/center normalized to 0–1 of the display. Structural wrapper nodes with\n * no signal collapse into their children. Returns a node, a flat list of nodes\n * (collapsed wrapper with multiple children), or null (nothing useful). Ported\n * verbatim from the proven MCP `pruneNode`.\n */\nexport function pruneLayout(node: RawLayoutNode, display: DisplaySize | null): LayoutNode | LayoutNode[] | null {\n const a = node.attributes ?? {};\n const px = parseBounds(a.bounds);\n const out: LayoutNode = {};\n if (px && display) {\n const w = display.width || 1;\n const h = display.height || 1;\n out.b = [\n +(px[0] / w).toFixed(3),\n +(px[1] / h).toFixed(3),\n +(px[2] / w).toFixed(3),\n +(px[3] / h).toFixed(3),\n ];\n out.c = [+(((px[0] + px[2]) / 2) / w).toFixed(3), +(((px[1] + px[3]) / 2) / h).toFixed(3)];\n }\n if (a.type && !STRUCTURAL_TYPES.has(a.type)) out.type = a.type;\n if (a.text) out.text = a.text;\n if (a.description) out.desc = a.description;\n if (a.id) out.id = a.id;\n if (a.key && a.key !== a.id) out.key = a.key;\n if (a.bundleName) out.bundle = a.bundleName;\n for (const [attr, short] of FLAG_MAP) {\n if (a[attr] === 'true') (out[short] as boolean) = true;\n }\n\n const children: LayoutNode[] = [];\n for (const c of node.children ?? []) {\n const pc = pruneLayout(c, display);\n if (pc) {\n if (Array.isArray(pc)) children.push(...pc);\n else children.push(pc);\n }\n }\n\n const hasSignal = Boolean(\n out.text || out.desc || out.id || out.key || out.click ||\n out.scroll || out.check || out.longClick || out.bundle ||\n (out.type && out.type !== 'root'),\n );\n\n if (!hasSignal && children.length === 0) return null;\n // Collapse structural wrappers: pass children up to the parent.\n if (!hasSignal) return children.length === 1 ? children[0]! : children;\n\n if (children.length) out.children = children;\n return out;\n}\n\nexport interface DumpLayoutOptions {\n config: ConfigProvider;\n /** Filter to a single window/bundle (`uitest dumpLayout -b '<bundle>'`). */\n bundleName?: string;\n /** When false, return the parsed-but-unpruned tree. Default true. */\n prune?: boolean;\n deviceSerial?: string;\n timeoutMs?: number;\n logger?: Logger;\n}\n\n/**\n * Dump the current on-screen layout via `uitest dumpLayout`, pull the JSON, and\n * return a pruned, 0–1-normalized tree (or the raw parsed tree when `prune:false`).\n */\nexport async function dumpLayout(opts: DumpLayoutOptions): Promise<DumpLayoutResult> {\n const timeoutMs = opts.timeoutMs ?? 30_000;\n const bundleArg = opts.bundleName ? ` -b '${opts.bundleName.replace(/'/g, `'\\\\''`)}'` : '';\n const dump = await shell({ config: opts.config, command: `uitest dumpLayout${bundleArg}`, deviceSerial: opts.deviceSerial, timeoutMs });\n ensureOk(dump, 'uitest dumpLayout');\n\n const m = dump.stdout.match(/saved to:\\s*(\\S+)/i);\n if (!m) throw new OniroError(`Could not parse dumpLayout output:\\n${dump.stdout}`);\n const remote = m[1]!;\n const local = path.join(os.tmpdir(), `oniro_layout_${randomBytes(6).toString('hex')}.json`);\n\n try {\n await recvFile({ config: opts.config, remote, local, deviceSerial: opts.deviceSerial, timeoutMs });\n const parsed = JSON.parse(await fs.promises.readFile(local, 'utf8')) as RawLayoutNode;\n const display = await getDisplaySize(opts.config, { deviceSerial: opts.deviceSerial });\n\n if (opts.prune === false) {\n return { display, tree: parsed as unknown as LayoutNode };\n }\n const prunedRaw = pruneLayout(parsed, display);\n const tree: LayoutNode = Array.isArray(prunedRaw) ? { children: prunedRaw } : prunedRaw ?? { children: [] };\n return { display, tree };\n } finally {\n fs.promises.unlink(local).catch(() => {});\n void shell({ config: opts.config, command: `rm -f ${remote}`, deviceSerial: opts.deviceSerial }).catch(() => {});\n }\n}\n","import { spawn, type ChildProcessWithoutNullStreams } from 'node:child_process';\nimport type { ConfigProvider } from '../ports/config.js';\nimport type { Logger } from '../ports/logger.js';\nimport { noopLogger } from '../ports/logger.js';\nimport { CancelledError, OniroError } from '../ports/errors.js';\nimport { getHdcPath } from '../sdk/paths.js';\nimport { shell } from './exec.js';\nimport { findRunningProcess } from './app.js';\n\nexport type HilogLevel = 'DEBUG' | 'INFO' | 'WARN' | 'ERROR' | 'FATAL';\n\n/** A parsed line of `hdc shell hilog` output. */\nexport interface HilogEntry {\n /** \"MM-DD HH:MM:SS.mmm\". The device timestamp; no year. */\n time: string;\n pid: string;\n tid: string;\n /** Short level letter as printed by hilog: D, I, W, E (F is rare). */\n level: 'D' | 'I' | 'W' | 'E' | 'F';\n tag: string;\n message: string;\n}\n\nexport interface SetHilogLevelOptions {\n config: ConfigProvider;\n level: HilogLevel;\n logger?: Logger;\n}\n\n/**\n * Set the hilog buffer level on the connected device. Resolves when the\n * underlying `hdc shell hilog -b <LEVEL>` exits successfully; rejects with\n * the stderr text if the command fails.\n */\nexport function setHilogLevel(opts: SetHilogLevelOptions): Promise<void> {\n const logger = opts.logger ?? noopLogger;\n const hdc = getHdcPath(opts.config);\n return new Promise((resolve, reject) => {\n const child = spawn(hdc, ['shell', 'hilog', '-b', opts.level]);\n let stderr = '';\n child.stderr.on('data', (chunk: Buffer) => {\n stderr += chunk.toString();\n });\n child.once('error', (err) => {\n logger.error(`[hilog] failed to spawn hdc: ${err.message}`);\n reject(err);\n });\n child.once('close', (code) => {\n if (code === 0) {\n resolve();\n } else {\n const msg = stderr.trim() || `hdc shell hilog -b ${opts.level} exited with code ${code}`;\n logger.error(`[hilog] ${msg}`);\n reject(new Error(msg));\n }\n });\n });\n}\n\nexport interface StreamHilogOptions {\n config: ConfigProvider;\n /** Restrict the stream to a single process id (passed as `-P <pid>`). */\n processId?: string;\n /** Filter by hilog domain, e.g. '0xD003900' (passed as `-D <domain>`). */\n domain?: string | number;\n /** Address a specific device (`-t <serial>`). */\n deviceSerial?: string;\n}\n\n/**\n * Spawn `hdc [-t serial] shell hilog [-P <pid>] [-D <domain>]` and return the\n * child process. The caller owns the stdout/stderr streams (typically wired\n * through `parseHilogLine`) and is responsible for killing the process when\n * streaming should stop.\n */\nexport function streamHilog(opts: StreamHilogOptions): ChildProcessWithoutNullStreams {\n const hdc = getHdcPath(opts.config);\n const args: string[] = [];\n if (opts.deviceSerial) args.push('-t', opts.deviceSerial);\n args.push('shell', 'hilog');\n if (opts.processId && opts.processId.trim() !== '') {\n args.push('-P', opts.processId.trim());\n }\n if (opts.domain !== undefined && `${opts.domain}` !== '') {\n args.push('-D', `${opts.domain}`);\n }\n return spawn(hdc, args);\n}\n\n// `\\S+` is greedy on the tag so values like `C01406/OHOS::RS` aren't split at\n// the first internal colon — the regex backtracks to the last `:` followed by\n// whitespace, which is the actual tag/message separator hilog emits.\nconst HILOG_LINE_RE = /^(\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}\\.\\d{3})\\s+(\\d+)\\s+(\\d+)\\s+([DIWEF])\\s+(\\S+):\\s+(.*)$/;\n\n/**\n * Parse a single line of `hdc shell hilog` output into structured fields.\n * Returns null when the line doesn't match the expected hilog format (e.g.\n * banners, blank lines, or partial chunks).\n */\nexport function parseHilogLine(line: string): HilogEntry | null {\n const match = HILOG_LINE_RE.exec(line);\n if (!match) return null;\n return {\n time: match[1]!,\n pid: match[2]!,\n tid: match[3]!,\n level: match[4]! as HilogEntry['level'],\n tag: match[5]!.trim(),\n message: match[6]!,\n };\n}\n\n/** The searchable text a pattern is tested against: `\"<tag>: <message>\"`. */\nfunction entryText(e: HilogEntry): string {\n return `${e.tag}: ${e.message}`;\n}\n\n/** Collapse consecutive duplicate entries (same level/tag/message), ignoring time/pid. */\nexport function dedupEntries(entries: HilogEntry[]): HilogEntry[] {\n const out: HilogEntry[] = [];\n let lastKey = '';\n for (const e of entries) {\n const key = `${e.level}|${e.tag}|${e.message}`;\n if (key === lastKey) continue;\n out.push(e);\n lastKey = key;\n }\n return out;\n}\n\n/** Resolve a bundle name to its pid for `-P` filtering, or undefined if not running. */\nasync function resolveProcessId(\n config: ConfigProvider,\n bundle: string | undefined,\n deviceSerial?: string,\n): Promise<string | undefined> {\n if (!bundle) return undefined;\n const proc = await findRunningProcess({ config, bundle, deviceSerial });\n return proc?.pid;\n}\n\nexport interface WaitForLogOptions {\n config: ConfigProvider;\n /** Tested against `\"<tag>: <message>\"` of each parsed line. */\n pattern: RegExp;\n timeoutMs: number;\n /** Restrict to a bundle's pid (resolved via pidof; re-resolved on each reconnect). */\n bundle?: string;\n domain?: string | number;\n deviceSerial?: string;\n abortSignal?: AbortSignal;\n logger?: Logger;\n}\n\n/**\n * Resolve with the first hilog entry whose `\"<tag>: <message>\"` matches `pattern`.\n * The underlying stream is auto-respawned if it dies before the deadline, so the\n * wait survives a reboot mid-observation. Rejects on timeout (OniroError) or\n * abort (CancelledError).\n */\nexport function waitForLog(opts: WaitForLogOptions): Promise<HilogEntry> {\n return new Promise<HilogEntry>((resolve, reject) => {\n const deadline = Date.now() + opts.timeoutMs;\n let settled = false;\n let child: ChildProcessWithoutNullStreams | null = null;\n let reconnectTimer: ReturnType<typeof setTimeout> | undefined;\n let buf = '';\n\n const cleanup = (): void => {\n clearTimeout(timer);\n if (reconnectTimer) clearTimeout(reconnectTimer);\n opts.abortSignal?.removeEventListener('abort', onAbort);\n if (child) {\n try {\n child.kill('SIGKILL');\n } catch {\n /* already gone */\n }\n child = null;\n }\n };\n const finish = (entry: HilogEntry): void => {\n if (settled) return;\n settled = true;\n cleanup();\n resolve(entry);\n };\n const fail = (err: Error): void => {\n if (settled) return;\n settled = true;\n cleanup();\n reject(err);\n };\n const onAbort = (): void => fail(new CancelledError('waitForLog cancelled.'));\n const timer = setTimeout(\n () => fail(new OniroError(`No log line matched ${String(opts.pattern)} within ${opts.timeoutMs}ms.`)),\n opts.timeoutMs,\n );\n opts.abortSignal?.addEventListener('abort', onAbort, { once: true });\n\n const spawnStream = async (): Promise<void> => {\n if (settled) return;\n const processId = await resolveProcessId(opts.config, opts.bundle, opts.deviceSerial);\n if (settled) return;\n const stream = streamHilog({ config: opts.config, processId, domain: opts.domain, deviceSerial: opts.deviceSerial });\n child = stream;\n stream.stdout.on('data', (d: Buffer) => {\n buf += d.toString();\n let idx: number;\n while ((idx = buf.indexOf('\\n')) >= 0) {\n const line = buf.slice(0, idx);\n buf = buf.slice(idx + 1);\n const entry = parseHilogLine(line);\n if (entry && opts.pattern.test(entryText(entry))) {\n finish(entry);\n return;\n }\n }\n });\n const onEnd = (): void => {\n if (settled || child !== stream) return;\n child = null;\n if (Date.now() < deadline) {\n // Auto-reconnect (survives a reboot) until the deadline.\n reconnectTimer = setTimeout(() => void spawnStream(), 1_000);\n }\n };\n stream.once('close', onEnd);\n stream.once('error', onEnd);\n };\n\n void spawnStream();\n });\n}\n\nexport interface WatchLogOptions {\n config: ConfigProvider;\n pattern: RegExp;\n /** How long to collect matching entries. */\n durationMs: number;\n bundle?: string;\n domain?: string | number;\n deviceSerial?: string;\n /** Collapse consecutive duplicate lines. Default true. */\n dedup?: boolean;\n abortSignal?: AbortSignal;\n logger?: Logger;\n}\n\n/** Collect all hilog entries matching `pattern` for `durationMs`. Deduped by default. */\nexport function watchLog(opts: WatchLogOptions): Promise<HilogEntry[]> {\n return new Promise<HilogEntry[]>((resolve, reject) => {\n const matches: HilogEntry[] = [];\n let settled = false;\n let child: ChildProcessWithoutNullStreams | null = null;\n let buf = '';\n\n const cleanup = (): void => {\n clearTimeout(timer);\n opts.abortSignal?.removeEventListener('abort', onAbort);\n if (child) {\n try {\n child.kill('SIGKILL');\n } catch {\n /* already gone */\n }\n child = null;\n }\n };\n const done = (): void => {\n if (settled) return;\n settled = true;\n cleanup();\n resolve(opts.dedup === false ? matches : dedupEntries(matches));\n };\n const onAbort = (): void => {\n if (settled) return;\n settled = true;\n cleanup();\n reject(new CancelledError('watchLog cancelled.'));\n };\n const timer = setTimeout(done, opts.durationMs);\n opts.abortSignal?.addEventListener('abort', onAbort, { once: true });\n\n void (async () => {\n const processId = await resolveProcessId(opts.config, opts.bundle, opts.deviceSerial);\n if (settled) return;\n const stream = streamHilog({ config: opts.config, processId, domain: opts.domain, deviceSerial: opts.deviceSerial });\n child = stream;\n stream.stdout.on('data', (d: Buffer) => {\n buf += d.toString();\n let idx: number;\n while ((idx = buf.indexOf('\\n')) >= 0) {\n const line = buf.slice(0, idx);\n buf = buf.slice(idx + 1);\n const entry = parseHilogLine(line);\n if (entry && opts.pattern.test(entryText(entry))) matches.push(entry);\n }\n });\n })();\n });\n}\n\nexport interface DumpLogOptions {\n config: ConfigProvider;\n /** Cap the result to the last N lines (device-side `tail -n`). */\n lines?: number;\n /** Restrict to a bundle's running pid (no output if it isn't running). */\n bundle?: string;\n /** Extended-regex string applied device-side via `grep -E`. */\n grep?: string;\n domain?: string | number;\n deviceSerial?: string;\n timeoutMs?: number;\n logger?: Logger;\n}\n\n/**\n * One-shot `hilog -x` dump, optionally filtered by domain, bundle pid, and a\n * grep regex, capped to the last `lines`. Mirrors the proven MCP get_logs\n * pipeline. Returns parsed entries.\n */\nexport async function dumpLog(opts: DumpLogOptions): Promise<HilogEntry[]> {\n let pipe = 'hilog -x';\n if (opts.domain !== undefined && `${opts.domain}` !== '') pipe += ` -D ${opts.domain}`;\n if (opts.bundle) {\n const proc = await findRunningProcess({ config: opts.config, bundle: opts.bundle, deviceSerial: opts.deviceSerial });\n if (!proc) return [];\n pipe += ` | grep -E '\\\\b${proc.pid}\\\\b'`;\n }\n if (opts.grep) {\n const safeGrep = opts.grep.replace(/'/g, `'\\\\''`);\n pipe += ` | grep -E '${safeGrep}'`;\n }\n if (opts.lines && opts.lines > 0) pipe += ` | tail -n ${Math.floor(opts.lines)}`;\n\n const res = await shell({\n config: opts.config,\n command: pipe,\n deviceSerial: opts.deviceSerial,\n timeoutMs: opts.timeoutMs ?? 30_000,\n logger: opts.logger,\n });\n return res.stdout\n .split('\\n')\n .map((line) => parseHilogLine(line))\n .filter((e): e is HilogEntry => e !== null);\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { spawn } from 'node:child_process';\nimport type { ConfigProvider } from '../ports/config.js';\nimport type { Logger } from '../ports/logger.js';\nimport { noopLogger } from '../ports/logger.js';\nimport { CancelledError, CmdToolsNotInstalledError, OniroError } from '../ports/errors.js';\nimport { getHvigorwPath, getOhosBaseSdkHome, getCmdToolsPath } from '../sdk/paths.js';\n\nexport interface RunHvigorwOptions {\n config: ConfigProvider;\n projectDir: string;\n /** Forwarded as `-p product=<product>`. Default `default`. */\n product?: string;\n /** Forwarded as `-p module=<module>` when set. */\n module?: string;\n /** Forwarded as `-p buildMode=<mode>` when set. */\n buildMode?: string;\n /** hvigor task to run. Default `assembleHap`. */\n task?: string;\n /** Extra raw args appended after the standard ones. */\n extraArgs?: readonly string[];\n /**\n * Build modules in parallel. Default `true`. Pass `false` to add `--no-parallel`\n * for projects that require serial builds.\n */\n parallel?: boolean;\n /** Abort the build; rejects with CancelledError and kills the hvigorw process. */\n abortSignal?: AbortSignal;\n logger?: Logger;\n /**\n * Optional callback for each stdout/stderr chunk, lets callers stream output\n * to a terminal or webview without buffering. Lines also flow through `logger`.\n */\n onOutput?: (chunk: string, stream: 'stdout' | 'stderr') => void;\n}\n\nexport interface RunHvigorwResult {\n exitCode: number;\n}\n\n/**\n * Build the hvigorw argv. Pure (no I/O) so it is unit-testable. `--no-parallel`\n * is added ONLY when `parallel === false` — builds are parallel by default.\n */\nexport function buildHvigorwArgs(opts: {\n task?: string;\n product?: string;\n module?: string;\n buildMode?: string;\n parallel?: boolean;\n extraArgs?: readonly string[];\n}): string[] {\n const args: string[] = [opts.task ?? 'assembleHap', '--mode', 'module'];\n args.push('-p', `product=${opts.product ?? 'default'}`);\n if (opts.module) args.push('-p', `module=${opts.module}`);\n if (opts.buildMode) args.push('-p', `buildMode=${opts.buildMode}`);\n args.push('--stacktrace', '--no-daemon');\n if (opts.parallel === false) args.push('--no-parallel');\n if (opts.extraArgs?.length) args.push(...opts.extraArgs);\n return args;\n}\n\n/**\n * Run the project's `hvigorw` wrapper. Replaces the extension's vscode-tasks indirection\n * and the bash CLI's chained `clean` + `assembleHap` calls with a single direct spawn.\n */\nexport function runHvigorw(opts: RunHvigorwOptions): Promise<RunHvigorwResult> {\n const { config, projectDir } = opts;\n const logger = opts.logger ?? noopLogger;\n\n if (!fs.existsSync(path.join(projectDir, 'build-profile.json5'))) {\n throw new OniroError(`Not an OpenHarmony project: ${projectDir} (build-profile.json5 not found).`);\n }\n if (!fs.existsSync(getCmdToolsPath(config))) {\n throw new CmdToolsNotInstalledError(getCmdToolsPath(config));\n }\n\n const hvigorw = getHvigorwPath(config, projectDir);\n const args = buildHvigorwArgs(opts);\n\n // Ensure hvigorw is executable on POSIX (project-local copies often aren't after a fresh clone).\n if (process.platform !== 'win32') {\n try { fs.chmodSync(hvigorw, 0o755); } catch { /* best effort */ }\n }\n\n const env: NodeJS.ProcessEnv = {\n ...process.env,\n OHOS_BASE_SDK_HOME: getOhosBaseSdkHome(config),\n };\n\n return new Promise((resolve, reject) => {\n if (opts.abortSignal?.aborted) {\n reject(new CancelledError('hvigorw build cancelled.'));\n return;\n }\n logger.info(`[build] ${hvigorw} ${args.join(' ')}`);\n const child = spawn(hvigorw, args, { cwd: projectDir, env, shell: false });\n let settled = false;\n const cleanup = (): void => opts.abortSignal?.removeEventListener('abort', onAbort);\n const onAbort = (): void => {\n if (settled) return;\n settled = true;\n cleanup();\n try {\n child.kill('SIGKILL');\n } catch {\n /* already gone */\n }\n reject(new CancelledError('hvigorw build cancelled.'));\n };\n opts.abortSignal?.addEventListener('abort', onAbort, { once: true });\n child.stdout.on('data', (chunk: Buffer) => {\n const text = chunk.toString();\n opts.onOutput?.(text, 'stdout');\n logger.info(text.trimEnd());\n });\n child.stderr.on('data', (chunk: Buffer) => {\n const text = chunk.toString();\n opts.onOutput?.(text, 'stderr');\n logger.warn(text.trimEnd());\n });\n child.on('error', (err) => {\n if (settled) return;\n settled = true;\n cleanup();\n reject(new OniroError(`Failed to start hvigorw: ${err.message}`, err));\n });\n child.on('close', (code) => {\n if (settled) return;\n settled = true;\n cleanup();\n const exitCode = code ?? 1;\n if (exitCode === 0) resolve({ exitCode });\n else reject(new OniroError(`hvigorw exited with code ${exitCode}`));\n });\n });\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nexport interface ModuleHaps {\n signed: string[];\n unsigned: string[];\n}\n\nexport interface DiscoverHapsOptions {\n projectDir: string;\n /** Max directory recursion depth. Default 8. */\n maxDepth?: number;\n}\n\n/**\n * The build module a HAP belongs to, parsed from its filename\n * (`<module>-<target>-<buildMode>-{signed,unsigned}.hap`): the segment before\n * the first dash. This is the build module NAME — what `--module` refers to and\n * what hvigor stamps into the filename — which, unlike the first path segment,\n * is robust to nested project layouts (e.g. systemui's\n * `product/phone/<folder>/build/.../phone_gestureNavigation-...-signed.hap`,\n * where the module folder is not a top-level directory under projectDir).\n */\nfunction moduleOfHap(hapFileName: string): string {\n const dash = hapFileName.indexOf('-');\n return dash > 0 ? hapFileName.slice(0, dash) : hapFileName.replace(/\\.hap$/i, '');\n}\n\n/**\n * Walk a project's build outputs and group `*-signed.hap` / `*-unsigned.hap`\n * by build module name (parsed from the HAP filename). Skips `node_modules` /\n * `oh_modules` / `.git`. Ported from the proven MCP `findHaps`, extended with\n * per-module grouping so multi-module projects can install the right HAP.\n * Empty object when nothing is built.\n */\nexport async function discoverHaps(opts: DiscoverHapsOptions): Promise<Record<string, ModuleHaps>> {\n const { projectDir } = opts;\n const maxDepth = opts.maxDepth ?? 8;\n const result: Record<string, ModuleHaps> = {};\n\n const walk = async (dir: string, depth: number): Promise<void> => {\n if (depth > maxDepth) return;\n const entries = await fs.promises.readdir(dir, { withFileTypes: true }).catch(() => [] as fs.Dirent[]);\n for (const e of entries) {\n const full = path.join(dir, e.name);\n if (e.isDirectory()) {\n if (e.name === 'node_modules' || e.name === 'oh_modules' || e.name === '.git') continue;\n await walk(full, depth + 1);\n } else if (e.isFile() && e.name.endsWith('.hap')) {\n const moduleName = moduleOfHap(e.name);\n const bucket = (result[moduleName] ??= { signed: [], unsigned: [] });\n if (e.name.includes('unsigned')) bucket.unsigned.push(full);\n else if (e.name.includes('signed')) bucket.signed.push(full);\n }\n }\n };\n\n await walk(projectDir, 0);\n return result;\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport type { ConfigProvider } from '../ports/config.js';\nimport type { Logger } from '../ports/logger.js';\nimport { runProcess, ensureOk, type HdcExecResult, type OutputSink } from '../hdc/exec.js';\nimport { getOhpmPath } from '../sdk/paths.js';\n\nexport interface RunOhpmOptions {\n config: ConfigProvider;\n projectDir: string;\n args: readonly string[];\n timeoutMs?: number;\n abortSignal?: AbortSignal;\n onOutput?: OutputSink;\n logger?: Logger;\n}\n\n/** Run `ohpm <args>` in the project directory. Resolves with the raw result (any exit code). */\nexport function runOhpm(opts: RunOhpmOptions): Promise<HdcExecResult> {\n return runProcess({\n command: getOhpmPath(opts.config),\n args: [...opts.args],\n cwd: opts.projectDir,\n timeoutMs: opts.timeoutMs ?? 600_000,\n abortSignal: opts.abortSignal,\n onOutput: opts.onOutput,\n logger: opts.logger,\n });\n}\n\n/**\n * Install dependencies (`ohpm install --all`) only when `oh_modules/` is missing.\n * Returns `{ installed: true }` when it ran. Throws CommandFailedError if the\n * install ran and failed.\n */\nexport async function ensureOhModules(opts: {\n config: ConfigProvider;\n projectDir: string;\n abortSignal?: AbortSignal;\n onOutput?: OutputSink;\n logger?: Logger;\n}): Promise<{ installed: boolean }> {\n if (fs.existsSync(path.join(opts.projectDir, 'oh_modules'))) {\n return { installed: false };\n }\n const res = await runOhpm({\n config: opts.config,\n projectDir: opts.projectDir,\n args: ['install', '--all'],\n abortSignal: opts.abortSignal,\n onOutput: opts.onOutput,\n logger: opts.logger,\n });\n ensureOk(res, 'ohpm install --all');\n return { installed: true };\n}\n","import type { ConfigProvider } from '../ports/config.js';\nimport type { Logger } from '../ports/logger.js';\nimport { runProcess } from '../hdc/exec.js';\nimport { getCmdToolsBin } from '../sdk/paths.js';\n\nexport interface CodelinterFinding {\n file: string;\n line: number;\n severity: string;\n /** Rule code/id when present in the output, else ''. */\n code: string;\n message: string;\n}\n\nexport interface CodelinterResult {\n /** codelinter process exit code. */\n code: number;\n findings: CodelinterFinding[];\n /** Combined stdout+stderr, for callers that want the raw report. */\n raw: string;\n}\n\nconst FINDING_RE = /^(.*?):(\\d+):(?:\\d+:)?\\s*(error|warning|warn|info)\\b[:\\s-]*(.*)$/i;\nconst TRAILING_CODE_RE = /[([]([\\w@/.\\-]+)[)\\]]\\s*$/;\n\n/**\n * Best-effort parser for codelinter output lines of the shape\n * `<file>:<line>[:<col>]: <severity>: <message> [<rule-code>]`. Lines that don't\n * match are ignored. Exported as a pure function so it is unit-testable.\n */\nexport function parseCodelinterFindings(output: string): CodelinterFinding[] {\n const findings: CodelinterFinding[] = [];\n for (const raw of output.split('\\n')) {\n const m = FINDING_RE.exec(raw.trim());\n if (!m) continue;\n let message = m[4]!.trim();\n let code = '';\n const codeMatch = TRAILING_CODE_RE.exec(message);\n if (codeMatch) {\n code = codeMatch[1]!;\n message = message.slice(0, codeMatch.index).trim();\n }\n findings.push({ file: m[1]!.trim(), line: Number(m[2]), severity: m[3]!.toLowerCase(), code, message });\n }\n return findings;\n}\n\nexport interface RunCodelinterOptions {\n config: ConfigProvider;\n projectDir: string;\n /** Files/globs to lint; when omitted, codelinter is run with no file args. */\n files?: readonly string[];\n timeoutMs?: number;\n abortSignal?: AbortSignal;\n logger?: Logger;\n}\n\n/** Run the OpenHarmony codelinter and return parsed findings + the raw report. */\nexport async function runCodelinter(opts: RunCodelinterOptions): Promise<CodelinterResult> {\n const res = await runProcess({\n command: getCmdToolsBin(opts.config, 'codelinter'),\n args: opts.files?.length ? [...opts.files] : [],\n cwd: opts.projectDir,\n timeoutMs: opts.timeoutMs ?? 600_000,\n abortSignal: opts.abortSignal,\n logger: opts.logger,\n });\n const raw = `${res.stdout}${res.stderr}`;\n return { code: res.code, findings: parseCodelinterFindings(raw), raw };\n}\n","import type { ConfigProvider } from '../ports/config.js';\nimport type { Logger } from '../ports/logger.js';\nimport { noopLogger, scopedLogger } from '../ports/logger.js';\nimport { runHvigorw } from './runHvigorw.js';\nimport { ensureOhModules } from './ohpm.js';\nimport { discoverHaps, type ModuleHaps } from './discoverHaps.js';\n\nexport interface BuildHapOptions {\n config: ConfigProvider;\n projectDir: string;\n product?: string;\n module?: string;\n /** Forwarded as hvigor `buildMode` (e.g. release, debug). */\n mode?: string;\n /** hvigor task. Default `assembleHap`. */\n task?: string;\n /** Run `ohpm install --all` first when `oh_modules/` is missing. Default true. */\n autoInstallDeps?: boolean;\n /** Build modules in parallel. Default true (see runHvigorw). */\n parallel?: boolean;\n abortSignal?: AbortSignal;\n onOutput?: (chunk: string, stream: 'stdout' | 'stderr') => void;\n logger?: Logger;\n}\n\nexport interface BuildHapResult {\n exitCode: number;\n durationMs: number;\n /** Built HAPs grouped by module folder. */\n discoveredHaps: Record<string, ModuleHaps>;\n warnings: string[];\n}\n\n/**\n * High-level build orchestration: ensure deps → run hvigorw → discover the\n * produced HAPs. The single call the CLI and MCP want; `runHvigorw` stays a raw\n * single-spawn primitive.\n */\nexport async function buildHap(opts: BuildHapOptions): Promise<BuildHapResult> {\n const logger = scopedLogger(opts.logger ?? noopLogger, 'build');\n const warnings: string[] = [];\n const start = Date.now();\n\n if (opts.autoInstallDeps !== false) {\n const r = await ensureOhModules({\n config: opts.config,\n projectDir: opts.projectDir,\n abortSignal: opts.abortSignal,\n onOutput: opts.onOutput,\n logger: opts.logger,\n });\n if (r.installed) logger.info('ran ohpm install --all (oh_modules was missing)');\n }\n\n const { exitCode } = await runHvigorw({\n config: opts.config,\n projectDir: opts.projectDir,\n product: opts.product,\n module: opts.module,\n buildMode: opts.mode,\n task: opts.task,\n parallel: opts.parallel,\n abortSignal: opts.abortSignal,\n onOutput: opts.onOutput,\n logger: opts.logger,\n });\n\n const discoveredHaps = await discoverHaps({ projectDir: opts.projectDir });\n const anySigned = Object.values(discoveredHaps).some((m) => m.signed.length > 0);\n if (!anySigned) {\n warnings.push(\n 'No signed HAPs found — configure signingConfigs in build-profile.json5 (unsigned HAPs are rejected by most devices).',\n );\n }\n\n return { exitCode, durationMs: Date.now() - start, discoveredHaps, warnings };\n}\n","/**\n * Conservative project-folder-name validator (no path separators, conservative charset).\n */\nexport function isValidProjectName(name: string): boolean {\n if (!name) return false;\n if (name.includes('/') || name.includes('\\\\')) return false;\n return /^[A-Za-z0-9._-]+$/.test(name);\n}\n\n/**\n * Bundle-name validator. Allows reverse-DNS style identifiers like `com.example.myapp`.\n */\nexport function isValidBundleName(bundleName: string): boolean {\n return /^[A-Za-z][A-Za-z0-9_]*(\\.[A-Za-z][A-Za-z0-9_]*)+$/.test(bundleName);\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nexport interface TemplateOption {\n id: string;\n label: string;\n description: string;\n defaultModuleName: string;\n}\n\ninterface TemplateMeta {\n id?: string;\n label?: string;\n description?: string;\n defaultModuleName?: string;\n}\n\nfunction toHumanTemplateName(folderName: string): string {\n return folderName.replace(/([a-z])([A-Z])/g, '$1 $2');\n}\n\n/**\n * Enumerate templates inside `templateRoot`. Each direct subfolder is a template;\n * per-template metadata (label/description/defaultModuleName) may live in a\n * `template.json` file alongside the template content.\n *\n * Callers own the template root — the CLI ships its own under\n * `<cli-package>/templates/`, the VS Code extension uses `extensionPath/template`.\n */\nexport function listTemplates(templateRoot: string): TemplateOption[] {\n if (!fs.existsSync(templateRoot)) return [];\n const entries = fs.readdirSync(templateRoot, { withFileTypes: true });\n return entries\n .filter((e) => e.isDirectory())\n .map((e) => {\n const dir = path.join(templateRoot, e.name);\n const metaPath = path.join(dir, 'template.json');\n let meta: TemplateMeta = {};\n if (fs.existsSync(metaPath)) {\n try {\n meta = JSON.parse(fs.readFileSync(metaPath, 'utf8')) as TemplateMeta;\n } catch {\n // Ignore malformed template metadata.\n }\n }\n return {\n id: e.name,\n label: meta.label ?? toHumanTemplateName(e.name),\n description: meta.description ?? '',\n defaultModuleName: (meta.defaultModuleName ?? 'entry').trim() || 'entry',\n };\n })\n .sort((a, b) => a.label.localeCompare(b.label));\n}\n\n/**\n * Verify that a template directory contains the files required by the scaffold pipeline.\n * Returns the list of missing relative paths, or [] if the template is complete.\n */\nexport function validateTemplateLayout(templateDir: string, defaultModuleName: string): string[] {\n const required = [\n 'build-profile.json5',\n path.join('AppScope', 'app.json5'),\n path.join(defaultModuleName, 'src', 'main', 'module.json5'),\n path.join(defaultModuleName, 'oh-package.json5'),\n 'hvigorfile.ts',\n ];\n return required.filter((rel) => !fs.existsSync(path.join(templateDir, rel)));\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport type { ConfigProvider } from '../ports/config.js';\nimport type { Logger } from '../ports/logger.js';\nimport { noopLogger } from '../ports/logger.js';\nimport { OniroError } from '../ports/errors.js';\nimport { getOhosBaseSdkHome } from '../sdk/paths.js';\nimport { listTemplates, validateTemplateLayout } from './templates.js';\nimport { isValidBundleName, isValidProjectName } from './validators.js';\nimport { readJson5File, readJsonFile, writeJson5File, writeJsonFile } from './jsonHelpers.js';\n\nconst IGNORED_DIRS = new Set(['oh_modules', 'node_modules', 'build', '.hvigor']);\n\nexport interface CreateScaffoldOptions {\n config: ConfigProvider;\n templateId: string;\n projectName: string;\n bundleName: string;\n /** Parent directory that will contain the new project folder. */\n location: string;\n sdkApi: number;\n /** Module folder name. Defaults to the template's `defaultModuleName`. */\n moduleName?: string;\n /** Absolute path to the directory containing template subfolders. */\n templateRoot: string;\n /** If the destination exists, remove it before scaffolding instead of throwing. */\n overwrite?: boolean;\n logger?: Logger;\n}\n\nexport interface CreateScaffoldResult {\n projectDir: string;\n}\n\n/**\n * Async existence check.\n */\nasync function pathExists(p: string): Promise<boolean> {\n try {\n await fs.promises.access(p);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Recursively copy a template directory, skipping symlinks and template metadata.\n */\nasync function copyDirRecursive(srcDir: string, destDir: string): Promise<void> {\n await fs.promises.mkdir(destDir, { recursive: true });\n const entries = await fs.promises.readdir(srcDir, { withFileTypes: true });\n for (const entry of entries) {\n const src = path.join(srcDir, entry.name);\n const dest = path.join(destDir, entry.name);\n if (entry.isDirectory()) {\n await copyDirRecursive(src, dest);\n } else if (entry.isSymbolicLink()) {\n continue;\n } else if (entry.isFile()) {\n if (entry.name === 'template.json') continue;\n await fs.promises.copyFile(src, dest);\n }\n }\n}\n\n/**\n * Normalize every .json5 file in `projectDir` to strict JSON formatting (quoted keys).\n * Keeps JSON5 parsers happy while letting VS Code's built-in JSON parser handle them.\n */\nasync function normalizeJson5ToJson(projectDir: string, logger: Logger): Promise<void> {\n const stack: string[] = [projectDir];\n while (stack.length > 0) {\n const currentDir = stack.pop()!;\n const entries = await fs.promises.readdir(currentDir, { withFileTypes: true });\n for (const entry of entries) {\n const fullPath = path.join(currentDir, entry.name);\n if (entry.isDirectory()) {\n if (IGNORED_DIRS.has(entry.name)) continue;\n stack.push(fullPath);\n continue;\n }\n if (!entry.isFile() || !entry.name.endsWith('.json5')) continue;\n try {\n const parsed = readJson5File<unknown>(fullPath);\n writeJson5File(fullPath, parsed);\n } catch (err) {\n logger.warn(`Failed to normalize ${fullPath}: ${String(err)}`);\n }\n }\n }\n}\n\nfunction toJavaPropertiesPath(p: string): string {\n return process.platform === 'win32' ? p.replace(/\\\\/g, '\\\\\\\\') : p;\n}\n\nfunction createOrUpdateLocalProperties(projectDir: string, sdkDir: string): void {\n const content = `sdk.dir=${toJavaPropertiesPath(sdkDir)}\\n`;\n fs.writeFileSync(path.join(projectDir, 'local.properties'), content, 'utf8');\n}\n\nfunction renameIfExists(fromPath: string, toPath: string): void {\n if (fs.existsSync(fromPath) && fromPath !== toPath) {\n fs.renameSync(fromPath, toPath);\n }\n}\n\n/**\n * Apply user-selected names/versions to template files. Mirrors the writes done by\n * the extension's `updateTemplateConfigs` so a scaffold is identical regardless of\n * which frontend produced it.\n */\nfunction updateTemplateConfigs(\n projectDir: string,\n args: {\n projectName: string;\n bundleName: string;\n sdkApi: number;\n moduleName: string;\n },\n sdkBaseDir: string,\n): void {\n // 1) AppScope/app.json5 -> bundleName\n const appJsonPath = path.join(projectDir, 'AppScope', 'app.json5');\n if (fs.existsSync(appJsonPath)) {\n const appJson = readJson5File<{ app?: { bundleName?: string } }>(appJsonPath);\n appJson.app = appJson.app ?? {};\n appJson.app.bundleName = args.bundleName;\n writeJson5File(appJsonPath, appJson);\n }\n\n // 2) AppScope/resources/base/element/string.json -> app_name = projectName\n const stringsPath = path.join(projectDir, 'AppScope', 'resources', 'base', 'element', 'string.json');\n if (fs.existsSync(stringsPath)) {\n const strings = readJsonFile<{ string?: Array<{ name?: string; value?: string }> }>(stringsPath);\n if (Array.isArray(strings.string)) {\n const appName = strings.string.find((s) => s.name === 'app_name');\n if (appName) appName.value = args.projectName;\n }\n writeJsonFile(stringsPath, strings);\n }\n\n // 3) build-profile.json5 -> sdk + module name + srcPath\n const buildProfilePath = path.join(projectDir, 'build-profile.json5');\n if (fs.existsSync(buildProfilePath)) {\n const buildProfile = readJson5File<{\n app?: { products?: Array<{ compileSdkVersion?: number; compatibleSdkVersion?: number }> };\n modules?: Array<{ name?: string; srcPath?: string }>;\n }>(buildProfilePath);\n buildProfile.app = buildProfile.app ?? {};\n if (Array.isArray(buildProfile.app.products) && buildProfile.app.products.length > 0) {\n buildProfile.app.products[0]!.compileSdkVersion = args.sdkApi;\n buildProfile.app.products[0]!.compatibleSdkVersion = args.sdkApi;\n }\n if (Array.isArray(buildProfile.modules) && buildProfile.modules.length > 0) {\n buildProfile.modules[0]!.name = args.moduleName;\n buildProfile.modules[0]!.srcPath = `./${args.moduleName}`;\n }\n writeJson5File(buildProfilePath, buildProfile);\n }\n\n // 4) <module>/src/main/module.json5 -> module.name\n const moduleJsonPath = path.join(projectDir, args.moduleName, 'src', 'main', 'module.json5');\n if (fs.existsSync(moduleJsonPath)) {\n const moduleJson = readJson5File<{ module?: { name?: string } }>(moduleJsonPath);\n moduleJson.module = moduleJson.module ?? {};\n moduleJson.module.name = args.moduleName;\n writeJson5File(moduleJsonPath, moduleJson);\n }\n\n // 5) <module>/oh-package.json5 -> name\n const moduleOhPackagePath = path.join(projectDir, args.moduleName, 'oh-package.json5');\n if (fs.existsSync(moduleOhPackagePath)) {\n const pkg = readJson5File<{ name?: string }>(moduleOhPackagePath);\n pkg.name = args.moduleName;\n writeJson5File(moduleOhPackagePath, pkg);\n }\n\n // 6) .vscode/settings.json — useful for users who do open the project in VS Code.\n const vscodeDir = path.join(projectDir, '.vscode');\n fs.mkdirSync(vscodeDir, { recursive: true });\n const hapPath = `${args.moduleName}/build/default/outputs/default/${args.moduleName}-default-signed.hap`;\n writeJsonFile(path.join(vscodeDir, 'settings.json'), {\n 'oniro.hapPath': hapPath,\n 'files.associations': { '*.json5': 'jsonc' },\n });\n\n // 7) local.properties — sdk.dir must point at the OS base SDK home (containing API folders),\n // NOT a specific API folder, otherwise hvigor double-nests the lookup.\n createOrUpdateLocalProperties(projectDir, sdkBaseDir);\n}\n\n/**\n * Scaffold a new Oniro/OpenHarmony project from a template. Returns the absolute path\n * to the created project directory.\n */\nexport async function createScaffold(opts: CreateScaffoldOptions): Promise<CreateScaffoldResult> {\n const logger = opts.logger ?? noopLogger;\n\n if (!isValidProjectName(opts.projectName)) {\n throw new OniroError(`Invalid project name '${opts.projectName}'. Use letters/numbers/._- and no slashes.`);\n }\n if (!isValidBundleName(opts.bundleName)) {\n throw new OniroError(`Invalid bundle name '${opts.bundleName}'. Example: com.example.myapplication`);\n }\n if (!opts.location || !(await pathExists(opts.location))) {\n throw new OniroError(`Location does not exist: ${opts.location}`);\n }\n\n const templateDir = path.join(opts.templateRoot, opts.templateId);\n if (!(await pathExists(templateDir))) {\n throw new OniroError(`Template not found: ${templateDir}`);\n }\n\n const templates = listTemplates(opts.templateRoot);\n const selected = templates.find((t) => t.id === opts.templateId);\n const defaultModuleName = selected?.defaultModuleName ?? 'entry';\n const moduleName = (opts.moduleName ?? defaultModuleName).trim() || defaultModuleName;\n\n const missing = validateTemplateLayout(templateDir, defaultModuleName);\n if (missing.length > 0) {\n throw new OniroError(`Template '${opts.templateId}' is missing required files:\\n- ${missing.join('\\n- ')}`);\n }\n\n const projectDir = path.join(opts.location, opts.projectName);\n if (await pathExists(projectDir)) {\n if (!opts.overwrite) {\n throw new OniroError(`Destination already exists: ${projectDir}. Pass overwrite: true to replace it.`);\n }\n await fs.promises.rm(projectDir, { recursive: true, force: true });\n }\n\n logger.info(`[create] Scaffolding ${opts.templateId} at ${projectDir}`);\n await copyDirRecursive(templateDir, projectDir);\n\n if (moduleName !== defaultModuleName) {\n renameIfExists(path.join(projectDir, defaultModuleName), path.join(projectDir, moduleName));\n }\n\n updateTemplateConfigs(\n projectDir,\n {\n projectName: opts.projectName,\n bundleName: opts.bundleName,\n sdkApi: opts.sdkApi,\n moduleName,\n },\n getOhosBaseSdkHome(opts.config),\n );\n\n await normalizeJson5ToJson(projectDir, logger);\n\n return { projectDir };\n}\n","import * as fs from 'node:fs';\nimport JSON5 from 'json5';\n\nexport function readJson5File<T>(filePath: string): T {\n return JSON5.parse(fs.readFileSync(filePath, 'utf8')) as T;\n}\n\n/**\n * Write strict JSON content (quoted keys) to a `.json5` file. Keeps the file\n * compatible with VS Code's JSON parser while remaining valid JSON5.\n */\nexport function writeJson5File(filePath: string, value: unknown): void {\n fs.writeFileSync(filePath, JSON.stringify(value, null, 2) + '\\n', 'utf8');\n}\n\nexport function readJsonFile<T>(filePath: string): T {\n return JSON.parse(fs.readFileSync(filePath, 'utf8')) as T;\n}\n\nexport function writeJsonFile(filePath: string, value: unknown): void {\n fs.writeFileSync(filePath, JSON.stringify(value, null, 2) + '\\n', 'utf8');\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { OniroError } from '../ports/errors.js';\nimport { readJson5File } from './jsonHelpers.js';\n\nexport interface ProjectModule {\n name: string;\n /** Source path relative to the project root (e.g. `./entry`). */\n srcPath: string;\n /** Target names declared under the module (often empty). */\n targets: string[];\n}\n\ninterface BuildProfile {\n modules?: Array<{ name?: string; srcPath?: string; targets?: Array<{ name?: string }> }>;\n}\n\n/**\n * Read the `modules[]` declared in `build-profile.json5` so callers can target a\n * specific module in a multi-module project.\n */\nexport function listModules(opts: { projectDir: string }): ProjectModule[] {\n const buildProfile = path.join(opts.projectDir, 'build-profile.json5');\n if (!fs.existsSync(buildProfile)) {\n throw new OniroError(`build-profile.json5 not found at ${buildProfile}`);\n }\n const parsed = readJson5File<BuildProfile>(buildProfile);\n return (parsed.modules ?? [])\n .filter((m): m is { name: string; srcPath?: string; targets?: Array<{ name?: string }> } => Boolean(m.name))\n .map((m) => ({\n name: m.name,\n srcPath: m.srcPath ?? `./${m.name}`,\n targets: (m.targets ?? []).map((t) => t.name).filter((n): n is string => Boolean(n)),\n }));\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { OniroError } from '../ports/errors.js';\nimport { readJson5File } from './jsonHelpers.js';\n\nexport interface AbilityInfo {\n name: string;\n type?: string;\n visible?: boolean;\n srcEntry?: string;\n}\n\ninterface ModuleJson {\n module?: { abilities?: Array<{ name?: string; type?: string; visible?: boolean; srcEntry?: string }> };\n}\n\n/**\n * Read all abilities declared in a module's `module.json5` `abilities[]`.\n * Defaults to the `entry` module folder.\n */\nexport function listAbilities(opts: { projectDir: string; moduleName?: string }): AbilityInfo[] {\n const moduleName = opts.moduleName ?? 'entry';\n const moduleJsonPath = path.join(opts.projectDir, moduleName, 'src', 'main', 'module.json5');\n if (!fs.existsSync(moduleJsonPath)) {\n throw new OniroError(`Could not find module.json5 at ${moduleJsonPath}`);\n }\n const parsed = readJson5File<ModuleJson>(moduleJsonPath);\n return (parsed.module?.abilities ?? [])\n .filter((a): a is { name: string; type?: string; visible?: boolean; srcEntry?: string } => Boolean(a.name))\n .map((a) => ({ name: a.name, type: a.type, visible: a.visible, srcEntry: a.srcEntry }));\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport type { ConfigProvider } from '../ports/config.js';\nimport type { Logger } from '../ports/logger.js';\nimport { getOhosBaseSdkHome } from '../sdk/paths.js';\nimport { generateSigningConfigs, type Apl, type AppFeature, type SigningPasswords } from '../sign/generateSigningConfigs.js';\nimport { readJson5File } from './jsonHelpers.js';\n\nexport interface PrepareSigningOptions {\n config: ConfigProvider;\n projectDir: string;\n // Forwarded to the fresh-generate fallback:\n apl?: Apl;\n appFeature?: AppFeature;\n acls?: string[];\n passwords?: SigningPasswords;\n logger?: Logger;\n}\n\nexport interface PrepareSigningResult {\n source: 'present' | 'fresh';\n}\n\n/** A project has usable signing material if `signatures/` exists AND build-profile declares signingConfigs. */\nfunction hasSigningArtifacts(dir: string): boolean {\n if (!fs.existsSync(path.join(dir, 'signatures'))) return false;\n const buildProfile = path.join(dir, 'build-profile.json5');\n if (!fs.existsSync(buildProfile)) return false;\n try {\n const parsed = readJson5File<{ app?: { signingConfigs?: unknown[] } }>(buildProfile);\n return Array.isArray(parsed.app?.signingConfigs) && parsed.app!.signingConfigs!.length > 0;\n } catch {\n return false;\n }\n}\n\n/**\n * Ensure a project has signing material: a no-op when `signatures/` +\n * signingConfigs already exist ('present'), otherwise generate them via\n * {@link generateSigningConfigs} ('fresh', which needs java + the SDK).\n */\nexport function prepareSigning(opts: PrepareSigningOptions): PrepareSigningResult {\n if (hasSigningArtifacts(opts.projectDir)) {\n return { source: 'present' };\n }\n generateSigningConfigs({\n projectDir: opts.projectDir,\n sdkHome: getOhosBaseSdkHome(opts.config),\n apl: opts.apl,\n appFeature: opts.appFeature,\n acls: opts.acls,\n passwords: opts.passwords,\n logger: opts.logger,\n });\n return { source: 'fresh' };\n}\n","import type { ConfigProvider } from '../ports/config.js';\nimport type { Logger } from '../ports/logger.js';\nimport { shell } from '../hdc/exec.js';\n\nexport interface HidumperOptions {\n config: ConfigProvider;\n deviceSerial?: string;\n timeoutMs?: number;\n logger?: Logger;\n}\n\nexport interface ScreenDump {\n width: number;\n height: number;\n /** Raw hidumper screen output. */\n raw: string;\n}\n\n/** `hidumper -s 10 -a screen` → parsed render resolution + raw text, or null. */\nexport async function dumpScreen(opts: HidumperOptions): Promise<ScreenDump | null> {\n const res = await shell({ config: opts.config, command: 'hidumper -s 10 -a screen', deviceSerial: opts.deviceSerial, timeoutMs: opts.timeoutMs ?? 10_000, logger: opts.logger });\n if (res.code !== 0) return null;\n const m = res.stdout.match(/render resolution=(\\d+)x(\\d+)/);\n if (!m) return null;\n return { width: Number(m[1]), height: Number(m[2]), raw: res.stdout };\n}\n\n/** `hidumper -s WindowManagerService -a -a` — windows in z-order with surface presence. */\nexport async function dumpWindow(opts: HidumperOptions): Promise<string> {\n const res = await shell({ config: opts.config, command: 'hidumper -s WindowManagerService -a -a', deviceSerial: opts.deviceSerial, timeoutMs: opts.timeoutMs ?? 15_000, logger: opts.logger });\n return res.stdout;\n}\n\n/** `hidumper -s RenderService -a allInfo` — composition state / refresh rate. */\nexport async function dumpRenderService(opts: HidumperOptions): Promise<string> {\n const res = await shell({ config: opts.config, command: 'hidumper -s RenderService -a allInfo', deviceSerial: opts.deviceSerial, timeoutMs: opts.timeoutMs ?? 15_000, logger: opts.logger });\n return res.stdout;\n}\n","import type { ConfigProvider } from '../ports/config.js';\nimport type { Logger } from '../ports/logger.js';\nimport { paramGet } from '../hdc/param.js';\nimport { dumpScreen } from './hidumper.js';\n\nexport interface DeviceFullInfo {\n serial: string;\n model?: string;\n manufacturer?: string;\n brand?: string;\n osFullName?: string;\n osReleaseType?: string;\n sdkApiVersion?: string;\n buildVersion?: string;\n display: { width: number; height: number } | null;\n}\n\n// Mirrors the MCP get_device_info property set.\nconst PROPS: ReadonlyArray<[keyof DeviceFullInfo, string]> = [\n ['model', 'const.product.model'],\n ['manufacturer', 'const.product.manufacturer'],\n ['brand', 'const.product.brand'],\n ['osFullName', 'const.ohos.fullname'],\n ['osReleaseType', 'const.ohos.releasetype'],\n ['sdkApiVersion', 'const.ohos.apiversion'],\n ['buildVersion', 'const.product.software.version'],\n];\n\nexport interface GetDeviceInfoOptions {\n config: ConfigProvider;\n deviceSerial?: string;\n timeoutMs?: number;\n logger?: Logger;\n}\n\n/** Collate device properties (`param get` × N) and the display resolution. */\nexport async function getDeviceInfo(opts: GetDeviceInfoOptions): Promise<DeviceFullInfo> {\n const info: DeviceFullInfo = { serial: opts.deviceSerial ?? '(default)', display: null };\n\n for (const [field, prop] of PROPS) {\n try {\n const value = await paramGet(opts.config, prop, { deviceSerial: opts.deviceSerial, timeoutMs: opts.timeoutMs ?? 10_000, logger: opts.logger });\n if (value) (info[field] as string) = value;\n } catch {\n // A missing/failed property is left undefined rather than failing the whole collation.\n }\n }\n\n const screen = await dumpScreen({ config: opts.config, deviceSerial: opts.deviceSerial, logger: opts.logger });\n if (screen) info.display = { width: screen.width, height: screen.height };\n return info;\n}\n","import StreamZip from 'node-stream-zip';\n\n// node-stream-zip's types are thin; this is the minimal shape we use (mirrors sdk/extract.ts).\ninterface ZipEntry {\n name: string;\n isDirectory: boolean;\n}\ninterface StreamZipAsync {\n entries(): Promise<Record<string, ZipEntry>>;\n close(): Promise<void>;\n}\n\nexport interface HapAssetDiff {\n /** File paths present in the new HAP but not the installed one. */\n addedAssetPaths: string[];\n /** File paths present in the installed HAP but not the new one. */\n removedAssetPaths: string[];\n}\n\n/** Pure set-diff of two file-name listings, sorted. */\nexport function diffEntryNames(installed: Iterable<string>, next: Iterable<string>): HapAssetDiff {\n const installedSet = new Set(installed);\n const nextSet = new Set(next);\n return {\n addedAssetPaths: [...nextSet].filter((n) => !installedSet.has(n)).sort(),\n removedAssetPaths: [...installedSet].filter((n) => !nextSet.has(n)).sort(),\n };\n}\n\nasync function listFileEntries(hapPath: string): Promise<string[]> {\n const zip = new (StreamZip as unknown as { async: new (cfg: { file: string }) => StreamZipAsync }).async({ file: hapPath });\n try {\n const entries = await zip.entries();\n return Object.values(entries)\n .filter((e) => !e.isDirectory)\n .map((e) => e.name);\n } finally {\n await zip.close();\n }\n}\n\n/**\n * Diff the file manifests of two HAP (zip) archives. Drives the ACE-extractor\n * cache-invalidation reboot decision in `applyChanges`: when the new HAP adds or\n * renames file paths vs the installed one, the path-keyed asset cache can serve\n * stale \"GetAsset failed\" errors until a reboot.\n */\nexport async function diffHapAssets(opts: { installedHap: string; newHap: string }): Promise<HapAssetDiff> {\n const [installed, next] = await Promise.all([listFileEntries(opts.installedHap), listFileEntries(opts.newHap)]);\n return diffEntryNames(installed, next);\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport type { ConfigProvider } from '../ports/config.js';\nimport type { Logger } from '../ports/logger.js';\nimport { noopLogger, scopedLogger } from '../ports/logger.js';\nimport { OniroError } from '../ports/errors.js';\nimport { hdcExec, ensureOk } from '../hdc/exec.js';\nimport { findRunningProcess, uninstallApp } from '../hdc/app.js';\nimport { reboot } from '../hdc/lifecycle.js';\nimport { discoverHaps } from '../build/discoverHaps.js';\nimport { diffHapAssets } from './diffHapAssets.js';\n\nexport type InstallMethod = 'replace' | 'uninstall-install' | 'refuse';\n\n/**\n * P0-5a decision: how to install given whether `hdc install -r` reported a\n * sign-info-inconsistent error (9568332). System bundles are NOT silently\n * uninstalled (that can brick the device) unless explicitly allowed.\n */\nexport function decideInstallMethod(s: {\n signInfoInconsistent: boolean;\n isSystemBundle: boolean;\n allowUninstall: boolean;\n}): InstallMethod {\n if (!s.signInfoInconsistent) return 'replace';\n if (s.isSystemBundle && !s.allowUninstall) return 'refuse';\n return 'uninstall-install';\n}\n\nexport interface RebootDecision {\n reboot: boolean;\n reason: 'asset-cache' | 'pid-unchanged' | 'none';\n}\n\n/**\n * P0-5b/c decision: whether to reboot after installing. Reboot when the HAP's\n * asset paths changed (ACE extractor cache is path-keyed and survives a process\n * kill), or when a persistent/system bundle's process didn't restart.\n */\nexport function decideReboot(s: {\n assetsChanged: boolean;\n isSystemBundle: boolean;\n preInstallPid: number | null;\n postInstallPid: number | null;\n}): RebootDecision {\n if (s.assetsChanged) return { reboot: true, reason: 'asset-cache' };\n if (s.isSystemBundle && s.preInstallPid !== null && s.postInstallPid === s.preInstallPid) {\n return { reboot: true, reason: 'pid-unchanged' };\n }\n return { reboot: false, reason: 'none' };\n}\n\nconst SIGN_INFO_INCONSISTENT = /9568332|sign.*info.*inconsistent/i;\n\nexport interface ApplyChangesOptions {\n config: ConfigProvider;\n bundle: string;\n /** Explicit HAP path. If omitted, resolved from projectDir (+ module) via discoverHaps. */\n hapPath?: string;\n projectDir?: string;\n module?: string;\n /** Local path to the currently-installed HAP; enables the asset-cache diff/reboot. */\n installedHapPath?: string;\n /** Persistent/system bundle (e.g. systemui). Default false. */\n isSystemBundle?: boolean;\n /** Permit uninstalling a system bundle on sign-info mismatch (dangerous). Default false. */\n allowUninstall?: boolean;\n deviceSerial?: string;\n abortSignal?: AbortSignal;\n logger?: Logger;\n}\n\nexport interface ApplyChangesResult {\n method: 'replace' | 'uninstall-install' | 'reboot';\n preInstallPid: number | null;\n postInstallPid: number | null;\n replaced: boolean;\n /** True when an asset-path change forced the reboot. */\n cacheCleared: boolean;\n}\n\nasync function pidOf(config: ConfigProvider, bundle: string, deviceSerial?: string): Promise<number | null> {\n const proc = await findRunningProcess({ config, bundle, deviceSerial });\n return proc ? Number(proc.pid) : null;\n}\n\nasync function resolveHapPath(opts: ApplyChangesOptions): Promise<string> {\n let hapPath = opts.hapPath;\n if (hapPath) {\n if (!path.isAbsolute(hapPath) && opts.projectDir) hapPath = path.join(opts.projectDir, hapPath);\n } else {\n if (!opts.projectDir) throw new OniroError('applyChanges requires hapPath or projectDir.');\n const haps = await discoverHaps({ projectDir: opts.projectDir });\n if (opts.module) {\n const signed = haps[opts.module]?.signed ?? [];\n if (signed.length === 0) throw new OniroError(`No signed HAP for module ${opts.module}. Build first.`);\n hapPath = signed[0]!;\n } else {\n const withSigned = Object.entries(haps).filter(([, m]) => m.signed.length > 0);\n if (withSigned.length === 0) throw new OniroError('No signed HAP found. Build first.');\n if (withSigned.length > 1) {\n throw new OniroError(\n `Multiple modules have signed HAPs (${withSigned.map(([k]) => k).join(', ')}). Pass module to choose.`,\n );\n }\n hapPath = withSigned[0]![1].signed[0]!;\n }\n }\n if (!fs.existsSync(hapPath)) throw new OniroError(`HAP not found at ${hapPath}.`);\n return hapPath;\n}\n\n/**\n * Install a HAP and verify the running process took the change. Handles the\n * three failure modes the naive \"install the most recent signed HAP\" deploy\n * ignores: sign-info-inconsistent on `-r`, asset-cache invalidation, and a\n * persistent bundle that didn't restart. See {@link decideInstallMethod} /\n * {@link decideReboot} for the (pure, tested) branch logic.\n */\nexport async function applyChanges(opts: ApplyChangesOptions): Promise<ApplyChangesResult> {\n const logger = scopedLogger(opts.logger ?? noopLogger, 'apply');\n const { config, bundle, deviceSerial } = opts;\n const isSystemBundle = opts.isSystemBundle ?? false;\n const allowUninstall = opts.allowUninstall ?? false;\n\n const hapPath = await resolveHapPath(opts);\n\n // Asset-path diff (best-effort; only when the caller supplies the installed HAP).\n let assetsChanged = false;\n if (opts.installedHapPath && fs.existsSync(opts.installedHapPath)) {\n try {\n const diff = await diffHapAssets({ installedHap: opts.installedHapPath, newHap: hapPath });\n assetsChanged = diff.addedAssetPaths.length > 0 || diff.removedAssetPaths.length > 0;\n } catch (err) {\n logger.debug(`asset diff skipped: ${(err as Error).message}`);\n }\n }\n\n const preInstallPid = await pidOf(config, bundle, deviceSerial);\n\n // Attempt a replace install, then decide based on the sign-info signal.\n const replaceRes = await hdcExec({ config, args: ['install', '-r', hapPath], deviceSerial, timeoutMs: 300_000 });\n const signInfoInconsistent = SIGN_INFO_INCONSISTENT.test(`${replaceRes.stdout}${replaceRes.stderr}`);\n const decision = decideInstallMethod({ signInfoInconsistent, isSystemBundle, allowUninstall });\n\n let installMethod: 'replace' | 'uninstall-install';\n if (decision === 'refuse') {\n throw new OniroError(\n `Refusing to reinstall system bundle ${bundle}: signing certs are inconsistent (9568332). ` +\n 'Align the signing certs first — uninstalling a system bundle can brick the device. ' +\n 'Pass allowUninstall to override.',\n );\n }\n if (decision === 'uninstall-install') {\n logger.warn(`sign-info inconsistent for ${bundle}; uninstalling then installing fresh.`);\n await uninstallApp({ config, bundle, deviceSerial });\n ensureOk(await hdcExec({ config, args: ['install', hapPath], deviceSerial, timeoutMs: 300_000 }), `hdc install ${hapPath}`);\n installMethod = 'uninstall-install';\n } else {\n ensureOk(replaceRes, `hdc install -r ${hapPath}`);\n installMethod = 'replace';\n }\n\n let postInstallPid = await pidOf(config, bundle, deviceSerial);\n const rebootDecision = decideReboot({ assetsChanged, isSystemBundle, preInstallPid, postInstallPid });\n\n let method: ApplyChangesResult['method'] = installMethod;\n let cacheCleared = false;\n if (rebootDecision.reboot) {\n logger.info(`rebooting (${rebootDecision.reason}) to apply changes to ${bundle}.`);\n await reboot({ config, waitForBundle: bundle, deviceSerial, abortSignal: opts.abortSignal, logger: opts.logger });\n postInstallPid = await pidOf(config, bundle, deviceSerial);\n method = 'reboot';\n cacheCleared = rebootDecision.reason === 'asset-cache';\n }\n\n return { method, preInstallPid, postInstallPid, replaced: installMethod === 'replace', cacheCleared };\n}\n"],"mappings":"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","names":["platform","os","platform","os","path","fs","path","JSON5","fs","os","path","fs","path","followRedirects","resolve","fs","os","path","import_node_stream","import_node_util","pipelineAsync","StreamZip","fs","path","fs","path","fs","path","fs","n","fs","os","path","platform","fs","path","crypto","fs","path","import_node_child_process","import_json5","JSON5","fs","path","fs","os","path","import_node_child_process","import_node_child_process","resolve","resolve","tail","resolve","fs","path","import_node_child_process","fs","path","import_json5","JSON5","module","resolve","fs","os","path","fs","os","path","import_node_crypto","import_node_child_process","resolve","fs","path","import_node_child_process","resolve","fs","path","fs","path","fs","path","fs","path","fs","import_json5","JSON5","fs","path","fs","path","fs","path","import_node_stream_zip","StreamZip","fs","path"]}
|