@0xobelisk/sui-cli 1.2.0-pre.53 → 1.2.0-pre.55
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/dubhe.js +3 -3
- package/dist/dubhe.js.map +1 -1
- package/package.json +7 -7
- package/src/commands/wait.ts +1 -1
- package/src/utils/utils.ts +2 -4
package/README.md
CHANGED
|
@@ -26,7 +26,7 @@ Some commands expect a Dubhe config in the same folder where the CLI is being ex
|
|
|
26
26
|
|
|
27
27
|
### `schemagen`
|
|
28
28
|
|
|
29
|
-
Generates Store libraries from a `dubhe.config.ts` file. See the [Store Config and `schemagen` documentation](
|
|
29
|
+
Generates Store libraries from a `dubhe.config.ts` file. See the [Store Config and `schemagen` documentation](https://dubhe-docs.obelisk.build/dubhe/sui/store/config) in the Store section for more details.
|
|
30
30
|
|
|
31
31
|
```bash
|
|
32
32
|
# in a folder with a dubhe.config.ts
|
|
@@ -58,7 +58,7 @@ dubhe publish --network mainnet
|
|
|
58
58
|
|
|
59
59
|
Upgrade Dubhe contract project.
|
|
60
60
|
|
|
61
|
-
When you add a new schema or modify the system code, you need to upgrade the contract through the `upgrade` method. ([
|
|
61
|
+
When you add a new schema or modify the system code, you need to upgrade the contract through the `upgrade` method. ([Migration Guide](https://dubhe-docs.obelisk.build/dubhe/migration))
|
|
62
62
|
|
|
63
63
|
```bash
|
|
64
64
|
dubhe upgrade --network <network:mainnet/testnet/devnet/localnet>
|
package/dist/dubhe.js
CHANGED
|
@@ -12,14 +12,14 @@ Welcome to Dubhe
|
|
|
12
12
|
|
|
13
13
|
`))}import{Transaction as de}from"@0xobelisk/sui-client";import{execSync as qt}from"child_process";import T from"chalk";import*as we from"fs/promises";import{mkdirSync as Mt,writeFileSync as Rt}from"fs";import{dirname as Ft}from"path";import{SUI_PRIVATE_KEY_PREFIX as jt}from"@mysten/sui/cryptography";import X from"chalk";import{ZodError as It}from"zod";import{fromZodError as At,ValidationError as Nt}from"zod-validation-error";var ye=class extends Error{name="NotInsideProjectError";message="You are not inside a Dubhe project"},N=class extends Error{name="DubheCliError"},ie=class extends Error{name="UpgradeError"};function M(e){if(e instanceof Nt)console.log(X.redBright(e.message));else if(e instanceof It){let t=At(e,{prefixSeparator:`
|
|
14
14
|
- `,issueSeparator:`
|
|
15
|
-
- `});console.log(X.redBright(t.message))}else e instanceof ye?(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 N?console.log(X.red(e)):console.log(e)}import*as L from"fs";import F from"chalk";import{spawn as _e}from"child_process";import{Dubhe as Ht,loadMetadata as Vt}from"@0xobelisk/sui-client";var R={name:"@0xobelisk/sui-cli",version:"1.2.0-pre.
|
|
15
|
+
- `});console.log(X.redBright(t.message))}else e instanceof ye?(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 N?console.log(X.red(e)):console.log(e)}import*as L from"fs";import F from"chalk";import{spawn as _e}from"child_process";import{Dubhe as Ht,loadMetadata as Vt}from"@0xobelisk/sui-client";var R={name:"@0xobelisk/sui-cli",version:"1.2.0-pre.55",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:">=22.0.0"},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.35.0","@types/sqlite3":"^3.1.11","@types/wait-on":"^5.3.4",axios:"^1.10.0",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.8.3","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":"^22.16.0","@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 ve(e){if(e.startsWith(jt))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 we.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 we.readFile(`${e}/.history/sui_${t}/latest.json`,"utf8");return JSON.parse(o).dappHub}catch{return""}}async function Y(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 Te(e,t){return(await z(e,t)).components}async function De(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,d,c){let g={projectName:e,network:t,startCheckpoint:o,packageId:n,dappHub:s,upgradeCap:r,version:a,components:u,resources:d,enums:c},f=process.cwd(),h=JSON.stringify(g,null,2);await be(h,`${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 Vt(t,o);if(s){let r=JSON.stringify(s,null,2);await be(r,`${n}/src/${e}/.history/sui_${t}/${o}.json`,"Save package metadata"),await be(r,`${n}/metadata.json`,"Save latest metadata")}}catch(s){console.warn(F.yellow(`Warning: Failed to save metadata: ${s}`))}}async function be(e,t,o){Mt(Ft(t),{recursive:!0}),Rt(t,e),o!==void 0&&console.log(`${o}: ${t}`)}function Ut(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${R.version}" }`;case"mainnet":return`Dubhe = { git = "https://github.com/0xobelisk/dubhe.git", subdir = "packages/sui-framework/src/dubhe", rev = "v${R.version}" }`;default:throw new Error(`Unsupported network: ${e}`)}}async function ce(e,t){let o=L.readFileSync(e,"utf-8"),n=Ut(t),s=o.replace(/Dubhe = \{.*\}/,n);L.writeFileSync(e,s,"utf-8"),console.log(`Updated Dubhe dependency in ${e} for ${t}.`)}async function Lt(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 zt(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 Lt(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="",d=_e("sui",["client","new-env","--alias",e,"--rpc",t[e]],{env:{...process.env},stdio:"pipe"});d.stdout.on("data",c=>{u+=c.toString()}),d.stderr.on("data",c=>{a+=c.toString()}),d.on("error",c=>{console.error(F.red(`
|
|
16
16
|
\u274C Failed to execute sui command: ${c.message}`)),r(new Error(`Failed to execute sui command: ${c.message}`))}),d.on("exit",c=>{if(a.includes("already exists")||u.includes("already exists")){console.log(F.yellow(`Environment ${e} already exists, proceeding...`)),s();return}if(c===0)console.log(F.green(`Successfully added environment ${e}`)),s();else{let g=a||u||`Process exited with code ${c}`;console.error(F.red(`
|
|
17
17
|
\u274C Failed to add environment ${e}`)),console.error(F.red(` \u2514\u2500 ${g.trim()}`)),r(new Error(g))}})})}async function W(e){try{return await zt(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(F.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(F.green(`Successfully switched to environment ${e}`)),t();else{let u=n||s||`Process exited with code ${a}`;console.error(F.red(`
|
|
19
19
|
\u274C Failed to switch to environment ${e}`)),console.error(F.red(` \u2514\u2500 ${u.trim()}`)),o(new Error(u))}})})}catch(t){throw t}}var q=e=>new Promise(t=>setTimeout(t,e));function Wt(){let e=process.env.PRIVATE_KEY||process.env.NEXT_PUBLIC_PRIVATE_KEY;if(!e)throw new N(`Missing private key environment variable.
|
|
20
20
|
Run 'echo "PRIVATE_KEY=YOUR_PRIVATE_KEY" > .env'
|
|
21
21
|
or 'echo "NEXT_PUBLIC_PRIVATE_KEY=YOUR_PRIVATE_KEY" > .env'
|
|
22
|
-
in your contracts directory to use the default sui private key.`);let t=ve(e);if(t===!1)throw new N("Please check your privateKey.");return t}function j({network:e,packageId:t,metadata:o}){let n=Wt();return new Ht({networkType:e,secretKey:n,packageId:t,metadata:o})}function Ne(e){let t=Object.entries(e.components).map(([s,r])=>{if(typeof r=="string")return{[s]:{fields:[{entity_id:"address"},{value:r}],keys:["entity_id"],offchain:!1}};if(Object.keys(r).length===0)return{[s]:{fields:[{entity_id:"address"}],keys:["entity_id"],offchain:!1}};let a=r.fields||{},u=r.keys||["entity_id"],d=r.offchain??!1;return!a.entity_id&&u.includes("entity_id")&&(a.entity_id="address"),{[s]:{fields:Object.entries(a).map(([c,g])=>({[c]:g})),keys:u,offchain:d}}}),o=Object.entries(e.resources).map(([s,r])=>{if(typeof r=="string")return{[s]:{fields:[{value:r}],keys:[],offchain:!1}};if(Object.keys(r).length===0)return{[s]:{fields:[],keys:[],offchain:!1}};let a=r.fields||{},u=r.keys||[],d=r.offchain??!1;return{[s]:{fields:Object.entries(a).map(([c,g])=>({[c]:g})),keys:u,offchain:d}}}),n=Object.entries(e.enums||{}).map(([s,r])=>{let a=r.sort((u,d)=>u.localeCompare(d)).map(
|
|
22
|
+
in your contracts directory to use the default sui private key.`);let t=ve(e);if(t===!1)throw new N("Please check your privateKey.");return t}function j({network:e,packageId:t,metadata:o}){let n=Wt();return new Ht({networkType:e,secretKey:n,packageId:t,metadata:o})}function Ne(e){let t=Object.entries(e.components).map(([s,r])=>{if(typeof r=="string")return{[s]:{fields:[{entity_id:"address"},{value:r}],keys:["entity_id"],offchain:!1}};if(Object.keys(r).length===0)return{[s]:{fields:[{entity_id:"address"}],keys:["entity_id"],offchain:!1}};let a=r.fields||{},u=r.keys||["entity_id"],d=r.offchain??!1;return!a.entity_id&&u.includes("entity_id")&&(a.entity_id="address"),{[s]:{fields:Object.entries(a).map(([c,g])=>({[c]:g})),keys:u,offchain:d}}}),o=Object.entries(e.resources).map(([s,r])=>{if(typeof r=="string")return{[s]:{fields:[{value:r}],keys:[],offchain:!1}};if(Object.keys(r).length===0)return{[s]:{fields:[],keys:[],offchain:!1}};let a=r.fields||{},u=r.keys||[],d=r.offchain??!1;return{[s]:{fields:Object.entries(a).map(([c,g])=>({[c]:g})),keys:u,offchain:d}}}),n=Object.entries(e.enums||{}).map(([s,r])=>{let a=r.sort((u,d)=>u.localeCompare(d)).map(u=>u);return{[s]:a}});return JSON.stringify({components:t,resources:o,enums:n},null,2)}function xe(e,t){let o=`${e}/Move.toml`,s=L.readFileSync(o,"utf-8").replace(/dubhe\s*=\s*"[^"]*"/,`dubhe = "${t}"`);L.writeFileSync(o,s,"utf-8")}function Oe(e,t){let o=`${e}/sources/codegen/genesis.move`,n=L.readFileSync(o,"utf-8"),s=/(\/\/ ==========================================)[\s\S]*?(\/\/ ==========================================)/,r=n.match(s);if(!r)throw new Error("Could not find separator comments in genesis.move");let a=t.map(c=>` ${c}::register_table(dapp_hub, _ctx);`).join(`
|
|
23
23
|
`),u=`${r[1]}
|
|
24
24
|
${a}
|
|
25
25
|
${r[2]}`,d=n.replace(s,u);L.writeFileSync(o,d,"utf-8")}import*as O from"fs";import*as Me from"path";async function Re(e,t){if(!O.existsSync(e))return;let o=O.readFileSync(e,"utf-8"),n=new RegExp(`\\[env\\.${t}\\][\\s\\S]*?(?=\\[|$)`,"g"),s=o.replace(n,"");O.writeFileSync(e,s,"utf-8")}function Fe(e,t,o,n,s){let r=Me.resolve(e),a=O.readFileSync(r,"utf-8"),u=a.split(`
|
|
@@ -64,7 +64,7 @@ export const NETWORK: NetworkType = '${e}';
|
|
|
64
64
|
export const PACKAGE_ID = '${t}';
|
|
65
65
|
export const DUBHE_SCHEMA_ID = '${n}';
|
|
66
66
|
`;Ro(s,o,"storeConfig")}async function Ro(e,t,o){Ao(Oo(t),{recursive:!0}),No(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 Mo(r.network,r.packageId,o)}import{loadConfig as Fo}from"@0xobelisk/sui-common";var jo={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 Fo(e);await rt(n,t,o)}catch(n){console.error("Error storing config:",n),process.exit(1)}process.exit(0)}},it=jo;import Ho from"chokidar";import{exec as Vo}from"child_process";var Uo={command:"watch",describe:"Watch dubhe config",builder(e){return e},async handler(){let e="dubhe.config.ts",t=()=>{Vo("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=Ho.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=Uo;import lt from"wait-on";import ke from"ora";import H from"chalk";import Lo from"net";function ct(e){let t={HTTP_PROXY:process.env.HTTP_PROXY,HTTPS_PROXY:process.env.HTTPS_PROXY,http_proxy:process.env.http_proxy,https_proxy:process.env.https_proxy,NO_PROXY:process.env.NO_PROXY,no_proxy:process.env.no_proxy};try{return delete process.env.HTTP_PROXY,delete process.env.HTTPS_PROXY,delete process.env.http_proxy,delete process.env.https_proxy,process.env.NO_PROXY="127.0.0.1,localhost,*.local",process.env.no_proxy="127.0.0.1,localhost,*.local",e()}finally{Object.keys(t).forEach(o=>{let n=t[o];n!==void 0?process.env[o]=n:delete process.env[o]})}}async function zo(){return new Promise(e=>{let t=new Lo.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 Wo(e){let t=ke({text:"Waiting for dubhe localnet services...",color:"cyan"});t.start();let o=Date.now();for(;Date.now()-o<e.timeout;){try{if(await ct(()=>lt({resources:["http://127.0.0.1:9123","http://127.0.0.1:4000"],timeout:e.interval,interval:500,validateStatus:s=>s===200})),await zo()){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 qo={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 Wo(t);else{let o=ke({text:`Waiting for ${t.url}...`,color:"cyan"});o.start(),await ct(()=>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{ke().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)}}},dt=qo;var Bo={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)}},ut=Bo;import Ko from"dotenv";import J from"chalk";Ko.config();var Yo={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){M(t),process.exit(1)}}},pt=Yo;import{loadConfig as Go}from"@0xobelisk/sui-common";async function gt(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 Jo={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 Go(t);await gt(n,e,o)}catch(n){M(n),process.exit(1)}process.exit(0)}},mt=Jo;import i from"chalk";import{spawn as Zo}from"child_process";import bt from"cli-table3";import fe from"inquirer";import*as x from"fs";import*as D from"path";import*as K from"os";import*as vt from"net";import en from"axios";import me from"chalk";import*as ft from"cli-progress";import*as ht from"fs";import Xo from"axios";async function yt(e,t){try{let o=await Xo.get(e,{responseType:"stream",timeout:3e4,headers:{"User-Agent":"dubhe-cli"},maxRedirects:5,validateStatus:n=>n<400});await Qo(o,t),console.log(me.green(" \u2713 Successfully downloaded"))}catch(o){if(o.code==="ENOTFOUND")throw new Error(`DNS resolution failed: ${o.message}. Please check your internet connection.`);if(o.code==="ECONNRESET")throw new Error(`Connection reset: ${o.message}. Please check your network connection.`);if(o.code==="ETIMEDOUT")throw new Error(`Connection timeout: ${o.message}. Please check your network connection.`);if(o.message.includes("protocol mismatch"))throw new Error(`Protocol mismatch: ${o.message}. Please check your network configuration.`);if(o.response)throw new Error(`HTTP ${o.response.status}: ${o.response.statusText}`);{let n=o instanceof Error?o.message:String(o);throw new Error(`Download failed: ${n}`)}}}async function Qo(e,t){let o=parseInt(e.headers["content-length"]||"0"),n=new ft.SingleBar({format:me.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});o>0?n.start(Math.round(o/1024/1024*100)/100,0,{speed:"0.00"}):console.log(me.blue("\u{1F4E5} Downloading... (unable to get file size)"));let s=ht.createWriteStream(t),r=0,a=Date.now();return new Promise((u,d)=>{e.data.on("data",c=>{if(r+=c.length,o>0){let g=Math.round(r/1024/1024*100)/100,f=(Date.now()-a)/1e3,h=f>0?Math.round(g/f*100)/100:0;n.update(g,{speed:h.toFixed(2)})}}),e.data.pipe(s),s.on("finish",()=>{o>0&&n.stop();let c=Math.round(r/1024/1024*100)/100,g=(Date.now()-a)/1e3,f=g>0?Math.round(c/g*100)/100:0;console.log(me.green(`\u2713 Download completed! ${c} MB, average speed: ${f} MB/s`)),u()}),s.on("error",c=>{o>0&&n.stop(),d(c)})})}function Se(){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:D.join(K.homedir(),".dubhe","bin")},"dubhe-indexer":{name:"dubhe-indexer",repo:"0xobelisk/dubhe",binaryName:"dubhe-indexer",installDir:D.join(K.homedir(),".dubhe","bin")}};async function V(e,t=[]){return new Promise(o=>{let n=Zo(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 xt(e,t={}){try{let o={timeout:3e4,maxRedirects:5,validateStatus:s=>s<500,...t},n=await en(e,o);return{ok:n.status>=200&&n.status<300,status:n.status,statusText:n.statusText,json:async()=>n.data,headers:n.headers}}catch(o){let n=o.response?.status||0,s=o.response?.statusText||o.message;return o.code==="ENOTFOUND"?s="DNS resolution failed - please check your internet connection":o.code==="ECONNRESET"?s="Connection reset - please check your network connection":o.code==="ETIMEDOUT"?s="Connection timeout - please check your network connection":o.message.includes("protocol mismatch")&&(s="Protocol mismatch - please check your network configuration"),{ok:!1,status:n,statusText:s,json:async()=>o.response?.data||{},headers:o.response?.headers||{}}}}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 xt(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)),d=a.some(g=>s.includes(g)),c=s.endsWith(".tar.gz")||s.endsWith(".zip")||s.endsWith(".tgz")||s.endsWith(".tar.bz2")||s.endsWith(".tar.xz");return u&&d&&c}).map(n=>n.name)}async function tn(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 on(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(x.existsSync(n)&&x.readFileSync(n,"utf8").includes(e)){console.log(i.green(` \u2713 PATH already configured in ${n}`));return}let a=`# Added by dubhe doctor
|
|
67
|
+
Watch stopped.`),process.exit()})}},at=Uo;import lt from"wait-on";import ke from"ora";import H from"chalk";import Lo from"net";function ct(e){let t={HTTP_PROXY:process.env.HTTP_PROXY,HTTPS_PROXY:process.env.HTTPS_PROXY,http_proxy:process.env.http_proxy,https_proxy:process.env.https_proxy,NO_PROXY:process.env.NO_PROXY,no_proxy:process.env.no_proxy};try{return delete process.env.HTTP_PROXY,delete process.env.HTTPS_PROXY,delete process.env.http_proxy,delete process.env.https_proxy,process.env.NO_PROXY="127.0.0.1,localhost,*.local",process.env.no_proxy="127.0.0.1,localhost,*.local",e()}finally{Object.keys(t).forEach(o=>{let n=t[o];n!==void 0?process.env[o]=n:delete process.env[o]})}}async function zo(){return new Promise(e=>{let t=new Lo.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 Wo(e){let t=ke({text:"Waiting for dubhe localnet services...",color:"cyan"});t.start();let o=Date.now();for(;Date.now()-o<e.timeout;){try{if(await ct(()=>lt({resources:["http://127.0.0.1:9123","http://127.0.0.1:4000"],timeout:e.interval,interval:500,validateStatus:s=>s===200})),await zo()){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 qo={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:24*60*60*1e3}).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 Wo(t);else{let o=ke({text:`Waiting for ${t.url}...`,color:"cyan"});o.start(),await ct(()=>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{ke().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)}}},dt=qo;var Bo={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)}},ut=Bo;import Ko from"dotenv";import J from"chalk";Ko.config();var Yo={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){M(t),process.exit(1)}}},pt=Yo;import{loadConfig as Go}from"@0xobelisk/sui-common";async function gt(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 Jo={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 Go(t);await gt(n,e,o)}catch(n){M(n),process.exit(1)}process.exit(0)}},mt=Jo;import i from"chalk";import{spawn as Zo}from"child_process";import bt from"cli-table3";import fe from"inquirer";import*as x from"fs";import*as D from"path";import*as K from"os";import*as vt from"net";import en from"axios";import me from"chalk";import*as ft from"cli-progress";import*as ht from"fs";import Xo from"axios";async function yt(e,t){try{let o=await Xo.get(e,{responseType:"stream",timeout:3e4,headers:{"User-Agent":"dubhe-cli"},maxRedirects:5,validateStatus:n=>n<400});await Qo(o,t),console.log(me.green(" \u2713 Successfully downloaded"))}catch(o){if(o.code==="ENOTFOUND")throw new Error(`DNS resolution failed: ${o.message}. Please check your internet connection.`);if(o.code==="ECONNRESET")throw new Error(`Connection reset: ${o.message}. Please check your network connection.`);if(o.code==="ETIMEDOUT")throw new Error(`Connection timeout: ${o.message}. Please check your network connection.`);if(o.message.includes("protocol mismatch"))throw new Error(`Protocol mismatch: ${o.message}. Please check your network configuration.`);if(o.response)throw new Error(`HTTP ${o.response.status}: ${o.response.statusText}`);{let n=o instanceof Error?o.message:String(o);throw new Error(`Download failed: ${n}`)}}}async function Qo(e,t){let o=parseInt(e.headers["content-length"]||"0"),n=new ft.SingleBar({format:me.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});o>0?n.start(Math.round(o/1024/1024*100)/100,0,{speed:"0.00"}):console.log(me.blue("\u{1F4E5} Downloading... (unable to get file size)"));let s=ht.createWriteStream(t),r=0,a=Date.now();return new Promise((u,d)=>{e.data.on("data",c=>{if(r+=c.length,o>0){let g=Math.round(r/1024/1024*100)/100,f=(Date.now()-a)/1e3,h=f>0?Math.round(g/f*100)/100:0;n.update(g,{speed:h.toFixed(2)})}}),e.data.pipe(s),s.on("finish",()=>{o>0&&n.stop();let c=Math.round(r/1024/1024*100)/100,g=(Date.now()-a)/1e3,f=g>0?Math.round(c/g*100)/100:0;console.log(me.green(`\u2713 Download completed! ${c} MB, average speed: ${f} MB/s`)),u()}),s.on("error",c=>{o>0&&n.stop(),d(c)})})}function Se(){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:D.join(K.homedir(),".dubhe","bin")},"dubhe-indexer":{name:"dubhe-indexer",repo:"0xobelisk/dubhe",binaryName:"dubhe-indexer",installDir:D.join(K.homedir(),".dubhe","bin")}};async function V(e,t=[]){return new Promise(o=>{let n=Zo(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 xt(e,t={}){try{let o={timeout:3e4,maxRedirects:5,validateStatus:s=>s<500,...t},n=await en(e,o);return{ok:n.status>=200&&n.status<300,status:n.status,statusText:n.statusText,json:async()=>n.data,headers:n.headers}}catch(o){let n=o.response?.status||0,s=o.response?.statusText||o.message;return o.code==="ENOTFOUND"?s="DNS resolution failed - please check your internet connection":o.code==="ECONNRESET"?s="Connection reset - please check your network connection":o.code==="ETIMEDOUT"?s="Connection timeout - please check your network connection":o.message.includes("protocol mismatch")&&(s="Protocol mismatch - please check your network configuration"),{ok:!1,status:n,statusText:s,json:async()=>o.response?.data||{},headers:o.response?.headers||{}}}}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 xt(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)),d=a.some(g=>s.includes(g)),c=s.endsWith(".tar.gz")||s.endsWith(".zip")||s.endsWith(".tgz")||s.endsWith(".tar.bz2")||s.endsWith(".tar.xz");return u&&d&&c}).map(n=>n.name)}async function tn(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 on(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(x.existsSync(n)&&x.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}`;x.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:D.join(e,".zshrc")};if(t.includes("bash")){let n=D.join(e,".bash_profile"),s=D.join(e,".bashrc");return{shellName:"bash",configFile:process.platform==="darwin"&&x.existsSync(n)?n:s}}else if(t.includes("fish")){let n=D.join(e,".config","fish");return x.existsSync(n)||x.mkdirSync(n,{recursive:!0}),{shellName:"fish",configFile:D.join(n,"config.fish")}}}let o=[{name:"zsh",file:D.join(e,".zshrc")},{name:"bash",file:process.platform==="darwin"?D.join(e,".bash_profile"):D.join(e,".bashrc")},{name:"bash",file:D.join(e,".bashrc")}];for(let n of o)if(x.existsSync(n.file))return{shellName:n.name,configFile:n.file};return process.env.ZSH||x.existsSync("/bin/zsh")?{shellName:"zsh",configFile:D.join(e,".zshrc")}:null}async function $e(e,t){let o=A[e];if(!o)return console.error(`Unknown tool: ${e}`),!1;let n=Se();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],d=r.assets.find(l=>l.name===u);if(!d)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: ${d.name}`));try{let l=await xt(d.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 k=l.headers["content-length"];k&&console.log(i.gray(` File size: ${Math.round(parseInt(k)/1024/1024*100)/100} MB`))}}catch{console.log(i.yellow(" \u26A0\uFE0F Warning: Unable to verify download file"))}x.existsSync(o.installDir)||(x.mkdirSync(o.installDir,{recursive:!0}),console.log(i.gray(` Created install directory: ${o.installDir}`))),console.log(i.blue(" \u{1F4E5} Downloading..."));let c=D.join(K.tmpdir(),d.name),g=3;for(let l=1;l<=g;l++)try{l>1&&console.log(i.gray(` Attempt ${l} to download...`)),await yt(d.browser_download_url,c);break}catch(k){let p=k instanceof Error?k.message:String(k);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(y=>setTimeout(y,l*2e3))}console.log(i.blue(" \u{1F4E6} Extracting and installing..."));let f=D.join(K.tmpdir(),`extract_${Date.now()}`);if(x.mkdirSync(f,{recursive:!0}),d.name.endsWith(".tar.gz")||d.name.endsWith(".tgz")){let l=await V("tar",["-xzf",c,"-C",f]);if(l.code!==0)throw new Error(`Extraction failed: ${l.stderr}`)}else if(d.name.endsWith(".tar.bz2")){let l=await V("tar",["-xjf",c,"-C",f]);if(l.code!==0)throw new Error(`Extraction failed: ${l.stderr}`)}else if(d.name.endsWith(".tar.xz")){let l=await V("tar",["-xJf",c,"-C",f]);if(l.code!==0)throw new Error(`Extraction failed: ${l.stderr}`)}else if(d.name.endsWith(".zip")){let l=await V("unzip",["-q",c,"-d",f]);if(l.code!==0)throw new Error(`Extraction failed: ${l.stderr}`)}else throw new Error(`Unsupported compression format: ${d.name}`);let h=l=>{let k=x.readdirSync(l,{withFileTypes:!0});for(let p of k){let y=D.join(l,p.name);if(p.isDirectory()){let $=h(y);if($)return $}else if(p.name===o.binaryName||p.name===`${o.binaryName}.exe`)return y}return null},b=h(f);if(!b)throw new Error(`Cannot find ${o.binaryName} binary in extracted files`);let P=D.join(o.installDir,o.binaryName+(process.platform==="win32"?".exe":""));return x.copyFileSync(b,P),process.platform!=="win32"&&x.chmodSync(P,493),x.rmSync(c,{force:!0}),x.rmSync(f,{recursive:!0,force:!0}),console.log(i.green(" \u2705 Installation completed!")),console.log(i.gray(` Location: ${P}`)),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 on(o.installDir)),!0}catch(s){return console.error(i.red(`\u274C Installation failed: ${s}`)),!1}}async function nn(e){let t=Se(),o=await tn(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(`
|