diff --git a/.gitignore b/.gitignore index a511978cc..234bc651e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,10 @@ # See http://help.github.com/ignore-files/ for more about ignoring files. # compiled output -dist -tmp -/out-tsc -*.orig +# dist +# tmp +# /out-tsc +# *.orig # dependencies node_modules diff --git a/.npmrc.orig b/.npmrc.orig new file mode 100644 index 000000000..aee1af065 --- /dev/null +++ b/.npmrc.orig @@ -0,0 +1,4 @@ +link-workspace-packages=true +auto-install-peers=true +package-manager-strict=true +package-manager-strict-version=true diff --git a/package.json b/package.json index 246a15b67..44629474d 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,25 @@ "version": "0.0.0", "license": "MIT", "type": "module", + "bin": { + "rock": "./packages/cli/dist/src/bin.js" + }, + "files": [ + "packages/cli", + "packages/config", + "packages/tools", + "packages/platform-android", + "packages/platform-harmony", + "packages/platform-ios", + "packages/platform-apple-helpers", + "packages/plugin-metro", + "packages/plugin-repack", + "packages/plugin-brownfield-android", + "packages/plugin-brownfield-ios", + "packages/provider-github", + "packages/provider-s3", + "pnpm-workspace.yaml" + ], "scripts": { "build": "pnpm -r run build", "test": "vitest run", @@ -20,8 +39,14 @@ "verdaccio:publish": "node ./scripts/verdaccio-publish.mjs", "verdaccio:reset": "./scripts/verdaccio-reset.sh" }, - "private": true, "dependencies": { + "@react-native-community/cli-config": "^20.0.0", + "@rock-js/config": "^0.11.9", + "@rock-js/tools": "^0.11.9", + "adm-zip": "^0.5.16", + "commander": "^12.1.0", + "node-apk": "^1.2.1", + "tar": "^7.5.1", "tslib": "^2.8.1" }, "devDependencies": { diff --git a/packages/cli/dist/src/bin.d.ts b/packages/cli/dist/src/bin.d.ts new file mode 100644 index 000000000..b7988016d --- /dev/null +++ b/packages/cli/dist/src/bin.d.ts @@ -0,0 +1,2 @@ +#!/usr/bin/env node +export {}; diff --git a/packages/cli/dist/src/bin.js b/packages/cli/dist/src/bin.js new file mode 100755 index 000000000..41e37c09c --- /dev/null +++ b/packages/cli/dist/src/bin.js @@ -0,0 +1,7 @@ +#!/usr/bin/env node +import { cli } from './lib/cli.js'; +cli({ + argv: process.argv, + cwd: process.cwd(), +}); +//# sourceMappingURL=bin.js.map \ No newline at end of file diff --git a/packages/cli/dist/src/bin.js.map b/packages/cli/dist/src/bin.js.map new file mode 100644 index 000000000..90785c513 --- /dev/null +++ b/packages/cli/dist/src/bin.js.map @@ -0,0 +1 @@ +{"version":3,"file":"bin.js","sourceRoot":"","sources":["../../src/bin.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAEnC,GAAG,CAAC;IACF,IAAI,EAAE,OAAO,CAAC,IAAI;IAClB,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE;CACnB,CAAC,CAAC"} \ No newline at end of file diff --git a/packages/cli/dist/src/index.d.ts b/packages/cli/dist/src/index.d.ts new file mode 100644 index 000000000..78dea6bec --- /dev/null +++ b/packages/cli/dist/src/index.d.ts @@ -0,0 +1,2 @@ +export * from './lib/cli.js'; +export type { Config } from '@rock-js/config'; diff --git a/packages/cli/dist/src/index.js b/packages/cli/dist/src/index.js new file mode 100644 index 000000000..bfaed4f5f --- /dev/null +++ b/packages/cli/dist/src/index.js @@ -0,0 +1,2 @@ +export * from './lib/cli.js'; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/packages/cli/dist/src/index.js.map b/packages/cli/dist/src/index.js.map new file mode 100644 index 000000000..eef485fa0 --- /dev/null +++ b/packages/cli/dist/src/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC"} \ No newline at end of file diff --git a/packages/cli/dist/src/lib/adHocTemplates.d.ts b/packages/cli/dist/src/lib/adHocTemplates.d.ts new file mode 100644 index 000000000..ed87dc873 --- /dev/null +++ b/packages/cli/dist/src/lib/adHocTemplates.d.ts @@ -0,0 +1,18 @@ +export declare function templateIndexHtmlIOS({ appName, version, bundleIdentifier, }: { + appName: string; + version: string; + bundleIdentifier: string; +}): string; +export declare function templateManifestPlist({ baseUrl, ipaName, bundleIdentifier, version, appName, platformIdentifier, }: { + baseUrl: string; + ipaName: string; + bundleIdentifier: string; + version: string; + appName: string; + platformIdentifier: string; +}): string; +export declare function templateIndexHtmlAndroid({ appName, version, packageName, }: { + appName: string; + version: string; + packageName: string; +}): string; diff --git a/packages/cli/dist/src/lib/adHocTemplates.js b/packages/cli/dist/src/lib/adHocTemplates.js new file mode 100644 index 000000000..73d62f321 --- /dev/null +++ b/packages/cli/dist/src/lib/adHocTemplates.js @@ -0,0 +1,415 @@ +// Template functions for ad-hoc iOS and Android distribution +// Shared CSS styles for both iOS and Android templates +const sharedStyles = ` + :root { + /* Light mode variables */ + --bg-primary: #ffffff; + --bg-secondary: #f5f5f7; + --text-primary: #1d1d1f; + --text-secondary: #86868b; + --accent-primary: #8232ff; + --accent-hover: rgba(130, 50, 255, 0.3); + --border-color: #e5e5e7; + --shadow-color: rgba(0, 0, 0, 0.1); + } + + @media (prefers-color-scheme: dark) { + :root { + /* Dark mode variables */ + --bg-primary: #1c1c1e; + --bg-secondary: #2c2c2e; + --text-primary: #ffffff; + --text-secondary: #8e8e93; + --accent-primary: #8232ff; + --accent-hover: rgba(130, 50, 255, 0.4); + --border-color: #38383a; + --shadow-color: rgba(0, 0, 0, 0.3); + } + } + + * { + margin: 0; + padding: 0; + box-sizing: border-box; + } + + body { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, + Oxygen, Ubuntu, Cantarell, sans-serif; + min-height: 100vh; + display: flex; + align-items: center; + justify-content: center; + padding: 20px; + font-size: 16px; + background-color: var(--bg-primary); + color: var(--text-primary); + transition: background-color 0.3s ease, color 0.3s ease; + } + + .container { + text-align: center; + max-width: 500px; + width: 100%; + } + + .app-icon { + width: 100px; + height: 100px; + margin: 0 auto 15px; + display: flex; + align-items: center; + justify-content: center; + font-size: 48px; + color: var(--text-primary); + background: var(--bg-secondary); + border-radius: 25px; + transition: background-color 0.3s ease; + } + + h1 { + color: var(--text-primary); + font-size: 28px; + font-weight: 600; + margin-bottom: 15px; + overflow-wrap: break-word; + transition: color 0.3s ease; + } + + .subtitle { + color: var(--text-secondary); + font-size: 16px; + line-height: 1.5; + margin-bottom: 30px; + transition: color 0.3s ease; + } + + .version { + color: var(--text-primary); + font-size: 16px; + line-height: 1.5; + margin-bottom: 10px; + transition: color 0.3s ease; + } + + .download-button { + background: var(--accent-primary); + color: white; + border: none; + padding: 16px 32px; + border-radius: 4px; + font-size: 14px; + font-weight: 600; + cursor: pointer; + transition: all 0.3s ease; + text-decoration: none; + display: inline-block; + margin-bottom: 20px; + box-shadow: 0 4px 12px var(--shadow-color); + } + + .download-button:hover { + transform: translateY(-2px); + box-shadow: 0 8px 24px var(--accent-hover); + } + + .download-button:active { + transform: translateY(0); + } + + .instructions { + background: var(--bg-secondary); + border-radius: 4px; + padding: 20px; + margin-top: 20px; + text-align: left; + border: 1px solid var(--border-color); + transition: background-color 0.3s ease, border-color 0.3s ease; + } + + .instructions h3 { + color: var(--text-primary); + font-size: 16px; + margin-bottom: 10px; + transition: color 0.3s ease; + } + + .instructions ol { + color: var(--text-secondary); + font-size: 14px; + line-height: 1.6; + padding-left: 20px; + transition: color 0.3s ease; + } + + .instructions li { + margin-bottom: 8px; + } + + .adhoc-info { + text-align: left; + margin-top: 20px; + padding: 1em 2em; + border-left: 3px solid var(--accent-primary); + background: var(--bg-primary); + border-radius: 4px; + transition: background-color 0.3s ease; + } + + .adhoc-info-title { + font-weight: 600; + margin-bottom: 10px; + color: var(--text-primary); + transition: color 0.3s ease; + } + + .adhoc-info-text { + color: var(--text-primary); + margin: 0; + transition: color 0.3s ease; + } + + .footer { + text-align: center; + margin-top: 40px; + font-size: 12px; + color: var(--text-secondary); + transition: color 0.3s ease; + } + + .link { + color: var(--accent-primary); + text-decoration: none; + transition: color 0.3s ease; + } + + .link:hover { + text-decoration: underline; + } + + .toast { + padding: 1em 3em; + font-size: 14px; + border: 1px solid var(--accent-primary); + color: var(--text-primary); + position: fixed; + bottom: 1em; + left: 50%; + transform: translateX(-50%); + max-width: 500px; + width: calc(100% - 2em); + text-align: left; + border-radius: 4px; + background-color: var(--bg-primary); + display: none; + box-shadow: 0 8px 24px var(--shadow-color); + transition: background-color 0.3s ease, border-color 0.3s ease, color 0.3s ease; + } + + .toast-visible { + display: block; + animation: slideUp 0.3s ease; + } + + @keyframes slideUp { + from { + opacity: 0; + transform: translateX(-50%) translateY(20px); + } + to { + opacity: 1; + transform: translateX(-50%) translateY(0); + } + } + + .toast-icon { + font-size: 1em; + position: absolute; + left: 1em; + top: 50%; + transform: translateY(-50%); + } + + .toast-close { + font-size: 1em; + padding: 0.5em; + cursor: pointer; + position: absolute; + right: 1em; + top: 50%; + transform: translateY(-50%); + color: var(--text-secondary); + transition: color 0.3s ease; + } + + .toast-close:hover { + color: var(--text-primary); + } + + /* Smooth transitions for all elements */ + * { + transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease; + } +`; +// Shared footer HTML +const sharedFooter = ` +
+`; +// Shared toast functions for both iOS and Android templates +const sharedToastFunctions = () => ` + function showToast() { + setTimeout(() => { + const toast = document.getElementById('home-screen-toast'); + toast.classList.add('toast-visible'); + }, 2000); + } + + function hideToast() { + const toast = document.getElementById('home-screen-toast'); + toast.classList.remove('toast-visible'); + } +`; +// Base template function for creating ad-hoc distribution pages +function createAdHocTemplate({ platform, appName, version, identifier, icon, buttonText, toastMessage, script, instructions, adhocDescription, }) { + return ` + + + + +${toastMessage}
+ โ +${identifier} (${version})
++ Download and install the latest version of our ${platform} app directly to your + device. +
+ + + ${buttonText} + + + + +Ad-hoc Distribution
+
+ ${adhocDescription}
+
+ Learn more at Rock Ad-hoc documentation.
+
Check Home Screen to see installation progress
- โ -${bundleIdentifier} (${version})
-- Download and install the latest version of our iOS app directly to your - device. + +
+ + +${toastMessage}
+ โ +${identifier} (${version})
++ Download and install the latest version of our ${platform} app directly to your + device. +
+ + + ${buttonText} + + + + +Ad-hoc Distribution
+
+ ${adhocDescription}
+
+ Learn more at Rock Ad-hoc documentation.
Ad-hoc Distribution
-
- This app is distributed via ad-hoc distribution for testing purposes.
- Your device must either be enrolled in enterprise distribution or have its UDID added to the app's provisioning profile.
-
- Learn more at Rock Ad-hoc documentation.
-
\\d+)m|\\${ef}(?.*)\x07)`).exec(a.slice(e).join(""))||{groups:{}};if(void 0!==t.code){let e=Number.parseFloat(t.code);n=39===e?void 0:e}else void 0!==t.uri&&(s=0===t.uri.length?void 0:t.uri)}let i=ed.codes.get(Number(n));a[e+1]===`
+`?(s&&(r+=em("")),n&&i&&(r+=ep(i))):t===`
+`&&(n&&i&&(r+=ep(n)),s&&(r+=em(s)))}return r})(e,t,i)).join(`
+`)}let eb={actions:new Set(["up","down","left","right","space","enter","cancel"]),aliases:new Map([["k","up"],["j","down"],["h","left"],["l","right"],["\x03","cancel"],["escape","cancel"]])};function ey(e,t){if("string"==typeof e)return eb.aliases.get(e)===t;for(let i of e)if(void 0!==i&&ey(i,t))return!0;return!1}let eF=globalThis.process.platform.startsWith("win"),eC=Symbol("clack:cancel");function ev(e,t){e.isTTY&&e.setRawMode(t)}var ew=Object.defineProperty,e_=(e,t,i)=>{let r;return(r="symbol"!=typeof t?t+"":t)in e?ew(e,r,{enumerable:!0,configurable:!0,writable:!0,value:i}):e[r]=i,i};class eS{constructor(e,t=!0){e_(this,"input"),e_(this,"output"),e_(this,"_abortSignal"),e_(this,"rl"),e_(this,"opts"),e_(this,"_render"),e_(this,"_track",!1),e_(this,"_prevFrame",""),e_(this,"_subscribers",new Map),e_(this,"_cursor",0),e_(this,"state","initial"),e_(this,"error",""),e_(this,"value");let{input:i=b,output:r=y,render:n,signal:s,...o}=e;this.opts=o,this.onKeypress=this.onKeypress.bind(this),this.close=this.close.bind(this),this.render=this.render.bind(this),this._render=n.bind(this),this._track=t,this._abortSignal=s,this.input=i,this.output=r}unsubscribe(){this._subscribers.clear()}setSubscriber(e,t){let i=this._subscribers.get(e)??[];i.push(t),this._subscribers.set(e,i)}on(e,t){this.setSubscriber(e,{cb:t})}once(e,t){this.setSubscriber(e,{cb:t,once:!0})}emit(e,...t){let i=this._subscribers.get(e)??[],r=[];for(let e of i)e.cb(...t),e.once&&r.push(()=>i.splice(i.indexOf(e),1));for(let e of r)e()}prompt(){return new Promise((e,t)=>{if(this._abortSignal){if(this._abortSignal.aborted)return this.state="cancel",this.close(),e(eC);this._abortSignal.addEventListener("abort",()=>{this.state="cancel",this.close()},{once:!0})}let i=new A;i._write=(e,t,i)=>{this._track&&(this.value=this.rl?.line.replace(/\t/g,""),this._cursor=this.rl?.cursor??0,this.emit("value",this.value)),i()},this.input.pipe(i),this.rl=F.createInterface({input:this.input,output:i,tabSize:2,prompt:"",escapeCodeTimeout:50,terminal:!0}),F.emitKeypressEvents(this.input,this.rl),this.rl.prompt(),void 0!==this.opts.initialValue&&this._track&&this.rl.write(this.opts.initialValue),this.input.on("keypress",this.onKeypress),ev(this.input,!0),this.output.on("resize",this.render),this.render(),this.once("submit",()=>{this.output.write(K.cursor.show),this.output.off("resize",this.render),ev(this.input,!1),e(this.value)}),this.once("cancel",()=>{this.output.write(K.cursor.show),this.output.off("resize",this.render),ev(this.input,!1),e(eC)})})}onKeypress(e,t){if("error"===this.state&&(this.state="active"),t?.name&&(!this._track&&eb.aliases.has(t.name)&&this.emit("cursor",eb.aliases.get(t.name)),eb.actions.has(t.name)&&this.emit("cursor",t.name)),e&&("y"===e.toLowerCase()||"n"===e.toLowerCase())&&this.emit("confirm","y"===e.toLowerCase())," "===e&&this.opts.placeholder&&(this.value||(this.rl?.write(this.opts.placeholder),this.emit("value",this.opts.placeholder))),e&&this.emit("key",e.toLowerCase()),t?.name==="return"){if(this.opts.validate){let e=this.opts.validate(this.value);e&&(this.error=e instanceof Error?e.message:e,this.state="error",this.rl?.write(this.value))}"error"!==this.state&&(this.state="submit")}ey([e,t?.name,t?.sequence],"cancel")&&(this.state="cancel"),("submit"===this.state||"cancel"===this.state)&&this.emit("finalize"),this.render(),("submit"===this.state||"cancel"===this.state)&&this.close()}close(){this.input.unpipe(),this.input.removeListener("keypress",this.onKeypress),this.output.write(`
+`),ev(this.input,!1),this.rl?.close(),this.rl=void 0,this.emit(`${this.state}`,this.value),this.unsubscribe()}restoreCursor(){let e=eE(this._prevFrame,process.stdout.columns,{hard:!0}).split(`
+`).length-1;this.output.write(K.cursor.move(-999,-1*e))}render(){let e=eE(this._render(this)??"",process.stdout.columns,{hard:!0});if(e!==this._prevFrame){if("initial"===this.state)this.output.write(K.cursor.hide);else{let t=function(e,t){if(e===t)return;let i=e.split(`
+`),r=t.split(`
+`),n=[];for(let e=0;e1){let i=t[0];this.output.write(K.cursor.move(0,i)),this.output.write(K.erase.down());let r=e.split(`
+`).slice(i);this.output.write(r.join(`
+`)),this._prevFrame=e;return}this.output.write(K.erase.down())}this.output.write(e),"initial"===this.state&&(this.state="active"),this._prevFrame=e}}}new WeakMap;var eA=Object.defineProperty,eR=(e,t,i)=>{let r;return(r="symbol"!=typeof t?t+"":t)in e?eA(e,r,{enumerable:!0,configurable:!0,writable:!0,value:i}):e[r]=i,i};let eO=class extends eS{constructor(e){super(e,!1),eR(this,"options"),eR(this,"cursor",0),this.options=e.options,this.value=[...e.initialValues??[]],this.cursor=Math.max(this.options.findIndex(({value:t})=>t===e.cursorAt),0),this.on("key",e=>{"a"===e&&this.toggleAll()}),this.on("cursor",e=>{switch(e){case"left":case"up":this.cursor=0===this.cursor?this.options.length-1:this.cursor-1;break;case"down":case"right":this.cursor=this.cursor===this.options.length-1?0:this.cursor+1;break;case"space":this.toggleValue()}})}get _value(){return this.options[this.cursor].value}toggleAll(){let e=this.value.length===this.options.length;this.value=e?[]:this.options.map(e=>e.value)}toggleValue(){let e=this.value.includes(this._value);this.value=e?this.value.filter(e=>e!==this._value):[...this.value,this._value]}};var eB=Object.defineProperty,ex=(e,t,i)=>{let r;return(r="symbol"!=typeof t?t+"":t)in e?eB(e,r,{enumerable:!0,configurable:!0,writable:!0,value:i}):e[r]=i,i};class eN extends eS{constructor(e){super(e,!1),ex(this,"options"),ex(this,"cursor",0),this.options=e.options,this.cursor=this.options.findIndex(({value:t})=>t===e.initialValue),-1===this.cursor&&(this.cursor=0),this.changeValue(),this.on("cursor",e=>{switch(e){case"left":case"up":this.cursor=0===this.cursor?this.options.length-1:this.cursor-1;break;case"down":case"right":this.cursor=this.cursor===this.options.length-1?0:this.cursor+1}this.changeValue()})}get _value(){return this.options[this.cursor]}changeValue(){this.value=this._value.value}}class eI extends eS{get valueWithCursor(){if("submit"===this.state)return this.value;if(this.cursor>=this.value.length)return`${this.value}\u2588`;let e=this.value.slice(0,this.cursor),[t,...i]=this.value.slice(this.cursor);return`${e}${q.inverse(t)}${i.join("")}`}get cursor(){return this._cursor}constructor(e){super(e),this.on("finalize",()=>{this.value||(this.value=e.defaultValue)})}}let eT="win32"!==E.platform?"linux"!==E.env.TERM:!!E.env.CI||!!E.env.WT_SESSION||!!E.env.TERMINUS_SUBLIME||"{cmd::Cmder}"===E.env.ConEmuTask||"Terminus-Sublime"===E.env.TERM_PROGRAM||"vscode"===E.env.TERM_PROGRAM||"xterm-256color"===E.env.TERM||"alacritty"===E.env.TERM||"JetBrains-JediTerm"===E.env.TERMINAL_EMULATOR,eL=(e,t)=>eT?e:t,ek=eL("โ","*"),eM=eL("โ ","x"),e$=eL("โฒ","x"),ej=eL("โ","o"),eP=eL("โ","T"),ez=eL("โ","|"),eU=eL("โ","โ"),eH=eL("โ",">"),eG=eL("โ"," "),eZ=eL("โป","[โข]"),eW=eL("โผ","[+]"),eV=eL("โป","[ ]"),eY=(eL("โช","โข"),eL("โ","-")),eX=eL("โฎ","+"),eK=eL("โ","+"),eq=eL("โฏ","+"),eJ=eL("โ","โข"),eQ=eL("โ","*"),e0=eL("โฒ","!"),e1=eL("โ ","x"),e2=e=>{switch(e){case"initial":case"active":return q.cyan(ek);case"cancel":return q.red(eM);case"error":return q.yellow(e$);case"submit":return q.green(ej)}},e3=e=>{let{cursor:t,options:i,style:r}=e,n=e.maxItems??1/0,s=Math.min(Math.max(process.stdout.rows-4,0),Math.max(n,5)),o=0;t>=0+s-3?o=Math.max(Math.min(t-s+3,i.length-s),0):t0,a=s{let s=i===n.length-1&&a;return 0===i&&u||s?q.dim("..."):r(e,i+o===t)})},e8=e=>{let t=(e,t)=>{let i=e.label??String(e.value);switch(t){case"selected":return`${q.dim(i)}`;case"active":return`${q.green(eH)} ${i} ${e.hint?q.dim(`(${e.hint})`):""}`;case"cancelled":return`${q.strikethrough(q.dim(i))}`;default:return`${q.dim(eG)} ${q.dim(i)}`}};return new eN({options:e.options,initialValue:e.initialValue,render(){let i=`${q.gray(ez)}
+${e2(this.state)} ${e.message}
+`;switch(this.state){case"submit":return`${i}${q.gray(ez)} ${t(this.options[this.cursor],"selected")}`;case"cancel":return`${i}${q.gray(ez)} ${t(this.options[this.cursor],"cancelled")}
+${q.gray(ez)}`;default:return`${i}${q.cyan(ez)} ${e3({cursor:this.cursor,options:this.options,maxItems:e.maxItems,style:(e,i)=>t(e,i?"active":"inactive")}).join(`
+${q.cyan(ez)} `)}
+${q.cyan(eU)}
+`}}}).prompt()},e6={message:(e="",{symbol:t=q.gray(ez)}={})=>{let i=[`${q.gray(ez)}`];if(e){let[r,...n]=e.split(`
+`);i.push(`${t} ${r}`,...n.map(e=>`${q.gray(ez)} ${e}`))}process.stdout.write(`${i.join(`
+`)}
+`)},info:e=>{e6.message(e,{symbol:q.blue(eJ)})},success:e=>{e6.message(e,{symbol:q.green(eQ)})},step:e=>{e6.message(e,{symbol:q.green(ej)})},warn:e=>{e6.message(e,{symbol:q.yellow(e0)})},warning:e=>{e6.warn(e)},error:e=>{e6.message(e,{symbol:q.red(e1)})}},e5=(q.gray(ez),async(e,t)=>{let i={};for(let r of Object.keys(e)){let n=e[r],s=await n({results:i})?.catch(e=>{throw e});if("function"==typeof t?.onCancel&&s===eC){i[r]="canceled",t.onCancel({results:i});continue}i[r]=s}return i});function e4({stream:e=process.stdout}={}){return!!(e&&e.isTTY&&"dumb"!==process.env.TERM&&!("CI"in process.env))}class e9 extends Error{constructor(e,{cause:t}={}){super(e,{cause:t}),this.name=this.constructor.name,Error.captureStackTrace(this,this.constructor)}}let e7=function(){let{env:e}=E,{TERM:t,TERM_PROGRAM:i}=e;return"win32"!==E.platform?"linux"!==t:!!e.WT_SESSION||!!e.TERMINUS_SUBLIME||"{cmd::Cmder}"===e.ConEmuTask||"Terminus-Sublime"===i||"vscode"===i||"xterm-256color"===t||"alacritty"===t||"rxvt-unicode"===t||"rxvt-unicode-256color"===t||"JetBrains-JediTerm"===e.TERMINAL_EMULATOR}()?"โ":"โข",te={info:(...e)=>{let t=m.format(...e);e6.info(t)},warn:(...e)=>{let t=m.format(...e);e6.warn(tt(t,J().yellow))},error:(...e)=>{let t=m.format(...e);e6.error(tt(t,J().red))},debug:(...e)=>{0},log:(...e)=>{let t=m.format(...e);e6.step(t)},isVerbose:()=>!e4()};function tt(e,t){return e.split("\n").map(t).join("\n")}function ti(e){return((e="")=>{process.stdout.write(`${q.gray(ez)}
+${q.gray(eU)} ${e}
+
+`)})(e)}function tr(e,t){return((e="",t="")=>{let i=`
+${e}
+`.split(`
+`),r=g(t).length,n=Math.max(i.reduce((e,t)=>{let i=g(t);return i.length>e?i.length:e},0),r)+2,s=i.map(e=>`${q.gray(ez)} ${q.dim(e)}${" ".repeat(n-g(e).length)}${q.gray(ez)}`).join(`
+`);process.stdout.write(`${q.gray(ez)}
+${q.green(ej)} ${q.reset(t)} ${q.gray(eY.repeat(Math.max(n-r-1,1))+eX)}
+${s}
+${q.gray(eK+eY.repeat(n+2)+eq)}
+`)})(e,t)}async function tn(e){let t=await new eI({validate:e.validate,placeholder:e.placeholder,defaultValue:e.defaultValue,initialValue:e.initialValue,render(){let t=`${q.gray(ez)}
+${e2(this.state)} ${e.message}
+`,i=e.placeholder?q.inverse(e.placeholder[0])+q.dim(e.placeholder.slice(1)):q.inverse(q.hidden("_")),r=this.value?this.valueWithCursor:i;switch(this.state){case"error":return`${t.trim()}
+${q.yellow(ez)} ${r}
+${q.yellow(eU)} ${q.yellow(this.error)}
+`;case"submit":return`${t}${q.gray(ez)} ${q.dim(this.value||e.placeholder)}`;case"cancel":return`${t}${q.gray(ez)} ${q.strikethrough(q.dim(this.value??""))}${this.value?.trim()?`
+${q.gray(ez)}`:""}`;default:return`${t}${q.cyan(ez)} ${r}
+${q.cyan(eU)}
+`}}}).prompt();return t===eC&&tc(),t}async function ts(e){if(1===e.options.length)return e.options[0].value;let t=await e8(e);return t===eC&&tc(),t}async function to(e){let t=await e8({message:e.message,options:[{value:!0,label:e.confirmLabel??"Confirm"},{value:!1,label:e.cancelLabel??"Cancel"}]});return t===eC&&tc(),!0===t}async function tu(e){let t=await (e=>{let t=(e,t)=>{let i=e.label??String(e.value);return"active"===t?`${q.cyan(eZ)} ${i} ${e.hint?q.dim(`(${e.hint})`):""}`:"selected"===t?`${q.green(eW)} ${q.dim(i)} ${e.hint?q.dim(`(${e.hint})`):""}`:"cancelled"===t?`${q.strikethrough(q.dim(i))}`:"active-selected"===t?`${q.green(eW)} ${i} ${e.hint?q.dim(`(${e.hint})`):""}`:"submitted"===t?`${q.dim(i)}`:`${q.dim(eV)} ${q.dim(i)}`};return new eO({options:e.options,initialValues:e.initialValues,required:e.required??!0,cursorAt:e.cursorAt,validate(e){if(this.required&&0===e.length)return`Please select at least one option.
+${q.reset(q.dim(`Press ${q.gray(q.bgWhite(q.inverse(" space ")))} to select, ${q.gray(q.bgWhite(q.inverse(" enter ")))} to submit`))}`},render(){let i=`${q.gray(ez)}
+${e2(this.state)} ${e.message}
+`,r=(e,i)=>{let r=this.value.includes(e.value);return i&&r?t(e,"active-selected"):r?t(e,"selected"):t(e,i?"active":"inactive")};switch(this.state){case"submit":return`${i}${q.gray(ez)} ${this.options.filter(({value:e})=>this.value.includes(e)).map(e=>t(e,"submitted")).join(q.dim(", "))||q.dim("none")}`;case"cancel":{let e=this.options.filter(({value:e})=>this.value.includes(e)).map(e=>t(e,"cancelled")).join(q.dim(", "));return`${i}${q.gray(ez)} ${e.trim()?`${e}
+${q.gray(ez)}`:""}`}case"error":{let t=this.error.split(`
+`).map((e,t)=>0===t?`${q.yellow(eU)} ${q.yellow(e)}`:` ${e}`).join(`
+`);return`${i+q.yellow(ez)} ${e3({options:this.options,cursor:this.cursor,maxItems:e.maxItems,style:r}).join(`
+${q.yellow(ez)} `)}
+${t}
+`}default:return`${i}${q.cyan(ez)} ${e3({options:this.options,cursor:this.cursor,maxItems:e.maxItems,style:r}).join(`
+${q.cyan(ez)} `)}
+${q.cyan(eU)}
+`}}}).prompt()})(e);return t===eC&&tc(),t}async function ta(e,t){let i=await e5(e,t);return i===eC&&tc(),i}function tl(e){if(null==e?void 0:e.silent)return{start:()=>{},stop:()=>{},message:()=>{}};if(te.isVerbose()||!e4())return{start:e=>te.log(th(e)),stop:(e,t=0)=>0===t?te.log(e):te.error(e),message:e=>te.log(th(e))};let t=(({indicator:e="dots"}={})=>{let t=eT?["โ","โ","โ","โ"]:["โข","o","O","0"],i=eT?80:120,r="true"===process.env.CI,n,s,o=!1,u="",a,l=performance.now(),h=e=>{o&&m(e>1?"Something went wrong":"Canceled",e)},c=()=>h(2),d=()=>h(1),D=()=>{if(void 0===a)return;r&&process.stdout.write(`
+`);let e=a.split(`
+`);process.stdout.write(K.cursor.move(-999,e.length-1)),process.stdout.write(K.erase.down(e.length))},f=e=>e.replace(/\.+$/,""),p=e=>{let t=(performance.now()-e)/1e3,i=Math.floor(t/60),r=Math.floor(t%60);return i>0?`[${i}m ${r}s]`:`[${r}s]`},m=(t="",i=0)=>{o=!1,clearInterval(s),D();let r=0===i?q.green(ej):1===i?q.red(eM):q.red(e$);u=f(t??u),"timer"===e?process.stdout.write(`${r} ${u} ${p(l)}
+`):process.stdout.write(`${r} ${u}
+`),process.removeListener("uncaughtExceptionMonitor",c),process.removeListener("unhandledRejection",c),process.removeListener("SIGINT",d),process.removeListener("SIGTERM",d),process.removeListener("exit",h),n()};return{start:(m="")=>{o=!0,n=function({input:e=b,output:t=y,overwrite:i=!0,hideCursor:r=!0}={}){let n=v({input:e,output:t,prompt:"",tabSize:1});w(e,n),e.isTTY&&e.setRawMode(!0);let s=(n,{name:o,sequence:u})=>{if(ey([String(n),o,u],"cancel")){r&&t.write(K.cursor.show),process.exit(0);return}i&&_(t,"return"===o?0:-1,"return"===o?-1:0,()=>{C(t,1,()=>{e.once("keypress",s)})})};return r&&t.write(K.cursor.hide),e.once("keypress",s),()=>{e.off("keypress",s),r&&t.write(K.cursor.show),e.isTTY&&!eF&&e.setRawMode(!1),n.terminal=!1,n.close()}}(),u=f(m),l=performance.now(),process.stdout.write(`${q.gray(ez)}
+`);let g=0,E=0;process.on("uncaughtExceptionMonitor",c),process.on("unhandledRejection",c),process.on("SIGINT",d),process.on("SIGTERM",d),process.on("exit",h),s=setInterval(()=>{if(r&&u===a)return;D(),a=u;let i=q.magenta(t[g]);if(r)process.stdout.write(`${i} ${u}...`);else if("timer"===e)process.stdout.write(`${i} ${u} ${p(l)}`);else{let e=".".repeat(Math.floor(E)).slice(0,3);process.stdout.write(`${i} ${u}${e}`)}g=g+1{u=f(e??u)}}})(e);return{start:e=>{t.start(e)},stop:(e,i)=>{t.stop(e,i)},message:e=>{t.message(e)}}}function th(e){if(void 0===e)return;let t=e.replace(/\.+$/,"");return`${t}...`}function tc(e){((e="")=>{process.stdout.write(`${q.gray(eU)} ${q.red(e)}
+
+`)})(e??"Operation cancelled by user."),process.exit(0)}Y("crypto");var td=Y("path"),tD=Y("fs");let tf=(e,t)=>e.at(-1)===t?e:tf([...e,t],u.resolve(t,"..")),tp=async(e,t,i)=>await tm(e,i)?[tC(e),t.map(e=>tF(e)),{...i,shell:!0}]:[e,t,i],tm=async(e,{shell:t,cwd:i,env:r=E.env})=>"win32"===E.platform&&!t&&!await tg(e,i,r),tg=async(e,t,{Path:i="",PATH:r=i})=>ty.some(t=>e.toLowerCase().endsWith(t))||(tE[`${e}\0${t}\0${r}`]??=await tb(e,t,r)),tE={},tb=async(e,t,i)=>{let r=i.split(u.delimiter).filter(Boolean).map(e=>e.replace(/^"(.*)"$/,"$1"));try{await Promise.all(ty.flatMap(i=>[t,...r].map(t=>`${u.resolve(t,e)}${i}`)).map(async e=>{try{await O(e)}catch{return}throw 0}))}catch{return!0}return!1},ty=[".exe",".com"],tF=e=>tC(tC(`"${e.replaceAll(/(\\*)"/g,'$1$1\\"').replace(/(\\*)$/,"$1$1")}"`)),tC=e=>e.replaceAll(/([()\][%!^"`<>&|;, *?])/g,"^$1"),tv=async(e,{input:t},i)=>{let r=await e;void 0!==t&&r.stdin.end(t);let n=T(r,"close");try{return await Promise.race([n,...r.stdio.filter(Boolean).map(e=>tw(e))]),t_(i,tO(r)),tB(i)}catch(e){throw await Promise.allSettled([n]),tS(e,r,i)}},tw=async e=>{for await(let[t]of I(e,"error"))if(!["ERR_STREAM_PREMATURE_CLOSE","EPIPE"].includes(t?.code))throw t},t_=({command:e},{exitCode:t,signalName:i})=>{if(void 0!==i)throw new tR(`Command was terminated with ${i}: ${e}`);if(void 0!==t)throw new tR(`Command failed with exit code ${t}: ${e}`)},tS=(e,t,i)=>Object.assign(tA(e,i),tO(t),tB(i)),tA=(e,{command:t})=>e instanceof tR?e:new tR(`Command failed: ${t}`,{cause:e});class tR extends Error{name="SubprocessError"}let tO=({exitCode:e,signalCode:t})=>({...e<1?{}:{exitCode:e},...null===t?{}:{signalName:t}}),tB=({state:{stdout:e,stderr:t,output:i},command:r,start:n})=>({stdout:tx(e),stderr:tx(t),output:tx(i),command:r,durationMs:Number(E.hrtime.bigint()-n)/1e6}),tx=e=>"\n"===e.at(-1)?e.slice(0,"\r"===e.at(-2)?-2:-1):e,tN=async(e,t,i,r)=>{try{[e,t]=["node","node.exe"].includes(e.toLowerCase())?[E.execPath,[...E.execArgv.filter(e=>!e.startsWith("--inspect")),...t]]:[e,t],[e,t,i]=await tp(e,t,i),[e,t,i]=tI(e,t,i);let n=x(e,t,i);return tT(n.stdout,r,"stdout"),tT(n.stderr,r,"stderr"),n.once("error",()=>{}),await T(n,"spawn"),n}catch(e){throw tS(e,{},r)}},tI=(e,t,i)=>i.shell&&t.length>0?[[e,...t].join(" "),[],i]:[e,t,i],tT=(e,{state:t},i)=>{e&&(e.setEncoding("utf8"),t.isIterating||(t.isIterating=!1,e.on("data",e=>{t[i]+=e,t.output+=e})))},tL=async e=>{let[[t,i]]=await Promise.all([Promise.allSettled(e),tk(e)]);if(i.reason)throw i.reason.pipedFrom=t.reason??t.value,i.reason;if(t.reason)throw t.reason;return{...i.value,pipedFrom:t.value}},tk=async e=>{try{let[{stdout:t},{stdin:i}]=await Promise.all(e.map(({nodeChildProcess:e})=>e));if(null===i)throw Error('The "stdin" option must be set on the first "spawn()" call in the pipeline.');if(null===t)throw Error('The "stdout" option must be set on the last "spawn()" call in the pipeline.');L(t,i).catch(()=>{})}catch(t){throw await Promise.allSettled(e.map(({nodeChildProcess:e})=>tM(e))),t}},tM=async e=>{let{stdin:t}=await e;t.end()},t$=async function*(e,{state:t},i){if(!1===t.isIterating)throw Error(`The subprocess must be iterated right away, for example:
+ for await (const line of spawn(...)) { ... }`);t.isIterating=!0;try{let{[i]:t}=await e.nodeChildProcess;if(!t)return;let r="";for await(let e of t.iterator({destroyOnReturn:!1})){let t=`${r}${e}`.split(/\r?\n/);r=t.pop(),yield*t}r&&(yield r)}finally{await e}},tj=async function*(...e){try{let t=[];for(;e.length>0;){t=e.map((e,i)=>t[i]??tP(e));let[{value:i,done:r},n]=await Promise.race(t.map((e,t)=>Promise.all([e,t]))),[s]=e.splice(n,1);t.splice(n,1),r||(e.push(s),yield i)}}finally{await Promise.all(e.map(e=>e.return()))}},tP=async e=>{try{return await e.next()}catch(t){await e.throw(t)}};function tz(e,t,i){let r=te.isVerbose()?"inherit":"pipe";te.debug(`Running: ${e}`,...t??[]);let n=function e(t,i,r,n){let s,[o=[],a={}]=Array.isArray(i)?[i,r]:[[],i],l=(s=[t,...o],{start:E.hrtime.bigint(),command:s.map(e=>{let t;return t=g(e),/[^\w./-]/.test(t)?`'${t.replaceAll("'","'\\''")}'`:t}).join(" "),state:{stdout:"",stderr:"",output:""}}),h=(({stdin:e,stdout:t,stderr:i,stdio:r=[e,t,i],env:n,preferLocal:s,cwd:o=".",...a})=>{let l=o instanceof URL?B(o):u.resolve(o),h=n?{...E.env,...n}:void 0,c=r[0]?.string;return{...a,input:c,stdio:void 0===c?r:["pipe",...r.slice(1)],env:s?(({Path:e="",PATH:t=e,...i},r)=>{let n=t.split(u.delimiter),s=tf([],u.resolve(r)).map(e=>u.join(e,"node_modules/.bin")).filter(e=>!n.includes(e));return{...i,PATH:[...s,t].filter(Boolean).join(u.delimiter)}})(h??E.env,l):h,cwd:l}})(a),c=tN(t,o,h,l),d=tv(c,h,l);Object.assign(d,{nodeChildProcess:c});let D=t$(d=n?tL([n,d]):d,l,"stdout"),f=t$(d,l,"stderr");return Object.assign(d,{nodeChildProcess:c,stdout:D,stderr:f,[Symbol.asyncIterator]:()=>tj(D,f),pipe:(t,i,r)=>e(t,i,r,d)})}(e,t,{stdin:r,stdout:r,stderr:"pipe",...i});return function(e){process.stdin.isTTY&&process.stdin.setRawMode(!1);let t=async()=>{try{(await e.nodeChildProcess).kill(),process.exit(1)}catch{}},i=()=>t(),r=()=>t();process.on("SIGINT",i),process.on("SIGTERM",r),e.nodeChildProcess.finally(()=>{process.off("SIGINT",i),process.off("SIGTERM",r)})}(n),n}function tU(e){return c(e)?e:d(process.cwd(),e)}Y("../../node_modules/.pnpm/adm-zip@0.5.16/node_modules/adm-zip/adm-zip.js");let tH="object"==typeof process&&process?process:{stdout:null,stderr:null},tG=e=>!!e&&"object"==typeof e&&(e instanceof iy||e instanceof S||tZ(e)||tW(e)),tZ=e=>!!e&&"object"==typeof e&&e instanceof N&&"function"==typeof e.pipe&&e.pipe!==S.Writable.prototype.pipe,tW=e=>!!e&&"object"==typeof e&&e instanceof N&&"function"==typeof e.write&&"function"==typeof e.end,tV=Symbol("EOF"),tY=Symbol("maybeEmitEnd"),tX=Symbol("emittedEnd"),tK=Symbol("emittingEnd"),tq=Symbol("emittedError"),tJ=Symbol("closed"),tQ=Symbol("read"),t0=Symbol("flush"),t1=Symbol("flushChunk"),t2=Symbol("encoding"),t3=Symbol("decoder"),t8=Symbol("flowing"),t6=Symbol("paused"),t5=Symbol("resume"),t4=Symbol("buffer"),t9=Symbol("pipes"),t7=Symbol("bufferLength"),ie=Symbol("bufferPush"),it=Symbol("bufferShift"),ii=Symbol("objectMode"),ir=Symbol("destroyed"),is=Symbol("error"),io=Symbol("emitData"),iu=Symbol("emitEnd"),ia=Symbol("emitEnd2"),il=Symbol("async"),ih=Symbol("abort"),ic=Symbol("aborted"),id=Symbol("signal"),iD=Symbol("dataListeners"),ip=Symbol("discarded"),im=e=>Promise.resolve().then(e),ig=e=>e();class iE{src;dest;opts;ondrain;constructor(e,t,i){this.src=e,this.dest=t,this.opts=i,this.ondrain=()=>e[t5](),this.dest.on("drain",this.ondrain)}unpipe(){this.dest.removeListener("drain",this.ondrain)}proxyErrors(e){}end(){this.unpipe(),this.opts.end&&this.dest.end()}}class ib extends iE{unpipe(){this.src.removeListener("error",this.proxyErrors),super.unpipe()}constructor(e,t,i){super(e,t,i),this.proxyErrors=e=>t.emit("error",e),e.on("error",this.proxyErrors)}}class iy extends N{[t8]=!1;[t6]=!1;[t9]=[];[t4]=[];[ii];[t2];[il];[t3];[tV]=!1;[tX]=!1;[tK]=!1;[tJ]=!1;[tq]=null;[t7]=0;[ir]=!1;[id];[ic]=!1;[iD]=0;[ip]=!1;writable=!0;readable=!0;constructor(...e){let t=e[0]||{};if(super(),t.objectMode&&"string"==typeof t.encoding)throw TypeError("Encoding and objectMode may not be used together");if(t.objectMode)this[ii]=!0,this[t2]=null;else t.objectMode||!t.encoding||"buffer"===t.encoding?(this[ii]=!1,this[t2]=null):(this[t2]=t.encoding,this[ii]=!1);this[il]=!!t.async,this[t3]=this[t2]?new $(this[t2]):null,t&&!0===t.debugExposeBuffer&&Object.defineProperty(this,"buffer",{get:()=>this[t4]}),t&&!0===t.debugExposePipes&&Object.defineProperty(this,"pipes",{get:()=>this[t9]});let{signal:i}=t;i&&(this[id]=i,i.aborted?this[ih]():i.addEventListener("abort",()=>this[ih]()))}get bufferLength(){return this[t7]}get encoding(){return this[t2]}set encoding(e){throw Error("Encoding must be set at instantiation time")}setEncoding(e){throw Error("Encoding must be set at instantiation time")}get objectMode(){return this[ii]}set objectMode(e){throw Error("objectMode must be set at instantiation time")}get async(){return this[il]}set async(e){this[il]=this[il]||!!e}[ih](){this[ic]=!0,this.emit("abort",this[id]?.reason),this.destroy(this[id]?.reason)}get aborted(){return this[ic]}set aborted(e){}write(e,t,i){if(this[ic])return!1;if(this[tV])throw Error("write after end");if(this[ir])return this.emit("error",Object.assign(Error("Cannot call write after a stream was destroyed"),{code:"ERR_STREAM_DESTROYED"})),!0;"function"==typeof t&&(i=t,t="utf8"),t||(t="utf8");let r=this[il]?im:ig;if(!this[ii]&&!Buffer.isBuffer(e)){let t;if(t=e,!Buffer.isBuffer(t)&&ArrayBuffer.isView(t))e=Buffer.from(e.buffer,e.byteOffset,e.byteLength);else{let t;if((t=e)instanceof ArrayBuffer||t&&"object"==typeof t&&t.constructor&&"ArrayBuffer"===t.constructor.name&&t.byteLength>=0)e=Buffer.from(e);else if("string"!=typeof e)throw Error("Non-contiguous data written to non-objectMode stream")}}return this[ii]?(this[t8]&&0!==this[t7]&&this[t0](!0),this[t8]?this.emit("data",e):this[ie](e)):e.length&&("string"==typeof e&&(t!==this[t2]||this[t3]?.lastNeed)&&(e=Buffer.from(e,t)),Buffer.isBuffer(e)&&this[t2]&&(e=this[t3].write(e)),this[t8]&&0!==this[t7]&&this[t0](!0),this[t8]?this.emit("data",e):this[ie](e)),0!==this[t7]&&this.emit("readable"),i&&r(i),this[t8]}read(e){if(this[ir])return null;if(this[ip]=!1,0===this[t7]||0===e||e&&e>this[t7])return this[tY](),null;this[ii]&&(e=null),this[t4].length>1&&!this[ii]&&(this[t4]=[this[t2]?this[t4].join(""):Buffer.concat(this[t4],this[t7])]);let t=this[tQ](e||null,this[t4][0]);return this[tY](),t}[tQ](e,t){if(this[ii])this[it]();else{let i=t;e===i.length||null===e?this[it]():("string"==typeof i?(this[t4][0]=i.slice(e),t=i.slice(0,e)):(this[t4][0]=i.subarray(e),t=i.subarray(0,e)),this[t7]-=e)}return this.emit("data",t),this[t4].length||this[tV]||this.emit("drain"),t}end(e,t,i){return"function"==typeof e&&(i=e,e=void 0),"function"==typeof t&&(i=t,t="utf8"),void 0!==e&&this.write(e,t),i&&this.once("end",i),this[tV]=!0,this.writable=!1,(this[t8]||!this[t6])&&this[tY](),this}[t5](){this[ir]||(this[iD]||this[t9].length||(this[ip]=!0),this[t6]=!1,this[t8]=!0,this.emit("resume"),this[t4].length?this[t0]():this[tV]?this[tY]():this.emit("drain"))}resume(){return this[t5]()}pause(){this[t8]=!1,this[t6]=!0,this[ip]=!1}get destroyed(){return this[ir]}get flowing(){return this[t8]}get paused(){return this[t6]}[ie](e){this[ii]?this[t7]+=1:this[t7]+=e.length,this[t4].push(e)}[it](){return this[ii]?this[t7]-=1:this[t7]-=this[t4][0].length,this[t4].shift()}[t0](e=!1){do;while(this[t1](this[it]())&&this[t4].length);e||this[t4].length||this[tV]||this.emit("drain")}[t1](e){return this.emit("data",e),this[t8]}pipe(e,t){if(this[ir])return e;this[ip]=!1;let i=this[tX];return t=t||{},e===tH.stdout||e===tH.stderr?t.end=!1:t.end=!1!==t.end,t.proxyErrors=!!t.proxyErrors,i?t.end&&e.end():(this[t9].push(t.proxyErrors?new ib(this,e,t):new iE(this,e,t)),this[il]?im(()=>this[t5]()):this[t5]()),e}unpipe(e){let t=this[t9].find(t=>t.dest===e);t&&(1===this[t9].length?(this[t8]&&0===this[iD]&&(this[t8]=!1),this[t9]=[]):this[t9].splice(this[t9].indexOf(t),1),t.unpipe())}addListener(e,t){return this.on(e,t)}on(e,t){let i=super.on(e,t);if("data"===e)this[ip]=!1,this[iD]++,this[t9].length||this[t8]||this[t5]();else if("readable"===e&&0!==this[t7])super.emit("readable");else("end"===e||"finish"===e||"prefinish"===e)&&this[tX]?(super.emit(e),this.removeAllListeners(e)):"error"===e&&this[tq]&&(this[il]?im(()=>t.call(this,this[tq])):t.call(this,this[tq]));return i}removeListener(e,t){return this.off(e,t)}off(e,t){let i=super.off(e,t);return"data"===e&&(this[iD]=this.listeners("data").length,0!==this[iD]||this[ip]||this[t9].length||(this[t8]=!1)),i}removeAllListeners(e){let t=super.removeAllListeners(e);return("data"===e||void 0===e)&&(this[iD]=0,this[ip]||this[t9].length||(this[t8]=!1)),t}get emittedEnd(){return this[tX]}[tY](){this[tK]||this[tX]||this[ir]||0!==this[t4].length||!this[tV]||(this[tK]=!0,this.emit("end"),this.emit("prefinish"),this.emit("finish"),this[tJ]&&this.emit("close"),this[tK]=!1)}emit(e,...t){let i=t[0];if("error"!==e&&"close"!==e&&e!==ir&&this[ir])return!1;if("data"===e)return(!!this[ii]||!!i)&&(this[il]?(im(()=>this[io](i)),!0):this[io](i));if("end"===e)return this[iu]();if("close"===e){if(this[tJ]=!0,!this[tX]&&!this[ir])return!1;let e=super.emit("close");return this.removeAllListeners("close"),e}if("error"===e){this[tq]=i,super.emit(is,i);let e=(!this[id]||!!this.listeners("error").length)&&super.emit("error",i);return this[tY](),e}else if("resume"===e){let e=super.emit("resume");return this[tY](),e}else if("finish"===e||"prefinish"===e){let t=super.emit(e);return this.removeAllListeners(e),t}let r=super.emit(e,...t);return this[tY](),r}[io](e){for(let t of this[t9])!1===t.dest.write(e)&&this.pause();let t=!this[ip]&&super.emit("data",e);return this[tY](),t}[iu](){return!this[tX]&&(this[tX]=!0,this.readable=!1,this[il]?(im(()=>this[ia]()),!0):this[ia]())}[ia](){if(this[t3]){let e=this[t3].end();if(e){for(let t of this[t9])t.dest.write(e);this[ip]||super.emit("data",e)}}for(let e of this[t9])e.end();let e=super.emit("end");return this.removeAllListeners("end"),e}async collect(){let e=Object.assign([],{dataLength:0});this[ii]||(e.dataLength=0);let t=this.promise();return this.on("data",t=>{e.push(t),this[ii]||(e.dataLength+=t.length)}),await t,e}async concat(){if(this[ii])throw Error("cannot concat in objectMode");let e=await this.collect();return this[t2]?e.join(""):Buffer.concat(e,e.dataLength)}async promise(){return new Promise((e,t)=>{this.on(ir,()=>t(Error("stream destroyed"))),this.on("error",e=>t(e)),this.on("end",()=>e())})}[Symbol.asyncIterator](){this[ip]=!1;let e=!1,t=async()=>(this.pause(),e=!0,{value:void 0,done:!0});return{next:()=>{let i,r;if(e)return t();let n=this.read();if(null!==n)return Promise.resolve({done:!1,value:n});if(this[tV])return t();let s=e=>{this.off("data",o),this.off("end",u),this.off(ir,a),t(),r(e)},o=e=>{this.off("error",s),this.off("end",u),this.off(ir,a),this.pause(),i({value:e,done:!!this[tV]})},u=()=>{this.off("error",s),this.off("data",o),this.off(ir,a),t(),i({done:!0,value:void 0})},a=()=>s(Error("stream destroyed"));return new Promise((e,t)=>{r=t,i=e,this.once(ir,a),this.once("error",s),this.once("end",u),this.once("data",o)})},throw:t,return:t,[Symbol.asyncIterator](){return this}}}[Symbol.iterator](){this[ip]=!1;let e=!1,t=()=>(this.pause(),this.off(is,t),this.off(ir,t),this.off("end",t),e=!0,{done:!0,value:void 0}),i=()=>{if(e)return t();let i=this.read();return null===i?t():{done:!1,value:i}};return this.once("end",t),this.once(is,t),this.once(ir,t),{next:i,throw:t,return:t,[Symbol.iterator](){return this}}}destroy(e){return this[ir]||(this[ir]=!0,this[ip]=!0,this[t4].length=0,this[t7]=0,"function"!=typeof this.close||this[tJ]||this.close()),e?this.emit("error",e):this.emit(ir),this}static get isStream(){return tG}}let iF=tD.default.writev,iC=Symbol("_autoClose"),iv=Symbol("_close"),iw=Symbol("_ended"),i_=Symbol("_fd"),iS=Symbol("_finished"),iA=Symbol("_flags"),iR=Symbol("_flush"),iO=Symbol("_handleChunk"),iB=Symbol("_makeBuf"),ix=Symbol("_mode"),iN=Symbol("_needDrain"),iI=Symbol("_onerror"),iT=Symbol("_onopen"),iL=Symbol("_onread"),ik=Symbol("_onwrite"),iM=Symbol("_open"),i$=Symbol("_path"),ij=Symbol("_pos"),iP=Symbol("_queue"),iz=Symbol("_read"),iU=Symbol("_readSize"),iH=Symbol("_reading"),iG=Symbol("_remain"),iZ=Symbol("_size"),iW=Symbol("_write"),iV=Symbol("_writing"),iY=Symbol("_defaultFlag"),iX=Symbol("_errored");class iK extends iy{[iX]=!1;[i_];[i$];[iU];[iH]=!1;[iZ];[iG];[iC];constructor(e,t){if(super(t=t||{}),this.readable=!0,this.writable=!1,"string"!=typeof e)throw TypeError("path must be a string");this[iX]=!1,this[i_]="number"==typeof t.fd?t.fd:void 0,this[i$]=e,this[iU]=t.readSize||0x1000000,this[iH]=!1,this[iZ]="number"==typeof t.size?t.size:1/0,this[iG]=this[iZ],this[iC]="boolean"!=typeof t.autoClose||t.autoClose,"number"==typeof this[i_]?this[iz]():this[iM]()}get fd(){return this[i_]}get path(){return this[i$]}write(){throw TypeError("this is a readable stream")}end(){throw TypeError("this is a readable stream")}[iM](){tD.default.open(this[i$],"r",(e,t)=>this[iT](e,t))}[iT](e,t){e?this[iI](e):(this[i_]=t,this.emit("open",t),this[iz]())}[iB](){return Buffer.allocUnsafe(Math.min(this[iU],this[iG]))}[iz](){if(!this[iH]){this[iH]=!0;let e=this[iB]();if(0===e.length)return process.nextTick(()=>this[iL](null,0,e));tD.default.read(this[i_],e,0,e.length,null,(e,t,i)=>this[iL](e,t,i))}}[iL](e,t,i){this[iH]=!1,e?this[iI](e):this[iO](t,i)&&this[iz]()}[iv](){if(this[iC]&&"number"==typeof this[i_]){let e=this[i_];this[i_]=void 0,tD.default.close(e,e=>e?this.emit("error",e):this.emit("close"))}}[iI](e){this[iH]=!0,this[iv](),this.emit("error",e)}[iO](e,t){let i=!1;return this[iG]-=e,e>0&&(i=super.write(ethis[iT](e,t))}[iT](e,t){this[iY]&&"r+"===this[iA]&&e&&"ENOENT"===e.code?(this[iA]="w",this[iM]()):e?this[iI](e):(this[i_]=t,this.emit("open",t),this[iV]||this[iR]())}end(e,t){return e&&this.write(e,t),this[iw]=!0,this[iV]||this[iP].length||"number"!=typeof this[i_]||this[ik](null,0),this}write(e,t){return("string"==typeof e&&(e=Buffer.from(e,t)),this[iw])?(this.emit("error",Error("write() after end()")),!1):void 0===this[i_]||this[iV]||this[iP].length?(this[iP].push(e),this[iN]=!0,!1):(this[iV]=!0,this[iW](e),!0)}[iW](e){tD.default.write(this[i_],e,0,e.length,this[ij],(e,t)=>this[ik](e,t))}[ik](e,t){e?this[iI](e):(void 0!==this[ij]&&"number"==typeof t&&(this[ij]+=t),this[iP].length?this[iR]():(this[iV]=!1,this[iw]&&!this[iS]?(this[iS]=!0,this[iv](),this.emit("finish")):this[iN]&&(this[iN]=!1,this.emit("drain"))))}[iR](){if(0===this[iP].length)this[iw]&&this[ik](null,0);else if(1===this[iP].length)this[iW](this[iP].pop());else{let e=this[iP];this[iP]=[],iF(this[i_],e,this[ij],(e,t)=>this[ik](e,t))}}[iv](){if(this[iC]&&"number"==typeof this[i_]){let e=this[i_];this[i_]=void 0,tD.default.close(e,e=>e?this.emit("error",e):this.emit("close"))}}}class iQ extends iJ{[iM](){let e;if(this[iY]&&"r+"===this[iA])try{e=tD.default.openSync(this[i$],this[iA],this[ix])}catch(e){if(e?.code==="ENOENT")return this[iA]="w",this[iM]();throw e}else e=tD.default.openSync(this[i$],this[iA],this[ix]);this[iT](null,e)}[iv](){if(this[iC]&&"number"==typeof this[i_]){let e=this[i_];this[i_]=void 0,tD.default.closeSync(e),this.emit("close")}}[iW](e){let t=!0;try{this[ik](null,tD.default.writeSync(this[i_],e,0,e.length,this[ij])),t=!1}finally{if(t)try{this[iv]()}catch{}}}}let i0=new Map([["C","cwd"],["f","file"],["z","gzip"],["P","preservePaths"],["U","unlink"],["strip-components","strip"],["stripComponents","strip"],["keep-newer","newer"],["keepNewer","newer"],["keep-newer-files","newer"],["keepNewerFiles","newer"],["k","keep"],["keep-existing","keep"],["keepExisting","keep"],["m","noMtime"],["no-mtime","noMtime"],["p","preserveOwner"],["L","follow"],["h","follow"],["onentry","onReadEntry"]]),i1=e=>{let t=i0.get(e);return t||e},i2=(e={})=>{if(!e)return{};let t={};for(let[i,r]of Object.entries(e))t[i1(i)]=r;return void 0===t.chmod&&!1===t.noChmod&&(t.chmod=!0),delete t.noChmod,t},i3=(e,t,i,r,n)=>Object.assign((s=[],o,u)=>{Array.isArray(s)&&(o=s,s={}),"function"==typeof o&&(u=o,o=void 0),o=o?Array.from(o):[];let a=i2(s);if(n?.(a,o),!a.sync||!a.file){if(a.sync||!a.file){if(!a.sync||a.file){if(a.sync||a.file)throw Error("impossible options??");if("function"==typeof u)throw TypeError("callback only supported with file option");return r(a,o)}if("function"==typeof u)throw TypeError("callback not supported for sync tar functions");return i(a,o)}{let e=t(a,o),i=u||void 0;return i?e.then(()=>i(),i):e}}if("function"==typeof u)throw TypeError("callback not supported for sync tar functions");return e(a,o)},{syncFile:e,asyncFile:t,syncNoFile:i,asyncNoFile:r,validate:n});var i8=Y("zlib");let i6=i8.default.constants||{ZLIB_VERNUM:4736},i5=Object.freeze(Object.assign(Object.create(null),{Z_NO_FLUSH:0,Z_PARTIAL_FLUSH:1,Z_SYNC_FLUSH:2,Z_FULL_FLUSH:3,Z_FINISH:4,Z_BLOCK:5,Z_OK:0,Z_STREAM_END:1,Z_NEED_DICT:2,Z_ERRNO:-1,Z_STREAM_ERROR:-2,Z_DATA_ERROR:-3,Z_MEM_ERROR:-4,Z_BUF_ERROR:-5,Z_VERSION_ERROR:-6,Z_NO_COMPRESSION:0,Z_BEST_SPEED:1,Z_BEST_COMPRESSION:9,Z_DEFAULT_COMPRESSION:-1,Z_FILTERED:1,Z_HUFFMAN_ONLY:2,Z_RLE:3,Z_FIXED:4,Z_DEFAULT_STRATEGY:0,DEFLATE:1,INFLATE:2,GZIP:3,GUNZIP:4,DEFLATERAW:5,INFLATERAW:6,UNZIP:7,BROTLI_DECODE:8,BROTLI_ENCODE:9,Z_MIN_WINDOWBITS:8,Z_MAX_WINDOWBITS:15,Z_DEFAULT_WINDOWBITS:15,Z_MIN_CHUNK:64,Z_MAX_CHUNK:1/0,Z_DEFAULT_CHUNK:16384,Z_MIN_MEMLEVEL:1,Z_MAX_MEMLEVEL:9,Z_DEFAULT_MEMLEVEL:8,Z_MIN_LEVEL:-1,Z_MAX_LEVEL:9,Z_DEFAULT_LEVEL:-1,BROTLI_OPERATION_PROCESS:0,BROTLI_OPERATION_FLUSH:1,BROTLI_OPERATION_FINISH:2,BROTLI_OPERATION_EMIT_METADATA:3,BROTLI_MODE_GENERIC:0,BROTLI_MODE_TEXT:1,BROTLI_MODE_FONT:2,BROTLI_DEFAULT_MODE:0,BROTLI_MIN_QUALITY:0,BROTLI_MAX_QUALITY:11,BROTLI_DEFAULT_QUALITY:11,BROTLI_MIN_WINDOW_BITS:10,BROTLI_MAX_WINDOW_BITS:24,BROTLI_LARGE_MAX_WINDOW_BITS:30,BROTLI_DEFAULT_WINDOW:22,BROTLI_MIN_INPUT_BLOCK_BITS:16,BROTLI_MAX_INPUT_BLOCK_BITS:24,BROTLI_PARAM_MODE:0,BROTLI_PARAM_QUALITY:1,BROTLI_PARAM_LGWIN:2,BROTLI_PARAM_LGBLOCK:3,BROTLI_PARAM_DISABLE_LITERAL_CONTEXT_MODELING:4,BROTLI_PARAM_SIZE_HINT:5,BROTLI_PARAM_LARGE_WINDOW:6,BROTLI_PARAM_NPOSTFIX:7,BROTLI_PARAM_NDIRECT:8,BROTLI_DECODER_RESULT_ERROR:0,BROTLI_DECODER_RESULT_SUCCESS:1,BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT:2,BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT:3,BROTLI_DECODER_PARAM_DISABLE_RING_BUFFER_REALLOCATION:0,BROTLI_DECODER_PARAM_LARGE_WINDOW:1,BROTLI_DECODER_NO_ERROR:0,BROTLI_DECODER_SUCCESS:1,BROTLI_DECODER_NEEDS_MORE_INPUT:2,BROTLI_DECODER_NEEDS_MORE_OUTPUT:3,BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_NIBBLE:-1,BROTLI_DECODER_ERROR_FORMAT_RESERVED:-2,BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_META_NIBBLE:-3,BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_ALPHABET:-4,BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_SAME:-5,BROTLI_DECODER_ERROR_FORMAT_CL_SPACE:-6,BROTLI_DECODER_ERROR_FORMAT_HUFFMAN_SPACE:-7,BROTLI_DECODER_ERROR_FORMAT_CONTEXT_MAP_REPEAT:-8,BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_1:-9,BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_2:-10,BROTLI_DECODER_ERROR_FORMAT_TRANSFORM:-11,BROTLI_DECODER_ERROR_FORMAT_DICTIONARY:-12,BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS:-13,BROTLI_DECODER_ERROR_FORMAT_PADDING_1:-14,BROTLI_DECODER_ERROR_FORMAT_PADDING_2:-15,BROTLI_DECODER_ERROR_FORMAT_DISTANCE:-16,BROTLI_DECODER_ERROR_DICTIONARY_NOT_SET:-19,BROTLI_DECODER_ERROR_INVALID_ARGUMENTS:-20,BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MODES:-21,BROTLI_DECODER_ERROR_ALLOC_TREE_GROUPS:-22,BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MAP:-25,BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_1:-26,BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_2:-27,BROTLI_DECODER_ERROR_ALLOC_BLOCK_TYPE_TREES:-30,BROTLI_DECODER_ERROR_UNREACHABLE:-31},i6)),i4=P.concat,i9=Object.getOwnPropertyDescriptor(P,"concat"),i7=e=>e,re=i9?.writable===!0||i9?.set!==void 0?e=>{P.concat=e?i7:i4}:e=>{},rt=Symbol("_superWrite");class ri extends Error{code;errno;constructor(e,t){super("zlib: "+e.message,{cause:e}),this.code=e.code,this.errno=e.errno,this.code||(this.code="ZLIB_ERROR"),this.message="zlib: "+e.message,Error.captureStackTrace(this,t??this.constructor)}get name(){return"ZlibError"}}let rr=Symbol("flushFlag");class rn extends iy{#e=!1;#t=!1;#i;#r;#n;#s;#o;get sawError(){return this.#e}get handle(){return this.#s}get flushFlag(){return this.#i}constructor(e,t){if(!e||"object"!=typeof e)throw TypeError("invalid options for ZlibBase constructor");if(super(e),this.#i=e.flush??0,this.#r=e.finishFlush??0,this.#n=e.fullFlushFlag??0,"function"!=typeof i8[t])throw TypeError("Compression method not supported: "+t);try{this.#s=new i8[t](e)}catch(e){throw new ri(e,this.constructor)}this.#o=e=>{this.#e||(this.#e=!0,this.close(),this.emit("error",e))},this.#s?.on("error",e=>this.#o(new ri(e))),this.once("end",()=>this.close)}close(){this.#s&&(this.#s.close(),this.#s=void 0,this.emit("close"))}reset(){if(!this.#e)return j(this.#s,"zlib binding closed"),this.#s.reset?.()}flush(e){this.ended||("number"!=typeof e&&(e=this.#n),this.write(Object.assign(P.alloc(0),{[rr]:e})))}end(e,t,i){return"function"==typeof e&&(i=e,t=void 0,e=void 0),"function"==typeof t&&(i=t,t=void 0),e&&(t?this.write(e,t):this.write(e)),this.flush(this.#r),this.#t=!0,super.end(i)}get ended(){return this.#t}[rt](e){return super.write(e)}write(e,t,i){let r,n;if("function"==typeof t&&(i=t,t="utf8"),"string"==typeof e&&(e=P.from(e,t)),this.#e)return;j(this.#s,"zlib binding closed");let s=this.#s._handle,o=s.close;s.close=()=>{};let u=this.#s.close;this.#s.close=()=>{},re(!0);try{let t="number"==typeof e[rr]?e[rr]:this.#i;n=this.#s._processChunk(e,t),re(!1)}catch(e){re(!1),this.#o(new ri(e,this.write))}finally{this.#s&&(this.#s._handle=s,s.close=o,this.#s.close=u,this.#s.removeAllListeners("error"))}if(this.#s&&this.#s.on("error",e=>this.#o(new ri(e,this.write))),n)if(Array.isArray(n)&&n.length>0){let e=n[0];r=this[rt](P.from(e));for(let e=1;e{"function"==typeof e&&(t=e,e=this.flushFlag),this.flush(e),t?.()};try{this.handle.params(e,t)}finally{this.handle.flush=i}this.handle&&(this.#u=e,this.#a=t)}}}}class ro extends rs{#l;constructor(e){super(e,"Gzip"),this.#l=e&&!!e.portable}[rt](e){return this.#l&&(this.#l=!1,e[9]=255),super[rt](e)}}class ru extends rs{constructor(e){super(e,"Unzip")}}class ra extends rn{constructor(e,t){(e=e||{}).flush=e.flush||i5.BROTLI_OPERATION_PROCESS,e.finishFlush=e.finishFlush||i5.BROTLI_OPERATION_FINISH,e.fullFlushFlag=i5.BROTLI_OPERATION_FLUSH,super(e,t)}}class rl extends ra{constructor(e){super(e,"BrotliCompress")}}class rh extends ra{constructor(e){super(e,"BrotliDecompress")}}class rc extends rn{constructor(e,t){(e=e||{}).flush=e.flush||i5.ZSTD_e_continue,e.finishFlush=e.finishFlush||i5.ZSTD_e_end,e.fullFlushFlag=i5.ZSTD_e_flush,super(e,t)}}class rd extends rc{constructor(e){super(e,"ZstdCompress")}}class rD extends rc{constructor(e){super(e,"ZstdDecompress")}}let rf=e=>(255^e)&255,rp=e=>(255^e)+1&255,rm=e=>rg.has(e),rg=new Map([["0","File"],["","OldFile"],["1","Link"],["2","SymbolicLink"],["3","CharacterDevice"],["4","BlockDevice"],["5","Directory"],["6","FIFO"],["7","ContiguousFile"],["g","GlobalExtendedHeader"],["x","ExtendedHeader"],["A","SolarisACL"],["D","GNUDumpDir"],["I","Inode"],["K","NextFileHasLongLinkpath"],["L","NextFileHasLongPath"],["M","ContinuationFile"],["N","OldGnuLongPath"],["S","SparseFile"],["V","TapeVolumeHeader"],["X","OldExtendedHeader"]]),rE=new Map(Array.from(rg).map(e=>[e[1],e[0]]));class rb{cksumValid=!1;needPax=!1;nullBlock=!1;block;path;mode;uid;gid;size;cksum;#h="Unsupported";linkpath;uname;gname;devmaj=0;devmin=0;atime;ctime;mtime;charset;comment;constructor(e,t=0,i,r){Buffer.isBuffer(e)?this.decode(e,t||0,i,r):e&&this.#c(e)}decode(e,t,i,r){if(t||(t=0),!e||!(e.length>=t+512))throw Error("need 512 bytes for header");this.path=rF(e,t,100),this.mode=rw(e,t+100,8),this.uid=rw(e,t+108,8),this.gid=rw(e,t+116,8),this.size=rw(e,t+124,12),this.mtime=rC(e,t+136,12),this.cksum=rw(e,t+148,12),r&&this.#c(r,!0),i&&this.#c(i);let n=rF(e,t+156,1);if(rm(n)&&(this.#h=n||"0"),"0"===this.#h&&"/"===this.path.slice(-1)&&(this.#h="5"),"5"===this.#h&&(this.size=0),this.linkpath=rF(e,t+157,100),"ustar\x0000"===e.subarray(t+257,t+265).toString())if(this.uname=rF(e,t+265,32),this.gname=rF(e,t+297,32),this.devmaj=rw(e,t+329,8)??0,this.devmin=rw(e,t+337,8)??0,0!==e[t+475]){let i=rF(e,t+345,155);this.path=i+"/"+this.path}else{let i=rF(e,t+345,130);i&&(this.path=i+"/"+this.path),this.atime=rC(e,t+476,12),this.ctime=rC(e,t+488,12)}let s=256;for(let i=t;i!(null==i||"path"===e&&t||"linkpath"===e&&t||"global"===e))))}encode(e,t=0){if(e||(e=this.block=Buffer.alloc(512)),"Unsupported"===this.#h&&(this.#h="0"),!(e.length>=t+512))throw Error("need 512 bytes for header");let i=this.ctime||this.atime?130:155,r=ry(this.path||"",i),n=r[0],s=r[1];this.needPax=!!r[2],this.needPax=rI(e,t,100,n)||this.needPax,this.needPax=rA(e,t+100,8,this.mode)||this.needPax,this.needPax=rA(e,t+108,8,this.uid)||this.needPax,this.needPax=rA(e,t+116,8,this.gid)||this.needPax,this.needPax=rA(e,t+124,12,this.size)||this.needPax,this.needPax=rx(e,t+136,12,this.mtime)||this.needPax,e[t+156]=this.#h.charCodeAt(0),this.needPax=rI(e,t+157,100,this.linkpath)||this.needPax,e.write("ustar\x0000",t+257,8),this.needPax=rI(e,t+265,32,this.uname)||this.needPax,this.needPax=rI(e,t+297,32,this.gname)||this.needPax,this.needPax=rA(e,t+329,8,this.devmaj)||this.needPax,this.needPax=rA(e,t+337,8,this.devmin)||this.needPax,this.needPax=rI(e,t+345,i,s)||this.needPax,0!==e[t+475]?this.needPax=rI(e,t+345,155,s)||this.needPax:(this.needPax=rI(e,t+345,130,s)||this.needPax,this.needPax=rx(e,t+476,12,this.atime)||this.needPax,this.needPax=rx(e,t+488,12,this.ctime)||this.needPax);let o=256;for(let i=t;i{let i,r=e,n="",s=D.parse(e).root||".";if(100>Buffer.byteLength(r))i=[r,n,!1];else{n=D.dirname(r),r=D.basename(r);do 100>=Buffer.byteLength(r)&&Buffer.byteLength(n)<=t?i=[r,n,!1]:Buffer.byteLength(r)>100&&Buffer.byteLength(n)<=t?i=[r.slice(0,99),n,!0]:(r=D.join(D.basename(n),r),n=D.dirname(n));while(n!==s&&void 0===i);i||(i=[e.slice(0,99),"",!0])}return i},rF=(e,t,i)=>e.subarray(t,t+i).toString("utf8").replace(/\0.*/,""),rC=(e,t,i)=>rv(rw(e,t,i)),rv=e=>void 0===e?void 0:new Date(1e3*e),rw=(e,t,i)=>128&Number(e[t])?(e=>{let t=e[0],i=128===t?(e=>{for(var t=e.length,i=0,r=t-1;r>-1;r--){var n=Number(e[r]);0!==n&&(i+=n*Math.pow(256,t-r-1))}return i})(e.subarray(1,e.length)):255===t?(e=>{for(var t=e.length,i=0,r=!1,n=t-1;n>-1;n--){var s,o=Number(e[n]);r?s=rf(o):0===o?s=o:(r=!0,s=rp(o)),0!==s&&(i-=s*Math.pow(256,t-n-1))}return i})(e):null;if(null===i)throw Error("invalid base256 encoding");if(!Number.isSafeInteger(i))throw Error("parsed number outside of javascript safe integer range");return i})(e.subarray(t,t+i)):r_(e,t,i),r_=(e,t,i)=>{let r;return isNaN(r=parseInt(e.subarray(t,t+i).toString("utf8").replace(/\0.*$/,"").trim(),8))?void 0:r},rS={12:0x1ffffffff,8:2097151},rA=(e,t,i,r)=>void 0!==r&&(r>rS[i]||r<0?(((e,t)=>{if(Number.isSafeInteger(e))e<0?((e,t)=>{t[0]=255;var i=!1;e*=-1;for(var r=t.length;r>1;r--){var n=255&e;e=Math.floor(e/256),i?t[r-1]=rf(n):0===n?t[r-1]=0:(i=!0,t[r-1]=rp(n))}})(e,t):((e,t)=>{t[0]=128;for(var i=t.length;i>1;i--)t[i-1]=255&e,e=Math.floor(e/256)})(e,t);else throw Error("cannot encode number outside of javascript safe integer range")})(r,e.subarray(t,t+i)),!0):(rR(e,t,i,r),!1)),rR=(e,t,i,r)=>e.write(rO(r,i),t,i,"ascii"),rO=(e,t)=>rB(Math.floor(e).toString(8),t),rB=(e,t)=>(e.length===t-1?e:Array(t-e.length-1).join("0")+e+" ")+"\0",rx=(e,t,i,r)=>void 0!==r&&rA(e,t,i,r.getTime()/1e3),rN=Array(156).join("\0"),rI=(e,t,i,r)=>void 0!==r&&(e.write(r+rN,t,i,"utf8"),r.length!==Buffer.byteLength(r)||r.length>i);class rT{atime;mtime;ctime;charset;comment;gid;uid;gname;uname;linkpath;dev;ino;nlink;path;size;mode;global;constructor(e,t=!1){this.atime=e.atime,this.charset=e.charset,this.comment=e.comment,this.ctime=e.ctime,this.dev=e.dev,this.gid=e.gid,this.global=t,this.gname=e.gname,this.ino=e.ino,this.linkpath=e.linkpath,this.mtime=e.mtime,this.nlink=e.nlink,this.path=e.path,this.size=e.size,this.uid=e.uid,this.uname=e.uname}encode(){let e=this.encodeBody();if(""===e)return Buffer.allocUnsafe(0);let t=Buffer.byteLength(e),i=512*Math.ceil(1+t/512),r=Buffer.allocUnsafe(i);for(let e=0;e<512;e++)r[e]=0;new rb({path:("PaxHeader/"+a(this.path??"")).slice(0,99),mode:this.mode||420,uid:this.uid,gid:this.gid,size:t,mtime:this.mtime,type:this.global?"GlobalExtendedHeader":"ExtendedHeader",linkpath:"",uname:this.uname||"",gname:this.gname||"",devmaj:0,devmin:0,atime:this.atime,ctime:this.ctime}).encode(r),r.write(e,512,t,"utf8");for(let e=t+512;e=Math.pow(10,n)&&(n+=1),n+r+i}static parse(e,t,i=!1){return new rT(rL(rk(e),t),i)}}let rL=(e,t)=>t?Object.assign({},t,e):e,rk=e=>e.replace(/\n$/,"").split("\n").reduce(rM,Object.create(null)),rM=(e,t)=>{let i=parseInt(t,10);if(i!==Buffer.byteLength(t)+1)return e;let r=(t=t.slice((i+" ").length)).split("="),n=r.shift();if(!n)return e;let s=n.replace(/^SCHILY\.(dev|ino|nlink)/,"$1"),o=r.join("=");return e[s]=/^([A-Z]+\.)?([mac]|birth|creation)time$/.test(s)?new Date(1e3*Number(o)):/^[0-9]+$/.test(o)?+o:o,e},r$="win32"!==(process.env.TESTING_TAR_FAKE_PLATFORM||process.platform)?e=>e:e=>e&&e.replace(/\\/g,"/");class rj extends iy{extended;globalExtended;header;startBlockSize;blockRemain;remain;type;meta=!1;ignore=!1;path;mode;uid;gid;uname;gname;size=0;mtime;atime;ctime;linkpath;dev;ino;nlink;invalid=!1;absolute;unsupported=!1;constructor(e,t,i){switch(super({}),this.pause(),this.extended=t,this.globalExtended=i,this.header=e,this.remain=e.size??0,this.startBlockSize=512*Math.ceil(this.remain/512),this.blockRemain=this.startBlockSize,this.type=e.type,this.type){case"File":case"OldFile":case"Link":case"SymbolicLink":case"CharacterDevice":case"BlockDevice":case"Directory":case"FIFO":case"ContiguousFile":case"GNUDumpDir":break;case"NextFileHasLongLinkpath":case"NextFileHasLongPath":case"OldGnuLongPath":case"GlobalExtendedHeader":case"ExtendedHeader":case"OldExtendedHeader":this.meta=!0;break;default:this.ignore=!0}if(!e.path)throw Error("no path provided for tar.ReadEntry");this.path=r$(e.path),this.mode=e.mode,this.mode&&(this.mode=4095&this.mode),this.uid=e.uid,this.gid=e.gid,this.uname=e.uname,this.gname=e.gname,this.size=this.remain,this.mtime=e.mtime,this.atime=e.atime,this.ctime=e.ctime,this.linkpath=e.linkpath?r$(e.linkpath):void 0,this.uname=e.uname,this.gname=e.gname,t&&this.#c(t),i&&this.#c(i,!0)}write(e){let t=e.length;if(t>this.blockRemain)throw Error("writing more to entry than is appropriate");let i=this.remain,r=this.blockRemain;return this.remain=Math.max(0,i-t),this.blockRemain=Math.max(0,r-t),!!this.ignore||(i>=t?super.write(e):super.write(e.subarray(0,i)))}#c(e,t=!1){e.path&&(e.path=r$(e.path)),e.linkpath&&(e.linkpath=r$(e.linkpath)),Object.assign(this,Object.fromEntries(Object.entries(e).filter(([e,i])=>!(null==i||"path"===e&&t))))}}let rP=(e,t,i,r={})=>{e.file&&(r.file=e.file),e.cwd&&(r.cwd=e.cwd),r.code=i instanceof Error&&i.code||t,r.tarCode=t,e.strict||!1===r.recoverable?i instanceof Error?e.emit("error",Object.assign(i,r)):e.emit("error",Object.assign(Error(`${t}: ${i}`),r)):(i instanceof Error&&(r=Object.assign(i,r),i=i.message),e.emit("warn",t,i,r))},rz=Buffer.from([31,139]),rU=Buffer.from([40,181,47,253]),rH=Math.max(rz.length,rU.length),rG=Symbol("state"),rZ=Symbol("writeEntry"),rW=Symbol("readEntry"),rV=Symbol("nextEntry"),rY=Symbol("processEntry"),rX=Symbol("extendedHeader"),rK=Symbol("globalExtendedHeader"),rq=Symbol("meta"),rJ=Symbol("emitMeta"),rQ=Symbol("buffer"),r0=Symbol("queue"),r1=Symbol("ended"),r2=Symbol("emittedEnd"),r3=Symbol("emit"),r8=Symbol("unzip"),r6=Symbol("consumeChunk"),r5=Symbol("consumeChunkSub"),r4=Symbol("consumeBody"),r9=Symbol("consumeMeta"),r7=Symbol("consumeHeader"),ne=Symbol("consuming"),nt=Symbol("bufferConcat"),ni=Symbol("maybeEnd"),nr=Symbol("writing"),nn=Symbol("aborted"),ns=Symbol("onDone"),no=Symbol("sawValidEntry"),nu=Symbol("sawNullBlock"),na=Symbol("sawEOF"),nl=Symbol("closeStream"),nh=()=>!0;class nc extends M{file;strict;maxMetaEntrySize;filter;brotli;zstd;writable=!0;readable=!1;[r0]=[];[rQ];[rW];[rZ];[rG]="begin";[rq]="";[rX];[rK];[r1]=!1;[r8];[nn]=!1;[no];[nu]=!1;[na]=!1;[nr]=!1;[ne]=!1;[r2]=!1;constructor(e={}){super(),this.file=e.file||"",this.on(ns,()=>{("begin"===this[rG]||!1===this[no])&&this.warn("TAR_BAD_ARCHIVE","Unrecognized archive format")}),e.ondone?this.on(ns,e.ondone):this.on(ns,()=>{this.emit("prefinish"),this.emit("finish"),this.emit("end")}),this.strict=!!e.strict,this.maxMetaEntrySize=e.maxMetaEntrySize||1048576,this.filter="function"==typeof e.filter?e.filter:nh;let t=e.file&&(e.file.endsWith(".tar.br")||e.file.endsWith(".tbr"));this.brotli=e.gzip||e.zstd||void 0===e.brotli?!!t&&void 0:e.brotli;let i=e.file&&(e.file.endsWith(".tar.zst")||e.file.endsWith(".tzst"));this.zstd=e.gzip||e.brotli||void 0===e.zstd?!!i||void 0:e.zstd,this.on("end",()=>this[nl]()),"function"==typeof e.onwarn&&this.on("warn",e.onwarn),"function"==typeof e.onReadEntry&&this.on("entry",e.onReadEntry)}warn(e,t,i={}){rP(this,e,t,i)}[r7](e,t){let i;void 0===this[no]&&(this[no]=!1);try{i=new rb(e,t,this[rX],this[rK])}catch(e){return this.warn("TAR_ENTRY_INVALID",e)}if(i.nullBlock)this[nu]?(this[na]=!0,"begin"===this[rG]&&(this[rG]="header"),this[r3]("eof")):(this[nu]=!0,this[r3]("nullBlock"));else if(this[nu]=!1,i.cksumValid)if(i.path){let e=i.type;if(/^(Symbolic)?Link$/.test(e)&&!i.linkpath)this.warn("TAR_ENTRY_INVALID","linkpath required",{header:i});else if(/^(Symbolic)?Link$/.test(e)||/^(Global)?ExtendedHeader$/.test(e)||!i.linkpath){let e=this[rZ]=new rj(i,this[rX],this[rK]);if(!this[no])if(e.remain){let t=()=>{e.invalid||(this[no]=!0)};e.on("end",t)}else this[no]=!0;e.meta?e.size>this.maxMetaEntrySize?(e.ignore=!0,this[r3]("ignoredEntry",e),this[rG]="ignore",e.resume()):e.size>0&&(this[rq]="",e.on("data",e=>this[rq]+=e),this[rG]="meta"):(this[rX]=void 0,e.ignore=e.ignore||!this.filter(e.path,e),e.ignore?(this[r3]("ignoredEntry",e),this[rG]=e.remain?"ignore":"header",e.resume()):(e.remain?this[rG]="body":(this[rG]="header",e.end()),this[rW]?this[r0].push(e):(this[r0].push(e),this[rV]())))}else this.warn("TAR_ENTRY_INVALID","linkpath forbidden",{header:i})}else this.warn("TAR_ENTRY_INVALID","path is required",{header:i});else this.warn("TAR_ENTRY_INVALID","checksum failure",{header:i})}[nl](){queueMicrotask(()=>this.emit("close"))}[rY](e){let t=!0;if(e)if(Array.isArray(e)){let[t,...i]=e;this.emit(t,...i)}else this[rW]=e,this.emit("entry",e),e.emittedEnd||(e.on("end",()=>this[rV]()),t=!1);else this[rW]=void 0,t=!1;return t}[rV](){do;while(this[rY](this[r0].shift()));if(!this[r0].length){let e=this[rW];!e||e.flowing||e.size===e.remain?this[nr]||this.emit("drain"):e.once("drain",()=>this.emit("drain"))}}[r4](e,t){let i=this[rZ];if(!i)throw Error("attempt to consume body without entry??");let r=i.blockRemain??0,n=r>=e.length&&0===t?e:e.subarray(t,t+r);return i.write(n),i.blockRemain||(this[rG]="header",this[rZ]=void 0,i.end()),n.length}[r9](e,t){let i=this[rZ],r=this[r4](e,t);return!this[rZ]&&i&&this[rJ](i),r}[r3](e,t,i){this[r0].length||this[rW]?this[r0].push([e,t,i]):this.emit(e,t,i)}[rJ](e){switch(this[r3]("meta",this[rq]),e.type){case"ExtendedHeader":case"OldExtendedHeader":this[rX]=rT.parse(this[rq],this[rX],!1);break;case"GlobalExtendedHeader":this[rK]=rT.parse(this[rq],this[rK],!0);break;case"NextFileHasLongPath":case"OldGnuLongPath":{let e=this[rX]??Object.create(null);this[rX]=e,e.path=this[rq].replace(/\0.*/,"");break}case"NextFileHasLongLinkpath":{let e=this[rX]||Object.create(null);this[rX]=e,e.linkpath=this[rq].replace(/\0.*/,"");break}default:throw Error("unknown meta: "+e.type)}}abort(e){this[nn]=!0,this.emit("abort",e),this.warn("TAR_ABORT",e,{recoverable:!1})}write(e,t,i){if("function"==typeof t&&(i=t,t=void 0),"string"==typeof e&&(e=Buffer.from(e,"string"==typeof t?t:"utf8")),this[nn])return i?.(),!1;if((void 0===this[r8]||void 0===this.brotli&&!1===this[r8])&&e){if(this[rQ]&&(e=Buffer.concat([this[rQ],e]),this[rQ]=void 0),e.lengththis[r6](e)),this[r8].on("error",e=>this.abort(e)),this[r8].on("end",()=>{this[r1]=!0,this[r6]()}),this[nr]=!0;let n=!!this[r8][r?"end":"write"](e);return this[nr]=!1,i?.(),n}}this[nr]=!0,this[r8]?this[r8].write(e):this[r6](e),this[nr]=!1;let r=!this[r0].length&&(!this[rW]||this[rW].flowing);return r||this[r0].length||this[rW]?.once("drain",()=>this.emit("drain")),i?.(),r}[nt](e){e&&!this[nn]&&(this[rQ]=this[rQ]?Buffer.concat([this[rQ],e]):e)}[ni](){if(this[r1]&&!this[r2]&&!this[nn]&&!this[ne]){this[r2]=!0;let e=this[rZ];if(e&&e.blockRemain){let t=this[rQ]?this[rQ].length:0;this.warn("TAR_BAD_ARCHIVE",`Truncated input (needed ${e.blockRemain} more bytes, only ${t} available)`,{entry:e}),this[rQ]&&e.write(this[rQ]),e.end()}this[r3](ns)}}[r6](e){if(this[ne]&&e)this[nt](e);else if(e||this[rQ]){if(e){if(this[ne]=!0,this[rQ]){this[nt](e);let t=this[rQ];this[rQ]=void 0,this[r5](t)}else this[r5](e);for(;this[rQ]&&this[rQ]?.length>=512&&!this[nn]&&!this[na];){let e=this[rQ];this[rQ]=void 0,this[r5](e)}this[ne]=!1}}else this[ni]();(!this[rQ]||this[r1])&&this[ni]()}[r5](e){let t=0,i=e.length;for(;t+512<=i&&!this[nn]&&!this[na];)switch(this[rG]){case"begin":case"header":this[r7](e,t),t+=512;break;case"ignore":case"body":t+=this[r4](e,t);break;case"meta":t+=this[r9](e,t);break;default:throw Error("invalid state: "+this[rG])}t{let t=e.length-1,i=-1;for(;t>-1&&"/"===e.charAt(t);)i=t,t--;return -1===i?e:e.slice(0,i)},nD=(e,t)=>{let i=new Map(t.map(e=>[nd(e),!0])),r=e.filter,n=(e,t="")=>{let r,s=t||(0,td.parse)(e).root||".";if(e===s)r=!1;else{let t=i.get(e);r=void 0!==t?t:n((0,td.dirname)(e),s)}return i.set(e,r),r};e.filter=r?(e,t)=>r(e,t)&&n(nd(e)):e=>n(nd(e))},nf=i3(t=>{let i,r=new nc(t),n=t.file;try{i=e.openSync(n,"r");let s=e.fstatSync(i),o=t.maxReadSize||0x1000000;if(s.size{let r=new nc(t),n=t.maxReadSize||0x1000000,s=t.file;return new Promise((t,i)=>{r.on("error",i),r.on("end",t),e.stat(s,(e,t)=>{if(e)i(e);else{let e=new iK(s,{readSize:n,size:t.size});e.on("error",i),e.pipe(r)}})})},e=>new nc(e),e=>new nc(e),(e,t)=>{t?.length&&nD(e,t),e.noResume||(e=>{let t=e.onReadEntry;e.onReadEntry=t?e=>{t(e),e.resume()}:e=>e.resume()})(e)}),np=(e,t,i)=>(e&=4095,i&&(e=(384|e)&-19),t&&(256&e&&(e|=64),32&e&&(e|=8),4&e&&(e|=1)),e),{isAbsolute:nm,parse:ng}=p,nE=e=>{let t="",i=ng(e);for(;nm(e)||i.root;){let r="/"===e.charAt(0)&&"//?/"!==e.slice(0,4)?"/":i.root;e=e.slice(r.length),t+=r,i=ng(e)}return[t,e]},nb=["|","<",">","?",":"],ny=nb.map(e=>String.fromCharCode(61440+e.charCodeAt(0))),nF=new Map(nb.map((e,t)=>[e,ny[t]])),nC=new Map(ny.map((e,t)=>[e,nb[t]])),nv=e=>nb.reduce((e,t)=>e.split(t).join(nF.get(t)),e),nw=(e,t)=>t?(e=r$(e).replace(/^\.(\/|$)/,""),nd(t)+"/"+e):r$(e),n_=Symbol("process"),nS=Symbol("file"),nA=Symbol("directory"),nR=Symbol("symlink"),nO=Symbol("hardlink"),nB=Symbol("header"),nx=Symbol("read"),nN=Symbol("lstat"),nI=Symbol("onlstat"),nT=Symbol("onread"),nL=Symbol("onreadlink"),nk=Symbol("openfile"),nM=Symbol("onopenfile"),n$=Symbol("close"),nj=Symbol("mode"),nP=Symbol("awaitDrain"),nz=Symbol("ondrain"),nU=Symbol("prefix");class nH extends iy{path;portable;myuid=process.getuid&&process.getuid()||0;myuser=process.env.USER||"";maxReadSize;linkCache;statCache;preservePaths;cwd;strict;mtime;noPax;noMtime;prefix;fd;blockLen=0;blockRemain=0;buf;pos=0;remain=0;length=0;offset=0;win32;absolute;header;type;linkpath;stat;onWriteEntry;#d=!1;constructor(e,t={}){let i=i2(t);super(),this.path=r$(e),this.portable=!!i.portable,this.maxReadSize=i.maxReadSize||0x1000000,this.linkCache=i.linkCache||new Map,this.statCache=i.statCache||new Map,this.preservePaths=!!i.preservePaths,this.cwd=r$(i.cwd||process.cwd()),this.strict=!!i.strict,this.noPax=!!i.noPax,this.noMtime=!!i.noMtime,this.mtime=i.mtime,this.prefix=i.prefix?r$(i.prefix):void 0,this.onWriteEntry=i.onWriteEntry,"function"==typeof i.onwarn&&this.on("warn",i.onwarn);let r=!1;if(!this.preservePaths){let[e,t]=nE(this.path);e&&"string"==typeof t&&(this.path=t,r=e)}if(this.win32=!!i.win32||"win32"===process.platform,this.win32){let t;this.path=(t=this.path.replace(/\\/g,"/"),ny.reduce((e,t)=>e.split(t).join(nC.get(t)),t)),e=e.replace(/\\/g,"/")}this.absolute=r$(i.absolute||td.default.resolve(this.cwd,e)),""===this.path&&(this.path="./"),r&&this.warn("TAR_ENTRY_INFO",`stripping ${r} from absolute path`,{entry:this,path:r+this.path});let n=this.statCache.get(this.absolute);n?this[nI](n):this[nN]()}warn(e,t,i={}){return rP(this,e,t,i)}emit(e,...t){return"error"===e&&(this.#d=!0),super.emit(e,...t)}[nN](){tD.default.lstat(this.absolute,(e,t)=>{if(e)return this.emit("error",e);this[nI](t)})}[nI](e){this.statCache.set(this.absolute,e),this.stat=e,e.isFile()||(e.size=0),this.type=nW(e),this.emit("stat",e),this[n_]()}[n_](){switch(this.type){case"File":return this[nS]();case"Directory":return this[nA]();case"SymbolicLink":return this[nR]();default:return this.end()}}[nj](e){return np(e,"Directory"===this.type,this.portable)}[nU](e){return nw(e,this.prefix)}[nB](){if(!this.stat)throw Error("cannot write header before stat");"Directory"===this.type&&this.portable&&(this.noMtime=!0),this.onWriteEntry?.(this),this.header=new rb({path:this[nU](this.path),linkpath:"Link"===this.type&&void 0!==this.linkpath?this[nU](this.linkpath):this.linkpath,mode:this[nj](this.stat.mode),uid:this.portable?void 0:this.stat.uid,gid:this.portable?void 0:this.stat.gid,size:this.stat.size,mtime:this.noMtime?void 0:this.mtime||this.stat.mtime,type:"Unsupported"===this.type?void 0:this.type,uname:this.portable?void 0:this.stat.uid===this.myuid?this.myuser:"",atime:this.portable?void 0:this.stat.atime,ctime:this.portable?void 0:this.stat.ctime}),this.header.encode()&&!this.noPax&&super.write(new rT({atime:this.portable?void 0:this.header.atime,ctime:this.portable?void 0:this.header.ctime,gid:this.portable?void 0:this.header.gid,mtime:this.noMtime?void 0:this.mtime||this.header.mtime,path:this[nU](this.path),linkpath:"Link"===this.type&&void 0!==this.linkpath?this[nU](this.linkpath):this.linkpath,size:this.header.size,uid:this.portable?void 0:this.header.uid,uname:this.portable?void 0:this.header.uname,dev:this.portable?void 0:this.stat.dev,ino:this.portable?void 0:this.stat.ino,nlink:this.portable?void 0:this.stat.nlink}).encode());let e=this.header?.block;if(!e)throw Error("failed to encode header");super.write(e)}[nA](){if(!this.stat)throw Error("cannot create directory entry without stat");"/"!==this.path.slice(-1)&&(this.path+="/"),this.stat.size=0,this[nB](),this.end()}[nR](){tD.default.readlink(this.absolute,(e,t)=>{if(e)return this.emit("error",e);this[nL](t)})}[nL](e){this.linkpath=r$(e),this[nB](),this.end()}[nO](e){if(!this.stat)throw Error("cannot create link entry without stat");this.type="Link",this.linkpath=r$(td.default.relative(this.cwd,e)),this.stat.size=0,this[nB](),this.end()}[nS](){if(!this.stat)throw Error("cannot create file entry without stat");if(this.stat.nlink>1){let e=`${this.stat.dev}:${this.stat.ino}`,t=this.linkCache.get(e);if(t?.indexOf(this.cwd)===0)return this[nO](t);this.linkCache.set(e,this.absolute)}if(this[nB](),0===this.stat.size)return this.end();this[nk]()}[nk](){tD.default.open(this.absolute,"r",(e,t)=>{if(e)return this.emit("error",e);this[nM](t)})}[nM](e){if(this.fd=e,this.#d)return this[n$]();if(!this.stat)throw Error("should stat before calling onopenfile");this.blockLen=512*Math.ceil(this.stat.size/512),this.blockRemain=this.blockLen;let t=Math.min(this.blockLen,this.maxReadSize);this.buf=Buffer.allocUnsafe(t),this.offset=0,this.pos=0,this.remain=this.stat.size,this.length=this.buf.length,this[nx]()}[nx](){let{fd:e,buf:t,offset:i,length:r,pos:n}=this;if(void 0===e||void 0===t)throw Error("cannot read file without first opening");tD.default.read(e,t,i,r,n,(e,t)=>{if(e)return this[n$](()=>this.emit("error",e));this[nT](t)})}[n$](e=()=>{}){void 0!==this.fd&&tD.default.close(this.fd,e)}[nT](e){if(e<=0&&this.remain>0){let e=Object.assign(Error("encountered unexpected EOF"),{path:this.absolute,syscall:"read",code:"EOF"});return this[n$](()=>this.emit("error",e))}if(e>this.remain){let e=Object.assign(Error("did not encounter expected EOF"),{path:this.absolute,syscall:"read",code:"EOF"});return this[n$](()=>this.emit("error",e))}if(!this.buf)throw Error("should have created buffer prior to reading");if(e===this.remain)for(let t=e;tthis[nz]())}[nP](e){this.once("drain",e)}write(e,t,i){if("function"==typeof t&&(i=t,t=void 0),"string"==typeof e&&(e=Buffer.from(e,"string"==typeof t?t:"utf8")),this.blockRemaine?this.emit("error",e):this.end());if(!this.buf)throw Error("buffer lost somehow in ONDRAIN");this.offset>=this.length&&(this.buf=Buffer.allocUnsafe(Math.min(this.blockRemain,this.buf.length)),this.offset=0),this.length=this.buf.length-this.offset,this[nx]()}}class nG extends nH{sync=!0;[nN](){this[nI](tD.default.lstatSync(this.absolute))}[nR](){this[nL](tD.default.readlinkSync(this.absolute))}[nk](){this[nM](tD.default.openSync(this.absolute,"r"))}[nx](){let e=!0;try{let{fd:t,buf:i,offset:r,length:n,pos:s}=this;if(void 0===t||void 0===i)throw Error("fd and buf must be set in READ method");let o=tD.default.readSync(t,i,r,n,s);this[nT](o),e=!1}finally{if(e)try{this[n$](()=>{})}catch(e){}}}[nP](e){e()}[n$](e=()=>{}){void 0!==this.fd&&tD.default.closeSync(this.fd),e()}}class nZ extends iy{blockLen=0;blockRemain=0;buf=0;pos=0;remain=0;length=0;preservePaths;portable;strict;noPax;noMtime;readEntry;type;prefix;path;mode;uid;gid;uname;gname;header;mtime;atime;ctime;linkpath;size;onWriteEntry;warn(e,t,i={}){return rP(this,e,t,i)}constructor(e,t={}){let i=i2(t);super(),this.preservePaths=!!i.preservePaths,this.portable=!!i.portable,this.strict=!!i.strict,this.noPax=!!i.noPax,this.noMtime=!!i.noMtime,this.onWriteEntry=i.onWriteEntry,this.readEntry=e;let{type:r}=e;if("Unsupported"===r)throw Error("writing entry that should be ignored");this.type=r,"Directory"===this.type&&this.portable&&(this.noMtime=!0),this.prefix=i.prefix,this.path=r$(e.path),this.mode=void 0!==e.mode?this[nj](e.mode):void 0,this.uid=this.portable?void 0:e.uid,this.gid=this.portable?void 0:e.gid,this.uname=this.portable?void 0:e.uname,this.gname=this.portable?void 0:e.gname,this.size=e.size,this.mtime=this.noMtime?void 0:i.mtime||e.mtime,this.atime=this.portable?void 0:e.atime,this.ctime=this.portable?void 0:e.ctime,this.linkpath=void 0!==e.linkpath?r$(e.linkpath):void 0,"function"==typeof i.onwarn&&this.on("warn",i.onwarn);let n=!1;if(!this.preservePaths){let[e,t]=nE(this.path);e&&"string"==typeof t&&(this.path=t,n=e)}this.remain=e.size,this.blockRemain=e.startBlockSize,this.onWriteEntry?.(this),this.header=new rb({path:this[nU](this.path),linkpath:"Link"===this.type&&void 0!==this.linkpath?this[nU](this.linkpath):this.linkpath,mode:this.mode,uid:this.portable?void 0:this.uid,gid:this.portable?void 0:this.gid,size:this.size,mtime:this.noMtime?void 0:this.mtime,type:this.type,uname:this.portable?void 0:this.uname,atime:this.portable?void 0:this.atime,ctime:this.portable?void 0:this.ctime}),n&&this.warn("TAR_ENTRY_INFO",`stripping ${n} from absolute path`,{entry:this,path:n+this.path}),this.header.encode()&&!this.noPax&&super.write(new rT({atime:this.portable?void 0:this.atime,ctime:this.portable?void 0:this.ctime,gid:this.portable?void 0:this.gid,mtime:this.noMtime?void 0:this.mtime,path:this[nU](this.path),linkpath:"Link"===this.type&&void 0!==this.linkpath?this[nU](this.linkpath):this.linkpath,size:this.size,uid:this.portable?void 0:this.uid,uname:this.portable?void 0:this.uname,dev:this.portable?void 0:this.readEntry.dev,ino:this.portable?void 0:this.readEntry.ino,nlink:this.portable?void 0:this.readEntry.nlink}).encode());let s=this.header?.block;if(!s)throw Error("failed to encode header");super.write(s),e.pipe(this)}[nU](e){return nw(e,this.prefix)}[nj](e){return np(e,"Directory"===this.type,this.portable)}write(e,t,i){"function"==typeof t&&(i=t,t=void 0),"string"==typeof e&&(e=Buffer.from(e,"string"==typeof t?t:"utf8"));let r=e.length;if(r>this.blockRemain)throw Error("writing more to entry than is appropriate");return this.blockRemain-=r,super.write(e,i)}end(e,t,i){return this.blockRemain&&super.write(Buffer.alloc(this.blockRemain)),"function"==typeof e&&(i=e,t=void 0,e=void 0),"function"==typeof t&&(i=t,t=void 0),"string"==typeof e&&(e=Buffer.from(e,t??"utf8")),i&&this.once("finish",i),e?super.end(e,i):super.end(i),this}}let nW=e=>e.isFile()?"File":e.isDirectory()?"Directory":e.isSymbolicLink()?"SymbolicLink":"Unsupported";class nV{tail;head;length=0;static create(e=[]){return new nV(e)}constructor(e=[]){for(let t of e)this.push(t)}*[Symbol.iterator](){for(let e=this.head;e;e=e.next)yield e.value}removeNode(e){if(e.list!==this)throw Error("removing node which does not belong to this list");let t=e.next,i=e.prev;return t&&(t.prev=i),i&&(i.next=t),e===this.head&&(this.head=t),e===this.tail&&(this.tail=i),this.length--,e.next=void 0,e.prev=void 0,e.list=void 0,t}unshiftNode(e){if(e===this.head)return;e.list&&e.list.removeNode(e);let t=this.head;e.list=this,e.next=t,t&&(t.prev=e),this.head=e,this.tail||(this.tail=e),this.length++}pushNode(e){if(e===this.tail)return;e.list&&e.list.removeNode(e);let t=this.tail;e.list=this,e.prev=t,t&&(t.next=e),this.tail=e,this.head||(this.head=e),this.length++}push(...e){for(let i=0,r=e.length;i1)i=t;else if(this.head)r=this.head.next,i=this.head.value;else throw TypeError("Reduce of empty list with no initial value");for(var n=0;r;n++)i=e(i,r.value,n),r=r.next;return i}reduceReverse(e,t){let i,r=this.tail;if(arguments.length>1)i=t;else if(this.tail)r=this.tail.prev,i=this.tail.value;else throw TypeError("Reduce of empty list with no initial value");for(let t=this.length-1;r;t--)i=e(i,r.value,t),r=r.prev;return i}toArray(){let e=Array(this.length);for(let t=0,i=this.head;i;t++)e[t]=i.value,i=i.next;return e}toArrayReverse(){let e=Array(this.length);for(let t=0,i=this.tail;i;t++)e[t]=i.value,i=i.prev;return e}slice(e=0,t=this.length){t<0&&(t+=this.length),e<0&&(e+=this.length);let i=new nV;if(tthis.length&&(t=this.length);let r=this.head,n=0;for(n=0;r&&nthis.length&&(t=this.length);let r=this.length,n=this.tail;for(;n&&r>t;r--)n=n.prev;for(;n&&r>e;r--,n=n.prev)i.push(n.value);return i}splice(e,t=0,...i){e>this.length&&(e=this.length-1),e<0&&(e=this.length+e);let r=this.head;for(let t=0;r&&t1)throw TypeError("gzip, brotli, zstd are mutually exclusive");if(e.gzip&&("object"!=typeof e.gzip&&(e.gzip={}),this.portable&&(e.gzip.portable=!0),this.zip=new ro(e.gzip)),e.brotli&&("object"!=typeof e.brotli&&(e.brotli={}),this.zip=new rl(e.brotli)),e.zstd&&("object"!=typeof e.zstd&&(e.zstd={}),this.zip=new rd(e.zstd)),!this.zip)throw Error("impossible");let t=this.zip;t.on("data",e=>super.write(e)),t.on("end",()=>super.end()),t.on("drain",()=>this[so]()),this.on("resume",()=>t.resume())}else this.on("drain",this[so]);this.noDirRecurse=!!e.noDirRecurse,this.follow=!!e.follow,this.noMtime=!!e.noMtime,e.mtime&&(this.mtime=e.mtime),this.filter="function"==typeof e.filter?e.filter:()=>!0,this[nQ]=new nV,this[n8]=0,this.jobs=Number(e.jobs)||4,this[n2]=!1,this[nJ]=!1}[ss](e){return super.write(e)}add(e){return this.write(e),this}end(e,t,i){return"function"==typeof e&&(i=e,e=void 0),"function"==typeof t&&(i=t,t=void 0),e&&this.add(e),this[nJ]=!0,this[n1](),i&&i(),this}write(e){if(this[nJ])throw Error("write after end");return e instanceof rj?this[n4](e):this[n5](e),this.flowing}[n4](e){let t=r$(td.default.resolve(this.cwd,e.path));if(this.filter(e.path,e)){let i=new nX(e.path,t);i.entry=new nZ(e,this[sr](i)),i.entry.on("end",()=>this[n6](i)),this[n8]+=1,this[nQ].push(i)}else e.resume();this[n1]()}[n5](e){let t=r$(td.default.resolve(this.cwd,e));this[nQ].push(new nX(e,t)),this[n1]()}[n9](e){e.pending=!0,this[n8]+=1;let t=this.follow?"stat":"lstat";tD.default[t](e.absolute,(t,i)=>{e.pending=!1,this[n8]-=1,t?this.emit("error",t):this[nq](e,i)})}[nq](e,t){this.statCache.set(e.absolute,t),e.stat=t,this.filter(e.path,t)||(e.ignore=!0),this[n1]()}[n7](e){e.pending=!0,this[n8]+=1,tD.default.readdir(e.absolute,(t,i)=>{if(e.pending=!1,this[n8]-=1,t)return this.emit("error",t);this[se](e,i)})}[se](e,t){this.readdirCache.set(e.absolute,t),e.readdir=t,this[n1]()}[n1](){if(!this[n2]){this[n2]=!0;for(let e=this[nQ].head;e&&this[n8]this.warn(e,t,i),noPax:this.noPax,cwd:this.cwd,absolute:e.absolute,preservePaths:this.preservePaths,maxReadSize:this.maxReadSize,strict:this.strict,portable:this.portable,linkCache:this.linkCache,statCache:this.statCache,noMtime:this.noMtime,mtime:this.mtime,prefix:this.prefix,onWriteEntry:this.onWriteEntry}}[si](e){this[n8]+=1;try{return new this[sn](e.path,this[sr](e)).on("end",()=>this[n6](e)).on("error",e=>this.emit("error",e))}catch(e){this.emit("error",e)}}[so](){this[n0]&&this[n0].entry&&this[n0].entry.resume()}[st](e){e.piped=!0,e.readdir&&e.readdir.forEach(t=>{let i=e.path,r="./"===i?"":i.replace(/\/*$/,"/");this[n5](r+t)});let t=e.entry,i=this.zip;if(!t)throw Error("cannot pipe without source");i?t.on("data",e=>{i.write(e)||t.pause()}):t.on("data",e=>{super.write(e)||t.pause()})}pause(){return this.zip&&this.zip.pause(),super.pause()}warn(e,t,i={}){rP(this,e,t,i)}}class sa extends su{sync=!0;constructor(e){super(e),this[sn]=nG}pause(){}resume(){}[n9](e){let t=this.follow?"statSync":"lstatSync";this[nq](e,tD.default[t](e.absolute))}[n7](e){this[se](e,tD.default.readdirSync(e.absolute))}[st](e){let t=e.entry,i=this.zip;if(e.readdir&&e.readdir.forEach(t=>{let i=e.path,r="./"===i?"":i.replace(/\/*$/,"/");this[n5](r+t)}),!t)throw Error("Cannot pipe without source");i?t.on("data",e=>{i.write(e)}):t.on("data",e=>{super[ss](e)})}}let sl=(e,t)=>{t.forEach(t=>{"@"===t.charAt(0)?nf({file:u.resolve(e.cwd,t.slice(1)),sync:!0,noResume:!0,onReadEntry:t=>e.add(t)}):e.add(t)}),e.end()},sh=async(e,t)=>{for(let i=0;i{e.add(t)}}):e.add(r)}e.end()};i3((e,t)=>{let i=new sa(e),r=new iQ(e.file,{mode:e.mode||438});i.pipe(r),sl(i,t)},(e,t)=>{let i=new su(e),r=new iJ(e.file,{mode:e.mode||438});i.pipe(r);let n=new Promise((e,t)=>{r.on("error",t),r.on("close",e),i.on("error",t)});return sh(i,t),n},(e,t)=>{let i=new sa(e);return sl(i,t),i},(e,t)=>{let i=new su(e);return sh(i,t),i},(e,t)=>{if(!t?.length)throw TypeError("no paths specified to add to archive")});let sc=process.env.__FAKE_PLATFORM__||process.platform,{O_CREAT:sd,O_TRUNC:sD,O_WRONLY:sf}=tD.default.constants,sp=Number(process.env.__FAKE_FS_O_FILENAME__)||tD.default.constants.UV_FS_O_FILEMAP||0,sm=sp|sD|sd|sf,sg="win32"===sc&&sp?e=>e<524288?sm:"w":()=>"w",sE=(t,i,r)=>{try{return e.lchownSync(t,i,r)}catch(e){if(e?.code!=="ENOENT")throw e}},sb=(t,i,r,n)=>{e.lchown(t,i,r,e=>{n(e&&e?.code!=="ENOENT"?e:null)})},sy=(e,t,i,r,n)=>{t.isDirectory()?sF(u.resolve(e,t.name),i,r,s=>{if(s)return n(s);sb(u.resolve(e,t.name),i,r,n)}):sb(u.resolve(e,t.name),i,r,n)},sF=(t,i,r,n)=>{e.readdir(t,{withFileTypes:!0},(e,s)=>{if(e){if("ENOENT"===e.code)return n();else if("ENOTDIR"!==e.code&&"ENOTSUP"!==e.code)return n(e)}if(e||!s.length)return sb(t,i,r,n);let o=s.length,u=null,a=e=>{if(!u){if(e)return n(u=e);if(0==--o)return sb(t,i,r,n)}};for(let e of s)sy(t,e,i,r,a)})},sC=(e,t,i,r)=>{t.isDirectory()&&sv(u.resolve(e,t.name),i,r),sE(u.resolve(e,t.name),i,r)},sv=(t,i,r)=>{let n;try{n=e.readdirSync(t,{withFileTypes:!0})}catch(e){if(e?.code==="ENOENT")return;if(e?.code==="ENOTDIR"||e?.code==="ENOTSUP")return sE(t,i,r);throw e}for(let e of n)sC(t,e,i,r);return sE(t,i,r)};class sw extends Error{path;code;syscall="chdir";constructor(e,t){super(`${t}: Cannot cd into '${e}'`),this.path=e,this.code=t}get name(){return"CwdError"}}class s_ extends Error{path;symlink;syscall="symlink";code="TAR_SYMLINK_ERROR";constructor(e,t){super("TAR_SYMLINK_ERROR: Cannot extract through symbolic link"),this.symlink=e,this.path=t}get name(){return"SymlinkError"}}let sS=(t,i,r,n,s,o,a)=>{if(!i.length)return a(null,o);let l=i.shift(),h=r$(u.resolve(t+"/"+l));e.mkdir(h,r,sA(h,i,r,n,s,o,a))},sA=(t,i,r,n,s,o,u)=>a=>{a?e.lstat(t,(l,h)=>{if(l)l.path=l.path&&r$(l.path),u(l);else if(h.isDirectory())sS(t,i,r,n,s,o,u);else if(n)e.unlink(t,a=>{if(a)return u(a);e.mkdir(t,r,sA(t,i,r,n,s,o,u))});else{if(h.isSymbolicLink())return u(new s_(t,t+"/"+i.join("/")));u(a)}}):(o=o||t,sS(t,i,r,n,s,o,u))},sR=Object.create(null),sO=new Set,sB="win32"===(process.env.TESTING_TAR_FAKE_PLATFORM||process.platform);class sx{#D=new Map;#f=new Map;#p=new Set;reserve(e,t){let i=new Set((e=sB?["win32 parallelization disabled"]:e.map(e=>nd(d((e=>{sO.has(e)?sO.delete(e):sR[e]=e.normalize("NFD"),sO.add(e);let t=sR[e],i=sO.size-1e4;if(i>1e3){for(let e of sO)if(sO.delete(e),delete sR[e],--i<=0)break}return t})(e))).toLowerCase())).map(e=>e.split("/").slice(0,-1).reduce((e,t)=>{let i=e[e.length-1];return void 0!==i&&(t=d(i,t)),e.push(t||"/"),e},[])).reduce((e,t)=>e.concat(t)));for(let r of(this.#f.set(t,{dirs:i,paths:e}),e)){let e=this.#D.get(r);e?e.push(t):this.#D.set(r,[t])}for(let e of i){let i=this.#D.get(e);if(i){let e=i[i.length-1];e instanceof Set?e.add(t):i.push(new Set([t]))}else this.#D.set(e,[new Set([t])])}return this.#m(t)}#g(e){let t=this.#f.get(e);if(!t)throw Error("function does not have any path reservations");return{paths:t.paths.map(e=>this.#D.get(e)),dirs:[...t.dirs].map(e=>this.#D.get(e))}}check(e){let{paths:t,dirs:i}=this.#g(e);return t.every(t=>t&&t[0]===e)&&i.every(t=>t&&t[0]instanceof Set&&t[0].has(e))}#m(e){return!this.#p.has(e)&&!!this.check(e)&&(this.#p.add(e),e(()=>this.#E(e)),!0)}#E(e){if(!this.#p.has(e))return!1;let t=this.#f.get(e);if(!t)throw Error("invalid reservation");let{paths:i,dirs:r}=t,n=new Set;for(let t of i){let i=this.#D.get(t);if(!i||i?.[0]!==e)continue;let r=i[1];if(!r){this.#D.delete(t);continue}if(i.shift(),"function"==typeof r)n.add(r);else for(let e of r)n.add(e)}for(let t of r){let i=this.#D.get(t),r=i?.[0];if(i&&r instanceof Set)if(1===r.size&&1===i.length){this.#D.delete(t);continue}else if(1===r.size){i.shift();let e=i[0];"function"==typeof e&&n.add(e)}else r.delete(e)}return this.#p.delete(e),n.forEach(e=>this.#m(e)),!0}}let sN=Symbol("onEntry"),sI=Symbol("checkFs"),sT=Symbol("checkFs2"),sL=Symbol("isReusable"),sk=Symbol("makeFs"),sM=Symbol("file"),s$=Symbol("directory"),sj=Symbol("link"),sP=Symbol("symlink"),sz=Symbol("hardlink"),sU=Symbol("unsupported"),sH=Symbol("checkPath"),sG=Symbol("mkdir"),sZ=Symbol("onError"),sW=Symbol("pending"),sV=Symbol("pend"),sY=Symbol("unpend"),sX=Symbol("ended"),sK=Symbol("maybeClose"),sq=Symbol("skip"),sJ=Symbol("doChown"),sQ=Symbol("uid"),s0=Symbol("gid"),s1=Symbol("checkedCwd"),s2="win32"===(process.env.TESTING_TAR_FAKE_PLATFORM||process.platform),s3=(e,t,i)=>void 0!==e&&e===e>>>0?e:void 0!==t&&t===t>>>0?t:i;class s8 extends nc{[sX]=!1;[s1]=!1;[sW]=0;reservations=new sx;transform;writable=!0;readable=!1;uid;gid;setOwner;preserveOwner;processGid;processUid;maxDepth;forceChown;win32;newer;keep;noMtime;preservePaths;unlink;cwd;strip;processUmask;umask;dmode;fmode;chmod;constructor(e={}){if(e.ondone=()=>{this[sX]=!0,this[sK]()},super(e),this.transform=e.transform,this.chmod=!!e.chmod,"number"==typeof e.uid||"number"==typeof e.gid){if("number"!=typeof e.uid||"number"!=typeof e.gid)throw TypeError("cannot set owner without number uid and gid");if(e.preserveOwner)throw TypeError("cannot preserve owner in archive and also set owner explicitly");this.uid=e.uid,this.gid=e.gid,this.setOwner=!0}else this.uid=void 0,this.gid=void 0,this.setOwner=!1;void 0===e.preserveOwner&&"number"!=typeof e.uid?this.preserveOwner=!!(process.getuid&&0===process.getuid()):this.preserveOwner=!!e.preserveOwner,this.processUid=(this.preserveOwner||this.setOwner)&&process.getuid?process.getuid():void 0,this.processGid=(this.preserveOwner||this.setOwner)&&process.getgid?process.getgid():void 0,this.maxDepth="number"==typeof e.maxDepth?e.maxDepth:1024,this.forceChown=!0===e.forceChown,this.win32=!!e.win32||s2,this.newer=!!e.newer,this.keep=!!e.keep,this.noMtime=!!e.noMtime,this.preservePaths=!!e.preservePaths,this.unlink=!!e.unlink,this.cwd=r$(u.resolve(e.cwd||process.cwd())),this.strip=Number(e.strip)||0,this.processUmask=this.chmod?"number"==typeof e.processUmask?e.processUmask:process.umask():0,this.umask="number"==typeof e.umask?e.umask:this.processUmask,this.dmode=e.dmode||511&~this.umask,this.fmode=e.fmode||438&~this.umask,this.on("entry",e=>this[sN](e))}warn(e,t,i={}){return("TAR_BAD_ARCHIVE"===e||"TAR_ABORT"===e)&&(i.recoverable=!1),super.warn(e,t,i)}[sK](){this[sX]&&0===this[sW]&&(this.emit("prefinish"),this.emit("finish"),this.emit("end"))}[sH](e){let t=r$(e.path),i=t.split("/");if(this.strip){if(i.length=this.strip))return!1;e.linkpath=t.slice(this.strip).join("/")}i.splice(0,this.strip),e.path=i.join("/")}if(isFinite(this.maxDepth)&&i.length>this.maxDepth)return this.warn("TAR_ENTRY_ERROR","path excessively deep",{entry:e,path:t,depth:i.length,maxDepth:this.maxDepth}),!1;if(!this.preservePaths){if(i.includes("..")||s2&&/^[a-z]:\.\.$/i.test(i[0]??""))return this.warn("TAR_ENTRY_ERROR","path contains '..'",{entry:e,path:t}),!1;let[r,n]=nE(t);r&&(e.path=String(n),this.warn("TAR_ENTRY_INFO",`stripping ${r} from absolute path`,{entry:e,path:t}))}if(u.isAbsolute(e.path)?e.absolute=r$(u.resolve(e.path)):e.absolute=r$(u.resolve(this.cwd,e.path)),!this.preservePaths&&"string"==typeof e.absolute&&0!==e.absolute.indexOf(this.cwd+"/")&&e.absolute!==this.cwd)return this.warn("TAR_ENTRY_ERROR","path escaped extraction target",{entry:e,path:r$(e.path),resolvedPath:e.absolute,cwd:this.cwd}),!1;if(e.absolute===this.cwd&&"Directory"!==e.type&&"GNUDumpDir"!==e.type)return!1;if(this.win32){let{root:t}=u.win32.parse(String(e.absolute));e.absolute=t+nv(String(e.absolute).slice(t.length));let{root:i}=u.win32.parse(e.path);e.path=i+nv(e.path.slice(i.length))}return!0}[sN](e){if(!this[sH](e))return e.resume();switch(z.equal(typeof e.absolute,"string"),e.type){case"Directory":case"GNUDumpDir":e.mode&&(e.mode=448|e.mode);case"File":case"OldFile":case"ContiguousFile":case"Link":case"SymbolicLink":return this[sI](e);default:return this[sU](e)}}[sZ](e,t){"CwdError"===e.name?this.emit("error",e):(this.warn("TAR_ENTRY_ERROR",e,{entry:t}),this[sY](),t.resume())}[sG](t,i,r){((t,i,r)=>{t=r$(t);let n=i.umask??18,s=448|i.mode,o=(s&n)!=0,a=i.uid,l=i.gid,h="number"==typeof a&&"number"==typeof l&&(a!==i.processUid||l!==i.processGid),c=i.preserve,d=i.unlink,D=r$(i.cwd),f=(i,n)=>{i?r(i):n&&h?sF(n,a,l,e=>f(e)):o?e.chmod(t,s,r):r()};if(t===D){var p;return p=t,e.stat(p,(e,t)=>{(e||!t.isDirectory())&&(e=new sw(p,e?.code||"ENOTDIR")),f(e)})}if(c)return R.mkdir(t,{mode:s,recursive:!0}).then(e=>f(null,e??void 0),f);let m=r$(u.relative(D,t)).split("/");sS(D,m,s,d,D,void 0,f)})(r$(t),{uid:this.uid,gid:this.gid,processUid:this.processUid,processGid:this.processGid,umask:this.processUmask,preserve:this.preservePaths,unlink:this.unlink,cwd:this.cwd,mode:i},r)}[sJ](e){return this.forceChown||this.preserveOwner&&("number"==typeof e.uid&&e.uid!==this.processUid||"number"==typeof e.gid&&e.gid!==this.processGid)||"number"==typeof this.uid&&this.uid!==this.processUid||"number"==typeof this.gid&&this.gid!==this.processGid}[sQ](e){return s3(this.uid,e.uid,this.processUid)}[s0](e){return s3(this.gid,e.gid,this.processGid)}[sM](t,i){let r="number"==typeof t.mode?4095&t.mode:this.fmode,n=new iJ(String(t.absolute),{flags:sg(t.size),mode:r,autoClose:!1});n.on("error",r=>{n.fd&&e.close(n.fd,()=>{}),n.write=()=>!0,this[sZ](r,t),i()});let s=1,o=r=>{if(r){n.fd&&e.close(n.fd,()=>{}),this[sZ](r,t),i();return}0==--s&&void 0!==n.fd&&e.close(n.fd,e=>{e?this[sZ](e,t):this[sY](),i()})};n.on("finish",()=>{let i=String(t.absolute),r=n.fd;if("number"==typeof r&&t.mtime&&!this.noMtime){s++;let n=t.atime||new Date,u=t.mtime;e.futimes(r,n,u,t=>t?e.utimes(i,n,u,e=>o(e&&t)):o())}if("number"==typeof r&&this[sJ](t)){s++;let n=this[sQ](t),u=this[s0](t);"number"==typeof n&&"number"==typeof u&&e.fchown(r,n,u,t=>t?e.chown(i,n,u,e=>o(e&&t)):o())}o()});let u=this.transform&&this.transform(t)||t;u!==t&&(u.on("error",e=>{this[sZ](e,t),i()}),t.pipe(u)),u.pipe(n)}[s$](t,i){let r="number"==typeof t.mode?4095&t.mode:this.dmode;this[sG](String(t.absolute),r,r=>{if(r){this[sZ](r,t),i();return}let n=1,s=()=>{0==--n&&(i(),this[sY](),t.resume())};t.mtime&&!this.noMtime&&(n++,e.utimes(String(t.absolute),t.atime||new Date,t.mtime,s)),this[sJ](t)&&(n++,e.chown(String(t.absolute),Number(this[sQ](t)),Number(this[s0](t)),s)),s()})}[sU](e){e.unsupported=!0,this.warn("TAR_ENTRY_UNSUPPORTED",`unsupported entry type: ${e.type}`,{entry:e}),e.resume()}[sP](e,t){this[sj](e,String(e.linkpath),"symlink",t)}[sz](e,t){let i=r$(u.resolve(this.cwd,String(e.linkpath)));this[sj](e,i,"link",t)}[sV](){this[sW]++}[sY](){this[sW]--,this[sK]()}[sq](e){this[sY](),e.resume()}[sL](e,t){return"File"===e.type&&!this.unlink&&t.isFile()&&t.nlink<=1&&!s2}[sI](e){this[sV]();let t=[e.path];e.linkpath&&t.push(e.linkpath),this.reservations.reserve(t,t=>this[sT](e,t))}[sT](t,i){let r=e=>{i(e)},n=()=>{this[sG](this.cwd,this.dmode,e=>{if(e){this[sZ](e,t),r();return}this[s1]=!0,s()})},s=()=>{if(t.absolute!==this.cwd){let e=r$(u.dirname(String(t.absolute)));if(e!==this.cwd)return this[sG](e,this.dmode,e=>{if(e){this[sZ](e,t),r();return}o()})}o()},o=()=>{e.lstat(String(t.absolute),(i,n)=>{if(n&&(this.keep||this.newer&&n.mtime>(t.mtime??n.mtime))){this[sq](t),r();return}if(i||this[sL](t,n))return this[sk](null,t,r);if(n.isDirectory()){if("Directory"===t.type){let i=this.chmod&&t.mode&&(4095&n.mode)!==t.mode,s=e=>this[sk](e??null,t,r);return i?e.chmod(String(t.absolute),Number(t.mode),s):s()}if(t.absolute!==this.cwd)return e.rmdir(String(t.absolute),e=>this[sk](e??null,t,r))}if(t.absolute===this.cwd)return this[sk](null,t,r);((t,i)=>{if(!s2)return e.unlink(t,i);let r=t+".DELETE."+U(16).toString("hex");e.rename(t,r,t=>{if(t)return i(t);e.unlink(r,i)})})(String(t.absolute),e=>this[sk](e??null,t,r))})};this[s1]?s():n()}[sk](e,t,i){if(e){this[sZ](e,t),i();return}switch(t.type){case"File":case"OldFile":case"ContiguousFile":return this[sM](t,i);case"Link":return this[sz](t,i);case"SymbolicLink":return this[sP](t,i);case"Directory":case"GNUDumpDir":return this[s$](t,i)}}[sj](t,i,r,n){e[r](i,String(t.absolute),e=>{e?this[sZ](e,t):(this[sY](),t.resume()),n()})}}let s6=e=>{try{return[null,e()]}catch(e){return[e,null]}};class s5 extends s8{sync=!0;[sk](e,t){return super[sk](e,t,()=>{})}[sI](t){if(!this[s1]){let e=this[sG](this.cwd,this.dmode);if(e)return this[sZ](e,t);this[s1]=!0}if(t.absolute!==this.cwd){let e=r$(u.dirname(String(t.absolute)));if(e!==this.cwd){let i=this[sG](e,this.dmode);if(i)return this[sZ](i,t)}}let[i,r]=s6(()=>e.lstatSync(String(t.absolute)));if(r&&(this.keep||this.newer&&r.mtime>(t.mtime??r.mtime)))return this[sq](t);if(i||this[sL](t,r))return this[sk](null,t);if(r.isDirectory()){if("Directory"===t.type){let[i]=this.chmod&&t.mode&&(4095&r.mode)!==t.mode?s6(()=>{e.chmodSync(String(t.absolute),Number(t.mode))}):[];return this[sk](i,t)}let[i]=s6(()=>e.rmdirSync(String(t.absolute)));this[sk](i,t)}let[n]=t.absolute===this.cwd?[]:s6(()=>(t=>{if(!s2)return e.unlinkSync(t);let i=t+".DELETE."+U(16).toString("hex");e.renameSync(t,i),e.unlinkSync(i)})(String(t.absolute)));this[sk](n,t)}[sM](t,i){let r,n="number"==typeof t.mode?4095&t.mode:this.fmode,s=n=>{let s;try{e.closeSync(r)}catch(e){s=e}(n||s)&&this[sZ](n||s,t),i()};try{r=e.openSync(String(t.absolute),sg(t.size),n)}catch(e){return s(e)}let o=this.transform&&this.transform(t)||t;o!==t&&(o.on("error",e=>this[sZ](e,t)),t.pipe(o)),o.on("data",t=>{try{e.writeSync(r,t,0,t.length)}catch(e){s(e)}}),o.on("end",()=>{let i=null;if(t.mtime&&!this.noMtime){let n=t.atime||new Date,s=t.mtime;try{e.futimesSync(r,n,s)}catch(r){try{e.utimesSync(String(t.absolute),n,s)}catch(e){i=r}}}if(this[sJ](t)){let n=this[sQ](t),s=this[s0](t);try{e.fchownSync(r,Number(n),Number(s))}catch(r){try{e.chownSync(String(t.absolute),Number(n),Number(s))}catch(e){i=i||r}}}s(i)})}[s$](t,i){let r="number"==typeof t.mode?4095&t.mode:this.dmode,n=this[sG](String(t.absolute),r);if(n){this[sZ](n,t),i();return}if(t.mtime&&!this.noMtime)try{e.utimesSync(String(t.absolute),t.atime||new Date,t.mtime)}catch(e){}if(this[sJ](t))try{e.chownSync(String(t.absolute),Number(this[sQ](t)),Number(this[s0](t)))}catch(e){}i(),t.resume()}[sG](t,i){try{return((t,i)=>{let r;t=r$(t);let n=i.umask??18,s=448|i.mode,o=(s&n)!=0,a=i.uid,l=i.gid,h="number"==typeof a&&"number"==typeof l&&(a!==i.processUid||l!==i.processGid),c=i.preserve,d=i.unlink,D=r$(i.cwd),f=i=>{i&&h&&sv(i,a,l),o&&e.chmodSync(t,s)};if(t===D){let t,i=!1;try{i=e.statSync(D).isDirectory()}catch(e){t=e?.code}finally{if(!i)throw new sw(D,t??"ENOTDIR")}return f()}if(c)return f(e.mkdirSync(t,{mode:s,recursive:!0})??void 0);let p=r$(u.relative(D,t)).split("/");for(let t=p.shift(),i=D;t&&(i+="/"+t);t=p.shift()){i=r$(u.resolve(i));try{e.mkdirSync(i,s),r=r||i}catch(n){let t=e.lstatSync(i);if(t.isDirectory())continue;if(d){e.unlinkSync(i),e.mkdirSync(i,s),r=r||i;continue}if(t.isSymbolicLink())return new s_(i,i+"/"+p.join("/"))}}return f(r)})(r$(t),{uid:this.uid,gid:this.gid,processUid:this.processUid,processGid:this.processGid,umask:this.processUmask,preserve:this.preservePaths,unlink:this.unlink,cwd:this.cwd,mode:i})}catch(e){return e}}[sj](t,i,r,n){let s=`${r}Sync`;try{e[s](i,String(t.absolute)),n(),t.resume()}catch(e){return this[sZ](e,t)}}}let s4=i3(t=>{let i=new s5(t),r=t.file,n=e.statSync(r);new iq(r,{readSize:t.maxReadSize||0x1000000,size:n.size}).pipe(i)},(t,i)=>{let r=new s8(t),n=t.maxReadSize||0x1000000,s=t.file;return new Promise((t,i)=>{r.on("error",i),r.on("close",t),e.stat(s,(e,t)=>{if(e)i(e);else{let e=new iK(s,{readSize:n,size:t.size});e.on("error",i),e.pipe(r)}})})},e=>new s5(e),e=>new s8(e),(e,t)=>{t?.length&&nD(e,t)}),s9=(e,t)=>{t.forEach(t=>{"@"===t.charAt(0)?nf({file:u.resolve(e.cwd,t.slice(1)),sync:!0,noResume:!0,onReadEntry:t=>e.add(t)}):e.add(t)}),e.end()},s7=async(e,t)=>{for(let i=0;ie.add(t)}):e.add(r)}e.end()},oe=i3((t,i)=>{let r,n,s=new sa(t),o=!0;try{try{r=e.openSync(t.file,"r+")}catch(i){if(i?.code==="ENOENT")r=e.openSync(t.file,"w+");else throw i}let u=e.fstatSync(r),a=Buffer.alloc(512);e:for(n=0;nu.size)break;n+=s,t.mtimeCache&&i.mtime&&t.mtimeCache.set(String(i.path),i.mtime)}o=!1,((e,t,i,r,n)=>{let s=new iQ(e.file,{fd:r,start:i});t.pipe(s),s9(t,n)})(t,s,n,r,i)}finally{if(o)try{e.closeSync(r)}catch(e){}}},(t,i)=>{i=Array.from(i);let r=new su(t);return new Promise((n,s)=>{r.on("error",s);let o="r+",u=(a,l)=>a&&"ENOENT"===a.code&&"r+"===o?(o="w+",e.open(t.file,o,u)):a||!l?s(a):void e.fstat(l,(o,u)=>{if(o)return e.close(l,()=>s(o));((i,r,n)=>{let s=(t,r)=>{t?e.close(i,e=>n(t)):n(null,r)},o=0;if(0===r)return s(null,0);let u=0,a=Buffer.alloc(512),l=(n,h)=>{if(n||void 0===h)return s(n);if((u+=h)<512&&h)return e.read(i,a,u,a.length-u,o+u,l);if(0===o&&31===a[0]&&139===a[1])return s(Error("cannot append to compressed archives"));if(u<512)return s(null,o);let c=new rb(a);if(!c.cksumValid)return s(null,o);let d=512*Math.ceil((c.size??0)/512);if(o+d+512>r||(o+=d+512)>=r)return s(null,o);t.mtimeCache&&c.mtime&&t.mtimeCache.set(String(c.path),c.mtime),u=0,e.read(i,a,0,512,o,l)};e.read(i,a,0,512,o,l)})(l,u.size,(e,o)=>{if(e)return s(e);let u=new iJ(t.file,{fd:l,start:o});r.pipe(u),u.on("error",s),u.on("close",n),s7(r,i)})});e.open(t.file,o,u)})},()=>{throw TypeError("file is required")},()=>{throw TypeError("file is required")},(e,t)=>{if(!e.file)throw TypeError("file is required");if(e.gzip||e.brotli||e.zstd||e.file.endsWith(".br")||e.file.endsWith(".tbr"))throw TypeError("cannot append to compressed archives");if(!t?.length)throw TypeError("no paths specified to add/replace")});i3(oe.syncFile,oe.asyncFile,oe.syncNoFile,oe.asyncNoFile,(e,t=[])=>{oe.validate?.(e,t),ot(e)});let ot=e=>{let t=e.filter;e.mtimeCache||(e.mtimeCache=new Map),e.filter=t?(i,r)=>t(i,r)&&!((e.mtimeCache?.get(i)??r.mtime??0)>(r.mtime??0)):(t,i)=>!((e.mtimeCache?.get(t)??i.mtime??0)>(i.mtime??0))};async function oi(e,t){if(!await on())return void te.info("Git client not found, skipping git initialization");if(await os(e))return void te.debug("Git repo already initialized, skipping git initialization");let i=tl();i.start("Initializing git repo");let r=`Initial commit
+
+Generated by rock${t?`@${t}`:""}.`;await or(e,r),i.stop("Git repo initialized.")}async function or(e,t){try{await tz("git",["init"],{cwd:e}),await tz("git",["branch","-M","main"],{cwd:e}),await tz("git",["add","."],{cwd:e}),await tz("git",["commit","-m",t],{cwd:e})}catch(e){te.warn("Failed to initialize git repository",e)}}async function on(){try{return await tz("git",["--version"],{stdio:"ignore"}),!0}catch{return!1}}async function os(e){try{return await tz("git",["rev-parse","--is-inside-work-tree"],{stdio:"ignore",cwd:e}),!0}catch{return!1}}let oo=[{type:"npm",name:"default",displayName:"default",packageName:"@rock-js/template-default",version:"latest",directory:"."}],ou=[{type:"npm",name:"brownfield-ios",displayName:"Brownfield iOS",packageName:"@rock-js/plugin-brownfield-ios",hint:"Setup packaging React Native app as a XCFramework",version:"latest",directory:"template",importName:"pluginBrownfieldIos"},{type:"npm",name:"brownfield-android",displayName:"Brownfield Android",packageName:"@rock-js/plugin-brownfield-android",hint:"Setup packaging React Native app as an AAR",version:"latest",directory:"template",importName:"pluginBrownfieldAndroid"}],oa=[{type:"npm",name:"metro",displayName:"Metro",packageName:"@rock-js/plugin-metro",version:"latest",directory:"template",importName:"pluginMetro"},{type:"npm",name:"repack",displayName:"Re.Pack",packageName:"@rock-js/plugin-repack",version:"latest",directory:"template",importName:"pluginRepack"}],ol=[{type:"npm",name:"ios",displayName:"iOS",packageName:"@rock-js/platform-ios",version:"latest",directory:"template",importName:"platformIOS"},{type:"npm",name:"android",displayName:"Android",packageName:"@rock-js/platform-android",version:"latest",directory:"template",importName:"platformAndroid"},{type:"npm",name:"harmony",displayName:"Harmony (experimental)",packageName:"@rock-js/platform-harmony",version:"latest",directory:"template",importName:"platformHarmony"}];function oh(e){return e.filter(e=>!Array.isArray(e)||!!e[1]).map(e=>Array.isArray(e)?e[0]:e).join("\n ")}function oc(e,t){let i=e.find(e=>e.name===t);if(i)return i;if(t.startsWith("./")||t.startsWith("../")||t.startsWith("/")||t.startsWith("file:///")){t.startsWith("file://")&&(t=t.slice(7));let e=a(t),i=h(e);return{type:"local",name:e.slice(0,e.length-i.length),displayName:e.slice(0,e.length-i.length),localPath:tU(t),directory:".",packageName:e.slice(0,e.length-i.length)}}return{type:"npm",name:od(t),displayName:od(t),packageName:od(t),directory:".",version:function(e){let t=e.split("@");return 3===t.length&&""===t[0]?t[2]:2===t.length&&""!==t[0]?t[1]:null}(t)??"latest"}}function od(e){let t=e.split("@");return 3===t.length&&""===t[0]?`@${t[1]}`:2===t.length&&""!==t[0]?t[0]:e}function oD(e,t,i){void 0!==i&&(e[t]=i)}function of(n,s,{skipFiles:a=[]}={}){for(let l of(e.mkdirSync(s,{recursive:!0}),e.readdirSync(n))){let h=u.resolve(n,l),c=e.statSync(h),d=u.resolve(s,l);if(c.isDirectory())of(h,d,{skipFiles:a});else if("package.json"===u.basename(h)){let e=JSON.parse(r(h,"utf-8"));i(d)||t(h,d);let n=JSON.parse(r(d,"utf-8"));n.scripts={...n.scripts,...e.scripts},n.dependencies={...n.dependencies,...e.dependencies},n.devDependencies={...n.devDependencies,...e.devDependencies},n.peerDependencies={...n.peerDependencies,...e.peerDependencies},o(d,JSON.stringify(n,null,2))}else(null==a?void 0:a.includes(u.basename(h)))||e.copyFileSync(h,d)}}function op(t){e.existsSync(t)&&e.rmSync(t,{recursive:!0})}function om(t,i,r){let n=u.join(u.dirname(t),u.basename(t).replaceAll(i,r));e.renameSync(t,n)}let og="HelloWorld";function oE(){return e.existsSync(u.join(process.cwd(),"pnpm-lock.yaml"))?"pnpm":e.existsSync(u.join(process.cwd(),"yarn.lock"))||e.existsSync(u.join(process.cwd(),".yarn"))?"yarn":e.existsSync(u.join(process.cwd(),"bun.lockb"))||e.existsSync(u.join(process.cwd(),"bun.lock"))?"bun":"npm"}async function ob(t){var i,r,n;let s=oE(),o=tl();o.start(`Adding ${J().bold("Rock")} dependencies with ${J().bold(s)}`),await oy(t,s,["rock","@rock-js/plugin-metro","@rock-js/platform-android","@rock-js/platform-ios"]),o.stop(`Added ${J().bold("Rock")} dependencies`),o.start(`Removing ${J().bold("React Native Community CLI")} packages`),await oF(t,s,["@react-native-community/cli","@react-native-community/cli-platform-android","@react-native-community/cli-platform-ios"]),o.stop(`Removed ${J().bold("React Native Community CLI")} packages`),o.start(`Adding ${J().bold(".gitignore")} entry for .rock/`),function(t,i){let r=u.join(t,".gitignore");e.existsSync(r)&&!e.readFileSync(r,"utf8").includes(i)&&e.appendFileSync(r,`
+# Rock
+${i}
+`)}(t,".rock/"),o.stop(`Added ${J().bold(".gitignore")} entry for .rock/`),o.start(`Generating ${J().bold("rock.config.mjs")}`);let a=function(t){let i=u.join(t,"react-native.config.js");if(!e.existsSync(i))return{};try{var r,n;let e=H(import.meta.url)(i);return{ios:null==(r=e.project)?void 0:r.ios,android:null==(n=e.project)?void 0:n.android}}catch{return{}}}(t);(function(t,i){let r=u.join(t,"rock.config.mjs"),n=i.ios?`({
+ ${Object.entries(i.ios).map(([e,t])=>`${e}: '${t}'`).join(",\n ")},
+ })`:"()",s=i.android?`({
+ ${Object.entries(i.android).map(([e,t])=>`${e}: '${t}'`).join(",\n ")},
+ })`:"()",o=`// @ts-check
+import { platformIOS } from '@rock-js/platform-ios';
+import { platformAndroid } from '@rock-js/platform-android';
+import { pluginMetro } from '@rock-js/plugin-metro';
+
+/** @type {import('rock').Config} */
+export default {
+ bundler: pluginMetro(),
+ platforms: {
+ ios: platformIOS${n},
+ android: platformAndroid${s},
+ },
+ remoteCacheProvider: null,
+};
+`;e.writeFileSync(r,o)})(t,a),o.stop(`Generated ${J().bold("rock.config.mjs")}`);let l=(null==(i=a.ios)?void 0:i.sourceDir)??"ios",h=(null==(r=a.android)?void 0:r.sourceDir)??"android";o.start(`Updating ${J().bold(`${h}/app/build.gradle`)} and ${J().bold(`${h}/settings.gradle`)}`),function(t,i){let r=u.join(t,i,"app","build.gradle");if(!e.existsSync(r))return;let n='cliFile = file("../../node_modules/rock/dist/src/bin.js")',s=e.readFileSync(r,"utf8");if(s.includes(n))return te.debug(`${r} already contains "${n}"`);let o=s.replace(/(?:\/\/\s+)?cliFile\s*=\s*file\([^)]*\)/g,n);if(o===s)return te.warn(`Unable to update ${J().bold(r)}.
+Please update the "CLI file" build phase manually with:
+ cliFile = file("../../node_modules/rock/dist/src/bin.js")
+`);e.writeFileSync(r,o)}(t,h),function(t,i){let r=u.join(t,i,"settings.gradle");if(!e.existsSync(r))return;let n=e.readFileSync(r,"utf8"),s=n.replace(/extensions\.configure\(com\.facebook\.react\.ReactSettingsExtension\)\{[^}]*autolinkLibrariesFromCommand\([^)]*\)[^}]*\}/gs,"extensions.configure(com.facebook.react.ReactSettingsExtension){ ex -> ex.autolinkLibrariesFromCommand(['npx', 'rock', 'config', '-p', 'android']) }");s===n&&(s=n.replace(/autolinkLibrariesFromCommand\([^)]*\)/g,"autolinkLibrariesFromCommand(['npx', 'rock', 'config', '-p', 'android'])")),s!==n&&e.writeFileSync(r,s)}(t,h),o.stop(`Updated ${J().bold(`${h}/app/build.gradle`)} and ${J().bold(`${h}/settings.gradle`)}`),o.start(`Updating ${J().bold(`${l}/Podfile`)}`),function(t,i){let r=u.join(t,i,"Podfile");if(!e.existsSync(r))return;let n=e.readFileSync(r,"utf8"),s=n.replace(/(config\s*=\s*use_native_modules!)(\s*)/g,"$1(['npx', 'rock', 'config', '-p', 'ios'])$2");n.includes("(['npx', 'rock', 'config', '-p', 'ios'])")||s===n||e.writeFileSync(r,s)}(t,l),o.stop(`Updated ${J().bold(`${l}/Podfile`)}`),o.start(`Updating ${J().bold(`${l}/project.pbxproj`)}`),function(t,i){let r=e.readdirSync(u.join(t,i)).find(e=>e.endsWith(".xcodeproj")),n=r?u.join(t,i,r,"project.pbxproj"):void 0;if(!n)return te.debug(`No Xcode project found in ${i}`);let s=e.readFileSync(n,"utf8"),o=s.replace('shellScript = "set -e\\n\\nWITH_ENVIRONMENT=\\"$REACT_NATIVE_PATH/scripts/xcode/with-environment.sh\\"\\nREACT_NATIVE_XCODE=\\"$REACT_NATIVE_PATH/scripts/react-native-xcode.sh\\"\\n\\n/bin/sh -c \\"$WITH_ENVIRONMENT $REACT_NATIVE_XCODE\\"\\n";','shellScript = "set -e\\nif [[ -f \\"$PODS_ROOT/../.xcode.env\\" ]]; then\\nsource \\"$PODS_ROOT/../.xcode.env\\"\\nfi\\nif [[ -f \\"$PODS_ROOT/../.xcode.env.local\\" ]]; then\\nsource \\"$PODS_ROOT/../.xcode.env.local\\"\\nfi\\nexport CONFIG_CMD=\\"dummy-workaround-value\\"\\nexport CLI_PATH=\\"$(\\"$NODE_BINARY\\" --print \\"require(\'path\').dirname(require.resolve(\'rock/package.json\')) + \'/dist/src/bin.js\'\\")\\"\\nWITH_ENVIRONMENT=\\"$REACT_NATIVE_PATH/scripts/xcode/with-environment.sh\\"\\n";');o!==s?e.writeFileSync(n,o):te.warn(`Unable to update ${J().bold(n)}.
+Please update the "Bundle React Native code and images" build phase manually with:
+ set -e
+ if [[ -f "$PODS_ROOT/../.xcode.env" ]]; then
+ source "$PODS_ROOT/../.xcode.env"
+ fi
+ if [[ -f "$PODS_ROOT/../.xcode.env.local" ]]; then
+ source "$PODS_ROOT/../.xcode.env.local"
+ fi
+ export CONFIG_CMD="dummy-workaround-value"
+ export CLI_PATH="$("$NODE_BINARY" --print "require('path').dirname(require.resolve('rock/package.json')) + '/dist/src/bin.js'")"
+ WITH_ENVIRONMENT="$REACT_NATIVE_PATH/scripts/xcode/with-environment.sh"
+`)}(t,l),o.stop(`Updated ${J().bold(`${l}/project.pbxproj`)}`),o.start(`Updating ${J().bold("package.json")} scripts`),function(t){let i=u.join(t,"package.json");if(!e.existsSync(i))return;let r=e.readFileSync(i,"utf8").replaceAll("react-native start","rock start").replaceAll("react-native run-android","rock run:android").replaceAll("react-native build-android","rock build:android").replaceAll("react-native run-ios","rock run:ios").replaceAll("react-native build-ios","rock build:ios").replaceAll(/run:android(.*)--mode(.*)/g,"run:android$1--variant$2").replaceAll(/run:ios(.*)--mode(.*)/g,"run:ios$1--configuration$2").replaceAll(/build:android(.*)--mode(.*)/g,"build:android$1--variant$2").replaceAll(/build:ios(.*)--mode(.*)/g,"build:ios$1--configuration$2").replaceAll("--appIdSuffix","--app-id-suffix").replaceAll("--appId","--app-id").replaceAll("--buildFolder","--build-folder");e.writeFileSync(i,r)}(t),o.stop(`Updated ${J().bold("package.json")} scripts`),tr(`1. Run ${J().bold("git diff")} to see the changes. Adjust as necessary e.g.:
+ - paths in monorepo
+ - commands in shell scripts
+ - commands in CI workflows
+2. Run the dev server as you would normally do
+3. Run iOS and Android apps as you would normally do
+4. Setup Remote Cache: ${(n="https://rockjs.dev/docs/configuration#remote-cache-configuration",q.cyan(q.underline(q.bold(n))))}`,"Next steps"),ti("Success \uD83C\uDF89.")}async function oy(e,t,i){let r={npm:["install","-D",...i],pnpm:["add","-D",...i],yarn:["add","-D",...i],bun:["add","-D",...i]}[t]??["install","-D",...i];await tz(t,r,{cwd:e})}async function oF(e,t,i){let r={npm:["remove",...i],pnpm:["remove",...i],yarn:["remove",...i],bun:["remove",...i]}[t]??["remove",...i];try{await tz(t,r,{cwd:e})}catch(e){te.debug(e.message,"Continuing with the rest of the steps\n")}}async function oC(t){let i=oE(),r=tl(),n={"@rnef/cli":"rock","@rnef/platform-android":"@rock-js/platform-android","@rnef/platform-ios":"@rock-js/platform-ios","@rnef/plugin-metro":"@rock-js/plugin-metro","@rnef/plugin-repack":"@rock-js/plugin-repack","@rnef/provider-github":"@rock-js/provider-github","@rnef/provider-s3":"@rock-js/provider-s3","@rnef/welcome-screen":"@rock-js/welcome-screen"},s=function(t){let i=u.join(t,"package.json"),r=JSON.parse(e.readFileSync(i,"utf8"));return[...Object.keys(r.dependencies).filter(e=>e.startsWith("@rnef/")),...Object.keys(r.devDependencies).filter(e=>e.startsWith("@rnef/"))]}(t);r.start(`Removing ${J().bold("RNEF")} packages`),await ow(t,i,s),r.stop(`Removed ${J().bold("RNEF")} packages`),r.start(`Adding ${J().bold("Rock")} packages with ${J().bold(i)}`),await ov(t,i,s.map(e=>n[e])),r.stop(`Added ${J().bold("Rock")} packages`),r.start(`Updating ${J().bold(".gitignore")}`),function(t){let i=u.join(t,".gitignore");if(e.existsSync(i)){let t=e.readFileSync(i,"utf8");t=t.replace(/\.rnef\//g,".rock/"),e.writeFileSync(i,t)}}(t),r.stop(`Updated ${J().bold(".gitignore")}`),r.start("Updating cache"),function(t){let i=u.join(t,".rnef"),r=u.join(t,".rock");e.existsSync(i)&&(e.existsSync(r)&&e.rmSync(r,{recursive:!0,force:!0}),e.renameSync(i,r))}(t),function(t){let i=u.join(t,".rock","cache","remote-build");e.existsSync(i)&&e.readdirSync(i).forEach(t=>{if(t.includes("rnef")){let r=t.replace(/rnef/g,"rock"),n=u.join(i,t),s=u.join(i,r);e.renameSync(n,s)}})}(t),r.stop("Updated cache"),r.start(`Renaming and updating ${J().bold("rnef.config.mjs")} to ${J().bold("rock.config.mjs")}`),function(t){let i=u.join(t,"rnef.config.mjs"),r=u.join(t,"rock.config.mjs");if(e.existsSync(i)){let t=e.readFileSync(i,"utf8");t=(t=t.replace(/@rnef\//g,"@rock-js/")).replace(/@rnef\/cli/g,"rock"),e.writeFileSync(r,t),e.unlinkSync(i)}}(t),r.stop(`Renamed and updated ${J().bold("rnef.config.mjs")} to ${J().bold("rock.config.mjs")}`),r.start(`Updating ${J().bold("android/app/build.gradle")}`),function(t){let i=u.join(t,"android","app","build.gradle");if(!e.existsSync(i))return;let r=e.readFileSync(i,"utf8");r=r.replace(/@rnef\/cli\/dist\/src\/bin\.js/g,"rock/dist/src/bin.js"),e.writeFileSync(i,r)}(t),r.stop(`Updated ${J().bold("android/app/build.gradle")}`),r.start(`Updating ${J().bold("ios/Podfile")}`),function(t){let i=u.join(t,"ios","Podfile");if(!e.existsSync(i))return;let r=e.readFileSync(i,"utf8");r=r.replace(/rnef/g,"rock"),e.writeFileSync(i,r)}(t),r.stop(`Updated ${J().bold("ios/Podfile")}`),r.start(`Updating ${J().bold("android/settings.gradle")}`),function(t){let i=u.join(t,"android","settings.gradle");if(!e.existsSync(i))return;let r=e.readFileSync(i,"utf8");r=r.replace(/rnef/g,"rock"),e.writeFileSync(i,r)}(t),r.stop(`Updated ${J().bold("android/settings.gradle")}`),r.start(`Updating ${J().bold("ios/project.pbxproj")}`),function(t){let i=u.join(t,"ios");if(!e.existsSync(i))return;let r=e.readdirSync(i).find(e=>e.endsWith(".xcodeproj"));if(!r)return;let n=u.join(i,r,"project.pbxproj");if(!e.existsSync(n))return;let s=e.readFileSync(n,"utf8");s=s.replace(/@rnef\/cli/g,"rock"),e.writeFileSync(n,s)}(t),r.stop(`Updated ${J().bold("ios/project.pbxproj")}`),r.start(`Updating ${J().bold("package.json")} scripts`),function(t){let i=u.join(t,"package.json");if(!e.existsSync(i))return;let r=e.readFileSync(i,"utf8");r=r.replace(/rnef/g,"rock"),e.writeFileSync(i,r)}(t),r.stop(`Updated ${J().bold("package.json")} scripts`),tr(`1. Run ${J().bold("git diff")} to see the changes. Adjust as necessary e.g.:
+ - paths in monorepo
+ - commands in shell scripts
+ - commands in CI workflows
+2. Run the dev server as you would normally do
+3. Run iOS and Android apps as you would normally do
+4. Setup Remote Cache: ${J().bold("https://rockjs.dev/docs/configuration#remote-cache-configuration")}`,"Next steps"),ti("RNEF to Rock migration completed successfully \uD83C\uDF89.")}async function ov(e,t,i){let r={npm:["install","-D",...i],pnpm:["add","-D",...i],yarn:["add","-D",...i],bun:["add","-D",...i]}[t]??["install","-D",...i];await tz(t,r,{cwd:e})}async function ow(e,t,i){let r={npm:["remove",...i],pnpm:["remove",...i],yarn:["remove",...i],bun:["remove",...i]}[t]??["remove",...i];try{await tz(t,r,{cwd:e})}catch(e){te.debug(e.message,"Continuing with the rest of the steps\n")}}var o_=Y("../../node_modules/.pnpm/minimist@1.2.8/node_modules/minimist/index.js"),oS=Y.n(o_);function oA(e){if(void 0!=e)return Array.isArray(e)?e[e.length-1]:e}function oR(e){if(void 0!=e)return Array.isArray(e)?e:[e]}let oO=/^[A-Z][0-9A-Z_-]*$/i,oB=["react","react-native","abstract","continue","for","new","switch","assert","default","goto","package","synchronized","boolean","do","if","private","this","break","double","implements","protected","throw","byte","else","import","public","throws","case","enum","instanceof","return","transient","catch","extends","int","short","try","char","final","interface","static","void","class","finally","long","strictfp","volatile","const","float","native","super","while"];function ox(e){if(0===e.length)return"Project name cannot be empty.";if(!e.match(oO))return`Invalid project name: "${e}". Please use a valid identifier name (alphanumeric, hyphen, underscore).`;let t=e.toLowerCase();if(oB.includes(t))return`Invalid project name: "${e}". Can't use reserved name. Please use another name.`}let oN=(e=0)=>t=>`\u001B[${t+e}m`,oI=(e=0)=>t=>`\u001B[${38+e};5;${t}m`,oT=(e=0)=>(t,i,r)=>`\u001B[${38+e};2;${t};${i};${r}m`,oL={modifier:{reset:[0,0],bold:[1,22],dim:[2,22],italic:[3,23],underline:[4,24],overline:[53,55],inverse:[7,27],hidden:[8,28],strikethrough:[9,29]},color:{black:[30,39],red:[31,39],green:[32,39],yellow:[33,39],blue:[34,39],magenta:[35,39],cyan:[36,39],white:[37,39],blackBright:[90,39],gray:[90,39],grey:[90,39],redBright:[91,39],greenBright:[92,39],yellowBright:[93,39],blueBright:[94,39],magentaBright:[95,39],cyanBright:[96,39],whiteBright:[97,39]},bgColor:{bgBlack:[40,49],bgRed:[41,49],bgGreen:[42,49],bgYellow:[43,49],bgBlue:[44,49],bgMagenta:[45,49],bgCyan:[46,49],bgWhite:[47,49],bgBlackBright:[100,49],bgGray:[100,49],bgGrey:[100,49],bgRedBright:[101,49],bgGreenBright:[102,49],bgYellowBright:[103,49],bgBlueBright:[104,49],bgMagentaBright:[105,49],bgCyanBright:[106,49],bgWhiteBright:[107,49]}};Object.keys(oL.modifier),[...Object.keys(oL.color),...Object.keys(oL.bgColor)];let ok=function(){let e=new Map;for(let[t,i]of Object.entries(oL)){for(let[t,r]of Object.entries(i))oL[t]={open:`\u001B[${r[0]}m`,close:`\u001B[${r[1]}m`},i[t]=oL[t],e.set(r[0],r[1]);Object.defineProperty(oL,t,{value:i,enumerable:!1})}return Object.defineProperty(oL,"codes",{value:e,enumerable:!1}),oL.color.close="\x1b[39m",oL.bgColor.close="\x1b[49m",oL.color.ansi=oN(),oL.color.ansi256=oI(),oL.color.ansi16m=oT(),oL.bgColor.ansi=oN(10),oL.bgColor.ansi256=oI(10),oL.bgColor.ansi16m=oT(10),Object.defineProperties(oL,{rgbToAnsi256:{value:(e,t,i)=>e===t&&t===i?e<8?16:e>248?231:Math.round((e-8)/247*24)+232:16+36*Math.round(e/255*5)+6*Math.round(t/255*5)+Math.round(i/255*5),enumerable:!1},hexToRgb:{value(e){let t=/[a-f\d]{6}|[a-f\d]{3}/i.exec(e.toString(16));if(!t)return[0,0,0];let[i]=t;3===i.length&&(i=[...i].map(e=>e+e).join(""));let r=Number.parseInt(i,16);return[r>>16&255,r>>8&255,255&r]},enumerable:!1},hexToAnsi256:{value:e=>oL.rgbToAnsi256(...oL.hexToRgb(e)),enumerable:!1},ansi256ToAnsi:{value(e){let t,i,r;if(e<8)return 30+e;if(e<16)return 90+(e-8);if(e>=232)i=t=((e-232)*10+8)/255,r=t;else{let n=(e-=16)%36;t=Math.floor(e/36)/5,i=Math.floor(n/6)/5,r=n%6/5}let n=2*Math.max(t,i,r);if(0===n)return 30;let s=30+(Math.round(r)<<2|Math.round(i)<<1|Math.round(t));return 2===n&&(s+=60),s},enumerable:!1},rgbToAnsi:{value:(e,t,i)=>oL.ansi256ToAnsi(oL.rgbToAnsi256(e,t,i)),enumerable:!1},hexToAnsi:{value:e=>oL.ansi256ToAnsi(oL.hexToAnsi256(e)),enumerable:!1}}),oL}();function oM(e,t=globalThis.Deno?globalThis.Deno.args:E.argv){let i=e.startsWith("-")?"":1===e.length?"-":"--",r=t.indexOf(i+e),n=t.indexOf("--");return -1!==r&&(-1===n||r=10&&Number(e[2])>=10586?Number(e[2])>=14931?3:2:1}if("CI"in o$)return"GITHUB_ACTIONS"in o$||"GITEA_ACTIONS"in o$?3:["TRAVIS","CIRCLECI","APPVEYOR","GITLAB_CI","BUILDKITE","DRONE"].some(e=>e in o$)||"codeship"===o$.CI_NAME?1:s;if("TEAMCITY_VERSION"in o$)return+!!/^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(o$.TEAMCITY_VERSION);if("truecolor"===o$.COLORTERM||"xterm-kitty"===o$.TERM)return 3;if("TERM_PROGRAM"in o$){let e=Number.parseInt((o$.TERM_PROGRAM_VERSION||"").split(".")[0],10);switch(o$.TERM_PROGRAM){case"iTerm.app":return e>=3?3:2;case"Apple_Terminal":return 2}}return/-256(color)?$/i.test(o$.TERM)?2:/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(o$.TERM)||"COLORTERM"in o$?1:s}(e,{streamIsTTY:e&&e.isTTY,...t}))&&{level:i,hasBasic:!0,has256:i>=2,has16m:i>=3}}oM("no-color")||oM("no-colors")||oM("color=false")||oM("color=never")?X=0:(oM("color")||oM("colors")||oM("color=true")||oM("color=always"))&&(X=1);let{stdout:oP,stderr:oz}={stdout:oj({isTTY:Z.isatty(1)}),stderr:oj({isTTY:Z.isatty(2)})},oU=Symbol("GENERATOR"),oH=Symbol("STYLER"),oG=Symbol("IS_EMPTY"),oZ=["ansi","ansi","ansi256","ansi16m"],oW=Object.create(null);function oV(e){let t=(...e)=>e.join(" ");return((e,t={})=>{if(t.level&&!(Number.isInteger(t.level)&&t.level>=0&&t.level<=3))throw Error("The `level` option should be an integer from 0 to 3");let i=oP?oP.level:0;e.level=void 0===t.level?i:t.level})(t,e),Object.setPrototypeOf(t,oV.prototype),t}for(let[e,t]of(Object.setPrototypeOf(oV.prototype,Function.prototype),Object.entries(ok)))oW[e]={get(){let i=oq(this,oK(t.open,t.close,this[oH]),this[oG]);return Object.defineProperty(this,e,{value:i}),i}};oW.visible={get(){let e=oq(this,this[oH],!0);return Object.defineProperty(this,"visible",{value:e}),e}};let oY=(e,t,i,...r)=>"rgb"===e?"ansi16m"===t?ok[i].ansi16m(...r):"ansi256"===t?ok[i].ansi256(ok.rgbToAnsi256(...r)):ok[i].ansi(ok.rgbToAnsi(...r)):"hex"===e?oY("rgb",t,i,...ok.hexToRgb(...r)):ok[i][e](...r);for(let e of["rgb","hex","ansi256"])oW[e]={get(){let{level:t}=this;return function(...i){return oq(this,oK(oY(e,oZ[t],"color",...i),ok.color.close,this[oH]),this[oG])}}},oW["bg"+e[0].toUpperCase()+e.slice(1)]={get(){let{level:t}=this;return function(...i){return oq(this,oK(oY(e,oZ[t],"bgColor",...i),ok.bgColor.close,this[oH]),this[oG])}}};let oX=Object.defineProperties(()=>{},{...oW,level:{enumerable:!0,get(){return this[oU].level},set(e){this[oU].level=e}}}),oK=(e,t,i)=>{let r,n;return void 0===i?(r=e,n=t):(r=i.openAll+e,n=t+i.closeAll),{open:e,close:t,openAll:r,closeAll:n,parent:i}},oq=(e,t,i)=>{let r=(...e)=>oJ(r,1===e.length?""+e[0]:e.join(" "));return Object.setPrototypeOf(r,oX),r[oU]=e,r[oH]=t,r[oG]=i,r},oJ=(e,t)=>{if(e.level<=0||!t)return e[oG]?"":t;let i=e[oH];if(void 0===i)return t;let{openAll:r,closeAll:n}=i;if(t.includes("\x1b"))for(;void 0!==i;)t=function(e,t,i){let r=e.indexOf(t);if(-1===r)return e;let n=t.length,s=0,o="";do o+=e.slice(s,r)+t+i,s=r+n,r=e.indexOf(t,s);while(-1!==r);return o+e.slice(s)}(t,i.close,i.open),i=i.parent;let s=t.indexOf("\n");return -1!==s&&(t=function(e,t,i,r){let n=0,s="";do{let o="\r"===e[r-1];s+=e.slice(n,o?r-1:r)+t+(o?"\r\n":"\n")+i,n=r+1,r=e.indexOf("\n",n)}while(-1!==r);return s+e.slice(n)}(t,n,r,s)),r+t+n};Object.defineProperties(oV.prototype,oW);let oQ=oV();oV({level:oz?oz.level:0});var o0=Y("../../node_modules/.pnpm/tinygradient@1.1.5/node_modules/tinygradient/index.js");let o1=(...e)=>{let t,i;if(0===e.length)throw Error("Missing gradient colors");if(Array.isArray(e[0]))t=o0(e[0]),i=o3(e[1]);else{if(1===e.length)throw Error(`Expected an array of colors, received ${JSON.stringify(e[0])}`);t=o0(...e)}let r=(e,r)=>(function(e,t,i){let r=o3(i),n=Math.max(e.replace(/\s/g,"").length,t.stops.length),s=o2(t,r,n),o="";for(let t of e)o+=t.match(/\s/g)?t:oQ.hex(s.shift()?.toHex()||"#000")(t);return o})(e?e.toString():"",t,r??i);return r.multiline=(e,r)=>(function(e,t,i){let r=o3(i),n=e.split("\n"),s=Math.max(...n.map(e=>e.length),t.stops.length),o=o2(t,r,s),u=[];for(let e of n){let t=o.slice(0),i="";for(let r of e)i+=oQ.hex(t.shift()?.toHex()||"#000")(r);u.push(i)}return u.join("\n")})(e?e.toString():"",t,r??i),r},o2=(e,t,i)=>t.interpolation?.toLowerCase()==="hsv"?e.hsv(i,t.hsvSpin?.toLowerCase()||!1):e.rgb(i);function o3(e){let t={interpolation:"rgb",hsvSpin:"short",...e};if(void 0!==e&&"object"!=typeof e)throw TypeError(`Expected \`options\` to be an \`object\`, got \`${typeof e}\``);if("string"!=typeof t.interpolation)throw TypeError(`Expected \`options.interpolation\` to be \`rgb\` or \`hsv\`, got \`${typeof t.interpolation}\``);if("hsv"===t.interpolation.toLowerCase()&&"string"!=typeof t.hsvSpin)throw TypeError(`Expected \`options.hsvSpin\` to be a \`short\` or \`long\`, got \`${typeof t.hsvSpin}\``);return t}function o8(e){let t=t=>o1(...e.colors)(t,e.options);return t.multiline=(t="")=>o1(...e.colors).multiline(t,e.options),t}let o6=o8({colors:["#feac5e","#c779d0","#4bc0c8"],options:{}}),o5=o8({colors:["#bdfff3","#4ac29a"],options:{}}),o4=o8({colors:["#77a1d3","#79cbca","#e684ae"],options:{}}),o9=o8({colors:["#473b7b","#3584a7","#30d2be"],options:{}}),o7=o8({colors:["#ff5f6d","#ffc371"],options:{interpolation:"hsv"}}),ue=o8({colors:["#5ee7df","#b490ca"],options:{interpolation:"hsv"}}),ut=o8({colors:["#f43b47","#453a94"],options:{}}),ui=o8({colors:["#ff4e50","#f9d423"],options:{}}),ur=o8({colors:["#833ab4","#fd1d1d","#fcb045"],options:{}}),un=o8({colors:["#3f51b1","#5a55ae","#7b5fac","#8f6aae","#a86aa4","#cc6b8e","#f18271","#f3a469","#f7c978"],options:{}}),us=o8({colors:["#fdbb2d","#22c1c3"],options:{}}),uo=o8({colors:["#ff0000","#ff0100"],options:{interpolation:"hsv",hsvSpin:"long"}}),uu=o8({colors:["#74ebd5","#74ecd5"],options:{interpolation:"hsv",hsvSpin:"long"}});function ua(){try{let e=l(B(import.meta.url)),t=d(e,"../../package.json");return JSON.parse(r(t,"utf-8")).version}catch(e){return te.warn("Failed to get Rock version",e),null}}function ul(e){return tn({message:"What is your app named?",initialValue:e,validate:ox})}async function uh(e){if(0===e.length)throw new e9("No templates found");return ts({message:"Select a template:",options:e.map(e=>({value:e,label:e.displayName}))})}async function uc(t,i="latest",r){try{var n;let s=null==(n=(await ud(t,i)).dist)?void 0:n.tarball;if(!s)throw new e9("Tarball URL not found.");let o=await fetch(s);if(!o.ok)throw new e9(`Failed to fetch package ${t}: ${o.statusText}`);let a=u.join(r,`${t.replace("/","-")}.tgz`),l=await o.arrayBuffer();return e.writeFileSync(a,new Uint8Array(l)),a}catch(e){throw new e9(`Error downloading package ${t}`,{cause:e})}}async function ud(e,t){var i,r,n;let s=`${process.env.NPM_CONFIG_REGISTRY||"https://registry.npmjs.org"}/${e}`,o=await fetch(s);if(!o.ok)throw new e9(`Failed to fetch package metadata for ${e}: ${o.statusText}`);let u=await o.json(),a=null==(i=u["dist-tags"])?void 0:i[t],l=a?null==(r=u.versions)?void 0:r[a]:null==(n=u.versions)?void 0:n[t];if(!l)throw new e9(`Version ${t} not found for package ${e}`);return l}async function uD(t,i){let r=u.join(t,`.temp-${u.basename(i,u.extname(i))}-${Date.now()}`);return e.mkdirSync(r,{recursive:!0}),await s4({file:i,cwd:r,strip:1}),r}async function uf(){let t=function(e){let t=oS()(e,{alias:{h:"help",v:"version",p:"platform",t:"template",d:"dir"},boolean:["help","version","override","install"],string:["template","platform","dir","plugin","bundler"]});return{name:t._[0],template:oA(t.template),platforms:oR(t.platform),plugins:oR(t.plugin),bundler:t.bundler,help:t.help,version:t.version,dir:oA(t.dir),override:t.override,remoteCacheProvider:t["remote-cache-provider"],install:t.install}}(process.argv.slice(2)),l=ua();if(t.help)return void console.log(`
+ Usage: create-rock [options]
+
+ Options:
+
+ -h, --help Display help for command
+ -v, --version Output the version number
+ -d, --dir Create project in specified directory
+ -t, --template Specify template to use
+ -p, --platform Specify platform(s) to use
+ --plugin Specify plugin(s) to use
+ --bundler Specify bundler to use
+ --remote-cache-provider Specify remote cache provider
+ --override Override files in target directory
+ --install Install Node.js dependencies
+
+ Available templates:
+ ${oo.map(e=>e.name).join(", ")}
+
+ Available platforms:
+ ${ol.map(e=>e.name).join(", ")}
+ `);if(t.version)return void console.log(`${ua()}`);console.log(""),((e="")=>{process.stdout.write(`${q.gray(eP)} ${e}
+`)})(`Welcome to ${J().bold(ue("Rock"))}!`);let h=tU(t.dir||process.cwd());if(function(t){var i,r;let n=u.join(t,"package.json");if(!e.existsSync(n))return!1;let s=JSON.parse(e.readFileSync(n,"utf8"));return(null==(i=s.dependencies)?void 0:i["@rnef/cli"])!==void 0||(null==(r=s.devDependencies)?void 0:r["@rnef/cli"])!==void 0}(h)){await up(h),await to({message:"Detected existing RNEF project. Would you like to migrate it to Rock?",confirmLabel:"Yes",cancelLabel:"No"})||tc(),await oC(h);return}if(function(t){var i,r;let n=u.join(t,"package.json");if(!e.existsSync(n))return!1;let s=JSON.parse(e.readFileSync(n,"utf8"));return(null==(i=s.dependencies)?void 0:i["react-native"])!==void 0||(null==(r=s.devDependencies)?void 0:r["react-native"])!==void 0}(h)){await up(h),await to({message:"Detected existing React Native project. Would you like to migrate it to Rock?",confirmLabel:"Yes",cancelLabel:"No"})||tc(),await ob(h);return}let c=(t.dir||t.name)??await ul();ox(c)&&(c=await ul(c));let{targetDir:D}=function(e){let t=e.trim().replace(/\/+$/g,"");return{packageName:t.startsWith("@")?t:u.basename(t),targetDir:t}}(c),p=tU(D);!t.override&&e.existsSync(p)&&!function(t){let i=e.readdirSync(t);return 0===i.length||1===i.length&&".git"===i[0]}(p)&&(await to({message:`"${p}" is not empty, please choose:`,confirmLabel:"Continue and override files",cancelLabel:"Cancel operation"})||tc()),op(p),e.mkdirSync(p,{recursive:!0});let m=t.template?oc(oo,t.template):await uh(oo),g=t.platforms?t.platforms.map(e=>oc(ol,e)):await function(e){if(0===e.length)throw new e9("No platforms found");let t=e.filter(e=>"android"===e.name||"ios"===e.name);return tu({message:`What platforms do you want to start with? ${J().dim("(Press to select, to skip)")}:`,initialValues:t,options:e.map(e=>({value:e,label:e.displayName}))})}(ol),E=t.bundler?oc(oa,t.bundler):await function(e){if(0===e.length)throw new e9("No bundlers found");return ts({message:"Which bundler do you want to use?",initialValues:[e[0]],options:e.map(e=>({value:e,label:e.displayName}))})}(oa),b=t.plugins?t.plugins.map(e=>oc(ou,e)):await (0===ou.length||!e4()?Promise.resolve(null):tu({message:`Select plugins ${J().dim("(Press to skip)")}:`,options:ou.map(e=>({value:e,label:e.displayName,hint:e.hint})),required:!1})),y=void 0!==t.remoteCacheProvider||!1===t.remoteCacheProvider?null:await ts({message:"What do you want to use as cache for your remote builds?",initialValue:"github-actions",options:[{value:"github-actions",label:"GitHub Actions",hint:"The easiest way to start if you store your code on GitHub"},{value:"s3",label:"S3",hint:"Work with any S3-compatible storage, including AWS S3 and Cloudflare R2"},{value:null,label:"None",hint:"Local cache only which isn't shared across team members or CI/CD environments"}]}),F=y?await function(e){let t="Ensure the below environment variables are set";switch(e){case"github-actions":return tr(`GITHUB_TOKEN Your GitHub personal access token (PAT)
+
+\u{1F4A1} Set this in your ${J().bold(".env")} file or pass it as an argument to ${J().bold("run:*")} commands.`,t),ta({owner:()=>tn({message:"GitHub repository owner"}),repository:()=>tn({message:"GitHub repository name"})});case"s3":return tr(`AWS_ACCESS_KEY_ID Your AWS access key ID
+AWS_SECRET_ACCESS_KEY Your AWS secret access key
+
+\u{1F4A1} Set these in your ${J().bold(".env")} file or pass them as arguments to ${J().bold("run:*")} commands.`,t),ta({bucket:()=>tn({message:"Pass your bucket name:",placeholder:"bucket-name",defaultValue:"bucket-name"}),region:()=>tn({message:"Pass your bucket region:",placeholder:"us-west-1",defaultValue:"us-west-1"}),endpoint:()=>tn({message:`If you're using self-hosted S3 or Cloudflare R2, pass your endpoint ${J().dim("(Press to skip)")}:`,placeholder:"https://.r2.cloudflarestorage.com",defaultValue:void 0})})}}(y):null,C=!!(t.install||e4())&&await to({message:"Do you want to install dependencies?",confirmLabel:"Yes",cancelLabel:"No"}),v=tl();for(let e of(v.start("Applying template, platforms and plugins"),await ug(p,m),g))await ug(p,e);let w=g.map(e=>e.name).includes("harmony")?["metro.config.js"]:void 0;for(let e of(await ug(p,E,w),b??[]))await ug(p,e);let _=d(p,"gitignore");i(_)&&n(_,d(p,".gitignore"));let S=d(p,"harmony","gitignore");i(S)&&n(S,d(p,"harmony",".gitignore"));var A,R=(A=c)?A.split("-").filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(""):"";if(R!==og)for(let t of(function t(i){if(!e.lstatSync(i).isDirectory())return[i];let r=e.readdirSync(i).flatMap(e=>t(u.join(i,e)));return[i,...r]})(p).reverse())s(t).isDirectory()||function(e,t){let i=r(e,"utf8"),n=i.replaceAll(og,t).replaceAll(og.toLowerCase(),t.toLowerCase());i!==n&&o(e,n,"utf8")}(t,R),a(t).includes(og)?om(t,og,R):a(t).includes(og.toLowerCase())&&om(t,og.toLowerCase(),R.toLowerCase());!function(e,t){let n=d(e,"package.json");if(!i(n))return;let s=JSON.parse(r(n,"utf-8"));s.name=t,s.version="1.0.0",s.private=!0,delete s.publishConfig,s.dependencies&&(s.dependencies=Object.fromEntries(Object.entries(s.dependencies).sort())),s.devDependencies&&(s.devDependencies=Object.fromEntries(Object.entries(s.devDependencies).sort())),s.peerDependencies&&(s.peerDependencies=Object.fromEntries(Object.entries(s.peerDependencies).sort())),o(n,JSON.stringify(function(e){let{name:t,version:i,private:r,scripts:n,dependencies:s,devDependencies:o,peerDependencies:u,...a}=e,l={};for(let e in oD(l,"name",t),oD(l,"version",i),oD(l,"private",r),oD(l,"scripts",n),oD(l,"dependencies",s),oD(l,"devDependencies",o),oD(l,"peerDependencies",u),a)l[e]=a[e];return l}(s),null,2))}(p,c),function(t,i,r,n,s){let o=u.join(t,"rock.config.mjs");e.writeFileSync(o,function(e,t,i,r){let n=e.filter(e=>e.importName),s=t?t.filter(e=>e.importName):null;return`${[...[...n,...s??[],i].map(e=>`import { ${e.importName} } from '${e.packageName}';`),(null==r?void 0:r.name)?function(e){switch(e){case"github-actions":return"import { providerGitHub } from '@rock-js/provider-github';";case"s3":return"import { providerS3 } from '@rock-js/provider-s3';"}}(r.name):""].filter(Boolean).join("\n")}
+
+export default {
+ ${[s&&s.length>0?`plugins: [
+ ${s.map(e=>`${e.importName}(),`).join("\n ")}
+ ],`:"",`bundler: ${i.importName}(),`,`platforms: {
+ ${n.map(e=>`${e.name}: ${e.importName}(),`).join("\n ")}
+ },`,(null==r?void 0:r.name)?function(e,t){switch(e){case"github-actions":return oh(["remoteCacheProvider: providerGitHub({",` owner: '${t.owner}',`,` repository: '${t.repository}',`,"}),"]);case"s3":return oh(["remoteCacheProvider: providerS3({",` bucket: '${t.bucket}',`,` region: '${t.region}',`,[` endpoint: '${t.endpoint}',`,!!t.endpoint],"}),"])}}(r.name,r.args):""].filter(Boolean).join("\n ")}
+};
+`}(i,r,n,s))}(p,g,b,E,y&&F?{name:y,args:F}:null),v.stop("Applied template, platforms and plugins.");let O=function(){let e=function(e){if(!e)return;let t=e.split(" ")[0].split("/");return{name:t[0],version:t[1]}}(process.env.npm_config_user_agent);return e?e.name:oE()}();C&&await um(p,O),await oi(p,l);let B=f(process.cwd(),p);tr([`cd ${B}`,C?void 0:`${O} install`,`${O} run start starts dev server`,`${O} run ios builds and runs iOS app`,`${O} run android builds and runs Android app`].filter(Boolean).join("\n"),"Next steps"),ti("Success \uD83C\uDF89.")}async function up(e){if(await os(e)&&await on()){let{output:t}=await tz("git",["status","--porcelain"],{cwd:e});""!==t.trim()&&(await to({message:"Git has uncommitted changes. Would you like to continue with initializing Rock in existing project?",confirmLabel:"Yes",cancelLabel:"No"})||tc())}}async function um(e,t){let i=tl();i.start(`Installing dependencies with ${t}`),await tz(t,["install"],{cwd:e}),i.stop(`Installed dependencies with ${t}`)}async function ug(t,i,r){var n,s,o;let a=null;if("npm"===i.type?a=await uc(i.packageName,i.version,t):((null==(n=i.localPath)?void 0:n.endsWith(".tgz"))||(null==(s=i.localPath)?void 0:s.endsWith(".tar.gz"))||(null==(o=i.localPath)?void 0:o.endsWith(".tar")))&&(a=i.localPath),a){let n=await uD(t,a);i.packageName&&e.unlinkSync(a),of(u.join(n,i.directory??""),t,{skipFiles:r}),op(n);return}if("local"===i.type)return void of(u.join(i.localPath,i.directory??""),t,{skipFiles:r});throw new e9(`Invalid state: template not found: ${JSON.stringify(i,null,2)}`)}o1.atlas=o6,o1.cristal=o5,o1.teen=o4,o1.mind=o9,o1.morning=o7,o1.vice=ue,o1.passion=ut,o1.fruit=ui,o1.instagram=ur,o1.retro=un,o1.summer=us,o1.rainbow=uo,o1.pastel=uu},crypto:function(e){e.exports=W},fs:function(e){e.exports=V},path:function(e){e.exports=Y},zlib:function(e){e.exports=X},"../../node_modules/.pnpm/tinycolor2@1.6.0/node_modules/tinycolor2/cjs/tinycolor.js":function(e){e.exports=function(){"use strict";function e(t){return(e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(t)}var t,i,r,n=/^\s+/,s=/\s+$/;function o(t,i){if(i=i||{},(t=t||"")instanceof o)return t;if(!(this instanceof o))return new o(t,i);var r,u,a,l,h,c,d,D,f,p,m,g,E,b,y,F,C,w,A,O,x=(u={r:0,g:0,b:0},a=1,l=null,h=null,c=null,d=!1,D=!1,"string"==typeof(r=t)&&(r=function(e){e=e.replace(n,"").replace(s,"").toLowerCase();var t,i=!1;if(v[e])e=v[e],i=!0;else if("transparent"==e)return{r:0,g:0,b:0,a:0,format:"name"};return(t=N.rgb.exec(e))?{r:t[1],g:t[2],b:t[3]}:(t=N.rgba.exec(e))?{r:t[1],g:t[2],b:t[3],a:t[4]}:(t=N.hsl.exec(e))?{h:t[1],s:t[2],l:t[3]}:(t=N.hsla.exec(e))?{h:t[1],s:t[2],l:t[3],a:t[4]}:(t=N.hsv.exec(e))?{h:t[1],s:t[2],v:t[3]}:(t=N.hsva.exec(e))?{h:t[1],s:t[2],v:t[3],a:t[4]}:(t=N.hex8.exec(e))?{r:R(t[1]),g:R(t[2]),b:R(t[3]),a:R(t[4])/255,format:i?"name":"hex8"}:(t=N.hex6.exec(e))?{r:R(t[1]),g:R(t[2]),b:R(t[3]),format:i?"name":"hex"}:(t=N.hex4.exec(e))?{r:R(t[1]+""+t[1]),g:R(t[2]+""+t[2]),b:R(t[3]+""+t[3]),a:R(t[4]+""+t[4])/255,format:i?"name":"hex8"}:!!(t=N.hex3.exec(e))&&{r:R(t[1]+""+t[1]),g:R(t[2]+""+t[2]),b:R(t[3]+""+t[3]),format:i?"name":"hex"}}(r)),"object"==e(r)&&(I(r.r)&&I(r.g)&&I(r.b)?(f=r.r,p=r.g,m=r.b,u={r:255*S(f,255),g:255*S(p,255),b:255*S(m,255)},d=!0,D="%"===String(r.r).substr(-1)?"prgb":"rgb"):I(r.h)&&I(r.s)&&I(r.v)?(l=B(r.s),h=B(r.v),g=r.h,E=l,b=h,g=6*S(g,360),E=S(E,100),b=S(b,100),y=Math.floor(g),F=g-y,C=b*(1-E),w=b*(1-F*E),A=b*(1-(1-F)*E),u={r:255*[b,w,C,C,A,b][O=y%6],g:255*[A,b,b,w,C,C][O],b:255*[C,C,A,b,b,w][O]},d=!0,D="hsv"):I(r.h)&&I(r.s)&&I(r.l)&&(l=B(r.s),c=B(r.l),u=function(e,t,i){var r,n,s;function o(e,t,i){return(i<0&&(i+=1),i>1&&(i-=1),i<1/6)?e+(t-e)*6*i:i<.5?t:i<2/3?e+(t-e)*(2/3-i)*6:e}if(e=S(e,360),t=S(t,100),i=S(i,100),0===t)r=n=s=i;else{var u=i<.5?i*(1+t):i+t-i*t,a=2*i-u;r=o(a,u,e+1/3),n=o(a,u,e),s=o(a,u,e-1/3)}return{r:255*r,g:255*n,b:255*s}}(r.h,l,c),d=!0,D="hsl"),r.hasOwnProperty("a")&&(a=r.a)),a=_(a),{ok:d,format:r.format||D,r:Math.min(255,Math.max(u.r,0)),g:Math.min(255,Math.max(u.g,0)),b:Math.min(255,Math.max(u.b,0)),a:a});this._originalInput=t,this._r=x.r,this._g=x.g,this._b=x.b,this._a=x.a,this._roundA=Math.round(100*this._a)/100,this._format=i.format||x.format,this._gradientType=i.gradientType,this._r<1&&(this._r=Math.round(this._r)),this._g<1&&(this._g=Math.round(this._g)),this._b<1&&(this._b=Math.round(this._b)),this._ok=x.ok}function u(e,t,i){e=S(e,255);var r,n,s=Math.max(e,t=S(t,255),i=S(i,255)),o=Math.min(e,t,i),u=(s+o)/2;if(s==o)r=n=0;else{var a=s-o;switch(n=u>.5?a/(2-s-o):a/(s+o),s){case e:r=(t-i)/a+6*(t>1)+720)%360;--t;)r.h=(r.h+n)%360,s.push(o(r));return s}function C(e,t){t=t||6;for(var i=o(e).toHsv(),r=i.h,n=i.s,s=i.v,u=[],a=1/t;t--;)u.push(o({h:r,s:n,v:s})),s=(s+a)%1;return u}o.prototype={isDark:function(){return 128>this.getBrightness()},isLight:function(){return!this.isDark()},isValid:function(){return this._ok},getOriginalInput:function(){return this._originalInput},getFormat:function(){return this._format},getAlpha:function(){return this._a},getBrightness:function(){var e=this.toRgb();return(299*e.r+587*e.g+114*e.b)/1e3},getLuminance:function(){var e,t,i,r=this.toRgb();return e=r.r/255,t=r.g/255,.2126*(e<=.03928?e/12.92:Math.pow((e+.055)/1.055,2.4))+.7152*(t<=.03928?t/12.92:Math.pow((t+.055)/1.055,2.4))+.0722*((i=r.b/255)<=.03928?i/12.92:Math.pow((i+.055)/1.055,2.4))},setAlpha:function(e){return this._a=_(e),this._roundA=Math.round(100*this._a)/100,this},toHsv:function(){var e=a(this._r,this._g,this._b);return{h:360*e.h,s:e.s,v:e.v,a:this._a}},toHsvString:function(){var e=a(this._r,this._g,this._b),t=Math.round(360*e.h),i=Math.round(100*e.s),r=Math.round(100*e.v);return 1==this._a?"hsv("+t+", "+i+"%, "+r+"%)":"hsva("+t+", "+i+"%, "+r+"%, "+this._roundA+")"},toHsl:function(){var e=u(this._r,this._g,this._b);return{h:360*e.h,s:e.s,l:e.l,a:this._a}},toHslString:function(){var e=u(this._r,this._g,this._b),t=Math.round(360*e.h),i=Math.round(100*e.s),r=Math.round(100*e.l);return 1==this._a?"hsl("+t+", "+i+"%, "+r+"%)":"hsla("+t+", "+i+"%, "+r+"%, "+this._roundA+")"},toHex:function(e){return l(this._r,this._g,this._b,e)},toHexString:function(e){return"#"+this.toHex(e)},toHex8:function(e){var t,i,r,n,s,o;return t=this._r,i=this._g,r=this._b,n=this._a,s=e,o=[O(Math.round(t).toString(16)),O(Math.round(i).toString(16)),O(Math.round(r).toString(16)),O(x(n))],s&&o[0].charAt(0)==o[0].charAt(1)&&o[1].charAt(0)==o[1].charAt(1)&&o[2].charAt(0)==o[2].charAt(1)&&o[3].charAt(0)==o[3].charAt(1)?o[0].charAt(0)+o[1].charAt(0)+o[2].charAt(0)+o[3].charAt(0):o.join("")},toHex8String:function(e){return"#"+this.toHex8(e)},toRgb:function(){return{r:Math.round(this._r),g:Math.round(this._g),b:Math.round(this._b),a:this._a}},toRgbString:function(){return 1==this._a?"rgb("+Math.round(this._r)+", "+Math.round(this._g)+", "+Math.round(this._b)+")":"rgba("+Math.round(this._r)+", "+Math.round(this._g)+", "+Math.round(this._b)+", "+this._roundA+")"},toPercentageRgb:function(){return{r:Math.round(100*S(this._r,255))+"%",g:Math.round(100*S(this._g,255))+"%",b:Math.round(100*S(this._b,255))+"%",a:this._a}},toPercentageRgbString:function(){return 1==this._a?"rgb("+Math.round(100*S(this._r,255))+"%, "+Math.round(100*S(this._g,255))+"%, "+Math.round(100*S(this._b,255))+"%)":"rgba("+Math.round(100*S(this._r,255))+"%, "+Math.round(100*S(this._g,255))+"%, "+Math.round(100*S(this._b,255))+"%, "+this._roundA+")"},toName:function(){return 0===this._a?"transparent":!(this._a<1)&&(w[l(this._r,this._g,this._b,!0)]||!1)},toFilter:function(e){var t="#"+h(this._r,this._g,this._b,this._a),i=t,r=this._gradientType?"GradientType = 1, ":"";if(e){var n=o(e);i="#"+h(n._r,n._g,n._b,n._a)}return"progid:DXImageTransform.Microsoft.gradient("+r+"startColorstr="+t+",endColorstr="+i+")"},toString:function(e){var t=!!e;e=e||this._format;var i=!1,r=this._a<1&&this._a>=0;return!t&&r&&("hex"===e||"hex6"===e||"hex3"===e||"hex4"===e||"hex8"===e||"name"===e)?"name"===e&&0===this._a?this.toName():this.toRgbString():("rgb"===e&&(i=this.toRgbString()),"prgb"===e&&(i=this.toPercentageRgbString()),("hex"===e||"hex6"===e)&&(i=this.toHexString()),"hex3"===e&&(i=this.toHexString(!0)),"hex4"===e&&(i=this.toHex8String(!0)),"hex8"===e&&(i=this.toHex8String()),"name"===e&&(i=this.toName()),"hsl"===e&&(i=this.toHslString()),"hsv"===e&&(i=this.toHsvString()),i||this.toHexString())},clone:function(){return o(this.toString())},_applyModification:function(e,t){var i=e.apply(null,[this].concat([].slice.call(t)));return this._r=i._r,this._g=i._g,this._b=i._b,this.setAlpha(i._a),this},lighten:function(){return this._applyModification(f,arguments)},brighten:function(){return this._applyModification(p,arguments)},darken:function(){return this._applyModification(m,arguments)},desaturate:function(){return this._applyModification(c,arguments)},saturate:function(){return this._applyModification(d,arguments)},greyscale:function(){return this._applyModification(D,arguments)},spin:function(){return this._applyModification(g,arguments)},_applyCombination:function(e,t){return e.apply(null,[this].concat([].slice.call(t)))},analogous:function(){return this._applyCombination(F,arguments)},complement:function(){return this._applyCombination(E,arguments)},monochromatic:function(){return this._applyCombination(C,arguments)},splitcomplement:function(){return this._applyCombination(y,arguments)},triad:function(){return this._applyCombination(b,[3])},tetrad:function(){return this._applyCombination(b,[4])}},o.fromRatio=function(t,i){if("object"==e(t)){var r={};for(var n in t)t.hasOwnProperty(n)&&("a"===n?r[n]=t[n]:r[n]=B(t[n]));t=r}return o(t,i)},o.equals=function(e,t){return!!e&&!!t&&o(e).toRgbString()==o(t).toRgbString()},o.random=function(){return o.fromRatio({r:Math.random(),g:Math.random(),b:Math.random()})},o.mix=function(e,t,i){i=0===i?0:i||50;var r=o(e).toRgb(),n=o(t).toRgb(),s=i/100;return o({r:(n.r-r.r)*s+r.r,g:(n.g-r.g)*s+r.g,b:(n.b-r.b)*s+r.b,a:(n.a-r.a)*s+r.a})},o.readability=function(e,t){var i=o(e),r=o(t);return(Math.max(i.getLuminance(),r.getLuminance())+.05)/(Math.min(i.getLuminance(),r.getLuminance())+.05)},o.isReadable=function(e,t,i){var r,n,s,u,a,l=o.readability(e,t);switch(a=!1,(n=((r=(r=i)||{level:"AA",size:"small"}).level||"AA").toUpperCase(),s=(r.size||"small").toLowerCase(),"AA"!==n&&"AAA"!==n&&(n="AA"),"small"!==s&&"large"!==s&&(s="small"),u={level:n,size:s}).level+u.size){case"AAsmall":case"AAAlarge":a=l>=4.5;break;case"AAlarge":a=l>=3;break;case"AAAsmall":a=l>=7}return a},o.mostReadable=function(e,t,i){var r,n,s,u,a=null,l=0;n=(i=i||{}).includeFallbackColors,s=i.level,u=i.size;for(var h=0;hl&&(l=r,a=o(t[h]));return o.isReadable(e,a,{level:s,size:u})||!n?a:(i.includeFallbackColors=!1,o.mostReadable(e,["#fff","#000"],i))};var v=o.names={aliceblue:"f0f8ff",antiquewhite:"faebd7",aqua:"0ff",aquamarine:"7fffd4",azure:"f0ffff",beige:"f5f5dc",bisque:"ffe4c4",black:"000",blanchedalmond:"ffebcd",blue:"00f",blueviolet:"8a2be2",brown:"a52a2a",burlywood:"deb887",burntsienna:"ea7e5d",cadetblue:"5f9ea0",chartreuse:"7fff00",chocolate:"d2691e",coral:"ff7f50",cornflowerblue:"6495ed",cornsilk:"fff8dc",crimson:"dc143c",cyan:"0ff",darkblue:"00008b",darkcyan:"008b8b",darkgoldenrod:"b8860b",darkgray:"a9a9a9",darkgreen:"006400",darkgrey:"a9a9a9",darkkhaki:"bdb76b",darkmagenta:"8b008b",darkolivegreen:"556b2f",darkorange:"ff8c00",darkorchid:"9932cc",darkred:"8b0000",darksalmon:"e9967a",darkseagreen:"8fbc8f",darkslateblue:"483d8b",darkslategray:"2f4f4f",darkslategrey:"2f4f4f",darkturquoise:"00ced1",darkviolet:"9400d3",deeppink:"ff1493",deepskyblue:"00bfff",dimgray:"696969",dimgrey:"696969",dodgerblue:"1e90ff",firebrick:"b22222",floralwhite:"fffaf0",forestgreen:"228b22",fuchsia:"f0f",gainsboro:"dcdcdc",ghostwhite:"f8f8ff",gold:"ffd700",goldenrod:"daa520",gray:"808080",green:"008000",greenyellow:"adff2f",grey:"808080",honeydew:"f0fff0",hotpink:"ff69b4",indianred:"cd5c5c",indigo:"4b0082",ivory:"fffff0",khaki:"f0e68c",lavender:"e6e6fa",lavenderblush:"fff0f5",lawngreen:"7cfc00",lemonchiffon:"fffacd",lightblue:"add8e6",lightcoral:"f08080",lightcyan:"e0ffff",lightgoldenrodyellow:"fafad2",lightgray:"d3d3d3",lightgreen:"90ee90",lightgrey:"d3d3d3",lightpink:"ffb6c1",lightsalmon:"ffa07a",lightseagreen:"20b2aa",lightskyblue:"87cefa",lightslategray:"789",lightslategrey:"789",lightsteelblue:"b0c4de",lightyellow:"ffffe0",lime:"0f0",limegreen:"32cd32",linen:"faf0e6",magenta:"f0f",maroon:"800000",mediumaquamarine:"66cdaa",mediumblue:"0000cd",mediumorchid:"ba55d3",mediumpurple:"9370db",mediumseagreen:"3cb371",mediumslateblue:"7b68ee",mediumspringgreen:"00fa9a",mediumturquoise:"48d1cc",mediumvioletred:"c71585",midnightblue:"191970",mintcream:"f5fffa",mistyrose:"ffe4e1",moccasin:"ffe4b5",navajowhite:"ffdead",navy:"000080",oldlace:"fdf5e6",olive:"808000",olivedrab:"6b8e23",orange:"ffa500",orangered:"ff4500",orchid:"da70d6",palegoldenrod:"eee8aa",palegreen:"98fb98",paleturquoise:"afeeee",palevioletred:"db7093",papayawhip:"ffefd5",peachpuff:"ffdab9",peru:"cd853f",pink:"ffc0cb",plum:"dda0dd",powderblue:"b0e0e6",purple:"800080",rebeccapurple:"663399",red:"f00",rosybrown:"bc8f8f",royalblue:"4169e1",saddlebrown:"8b4513",salmon:"fa8072",sandybrown:"f4a460",seagreen:"2e8b57",seashell:"fff5ee",sienna:"a0522d",silver:"c0c0c0",skyblue:"87ceeb",slateblue:"6a5acd",slategray:"708090",slategrey:"708090",snow:"fffafa",springgreen:"00ff7f",steelblue:"4682b4",tan:"d2b48c",teal:"008080",thistle:"d8bfd8",tomato:"ff6347",turquoise:"40e0d0",violet:"ee82ee",wheat:"f5deb3",white:"fff",whitesmoke:"f5f5f5",yellow:"ff0",yellowgreen:"9acd32"},w=o.hexNames=function(e){var t={};for(var i in e)e.hasOwnProperty(i)&&(t[e[i]]=i);return t}(v);function _(e){return(isNaN(e=parseFloat(e))||e<0||e>1)&&(e=1),e}function S(e,t){"string"==typeof(i=e)&&-1!=i.indexOf(".")&&1===parseFloat(i)&&(e="100%");var i,r,n="string"==typeof(r=e)&&-1!=r.indexOf("%");return(e=Math.min(t,Math.max(0,parseFloat(e))),n&&(e=parseInt(e*t,10)/100),1e-6>Math.abs(e-t))?1:e%t/parseFloat(t)}function A(e){return Math.min(1,Math.max(0,e))}function R(e){return parseInt(e,16)}function O(e){return 1==e.length?"0"+e:""+e}function B(e){return e<=1&&(e=100*e+"%"),e}function x(e){return Math.round(255*parseFloat(e)).toString(16)}var N=(i="[\\s|\\(]+("+(t="(?:[-\\+]?\\d*\\.\\d+%?)|(?:[-\\+]?\\d+%?)")+")[,|\\s]+("+t+")[,|\\s]+("+t+")\\s*\\)?",r="[\\s|\\(]+("+t+")[,|\\s]+("+t+")[,|\\s]+("+t+")[,|\\s]+("+t+")\\s*\\)?",{CSS_UNIT:new RegExp(t),rgb:RegExp("rgb"+i),rgba:RegExp("rgba"+r),hsl:RegExp("hsl"+i),hsla:RegExp("hsla"+r),hsv:RegExp("hsv"+i),hsva:RegExp("hsva"+r),hex3:/^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex6:/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,hex4:/^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex8:/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/});function I(e){return!!N.CSS_UNIT.exec(e)}return o}()}},et={};function ei(e){var t=et[e];if(void 0!==t)return t.exports;var i=et[e]={exports:{}};return ee[e].call(i.exports,i,i.exports,ei),i.exports}K="function"==typeof Symbol?Symbol("webpack queues"):"__webpack_queues__",q="function"==typeof Symbol?Symbol("webpack exports"):"__webpack_exports__",J="function"==typeof Symbol?Symbol("webpack error"):"__webpack_error__",Q=e=>{e&&e.d<1&&(e.d=1,e.forEach(e=>e.r--),e.forEach(e=>e.r--?e.r++:e()))},ei.a=(e,t,i)=>{i&&((r=[]).d=-1);var r,n,s,o,u=new Set,a=e.exports,l=new Promise((e,t)=>{o=t,s=e});l[q]=a,l[K]=e=>{r&&e(r),u.forEach(e),l.catch(function(){})},e.exports=l,t(e=>{n=e.map(e=>{if(null!==e&&"object"==typeof e){if(e[K])return e;if(e.then){var t=[];t.d=0,e.then(e=>{i[q]=e,Q(t)},e=>{i[J]=e,Q(t)});var i={};return i[K]=e=>e(t),i}}var r={};return r[K]=function(){},r[q]=e,r});var t,i=()=>n.map(e=>{if(e[J])throw e[J];return e[q]}),s=new Promise(e=>{(t=()=>e(i)).r=0;var s=e=>e!==r&&!u.has(e)&&(u.add(e),e&&!e.d&&(t.r++,e.push(t)));n.map(e=>e[K](s))});return t.r?s:i()},e=>(e?o(l[J]=e):s(a),Q(r))),r&&r.d<0&&(r.d=0)},ei.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return ei.d(t,{a:t}),t},ei.d=(e,t)=>{for(var i in t)ei.o(t,i)&&!ei.o(e,i)&&Object.defineProperty(e,i,{enumerable:!0,get:t[i]})},ei.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),ei.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},ei("./src/bin.ts");
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/index.d.ts b/packages/platform-android/dist/src/index.d.ts
new file mode 100644
index 000000000..5d9b6a5c6
--- /dev/null
+++ b/packages/platform-android/dist/src/index.d.ts
@@ -0,0 +1,3 @@
+export * from './lib/platformAndroid.js';
+export { type PackageAarFlags, packageAar, options as packageAarOptions, } from './lib/commands/aar/packageAar.js';
+export { publishLocalAar, options as publishLocalAarOptions, } from './lib/commands/aar/publishLocalAar.js';
diff --git a/packages/platform-android/dist/src/index.js b/packages/platform-android/dist/src/index.js
new file mode 100644
index 000000000..3d946d010
--- /dev/null
+++ b/packages/platform-android/dist/src/index.js
@@ -0,0 +1,4 @@
+export * from './lib/platformAndroid.js';
+export { packageAar, options as packageAarOptions, } from './lib/commands/aar/packageAar.js';
+export { publishLocalAar, options as publishLocalAarOptions, } from './lib/commands/aar/publishLocalAar.js';
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/index.js.map b/packages/platform-android/dist/src/index.js.map
new file mode 100644
index 000000000..ad327389f
--- /dev/null
+++ b/packages/platform-android/dist/src/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAC;AACzC,OAAO,EAEL,UAAU,EACV,OAAO,IAAI,iBAAiB,GAC7B,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EACL,eAAe,EACf,OAAO,IAAI,sBAAsB,GAClC,MAAM,uCAAuC,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/lib/commands/aar/packageAar.d.ts b/packages/platform-android/dist/src/lib/commands/aar/packageAar.d.ts
new file mode 100644
index 000000000..2e62fcf4f
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/aar/packageAar.d.ts
@@ -0,0 +1,14 @@
+export interface AarProject {
+ sourceDir: string;
+ moduleName: string;
+}
+export type PackageAarFlags = {
+ variant: string;
+ moduleName?: string;
+};
+export declare function packageAar(aarProject: AarProject, args: PackageAarFlags): Promise;
+export declare function localPublishAar(aarProject: AarProject, args: PackageAarFlags): Promise;
+export declare const options: {
+ name: string;
+ description: string;
+}[];
diff --git a/packages/platform-android/dist/src/lib/commands/aar/packageAar.js b/packages/platform-android/dist/src/lib/commands/aar/packageAar.js
new file mode 100644
index 000000000..2d542d4c7
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/aar/packageAar.js
@@ -0,0 +1,34 @@
+import { outro } from '@rock-js/tools';
+import { runGradleAar } from '../runGradle.js';
+import { toPascalCase } from '../toPascalCase.js';
+export async function packageAar(aarProject, args) {
+ normalizeArgs(args);
+ const tasks = [`assemble${toPascalCase(args.variant)}`];
+ await runGradleAar({ tasks, aarProject, variant: args.variant });
+ outro('Success ๐.');
+}
+export async function localPublishAar(aarProject, args) {
+ const tasks = ['publishToMavenLocal'];
+ await runGradleAar({
+ tasks,
+ aarProject,
+ variant: args.variant,
+ });
+ outro('Success ๐.');
+}
+function normalizeArgs(args) {
+ if (!args.variant) {
+ args.variant = 'debug';
+ }
+}
+export const options = [
+ {
+ name: '--variant ',
+ description: "Specify your app's build variant, which is constructed from build type and product flavor, e.g. 'debug' or 'freeRelease'.",
+ },
+ {
+ name: '--module-name ',
+ description: 'AAR module name',
+ },
+];
+//# sourceMappingURL=packageAar.js.map
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/lib/commands/aar/packageAar.js.map b/packages/platform-android/dist/src/lib/commands/aar/packageAar.js.map
new file mode 100644
index 000000000..013ee5f0f
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/aar/packageAar.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"packageAar.js","sourceRoot":"","sources":["../../../../../src/lib/commands/aar/packageAar.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAYlD,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,UAAsB,EACtB,IAAqB;IAErB,aAAa,CAAC,IAAI,CAAC,CAAC;IAEpB,MAAM,KAAK,GAAG,CAAC,WAAW,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAExD,MAAM,YAAY,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;IACjE,KAAK,CAAC,aAAa,CAAC,CAAC;AACvB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,UAAsB,EACtB,IAAqB;IAErB,MAAM,KAAK,GAAG,CAAC,qBAAqB,CAAC,CAAC;IAEtC,MAAM,YAAY,CAAC;QACjB,KAAK;QACL,UAAU;QACV,OAAO,EAAE,IAAI,CAAC,OAAO;KACtB,CAAC,CAAC;IACH,KAAK,CAAC,aAAa,CAAC,CAAC;AACvB,CAAC;AAED,SAAS,aAAa,CAAC,IAAqB;IAC1C,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;QAClB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB;QACE,IAAI,EAAE,oBAAoB;QAC1B,WAAW,EACT,2HAA2H;KAC9H;IACD;QACE,IAAI,EAAE,wBAAwB;QAC9B,WAAW,EAAE,iBAAiB;KAC/B;CACF,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/lib/commands/aar/publishLocalAar.d.ts b/packages/platform-android/dist/src/lib/commands/aar/publishLocalAar.d.ts
new file mode 100644
index 000000000..5126fb7bd
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/aar/publishLocalAar.d.ts
@@ -0,0 +1,6 @@
+import type { AarProject } from './packageAar.js';
+export declare function publishLocalAar(aarProject: AarProject): Promise;
+export declare const options: {
+ name: string;
+ description: string;
+}[];
diff --git a/packages/platform-android/dist/src/lib/commands/aar/publishLocalAar.js b/packages/platform-android/dist/src/lib/commands/aar/publishLocalAar.js
new file mode 100644
index 000000000..a853f7b2f
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/aar/publishLocalAar.js
@@ -0,0 +1,17 @@
+import { outro } from '@rock-js/tools';
+import { runGradleAar } from '../runGradle.js';
+export async function publishLocalAar(aarProject) {
+ const tasks = ['publishToMavenLocal'];
+ await runGradleAar({
+ tasks,
+ aarProject,
+ });
+ outro('Success ๐.');
+}
+export const options = [
+ {
+ name: '--module-name ',
+ description: 'AAR module name',
+ },
+];
+//# sourceMappingURL=publishLocalAar.js.map
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/lib/commands/aar/publishLocalAar.js.map b/packages/platform-android/dist/src/lib/commands/aar/publishLocalAar.js.map
new file mode 100644
index 000000000..e3fae0cdb
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/aar/publishLocalAar.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"publishLocalAar.js","sourceRoot":"","sources":["../../../../../src/lib/commands/aar/publishLocalAar.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAG/C,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,UAAsB;IAC1D,MAAM,KAAK,GAAG,CAAC,qBAAqB,CAAC,CAAC;IAEtC,MAAM,YAAY,CAAC;QACjB,KAAK;QACL,UAAU;KACX,CAAC,CAAC;IACH,KAAK,CAAC,aAAa,CAAC,CAAC;AACvB,CAAC;AAED,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB;QACE,IAAI,EAAE,wBAAwB;QAC9B,WAAW,EAAE,iBAAiB;KAC/B;CACF,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/lib/commands/buildAndroid/buildAndroid.d.ts b/packages/platform-android/dist/src/lib/commands/buildAndroid/buildAndroid.d.ts
new file mode 100644
index 000000000..b936afea2
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/buildAndroid/buildAndroid.d.ts
@@ -0,0 +1,21 @@
+import type { AndroidProjectConfig } from '@react-native-community/cli-types';
+import type { RemoteBuildCache } from '@rock-js/tools';
+import { type FingerprintSources } from '@rock-js/tools';
+export interface BuildFlags {
+ variant: string;
+ aab?: boolean;
+ activeArchOnly?: boolean;
+ tasks?: Array;
+ extraParams?: Array;
+ local?: boolean;
+}
+export declare function buildAndroid(androidProject: AndroidProjectConfig, args: BuildFlags, projectRoot: string, remoteCacheProvider: null | (() => RemoteBuildCache) | undefined, fingerprintOptions: FingerprintSources): Promise;
+export declare const options: ({
+ name: string;
+ description: string;
+ parse?: undefined;
+} | {
+ name: string;
+ description: string;
+ parse: (val: string) => string[];
+})[];
diff --git a/packages/platform-android/dist/src/lib/commands/buildAndroid/buildAndroid.js b/packages/platform-android/dist/src/lib/commands/buildAndroid/buildAndroid.js
new file mode 100644
index 000000000..873eeffbb
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/buildAndroid/buildAndroid.js
@@ -0,0 +1,69 @@
+import { colorLink, formatArtifactName, getBinaryPath, logger, outro, parseArgs, relativeToCwd, } from '@rock-js/tools';
+import { findOutputFile } from '../runAndroid/findOutputFile.js';
+import { runGradle } from '../runGradle.js';
+import { toPascalCase } from '../toPascalCase.js';
+export async function buildAndroid(androidProject, args, projectRoot, remoteCacheProvider, fingerprintOptions) {
+ normalizeArgs(args);
+ // Use assemble task by default, but bundle if the flag is set
+ const buildTaskBase = args.aab ? 'bundle' : 'assemble';
+ const tasks = args.tasks ?? [`${buildTaskBase}${toPascalCase(args.variant)}`];
+ const artifactName = await formatArtifactName({
+ platform: 'android',
+ traits: [args.variant],
+ root: projectRoot,
+ fingerprintOptions,
+ });
+ const binaryPath = await getBinaryPath({
+ platformName: 'android',
+ artifactName,
+ localFlag: args.local,
+ remoteCacheProvider,
+ fingerprintOptions,
+ sourceDir: androidProject.sourceDir,
+ });
+ if (!binaryPath) {
+ await runGradle({ tasks, androidProject, args, artifactName });
+ }
+ const outputFilePath = binaryPath ?? (await findOutputFile(androidProject, tasks));
+ if (outputFilePath) {
+ logger.log(`Build available at: ${colorLink(relativeToCwd(outputFilePath))}`);
+ }
+ outro('Success ๐.');
+}
+function normalizeArgs(args) {
+ if (args.tasks && args.variant) {
+ logger.warn('Both "--tasks" and "--variant" parameters were passed. Using "--tasks" for building the app.');
+ }
+ if (!args.variant) {
+ args.variant = 'debug';
+ }
+}
+export const options = [
+ {
+ name: '--variant ',
+ description: `Specify your app's build variant, which is constructed from build type and product flavor, e.g. "debug" or "freeRelease".`,
+ },
+ {
+ name: '--aab',
+ description: 'Produces an Android App Bundle (AAB) suited for app stores such as Google Play. If not set, APK is created.',
+ },
+ {
+ name: '--tasks ',
+ description: 'Run custom Gradle tasks. Will override the "--variant" and "--bundle" arguments.',
+ parse: (val) => val.split(','),
+ },
+ {
+ name: '--active-arch-only',
+ description: 'Build native libraries only for the current device architecture. Set by default in debug builds and interactive environments.',
+ },
+ {
+ name: '--extra-params ',
+ description: 'Custom params passed to gradle build command',
+ parse: parseArgs,
+ },
+ {
+ name: '--local',
+ description: 'Force local build with Gradle wrapper.',
+ },
+];
+//# sourceMappingURL=buildAndroid.js.map
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/lib/commands/buildAndroid/buildAndroid.js.map b/packages/platform-android/dist/src/lib/commands/buildAndroid/buildAndroid.js.map
new file mode 100644
index 000000000..3ec0c8f8e
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/buildAndroid/buildAndroid.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"buildAndroid.js","sourceRoot":"","sources":["../../../../../src/lib/commands/buildAndroid/buildAndroid.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,SAAS,EAET,kBAAkB,EAClB,aAAa,EACb,MAAM,EACN,KAAK,EACL,SAAS,EACT,aAAa,GACd,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAWlD,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,cAAoC,EACpC,IAAgB,EAChB,WAAmB,EACnB,mBAAgE,EAChE,kBAAsC;IAEtC,aAAa,CAAC,IAAI,CAAC,CAAC;IACpB,8DAA8D;IAC9D,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC;IACvD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,CAAC,GAAG,aAAa,GAAG,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC9E,MAAM,YAAY,GAAG,MAAM,kBAAkB,CAAC;QAC5C,QAAQ,EAAE,SAAS;QACnB,MAAM,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC;QACtB,IAAI,EAAE,WAAW;QACjB,kBAAkB;KACnB,CAAC,CAAC;IACH,MAAM,UAAU,GAAG,MAAM,aAAa,CAAC;QACrC,YAAY,EAAE,SAAS;QACvB,YAAY;QACZ,SAAS,EAAE,IAAI,CAAC,KAAK;QACrB,mBAAmB;QACnB,kBAAkB;QAClB,SAAS,EAAE,cAAc,CAAC,SAAS;KACpC,CAAC,CAAC;IACH,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,SAAS,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC;IACjE,CAAC;IAED,MAAM,cAAc,GAClB,UAAU,IAAI,CAAC,MAAM,cAAc,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC,CAAC;IAE9D,IAAI,cAAc,EAAE,CAAC;QACnB,MAAM,CAAC,GAAG,CACR,uBAAuB,SAAS,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC,EAAE,CAClE,CAAC;IACJ,CAAC;IACD,KAAK,CAAC,aAAa,CAAC,CAAC;AACvB,CAAC;AAED,SAAS,aAAa,CAAC,IAAgB;IACrC,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;QAC/B,MAAM,CAAC,IAAI,CACT,8FAA8F,CAC/F,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;QAClB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB;QACE,IAAI,EAAE,oBAAoB;QAC1B,WAAW,EAAE,2HAA2H;KACzI;IACD;QACE,IAAI,EAAE,OAAO;QACb,WAAW,EACT,6GAA6G;KAChH;IACD;QACE,IAAI,EAAE,gBAAgB;QACtB,WAAW,EACT,kFAAkF;QACpF,KAAK,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC;KACvC;IACD;QACE,IAAI,EAAE,oBAAoB;QAC1B,WAAW,EACT,+HAA+H;KAClI;IACD;QACE,IAAI,EAAE,yBAAyB;QAC/B,WAAW,EAAE,8CAA8C;QAC3D,KAAK,EAAE,SAAS;KACjB;IACD;QACE,IAAI,EAAE,SAAS;QACf,WAAW,EAAE,wCAAwC;KACtD;CACF,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/lib/commands/buildAndroid/command.d.ts b/packages/platform-android/dist/src/lib/commands/buildAndroid/command.d.ts
new file mode 100644
index 000000000..9dc586b7c
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/buildAndroid/command.d.ts
@@ -0,0 +1,3 @@
+import type { AndroidProjectConfig } from '@react-native-community/cli-types';
+import type { PluginApi } from '@rock-js/config';
+export declare function registerBuildCommand(api: PluginApi, pluginConfig: Partial | undefined): void;
diff --git a/packages/platform-android/dist/src/lib/commands/buildAndroid/command.js b/packages/platform-android/dist/src/lib/commands/buildAndroid/command.js
new file mode 100644
index 000000000..b16a010cc
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/buildAndroid/command.js
@@ -0,0 +1,14 @@
+import { getValidProjectConfig } from '../getValidProjectConfig.js';
+import { buildAndroid, options } from './buildAndroid.js';
+export function registerBuildCommand(api, pluginConfig) {
+ api.registerCommand({
+ name: 'build:android',
+ description: 'Builds your app for Android platform.',
+ action: async (args) => {
+ const androidConfig = getValidProjectConfig(api.getProjectRoot(), pluginConfig);
+ await buildAndroid(androidConfig, args, api.getProjectRoot(), await api.getRemoteCacheProvider(), api.getFingerprintOptions());
+ },
+ options: options,
+ });
+}
+//# sourceMappingURL=command.js.map
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/lib/commands/buildAndroid/command.js.map b/packages/platform-android/dist/src/lib/commands/buildAndroid/command.js.map
new file mode 100644
index 000000000..2089f8886
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/buildAndroid/command.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"command.js","sourceRoot":"","sources":["../../../../../src/lib/commands/buildAndroid/command.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AAEpE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAE1D,MAAM,UAAU,oBAAoB,CAClC,GAAc,EACd,YAAuD;IAEvD,GAAG,CAAC,eAAe,CAAC;QAClB,IAAI,EAAE,eAAe;QACrB,WAAW,EAAE,uCAAuC;QACpD,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YACrB,MAAM,aAAa,GAAG,qBAAqB,CACzC,GAAG,CAAC,cAAc,EAAE,EACpB,YAAY,CACb,CAAC;YACF,MAAM,YAAY,CAChB,aAAa,EACb,IAAkB,EAClB,GAAG,CAAC,cAAc,EAAE,EACpB,MAAM,GAAG,CAAC,sBAAsB,EAAE,EAClC,GAAG,CAAC,qBAAqB,EAAE,CAC5B,CAAC;QACJ,CAAC;QACD,OAAO,EAAE,OAAO;KACjB,CAAC,CAAC;AACL,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/lib/commands/generateKeystore.d.ts b/packages/platform-android/dist/src/lib/commands/generateKeystore.d.ts
new file mode 100644
index 000000000..2d8b9b39e
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/generateKeystore.d.ts
@@ -0,0 +1,13 @@
+import type { AndroidProjectConfig } from '@react-native-community/cli-types';
+import type { PluginApi } from '@rock-js/config';
+export declare function registerCreateKeystoreCommand(api: PluginApi, pluginConfig: Partial | undefined): void;
+export declare function generateKeystore(androidProject: AndroidProjectConfig, args: Flags): Promise;
+type Flags = {
+ name?: string;
+ alias?: string;
+};
+export declare const generateKeystoreOptions: {
+ name: string;
+ description: string;
+}[];
+export {};
diff --git a/packages/platform-android/dist/src/lib/commands/generateKeystore.js b/packages/platform-android/dist/src/lib/commands/generateKeystore.js
new file mode 100644
index 000000000..0e65a454a
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/generateKeystore.js
@@ -0,0 +1,80 @@
+import path from 'node:path';
+import { color, colorLink, intro, logger, outro, promptGroup, promptText, RockError, spawn, } from '@rock-js/tools';
+import { getValidProjectConfig } from './getValidProjectConfig.js';
+export function registerCreateKeystoreCommand(api, pluginConfig) {
+ api.registerCommand({
+ name: 'create-keystore:android',
+ description: 'Creates a keystore file for signing Android release builds.',
+ action: async (args) => {
+ const androidConfig = getValidProjectConfig(api.getProjectRoot(), pluginConfig);
+ await generateKeystore(androidConfig, args);
+ },
+ options: generateKeystoreOptions,
+ });
+}
+export async function generateKeystore(androidProject, args) {
+ intro('Generate a keystore file for signing Android release builds.');
+ await runKeytool(androidProject, args);
+ outro('Success ๐.');
+}
+async function runKeytool(androidProject, args) {
+ const { name, alias } = await prompts({ name: args.name, alias: args.alias });
+ const keystoreOutputPath = path.join(androidProject.sourceDir, androidProject.appName, `${name}.keystore`);
+ logger.info(`Running "keytool" command. You'll be further prompted for password and extra information.`);
+ logger.log('');
+ try {
+ // keytool -genkey -v -keystore release.keystore -alias rock-alias -keyalg RSA -keysize 2048 -validity 10000
+ await spawn('keytool', [
+ '-genkey',
+ '-v',
+ '-keystore',
+ keystoreOutputPath,
+ '-alias',
+ alias,
+ '-keyalg',
+ 'RSA',
+ '-keysize',
+ '2048',
+ '-validity',
+ '10000',
+ ], { stdio: 'inherit' });
+ logger.success(`Keystore generated at: ${colorLink(keystoreOutputPath)}`);
+ logger.warn(`Edit the ${colorLink('~/.gradle/gradle.properties')} or ${colorLink('./android/gradle.properties')} file, and add the following (replace ***** with the correct keystore password):`);
+ // use console log to make it easy to copy-paste without messing with "|" characters injected by `logger.log`
+ console.log(color.yellow(`
+ ROCK_UPLOAD_STORE_FILE=release.keystore
+ ROCK_UPLOAD_KEY_ALIAS=rock-alias
+ ROCK_UPLOAD_STORE_PASSWORD=*****
+ ROCK_UPLOAD_KEY_PASSWORD=*****`));
+ }
+ catch (error) {
+ throw new RockError(`Failed to generate keystore. Please try manually by following instructions at: ${colorLink('https://reactnative.dev/docs/signed-apk-android')}`, { cause: error.stderr });
+ }
+}
+async function prompts({ name, alias }) {
+ return promptGroup({
+ name: () => name
+ ? Promise.resolve(name)
+ : promptText({
+ message: 'Provide keystore name',
+ initialValue: 'release',
+ }),
+ alias: () => alias
+ ? Promise.resolve(alias)
+ : promptText({
+ message: 'Provide keystore alias',
+ initialValue: 'rock-alias',
+ }),
+ });
+}
+export const generateKeystoreOptions = [
+ {
+ name: '--name ',
+ description: 'Name of the keystore file.',
+ },
+ {
+ name: '--alias ',
+ description: 'Alias for the key.',
+ },
+];
+//# sourceMappingURL=generateKeystore.js.map
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/lib/commands/generateKeystore.js.map b/packages/platform-android/dist/src/lib/commands/generateKeystore.js.map
new file mode 100644
index 000000000..c38b13f99
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/generateKeystore.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"generateKeystore.js","sourceRoot":"","sources":["../../../../src/lib/commands/generateKeystore.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/lib/commands/getValidProjectConfig.d.ts b/packages/platform-android/dist/src/lib/commands/getValidProjectConfig.d.ts
new file mode 100644
index 000000000..ab987ec29
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/getValidProjectConfig.d.ts
@@ -0,0 +1,2 @@
+import type { AndroidProjectConfig } from '@react-native-community/cli-types';
+export declare function getValidProjectConfig(projectRoot: string, pluginConfig?: Partial): AndroidProjectConfig;
diff --git a/packages/platform-android/dist/src/lib/commands/getValidProjectConfig.js b/packages/platform-android/dist/src/lib/commands/getValidProjectConfig.js
new file mode 100644
index 000000000..b785053c2
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/getValidProjectConfig.js
@@ -0,0 +1,10 @@
+import { projectConfig } from '@react-native-community/cli-config-android';
+import { RockError } from '@rock-js/tools';
+export function getValidProjectConfig(projectRoot, pluginConfig) {
+ const androidConfig = projectConfig(projectRoot, pluginConfig);
+ if (!androidConfig) {
+ throw new RockError('Android project not found.');
+ }
+ return androidConfig;
+}
+//# sourceMappingURL=getValidProjectConfig.js.map
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/lib/commands/getValidProjectConfig.js.map b/packages/platform-android/dist/src/lib/commands/getValidProjectConfig.js.map
new file mode 100644
index 000000000..d0a6cf7eb
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/getValidProjectConfig.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"getValidProjectConfig.js","sourceRoot":"","sources":["../../../../src/lib/commands/getValidProjectConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,4CAA4C,CAAC;AAE3E,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,MAAM,UAAU,qBAAqB,CACnC,WAAmB,EACnB,YAA4C;IAE5C,MAAM,aAAa,GAAG,aAAa,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;IAC/D,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,MAAM,IAAI,SAAS,CAAC,4BAA4B,CAAC,CAAC;IACpD,CAAC;IACD,OAAO,aAAa,CAAC;AACvB,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/adb.d.ts b/packages/platform-android/dist/src/lib/commands/runAndroid/adb.d.ts
new file mode 100644
index 000000000..de1b858a8
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/runAndroid/adb.d.ts
@@ -0,0 +1,5 @@
+export declare function getAdbPath(): string;
+/**
+ * Executes the commands needed to get a list of devices from ADB
+ */
+export declare function getDevices(): Promise;
diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/adb.js b/packages/platform-android/dist/src/lib/commands/runAndroid/adb.js
new file mode 100644
index 000000000..85d25088f
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/runAndroid/adb.js
@@ -0,0 +1,38 @@
+import path from 'node:path';
+import { spawn } from '@rock-js/tools';
+export function getAdbPath() {
+ return process.env['ANDROID_HOME']
+ ? path.join(process.env['ANDROID_HOME'], 'platform-tools', 'adb')
+ : 'adb';
+}
+/**
+ * Parses the output of the 'adb devices' command
+ */
+function parseDevicesResult(result) {
+ if (!result) {
+ return [];
+ }
+ const devices = [];
+ const lines = result.trim().split(/\r?\n/);
+ for (let i = 0; i < lines.length; i++) {
+ const words = lines[i].split(/[ ,\t]+/).filter((w) => w !== '');
+ if (words[1] === 'device') {
+ devices.push(words[0]);
+ }
+ }
+ return devices;
+}
+/**
+ * Executes the commands needed to get a list of devices from ADB
+ */
+export async function getDevices() {
+ const adbPath = getAdbPath();
+ try {
+ const { output } = await spawn(adbPath, ['devices'], { stdio: 'pipe' });
+ return parseDevicesResult(output);
+ }
+ catch {
+ return [];
+ }
+}
+//# sourceMappingURL=adb.js.map
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/adb.js.map b/packages/platform-android/dist/src/lib/commands/runAndroid/adb.js.map
new file mode 100644
index 000000000..9e25f1e5f
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/runAndroid/adb.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"adb.js","sourceRoot":"","sources":["../../../../../src/lib/commands/runAndroid/adb.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAEvC,MAAM,UAAU,UAAU;IACxB,OAAO,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;QAChC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,gBAAgB,EAAE,KAAK,CAAC;QACjE,CAAC,CAAC,KAAK,CAAC;AACZ,CAAC;AAED;;GAEG;AACH,SAAS,kBAAkB,CAAC,MAAc;IACxC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,OAAO,GAAG,EAAE,CAAC;IACnB,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAE3C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;QAEhE,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,QAAQ,EAAE,CAAC;YAC1B,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC,SAAS,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QACxE,OAAO,kBAAkB,CAAC,MAAM,CAAC,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/command.d.ts b/packages/platform-android/dist/src/lib/commands/runAndroid/command.d.ts
new file mode 100644
index 000000000..009106a88
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/runAndroid/command.d.ts
@@ -0,0 +1,3 @@
+import type { AndroidProjectConfig } from '@react-native-community/cli-types';
+import type { PluginApi } from '@rock-js/config';
+export declare function registerRunCommand(api: PluginApi, pluginConfig: Partial | undefined): void;
diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/command.js b/packages/platform-android/dist/src/lib/commands/runAndroid/command.js
new file mode 100644
index 000000000..ada9aef42
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/runAndroid/command.js
@@ -0,0 +1,18 @@
+import { intro, outro } from '@rock-js/tools';
+import { getValidProjectConfig } from '../getValidProjectConfig.js';
+import { runAndroid, runOptions } from './runAndroid.js';
+export function registerRunCommand(api, pluginConfig) {
+ api.registerCommand({
+ name: 'run:android',
+ description: 'Builds your app and starts it on a connected Android emulator or a device.',
+ action: async (args) => {
+ intro('Running Android app');
+ const projectRoot = api.getProjectRoot();
+ const androidConfig = getValidProjectConfig(projectRoot, pluginConfig);
+ await runAndroid(androidConfig, args, projectRoot, await api.getRemoteCacheProvider(), api.getFingerprintOptions(), api.getBundlerStart(), api.getReactNativeVersion(), api.getReactNativePath(), api.getPlatforms());
+ outro('Success ๐.');
+ },
+ options: runOptions,
+ });
+}
+//# sourceMappingURL=command.js.map
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/command.js.map b/packages/platform-android/dist/src/lib/commands/runAndroid/command.js.map
new file mode 100644
index 000000000..c9048380a
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/runAndroid/command.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"command.js","sourceRoot":"","sources":["../../../../../src/lib/commands/runAndroid/command.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAEzD,MAAM,UAAU,kBAAkB,CAChC,GAAc,EACd,YAAuD;IAEvD,GAAG,CAAC,eAAe,CAAC;QAClB,IAAI,EAAE,aAAa;QACnB,WAAW,EACT,4EAA4E;QAC9E,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YACrB,KAAK,CAAC,qBAAqB,CAAC,CAAC;YAC7B,MAAM,WAAW,GAAG,GAAG,CAAC,cAAc,EAAE,CAAC;YACzC,MAAM,aAAa,GAAG,qBAAqB,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;YACvE,MAAM,UAAU,CACd,aAAa,EACb,IAAa,EACb,WAAW,EACX,MAAM,GAAG,CAAC,sBAAsB,EAAE,EAClC,GAAG,CAAC,qBAAqB,EAAE,EAC3B,GAAG,CAAC,eAAe,EAAE,EACrB,GAAG,CAAC,qBAAqB,EAAE,EAC3B,GAAG,CAAC,kBAAkB,EAAE,EACxB,GAAG,CAAC,YAAY,EAAE,CACnB,CAAC;YACF,KAAK,CAAC,aAAa,CAAC,CAAC;QACvB,CAAC;QACD,OAAO,EAAE,UAAU;KACpB,CAAC,CAAC;AACL,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/findOutputFile.d.ts b/packages/platform-android/dist/src/lib/commands/runAndroid/findOutputFile.d.ts
new file mode 100644
index 000000000..8b9885303
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/runAndroid/findOutputFile.d.ts
@@ -0,0 +1,2 @@
+import type { AndroidProject } from './runAndroid.js';
+export declare function findOutputFile(androidProject: AndroidProject, tasks: string[], device?: string): Promise;
diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/findOutputFile.js b/packages/platform-android/dist/src/lib/commands/runAndroid/findOutputFile.js
new file mode 100644
index 000000000..2938c2975
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/runAndroid/findOutputFile.js
@@ -0,0 +1,67 @@
+import { existsSync } from 'node:fs';
+import { logger, spawn } from '@rock-js/tools';
+import { getAdbPath } from './adb.js';
+export async function findOutputFile(androidProject, tasks, device) {
+ const { appName, sourceDir } = androidProject;
+ const selectedTask = tasks.find((t) => t.startsWith('install') ||
+ t.startsWith('assemble') ||
+ t.startsWith('bundle'));
+ if (!selectedTask) {
+ return false;
+ }
+ // handle if selected task includes build flavour as well, eg. installProductionDebug should create ['production','debug'] array
+ const variantFromSelectedTask = selectedTask
+ ?.replace('install', '')
+ ?.replace('assemble', '')
+ ?.replace('bundle', '')
+ .split(/(?=[A-Z])/);
+ // create path to output file, eg. `production/debug`
+ const variantPath = variantFromSelectedTask?.join('/')?.toLowerCase();
+ // create output file name, eg. `production-debug`
+ const variantAppName = variantFromSelectedTask?.join('-')?.toLowerCase();
+ const apkOrBundle = selectedTask?.includes('bundle') ? 'bundle' : 'apk';
+ const buildDirectory = `${sourceDir}/${appName}/build/outputs/${apkOrBundle}/${variantPath}`;
+ const outputFile = await getInstallOutputFileName(appName, variantAppName, buildDirectory, apkOrBundle === 'apk' ? 'apk' : 'aab', device);
+ return outputFile ? `${buildDirectory}/${outputFile}` : undefined;
+}
+async function getInstallOutputFileName(appName, variant, buildDirectory, apkOrAab, device) {
+ const availableCPUs = await getAvailableCPUs(device);
+ // check if there is an apk file like app-armeabi-v7a-debug.apk
+ for (const availableCPU of availableCPUs.concat('universal')) {
+ const outputFile = `${appName}-${availableCPU}-${variant}.${apkOrAab}`;
+ if (existsSync(`${buildDirectory}/${outputFile}`)) {
+ return outputFile;
+ }
+ }
+ // check if there is a default file like app-debug.apk
+ const outputFile = `${appName}-${variant}.${apkOrAab}`;
+ if (existsSync(`${buildDirectory}/${outputFile}`)) {
+ return outputFile;
+ }
+ logger.debug('Could not find the output file:', {
+ buildDirectory,
+ outputFile,
+ appName,
+ variant,
+ apkOrAab,
+ });
+ return undefined;
+}
+/**
+ * Gets available CPUs of devices from ADB
+ */
+async function getAvailableCPUs(device) {
+ const adbPath = getAdbPath();
+ try {
+ const adbArgs = ['shell', 'getprop', 'ro.product.cpu.abilist'];
+ if (device) {
+ adbArgs.unshift('-s', device);
+ }
+ const { output } = await spawn(adbPath, adbArgs, { stdio: 'pipe' });
+ return output.trim().split(',');
+ }
+ catch {
+ return [];
+ }
+}
+//# sourceMappingURL=findOutputFile.js.map
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/findOutputFile.js.map b/packages/platform-android/dist/src/lib/commands/runAndroid/findOutputFile.js.map
new file mode 100644
index 000000000..a66ffcd38
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/runAndroid/findOutputFile.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"findOutputFile.js","sourceRoot":"","sources":["../../../../../src/lib/commands/runAndroid/findOutputFile.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/listAndroidDevices.d.ts b/packages/platform-android/dist/src/lib/commands/runAndroid/listAndroidDevices.d.ts
new file mode 100644
index 000000000..abde41d81
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/runAndroid/listAndroidDevices.d.ts
@@ -0,0 +1,7 @@
+export type DeviceData = {
+ deviceId: string | undefined;
+ readableName: string;
+ connected: boolean;
+ type: 'emulator' | 'phone';
+};
+export declare function listAndroidDevices(): Promise;
diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/listAndroidDevices.js b/packages/platform-android/dist/src/lib/commands/runAndroid/listAndroidDevices.js
new file mode 100644
index 000000000..316286aaf
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/runAndroid/listAndroidDevices.js
@@ -0,0 +1,69 @@
+import os from 'node:os';
+import { spawn } from '@rock-js/tools';
+import { getAdbPath, getDevices } from './adb.js';
+import { getEmulators } from './tryLaunchEmulator.js';
+/**
+ *
+ * @param deviceId string
+ * @returns name of Android emulator
+ */
+async function getEmulatorName(deviceId) {
+ const adbPath = getAdbPath();
+ const { output } = await spawn(adbPath, ['-s', deviceId, 'emu', 'avd', 'name'], { stdio: 'pipe' });
+ // 1st line should get us emu name
+ return output
+ .split(os.EOL)[0]
+ .replace(/(\r\n|\n|\r)/gm, '')
+ .trim();
+}
+/**
+ *
+ * @param deviceId string
+ * @returns Android device name in readable format
+ */
+async function getPhoneName(deviceId) {
+ const adbPath = getAdbPath();
+ const { output } = await spawn(adbPath, ['-s', deviceId, 'shell', 'getprop', 'ro.product.model'], { stdio: 'pipe' });
+ return output.replace(/\[ro\.product\.model\]:\s*\[(.*)\]/, '$1').trim();
+}
+export async function listAndroidDevices() {
+ const devices = await getDevices();
+ let allDevices = [];
+ for (const deviceId of devices) {
+ if (deviceId.includes('emulator')) {
+ const emulatorData = {
+ deviceId,
+ readableName: await getEmulatorName(deviceId),
+ connected: true,
+ type: 'emulator',
+ };
+ allDevices = [...allDevices, emulatorData];
+ }
+ else {
+ const phoneData = {
+ deviceId,
+ readableName: await getPhoneName(deviceId),
+ type: 'phone',
+ connected: true,
+ };
+ allDevices = [...allDevices, phoneData];
+ }
+ }
+ const emulators = await getEmulators();
+ // Find not booted ones:
+ emulators.forEach((emulatorName) => {
+ // skip those already booted
+ if (allDevices.some((device) => device.readableName === emulatorName)) {
+ return;
+ }
+ const emulatorData = {
+ deviceId: undefined,
+ readableName: emulatorName,
+ type: 'emulator',
+ connected: false,
+ };
+ allDevices = [...allDevices, emulatorData];
+ });
+ return allDevices;
+}
+//# sourceMappingURL=listAndroidDevices.js.map
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/listAndroidDevices.js.map b/packages/platform-android/dist/src/lib/commands/runAndroid/listAndroidDevices.js.map
new file mode 100644
index 000000000..701abf075
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/runAndroid/listAndroidDevices.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"listAndroidDevices.js","sourceRoot":"","sources":["../../../../../src/lib/commands/runAndroid/listAndroidDevices.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAStD;;;;GAIG;AACH,KAAK,UAAU,eAAe,CAAC,QAAgB;IAC7C,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,KAAK,CAC5B,OAAO,EACP,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,EACtC,EAAE,KAAK,EAAE,MAAM,EAAE,CAClB,CAAC;IAEF,kCAAkC;IAClC,OAAO,MAAM;SACV,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;SAChB,OAAO,CAAC,gBAAgB,EAAE,EAAE,CAAC;SAC7B,IAAI,EAAE,CAAC;AACZ,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,YAAY,CAAC,QAAgB;IAC1C,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,KAAK,CAC5B,OAAO,EACP,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,kBAAkB,CAAC,EACxD,EAAE,KAAK,EAAE,MAAM,EAAE,CAClB,CAAC;IACF,OAAO,MAAM,CAAC,OAAO,CAAC,oCAAoC,EAAE,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;AAC3E,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB;IACtC,MAAM,OAAO,GAAG,MAAM,UAAU,EAAE,CAAC;IAEnC,IAAI,UAAU,GAAsB,EAAE,CAAC;IAEvC,KAAK,MAAM,QAAQ,IAAI,OAAO,EAAE,CAAC;QAC/B,IAAI,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;YAClC,MAAM,YAAY,GAAe;gBAC/B,QAAQ;gBACR,YAAY,EAAE,MAAM,eAAe,CAAC,QAAQ,CAAC;gBAC7C,SAAS,EAAE,IAAI;gBACf,IAAI,EAAE,UAAU;aACjB,CAAC;YACF,UAAU,GAAG,CAAC,GAAG,UAAU,EAAE,YAAY,CAAC,CAAC;QAC7C,CAAC;aAAM,CAAC;YACN,MAAM,SAAS,GAAe;gBAC5B,QAAQ;gBACR,YAAY,EAAE,MAAM,YAAY,CAAC,QAAQ,CAAC;gBAC1C,IAAI,EAAE,OAAO;gBACb,SAAS,EAAE,IAAI;aAChB,CAAC;YACF,UAAU,GAAG,CAAC,GAAG,UAAU,EAAE,SAAS,CAAC,CAAC;QAC1C,CAAC;IACH,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,YAAY,EAAE,CAAC;IAEvC,wBAAwB;IACxB,SAAS,CAAC,OAAO,CAAC,CAAC,YAAY,EAAE,EAAE;QACjC,4BAA4B;QAC5B,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,YAAY,KAAK,YAAY,CAAC,EAAE,CAAC;YACtE,OAAO;QACT,CAAC;QACD,MAAM,YAAY,GAAe;YAC/B,QAAQ,EAAE,SAAS;YACnB,YAAY,EAAE,YAAY;YAC1B,IAAI,EAAE,UAAU;YAChB,SAAS,EAAE,KAAK;SACjB,CAAC;QACF,UAAU,GAAG,CAAC,GAAG,UAAU,EAAE,YAAY,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,OAAO,UAAU,CAAC;AACpB,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/listAndroidUsers.d.ts b/packages/platform-android/dist/src/lib/commands/runAndroid/listAndroidUsers.d.ts
new file mode 100644
index 000000000..0e281eb4f
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/runAndroid/listAndroidUsers.d.ts
@@ -0,0 +1,7 @@
+type User = {
+ id: string;
+ name: string;
+};
+export declare function checkUsers(device: string): Promise;
+export declare function promptForUser(deviceId: string): Promise;
+export {};
diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/listAndroidUsers.js b/packages/platform-android/dist/src/lib/commands/runAndroid/listAndroidUsers.js
new file mode 100644
index 000000000..996021669
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/runAndroid/listAndroidUsers.js
@@ -0,0 +1,42 @@
+import { logger, promptSelect, spawn } from '@rock-js/tools';
+import { getAdbPath } from './adb.js';
+const regex = new RegExp(/^\s*UserInfo\{(?\d+):(?.*):(?[0-9a-f]*)}/);
+export async function checkUsers(device) {
+ const adbPath = getAdbPath();
+ const adbArgs = ['-s', device, 'shell', 'pm', 'list', 'users'];
+ try {
+ const { stdout, stderr } = await spawn(adbPath, adbArgs, { stdio: 'pipe' });
+ if (stderr) {
+ logger.debug(`Failed to check users on the device. ${stderr}`, 1);
+ return [];
+ }
+ const lines = stdout.split('\n');
+ const users = [];
+ for (const line of lines) {
+ const res = regex.exec(line);
+ if (res?.groups) {
+ users.push({ id: res.groups['userId'], name: res.groups['userName'] });
+ }
+ }
+ return users;
+ }
+ catch (error) {
+ logger.debug(`Unexpected error while checking users on the device. Continuing without user selection. Error details: ${error.message}.`, 1);
+ return [];
+ }
+}
+export async function promptForUser(deviceId) {
+ const users = await checkUsers(deviceId);
+ if (users.length > 1) {
+ const selectedUser = await promptSelect({
+ message: 'Which user profile would you like to launch your app into?',
+ options: users.map((user) => ({
+ label: user.name,
+ value: user,
+ })),
+ });
+ return selectedUser;
+ }
+ return null;
+}
+//# sourceMappingURL=listAndroidUsers.js.map
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/listAndroidUsers.js.map b/packages/platform-android/dist/src/lib/commands/runAndroid/listAndroidUsers.js.map
new file mode 100644
index 000000000..c3a6e0ef7
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/runAndroid/listAndroidUsers.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"listAndroidUsers.js","sourceRoot":"","sources":["../../../../../src/lib/commands/runAndroid/listAndroidUsers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAOtC,MAAM,KAAK,GAAG,IAAI,MAAM,CACtB,uEAAuE,CACxE,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,MAAc;IAC7C,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,OAAO,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IAE/D,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QAE5E,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,CAAC,KAAK,CAAC,wCAAwC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC;YAClE,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACjC,MAAM,KAAK,GAAG,EAAE,CAAC;QAEjB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC7B,IAAI,GAAG,EAAE,MAAM,EAAE,CAAC;gBAChB,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;YACzE,CAAC;QACH,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CACV,0GACG,KAA6B,CAAC,OACjC,GAAG,EACH,CAAC,CACF,CAAC;QACF,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,QAAgB;IAClD,MAAM,KAAK,GAAG,MAAM,UAAU,CAAC,QAAQ,CAAC,CAAC;IACzC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,MAAM,YAAY,GAAG,MAAM,YAAY,CAAC;YACtC,OAAO,EAAE,4DAA4D;YACrE,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;gBAC5B,KAAK,EAAE,IAAI,CAAC,IAAI;gBAChB,KAAK,EAAE,IAAI;aACZ,CAAC,CAAC;SACJ,CAAC,CAAC;QAEH,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/runAndroid.d.ts b/packages/platform-android/dist/src/lib/commands/runAndroid/runAndroid.d.ts
new file mode 100644
index 000000000..81eecd913
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/runAndroid/runAndroid.d.ts
@@ -0,0 +1,36 @@
+import type { AndroidProjectConfig, Config } from '@react-native-community/cli-types';
+import type { StartDevServerArgs } from '@rock-js/config';
+import type { FingerprintSources, RemoteBuildCache } from '@rock-js/tools';
+import type { BuildFlags } from '../buildAndroid/buildAndroid.js';
+export interface Flags extends BuildFlags {
+ appId: string;
+ appIdSuffix: string;
+ mainActivity?: string;
+ port: string;
+ device?: string;
+ binaryPath?: string;
+ user?: string;
+ local?: boolean;
+ devServer?: boolean;
+ clientLogs?: boolean;
+}
+export type AndroidProject = NonNullable;
+/**
+ * Starts the app on a connected Android emulator or device.
+ */
+export declare function runAndroid(androidProject: AndroidProjectConfig, args: Flags, projectRoot: string, remoteCacheProvider: null | (() => RemoteBuildCache) | undefined, fingerprintOptions: FingerprintSources, startDevServer: (options: StartDevServerArgs) => void, reactNativeVersion: string, reactNativePath: string, platforms: {
+ [platform: string]: object;
+}): Promise;
+export declare const runOptions: ({
+ name: string;
+ description: string;
+ parse?: undefined;
+} | {
+ name: string;
+ description: string;
+ parse: (val: string) => string[];
+} | {
+ name: string;
+ description: string;
+ default: string;
+})[];
diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/runAndroid.js b/packages/platform-android/dist/src/lib/commands/runAndroid/runAndroid.js
new file mode 100644
index 000000000..410a54c0b
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/runAndroid/runAndroid.js
@@ -0,0 +1,203 @@
+import fs from 'node:fs';
+import path from 'node:path';
+import { color, formatArtifactName, isInteractive, logger, promptSelect, RockError, spinner, } from '@rock-js/tools';
+import { getBinaryPath } from '@rock-js/tools';
+import { options } from '../buildAndroid/buildAndroid.js';
+import { runGradle } from '../runGradle.js';
+import { toPascalCase } from '../toPascalCase.js';
+import { getDevices } from './adb.js';
+import { listAndroidDevices } from './listAndroidDevices.js';
+import { tryInstallAppOnDevice } from './tryInstallAppOnDevice.js';
+import { tryLaunchAppOnDevice } from './tryLaunchAppOnDevice.js';
+import { tryLaunchEmulator } from './tryLaunchEmulator.js';
+/**
+ * Starts the app on a connected Android emulator or device.
+ */
+export async function runAndroid(androidProject, args, projectRoot, remoteCacheProvider, fingerprintOptions, startDevServer, reactNativeVersion, reactNativePath, platforms) {
+ const startDevServerHelper = () => {
+ if (args.devServer) {
+ logger.info('Starting dev server...');
+ startDevServer({
+ root: projectRoot,
+ reactNativePath,
+ reactNativeVersion,
+ platforms,
+ args: {
+ interactive: isInteractive(),
+ clientLogs: args.clientLogs ?? true,
+ },
+ });
+ }
+ };
+ normalizeArgs(args, projectRoot);
+ const devices = await listAndroidDevices();
+ const device = await selectDevice(devices, args);
+ const mainTaskType = device ? 'assemble' : 'install';
+ const tasks = args.tasks ?? [`${mainTaskType}${toPascalCase(args.variant)}`];
+ const artifactName = await formatArtifactName({
+ platform: 'android',
+ traits: [args.variant],
+ root: projectRoot,
+ fingerprintOptions,
+ });
+ const binaryPath = await getBinaryPath({
+ platformName: 'android',
+ artifactName,
+ binaryPathFlag: args.binaryPath,
+ localFlag: args.local,
+ remoteCacheProvider,
+ fingerprintOptions,
+ sourceDir: androidProject.sourceDir,
+ });
+ if (device) {
+ if (!(await getDevices()).find((d) => d === device.deviceId)) {
+ // deviceId is undefined until it's launched, hence overwriting it here
+ device.deviceId = await tryLaunchEmulator(device.readableName);
+ }
+ if (device.deviceId) {
+ if (!binaryPath) {
+ await runGradle({ tasks, androidProject, args, artifactName });
+ }
+ await runOnDevice({ device, androidProject, args, tasks, binaryPath });
+ }
+ }
+ else {
+ if ((await getDevices()).length === 0) {
+ if (isInteractive()) {
+ await selectAndLaunchDevice();
+ }
+ else {
+ logger.debug('No booted devices or emulators found. Launching first available emulator.');
+ await tryLaunchEmulator();
+ }
+ }
+ if (!binaryPath) {
+ await runGradle({ tasks, androidProject, args, artifactName });
+ }
+ for (const device of await listAndroidDevices()) {
+ if (device.connected) {
+ await runOnDevice({ device, androidProject, args, tasks, binaryPath });
+ }
+ }
+ }
+ startDevServerHelper();
+}
+async function selectAndLaunchDevice() {
+ const allDevices = await listAndroidDevices();
+ const device = await promptForDeviceSelection(allDevices);
+ if (!device.connected) {
+ await tryLaunchEmulator(device.readableName);
+ // list devices once again when emulator is booted
+ const allDevices = await listAndroidDevices();
+ const newDevice = allDevices.find((d) => d.readableName === device.readableName) ?? device;
+ return newDevice;
+ }
+ return device;
+}
+async function selectDevice(devices, args) {
+ const device = args.device ? matchingDevice(devices, args.device) : undefined;
+ if (!device && args.device) {
+ logger.warn(`No devices or emulators found matching "${args.device}". Using available one instead.`);
+ }
+ return device;
+}
+function matchingDevice(devices, deviceArg) {
+ const deviceByName = devices.find((device) => device.readableName === deviceArg);
+ const deviceById = devices.find((d) => d.deviceId === deviceArg);
+ return deviceByName || deviceById;
+}
+function normalizeArgs(args, projectRoot) {
+ if (args.tasks && args.variant) {
+ logger.warn('Both "--tasks" and "--variant" parameters were passed. Using "--tasks" for building the app.');
+ }
+ if (!args.variant) {
+ args.variant = 'debug';
+ }
+ // turn on activeArchOnly for debug to speed up local builds
+ if (args.variant !== 'release' &&
+ !args.variant.endsWith('Release') &&
+ args.activeArchOnly === undefined &&
+ isInteractive()) {
+ args.activeArchOnly = true;
+ }
+ if (args.binaryPath) {
+ if (args.tasks) {
+ throw new RockError('Both "--binary-path" and "--tasks" flags were specified, which are incompatible. Please specify only one.');
+ }
+ args.binaryPath = path.isAbsolute(args.binaryPath)
+ ? args.binaryPath
+ : path.join(projectRoot, args.binaryPath);
+ if (args.binaryPath && !fs.existsSync(args.binaryPath)) {
+ throw new RockError(`"--binary-path" was specified, but the file was not found at "${args.binaryPath}".`);
+ }
+ }
+}
+async function promptForDeviceSelection(allDevices) {
+ if (!allDevices.length) {
+ throw new RockError('No devices and/or emulators connected. Please create emulator with Android Studio or connect Android device.');
+ }
+ const selected = await promptSelect({
+ message: 'Select the device / emulator you want to use',
+ options: allDevices.map((d) => ({
+ label: `${d.readableName}${d.type === 'phone' ? ' - (physical device)' : ''}${d.connected ? ' (connected)' : ''}`,
+ value: d,
+ })),
+ });
+ return selected;
+}
+async function runOnDevice({ device, androidProject, args, tasks, binaryPath, }) {
+ const loader = spinner();
+ loader.start('Installing the app');
+ await tryInstallAppOnDevice(device, androidProject, args, tasks, binaryPath);
+ loader.message('Launching the app');
+ const { applicationIdWithSuffix } = await tryLaunchAppOnDevice(device, androidProject, args);
+ if (applicationIdWithSuffix) {
+ loader.stop(`Installed and launched the app on ${color.bold(device.readableName)}`);
+ }
+ else {
+ loader.stop(`Failed: installing and launching the app on ${color.bold(device.readableName)}`);
+ }
+}
+export const runOptions = [
+ ...options,
+ {
+ name: '--port ',
+ description: 'Part for packager.',
+ default: process.env['RCT_METRO_PORT'] || '8081',
+ },
+ {
+ name: '--app-id ',
+ description: 'Specify an applicationId to launch after build. If not specified, `package` from AndroidManifest.xml will be used.',
+ default: '',
+ },
+ {
+ name: '--app-id-suffix ',
+ description: 'Specify an applicationIdSuffix to launch after build.',
+ default: '',
+ },
+ {
+ name: '--main-activity ',
+ description: 'Name of the activity to start',
+ },
+ {
+ name: '--device ',
+ description: 'Explicitly set the device or emulator to use by name or ID (if launched).',
+ },
+ {
+ name: '--binary-path ',
+ description: 'Path relative to project root where pre-built .apk binary lives.',
+ },
+ {
+ name: '--user ',
+ description: 'Id of the User Profile you want to install the app on.',
+ },
+ {
+ name: '--client-logs',
+ description: 'Enable client logs in dev server.',
+ },
+ {
+ name: '--dev-server',
+ description: 'Automatically start a dev server (bundler) after building the app.',
+ },
+];
+//# sourceMappingURL=runAndroid.js.map
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/runAndroid.js.map b/packages/platform-android/dist/src/lib/commands/runAndroid/runAndroid.js.map
new file mode 100644
index 000000000..635a094dc
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/runAndroid/runAndroid.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"runAndroid.js","sourceRoot":"","sources":["../../../../../src/lib/commands/runAndroid/runAndroid.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/tryInstallAppOnDevice.d.ts b/packages/platform-android/dist/src/lib/commands/runAndroid/tryInstallAppOnDevice.d.ts
new file mode 100644
index 000000000..d0d332b5c
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/runAndroid/tryInstallAppOnDevice.d.ts
@@ -0,0 +1,3 @@
+import type { DeviceData } from './listAndroidDevices.js';
+import type { AndroidProject, Flags } from './runAndroid.js';
+export declare function tryInstallAppOnDevice(device: DeviceData, androidProject: AndroidProject, args: Flags, tasks: string[], binaryPath: string | undefined): Promise;
diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/tryInstallAppOnDevice.js b/packages/platform-android/dist/src/lib/commands/runAndroid/tryInstallAppOnDevice.js
new file mode 100644
index 000000000..4fc85dc1d
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/runAndroid/tryInstallAppOnDevice.js
@@ -0,0 +1,63 @@
+import { color, logger, RockError, spawn, } from '@rock-js/tools';
+import { getAdbPath } from './adb.js';
+import { findOutputFile } from './findOutputFile.js';
+import { promptForUser } from './listAndroidUsers.js';
+export async function tryInstallAppOnDevice(device, androidProject, args, tasks, binaryPath) {
+ let deviceId;
+ if (!device.deviceId) {
+ logger.debug(`No "deviceId" for ${device}, skipping launching the app`);
+ return;
+ }
+ else {
+ deviceId = device.deviceId;
+ }
+ logger.debug(`Connected to device ${color.bold(device.readableName)}`);
+ let pathToApk;
+ if (!binaryPath) {
+ const outputFilePath = await findOutputFile(androidProject, tasks, deviceId);
+ if (!outputFilePath) {
+ logger.warn("Skipping installation because there's no build output file.");
+ return;
+ }
+ pathToApk = outputFilePath;
+ }
+ else {
+ pathToApk = binaryPath;
+ }
+ const adbArgs = ['-s', deviceId, 'install', '-r', '-d'];
+ const user = args.user ?? (await promptForUser(deviceId))?.id;
+ if (user !== undefined) {
+ adbArgs.push('--user', `${user}`);
+ }
+ adbArgs.push(pathToApk);
+ const adbPath = getAdbPath();
+ try {
+ await spawn(adbPath, adbArgs, { stdio: 'pipe' });
+ }
+ catch (error) {
+ logger.debug(`Failed: Installing the app`, error);
+ const errorMessage = error.stderr || error.stdout;
+ const isInsufficientStorage = errorMessage.includes('INSTALL_FAILED_INSUFFICIENT_STORAGE');
+ const isUpdateIncompatible = errorMessage.includes('INSTALL_FAILED_UPDATE_INCOMPATIBLE');
+ if (isInsufficientStorage || isUpdateIncompatible) {
+ try {
+ const message = isInsufficientStorage
+ ? 'Recovery: Trying to re-install the app due to insufficient storage'
+ : 'Recovery: Trying to re-install the app due to binary incompatibility';
+ logger.debug(message);
+ const appId = args.appId || androidProject.applicationId;
+ await spawn(adbPath, ['-s', deviceId, 'uninstall', appId]);
+ await spawn(adbPath, adbArgs);
+ logger.debug(`Recovery: Re-installed the app`);
+ return;
+ }
+ catch (error) {
+ const errorMessage = error.stderr ||
+ error.stdout;
+ throw new RockError(`The "adb" command failed with: ${errorMessage}.`);
+ }
+ }
+ throw new RockError(`The "adb" command failed with: ${errorMessage}.`);
+ }
+}
+//# sourceMappingURL=tryInstallAppOnDevice.js.map
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/tryInstallAppOnDevice.js.map b/packages/platform-android/dist/src/lib/commands/runAndroid/tryInstallAppOnDevice.js.map
new file mode 100644
index 000000000..f81b0dcb9
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/runAndroid/tryInstallAppOnDevice.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"tryInstallAppOnDevice.js","sourceRoot":"","sources":["../../../../../src/lib/commands/runAndroid/tryInstallAppOnDevice.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/tryLaunchAppOnDevice.d.ts b/packages/platform-android/dist/src/lib/commands/runAndroid/tryLaunchAppOnDevice.d.ts
new file mode 100644
index 000000000..68f7e5371
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/runAndroid/tryLaunchAppOnDevice.d.ts
@@ -0,0 +1,7 @@
+import type { DeviceData } from './listAndroidDevices.js';
+import type { AndroidProject, Flags } from './runAndroid.js';
+export declare function tryLaunchAppOnDevice(device: DeviceData, androidProject: AndroidProject, args: Flags): Promise<{
+ applicationIdWithSuffix?: undefined;
+} | {
+ applicationIdWithSuffix: string;
+}>;
diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/tryLaunchAppOnDevice.js b/packages/platform-android/dist/src/lib/commands/runAndroid/tryLaunchAppOnDevice.js
new file mode 100644
index 000000000..158178a26
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/runAndroid/tryLaunchAppOnDevice.js
@@ -0,0 +1,51 @@
+import { logger, RockError, spawn } from '@rock-js/tools';
+import { getAdbPath } from './adb.js';
+import { tryRunAdbReverse } from './tryRunAdbReverse.js';
+export async function tryLaunchAppOnDevice(device, androidProject, args) {
+ let deviceId;
+ if (!device.deviceId) {
+ logger.debug(`No "deviceId" for ${device}, skipping launching the app`);
+ return {};
+ }
+ else {
+ deviceId = device.deviceId;
+ }
+ await tryRunAdbReverse(args.port, deviceId);
+ const { appId, appIdSuffix } = args;
+ const { packageName, mainActivity, applicationId } = androidProject;
+ const applicationIdWithSuffix = [appId || applicationId, appIdSuffix]
+ .filter(Boolean)
+ .join('.');
+ const activity = args.mainActivity ?? mainActivity;
+ const activityToLaunch = activity.startsWith(packageName) ||
+ (!activity.startsWith('.') && activity.includes('.'))
+ ? activity
+ : activity.startsWith('.')
+ ? [packageName, activity].join('')
+ : [packageName, activity].filter(Boolean).join('.');
+ // Here we're using the same flags as Android Studio to launch the app
+ const adbArgs = [
+ 'shell',
+ 'am',
+ 'start',
+ '-n',
+ `${applicationIdWithSuffix}/${activityToLaunch}`,
+ '-a',
+ 'android.intent.action.MAIN',
+ '-c',
+ 'android.intent.category.LAUNCHER',
+ ];
+ adbArgs.unshift('-s', deviceId);
+ const adbPath = getAdbPath();
+ logger.debug(`Running ${adbPath} ${adbArgs.join(' ')}.`);
+ try {
+ await spawn(adbPath, adbArgs);
+ }
+ catch (error) {
+ throw new RockError(`Failed to launch the app on ${device.readableName}`, {
+ cause: error.stderr,
+ });
+ }
+ return { applicationIdWithSuffix };
+}
+//# sourceMappingURL=tryLaunchAppOnDevice.js.map
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/tryLaunchAppOnDevice.js.map b/packages/platform-android/dist/src/lib/commands/runAndroid/tryLaunchAppOnDevice.js.map
new file mode 100644
index 000000000..8d4d2d13e
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/runAndroid/tryLaunchAppOnDevice.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"tryLaunchAppOnDevice.js","sourceRoot":"","sources":["../../../../../src/lib/commands/runAndroid/tryLaunchAppOnDevice.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAwB,MAAM,gBAAgB,CAAC;AAChF,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAGtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzD,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,MAAkB,EAClB,cAA8B,EAC9B,IAAW;IAEX,IAAI,QAAQ,CAAC;IACb,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;QACrB,MAAM,CAAC,KAAK,CACV,qBAAqB,MAAM,8BAA8B,CAC1D,CAAC;QACF,OAAO,EAAE,CAAC;IACZ,CAAC;SAAM,CAAC;QACN,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;IAC7B,CAAC;IACD,MAAM,gBAAgB,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC5C,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC;IACpC,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,aAAa,EAAE,GAAG,cAAc,CAAC;IAEpE,MAAM,uBAAuB,GAAG,CAAC,KAAK,IAAI,aAAa,EAAE,WAAW,CAAC;SAClE,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,GAAG,CAAC,CAAC;IAEb,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,IAAI,YAAY,CAAC;IAEnD,MAAM,gBAAgB,GACpB,QAAQ,CAAC,UAAU,CAAC,WAAW,CAAC;QAChC,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QACnD,CAAC,CAAC,QAAQ;QACV,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC;YACxB,CAAC,CAAC,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;YAClC,CAAC,CAAC,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAE1D,sEAAsE;IACtE,MAAM,OAAO,GAAG;QACd,OAAO;QACP,IAAI;QACJ,OAAO;QACP,IAAI;QACJ,GAAG,uBAAuB,IAAI,gBAAgB,EAAE;QAChD,IAAI;QACJ,4BAA4B;QAC5B,IAAI;QACJ,kCAAkC;KACnC,CAAC;IAEF,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAEhC,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,CAAC,KAAK,CAAC,WAAW,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACzD,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAChC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CAAC,+BAA+B,MAAM,CAAC,YAAY,EAAE,EAAE;YACxE,KAAK,EAAG,KAAyB,CAAC,MAAM;SACzC,CAAC,CAAC;IACL,CAAC;IACD,OAAO,EAAE,uBAAuB,EAAE,CAAC;AACrC,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/tryLaunchEmulator.d.ts b/packages/platform-android/dist/src/lib/commands/runAndroid/tryLaunchEmulator.d.ts
new file mode 100644
index 000000000..210dea110
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/runAndroid/tryLaunchEmulator.d.ts
@@ -0,0 +1,2 @@
+export declare const getEmulators: () => Promise;
+export declare function tryLaunchEmulator(name?: string): Promise;
diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/tryLaunchEmulator.js b/packages/platform-android/dist/src/lib/commands/runAndroid/tryLaunchEmulator.js
new file mode 100644
index 000000000..313c2af54
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/runAndroid/tryLaunchEmulator.js
@@ -0,0 +1,120 @@
+import os from 'node:os';
+import { color, RockError, spawn, spinner } from '@rock-js/tools';
+import { getAdbPath, getDevices } from './adb.js';
+const emulatorCommand = process.env['ANDROID_HOME']
+ ? `${process.env['ANDROID_HOME']}/emulator/emulator`
+ : 'emulator';
+export const getEmulators = async () => {
+ try {
+ const { output } = await spawn(emulatorCommand, ['-list-avds'], {
+ stdio: 'pipe',
+ });
+ // The `name` is AVD ID which is expected to not contain whitespace.
+ // The `emulator` command, however, can occasionally return verbose
+ // information about crashes or similar. Hence filtering out anything
+ // that has basic whitespace.
+ return output
+ .split(os.EOL)
+ .filter((name) => name !== '' && !name.includes(' '));
+ }
+ catch {
+ return [];
+ }
+};
+const launchEmulator = async ({ emulatorName, port, onConnected, }) => {
+ const manualCommand = `${emulatorCommand} @${emulatorName}`;
+ const cp = spawn(emulatorCommand, [`@${emulatorName}`, '-port', `${port}`], {
+ detached: true,
+ stdio: 'ignore',
+ });
+ (await cp.nodeChildProcess).unref();
+ const timeout = 120;
+ return new Promise((resolve, reject) => {
+ const bootCheckInterval = setInterval(async () => {
+ const devices = await getDevices();
+ const connected = port
+ ? devices.find((d) => d.includes(`${port}`))
+ : false;
+ if (connected) {
+ onConnected();
+ if (await isEmulatorBooted(connected)) {
+ cleanup();
+ resolve(connected);
+ }
+ }
+ }, 1000);
+ // Reject command after timeout
+ const rejectTimeout = setTimeout(() => {
+ stopWaitingAndReject(`It took too long to start and connect with Android emulator: ${emulatorName}. You can try starting the emulator manually from the terminal with: ${manualCommand}`);
+ }, timeout * 1000);
+ const cleanup = () => {
+ clearTimeout(rejectTimeout);
+ clearInterval(bootCheckInterval);
+ };
+ const stopWaitingAndReject = (message) => {
+ cleanup();
+ reject(new Error(message));
+ };
+ cp.nodeChildProcess.catch((error) => {
+ stopWaitingAndReject(error);
+ });
+ });
+};
+const defaultPort = 5552;
+async function getAvailableDevicePort(port = defaultPort) {
+ /**
+ * The default value is 5554 for the first virtual device instance running on your machine. A virtual device normally occupies a pair of adjacent ports: a console port and an adb port. The console of the first virtual device running on a particular machine uses console port 5554 and adb port 5555. Subsequent instances use port numbers increasing by two. For example, 5556/5557, 5558/5559, and so on. The range is 5554 to 5682, allowing for 64 concurrent virtual devices.
+ */
+ const devices = await getDevices();
+ if (port > 5682) {
+ throw new RockError('Failed to launch emulator');
+ }
+ if (devices.some((d) => d.includes(port.toString()))) {
+ return await getAvailableDevicePort(port + 2);
+ }
+ return port;
+}
+export async function tryLaunchEmulator(name) {
+ const port = await getAvailableDevicePort();
+ const loader = spinner();
+ loader.start(`Looking for available emulators"`);
+ const emulators = await getEmulators();
+ const emulatorName = name ?? emulators[0];
+ const displayEmulatorName = color.bold(emulatorName);
+ let deviceId;
+ if (emulators.length > 0) {
+ try {
+ loader.message(`Launching emulator ${displayEmulatorName}`);
+ deviceId = await launchEmulator({
+ emulatorName,
+ port,
+ onConnected: () => {
+ loader.message(`Emulator ${color.bold(emulatorName)} is connected. Waiting for boot`);
+ },
+ });
+ loader.stop(`Launched ${displayEmulatorName} emulator.`);
+ }
+ catch (error) {
+ loader.stop(`Failed to launch ${displayEmulatorName} emulator. ${error.message}`, 1);
+ }
+ }
+ else {
+ loader.stop('No emulators found as an output of `emulator -list-avds`. Please launch an emulator manually or connect a device', 1);
+ }
+ return deviceId;
+}
+/**
+ * Check if emulator is booted
+ */
+async function isEmulatorBooted(device) {
+ const adbPath = getAdbPath();
+ const adbArgs = ['-s', device, 'shell', 'getprop', 'sys.boot_completed'];
+ try {
+ const { output } = await spawn(adbPath, adbArgs, { stdio: 'pipe' });
+ return output.trim() === '1';
+ }
+ catch {
+ return false;
+ }
+}
+//# sourceMappingURL=tryLaunchEmulator.js.map
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/tryLaunchEmulator.js.map b/packages/platform-android/dist/src/lib/commands/runAndroid/tryLaunchEmulator.js.map
new file mode 100644
index 000000000..d3bd94f07
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/runAndroid/tryLaunchEmulator.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"tryLaunchEmulator.js","sourceRoot":"","sources":["../../../../../src/lib/commands/runAndroid/tryLaunchEmulator.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/tryRunAdbReverse.d.ts b/packages/platform-android/dist/src/lib/commands/runAndroid/tryRunAdbReverse.d.ts
new file mode 100644
index 000000000..398200cfc
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/runAndroid/tryRunAdbReverse.d.ts
@@ -0,0 +1 @@
+export declare function tryRunAdbReverse(packagerPort: number | string, device: string): Promise;
diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/tryRunAdbReverse.js b/packages/platform-android/dist/src/lib/commands/runAndroid/tryRunAdbReverse.js
new file mode 100644
index 000000000..361c8812f
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/runAndroid/tryRunAdbReverse.js
@@ -0,0 +1,21 @@
+import { logger, RockError, spawn } from '@rock-js/tools';
+import { getAdbPath } from './adb.js';
+// Runs ADB reverse tcp:8081 tcp:8081 to allow loading the jsbundle from the packager
+export async function tryRunAdbReverse(packagerPort, device) {
+ try {
+ const adbPath = getAdbPath();
+ const adbArgs = [
+ '-s',
+ device,
+ 'reverse',
+ `tcp:${packagerPort}`,
+ `tcp:${packagerPort}`,
+ ];
+ logger.debug(`Connecting "${device}" to the development server`);
+ await spawn(adbPath, adbArgs);
+ }
+ catch (error) {
+ throw new RockError(`Failed to connect "${device}" to development server using "adb reverse"`, { cause: error.stderr });
+ }
+}
+//# sourceMappingURL=tryRunAdbReverse.js.map
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/lib/commands/runAndroid/tryRunAdbReverse.js.map b/packages/platform-android/dist/src/lib/commands/runAndroid/tryRunAdbReverse.js.map
new file mode 100644
index 000000000..f9b0a29e9
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/runAndroid/tryRunAdbReverse.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"tryRunAdbReverse.js","sourceRoot":"","sources":["../../../../../src/lib/commands/runAndroid/tryRunAdbReverse.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEtC,qFAAqF;AACrF,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,YAA6B,EAC7B,MAAc;IAEd,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAG;YACd,IAAI;YACJ,MAAM;YACN,SAAS;YACT,OAAO,YAAY,EAAE;YACrB,OAAO,YAAY,EAAE;SACtB,CAAC;QAEF,MAAM,CAAC,KAAK,CAAC,eAAe,MAAM,6BAA6B,CAAC,CAAC;QACjE,MAAM,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAChC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CACjB,sBAAsB,MAAM,6CAA6C,EACzE,EAAE,KAAK,EAAG,KAAyB,CAAC,MAAM,EAAE,CAC7C,CAAC;IACJ,CAAC;AACH,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/lib/commands/runGradle.d.ts b/packages/platform-android/dist/src/lib/commands/runGradle.d.ts
new file mode 100644
index 000000000..6a7255880
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/runGradle.d.ts
@@ -0,0 +1,18 @@
+import type { AarProject } from './aar/packageAar.js';
+import type { BuildFlags } from './buildAndroid/buildAndroid.js';
+import type { AndroidProject, Flags } from './runAndroid/runAndroid.js';
+type RunGradleAarArgs = {
+ tasks: string[];
+ aarProject: AarProject;
+ variant?: string;
+};
+export type RunGradleArgs = {
+ tasks: string[];
+ androidProject: AndroidProject;
+ args: BuildFlags | Flags;
+ artifactName: string;
+};
+export declare function runGradle({ tasks, androidProject, args, artifactName, }: RunGradleArgs): Promise;
+export declare function runGradleAar({ tasks, aarProject, variant, }: RunGradleAarArgs): Promise;
+export declare function getGradleWrapper(): "gradlew.bat" | "./gradlew";
+export {};
diff --git a/packages/platform-android/dist/src/lib/commands/runGradle.js b/packages/platform-android/dist/src/lib/commands/runGradle.js
new file mode 100644
index 000000000..0ac455c66
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/runGradle.js
@@ -0,0 +1,124 @@
+import { color, logger, RockError, saveLocalBuildCache, spawn, spinner, } from '@rock-js/tools';
+import { getAdbPath, getDevices } from './runAndroid/adb.js';
+import { findOutputFile } from './runAndroid/findOutputFile.js';
+const getCleanedErrorMessage = (error) => {
+ return error.stderr
+ .split('\n')
+ .filter((line) => !gradleLinesToRemove.some((l) => line.includes(l)))
+ .join('\n')
+ .trim();
+};
+export async function runGradle({ tasks, androidProject, args, artifactName, }) {
+ const humanReadableTasks = tasks.join(', ');
+ const { appId, appIdSuffix } = args;
+ const { applicationId } = androidProject;
+ const applicationIdWithSuffix = [appId || applicationId, appIdSuffix]
+ .filter(Boolean)
+ .join('.');
+ logger.log(`Build Settings:
+App ID ${color.bold(color.blue(applicationIdWithSuffix))}
+Variant ${color.bold(args.variant)}
+Tasks ${color.bold(humanReadableTasks)}`);
+ const loader = spinner({ indicator: 'timer' });
+ const message = `Building the app`;
+ loader.start(message);
+ const gradleArgs = getTaskNames(androidProject.appName, tasks);
+ gradleArgs.push('-x', 'lint');
+ if (args.extraParams) {
+ gradleArgs.push(...args.extraParams);
+ }
+ if ('port' in args && args.port != null) {
+ gradleArgs.push('-PreactNativeDevServerPort=' + args.port);
+ }
+ if (args.activeArchOnly) {
+ const devices = await getDevices();
+ const cpus = await Promise.all(devices.map(getCPU));
+ const architectures = cpus.filter((arch, index, array) => arch != null && array.indexOf(arch) === index);
+ if (architectures.length > 0) {
+ gradleArgs.push('-PreactNativeArchitectures=' + architectures.join(','));
+ }
+ }
+ const gradleWrapper = getGradleWrapper();
+ try {
+ await spawn(gradleWrapper, gradleArgs, { cwd: androidProject.sourceDir });
+ loader.stop(`Built the app`);
+ }
+ catch (error) {
+ loader.stop('Failed to build the app');
+ const cleanedErrorMessage = getCleanedErrorMessage(error);
+ if (cleanedErrorMessage) {
+ logger.error(cleanedErrorMessage);
+ }
+ const hints = getErrorHints(error.stdout ?? '');
+ throw new RockError(hints ||
+ 'Failed to build the app. See the error above for details from Gradle.');
+ }
+ const outputFilePath = await findOutputFile(androidProject, tasks);
+ if (outputFilePath) {
+ saveLocalBuildCache(artifactName, outputFilePath);
+ }
+}
+export async function runGradleAar({ tasks, aarProject, variant, }) {
+ const loader = spinner({ indicator: 'timer' });
+ const message = variant
+ ? `Building the AAR with Gradle in ${variant} build variant`
+ : 'Publishing the AAR';
+ loader.start(message);
+ const gradleArgs = getTaskNames(aarProject.moduleName, tasks);
+ gradleArgs.push('-x', 'lint');
+ const gradleWrapper = getGradleWrapper();
+ try {
+ logger.debug(`Running ${gradleWrapper} ${gradleArgs.join(' ')}.`);
+ await spawn(gradleWrapper, gradleArgs, { cwd: aarProject.sourceDir });
+ loader.stop(variant
+ ? `Built the AAR in ${variant} build variant.`
+ : 'Published the AAR to local maven (~/.m2/repository)');
+ }
+ catch (error) {
+ loader.stop(`Failed to ${variant ? 'build' : 'publish'} the AAR`);
+ const cleanedErrorMessage = getCleanedErrorMessage(error);
+ if (cleanedErrorMessage) {
+ logger.error(cleanedErrorMessage);
+ }
+ const hints = getErrorHints(error.stdout ?? '');
+ throw new RockError(hints ||
+ `Failed to ${variant ? 'build' : 'publish'} the AAR. See the error above for details from Gradle.`, { cause: error.stderr });
+ }
+}
+function getErrorHints(output) {
+ const signingMessage = output.includes('validateSigningRelease FAILED')
+ ? `Hint: You can run "${color.bold('rock create-keystore:android')}" to create a keystore file.`
+ : '';
+ return signingMessage;
+}
+const gradleLinesToRemove = [
+ 'FAILURE: Build failed with an exception.',
+ '* Try:',
+ '> Run with --stacktrace option to get the stack trace.',
+ '> Run with --info or --debug option to get more log output.',
+ '> Run with --scan to get full insights.',
+ '> Get more help at [undefined](https://help.gradle.org).',
+ '> Get more help at https://help.gradle.org.',
+ 'BUILD FAILED',
+];
+export function getGradleWrapper() {
+ return process.platform.startsWith('win') ? 'gradlew.bat' : './gradlew';
+}
+function getTaskNames(appName, tasks) {
+ return tasks.map((task) => `${appName}:${task}`);
+}
+/**
+ * Gets the CPU architecture of a device from ADB
+ */
+async function getCPU(device) {
+ const adbPath = getAdbPath();
+ try {
+ const { output } = await spawn(adbPath, ['-s', device, 'shell', 'getprop', 'ro.product.cpu.abi'], { stdio: 'pipe' });
+ const cpus = output.trim();
+ return cpus.length > 0 ? cpus : null;
+ }
+ catch {
+ return null;
+ }
+}
+//# sourceMappingURL=runGradle.js.map
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/lib/commands/runGradle.js.map b/packages/platform-android/dist/src/lib/commands/runGradle.js.map
new file mode 100644
index 000000000..d3d2465b2
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/runGradle.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"runGradle.js","sourceRoot":"","sources":["../../../../src/lib/commands/runGradle.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/lib/commands/signAndroid/bundle.d.ts b/packages/platform-android/dist/src/lib/commands/signAndroid/bundle.d.ts
new file mode 100644
index 000000000..247b9ec1d
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/signAndroid/bundle.d.ts
@@ -0,0 +1,8 @@
+type BuildJsBundleOptions = {
+ bundleOutputPath: string;
+ assetsDestPath: string;
+ sourcemapOutputPath: string;
+ useHermes?: boolean;
+};
+export declare function buildJsBundle(options: BuildJsBundleOptions): Promise;
+export {};
diff --git a/packages/platform-android/dist/src/lib/commands/signAndroid/bundle.js b/packages/platform-android/dist/src/lib/commands/signAndroid/bundle.js
new file mode 100644
index 000000000..f9b2ab0fd
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/signAndroid/bundle.js
@@ -0,0 +1,58 @@
+import fs from 'node:fs';
+import { logger, runHermes, spawn } from '@rock-js/tools';
+export async function buildJsBundle(options) {
+ if (fs.existsSync(options.bundleOutputPath)) {
+ fs.unlinkSync(options.bundleOutputPath);
+ logger.debug('Removed existing JS bundle:', options.bundleOutputPath);
+ }
+ if (fs.existsSync(options.sourcemapOutputPath)) {
+ fs.unlinkSync(options.sourcemapOutputPath);
+ logger.debug('Removed existing sourcemap:', options.sourcemapOutputPath);
+ }
+ if (fs.existsSync(options.assetsDestPath)) {
+ fs.rmSync(options.assetsDestPath, { recursive: true });
+ logger.debug('Removed existing assets:', options.assetsDestPath);
+ }
+ // Captured params:
+ // bundle
+ // --platform android
+ // --dev false
+ // --reset-cache
+ // --entry-file /index.js
+ // --bundle-output /android/app/build/generated/assets/createBundleReleaseJsAndAssets/index.android.bundle
+ // --assets-dest /android/app/build/generated/res/createBundleReleaseJsAndAssets
+ // --sourcemap-output /android/app/build/intermediates/sourcemaps/react/release/index.android.bundle.packager.map
+ // --minify false
+ // --verbose
+ // Reasonable defaults
+ // If user wants to build bundle differently, they should use `rock bundle` command directly
+ // and provide the JS bundle path to `--jsbundle` flag
+ const rockBundleArgs = [
+ 'bundle',
+ '--platform',
+ 'android',
+ `--dev`,
+ 'false',
+ '--reset-cache',
+ `--entry-file`,
+ `index.js`,
+ '--bundle-output',
+ options.bundleOutputPath,
+ '--assets-dest',
+ options.assetsDestPath,
+ '--sourcemap-output',
+ options.sourcemapOutputPath,
+ '--minify',
+ 'false',
+ '--verbose',
+ ];
+ await spawn('rock', rockBundleArgs, { preferLocal: true });
+ if (!options.useHermes) {
+ return;
+ }
+ await runHermes({
+ bundleOutputPath: options.bundleOutputPath,
+ sourcemapOutputPath: options.sourcemapOutputPath,
+ });
+}
+//# sourceMappingURL=bundle.js.map
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/lib/commands/signAndroid/bundle.js.map b/packages/platform-android/dist/src/lib/commands/signAndroid/bundle.js.map
new file mode 100644
index 000000000..bf2508f13
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/signAndroid/bundle.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"bundle.js","sourceRoot":"","sources":["../../../../../src/lib/commands/signAndroid/bundle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAS1D,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,OAA6B;IAC/D,IAAI,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE,CAAC;QAC5C,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;QACxC,MAAM,CAAC,KAAK,CAAC,6BAA6B,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACxE,CAAC;IAED,IAAI,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,mBAAmB,CAAC,EAAE,CAAC;QAC/C,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;QAC3C,MAAM,CAAC,KAAK,CAAC,6BAA6B,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC3E,CAAC;IAED,IAAI,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE,CAAC;QAC1C,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACvD,MAAM,CAAC,KAAK,CAAC,0BAA0B,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IACnE,CAAC;IAED,mBAAmB;IACnB,SAAS;IACT,uBAAuB;IACvB,gBAAgB;IAChB,kBAAkB;IAClB,wCAAwC;IACxC,yHAAyH;IACzH,+FAA+F;IAC/F,gIAAgI;IAChI,mBAAmB;IACnB,cAAc;IAEd,sBAAsB;IACtB,4FAA4F;IAC5F,sDAAsD;IACtD,MAAM,cAAc,GAAG;QACrB,QAAQ;QACR,YAAY;QACZ,SAAS;QACT,OAAO;QACP,OAAO;QACP,eAAe;QACf,cAAc;QACd,UAAU;QACV,iBAAiB;QACjB,OAAO,CAAC,gBAAgB;QACxB,eAAe;QACf,OAAO,CAAC,cAAc;QACtB,oBAAoB;QACpB,OAAO,CAAC,mBAAmB;QAC3B,UAAU;QACV,OAAO;QACP,WAAW;KACZ,CAAC;IACF,MAAM,KAAK,CAAC,MAAM,EAAE,cAAc,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC;IAE3D,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC;QACvB,OAAO;IACT,CAAC;IAED,MAAM,SAAS,CAAC;QACd,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;QAC1C,mBAAmB,EAAE,OAAO,CAAC,mBAAmB;KACjD,CAAC,CAAC;AACL,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/lib/commands/signAndroid/command.d.ts b/packages/platform-android/dist/src/lib/commands/signAndroid/command.d.ts
new file mode 100644
index 000000000..53bf78193
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/signAndroid/command.d.ts
@@ -0,0 +1,14 @@
+import type { PluginApi } from '@rock-js/config';
+export type SignFlags = {
+ verbose?: boolean;
+ path: string;
+ output?: string;
+ keystore?: string;
+ keystorePassword?: string;
+ keyAlias?: string;
+ keyPassword?: string;
+ buildJsbundle?: boolean;
+ jsbundle?: string;
+ noHermes?: boolean;
+};
+export declare const registerSignCommand: (api: PluginApi) => void;
diff --git a/packages/platform-android/dist/src/lib/commands/signAndroid/command.js b/packages/platform-android/dist/src/lib/commands/signAndroid/command.js
new file mode 100644
index 000000000..e0fce174b
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/signAndroid/command.js
@@ -0,0 +1,67 @@
+import { signAndroid } from './signAndroid.js';
+const ARGUMENTS = [
+ {
+ name: 'binaryPath',
+ description: 'Archive (apk or aab) file path',
+ },
+];
+const OPTIONS = [
+ {
+ name: '--verbose',
+ description: '',
+ },
+ {
+ name: '--keystore ',
+ description: 'Path to keystore file',
+ },
+ {
+ name: '--keystore-password ',
+ description: 'Password for keystore file',
+ },
+ {
+ name: '--key-alias ',
+ description: 'Alias for key in keystore file',
+ },
+ {
+ name: '--key-password ',
+ description: 'Password for key in keystore file',
+ },
+ {
+ name: '--output ',
+ description: 'Path to the output APK/AAB file.',
+ },
+ {
+ name: '--build-jsbundle',
+ description: 'Build the JS bundle before signing.',
+ },
+ {
+ name: '--jsbundle ',
+ description: 'Path to the JS bundle to apply before signing.',
+ },
+ {
+ name: '--no-hermes',
+ description: 'Do not use Hermes to build the JS bundle.',
+ },
+];
+export const registerSignCommand = (api) => {
+ api.registerCommand({
+ name: 'sign:android',
+ description: 'Sign the Android app with modified JS bundle.',
+ args: ARGUMENTS,
+ options: OPTIONS,
+ action: async (binaryPath, flags) => {
+ await signAndroid({
+ binaryPath,
+ keystorePath: flags.keystore,
+ keystorePassword: flags.keystorePassword,
+ keyAlias: flags.keyAlias,
+ keyPassword: flags.keyPassword,
+ outputPath: flags.output,
+ buildJsBundle: flags.buildJsbundle,
+ jsBundlePath: flags.jsbundle,
+ useHermes: !flags.noHermes,
+ });
+ },
+ });
+};
+//# sourceMappingURL=command.js.map
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/lib/commands/signAndroid/command.js.map b/packages/platform-android/dist/src/lib/commands/signAndroid/command.js.map
new file mode 100644
index 000000000..89d7bbac5
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/signAndroid/command.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"command.js","sourceRoot":"","sources":["../../../../../src/lib/commands/signAndroid/command.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAe/C,MAAM,SAAS,GAAG;IAChB;QACE,IAAI,EAAE,YAAY;QAClB,WAAW,EAAE,gCAAgC;KAC9C;CACF,CAAC;AAEF,MAAM,OAAO,GAAG;IACd;QACE,IAAI,EAAE,WAAW;QACjB,WAAW,EAAE,EAAE;KAChB;IACD;QACE,IAAI,EAAE,qBAAqB;QAC3B,WAAW,EAAE,uBAAuB;KACrC;IACD;QACE,IAAI,EAAE,8BAA8B;QACpC,WAAW,EAAE,4BAA4B;KAC1C;IACD;QACE,IAAI,EAAE,sBAAsB;QAC5B,WAAW,EAAE,gCAAgC;KAC9C;IACD;QACE,IAAI,EAAE,yBAAyB;QAC/B,WAAW,EAAE,mCAAmC;KACjD;IACD;QACE,IAAI,EAAE,mBAAmB;QACzB,WAAW,EAAE,kCAAkC;KAChD;IACD;QACE,IAAI,EAAE,kBAAkB;QACxB,WAAW,EAAE,qCAAqC;KACnD;IACD;QACE,IAAI,EAAE,qBAAqB;QAC3B,WAAW,EAAE,gDAAgD;KAC9D;IACD;QACE,IAAI,EAAE,aAAa;QACnB,WAAW,EAAE,2CAA2C;KACzD;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,GAAc,EAAE,EAAE;IACpD,GAAG,CAAC,eAAe,CAAC;QAClB,IAAI,EAAE,cAAc;QACpB,WAAW,EAAE,+CAA+C;QAC5D,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,OAAO;QAChB,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,KAAgB,EAAE,EAAE;YAC7C,MAAM,WAAW,CAAC;gBAChB,UAAU;gBACV,YAAY,EAAE,KAAK,CAAC,QAAQ;gBAC5B,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;gBACxC,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,WAAW,EAAE,KAAK,CAAC,WAAW;gBAC9B,UAAU,EAAE,KAAK,CAAC,MAAM;gBACxB,aAAa,EAAE,KAAK,CAAC,aAAa;gBAClC,YAAY,EAAE,KAAK,CAAC,QAAQ;gBAC5B,SAAS,EAAE,CAAC,KAAK,CAAC,QAAQ;aAC3B,CAAC,CAAC;QACL,CAAC;KACF,CAAC,CAAC;AACL,CAAC,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/lib/commands/signAndroid/signAndroid.d.ts b/packages/platform-android/dist/src/lib/commands/signAndroid/signAndroid.d.ts
new file mode 100644
index 000000000..a576c37bb
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/signAndroid/signAndroid.d.ts
@@ -0,0 +1,12 @@
+export type SignAndroidOptions = {
+ binaryPath: string;
+ keystorePath?: string;
+ keystorePassword?: string;
+ keyAlias?: string;
+ keyPassword?: string;
+ outputPath?: string;
+ buildJsBundle?: boolean;
+ jsBundlePath?: string;
+ useHermes?: boolean;
+};
+export declare function signAndroid(options: SignAndroidOptions): Promise;
diff --git a/packages/platform-android/dist/src/lib/commands/signAndroid/signAndroid.js b/packages/platform-android/dist/src/lib/commands/signAndroid/signAndroid.js
new file mode 100644
index 000000000..bf00b00c6
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/signAndroid/signAndroid.js
@@ -0,0 +1,169 @@
+import fs from 'node:fs';
+import path from 'node:path';
+import { colorLink, getDotRockPath, intro, outro, relativeToCwd, RockError, spawn, spinner, } from '@rock-js/tools';
+import AdmZip from 'adm-zip';
+import { findAndroidBuildTool, getAndroidBuildToolsPath } from '../../paths.js';
+import { buildJsBundle } from './bundle.js';
+export async function signAndroid(options) {
+ validateOptions(options);
+ const extension = path.extname(options.binaryPath).slice(1);
+ intro(`Modifying ${extension.toUpperCase()} file`);
+ const tempPath = getSignOutputPath();
+ if (fs.existsSync(tempPath)) {
+ fs.rmSync(tempPath, { recursive: true });
+ }
+ const loader = spinner();
+ // 1. Build JS bundle if needed
+ if (options.buildJsBundle) {
+ const bundleOutputPath = path.join(tempPath, 'index.android.bundle');
+ loader.start('Building JS bundle...');
+ await buildJsBundle({
+ bundleOutputPath,
+ assetsDestPath: path.join(tempPath, 'res'),
+ sourcemapOutputPath: path.join(tempPath, 'index.android.bundle.packager.map'),
+ useHermes: options.useHermes ?? true,
+ });
+ loader.stop(`Built JS bundle: ${colorLink(relativeToCwd(bundleOutputPath))}`);
+ options.jsBundlePath = bundleOutputPath;
+ }
+ // 2. Initialize temporary archive file
+ const tempArchivePath = path.join(tempPath, `output-app.${extension}`);
+ loader.start(`Initializing output ${extension.toUpperCase()}...`);
+ try {
+ const zip = new AdmZip(options.binaryPath);
+ // Remove old signature files
+ zip.deleteFile('META-INF/*');
+ zip.writeZip(tempArchivePath);
+ }
+ catch (error) {
+ throw new RockError(`Failed to initialize output file: ${options.outputPath}`, { cause: error.stderr });
+ }
+ loader.stop(`Initialized output ${extension.toUpperCase()}`);
+ // 3. Replace JS bundle if provided
+ if (options.jsBundlePath) {
+ loader.start('Replacing JS bundle...');
+ await replaceJsBundle({
+ archivePath: tempArchivePath,
+ jsBundlePath: options.jsBundlePath,
+ });
+ loader.stop(`Replaced JS bundle with ${colorLink(relativeToCwd(options.jsBundlePath))}.`);
+ }
+ // 4. Align archive
+ loader.start('Aligning output file...');
+ const outputPath = options.outputPath ?? options.binaryPath;
+ await alignArchiveFile(tempArchivePath, outputPath);
+ loader.stop(`Created output ${extension.toUpperCase()} file: ${colorLink(relativeToCwd(outputPath))}.`);
+ // 5. Sign archive file
+ loader.start(`Signing the ${extension.toUpperCase()} file...`);
+ const keystorePath = options.keystorePath ?? 'android/app/debug.keystore';
+ await signArchive({
+ binaryPath: outputPath,
+ keystorePath,
+ keystorePassword: options.keystorePassword ?? 'pass:android',
+ keyAlias: options.keyAlias,
+ keyPassword: options.keyPassword,
+ });
+ loader.stop(`Signed the ${extension.toUpperCase()} file with keystore: ${colorLink(keystorePath)}.`);
+ outro('Success ๐.');
+}
+function validateOptions(options) {
+ if (!fs.existsSync(options.binaryPath)) {
+ throw new RockError(`File not found "${options.binaryPath}"`);
+ }
+ if (options.buildJsBundle && options.jsBundlePath) {
+ throw new RockError('The "--build-jsbundle" flag is incompatible with "--jsbundle". Pick one.');
+ }
+ if (options.jsBundlePath && !fs.existsSync(options.jsBundlePath)) {
+ throw new RockError(`JS bundle file not found "${options.jsBundlePath}"`);
+ }
+}
+async function replaceJsBundle({ archivePath, jsBundlePath, }) {
+ try {
+ const zip = new AdmZip(archivePath);
+ const assetsPath = isAab(archivePath) ? 'base/assets' : 'assets';
+ zip.deleteFile(path.join(assetsPath, 'index.android.bundle'));
+ zip.addLocalFile(jsBundlePath, assetsPath, 'index.android.bundle');
+ zip.writeZip(archivePath);
+ }
+ catch (error) {
+ throw new RockError(`Failed to replace JS bundle in destination file: ${archivePath}`, { cause: error });
+ }
+}
+function isSdkGTE35(versionString) {
+ const match = versionString.match(/build-tools\/([\d.]+)/);
+ if (!match)
+ return false;
+ return match[1].localeCompare('35.0.0', undefined, { numeric: true }) >= 0;
+}
+async function alignArchiveFile(inputArchivePath, outputPath) {
+ const zipAlignPath = findAndroidBuildTool('zipalign');
+ if (!zipAlignPath) {
+ throw new RockError(`"zipalign" not found in Android Build-Tools directory: ${colorLink(getAndroidBuildToolsPath())}
+Please follow instructions at: https://reactnative.dev/docs/set-up-your-environment?platform=android'`);
+ }
+ // See: https://developer.android.com/tools/zipalign#usage
+ const zipalignArgs = [
+ // aligns uncompressed .so files to the specified page size in KiB. Available since SDK 35
+ ...(isSdkGTE35(zipAlignPath) ? ['-P', '16'] : ['-p']),
+ '-f', // Overwrites existing output file.
+ '-v', // Overwrites existing output file.
+ '4', // alignment in bytes, e.g. '4' provides 32-bit alignment
+ inputArchivePath,
+ outputPath,
+ ];
+ try {
+ await spawn(zipAlignPath, zipalignArgs);
+ }
+ catch (error) {
+ throw new RockError(`Failed to align archive file: ${zipAlignPath} ${zipalignArgs.join(' ')}`, { cause: error.stderr });
+ }
+}
+async function signArchive({ binaryPath, keystorePath, keystorePassword, keyAlias, keyPassword, }) {
+ if (!fs.existsSync(keystorePath)) {
+ throw new RockError(`Keystore file not found "${keystorePath}". Provide a valid keystore path using the "--keystore" option.`);
+ }
+ const apksignerPath = findAndroidBuildTool('apksigner');
+ if (!apksignerPath) {
+ throw new RockError(`"apksigner" not found in Android Build-Tools directory: ${colorLink(getAndroidBuildToolsPath())}
+Please follow instructions at: https://reactnative.dev/docs/set-up-your-environment?platform=android'`);
+ }
+ // apksigner sign --ks-pass "pass:android" --ks "android/app/debug.keystore" --ks-key-alias "androiddebugkey" --key-pass "pass:android" "$OUTPUT2_APK"
+ const apksignerArgs = [
+ 'sign',
+ '--ks',
+ keystorePath,
+ '--ks-pass',
+ formatPassword(keystorePassword),
+ ...(keyAlias ? ['--ks-key-alias', keyAlias] : []),
+ ...(keyPassword ? ['--key-pass', formatPassword(keyPassword)] : []),
+ ...(isAab(binaryPath) ? ['--min-sdk-version', '36'] : []),
+ binaryPath,
+ ];
+ try {
+ await spawn(apksignerPath, apksignerArgs);
+ }
+ catch (error) {
+ throw new RockError(`Failed to sign APK file: ${apksignerPath} ${apksignerArgs.join(' ')}`, { cause: error.stderr });
+ }
+}
+/**
+ * apksigner expects the password info to be prefixed by the password type.
+ *
+ * @see https://developer.android.com/tools/apksigner
+ */
+function formatPassword(password) {
+ if (password.startsWith('pass:') ||
+ password.startsWith('env:') ||
+ password.startsWith('file:') ||
+ password === 'stdin') {
+ return password;
+ }
+ return `pass:${password}`;
+}
+function getSignOutputPath() {
+ return path.join(getDotRockPath(), 'android/sign');
+}
+function isAab(filePath) {
+ return path.extname(filePath).toLowerCase() === '.aab';
+}
+//# sourceMappingURL=signAndroid.js.map
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/lib/commands/signAndroid/signAndroid.js.map b/packages/platform-android/dist/src/lib/commands/signAndroid/signAndroid.js.map
new file mode 100644
index 000000000..0bbf022e4
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/signAndroid/signAndroid.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"signAndroid.js","sourceRoot":"","sources":["../../../../../src/lib/commands/signAndroid/signAndroid.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/lib/commands/toPascalCase.d.ts b/packages/platform-android/dist/src/lib/commands/toPascalCase.d.ts
new file mode 100644
index 000000000..cdd38c9e5
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/toPascalCase.d.ts
@@ -0,0 +1 @@
+export declare function toPascalCase(value: string): string;
diff --git a/packages/platform-android/dist/src/lib/commands/toPascalCase.js b/packages/platform-android/dist/src/lib/commands/toPascalCase.js
new file mode 100644
index 000000000..656bebdbb
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/toPascalCase.js
@@ -0,0 +1,4 @@
+export function toPascalCase(value) {
+ return value !== '' ? value[0].toUpperCase() + value.slice(1) : value;
+}
+//# sourceMappingURL=toPascalCase.js.map
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/lib/commands/toPascalCase.js.map b/packages/platform-android/dist/src/lib/commands/toPascalCase.js.map
new file mode 100644
index 000000000..3986ae069
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/commands/toPascalCase.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"toPascalCase.js","sourceRoot":"","sources":["../../../../src/lib/commands/toPascalCase.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,OAAO,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;AACxE,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/lib/getApkInfo.d.ts b/packages/platform-android/dist/src/lib/getApkInfo.d.ts
new file mode 100644
index 000000000..50fc4208f
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/getApkInfo.d.ts
@@ -0,0 +1,12 @@
+export interface ApkInfo {
+ packageName: string;
+ version: string;
+}
+/**
+ * Extracts package information from an APK file using app-info-parser.
+ * Similar to getInfoPlist for iOS, but for Android APK files.
+ *
+ * @param apkPath - Path to the APK file
+ * @returns Object containing packageName and version
+ */
+export declare function getApkInfo(apkPath: string): Promise;
diff --git a/packages/platform-android/dist/src/lib/getApkInfo.js b/packages/platform-android/dist/src/lib/getApkInfo.js
new file mode 100644
index 000000000..ffe97120b
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/getApkInfo.js
@@ -0,0 +1,29 @@
+import path from 'node:path';
+// @ts-expect-error - app-info-parser doesn't have types
+import AppInfoParser from 'app-info-parser';
+/**
+ * Extracts package information from an APK file using app-info-parser.
+ * Similar to getInfoPlist for iOS, but for Android APK files.
+ *
+ * @param apkPath - Path to the APK file
+ * @returns Object containing packageName and version
+ */
+export async function getApkInfo(apkPath) {
+ try {
+ const parser = new AppInfoParser(apkPath);
+ const appInfo = await parser.parse();
+ return {
+ packageName: appInfo.package || 'unknown',
+ version: appInfo.versionName || appInfo.versionCode?.toString() || '1.0',
+ };
+ }
+ catch {
+ // Fallback to filename if parsing fails
+ const apkFileName = path.basename(apkPath, '.apk');
+ return {
+ packageName: apkFileName,
+ version: '1.0',
+ };
+ }
+}
+//# sourceMappingURL=getApkInfo.js.map
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/lib/getApkInfo.js.map b/packages/platform-android/dist/src/lib/getApkInfo.js.map
new file mode 100644
index 000000000..465d5ff0c
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/getApkInfo.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"getApkInfo.js","sourceRoot":"","sources":["../../../src/lib/getApkInfo.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,wDAAwD;AACxD,OAAO,aAAa,MAAM,iBAAiB,CAAC;AAO5C;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,OAAe;IAC9C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,aAAa,CAAC,OAAO,CAAC,CAAC;QAC1C,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QAErC,OAAO;YACL,WAAW,EAAE,OAAO,CAAC,OAAO,IAAI,SAAS;YACzC,OAAO,EAAE,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,WAAW,EAAE,QAAQ,EAAE,IAAI,KAAK;SACzE,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,wCAAwC;QACxC,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACnD,OAAO;YACL,WAAW,EAAE,WAAW;YACxB,OAAO,EAAE,KAAK;SACf,CAAC;IACJ,CAAC;AACH,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/lib/paths.d.ts b/packages/platform-android/dist/src/lib/paths.d.ts
new file mode 100644
index 000000000..67b9fe02e
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/paths.d.ts
@@ -0,0 +1,7 @@
+export declare function getAndroidSdkPath(): string;
+export declare function getAndroidBuildToolsPath(): string;
+/**
+ * Build tools are located in the /build-tools// directory.
+ */
+export declare function findAndroidBuildTool(toolName: string): string | null;
+export declare function versionCompare(first: string, second: string): number;
diff --git a/packages/platform-android/dist/src/lib/paths.js b/packages/platform-android/dist/src/lib/paths.js
new file mode 100644
index 000000000..8655e7fbd
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/paths.js
@@ -0,0 +1,60 @@
+import fs from 'node:fs';
+import path from 'node:path';
+export function getAndroidSdkPath() {
+ const sdkRoot = process.env['ANDROID_HOME'] || process.env['ANDROID_SDK_ROOT'];
+ if (!sdkRoot) {
+ throw new Error('ANDROID_HOME or ANDROID_SDK_ROOT environment variable is not set. Please follow instructions at: https://reactnative.dev/docs/set-up-your-environment?platform=android');
+ }
+ return sdkRoot;
+}
+export function getAndroidBuildToolsPath() {
+ return path.join(getAndroidSdkPath(), 'build-tools');
+}
+/**
+ * Build tools are located in the /build-tools// directory.
+ */
+export function findAndroidBuildTool(toolName) {
+ const buildToolsPath = path.join(getAndroidBuildToolsPath());
+ const versions = fs
+ .readdirSync(buildToolsPath, { withFileTypes: true })
+ .filter((entry) => entry.isDirectory())
+ .map((entry) => entry.name)
+ .sort(versionCompare)
+ .reverse();
+ for (const version of versions) {
+ const toolPath = path.join(buildToolsPath, version, toolName);
+ if (fs.existsSync(toolPath)) {
+ return toolPath;
+ }
+ }
+ return null;
+}
+export function versionCompare(first, second) {
+ const firstVersion = parseVersionString(first);
+ const secondVersion = parseVersionString(second);
+ if (!firstVersion || !secondVersion) {
+ return first.localeCompare(second);
+ }
+ if (firstVersion.major !== secondVersion.major) {
+ return firstVersion.major - secondVersion.major;
+ }
+ if (firstVersion.minor !== secondVersion.minor) {
+ return firstVersion.minor - secondVersion.minor;
+ }
+ return firstVersion.patch - secondVersion.patch;
+}
+function parseVersionString(version) {
+ if (!isVersionString(version)) {
+ return null;
+ }
+ const [major, minor, patch] = version.split('.').map(Number);
+ return {
+ major: Number(major),
+ minor: Number(minor),
+ patch: Number(patch),
+ };
+}
+function isVersionString(version) {
+ return /^[0-9]+\.[0-9]+\.[0-9]+$/.test(version);
+}
+//# sourceMappingURL=paths.js.map
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/lib/paths.js.map b/packages/platform-android/dist/src/lib/paths.js.map
new file mode 100644
index 000000000..6661f2d0e
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/paths.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../../src/lib/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,UAAU,iBAAiB;IAC/B,MAAM,OAAO,GACX,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;IACjE,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,wKAAwK,CACzK,CAAC;IACJ,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,wBAAwB;IACtC,OAAO,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,EAAE,aAAa,CAAC,CAAC;AACvD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,QAAgB;IACnD,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,wBAAwB,EAAE,CAAC,CAAC;IAC7D,MAAM,QAAQ,GAAG,EAAE;SAChB,WAAW,CAAC,cAAc,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;SACpD,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;SACtC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC;SAC1B,IAAI,CAAC,cAAc,CAAC;SACpB,OAAO,EAAE,CAAC;IAEb,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;QAC9D,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC5B,OAAO,QAAQ,CAAC;QAClB,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAa,EAAE,MAAc;IAC1D,MAAM,YAAY,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;IAC/C,MAAM,aAAa,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAEjD,IAAI,CAAC,YAAY,IAAI,CAAC,aAAa,EAAE,CAAC;QACpC,OAAO,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;IACrC,CAAC;IAED,IAAI,YAAY,CAAC,KAAK,KAAK,aAAa,CAAC,KAAK,EAAE,CAAC;QAC/C,OAAO,YAAY,CAAC,KAAK,GAAG,aAAa,CAAC,KAAK,CAAC;IAClD,CAAC;IACD,IAAI,YAAY,CAAC,KAAK,KAAK,aAAa,CAAC,KAAK,EAAE,CAAC;QAC/C,OAAO,YAAY,CAAC,KAAK,GAAG,aAAa,CAAC,KAAK,CAAC;IAClD,CAAC;IAED,OAAO,YAAY,CAAC,KAAK,GAAG,aAAa,CAAC,KAAK,CAAC;AAClD,CAAC;AAED,SAAS,kBAAkB,CAAC,OAAe;IACzC,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,EAAE,CAAC;QAC9B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC7D,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC;QACpB,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC;QACpB,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC;KACrB,CAAC;AACJ,CAAC;AAED,SAAS,eAAe,CAAC,OAAe;IACtC,OAAO,0BAA0B,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AAClD,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/lib/platformAndroid.d.ts b/packages/platform-android/dist/src/lib/platformAndroid.d.ts
new file mode 100644
index 000000000..5628e9814
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/platformAndroid.d.ts
@@ -0,0 +1,5 @@
+import type { AndroidProjectConfig } from '@react-native-community/cli-types';
+import type { PlatformOutput, PluginApi } from '@rock-js/config';
+type PluginConfig = AndroidProjectConfig;
+export declare const platformAndroid: (pluginConfig?: Partial) => (api: PluginApi) => PlatformOutput;
+export default platformAndroid;
diff --git a/packages/platform-android/dist/src/lib/platformAndroid.js b/packages/platform-android/dist/src/lib/platformAndroid.js
new file mode 100644
index 000000000..89fd2aed4
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/platformAndroid.js
@@ -0,0 +1,23 @@
+import { registerBuildCommand } from './commands/buildAndroid/command.js';
+import { registerCreateKeystoreCommand } from './commands/generateKeystore.js';
+import { getValidProjectConfig } from './commands/getValidProjectConfig.js';
+import { registerRunCommand } from './commands/runAndroid/command.js';
+import { registerSignCommand } from './commands/signAndroid/command.js';
+export const platformAndroid = (pluginConfig) => (api) => {
+ registerBuildCommand(api, pluginConfig);
+ registerRunCommand(api, pluginConfig);
+ registerCreateKeystoreCommand(api, pluginConfig);
+ registerSignCommand(api);
+ return {
+ name: '@rock-js/platform-android',
+ description: 'Rock plugin for everything Android.',
+ autolinkingConfig: {
+ get project() {
+ const androidConfig = getValidProjectConfig(api.getProjectRoot(), pluginConfig);
+ return { ...androidConfig };
+ },
+ },
+ };
+};
+export default platformAndroid;
+//# sourceMappingURL=platformAndroid.js.map
\ No newline at end of file
diff --git a/packages/platform-android/dist/src/lib/platformAndroid.js.map b/packages/platform-android/dist/src/lib/platformAndroid.js.map
new file mode 100644
index 000000000..185c74a84
--- /dev/null
+++ b/packages/platform-android/dist/src/lib/platformAndroid.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"platformAndroid.js","sourceRoot":"","sources":["../../../src/lib/platformAndroid.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAC1E,OAAO,EAAE,6BAA6B,EAAE,MAAM,gCAAgC,CAAC;AAC/E,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAC5E,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AAIxE,MAAM,CAAC,MAAM,eAAe,GAC1B,CAAC,YAAoC,EAAE,EAAE,CACzC,CAAC,GAAc,EAAkB,EAAE;IACjC,oBAAoB,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IACxC,kBAAkB,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IACtC,6BAA6B,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IACjD,mBAAmB,CAAC,GAAG,CAAC,CAAC;IAEzB,OAAO;QACL,IAAI,EAAE,2BAA2B;QACjC,WAAW,EAAE,qCAAqC;QAClD,iBAAiB,EAAE;YACjB,IAAI,OAAO;gBACT,MAAM,aAAa,GAAG,qBAAqB,CACzC,GAAG,CAAC,cAAc,EAAE,EACpB,YAAY,CACb,CAAC;gBACF,OAAO,EAAE,GAAG,aAAa,EAAE,CAAC;YAC9B,CAAC;SACF;KACF,CAAC;AACJ,CAAC,CAAC;AAEJ,eAAe,eAAe,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/index.d.ts b/packages/platform-apple-helpers/dist/src/index.d.ts
new file mode 100644
index 000000000..09c185e22
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/index.d.ts
@@ -0,0 +1 @@
+export * from './lib/index.js';
diff --git a/packages/platform-apple-helpers/dist/src/index.js b/packages/platform-apple-helpers/dist/src/index.js
new file mode 100644
index 000000000..6be7947e9
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/index.js
@@ -0,0 +1,2 @@
+export * from './lib/index.js';
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/index.js.map b/packages/platform-apple-helpers/dist/src/index.js.map
new file mode 100644
index 000000000..15330ef5a
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/build/buildOptions.d.ts b/packages/platform-apple-helpers/dist/src/lib/commands/build/buildOptions.d.ts
new file mode 100644
index 000000000..698a369a9
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/build/buildOptions.d.ts
@@ -0,0 +1,33 @@
+import { parseArgs } from '@rock-js/tools';
+import type { BuilderCommand } from '../../types/index.js';
+export type BuildFlags = {
+ verbose?: boolean;
+ configuration?: string;
+ scheme?: string;
+ target?: string;
+ extraParams?: string[];
+ exportExtraParams?: string[];
+ exportOptionsPlist?: string;
+ buildFolder?: string;
+ destination?: string[];
+ archive?: boolean;
+ installPods: boolean;
+ newArch: boolean;
+ local?: boolean;
+};
+export declare const getBuildOptions: ({ platformName }: BuilderCommand) => ({
+ name: string;
+ description: string;
+ parse?: undefined;
+ value?: undefined;
+} | {
+ name: string;
+ description: string;
+ parse: typeof parseArgs;
+ value?: undefined;
+} | {
+ name: string;
+ description: string;
+ value: string;
+ parse?: undefined;
+})[];
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/build/buildOptions.js b/packages/platform-apple-helpers/dist/src/lib/commands/build/buildOptions.js
new file mode 100644
index 000000000..ba205d470
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/build/buildOptions.js
@@ -0,0 +1,65 @@
+import { parseArgs } from '@rock-js/tools';
+import { getPlatformInfo } from '../../utils/getPlatformInfo.js';
+export const getBuildOptions = ({ platformName }) => {
+ const { readableName } = getPlatformInfo(platformName);
+ return [
+ {
+ name: '--verbose',
+ description: '',
+ },
+ {
+ name: '--configuration ',
+ description: 'Explicitly set the scheme configuration to use. This option is case sensitive.',
+ },
+ {
+ name: '--scheme ',
+ description: 'Explicitly set Xcode scheme to use',
+ },
+ {
+ name: '--target ',
+ description: 'Explicitly set Xcode target to use.',
+ },
+ {
+ name: '--extra-params ',
+ description: 'Custom params that will be passed to xcodebuild command.',
+ parse: parseArgs,
+ },
+ {
+ name: '--export-extra-params ',
+ description: 'Custom params that will be passed to xcodebuild export archive command.\n' +
+ 'Example:\n' +
+ ' --export-extra-params "-allowProvisioningUpdates"',
+ parse: parseArgs,
+ },
+ {
+ name: '--export-options-plist ',
+ description: 'Name of the export options file for archiving. Defaults to: ExportOptions.plist',
+ },
+ {
+ name: '--build-folder ',
+ description: `Location for ${readableName} build artifacts. Corresponds to Xcode's "-derivedDataPath".`,
+ value: 'build',
+ },
+ {
+ name: '--destination ',
+ description: 'Define destination(s) for the build. You can pass multiple destinations as separate values or repeated use of the flag. Values can be either: "simulator", "device" or destinations supported by "xcodebuild -destination" flag, e.g. "generic/platform=iOS"',
+ },
+ {
+ name: '--archive',
+ description: 'Create an Xcode archive (IPA) of the build, required for uploading to App Store Connect or distributing to TestFlight',
+ },
+ {
+ name: '--no-install-pods',
+ description: 'Skip automatic CocoaPods installation',
+ },
+ {
+ name: '--no-new-arch',
+ description: 'Run React Native in legacy async architecture.',
+ },
+ {
+ name: '--local',
+ description: 'Force local build with xcodebuild.',
+ },
+ ];
+};
+//# sourceMappingURL=buildOptions.js.map
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/build/buildOptions.js.map b/packages/platform-apple-helpers/dist/src/lib/commands/build/buildOptions.js.map
new file mode 100644
index 000000000..4b0b82490
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/build/buildOptions.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"buildOptions.js","sourceRoot":"","sources":["../../../../../src/lib/commands/build/buildOptions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAkBjE,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,EAAE,YAAY,EAAkB,EAAE,EAAE;IAClE,MAAM,EAAE,YAAY,EAAE,GAAG,eAAe,CAAC,YAAY,CAAC,CAAC;IAEvD,OAAO;QACL;YACE,IAAI,EAAE,WAAW;YACjB,WAAW,EAAE,EAAE;SAChB;QACD;YACE,IAAI,EAAE,0BAA0B;YAChC,WAAW,EACT,gFAAgF;SACnF;QACD;YACE,IAAI,EAAE,mBAAmB;YACzB,WAAW,EAAE,oCAAoC;SAClD;QACD;YACE,IAAI,EAAE,mBAAmB;YACzB,WAAW,EAAE,qCAAqC;SACnD;QACD;YACE,IAAI,EAAE,yBAAyB;YAC/B,WAAW,EAAE,0DAA0D;YACvE,KAAK,EAAE,SAAS;SACjB;QACD;YACE,IAAI,EAAE,gCAAgC;YACtC,WAAW,EACT,2EAA2E;gBAC3E,YAAY;gBACZ,qDAAqD;YACvD,KAAK,EAAE,SAAS;SACjB;QACD;YACE,IAAI,EAAE,iCAAiC;YACvC,WAAW,EACT,iFAAiF;SACpF;QACD;YACE,IAAI,EAAE,yBAAyB;YAC/B,WAAW,EAAE,gBAAgB,YAAY,8DAA8D;YACvG,KAAK,EAAE,OAAO;SACf;QACD;YACE,IAAI,EAAE,4BAA4B;YAClC,WAAW,EACT,8PAA8P;SACjQ;QACD;YACE,IAAI,EAAE,WAAW;YACjB,WAAW,EACT,uHAAuH;SAC1H;QACD;YACE,IAAI,EAAE,mBAAmB;YACzB,WAAW,EAAE,uCAAuC;SACrD;QACD;YACE,IAAI,EAAE,eAAe;YACrB,WAAW,EAAE,gDAAgD;SAC9D;QACD;YACE,IAAI,EAAE,SAAS;YACf,WAAW,EAAE,oCAAoC;SAClD;KACF,CAAC;AACJ,CAAC,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/build/buildProject.d.ts b/packages/platform-apple-helpers/dist/src/lib/commands/build/buildProject.d.ts
new file mode 100644
index 000000000..5558502d7
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/build/buildProject.d.ts
@@ -0,0 +1,12 @@
+import type { ApplePlatform, XcodeProjectInfo } from '../../types/index.js';
+import type { RunFlags } from '../run/runOptions.js';
+import type { BuildFlags } from './buildOptions.js';
+export declare const buildProject: ({ xcodeProject, sourceDir, platformName, scheme, configuration, destinations, args, }: {
+ xcodeProject: XcodeProjectInfo;
+ sourceDir: string;
+ platformName: ApplePlatform;
+ scheme: string;
+ configuration: string;
+ destinations: string[];
+ args: RunFlags | BuildFlags;
+}) => Promise;
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/build/buildProject.js b/packages/platform-apple-helpers/dist/src/lib/commands/build/buildProject.js
new file mode 100644
index 000000000..61234acee
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/build/buildProject.js
@@ -0,0 +1,109 @@
+import path from 'node:path';
+import { color, logger, RockError, spawn, spinner } from '@rock-js/tools';
+import { getBuildPaths } from '../../utils/getBuildPaths.js';
+import { supportedPlatforms } from '../../utils/supportedPlatforms.js';
+let lastProgress = 0;
+/**
+ * Creates an ASCII progress bar
+ * @param percent - Percentage of completion (0-100)
+ * @param length - Length of the progress bar in characters
+ * @returns ASCII progress bar string
+ */
+function createProgressBar(percent, length = 20) {
+ const latestPercent = percent > lastProgress ? percent : lastProgress;
+ lastProgress = latestPercent;
+ const filledLength = Math.round(length * (latestPercent / 100));
+ const emptyLength = length - filledLength;
+ const filled = 'โ'.repeat(filledLength);
+ const empty = 'โ'.repeat(emptyLength);
+ return `[${filled}${empty}]`;
+}
+function reportProgress(chunk, loader, message) {
+ if (chunk.includes('PhaseScriptExecution')) {
+ if (chunk.includes('[CP-User]\\ [Hermes]\\ Replace\\ Hermes\\')) {
+ const progressBar = createProgressBar(10);
+ loader.message(`${message} ${progressBar}`);
+ }
+ if (chunk.includes('[CP-User]\\ [RN]Check\\ rncore') &&
+ chunk.includes('React-Fabric')) {
+ const progressBar = createProgressBar(35);
+ loader.message(`${message} ${progressBar}`);
+ }
+ if (chunk.includes('[CP-User]\\ [RN]Check\\ FBReactNativeSpec')) {
+ const progressBar = createProgressBar(53);
+ loader.message(`${message} ${progressBar}`);
+ }
+ if (chunk.includes('[CP-User]\\ [RN]Check\\ rncore') &&
+ chunk.includes('React-FabricComponents')) {
+ const progressBar = createProgressBar(66);
+ loader.message(`${message} ${progressBar}`);
+ }
+ if (chunk.includes('[CP]\\ Check\\ Pods\\ Manifest.lock')) {
+ const progressBar = createProgressBar(90);
+ loader.message(`${message} ${progressBar}`);
+ }
+ }
+ else if (chunk.includes('BUILD SUCCEEDED')) {
+ const progressBar = createProgressBar(100);
+ loader.message(`${message} ${progressBar}`);
+ }
+}
+export const buildProject = async ({ xcodeProject, sourceDir, platformName, scheme, configuration, destinations, args, }) => {
+ if (!supportedPlatforms[platformName]) {
+ throw new RockError(`Unknown platform: ${platformName}. Please, use one of: ${Object.values(supportedPlatforms).join(', ')}.`);
+ }
+ const xcodebuildArgs = [
+ xcodeProject.isWorkspace ? '-workspace' : '-project',
+ xcodeProject.name,
+ ...(args.buildFolder ? ['-derivedDataPath', args.buildFolder] : []),
+ '-configuration',
+ configuration,
+ '-scheme',
+ scheme,
+ ...destinations.flatMap((destination) => ['-destination', destination]),
+ ];
+ if (args.archive) {
+ const { archiveDir } = getBuildPaths(platformName);
+ const archiveName = `${xcodeProject.name.replace('.xcworkspace', '')}.xcarchive`;
+ xcodebuildArgs.push('-archivePath', path.join(archiveDir, archiveName), 'archive');
+ }
+ if (args.extraParams) {
+ xcodebuildArgs.push(...args.extraParams);
+ }
+ logger.log(`Build Settings:
+Scheme ${color.bold(scheme)}
+Configuration ${color.bold(configuration)}`);
+ const loader = spinner({ indicator: 'timer' });
+ const message = `${args.archive ? 'Archiving' : 'Building'} the app`;
+ let commandOutput = '';
+ loader.start(message);
+ try {
+ const process = spawn('xcodebuild', xcodebuildArgs, {
+ cwd: sourceDir,
+ });
+ if (!logger.isVerbose()) {
+ // Process the output from the AsyncIterable
+ for await (const chunk of process) {
+ commandOutput += chunk + '\n';
+ reportProgress(chunk, loader, message);
+ }
+ }
+ await process;
+ loader.stop(`${args.archive ? 'Archived' : 'Built'} the app.`);
+ }
+ catch (error) {
+ loader.stop(`Failed: ${message}.`, 1);
+ if (!xcodeProject.isWorkspace) {
+ logger.error(`If your project uses CocoaPods, make sure to install pods with "pod install" in ${sourceDir} directory.`);
+ }
+ if (commandOutput) {
+ // Use lightweight console.error instead of logger.error to avoid stack overflow issues when Xcode logs go crazy
+ console.error(color.red(`xcodebuild output: ${commandOutput}`));
+ throw new RockError('Running xcodebuild failed. See error details above.');
+ }
+ throw new RockError('Running xcodebuild failed', {
+ cause: error.stderr || error.command,
+ });
+ }
+};
+//# sourceMappingURL=buildProject.js.map
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/build/buildProject.js.map b/packages/platform-apple-helpers/dist/src/lib/commands/build/buildProject.js.map
new file mode 100644
index 000000000..e4b9661f7
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/build/buildProject.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"buildProject.js","sourceRoot":"","sources":["../../../../../src/lib/commands/build/buildProject.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/build/createBuild.d.ts b/packages/platform-apple-helpers/dist/src/lib/commands/build/createBuild.d.ts
new file mode 100644
index 000000000..7aba01cf8
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/build/createBuild.d.ts
@@ -0,0 +1,15 @@
+import type { FingerprintSources, RemoteBuildCache } from '@rock-js/tools';
+import type { BuilderCommand, ProjectConfig } from '../../types/index.js';
+import type { BuildFlags } from './buildOptions.js';
+export declare const createBuild: ({ platformName, projectConfig, args, projectRoot, reactNativePath, fingerprintOptions, brownfield, remoteCacheProvider, }: {
+ platformName: BuilderCommand["platformName"];
+ projectConfig: ProjectConfig;
+ args: BuildFlags;
+ projectRoot: string;
+ reactNativePath: string;
+ fingerprintOptions: FingerprintSources;
+ brownfield?: boolean;
+ remoteCacheProvider: null | (() => RemoteBuildCache) | undefined;
+}) => Promise<{
+ scheme: string | undefined;
+}>;
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/build/createBuild.js b/packages/platform-apple-helpers/dist/src/lib/commands/build/createBuild.js
new file mode 100644
index 000000000..445be8614
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/build/createBuild.js
@@ -0,0 +1,106 @@
+import fs from 'node:fs';
+import path from 'node:path';
+import { colorLink, formatArtifactName, getBinaryPath, isInteractive, logger, promptSelect, relativeToCwd, RockError, saveLocalBuildCache, } from '@rock-js/tools';
+import { buildApp } from '../../utils/buildApp.js';
+import { getBuildPaths } from '../../utils/getBuildPaths.js';
+import { exportArchive } from './exportArchive.js';
+export const createBuild = async ({ platformName, projectConfig, args, projectRoot, reactNativePath, fingerprintOptions, brownfield, remoteCacheProvider, }) => {
+ await validateArgs(args);
+ let xcodeProject;
+ let sourceDir;
+ let scheme = args.scheme;
+ const deviceOrSimulator = args.destination
+ ? // there can be multiple destinations, so we'll pick the first one
+ args.destination[0].match(/simulator/i)
+ ? 'simulator'
+ : 'device'
+ : 'simulator';
+ const artifactName = await formatArtifactName({
+ platform: 'ios',
+ traits: [deviceOrSimulator, args.configuration ?? 'Debug'],
+ root: projectRoot,
+ fingerprintOptions,
+ });
+ const binaryPath = await getBinaryPath({
+ platformName,
+ artifactName,
+ localFlag: args.local,
+ remoteCacheProvider,
+ fingerprintOptions,
+ sourceDir: projectConfig.sourceDir,
+ });
+ if (binaryPath) {
+ logger.log(`Build available at: ${colorLink(relativeToCwd(binaryPath))}`);
+ if (args.archive) {
+ const { exportDir } = getBuildPaths(platformName);
+ if (fs.existsSync(exportDir) && fs.statSync(exportDir).isDirectory()) {
+ logger.log(`Archives available at: ${colorLink(relativeToCwd(exportDir))}`);
+ }
+ }
+ return { scheme };
+ }
+ try {
+ const { appPath, ...buildAppResult } = await buildApp({
+ projectRoot,
+ projectConfig,
+ platformName,
+ args,
+ reactNativePath,
+ brownfield,
+ artifactName,
+ deviceOrSimulator,
+ fingerprintOptions,
+ });
+ logger.log(`Build available at: ${colorLink(relativeToCwd(appPath))}`);
+ xcodeProject = buildAppResult.xcodeProject;
+ sourceDir = buildAppResult.sourceDir;
+ scheme = buildAppResult.scheme;
+ }
+ catch (error) {
+ const message = `Failed to create ${args.archive ? 'archive' : 'build'}`;
+ throw new RockError(message, { cause: error });
+ }
+ if (args.archive) {
+ const { archiveDir } = getBuildPaths(platformName);
+ const archivePath = path.join(archiveDir, `${xcodeProject.name.replace('.xcworkspace', '')}.xcarchive`);
+ const { ipaPath } = await exportArchive({
+ sourceDir,
+ archivePath,
+ platformName,
+ exportExtraParams: args.exportExtraParams ?? [],
+ exportOptionsPlist: args.exportOptionsPlist,
+ });
+ // Save the IPA to the local build cache so it's available for remote-cache command
+ saveLocalBuildCache(artifactName, ipaPath);
+ }
+ return { scheme };
+};
+async function validateArgs(args) {
+ if (!args.destination) {
+ if (isInteractive()) {
+ const destination = await promptSelect({
+ message: 'Select destination for a generic build',
+ options: [
+ {
+ label: 'Simulator',
+ value: 'simulator',
+ },
+ {
+ label: 'Device',
+ value: 'device',
+ },
+ ],
+ });
+ args.destination = [destination];
+ logger.info(`You can set configuration manually next time using "--destination ${destination}" flag.`);
+ }
+ else {
+ logger.error(`The "--destination" flag is required in non-interactive environments. Available flag values:
+- "simulator" โ suitable for unsigned simulator builds for developers
+- "device" โ suitable for signed device builds for testers
+- or values supported by "xcodebuild -destination" flag, e.g. "generic/platform=iOS"`);
+ process.exit(1);
+ }
+ }
+}
+//# sourceMappingURL=createBuild.js.map
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/build/createBuild.js.map b/packages/platform-apple-helpers/dist/src/lib/commands/build/createBuild.js.map
new file mode 100644
index 000000000..0dccc6b8e
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/build/createBuild.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"createBuild.js","sourceRoot":"","sources":["../../../../../src/lib/commands/build/createBuild.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/build/exportArchive.d.ts b/packages/platform-apple-helpers/dist/src/lib/commands/build/exportArchive.d.ts
new file mode 100644
index 000000000..8fa7492a1
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/build/exportArchive.d.ts
@@ -0,0 +1,9 @@
+export declare const exportArchive: ({ sourceDir, archivePath, platformName, exportExtraParams, exportOptionsPlist, }: {
+ sourceDir: string;
+ archivePath: string;
+ platformName: string;
+ exportExtraParams: string[];
+ exportOptionsPlist?: string;
+}) => Promise<{
+ ipaPath: string;
+}>;
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/build/exportArchive.js b/packages/platform-apple-helpers/dist/src/lib/commands/build/exportArchive.js
new file mode 100644
index 000000000..9547cee46
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/build/exportArchive.js
@@ -0,0 +1,46 @@
+import { colorLink, relativeToCwd, RockError, spawn, spinner, } from '@rock-js/tools';
+import { existsSync, readdirSync } from 'fs';
+import path from 'path';
+import { getBuildPaths } from '../../utils/getBuildPaths.js';
+export const exportArchive = async ({ sourceDir, archivePath, platformName, exportExtraParams, exportOptionsPlist, }) => {
+ const loader = spinner();
+ loader.start('Exporting the archive...');
+ const exportOptionsPlistPath = path.join(sourceDir, exportOptionsPlist ?? 'ExportOptions.plist');
+ if (!existsSync(exportOptionsPlistPath)) {
+ loader.stop('Failed to export the archive.', 1);
+ throw new RockError(`ExportOptions.plist not found, please create ${colorLink(relativeToCwd(exportOptionsPlistPath))} file with valid configuration for Archive export.`);
+ }
+ const { exportDir } = getBuildPaths(platformName);
+ const xcodebuildArgs = [
+ '-exportArchive',
+ '-archivePath',
+ archivePath,
+ '-exportPath',
+ exportDir,
+ '-exportOptionsPlist',
+ exportOptionsPlistPath,
+ ...exportExtraParams,
+ ];
+ try {
+ let ipaFiles = [];
+ await spawn('xcodebuild', xcodebuildArgs, {
+ cwd: sourceDir,
+ stdio: 'pipe',
+ });
+ try {
+ ipaFiles = readdirSync(exportDir).filter((file) => file.endsWith('.ipa'));
+ }
+ catch {
+ ipaFiles = [];
+ }
+ loader.stop(`Archive available at: ${colorLink(path.join(exportDir, ipaFiles[0]) ?? exportDir)}`);
+ return { ipaPath: path.join(exportDir, ipaFiles[0]) };
+ }
+ catch (error) {
+ loader.stop('Running xcodebuild failed.', 1);
+ throw new Error('Running xcodebuild failed', {
+ cause: error.stderr,
+ });
+ }
+};
+//# sourceMappingURL=exportArchive.js.map
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/build/exportArchive.js.map b/packages/platform-apple-helpers/dist/src/lib/commands/build/exportArchive.js.map
new file mode 100644
index 000000000..02856d4bb
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/build/exportArchive.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"exportArchive.js","sourceRoot":"","sources":["../../../../../src/lib/commands/build/exportArchive.ts"],"names":[],"mappings":"AACA,OAAO,EACL,SAAS,EACT,aAAa,EACb,SAAS,EACT,KAAK,EACL,OAAO,GACR,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,IAAI,CAAC;AAC7C,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAE7D,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,EAAE,EAClC,SAAS,EACT,WAAW,EACX,YAAY,EACZ,iBAAiB,EACjB,kBAAkB,GAOnB,EAAgC,EAAE;IACjC,MAAM,MAAM,GAAG,OAAO,EAAE,CAAC;IAEzB,MAAM,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;IACzC,MAAM,sBAAsB,GAAG,IAAI,CAAC,IAAI,CACtC,SAAS,EACT,kBAAkB,IAAI,qBAAqB,CAC5C,CAAC;IAEF,IAAI,CAAC,UAAU,CAAC,sBAAsB,CAAC,EAAE,CAAC;QACxC,MAAM,CAAC,IAAI,CAAC,+BAA+B,EAAE,CAAC,CAAC,CAAC;QAChD,MAAM,IAAI,SAAS,CACjB,gDAAgD,SAAS,CACvD,aAAa,CAAC,sBAAsB,CAAC,CACtC,oDAAoD,CACtD,CAAC;IACJ,CAAC;IAED,MAAM,EAAE,SAAS,EAAE,GAAG,aAAa,CAAC,YAAY,CAAC,CAAC;IAClD,MAAM,cAAc,GAAG;QACrB,gBAAgB;QAChB,cAAc;QACd,WAAW;QACX,aAAa;QACb,SAAS;QACT,qBAAqB;QACrB,sBAAsB;QACtB,GAAG,iBAAiB;KACrB,CAAC;IAEF,IAAI,CAAC;QACH,IAAI,QAAQ,GAAa,EAAE,CAAC;QAE5B,MAAM,KAAK,CAAC,YAAY,EAAE,cAAc,EAAE;YACxC,GAAG,EAAE,SAAS;YACd,KAAK,EAAE,MAAM;SACd,CAAC,CAAC;QACH,IAAI,CAAC;YACH,QAAQ,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;QAC5E,CAAC;QAAC,MAAM,CAAC;YACP,QAAQ,GAAG,EAAE,CAAC;QAChB,CAAC;QAED,MAAM,CAAC,IAAI,CACT,yBAAyB,SAAS,CAChC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,SAAS,CAC/C,EAAE,CACJ,CAAC;QACF,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACxD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,IAAI,CAAC,4BAA4B,EAAE,CAAC,CAAC,CAAC;QAC7C,MAAM,IAAI,KAAK,CAAC,2BAA2B,EAAE;YAC3C,KAAK,EAAG,KAAyB,CAAC,MAAM;SACzC,CAAC,CAAC;IACL,CAAC;AACH,CAAC,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/build/simulatorDestinationMap.d.ts b/packages/platform-apple-helpers/dist/src/lib/commands/build/simulatorDestinationMap.d.ts
new file mode 100644
index 000000000..c145cafab
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/build/simulatorDestinationMap.d.ts
@@ -0,0 +1,2 @@
+import type { ApplePlatform } from '../../types/index.js';
+export declare const simulatorDestinationMap: Record;
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/build/simulatorDestinationMap.js b/packages/platform-apple-helpers/dist/src/lib/commands/build/simulatorDestinationMap.js
new file mode 100644
index 000000000..f8e79383c
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/build/simulatorDestinationMap.js
@@ -0,0 +1,7 @@
+export const simulatorDestinationMap = {
+ ios: 'iOS Simulator',
+ macos: 'macOS',
+ visionos: 'visionOS Simulator',
+ tvos: 'tvOS Simulator',
+};
+//# sourceMappingURL=simulatorDestinationMap.js.map
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/build/simulatorDestinationMap.js.map b/packages/platform-apple-helpers/dist/src/lib/commands/build/simulatorDestinationMap.js.map
new file mode 100644
index 000000000..20c846553
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/build/simulatorDestinationMap.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"simulatorDestinationMap.js","sourceRoot":"","sources":["../../../../../src/lib/commands/build/simulatorDestinationMap.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,uBAAuB,GAAkC;IACpE,GAAG,EAAE,eAAe;IACpB,KAAK,EAAE,OAAO;IACd,QAAQ,EAAE,oBAAoB;IAC9B,IAAI,EAAE,gBAAgB;CACvB,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/createRun.d.ts b/packages/platform-apple-helpers/dist/src/lib/commands/run/createRun.d.ts
new file mode 100644
index 000000000..f3e8e4e11
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/createRun.d.ts
@@ -0,0 +1,18 @@
+import type { StartDevServerArgs } from '@rock-js/config';
+import type { FingerprintSources, RemoteBuildCache } from '@rock-js/tools';
+import type { ApplePlatform, ProjectConfig } from '../../types/index.js';
+import type { RunFlags } from './runOptions.js';
+export declare const createRun: ({ platformName, projectConfig, args, projectRoot, remoteCacheProvider, fingerprintOptions, reactNativePath, reactNativeVersion, platforms, startDevServer, }: {
+ platformName: ApplePlatform;
+ projectConfig: ProjectConfig;
+ args: RunFlags;
+ projectRoot: string;
+ remoteCacheProvider: null | (() => RemoteBuildCache) | undefined;
+ fingerprintOptions: FingerprintSources;
+ reactNativePath: string;
+ reactNativeVersion: string;
+ platforms: {
+ [platform: string]: object;
+ };
+ startDevServer: (options: StartDevServerArgs) => void;
+}) => Promise;
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/createRun.js b/packages/platform-apple-helpers/dist/src/lib/commands/run/createRun.js
new file mode 100644
index 000000000..a815d0641
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/createRun.js
@@ -0,0 +1,232 @@
+import fs from 'node:fs';
+import path from 'node:path';
+import { color, formatArtifactName, getBinaryPath, isInteractive, logger, promptSelect, RockError, } from '@rock-js/tools';
+import { buildApp } from '../../utils/buildApp.js';
+import { getPlatformInfo } from '../../utils/getPlatformInfo.js';
+import { listDevicesAndSimulators } from '../../utils/listDevices.js';
+import { matchingDevice } from './matchingDevice.js';
+import { cacheRecentDevice, sortByRecentDevices } from './recentDevices.js';
+import { runOnDevice } from './runOnDevice.js';
+import { runOnMac } from './runOnMac.js';
+import { runOnMacCatalyst } from './runOnMacCatalyst.js';
+import { launchSimulator, runOnSimulator } from './runOnSimulator.js';
+export const createRun = async ({ platformName, projectConfig, args, projectRoot, remoteCacheProvider, fingerprintOptions, reactNativePath, reactNativeVersion, platforms, startDevServer, }) => {
+ const startDevServerHelper = () => {
+ if (args.devServer) {
+ logger.info('Starting dev server...');
+ startDevServer({
+ root: projectRoot,
+ reactNativePath,
+ reactNativeVersion,
+ platforms,
+ args: {
+ interactive: isInteractive(),
+ clientLogs: args.clientLogs ?? true,
+ },
+ });
+ }
+ };
+ validateArgs(args, projectRoot);
+ const deviceOrSimulator = args.destination
+ ? // there can be multiple destinations, so we'll pick the first one
+ args.destination[0].match(/simulator/i)
+ ? 'simulator'
+ : 'device'
+ : 'simulator';
+ const artifactName = await formatArtifactName({
+ platform: 'ios',
+ traits: [deviceOrSimulator, args.configuration ?? 'Debug'],
+ root: projectRoot,
+ fingerprintOptions,
+ });
+ const binaryPath = await getBinaryPath({
+ platformName: 'ios',
+ artifactName,
+ binaryPathFlag: args.binaryPath,
+ localFlag: args.local,
+ remoteCacheProvider,
+ fingerprintOptions,
+ sourceDir: projectConfig.sourceDir,
+ });
+ // Check if the device argument looks like a UDID
+ // (assuming UDIDs are alphanumeric and have specific length)
+ const udid = args.device && /^[A-Fa-f0-9-]{25,}$/.test(args.device)
+ ? args.device
+ : undefined;
+ const deviceName = udid ? undefined : args.device;
+ if (platformName === 'macos') {
+ const { appPath } = await buildApp({
+ args,
+ projectConfig,
+ platformName,
+ projectRoot,
+ udid,
+ deviceName,
+ reactNativePath,
+ binaryPath,
+ artifactName,
+ deviceOrSimulator,
+ fingerprintOptions,
+ });
+ await runOnMac(appPath);
+ startDevServerHelper();
+ return;
+ }
+ else if (args.catalyst) {
+ const { appPath, scheme } = await buildApp({
+ args,
+ projectConfig,
+ platformName,
+ projectRoot,
+ udid,
+ deviceName,
+ reactNativePath,
+ binaryPath,
+ artifactName,
+ deviceOrSimulator,
+ fingerprintOptions,
+ });
+ if (scheme) {
+ await runOnMacCatalyst(appPath, scheme);
+ startDevServerHelper();
+ return;
+ }
+ else {
+ throw new RockError('Failed to get project scheme');
+ }
+ }
+ const devices = await listDevicesAndSimulators(platformName);
+ if (devices.length === 0) {
+ const { readableName } = getPlatformInfo(platformName);
+ throw new RockError(`No devices or simulators detected. Install simulators via Xcode or connect a physical ${readableName} device.`);
+ }
+ const device = await selectDevice(devices, args);
+ if (device) {
+ if (device.type !== deviceOrSimulator) {
+ throw new RockError(`Selected device "${device.name}" is not a ${deviceOrSimulator}.
+Please either use "--destination ${deviceOrSimulator === 'simulator' ? 'device' : 'simulator'}" flag or select available ${deviceOrSimulator}:
+${devices
+ .filter(({ type }) => type === deviceOrSimulator)
+ .map(({ name }) => `โข ${name}`)
+ .join('\n')}`);
+ }
+ cacheRecentDevice(device, platformName);
+ if (device.type === 'simulator') {
+ const [, { appPath, infoPlistPath }] = await Promise.all([
+ launchSimulator(device),
+ buildApp({
+ args,
+ projectConfig,
+ platformName,
+ udid: device.udid,
+ projectRoot,
+ reactNativePath,
+ binaryPath,
+ artifactName,
+ deviceOrSimulator,
+ fingerprintOptions,
+ }),
+ ]);
+ await runOnSimulator(device, appPath, infoPlistPath);
+ startDevServerHelper();
+ }
+ else if (device.type === 'device') {
+ const { appPath, bundleIdentifier } = await buildApp({
+ args,
+ projectConfig,
+ platformName,
+ udid: device.udid,
+ projectRoot,
+ reactNativePath,
+ binaryPath,
+ artifactName,
+ deviceOrSimulator,
+ fingerprintOptions,
+ });
+ await runOnDevice(device, appPath, projectConfig.sourceDir, bundleIdentifier);
+ startDevServerHelper();
+ }
+ return;
+ }
+ else {
+ const bootedDevices = devices.filter(({ state, type }) => state === 'Booted' && type === deviceOrSimulator);
+ if (bootedDevices.length === 0) {
+ // fallback to present all devices when no device is selected
+ if (isInteractive()) {
+ const simulator = await promptForDeviceSelection(devices.filter(({ type }) => type === deviceOrSimulator), platformName);
+ bootedDevices.push(simulator);
+ cacheRecentDevice(simulator, platformName);
+ }
+ else {
+ logger.debug('No booted devices or simulators found. Launching first available simulator...');
+ const simulator = devices.filter((device) => device.type === 'simulator')[0];
+ if (simulator) {
+ bootedDevices.push(simulator);
+ }
+ else {
+ throw new RockError('No Apple simulators found. Install simulators via Xcode.');
+ }
+ }
+ }
+ for (const bootedDevice of bootedDevices) {
+ const [, { appPath, infoPlistPath, bundleIdentifier }] = await Promise.all([
+ launchSimulator(bootedDevice),
+ buildApp({
+ args,
+ projectConfig,
+ platformName,
+ udid: bootedDevice.udid,
+ projectRoot,
+ reactNativePath,
+ binaryPath,
+ artifactName,
+ deviceOrSimulator,
+ fingerprintOptions,
+ }),
+ ]);
+ if (bootedDevice.type === 'simulator') {
+ await runOnSimulator(bootedDevice, appPath, infoPlistPath);
+ }
+ else {
+ await runOnDevice(bootedDevice, appPath, projectConfig.sourceDir, bundleIdentifier);
+ }
+ }
+ startDevServerHelper();
+ }
+};
+async function selectDevice(devices, args) {
+ let device;
+ if (args.device) {
+ device = matchingDevice(devices, args.device);
+ }
+ if (!device && args.device) {
+ logger.warn(`No devices or simulators found matching "${args.device}". Falling back to default simulator.`);
+ }
+ return device;
+}
+function validateArgs(args, projectRoot) {
+ if (args.binaryPath) {
+ args.binaryPath = path.isAbsolute(args.binaryPath)
+ ? args.binaryPath
+ : path.join(projectRoot, args.binaryPath);
+ if (!fs.existsSync(args.binaryPath)) {
+ throw new Error(`"--binary-path" was specified, but the file was not found at "${args.binaryPath}".`);
+ }
+ // No need to install pods if binary path is provided
+ args.installPods = false;
+ }
+}
+function promptForDeviceSelection(devices, platformName) {
+ const sortedDevices = sortByRecentDevices(devices, platformName);
+ return promptSelect({
+ message: 'Select the device / simulator you want to use',
+ options: sortedDevices.map((d) => {
+ const markDevice = d.type === 'device' ? ` - (physical device)` : '';
+ return {
+ label: `${d.name} ${color.dim(`(${d.version})${markDevice}`)}`,
+ value: d,
+ };
+ }),
+ });
+}
+//# sourceMappingURL=createRun.js.map
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/createRun.js.map b/packages/platform-apple-helpers/dist/src/lib/commands/run/createRun.js.map
new file mode 100644
index 000000000..25d7d0c5e
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/createRun.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"createRun.js","sourceRoot":"","sources":["../../../../../src/lib/commands/run/createRun.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/getBuildSettings.d.ts b/packages/platform-apple-helpers/dist/src/lib/commands/run/getBuildSettings.d.ts
new file mode 100644
index 000000000..61cad5a8b
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/getBuildSettings.d.ts
@@ -0,0 +1,15 @@
+import type { ApplePlatform, XcodeProjectInfo } from '../../types/index.js';
+export declare function getBuildSettings({ xcodeProject, sourceDir, platformName, configuration, destinations, scheme, target, buildFolder, }: {
+ xcodeProject: XcodeProjectInfo;
+ sourceDir: string;
+ platformName: ApplePlatform;
+ configuration: string;
+ destinations: string[];
+ scheme: string;
+ target?: string;
+ buildFolder?: string;
+}): Promise<{
+ appPath: string;
+ infoPlistPath: string;
+ bundleIdentifier: string;
+}>;
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/getBuildSettings.js b/packages/platform-apple-helpers/dist/src/lib/commands/run/getBuildSettings.js
new file mode 100644
index 000000000..464538708
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/getBuildSettings.js
@@ -0,0 +1,98 @@
+import path from 'node:path';
+import { color, logger, RockError, spawn } from '@rock-js/tools';
+export async function getBuildSettings({ xcodeProject, sourceDir, platformName, configuration, destinations, scheme, target, buildFolder, }) {
+ const destination = destinations[0];
+ const sdk = destination.match(/simulator/i)
+ ? getSimulatorPlatformSDK(platformName)
+ : getDevicePlatformSDK(platformName);
+ const { stdout: buildSettingsOutput } = await spawn('xcodebuild', [
+ xcodeProject.isWorkspace ? '-workspace' : '-project',
+ xcodeProject.name,
+ ...(buildFolder ? ['-derivedDataPath', buildFolder] : []),
+ '-scheme',
+ scheme,
+ '-configuration',
+ configuration,
+ '-sdk',
+ sdk,
+ // -showBuildSettings supports exactly one -destination argument
+ '-destination',
+ destination,
+ '-showBuildSettings',
+ '-json',
+ ], { cwd: sourceDir, stdio: 'pipe' });
+ const settings = JSON.parse(buildSettingsOutput).filter(({ buildSettings: { WRAPPER_EXTENSION }, }) => WRAPPER_EXTENSION === 'app' || WRAPPER_EXTENSION === 'framework');
+ const targets = settings.map(({ target: settingsTarget }) => settingsTarget);
+ if (settings.length === 0) {
+ throw new RockError(`Failed to get build settings for your project. Looking for "app" or "framework" wrapper extensions but found none.`);
+ }
+ let selectedTarget = targets[0];
+ if (target) {
+ if (!targets.includes(target)) {
+ logger.info(`Target ${color.bold(target)} not found for scheme ${color.bold(scheme)}, automatically selected target ${color.bold(selectedTarget)}`);
+ }
+ else {
+ selectedTarget = target;
+ }
+ }
+ logger.debug(`Selected target: ${selectedTarget}`);
+ // Find app in all building settings - look for WRAPPER_EXTENSION: 'app',
+ const targetIndex = targets.indexOf(selectedTarget);
+ const buildSettings = settings[targetIndex].buildSettings;
+ if (!buildSettings) {
+ throw new RockError('Failed to get build settings for your project');
+ }
+ const appPath = getBuildPath(buildSettings, platformName);
+ const infoPlistPath = buildSettings.INFOPLIST_PATH;
+ const targetBuildDir = buildSettings.TARGET_BUILD_DIR;
+ return {
+ appPath,
+ infoPlistPath: path.join(targetBuildDir, infoPlistPath),
+ bundleIdentifier: buildSettings.PRODUCT_BUNDLE_IDENTIFIER,
+ };
+}
+function getBuildPath(buildSettings, platformName) {
+ const targetBuildDir = buildSettings.TARGET_BUILD_DIR;
+ const executableFolderPath = buildSettings.EXECUTABLE_FOLDER_PATH;
+ const fullProductName = buildSettings.FULL_PRODUCT_NAME;
+ if (!targetBuildDir) {
+ throw new Error('Failed to get the target build directory.');
+ }
+ if (!executableFolderPath) {
+ throw new Error('Failed to get the app name.');
+ }
+ if (!fullProductName) {
+ throw new Error('Failed to get product name.');
+ }
+ if (platformName === 'macos') {
+ return path.join(targetBuildDir, fullProductName);
+ }
+ else {
+ return path.join(targetBuildDir, executableFolderPath);
+ }
+}
+function getSimulatorPlatformSDK(platform) {
+ switch (platform) {
+ case 'ios':
+ return 'iphonesimulator';
+ case 'macos':
+ return 'macosx';
+ case 'tvos':
+ return 'appletvsimulator';
+ case 'visionos':
+ return 'xrsimulator';
+ }
+}
+function getDevicePlatformSDK(platform) {
+ switch (platform) {
+ case 'ios':
+ return 'iphoneos';
+ case 'macos':
+ return 'macosx';
+ case 'tvos':
+ return 'appletvos';
+ case 'visionos':
+ return 'xr';
+ }
+}
+//# sourceMappingURL=getBuildSettings.js.map
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/getBuildSettings.js.map b/packages/platform-apple-helpers/dist/src/lib/commands/run/getBuildSettings.js.map
new file mode 100644
index 000000000..8f58926a4
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/getBuildSettings.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"getBuildSettings.js","sourceRoot":"","sources":["../../../../../src/lib/commands/run/getBuildSettings.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/matchingDevice.d.ts b/packages/platform-apple-helpers/dist/src/lib/commands/run/matchingDevice.d.ts
new file mode 100644
index 000000000..8724b0581
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/matchingDevice.d.ts
@@ -0,0 +1,3 @@
+import type { Device } from '../../types/index.js';
+export declare function matchingDevice(devices: Array, deviceArg: string): Device | undefined;
+export declare function formattedDeviceName(simulator: Device): string;
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/matchingDevice.js b/packages/platform-apple-helpers/dist/src/lib/commands/run/matchingDevice.js
new file mode 100644
index 000000000..a7e4e9aa5
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/matchingDevice.js
@@ -0,0 +1,11 @@
+export function matchingDevice(devices, deviceArg) {
+ const deviceByName = devices.find((device) => device.name === deviceArg || formattedDeviceName(device) === deviceArg);
+ const deviceByUdid = devices.find((d) => d.udid === deviceArg);
+ return deviceByName || deviceByUdid;
+}
+export function formattedDeviceName(simulator) {
+ return simulator.version
+ ? `${simulator.name} (${simulator.version})`
+ : simulator.name;
+}
+//# sourceMappingURL=matchingDevice.js.map
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/matchingDevice.js.map b/packages/platform-apple-helpers/dist/src/lib/commands/run/matchingDevice.js.map
new file mode 100644
index 000000000..d7ad48b97
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/matchingDevice.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"matchingDevice.js","sourceRoot":"","sources":["../../../../../src/lib/commands/run/matchingDevice.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,cAAc,CAAC,OAAsB,EAAE,SAAiB;IACtE,MAAM,YAAY,GAAG,OAAO,CAAC,IAAI,CAC/B,CAAC,MAAM,EAAE,EAAE,CACT,MAAM,CAAC,IAAI,KAAK,SAAS,IAAI,mBAAmB,CAAC,MAAM,CAAC,KAAK,SAAS,CACzE,CAAC;IACF,MAAM,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC;IAC/D,OAAO,YAAY,IAAI,YAAY,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,SAAiB;IACnD,OAAO,SAAS,CAAC,OAAO;QACtB,CAAC,CAAC,GAAG,SAAS,CAAC,IAAI,KAAK,SAAS,CAAC,OAAO,GAAG;QAC5C,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC;AACrB,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/recentDevices.d.ts b/packages/platform-apple-helpers/dist/src/lib/commands/run/recentDevices.d.ts
new file mode 100644
index 000000000..080c7a205
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/recentDevices.d.ts
@@ -0,0 +1,3 @@
+import type { ApplePlatform, Device } from '../../types/index.js';
+export declare function cacheRecentDevice(device: Device, platform: ApplePlatform): void;
+export declare function sortByRecentDevices(devices: Device[], platform: ApplePlatform): Device[];
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/recentDevices.js b/packages/platform-apple-helpers/dist/src/lib/commands/run/recentDevices.js
new file mode 100644
index 000000000..1028fd909
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/recentDevices.js
@@ -0,0 +1,32 @@
+import { cacheManager, logger } from '@rock-js/tools';
+export function cacheRecentDevice(device, platform) {
+ const cacheKey = 'recentDevicesUDID-' + platform;
+ try {
+ const recentDevices = getRecentDevices(platform);
+ const newRecentDevices = [device.udid, ...recentDevices];
+ const uniqueDevices = Array.from(new Set(newRecentDevices)).slice(0, 5);
+ cacheManager.set(cacheKey, JSON.stringify(uniqueDevices));
+ }
+ catch (error) {
+ logger.debug(`Failed to cache recent device ${device.name} with UDID ${device.udid}. ${error}`);
+ }
+}
+function getRecentDevices(platform) {
+ const cacheKey = 'recentDevicesUDID-' + platform;
+ const recentDevicesString = cacheManager.get(cacheKey);
+ try {
+ return recentDevicesString ? JSON.parse(recentDevicesString) : [];
+ }
+ catch (error) {
+ logger.debug(`Failed to read recent devices from cache. ${error}`);
+ return [];
+ }
+}
+export function sortByRecentDevices(devices, platform) {
+ const recentDevices = getRecentDevices(platform);
+ const udids = Array.from(new Set([...recentDevices, ...devices.map(({ udid }) => udid)]));
+ return udids
+ .map((udid) => devices.find((device) => device.udid === udid))
+ .filter(Boolean);
+}
+//# sourceMappingURL=recentDevices.js.map
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/recentDevices.js.map b/packages/platform-apple-helpers/dist/src/lib/commands/run/recentDevices.js.map
new file mode 100644
index 000000000..266d0b642
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/recentDevices.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"recentDevices.js","sourceRoot":"","sources":["../../../../../src/lib/commands/run/recentDevices.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAGtD,MAAM,UAAU,iBAAiB,CAAC,MAAc,EAAE,QAAuB;IACvE,MAAM,QAAQ,GAAG,oBAAoB,GAAG,QAAQ,CAAC;IACjD,IAAI,CAAC;QACH,MAAM,aAAa,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QACjD,MAAM,gBAAgB,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,aAAa,CAAC,CAAC;QACzD,MAAM,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACxE,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC;IAC5D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CACV,iCAAiC,MAAM,CAAC,IAAI,cAAc,MAAM,CAAC,IAAI,KAAK,KAAK,EAAE,CAClF,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,gBAAgB,CAAC,QAAuB;IAC/C,MAAM,QAAQ,GAAG,oBAAoB,GAAG,QAAQ,CAAC;IACjD,MAAM,mBAAmB,GAAG,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACvD,IAAI,CAAC;QACH,OAAO,mBAAmB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACpE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,6CAA6C,KAAK,EAAE,CAAC,CAAC;QACnE,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,OAAiB,EACjB,QAAuB;IAEvB,MAAM,aAAa,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IACjD,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CACtB,IAAI,GAAG,CAAC,CAAC,GAAG,aAAa,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAChE,CAAC;IACF,OAAO,KAAK;SACT,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;SAC7D,MAAM,CAAC,OAAO,CAAa,CAAC;AACjC,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnDevice.d.ts b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnDevice.d.ts
new file mode 100644
index 000000000..5bc1e05ea
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnDevice.d.ts
@@ -0,0 +1,2 @@
+import type { Device } from '../../types/index.js';
+export declare function runOnDevice(selectedDevice: Device, binaryPath: string, sourceDir: string, bundleIdentifier: string): Promise;
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnDevice.js b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnDevice.js
new file mode 100644
index 000000000..df7897515
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnDevice.js
@@ -0,0 +1,32 @@
+import { color, RockError, spawn, spinner } from '@rock-js/tools';
+export async function runOnDevice(selectedDevice, binaryPath, sourceDir, bundleIdentifier) {
+ const loader = spinner();
+ loader.start(`Installing and launching your app on ${color.bold(selectedDevice.name)}`);
+ try {
+ await spawn('xcrun', [
+ 'devicectl',
+ 'device',
+ 'install',
+ 'app',
+ '--device',
+ selectedDevice.udid,
+ binaryPath,
+ ], { cwd: sourceDir });
+ await spawn('xcrun', [
+ 'devicectl',
+ 'device',
+ 'process',
+ 'launch',
+ '--device',
+ selectedDevice.udid,
+ bundleIdentifier,
+ ], { cwd: sourceDir });
+ }
+ catch (error) {
+ loader.stop(`Failed: Installing and launching your app on ${color.bold(selectedDevice.name)}`);
+ throw new RockError(error.stderr);
+ }
+ loader.stop(`Installed the app on ${color.bold(selectedDevice.name)}.`);
+ return;
+}
+//# sourceMappingURL=runOnDevice.js.map
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnDevice.js.map b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnDevice.js.map
new file mode 100644
index 000000000..1af9f970f
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnDevice.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"runOnDevice.js","sourceRoot":"","sources":["../../../../../src/lib/commands/run/runOnDevice.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAGlE,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,cAAsB,EACtB,UAAkB,EAClB,SAAiB,EACjB,gBAAwB;IAExB,MAAM,MAAM,GAAG,OAAO,EAAE,CAAC;IACzB,MAAM,CAAC,KAAK,CACV,wCAAwC,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,CAC1E,CAAC;IACF,IAAI,CAAC;QACH,MAAM,KAAK,CACT,OAAO,EACP;YACE,WAAW;YACX,QAAQ;YACR,SAAS;YACT,KAAK;YACL,UAAU;YACV,cAAc,CAAC,IAAI;YACnB,UAAU;SACX,EACD,EAAE,GAAG,EAAE,SAAS,EAAE,CACnB,CAAC;QACF,MAAM,KAAK,CACT,OAAO,EACP;YACE,WAAW;YACX,QAAQ;YACR,SAAS;YACT,QAAQ;YACR,UAAU;YACV,cAAc,CAAC,IAAI;YACnB,gBAAgB;SACjB,EACD,EAAE,GAAG,EAAE,SAAS,EAAE,CACnB,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,IAAI,CACT,gDAAgD,KAAK,CAAC,IAAI,CACxD,cAAc,CAAC,IAAI,CACpB,EAAE,CACJ,CAAC;QACF,MAAM,IAAI,SAAS,CAAE,KAAyB,CAAC,MAAM,CAAC,CAAC;IACzD,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,wBAAwB,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACxE,OAAO;AACT,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnMac.d.ts b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnMac.d.ts
new file mode 100644
index 000000000..c10f449e6
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnMac.d.ts
@@ -0,0 +1 @@
+export declare function runOnMac(binaryPath: string): Promise;
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnMac.js b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnMac.js
new file mode 100644
index 000000000..1f1b26e35
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnMac.js
@@ -0,0 +1,13 @@
+import { color, logger, RockError, spawn } from '@rock-js/tools';
+export async function runOnMac(binaryPath) {
+ logger.debug(`Opening "${color.bold(binaryPath)}"`);
+ try {
+ await spawn('open', [binaryPath]);
+ }
+ catch (error) {
+ throw new RockError('Failed to launch the app', {
+ cause: error.stderr,
+ });
+ }
+}
+//# sourceMappingURL=runOnMac.js.map
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnMac.js.map b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnMac.js.map
new file mode 100644
index 000000000..c1f499e6a
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnMac.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"runOnMac.js","sourceRoot":"","sources":["../../../../../src/lib/commands/run/runOnMac.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAEjE,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,UAAkB;IAC/C,MAAM,CAAC,KAAK,CAAC,YAAY,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;IAEpD,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,MAAM,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;IACpC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CAAC,0BAA0B,EAAE;YAC9C,KAAK,EAAG,KAAyB,CAAC,MAAM;SACzC,CAAC,CAAC;IACL,CAAC;AACH,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnMacCatalyst.d.ts b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnMacCatalyst.d.ts
new file mode 100644
index 000000000..482491548
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnMacCatalyst.d.ts
@@ -0,0 +1 @@
+export declare function runOnMacCatalyst(binaryPath: string, scheme: string): Promise;
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnMacCatalyst.js b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnMacCatalyst.js
new file mode 100644
index 000000000..343104e9a
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnMacCatalyst.js
@@ -0,0 +1,9 @@
+import { spawn } from '@rock-js/tools';
+export async function runOnMacCatalyst(binaryPath, scheme) {
+ const appProcess = spawn(`${binaryPath}/${scheme}`, [], {
+ detached: true,
+ stdio: 'ignore',
+ });
+ (await appProcess.nodeChildProcess).unref();
+}
+//# sourceMappingURL=runOnMacCatalyst.js.map
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnMacCatalyst.js.map b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnMacCatalyst.js.map
new file mode 100644
index 000000000..8cd6646a0
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnMacCatalyst.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"runOnMacCatalyst.js","sourceRoot":"","sources":["../../../../../src/lib/commands/run/runOnMacCatalyst.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAEvC,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,UAAkB,EAAE,MAAc;IACvE,MAAM,UAAU,GAAG,KAAK,CAAC,GAAG,UAAU,IAAI,MAAM,EAAE,EAAE,EAAE,EAAE;QACtD,QAAQ,EAAE,IAAI;QACd,KAAK,EAAE,QAAQ;KAChB,CAAC,CAAC;IACH,CAAC,MAAM,UAAU,CAAC,gBAAgB,CAAC,CAAC,KAAK,EAAE,CAAC;AAC9C,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnSimulator.d.ts b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnSimulator.d.ts
new file mode 100644
index 000000000..f964fbfef
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnSimulator.d.ts
@@ -0,0 +1,5 @@
+import type { Device } from '../../types/index.js';
+export declare function launchSimulator(device: Device): Promise;
+export declare function runOnSimulator(device: Device, binaryPath: string, infoPlistPath: string): Promise;
+export default function installAppOnSimulator(udid: string, binaryPath: string): Promise;
+export declare function launchAppOnSimulator(udid: string, binaryPath: string, infoPlistPath: string): Promise;
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnSimulator.js b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnSimulator.js
new file mode 100644
index 000000000..4d0bb353d
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnSimulator.js
@@ -0,0 +1,85 @@
+import path from 'node:path';
+import { color, logger, RockError, spawn, spinner } from '@rock-js/tools';
+import { readKeyFromPlist } from '../../utils/plist.js';
+export async function launchSimulator(device) {
+ if (device.type !== 'simulator') {
+ // bail if device is not a simulator
+ return undefined;
+ }
+ /**
+ * Booting simulator through `xcrun simctl boot` will boot it in the `headless` mode
+ * (running in the background).
+ *
+ * In order for user to see the app and the simulator itself, we have to make sure
+ * that the Simulator.app is running.
+ *
+ * We also pass it `-CurrentDeviceUDID` so that when we launch it for the first time,
+ * it will not boot the "default" device, but the one we set. If the app is already running,
+ * this flag has no effect.
+ */
+ const { output: activeDeveloperDir } = await spawn('xcode-select', ['-p'], {
+ stdio: 'pipe',
+ });
+ await spawn('open', [
+ `${activeDeveloperDir}/Applications/Simulator.app`,
+ '--args',
+ '-CurrentDeviceUDID',
+ device.udid,
+ ]);
+ if (device.state !== 'Booted') {
+ await bootSimulator(device);
+ }
+}
+export async function runOnSimulator(device, binaryPath, infoPlistPath) {
+ const loader = spinner();
+ loader.start(`Installing the app on ${color.bold(device.name)}`);
+ await installAppOnSimulator(device.udid, binaryPath);
+ loader.message(`Launching the app on ${color.bold(device.name)}`);
+ await launchAppOnSimulator(device.udid, binaryPath, infoPlistPath);
+ loader.stop(`Installed and launched the app on ${color.bold(device.name)}.`);
+}
+async function bootSimulator(selectedSimulator) {
+ try {
+ await spawn('xcrun', ['simctl', 'boot', selectedSimulator.udid]);
+ }
+ catch (error) {
+ if (
+ // It may happen on GitHub Actions when the simulator is already booted,
+ // even though the simctl returns its state as Shutdown
+ error.stderr.includes('Unable to boot device in current state: Booted')) {
+ logger.debug(`Simulator ${selectedSimulator.udid} already booted. Skipping.`);
+ return;
+ }
+ throw new RockError('Failed to boot Simulator', {
+ cause: error.stderr,
+ });
+ }
+}
+export default async function installAppOnSimulator(udid, binaryPath) {
+ logger.debug(`Installing "${path.basename(binaryPath)}"`);
+ try {
+ await spawn('xcrun', ['simctl', 'install', udid, binaryPath]);
+ }
+ catch (error) {
+ throw new RockError('Failed to install the app on Simulator', {
+ cause: error.stderr,
+ });
+ }
+}
+export async function launchAppOnSimulator(udid, binaryPath, infoPlistPath) {
+ const infoPlist = binaryPath
+ ? // @todo Info.plist is hardcoded when reading from binaryPath
+ path.join(binaryPath, 'Info.plist')
+ : infoPlistPath;
+ const bundleID = await readKeyFromPlist(infoPlist, 'CFBundleIdentifier');
+ logger.debug(`Launching "${bundleID}"`);
+ try {
+ await spawn('xcrun', ['simctl', 'launch', udid, bundleID]);
+ }
+ catch (error) {
+ throw new RockError(`Failed to launch the app on Simulator`, {
+ cause: error.stderr,
+ });
+ }
+}
+//# sourceMappingURL=runOnSimulator.js.map
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnSimulator.js.map b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnSimulator.js.map
new file mode 100644
index 000000000..811d47450
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOnSimulator.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"runOnSimulator.js","sourceRoot":"","sources":["../../../../../src/lib/commands/run/runOnSimulator.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/runOptions.d.ts b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOptions.d.ts
new file mode 100644
index 000000000..db61c0646
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOptions.d.ts
@@ -0,0 +1,30 @@
+import type { BuilderCommand } from '../../types/index.js';
+import type { BuildFlags } from '../build/buildOptions.js';
+export interface RunFlags extends BuildFlags {
+ binaryPath?: string;
+ port: string;
+ device?: string;
+ catalyst?: boolean;
+ local?: boolean;
+ devServer?: boolean;
+ clientLogs?: boolean;
+}
+export declare const getRunOptions: ({ platformName }: BuilderCommand) => ({
+ name: string;
+ description: string;
+ parse?: undefined;
+ value?: undefined;
+} | {
+ name: string;
+ description: string;
+ parse: typeof import("packages/tools/dist/src/index.js").parseArgs;
+ value?: undefined;
+} | {
+ name: string;
+ description: string;
+ value: string;
+ parse?: undefined;
+} | {
+ name: string;
+ default: string;
+})[];
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/runOptions.js b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOptions.js
new file mode 100644
index 000000000..dd9c9cc32
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOptions.js
@@ -0,0 +1,31 @@
+import { getBuildOptions } from '../build/buildOptions.js';
+export const getRunOptions = ({ platformName }) => {
+ return [
+ {
+ name: '--port ',
+ default: process.env['RCT_METRO_PORT'] || '8081',
+ },
+ {
+ name: '--binary-path ',
+ description: 'Path relative to project root where pre-built .app binary lives.',
+ },
+ {
+ name: '--device ',
+ description: 'Explicitly set the device or simulator to use by name or by UDID.',
+ },
+ {
+ name: '--catalyst',
+ description: 'Run on Mac Catalyst.',
+ },
+ {
+ name: '--client-logs',
+ description: 'Enable client logs in dev server.',
+ },
+ {
+ name: '--dev-server',
+ description: 'Automatically start a dev server (bundler) after building the app.',
+ },
+ ...getBuildOptions({ platformName }),
+ ];
+};
+//# sourceMappingURL=runOptions.js.map
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/run/runOptions.js.map b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOptions.js.map
new file mode 100644
index 000000000..640506fcf
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/run/runOptions.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"runOptions.js","sourceRoot":"","sources":["../../../../../src/lib/commands/run/runOptions.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAY3D,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,EAAE,YAAY,EAAkB,EAAE,EAAE;IAChE,OAAO;QACL;YACE,IAAI,EAAE,iBAAiB;YACvB,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,MAAM;SACjD;QACD;YACE,IAAI,EAAE,wBAAwB;YAC9B,WAAW,EACT,kEAAkE;SACrE;QACD;YACE,IAAI,EAAE,mBAAmB;YACzB,WAAW,EACT,mEAAmE;SACtE;QACD;YACE,IAAI,EAAE,YAAY;YAClB,WAAW,EAAE,sBAAsB;SACpC;QACD;YACE,IAAI,EAAE,eAAe;YACrB,WAAW,EAAE,mCAAmC;SACjD;QACD;YACE,IAAI,EAAE,cAAc;YACpB,WAAW,EAAE,oEAAoE;SAClF;QACD,GAAG,eAAe,CAAC,EAAE,YAAY,EAAE,CAAC;KACrC,CAAC;AACJ,CAAC,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/sign/bundle.d.ts b/packages/platform-apple-helpers/dist/src/lib/commands/sign/bundle.d.ts
new file mode 100644
index 000000000..de6f3f978
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/sign/bundle.d.ts
@@ -0,0 +1,11 @@
+type BuildJsBundleOptions = {
+ bundleOutputPath: string;
+ assetsDestPath: string;
+ useHermes?: boolean;
+ sourcemapOutputPath?: string;
+};
+/**
+ * This function is modelled after [react-native-xcode.sh](https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react-native-xcode.sh).
+ */
+export declare function buildJsBundle(options: BuildJsBundleOptions): Promise;
+export {};
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/sign/bundle.js b/packages/platform-apple-helpers/dist/src/lib/commands/sign/bundle.js
new file mode 100644
index 000000000..1ef33abc2
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/sign/bundle.js
@@ -0,0 +1,49 @@
+import fs from 'node:fs';
+import { logger, RockError, runHermes, spawn } from '@rock-js/tools';
+/**
+ * This function is modelled after [react-native-xcode.sh](https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react-native-xcode.sh).
+ */
+export async function buildJsBundle(options) {
+ if (fs.existsSync(options.bundleOutputPath)) {
+ fs.unlinkSync(options.bundleOutputPath);
+ logger.debug('Removed existing JS bundle:', options.bundleOutputPath);
+ }
+ // Reasonable defaults
+ // If user wants to build bundle differently, they should use `rock bundle` command directly
+ // and provide the JS bundle path to `--jsbundle` flag
+ const rockBundleArgs = [
+ 'bundle',
+ `--entry-file`,
+ `index.js`,
+ '--platform',
+ 'ios',
+ `--dev`,
+ 'false',
+ '--minify',
+ 'false',
+ '--reset-cache',
+ '--bundle-output',
+ options.bundleOutputPath,
+ '--assets-dest',
+ options.assetsDestPath,
+ ...(options.sourcemapOutputPath
+ ? ['--sourcemap-output', options.sourcemapOutputPath]
+ : []),
+ ];
+ try {
+ await spawn('rock', rockBundleArgs, { preferLocal: true });
+ }
+ catch (error) {
+ throw new RockError('Failed to build JS bundle', {
+ cause: error.stderr,
+ });
+ }
+ if (!options.useHermes) {
+ return;
+ }
+ await runHermes({
+ bundleOutputPath: options.bundleOutputPath,
+ sourcemapOutputPath: options.sourcemapOutputPath,
+ });
+}
+//# sourceMappingURL=bundle.js.map
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/sign/bundle.js.map b/packages/platform-apple-helpers/dist/src/lib/commands/sign/bundle.js.map
new file mode 100644
index 000000000..8a2a4c54b
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/sign/bundle.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"bundle.js","sourceRoot":"","sources":["../../../../../src/lib/commands/sign/bundle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AASrE;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,OAA6B;IAC/D,IAAI,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE,CAAC;QAC5C,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;QACxC,MAAM,CAAC,KAAK,CAAC,6BAA6B,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACxE,CAAC;IAED,sBAAsB;IACtB,4FAA4F;IAC5F,sDAAsD;IACtD,MAAM,cAAc,GAAG;QACrB,QAAQ;QACR,cAAc;QACd,UAAU;QACV,YAAY;QACZ,KAAK;QACL,OAAO;QACP,OAAO;QACP,UAAU;QACV,OAAO;QACP,eAAe;QACf,iBAAiB;QACjB,OAAO,CAAC,gBAAgB;QACxB,eAAe;QACf,OAAO,CAAC,cAAc;QACtB,GAAG,CAAC,OAAO,CAAC,mBAAmB;YAC7B,CAAC,CAAC,CAAC,oBAAoB,EAAE,OAAO,CAAC,mBAAmB,CAAC;YACrD,CAAC,CAAC,EAAE,CAAC;KACR,CAAC;IACF,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,MAAM,EAAE,cAAc,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CAAC,2BAA2B,EAAE;YAC/C,KAAK,EAAG,KAAyB,CAAC,MAAM;SACzC,CAAC,CAAC;IACL,CAAC;IAED,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC;QACvB,OAAO;IACT,CAAC;IAED,MAAM,SAAS,CAAC;QACd,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;QAC1C,mBAAmB,EAAE,OAAO,CAAC,mBAAmB;KACjD,CAAC,CAAC;AACL,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/sign/modifyApp.d.ts b/packages/platform-apple-helpers/dist/src/lib/commands/sign/modifyApp.d.ts
new file mode 100644
index 000000000..6c5d33a92
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/sign/modifyApp.d.ts
@@ -0,0 +1,8 @@
+export type ModifyAppOptions = {
+ appPath: string;
+ outputPath?: string;
+ buildJsBundle?: boolean;
+ jsBundlePath?: string;
+ useHermes?: boolean;
+};
+export declare const modifyApp: (options: ModifyAppOptions) => Promise;
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/sign/modifyApp.js b/packages/platform-apple-helpers/dist/src/lib/commands/sign/modifyApp.js
new file mode 100644
index 000000000..fa2ac99cc
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/sign/modifyApp.js
@@ -0,0 +1,48 @@
+import fs from 'node:fs';
+import { colorLink, intro, logger, outro, relativeToCwd, RockError, spinner, } from '@rock-js/tools';
+import { buildJsBundle } from './bundle.js';
+import { getAppPaths } from './utils.js';
+export const modifyApp = async (options) => {
+ validateOptions(options);
+ intro(`Modifying APP file`);
+ const loader = spinner();
+ // 1. Copy APP file to output path if provided
+ if (options.outputPath) {
+ try {
+ fs.cpSync(options.appPath, options.outputPath, { recursive: true });
+ }
+ catch (error) {
+ throw new RockError(`Failed to copy APP file to ${colorLink(relativeToCwd(options.outputPath))}.`, { cause: error });
+ }
+ }
+ // 2. Make APP content changes if needed: build or swap JS bundle
+ const appPaths = getAppPaths(options.outputPath ?? options.appPath);
+ if (options.buildJsBundle) {
+ loader.start('Building JS bundle');
+ await buildJsBundle({
+ bundleOutputPath: appPaths.jsBundle,
+ assetsDestPath: appPaths.assetsDest,
+ useHermes: options.useHermes ?? true,
+ });
+ loader.stop(`Built JS bundle: ${colorLink(relativeToCwd(appPaths.jsBundle))}`);
+ }
+ else if (options.jsBundlePath) {
+ loader.start('Replacing JS bundle');
+ fs.copyFileSync(options.jsBundlePath, appPaths.jsBundle);
+ loader.stop(`Replaced JS bundle with ${colorLink(relativeToCwd(options.jsBundlePath))}`);
+ }
+ logger.log(`Modified APP file with new JS bundle. Available at: ${colorLink(relativeToCwd(options.outputPath ?? options.appPath))}`);
+ outro('Success ๐.');
+};
+function validateOptions(options) {
+ if (!fs.existsSync(options.appPath)) {
+ throw new RockError(`APP file (directory) not found at "${options.appPath}". Please provide a correct path.`);
+ }
+ if (options.buildJsBundle && options.jsBundlePath) {
+ throw new RockError('The "--build-jsbundle" flag is incompatible with "--jsbundle". Pick one.');
+ }
+ if (options.jsBundlePath && !fs.existsSync(options.jsBundlePath)) {
+ throw new RockError(`JS bundle file not found at "${options.jsBundlePath}". Please provide a correct path.`);
+ }
+}
+//# sourceMappingURL=modifyApp.js.map
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/sign/modifyApp.js.map b/packages/platform-apple-helpers/dist/src/lib/commands/sign/modifyApp.js.map
new file mode 100644
index 000000000..8e43c8260
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/sign/modifyApp.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"modifyApp.js","sourceRoot":"","sources":["../../../../../src/lib/commands/sign/modifyApp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EACL,SAAS,EACT,KAAK,EACL,MAAM,EACN,KAAK,EACL,aAAa,EACb,SAAS,EACT,OAAO,GACR,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAUzC,MAAM,CAAC,MAAM,SAAS,GAAG,KAAK,EAAE,OAAyB,EAAE,EAAE;IAC3D,eAAe,CAAC,OAAO,CAAC,CAAC;IAEzB,KAAK,CAAC,oBAAoB,CAAC,CAAC;IAE5B,MAAM,MAAM,GAAG,OAAO,EAAE,CAAC;IAEzB,8CAA8C;IAC9C,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;QACvB,IAAI,CAAC;YACH,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACtE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,SAAS,CACjB,8BAA8B,SAAS,CACrC,aAAa,CAAC,OAAO,CAAC,UAAU,CAAC,CAClC,GAAG,EACJ,EAAE,KAAK,EAAE,KAAK,EAAE,CACjB,CAAC;QACJ,CAAC;IACH,CAAC;IAED,iEAAiE;IACjE,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IACpE,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;QAC1B,MAAM,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;QACnC,MAAM,aAAa,CAAC;YAClB,gBAAgB,EAAE,QAAQ,CAAC,QAAQ;YACnC,cAAc,EAAE,QAAQ,CAAC,UAAU;YACnC,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,IAAI;SACrC,CAAC,CAAC;QACH,MAAM,CAAC,IAAI,CACT,oBAAoB,SAAS,CAAC,aAAa,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,EAAE,CAClE,CAAC;IACJ,CAAC;SAAM,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;QAChC,MAAM,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;QACpC,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,YAAY,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACzD,MAAM,CAAC,IAAI,CACT,2BAA2B,SAAS,CAClC,aAAa,CAAC,OAAO,CAAC,YAAY,CAAC,CACpC,EAAE,CACJ,CAAC;IACJ,CAAC;IAED,MAAM,CAAC,GAAG,CACR,uDAAuD,SAAS,CAC9D,aAAa,CAAC,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC,CACrD,EAAE,CACJ,CAAC;IAEF,KAAK,CAAC,aAAa,CAAC,CAAC;AACvB,CAAC,CAAC;AAEF,SAAS,eAAe,CAAC,OAAyB;IAChD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACpC,MAAM,IAAI,SAAS,CACjB,sCAAsC,OAAO,CAAC,OAAO,mCAAmC,CACzF,CAAC;IACJ,CAAC;IAED,IAAI,OAAO,CAAC,aAAa,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;QAClD,MAAM,IAAI,SAAS,CACjB,0EAA0E,CAC3E,CAAC;IACJ,CAAC;IAED,IAAI,OAAO,CAAC,YAAY,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;QACjE,MAAM,IAAI,SAAS,CACjB,gCAAgC,OAAO,CAAC,YAAY,mCAAmC,CACxF,CAAC;IACJ,CAAC;AACH,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/sign/modifyIpa.d.ts b/packages/platform-apple-helpers/dist/src/lib/commands/sign/modifyIpa.d.ts
new file mode 100644
index 000000000..9ad991bdf
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/sign/modifyIpa.d.ts
@@ -0,0 +1,10 @@
+export type ModifyIpaOptions = {
+ platformName: string;
+ ipaPath: string;
+ identity?: string;
+ outputPath?: string;
+ buildJsBundle?: boolean;
+ jsBundlePath?: string;
+ useHermes?: boolean;
+};
+export declare const modifyIpa: (options: ModifyIpaOptions) => Promise;
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/sign/modifyIpa.js b/packages/platform-apple-helpers/dist/src/lib/commands/sign/modifyIpa.js
new file mode 100644
index 000000000..88e9fefe3
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/sign/modifyIpa.js
@@ -0,0 +1,85 @@
+import fs from 'node:fs';
+import { color, colorLink, intro, isInteractive, logger, outro, relativeToCwd, RockError, spawn, spinner, } from '@rock-js/tools';
+import { promptSigningIdentity } from '../../utils/signingIdentities.js';
+import { buildJsBundle } from './bundle.js';
+import { decodeProvisioningProfileToPlist, generateEntitlementsPlist, getIdentityFromProvisioningPlist, } from './provisioningProfile.js';
+import { getAppPaths, getTempPaths, packIpa, unpackIpa } from './utils.js';
+export const modifyIpa = async (options) => {
+ validateOptions(options);
+ intro(`Modifying IPA file`);
+ // 1. Extract IPA contents
+ const loader = spinner();
+ loader.start(`Unzipping the IPA file`);
+ const tempPaths = getTempPaths(options.platformName);
+ const appPath = unpackIpa(options.ipaPath, tempPaths.content);
+ loader.stop(`Unzipped IPA contents: ${colorLink(relativeToCwd(appPath))}`);
+ // 2. Make IPA content changes if needed: build or swap JS bundle
+ const appPaths = getAppPaths(appPath);
+ if (options.buildJsBundle) {
+ loader.start('Building JS bundle');
+ await buildJsBundle({
+ bundleOutputPath: appPaths.jsBundle,
+ assetsDestPath: appPaths.assetsDest,
+ useHermes: options.useHermes ?? true,
+ });
+ loader.stop(`Built JS bundle: ${colorLink(relativeToCwd(appPaths.jsBundle))}`);
+ }
+ else if (options.jsBundlePath) {
+ loader.start('Replacing JS bundle');
+ fs.copyFileSync(options.jsBundlePath, appPaths.jsBundle);
+ loader.stop(`Replaced JS bundle with ${colorLink(relativeToCwd(options.jsBundlePath))}`);
+ }
+ // 3. Sign the IPA contents
+ await decodeProvisioningProfileToPlist(appPaths.provisioningProfile, tempPaths.provisioningPlist);
+ let identity = options.identity;
+ if (!identity) {
+ const currentIdentity = await getIdentityFromProvisioningPlist(tempPaths.provisioningPlist);
+ if (currentIdentity) {
+ logger.debug(`Extracted identity from provisioning profile: ${currentIdentity}`);
+ }
+ identity = await promptSigningIdentity(currentIdentity);
+ }
+ loader.start('Signing the app');
+ await generateEntitlementsPlist({
+ provisioningPlistPath: tempPaths.provisioningPlist,
+ outputPath: tempPaths.entitlementsPlist,
+ });
+ const codeSignArgs = [
+ '--force',
+ '--sign',
+ identity,
+ '--entitlements',
+ tempPaths.entitlementsPlist,
+ appPath,
+ ];
+ try {
+ await spawn('codesign', codeSignArgs, { cwd: tempPaths.content });
+ }
+ catch (error) {
+ throw new RockError('Codesign failed', {
+ cause: error.stderr,
+ });
+ }
+ loader.stop(`Signed the IPA contents with identity: ${color.cyan(identity)}`);
+ // 4. Repack the IPA file
+ loader.start('Creating final IPA file');
+ const outputPath = options.outputPath ?? options.ipaPath;
+ packIpa(tempPaths.content, outputPath);
+ loader.stop(`Created final IPA file: ${colorLink(outputPath)}`);
+ outro('Success ๐.');
+};
+function validateOptions(options) {
+ if (!fs.existsSync(options.ipaPath)) {
+ throw new RockError(`IPA file not found at "${options.ipaPath}". Please provide a correct path.`);
+ }
+ if (!options.identity && !isInteractive()) {
+ throw new RockError('The "--identity" flag is required in non-interactive environments, such as CI. Please pass one.');
+ }
+ if (options.buildJsBundle && options.jsBundlePath) {
+ throw new RockError('The "--build-jsbundle" flag is incompatible with "--jsbundle". Pick one.');
+ }
+ if (options.jsBundlePath && !fs.existsSync(options.jsBundlePath)) {
+ throw new RockError(`JS bundle file not found at "${options.jsBundlePath}". Please provide a correct path.`);
+ }
+}
+//# sourceMappingURL=modifyIpa.js.map
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/sign/modifyIpa.js.map b/packages/platform-apple-helpers/dist/src/lib/commands/sign/modifyIpa.js.map
new file mode 100644
index 000000000..c41216bbd
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/sign/modifyIpa.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"modifyIpa.js","sourceRoot":"","sources":["../../../../../src/lib/commands/sign/modifyIpa.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB,OAAO,EACL,KAAK,EACL,SAAS,EACT,KAAK,EACL,aAAa,EACb,MAAM,EACN,KAAK,EACL,aAAa,EACb,SAAS,EACT,KAAK,EACL,OAAO,GACR,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EACL,gCAAgC,EAChC,yBAAyB,EACzB,gCAAgC,GACjC,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAY3E,MAAM,CAAC,MAAM,SAAS,GAAG,KAAK,EAAE,OAAyB,EAAE,EAAE;IAC3D,eAAe,CAAC,OAAO,CAAC,CAAC;IAEzB,KAAK,CAAC,oBAAoB,CAAC,CAAC;IAE5B,0BAA0B;IAC1B,MAAM,MAAM,GAAG,OAAO,EAAE,CAAC;IACzB,MAAM,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;IACvC,MAAM,SAAS,GAAG,YAAY,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IACrD,MAAM,OAAO,GAAG,SAAS,CAAC,OAAO,CAAC,OAAO,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC;IAC9D,MAAM,CAAC,IAAI,CAAC,0BAA0B,SAAS,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;IAE3E,iEAAiE;IACjE,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IACtC,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;QAC1B,MAAM,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;QACnC,MAAM,aAAa,CAAC;YAClB,gBAAgB,EAAE,QAAQ,CAAC,QAAQ;YACnC,cAAc,EAAE,QAAQ,CAAC,UAAU;YACnC,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,IAAI;SACrC,CAAC,CAAC;QACH,MAAM,CAAC,IAAI,CACT,oBAAoB,SAAS,CAAC,aAAa,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,EAAE,CAClE,CAAC;IACJ,CAAC;SAAM,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;QAChC,MAAM,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;QACpC,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,YAAY,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACzD,MAAM,CAAC,IAAI,CACT,2BAA2B,SAAS,CAClC,aAAa,CAAC,OAAO,CAAC,YAAY,CAAC,CACpC,EAAE,CACJ,CAAC;IACJ,CAAC;IAED,2BAA2B;IAC3B,MAAM,gCAAgC,CACpC,QAAQ,CAAC,mBAAmB,EAC5B,SAAS,CAAC,iBAAiB,CAC5B,CAAC;IAEF,IAAI,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;IAChC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,eAAe,GAAG,MAAM,gCAAgC,CAC5D,SAAS,CAAC,iBAAiB,CAC5B,CAAC;QACF,IAAI,eAAe,EAAE,CAAC;YACpB,MAAM,CAAC,KAAK,CACV,iDAAiD,eAAe,EAAE,CACnE,CAAC;QACJ,CAAC;QAED,QAAQ,GAAG,MAAM,qBAAqB,CAAC,eAAe,CAAC,CAAC;IAC1D,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;IAChC,MAAM,yBAAyB,CAAC;QAC9B,qBAAqB,EAAE,SAAS,CAAC,iBAAiB;QAClD,UAAU,EAAE,SAAS,CAAC,iBAAiB;KACxC,CAAC,CAAC;IAEH,MAAM,YAAY,GAAG;QACnB,SAAS;QACT,QAAQ;QACR,QAAQ;QACR,gBAAgB;QAChB,SAAS,CAAC,iBAAiB;QAC3B,OAAO;KACR,CAAC;IACF,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,UAAU,EAAE,YAAY,EAAE,EAAE,GAAG,EAAE,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC;IACpE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CAAC,iBAAiB,EAAE;YACrC,KAAK,EAAG,KAAyB,CAAC,MAAM;SACzC,CAAC,CAAC;IACL,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,0CAA0C,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IAE9E,yBAAyB;IACzB,MAAM,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC;IACxC,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC;IACzD,OAAO,CAAC,SAAS,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IACvC,MAAM,CAAC,IAAI,CAAC,2BAA2B,SAAS,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;IAEhE,KAAK,CAAC,aAAa,CAAC,CAAC;AACvB,CAAC,CAAC;AAEF,SAAS,eAAe,CAAC,OAAyB;IAChD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACpC,MAAM,IAAI,SAAS,CACjB,0BAA0B,OAAO,CAAC,OAAO,mCAAmC,CAC7E,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,OAAO,CAAC,QAAQ,IAAI,CAAC,aAAa,EAAE,EAAE,CAAC;QAC1C,MAAM,IAAI,SAAS,CACjB,iGAAiG,CAClG,CAAC;IACJ,CAAC;IAED,IAAI,OAAO,CAAC,aAAa,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;QAClD,MAAM,IAAI,SAAS,CACjB,0EAA0E,CAC3E,CAAC;IACJ,CAAC;IAED,IAAI,OAAO,CAAC,YAAY,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;QACjE,MAAM,IAAI,SAAS,CACjB,gCAAgC,OAAO,CAAC,YAAY,mCAAmC,CACxF,CAAC;IACJ,CAAC;AACH,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/sign/provisioningProfile.d.ts b/packages/platform-apple-helpers/dist/src/lib/commands/sign/provisioningProfile.d.ts
new file mode 100644
index 000000000..bfa3639e9
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/sign/provisioningProfile.d.ts
@@ -0,0 +1,27 @@
+/**
+ * Decodes provisioning profile to XML plist.
+ * @param profilePath - Path to the provisioning profile.
+ * @param outputPath - Path to the output plist file.
+ */
+export declare function decodeProvisioningProfileToPlist(profilePath: string, outputPath: string): Promise;
+export type GenerateEntitlementsFileOptions = {
+ provisioningPlistPath: string;
+ outputPath: string;
+};
+/**
+ * Generates entitlements plist from provisioning profile plist.
+ * @param provisioningPlistPath - Path to the provisioning profile plist.
+ * @param outputPath - Path to the output entitlements plist file.
+ */
+export declare const generateEntitlementsPlist: ({ outputPath, provisioningPlistPath, }: GenerateEntitlementsFileOptions) => Promise;
+/**
+ * Extract code sign identity from provisioning profile plist file.
+ * @param plistPath - Path to the provisioning profile plist file.
+ * @returns Code sign identity name.
+ */
+export declare function getIdentityFromProvisioningPlist(plistPath: string): Promise;
+/**
+ * Extracts certificate name used from subject field. This names corresponds to
+ * the name of the signing identity.
+ */
+export declare function extractCertificateName(subject: string): string | null;
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/sign/provisioningProfile.js b/packages/platform-apple-helpers/dist/src/lib/commands/sign/provisioningProfile.js
new file mode 100644
index 000000000..fda52fd3d
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/sign/provisioningProfile.js
@@ -0,0 +1,50 @@
+import crypto from 'node:crypto';
+import fs from 'node:fs';
+import { logger, relativeToCwd, RockError, spawn } from '@rock-js/tools';
+import { readBufferFromPlist, readKeyFromPlist } from '../../utils/plist.js';
+/**
+ * Decodes provisioning profile to XML plist.
+ * @param profilePath - Path to the provisioning profile.
+ * @param outputPath - Path to the output plist file.
+ */
+export async function decodeProvisioningProfileToPlist(profilePath, outputPath) {
+ try {
+ await spawn('security', ['cms', '-D', '-i', profilePath, '-o', outputPath]);
+ logger.debug(`Decoded provisioning profile to plist: ${relativeToCwd(outputPath)}`);
+ }
+ catch (error) {
+ throw new RockError(`Failed to decode provisioning profile: ${profilePath}`, { cause: error.stderr });
+ }
+}
+/**
+ * Generates entitlements plist from provisioning profile plist.
+ * @param provisioningPlistPath - Path to the provisioning profile plist.
+ * @param outputPath - Path to the output entitlements plist file.
+ */
+export const generateEntitlementsPlist = async ({ outputPath, provisioningPlistPath, }) => {
+ const entitlements = await readKeyFromPlist(provisioningPlistPath, 'Entitlements', {
+ xml: true,
+ });
+ fs.writeFileSync(outputPath, entitlements);
+ logger.debug(`Generated entitlements file: ${relativeToCwd(outputPath)}`);
+};
+/**
+ * Extract code sign identity from provisioning profile plist file.
+ * @param plistPath - Path to the provisioning profile plist file.
+ * @returns Code sign identity name.
+ */
+export async function getIdentityFromProvisioningPlist(plistPath) {
+ const cert = await readBufferFromPlist(plistPath, 'DeveloperCertificates:0');
+ const decodedCert = new crypto.X509Certificate(cert);
+ return extractCertificateName(decodedCert.subject);
+}
+/**
+ * Extracts certificate name used from subject field. This names corresponds to
+ * the name of the signing identity.
+ */
+export function extractCertificateName(subject) {
+ const regex = /CN=(.+)$/m;
+ const match = subject.match(regex);
+ return match ? match[1] : null;
+}
+//# sourceMappingURL=provisioningProfile.js.map
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/sign/provisioningProfile.js.map b/packages/platform-apple-helpers/dist/src/lib/commands/sign/provisioningProfile.js.map
new file mode 100644
index 000000000..2021cc096
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/sign/provisioningProfile.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"provisioningProfile.js","sourceRoot":"","sources":["../../../../../src/lib/commands/sign/provisioningProfile.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACzE,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE7E;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,gCAAgC,CACpD,WAAmB,EACnB,UAAkB;IAElB,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,UAAU,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC;QAC5E,MAAM,CAAC,KAAK,CACV,0CAA0C,aAAa,CAAC,UAAU,CAAC,EAAE,CACtE,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CACjB,0CAA0C,WAAW,EAAE,EACvD,EAAE,KAAK,EAAG,KAAyB,CAAC,MAAM,EAAE,CAC7C,CAAC;IACJ,CAAC;AACH,CAAC;AAOD;;;;GAIG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,KAAK,EAAE,EAC9C,UAAU,EACV,qBAAqB,GACW,EAAE,EAAE;IACpC,MAAM,YAAY,GAAG,MAAM,gBAAgB,CACzC,qBAAqB,EACrB,cAAc,EACd;QACE,GAAG,EAAE,IAAI;KACV,CACF,CAAC;IAEF,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;IAC3C,MAAM,CAAC,KAAK,CAAC,gCAAgC,aAAa,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;AAC5E,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,gCAAgC,CAAC,SAAiB;IACtE,MAAM,IAAI,GAAG,MAAM,mBAAmB,CAAC,SAAS,EAAE,yBAAyB,CAAC,CAAC;IAC7E,MAAM,WAAW,GAAG,IAAI,MAAM,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;IACrD,OAAO,sBAAsB,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;AACrD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,OAAe;IACpD,MAAM,KAAK,GAAG,WAAW,CAAC;IAC1B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACnC,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACjC,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/sign/utils.d.ts b/packages/platform-apple-helpers/dist/src/lib/commands/sign/utils.d.ts
new file mode 100644
index 000000000..a2d22de90
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/sign/utils.d.ts
@@ -0,0 +1,40 @@
+/**
+ * Temporary paths for sign operation.
+ * @param platformName - Platform name.
+ */
+export declare function getTempPaths(platformName: string): {
+ /** Root path for sign operation. */
+ root: string;
+ /** Path to extracted IPA contents. */
+ content: string;
+ /** Path to the temporary provisioning plist. */
+ provisioningPlist: string;
+ /** Path to the temporary entitlements plist. */
+ entitlementsPlist: string;
+};
+/**
+ * Paths inside .app directory in extracted IPA file.
+ * @param appPath - Path to the .app directory.
+ */
+export declare function getAppPaths(appPath: string): {
+ /** Path to assets directory. */
+ assetsDest: string;
+ /** Path to the JS bundle. */
+ jsBundle: string;
+ /** Path to embedded provisioning profile. */
+ provisioningProfile: string;
+};
+/**
+ * Unpack IPA file contents to given path.
+ * @param ipaPath - Path to the IPA file.
+ * @param destination - Path to the destination folder.
+ * @returns Path to .app directory (package) inside the IPA file.
+ */
+export declare const unpackIpa: (ipaPath: string, destination: string) => string;
+/**
+ * Pack IPA file from content path.
+ * @param contentPath - Path to pack as IPA contents.
+ * @param ipaPath - Path to the output IPA file.
+ * @returns Path to the output IPA file.
+ */
+export declare const packIpa: (contentPath: string, ipaPath: string) => string;
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/sign/utils.js b/packages/platform-apple-helpers/dist/src/lib/commands/sign/utils.js
new file mode 100644
index 000000000..cfc9a22a6
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/sign/utils.js
@@ -0,0 +1,74 @@
+import { existsSync, mkdirSync, rmSync } from 'node:fs';
+import path from 'node:path';
+import { findDirectoriesWithPattern, getDotRockPath, RockError, } from '@rock-js/tools';
+import AdmZip from 'adm-zip';
+/**
+ * Temporary paths for sign operation.
+ * @param platformName - Platform name.
+ */
+export function getTempPaths(platformName) {
+ const root = path.join(getDotRockPath(), platformName, 'sign');
+ return {
+ /** Root path for sign operation. */
+ root,
+ /** Path to extracted IPA contents. */
+ content: path.join(root, 'content'),
+ /** Path to the temporary provisioning plist. */
+ provisioningPlist: path.join(root, 'provisioning.plist'),
+ /** Path to the temporary entitlements plist. */
+ entitlementsPlist: path.join(root, 'entitlements.plist'),
+ };
+}
+/**
+ * Paths inside .app directory in extracted IPA file.
+ * @param appPath - Path to the .app directory.
+ */
+export function getAppPaths(appPath) {
+ return {
+ /** Path to assets directory. */
+ assetsDest: path.join(appPath, 'assets'),
+ /** Path to the JS bundle. */
+ jsBundle: path.join(appPath, 'main.jsbundle'),
+ /** Path to embedded provisioning profile. */
+ provisioningProfile: path.join(appPath, 'embedded.mobileprovision'),
+ };
+}
+/**
+ * Unpack IPA file contents to given path.
+ * @param ipaPath - Path to the IPA file.
+ * @param destination - Path to the destination folder.
+ * @returns Path to .app directory (package) inside the IPA file.
+ */
+export const unpackIpa = (ipaPath, destination) => {
+ if (existsSync(destination)) {
+ rmSync(destination, { recursive: true, force: true });
+ }
+ mkdirSync(destination, { recursive: true });
+ const zip = new AdmZip(ipaPath);
+ zip.extractAllTo(destination, true);
+ const payloadPath = `${destination}/Payload`;
+ if (!existsSync(payloadPath)) {
+ throw new Error('Payload folder not found in the extracted IPA file');
+ }
+ const appPath = findDirectoriesWithPattern(payloadPath, /\.app$/)[0];
+ if (!appPath) {
+ throw new RockError(`.app package not found in the extracted IPA file ${payloadPath}`);
+ }
+ return appPath;
+};
+/**
+ * Pack IPA file from content path.
+ * @param contentPath - Path to pack as IPA contents.
+ * @param ipaPath - Path to the output IPA file.
+ * @returns Path to the output IPA file.
+ */
+export const packIpa = (contentPath, ipaPath) => {
+ if (existsSync(ipaPath)) {
+ rmSync(ipaPath, { recursive: true, force: true });
+ }
+ const zip = new AdmZip();
+ zip.addLocalFolder(contentPath);
+ zip.writeZip(ipaPath);
+ return ipaPath;
+};
+//# sourceMappingURL=utils.js.map
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/commands/sign/utils.js.map b/packages/platform-apple-helpers/dist/src/lib/commands/sign/utils.js.map
new file mode 100644
index 000000000..238c7ef5b
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/commands/sign/utils.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../../../src/lib/commands/sign/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACxD,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EACL,0BAA0B,EAC1B,cAAc,EACd,SAAS,GACV,MAAM,gBAAgB,CAAC;AACxB,OAAO,MAAM,MAAM,SAAS,CAAC;AAE7B;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,YAAoB;IAC/C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,YAAY,EAAE,MAAM,CAAC,CAAC;IAC/D,OAAO;QACL,oCAAoC;QACpC,IAAI;QACJ,sCAAsC;QACtC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC;QACnC,gDAAgD;QAChD,iBAAiB,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,oBAAoB,CAAC;QACxD,gDAAgD;QAChD,iBAAiB,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,oBAAoB,CAAC;KACzD,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,OAAe;IACzC,OAAO;QACL,gCAAgC;QAChC,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC;QACxC,6BAA6B;QAC7B,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,eAAe,CAAC;QAC7C,6CAA6C;QAC7C,mBAAmB,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,0BAA0B,CAAC;KACpE,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,OAAe,EAAE,WAAmB,EAAU,EAAE;IACxE,IAAI,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAC5B,MAAM,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACxD,CAAC;IAED,SAAS,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE5C,MAAM,GAAG,GAAG,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC;IAChC,GAAG,CAAC,YAAY,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;IAEpC,MAAM,WAAW,GAAG,GAAG,WAAW,UAAU,CAAC;IAC7C,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;IACxE,CAAC;IAED,MAAM,OAAO,GAAG,0BAA0B,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IACrE,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,SAAS,CACjB,oDAAoD,WAAW,EAAE,CAClE,CAAC;IACJ,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,WAAmB,EAAE,OAAe,EAAE,EAAE;IAC9D,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACxB,MAAM,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACpD,CAAC;IAED,MAAM,GAAG,GAAG,IAAI,MAAM,EAAE,CAAC;IACzB,GAAG,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;IAChC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAEtB,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/index.d.ts b/packages/platform-apple-helpers/dist/src/lib/index.d.ts
new file mode 100644
index 000000000..2c592387a
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/index.d.ts
@@ -0,0 +1,12 @@
+export { createBuild } from './commands/build/createBuild.js';
+export { createRun } from './commands/run/createRun.js';
+export { getBuildOptions, BuildFlags } from './commands/build/buildOptions.js';
+export { getRunOptions, RunFlags } from './commands/run/runOptions.js';
+export { modifyIpa, type ModifyIpaOptions } from './commands/sign/modifyIpa.js';
+export { modifyApp, type ModifyAppOptions } from './commands/sign/modifyApp.js';
+export { genericDestinations } from './utils/destionation.js';
+export { getBuildPaths } from './utils/getBuildPaths.js';
+export { getInfo } from './utils/getInfo.js';
+export { getScheme } from './utils/getScheme.js';
+export { getValidProjectConfig } from './utils/getValidProjectConfig.js';
+export { promptSigningIdentity } from './utils/signingIdentities.js';
diff --git a/packages/platform-apple-helpers/dist/src/lib/index.js b/packages/platform-apple-helpers/dist/src/lib/index.js
new file mode 100644
index 000000000..b6bf4b10a
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/index.js
@@ -0,0 +1,13 @@
+export { createBuild } from './commands/build/createBuild.js';
+export { createRun } from './commands/run/createRun.js';
+export { getBuildOptions } from './commands/build/buildOptions.js';
+export { getRunOptions } from './commands/run/runOptions.js';
+export { modifyIpa } from './commands/sign/modifyIpa.js';
+export { modifyApp } from './commands/sign/modifyApp.js';
+export { genericDestinations } from './utils/destionation.js';
+export { getBuildPaths } from './utils/getBuildPaths.js';
+export { getInfo } from './utils/getInfo.js';
+export { getScheme } from './utils/getScheme.js';
+export { getValidProjectConfig } from './utils/getValidProjectConfig.js';
+export { promptSigningIdentity } from './utils/signingIdentities.js';
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/index.js.map b/packages/platform-apple-helpers/dist/src/lib/index.js.map
new file mode 100644
index 000000000..616d7c2cc
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AACxD,OAAO,EAAE,eAAe,EAAc,MAAM,kCAAkC,CAAC;AAC/E,OAAO,EAAE,aAAa,EAAY,MAAM,8BAA8B,CAAC;AACvE,OAAO,EAAE,SAAS,EAAyB,MAAM,8BAA8B,CAAC;AAChF,OAAO,EAAE,SAAS,EAAyB,MAAM,8BAA8B,CAAC;AAChF,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/types/index.d.ts b/packages/platform-apple-helpers/dist/src/lib/types/index.d.ts
new file mode 100644
index 000000000..a6bba7827
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/types/index.d.ts
@@ -0,0 +1,35 @@
+import type { supportedPlatforms } from '../utils/supportedPlatforms.js';
+type ObjectValues = T[keyof T];
+export type ApplePlatform = ObjectValues;
+export interface Device {
+ name: string;
+ udid: string;
+ version: string;
+ platform: ApplePlatform | undefined;
+ type: DeviceType;
+ state: 'Booted' | 'Shutdown';
+}
+export type DeviceType = 'simulator' | 'device';
+export interface Info {
+ name: string;
+ schemes?: string[];
+ configurations?: string[];
+ targets?: string[];
+}
+export interface BuilderCommand {
+ platformName: ApplePlatform;
+}
+export interface XcodeProjectInfo {
+ name: string;
+ path: string;
+ isWorkspace: boolean;
+}
+export interface Params {
+ sourceDir?: string;
+ assets?: string[];
+}
+export interface ProjectConfig {
+ sourceDir: string;
+ xcodeProject: XcodeProjectInfo;
+}
+export {};
diff --git a/packages/platform-apple-helpers/dist/src/lib/types/index.js b/packages/platform-apple-helpers/dist/src/lib/types/index.js
new file mode 100644
index 000000000..f8a711af8
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/types/index.js
@@ -0,0 +1,2 @@
+export {};
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/types/index.js.map b/packages/platform-apple-helpers/dist/src/lib/types/index.js.map
new file mode 100644
index 000000000..c65e2c333
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/types/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/lib/types/index.ts"],"names":[],"mappings":""}
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/__tests__/signgningIdentity.d.ts b/packages/platform-apple-helpers/dist/src/lib/utils/__tests__/signgningIdentity.d.ts
new file mode 100644
index 000000000..cb0ff5c3b
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/utils/__tests__/signgningIdentity.d.ts
@@ -0,0 +1 @@
+export {};
diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/__tests__/signgningIdentity.js b/packages/platform-apple-helpers/dist/src/lib/utils/__tests__/signgningIdentity.js
new file mode 100644
index 000000000..a62db64a7
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/utils/__tests__/signgningIdentity.js
@@ -0,0 +1,40 @@
+import { describe, expect, it } from 'vitest';
+import { parseSigningIdentities } from '../signingIdentities.js';
+describe('parseSigningIdentities', () => {
+ it('should parse valid signing identities output', () => {
+ const input = `
+ 1) 1234567890ABCDEF1234567890ABCDEF12345678 "Apple Development: John Doe (TEAMID1234)"
+ 2) ABCDEF1234567890ABCDEF1234567890ABCDEF12 "Apple Distribution: Jane Smith (TEAMID5678)"
+ `;
+ const result = parseSigningIdentities(input);
+ expect(result).toEqual([
+ {
+ hash: '1234567890ABCDEF1234567890ABCDEF12345678',
+ name: 'Apple Development: John Doe (TEAMID1234)',
+ },
+ {
+ hash: 'ABCDEF1234567890ABCDEF1234567890ABCDEF12',
+ name: 'Apple Distribution: Jane Smith (TEAMID5678)',
+ },
+ ]);
+ });
+ it('should handle empty input', () => {
+ const result = parseSigningIdentities('');
+ expect(result).toEqual([]);
+ });
+ it('should handle input with invalid lines', () => {
+ const input = `
+ Invalid line
+ 1) 1234567890ABCDEF1234567890ABCDEF12345678 "Apple Development: John Doe (TEAMID1234)"
+ Another invalid line
+ `;
+ const result = parseSigningIdentities(input);
+ expect(result).toEqual([
+ {
+ hash: '1234567890ABCDEF1234567890ABCDEF12345678',
+ name: 'Apple Development: John Doe (TEAMID1234)',
+ },
+ ]);
+ });
+});
+//# sourceMappingURL=signgningIdentity.js.map
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/__tests__/signgningIdentity.js.map b/packages/platform-apple-helpers/dist/src/lib/utils/__tests__/signgningIdentity.js.map
new file mode 100644
index 000000000..f5c0e9a58
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/utils/__tests__/signgningIdentity.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"signgningIdentity.js","sourceRoot":"","sources":["../../../../../src/lib/utils/__tests__/signgningIdentity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAEjE,QAAQ,CAAC,wBAAwB,EAAE,GAAG,EAAE;IACtC,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACtD,MAAM,KAAK,GAAG;;;KAGb,CAAC;QAEF,MAAM,MAAM,GAAG,sBAAsB,CAAC,KAAK,CAAC,CAAC;QAE7C,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;YACrB;gBACE,IAAI,EAAE,0CAA0C;gBAChD,IAAI,EAAE,0CAA0C;aACjD;YACD;gBACE,IAAI,EAAE,0CAA0C;gBAChD,IAAI,EAAE,6CAA6C;aACpD;SACF,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2BAA2B,EAAE,GAAG,EAAE;QACnC,MAAM,MAAM,GAAG,sBAAsB,CAAC,EAAE,CAAC,CAAC;QAC1C,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,MAAM,KAAK,GAAG;;;;KAIb,CAAC;QAEF,MAAM,MAAM,GAAG,sBAAsB,CAAC,KAAK,CAAC,CAAC;QAE7C,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;YACrB;gBACE,IAAI,EAAE,0CAA0C;gBAChD,IAAI,EAAE,0CAA0C;aACjD;SACF,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/buildApp.d.ts b/packages/platform-apple-helpers/dist/src/lib/utils/buildApp.d.ts
new file mode 100644
index 000000000..175c3556e
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/utils/buildApp.d.ts
@@ -0,0 +1,27 @@
+import type { IOSProjectConfig } from '@react-native-community/cli-types';
+import { type FingerprintSources } from '@rock-js/tools';
+import type { BuildFlags } from '../commands/build/buildOptions.js';
+import type { RunFlags } from '../commands/run/runOptions.js';
+import type { ApplePlatform, ProjectConfig } from '../types/index.js';
+export declare function buildApp({ args, projectConfig, pluginConfig, platformName, udid, projectRoot, deviceName, reactNativePath, binaryPath, brownfield, artifactName, fingerprintOptions, deviceOrSimulator, }: {
+ args: RunFlags | BuildFlags;
+ projectConfig: ProjectConfig;
+ pluginConfig?: IOSProjectConfig;
+ platformName: ApplePlatform;
+ udid?: string;
+ deviceName?: string;
+ projectRoot: string;
+ reactNativePath: string;
+ binaryPath?: string;
+ brownfield?: boolean;
+ artifactName: string;
+ fingerprintOptions: FingerprintSources;
+ deviceOrSimulator: string;
+}): Promise<{
+ appPath: string;
+ bundleIdentifier: any;
+ infoPlistPath: string;
+ scheme: string | undefined;
+ xcodeProject: import("../types/index.js").XcodeProjectInfo;
+ sourceDir: string;
+}>;
diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/buildApp.js b/packages/platform-apple-helpers/dist/src/lib/utils/buildApp.js
new file mode 100644
index 000000000..50937a5a2
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/utils/buildApp.js
@@ -0,0 +1,116 @@
+import path from 'node:path';
+import { formatArtifactName, getInfoPlist, RockError, saveLocalBuildCache, } from '@rock-js/tools';
+import { buildProject } from '../commands/build/buildProject.js';
+import { getBuildSettings } from '../commands/run/getBuildSettings.js';
+import { getGenericDestination } from './destionation.js';
+import { getConfiguration } from './getConfiguration.js';
+import { getInfo } from './getInfo.js';
+import { getScheme } from './getScheme.js';
+import { getValidProjectConfig } from './getValidProjectConfig.js';
+import { installPodsIfNeeded } from './pods.js';
+export async function buildApp({ args, projectConfig, pluginConfig, platformName, udid, projectRoot, deviceName, reactNativePath, binaryPath, brownfield, artifactName, fingerprintOptions, deviceOrSimulator, }) {
+ if (binaryPath) {
+ // @todo Info.plist is hardcoded when reading from binaryPath
+ const infoPlistPath = path.join(binaryPath, 'Info.plist');
+ const infoPlistJson = await getInfoPlist(infoPlistPath);
+ const bundleIdentifier = infoPlistJson?.['CFBundleIdentifier'] ?? 'unknown';
+ return {
+ appPath: binaryPath,
+ bundleIdentifier,
+ infoPlistPath,
+ scheme: args.scheme,
+ xcodeProject: projectConfig.xcodeProject,
+ sourceDir: projectConfig.sourceDir,
+ };
+ }
+ let artifactNameToSave = artifactName;
+ let { xcodeProject, sourceDir } = projectConfig;
+ if (args.installPods) {
+ const didInstallPods = await installPodsIfNeeded(projectRoot, platformName, sourceDir, args.newArch, reactNativePath, brownfield);
+ // When the project is not a workspace, we need to get the project config again,
+ // because running pods install might have generated .xcworkspace project.
+ // This should be only case in new project.
+ if (xcodeProject.isWorkspace === false) {
+ const newProjectConfig = getValidProjectConfig(platformName, projectRoot, pluginConfig);
+ xcodeProject = newProjectConfig.xcodeProject;
+ sourceDir = newProjectConfig.sourceDir;
+ }
+ if (didInstallPods) {
+ // After installing pods the fingerprint likely changes.
+ // We update the artifact name to reflect the new fingerprint and store proper entry in the local cache.
+ artifactNameToSave = await formatArtifactName({
+ platform: 'ios',
+ traits: [deviceOrSimulator, args.configuration ?? 'Debug'],
+ root: projectRoot,
+ fingerprintOptions,
+ type: 'update',
+ });
+ }
+ }
+ const info = await getInfo(xcodeProject, sourceDir);
+ if (!info) {
+ throw new RockError('Failed to get Xcode project information');
+ }
+ const scheme = await getScheme(info.schemes, args.scheme, xcodeProject.name);
+ const configuration = await getConfiguration(info.configurations, args.configuration);
+ const destinations = determineDestinations({
+ destination: args.destination,
+ isCatalyst: 'catalyst' in args && args.catalyst,
+ platformName,
+ udid,
+ deviceName,
+ });
+ await buildProject({
+ xcodeProject,
+ sourceDir,
+ platformName,
+ scheme,
+ configuration,
+ destinations,
+ args,
+ });
+ const buildSettings = await getBuildSettings({
+ xcodeProject,
+ sourceDir,
+ platformName,
+ configuration,
+ destinations,
+ scheme,
+ target: args.target,
+ buildFolder: args.buildFolder,
+ });
+ saveLocalBuildCache(artifactNameToSave, buildSettings.appPath);
+ return {
+ appPath: buildSettings.appPath,
+ infoPlistPath: buildSettings.infoPlistPath,
+ scheme: scheme,
+ xcodeProject,
+ sourceDir,
+ bundleIdentifier: buildSettings.bundleIdentifier,
+ };
+}
+function determineDestinations({ destination, isCatalyst, platformName, udid, deviceName, }) {
+ if (isCatalyst) {
+ return ['platform=macOS,variant=Mac Catalyst'];
+ }
+ if (udid) {
+ return [`id=${udid}`];
+ }
+ if (deviceName) {
+ return [`name=${deviceName}`];
+ }
+ if (destination && destination.length > 0) {
+ return destination.map((destination) => resolveDestination(destination, platformName));
+ }
+ return [getGenericDestination(platformName, 'device')];
+}
+function resolveDestination(destination, platformName) {
+ if (destination === 'device') {
+ return getGenericDestination(platformName, 'device');
+ }
+ if (destination === 'simulator') {
+ return getGenericDestination(platformName, 'simulator');
+ }
+ return destination;
+}
+//# sourceMappingURL=buildApp.js.map
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/buildApp.js.map b/packages/platform-apple-helpers/dist/src/lib/utils/buildApp.js.map
new file mode 100644
index 000000000..136bd6fb5
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/utils/buildApp.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"buildApp.js","sourceRoot":"","sources":["../../../../src/lib/utils/buildApp.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/codegen.d.ts b/packages/platform-apple-helpers/dist/src/lib/utils/codegen.d.ts
new file mode 100644
index 000000000..597e5953c
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/utils/codegen.d.ts
@@ -0,0 +1,9 @@
+import type { ApplePlatform } from '../types/index.js';
+interface CodegenOptions {
+ projectRoot: string;
+ platformName: ApplePlatform;
+ reactNativePath: string;
+ sourceDir: string;
+}
+declare function runCodegen(options: CodegenOptions): Promise;
+export default runCodegen;
diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/codegen.js b/packages/platform-apple-helpers/dist/src/lib/utils/codegen.js
new file mode 100644
index 000000000..c9fa9a7d2
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/utils/codegen.js
@@ -0,0 +1,29 @@
+import { spawn } from '@rock-js/tools';
+import { RockError } from '@rock-js/tools';
+import fs from 'fs';
+import path from 'path';
+async function runCodegen(options) {
+ const buildDir = path.join(options.sourceDir, 'build');
+ if (fs.existsSync(buildDir)) {
+ fs.rmSync(buildDir, { recursive: true });
+ }
+ const codegenScript = path.join(options.reactNativePath, 'scripts/generate-codegen-artifacts.js');
+ try {
+ await spawn('node', [
+ codegenScript,
+ '-p',
+ options.projectRoot,
+ '-o',
+ options.sourceDir,
+ '-t',
+ options.platformName,
+ ]);
+ }
+ catch (error) {
+ throw new RockError('Failed to run React Native codegen script', {
+ cause: error.output,
+ });
+ }
+}
+export default runCodegen;
+//# sourceMappingURL=codegen.js.map
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/codegen.js.map b/packages/platform-apple-helpers/dist/src/lib/utils/codegen.js.map
new file mode 100644
index 000000000..2365207e1
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/utils/codegen.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"codegen.js","sourceRoot":"","sources":["../../../../src/lib/utils/codegen.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAUxB,KAAK,UAAU,UAAU,CAAC,OAAuB;IAC/C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IACvD,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5B,EAAE,CAAC,MAAM,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3C,CAAC;IAED,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAC7B,OAAO,CAAC,eAAe,EACvB,uCAAuC,CACxC,CAAC;IAEF,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,MAAM,EAAE;YAClB,aAAa;YACb,IAAI;YACJ,OAAO,CAAC,WAAW;YACnB,IAAI;YACJ,OAAO,CAAC,SAAS;YACjB,IAAI;YACJ,OAAO,CAAC,YAAY;SACrB,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CAAC,2CAA2C,EAAE;YAC/D,KAAK,EAAG,KAAyB,CAAC,MAAM;SACzC,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED,eAAe,UAAU,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/destionation.d.ts b/packages/platform-apple-helpers/dist/src/lib/utils/destionation.d.ts
new file mode 100644
index 000000000..079801a04
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/utils/destionation.d.ts
@@ -0,0 +1,24 @@
+import type { ApplePlatform, DeviceType } from '../types/index.js';
+export type DestinationInfo = {
+ device: string;
+ simulator: string;
+};
+export declare const genericDestinations: {
+ readonly ios: {
+ readonly device: "generic/platform=iOS";
+ readonly simulator: "generic/platform=iOS Simulator";
+ };
+ readonly macos: {
+ readonly device: "generic/platform=macOS";
+ readonly simulator: "generic/platform=macOS";
+ };
+ readonly visionos: {
+ readonly device: "generic/platform=visionOS";
+ readonly simulator: "generic/platform=visionOS Simulator";
+ };
+ readonly tvos: {
+ readonly device: "generic/platform=tvOS";
+ readonly simulator: "generic/platform=tvOS Simulator";
+ };
+};
+export declare function getGenericDestination(platform: ApplePlatform, deviceType: DeviceType): string;
diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/destionation.js b/packages/platform-apple-helpers/dist/src/lib/utils/destionation.js
new file mode 100644
index 000000000..558726979
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/utils/destionation.js
@@ -0,0 +1,22 @@
+export const genericDestinations = {
+ ios: {
+ device: 'generic/platform=iOS',
+ simulator: 'generic/platform=iOS Simulator',
+ },
+ macos: {
+ device: 'generic/platform=macOS',
+ simulator: 'generic/platform=macOS',
+ },
+ visionos: {
+ device: 'generic/platform=visionOS',
+ simulator: 'generic/platform=visionOS Simulator',
+ },
+ tvos: {
+ device: 'generic/platform=tvOS',
+ simulator: 'generic/platform=tvOS Simulator',
+ },
+};
+export function getGenericDestination(platform, deviceType) {
+ return genericDestinations[platform][deviceType];
+}
+//# sourceMappingURL=destionation.js.map
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/destionation.js.map b/packages/platform-apple-helpers/dist/src/lib/utils/destionation.js.map
new file mode 100644
index 000000000..e1abce860
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/utils/destionation.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"destionation.js","sourceRoot":"","sources":["../../../../src/lib/utils/destionation.ts"],"names":[],"mappings":"AAOA,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,GAAG,EAAE;QACH,MAAM,EAAE,sBAAsB;QAC9B,SAAS,EAAE,gCAAgC;KAC5C;IACD,KAAK,EAAE;QACL,MAAM,EAAE,wBAAwB;QAChC,SAAS,EAAE,wBAAwB;KACpC;IACD,QAAQ,EAAE;QACR,MAAM,EAAE,2BAA2B;QACnC,SAAS,EAAE,qCAAqC;KACjD;IACD,IAAI,EAAE;QACJ,MAAM,EAAE,uBAAuB;QAC/B,SAAS,EAAE,iCAAiC;KAC7C;CACwD,CAAC;AAE5D,MAAM,UAAU,qBAAqB,CACnC,QAAuB,EACvB,UAAsB;IAEtB,OAAO,mBAAmB,CAAC,QAAQ,CAAC,CAAC,UAAU,CAAC,CAAC;AACnD,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/getBuildPaths.d.ts b/packages/platform-apple-helpers/dist/src/lib/utils/getBuildPaths.d.ts
new file mode 100644
index 000000000..7512c4519
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/utils/getBuildPaths.d.ts
@@ -0,0 +1,7 @@
+export declare const getBuildPaths: (platformName: string) => {
+ buildDir: string;
+ exportDir: string;
+ archiveDir: string;
+ packageDir: string;
+ derivedDataDir: string;
+};
diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/getBuildPaths.js b/packages/platform-apple-helpers/dist/src/lib/utils/getBuildPaths.js
new file mode 100644
index 000000000..65bc617a9
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/utils/getBuildPaths.js
@@ -0,0 +1,13 @@
+import path from 'node:path';
+import { getCacheRootPath } from '@rock-js/tools';
+export const getBuildPaths = (platformName) => {
+ const buildDir = path.join(getCacheRootPath(), platformName);
+ return {
+ buildDir,
+ exportDir: path.join(buildDir, 'export'),
+ archiveDir: path.join(buildDir, 'archive'),
+ packageDir: path.join(buildDir, 'package'),
+ derivedDataDir: path.join(buildDir, 'derivedData'),
+ };
+};
+//# sourceMappingURL=getBuildPaths.js.map
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/getBuildPaths.js.map b/packages/platform-apple-helpers/dist/src/lib/utils/getBuildPaths.js.map
new file mode 100644
index 000000000..f90f0c10d
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/utils/getBuildPaths.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"getBuildPaths.js","sourceRoot":"","sources":["../../../../src/lib/utils/getBuildPaths.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAElD,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,YAAoB,EAAE,EAAE;IACpD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE,YAAY,CAAC,CAAC;IAE7D,OAAO;QACL,QAAQ;QACR,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC;QACxC,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC;QAC1C,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC;QAC1C,cAAc,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,aAAa,CAAC;KACnD,CAAC;AACJ,CAAC,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/getConfiguration.d.ts b/packages/platform-apple-helpers/dist/src/lib/utils/getConfiguration.d.ts
new file mode 100644
index 000000000..ec7868bab
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/utils/getConfiguration.d.ts
@@ -0,0 +1,2 @@
+import type { Info } from '../types/index.js';
+export declare function getConfiguration(configurations: Info['configurations'], preselectedConfiguration: string | undefined): Promise;
diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/getConfiguration.js b/packages/platform-apple-helpers/dist/src/lib/utils/getConfiguration.js
new file mode 100644
index 000000000..a4cbe3164
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/utils/getConfiguration.js
@@ -0,0 +1,46 @@
+import { isInteractive, logger, promptSelect, RockError } from '@rock-js/tools';
+export async function getConfiguration(configurations, preselectedConfiguration) {
+ let configuration = preselectedConfiguration;
+ if (configurations &&
+ configurations.length > 1 &&
+ !preselectedConfiguration) {
+ // This is default and common configuration for React Native projects.
+ // In such cases we 90% want a Debug configuration.
+ // For the rest 10% user can pass the --configuration flag.
+ if (configurations.length === 2 &&
+ configurations.includes('Debug') &&
+ configurations.includes('Release')) {
+ configuration = 'Debug';
+ }
+ else if (isInteractive()) {
+ configuration = await promptForConfigurationSelection(configurations);
+ logger.info(`You can set configuration manually next time using "--configuration ${configuration}" flag.`);
+ }
+ }
+ if (!configuration) {
+ configuration = 'Debug';
+ }
+ invalidateConfiguration(configurations, configuration);
+ return configuration;
+}
+function invalidateConfiguration(configurations, configuration) {
+ if (!configurations || configurations.length === 0) {
+ logger.warn(`Unable to check whether "${configuration}" configuration exists in your project`);
+ return;
+ }
+ if (!configurations.includes(configuration)) {
+ throw new RockError(`Configuration "${configuration}" doesn't exist. Please use one of the existing configurations: ${configurations
+ .map((configuration) => `\n- ${configuration}`)
+ .join('')}`);
+ }
+}
+function promptForConfigurationSelection(configurations) {
+ return promptSelect({
+ message: 'Select the configuration you want to use',
+ options: configurations.map((value) => ({
+ label: value,
+ value: value,
+ })),
+ });
+}
+//# sourceMappingURL=getConfiguration.js.map
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/getConfiguration.js.map b/packages/platform-apple-helpers/dist/src/lib/utils/getConfiguration.js.map
new file mode 100644
index 000000000..05fb6ffc6
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/utils/getConfiguration.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"getConfiguration.js","sourceRoot":"","sources":["../../../../src/lib/utils/getConfiguration.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAGhF,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,cAAsC,EACtC,wBAA4C;IAE5C,IAAI,aAAa,GAAG,wBAAwB,CAAC;IAC7C,IACE,cAAc;QACd,cAAc,CAAC,MAAM,GAAG,CAAC;QACzB,CAAC,wBAAwB,EACzB,CAAC;QACD,sEAAsE;QACtE,mDAAmD;QACnD,2DAA2D;QAC3D,IACE,cAAc,CAAC,MAAM,KAAK,CAAC;YAC3B,cAAc,CAAC,QAAQ,CAAC,OAAO,CAAC;YAChC,cAAc,CAAC,QAAQ,CAAC,SAAS,CAAC,EAClC,CAAC;YACD,aAAa,GAAG,OAAO,CAAC;QAC1B,CAAC;aAAM,IAAI,aAAa,EAAE,EAAE,CAAC;YAC3B,aAAa,GAAG,MAAM,+BAA+B,CAAC,cAAc,CAAC,CAAC;YACtE,MAAM,CAAC,IAAI,CACT,uEAAuE,aAAa,SAAS,CAC9F,CAAC;QACJ,CAAC;IACH,CAAC;IACD,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,aAAa,GAAG,OAAO,CAAC;IAC1B,CAAC;IACD,uBAAuB,CAAC,cAAc,EAAE,aAAa,CAAC,CAAC;IACvD,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,SAAS,uBAAuB,CAC9B,cAAsC,EACtC,aAAqB;IAErB,IAAI,CAAC,cAAc,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACnD,MAAM,CAAC,IAAI,CACT,4BAA4B,aAAa,wCAAwC,CAClF,CAAC;QACF,OAAO;IACT,CAAC;IAED,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;QAC5C,MAAM,IAAI,SAAS,CACjB,kBAAkB,aAAa,mEAAmE,cAAc;aAC7G,GAAG,CAAC,CAAC,aAAa,EAAE,EAAE,CAAC,OAAO,aAAa,EAAE,CAAC;aAC9C,IAAI,CAAC,EAAE,CAAC,EAAE,CACd,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,+BAA+B,CAAC,cAAwB;IAC/D,OAAO,YAAY,CAAC;QAClB,OAAO,EAAE,0CAA0C;QACnD,OAAO,EAAE,cAAc,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YACtC,KAAK,EAAE,KAAK;YACZ,KAAK,EAAE,KAAK;SACb,CAAC,CAAC;KACJ,CAAC,CAAC;AACL,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/getInfo.d.ts b/packages/platform-apple-helpers/dist/src/lib/utils/getInfo.d.ts
new file mode 100644
index 000000000..f901db56d
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/utils/getInfo.d.ts
@@ -0,0 +1,2 @@
+import type { Info, XcodeProjectInfo } from '../types/index.js';
+export declare function getInfo(projectInfo: XcodeProjectInfo, sourceDir: string): Promise;
diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/getInfo.js b/packages/platform-apple-helpers/dist/src/lib/utils/getInfo.js
new file mode 100644
index 000000000..6161a6cef
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/utils/getInfo.js
@@ -0,0 +1,85 @@
+import * as fs from 'node:fs';
+import * as path from 'node:path';
+import { logger, RockError, spawn } from '@rock-js/tools';
+import { XMLParser } from 'fast-xml-parser';
+function parseTargetList(json) {
+ try {
+ const info = JSON.parse(json);
+ if ('project' in info) {
+ return info.project;
+ }
+ else if ('workspace' in info) {
+ return info.workspace;
+ }
+ return undefined;
+ }
+ catch (error) {
+ throw new RockError('Failed to parse target list', { cause: error });
+ }
+}
+export async function getInfo(projectInfo, sourceDir) {
+ if (!projectInfo.isWorkspace) {
+ try {
+ const { stdout } = await spawn('xcodebuild', ['-list', '-json'], {
+ cwd: sourceDir,
+ stdio: 'pipe',
+ });
+ const info = parseTargetList(stdout);
+ if (!info) {
+ throw new RockError('Failed to get Xcode project information');
+ }
+ return info;
+ }
+ catch (error) {
+ throw new RockError('Failed to get a target list.', {
+ cause: error,
+ });
+ }
+ }
+ const xmlParser = new XMLParser({ ignoreAttributes: false });
+ const xcworkspacedata = path.join(sourceDir, projectInfo.name, 'contents.xcworkspacedata');
+ const workspace = fs.readFileSync(xcworkspacedata, { encoding: 'utf-8' });
+ const fileRef = xmlParser.parse(workspace).Workspace.FileRef;
+ const refs = Array.isArray(fileRef) ? fileRef : [fileRef];
+ const locations = refs
+ .map((ref) => ref['@_location'])
+ .filter((location) => !location.endsWith('/Pods.xcodeproj') && // Ignore the project generated by CocoaPods
+ location.endsWith('.xcodeproj'));
+ let info = undefined;
+ for (const location of locations) {
+ let stdout = '';
+ try {
+ const buildOutput = await spawn('xcodebuild', ['-list', '-json', '-project', location.replace('group:', '')], { cwd: sourceDir, stdio: 'pipe' });
+ stdout = buildOutput.stdout;
+ logger.debug(stdout);
+ logger.debug(buildOutput.stderr);
+ }
+ catch (error) {
+ throw new RockError('Failed to get project info', {
+ cause: error.stderr,
+ });
+ }
+ const projectInfo = parseTargetList(stdout);
+ if (!projectInfo) {
+ continue;
+ }
+ const schemes = projectInfo.schemes;
+ // If this is the first project, use it as the "main" project
+ if (!info) {
+ if (!Array.isArray(schemes)) {
+ projectInfo.schemes = [];
+ }
+ info = projectInfo;
+ continue;
+ }
+ if (!Array.isArray(info.schemes)) {
+ throw new RockError("This shouldn't happen since we set it earlier");
+ }
+ // For subsequent projects, merge schemes list
+ if (Array.isArray(schemes) && schemes.length > 0) {
+ info.schemes = info.schemes.concat(schemes);
+ }
+ }
+ return info;
+}
+//# sourceMappingURL=getInfo.js.map
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/getInfo.js.map b/packages/platform-apple-helpers/dist/src/lib/utils/getInfo.js.map
new file mode 100644
index 000000000..3f5e38cef
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/utils/getInfo.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"getInfo.js","sourceRoot":"","sources":["../../../../src/lib/utils/getInfo.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/getPlatformInfo.d.ts b/packages/platform-apple-helpers/dist/src/lib/utils/getPlatformInfo.d.ts
new file mode 100644
index 000000000..e26040e4a
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/utils/getPlatformInfo.d.ts
@@ -0,0 +1,10 @@
+import type { ApplePlatform } from '../types/index.js';
+interface PlatformInfo {
+ readableName: string;
+}
+/**
+ * Returns platform readable name.
+ * Falls back to iOS if platform is not supported.
+ */
+export declare function getPlatformInfo(platform: ApplePlatform): PlatformInfo;
+export {};
diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/getPlatformInfo.js b/packages/platform-apple-helpers/dist/src/lib/utils/getPlatformInfo.js
new file mode 100644
index 000000000..93f071e21
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/utils/getPlatformInfo.js
@@ -0,0 +1,26 @@
+/**
+ * Returns platform readable name.
+ * Falls back to iOS if platform is not supported.
+ */
+export function getPlatformInfo(platform) {
+ switch (platform) {
+ case 'tvos':
+ return {
+ readableName: 'tvOS',
+ };
+ case 'visionos':
+ return {
+ readableName: 'visionOS',
+ };
+ case 'macos':
+ return {
+ readableName: 'macOS',
+ };
+ case 'ios':
+ default:
+ return {
+ readableName: 'iOS',
+ };
+ }
+}
+//# sourceMappingURL=getPlatformInfo.js.map
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/getPlatformInfo.js.map b/packages/platform-apple-helpers/dist/src/lib/utils/getPlatformInfo.js.map
new file mode 100644
index 000000000..277cd9c2a
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/utils/getPlatformInfo.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"getPlatformInfo.js","sourceRoot":"","sources":["../../../../src/lib/utils/getPlatformInfo.ts"],"names":[],"mappings":"AAMA;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,QAAuB;IACrD,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,MAAM;YACT,OAAO;gBACL,YAAY,EAAE,MAAM;aACrB,CAAC;QACJ,KAAK,UAAU;YACb,OAAO;gBACL,YAAY,EAAE,UAAU;aACzB,CAAC;QACJ,KAAK,OAAO;YACV,OAAO;gBACL,YAAY,EAAE,OAAO;aACtB,CAAC;QACJ,KAAK,KAAK,CAAC;QACX;YACE,OAAO;gBACL,YAAY,EAAE,KAAK;aACpB,CAAC;IACN,CAAC;AACH,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/getScheme.d.ts b/packages/platform-apple-helpers/dist/src/lib/utils/getScheme.d.ts
new file mode 100644
index 000000000..519e6b286
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/utils/getScheme.d.ts
@@ -0,0 +1,2 @@
+import type { Info } from '../types/index.js';
+export declare function getScheme(schemes: Info['schemes'], preselectedScheme: string | undefined, projectName: string): Promise;
diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/getScheme.js b/packages/platform-apple-helpers/dist/src/lib/utils/getScheme.js
new file mode 100644
index 000000000..2c8e2b7e1
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/utils/getScheme.js
@@ -0,0 +1,37 @@
+import { isInteractive, logger, promptSelect, RockError } from '@rock-js/tools';
+import path from 'path';
+export async function getScheme(schemes, preselectedScheme, projectName) {
+ let scheme = preselectedScheme;
+ if (schemes && schemes.length > 1 && !preselectedScheme) {
+ if (isInteractive()) {
+ scheme = await promptForSchemeSelection(schemes);
+ logger.info(`You can set scheme manually next time using "--scheme ${scheme}" flag.`);
+ }
+ }
+ if (!scheme) {
+ scheme = path.basename(projectName, path.extname(projectName));
+ }
+ invalidateScheme(schemes, scheme);
+ return scheme;
+}
+function invalidateScheme(schemes, scheme) {
+ if (!schemes || schemes.length === 0) {
+ logger.warn(`Unable to check whether "${scheme}" scheme exists in your project`);
+ return;
+ }
+ if (!schemes.includes(scheme)) {
+ throw new RockError(`Scheme "${scheme}" doesn't exist. Please use one of the existing schemes: ${schemes
+ .map((scheme) => `\n- ${scheme}`)
+ .join('')}`);
+ }
+}
+function promptForSchemeSelection(schemes) {
+ return promptSelect({
+ message: 'Select the scheme you want to use',
+ options: schemes.map((value) => ({
+ label: value,
+ value: value,
+ })),
+ });
+}
+//# sourceMappingURL=getScheme.js.map
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/getScheme.js.map b/packages/platform-apple-helpers/dist/src/lib/utils/getScheme.js.map
new file mode 100644
index 000000000..c465c0d28
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/utils/getScheme.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"getScheme.js","sourceRoot":"","sources":["../../../../src/lib/utils/getScheme.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChF,OAAO,IAAI,MAAM,MAAM,CAAC;AAGxB,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,OAAwB,EACxB,iBAAqC,EACrC,WAAmB;IAEnB,IAAI,MAAM,GAAG,iBAAiB,CAAC;IAC/B,IAAI,OAAO,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACxD,IAAI,aAAa,EAAE,EAAE,CAAC;YACpB,MAAM,GAAG,MAAM,wBAAwB,CAAC,OAAO,CAAC,CAAC;YACjD,MAAM,CAAC,IAAI,CACT,yDAAyD,MAAM,SAAS,CACzE,CAAC;QACJ,CAAC;IACH,CAAC;IACD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC;IACjE,CAAC;IACD,gBAAgB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAClC,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,gBAAgB,CAAC,OAAwB,EAAE,MAAc;IAChE,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrC,MAAM,CAAC,IAAI,CACT,4BAA4B,MAAM,iCAAiC,CACpE,CAAC;QACF,OAAO;IACT,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,SAAS,CACjB,WAAW,MAAM,4DAA4D,OAAO;aACjF,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,OAAO,MAAM,EAAE,CAAC;aAChC,IAAI,CAAC,EAAE,CAAC,EAAE,CACd,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,wBAAwB,CAAC,OAAiB;IACjD,OAAO,YAAY,CAAC;QAClB,OAAO,EAAE,mCAAmC;QAC5C,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YAC/B,KAAK,EAAE,KAAK;YACZ,KAAK,EAAE,KAAK;SACb,CAAC,CAAC;KACJ,CAAC,CAAC;AACL,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/getValidProjectConfig.d.ts b/packages/platform-apple-helpers/dist/src/lib/utils/getValidProjectConfig.d.ts
new file mode 100644
index 000000000..78e731944
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/utils/getValidProjectConfig.d.ts
@@ -0,0 +1,7 @@
+import type { IOSProjectParams } from '@react-native-community/cli-types';
+import type { ApplePlatform, ProjectConfig } from '../types/index.js';
+/**
+ * Get the valid project config with non-null `xcodeProject` for the given Apple platform.
+ * To be used before running commands or after installing pods.
+ */
+export declare function getValidProjectConfig(platformName: ApplePlatform, projectRoot: string, userConfig?: IOSProjectParams): ProjectConfig;
diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/getValidProjectConfig.js b/packages/platform-apple-helpers/dist/src/lib/utils/getValidProjectConfig.js
new file mode 100644
index 000000000..8ec5cd684
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/utils/getValidProjectConfig.js
@@ -0,0 +1,17 @@
+import { getProjectConfig } from '@react-native-community/cli-config-apple';
+import { RockError } from '@rock-js/tools';
+/**
+ * Get the valid project config with non-null `xcodeProject` for the given Apple platform.
+ * To be used before running commands or after installing pods.
+ */
+export function getValidProjectConfig(platformName, projectRoot, userConfig = {}) {
+ const newProjectConfig = getProjectConfig({ platformName })(projectRoot, userConfig);
+ if (!newProjectConfig || newProjectConfig.xcodeProject === null) {
+ throw new RockError('Failed to get Xcode project information');
+ }
+ return {
+ sourceDir: newProjectConfig.sourceDir,
+ xcodeProject: newProjectConfig.xcodeProject,
+ };
+}
+//# sourceMappingURL=getValidProjectConfig.js.map
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/getValidProjectConfig.js.map b/packages/platform-apple-helpers/dist/src/lib/utils/getValidProjectConfig.js.map
new file mode 100644
index 000000000..d142a79cc
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/utils/getValidProjectConfig.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"getValidProjectConfig.js","sourceRoot":"","sources":["../../../../src/lib/utils/getValidProjectConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,0CAA0C,CAAC;AAE5E,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAG3C;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CACnC,YAA2B,EAC3B,WAAmB,EACnB,aAA+B,EAAE;IAEjC,MAAM,gBAAgB,GAAG,gBAAgB,CAAC,EAAE,YAAY,EAAE,CAAC,CACzD,WAAW,EACX,UAAU,CACX,CAAC;IACF,IAAI,CAAC,gBAAgB,IAAI,gBAAgB,CAAC,YAAY,KAAK,IAAI,EAAE,CAAC;QAChE,MAAM,IAAI,SAAS,CAAC,yCAAyC,CAAC,CAAC;IACjE,CAAC;IACD,OAAO;QACL,SAAS,EAAE,gBAAgB,CAAC,SAAS;QACrC,YAAY,EAAE,gBAAgB,CAAC,YAAY;KAC5C,CAAC;AACJ,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/listDevices.d.ts b/packages/platform-apple-helpers/dist/src/lib/utils/listDevices.d.ts
new file mode 100644
index 000000000..490fa71cc
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/utils/listDevices.d.ts
@@ -0,0 +1,2 @@
+import type { ApplePlatform, Device } from '../types/index.js';
+export declare function listDevicesAndSimulators(platform: ApplePlatform): Promise;
diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/listDevices.js b/packages/platform-apple-helpers/dist/src/lib/utils/listDevices.js
new file mode 100644
index 000000000..42df057f5
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/utils/listDevices.js
@@ -0,0 +1,80 @@
+import fs from 'node:fs';
+import os from 'node:os';
+import path from 'node:path';
+import { RockError, spawn } from '@rock-js/tools';
+function parseDevicectlList(devicectlOutput) {
+ const devices = devicectlOutput.map((device) => ({
+ name: device.deviceProperties.name,
+ udid: device.hardwareProperties.udid,
+ version: `${device.hardwareProperties.platform} ${device.deviceProperties.osVersionNumber}`,
+ platform: getPlatformFromOsVersion(device.hardwareProperties.platform),
+ state: device.deviceProperties.bootState === 'booted' ? 'Booted' : 'Shutdown',
+ type: 'device',
+ }));
+ return devices;
+}
+async function getDevices() {
+ const tmpPath = path.resolve(os.tmpdir(), 'iosPhysicalDevices.json'); // same as Minisim.app
+ try {
+ await spawn('xcrun', ['devicectl', 'list', 'devices', '-j', tmpPath]);
+ const output = JSON.parse(fs.readFileSync(tmpPath, 'utf8'));
+ return parseDevicectlList(output.result.devices);
+ }
+ catch (error) {
+ throw new RockError('Failed to get devices', {
+ cause: error.stderr,
+ });
+ }
+}
+async function getSimulators() {
+ const { output } = await spawn('xcrun', ['simctl', 'list', 'devices', 'available'], { stdio: 'pipe' });
+ return parseSimctlOutput(output);
+}
+export async function listDevicesAndSimulators(platform) {
+ const simulators = await getSimulators();
+ const devices = await getDevices();
+ return [...simulators, ...devices].filter((device) => device.platform === platform);
+}
+function parseSimctlOutput(input) {
+ const lines = input.split('\n');
+ const devices = [];
+ const currentOSIdx = 1;
+ const deviceNameIdx = 1;
+ const identifierIdx = 4;
+ const deviceStateIdx = 5;
+ let osVersion = '';
+ lines.forEach((line) => {
+ const currentOsMatch = line.match(/-- (.*?) --/);
+ if (currentOsMatch && currentOsMatch.length > 0) {
+ osVersion = currentOsMatch[currentOSIdx];
+ }
+ const deviceMatch = line.match(/(.*?) (\(([0-9.]+)\) )?\(([0-9A-F-]+)\) \((.*?)\)/);
+ if (deviceMatch && deviceMatch.length > 0) {
+ devices.push({
+ name: deviceMatch[deviceNameIdx].trim(),
+ udid: deviceMatch[identifierIdx],
+ version: osVersion,
+ platform: getPlatformFromOsVersion(osVersion.split(' ')[0]),
+ state: deviceMatch[deviceStateIdx],
+ type: 'simulator',
+ });
+ }
+ });
+ return devices;
+}
+function getPlatformFromOsVersion(osVersion) {
+ switch (osVersion) {
+ case 'iOS':
+ return 'ios';
+ case 'tvOS':
+ return 'tvos';
+ case 'macOS':
+ return 'macos';
+ case 'xrOS':
+ case 'visionOS':
+ return 'visionos';
+ default:
+ return undefined;
+ }
+}
+//# sourceMappingURL=listDevices.js.map
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/listDevices.js.map b/packages/platform-apple-helpers/dist/src/lib/utils/listDevices.js.map
new file mode 100644
index 000000000..1fc2cfb80
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/utils/listDevices.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"listDevices.js","sourceRoot":"","sources":["../../../../src/lib/utils/listDevices.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/plist.d.ts b/packages/platform-apple-helpers/dist/src/lib/utils/plist.d.ts
new file mode 100644
index 000000000..dc1afdc95
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/utils/plist.d.ts
@@ -0,0 +1,6 @@
+type PListBuddyOptions = {
+ xml?: boolean;
+};
+export declare function readKeyFromPlist(plistPath: string, key: string, options?: PListBuddyOptions): Promise;
+export declare function readBufferFromPlist(plistPath: string, key: string): Promise;
+export {};
diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/plist.js b/packages/platform-apple-helpers/dist/src/lib/utils/plist.js
new file mode 100644
index 000000000..9628a11cb
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/utils/plist.js
@@ -0,0 +1,48 @@
+import { execFile } from 'node:child_process';
+import { promisify } from 'node:util';
+import { RockError, spawn, SubprocessError } from '@rock-js/tools';
+const execFileAsync = promisify(execFile);
+export async function readKeyFromPlist(plistPath, key, options = {}) {
+ try {
+ const result = await plistBuddy(plistPath, `Print:${key}`, options);
+ return result.stdout.trim();
+ }
+ catch (error) {
+ throw new RockError(`Error reading key ${key} from ${plistPath}`, {
+ cause: error instanceof SubprocessError ? error.stderr : error,
+ });
+ }
+}
+async function plistBuddy(path, command, options) {
+ const args = ['-c', command, path];
+ if (options?.xml) {
+ args.unshift('-x');
+ }
+ const result = await spawn('/usr/libexec/PlistBuddy', args, {
+ stdio: 'pipe',
+ });
+ return result;
+}
+export async function readBufferFromPlist(plistPath, key) {
+ try {
+ const result = await binaryPlistBuddy(plistPath, `Print:${key}`);
+ return Buffer.from(result.stdout, 'binary');
+ }
+ catch (error) {
+ throw new RockError(`Error reading key ${key} from ${plistPath}`, {
+ cause: error instanceof SubprocessError ? error.stderr : error,
+ });
+ }
+}
+/**
+ * Special version of plistBuddy that reads the output as binary. Use `execFile`
+ * instead of nano-spawn which does not support binary output.
+ */
+async function binaryPlistBuddy(path, command) {
+ const args = ['-c', command, path];
+ const result = await execFileAsync('/usr/libexec/PlistBuddy', args, {
+ encoding: 'binary',
+ });
+ return result;
+}
+//# sourceMappingURL=plist.js.map
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/plist.js.map b/packages/platform-apple-helpers/dist/src/lib/utils/plist.js.map
new file mode 100644
index 000000000..4c5c2a230
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/utils/plist.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"plist.js","sourceRoot":"","sources":["../../../../src/lib/utils/plist.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEnE,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAM1C,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,SAAiB,EACjB,GAAW,EACX,UAA6B,EAAE;IAE/B,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,SAAS,EAAE,SAAS,GAAG,EAAE,EAAE,OAAO,CAAC,CAAC;QACpE,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IAC9B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CAAC,qBAAqB,GAAG,SAAS,SAAS,EAAE,EAAE;YAChE,KAAK,EAAE,KAAK,YAAY,eAAe,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK;SAC/D,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED,KAAK,UAAU,UAAU,CACvB,IAAY,EACZ,OAAe,EACf,OAA2B;IAE3B,MAAM,IAAI,GAAG,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IACnC,IAAI,OAAO,EAAE,GAAG,EAAE,CAAC;QACjB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACrB,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,yBAAyB,EAAE,IAAI,EAAE;QAC1D,KAAK,EAAE,MAAM;KACd,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,SAAiB,EACjB,GAAW;IAEX,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,SAAS,EAAE,SAAS,GAAG,EAAE,CAAC,CAAC;QACjE,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC9C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CAAC,qBAAqB,GAAG,SAAS,SAAS,EAAE,EAAE;YAChE,KAAK,EAAE,KAAK,YAAY,eAAe,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK;SAC/D,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,gBAAgB,CAAC,IAAY,EAAE,OAAe;IAC3D,MAAM,IAAI,GAAG,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IACnC,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,yBAAyB,EAAE,IAAI,EAAE;QAClE,QAAQ,EAAE,QAAQ;KACnB,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/pods.d.ts b/packages/platform-apple-helpers/dist/src/lib/utils/pods.d.ts
new file mode 100644
index 000000000..05f05c3ab
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/utils/pods.d.ts
@@ -0,0 +1,2 @@
+import type { ApplePlatform } from '../types/index.js';
+export declare function installPodsIfNeeded(projectRoot: string, platformName: ApplePlatform, sourceDir: string, newArch: boolean, reactNativePath: string, brownfield?: boolean): Promise;
diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/pods.js b/packages/platform-apple-helpers/dist/src/lib/utils/pods.js
new file mode 100644
index 000000000..e5531f67f
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/utils/pods.js
@@ -0,0 +1,266 @@
+import { createHash } from 'node:crypto';
+import fs from 'node:fs';
+import path from 'node:path';
+import { cacheManager, color, colorLink, getReactNativeVersion, logger, RockError, spawn, spinner, } from '@rock-js/tools';
+import runCodegen from './codegen.js';
+const podErrorHelpMessage = `Please make sure your environment is correctly set up.
+Learn more at: ${color.dim('https://cocoapods.org/')}
+To skip automatic CocoaPods installation run with "--no-install-pods" flag after installing CocoaPods manually.`;
+export async function installPodsIfNeeded(projectRoot, platformName, sourceDir, newArch, reactNativePath, brownfield) {
+ const podsPath = path.join(sourceDir, 'Pods');
+ const podfilePath = path.join(sourceDir, 'Podfile');
+ // There's a possibility to define a custom dependencies in `react-native.config.js`, that contain native code for a platform and that should also trigger install CocoaPods
+ const nativeDependencies = await getNativeDependencies(platformName);
+ const cacheKey = `pods-dependencies`;
+ const cachedDependenciesHash = cacheManager.get(cacheKey);
+ const podsDirExists = fs.existsSync(podsPath);
+ const hashChanged = cachedDependenciesHash
+ ? !compareMd5Hashes(calculateCurrentHash({ podfilePath, podsPath, nativeDependencies }), cachedDependenciesHash)
+ : true;
+ if (!podsDirExists || hashChanged) {
+ await runCodegen({ projectRoot, platformName, reactNativePath, sourceDir });
+ await installPods({
+ projectRoot,
+ sourceDir,
+ podfilePath,
+ newArch,
+ brownfield,
+ });
+ cacheManager.set(cacheKey, calculateCurrentHash({ podfilePath, podsPath, nativeDependencies }));
+ return true;
+ }
+ return false;
+}
+const calculateCurrentHash = ({ podfilePath, podsPath, nativeDependencies, }) => {
+ const podfileLockPath = podfilePath + '.lock';
+ const manifestLockPath = path.join(podsPath, 'Manifest.lock');
+ let podfile;
+ try {
+ podfile = fs.readFileSync(podfilePath, 'utf-8');
+ }
+ catch {
+ throw new RockError(`No Podfile found at: ${podfilePath}.
+${podErrorHelpMessage}`);
+ }
+ let podfileLock;
+ try {
+ podfileLock = fs.readFileSync(podfileLockPath, 'utf-8');
+ }
+ catch {
+ logger.debug('No Podfile.lock, continue');
+ }
+ return generateDependenciesHash([
+ generateMd5Hash(podfile),
+ generateMd5Hash(podfileLock ?? ''),
+ getLockfileChecksum(podfileLockPath),
+ getLockfileChecksum(manifestLockPath),
+ generateDependenciesHash(nativeDependencies),
+ ]);
+};
+async function runPodInstall(options) {
+ if (!options.useBundler) {
+ await validatePodCommand(options.sourceDir);
+ }
+ // Remove build folder to avoid codegen path clashes when developing native modules
+ if (fs.existsSync('./build')) {
+ fs.rmSync('build', { recursive: true });
+ }
+ const shouldHandleRepoUpdate = options?.shouldHandleRepoUpdate || true;
+ const loader = spinner({ indicator: 'timer' });
+ loader.start('Installing CocoaPods dependencies');
+ const reactNativeVersion = await getReactNativeVersion(options.projectRoot);
+ const isReactNative81OrHigher = reactNativeVersion.localeCompare('0.81.0', undefined, {
+ numeric: true,
+ sensitivity: 'base',
+ }) >= 0;
+ const usePrebuiltReactNative = !options.brownfield && isReactNative81OrHigher;
+ const command = options.useBundler ? 'bundle' : 'pod';
+ const args = options.useBundler ? ['exec', 'pod', 'install'] : ['install'];
+ try {
+ await spawn(command, args, {
+ env: {
+ RCT_NEW_ARCH_ENABLED: options.newArch ? '1' : '0',
+ RCT_IGNORE_PODS_DEPRECATION: '1',
+ RCT_USE_RN_DEP: process.env['RCT_USE_RN_DEP'] != undefined
+ ? String(process.env['RCT_USE_RN_DEP'])
+ : usePrebuiltReactNative ? '1' : '0',
+ RCT_USE_PREBUILT_RNCORE: process.env['RCT_USE_PREBUILT_RNCORE'] != undefined
+ ? String(process.env['RCT_USE_PREBUILT_RNCORE'])
+ : usePrebuiltReactNative ? '1' : '0',
+ ...(options.brownfield && { USE_FRAMEWORKS: 'static' }),
+ ...(process.env['USE_THIRD_PARTY_JSC'] && {
+ USE_THIRD_PARTY_JSC: process.env['USE_THIRD_PARTY_JSC'],
+ }),
+ },
+ cwd: options.sourceDir,
+ });
+ }
+ catch (error) {
+ loader.stop('Failed: Installing CocoaPods dependencies', 1);
+ const stderr = error.stderr;
+ const fullOutput = error.output;
+ let errorMessage = stderr;
+ /**
+ * CocoaPods occasionally provides a markdown template with error message.
+ * We don't need the part above the Error secion.
+ */
+ if (fullOutput.includes('### Error')) {
+ errorMessage = fullOutput.split('### Error')[1].trim();
+ }
+ /**
+ * If CocoaPods failed due to repo being out of date, it will
+ * include the update command in the error message.
+ *
+ * `shouldHandleRepoUpdate` will be set to `false` to
+ * prevent infinite loop (unlikely scenario)
+ */
+ if (fullOutput.includes('pod repo update') && shouldHandleRepoUpdate) {
+ await runPodUpdate(options.sourceDir, options.useBundler);
+ await runPodInstall({
+ shouldHandleRepoUpdate: false,
+ sourceDir: options.sourceDir,
+ newArch: options.newArch,
+ useBundler: options.useBundler,
+ brownfield: options.brownfield,
+ projectRoot: options.projectRoot,
+ });
+ }
+ else {
+ throw new RockError(`CocoaPods installation failed.
+${podErrorHelpMessage}`, { cause: errorMessage });
+ }
+ }
+ loader.stop('Installed CocoaPods dependencies successfully');
+}
+async function runPodUpdate(cwd, useBundler) {
+ const loader = spinner({ indicator: 'timer' });
+ try {
+ loader.start('Updating CocoaPods repositories');
+ if (useBundler) {
+ await spawn('bundle', ['exec', 'pod', 'repo', 'update'], { cwd });
+ }
+ else {
+ await spawn('pod', ['repo', 'update'], { cwd });
+ }
+ }
+ catch (error) {
+ const stderr = error.stderr || error.stdout;
+ loader.stop('Failed: Updating CocoaPods repositories', 1);
+ throw new RockError(`Failed to update CocoaPods repositories for iOS project.
+${podErrorHelpMessage}`, { cause: stderr });
+ }
+}
+async function installPods(options) {
+ if (!fs.existsSync(options.podfilePath)) {
+ logger.debug(`No Podfile at ${options.podfilePath}. Skipping pod installation.`);
+ return;
+ }
+ const useBundler = await runBundleInstall(options.sourceDir, options.projectRoot);
+ if (!useBundler) {
+ logger.info('Unable to use Ruby bundler, falling back to "pod install"');
+ }
+ await runPodInstall({
+ sourceDir: options.sourceDir,
+ newArch: options.newArch,
+ useBundler,
+ brownfield: options.brownfield,
+ projectRoot: options.projectRoot,
+ });
+}
+/*
+ * Check if "pod" is available and usable. It happens that there are
+ * multiple versions of "pod" command and even though it's there, it exits
+ * with a failure
+ */
+async function validatePodCommand(sourceDir) {
+ try {
+ await spawn('pod', ['--version'], { cwd: sourceDir });
+ }
+ catch (error) {
+ const cause = error.cause;
+ if (cause instanceof Error && cause.message.includes('ENOENT')) {
+ throw new RockError(`The "pod" command is not available.
+${podErrorHelpMessage}`);
+ }
+ const stderr = error.stderr || error.stdout;
+ throw new RockError(`CocoaPods "pod" command failed.
+${podErrorHelpMessage}`, { cause: stderr });
+ }
+}
+function checkGemfileForCocoaPods(gemfilePath) {
+ try {
+ const gemfileContent = fs.readFileSync(gemfilePath, 'utf-8');
+ // Check for common CocoaPods gem declarations, because some projects might have Gemfile but for other purposes
+ return /^\s*gem\s+['"]cocoapods['"]/m.test(gemfileContent);
+ }
+ catch (error) {
+ logger.debug(`Failed to read Gemfile at: ${gemfilePath}`);
+ logger.debug(error);
+ return false;
+ }
+}
+async function runBundleInstall(sourceDir, projectRoot) {
+ const gemfilePath = path.join(projectRoot, 'Gemfile');
+ if (!fs.existsSync(gemfilePath)) {
+ logger.debug(`Could not find the Gemfile at: ${colorLink(gemfilePath)}
+The default React Native Template uses Gemfile to leverage Ruby Bundler and we advice the same.
+If you use Gemfile, make sure it's ${color.bold('in the project root directory')}.
+Falling back to installing CocoaPods using globally installed "pod".`);
+ return false;
+ }
+ if (!checkGemfileForCocoaPods(gemfilePath)) {
+ logger.debug(`CocoaPods not found in Gemfile at: ${colorLink(gemfilePath)}
+skipping Ruby Gems installation.`);
+ return false;
+ }
+ const loader = spinner();
+ try {
+ loader.start('Installing Ruby Gems');
+ await spawn('bundle', ['install'], { cwd: sourceDir });
+ }
+ catch (error) {
+ const stderr = error.stderr || error.stdout;
+ loader.stop('Failed: Installing Ruby Gems', 1);
+ throw new RockError(`Failed to install Ruby Gems with "bundle install".
+${podErrorHelpMessage}`, { cause: stderr });
+ }
+ loader.stop('Installed Ruby Gems');
+ return true;
+}
+async function getNativeDependencies(platformName) {
+ const { loadConfigAsync } = await import('@react-native-community/cli-config');
+ const config = await loadConfigAsync({ selectedPlatform: platformName });
+ const dependencies = config.dependencies;
+ return Object.keys(dependencies)
+ .filter((dependency) => dependencies[dependency].platforms?.[platformName])
+ .map((dependency) => `${dependency}@${(dependencies[dependency].platforms?.[platformName]).version}`)
+ .sort();
+}
+function generateMd5Hash(text) {
+ return createHash('md5').update(text).digest('hex');
+}
+function compareMd5Hashes(hash1, hash2) {
+ return hash1 === hash2;
+}
+function generateDependenciesHash(deps) {
+ return generateMd5Hash(JSON.stringify(deps));
+}
+/**
+ * Gets the checksum of Podfile.lock or Pods/Manifest.lock
+ */
+function getLockfileChecksum(lockfilePath) {
+ try {
+ const checksumLine = fs
+ .readFileSync(lockfilePath, 'utf8')
+ .split('\n')
+ .find((line) => line.includes('PODFILE CHECKSUM'));
+ if (checksumLine) {
+ return checksumLine.split(': ')[1];
+ }
+ }
+ catch (error) {
+ logger.debug(`Failed to load the lockfile ${lockfilePath}`, error);
+ }
+ return '';
+}
+//# sourceMappingURL=pods.js.map
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/pods.js.map b/packages/platform-apple-helpers/dist/src/lib/utils/pods.js.map
new file mode 100644
index 000000000..ae9b5c6c6
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/utils/pods.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"pods.js","sourceRoot":"","sources":["../../../../src/lib/utils/pods.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/signingIdentities.d.ts b/packages/platform-apple-helpers/dist/src/lib/utils/signingIdentities.d.ts
new file mode 100644
index 000000000..284ef9ff7
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/utils/signingIdentities.d.ts
@@ -0,0 +1,16 @@
+export type SigningIdentity = {
+ hash: string;
+ name: string;
+};
+/**
+ * Input is in the form of:
+ * ```
+ * 1) 1234567890ABCDEF1234567890ABCDEF12345678 "Apple Development: John Doe (TEAMID1234)"
+ * 2) ABCDEF1234567890ABCDEF1234567890ABCDEF12 "Apple Distribution: Jane Smith (TEAMID5678)"
+ * ```
+ * @param output
+ * @returns
+ */
+export declare function parseSigningIdentities(output: string): SigningIdentity[];
+export declare function getValidSigningIdentities(): Promise;
+export declare function promptSigningIdentity(currentIdentity?: string | null): Promise;
diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/signingIdentities.js b/packages/platform-apple-helpers/dist/src/lib/utils/signingIdentities.js
new file mode 100644
index 000000000..150841cba
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/utils/signingIdentities.js
@@ -0,0 +1,52 @@
+import { promptSelect, RockError, spawn } from '@rock-js/tools';
+/**
+ * Input is in the form of:
+ * ```
+ * 1) 1234567890ABCDEF1234567890ABCDEF12345678 "Apple Development: John Doe (TEAMID1234)"
+ * 2) ABCDEF1234567890ABCDEF1234567890ABCDEF12 "Apple Distribution: Jane Smith (TEAMID5678)"
+ * ```
+ * @param output
+ * @returns
+ */
+export function parseSigningIdentities(output) {
+ const result = [];
+ const lines = output.split('\n');
+ const regex = /^\s*(\d+)\)\s+([A-F0-9]+)\s+"(.+)"$/;
+ for (const line of lines) {
+ const match = line.match(regex);
+ if (match) {
+ const hash = match[2];
+ const name = match[3];
+ result.push({ hash, name });
+ }
+ }
+ return result;
+}
+export async function getValidSigningIdentities() {
+ try {
+ const { output } = await spawn('security', ['find-identity', '-v', '-p', 'codesigning'], { stdio: 'pipe' });
+ return parseSigningIdentities(output);
+ }
+ catch (error) {
+ throw new RockError('Failed to load signing identities', {
+ cause: error,
+ });
+ }
+}
+export async function promptSigningIdentity(currentIdentity) {
+ const identities = await getValidSigningIdentities();
+ const current = currentIdentity
+ ? identities.find((i) => i.name === currentIdentity)
+ : undefined;
+ const other = identities.filter((i) => i.name !== currentIdentity);
+ const list = current ? [current, ...other] : other;
+ return await promptSelect({
+ message: 'Select a signing identity:',
+ options: list.map((identity) => ({
+ label: identity.name,
+ value: identity.name,
+ hint: identity.name === currentIdentity ? 'Current' : undefined,
+ })),
+ });
+}
+//# sourceMappingURL=signingIdentities.js.map
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/signingIdentities.js.map b/packages/platform-apple-helpers/dist/src/lib/utils/signingIdentities.js.map
new file mode 100644
index 000000000..7ce7e0989
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/utils/signingIdentities.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"signingIdentities.js","sourceRoot":"","sources":["../../../../src/lib/utils/signingIdentities.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAOhE;;;;;;;;GAQG;AACH,MAAM,UAAU,sBAAsB,CAAC,MAAc;IACnD,MAAM,MAAM,GAAsB,EAAE,CAAC;IACrC,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAEjC,MAAM,KAAK,GAAG,qCAAqC,CAAC;IAEpD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAChC,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YACtB,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YACtB,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,yBAAyB;IAC7C,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,KAAK,CAC5B,UAAU,EACV,CAAC,eAAe,EAAE,IAAI,EAAE,IAAI,EAAE,aAAa,CAAC,EAC5C,EAAE,KAAK,EAAE,MAAM,EAAE,CAClB,CAAC;QAEF,OAAO,sBAAsB,CAAC,MAAM,CAAC,CAAC;IACxC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CAAC,mCAAmC,EAAE;YACvD,KAAK,EAAE,KAAK;SACb,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,eAA+B;IACzE,MAAM,UAAU,GAAG,MAAM,yBAAyB,EAAE,CAAC;IAErD,MAAM,OAAO,GAAG,eAAe;QAC7B,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,eAAe,CAAC;QACpD,CAAC,CAAC,SAAS,CAAC;IACd,MAAM,KAAK,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,eAAe,CAAC,CAAC;IACnE,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IAEnD,OAAO,MAAM,YAAY,CAAC;QACxB,OAAO,EAAE,4BAA4B;QACrC,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;YAC/B,KAAK,EAAE,QAAQ,CAAC,IAAI;YACpB,KAAK,EAAE,QAAQ,CAAC,IAAI;YACpB,IAAI,EAAE,QAAQ,CAAC,IAAI,KAAK,eAAe,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;SAChE,CAAC,CAAC;KACJ,CAAC,CAAC;AACL,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/supportedPlatforms.d.ts b/packages/platform-apple-helpers/dist/src/lib/utils/supportedPlatforms.d.ts
new file mode 100644
index 000000000..fd245c515
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/utils/supportedPlatforms.d.ts
@@ -0,0 +1,6 @@
+export declare const supportedPlatforms: {
+ readonly ios: "ios";
+ readonly macos: "macos";
+ readonly visionos: "visionos";
+ readonly tvos: "tvos";
+};
diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/supportedPlatforms.js b/packages/platform-apple-helpers/dist/src/lib/utils/supportedPlatforms.js
new file mode 100644
index 000000000..4d05348a9
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/utils/supportedPlatforms.js
@@ -0,0 +1,7 @@
+export const supportedPlatforms = {
+ ios: 'ios',
+ macos: 'macos',
+ visionos: 'visionos',
+ tvos: 'tvos',
+};
+//# sourceMappingURL=supportedPlatforms.js.map
\ No newline at end of file
diff --git a/packages/platform-apple-helpers/dist/src/lib/utils/supportedPlatforms.js.map b/packages/platform-apple-helpers/dist/src/lib/utils/supportedPlatforms.js.map
new file mode 100644
index 000000000..80cc708d5
--- /dev/null
+++ b/packages/platform-apple-helpers/dist/src/lib/utils/supportedPlatforms.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"supportedPlatforms.js","sourceRoot":"","sources":["../../../../src/lib/utils/supportedPlatforms.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,GAAG,EAAE,KAAK;IACV,KAAK,EAAE,OAAO;IACd,QAAQ,EAAE,UAAU;IACpB,IAAI,EAAE,MAAM;CACJ,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-harmony/dist/src/index.d.ts b/packages/platform-harmony/dist/src/index.d.ts
new file mode 100644
index 000000000..91ed5743c
--- /dev/null
+++ b/packages/platform-harmony/dist/src/index.d.ts
@@ -0,0 +1 @@
+export * from './lib/platformHarmony.js';
diff --git a/packages/platform-harmony/dist/src/index.js b/packages/platform-harmony/dist/src/index.js
new file mode 100644
index 000000000..1b66e2ace
--- /dev/null
+++ b/packages/platform-harmony/dist/src/index.js
@@ -0,0 +1,2 @@
+export * from './lib/platformHarmony.js';
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/packages/platform-harmony/dist/src/index.js.map b/packages/platform-harmony/dist/src/index.js.map
new file mode 100644
index 000000000..eeccc5d6f
--- /dev/null
+++ b/packages/platform-harmony/dist/src/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-harmony/dist/src/lib/commands/build/buildHarmony.d.ts b/packages/platform-harmony/dist/src/lib/commands/build/buildHarmony.d.ts
new file mode 100644
index 000000000..09cab8bbb
--- /dev/null
+++ b/packages/platform-harmony/dist/src/lib/commands/build/buildHarmony.d.ts
@@ -0,0 +1,21 @@
+import type { RemoteBuildCache } from '@rock-js/tools';
+import { type FingerprintSources } from '@rock-js/tools';
+export interface BuildFlags {
+ buildMode: string;
+ module: string;
+ product: string;
+ local?: boolean;
+}
+export declare function buildHarmony(harmonyConfig: {
+ sourceDir: string;
+ bundleName: string;
+}, args: BuildFlags, projectRoot: string, remoteCacheProvider: null | (() => RemoteBuildCache) | undefined, fingerprintOptions: FingerprintSources): Promise;
+export declare const options: ({
+ name: string;
+ description: string;
+ default?: undefined;
+} | {
+ name: string;
+ description: string;
+ default: string;
+})[];
diff --git a/packages/platform-harmony/dist/src/lib/commands/build/buildHarmony.js b/packages/platform-harmony/dist/src/lib/commands/build/buildHarmony.js
new file mode 100644
index 000000000..efe162b2e
--- /dev/null
+++ b/packages/platform-harmony/dist/src/lib/commands/build/buildHarmony.js
@@ -0,0 +1,69 @@
+import { colorLink, formatArtifactName, getBinaryPath, logger, outro, relativeToCwd, } from '@rock-js/tools';
+import { findOutputFile } from '../run/findOutputFile.js';
+import { runHvigor } from '../runHvigor.js';
+export async function buildHarmony(harmonyConfig, args, projectRoot, remoteCacheProvider, fingerprintOptions) {
+ const { sourceDir, bundleName } = harmonyConfig;
+ const artifactName = await formatArtifactName({
+ platform: 'harmony',
+ traits: [args.buildMode],
+ root: projectRoot,
+ fingerprintOptions,
+ });
+ const binaryPath = await getBinaryPath({
+ platformName: 'harmony',
+ artifactName,
+ localFlag: args.local,
+ remoteCacheProvider,
+ fingerprintOptions,
+ sourceDir,
+ });
+ if (!binaryPath) {
+ await runHvigor({ sourceDir, args, artifactName, bundleName });
+ }
+ if (binaryPath) {
+ logger.log(`Build available at: ${colorLink(relativeToCwd(binaryPath))}`);
+ }
+ else {
+ const signedHapPath = await findOutputFile(sourceDir, args.module, {
+ deviceId: undefined,
+ readableName: undefined,
+ type: 'phone',
+ connected: false,
+ });
+ if (signedHapPath) {
+ logger.log(`Signed build available at: ${colorLink(relativeToCwd(signedHapPath))}`);
+ }
+ const unsignedHapPath = await findOutputFile(sourceDir, args.module, {
+ deviceId: undefined,
+ readableName: undefined,
+ type: 'emulator',
+ connected: false,
+ });
+ if (unsignedHapPath) {
+ logger.log(`Unsigned build available at: ${colorLink(relativeToCwd(unsignedHapPath))}`);
+ }
+ }
+ outro('Success ๐.');
+}
+export const options = [
+ {
+ name: '--local',
+ description: 'Force local build with Gradle wrapper.',
+ },
+ {
+ name: '--module ',
+ description: 'Name of the OH module to run.',
+ default: 'entry',
+ },
+ {
+ name: '--build-mode ',
+ description: `Specify your app's build mode, e.g. "debug" or "release".`,
+ default: 'debug',
+ },
+ {
+ name: '--product ',
+ description: 'OpenHarmony product defined in build-profile.json5.',
+ default: 'default',
+ },
+];
+//# sourceMappingURL=buildHarmony.js.map
\ No newline at end of file
diff --git a/packages/platform-harmony/dist/src/lib/commands/build/buildHarmony.js.map b/packages/platform-harmony/dist/src/lib/commands/build/buildHarmony.js.map
new file mode 100644
index 000000000..1f6552c4f
--- /dev/null
+++ b/packages/platform-harmony/dist/src/lib/commands/build/buildHarmony.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"buildHarmony.js","sourceRoot":"","sources":["../../../../../src/lib/commands/build/buildHarmony.ts"],"names":[],"mappings":"AACA,OAAO,EACL,SAAS,EAET,kBAAkB,EAClB,aAAa,EACb,MAAM,EACN,KAAK,EACL,aAAa,GACd,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAS5C,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,aAGC,EACD,IAAgB,EAChB,WAAmB,EACnB,mBAAgE,EAChE,kBAAsC;IAEtC,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,aAAa,CAAC;IAChD,MAAM,YAAY,GAAG,MAAM,kBAAkB,CAAC;QAC5C,QAAQ,EAAE,SAAS;QACnB,MAAM,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC;QACxB,IAAI,EAAE,WAAW;QACjB,kBAAkB;KACnB,CAAC,CAAC;IACH,MAAM,UAAU,GAAG,MAAM,aAAa,CAAC;QACrC,YAAY,EAAE,SAAS;QACvB,YAAY;QACZ,SAAS,EAAE,IAAI,CAAC,KAAK;QACrB,mBAAmB;QACnB,kBAAkB;QAClB,SAAS;KACV,CAAC,CAAC;IACH,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,SAAS,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC,CAAC;IACjE,CAAC;IAED,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,CAAC,GAAG,CAAC,uBAAuB,SAAS,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC;IAC5E,CAAC;SAAM,CAAC;QACN,MAAM,aAAa,GAAG,MAAM,cAAc,CAAC,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE;YACjE,QAAQ,EAAE,SAAS;YACnB,YAAY,EAAE,SAAS;YACvB,IAAI,EAAE,OAAO;YACb,SAAS,EAAE,KAAK;SACjB,CAAC,CAAC;QACH,IAAI,aAAa,EAAE,CAAC;YAClB,MAAM,CAAC,GAAG,CACR,8BAA8B,SAAS,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,EAAE,CACxE,CAAC;QACJ,CAAC;QACD,MAAM,eAAe,GAAG,MAAM,cAAc,CAAC,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE;YACnE,QAAQ,EAAE,SAAS;YACnB,YAAY,EAAE,SAAS;YACvB,IAAI,EAAE,UAAU;YAChB,SAAS,EAAE,KAAK;SACjB,CAAC,CAAC;QACH,IAAI,eAAe,EAAE,CAAC;YACpB,MAAM,CAAC,GAAG,CACR,gCAAgC,SAAS,CAAC,aAAa,CAAC,eAAe,CAAC,CAAC,EAAE,CAC5E,CAAC;QACJ,CAAC;IACH,CAAC;IACD,KAAK,CAAC,aAAa,CAAC,CAAC;AACvB,CAAC;AAED,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB;QACE,IAAI,EAAE,SAAS;QACf,WAAW,EAAE,wCAAwC;KACtD;IACD;QACE,IAAI,EAAE,mBAAmB;QACzB,WAAW,EAAE,+BAA+B;QAC5C,OAAO,EAAE,OAAO;KACjB;IACD;QACE,IAAI,EAAE,uBAAuB;QAC7B,WAAW,EAAE,2DAA2D;QACxE,OAAO,EAAE,OAAO;KACjB;IACD;QACE,IAAI,EAAE,oBAAoB;QAC1B,WAAW,EAAE,qDAAqD;QAClE,OAAO,EAAE,SAAS;KACnB;CACF,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-harmony/dist/src/lib/commands/build/command.d.ts b/packages/platform-harmony/dist/src/lib/commands/build/command.d.ts
new file mode 100644
index 000000000..7348c6abb
--- /dev/null
+++ b/packages/platform-harmony/dist/src/lib/commands/build/command.d.ts
@@ -0,0 +1,3 @@
+import type { PluginApi } from '@rock-js/config';
+import { type HarmonyProjectConfig } from '../getValidProjectConfig.js';
+export declare function registerBuildCommand(api: PluginApi, pluginConfig: Partial | undefined): void;
diff --git a/packages/platform-harmony/dist/src/lib/commands/build/command.js b/packages/platform-harmony/dist/src/lib/commands/build/command.js
new file mode 100644
index 000000000..0140960c2
--- /dev/null
+++ b/packages/platform-harmony/dist/src/lib/commands/build/command.js
@@ -0,0 +1,15 @@
+import { getValidProjectConfig, } from '../getValidProjectConfig.js';
+import { buildHarmony, options } from './buildHarmony.js';
+export function registerBuildCommand(api, pluginConfig) {
+ api.registerCommand({
+ name: 'build:harmony',
+ description: 'Builds your app for HarmonyOS Next platform.',
+ action: async (args) => {
+ const projectRoot = api.getProjectRoot();
+ const harmonyConfig = getValidProjectConfig(projectRoot, pluginConfig);
+ await buildHarmony(harmonyConfig, args, projectRoot, await api.getRemoteCacheProvider(), api.getFingerprintOptions());
+ },
+ options: options,
+ });
+}
+//# sourceMappingURL=command.js.map
\ No newline at end of file
diff --git a/packages/platform-harmony/dist/src/lib/commands/build/command.js.map b/packages/platform-harmony/dist/src/lib/commands/build/command.js.map
new file mode 100644
index 000000000..db26a6989
--- /dev/null
+++ b/packages/platform-harmony/dist/src/lib/commands/build/command.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"command.js","sourceRoot":"","sources":["../../../../../src/lib/commands/build/command.ts"],"names":[],"mappings":"AACA,OAAO,EACL,qBAAqB,GAEtB,MAAM,6BAA6B,CAAC;AAErC,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAE1D,MAAM,UAAU,oBAAoB,CAClC,GAAc,EACd,YAAuD;IAEvD,GAAG,CAAC,eAAe,CAAC;QAClB,IAAI,EAAE,eAAe;QACrB,WAAW,EAAE,8CAA8C;QAC3D,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YACrB,MAAM,WAAW,GAAG,GAAG,CAAC,cAAc,EAAE,CAAC;YACzC,MAAM,aAAa,GAAG,qBAAqB,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;YACvE,MAAM,YAAY,CAChB,aAAa,EACb,IAAkB,EAClB,WAAW,EACX,MAAM,GAAG,CAAC,sBAAsB,EAAE,EAClC,GAAG,CAAC,qBAAqB,EAAE,CAC5B,CAAC;QACJ,CAAC;QACD,OAAO,EAAE,OAAO;KACjB,CAAC,CAAC;AACL,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-harmony/dist/src/lib/commands/getValidProjectConfig.d.ts b/packages/platform-harmony/dist/src/lib/commands/getValidProjectConfig.d.ts
new file mode 100644
index 000000000..651bf3a3a
--- /dev/null
+++ b/packages/platform-harmony/dist/src/lib/commands/getValidProjectConfig.d.ts
@@ -0,0 +1,10 @@
+export type HarmonyProjectConfig = {
+ sourceDir: string;
+ bundleName: string;
+ signingConfigs: boolean | undefined;
+};
+export declare function getValidProjectConfig(projectRoot: string, pluginConfig?: Partial): {
+ sourceDir: string;
+ bundleName: string;
+ signingConfigs: boolean | undefined;
+};
diff --git a/packages/platform-harmony/dist/src/lib/commands/getValidProjectConfig.js b/packages/platform-harmony/dist/src/lib/commands/getValidProjectConfig.js
new file mode 100644
index 000000000..5aea3531b
--- /dev/null
+++ b/packages/platform-harmony/dist/src/lib/commands/getValidProjectConfig.js
@@ -0,0 +1,39 @@
+import fs from 'node:fs';
+import path from 'node:path';
+import { logger, RockError } from '@rock-js/tools';
+import json5 from 'json5';
+export function getValidProjectConfig(projectRoot, pluginConfig) {
+ const sourceDir = pluginConfig?.sourceDir
+ ? path.isAbsolute(pluginConfig?.sourceDir)
+ ? pluginConfig?.sourceDir
+ : path.join(projectRoot, pluginConfig?.sourceDir)
+ : path.join(projectRoot, 'harmony');
+ if (!fs.existsSync(sourceDir)) {
+ throw new RockError(`Harmony project not found under ${sourceDir}.`);
+ }
+ let bundleName;
+ try {
+ bundleName = json5.parse(fs.readFileSync(path.join(sourceDir, 'AppScope', 'app.json5'), 'utf8')).app.bundleName;
+ }
+ catch (error) {
+ throw new RockError('Error reading app.json5 file.', {
+ cause: error,
+ });
+ }
+ let signingConfigs;
+ try {
+ const buildProfile = json5.parse(fs.readFileSync(path.join(sourceDir, 'build-profile.json5'), 'utf8'));
+ signingConfigs = Boolean(buildProfile.app.signingConfigs);
+ }
+ catch (error) {
+ logger.debug('Error reading build-profile.json5 file.', {
+ cause: error.message,
+ });
+ }
+ return {
+ sourceDir,
+ bundleName,
+ signingConfigs,
+ };
+}
+//# sourceMappingURL=getValidProjectConfig.js.map
\ No newline at end of file
diff --git a/packages/platform-harmony/dist/src/lib/commands/getValidProjectConfig.js.map b/packages/platform-harmony/dist/src/lib/commands/getValidProjectConfig.js.map
new file mode 100644
index 000000000..a6137a9c1
--- /dev/null
+++ b/packages/platform-harmony/dist/src/lib/commands/getValidProjectConfig.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"getValidProjectConfig.js","sourceRoot":"","sources":["../../../../src/lib/commands/getValidProjectConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,KAAK,MAAM,OAAO,CAAC;AAQ1B,MAAM,UAAU,qBAAqB,CACnC,WAAmB,EACnB,YAA4C;IAE5C,MAAM,SAAS,GAAG,YAAY,EAAE,SAAS;QACvC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,YAAY,EAAE,SAAS,CAAC;YACxC,CAAC,CAAC,YAAY,EAAE,SAAS;YACzB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,YAAY,EAAE,SAAS,CAAC;QACnD,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;IAEtC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,SAAS,CAAC,mCAAmC,SAAS,GAAG,CAAC,CAAC;IACvE,CAAC;IAED,IAAI,UAAkB,CAAC;IACvB,IAAI,CAAC;QACH,UAAU,GAAG,KAAK,CAAC,KAAK,CACtB,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,EAAE,WAAW,CAAC,EAAE,MAAM,CAAC,CACvE,CAAC,GAAG,CAAC,UAAU,CAAC;IACnB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CAAC,+BAA+B,EAAE;YACnD,KAAK,EAAE,KAAK;SACb,CAAC,CAAC;IACL,CAAC;IAED,IAAI,cAAc,CAAC;IACnB,IAAI,CAAC;QACH,MAAM,YAAY,GAAG,KAAK,CAAC,KAAK,CAC9B,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,qBAAqB,CAAC,EAAE,MAAM,CAAC,CACrE,CAAC;QACF,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAC5D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,yCAAyC,EAAE;YACtD,KAAK,EAAG,KAAe,CAAC,OAAO;SAChC,CAAC,CAAC;IACL,CAAC;IAED,OAAO;QACL,SAAS;QACT,UAAU;QACV,cAAc;KACf,CAAC;AACJ,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-harmony/dist/src/lib/commands/run/command.d.ts b/packages/platform-harmony/dist/src/lib/commands/run/command.d.ts
new file mode 100644
index 000000000..a5329d651
--- /dev/null
+++ b/packages/platform-harmony/dist/src/lib/commands/run/command.d.ts
@@ -0,0 +1,3 @@
+import type { PluginApi } from '@rock-js/config';
+import { type HarmonyProjectConfig } from '../getValidProjectConfig.js';
+export declare function registerRunCommand(api: PluginApi, pluginConfig: Partial | undefined): void;
diff --git a/packages/platform-harmony/dist/src/lib/commands/run/command.js b/packages/platform-harmony/dist/src/lib/commands/run/command.js
new file mode 100644
index 000000000..88a0cbc62
--- /dev/null
+++ b/packages/platform-harmony/dist/src/lib/commands/run/command.js
@@ -0,0 +1,15 @@
+import { getValidProjectConfig, } from '../getValidProjectConfig.js';
+import { runHarmony, runOptions } from './runHarmony.js';
+export function registerRunCommand(api, pluginConfig) {
+ api.registerCommand({
+ name: 'run:harmony',
+ description: 'Builds your app and starts it on a connected HarmonyOS Next device.',
+ action: async (args) => {
+ const projectRoot = api.getProjectRoot();
+ const harmonyConfig = getValidProjectConfig(projectRoot, pluginConfig);
+ await runHarmony(harmonyConfig, args, projectRoot, await api.getRemoteCacheProvider(), api.getFingerprintOptions());
+ },
+ options: runOptions,
+ });
+}
+//# sourceMappingURL=command.js.map
\ No newline at end of file
diff --git a/packages/platform-harmony/dist/src/lib/commands/run/command.js.map b/packages/platform-harmony/dist/src/lib/commands/run/command.js.map
new file mode 100644
index 000000000..936629338
--- /dev/null
+++ b/packages/platform-harmony/dist/src/lib/commands/run/command.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"command.js","sourceRoot":"","sources":["../../../../../src/lib/commands/run/command.ts"],"names":[],"mappings":"AACA,OAAO,EACL,qBAAqB,GAEtB,MAAM,6BAA6B,CAAC;AAErC,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAEzD,MAAM,UAAU,kBAAkB,CAChC,GAAc,EACd,YAAuD;IAEvD,GAAG,CAAC,eAAe,CAAC;QAClB,IAAI,EAAE,aAAa;QACnB,WAAW,EACT,qEAAqE;QACvE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YACrB,MAAM,WAAW,GAAG,GAAG,CAAC,cAAc,EAAE,CAAC;YACzC,MAAM,aAAa,GAAG,qBAAqB,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;YACvE,MAAM,UAAU,CACd,aAAa,EACb,IAAa,EACb,WAAW,EACX,MAAM,GAAG,CAAC,sBAAsB,EAAE,EAClC,GAAG,CAAC,qBAAqB,EAAE,CAC5B,CAAC;QACJ,CAAC;QACD,OAAO,EAAE,UAAU;KACpB,CAAC,CAAC;AACL,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-harmony/dist/src/lib/commands/run/findOutputFile.d.ts b/packages/platform-harmony/dist/src/lib/commands/run/findOutputFile.d.ts
new file mode 100644
index 000000000..cb68d6678
--- /dev/null
+++ b/packages/platform-harmony/dist/src/lib/commands/run/findOutputFile.d.ts
@@ -0,0 +1,2 @@
+import type { DeviceData } from './listHarmonyDevices.js';
+export declare function findOutputFile(sourceDir: string, module: string, device?: DeviceData): Promise;
diff --git a/packages/platform-harmony/dist/src/lib/commands/run/findOutputFile.js b/packages/platform-harmony/dist/src/lib/commands/run/findOutputFile.js
new file mode 100644
index 000000000..da5e6292c
--- /dev/null
+++ b/packages/platform-harmony/dist/src/lib/commands/run/findOutputFile.js
@@ -0,0 +1,14 @@
+import fs from 'node:fs';
+import path from 'node:path';
+export async function findOutputFile(sourceDir, module, device) {
+ let hapName;
+ if (device?.type === 'emulator') {
+ hapName = `${module}-default-unsigned.hap`;
+ }
+ else {
+ hapName = `${module}-default-signed.hap`;
+ }
+ const pathToHap = path.join(sourceDir, module, 'build', 'default', 'outputs', 'default', hapName);
+ return fs.existsSync(pathToHap) ? pathToHap : undefined;
+}
+//# sourceMappingURL=findOutputFile.js.map
\ No newline at end of file
diff --git a/packages/platform-harmony/dist/src/lib/commands/run/findOutputFile.js.map b/packages/platform-harmony/dist/src/lib/commands/run/findOutputFile.js.map
new file mode 100644
index 000000000..d4772032d
--- /dev/null
+++ b/packages/platform-harmony/dist/src/lib/commands/run/findOutputFile.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"findOutputFile.js","sourceRoot":"","sources":["../../../../../src/lib/commands/run/findOutputFile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,SAAiB,EACjB,MAAc,EACd,MAAmB;IAEnB,IAAI,OAAe,CAAC;IACpB,IAAI,MAAM,EAAE,IAAI,KAAK,UAAU,EAAE,CAAC;QAChC,OAAO,GAAG,GAAG,MAAM,uBAAuB,CAAC;IAC7C,CAAC;SAAM,CAAC;QACN,OAAO,GAAG,GAAG,MAAM,qBAAqB,CAAC;IAC3C,CAAC;IACD,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CACzB,SAAS,EACT,MAAM,EACN,OAAO,EACP,SAAS,EACT,SAAS,EACT,SAAS,EACT,OAAO,CACR,CAAC;IACF,OAAO,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;AAC1D,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-harmony/dist/src/lib/commands/run/hdc.d.ts b/packages/platform-harmony/dist/src/lib/commands/run/hdc.d.ts
new file mode 100644
index 000000000..469bb63e0
--- /dev/null
+++ b/packages/platform-harmony/dist/src/lib/commands/run/hdc.d.ts
@@ -0,0 +1,11 @@
+export declare function getHdcPath(): string;
+/**
+ * Executes the commands needed to get a list of devices from ADB
+ */
+export declare function getDevices(): Promise<{
+ name: string;
+ method: string;
+ state: string;
+ locate: string;
+ connectTool: string;
+}[]>;
diff --git a/packages/platform-harmony/dist/src/lib/commands/run/hdc.js b/packages/platform-harmony/dist/src/lib/commands/run/hdc.js
new file mode 100644
index 000000000..af3fa25db
--- /dev/null
+++ b/packages/platform-harmony/dist/src/lib/commands/run/hdc.js
@@ -0,0 +1,35 @@
+import path from 'node:path';
+import { spawn } from '@rock-js/tools';
+import { getDevEcoSdkPath } from '../../paths.js';
+export function getHdcPath() {
+ return path.join(getDevEcoSdkPath(), 'default', 'openharmony', 'toolchains', 'hdc');
+}
+/**
+ * Executes the commands needed to get a list of devices from ADB
+ */
+export async function getDevices() {
+ const hdcPath = getHdcPath();
+ try {
+ const { output } = await spawn(hdcPath, ['list', 'targets', '-v'], {
+ stdio: 'pipe',
+ });
+ const lines = output.trim().split('\n');
+ return (lines
+ .map((line) => {
+ const parts = line.split(/\s+/);
+ return {
+ name: parts[0],
+ method: parts[1], // USB
+ state: parts[2], // Connected, Offline
+ locate: parts[3], // localhost
+ connectTool: parts[4],
+ };
+ })
+ // hdc will report no devices as [Empty] sometimes
+ .filter((line) => line.state != undefined));
+ }
+ catch {
+ return [];
+ }
+}
+//# sourceMappingURL=hdc.js.map
\ No newline at end of file
diff --git a/packages/platform-harmony/dist/src/lib/commands/run/hdc.js.map b/packages/platform-harmony/dist/src/lib/commands/run/hdc.js.map
new file mode 100644
index 000000000..37f0efaa6
--- /dev/null
+++ b/packages/platform-harmony/dist/src/lib/commands/run/hdc.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"hdc.js","sourceRoot":"","sources":["../../../../../src/lib/commands/run/hdc.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAElD,MAAM,UAAU,UAAU;IACxB,OAAO,IAAI,CAAC,IAAI,CACd,gBAAgB,EAAE,EAClB,SAAS,EACT,aAAa,EACb,YAAY,EACZ,KAAK,CACN,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,EAAE;YACjE,KAAK,EAAE,MAAM;SACd,CAAC,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACxC,OAAO,CACL,KAAK;aACF,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;YACZ,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAChC,OAAO;gBACL,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;gBACd,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,MAAM;gBACxB,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,qBAAqB;gBACtC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,YAAY;gBAC9B,WAAW,EAAE,KAAK,CAAC,CAAC,CAAC;aACtB,CAAC;QACJ,CAAC,CAAC;YACF,kDAAkD;aACjD,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,IAAI,SAAS,CAAC,CAC7C,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-harmony/dist/src/lib/commands/run/listHarmonyDevices.d.ts b/packages/platform-harmony/dist/src/lib/commands/run/listHarmonyDevices.d.ts
new file mode 100644
index 000000000..fd20f8c6e
--- /dev/null
+++ b/packages/platform-harmony/dist/src/lib/commands/run/listHarmonyDevices.d.ts
@@ -0,0 +1,7 @@
+export type DeviceData = {
+ deviceId: string | undefined;
+ readableName: string | undefined;
+ connected: boolean;
+ type: 'emulator' | 'phone';
+};
+export declare function listHarmonyDevices(): Promise;
diff --git a/packages/platform-harmony/dist/src/lib/commands/run/listHarmonyDevices.js b/packages/platform-harmony/dist/src/lib/commands/run/listHarmonyDevices.js
new file mode 100644
index 000000000..447842596
--- /dev/null
+++ b/packages/platform-harmony/dist/src/lib/commands/run/listHarmonyDevices.js
@@ -0,0 +1,17 @@
+import { getDevices } from './hdc.js';
+export async function listHarmonyDevices() {
+ const devices = await getDevices();
+ const allDevices = [];
+ for (const device of devices) {
+ const phoneData = {
+ deviceId: device.name,
+ // @todo get readable name
+ readableName: device.name,
+ type: 'phone',
+ connected: device.state === 'Connected',
+ };
+ allDevices.push(phoneData);
+ }
+ return allDevices;
+}
+//# sourceMappingURL=listHarmonyDevices.js.map
\ No newline at end of file
diff --git a/packages/platform-harmony/dist/src/lib/commands/run/listHarmonyDevices.js.map b/packages/platform-harmony/dist/src/lib/commands/run/listHarmonyDevices.js.map
new file mode 100644
index 000000000..dd63c8617
--- /dev/null
+++ b/packages/platform-harmony/dist/src/lib/commands/run/listHarmonyDevices.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"listHarmonyDevices.js","sourceRoot":"","sources":["../../../../../src/lib/commands/run/listHarmonyDevices.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAStC,MAAM,CAAC,KAAK,UAAU,kBAAkB;IACtC,MAAM,OAAO,GAAG,MAAM,UAAU,EAAE,CAAC;IAEnC,MAAM,UAAU,GAAsB,EAAE,CAAC;IAEzC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,SAAS,GAAe;YAC5B,QAAQ,EAAE,MAAM,CAAC,IAAI;YACrB,0BAA0B;YAC1B,YAAY,EAAE,MAAM,CAAC,IAAI;YACzB,IAAI,EAAE,OAAO;YACb,SAAS,EAAE,MAAM,CAAC,KAAK,KAAK,WAAW;SACxC,CAAC;QACF,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC7B,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-harmony/dist/src/lib/commands/run/runHarmony.d.ts b/packages/platform-harmony/dist/src/lib/commands/run/runHarmony.d.ts
new file mode 100644
index 000000000..b515f5a3e
--- /dev/null
+++ b/packages/platform-harmony/dist/src/lib/commands/run/runHarmony.d.ts
@@ -0,0 +1,24 @@
+import type { FingerprintSources, RemoteBuildCache } from '@rock-js/tools';
+import type { BuildFlags } from '../build/buildHarmony.js';
+export interface Flags extends BuildFlags {
+ ability: string;
+ port: string;
+ device?: string;
+ binaryPath?: string;
+}
+/**
+ * Starts the app on a connected HarmonyOS emulator or device.
+ */
+export declare function runHarmony(harmonyConfig: {
+ sourceDir: string;
+ bundleName: string;
+}, args: Flags, projectRoot: string, remoteCacheProvider: null | (() => RemoteBuildCache) | undefined, fingerprintOptions: FingerprintSources): Promise;
+export declare const runOptions: ({
+ name: string;
+ description: string;
+ default?: undefined;
+} | {
+ name: string;
+ description: string;
+ default: string;
+})[];
diff --git a/packages/platform-harmony/dist/src/lib/commands/run/runHarmony.js b/packages/platform-harmony/dist/src/lib/commands/run/runHarmony.js
new file mode 100644
index 000000000..0e6a43275
--- /dev/null
+++ b/packages/platform-harmony/dist/src/lib/commands/run/runHarmony.js
@@ -0,0 +1,148 @@
+import fs from 'node:fs';
+import path from 'node:path';
+import { color, formatArtifactName, intro, isInteractive, logger, outro, promptSelect, RockError, spinner, } from '@rock-js/tools';
+import { getBinaryPath } from '@rock-js/tools';
+import { options } from '../build/buildHarmony.js';
+import { runHvigor } from '../runHvigor.js';
+import { getDevices } from './hdc.js';
+import { listHarmonyDevices } from './listHarmonyDevices.js';
+import { tryInstallAppOnDevice } from './tryInstallAppOnDevice.js';
+import { tryLaunchAppOnDevice } from './tryLaunchAppOnDevice.js';
+/**
+ * Starts the app on a connected HarmonyOS emulator or device.
+ */
+export async function runHarmony(harmonyConfig, args, projectRoot, remoteCacheProvider, fingerprintOptions) {
+ intro('Running HarmonyOS Next app');
+ normalizeArgs(args, projectRoot);
+ const { sourceDir, bundleName } = harmonyConfig;
+ const devices = await listHarmonyDevices();
+ const device = await selectDevice(devices, args);
+ const artifactName = await formatArtifactName({
+ platform: 'harmony',
+ traits: [args.buildMode],
+ root: projectRoot,
+ fingerprintOptions,
+ });
+ const binaryPath = await getBinaryPath({
+ platformName: 'harmony',
+ artifactName,
+ binaryPathFlag: args.binaryPath,
+ localFlag: args.local,
+ remoteCacheProvider,
+ fingerprintOptions,
+ sourceDir: sourceDir,
+ });
+ if (device) {
+ if (device.deviceId) {
+ if (!binaryPath) {
+ await runHvigor({ sourceDir, args, artifactName, device, bundleName });
+ }
+ await runOnDevice({ device, sourceDir, args, binaryPath, bundleName });
+ }
+ }
+ else {
+ if ((await getDevices()).length === 0) {
+ if (isInteractive()) {
+ await selectAndLaunchDevice();
+ }
+ else {
+ logger.warn('No booted devices or emulators found. Launching first available emulator.');
+ // @todo add emulators
+ }
+ }
+ if (!binaryPath) {
+ await runHvigor({ sourceDir, args, artifactName, bundleName });
+ }
+ for (const device of await listHarmonyDevices()) {
+ if (device.connected) {
+ await runOnDevice({ device, sourceDir, args, binaryPath, bundleName });
+ }
+ }
+ }
+ outro('Success ๐.');
+}
+async function selectAndLaunchDevice() {
+ const allDevices = await listHarmonyDevices();
+ const device = await promptForDeviceSelection(allDevices);
+ if (!device.connected) {
+ // @todo add emulators
+ // list devices once again when emulator is booted
+ const allDevices = await listHarmonyDevices();
+ const newDevice = allDevices.find((d) => d.readableName === device.readableName) ?? device;
+ return newDevice;
+ }
+ return device;
+}
+async function selectDevice(devices, args) {
+ const device = args.device ? matchingDevice(devices, args.device) : undefined;
+ if (!device && args.device) {
+ logger.warn(`No devices or emulators found matching "${args.device}". Using available one instead.`);
+ }
+ return device;
+}
+function matchingDevice(devices, deviceArg) {
+ const deviceByName = devices.find((device) => device.readableName === deviceArg);
+ const deviceById = devices.find((d) => d.deviceId === deviceArg);
+ return deviceByName || deviceById;
+}
+function normalizeArgs(args, projectRoot) {
+ if (args.binaryPath) {
+ args.binaryPath = path.isAbsolute(args.binaryPath)
+ ? args.binaryPath
+ : path.join(projectRoot, args.binaryPath);
+ if (args.binaryPath && !fs.existsSync(args.binaryPath)) {
+ throw new RockError(`"--binary-path" was specified, but the file was not found at "${args.binaryPath}".`);
+ }
+ }
+}
+async function promptForDeviceSelection(allDevices) {
+ if (!allDevices.length) {
+ throw new RockError(
+ // @todo add emulators
+ 'No devices connected. Please create connect HarmonyOS device.');
+ }
+ const selected = await promptSelect({
+ // @todo add emulators
+ message: 'Select the device you want to use',
+ options: allDevices.map((d) => ({
+ label: `${d.readableName}${d.type === 'phone' ? ' - (physical device)' : ''}${d.connected ? ' (connected)' : ''}`,
+ value: d,
+ })),
+ });
+ return selected;
+}
+async function runOnDevice({ device, sourceDir, args, binaryPath, bundleName, }) {
+ const loader = spinner();
+ loader.start('Installing the app');
+ await tryInstallAppOnDevice(device, sourceDir, args, binaryPath);
+ loader.message('Launching the app');
+ const { applicationIdWithSuffix } = await tryLaunchAppOnDevice(device, bundleName, args);
+ if (applicationIdWithSuffix) {
+ loader.stop(`Installed and launched the app on ${color.bold(device.readableName)}`);
+ }
+ else {
+ loader.stop(`Failed: installing and launching the app on ${color.bold(device.readableName)}`);
+ }
+}
+export const runOptions = [
+ ...options,
+ {
+ name: '--port ',
+ description: 'Part for packager.',
+ default: process.env['RCT_METRO_PORT'] || '8081',
+ },
+ {
+ name: '--ability ',
+ description: 'Name of the ability to start.',
+ default: 'EntryAbility',
+ },
+ {
+ name: '--device ',
+ description: 'Explicitly set the device or emulator to use by name or ID (if launched).',
+ },
+ {
+ name: '--binary-path ',
+ description: 'Path relative to project root where pre-built .apk binary lives.',
+ },
+];
+//# sourceMappingURL=runHarmony.js.map
\ No newline at end of file
diff --git a/packages/platform-harmony/dist/src/lib/commands/run/runHarmony.js.map b/packages/platform-harmony/dist/src/lib/commands/run/runHarmony.js.map
new file mode 100644
index 000000000..00f1a913b
--- /dev/null
+++ b/packages/platform-harmony/dist/src/lib/commands/run/runHarmony.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"runHarmony.js","sourceRoot":"","sources":["../../../../../src/lib/commands/run/runHarmony.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/packages/platform-harmony/dist/src/lib/commands/run/tryInstallAppOnDevice.d.ts b/packages/platform-harmony/dist/src/lib/commands/run/tryInstallAppOnDevice.d.ts
new file mode 100644
index 000000000..7d238e689
--- /dev/null
+++ b/packages/platform-harmony/dist/src/lib/commands/run/tryInstallAppOnDevice.d.ts
@@ -0,0 +1,3 @@
+import type { DeviceData } from './listHarmonyDevices.js';
+import type { Flags } from './runHarmony.js';
+export declare function tryInstallAppOnDevice(device: DeviceData, sourceDir: string, args: Flags, binaryPath: string | undefined): Promise;
diff --git a/packages/platform-harmony/dist/src/lib/commands/run/tryInstallAppOnDevice.js b/packages/platform-harmony/dist/src/lib/commands/run/tryInstallAppOnDevice.js
new file mode 100644
index 000000000..e6ae0dab2
--- /dev/null
+++ b/packages/platform-harmony/dist/src/lib/commands/run/tryInstallAppOnDevice.js
@@ -0,0 +1,42 @@
+import path from 'node:path';
+import { color, colorLink, logger, RockError, spawn, } from '@rock-js/tools';
+import { findOutputFile } from './findOutputFile.js';
+import { getHdcPath } from './hdc.js';
+export async function tryInstallAppOnDevice(device, sourceDir, args, binaryPath) {
+ if (!device.deviceId) {
+ logger.debug(`No "deviceId" for ${device}, skipping launching the app`);
+ return;
+ }
+ logger.debug(`Connected to device ${color.bold(device.readableName)}`);
+ let pathToHap;
+ if (!binaryPath) {
+ const outputFilePath = await findOutputFile(sourceDir, args.module, device);
+ if (!outputFilePath) {
+ if (device.type === 'phone') {
+ throw new RockError(`There was no signed build output file for the physical device.
+This usually means you're missing signing config in your ${colorLink(path.join(sourceDir, 'build-profile.json5'))} file.
+Please open DevEco Studio, proceed to: ${color.bold('File > Project Structure... > Signing Configs')}
+and log in to your Huawei account to fill the signing information.`);
+ }
+ else {
+ logger.warn("Skipping installation because there's no build output file.");
+ return;
+ }
+ }
+ pathToHap = outputFilePath;
+ }
+ else {
+ pathToHap = binaryPath;
+ }
+ const hdcPath = getHdcPath();
+ try {
+ await spawn(hdcPath, ['-t', device.deviceId, 'install', '-r', pathToHap]);
+ }
+ catch (error) {
+ const errorMessage = error.stderr || error.stdout;
+ if (errorMessage.includes('failed to install')) {
+ throw new RockError(`Installation failed. If an application with the same bundle name is already installed, try uninstalling it`, { cause: error });
+ }
+ }
+}
+//# sourceMappingURL=tryInstallAppOnDevice.js.map
\ No newline at end of file
diff --git a/packages/platform-harmony/dist/src/lib/commands/run/tryInstallAppOnDevice.js.map b/packages/platform-harmony/dist/src/lib/commands/run/tryInstallAppOnDevice.js.map
new file mode 100644
index 000000000..eeb86be19
--- /dev/null
+++ b/packages/platform-harmony/dist/src/lib/commands/run/tryInstallAppOnDevice.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"tryInstallAppOnDevice.js","sourceRoot":"","sources":["../../../../../src/lib/commands/run/tryInstallAppOnDevice.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EACL,KAAK,EACL,SAAS,EACT,MAAM,EACN,SAAS,EACT,KAAK,GAEN,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAItC,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,MAAkB,EAClB,SAAiB,EACjB,IAAW,EACX,UAA8B;IAE9B,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;QACrB,MAAM,CAAC,KAAK,CACV,qBAAqB,MAAM,8BAA8B,CAC1D,CAAC;QACF,OAAO;IACT,CAAC;IACD,MAAM,CAAC,KAAK,CAAC,uBAAuB,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;IACvE,IAAI,SAAiB,CAAC;IACtB,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,cAAc,GAAG,MAAM,cAAc,CAAC,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC5E,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBAC5B,MAAM,IAAI,SAAS,CACjB;2DACiD,SAAS,CACxD,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,qBAAqB,CAAC,CAC5C;yCAC8B,KAAK,CAAC,IAAI,CAAC,+CAA+C,CAAC;mEACjC,CAC1D,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,IAAI,CACT,6DAA6D,CAC9D,CAAC;gBACF,OAAO;YACT,CAAC;QACH,CAAC;QACD,SAAS,GAAG,cAAc,CAAC;IAC7B,CAAC;SAAM,CAAC;QACN,SAAS,GAAG,UAAU,CAAC;IACzB,CAAC;IACD,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAE7B,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC;IAC5E,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,YAAY,GACf,KAAyB,CAAC,MAAM,IAAK,KAAyB,CAAC,MAAM,CAAC;QACzE,IAAI,YAAY,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC;YAC/C,MAAM,IAAI,SAAS,CACjB,4GAA4G,EAC5G,EAAE,KAAK,EAAE,KAAK,EAAE,CACjB,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-harmony/dist/src/lib/commands/run/tryLaunchAppOnDevice.d.ts b/packages/platform-harmony/dist/src/lib/commands/run/tryLaunchAppOnDevice.d.ts
new file mode 100644
index 000000000..b92bb0e80
--- /dev/null
+++ b/packages/platform-harmony/dist/src/lib/commands/run/tryLaunchAppOnDevice.d.ts
@@ -0,0 +1,7 @@
+import type { DeviceData } from './listHarmonyDevices.js';
+import type { Flags } from './runHarmony.js';
+export declare function tryLaunchAppOnDevice(device: DeviceData, bundleName: string, args: Flags): Promise<{
+ applicationIdWithSuffix?: undefined;
+} | {
+ applicationIdWithSuffix: string;
+}>;
diff --git a/packages/platform-harmony/dist/src/lib/commands/run/tryLaunchAppOnDevice.js b/packages/platform-harmony/dist/src/lib/commands/run/tryLaunchAppOnDevice.js
new file mode 100644
index 000000000..2ae1a1ea9
--- /dev/null
+++ b/packages/platform-harmony/dist/src/lib/commands/run/tryLaunchAppOnDevice.js
@@ -0,0 +1,43 @@
+import { logger, RockError, spawn } from '@rock-js/tools';
+import { getHdcPath } from './hdc.js';
+import { tryRunHdcReverse } from './tryRunHdcReverse.js';
+export async function tryLaunchAppOnDevice(device, bundleName, args) {
+ let deviceId;
+ if (!device.deviceId) {
+ logger.debug(`No "deviceId" for ${device}, skipping launching the app`);
+ return {};
+ }
+ else {
+ deviceId = device.deviceId;
+ }
+ await tryRunHdcReverse(args.port, deviceId);
+ const hdcPath = getHdcPath();
+ try {
+ await spawn(hdcPath, [
+ '-t',
+ device.deviceId,
+ 'shell',
+ 'aa',
+ 'force-stop',
+ bundleName,
+ ]);
+ await spawn(hdcPath, [
+ '-t',
+ device.deviceId,
+ 'shell',
+ 'aa',
+ 'start',
+ '-a',
+ args.ability,
+ '-b',
+ bundleName,
+ ]);
+ }
+ catch (error) {
+ throw new RockError(`Failed to launch the app on ${device.readableName}`, {
+ cause: error.stderr,
+ });
+ }
+ return { applicationIdWithSuffix: bundleName };
+}
+//# sourceMappingURL=tryLaunchAppOnDevice.js.map
\ No newline at end of file
diff --git a/packages/platform-harmony/dist/src/lib/commands/run/tryLaunchAppOnDevice.js.map b/packages/platform-harmony/dist/src/lib/commands/run/tryLaunchAppOnDevice.js.map
new file mode 100644
index 000000000..078f79ec2
--- /dev/null
+++ b/packages/platform-harmony/dist/src/lib/commands/run/tryLaunchAppOnDevice.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"tryLaunchAppOnDevice.js","sourceRoot":"","sources":["../../../../../src/lib/commands/run/tryLaunchAppOnDevice.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAwB,MAAM,gBAAgB,CAAC;AAChF,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAGtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzD,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,MAAkB,EAClB,UAAkB,EAClB,IAAW;IAEX,IAAI,QAAQ,CAAC;IACb,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;QACrB,MAAM,CAAC,KAAK,CACV,qBAAqB,MAAM,8BAA8B,CAC1D,CAAC;QACF,OAAO,EAAE,CAAC;IACZ,CAAC;SAAM,CAAC;QACN,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;IAC7B,CAAC;IACD,MAAM,gBAAgB,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAE5C,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAE7B,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,OAAO,EAAE;YACnB,IAAI;YACJ,MAAM,CAAC,QAAQ;YACf,OAAO;YACP,IAAI;YACJ,YAAY;YACZ,UAAU;SACX,CAAC,CAAC;QACH,MAAM,KAAK,CAAC,OAAO,EAAE;YACnB,IAAI;YACJ,MAAM,CAAC,QAAQ;YACf,OAAO;YACP,IAAI;YACJ,OAAO;YACP,IAAI;YACJ,IAAI,CAAC,OAAO;YACZ,IAAI;YACJ,UAAU;SACX,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CAAC,+BAA+B,MAAM,CAAC,YAAY,EAAE,EAAE;YACxE,KAAK,EAAG,KAAyB,CAAC,MAAM;SACzC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,EAAE,uBAAuB,EAAE,UAAU,EAAE,CAAC;AACjD,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-harmony/dist/src/lib/commands/run/tryRunHdcReverse.d.ts b/packages/platform-harmony/dist/src/lib/commands/run/tryRunHdcReverse.d.ts
new file mode 100644
index 000000000..d97740f45
--- /dev/null
+++ b/packages/platform-harmony/dist/src/lib/commands/run/tryRunHdcReverse.d.ts
@@ -0,0 +1 @@
+export declare function tryRunHdcReverse(packagerPort: number | string, device: string): Promise;
diff --git a/packages/platform-harmony/dist/src/lib/commands/run/tryRunHdcReverse.js b/packages/platform-harmony/dist/src/lib/commands/run/tryRunHdcReverse.js
new file mode 100644
index 000000000..8c4f36313
--- /dev/null
+++ b/packages/platform-harmony/dist/src/lib/commands/run/tryRunHdcReverse.js
@@ -0,0 +1,21 @@
+import { logger, RockError, spawn } from '@rock-js/tools';
+import { getHdcPath } from './hdc.js';
+// Runs hdc rport tcp:8081 tcp:8081 to allow loading the jsbundle from the packager
+export async function tryRunHdcReverse(packagerPort, device) {
+ try {
+ const hdcPath = getHdcPath();
+ const hdcArgs = [
+ '-t',
+ device,
+ 'rport',
+ `tcp:${packagerPort}`,
+ `tcp:${packagerPort}`,
+ ];
+ logger.debug(`Connecting "${device}" to the development server`);
+ await spawn(hdcPath, hdcArgs);
+ }
+ catch (error) {
+ throw new RockError(`Failed to connect "${device}" to development server using "hdb rport"`, { cause: error.stderr });
+ }
+}
+//# sourceMappingURL=tryRunHdcReverse.js.map
\ No newline at end of file
diff --git a/packages/platform-harmony/dist/src/lib/commands/run/tryRunHdcReverse.js.map b/packages/platform-harmony/dist/src/lib/commands/run/tryRunHdcReverse.js.map
new file mode 100644
index 000000000..a4b592717
--- /dev/null
+++ b/packages/platform-harmony/dist/src/lib/commands/run/tryRunHdcReverse.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"tryRunHdcReverse.js","sourceRoot":"","sources":["../../../../../src/lib/commands/run/tryRunHdcReverse.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEtC,mFAAmF;AACnF,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,YAA6B,EAC7B,MAAc;IAEd,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAG;YACd,IAAI;YACJ,MAAM;YACN,OAAO;YACP,OAAO,YAAY,EAAE;YACrB,OAAO,YAAY,EAAE;SACtB,CAAC;QAEF,MAAM,CAAC,KAAK,CAAC,eAAe,MAAM,6BAA6B,CAAC,CAAC;QACjE,MAAM,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAChC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CACjB,sBAAsB,MAAM,2CAA2C,EACvE,EAAE,KAAK,EAAG,KAAyB,CAAC,MAAM,EAAE,CAC7C,CAAC;IACJ,CAAC;AACH,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-harmony/dist/src/lib/commands/runHvigor.d.ts b/packages/platform-harmony/dist/src/lib/commands/runHvigor.d.ts
new file mode 100644
index 000000000..6081052f5
--- /dev/null
+++ b/packages/platform-harmony/dist/src/lib/commands/runHvigor.d.ts
@@ -0,0 +1,11 @@
+import type { BuildFlags } from './build/buildHarmony.js';
+import type { DeviceData } from './run/listHarmonyDevices.js';
+import type { Flags } from './run/runHarmony.js';
+export type RunHvigorArgs = {
+ sourceDir: string;
+ bundleName: string;
+ args: BuildFlags | Flags;
+ artifactName: string;
+ device?: DeviceData;
+};
+export declare function runHvigor({ sourceDir, bundleName, args, artifactName, device, }: RunHvigorArgs): Promise;
diff --git a/packages/platform-harmony/dist/src/lib/commands/runHvigor.js b/packages/platform-harmony/dist/src/lib/commands/runHvigor.js
new file mode 100644
index 000000000..4b3628efe
--- /dev/null
+++ b/packages/platform-harmony/dist/src/lib/commands/runHvigor.js
@@ -0,0 +1,56 @@
+import path from 'node:path';
+import { color, logger, RockError, saveLocalBuildCache, spawn, spinner, } from '@rock-js/tools';
+import { getDevEcoBuildToolsPath } from '../paths.js';
+import { findOutputFile } from './run/findOutputFile.js';
+async function runOhpm(sourceDir, loader) {
+ loader.message('Installing dependencies with ohpm');
+ const ohpmPath = path.join(getDevEcoBuildToolsPath(), 'ohpm', 'bin', process.platform === 'win32' ? 'ohpm.bat' : 'ohpm');
+ try {
+ await spawn(ohpmPath, ['install', '--all', '--strict_ssl', 'true'], {
+ cwd: sourceDir,
+ });
+ }
+ catch (error) {
+ loader.stop('Failed to install dependencies with ohpm', 1);
+ throw new RockError('Failed to install native dependencies with ohpm', {
+ cause: error.output,
+ });
+ }
+}
+export async function runHvigor({ sourceDir, bundleName, args, artifactName, device, }) {
+ logger.log(`Build Settings:
+Bundle Name ${color.bold(bundleName)}
+Build Mode ${color.bold(args.buildMode)}`);
+ const loader = spinner({ indicator: 'timer' });
+ const message = `Building the app`;
+ loader.start(message);
+ await runOhpm(sourceDir, loader);
+ const hvigorPath = path.join(getDevEcoBuildToolsPath(), 'hvigor', 'bin', 'hvigorw.js');
+ try {
+ loader.message('Building the app with Hvigor');
+ await spawn('node', [
+ hvigorPath,
+ `-p`,
+ `module=${args.module}@default`,
+ `-p`,
+ `product=${args.product}`,
+ `-p`,
+ `buildMode=${args.buildMode}`,
+ `-p`,
+ `requiredDeviceType=phone`,
+ `assembleHap`,
+ ], { cwd: sourceDir });
+ loader.stop(`Built the app`);
+ }
+ catch (error) {
+ loader.stop('Failed to build the app', 1);
+ throw new RockError('Failed to build the app with Hvigor', {
+ cause: error.output,
+ });
+ }
+ const outputFilePath = await findOutputFile(sourceDir, args.module, device);
+ if (outputFilePath) {
+ saveLocalBuildCache(artifactName, outputFilePath);
+ }
+}
+//# sourceMappingURL=runHvigor.js.map
\ No newline at end of file
diff --git a/packages/platform-harmony/dist/src/lib/commands/runHvigor.js.map b/packages/platform-harmony/dist/src/lib/commands/runHvigor.js.map
new file mode 100644
index 000000000..46fbe1730
--- /dev/null
+++ b/packages/platform-harmony/dist/src/lib/commands/runHvigor.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"runHvigor.js","sourceRoot":"","sources":["../../../../src/lib/commands/runHvigor.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EACL,KAAK,EACL,MAAM,EACN,SAAS,EACT,mBAAmB,EACnB,KAAK,EACL,OAAO,GAER,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAEtD,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAYzD,KAAK,UAAU,OAAO,CAAC,SAAiB,EAAE,MAAkC;IAC1E,MAAM,CAAC,OAAO,CAAC,mCAAmC,CAAC,CAAC;IAEpD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CACxB,uBAAuB,EAAE,EACzB,MAAM,EACN,KAAK,EACL,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CACnD,CAAC;IAEF,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,QAAQ,EAAE,CAAC,SAAS,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,CAAC,EAAE;YAClE,GAAG,EAAE,SAAS;SACf,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,IAAI,CAAC,0CAA0C,EAAE,CAAC,CAAC,CAAC;QAC3D,MAAM,IAAI,SAAS,CAAC,iDAAiD,EAAE;YACrE,KAAK,EAAG,KAAyB,CAAC,MAAM;SACzC,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,EAC9B,SAAS,EACT,UAAU,EACV,IAAI,EACJ,YAAY,EACZ,MAAM,GACQ;IACd,MAAM,CAAC,GAAG,CAAC;gBACG,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC;gBACtB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IAE5C,MAAM,MAAM,GAAG,OAAO,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC;IAC/C,MAAM,OAAO,GAAG,kBAAkB,CAAC;IAEnC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAEtB,MAAM,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAEjC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAC1B,uBAAuB,EAAE,EACzB,QAAQ,EACR,KAAK,EACL,YAAY,CACb,CAAC;IAEF,IAAI,CAAC;QACH,MAAM,CAAC,OAAO,CAAC,8BAA8B,CAAC,CAAC;QAC/C,MAAM,KAAK,CACT,MAAM,EACN;YACE,UAAU;YACV,IAAI;YACJ,UAAU,IAAI,CAAC,MAAM,UAAU;YAC/B,IAAI;YACJ,WAAW,IAAI,CAAC,OAAO,EAAE;YACzB,IAAI;YACJ,aAAa,IAAI,CAAC,SAAS,EAAE;YAC7B,IAAI;YACJ,0BAA0B;YAC1B,aAAa;SACd,EACD,EAAE,GAAG,EAAE,SAAS,EAAE,CACnB,CAAC;QACF,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IAC/B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,IAAI,CAAC,yBAAyB,EAAE,CAAC,CAAC,CAAC;QAE1C,MAAM,IAAI,SAAS,CAAC,qCAAqC,EAAE;YACzD,KAAK,EAAG,KAAyB,CAAC,MAAM;SACzC,CAAC,CAAC;IACL,CAAC;IAED,MAAM,cAAc,GAAG,MAAM,cAAc,CAAC,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5E,IAAI,cAAc,EAAE,CAAC;QACnB,mBAAmB,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC;IACpD,CAAC;AACH,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-harmony/dist/src/lib/commands/toPascalCase.d.ts b/packages/platform-harmony/dist/src/lib/commands/toPascalCase.d.ts
new file mode 100644
index 000000000..cdd38c9e5
--- /dev/null
+++ b/packages/platform-harmony/dist/src/lib/commands/toPascalCase.d.ts
@@ -0,0 +1 @@
+export declare function toPascalCase(value: string): string;
diff --git a/packages/platform-harmony/dist/src/lib/commands/toPascalCase.js b/packages/platform-harmony/dist/src/lib/commands/toPascalCase.js
new file mode 100644
index 000000000..656bebdbb
--- /dev/null
+++ b/packages/platform-harmony/dist/src/lib/commands/toPascalCase.js
@@ -0,0 +1,4 @@
+export function toPascalCase(value) {
+ return value !== '' ? value[0].toUpperCase() + value.slice(1) : value;
+}
+//# sourceMappingURL=toPascalCase.js.map
\ No newline at end of file
diff --git a/packages/platform-harmony/dist/src/lib/commands/toPascalCase.js.map b/packages/platform-harmony/dist/src/lib/commands/toPascalCase.js.map
new file mode 100644
index 000000000..3986ae069
--- /dev/null
+++ b/packages/platform-harmony/dist/src/lib/commands/toPascalCase.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"toPascalCase.js","sourceRoot":"","sources":["../../../../src/lib/commands/toPascalCase.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,OAAO,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;AACxE,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-harmony/dist/src/lib/paths.d.ts b/packages/platform-harmony/dist/src/lib/paths.d.ts
new file mode 100644
index 000000000..3abd2ec53
--- /dev/null
+++ b/packages/platform-harmony/dist/src/lib/paths.d.ts
@@ -0,0 +1,2 @@
+export declare function getDevEcoSdkPath(): string;
+export declare function getDevEcoBuildToolsPath(): string;
diff --git a/packages/platform-harmony/dist/src/lib/paths.js b/packages/platform-harmony/dist/src/lib/paths.js
new file mode 100644
index 000000000..4ac3319ed
--- /dev/null
+++ b/packages/platform-harmony/dist/src/lib/paths.js
@@ -0,0 +1,12 @@
+import path from 'node:path';
+export function getDevEcoSdkPath() {
+ const sdkRoot = process.env['DEVECO_SDK_HOME'];
+ if (!sdkRoot) {
+ throw new Error('DEVECO_SDK_HOME environment variable is not set. Please set it and run again');
+ }
+ return sdkRoot;
+}
+export function getDevEcoBuildToolsPath() {
+ return path.join(getDevEcoSdkPath(), '..', 'tools');
+}
+//# sourceMappingURL=paths.js.map
\ No newline at end of file
diff --git a/packages/platform-harmony/dist/src/lib/paths.js.map b/packages/platform-harmony/dist/src/lib/paths.js.map
new file mode 100644
index 000000000..2c88285da
--- /dev/null
+++ b/packages/platform-harmony/dist/src/lib/paths.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../../src/lib/paths.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,UAAU,gBAAgB;IAC9B,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IAC/C,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,8EAA8E,CAC/E,CAAC;IACJ,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,uBAAuB;IACrC,OAAO,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;AACtD,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-harmony/dist/src/lib/platformHarmony.d.ts b/packages/platform-harmony/dist/src/lib/platformHarmony.d.ts
new file mode 100644
index 000000000..8c5a4815d
--- /dev/null
+++ b/packages/platform-harmony/dist/src/lib/platformHarmony.d.ts
@@ -0,0 +1,5 @@
+import type { PlatformOutput, PluginApi } from '@rock-js/config';
+import { type HarmonyProjectConfig } from './commands/getValidProjectConfig.js';
+type PluginConfig = HarmonyProjectConfig;
+export declare const platformHarmony: (pluginConfig?: Partial) => (api: PluginApi) => PlatformOutput;
+export default platformHarmony;
diff --git a/packages/platform-harmony/dist/src/lib/platformHarmony.js b/packages/platform-harmony/dist/src/lib/platformHarmony.js
new file mode 100644
index 000000000..a4f8ab883
--- /dev/null
+++ b/packages/platform-harmony/dist/src/lib/platformHarmony.js
@@ -0,0 +1,19 @@
+import { registerBuildCommand } from './commands/build/command.js';
+import { getValidProjectConfig, } from './commands/getValidProjectConfig.js';
+import { registerRunCommand } from './commands/run/command.js';
+export const platformHarmony = (pluginConfig) => (api) => {
+ registerBuildCommand(api, pluginConfig);
+ registerRunCommand(api, pluginConfig);
+ return {
+ name: '@rock-js/platform-harmony',
+ description: 'Rock plugin for HarmonyOS Next.',
+ autolinkingConfig: {
+ get project() {
+ const harmonyConfig = getValidProjectConfig(api.getProjectRoot(), pluginConfig);
+ return harmonyConfig;
+ },
+ },
+ };
+};
+export default platformHarmony;
+//# sourceMappingURL=platformHarmony.js.map
\ No newline at end of file
diff --git a/packages/platform-harmony/dist/src/lib/platformHarmony.js.map b/packages/platform-harmony/dist/src/lib/platformHarmony.js.map
new file mode 100644
index 000000000..28164cd2e
--- /dev/null
+++ b/packages/platform-harmony/dist/src/lib/platformHarmony.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"platformHarmony.js","sourceRoot":"","sources":["../../../src/lib/platformHarmony.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EACL,qBAAqB,GAEtB,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAI/D,MAAM,CAAC,MAAM,eAAe,GAC1B,CAAC,YAAoC,EAAE,EAAE,CACzC,CAAC,GAAc,EAAkB,EAAE;IACjC,oBAAoB,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IACxC,kBAAkB,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IAEtC,OAAO;QACL,IAAI,EAAE,2BAA2B;QACjC,WAAW,EAAE,iCAAiC;QAC9C,iBAAiB,EAAE;YACjB,IAAI,OAAO;gBACT,MAAM,aAAa,GAAG,qBAAqB,CACzC,GAAG,CAAC,cAAc,EAAE,EACpB,YAAY,CACb,CAAC;gBACF,OAAO,aAAa,CAAC;YACvB,CAAC;SACF;KACF,CAAC;AACJ,CAAC,CAAC;AAEJ,eAAe,eAAe,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-ios/dist/src/index.d.ts b/packages/platform-ios/dist/src/index.d.ts
new file mode 100644
index 000000000..b11daa579
--- /dev/null
+++ b/packages/platform-ios/dist/src/index.d.ts
@@ -0,0 +1 @@
+export * from './lib/platformIOS.js';
diff --git a/packages/platform-ios/dist/src/index.js b/packages/platform-ios/dist/src/index.js
new file mode 100644
index 000000000..cab7b2a75
--- /dev/null
+++ b/packages/platform-ios/dist/src/index.js
@@ -0,0 +1,2 @@
+export * from './lib/platformIOS.js';
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/packages/platform-ios/dist/src/index.js.map b/packages/platform-ios/dist/src/index.js.map
new file mode 100644
index 000000000..92bf7ff59
--- /dev/null
+++ b/packages/platform-ios/dist/src/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-ios/dist/src/lib/commands/signIos.d.ts b/packages/platform-ios/dist/src/lib/commands/signIos.d.ts
new file mode 100644
index 000000000..a1a683003
--- /dev/null
+++ b/packages/platform-ios/dist/src/lib/commands/signIos.d.ts
@@ -0,0 +1,10 @@
+import type { PluginApi } from '@rock-js/config';
+export type SignFlags = {
+ app: string;
+ output?: string;
+ identity?: string;
+ buildJsbundle?: boolean;
+ jsbundle?: string;
+ noHermes?: boolean;
+};
+export declare const registerSignCommand: (api: PluginApi) => void;
diff --git a/packages/platform-ios/dist/src/lib/commands/signIos.js b/packages/platform-ios/dist/src/lib/commands/signIos.js
new file mode 100644
index 000000000..a71886837
--- /dev/null
+++ b/packages/platform-ios/dist/src/lib/commands/signIos.js
@@ -0,0 +1,64 @@
+import { modifyApp, modifyIpa } from '@rock-js/platform-apple-helpers';
+const ARGUMENTS = [
+ {
+ name: 'binaryPath',
+ description: 'Path to the IPA or APP file.',
+ },
+];
+const OPTIONS = [
+ {
+ name: '--app',
+ description: 'Modify APP file (directory) instead of IPA file. No signing is done.',
+ },
+ {
+ name: '--identity ',
+ description: 'Certificate Identity name to use for code signing, e.g. "Apple Distribution: Your Team (HFJASKHDDS)".',
+ },
+ {
+ name: '--output ',
+ description: 'Path to the output IPA file.',
+ },
+ {
+ name: '--build-jsbundle',
+ description: 'Build the JS bundle before signing.',
+ },
+ {
+ name: '--jsbundle ',
+ description: 'Path to the JS bundle to apply before signing.',
+ },
+ {
+ name: '--no-hermes',
+ description: 'Do not use Hermes to build the JS bundle.',
+ },
+];
+export const registerSignCommand = (api) => {
+ api.registerCommand({
+ name: 'sign:ios',
+ description: 'Sign the iOS app (IPA or APP file) with modified JS bundle.',
+ args: ARGUMENTS,
+ options: OPTIONS,
+ action: async (binaryPath, flags) => {
+ if (flags.app) {
+ await modifyApp({
+ appPath: binaryPath,
+ outputPath: flags.output,
+ buildJsBundle: flags.buildJsbundle,
+ jsBundlePath: flags.jsbundle,
+ useHermes: !flags.noHermes,
+ });
+ }
+ else {
+ await modifyIpa({
+ platformName: 'ios',
+ ipaPath: binaryPath,
+ identity: flags.identity,
+ outputPath: flags.output,
+ buildJsBundle: flags.buildJsbundle,
+ jsBundlePath: flags.jsbundle,
+ useHermes: !flags.noHermes,
+ });
+ }
+ },
+ });
+};
+//# sourceMappingURL=signIos.js.map
\ No newline at end of file
diff --git a/packages/platform-ios/dist/src/lib/commands/signIos.js.map b/packages/platform-ios/dist/src/lib/commands/signIos.js.map
new file mode 100644
index 000000000..2a2a15b6c
--- /dev/null
+++ b/packages/platform-ios/dist/src/lib/commands/signIos.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"signIos.js","sourceRoot":"","sources":["../../../../src/lib/commands/signIos.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AAWvE,MAAM,SAAS,GAAG;IAChB;QACE,IAAI,EAAE,YAAY;QAClB,WAAW,EAAE,8BAA8B;KAC5C;CACF,CAAC;AAEF,MAAM,OAAO,GAAG;IACd;QACE,IAAI,EAAE,OAAO;QACb,WAAW,EACT,sEAAsE;KACzE;IACD;QACE,IAAI,EAAE,qBAAqB;QAC3B,WAAW,EACT,uGAAuG;KAC1G;IACD;QACE,IAAI,EAAE,mBAAmB;QACzB,WAAW,EAAE,8BAA8B;KAC5C;IACD;QACE,IAAI,EAAE,kBAAkB;QACxB,WAAW,EAAE,qCAAqC;KACnD;IACD;QACE,IAAI,EAAE,qBAAqB;QAC3B,WAAW,EAAE,gDAAgD;KAC9D;IACD;QACE,IAAI,EAAE,aAAa;QACnB,WAAW,EAAE,2CAA2C;KACzD;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,GAAc,EAAE,EAAE;IACpD,GAAG,CAAC,eAAe,CAAC;QAClB,IAAI,EAAE,UAAU;QAChB,WAAW,EAAE,6DAA6D;QAC1E,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,OAAO;QAChB,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,KAAgB,EAAE,EAAE;YAC7C,IAAI,KAAK,CAAC,GAAG,EAAE,CAAC;gBACd,MAAM,SAAS,CAAC;oBACd,OAAO,EAAE,UAAU;oBACnB,UAAU,EAAE,KAAK,CAAC,MAAM;oBACxB,aAAa,EAAE,KAAK,CAAC,aAAa;oBAClC,YAAY,EAAE,KAAK,CAAC,QAAQ;oBAC5B,SAAS,EAAE,CAAC,KAAK,CAAC,QAAQ;iBAC3B,CAAC,CAAC;YACL,CAAC;iBAAM,CAAC;gBACN,MAAM,SAAS,CAAC;oBACd,YAAY,EAAE,KAAK;oBACnB,OAAO,EAAE,UAAU;oBACnB,QAAQ,EAAE,KAAK,CAAC,QAAQ;oBACxB,UAAU,EAAE,KAAK,CAAC,MAAM;oBACxB,aAAa,EAAE,KAAK,CAAC,aAAa;oBAClC,YAAY,EAAE,KAAK,CAAC,QAAQ;oBAC5B,SAAS,EAAE,CAAC,KAAK,CAAC,QAAQ;iBAC3B,CAAC,CAAC;YACL,CAAC;QACH,CAAC;KACF,CAAC,CAAC;AACL,CAAC,CAAC"}
\ No newline at end of file
diff --git a/packages/platform-ios/dist/src/lib/platformIOS.d.ts b/packages/platform-ios/dist/src/lib/platformIOS.d.ts
new file mode 100644
index 000000000..b4f15c276
--- /dev/null
+++ b/packages/platform-ios/dist/src/lib/platformIOS.d.ts
@@ -0,0 +1,4 @@
+import type { IOSProjectConfig } from '@react-native-community/cli-types';
+import type { PlatformOutput, PluginApi } from '@rock-js/config';
+export declare const platformIOS: (pluginConfig?: Partial) => (api: PluginApi) => PlatformOutput;
+export default platformIOS;
diff --git a/packages/platform-ios/dist/src/lib/platformIOS.js b/packages/platform-ios/dist/src/lib/platformIOS.js
new file mode 100644
index 000000000..c4a555ac4
--- /dev/null
+++ b/packages/platform-ios/dist/src/lib/platformIOS.js
@@ -0,0 +1,64 @@
+import { createBuild, createRun, getBuildOptions, getRunOptions, getValidProjectConfig, } from '@rock-js/platform-apple-helpers';
+import { intro, outro } from '@rock-js/tools';
+import { registerSignCommand } from './commands/signIos.js';
+const buildOptions = getBuildOptions({ platformName: 'ios' });
+const runOptions = getRunOptions({ platformName: 'ios' });
+export const platformIOS = (pluginConfig) => (api) => {
+ api.registerCommand({
+ name: 'build:ios',
+ description: 'Build iOS app.',
+ action: async (args) => {
+ intro('Building iOS app');
+ const projectRoot = api.getProjectRoot();
+ const iosConfig = getValidProjectConfig('ios', projectRoot, pluginConfig);
+ await createBuild({
+ platformName: 'ios',
+ projectConfig: iosConfig,
+ args: args,
+ projectRoot,
+ reactNativePath: api.getReactNativePath(),
+ fingerprintOptions: api.getFingerprintOptions(),
+ remoteCacheProvider: await api.getRemoteCacheProvider(),
+ });
+ outro('Success ๐.');
+ },
+ options: buildOptions,
+ });
+ api.registerCommand({
+ name: 'run:ios',
+ description: 'Run iOS app.',
+ action: async (args) => {
+ intro('Running iOS app');
+ const projectRoot = api.getProjectRoot();
+ const iosConfig = getValidProjectConfig('ios', projectRoot, pluginConfig);
+ await createRun({
+ platformName: 'ios',
+ projectConfig: iosConfig,
+ args: args,
+ projectRoot,
+ remoteCacheProvider: await api.getRemoteCacheProvider(),
+ fingerprintOptions: api.getFingerprintOptions(),
+ reactNativePath: api.getReactNativePath(),
+ reactNativeVersion: api.getReactNativeVersion(),
+ platforms: api.getPlatforms(),
+ startDevServer: api.getBundlerStart(),
+ });
+ outro('Success ๐.');
+ },
+ // @ts-expect-error: fix `simulator` is not defined in `RunFlags`
+ options: runOptions,
+ });
+ registerSignCommand(api);
+ return {
+ name: '@rock-js/platform-ios',
+ description: 'Rock plugin for everything iOS.',
+ autolinkingConfig: {
+ get project() {
+ const iosConfig = getValidProjectConfig('ios', api.getProjectRoot(), pluginConfig);
+ return { ...iosConfig };
+ },
+ },
+ };
+};
+export default platformIOS;
+//# sourceMappingURL=platformIOS.js.map
\ No newline at end of file
diff --git a/packages/platform-ios/dist/src/lib/platformIOS.js.map b/packages/platform-ios/dist/src/lib/platformIOS.js.map
new file mode 100644
index 000000000..b42af02aa
--- /dev/null
+++ b/packages/platform-ios/dist/src/lib/platformIOS.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"platformIOS.js","sourceRoot":"","sources":["../../../src/lib/platformIOS.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,WAAW,EACX,SAAS,EACT,eAAe,EACf,aAAa,EACb,qBAAqB,GACtB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,YAAY,GAAG,eAAe,CAAC,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,CAAC;AAC9D,MAAM,UAAU,GAAG,aAAa,CAAC,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,CAAC;AAE1D,MAAM,CAAC,MAAM,WAAW,GACtB,CAAC,YAAwC,EAAE,EAAE,CAC7C,CAAC,GAAc,EAAkB,EAAE;IACjC,GAAG,CAAC,eAAe,CAAC;QAClB,IAAI,EAAE,WAAW;QACjB,WAAW,EAAE,gBAAgB;QAC7B,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YACrB,KAAK,CAAC,kBAAkB,CAAC,CAAC;YAC1B,MAAM,WAAW,GAAG,GAAG,CAAC,cAAc,EAAE,CAAC;YACzC,MAAM,SAAS,GAAG,qBAAqB,CACrC,KAAK,EACL,WAAW,EACX,YAAY,CACb,CAAC;YACF,MAAM,WAAW,CAAC;gBAChB,YAAY,EAAE,KAAK;gBACnB,aAAa,EAAE,SAAS;gBACxB,IAAI,EAAE,IAAkB;gBACxB,WAAW;gBACX,eAAe,EAAE,GAAG,CAAC,kBAAkB,EAAE;gBACzC,kBAAkB,EAAE,GAAG,CAAC,qBAAqB,EAAE;gBAC/C,mBAAmB,EAAE,MAAM,GAAG,CAAC,sBAAsB,EAAE;aACxD,CAAC,CAAC;YACH,KAAK,CAAC,aAAa,CAAC,CAAC;QACvB,CAAC;QACD,OAAO,EAAE,YAAY;KACtB,CAAC,CAAC;IAEH,GAAG,CAAC,eAAe,CAAC;QAClB,IAAI,EAAE,SAAS;QACf,WAAW,EAAE,cAAc;QAC3B,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YACrB,KAAK,CAAC,iBAAiB,CAAC,CAAC;YACzB,MAAM,WAAW,GAAG,GAAG,CAAC,cAAc,EAAE,CAAC;YACzC,MAAM,SAAS,GAAG,qBAAqB,CACrC,KAAK,EACL,WAAW,EACX,YAAY,CACb,CAAC;YACF,MAAM,SAAS,CAAC;gBACd,YAAY,EAAE,KAAK;gBACnB,aAAa,EAAE,SAAS;gBACxB,IAAI,EAAE,IAAgB;gBACtB,WAAW;gBACX,mBAAmB,EAAE,MAAM,GAAG,CAAC,sBAAsB,EAAE;gBACvD,kBAAkB,EAAE,GAAG,CAAC,qBAAqB,EAAE;gBAC/C,eAAe,EAAE,GAAG,CAAC,kBAAkB,EAAE;gBACzC,kBAAkB,EAAE,GAAG,CAAC,qBAAqB,EAAE;gBAC/C,SAAS,EAAE,GAAG,CAAC,YAAY,EAAE;gBAC7B,cAAc,EAAE,GAAG,CAAC,eAAe,EAAE;aACtC,CAAC,CAAC;YACH,KAAK,CAAC,aAAa,CAAC,CAAC;QACvB,CAAC;QACD,iEAAiE;QACjE,OAAO,EAAE,UAAU;KACpB,CAAC,CAAC;IAEH,mBAAmB,CAAC,GAAG,CAAC,CAAC;IAEzB,OAAO;QACL,IAAI,EAAE,uBAAuB;QAC7B,WAAW,EAAE,iCAAiC;QAC9C,iBAAiB,EAAE;YACjB,IAAI,OAAO;gBACT,MAAM,SAAS,GAAG,qBAAqB,CACrC,KAAK,EACL,GAAG,CAAC,cAAc,EAAE,EACpB,YAAY,CACb,CAAC;gBACF,OAAO,EAAE,GAAG,SAAS,EAAE,CAAC;YAC1B,CAAC;SACF;KACF,CAAC;AACJ,CAAC,CAAC;AAEJ,eAAe,WAAW,CAAC"}
\ No newline at end of file
diff --git a/packages/plugin-brownfield-android/dist/src/index.d.ts b/packages/plugin-brownfield-android/dist/src/index.d.ts
new file mode 100644
index 000000000..42964b1db
--- /dev/null
+++ b/packages/plugin-brownfield-android/dist/src/index.d.ts
@@ -0,0 +1 @@
+export * from './lib/pluginBrownfieldAndroid.js';
diff --git a/packages/plugin-brownfield-android/dist/src/index.js b/packages/plugin-brownfield-android/dist/src/index.js
new file mode 100644
index 000000000..47854fdf8
--- /dev/null
+++ b/packages/plugin-brownfield-android/dist/src/index.js
@@ -0,0 +1,2 @@
+export * from './lib/pluginBrownfieldAndroid.js';
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/packages/plugin-brownfield-android/dist/src/index.js.map b/packages/plugin-brownfield-android/dist/src/index.js.map
new file mode 100644
index 000000000..0678482b8
--- /dev/null
+++ b/packages/plugin-brownfield-android/dist/src/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,kCAAkC,CAAC"}
\ No newline at end of file
diff --git a/packages/plugin-brownfield-android/dist/src/lib/pluginBrownfieldAndroid.d.ts b/packages/plugin-brownfield-android/dist/src/lib/pluginBrownfieldAndroid.d.ts
new file mode 100644
index 000000000..a741f9a4b
--- /dev/null
+++ b/packages/plugin-brownfield-android/dist/src/lib/pluginBrownfieldAndroid.d.ts
@@ -0,0 +1,3 @@
+import type { AndroidProjectConfig } from '@react-native-community/cli-types';
+import type { PluginApi, PluginOutput } from '@rock-js/config';
+export declare const pluginBrownfieldAndroid: (pluginConfig?: AndroidProjectConfig) => (api: PluginApi) => PluginOutput;
diff --git a/packages/plugin-brownfield-android/dist/src/lib/pluginBrownfieldAndroid.js b/packages/plugin-brownfield-android/dist/src/lib/pluginBrownfieldAndroid.js
new file mode 100644
index 000000000..e38b40d0d
--- /dev/null
+++ b/packages/plugin-brownfield-android/dist/src/lib/pluginBrownfieldAndroid.js
@@ -0,0 +1,50 @@
+import { projectConfig } from '@react-native-community/cli-config-android';
+import { packageAar, packageAarOptions, publishLocalAar, publishLocalAarOptions, } from '@rock-js/platform-android';
+import { intro, RockError } from '@rock-js/tools';
+const getAarConfig = (args, androidConfig) => {
+ const config = {
+ sourceDir: androidConfig.sourceDir,
+ moduleName: args.moduleName ?? '',
+ };
+ return config;
+};
+export const pluginBrownfieldAndroid = (pluginConfig) => (api) => {
+ const projectRoot = api.getProjectRoot();
+ api.registerCommand({
+ name: 'package:aar',
+ description: 'Produces an AAR file suitable for including React Native app in native projects.',
+ action: async (args) => {
+ intro('Creating an AAR file');
+ const androidConfig = projectConfig(projectRoot, pluginConfig);
+ if (androidConfig) {
+ const config = getAarConfig(args, androidConfig);
+ await packageAar(config, args);
+ }
+ else {
+ throw new RockError('Android project not found.');
+ }
+ },
+ options: packageAarOptions,
+ });
+ api.registerCommand({
+ name: 'publish-local:aar',
+ description: 'Publishes a AAR to local maven repo',
+ action: async (args) => {
+ intro('Publishing AAR');
+ const androidConfig = projectConfig(projectRoot, pluginConfig);
+ if (androidConfig) {
+ const config = getAarConfig(args, androidConfig);
+ await publishLocalAar(config);
+ }
+ else {
+ throw new RockError('Android project not found.');
+ }
+ },
+ options: publishLocalAarOptions,
+ });
+ return {
+ name: 'plugin-brownfield-android',
+ description: 'Rock plugin for brownfield Android.',
+ };
+};
+//# sourceMappingURL=pluginBrownfieldAndroid.js.map
\ No newline at end of file
diff --git a/packages/plugin-brownfield-android/dist/src/lib/pluginBrownfieldAndroid.js.map b/packages/plugin-brownfield-android/dist/src/lib/pluginBrownfieldAndroid.js.map
new file mode 100644
index 000000000..d5449c80a
--- /dev/null
+++ b/packages/plugin-brownfield-android/dist/src/lib/pluginBrownfieldAndroid.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"pluginBrownfieldAndroid.js","sourceRoot":"","sources":["../../../src/lib/pluginBrownfieldAndroid.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,4CAA4C,CAAC;AAG3E,OAAO,EACL,UAAU,EAEV,iBAAiB,EACjB,eAAe,EACf,sBAAsB,GACvB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAElD,MAAM,YAAY,GAAG,CACnB,IAAqB,EACrB,aAAmC,EACnC,EAAE;IACF,MAAM,MAAM,GAAG;QACb,SAAS,EAAE,aAAa,CAAC,SAAS;QAClC,UAAU,EAAE,IAAI,CAAC,UAAU,IAAI,EAAE;KAClC,CAAC;IACF,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AACF,MAAM,CAAC,MAAM,uBAAuB,GAClC,CAAC,YAAmC,EAAE,EAAE,CACxC,CAAC,GAAc,EAAgB,EAAE;IAC/B,MAAM,WAAW,GAAG,GAAG,CAAC,cAAc,EAAE,CAAC;IAEzC,GAAG,CAAC,eAAe,CAAC;QAClB,IAAI,EAAE,aAAa;QACnB,WAAW,EACT,kFAAkF;QACpF,MAAM,EAAE,KAAK,EAAE,IAAqB,EAAE,EAAE;YACtC,KAAK,CAAC,sBAAsB,CAAC,CAAC;YAE9B,MAAM,aAAa,GAAG,aAAa,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;YAE/D,IAAI,aAAa,EAAE,CAAC;gBAClB,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;gBACjD,MAAM,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YACjC,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,SAAS,CAAC,4BAA4B,CAAC,CAAC;YACpD,CAAC;QACH,CAAC;QACD,OAAO,EAAE,iBAAiB;KAC3B,CAAC,CAAC;IAEH,GAAG,CAAC,eAAe,CAAC;QAClB,IAAI,EAAE,mBAAmB;QACzB,WAAW,EAAE,qCAAqC;QAClD,MAAM,EAAE,KAAK,EAAE,IAAqB,EAAE,EAAE;YACtC,KAAK,CAAC,gBAAgB,CAAC,CAAC;YAExB,MAAM,aAAa,GAAG,aAAa,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;YAE/D,IAAI,aAAa,EAAE,CAAC;gBAClB,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;gBACjD,MAAM,eAAe,CAAC,MAAM,CAAC,CAAC;YAChC,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,SAAS,CAAC,4BAA4B,CAAC,CAAC;YACpD,CAAC;QACH,CAAC;QACD,OAAO,EAAE,sBAAsB;KAChC,CAAC,CAAC;IAEH,OAAO;QACL,IAAI,EAAE,2BAA2B;QACjC,WAAW,EAAE,qCAAqC;KACnD,CAAC;AACJ,CAAC,CAAC"}
\ No newline at end of file
diff --git a/packages/plugin-brownfield-ios/dist/src/index.d.ts b/packages/plugin-brownfield-ios/dist/src/index.d.ts
new file mode 100644
index 000000000..eb9f9afa8
--- /dev/null
+++ b/packages/plugin-brownfield-ios/dist/src/index.d.ts
@@ -0,0 +1 @@
+export * from './lib/pluginBrownfieldIos.js';
diff --git a/packages/plugin-brownfield-ios/dist/src/index.js b/packages/plugin-brownfield-ios/dist/src/index.js
new file mode 100644
index 000000000..25c79e991
--- /dev/null
+++ b/packages/plugin-brownfield-ios/dist/src/index.js
@@ -0,0 +1,2 @@
+export * from './lib/pluginBrownfieldIos.js';
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/packages/plugin-brownfield-ios/dist/src/index.js.map b/packages/plugin-brownfield-ios/dist/src/index.js.map
new file mode 100644
index 000000000..ad9690e80
--- /dev/null
+++ b/packages/plugin-brownfield-ios/dist/src/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,8BAA8B,CAAC"}
\ No newline at end of file
diff --git a/packages/plugin-brownfield-ios/dist/src/lib/copyHermesXcframework.d.ts b/packages/plugin-brownfield-ios/dist/src/lib/copyHermesXcframework.d.ts
new file mode 100644
index 000000000..e0548dca6
--- /dev/null
+++ b/packages/plugin-brownfield-ios/dist/src/lib/copyHermesXcframework.d.ts
@@ -0,0 +1,4 @@
+export declare function copyHermesXcframework({ sourceDir, destinationDir, }: {
+ sourceDir: string;
+ destinationDir: string;
+}): void;
diff --git a/packages/plugin-brownfield-ios/dist/src/lib/copyHermesXcframework.js b/packages/plugin-brownfield-ios/dist/src/lib/copyHermesXcframework.js
new file mode 100644
index 000000000..cb69784a9
--- /dev/null
+++ b/packages/plugin-brownfield-ios/dist/src/lib/copyHermesXcframework.js
@@ -0,0 +1,15 @@
+import fs, { existsSync } from 'node:fs';
+import path from 'node:path';
+import { color, logger, spinner } from '@rock-js/tools';
+export function copyHermesXcframework({ sourceDir, destinationDir, }) {
+ const loader = spinner();
+ loader.start(`Copying ${color.bold('hermes.xcframework')}`);
+ const hermesDestination = path.join(destinationDir, 'hermes.xcframework');
+ if (existsSync(hermesDestination)) {
+ logger.debug(`Removing old hermes copy`);
+ fs.rmSync(hermesDestination, { recursive: true, force: true });
+ }
+ fs.cpSync(path.join(sourceDir, 'Pods/hermes-engine/destroot/Library/Frameworks/universal/hermes.xcframework'), hermesDestination, { recursive: true, force: true });
+ loader.stop(`Copied ${color.bold('hermes.xcframework')}`);
+}
+//# sourceMappingURL=copyHermesXcframework.js.map
\ No newline at end of file
diff --git a/packages/plugin-brownfield-ios/dist/src/lib/copyHermesXcframework.js.map b/packages/plugin-brownfield-ios/dist/src/lib/copyHermesXcframework.js.map
new file mode 100644
index 000000000..767658157
--- /dev/null
+++ b/packages/plugin-brownfield-ios/dist/src/lib/copyHermesXcframework.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"copyHermesXcframework.js","sourceRoot":"","sources":["../../../src/lib/copyHermesXcframework.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAExD,MAAM,UAAU,qBAAqB,CAAC,EACpC,SAAS,EACT,cAAc,GAIf;IACC,MAAM,MAAM,GAAG,OAAO,EAAE,CAAC;IAEzB,MAAM,CAAC,KAAK,CAAC,WAAW,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC,EAAE,CAAC,CAAC;IAC5D,MAAM,iBAAiB,GAAG,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,oBAAoB,CAAC,CAAC;IAE1E,IAAI,UAAU,CAAC,iBAAiB,CAAC,EAAE,CAAC;QAClC,MAAM,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;QACzC,EAAE,CAAC,MAAM,CAAC,iBAAiB,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACjE,CAAC;IAED,EAAE,CAAC,MAAM,CACP,IAAI,CAAC,IAAI,CACP,SAAS,EACT,6EAA6E,CAC9E,EACD,iBAAiB,EACjB,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CACjC,CAAC;IAEF,MAAM,CAAC,IAAI,CAAC,UAAU,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC,EAAE,CAAC,CAAC;AAC5D,CAAC"}
\ No newline at end of file
diff --git a/packages/plugin-brownfield-ios/dist/src/lib/mergeFrameworks.d.ts b/packages/plugin-brownfield-ios/dist/src/lib/mergeFrameworks.d.ts
new file mode 100644
index 000000000..c1343572a
--- /dev/null
+++ b/packages/plugin-brownfield-ios/dist/src/lib/mergeFrameworks.d.ts
@@ -0,0 +1,9 @@
+/**
+ * Xcode emits different `.framework` file based on the destination (simulator arm64/x86_64, iphone arm64 etc.)
+ * This takes those `.frameworks` files and merges them to a single `.xcframework` file for easier distribution.
+ */
+export declare function mergeFrameworks({ frameworkPaths, outputPath, sourceDir, }: {
+ frameworkPaths: string[];
+ outputPath: string;
+ sourceDir: string;
+}): Promise;
diff --git a/packages/plugin-brownfield-ios/dist/src/lib/mergeFrameworks.js b/packages/plugin-brownfield-ios/dist/src/lib/mergeFrameworks.js
new file mode 100644
index 000000000..6bb999095
--- /dev/null
+++ b/packages/plugin-brownfield-ios/dist/src/lib/mergeFrameworks.js
@@ -0,0 +1,33 @@
+import fs, { existsSync } from 'node:fs';
+import path from 'node:path';
+import { color, logger, spawn, spinner } from '@rock-js/tools';
+/**
+ * Xcode emits different `.framework` file based on the destination (simulator arm64/x86_64, iphone arm64 etc.)
+ * This takes those `.frameworks` files and merges them to a single `.xcframework` file for easier distribution.
+ */
+export async function mergeFrameworks({ frameworkPaths, outputPath, sourceDir, }) {
+ const loader = spinner();
+ const xcframeworkName = path.basename(outputPath);
+ if (existsSync(outputPath)) {
+ logger.debug(`Removing `);
+ fs.rmSync(outputPath, { recursive: true, force: true });
+ }
+ loader.start(`Creating ${color.bold(xcframeworkName)}`);
+ const xcodebuildArgs = [
+ '-create-xcframework',
+ ...frameworkPaths.flatMap((frameworkPath) => ['-framework', frameworkPath]),
+ '-output',
+ outputPath,
+ ];
+ try {
+ await spawn('xcodebuild', xcodebuildArgs, { cwd: sourceDir });
+ loader.stop(`Created ${color.bold(xcframeworkName)}`);
+ }
+ catch (error) {
+ loader.stop(`Couldn't create ${color.bold(xcframeworkName)}.`, 1);
+ throw new Error('Running xcodebuild failed', {
+ cause: error.stderr,
+ });
+ }
+}
+//# sourceMappingURL=mergeFrameworks.js.map
\ No newline at end of file
diff --git a/packages/plugin-brownfield-ios/dist/src/lib/mergeFrameworks.js.map b/packages/plugin-brownfield-ios/dist/src/lib/mergeFrameworks.js.map
new file mode 100644
index 000000000..5dd5ba5fc
--- /dev/null
+++ b/packages/plugin-brownfield-ios/dist/src/lib/mergeFrameworks.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"mergeFrameworks.js","sourceRoot":"","sources":["../../../src/lib/mergeFrameworks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAE/D;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,EACpC,cAAc,EACd,UAAU,EACV,SAAS,GAKV;IACC,MAAM,MAAM,GAAG,OAAO,EAAE,CAAC;IACzB,MAAM,eAAe,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;IAElD,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC3B,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QAC1B,EAAE,CAAC,MAAM,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1D,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,YAAY,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;IAExD,MAAM,cAAc,GAAG;QACrB,qBAAqB;QACrB,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC;QAC3E,SAAS;QACT,UAAU;KACX,CAAC;IAEF,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,YAAY,EAAE,cAAc,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;QAE9D,MAAM,CAAC,IAAI,CAAC,WAAW,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;IACxD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,IAAI,CAAC,mBAAmB,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QAClE,MAAM,IAAI,KAAK,CAAC,2BAA2B,EAAE;YAC3C,KAAK,EAAG,KAAyB,CAAC,MAAM;SACzC,CAAC,CAAC;IACL,CAAC;AACH,CAAC"}
\ No newline at end of file
diff --git a/packages/plugin-brownfield-ios/dist/src/lib/pluginBrownfieldIos.d.ts b/packages/plugin-brownfield-ios/dist/src/lib/pluginBrownfieldIos.d.ts
new file mode 100644
index 000000000..3e58a05bd
--- /dev/null
+++ b/packages/plugin-brownfield-ios/dist/src/lib/pluginBrownfieldIos.d.ts
@@ -0,0 +1,4 @@
+import type { IOSProjectConfig } from '@react-native-community/cli-types';
+import type { PluginApi, PluginOutput } from '@rock-js/config';
+export declare const pluginBrownfieldIos: (pluginConfig?: IOSProjectConfig) => (api: PluginApi) => PluginOutput;
+export default pluginBrownfieldIos;
diff --git a/packages/plugin-brownfield-ios/dist/src/lib/pluginBrownfieldIos.js b/packages/plugin-brownfield-ios/dist/src/lib/pluginBrownfieldIos.js
new file mode 100644
index 000000000..a04cb6e93
--- /dev/null
+++ b/packages/plugin-brownfield-ios/dist/src/lib/pluginBrownfieldIos.js
@@ -0,0 +1,71 @@
+import path from 'node:path';
+import { createBuild, genericDestinations, getBuildOptions, getBuildPaths, getValidProjectConfig, } from '@rock-js/platform-apple-helpers';
+import { colorLink, intro, logger, outro, relativeToCwd } from '@rock-js/tools';
+import { copyHermesXcframework } from './copyHermesXcframework.js';
+import { mergeFrameworks } from './mergeFrameworks.js';
+const buildOptions = getBuildOptions({ platformName: 'ios' });
+export const pluginBrownfieldIos = (pluginConfig) => (api) => {
+ api.registerCommand({
+ name: 'package:ios',
+ description: 'Emit a .xcframework file from React Native code.',
+ action: async (args) => {
+ intro('Packaging iOS project');
+ // 1) Build the project
+ const projectRoot = api.getProjectRoot();
+ const iosConfig = getValidProjectConfig('ios', projectRoot, pluginConfig);
+ const { derivedDataDir } = getBuildPaths('ios');
+ const destination = args.destination ?? [
+ genericDestinations.ios.device,
+ genericDestinations.ios.simulator,
+ ];
+ const buildFolder = args.buildFolder ?? derivedDataDir;
+ const configuration = args.configuration ?? 'Debug';
+ const { sourceDir } = iosConfig;
+ const { scheme } = await createBuild({
+ platformName: 'ios',
+ projectConfig: iosConfig,
+ args: { ...args, destination, buildFolder },
+ projectRoot,
+ reactNativePath: api.getReactNativePath(),
+ fingerprintOptions: api.getFingerprintOptions(),
+ brownfield: true,
+ remoteCacheProvider: await api.getRemoteCacheProvider(),
+ });
+ // 2) Merge the .framework outputs of the framework target
+ const productsPath = path.join(buildFolder, 'Build', 'Products');
+ const { packageDir: frameworkTargetOutputDir } = getBuildPaths('ios');
+ await mergeFrameworks({
+ sourceDir,
+ frameworkPaths: [
+ path.join(productsPath, `${configuration}-iphoneos`, `${scheme}.framework`),
+ path.join(productsPath, `${configuration}-iphonesimulator`, `${scheme}.framework`),
+ ],
+ outputPath: path.join(frameworkTargetOutputDir, `${scheme}.xcframework`),
+ });
+ // 3) Merge React Native Brownfield paths
+ await mergeFrameworks({
+ sourceDir,
+ frameworkPaths: [
+ path.join(productsPath, `${configuration}-iphoneos`, 'ReactBrownfield', 'ReactBrownfield.framework'),
+ path.join(productsPath, `${configuration}-iphonesimulator`, 'ReactBrownfield', 'ReactBrownfield.framework'),
+ ],
+ outputPath: path.join(frameworkTargetOutputDir, 'ReactBrownfield.xcframework'),
+ });
+ // 4) Copy hermes xcframework to the output path
+ copyHermesXcframework({
+ sourceDir,
+ destinationDir: frameworkTargetOutputDir,
+ });
+ // 5) Inform the user
+ logger.log(`XCFrameworks are available at: ${colorLink(relativeToCwd(frameworkTargetOutputDir))}`);
+ outro('Success ๐.');
+ },
+ options: buildOptions,
+ });
+ return {
+ name: 'plugin-brownfield-ios',
+ description: 'Rock plugin for brownfield iOS.',
+ };
+};
+export default pluginBrownfieldIos;
+//# sourceMappingURL=pluginBrownfieldIos.js.map
\ No newline at end of file
diff --git a/packages/plugin-brownfield-ios/dist/src/lib/pluginBrownfieldIos.js.map b/packages/plugin-brownfield-ios/dist/src/lib/pluginBrownfieldIos.js.map
new file mode 100644
index 000000000..598bea473
--- /dev/null
+++ b/packages/plugin-brownfield-ios/dist/src/lib/pluginBrownfieldIos.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"pluginBrownfieldIos.js","sourceRoot":"","sources":["../../../src/lib/pluginBrownfieldIos.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/packages/plugin-metro/dist/src/index.d.ts b/packages/plugin-metro/dist/src/index.d.ts
new file mode 100644
index 000000000..aa80ef452
--- /dev/null
+++ b/packages/plugin-metro/dist/src/index.d.ts
@@ -0,0 +1,2 @@
+export * from './lib/pluginMetro.js';
+export { startDevServer } from './lib/start/command.js';
diff --git a/packages/plugin-metro/dist/src/index.js b/packages/plugin-metro/dist/src/index.js
new file mode 100644
index 000000000..69fbb0c00
--- /dev/null
+++ b/packages/plugin-metro/dist/src/index.js
@@ -0,0 +1,3 @@
+export * from './lib/pluginMetro.js';
+export { startDevServer } from './lib/start/command.js';
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/packages/plugin-metro/dist/src/index.js.map b/packages/plugin-metro/dist/src/index.js.map
new file mode 100644
index 000000000..3c3140c47
--- /dev/null
+++ b/packages/plugin-metro/dist/src/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC"}
\ No newline at end of file
diff --git a/packages/plugin-metro/dist/src/lib/bundle/command.d.ts b/packages/plugin-metro/dist/src/lib/bundle/command.d.ts
new file mode 100644
index 000000000..b1ecd3e91
--- /dev/null
+++ b/packages/plugin-metro/dist/src/lib/bundle/command.d.ts
@@ -0,0 +1,2 @@
+import type { PluginApi } from '@rock-js/config';
+export declare function registerBundleCommand(api: PluginApi): void;
diff --git a/packages/plugin-metro/dist/src/lib/bundle/command.js b/packages/plugin-metro/dist/src/lib/bundle/command.js
new file mode 100644
index 000000000..365c7e832
--- /dev/null
+++ b/packages/plugin-metro/dist/src/lib/bundle/command.js
@@ -0,0 +1,135 @@
+import fs from 'node:fs';
+import path from 'node:path';
+import { colorLink, intro, logger, outro, RockError, runHermes, spinner, } from '@rock-js/tools';
+import { getReactNativeCommunityCliPlugin } from '../getReactNativeDeps.js';
+export function registerBundleCommand(api) {
+ api.registerCommand({
+ name: 'bundle',
+ description: 'Build the bundle for the provided JavaScript entry file with Metro.',
+ action: async (args) => {
+ if (!args.platform || !args.bundleOutput || !args.entryFile) {
+ throw new RockError('"rock bundle" command requires all of these flags to bundle JavaScript with Metro: \n "--platform", "--bundle-output", "--entry-file"');
+ }
+ intro('Compiling JS bundle with Metro');
+ const root = api.getProjectRoot();
+ const reactNativeVersion = api.getReactNativeVersion();
+ const reactNativePath = api.getReactNativePath();
+ const platforms = api.getPlatforms();
+ // create the bundle output directory if it doesn't exist
+ const bundleOutputDir = path.dirname(args.bundleOutput);
+ fs.mkdirSync(bundleOutputDir, { recursive: true });
+ const { bundleCommand } = await getReactNativeCommunityCliPlugin(reactNativePath);
+ await bundleCommand.func(undefined, { root, reactNativeVersion, reactNativePath, platforms }, args);
+ if (args.hermes) {
+ const loader = spinner();
+ loader.start('Running Hermes compiler...');
+ await runHermes({
+ bundleOutputPath: args.bundleOutput,
+ sourcemapOutputPath: args.sourcemapOutput,
+ });
+ loader.stop(`Hermes bytecode bundle created at: ${colorLink(args.bundleOutput)}`);
+ }
+ else {
+ logger.info(`JavaScript bundle created at: ${colorLink(args.bundleOutput)}`);
+ }
+ outro('Success ๐.');
+ },
+ options: [
+ {
+ name: '--entry-file ',
+ description: 'Path to the root JS file, either absolute or relative to JS root',
+ },
+ {
+ name: '--platform ',
+ description: 'Either "ios" or "android"',
+ default: 'ios',
+ },
+ {
+ name: '--transformer ',
+ description: 'Specify a custom transformer to be used',
+ },
+ {
+ name: '--dev [boolean]',
+ description: 'If false, warnings are disabled and the bundle is minified',
+ parse: (val) => val !== 'false',
+ default: true,
+ },
+ {
+ name: '--minify [boolean]',
+ description: 'Allows overriding whether bundle is minified. This defaults to ' +
+ 'false if dev is true, and true if dev is false. Disabling minification ' +
+ 'can be useful for speeding up production builds for testing purposes.',
+ parse: (val) => val !== 'false',
+ },
+ {
+ name: '--bundle-output ',
+ description: 'File name where to store the resulting bundle, ex. /tmp/groups.bundle',
+ },
+ {
+ name: '--bundle-encoding ',
+ description: 'Encoding the bundle should be written in (https://nodejs.org/api/buffer.html#buffer_buffer).',
+ default: 'utf8',
+ },
+ {
+ name: '--max-workers ',
+ description: 'Specifies the maximum number of workers the worker-pool ' +
+ 'will spawn for transforming files. This defaults to the number of the ' +
+ 'cores available on your machine.',
+ },
+ {
+ name: '--sourcemap-output ',
+ description: 'File name where to store the sourcemap file for resulting bundle, ex. /tmp/groups.map',
+ },
+ {
+ name: '--sourcemap-sources-root ',
+ description: "Path to make sourcemap's sources entries relative to, ex. /root/dir",
+ },
+ {
+ name: '--sourcemap-use-absolute-path',
+ description: 'Report SourceMapURL using its full path',
+ default: false,
+ },
+ {
+ name: '--assets-dest ',
+ description: 'Directory name where to store assets referenced in the bundle',
+ },
+ {
+ name: '--unstable-transform-profile ',
+ description: 'Experimental, transform JS for a specific JS engine. Currently supported: hermes, hermes-canary, default',
+ default: 'default',
+ },
+ {
+ name: '--asset-catalog-dest [string]',
+ description: 'Path where to create an iOS Asset Catalog for images',
+ },
+ {
+ name: '--reset-cache',
+ description: 'Removes cached files',
+ default: false,
+ },
+ {
+ name: '--read-global-cache',
+ description: 'Try to fetch transformed JS code from the global cache, if configured.',
+ default: false,
+ },
+ {
+ name: '--config ',
+ description: 'Path to the CLI configuration file',
+ parse: (val) => path.resolve(val),
+ },
+ {
+ name: '--resolver-option ',
+ description: 'Custom resolver options of the form key=value. URL-encoded. May be specified multiple times.',
+ },
+ {
+ name: '--config-cmd [string]',
+ description: '[Internal] A hack for Xcode build script pointing to wrong bundle command that recognizes this flag. Do not use.',
+ },
+ {
+ name: '--hermes',
+ description: 'Passes the output JS bundle to Hermes compiler and outputs a bytecode file.',
+ },
+ ],
+ });
+}
+//# sourceMappingURL=command.js.map
\ No newline at end of file
diff --git a/packages/plugin-metro/dist/src/lib/bundle/command.js.map b/packages/plugin-metro/dist/src/lib/bundle/command.js.map
new file mode 100644
index 000000000..4e70349a1
--- /dev/null
+++ b/packages/plugin-metro/dist/src/lib/bundle/command.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"command.js","sourceRoot":"","sources":["../../../../src/lib/bundle/command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EACL,SAAS,EACT,KAAK,EACL,MAAM,EACN,KAAK,EACL,SAAS,EACT,SAAS,EACT,OAAO,GACR,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,gCAAgC,EAAE,MAAM,0BAA0B,CAAC;AA2B5E,MAAM,UAAU,qBAAqB,CAAC,GAAc;IAClD,GAAG,CAAC,eAAe,CAAC;QAClB,IAAI,EAAE,QAAQ;QACd,WAAW,EACT,qEAAqE;QACvE,MAAM,EAAE,KAAK,EAAE,IAAuB,EAAE,EAAE;YACxC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;gBAC5D,MAAM,IAAI,SAAS,CACjB,wIAAwI,CACzI,CAAC;YACJ,CAAC;YACD,KAAK,CAAC,gCAAgC,CAAC,CAAC;YACxC,MAAM,IAAI,GAAG,GAAG,CAAC,cAAc,EAAE,CAAC;YAClC,MAAM,kBAAkB,GAAG,GAAG,CAAC,qBAAqB,EAAE,CAAC;YACvD,MAAM,eAAe,GAAG,GAAG,CAAC,kBAAkB,EAAE,CAAC;YACjD,MAAM,SAAS,GAAG,GAAG,CAAC,YAAY,EAAE,CAAC;YAErC,yDAAyD;YACzD,MAAM,eAAe,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YACxD,EAAE,CAAC,SAAS,CAAC,eAAe,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAEnD,MAAM,EAAE,aAAa,EAAE,GACrB,MAAM,gCAAgC,CAAC,eAAe,CAAC,CAAC;YAE1D,MAAM,aAAa,CAAC,IAAI,CACtB,SAAS,EACT,EAAE,IAAI,EAAE,kBAAkB,EAAE,eAAe,EAAE,SAAS,EAAE,EACxD,IAAI,CACL,CAAC;YAEF,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;gBAChB,MAAM,MAAM,GAAG,OAAO,EAAE,CAAC;gBACzB,MAAM,CAAC,KAAK,CAAC,4BAA4B,CAAC,CAAC;gBAC3C,MAAM,SAAS,CAAC;oBACd,gBAAgB,EAAE,IAAI,CAAC,YAAY;oBACnC,mBAAmB,EAAE,IAAI,CAAC,eAAe;iBAC1C,CAAC,CAAC;gBACH,MAAM,CAAC,IAAI,CACT,sCAAsC,SAAS,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CACrE,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,IAAI,CACT,iCAAiC,SAAS,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAChE,CAAC;YACJ,CAAC;YACD,KAAK,CAAC,aAAa,CAAC,CAAC;QACvB,CAAC;QACD,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,qBAAqB;gBAC3B,WAAW,EACT,kEAAkE;aACrE;YACD;gBACE,IAAI,EAAE,qBAAqB;gBAC3B,WAAW,EAAE,2BAA2B;gBACxC,OAAO,EAAE,KAAK;aACf;YACD;gBACE,IAAI,EAAE,wBAAwB;gBAC9B,WAAW,EAAE,yCAAyC;aACvD;YACD;gBACE,IAAI,EAAE,iBAAiB;gBACvB,WAAW,EACT,4DAA4D;gBAC9D,KAAK,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,KAAK,OAAO;gBAC/B,OAAO,EAAE,IAAI;aACd;YACD;gBACE,IAAI,EAAE,oBAAoB;gBAC1B,WAAW,EACT,iEAAiE;oBACjE,yEAAyE;oBACzE,uEAAuE;gBACzE,KAAK,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,KAAK,OAAO;aAChC;YACD;gBACE,IAAI,EAAE,0BAA0B;gBAChC,WAAW,EACT,uEAAuE;aAC1E;YACD;gBACE,IAAI,EAAE,4BAA4B;gBAClC,WAAW,EACT,8FAA8F;gBAChG,OAAO,EAAE,MAAM;aAChB;YACD;gBACE,IAAI,EAAE,wBAAwB;gBAC9B,WAAW,EACT,0DAA0D;oBAC1D,wEAAwE;oBACxE,kCAAkC;aACrC;YACD;gBACE,IAAI,EAAE,6BAA6B;gBACnC,WAAW,EACT,uFAAuF;aAC1F;YACD;gBACE,IAAI,EAAE,mCAAmC;gBACzC,WAAW,EACT,qEAAqE;aACxE;YACD;gBACE,IAAI,EAAE,+BAA+B;gBACrC,WAAW,EAAE,yCAAyC;gBACtD,OAAO,EAAE,KAAK;aACf;YACD;gBACE,IAAI,EAAE,wBAAwB;gBAC9B,WAAW,EACT,+DAA+D;aAClE;YACD;gBACE,IAAI,EAAE,uCAAuC;gBAC7C,WAAW,EACT,0GAA0G;gBAC5G,OAAO,EAAE,SAAS;aACnB;YACD;gBACE,IAAI,EAAE,+BAA+B;gBACrC,WAAW,EAAE,sDAAsD;aACpE;YACD;gBACE,IAAI,EAAE,eAAe;gBACrB,WAAW,EAAE,sBAAsB;gBACnC,OAAO,EAAE,KAAK;aACf;YACD;gBACE,IAAI,EAAE,qBAAqB;gBAC3B,WAAW,EACT,wEAAwE;gBAC1E,OAAO,EAAE,KAAK;aACf;YACD;gBACE,IAAI,EAAE,mBAAmB;gBACzB,WAAW,EAAE,oCAAoC;gBACjD,KAAK,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC;aAClC;YACD;gBACE,IAAI,EAAE,+BAA+B;gBACrC,WAAW,EACT,8FAA8F;aACjG;YACD;gBACE,IAAI,EAAE,uBAAuB;gBAC7B,WAAW,EACT,kHAAkH;aACrH;YACD;gBACE,IAAI,EAAE,UAAU;gBAChB,WAAW,EACT,6EAA6E;aAChF;SACF;KACF,CAAC,CAAC;AACL,CAAC"}
\ No newline at end of file
diff --git a/packages/plugin-metro/dist/src/lib/getReactNativeDeps.d.ts b/packages/plugin-metro/dist/src/lib/getReactNativeDeps.d.ts
new file mode 100644
index 000000000..d5e5c6d34
--- /dev/null
+++ b/packages/plugin-metro/dist/src/lib/getReactNativeDeps.d.ts
@@ -0,0 +1,3 @@
+import type devMiddleware from '@react-native/dev-middleware';
+export declare function getDevMiddleware(reactNativePath: string): Promise;
+export declare function getReactNativeCommunityCliPlugin(reactNativePath: string): Promise;
diff --git a/packages/plugin-metro/dist/src/lib/getReactNativeDeps.js b/packages/plugin-metro/dist/src/lib/getReactNativeDeps.js
new file mode 100644
index 000000000..d523e094e
--- /dev/null
+++ b/packages/plugin-metro/dist/src/lib/getReactNativeDeps.js
@@ -0,0 +1,15 @@
+import { createRequire } from 'node:module';
+export async function getDevMiddleware(reactNativePath) {
+ const require = createRequire(import.meta.url);
+ const reactNativeCommunityCliPluginPath = require.resolve('@react-native/community-cli-plugin', { paths: [reactNativePath] });
+ const devMiddlewarePath = require.resolve('@react-native/dev-middleware', {
+ paths: [reactNativeCommunityCliPluginPath],
+ });
+ return import(devMiddlewarePath);
+}
+export async function getReactNativeCommunityCliPlugin(reactNativePath) {
+ const require = createRequire(import.meta.url);
+ const reactNativeCommunityCliPluginPath = require.resolve('@react-native/community-cli-plugin', { paths: [reactNativePath] });
+ return import(reactNativeCommunityCliPluginPath);
+}
+//# sourceMappingURL=getReactNativeDeps.js.map
\ No newline at end of file
diff --git a/packages/plugin-metro/dist/src/lib/getReactNativeDeps.js.map b/packages/plugin-metro/dist/src/lib/getReactNativeDeps.js.map
new file mode 100644
index 000000000..adbcfd054
--- /dev/null
+++ b/packages/plugin-metro/dist/src/lib/getReactNativeDeps.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"getReactNativeDeps.js","sourceRoot":"","sources":["../../../src/lib/getReactNativeDeps.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAG5C,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,eAAuB;IAEvB,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/C,MAAM,iCAAiC,GAAG,OAAO,CAAC,OAAO,CACvD,oCAAoC,EACpC,EAAE,KAAK,EAAE,CAAC,eAAe,CAAC,EAAE,CAC7B,CAAC;IAEF,MAAM,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC,8BAA8B,EAAE;QACxE,KAAK,EAAE,CAAC,iCAAiC,CAAC;KAC3C,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC,iBAAiB,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gCAAgC,CACpD,eAAuB;IAEvB,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/C,MAAM,iCAAiC,GAAG,OAAO,CAAC,OAAO,CACvD,oCAAoC,EACpC,EAAE,KAAK,EAAE,CAAC,eAAe,CAAC,EAAE,CAC7B,CAAC;IAEF,OAAO,MAAM,CAAC,iCAAiC,CAAC,CAAC;AACnD,CAAC"}
\ No newline at end of file
diff --git a/packages/plugin-metro/dist/src/lib/pluginMetro.d.ts b/packages/plugin-metro/dist/src/lib/pluginMetro.d.ts
new file mode 100644
index 000000000..83032bbae
--- /dev/null
+++ b/packages/plugin-metro/dist/src/lib/pluginMetro.d.ts
@@ -0,0 +1,3 @@
+import type { BundlerPluginOutput, PluginApi } from '@rock-js/config';
+export declare const pluginMetro: () => (api: PluginApi) => BundlerPluginOutput;
+export default pluginMetro;
diff --git a/packages/plugin-metro/dist/src/lib/pluginMetro.js b/packages/plugin-metro/dist/src/lib/pluginMetro.js
new file mode 100644
index 000000000..3ebc678ac
--- /dev/null
+++ b/packages/plugin-metro/dist/src/lib/pluginMetro.js
@@ -0,0 +1,13 @@
+import { registerBundleCommand } from './bundle/command.js';
+import { registerStartCommand, startDevServer } from './start/command.js';
+export const pluginMetro = () => (api) => {
+ registerStartCommand(api);
+ registerBundleCommand(api);
+ return {
+ name: '@rock-js/plugin-metro',
+ description: 'Rock plugin for Metro bundler.',
+ start: startDevServer,
+ };
+};
+export default pluginMetro;
+//# sourceMappingURL=pluginMetro.js.map
\ No newline at end of file
diff --git a/packages/plugin-metro/dist/src/lib/pluginMetro.js.map b/packages/plugin-metro/dist/src/lib/pluginMetro.js.map
new file mode 100644
index 000000000..ba4aa4f90
--- /dev/null
+++ b/packages/plugin-metro/dist/src/lib/pluginMetro.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"pluginMetro.js","sourceRoot":"","sources":["../../../src/lib/pluginMetro.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAE1E,MAAM,CAAC,MAAM,WAAW,GACtB,GAAG,EAAE,CACL,CAAC,GAAc,EAAuB,EAAE;IACtC,oBAAoB,CAAC,GAAG,CAAC,CAAC;IAC1B,qBAAqB,CAAC,GAAG,CAAC,CAAC;IAE3B,OAAO;QACL,IAAI,EAAE,uBAAuB;QAC7B,WAAW,EAAE,gCAAgC;QAC7C,KAAK,EAAE,cAAc;KACtB,CAAC;AACJ,CAAC,CAAC;AAEJ,eAAe,WAAW,CAAC"}
\ No newline at end of file
diff --git a/packages/plugin-metro/dist/src/lib/start/OpenDebuggerKeyboardHandler.d.ts b/packages/plugin-metro/dist/src/lib/start/OpenDebuggerKeyboardHandler.d.ts
new file mode 100644
index 000000000..95992e889
--- /dev/null
+++ b/packages/plugin-metro/dist/src/lib/start/OpenDebuggerKeyboardHandler.d.ts
@@ -0,0 +1,35 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+import type { TerminalReporter } from 'metro';
+export default class OpenDebuggerKeyboardHandler {
+ #private;
+ constructor({ devServerUrl, reporter, }: {
+ devServerUrl: string;
+ reporter: TerminalReporter;
+ });
+ /**
+ * Used in response to 'j' to debug - fetch the available debug targets and:
+ * - If no targets, warn
+ * - If one target, open it
+ * - If more, show a list. The keyboard listener should run subsequent key
+ * presses through maybeHandleTargetSelection, which will launch the
+ * debugger if a match is made.
+ */
+ handleOpenDebugger(): Promise;
+ /**
+ * Handle key presses that correspond to a valid selection from a visible
+ * selection list.
+ *
+ * @return true if we've handled the key as a target selection, false if the
+ * caller should handle the key.
+ */
+ maybeHandleTargetSelection(keyName: string): boolean;
+ /**
+ * Dismiss any target selection UI, if shown.
+ */
+ dismiss(): void;
+}
diff --git a/packages/plugin-metro/dist/src/lib/start/OpenDebuggerKeyboardHandler.js b/packages/plugin-metro/dist/src/lib/start/OpenDebuggerKeyboardHandler.js
new file mode 100644
index 000000000..3d22efee9
--- /dev/null
+++ b/packages/plugin-metro/dist/src/lib/start/OpenDebuggerKeyboardHandler.js
@@ -0,0 +1,128 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+import { color } from '@rock-js/tools';
+export default class OpenDebuggerKeyboardHandler {
+ #devServerUrl;
+ #reporter;
+ #targetsShownForSelection = null;
+ constructor({ devServerUrl, reporter, }) {
+ this.#devServerUrl = devServerUrl;
+ this.#reporter = reporter;
+ }
+ async #tryOpenDebuggerForTarget(target) {
+ this.#targetsShownForSelection = null;
+ this.#clearTerminalMenu();
+ try {
+ await fetch(new URL('/open-debugger?target=' + encodeURIComponent(target.id), this.#devServerUrl).href, { method: 'POST' });
+ }
+ catch (e) {
+ this.#log('error', 'Failed to open debugger for %s (%s): %s', target.title, target.description, 'Network error');
+ // @ts-expect-error - TBD
+ if (e.cause != null) {
+ // @ts-expect-error - it's not null
+ this.#log('error', 'Cause: %s', e.cause);
+ }
+ this.#clearTerminalMenu();
+ }
+ }
+ /**
+ * Used in response to 'j' to debug - fetch the available debug targets and:
+ * - If no targets, warn
+ * - If one target, open it
+ * - If more, show a list. The keyboard listener should run subsequent key
+ * presses through maybeHandleTargetSelection, which will launch the
+ * debugger if a match is made.
+ */
+ async handleOpenDebugger() {
+ this.#setTerminalMenu('Fetching available debugging targets...');
+ this.#targetsShownForSelection = null;
+ try {
+ const res = await fetch(this.#devServerUrl + '/json/list', {
+ method: 'POST',
+ });
+ if (res.status !== 200) {
+ throw new Error(`Unexpected status code: ${res.status}`);
+ }
+ const targets = (await res.json());
+ if (!Array.isArray(targets)) {
+ throw new Error('Expected array.');
+ }
+ if (targets.length === 0) {
+ this.#log('warn', 'No connected targets');
+ this.#clearTerminalMenu();
+ }
+ else if (targets.length === 1) {
+ const target = targets[0];
+ void this.#tryOpenDebuggerForTarget(target);
+ }
+ else {
+ this.#targetsShownForSelection = targets;
+ if (targets.length > 9) {
+ this.#log('warn', '10 or more debug targets available, showing the first 9.');
+ }
+ this.#setTerminalMenu(`Multiple debug targets available, please select:\n ${targets
+ .slice(0, 9)
+ .map(({ title }, i) => `${color.inverse(` ${i + 1} `)} - "${title}"`)
+ .join('\n ')}`);
+ }
+ }
+ catch (e) {
+ // @ts-expect-error - error is not typed
+ this.#log('error', `Failed to fetch debug targets: ${e.message}`);
+ this.#clearTerminalMenu();
+ }
+ }
+ /**
+ * Handle key presses that correspond to a valid selection from a visible
+ * selection list.
+ *
+ * @return true if we've handled the key as a target selection, false if the
+ * caller should handle the key.
+ */
+ maybeHandleTargetSelection(keyName) {
+ if (keyName >= '1' && keyName <= '9') {
+ const targetIndex = Number(keyName) - 1;
+ if (this.#targetsShownForSelection != null &&
+ targetIndex < this.#targetsShownForSelection.length) {
+ const target = this.#targetsShownForSelection[targetIndex];
+ void this.#tryOpenDebuggerForTarget(target);
+ return true;
+ }
+ }
+ return false;
+ }
+ /**
+ * Dismiss any target selection UI, if shown.
+ */
+ dismiss() {
+ this.#clearTerminalMenu();
+ this.#targetsShownForSelection = null;
+ }
+ #log(level, ...data) {
+ this.#reporter.update({
+ // @ts-expect-error - metro types are not updated
+ type: 'unstable_server_log',
+ // @ts-expect-error - metro types are not updated
+ level,
+ data,
+ });
+ }
+ #setTerminalMenu(message) {
+ this.#reporter.update({
+ // @ts-expect-error - metro types are not updated
+ type: 'unstable_server_menu_updated',
+ message,
+ });
+ }
+ #clearTerminalMenu() {
+ this.#reporter.update({
+ // @ts-expect-error - metro types are not updated
+ type: 'unstable_server_menu_cleared',
+ });
+ }
+}
+//# sourceMappingURL=OpenDebuggerKeyboardHandler.js.map
\ No newline at end of file
diff --git a/packages/plugin-metro/dist/src/lib/start/OpenDebuggerKeyboardHandler.js.map b/packages/plugin-metro/dist/src/lib/start/OpenDebuggerKeyboardHandler.js.map
new file mode 100644
index 000000000..e1d351d44
--- /dev/null
+++ b/packages/plugin-metro/dist/src/lib/start/OpenDebuggerKeyboardHandler.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"OpenDebuggerKeyboardHandler.js","sourceRoot":"","sources":["../../../../src/lib/start/OpenDebuggerKeyboardHandler.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/packages/plugin-metro/dist/src/lib/start/attachKeyHandlers.d.ts b/packages/plugin-metro/dist/src/lib/start/attachKeyHandlers.d.ts
new file mode 100644
index 000000000..89dfe2e88
--- /dev/null
+++ b/packages/plugin-metro/dist/src/lib/start/attachKeyHandlers.d.ts
@@ -0,0 +1,14 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+import type { TerminalReporter } from 'metro';
+export default function attachKeyHandlers({ devServerUrl, messageSocket, reporter, }: {
+ devServerUrl: string;
+ messageSocket: {
+ broadcast: (type: string, params?: Record | null) => void;
+ };
+ reporter: TerminalReporter;
+}): void;
diff --git a/packages/plugin-metro/dist/src/lib/start/attachKeyHandlers.js b/packages/plugin-metro/dist/src/lib/start/attachKeyHandlers.js
new file mode 100644
index 000000000..41a201ba1
--- /dev/null
+++ b/packages/plugin-metro/dist/src/lib/start/attachKeyHandlers.js
@@ -0,0 +1,109 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+import readline from 'node:readline';
+import { ReadStream } from 'node:tty';
+import { color, RockError } from '@rock-js/tools';
+import OpenDebuggerKeyboardHandler from './OpenDebuggerKeyboardHandler.js';
+const CTRL_C = '\u0003';
+const CTRL_D = '\u0004';
+const RELOAD_TIMEOUT = 500;
+const throttle = (callback, timeout) => {
+ let previousCallTimestamp = 0;
+ return () => {
+ const currentCallTimestamp = new Date().getTime();
+ if (currentCallTimestamp - previousCallTimestamp > timeout) {
+ previousCallTimestamp = currentCallTimestamp;
+ callback();
+ }
+ };
+};
+export default function attachKeyHandlers({ devServerUrl, messageSocket, reporter, }) {
+ if (process.stdin.isTTY !== true) {
+ reporter.update({
+ // @ts-expect-error - metro types are not updated
+ type: 'unstable_server_log',
+ level: 'info',
+ // @ts-expect-error - metro types are not updated
+ data: 'Interactive mode is not supported in this environment',
+ });
+ return;
+ }
+ readline.emitKeypressEvents(process.stdin);
+ setRawMode(true);
+ // resume stdin to allow reading keypresses
+ process.stdin.resume();
+ const reload = throttle(() => {
+ reporter.update({
+ // @ts-expect-error - metro types are not updated
+ type: 'unstable_server_log',
+ level: 'info',
+ // @ts-expect-error - metro types are not updated
+ data: 'Reloading connected app(s)...',
+ });
+ messageSocket.broadcast('reload', null);
+ }, RELOAD_TIMEOUT);
+ const openDebuggerKeyboardHandler = new OpenDebuggerKeyboardHandler({
+ reporter,
+ devServerUrl,
+ });
+ process.stdin.on('keypress', (str, key) => {
+ if (openDebuggerKeyboardHandler.maybeHandleTargetSelection(key.name)) {
+ return;
+ }
+ switch (key.sequence) {
+ case 'r':
+ reload();
+ break;
+ case 'd':
+ reporter.update({
+ // @ts-expect-error - metro types are not updated
+ type: 'unstable_server_log',
+ level: 'info',
+ // @ts-expect-error - metro types are not updated
+ data: 'Opening Dev Menu...',
+ });
+ messageSocket.broadcast('devMenu', null);
+ break;
+ case 'j':
+ void openDebuggerKeyboardHandler.handleOpenDebugger();
+ break;
+ case CTRL_C:
+ case CTRL_D:
+ openDebuggerKeyboardHandler.dismiss();
+ reporter.update({
+ // @ts-expect-error - metro types are not updated
+ type: 'unstable_server_log',
+ level: 'info',
+ // @ts-expect-error - metro types are not updated
+ data: 'Stopping server',
+ });
+ setRawMode(false);
+ process.stdin.pause();
+ process.emit('SIGINT');
+ process.exit();
+ }
+ });
+ reporter.update({
+ // @ts-expect-error - metro types are not updated
+ type: 'unstable_server_log',
+ level: 'info',
+ // @ts-expect-error - metro types are not updated
+ data: `Key commands available:
+
+ ${color.bold(color.inverse(' r '))} - reload app(s)
+ ${color.bold(color.inverse(' d '))} - open Dev Menu
+ ${color.bold(color.inverse(' j '))} - open DevTools
+`,
+ });
+}
+function setRawMode(enable) {
+ if (!(process.stdin instanceof ReadStream)) {
+ throw new RockError('process.stdin must be a readable stream to modify raw mode');
+ }
+ process.stdin.setRawMode(enable);
+}
+//# sourceMappingURL=attachKeyHandlers.js.map
\ No newline at end of file
diff --git a/packages/plugin-metro/dist/src/lib/start/attachKeyHandlers.js.map b/packages/plugin-metro/dist/src/lib/start/attachKeyHandlers.js.map
new file mode 100644
index 000000000..03159d2d6
--- /dev/null
+++ b/packages/plugin-metro/dist/src/lib/start/attachKeyHandlers.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"attachKeyHandlers.js","sourceRoot":"","sources":["../../../../src/lib/start/attachKeyHandlers.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/packages/plugin-metro/dist/src/lib/start/command.d.ts b/packages/plugin-metro/dist/src/lib/start/command.d.ts
new file mode 100644
index 000000000..4faafa4ae
--- /dev/null
+++ b/packages/plugin-metro/dist/src/lib/start/command.d.ts
@@ -0,0 +1,10 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+import type { PluginApi } from '@rock-js/config';
+import type { StartDevServerArgs } from '@rock-js/config';
+export declare function startDevServer({ root, args, reactNativeVersion, reactNativePath, platforms, }: StartDevServerArgs): Promise;
+export declare const registerStartCommand: (api: PluginApi) => void;
diff --git a/packages/plugin-metro/dist/src/lib/start/command.js b/packages/plugin-metro/dist/src/lib/start/command.js
new file mode 100644
index 000000000..cfd7cd6d6
--- /dev/null
+++ b/packages/plugin-metro/dist/src/lib/start/command.js
@@ -0,0 +1,110 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+import path from 'node:path';
+import { findDevServerPort, intro } from '@rock-js/tools';
+import runServer from './runServer.js';
+export async function startDevServer({ root, args, reactNativeVersion, reactNativePath, platforms, }) {
+ const { port, startDevServer } = await findDevServerPort(args.port ? Number(args.port) : 8081, root);
+ if (!startDevServer) {
+ return;
+ }
+ return runServer({ root, reactNativeVersion, reactNativePath, platforms }, { ...args, port, platforms: Object.keys(platforms) });
+}
+export const registerStartCommand = (api) => {
+ api.registerCommand({
+ name: 'start',
+ action: async (args) => {
+ intro('Starting Metro dev server');
+ startDevServer({
+ root: api.getProjectRoot(),
+ reactNativeVersion: api.getReactNativeVersion(),
+ reactNativePath: api.getReactNativePath(),
+ platforms: api.getPlatforms(),
+ args,
+ });
+ },
+ description: 'Start the Metro development server.',
+ options: [
+ {
+ name: '--port ',
+ description: 'Port to run the server on',
+ },
+ {
+ name: '--host ',
+ description: 'Host to run the server on',
+ default: '',
+ },
+ {
+ name: '--project-root, --projectRoot ',
+ description: 'Path to a custom project root',
+ parse: (val) => path.resolve(val),
+ },
+ {
+ name: '--watch-folders, --watchFolders ',
+ description: 'Specify any additional folders to be added to the watch list',
+ parse: (val) => val.split(',').map((folder) => path.resolve(folder)),
+ },
+ {
+ name: '--asset-plugins, --assetPlugins ',
+ description: 'Specify any additional asset plugins to be used by the packager by full filepath',
+ parse: (val) => val.split(','),
+ },
+ {
+ name: '--source-exts, --sourceExts ',
+ description: 'Specify any additional source extensions to be used by the packager',
+ parse: (val) => val.split(','),
+ },
+ {
+ name: '--max-workers ',
+ description: 'Specifies the maximum number of workers the worker-pool ' +
+ 'will spawn for transforming files. This defaults to the number of the ' +
+ 'cores available on your machine.',
+ },
+ {
+ name: '--transformer ',
+ description: 'Specify a custom transformer to be used',
+ },
+ {
+ name: '--reset-cache, --resetCache',
+ description: 'Removes cached files',
+ },
+ {
+ name: '--custom-log-reporter-path, --customLogReporterPath ',
+ description: 'Path to a JavaScript file that exports a log reporter as a replacement for TerminalReporter',
+ },
+ {
+ name: '--https',
+ description: 'Enables https connections to the server',
+ },
+ {
+ name: '--key ',
+ description: 'Path to custom SSL key',
+ },
+ {
+ name: '--cert ',
+ description: 'Path to custom SSL cert',
+ },
+ {
+ name: '--config ',
+ description: 'Path to the CLI configuration file',
+ parse: (val) => path.resolve(val),
+ },
+ {
+ name: '--no-interactive',
+ description: 'Disables interactive mode',
+ },
+ {
+ name: '--client-logs',
+ description: '[Deprecated] Enable plain text JavaScript log streaming for all ' +
+ 'connected apps. This feature is deprecated and will be removed in ' +
+ 'future.',
+ default: false,
+ },
+ ],
+ });
+};
+//# sourceMappingURL=command.js.map
\ No newline at end of file
diff --git a/packages/plugin-metro/dist/src/lib/start/command.js.map b/packages/plugin-metro/dist/src/lib/start/command.js.map
new file mode 100644
index 000000000..0af7e3ea3
--- /dev/null
+++ b/packages/plugin-metro/dist/src/lib/start/command.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"command.js","sourceRoot":"","sources":["../../../../src/lib/start/command.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/packages/plugin-metro/dist/src/lib/start/createDevMiddlewareLogger.d.ts b/packages/plugin-metro/dist/src/lib/start/createDevMiddlewareLogger.d.ts
new file mode 100644
index 000000000..576371fbe
--- /dev/null
+++ b/packages/plugin-metro/dist/src/lib/start/createDevMiddlewareLogger.d.ts
@@ -0,0 +1,18 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+import type { TerminalReporter } from 'metro';
+type LoggerFn = (...message: ReadonlyArray) => void;
+/**
+ * Create a dev-middleware logger object that will emit logs via Metro's
+ * terminal reporter.
+ */
+export default function createDevMiddlewareLogger(reporter: TerminalReporter): Readonly<{
+ info: LoggerFn;
+ error: LoggerFn;
+ warn: LoggerFn;
+}>;
+export {};
diff --git a/packages/plugin-metro/dist/src/lib/start/createDevMiddlewareLogger.js b/packages/plugin-metro/dist/src/lib/start/createDevMiddlewareLogger.js
new file mode 100644
index 000000000..936efd8ca
--- /dev/null
+++ b/packages/plugin-metro/dist/src/lib/start/createDevMiddlewareLogger.js
@@ -0,0 +1,27 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+/**
+ * Create a dev-middleware logger object that will emit logs via Metro's
+ * terminal reporter.
+ */
+export default function createDevMiddlewareLogger(reporter) {
+ return {
+ info: makeLogger(reporter, 'info'),
+ warn: makeLogger(reporter, 'warn'),
+ error: makeLogger(reporter, 'error'),
+ };
+}
+function makeLogger(reporter, level) {
+ return (...data) => reporter.update({
+ // @ts-expect-error - metro types are not updated
+ type: 'unstable_server_log',
+ // @ts-expect-error - metro types are not updated
+ level,
+ data,
+ });
+}
+//# sourceMappingURL=createDevMiddlewareLogger.js.map
\ No newline at end of file
diff --git a/packages/plugin-metro/dist/src/lib/start/createDevMiddlewareLogger.js.map b/packages/plugin-metro/dist/src/lib/start/createDevMiddlewareLogger.js.map
new file mode 100644
index 000000000..49ec024ab
--- /dev/null
+++ b/packages/plugin-metro/dist/src/lib/start/createDevMiddlewareLogger.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"createDevMiddlewareLogger.js","sourceRoot":"","sources":["../../../../src/lib/start/createDevMiddlewareLogger.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH;;;GAGG;AACH,MAAM,CAAC,OAAO,UAAU,yBAAyB,CAC/C,QAA0B;IAM1B,OAAO;QACL,IAAI,EAAE,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC;QAClC,IAAI,EAAE,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC;QAClC,KAAK,EAAE,UAAU,CAAC,QAAQ,EAAE,OAAO,CAAC;KACrC,CAAC;AACJ,CAAC;AAED,SAAS,UAAU,CACjB,QAA0B,EAC1B,KAAgC;IAEhC,OAAO,CAAC,GAAG,IAAoB,EAAE,EAAE,CACjC,QAAQ,CAAC,MAAM,CAAC;QACd,iDAAiD;QACjD,IAAI,EAAE,qBAAqB;QAC3B,iDAAiD;QACjD,KAAK;QACL,IAAI;KACL,CAAC,CAAC;AACP,CAAC"}
\ No newline at end of file
diff --git a/packages/plugin-metro/dist/src/lib/start/loadMetroConfig.d.ts b/packages/plugin-metro/dist/src/lib/start/loadMetroConfig.d.ts
new file mode 100644
index 000000000..5b5fa9eb6
--- /dev/null
+++ b/packages/plugin-metro/dist/src/lib/start/loadMetroConfig.d.ts
@@ -0,0 +1,24 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+import type { ConfigT, YargArguments } from 'metro-config';
+export type ConfigLoadingContext = Readonly<{
+ root: string;
+ reactNativePath: string;
+ platforms: Record;
+}>;
+/**
+ * Load Metro config.
+ *
+ * Allows the CLI to override select values in `metro.config.js` based on
+ * dynamic user options in `ctx`.
+ */
+export default function loadMetroConfig(ctx: {
+ platforms: Record;
+ reactNativeVersion: string;
+ reactNativePath: string;
+ root: string;
+}, options?: YargArguments): Promise;
diff --git a/packages/plugin-metro/dist/src/lib/start/loadMetroConfig.js b/packages/plugin-metro/dist/src/lib/start/loadMetroConfig.js
new file mode 100644
index 000000000..761308c62
--- /dev/null
+++ b/packages/plugin-metro/dist/src/lib/start/loadMetroConfig.js
@@ -0,0 +1,101 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+import { createRequire } from 'node:module';
+import path from 'node:path';
+import { logger, RockError } from '@rock-js/tools';
+import { loadConfig, mergeConfig, resolveConfig } from 'metro-config';
+import { reactNativePlatformResolver } from './metroPlatformResolver.js';
+/**
+ * Get the config options to override based on RN CLI inputs.
+ */
+function getCommunityCliDefaultConfig(ctx, config) {
+ const outOfTreePlatforms = Object.keys(ctx.platforms).filter(
+ // @ts-expect-error - TBD
+ (platform) => ctx.platforms[platform].npmPackageName);
+ const resolver = {
+ platforms: [...Object.keys(ctx.platforms), 'native'],
+ };
+ if (outOfTreePlatforms.length) {
+ // @ts-expect-error - TBD
+ resolver.resolveRequest = reactNativePlatformResolver(outOfTreePlatforms.reduce((result, platform) => {
+ // @ts-expect-error - TBD
+ result[platform] = ctx.platforms[platform].npmPackageName;
+ return result;
+ }, {}), config.resolver?.resolveRequest);
+ }
+ const require = createRequire(import.meta.url);
+ return {
+ resolver,
+ serializer: {
+ // We can include multiple copies of InitializeCore here because metro will
+ // only add ones that are already part of the bundle
+ getModulesRunBeforeMainModule: () => [
+ require.resolve(path.join(ctx.reactNativePath, 'Libraries/Core/InitializeCore'), { paths: [ctx.root] }),
+ ...outOfTreePlatforms.map((platform) => require.resolve(
+ // @ts-expect-error - TBD
+ `${ctx.platforms[platform].npmPackageName}/Libraries/Core/InitializeCore`, { paths: [ctx.root] })),
+ ],
+ },
+ };
+}
+/**
+ * Load Metro config.
+ *
+ * Allows the CLI to override select values in `metro.config.js` based on
+ * dynamic user options in `ctx`.
+ */
+export default async function loadMetroConfig(ctx, options = {}) {
+ const require = createRequire(import.meta.url);
+ let RNMetroConfig = null;
+ try {
+ RNMetroConfig = await import(require.resolve('@react-native/metro-config', { paths: [ctx.root] }));
+ }
+ catch {
+ throw new Error("Cannot resolve `@react-native/metro-config`. Ensure it is listed in your project's `devDependencies`.");
+ }
+ // Get the RN defaults before our customisations
+ const defaultConfig = RNMetroConfig.getDefaultConfig(ctx.root);
+ // Unflag the config as being loaded - it must be loaded again in userland.
+ // @ts-expect-error - overriding global
+ global.__REACT_NATIVE_METRO_CONFIG_LOADED = false;
+ // Add our defaults to `@react-native/metro-config` before the user config
+ // loads them.
+ // Available since RN 0.81
+ if (typeof RNMetroConfig.setFrameworkDefaults === 'function') {
+ RNMetroConfig.setFrameworkDefaults(getCommunityCliDefaultConfig(ctx, defaultConfig));
+ }
+ const cwd = ctx.root;
+ const projectConfig = await resolveConfig(options.config, cwd);
+ if (projectConfig.isEmpty) {
+ throw new RockError(`No Metro config found in ${cwd}`);
+ }
+ logger.debug(`Reading Metro config from ${projectConfig.filepath}`);
+ // @ts-expect-error - we're fine with this
+ if (!global.__REACT_NATIVE_METRO_CONFIG_LOADED) {
+ const warning = `
+=================================================================================================
+From React Native 0.73, your project's Metro config should extend '@react-native/metro-config'
+or it will fail to build. Please copy the template at:
+https://github.com/react-native-community/template/blob/main/template/metro.config.js
+This warning will be removed in future (https://github.com/facebook/metro/issues/1018).
+=================================================================================================
+ `;
+ for (const line of warning.trim().split('\n')) {
+ console.warn(line);
+ }
+ }
+ const config = await loadConfig({ cwd, ...options });
+ if (typeof RNMetroConfig.setFrameworkDefaults === 'function') {
+ return config;
+ }
+ else {
+ // Fallback to the old API for RN < 0.81
+ const overrideConfig = getCommunityCliDefaultConfig(ctx, config);
+ return mergeConfig(config, overrideConfig);
+ }
+}
+//# sourceMappingURL=loadMetroConfig.js.map
\ No newline at end of file
diff --git a/packages/plugin-metro/dist/src/lib/start/loadMetroConfig.js.map b/packages/plugin-metro/dist/src/lib/start/loadMetroConfig.js.map
new file mode 100644
index 000000000..d1bb19233
--- /dev/null
+++ b/packages/plugin-metro/dist/src/lib/start/loadMetroConfig.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"loadMetroConfig.js","sourceRoot":"","sources":["../../../../src/lib/start/loadMetroConfig.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/packages/plugin-metro/dist/src/lib/start/metroPlatformResolver.d.ts b/packages/plugin-metro/dist/src/lib/start/metroPlatformResolver.d.ts
new file mode 100644
index 000000000..b156e337d
--- /dev/null
+++ b/packages/plugin-metro/dist/src/lib/start/metroPlatformResolver.d.ts
@@ -0,0 +1,24 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+import type { CustomResolver } from 'metro-resolver';
+/**
+ * This is an implementation of a metro resolveRequest option which will remap react-native imports
+ * to different npm packages based on the platform requested. This allows a single metro instance/config
+ * to produce bundles for multiple out of tree platforms at a time.
+ *
+ * @param platformImplementations
+ * A map of platform to npm package that implements that platform
+ *
+ * Ex:
+ * {
+ * windows: 'react-native-windows'
+ * macos: 'react-native-macos'
+ * }
+ */
+export declare function reactNativePlatformResolver(platformImplementations: {
+ [platform: string]: string;
+}, customResolver: CustomResolver | null | undefined): CustomResolver;
diff --git a/packages/plugin-metro/dist/src/lib/start/metroPlatformResolver.js b/packages/plugin-metro/dist/src/lib/start/metroPlatformResolver.js
new file mode 100644
index 000000000..ba2f50841
--- /dev/null
+++ b/packages/plugin-metro/dist/src/lib/start/metroPlatformResolver.js
@@ -0,0 +1,38 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+/**
+ * This is an implementation of a metro resolveRequest option which will remap react-native imports
+ * to different npm packages based on the platform requested. This allows a single metro instance/config
+ * to produce bundles for multiple out of tree platforms at a time.
+ *
+ * @param platformImplementations
+ * A map of platform to npm package that implements that platform
+ *
+ * Ex:
+ * {
+ * windows: 'react-native-windows'
+ * macos: 'react-native-macos'
+ * }
+ */
+export function reactNativePlatformResolver(platformImplementations, customResolver) {
+ return (context, moduleName, platform) => {
+ let modifiedModuleName = moduleName;
+ if (platform != null && platformImplementations[platform]) {
+ if (moduleName === 'react-native') {
+ modifiedModuleName = platformImplementations[platform];
+ }
+ else if (moduleName.startsWith('react-native/')) {
+ modifiedModuleName = `${platformImplementations[platform]}/${modifiedModuleName.slice('react-native/'.length)}`;
+ }
+ }
+ if (customResolver) {
+ return customResolver(context, modifiedModuleName, platform);
+ }
+ return context.resolveRequest(context, modifiedModuleName, platform);
+ };
+}
+//# sourceMappingURL=metroPlatformResolver.js.map
\ No newline at end of file
diff --git a/packages/plugin-metro/dist/src/lib/start/metroPlatformResolver.js.map b/packages/plugin-metro/dist/src/lib/start/metroPlatformResolver.js.map
new file mode 100644
index 000000000..047f8f306
--- /dev/null
+++ b/packages/plugin-metro/dist/src/lib/start/metroPlatformResolver.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"metroPlatformResolver.js","sourceRoot":"","sources":["../../../../src/lib/start/metroPlatformResolver.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,2BAA2B,CACzC,uBAEC,EACD,cAAiD;IAEjD,OAAO,CAAC,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE;QACvC,IAAI,kBAAkB,GAAG,UAAU,CAAC;QACpC,IAAI,QAAQ,IAAI,IAAI,IAAI,uBAAuB,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC1D,IAAI,UAAU,KAAK,cAAc,EAAE,CAAC;gBAClC,kBAAkB,GAAG,uBAAuB,CAAC,QAAQ,CAAC,CAAC;YACzD,CAAC;iBAAM,IAAI,UAAU,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;gBAClD,kBAAkB,GAAG,GACnB,uBAAuB,CAAC,QAAQ,CAClC,IAAI,kBAAkB,CAAC,KAAK,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC;YACzD,CAAC;QACH,CAAC;QACD,IAAI,cAAc,EAAE,CAAC;YACnB,OAAO,cAAc,CAAC,OAAO,EAAE,kBAAkB,EAAE,QAAQ,CAAC,CAAC;QAC/D,CAAC;QACD,OAAO,OAAO,CAAC,cAAc,CAAC,OAAO,EAAE,kBAAkB,EAAE,QAAQ,CAAC,CAAC;IACvE,CAAC,CAAC;AACJ,CAAC"}
\ No newline at end of file
diff --git a/packages/plugin-metro/dist/src/lib/start/runServer.d.ts b/packages/plugin-metro/dist/src/lib/start/runServer.d.ts
new file mode 100644
index 000000000..760ec9c5f
--- /dev/null
+++ b/packages/plugin-metro/dist/src/lib/start/runServer.d.ts
@@ -0,0 +1,32 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+export type StartCommandArgs = {
+ assetPlugins?: string[];
+ cert?: string;
+ customLogReporterPath?: string;
+ host?: string;
+ https?: boolean;
+ maxWorkers?: string;
+ key?: string;
+ platforms: string[];
+ port?: string;
+ resetCache?: boolean;
+ sourceExts?: string[];
+ transformer?: string;
+ watchFolders?: string[];
+ config?: string;
+ projectRoot?: string;
+ interactive: boolean;
+ clientLogs: boolean;
+};
+declare function runServer(options: {
+ platforms: Record;
+ reactNativeVersion: string;
+ reactNativePath: string;
+ root: string;
+}, args: StartCommandArgs): Promise;
+export default runServer;
diff --git a/packages/plugin-metro/dist/src/lib/start/runServer.js b/packages/plugin-metro/dist/src/lib/start/runServer.js
new file mode 100644
index 000000000..40bb4269a
--- /dev/null
+++ b/packages/plugin-metro/dist/src/lib/start/runServer.js
@@ -0,0 +1,138 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+import { createRequire } from 'node:module';
+import path from 'node:path';
+import url from 'node:url';
+import { createDevServerMiddleware } from '@react-native-community/cli-server-api';
+import { color } from '@rock-js/tools';
+import Metro from 'metro';
+import { Terminal } from 'metro-core';
+import { getDevMiddleware } from '../getReactNativeDeps.js';
+import attachKeyHandlers from './attachKeyHandlers.js';
+import createDevMiddlewareLogger from './createDevMiddlewareLogger.js';
+import loadMetroConfig from './loadMetroConfig.js';
+async function runServer(options, args) {
+ const metroConfig = await loadMetroConfig({
+ platforms: options.platforms,
+ reactNativeVersion: options.reactNativeVersion,
+ reactNativePath: options.reactNativePath,
+ root: options.root,
+ }, {
+ config: args.config,
+ maxWorkers: args.maxWorkers,
+ port: args.port,
+ resetCache: args.resetCache,
+ watchFolders: args.watchFolders,
+ projectRoot: args.projectRoot,
+ sourceExts: args.sourceExts,
+ });
+ const hostname = args.host?.length ? args.host : 'localhost';
+ const { projectRoot, server: { port }, watchFolders, } = metroConfig;
+ const protocol = args.https === true ? 'https' : 'http';
+ const devServerUrl = url.format({ protocol, hostname, port });
+ console.info(`Starting dev server on ${devServerUrl}\n`);
+ if (args.assetPlugins) {
+ // @ts-expect-error Assigning to readonly property
+ metroConfig.transformer.assetPlugins = args.assetPlugins.map((plugin) => require.resolve(plugin));
+ }
+ // TODO(T214991636): Remove legacy Metro log forwarding
+ if (!args.clientLogs) {
+ // @ts-expect-error Assigning to readonly property
+ metroConfig.server.forwardClientLogs = false;
+ }
+ let reportEvent = () => {
+ // do nothing
+ };
+ const terminal = new Terminal(process.stdout);
+ const ReporterImpl = getReporterImpl(args.customLogReporterPath);
+ // @ts-expect-error - metro types are not updated
+ const terminalReporter = new ReporterImpl(terminal);
+ const { middleware: communityMiddleware, websocketEndpoints: communityWebsocketEndpoints, messageSocketEndpoint, eventsSocketEndpoint, } = createDevServerMiddleware({
+ host: hostname,
+ port,
+ watchFolders,
+ });
+ const { createDevMiddleware } = await getDevMiddleware(options.reactNativePath);
+ const { middleware, websocketEndpoints } = createDevMiddleware({
+ projectRoot,
+ serverBaseUrl: devServerUrl,
+ logger: createDevMiddlewareLogger(terminalReporter),
+ });
+ const reporter = {
+ update(event) {
+ terminalReporter.update(event);
+ if (reportEvent) {
+ reportEvent(event);
+ }
+ if (args.interactive && event.type === 'initialize_done') {
+ terminalReporter.update({
+ type: 'unstable_server_log',
+ level: 'info',
+ data: `Dev server ready. ${color.dim('Press Ctrl+C to exit.')}`,
+ });
+ attachKeyHandlers({
+ devServerUrl,
+ // @ts-expect-error - TBD
+ messageSocket: messageSocketEndpoint,
+ reporter: terminalReporter,
+ });
+ }
+ },
+ };
+ // @ts-expect-error Assigning to readonly property
+ metroConfig.reporter = reporter;
+ const { httpServer: serverInstance } = await Metro.runServer(metroConfig, {
+ host: args.host,
+ secure: args.https,
+ secureCert: args.cert,
+ secureKey: args.key,
+ unstable_extraMiddleware: [communityMiddleware, middleware],
+ websocketEndpoints: {
+ ...communityWebsocketEndpoints,
+ ...websocketEndpoints,
+ },
+ });
+ reportEvent = eventsSocketEndpoint.reportEvent;
+ // In Node 8, the default keep-alive for an HTTP connection is 5 seconds. In
+ // early versions of Node 8, this was implemented in a buggy way which caused
+ // some HTTP responses (like those containing large JS bundles) to be
+ // terminated early.
+ //
+ // As a workaround, arbitrarily increase the keep-alive from 5 to 30 seconds,
+ // which should be enough to send even the largest of JS bundles.
+ //
+ // For more info: https://github.com/nodejs/node/issues/13391
+ //
+ serverInstance.keepAliveTimeout = 30000;
+}
+const require = createRequire(import.meta.url);
+function getReporterImpl(customLogReporterPath) {
+ if (customLogReporterPath == null) {
+ try {
+ return require('metro').TerminalReporter;
+ }
+ catch {
+ // Fallback to legacy path for Metro < 0.83
+ return require('metro/src/lib/TerminalReporter');
+ }
+ }
+ try {
+ // First we let require resolve it, so we can require packages in node_modules
+ // as expected. eg: require('my-package/reporter');
+ return require(customLogReporterPath);
+ }
+ catch (e) {
+ if (e instanceof Error && 'code' in e && e.code !== 'MODULE_NOT_FOUND') {
+ throw e;
+ }
+ // If that doesn't work, then we next try relative to the cwd, eg:
+ // require('./reporter');
+ return require(path.resolve(customLogReporterPath));
+ }
+}
+export default runServer;
+//# sourceMappingURL=runServer.js.map
\ No newline at end of file
diff --git a/packages/plugin-metro/dist/src/lib/start/runServer.js.map b/packages/plugin-metro/dist/src/lib/start/runServer.js.map
new file mode 100644
index 000000000..78076d438
--- /dev/null
+++ b/packages/plugin-metro/dist/src/lib/start/runServer.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"runServer.js","sourceRoot":"","sources":["../../../../src/lib/start/runServer.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/packages/plugin-repack/dist/src/index.d.ts b/packages/plugin-repack/dist/src/index.d.ts
new file mode 100644
index 000000000..10556cbda
--- /dev/null
+++ b/packages/plugin-repack/dist/src/index.d.ts
@@ -0,0 +1,2 @@
+export * from './lib/pluginRepack.js';
+export { startDevServer } from './lib/pluginRepack.js';
diff --git a/packages/plugin-repack/dist/src/index.js b/packages/plugin-repack/dist/src/index.js
new file mode 100644
index 000000000..2a157da20
--- /dev/null
+++ b/packages/plugin-repack/dist/src/index.js
@@ -0,0 +1,3 @@
+export * from './lib/pluginRepack.js';
+export { startDevServer } from './lib/pluginRepack.js';
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/packages/plugin-repack/dist/src/index.js.map b/packages/plugin-repack/dist/src/index.js.map
new file mode 100644
index 000000000..93ad4a218
--- /dev/null
+++ b/packages/plugin-repack/dist/src/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC"}
\ No newline at end of file
diff --git a/packages/plugin-repack/dist/src/lib/pluginRepack.d.ts b/packages/plugin-repack/dist/src/lib/pluginRepack.d.ts
new file mode 100644
index 000000000..499378502
--- /dev/null
+++ b/packages/plugin-repack/dist/src/lib/pluginRepack.d.ts
@@ -0,0 +1,9 @@
+import type { BundlerPluginOutput, PluginApi, StartDevServerArgs } from '@rock-js/config';
+type PluginConfig = {
+ platforms?: {
+ [key: string]: object;
+ };
+};
+export declare function startDevServer({ root, args, reactNativeVersion: _reactNativeVersion, reactNativePath, platforms, }: StartDevServerArgs, pluginConfig?: PluginConfig): Promise;
+export declare const pluginRepack: (pluginConfig?: PluginConfig) => (api: PluginApi) => BundlerPluginOutput;
+export default pluginRepack;
diff --git a/packages/plugin-repack/dist/src/lib/pluginRepack.js b/packages/plugin-repack/dist/src/lib/pluginRepack.js
new file mode 100644
index 000000000..402a72cb8
--- /dev/null
+++ b/packages/plugin-repack/dist/src/lib/pluginRepack.js
@@ -0,0 +1,85 @@
+import commands from '@callstack/repack/commands/rspack';
+import { colorLink, findDevServerPort, intro, logger, RockError, runHermes, spinner, } from '@rock-js/tools';
+const startCommand = commands.find((command) => command.name === 'start');
+const bundleCommand = commands.find((command) => command.name === 'bundle');
+export async function startDevServer({ root, args, reactNativeVersion: _reactNativeVersion, reactNativePath, platforms, }, pluginConfig = {}) {
+ const { port, startDevServer } = await findDevServerPort(args.port ? Number(args.port) : 8081, root);
+ if (!startDevServer) {
+ return;
+ }
+ if (!startCommand) {
+ throw new RockError('Re.Pack "start" command not found.');
+ }
+ logger.info('Starting Re.Pack dev server...');
+ startCommand.func([],
+ // @ts-expect-error TODO fix getPlatforms type
+ { reactNativePath, root, platforms, ...pluginConfig }, { ...args, port });
+}
+export const pluginRepack = (pluginConfig = {}) => (api) => {
+ if (!startCommand) {
+ throw new RockError('Re.Pack "start" command not found.');
+ }
+ if (!bundleCommand) {
+ throw new RockError('Re.Pack "bundle" command not found.');
+ }
+ api.registerCommand({
+ name: 'start',
+ description: 'Starts Re.Pack dev server.',
+ action: async (args) => {
+ startDevServer({
+ root: api.getProjectRoot(),
+ reactNativeVersion: api.getReactNativeVersion(),
+ reactNativePath: api.getReactNativePath(),
+ platforms: api.getPlatforms(),
+ // @ts-expect-error Re.Pack doesn't have clientLogs
+ args,
+ });
+ },
+ // @ts-expect-error fixup types
+ options: startCommand.options,
+ });
+ api.registerCommand({
+ name: 'bundle',
+ description: 'Bundles JavaScript with Re.Pack.',
+ action: async (args) => {
+ if (!args.entryFile) {
+ throw new RockError('"rock bundle" command is missing "--entry-file" argument.');
+ }
+ intro('Compiling JS bundle with Re.Pack');
+ const root = api.getProjectRoot();
+ const platforms = api.getPlatforms();
+ await bundleCommand.func([],
+ // @ts-expect-error TODO fix getPlatforms type
+ { root, platforms, ...pluginConfig }, args);
+ if (args.hermes) {
+ if (!args.bundleOutput) {
+ throw new RockError('Missing "--bundle-output" argument to run "bundle --hermes".');
+ }
+ const loader = spinner();
+ loader.start('Running Hermes compiler...');
+ await runHermes({
+ bundleOutputPath: args.bundleOutput,
+ sourcemapOutputPath: args.sourcemapOutput,
+ });
+ loader.stop(`Hermes bytecode bundle created at: ${colorLink(args.bundleOutput)}`);
+ }
+ else if (args.bundleOutput) {
+ logger.info(`JavaScript bundle created at: ${colorLink(args.bundleOutput)}`);
+ }
+ },
+ options: [
+ ...bundleCommand.options,
+ {
+ name: '--hermes',
+ description: 'Passes the output JS bundle to Hermes compiler and outputs a bytecode file.',
+ },
+ ],
+ });
+ return {
+ name: '@rock-js/plugin-repack',
+ description: 'Rock plugin for Re.Pack toolkit with Rspack.',
+ start: startDevServer,
+ };
+};
+export default pluginRepack;
+//# sourceMappingURL=pluginRepack.js.map
\ No newline at end of file
diff --git a/packages/plugin-repack/dist/src/lib/pluginRepack.js.map b/packages/plugin-repack/dist/src/lib/pluginRepack.js.map
new file mode 100644
index 000000000..ff01b53ef
--- /dev/null
+++ b/packages/plugin-repack/dist/src/lib/pluginRepack.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"pluginRepack.js","sourceRoot":"","sources":["../../../src/lib/pluginRepack.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/packages/provider-github/dist/src/index.d.ts b/packages/provider-github/dist/src/index.d.ts
new file mode 100644
index 000000000..b160ce9ea
--- /dev/null
+++ b/packages/provider-github/dist/src/index.d.ts
@@ -0,0 +1 @@
+export { providerGitHub } from './lib/providerGitHub.js';
diff --git a/packages/provider-github/dist/src/index.js b/packages/provider-github/dist/src/index.js
new file mode 100644
index 000000000..d69a7143f
--- /dev/null
+++ b/packages/provider-github/dist/src/index.js
@@ -0,0 +1,2 @@
+export { providerGitHub } from './lib/providerGitHub.js';
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/packages/provider-github/dist/src/index.js.map b/packages/provider-github/dist/src/index.js.map
new file mode 100644
index 000000000..37cbc7b6c
--- /dev/null
+++ b/packages/provider-github/dist/src/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC"}
\ No newline at end of file
diff --git a/packages/provider-github/dist/src/lib/artifacts.d.ts b/packages/provider-github/dist/src/lib/artifacts.d.ts
new file mode 100644
index 000000000..d6948fcdb
--- /dev/null
+++ b/packages/provider-github/dist/src/lib/artifacts.d.ts
@@ -0,0 +1,12 @@
+import { type RemoteArtifact } from '@rock-js/tools';
+import { type GitHubRepoDetails } from './config.js';
+type GitHubArtifact = {
+ id: number;
+ name: string;
+ expiresAt: string | null;
+ sizeInBytes: number;
+ downloadUrl: string;
+};
+export declare function fetchGitHubArtifactsByName(name: string | undefined, repoDetails: GitHubRepoDetails, limit?: number): Promise;
+export declare function deleteGitHubArtifacts(artifacts: GitHubArtifact[], repoDetails: GitHubRepoDetails, artifactName: string): Promise;
+export {};
diff --git a/packages/provider-github/dist/src/lib/artifacts.js b/packages/provider-github/dist/src/lib/artifacts.js
new file mode 100644
index 000000000..a996824de
--- /dev/null
+++ b/packages/provider-github/dist/src/lib/artifacts.js
@@ -0,0 +1,98 @@
+import { cacheManager, color, colorLink, logger, RockError, } from '@rock-js/tools';
+const PAGE_SIZE = 100; // Maximum allowed by GitHub API
+export async function fetchGitHubArtifactsByName(name, repoDetails, limit) {
+ let page = 1;
+ const result = [];
+ const owner = repoDetails.owner;
+ const repo = repoDetails.repository;
+ try {
+ while (true) {
+ const url = `https://api.github.com/repos/${owner}/${repo}/actions/artifacts?per_page=${limit ?? PAGE_SIZE}&page=${page}${name ? `&name=${name}` : ''}`;
+ let data;
+ try {
+ const response = await fetch(url, {
+ headers: { Authorization: `token ${repoDetails.token}` },
+ });
+ if (!response.ok) {
+ throw new Error(`HTTP error: ${response.status} ${response.statusText}`);
+ }
+ data = await response.json();
+ }
+ catch (error) {
+ throw new Error(`Error fetching artifacts from ${colorLink(url)}: ${error}`);
+ }
+ const artifacts = data.artifacts
+ .filter((artifact) => !artifact.expired && artifact.workflow_run?.id)
+ .map((artifact) => ({
+ id: artifact.id,
+ name: artifact.name,
+ sizeInBytes: artifact.size_in_bytes,
+ expiresAt: artifact.expires_at,
+ downloadUrl: artifact.archive_download_url,
+ }));
+ result.push(...artifacts);
+ if (artifacts.length < PAGE_SIZE) {
+ break;
+ }
+ page += 1;
+ }
+ }
+ catch (error) {
+ if (error.message.includes('401 Unauthorized')) {
+ cacheManager.remove('githubToken');
+ throw new RockError(`Failed to fetch GitHub artifacts due to invalid or expired GitHub Personal Access Token provided.
+Update the token under "${color.bold('remoteCacheProvider')}" key in ${colorLink('rock.config.mjs')} config file.
+
+๐ Read more about generating a new token: ${colorLink('https://rockjs.dev/docs/github-actions/configuration#generate-github-personal-access-token-for-downloading-cached-builds')}`);
+ }
+ if (error.message.includes('404 Not Found')) {
+ throw new RockError(`Failed to fetch GitHub artifacts due to "404 Not Found" error. This can happen for the following reasons:
+- permission mismatch between your GitHub Personal Access Token and the repository
+- you're blocked by the owner of the repository
+- repository address is incorrect
+
+Make sure the repository information and token under "${color.bold('remoteCacheProvider')}" key in ${colorLink('rock.config.mjs')} config file is valid.
+
+๐ Read more about generating a new token: ${colorLink('https://rockjs.dev/docs/github-actions/configuration#generate-github-personal-access-token-for-downloading-cached-builds')}`);
+ }
+ throw new RockError(`Failed to fetch GitHub artifacts`, { cause: error });
+ }
+ result.sort((a, b) => {
+ const expiresA = a.expiresAt ?? '0000-00-00';
+ const expiresB = b.expiresAt ?? '0000-00-00';
+ // Sort in descending order
+ return expiresB.localeCompare(expiresA);
+ });
+ return result;
+}
+export async function deleteGitHubArtifacts(artifacts, repoDetails, artifactName) {
+ const deletedArtifacts = [];
+ try {
+ const owner = repoDetails.owner;
+ const repo = repoDetails.repository;
+ // Delete all matching artifacts
+ for (const artifact of artifacts) {
+ const artifactId = artifact.id;
+ const url = `https://api.github.com/repos/${owner}/${repo}/actions/artifacts/${artifactId}`;
+ const response = await fetch(url, {
+ method: 'DELETE',
+ headers: {
+ Authorization: `Bearer ${repoDetails.token}`,
+ Accept: 'application/vnd.github+json',
+ },
+ });
+ if (!response.ok) {
+ logger.warn(`Failed to delete artifact ID ${artifactId}: ${response.status} ${response.statusText}`);
+ continue;
+ }
+ deletedArtifacts.push({ name: artifact.name, url: artifact.downloadUrl });
+ }
+ return deletedArtifacts;
+ }
+ catch (error) {
+ throw new RockError(`Failed to delete artifacts named "${artifactName}"`, {
+ cause: error,
+ });
+ }
+}
+//# sourceMappingURL=artifacts.js.map
\ No newline at end of file
diff --git a/packages/provider-github/dist/src/lib/artifacts.js.map b/packages/provider-github/dist/src/lib/artifacts.js.map
new file mode 100644
index 000000000..85b82981c
--- /dev/null
+++ b/packages/provider-github/dist/src/lib/artifacts.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"artifacts.js","sourceRoot":"","sources":["../../../src/lib/artifacts.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/packages/provider-github/dist/src/lib/config.d.ts b/packages/provider-github/dist/src/lib/config.d.ts
new file mode 100644
index 000000000..5d767e731
--- /dev/null
+++ b/packages/provider-github/dist/src/lib/config.d.ts
@@ -0,0 +1,8 @@
+export declare function getGitHubToken(): string | undefined;
+export declare function promptForGitHubToken(): Promise;
+export type GitHubRepoDetails = {
+ owner: string;
+ repository: string;
+ token: string;
+};
+export declare function detectGitHubRepoDetails(): Promise;
diff --git a/packages/provider-github/dist/src/lib/config.js b/packages/provider-github/dist/src/lib/config.js
new file mode 100644
index 000000000..02ba9ee22
--- /dev/null
+++ b/packages/provider-github/dist/src/lib/config.js
@@ -0,0 +1,56 @@
+import { cacheManager, colorLink, logger, promptPassword, RockError, spawn, } from '@rock-js/tools';
+import * as r from 'ts-regex-builder';
+import { getGitRemote } from './getGitRemote.js';
+const GITHUB_REPO_REGEX = r.buildRegExp([
+ r.startOfString,
+ r.choiceOf('git@', 'https://'),
+ r.oneOrMore(/[^:/]/),
+ r.anyOf(':/'),
+ r.capture(r.oneOrMore(/[^/]/)), // organization
+ '/',
+ r.capture(r.oneOrMore(r.any, { greedy: false })), // repository
+ r.optional('.git'),
+ r.endOfString,
+]);
+export function getGitHubToken() {
+ return cacheManager.get('githubToken');
+}
+export async function promptForGitHubToken() {
+ const githubToken = (await promptPassword({
+ message: 'Paste your GitHub Personal Access Token',
+ validate: (value) => value.length === 0 ? 'Value is required.' : undefined,
+ }));
+ cacheManager.set('githubToken', githubToken);
+ return githubToken;
+}
+export async function detectGitHubRepoDetails() {
+ const gitRemote = await getGitRemote();
+ if (!gitRemote) {
+ throw new RockError(`No git remote found for GitHub repository.`);
+ }
+ try {
+ const { output: url } = await spawn('git', ['config', '--get', `remote.${gitRemote}.url`], { stdio: 'pipe' });
+ const match = url.match(GITHUB_REPO_REGEX);
+ if (!match) {
+ throw new RockError(`The remote URL "${url}" doesn't look like a GitHub repo.`);
+ }
+ let token = getGitHubToken();
+ if (!token) {
+ logger.warn(`No GitHub Personal Access Token found necessary to download cached builds.
+Please generate one at: ${colorLink('https://github.com/settings/tokens')}
+Include "repo", "workflow", and "read:org" permissions.`);
+ token = await promptForGitHubToken();
+ }
+ return {
+ owner: match[1],
+ repository: match[2],
+ token,
+ };
+ }
+ catch (error) {
+ throw new RockError('Unable to detect GitHub repository details.', {
+ cause: error,
+ });
+ }
+}
+//# sourceMappingURL=config.js.map
\ No newline at end of file
diff --git a/packages/provider-github/dist/src/lib/config.js.map b/packages/provider-github/dist/src/lib/config.js.map
new file mode 100644
index 000000000..34de5d319
--- /dev/null
+++ b/packages/provider-github/dist/src/lib/config.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/lib/config.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,SAAS,EACT,MAAM,EACN,cAAc,EACd,SAAS,EACT,KAAK,GACN,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,CAAC,MAAM,kBAAkB,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,MAAM,iBAAiB,GAAG,CAAC,CAAC,WAAW,CAAC;IACtC,CAAC,CAAC,aAAa;IACf,CAAC,CAAC,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC9B,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC;IACpB,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC;IACb,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,EAAE,eAAe;IAC/C,GAAG;IACH,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,aAAa;IAC/D,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;IAClB,CAAC,CAAC,WAAW;CACd,CAAC,CAAC;AAEH,MAAM,UAAU,cAAc;IAC5B,OAAO,YAAY,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB;IACxC,MAAM,WAAW,GAAG,CAAC,MAAM,cAAc,CAAC;QACxC,OAAO,EAAE,yCAAyC;QAClD,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAClB,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,SAAS;KACxD,CAAC,CAAW,CAAC;IACd,YAAY,CAAC,GAAG,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;IAC7C,OAAO,WAAW,CAAC;AACrB,CAAC;AAQD,MAAM,CAAC,KAAK,UAAU,uBAAuB;IAC3C,MAAM,SAAS,GAAG,MAAM,YAAY,EAAE,CAAC;IAEvC,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CAAC,4CAA4C,CAAC,CAAC;IACpE,CAAC;IAED,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,MAAM,KAAK,CACjC,KAAK,EACL,CAAC,QAAQ,EAAE,OAAO,EAAE,UAAU,SAAS,MAAM,CAAC,EAC9C,EAAE,KAAK,EAAE,MAAM,EAAE,CAClB,CAAC;QAEF,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;QAC3C,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,SAAS,CACjB,mBAAmB,GAAG,oCAAoC,CAC3D,CAAC;QACJ,CAAC;QACD,IAAI,KAAK,GAAG,cAAc,EAAE,CAAC;QAC7B,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,CAAC,IAAI,CACT;0BACkB,SAAS,CAAC,oCAAoC,CAAC;wDACjB,CACjD,CAAC;YACF,KAAK,GAAG,MAAM,oBAAoB,EAAE,CAAC;QACvC,CAAC;QAED,OAAO;YACL,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;YACf,UAAU,EAAE,KAAK,CAAC,CAAC,CAAC;YACpB,KAAK;SACN,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CAAC,6CAA6C,EAAE;YACjE,KAAK,EAAE,KAAK;SACb,CAAC,CAAC;IACL,CAAC;AACH,CAAC"}
\ No newline at end of file
diff --git a/packages/provider-github/dist/src/lib/getGitRemote.d.ts b/packages/provider-github/dist/src/lib/getGitRemote.d.ts
new file mode 100644
index 000000000..41dcb5e7a
--- /dev/null
+++ b/packages/provider-github/dist/src/lib/getGitRemote.d.ts
@@ -0,0 +1 @@
+export declare function getGitRemote(): Promise;
diff --git a/packages/provider-github/dist/src/lib/getGitRemote.js b/packages/provider-github/dist/src/lib/getGitRemote.js
new file mode 100644
index 000000000..38f22e465
--- /dev/null
+++ b/packages/provider-github/dist/src/lib/getGitRemote.js
@@ -0,0 +1,29 @@
+import { cacheManager, promptSelect, spawn } from '@rock-js/tools';
+export async function getGitRemote() {
+ let gitRemote = cacheManager.get('gitRemote');
+ if (gitRemote) {
+ return gitRemote;
+ }
+ const { output: remoteOutput } = await spawn('git', ['remote'], {
+ stdio: 'pipe',
+ });
+ const remotes = remoteOutput.split('\n').filter(Boolean);
+ if (remotes.length > 1) {
+ gitRemote = await promptSelect({
+ message: 'Select git remote of the upstream repository:',
+ options: remotes.map((remote) => ({
+ value: remote,
+ label: remote,
+ })),
+ });
+ cacheManager.set('gitRemote', gitRemote);
+ }
+ else if (remotes.length === 1) {
+ gitRemote = remotes[0];
+ }
+ else {
+ return null;
+ }
+ return gitRemote;
+}
+//# sourceMappingURL=getGitRemote.js.map
\ No newline at end of file
diff --git a/packages/provider-github/dist/src/lib/getGitRemote.js.map b/packages/provider-github/dist/src/lib/getGitRemote.js.map
new file mode 100644
index 000000000..6ef6f231d
--- /dev/null
+++ b/packages/provider-github/dist/src/lib/getGitRemote.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"getGitRemote.js","sourceRoot":"","sources":["../../../src/lib/getGitRemote.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAEnE,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,IAAI,SAAS,GAAG,YAAY,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAC9C,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC,QAAQ,CAAC,EAAE;QAC9D,KAAK,EAAE,MAAM;KACd,CAAC,CAAC;IACH,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACzD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,SAAS,GAAG,MAAM,YAAY,CAAC;YAC7B,OAAO,EAAE,+CAA+C;YACxD,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;gBAChC,KAAK,EAAE,MAAM;gBACb,KAAK,EAAE,MAAM;aACd,CAAC,CAAC;SACJ,CAAC,CAAC;QAEH,YAAY,CAAC,GAAG,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;IAC3C,CAAC;SAAM,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChC,SAAS,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACzB,CAAC;SAAM,CAAC;QACN,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC"}
\ No newline at end of file
diff --git a/packages/provider-github/dist/src/lib/providerGitHub.d.ts b/packages/provider-github/dist/src/lib/providerGitHub.d.ts
new file mode 100644
index 000000000..39968e377
--- /dev/null
+++ b/packages/provider-github/dist/src/lib/providerGitHub.d.ts
@@ -0,0 +1,32 @@
+import type { RemoteArtifact, RemoteBuildCache } from '@rock-js/tools';
+import { type GitHubRepoDetails } from './config.js';
+export declare class GitHubBuildCache implements RemoteBuildCache {
+ name: string;
+ repoDetails: GitHubRepoDetails | null;
+ constructor(config?: {
+ owner: string;
+ repository: string;
+ token: string;
+ });
+ getRepoDetails(): Promise;
+ list({ artifactName, limit, }: {
+ artifactName?: string;
+ limit?: number;
+ }): Promise;
+ download({ artifactName, }: {
+ artifactName: string;
+ }): Promise;
+ delete({ artifactName, limit, skipLatest, }: {
+ artifactName: string;
+ limit?: number;
+ skipLatest?: boolean;
+ }): Promise;
+ upload(): Promise Buffer), contentType?: string | undefined) => Response;
+ }>;
+}
+export declare const providerGitHub: (options?: {
+ owner: string;
+ repository: string;
+ token: string;
+}) => () => RemoteBuildCache;
diff --git a/packages/provider-github/dist/src/lib/providerGitHub.js b/packages/provider-github/dist/src/lib/providerGitHub.js
new file mode 100644
index 000000000..6f0dcc845
--- /dev/null
+++ b/packages/provider-github/dist/src/lib/providerGitHub.js
@@ -0,0 +1,61 @@
+import { deleteGitHubArtifacts, fetchGitHubArtifactsByName, } from './artifacts.js';
+import { detectGitHubRepoDetails } from './config.js';
+export class GitHubBuildCache {
+ name = 'GitHub';
+ repoDetails = null;
+ constructor(config) {
+ if (config) {
+ const token = config.token || process.env['GITHUB_TOKEN'];
+ if (!token) {
+ throw new Error('GitHub Personal Access Token is required to fetch remote cache. Configure `GITHUB_TOKEN` variable in .env file or pass it as a `token` argument.');
+ }
+ this.repoDetails = {
+ owner: config.owner,
+ repository: config.repository,
+ token,
+ };
+ }
+ }
+ async getRepoDetails() {
+ if (!this.repoDetails) {
+ this.repoDetails = await detectGitHubRepoDetails();
+ }
+ return this.repoDetails;
+ }
+ async list({ artifactName, limit, }) {
+ const repoDetails = await this.getRepoDetails();
+ const artifacts = await fetchGitHubArtifactsByName(artifactName, repoDetails, limit);
+ return artifacts.map((artifact) => ({
+ name: artifact.name,
+ url: artifact.downloadUrl,
+ id: String(artifact.id),
+ }));
+ }
+ async download({ artifactName, }) {
+ const repoDetails = await this.getRepoDetails();
+ const artifacts = await this.list({ artifactName });
+ if (artifacts.length === 0) {
+ throw new Error(`No artifact found with name "${artifactName}"`);
+ }
+ return fetch(artifacts[0].url, {
+ headers: {
+ Authorization: `token ${repoDetails.token}`,
+ 'Accept-Encoding': 'None',
+ },
+ });
+ }
+ async delete({ artifactName, limit, skipLatest, }) {
+ const repoDetails = await this.getRepoDetails();
+ const artifacts = await fetchGitHubArtifactsByName(artifactName, repoDetails, limit);
+ if (artifacts.length === 0) {
+ throw new Error(`No artifact found with name "${artifactName}"`);
+ }
+ const [, ...rest] = artifacts;
+ return await deleteGitHubArtifacts(skipLatest ? rest : artifacts, repoDetails, artifactName);
+ }
+ async upload() {
+ throw new Error('Uploading artifacts to GitHub is not supported through GitHub API. See: https://docs.github.com/en/rest/actions/artifacts?apiVersion=2022-11-28');
+ }
+}
+export const providerGitHub = (options) => () => new GitHubBuildCache(options);
+//# sourceMappingURL=providerGitHub.js.map
\ No newline at end of file
diff --git a/packages/provider-github/dist/src/lib/providerGitHub.js.map b/packages/provider-github/dist/src/lib/providerGitHub.js.map
new file mode 100644
index 000000000..bca548770
--- /dev/null
+++ b/packages/provider-github/dist/src/lib/providerGitHub.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"providerGitHub.js","sourceRoot":"","sources":["../../../src/lib/providerGitHub.ts"],"names":[],"mappings":"AACA,OAAO,EACL,qBAAqB,EACrB,0BAA0B,GAC3B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,uBAAuB,EAA0B,MAAM,aAAa,CAAC;AAE9E,MAAM,OAAO,gBAAgB;IAC3B,IAAI,GAAG,QAAQ,CAAC;IAChB,WAAW,GAA6B,IAAI,CAAC;IAE7C,YAAY,MAA6D;QACvE,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;YAC1D,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,MAAM,IAAI,KAAK,CACb,kJAAkJ,CACnJ,CAAC;YACJ,CAAC;YACD,IAAI,CAAC,WAAW,GAAG;gBACjB,KAAK,EAAE,MAAM,CAAC,KAAK;gBACnB,UAAU,EAAE,MAAM,CAAC,UAAU;gBAC7B,KAAK;aACN,CAAC;QACJ,CAAC;IACH,CAAC;IAED,KAAK,CAAC,cAAc;QAClB,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,IAAI,CAAC,WAAW,GAAG,MAAM,uBAAuB,EAAE,CAAC;QACrD,CAAC;QACD,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,EACT,YAAY,EACZ,KAAK,GAIN;QACC,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;QAChD,MAAM,SAAS,GAAG,MAAM,0BAA0B,CAChD,YAAY,EACZ,WAAW,EACX,KAAK,CACN,CAAC;QACF,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;YAClC,IAAI,EAAE,QAAQ,CAAC,IAAI;YACnB,GAAG,EAAE,QAAQ,CAAC,WAAW;YACzB,EAAE,EAAE,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;SACxB,CAAC,CAAC,CAAC;IACN,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,EACb,YAAY,GAGb;QACC,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;QAChD,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC;QACpD,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,gCAAgC,YAAY,GAAG,CAAC,CAAC;QACnE,CAAC;QACD,OAAO,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE;YAC7B,OAAO,EAAE;gBACP,aAAa,EAAE,SAAS,WAAW,CAAC,KAAK,EAAE;gBAC3C,iBAAiB,EAAE,MAAM;aAC1B;SACF,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,EACX,YAAY,EACZ,KAAK,EACL,UAAU,GAKX;QACC,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;QAChD,MAAM,SAAS,GAAG,MAAM,0BAA0B,CAChD,YAAY,EACZ,WAAW,EACX,KAAK,CACN,CAAC;QACF,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,gCAAgC,YAAY,GAAG,CAAC,CAAC;QACnE,CAAC;QACD,MAAM,CAAC,EAAE,GAAG,IAAI,CAAC,GAAG,SAAS,CAAC;QAC9B,OAAO,MAAM,qBAAqB,CAChC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,EAC7B,WAAW,EACX,YAAY,CACb,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,MAAM;QAQV,MAAM,IAAI,KAAK,CACb,iJAAiJ,CAClJ,CAAC;IACJ,CAAC;CACF;AAED,MAAM,CAAC,MAAM,cAAc,GACzB,CAAC,OAA8D,EAAE,EAAE,CACnE,GAAqB,EAAE,CACrB,IAAI,gBAAgB,CAAC,OAAO,CAAC,CAAC"}
\ No newline at end of file
diff --git a/packages/provider-s3/dist/src/index.d.ts b/packages/provider-s3/dist/src/index.d.ts
new file mode 100644
index 000000000..fc11f84c7
--- /dev/null
+++ b/packages/provider-s3/dist/src/index.d.ts
@@ -0,0 +1 @@
+export { providerS3 } from './lib/providerS3.js';
diff --git a/packages/provider-s3/dist/src/index.js b/packages/provider-s3/dist/src/index.js
new file mode 100644
index 000000000..fcdcc8f57
--- /dev/null
+++ b/packages/provider-s3/dist/src/index.js
@@ -0,0 +1,2 @@
+export { providerS3 } from './lib/providerS3.js';
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/packages/provider-s3/dist/src/index.js.map b/packages/provider-s3/dist/src/index.js.map
new file mode 100644
index 000000000..66a32ae1f
--- /dev/null
+++ b/packages/provider-s3/dist/src/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC"}
\ No newline at end of file
diff --git a/packages/provider-s3/dist/src/lib/providerS3.d.ts b/packages/provider-s3/dist/src/lib/providerS3.d.ts
new file mode 100644
index 000000000..8c4160c18
--- /dev/null
+++ b/packages/provider-s3/dist/src/lib/providerS3.d.ts
@@ -0,0 +1,80 @@
+import * as clientS3 from '@aws-sdk/client-s3';
+import type { RemoteArtifact, RemoteBuildCache } from '@rock-js/tools';
+type ProviderConfig = {
+ /**
+ * Optional endpoint, necessary for self-hosted S3 servers or Cloudflare R2 integration.
+ */
+ endpoint?: string;
+ /**
+ * The bucket name to use for the S3 server.
+ */
+ bucket: string;
+ /**
+ * The region of the S3 server.
+ */
+ region: string;
+ /**
+ * The access key ID for the S3 server. Not required when using IAM roles or other auth methods.
+ */
+ accessKeyId?: string;
+ /**
+ * The secret access key for the S3 server. Not required when using IAM roles or other auth methods.
+ */
+ secretAccessKey?: string;
+ /**
+ * The directory to store artifacts in the S3 server.
+ */
+ directory?: string;
+ /**
+ * The display name of the provider
+ */
+ name?: string;
+ /**
+ * The time in seconds for the presigned URL to expire. By default, it is 24 hours.
+ */
+ linkExpirationTime?: number;
+ /**
+ * AWS profile name to use for authentication. Useful for local development.
+ */
+ profile?: string;
+ /**
+ * Role ARN to assume for authentication. Useful for cross-account access.
+ */
+ roleArn?: string;
+ /**
+ * Session name when assuming a role.
+ */
+ roleSessionName?: string;
+ /**
+ * External ID when assuming a role (for additional security).
+ */
+ externalId?: string;
+};
+export declare class S3BuildCache implements RemoteBuildCache {
+ name: string;
+ directory: string;
+ s3: clientS3.S3Client;
+ bucket: string;
+ config: ProviderConfig;
+ linkExpirationTime: number;
+ constructor(config: ProviderConfig);
+ private uploadFileWithProgress;
+ list({ artifactName, }: {
+ artifactName?: string;
+ }): Promise;
+ download({ artifactName, }: {
+ artifactName: string;
+ }): Promise;
+ delete({ artifactName, skipLatest, }: {
+ artifactName: string;
+ skipLatest?: boolean;
+ }): Promise;
+ upload({ artifactName, uploadArtifactName, }: {
+ artifactName: string;
+ uploadArtifactName?: string;
+ }): Promise Buffer), contentType?: string) => Response;
+ }>;
+}
+export declare const providerS3: (options: ProviderConfig) => () => RemoteBuildCache;
+export {};
diff --git a/packages/provider-s3/dist/src/lib/providerS3.js b/packages/provider-s3/dist/src/lib/providerS3.js
new file mode 100644
index 000000000..1d9331bca
--- /dev/null
+++ b/packages/provider-s3/dist/src/lib/providerS3.js
@@ -0,0 +1,172 @@
+import * as clientS3 from '@aws-sdk/client-s3';
+import { fromIni } from '@aws-sdk/credential-provider-ini';
+import { fromTemporaryCredentials } from '@aws-sdk/credential-providers';
+import { Upload } from '@aws-sdk/lib-storage';
+import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
+function toWebStream(stream) {
+ return new ReadableStream({
+ start(controller) {
+ stream.on('data', (chunk) => controller.enqueue(chunk));
+ stream.on('end', () => controller.close());
+ stream.on('error', (err) => controller.error(err));
+ },
+ });
+}
+export class S3BuildCache {
+ name = 'S3';
+ directory = 'rock-artifacts';
+ s3;
+ bucket;
+ config;
+ linkExpirationTime;
+ constructor(config) {
+ this.config = config;
+ const s3Config = {
+ endpoint: config.endpoint,
+ region: config.region,
+ };
+ if (config.accessKeyId && config.secretAccessKey) {
+ s3Config.credentials = {
+ accessKeyId: config.accessKeyId,
+ secretAccessKey: config.secretAccessKey,
+ };
+ }
+ else if (config.roleArn) {
+ // Use STS to assume a role
+ s3Config.credentials = fromTemporaryCredentials({
+ params: {
+ RoleArn: config.roleArn,
+ RoleSessionName: config.roleSessionName ?? 's3-build-cache-session',
+ ExternalId: config.externalId,
+ },
+ // Optional: use named profile as source credentials
+ masterCredentials: config.profile
+ ? fromIni({ profile: config.profile })
+ : undefined,
+ });
+ }
+ else if (config.profile) {
+ // Use shared config file (e.g. ~/.aws/credentials) with a profile
+ s3Config.credentials = fromIni({ profile: config.profile });
+ }
+ this.s3 = new clientS3.S3Client(s3Config);
+ const awsBucket = config.bucket ?? '';
+ const bucketTokens = awsBucket.split('/');
+ this.bucket = bucketTokens.shift();
+ this.directory = config.directory ?? this.directory;
+ this.name = config.name ?? this.name;
+ this.linkExpirationTime = config.linkExpirationTime ?? 3600 * 24;
+ }
+ async uploadFileWithProgress(key, buffer, contentType, onProgress) {
+ const upload = new Upload({
+ client: this.s3,
+ params: {
+ Bucket: this.bucket,
+ Key: key,
+ Body: buffer,
+ ContentType: contentType || 'application/octet-stream',
+ Metadata: {
+ createdAt: new Date().toISOString(),
+ },
+ },
+ });
+ upload.on('httpUploadProgress', (progress) => {
+ if (progress.loaded !== undefined && progress.total !== undefined) {
+ onProgress(progress.loaded, progress.total);
+ }
+ });
+ return upload.done();
+ }
+ async list({ artifactName, }) {
+ const artifacts = await this.s3.send(new clientS3.ListObjectsV2Command({
+ Bucket: this.bucket,
+ Prefix: artifactName
+ ? `${this.directory}/${artifactName}.zip`
+ : `${this.directory}/`,
+ }));
+ const results = [];
+ for (const artifact of artifacts.Contents ?? []) {
+ if (!artifact.Key)
+ continue;
+ const name = artifactName ?? artifact.Key.split('/').pop() ?? '';
+ const presignedUrl = await getSignedUrl(this.s3, new clientS3.GetObjectCommand({
+ Bucket: this.bucket,
+ Key: artifact.Key,
+ }), { expiresIn: this.linkExpirationTime });
+ results.push({ name, url: presignedUrl });
+ }
+ return results;
+ }
+ async download({ artifactName, }) {
+ const res = await this.s3.send(new clientS3.GetObjectCommand({
+ Bucket: this.bucket,
+ Key: `${this.directory}/${artifactName}.zip`,
+ }));
+ return new Response(toWebStream(res.Body), {
+ headers: {
+ 'content-length': String(res.ContentLength),
+ },
+ });
+ }
+ async delete({ artifactName, skipLatest, }) {
+ if (skipLatest) {
+ // Artifacts on S3 are unique by name, so skipping latest means we don't delete anything
+ // @todo revisit with bucket versioning
+ return [];
+ }
+ await this.s3.send(new clientS3.DeleteObjectCommand({
+ Bucket: this.bucket,
+ Key: `${this.directory}/${artifactName}.zip`,
+ }));
+ return [
+ {
+ name: artifactName,
+ url: `${this.bucket}/${this.directory}/${artifactName}.zip`,
+ },
+ ];
+ }
+ async upload({ artifactName, uploadArtifactName, }) {
+ const key = uploadArtifactName
+ ? `${this.directory}/${uploadArtifactName}`
+ : `${this.directory}/${artifactName}.zip`;
+ const presignedUrl = await getSignedUrl(this.s3, new clientS3.GetObjectCommand({ Bucket: this.bucket, Key: key }), { expiresIn: this.linkExpirationTime });
+ return {
+ name: artifactName,
+ url: presignedUrl,
+ getResponse: (buffer, contentType) => {
+ const bufferToUpload = typeof buffer === 'function'
+ ? buffer(presignedUrl.split('?')[0])
+ : buffer;
+ const readable = new ReadableStream({
+ start: (controller) => {
+ let lastEmittedBytes = 0;
+ try {
+ this.uploadFileWithProgress(key, bufferToUpload, contentType, (loaded, total) => {
+ const newBytes = loaded - lastEmittedBytes;
+ if (newBytes > 0) {
+ const chunk = bufferToUpload.subarray(lastEmittedBytes, loaded);
+ controller.enqueue(chunk);
+ lastEmittedBytes = loaded;
+ if (loaded >= total) {
+ controller.close();
+ }
+ }
+ });
+ }
+ catch (error) {
+ controller.error(error);
+ }
+ },
+ });
+ return new Response(readable, {
+ headers: {
+ 'content-length': String(bufferToUpload.length),
+ 'content-type': contentType || 'application/octet-stream',
+ },
+ });
+ },
+ };
+ }
+}
+export const providerS3 = (options) => () => new S3BuildCache(options);
+//# sourceMappingURL=providerS3.js.map
\ No newline at end of file
diff --git a/packages/provider-s3/dist/src/lib/providerS3.js.map b/packages/provider-s3/dist/src/lib/providerS3.js.map
new file mode 100644
index 000000000..fefe11852
--- /dev/null
+++ b/packages/provider-s3/dist/src/lib/providerS3.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"providerS3.js","sourceRoot":"","sources":["../../../src/lib/providerS3.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/packages/test-helpers/dist/src/index.d.ts b/packages/test-helpers/dist/src/index.d.ts
new file mode 100644
index 000000000..117b1cd41
--- /dev/null
+++ b/packages/test-helpers/dist/src/index.d.ts
@@ -0,0 +1,3 @@
+export * from './lib/exec.js';
+export * from './lib/random.js';
+export * from './lib/test-helpers.js';
diff --git a/packages/test-helpers/dist/src/index.js b/packages/test-helpers/dist/src/index.js
new file mode 100644
index 000000000..0b9dd8466
--- /dev/null
+++ b/packages/test-helpers/dist/src/index.js
@@ -0,0 +1,4 @@
+export * from './lib/exec.js';
+export * from './lib/random.js';
+export * from './lib/test-helpers.js';
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/packages/test-helpers/dist/src/index.js.map b/packages/test-helpers/dist/src/index.js.map
new file mode 100644
index 000000000..0f9f73c26
--- /dev/null
+++ b/packages/test-helpers/dist/src/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC"}
\ No newline at end of file
diff --git a/packages/test-helpers/dist/src/lib/exec.d.ts b/packages/test-helpers/dist/src/lib/exec.d.ts
new file mode 100644
index 000000000..dc7346267
--- /dev/null
+++ b/packages/test-helpers/dist/src/lib/exec.d.ts
@@ -0,0 +1,2 @@
+import type { ExecOptions } from 'node:child_process';
+export declare const execAsync: (command: string, options?: ExecOptions) => Promise;
diff --git a/packages/test-helpers/dist/src/lib/exec.js b/packages/test-helpers/dist/src/lib/exec.js
new file mode 100644
index 000000000..8f4972354
--- /dev/null
+++ b/packages/test-helpers/dist/src/lib/exec.js
@@ -0,0 +1,13 @@
+import { exec } from 'node:child_process';
+export const execAsync = (command, options) => {
+ return new Promise((resolve, reject) => {
+ exec(command, options, (error, stdout, stderr) => {
+ if (error) {
+ reject(`exec error: ${error}\n\n${stdout}\n\n${stderr}`);
+ return;
+ }
+ resolve(stdout);
+ });
+ });
+};
+//# sourceMappingURL=exec.js.map
\ No newline at end of file
diff --git a/packages/test-helpers/dist/src/lib/exec.js.map b/packages/test-helpers/dist/src/lib/exec.js.map
new file mode 100644
index 000000000..f9aa521f8
--- /dev/null
+++ b/packages/test-helpers/dist/src/lib/exec.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"exec.js","sourceRoot":"","sources":["../../../src/lib/exec.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAE1C,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,OAAe,EAAE,OAAqB,EAAE,EAAE;IAClE,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;YAC/C,IAAI,KAAK,EAAE,CAAC;gBACV,MAAM,CAAC,eAAe,KAAK,OAAO,MAAM,OAAO,MAAM,EAAE,CAAC,CAAC;gBACzD,OAAO;YACT,CAAC;YACD,OAAO,CAAC,MAAM,CAAC,CAAC;QAClB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC"}
\ No newline at end of file
diff --git a/packages/test-helpers/dist/src/lib/random.d.ts b/packages/test-helpers/dist/src/lib/random.d.ts
new file mode 100644
index 000000000..183cd0a94
--- /dev/null
+++ b/packages/test-helpers/dist/src/lib/random.d.ts
@@ -0,0 +1 @@
+export declare function getRandomString(length: number): string;
diff --git a/packages/test-helpers/dist/src/lib/random.js b/packages/test-helpers/dist/src/lib/random.js
new file mode 100644
index 000000000..e667dadd4
--- /dev/null
+++ b/packages/test-helpers/dist/src/lib/random.js
@@ -0,0 +1,6 @@
+export function getRandomString(length) {
+ return Math.random()
+ .toString(36)
+ .substring(2, length + 2);
+}
+//# sourceMappingURL=random.js.map
\ No newline at end of file
diff --git a/packages/test-helpers/dist/src/lib/random.js.map b/packages/test-helpers/dist/src/lib/random.js.map
new file mode 100644
index 000000000..3073b5914
--- /dev/null
+++ b/packages/test-helpers/dist/src/lib/random.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"random.js","sourceRoot":"","sources":["../../../src/lib/random.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,eAAe,CAAC,MAAc;IAC5C,OAAO,IAAI,CAAC,MAAM,EAAE;SACjB,QAAQ,CAAC,EAAE,CAAC;SACZ,SAAS,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,CAAC;AAC9B,CAAC"}
\ No newline at end of file
diff --git a/packages/test-helpers/dist/src/lib/test-helpers.d.ts b/packages/test-helpers/dist/src/lib/test-helpers.d.ts
new file mode 100644
index 000000000..036168bb0
--- /dev/null
+++ b/packages/test-helpers/dist/src/lib/test-helpers.d.ts
@@ -0,0 +1,15 @@
+export declare const getTempDirectory: (name: string) => string;
+export declare const cleanup: (directory: string) => void;
+/**
+ * Creates a nested directory with files and their contents
+ * writeFiles(
+ * '/home/tmp',
+ * {
+ * 'package.json': '{}',
+ * 'dir/file.js': 'module.exports = "x";',
+ * }
+ * );
+ */
+export declare const writeFiles: (directory: string, files: {
+ [filename: string]: string | NodeJS.ArrayBufferView;
+}) => void;
diff --git a/packages/test-helpers/dist/src/lib/test-helpers.js b/packages/test-helpers/dist/src/lib/test-helpers.js
new file mode 100644
index 000000000..3b4426a3f
--- /dev/null
+++ b/packages/test-helpers/dist/src/lib/test-helpers.js
@@ -0,0 +1,39 @@
+import * as fs from 'node:fs';
+import * as os from 'node:os';
+import * as path from 'node:path';
+export const getTempDirectory = (name) => path.resolve(os.tmpdir(), name);
+export const cleanup = (directory) => {
+ fs.rmSync(directory, { recursive: true, force: true, maxRetries: 10 });
+};
+/**
+ * Creates a nested directory with files and their contents
+ * writeFiles(
+ * '/home/tmp',
+ * {
+ * 'package.json': '{}',
+ * 'dir/file.js': 'module.exports = "x";',
+ * }
+ * );
+ */
+export const writeFiles = (directory, files) => {
+ createDirectory(directory);
+ Object.keys(files).forEach((fileOrPath) => {
+ const dirname = path.dirname(fileOrPath);
+ if (dirname !== '/') {
+ createDirectory(path.join(directory, dirname));
+ }
+ fs.writeFileSync(path.resolve(directory, ...fileOrPath.split('/')), files[fileOrPath]);
+ });
+};
+function createDirectory(path) {
+ try {
+ fs.mkdirSync(path, { recursive: true });
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ }
+ catch (error) {
+ if (error.code !== 'EEXIST') {
+ throw error;
+ }
+ }
+}
+//# sourceMappingURL=test-helpers.js.map
\ No newline at end of file
diff --git a/packages/test-helpers/dist/src/lib/test-helpers.js.map b/packages/test-helpers/dist/src/lib/test-helpers.js.map
new file mode 100644
index 000000000..d12d983d5
--- /dev/null
+++ b/packages/test-helpers/dist/src/lib/test-helpers.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"test-helpers.js","sourceRoot":"","sources":["../../../src/lib/test-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,IAAY,EAAE,EAAE,CAC/C,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,IAAI,CAAC,CAAC;AAElC,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,SAAiB,EAAE,EAAE;IAC3C,EAAE,CAAC,MAAM,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,CAAC;AACzE,CAAC,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CACxB,SAAiB,EACjB,KAA8D,EAC9D,EAAE;IACF,eAAe,CAAC,SAAS,CAAC,CAAC;IAE3B,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,UAAU,EAAE,EAAE;QACxC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QAEzC,IAAI,OAAO,KAAK,GAAG,EAAE,CAAC;YACpB,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC;QACjD,CAAC;QACD,EAAE,CAAC,aAAa,CACd,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EACjD,KAAK,CAAC,UAAU,CAAC,CAClB,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,SAAS,eAAe,CAAC,IAAY;IACnC,IAAI,CAAC;QACH,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACxC,8DAA8D;IAChE,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC5B,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;AACH,CAAC"}
\ No newline at end of file
diff --git a/packages/tools/dist/src/index.d.ts b/packages/tools/dist/src/index.d.ts
new file mode 100644
index 000000000..a140626bf
--- /dev/null
+++ b/packages/tools/dist/src/index.d.ts
@@ -0,0 +1,21 @@
+export * from './lib/prompts.js';
+export * from './lib/env.js';
+export * from './lib/error.js';
+export { default as logger } from './lib/logger.js';
+export * from './lib/fingerprint/index.js';
+export { default as cacheManager } from './lib/cacheManager.js';
+export * from './lib/parse-args.js';
+export * from './lib/path.js';
+export * from './lib/project.js';
+export * from './lib/build-cache/common.js';
+export * from './lib/build-cache/localBuildCache.js';
+export { getBinaryPath } from './lib/build-cache/getBinaryPath.js';
+export { findDevServerPort } from './lib/dev-server/findDevServerPort.js';
+export { isDevServerRunning } from './lib/dev-server/isDevServerRunning.js';
+export { isInteractive } from './lib/isInteractive.js';
+export { spawn, SubprocessError } from './lib/spawn.js';
+export { color, colorLink } from './lib/color.js';
+export { runHermes } from './lib/hermes.js';
+export { fetchCachedBuild, handleDownloadResponse, handleUploadResponse, } from './lib/build-cache/fetchCachedBuild.js';
+export { getInfoPlist } from './lib/getInfoPlist.js';
+export { getReactNativeVersion } from './lib/getReactNativeVersion.js';
diff --git a/packages/tools/dist/src/index.js b/packages/tools/dist/src/index.js
new file mode 100644
index 000000000..b66558065
--- /dev/null
+++ b/packages/tools/dist/src/index.js
@@ -0,0 +1,22 @@
+export * from './lib/prompts.js';
+export * from './lib/env.js';
+export * from './lib/error.js';
+export { default as logger } from './lib/logger.js';
+export * from './lib/fingerprint/index.js';
+export { default as cacheManager } from './lib/cacheManager.js';
+export * from './lib/parse-args.js';
+export * from './lib/path.js';
+export * from './lib/project.js';
+export * from './lib/build-cache/common.js';
+export * from './lib/build-cache/localBuildCache.js';
+export { getBinaryPath } from './lib/build-cache/getBinaryPath.js';
+export { findDevServerPort } from './lib/dev-server/findDevServerPort.js';
+export { isDevServerRunning } from './lib/dev-server/isDevServerRunning.js';
+export { isInteractive } from './lib/isInteractive.js';
+export { spawn, SubprocessError } from './lib/spawn.js';
+export { color, colorLink } from './lib/color.js';
+export { runHermes } from './lib/hermes.js';
+export { fetchCachedBuild, handleDownloadResponse, handleUploadResponse, } from './lib/build-cache/fetchCachedBuild.js';
+export { getInfoPlist } from './lib/getInfoPlist.js';
+export { getReactNativeVersion } from './lib/getReactNativeVersion.js';
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/packages/tools/dist/src/index.js.map b/packages/tools/dist/src/index.js.map
new file mode 100644
index 000000000..9dc978802
--- /dev/null
+++ b/packages/tools/dist/src/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACpD,cAAc,4BAA4B,CAAC;AAC3C,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAChE,cAAc,qBAAqB,CAAC;AACpC,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,sCAAsC,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAC1E,OAAO,EAAE,kBAAkB,EAAE,MAAM,wCAAwC,CAAC;AAC5E,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC"}
\ No newline at end of file
diff --git a/packages/tools/dist/src/lib/build-cache/common.d.ts b/packages/tools/dist/src/lib/build-cache/common.d.ts
new file mode 100644
index 000000000..c4e169db7
--- /dev/null
+++ b/packages/tools/dist/src/lib/build-cache/common.d.ts
@@ -0,0 +1,81 @@
+import type { FingerprintSources } from '../fingerprint/index.js';
+export declare const BUILD_CACHE_DIR = "remote-build";
+export declare const supportedRemoteCacheProviders: readonly ["github-actions", "s3"];
+export type SupportedRemoteCacheProviders = typeof supportedRemoteCacheProviders[number];
+export type RemoteArtifact = {
+ name: string;
+ url: string;
+ id?: string;
+};
+export type LocalArtifact = {
+ name: string;
+};
+/**
+ * Interface for implementing remote build cache providers.
+ * Remote cache providers allow storing and retrieving native build artifacts (e.g. APK, IPA)
+ * from remote storage like S3, GitHub Artifacts etc.
+ */
+export interface RemoteBuildCache {
+ /** Unique identifier for this cache provider, will be displayed in logs */
+ name: string;
+ /**
+ * List available artifacts matching the given name pattern
+ * @param artifactName - Passed after fingerprinting the build, e.g. `rock-android-debug-1234567890` for android in debug variant
+ * @param limit - Optional maximum number of artifacts to return
+ * @returns Array of matching remote artifacts, or empty array if none found
+ */
+ list({ artifactName, limit, }: {
+ artifactName: string | undefined;
+ limit?: number;
+ }): Promise;
+ /**
+ * Download a remote artifact to local storage
+ * @param artifactName - Name of the artifact to download, e.g. `rock-android-debug-1234567890` for android in debug variant
+ * @returns Response object from fetch, which will be used to download the artifact
+ */
+ download({ artifactName }: {
+ artifactName: string;
+ }): Promise;
+ /**
+ * Delete a remote artifact
+ * @param artifactName - Name of the artifact to delete, e.g. `rock-android-debug-1234567890` for android in debug variant
+ * @param limit - Optional maximum number of artifacts to delete
+ * @param skipLatest - Optional flag to skip the latest artifact, helpful when deleting all but the latest artifact
+ * @returns Array of deleted artifacts
+ * @throws {Error} Throws if artifact is not found or deletion fails
+ */
+ delete({ artifactName, limit, skipLatest, }: {
+ artifactName: string;
+ limit?: number;
+ skipLatest?: boolean;
+ }): Promise;
+ /**
+ * Upload a local artifact stored in build cache to remote storage
+ * @param artifactName - Name of the artifact to upload, e.g. `rock-android-debug-1234567890` for android in debug variant
+ * @param uploadArtifactName - Name of the artifact to upload, e.g. `ad-hoc/rock-ios-device-Release-1234567890/YourApp.ipa` for ad-hoc distribution
+ * @returns Remote artifact info with response function for upload control
+ * @throws {Error} Throws if upload fails
+ */
+ upload({ artifactName, uploadArtifactName, }: {
+ artifactName: string;
+ uploadArtifactName?: string;
+ }): Promise Buffer), contentType?: string) => Response;
+ }>;
+}
+/**
+ * Used formats:
+ * - rock-android-debug-1234567890
+ * - rock-ios-simulator-debug-1234567890
+ * - rock-ios-device-debug-1234567890
+ */
+export declare function formatArtifactName({ platform, traits, root, fingerprintOptions, raw, type, }: {
+ platform?: 'ios' | 'android' | 'harmony';
+ traits?: string[];
+ root: string;
+ fingerprintOptions: FingerprintSources;
+ raw?: boolean;
+ type?: 'create' | 'update';
+}): Promise