@0xobelisk/sui-cli 1.2.0-pre.50 → 1.2.0-pre.51
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/dubhe.js +3 -3
- package/dist/dubhe.js.map +1 -1
- package/package.json +3 -3
- package/src/commands/doctor.ts +2 -2
- package/src/utils/utils.ts +28 -23
package/dist/dubhe.js
CHANGED
|
@@ -12,7 +12,7 @@ Welcome to Dubhe
|
|
|
12
12
|
|
|
13
13
|
`))}import{Transaction as de}from"@0xobelisk/sui-client";import{execSync as Lt}from"child_process";import D from"chalk";import*as be from"fs/promises";import{mkdirSync as At,writeFileSync as Mt}from"fs";import{dirname as Nt}from"path";import{SUI_PRIVATE_KEY_PREFIX as Ot}from"@mysten/sui/cryptography";import X from"chalk";import{ZodError as Dt}from"zod";import{fromZodError as Tt,ValidationError as Et}from"zod-validation-error";var he=class extends Error{name="NotInsideProjectError";message="You are not inside a Dubhe project"},M=class extends Error{name="DubheCliError"},ie=class extends Error{name="UpgradeError"};function O(e){if(e instanceof Et)console.log(X.redBright(e.message));else if(e instanceof Dt){let t=Tt(e,{prefixSeparator:`
|
|
14
14
|
- `,issueSeparator:`
|
|
15
|
-
- `});console.log(X.redBright(t.message))}else e instanceof he?(console.log(X.red(e.message)),console.log(""),console.log(X.blue("To learn more about Dubhe's configuration, please go to https://github.com/0xobelisk"))):e instanceof M?console.log(X.red(e)):console.log(e)}import*as L from"fs";import R from"chalk";import{spawn as _e}from"child_process";import{Dubhe as Ft,loadMetadata as Rt}from"@0xobelisk/sui-client";var F={name:"@0xobelisk/sui-cli",version:"1.2.0-pre.
|
|
15
|
+
- `});console.log(X.redBright(t.message))}else e instanceof he?(console.log(X.red(e.message)),console.log(""),console.log(X.blue("To learn more about Dubhe's configuration, please go to https://github.com/0xobelisk"))):e instanceof M?console.log(X.red(e)):console.log(e)}import*as L from"fs";import R from"chalk";import{spawn as _e}from"child_process";import{Dubhe as Ft,loadMetadata as Rt}from"@0xobelisk/sui-client";var F={name:"@0xobelisk/sui-cli",version:"1.2.0-pre.51",description:"Tookit for interacting with move eps framework",keywords:["sui","obelisk labs","move","blockchain"],type:"module",author:"team@obelisk.build",homepage:"https://github.com/0xobelisk/dubhe/tree/main/packages/sui-cli#readme",bugs:"https://github.com/0xobelisk/dubhe/issues",repository:{type:"git",url:"https://github.com/0xobelisk/dubhe.git"},license:"Apache-2.0",publishConfig:{access:"public"},engines:{node:">=18"},exports:{".":"./dist/index.js"},types:"src/index.ts",bin:{dubhe:"./dist/dubhe.js"},scripts:{build:"pnpm run type-check && pnpm run build:js","build:js":"tsup && chmod +x ./dist/dubhe.js",clean:"pnpm run clean:js","clean:js":"rimraf dist",dev:"tsup --watch",lint:"eslint . --ext .ts",format:"prettier --write .","format:check":"prettier --check .","type-check":"tsc --noEmit",validate:"pnpm format:check && pnpm type-check"},dependencies:{"@0xobelisk/sui-client":"workspace:*","@0xobelisk/sui-common":"workspace:*","@mysten/sui":"^1.19.0","@types/sqlite3":"^3.1.11","@types/wait-on":"^5.3.4",chalk:"^5.0.1",child_process:"^1.0.2",chokidar:"^3.5.3","cli-progress":"^3.12.0","cli-table3":"^0.6.5",dotenv:"^16.0.3",ejs:"^3.1.8",execa:"^7.0.0",glob:"^8.0.3","http-proxy-agent":"^7.0.2","https-proxy-agent":"^7.0.6",inquirer:"^9.2.15",ora:"^5.4.1",path:"^0.12.7",sqlite:"^5.1.1",sqlite3:"^5.1.7",typescript:"5.1.6","wait-on":"^7.0.1",yargs:"^17.7.1",zod:"^3.22.3","zod-validation-error":"^1.3.0"},devDependencies:{"@types/cli-progress":"^3.11.5","@types/ejs":"^3.1.1","@types/glob":"^7.2.0","@types/inquirer":"^9.0.7","@types/node":"^18.15.11","@types/yargs":"^17.0.10",eslint:"^8.56.0","eslint-config-prettier":"^9.1.0",prettier:"3.3.3","ts-node":"^10.9.1",tsup:"^6.7.0",tsx:"^3.12.6",vitest:"0.31.4"}};function we(e){if(e.startsWith(Ot))return e.length===70?e:!1;if(e.startsWith("0x")){let t=e.slice(2);return t.length===64?t:!1}else return e.length===64?e:!1}async function z(e,t){try{let o=await be.readFile(`${e}/.history/sui_${t}/latest.json`,"utf8");return JSON.parse(o)}catch(o){throw new Error(`read .history/sui_${t}/latest.json failed. ${o}`)}}async function ae(e,t){try{let o=await be.readFile(`${e}/.history/sui_${t}/latest.json`,"utf8");return JSON.parse(o).dappHub}catch{return""}}async function G(e){let o=`${process.cwd()}/src/dubhe`;switch(e){case"mainnet":return await ae(o,"mainnet");case"testnet":return await ae(o,"testnet");case"devnet":return await ae(o,"devnet");case"localnet":return await ae(o,"localnet");default:throw new Error(`Invalid network: ${e}`)}}async function De(e,t){return(await z(e,t)).components}async function Te(e,t){return(await z(e,t)).resources}async function Ee(e,t){return(await z(e,t)).version}async function le(e,t){return(await z(e,t)).packageId}async function Ie(e,t){return(await z(e,t)).upgradeCap}async function Ae(e,t){return(await z(e,t)).startCheckpoint}async function Q(e,t,o,n,s,r,a,u,c,d){let g={projectName:e,network:t,startCheckpoint:o,packageId:n,dappHub:s,upgradeCap:r,version:a,components:u,resources:c,enums:d},f=process.cwd(),y=JSON.stringify(g,null,2);await ye(y,`${f}/src/${e}/.history/sui_${t}/latest.json`,"Update deploy log")}async function Z(e,t,o){let n=process.cwd();try{let s=await Rt(t,o);if(s){let r=JSON.stringify(s,null,2);await ye(r,`${n}/src/${e}/.history/sui_${t}/${o}.json`,"Save package metadata"),await ye(r,`${n}/metadata.json`,"Save latest metadata")}}catch(s){console.warn(R.yellow(`Warning: Failed to save metadata: ${s}`))}}async function ye(e,t,o){At(Nt(t),{recursive:!0}),Mt(t,e),o!==void 0&&console.log(`${o}: ${t}`)}function jt(e){switch(e){case"localnet":return'Dubhe = { local = "../dubhe" }';case"testnet":return`Dubhe = { git = "https://github.com/0xobelisk/dubhe.git", subdir = "packages/sui-framework/src/dubhe", rev = "v${F.version}" }`;case"mainnet":return`Dubhe = { git = "https://github.com/0xobelisk/dubhe.git", subdir = "packages/sui-framework/src/dubhe", rev = "v${F.version}" }`;default:throw new Error(`Unsupported network: ${e}`)}}async function ce(e,t){let o=L.readFileSync(e,"utf-8"),n=jt(t),s=o.replace(/Dubhe = \{.*\}/,n);L.writeFileSync(e,s,"utf-8"),console.log(`Updated Dubhe dependency in ${e} for ${t}.`)}async function Ht(e){try{let t=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({jsonrpc:"2.0",id:1,method:"sui_getLatestCheckpointSequenceNumber",params:[]})});return t.ok?!(await t.json()).error:!1}catch{return!1}}async function Vt(e){let t={localnet:"http://127.0.0.1:9000",devnet:"https://fullnode.devnet.sui.io:443/",testnet:"https://fullnode.testnet.sui.io:443/",mainnet:"https://fullnode.mainnet.sui.io:443/"},o=t[e];if(!await Ht(o))throw new Error(`RPC endpoint ${o} is not available. Please check your network connection or try again later.`);return new Promise((s,r)=>{let a="",u="",c=_e("sui",["client","new-env","--alias",e,"--rpc",t[e]],{env:{...process.env},stdio:"pipe"});c.stdout.on("data",d=>{u+=d.toString()}),c.stderr.on("data",d=>{a+=d.toString()}),c.on("error",d=>{console.error(R.red(`
|
|
16
16
|
\u274C Failed to execute sui command: ${d.message}`)),r(new Error(`Failed to execute sui command: ${d.message}`))}),c.on("exit",d=>{if(a.includes("already exists")||u.includes("already exists")){console.log(R.yellow(`Environment ${e} already exists, proceeding...`)),s();return}if(d===0)console.log(R.green(`Successfully added environment ${e}`)),s();else{let g=a||u||`Process exited with code ${d}`;console.error(R.red(`
|
|
17
17
|
\u274C Failed to add environment ${e}`)),console.error(R.red(` \u2514\u2500 ${g.trim()}`)),r(new Error(g))}})})}async function W(e){try{return await Vt(e),new Promise((t,o)=>{let n="",s="",r=_e("sui",["client","switch","--env",e],{env:{...process.env},stdio:"pipe"});r.stdout.on("data",a=>{s+=a.toString()}),r.stderr.on("data",a=>{n+=a.toString()}),r.on("error",a=>{console.error(R.red(`
|
|
18
18
|
\u274C Failed to execute sui command: ${a.message}`)),o(new Error(`Failed to execute sui command: ${a.message}`))}),r.on("exit",a=>{if(a===0)console.log(R.green(`Successfully switched to environment ${e}`)),t();else{let u=n||s||`Process exited with code ${a}`;console.error(R.red(`
|
|
@@ -64,14 +64,14 @@ export const NETWORK: NetworkType = '${e}';
|
|
|
64
64
|
export const PACKAGE_ID = '${t}';
|
|
65
65
|
export const DUBHE_SCHEMA_ID = '${n}';
|
|
66
66
|
`;Mo(s,o,"storeConfig")}async function Mo(e,t,o){To(Io(t),{recursive:!0}),Eo(t,e),o!==void 0&&console.log(`${o}: ${t}`)}async function rt(e,t,o){let s=`${process.cwd()}/src/${e.name}`,r=await z(s,t);await Ao(r.network,r.packageId,o)}import{loadConfig as No}from"@0xobelisk/sui-common";var Oo={command:"config-store",describe:"Store configuration for the Dubhe project",builder:{"config-path":{type:"string",default:"dubhe.config.ts",desc:"Path to the config file"},network:{type:"string",choices:["mainnet","testnet","devnet","localnet"],desc:"Network to store config for"},"output-ts-path":{type:"string",desc:"Specify the output path for the generated TypeScript configuration file (e.g., ./src/config/generated.ts)"}},async handler({"config-path":e,network:t,"output-ts-path":o}){try{let n=await No(e);await rt(n,t,o)}catch(n){console.error("Error storing config:",n),process.exit(1)}process.exit(0)}},it=Oo;import Fo from"chokidar";import{exec as Ro}from"child_process";var jo={command:"watch",describe:"Watch dubhe config",builder(e){return e},async handler(){let e="dubhe.config.ts",t=()=>{Ro("pnpm dubhe schemagen",(n,s,r)=>{if(n){console.error(`Error executing schemagen: ${n.message}`);return}if(r){console.error(`schemagen stderr: ${r}`);return}console.log(`schemagen stdout: ${s}`)})},o=Fo.watch(e,{persistent:!0});o.on("change",n=>{console.log(`${n} has been changed. Running schemagen...`),t()}),console.log(`Watching for changes in ${e}...`),process.on("SIGINT",()=>{o.close(),console.log(`
|
|
67
|
-
Watch stopped.`),process.exit()})}},at=jo;import lt from"wait-on";import Ce from"ora";import H from"chalk";import Ho from"net";async function Vo(){return new Promise(e=>{let t=new Ho.Socket,o=!1,n=setTimeout(()=>{t.destroy(),o||e(!1)},2e3);t.connect(5432,"127.0.0.1",()=>{o=!0,clearTimeout(n),t.destroy(),e(!0)}),t.on("error",()=>{clearTimeout(n),o||e(!1)})})}async function Uo(e){let t=Ce({text:"Waiting for dubhe localnet services...",color:"cyan"});t.start();let o=Date.now();for(;Date.now()-o<e.timeout;){try{if(await lt({resources:["http://127.0.0.1:9123","http://127.0.0.1:4000"],timeout:e.interval,interval:500,validateStatus:s=>s===200}),await Vo()){t.succeed(H.green("All dubhe localnet services are ready!"));return}}catch{}await new Promise(n=>setTimeout(n,e.interval))}throw new Error("Timeout waiting for services")}var Lo={command:"wait",describe:"Wait for service(s) to be ready",builder(e){return e.option("url",{type:"string",description:"URL to wait for (single service)"}).option("localnet",{type:"boolean",description:"Wait for all dubhe localnet services (sui localnode:9000&9123, postgres:5432, graphql:4000)",default:!1}).option("timeout",{type:"number",description:"Timeout (in milliseconds)",default:18e4}).option("interval",{type:"number",description:"Check interval (in milliseconds)",default:1e3}).check(t=>{if(!t.url&&!t.localnet)throw new Error("Please provide either --url or --localnet option");if(t.url&&t.localnet)throw new Error("Cannot use both --url and --localnet options together");return!0})},async handler(e){let t=e;try{if(t.localnet)await Uo(t);else{let o=Ce({text:`Waiting for ${t.url}...`,color:"cyan"});o.start(),await lt({resources:[t.url],timeout:t.timeout,interval:t.interval,validateStatus:n=>n===200}),o.succeed(H.green("Service is ready!"))}process.exit(0)}catch{Ce().fail(H.red(t.localnet?"Timeout waiting for dubhe localnet services":"Timeout waiting for service")),t.localnet?(console.error(H.yellow("Please make sure all required services are running:")),console.error(H.yellow("- Sui localnode on port 9000")),console.error(H.yellow("- Sui faucet on port 9123")),console.error(H.yellow("- PostgreSQL database on port 5432")),console.error(H.yellow("- Dubhe GraphQL server on port 4000"))):console.error(H.yellow("Please make sure the service is running...")),process.exit(1)}}},ct=Lo;var zo={command:"switch-env",describe:"Switch environment",builder(e){return e.option("network",{type:"string",choices:["mainnet","testnet","devnet","localnet"],default:"localnet",desc:"Switch to node network (mainnet/testnet/devnet/localnet)"})},async handler(e){await W(e.network)}},dt=zo;import Wo from"dotenv";import J from"chalk";Wo.config();var qo={command:"info",describe:"Get information about the current Sui node",builder(e){return e.options({network:{type:"string",choices:["mainnet","testnet","devnet","localnet"],default:"localnet",desc:"Node network (mainnet/testnet/devnet/localnet)"}})},handler:async({network:e})=>{try{let t=j({network:e}),o=t.getSigner();console.log(J.blue("Account Information:")),console.log(` Network: ${J.green(e)}`),console.log(` Address: ${J.green(o.toSuiAddress())}`);try{let n=await t.getBalance("0x2::sui::SUI"),s=(Number(n.totalBalance)/10**9).toFixed(4);console.log(` Balance: ${J.green(s)} SUI`)}catch{console.log(` Balance: ${J.red("Failed to fetch balance")} ${J.gray("(Network error)")}`)}}catch(t){O(t),process.exit(1)}}},ut=qo;import{loadConfig as Bo}from"@0xobelisk/sui-common";async function pt(e,t,o){if(o)await Z(e.name,t,o);else{let n=`${process.cwd()}/src/${e.name}`,s=await le(n,t);await Z(e.name,t,s)}}var Ko={command:"load-metadata",describe:"Load metadata for a package",builder(e){return e.options({network:{type:"string",choices:["mainnet","testnet","devnet","localnet"],default:"localnet",desc:"Node network (mainnet/testnet/devnet/localnet)"},"config-path":{type:"string",desc:"Configuration file path",default:"dubhe.config.ts"},"package-id":{type:"string",desc:"Package ID to load metadata for",optional:!0}})},async handler({network:e,"config-path":t,"package-id":o}){try{let n=await Bo(t);await pt(n,e,o)}catch(n){O(n),process.exit(1)}process.exit(0)}},gt=Ko;import i from"chalk";import{spawn as Go}from"child_process";import mt from"cli-table3";import me from"inquirer";import*as yt from"cli-progress";import*as C from"fs";import*as E from"path";import*as K from"os";import*as bt from"net";import{HttpsProxyAgent as ft}from"https-proxy-agent";import{HttpProxyAgent as Yo}from"http-proxy-agent";function $e(){let e=process.platform,t=process.arch,o,n;switch(e){case"darwin":o="macos";break;case"win32":o="windows";break;case"linux":o="ubuntu";break;default:o=e}switch(t){case"x64":n="x86_64";break;case"arm64":n="aarch64";break;default:n=t}return{platform:e,arch:t,platformForAsset:o,archForAsset:n}}var A={sui:{name:"sui",repo:"MystenLabs/sui",binaryName:"sui",installDir:E.join(K.homedir(),".dubhe","bin")},"dubhe-indexer":{name:"dubhe-indexer",repo:"0xobelisk/dubhe
|
|
67
|
+
Watch stopped.`),process.exit()})}},at=jo;import lt from"wait-on";import Ce from"ora";import H from"chalk";import Ho from"net";async function Vo(){return new Promise(e=>{let t=new Ho.Socket,o=!1,n=setTimeout(()=>{t.destroy(),o||e(!1)},2e3);t.connect(5432,"127.0.0.1",()=>{o=!0,clearTimeout(n),t.destroy(),e(!0)}),t.on("error",()=>{clearTimeout(n),o||e(!1)})})}async function Uo(e){let t=Ce({text:"Waiting for dubhe localnet services...",color:"cyan"});t.start();let o=Date.now();for(;Date.now()-o<e.timeout;){try{if(await lt({resources:["http://127.0.0.1:9123","http://127.0.0.1:4000"],timeout:e.interval,interval:500,validateStatus:s=>s===200}),await Vo()){t.succeed(H.green("All dubhe localnet services are ready!"));return}}catch{}await new Promise(n=>setTimeout(n,e.interval))}throw new Error("Timeout waiting for services")}var Lo={command:"wait",describe:"Wait for service(s) to be ready",builder(e){return e.option("url",{type:"string",description:"URL to wait for (single service)"}).option("localnet",{type:"boolean",description:"Wait for all dubhe localnet services (sui localnode:9000&9123, postgres:5432, graphql:4000)",default:!1}).option("timeout",{type:"number",description:"Timeout (in milliseconds)",default:18e4}).option("interval",{type:"number",description:"Check interval (in milliseconds)",default:1e3}).check(t=>{if(!t.url&&!t.localnet)throw new Error("Please provide either --url or --localnet option");if(t.url&&t.localnet)throw new Error("Cannot use both --url and --localnet options together");return!0})},async handler(e){let t=e;try{if(t.localnet)await Uo(t);else{let o=Ce({text:`Waiting for ${t.url}...`,color:"cyan"});o.start(),await lt({resources:[t.url],timeout:t.timeout,interval:t.interval,validateStatus:n=>n===200}),o.succeed(H.green("Service is ready!"))}process.exit(0)}catch{Ce().fail(H.red(t.localnet?"Timeout waiting for dubhe localnet services":"Timeout waiting for service")),t.localnet?(console.error(H.yellow("Please make sure all required services are running:")),console.error(H.yellow("- Sui localnode on port 9000")),console.error(H.yellow("- Sui faucet on port 9123")),console.error(H.yellow("- PostgreSQL database on port 5432")),console.error(H.yellow("- Dubhe GraphQL server on port 4000"))):console.error(H.yellow("Please make sure the service is running...")),process.exit(1)}}},ct=Lo;var zo={command:"switch-env",describe:"Switch environment",builder(e){return e.option("network",{type:"string",choices:["mainnet","testnet","devnet","localnet"],default:"localnet",desc:"Switch to node network (mainnet/testnet/devnet/localnet)"})},async handler(e){await W(e.network)}},dt=zo;import Wo from"dotenv";import J from"chalk";Wo.config();var qo={command:"info",describe:"Get information about the current Sui node",builder(e){return e.options({network:{type:"string",choices:["mainnet","testnet","devnet","localnet"],default:"localnet",desc:"Node network (mainnet/testnet/devnet/localnet)"}})},handler:async({network:e})=>{try{let t=j({network:e}),o=t.getSigner();console.log(J.blue("Account Information:")),console.log(` Network: ${J.green(e)}`),console.log(` Address: ${J.green(o.toSuiAddress())}`);try{let n=await t.getBalance("0x2::sui::SUI"),s=(Number(n.totalBalance)/10**9).toFixed(4);console.log(` Balance: ${J.green(s)} SUI`)}catch{console.log(` Balance: ${J.red("Failed to fetch balance")} ${J.gray("(Network error)")}`)}}catch(t){O(t),process.exit(1)}}},ut=qo;import{loadConfig as Bo}from"@0xobelisk/sui-common";async function pt(e,t,o){if(o)await Z(e.name,t,o);else{let n=`${process.cwd()}/src/${e.name}`,s=await le(n,t);await Z(e.name,t,s)}}var Ko={command:"load-metadata",describe:"Load metadata for a package",builder(e){return e.options({network:{type:"string",choices:["mainnet","testnet","devnet","localnet"],default:"localnet",desc:"Node network (mainnet/testnet/devnet/localnet)"},"config-path":{type:"string",desc:"Configuration file path",default:"dubhe.config.ts"},"package-id":{type:"string",desc:"Package ID to load metadata for",optional:!0}})},async handler({network:e,"config-path":t,"package-id":o}){try{let n=await Bo(t);await pt(n,e,o)}catch(n){O(n),process.exit(1)}process.exit(0)}},gt=Ko;import i from"chalk";import{spawn as Go}from"child_process";import mt from"cli-table3";import me from"inquirer";import*as yt from"cli-progress";import*as C from"fs";import*as E from"path";import*as K from"os";import*as bt from"net";import{HttpsProxyAgent as ft}from"https-proxy-agent";import{HttpProxyAgent as Yo}from"http-proxy-agent";function $e(){let e=process.platform,t=process.arch,o,n;switch(e){case"darwin":o="macos";break;case"win32":o="windows";break;case"linux":o="ubuntu";break;default:o=e}switch(t){case"x64":n="x86_64";break;case"arm64":n="aarch64";break;default:n=t}return{platform:e,arch:t,platformForAsset:o,archForAsset:n}}var A={sui:{name:"sui",repo:"MystenLabs/sui",binaryName:"sui",installDir:E.join(K.homedir(),".dubhe","bin")},"dubhe-indexer":{name:"dubhe-indexer",repo:"0xobelisk/dubhe",binaryName:"dubhe-indexer",installDir:E.join(K.homedir(),".dubhe","bin")}};async function V(e,t=[]){return new Promise(o=>{let n=Go(e,t,{shell:!0}),s="",r="";n.stdout?.on("data",a=>{s+=a.toString()}),n.stderr?.on("data",a=>{r+=a.toString()}),n.on("close",a=>{o({code:a||0,stdout:s,stderr:r})}),n.on("error",()=>{o({code:-1,stdout:s,stderr:r})})})}async function Jo(e,t){let o=await Se(e,{headers:{"User-Agent":"dubhe-cli"}});if(!o.ok)throw new Error(`HTTP ${o.status}: ${o.statusText}`);let n=o.headers.get("content-length"),s=n?parseInt(n):0,r=new yt.SingleBar({format:i.cyan("Download Progress")+" |{bar}| {percentage}% | {value}/{total} MB | Speed: {speed} MB/s | ETA: {eta}s",barCompleteChar:"\u2588",barIncompleteChar:"\u2591",hideCursor:!0,barsize:30,forceRedraw:!0});s>0?r.start(Math.round(s/1024/1024*100)/100,0,{speed:"0.00"}):console.log(i.blue("\u{1F4E5} Downloading... (unable to get file size)"));let a=o.body?.getReader();if(!a)throw new Error("Unable to get response stream");let u=[],c=0,d=Date.now();try{for(;;){let{done:l,value:x}=await a.read();if(l)break;if(u.push(x),c+=x.length,s>0){let p=Math.round(c/1024/1024*100)/100,h=(Date.now()-d)/1e3,k=h>0?Math.round(p/h*100)/100:0;r.update(p,{speed:k.toFixed(2)})}}let g=u.reduce((l,x)=>l+x.length,0),f=new Uint8Array(g),y=0;for(let l of u)f.set(l,y),y+=l.length;C.writeFileSync(t,f),s>0&&r.stop();let b=Math.round(c/1024/1024*100)/100,S=(Date.now()-d)/1e3,T=S>0?Math.round(b/S*100)/100:0;console.log(i.green(`\u2713 Download completed! ${b} MB, average speed: ${T} MB/s`))}catch(g){throw s>0&&r.stop(),g}}async function Se(e,t={}){let o=process.env.HTTP_PROXY||process.env.http_proxy,n=process.env.HTTPS_PROXY||process.env.https_proxy,s=process.env.NO_PROXY||process.env.no_proxy;if(s){let u=s.split(",").map(d=>d.trim()),c=new URL(e).hostname;for(let d of u)if(d==="*"||c===d||c.endsWith("."+d)||d.startsWith(".")&&c.endsWith(d))return fetch(e,t)}let r=new URL(e).protocol,a;if(r==="https:"&&n?a=new ft(n):r==="http:"&&o?a=new Yo(o):n&&r==="https:"&&(a=new ft(n)),a)try{let u={...t,dispatcher:a};return await fetch(e,u)}catch{try{let c={...t,agent:a};return await fetch(e,c)}catch{return console.log(i.yellow(" \u26A0\uFE0F Warning: Could not use proxy, falling back to direct connection")),fetch(e,t)}}return fetch(e,t)}async function Pe(e,t=10,o=3){let n=`https://api.github.com/repos/${e}/releases?per_page=${t}`;for(let s=1;s<=o;s++)try{s>1&&console.log(i.gray(` Retry ${s}/${o}...`));let r=await Se(n,{headers:{"User-Agent":"dubhe-cli",Accept:"application/vnd.github.v3+json"}});if(!r.ok)throw r.status===403?new Error(`GitHub API rate limit: ${r.status}. Please retry later or set GITHUB_TOKEN environment variable`):new Error(`GitHub API request failed: ${r.status} ${r.statusText}`);return await r.json()}catch(r){if(s>1&&console.log(i.yellow(` \u26A0\uFE0F Attempt ${s} failed: ${r instanceof Error?r.message:String(r)}`)),s===o)return console.error(i.red(` \u274C Failed to fetch releases after ${o} attempts`)),[];await new Promise(a=>setTimeout(a,1e3*s))}return[]}function ne(e,t){return e.assets.filter(n=>{let s=n.name.toLowerCase(),r=[t.platformForAsset.toLowerCase(),...t.platformForAsset==="macos"?["darwin","apple"]:[],...t.platformForAsset==="windows"?["win","win32","windows"]:[],...t.platformForAsset==="ubuntu"?["linux","gnu"]:[]],a=[t.archForAsset.toLowerCase(),...t.archForAsset==="x86_64"?["amd64","x64"]:[],...t.archForAsset==="aarch64"?["arm64"]:[]],u=r.some(g=>s.includes(g)),c=a.some(g=>s.includes(g)),d=s.endsWith(".tar.gz")||s.endsWith(".zip")||s.endsWith(".tgz")||s.endsWith(".tar.bz2")||s.endsWith(".tar.xz");return u&&c&&d}).map(n=>n.name)}async function Xo(e,t){let o=A[e];return o?(await Pe(o.repo,10)).map(s=>({version:s.tag_name,hasCompatibleAsset:ne(s,t).length>0})):[]}async function Qo(e){try{let t=se();if(!t){console.log(i.gray(`Please add to PATH: export PATH="$PATH:${e}"`));return}let{shellName:o,configFile:n}=t,s=o==="fish"?`set -gx PATH $PATH ${e}`:`export PATH="$PATH:${e}"`;if(C.existsSync(n)&&C.readFileSync(n,"utf8").includes(e)){console.log(i.green(` \u2713 PATH already configured in ${n}`));return}let a=`# Added by dubhe doctor
|
|
68
68
|
${s}`;C.appendFileSync(n,`
|
|
69
69
|
${a}
|
|
70
70
|
`),console.log(i.green(` \u2713 Automatically added to PATH in ${n}`)),console.log(i.blue(` \u{1F4DD} To apply changes: source ${n} or restart terminal`))}catch(t){console.log(i.yellow(` \u26A0\uFE0F Could not auto-configure PATH: ${t instanceof Error?t.message:String(t)}`)),console.log(i.gray(` Please manually add to PATH: export PATH="$PATH:${e}"`))}}function se(){let e=K.homedir(),t=process.env.SHELL;if(t){if(t.includes("zsh"))return{shellName:"zsh",configFile:E.join(e,".zshrc")};if(t.includes("bash")){let n=E.join(e,".bash_profile"),s=E.join(e,".bashrc");return{shellName:"bash",configFile:process.platform==="darwin"&&C.existsSync(n)?n:s}}else if(t.includes("fish")){let n=E.join(e,".config","fish");return C.existsSync(n)||C.mkdirSync(n,{recursive:!0}),{shellName:"fish",configFile:E.join(n,"config.fish")}}}let o=[{name:"zsh",file:E.join(e,".zshrc")},{name:"bash",file:process.platform==="darwin"?E.join(e,".bash_profile"):E.join(e,".bashrc")},{name:"bash",file:E.join(e,".bashrc")}];for(let n of o)if(C.existsSync(n.file))return{shellName:n.name,configFile:n.file};return process.env.ZSH||C.existsSync("/bin/zsh")?{shellName:"zsh",configFile:E.join(e,".zshrc")}:null}async function ke(e,t){let o=A[e];if(!o)return console.error(`Unknown tool: ${e}`),!1;let n=$e();console.log(i.gray(` System: ${n.platform}/${n.arch}`));try{console.log(i.gray(" Fetching release information..."));let s=await Pe(o.repo,10);if(s.length===0)return console.error(i.red(` \u274C Unable to fetch releases for ${o.name}`)),!1;let r=null;if(t){if(t.startsWith("v")||(t=`v${t}`),r=s.find(l=>l.tag_name===t)||null,!r)return console.error(`Version ${t} not found`),!1}else for(let l of s)if(ne(l,n).length>0){r=l;break}if(!r)return console.error("No compatible version found"),!1;let a=ne(r,n);if(a.length===0)return console.error(`Version ${r.tag_name} has no compatible binaries`),!1;let u=a[0],c=r.assets.find(l=>l.name===u);if(!c)return console.error(`Asset file not found: ${u}`),!1;console.log(i.green(` \u2713 Found compatible version: ${r.tag_name}`)),console.log(i.gray(` Download file: ${c.name}`));try{let l=await Se(c.browser_download_url,{method:"HEAD",headers:{"User-Agent":"dubhe-cli"}});if(!l.ok)console.log(i.yellow(` \u26A0\uFE0F Warning: Unable to access download file (${l.status})`));else{let x=l.headers.get("content-length");x&&console.log(i.gray(` File size: ${Math.round(parseInt(x)/1024/1024*100)/100} MB`))}}catch{console.log(i.yellow(" \u26A0\uFE0F Warning: Unable to verify download file"))}C.existsSync(o.installDir)||(C.mkdirSync(o.installDir,{recursive:!0}),console.log(i.gray(` Created install directory: ${o.installDir}`))),console.log(i.blue(" \u{1F4E5} Downloading..."));let d=E.join(K.tmpdir(),c.name),g=3;for(let l=1;l<=g;l++)try{l>1&&console.log(i.gray(` Attempt ${l} to download...`)),await Jo(c.browser_download_url,d);break}catch(x){let p=x instanceof Error?x.message:String(x);if(console.log(i.yellow(` \u26A0\uFE0F Download failed (attempt ${l}): ${p}`)),l===g)throw new Error(`Download failed after ${g} attempts: ${p}`);console.log(i.gray(` Waiting ${l*2} seconds before retry...`)),await new Promise(h=>setTimeout(h,l*2e3))}console.log(i.blue(" \u{1F4E6} Extracting and installing..."));let f=E.join(K.tmpdir(),`extract_${Date.now()}`);if(C.mkdirSync(f,{recursive:!0}),c.name.endsWith(".tar.gz")||c.name.endsWith(".tgz")){let l=await V("tar",["-xzf",d,"-C",f]);if(l.code!==0)throw new Error(`Extraction failed: ${l.stderr}`)}else if(c.name.endsWith(".tar.bz2")){let l=await V("tar",["-xjf",d,"-C",f]);if(l.code!==0)throw new Error(`Extraction failed: ${l.stderr}`)}else if(c.name.endsWith(".tar.xz")){let l=await V("tar",["-xJf",d,"-C",f]);if(l.code!==0)throw new Error(`Extraction failed: ${l.stderr}`)}else if(c.name.endsWith(".zip")){let l=await V("unzip",["-q",d,"-d",f]);if(l.code!==0)throw new Error(`Extraction failed: ${l.stderr}`)}else throw new Error(`Unsupported compression format: ${c.name}`);let y=l=>{let x=C.readdirSync(l,{withFileTypes:!0});for(let p of x){let h=E.join(l,p.name);if(p.isDirectory()){let k=y(h);if(k)return k}else if(p.name===o.binaryName||p.name===`${o.binaryName}.exe`)return h}return null},b=y(f);if(!b)throw new Error(`Cannot find ${o.binaryName} binary in extracted files`);let S=E.join(o.installDir,o.binaryName+(process.platform==="win32"?".exe":""));return C.copyFileSync(b,S),process.platform!=="win32"&&C.chmodSync(S,493),C.rmSync(d,{force:!0}),C.rmSync(f,{recursive:!0,force:!0}),console.log(i.green(" \u2705 Installation completed!")),console.log(i.gray(` Location: ${S}`)),console.log(i.gray(` Version: ${r.tag_name}`)),(process.env.PATH||"").includes(o.installDir)||(console.log(i.yellow(" \u26A0\uFE0F Warning: Install directory is not in PATH environment variable")),process.platform==="win32"?console.log(i.gray(` Please add to PATH: set PATH=%PATH%;${o.installDir}`)):await Qo(o.installDir)),!0}catch(s){return console.error(i.red(`\u274C Installation failed: ${s}`)),!1}}async function Zo(e){let t=$e(),o=await Xo(e,t);if(o.length===0)return console.log(i.red(`Unable to get version information for ${e}`)),null;let n=o.filter(r=>r.hasCompatibleAsset).slice(0,5);if(n.length===0)return console.log(i.red("No compatible versions found for current system")),null;console.log(i.blue(`
|
|
71
71
|
\u{1F4CB} Select version for ${e}`)),console.log(i.gray(`System: ${t.platform}/${t.arch}`)),console.log(i.gray(`Compatible versions (latest 5):
|
|
72
72
|
`));let s=n.map((r,a)=>({name:`${r.version} ${a===0?i.green("(latest)"):i.gray("(available)")}`,value:r.version,short:r.version}));try{let r=await me.prompt([{type:"list",name:"version",message:"Please select a version to install:",choices:[...s,new me.Separator,{name:i.gray("Cancel installation"),value:"cancel"}],default:s[0].value}]);return r.version==="cancel"?(console.log(i.gray("Installation cancelled")),null):r.version}catch{return console.log(i.gray(`
|
|
73
73
|
Installation cancelled`)),null}}function fe(e){let t=A[e];if(!t)return!1;let o=E.join(t.installDir,t.binaryName+(process.platform==="win32"?".exe":""));return C.existsSync(o)}async function en(){try{let e=F.version,t=await V("dubhe-indexer",["--version"]);if(t.code!==0)return{name:"Dubhe-indexer Version Consistency",status:"warning",message:"Cannot get dubhe-indexer version",fixSuggestion:"Unable to verify version consistency"};let o=t.stdout.trim().match(/dubhe-indexer\s+(\S+)/);if(!o)return{name:"Dubhe-indexer Version Consistency",status:"warning",message:"Cannot parse dubhe-indexer version",fixSuggestion:"Unable to verify version consistency"};let n=o[1];return e===n?{name:"Dubhe-indexer Version Consistency",status:"success",message:`Versions match (${e})`}:{name:"Dubhe-indexer Version Consistency",status:"warning",message:`Version mismatch: sui-cli ${e}, dubhe-indexer ${n}`,fixSuggestion:`Consider reinstalling dubhe-indexer to match sui-cli version ${e}`}}catch{return{name:"Dubhe-indexer Version Consistency",status:"warning",message:"Version check failed",fixSuggestion:"Unable to verify version consistency"}}}async function oe(e,t="--version"){try{let o=await V(e,[t]);if(o.code===0){let n=o.stdout.trim().split(`
|
|
74
|
-
`)[0];return{name:e,status:"success",message:`Installed ${n}`}}else{if(fe(e)){let n=se(),s=n?n.configFile:"~/.zshrc (or ~/.bashrc)";return{name:e,status:"warning",message:"Installed but not in PATH",fixSuggestion:`Binary exists in install directory. Please apply PATH changes: source ${s} (or restart terminal), then run dubhe doctor again`}}return{name:e,status:"error",message:"Not installed",fixSuggestion:ht(e)}}}catch{if(fe(e)){let n=se(),s=n?n.configFile:"~/.zshrc (or ~/.bashrc)";return{name:e,status:"warning",message:"Installed but not in PATH",fixSuggestion:`Binary exists in install directory. Please apply PATH changes: source ${s} (or restart terminal), then run dubhe doctor again`}}return{name:e,status:"error",message:"Not installed",fixSuggestion:ht(e)}}}function ht(e){return{docker:"Visit https://docs.docker.com/get-docker/ to install Docker","docker-compose":"Visit https://docs.docker.com/compose/install/ to install Docker Compose",sui:"Run `dubhe doctor --install sui` to auto-install, or visit https://docs.sui.io/guides/developer/getting-started/sui-install","dubhe-indexer":"Run `dubhe doctor --install dubhe-indexer` to auto-install, or download from https://github.com/0xobelisk/dubhe
|
|
74
|
+
`)[0];return{name:e,status:"success",message:`Installed ${n}`}}else{if(fe(e)){let n=se(),s=n?n.configFile:"~/.zshrc (or ~/.bashrc)";return{name:e,status:"warning",message:"Installed but not in PATH",fixSuggestion:`Binary exists in install directory. Please apply PATH changes: source ${s} (or restart terminal), then run dubhe doctor again`}}return{name:e,status:"error",message:"Not installed",fixSuggestion:ht(e)}}}catch{if(fe(e)){let n=se(),s=n?n.configFile:"~/.zshrc (or ~/.bashrc)";return{name:e,status:"warning",message:"Installed but not in PATH",fixSuggestion:`Binary exists in install directory. Please apply PATH changes: source ${s} (or restart terminal), then run dubhe doctor again`}}return{name:e,status:"error",message:"Not installed",fixSuggestion:ht(e)}}}function ht(e){return{docker:"Visit https://docs.docker.com/get-docker/ to install Docker","docker-compose":"Visit https://docs.docker.com/compose/install/ to install Docker Compose",sui:"Run `dubhe doctor --install sui` to auto-install, or visit https://docs.sui.io/guides/developer/getting-started/sui-install","dubhe-indexer":"Run `dubhe doctor --install dubhe-indexer` to auto-install, or download from https://github.com/0xobelisk/dubhe/releases",pnpm:"Run: npm install -g pnpm",node:"Visit https://nodejs.org/ to download and install Node.js"}[e]||`Please install ${e}`}async function tn(){try{let e=await V("node",["--version"]);if(e.code===0){let t=e.stdout.trim();return parseFloat(t.replace("v",""))>=18?{name:"Node.js Version",status:"success",message:`${t} (meets requirement >=18.0)`}:{name:"Node.js Version",status:"warning",message:`${t} (recommend upgrade to >=18.0)`,fixSuggestion:"Please upgrade Node.js to 18.0 or higher"}}else return{name:"Node.js Version",status:"error",message:"Not installed",fixSuggestion:"Please install Node.js 18.0 or higher"}}catch{return{name:"Node.js Version",status:"error",message:"Check failed",fixSuggestion:"Please install Node.js"}}}async function on(){try{return(await V("docker",["info"])).code===0?{name:"Docker Service",status:"success",message:"Running"}:{name:"Docker Service",status:"warning",message:"Not running",fixSuggestion:"Please start Docker service"}}catch{return{name:"Docker Service",status:"error",message:"Check failed",fixSuggestion:"Please install and start Docker"}}}async function nn(){try{let e=await V("npm",["config","get","registry"]);return e.code===0?{name:"NPM Configuration",status:"success",message:`Configured (${e.stdout.trim()})`}:{name:"NPM Configuration",status:"warning",message:"Configuration issue",fixSuggestion:"Check NPM configuration: npm config list"}}catch{return{name:"NPM Configuration",status:"warning",message:"Check failed",fixSuggestion:"Please install Node.js and NPM"}}}async function wt(e){let t=["127.0.0.1","0.0.0.0"];for(let o of t)if(!await sn(e,o))return!1;return!0}async function sn(e,t){return new Promise(o=>{let n=bt.createServer(),s=setTimeout(()=>{n.close(),o(!1)},2e3);n.listen(e,t,()=>{clearTimeout(s),n.close(()=>{o(!0)})}),n.on("error",r=>{clearTimeout(s),n.close(),r.code,o(!1)})})}async function rn(){try{return await wt(5432)?{name:"PostgreSQL Port (5432)",status:"success",message:"Available"}:{name:"PostgreSQL Port (5432)",status:"warning",message:"Port is occupied",fixSuggestion:"Port 5432 is in use. Check if PostgreSQL is already running or stop the service using this port. This may cause template startup failure."}}catch{return{name:"PostgreSQL Port (5432)",status:"warning",message:"Check failed",fixSuggestion:"Unable to check port status"}}}async function an(){try{return await wt(4e3)?{name:"GraphQL Server Port (4000)",status:"success",message:"Available"}:{name:"GraphQL Server Port (4000)",status:"warning",message:"Port is occupied",fixSuggestion:"Port 4000 is in use. Check if GraphQL server is already running or stop the service using this port. This may cause template startup failure."}}catch{return{name:"GraphQL Server Port (4000)",status:"warning",message:"Check failed",fixSuggestion:"Unable to check port status"}}}function ln(e){let t={success:i.green("\u2713"),warning:i.yellow("!"),error:i.red("\u2717")},o={success:i.green("Pass"),warning:i.yellow("Warning"),error:i.red("Fail")},n="";return e.status==="success"?n=e.message:n=e.fixSuggestion||e.message,[e.name,`${t[e.status]} ${o[e.status]}`,n]}async function cn(e){if(console.log(i.bold.blue(`
|
|
75
75
|
\u{1F50D} Dubhe Doctor - Development Environment Checker
|
|
76
76
|
`)),e.listVersions){let p=e.listVersions;A[p]||(console.error(i.red(`\u274C Unsupported tool: ${p}`)),process.exit(1)),console.log(i.blue(`\u{1F4CB} Available versions for ${p}:`));let h=$e();console.log(i.gray(`System: ${h.platform}/${h.arch}
|
|
77
77
|
`));let k=A[p],I=await Pe(k.repo,10);I.length===0&&(console.log(i.red("Unable to get version information")),process.exit(1));let P=I.map(m=>({version:m.tag_name,hasCompatibleAsset:ne(m,h).length>0,publishDate:new Date(m.published_at).toLocaleDateString("en-US")})),_=new mt({head:[i.bold.cyan("Version"),i.bold.cyan("Compatibility"),i.bold.cyan("Release Date")],colWidths:[30,15,25]});if(P.forEach(m=>{_.push([m.version,m.hasCompatibleAsset?i.green("\u2713 Compatible"):i.red("\u2717 Incompatible"),m.publishDate])}),console.log(_.toString()),e.debug&&P.length>0){console.log(i.blue(`
|