@deveco-test/hmos-deveco-cli 0.3.0-TD.1.2 → 0.3.0-TD.1.3
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/dist/cli.js +3 -3
- package/docs.zip +0 -0
- package/index.zip +0 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -61,7 +61,7 @@ Available runnable modules:
|
|
|
61
61
|
Installing artifacts to device ${e}...`),await n.installApp(e,r),o){console.log(`Launching ${t}/${o}...`);let s=await n.launchApp(e,t,o);console.log(mo(`
|
|
62
62
|
Application '${t}': ${s}`))}else console.log(`
|
|
63
63
|
Application '${t}' installed successfully (no ability to launch).`)}var Wc=new cb("run").description("Build and run the project on a connected device").option("--module <modules...>","Module(s) to run (format: module or module@target)").option("--device <device>","Target device name or serial").option("--product <product>","Product name (default: default)").option("--build-mode <mode>","Build mode (options: debug, release; default: debug)").option("--ability <ability>","Ability name to launch").option("--uninstall","Uninstall existing app before installation").option("--skip-build","Skip build step and deploy existing artifacts").option("--apply <fileName>","Quick-apply changed files via quickfix (incremental hqf) and restart. <fileName> under project .hvigor/");b()||Wc.option("--hotreload [action]",'Start hot-reload mode (build+deploy with daemon, then exit). Use "stop" to shut down the hvigor daemon.').option("--hotreload-apply <fileName>","Hot-reload changed files (.hvigor/<fileName> list) via daemon hot compile + signed hqf + quickfix, without restarting the app.");Wc.action(async n=>{try{await fb(n)}catch(e){console.error(lb(e.message)),process.exit(1)}});async function db(n,e,t,r,o){let i=new Jt(e,n.rootDir),s=new Te(e,n.rootDir),a=new Set,c=new Set;for(let{moduleName:w,targetName:S}of t)for(let k of n.collectNonHarDependentModuleList(w))a.add(`${k}@${S}`),c.add(k);let l=[...a],d=ao(n,l),h={type:"modules",modulesToBuild:l,moduleTasks:d};for(let w of c)Yi.generate(n.rootDir,w,r,e);await At(n.rootDir,()=>co(i,s,r,o,h,n.rootDir),()=>console.log("Another build is already running for this project. Waiting for completion...")),console.log(`
|
|
64
|
-
`+mo("Build completed successfully."))}async function ub(n,e,t,r,o){let i=new Tt(t),s=te.from(t),a=r[0]?.moduleName||o[0];await Ip(n,e,t,i,s,a)}function pb(n,e){for(let{moduleName:t}of e){let r=n.getModuleType(t);if(r!=="entry"&&r!=="feature"&&r!=="shared")throw new Error(`Module '${t}' '${r}' is not runnable. Specify an entry or feature module.`)}}async function fb(n){let e=G.discover(process.cwd());console.warn(os("Ensure the project source is trusted before proceeding."));let t=await A.new();if(n.skipBuild||t.assertJava(),n.hotreloadApply){await hb(n,e,t);return}if(n.hotreload){await mb(n,e,t);return}if(n.apply){await yb(n,e,t);return}await Rp(n,e,t)}async function mb(n,e,t){if(n.hotreload==="stop"){await Ep(t,e);return}let o=Bc(e,n.module).map(Uc),{moduleName:i,targetName:s}=o[0];_c(n.module,i);let a=new Tt(t),c=te.from(t),l=await ss(c,n.device),d=l.includes("127.0.0.1")||l.includes("localhost"),h=n.product||"default";e.validateProduct(h);let w=e.getBundleName(),S=Ap(e,o,n.ability);Ki.generate(e.rootDir,i,h,t);let k=new Te(t,e.rootDir);console.log(mo("Ensuring hvigor daemon is running (via --sync --daemon, no hap build)...")),await k.ensureDaemonRunning();let re=[`${i}@${h}`];for(let We of e.collectNonHarDependentModuleList(i))re.includes(`${We}@${h}`)||re.push(`${We}@${h}`);console.log(mo("Building hap + starting watch session (socket -> CommonBuild assembleHap --hot-reload-build --watch, kept open)..."));let De=new ar(e.rootDir,t);await De.startWatchSession({moduleSpecs:re,productName:h});let Pe=bp(e,i,s,d,h);await Dp(a,l,w,Pe,S,!!n.uninstall),console.log(mo("Hot-reload watch session active (socket persistent). Edit code, write .hvigor/<file>, then `devecocli run --hotreload-apply <file>` in another terminal. Ctrl+C here to stop.")),De.onSocketDisconnect(()=>{console.log("Daemon disconnected (likely via --hotreload stop). Exiting watch session."),process.exit(0)}),await new Promise(()=>{})}async function hb(n,e,t){let r=n.hotreloadApply;if(!r)throw new Error("hotreload-apply requires --hotreload-apply <fileName> (under .hvigor/)");let o=Bc(e,n.module),{moduleName:i}=Uc(o[0]);_c(n.module,i);let s=te.from(t),a=await ss(s,n.device),c=n.product||"default";e.validateProduct(c);let l=e.getBundleName();Sp(e,i,r);let d=[`${i}@${c}`],h=await vp({applyFileName:r,projectPath:e.rootDir,moduleName:i,productName:c,bundleName:l,toolProvider:t,targetDeviceId:a,moduleSpecs:d});if(!h.success)throw new Error(h.message)}function gb(n,e,t,r){let o=new Set;for(let{moduleName:i,targetName:s}of e)for(let a of n.collectNonHarDependentModuleList(i)){o.add(n.findArtifactPath(a,s,t,r));for(let c of n.findRemoteHspPaths(a,s,r))o.add(c)}return[...o]}async function Rp(n,e,t){let r=Bc(e,n.module),o=r.map(Uc),i=te.from(t);if(await Cp(n.device,i)){await ub(n,e,t,o,r);return}pb(e,o);let s=new Tt(t),a=await ss(i,n.device),c=a.includes("127.0.0.1")||a.includes("localhost"),l=n.product||"default";e.validateProduct(l);let d=n.buildMode||"debug";n.skipBuild||await db(e,t,o,l,d);let h=gb(e,o,c,l),w=e.getBundleName(),S=Ap(e,o,n.ability);await Dp(s,a,w,h,S,!!n.uninstall)}async function yb(n,e,t){let r=n.apply;if(!r)throw new Error("apply requires --apply <fileName> (under .hvigor/)");if(is.basename(r)!==r)throw new Error(`apply file must be a plain file name (under .hvigor/), got: ${r}`);let o=is.join(e.rootDir,".hvigor",r),i=te.from(t),s=await ss(i,n.device),a=n.product||"default";e.validateProduct(a);let c=e.getBundleName(),l=e.profile.modules.find(w=>e.getModuleType(w.name)==="entry")?.name,d=l?e.getMainAbility(l,n.ability):n.ability||"EntryAbility",h=new Ji(t,e.rootDir);try{await h.execute({applyFile:o,productName:a,targetDeviceId:s,bundleName:c,abilityName:d}),console.log(os("[Apply] \u5B8C\u6210\u3002\u82E5\u6539\u52A8\u672A\u751F\u6548\uFF0C\u8BF7\u68C0\u67E5 <module>/build/config/buildConfig.json \u662F\u5426\u6709\u5185\u5BB9\uFF0C\u6216\u6267\u884C devecocli run \u5168\u91CF\u6784\u5EFA\u3002"));return}catch(w){console.warn(os(`[Apply] \u5931\u8D25\uFF1A${w.message}`)),console.warn(os("[Apply] \u81EA\u52A8\u56DE\u9000\u5230\u5168\u91CF devecocli run..."))}await Rp(n,e,t)}var Tp=Wc;import{Command as wb}from"commander";import{green as kp,red as xp,cyan as Gc}from"colorette";import{execa as Np}from"execa";function vb(){return"beta"}function Sb(){return"@deveco-test/hmos-deveco-cli"}function bb(){return"0.3.0-TD.1.
|
|
64
|
+
`+mo("Build completed successfully."))}async function ub(n,e,t,r,o){let i=new Tt(t),s=te.from(t),a=r[0]?.moduleName||o[0];await Ip(n,e,t,i,s,a)}function pb(n,e){for(let{moduleName:t}of e){let r=n.getModuleType(t);if(r!=="entry"&&r!=="feature"&&r!=="shared")throw new Error(`Module '${t}' '${r}' is not runnable. Specify an entry or feature module.`)}}async function fb(n){let e=G.discover(process.cwd());console.warn(os("Ensure the project source is trusted before proceeding."));let t=await A.new();if(n.skipBuild||t.assertJava(),n.hotreloadApply){await hb(n,e,t);return}if(n.hotreload){await mb(n,e,t);return}if(n.apply){await yb(n,e,t);return}await Rp(n,e,t)}async function mb(n,e,t){if(n.hotreload==="stop"){await Ep(t,e);return}let o=Bc(e,n.module).map(Uc),{moduleName:i,targetName:s}=o[0];_c(n.module,i);let a=new Tt(t),c=te.from(t),l=await ss(c,n.device),d=l.includes("127.0.0.1")||l.includes("localhost"),h=n.product||"default";e.validateProduct(h);let w=e.getBundleName(),S=Ap(e,o,n.ability);Ki.generate(e.rootDir,i,h,t);let k=new Te(t,e.rootDir);console.log(mo("Ensuring hvigor daemon is running (via --sync --daemon, no hap build)...")),await k.ensureDaemonRunning();let re=[`${i}@${h}`];for(let We of e.collectNonHarDependentModuleList(i))re.includes(`${We}@${h}`)||re.push(`${We}@${h}`);console.log(mo("Building hap + starting watch session (socket -> CommonBuild assembleHap --hot-reload-build --watch, kept open)..."));let De=new ar(e.rootDir,t);await De.startWatchSession({moduleSpecs:re,productName:h});let Pe=bp(e,i,s,d,h);await Dp(a,l,w,Pe,S,!!n.uninstall),console.log(mo("Hot-reload watch session active (socket persistent). Edit code, write .hvigor/<file>, then `devecocli run --hotreload-apply <file>` in another terminal. Ctrl+C here to stop.")),De.onSocketDisconnect(()=>{console.log("Daemon disconnected (likely via --hotreload stop). Exiting watch session."),process.exit(0)}),await new Promise(()=>{})}async function hb(n,e,t){let r=n.hotreloadApply;if(!r)throw new Error("hotreload-apply requires --hotreload-apply <fileName> (under .hvigor/)");let o=Bc(e,n.module),{moduleName:i}=Uc(o[0]);_c(n.module,i);let s=te.from(t),a=await ss(s,n.device),c=n.product||"default";e.validateProduct(c);let l=e.getBundleName();Sp(e,i,r);let d=[`${i}@${c}`],h=await vp({applyFileName:r,projectPath:e.rootDir,moduleName:i,productName:c,bundleName:l,toolProvider:t,targetDeviceId:a,moduleSpecs:d});if(!h.success)throw new Error(h.message)}function gb(n,e,t,r){let o=new Set;for(let{moduleName:i,targetName:s}of e)for(let a of n.collectNonHarDependentModuleList(i)){o.add(n.findArtifactPath(a,s,t,r));for(let c of n.findRemoteHspPaths(a,s,r))o.add(c)}return[...o]}async function Rp(n,e,t){let r=Bc(e,n.module),o=r.map(Uc),i=te.from(t);if(await Cp(n.device,i)){await ub(n,e,t,o,r);return}pb(e,o);let s=new Tt(t),a=await ss(i,n.device),c=a.includes("127.0.0.1")||a.includes("localhost"),l=n.product||"default";e.validateProduct(l);let d=n.buildMode||"debug";n.skipBuild||await db(e,t,o,l,d);let h=gb(e,o,c,l),w=e.getBundleName(),S=Ap(e,o,n.ability);await Dp(s,a,w,h,S,!!n.uninstall)}async function yb(n,e,t){let r=n.apply;if(!r)throw new Error("apply requires --apply <fileName> (under .hvigor/)");if(is.basename(r)!==r)throw new Error(`apply file must be a plain file name (under .hvigor/), got: ${r}`);let o=is.join(e.rootDir,".hvigor",r),i=te.from(t),s=await ss(i,n.device),a=n.product||"default";e.validateProduct(a);let c=e.getBundleName(),l=e.profile.modules.find(w=>e.getModuleType(w.name)==="entry")?.name,d=l?e.getMainAbility(l,n.ability):n.ability||"EntryAbility",h=new Ji(t,e.rootDir);try{await h.execute({applyFile:o,productName:a,targetDeviceId:s,bundleName:c,abilityName:d}),console.log(os("[Apply] \u5B8C\u6210\u3002\u82E5\u6539\u52A8\u672A\u751F\u6548\uFF0C\u8BF7\u68C0\u67E5 <module>/build/config/buildConfig.json \u662F\u5426\u6709\u5185\u5BB9\uFF0C\u6216\u6267\u884C devecocli run \u5168\u91CF\u6784\u5EFA\u3002"));return}catch(w){console.warn(os(`[Apply] \u5931\u8D25\uFF1A${w.message}`)),console.warn(os("[Apply] \u81EA\u52A8\u56DE\u9000\u5230\u5168\u91CF devecocli run..."))}await Rp(n,e,t)}var Tp=Wc;import{Command as wb}from"commander";import{green as kp,red as xp,cyan as Gc}from"colorette";import{execa as Np}from"execa";function vb(){return"beta"}function Sb(){return"@deveco-test/hmos-deveco-cli"}function bb(){return"0.3.0-TD.1.3"}var Eb=new wb("update").description("Update deveco-cli to latest").action(async()=>{let n=Sb(),e=bb(),t=vb();console.log(Gc("Checking for updates..."));try{let{stdout:r}=await Np("npm",["view",n,`dist-tags.${t}`]),o=r.trim();if(!o||o===e){console.log(kp(`
|
|
65
65
|
${n} is already up to date (v${e}, tag: ${t})`));return}console.log(Gc(`
|
|
66
66
|
New version found: ${o} (current: ${e})`)),console.log(Gc(`Updating ${n}...`)),await Np("npm",["install","-g",`${n}@${t}`],{stdio:"inherit"}),console.log(`
|
|
67
67
|
`+kp(`${n} updated successfully to version ${o}.`))}catch(r){let o=r;console.error(xp(`Failed to update ${n}`)),o.message&&console.error(xp(o.message)),process.exit(1)}}),Lp=Eb;import{Command as Zb}from"commander";import{execa as cs}from"execa";function ve(n){return n.normalize("NFKC").replace(/\s+/g," ").trim()}import{spawn as Pb}from"child_process";var Cb=2500;function Ib(n,e,t,r,o,i){n.once("exit",s=>{if(i())return;clearTimeout(e);let a=t();s===0||s===null?r():o(a||`Emulator process exited with code ${s}`)})}function Ab(n,e,t,r){let o=!1,i=()=>o,s=()=>Buffer.concat(e).toString("utf8").trim(),a=()=>{o||(o=!0,clearTimeout(l),n.removeAllListeners(),n.stderr?.removeAllListeners(),n.stderr?.destroy(),n.unref(),t())},c=d=>{if(!o){o=!0,clearTimeout(l),n.removeAllListeners(),n.stderr?.removeAllListeners();try{n.kill()}catch{}r(new Error(d))}},l=setTimeout(a,Cb);n.once("error",d=>c(d.message)),Ib(n,l,s,a,c,i)}function Op(n,e,t){return m(`Spawning emulator: ${n} ${t.join(" ")}`),new Promise((r,o)=>{let i=[],s=Pb(n,t,{detached:!0,stdio:["ignore","ignore","pipe"],env:{...process.env,DEVECO_SDK_HOME:e},windowsHide:!0});s.stderr?.on("data",a=>i.push(a)),Ab(s,i,r,o)})}import*as lr from"path";function Db(n){let e=new Set,t=[];for(let r of n){let o=JSON.stringify(r);e.has(o)||(e.add(o),t.push(r))}return t}function Rb(n){let e=n.instancePath?.trim();if(e)return lr.dirname(lr.normalize(e)).replace(/\\/g,"/");let t=n.path?.trim();return t?lr.dirname(lr.normalize(t)).replace(/\\/g,"/"):""}function Tb(n){let e=[];return n&&e.push(["-imageRoot",n]),e.push([]),e}function Mp(n,e){return e?[...n,"-bootmode",e]:n}function kb(n,e,t){let r=[Mp(["-start",n],t)],o=Rb(e);if(o)for(let i of Tb(e.imageRoot))r.push(Mp(["-hvd",n,"-path",o,...i],t));return Db(r)}async function _p(n,e,t,r){let o=new Error("No start strategy ran"),i=kb(n,e,r);for(let s of i)try{return await t(s),{ok:!0}}catch(a){o=a}return{ok:!1,lastError:o}}async function zc(n){return(await te.withHdcPath(n).listDevices()).map(t=>t.serial).filter(Ln)}async function qc(n){let e=await zc(n);return e.length===0?[]:(await Promise.all(e.map(r=>Vi(n,r,"ohos.qemu.hvd.name")))).filter(r=>!!r)}async function Fp(n,e){return(await qc(n)).includes(e)}import*as ur from"path";import{existsSync as xb,statSync as Nb}from"fs";function dr(n,e){for(let t of e){let r=n[t];if(typeof r=="string"&&r.trim())return r.trim()}return""}function Lb(n){let e=dr(n,["instancePath","instance_path","InstancePath","instancepath","instanceDir","instance_dir","InstanceDir","deployPath","deploy_path","deployedPath","deployed_path","workPath","work_path","dataPath","data_path"]);if(e)return e;for(let[t,r]of Object.entries(n)){if(typeof r!="string"||!r.trim())continue;let o=t.toLowerCase();if(o.includes("instance")&&(o.includes("path")||o.includes("dir"))||o==="deployedpath")return r.trim()}return""}function Ob(n){return dr(n,["uuid","UUID","Uuid","instanceUuid","instance_uuid","InstanceUuid"])}function Mb(n){let e=n.find(r=>r.instancePath?.trim());if(!e?.instancePath?.trim())return;let t=ur.dirname(ur.normalize(e.instancePath));for(let r of n){if(r.instancePath?.trim())continue;let o=ur.join(t,r.name);xb(o)&&Nb(o).isDirectory()&&(r.instancePath=o.replace(/\\/g,"/"))}}function _b(n){try{let e=JSON.parse(n);return Array.isArray(e)?e.map(t=>{let r=Ob(t),o=dr(t,["deviceType","DeviceType","devicetype"]),i=dr(t,["os.osVersion","osVersion","OsVersion","OSVersion"]);return{name:t.name||t.Name||"",isRunning:t.isRunning===!0||String(t.isRunning).toLowerCase()==="true",instancePath:Lb(t),path:dr(t,["path","Path","hvdPath","hvd_path"]),imageRoot:dr(t,["imageRoot","image_root","ImageRoot"]),uuid:r||void 0,deviceType:o||void 0,osVersion:i||void 0}}).filter(t=>t.name):null}catch{return null}}function Fb(n){let e=[],t=/^(name|isrunning|instancepath|path|imageroot|devicetype|os\.osversion)\s*:\s*(.+)/gim,r=null,o;for(;(o=t.exec(n))!==null;){let[,i,s]=o;if(i.toLowerCase()==="name")r&&e.push(r),r={name:s.trim()};else if(r){let a=i.toLowerCase();a==="isrunning"?r.isRunning=s.trim().toLowerCase()==="true":a==="instancepath"?r.instancePath=s.trim():a==="path"?r.path=s.trim():a==="imageroot"?r.imageRoot=s.trim():a==="devicetype"?r.deviceType=s.trim():a==="os.osversion"&&(r.osVersion=s.trim())}}return r&&e.push(r),e}function jp(n){let t=_b(n)??Fb(n);return Mb(t),t}function Vc(n,e){for(let t of e){let r=n[t];if(typeof r=="string"&&r.trim())return r.trim()}return""}function jb(n){let e=n.downloaded??n.Downloaded;return e===!0||String(e).toLowerCase()==="true"}function Hb(n){if(!jb(n))return null;let e=Vc(n,["osVersion","OsVersion","OSVersion"]),t=Vc(n,["SoftWareVersion","SoftwareVersion","softwareVersion"]),r=Vc(n,["deviceType","DeviceType"]);return!e&&!t?null:{osVersion:e,softwareVersion:t,deviceType:r}}function as(n){let e=n.trim();if(!e)return[];try{let t=JSON.parse(e);if(!Array.isArray(t))return[];let r=[];for(let o of t){if(!o||typeof o!="object")continue;let i=Hb(o);i&&r.push(i)}return r}catch{return[]}}function Hp(n){let t=as(n).map(r=>r.osVersion).filter(Boolean);return[...new Set(t)]}var $p=/no images are available/i,$b="7.0.0",Ub={foldable:["open","half-open","close"],"2in1_foldable":["open","vertical-open","half-open","close"],triplefold:["single","double","triple","left-folded-right-half-folded","left-half-folded-right-expanded","left-expanded-right-folded","left-half-folded-right-folded","left-expanded-right-half-folded","left-half-folded-right-half-folded"]};function at(n){return n.normalize("NFKC").trim().toLowerCase()}function Bb(n,e){let t=n.deviceType?.trim(),r=t?Ub[at(t)]:void 0;if(!r)throw new Error(`Fold-state control is not supported for emulator "${n.name}" (device type: ${t||"unknown"}).`);if(!r.includes(e))throw new Error(`Fold state "${e}" is not supported by emulator "${n.name}" (device type: ${t}). Available states: ${r.join(", ")}.`)}function Wb(n){let e=n.message||"";return $p.test(e)}function Gb(n){return n.normalize("NFKC").match(/(\d+(?:\.\d+){1,3})/)?.[1]}function ho(n,e){return`${n} ${e.join(" ")}`.trim()}function zb(n){switch(n.type){case"gps":return`${n.type}:${n.key}=${n.value}`;case"sensor":return`${n.type}:${n.key}=${n.value}`;case"rotation":case"volume":return`${n.type}:${n.direction}`;case"folded-state":return`${n.type}:${n.state}`;case"battery":return`${n.type}:${n.level}`;case"battery-status":return`${n.type}:${n.status}`;default:return n.type}}var pr=class n{static supportedControlPaths=new Set;emulatorPath;sdkPath;hdcPath;constructor(e,t,r){this.emulatorPath=e,this.sdkPath=t,this.hdcPath=r}static from(e){return new n(e.emulatorPath,e.sdkPath,e.hdcPath)}async executeEmulator(e){return m(`Executing: ${ho(this.emulatorPath,e)}`),cs(this.emulatorPath,e,{stdio:["ignore","pipe","pipe"],env:{...process.env,DEVECO_SDK_HOME:this.sdkPath}})}executeEmulatorDetached(e){return Op(this.emulatorPath,this.sdkPath,e)}async listEmulators(){let{stdout:e}=await this.executeEmulator(["-list","-details"]);return jp(e)}async getDeviceTypeByName(){let e=new Map;try{let t=await this.listEmulators();for(let r of t)r.name&&r.deviceType&&e.set(ve(r.name),r.deviceType)}catch{}return e}async startEmulator(e){let t=await this.listEmulators(),r=ve(e),o=t.find(a=>ve(a.name)===r);if(!o)throw new Error(`Emulator "${e}" not found.`);let i=o.name;if(await this.isAlreadyRunning(i,o))return"already-running";await this.assertSystemImageAvailable(o);let s=await _p(i,o,a=>this.executeEmulatorDetached(a),"snapshot");if(s.ok)return"started";if(await this.isAlreadyRunning(i))return"already-running";throw new Error(`Unable to start emulator "${e}". All methods failed.
|
|
@@ -1299,7 +1299,7 @@ ${t}`}handleData(t){for(this.buffer=Buffer.concat([this.buffer,t]);;){let r=this
|
|
|
1299
1299
|
`):"No valid C/C++ files"}],isError:!0};this.patchSdkPathInCompileCommands(this.manager.projectRoot,this.toolProvider.sdkPath);for(let c of o){await mI(pI);try{let l=await this.checkFile(c);r.push(fI(c,l))}catch(l){t.push(`${c} => wait for diagnostics failed: ${l.message}`)}}let i=t.length>0,s=[];t.length>0&&s.push(t.join(`
|
|
1300
1300
|
`)),r.length>0&&s.push(r.join(`
|
|
1301
1301
|
`));let a=s.join(`
|
|
1302
|
-
`).trim();return!i&&r.length===0&&(a="No diagnostic information collected"),{content:[{type:"text",text:a}],isError:i}}patchSdkPathInCompileCommands(e,t){if(!b())return;let r=Rn(e);if(!Ue.existsSync(r))return;let o=Ue.readFileSync(r,"utf8");if(!o.includes(Gi))return;let i=o.replaceAll(Gi,t);Ue.writeFileSync(r,i,"utf8"),f.info(`[CppCheck] Patched SDK path in compile_commands.json: ${Gi} -> ${t}`)}async checkFile(e){let t=kn(e),r=await Ue.promises.readFile(e,"utf8"),o=Hi(e),i=this.manager.registerDiagnosticCallback(t);this.manager.sendNotification({jsonrpc:"2.0",method:"textDocument/didOpen",params:{textDocument:{uri:t,text:r,languageId:o,version:r.length}}});try{return await i}finally{this.manager.sendNotification({jsonrpc:"2.0",method:"textDocument/didClose",params:{textDocument:{uri:t}}})}}collectValidFiles(e,t){let r=this.manager.projectRoot,o=[];for(let i of e){let s=ia.isAbsolute(i)?i:ia.join(r,i);if(!Ue.existsSync(s)){t.push(`File does not exist: ${i}`);continue}if(!Ue.statSync(s).isFile()){t.push(`Not a regular file: ${i}`);continue}if(!Tn(s)){t.push(`Not a supported C/C++ file: ${i}`);continue}try{o.push(Ue.realpathSync(s))}catch{o.push(s)}}return o}};function fI(n,e){if(Array.isArray(e))return e.length===0?`${n} => no diagnostics`:`${n} => Diagnostic: ${JSON.stringify(e)}`;if(e&&typeof e=="object"&&typeof e.errorMessage=="string"){let t=e.errorMessage;return`${n} diagnostic failed, error_message: ${t}`}return`${n} => diagnostic failed, result: ${JSON.stringify(e)}`}function mI(n){return new Promise(e=>setTimeout(e,n))}import*as Lr from"fs";import*as sa from"path";var Nr=class n{manager;static FEATURE_METHOD_MAP={hover:y.HOVER,definition:y.DEFINITION,declaration:y.DECLARATION,references:y.REFERENCES,implementation:y.IMPLEMENTATION};constructor(e){this.manager=e}async handleLspFeature(e,t){if(!this.manager.ready)return kr();let r=this.resolveSingleFile(t.file);if(!r)return{content:[{type:"text",text:`File does not exist or is not a C/C++ file: ${t.file}`}],isError:!0};let o=n.FEATURE_METHOD_MAP[e];if(!o)return{content:[{type:"text",text:`Unknown feature: ${e}`}],isError:!0};g.info(`[ClangdLspTool] handleLspFeature: ${e} file=${r} line=${t.line} char=${t.character}`);try{let i=await this.withOpenFile(r,async a=>{let c={textDocument:{uri:a},position:{line:t.line,character:t.character}};return e==="references"&&(c.context={includeDeclaration:!0}),this.manager.sendFeatureRequest(o,c)});return{content:[{type:"text",text:i==null?`${e}: no result`:`${e}: ${JSON.stringify(i,null,2)}`}]}}catch(i){return oa(e,i)}}async handleWorkspaceSymbolRaw(e){if(!this.manager.ready)return null;try{let t=await this.manager.sendFeatureRequest(y.WORKSPACE_SYMBOL,{query:e});return Array.isArray(t)?t:t==null?null:[t]}catch(t){return g.error(`[ClangdLspTool] handleWorkspaceSymbolRaw failed: ${t.message}`),null}}async handleDocumentSymbol(e){if(!this.manager.ready)return kr();let t=this.resolveSingleFile(e);if(!t)return{content:[{type:"text",text:`File does not exist or is not a C/C++ file: ${e}`}],isError:!0};g.info(`[ClangdLspTool] handleDocumentSymbol: file=${t}`);try{let r=await this.withOpenFile(t,async i=>this.manager.sendFeatureRequest(y.DOCUMENT_SYMBOL,{textDocument:{uri:i}}));return{content:[{type:"text",text:r==null?"documentSymbol: no result":`documentSymbol: ${JSON.stringify(r,null,2)}`}]}}catch(r){return oa("documentSymbol",r)}}async handleCallHierarchy(e){if(!this.manager.ready)return kr();if(e.direction==="outgoing")return{content:[{type:"text",text:"callHierarchy outgoing is not supported by clangd (incoming only)"}],isError:!0};let t=this.resolveSingleFile(e.file);if(!t)return{content:[{type:"text",text:`File does not exist or is not a C/C++ file: ${e.file}`}],isError:!0};g.info(`[ClangdLspTool] handleCallHierarchy: file=${t} line=${e.line} char=${e.character} direction=${e.direction}`);try{let r=await this.withOpenFile(t,i=>this.fetchCallHierarchyResult(i,e));return{content:[{type:"text",text:`callHierarchy (${e.direction}): ${JSON.stringify(r,null,2)}`}]}}catch(r){return oa("callHierarchy",r)}}async fetchCallHierarchyResult(e,t){let r=await this.manager.sendFeatureRequest(y.PREPARE_CALL_HIERARCHY,{textDocument:{uri:e},position:{line:t.line,character:t.character}}),o=this.normalizeCallHierarchyItems(r);if(o.length===0)return{items:[],calls:[]};let i=await this.collectIncomingCalls(o);return{items:o,calls:i}}normalizeCallHierarchyItems(e){return Array.isArray(e)?e:e?[e]:[]}async collectIncomingCalls(e){let t=[];for(let r of e)t.push(...await this.fetchIncomingCalls(r));return t}async fetchIncomingCalls(e){let t=await this.manager.sendFeatureRequest(y.INCOMING_CALLS,{item:e});return Array.isArray(t)?t:t?[t]:[]}async withOpenFile(e,t){let r=kn(e),o=await Lr.promises.readFile(e,"utf8"),i=Hi(e);g.info(`[ClangdLspTool] withOpenFile didOpen uri=${r} langId=${i} len=${o.length}`),this.manager.sendNotification({jsonrpc:"2.0",method:"textDocument/didOpen",params:{textDocument:{uri:r,text:o,languageId:i,version:o.length}}});try{return await t(r)}finally{this.manager.sendNotification({jsonrpc:"2.0",method:"textDocument/didClose",params:{textDocument:{uri:r}}})}}resolveSingleFile(e){let t=sa.isAbsolute(e)?e:sa.join(this.manager.projectRoot,e);return!Lr.existsSync(t)||!Lr.statSync(t).isFile()||!Tn(t)?null:t}};import{spawn as hI}from"child_process";import*as ca from"fs";import*as Vm from"path";var gI=30*1e3,yI=30*1e3,aa=class{config;client=null;clangdProcess=null;nextRequestId=1;requestCallbacks=new nn;diagnosticWaiters=new Map;lastStartErrorMessage=null;onMessage=()=>{};disposeOnce=null;constructor(e){this.config=e}setOnMessage(e){this.onMessage=e}consumeStartErrorMessage(){let e=this.lastStartErrorMessage;return this.lastStartErrorMessage=null,e}async start(e){let t=!1;try{f.info(`[ClangdLspProxy] clangdPath: ${this.config.clangdPath}`),f.info(`[ClangdLspProxy] workspaceRoot: ${this.config.workspaceRoot}`),f.info(`[ClangdLspProxy] compileCommandsDir: ${this.config.compileCommandsDir}`),this.ensureLogDir(),this.clangdProcess=this.spawnClangd();let r={serverPath:"",logPath:this.config.logPath,indexingDataLocation:this.config.logPath,cwd:this.config.workspaceRoot,nodePath:this.config.nodePath};this.client=new tn(r),this.client.on("message",i=>this.handleRawMessage(i)),this.client.on("error",i=>this.handleError(i)),this.client.attachProcess(this.clangdProcess,{stderrAsError:!1});let o=this.buildInitializeParams();await this.sendLspRequest(y.INITIALIZE,o,ze),f.info("[ClangdLspProxy] initialize response received"),this.sendNotification(y.INITIALIZED,{}),t=!0}catch(r){this.lastStartErrorMessage=r instanceof Error?r.message:String(r),f.error(`[ClangdLspProxy] initialization failed: ${this.lastStartErrorMessage}`),await this.dispose()}e?.(t)}async hover(e){return this.sendLspRequest(y.HOVER,e)}async definition(e){return this.sendLspRequest(y.DEFINITION,e)}async declaration(e){return this.sendLspRequest(y.DECLARATION,e)}async references(e){return this.sendLspRequest(y.REFERENCES,e)}async implementation(e){return this.sendLspRequest(y.IMPLEMENTATION,e)}async documentSymbol(e){return this.sendLspRequest(y.DOCUMENT_SYMBOL,e)}async workspaceSymbol(e){return this.sendLspRequest(y.WORKSPACE_SYMBOL,e)}async prepareCallHierarchy(e){return this.sendLspRequest(y.PREPARE_CALL_HIERARCHY,e)}async incomingCalls(e){return this.sendLspRequest(y.INCOMING_CALLS,e)}async sendFeatureRequest(e,t){return this.sendLspRequest(e,t)}sendDidOpen(e){this.sendNotification(y.DID_OPEN,e)}sendDidChange(e){this.sendNotification(y.DID_CHANGE,e)}sendDidClose(e){this.sendNotification(y.DID_CLOSE,e)}sendNotification(e,t){if(!this.client){f.warn("[ClangdLspProxy] sendNotification before ready, dropped");return}this.client.sendNotification(e,t)}registerDiagnosticCallback(e){let t=this.normalizeClangdUri(e);if(this.diagnosticWaiters.has(t)){f.warn(`[ClangdLspProxy] overwrite existing diagnostic waiter for ${t}`);let r=this.diagnosticWaiters.get(t);clearTimeout(r.timer),this.diagnosticWaiters.delete(t)}return new Promise((r,o)=>{let i=setTimeout(()=>{this.diagnosticWaiters.delete(t)&&o(new Error(`Wait for clangd diagnostics timeout, uri: ${t}`))},yI);this.diagnosticWaiters.set(t,{resolve:r,reject:o,timer:i})})}async dispose(){return this.disposeOnce||(this.disposeOnce=this.performDispose()),this.disposeOnce}async performDispose(){this.requestCallbacks.rejectAll(new Error("ClangdLspProxy disposing"));for(let[,e]of this.diagnosticWaiters)clearTimeout(e.timer),e.reject(new Error("ClangdLspProxy disposing"));if(this.diagnosticWaiters.clear(),this.client&&this.clangdProcess)try{await this.sendLspRequest(y.SHUTDOWN,null,3e3).catch(e=>{f.warn(`[ClangdLspProxy] shutdown request failed: ${e}`)}),this.sendNotification(y.EXIT,null),await this.client.waitForExitOrTimeout(300)}catch(e){f.warn(`[ClangdLspProxy] dispose error: ${e}`)}if(this.clangdProcess){try{this.clangdProcess.exitCode===null&&this.clangdProcess.signalCode===null&&this.clangdProcess.kill()}catch{}this.clangdProcess=null}this.client=null}spawnClangd(){let e=[`--compile-commands-dir=${U(this.config.compileCommandsDir)}`,"--log=info","--pch-storage=memory","--limit-results=100"];f.info(`[ClangdLspProxy] spawn: ${this.config.clangdPath} ${e.join(" ")}`);let t=hI(this.config.clangdPath,e,{cwd:this.config.workspaceRoot,stdio:["pipe","pipe","pipe"],windowsHide:!0});if(!t.stdin||!t.stdout||!t.stderr)throw new Error("Failed to spawn clangd: stdio not available");return t}buildInitializeParams(){let e=tr(this.config.workspaceRoot),t=st(e),r=Vm.basename(e)||"workspace";return{processId:process.pid,clientInfo:{name:"devecocli-mcp-server",version:"0.3.0-TD.1.2"},rootPath:e,rootUri:t,workspaceFolders:[{uri:t,name:r}],capabilities:this.buildClientCapabilities(),initializationOptions:null}}buildClientCapabilities(){return{textDocument:{synchronization:{didOpen:!0,didChange:!0,didClose:!0,willSave:!1,save:!1},publishDiagnostics:{relatedInformation:!0,versionSupport:!1,tagSupport:{valueSet:[1,2]}},hover:{contentFormat:["markdown","plaintext"]},completion:{contextSupport:!1,completionItemKind:{valueSet:[]}},signatureHelp:{signatureInformation:{documentationFormat:["markdown","plaintext"]}},references:{},declaration:{linkSupport:!0},definition:{linkSupport:!0},implementation:{linkSupport:!0},documentSymbol:{hierarchicalDocumentSymbolSupport:!0,symbolKind:{valueSet:[]}},callHierarchy:{dynamicRegistration:!1}},workspace:{symbol:{symbolKind:{valueSet:[]}},configuration:!1,didChangeWatchedFiles:{dynamicRegistration:!1}}}}sendLspRequest(e,t,r=gI){if(!this.client)return Promise.reject(new Error("[ClangdLspProxy] client not ready"));let o=this.nextRequestId++,i=this.requestCallbacks.registerPending(o,e,r);return this.client.sendRequest(e,t,o),i}handleRawMessage(e){let t;try{t=JSON.parse(e)}catch(r){let o=r instanceof Error?r.message:String(r);f.error(`[ClangdLspProxy] JSON parse error: ${o}, raw: ${e.slice(0,200)}`);return}"id"in t&&("result"in t||"error"in t)?this.handleResponse(t):"method"in t?this.handleNotification(t):f.warn(`[ClangdLspProxy] unrecognized message: ${JSON.stringify(t).slice(0,200)}`)}handleResponse(e){let t=e.id;if(t==null||typeof t!="string"&&typeof t!="number")return;let r=t;if(e.error!==void 0){let o=e.error;f.warn(`[ClangdLspProxy] LSP error id=${r}: code=${o.code??-1} message=${o.message??"unknown"}`),this.requestCallbacks.rejectPending(r,new Error(`LSP error ${o.code??-1}: ${o.message??"unknown"}`))}else this.requestCallbacks.resolvePending(r,e.result)}handleNotification(e){let t=e.method;if(t)switch(t){case y.PUBLISH_DIAGNOSTICS:this.handlePublishDiagnostics(e.params);break;case y.PROGRESS:this.onMessage({jsonrpc:R,method:y.PROGRESS,params:e.params});break;case y.WINDOW_SHOW_MESSAGE:f.info(`[ClangdLspProxy] window/showMessage: ${JSON.stringify(e.params)}`);break;case y.WINDOW_LOG_MESSAGE:f.info(`[ClangdLspProxy] window/logMessage: ${JSON.stringify(e.params)}`);break;default:this.onMessage({jsonrpc:R,method:t,params:e.params})}}handlePublishDiagnostics(e){if(!e||!e.uri)return;let t=this.normalizeClangdUri(e.uri),r=this.diagnosticWaiters.get(t);if(!r&&this.diagnosticWaiters.size===1){let s=this.diagnosticWaiters.keys().next().value;r=this.diagnosticWaiters.get(s),r&&this.diagnosticWaiters.delete(s)}else r&&this.diagnosticWaiters.delete(t);if(!r)return;clearTimeout(r.timer);let o=Array.isArray(e.diagnostics)?e.diagnostics:[],i=o.length;f.info(`[ClangdLspProxy] diagnostics received uri=${t} count=${i}`),r.resolve(o)}handleError(e){for(let[,t]of this.diagnosticWaiters)clearTimeout(t.timer),t.reject(e);this.diagnosticWaiters.clear(),this.requestCallbacks.rejectAll(e),this.onMessage({jsonrpc:R,method:y.CPP_ERROR,params:{message:e.message}})}ensureLogDir(){if(this.config.logPath)try{ca.existsSync(this.config.logPath)||ca.mkdirSync(this.config.logPath,{recursive:!0})}catch{}}normalizeClangdUri(e){try{let t=new URL(e);if(t.protocol==="file:"){let r=decodeURIComponent(t.pathname);return process.platform==="win32"&&/^\/[a-zA-Z]:/.test(r)&&(r=r.slice(1)),st(r)}}catch{}return e}};import*as Wo from"path";import*as Ol from"fs";var Go=class{config;proxy=null;isInitialized=!1;onMessage=()=>{};disposeOnce=null;initPromise=null;initDeadlineTimer=null;initResolve=null;initReject=null;resolvedRoot="";constructor(e){this.config=e}setOnMessage(e){this.onMessage=e}get ready(){return this.isInitialized&&this.proxy!==null}get projectRoot(){return this.resolvedRoot}async start(){if(!this.isInitialized){if(this.initPromise){await this.initPromise;return}this.initPromise=this.doStart();try{await this.initPromise}catch(e){throw this.initPromise=null,e}}}sendNotification(e){if(!this.proxy){f.warn("[ClangdLspManager] sendNotification before LSP ready, dropped");return}this.dispatchNotification(e)}async sendFeatureRequest(e,t){if(!this.proxy)throw new Error("[ClangdLspManager] LSP not ready");return this.proxy.sendFeatureRequest(e,t)}registerDiagnosticCallback(e){return this.proxy?this.proxy.registerDiagnosticCallback(e):Promise.reject(new Error("[ClangdLspManager] LSP not ready"))}static async handleSyncCppProject(e,t){if(f.info("[ClangdLspManager] Received cpp/syncProject"),!e)return f.error("[ClangdLspManager] handleSyncCppProject: workspaceRoot or devecoPath is empty"),{status:"failed",reason:"workspaceRoot or devecoPath is empty"};if(Nn(e).length===0)return f.info("[ClangdLspManager] No C++ modules found, skipping compileNative"),{status:"success"};let o=await Li(e,async()=>{try{return await Xu(e,t),f.info("[ClangdLspManager] compileNative + merge compile_commands completed"),{status:"success"}}catch(i){let s=i instanceof Error?i.message:String(i);return f.error(`[ClangdLspManager] compileNative failed: ${s}`),{status:"failed",reason:s}}});return o.acquired?o.result:(f.info("[ClangdLspManager] Build lock held by another process, skipping sync"),{status:"skipped",reason:"build lock held by another process"})}async dispose(){return this.disposeOnce||(this.disposeOnce=this.performDispose()),this.disposeOnce}doStart(){return new Promise((e,t)=>{this.initResolve=e,this.initReject=t,this.armInitTimer(ze);try{this.startProxy()}catch(r){this.failInit(r instanceof Error?r:new Error(String(r)))}})}startProxy(){let e=Dt(this.config.workspaceRoot);this.resolvedRoot=e?ue(e):ue(this.config.workspaceRoot);let t=this.config.logPath??this.getLogPath();Wi(t);let r=this.config.toolProvider.clangdPath;if(!r){let s="clangd executable not found inside DevEco Studio SDK";f.error(`[ClangdLspManager] ${s}`),this.failInit(new Error(s));return}let o=Wo.dirname(Rn(this.resolvedRoot));try{Ol.mkdirSync(o,{recursive:!0})}catch(s){f.warn(`[ClangdLspManager] Failed to create compile_commands dir: ${s}`)}f.info(`[ClangdLspManager] clangdPath: ${r}`),f.info(`[ClangdLspManager] workspaceRoot: ${this.resolvedRoot}`),f.info(`[ClangdLspManager] compileCommandsDir: ${o}`);let i=new aa({clangdPath:r,workspaceRoot:this.resolvedRoot,compileCommandsDir:o,logPath:t,nodePath:this.config.toolProvider.nodePath});i.setOnMessage(s=>this.handleLspMessage(s)),this.proxy=i,i.start(s=>this.handleProxyInitialized(s)).catch(s=>{let a=s instanceof Error?s:new Error(String(s));this.handleProxyInitialized(!1,a.message)})}handleProxyInitialized=(e,t)=>{if(this.clearInitTimer(),e){this.isInitialized=!0,f.info("[ClangdLspManager] clangd initialized");let r=this.initResolve;this.clearInitHandlers(),r?.()}else{let r=t??this.proxy?.consumeStartErrorMessage()??"unknown error";f.error(`[ClangdLspManager] clangd initialization failed: ${r}`),this.isInitialized=!1,this.proxy=null;let o=this.initReject;this.clearInitHandlers(),o?.(new Error(`C++ LSP initialize failed: ${r}`))}};handleLspMessage(e){this.onMessage(e)}dispatchNotification(e){if(!this.proxy)return;let t=e,r=t.method;if(!r){f.warn("[ClangdLspManager] dispatchNotification: missing method");return}let o=t.params;switch(r){case y.DID_OPEN:this.proxy.sendDidOpen(o);break;case y.DID_CHANGE:this.proxy.sendDidChange(o);break;case y.DID_CLOSE:this.proxy.sendDidClose(o);break;default:this.proxy.sendNotification(r,o)}}armInitTimer(e){this.clearInitTimer(),this.initDeadlineTimer=setTimeout(()=>{this.failInit(new Error("C++ LSP initialize timeout"))},e)}clearInitTimer(){this.initDeadlineTimer&&(clearTimeout(this.initDeadlineTimer),this.initDeadlineTimer=null)}clearInitHandlers(){this.clearInitTimer(),this.initResolve=null,this.initReject=null}failInit(e){let t=this.initReject;this.clearInitHandlers(),t?.(e)}async performDispose(){let e=this.initReject;if(this.clearInitHandlers(),e?.(new Error("ClangdLspManager disposing")),this.proxy){try{await this.proxy.dispose()}catch(t){f.warn(`[ClangdLspManager] proxy dispose error: ${t}`)}this.proxy=null}this.isInitialized=!1,this.initPromise=null}getLogPath(){try{let e=Wo.join(Kt(),"CppCheck"),t=`${Date.now()}${process.hrtime.bigint()%1000000n}`,r=Wo.join(e,"lsp-log",t);return Ol.mkdirSync(r,{recursive:!0}),ue(r)}catch{return"auto"}}};function Jm(n){let e=Mi(n);return f.info(`[SyncGuard] ${e.reason}`),e}var _l=(s=>(s[s.IDLE=0]="IDLE",s[s.DISCOVERING=1]="DISCOVERING",s[s.SYNCING=2]="SYNCING",s[s.INITIALIZING=3]="INITIALIZING",s[s.READY=4]="READY",s[s.ERROR=5]="ERROR",s))(_l||{}),Km=(s=>(s[s.IDLE_CPP=0]="IDLE_CPP",s[s.DISCOVERING_CPP=1]="DISCOVERING_CPP",s[s.SYNCING_CPP=2]="SYNCING_CPP",s[s.INITIALIZING_CPP=3]="INITIALIZING_CPP",s[s.READY_CPP=4]="READY_CPP",s[s.ERROR_CPP=5]="ERROR_CPP",s))(Km||{}),an=3,Ml=600*1e3,la=class{server;toolRouter;config;arktsCheckTool=null;cppCheckTool=null;cppLspTool=null;cppLspManager=null;projectState=0;workspaceRoot="";initPromise=null;needsReinit=!1;initRetryCount=0;originalProjectPath="";configChangedTriggeredResync=!1;syncSkippedDueToLock=!1;syncSkipStartedAt=0;standardProtocolAvailable=!1;cppProjectState=0;cppInitPromise=null;cppNeedsReinit=!1;cppInitRetryCount=0;cppSyncSkippedDueToLock=!1;cppSyncSkipStartedAt=0;cppHasNoCppCode=!1;constructor(e){this.config=e,xn(e.debug??!1);let t,r=e.projectPath?.trim()??"";this.originalProjectPath=r,r==="."?(t=process.cwd(),g.info(`Constructor: configuredPath is '.', startPath: '${t}'`)):r===""?(t="",g.info("Constructor: configuredPath is empty, startPath remains empty")):(t=r,g.info(`Constructor: using configured path as startPath: '${t}'`));let o=Dt(t);g.info(`Constructor: findHarmonyProject('${t}') => ${o??"null"}`),this.config.projectPath=o??void 0,this.server=new wI({name:"devecocli-mcp-server",version:"0.0.1"}),this.toolRouter=kl(),this.standardProtocolAvailable=this.detectStandardProtocolAvailable(),this.registerTools()}registerTools(){this.registerCheckTool(),b()||this.registerLspFeatureTools()}registerCheckTool(){this.toolRouter.add({name:"check",description:"Perform static syntax analysis on HarmonyOS project source files and return structured diagnostics. Supported languages: ArkTS and C/C++.",inputSchema:Se.object({files:Se.array(Se.string()).min(1).describe("List of source file paths to check, relative to the project root. Supports ArkTS and C/C++ files in the same call.")})},async e=>this.handleCheckCall(e))}registerLspFeatureTools(){if(!this.standardProtocolAvailable){g.info("Skip registering LSP feature tools (hover/definition/declaration/references/implementation, workspaceSymbol, documentSymbol, callHierarchy): standard LSP protocol unavailable (standardIndex/index.js not found). These tools require a DevEco Studio version that ships the standard LSP server entry.");return}let e=Se.object({file:Se.string().describe("Source file path, relative to the project root. Supports .ets (ArkTS) and C/C++ extensions."),line:Se.number().describe("Line number (0-based)"),character:Se.number().describe("Character offset in the line (0-based)")});for(let{name:t,description:r,feature:o}of this.getPositionFeatures())this.toolRouter.add({name:t,description:r,inputSchema:e},async i=>this.handleLspFeatureCall(o,i));this.registerSymbolTools(),this.registerCallHierarchyTool()}getPositionFeatures(){return[{name:"hover",description:"Get hover information (type info, documentation) at a specific position in an ArkTS (.ets) or C/C++ file.",feature:"hover"},{name:"definition",description:"Find where the symbol at the given position is defined. Returns file path, line, and character.",feature:"definition"},{name:"declaration",description:"Find the declaration of the symbol at the given position. In ArkTS, this may differ from definition.",feature:"declaration"},{name:"references",description:"Find all references to the symbol at the given position across the HarmonyOS project.",feature:"references"},{name:"implementation",description:"Find implementations of the symbol at the given position (e.g., interface implementations).",feature:"implementation"}]}registerSymbolTools(){this.toolRouter.add({name:"workspaceSymbol",description:"Search for symbols by name across the entire HarmonyOS project.",inputSchema:Se.object({query:Se.string().describe("Symbol name (or partial) to search for")})},async e=>this.handleWorkspaceSymbolCall(e)),this.toolRouter.add({name:"documentSymbol",description:"Get the symbol tree (functions, classes, variables with ranges) of an ArkTS (.ets) or C/C++ file. Useful for file overview, structured code breakdown, and large file slicing.",inputSchema:Se.object({file:Se.string().describe("Source file path, relative to the project root. Supports .ets and C/C++ extensions.")})},async e=>this.handleDocumentSymbolCall(e))}registerCallHierarchyTool(){this.toolRouter.add({name:"callHierarchy",description:'Query call hierarchy for a function at the given position. Use direction "incoming" to find callers, "outgoing" to find callees. ArkTS supports both directions; C/C++ (clangd) supports incoming only.',inputSchema:Se.object({file:Se.string().describe("Source file path, relative to the project root. Supports .ets and C/C++ extensions."),line:Se.number().describe("Line number (0-based)"),character:Se.number().describe("Character offset in the line (0-based)"),direction:Se.enum(["incoming","outgoing"]).describe('"incoming" = who calls this function, "outgoing" = what this function calls')})},async e=>this.handleCallHierarchyCall(e))}detectStandardProtocolAvailable(){try{let e=this.config.toolProvider.lspServerPath;if(!e)return g.info("Standard LSP protocol unavailable: arkts-lang-server path not found"),!1;let t=cn.join(cn.dirname(e),"standardIndex","index.js"),r=Ym.existsSync(t);return g.info(`ArktsCheck protocol: ${r?"standard LSP":"legacy ace-server"} (standardIndex/index.js exists=${r})`),r}catch(e){return g.warn(`Failed to detect standard LSP protocol availability: ${e}`),!1}}validateContainment(e){let t=this.config.projectPath;if(t){let o=[];for(let i of e){let s=P.isPathContainedWithSymlink(i,t);s.contained||(g.warn(`Containment check failed: ${s.reason}`),o.push(s.reason))}return o.length>0?{content:[{type:"text",text:o.join(`
|
|
1302
|
+
`).trim();return!i&&r.length===0&&(a="No diagnostic information collected"),{content:[{type:"text",text:a}],isError:i}}patchSdkPathInCompileCommands(e,t){if(!b())return;let r=Rn(e);if(!Ue.existsSync(r))return;let o=Ue.readFileSync(r,"utf8");if(!o.includes(Gi))return;let i=o.replaceAll(Gi,t);Ue.writeFileSync(r,i,"utf8"),f.info(`[CppCheck] Patched SDK path in compile_commands.json: ${Gi} -> ${t}`)}async checkFile(e){let t=kn(e),r=await Ue.promises.readFile(e,"utf8"),o=Hi(e),i=this.manager.registerDiagnosticCallback(t);this.manager.sendNotification({jsonrpc:"2.0",method:"textDocument/didOpen",params:{textDocument:{uri:t,text:r,languageId:o,version:r.length}}});try{return await i}finally{this.manager.sendNotification({jsonrpc:"2.0",method:"textDocument/didClose",params:{textDocument:{uri:t}}})}}collectValidFiles(e,t){let r=this.manager.projectRoot,o=[];for(let i of e){let s=ia.isAbsolute(i)?i:ia.join(r,i);if(!Ue.existsSync(s)){t.push(`File does not exist: ${i}`);continue}if(!Ue.statSync(s).isFile()){t.push(`Not a regular file: ${i}`);continue}if(!Tn(s)){t.push(`Not a supported C/C++ file: ${i}`);continue}try{o.push(Ue.realpathSync(s))}catch{o.push(s)}}return o}};function fI(n,e){if(Array.isArray(e))return e.length===0?`${n} => no diagnostics`:`${n} => Diagnostic: ${JSON.stringify(e)}`;if(e&&typeof e=="object"&&typeof e.errorMessage=="string"){let t=e.errorMessage;return`${n} diagnostic failed, error_message: ${t}`}return`${n} => diagnostic failed, result: ${JSON.stringify(e)}`}function mI(n){return new Promise(e=>setTimeout(e,n))}import*as Lr from"fs";import*as sa from"path";var Nr=class n{manager;static FEATURE_METHOD_MAP={hover:y.HOVER,definition:y.DEFINITION,declaration:y.DECLARATION,references:y.REFERENCES,implementation:y.IMPLEMENTATION};constructor(e){this.manager=e}async handleLspFeature(e,t){if(!this.manager.ready)return kr();let r=this.resolveSingleFile(t.file);if(!r)return{content:[{type:"text",text:`File does not exist or is not a C/C++ file: ${t.file}`}],isError:!0};let o=n.FEATURE_METHOD_MAP[e];if(!o)return{content:[{type:"text",text:`Unknown feature: ${e}`}],isError:!0};g.info(`[ClangdLspTool] handleLspFeature: ${e} file=${r} line=${t.line} char=${t.character}`);try{let i=await this.withOpenFile(r,async a=>{let c={textDocument:{uri:a},position:{line:t.line,character:t.character}};return e==="references"&&(c.context={includeDeclaration:!0}),this.manager.sendFeatureRequest(o,c)});return{content:[{type:"text",text:i==null?`${e}: no result`:`${e}: ${JSON.stringify(i,null,2)}`}]}}catch(i){return oa(e,i)}}async handleWorkspaceSymbolRaw(e){if(!this.manager.ready)return null;try{let t=await this.manager.sendFeatureRequest(y.WORKSPACE_SYMBOL,{query:e});return Array.isArray(t)?t:t==null?null:[t]}catch(t){return g.error(`[ClangdLspTool] handleWorkspaceSymbolRaw failed: ${t.message}`),null}}async handleDocumentSymbol(e){if(!this.manager.ready)return kr();let t=this.resolveSingleFile(e);if(!t)return{content:[{type:"text",text:`File does not exist or is not a C/C++ file: ${e}`}],isError:!0};g.info(`[ClangdLspTool] handleDocumentSymbol: file=${t}`);try{let r=await this.withOpenFile(t,async i=>this.manager.sendFeatureRequest(y.DOCUMENT_SYMBOL,{textDocument:{uri:i}}));return{content:[{type:"text",text:r==null?"documentSymbol: no result":`documentSymbol: ${JSON.stringify(r,null,2)}`}]}}catch(r){return oa("documentSymbol",r)}}async handleCallHierarchy(e){if(!this.manager.ready)return kr();if(e.direction==="outgoing")return{content:[{type:"text",text:"callHierarchy outgoing is not supported by clangd (incoming only)"}],isError:!0};let t=this.resolveSingleFile(e.file);if(!t)return{content:[{type:"text",text:`File does not exist or is not a C/C++ file: ${e.file}`}],isError:!0};g.info(`[ClangdLspTool] handleCallHierarchy: file=${t} line=${e.line} char=${e.character} direction=${e.direction}`);try{let r=await this.withOpenFile(t,i=>this.fetchCallHierarchyResult(i,e));return{content:[{type:"text",text:`callHierarchy (${e.direction}): ${JSON.stringify(r,null,2)}`}]}}catch(r){return oa("callHierarchy",r)}}async fetchCallHierarchyResult(e,t){let r=await this.manager.sendFeatureRequest(y.PREPARE_CALL_HIERARCHY,{textDocument:{uri:e},position:{line:t.line,character:t.character}}),o=this.normalizeCallHierarchyItems(r);if(o.length===0)return{items:[],calls:[]};let i=await this.collectIncomingCalls(o);return{items:o,calls:i}}normalizeCallHierarchyItems(e){return Array.isArray(e)?e:e?[e]:[]}async collectIncomingCalls(e){let t=[];for(let r of e)t.push(...await this.fetchIncomingCalls(r));return t}async fetchIncomingCalls(e){let t=await this.manager.sendFeatureRequest(y.INCOMING_CALLS,{item:e});return Array.isArray(t)?t:t?[t]:[]}async withOpenFile(e,t){let r=kn(e),o=await Lr.promises.readFile(e,"utf8"),i=Hi(e);g.info(`[ClangdLspTool] withOpenFile didOpen uri=${r} langId=${i} len=${o.length}`),this.manager.sendNotification({jsonrpc:"2.0",method:"textDocument/didOpen",params:{textDocument:{uri:r,text:o,languageId:i,version:o.length}}});try{return await t(r)}finally{this.manager.sendNotification({jsonrpc:"2.0",method:"textDocument/didClose",params:{textDocument:{uri:r}}})}}resolveSingleFile(e){let t=sa.isAbsolute(e)?e:sa.join(this.manager.projectRoot,e);return!Lr.existsSync(t)||!Lr.statSync(t).isFile()||!Tn(t)?null:t}};import{spawn as hI}from"child_process";import*as ca from"fs";import*as Vm from"path";var gI=30*1e3,yI=30*1e3,aa=class{config;client=null;clangdProcess=null;nextRequestId=1;requestCallbacks=new nn;diagnosticWaiters=new Map;lastStartErrorMessage=null;onMessage=()=>{};disposeOnce=null;constructor(e){this.config=e}setOnMessage(e){this.onMessage=e}consumeStartErrorMessage(){let e=this.lastStartErrorMessage;return this.lastStartErrorMessage=null,e}async start(e){let t=!1;try{f.info(`[ClangdLspProxy] clangdPath: ${this.config.clangdPath}`),f.info(`[ClangdLspProxy] workspaceRoot: ${this.config.workspaceRoot}`),f.info(`[ClangdLspProxy] compileCommandsDir: ${this.config.compileCommandsDir}`),this.ensureLogDir(),this.clangdProcess=this.spawnClangd();let r={serverPath:"",logPath:this.config.logPath,indexingDataLocation:this.config.logPath,cwd:this.config.workspaceRoot,nodePath:this.config.nodePath};this.client=new tn(r),this.client.on("message",i=>this.handleRawMessage(i)),this.client.on("error",i=>this.handleError(i)),this.client.attachProcess(this.clangdProcess,{stderrAsError:!1});let o=this.buildInitializeParams();await this.sendLspRequest(y.INITIALIZE,o,ze),f.info("[ClangdLspProxy] initialize response received"),this.sendNotification(y.INITIALIZED,{}),t=!0}catch(r){this.lastStartErrorMessage=r instanceof Error?r.message:String(r),f.error(`[ClangdLspProxy] initialization failed: ${this.lastStartErrorMessage}`),await this.dispose()}e?.(t)}async hover(e){return this.sendLspRequest(y.HOVER,e)}async definition(e){return this.sendLspRequest(y.DEFINITION,e)}async declaration(e){return this.sendLspRequest(y.DECLARATION,e)}async references(e){return this.sendLspRequest(y.REFERENCES,e)}async implementation(e){return this.sendLspRequest(y.IMPLEMENTATION,e)}async documentSymbol(e){return this.sendLspRequest(y.DOCUMENT_SYMBOL,e)}async workspaceSymbol(e){return this.sendLspRequest(y.WORKSPACE_SYMBOL,e)}async prepareCallHierarchy(e){return this.sendLspRequest(y.PREPARE_CALL_HIERARCHY,e)}async incomingCalls(e){return this.sendLspRequest(y.INCOMING_CALLS,e)}async sendFeatureRequest(e,t){return this.sendLspRequest(e,t)}sendDidOpen(e){this.sendNotification(y.DID_OPEN,e)}sendDidChange(e){this.sendNotification(y.DID_CHANGE,e)}sendDidClose(e){this.sendNotification(y.DID_CLOSE,e)}sendNotification(e,t){if(!this.client){f.warn("[ClangdLspProxy] sendNotification before ready, dropped");return}this.client.sendNotification(e,t)}registerDiagnosticCallback(e){let t=this.normalizeClangdUri(e);if(this.diagnosticWaiters.has(t)){f.warn(`[ClangdLspProxy] overwrite existing diagnostic waiter for ${t}`);let r=this.diagnosticWaiters.get(t);clearTimeout(r.timer),this.diagnosticWaiters.delete(t)}return new Promise((r,o)=>{let i=setTimeout(()=>{this.diagnosticWaiters.delete(t)&&o(new Error(`Wait for clangd diagnostics timeout, uri: ${t}`))},yI);this.diagnosticWaiters.set(t,{resolve:r,reject:o,timer:i})})}async dispose(){return this.disposeOnce||(this.disposeOnce=this.performDispose()),this.disposeOnce}async performDispose(){this.requestCallbacks.rejectAll(new Error("ClangdLspProxy disposing"));for(let[,e]of this.diagnosticWaiters)clearTimeout(e.timer),e.reject(new Error("ClangdLspProxy disposing"));if(this.diagnosticWaiters.clear(),this.client&&this.clangdProcess)try{await this.sendLspRequest(y.SHUTDOWN,null,3e3).catch(e=>{f.warn(`[ClangdLspProxy] shutdown request failed: ${e}`)}),this.sendNotification(y.EXIT,null),await this.client.waitForExitOrTimeout(300)}catch(e){f.warn(`[ClangdLspProxy] dispose error: ${e}`)}if(this.clangdProcess){try{this.clangdProcess.exitCode===null&&this.clangdProcess.signalCode===null&&this.clangdProcess.kill()}catch{}this.clangdProcess=null}this.client=null}spawnClangd(){let e=[`--compile-commands-dir=${U(this.config.compileCommandsDir)}`,"--log=info","--pch-storage=memory","--limit-results=100"];f.info(`[ClangdLspProxy] spawn: ${this.config.clangdPath} ${e.join(" ")}`);let t=hI(this.config.clangdPath,e,{cwd:this.config.workspaceRoot,stdio:["pipe","pipe","pipe"],windowsHide:!0});if(!t.stdin||!t.stdout||!t.stderr)throw new Error("Failed to spawn clangd: stdio not available");return t}buildInitializeParams(){let e=tr(this.config.workspaceRoot),t=st(e),r=Vm.basename(e)||"workspace";return{processId:process.pid,clientInfo:{name:"devecocli-mcp-server",version:"0.3.0-TD.1.3"},rootPath:e,rootUri:t,workspaceFolders:[{uri:t,name:r}],capabilities:this.buildClientCapabilities(),initializationOptions:null}}buildClientCapabilities(){return{textDocument:{synchronization:{didOpen:!0,didChange:!0,didClose:!0,willSave:!1,save:!1},publishDiagnostics:{relatedInformation:!0,versionSupport:!1,tagSupport:{valueSet:[1,2]}},hover:{contentFormat:["markdown","plaintext"]},completion:{contextSupport:!1,completionItemKind:{valueSet:[]}},signatureHelp:{signatureInformation:{documentationFormat:["markdown","plaintext"]}},references:{},declaration:{linkSupport:!0},definition:{linkSupport:!0},implementation:{linkSupport:!0},documentSymbol:{hierarchicalDocumentSymbolSupport:!0,symbolKind:{valueSet:[]}},callHierarchy:{dynamicRegistration:!1}},workspace:{symbol:{symbolKind:{valueSet:[]}},configuration:!1,didChangeWatchedFiles:{dynamicRegistration:!1}}}}sendLspRequest(e,t,r=gI){if(!this.client)return Promise.reject(new Error("[ClangdLspProxy] client not ready"));let o=this.nextRequestId++,i=this.requestCallbacks.registerPending(o,e,r);return this.client.sendRequest(e,t,o),i}handleRawMessage(e){let t;try{t=JSON.parse(e)}catch(r){let o=r instanceof Error?r.message:String(r);f.error(`[ClangdLspProxy] JSON parse error: ${o}, raw: ${e.slice(0,200)}`);return}"id"in t&&("result"in t||"error"in t)?this.handleResponse(t):"method"in t?this.handleNotification(t):f.warn(`[ClangdLspProxy] unrecognized message: ${JSON.stringify(t).slice(0,200)}`)}handleResponse(e){let t=e.id;if(t==null||typeof t!="string"&&typeof t!="number")return;let r=t;if(e.error!==void 0){let o=e.error;f.warn(`[ClangdLspProxy] LSP error id=${r}: code=${o.code??-1} message=${o.message??"unknown"}`),this.requestCallbacks.rejectPending(r,new Error(`LSP error ${o.code??-1}: ${o.message??"unknown"}`))}else this.requestCallbacks.resolvePending(r,e.result)}handleNotification(e){let t=e.method;if(t)switch(t){case y.PUBLISH_DIAGNOSTICS:this.handlePublishDiagnostics(e.params);break;case y.PROGRESS:this.onMessage({jsonrpc:R,method:y.PROGRESS,params:e.params});break;case y.WINDOW_SHOW_MESSAGE:f.info(`[ClangdLspProxy] window/showMessage: ${JSON.stringify(e.params)}`);break;case y.WINDOW_LOG_MESSAGE:f.info(`[ClangdLspProxy] window/logMessage: ${JSON.stringify(e.params)}`);break;default:this.onMessage({jsonrpc:R,method:t,params:e.params})}}handlePublishDiagnostics(e){if(!e||!e.uri)return;let t=this.normalizeClangdUri(e.uri),r=this.diagnosticWaiters.get(t);if(!r&&this.diagnosticWaiters.size===1){let s=this.diagnosticWaiters.keys().next().value;r=this.diagnosticWaiters.get(s),r&&this.diagnosticWaiters.delete(s)}else r&&this.diagnosticWaiters.delete(t);if(!r)return;clearTimeout(r.timer);let o=Array.isArray(e.diagnostics)?e.diagnostics:[],i=o.length;f.info(`[ClangdLspProxy] diagnostics received uri=${t} count=${i}`),r.resolve(o)}handleError(e){for(let[,t]of this.diagnosticWaiters)clearTimeout(t.timer),t.reject(e);this.diagnosticWaiters.clear(),this.requestCallbacks.rejectAll(e),this.onMessage({jsonrpc:R,method:y.CPP_ERROR,params:{message:e.message}})}ensureLogDir(){if(this.config.logPath)try{ca.existsSync(this.config.logPath)||ca.mkdirSync(this.config.logPath,{recursive:!0})}catch{}}normalizeClangdUri(e){try{let t=new URL(e);if(t.protocol==="file:"){let r=decodeURIComponent(t.pathname);return process.platform==="win32"&&/^\/[a-zA-Z]:/.test(r)&&(r=r.slice(1)),st(r)}}catch{}return e}};import*as Wo from"path";import*as Ol from"fs";var Go=class{config;proxy=null;isInitialized=!1;onMessage=()=>{};disposeOnce=null;initPromise=null;initDeadlineTimer=null;initResolve=null;initReject=null;resolvedRoot="";constructor(e){this.config=e}setOnMessage(e){this.onMessage=e}get ready(){return this.isInitialized&&this.proxy!==null}get projectRoot(){return this.resolvedRoot}async start(){if(!this.isInitialized){if(this.initPromise){await this.initPromise;return}this.initPromise=this.doStart();try{await this.initPromise}catch(e){throw this.initPromise=null,e}}}sendNotification(e){if(!this.proxy){f.warn("[ClangdLspManager] sendNotification before LSP ready, dropped");return}this.dispatchNotification(e)}async sendFeatureRequest(e,t){if(!this.proxy)throw new Error("[ClangdLspManager] LSP not ready");return this.proxy.sendFeatureRequest(e,t)}registerDiagnosticCallback(e){return this.proxy?this.proxy.registerDiagnosticCallback(e):Promise.reject(new Error("[ClangdLspManager] LSP not ready"))}static async handleSyncCppProject(e,t){if(f.info("[ClangdLspManager] Received cpp/syncProject"),!e)return f.error("[ClangdLspManager] handleSyncCppProject: workspaceRoot or devecoPath is empty"),{status:"failed",reason:"workspaceRoot or devecoPath is empty"};if(Nn(e).length===0)return f.info("[ClangdLspManager] No C++ modules found, skipping compileNative"),{status:"success"};let o=await Li(e,async()=>{try{return await Xu(e,t),f.info("[ClangdLspManager] compileNative + merge compile_commands completed"),{status:"success"}}catch(i){let s=i instanceof Error?i.message:String(i);return f.error(`[ClangdLspManager] compileNative failed: ${s}`),{status:"failed",reason:s}}});return o.acquired?o.result:(f.info("[ClangdLspManager] Build lock held by another process, skipping sync"),{status:"skipped",reason:"build lock held by another process"})}async dispose(){return this.disposeOnce||(this.disposeOnce=this.performDispose()),this.disposeOnce}doStart(){return new Promise((e,t)=>{this.initResolve=e,this.initReject=t,this.armInitTimer(ze);try{this.startProxy()}catch(r){this.failInit(r instanceof Error?r:new Error(String(r)))}})}startProxy(){let e=Dt(this.config.workspaceRoot);this.resolvedRoot=e?ue(e):ue(this.config.workspaceRoot);let t=this.config.logPath??this.getLogPath();Wi(t);let r=this.config.toolProvider.clangdPath;if(!r){let s="clangd executable not found inside DevEco Studio SDK";f.error(`[ClangdLspManager] ${s}`),this.failInit(new Error(s));return}let o=Wo.dirname(Rn(this.resolvedRoot));try{Ol.mkdirSync(o,{recursive:!0})}catch(s){f.warn(`[ClangdLspManager] Failed to create compile_commands dir: ${s}`)}f.info(`[ClangdLspManager] clangdPath: ${r}`),f.info(`[ClangdLspManager] workspaceRoot: ${this.resolvedRoot}`),f.info(`[ClangdLspManager] compileCommandsDir: ${o}`);let i=new aa({clangdPath:r,workspaceRoot:this.resolvedRoot,compileCommandsDir:o,logPath:t,nodePath:this.config.toolProvider.nodePath});i.setOnMessage(s=>this.handleLspMessage(s)),this.proxy=i,i.start(s=>this.handleProxyInitialized(s)).catch(s=>{let a=s instanceof Error?s:new Error(String(s));this.handleProxyInitialized(!1,a.message)})}handleProxyInitialized=(e,t)=>{if(this.clearInitTimer(),e){this.isInitialized=!0,f.info("[ClangdLspManager] clangd initialized");let r=this.initResolve;this.clearInitHandlers(),r?.()}else{let r=t??this.proxy?.consumeStartErrorMessage()??"unknown error";f.error(`[ClangdLspManager] clangd initialization failed: ${r}`),this.isInitialized=!1,this.proxy=null;let o=this.initReject;this.clearInitHandlers(),o?.(new Error(`C++ LSP initialize failed: ${r}`))}};handleLspMessage(e){this.onMessage(e)}dispatchNotification(e){if(!this.proxy)return;let t=e,r=t.method;if(!r){f.warn("[ClangdLspManager] dispatchNotification: missing method");return}let o=t.params;switch(r){case y.DID_OPEN:this.proxy.sendDidOpen(o);break;case y.DID_CHANGE:this.proxy.sendDidChange(o);break;case y.DID_CLOSE:this.proxy.sendDidClose(o);break;default:this.proxy.sendNotification(r,o)}}armInitTimer(e){this.clearInitTimer(),this.initDeadlineTimer=setTimeout(()=>{this.failInit(new Error("C++ LSP initialize timeout"))},e)}clearInitTimer(){this.initDeadlineTimer&&(clearTimeout(this.initDeadlineTimer),this.initDeadlineTimer=null)}clearInitHandlers(){this.clearInitTimer(),this.initResolve=null,this.initReject=null}failInit(e){let t=this.initReject;this.clearInitHandlers(),t?.(e)}async performDispose(){let e=this.initReject;if(this.clearInitHandlers(),e?.(new Error("ClangdLspManager disposing")),this.proxy){try{await this.proxy.dispose()}catch(t){f.warn(`[ClangdLspManager] proxy dispose error: ${t}`)}this.proxy=null}this.isInitialized=!1,this.initPromise=null}getLogPath(){try{let e=Wo.join(Kt(),"CppCheck"),t=`${Date.now()}${process.hrtime.bigint()%1000000n}`,r=Wo.join(e,"lsp-log",t);return Ol.mkdirSync(r,{recursive:!0}),ue(r)}catch{return"auto"}}};function Jm(n){let e=Mi(n);return f.info(`[SyncGuard] ${e.reason}`),e}var _l=(s=>(s[s.IDLE=0]="IDLE",s[s.DISCOVERING=1]="DISCOVERING",s[s.SYNCING=2]="SYNCING",s[s.INITIALIZING=3]="INITIALIZING",s[s.READY=4]="READY",s[s.ERROR=5]="ERROR",s))(_l||{}),Km=(s=>(s[s.IDLE_CPP=0]="IDLE_CPP",s[s.DISCOVERING_CPP=1]="DISCOVERING_CPP",s[s.SYNCING_CPP=2]="SYNCING_CPP",s[s.INITIALIZING_CPP=3]="INITIALIZING_CPP",s[s.READY_CPP=4]="READY_CPP",s[s.ERROR_CPP=5]="ERROR_CPP",s))(Km||{}),an=3,Ml=600*1e3,la=class{server;toolRouter;config;arktsCheckTool=null;cppCheckTool=null;cppLspTool=null;cppLspManager=null;projectState=0;workspaceRoot="";initPromise=null;needsReinit=!1;initRetryCount=0;originalProjectPath="";configChangedTriggeredResync=!1;syncSkippedDueToLock=!1;syncSkipStartedAt=0;standardProtocolAvailable=!1;cppProjectState=0;cppInitPromise=null;cppNeedsReinit=!1;cppInitRetryCount=0;cppSyncSkippedDueToLock=!1;cppSyncSkipStartedAt=0;cppHasNoCppCode=!1;constructor(e){this.config=e,xn(e.debug??!1);let t,r=e.projectPath?.trim()??"";this.originalProjectPath=r,r==="."?(t=process.cwd(),g.info(`Constructor: configuredPath is '.', startPath: '${t}'`)):r===""?(t="",g.info("Constructor: configuredPath is empty, startPath remains empty")):(t=r,g.info(`Constructor: using configured path as startPath: '${t}'`));let o=Dt(t);g.info(`Constructor: findHarmonyProject('${t}') => ${o??"null"}`),this.config.projectPath=o??void 0,this.server=new wI({name:"devecocli-mcp-server",version:"0.0.1"}),this.toolRouter=kl(),this.standardProtocolAvailable=this.detectStandardProtocolAvailable(),this.registerTools()}registerTools(){this.registerCheckTool(),b()||this.registerLspFeatureTools()}registerCheckTool(){this.toolRouter.add({name:"check",description:"Perform static syntax analysis on HarmonyOS project source files and return structured diagnostics. Supported languages: ArkTS and C/C++.",inputSchema:Se.object({files:Se.array(Se.string()).min(1).describe("List of source file paths to check, relative to the project root. Supports ArkTS and C/C++ files in the same call.")})},async e=>this.handleCheckCall(e))}registerLspFeatureTools(){if(!this.standardProtocolAvailable){g.info("Skip registering LSP feature tools (hover/definition/declaration/references/implementation, workspaceSymbol, documentSymbol, callHierarchy): standard LSP protocol unavailable (standardIndex/index.js not found). These tools require a DevEco Studio version that ships the standard LSP server entry.");return}let e=Se.object({file:Se.string().describe("Source file path, relative to the project root. Supports .ets (ArkTS) and C/C++ extensions."),line:Se.number().describe("Line number (0-based)"),character:Se.number().describe("Character offset in the line (0-based)")});for(let{name:t,description:r,feature:o}of this.getPositionFeatures())this.toolRouter.add({name:t,description:r,inputSchema:e},async i=>this.handleLspFeatureCall(o,i));this.registerSymbolTools(),this.registerCallHierarchyTool()}getPositionFeatures(){return[{name:"hover",description:"Get hover information (type info, documentation) at a specific position in an ArkTS (.ets) or C/C++ file.",feature:"hover"},{name:"definition",description:"Find where the symbol at the given position is defined. Returns file path, line, and character.",feature:"definition"},{name:"declaration",description:"Find the declaration of the symbol at the given position. In ArkTS, this may differ from definition.",feature:"declaration"},{name:"references",description:"Find all references to the symbol at the given position across the HarmonyOS project.",feature:"references"},{name:"implementation",description:"Find implementations of the symbol at the given position (e.g., interface implementations).",feature:"implementation"}]}registerSymbolTools(){this.toolRouter.add({name:"workspaceSymbol",description:"Search for symbols by name across the entire HarmonyOS project.",inputSchema:Se.object({query:Se.string().describe("Symbol name (or partial) to search for")})},async e=>this.handleWorkspaceSymbolCall(e)),this.toolRouter.add({name:"documentSymbol",description:"Get the symbol tree (functions, classes, variables with ranges) of an ArkTS (.ets) or C/C++ file. Useful for file overview, structured code breakdown, and large file slicing.",inputSchema:Se.object({file:Se.string().describe("Source file path, relative to the project root. Supports .ets and C/C++ extensions.")})},async e=>this.handleDocumentSymbolCall(e))}registerCallHierarchyTool(){this.toolRouter.add({name:"callHierarchy",description:'Query call hierarchy for a function at the given position. Use direction "incoming" to find callers, "outgoing" to find callees. ArkTS supports both directions; C/C++ (clangd) supports incoming only.',inputSchema:Se.object({file:Se.string().describe("Source file path, relative to the project root. Supports .ets and C/C++ extensions."),line:Se.number().describe("Line number (0-based)"),character:Se.number().describe("Character offset in the line (0-based)"),direction:Se.enum(["incoming","outgoing"]).describe('"incoming" = who calls this function, "outgoing" = what this function calls')})},async e=>this.handleCallHierarchyCall(e))}detectStandardProtocolAvailable(){try{let e=this.config.toolProvider.lspServerPath;if(!e)return g.info("Standard LSP protocol unavailable: arkts-lang-server path not found"),!1;let t=cn.join(cn.dirname(e),"standardIndex","index.js"),r=Ym.existsSync(t);return g.info(`ArktsCheck protocol: ${r?"standard LSP":"legacy ace-server"} (standardIndex/index.js exists=${r})`),r}catch(e){return g.warn(`Failed to detect standard LSP protocol availability: ${e}`),!1}}validateContainment(e){let t=this.config.projectPath;if(t){let o=[];for(let i of e){let s=P.isPathContainedWithSymlink(i,t);s.contained||(g.warn(`Containment check failed: ${s.reason}`),o.push(s.reason))}return o.length>0?{content:[{type:"text",text:o.join(`
|
|
1303
1303
|
`)}],isError:!0}:null}let r=e.filter(o=>cn.isAbsolute(o));return r.length>0?(g.warn(`Absolute paths rejected (no project root): ${r.join(", ")}`),{content:[{type:"text",text:r.map(o=>`Absolute path is not allowed: ${o}`).join(`
|
|
1304
1304
|
`)}],isError:!0}):null}async handleCheckCall(e){let t=Array.isArray(e.files)?e.files.filter(h=>typeof h=="string"):[];if(t.length===0)return g.warn("check tool called with empty files list"),{content:[{type:"text",text:"No files provided"}],isError:!0};let r=this.validateContainment(t);if(r)return r;let{etsFiles:o,cppFiles:i,unsupported:s}=SI(t);s.length>0&&g.warn(`Unsupported file types in check request: ${s.join(", ")}`);let a=s.map(h=>`Unsupported file type: ${h} (only .ets and C/C++ source/header files are supported)`),c=[];o.length>0&&this.mergeCheckResult(await this.callArktsCheck(o),a,c),i.length>0&&this.mergeCheckResult(await this.callCppCheck(i),a,c);let l=a.length>0;return{content:[{type:"text",text:[c.join(`
|
|
1305
1305
|
`),a.join(`
|
|
@@ -1412,4 +1412,4 @@ Run \`devecocli compat versions\` to see all available versions.`)}if(n.sourceVe
|
|
|
1412
1412
|
`)){let i=o.trim();if(!i||i.startsWith("[Empty]"))continue;let s=i.split(/\s+/),a=s[0],c=s.length>=2?s[1]:"device";a&&!a.startsWith("[Empty]")&&c.toLowerCase()!=="unauthorized"&&t.push(a)}let r=[];for(let o of t)try{m(`Executing: ${n} -t ${o} shell bm get -u`);let{stdout:i}=await Ow(n,["-t",o,"shell","bm","get","-u"],{stdio:["ignore","pipe","pipe"]}),s=LN(i);s&&r.push(s)}catch{m(`[reGenerateSign] Failed to get UDID for ${o}, skipping`)}return r}function LN(n){let e=n.trim();if(!e)return null;let t=e.split(`
|
|
1413
1413
|
`);for(let o=0;o<t.length-1;o++)if(t[o].includes("udid of current device is")){let s=t[o+1].trim().match(/^[A-Fa-f0-9]{64}$/);if(s)return s[0].toUpperCase()}let r=e.match(/[A-Fa-f0-9]{64}/);return r?r[0].toUpperCase():null}function _w(n){let e=[n.storeFile,n.csrFile,n.cerFile,n.profileFile],t=[];for(let r of e)In.existsSync(r)||t.push(r);return{allExist:t.length===0,missing:t}}function ON(n,e){let t=[];for(let r of e)n.includes(r)||t.push(r);return{allPresent:t.length===0,missing:t}}function MN(n,e){let t=[...n].sort(),r=[...e].sort();return t.length!==r.length?!1:t.every((o,i)=>o===r[i])}function Be(n){let e={force:!1,allFilesExist:!1,missingFiles:[],profileContentNotEmpty:!1,profileNotExpired:!1,bundleNameMatched:!1,teamIdMatched:!1,allDevicesInProfile:!1,missingDeviceUdids:[],aclMatched:!1,cerMatched:!1,cerNotExpired:!1,storePasswordValid:!1};return n.force?{...e,force:!0}:{...e,...n,force:!1}}import{debuglog as cu}from"util";import{execa as lu}from"execa";async function Hw(n,e){let t=await oc(n);if(!t)throw new Error(E.DEVICE_LIST_EMPTY);let r=await jN(e);if(t.length===0)for(let s of r)await _N(n,s.udid,s.deviceName);else for(let s of r)await FN(n,t,s.udid,s.deviceName);let i=(await oc(n)).map(s=>s.id);if(i.length===0)throw new Error(E.DEVICE_LIST_EMPTY);return i}async function _N(n,e,t){await Bw(n,e,$w(t))}async function FN(n,e,t,r){for(let o=0;o<e.length;o++){if(t===e[o].udid)return;if(o===e.length-1){await Bw(n,t,$w(r));return}}}function $w(n){switch(n){case"liteWearable":return"1";case"wearable":return"2";case"tv":return"3";default:return"4"}}async function jw(n,e=1,t=100){let r=`${Q.BASE_URL}${Q.DEVICE_LIST_PATH}?encodeFlag=0&start=${e}&pageSize=${t}`,o=Ww(n),i=await N.get(r,{headers:o});if(!i)throw cu("query devices failed: response is null"),new Error(E.ERROR_WHILE_ADD_DEVICE);if(i.statusCode!==200)throw Uw(i.statusCode,i.statusText,i.data);let s=JSON.parse(i.data);if(!s||!s.list)throw cu("query devices failed: response list is null"),new Error(s.ret?.msg||E.ERROR_WHILE_ADD_DEVICE);return{deviceList:s.list,total:s.totalCount||0}}function Uw(n,e,t){return n===pt.FORBIDDEN?e===ye.OPENPROXY_BLOCKED_URL?new Error(E.ERR_CERT_NETWORK_ERROR):new Error(E.ERR_FORBIDDEN):n===pt.UNAUTHORIZED?new Error(E.ERR_UNAUTHORIZED):t.includes(ye.DEVICE_EXCEEDS_LIMIT_CODE)?new Error(E.DEVICE_LIMIT_REACHED):new Error(E.ERROR_WHILE_ADD_DEVICE)}async function oc(n){let t=await jw(n,1,100);if(!t||!t.deviceList||t.deviceList.length===0)return[];let r=[...t.deviceList],o=t.total,i=Math.floor(o/100)+(o%100===0?0:1);for(let s=2;s<=i;s++){let a=await jw(n,s,100);if(!a||!a.deviceList||a.deviceList.length===0)break;r.push(...a.deviceList)}return r}async function Bw(n,e,t){let r=`${Q.BASE_URL}${Q.DEVICE_ADD_PATH}`,o=Ww(n),s={deviceName:`auto_sign_device_No.${Math.floor(Math.random()*3e3)}${Date.now()}`,udid:e,deviceType:t},a=await N.postAllowFailure(r,{headers:o,params:s});if(!a)throw cu("add device failed: response is null"),new Error(E.ERROR_WHILE_ADD_DEVICE);if(a.statusCode!==200)throw Uw(a.statusCode,a.statusText,a.data);let c=a.data,l=JSON.parse(a.data);if(!l||!l.ret||l.ret.code!==0)throw c.includes(ye.DEVICE_EXCEEDS_LIMIT_CODE)?new Error(E.DEVICE_LIMIT_REACHED):c.includes(ye.DEVICE_NAME_REPEAT_CODE)?new Error(E.DEVICE_NAME_REPEAT):new Error(E.ERROR_WHILE_ADD_DEVICE)}function Ww(n){return{uid:n.uid,teamId:n.teamId,oauth2Token:n.accessToken}}async function jN(n){let{stdout:e}=await lu(n,["list","targets"],{stdio:["ignore","pipe","pipe"]}),t=[];for(let o of e.split(`
|
|
1414
1414
|
`)){let i=o.trim();if(!i||i.startsWith("[Empty]"))continue;let s=i.split(/\s+/),a=s[0],c=s.length>=2?s[1]:"device";a&&!a.startsWith("[Empty]")&&c.toLowerCase()!=="unauthorized"&&t.push(a)}let r=[];for(let o of t)try{let i=await HN(o,n),s=await $N(o,n);i.length>0&&r.push({id:"",udid:i,deviceName:s})}catch{m(`Failed to get device info for ${o}, skipping`)}return r}async function HN(n,e){let{stdout:t}=await lu(e,["-t",n,"shell","bm","get","-u"],{stdio:["ignore","pipe","pipe"]}),r=t.trim();if(!r)return"";let o=r.split(`
|
|
1415
|
-
`);for(let s=0;s<o.length-1;s++)if(o[s].includes("udid of current device is")){let c=o[s+1].trim().match(/^[A-Fa-f0-9]{64}$/);if(c)return c[0].toUpperCase()}let i=r.match(/[A-Fa-f0-9]{64}/);return i?i[0].toUpperCase():""}async function $N(n,e){let{stdout:t}=await lu(e,["-c","-t",n,"shell","getprop","hw_sc.build.os.deviceType"],{stdio:["ignore","pipe","pipe"]});return UN(t)}function UN(n){let e=n.trim();return!e||e.includes("inaccessible")?"phone":n.includes("liteWearable")?"liteWearable":n.includes("wearable")?"wearable":n.includes("tv")?"tv":"phone"}import Zn from"fs";import{createHash as BN}from"crypto";import{debuglog as Gt}from"util";import{Buffer as zw}from"buffer";import{createPublicKey as WN,X509Certificate as du}from"crypto";import{readFileSync as GN}from"fs";import Qn from"node-forge";async function qw(n,e){console.log("Start generating profile");let{productName:t,bundleName:r,projectPath:o,aclPermissionList:i,allDeviceIds:s,certIds:a,keyAlias:c,keyPwd:l}=e;if(s==null||s.length===0)throw new Error(E.DEVICE_LIST_EMPTY);let d=`${Q.BASE_URL}${Q.PROVISION_ADD_TEST_PATH}`,h=zN(t,r),w=await VN(n,d,a||[],r,s,h,i||[]);if(!w||!w.profileInfo||!w.profileInfo.provisionFileUrl)throw Gt("add provision failed, the provision file url is null"),new Error(E.ADD_PROFILE_FAIL);let S=w.profileInfo,re=(await XN(n,S.provisionFileUrl)).urlList,De=w.profileInfo.id;if(re&&re.length>0){let Pe=await Ew(t,o),We=Pe.profilePath;if(!await ZN(re,We))throw await Gw(n,De),new Error(E.ERROR_WHILE_DOWNLOAD_PROFILE);if(await Gw(n,De),Zn.existsSync(Pe.certPath)&&Zn.existsSync(We)&&Zn.existsSync(Pe.p12Path)){let ev=Zn.readFileSync(Pe.certPath,"utf8"),tv=Zn.readFileSync(We,"utf8");return QN(tv,ev,Pe.p12Path,c,l)||KN(We),We}}throw new Error(E.ADD_PROFILE_FAIL)}function zN(n,e){let t=n?`${n}_`:"";return`${qN(`${t}${e}_${e}`)}`}function qN(n){return BN("sha256").update(n).digest("hex").substring(0,16)}async function VN(n,e,t,r,o,i,s){JN(r);let a=pu(n),c={certList:t,packageName:r,deviceList:o,provisionName:i};s.length&&(c.aclPermissionList=s);let l=await N.postAllowFailure(e,{headers:a,params:c});if(!l)throw Gt("add provision failed: response is null"),new Error(E.ADD_PROFILE_FAIL);if(l.statusCode!==200)throw uu(l.statusCode,l.statusText,l.data);let d=JSON.parse(l.data);if(!d||!d.ret||d.ret.code!==0)throw Gt(`add provision fail: ${l.data}`),YN(l.data,i),new Error(d.ret?.msg||E.ADD_PROFILE_FAIL);let h=d.provisionFileUrl;return{profileInfo:{id:d.id,name:i,provisionFileUrl:h}}}function uu(n,e,t){return n===pt.FORBIDDEN?e===ye.OPENPROXY_BLOCKED_URL?new Error(E.ERR_CERT_NETWORK_ERROR):new Error(E.ERR_FORBIDDEN):n===pt.UNAUTHORIZED?new Error(E.ERR_UNAUTHORIZED):t.includes(ye.PROVISION_EXCEEDS_LIMIT_CODE)?new Error(E.TEST_PROVISION_EXCEEDS_LIMIT):new Error(E.ADD_PROFILE_FAIL)}function JN(n){if(!n||n.trim().length===0)throw new Error(E.ERROR_SIGN_BUNDLE_NAME_VALIDATE);if(!_e.BUNDLE_NAME_REGEX.test(n))throw new Error(E.ERROR_SIGN_BUNDLE_NAME_VALIDATE)}function YN(n,e){if(n.includes(ye.PROVISION_EXCEEDS_LIMIT_CODE))throw new Error(E.TEST_PROVISION_EXCEEDS_LIMIT);if(n.includes(ye.PROVISION_NAME_REPEAT_CODE)&&e)throw new Error(E.PROFILE_NAME_REPEAT)}async function Gw(n,e){if(!e||e.trim().length===0)return;let t=`${Q.BASE_URL}${Q.PROVISION_DELETE_PATH}?id=${e}`,r=await N.deleteAllowFailure(t,{headers:pu(n)});if(r.statusCode!==200)throw uu(r.statusCode,r.statusText,r.data);let o=JSON.parse(r.data);(!o||!o.ret||o.ret.code!==0)&&Gt(`delete provision failed: ${r.data}`)}function KN(...n){for(let e of n)try{Zn.existsSync(e)&&Zn.unlinkSync(e)}catch(t){Gt(`delete local sign file error: ${t.message}`)}}async function XN(n,e){let t=`${Q.BASE_URL}${Q.CERT_DOWNLOAD_URL_PATH}`,r=pu(n),o={sourceUrls:e},i=await N.postAllowFailure(t,{headers:r,params:o});if(!i)throw Gt("get download list failed: response is null"),new Error(E.ADD_PROFILE_FAIL);if(i.statusCode!==200)throw uu(i.statusCode,i.statusText,i.data);let s=JSON.parse(i.data);if(!s||!s.urlsInfo||s.urlsInfo.length===0)throw Gt("download: The application does not exist"),new Error(s.ret?.msg||E.ADD_PROFILE_FAIL);return{urlList:s.urlsInfo,hasPermission:!0}}async function ZN(n,e){if(!n||n.length===0)return!1;let t=n[0].newUrl;return await Si(t,e),!0}function QN(n,e,t,r,o){return eL(n,e),r=r||_e.TARGET_FRIENDLY_NAME,o=o||"",tL(e,t,r,o),!0}function eL(n,e){if(e.lastIndexOf(_e.CERT_BEGIN_HEADER)<0)throw new Error(E.ERROR_WHILE_PARSE_PROFILE);let t=JSON.stringify(e.substring(e.lastIndexOf(_e.CERT_BEGIN_HEADER))).replace(/\\r/g,"");if(!n.includes(t))throw new Error(E.CERTIFICATION_AND_PROFILE_NOT_INCONSISTENT);return!0}function tL(n,e,t,r){let o=n.matchAll(_e.CERTIFICATE_PATTERN_GLOBAL),i=[],s=new Date;for(let c of o)try{let l=c[0],d=nL(l),h=new Date(d.validFrom),w=new Date(d.validTo);if(s<h||s>w){let S=`Certificate is not valid, Valid from ${h} to ${w}`;throw console.warn(`checkCertificateInValidityPeriod: ${S}`),new Error(E.CERTIFICATE_HAS_EXPIRED)}i.push(d)}catch(l){throw console.warn(`checkCertificateInValidityPeriod\uFF1A ${l.message}`),new Error(E.CERTIFICATE_HAS_EXPIRED,{cause:l})}if(!i||i.length===0)throw new Error(E.CERTIFICATE_HAS_EXPIRED);if(!oL(e,t,r,i))throw new Error(E.CERTIFICATION_AND_PROFILE_NOT_INCONSISTENT)}function nL(n){let e="-----BEGIN CERTIFICATE-----",t=n.trim();try{if(t.startsWith(e))return new du(t);let r=zw.from(t,"base64");return new du(r)}catch(r){throw new Error("decodeBase64ToX509Certificate",{cause:r})}}function rL(n){if(n.cert){let e=Qn.pki.publicKeyToPem(n.cert.publicKey);return WN(e).export({type:"spki",format:"der"})}if(n.asn1)try{let e=Qn.asn1.toDer(n.asn1).getBytes(),t=zw.from(e,"binary");return new du(t).publicKey.export({type:"spki",format:"der"})}catch(e){return Gt(`Failed to parse cert from asn1: ${e}`),null}return null}function oL(n,e,t,r){try{let o=GN(n),i=Qn.asn1.fromDer(Qn.util.createBuffer(o)),c=Qn.pkcs12.pkcs12FromAsn1(i,t).getBags({bagType:Qn.pki.oids.certBag})[Qn.pki.oids.certBag]||[];for(let l of c){let d=l.attributes?.friendlyName?.[0];if(!d||d.toLowerCase()!==e.toLowerCase())continue;let h=rL(l);if(!h)continue;if(r.some(S=>{let k=S.publicKey.export({type:"spki",format:"der"});return h.equals(k)}))return!0}return!1}catch(o){let i=o instanceof Error?o.message:String(o);return Gt(`Failed to process P12 file: ${n}, error: ${i}`),!1}}function pu(n){return{uid:n.uid,teamId:n.teamId,oauth2Token:n.accessToken}}var Jw="https://developer.huawei.com",iL={"ohos.permission.SYSTEM_FLOAT_WINDOW":"/consumer/cn/doc/harmonyos-guides/window-pipwindow","ohos.permission.READ_CONTACTS":"/consumer/cn/doc/harmonyos-references/js-apis-contact#contactselectcontacts10","ohos.permission.READ_IMAGEVIDEO":"/consumer/cn/doc/harmonyos-guides/select-user-file#%E9%80%89%E6%8B%A9%E5%9B%BE%E7%89%87%E6%88%96%E8%A7%86%E9%A2%91%E7%B1%BB%E6%96%87%E4%BB%B6","ohos.permission.WRITE_IMAGEVIDEO":"/consumer/cn/doc/harmonyos-guides/savebutton","ohos.permission.READ_AUDIO":"/consumer/cn/doc/harmonyos-guides/select-user-file#%E9%80%89%E6%8B%A9%E9%9F%B3%E9%A2%91%E7%B1%BB%E6%96%87%E4%BB%B6","ohos.permission.WRITE_AUDIO":"/consumer/cn/doc/harmonyos-guides/save-user-file#%E4%BF%9D%E5%AD%98%E9%9F%B3%E9%A2%91%E7%B1%BB%E6%96%87%E4%BB%B6","ohos.permission.READ_PASTEBOARD":"/consumer/cn/doc/harmonyos-guides/pastebutton"},sL="/consumer/cn/doc/harmonyos-guides/restricted-permissions";function aL(n){let e=iL[n];return e?`${Jw}${e}`:void 0}function cL(){return`${Jw}${sL}`}var lL={"acl.can.apply.text":"Permission Application Scenarios","acl.permissions.warn":"Note: You are applying for restricted ACL permissions: {0} These permissions are subject to review together with your app release. For a faster review process, apply for the following permissions instead, if they are sufficient for your purposes: {1} {2}"};function Vw(n,e){return(lL[n]??n).replace(/\{(\d+)\}/g,(r,o)=>String(e[Number(o)]??""))}function dL(n){return Array.from(n).join(", ")}function Yw(n,e){if(n.size===0)return;let t=Cn.getAclPermissionInfos(e),r=new Set;for(let h of t)n.has(h.permissionName)&&r.add(h);for(let h of r){let w=aL(h.permissionName);w!=null&&(h.permissionHelpUrlKey=w)}let o=new Set;for(let h of r)o.add(h.permissionDisplayName);let i=new Set;for(let h of r)if(h.permissionHelpUrlKey!=null){let w=h.permissionInsteadName??h.permissionDisplayName;i.add(`${w} (${h.permissionHelpUrlKey})`)}let s=cL(),a=Vw("acl.can.apply.text",[]),c=s?`${a} (${s})`:a,l=i.size>0?Array.from(i).join(", ")+".":"",d=Vw("acl.permissions.warn",[dL(o),l,c]);console.log(d)}var ic=class{_project=null;get project(){if(!this._project)throw new Error("Project not initialized. Call checkProjectDir first.");return this._project}checkProjectDir(e){try{return this._project=G.discover(process.cwd()),{passed:!0,message:""}}catch(t){return m(`[EnvCheck] Project.discover() failed: ${t.message}`),e(K.PROJECT_DIR_MISSING)}}checkProduct(e,t){try{return this._project.validateProduct(e),{passed:!0,message:""}}catch(r){return m(`[EnvCheck] Product validation failed: ${r.message}`),t(`Product "${e}" not found.Check the product property in the build-profile.json5 file.`)}}checkBundleName(e,t){try{return this._project.getBundleName(),{passed:!0,message:""}}catch(r){return m(`[EnvCheck] BundleName check failed: ${r.message}`),t(`bundleName was not found under product "${e}".Check the bundleName configuration.`)}}checkAtomicService(){return this._project.isAtomicService()?{passed:!1,message:K.ATOMIC_SERVICE_UNSUPPORTED}:{passed:!0,message:""}}};import uL from"fs";import Kw from"path";var sc=class{constructor(e){this.toolProvider=e}toolProvider;checkJava(e){try{return this.toolProvider.assertJava(),{passed:!0,message:""}}catch(t){return m(`[EnvCheck] Java check failed: ${t.message}`),e(K.JAVA_PLATFORM_UNSUPPORTED)}}checkHapSignTools(e){let t=this.toolProvider.sdkPath,r=b()?"hap-sign-tool":"hap-sign-tool.jar",o=Kw.join(t,"default","openharmony","toolchains","lib",r);if(!uL.existsSync(o)){let i=Kw.join("sdk","default","openharmony","toolchains","lib",r);return e(`${r} not found.Check whether ${i} exists.`)}return{passed:!0,message:""}}};var ac=class{_userInfo=null;async ensureUserInfo(){if(!this._userInfo)try{this._userInfo=await ae.getUserInfo()}catch(e){return m(`[EnvCheck] Failed to load user info: ${e.message}`),null}return this._userInfo}async checkLogin(e){try{return await ae.isLoggedIn()?(await this.ensureUserInfo(),{passed:!0,message:""}):e(K.LOGIN_REQUIRED)}catch(t){return m(`[EnvCheck] Login check failed: ${t.message}`),e(K.LOGIN_REQUIRED)}}async checkTeamInfo(e){if(!await this.ensureUserInfo())return e(K.TEAM_INFO_FAILED);try{if((await Qt()).teamList.length>0)return{passed:!0,message:""}}catch(r){return m(`[EnvCheck] Team API error: ${r.message}`),e(K.TEAM_INFO_FAILED)}return m("[EnvCheck] No teams found for current user"),e(K.TEAM_INFO_FAILED)}async checkRealname(e){let t=await this.ensureUserInfo();return t?t.isRealName===!1?e(K.REALNAME_REQUIRED):t.isRealName!==!0?(m("[EnvCheck] Scenario 3 Real-name check: AGC API did not return realName field"),e(K.REALNAME_REQUIRED)):{passed:!0,message:""}:e(K.SESSION_EXPIRED)}async checkTeamId(e){let t=await this.ensureUserInfo();if(!t)return{passed:!0,message:""};let r=e??"";try{let o=await Qt();if(r=e??(o.teamList.length>0?o.teamList[0].id:t.userId)??"",!o.teamList.some(s=>s.id===r)){let s=`team-id for ${r} not found.Run devecocli auth team list to view the team to which the logged-in user belongs.`;return m(`[EnvCheck] ${s}`),{passed:!1,message:s}}return{passed:!0,message:""}}catch(o){return m(`[EnvCheck] Team ID check failed: ${o.message}`),{passed:!1,message:`team-id for ${r} not found.Run devecocli auth team list to view the team to which the logged-in user belongs.`}}}async checkRegion(e){let t=await this.ensureUserInfo();return t?t.countryCode?t.countryCode!=="CN"?e(K.REGION_CHINA_ONLY):{passed:!0,message:""}:(m("[EnvCheck] Scenario 12 Region check: AGC API did not return nationalCode field"),e(K.REGION_CHINA_ONLY)):e("User session expired or token invalid. Please login again.")}};async function pL(n){try{let{teamList:e}=await Qt();if(e.length>0)return e[0].id}catch(e){m(`[EnvCheck] resolveDefaultTeamId failed: ${e.message}`)}return n??""}async function fL(n){let e=await ae.getUserInfo(),t=await ae.refreshToken();if(!e||!t?.accessToken)throw new Error("Not logged in");let r=n||await pL(e.userId);if(!r)throw new Error("No team found");let o={uid:e.userId??"",teamId:r,accessToken:t.accessToken};return(await oc(o)).map(s=>({deviceId:s.udid,deviceName:s.deviceName}))}var cc=class{constructor(e){this.toolProvider=e}toolProvider;async checkDevice(e,t){try{let r=await fL(t);if(r.length>0)return m(`[EnvCheck] Scenario 4 Device check: ${r.length} device(s) found in AGC cloud, skipping local device check`),{passed:!0,message:""};m("[EnvCheck] Scenario 4 Device check: no cloud devices found, falling back to local hdc");let i=await te.from(this.toolProvider).listDevices();return i.length===0?(m("[EnvCheck] Scenario 4 Device check: no local devices found"),e(K.DEVICE_MISSING)):i.some(a=>Ln(a.serial))?{passed:!0,message:""}:(m("[EnvCheck] Scenario 4 Device check: local device found but not an emulator"),e(K.DEVICE_MISSING))}catch(r){return m(`[EnvCheck] Scenario 4 Device check failed: ${r.message}`),e(K.DEVICE_DETECT_FAILED)}}};var lc=class{projectChecker=new ic;toolchainChecker=null;authChecker=new ac;deviceChecker=null;constructor(){}async preflight(e){let t=r=>this.blockingFail(r);return!(!await this.runAuthChain(e,t)||!await this.initToolchain()||!await this.runDeviceCheck(e,t)||!await this.runProjectChecks(e,t)||!await this.runAuxChecks(e))}async runAuthChain(e,t){let r=i=>(i.passed||this.fail(i),!0),o=[()=>this.authChecker.checkLogin(t),()=>this.authChecker.checkTeamInfo(t),()=>this.authChecker.checkRealname(t)];for(let i of o)if(!r(await i()))return!1;return!(e.teamId&&!r(await this.authChecker.checkTeamId(e.teamId)))}async initToolchain(){try{let e=await A.new();return this.toolchainChecker=new sc(e),this.deviceChecker=new cc(e),!0}catch(e){throw m(`[EnvCheck] ToolProvider.new() failed: ${e.message}`),new Error(K.TOOLCHAIN_INIT_FAILED,{cause:e})}}async runDeviceCheck(e,t){return(o=>o.passed?!0:(this.fail(o),!1))(await this.deviceChecker.checkDevice(t,e.teamId))}async runProjectChecks(e,t){let r=i=>i.passed?!0:(this.fail(i),!1);if(!r(this.projectChecker.checkProjectDir(t))||!r(this.projectChecker.checkAtomicService()))return!1;let o=[()=>this.projectChecker.checkProduct(e.productName,t),()=>this.projectChecker.checkBundleName(e.productName,t),()=>this.toolchainChecker.checkJava(t),()=>this.toolchainChecker.checkHapSignTools(t)];for(let i of o)if(!r(i()))return!1;return!0}async runAuxChecks(e){let t=r=>r.passed?!0:(this.fail(r),!1);return!e.teamId&&!t(await this.authChecker.checkTeamId(e.teamId))?!1:(await this.authChecker.checkRegion(r=>this.blockingFail(r)),!0)}blockingFail(e){return{passed:!1,message:e}}fail(e){throw m(`[EnvCheck] FAIL: ${e.message}`),new Error(e.message)}};function yL(n){if(mu.existsSync(n)){let e=mu.readFileSync(n,"utf-8");return gL.parse(e)}return{app:{signingConfigs:[],products:[]}}}function wL(n){n.app||(n.app={signingConfigs:[],products:[]}),n.app.signingConfigs||(n.app.signingConfigs=[]),n.app.products||(n.app.products=[])}async function vL(n){if(n.keyPwd===n.storePassword){let r=await Pn.encryptedPassword(n.keyPwd,n.p12FilePath);return{keyPassword:r,storePassword:r}}let e=await Pn.encryptedPassword(n.keyPwd,n.p12FilePath),t=await Pn.encryptedPassword(n.storePassword,n.p12FilePath);return{keyPassword:e,storePassword:t}}async function SL(n,e,t){let r=Xw.join(n,"build-profile.json5"),o=yL(r);wL(o);let i=t??"default",{keyPassword:s,storePassword:a}=await vL(e),c={name:i,type:"HarmonyOS",material:{certpath:e.cerFilePath,keyAlias:e.keyAlias,keyPassword:s,profile:e.profileFilePath,signAlg:ft.signAlg,storeFile:e.p12FilePath,storePassword:a}},l=o.app?.signingConfigs?.findIndex(h=>h.name===i);l!==void 0&&l>=0?o.app.signingConfigs[l]=c:o.app.signingConfigs.push(c);let d=o.app?.products?.findIndex(h=>h.name===i);d!==void 0&&d>=0?o.app.products[d].signingConfig=i:o.app.products.push({name:i,signingConfig:i}),mu.writeFileSync(r,JSON.stringify(o,null,2),"utf-8")}async function bL(n){let e=await ae.getUserInfo(),t=await ae.refreshToken();if(!e||!t)throw new Error("Failed to obtain login credentials. Run `devecocli login` again.");return{uid:e.userId??"",teamId:n.teamId??e.userId??"",accessToken:t.accessToken??""}}async function EL(n){let e=n.product||"default";await new lc().preflight({productName:e,teamId:n.teamId}),console.log("Executing signature generate command");let r=await bL(n),o=await A.new(),{shouldRegenerate:i}=await Pi.shouldRegenerate({force:n.force??!1,teamId:r.teamId,productName:n.product},o);if(!i){console.log(fu("Signature generation completed successfully."));return}await PL(n,r,o),console.log(fu("Signature generation completed successfully."))}async function PL(n,e,t){let r=await eu(e,n.product),o=CL(n,e,r,t);o.allDeviceIds=await Hw(e,t.hdcPath),await qw(e,o);let i=G.discover(process.cwd()).rootDir;await SL(i,r,n.product??"default"),console.log(fu(`Signing config written to ${Xw.join(i,"build-profile.json5")}`))}function CL(n,e,t,r){let o=process.cwd(),i=G.discover(o),s=nc(i,r);return Yw(s,i),{productName:n.product||"default",bundleName:i.getBundleName(),projectPath:i.rootDir,teamId:e.teamId,force:n.force||!1,aclPermissionList:[...s],certIds:[t.certId],keyAlias:t.keyAlias,keyPwd:t.keyPwd}}var Zw=new mL("signature").description("Generate application signature.");Zw.command("generate").description("Automatically generate signing materials and write them to the project configuration.").option("--force","Force overwrite existing local signing materials.").option("--team-id <team-id>","Specify the team ID to use.").option("--product <product>","Specify the product. The default value is default.").action(async n=>{try{await EL(n)}catch(e){console.error(hL(e.message)),process.exit(1)}});var Qw=Zw;process.env.GLOBAL_AGENT_ENVIRONMENT_VARIABLE_NAMESPACE="";IL();ie.name("devecocli").description("HarmonyOS application development command line tool").version("0.3.0-TD.1.2");ie.addCommand(Qu);ie.addCommand(Tp);ie.addCommand(Lp);ie.addCommand(qp);ie.addCommand(Uf);ie.addCommand(pm);ie.addCommand(gm);ie.addCommand(Am);ie.addCommand(Om);ie.addCommand(eh);ie.addCommand(uy);ie.addCommand(Qw);ie.addCommand(mw);ie.addCommand(_y);b()||ie.addCommand(Sf);var hu=process.argv.slice(2);hu.length>=2&&hu[hu.length-1]==="help"&&(process.argv=[...process.argv.slice(0,-1),"--help"]);var DL=new Set(["update","auth"]);ie.hook("preAction",async(n,e)=>{if(process.env.DEVECO_CLI_SKIP_VERSION_CHECK)return;let t=e;for(;t.parent&&t.parent!==ie;)t=t.parent;DL.has(t.name())||await A.checkVersion()});ie.parseAsync(process.argv).catch(n=>{let e=n instanceof Error?n.message:String(n??"Unknown error");console.error(AL(`Error: ${e}`)),process.env.DEVECO_CLI_DEBUG==="1"&&n instanceof Error&&n.stack&&console.error(n.stack),process.exit(1)});
|
|
1415
|
+
`);for(let s=0;s<o.length-1;s++)if(o[s].includes("udid of current device is")){let c=o[s+1].trim().match(/^[A-Fa-f0-9]{64}$/);if(c)return c[0].toUpperCase()}let i=r.match(/[A-Fa-f0-9]{64}/);return i?i[0].toUpperCase():""}async function $N(n,e){let{stdout:t}=await lu(e,["-c","-t",n,"shell","getprop","hw_sc.build.os.deviceType"],{stdio:["ignore","pipe","pipe"]});return UN(t)}function UN(n){let e=n.trim();return!e||e.includes("inaccessible")?"phone":n.includes("liteWearable")?"liteWearable":n.includes("wearable")?"wearable":n.includes("tv")?"tv":"phone"}import Zn from"fs";import{createHash as BN}from"crypto";import{debuglog as Gt}from"util";import{Buffer as zw}from"buffer";import{createPublicKey as WN,X509Certificate as du}from"crypto";import{readFileSync as GN}from"fs";import Qn from"node-forge";async function qw(n,e){console.log("Start generating profile");let{productName:t,bundleName:r,projectPath:o,aclPermissionList:i,allDeviceIds:s,certIds:a,keyAlias:c,keyPwd:l}=e;if(s==null||s.length===0)throw new Error(E.DEVICE_LIST_EMPTY);let d=`${Q.BASE_URL}${Q.PROVISION_ADD_TEST_PATH}`,h=zN(t,r),w=await VN(n,d,a||[],r,s,h,i||[]);if(!w||!w.profileInfo||!w.profileInfo.provisionFileUrl)throw Gt("add provision failed, the provision file url is null"),new Error(E.ADD_PROFILE_FAIL);let S=w.profileInfo,re=(await XN(n,S.provisionFileUrl)).urlList,De=w.profileInfo.id;if(re&&re.length>0){let Pe=await Ew(t,o),We=Pe.profilePath;if(!await ZN(re,We))throw await Gw(n,De),new Error(E.ERROR_WHILE_DOWNLOAD_PROFILE);if(await Gw(n,De),Zn.existsSync(Pe.certPath)&&Zn.existsSync(We)&&Zn.existsSync(Pe.p12Path)){let ev=Zn.readFileSync(Pe.certPath,"utf8"),tv=Zn.readFileSync(We,"utf8");return QN(tv,ev,Pe.p12Path,c,l)||KN(We),We}}throw new Error(E.ADD_PROFILE_FAIL)}function zN(n,e){let t=n?`${n}_`:"";return`${qN(`${t}${e}_${e}`)}`}function qN(n){return BN("sha256").update(n).digest("hex").substring(0,16)}async function VN(n,e,t,r,o,i,s){JN(r);let a=pu(n),c={certList:t,packageName:r,deviceList:o,provisionName:i};s.length&&(c.aclPermissionList=s);let l=await N.postAllowFailure(e,{headers:a,params:c});if(!l)throw Gt("add provision failed: response is null"),new Error(E.ADD_PROFILE_FAIL);if(l.statusCode!==200)throw uu(l.statusCode,l.statusText,l.data);let d=JSON.parse(l.data);if(!d||!d.ret||d.ret.code!==0)throw Gt(`add provision fail: ${l.data}`),YN(l.data,i),new Error(d.ret?.msg||E.ADD_PROFILE_FAIL);let h=d.provisionFileUrl;return{profileInfo:{id:d.id,name:i,provisionFileUrl:h}}}function uu(n,e,t){return n===pt.FORBIDDEN?e===ye.OPENPROXY_BLOCKED_URL?new Error(E.ERR_CERT_NETWORK_ERROR):new Error(E.ERR_FORBIDDEN):n===pt.UNAUTHORIZED?new Error(E.ERR_UNAUTHORIZED):t.includes(ye.PROVISION_EXCEEDS_LIMIT_CODE)?new Error(E.TEST_PROVISION_EXCEEDS_LIMIT):new Error(E.ADD_PROFILE_FAIL)}function JN(n){if(!n||n.trim().length===0)throw new Error(E.ERROR_SIGN_BUNDLE_NAME_VALIDATE);if(!_e.BUNDLE_NAME_REGEX.test(n))throw new Error(E.ERROR_SIGN_BUNDLE_NAME_VALIDATE)}function YN(n,e){if(n.includes(ye.PROVISION_EXCEEDS_LIMIT_CODE))throw new Error(E.TEST_PROVISION_EXCEEDS_LIMIT);if(n.includes(ye.PROVISION_NAME_REPEAT_CODE)&&e)throw new Error(E.PROFILE_NAME_REPEAT)}async function Gw(n,e){if(!e||e.trim().length===0)return;let t=`${Q.BASE_URL}${Q.PROVISION_DELETE_PATH}?id=${e}`,r=await N.deleteAllowFailure(t,{headers:pu(n)});if(r.statusCode!==200)throw uu(r.statusCode,r.statusText,r.data);let o=JSON.parse(r.data);(!o||!o.ret||o.ret.code!==0)&&Gt(`delete provision failed: ${r.data}`)}function KN(...n){for(let e of n)try{Zn.existsSync(e)&&Zn.unlinkSync(e)}catch(t){Gt(`delete local sign file error: ${t.message}`)}}async function XN(n,e){let t=`${Q.BASE_URL}${Q.CERT_DOWNLOAD_URL_PATH}`,r=pu(n),o={sourceUrls:e},i=await N.postAllowFailure(t,{headers:r,params:o});if(!i)throw Gt("get download list failed: response is null"),new Error(E.ADD_PROFILE_FAIL);if(i.statusCode!==200)throw uu(i.statusCode,i.statusText,i.data);let s=JSON.parse(i.data);if(!s||!s.urlsInfo||s.urlsInfo.length===0)throw Gt("download: The application does not exist"),new Error(s.ret?.msg||E.ADD_PROFILE_FAIL);return{urlList:s.urlsInfo,hasPermission:!0}}async function ZN(n,e){if(!n||n.length===0)return!1;let t=n[0].newUrl;return await Si(t,e),!0}function QN(n,e,t,r,o){return eL(n,e),r=r||_e.TARGET_FRIENDLY_NAME,o=o||"",tL(e,t,r,o),!0}function eL(n,e){if(e.lastIndexOf(_e.CERT_BEGIN_HEADER)<0)throw new Error(E.ERROR_WHILE_PARSE_PROFILE);let t=JSON.stringify(e.substring(e.lastIndexOf(_e.CERT_BEGIN_HEADER))).replace(/\\r/g,"");if(!n.includes(t))throw new Error(E.CERTIFICATION_AND_PROFILE_NOT_INCONSISTENT);return!0}function tL(n,e,t,r){let o=n.matchAll(_e.CERTIFICATE_PATTERN_GLOBAL),i=[],s=new Date;for(let c of o)try{let l=c[0],d=nL(l),h=new Date(d.validFrom),w=new Date(d.validTo);if(s<h||s>w){let S=`Certificate is not valid, Valid from ${h} to ${w}`;throw console.warn(`checkCertificateInValidityPeriod: ${S}`),new Error(E.CERTIFICATE_HAS_EXPIRED)}i.push(d)}catch(l){throw console.warn(`checkCertificateInValidityPeriod\uFF1A ${l.message}`),new Error(E.CERTIFICATE_HAS_EXPIRED,{cause:l})}if(!i||i.length===0)throw new Error(E.CERTIFICATE_HAS_EXPIRED);if(!oL(e,t,r,i))throw new Error(E.CERTIFICATION_AND_PROFILE_NOT_INCONSISTENT)}function nL(n){let e="-----BEGIN CERTIFICATE-----",t=n.trim();try{if(t.startsWith(e))return new du(t);let r=zw.from(t,"base64");return new du(r)}catch(r){throw new Error("decodeBase64ToX509Certificate",{cause:r})}}function rL(n){if(n.cert){let e=Qn.pki.publicKeyToPem(n.cert.publicKey);return WN(e).export({type:"spki",format:"der"})}if(n.asn1)try{let e=Qn.asn1.toDer(n.asn1).getBytes(),t=zw.from(e,"binary");return new du(t).publicKey.export({type:"spki",format:"der"})}catch(e){return Gt(`Failed to parse cert from asn1: ${e}`),null}return null}function oL(n,e,t,r){try{let o=GN(n),i=Qn.asn1.fromDer(Qn.util.createBuffer(o)),c=Qn.pkcs12.pkcs12FromAsn1(i,t).getBags({bagType:Qn.pki.oids.certBag})[Qn.pki.oids.certBag]||[];for(let l of c){let d=l.attributes?.friendlyName?.[0];if(!d||d.toLowerCase()!==e.toLowerCase())continue;let h=rL(l);if(!h)continue;if(r.some(S=>{let k=S.publicKey.export({type:"spki",format:"der"});return h.equals(k)}))return!0}return!1}catch(o){let i=o instanceof Error?o.message:String(o);return Gt(`Failed to process P12 file: ${n}, error: ${i}`),!1}}function pu(n){return{uid:n.uid,teamId:n.teamId,oauth2Token:n.accessToken}}var Jw="https://developer.huawei.com",iL={"ohos.permission.SYSTEM_FLOAT_WINDOW":"/consumer/cn/doc/harmonyos-guides/window-pipwindow","ohos.permission.READ_CONTACTS":"/consumer/cn/doc/harmonyos-references/js-apis-contact#contactselectcontacts10","ohos.permission.READ_IMAGEVIDEO":"/consumer/cn/doc/harmonyos-guides/select-user-file#%E9%80%89%E6%8B%A9%E5%9B%BE%E7%89%87%E6%88%96%E8%A7%86%E9%A2%91%E7%B1%BB%E6%96%87%E4%BB%B6","ohos.permission.WRITE_IMAGEVIDEO":"/consumer/cn/doc/harmonyos-guides/savebutton","ohos.permission.READ_AUDIO":"/consumer/cn/doc/harmonyos-guides/select-user-file#%E9%80%89%E6%8B%A9%E9%9F%B3%E9%A2%91%E7%B1%BB%E6%96%87%E4%BB%B6","ohos.permission.WRITE_AUDIO":"/consumer/cn/doc/harmonyos-guides/save-user-file#%E4%BF%9D%E5%AD%98%E9%9F%B3%E9%A2%91%E7%B1%BB%E6%96%87%E4%BB%B6","ohos.permission.READ_PASTEBOARD":"/consumer/cn/doc/harmonyos-guides/pastebutton"},sL="/consumer/cn/doc/harmonyos-guides/restricted-permissions";function aL(n){let e=iL[n];return e?`${Jw}${e}`:void 0}function cL(){return`${Jw}${sL}`}var lL={"acl.can.apply.text":"Permission Application Scenarios","acl.permissions.warn":"Note: You are applying for restricted ACL permissions: {0} These permissions are subject to review together with your app release. For a faster review process, apply for the following permissions instead, if they are sufficient for your purposes: {1} {2}"};function Vw(n,e){return(lL[n]??n).replace(/\{(\d+)\}/g,(r,o)=>String(e[Number(o)]??""))}function dL(n){return Array.from(n).join(", ")}function Yw(n,e){if(n.size===0)return;let t=Cn.getAclPermissionInfos(e),r=new Set;for(let h of t)n.has(h.permissionName)&&r.add(h);for(let h of r){let w=aL(h.permissionName);w!=null&&(h.permissionHelpUrlKey=w)}let o=new Set;for(let h of r)o.add(h.permissionDisplayName);let i=new Set;for(let h of r)if(h.permissionHelpUrlKey!=null){let w=h.permissionInsteadName??h.permissionDisplayName;i.add(`${w} (${h.permissionHelpUrlKey})`)}let s=cL(),a=Vw("acl.can.apply.text",[]),c=s?`${a} (${s})`:a,l=i.size>0?Array.from(i).join(", ")+".":"",d=Vw("acl.permissions.warn",[dL(o),l,c]);console.log(d)}var ic=class{_project=null;get project(){if(!this._project)throw new Error("Project not initialized. Call checkProjectDir first.");return this._project}checkProjectDir(e){try{return this._project=G.discover(process.cwd()),{passed:!0,message:""}}catch(t){return m(`[EnvCheck] Project.discover() failed: ${t.message}`),e(K.PROJECT_DIR_MISSING)}}checkProduct(e,t){try{return this._project.validateProduct(e),{passed:!0,message:""}}catch(r){return m(`[EnvCheck] Product validation failed: ${r.message}`),t(`Product "${e}" not found.Check the product property in the build-profile.json5 file.`)}}checkBundleName(e,t){try{return this._project.getBundleName(),{passed:!0,message:""}}catch(r){return m(`[EnvCheck] BundleName check failed: ${r.message}`),t(`bundleName was not found under product "${e}".Check the bundleName configuration.`)}}checkAtomicService(){return this._project.isAtomicService()?{passed:!1,message:K.ATOMIC_SERVICE_UNSUPPORTED}:{passed:!0,message:""}}};import uL from"fs";import Kw from"path";var sc=class{constructor(e){this.toolProvider=e}toolProvider;checkJava(e){try{return this.toolProvider.assertJava(),{passed:!0,message:""}}catch(t){return m(`[EnvCheck] Java check failed: ${t.message}`),e(K.JAVA_PLATFORM_UNSUPPORTED)}}checkHapSignTools(e){let t=this.toolProvider.sdkPath,r=b()?"hap-sign-tool":"hap-sign-tool.jar",o=Kw.join(t,"default","openharmony","toolchains","lib",r);if(!uL.existsSync(o)){let i=Kw.join("sdk","default","openharmony","toolchains","lib",r);return e(`${r} not found.Check whether ${i} exists.`)}return{passed:!0,message:""}}};var ac=class{_userInfo=null;async ensureUserInfo(){if(!this._userInfo)try{this._userInfo=await ae.getUserInfo()}catch(e){return m(`[EnvCheck] Failed to load user info: ${e.message}`),null}return this._userInfo}async checkLogin(e){try{return await ae.isLoggedIn()?(await this.ensureUserInfo(),{passed:!0,message:""}):e(K.LOGIN_REQUIRED)}catch(t){return m(`[EnvCheck] Login check failed: ${t.message}`),e(K.LOGIN_REQUIRED)}}async checkTeamInfo(e){if(!await this.ensureUserInfo())return e(K.TEAM_INFO_FAILED);try{if((await Qt()).teamList.length>0)return{passed:!0,message:""}}catch(r){return m(`[EnvCheck] Team API error: ${r.message}`),e(K.TEAM_INFO_FAILED)}return m("[EnvCheck] No teams found for current user"),e(K.TEAM_INFO_FAILED)}async checkRealname(e){let t=await this.ensureUserInfo();return t?t.isRealName===!1?e(K.REALNAME_REQUIRED):t.isRealName!==!0?(m("[EnvCheck] Scenario 3 Real-name check: AGC API did not return realName field"),e(K.REALNAME_REQUIRED)):{passed:!0,message:""}:e(K.SESSION_EXPIRED)}async checkTeamId(e){let t=await this.ensureUserInfo();if(!t)return{passed:!0,message:""};let r=e??"";try{let o=await Qt();if(r=e??(o.teamList.length>0?o.teamList[0].id:t.userId)??"",!o.teamList.some(s=>s.id===r)){let s=`team-id for ${r} not found.Run devecocli auth team list to view the team to which the logged-in user belongs.`;return m(`[EnvCheck] ${s}`),{passed:!1,message:s}}return{passed:!0,message:""}}catch(o){return m(`[EnvCheck] Team ID check failed: ${o.message}`),{passed:!1,message:`team-id for ${r} not found.Run devecocli auth team list to view the team to which the logged-in user belongs.`}}}async checkRegion(e){let t=await this.ensureUserInfo();return t?t.countryCode?t.countryCode!=="CN"?e(K.REGION_CHINA_ONLY):{passed:!0,message:""}:(m("[EnvCheck] Scenario 12 Region check: AGC API did not return nationalCode field"),e(K.REGION_CHINA_ONLY)):e("User session expired or token invalid. Please login again.")}};async function pL(n){try{let{teamList:e}=await Qt();if(e.length>0)return e[0].id}catch(e){m(`[EnvCheck] resolveDefaultTeamId failed: ${e.message}`)}return n??""}async function fL(n){let e=await ae.getUserInfo(),t=await ae.refreshToken();if(!e||!t?.accessToken)throw new Error("Not logged in");let r=n||await pL(e.userId);if(!r)throw new Error("No team found");let o={uid:e.userId??"",teamId:r,accessToken:t.accessToken};return(await oc(o)).map(s=>({deviceId:s.udid,deviceName:s.deviceName}))}var cc=class{constructor(e){this.toolProvider=e}toolProvider;async checkDevice(e,t){try{let r=await fL(t);if(r.length>0)return m(`[EnvCheck] Scenario 4 Device check: ${r.length} device(s) found in AGC cloud, skipping local device check`),{passed:!0,message:""};m("[EnvCheck] Scenario 4 Device check: no cloud devices found, falling back to local hdc");let i=await te.from(this.toolProvider).listDevices();return i.length===0?(m("[EnvCheck] Scenario 4 Device check: no local devices found"),e(K.DEVICE_MISSING)):i.some(a=>Ln(a.serial))?{passed:!0,message:""}:(m("[EnvCheck] Scenario 4 Device check: local device found but not an emulator"),e(K.DEVICE_MISSING))}catch(r){return m(`[EnvCheck] Scenario 4 Device check failed: ${r.message}`),e(K.DEVICE_DETECT_FAILED)}}};var lc=class{projectChecker=new ic;toolchainChecker=null;authChecker=new ac;deviceChecker=null;constructor(){}async preflight(e){let t=r=>this.blockingFail(r);return!(!await this.runAuthChain(e,t)||!await this.initToolchain()||!await this.runDeviceCheck(e,t)||!await this.runProjectChecks(e,t)||!await this.runAuxChecks(e))}async runAuthChain(e,t){let r=i=>(i.passed||this.fail(i),!0),o=[()=>this.authChecker.checkLogin(t),()=>this.authChecker.checkTeamInfo(t),()=>this.authChecker.checkRealname(t)];for(let i of o)if(!r(await i()))return!1;return!(e.teamId&&!r(await this.authChecker.checkTeamId(e.teamId)))}async initToolchain(){try{let e=await A.new();return this.toolchainChecker=new sc(e),this.deviceChecker=new cc(e),!0}catch(e){throw m(`[EnvCheck] ToolProvider.new() failed: ${e.message}`),new Error(K.TOOLCHAIN_INIT_FAILED,{cause:e})}}async runDeviceCheck(e,t){return(o=>o.passed?!0:(this.fail(o),!1))(await this.deviceChecker.checkDevice(t,e.teamId))}async runProjectChecks(e,t){let r=i=>i.passed?!0:(this.fail(i),!1);if(!r(this.projectChecker.checkProjectDir(t))||!r(this.projectChecker.checkAtomicService()))return!1;let o=[()=>this.projectChecker.checkProduct(e.productName,t),()=>this.projectChecker.checkBundleName(e.productName,t),()=>this.toolchainChecker.checkJava(t),()=>this.toolchainChecker.checkHapSignTools(t)];for(let i of o)if(!r(i()))return!1;return!0}async runAuxChecks(e){let t=r=>r.passed?!0:(this.fail(r),!1);return!e.teamId&&!t(await this.authChecker.checkTeamId(e.teamId))?!1:(await this.authChecker.checkRegion(r=>this.blockingFail(r)),!0)}blockingFail(e){return{passed:!1,message:e}}fail(e){throw m(`[EnvCheck] FAIL: ${e.message}`),new Error(e.message)}};function yL(n){if(mu.existsSync(n)){let e=mu.readFileSync(n,"utf-8");return gL.parse(e)}return{app:{signingConfigs:[],products:[]}}}function wL(n){n.app||(n.app={signingConfigs:[],products:[]}),n.app.signingConfigs||(n.app.signingConfigs=[]),n.app.products||(n.app.products=[])}async function vL(n){if(n.keyPwd===n.storePassword){let r=await Pn.encryptedPassword(n.keyPwd,n.p12FilePath);return{keyPassword:r,storePassword:r}}let e=await Pn.encryptedPassword(n.keyPwd,n.p12FilePath),t=await Pn.encryptedPassword(n.storePassword,n.p12FilePath);return{keyPassword:e,storePassword:t}}async function SL(n,e,t){let r=Xw.join(n,"build-profile.json5"),o=yL(r);wL(o);let i=t??"default",{keyPassword:s,storePassword:a}=await vL(e),c={name:i,type:"HarmonyOS",material:{certpath:e.cerFilePath,keyAlias:e.keyAlias,keyPassword:s,profile:e.profileFilePath,signAlg:ft.signAlg,storeFile:e.p12FilePath,storePassword:a}},l=o.app?.signingConfigs?.findIndex(h=>h.name===i);l!==void 0&&l>=0?o.app.signingConfigs[l]=c:o.app.signingConfigs.push(c);let d=o.app?.products?.findIndex(h=>h.name===i);d!==void 0&&d>=0?o.app.products[d].signingConfig=i:o.app.products.push({name:i,signingConfig:i}),mu.writeFileSync(r,JSON.stringify(o,null,2),"utf-8")}async function bL(n){let e=await ae.getUserInfo(),t=await ae.refreshToken();if(!e||!t)throw new Error("Failed to obtain login credentials. Run `devecocli login` again.");return{uid:e.userId??"",teamId:n.teamId??e.userId??"",accessToken:t.accessToken??""}}async function EL(n){let e=n.product||"default";await new lc().preflight({productName:e,teamId:n.teamId}),console.log("Executing signature generate command");let r=await bL(n),o=await A.new(),{shouldRegenerate:i}=await Pi.shouldRegenerate({force:n.force??!1,teamId:r.teamId,productName:n.product},o);if(!i){console.log(fu("Signature generation completed successfully."));return}await PL(n,r,o),console.log(fu("Signature generation completed successfully."))}async function PL(n,e,t){let r=await eu(e,n.product),o=CL(n,e,r,t);o.allDeviceIds=await Hw(e,t.hdcPath),await qw(e,o);let i=G.discover(process.cwd()).rootDir;await SL(i,r,n.product??"default"),console.log(fu(`Signing config written to ${Xw.join(i,"build-profile.json5")}`))}function CL(n,e,t,r){let o=process.cwd(),i=G.discover(o),s=nc(i,r);return Yw(s,i),{productName:n.product||"default",bundleName:i.getBundleName(),projectPath:i.rootDir,teamId:e.teamId,force:n.force||!1,aclPermissionList:[...s],certIds:[t.certId],keyAlias:t.keyAlias,keyPwd:t.keyPwd}}var Zw=new mL("signature").description("Generate application signature.");Zw.command("generate").description("Automatically generate signing materials and write them to the project configuration.").option("--force","Force overwrite existing local signing materials.").option("--team-id <team-id>","Specify the team ID to use.").option("--product <product>","Specify the product. The default value is default.").action(async n=>{try{await EL(n)}catch(e){console.error(hL(e.message)),process.exit(1)}});var Qw=Zw;process.env.GLOBAL_AGENT_ENVIRONMENT_VARIABLE_NAMESPACE="";IL();ie.name("devecocli").description("HarmonyOS application development command line tool").version("0.3.0-TD.1.3");ie.addCommand(Qu);ie.addCommand(Tp);ie.addCommand(Lp);ie.addCommand(qp);ie.addCommand(Uf);ie.addCommand(pm);ie.addCommand(gm);ie.addCommand(Am);ie.addCommand(Om);ie.addCommand(eh);ie.addCommand(uy);ie.addCommand(Qw);ie.addCommand(mw);ie.addCommand(_y);b()||ie.addCommand(Sf);var hu=process.argv.slice(2);hu.length>=2&&hu[hu.length-1]==="help"&&(process.argv=[...process.argv.slice(0,-1),"--help"]);var DL=new Set(["update","auth"]);ie.hook("preAction",async(n,e)=>{if(process.env.DEVECO_CLI_SKIP_VERSION_CHECK)return;let t=e;for(;t.parent&&t.parent!==ie;)t=t.parent;DL.has(t.name())||await A.checkVersion()});ie.parseAsync(process.argv).catch(n=>{let e=n instanceof Error?n.message:String(n??"Unknown error");console.error(AL(`Error: ${e}`)),process.env.DEVECO_CLI_DEBUG==="1"&&n instanceof Error&&n.stack&&console.error(n.stack),process.exit(1)});
|
package/docs.zip
CHANGED
|
Binary file
|
package/index.zip
CHANGED
|
Binary file
|