nx-react-native-cli 2.6.12 → 2.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.cjs +1 -1
- package/package.json +1 -1
- package/templates/19.7.0/apps/mobile/.ignorefile +1 -0
- package/templates/19.7.0/apps/mobile/project.json +17 -19
- package/templates/21.2.2/apps/mobile/.ignorefile +1 -0
- package/templates/21.2.2/apps/mobile/project.json +17 -19
- package/templates/shared/.ignorefile +1 -0
- package/templates/shared/apps/mobile/deploy.sh +107 -0
- package/templates/shared/apps/mobile/package.json +1 -78
- package/templates/shared/apps/mobile/picker.sh +151 -0
- package/templates/shared/apps/mobile/pod-install.sh +40 -0
- package/templates/shared/apps/mobile/react-native.config.js +15 -0
- package/templates/shared/apps/mobile/run-android.sh +130 -0
- package/templates/shared/apps/mobile/run-ios.sh +89 -0
- package/templates/shared/apps/mobile/src/components/atoms/Modal/modal.component.tsx +19 -6
- package/templates/shared/apps/mobile/src/components/atoms/Typography/typography.component.tsx +1 -1
- package/templates/shared/apps/mobile/src/components/molecules/ScreenHeader/screen-header.component.tsx +1 -1
- package/templates/shared/clean-generated-outputs.sh +4 -0
package/lib/index.cjs
CHANGED
|
@@ -61,7 +61,7 @@ ${m.description}`:"";return`${[a,v,b].filter(Boolean).join(" ")}
|
|
|
61
61
|
${C}${T}${F}${N2.default.cursorHide}`});var b1=O(require("node:readline"),1),j=O(d1(),1),ml=O(m1(),1),E1=O(Ha(),1),F1=O(Et(),1),v1={set:(e,r="",t)=>{let n=e;r.split(".").forEach((i,u,o)=>{i==="__proto__"||i==="constructor"||(u===o.length-1?n[i]=t:i in n||(n[i]={}),n=n[i])})},get:(e,r="",t)=>{let n=u=>String.prototype.split.call(r,u).filter(Boolean).reduce((o,a)=>o!=null?o[a]:o,e),i=n(/[,[\]]+?/)||n(/[,.[\]]+?/);return i===void 0||i===e?t:i}};function Dl(e,r,t){if(r in e){let n=e[r];if(typeof n=="function")return(0,j.from)((0,ml.default)(n)(t).then(i=>Object.assign(e,{[r]:i})))}return(0,j.of)(e)}var hl=class extends Error{isTtyError=!0};function ES(e={}){e.skipTTYChecks=e.skipTTYChecks===void 0?!0:e.skipTTYChecks;let r=e.input||process.stdin;if(!e.skipTTYChecks&&!r.isTTY)throw new hl("Prompts can not be meaningfully rendered in non-TTY environments");let t=new E1.default;return t.pipe(e.output||process.stdout),{terminal:!0,...e,input:r,output:t}}function FS(e){return Object.values(e).every(r=>typeof r=="object"&&!Array.isArray(r)&&r!=null)}function _S(e){return e.prototype&&"run"in e.prototype&&typeof e.prototype.run=="function"}var Dn=class{prompts;answers={};process=j.EMPTY;onClose;opt;rl;constructor(r,t){this.opt=t,this.prompts=r}run(r,t){this.answers=typeof t=="object"?{...t}:{};let n;Array.isArray(r)?n=(0,j.from)(r):(0,j.isObservable)(r)?n=r:FS(r)?n=(0,j.from)(Object.entries(r).map(([u,o])=>Object.assign({},o,{name:u}))):n=(0,j.from)([r]),this.process=n.pipe((0,j.concatMap)(u=>this.processQuestion(u)));let i=(0,j.lastValueFrom)(this.process.pipe((0,j.reduce)((u,o)=>(v1.set(u,o.name,o.answer),u),this.answers))).then(()=>this.onCompletion(),u=>this.onError(u));return Object.assign(i,{ui:this})}onCompletion(){return this.close(),this.answers}onError(r){return this.close(),Promise.reject(r)}processQuestion(r){return r={...r},(0,j.defer)(()=>(0,j.of)(r).pipe((0,j.concatMap)(this.setDefaultType),(0,j.concatMap)(this.filterIfRunnable),(0,j.concatMap)(n=>Dl(n,"message",this.answers)),(0,j.concatMap)(n=>Dl(n,"default",this.answers)),(0,j.concatMap)(n=>Dl(n,"choices",this.answers)),(0,j.concatMap)(n=>("choices"in n&&(n.choices=n.choices.map(i=>typeof i=="string"?{name:i,value:i}:i)),(0,j.of)(n))),(0,j.concatMap)(n=>this.fetchAnswer(n))))}fetchAnswer(r){let t=this.prompts[r.type];if(t==null)throw new Error(`Prompt for type ${r.type} not found`);return _S(t)?(0,j.defer)(()=>{let n=b1.default.createInterface(ES(this.opt));n.resume();let i=()=>{n.removeListener("SIGINT",this.onForceClose),n.setPrompt(""),n.output.unmute(),n.output.write(F1.default.cursorShow),n.output.end(),n.close()};this.onClose=i,this.rl=n,process.on("exit",this.onForceClose),n.on("SIGINT",this.onForceClose);let u=new t(r,n,this.answers);return(0,j.from)(u.run().then(o=>(i(),this.onClose=void 0,this.rl=void 0,{name:r.name,answer:o})))}):(0,j.defer)(()=>(0,j.from)(t(r,this.opt).then(n=>({name:r.name,answer:n}))))}onForceClose=()=>{this.close(),process.kill(process.pid,"SIGINT"),console.log("")};close=()=>{process.removeListener("exit",this.onForceClose),typeof this.onClose=="function"&&this.onClose()};setDefaultType=r=>(this.prompts[r.type]||(r.type="input"),(0,j.defer)(()=>(0,j.of)(r)));filterIfRunnable=r=>{if(r.askAnswered!==!0&&v1.get(this.answers,r.name)!==void 0)return j.EMPTY;let{when:t}=r;return t===!1?j.EMPTY:typeof t!="function"?(0,j.of)(r):(0,j.defer)(()=>(0,j.from)((0,ml.default)(t)(this.answers).then(n=>{if(n)return r})).pipe((0,j.filter)(n=>n!=null)))}};var _1={input:zs,select:zi,list:zi,number:Ks,confirm:Gs,rawlist:Zs,expand:Xs,checkbox:ts,password:ec,editor:Hs};function y1(e){function r(t,n){let i=new Dn(r.prompts,e);try{return i.run(t,n)}catch(u){let o=Promise.reject(u);return Object.assign(o,{ui:i})}}return r.prompts={..._1},r.registerPrompt=function(t,n){return r.prompts[t]=n,this},r.restoreDefaultPrompts=function(){r.prompts={..._1}},r}var vl=y1();function yS(e,r){vl.registerPrompt(e,r)}function gS(){vl.restoreDefaultPrompts()}var CS={prompt:vl,ui:{Prompt:Dn},createPromptModule:y1,registerPrompt:yS,restoreDefaultPrompts:gS,Separator:ae},ri=CS;var ui=O(require("node:process"),1);var _l=O(require("node:process"),1);var k1=O(require("node:process"),1),T1=O(A1(),1),M1=O(P1(),1),AS=(0,T1.default)(()=>{(0,M1.default)(()=>{k1.default.stderr.write("\x1B[?25h")},{alwaysLast:!0})}),I1=AS;var la=!1,bn={};bn.show=(e=_l.default.stderr)=>{e.isTTY&&(la=!1,e.write("\x1B[?25h"))};bn.hide=(e=_l.default.stderr)=>{e.isTTY&&(I1(),la=!0,e.write("\x1B[?25l"))};bn.toggle=(e,r)=>{e!==void 0&&(la=e),la?bn.show(r):bn.hide(r)};var yl=bn;var oi=O(Ei(),1);var Se=O(require("node:process"),1);function gl(){return Se.default.platform!=="win32"?Se.default.env.TERM!=="linux":!!Se.default.env.CI||!!Se.default.env.WT_SESSION||!!Se.default.env.TERMINUS_SUBLIME||Se.default.env.ConEmuTask==="{cmd::Cmder}"||Se.default.env.TERM_PROGRAM==="Terminus-Sublime"||Se.default.env.TERM_PROGRAM==="vscode"||Se.default.env.TERM==="xterm-256color"||Se.default.env.TERM==="alacritty"||Se.default.env.TERMINAL_EMULATOR==="JetBrains-JediTerm"}var OS={info:z.blue("\u2139"),success:z.green("\u2714"),warning:z.yellow("\u26A0"),error:z.red("\u2716")},SS={info:z.blue("i"),success:z.green("\u221A"),warning:z.yellow("\u203C"),error:z.red("\xD7")},BS=gl()?OS:SS,ni=BS;function Cl({onlyFirst:e=!1}={}){let r=["[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)","(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))"].join("|");return new RegExp(r,e?void 0:"g")}var qS=Cl();function ii(e){if(typeof e!="string")throw new TypeError(`Expected a \`string\`, got \`${typeof e}\``);return e.replace(qS,"")}function R1(e){return e===161||e===164||e===167||e===168||e===170||e===173||e===174||e>=176&&e<=180||e>=182&&e<=186||e>=188&&e<=191||e===198||e===208||e===215||e===216||e>=222&&e<=225||e===230||e>=232&&e<=234||e===236||e===237||e===240||e===242||e===243||e>=247&&e<=250||e===252||e===254||e===257||e===273||e===275||e===283||e===294||e===295||e===299||e>=305&&e<=307||e===312||e>=319&&e<=322||e===324||e>=328&&e<=331||e===333||e===338||e===339||e===358||e===359||e===363||e===462||e===464||e===466||e===468||e===470||e===472||e===474||e===476||e===593||e===609||e===708||e===711||e>=713&&e<=715||e===717||e===720||e>=728&&e<=731||e===733||e===735||e>=768&&e<=879||e>=913&&e<=929||e>=931&&e<=937||e>=945&&e<=961||e>=963&&e<=969||e===1025||e>=1040&&e<=1103||e===1105||e===8208||e>=8211&&e<=8214||e===8216||e===8217||e===8220||e===8221||e>=8224&&e<=8226||e>=8228&&e<=8231||e===8240||e===8242||e===8243||e===8245||e===8251||e===8254||e===8308||e===8319||e>=8321&&e<=8324||e===8364||e===8451||e===8453||e===8457||e===8467||e===8470||e===8481||e===8482||e===8486||e===8491||e===8531||e===8532||e>=8539&&e<=8542||e>=8544&&e<=8555||e>=8560&&e<=8569||e===8585||e>=8592&&e<=8601||e===8632||e===8633||e===8658||e===8660||e===8679||e===8704||e===8706||e===8707||e===8711||e===8712||e===8715||e===8719||e===8721||e===8725||e===8730||e>=8733&&e<=8736||e===8739||e===8741||e>=8743&&e<=8748||e===8750||e>=8756&&e<=8759||e===8764||e===8765||e===8776||e===8780||e===8786||e===8800||e===8801||e>=8804&&e<=8807||e===8810||e===8811||e===8814||e===8815||e===8834||e===8835||e===8838||e===8839||e===8853||e===8857||e===8869||e===8895||e===8978||e>=9312&&e<=9449||e>=9451&&e<=9547||e>=9552&&e<=9587||e>=9600&&e<=9615||e>=9618&&e<=9621||e===9632||e===9633||e>=9635&&e<=9641||e===9650||e===9651||e===9654||e===9655||e===9660||e===9661||e===9664||e===9665||e>=9670&&e<=9672||e===9675||e>=9678&&e<=9681||e>=9698&&e<=9701||e===9711||e===9733||e===9734||e===9737||e===9742||e===9743||e===9756||e===9758||e===9792||e===9794||e===9824||e===9825||e>=9827&&e<=9829||e>=9831&&e<=9834||e===9836||e===9837||e===9839||e===9886||e===9887||e===9919||e>=9926&&e<=9933||e>=9935&&e<=9939||e>=9941&&e<=9953||e===9955||e===9960||e===9961||e>=9963&&e<=9969||e===9972||e>=9974&&e<=9977||e===9979||e===9980||e===9982||e===9983||e===10045||e>=10102&&e<=10111||e>=11094&&e<=11097||e>=12872&&e<=12879||e>=57344&&e<=63743||e>=65024&&e<=65039||e===65533||e>=127232&&e<=127242||e>=127248&&e<=127277||e>=127280&&e<=127337||e>=127344&&e<=127373||e===127375||e===127376||e>=127387&&e<=127404||e>=917760&&e<=917999||e>=983040&&e<=1048573||e>=1048576&&e<=1114109}function L1(e){return e===12288||e>=65281&&e<=65376||e>=65504&&e<=65510}function N1(e){return e>=4352&&e<=4447||e===8986||e===8987||e===9001||e===9002||e>=9193&&e<=9196||e===9200||e===9203||e===9725||e===9726||e===9748||e===9749||e>=9800&&e<=9811||e===9855||e===9875||e===9889||e===9898||e===9899||e===9917||e===9918||e===9924||e===9925||e===9934||e===9940||e===9962||e===9970||e===9971||e===9973||e===9978||e===9981||e===9989||e===9994||e===9995||e===10024||e===10060||e===10062||e>=10067&&e<=10069||e===10071||e>=10133&&e<=10135||e===10160||e===10175||e===11035||e===11036||e===11088||e===11093||e>=11904&&e<=11929||e>=11931&&e<=12019||e>=12032&&e<=12245||e>=12272&&e<=12287||e>=12289&&e<=12350||e>=12353&&e<=12438||e>=12441&&e<=12543||e>=12549&&e<=12591||e>=12593&&e<=12686||e>=12688&&e<=12771||e>=12783&&e<=12830||e>=12832&&e<=12871||e>=12880&&e<=19903||e>=19968&&e<=42124||e>=42128&&e<=42182||e>=43360&&e<=43388||e>=44032&&e<=55203||e>=63744&&e<=64255||e>=65040&&e<=65049||e>=65072&&e<=65106||e>=65108&&e<=65126||e>=65128&&e<=65131||e>=94176&&e<=94180||e===94192||e===94193||e>=94208&&e<=100343||e>=100352&&e<=101589||e>=101632&&e<=101640||e>=110576&&e<=110579||e>=110581&&e<=110587||e===110589||e===110590||e>=110592&&e<=110882||e===110898||e>=110928&&e<=110930||e===110933||e>=110948&&e<=110951||e>=110960&&e<=111355||e===126980||e===127183||e===127374||e>=127377&&e<=127386||e>=127488&&e<=127490||e>=127504&&e<=127547||e>=127552&&e<=127560||e===127568||e===127569||e>=127584&&e<=127589||e>=127744&&e<=127776||e>=127789&&e<=127797||e>=127799&&e<=127868||e>=127870&&e<=127891||e>=127904&&e<=127946||e>=127951&&e<=127955||e>=127968&&e<=127984||e===127988||e>=127992&&e<=128062||e===128064||e>=128066&&e<=128252||e>=128255&&e<=128317||e>=128331&&e<=128334||e>=128336&&e<=128359||e===128378||e===128405||e===128406||e===128420||e>=128507&&e<=128591||e>=128640&&e<=128709||e===128716||e>=128720&&e<=128722||e>=128725&&e<=128727||e>=128732&&e<=128735||e===128747||e===128748||e>=128756&&e<=128764||e>=128992&&e<=129003||e===129008||e>=129292&&e<=129338||e>=129340&&e<=129349||e>=129351&&e<=129535||e>=129648&&e<=129660||e>=129664&&e<=129672||e>=129680&&e<=129725||e>=129727&&e<=129733||e>=129742&&e<=129755||e>=129760&&e<=129768||e>=129776&&e<=129784||e>=131072&&e<=196605||e>=196608&&e<=262141}function jS(e){if(!Number.isSafeInteger(e))throw new TypeError(`Expected a code point, got \`${typeof e}\`.`)}function $1(e,{ambiguousAsWide:r=!1}={}){return jS(e),L1(e)||N1(e)||r&&R1(e)?2:1}var W1=O(V1(),1),PS=new Intl.Segmenter,kS=/^\p{Default_Ignorable_Code_Point}$/u;function wl(e,r={}){if(typeof e!="string"||e.length===0)return 0;let{ambiguousIsNarrow:t=!0,countAnsiEscapeCodes:n=!1}=r;if(n||(e=ii(e)),e.length===0)return 0;let i=0,u={ambiguousAsWide:!t};for(let{segment:o}of PS.segment(e)){let a=o.codePointAt(0);if(!(a<=31||a>=127&&a<=159)&&!(a>=8203&&a<=8207||a===65279)&&!(a>=768&&a<=879||a>=6832&&a<=6911||a>=7616&&a<=7679||a>=8400&&a<=8447||a>=65056&&a<=65071)&&!(a>=55296&&a<=57343)&&!(a>=65024&&a<=65039)&&!kS.test(o)){if((0,W1.default)().test(o)){i+=2;continue}i+=$1(a,u)}}return i}function Al({stream:e=process.stdout}={}){return!!(e&&e.isTTY&&process.env.TERM!=="dumb"&&!("CI"in process.env))}var Re=O(require("node:process"),1);function Ol(){return Re.default.platform!=="win32"?Re.default.env.TERM!=="linux":!!Re.default.env.WT_SESSION||!!Re.default.env.TERMINUS_SUBLIME||Re.default.env.ConEmuTask==="{cmd::Cmder}"||Re.default.env.TERM_PROGRAM==="Terminus-Sublime"||Re.default.env.TERM_PROGRAM==="vscode"||Re.default.env.TERM==="xterm-256color"||Re.default.env.TERM==="alacritty"||Re.default.env.TERMINAL_EMULATOR==="JetBrains-JediTerm"}var Le=O(require("node:process"),1),TS=3,Sl=class{#i=0;start(){this.#i++,this.#i===1&&this.#t()}stop(){if(this.#i<=0)throw new Error("`stop` called more times than `start`");this.#i--,this.#i===0&&this.#e()}#t(){Le.default.platform==="win32"||!Le.default.stdin.isTTY||(Le.default.stdin.setRawMode(!0),Le.default.stdin.on("data",this.#u),Le.default.stdin.resume())}#e(){Le.default.stdin.isTTY&&(Le.default.stdin.off("data",this.#u),Le.default.stdin.pause(),Le.default.stdin.setRawMode(!1))}#u(r){r[0]===TS&&Le.default.emit("SIGINT")}},MS=new Sl,Bl=MS;var IS=O(Ei(),1),ql=class{#i=0;#t=!1;#e=0;#u=0;#r;#o;#n;#x;#d;#c;#l;#f;#D;#a;#s;color;constructor(r){typeof r=="string"&&(r={text:r}),this.#r={color:"cyan",stream:ui.default.stderr,discardStdin:!0,hideCursor:!0,...r},this.color=this.#r.color,this.spinner=this.#r.spinner,this.#d=this.#r.interval,this.#n=this.#r.stream,this.#c=typeof this.#r.isEnabled=="boolean"?this.#r.isEnabled:Al({stream:this.#n}),this.#l=typeof this.#r.isSilent=="boolean"?this.#r.isSilent:!1,this.text=this.#r.text,this.prefixText=this.#r.prefixText,this.suffixText=this.#r.suffixText,this.indent=this.#r.indent,ui.default.env.NODE_ENV==="test"&&(this._stream=this.#n,this._isEnabled=this.#c,Object.defineProperty(this,"_linesToClear",{get(){return this.#i},set(t){this.#i=t}}),Object.defineProperty(this,"_frameIndex",{get(){return this.#u}}),Object.defineProperty(this,"_lineCount",{get(){return this.#e}}))}get indent(){return this.#f}set indent(r=0){if(!(r>=0&&Number.isInteger(r)))throw new Error("The `indent` option must be an integer from 0 and up");this.#f=r,this.#p()}get interval(){return this.#d??this.#o.interval??100}get spinner(){return this.#o}set spinner(r){if(this.#u=0,this.#d=void 0,typeof r=="object"){if(r.frames===void 0)throw new Error("The given spinner must have a `frames` property");this.#o=r}else if(!Ol())this.#o=oi.default.line;else if(r===void 0)this.#o=oi.default.dots;else if(r!=="default"&&oi.default[r])this.#o=oi.default[r];else throw new Error(`There is no built-in spinner named '${r}'. See https://github.com/sindresorhus/cli-spinners/blob/main/spinners.json for a full list.`)}get text(){return this.#D}set text(r=""){this.#D=r,this.#p()}get prefixText(){return this.#a}set prefixText(r=""){this.#a=r,this.#p()}get suffixText(){return this.#s}set suffixText(r=""){this.#s=r,this.#p()}get isSpinning(){return this.#x!==void 0}#h(r=this.#a,t=" "){return typeof r=="string"&&r!==""?r+t:typeof r=="function"?r()+t:""}#m(r=this.#s,t=" "){return typeof r=="string"&&r!==""?t+r:typeof r=="function"?t+r():""}#p(){let r=this.#n.columns??80,t=this.#h(this.#a,"-"),n=this.#m(this.#s,"-"),i=" ".repeat(this.#f)+t+"--"+this.#D+"--"+n;this.#e=0;for(let u of ii(i).split(`
|
|
62
62
|
`))this.#e+=Math.max(1,Math.ceil(wl(u,{countAnsiEscapeCodes:!0})/r))}get isEnabled(){return this.#c&&!this.#l}set isEnabled(r){if(typeof r!="boolean")throw new TypeError("The `isEnabled` option must be a boolean");this.#c=r}get isSilent(){return this.#l}set isSilent(r){if(typeof r!="boolean")throw new TypeError("The `isSilent` option must be a boolean");this.#l=r}frame(){let{frames:r}=this.#o,t=r[this.#u];this.color&&(t=z[this.color](t)),this.#u=++this.#u%r.length;let n=typeof this.#a=="string"&&this.#a!==""?this.#a+" ":"",i=typeof this.text=="string"?" "+this.text:"",u=typeof this.#s=="string"&&this.#s!==""?" "+this.#s:"";return n+t+i+u}clear(){if(!this.#c||!this.#n.isTTY)return this;this.#n.cursorTo(0);for(let r=0;r<this.#i;r++)r>0&&this.#n.moveCursor(0,-1),this.#n.clearLine(1);return(this.#f||this.lastIndent!==this.#f)&&this.#n.cursorTo(this.#f),this.lastIndent=this.#f,this.#i=0,this}render(){return this.#l?this:(this.clear(),this.#n.write(this.frame()),this.#i=this.#e,this)}start(r){return r&&(this.text=r),this.#l?this:this.#c?this.isSpinning?this:(this.#r.hideCursor&&yl.hide(this.#n),this.#r.discardStdin&&ui.default.stdin.isTTY&&(this.#t=!0,Bl.start()),this.render(),this.#x=setInterval(this.render.bind(this),this.interval),this):(this.text&&this.#n.write(`- ${this.text}
|
|
63
63
|
`),this)}stop(){return this.#c?(clearInterval(this.#x),this.#x=void 0,this.#u=0,this.clear(),this.#r.hideCursor&&yl.show(this.#n),this.#r.discardStdin&&ui.default.stdin.isTTY&&this.#t&&(Bl.stop(),this.#t=!1),this):this}succeed(r){return this.stopAndPersist({symbol:ni.success,text:r})}fail(r){return this.stopAndPersist({symbol:ni.error,text:r})}warn(r){return this.stopAndPersist({symbol:ni.warning,text:r})}info(r){return this.stopAndPersist({symbol:ni.info,text:r})}stopAndPersist(r={}){if(this.#l)return this;let t=r.prefixText??this.#a,n=this.#h(t," "),i=r.symbol??" ",u=r.text??this.text,o=typeof u=="string"?" "+u:"",a=r.suffixText??this.#s,s=this.#m(a," "),c=n+i+o+s+`
|
|
64
|
-
`;return this.stop(),this.#n.write(c),this}};function _e(e){return new ql(e)}var z1=require("child_process"),Be=O(require("fs"),1),at=O(require("path"),1);var H1={dependencies:{"@gorhom/bottom-sheet":"5.2.8","@hookform/resolvers":"5.0.1","@react-native-community/datetimepicker":"8.6.0","@react-native-community/hooks":"100.1.0","@react-navigation/core":"7.4.0","@react-navigation/material-top-tabs":"7.2.13","@react-navigation/native-stack":"7.2.1","@react-navigation/native":"7.0.15","@react-navigation/stack":"7.1.2","@shopify/react-native-skia":"2.4.14","@tanstack/query-async-storage-persister":"5.67.3","@tanstack/query-core":"5.67.3","@tanstack/query-sync-storage-persister":"5.67.3","@tanstack/react-query-persist-client":"5.67.3","@tanstack/react-query":"5.67.3",axios:"1.13.2","babel-plugin-module-resolver":"5.0.2",dayjs:"1.11.19","jotai-optics":"0.4.0",jotai:"2.16.1","lodash-es":"4.17.22","react-hook-form":"7.56.4","react-native-dotenv":"3.4.11","react-native-gesture-handler":"2.29.1","react-native-get-random-values":"1.11.0","react-native-haptic-feedback":"2.3.3","react-native-keyboard-controller":"1.19.1","react-native-mmkv":"4.1.0","react-native-modal-datetime-picker":"18.0.0","react-native-modal":"14.0.0-rc.1","react-native-nitro-modules":"0.32.0","react-native-pager-view":"6.8.0","react-native-reanimated":"4.2.1","react-native-safe-area-context":"5.6.0","react-native-screens":"4.19.0","react-native-simple-toast":"3.3.2","react-native-turbo-image":"1.22.1","react-native-url-polyfill":"2.0.0","react-native-worklets":"0.7.1","react-native":"0.83.1",react:"19.2.0",tailwindcss:"3.4.16",twrnc:"4.16.0",uuid:"11.1.0","zod-validation-error":"3.4.0",zod:"3.24.2",zustand:"5.0.5"}};var G1={devDependencies:{"@babel/core":"7.25.2","@babel/eslint-parser":"7.23.10","@babel/preset-env":"7.25.3","@babel/preset-react":"7.27.1","@babel/runtime":"7.25.0","@react-native-community/cli-platform-android":"20.0.0","@react-native-community/cli-platform-ios":"20.0.0","@react-native-community/cli":"20.0.0","@react-native/babel-preset":"0.83.1","@react-native/eslint-config":"0.83.1","@react-native/metro-config":"0.83.1","@react-native/typescript-config":"0.83.1","@swc-node/register":"~1.8.0","@tanstack/eslint-plugin-query":"5.91.2","@testing-library/jest-native":"5.4.3","@testing-library/react-native":"12.5.1","@types/jest":"29.5.13","@types/jwt-encode":"1.0.3","@types/lodash-es":"4.17.12","@types/react-native-vector-icons":"6.4.18","@types/react-test-renderer":"19.1.0","@types/react":"19.2.0","@typescript-eslint/eslint-plugin":"^6.13.2","@typescript-eslint/parser":"^6.21.0","babel-jest":"29.6.3","babel-plugin-module-resolver":"5.0.2","eslint-config-airbnb-typescript":"^17.1.0","eslint-config-prettier":"10.1.8","eslint-import-resolver-typescript":"^3.8.5","eslint-plugin-ft-flow":"2.0.3","eslint-plugin-import":"^2.31.0","eslint-plugin-jest":"27.9.0","eslint-plugin-prettier":"^5.2.3","eslint-plugin-react-hooks":"^4.6.0","eslint-plugin-react-perf":"^3.3.3","eslint-plugin-react":"^7.32.2","eslint-plugin-sonarjs":"0.25.1","eslint-plugin-sort-destructure-keys":"^2.0.0","eslint-plugin-sort-keys-fix":"^1.1.2","eslint-plugin-tailwindcss":"^3.18.0","eslint-plugin-testing-library":"6.2.2",eslint:"8.57.0",husky:"9.1.7","jest-environment-jsdom":"30.1.2",jest:"29.6.3","prettier-plugin-tailwindcss":"^0.6.11",prettier:"3.3.2","react-native-dotenv":"3.4.11","react-native-svg-transformer":"1.3.0","react-native-svg":"15.15.1","react-test-renderer":"19.2.0",typescript:"5.8.3"}};function fa(){return __dirname}var pe=(e,r)=>{(0,z1.execSync)(`cd ${e} && ${r}`,{stdio:"inherit"})},te=(e,r,t,n)=>{let i=at.default.join(fa(),`../templates/${t}/${r}`);!Be.default.existsSync(i)&&n&&(i=at.default.join(fa(),`../templates/${n}/${r}`)),Be.default.copyFile(i,e,u=>{if(u){console.error(`Error copying file: ${u.message}`);return}})},Ne=(e,r,t,n)=>{let i=at.default.join(fa(),`../templates/${t}/${r}`);!Be.default.existsSync(i)&&n&&(i=at.default.join(fa(),`../templates/${n}/${r}`)),Be.default.cpSync(i,e,{recursive:!0},u=>{if(u){console.error(`Error copying file: ${u.message}`);return}})},jl=e=>{Be.default.rmSync(e,{recursive:!0,force:!0},r=>{if(r){console.error(`Error removing directory: ${r.message}`);return}})},ai=e=>{Be.default.rmSync(e,{recursive:!0,force:!0},r=>{if(r){console.error(`Error removing file: ${r.message}`);return}})},Pl=e=>{let r={doctor:"npx nx react-native doctor",android:"
|
|
64
|
+
`;return this.stop(),this.#n.write(c),this}};function _e(e){return new ql(e)}var z1=require("child_process"),Be=O(require("fs"),1),at=O(require("path"),1);var H1={dependencies:{"@gorhom/bottom-sheet":"5.2.8","@hookform/resolvers":"5.0.1","@react-native-community/datetimepicker":"8.6.0","@react-native-community/hooks":"100.1.0","@react-navigation/core":"7.4.0","@react-navigation/material-top-tabs":"7.2.13","@react-navigation/native-stack":"7.2.1","@react-navigation/native":"7.0.15","@react-navigation/stack":"7.1.2","@shopify/react-native-skia":"2.4.14","@tanstack/query-async-storage-persister":"5.67.3","@tanstack/query-core":"5.67.3","@tanstack/query-sync-storage-persister":"5.67.3","@tanstack/react-query-persist-client":"5.67.3","@tanstack/react-query":"5.67.3",axios:"1.13.2","babel-plugin-module-resolver":"5.0.2",dayjs:"1.11.19","jotai-optics":"0.4.0",jotai:"2.16.1","lodash-es":"4.17.22","react-hook-form":"7.56.4","react-native-dotenv":"3.4.11","react-native-gesture-handler":"2.29.1","react-native-get-random-values":"1.11.0","react-native-haptic-feedback":"2.3.3","react-native-keyboard-controller":"1.19.1","react-native-mmkv":"4.1.0","react-native-modal-datetime-picker":"18.0.0","react-native-modal":"14.0.0-rc.1","react-native-nitro-modules":"0.32.0","react-native-pager-view":"6.8.0","react-native-reanimated":"4.2.1","react-native-safe-area-context":"5.6.0","react-native-screens":"4.19.0","react-native-simple-toast":"3.3.2","react-native-turbo-image":"1.22.1","react-native-url-polyfill":"2.0.0","react-native-worklets":"0.7.1","react-native":"0.83.1",react:"19.2.0",tailwindcss:"3.4.16",twrnc:"4.16.0",uuid:"11.1.0","zod-validation-error":"3.4.0",zod:"3.24.2",zustand:"5.0.5"}};var G1={devDependencies:{"@babel/core":"7.25.2","@babel/eslint-parser":"7.23.10","@babel/preset-env":"7.25.3","@babel/preset-react":"7.27.1","@babel/runtime":"7.25.0","@react-native-community/cli-platform-android":"20.0.0","@react-native-community/cli-platform-ios":"20.0.0","@react-native-community/cli":"20.0.0","@react-native/babel-preset":"0.83.1","@react-native/eslint-config":"0.83.1","@react-native/metro-config":"0.83.1","@react-native/typescript-config":"0.83.1","@swc-node/register":"~1.8.0","@tanstack/eslint-plugin-query":"5.91.2","@testing-library/jest-native":"5.4.3","@testing-library/react-native":"12.5.1","@types/jest":"29.5.13","@types/jwt-encode":"1.0.3","@types/lodash-es":"4.17.12","@types/react-native-vector-icons":"6.4.18","@types/react-test-renderer":"19.1.0","@types/react":"19.2.0","@typescript-eslint/eslint-plugin":"^6.13.2","@typescript-eslint/parser":"^6.21.0","babel-jest":"29.6.3","babel-plugin-module-resolver":"5.0.2","eslint-config-airbnb-typescript":"^17.1.0","eslint-config-prettier":"10.1.8","eslint-import-resolver-typescript":"^3.8.5","eslint-plugin-ft-flow":"2.0.3","eslint-plugin-import":"^2.31.0","eslint-plugin-jest":"27.9.0","eslint-plugin-prettier":"^5.2.3","eslint-plugin-react-hooks":"^4.6.0","eslint-plugin-react-perf":"^3.3.3","eslint-plugin-react":"^7.32.2","eslint-plugin-sonarjs":"0.25.1","eslint-plugin-sort-destructure-keys":"^2.0.0","eslint-plugin-sort-keys-fix":"^1.1.2","eslint-plugin-tailwindcss":"^3.18.0","eslint-plugin-testing-library":"6.2.2",eslint:"8.57.0",husky:"9.1.7","jest-environment-jsdom":"30.1.2",jest:"29.6.3","prettier-plugin-tailwindcss":"^0.6.11",prettier:"3.3.2","react-native-dotenv":"3.4.11","react-native-svg-transformer":"1.3.0","react-native-svg":"15.15.1","react-test-renderer":"19.2.0",typescript:"5.8.3"}};function fa(){return __dirname}var pe=(e,r)=>{(0,z1.execSync)(`cd ${e} && ${r}`,{stdio:"inherit"})},te=(e,r,t,n)=>{let i=at.default.join(fa(),`../templates/${t}/${r}`);!Be.default.existsSync(i)&&n&&(i=at.default.join(fa(),`../templates/${n}/${r}`)),Be.default.copyFile(i,e,u=>{if(u){console.error(`Error copying file: ${u.message}`);return}})},Ne=(e,r,t,n)=>{let i=at.default.join(fa(),`../templates/${t}/${r}`);!Be.default.existsSync(i)&&n&&(i=at.default.join(fa(),`../templates/${n}/${r}`)),Be.default.cpSync(i,e,{recursive:!0},u=>{if(u){console.error(`Error copying file: ${u.message}`);return}})},jl=e=>{Be.default.rmSync(e,{recursive:!0,force:!0},r=>{if(r){console.error(`Error removing directory: ${r.message}`);return}})},ai=e=>{Be.default.rmSync(e,{recursive:!0,force:!0},r=>{if(r){console.error(`Error removing file: ${r.message}`);return}})},Pl=e=>{let r={doctor:"npx nx react-native doctor",android:"npx nx run-android mobile","android:connect":"adb reverse tcp:8081 tcp:8081","check-env:mobile":"./check-env.sh apps/mobile/.env apps/mobile/.env.template",ios:"npx nx run-ios mobile",clean:"./clean-generated-outputs.sh","lint:all":"npx nx run-many -t lint -p mobile --parallel=1 --skip-nx-cache","lint:mobile":"npx nx run mobile:lint --skip-nx-cache",prepare:"husky install","serve:mobile":"npx nx start mobile --skip-nx-cache","serve:all":"npx nx run-many -t serve -p mobile --parallel=1 --skip-nx-cache",xcode:"cd apps/mobile && ./ios-only.sh 'xed -b ios'","touch-xcode":"cd apps/mobile && ./ios-only.sh 'touch ios/.xcode.env'","setup-fastlane":"cd apps/mobile && rbenv local && bundle install && bundle update","deploy:mobile":"cd apps/mobile && ./deploy.sh","ios-certificates":"cd apps/mobile && ./ios-only.sh 'rbenv local && bundle install && bundle update && bundle exec fastlane ios certificates --env development'","pod-install":"npx nx pod-install mobile","pod-install:force":"npx nx pod-install:force mobile","list:ios-configurations":"cd apps/mobile && ./ios-only.sh 'cd ios && xcodebuild -list'","list:ios-devices":"cd apps/mobile && ./ios-only.sh 'xcrun xctrace list devices'","react-native-asset":"cd apps/mobile && npx react-native-asset"},t=at.default.join(e,"package.json"),n=JSON.parse(Be.default.readFileSync(t,"utf8"));n.dependencies={...n.dependencies,...H1.dependencies},n.devDependencies={...n.devDependencies,...G1.devDependencies},n.scripts={...n.scripts,...r},Be.default.writeFileSync(t,JSON.stringify(n,null,2))},K1=e=>{let r=at.default.join(e,"nx.json");if(!Be.default.existsSync(r))return;let t=JSON.parse(Be.default.readFileSync(r,"utf-8"));t.tui={...t.tui||{},enabled:!1},Be.default.writeFileSync(r,JSON.stringify(t,null,2))},kl=(e,r)=>{let t=_e({text:"Configuring iOS Dev scheme and build configurations...",color:"cyan"}).start();try{pe(e,"bundle check || bundle install"),pe(e,"bundle exec ruby ./scripts/setup-ios-dev-scheme.rb"),t.succeed(r.success("iOS Dev scheme and build configurations configured successfully"))}catch(n){throw t.fail(r.error("Failed to configure iOS Dev scheme and build configurations")),n}};var NS="2.7.0",De="21.2.2",E={title:z.bold.cyan,subtitle:z.cyan,success:z.bold.green,info:z.bold.blue,warning:z.hex("#FFA500").bold,error:z.bold.red,highlight:z.bold.magenta,command:z.yellow.italic,path:z.green.underline,step:e=>z.bgCyan.black(` STEP ${e} `),emoji:{rocket:"\u{1F680}",check:"\u2705",warning:"\u26A0\uFE0F",star:"\u2B50",sparkles:"\u2728",tools:"\u{1F6E0}\uFE0F",mobile:"\u{1F4F1}",folder:"\u{1F4C1}",code:"\u{1F4BB}"}},J1=()=>{console.log(`
|
|
65
65
|
`),console.log(E.title("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557")),console.log(E.title("\u2551 \u2551")),console.log(E.title("\u2551 ")+E.highlight("NX REACT NATIVE CLI")+E.title(" \u2551")),console.log(E.title("\u2551 ")+E.subtitle("A powerful starter for React Native with NX")+E.title(" \u2551")),console.log(E.title("\u2551 \u2551")),console.log(E.title("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D")),console.log(`
|
|
66
66
|
`)};yn.name("React Native Starter with NX").description("A starter script to create a new React Native project with NX").version(NS);yn.command("create [workspace_name] [bundle_id]").description("create nx workspace with react-native").option("--fresh","Create a fresh project without copying template files").option("--nx-version <version>","Specify Nx version to use",De).option("--package-manager <pm>","Package manager to use (yarn or npm)","yarn").option("--skip-install","Skip package install after adding dependencies").option("--skip-configs","Skip copying prettier, eslint, and husky configs").action(async(e,r,t)=>{J1(),e||(e=(await ri.prompt([{type:"input",name:"workspace_name",message:E.info("Enter the workspace name:")}])).workspace_name),r||(r=(await ri.prompt([{type:"input",name:"bundle_id",message:E.info("Enter the bundle ID: ex. org.reactjsnative.example")}])).bundle_id);let n=t.fresh||!1,i=t.nxVersion||De,u=t.packageManager||"yarn",o=t.skipInstall||!1,a=t.skipConfigs||!1,s=process.cwd(),c=`${s}/${e}`,x=`${c}/apps/mobile`;console.log(`
|
|
67
67
|
${E.step(1)} ${E.emoji.folder} ${E.success(`Creating Nx workspace in ${E.path(`./${e}`)}`)}`);let d=_e({text:"Setting up Nx workspace...",color:"cyan"}).start();(0,Y1.execSync)(`cd ${s} && npx create-nx-workspace@${i} --preset apps --workspaceType integrated --name ${e} --package-manager=${u} --interactive false --nxCloud skip`,{stdio:"inherit"}),K1(c),d.succeed(E.success("Nx workspace created successfully")),console.log(`
|
package/package.json
CHANGED
|
@@ -7,14 +7,14 @@
|
|
|
7
7
|
"// targets": "to see all targets run: nx show project mobile --web",
|
|
8
8
|
"targets": {
|
|
9
9
|
"check-env": {
|
|
10
|
-
"executor": "nx:run-
|
|
10
|
+
"executor": "nx:run-commands",
|
|
11
11
|
"options": {
|
|
12
|
-
"
|
|
12
|
+
"command": "./check-env.sh apps/mobile/.env apps/mobile/.env.template"
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
15
|
"start": {
|
|
16
16
|
"executor": "@nx/react-native:start",
|
|
17
|
-
"dependsOn": ["check-env", "
|
|
17
|
+
"dependsOn": ["check-env", "pod-install"],
|
|
18
18
|
"options": {
|
|
19
19
|
"port": 8081,
|
|
20
20
|
"resetCache": true,
|
|
@@ -28,9 +28,11 @@
|
|
|
28
28
|
}
|
|
29
29
|
},
|
|
30
30
|
"run-ios": {
|
|
31
|
-
"executor": "
|
|
31
|
+
"executor": "nx:run-commands",
|
|
32
32
|
"dependsOn": ["pod-install"],
|
|
33
|
-
"options": {
|
|
33
|
+
"options": {
|
|
34
|
+
"command": "cd apps/mobile && ./run-ios.sh"
|
|
35
|
+
}
|
|
34
36
|
},
|
|
35
37
|
"bundle-ios": {
|
|
36
38
|
"executor": "@nx/react-native:bundle",
|
|
@@ -43,12 +45,10 @@
|
|
|
43
45
|
}
|
|
44
46
|
},
|
|
45
47
|
"run-android": {
|
|
46
|
-
"executor": "
|
|
48
|
+
"executor": "nx:run-commands",
|
|
47
49
|
"dependsOn": [],
|
|
48
50
|
"options": {
|
|
49
|
-
"
|
|
50
|
-
"mode": "debug",
|
|
51
|
-
"tasks": "installDevDebug"
|
|
51
|
+
"command": "cd apps/mobile && ./run-android.sh"
|
|
52
52
|
}
|
|
53
53
|
},
|
|
54
54
|
"build-android": {
|
|
@@ -67,9 +67,15 @@
|
|
|
67
67
|
"options": {}
|
|
68
68
|
},
|
|
69
69
|
"pod-install": {
|
|
70
|
-
"executor": "nx:run-
|
|
70
|
+
"executor": "nx:run-commands",
|
|
71
71
|
"options": {
|
|
72
|
-
"
|
|
72
|
+
"command": "cd apps/mobile && ./pod-install.sh"
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
"pod-install:force": {
|
|
76
|
+
"executor": "nx:run-commands",
|
|
77
|
+
"options": {
|
|
78
|
+
"command": "cd apps/mobile && ./ios-only.sh 'cd ios && bundle install && bundle exec pod install --repo-update && cd .. && ./export-node-binary.sh'"
|
|
73
79
|
}
|
|
74
80
|
},
|
|
75
81
|
"bundle-android": {
|
|
@@ -82,14 +88,6 @@
|
|
|
82
88
|
"bundleOutput": "dist/apps/mobile/android/main.jsbundle"
|
|
83
89
|
}
|
|
84
90
|
},
|
|
85
|
-
"sync-deps": {
|
|
86
|
-
"executor": "@nx/react-native:sync-deps",
|
|
87
|
-
"options": {}
|
|
88
|
-
},
|
|
89
|
-
"ensure-symlink": {
|
|
90
|
-
"executor": "@nx/react-native:ensure-symlink",
|
|
91
|
-
"options": {}
|
|
92
|
-
},
|
|
93
91
|
"lint": {
|
|
94
92
|
"executor": "@nx/eslint:lint",
|
|
95
93
|
"outputs": ["{options.outputFile}"],
|
|
@@ -7,14 +7,14 @@
|
|
|
7
7
|
"// targets": "to see all targets run: nx show project mobile --web",
|
|
8
8
|
"targets": {
|
|
9
9
|
"check-env": {
|
|
10
|
-
"executor": "nx:run-
|
|
10
|
+
"executor": "nx:run-commands",
|
|
11
11
|
"options": {
|
|
12
|
-
"
|
|
12
|
+
"command": "./check-env.sh apps/mobile/.env apps/mobile/.env.template"
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
15
|
"start": {
|
|
16
16
|
"executor": "@nx/react-native:start",
|
|
17
|
-
"dependsOn": ["check-env", "
|
|
17
|
+
"dependsOn": ["check-env", "pod-install"],
|
|
18
18
|
"options": {
|
|
19
19
|
"port": 8081,
|
|
20
20
|
"resetCache": true,
|
|
@@ -28,9 +28,11 @@
|
|
|
28
28
|
}
|
|
29
29
|
},
|
|
30
30
|
"run-ios": {
|
|
31
|
-
"executor": "
|
|
31
|
+
"executor": "nx:run-commands",
|
|
32
32
|
"dependsOn": ["pod-install"],
|
|
33
|
-
"options": {
|
|
33
|
+
"options": {
|
|
34
|
+
"command": "cd apps/mobile && ./run-ios.sh"
|
|
35
|
+
}
|
|
34
36
|
},
|
|
35
37
|
"bundle-ios": {
|
|
36
38
|
"executor": "@nx/react-native:bundle",
|
|
@@ -43,12 +45,10 @@
|
|
|
43
45
|
}
|
|
44
46
|
},
|
|
45
47
|
"run-android": {
|
|
46
|
-
"executor": "
|
|
48
|
+
"executor": "nx:run-commands",
|
|
47
49
|
"dependsOn": [],
|
|
48
50
|
"options": {
|
|
49
|
-
"
|
|
50
|
-
"mode": "debug",
|
|
51
|
-
"tasks": "installDevDebug"
|
|
51
|
+
"command": "cd apps/mobile && ./run-android.sh"
|
|
52
52
|
}
|
|
53
53
|
},
|
|
54
54
|
"build-android": {
|
|
@@ -67,9 +67,15 @@
|
|
|
67
67
|
"options": {}
|
|
68
68
|
},
|
|
69
69
|
"pod-install": {
|
|
70
|
-
"executor": "nx:run-
|
|
70
|
+
"executor": "nx:run-commands",
|
|
71
71
|
"options": {
|
|
72
|
-
"
|
|
72
|
+
"command": "cd apps/mobile && ./pod-install.sh"
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
"pod-install:force": {
|
|
76
|
+
"executor": "nx:run-commands",
|
|
77
|
+
"options": {
|
|
78
|
+
"command": "cd apps/mobile && ./ios-only.sh 'cd ios && bundle install && bundle exec pod install --repo-update && cd .. && ./export-node-binary.sh'"
|
|
73
79
|
}
|
|
74
80
|
},
|
|
75
81
|
"bundle-android": {
|
|
@@ -82,14 +88,6 @@
|
|
|
82
88
|
"bundleOutput": "dist/apps/mobile/android/main.jsbundle"
|
|
83
89
|
}
|
|
84
90
|
},
|
|
85
|
-
"sync-deps": {
|
|
86
|
-
"executor": "@nx/react-native:sync-deps",
|
|
87
|
-
"options": {}
|
|
88
|
-
},
|
|
89
|
-
"ensure-symlink": {
|
|
90
|
-
"executor": "@nx/react-native:ensure-symlink",
|
|
91
|
-
"options": {}
|
|
92
|
-
},
|
|
93
91
|
"lint": {
|
|
94
92
|
"executor": "@nx/eslint:lint",
|
|
95
93
|
"outputs": ["{options.outputFile}"],
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Interactive deployment - picks platform, lane, and environment
|
|
3
|
+
|
|
4
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
5
|
+
FASTLANE_DIR="$SCRIPT_DIR/fastlane"
|
|
6
|
+
|
|
7
|
+
source "$SCRIPT_DIR/picker.sh"
|
|
8
|
+
|
|
9
|
+
# --- Platform selection ---
|
|
10
|
+
PLATFORMS=("ios" "android")
|
|
11
|
+
pick "Select a platform:" "${PLATFORMS[@]}" --key "deploy-platform"
|
|
12
|
+
SELECTED_PLATFORM="${PLATFORMS[$PICKED_INDEX]}"
|
|
13
|
+
|
|
14
|
+
# --- Lane selection (dynamically parsed from Fastfile) ---
|
|
15
|
+
LANES=$(python3 -c "
|
|
16
|
+
import re
|
|
17
|
+
with open('$FASTLANE_DIR/Fastfile') as f:
|
|
18
|
+
content = f.read()
|
|
19
|
+
|
|
20
|
+
# Find the platform block for the selected platform
|
|
21
|
+
pattern = r'platform\s+:$SELECTED_PLATFORM\s+do(.*?)^end'
|
|
22
|
+
match = re.search(pattern, content, re.DOTALL | re.MULTILINE)
|
|
23
|
+
if match:
|
|
24
|
+
block = match.group(1)
|
|
25
|
+
# Find all lane declarations
|
|
26
|
+
lanes = re.findall(r'lane\s+:(\w+)\s+do', block)
|
|
27
|
+
for lane in lanes:
|
|
28
|
+
print(lane)
|
|
29
|
+
")
|
|
30
|
+
|
|
31
|
+
if [ -z "$LANES" ]; then
|
|
32
|
+
echo "No lanes found for platform: $SELECTED_PLATFORM"
|
|
33
|
+
exit 1
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
LANE_ARRAY=()
|
|
37
|
+
while IFS= read -r line; do
|
|
38
|
+
[ -z "$line" ] && continue
|
|
39
|
+
LANE_ARRAY+=("$line")
|
|
40
|
+
done <<< "$LANES"
|
|
41
|
+
|
|
42
|
+
pick "Select a lane:" "${LANE_ARRAY[@]}" --key "deploy-lane-$SELECTED_PLATFORM"
|
|
43
|
+
SELECTED_LANE="${LANE_ARRAY[$PICKED_INDEX]}"
|
|
44
|
+
|
|
45
|
+
# --- Environment selection (dynamically from .env.* files) ---
|
|
46
|
+
ENV_ARRAY=()
|
|
47
|
+
for env_file in "$FASTLANE_DIR"/.env.*; do
|
|
48
|
+
[ -f "$env_file" ] || continue
|
|
49
|
+
env_name=$(basename "$env_file" | sed 's/^\.env\.//')
|
|
50
|
+
# Skip template
|
|
51
|
+
if [ "$env_name" = "template" ]; then
|
|
52
|
+
continue
|
|
53
|
+
fi
|
|
54
|
+
ENV_ARRAY+=("$env_name")
|
|
55
|
+
done
|
|
56
|
+
|
|
57
|
+
if [ ${#ENV_ARRAY[@]} -eq 0 ]; then
|
|
58
|
+
echo ""
|
|
59
|
+
echo "No environment files found. Create at least one of:"
|
|
60
|
+
echo " fastlane/.env.development"
|
|
61
|
+
echo " fastlane/.env.staging"
|
|
62
|
+
echo " fastlane/.env.production"
|
|
63
|
+
exit 1
|
|
64
|
+
fi
|
|
65
|
+
|
|
66
|
+
pick "Select an environment:" "${ENV_ARRAY[@]}" --key "deploy-env"
|
|
67
|
+
SELECTED_ENV="${ENV_ARRAY[$PICKED_INDEX]}"
|
|
68
|
+
|
|
69
|
+
# --- Safeguard: check for local URLs in .env ---
|
|
70
|
+
APP_ENV="$SCRIPT_DIR/.env"
|
|
71
|
+
if [ -f "$APP_ENV" ]; then
|
|
72
|
+
if grep -qiE 'localhost|192\.168\.' "$APP_ENV"; then
|
|
73
|
+
echo ""
|
|
74
|
+
echo "Deployment aborted: apps/mobile/.env contains a local URL (localhost or 192.168.*)."
|
|
75
|
+
echo "Update your .env to point to the correct remote server before deploying."
|
|
76
|
+
exit 1
|
|
77
|
+
fi
|
|
78
|
+
fi
|
|
79
|
+
|
|
80
|
+
# --- Confirmation ---
|
|
81
|
+
echo ""
|
|
82
|
+
echo "Deploy summary:"
|
|
83
|
+
echo " Platform: $SELECTED_PLATFORM"
|
|
84
|
+
echo " Lane: $SELECTED_LANE"
|
|
85
|
+
if [ -n "$SELECTED_ENV" ]; then
|
|
86
|
+
echo " Environment: $SELECTED_ENV"
|
|
87
|
+
fi
|
|
88
|
+
echo ""
|
|
89
|
+
|
|
90
|
+
CONFIRM_ARRAY=("Yes" "No")
|
|
91
|
+
pick "Proceed with deployment?" "${CONFIRM_ARRAY[@]}"
|
|
92
|
+
if [ "$PICKED_INDEX" -ne 0 ]; then
|
|
93
|
+
echo "Deployment cancelled."
|
|
94
|
+
exit 0
|
|
95
|
+
fi
|
|
96
|
+
|
|
97
|
+
# --- Run fastlane ---
|
|
98
|
+
echo ""
|
|
99
|
+
FASTLANE_CMD="bundle exec fastlane $SELECTED_PLATFORM $SELECTED_LANE"
|
|
100
|
+
if [ -n "$SELECTED_ENV" ]; then
|
|
101
|
+
FASTLANE_CMD="$FASTLANE_CMD --env $SELECTED_ENV"
|
|
102
|
+
fi
|
|
103
|
+
|
|
104
|
+
echo "Running: $FASTLANE_CMD"
|
|
105
|
+
echo ""
|
|
106
|
+
|
|
107
|
+
cd "$SCRIPT_DIR" && $FASTLANE_CMD
|
|
@@ -1,82 +1,5 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mobile",
|
|
3
3
|
"version": "0.0.1",
|
|
4
|
-
"private": true
|
|
5
|
-
"scripts": {
|
|
6
|
-
"android:connect": "adb reverse tcp:8081 tcp:8081",
|
|
7
|
-
"start": "npx nx start mobile --skip-nx-cache",
|
|
8
|
-
"run-ios": "./ios-only.sh npx nx run-ios mobile --skip-nx-cache --scheme=Dev --simulator='iPhone 16'",
|
|
9
|
-
"run-android": "npx nx run-android mobile --skip-nx-cache",
|
|
10
|
-
"ensure-symlink": "npx nx ensure-symlink mobile",
|
|
11
|
-
"sync-deps": "npx nx sync-deps mobile",
|
|
12
|
-
"pod-install": "./ios-only.sh npx nx pod-install mobile",
|
|
13
|
-
"export-node-binary": "./export-node-binary.sh",
|
|
14
|
-
"bundle:pod-install": "./ios-only.sh 'cd ios && bundle install && bundle exec pod install --repo-update && npm run export-node-binary'",
|
|
15
|
-
"pre-build": "npm run ensure-symlink && npm run sync-deps && npm run pod-install",
|
|
16
|
-
"list:ios-configurations": "./ios-only.sh 'cd ios && xcodebuild -list'",
|
|
17
|
-
"list:ios-devices": "./ios-only.sh xcrun xctrace list devices",
|
|
18
|
-
"xcode": "./ios-only.sh xed -b ios",
|
|
19
|
-
"touch-xcode": "./ios-only.sh 'cd ios && touch .xcode.env'",
|
|
20
|
-
"check-env:mobile": "cd ../.. && npm run check-env:mobile",
|
|
21
|
-
"setup-fastlane": "rbenv local && bundle install && bundle update",
|
|
22
|
-
"deploy-android:dev": "bundle exec fastlane android dev --env development",
|
|
23
|
-
"deploy-ios:dev": "./ios-only.sh 'bundle exec fastlane ios dev --env development'",
|
|
24
|
-
"ios-certificates": "./ios-only.sh 'npm run setup-fastlane && bundle exec fastlane ios certificates --env development'"
|
|
25
|
-
},
|
|
26
|
-
"dependencies": {
|
|
27
|
-
"@gorhom/bottom-sheet": "*",
|
|
28
|
-
"@hookform/resolvers": "*",
|
|
29
|
-
"@react-native-community/datetimepicker": "*",
|
|
30
|
-
"@react-native-community/hooks": "*",
|
|
31
|
-
"@react-native/metro-config": "*",
|
|
32
|
-
"@react-navigation/core": "*",
|
|
33
|
-
"@react-navigation/material-top-tabs": "*",
|
|
34
|
-
"@react-navigation/native-stack": "*",
|
|
35
|
-
"@react-navigation/native": "*",
|
|
36
|
-
"@react-navigation/routers": "*",
|
|
37
|
-
"@react-navigation/stack": "*",
|
|
38
|
-
"@shopify/react-native-skia": "*",
|
|
39
|
-
"@tanstack/query-async-storage-persister": "*",
|
|
40
|
-
"@tanstack/query-core": "*",
|
|
41
|
-
"@tanstack/query-sync-storage-persister": "*",
|
|
42
|
-
"@tanstack/react-query-persist-client": "*",
|
|
43
|
-
"@tanstack/react-query": "*",
|
|
44
|
-
"@testing-library/jest-native": "*",
|
|
45
|
-
"@testing-library/react-native": "*",
|
|
46
|
-
"axios": "*",
|
|
47
|
-
"babel-plugin-module-resolver": "*",
|
|
48
|
-
"dayjs": "*",
|
|
49
|
-
"jotai-optics": "*",
|
|
50
|
-
"jotai": "*",
|
|
51
|
-
"lodash": "*",
|
|
52
|
-
"metro-config": "*",
|
|
53
|
-
"react-hook-form": "*",
|
|
54
|
-
"react-native-dotenv": "*",
|
|
55
|
-
"react-native-gesture-handler": "*",
|
|
56
|
-
"react-native-get-random-values": "*",
|
|
57
|
-
"react-native-haptic-feedback": "*",
|
|
58
|
-
"react-native-keyboard-controller": "*",
|
|
59
|
-
"react-native-mmkv": "*",
|
|
60
|
-
"react-native-modal-datetime-picker": "*",
|
|
61
|
-
"react-native-modal": "*",
|
|
62
|
-
"react-native-nitro-modules": "*",
|
|
63
|
-
"react-native-pager-view": "*",
|
|
64
|
-
"react-native-reanimated": "*",
|
|
65
|
-
"react-native-safe-area-context": "*",
|
|
66
|
-
"react-native-screens": "*",
|
|
67
|
-
"react-native-simple-toast": "*",
|
|
68
|
-
"react-native-svg-transformer": "*",
|
|
69
|
-
"react-native-svg": "*",
|
|
70
|
-
"react-native-turbo-image": "*",
|
|
71
|
-
"react-native-url-polyfill": "*",
|
|
72
|
-
"react-native-worklets": "*",
|
|
73
|
-
"react-native": "*",
|
|
74
|
-
"react": "*",
|
|
75
|
-
"tailwindcss": "*",
|
|
76
|
-
"twrnc": "*",
|
|
77
|
-
"uuid": "*",
|
|
78
|
-
"zod-validation-error": "*",
|
|
79
|
-
"zod": "*",
|
|
80
|
-
"zustand": "*"
|
|
81
|
-
}
|
|
4
|
+
"private": true
|
|
82
5
|
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Arrow key menu picker with scrolling and recent selection memory
|
|
3
|
+
# Usage: source picker.sh
|
|
4
|
+
# pick "Title" options_array # no memory
|
|
5
|
+
# pick "Title" options_array --key "cache-key" # remembers last pick
|
|
6
|
+
|
|
7
|
+
PICKER_CACHE_DIR="${HOME}/.cache/nxrn-picker"
|
|
8
|
+
|
|
9
|
+
pick() {
|
|
10
|
+
local title="$1"
|
|
11
|
+
shift
|
|
12
|
+
|
|
13
|
+
# Parse options and --key flag
|
|
14
|
+
local raw_options=()
|
|
15
|
+
local cache_key=""
|
|
16
|
+
while [ $# -gt 0 ]; do
|
|
17
|
+
if [ "$1" = "--key" ]; then
|
|
18
|
+
cache_key="$2"
|
|
19
|
+
shift 2
|
|
20
|
+
else
|
|
21
|
+
raw_options+=("$1")
|
|
22
|
+
shift
|
|
23
|
+
fi
|
|
24
|
+
done
|
|
25
|
+
|
|
26
|
+
local options=("${raw_options[@]}")
|
|
27
|
+
local count=${#options[@]}
|
|
28
|
+
local selected=0
|
|
29
|
+
|
|
30
|
+
# If cache key provided, sort last-used to top
|
|
31
|
+
local reordered_indices=()
|
|
32
|
+
if [ -n "$cache_key" ] && [ -f "$PICKER_CACHE_DIR/$cache_key" ]; then
|
|
33
|
+
local last_pick
|
|
34
|
+
last_pick=$(cat "$PICKER_CACHE_DIR/$cache_key")
|
|
35
|
+
|
|
36
|
+
# Find the last-used item and move it to front
|
|
37
|
+
local found_idx=-1
|
|
38
|
+
for i in "${!options[@]}"; do
|
|
39
|
+
if [ "${options[$i]}" = "$last_pick" ]; then
|
|
40
|
+
found_idx=$i
|
|
41
|
+
break
|
|
42
|
+
fi
|
|
43
|
+
done
|
|
44
|
+
|
|
45
|
+
if [ $found_idx -ge 0 ]; then
|
|
46
|
+
local new_options=("${options[$found_idx]}")
|
|
47
|
+
reordered_indices=($found_idx)
|
|
48
|
+
for i in "${!options[@]}"; do
|
|
49
|
+
if [ "$i" -ne $found_idx ]; then
|
|
50
|
+
new_options+=("${options[$i]}")
|
|
51
|
+
reordered_indices+=($i)
|
|
52
|
+
fi
|
|
53
|
+
done
|
|
54
|
+
options=("${new_options[@]}")
|
|
55
|
+
fi
|
|
56
|
+
fi
|
|
57
|
+
|
|
58
|
+
# If no reorder happened, build identity mapping
|
|
59
|
+
if [ ${#reordered_indices[@]} -eq 0 ]; then
|
|
60
|
+
for i in "${!options[@]}"; do
|
|
61
|
+
reordered_indices+=($i)
|
|
62
|
+
done
|
|
63
|
+
fi
|
|
64
|
+
|
|
65
|
+
# Max visible rows
|
|
66
|
+
local term_height=$(tput lines)
|
|
67
|
+
local max_visible=$((term_height - 4))
|
|
68
|
+
if [ $max_visible -gt $count ]; then
|
|
69
|
+
max_visible=$count
|
|
70
|
+
fi
|
|
71
|
+
if [ $max_visible -lt 3 ]; then
|
|
72
|
+
max_visible=3
|
|
73
|
+
fi
|
|
74
|
+
|
|
75
|
+
local scroll_offset=0
|
|
76
|
+
|
|
77
|
+
tput civis
|
|
78
|
+
trap 'tput cnorm' RETURN
|
|
79
|
+
|
|
80
|
+
draw_menu() {
|
|
81
|
+
for ((i = 0; i < max_visible; i++)); do
|
|
82
|
+
local idx=$((scroll_offset + i))
|
|
83
|
+
tput el
|
|
84
|
+
if [ "$idx" -eq $selected ]; then
|
|
85
|
+
echo -e " \033[7m> ${options[$idx]}\033[0m"
|
|
86
|
+
else
|
|
87
|
+
echo " ${options[$idx]}"
|
|
88
|
+
fi
|
|
89
|
+
done
|
|
90
|
+
tput el
|
|
91
|
+
if [ $count -gt $max_visible ]; then
|
|
92
|
+
echo -e " \033[2m[$((selected + 1))/$count]\033[0m"
|
|
93
|
+
else
|
|
94
|
+
echo ""
|
|
95
|
+
fi
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
echo ""
|
|
99
|
+
echo "$title"
|
|
100
|
+
draw_menu
|
|
101
|
+
|
|
102
|
+
local visible_lines=$((max_visible + 1))
|
|
103
|
+
|
|
104
|
+
while true; do
|
|
105
|
+
IFS= read -rsn1 key
|
|
106
|
+
|
|
107
|
+
if [[ "$key" == $'\x1b' ]]; then
|
|
108
|
+
read -rsn2 rest
|
|
109
|
+
key+="$rest"
|
|
110
|
+
fi
|
|
111
|
+
|
|
112
|
+
case "$key" in
|
|
113
|
+
$'\x1b[A' | k)
|
|
114
|
+
((selected--))
|
|
115
|
+
if [ $selected -lt 0 ]; then
|
|
116
|
+
selected=$((count - 1))
|
|
117
|
+
scroll_offset=$((count - max_visible))
|
|
118
|
+
if [ $scroll_offset -lt 0 ]; then scroll_offset=0; fi
|
|
119
|
+
elif [ $selected -lt $scroll_offset ]; then
|
|
120
|
+
scroll_offset=$selected
|
|
121
|
+
fi
|
|
122
|
+
;;
|
|
123
|
+
$'\x1b[B' | j)
|
|
124
|
+
((selected++))
|
|
125
|
+
if [ $selected -ge $count ]; then
|
|
126
|
+
selected=0
|
|
127
|
+
scroll_offset=0
|
|
128
|
+
elif [ $selected -ge $((scroll_offset + max_visible)) ]; then
|
|
129
|
+
scroll_offset=$((selected - max_visible + 1))
|
|
130
|
+
fi
|
|
131
|
+
;;
|
|
132
|
+
'')
|
|
133
|
+
break
|
|
134
|
+
;;
|
|
135
|
+
esac
|
|
136
|
+
|
|
137
|
+
tput cuu $visible_lines
|
|
138
|
+
draw_menu
|
|
139
|
+
done
|
|
140
|
+
|
|
141
|
+
tput cnorm
|
|
142
|
+
|
|
143
|
+
# Save selection to cache
|
|
144
|
+
if [ -n "$cache_key" ]; then
|
|
145
|
+
mkdir -p "$PICKER_CACHE_DIR"
|
|
146
|
+
echo "${options[$selected]}" > "$PICKER_CACHE_DIR/$cache_key"
|
|
147
|
+
fi
|
|
148
|
+
|
|
149
|
+
# Map back to original index
|
|
150
|
+
PICKED_INDEX=${reordered_indices[$selected]}
|
|
151
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Smart pod install - only runs when dependencies have changed
|
|
3
|
+
# Compares checksum of Podfile + root package.json deps against cached value
|
|
4
|
+
|
|
5
|
+
if [[ "$OSTYPE" != "darwin"* ]]; then
|
|
6
|
+
echo "Skipping pod install on non-macOS platform"
|
|
7
|
+
exit 0
|
|
8
|
+
fi
|
|
9
|
+
|
|
10
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
11
|
+
IOS_DIR="$SCRIPT_DIR/ios"
|
|
12
|
+
ROOT_DIR="$SCRIPT_DIR/../.."
|
|
13
|
+
CHECKSUM_FILE="$IOS_DIR/.pods-checksum"
|
|
14
|
+
|
|
15
|
+
# Generate checksum from files that affect pods
|
|
16
|
+
CURRENT_CHECKSUM=$(cat \
|
|
17
|
+
"$IOS_DIR/Podfile" \
|
|
18
|
+
"$ROOT_DIR/package.json" \
|
|
19
|
+
"$ROOT_DIR/yarn.lock" \
|
|
20
|
+
2>/dev/null | shasum -a 256 | awk '{print $1}')
|
|
21
|
+
|
|
22
|
+
# Compare with cached checksum
|
|
23
|
+
if [ -f "$CHECKSUM_FILE" ]; then
|
|
24
|
+
CACHED_CHECKSUM=$(cat "$CHECKSUM_FILE")
|
|
25
|
+
if [ "$CURRENT_CHECKSUM" = "$CACHED_CHECKSUM" ]; then
|
|
26
|
+
echo "Pods up to date, skipping install."
|
|
27
|
+
exit 0
|
|
28
|
+
fi
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
echo "Dependencies changed, running pod install..."
|
|
32
|
+
cd "$IOS_DIR" && bundle install && bundle exec pod install
|
|
33
|
+
|
|
34
|
+
if [ $? -eq 0 ]; then
|
|
35
|
+
echo "$CURRENT_CHECKSUM" > "$CHECKSUM_FILE"
|
|
36
|
+
cd "$SCRIPT_DIR" && ./export-node-binary.sh
|
|
37
|
+
else
|
|
38
|
+
echo "Pod install failed"
|
|
39
|
+
exit 1
|
|
40
|
+
fi
|
|
@@ -1,4 +1,19 @@
|
|
|
1
|
+
const rootPkg = require('../../package.json');
|
|
2
|
+
|
|
3
|
+
// Dynamically read all dependencies from the root package.json
|
|
4
|
+
// so autolinking discovers native modules without duplicating deps here.
|
|
5
|
+
const allDeps = Object.keys({
|
|
6
|
+
...rootPkg.dependencies,
|
|
7
|
+
...rootPkg.devDependencies,
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
const dependencies = {};
|
|
11
|
+
for (const dep of allDeps) {
|
|
12
|
+
dependencies[dep] = {};
|
|
13
|
+
}
|
|
14
|
+
|
|
1
15
|
module.exports = {
|
|
16
|
+
dependencies,
|
|
2
17
|
project: {
|
|
3
18
|
ios: {},
|
|
4
19
|
android: {},
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Interactive Android launcher - picks variant and device
|
|
3
|
+
|
|
4
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
5
|
+
ANDROID_DIR="$SCRIPT_DIR/android"
|
|
6
|
+
|
|
7
|
+
source "$SCRIPT_DIR/picker.sh"
|
|
8
|
+
|
|
9
|
+
# --- Variant selection via gradle install tasks ---
|
|
10
|
+
echo ""
|
|
11
|
+
echo "Fetching build variants..."
|
|
12
|
+
|
|
13
|
+
INSTALL_TASKS=$(cd "$ANDROID_DIR" && ./gradlew app:tasks --group=install --quiet 2>/dev/null | grep "^install" | grep -vi "AndroidTest\|Optimized" | awk '{print $1}')
|
|
14
|
+
|
|
15
|
+
if [ -z "$INSTALL_TASKS" ]; then
|
|
16
|
+
echo "Could not read build variants from Gradle"
|
|
17
|
+
exit 1
|
|
18
|
+
fi
|
|
19
|
+
|
|
20
|
+
TASK_ARRAY=()
|
|
21
|
+
DISPLAY_ARRAY=()
|
|
22
|
+
while IFS= read -r line; do
|
|
23
|
+
[ -z "$line" ] && continue
|
|
24
|
+
TASK_ARRAY+=("$line")
|
|
25
|
+
DISPLAY_ARRAY+=("${line#install}")
|
|
26
|
+
done <<< "$INSTALL_TASKS"
|
|
27
|
+
|
|
28
|
+
pick "Select a build variant:" "${DISPLAY_ARRAY[@]}" --key "android-variant"
|
|
29
|
+
SELECTED_TASK="${TASK_ARRAY[$PICKED_INDEX]}"
|
|
30
|
+
SELECTED_VARIANT="${SELECTED_TASK#install}"
|
|
31
|
+
|
|
32
|
+
# Mode is the full variant name with first letter lowercased (e.g. devDebug, productionRelease)
|
|
33
|
+
MODE="$(tr '[:upper:]' '[:lower:]' <<< "${SELECTED_VARIANT:0:1}")${SELECTED_VARIANT:1}"
|
|
34
|
+
|
|
35
|
+
# Infer appIdSuffix from flavor (lowercase first char of variant minus build type)
|
|
36
|
+
FLAVOR=$(echo "$SELECTED_VARIANT" | sed -E 's/(Debug|Release)$//' | tr '[:upper:]' '[:lower:]')
|
|
37
|
+
APP_ID_SUFFIX=""
|
|
38
|
+
if [ "$FLAVOR" != "production" ] && [ -n "$FLAVOR" ]; then
|
|
39
|
+
APP_ID_SUFFIX="$FLAVOR"
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
# --- Device selection (booted devices + shutdown AVDs) ---
|
|
43
|
+
DEVICE_ARRAY=()
|
|
44
|
+
DEVICE_IDS=()
|
|
45
|
+
DEVICE_TYPES=() # "booted" or "avd"
|
|
46
|
+
|
|
47
|
+
# Collect running devices/emulators
|
|
48
|
+
RUNNING_AVDS=()
|
|
49
|
+
DEVICES=$(adb devices -l 2>/dev/null | tail -n +2 | grep -v '^$')
|
|
50
|
+
if [ -n "$DEVICES" ]; then
|
|
51
|
+
while IFS= read -r line; do
|
|
52
|
+
[ -z "$line" ] && continue
|
|
53
|
+
SERIAL=$(echo "$line" | awk '{print $1}')
|
|
54
|
+
MODEL=$(echo "$line" | grep -o 'model:[^ ]*' | cut -d: -f2)
|
|
55
|
+
|
|
56
|
+
if echo "$SERIAL" | grep -q "emulator"; then
|
|
57
|
+
# Get AVD name for this running emulator
|
|
58
|
+
AVD_NAME=$(adb -s "$SERIAL" emu avd name 2>/dev/null | head -1 | tr -d '\r')
|
|
59
|
+
RUNNING_AVDS+=("$AVD_NAME")
|
|
60
|
+
LABEL="[Booted] $SERIAL${AVD_NAME:+ ($AVD_NAME)}"
|
|
61
|
+
else
|
|
62
|
+
LABEL="[Device] $SERIAL${MODEL:+ ($MODEL)}"
|
|
63
|
+
fi
|
|
64
|
+
|
|
65
|
+
DEVICE_ARRAY+=("$LABEL")
|
|
66
|
+
DEVICE_IDS+=("$SERIAL")
|
|
67
|
+
DEVICE_TYPES+=("booted")
|
|
68
|
+
done <<< "$DEVICES"
|
|
69
|
+
fi
|
|
70
|
+
|
|
71
|
+
# Collect shutdown AVDs
|
|
72
|
+
ALL_AVDS=$(emulator -list-avds 2>/dev/null)
|
|
73
|
+
if [ -n "$ALL_AVDS" ]; then
|
|
74
|
+
while IFS= read -r avd; do
|
|
75
|
+
[ -z "$avd" ] && continue
|
|
76
|
+
# Skip if already running
|
|
77
|
+
ALREADY_RUNNING=false
|
|
78
|
+
for running in "${RUNNING_AVDS[@]}"; do
|
|
79
|
+
if [ "$avd" = "$running" ]; then
|
|
80
|
+
ALREADY_RUNNING=true
|
|
81
|
+
break
|
|
82
|
+
fi
|
|
83
|
+
done
|
|
84
|
+
if [ "$ALREADY_RUNNING" = false ]; then
|
|
85
|
+
DEVICE_ARRAY+=("[Shutdown] $avd")
|
|
86
|
+
DEVICE_IDS+=("$avd")
|
|
87
|
+
DEVICE_TYPES+=("avd")
|
|
88
|
+
fi
|
|
89
|
+
done <<< "$ALL_AVDS"
|
|
90
|
+
fi
|
|
91
|
+
|
|
92
|
+
if [ ${#DEVICE_ARRAY[@]} -eq 0 ]; then
|
|
93
|
+
echo ""
|
|
94
|
+
echo "No Android devices or AVDs found."
|
|
95
|
+
exit 1
|
|
96
|
+
fi
|
|
97
|
+
|
|
98
|
+
pick "Select a device:" "${DEVICE_ARRAY[@]}" --key "android-device"
|
|
99
|
+
SELECTED_INDEX=$PICKED_INDEX
|
|
100
|
+
SELECTED_DEVICE="${DEVICE_IDS[$SELECTED_INDEX]}"
|
|
101
|
+
|
|
102
|
+
# Boot AVD if shutdown
|
|
103
|
+
if [ "${DEVICE_TYPES[$SELECTED_INDEX]}" = "avd" ]; then
|
|
104
|
+
echo ""
|
|
105
|
+
echo "Booting AVD: $SELECTED_DEVICE..."
|
|
106
|
+
emulator -avd "$SELECTED_DEVICE" -no-snapshot-load &>/dev/null &
|
|
107
|
+
|
|
108
|
+
# Wait for device to come online
|
|
109
|
+
echo "Waiting for device to boot..."
|
|
110
|
+
adb wait-for-device
|
|
111
|
+
# Wait for boot animation to finish
|
|
112
|
+
while [ "$(adb shell getprop sys.boot_completed 2>/dev/null | tr -d '\r')" != "1" ]; do
|
|
113
|
+
sleep 1
|
|
114
|
+
done
|
|
115
|
+
echo "Device booted."
|
|
116
|
+
|
|
117
|
+
# Get the serial of the newly booted emulator
|
|
118
|
+
SELECTED_DEVICE=$(adb devices | grep "emulator" | tail -1 | awk '{print $1}')
|
|
119
|
+
fi
|
|
120
|
+
|
|
121
|
+
echo ""
|
|
122
|
+
echo "Running: task=$SELECTED_TASK mode=$MODE device=$SELECTED_DEVICE"
|
|
123
|
+
echo ""
|
|
124
|
+
|
|
125
|
+
RN_ARGS="--tasks=$SELECTED_TASK --mode=$MODE --device=$SELECTED_DEVICE"
|
|
126
|
+
if [ -n "$APP_ID_SUFFIX" ]; then
|
|
127
|
+
RN_ARGS="$RN_ARGS --appIdSuffix=$APP_ID_SUFFIX"
|
|
128
|
+
fi
|
|
129
|
+
|
|
130
|
+
cd "$SCRIPT_DIR" && npx react-native run-android $RN_ARGS
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Interactive iOS launcher - picks scheme and simulator
|
|
3
|
+
|
|
4
|
+
if [[ "$OSTYPE" != "darwin"* ]]; then
|
|
5
|
+
echo "iOS builds only work on macOS"
|
|
6
|
+
exit 1
|
|
7
|
+
fi
|
|
8
|
+
|
|
9
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
10
|
+
PROJECT_DIR="$SCRIPT_DIR/ios"
|
|
11
|
+
|
|
12
|
+
source "$SCRIPT_DIR/picker.sh"
|
|
13
|
+
|
|
14
|
+
# --- Scheme selection ---
|
|
15
|
+
SCHEMES=$(cd "$PROJECT_DIR" && xcodebuild -list -json 2>/dev/null | python3 -c "
|
|
16
|
+
import sys, json
|
|
17
|
+
data = json.load(sys.stdin)
|
|
18
|
+
for s in data.get('project', {}).get('schemes', []):
|
|
19
|
+
print(s)
|
|
20
|
+
")
|
|
21
|
+
|
|
22
|
+
if [ -z "$SCHEMES" ]; then
|
|
23
|
+
echo "Could not read schemes from Xcode project"
|
|
24
|
+
exit 1
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
SCHEME_ARRAY=()
|
|
28
|
+
while IFS= read -r line; do
|
|
29
|
+
SCHEME_ARRAY+=("$line")
|
|
30
|
+
done <<< "$SCHEMES"
|
|
31
|
+
|
|
32
|
+
pick "Select a scheme:" "${SCHEME_ARRAY[@]}" --key "ios-scheme"
|
|
33
|
+
SELECTED_SCHEME="${SCHEME_ARRAY[$PICKED_INDEX]}"
|
|
34
|
+
|
|
35
|
+
# --- Simulator selection (booted first, then by name, then iOS version desc) ---
|
|
36
|
+
SIMULATORS=$(xcrun simctl list devices available -j 2>/dev/null | python3 -c "
|
|
37
|
+
import sys, json, re
|
|
38
|
+
|
|
39
|
+
data = json.load(sys.stdin)
|
|
40
|
+
devices_list = []
|
|
41
|
+
|
|
42
|
+
for runtime, devices in data.get('devices', {}).items():
|
|
43
|
+
if 'iOS' not in runtime:
|
|
44
|
+
continue
|
|
45
|
+
ver_match = re.search(r'(\d+)[\-\.](\d+)', runtime)
|
|
46
|
+
if not ver_match:
|
|
47
|
+
continue
|
|
48
|
+
ver_major, ver_minor = int(ver_match.group(1)), int(ver_match.group(2))
|
|
49
|
+
ver = f'{ver_major}.{ver_minor}'
|
|
50
|
+
for d in devices:
|
|
51
|
+
is_booted = d['state'] == 'Booted'
|
|
52
|
+
devices_list.append((is_booted, d['name'], ver_major, ver_minor, ver))
|
|
53
|
+
|
|
54
|
+
# Parse model number from name (e.g. 'iPhone 16 Pro Max' -> 16)
|
|
55
|
+
def sort_key(x):
|
|
56
|
+
is_booted, name, ver_major, ver_minor, ver = x
|
|
57
|
+
is_iphone = name.startswith('iPhone')
|
|
58
|
+
model_match = re.search(r'(\d+)', name)
|
|
59
|
+
model_num = int(model_match.group(1)) if model_match else 0
|
|
60
|
+
# booted first, iPhone over iPad, highest model first, Pro Max > Pro > base, newest iOS first
|
|
61
|
+
return (not is_booted, not is_iphone, -model_num, name.count('Pro') == 0, 'Max' not in name, -ver_major, -ver_minor)
|
|
62
|
+
|
|
63
|
+
devices_list.sort(key=sort_key)
|
|
64
|
+
|
|
65
|
+
for is_booted, name, _, _, ver in devices_list:
|
|
66
|
+
prefix = '[Booted] ' if is_booted else ''
|
|
67
|
+
print(f'{prefix}{name} ({ver})')
|
|
68
|
+
")
|
|
69
|
+
|
|
70
|
+
if [ -z "$SIMULATORS" ]; then
|
|
71
|
+
echo "No iOS simulators found"
|
|
72
|
+
exit 1
|
|
73
|
+
fi
|
|
74
|
+
|
|
75
|
+
SIM_ARRAY=()
|
|
76
|
+
while IFS= read -r line; do
|
|
77
|
+
SIM_ARRAY+=("$line")
|
|
78
|
+
done <<< "$SIMULATORS"
|
|
79
|
+
|
|
80
|
+
pick "Select a simulator:" "${SIM_ARRAY[@]}" --key "ios-simulator"
|
|
81
|
+
SELECTED_SIM="${SIM_ARRAY[$PICKED_INDEX]}"
|
|
82
|
+
# Strip [Booted] prefix to get "Name (version)"
|
|
83
|
+
SIM_NAME=$(echo "$SELECTED_SIM" | sed 's/^\[Booted\] //')
|
|
84
|
+
|
|
85
|
+
echo ""
|
|
86
|
+
echo "Running: scheme=$SELECTED_SCHEME simulator=$SIM_NAME"
|
|
87
|
+
echo ""
|
|
88
|
+
|
|
89
|
+
cd "$SCRIPT_DIR" && npx react-native run-ios --scheme="$SELECTED_SCHEME" --simulator="$SIM_NAME"
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
/* eslint-disable no-magic-numbers */
|
|
2
2
|
import { BottomSheetModalProvider } from '@gorhom/bottom-sheet';
|
|
3
3
|
import React, { useCallback, useState } from 'react';
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
Keyboard,
|
|
6
|
+
Pressable,
|
|
7
|
+
Modal as RNBuiltInModal,
|
|
8
|
+
StyleProp,
|
|
9
|
+
View,
|
|
10
|
+
ViewStyle,
|
|
11
|
+
} from 'react-native';
|
|
5
12
|
import RNModal from 'react-native-modal';
|
|
6
13
|
|
|
7
14
|
import CONFIG from '@/config';
|
|
@@ -35,7 +42,12 @@ function IOSModal(props: ModalProps) {
|
|
|
35
42
|
onBackButtonPress={onBackButtonPress}
|
|
36
43
|
onBackdropPress={onBackdropPress}
|
|
37
44
|
>
|
|
38
|
-
|
|
45
|
+
<>
|
|
46
|
+
<Pressable style={tw`absolute h-full w-full`} onPress={onBackdropPress}>
|
|
47
|
+
<View style={tw`h-full w-full bg-black/60`} />
|
|
48
|
+
</Pressable>
|
|
49
|
+
<BottomSheetModalProvider>{children}</BottomSheetModalProvider>
|
|
50
|
+
</>
|
|
39
51
|
</RNModal>
|
|
40
52
|
);
|
|
41
53
|
}
|
|
@@ -52,11 +64,12 @@ function AndroidModal(props: ModalProps) {
|
|
|
52
64
|
visible={isVisible}
|
|
53
65
|
onRequestClose={onBackButtonPress}
|
|
54
66
|
>
|
|
55
|
-
|
|
56
|
-
<Pressable style={tw`
|
|
57
|
-
<
|
|
67
|
+
<>
|
|
68
|
+
<Pressable style={tw`absolute h-full w-full`} onPress={onBackdropPress}>
|
|
69
|
+
<View style={tw`h-full w-full bg-black/60`} />
|
|
58
70
|
</Pressable>
|
|
59
|
-
|
|
71
|
+
<BottomSheetModalProvider>{children}</BottomSheetModalProvider>
|
|
72
|
+
</>
|
|
60
73
|
</RNBuiltInModal>
|
|
61
74
|
);
|
|
62
75
|
}
|
package/templates/shared/apps/mobile/src/components/atoms/Typography/typography.component.tsx
CHANGED
|
@@ -16,7 +16,7 @@ export function Typography(props: Props): JSX.Element {
|
|
|
16
16
|
return (
|
|
17
17
|
<RNText
|
|
18
18
|
{...shouldTruncateTextProps}
|
|
19
|
-
style={[tw`
|
|
19
|
+
style={[tw`font-sans text-base font-normal text-black`, style]}
|
|
20
20
|
{...extraProps}
|
|
21
21
|
/>
|
|
22
22
|
);
|
|
@@ -39,7 +39,7 @@ export function ScreenHeader(props: Props) {
|
|
|
39
39
|
{extraActionComponent ? (
|
|
40
40
|
extraActionComponent
|
|
41
41
|
) : (
|
|
42
|
-
<GearIcon height={25} style={tw`text-black
|
|
42
|
+
<GearIcon height={25} style={tw`text-black`} width={25} />
|
|
43
43
|
)}
|
|
44
44
|
</View>
|
|
45
45
|
</TouchableOpacity>
|
|
@@ -34,6 +34,10 @@ rm -rf "$app_rn_node_modules_path"
|
|
|
34
34
|
echo "Deleting $app_rn_ios_pods_path..."
|
|
35
35
|
rm -rf "$app_rn_ios_pods_path"
|
|
36
36
|
|
|
37
|
+
app_rn_ios_pods_checksum="apps/$app_rn_name/ios/.pods-checksum"
|
|
38
|
+
echo "Deleting $app_rn_ios_pods_checksum..."
|
|
39
|
+
rm -f "$app_rn_ios_pods_checksum"
|
|
40
|
+
|
|
37
41
|
echo "Deleting $app_rn_ios_build_path..."
|
|
38
42
|
rm -rf "$app_rn_ios_build_path"
|
|
39
43
|
|