@radhya/mach 2.0.36 → 2.0.37

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.
Files changed (2) hide show
  1. package/dist/index.js +1 -1
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1535,7 +1535,7 @@ ${r}
1535
1535
  `)?`\r
1536
1536
  `:`
1537
1537
  `,l=o[1]||"",a=o[2]||"",u=a.match(/\r?\n([ \t]+)\S/)?.[1]||`${l} `,c=a.trim().length===0?`${s}${u}'${ke}',${s}${l}`:a.includes(`
1538
- `)||a.includes("\r")?`${s}${u}'${ke}',${a}`:`${s}${u}'${ke}',${s}${u}${a.trim()}${s}${l}`,p=`${o[0].slice(0,o[0].indexOf("[")+1)}${c}]`;return le.writeFileSync(n,`${i.slice(0,o.index)}${p}${i.slice(o.index+o[0].length)}`),"inserted"}async function fm(e,t){let n=[];if(!Qr(e)){let r=!!(t.installPlugin||t.yes);if(!r&&!t.skipInstall&&el()){let o=await tm({message:`Install ${m.npmScope}/mach locally so Expo can use ${ke}?`,initialValue:!0});Yr(o)&&qr(),r=!!o}if(r&&!t.skipInstall){let o=dm(e);o.ok?n.push(`Installed ${m.npmScope}/mach with ${o.label}.`):n.push(`Could not install ${m.npmScope}/mach with ${o.label}: ${o.error||"unknown error"}.`)}else n.push(`Install ${m.npmScope}/mach in this app so Expo can resolve ${ke}.`)}let i=pm(e);if(i==="already"&&n.push(`Expo config already includes ${ke}.`),i==="inserted"&&n.push(`Expo config updated to include ${ke}.`),i==="manual"&&n.push(`Add "${ke}" to the plugins array in app.config.ts/app.config.js.`),i==="missing"){let r=um(e);r?n.push(`${r} updated to include ${ke}.`):n.push(`Add "${ke}" to your Expo config plugins array.`)}return n}async function Ya(e,t,n,i,r){if(t)return t;if(r||!el()){if(i)throw new Error(`${e.replace(/:$/,"")} is required.`);return}let o=await om({message:e,placeholder:n,validate(s){if(i&&s.trim().length===0)return"Required."}});return Yr(o)&&qr(),Rt(o)}function mm(e,t,n){return bn(e,{runtimeVersion:t.runtimeVersion,framework:He(t.framework)||He(e.framework),platform:n})}function gm(e){return Qa.createHash("sha256").update(le.readFileSync(e)).digest("hex")}function hm(e){let t=Se.extname(e).toLowerCase();return t===".json"?"application/json":t===".js"||t===".bundle"||t===".hbc"?"application/javascript":t===".map"?"application/json":t===".png"?"image/png":t===".jpg"||t===".jpeg"?"image/jpeg":t===".webp"?"image/webp":t===".gif"?"image/gif":t===".svg"?"image/svg+xml":t===".ttf"?"font/ttf":t===".otf"?"font/otf":t===".woff"?"font/woff":t===".woff2"?"font/woff2":"application/octet-stream"}function nl(e){let t=[];if(!le.existsSync(e))return t;for(let n of le.readdirSync(e)){let i=Se.join(e,n),r=le.statSync(i);r.isDirectory()?t.push(...nl(i)):r.isFile()&&t.push(i)}return t}function ym(e,t){let n=e.filter(i=>{let r=i.toLowerCase();return r.endsWith(".map")?!1:r.endsWith(".js")||r.endsWith(".bundle")||r.endsWith(".hbc")});return n.find(i=>i.toLowerCase().includes(t))||n.sort((i,r)=>le.statSync(r).size-le.statSync(i).size)[0]}async function qa(e){let t=await N.post("/ota/upload-url",{projectId:e.projectId,updateId:e.updateId,platform:e.platform,fileName:e.fileName,contentType:e.contentType});if(t.data.status!=="success")throw new Error(t.data.message||`Could not create upload URL for ${e.fileName}`);return await sm.put(t.data.uploadUrl,le.createReadStream(e.filePath),{headers:{"Content-Type":e.contentType},maxBodyLength:1/0,maxContentLength:1/0}),{key:t.data.key,url:t.data.publicUrl,contentType:e.contentType,hash:gm(e.filePath),size:le.statSync(e.filePath).size}}function il(e,t,n){let i=Za(e,t,{cwd:n,stdio:"inherit",env:{...process.env,CI:process.env.CI||"1",EXPO_NO_TELEMETRY:"1"}});if(i.error)throw new Error(i.error.message);if(i.status!==0)throw new Error(`${e} ${t.join(" ")} exited with code ${i.status}`)}function Sm(e,t){il("npx",["expo","export","--platform",e,"--output-dir",t],process.cwd())}function bm(e,t){let n=e==="ios"?"main.jsbundle":"index.android.bundle",r=["index.js","index.ts","index.tsx"].find(s=>le.existsSync(Se.join(process.cwd(),s)))||"index.js",o=Se.join(t,"assets");le.mkdirSync(o,{recursive:!0}),il("npx",["react-native","bundle","--platform",e,"--dev","false","--entry-file",r,"--bundle-output",Se.join(t,n),"--assets-dest",o],process.cwd())}async function Am(e){let t=e.config.projectId,n=`ota_${Date.now()}_${e.platform}_${Qa.randomUUID().slice(0,8)}`,i=Se.join(process.cwd(),".mach","ota",n,e.platform);le.rmSync(i,{recursive:!0,force:!0}),le.mkdirSync(i,{recursive:!0}),e.engine==="expo-updates"?Sm(e.platform,i):bm(e.platform,i);let r=nl(i),o=ym(r,e.platform);if(!o)throw new Error(`Could not find a ${e.platform} JS bundle in ${i}.`);let s=[];for(let f of r){let g=Se.relative(i,f).replace(/\\/g,"/");s.push({filePath:f,relative:g,uploaded:await qa({projectId:t,updateId:n,platform:e.platform,filePath:f,fileName:g,contentType:hm(f)})})}let l=s.find(f=>f.filePath===o),a=s.filter(f=>f.filePath!==o&&!f.relative.endsWith(".map")).map(f=>({key:f.relative,url:f.uploaded.url,contentType:f.uploaded.contentType,hash:f.uploaded.hash,size:f.uploaded.size})),d={id:n,createdAt:new Date().toISOString(),runtimeVersion:e.runtimeVersion,platform:e.platform,launchAsset:{key:Se.basename(l.relative),url:l.uploaded.url,contentType:l.uploaded.contentType,hash:l.uploaded.hash,size:l.uploaded.size},assets:a,metadata:{projectId:t,channel:e.channel,message:e.message||null,engine:e.engine},extra:{mach:{projectId:t,updateId:n,channel:e.channel,platform:e.platform}}},u=Se.join(i,"mach-manifest.json");le.writeFileSync(u,JSON.stringify(d,null,2));let c=await qa({projectId:t,updateId:n,platform:e.platform,filePath:u,fileName:"manifest.json",contentType:"application/json"}),p=await N.post("/ota/publish",{projectId:t,updateId:n,channelName:e.channel,runtimeVersion:e.runtimeVersion,platform:e.platform,manifestKey:c.key,message:e.message,launchAsset:d.launchAsset,assets:a});if(p.data.status!=="success")throw new Error(p.data.message||`Failed to publish ${e.platform} OTA update.`);return p.data.update}async function Em(e){let t=Ln(),n=He(e.framework)||Xr(t),i=Zr(e.engine||t.ota?.engine,n),r=!!e.yes,o=await Ya("OTA channel:",Rt(e.channel||e.branch||t.ota?.channel)||"production","production",!0,r),s=`${dt.replace(/\/$/,"")}/api/ota/${i==="expo-updates"?"expo":"react-native"}/${t.projectId}`,l=await Ya("Mach OTA update URL:",Rt(e.url||t.ota?.url)||s,s,!0,r);t.framework=n,t.ota={...t.ota||{},enabled:!0,engine:i,channel:o,url:l,deploymentUrl:l,statsUrl:`${dt.replace(/\/$/,"")}/api/ota/events`,runtimeVersionPolicy:t.ota?.runtimeVersionPolicy||"appVersion"},delete t.update,am(t);let a=[`${m.configFileName} updated.`];n==="expo"?a.push(...await fm(process.cwd(),e)):a.push("Vanilla React Native native OTA client setup is planned; this command wrote Mach config only for now."),nm(a.map(d=>`- ${d}`).join(`
1538
+ `)||a.includes("\r")?`${s}${u}'${ke}',${a}`:`${s}${u}'${ke}',${s}${u}${a.trim()}${s}${l}`,p=`${o[0].slice(0,o[0].indexOf("[")+1)}${c}]`;return le.writeFileSync(n,`${i.slice(0,o.index)}${p}${i.slice(o.index+o[0].length)}`),"inserted"}async function fm(e,t){let n=[];if(!Qr(e)){let r=!!(t.installPlugin||t.yes);if(!r&&!t.skipInstall&&el()){let o=await tm({message:`Install ${m.npmScope}/mach locally so Expo can use ${ke}?`,initialValue:!0});Yr(o)&&qr(),r=!!o}if(r&&!t.skipInstall){let o=dm(e);o.ok?n.push(`Installed ${m.npmScope}/mach with ${o.label}.`):n.push(`Could not install ${m.npmScope}/mach with ${o.label}: ${o.error||"unknown error"}.`)}else n.push(`Install ${m.npmScope}/mach in this app so Expo can resolve ${ke}.`)}let i=pm(e);if(i==="already"&&n.push(`Expo config already includes ${ke}.`),i==="inserted"&&n.push(`Expo config updated to include ${ke}.`),i==="manual"&&n.push(`Add "${ke}" to the plugins array in app.config.ts/app.config.js.`),i==="missing"){let r=um(e);r?n.push(`${r} updated to include ${ke}.`):n.push(`Add "${ke}" to your Expo config plugins array.`)}return n}async function Ya(e,t,n,i,r){if(t)return t;if(r||!el()){if(i)throw new Error(`${e.replace(/:$/,"")} is required.`);return}let o=await om({message:e,placeholder:n,validate(s){if(i&&s.trim().length===0)return"Required."}});return Yr(o)&&qr(),Rt(o)}function mm(e,t,n){return bn(e,{runtimeVersion:t.runtimeVersion,framework:He(t.framework)||He(e.framework),platform:n})}function gm(e){return Qa.createHash("sha256").update(le.readFileSync(e)).digest("hex")}function hm(e){let t=Se.extname(e).toLowerCase();return t===".json"?"application/json":t===".js"||t===".bundle"||t===".hbc"?"application/javascript":t===".map"?"application/json":t===".png"?"image/png":t===".jpg"||t===".jpeg"?"image/jpeg":t===".webp"?"image/webp":t===".gif"?"image/gif":t===".svg"?"image/svg+xml":t===".ttf"?"font/ttf":t===".otf"?"font/otf":t===".woff"?"font/woff":t===".woff2"?"font/woff2":"application/octet-stream"}function nl(e){let t=[];if(!le.existsSync(e))return t;for(let n of le.readdirSync(e)){let i=Se.join(e,n),r=le.statSync(i);r.isDirectory()?t.push(...nl(i)):r.isFile()&&t.push(i)}return t}function ym(e,t){let n=e.filter(i=>{let r=i.toLowerCase();return r.endsWith(".map")?!1:r.endsWith(".js")||r.endsWith(".bundle")||r.endsWith(".hbc")});return n.find(i=>i.toLowerCase().includes(t))||n.sort((i,r)=>le.statSync(r).size-le.statSync(i).size)[0]}async function qa(e){let t=await N.post("/ota/upload-url",{projectId:e.projectId,updateId:e.updateId,platform:e.platform,fileName:e.fileName,contentType:e.contentType});if(t.data.status!=="success")throw new Error(t.data.message||`Could not create upload URL for ${e.fileName}`);let n=le.statSync(e.filePath).size;return await sm.put(t.data.uploadUrl,le.createReadStream(e.filePath),{headers:{"Content-Type":e.contentType,"Content-Length":n},maxBodyLength:1/0,maxContentLength:1/0}),{key:t.data.key,url:t.data.publicUrl,contentType:e.contentType,hash:gm(e.filePath),size:n}}function il(e,t,n){let i=Za(e,t,{cwd:n,stdio:"inherit",env:{...process.env,CI:process.env.CI||"1",EXPO_NO_TELEMETRY:"1"}});if(i.error)throw new Error(i.error.message);if(i.status!==0)throw new Error(`${e} ${t.join(" ")} exited with code ${i.status}`)}function Sm(e,t){il("npx",["expo","export","--platform",e,"--output-dir",t],process.cwd())}function bm(e,t){let n=e==="ios"?"main.jsbundle":"index.android.bundle",r=["index.js","index.ts","index.tsx"].find(s=>le.existsSync(Se.join(process.cwd(),s)))||"index.js",o=Se.join(t,"assets");le.mkdirSync(o,{recursive:!0}),il("npx",["react-native","bundle","--platform",e,"--dev","false","--entry-file",r,"--bundle-output",Se.join(t,n),"--assets-dest",o],process.cwd())}async function Am(e){let t=e.config.projectId,n=`ota_${Date.now()}_${e.platform}_${Qa.randomUUID().slice(0,8)}`,i=Se.join(process.cwd(),".mach","ota",n,e.platform);le.rmSync(i,{recursive:!0,force:!0}),le.mkdirSync(i,{recursive:!0}),e.engine==="expo-updates"?Sm(e.platform,i):bm(e.platform,i);let r=nl(i),o=ym(r,e.platform);if(!o)throw new Error(`Could not find a ${e.platform} JS bundle in ${i}.`);let s=[];for(let f of r){let g=Se.relative(i,f).replace(/\\/g,"/");s.push({filePath:f,relative:g,uploaded:await qa({projectId:t,updateId:n,platform:e.platform,filePath:f,fileName:g,contentType:hm(f)})})}let l=s.find(f=>f.filePath===o),a=s.filter(f=>f.filePath!==o&&!f.relative.endsWith(".map")).map(f=>({key:f.relative,url:f.uploaded.url,contentType:f.uploaded.contentType,hash:f.uploaded.hash,size:f.uploaded.size})),d={id:n,createdAt:new Date().toISOString(),runtimeVersion:e.runtimeVersion,platform:e.platform,launchAsset:{key:Se.basename(l.relative),url:l.uploaded.url,contentType:l.uploaded.contentType,hash:l.uploaded.hash,size:l.uploaded.size},assets:a,metadata:{projectId:t,channel:e.channel,message:e.message||null,engine:e.engine},extra:{mach:{projectId:t,updateId:n,channel:e.channel,platform:e.platform}}},u=Se.join(i,"mach-manifest.json");le.writeFileSync(u,JSON.stringify(d,null,2));let c=await qa({projectId:t,updateId:n,platform:e.platform,filePath:u,fileName:"manifest.json",contentType:"application/json"}),p=await N.post("/ota/publish",{projectId:t,updateId:n,channelName:e.channel,runtimeVersion:e.runtimeVersion,platform:e.platform,manifestKey:c.key,message:e.message,launchAsset:d.launchAsset,assets:a});if(p.data.status!=="success")throw new Error(p.data.message||`Failed to publish ${e.platform} OTA update.`);return p.data.update}async function Em(e){let t=Ln(),n=He(e.framework)||Xr(t),i=Zr(e.engine||t.ota?.engine,n),r=!!e.yes,o=await Ya("OTA channel:",Rt(e.channel||e.branch||t.ota?.channel)||"production","production",!0,r),s=`${dt.replace(/\/$/,"")}/api/ota/${i==="expo-updates"?"expo":"react-native"}/${t.projectId}`,l=await Ya("Mach OTA update URL:",Rt(e.url||t.ota?.url)||s,s,!0,r);t.framework=n,t.ota={...t.ota||{},enabled:!0,engine:i,channel:o,url:l,deploymentUrl:l,statsUrl:`${dt.replace(/\/$/,"")}/api/ota/events`,runtimeVersionPolicy:t.ota?.runtimeVersionPolicy||"appVersion"},delete t.update,am(t);let a=[`${m.configFileName} updated.`];n==="expo"?a.push(...await fm(process.cwd(),e)):a.push("Vanilla React Native native OTA client setup is planned; this command wrote Mach config only for now."),nm(a.map(d=>`- ${d}`).join(`
1539
1539
  `),"OTA setup"),await rl({...e,action:"verify"})}async function Im(e){Kt();let t=Ln(),n=He(e.framework)||Xr(t),i=Zr(e.engine||t.ota?.engine,n),r=Rt(e.channel||e.branch||t.ota?.channel)||"production",o=lm(e.platform||"all"),s=rm();s.start(`Publishing OTA update (${o.join("+")}, ${r})`);try{let l=[];for(let a of o){let d=mm(t,e,a);s.message(`Exporting and uploading ${a} OTA bundle for runtime ${d}...`),l.push(await Am({config:t,engine:i,platform:a,channel:r,runtimeVersion:d,message:e.message}))}if(s.stop("OTA update published."),e.json)at.info(JSON.stringify({status:"success",updates:l},null,2));else{let a=Array.from(new Set(l.map(d=>d.runtimeVersion).filter(Boolean)));on(Qe.green(`\u2713 OTA update live on "${r}" for runtime ${a.join(", ")||"unknown"}.`));for(let d of l)at.info(Qe.dim(`${d.platform}: ${d.updateId}`))}}catch(l){s.stop("OTA publish failed."),at.error(l.response?.data?.message||l.message),process.exit(1)}}async function rl(e){let t=Ln(),n=He(e.framework)||Xr(t),i=Zr(e.engine||t.ota?.engine,n),r=[],o=t.ota;if(r.push(o?.enabled?{level:"pass",message:"mach.config.json has ota.enabled."}:{level:"fail",message:"mach.config.json is missing ota.enabled. Run `mach ota setup`."}),r.push(o?.url?{level:"pass",message:`OTA URL configured: ${o.url}`}:{level:"fail",message:"OTA URL is missing. Run `mach ota setup`."}),r.push(o?.channel?{level:"pass",message:`Default channel: ${o.channel}`}:{level:"warn",message:"No default OTA channel configured; publish will use production."}),r.push(o?.runtimeVersionPolicy||o?.runtimeVersion?{level:"pass",message:"Runtime version policy configured."}:{level:"warn",message:"No explicit runtime policy configured; Mach will use Expo runtimeVersion or package.json version."}),i==="expo-updates"){let l=Ii(Se.join(process.cwd(),"package.json"))||{},a={...l.dependencies||{},...l.devDependencies||{}};r.push(a["expo-updates"]?{level:"pass",message:"expo-updates is installed."}:{level:"warn",message:"Install expo-updates before making native builds that consume Mach OTA."}),r.push(Qr(process.cwd())?{level:"pass",message:`${m.npmScope}/mach is installed locally for the Expo plugin.`}:{level:"warn",message:`${m.npmScope}/mach is not installed locally; Expo may not resolve ${ke}.`});let d=sr(process.cwd());if(d){let u=Rt(d.updates?.url),c=Rt(o?.channel)||"production",p=Rt(d.updates?.requestHeaders?.["expo-channel-name"]);r.push(u===o?.url?{level:"pass",message:"Expo Updates URL resolves to Mach."}:{level:"warn",message:`Expo Updates URL resolves to ${u||"none"} instead of ${o?.url||"the Mach OTA URL"}.`}),r.push(p===c?{level:"pass",message:`Expo update channel header resolves to ${c}.`}:{level:"warn",message:`Expo update channel header is ${p||"not set"}; install the latest ${m.npmScope}/mach package and rebuild.`})}else r.push({level:"warn",message:"Could not resolve Expo config to confirm update URL/channel header."})}else r.push({level:"warn",message:"Vanilla React Native OTA native client is not fully automated yet. Publish can upload bundles, but apps need the Mach RN OTA client before consuming them."});for(let l of r){let a=l.level==="pass"?Qe.green("PASS"):l.level==="warn"?Qe.yellow("WARN"):Qe.red("FAIL");at.info(`${a} ${l.message}`)}let s=r.filter(l=>l.level==="fail").length;s>0&&(on(Qe.red(`OTA verification failed with ${s} issue(s).`)),process.exit(1)),on(Qe.green("OTA verification passed."))}async function wm(e){Kt();let t=Ln(),n=await N.get(`/ota/${t.projectId}/updates`),i=n.data.updates||[];if(e.json){at.info(JSON.stringify(n.data,null,2));return}if(i.length===0){on("No OTA updates found.");return}for(let r of i){let o=r.stats?.total||{};at.info(`${Qe.bold(r.updateId)} ${Qe.dim(`${r.platform} ${r.channelName} runtime ${r.runtimeVersion}`)} ${r.status||"active"}`),at.info(Qe.dim(` downloads ios=${o.iosDownloaded||0} android=${o.androidDownloaded||0} applied ios=${o.iosApplied||0} android=${o.androidApplied||0}`))}on(`Found ${i.length} OTA update(s).`)}async function Xa(e,t){Kt();let n=Ln(),i=Rt(t.updateId);i||(at.error(`Missing update id. Use \`${m.nameLower} ota ${e} --update-id <id>\`.`),process.exit(1));let r=await N.post(`/ota/${n.projectId}/updates/${encodeURIComponent(i)}/${e}`);t.json?at.info(JSON.stringify(r.data,null,2)):on(Qe.green(`\u2713 OTA update ${e==="rollback"?"rolled back":"promoted"}: ${i}`))}async function Pt(e,t={}){let n=e||t.action||"publish";if(n==="setup")return Em({...t,action:n});if(n==="publish")return Im({...t,action:n});if(n==="verify")return rl({...t,action:n});if(n==="list")return wm({...t,action:n});if(n==="rollback")return Xa("rollback",{...t,action:n});if(n==="promote")return Xa("promote",{...t,action:n});let i=await im({message:"What do you want to do?",options:[{value:"setup",label:"Setup OTA"},{value:"publish",label:"Publish OTA update"},{value:"verify",label:"Verify OTA setup"},{value:"list",label:"List OTA updates"}]});return Yr(i)&&qr(),Pt(i,t)}import{intro as _m,outro as ol,log as sn}from"@clack/prompts";import lt from"chalk";async function sl(){_m(lt.blue(`${m.name} CLI - User Profile`));let e=Ne();if(!e){sn.warn(lt.yellow("You are not logged in.")),sn.info(`Run \`${m.nameLower} login\` to authenticate.`),ol();return}sn.info(`${lt.bold("Logged in as:")} ${lt.green(e.email)}`);try{await N.get("/projects");let n=Ne().token.split(".");if(n.length===3){let i=JSON.parse(Buffer.from(n[1],"base64").toString());if(i.exp){let r=new Date(i.exp*1e3),o=new Date,s=r.getTime()-o.getTime();if(s>0){let l=Math.round(s/6e4),a=(l/60).toFixed(1);sn.info(`${lt.bold("Token status:")} Valid (Expires in ~${a}h / ${l}m)`)}else sn.warn(`${lt.bold("Token status:")} ${lt.red("Expired")} (Auto-refresh failed)`)}}}catch{sn.warn(`${lt.bold("Token status:")} ${lt.red("Unreachable")} (Session might be truly expired)${dt}`)}ol(lt.blue("---"))}import{spawn as Rm}from"child_process";import{log as Dt}from"@clack/prompts";import Ve from"chalk";import Pm from"fs";import $m from"net";async function vm(e){return new Promise(t=>{let n=$m.createServer();n.once("error",i=>{i.code==="EADDRINUSE"?t(!0):t(!1)}),n.once("listening",()=>{n.close(),t(!1)}),n.listen(e,"0.0.0.0")})}async function al(e,t=20){let n=e;for(;n<e+t;){if(!await vm(n))return n;n++}throw new Error(`Could not find an available port after ${t} attempts starting from ${e}.`)}var ll=async e=>{Dt.info(Ve.blue(`Starting ${m.name} Dev Orchestrator...`));let t=ve(),n=e.buildProfile||"development",i=t?xe(t,n):null,r={...process.env};if(t?.projectId)try{Dt.info(Ve.dim(`Fetching managed secrets for profile: ${n}...`));let c=await N.get(`/projects/${t.projectId}/secrets/export?env=${n}`);c.data?.status==="success"&&c.data.secrets&&(Object.assign(r,c.data.secrets),Dt.info(Ve.magenta(`\u2713 Injected secrets from ${m.name} Dashboard.`)))}catch{Dt.warn("Could not fetch managed secrets. Running with local env only.")}t&&Object.assign(r,Wt(t,m.envPrefix)),i&&(Object.assign(r,Wt(i,`${m.envPrefix}PROFILE_`)),i.env&&Object.assign(r,i.env));let o=!1;try{let c=JSON.parse(Pm.readFileSync("package.json","utf-8"));o=!!(c.dependencies?.expo||c.devDependencies?.expo)}catch{Dt.warn("Could not parse package.json. Defaulting to Bare React Native mode.")}let s=Number(e.port||i?.port||8081),l=await al(s);l!==s&&Dt.info(Ve.yellow(`Port ${s} is busy. ${m.name} is using ${l} instead.`));let a=process.platform==="win32"?"npx.cmd":"npx",d=[];if(o?(d=["expo","start","--port",String(l)],e.clear&&d.push("--clear"),e.tunnel&&d.push("--tunnel"),e.lan&&d.push("--lan"),e.localhost&&d.push("--localhost"),e.ios&&d.push("--ios"),e.android&&d.push("--android"),e.web&&d.push("--web")):(d=["react-native","start","--port",String(l)],e.clear&&d.push("--clear")),o){let c=[`${Ve.cyan("i")} open iOS simulator`,`${Ve.cyan("a")} open Android emulator/device`,`${Ve.cyan("w")} open web`,`${Ve.cyan("r")} reload app`];Dt.info([Ve.bold("Launch controls"),...c.map(p=>` ${p}`),"",Ve.dim("Direct launch: mach start --ios | --android | --web"),Ve.dim(`Metro URL: http://localhost:${l}`)].join(`
1540
1540
  `))}else Dt.info(Ve.dim(`Metro URL: http://localhost:${l}`));let u=Rm(a,d,{stdio:"inherit",env:r});return new Promise((c,p)=>{u.on("exit",f=>{f===0?c():p(new Error(`Dev server exited with code ${f}`))}),u.on("error",f=>{p(f)})})};import{log as Fe}from"@clack/prompts";import et from"chalk";var cl=async e=>{let t=ve();t||(Fe.error(et.red(`No ${m.configFileName} found in the current directory.`)),process.exit(1));let n=e.profile||"development",i=xe(t,n);if(e.json){console.log(JSON.stringify({project:t,resolved:i},null,2));return}Fe.info(et.bgBlue.white(` Resolved ${m.name} Config [${n}] `)),Fe.info(et.dim("----------------------------------------")),Fe.info(`${et.blue("Project ID:")} ${t.projectId}`),Fe.info(`${et.blue("Name:")} ${t.name}`),Fe.info(`${et.blue("Scheme:")} ${t.scheme}`),i?(Fe.info(et.dim(`
1541
1541
  Profile Settings:`)),Fe.info(`${et.cyan("Distribution:")} ${i.distribution||"none"}`),Fe.info(`${et.cyan("Development Client:")} ${i.developmentClient||"false"}`),i.env&&Object.keys(i.env).length>0&&(Fe.info(et.dim(`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@radhya/mach",
3
- "version": "2.0.36",
3
+ "version": "2.0.37",
4
4
  "description": "Mach CLI: Cloud Build Orchestrator for React Native & Expo",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",