From 91aa32161befb3099ca7b8904f182a0ca52421c8 Mon Sep 17 00:00:00 2001 From: Rares Matei Date: Wed, 5 Jul 2023 13:29:35 +0100 Subject: [PATCH 001/262] docs(nx-cloud): ami deplopyment docs (#17865) --- docs/generated/manifests/cloud.json | 64 ++-- docs/generated/manifests/menus.json | 50 +-- docs/map.json | 19 +- docs/nx-cloud/private/ami-setup.md | 170 ++++++++++ docs/nx-cloud/private/get-started.md | 63 +++- .../private/images/nx-cloud-landing.png | Bin 0 -> 130714 bytes docs/nx-cloud/private/kubernetes-setup.md | 282 ---------------- docs/nx-cloud/private/standalone.md | 315 ------------------ docs/shared/reference/sitemap.md | 5 +- .../src/e2e/nx-cloud-documentation.cy.ts | 6 +- nx-dev/nx-dev/redirect-rules.js | 3 + 11 files changed, 277 insertions(+), 700 deletions(-) create mode 100644 docs/nx-cloud/private/ami-setup.md create mode 100644 docs/nx-cloud/private/images/nx-cloud-landing.png delete mode 100644 docs/nx-cloud/private/kubernetes-setup.md delete mode 100644 docs/nx-cloud/private/standalone.md diff --git a/docs/generated/manifests/cloud.json b/docs/generated/manifests/cloud.json index 7640ebc9a28cb..2c4a81f9ef7ce 100644 --- a/docs/generated/manifests/cloud.json +++ b/docs/generated/manifests/cloud.json @@ -234,8 +234,8 @@ }, "/nx-cloud/private-cloud": { "id": "private-cloud", - "name": "On Prem", - "description": "Learn about Nx Cloud On Premise, dedicated Nx Cloud application hosted on your server, in your network with total private access.", + "name": "Enterprise + On Prem", + "description": "Learn about Nx Cloud Enterprise + On-Prem.", "file": "", "itemList": [ { @@ -268,6 +268,16 @@ "path": "/nx-cloud/private-cloud/auth-github", "tags": [] }, + { + "id": "ami-setup", + "name": "On-Prem VM Setup", + "description": "", + "file": "nx-cloud/private/ami-setup", + "itemList": [], + "isExternal": false, + "path": "/nx-cloud/private-cloud/ami-setup", + "tags": [] + }, { "id": "auth-gitlab", "name": "Authenticate with GitLab", @@ -307,26 +317,6 @@ "isExternal": false, "path": "/nx-cloud/private-cloud/advanced-config", "tags": [] - }, - { - "id": "kubernetes-setup", - "name": "Kubernetes Setup", - "description": "", - "file": "nx-cloud/private/kubernetes-setup", - "itemList": [], - "isExternal": false, - "path": "/nx-cloud/private-cloud/kubernetes-setup", - "tags": [] - }, - { - "id": "standalone", - "name": "Standalone", - "description": "", - "file": "nx-cloud/private/standalone", - "itemList": [], - "isExternal": false, - "path": "/nx-cloud/private-cloud/standalone", - "tags": [] } ], "isExternal": false, @@ -363,6 +353,16 @@ "path": "/nx-cloud/private-cloud/auth-github", "tags": [] }, + "/nx-cloud/private-cloud/ami-setup": { + "id": "ami-setup", + "name": "On-Prem VM Setup", + "description": "", + "file": "nx-cloud/private/ami-setup", + "itemList": [], + "isExternal": false, + "path": "/nx-cloud/private-cloud/ami-setup", + "tags": [] + }, "/nx-cloud/private-cloud/auth-gitlab": { "id": "auth-gitlab", "name": "Authenticate with GitLab", @@ -403,26 +403,6 @@ "path": "/nx-cloud/private-cloud/advanced-config", "tags": [] }, - "/nx-cloud/private-cloud/kubernetes-setup": { - "id": "kubernetes-setup", - "name": "Kubernetes Setup", - "description": "", - "file": "nx-cloud/private/kubernetes-setup", - "itemList": [], - "isExternal": false, - "path": "/nx-cloud/private-cloud/kubernetes-setup", - "tags": [] - }, - "/nx-cloud/private-cloud/standalone": { - "id": "standalone", - "name": "Standalone", - "description": "", - "file": "nx-cloud/private/standalone", - "itemList": [], - "isExternal": false, - "path": "/nx-cloud/private-cloud/standalone", - "tags": [] - }, "/nx-cloud/reference": { "id": "reference", "name": "Reference", diff --git a/docs/generated/manifests/menus.json b/docs/generated/manifests/menus.json index ccf379a5e7492..1aef7726d7df3 100644 --- a/docs/generated/manifests/menus.json +++ b/docs/generated/manifests/menus.json @@ -3960,7 +3960,7 @@ "disableCollapsible": false }, { - "name": "On Prem", + "name": "Enterprise + On Prem", "path": "/nx-cloud/private-cloud", "id": "private-cloud", "isExternal": false, @@ -3989,6 +3989,14 @@ "children": [], "disableCollapsible": false }, + { + "name": "On-Prem VM Setup", + "path": "/nx-cloud/private-cloud/ami-setup", + "id": "ami-setup", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, { "name": "Authenticate with GitLab", "path": "/nx-cloud/private-cloud/auth-gitlab", @@ -4020,22 +4028,6 @@ "isExternal": false, "children": [], "disableCollapsible": false - }, - { - "name": "Kubernetes Setup", - "path": "/nx-cloud/private-cloud/kubernetes-setup", - "id": "kubernetes-setup", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Standalone", - "path": "/nx-cloud/private-cloud/standalone", - "id": "standalone", - "isExternal": false, - "children": [], - "disableCollapsible": false } ], "disableCollapsible": false @@ -4064,6 +4056,14 @@ "children": [], "disableCollapsible": false }, + { + "name": "On-Prem VM Setup", + "path": "/nx-cloud/private-cloud/ami-setup", + "id": "ami-setup", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, { "name": "Authenticate with GitLab", "path": "/nx-cloud/private-cloud/auth-gitlab", @@ -4096,22 +4096,6 @@ "children": [], "disableCollapsible": false }, - { - "name": "Kubernetes Setup", - "path": "/nx-cloud/private-cloud/kubernetes-setup", - "id": "kubernetes-setup", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Standalone", - "path": "/nx-cloud/private-cloud/standalone", - "id": "standalone", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, { "name": "Reference", "path": "/nx-cloud/reference", diff --git a/docs/map.json b/docs/map.json index b3b6ccb843e72..fe9595f79b3b8 100644 --- a/docs/map.json +++ b/docs/map.json @@ -1540,9 +1540,9 @@ ] }, { - "name": "On Prem", + "name": "Enterprise + On Prem", "id": "private-cloud", - "description": "Learn about Nx Cloud On Premise, dedicated Nx Cloud application hosted on your server, in your network with total private access.", + "description": "Learn about Nx Cloud Enterprise + On-Prem.", "itemList": [ { "name": "Get Started", @@ -1559,6 +1559,11 @@ "id": "auth-github", "file": "nx-cloud/private/auth-github" }, + { + "name": "On-Prem VM Setup", + "id": "ami-setup", + "file": "nx-cloud/private/ami-setup" + }, { "name": "Authenticate with GitLab", "id": "auth-gitlab", @@ -1578,16 +1583,6 @@ "name": "Advanced Configuration", "id": "advanced-config", "file": "nx-cloud/private/advanced-config" - }, - { - "name": "Kubernetes Setup", - "id": "kubernetes-setup", - "file": "nx-cloud/private/kubernetes-setup" - }, - { - "name": "Standalone", - "id": "standalone", - "file": "nx-cloud/private/standalone" } ] }, diff --git a/docs/nx-cloud/private/ami-setup.md b/docs/nx-cloud/private/ami-setup.md new file mode 100644 index 0000000000000..a52939dbfcf43 --- /dev/null +++ b/docs/nx-cloud/private/ami-setup.md @@ -0,0 +1,170 @@ +# Setting up a dedicated NxCloud VM + +## AWS EC2 + +1. Login to your AWS Console and select [the top image published here](https://console.aws.amazon.com/ec2/v2/home?home#Images:visibility=public-images;imageName=nx-cloud;owner=623002322076;sort=desc:imageName) +2. Launch a new instance from that AMI +3. Recommended instance type: `t3.2xlarge` +4. You will need to SSH into the instance once it's created: + - Use an existing SSH key-pair that you already have installed locally. + - [Or create a new one and download the keys locally](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html?icmpid=docs_ec2_console#having-ec2-create-your-key-pair) + - Then select your new SSH pair from the list +5. Networking: + - Allow the instance to receive HTTP and HTTPS traffic + - Allow SSH from your current IP +6. Leave the storage options as they are +7. "Launch instance" +8. Wait 10 minutes, then navigate to your instance's IP in the browser. You should see the NxCloud dashboard! + +![NxCloud landing page](/nx-cloud/private/images/nx-cloud-landing.png) + +### Your NxCloud URL + +1. At this point, your instance will have a public IP accessible from the browser. + - You can consider this IP the URL of NxCloud, and proceed with the below steps and all will work fine! +2. You might want, however, to add a Load Balancer in front of the instance, with an explicit domain (e.g. https://my-nxcloud.my-org.com). + - This is strongly recommended because you will be able to upgrade/restart/re-configure your NxCloud EC2 instance while keeping the NxCloud URL static. + - Create an [application load balancer](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-application-load-balancer.html) + - You will need to create a certificate for your domain to assign to the LB + - And you will need to target your EC2 instance from the LB + - You should now have a permanent domain pointing to your NxCloud instance + +Once you have your NxCloud URL proceed to the below steps! + +### Configuring your NxCloud instance + +1. Create a new `myconfiguration.yaml` file with the below contents + +```yaml +# This is all you need to get the baseline of your nx-cloud instance configured! + +# Set the external URL your instance is running on. This is the URL from the previous step +nxCloudAppURL: 'https://nx-cloud.on.my-domain.ca' + +secret: + # set your initial admin password for logging into the app + adminPassword: 'correcthorsebatterystaple' +``` + +2. Apply the configuration: + +```bash +scp -r ./myconfiguration.yaml nx-cloud@:~/config/user/update.yaml +``` + +That's it! After a few minutes, you should be able to log-in with: + +- username: `admin` +- password: `` + +### Applying the license + +Once you log-in, you will see an organisation has been created for you. + +1. You can rename it or create a new organization. +2. Navigate to your new organization's page and send us it's id + - It should look something like this: https://your-url.com/orgs/649f240f7fb955000c1fd10b/workspaces +3. We will then give you a License Key which you can apply on your org's billing page + +### Connecting to your NxCloud instance + +In your Nx workspace, you can enable NxCloud by running: + +```bash +NX_CLOUD_API="https://nx-cloud.on.my-domain.ca" npx nx connect +``` + +If it doesn't work, there might be an issue with unrecognized certificates on your instance. You can try running with: + +```bash +NODE_TLS_REJECT_UNAUTHORIZED=0 NX_CLOUD_API="https://nx-cloud.on.my-domain.ca" npx nx connect +``` + +Although we have [a full guide here](https://github.com/nrwl/nx-cloud-helm/blob/main/PROXY-GUIDE.md#nxcloud-runner-proxy-issues) for dealing with self-signed certificates. + +### Advanced configuration and auth + +You can optionally enable authentication using your preferred SSO provider: + +- GitHub +- Bitbucket +- GitLab +- SAML (Okta, Azure AD etc.) + +```yaml +# This is all you need to get the baseline of your nx-cloud instance configured! + +# only use this if you'd like to use any of the newer NxCloud version from here: https://nx.dev/nx-cloud/reference/release-notes#docker-containers +# global.imageTag: '' + +# Set the external URL your instance is running on +nxCloudAppURL: 'https://nx-cloud.on.my-domain.ca' + +# Uncomment (along with github secrets below) to enable working with GitHub pull requests or github auth +#github: +# auth: +# enabled: false +# pr: +# apiUrl: '' # this is only needed if you have a self-hosted github instance + +#gitlab: +# apiUrl: '' # this is only needed if you have a self-hosted gitlab instance +# auth: +# enabled: false + +# we do not support self-hosted bitbucket instances +#bitbucket: +# auth: +# enabled: false + +#saml: +# auth: +# enabled: false + +# Provide plaintext values for your application to use. We will extract them, +# store them within the application runtime, and scrub the plaintext ones from +# the filesystem +secret: + # set your initial admin password for logging into the app + # see here: https://nx.dev/nx-cloud/private-cloud/auth-single-admin + adminPassword: 'correcthorsebatterystaple' + + # If you want to enable GitHub Login, just provide your client id & secret, we handle the rest + # see here: https://nx.dev/nx-cloud/private-cloud/auth-github + githubAuthClientId: 'my_client_id' + githubAuthClientSecret: 'my_client_secret' + + # The same goes for GitLab authentication + # see here: https://nx.dev/nx-cloud/private-cloud/auth-gitlab + # gitlabAppId: 'my_gitlab_app_id' + # gitlabAppSecret: 'my_gitlab_app_secret' + + # Bitbucket too! If these are uncommented, BB auth is automatically enabled + # see here: https://nx.dev/nx-cloud/private-cloud/auth-bitbucket + # bitbucketAppId: 'bitbucket_app_id' + # bitbucketAppSecret: 'bitbucket_app_secret' + + # SAML auth + # see here: https://nx.dev/nx-cloud/private-cloud/auth-saml + # samlEntryPoint: 'your_saml_entry_point' + # samlCert: 'saml_cert' +``` + +### Upgrades + +We send out emails with every new NxCloud release to all our Enterprise customers: + +1. You can view your current version at the `/version` route: https://your-nx-cloud-url.com/version +2. [And these are the latest NxCloud releases](https://nx.dev/nx-cloud/reference/release-notes#docker-containers) + +To upgrade to a newer version, add the below line to your `myconfiguration.yml` file: + +```yaml +global.imageTag: '2306.01.2' # set the version of nx-cloud you'd like +``` + +And apply the changes: + +```bash +scp -r ./myconfiguration.yaml nx-cloud@:~/config/user/update.yaml +``` diff --git a/docs/nx-cloud/private/get-started.md b/docs/nx-cloud/private/get-started.md index 5348dfb5be42c..f24f788548710 100644 --- a/docs/nx-cloud/private/get-started.md +++ b/docs/nx-cloud/private/get-started.md @@ -1,23 +1,62 @@ -# Running Nx Cloud on Prem +# Running Nx Cloud Enterprise -Nx Cloud can be deployed to your cloud, which gives you full control of your data, with no external API calls. +We offer multiple ways of running NxCloud for our Enterprise customers. The below options are listed in recommended order, from easiest to most complex in +terms of set-up and maintenance for your team. Please carefully consider your organization's requirements and level of infrastructure expertise before deciding on +a deployment option. -This solution is included as part of the Nx Enterprise package. You can learn more about it at [nx.app/enterprise](https://nx.app/enterprise). +Also, please make sure to [get in touch with us first](https://nx.app/enterprise?utm_source=nx.dev) so we can start creating an Enterprise package +that best fits your needs, and discuss any questions you might have! -Nx Cloud can be deployed in two ways: +## Clusters managed by us -- Using Kubernetes (several containers working together) -- Using a single standalone container (NOT RECOMMENDED) +### Multi-tenant -The flags and the capabilities are the same between the two, but the Kubernetes setup is more robust and better -documented. +The quickest way and easiest way to get up and running with NxCloud is using one of our existing secure, multi-tenant managed clusters: + +- https://nx.app/ +- Or, if you'd like all of your data to be hosted in Europe, you can use https://eu.nx.app/ + +You get the same level of security, dedicated support, SSO/SAML auth options and predictable seat-based pricing as all our other hosting options, but you won't have +to manage the instance yourself. + +We also offer an uptime SLA guarantee of 99.98% for our Enterprise customers, SOC certificates on request, and we're happy to meet with your security teams if they +have questions, or fill in security questionnaires. We also maintain a [Status Page here](https://status.nx.app/). + +To start with this option, it's as easy as running `npx nx connect` in your Nx workspace! + +### Single-tenant instance + +If you have very specific requirements, then we can also offer to host NxCloud for you in an isolated/single-tenant cluster. + +We'll be able to discuss specific requirements such as: + +- Specific regions you want your data to be in +- Network isolation / dedicated VPCs +- Dedicated instances +- Storage encryption +- Storage replication / redundancy + +This would be a "best of both worlds" option, as it would free you up from managing the instance yourself, but you will get to define specific parameters of how it should it run. +Your data and the NxCloud will run in complete isolation and will only serve your company. There will be no external API calls to any services outside of the cluster we set-up for you. + +Once you let us know you'd like this option, depending on the agreed requirements, it might take a few days to get it set up. + +## On-prem, managed by your organization + +#### Self-contained VM + +If you would like to host NxCloud yourself, within your organization's infrastructure, the easiest way to set it up is as a self-contained VM. + +Refer to our ["Self-contained VM" guide](/nx-cloud/private-cloud/ami-setup) for instructions on running NxCloud on Amazon EC2. + +#### Multi-node setup with Kubernetes + +The options above remove most of the maintenance burden required on your part, so we strongly recommend them! They also don't require too much infrastructure expertise. + +We do offer, however, a multi-node Kubernetes setup, that is deployed via Helm. You can head over to our [Helm repository](https://github.com/nrwl/nx-cloud-helm/) to explore this option. ## Resources -- [Kubernetes Setup Instructions](/nx-cloud/private-cloud/kubernetes-setup) -- [Nx Cloud K8s Example + All Config Options](https://github.com/nrwl/nx-cloud-helm) -- [Nx Cloud K8s Example + All Config Options (no Helm)](https://github.com/nrwl/nx-cloud-helm/tree/main/no-helm) -- [Standalone Container](/nx-cloud/private-cloud/standalone) - [GitHub PR Integration](/nx-cloud/set-up/github) - [Auth (Basic)](/nx-cloud/private-cloud/auth-single-admin) - [GitHub Auth](/nx-cloud/private-cloud/auth-github) diff --git a/docs/nx-cloud/private/images/nx-cloud-landing.png b/docs/nx-cloud/private/images/nx-cloud-landing.png new file mode 100644 index 0000000000000000000000000000000000000000..f5d3d9dcc0e43bb7f7f68f1f48858f2fb779701f GIT binary patch literal 130714 zcmeFabyQVb_dZU85)#tVAkrZreWa0;?vU>8R_T(KM(LLBP((VUyE~;Dew!Qbm2=UdX*i0V+LNp*+30_&Q9V=Na;vLB7gZRDrd;Rx_Dc)j% zT(G0x!5~n41IZM}3c-%hV}1INM|xi|9#&|RHn5%nOFqiJSX*g2-K+4tGylfRsrS*i@2X z42QRd`^wfQ0#huX5`Owd>S%`LsUIsx;-(I5N>EqSYZ#x8Zast7rH`&B?(b0uFy(8@ zwWIm9h^-)PI6Sp{_4Z*NXp*ukIM7!aWBvhDau?C7s0gxq;!)>mzLWe|`M7=FqXDh= z0=-62=TUV$xhMB+;WlSKOD6(uMiewW`v$Exm&VX4!rL{hBrcN7Lpm=`Lc z%2-Nx8x7StNzH~d2TVf|iEs7%sZiA(B1U{9R`eMyW@O;ypL<$E?uW^`NEY)| zY`@a$SttV%a@2-yi^}}FXFi@P&*%Ewin}?W9HO9h7&^odB1hm&S8Vi7o2#{BPxuYy z-=Q=zQrH;Lb9=~qa@!t#+Q7)9`COc#lffxO)JxsO4m7l(O2I9W zfwQlpHWpMqetZw(oa`hzgUGR(W`GML35tH_Z5~HYO&cg zz%0t@nJT&y67FZdkG9$iU)=U}B9E?JJ^U|w7)da4w8;g~)=UJFziPiiWeUdOFKa=z z;+upId)o>zs%{0h&B_wCbM=<;E&UgPFRc9RbHgy7)pw;;LLsMQ_yk`DbrG3*t38)= za4G~J)u=h=TXf#gwzf1j@e1D9eW0=kWjFHF8% z&YnmyeE6*Otj)IjQ6al&)ym3AK2dJ(n-%{Qo?@R-$W0^%C@w#O&v=jorY-TGP&Tt4 zJ}4?|Eg52cNGBB|O*n{lK{nl&6s=g&mouC*vKCZV=rimas5#0bx3#Y^7=ec}ayiuC0Yh5ZfuBDc z0r|U#1giK~LhI)^{zT}(f~3}>)Dhl#Wc-4!B}A4tHIgD*BZ-ox8zqd^`IT_6#j+&TbO2aF&r9 zZDl_4N8HIPH=YIz%chB4niJ?cqHEz)bfkMnFqTjW@A%suOFWK3r$(5#=ZBCrTRJG< zBtnjE?>{UkeL|awZW}P*9~6M^fB1FbEB!p#JVbzCKjm1Yo7i`9lpKHg7pfxTk|q=y zj}PDRKB1zCds6+x=Sc?Dz363Xg(q9GoSAkiYdQUfC7fdso06fA_uJ&!#oH&^=oW(( z3HJ;G;acM7#l=z=WtU}!W!Il%J#nP6jEau#j;fE+jfU+gjUJ)iQQ*zH0G*}J=|c_mTd?u#B|qjvQZhzdV7$ST6UFN^W#6a&D}G zR&MwZ?a+IZg`pRN)PpG58uA-*lzD17rGp&nPlsrR5{4|Z9~kwqB(i>Fz0ZPWy4n9M zYgZyN-8cg`zkMLFs9Iq^eVGhT_-R(Lk@`6IINLatY8ckbPSv1-=sbnOa*;f_JS{c3 z2}v$7*FcAiqnBG21QM+;{0btAO63h3d+d{>YlLegG#a)^r#PoNYjzHWS7BFo4?7Ol z4-41a`?EISH&)gdMl1ZZM3alhh8u#Fm7b);Ip9Y#n&n?%zmI|{2Z_s1K@{e~;` zbkby0=b5&i*+Ua@W>rJG{_I}m)@M!6Mx3H|nHDrL;sa6wn)IT@^4e`{*pkG0vx+h* z2hJstC7UHEGSwuwB>56l5-8%kS@YOy4W*b2-y6miF=a4DJ?w6uqM9*I7$7i|T(MfI?xE``(%4k5qK~Fm(#Ruw9H2;WP?OMA}3 z<)VL3kF)V!jLA$NXaUrucDIlvw+J6S~nx2GF$M{QY}WonCWa8;r$W)6#!CdUq+HO}T zX&8f#tsXyWBi17~-0V2{60j_93&%Vbrx16kj^&7a49nnE8935;yi_#H*S*)R8h%JS z!S1T>U>WKuB_x&NMWM{#6pbHKOLgq7X*V5O_xWP+;tVR|b?|G051EY8qrBgp=A!~M zNL^p%WV=Qjrw>J*wV=&!`H0R{eaR%HJ0Y7PDGt9Nb(YywQdhaqvFTrgmSf38$g-0t zPpC0kABcDtF_SqrP&F`~nIM(&^zt*(axmS~@VL0A69#d;@qBrP4y&6Ys^zLu)7KX_8Gg?6IpP2OrAMeRXqfIy@f!`7*0#Ln z%PV~*$K6w{Bu|a=joFBNiX?HK7z=e_^~dTC?$y_ONi-~qQTa|~HeDUQ3I_`MdDDf- zpU%{M)LJrGqgW$Yr%cI4*a}LOE6t{24>>l96yOwxm2eg5a$Op|E9dsUd4<>~1hYk3 zo|UP5I$e(GqeC829Kuu!Pz$Q$9g8X3>aq-;F}bmonJargE0N=#s-!K}WLDN%BuBae zAybO-`q}|Ut#OR9tel1tmS^j*rUpGp3KMc7drVQl~Ho*>8xcmIe ziMJJ8lyXv<=3(YL+?dwun``d|D0>-u%aRXyTo)6MtC#nK_d~F`=~?Wm93P!cT^R)$K7Q$$7xJSDmeksp3)fmAjnyCx-NIQSLvs|inTB$ij z-*9=_vswGLR{wZ#M`4n^PV3Tdi|BBQa7u&-hG*3Y=lVwv*>)Os7$TA9THN*9v-J6# z_JMdq`rgn3-vdn--XrH;#P319?irpY7b=JS%S)ddp{~|frPp?xDLhzDTz2s<*}0}` z>do=}ajUKiXQx(<^@$GnHZR&voR;PGva(VrJxSbE&WDanJ1hMy9pMq-;DsJBi5$^* zefBlbhy39J4>2eYVPxegj7u|f-HsH#qoR*+K}kD9*3kv+#d&f~I01icVFB^U5r5L- zxqG=C#H(xwawo{aA^R%its%Yh7ddEiyxO*1BVDg0eppI0tXz=nr1XMv*Wo;PuMri> z-Bfi!97n)@009Gu2LTJbf&{*KA@Tq7S{U*P1oUs$p&%gqj3HqD zxJL^3ee?AW_`YfL`)}w7UkG^MFLdDBDHZC^yAgs@q5pgha|OHy@mx+oObqxfr)#6H zZ((a>X=k@tPYGPOXCbudyt19Lqy(p~r8&Khp5-fjdM9(M zo994qJ8=Rp&Gqech@H&MENnTQcu0S{gA;gtbD4pZ__tf^OnFF^C1r>OEN%3O+2|SR z8A*BX6B842+vpi^$_fhq(H!`Tht$Z<&We+P!O_u?-tj5DrHvs269)$e10yp7Gcz4< z2c506g`JKQorNvg?+^L&IfDAOx;DmEcE*+##5d2?d1YyD$3seb)6svvejlg4lks0Y zS=jzDEntESH}5bo(K9mq=h;A0?whNeGR98&W-5Zl=77wAK6sg!*`IO$*5Ge%{nh19 zO_l#@%FOiaR@0x}0&l8dt8XJeyuJ?cHl*5zfB->=2|ky1g4~=c zw!~L+fS(;>8+E~+fJKlke%A!Qh)IQBM=CiEZ*R)wrGOx&3yGK>nCb~CM8~wzsl5lP zY6Bc}3t9T>ZfGpEbg@{2aEFEPSZ1*Y&IWC`HcrbJvm!RzNnFQnhMLFCT?|(Tr$s+R zydWT|GzKaTu5xp<_&<02 zXK$!D)(`&Y2!Fp3?lCbV^Cw@L*t@4h%s5Z@zoz_0&qxv=Z9Q#dCHgyM1OjP)<@s~G z|KrIx@4cGZn(zwM?-Dx5%d5%X^={b^GcrPYhkLWCSKpz zmCe1og$_lweYb49nwnr>gyDv*meBu)X#RK$MtBnX?x}ct-vc0-KiBauAPE2x{udzs zK~4V$KsL=nkqw-ySRY&Ljh?PG=VLoIo#@F&U3WC@V;k0wMoQid7iU;FOq^;bdxZlE z@{;Wsm(xuNBRzu9g*z1vqJesIFWBw6Ijq2I%QRe?h;MU4wou?s`#_S=M)eM_t&E)S zK4&QUz!7s5QAwOU@+VN%s1C#(ur@#r7)@|U6fc=C>y(Pno& z_dRb{^7!T2f?w8-`?)Ny@#6g6y0ID*ne@YkyCqL|KmEaP@)K8gM+uI?=c%})pF4Yg zrvM-Mcr}Ukj*~O?m->#P+%;IyC&a*wnfHSa@<}T0)DAk}D-Kd~08H%;tauLiFggW-&jp0RV~fP^A*tJKUZ*6yq<+{R1CQ0Nt9=R4zDU7ZtL> z2`zUb26s`o-AzsA0OgcXsMscPN@J?1ztGlu*?jjfQ;`9BW_yUA|MIwu{F|jIw!#WiS3e^Ehl%}#LI+e-oH59v_MC(-qzoxZ zm@5oDgt6yWenhb`m^do)Ki=Hw28^DAw9{d~a*F4}J@2sXpbSjpbOm6k=JxN7n5jR^qmfRHM9Nqq){k=+f{6Qk0l?u0e#UF$xz^a--?{$8V!F%9 z5(EuJ7KGPuw{|rU5Q6PK)RZinAS@DH&+P9t8Hq- z@L~8%NB`iGKq7$mCHUMETkpz6HC>m|<;m+|;nE%4)P^2Sba!j`o7SoH^i+%`*>hZX z&a@96fM;m!kBR*mOup-@2hvKX-9?@X7bBimtphtl49Sco)bs3jKc)hZ*ThGfjRH6j zjIg5D#oZ7+q6g4H;ykorq{+)g)1#GGP`_@{v^dcEz;p%gP8)_nFe4*oED2HVwpDB< zS~C7a%nm+7wlKoOvbc9YpyDB5BIxv-<_TFrQKt8U1xvo&ZI>FbFv1R)>KvXfd^DQZ z=M(cQGuJx$=}$h6e2=0;2zF~;zSFRX`$_;=1*IxTW5zLPQPRrxVB*9Do!%|58gyX5 z{1tA2Z5KP+Q|TuQMAt=o0i^pJ_RXYAZr(S3e-Z|&h7eE~SX0s(P@739l!^5Zene@n) zhgz5V)~CJK^1;#~;;kDOs5m)kdUtvl;!i<91dUh!SSNhu;!LT9!SfWmW#)2g=HZMx zN`M*0!#GQUe?O>neg`?_bT=1K{Lk+KJ9!BK1E*Ygb~oH(fH4Fv{!Y$%ORKRde~>J7 z>p15V#{QUe`+uT1`A5w;UU~`cS8{ia1mIj zBlUsHfXN`1)?89E_7@Zl-QDn`C=redviIb)x)Lvy9sp!|`l5zv%A;Mp_){UJV;SDD z#iPSRw^7PF#Q;jh^!^MhJPZrU)f6eUu%Ow)49efunHeb>jS#q-s`$MRyu*jG9HMyg z@4w3D4bYpaqu=(n2?K(wDz3B32YiH*x~-IH^T4#fZ;lAxEy4wK90~1ov(BlBcJ?CoHMLr9m2^vj zVxqf(mUq(HGTz}O?)paQ7YV#wgx5S*&wh9U&Na$&rMEY5cP(}YembJ_ZYLK23x|y( zHYuKgb~n+P0Ab7EE9QW|p!ZLTeJ29aCYNSVxZAa(W>XL|$_BNQ-!)^97l;s`9PWDg zd;iqyU%^Z&U{<1Zk0b9=9WWDT0R4LhvJ`is48mI#u(R^_5~P3i^G}h>A{r`A`+#`# z-O)76FQNVt>Mx}Jzh?d?EuPoC*H={19MmLt(*>$OKtiM>cPB3(y!D_o#Uk@Rbo`5_ z3IcQ${?7Ve5Gyl4ta``_cZW-mOq_ASEp}EVJ}4_@5Mzy=dFrks^pV z4iHm`FSXy@azX`UFUWuQDg+X$9ROYgt31cQ@P49z?9rK}{>kP2HC0g{dmix%qIat4 z|6=sNAo>fUcUayp7X8Jdf06KiUCn`hIr?9Y{tk>lc>i+rzhcolqV`|0=&$9{ol6GL zujSIO<q?o6iqN;>_@i{7~}_$x2^D|LStll)5E|4QB8 zg^^#oOaH&yU2=c;e!4fX)-f`xK$6Hndd8h9aJPLmT<6O9Y90v@+%u%g0lRKe&U9eA zS-x~u#}2Y}&eyC@n9V{Ah8o=*6cIvMo<2viXV=$Wr7^G4MH`pMx)4V>l2`4MU`3S4(lp%nL=7$P!{=^(?a0r{U z#Iz+(b+%wFEDM8n*Rqe?F#cBCqyTI;D^Q1m*Aa!lG+fWM3hzr!OU?rIWwms(X5a(* z0knM62n%sLGwD4A6VI)o=f+Iklak`h|Ly+ifrsM7!RbuGab$G(dWxo`+}8XPu;I&S z0R^)S(Q#l)3Xl&dDJuveP`;^vL!RAhfr`u&g5WXOEdQYrCmTH*!{P@^Fm-izE4`)$ z=78VWH!+|}GV_y|lGTy{vEO*q)Gx@ zcz8guG)oh6G#Emau~3bakBrW-XDWmWz>kP^0X49HFJkxp1_gy2(vFwZREZYb{|J0gp)eXFsA^t{<-)z43s_CWO}@1w|=g;f!rsMuAO78E_jV)8D{37ZnhCKKwc- zt*oYswqAWB8aV1o0RS5irGbgO3GQYTiEEenRaJGlg!$HXZpK z@c9Wih@l4^O7dTxE?V9TlvI=6ca=|4ffEAw7IR^M!5ghX;lN`IujnSmc%zL6A0q+lXv&VRIIP&%?^Jo>=@A% zrRV6`f*VLS3EX4TGt<|<(4P^2;9w%1CG>K;5*)J zQEI0G^r3}6rn=Piq-^yN|)g00na{# zzMq^{wy?`_*J3{j3~feo01-$^n%?%vH|HH$+>D*3n%cIy?U{H9h8o0AhBKMN!CT)P zz(Vb^1C#V@9x!L@ptcW*LkDZ5OB~;8G{xkoPr>C}0TjTF33r1RZ8W8MfdpPk{B{&Z z!AXS0y+*W}c;?*@3|KGP;sCVi<`RX$Y90_+qK-kp$l0W!(QtM>ac}E`xGx$ImQu+u z*ilYsR8*rUfxjQ!YyW0pxz8DI^Sl9H1sU9nZ~@rf^jZO9eMUP-Z#eJp57&ID9=FG7 zl@DmKb)4fIjLvv&!ZmCh;8Y(yaM0-+!NSD*u6wru;02NdrWh}id0RV>P&4-tSb*~% zu1e3qi>DvG0ce29uAT5U7C_PfI0NVBhZL9q)8FjN3L|0*Ey7={mHGx=`=_l0^r-=x zBz;?~aJ0mIz=7x439Yr;gPhF<9vxca&IZ;1ZPIvq&=9tAC!pZ2#8d`lU^n z@XhVPdNp|i#cU`rJ0-WT69ZxseT3tDx|#pX)4D>T)^EEOGakG&{GW=ub76c5jr`Xc zx?zNKw;#2F6N3Q2X^(243&8{ws!V)e!tLy2&OdLW?vS%6jY?^>MZ2vb;V=XobG3ly z+oWD~yNxVHZEq5IypQ9Z6R&^(*g{Lo(%nyRWRxPfq}Zy)f9U=awG;e z6P6pYq&DEa-I(|XIb#{9`L{zqjIOz!1F;%fB65X1EHjeH-@rBUPgLFX4hs1kB`Au$ z|D7BBAz$b#Fe`chfXAf|Mh&cRrj?rUEvOk-d8n&vvYLGVoibTDvrP6--SXBQg27mG zRTJP`S6wBrrx?SQz~gOCO9is;P==h1e9JRh#_rnYDjERi`%j*Lg>Z#! zUWG;AxE64D7w^#IcT})*8V)SxHzb&_fivYMZ~{Y*ucr`=7@$xRWzeC^O$WJ+(a&c19oeM zTAP8lh5g6}lyalffGA|Vl;FVq6~h8P6}{;T-qW7rMexN<8xS}|q=n^zO%xt&RUmZ^ z^?5jYEm9D`W!r=G4;qrNjKG<5_U4le;L{v+Zrg^{1(Y8O%S~*X`Jl93paIAiBsMF{X%Pa9Z5u=Mz#tdcjG$%>iR{m~Zi&((9lqsztFf~ZQ9uXK- z{eDW+PIbU-mziAlih%S9^GtJt`^v~6xS1{jE1mWkUCi5x^6r5-!Zli@re%KM8zs7Q zyd%{JBlOMlY7?pG+n4i$f?@(WaAUnGQ4fgE0So6oS$ey};yEA(bqSCx4e&2}x+A>p zIxg9^)oR!%+yO6@ey0Q!CRUSma+~GFXBF+YAXHj>(!=@pb>9h zb4{WB-(%a2JVUHwSF@SgBObN~=U{OP%s5asZrt1d0?g{Hpfup{D((dV2ko#I242SV z+N~wPiILpC%d1Hdn1Na`2e=D<0$YRhCq&2l#=ekhoDci5f`@yeRDgYy6a<1DZaPO> z1x^D3kzSmpKVWEY!vRLlPP1&__>w~F4waeOec`lNM3!7jC6!M-R3Dy(qF zs{~)p^@dP`Hfd}sji)18!zTCS2x?k+w->_RgHXSF(DLGMnbKdf@o|jt1jnk{ zlaYs++SEOJ$91@FOOH4MF!zoMYB0{*lunhZ`mjB~_;KVDt>Pgd%9a$WhFHi%AoKa^ zj1h68UD;E)>~FEADFBUvm#Sdgfh3nI)|Q48>gLEv{VnBM;c`eL&jKQ29nYOh(O0me zvF3TWjYZ~Jr_04{zJP=}2MA!Sv6=>q0PLXblbIt5SD`Tn4>0-Q$1^)`-v9~412kN7 zeq#nEwMTD2r%}NGKy*jfzwZDshRYU)YG}hV*xMluB$O*)A!GREh_?siJqcy6MH#8~ zVPd^5F!S%iCjrhwAmvP$fY}=XB0`8AJS}a1QbF`>vu{ELq8Q&%dsZ+lqQJft9&g3O zGM*U>ysa!U{(E+3sKeQwjV7#$bYp|!R zssdOw)!Dc`OR!=5Zm2GR>-tw8+(8UVH3bZ)(5C=Q5@6i_TQ93OXIgskUV(uhEGqmB z1m1;!N@}nwz+=O|@dz*gLqHcirv6*t=((-3-+HM5JmQ+_=-GdH3v9sN$pDJ})u)jl zp#Bmp%rC+ILhLUp_(cT(&;O!=|5vEs#PetyX4-cTdG-Y3BQga#saimUOw=ZYYT1i1 zN7D0#&ISXmlFk^ql85>{KHcHk z>2fpVa!%QAKp^&lfcp8zyEYgE95Fr0w^Pp{AYo8Jcm9}H^YRKm!OHabH#eh#h{Nxp zGDfsXA=JLP-7(lW{`2S8N(e}@T{?-&pGWzhcfp761tP^D)+P^6LUn-uSHnm3w}gZe zo>zN+hIaQ{0daT>J_a?3l5&x3qTG_(KaL1>1_~zlYbE0$*+1TL>x}>jK%RmQ{G$Z_ zQlJg62si4&GcT$XfaVbO6%v2J5W zu~sO4O5^*K_6Ul|1NIs6wSgI0_N?0P@1-b@CzC`9tC!=IC+OT(cyg{^sI?vvQL8Fr z^`y||$Y$Dg8R~4pa@uXvU}SaK1kWpPhp)5CDns6%GdeEHOf; zMtmOE{L3F0DpyykDxa+4MAl|EDXF8PTRUT;OEQRJB;uIi3~Rawo;iu$pS;c%zZZUF z9xvMJAgR&$4mYl;r=SLI`0 z{K8m|dd@&Nf~t%P0@wB^W82BV_s-|X7Evt5vaT^{UVPsCLYcvS1>_%a z)2o&Ky+j^Ysd4*tI!fteBvbq57D9vxqo_P~ajHb^ojn zT*w5+(G{bMpjOUVzb(_S&htrF-b=H{!JHY{&`TTc?2^q&!{~du@a>mAh%j`GlZFU5 z)swx%=QpJF707vz?Jm41_!%Oozz6FIzgqdG`t!wE0qy0@$_(cX3*Hx+v>!E!u<7lJ zCZj1U7ujC(mWjNxY`Bzan7#}_n=KYPy0&U^)UXUDd=gEgU`Ok@J;|YR-M&&{J3=TH zN1ZWgr>jbJGQ*VR6F%10;^~VOsBa;BU6$?}hk;M+Jy)yg>4OR1i zGpU}JW`g(s%gjJu5FT+IQ13`TQAFH4b19N9n(9)rBojd~ zi;Pmz+RD?sPl76WW0g5#8owcv4Aj&XZA;IA{*!?e!T@&^zAbHI`pJdALxAPIeibC2 zt=w(fn<@3^aj!h>j!KValjYRLNCVmF-n6ln0=;?_Dhm;(?T~_!54}y&$eCSRBGH2j zy$eTCkCWY0BVCzobq?|w4afJ*8+u*uKNp9NZi|}@56ro6U zto!zZ&w0CxqS|)l9YBNDlf6c?!QH&B1!?C?b`4UACvpv=bqXki+_dnXoaB7?pT*-W z>RY&_c!m=>EMiTI>L26zVP=!rX{9)2`Z5Lg$9lVE1w6m3eNjKI@Jf$^KrWcS0yax3 zDT2qfF|t`CwBv(-NOv!pNSN6AAiF3Q88MA`jD$^|HS)T(VVhN{dH1T6FW$2u!nI;! z0+00}8;^~vwLY|`vzu+ycea{{!)~E zEq=H_liYCy@d_o4=Gj)3sgT}ne|y7bRkQDW{z57QR5AAZO6{Dw{<1fQuz*JiRuGsa z!=&zvDd1AyNICe1>U=du38k-CaH>qLWd88IWBe11-1oGJTCWA!cddS-ayJ$9+hL%SScZWvo$7z;?p=G_{qAFGAn% z0a0{q$Xx8lXf|`@xjbt{*NHfuV}dwd+lGt7k(mZIt+`@mS-@HEt&&lE96#@=+O>QU zO9;(#{6V)iv%f(Squ1sLilT#e#W~Cw`T5~aBW1|BeMTLJZnD{E)tILHs4=o~wkgbk zeBnXaVp}q+S#@79;Ei36ybgBp%n^DpYH}AYM2I{e_tq^(LoG<8d zZS+nwtMF29>MX>YGd}>|qDs@_;t0`{ttSN!XD`Njs-f~#h@nihyRLrc!&u6W*yvbI zH&vEVI{LLRzN@Gf@tIhvf#tS}ty(vQjL!xNS{^+}R$VcyK}GgoFkh^05wSvbEH~Cm zWY%%C?yHuEegIv$$>s^`J0Hc}Z+L^qN=)PVp+pfgG$mY93)(Lj?Xs87hu4s_o~Ufw zs6jf0_8ep~V!2k)*|2|5U1r$oGP6YW6U_lIast*S^Av)-Ka=j)7ut*O+xJv=MtDXp z7n@rmMpgsJ`dJJn<>L%kqG~fpE^EbdA|Aj7(z4>2n>e$KPij?px&7Ey^R`cX+%Q?9 zkvnL#iR*<{vt25!^bXRUGXWBXDE~}UvvB%ZnP^`f+Y{5~5*{A4oKW4g!uqZgrZeb?!J4EKN*4s1x7k5H{NdUDqFBAQx3aESci$dhl^uWV;f z1dCQ3>$`^^mW6Ur{K4w@x6-W4ordd|+n(9{tLse5VMM#wWoa}H8yw09mpd`4ECrUE zS{tBn(QUsIrJZwpXh(ag1QPoIqE7ak!e3Ij)}h`biFTc zG8;S^|3FWmCYlfvQWq#h!G{M)X3BRVsOfatn9N8z#bmyDy1AfVqPw!~gpBij4u+an ziKc%FF=}L5IEL13KuH?gJNk>nSH~v*b6C$L$c_$7gt+R6u|A>~L4jN=rmm@sX2|{7GqYY94 z-_ZRbr=5yMPPg{WwQY^-+5*d^7Q-fgwowxqkhc$(@Lbjf%%`fMt*8~uMF$SpVEID%mn;bFbii;IM~k(V*04=Flk3kX z*)a0z45?#c0~UN?l3cR_e+zGN`x&Kp5}pm^v5k`rX*k<(>BGlR92}+LenNfrM3+Cz zGZ3vTjpxU+j7~a0LerGr55hJsSM8FOeSda!VmFDGboVO`m!HC_c}WmHJQ20ZcgIU} zwR%$Ibp>n!3*rV@btvI7nrl}?KJ;=p5rX*Ujo9sCWSoG^nUBtqZ+s5}B&T+98PO9i ztyM+v=NcwY8qym%_BM88VSGha4{|XO=#oOFI{?l)G16E4RCok0iyNH$8xIyU(8UR5OoVkvhRBc?kT{sn@(l@C)g6SXXRij+f(;w2w%9M3pFScKAuo8a^e00B+LOWexrGeSH zgVs-V!SdxR1f1`-KX&6CxjjGcWLj~+1g~D5BkLjX44~q50SYj>;2 zzQSZ$rp6wH7ha4*TTn9pxcy^GXNG1PTg{UmvEJ{=1RD$L4={gP?f|Q>7+?_=1Cw%V zQD^TxQs1|T){f{H^at3OmkP%PmDBU(FNpanAjzg&P-2)CUR}9x z%UHL)Wpf)YxGY)hi54iVS*JezZgi2zrkhNwdFCN1c06VT6KwQ=L^5G88n7!yKm6~$ zqYRa1vB~bfHI|bxTzVkKeJ8UZ()c=gU_9qZj*C&YD?ObJJ4c=CtQ%zOxWcX>ZL!Ba z{-M%{fQMG4$EjaeUTZfr?EoU{e3jPTX`XShdQOGcdj~FJ`YeiS#vNrG{S~?lro)G& zW^wZdZ_K?fPNA0Uo@DG|7`8Q$=t6Z)KDL_z0)Z+_>+byt5VwtyWsc?{>_|=Su$zLS z+o$1ji3MNQ49lWWgE(MKE7ns>cresf!1LD5WJbbdB%5{w?=z`lKe11;yXG;sqvEM^ zX=`VizPNJf^2*X9M%ijvq3WV09vj=5gvG`7$P(Ay%DvVU&-QGcZEvpU5Z5WEyG_zI zGtf(kC9h)?^7iWN*7~@=m0pZ2G>WBMku6FtjIBi{CP&}I9FxvLrwxRh_~$ZtXF<5!X0xdns6ZqtcEc&2U!JdRO_A!yi4VE_OKav3cwcxok#pnh(UW z>#2@FG_Kx&>4+^DB)J_97CWxEh*yej=gNt~y_eR*)kG%M&z*okv9Qis zn&^C~%Ds5u;0Fm$Mkbn_Zbm07;Pz)I@q(i{&RbSu^p_4!cjJYGn?wn-Xk%`2H-FK^ z%bVQ}lPLMOKVO`KG3eDGmsGR67fTSmG@i}uA~^FY#G@vB6ef7{a+%Bd(^t8Mqh0f~ z&*c(pej1%7sNQfGCt}w3aK78mxEt1_i$!v7X4+LnFfUR2bXPL7KnO$Yyh@no(iU`m z(nm-$3FSM@=rXoCSp#v1F@@6oOte z|COrr#*=;s((S6W91!HJFvZiYo`Lo7o$C`m+i~#3a!6q}o1~TIm20+-9G~bbG$(?6 zt%t|H@x*q8!CFJ)X*o8+7V;Om%l+O)*-xSzS|N+T;vT7{m%h>qZOdo1p5kd59_`19 zH-4d!S8s%?nL0!1Oet(LgA4U9c%M3&UovLLqBk}dce&UGkCpmPNL?5ol*q1s$L5BH zXZ^7_=SRqx_o8jf^qqJEREC>I;|B{V6fN^>)fch0J7}UK13K|B_#+X~^sQdu;=8;g z+Fxt?Ct1zbjA|n=KJk&WCz4MTlQj-Zp*6hEi4M&`1#%k{&hFY_R(|uY&VUx+>UkC6kO;S`CASDb zenxvQ#!W?Z(kdSnxynd3j@NNAviK;~e>mm4z6hGMw`}igVOmxydQUlC>Lb@rVpr$; z-FWYX`P#m!tF66xU*lycsgwdNoolv{jags9RK1xNBdhvF>&jwd(gyyX)lDe#3FevHIZJysU=HnIDld$JM|XN~Y8^ z(LHpb`QQU2$}n3J?5*V{YU7Gq0nXmU4yB&|Zr(l+(X{3XSCPoS!eH#rG3CSM zTWi#k@SE5T*@$f?sJ=vAuwHEIjo4}EpUb^Z8)n|*e^mF$(C-)(rG|trBvp0$BwXVR zE$<%_KQnPY3PBOa7_1xV~K$pA%QhuhXGg|i-g9}79Dy_?N>FhxvaLoXL@7EK{tC$Sel>- zgwC<+!1~O;NIaDPFJ1vQI|6`>;A+7>Gq|54=PQi9rtr0=E1h54OSxUSPAm)BGRrC- zY#lZy19FwUj;<*AL2wLrI(pDFm-U<*h*HKOazh+EBG}eV7aEjay_6W$^7pp}n?Rny>-ZnBJ$Nl*@F= z)I}^?vo)%_uY~m4zZf%htnQPHXgp|9w$Ms_{!+`coW2jS<^fiEQ zskiZpna^I+73cf0k5UPI@QL%VsXLx>)=0!mI#1@R6~mltOjjJa`S@UiFW&&?yy>|{ z&4V9EU4tL|+49x!wq;(?-sEK#>o%U>Y?kOQj$tFMP6*)*=NZt~OhO6M51qgDLOaK7 zX8DOU5Xj4bkno;6-006)C^7Zf3HO=K)(yVcaw2z9qQZ&UF&xZ$BMnpdi#HBSad*Jq z$#V{B?{n=nGWI@@rqsX8N`YUuibvSeY08mUW#$vG_{yf8?il8MEe3mJ#aQM!qW)`pdjeeUJ(!CyxXQER%b_JPPt^-wMTInCUWbS!(Wmd4rf z+NL78@O0-8ekXh$Z(#9c1IQJ*fBFrJ#(&U$8K{HzGp^B9Z+4J*q0NYXz6u3}O|Slr z$b00vRMF5cBn8;L!IIQT>thHQj z1QM}jCdcunV_(r3_l{?-MTgaoYqtT!XfewLVo@yuyCJiLy2>E}-+tg(7!Q8pl?Aec z7DC+n7Y990J&$0V)6I5MYyQ}*zORbKS-MxxAzRf~@7>~l_8|5H+2b4Ozlf!NjJQ&B z%!pBwoRTcd@8?yM2qg@plu3Z)9U{+Wb}tdI3w?%yL$Z#m)lSIRUpr%k%f@^*@@B?e zdUfl3?K3soPQh|PZF|?4Wi4~v!TbQT#UMm!*Af<^P0lnWkeJuxzm=|UqQD~7UPOOW z%JDO2`%BEucuIF*CselAgt7a>sXPK=p`H8u(DVSC%xCR7j?RvxD~5D59E&5;yE|qK z=8k-^PwKlI`O>SHO9t$w*=dA%p&2Fv)~t8^06tyj`(6+HE48yV5%I-B?rL-KI?B$d zyv4Cnf!I*GbV>1@4}p^vnF7_T@8~V4%Cb=DHZc1lIOK#+P4?HDtXOKK2Cy{rjwXdT zaoKpz?O@}Wb&N*cvXHhUpSvpjc)>?BNlzt9&K`8?Z15JYu4-tfm8mQigMfE2W}?nD zA|Ty+(wwMyDT&W>8fkHj-Ab>D^rf1`1Dt@Ojn6whj}MM6)!zuf*FP>d6+W8Ydz!D* zJ}{BW?&)pgv* z>gPF04U{Udus=-jLNhNL`Q}>ra6B?VO@+pCxBoZ;h-8QJ7bt-=iTMuztn>QIltBG) zR!o15kY4@rTg|UGn^aue^xG~)%hgX~&6JO|iZEt&_=tUo>>flFKXBGDFICAaWZo$7 z`TaReD)Uc)XfU{6=e6CFZ1M0-ATjCk#lQP-_V^jP%Q;N&1v_nMa_I>|YGCIL%QZTp zFa5j}nUw`U1NATLMpp z%tuwHRZ2+BoC!h=&SOm%bMp%CQ$ICcH!EciO7$UmT5Y2r%fRc*pqF#L`Tw!^-tlm@ zUDxmx5~+w3y(L--(TPsTXhHPeqxT*&3?fKTf*^YDy)z7gsA2SOCZZdoGZ@2ry6@+D zE_v?n{eI8?-}m1nb0%|^WA9__wbtI}Hy8D6eZ=>Ypcf&5+rtfQJ1o4}){!qt_Vwc3 zmN;Tr`$Tjr!&B37zp$d6+N4b9ilOT=$5LIX@=d3@Iq=}JVgLH%LPz3|!W3WrBI`V_ z(%MLrfP*a}J*-L@(()nIzj4BVR2jEX#hzYkTnJSh#3t+8YBa<4HisvRZDtN#gD% z#5Ogk0VOgS?0LrtG8xT+?^`uvC#_8bV{&$opZMo0`u;_*^XB3y8iBxkvvWAUSZ_t| zRXpCaHw;lQyGcnUZ1!%Ogwm1j#e@oR!s<|Yz39mRA@@7~^`}SIQvhsY{UwzM=bi23 z>H82cHFX#2F#2IroL-i$IzK*_n9Zm7EWen(aBNl|hw?y&emXbUJR_we>8UP@%$K4t z!sd<*mU^*yXG;-R3O8S35~(eUc?IGEpm#3z9s%e?PVEm6c)RYAWXm;efiM{dkIUJ+}2qh0o~^^8D9>B7b4}A7A8 zzmvz4o9t_PAYKfRV#Dxzz;wdBuT7p%IyjBUm%fEt(y4ylR;>U^XV80DQk z+aYoot3L#}&%4_UsDSjoCoG5xbvBY{Kn@V>JtC$o$6j8l3D{jmC?5a(-li%P!)DSh zA7pV6gZuke0t>$X8T-qN#pd&CwEwb*ZO&fHh2OB=Bq*2Xm_GOdpmInFc%el=-g|%4 zvL0CJ_LH`kz25Sf*)2|)G}!(yFrHnL!23Ap0!nrYP8rCTbX+`ne%krQxwaE%lV4xB zGtRuTS#IXa1Ms@>(?=r7dmN`(>t}QRcDi&2i-moK=5#;r>m6xNH^&Yw8eKD_k8L>;c?K$xdEpywb*(6<8OeykDA`x5_rwFzZ1RGZ~QPU(PNLD`j~cinD^DH+K)GL zGh0%8V<5ah9b1h*nFNs&BL0zuf`mPt?SxA6cZvi5$mX+C*@`9DM5V^Wr?Aj-(MRNF z4($H*1*JrB6}?(N4z5i;?lNPF%H^W>$Wz!p&ElkjN0KMEwJzY7%l4(g{!+FJvMh%6 z6xEXJRhmi&{u|ox?ncnzGqc7 zc72MKuEQbH)ZN1=8+afqoC&)~{UHxI;=)rB2jlyIKz)RnlR^W?sE35|x?tlc5B%Q* z&6xcJ;vIIDiJ=h}YgHDNO5`*vH?37Fw@iX;^L{`3Ammo*U+*sYHgxfr>rmB77I+rZ zDCQpY(b_iG<^2~+U3R3^@n1;#JfEMPLe%IV9n>wCsls-!5CMg$s(iwIYiYQ^1cXH* zKpYCD7{oB2KM?7zBB)==J@#L-`ZCEx#cu!z0e>C{rW|agUeA=0FtRyazrG_k`Mc!D z9{ADG%5I9Z%p}6*g`;suL_JO%o1RugcnY4Djp8;ZvK!l04~c(jw4~c9ifhH)q~J<@ zImR;^q3^g04M&$bQfK9~9lcjPJJ~J02fRpgyx~ycoEp)%-ygd8XDBcLhM|*3s()mn zhvZwl%mJD~08$&wjeHQ-!^Q-*1iq@MH$MW_3V4r%7nM zpku$%B~x!`@EWyz@^NsQ>(sBjw#&D`zV-vIwNwP4MjGl`2R#;Dr{47r$}Wgohp5fy zMs-W$aQof+{{m{s6%X~6te#U5>ka(6Qmc_;z%p6m8>dgkTM8bfcystA#T0U7o90b+ zjExh+4B^|dzh?me4yM)mKDisW=(weh_edqGq6PSzrW*UIdq}mLIIv3ynwrqm^fGq~ zha{sKYw!e2Ia!>edadRQsh00OPkpUm5_r0_^F%aC@)Di0buc$`4-C?L0LB(GTW>UkO6oU=9hlx6wEF<)fh^W% zNtSz4x>Y6$6DDD)By^EGDq7q3Mfm|4AzvT2nAUe#Pwsxj_aK~p5aA+0a_X)_O?AnX zM!=DzKxF2X87bwUorpB~CN`18DXWb(^1@~gFxQ9o&J{b4e42lPEP$E4Y#pwd(HtJZ ztO-7S-0f!dte(k>g!k>jl%0Avsl+KWYGaxc<%3IZJo_HfL|t6u0By8Xea&P7R9ynl z(`?aGcaK6ngo=ZIk!o?2%dOh(RrTD(IAcFv8tByJ?G3OswHyl;kZh!UBAbb z)Ocu!)^+V-h1*kNif(<;^XPD+$m9gu6twt&U6c}92W{_r+ z5PL>vwlYed{1U|kRksF&ZOWy7{h!$Vw6+Y5(w!Fr`(=O;(FT3m-| zCKC(^pov%>eWw(+>#a%V@fndZULKsXJb#k-y)_T{-W9jC;fUBS2VI_3_Ur#VIN;L< z3LtKO2gN8{EMFx3Vhm673sT@j?Qvh#H;Dl`anN^f+D?)$qBDORsWLzPZy!u!2+yGJ zY^7JKs76J`vLl1U@7dm$bqd0st55H;B5uSv04T<>ee*TZc^N%4GHEGYiIzH(P^U?_ zNdX%_wD8pv@?QHo!uKxhT#e+_CKRWChOgQr(l?Y3d>WN2_e{{hE4dUYf7(p5BwI)1 z1BstdmQYKtI5)j&72>Ei z1_U|350B)eA*}=S+%KXJ`m^EghCS|p5-sEEXgiw6?nNmjmR}-oLBwaXX~TT6(w1b@ z0}2%x#VGK_Xk!eP%o1~J&toLHsnsl@a)Z2%Eibt4awx4B_|*>iqx%}hJ_tZHo;h4w zNY)_)osh`RxxY&Fsngj(ddM=O)n;XdzrH7VOlJHziZNlp_Zo)d5g#f+!tbf;TIR>nxgfLJ(a&}^ zo8r5c5fQ2{UpSqeYjNC6j9U|&o#yNMd=x7Uwxc^jQBO1rC`ajqb}APdO5H;jx9fko z0@8d+Xw~vpxoD#OlS2$eWC_Uo&&w|Ykd&!S*ToGz!1|gDPZo%;CfDOVn&rW>OH6vD zo(N-r#1y8=%_0^z6sf+4@owWF<8nPB3O#XO`LMvLF^1U-?z;)B*LQ%$jQi|ngBmTb zyWA&_LUJPFPO{D?=0)_=X-{Ws&ucA^?;QDxC!Yz^(1Wzr(d8GV7Zs=C?h?tRuuXn{is9={iO8$}1SZ|3Vbi zBHKIlrn72p&+DCIngOTdPyI4J1J98-W0FfupW~W1J*cZb9Zp>T5BaY}+TWjyl(FJs zATn+cl&{80)ad(~?@8txCO`@M z5Q6p^4;c6qh)C&{JwMUy0?bi=l91hHM)#Qd-MHr^cjJPleu-HvJ+I#lPjboc7>C6a z@O|aC8^=AdyT3M3l3(RC+@7$%pAWA9>H^iq%hv(63=qy8S78iOmF+h<1;3C=9FJ5d zY3HOQDq|AmGqtB1$dy7bF##Hn6qAb*9_$s>KYI+(y8FyTM*HOCGe^d_QB~lFs%>c4 zV4@~q|24pJrq@dR-P7P3>aY}=4``*G3@(O-5aGu<3+2yo5&*$--V72-B{=E=z51Lo!B__J}(ce}qpz!Li-cK{B{gfBbOj=J&KF!z@5i zYum5`M3^d9hm*qpQh(NKl6cOY*n5K15}!q1570i83h8%N1oR5zC8l%kIr3>U7VOZ&EvNk9g)jUFMJgjQaUo8lxXl?;a>fm+^qOKHBuW!`Pm;R%oZQnD<-qe5`f%^>8P{Aw`anu0+8Nz508DI z=6iqb@)}U#c7QUcsn&MHhP>LVtjWzvi3TGwV2=q&{U)X187-H?o29~*TI{DC9RAJu z<+&l`+|v4ZXDd3A3ox;hxu{ZJ+#`GdF6cMm$A=g3-fg-7AQZGaR1zKlE|3W2ptI6* zFMwL9^8NGrreq)V)I>(m^)Utpd8B{uj{$m@HATs zPF{irV%Ym?=t?)<7B{Ze09BkkYr8b==789{@#Vbg2MhdZJ)A(3LvTik;kLTHUo8rG6CvfUt7*+)pm`{+Q!Kb zpIl;sae~G67@jKtMQv7Px$@M!QXx4pi)PPPveC$aX$jADZJXir+;iqg21ln?XSq+2 z?Svq4#qW;?S=RTXcL8~WmF%jj*xCBsA;en*%2g4(I_9=@AAr3&yC@^el)KGv6mXlt zA0z+O%kno>RetV|BDXGjcTqrgxjV428ds{rR2Y{2cu%64m}N|>`nya+3nx}i{;_^e z-OM+Eu$aZ;dT<}u{M)DC5{rKm%Am1td1BXTMc?W`MYp2QtJMBv5i34+tLT~fO2z*5 zT9E@J*P98NA*Ww*8jRoc)oSm=&%+4mWn z-MGx(gzx2#V%aSY@R(r*aCqZ7;e6AcmvU8!sMk_d0jGo&(WwQTqf&oA#rrzk7ei-< ze8wK<=CSYMZ`iKiD+_Or3BDMCz8@?uQhmU9L00&~53|D_9! zi(l$4SLKE~bZ`z}eJWL;BBu=}wkNq^Y|DsbK|kUY;r;!n(&Ly#tg(O zjho+vF6<1xefKcE`8U0IR_>X?;d}(roVgR`1Xg-6!P|I!lPU{MQ`O=sX5TgbV zx(lmpz45(x`cQ$6P5cr>$aT+Z&{U_2ObbGMgx>UH{yg|AVbWTrnctjf7ujv?!}@0E z*T;7+d%Oki>EjNM*ftdm-tiZK*Hfu~Wq&smmgxdoFBZ$@at@|&5dyDKU^GWm_aP@D zxjyqW=?IJ!%s7i*?w){B&!3=cHu>I>xzb4cSTnxZS)d?%xsLN;Q91**e;+KKbO-Pt zbmb4{E+%c0bUE(LM2T2=4xg$Wyv;1pN=r2&g*nNF;bEsRyT08tY#5SP$Zci=vJxYQ z(0t)|2KWwl`f58Wr6cfLWV_HqEGl}bK^s*Y&r5|MnK!EId;4thXC%jvv>QjM6s@uS zlqFHo3UBWX+CIPqKjR`xvI~}5S&l(pYM0J|G7Op8?$MQ>8=GpkZ;j8jo;R$N@RoG* z**J2Q{s4HUh>&7+mW!JhvnBw>qt@b=>n?(TmNl~O+Pheuo9wgGnQ4t-^)f22lqce4i+E|3Bcp(K7k7-mGa4CS;=e;i5p?ki86V#W zr4*9~A5g8K2lN5wxQc|P(GJQjPKf^34Tnc2&@>VW^lKu( z*irU&6$dhrbLzIa#qH|x>0ZSsrE3qhW9#Or1weCpI^rL#Nw*%(ivJ;R{F|-|$U3)$ zs6FqcWxDtf+U0-!QVCf^wnoSp$S%F2>hl1q3F>XwUde54s;A6%0_4@LWJjVu3_H5v zMe@sT{pW4{Py&G2!Tl_Oi+8o|#g%{CGCb>abf$FbDp%;b+Z%{_g?IkAb@pC5oZ_L+@?}{Q{iBJm49P z)j>Nsdo8TNGNAl+pF0|Wbg<2?c2YNCMA!c6jO?rvol*WPWV01vca56#`2-cO`s9R*WE z*`Kr!I14SvU{q3XmyZ=uY1GHVc zzDzYDA-VYcfr|lhkHvIN@=kX!=R(7#-&bQlyb=_Le}A%rcBxeubbOTvI`^B{gw0tx z@@;&4Rf~KGfa8XdhK_@OF8-fSz$p3939fG!O;8t4^PdC%^(pFHw~?P?cMH9E)BX%^?hYu0C0?Z%yKpZIlzdM@o zF@UY3?)CF@{@LmDrwjSQ$xQ$mpxl(}4~%%>>;LiZn6I4gC#||mlozw@e@4xJ-+bVG z4om{KSpRoN|6lUw|2T&We>4HyknO?W|L88h@b&*#a9{47kGi;F6>t8(T*m+ZqW{l4 z_4hsf|M;T6liU(?lVV{YGL=O!C-kEuYU06pfClu+{+g-Z1?Us1dREPXUaQg7%^cZ%HU6)~tVN zlI}ex^?45MG>*of%W9&l`NyAXo?Nn-tjiJd z%|5Xiweep++h(g@&8gzCa8K2t)8bqEFdD3TJ>dDZBvB8AXGzVB9fa-JUF}qf<6C3y znCkI%Q?!e|Cf0X+!`Jn&i~Hy(&Ug_9;QRC08&@{_p00*MCOHhRW9^#9J9{aNH@HaM z=6*&7c==DeOz-aDMLfnHPHr8MGaYVyi}&zC&hX?d|FD9?*@v$&dj@R!J%7X@d~lZ- z3T`yGZZnmpXNIzHJDX`j7?NLYQT{Vg2Ln0BfasqjR!;tWyE9d-8rslujEB`m5nvat z{}fSL;gqv$8d5zy*>&Q@jS^`tespC?{$y0%+jQvK&?sQ?>enIBzU@;lRLpde@!4eD zkl)H>H<$}NZZUr+n{W{nmiqXqR;l1JTjlI5#SptlcVu zVNG5H*vvkn-7CYg?Q35$RAq|Gnm~kgWINhf*eP;2tXr*c#pGJn z4+b{Khfi0&ExFrA;75hX)ZLBkZeZ}S79bHBOlW916vjuw>n1ZE8LHM`0LD~CT8wlcS&+Y zE#EQon_>#%}{dIzeWc9m4lWL{HB;DEgxKLusf0-cea|;D%)3$VD3lm8{XlgcjD=>t!6G+*`o{AvdI0EIcK}-N zn|kv}*R4P9%a`;13i)=n5X1it+GkfUVZS#s!ZwjouEqjQa`uXi(Rz zkaf`@o1~GWaPAGG`o=P_@b;LHqm-x&F?W&LAUd;NAw# zz*=bOk9|C#{Rsf@&BS>B0q4$C*L~ntsZ|((i5YWz=U#UvP9Zqa>66Rl;)Yva#ZW#@ z&q}wfuiK1m?NDZlcLcQ069DC6XBcSS1xPSHh#$03f&P&bUFG37&IOZ-5{yw~2z{Lj z8=d-#E1|cj_+O4ePwMMcj#DUy8sIbWB9Ktuk+~i)DHWSY^QpjV&$0L4GsNc*Yn6`oebI~Bh)?KbU_+qs`N;F1ioAW^!RY-f{ztLBn*_Gh% zc*|RETk+mLK{pnnk%kFZ>CiA0f$kQv=${tjM$rnEuP7IuySGldEidE(bc2=o%DbBs zGLGF}lpTAMRMoPso!JdHhZ&d9ygX<2O#NaC#Dq>DJ6ZL3bZLVY(6?2PhIdO4@>r`% z5`t(|E$ojQFKfsYIphN4k+_ON;c31N<3?^uzsB>ApW@s)%2`!XM7!qH0Br)dDL;8O zuL8K;{kn>&h84%y<6Dm>Bjj_>xW~i}hsg%h$%b;|IdpkYW_w?wSgUl3mJmroPbGlS z7P4XVS1XXQ-J)lX%f0#Ahea+(k`s3g5{4sPM;Le58{W0+UL+oD$!pG2-o@B77higz zIysL#S%jASoC4GWD8&0<#d0iS%us1ToBr)G>rOgKWS__i3>`uM$ zRo)@HUZW5q9@^*bGEl*dIG~s@Gf1o@3PueZ^)q3F~J|6HVJ^SSQL=rC;kAwwU5W5rVmn zB?;|=i~_?g&|b^qs4nmMlY0WlUB^ue931UoyyCW>Wt!c6n!-nMa)#Ih#$-tY=Kb+@ zrH%$r2x`!DtCa;lu97T{IX)fp;20k8bq7CN<6h<6WSdX2831KCA^gK;>0kXEe(bN5T ziL+R|4x(Nw`8aVrxkLgoWU?!gs635|8RNfq?5o^6sa~}qjW?>tPH(=1?@>4YSV`{& znpS-oe)HgQfN6eu6Uxn#hZp> zH7DZJCn@93Pgt4=T6C9^Sc%@s(|^%vJGzaCKAQB8zM_)G{M?HN%Y029y;ClxQP{qE^UB9niAO4_ zl{!e>8sXO=nv!R#d)u7~3h*_~%LLDgL>;PXsAoLh28MT(7AFt=_R{WsFSwkjd*JK# z#Et{aZ(U?Rvlk;I;$Uz_3C}qJpLkWOs^7E@#J5Mni!}*T4=|qAy2c9R4XB@$)Zlad zV>qF&?RopCY{ggfrA= z>QT?pTg<(4!alIEay2Z;ULYqZ7Lm-G=xuexSuVdPr`L7(oo2 z6*v1KOpkC8fKjVF8W|NKXiuV7!b?s2y0E8mM`tp`e8HRJTdj3a}?Kl=RwxEL7YHXtH7_0gQ+2hJlvMc zFd>4#u3<_Mlx&OWtyB?zh|usIZA4aB^*%HYcCY+&S$rPdRGz{#g#(qW>sp`>W|stZ zmmAcH8pnjod~q^${*h_)Y4neu^-*iqmRc%LhrAf3*ak%6s|_UF7Q3E=p_|yf zcNZ!+1#&SSYa(N-v*}kjhS}qJdftMnD(Cy)~7TU0iA>{jni*Qym+zE*< z(NbTuI!NUk%hcOa`Axh~v@xl@I5nd1{aYQ2qR^=dRHV175@k$y#9 zm5m---ZwpB8eES3R0WfDegBHbV1)~DJ*OX1GKGju({4cg+-jF5YuD|EO}32PryYZ> zqn3;IGdvj9cnzE5^x&Mj`)Ds}I+!9Vb31a+XuvA|exr?pbfD#)m}#?du_#(S@CTc6 zD#NwY%2>3xHgv;fzWK&j24(8tDbm8BWwWvvlu5D#4MCb~i5=&+-M8W7OL!t~1TxCs zjS?#Mdl5*``6_{iErk95<5X_~+1BYL5#fwnZTR z0&~Jx128x3TH*WuO+Q>VyEZ}deV;+cs*!uZ{x4{o^|~(Xw{+zR+-o`VR7~%Oj@SD^ zM%?!)6?67lPUjof27~==iJu(|q)9zGj>uKE8LZIcu{kE-Eo>OvGOXHyEB|;0wC}qn zhsHmjHpr18UknWvhv+r!m{Wz_s%0gOJ70o`LO99 ziQ7S0@Ezmr50uF!w!d6=xLmsT)BJ(r%RP!|ptj*X3lIe@ol#g5z7v4GoSNr6`|Vq*D5?bMDd5fi*5=xESz#}HVFD3@&+SUvfM&c>LOA_Ql)w^T z@JoH;bc<9Q3E0}hi2A0nH*L#2^h)ao->M_6*CUww466)snyV)aUec^-6&+8wco45s zPL&2$@dl?3F>>W*EnAQLD!DU-?(sLhOGjw9?qOXPbRcSaHd+BM-%Edp?Ox&#G3Tq9 zKs(z~hWA!4E+>qGGO*%@kL&>(ny?uJrGp^zMTRpRB#b!D2>r^GdZiM}X|c?miy>ak z40FrAbSa@qHkF72c9lBYXmeU>1I82*pX>L6@a)Ad;T1a8ss|G{c5F}?DPO^dmqOIO zf37NbUfyu(3!1WPp{sW!y|)GXSI~ZcICWF5E{oV#aK_n?@!CVZOH39D_qb`oi!mKz zQscGMn*5YIKPTO|kyJ*2*F%;mQ=1B-Bt2Z0E=EfT+Y^;AhSz(~+TI>Jv1wz88BF}b zYFMj_YYMQNGN9a%9UnA#h!(D?z`#?K=!OyN#Xoy0{eYiHmr6ZY&VXXC5s!RkHer5- zZ~}H-h|_S(ed2}kC^+{tqOt?+9rGGtOANA|$O!S)xo>~TE|MtpJ(6(hreX+vX@ik8 zOqEz?#Q&+%6k5-NscVvB6{~|6FYE@BgxsY3*x{RpxP=*A$1#uu&vHOsyH30ydz0sj z2ryslb!adcAHs$gndh|;E62Q_>{o|vw zd-Z2VyW^gzPRM6=q3MoADT*njI?8KQ&HXiMK189`ahuiDUOa+}BhTNE5)HmkmSUNs z&TQr9Ivu=40j=Qyf24#toL!9{h_?LY^kWxM29nz_pw(w_` zcxzI!1oxHbaolCW1)Z?Yv6?;VA)-~F)Ib>QP3AaQ-u^h+l{21w&|#{gMMu4Lo0==* ztgBSa+Z_!4f-zPe|LDL34rltoqaGiapoRVy?+MGd~Nxwgs z7${%-LGKC>>rb`{y)mDf%@OGV!B;U#3z2H1@^iQi0qQ&9G}9ktJ!%Y2n`>iLVF7#~wCa9q17-aeHy zsV)aKzebEn{sjQCua7IqiNJLEM)eu>4uxg#@)5lp_};yzdIRfY(1<~fX5VSB7B`H;|a%v<((C@yx;i`Z%gz_T-2dcFalPv}fq9f(^V9vu)<&DDGzf$y$mET6OAHF=fMHOk8BZZ9)eUet7XKNI zGc!>+-V>AunZLcEeQKyu!a%w|&~g>*Z;FElYjpbZtK%Wo!?R z?=Ko$!YcbZZcf1wGh_a9cM0LMj^F%+i;`6?@co>#n@6kisx3!0nZMsWUHFIR-raKIQ!4QUz*WKw9=Y(qA3HdCh9>Zw^lt7v-J?@cwi$}`b<^# zOsc6xjKZ(l#$nqovplVMurMH|isBt)2Wi^h0St9=lq3Z4Im^)WR$V1~Y7_X5|5i}- zE5duQ8eFNVh96yVbJ^HE>Xkbs0dv6Yq7{iIJ5I)f4*uCrm+0lL3arG4eC307`seAr z{KnCG)|pOgG$n$|`w;?+H7gSmxA}e_6b`m1oTcj6@TIMNVMyTn@REiF$c9hW_%XIA zS0S0XM(~_A6CH<<|2-ti)dii2?`s&XVu*I2?#9naxVj9j^fWyO-}*#;G#lO7{Y92>+ZQ z1i8=7;YH+?&EMXAO2=DrHg!gtG-N@2o6pQ-S<*cIStTlS>YI?O35B6OD;-!C!Y~BW z=g;RjzUd69kl=lRf00T$f|$@IUAtpcTfR_S9&l1;pg--oe*N;Ubdg;XRR@<^)-?o1$q@!$Sel2Z(f=0921>9oi@NUD~ zPTvuj8HiO&{w&QDL=y{2#e-9AE3i{04E+xx28Y9lZWviymer9j7Qs@}*J(+Ia8#hK zx?oIYYFGKbrc`q}rXEyL7eEx!qscRjJ^!6unmbcc$FS?@E)vN<;ouc=|MX6o)cG3@t=U&2#g5GywJ=UgXuSuoZ6o)~;n`e^3-O=zo zknDqv%0bKSlxAuSMQZWwt`dWW7@ItCClv-NCdpF77eRvWt;#4R!u#C+=mh@$qyT5@ z!>D@sZ|X`C=oWS88Y1F=4Ef2W^1xI=gI_?*af%3*FoXz_gdv zeaZB*t}}(glmJteb!ielhjF%n``{H|yi%Yrz~@-D1@+r)GQ%7AYAb%9*hr94ho(tg z*Q%h7@DMjJPgt645Ol)Za#Y5V7?yMwF!7nl_`z`pQKUb4l*8x~(uw0dj4);-lWF5E z8M>K2cc7<-z^D?(<7#fDXfd59RZs|_9kb!rX+qFCHWm)0`y>Y;92}|9rDIyj%oCeV zssRrVb`V1bK%wtQZWcXId@)`vSXb|H(+MSk5Apz780l($H$IxF-XEI=WuDA@4%?aQ zhmTn^K$-b~K`fgzXrXhXyK%pre~dT{e~`E~9PmcMg_TZera+rs4kN+`y)Kna&e-Po z)vZqY+xMo@)?UwyXE z5)zpC0Z6mf|8tAf`}mbHuQw)gp9hc@dy_WAvYA-yOun>IX>*ulbk7+n-=I}N)8{>E zQl+yKh?=dy+U=Eci?Md8fVqJTDz4uGGlnbTLH(WkM;I&>W!SRjN|Q)m=Xj;Cz$K;w zqem|wajsKdxfTa4K?DAGIT!%fhBYcA8nhoiX#RC06Hm9`)x~LucsdEW<$mMat=iKu zOhdNf=A32C!TYg7H{Q;SgLH7mtyRl|jPxt>I7l4IN}rDqWaRK#Gv$#sPjFj!X)|}o ztD##MA?4;o+aarYbxwYP+e3c;U1P$FhFnXrbah!-#$suu+crTo5loDkA{Ws~)zoLwi6BUO& zDLT1o&oaRPBn~xwT9eo;SA7OnLsw9PF`XH`oWS6}>C#D*51K9>AT>5Vx!a9T&{B8M zkNmoSTeVn9q%wV~*acN2`c8tnD}$I*YkVgCyP(#5xmJGj3sS*XEeFYvzI4N?ndn7D z`Dn1F`_L;bx^!R;hyXlXwNyStbl`zbQq+F0ec$ISmr+ObNZSXbB0|G^bmomU*UJ^? z1f()=OU}h+EDvl=*69stkwa_S(S(tcc095=yYFQ^zN=-5HaeJ6DQw)&Z~jt(YJ@N{ z&dqu|>F7$$PBmP4Fp0+ys|0*%eN|_ue-OOkOzfeD5jU4hS)x0R*9SC#350{stl*ei zJ5b??RA8s^Lj}8kxuxz!;E&MvxiS_pZ3QbwBj$tmj&EAKrFW((QgN9X2Er7tZ;KDM zND*rcELeH~4U*n9dg_%)r!ElIt2ZWD8^M$x3j-Z{Y&D4CHTDg2c0));24VIve7yZ; zkYb1|`c&dzgFv}p&2RpYLZ$5iI8o6{bZ#%B4jK|bM%h z^ZHO=#OrB|&02f#u`~5hCwZr|KtThg>Nu9okErT>CM1Y3n}a+azri#IyHZcTDtUtA z8s7Y}1sh)3(ewO1$+qlGa>e(T#Img~#<=Z^jdi@nT(L6)b%)~^KB7Th+t|B2*=yf-;%V;7RQ-`pIJY>#zRfAEuK|(nsfv7iu?Ly4hg590k_sx~3hHQ~69Muu zpqZYN3;aad7lO;68`rzm{t1EnD@HzxN@yVy%}%E<=|bJw@Iqnu-MFSIQ+<7ydwgQi z>mSGHI7NeYG3Aq*v^U?1z$#RT4 zkWJmkzOb%Nxp6jG-ng1~)N`3SN>+OJFeg0F9RqNHp;oiprmvgmZf>^@CaXxCO&LM= zIUpQ2R;^QyW9w^{MGEm1@dQlNAldW?4TsgzUW0h|K1JFlMne;3QHe@lf775dR?k7%fgMKqLPr3Cw#es* zI76~+A@AYPXUF5NOUX=y1sl-c5nRk!-tkW?nM-KIwSGh=#Krvl!Z(NW@Hi2_j*#{( zG(wfAjQdz+Em3%wWR;N!v!e2;Q-%{#?1uT3m-9;&Kei3MzfZ*XDj~Q*4Z=>H0oonm zfp79l6j_heowAhle9fV-FkzncP{nnReENM%M+9npt@Imu69V6v);AnqGaz6(o*B>c zw$j!GH9Or~+FK6yqn|4-`N7%mJB&XabY|;~JF|p6V}aH@T5FM0Z6f8xpK5dIet%pY z95?DN%@~YmPQ!Yf3TzJWo`!DJW+IBOGL%Im`8(^i4sw;CSM zq4)NP_4C%)GZI-!*!|As68lnzQ|jc$e-%rXi{tW=-Hx}%>b_@h?`{k@q`|S@**08Y z=@W0#*6eMM*R$=yoJ>t-Rfdb9R@xG8{6zNKGu5?{uE#B298@!T19(BH)~5?*NY^{p zL`vHvF0(ndpUnxBS4jVM1=F6AO?o|{@G_CXX|gq@LEy!K+gd_^mhImC!iZ&uv`~oqsT|ep0 zEPZ)8jp&@d@DQkcZBlB=Gp>yAD-6s#y{yRNU5@fVF+-Df&eXc(R}tuO_<(J)mu=3= z-`+=8Kre8wzCU$v-j0x%UJNUBn?~A27}`6RYNGVQykeJ>U9N(lVecevM8J1X8~J3v zcvbj0+1b7ow_IZ<7Fla+ku&Y*@Pn&{EWm3c6ojfigsY-p5~ckG&dL+@^i7_6&!%HB zIMDR&cx3yo?yiQ|;#7?w%p{Q>hjy+Bh-4r?r6jI)hiiFoxKILpeTmaszF*N_1oCTA zQNU6JO5{S(P`atM0>|1Xe?_hdy>An{=V8(gp%{_sMAwp~4CklF3Je28yk*1*%FR(# zf;|kGNMShG<8iD#3)QC)$$~UK)?|AfL%{FRQotl&sD3EFT&0K6v(klsMz~Xu?%l7*Tw*VZqtm*>oBXn~&HBdy0S0 zy6Q^AAq=6oBg5%WJX}#5)TxiTGL}mbN_U+SEq2B64_QLqCEZwX(zW^gbvOQkV@(oZ zazPa_X8#P22}rtJK^%IhOyb}(=Fm1P_)8rlmwb8IV5+_E#@S(tg9-Dx|JqdfM>^=r zrF_q5SG~Fo%>2~}w3F{If`@BzDf}MqWAvTiqSDW2_`UPQ#Fp>Vc=z(v!u4gbiN8ojy_#6G6jts9$qiNC_dBs!6x7iSSQyCb z2{I}?nffY{p>VBIOY_A*ML~FZXNkz9mcC|{lHlZoKw+8uJy!3TnDFrv_W-iKXgr9< zA+JH+p_@~&SUK~+5p0(B(D17JTWEoLmVG>r{PgJi=8WCSS9`{j6&CgpvtBh0Pn_ai z>)Ss9Yqs^aoLR2z?;0fjmpOXE;Y(tY@$#EGM_{e$8I4biAFV&FRfJpd6}@ZXfd5!Z z)D2P+bUB0VQ_Ts7SHD&z0^M+P^g#3Sh%fVaoFZ@w&2z@BBzeD~sIDGkS+y%5zO(5~ z3cdNU+28#`8>*x6%SLZG3V|K-HN#YFlZBY~D^wA3SWn!(>0xwEkTfKycfnO65sO|s z^yP8fN%q_fRH@4y!ozX~Yg-Dlef6M+&p5u6@N&=g91+XkHLAVwI}L9+ou9Bl*|u7+ zHJoA2DcDV_m>E8RhLL&>xArh5+zyuP7n_%9$T|JtSg#?`ihWD@tXqKVcdC`yezASY z=lpQCB&~bno4`s9f*Y;YX)jj`Pq%cfT=)7GY^>f}di?5bxQ(|*$)F_(onff; zr3CB@@s{bv@5cN1n}wAt*t5DvX?4Ie!2h1P;7$5c`By+>Qn${fe+o640N{e4ls6sR ztW%Y1Ivqu_XHK+tn=9?6_ndcI2c#(pUdu|RIu@&!FnIDTP*cXAVF(&>GzDu7@!Q8i zaVRcg1R0cRrxvAM*RRi!CHZ4mb?XJofUjm$d*BWooP~~Z&?O7kR=uQ@B>c2wZ%#zC z?SWuL{_k|m!cd9hWZ#Hx)>t;a+EZqqFj|W=Y5)~d8k(J}m~V2z^gL&M#@Fm2ym zO-vH6GM9(i@lq{Wa3o);yhgedor3LY;`W9V8NQ2?>rTJ+#KYl%M_BQ_tgr@;9FYoM zWucA)LruZL%%3^te6%UdaSv=px;35_Jp46XrB75hr+Q-USNI^}UfJuXJ?AO4SY!j* z<(TM_Dw5M{mueMf;2hkLdN?2Zh}jv@{2-u=u%HelC`{r=EddfUp)Z}6+lfjxx5wBkl` zzKSd@#9_OK-Ik^RB5s!37;59*Z}9CnNw@qrX~R|pxuX!i%Uvm);>O1N6yJvGa$6jR z>Ln{m@c^N5O8}@dhL*7@Rn zB2s#T-u7ei;oK$VczVtBZ}5T}FDIxLME<^fzJh^%mT#4gLyBt zhXtudbHdS1_iHD9&XVGXJeq8zd^7b>l%ot2mH8FhxKH=Bb}KZ^YpmAx4o;_Jb6P$y zcuM!O)JQS0z4UwIH>u<}-q@7v{Bv&m;i_<28f$AA+a{0lSfqngPm+BJ&ra7w&XYEtrq(kqLEM&->-S}2TLeAXur;Pk} zsZ+r;jwUp*DkbE(WgiM;^MerhYC+WJHfa32nS!Wt>urQ1{?p(xgE3u6orISK!~y*` zU_ETL`<%G78No%X{xyKim;TIS(#estpgnet*Mjnn@_x$oh-lnD<<_+YHc1m^i3dyn z^tj!VW1I#mjY}i>Yx)H@?waO?$I=YpV0G@*^dWRScyLuUKGSI+1oP3#h$ki&Tg(_h zW{foQtI}j^*8BaMm)A9o zmpA1Hs?vqo&Ij+8VG8Z%tt=W1YwYU{4Vsl2LsQyTzRyODF+4ZR5Zj+Is5LOVS{1B2 z;C$0|t!VK0V>0L50PRO~!~NltE%E{*9uEVFX=dtRR(sRYyGn?Al!GS+9MlurXNBnv zE|9hQxc|f6Uq?mVt$)C%K(+GBz(gWpsn;6h3>eXhd?u3t*Z>PYWdm_wXG)IydC6?IY{9q~bL@@qWsG@5e3hWPA%8E23{VycdBC2#d5|AXaxhuw1jfGklKU($U7~3Z!*_$!P73 z62&?G4_iYpL#oc1VgaO5{mYry>T#Xd24oPO$4J)2qEE&b;gks}Xc>PfbDBFn9bpg; zdebg(?8}H9YCo{1Qo^F#JWuXuf8DWSZYX_pvLe97wG?ECx=aH$3i&s1ovYA@M>mSM zj0#gVK#8wl;Dy|S6{R5kwpRAxRbp?XJX0d;l)(PBm04Kp%$0%*wln40cZWexee|GX zZ>P$Eef&hV>Sr258Oq)*uO+kUYv=d<5-<3Xc!(fk;D`4o?e-?*q=tC6@;|~woHo{G z%tEtSB?|qsE#G-&Q;r;+;oXnc7F+q&+lTh|DtVIr_>zm6gxykyp%<>uP0Q$;nZS)@ zjSid<+qi*mRi-xFH!tmW5h7$ng4?>k(k~6M+TTe)E<1}4uyxp|v9DRVr+D;S+qehO zNtPioU7s;7X1#F8NA1a&R~GC*XMpcF>rgC!&yf}y_=s-c{N+^r&7$efGcX%)?tMLB z1(y-D_T~3DPGWdlMR>P4jdF$jCkBWHespH2gR_?NgeGs%RDO6gPK9ypK@l6$M4e(= za+BJ+6~3NuRH_Yh1#){4G&!OA^*_V!rmt*DCIoRx(Crq5ZXZLIg#$nsZh88J#jo;? z+ae|mhnnbm`S4vL;(z7Z$ED5~g?_S8KUtJjMsxIV%V%%~Sxf#gcIK+suw{wh#&)h* zRBx8!+I>Xda!Egjlxse@w*8&MtyJwVSAm}kEEtr98#8K)k0KObUNuEaQ$^-XJkZ1w zkvuJC?KJ;ZkP&{{a`mL6IOJhiKT1Jff8?`vjn{+Klr2P?R!ME(<)gx^_V4gbWt&(N z4ad7kY^A|w2}N!zFny850;hbP@eFNL{ls`^kBc0C%G*ywNA?r*ogC~$LiRTN5& zqM@}}4)>N#1pCGKm$^F^6+<8G-@W9O+_6q+_IUIaq-*EXH6jw6L4jSdbUxH_z#B>z z0sAFoQVL6>^2MUw4pbknXhB*|K8>BVO~I9c(f%U?<$STr)_(IJ@9P|u4f8H)N9>91 zv#YeoZFJ;GX8=z-xKgW(uGq`;pA-iHZNnq6axap6TAf7*TzI4I))5NG_o92?MIQ8>r(NGTS7^lNeyyFWV(`lqOK$CB#WAtTE z8Nr@TnPju!IGf2*9nANLM~Mti2ju*z@g*A0g{&rwH=O!;vbReqC z*FPa`?~%w9`W?m(UT1|Y^9NShAC~hilGMqwNdTNh{_|_|InTCpUa|_}V<3>+XSFx$ zvf(5F7|cUFLMoJKw{BP_PepNNOl+cv*hI<#)$p#TQ%abLk*RZZo^$x&8eQGxf(+TH zY9jth4{>e|F5-)}v~iYI9k!#@a*SrzU7Ym%QL<5r?(=S01dG@=I0s8BV^wW#Of(+s00l#=4QZxc@?~?EOr8PeTuYZf~vr zNPBVv#FURL%FOd%t~3pd0Q#xk-DBanud+ z-byCsXsP)8yEML8icTIHk*2zEq+~r!P@aU#N?*^x-s9@@Iq=1S88g+Vfepu}8TWAL z2hDV;K{VClk^_V5e6niiwRw#&b&7P2uui+6@9aJrXC+DS`0~b{t|E7hKMtL@jN1vD z?awB75F~QsX!RNS50*@D+=ynxf*qny_=uVSxCel`Si1$igmN8G-x>DQMND<@q&Zuc zHEh_6LxyNyZ5S0afWR`l_-WzjgJHFL(%^j?;3^(3kf8TCpXuD7w*0J#I-{U-$9yw? z^*+N$xVl&7sfkL%ai=4dxE6>ci^X<^;x*BVfQp_yJC%wB&G$8OsDiN-8zJ^J#MQVG z%OV8BVXO2|g@ChudE$9Ls1V#NW!_VlnZe@7VTcvpn)rj^S1&xM-c+3>reN`-UHChl zO(s2i^gZ_0Y*1ki-+;jgN+K52^sd-6_X?mDl~t4do`@wwck48dbT5y$(p9`Wd_7v+ zK)MCt-ta%%PVc4PWlS#r6lG%4@ip9ecc;%RKRfs8P-}a~v&A)6{;)g#3@a54Y39|& zuSiC#%(?HDz%v_K3$lY7w=eRlhQfmRzwhUaW$-ze0OU*NsZJs+cQ@r}ulG0n`)O}{ zJryMSHd=E?MhzSLwlvKM7vnU?wD7ggBA)m zN1384R+Y8d}ra zO=#`&?AWU%T6$^K-H~~LHy_|LcePtSy9^W1uRII6%QI8km)`bXeaPBoWB9&4G*u;EWG(QeUPaemJ+Y{R8> z&zB#!%*D`=P+H*a8{kv=@^?#c2{IH=x0a1Q+Bbgf-GK8gm$ya|%-@xBaxkJ}qaOOw z(zE7-yXEO08LT+)`DtxS#!k%H@siV5hchw8ExuB(B^F&H?yBp z%-)Jl2*|>K40eB2jL0FKYwXlHYXRrnHF#)+IHJ{K3X8OPJW7b~nW)WMsNpyg&o}$eH*hJTc8j!0v+OS7gGFzv}M-SR7 z;D)7T6@DM?3zQY~j1V&H)SR$!iPbKMR2M(ePCODi7yV|{T};*oKHz*&o0mu1#qn|V zKFiG<5$mPIV@-YXDkpL1JxKMO|BmghleW_tx`Lckodox6HzGaHV~%KV?#=ZtwwXfG z3q(kK-&Fe0Fg4*AThN5&o)$0vWt=QXxi&qf=gOxGg$z<*YCG#w!v!Tx;iFeK11uxp zt2F@2vVvSe1oHV3JbSKQ{}~1CN;P!~g&`WBEem*wH0GwZ%0VRML&;)7@GqDaH`LjO zu{57@=GQ>v3~^e@^lTKftL-NpkPKugBhsl_MMxQ+h&1hlGK{==CmpPu7H(b zLASz|i1mdpELWdd_(Dzw)f_B1Sjj9bn_0S$UiMjV4tXX0Y3yt31gLd2YPwsu^yRD3 z=peTZ!$eitipD>+z)<<$H+0s@z(C$wHEghM#!eZi5t|csp|D9 zN)zqICbg&;$*c0+IHx@2tgCNAOW;=%o?OaHy!gWb!X04Jr9>iJR_H>7{%}iRhU8ff zKjrT`<(|B*lwc)IIVNhDJ;UiJ97=d4QE0A$Vx(|2`%(#dS?L;_EWsF;(pGO^ee`3< zBL+KZ>PdKYI_l+#tE*YB;R0WtwpnqMk`cM5;9u)X8sp+l$H|yIU8qGGGc}maaIm~y zy|l5=(YrNj7??k1v_}1R+c$`vC{Ba*pJI*vW3M;!0S+bY7pbhVHDcAd*dWh}`Ozdz zZfUVk*1nuHZZ=QjMeDUX+C{Wy?3ZcOd2(I^^4)CXrX|sOy#N^_>`P%6*qTJ$HEo97 zir{gam%vdo>GEx|I(7qHJlH7cN5aJ%eT)|v4yZVuR?5^cdbV8H7VA6)QKx`BS(WLz zXxm@z13}sml_a*}rr_V;K27|cjrfchqQCS_K1^x!!u^+{r37oK-!ZGcqW@*IeR2-n z-#if5|FCBZp{1!7x;s;S`B;hhgxmP#tDH}r5T;kKFx|ht)nUK1Jrm~&dWy+ZL3shT zkP4TGysh7xXjuR3Vf-wv%f6BK!Ol#a(%13n6y0bj15@QDd@{YSMsRNPXm7oJ@m2ko zfAn4jX4a(L_glh$p1`l|-q?-x4A+Epl5cz%!23WZ1tz$UCzb*3EQ0Wgr zlG7Vc?k;jni?HI*%ixAfK#mL}o-Ny+7A(ojJJ=d=)|~!P6#l-_ydo=`j}Tc@MuV=H@0}lPl7hCS*>;)tzjEB# zQHHs1_7y0&7Z2JZm2Pz$T{szeZqM^zX4i*p$m`I^g>%WG# zTrwEweM)5yH;i4~jJ(f$A{P3uMh_XOMM<{wrwi+0Ylp^t0!{Opma_X1{KrW1FNu-g z2L$pNjS&1(fZi(rODjfeKo%klAnD>QT3x!0YK9c^E)A6q`<|>Or{f~tRU)2Un+`05snCmQwp-!?Sl4_|btHMUyd2}NhR<;>@ zioPOCMb}E(vEFu2mmi%)5qtelQwy?&^I+`o z?~~r>vOgV(80MhB`tpNAygi3Qw9=RHX+)DO1a`35^hq$0laRqb*0I88QR5w}kj=xsXBLCS@nS7YizB1xM>tro>B*j!36me6zJge82sjnJ0V3 zhjxe`UZMz*9#$nDKE!SP#$^8F>rv%d%q0}&8QSfg`ipb-1lwu+DDQ;ngy!*&DT?lxo(hq@liyJX?SUHzp2(1MrRbL{N8j z8To|B_OtsN!$&IttjmOCekD{KqqnWlj-sz-jQs5$cEG+$HH;!=yt-n4=?`W`o+dd@ zVTsan-1N5#AxkTTFqqgZ>D$WZI|ol|_Bm&RJ_`Zf1Gg(luA2;g3>)uOMZD|?v?o)LNZ7sBGsKlbaMNk4 zwlAp3dJlAy+4uGk-zZrr4#_texr*PLe8H9Zu@%y9&vfhHC|nOd0qe|0^xVr+i(T5q zqiogdpG7W$0KK5%a2F|OTYyv^sN>5o8uYMSZ{9|`;qU>#Je2_Q7DZ|R1^Ffa^mmc! z2GwEZ)fbH$j!Ut4M;vpnSQYzgjAN~QG_4QkB$4>lk3gGL4jtJogm;(0KYG}=A=OXhpFCNFxnkXe z_+14LP+(YZCZhZ3P^HkjKG;+(xqKMC;soU# z;^sCgj*Hi+m8_@L4HVpb6aB$NXY!kP+}CI(X>_!deOh+?>*&D}A69RIW^ZsJe&TE4 zloU?k(PdaL+$HtR<1PfRL0%7PVKBj)#&-2kvV_8>X=$r{qK#38hzVNJv!zMOx!UEb zvYnK_!dFSge%K)Q#2)!opTzdwZbh~`YvjhPU2fT7?;cAy`f?lJ(misewLnw}WHr%f zFILhmx@J>WXwJ2FalY7s^kPdK*PbppcZc(ma+YCn3UNzKkYLCgN!?2N;bQ)k!m`bU zj=OTCp@2)ui8>JU1Nz|RGkAZu4%a;efTWvdW{lg#5{_rw%_)AvH-Ub2hLy`867VBJynPvWHR$_tO8fs8M zDl&_GLx{oRKi_!(u%T-ZpTgC}XNf1OX}8q5{k}UZyq*m0Q?_|!a@Ydgq%6Pb=aNkJ zcW_Z|vmU_<*K-8`aXxFj~l#l(l?+7x`-Eio(^a=>Z9={;bbazu?!+bu3tdKE$FW_;{ml zR_WaIoXwRx$>OoB4EW!-bv)h>%TV?pXbQ5P$BFgG#yV~3JB~+^4;MR>r3BJZ;Bjj? zOtF_3RYG~?u0<&+R2m*J`{iuc$1V1N(xf|;n$CEt7D8rC-gjg9VDVq5NziZd*!0h6`LHYfA0Vo3-Ih4=D*ay=%RX#A=CWZVc+$*o&AICHg zrmO~=uQ*ebd1@Xx5}L$1!uf>?((^>Qhgy~G;i26n+tg{A3l%=pb2#+yMT-v7jG_CP z6Gf=rgk_ce2L~|UfU4X$MkF}%)sEr9L`0C>X2bOOb~k-^Bc*gE z*HT#<05UjK{P{7dEXnJ$(Vmh<{pq=BH3_n4PU0k84P(ub+ZS?g*cO}cSBQn)$t*>L z5L}r38lbI9&I6HA*d*ccxa)~7`Q|}0^w!liZ{>F7$PpCs`p3VDRq2$$q7Q=^74$ES zdTx}rdc4|yG0ZAG&Q^TGQ}b4NPCk{aSliq(OLd5++T8t@e&FbMFAk&h}lPSInd$BC;Vd(lrCW<2WHmc-3QfUZUlkt4T2w2rdpHaFc8_EJVaTAM)!Kzo_TM-s8M43NP~id=Rkj!|ApL`lgk z-!Z4T6o-c^D71fAc>GQoOgyHeiD71DX{UhPZ_GU5_5nw?$9va?<7Lma{WrQg$)G1= zvH4lRX70E;1i#}wuQ3yiU2?vWgQ&pDo8lJDt0FXm1p&*jXmh1&u`?^F_>%4^M>dGh z_~*Cv2`s6U)a5^y^PzhbuY7VGRah>^p`*vMZoO<^apzFeY#(M<;staf@y=QIGx)61 zw8MR@W?v(<8Ok;HC)#@R(Py8%)Q?MrdlKbIV>+0kEH+8W2SB41N!G+lYNP1Ecm1(M zI?by(TX`4F!cyWu346I*!*GbNzXiRZUktMn5!#!bXdAw+yUozWC(0!kszcJM(Dm{r zWmqlHNK3s<_jIehIu|7;whELnuT3BuWN65Y3ds>0-V&3hW^EB_x}nBWI;OtO*LyE7 ziX~!9onl^+=VnV8k)Y9pS1((OZ!L{L!~S_BLPooywz5=5f$B& zAnHClG}3`@<&r#z*Y$@TCRT~YwAHj^-D*1qwqv++HR&~9IE1DKkLgy1eTt@SL(v+a zu8v-J<*m$MF#*&lKcy`I!@9YXeR1fF$2Mx<#Aa?k#QTf1KDc2n(?LRfR;vp(RytZS z-ADy9>WrgCXo2mwC9d{MsKsD{*0TZ3sNufEF?EvD3SC=y!y0N`w!8!6+RhV7R|E^A zmsIkfH1;@eo^R=X&!n!LIT>csTmISkaLUQfwFJf%4R^zIxLbIfKzV}Zt62v*LV88d$5`v-lsNYJ$He=AF${G+p_07vOF zGGPYgilHTBfM~IgMZh8i{8Z;7#5Fnj0SJw%@Q&iF$c2swCySuUF(6 z6;a!q2Akj81+p9c&)QMdbo>Q>M4V^S*)UmUsB+ZI?c5REwp=k`z^0BcEi5d_($!a#e7qEIyr+_NEA7omOrk?rlrR?wzX3gr z4+>dqFx2kVB)_MydLumLn!sNT^h+7&;nh3%IJ1S9;)M*Olpv3R z_mX)QAqJ5S6U+MMGkWySYkv*dKtj<#LRMU?&$~BWf@=m1&wla_k@h2GD-E?5gPs=s z7Ob6UwU17AHW>iT>bc9VLyY_CnvB$8(=!ZGNn_AK6DtMznG=}Us)X+FtOy8e7B zj73P#NEFJsR>aSEX~(JmZcaeDOo~aD8`)Y=zk_kT3U2omm=ljy&qzw~`ea8J638v8zcm*d2*3QH^|b%6oy8nbT-+@ztyFnjP=J z>dNngyo8`-Xs4b1wylI+TJZtG+xN3G^_g>&eHAqz-h7+aloDlOw#2AfMmtu#xu8Ws zNN#N`Fc*WK8K^-T43x@My!-57$Gs8YsWOn$Nj9eU463(Sb7ku}$+AQb299H)PDpr> z1H->&vwXi9653!M1G+mr{7Lwp^mKwwF8?@T6g(t)&{LTTefT>!Bm)strzZe!j#?caoIZaPgXMx zf*!}>fuhr5DMJ=nEfJe9OI2-#R=zICB6^faVO=tJ5iP8ympmkC?W&id37njlmUE@{ zOqSlwR$4(t9qKMFW9u7ZGicG9th=&mdgjq z0CGgWK*zwM8`XDJ*Oow2>>vS0g|7MIvG9UKS6xUjeg}$IN}ku!*>;3xjGyqsVG{4T*AM#O{b7iKl#crdZ^%0>UqsAa zNslidXXkqH$QIDTB3M>|mMZ^NYPIQS8bmJp-O=Wl3BINP$4I@i?|ane>(&1z^ER#6K3*I}AJI9W4t6>kKc>O(FO@QtEWj}9t^x}IFn~+!ZEXx3}XoN!J!Zq~C>E1)THt_l9 z3hAHSjIj&$(X{Y8_QJ^7P0W@-oM9xJlHKVdiohos`>L60%7=}fQe zMifY6qHiB)@p6EDQut-v#fcCn#V)fe#JHlYHGu~)Y?(`wo~)e{8mH(f5fatpUv?VV zT<%dqS`;=vDzZEIThRoksP4sX?S!L-4XUl~_PAI^DuJvq{2=?cTQx8k)+bSbTN&AZ zx+nX)p>X?%TP0lkfy+6>ld0p(9wC)^+k+!G()RhwM3Dlwtr5JqLi?f%l1ZT;+Utba z%1?QD(>sE8dnIcmzN-@rt|+Cr+r?4Pp0r>7+@q&7{gb*(DED#%=Xdk#Z7`J<`b8(A zv@FFDc<}J;MKMeZ8_4(Fm9<>!>qc!04p1PEXz=)4vg!eUHCqJkSs2Y+uK`_o(z@O? z2xiJdOz^Tb(->-73EFJB(&h_AxfKIF7ZuX9(QlxskzGRvHFThd)Zni^(zN1t)XHMW zT}(G(6xGBUp__9SBJ%*4X|*Z;O4UVdcA86=|u0~rr4 zlq6XJ6LI!t+Mlu$TB`^3S)>(5*>r15>k<_*0Fp*Bzb`TLAn*@~CssjXf|jK$&Niao zfISs2ToNVu9}n5jOT7vX*RpRiqvRYE$^$KS*1(l17Cp)^RumPXS)A%s=NO5D>u3z; zq#bN`1;0{5xLwTnaf$_CV&yV4eH_a#(Nxj*Y?Qcfw7^-fN0CwPquPX&N)-4}B444* zmm%-ZB0(wdIbqZYF%jz0nbW)HX$`Hk9ERC5uljkquxPuuzp{a8i-bF28Vd#?${Knz zaW=svM?2x8D!E&{wM{7wt@yso5)&e{U^^@#gH748x^07!yEmf*10|}AE`&Uy*ZooH zbuX_>iYm`$p}}Nml`6yX(QBsj9mxbbHFyUrG>~is=wtS^{f<2Ia`hjcNo%d3b?e-z zTi(c?avK+nmw50I9Z6dpW}@?$jnE(7EkFzTqHynXBSO7|^(NA^3_|i|zQ{O<#RXB6 z5a*2PH1xgCUGauew4H!{&aQ$Kg{m7qK={=%O8Jl`_#%r_>q_ak7 z!3{-j>z>$K-#@TEo(i8L`;8eO{qMX5N(p%tZ>WWSuO$epxrxU{yr8d>wLy_yx(7CP zW$a$t6DMU26Mq;$Bppgu71lqd-46`G8?ZmiOI)D`A0pkaUk~3JV~RuGv6`-PJL^jQ zrRuVa);QSfb8pS5`(b8EyC+{yPshRL{)&u$2$1m3X}cU`@T|0VK?2(+hHVGF zk$jNPf6t4t`R1z+y~@x-J!du-<7+j#tc(Yj8P!*-ucHe=$$hCXDGhnJx2Ov?302XA z(;0|AbdM~!(D1BBgj7t?=&=kcFx}-n4J9P2Ux4!I6ln6uD@hu&RBU(*R??HcXCpIw zfPqWHd(AILFPHS0E!zw;6>F|HJ;k)gE`fGCtETz-m=LeQIx5&Kt=CCfdzMPeABT=b z_U7fNgkguh#r{Oc&jw0@@YEn}_3W2l33|4tChZjc-IG`urOi!j}R`>;7KeU-9yp;=~yIc={Qw(5fXBwu9+{}ROxC%#LbKh9NMU^1$h zcwv9uk0OJb~F;V47P-d|%znxJDc>JsoGSgTV3ZVQdYVa11Ur&vwQRudsCr+R%K z>8uPASdG5ZPIDlSdy#JvGeySUyp!-+u`KO~zdl-9vrkrNhr;#j@l7Xx6=|}2F;$`k zt*5cXzl*|aauom@_m(%E*c(qX-%n0P=F0JpVA_v(%ThtBA{5?gTafGOn#xzzpwKQ7 z%GwRWo7AV`d$$fIR%+^z{=4804O1O8b^sB}+s^-QHVr=_c&uq@m!X>unZ)23xaa&7lR@rd>Vmu z*R)4B!A>6qVS^v&{D0c7RwP4UvJ$*&?3kYf7JjvkO^yYOPyZ>3Gy2-dM zu*m(-BGe!wz`kLQqV^B|$VBWB!q4Crw+51AQHiPAZB)iQ~UyaLxyY>)4X)7r*sB2y78+d=TT`~Gp3pUd{=k@f~AJI?5l z7B!xt>nzZ5^6qRN45&Tqd^EAve$Qouk;;4$F2>v*Vyr^EWY_*(Qh_I!WBs(aVuoJe zum>+W+?=Pi{y>pr(ukd3{<4(0ppiwvw7GhaIs&-gK*tgN!$9kQg z7wh3Lj&<~j0a?76IvnTrJ^ae;lo=tTK~ps6`DfcZhX_!I(iEkDS%GxlC8wn4KHP`a zyXUd2{~HOy#7cKhgLSY)*X^Pzh+jgHbwNBAa$1)tX9mo+bsA~VgMO++C6aqfxg`X2 z9;j!-u1hWG#6I-bZNX&ys+oSP9~791f>}>V;uB7)1NC!^Lt$?eF#z6|OM&ps)JJ}F z)65#;XaWZp>m|V|>mmH=S)0yweo(Xjy{gu$1VTlV1-2&CAH5e6m$uEmRYCiMwL$qk zR~6K$%_!HOE0C@hXAd75)_~d(8t|YjCAaKy1hxVNj<+ z<)X@3Huu}_ms*ghur~DF8fE(SyRiXEL*fp~^UsC#|HD-em4nyg;~`1YnnPV+1ESHy znF!XR_CH7q`Z}x$KzVsMi%vZ74;{peUR2pwahPLXuBk)kyzVi4e{by7y-$pUCP>is zuROW;!u=2JJbP7s9aCl;`6&2zW8<$nt4UrZa>ZFM#^HQ}l^^Bw^z=8)j3I}GsmRt- zfAXA|IR-P%%tD>Q-&;$54OGhrdOEoGn}d3Yau6*G$TJIB+NOJY)&D-5|D))M8Ofxy zvN4nmhSBW(GgK;{e4?|~>YGmf+q{LB!AvawxPs?*2|Z5Lcts3BdpPLu{sTdOt>D;9 zCqYzk!|qP+|2-tOdjHpBp5z0LKRsBtSUonze;W7aXaAf2e{8G33j6=4|KG&uf5P)W z;rV5k{%3jq%}f2F4RECYv-`jKspCEoeDOcw`TtgUDvwT`IB|5;Xji9u;)L)C%m(_! zVY>+GK6|El^Xr`7gHE5jB>kL(Md6bBV=l=L5>p=~8p8B(y*6!%O-2pvoU{7&?rCU` zYOWa5WRfm!s$FMLb<Vzgl6EgD=y&xpL<7G7{mP^4;h^FGV=M7Cc)m z{YQ$_f8*l61|p_dqx$EioXv{>IJPh8koCEL<|Gci%c+0np&Qv{VhW?LZ=!GgGbe?0 zYRvz6DOcN{92y#$y`8tn zzX{|Aq;H$y*FzSc={)Dud!=`SZxD&z`AGGfXy{DiGVYmkKManv>pS(6An_fzr^P7C z-qgwcTzkYdxB2(qw+=PGmbqTFO%~$Edk%edLrh%UFx4>Yw>7&RT!fmK__hXYMcgUj zpWd*pAKGtAZ)AHb&PsCO*Ms3eOyHciLuTm9KZytahr zr|7kcp;|XT_Jtgo---kj^P^o%g^#(A+_wpZ3$P1Udkn0SC_XIe=bzo2 zF+^%X?oJdfx~fpO9C{CSu!YsEGoa9$sVjdoAN)W5Ee_S)&AK}aclFsGBWi;NgifoJ z#*0If-`d>1@l)A_%K#7N8M3so@4Zj^z@P|yDe}+R5`&&%D#?#=Z<8Fi4Ak+$7bzu? zUEolvH>PPF-Razxuj6Uye@Z-e5YW@hq+N_n!~Ed7|n;JVae;|#<=QH`S?*~r%WIz$< zmBujEkxL@g^cK6`Y)K_)xuzmKw7(5~?*xX@uYPp!bPROFW-t~pPj5Bn@U)z~=kWF? z+$QeEO!GP_fSW z>q-UAY^QRQ;qZUq6qJU-=^A6 zG3HdKLxj+&h0wqZB9;Nxd#Od zXS_UN;<-Yvmyc_su=`mOWT&-_ZH?CwB=eMZn} zpUUri^gy%W$v+NB`v*Xmnt0sps1dROS@=#?ZmEH{IrD!-Em-@1IvHN`ia zW+d=SX0ZhX8IYFo`YAfXI($HOx)dzI$-sY&8GjD&J}NskHIvR{v7JzHsC49+7@~|xU(>p@h!5@0z1p`=GZZUvXHI8ee*tJI~0t+Nb zV50VmV&Fx@BY?r^AtTjl)_;IyYU05Ri>8$^MV2zstuGkqoujhK! z+=EDDQd;f{wPKO#YAykROE4I$W4PyjhT+h02|0-~0j5^xcn@nz^NIoI(vEPNW|Ji8T4xkJ2)W?jyF$+Exx`_ilN|4h(lWw8|W3)zxfuz^eie z`kzDurvroV73Xh~cC&G=6RGOxajWa<9pTXP>bnKe*na}Dw}EFecx)u zZ?AN_5VOF6-xth%J~zI@W!JjMLPtYQ8IZ6j=jf>3JipwyLUrYew_&fD-{GOA#YRvQ zYujhLKtDa?s&$^Yvhs{CI-o9UhPSRY=G0fyhBqpuFGoH&LtKLpC`l{n7csncw$$ZL z3R@!q^Xhdpa=qxvAMyfa1|rsWc6B~ezDawvT%<%PU(2)Y)qCa4Z)$Q2g&78P!OD<( zFS@2jX4|Iobq+r|nOzg<%H+yZY!`E)eQ+Q-#f`#EB-UFql!gJ)WF&Bj=VgK zw4Y5VRC03J8B~9c>Mh^jxJ*~fomsw&5YSU_ave#N^$w45&~Vu$(%v_FkZG@aVyevC z9;SgRLq2apEY)W07&}c;#ZGf;K79pA@4*LGpGPHHwSBMVup2=`hd@<}>*-W~Z*N$|or7JqAGiG;fmDJ!t|5biFegudb*)&ZXpdg^em;FLAWBjIji-GupEm_)dH?^n`)Yg zN7NyLt|O|S>zZWm+YTv<>fG2Ij>Q#9iCO>~Fs{%HJYf)WU5vD7Q;z%iviTyHD)dIi ztMwl9;o`ovPpd6>qb?7VSG|t~pTf>SndT=lm9cA51=gTZ?aBmJO`5ZXb5Dz9mh3FQ zTA!P-%E&G#;iv6-)pcJ<`8yFTOf(g@ zwFzGw5U7ujG4(!H>!HslL2R#<+@dWgld%DZ=!U!@7SB+jWXly|dG(bQ8El|S7A%o* z7BzEeY$IZOpbXxS<+AEOp@c7~-lk#SBD15?NkG;b7k!`hid0U9 zY48EP+=FoQ;gE8EgDKs$>Ao^n8slTOs{0{uHy37$Z~QbeA3%tcTvN-%{gb?v()iq< z**#ZTlf1f`-d<&Vg3jTEwSlhxd>Fzmrqs_A7^kC%}V(qPl%aj2yN;G*v*eZOxi~Du!qm` zy8DD&rgoiZ=LY#X1bKIZMkkj6&9p|35 z8S?#O-d?x`D4MZY2G$)4i-5?C`*Gy?V65?&#f`eg8LS9*r!(?+pR4Wiw49-_CR7ZL zD=sEBaYuRiLX^{dwK@FIVQ6ipVx!E-B#h+U_T*GJq&)3{pT=6N@AHQUOJG^f!jk2i z6rG2|VF&9I{I0PT&s{}G0}YVnL#s(~Q*9|3W}OHDQMTP!*7Lzi7bMxBkyPkogAWA;!t!;d1dQxdz{y-SuXINsRiOq z<2FRrXU_>6!vSN-nF}1porMK#+TtdL!8`JNu5kSHpg)MuVN_tPXCa5PS_PUAWiaw_ zV4(MA)Afu(E(_5>SQ-ENl7Y|Ov-dCHN~WKJ%a3OFwBlguci1ZO`8d}X=oW14^7Zz#+|bh+gb{a)8#&db)UC4JHG1N(5tV^K`M5b#q6C`(>!z%+mf zKFg}6#eXVd#G`mEw;*8OG!eJ!Bp$#q;>(p*V&ZcVY^*qFt{1X4N?w96ni%E#dC_TK zZcBH*cGql>tS8Og+Mq2tBO<%_;fvV%v^q(g6$Y`UM-_`|UX zW4mz+aoPRB`#)!mnJW(n;=Y{BxrKGYgf~FAFI;I9Iv-S>ibibIDwo?!xwsClPd@9?h`EkSvV2rKUpQeHsD#5hQ#Sv>$v28bMe^E* z?yZ@aol_i#khIG0K>n!$v$Ueo4*PIYi#d<1R9Z2Y{U7vlGi>jZL)6ZQ!3$2QmFwx2 zqS7%xD1DW^zd8E+6Hi$SLB%V zR^91F$pZzxGFG^b?ccYsM?8_}@bnUYK9lLTpJ%w04mCGtD~CHBZj6YJFXPd+wFTav z&whof&1wuhVj##gb>%8t&y)h@_=38IeadcpL6#6m#dGWm>JxFT*tC0CIoI2?%dYL( z1+;)3=;Feh3|alF1K;xdj<|aTD!3{Xn<~G92y%ZSJgaR_=0U~!p%g1ywqhU$&F3F- zHPG_J<{?uPT5L>+i4z9_tld4L5%_D7;QfapzB+735%Ca{E%d_rsgWWIK#WDRu_!T&St; znzfWTH!ZaKK-j{`MZODlkqHRxH#moy0If-ut=L_nt0frN68iEfQ z>N#`<#9cKQ7g;f?eO%|2fQ}-89XMTbgrj!IP0P58te$zJ(zv26LC??=f z*UBv~Uzp*W?h zI~_4XfgK$kg5_!Dt5K#lLE#mJ#S#|I&{y}$ty@|;3SJmm70fr9na8hXR zOlN#`=6E4}GMFh=E1W2!*Da`fZaTwxEo*>6d`rRIo2`Z*tJ++W1HB|)h@2T%hbc0@}t3q zcQ_hgvRo%yYNsTHj>ddPTSf(4&E%Z6hsos}+OSU672Vh+_s*(S;ESa;KEerI zSF#RKhKpR$)QqwCcAulAK2ixLx%7!CqcMw=XeDiBq#XF&9^UDKEIv#7(y2{D(m`}&`0$uTCa(XRH}t|{_kw7KI|t$qQ7pp1o}^DXt#tF1yac`9F>EH?G) zk4rcvI<5Or{7b?$!23zu+X7hgDt+$5HO{Ba>>h-7^;~xm=o$6ajpkTVU-DMpq?`=> ztpeE6a1fq2nZd&#T-1#8-dbK+OBjql2c~E%W=B?|k^^-q7i`VbmQSMMh0Qe;AXN)> zWRp)k85qS?IW9IUiA6?doXurUdolP#96J#V40Q-ZY%|O4A{Lu!1h)TaiZKNN z)~k8q=;Ql!zZ@*arYe|U3O8Y(8q+zMk3U6~^9uk6l5gI^ia?Y$SmTa~spl~|5T}v> zKhyhC8XKq{$9JHZtdESn)Ce200`uOU1186=?r<54^+^L9>Nbn7FV-whlY^k=kTUw( zF=uuf4%{%Dhx*qz$Kf3{4B911V169<$V&&}+!QuagB9@*ur}$&aV**!zk~7X6?Fy@ z*m+|tv@w{jG2!2AJ_fwGkzv5Dj;iRp$EL*&GXKt;PrMdbrYD27h2#`s2Zg$T0jIOR zUcpij-Q3*v+a^p9 zlOZlsM)llBlP%c7)L)SYJ2R)MPI5*DJHP|g<*Pqng$bl1f7faM#8ENIqlWQ+`cmfO zSfR#Xn2h=sL0BiS53p^$moGWBbtk_X^3H@Hsw7Z-Bj0C8wD>dEy?gIU;br!`U@~1x&IL8IQUB^pikVKam7H55`BMVZYZ}cywL3@+5WZM z3o7v$8L+rEGBkjrLmCOO6bZxNjbFe?(?2y!r$E>ST%QVMc3JE8+;3`7qPTc|U}^f@ z@xlDB%D;UKuU9)Q1~4IeYg^mtG{5AP49=$+lUQV`9aAjGcxG}3TcGi~4Ctn4E_r8} zk?H5N|MkRnYaB$fQE_k-@y{9jcnu`w!n+m`>=f(BCDJ^T+a=UAAL}HqEf}3S{{M(f zP{5J|&+idsRQJ~_Ua_S6InHb031Ggs&6fPIrun5j&NEywMr81GJl{Ge_Gf>s?8Bq@ z{$MekWRfY)vsiu&1M!>J!a0SlI&_Nz`FybKfL+pG=Ks&S;(hR^Mpg18ETftW0iXOX zFZ^wq!1F#~>Z$(^dtVt<)%Ny#4k{>V&=M*wU5d0Koq`fl(jX<$efB{CNkO`iR7$!- zIuvlzARsN>vB^6Zx;X0jzxRFbxMSQ8cleDBlfCAA=99lC)`MHvp5LjeU=LJYS$NGK zaNMzZftZA(g^z-a%x_~RDDCF-Oi}V1d4Ub7AHD_=Nf-e-g6HO1%grn;<7cxgzXRw% zTRsESr(yEB3iH$Bs|w`AB&4K1UMkfu?ZHH3ELT_9&K;}QEhud?sTU?{WMl*!?keXX9ngES?`%WrLMkp|wiKj9Yx5Z*C}5ct8Op@4w^2u@9nF#p!V zvA(=wSPPzeTn#uxC!@g@cplfgk8W zGE1U#PKWFJFA+{qKvRyk3tRGT$%L~I_aft)`pjCyb)N_E65K8R@hc*9Aj;OZilQ*7 zOhPX(`h8$4>w}HD6cZrk_&70KPxOcuFrcAgU-?hR5Cr_S)>H2dU)Uzd%DqXes)85U z;uBL)v^y8qN|5^|zzXa5SltSb0LC#_1xW9i)CrodzwJy|4G3wg;<3rcVl^Zq8rg>P9IP^>Vx7fvZ2b9XDGCj)qi&%leAAXa$u%nH8g$Iy}W zo(%uQKkZfllZ;+4K;=U+uXw`gq4ZF2uY*nut@E?4jIfBq!3>aYy88k;1B8fU{Neqf-_8YC@C(be7+7&-*-y^;Z#QM!k>?+ zeha#qdl*UZ)r5$GMNFY=xbV09Qep7zo*{s#{Y>Xc0#P3jl!noJ?1btdU8=}vasYpZ zNRmJX7EPsl+=GAFdJQZJlOo1|@2(MT6VneH7q{U{=Mz6azq=sgM3EoYGhEojP1MT# zWYe~|VV9_A(qq5dYxMrodr~+x4=6?mXm2t$9?kpxyB=KxbeB}nfHiBu-w?bJU%FPt z&%_aG<*csGq*-w#fcL2yG<%3W&8YW&ahcXd1go~QwAsjDc;Iv&;AC}WksslOHR$eg zXvN?RWqKN*xWMKn>`JC539Fr=>Y*M6h$W@V-We#vHrEy){R<<5?f!SURS?)bbt?K> z!ggq+n)8O`tS|FWkqS$ixvAhz(YoHq=eSmGj48-2s0jGMc0u^Bn)`slN-ZUFu$h+y zMCi>dSA#|B^#~#esJWePf^gY~FE%e1Hx`Z_nE;AUjpk_Na*Z5%TGLkcHS9v%RgEt8 z%^861?qBJATfjCC(|QeI8$(Q|Fb&Ynuht!wK1a3(i>Qd9!NIjBlDjee0Op){?mx8l zKr)P3?YuNmM_|iR^o|BEB?*Z?*n*!xxx;RU+;-_<>?y}$O-*u8kCNMT9@&q9;k7=W zZ)7XWyM$ok;siNj0JH=ZeU0oF6BE;&m>zM#O&SRIo$hGCCY;=suPEjj*xZ;%cVMUw+ z0B@UWQPzxoZ}DzeF8W#?t+a#8Yfe=RC98HG+sN9kifG4znzKu>P>1;-@-hS_p!foK z%p@z;k=EM|+7Cqy0F;Er>~_46Ihjs?ZbBzY*Wh1gk?qqU)twE&;`$Ehv)TIN{+O1Hj-AZ*{T zT~xzF$8-mNA9ChxXd9J3-x=p%*~iseV>e|gPvJ5`?5v-L?MK<%LVIysfcj~ZGvcbpP>$Lj=~*>(Pz*EPA6%Ozx8$c&W}K1r86U)!$7cTGfREO1)SUL_bEh~MY$vT@?eB*&a%2~gS4@>PT zq>>rF_lp6Zj_JFHlp1Du!$&5Q$YMRrb zeBRN`>`c(yc`;H2TVm>1dBW?Gi4ph#l8c)&l}vKH;E%!TZo7~8cbdCUn*|5$pTt>w zCseYURR|r&XKfu{QfEm84?@}29QVbx^@;JEYix=!_6CTs2LMl_$`h8uEQzs0zIDNh z)#l$a`|L1u&|q%Wk9>}@<6fWMx;r=1Viec0ob&l5`B}gFraW-52e4!;fI?4u>WpCu zZ9?YG{>%nkd6WK1c;FOBKpwbg*sl+l$_?sHDS=_-Zw?j`=_csxkFE*DnLP-=ci5pk zauP{?B#EiyvgXsac16_bih1;CrL|+xM_F5GMsp3vP1ztprTBP<)qzv4 zEYEorOQ;Ih+j+UQ>{@eCR=e{}_6Ph+dnl#Qb(R6p`*Zz8BA!~iHMM=`r#g7B6)J^(~A^2G!Raq40c%%-> zw$3qB$;X?tMHSqU+Ld884}Vn@|Hk6-&Fw~&>Vu?KfmuEPVO;$O!Z_Uu8M|yJVjS3x zjQ};gnf=!xEH1Ve>8&48XK4f#`IAskwAdo&NW!&td`zTM5+pHWl9ek%KXP`Mds`lS zY2V)k*!YCVGI8~;#9;%qJNZ{@K6@O)vC!oiOPP$wip5~->z1rVLy{SGX8i@sc$yXC z8<)mEbIQN{tYl`A|7awpWL#5kENtGg^d^ON<&El@?r<`4sQ#e!pa-J|5%S`F6!2oF zBH!13(A9OmdRYn6Bl(7q`n}1z0Zi6cg%}iCc&OAPCkqEKY2FYlOE>lCMA&Ez zzm1RY8783ItGRq#n+OrqQuLm|qHLK+z9DdV-_dP1PbtuUU5mTdebsgK)+Z3yyJlEtk$oq3)uwz-EQmEg+YI{ z8hsUP1Ax;mD)}(q_u0!hMKwG4u~_Ill#X4sJ&Y{MmShY_&eBxmNiwqAE?MqsK?vGU zm~S_+QaImmA7!nav1Pv*twg$wQ+&u&y~VifE|Q#Oy0kMurKkQ?!_B0ixVTAkTPRG^ znX7t6z|u(;n74awF@MuCJP978%X8-A<6WD0;ZEa)k1d(yBpq*~by^Imij1H&?O}|p zSpA!G;+bAR#6r>jAY|IG4b}fhp=Ar^+<`+C;F~i5-&{(K&;xd-x@Ca_XtBWytA}ot zgiMeZ4~uwp<_1tw2Fc71%XphGt|@})4WM|1!cq5Q!5?(!Vn`AD;UkBApb>PxG`y^< zC(44{j@{k-wJ&0u_CWVX*k+ppr(h8?fy*QI8mm|vX{ z^D&Bdc2nXH%i78{98T>YEUzqyaaXp)<6QDx(07lM{xiHo%TY5q>nXDLre(|D^bI~_ zX|WDA8V*adsQIH=#?e5{QywTO3KP-54lP?vY@>`+GRK`@ho;LNS=foZr`J~TG|R*j zQcKu3w7Z!BFO!44rhRn>(s6O`F3Zun3$})9J#K0 zUiOV$rZ*=9gI&O znQ7jMF)3Njl0hI@vp4Rm23uht%s-+PG2JXq+4#Fp9h^mpe zI`-LR6C8`rfRswe$x4V17$oCR1oTBm=AmlKy4d~|0&w4Bvl=Y5XEko-$ zRLxS9Ah`_H@PiUMT4%1Rtwl=lT;3MZ96Dgu{!!(z$b{h&7s#o01PHPCx&F>V8^>6^+Kv^7zxyYIIat*gps&YM_|_mR%p+7+}%GK`_g1kyfRWqtY?nK5i`p`lGGIljPH zrIpY?(TDDoPfF-II4AO>iF7nqc6Wfft%HW$*ixrtS<&}m1f)*NIlue#WH4g_*d!Lj zVY5=Y!f<$82C%&DQ0*D`^X@sW#~=fVuc&af5VRdQwB(A{zoiOqYGkfl?N>6@17&|! z={<;`O;)oPIqutZq01^+8Wc@A4=;EzYlaB)T^6d`{siP!;7Bm*?P?pVCpYd!sg(G@ zdm-1Uy~gRb9eMa7N`j>}?Hg9>vy6S_yTH@-EIW#j zrF27zMsLHEAGI{=wH4(i_}4VwSImaF4?q^x;NlKUADxCTiUW$U-;g%KInwk*;mT7~ zP=dXsjg>Ef#By=?!f4r8K!0zs-sg2+!Vmt^T6=2_JOHIdc&W^cg1PYd6JM#q{L5Lh z?mnF-$7^iYELYi=xS7mO4vIiE>^?DWpS4b2#@i^}FdM|AGdF)VxL+!;I%cmOL#c99 z=-Sl26P|O#Rvq#;Ykb9co{MwTob%g2rHF|`vp5lvx}NZL$K)PqE$3d7iEJV|kYRXh zg}+S@Up%@e0a>-}v$HWS`>i}jG2x9j^B$;!CXuVA@XN<< zvRL6oP!h6Ln~Dl1{|9dfVSneu@I!QaS_&i?6$g>T#IWsS0eaI`rw?BAuWauzoD~KZ z6?XT+adN^w_&k*pbOFvp8iFPzFo?MFr*_N~2nIGc!S;he1|rCfem4&Kcl&D2 z!ci7PSOsbD%ZHEWVTVisN_wvKHJ^n83{HTgaZqJy!IyaqA|e6RLyEZ2;o_Hc2t?HE zw}lt|DtyO>Pfvl^pl}ne4Wx%86lJRa48CBJ3!wSnf->t*c?}cDJya(>1v6MT1R}C5 z@WP9_p|tiPHyd1Ee|-3EMexh8!ClxChd_(=xjF89zq=Ygz*`^AW`x58J*IjAWYU=Z z5ho@M0uhPqV&O$|tRQ(YP-uE3PNSR~WVj{>(kL#On{QIapXBO~Nn4Y6srk^FbqR%< zTd3Y19N(cL5(8<#L%Pk*PoKd1jn-(tZ{rVyCpfZ6gdz$3clP+wiFqGG3>_UEC}n58 zC&oN-LRJPg_O=v*?G-=3g<$pEbv8C0d_4X#+A>}~-JY@aGh%ZOaZb$dzrbr2GzP9< zD9PuURj#Y9?M~+2y{205NKUgc31<6md=o)((h_xM-ANZ!s}@=V8nO%qh{5E<{@!LpK|D~T$JT2(=bPd?-M}u+5}Qa-8Fu0#K|jo0eYaccpKB$pO;)6@ z#T3yMiXm23R%Rxy6sY?Z_NEjdh&33$mJMdr&GQmqv`%Oc`N64Ni>@tVQi@z=SplEK zA57Khvmagx=aS1Bi92Via@+(xkTZy&f--LcF~hUNrtsErpsoKQ%5fLoy39F1aAXnJ zkR5hYs#&CNhTn&fl5P0PkNIK?tzqt(bl##k(T7>$Vsif)iN*Ou@$X;o?*znckVnDK z@LM1w4j?MpYRX0=@;EgFt5)f|k&C5B!&iTN;XL=@j=_e^rFPY#cXWpKfxxNn5e1pY z(1LB)4+wFmB%DD<_tIVT%z~~n`CW6~b8B6@zONKI7czXwxC)6*wht9eB(@o? zz}xpAlDHkz4g5b34-a-8}hFyfT{D3KCx@|{Pe_x5wroc zAa))ue7;=_T~lp$3VcaDsi97$7(T|bL9e8Y3{#Cq)UK>-!T50Dx$r#DRRtD{AK@rW z;R5{~DihnFYdpbssOpjyb4`u8obtakcdkfGxnX?Y;Wu$q&_X~Rwee>}4Q-1=#fKzl zn1a!+4G#~aYMzU>stZw_D5YQ0A0Zl7&WOG}!XFDtT+n{wUu5g|TpZmq$-VCp1qF%h z(KA{2ACD=7D8owjz^4j^X91WSDM}<8DXSE{l@O=6XmXi6pxw;2`5JYwV8&6mYbW}N z7yhqw?bHP*xlIY)zt`L>F(pr$3koym45@!OR6!Ax?e85K(LyOb6MZXkt-;FFG!jm> z{Pjz1!1?AgiVD<)0OYiaxpR$yC-@;RA!!T4kLBHeAj-}qzmouM4dg`cU(R)K)!1ai z3KST1U|2EF#h+||05R7oQKkxN^K9p&KlZn94 z|5Pz?h3yU06sxUFi3RF{rr^4uV?cH8I?&RRr`~AEChwMHdvu?a)e1xHQ&JCbJx+pe zr379!#r6xNC)vbfO?4mZ?28}a$p|o~K%ax4?}QUmX|70cFw@@r=a?Xi(Rli_h@oGv zFRW-}S%IS2pt*7TCxQRbp*T^CH4Z@Atx~j~JmA0n;rF-xroe9s{HDNf3jC(P{~HR_ zBocsHOMwE`4Y=j!o897}Mgx7-UXub^Frad!lN1C{S@(?c;fQ#l_^(IJZm%5SMCY;N zl7fGpn!!K~8!oB;w-a+Qf*4=&sBS#UzixHH3w;8S=Bc~6JJw(3N-f63rI=ky0;j{E zFJ@-!jALfXdt%{CX00k7<7Q?QWB*VkQ)BSLtAlOLwri0*-<&y6!$1M{=lrq+_MbqJ z=D53rOgsa%;%U(;m#+4b*+WF{UG|^qj=0imM2&2kFj%8B&jsKgWre5eH3XqEztw@E zCfr;Q_FqNcu!O!^-orWRlt2DL>vJxXn*ytcScZXE z{;CGarH{>Sz^?Ww5Mkar&)ot0;!zR_XMK|y3X6-yAF54S<_v$j%gIIXlasP@(~?r% zL||Sz%;R%fIX5o$C3WFgSe{}N0>|;!b(6tTPh*Ty*&08*bM=wzths{R9 z1w7wa=>9nk8!`L+k@A_l4-Jyf`hl}zHp8Xn3BOK3N+$#*u(R$=E^emk`_rRl8Ha-> zb=%)JSTlOi`!|ovSicY{hzewHh<3rw;rWPEaIaj6pW%SYSPZJsyXnS(uf22Iol~wW z<|jApizp(nqKa}4weA~QfFI`!Fxi3VfMxizEDLaWQIl!*_0v^BwDGyKKl-H! zg=YvmOanU(x5z-f&LK$z?CM_uMF^`Rus>RmE{y4$tenZVhN%AP8v#nJLEt?|LqJMJE&$?`mf|oWDz)Wyf z|NYp)(Y-IDLAxh|lO8H0>m1|M*2*lkkN4XW7KyxXS)X? zfY;vEuo(D)rxr*g%EEBPu|l~79!>if4~$C{{I_#JeyyOQ1y7a1w>qh?f{;r>h60lx zv4}^11ExHE{sa^KwXfk{gR`>PF66c6H)O%t$o{IC zZL(`5X|iiLkjI&p7h37={IjBg>e~efs{thL#|HWCU)#jQ0A0CK*v^Bm3K9FV=IcBz zLi91thM$4!X^-r|RelbJz;Asb35kGKq;ECQ;YlkI>|j?UNt?Pbg-fAlX;LPEI2qus zTZH(LJOQl31)SMsx$ffz-;*!Gr=T$e3c1*!@I85eo96VM@A=L$2o4Ah{???27(6F~ z?VBttG3b-3DoJfFZ;cWa2om(A2VCtq<^$V71Z>jb+hV z+lASr`-gHzsVgsQuQjw@?K=0@eGC~SXiX;h9v&O>g9kTeL|%Y-*bo{ALwmmx=D^M$ z`qFB!G4Fc`Z5jDS&M}*%UgC&+&+uUq%_Ii`=`rbC3ah^6g*?4pyu((FC{h>Lj z96Vg4Le9GMOAh*MH@5v{2D+l#qX?>3dvAp@o8<*6h z$%*jIdi9P-kkkRM$kQJSsxG$^-(RUh2w3d2X~$BgkqxVrx(#ar%Uo5O^mODbhKkYq zIHL7yR`VXGR#mizN6yyWI0iM-5kS%4ytIW=7RF!%VGuff@KsnCf4l&HswZrSAP>hP z!aJJe7u>fP*C!^E>@WnkdY5swaqH7^NGMZFCO<6gEZVnc@o(`RjTSk~p&B2)7I~Dc zD0qAeY@iN6AI%#^V*jhTJBVIFo`}w-_x$Qun@78*SmPxGYLAoOrYsu8jq+dAj5W{I zwQ~LttC?BJZr7zhG+%LjsByY5&9=#Y=`%rKHpyEjbv-gnKQ6IYKdAeD6Y4VdDm&>U zoccA}cL|(2ifta6+Lc1^?a6#ySHxMDy{l0l&xBf_=ZoGx+?RH>+Sc<3HJ$x3Jo7Oi zuqrn#&!8=JBxtAKeSmibjiz-<2ane||KAiDz| zDdIi*0Ad7TgvU8ovJd&3vY~%psSZAK+sCfQ{~$;iFEaCBXuI7XOKv&aWpn<>)iiUM zD>%Mm$-=iw+27oRlb6)0V`AbIU8q-{N51@AYjL$2S1~h%HXoUgE8t0s%P)$|F1!Lp zwpFO>056-uN7G}VE$@brvU<$ZjkslPwlroI-XuObjRBI3KD;JZd0g_9Ia*NaK~|M6 zpv-a^G?LD51-X1S(GWN2V{ucnXNnx92o$)9Z!f@0++j(=DLHBi>7Y)iF8Sj<@qF0M zl7Y^)=J%LRumjbZ02bgp6Du|lCwOV9t_@L@2Q2T2%$3iX} zmeD@)^4mHZzV!rgryW~0<8k{@f#S6|ZB&OkmAR?Xuofyfd#7%@!#|Em1B@i0o)pK! zttWCX;XFJnw#%_wJKCS$+W91M3YBFkWUuTpE^B=~&~=5is9xJheU_{=x$0{tr80wdjdPrOcr(e2%smcGb5WHI%Sc)dJiR$W+At>8AFxdleW+;!~!DX!1dL1s} zDbeD+*bR~cQddQX)E`m%ukR4(F}mSztGH)(D5G{J-G{1~twADuATrA-*o78d`|V!! z*a%{0gL^20^%mr&gK20WC-Y^T1g`h~avm6FvO6+4@Nu|;fpVaF(54E!kS8l>43k#C zl-wiV;@K%)auZSen`&_YjYRvXnoxX`m&C*%!1BOG#btd4Bx-->59f19%WHD?)Zi`xPieK7J$tmrD1C;xiw6SCZ7y}%wZ5AQdx}$#j@uZ73-1?i61?dHXCLas2-0!7VCriWx#nl-;_#LwQnYanb_J>~XOR)~pA3NOlVy!2F zIm_u5i;La4kc6zo{A}m@Mk`HQ&6T$ZiBUTS0;>Tk%UX#vXB6EwtIhoJOXvryk2))O zwkNa4xsE=A>u6v*)UVyTWx^dX7y8J;-GL2K9up&_#jg&|K?xIoc>~6X`xti)N98{R zUdm9GK+Q9~dphBET6ycnjZx?b!mfa~=H_$kVOyXE8QA~a{~=6%MlqcV%&FT$%JNOT zy}XAvYy8#&hjaDt6v@JJm9s^1XVb_-Ob7mr4Tb&1!XdrI)VBrVTb&Tghn`{Z$udOp zxh;07>(%wHcBHup?UiFqyn9~0ojCxG@?7O`dXU^1dzyr;zqx8;PWfCUwW?2z#zdyJUt5gkF%MdNMGuWxHY2Dl>+fa#CgoB!rmu4WtZ zoQY`v+8;aA+@yBU*ZHKr`rvbs!&6PW6b%KCMhGM*A+*V-q zJ(hjW-Mr$OX7{o@)+HyKcVDZ(WU0#xB|(FYW*HF$!7VmJHlWGf_LaTtYIzB-`SSXB zJ6EwF&w2OFp2e=k5m#vQ3c5gZUnFYkgyRx!sJG{8Q8xV90BR~w;`W1vcXBc+fbO8D zZ4nPQtP-RcR-U|918?^w(>x1&YlC?xi%yUZyv)1jHsC6#HU? zujvOz?%<~xx*m*H^A_bvm$_Rag7EfHVg1}Zz4oh18>qhOqALN~pMtcb-qbX2#U`OX zXY4TtRPT!WCYfgL^$%(I?zuu{Tv!isBfgtL=mfv^O(BAT;D;2jd4h~Jg5-R0)ej~FWKLKL^1L)Ga8kv+M~%jHC4krS~iYIAIM%9y8se4<|LB9;SnyV zoM=u|*f{B!IR$pa_2?5eWIr+J6@1ymnRj_=X5~@+sDZas?kiQLq05$g4UhI4!uQtJ z-+=J9jrDNsbwnR0A&FYK3ANinwS1NA2Ucz5rDXwkCv_yK#BTk@iH|{MRPmI)Cj4wt z5T7Ui>7(xrb7my)79!6*SO(~h@U1hCFHEP4Qg(ehNNSsD$UC!$%CZ;aB?h7Kkrrk7 zZlHY*;aYQ4;*Lkh=JfV5GuvADzzxnc{h^P^H=-7=tydo$6ge2y?M&T9_HrNX>|yDx zR^;X;J8u`!fb{A`B*ZiSM~-RArEk|GgR$klzg#Xt%J5;|&o+Ay+zoW+Y%?JaYJYhVHx=KqKhKrgGw-=rm?2|~pSh}%3+EOC z8^=f;2^8XXLwR7gEhiXG3i)?WB&bpG&SHetswEKW1U%eeCvUu!KRAx%UP7;!o>XQ& zdW$sLN&Gdl^wVT!Q;=>Bw8}TUdt%oM^tIMyH@ikSaIS9IrtTsQ2 zaaB~A3a*iOUi;_qK7NQ=j<4!}(^{F}hE{miy8CtDEG9)^Ce`Rg!}l?7>d1PQr7{Bd z%iZVv-<#RKe7y(;iY)QDi8dW|jA+)h+#`4U!~LH3C9ab4u(dRN=B0)d;h=Fv4Uclu zpgZ((R`w4I6q1dt?2FHP54n#dbAB*iVzDnRuN)p)-gq@M5P6ex*>!Y**2ZmHi^m~< zM5po1e5z7o0M^)6n%FbvI1&<;p=xcr)+=nmN~%z3hOmQ-{tWIDN7$}B2g>2Tgm^k+ z7mts492ODU3xJOW@xr%i$)-xgtWWdNsRdCL&yf?xXAIp<^4Fgs;Wl(}_=37OhTQWq zh+gaCG5Gjr^hWEbrStBWm5Fz&sJ(HiqmkG;7f$vz@UuX+gn)-$n%5i7s-KL4hx@$vdG;aKLO3|s@ zNirjX_Ipf5u|ScWehUSqWxLYmFsxz@+76J)dF^m~p8fj60k0R$%q-z_T&^_fi7_&1Qv8x<){ z=0&w3I?)fDCZo5@o=EIWM%S{@q9_=@QMdwfRW|Lo;VVc1%I^N-j`Wikhp&q zY*XPj+SFO=kO|VzJ7pu5sb~3eHru{lVWs;sBq@9MjohX#&(ucj?sQUg{U?zdx5m7j zJZNljH@@|=eJi?dW`TpdbTn|f>tCrKz_@h*RIsL=&PxYqb6qKcOef%}MpCeiB^l3y zh}Y^I%O8)z*js9@Y9H~iU>`baMBE_xq`x~UZ&kWC5Tw)TdP&|@iAnF6vS&je(rO^H z;U3I%Gw`g|CCWm$0-zugJS+MWFN929m-_;WnlBV-n6wsXT_)QT$>_5Tx>e>$O#GrP zgEHWpm$sUHfxmL~qcbs2P|wS~4sOg5l-Whv7+5&C+}+uus-x3XICo4v1zPYJj@#w% z^v;A@K)UM{9{1tVmz_}5Z%#8`0Z5=TK!aFPHS(E(hivr061YK_GYY^KUt*q3RCz&EdE<^m2-~&9e zx9R!!VN|Bm6MB^Qd^c=Jq=2lwnH;%y6B4B=VRkO$u2KAx#)l-D$%54uEfQ4g?Vq{H zttJ;c8a*#0HTJ1|_?CK5xB$M0;1kYu_~MMAc6GaDGy*uhDu6~&?Uj^Y2gDpyN?;bD z>Jz$gO=COVL}f7FUGrPjD%S&WC2tg4VUL)%2>esil6Dq+C0z7?`>*(ugZ+N(L>uU4 z_ig`_)ia1{^-3}|B#lxQvA%XpM0o3a0JXa3SCP^TN*!;q13M`G#fB$~g{~H=gouZ14-?t{dSrx#RpHsR~c>UDxeVX^3Fk}Q0DxER?Y`zHgo>VI-fxC~oo<%Yrz> ze?E{88qreEO_@>qm>P)-4RGk3AO?=}xL|@Ct`|RlM%P&XbBWb#e70t}XTIfSLJDUC ze0b#iH#&d)3yqO^P++0>UI&}uhX^o`{Ebo?Zoi@|9DkoT_5l*36cPeUkc|RRV9C}q z?PG24uP)fWf5~Ryf?@v75SH*``z>~cm#*~X`u4(QbQuDqHmUa!4)GBn(^s6t0r-%h zthU}9zVCD$1Tk^T9jetr^< zW{|;L=+B*vAOCs{6b0K0fj5$TyXGqZt!tsKfDy^Z3RkfF^ppJRJ0<$EHM=?`$V?_* zmwQFVrJ^rm$-*8Zq@eZA)|(jHX%6nyX^F=%Hdf4R}~GR5T!;QH=kJkCx1&Nat`OqjsREHK`F*C3_j8JRX4 zj4tY<69g`3LfRP4)%_(b0=^!nr5~nc`UM0NTd+SzaAo5thp$q1{SnowFJ+^bd$k~M z#qL;?VR8va-Z!cB4x1forhZ&G} zP$2R+xC768S1MN&>Hs0QKch~#iXKxR@p9bMs#3KV7Nc)#?-vOZo^AR2T5eH;d8nrI zi3f3>-V2Dstq@I*Z`-}1Ad0s6{BEB4gKq2xFs=&SkFYG3{@6?Jmsv(R+&D?AC)+Cp z|1PHkzf(gvf&L1$V)r}vW{$ahj^I50n~^G|lN6Xb&@crl+17Ae#GCNf6-kVR`~L_j zU^Fo4)zik?qWff$%>YC*vBf(lkNz)zK(s>Gw4a*-oJReAHdr{nDXDM&F8upz!R7uY z!fzrR8<5|e0O`8l;_#aYzs2FZtN2?Sj{TqCI^nlY`2R>J2s@v3IXd{#nWG)wnIav& zRpR1RHr*kFhZDg?Kxol7$`zemj)?wnb{eIW9tU9#y z4$ZQ*y}xTjJ+jYHy6l*gO@&P0$)!m#EXb+I^K9;~^z@CU&hIU4rm=0uz|vF@~n#*iG5PX)Ow!Z2qoj27{Zb>v9ZPdPy)prr` zO0JrXGHdE{SK!;5Y#fif(^ux^ExkxEWa1AQZapvlc%E3u&BbAUaa$yQKE`!U=C8(D;2VQR6#@-r6|URjwlwS4Z&TFzoQcfDHuhFQTODad!UzKnOn zHHzV*kIkd9SnkO%;#u-OxU;=9?9-5WB%i?W=NZ+hOU6>}AlaHDr19c}_{TrUfYv&F z#XDPYp!w~75QJyRoVrbPzIN)&l7y*G_vy5K?6ur5tMdvxD^B6AOnmF<{f8`adl%A< zn!|Wn>sBsMA&Zr4mMO|?W`ncw4y`11zD{%?U$*dDe~crrT$}ID)vN0pbs?&f7UO&I zXXt=YEQ1Vt1HP=_;m~rGd>}cyuKrh{2i0r`HeJsc(#&>t?j?zNvFkNGYmepaW7r1L zle`&WG5Ds-T7QvInVQsJ{?Hz9f9=gtxA-MqRKLfa8J5_tO$sGB5?P|M>bcMW7iV;h%qA7PX z;gfD_+;!O-#xrqlq;X~c$aQep%zZXDWm%kdlQgqVu;pJNWwS=lZQ9S+QBKX<_EVBcd(w7(dV_p4x^0V1bmY%CTvmf1K8+IEZ5%;=mQA)?Z z7avahwyw-Hi>z1G_BsE{RV5D0wi>2%B!yuFxSTwl5JqAk2 z^4bpo&k}+wHQBsUuLyR-7@w;T^>$^+P$QF=)h-A8f@gwdDel3Xw z-pu1Vmg_F?icsU}3(;C!_s=#+3>unoW6C`W7Zm5uY~Bj5(sExP9&1U9V;t6)Ik4ma{GM zTc=L39uAGxW#m-HX2;vrCZg!6M4O0R91i^LX)!bK=g+61`88)%NrEooCv|7S zHONO?<|{Yeamow2yqL2WR~Ejep=Qxx2GW~)?x?+*VncAV_i7xvVU*S>&@K2sw2 z^!YyD+g>|@EcqY!^;B)fP_;6g?JwmTE}l9st487SReLPknNrHPk>NquZqI9-)doVD zQ;e(!+nXy$_tEA$dd94k=y$W8rZZ`-GsAebjzpS~)!O=rs9IfLrt_(?sfv#4i`#Ww zE%bx~-X!_$97;TomdV#=!7FA&qjv<+HDAk7Ba(58aa^l;@we1~V9qZnqHr5@Gt)E1Kil}u zgc>Wl_;7ivypA}&XO7cRmGARX_;ppYK)goaF1U+#l1>8 zfJ9yp(>*`gNhROrdSm2K);lotP(MvxdxHL|RRK`Z^YO7VCYQA73hQTIpi{UyJ!A^# zydXZ;90n#SUW>8YVm+WJw#;pD(m@%7xB4U}Rep9Ea-H21ut({6Qw`LoRMkk7O}Gn1 zAt}M`$#SROowDl?cWr5Zz~52TGGn-8=wgv)?eHVS44G_N(Eh<;LPZ111^3mJ*7-{m z%{_PZxS^_J+4HJ4iH^|iGq{(Qg0>bWT_`Lr+40It_^Diz)*V4ti z#c6F#>fvElI&Vw$sgn{r&c|-oq1-F43#i1b8EwZFGu&X-uHN$GtL^Hjil`D=s2T3M zr@t2KpQ*2tA}Hx9FEtm-ye+U}T(XT27cpD^>(8#|#F##am&DjWc{NYRbOn46_cU3o zX@`*@iMXxlvqTRHHED zsv_4m{rB(j-(%;p9z5qYog|5WiVEk<)o~k6FG^=ar!u61$Y)hE5os`&GM3M@F0^kX zN=9gXbi+J1jv2@Avs<6XSfcn*Y@GcooIcEI^~9yG*9JCy$6hq1R<*Pm}6-Zc;LbYYTk>|m9(9I8M$%rv~8c)taM-(Rn?*i$kh^R4Kk_Z4-&W!W4rE|7o1GF zk%q#c?x8_=V9huG)_|Z{%+Z@@*eGzZj^DcD)8ssnxMRP|gl!#W+kv)|89Q6v+;SMs z3h4qxx3rF1pcn;X$6#nv+zMU`o|ZOV>452y9xRgB3?uA1oJ-$t&CHN~fv z;|e)+us!meMQ(ybSmL{;uk3oYhh8x+!{XhmN^7;sE!1Z&W)Tpp8KjJQ`nzc#on>qY zQpJ@O+ws2YTT%ehx2T?*be=iWizdxNr21_f(nr_LDjU!ThQzc-U6<=1cPQClyqOIO zym$v?u|4VyX2^@MIdLNd>z%n+;3yRp`nwK)jiQ1D7!P5IZ#gYX&X}WjG6MmX0f2Gq9Z583_@`N%R>9suDDCS1y_*qS7 zB~S!;adqqv7^aum#mbNL<2?efKo}+MaScbH#4_E<>UtKDfr;R4HP z`LKA`4QODRu~+g!^7aIEG=&$58PG-A`B5v>$)A`D=>ypEfHr@2YbK&lu*zoW>nFWC z#TJ@%-3Muy`5iZ`J*K4WW8AGSE;#NTusx`*8rwXg&hBjLIdO{J87_s39yFCso7ib&_D^D!z>9>&R{k0DeH?P#uLKFf9{WV} zpF#rR6ik=h0iv<)d=|M3qO>nOv;7{mAxd(*5v!9*9na@2Y1Ja@8kF; z!ZPyZ%fQ%{&O`~6*Hdd-me0RmSxGvQYs;!`f2-sFK*e|^f+t1hMwS$NgyJG12y(Sa z1g63YhGCP~XQ~hrmQGAux(M9rxu)Se>j7q1T4LCXg<;ag!;X3Q@XYBz| zkK%!AI{Y5w?^pdE4N`W*9Fu7Uo{(1BnV`J!xS&YHZTA+Lb?q(3=GR<)oevQ~oGzDCn20J^s966% zvNhsbzF#sfg*}8#!LRf9HPFA@rqmIXZaeH`05zGN?Nzg$da`^fFnPWqNUM>0CQzxb zK1DT^2S>4t6ZHucdx#udn7=e{AQdIk!w93z$6R#Y7tn612NCCe1=SH+MQ?6&vRv)W3mCTib{$6N$}P$;3cRcT6{;pH49elDCAGVAeD$CVTt z>fqk9eld}%uE2SnwJjcaT4!_Lk2h3eq~O7$Wa0vEok(LPG67n2v+UBPEgQ^;OgZ50 zycvti$Rh4lcMi=o-X-l=?UO!=3qZSgv%62+7B_uHmQdBl)~_$q@@*vX+>5ceOd0-< zBy>13BIFH9a@X0A5T?W6^Y9n$T7+IXRdtyCV{RS1?C}cp{(q&^b#eC6WUl9pc)=g2G3n1 z_C_u3Q6lFzW``N;6+RSnZO9kl;0Drky{~6@;Uf*|TZ-LxKBc|UQ8tV#ojL2v#HAf! zRbw+2ZCQC-ysv*Apoau;F1x4-3D=}V{;hh>s{zTu z%uuw%qkp8CUyPbhMx#0gq++@-e_^#>3jvR%84DcR?JXkKcZ7VwcsGiNGbM)yd(T5vG-y%l zL%c)2mb%eP6*KW;fa9)P$fey>b9&QI=Q*DhC+DGPWVAM2;hT-UT(Nh%3{}Aykj=R( zp%XXuV^JXfCySvfLp6-Hc`fk}JNkDOL_*|}S%c%$o69Sen*hD#1qAz;R z0SwT529Ubz0@EuV+cES7tA`krUY9K^Z@O%u!c8I<#IZBY3Q@absp`vZX(6}vx~XU} zhwInaxh~>V@9qvQtZZoN z0Xrm5y(r$PM>wYbiDDmUeI+kIlwFNl+E{GoGm8wMf3?`AMb|?)kj}&|V?Fr7%h0RG z(O-#^9K>(4MLf^D08pcDRDJW;ICCEA0}n{b|LI2lK+s~kGXsel8`^(wB zDeIqLUql!va4h)H@#%lC^ew1OdsD`ur1P^Q^)r_E-L?GB(fWT}+5>iQUo-p-Tw)0q zQT>O-2?oH$XI{7F`dL%_bfWKnN|*z9!Q1S%`|wM{{=?V7PwM0VMlB3=3my&dzgena z3wH3J&*1vcDEWV+o-tGf-nLH$zwYHfZS(sU(s{uS-p+Fn{7}*d@9x*#6oA(4WCOQ= z|H0Dx(4gZU+eplxf%gAMy@wF|&mkoKKUn$}dd>M(}F$>_I}@F&`DC*l9jNl>sx zn`jE`7}C(_xcLz7wK?|H5P9cp=DHcGm8}FujZYc}{t`X~JYJlde%Rqnw?*g@Czoi= zvkby-@`4;&#N+eyp5i|9Jqq@=C*cS^)Vk*wqX~bT0yml(54E%ZQPa40P*UBOc+cnY zUIEy3uQox|g|e*keR!<>u`^kCrL#~vyi?D|BGEpFq4vJ3lPANg&2jfW(Nph(9+q4x zIC*!o4e*{*)fwOcVNiqLQBXuBc#%76^#S`no4%@-MS0_o8T5pta~sP;oY)aX@n0mw z=T#SBQWU%fTV~Ydg~tacJUnyUXi|4=^l(LKXR?iQjaHWP!E$GgeIQ6xY(rI3lQ+B8 zG?jk>*FnEuW8nX4?>*z1%(}i&l~F7Rib|2D(nRS}qy-QKq$;TNjua6h9cd9!dJ$>T zRjO3!ohU^>s`Mg+9z%FG?X_3^ueInb$gb3w*t{rniI8gc~UpNOQPhs3av5vvd52sPWsyU$R#VA2~k}qL#=I7?e z7>iHgL;u0Ub8cc7ZB`SmBg)geGb{O`i8fC+L0q7gFsyQSQfSBI4?^|^>oH(Q_sYwChx zG8g|&*;AnGP^bZNQMl|A>tJ?3%=NFJjE{QN?sq|x7-#~R6?!L(LT>3~aQjtO?*0}B z}AU!FgZLm~LzF#u4%CH%Mgt-On13Fns|Yf_f*Yn`C$ z&z!{XK#~+DMneO5~Nk0^eM7^0(v)0~@_{a^N!AdAbpEtI0Rw?QE4@+hxdoN^O>3Gz^|mC66_w^Dyt(+|YE4WDea z1`F1#l0NAMcLhbGS$URvfop-H$tw4HR+4;szMZ&*{6uDBn3mA zVmGD#ehiTyMJl##CG?k6d^ z)G?wQvJrSwMdim$%6VM52hQV$OiputJZKDJ>^u8$(<4Ru!CJa@PG#*@KFgq0q@bw5 z3tCFWDJU2JZ=ppCb~Ip7r=vvKVh=gklCD>j(0hne#-eKXWRa;<3LQmPEW9_OE{YV=~vXAZ;@AJR_61x7#j&=qmNG%iYL; zG;TCQc%^Oy8)6Jr?o53U;XbsErauKO_;2sV5zHJL$Z61`q*L;Y!9u>SrKsg6eNsKj zsT@UvZX`K-Asgvh`Yl>OO1~$am}Im3;rwcTB7n)RmSIot5$mB1TpE&VLwoo~`k`y= z^8Pn8>pfS_1E8qR$zi98C_Uo-$dlP@n08mUM3=_wm#cjz)1=*jA{|IGE0yid*CgwdeV z15@XuCtpRVC6G@Z9urf4E544-P4^R7_4yIH=dL-PsH@Kx2re1(D-%i?FQ^3tLC7J4 zdz7QDSYMFEWe$NS^Mg|WA>Brg3nnwMmWcH9&>hJAo-ilrT1GBO= z1Jcn`nHkrJQHTVUd*2Cem^o+1SG!&oU5={+$J&waUV>oVXf%vwHO2-owpO3 zruW0>Cgz!)YL^JYT^c7|s zm6YfFaO~q+F*OpQjz`xjjakOJ8|~+doITfa*EuN_T{5y;D4u(lk*1Ev*nMgZb@8eo z7B;&zPiNmd`<31HSCcVM!8HApvXH*Q$LMj zKi=5`6pBZv#NTNF5_r5yAI{BacHP)*r_}y__~%z&sw68-#-FAbHi>u1ZH?(#%#_+n zpyEVSOZ(U-gV(3(78lKY=F@)W%F%Tp5Uzu7h1bOPH?hMXb$Epblrx#)CTAyD&@{;X z?fk7W*ItNv4ROPD`Q9uTRH~)SS0gZ0HRJ30vRqrLp_jO;Y;Jw&wYMYy_hK!kdOSL@ z+aTpuSh;-MVrSe&tyveYo=f$MjRGDT+XFNtAJ*%!nmQF{EUvIpA`$Ss=Gx>)RY}`s z<(GW{VV!VKt;Grh^DGzK4Nc0uk0-ZzI@b7>mLh#TK%uQY_12XJYX(}rC?+=uvfk)&vb=Yc>3xl#I;K;0m=;l?*Q)R+k}^dv9ec zK&&1{X2@)Y#H*d#@Kr?(&EkruOK-;S+hJh7*;>%4#4QD%Tsr7 z!dpuPM0%UFhhIX!KENZb-yey$AVZKeYul~P7@lWJ8nP{_O!`ClhTS7XRh6GWdI`8H z187ywh@rW(A%8~(CVP1wJ&G-JkF1%vcfzD8y8SDeNJkcEpM;Weh>j0HK2wF={&6VX z=DZF~p4fvXfgQ)j!GjmIRL&$aUA{gW;urhmbIFSFGQft>P({mJ&0x5cfNx*ZdjZ-U z4DsppK&34KihciE9Cb0Ms@F;VC?DnVWaqG67Stx)Iq1nsC8OAyLN*WIos(d+yu|x> zpa6gh*bo?A%00tm?`p|tN9Nkoto4**6elbBz_j8{$}xi9=OA`r3IG~)9)EJe@?%!1 zi{=OHLISghi?zP}TG3_;sb(?AqQs=C6TzrA?L(UXIIM+7rp#?|cM0wnZ0(aFNwyiV z_+n4s+I2%#G@jND#AD?NT&)LwA^6LCWv$-$6p!CPo60E>PA)~u?_ctZZ0{Bwd?pd)0Ku`!W0jJQ2!GmTG#Ojy;HX7QP;d!+A7X+gXUqd$))2N_bz5T^0>VF>|C5gw!60W zNH@nfT#x58otfXhqxV9CYv1XmRI3DO-3#I#UjeX0uxL;c;mZM31#6DB1`-rnY!U5# z)Fga2B1>{6Id6@c`E*zi9O0(t9SQ)aa;aWJFZ$F7vaOKt632b1q#vfYA#~e*4Cm{F zEEieoMy+Jbp02G`_+1si!p>}O=Y7j;VSzR=LP#4c!lHYop&2o?$W#HEHx_kUZ*K4J z^3=lS?UWI`Sclc}+NC$*86%He0KbAeFtyBL!R62Ew}r8t9k%{j1n|!%PY4KmzNsVK z+m^@{83g4Exq_HabJ+PA4%l%a_=Yl0Dsr}Yw-Mm)*`@g#_JI!XS|~pS=bZO6+L@Y| z04;fOa{jdQo*o4DP`~r&HT#@m#9MuA4STLVP8bu8aQ^04EM==Xab2kqYt7FgU*8fG z9a3PCoaIXpj3jyZARD7!%X8!mN*BHP?gQkMWy+jXrpZIUjP`jHuNs;tIcE> zQiy$!wY;-Y5~S1-of-bbhd58&2KhOp&AUD1v8j5JsEP4|(K%0Jo0PSyO|;qsxEk)F z(H!CfMkcEiFLRZ}Y~HgUWRep#9`0z?NwIUlsV!?Nqyl1g(Sf^I?}`XNhDox}mE6TT zsI!J|gPI)Br9|2Z@#t5NHDDf_yO3=(l^zkw<)S4|4Lc}ZN}~x%Cv<2$&Z-;=)g4%E zB7L(j3Y!dHWI6F%tkT#>LIx7Cx1UhIn0S5etz0wCq2x7O$mHpd(%c)qZ_g%@F%&Sb zJ)99bh|NP@Oo-SqrKc^nf7|zo*8nr)OR`BK#HcrC$L+IT;Z8<_HYc;Jy+YU9^fO-! zIy^_uQ6U8Xl7R9iIAdztbLm7#E|}qqLEK?oI&ecVR{xpxGjhHH2_K-1rJp(w#dUnf zE^Q}K78rsE%}2yL-k`DdfyMrPkCOmvY8Xg&OTDY45)(BW{8>IHg>Kpt`LPo{TBy4K zmO)pK_Pp1$R(3-B*a;zFZ6c(&^=)%4z?(azxb7Gy+xvACpl{;d! znx!&wS5EGGEx$_{kQicQszq}|=ME~yvDcG9Z1c2;+|JpkISeKMA;oBV+NpLkU~b7* zF3Q_=;j>Q=urGS5&*{xkA$0qixCkpBkYOpC+uI|CQmng3Hs0gX6dq_mlk3XH&2JSM9JK zR!_9=`q)lvU&v%xgCl7z!Zk;F!o+qbQhj98v&4kyTaK%wd9B|>2w^tedq1eWILJNd zByM9!sJ~>oGP{7s%y4R-=xf|n^Gy*9=2m7Yt~cC~F!tMDn=Ny2O8SB8A|U8de!fUQ zx|apT^>P9nk=pXaSA?-n1HLtEY}B-TD|)nk-N)s${Ldj~JM_ z12ph_tbL>!$B$vYdmB8&2e=sC)H9YBK9q9rtc-VFzU&+qI7bg-@k?xsKFZ;{W$(Os za|L68XXa%;U+2D-jJ|p@LJa%s_S{x~kbIuW9)--Rq~avoR7~QJhHe%Es9S^QyxjLO zdiiUNJcty`XIJM?gghp|pXP#iMeEx;G*u4=ZQ?nF={fRjInhIUCA$X*uQ#Jg&OEpO zQO*!8R9%{Bun#!C?EFYylLYf?P(CLK2kC&z!sT9P&wZV=5M&0p-AJ~I-`Q3 zR}qk2dETWisl5g9@7+;vmTx;P4aymG_{_meU`ZI!G4oi#)!gmB^9y5Co=5zM& zkGX@GtH=B^Rvj-#rN=`HZL@c=%?rum*y)f=r^nTkpSOo{)^i4`(qWzA_DA^=!lFnG z^I_ibOsls7CvFrs;=*n}u|aROMouA0Kgo0+6`ox6H8-q!$04%nycX%XRIg5&x;BfS zArP8+Pb3sRu9}^&KagEhTN~A8RWup|xX*E``~juYQZm`?yvMglvBlWPD2qUMI~H-? z6TxRyXhP{OrE3!b0DDccuY|R_oqHX>O@AVoJ67J={_;`!YRPP4@7JP4Ca={bclPc! z#9M?@L1gnr7yt0gPjvRM1HUjm%xbrfnq3b$YvnsryKx+TtnszQR)(tbi#)U<3>Z+W zIE=-HWv42ya}8nlS@rdajwYYS9F{fjKB!|p|9Zezq~YU$i#qS1*p{~PaW4T`JfUm6 zcq`z0qokSiH>!;W1q*J-*+{=ri9cLOMX;-@Cs7>&<5UeboKa6)J|~?~t_nrZL!(O! zkM5^>PQ=Vgstd4titifDdLl@wOoaJYKTBZpiCA^tkT-G~k#x@UEsZsCQNpjCH2eup zdx#e=8B--&W8|C~ik!TVg|W0JN}9 z?K5{-@8{ICUTF2*>^=>u9ft{@-JM~&RAgIgelMIe!g@3ufl?PJRSiK{U?IEuX`hTl z-kj@_+)-%UvheUA?y_wZv@xiyw`pArQk_HY0Q@ek%(}S6qr5_6nsxsDm9~Mq@pBdI z+2qoOFl4l1NE@Tcg@$wu$$PA)xf4P;iLEg{W!zfdbZG2acZy2CZlG)>rt#5on8%Q> zw`6&uUYsR0fjSd&u1N;7M18lt zl-Mrse)(1`VF=r@e>A5kf&I(ufKBB@E+%)G$+4Acy z=4pK@J6NmK2dL5onVMZsSC5{7PaWKeW*kJ1?Vj=VEp*+k9D5)a$$zO$8f%s+E#!Zs zJX)F1@Vk}sm7OjUf!eKYf{+C;K(=KCf_j_X5- zv1`fj`NerCfBOgbWuLcaRF3FdmL86cxzC`+ZX@_@CWI|g?x@g_OO}4~RKY&ZaXj7abQni19-~+vPnFl@?$5cp?`1 z$CR49RQa6A7IThkgmpl9N1SZ7MOYi7=+b?hw1oQ*o`zQsx!ZO3%b0K%!ybEtfy z+f^vIG4_*6RqH1O)>~XB+*;Q#2Qe5>GI#D+TX0%7=f~C${2pUAu?>%nrIr>pmm@5l zn@{6k4(k~R3h0`dTf3|m-8N_suiQpvf!5O^gpE;aw^ws##YzR7ALS#8>NSlu6L(FV zze%+(VNJg?snCY*jME27i!hx|9Pp8WE@zRB@SJheXxk7a7M?MH6IFnIZd$S%Hi_PC%Wo(B9PvZ_;j+8ep= ztCaeP=g5t+#T97N38U4IP@)`Tbv1xv?@EP_?g=x0<~6Oak;Tkx?}f-!Ble@8Y#1=+ z*3bL7-V!}L@{BpBD?ITCeON${ejeErbH<>Um7u4tj?sQmCB><@4KjHeY90QR zs4q2$F{9qHO@8fp)b&Z#_aj?wai=ohhqzCwToH6-SlO8|X}XK*_VZL(m3l@ZY55O} zrEH4I>r1I;+k$Uns-sB6>hc>I(~Zll90*qTxmtH+E<3U+DUc)PJVoiyIJQ#vVFGk? z6PNx_o^z7~!0NZXAJjRXWjwK_SJQub>oh9bgEEDG-Fn9Xr#*TwrDkB1^d~@7hyip!LWc#m+oV z5N;d)D#F{&XUndR_;S~1?#DIfr+e`W2Qd)%_kxp}R4(J=?BzY}#K550+B2(r=*v8M^b*{+7%zw$o&t1ON*01NGK!AiJ9Gne2dk`-( zX~(Zl-scsjho4}t*)BVx6oz@5;|serC@%5+BB{P;h+O(Wx8hW#ZW`PrcwLH3iVxA> zp$0mKx^yRdLw%F}xFk8|Qr#dyc1V8aI`X8OA{(*tv_@+cFw^4Qr?pF9D3ac;+QZ;mQvKw6^G80GA^?cbp-9~>MT{0R&B zX_tnuEJk}Lruy8F)>N!20et-JGNe1SD`=&dfmUWFG1zn*gV{Fg91^4EdH3wGJ>ccO z(|z~r&bFMv1k7`KYI|LOU|8IQ)dVK4$Mkg_RaOx$LF%<~*D<$1@s;|ao0EdIb3vy# zAYZa~Q-<4u?GjDA)OH8i&nRo~K~y1o-SD7E^q#HvV?xjFF3ZM0`1+*Wm=HwP(QY}o z(6nuI4%*m`vW$}P&6rzP9-UX}sFWP%6VjEoRBYljkXj*h0dGO;jdbod;~TohtTmokPdxpoejdgvJKapRWY0QW!+IqC~7ENc57vlS71P& zl*sPcat;{;D!yvHmfe800izl1kwZQ{6CchJwhbyUWpS<7I^7h{(BFUl3vAl?VWaNrND#2&ug3`mlv0up1ljGP)(f2>TovMC%m?RdbcH%{(T3v8 z7nifFv+^GEMS&6*^z)pZwQ)w{)5Y+I&5h>+J)K`Ydi$B7yuF~=7 z2QlhhGCq+Ami;CE>@T0&qtS+y-T03EaMopZyKMw#ZaqA zEA`@nE(c$D9&)sUyPEa=g|NbcyjAa+vM}EF9T%AtUR^sigMiZxqdY}7n>Kk+ zS%{=uNQSkycb!9i#`06M8-BUVQ_wz5W{f_`X3|Zpz&e$~ibt=G zqh~VnXBKcP#k%}L5=FkXX6@c4Rl&emv97^Q4pY2@FThw~R`2+oAw3AhJ9B?jT3_NY znDByaGisx`$a}8q+RYEt5bw1Tx{x^DVPbxU{DgC*F2k5jck9n^7FeSHb_ybw!x&rs z$R@~}YMJUmi z5Owb6N~YWn3lqvX?7gY2U%!KFK+GE{t|RK1LoEy#$K@a4vK>j(q4jKMkR$Lljy|80 z8*L7Eam-KFRui4d3vQa2HLm8nZDDf1EQL5+_KeujoAOIslTX z_-wb%QMgIE#00+e*_MNYyb{Arb1oa9up}GlE;Q+9Zbcidk6t}eLU<#yK8(1+<%0!Y=x^(hHNkVH zVFOY|T7D9*j?y?bqVQkmm#?+U+HMaI+_LR4Rl7p_V|%m6HR+uYyQiJ^@KrOzk@3CJ zTZw+x{FZjdvBvvwpJh0;bl=K$1JO0ptliXoTz(g%r2-M{#jpNK9}BYsA&jw;N}&9% z03M(kN;+w(MjJe2OA{Ipk|8Ijq-?6ilY9!F+3Mgx+U(MyF};a8_ebddKC9k?fik%N z{-k_XU+NP>++vBpUghHnEu-w7@NC8RTj!6W2|Lb6mjm}7wkiL?dFet-mmToRgS=i` zmhRFI#HF>5W{gr7N(TyT2Yl9pFP}rTTG{mQ>&nYlkq>EXJ~~&ju-g8B`w}XMNu$U8((kwU z{RWwtk|uo|_*cB1p?Zl2hwT|2);8i zw{Cz=f@~p2cSj)CR1^!^N1$WgN-BV9>)0Mm@hlR>5yPy@hsyQ=qhUZdeq8HYEw5 zKKXetD^5DR65<%@d*%=u5M!qzmsj4i#FCR%J;^T#?QWN!axuawIBPG_JCSh9;+un~ zqZv)TABJ)JyL4VNskkUi@0iSy5!?HzW3-oK={@rG>XLdf`^x7RiA}pNQCqP#LWl2j z`~gl#C!_7c70BExzkJ*Z3#J}h+RiS79_|n=+Jur`^Jpf=Ee8ZA!nZgE?K4RC_A4IM zyB>>Eq>XSR(hy3nHoZ;&ZF0W8Z@QbooOw-nV-kTdeqrSFfdkUMqthmO18Rz_9430h zqs3)({W@dUs;957-64e12Lv6JSfIalv2n+YC{5b0pZCaz6?1CFLDW1#z8OY`LhAr2!*f=oK`YLi8SS!tX`1#hCo ziHOz>)=~|XI6BA80JoJj*lk1u4!<}cJ!m6$1B8my9BQ=R*~k;UDZ(xV~+G z9EBK~FYF4X$M@F$+$f8(EvZwhTSzsS%^|Q`$&J`bhgg-=FTEH0AR(g#Ate~0Rau~N z0`i)f+s^KH95XX~WNG`l`6TeGq^co0Q1OO3DI6PIjp^`_}XspZt%K{<(JI7)iW88 zCPFR4mr1rZTdVN#jL4(LzPPd2!Rq2#iR9N`%3lC?4l@eWl;n?oDWw4eUXJ@j z+Fr*G@=Mv>mI&NRlZfA3X8o`kyGTk0(PvdZNGWFx-?{O|^jdbrPJNcY&^l(;aexO6 z8x6sBX+tomGht06Q~%`UfS8_Y#MLRc&B9lM$}EL?J1Xwx94!0NJ9p!ijsTRBwSvsZ zLrNBXNe6r&IGakDp#0_sV6rof)QlSV6fpL{!H?w-C!?|NE$N-s!Ga}|Ctr{Qo9UaY z%TN6{kBlIQ({wq(;YrHxhY~L_fg5ec!_ym{Z4L1p3a}4t3x^(K66BQLIB{iIRI!w`XQR)! zSXxj*nPnk-bR`faQlLPa)9O$wCfCxzs3pal_H;UXZ*4#-mp#_f=DByM4>Tohr{Kt0 z`K`~I10F_B_t7p*!p5RmZ!hEw>}nNftLHYqel`I?A6V!{e878d7^O|2dAFX zl@jjKq#~1^F99{#LLwSWY+98k?xIGZvoNe2OkI+M8Y#P)AOK{!SU5cvJ0i1Y<9?zgFULmPN#6qFJ=9+=apwgW>W&%?+zRb}h=GeI2CD z(P^85%NUryx6;?y=&^Cfq!OI1q|Gyf#$CDBRMvNGho%ga@g`;1gDP2X_OGbDXz%53 z<`+rPXl(6!rdd6e+2jDsy#&j!r0DlI*=#d5lFpXTxFyIll&iJ%ZC)-FGfY30ZPwn4 zljR_rJ+mkWJqm#7hYE-aa&WhkVT@#9b>t4p zH0qCb@VY)TTP@tu1f_w!Pmymco!If zt+r5jG>4q!&a3OZHnIA?n6`mvf5PUY10p*}(Z>NXHS4&y?j9k~;P&cP*HGqLTC$5* z_w4udGuE<+&31vl&foVKVVTC~xiSVFr2=xOIKiwlj=={qy{5ejQUxUmT2iw=E54Vh zC-#Kld7lg9rtJ@Z@4iPT;kR8@Fz~HC!?2N|i`~zyFYT*=swI*$x>vQH5s}_U)mDmr zkx8djVt|h?O`4!*N&doS0l@3+to2ELgRrTj-o05h7rt-cUh#b!V6{O+%*UP5s&QgW26+YVA1Cu8$wcO6TT$$<1-i`bg1-a8493dwG} zwpw4c3))BF9&2u^xe!A+w5OG6&z#?vGj3zRIn(7gic^0fW64)`D?L4l*CubgY}X(e ze<2FL^DsA2y?ViQP6T4K{nK{K3W8jIFP~`O{b>KEi%$iDdz-s>Zl;C<E=dURF}m z?5(bp;w}hwrsW;iu5-cz!C8p&x7RF{TPHu?uI6sc7JsHtj z3n#8|3`oeJ8B^|u`um{Ni5I7~M}6`aAsgYjenef)X1l3%_|bG(($j)OD%4&BZr+Ou z^rpz%WRJ#8(ldqjP1@WF5u%$xIz%TWSu(uuC5DdzopW=_nbcZ#{ppv?vBa*>cHag< z>Jl;yu72s`7H+gSp55!`yRG?*eKYX_O^Cm#EfcC5x`}u19f-kt8ueaA_p_3XtDGV z=Uwy^_Irw!^jgDKWI>b6oZ}_mGNaQBq0Ai98^rg;0tHvM71Pa5KA9>V1Sn2P5?t1;hi6iQJWE)9$0j_kw81ZvJz6YBmq!%EHef z;dycfn~Oqxf&6Le=$k*R5LD5uB5(C&iY5rr*y4y&#w_vIySVft-%!GP2Fx_HyTja=B`+*X_A?R?XR^Vr66){rRX zqwgamg$MfN*te^|vyLA~O(DoM?n8bhzT@G8zz;9?wfCo1zBE)bQT`x(-qyX5jbr>_ zN(D+8osYiK^0Iz)FSPhw!gXPr41>*cLbvruNV=}gC2`>aC}M zQkz^agZb%6<6`mgvze!5GWG>$hMqqbUkabiK#mz;8mVgVUp_dwou2~Zq?2)-i#^Nw^Gm9(3g)SS5LZRN*$?? z&W+`8JRsO4MM|vC$qf!`A5O2-F|^pTO}J*zS|+&yhvAoB_epKPIeYEk&CoktD+pr1 za;1J5*AWewF1lj8!Nkfl?ZkSkJE(fZ_4>_M>3zVny1!A4!%ogC*|&JY8>M$5Tm|`> z1(6ATGPX5&v{xjSy8>3>?NKN{v}rYQ({--TWsl809bw~KV&2l?oXZ;2+DG`Hznh&NWK=WjmDXhOX-G2?p*wPGs!4GnDS zeW~v2*(ic~aUMP7Bkn7K_oD4Pc80DPH#c&@s@9| zH)~I+b)Ryz_-1RH>WT`%3qj!ZjEZIYE>?IGx;z{0G24lqhh`oH1*1)+>zM1%mLB<3 zCsLQm!*dzCKPoJl^W2y6*6Cmb*NMmVas~T{y@{mZGL}rg5vScY=s>WC{6}eY9oqPM zyPtmJ?v`?QgzH>llW2RPhLNv%Ux~VGXI{0Vd!GyG`y{NSdJs38fvn!SPWNrpZ;wfO@N4O zb~1+Hxt~XG(+A|(%Q(fqpDMk1UvLU&pW?12OxoFl@x9!S-$#;4Kg)!1Cr|4N7$mGD zv$Xpbx6cAhG;@@{M?580=MNBqxOf-JST^%d03djzP>H23m6i5`kjS8;nLplX_LUQU z1GC-kA6<}9exZuPXBA_K3Y;9|AbL5}`VP8|=ohiBns_hkxNh%=y!C8P8|-rB6)02n z9+z*-qX}_);9(-7V923?TWZVA=}qF2?!)*JkKg<;_u*1a>F!*3&*|gIaP&}p6_aoS zavDFdRgc!x&C$>*koOsO_QR7xdDAcVHKK{s1E9Z65~vl}tMEOo7UomZlO5W3`-KRR zfSeqRn7g)Lc>e*b$kjV%7*2cDIpC%i@dEJgqKgsqvAo*rD@AjjZd*_J>r20vb!DB? zdvlI!Wo5ycbtuTkm$gSg380C5U{bH(AmkvqQ@ctd-|BMh?%XER#aBNPA0`^qttR&N z->+T??VDwT?KvbH$QB#^LAAN@a4IUz439%i9{o)AR12zCjUVKCzl)CCa~x?min_k= zjrrQZ7OEU_4Rg&Wd(PHm>szzn=_8HhM_+0QHb3o4?rO@|_L+gU^}T?fo6Wx!hA-Zg zB6dHlCswyKH<_a4MaYm%WqEtLA6;afNBgkaf>q0Ba1x88eNPDE5t!4{{`at1+pU_p72}iT0=eoTO!X~hm$i>0f zD7h@()j!wn@!e1xZo6NjI7VDUlitu07HkJIp!HVWU3*{{K(1uN`mhx{^1z`$9X^n^u(;3x-3dwouf8w{ zDxCN-UQh7{4aoxq>ICgI1D6$JUQXp5&0qc4^W{W6b7TW4^O{Xod2gebA39k6w&av= zR|wV%6K?v-l<*#z+au|(?LF<9E;lExeUv8lSzo8{wuevgcIpWs?c8+tyW?+13%9?z zExf~5%BTjI7*e>ofu>)*yKZq}bO2 z7Ye?>2P|P?Qqs}Rpj));W0&wBw-~BQvA;XiF$sbd%`QXrD7A}Bo#S%*4%>NPJ zA@j#u^6WV}rh3YkDv?dlEH-o*<%2_<>wn$IKf#IYu=T2#-`)iRuE&|@6`r`B#$v(Xz$ImUF1 z0Vq!N`CXhy{-K3zfgA6yJ)&&a3P_y@?gh#u&QH(CZ?J2xt{Vz$`hJSWNWzjU6ckBIFDG2BntLTmih{NQIRN!{2G` z4TAn#&q^tke8O4arYKEd1Suc%UlrcShj}|0TAzmeMc6<8Tv+vxwp{!`AIwkv>20B> z(`xo#^CurE2}J&G)*bp5(>-0g_+`aYf$Rf2`Qd7$s~$b0?K)jR(wswAJp zLHe4-D4zj2tlXOirv8r%{gb#4D<8>&nov3tnmd7`SbEU=l)|dV1Yc2cYRh77O0{&% zx4DQ(?(eN{YfTz;JRJ0Nz}Yon7_mo`EpS&VPWW7H1?TIq>*sq)4l|9+}(J{@}M5%Vxt zFy?{T!`ibXhHjAFtA6_*dZd!+F^(>#v^KkQeBqPo3+4B%)xDrae!7cKq^&^414Dn5 z%cR-gUwlDW(liG{v`6;fMvKAU$vD-%r2*}s0jXk0cD$;;2K-|U(TmY zsuWf{Y-y0}ZO28lwJ5aTPps#-T%u}c{oJF_h9Y%-37J!Q!M7fmIHO!7I(M5D8>R`2Z=MqwqADGyWFB{p7{avgmyq!8E z;ERmN+oU*HGlqd%$E&U zh&_yoF-Id7V4KInE8rZJlw@;%7P#24b;}fWrEwqtJk_uI;?^AO(if}Ma8fAKA|^>Y zhnhV-h8K!0*-y`ub!GMtvGjL5>(+ zc|~dZKI$IwxHRWPbqc(lihy5`|m&W>j3eU;1OX%$rAnjKmY6R$Q|zO z)gCndL)!e;Gk^YhKmys|s<0BHba?+CpZasT{c(V|b<371y!Lm^^bh3@rqh!P@3Yx{ z_uQxK_aCOlUn|G~oR<9hKBfHszuxrsFL|2{s3ow*^pA7>A6`lRHZgJtC$7-@?^o)7 z*_!~ciR|s$?fzi{{Lj<{GnYUY9P433F(d=R2co|H!`k{^R`4&& z2K>vihyG>RKmL`n|4LcV#N}Tp`>$aDT5|ns82oD({A(D1DP{lKvi}+e{~8AW8V11K f{Qu1`Aj%it3Djp-qV_ug{@uQ%b+h<}`Sbq=L4{jA literal 0 HcmV?d00001 diff --git a/docs/nx-cloud/private/kubernetes-setup.md b/docs/nx-cloud/private/kubernetes-setup.md deleted file mode 100644 index 330e694d79fe7..0000000000000 --- a/docs/nx-cloud/private/kubernetes-setup.md +++ /dev/null @@ -1,282 +0,0 @@ -# Set Up Nx Cloud on Kubernetes - -A lot of organizations deploy Nx Cloud to Kubernetes. - -This guide references the [nx-cloud-helm](https://github.com/nrwl/nx-cloud-helm) repo which contains: - -- Nx Cloud Helm Chart -- Instructions on how to install Nx Cloud using Helm -- Instructions on how to install Nx Cloud using kubectl. See [here](https://github.com/nrwl/nx-cloud-helm/blob/main/no-helm/README.md). - -## Deployments on AWS/EKS - -If you're deploying on EKS, check out our [AWS Guide](https://github.com/nrwl/nx-cloud-helm/blob/main/aws-guide/AWS-GUIDE.md). Otherwise, continue reading below. - -## Installing Using Helm - -Steps: - -1. Deploy MongoDB Kubernetes Operator - - using helm: https://github.com/mongodb/helm-charts - - using kubectl: https://github.com/mongodb/mongodb-kubernetes-operator -2. Create a mongodb replica set -3. Create a secret -4. Install Nx Cloud using helm - -### Step 1: Deploy MongoDB Kubernetes Operator - -If you are using a hosted MongoDB installation (e.g., Mongo Atlas or CosmosSB, or you are running one yourself), you can -skip steps 1 and 2. - -``` -> helm repo add mongodb https://mongodb.github.io/helm-charts -> helm install community-operator mongodb/community-operator -``` - -### Step 2: Deploy a MongoDB replica set - -``` -> kubectl apply -f examples/mongodb.yml -``` - -This will create a secret. You can get the value of the secret as follows: - -> kubectl get secret cloud-mongodb-nrwl-api-admin-user -o go-template='{{range $k,$v := .data}}{{"### "}}{{$k}}{{"n"}}{{$v|base64decode}}{{"nn"}}{{end}}' - -You might need to wait a bit for the Pods to be created before this secret will be available. - -The output of the command can be a bit confusing (you are only interested in the second part of the output). The default connection string for the Mongo Community Operator will look like -this: `mongodb+srv://admin-user:DB_PASSWORD@cloud-mongodb-svc.default.svc.cluster.local/nrwl-api?replicaSet=cloud-mongodb&ssl=false` -. You should be able to use this value. - -Take this connection string and paste it into your `examples/secret.yml`, replacing the placeholder value. - -### Step 3: Create a secret - -With the values updated, create a secret by running `kubectl apply -f examples/secret.yml` - -### Step 4: Install Nx Cloud using helm - -``` -> helm repo add nx-cloud https://nrwl.github.io/nx-cloud-helm -> helm install nx-cloud nx-cloud/nx-cloud --values=overrides.yml -``` - -`examples/overrides` contains the min overrides files. You need to provision: - -1. The image tag you want to install -2. `nxCloudAppURL` which is the url used to access ingress from CI and dev machines ( - e.g., `https://nx-cloud.myorg.com`). -3. `secret/name` the name of the secret you created in Step 3. -4. `secret/nxCloudMongoServerEndpoint`, the name of the key from the secret. - 5`secret/adminPassword`, the name of the key from the secret. - -If you only applied the secret from Step 3, the only thing you will need to change is `nxCloudAppURL`. - -## Cloud Containers - -The installation will create the following: - -1. nx-cloud-frontend (deployment) -2. nx-cloud-api (deployment) -3. nx-cloud-nx-api (deployment) -4. nx-cloud-file-server (deployment) -5. nx-cloud-aggregator (cron job) - -## Ingress, IP, Certificates - -You can configure Ingress. For instance, the following will see the ingress class to 'gce', the global static ip name -to 'nx-cloud-ip', and will set a global Google managed certificate. - -```yaml -image: - tag: 'latest' - -nxCloudAppURL: 'https://nx-cloud.myorg.com' - -ingress: - class: 'gce' - globalStaticIpName: 'nx-cloud-ip' - managedCertificates: 'cloud-cert' - -secret: - name: 'cloud' - nxCloudMongoServerEndpoint: 'NX_CLOUD_MONGO_SERVER_ENDPOINT' - adminPassword: 'ADMIN_PASSWORD' -``` - -This configuration will look different for you. You will have a different global static ip and your cert name will also -be different. If you are interested in creating the two using GKE, check out the following links: - -- [Reserving a static external IP address](https://cloud.google.com/compute/docs/ip-addresses/reserve-static-external-ip-address) -- [Using Google-managed SSL certificates](https://cloud.google.com/kubernetes-engine/docs/how-to/managed-certs) - -If you aren't using GKE, `ingress.class` will also be different. For example, see [our example config for AWS](https://github.com/nrwl/nx-cloud-helm/blob/main/aws-guide/helm-values.yml#L7) or check out the AWS Load Balancer set-up section [here for AWS set-up instructions.](https://github.com/nrwl/nx-cloud-helm/blob/main/aws-guide/AWS-GUIDE.md#3-install-a-load-balancer) - -If you need to have a detailed Ingress configuration, you can tell the package to skip defining ingress: - -```yaml -image: - tag: 'latest' - -nxCloudAppURL: 'https://nx-cloud.myorg.com' - -ingress: - skip: true -``` - -⤵️ and then define it yourself - -```yaml -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: nx-cloud-ingress - annotations: - - labels: - app: nx-cloud -spec: - rules: - - http: - paths: - # define the next /file section only if you use the built-in file server - - path: /file - pathType: Prefix - backend: - service: - name: nx-cloud-file-server-service - port: - number: 5000 - - path: /nx-cloud - pathType: Prefix - backend: - service: - name: nx-cloud-nx-api-service - port: - number: 4203 - - path: /api - pathType: Prefix - backend: - service: - name: nx-cloud-nrwl-api-service - port: - number: 4000 - - path: /graphql - pathType: Prefix - backend: - service: - name: nx-cloud-nrwl-api-service - port: - number: 4000 - - path: /auth - pathType: Prefix - backend: - service: - name: nx-cloud-nrwl-api-service - port: - number: 4000 - - path: /download - pathType: Prefix - backend: - service: - name: nx-cloud-nrwl-api-service - port: - number: 4000 - - path: /download - - pathType: Prefix - backend: - service: - name: nx-cloud-frontend-service - port: - number: 8080 -``` - -### Step 5: Connect Your Workspace - -Run `NX_CLOUD_API=https://nx-cloud.myorg.com nx connect`. Click on the link to connect the workspace -to your admin account. - -## Variations - -### External File Storage - -If you use AWS or Azure, you can configure Nx Cloud to store cached artifacts on S3 or Azure Blob. In this case, you -won't need the PVC or the file-server container. S3 and Azure Blob also tend to be faster. - -For S3 buckets, see the [AWS Guide](https://github.com/nrwl/nx-cloud-helm/blob/main/aws-guide/AWS-GUIDE.md#6-external-s3-access) - -For Azure: - -```yaml -image: - tag: 'latest' - -nxCloudAppURL: 'https://nx-cloud.myorg.com' - -azure: - enabled: true - container: 'nx-cloud' - -secret: - name: 'cloudsecret' - nxCloudMongoServerEndpoint: 'NX_CLOUD_MONGO_SERVER_ENDPOINT' - adminPassword: 'ADMIN_PASSWORD' - azureConnectionString: 'AZURE_CONNECTION_STRING' -``` - -Note that the secret for setting up Azure must contain `AZURE_CONNECTION_STRING`. - -### GitHub Auth - -To use GitHub for user authentication, you can use the following configuration: - -```yaml -image: - tag: 'latest' - -nxCloudAppURL: 'https://nx-cloud.myorg.com' - -github: - auth: - enabled: true - -secret: - name: 'cloudsecret' - nxCloudMongoServerEndpoint: 'NX_CLOUD_MONGO_SERVER_ENDPOINT' - githubAuthClientId: 'GITHUB_AUTH_CLIENT_ID' - githubAuthClientSecret: 'GITHUB_AUTH_CLIENT_SECRET' -``` - -Note that the secret must contain `GITHUB_AUTH_CLIENT_ID` and `GITHUB_AUTH_CLIENT_SECRET`. -Read [here](https://nx.dev/nx-cloud/private-cloud/auth-github) on how to get those values. - -### GitHub Integration - -To enable the GitHub PR integration, you can use the following configuration: - -```yaml -image: - tag: 'latest' - -nxCloudAppURL: 'https://nx-cloud.myorg.com' - -github: - pr: - enabled: true - # apiUrl: '' uncomment when using github enterprise - -secret: - name: 'cloudsecret' - nxCloudMongoServerEndpoint: 'NX_CLOUD_MONGO_SERVER_ENDPOINT' - githubWebhookSecret: 'GITHUB_WEBHOOK_SECRET' - githubAuthToken: 'GITHUB_AUTH_TOKEN' -``` - -Note that the secret must contain `GITHUB_WEBHOOK_SECRET` and `GITHUB_AUTH_TOKEN`. -Read [here](https://nx.dev/nx-cloud/private-cloud/github) on how to get those values. - -## More Information - -You can find more information about Nx Cloud and running it on -prem [here](https://nx.dev/nx-cloud/private-cloud/get-started). diff --git a/docs/nx-cloud/private/standalone.md b/docs/nx-cloud/private/standalone.md deleted file mode 100644 index 7f1b34491aa87..0000000000000 --- a/docs/nx-cloud/private/standalone.md +++ /dev/null @@ -1,315 +0,0 @@ -# Running a Standalone Container - -Nx Cloud can be deployed in two ways: - -- [Using Kubernetes](https://github.com/nrwl/nx-cloud-helm) (several containers working together) -- Using a single standalone container (NOT RECOMMENDED) - -The flags and the capabilities are the same between the two, but the Kubernetes setup is more robust and better -documented. This document covers the latter version. - -**Nx Cloud consists of 3 parts:** - -1. The stateless Nx Cloud service -2. MongoDB database -3. File server - -By default, the container created by the `nxprivatecloud/single-image` image will create two of them: the stateless Nx Cloud service, and the file server. Using a single container is the easiest way to set it up, but it isn't the most robust way to run Nx Cloud. - -You will then need to host the database separately: - -- Either by using a service such as Mongo Atlas -- Or running it yourself. For that, we created the `nxprivatecloud/nx-cloud-mongo` image. - -The instructions will go through running the embedded file server, and then, at the end, will talk about hosting your cached artefacts on an external service, such as Amazon S3. - -## Running Nx Cloud - -### Step 1: Pull the Image - -```shell -> docker pull nxprivatecloud/single-image -``` - -To update the version of Nx Cloud, pull the new version of the image and run it against the same mount (see -below). - -### Step 2: Create a Container - -Depending on how your infrastructure is set up, you can either run Nx Cloud using HTTPS or HTTP. If you have a -proxy/load-balancer in front of Nx Cloud, you will likely want to run Nx Cloud using HTTP (the -proxy/load-balancer will handle TLS). Otherwise, you will likely want to run Nx Cloud using HTTPS. - -**To create a container:** - -1. You will need to create a directory on the host machine where data will be stored. (_This is not necessary if you are - running the file server separately. See below._) -2. You will need to know the URL that the Nx Cloud installation can be accessed by (see `NX_CLOUD_APP_URL` below). - - `NX_CLOUD_APP_URL` should be accessible from your CI and dev machines. - - `NX_CLOUD_APP_URL` can be set with an HTTP or HTTPS url. In a case where you are using a proxy/load-balancer, you - can still put HTTPS (the url will be resolved by the proxy before hitting the app). - - `NX_CLOUD_APP_URL` is likely to be an external IP/domain of the load balancer. -3. If you are running Nx Cloud using HTTPS, you need to generate or obtain an SSL certificate and an SSL private - key. - -**Once you obtain all the needed information, you can run the following:** - -**Using HTTPS** - -```shell -> docker create --name cloud \ - - -p 443:8081 \ - -e CERT_KEY="$(cat ./tools/certs/key.pem)" \ - -e CERT="$(cat ./tools/certs/cert.pem)" \ - -e NX_CLOUD_APP_URL="https://cloud.myorg.com" \ - -e ADMIN_PASSWORD=admin \ - -v /data/private-cloud:/data nxprivatecloud/nxcloud:latest -``` - -**Using HTTP (no proxy)** - -```shell -> docker create --name cloud \ - - -p 80:8081 \ - -e NX_CLOUD_APP_URL="http://cloud.myorg.com" \ - -e ADMIN_PASSWORD=admin \ - -v /data/private-cloud:/data nxprivatecloud/nxcloud:latest -``` - -**Using HTTPS via proxy** - -```shell -> docker create --name cloud \ - -p 80:8081 \ - -e NX_CLOUD_APP_URL="https://cloud.myorg.com" \ - -e ADMIN_PASSWORD=admin \ - -v /data/private-cloud:/data nxprivatecloud/nxcloud:latest -``` - -**Let's see what those options mean:** - -- `443:8081` maps the internal port 8081 to 443, so it can be accessed in the browser without specifying the port. 80: - 8081 works the same way when you use HTTP instead of HTTPS. -- `CERT_KEY` and `CERT` contain the values of private key and cert. The file extensions of the cert and key files can be - different, but as long as they are in the PEM format (which is the case if you use, for instance, OpenSSL), the - command will work. -- `NX_CLOUD_APP_URL` is the URL the cloud can be accessed by (e.g., `https://nxcloud.privateurl.com`). **Important: - Unless you are experimenting, it won't be localhost. It has to be the URL that your CI and your developer machine can - reach. Also note, there is no trailing slash in the URL.** -- `ADMIN_PASSWORD` contains the password of the admin user. The admin user is created the first time you run cloud, you - can remove this env variable after that. Instead of an admin password, you can also - follow [the instructions here](/nx-cloud/private-cloud/auth-github) to set up GitHub auth. -- `-v /data/private-cloud:/data` sets up the volume where the data (the cached artefacts) is stored. `/data/private-cloud` refers to a folder - on your machine, `/data` is the shareable folder from the Docker image. - -### Step 3: Run the Container - -Once you create the container, you can start it using: - -```shell -> docker start cloud -``` - -Imagine `NX_CLOUD_APP_URL` is set to `https://nxcloud.privateurl.com`. - -Now, go to https://nxcloud.privateurl.com to see cloud running. You can log into the account -using `admin/ADMIN_PASSWORD`. - -### Step 4: Connect Your Workspace - -Run `NX_CLOUD_API=https://nxcloud.privateurl.com` nx connect. Click on the link to connect the workspace -to your admin account. - -### Optional step 5: set up GitHub auth - -Follow the [instructions here](/nx-cloud/private-cloud/auth-github) to set up GitHub OAuth authentication so you can -invite other members in your team to the workspace. - -### Optional step 6: set up GitHub Pull Request integration - -You can [optionally configure Nx Cloud](/nx-cloud/set-up/github) to post build stats directly on your GitHub -pull requests. - -### Optional step 7: Setting Up Proxy - -If your container cannot access `api.nrwl.io` directly and has to talk via a proxy, you can -add `-e HTTPS_PROXY="https://myproxy.myorg.com"` to the container creation command. - -## Running the Mongo Database - -Nx Cloud uses MongoDB to store its metadata. You will need to provision the `NX_CLOUD_MONGO_SERVER_ENDPOINT` env variable when -creating a container, like so: - -```shell --e NX_CLOUD_MONGO_SERVER_ENDPOINT="mongodb://domain-with-mongo:27017/nrwl-api" -``` - -By default, Nx Cloud requires Mongo 4.2+. If you are using an older version of Mongo (for instance, if you are using -Cosmos DB), please add - -```shell --e NX_CLOUD_USE_MONGO42=false -``` - -### Deploy Mongo on your Kubernetes engine or Docker VM - -See [here](https://github.com/nrwl/nx-cloud-helm/blob/main/MONGO-OPERATOR-GUIDE.md) for a full guide on running Mongo yourself. - -### Using CosmosDB - -If you are deploying to Azure, you might have access to CosmosDB. See here for more information. - -### Using Mongo Atlas - -[Mongo Atlas](https://mongodb.com/) is a great option for deploying MongoDB. - -## Using External File Storage - -By default, Nx Cloud is going to start a file server and store the cached artifacts in the provided volume. But -you can also configure Nx Cloud to use an external file storage. At the moment, only S3 and Azure Blob are -supported. - -### Using S3/Minio - -To configure S3 as a file storage, provision the `AWS_S3_ACCESS_KEY_ID`, `AWS_S3_SECRET_ACCESS_KEY`, and `AWS_S3_BUCKET` -env variables when creating the Nx Cloud docker container, like so: - -```shell --e AWS_S3_ACCESS_KEY_ID="SOMEKEY" --e AWS_S3_SECRET_ACCESS_KEY="SOMESECRETKEY" --e AWS_S3_BUCKET="nx-cache-bucket-name" -``` - -If you are using an accelerated bucket, add: `-e AWS_S3_ACCELERATED=true` - -If you are using a local S3 installation (e.g., Minio), you can set the endpoint as follows: - -```shell --e AWS_S3_ENDPOINT="https://local-installation.myorg.com" --e AWS_S3_ACCESS_KEY_ID="SOMEKEY" --e AWS_S3_SECRET_ACCESS_KEY="SOMESECRETKEY" --e AWS_S3_BUCKET="nx-cache-bucket-name" -``` - -{% callout type="note" title="On cache item expiration time" %} -Remember to -set [a cache item expiration time](https://docs.aws.amazon.com/AmazonS3/latest/userguide/lifecycle-expire-general-considerations.html) -. The default is currently 4 weeks. If you would like to keep items for longer, for example for 8 weeks, please remember -to set the `NX_CACHE_EXPIRATION_PERIOD_IN_DAYS=56` env variable as well, so the container knows when to expire the Mongo -cache entries as well. -{% /callout %} - -### Using Azure - -To configure Azure Blob as a file storage, provision the `AZURE_CONNECTION_STRING`, `AZURE_CONTAINER` env variables when -creating the Nx Cloud docker container, like so: - -```shell --e AZURE_CONNECTION_STRING="SOME-CONNECTION-STRING" --e AZURE_CONTAINER="files" -``` - -To obtain the `AZURE_CONNECTION_STRING` value go to your "Storage Account" and click on "Access Keys". You will also -need to create a container in your storage account before starting the Nx Cloud container. - -If you use an external file storage solution, you don't have to provision the volume. - -{% callout type="note" title="Cache expiration time" %} -See note above about setting a cache expiration time. For Azure blob -storage, [see this guide](https://docs.microsoft.com/en-us/azure/cdn/cdn-manage-expiration-of-blob-content). -{% /callout %} - -## Configure Memory Limits - -By default, the Nx Cloud container is configured to run on an instance with 8GB of RAM. - -If you have a container with 4GB of RAM, you can decrease the memory limits by setting the following env variables: - -- `NX_CLOUD_FILE_SERVER_MEMORY_LIMIT=500` -- `NX_CLOUD_API_MEMORY_LIMIT=800` - -Example: - -```shell -> docker create --name cloud \ - -p 80:8081 \ - -e NX_CLOUD_APP_URL="https://cloud.myorg.com" \ - -e ADMIN_PASSWORD=admin \ - -e NX_CLOUD_FILE_SERVER_MEMORY_LIMIT=500 \ - -e NX_CLOUD_API_MEMORY_LIMIT=800 \ - -v /data/private-cloud:/data nxprivatecloud/nxcloud:latest -``` - -The right amount of RAM depends heavily on how you run Nx Cloud. - -- The `NX_CLOUD_FILE_SERVER_MEMORY_LIMIT` value is only relevant if you use the built-in file server. - -For instance, if you use S3 to store the cached artifacts, even 2GB might be sufficient. You can set the following limit: - -- `NX_CLOUD_API_MEMORY_LIMIT=800` - -If you run everything in the Nx Cloud container, then 5GB is much preferred. - -## Configure Artifact Expiration When Using Built-in File Server - -By default, the Nx Cloud container is going to remove cached artifacts after two weeks. You can change it by setting `NX_CACHE_EXPIRATION_PERIOD_IN_DAYS` when starting the container. - -Example: - -```shell -> docker create --name cloud \ - -p 80:8081 \ - -e NX_CLOUD_APP_URL="https://cloud.myorg.com" \ - -e ADMIN_PASSWORD=admin \ - -e NX_CACHE_EXPIRATION_PERIOD_IN_DAYS=5 \ - -v /data/private-cloud:/data nxprivatecloud/nxcloud:latest -``` - -## Self-Signed Certificates - -If you have a self-signed certificate, you will have to provision `NODE_EXTRA_CA_CERTS`. The env variable should point to a PEM file with either your certificate, or the root certificate your certificate was created from. Though this can be accomplished with a CLI command like `NODE_EXTRA_CA_CERTS=./tools/certs/cert.crt nx test myapp`, you will most likely want to configure it as a global env variable (for instance in your `.bashrc` file). - -A self-sign certificate registered in your OS won't be picked up by Node. Node requires you to provision `NODE_EXTRA_CA_CERTS`. - -## Migration guide from `nxprivatecloud/nxcloud` to `nxprivatecloud/single-image` - -The old version of our Docker image, `nxprivatecloud/nxcloud`, is no longer being maintained. This section will explain how to migrate to the new standalone image, `nxprivatecloud/single-image`. - -Unlike `nxprivatecloud/nx-cloud`, the `nxprivatecloud/single-image` container does not come with MongoDB included. This makes for a much simpler image, based on Alpine (and not Ubuntu), with less chances for security vulnerabilities. However, it does require you to connect to an external Mongo instance. Below we'll cover the two possible migration scenarios. - -#### You are connecting to an external Mongo instance - -If you are currently connecting to an external Mongo instance, then migrating to the new image is as simple as switching the Docker tag from `nxprivatecloud/nxcloud` to `nxprivatecloud/single-image`. All the other configuration options can stay the same. - -#### You are running Mongo inside the Docker image - -If you are currently relying on the image to host Mongo, we will need to move that to an external instance. - -##### Starting fresh with a dedicated Mongo instance - -1. We recommend setting up a dedicated Mongo host, on Atlas [as described above](#using-mongo-atlas). This means you will lose you current workspace set-up, but it is the easiest migration path and the most maintanable one. - 1. To do this, get the connection string from Mongo Atlas - 2. And configure the image with it: `-e NX_CLOUD_MONGO_SERVER_ENDPOINT="mongodb://domain-with-mongo:27017/nrwl-api"` - 3. That's it! -2. If you cannot use Atlas or Azure CosmosDB within your org, then you'll need to run our dedidcated Mongo Docker image. Instructions for this approach are described below. - -##### Migrating your data to a separate self-hosted Mongo instance - -1. When running the image, you are probably mapping to the host volume like this `-v /data/private-cloud:/data:Z` -2. That data folder is where the image stores all its persistent data that needs exist between restarts or updates of the image. Inside it you'll find: - - 1. In the old image (`nxprivatecloud/nx-cloud`): - 1. `/data/file-server`: if you are using the built-in file-server, this is where you'll find all the cached artefacts. If you are using an external S3 buckets this folder won't exist. - 2. `/data/mongo`: this is where Mongo stores all its files. - 2. In the new image (`nxprivatecloud/single-image`): - 1. `/data/file-server` (if using the built-in file-server, otherwise you don't need to map anything) - -3. Copy the contents of `/data/mongo` folder from the host where you previously used to run Mongo, to the new host where you'll run the dedicated Mongo image -4. Run Mongo as described [here](https://github.com/nrwl/nx-cloud-helm/blob/main/MONGO-OPERATOR-GUIDE.md) - 1. In there, you'll find instructions to map the `$PWD/mongo-data:/data/db` folder to your host - 2. Copy the data from Step 1. above into the new mapped folder above. -5. Get the connection string for the above image -6. Start your `nxprivatecloud/single-image` container with the `-e NX_CLOUD_MONGO_SERVER_ENDPOINT="mongodb://52.201.253.213:27017/?authSource=admin&directConnection=true"` env var -7. You can remove the `/data/mongo` folder from the `single-image` mapping (you will need to keep `/data/file-server` if you not using an external S3 bucket) diff --git a/docs/shared/reference/sitemap.md b/docs/shared/reference/sitemap.md index 00974a9797dec..564e8aa500a41 100644 --- a/docs/shared/reference/sitemap.md +++ b/docs/shared/reference/sitemap.md @@ -256,16 +256,15 @@ - [Access Tokens](/nx-cloud/account/access-tokens) - [Security Scenarios](/nx-cloud/account/scenarios) - [End to End Encryption](/nx-cloud/account/encryption) - - [On Prem](/nx-cloud/private-cloud) + - [Enterprise + On Prem](/nx-cloud/private-cloud) - [Get Started](/nx-cloud/private-cloud/get-started) - [Authenticate with a Single Admin](/nx-cloud/private-cloud/auth-single-admin) - [Authenticate with GitHub](/nx-cloud/private-cloud/auth-github) + - [On-Prem VM Setup](/nx-cloud/private-cloud/ami-setup) - [Authenticate with GitLab](/nx-cloud/private-cloud/auth-gitlab) - [Authenticate with BitBucket](/nx-cloud/private-cloud/auth-bitbucket) - [Authenticate via SAML](/nx-cloud/private-cloud/auth-saml) - [Advanced Configuration](/nx-cloud/private-cloud/advanced-config) - - [Kubernetes Setup](/nx-cloud/private-cloud/kubernetes-setup) - - [Standalone](/nx-cloud/private-cloud/standalone) - [Reference](/nx-cloud/reference) - [Configuration Options](/nx-cloud/reference/config) - [nx-cloud CLI](/nx-cloud/reference/nx-cloud-cli) diff --git a/nx-dev/nx-dev-e2e/src/e2e/nx-cloud-documentation.cy.ts b/nx-dev/nx-dev-e2e/src/e2e/nx-cloud-documentation.cy.ts index adac08ba2b22a..4a496882152cf 100644 --- a/nx-dev/nx-dev-e2e/src/e2e/nx-cloud-documentation.cy.ts +++ b/nx-dev/nx-dev-e2e/src/e2e/nx-cloud-documentation.cy.ts @@ -36,7 +36,7 @@ describe('nx-dev: Nx Cloud section', () => { path: '/nx-cloud/account/encryption', }, { - title: 'Running Nx Cloud on Prem', + title: 'Running Nx Cloud Enterprise', path: '/nx-cloud/private-cloud/get-started', }, { @@ -51,6 +51,10 @@ describe('nx-dev: Nx Cloud section', () => { title: 'GitLab Auth', path: '/nx-cloud/private-cloud/auth-gitlab', }, + { + title: 'Setting up a dedicated NxCloud VM', + path: '/nx-cloud/private-cloud/ami-setup', + }, { title: 'BitBucket Auth', path: '/nx-cloud/private-cloud/auth-bitbucket', diff --git a/nx-dev/nx-dev/redirect-rules.js b/nx-dev/nx-dev/redirect-rules.js index 414242945285c..eaa591dd3a8f1 100644 --- a/nx-dev/nx-dev/redirect-rules.js +++ b/nx-dev/nx-dev/redirect-rules.js @@ -360,6 +360,9 @@ const nxCloudUrls = { '/nx-cloud/set-up/add-nx-cloud': '/core-features/share-your-cache', '/nx-cloud/set-up/set-up-caching': '/core-features/share-your-cache', '/nx-cloud/set-up/set-up-dte': '/core-features/distribute-task-execution', + '/nx-cloud/private-cloud/standalone': '/nx-cloud/private-cloud/ami-setup', + '/nx-cloud/private-cloud/kubernetes-setup': + '/nx-cloud/private-cloud/get-started', }; /** From 62f37fa0ee5ae084d71082928eba042405f88402 Mon Sep 17 00:00:00 2001 From: Isaac Mann Date: Wed, 5 Jul 2023 08:34:34 -0400 Subject: [PATCH 002/262] docs(core): changelog redirect (#17855) --- nx-dev/nx-dev/redirect-rules.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/nx-dev/nx-dev/redirect-rules.js b/nx-dev/nx-dev/redirect-rules.js index eaa591dd3a8f1..c35422029b35b 100644 --- a/nx-dev/nx-dev/redirect-rules.js +++ b/nx-dev/nx-dev/redirect-rules.js @@ -649,6 +649,10 @@ const pluginUrls = { '/recipes/generators/modifying-files': '/plugins/recipes/modifying-files', }; +const referenceUrls = { + '/changelog': '/reference/changelog', +}; + /** * Public export API */ @@ -667,4 +671,5 @@ module.exports = { conceptUrls, nested5minuteTutorialUrls, pluginUrls, + referenceUrls, }; From 3a8810318b5fe9a3a8dc6e9ba1cd1ae039187e73 Mon Sep 17 00:00:00 2001 From: Miroslav Jonas Date: Tue, 4 Jul 2023 14:51:50 +0200 Subject: [PATCH 003/262] docs(nx-dev): move azure recipe to CI section --- docs/generated/manifests/menus.json | 32 ++++++++++----------- docs/generated/manifests/recipes.json | 40 +++++++++++++-------------- docs/map.json | 10 +++---- docs/shared/monorepo-ci-azure.md | 2 +- docs/shared/reference/sitemap.md | 2 +- nx-dev/nx-dev/redirect-rules.js | 2 ++ 6 files changed, 45 insertions(+), 43 deletions(-) diff --git a/docs/generated/manifests/menus.json b/docs/generated/manifests/menus.json index 1aef7726d7df3..e8d3610b0fa04 100644 --- a/docs/generated/manifests/menus.json +++ b/docs/generated/manifests/menus.json @@ -2169,6 +2169,14 @@ "children": [], "disableCollapsible": false }, + { + "name": "Find the Last Successful Commit in Azure Pipelines", + "path": "/recipes/ci/azure-last-successful-commit", + "id": "azure-last-successful-commit", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, { "name": "Setting up CircleCI", "path": "/recipes/ci/monorepo-ci-circle-ci", @@ -2244,6 +2252,14 @@ "children": [], "disableCollapsible": false }, + { + "name": "Find the Last Successful Commit in Azure Pipelines", + "path": "/recipes/ci/azure-last-successful-commit", + "id": "azure-last-successful-commit", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, { "name": "Setting up CircleCI", "path": "/recipes/ci/monorepo-ci-circle-ci", @@ -3212,14 +3228,6 @@ "children": [], "disableCollapsible": false }, - { - "name": "Find the Last Successful Commit in Azure Pipelines", - "path": "/recipes/other/azure-last-successful-commit", - "id": "azure-last-successful-commit", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, { "name": "Troubleshoot Cache Misses", "path": "/recipes/other/troubleshoot-cache-misses", @@ -3423,14 +3431,6 @@ "children": [], "disableCollapsible": false }, - { - "name": "Find the Last Successful Commit in Azure Pipelines", - "path": "/recipes/other/azure-last-successful-commit", - "id": "azure-last-successful-commit", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, { "name": "Troubleshoot Cache Misses", "path": "/recipes/other/troubleshoot-cache-misses", diff --git a/docs/generated/manifests/recipes.json b/docs/generated/manifests/recipes.json index ce83e22146783..dee91d895781c 100644 --- a/docs/generated/manifests/recipes.json +++ b/docs/generated/manifests/recipes.json @@ -197,6 +197,16 @@ "path": "/recipes/ci/monorepo-ci-azure", "tags": [] }, + { + "id": "azure-last-successful-commit", + "name": "Find the Last Successful Commit in Azure Pipelines", + "description": "", + "file": "shared/recipes/azure-last-successful-commit", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/azure-last-successful-commit", + "tags": [] + }, { "id": "monorepo-ci-circle-ci", "name": "Setting up CircleCI", @@ -292,6 +302,16 @@ "path": "/recipes/ci/monorepo-ci-azure", "tags": [] }, + "/recipes/ci/azure-last-successful-commit": { + "id": "azure-last-successful-commit", + "name": "Find the Last Successful Commit in Azure Pipelines", + "description": "", + "file": "shared/recipes/azure-last-successful-commit", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/azure-last-successful-commit", + "tags": [] + }, "/recipes/ci/monorepo-ci-circle-ci": { "id": "monorepo-ci-circle-ci", "name": "Setting up CircleCI", @@ -1498,16 +1518,6 @@ "path": "/recipes/other/misc-data-persistence", "tags": [] }, - { - "id": "azure-last-successful-commit", - "name": "Find the Last Successful Commit in Azure Pipelines", - "description": "", - "file": "shared/recipes/azure-last-successful-commit", - "itemList": [], - "isExternal": false, - "path": "/recipes/other/azure-last-successful-commit", - "tags": [] - }, { "id": "troubleshoot-cache-misses", "name": "Troubleshoot Cache Misses", @@ -1763,16 +1773,6 @@ "path": "/recipes/other/misc-data-persistence", "tags": [] }, - "/recipes/other/azure-last-successful-commit": { - "id": "azure-last-successful-commit", - "name": "Find the Last Successful Commit in Azure Pipelines", - "description": "", - "file": "shared/recipes/azure-last-successful-commit", - "itemList": [], - "isExternal": false, - "path": "/recipes/other/azure-last-successful-commit", - "tags": [] - }, "/recipes/other/troubleshoot-cache-misses": { "id": "troubleshoot-cache-misses", "name": "Troubleshoot Cache Misses", diff --git a/docs/map.json b/docs/map.json index fe9595f79b3b8..a5cf73848c8c8 100644 --- a/docs/map.json +++ b/docs/map.json @@ -958,6 +958,11 @@ "id": "monorepo-ci-azure", "file": "shared/monorepo-ci-azure" }, + { + "name": "Find the Last Successful Commit in Azure Pipelines", + "id": "azure-last-successful-commit", + "file": "shared/recipes/azure-last-successful-commit" + }, { "name": "Setting up CircleCI", "id": "monorepo-ci-circle-ci", @@ -1406,11 +1411,6 @@ "id": "misc-data-persistence", "file": "shared/guides/misc-data-persistence" }, - { - "name": "Find the Last Successful Commit in Azure Pipelines", - "id": "azure-last-successful-commit", - "file": "shared/recipes/azure-last-successful-commit" - }, { "name": "Troubleshoot Cache Misses", "id": "troubleshoot-cache-misses", diff --git a/docs/shared/monorepo-ci-azure.md b/docs/shared/monorepo-ci-azure.md index dd2292f19d82c..b2835eb561a02 100644 --- a/docs/shared/monorepo-ci-azure.md +++ b/docs/shared/monorepo-ci-azure.md @@ -8,7 +8,7 @@ Nx needs additional Git history available for `affected` to function correctly. {% /callout %} -Unlike `GitHub Actions` and `CircleCI`, you don't have the metadata to help you track the last successful run on `main`. In the example below, the base is set to `HEAD~1` (for push) or branching point (for pull requests), but a more robust solution would be to tag an SHA in the main job once it succeeds and then use this tag as a base. You can also try [using the devops CLI within the pipeline yaml](/recipes/other/azure-last-successful-commit). See the [nx-tag-successful-ci-run](https://github.com/nrwl/nx-tag-successful-ci-run) and [nx-set-shas](https://github.com/nrwl/nx-set-shas) (version 1 implements tagging mechanism) repositories for more information. +Unlike `GitHub Actions` and `CircleCI`, you don't have the metadata to help you track the last successful run on `main`. In the example below, the base is set to `HEAD~1` (for push) or branching point (for pull requests), but a more robust solution would be to tag an SHA in the main job once it succeeds and then use this tag as a base. You can also try [using the devops CLI within the pipeline yaml](/recipes/ci/azure-last-successful-commit). See the [nx-tag-successful-ci-run](https://github.com/nrwl/nx-tag-successful-ci-run) and [nx-set-shas](https://github.com/nrwl/nx-set-shas) (version 1 implements tagging mechanism) repositories for more information. {% callout type="note" title="Tracking the origin branch" %} diff --git a/docs/shared/reference/sitemap.md b/docs/shared/reference/sitemap.md index 564e8aa500a41..9c5f17bca2529 100644 --- a/docs/shared/reference/sitemap.md +++ b/docs/shared/reference/sitemap.md @@ -133,6 +133,7 @@ - [CI Setup](/recipes/ci/ci-setup) - [Prepare applications for deployment via CI](/recipes/ci/ci-deployment) - [Setting up Azure Pipelines](/recipes/ci/monorepo-ci-azure) + - [Find the Last Successful Commit in Azure Pipelines](/recipes/ci/azure-last-successful-commit) - [Setting up CircleCI](/recipes/ci/monorepo-ci-circle-ci) - [Setting up GitHub Actions](/recipes/ci/monorepo-ci-github-actions) - [Setting up Jenkins](/recipes/ci/monorepo-ci-jenkins) @@ -210,7 +211,6 @@ - [Using Tailwind CSS with Angular projects](/recipes/other/using-tailwind-css-with-angular-projects) - [Using NgRx](/recipes/other/misc-ngrx) - [Using Data Persistence operators](/recipes/other/misc-data-persistence) - - [Find the Last Successful Commit in Azure Pipelines](/recipes/other/azure-last-successful-commit) - [Troubleshoot Cache Misses](/recipes/other/troubleshoot-cache-misses) - [Export Project Graph](/recipes/other/export-project-graph) - [Resolve Circular Dependencies](/recipes/other/resolve-circular-dependencies) diff --git a/nx-dev/nx-dev/redirect-rules.js b/nx-dev/nx-dev/redirect-rules.js index c35422029b35b..5f52ad21c4e6a 100644 --- a/nx-dev/nx-dev/redirect-rules.js +++ b/nx-dev/nx-dev/redirect-rules.js @@ -351,6 +351,8 @@ const recipesUrls = { '/recipes/other/dte': '/recipes/example-repos/dte', '/recipes/other/deploy-nextjs-to-vercel': '/recipes/deployment/deploy-nextjs-to-vercel', + '/recipes/other/azure-last-successful-commit': + '/recipes/ci/azure-last-successful-commit', }; /** From 088018a846966609547ee818d6f3f3add0dadb22 Mon Sep 17 00:00:00 2001 From: Zayd Krunz <70227235+ShrootBuck@users.noreply.github.com> Date: Wed, 5 Jul 2023 05:50:48 -0700 Subject: [PATCH 004/262] docs(core): fixes minor typo in getting started (#17901) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Miroslav Jonaš --- docs/shared/getting-started/why-nx.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/shared/getting-started/why-nx.md b/docs/shared/getting-started/why-nx.md index 4548a78c64ccf..86a7352168b0e 100644 --- a/docs/shared/getting-started/why-nx.md +++ b/docs/shared/getting-started/why-nx.md @@ -2,7 +2,7 @@ We created Nx because developers struggle to configure, maintain and especially integrate various tools and frameworks. Setting up a system that works well for a handful of developers and at the same time, easily scales up to an entire organization is hard. This includes setting up low-level build tooling, configuring fast CI, and keeping your codebase healthy, up-to-date, and maintainable. -We wanted to provide a solution that is easy to adopt and scales. +We wanted to provide a solution that is easy to adopt and scale. ## How Does Nx Help You? From 446539a5acfa9ff59d36f1b5c01e13bdfc59083f Mon Sep 17 00:00:00 2001 From: Zayd Krunz <70227235+ShrootBuck@users.noreply.github.com> Date: Sat, 1 Jul 2023 15:21:31 -0700 Subject: [PATCH 005/262] docs(core): readability fix in caching doc Improved readability --- docs/shared/concepts/how-caching-works.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/shared/concepts/how-caching-works.md b/docs/shared/concepts/how-caching-works.md index 3946f19574b81..ca04ec79962f6 100644 --- a/docs/shared/concepts/how-caching-works.md +++ b/docs/shared/concepts/how-caching-works.md @@ -3,7 +3,7 @@ Before running any task, Nx computes its computation hash. As long as the computation hash is the same, the output of running the task is the same. -By default, the computation hash for - say - `nx test remixapp` includes: +By default, the computation hash for something like `nx test remixapp` includes: - All the source files of `remixapp` and its dependencies - Relevant global configuration From 093922812f72665f0e0ad496784c680699383ff7 Mon Sep 17 00:00:00 2001 From: Juri Date: Tue, 4 Jul 2023 23:30:44 +0200 Subject: [PATCH 006/262] docs(core): add some more info about the "why" of the automated update --- .../automate-updating-dependencies.md | 36 ++++++++++--------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/docs/shared/core-features/automate-updating-dependencies.md b/docs/shared/core-features/automate-updating-dependencies.md index 07a5f3f5eb21f..b2b47e7d0483a 100644 --- a/docs/shared/core-features/automate-updating-dependencies.md +++ b/docs/shared/core-features/automate-updating-dependencies.md @@ -1,16 +1,24 @@ # Automate Updating Dependencies -The Nx CLI provides the `migrate` command to help you stay up to date with the latest version of Nx. +Keeping a codebase updated with the latest changes in your framework of choice and tooling can be challenging. Not to mention that "tooling maintenance work" is usually hard to squeeze into your feature sprint. -Not only does `nx migrate` update you to the latest version of Nx, but it also updates the versions of dependencies that we support and test such as Jest and Cypress. You can also use the `migrate` command to update any Nx plugin. +The `nx migrate` helps by automating the process of updating: -## Update to the latest Nx version +- package versions in your `package.json` +- configuration files (e.g. your Jest, ESLint or Nx config) +- your source code (e.g. fixing breaking changes or migrating to new best practices) + +## How does it work? + +Nx knows where its configuration files are and can therefore make sure they match the expected format or can alternatively adjust them. This automated update process, commonly referred to as "migration," becomes even more powerful when you leverage [Nx plugins](/packages). Nx plugins, which are NPM packages with a range of capabilities (code generation, task automation...), offer targeted updates based on their specific areas of responsibility. + +For example, the [Nx ESLint plugin](/packages/linter) excels at configuring linting in your workspace. With its understanding of the configuration file locations, this plugin can provide precise migration scripts to update ESLint packages in your `package.json` and corresponding configuration files in your workspace when a new version is released. Updating happens in three steps: - The installed dependencies are updated including the `package.json` (and `node_modules`). -- The source code in the repo is updated to match the new versions of packages in `package.json`. -- Remove the `migrations.json` file +- The source code in the repo is updated to match the new versions of packages according to set of instructions specified in `migrations.json` file. +- Optionally remove the `migrations.json` file or keep it to re-run it in different Git branches ### Step 1: Updating dependencies and generating migrations @@ -20,11 +28,7 @@ First, run the `migrate` command: nx migrate latest # same as nx migrate nx@latest ``` -You can also specify the name of the package and the version: - -```shell -nx migrate nx@version # you can also specify version -``` +Note you can also specify an exact version by replacing `latest` with `nx@`. This fetches the specified version of the `nx` package, analyzes the dependencies and fetches all the dependent packages. The process keeps going until all the dependencies are resolved. This results in: @@ -41,11 +45,7 @@ At this stage, after inspecting the `package.json`, you may wish to manually run ### Step 2: Running migrations -The next step in the process involves using the `migrate` CLI in order to apply the migrations that were generated in `migrations.json` in the previous step. - -Each Nx plugin is able to provide a set of migrations which are relevant to particular versions of the package, and so `migrations.json` will only contain migrations which are appropriate for the update you are currently applying. - -The common case is that you will simply apply all migrations from the generated JSON file, exactly as they were generated in the previous step, by running: +You can now run the actual code migrations that were generated in the `migrations.json` in the previous step. ```shell nx migrate --run-migrations @@ -53,12 +53,14 @@ nx migrate --run-migrations This will update your source code in your workspace in accordance with the implementation of the various migrations which ran and all the changes will be unstaged ready for you to review and commit yourself. +Note that each Nx plugin is able to provide a set of migrations which are relevant to particular versions of the package. Hence `migrations.json` will only contain migrations which are appropriate for the update you are currently applying. + ### Step 3: Cleaning up After you run all the migrations, you can remove `migrations.json` and commit any outstanding changes. Note: You may want to keep the `migrations.json` until every branch that was created before the migration has been merged. Leaving the `migrations.json` in place allows devs to run `nx migrate --run-migrations` to apply the same migration process to their newly merged code as well. -## Problems? +## Need to opt-out of some migrations? -If you can't run `nx migrate --run-migrations` all in one step, try the tips in [Advanced Update Process](/recipes/other/advanced-update) +Sometimes you need to temporarily opt-out from some migrations because your workspace is not ready yet. You can manually adjust the `migrations.json` or run the update with the `--interactive` flag to choose which migrations you accept. Find more details in our [Advanced Update Process](/recipes/other/advanced-update) guide. From eaebcc34f92db2200dab0bde2e2e1dde107a47bf Mon Sep 17 00:00:00 2001 From: FrozenPandaz Date: Wed, 5 Jul 2023 09:34:28 -0400 Subject: [PATCH 007/262] chore(misc): publish 16.5.0 --- lerna.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lerna.json b/lerna.json index 39ea757915bca..9ffc4c43a8b9c 100644 --- a/lerna.json +++ b/lerna.json @@ -1,6 +1,6 @@ { "packages": ["build/packages/*", "build/packages/nx/native-packages/*"], - "version": "16.5.0-beta.3", + "version": "16.5.0", "granularPathspec": false, "command": { "publish": { From 65adb94bf671117b9307ea22037440836b4da9e3 Mon Sep 17 00:00:00 2001 From: Denis Frenademetz Date: Wed, 5 Jul 2023 16:42:58 +0200 Subject: [PATCH 008/262] fix(core): ensure external dependency hashes are resolved in a deterministic way (#17926) --- packages/nx/src/hasher/task-hasher.spec.ts | 138 +++++++++++++++++++++ packages/nx/src/hasher/task-hasher.ts | 51 +++++--- 2 files changed, 175 insertions(+), 14 deletions(-) diff --git a/packages/nx/src/hasher/task-hasher.spec.ts b/packages/nx/src/hasher/task-hasher.spec.ts index e108672d31c6a..6ba82a56e424a 100644 --- a/packages/nx/src/hasher/task-hasher.spec.ts +++ b/packages/nx/src/hasher/task-hasher.spec.ts @@ -1161,6 +1161,144 @@ describe('TaskHasher', () => { expect(hash.value).toContain('|5.0.0|'); }); + it('should hash entire subtree of dependencies', async () => { + const createHasher = () => + new InProcessTaskHasher( + {}, + allWorkspaceFiles, + { + nodes: { + appA: { + name: 'appA', + type: 'app', + data: { + root: 'apps/appA', + targets: { build: { executor: '@nx/webpack:webpack' } }, + }, + }, + appB: { + name: 'appB', + type: 'app', + data: { + root: 'apps/appB', + targets: { build: { executor: '@nx/webpack:webpack' } }, + }, + }, + }, + externalNodes: { + 'npm:packageA': { + name: 'npm:packageA', + type: 'npm', + data: { + packageName: 'packageA', + version: '0.0.0', + hash: '$packageA0.0.0$', + }, + }, + 'npm:packageB': { + name: 'npm:packageB', + type: 'npm', + data: { + packageName: 'packageB', + version: '0.0.0', + hash: '$packageB0.0.0$', + }, + }, + 'npm:packageC': { + name: 'npm:packageC', + type: 'npm', + data: { + packageName: 'packageC', + version: '0.0.0', + hash: '$packageC0.0.0$', + }, + }, + }, + dependencies: { + appA: [ + { + source: 'app', + target: 'npm:packageA', + type: DependencyType.static, + }, + { + source: 'app', + target: 'npm:packageB', + type: DependencyType.static, + }, + { + source: 'app', + target: 'npm:packageC', + type: DependencyType.static, + }, + ], + appB: [ + { + source: 'app', + target: 'npm:packageC', + type: DependencyType.static, + }, + ], + 'npm:packageC': [ + { + source: 'app', + target: 'npm:packageA', + type: DependencyType.static, + }, + { + source: 'app', + target: 'npm:packageB', + type: DependencyType.static, + }, + ], + 'npm:packageB': [ + { + source: 'app', + target: 'npm:packageA', + type: DependencyType.static, + }, + ], + }, + }, + { + roots: ['app-build'], + tasks: { + 'app-build': { + id: 'app-build', + target: { project: 'app', target: 'build' }, + overrides: {}, + }, + }, + dependencies: {}, + }, + {} as any, + {}, + fileHasher + ); + + const computeTaskHash = async (hasher, appName) => { + const hashAppA = await hasher.hashTask({ + target: { project: appName, target: 'build' }, + id: `${appName}-build`, + overrides: { prop: 'prop-value' }, + }); + + return hashAppA.value; + }; + + const hasher1 = createHasher(); + + await computeTaskHash(hasher1, 'appA'); + const hashAppB1 = await computeTaskHash(hasher1, 'appB'); + + const hasher2 = createHasher(); + + const hashAppB2 = await computeTaskHash(hasher2, 'appB'); + await computeTaskHash(hasher2, 'appA'); + + expect(hashAppB1).toEqual(hashAppB2); + }); + it('should not hash when nx:run-commands executor', async () => { const hasher = new InProcessTaskHasher( {}, diff --git a/packages/nx/src/hasher/task-hasher.ts b/packages/nx/src/hasher/task-hasher.ts index 05246b9ac559c..4b40e50a03337 100644 --- a/packages/nx/src/hasher/task-hasher.ts +++ b/packages/nx/src/hasher/task-hasher.ts @@ -332,7 +332,7 @@ class TaskHasherImpl { visited ); } else { - const hash = this.hashExternalDependency(d.target); + const hash = this.hashExternalDependency(d.source, d.target); return { value: hash, details: { @@ -408,16 +408,29 @@ class TaskHasherImpl { return partialHashes; } + private computeExternalDependencyIdentifier( + sourceProjectName: string, + targetProjectName: string + ): `${string}->${string}` { + return `${sourceProjectName}->${targetProjectName}`; + } + private hashExternalDependency( - projectName: string, + sourceProjectName: string, + targetProjectName: string, visited = new Set() ): string { // try to retrieve the hash from cache - if (this.externalDepsHashCache[projectName]) { - return this.externalDepsHashCache[projectName]; + if (this.externalDepsHashCache[targetProjectName]) { + return this.externalDepsHashCache[targetProjectName]; } - visited.add(projectName); - const node = this.projectGraph.externalNodes[projectName]; + visited.add( + this.computeExternalDependencyIdentifier( + sourceProjectName, + targetProjectName + ) + ); + const node = this.projectGraph.externalNodes[targetProjectName]; let partialHash: string; if (node) { const partialHashes: string[] = []; @@ -429,22 +442,32 @@ class TaskHasherImpl { partialHashes.push(node.data.version); } // we want to calculate the hash of the entire dependency tree - if (this.projectGraph.dependencies[projectName]) { - this.projectGraph.dependencies[projectName].forEach((d) => { - if (!visited.has(d.target)) { - partialHashes.push(this.hashExternalDependency(d.target, visited)); + if (this.projectGraph.dependencies[targetProjectName]) { + this.projectGraph.dependencies[targetProjectName].forEach((d) => { + if ( + !visited.has( + this.computeExternalDependencyIdentifier( + targetProjectName, + d.target + ) + ) + ) { + partialHashes.push( + this.hashExternalDependency(targetProjectName, d.target, visited) + ); } }); } + partialHash = hashArray(partialHashes); } else { // unknown dependency // this may occur if dependency is not an npm package // but rather symlinked in node_modules or it's pointing to a remote git repo // in this case we have no information about the versioning of the given package - partialHash = `__${projectName}__`; + partialHash = `__${targetProjectName}__`; } - this.externalDepsHashCache[projectName] = partialHash; + this.externalDepsHashCache[targetProjectName] = partialHash; return partialHash; } @@ -470,7 +493,7 @@ class TaskHasherImpl { const executorPackage = target.executor.split(':')[0]; const executorNodeName = this.findExternalDependencyNodeName(executorPackage); - hash = this.hashExternalDependency(executorNodeName); + hash = this.hashExternalDependency(projectName, executorNodeName); } else { // use command external dependencies if available to construct the hash const partialHashes: string[] = []; @@ -482,7 +505,7 @@ class TaskHasherImpl { const externalDependencies = input['externalDependencies']; for (let dep of externalDependencies) { dep = this.findExternalDependencyNodeName(dep); - partialHashes.push(this.hashExternalDependency(dep)); + partialHashes.push(this.hashExternalDependency(projectName, dep)); } } } From d42d2f46fbad6171288d04c864e54cfae4318969 Mon Sep 17 00:00:00 2001 From: Vergil Penkov <85731267+vergilfromadyen@users.noreply.github.com> Date: Wed, 5 Jul 2023 16:43:57 +0200 Subject: [PATCH 009/262] fix(core): add license information for native packages (#17964) --- packages/nx/native-packages/darwin-arm64/package.json | 1 + packages/nx/native-packages/darwin-x64/package.json | 1 + packages/nx/native-packages/freebsd-x64/package.json | 1 + packages/nx/native-packages/linux-arm-gnueabihf/package.json | 1 + packages/nx/native-packages/linux-arm64-gnu/package.json | 1 + packages/nx/native-packages/linux-arm64-musl/package.json | 1 + packages/nx/native-packages/linux-x64-gnu/package.json | 1 + packages/nx/native-packages/linux-x64-musl/package.json | 1 + packages/nx/native-packages/win32-arm64-msvc/package.json | 1 + packages/nx/native-packages/win32-x64-msvc/package.json | 1 + 10 files changed, 10 insertions(+) diff --git a/packages/nx/native-packages/darwin-arm64/package.json b/packages/nx/native-packages/darwin-arm64/package.json index aec51e000747c..718ee102efaff 100644 --- a/packages/nx/native-packages/darwin-arm64/package.json +++ b/packages/nx/native-packages/darwin-arm64/package.json @@ -1,6 +1,7 @@ { "name": "@nx/nx-darwin-arm64", "version": "0.0.0", + "license": "MIT", "repository": { "type": "git", "url": "https://github.com/nrwl/nx.git", diff --git a/packages/nx/native-packages/darwin-x64/package.json b/packages/nx/native-packages/darwin-x64/package.json index 8e1a58dae0368..1a681de1fd4ae 100644 --- a/packages/nx/native-packages/darwin-x64/package.json +++ b/packages/nx/native-packages/darwin-x64/package.json @@ -1,6 +1,7 @@ { "name": "@nx/nx-darwin-x64", "version": "0.0.0", + "license": "MIT", "repository": { "type": "git", "url": "https://github.com/nrwl/nx.git", diff --git a/packages/nx/native-packages/freebsd-x64/package.json b/packages/nx/native-packages/freebsd-x64/package.json index 422f23c6d60b2..4b6596b53e848 100644 --- a/packages/nx/native-packages/freebsd-x64/package.json +++ b/packages/nx/native-packages/freebsd-x64/package.json @@ -1,6 +1,7 @@ { "name": "@nx/nx-freebsd-x64", "version": "0.0.0", + "license": "MIT", "repository": { "type": "git", "url": "https://github.com/nrwl/nx.git", diff --git a/packages/nx/native-packages/linux-arm-gnueabihf/package.json b/packages/nx/native-packages/linux-arm-gnueabihf/package.json index 87ae7d149e1a0..0cb5b75ba7d1a 100644 --- a/packages/nx/native-packages/linux-arm-gnueabihf/package.json +++ b/packages/nx/native-packages/linux-arm-gnueabihf/package.json @@ -1,6 +1,7 @@ { "name": "@nx/nx-linux-arm-gnueabihf", "version": "0.0.0", + "license": "MIT", "repository": { "type": "git", "url": "https://github.com/nrwl/nx.git", diff --git a/packages/nx/native-packages/linux-arm64-gnu/package.json b/packages/nx/native-packages/linux-arm64-gnu/package.json index fd0e3a428b8a0..4f039842b3366 100644 --- a/packages/nx/native-packages/linux-arm64-gnu/package.json +++ b/packages/nx/native-packages/linux-arm64-gnu/package.json @@ -1,6 +1,7 @@ { "name": "@nx/nx-linux-arm64-gnu", "version": "0.0.0", + "license": "MIT", "repository": { "type": "git", "url": "https://github.com/nrwl/nx.git", diff --git a/packages/nx/native-packages/linux-arm64-musl/package.json b/packages/nx/native-packages/linux-arm64-musl/package.json index afe177d254d47..bb8cef8ef661c 100644 --- a/packages/nx/native-packages/linux-arm64-musl/package.json +++ b/packages/nx/native-packages/linux-arm64-musl/package.json @@ -1,6 +1,7 @@ { "name": "@nx/nx-linux-arm64-musl", "version": "0.0.0", + "license": "MIT", "repository": { "type": "git", "url": "https://github.com/nrwl/nx.git", diff --git a/packages/nx/native-packages/linux-x64-gnu/package.json b/packages/nx/native-packages/linux-x64-gnu/package.json index 7d391277fdda3..d6760f275199f 100644 --- a/packages/nx/native-packages/linux-x64-gnu/package.json +++ b/packages/nx/native-packages/linux-x64-gnu/package.json @@ -1,6 +1,7 @@ { "name": "@nx/nx-linux-x64-gnu", "version": "0.0.0", + "license": "MIT", "repository": { "type": "git", "url": "https://github.com/nrwl/nx.git", diff --git a/packages/nx/native-packages/linux-x64-musl/package.json b/packages/nx/native-packages/linux-x64-musl/package.json index a2127e3a49211..5a5801848acfb 100644 --- a/packages/nx/native-packages/linux-x64-musl/package.json +++ b/packages/nx/native-packages/linux-x64-musl/package.json @@ -1,6 +1,7 @@ { "name": "@nx/nx-linux-x64-musl", "version": "0.0.0", + "license": "MIT", "repository": { "type": "git", "url": "https://github.com/nrwl/nx.git", diff --git a/packages/nx/native-packages/win32-arm64-msvc/package.json b/packages/nx/native-packages/win32-arm64-msvc/package.json index fbc9b30010777..a14d114f3780b 100644 --- a/packages/nx/native-packages/win32-arm64-msvc/package.json +++ b/packages/nx/native-packages/win32-arm64-msvc/package.json @@ -1,6 +1,7 @@ { "name": "@nx/nx-win32-arm64-msvc", "version": "0.0.0", + "license": "MIT", "repository": { "type": "git", "url": "https://github.com/nrwl/nx.git", diff --git a/packages/nx/native-packages/win32-x64-msvc/package.json b/packages/nx/native-packages/win32-x64-msvc/package.json index 021457307d04a..81f986ecd9c30 100644 --- a/packages/nx/native-packages/win32-x64-msvc/package.json +++ b/packages/nx/native-packages/win32-x64-msvc/package.json @@ -1,6 +1,7 @@ { "name": "@nx/nx-win32-x64-msvc", "version": "0.0.0", + "license": "MIT", "repository": { "type": "git", "url": "https://github.com/nrwl/nx.git", From 28a071f2432e34757581ad5713b2e9361bd95f9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Jona=C5=A1?= Date: Wed, 5 Jul 2023 17:47:49 +0200 Subject: [PATCH 010/262] fix(js): ignore dependencies from non-index root files for create-package-json (#17930) --- .../src/rules/dependency-checks.ts | 13 +++++++--- .../src/utils/package-json-utils.ts | 22 ++++++++++------ .../package-json/update-package-json.spec.ts | 2 +- .../js/package-json/create-package-json.ts | 26 +++++++++++++++---- 4 files changed, 45 insertions(+), 18 deletions(-) diff --git a/packages/eslint-plugin/src/rules/dependency-checks.ts b/packages/eslint-plugin/src/rules/dependency-checks.ts index 9b047098fc978..25c4ae9c400e0 100644 --- a/packages/eslint-plugin/src/rules/dependency-checks.ts +++ b/packages/eslint-plugin/src/rules/dependency-checks.ts @@ -9,6 +9,7 @@ import { satisfies } from 'semver'; import { getHelperDependenciesFromProjectGraph } from '@nx/js'; import { getAllDependencies, + getPackageJson, removePackageJsonFromFileMap, } from '../utils/package-json-utils'; import { JSONLiteral } from 'jsonc-eslint-parser/lib/parser/ast'; @@ -126,13 +127,17 @@ export default createESLintRule({ projectGraph ); + const rootPackageJson = getPackageJson(join(workspaceRoot, 'package.json')); + // find all dependencies for the project const npmDeps = findProjectsNpmDependencies( sourceProject, projectGraph, buildTarget, + rootPackageJson, { helperDependencies: helperDependencies.map((dep) => dep.target), + isProduction: true, }, removePackageJsonFromFileMap(projectFileMap) ); @@ -148,12 +153,12 @@ export default createESLintRule({ 'package.json' ); - globalThis.projPackageJsonDeps ??= getAllDependencies(projPackageJsonPath); + globalThis.projPackageJsonDeps ??= getAllDependencies( + getPackageJson(projPackageJsonPath) + ); const projPackageJsonDeps: Record = globalThis.projPackageJsonDeps; - const rootPackageJsonDeps = getAllDependencies( - join(workspaceRoot, 'package.json') - ); + const rootPackageJsonDeps = getAllDependencies(rootPackageJson); function validateMissingDependencies(node: AST.JSONProperty) { if (!checkMissingDependencies) { diff --git a/packages/eslint-plugin/src/utils/package-json-utils.ts b/packages/eslint-plugin/src/utils/package-json-utils.ts index 4423ab7128d9d..bf1759d37f32e 100644 --- a/packages/eslint-plugin/src/utils/package-json-utils.ts +++ b/packages/eslint-plugin/src/utils/package-json-utils.ts @@ -1,16 +1,22 @@ import { ProjectFileMap, readJsonFile } from '@nx/devkit'; import { existsSync } from 'fs'; +import { PackageJson } from 'nx/src/utils/package-json'; -export function getAllDependencies(path: string): Record { +export function getAllDependencies( + packageJson: PackageJson +): Record { + return { + ...packageJson.dependencies, + ...packageJson.devDependencies, + ...packageJson.peerDependencies, + }; +} + +export function getPackageJson(path: string): PackageJson { if (existsSync(path)) { - const packageJson = readJsonFile(path); - return { - ...packageJson.dependencies, - ...packageJson.devDependencies, - ...packageJson.peerDependencies, - }; + return readJsonFile(path); } - return {}; + return {} as PackageJson; } export function removePackageJsonFromFileMap( diff --git a/packages/js/src/utils/package-json/update-package-json.spec.ts b/packages/js/src/utils/package-json/update-package-json.spec.ts index c627c25889fd9..0a8f44ca810dd 100644 --- a/packages/js/src/utils/package-json/update-package-json.spec.ts +++ b/packages/js/src/utils/package-json/update-package-json.spec.ts @@ -290,7 +290,7 @@ describe('updatePackageJson', () => { const fileMap = { '@org/lib1': [ { - file: 'test.ts', + file: 'libs/lib1/src/test.ts', hash: '', deps: ['npm:external1', 'npm:external2'], }, diff --git a/packages/nx/src/plugins/js/package-json/create-package-json.ts b/packages/nx/src/plugins/js/package-json/create-package-json.ts index c84ad7ea027a5..e67be3838eb79 100644 --- a/packages/nx/src/plugins/js/package-json/create-package-json.ts +++ b/packages/nx/src/plugins/js/package-json/create-package-json.ts @@ -43,11 +43,19 @@ export function createPackageJson( const projectNode = graph.nodes[projectName]; const isLibrary = projectNode.type === 'lib'; + const rootPackageJson = readJsonFile( + `${options.root || workspaceRoot}/package.json` + ); + const npmDeps = findProjectsNpmDependencies( projectNode, graph, options.target, - { helperDependencies: options.helperDependencies }, + rootPackageJson, + { + helperDependencies: options.helperDependencies, + isProduction: options.isProduction, + }, fileMap ); @@ -92,9 +100,6 @@ export function createPackageJson( ); }; - const rootPackageJson = readJsonFile( - `${options.root || workspaceRoot}/package.json` - ); Object.entries(npmDeps.dependencies).forEach(([packageName, version]) => { if ( rootPackageJson.devDependencies?.[packageName] && @@ -179,9 +184,11 @@ export function findProjectsNpmDependencies( projectNode: ProjectGraphProjectNode, graph: ProjectGraph, target: string, + rootPackageJson: PackageJson, options: { helperDependencies?: string[]; ignoredDependencies?: string[]; + isProduction?: boolean; }, fileMap?: ProjectFileMap ): NpmDeps { @@ -208,13 +215,22 @@ export function findProjectsNpmDependencies( recursivelyCollectPeerDependencies(dep, graph, npmDeps, seen); }); + // if it's production, we want to ignore all found devDependencies + const ignoredDependencies = + options.isProduction && rootPackageJson.devDependencies + ? [ + ...(options.ignoredDependencies || []), + ...Object.keys(rootPackageJson.devDependencies), + ] + : options.ignoredDependencies || []; + findAllNpmDeps( fileMap, projectNode, graph, npmDeps, seen, - options.ignoredDependencies || [], + ignoredDependencies, dependencyInputs, selfInputs ); From fc58ef45d6bff3e8d8ea9d6ce0b43b339cc0da4b Mon Sep 17 00:00:00 2001 From: Isaac Mann Date: Wed, 5 Jul 2023 11:51:42 -0400 Subject: [PATCH 011/262] docs(core): fix wording in update dependencies page (#17968) --- .../core-features/automate-updating-dependencies.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/shared/core-features/automate-updating-dependencies.md b/docs/shared/core-features/automate-updating-dependencies.md index b2b47e7d0483a..5edc4e1d6ce99 100644 --- a/docs/shared/core-features/automate-updating-dependencies.md +++ b/docs/shared/core-features/automate-updating-dependencies.md @@ -1,8 +1,8 @@ # Automate Updating Dependencies -Keeping a codebase updated with the latest changes in your framework of choice and tooling can be challenging. Not to mention that "tooling maintenance work" is usually hard to squeeze into your feature sprint. +Keeping a codebase updated with the latest changes in your framework of choice can be challenging. Not to mention that "tooling maintenance work" is usually hard to squeeze into your feature sprint. -The `nx migrate` helps by automating the process of updating: +The `nx migrate` command helps by automating the process of updating: - package versions in your `package.json` - configuration files (e.g. your Jest, ESLint or Nx config) @@ -10,15 +10,15 @@ The `nx migrate` helps by automating the process of updating: ## How does it work? -Nx knows where its configuration files are and can therefore make sure they match the expected format or can alternatively adjust them. This automated update process, commonly referred to as "migration," becomes even more powerful when you leverage [Nx plugins](/packages). Nx plugins, which are NPM packages with a range of capabilities (code generation, task automation...), offer targeted updates based on their specific areas of responsibility. +Nx knows where its configuration files are and can therefore make sure they match the expected format. This automated update process, commonly referred to as "migration," becomes even more powerful when you leverage [Nx plugins](/packages). Nx plugins, which are NPM packages with a range of capabilities (code generation, task automation...), offer targeted updates based on their specific areas of responsibility. For example, the [Nx ESLint plugin](/packages/linter) excels at configuring linting in your workspace. With its understanding of the configuration file locations, this plugin can provide precise migration scripts to update ESLint packages in your `package.json` and corresponding configuration files in your workspace when a new version is released. Updating happens in three steps: - The installed dependencies are updated including the `package.json` (and `node_modules`). -- The source code in the repo is updated to match the new versions of packages according to set of instructions specified in `migrations.json` file. -- Optionally remove the `migrations.json` file or keep it to re-run it in different Git branches +- The source code in the repo is updated to match the new versions of packages according to the set of instructions specified in `migrations.json` file. +- Optionally remove the `migrations.json` file or keep it to re-run the migration in different Git branches ### Step 1: Updating dependencies and generating migrations From c64f26ef3cb0ce14f383652169df503840f97557 Mon Sep 17 00:00:00 2001 From: Colum Ferry Date: Wed, 5 Jul 2023 16:57:40 +0100 Subject: [PATCH 012/262] fix(angular): automatically skip remotes not in the current workspace #17473 (#17497) --- .../module-federation-dev-server.json | 2 +- .../executors/module-federation-dev-ssr.json | 2 +- .../module-federation-dev-server.json | 2 +- .../module-federation-ssr-dev-server.json | 2 +- .../module-federation-dev-server.impl.ts | 13 ++++- .../module-federation-dev-server/schema.json | 2 +- .../module-federation-dev-ssr/schema.json | 2 +- .../builders/utilities/module-federation.ts | 58 +++++++++++-------- .../src/utils/find-matching-projects.spec.ts | 2 +- .../module-federation-dev-server.impl.ts | 31 +++++++++- .../module-federation-dev-server/schema.json | 2 +- .../module-federation-ssr-dev-server.impl.ts | 24 +++++++- .../schema.json | 2 +- 13 files changed, 106 insertions(+), 38 deletions(-) diff --git a/docs/generated/packages/angular/executors/module-federation-dev-server.json b/docs/generated/packages/angular/executors/module-federation-dev-server.json index 82305582cd68a..73ee722d00fb0 100644 --- a/docs/generated/packages/angular/executors/module-federation-dev-server.json +++ b/docs/generated/packages/angular/executors/module-federation-dev-server.json @@ -107,7 +107,7 @@ "skipRemotes": { "type": "array", "items": { "type": "string" }, - "description": "List of remote applications to not automatically serve, either statically or in development mode. This can be useful for multi-repository module federation setups where the host application uses a remote application from an external repository." + "description": "List of remote applications to not automatically serve, either statically or in development mode." }, "pathToManifestFile": { "type": "string", diff --git a/docs/generated/packages/angular/executors/module-federation-dev-ssr.json b/docs/generated/packages/angular/executors/module-federation-dev-ssr.json index 362f71f47eaca..28330f038d446 100644 --- a/docs/generated/packages/angular/executors/module-federation-dev-ssr.json +++ b/docs/generated/packages/angular/executors/module-federation-dev-ssr.json @@ -72,7 +72,7 @@ "skipRemotes": { "type": "array", "items": { "type": "string" }, - "description": "List of remote applications to not automatically serve, either statically or in development mode. This can be useful for multi-repository module federation setups where the host application uses a remote application from an external repository." + "description": "List of remote applications to not automatically serve, either statically or in development mode." }, "verbose": { "type": "boolean", diff --git a/docs/generated/packages/react/executors/module-federation-dev-server.json b/docs/generated/packages/react/executors/module-federation-dev-server.json index b962cf3a45323..7a346ba1dd993 100644 --- a/docs/generated/packages/react/executors/module-federation-dev-server.json +++ b/docs/generated/packages/react/executors/module-federation-dev-server.json @@ -18,7 +18,7 @@ "skipRemotes": { "type": "array", "items": { "type": "string" }, - "description": "List of remote applications to not automatically serve, either statically or in development mode. This can be useful for multi-repository module federation setups where the host application uses a remote application from an external repository.", + "description": "List of remote applications to not automatically serve, either statically or in development mode.", "x-priority": "important" }, "buildTarget": { diff --git a/docs/generated/packages/react/executors/module-federation-ssr-dev-server.json b/docs/generated/packages/react/executors/module-federation-ssr-dev-server.json index bdca395348390..fb5b3ec88d0c4 100644 --- a/docs/generated/packages/react/executors/module-federation-ssr-dev-server.json +++ b/docs/generated/packages/react/executors/module-federation-ssr-dev-server.json @@ -34,7 +34,7 @@ "skipRemotes": { "type": "array", "items": { "type": "string" }, - "description": "List of remote applications to not automatically serve, either statically or in development mode. This can be useful for multi-repository module federation setups where the host application uses a remote application from an external repository.", + "description": "List of remote applications to not automatically serve, either statically or in development mode.", "x-priority": "important" }, "host": { diff --git a/packages/angular/src/builders/module-federation-dev-server/module-federation-dev-server.impl.ts b/packages/angular/src/builders/module-federation-dev-server/module-federation-dev-server.impl.ts index 9cf8342544535..c622db524c85e 100644 --- a/packages/angular/src/builders/module-federation-dev-server/module-federation-dev-server.impl.ts +++ b/packages/angular/src/builders/module-federation-dev-server/module-federation-dev-server.impl.ts @@ -1,5 +1,10 @@ import type { Schema } from './schema'; -import { readCachedProjectGraph, workspaceRoot, Workspaces } from '@nx/devkit'; +import { + logger, + readCachedProjectGraph, + workspaceRoot, + Workspaces, +} from '@nx/devkit'; import { scheduleTarget } from 'nx/src/adapter/ngcli-adapter'; import { executeWebpackDevServerBuilder } from '../webpack-dev-server/webpack-dev-server.impl'; import { readProjectsConfigurationFromProjectGraph } from 'nx/src/project-graph/project-graph'; @@ -51,6 +56,12 @@ export function executeModuleFederationDevServerBuilder( const remotesToSkip = new Set( findMatchingProjects(options.skipRemotes, projectGraph.nodes) ?? [] ); + + if (remotesToSkip.size > 0) { + logger.info( + `Remotes not served automatically: ${[...remotesToSkip].join(', ')}` + ); + } const staticRemotes = getStaticRemotes( project, context, diff --git a/packages/angular/src/builders/module-federation-dev-server/schema.json b/packages/angular/src/builders/module-federation-dev-server/schema.json index 008903e882c50..897762871c1b6 100644 --- a/packages/angular/src/builders/module-federation-dev-server/schema.json +++ b/packages/angular/src/builders/module-federation-dev-server/schema.json @@ -117,7 +117,7 @@ "items": { "type": "string" }, - "description": "List of remote applications to not automatically serve, either statically or in development mode. This can be useful for multi-repository module federation setups where the host application uses a remote application from an external repository." + "description": "List of remote applications to not automatically serve, either statically or in development mode." }, "pathToManifestFile": { "type": "string", diff --git a/packages/angular/src/builders/module-federation-dev-ssr/schema.json b/packages/angular/src/builders/module-federation-dev-ssr/schema.json index 9687c230e8f20..31dd2e589bec9 100644 --- a/packages/angular/src/builders/module-federation-dev-ssr/schema.json +++ b/packages/angular/src/builders/module-federation-dev-ssr/schema.json @@ -73,7 +73,7 @@ "items": { "type": "string" }, - "description": "List of remote applications to not automatically serve, either statically or in development mode. This can be useful for multi-repository module federation setups where the host application uses a remote application from an external repository." + "description": "List of remote applications to not automatically serve, either statically or in development mode." }, "verbose": { "type": "boolean", diff --git a/packages/angular/src/builders/utilities/module-federation.ts b/packages/angular/src/builders/utilities/module-federation.ts index c7eb08d2d6139..eebc91bc660c1 100644 --- a/packages/angular/src/builders/utilities/module-federation.ts +++ b/packages/angular/src/builders/utilities/module-federation.ts @@ -1,7 +1,7 @@ import { ProjectConfiguration } from 'nx/src/config/workspace-json-project-json'; import { join } from 'path'; import { existsSync, readFileSync } from 'fs'; -import { Remotes } from '@nx/devkit'; +import { logger, Remotes } from '@nx/devkit'; export function getDynamicRemotes( project: ProjectConfiguration, @@ -45,19 +45,26 @@ export function getDynamicRemotes( return []; } - const dynamicRemotes = Object.entries(parsedManifest) + const allDynamicRemotes = Object.entries(parsedManifest) .map(([remoteName]) => remoteName) .filter((r) => !remotesToSkip.has(r)); - const invalidDynamicRemotes = dynamicRemotes.filter( - (remote) => !workspaceProjects[remote] - ); - if (invalidDynamicRemotes.length) { - throw new Error( - invalidDynamicRemotes.length === 1 - ? `Invalid dynamic remote configured in "${pathToManifestFile}": ${invalidDynamicRemotes[0]}.` - : `Invalid dynamic remotes configured in "${pathToManifestFile}": ${invalidDynamicRemotes.join( - ', ' - )}.` + + const remotesNotInWorkspace: string[] = []; + + const dynamicRemotes = allDynamicRemotes.filter((remote) => { + if (!workspaceProjects[remote]) { + remotesNotInWorkspace.push(remote); + + return false; + } + return true; + }); + + if (remotesNotInWorkspace.length > 0) { + logger.warn( + `Skipping serving ${remotesNotInWorkspace.join( + ', ' + )} as they could not be found in the workspace. Ensure they are served correctly.` ); } @@ -89,22 +96,27 @@ export function getStaticRemotes( Array.isArray(mfeConfig.remotes) && mfeConfig.remotes.length > 0 ? mfeConfig.remotes : []; - const staticRemotes = remotesConfig + const allStaticRemotes = remotesConfig .map((remoteDefinition) => Array.isArray(remoteDefinition) ? remoteDefinition[0] : remoteDefinition ) .filter((r) => !remotesToSkip.has(r)); + const remotesNotInWorkspace: string[] = []; - const invalidStaticRemotes = staticRemotes.filter( - (remote) => !workspaceProjects[remote] - ); - if (invalidStaticRemotes.length) { - throw new Error( - invalidStaticRemotes.length === 1 - ? `Invalid static remote configured in "${mfConfigPath}": ${invalidStaticRemotes[0]}.` - : `Invalid static remotes configured in "${mfConfigPath}": ${invalidStaticRemotes.join( - ', ' - )}.` + const staticRemotes = allStaticRemotes.filter((remote) => { + if (!workspaceProjects[remote]) { + remotesNotInWorkspace.push(remote); + + return false; + } + return true; + }); + + if (remotesNotInWorkspace.length > 0) { + logger.warn( + `Skipping serving ${remotesNotInWorkspace.join( + ', ' + )} as they could not be found in the workspace. Ensure they are served correctly.` ); } diff --git a/packages/nx/src/utils/find-matching-projects.spec.ts b/packages/nx/src/utils/find-matching-projects.spec.ts index 0ad750ce5645e..72c2b57bfe7a8 100644 --- a/packages/nx/src/utils/find-matching-projects.spec.ts +++ b/packages/nx/src/utils/find-matching-projects.spec.ts @@ -2,8 +2,8 @@ import { findMatchingProjects, getMatchingStringsWithCache, } from './find-matching-projects'; -import minimatch = require('minimatch'); import type { ProjectGraphProjectNode } from '../config/project-graph'; +import minimatch = require('minimatch'); describe('findMatchingProjects', () => { let projectGraph: Record = { diff --git a/packages/react/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts b/packages/react/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts index 892ebc92b52e6..262ac3d878dd2 100644 --- a/packages/react/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts +++ b/packages/react/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts @@ -39,12 +39,39 @@ export default async function* moduleFederationDevServer( } const remotesToSkip = new Set( - findMatchingProjects(options.skipRemotes ?? [], context.projectGraph.nodes) + findMatchingProjects(options.skipRemotes, context.projectGraph.nodes) ?? [] ); + + if (remotesToSkip.size > 0) { + logger.info( + `Remotes not served automatically: ${[...remotesToSkip.values()].join( + ', ' + )}` + ); + } + const remotesNotInWorkspace: string[] = []; + const knownRemotes = (moduleFederationConfig.remotes ?? []).filter((r) => { const validRemote = Array.isArray(r) ? r[0] : r; - return !remotesToSkip.has(validRemote); + + if (remotesToSkip.has(validRemote)) { + return false; + } else if (!context.projectGraph.nodes[validRemote]) { + remotesNotInWorkspace.push(validRemote); + return false; + } else { + return true; + } }); + + if (remotesNotInWorkspace.length > 0) { + logger.warn( + `Skipping serving ${remotesNotInWorkspace.join( + ', ' + )} as they could not be found in the workspace. Ensure they are served correctly.` + ); + } + const remotePorts = knownRemotes.map( (r) => context.projectGraph.nodes[r].data.targets['serve'].options.port ); diff --git a/packages/react/src/executors/module-federation-dev-server/schema.json b/packages/react/src/executors/module-federation-dev-server/schema.json index 261ea0453decb..59cc7679d6d99 100644 --- a/packages/react/src/executors/module-federation-dev-server/schema.json +++ b/packages/react/src/executors/module-federation-dev-server/schema.json @@ -19,7 +19,7 @@ "items": { "type": "string" }, - "description": "List of remote applications to not automatically serve, either statically or in development mode. This can be useful for multi-repository module federation setups where the host application uses a remote application from an external repository.", + "description": "List of remote applications to not automatically serve, either statically or in development mode.", "x-priority": "important" }, "buildTarget": { diff --git a/packages/react/src/executors/module-federation-ssr-dev-server/module-federation-ssr-dev-server.impl.ts b/packages/react/src/executors/module-federation-ssr-dev-server/module-federation-ssr-dev-server.impl.ts index 1e6929ed8feba..e2e2c355a20e3 100644 --- a/packages/react/src/executors/module-federation-ssr-dev-server/module-federation-ssr-dev-server.impl.ts +++ b/packages/react/src/executors/module-federation-ssr-dev-server/module-federation-ssr-dev-server.impl.ts @@ -46,9 +46,27 @@ export default async function* moduleFederationSsrDevServer( } const remotesToSkip = new Set(options.skipRemotes ?? []); - const knownRemotes = (moduleFederationConfig.remotes ?? []).filter( - (r) => !remotesToSkip.has(r) - ); + const remotesNotInWorkspace: string[] = []; + const knownRemotes = (moduleFederationConfig.remotes ?? []).filter((r) => { + const validRemote = Array.isArray(r) ? r[0] : r; + + if (remotesToSkip.has(validRemote)) { + return false; + } else if (!context.projectGraph.nodes[validRemote]) { + remotesNotInWorkspace.push(validRemote); + return false; + } else { + return true; + } + }); + + if (remotesNotInWorkspace.length > 0) { + logger.warn( + `Skipping serving ${remotesNotInWorkspace.join( + ', ' + )} as they could not be found in the workspace. Ensure they are served correctly.` + ); + } const devServeApps = !options.devRemotes ? [] diff --git a/packages/react/src/executors/module-federation-ssr-dev-server/schema.json b/packages/react/src/executors/module-federation-ssr-dev-server/schema.json index 2653fe1c2235d..865ea1ee7cf12 100644 --- a/packages/react/src/executors/module-federation-ssr-dev-server/schema.json +++ b/packages/react/src/executors/module-federation-ssr-dev-server/schema.json @@ -35,7 +35,7 @@ "items": { "type": "string" }, - "description": "List of remote applications to not automatically serve, either statically or in development mode. This can be useful for multi-repository module federation setups where the host application uses a remote application from an external repository.", + "description": "List of remote applications to not automatically serve, either statically or in development mode.", "x-priority": "important" }, "host": { From 4691d841a275f38d364c42b6dab28434dcb2cfaf Mon Sep 17 00:00:00 2001 From: Juri Date: Wed, 5 Jul 2023 17:34:50 +0200 Subject: [PATCH 013/262] docs(devkit): improve structure and fix some typos --- docs/shared/recipes/plugins/create-preset.md | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/docs/shared/recipes/plugins/create-preset.md b/docs/shared/recipes/plugins/create-preset.md index 6d421da6f4f28..a409a546f5eb1 100644 --- a/docs/shared/recipes/plugins/create-preset.md +++ b/docs/shared/recipes/plugins/create-preset.md @@ -1,4 +1,4 @@ -## Preset +# Create a Custom Plugin Preset When you create a new nx workspace, you run the command: [`npx create-nx-workspace`](/packages/nx/documents/create-nx-workspace). This command accepts a `--preset` option, for example: `npx create-nx-workspace --preset=react-standalone`. @@ -9,30 +9,32 @@ src="https://www.youtube.com/embed/yGUrF0-uqaU" title="Develop a Nx Preset for your Nx Plugin" width="100%" /%} -### Custom Preset +## What is a preset? -At its core a preset is a generator, which we can create inside of a plugin. +At its core, a preset is a special [generator](/plugin-features/use-code-generators) that is shipped as part of an Nx Plugin package. -All first-party Nx presets are built into nx itself, but you can [create your own plugin](/plugins/intro/getting-started) and create a generator with the magic name: `preset`. Once you've [published your plugin](/plugins/tutorials/publish-plugin) on npm, you can now run. the create-nx-workspace command with the preset option set to the name of your published package. +All first-party Nx presets are built into Nx itself, but you can [create your own plugin](/plugins/intro/getting-started) and create a generator with the magic name: `preset`. Once you've [published your plugin](/plugins/tutorials/publish-plugin) on npm, you can now run the `create-nx-workspace` command with the preset option set to the name of your published package. -For example, take +To use a concrete example, let's look at the [`qwik-nx`](https://www.npmjs.com/package/qwik-nx) Nx community plugin. They include a [preset generator](https://github.com/qwikifiers/qwik-nx/tree/main/packages/qwik-nx/src/generators/preset) that you can use to create a new Nx workspace with Qwik support. ```shell npx create-nx-workspace --preset=qwik-nx ``` -This command will create a new Qwik preset based on the [published npm package: `qwik-nx`](https://www.npmjs.com/package/qwik-nx). If we check this package's source code, we can see that it has a [generator named `preset`](https://github.com/qwikifiers/qwik-nx/tree/main/packages/qwik-nx/src/generators/preset). +## Create a new Nx plugin If you **don't** have an existing plugin you can create one by running ```shell - npx create-nx-plugin my-org --pluginName my-plugin +npx create-nx-plugin my-org --pluginName my-plugin ``` +## Creating a "Preset" generator + To create our preset inside of our plugin we can run ```shell - nx generate @nx/plugin:generator --name=preset --project=happynrwl +nx generate @nx/plugin:generator --name=preset --project=happynrwl ``` {% callout type="warning" title="Double check" %} @@ -90,7 +92,7 @@ export default async function (tree: Tree, options: PresetGeneratorSchema) { To get an in-depth guide on customizing/running or debugging your generator see [local generators](/plugins/recipes/local-generators). -#### Usage +## Usage Before you are able to use your newly created preset you must package and publish it to a registry. From 8c9ad0da69b76def41ef1af615d0795272a0b78f Mon Sep 17 00:00:00 2001 From: Colum Ferry Date: Wed, 5 Jul 2023 17:10:25 +0100 Subject: [PATCH 014/262] fix(bundling): update the browsers for es5 terser check (#17784) --- packages/webpack/src/utils/with-nx.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/packages/webpack/src/utils/with-nx.ts b/packages/webpack/src/utils/with-nx.ts index a05023af6a562..b7e1616117216 100644 --- a/packages/webpack/src/utils/with-nx.ts +++ b/packages/webpack/src/utils/with-nx.ts @@ -20,6 +20,18 @@ import browserslist = require('browserslist'); const VALID_BROWSERSLIST_FILES = ['.browserslistrc', 'browserslist']; +const ES5_BROWSERS = [ + 'ie 10', + 'ie 11', + 'safari 11', + 'safari 11.1', + 'safari 12', + 'safari 12.1', + 'safari 13', + 'ios_saf 13.0', + 'ios_saf 13.3', +]; + function getTerserEcmaVersion(projectRoot: string) { let pathToBrowserslistFile = ''; for (const browserslistFile of VALID_BROWSERSLIST_FILES) { @@ -36,7 +48,7 @@ function getTerserEcmaVersion(projectRoot: string) { const env = browserslist.loadConfig({ path: pathToBrowserslistFile }); const browsers = browserslist(env); - return browsers.includes('ie 11') ? 5 : 2020; + return browsers.some((b) => ES5_BROWSERS.includes(b)) ? 5 : 2020; } const IGNORED_WEBPACK_WARNINGS = [ From 4ee6ed1f98a980f90d66d8134d3d21c11fb708ec Mon Sep 17 00:00:00 2001 From: Isaac Mann Date: Wed, 5 Jul 2023 11:49:05 -0400 Subject: [PATCH 015/262] docs(core): set env vars from the command line Co-authored-by: Muhamed Karajic --- docs/shared/guides/use-environment-variables-in-angular.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/shared/guides/use-environment-variables-in-angular.md b/docs/shared/guides/use-environment-variables-in-angular.md index f718584449e78..8dd2c8d1cbb01 100644 --- a/docs/shared/guides/use-environment-variables-in-angular.md +++ b/docs/shared/guides/use-environment-variables-in-angular.md @@ -101,6 +101,13 @@ Now, when we define variables in our `.env` file, such as... NX_API_URL=http://localhost:3333 ``` +{% callout type="note" title="Set environment variables from the terminal" %} +Alternatively, you can set the variable when running a terminal command by using: + +- MacOS & Linux: `NX_API_URL=http://localhost:9999 npm run build-prod` +- Windows: `set NX_API_URL=http://localhost:9999 & npm run build-prod` + {% /callout %} + Finally, We can use environment variables in our code. For example, ```typescript {% fileName="apps/myapp/src/main.ts" %} From a4b9a8c879ba51304bb97d856c97c3faad70f8ae Mon Sep 17 00:00:00 2001 From: Isaac Mann Date: Wed, 5 Jul 2023 12:04:08 -0400 Subject: [PATCH 016/262] docs(core): fix formatting --- docs/shared/guides/use-environment-variables-in-angular.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/shared/guides/use-environment-variables-in-angular.md b/docs/shared/guides/use-environment-variables-in-angular.md index 8dd2c8d1cbb01..5477bb5376b1b 100644 --- a/docs/shared/guides/use-environment-variables-in-angular.md +++ b/docs/shared/guides/use-environment-variables-in-angular.md @@ -106,7 +106,8 @@ Alternatively, you can set the variable when running a terminal command by using - MacOS & Linux: `NX_API_URL=http://localhost:9999 npm run build-prod` - Windows: `set NX_API_URL=http://localhost:9999 & npm run build-prod` - {% /callout %} + +{% /callout %} Finally, We can use environment variables in our code. For example, From c6a0615fa511bde3fa9bc1ac9981172620dcf943 Mon Sep 17 00:00:00 2001 From: Jack Hsu Date: Wed, 5 Jul 2023 14:50:53 -0400 Subject: [PATCH 017/262] fix(js): add watchIgnore and runBuildTargetDependencies options to speed up build (#17953) --- .../generated/packages/js/executors/node.json | 27 +++-- e2e/node/src/node-webpack.test.ts | 52 +++++++++ packages/js/docs/node-examples.md | 82 ++++++++++++++ packages/js/src/executors/node/node.impl.ts | 106 +++++++++++------- packages/js/src/executors/node/schema.d.ts | 1 + packages/js/src/executors/node/schema.json | 29 +++-- 6 files changed, 241 insertions(+), 56 deletions(-) create mode 100644 packages/js/docs/node-examples.md diff --git a/docs/generated/packages/js/executors/node.json b/docs/generated/packages/js/executors/node.json index 57200acfaabcc..b93476e9bf59c 100644 --- a/docs/generated/packages/js/executors/node.json +++ b/docs/generated/packages/js/executors/node.json @@ -28,12 +28,14 @@ "host": { "type": "string", "default": "localhost", - "description": "The host to inspect the process on." + "description": "The host to inspect the process on.", + "x-priority": "important" }, "port": { "type": "number", "default": 9229, - "description": "The port to inspect the process on. Setting port to 0 will assign random free ports to all forked processes." + "description": "The port to inspect the process on. Setting port to 0 will assign random free ports to all forked processes.", + "x-priority": "important" }, "inspect": { "oneOf": [ @@ -41,33 +43,44 @@ { "type": "boolean" } ], "description": "Ensures the app is starting with debugging.", - "default": "inspect" + "default": "inspect", + "x-priority": "important" }, "runtimeArgs": { "type": "array", "description": "Extra args passed to the node process.", "default": [], - "items": { "type": "string" } + "items": { "type": "string" }, + "x-priority": "important" }, "args": { "type": "array", "description": "Extra args when starting the app.", "default": [], - "items": { "type": "string" } + "items": { "type": "string" }, + "x-priority": "important" }, "watch": { "type": "boolean", "description": "Enable re-building when files change.", - "default": true + "default": true, + "x-priority": "important" }, "debounce": { "type": "number", "description": "Delay in milliseconds to wait before restarting. Useful to batch multiple file changes events together. Set to zero (0) to disable.", - "default": 500 + "default": 500, + "x-priority": "important" + }, + "runBuildTargetDependencies": { + "type": "boolean", + "description": "Whether to run dependencies before running the build. Set this to true if the project does not build libraries from source (e.g. 'buildLibsFromSource: false').", + "default": false } }, "additionalProperties": false, "required": ["buildTarget"], + "examplesFile": "---\ntitle: JS Node executor examples\ndescription: This page contains examples for the @nx/js:node executor.\n---\n\nThe `@nx/js:node` executor runs the output of a build target. For example, an application uses esbuild ([`@nx/esbuild:esbuild`](/packages/esbuild/executors/esbuild)) to output the bundle to `dist/my-app` folder, which can then be executed by `@nx/js:node`.\n\n`project.json`:\n\n```json\n\"my-app\": {\n \"targets\": {\n \"serve\": {\n \"executor\": \"@nx/js:node\",\n \"options\": {\n \"buildTarget\": \"my-app:build\"\n }\n },\n \"build\": {\n \"executor\": \"@nx/esbuild:esbuild\",\n \"options\": {\n \"main\": \"my-app/src/main.ts\",\n \"output\": [\"dist/my-app\"],\n //...\n }\n },\n }\n}\n```\n\n```bash\nnpx nx serve my-app\n```\n\n## Examples\n\n{% tabs %}\n{% tab label=\"Pass extra Node CLI arguments\" %}\n\nUsing `runtimeArgs`, you can pass arguments to the underlying `node` command. For example, if you want to set [`--no-warnings`](https://nodejs.org/api/cli.html#--no-warnings) to silence all Node warnings, then add the following to the `project.json` file.\n\n```json\n\"my-app\": {\n \"targets\": {\n \"serve\": {\n \"executor\": \"@nx/js:node\",\n \"options\": {\n \"runtimeArgs\": [\"--no-warnings\"],\n //...\n },\n },\n }\n}\n```\n\n{% /tab %}\n\n{% tab label=\"Run all task dependencies\" %}\n\nIf your application build depends on other tasks, and you want those tasks to also be executed, then set the `runBuildTargetDependencies` to `true`. For example, a library may have a task to generate GraphQL schemas, which is consume by the application. In this case, you want to run the generate task before building and running the application.\n\nThis option is also useful when the build consumes a library from its output, not its source. For example, if an executor that supports `buildLibsFromSource` option has it set to `false` (e.g. [`@nx/webpack:webpack`](/packages/webpack/executors/webpack)).\n\nNote that this option will increase the build time, so use it only when necessary.\n\n```json\n\"my-app\": {\n \"targets\": {\n \"serve\": {\n \"executor\": \"@nx/js:node\",\n \"options\": {\n \"runBuildTargetDependencies\": true,\n //...\n },\n },\n }\n}\n```\n\n{% /tab %}\n\n{% /tabs %}\n", "presets": [] }, "description": "Execute a Node application.", diff --git a/e2e/node/src/node-webpack.test.ts b/e2e/node/src/node-webpack.test.ts index c1ecda50cad9f..ed023a0cc622e 100644 --- a/e2e/node/src/node-webpack.test.ts +++ b/e2e/node/src/node-webpack.test.ts @@ -5,9 +5,12 @@ import { readFile, runCLI, runCLIAsync, + runCommandUntil, + waitUntil, tmpProjPath, uniq, updateFile, + updateProjectConfig, } from '@nx/e2e/utils'; import { execSync } from 'child_process'; @@ -47,5 +50,54 @@ describe('Node Applications + webpack', () => { await runCLIAsync(`build ${app} --optimization`); const optimizedContent = readFile(`dist/apps/${app}/main.js`); expect(optimizedContent).toContain('console.log("foo "+"bar")'); + + // Test that serve can re-run dependency builds. + const lib = uniq('nodelib'); + runCLI(`generate @nx/js:lib ${lib} --bundler=esbuild --no-interactive`); + + updateProjectConfig(app, (config) => { + // Since we read from lib from dist, we should re-build it when lib changes. + config.targets.build.options.buildLibsFromSource = false; + config.targets.serve.options.runBuildTargetDependencies = true; + return config; + }); + + updateFile( + `apps/${app}/src/main.ts`, + ` + import { ${lib} } from '@proj/${lib}'; + console.log('Hello ' + ${lib}()); + ` + ); + + const serveProcess = await runCommandUntil( + `serve ${app} --watch --runBuildTargetDependencies`, + (output) => { + return output.includes(`Hello`); + } + ); + + // Update library source and check that it triggers rebuild. + const terminalOutputs: string[] = []; + serveProcess.stdout.on('data', (chunk) => { + const data = chunk.toString(); + terminalOutputs.push(data); + }); + + updateFile( + `libs/${lib}/src/index.ts`, + `export function ${lib}() { return 'should rebuild lib'; }` + ); + + await waitUntil( + () => { + return terminalOutputs.some((output) => + output.includes(`should rebuild lib`) + ); + }, + { timeout: 30_000, ms: 200 } + ); + + serveProcess.kill(); }, 300_000); }); diff --git a/packages/js/docs/node-examples.md b/packages/js/docs/node-examples.md new file mode 100644 index 0000000000000..9684a2219dffd --- /dev/null +++ b/packages/js/docs/node-examples.md @@ -0,0 +1,82 @@ +--- +title: JS Node executor examples +description: This page contains examples for the @nx/js:node executor. +--- + +The `@nx/js:node` executor runs the output of a build target. For example, an application uses esbuild ([`@nx/esbuild:esbuild`](/packages/esbuild/executors/esbuild)) to output the bundle to `dist/my-app` folder, which can then be executed by `@nx/js:node`. + +`project.json`: + +```json +"my-app": { + "targets": { + "serve": { + "executor": "@nx/js:node", + "options": { + "buildTarget": "my-app:build" + } + }, + "build": { + "executor": "@nx/esbuild:esbuild", + "options": { + "main": "my-app/src/main.ts", + "output": ["dist/my-app"], + //... + } + }, + } +} +``` + +```bash +npx nx serve my-app +``` + +## Examples + +{% tabs %} +{% tab label="Pass extra Node CLI arguments" %} + +Using `runtimeArgs`, you can pass arguments to the underlying `node` command. For example, if you want to set [`--no-warnings`](https://nodejs.org/api/cli.html#--no-warnings) to silence all Node warnings, then add the following to the `project.json` file. + +```json +"my-app": { + "targets": { + "serve": { + "executor": "@nx/js:node", + "options": { + "runtimeArgs": ["--no-warnings"], + //... + }, + }, + } +} +``` + +{% /tab %} + +{% tab label="Run all task dependencies" %} + +If your application build depends on other tasks, and you want those tasks to also be executed, then set the `runBuildTargetDependencies` to `true`. For example, a library may have a task to generate GraphQL schemas, which is consume by the application. In this case, you want to run the generate task before building and running the application. + +This option is also useful when the build consumes a library from its output, not its source. For example, if an executor that supports `buildLibsFromSource` option has it set to `false` (e.g. [`@nx/webpack:webpack`](/packages/webpack/executors/webpack)). + +Note that this option will increase the build time, so use it only when necessary. + +```json +"my-app": { + "targets": { + "serve": { + "executor": "@nx/js:node", + "options": { + "runBuildTargetDependencies": true, + //... + }, + }, + } +} +``` + +{% /tab %} + +{% /tabs %} diff --git a/packages/js/src/executors/node/node.impl.ts b/packages/js/src/executors/node/node.impl.ts index ded44973ea31c..841ce5b2fdd4a 100644 --- a/packages/js/src/executors/node/node.impl.ts +++ b/packages/js/src/executors/node/node.impl.ts @@ -114,48 +114,67 @@ export async function* nodeExecutor( childProcess: null, promise: null, start: async () => { - let buildFailed = false; - // Run the build - task.promise = new Promise(async (resolve, reject) => { - task.childProcess = exec( - `npx nx run ${context.projectName}:${buildTarget.target}${ - buildTarget.configuration ? `:${buildTarget.configuration}` : '' - }`, + if (options.runBuildTargetDependencies) { + // If task dependencies are to be run, then we need to run through CLI since `runExecutor` doesn't support it. + task.promise = new Promise(async (resolve, reject) => { + task.childProcess = fork( + require.resolve('nx'), + [ + 'run', + `${context.projectName}:${buildTarget.target}${ + buildTarget.configuration + ? `:${buildTarget.configuration}` + : '' + }`, + ], + { + cwd: context.root, + stdio: 'inherit', + } + ); + task.childProcess.once('exit', (code) => { + if (code === 0) resolve(); + else reject(); + }); + }); + } else { + const output = await runExecutor( + buildTarget, { - cwd: context.root, + ...options.buildTargetOptions, + watch: false, // we'll handle the watch in this executor }, - (error, stdout, stderr) => { - if ( - // Build succeeded - !error || - // If task was killed then another build process has started, ignore errors. - task.killed - ) { - resolve(); - return; - } - - logger.info(stdout); - buildFailed = true; - if (options.watch) { - logger.error( - `Build failed, waiting for changes to restart...` - ); - resolve(); // Don't reject because it'll error out and kill the Nx process. - } else { - logger.error(`Build failed. See above for errors.`); - reject(); - } - } + context ); - }); + task.promise = new Promise(async (resolve, reject) => { + let error = false; + let event; + do { + event = await output.next(); + if (event.value?.success === false) { + error = true; + } + } while (!event.done); + if (error) reject(); + else resolve(); + }); + } - // Wait for build to finish - await task.promise; + // Wait for build to finish. + try { + await task.promise; + } catch { + // If in watch-mode, don't throw or else the process exits. + if (options.watch) { + logger.error(`Build failed, waiting for changes to restart...`); + return; + } else { + throw new Error(`Build failed. See above for errors.`); + } + } - // Task may have been stopped due to another running task. - // OR build failed, so don't start the process. - if (task.killed || buildFailed) return; + // Before running the program, check if the task has been killed (by a new change during watch). + if (task.killed) return; // Run the program task.promise = new Promise((resolve, reject) => { @@ -173,16 +192,17 @@ export async function* nodeExecutor( } ); - task.childProcess.stderr.on('data', (data) => { + const handleStdErr = (data) => { // Don't log out error if task is killed and new one has started. // This could happen if a new build is triggered while new process is starting, since the operation is not atomic. // Log the error in normal mode if (!options.watch || !task.killed) { logger.error(data.toString()); } - }); - + }; + task.childProcess.stderr.on('data', handleStdErr); task.childProcess.once('exit', (code) => { + task.childProcess.off('data', handleStdErr); if (options.watch && !task.killed) { logger.info( `NX Process exited with code ${code}, waiting for changes to restart...` @@ -203,7 +223,11 @@ export async function* nodeExecutor( if (task.childProcess) { await killTree(task.childProcess.pid, signal); } - await task.promise; + try { + await task.promise; + } catch { + // Doesn't matter if task fails, we just need to wait until it finishes. + } }, }; diff --git a/packages/js/src/executors/node/schema.d.ts b/packages/js/src/executors/node/schema.d.ts index 08b8ebb072e8d..1da16bda357ff 100644 --- a/packages/js/src/executors/node/schema.d.ts +++ b/packages/js/src/executors/node/schema.d.ts @@ -14,4 +14,5 @@ export interface NodeExecutorOptions { port: number; watch?: boolean; debounce?: number; + runBuildTargetDependencies?: boolean; } diff --git a/packages/js/src/executors/node/schema.json b/packages/js/src/executors/node/schema.json index 302562492b8e5..4433bcb6d2066 100644 --- a/packages/js/src/executors/node/schema.json +++ b/packages/js/src/executors/node/schema.json @@ -27,12 +27,14 @@ "host": { "type": "string", "default": "localhost", - "description": "The host to inspect the process on." + "description": "The host to inspect the process on.", + "x-priority": "important" }, "port": { "type": "number", "default": 9229, - "description": "The port to inspect the process on. Setting port to 0 will assign random free ports to all forked processes." + "description": "The port to inspect the process on. Setting port to 0 will assign random free ports to all forked processes.", + "x-priority": "important" }, "inspect": { "oneOf": [ @@ -45,7 +47,8 @@ } ], "description": "Ensures the app is starting with debugging.", - "default": "inspect" + "default": "inspect", + "x-priority": "important" }, "runtimeArgs": { "type": "array", @@ -53,7 +56,8 @@ "default": [], "items": { "type": "string" - } + }, + "x-priority": "important" }, "args": { "type": "array", @@ -61,19 +65,28 @@ "default": [], "items": { "type": "string" - } + }, + "x-priority": "important" }, "watch": { "type": "boolean", "description": "Enable re-building when files change.", - "default": true + "default": true, + "x-priority": "important" }, "debounce": { "type": "number", "description": "Delay in milliseconds to wait before restarting. Useful to batch multiple file changes events together. Set to zero (0) to disable.", - "default": 500 + "default": 500, + "x-priority": "important" + }, + "runBuildTargetDependencies": { + "type": "boolean", + "description": "Whether to run dependencies before running the build. Set this to true if the project does not build libraries from source (e.g. 'buildLibsFromSource: false').", + "default": false } }, "additionalProperties": false, - "required": ["buildTarget"] + "required": ["buildTarget"], + "examplesFile": "../../../docs/node-examples.md" } From 64765eb313d33c93bd4db35d86b21ecb43fa5757 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leosvel=20P=C3=A9rez=20Espinosa?= Date: Thu, 6 Jul 2023 09:06:48 +0100 Subject: [PATCH 018/262] feat(misc): change updateBuildableProjectDepsInPackageJson option default value to false (#17920) --- .../angular/executors/ng-packagr-lite.json | 2 +- .../packages/angular/executors/package.json | 2 +- docs/generated/packages/js/executors/swc.json | 2 +- docs/generated/packages/js/executors/tsc.json | 2 +- .../packages/rollup/executors/rollup.json | 2 +- e2e/js/src/js-swc.test.ts | 4 +- e2e/js/src/js-tsc.test.ts | 6 +- e2e/react-core/src/react-package.test.ts | 2 +- packages/angular/migrations.json | 6 ++ .../src/executors/ng-packagr-lite/schema.json | 2 +- .../angular/src/executors/package/schema.json | 2 +- ...-projects-to-update-buildable-deps.spec.ts | 86 +++++++++++++++++++ ...y-set-projects-to-update-buildable-deps.ts | 44 ++++++++++ packages/js/migrations.json | 6 ++ packages/js/src/executors/swc/schema.json | 2 +- packages/js/src/executors/tsc/schema.json | 2 +- ...-projects-to-update-buildable-deps.spec.ts | 76 ++++++++++++++++ ...y-set-projects-to-update-buildable-deps.ts | 44 ++++++++++ packages/rollup/migrations.json | 6 ++ .../rollup/src/executors/rollup/schema.json | 2 +- ...-projects-to-update-buildable-deps.spec.ts | 76 ++++++++++++++++ ...y-set-projects-to-update-buildable-deps.ts | 39 +++++++++ 22 files changed, 399 insertions(+), 16 deletions(-) create mode 100644 packages/angular/src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps.spec.ts create mode 100644 packages/angular/src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps.ts create mode 100644 packages/js/src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps.spec.ts create mode 100644 packages/js/src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps.ts create mode 100644 packages/rollup/src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps.spec.ts create mode 100644 packages/rollup/src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps.ts diff --git a/docs/generated/packages/angular/executors/ng-packagr-lite.json b/docs/generated/packages/angular/executors/ng-packagr-lite.json index 5a6b2543c78dd..306a1c5092183 100644 --- a/docs/generated/packages/angular/executors/ng-packagr-lite.json +++ b/docs/generated/packages/angular/executors/ng-packagr-lite.json @@ -43,7 +43,7 @@ "updateBuildableProjectDepsInPackageJson": { "type": "boolean", "description": "Whether to update the buildable project dependencies in the build output package.json.", - "default": true + "default": false }, "buildableProjectDepsInPackageJsonType": { "type": "string", diff --git a/docs/generated/packages/angular/executors/package.json b/docs/generated/packages/angular/executors/package.json index 2efc57dc3abc4..a6cbc49aa14f9 100644 --- a/docs/generated/packages/angular/executors/package.json +++ b/docs/generated/packages/angular/executors/package.json @@ -46,7 +46,7 @@ "updateBuildableProjectDepsInPackageJson": { "type": "boolean", "description": "Whether to update the buildable project dependencies in the build output package.json.", - "default": true + "default": false }, "buildableProjectDepsInPackageJsonType": { "type": "string", diff --git a/docs/generated/packages/js/executors/swc.json b/docs/generated/packages/js/executors/swc.json index 48bec366c3f6f..1578c85eb9da6 100644 --- a/docs/generated/packages/js/executors/swc.json +++ b/docs/generated/packages/js/executors/swc.json @@ -98,7 +98,7 @@ "updateBuildableProjectDepsInPackageJson": { "type": "boolean", "description": "Whether to update the buildable project dependencies in the build output package.json.", - "default": true + "default": false }, "buildableProjectDepsInPackageJsonType": { "type": "string", diff --git a/docs/generated/packages/js/executors/tsc.json b/docs/generated/packages/js/executors/tsc.json index a0f26a4878d02..61f9e1b61d88a 100644 --- a/docs/generated/packages/js/executors/tsc.json +++ b/docs/generated/packages/js/executors/tsc.json @@ -98,7 +98,7 @@ "updateBuildableProjectDepsInPackageJson": { "type": "boolean", "description": "Whether to update the buildable project dependencies in the build output package.json.", - "default": true + "default": false }, "buildableProjectDepsInPackageJsonType": { "type": "string", diff --git a/docs/generated/packages/rollup/executors/rollup.json b/docs/generated/packages/rollup/executors/rollup.json index 1db6a873ceb85..0034da2d0f532 100644 --- a/docs/generated/packages/rollup/executors/rollup.json +++ b/docs/generated/packages/rollup/executors/rollup.json @@ -84,7 +84,7 @@ "updateBuildableProjectDepsInPackageJson": { "type": "boolean", "description": "Update buildable project dependencies in `package.json`.", - "default": true + "default": false }, "buildableProjectDepsInPackageJsonType": { "type": "string", diff --git a/e2e/js/src/js-swc.test.ts b/e2e/js/src/js-swc.test.ts index 502abcf3ffaba..f07b82f080ca8 100644 --- a/e2e/js/src/js-swc.test.ts +++ b/e2e/js/src/js-swc.test.ts @@ -91,7 +91,9 @@ describe('js e2e', () => { return json; }); - runCLI(`build ${lib} --generateLockfile=true`); + runCLI( + `build ${lib} --generateLockfile=true --updateBuildableProjectDepsInPackageJson` + ); checkFilesExist( `dist/libs/${lib}/package.json`, `dist/libs/${lib}/${ diff --git a/e2e/js/src/js-tsc.test.ts b/e2e/js/src/js-tsc.test.ts index 7c33ab06a7837..3494742bc2c64 100644 --- a/e2e/js/src/js-tsc.test.ts +++ b/e2e/js/src/js-tsc.test.ts @@ -129,9 +129,7 @@ describe('js e2e', () => { return json; }); - runCLI(`build ${lib}`); - - const rootPackageJson = readJson(`package.json`); + runCLI(`build ${lib} --updateBuildableProjectDepsInPackageJson`); expect(readJson(`dist/libs/${lib}/package.json`)).toHaveProperty( 'peerDependencies.tslib' @@ -221,7 +219,7 @@ describe('package.json updates', () => { `; }); - runCLI(`build ${lib}`); + runCLI(`build ${lib} --updateBuildableProjectDepsInPackageJson`); // Check that only 'react' exists, don't care about version expect(readJson(`dist/libs/${lib}/package.json`).dependencies).toEqual({ diff --git a/e2e/react-core/src/react-package.test.ts b/e2e/react-core/src/react-package.test.ts index 17f33f546e70e..6042f542cddd5 100644 --- a/e2e/react-core/src/react-package.test.ts +++ b/e2e/react-core/src/react-package.test.ts @@ -129,7 +129,7 @@ describe('Build React libraries and apps', () => { /* * 2. With dependencies */ - runCLI(`build ${parentLib}`); + runCLI(`build ${parentLib} --updateBuildableProjectDepsInPackageJson`); checkFilesExist(`dist/libs/${parentLib}/index.js`); diff --git a/packages/angular/migrations.json b/packages/angular/migrations.json index 7c696d62d6a52..3cfcbaa2da113 100644 --- a/packages/angular/migrations.json +++ b/packages/angular/migrations.json @@ -263,6 +263,12 @@ }, "description": "Update the @angular/cli package version to ~16.1.0.", "factory": "./src/migrations/update-16-4-0/update-angular-cli" + }, + "explicitly-set-projects-to-update-buildable-deps": { + "cli": "nx", + "version": "16.6.0-beta.0", + "description": "Explicitly set 'updateBuildableProjectDepsInPackageJson' to 'true' in targets that rely on that value as the default.", + "factory": "./src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps" } }, "packageJsonUpdates": { diff --git a/packages/angular/src/executors/ng-packagr-lite/schema.json b/packages/angular/src/executors/ng-packagr-lite/schema.json index 2a769f6bfdb06..2051bb28a8e0a 100644 --- a/packages/angular/src/executors/ng-packagr-lite/schema.json +++ b/packages/angular/src/executors/ng-packagr-lite/schema.json @@ -40,7 +40,7 @@ "updateBuildableProjectDepsInPackageJson": { "type": "boolean", "description": "Whether to update the buildable project dependencies in the build output package.json.", - "default": true + "default": false }, "buildableProjectDepsInPackageJsonType": { "type": "string", diff --git a/packages/angular/src/executors/package/schema.json b/packages/angular/src/executors/package/schema.json index 8b48557b25ba4..1279a11875937 100644 --- a/packages/angular/src/executors/package/schema.json +++ b/packages/angular/src/executors/package/schema.json @@ -40,7 +40,7 @@ "updateBuildableProjectDepsInPackageJson": { "type": "boolean", "description": "Whether to update the buildable project dependencies in the build output package.json.", - "default": true + "default": false }, "buildableProjectDepsInPackageJsonType": { "type": "string", diff --git a/packages/angular/src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps.spec.ts b/packages/angular/src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps.spec.ts new file mode 100644 index 0000000000000..cc0f0378242ae --- /dev/null +++ b/packages/angular/src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps.spec.ts @@ -0,0 +1,86 @@ +import { + ProjectConfiguration, + Tree, + addProjectConfiguration, + readProjectConfiguration, +} from '@nx/devkit'; +import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; +import migration from './explicitly-set-projects-to-update-buildable-deps'; + +describe('explicitly-set-projects-to-update-buildable-deps migration', () => { + let tree: Tree; + + beforeEach(() => { + tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' }); + }); + + it.each([ + '@nx/angular:ng-packagr-lite', + '@nrwl/angular:ng-packagr-lite', + '@nx/angular:package', + '@nrwl/angular:package', + ])( + 'should set updateBuildableProjectDepsInPackageJson option to "true" when not specified in target using "%s"', + async (executor) => { + addProjectConfiguration(tree, 'lib1', { + root: 'libs/lib1', + projectType: 'library', + targets: { build: { executor, options: {} } }, + }); + + await migration(tree); + + const project = readProjectConfiguration(tree, 'lib1'); + expect( + project.targets.build.options.updateBuildableProjectDepsInPackageJson + ).toBe(true); + } + ); + + it.each([ + '@nx/angular:ng-packagr-lite', + '@nrwl/angular:ng-packagr-lite', + '@nx/angular:package', + '@nrwl/angular:package', + ])( + 'should not overwrite updateBuildableProjectDepsInPackageJson option when it is specified in target using "%s"', + async (executor) => { + addProjectConfiguration(tree, 'lib1', { + root: 'libs/lib1', + projectType: 'library', + targets: { + build: { + executor, + options: { updateBuildableProjectDepsInPackageJson: false }, + }, + }, + }); + + await migration(tree); + + const project = readProjectConfiguration(tree, 'lib1'); + expect( + project.targets.build.options.updateBuildableProjectDepsInPackageJson + ).toBe(false); + } + ); + + it('should not update targets using other executors', async () => { + const originalProjectConfig: ProjectConfiguration = { + root: 'libs/lib1', + projectType: 'library', + targets: { + build: { + executor: 'some-executor', + options: {}, + }, + }, + }; + addProjectConfiguration(tree, 'lib1', originalProjectConfig); + + await migration(tree); + + const project = readProjectConfiguration(tree, 'lib1'); + expect(project.targets).toStrictEqual(originalProjectConfig.targets); + }); +}); diff --git a/packages/angular/src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps.ts b/packages/angular/src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps.ts new file mode 100644 index 0000000000000..09e5f6c9cc4d5 --- /dev/null +++ b/packages/angular/src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps.ts @@ -0,0 +1,44 @@ +import { + formatFiles, + getProjects, + Tree, + updateProjectConfiguration, +} from '@nx/devkit'; + +const executors = new Set([ + '@nx/angular:ng-packagr-lite', + '@nrwl/angular:ng-packagr-lite', + '@nx/angular:package', + '@nrwl/angular:package', +]); + +export default async function (tree: Tree) { + const projects = getProjects(tree); + + for (const [projectName, project] of projects) { + if (project.projectType !== 'library') { + continue; + } + + let updated = false; + for (const [, target] of Object.entries(project.targets || {})) { + if (!executors.has(target.executor)) { + continue; + } + + if ( + target.options && + target.options.updateBuildableProjectDepsInPackageJson === undefined + ) { + target.options.updateBuildableProjectDepsInPackageJson = true; + updated = true; + } + } + + if (updated) { + updateProjectConfiguration(tree, projectName, project); + } + } + + await formatFiles(tree); +} diff --git a/packages/js/migrations.json b/packages/js/migrations.json index 8e3618d770e4b..9f0ced6950a75 100644 --- a/packages/js/migrations.json +++ b/packages/js/migrations.json @@ -41,6 +41,12 @@ "version": "16.0.0-beta.1", "description": "Replace @nrwl/js with @nx/js", "implementation": "./src/migrations/update-16-0-0-add-nx-packages/update-16-0-0-add-nx-packages" + }, + "explicitly-set-projects-to-update-buildable-deps": { + "cli": "nx", + "version": "16.6.0-beta.0", + "description": "Explicitly set 'updateBuildableProjectDepsInPackageJson' to 'true' in targets that rely on that value as the default.", + "factory": "./src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps" } }, "packageJsonUpdates": { diff --git a/packages/js/src/executors/swc/schema.json b/packages/js/src/executors/swc/schema.json index dc8bfc12303c6..6b356438d8d1b 100644 --- a/packages/js/src/executors/swc/schema.json +++ b/packages/js/src/executors/swc/schema.json @@ -69,7 +69,7 @@ "updateBuildableProjectDepsInPackageJson": { "type": "boolean", "description": "Whether to update the buildable project dependencies in the build output package.json.", - "default": true + "default": false }, "buildableProjectDepsInPackageJsonType": { "type": "string", diff --git a/packages/js/src/executors/tsc/schema.json b/packages/js/src/executors/tsc/schema.json index 9a8cc6557b78c..03078862a882d 100644 --- a/packages/js/src/executors/tsc/schema.json +++ b/packages/js/src/executors/tsc/schema.json @@ -57,7 +57,7 @@ "updateBuildableProjectDepsInPackageJson": { "type": "boolean", "description": "Whether to update the buildable project dependencies in the build output package.json.", - "default": true + "default": false }, "buildableProjectDepsInPackageJsonType": { "type": "string", diff --git a/packages/js/src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps.spec.ts b/packages/js/src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps.spec.ts new file mode 100644 index 0000000000000..07caa361d79f4 --- /dev/null +++ b/packages/js/src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps.spec.ts @@ -0,0 +1,76 @@ +import { + ProjectConfiguration, + Tree, + addProjectConfiguration, + readProjectConfiguration, +} from '@nx/devkit'; +import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; +import migration from './explicitly-set-projects-to-update-buildable-deps'; + +describe('explicitly-set-projects-to-update-buildable-deps migration', () => { + let tree: Tree; + + beforeEach(() => { + tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' }); + }); + + it.each(['@nx/js:swc', '@nrwl/js:swc', '@nx/js:tsc', '@nrwl/js:tsc'])( + 'should set updateBuildableProjectDepsInPackageJson option to "true" when not specified in target using "%s"', + async (executor) => { + addProjectConfiguration(tree, 'lib1', { + root: 'libs/lib1', + projectType: 'library', + targets: { build: { executor, options: {} } }, + }); + + await migration(tree); + + const project = readProjectConfiguration(tree, 'lib1'); + expect( + project.targets.build.options.updateBuildableProjectDepsInPackageJson + ).toBe(true); + } + ); + + it.each(['@nx/js:swc', '@nrwl/js:swc', '@nx/js:tsc', '@nrwl/js:tsc'])( + 'should not overwrite updateBuildableProjectDepsInPackageJson option when it is specified in target using "%s"', + async (executor) => { + addProjectConfiguration(tree, 'lib1', { + root: 'libs/lib1', + projectType: 'library', + targets: { + build: { + executor, + options: { updateBuildableProjectDepsInPackageJson: false }, + }, + }, + }); + + await migration(tree); + + const project = readProjectConfiguration(tree, 'lib1'); + expect( + project.targets.build.options.updateBuildableProjectDepsInPackageJson + ).toBe(false); + } + ); + + it('should not update targets using other executors', async () => { + const originalProjectConfig: ProjectConfiguration = { + root: 'libs/lib1', + projectType: 'library', + targets: { + build: { + executor: 'some-executor', + options: {}, + }, + }, + }; + addProjectConfiguration(tree, 'lib1', originalProjectConfig); + + await migration(tree); + + const project = readProjectConfiguration(tree, 'lib1'); + expect(project.targets).toStrictEqual(originalProjectConfig.targets); + }); +}); diff --git a/packages/js/src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps.ts b/packages/js/src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps.ts new file mode 100644 index 0000000000000..5273b2a748520 --- /dev/null +++ b/packages/js/src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps.ts @@ -0,0 +1,44 @@ +import { + formatFiles, + getProjects, + Tree, + updateProjectConfiguration, +} from '@nx/devkit'; + +const executors = new Set([ + '@nx/js:swc', + '@nrwl/js:swc', + '@nx/js:tsc', + '@nrwl/js:tsc', +]); + +export default async function (tree: Tree) { + const projects = getProjects(tree); + + for (const [projectName, project] of projects) { + if (project.projectType !== 'library') { + continue; + } + + let updated = false; + for (const [, target] of Object.entries(project.targets || {})) { + if (!executors.has(target.executor)) { + continue; + } + + if ( + target.options && + target.options.updateBuildableProjectDepsInPackageJson === undefined + ) { + target.options.updateBuildableProjectDepsInPackageJson = true; + updated = true; + } + } + + if (updated) { + updateProjectConfiguration(tree, projectName, project); + } + } + + await formatFiles(tree); +} diff --git a/packages/rollup/migrations.json b/packages/rollup/migrations.json index eb151def3ad9b..cfd0ba1e6e6fe 100644 --- a/packages/rollup/migrations.json +++ b/packages/rollup/migrations.json @@ -17,6 +17,12 @@ "version": "16-3-3-beta.0", "description": "Add babelUpwardRootMode if not already defined", "implementation": "./src/migrations/update-16-3-3-add-babel-upward-root-mode-flag/update-16-3-3-add-babel-upward-root-mode-flag" + }, + "explicitly-set-projects-to-update-buildable-deps": { + "cli": "nx", + "version": "16.6.0-beta.0", + "description": "Explicitly set 'updateBuildableProjectDepsInPackageJson' to 'true' in targets that rely on that value as the default.", + "factory": "./src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps" } }, "packageJsonUpdates": {} diff --git a/packages/rollup/src/executors/rollup/schema.json b/packages/rollup/src/executors/rollup/schema.json index bbd35b6a81c22..c30f11f6d18c8 100644 --- a/packages/rollup/src/executors/rollup/schema.json +++ b/packages/rollup/src/executors/rollup/schema.json @@ -92,7 +92,7 @@ "updateBuildableProjectDepsInPackageJson": { "type": "boolean", "description": "Update buildable project dependencies in `package.json`.", - "default": true + "default": false }, "buildableProjectDepsInPackageJsonType": { "type": "string", diff --git a/packages/rollup/src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps.spec.ts b/packages/rollup/src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps.spec.ts new file mode 100644 index 0000000000000..0d244a11a33ec --- /dev/null +++ b/packages/rollup/src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps.spec.ts @@ -0,0 +1,76 @@ +import { + ProjectConfiguration, + Tree, + addProjectConfiguration, + readProjectConfiguration, +} from '@nx/devkit'; +import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; +import migration from './explicitly-set-projects-to-update-buildable-deps'; + +describe('explicitly-set-projects-to-update-buildable-deps migration', () => { + let tree: Tree; + + beforeEach(() => { + tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' }); + }); + + it.each(['@nx/rollup:rollup', '@nrwl/rollup:rollup'])( + 'should set updateBuildableProjectDepsInPackageJson option to "true" when not specified in target using "%s"', + async (executor) => { + addProjectConfiguration(tree, 'lib1', { + root: 'libs/lib1', + projectType: 'library', + targets: { build: { executor, options: {} } }, + }); + + await migration(tree); + + const project = readProjectConfiguration(tree, 'lib1'); + expect( + project.targets.build.options.updateBuildableProjectDepsInPackageJson + ).toBe(true); + } + ); + + it.each(['@nx/js:swc', '@nrwl/js:swc', '@nx/js:tsc', '@nrwl/js:tsc'])( + 'should not overwrite updateBuildableProjectDepsInPackageJson option when it is specified in target using "%s"', + async (executor) => { + addProjectConfiguration(tree, 'lib1', { + root: 'libs/lib1', + projectType: 'library', + targets: { + build: { + executor, + options: { updateBuildableProjectDepsInPackageJson: false }, + }, + }, + }); + + await migration(tree); + + const project = readProjectConfiguration(tree, 'lib1'); + expect( + project.targets.build.options.updateBuildableProjectDepsInPackageJson + ).toBe(false); + } + ); + + it('should not update targets using other executors', async () => { + const originalProjectConfig: ProjectConfiguration = { + root: 'libs/lib1', + projectType: 'library', + targets: { + build: { + executor: 'some-executor', + options: {}, + }, + }, + }; + addProjectConfiguration(tree, 'lib1', originalProjectConfig); + + await migration(tree); + + const project = readProjectConfiguration(tree, 'lib1'); + expect(project.targets).toStrictEqual(originalProjectConfig.targets); + }); +}); diff --git a/packages/rollup/src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps.ts b/packages/rollup/src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps.ts new file mode 100644 index 0000000000000..e3377e89e2f7d --- /dev/null +++ b/packages/rollup/src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps.ts @@ -0,0 +1,39 @@ +import { + formatFiles, + getProjects, + Tree, + updateProjectConfiguration, +} from '@nx/devkit'; + +const executors = new Set(['@nx/rollup:rollup', '@nrwl/rollup:rollup']); + +export default async function (tree: Tree) { + const projects = getProjects(tree); + + for (const [projectName, project] of projects) { + if (project.projectType !== 'library') { + continue; + } + + let updated = false; + for (const [, target] of Object.entries(project.targets || {})) { + if (!executors.has(target.executor)) { + continue; + } + + if ( + target.options && + target.options.updateBuildableProjectDepsInPackageJson === undefined + ) { + target.options.updateBuildableProjectDepsInPackageJson = true; + updated = true; + } + } + + if (updated) { + updateProjectConfiguration(tree, projectName, project); + } + } + + await formatFiles(tree); +} From 0f9cece6415a15421170f8e132e8961dbbd1e9f2 Mon Sep 17 00:00:00 2001 From: Isaac Mann Date: Wed, 5 Jul 2023 12:38:20 -0400 Subject: [PATCH 019/262] feat(nx-dev): changelog anchor links to each version --- nx-dev/nx-dev/pages/reference/changelog.tsx | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/nx-dev/nx-dev/pages/reference/changelog.tsx b/nx-dev/nx-dev/pages/reference/changelog.tsx index 8df1e75b21ada..38d77a80ae6f2 100644 --- a/nx-dev/nx-dev/pages/reference/changelog.tsx +++ b/nx-dev/nx-dev/pages/reference/changelog.tsx @@ -1,4 +1,4 @@ -import { TagIcon } from '@heroicons/react/24/outline'; +import { LinkIcon, TagIcon } from '@heroicons/react/24/outline'; import { Breadcrumbs, DocumentationHeader, @@ -188,7 +188,7 @@ export default function Changelog(props: ChangeLogProps): JSX.Element { return entry; }); const convertToDate = (invalidDate) => - new Date(invalidDate.replace(/(nd|th|rd)/g, '')); + new Date(invalidDate.replace(/(nd|th|rd|st)/g, '')); const { toggleNav, navIsOpen } = useNavToggle(); const menu = { @@ -251,7 +251,10 @@ export default function Changelog(props: ChangeLogProps): JSX.Element {
-
+ From e60702f428e3379689fc79de630884a53957e003 Mon Sep 17 00:00:00 2001 From: Isaac Mann Date: Wed, 5 Jul 2023 14:32:18 -0400 Subject: [PATCH 020/262] feat(nx-dev): anchor links to version instead of timestamp --- nx-dev/nx-dev/pages/reference/changelog.tsx | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/nx-dev/nx-dev/pages/reference/changelog.tsx b/nx-dev/nx-dev/pages/reference/changelog.tsx index 38d77a80ae6f2..1041730db2305 100644 --- a/nx-dev/nx-dev/pages/reference/changelog.tsx +++ b/nx-dev/nx-dev/pages/reference/changelog.tsx @@ -252,7 +252,7 @@ export default function Changelog(props: ChangeLogProps): JSX.Element {

@@ -269,6 +269,9 @@ export default function Changelog(props: ChangeLogProps): JSX.Element { />{' '} v{changelog.version} +

From ccd195d60a13008f9410a3382e85e31c4474290b Mon Sep 17 00:00:00 2001 From: Nathan Walker Date: Thu, 6 Jul 2023 06:20:02 -0700 Subject: [PATCH 021/262] fix(js): remove duplicate alias (#17978) --- packages/js/generators.json | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/js/generators.json b/packages/js/generators.json index 5b44089d15bae..6b71476703797 100644 --- a/packages/js/generators.json +++ b/packages/js/generators.json @@ -12,7 +12,6 @@ "init": { "factory": "./src/generators/init/init#initSchematic", "schema": "./src/generators/init/schema.json", - "aliases": ["lib"], "x-type": "init", "description": "Initialize a TS/JS workspace.", "hidden": true From 601c65241b0f4da45c4946d650359df1582fdd1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Jona=C5=A1?= Date: Thu, 6 Jul 2023 18:18:53 +0200 Subject: [PATCH 022/262] chore(repo): bump versions of ci images (#17969) --- .circleci/config.yml | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 4b0db7816e8be..e774a3c7a5275 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -5,7 +5,6 @@ version: 2.1 # ------------------------- orbs: nx: nrwl/nx@1.6.1 - node: circleci/node@5.1.0 rust: circleci/rust@1.6.0 browser-tools: circleci/browser-tools@1.4.0 @@ -20,14 +19,14 @@ executors: linux: <<: *defaults docker: - - image: cimg/rust:1.66.1-browsers + - image: cimg/rust:1.70.0-browsers resource_class: medium+ macos: <<: *defaults resource_class: macos.x86.medium.gen2 macos: - xcode: &_XCODE_VERSION '13.0.0' + xcode: '14.2.0' # ------------------------- # COMMANDS @@ -42,10 +41,22 @@ commands: name: Restore pnpm Package Cache keys: - node-deps-{{ arch }}-v3-{{ checksum "pnpm-lock.yaml" }} - - run: - name: Install pnpm package manager - command: | - npm install -g @pnpm/exe@8.3.1 + - when: + condition: + equal: [<< parameters.os >>, linux] + steps: + - run: + name: Install pnpm package manager (linux) + command: | + npm install --prefix=$HOME/.local -g @pnpm/exe@8.3.1 + - when: + condition: + equal: [<< parameters.os >>, macos] + steps: + - run: + name: Install pnpm package manager (macos) + command: | + npm install -g @pnpm/exe@8.3.1 - run: name: Install Dependencies command: | @@ -95,9 +106,6 @@ commands: sudo apt-get install -y ca-certificates lsof - browser-tools/install-chrome - browser-tools/install-chromedriver - - node/install: - # Use LTS version - node-version: '' - run-pnpm-install: os: << parameters.os >> From b40f0bea99aa25f2ecfb99f553a3a4851b12d5e8 Mon Sep 17 00:00:00 2001 From: Isaac Mann Date: Thu, 6 Jul 2023 12:57:39 -0400 Subject: [PATCH 023/262] docs(core): changelog for 16.5.0 (#18004) --- docs/changelog/16_5_0.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 docs/changelog/16_5_0.md diff --git a/docs/changelog/16_5_0.md b/docs/changelog/16_5_0.md new file mode 100644 index 0000000000000..d076d859d61b0 --- /dev/null +++ b/docs/changelog/16_5_0.md @@ -0,0 +1,17 @@ +# Nx 16.5 + +[Read the 16.5 release blog post](https://blog.nrwl.io/nx-16-5-release-7887a27cb5) + +{% youtube +src="https://www.youtube.com/embed/7XLoLOc3afY" +title="Nx 16.5 Release!!!!" +width="100%" /%} + +Feature highlights: + +{% cards cols="2" %} +{% card title="Targeting Tasks by Tags" type="video" url="https://youtu.be/enQDQmFquGU" /%} +{% card title="Nx Verdaccio Support" type="video" url="https://youtu.be/t1c925TzrzE" /%} +{% card title="externalDependencies Input Type" type="video" url="https://youtu.be/FRqgWBmHmAU" /%} +{% card title="Nx Console Revamped" type="video" url="https://youtu.be/p455D4W7330" /%} +{% /cards %} From 5af5e6ca91eca112d3dc0cf89565284575749135 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Jona=C5=A1?= Date: Fri, 7 Jul 2023 03:01:49 +0200 Subject: [PATCH 024/262] docs(linter): add documentation on dependency-checks rule (#17962) --- docs/generated/manifests/menus.json | 8 +++ docs/generated/manifests/packages.json | 11 +++ docs/generated/packages-metadata.json | 11 +++ .../documents/dependency-checks.md | 71 +++++++++++++++++++ .../documents/enforce-module-boundaries.md | 2 + .../eslint-plugin/documents/overview.md | 11 ++- docs/map.json | 6 ++ .../packages/linter/dependency-checks.md | 71 +++++++++++++++++++ .../linter/enforce-module-boundaries.md | 2 + docs/shared/packages/linter/eslint-plugin.md | 11 ++- docs/shared/reference/sitemap.md | 1 + 11 files changed, 201 insertions(+), 4 deletions(-) create mode 100644 docs/generated/packages/eslint-plugin/documents/dependency-checks.md create mode 100644 docs/shared/packages/linter/dependency-checks.md diff --git a/docs/generated/manifests/menus.json b/docs/generated/manifests/menus.json index e8d3610b0fa04..8f3fb2d28b032 100644 --- a/docs/generated/manifests/menus.json +++ b/docs/generated/manifests/menus.json @@ -4881,6 +4881,14 @@ "isExternal": false, "children": [], "disableCollapsible": false + }, + { + "name": "The `dependency-checks` rule", + "path": "/packages/eslint-plugin/documents/dependency-checks", + "id": "dependency-checks", + "isExternal": false, + "children": [], + "disableCollapsible": false } ], "isExternal": false, diff --git a/docs/generated/manifests/packages.json b/docs/generated/manifests/packages.json index f8117f2c9464f..cf9da9f004552 100644 --- a/docs/generated/manifests/packages.json +++ b/docs/generated/manifests/packages.json @@ -690,6 +690,17 @@ "path": "/packages/eslint-plugin/documents/enforce-module-boundaries", "tags": [], "originalFilePath": "shared/packages/linter/enforce-module-boundaries" + }, + "/packages/eslint-plugin/documents/dependency-checks": { + "id": "dependency-checks", + "name": "The `dependency-checks` rule", + "description": "The eslint-plugin package is an ESLint plugin that contains a collection of recommended ESLint rule configurations which you can extend from in your own ESLint configs, as well as an Nx-specific lint rule called enforce-module-boundaries.", + "file": "generated/packages/eslint-plugin/documents/dependency-checks", + "itemList": [], + "isExternal": false, + "path": "/packages/eslint-plugin/documents/dependency-checks", + "tags": [], + "originalFilePath": "shared/packages/linter/dependency-checks" } }, "root": "/packages/eslint-plugin", diff --git a/docs/generated/packages-metadata.json b/docs/generated/packages-metadata.json index 406d9b0d5d290..6efa02fb1bf79 100644 --- a/docs/generated/packages-metadata.json +++ b/docs/generated/packages-metadata.json @@ -680,6 +680,17 @@ "path": "eslint-plugin/documents/enforce-module-boundaries", "tags": [], "originalFilePath": "shared/packages/linter/enforce-module-boundaries" + }, + { + "id": "dependency-checks", + "name": "The `dependency-checks` rule", + "description": "The eslint-plugin package is an ESLint plugin that contains a collection of recommended ESLint rule configurations which you can extend from in your own ESLint configs, as well as an Nx-specific lint rule called enforce-module-boundaries.", + "file": "generated/packages/eslint-plugin/documents/dependency-checks", + "itemList": [], + "isExternal": false, + "path": "eslint-plugin/documents/dependency-checks", + "tags": [], + "originalFilePath": "shared/packages/linter/dependency-checks" } ], "executors": [], diff --git a/docs/generated/packages/eslint-plugin/documents/dependency-checks.md b/docs/generated/packages/eslint-plugin/documents/dependency-checks.md new file mode 100644 index 0000000000000..c905320bf852e --- /dev/null +++ b/docs/generated/packages/eslint-plugin/documents/dependency-checks.md @@ -0,0 +1,71 @@ +# Dependency Checks rule + +The `@nx/dependency-checks` ESLint rule enables you to discover mismatches between dependencies specified in a project's `package.json` and the dependencies that your project depends on. If your project is using, for example, the `axios`, but the `package.json` does not specify it as a dependency, your library might not work correctly. This rule helps catch these problems before your users do. + +The rule uses the project graph to collect all the dependencies of your project, based on the input of your `build` target. It will filter out all the dependencies marked as `devDependencies` in your root `package.json` to ensure dependencies of your compilation pipelines (e.g. dependencies of `webpack.config` or `vite.config`) or test setups are not included in the expected list. + +We use the version numbers of the installed packages when checking whether the version specifier in `package.json` is correct. We do this because this is the only version for which we can "guarantee" that things work and were tested. If you specify a range outside of that version, that would mean that you are shipping potentially untested code. + +## Usage + +You can use the `dependency-checks` rule by adding it to your ESLint rules configuration: + +```jsonc {% fileName=".eslintrc.json" %} +{ + // ... more ESLint config here + "overrides": [ + { + "files": ["*.json"], + "parser": "jsonc-eslint-parser", + "rules": { + "@nx/dependency-checks": "error" + } + } + // ... more ESLint overrides here + ] +} +``` + +Linting `JSON` files is not enabled by default, so you will also need to add `package.json` to the `lintFilePatterns`: + +```jsonc {% fileName="project.json" %} +{ + // ... project.json config + "targets": { + // ... more targets + "lint": { + "executor": "@nx/linter:eslint", + "outputs": ["{options.outputFile}"], + "options": { + "lintFilePatterns": [ + "libs/my-lib/**/*.{ts,tsx,js,jsx}", + "libs/my-lib/package.json" // add this line + ] + } + } + } +} +``` + +Sometimes we intentionally want to add or remove a dependency from our `package.json` despite what the rule suggests. We can use the rule's options to override default behavior: + +```jsonc {% fileName=".eslintrc.json" %} +{ + "@nx/dependency-checks": [ + "error", + { + // for available options check below + } + ] +} +``` + +## Options + +| Property | Type | Default | Description | +| ------------------------- | --------------- | ----------- | ----------------------------------------------------------------------- | +| buildTargets | _Array_ | _["build"]_ | List of build target names | +| ignoredDependencies | _Array_ | _[]_ | List of dependencies to ignore for checks | +| checkMissingDependencies | _boolean_ | _true_ | Disable to skip checking for missing dependencies | +| checkObsoleteDependencies | _boolean_ | _true_ | Disable to skip checking for unused dependencies | +| checkVersionMismatches | _boolean_ | _true_ | Disable to skip checking if version specifier matches installed version | diff --git a/docs/generated/packages/eslint-plugin/documents/enforce-module-boundaries.md b/docs/generated/packages/eslint-plugin/documents/enforce-module-boundaries.md index 17df00f19fed5..4d8061b492eb9 100644 --- a/docs/generated/packages/eslint-plugin/documents/enforce-module-boundaries.md +++ b/docs/generated/packages/eslint-plugin/documents/enforce-module-boundaries.md @@ -1,3 +1,5 @@ +# Enforce module boundaries rule + The `@nx/enforce-module-boundaries` ESLint rule enables you to define strict rules for accessing resources between different projects in the repository. Enforcing strict boundaries helps to prevent unplanned cross-dependencies. ## Usage diff --git a/docs/generated/packages/eslint-plugin/documents/overview.md b/docs/generated/packages/eslint-plugin/documents/overview.md index 7c966c2c24aba..7b00732054f64 100644 --- a/docs/generated/packages/eslint-plugin/documents/overview.md +++ b/docs/generated/packages/eslint-plugin/documents/overview.md @@ -1,4 +1,7 @@ -The `@nx/eslint-plugin` package is an ESLint plugin that contains a collection of recommended ESLint rule configurations which you can extend from in your own ESLint configs, as well as an Nx-specific lint rule called [enforce-module-boundaries](#enforce-module-boundaries-rule). +The `@nx/eslint-plugin` package is an ESLint plugin that contains a collection of recommended ESLint rule configurations which you can extend from in your own ESLint configs, as well as the following Nx-specific ESLint rules: + +- [enforce-module-boundaries](#enforce-module-boundaries-rule) +- [dependency-checks](#dependency-checks-rule) ## Setting Up ESLint Plugin @@ -54,4 +57,8 @@ You can also use `@nx/react` which includes all three `@nx/react-*` plugins ### Enforce Module Boundaries rule -The `enforce-module-boundaries` ESLint rule enables you to define strict rules for accessing resources between different projects in the repository. Enforcing strict boundaries helps keep prevent unplanned cross-dependencies. Read more about it on a [dedicated page](/packages/eslint-plugin/documents/enforce-module-boundaries) +The `enforce-module-boundaries` ESLint rule enables you to define strict rules for accessing resources between different projects in the repository. Enforcing strict boundaries helps prevent unplanned cross-dependencies. Read more about it on a [dedicated page](/packages/eslint-plugin/documents/enforce-module-boundaries). + +### Dependency Checks rule + +The `@nx/dependency-checks` ESLint rule enables you to discover mismatches between dependencies specified in a project's `package.json` and the dependencies that your project actually depends on. Read more about it on a [dedicated page](/packages/eslint-plugin/documents/dependency-checks). diff --git a/docs/map.json b/docs/map.json index a5cf73848c8c8..de3bc1853a0c5 100644 --- a/docs/map.json +++ b/docs/map.json @@ -2062,6 +2062,12 @@ "name": "The `enforce-module-boundaries` rule", "path": "/packages/eslint-plugin", "file": "shared/packages/linter/enforce-module-boundaries" + }, + { + "id": "dependency-checks", + "name": "The `dependency-checks` rule", + "path": "/packages/eslint-plugin", + "file": "shared/packages/linter/dependency-checks" } ] }, diff --git a/docs/shared/packages/linter/dependency-checks.md b/docs/shared/packages/linter/dependency-checks.md new file mode 100644 index 0000000000000..c905320bf852e --- /dev/null +++ b/docs/shared/packages/linter/dependency-checks.md @@ -0,0 +1,71 @@ +# Dependency Checks rule + +The `@nx/dependency-checks` ESLint rule enables you to discover mismatches between dependencies specified in a project's `package.json` and the dependencies that your project depends on. If your project is using, for example, the `axios`, but the `package.json` does not specify it as a dependency, your library might not work correctly. This rule helps catch these problems before your users do. + +The rule uses the project graph to collect all the dependencies of your project, based on the input of your `build` target. It will filter out all the dependencies marked as `devDependencies` in your root `package.json` to ensure dependencies of your compilation pipelines (e.g. dependencies of `webpack.config` or `vite.config`) or test setups are not included in the expected list. + +We use the version numbers of the installed packages when checking whether the version specifier in `package.json` is correct. We do this because this is the only version for which we can "guarantee" that things work and were tested. If you specify a range outside of that version, that would mean that you are shipping potentially untested code. + +## Usage + +You can use the `dependency-checks` rule by adding it to your ESLint rules configuration: + +```jsonc {% fileName=".eslintrc.json" %} +{ + // ... more ESLint config here + "overrides": [ + { + "files": ["*.json"], + "parser": "jsonc-eslint-parser", + "rules": { + "@nx/dependency-checks": "error" + } + } + // ... more ESLint overrides here + ] +} +``` + +Linting `JSON` files is not enabled by default, so you will also need to add `package.json` to the `lintFilePatterns`: + +```jsonc {% fileName="project.json" %} +{ + // ... project.json config + "targets": { + // ... more targets + "lint": { + "executor": "@nx/linter:eslint", + "outputs": ["{options.outputFile}"], + "options": { + "lintFilePatterns": [ + "libs/my-lib/**/*.{ts,tsx,js,jsx}", + "libs/my-lib/package.json" // add this line + ] + } + } + } +} +``` + +Sometimes we intentionally want to add or remove a dependency from our `package.json` despite what the rule suggests. We can use the rule's options to override default behavior: + +```jsonc {% fileName=".eslintrc.json" %} +{ + "@nx/dependency-checks": [ + "error", + { + // for available options check below + } + ] +} +``` + +## Options + +| Property | Type | Default | Description | +| ------------------------- | --------------- | ----------- | ----------------------------------------------------------------------- | +| buildTargets | _Array_ | _["build"]_ | List of build target names | +| ignoredDependencies | _Array_ | _[]_ | List of dependencies to ignore for checks | +| checkMissingDependencies | _boolean_ | _true_ | Disable to skip checking for missing dependencies | +| checkObsoleteDependencies | _boolean_ | _true_ | Disable to skip checking for unused dependencies | +| checkVersionMismatches | _boolean_ | _true_ | Disable to skip checking if version specifier matches installed version | diff --git a/docs/shared/packages/linter/enforce-module-boundaries.md b/docs/shared/packages/linter/enforce-module-boundaries.md index 17df00f19fed5..4d8061b492eb9 100644 --- a/docs/shared/packages/linter/enforce-module-boundaries.md +++ b/docs/shared/packages/linter/enforce-module-boundaries.md @@ -1,3 +1,5 @@ +# Enforce module boundaries rule + The `@nx/enforce-module-boundaries` ESLint rule enables you to define strict rules for accessing resources between different projects in the repository. Enforcing strict boundaries helps to prevent unplanned cross-dependencies. ## Usage diff --git a/docs/shared/packages/linter/eslint-plugin.md b/docs/shared/packages/linter/eslint-plugin.md index 7c966c2c24aba..7b00732054f64 100644 --- a/docs/shared/packages/linter/eslint-plugin.md +++ b/docs/shared/packages/linter/eslint-plugin.md @@ -1,4 +1,7 @@ -The `@nx/eslint-plugin` package is an ESLint plugin that contains a collection of recommended ESLint rule configurations which you can extend from in your own ESLint configs, as well as an Nx-specific lint rule called [enforce-module-boundaries](#enforce-module-boundaries-rule). +The `@nx/eslint-plugin` package is an ESLint plugin that contains a collection of recommended ESLint rule configurations which you can extend from in your own ESLint configs, as well as the following Nx-specific ESLint rules: + +- [enforce-module-boundaries](#enforce-module-boundaries-rule) +- [dependency-checks](#dependency-checks-rule) ## Setting Up ESLint Plugin @@ -54,4 +57,8 @@ You can also use `@nx/react` which includes all three `@nx/react-*` plugins ### Enforce Module Boundaries rule -The `enforce-module-boundaries` ESLint rule enables you to define strict rules for accessing resources between different projects in the repository. Enforcing strict boundaries helps keep prevent unplanned cross-dependencies. Read more about it on a [dedicated page](/packages/eslint-plugin/documents/enforce-module-boundaries) +The `enforce-module-boundaries` ESLint rule enables you to define strict rules for accessing resources between different projects in the repository. Enforcing strict boundaries helps prevent unplanned cross-dependencies. Read more about it on a [dedicated page](/packages/eslint-plugin/documents/enforce-module-boundaries). + +### Dependency Checks rule + +The `@nx/dependency-checks` ESLint rule enables you to discover mismatches between dependencies specified in a project's `package.json` and the dependencies that your project actually depends on. Read more about it on a [dedicated page](/packages/eslint-plugin/documents/dependency-checks). diff --git a/docs/shared/reference/sitemap.md b/docs/shared/reference/sitemap.md index 9c5f17bca2529..d1a8b24fcdd01 100644 --- a/docs/shared/reference/sitemap.md +++ b/docs/shared/reference/sitemap.md @@ -358,6 +358,7 @@ - [documents](/packages/eslint-plugin/documents) - [Overview](/packages/eslint-plugin/documents/overview) - [The `enforce-module-boundaries` rule](/packages/eslint-plugin/documents/enforce-module-boundaries) + - [The `dependency-checks` rule](/packages/eslint-plugin/documents/dependency-checks) - [expo](/packages/expo) - [documents](/packages/expo/documents) - [Overview](/packages/expo/documents/overview) From 3fdc66dd691c8385ac2f88eb156936449378ae89 Mon Sep 17 00:00:00 2001 From: Jack Hsu Date: Fri, 7 Jul 2023 03:47:03 -0400 Subject: [PATCH 025/262] feat(vite): pin Vite version range to patch releases only to avoid conflicts with Angular (#18010) --- packages/cypress/src/utils/versions.ts | 2 +- packages/storybook/src/utils/versions.ts | 2 +- .../init/__snapshots__/init.spec.ts.snap | 34 +++++++++---------- packages/vite/src/utils/versions.ts | 16 ++++----- 4 files changed, 27 insertions(+), 27 deletions(-) diff --git a/packages/cypress/src/utils/versions.ts b/packages/cypress/src/utils/versions.ts index 8e8160c8a17f2..3faa3cb39093f 100644 --- a/packages/cypress/src/utils/versions.ts +++ b/packages/cypress/src/utils/versions.ts @@ -5,5 +5,5 @@ export const cypressViteDevServerVersion = '^2.2.1'; export const cypressVersion = '^12.16.0'; export const cypressWebpackVersion = '^2.0.0'; export const webpackHttpPluginVersion = '^5.5.0'; -export const viteVersion = '^4.3.4'; +export const viteVersion = '~4.3.9'; export const htmlWebpackPluginVersion = '^5.5.0'; diff --git a/packages/storybook/src/utils/versions.ts b/packages/storybook/src/utils/versions.ts index 24c4a986f06c9..83633c1779fe4 100644 --- a/packages/storybook/src/utils/versions.ts +++ b/packages/storybook/src/utils/versions.ts @@ -7,4 +7,4 @@ export const tsNodeVersion = '10.9.1'; export const storybookVersion = '^7.0.24'; export const reactVersion = '^18.2.0'; -export const viteVersion = '^4.3.4'; +export const viteVersion = '~4.3.9'; diff --git a/packages/vite/src/generators/init/__snapshots__/init.spec.ts.snap b/packages/vite/src/generators/init/__snapshots__/init.spec.ts.snap index cc1fa567b764f..3820d22ed0171 100644 --- a/packages/vite/src/generators/init/__snapshots__/init.spec.ts.snap +++ b/packages/vite/src/generators/init/__snapshots__/init.spec.ts.snap @@ -8,14 +8,14 @@ exports[`@nx/vite:init dependencies for package.json should add vite packages an "devDependencies": { "@nx/js": "0.0.1", "@nx/vite": "0.0.1", - "@vitejs/plugin-react": "^4.0.0", - "@vitest/ui": "^0.32.0", + "@vitejs/plugin-react": "~4.0.0", + "@vitest/ui": "~0.32.0", "existing": "1.0.0", "prettier": "^2.6.2", "typescript": "~5.1.3", - "vite": "^4.3.9", - "vite-tsconfig-paths": "^4.2.0", - "vitest": "^0.32.0", + "vite": "~4.3.9", + "vite-tsconfig-paths": "~4.2.0", + "vitest": "~0.32.0", }, "name": "test-name", } @@ -28,12 +28,12 @@ exports[`@nx/vite:init dependencies for package.json should support --testEnviro "@edge-runtime/vm": "~3.0.2", "@nx/js": "0.0.1", "@nx/vite": "0.0.1", - "@vitest/ui": "^0.32.0", + "@vitest/ui": "~0.32.0", "prettier": "^2.6.2", "typescript": "~5.1.3", - "vite": "^4.3.9", - "vite-tsconfig-paths": "^4.2.0", - "vitest": "^0.32.0", + "vite": "~4.3.9", + "vite-tsconfig-paths": "~4.2.0", + "vitest": "~0.32.0", }, "name": "test-name", } @@ -45,13 +45,13 @@ exports[`@nx/vite:init dependencies for package.json should support --testEnviro "devDependencies": { "@nx/js": "0.0.1", "@nx/vite": "0.0.1", - "@vitest/ui": "^0.32.0", + "@vitest/ui": "~0.32.0", "happy-dom": "~9.20.3", "prettier": "^2.6.2", "typescript": "~5.1.3", - "vite": "^4.3.9", - "vite-tsconfig-paths": "^4.2.0", - "vitest": "^0.32.0", + "vite": "~4.3.9", + "vite-tsconfig-paths": "~4.2.0", + "vitest": "~0.32.0", }, "name": "test-name", } @@ -63,13 +63,13 @@ exports[`@nx/vite:init dependencies for package.json should support --testEnviro "devDependencies": { "@nx/js": "0.0.1", "@nx/vite": "0.0.1", - "@vitest/ui": "^0.32.0", + "@vitest/ui": "~0.32.0", "jsdom": "~22.1.0", "prettier": "^2.6.2", "typescript": "~5.1.3", - "vite": "^4.3.9", - "vite-tsconfig-paths": "^4.2.0", - "vitest": "^0.32.0", + "vite": "~4.3.9", + "vite-tsconfig-paths": "~4.2.0", + "vitest": "~0.32.0", }, "name": "test-name", } diff --git a/packages/vite/src/utils/versions.ts b/packages/vite/src/utils/versions.ts index e3be36b046dc5..cd3c3210791a3 100644 --- a/packages/vite/src/utils/versions.ts +++ b/packages/vite/src/utils/versions.ts @@ -1,15 +1,15 @@ export const nxVersion = require('../../package.json').version; -export const viteVersion = '^4.3.9'; -export const vitestVersion = '^0.32.0'; -export const vitestUiVersion = '^0.32.0'; -export const vitePluginReactVersion = '^4.0.0'; -export const vitePluginReactSwcVersion = '^3.3.2'; -export const viteTsConfigPathsVersion = '^4.2.0'; +export const viteVersion = '~4.3.9'; +export const vitestVersion = '~0.32.0'; +export const vitestUiVersion = '~0.32.0'; +export const vitePluginReactVersion = '~4.0.0'; +export const vitePluginReactSwcVersion = '~3.3.2'; +export const viteTsConfigPathsVersion = '~4.2.0'; export const jsdomVersion = '~22.1.0'; export const vitePluginDtsVersion = '~2.3.0'; export const happyDomVersion = '~9.20.3'; export const edgeRuntimeVmVersion = '~3.0.2'; // Coverage providers -export const vitestCoverageC8Version = '^0.32.0'; -export const vitestCoverageIstanbulVersion = '^0.32.0'; +export const vitestCoverageC8Version = '~0.32.0'; +export const vitestCoverageIstanbulVersion = '~0.32.0'; From 3edbe49fa2ea0503547ba5bff707a67382fb4d13 Mon Sep 17 00:00:00 2001 From: Katerina Skroumpelou Date: Fri, 7 Jul 2023 11:33:46 +0300 Subject: [PATCH 026/262] fix(storybook): optional chain .length in utils (#18001) --- .../generators/configuration/lib/util-functions.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/storybook/src/generators/configuration/lib/util-functions.ts b/packages/storybook/src/generators/configuration/lib/util-functions.ts index 595578b44860b..0b46fcd9220f8 100644 --- a/packages/storybook/src/generators/configuration/lib/util-functions.ts +++ b/packages/storybook/src/generators/configuration/lib/util-functions.ts @@ -564,7 +564,7 @@ export function getTsConfigPath( const { root, projectType } = readProjectConfiguration(tree, projectName); return join( root, - path && path.length > 0 + path?.length > 0 ? path : projectType === 'application' ? 'tsconfig.app.json' @@ -595,7 +595,7 @@ export function addBuildStorybookToCacheableOperations(tree: Tree) { } export function projectIsRootProjectInStandaloneWorkspace(projectRoot: string) { - return relative(workspaceRoot, projectRoot).length === 0; + return relative(workspaceRoot, projectRoot)?.length === 0; } export function workspaceHasRootProject(tree: Tree) { @@ -682,14 +682,14 @@ export function renameAndMoveOldTsConfig( json.extends = json.extends.replace('../', './'); } - for (let i = 0; i < json.files.length; i++) { + for (let i = 0; i < json.files?.length; i++) { // drop one level of nesting if (json.files[i].startsWith('../../../')) { json.files[i] = json.files[i].replace('../../../', '../../'); } } - for (let i = 0; i < json.include.length; i++) { + for (let i = 0; i < json.include?.length; i++) { if (json.include[i].startsWith('../')) { json.include[i] = json.include[i].replace('../', ''); } @@ -702,7 +702,7 @@ export function renameAndMoveOldTsConfig( } } - for (let i = 0; i < json.exclude.length; i++) { + for (let i = 0; i < json.exclude?.length; i++) { if (json.exclude[i].startsWith('../')) { json.exclude[i] = json.exclude[i].replace('../', 'src/'); } @@ -719,7 +719,7 @@ export function renameAndMoveOldTsConfig( const projectTsConfig = joinPathFragments(projectRoot, 'tsconfig.json'); updateJson(tree, projectTsConfig, (json) => { - for (let i = 0; i < json.references.length; i++) { + for (let i = 0; i < json.references?.length; i++) { if (json.references[i].path === './.storybook/tsconfig.json') { json.references[i].path = './tsconfig.storybook.json'; break; From 21007d8922cbf5f0bd2e469d4a5f617364b9dcb3 Mon Sep 17 00:00:00 2001 From: Katerina Skroumpelou Date: Fri, 7 Jul 2023 11:48:28 +0300 Subject: [PATCH 027/262] fix(storybook): properly identify file as story (#18016) --- .../storybook/src/utils/utilities.spec.ts | 26 +++++++++++++++++++ packages/storybook/src/utils/utilities.ts | 1 + 2 files changed, 27 insertions(+) diff --git a/packages/storybook/src/utils/utilities.spec.ts b/packages/storybook/src/utils/utilities.spec.ts index 3bd6ea908dac8..3a4ca203c55bf 100644 --- a/packages/storybook/src/utils/utilities.spec.ts +++ b/packages/storybook/src/utils/utilities.spec.ts @@ -88,6 +88,24 @@ describe('testing utilities', () => { ` ); + appTree.write( + `test-ui-lib/src/lib/button/button.other.stories.ts`, + ` + import type { Meta } from '@storybook/react'; + import { Button } from './button'; + + const Story: Meta = { + component: Button, + title: 'Layout/Texts/Button', + }; + export default Story; + + export const Primary = { + args: {}, + }; + ` + ); + appTree.write( `test-ui-lib/src/lib/button/button.component.other.ts`, ` @@ -155,6 +173,14 @@ describe('testing utilities', () => { expect(fileIsStory).toBeTruthy(); }); + it('should verify it is story when using Meta', () => { + const fileIsStory = isTheFileAStory( + appTree, + 'test-ui-lib/src/lib/button/button.other.stories.ts' + ); + expect(fileIsStory).toBeTruthy(); + }); + it('should verify it is story for ReactNative', () => { const fileIsStory = isTheFileAStory( appTree, diff --git a/packages/storybook/src/utils/utilities.ts b/packages/storybook/src/utils/utilities.ts index 05f1d0eb2715a..7846997dcf090 100644 --- a/packages/storybook/src/utils/utilities.ts +++ b/packages/storybook/src/utils/utilities.ts @@ -221,6 +221,7 @@ export function isTheFileAStory(tree: Tree, path: string): boolean { importSpecifiers.forEach((importSpecifier: ts.ImportSpecifier) => { if ( importSpecifier.getText() === 'Story' || + importSpecifier.getText() === 'Meta' || importSpecifier.getText() === 'storiesOf' || importSpecifier.getText() === 'ComponentStory' ) { From d0c37727c59a036c95041090f78447f0437ab556 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Jona=C5=A1?= Date: Fri, 7 Jul 2023 15:19:04 +0200 Subject: [PATCH 028/262] fix(core): ensure yarn runs install with correct version (#17997) --- packages/create-nx-workspace/src/create-sandbox.ts | 6 +++++- .../create-nx-workspace/src/utils/package-manager.ts | 4 ++++ packages/devkit/src/utils/package-json.ts | 10 +++++++++- packages/nx/src/utils/package-manager.ts | 4 ++++ 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/packages/create-nx-workspace/src/create-sandbox.ts b/packages/create-nx-workspace/src/create-sandbox.ts index b159d3316d2f4..d6ac8476df3f2 100644 --- a/packages/create-nx-workspace/src/create-sandbox.ts +++ b/packages/create-nx-workspace/src/create-sandbox.ts @@ -23,7 +23,7 @@ export async function createSandbox(packageManager: PackageManager) { `Installing dependencies with ${packageManager}` ).start(); - const { install } = getPackageManagerCommand(packageManager); + const { install, preInstall } = getPackageManagerCommand(packageManager); const tmpDir = dirSync().name; try { @@ -39,6 +39,10 @@ export async function createSandbox(packageManager: PackageManager) { ); generatePackageManagerFiles(tmpDir, packageManager); + if (preInstall) { + await execAndWait(preInstall, tmpDir); + } + await execAndWait(install, tmpDir); installSpinner.succeed(); diff --git a/packages/create-nx-workspace/src/utils/package-manager.ts b/packages/create-nx-workspace/src/utils/package-manager.ts index 13481326b7859..da3c77892d8f2 100644 --- a/packages/create-nx-workspace/src/utils/package-manager.ts +++ b/packages/create-nx-workspace/src/utils/package-manager.ts @@ -36,6 +36,7 @@ export function getPackageManagerCommand( ): { install: string; exec: string; + preInstall?: string; } { const [pmMajor, pmMinor] = getPackageManagerVersion(packageManager).split('.'); @@ -45,6 +46,9 @@ export function getPackageManagerCommand( const useBerry = +pmMajor >= 2; const installCommand = 'yarn install --silent'; return { + preInstall: useBerry + ? 'yarn set version stable' + : 'yarn set version classic', install: useBerry ? installCommand : `${installCommand} --ignore-scripts`, diff --git a/packages/devkit/src/utils/package-json.ts b/packages/devkit/src/utils/package-json.ts index 0d5cce306be35..5ae94e120ea01 100644 --- a/packages/devkit/src/utils/package-json.ts +++ b/packages/devkit/src/utils/package-json.ts @@ -464,12 +464,20 @@ export function ensurePackage( console.log(`Fetching ${pkg}...`); const packageManager = detectPackageManager(); + const isVerbose = process.env.NX_VERBOSE_LOGGING === 'true'; + const preInstallCommand = getPackageManagerCommand(packageManager).preInstall; + if (preInstallCommand) { + // ensure package.json and repo in tmp folder is set to a proper package manager state + execSync(preInstallCommand, { + cwd: tempDir, + stdio: isVerbose ? 'inherit' : 'ignore', + }); + } let addCommand = getPackageManagerCommand(packageManager).addDev; if (packageManager === 'pnpm') { addCommand = 'pnpm add -D'; // we need to ensure that we are not using workspace command } - const isVerbose = process.env.NX_VERBOSE_LOGGING === 'true'; execSync(`${addCommand} ${pkg}@${requiredVersion}`, { cwd: tempDir, stdio: isVerbose ? 'inherit' : 'ignore', diff --git a/packages/nx/src/utils/package-manager.ts b/packages/nx/src/utils/package-manager.ts index 2358673ca3634..713bc57b7b361 100644 --- a/packages/nx/src/utils/package-manager.ts +++ b/packages/nx/src/utils/package-manager.ts @@ -15,6 +15,7 @@ const execAsync = promisify(exec); export type PackageManager = 'yarn' | 'pnpm' | 'npm'; export interface PackageManagerCommands { + preInstall?: string; install: string; ciInstall: string; add: string; @@ -64,6 +65,9 @@ export function getPackageManagerCommand( const useBerry = gte(yarnVersion, '2.0.0'); return { + preInstall: useBerry + ? 'yarn set version stable' + : 'yarn set version classic', install: 'yarn', ciInstall: useBerry ? 'yarn install --immutable' From 9940a0c54467414f0b6365286d4ca5d625ddc1ad Mon Sep 17 00:00:00 2001 From: Jack Hsu Date: Fri, 7 Jul 2023 12:43:29 -0400 Subject: [PATCH 029/262] feat(testing): renamed cypress-e2e-configuration to configuration to maintain consistency between plugins (#17998) --- docs/generated/manifests/menus.json | 12 +-- docs/generated/manifests/packages.json | 20 ++-- docs/generated/packages-metadata.json | 16 ++-- .../generators/component-configuration.json | 47 +++++++++ .../cypress/generators/configuration.json | 95 +++++++++++++++++++ docs/shared/reference/sitemap.md | 4 +- nx-dev/nx-dev/redirect-rules.js | 4 + .../cypress-component-configuration.ts | 2 +- .../docs/cypress-e2e-config-examples.md | 12 +-- packages/cypress/generators.json | 30 +++--- packages/cypress/index.ts | 11 ++- .../component-configuration.spec.ts.snap} | 0 .../component-configuration.spec.ts} | 10 +- .../component-configuration.ts} | 6 +- .../support/component-index.html | 0 .../__directory__/support/component.ts__ext__ | 0 .../schema.d.ts | 0 .../schema.json | 2 +- .../__snapshots__/configuration.spec.ts.snap} | 0 .../configuration.spec.ts} | 2 +- .../configuration.ts} | 6 +- .../v10/__directory__/e2e/app.cy.ts__tmpl__ | 0 .../__directory__/support/app.po.ts__tmpl__ | 0 .../v10/__directory__/support/e2e.ts__tmpl__ | 0 .../fixtures/example.json__tmpl__ | 0 .../integration/app.spec.ts__tmpl__ | 0 .../files/v9/__directory__/plugins/index.js | 0 .../__directory__/support/app.po.ts__tmpl__ | 0 .../__directory__/support/commands.ts__tmpl__ | 0 .../v9/__directory__/support/index.ts__tmpl__ | 0 .../files/v9/__directory__/tsconfig.json | 0 .../files/v9/cypress.json | 0 .../schema.json | 0 .../update-cy-mount-usage.spec.ts | 2 +- .../update-15-1-0/cypress-11.spec.ts | 2 +- .../cypress-component-configuration.ts | 2 +- .../cypress-component-configuration.ts | 2 +- 37 files changed, 222 insertions(+), 65 deletions(-) create mode 100644 docs/generated/packages/cypress/generators/component-configuration.json create mode 100644 docs/generated/packages/cypress/generators/configuration.json rename packages/cypress/src/generators/{cypress-component-configuration/__snapshots__/cypress-component-configuration.spec.ts.snap => component-configuration/__snapshots__/component-configuration.spec.ts.snap} (100%) rename packages/cypress/src/generators/{cypress-component-configuration/cypress-component-configuration.spec.ts => component-configuration/component-configuration.spec.ts} (95%) rename packages/cypress/src/generators/{cypress-component-configuration/cypress-component-configuration.ts => component-configuration/component-configuration.ts} (96%) rename packages/cypress/src/generators/{cypress-component-configuration => component-configuration}/files/__directory__/support/component-index.html (100%) rename packages/cypress/src/generators/{cypress-component-configuration => component-configuration}/files/__directory__/support/component.ts__ext__ (100%) rename packages/cypress/src/generators/{cypress-component-configuration => component-configuration}/schema.d.ts (100%) rename packages/cypress/src/generators/{cypress-component-configuration => component-configuration}/schema.json (92%) rename packages/cypress/src/generators/{cypress-e2e-configuration/__snapshots__/cypress-e2e-configuration.spec.ts.snap => configuration/__snapshots__/configuration.spec.ts.snap} (100%) rename packages/cypress/src/generators/{cypress-e2e-configuration/cypress-e2e-configuration.spec.ts => configuration/configuration.spec.ts} (99%) rename packages/cypress/src/generators/{cypress-e2e-configuration/cypress-e2e-configuration.ts => configuration/configuration.ts} (97%) rename packages/cypress/src/generators/{cypress-e2e-configuration => configuration}/files/v10/__directory__/e2e/app.cy.ts__tmpl__ (100%) rename packages/cypress/src/generators/{cypress-e2e-configuration => configuration}/files/v10/__directory__/support/app.po.ts__tmpl__ (100%) rename packages/cypress/src/generators/{cypress-e2e-configuration => configuration}/files/v10/__directory__/support/e2e.ts__tmpl__ (100%) rename packages/cypress/src/generators/{cypress-e2e-configuration => configuration}/files/v9/__directory__/fixtures/example.json__tmpl__ (100%) rename packages/cypress/src/generators/{cypress-e2e-configuration => configuration}/files/v9/__directory__/integration/app.spec.ts__tmpl__ (100%) rename packages/cypress/src/generators/{cypress-e2e-configuration => configuration}/files/v9/__directory__/plugins/index.js (100%) rename packages/cypress/src/generators/{cypress-e2e-configuration => configuration}/files/v9/__directory__/support/app.po.ts__tmpl__ (100%) rename packages/cypress/src/generators/{cypress-e2e-configuration => configuration}/files/v9/__directory__/support/commands.ts__tmpl__ (100%) rename packages/cypress/src/generators/{cypress-e2e-configuration => configuration}/files/v9/__directory__/support/index.ts__tmpl__ (100%) rename packages/cypress/src/generators/{cypress-e2e-configuration => configuration}/files/v9/__directory__/tsconfig.json (100%) rename packages/cypress/src/generators/{cypress-e2e-configuration => configuration}/files/v9/cypress.json (100%) rename packages/cypress/src/generators/{cypress-e2e-configuration => configuration}/schema.json (100%) diff --git a/docs/generated/manifests/menus.json b/docs/generated/manifests/menus.json index 8f3fb2d28b032..9c7e822ce0cb8 100644 --- a/docs/generated/manifests/menus.json +++ b/docs/generated/manifests/menus.json @@ -4647,17 +4647,17 @@ "disableCollapsible": false }, { - "id": "cypress-e2e-configuration", - "path": "/packages/cypress/generators/cypress-e2e-configuration", - "name": "cypress-e2e-configuration", + "id": "configuration", + "path": "/packages/cypress/generators/configuration", + "name": "configuration", "children": [], "isExternal": false, "disableCollapsible": false }, { - "id": "cypress-component-configuration", - "path": "/packages/cypress/generators/cypress-component-configuration", - "name": "cypress-component-configuration", + "id": "component-configuration", + "path": "/packages/cypress/generators/component-configuration", + "name": "component-configuration", "children": [], "isExternal": false, "disableCollapsible": false diff --git a/docs/generated/manifests/packages.json b/docs/generated/manifests/packages.json index cf9da9f004552..ab397134b52de 100644 --- a/docs/generated/manifests/packages.json +++ b/docs/generated/manifests/packages.json @@ -483,22 +483,22 @@ "path": "/packages/cypress/generators/cypress-project", "type": "generator" }, - "/packages/cypress/generators/cypress-e2e-configuration": { + "/packages/cypress/generators/configuration": { "description": "Add a Cypress E2E Configuration to an existing project.", - "file": "generated/packages/cypress/generators/cypress-e2e-configuration.json", + "file": "generated/packages/cypress/generators/configuration.json", "hidden": false, - "name": "cypress-e2e-configuration", - "originalFilePath": "/packages/cypress/src/generators/cypress-e2e-configuration/schema.json", - "path": "/packages/cypress/generators/cypress-e2e-configuration", + "name": "configuration", + "originalFilePath": "/packages/cypress/src/generators/configuration/schema.json", + "path": "/packages/cypress/generators/configuration", "type": "generator" }, - "/packages/cypress/generators/cypress-component-configuration": { + "/packages/cypress/generators/component-configuration": { "description": "Set up Cypress Component Test for a project", - "file": "generated/packages/cypress/generators/cypress-component-configuration.json", + "file": "generated/packages/cypress/generators/component-configuration.json", "hidden": true, - "name": "cypress-component-configuration", - "originalFilePath": "/packages/cypress/src/generators/cypress-component-configuration/schema.json", - "path": "/packages/cypress/generators/cypress-component-configuration", + "name": "component-configuration", + "originalFilePath": "/packages/cypress/src/generators/component-configuration/schema.json", + "path": "/packages/cypress/generators/component-configuration", "type": "generator" }, "/packages/cypress/generators/migrate-to-cypress-11": { diff --git a/docs/generated/packages-metadata.json b/docs/generated/packages-metadata.json index 6efa02fb1bf79..176350597fcc7 100644 --- a/docs/generated/packages-metadata.json +++ b/docs/generated/packages-metadata.json @@ -477,20 +477,20 @@ }, { "description": "Add a Cypress E2E Configuration to an existing project.", - "file": "generated/packages/cypress/generators/cypress-e2e-configuration.json", + "file": "generated/packages/cypress/generators/configuration.json", "hidden": false, - "name": "cypress-e2e-configuration", - "originalFilePath": "/packages/cypress/src/generators/cypress-e2e-configuration/schema.json", - "path": "cypress/generators/cypress-e2e-configuration", + "name": "configuration", + "originalFilePath": "/packages/cypress/src/generators/configuration/schema.json", + "path": "cypress/generators/configuration", "type": "generator" }, { "description": "Set up Cypress Component Test for a project", - "file": "generated/packages/cypress/generators/cypress-component-configuration.json", + "file": "generated/packages/cypress/generators/component-configuration.json", "hidden": true, - "name": "cypress-component-configuration", - "originalFilePath": "/packages/cypress/src/generators/cypress-component-configuration/schema.json", - "path": "cypress/generators/cypress-component-configuration", + "name": "component-configuration", + "originalFilePath": "/packages/cypress/src/generators/component-configuration/schema.json", + "path": "cypress/generators/component-configuration", "type": "generator" }, { diff --git a/docs/generated/packages/cypress/generators/component-configuration.json b/docs/generated/packages/cypress/generators/component-configuration.json new file mode 100644 index 0000000000000..6fc62deecec01 --- /dev/null +++ b/docs/generated/packages/cypress/generators/component-configuration.json @@ -0,0 +1,47 @@ +{ + "name": "component-configuration", + "aliases": ["cypress-component-configuration"], + "factory": "./src/generators/component-configuration/component-configuration", + "schema": { + "$schema": "http://json-schema.org/schema", + "$id": "NxCypressComponentConfiguration", + "cli": "nx", + "title": "Set up Cypress component testing for a project", + "description": "Set up Cypress component test for a project.", + "type": "object", + "examples": [ + { + "command": "nx g @nx/cypress:component-configuration --project=my-cool-lib ", + "description": "Add cypress component testing to an existing project named my-cool-lib" + } + ], + "properties": { + "project": { + "type": "string", + "description": "The name of the project to add cypress component testing to", + "$default": { "$source": "projectName" }, + "x-prompt": "What project should we add Cypress component testing to?" + }, + "bundler": { + "description": "The Cypress bundler to use.", + "type": "string", + "enum": ["vite", "webpack"], + "x-prompt": "Which Cypress bundler do you want to use for the dev-server?", + "default": "webpack" + }, + "directory": { + "type": "string", + "description": "A directory where the project is placed relative from the project root", + "default": "cypress" + } + }, + "required": ["project"], + "examplesFile": "This is a framework-agnostic generator for adding component testing to a project.\n\n```bash\nnx g cypress-component-configuration --project=my-cool-project\n```\n\nRunning this generator, adds the required files to the specified project without any configurations for Cypress. It's best to use the framework specific generator, instead `cypress-component-configuration` directly\n\n- [React component testing](/packages/react/generators/cypress-component-configuration)\n- [Angular component testing](/packages/angular/generators/cypress-component-configuration)\n\nA new `component-test` target will be added to the specified project.\n\n```bash\nnx g component-test my-cool-project\n```\n\nRead more about [Cypress Component Testing](/cypress/cypress-component-testing)\n", + "presets": [] + }, + "description": "Set up Cypress Component Test for a project", + "hidden": true, + "implementation": "/packages/cypress/src/generators/component-configuration/component-configuration.ts", + "path": "/packages/cypress/src/generators/component-configuration/schema.json", + "type": "generator" +} diff --git a/docs/generated/packages/cypress/generators/configuration.json b/docs/generated/packages/cypress/generators/configuration.json new file mode 100644 index 0000000000000..d9b209b8a9398 --- /dev/null +++ b/docs/generated/packages/cypress/generators/configuration.json @@ -0,0 +1,95 @@ +{ + "name": "configuration", + "aliases": ["cypress-e2e-configuration", "e2e", "e2e-config"], + "factory": "./src/generators/configuration/configuration", + "schema": { + "$schema": "http://json-schema.org/schema", + "$id": "NxCypressE2EConfigGenerator", + "cli": "nx", + "title": "Add a Cypress Configuration.", + "description": "Add a Cypress configuration to an existing project.", + "type": "object", + "properties": { + "project": { + "type": "string", + "description": "The project to add a Cypress configuration to", + "$default": { "$source": "projectName" }, + "x-priority": "important", + "x-prompt": "What project do you want to add Cypress to?" + }, + "devServerTarget": { + "type": "string", + "description": "A devServerTarget,':[:], that will be used to run tests against. This is usually the app this project will be used in. Pass --baseUrl if you wish to not use a devServerTarget.", + "x-priority": "important" + }, + "port": { + "oneOf": [ + { "type": "string", "enum": ["cypress-auto"] }, + { "type": "number" } + ], + "description": "Set the 'port' option on the e2e target. It's recommend to set a different port so you can run tests e2e targets in parallel. Most dev servers support using '0' to automatically find a free port. The value 'cypress-auto' can be used if the underlying dev server does not support automatically finding a free port.", + "x-priority": "important" + }, + "baseUrl": { + "type": "string", + "description": "The address (with the port) which your application is running on. If you wish to start your application when running the e2e target, then use --devServerTarget instead." + }, + "directory": { + "type": "string", + "description": "A directory where the project is placed relative from the project root", + "x-priority": "important", + "default": "cypress" + }, + "linter": { + "description": "The tool to use for running lint checks.", + "type": "string", + "enum": ["eslint", "none"], + "default": "eslint" + }, + "js": { + "description": "Generate JavaScript files rather than TypeScript files.", + "type": "boolean", + "default": false + }, + "skipFormat": { + "description": "Skip formatting files.", + "type": "boolean", + "default": false, + "x-priority": "internal" + }, + "setParserOptionsProject": { + "type": "boolean", + "description": "Whether or not to configure the ESLint `parserOptions.project` option. We do not do this by default for lint performance reasons.", + "default": false + }, + "skipPackageJson": { + "type": "boolean", + "default": false, + "description": "Do not add dependencies to `package.json`.", + "x-priority": "internal" + }, + "rootProject": { + "description": "Create a application at the root of the workspace", + "type": "boolean", + "default": false, + "hidden": true, + "x-priority": "internal" + }, + "bundler": { + "description": "The Cypress bundler to use.", + "type": "string", + "enum": ["vite", "webpack", "none"], + "x-prompt": "Which Cypress bundler do you want to use?", + "default": "webpack" + } + }, + "required": ["project"], + "examplesFile": "This is a generator to add a cypress e2e configuration to an existing project.\n\n```bash\nnx g @nx/cypress:configuration --project=my-cool-project --devServerTarget=some-app:serve\n```\n\nRunning this generator, adds the required files to run cypress tests for a project,\nMainly a `cypress.config.ts` file and default files in the `/cypress/` directory.\nTests will be located in `/cypress/e2e/*` by default.\n\nYou can customize the directory used via the `--directory` flag, the value is relative to the project root.\n\nFor example if you wanted to place the files inside an `e2e` folder\n\n```bash\nnx g @nx/cypress:configuration --project=my-cool-project --devServerTarget=some-app:serve --directory=e2e\n```\n\nProviding a `--devServerTarget` is optional if you provide a `--baseUrl` or the project you're adding the configuration to has a `serve` target already.\nOtherwise, a `--devServerTarget` is recommend for the `@nx/cypress:cypress` executor to spin up the dev server for you automatically when needed.\n\n## Feature Based Testing\n\nThis generator helps in creating feature based e2e/integration testing setups where you can place the feature tests in the same project as the feature library.\nThis differs from creating a separate e2e project that contained all tests for an application which can easily cause more tests to run than is strictly necessary.\n\nTake the following workspace where the `feature-cart` project is affected.\n\n{% graph height=\"450px\" %}\n\n```json\n{\n \"projects\": [\n {\n \"type\": \"app\",\n \"name\": \"fancy-app\",\n \"data\": {\n \"tags\": []\n }\n },\n {\n \"type\": \"app\",\n \"name\": \"fancy-app-e2e\",\n \"data\": {\n \"tags\": []\n }\n },\n {\n \"type\": \"lib\",\n \"name\": \"feature-user\",\n \"data\": {\n \"tags\": []\n }\n },\n {\n \"type\": \"lib\",\n \"name\": \"feature-dashboard\",\n \"data\": {\n \"tags\": []\n }\n },\n {\n \"type\": \"lib\",\n \"name\": \"feature-cart\",\n \"data\": {\n \"tags\": []\n }\n }\n ],\n \"groupByFolder\": false,\n \"workspaceLayout\": {\n \"appsDir\": \"apps\",\n \"libsDir\": \"libs\"\n },\n \"dependencies\": {\n \"fancy-app\": [\n {\n \"target\": \"feature-user\",\n \"source\": \"fancy-app\",\n \"type\": \"static\"\n },\n {\n \"target\": \"feature-cart\",\n \"source\": \"fancy-app\",\n \"type\": \"static\"\n }\n ],\n \"fancy-app-e2e\": [\n {\n \"target\": \"fancy-app\",\n \"source\": \"fancy-app-e2e\",\n \"type\": \"implicit\"\n }\n ],\n \"feature-user\": [\n {\n \"target\": \"feature-dashboard\",\n \"source\": \"feature-user\",\n \"type\": \"direct\"\n }\n ],\n \"feature-cart\": [],\n \"feature-dashboard\": []\n },\n \"affectedProjectIds\": [\"feature-cart\", \"fancy-app\", \"fancy-app-e2e\"]\n}\n```\n\n{% /graph %}\n\nIn this case, if tests for the all the `feature-*` projects where contained in the `fancy-app-e2e` project, then all of those features will be tested in the app, when only the `feature-cart` tests need to run.\n\nRunning these e2e/integration tests more often than they should results in longer CI times.\n\nBrining those e2e test closer to each feature can result is lowering CI times since we don't need to test those features if they did not change.\n\nBuilding this way leaves the `fancy-app-e2e` for mostly smoke type testing instead of more in-depth feature testing.\n\nUsing the `@nx/cypress:configuration` generator can help you accomplish this in your workspace.\n\n```bash\nnx g @nx/cypress:configuration --project=feature-cart --devServerTarget=fancy-app:serve\nnx g @nx/cypress:configuration --project=feature-user --devServerTarget=fancy-app:serve\nnx g @nx/cypress:configuration --project=feature-dashboard --devServerTarget=fancy-app:serve\n```\n\nEach project will now get their own `e2e` target, where the feature project is only concerned with itself. This allows for more focused tests without worrying about forcing unrelated tests to also run.\n\nIt's important to remember that these feature tests are still going to be leveraging the same app to run the tests against so if you plan to run in parallel, you can leverage using a file server and the ability for `@nx/cypress:cypress` executor to pass through a port or find a free port to allow running tests in parallel. Read more [about the --port flag](/packages/cypress/executors/cypress#port)\n", + "presets": [] + }, + "description": "Add a Cypress E2E Configuration to an existing project.", + "implementation": "/packages/cypress/src/generators/configuration/configuration.ts", + "hidden": false, + "path": "/packages/cypress/src/generators/configuration/schema.json", + "type": "generator" +} diff --git a/docs/shared/reference/sitemap.md b/docs/shared/reference/sitemap.md index d1a8b24fcdd01..bcf99cf1a0a1d 100644 --- a/docs/shared/reference/sitemap.md +++ b/docs/shared/reference/sitemap.md @@ -330,8 +330,8 @@ - [generators](/packages/cypress/generators) - [init](/packages/cypress/generators/init) - [cypress-project](/packages/cypress/generators/cypress-project) - - [cypress-e2e-configuration](/packages/cypress/generators/cypress-e2e-configuration) - - [cypress-component-configuration](/packages/cypress/generators/cypress-component-configuration) + - [configuration](/packages/cypress/generators/configuration) + - [component-configuration](/packages/cypress/generators/component-configuration) - [migrate-to-cypress-11](/packages/cypress/generators/migrate-to-cypress-11) - [detox](/packages/detox) - [documents](/packages/detox/documents) diff --git a/nx-dev/nx-dev/redirect-rules.js b/nx-dev/nx-dev/redirect-rules.js index 5f52ad21c4e6a..f3c66b863c569 100644 --- a/nx-dev/nx-dev/redirect-rules.js +++ b/nx-dev/nx-dev/redirect-rules.js @@ -144,6 +144,10 @@ const schemaUrls = { '/react-native/start': '/packages/react-native/executors/start', '/react-native/storybook': '/packages/react-native/executors/storybook', '/react-native/sync-deps': '/packages/react-native/executors/sync-deps', + '/packages/cypress/generators/cypress-e2e-configuration': + '/packages/cypress/generators/configuration', + '/packages/cypress/generators/cypress-component-configuration': + '/packages/cypress/generators/component-configuration', '/packages/nx-plugin/generators/executor': '/packages/plugin/generators/executor', '/packages/nx-plugin/generators/migration': diff --git a/packages/angular/src/generators/cypress-component-configuration/cypress-component-configuration.ts b/packages/angular/src/generators/cypress-component-configuration/cypress-component-configuration.ts index cf1afd3bf9d41..7a38051ffa144 100644 --- a/packages/angular/src/generators/cypress-component-configuration/cypress-component-configuration.ts +++ b/packages/angular/src/generators/cypress-component-configuration/cypress-component-configuration.ts @@ -1,4 +1,4 @@ -import { cypressComponentConfiguration as baseCyCTConfig } from '@nx/cypress'; +import { componentConfigurationGenerator as baseCyCTConfig } from '@nx/cypress'; import { addDefaultCTConfig, addMountDefinition, diff --git a/packages/cypress/docs/cypress-e2e-config-examples.md b/packages/cypress/docs/cypress-e2e-config-examples.md index 4472ebaf40512..60c535aabf4ba 100644 --- a/packages/cypress/docs/cypress-e2e-config-examples.md +++ b/packages/cypress/docs/cypress-e2e-config-examples.md @@ -1,7 +1,7 @@ This is a generator to add a cypress e2e configuration to an existing project. ```bash -nx g cypress-e2e-configuration --project=my-cool-project --devServerTarget=some-app:serve +nx g @nx/cypress:configuration --project=my-cool-project --devServerTarget=some-app:serve ``` Running this generator, adds the required files to run cypress tests for a project, @@ -13,7 +13,7 @@ You can customize the directory used via the `--directory` flag, the value is re For example if you wanted to place the files inside an `e2e` folder ```bash -nx g cypress-e2e-configuration --project=my-cool-project --devServerTarget=some-app:serve --directory=e2e +nx g @nx/cypress:configuration --project=my-cool-project --devServerTarget=some-app:serve --directory=e2e ``` Providing a `--devServerTarget` is optional if you provide a `--baseUrl` or the project you're adding the configuration to has a `serve` target already. @@ -116,12 +116,12 @@ Brining those e2e test closer to each feature can result is lowering CI times si Building this way leaves the `fancy-app-e2e` for mostly smoke type testing instead of more in-depth feature testing. -Using the `cypress-e2e-configuration` generator can help you accomplish this in your workspace. +Using the `@nx/cypress:configuration` generator can help you accomplish this in your workspace. ```bash -nx g cypress-e2e-configuration --project=feature-cart --devServerTarget=fancy-app:serve -nx g cypress-e2e-configuration --project=feature-user --devServerTarget=fancy-app:serve -nx g cypress-e2e-configuration --project=feature-dashboard --devServerTarget=fancy-app:serve +nx g @nx/cypress:configuration --project=feature-cart --devServerTarget=fancy-app:serve +nx g @nx/cypress:configuration --project=feature-user --devServerTarget=fancy-app:serve +nx g @nx/cypress:configuration --project=feature-dashboard --devServerTarget=fancy-app:serve ``` Each project will now get their own `e2e` target, where the feature project is only concerned with itself. This allows for more focused tests without worrying about forcing unrelated tests to also run. diff --git a/packages/cypress/generators.json b/packages/cypress/generators.json index a4763971eeb3d..873814a0e79f7 100644 --- a/packages/cypress/generators.json +++ b/packages/cypress/generators.json @@ -14,15 +14,16 @@ "schema": "./src/generators/cypress-project/schema.json", "description": "Add a Cypress E2E Project." }, - "cypress-e2e-configuration": { - "aliases": ["e2e", "e2e-config"], - "factory": "./src/generators/cypress-e2e-configuration/cypress-e2e-configuration#compat", - "schema": "./src/generators/cypress-e2e-configuration/schema.json", + "configuration": { + "aliases": ["cypress-e2e-configuration", "e2e", "e2e-config"], + "factory": "./src/generators/configuration/configuration#compat", + "schema": "./src/generators/configuration/schema.json", "description": "Add a Cypress E2E Configuration to an existing project." }, - "cypress-component-configuration": { - "factory": "./src/generators/cypress-component-configuration/cypress-component-configuration#cypressComponentConfiguration", - "schema": "./src/generators/cypress-component-configuration/schema.json", + "component-configuration": { + "aliases": ["cypress-component-configuration"], + "factory": "./src/generators/component-configuration/component-configuration#compat", + "schema": "./src/generators/component-configuration/schema.json", "description": "Set up Cypress Component Test for a project" }, "migrate-to-cypress-11": { @@ -45,15 +46,16 @@ "description": "Add a Cypress E2E Project.", "hidden": true }, - "cypress-e2e-configuration": { - "aliases": ["e2e", "e2e-config"], - "factory": "./src/generators/cypress-e2e-configuration/cypress-e2e-configuration", - "schema": "./src/generators/cypress-e2e-configuration/schema.json", + "configuration": { + "aliases": ["cypress-e2e-configuration", "e2e", "e2e-config"], + "factory": "./src/generators/configuration/configuration", + "schema": "./src/generators/configuration/schema.json", "description": "Add a Cypress E2E Configuration to an existing project." }, - "cypress-component-configuration": { - "factory": "./src/generators/cypress-component-configuration/cypress-component-configuration#cypressComponentConfiguration", - "schema": "./src/generators/cypress-component-configuration/schema.json", + "component-configuration": { + "aliases": ["cypress-component-configuration"], + "factory": "./src/generators/component-configuration/component-configuration", + "schema": "./src/generators/component-configuration/schema.json", "description": "Set up Cypress Component Test for a project", "hidden": true }, diff --git a/packages/cypress/index.ts b/packages/cypress/index.ts index bab858ef04a73..5b62a7fb29870 100644 --- a/packages/cypress/index.ts +++ b/packages/cypress/index.ts @@ -1,6 +1,13 @@ +import { configurationGenerator } from './src/generators/configuration/configuration'; +import { componentConfigurationGenerator } from './src/generators/component-configuration/component-configuration'; +export { configurationGenerator, componentConfigurationGenerator }; + +// Maintain backwards compatibility with the old names in case community plugins used them. +/** @deprecated Use `configurationGenerator` instead. */ +export const cypressComponentConfiguration = componentConfigurationGenerator; + +export { configurationGenerator as cypressE2EConfigurationGenerator }; export { cypressProjectGenerator } from './src/generators/cypress-project/cypress-project'; export { cypressInitGenerator } from './src/generators/init/init'; export { conversionGenerator } from './src/generators/convert-tslint-to-eslint/convert-tslint-to-eslint'; -export { cypressComponentConfiguration } from './src/generators/cypress-component-configuration/cypress-component-configuration'; export { migrateCypressProject } from './src/generators/migrate-to-cypress-11/migrate-to-cypress-11'; -export { cypressE2EConfigurationGenerator } from './src/generators/cypress-e2e-configuration/cypress-e2e-configuration'; diff --git a/packages/cypress/src/generators/cypress-component-configuration/__snapshots__/cypress-component-configuration.spec.ts.snap b/packages/cypress/src/generators/component-configuration/__snapshots__/component-configuration.spec.ts.snap similarity index 100% rename from packages/cypress/src/generators/cypress-component-configuration/__snapshots__/cypress-component-configuration.spec.ts.snap rename to packages/cypress/src/generators/component-configuration/__snapshots__/component-configuration.spec.ts.snap diff --git a/packages/cypress/src/generators/cypress-component-configuration/cypress-component-configuration.spec.ts b/packages/cypress/src/generators/component-configuration/component-configuration.spec.ts similarity index 95% rename from packages/cypress/src/generators/cypress-component-configuration/cypress-component-configuration.spec.ts rename to packages/cypress/src/generators/component-configuration/component-configuration.spec.ts index 22e47c4525612..83d91822038f2 100644 --- a/packages/cypress/src/generators/cypress-component-configuration/cypress-component-configuration.spec.ts +++ b/packages/cypress/src/generators/component-configuration/component-configuration.spec.ts @@ -9,7 +9,7 @@ import { } from '@nx/devkit'; import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; import { installedCypressVersion } from '../../utils/cypress-version'; -import { cypressComponentConfiguration } from './cypress-component-configuration'; +import { componentConfigurationGenerator } from './component-configuration'; jest.mock('../../utils/cypress-version'); let projectConfig: ProjectConfiguration = { @@ -97,7 +97,7 @@ describe('Cypress Component Configuration', () => { it('should add base cypress component testing config', async () => { mockedInstalledCypressVersion.mockReturnValue(10); - await cypressComponentConfiguration(tree, { + await componentConfigurationGenerator(tree, { project: 'cool-lib', skipFormat: false, }); @@ -157,7 +157,7 @@ describe('Cypress Component Configuration', () => { }; return json; }); - await cypressComponentConfiguration(tree, { + await componentConfigurationGenerator(tree, { project: 'cool-lib', skipFormat: false, }); @@ -202,7 +202,7 @@ export default defineConfig({ }, }); - await cypressComponentConfiguration(tree, { + await componentConfigurationGenerator(tree, { project: 'cool-lib', skipFormat: true, }); @@ -219,7 +219,7 @@ export default defineConfig({ mockedInstalledCypressVersion.mockReturnValue(9); await expect( async () => - await cypressComponentConfiguration(tree, { + await componentConfigurationGenerator(tree, { project: 'cool-lib', skipFormat: true, }) diff --git a/packages/cypress/src/generators/cypress-component-configuration/cypress-component-configuration.ts b/packages/cypress/src/generators/component-configuration/component-configuration.ts similarity index 96% rename from packages/cypress/src/generators/cypress-component-configuration/cypress-component-configuration.ts rename to packages/cypress/src/generators/component-configuration/component-configuration.ts index 67e4979d9ba4d..e05e14d9897da 100644 --- a/packages/cypress/src/generators/cypress-component-configuration/cypress-component-configuration.ts +++ b/packages/cypress/src/generators/component-configuration/component-configuration.ts @@ -11,6 +11,7 @@ import { updateJson, updateProjectConfiguration, updateNxJson, + convertNxGenerator, } from '@nx/devkit'; import { installedCypressVersion } from '../../utils/cypress-version'; @@ -25,7 +26,7 @@ import { addBaseCypressSetup } from '../base-setup/base-setup'; type NormalizeCTOptions = ReturnType; -export async function cypressComponentConfiguration( +export async function componentConfigurationGenerator( tree: Tree, options: CypressComponentConfigurationSchema ) { @@ -216,4 +217,5 @@ export function updateTsConfigForComponentTesting( } } -export default cypressComponentConfiguration; +export default componentConfigurationGenerator; +export const compat = convertNxGenerator(componentConfigurationGenerator); diff --git a/packages/cypress/src/generators/cypress-component-configuration/files/__directory__/support/component-index.html b/packages/cypress/src/generators/component-configuration/files/__directory__/support/component-index.html similarity index 100% rename from packages/cypress/src/generators/cypress-component-configuration/files/__directory__/support/component-index.html rename to packages/cypress/src/generators/component-configuration/files/__directory__/support/component-index.html diff --git a/packages/cypress/src/generators/cypress-component-configuration/files/__directory__/support/component.ts__ext__ b/packages/cypress/src/generators/component-configuration/files/__directory__/support/component.ts__ext__ similarity index 100% rename from packages/cypress/src/generators/cypress-component-configuration/files/__directory__/support/component.ts__ext__ rename to packages/cypress/src/generators/component-configuration/files/__directory__/support/component.ts__ext__ diff --git a/packages/cypress/src/generators/cypress-component-configuration/schema.d.ts b/packages/cypress/src/generators/component-configuration/schema.d.ts similarity index 100% rename from packages/cypress/src/generators/cypress-component-configuration/schema.d.ts rename to packages/cypress/src/generators/component-configuration/schema.d.ts diff --git a/packages/cypress/src/generators/cypress-component-configuration/schema.json b/packages/cypress/src/generators/component-configuration/schema.json similarity index 92% rename from packages/cypress/src/generators/cypress-component-configuration/schema.json rename to packages/cypress/src/generators/component-configuration/schema.json index b59a72ed17578..a34fbc9d8cbd0 100644 --- a/packages/cypress/src/generators/cypress-component-configuration/schema.json +++ b/packages/cypress/src/generators/component-configuration/schema.json @@ -7,7 +7,7 @@ "type": "object", "examples": [ { - "command": "nx g @nx/cypress:cypress-component-configuration --project=my-cool-lib ", + "command": "nx g @nx/cypress:component-configuration --project=my-cool-lib ", "description": "Add cypress component testing to an existing project named my-cool-lib" } ], diff --git a/packages/cypress/src/generators/cypress-e2e-configuration/__snapshots__/cypress-e2e-configuration.spec.ts.snap b/packages/cypress/src/generators/configuration/__snapshots__/configuration.spec.ts.snap similarity index 100% rename from packages/cypress/src/generators/cypress-e2e-configuration/__snapshots__/cypress-e2e-configuration.spec.ts.snap rename to packages/cypress/src/generators/configuration/__snapshots__/configuration.spec.ts.snap diff --git a/packages/cypress/src/generators/cypress-e2e-configuration/cypress-e2e-configuration.spec.ts b/packages/cypress/src/generators/configuration/configuration.spec.ts similarity index 99% rename from packages/cypress/src/generators/cypress-e2e-configuration/cypress-e2e-configuration.spec.ts rename to packages/cypress/src/generators/configuration/configuration.spec.ts index 0bc0554a6b8bb..db32cf1cba186 100644 --- a/packages/cypress/src/generators/cypress-e2e-configuration/cypress-e2e-configuration.spec.ts +++ b/packages/cypress/src/generators/configuration/configuration.spec.ts @@ -7,7 +7,7 @@ import { updateProjectConfiguration, } from '@nx/devkit'; import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; -import { cypressE2EConfigurationGenerator } from './cypress-e2e-configuration'; +import cypressE2EConfigurationGenerator from './configuration'; import { installedCypressVersion } from '../../utils/cypress-version'; diff --git a/packages/cypress/src/generators/cypress-e2e-configuration/cypress-e2e-configuration.ts b/packages/cypress/src/generators/configuration/configuration.ts similarity index 97% rename from packages/cypress/src/generators/cypress-e2e-configuration/cypress-e2e-configuration.ts rename to packages/cypress/src/generators/configuration/configuration.ts index a20defaebea5d..a4aa0f33bfbe0 100644 --- a/packages/cypress/src/generators/cypress-e2e-configuration/cypress-e2e-configuration.ts +++ b/packages/cypress/src/generators/configuration/configuration.ts @@ -39,7 +39,7 @@ export interface CypressE2EConfigSchema { } type NormalizedSchema = ReturnType; -export async function cypressE2EConfigurationGenerator( +export async function configurationGenerator( tree: Tree, options: CypressE2EConfigSchema ) { @@ -220,5 +220,5 @@ function addTarget(tree: Tree, opts: NormalizedSchema) { updateProjectConfiguration(tree, opts.project, projectConfig); } -export default cypressE2EConfigurationGenerator; -export const compat = convertNxGenerator(cypressE2EConfigurationGenerator); +export default configurationGenerator; +export const compat = convertNxGenerator(configurationGenerator); diff --git a/packages/cypress/src/generators/cypress-e2e-configuration/files/v10/__directory__/e2e/app.cy.ts__tmpl__ b/packages/cypress/src/generators/configuration/files/v10/__directory__/e2e/app.cy.ts__tmpl__ similarity index 100% rename from packages/cypress/src/generators/cypress-e2e-configuration/files/v10/__directory__/e2e/app.cy.ts__tmpl__ rename to packages/cypress/src/generators/configuration/files/v10/__directory__/e2e/app.cy.ts__tmpl__ diff --git a/packages/cypress/src/generators/cypress-e2e-configuration/files/v10/__directory__/support/app.po.ts__tmpl__ b/packages/cypress/src/generators/configuration/files/v10/__directory__/support/app.po.ts__tmpl__ similarity index 100% rename from packages/cypress/src/generators/cypress-e2e-configuration/files/v10/__directory__/support/app.po.ts__tmpl__ rename to packages/cypress/src/generators/configuration/files/v10/__directory__/support/app.po.ts__tmpl__ diff --git a/packages/cypress/src/generators/cypress-e2e-configuration/files/v10/__directory__/support/e2e.ts__tmpl__ b/packages/cypress/src/generators/configuration/files/v10/__directory__/support/e2e.ts__tmpl__ similarity index 100% rename from packages/cypress/src/generators/cypress-e2e-configuration/files/v10/__directory__/support/e2e.ts__tmpl__ rename to packages/cypress/src/generators/configuration/files/v10/__directory__/support/e2e.ts__tmpl__ diff --git a/packages/cypress/src/generators/cypress-e2e-configuration/files/v9/__directory__/fixtures/example.json__tmpl__ b/packages/cypress/src/generators/configuration/files/v9/__directory__/fixtures/example.json__tmpl__ similarity index 100% rename from packages/cypress/src/generators/cypress-e2e-configuration/files/v9/__directory__/fixtures/example.json__tmpl__ rename to packages/cypress/src/generators/configuration/files/v9/__directory__/fixtures/example.json__tmpl__ diff --git a/packages/cypress/src/generators/cypress-e2e-configuration/files/v9/__directory__/integration/app.spec.ts__tmpl__ b/packages/cypress/src/generators/configuration/files/v9/__directory__/integration/app.spec.ts__tmpl__ similarity index 100% rename from packages/cypress/src/generators/cypress-e2e-configuration/files/v9/__directory__/integration/app.spec.ts__tmpl__ rename to packages/cypress/src/generators/configuration/files/v9/__directory__/integration/app.spec.ts__tmpl__ diff --git a/packages/cypress/src/generators/cypress-e2e-configuration/files/v9/__directory__/plugins/index.js b/packages/cypress/src/generators/configuration/files/v9/__directory__/plugins/index.js similarity index 100% rename from packages/cypress/src/generators/cypress-e2e-configuration/files/v9/__directory__/plugins/index.js rename to packages/cypress/src/generators/configuration/files/v9/__directory__/plugins/index.js diff --git a/packages/cypress/src/generators/cypress-e2e-configuration/files/v9/__directory__/support/app.po.ts__tmpl__ b/packages/cypress/src/generators/configuration/files/v9/__directory__/support/app.po.ts__tmpl__ similarity index 100% rename from packages/cypress/src/generators/cypress-e2e-configuration/files/v9/__directory__/support/app.po.ts__tmpl__ rename to packages/cypress/src/generators/configuration/files/v9/__directory__/support/app.po.ts__tmpl__ diff --git a/packages/cypress/src/generators/cypress-e2e-configuration/files/v9/__directory__/support/commands.ts__tmpl__ b/packages/cypress/src/generators/configuration/files/v9/__directory__/support/commands.ts__tmpl__ similarity index 100% rename from packages/cypress/src/generators/cypress-e2e-configuration/files/v9/__directory__/support/commands.ts__tmpl__ rename to packages/cypress/src/generators/configuration/files/v9/__directory__/support/commands.ts__tmpl__ diff --git a/packages/cypress/src/generators/cypress-e2e-configuration/files/v9/__directory__/support/index.ts__tmpl__ b/packages/cypress/src/generators/configuration/files/v9/__directory__/support/index.ts__tmpl__ similarity index 100% rename from packages/cypress/src/generators/cypress-e2e-configuration/files/v9/__directory__/support/index.ts__tmpl__ rename to packages/cypress/src/generators/configuration/files/v9/__directory__/support/index.ts__tmpl__ diff --git a/packages/cypress/src/generators/cypress-e2e-configuration/files/v9/__directory__/tsconfig.json b/packages/cypress/src/generators/configuration/files/v9/__directory__/tsconfig.json similarity index 100% rename from packages/cypress/src/generators/cypress-e2e-configuration/files/v9/__directory__/tsconfig.json rename to packages/cypress/src/generators/configuration/files/v9/__directory__/tsconfig.json diff --git a/packages/cypress/src/generators/cypress-e2e-configuration/files/v9/cypress.json b/packages/cypress/src/generators/configuration/files/v9/cypress.json similarity index 100% rename from packages/cypress/src/generators/cypress-e2e-configuration/files/v9/cypress.json rename to packages/cypress/src/generators/configuration/files/v9/cypress.json diff --git a/packages/cypress/src/generators/cypress-e2e-configuration/schema.json b/packages/cypress/src/generators/configuration/schema.json similarity index 100% rename from packages/cypress/src/generators/cypress-e2e-configuration/schema.json rename to packages/cypress/src/generators/configuration/schema.json diff --git a/packages/cypress/src/migrations/update-15-0-0/update-cy-mount-usage.spec.ts b/packages/cypress/src/migrations/update-15-0-0/update-cy-mount-usage.spec.ts index 4da3c27a3654f..6c98abd0266d0 100644 --- a/packages/cypress/src/migrations/update-15-0-0/update-cy-mount-usage.spec.ts +++ b/packages/cypress/src/migrations/update-15-0-0/update-cy-mount-usage.spec.ts @@ -11,7 +11,7 @@ import { updateCyMountUsage, } from './update-cy-mount-usage'; import { libraryGenerator } from '@nx/js'; -import { cypressComponentConfiguration } from '../../generators/cypress-component-configuration/cypress-component-configuration'; +import cypressComponentConfiguration from '../../generators/component-configuration/component-configuration'; jest.mock('../../utils/cypress-version'); // nested code imports graph from the repo, which might have innacurate graph version diff --git a/packages/cypress/src/migrations/update-15-1-0/cypress-11.spec.ts b/packages/cypress/src/migrations/update-15-1-0/cypress-11.spec.ts index 8b3f953b39e15..02980e019e526 100644 --- a/packages/cypress/src/migrations/update-15-1-0/cypress-11.spec.ts +++ b/packages/cypress/src/migrations/update-15-1-0/cypress-11.spec.ts @@ -9,7 +9,7 @@ import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; import updateToCypress11 from './cypress-11'; import { installedCypressVersion } from '../../utils/cypress-version'; jest.mock('../../utils/cypress-version'); -import { cypressComponentConfiguration } from '../../generators/cypress-component-configuration/cypress-component-configuration'; +import cypressComponentConfiguration from '../../generators/component-configuration/component-configuration'; describe('Cypress 11 Migration', () => { let tree: Tree; diff --git a/packages/next/src/generators/cypress-component-configuration/cypress-component-configuration.ts b/packages/next/src/generators/cypress-component-configuration/cypress-component-configuration.ts index a018c34d63b2c..eb6e972ded842 100644 --- a/packages/next/src/generators/cypress-component-configuration/cypress-component-configuration.ts +++ b/packages/next/src/generators/cypress-component-configuration/cypress-component-configuration.ts @@ -22,7 +22,7 @@ export async function cypressComponentConfiguration( ) { const tasks: GeneratorCallback[] = []; - const { cypressComponentConfiguration: baseCyCtConfig } = ensurePackage< + const { componentConfigurationGenerator: baseCyCtConfig } = ensurePackage< typeof import('@nx/cypress') >('@nx/cypress', nxVersion); tasks.push( diff --git a/packages/react/src/generators/cypress-component-configuration/cypress-component-configuration.ts b/packages/react/src/generators/cypress-component-configuration/cypress-component-configuration.ts index dd2b75a552a79..761ca09d80d13 100644 --- a/packages/react/src/generators/cypress-component-configuration/cypress-component-configuration.ts +++ b/packages/react/src/generators/cypress-component-configuration/cypress-component-configuration.ts @@ -18,7 +18,7 @@ export async function cypressComponentConfigGenerator( tree: Tree, options: CypressComponentConfigurationSchema ) { - const { cypressComponentConfiguration: baseCyCtConfig } = ensurePackage< + const { componentConfigurationGenerator: baseCyCtConfig } = ensurePackage< typeof import('@nx/cypress') >('@nx/cypress', nxVersion); const projectConfig = readProjectConfiguration(tree, options.project); From 8d5cfcc2b3d35bfdf7c4c610edd14c991ba55e45 Mon Sep 17 00:00:00 2001 From: Emily Xiong Date: Fri, 7 Jul 2023 13:44:25 -0400 Subject: [PATCH 030/262] fix(js): restore registry for only localhost (#17999) --- .../src/executors/verdaccio/verdaccio.impl.ts | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/packages/js/src/executors/verdaccio/verdaccio.impl.ts b/packages/js/src/executors/verdaccio/verdaccio.impl.ts index e1badd1decc50..69e835e571c7a 100644 --- a/packages/js/src/executors/verdaccio/verdaccio.impl.ts +++ b/packages/js/src/executors/verdaccio/verdaccio.impl.ts @@ -131,7 +131,7 @@ function setupNpm(options: VerdaccioExecutorSchema) { return () => {}; } - let npmRegistryPath; + let npmRegistryPath: string; try { npmRegistryPath = execSync( `npm config get registry --location ${options.location}` @@ -154,7 +154,13 @@ function setupNpm(options: VerdaccioExecutorSchema) { return () => { try { - if (npmRegistryPath) { + const currentNpmRegistryPath = execSync( + `npm config get registry --location ${options.location}` + ) + ?.toString() + ?.trim() + ?.replace('\u001b[2K\u001b[1G', ''); // strip out ansi codes + if (npmRegistryPath && currentNpmRegistryPath.includes('localhost')) { execSync( `npm config set registry ${npmRegistryPath} --location ${options.location}` ); @@ -240,7 +246,13 @@ function setupYarn(options: VerdaccioExecutorSchema) { return () => { try { - if (yarnRegistryPath) { + const currentYarnRegistryPath = execSync( + `yarn config get ${registryConfigName}` + ) + ?.toString() + ?.trim() + ?.replace('\u001b[2K\u001b[1G', ''); // strip out ansi codes + if (yarnRegistryPath && currentYarnRegistryPath.includes('localhost')) { execSync( `yarn config set ${registryConfigName} ${yarnRegistryPath}` + (options.location === 'user' ? ' --home' : '') From 24e45d494f50c6a883a389216ed663b9fb1e2523 Mon Sep 17 00:00:00 2001 From: Jack Hsu Date: Fri, 7 Jul 2023 13:59:41 -0400 Subject: [PATCH 031/262] feat(bundling): rename esbuild-project, rollup-project, and webpack-project generators to "configuration" generators for consistency in naming (#18003) --- docs/generated/manifests/menus.json | 18 ++-- docs/generated/manifests/packages.json | 30 +++---- docs/generated/packages-metadata.json | 24 +++--- .../packages/esbuild/documents/overview.md | 4 +- .../packages/esbuild/executors/esbuild.json | 2 +- .../esbuild/generators/configuration.json | 75 ++++++++++++++++ .../rollup/generators/configuration.json | 83 ++++++++++++++++++ .../webpack/generators/configuration.json | 85 +++++++++++++++++++ .../shared/packages/esbuild/esbuild-plugin.md | 4 +- docs/shared/reference/sitemap.md | 6 +- e2e/rollup/src/rollup.test.ts | 6 +- e2e/webpack/src/webpack.test.ts | 8 +- nx-dev/nx-dev/redirect-rules.js | 6 ++ ...-examples.md => configuration-examples.md} | 6 +- packages/esbuild/docs/esbuild-examples.md | 2 +- packages/esbuild/generators.json | 14 +-- packages/esbuild/index.ts | 8 +- .../configuration.spec.ts} | 8 +- .../configuration.ts} | 8 +- .../schema.d.ts | 0 .../schema.json | 2 +- .../src/generators/setup-build/generator.ts | 8 +- packages/rollup/generators.json | 14 +-- packages/rollup/index.ts | 8 +- .../configuration.spec.ts} | 12 +-- .../configuration.ts} | 8 +- .../schema.d.ts | 0 .../schema.json | 0 .../src/generators/application/application.ts | 7 +- packages/webpack/generators.json | 14 +-- packages/webpack/index.ts | 8 +- .../configuration.spec.ts} | 10 +-- .../configuration.ts} | 18 ++-- .../schema.d.ts | 2 +- .../schema.json | 0 35 files changed, 388 insertions(+), 120 deletions(-) create mode 100644 docs/generated/packages/esbuild/generators/configuration.json create mode 100644 docs/generated/packages/rollup/generators/configuration.json create mode 100644 docs/generated/packages/webpack/generators/configuration.json rename packages/esbuild/docs/{esbuild-project-examples.md => configuration-examples.md} (60%) rename packages/esbuild/src/generators/{esbuild-project/esbuild-project.spec.ts => configuration/configuration.spec.ts} (89%) rename packages/esbuild/src/generators/{esbuild-project/esbuild-project.ts => configuration/configuration.ts} (95%) rename packages/esbuild/src/generators/{esbuild-project => configuration}/schema.d.ts (100%) rename packages/esbuild/src/generators/{esbuild-project => configuration}/schema.json (97%) rename packages/rollup/src/generators/{rollup-project/rollup-project.spec.ts => configuration/configuration.spec.ts} (89%) rename packages/rollup/src/generators/{rollup-project/rollup-project.ts => configuration/configuration.ts} (94%) rename packages/rollup/src/generators/{rollup-project => configuration}/schema.d.ts (100%) rename packages/rollup/src/generators/{rollup-project => configuration}/schema.json (100%) rename packages/webpack/src/generators/{webpack-project/webpack-project.spec.ts => configuration/configuration.spec.ts} (91%) rename packages/webpack/src/generators/{webpack-project/webpack-project.ts => configuration/configuration.ts} (89%) rename packages/webpack/src/generators/{webpack-project => configuration}/schema.d.ts (85%) rename packages/webpack/src/generators/{webpack-project => configuration}/schema.json (100%) diff --git a/docs/generated/manifests/menus.json b/docs/generated/manifests/menus.json index 9c7e822ce0cb8..f2c0767a352c9 100644 --- a/docs/generated/manifests/menus.json +++ b/docs/generated/manifests/menus.json @@ -4841,9 +4841,9 @@ "disableCollapsible": false }, { - "id": "esbuild-project", - "path": "/packages/esbuild/generators/esbuild-project", - "name": "esbuild-project", + "id": "configuration", + "path": "/packages/esbuild/generators/configuration", + "name": "configuration", "children": [], "isExternal": false, "disableCollapsible": false @@ -6530,9 +6530,9 @@ "disableCollapsible": false }, { - "id": "rollup-project", - "path": "/packages/rollup/generators/rollup-project", - "name": "rollup-project", + "id": "configuration", + "path": "/packages/rollup/generators/configuration", + "name": "configuration", "children": [], "isExternal": false, "disableCollapsible": false @@ -6986,9 +6986,9 @@ "disableCollapsible": false }, { - "id": "webpack-project", - "path": "/packages/webpack/generators/webpack-project", - "name": "webpack-project", + "id": "configuration", + "path": "/packages/webpack/generators/configuration", + "name": "configuration", "children": [], "isExternal": false, "disableCollapsible": false diff --git a/docs/generated/manifests/packages.json b/docs/generated/manifests/packages.json index ab397134b52de..181b7b7096873 100644 --- a/docs/generated/manifests/packages.json +++ b/docs/generated/manifests/packages.json @@ -651,13 +651,13 @@ "path": "/packages/esbuild/generators/init", "type": "generator" }, - "/packages/esbuild/generators/esbuild-project": { + "/packages/esbuild/generators/configuration": { "description": "Add esbuild configuration to a project.", - "file": "generated/packages/esbuild/generators/esbuild-project.json", + "file": "generated/packages/esbuild/generators/configuration.json", "hidden": true, - "name": "esbuild-project", - "originalFilePath": "/packages/esbuild/src/generators/esbuild-project/schema.json", - "path": "/packages/esbuild/generators/esbuild-project", + "name": "configuration", + "originalFilePath": "/packages/esbuild/src/generators/configuration/schema.json", + "path": "/packages/esbuild/generators/configuration", "type": "generator" } }, @@ -2336,13 +2336,13 @@ "path": "/packages/rollup/generators/init", "type": "generator" }, - "/packages/rollup/generators/rollup-project": { + "/packages/rollup/generators/configuration": { "description": "Add rollup configuration to a project.", - "file": "generated/packages/rollup/generators/rollup-project.json", + "file": "generated/packages/rollup/generators/configuration.json", "hidden": true, - "name": "rollup-project", - "originalFilePath": "/packages/rollup/src/generators/rollup-project/schema.json", - "path": "/packages/rollup/generators/rollup-project", + "name": "configuration", + "originalFilePath": "/packages/rollup/src/generators/configuration/schema.json", + "path": "/packages/rollup/generators/configuration", "type": "generator" } }, @@ -2782,13 +2782,13 @@ "path": "/packages/webpack/generators/init", "type": "generator" }, - "/packages/webpack/generators/webpack-project": { + "/packages/webpack/generators/configuration": { "description": "Add webpack configuration to a project.", - "file": "generated/packages/webpack/generators/webpack-project.json", + "file": "generated/packages/webpack/generators/configuration.json", "hidden": true, - "name": "webpack-project", - "originalFilePath": "/packages/webpack/src/generators/webpack-project/schema.json", - "path": "/packages/webpack/generators/webpack-project", + "name": "configuration", + "originalFilePath": "/packages/webpack/src/generators/configuration/schema.json", + "path": "/packages/webpack/generators/configuration", "type": "generator" } }, diff --git a/docs/generated/packages-metadata.json b/docs/generated/packages-metadata.json index 176350597fcc7..e3fe8f5992f7d 100644 --- a/docs/generated/packages-metadata.json +++ b/docs/generated/packages-metadata.json @@ -642,11 +642,11 @@ }, { "description": "Add esbuild configuration to a project.", - "file": "generated/packages/esbuild/generators/esbuild-project.json", + "file": "generated/packages/esbuild/generators/configuration.json", "hidden": true, - "name": "esbuild-project", - "originalFilePath": "/packages/esbuild/src/generators/esbuild-project/schema.json", - "path": "esbuild/generators/esbuild-project", + "name": "configuration", + "originalFilePath": "/packages/esbuild/src/generators/configuration/schema.json", + "path": "esbuild/generators/configuration", "type": "generator" } ], @@ -2313,11 +2313,11 @@ }, { "description": "Add rollup configuration to a project.", - "file": "generated/packages/rollup/generators/rollup-project.json", + "file": "generated/packages/rollup/generators/configuration.json", "hidden": true, - "name": "rollup-project", - "originalFilePath": "/packages/rollup/src/generators/rollup-project/schema.json", - "path": "rollup/generators/rollup-project", + "name": "configuration", + "originalFilePath": "/packages/rollup/src/generators/configuration/schema.json", + "path": "rollup/generators/configuration", "type": "generator" } ], @@ -2754,11 +2754,11 @@ }, { "description": "Add webpack configuration to a project.", - "file": "generated/packages/webpack/generators/webpack-project.json", + "file": "generated/packages/webpack/generators/configuration.json", "hidden": true, - "name": "webpack-project", - "originalFilePath": "/packages/webpack/src/generators/webpack-project/schema.json", - "path": "webpack/generators/webpack-project", + "name": "configuration", + "originalFilePath": "/packages/webpack/src/generators/configuration/schema.json", + "path": "webpack/generators/configuration", "type": "generator" } ], diff --git a/docs/generated/packages/esbuild/documents/overview.md b/docs/generated/packages/esbuild/documents/overview.md index 5dba8a19770a4..e080e503494fc 100644 --- a/docs/generated/packages/esbuild/documents/overview.md +++ b/docs/generated/packages/esbuild/documents/overview.md @@ -45,13 +45,13 @@ This command will install the esbuild plugin if needed, and set `@nx/esbuild:esb If you already have a JS project that you want to use esbuild for, run this command: ```shell -nx g esbuild-project mylib +nx g @nx/esbuild:configuration mylib ``` This generator validates there isn't an existing `build` target. If you want to overwrite the existing target you can pass the `--skipValidation` option. ```shell -nx g esbuild-project mylib --skipValidation +nx g @nx/esbuild:configuration mylib --skipValidation ``` ## Using esbuild diff --git a/docs/generated/packages/esbuild/executors/esbuild.json b/docs/generated/packages/esbuild/executors/esbuild.json index 67783d869a46c..fc93bfb457729 100644 --- a/docs/generated/packages/esbuild/executors/esbuild.json +++ b/docs/generated/packages/esbuild/executors/esbuild.json @@ -206,7 +206,7 @@ } }, "additionalProperties": true, - "examplesFile": "`/project.json`:\n\n```json\n{\n //...\n \"targets\": {\n //...\n \"build\": {\n \"executor\": \"@nx/esbuild:esbuild\",\n \"options\": {\n \"main\": \"\",\n \"tsConfig\": \"/tsconfig.app.json\",\n \"outputPath\": \"dist/\"\n }\n }\n }\n}\n```\n\n```bash\nnx build \n```\n\n## Examples\n\n{% tabs %}\n{% tab label=\"CommonJS output\" %}\n\nThe CommonJS format is required in some environments, such as Electron applications. By default, `esbuild` will use the ESM format, which is recommended for Web and Node applications. You may also output to multiple formats.\n\n```bash\nnx build --format=cjs\nnx build --format=esm,cjs\nnx build # defaults to es# defaults to esm\n```\n\n```json\n\"build\": {\n \"executor\": \"@nx/esbuild:esbuild\",\n \"options\": {\n \"main\": \"\",\n \"tsConfig\": \"/tsconfig.app.json\",\n \"outputPath\": \"dist/\",\n \"format\": [\"esm\", \"cjs\"]\n}\n```\n\n{% /tab %}\n{% tab label=\"External packages\" %}\n\nYou can avoid packages from being bundled by providing the `external` option with a list of packages to skip.\n\nYou can also use `*` wildcard to match assets.\n\n```json\n\"build\": {\n \"executor\": \"@nx/esbuild:esbuild\",\n \"options\": {\n \"main\": \"\",\n \"tsConfig\": \"/tsconfig.app.json\",\n \"outputPath\": \"dist/\",\n \"external\": [\"lodash\", \"*.png\"]\n}\n```\n\n{% /tab %}\n{% tab label=\"Skip type checking\" %}\n\nType checking is the slowest part of the build. You may want to skip type checking during build and run it as another job in CI.\n\n```json\n\"build\": {\n \"executor\": \"@nx/esbuild:esbuild\",\n \"options\": {\n \"main\": \"\",\n \"tsConfig\": \"/tsconfig.app.json\",\n \"outputPath\": \"dist/\",\n \"skipTypeCheck\": true\n}\n```\n\n{% /tab %}\n{% tab label=\"Additional esbuild options\" %}\n\nAdditional [esbuild options](https://esbuild.github.io/api/) can be passed using `esbuildOptions` in your project configuration.\n\n```json\n\"build\": {\n \"executor\": \"@nx/esbuild:esbuild\",\n \"options\": {\n \"main\": \"\",\n \"tsConfig\": \"/tsconfig.app.json\",\n \"outputPath\": \"dist/\",\n \"esbuildOptions\": {\n \"legalComments\": \"inline\"\n \"banner\": {\n \".js\": \"// banner\"\n },\n \"footer\": {\n \".js\": \"// footer\"\n }\n }\n}\n```\n\n{% /tab %}\n{% tabs %}\n", + "examplesFile": "`/project.json`:\n\n```jsonc\n{\n //...\n \"targets\": {\n //...\n \"build\": {\n \"executor\": \"@nx/esbuild:esbuild\",\n \"options\": {\n \"main\": \"\",\n \"tsConfig\": \"/tsconfig.app.json\",\n \"outputPath\": \"dist/\"\n }\n }\n }\n}\n```\n\n```bash\nnx build \n```\n\n## Examples\n\n{% tabs %}\n{% tab label=\"CommonJS output\" %}\n\nThe CommonJS format is required in some environments, such as Electron applications. By default, `esbuild` will use the ESM format, which is recommended for Web and Node applications. You may also output to multiple formats.\n\n```bash\nnx build --format=cjs\nnx build --format=esm,cjs\nnx build # defaults to es# defaults to esm\n```\n\n```json\n\"build\": {\n \"executor\": \"@nx/esbuild:esbuild\",\n \"options\": {\n \"main\": \"\",\n \"tsConfig\": \"/tsconfig.app.json\",\n \"outputPath\": \"dist/\",\n \"format\": [\"esm\", \"cjs\"]\n}\n```\n\n{% /tab %}\n{% tab label=\"External packages\" %}\n\nYou can avoid packages from being bundled by providing the `external` option with a list of packages to skip.\n\nYou can also use `*` wildcard to match assets.\n\n```json\n\"build\": {\n \"executor\": \"@nx/esbuild:esbuild\",\n \"options\": {\n \"main\": \"\",\n \"tsConfig\": \"/tsconfig.app.json\",\n \"outputPath\": \"dist/\",\n \"external\": [\"lodash\", \"*.png\"]\n}\n```\n\n{% /tab %}\n{% tab label=\"Skip type checking\" %}\n\nType checking is the slowest part of the build. You may want to skip type checking during build and run it as another job in CI.\n\n```json\n\"build\": {\n \"executor\": \"@nx/esbuild:esbuild\",\n \"options\": {\n \"main\": \"\",\n \"tsConfig\": \"/tsconfig.app.json\",\n \"outputPath\": \"dist/\",\n \"skipTypeCheck\": true\n}\n```\n\n{% /tab %}\n{% tab label=\"Additional esbuild options\" %}\n\nAdditional [esbuild options](https://esbuild.github.io/api/) can be passed using `esbuildOptions` in your project configuration.\n\n```json\n\"build\": {\n \"executor\": \"@nx/esbuild:esbuild\",\n \"options\": {\n \"main\": \"\",\n \"tsConfig\": \"/tsconfig.app.json\",\n \"outputPath\": \"dist/\",\n \"esbuildOptions\": {\n \"legalComments\": \"inline\"\n \"banner\": {\n \".js\": \"// banner\"\n },\n \"footer\": {\n \".js\": \"// footer\"\n }\n }\n}\n```\n\n{% /tab %}\n{% tabs %}\n", "presets": [] }, "description": "Bundle a package using EsBuild.", diff --git a/docs/generated/packages/esbuild/generators/configuration.json b/docs/generated/packages/esbuild/generators/configuration.json new file mode 100644 index 0000000000000..0dd6daf91f77e --- /dev/null +++ b/docs/generated/packages/esbuild/generators/configuration.json @@ -0,0 +1,75 @@ +{ + "name": "configuration", + "aliases": ["esbuild-project"], + "factory": "./src/generators/configuration/configuration", + "schema": { + "$schema": "http://json-schema.org/schema", + "$id": "NxEsBuildProject", + "cli": "nx", + "title": "Add esbuild configuration to a project", + "description": "Add esbuild configuration to a project.", + "type": "object", + "properties": { + "project": { + "type": "string", + "description": "The name of the project.", + "$default": { "$source": "argv", "index": 0 }, + "x-dropdown": "project", + "x-prompt": "What is the name of the project to set up a esbuild for?", + "x-priority": "important" + }, + "main": { + "type": "string", + "description": "Path relative to the workspace root for the main entry file. Defaults to `/src/main.ts` or `src/index.ts`, whichever is found.", + "alias": "entryFile", + "x-priority": "important" + }, + "tsConfig": { + "type": "string", + "description": "Path relative to the workspace root for the tsconfig file to build with. Defaults to `/tsconfig.app.json` or `/tsconfig.lib.json`, whichever is found.", + "x-priority": "important" + }, + "skipFormat": { + "description": "Skip formatting files.", + "type": "boolean", + "default": false, + "x-priority": "internal" + }, + "skipPackageJson": { + "type": "boolean", + "default": false, + "description": "Do not add dependencies to `package.json`.", + "x-priority": "internal" + }, + "skipValidation": { + "type": "boolean", + "default": false, + "description": "Do not perform any validation on existing project.", + "x-priority": "internal" + }, + "importPath": { + "type": "string", + "description": "The library name used to import it, like `@myorg/my-awesome-lib`." + }, + "platform": { + "type": "string", + "description": "Platform target for outputs.", + "enum": ["browser", "node", "neutral"], + "default": "node" + }, + "buildTarget": { + "description": "The build target to add.", + "type": "string", + "default": "build" + } + }, + "required": [], + "examplesFile": "```bash\nnx g @nx/esbuild:configuration my-package\n```\n\n{% callout type=\"note\" title=\"Overwriting existing build option\" %}\nThe `configuration` generator validates that an existing `build` target isn't already defined for the project. If you are adding esbuild to a project with an existing `build` target, pass the `--skipValidation` option.\n{% /callout %}\n\nYou may also provide a custom main entry file, or a custom tsconfig file if the defaults don't work. By default, the generator will look for a main file matching `src/index.ts` or `src/main.ts`, and a tsconfig file matching `tsconfig.app.json` or `tsconfig.lib.json`.\n\n```bash\nnx g @nx/esbuild:configuration my-package \\\n--main=packages/my-package/src/entry.ts \\\n--tsConfig=packages/my-package/tsconfig.custom.json\n```\n", + "presets": [] + }, + "description": "Add esbuild configuration to a project.", + "hidden": true, + "implementation": "/packages/esbuild/src/generators/configuration/configuration.ts", + "path": "/packages/esbuild/src/generators/configuration/schema.json", + "type": "generator" +} diff --git a/docs/generated/packages/rollup/generators/configuration.json b/docs/generated/packages/rollup/generators/configuration.json new file mode 100644 index 0000000000000..e17a829963cb2 --- /dev/null +++ b/docs/generated/packages/rollup/generators/configuration.json @@ -0,0 +1,83 @@ +{ + "name": "configuration", + "aliases": ["rollup-project"], + "factory": "./src/generators/configuration/configuration", + "schema": { + "$schema": "http://json-schema.org/schema", + "$id": "NxRollupProject", + "cli": "nx", + "title": "Add Rollup Configuration to a project", + "description": "Add Rollup Configuration to a project.", + "type": "object", + "properties": { + "project": { + "type": "string", + "description": "The name of the project.", + "$default": { "$source": "argv", "index": 0 }, + "x-dropdown": "project", + "x-prompt": "What is the name of the project to set up a rollup for?", + "x-priority": "important" + }, + "compiler": { + "type": "string", + "enum": ["babel", "swc", "tsc"], + "description": "The compiler to use to build source.", + "default": "babel" + }, + "main": { + "type": "string", + "description": "Path relative to the workspace root for the main entry file. Defaults to '/src/main.ts'.", + "alias": "entryFile", + "x-priority": "important" + }, + "tsConfig": { + "type": "string", + "description": "Path relative to the workspace root for the tsconfig file to build with. Defaults to '/tsconfig.app.json'.", + "x-priority": "important" + }, + "skipFormat": { + "description": "Skip formatting files.", + "type": "boolean", + "default": false, + "x-priority": "internal" + }, + "skipPackageJson": { + "type": "boolean", + "default": false, + "description": "Do not add dependencies to `package.json`.", + "x-priority": "internal" + }, + "skipValidation": { + "type": "boolean", + "default": false, + "description": "Do not perform any validation on existing project.", + "x-priority": "internal" + }, + "importPath": { + "type": "string", + "description": "The library name used to import it, like `@myorg/my-awesome-lib`." + }, + "external": { + "type": "array", + "description": "A list of external modules that will not be bundled (`react`, `react-dom`, etc.).", + "items": { "type": "string" } + }, + "rollupConfig": { + "type": "string", + "description": "Path relative to workspace root to a custom rollup file that takes a config object and returns an updated config." + }, + "buildTarget": { + "description": "The build target to add.", + "type": "string", + "default": "build" + } + }, + "required": [], + "presets": [] + }, + "description": "Add rollup configuration to a project.", + "hidden": true, + "implementation": "/packages/rollup/src/generators/configuration/configuration.ts", + "path": "/packages/rollup/src/generators/configuration/schema.json", + "type": "generator" +} diff --git a/docs/generated/packages/webpack/generators/configuration.json b/docs/generated/packages/webpack/generators/configuration.json new file mode 100644 index 0000000000000..508705b601e49 --- /dev/null +++ b/docs/generated/packages/webpack/generators/configuration.json @@ -0,0 +1,85 @@ +{ + "name": "configuration", + "aliases": ["webpack-project"], + "factory": "./src/generators/configuration/configuration", + "schema": { + "$schema": "http://json-schema.org/schema", + "$id": "NxWebpackProject", + "cli": "nx", + "title": "Add Webpack Configuration to a project", + "description": "Add Webpack Configuration to a project.", + "type": "object", + "properties": { + "project": { + "type": "string", + "description": "The name of the project.", + "$default": { "$source": "argv", "index": 0 }, + "x-dropdown": "project", + "x-prompt": "What is the name of the project to set up a webpack for?", + "x-priority": "important" + }, + "compiler": { + "type": "string", + "enum": ["babel", "swc", "tsc"], + "description": "The compiler to use to build source.", + "default": "swc" + }, + "main": { + "type": "string", + "description": "Path relative to the workspace root for the main entry file. Defaults to '/src/main.ts'.", + "x-priority": "important" + }, + "tsConfig": { + "type": "string", + "description": "Path relative to the workspace root for the tsconfig file to build with. Defaults to '/tsconfig.app.json'.", + "x-priority": "important" + }, + "target": { + "type": "string", + "description": "Target platform for the build, same as the Webpack config option.", + "enum": ["node", "web", "webworker"], + "default": "web" + }, + "skipFormat": { + "description": "Skip formatting files.", + "type": "boolean", + "default": false, + "x-priority": "internal" + }, + "skipPackageJson": { + "type": "boolean", + "default": false, + "description": "Do not add dependencies to `package.json`.", + "x-priority": "internal" + }, + "skipValidation": { + "type": "boolean", + "default": false, + "description": "Do not perform any validation on existing project.", + "x-priority": "internal" + }, + "devServer": { + "type": "boolean", + "description": "Add a serve target to run a local webpack dev-server", + "default": false + }, + "webpackConfig": { + "type": "string", + "description": "Path relative to workspace root to a custom webpack file that takes a config object and returns an updated config.", + "x-priority": "internal" + }, + "babelConfig": { + "type": "string", + "description": "Optionally specify a path relative to workspace root to the babel configuration file of your project.", + "x-completion-type": "file" + } + }, + "required": [], + "presets": [] + }, + "description": "Add webpack configuration to a project.", + "hidden": true, + "implementation": "/packages/webpack/src/generators/configuration/configuration.ts", + "path": "/packages/webpack/src/generators/configuration/schema.json", + "type": "generator" +} diff --git a/docs/shared/packages/esbuild/esbuild-plugin.md b/docs/shared/packages/esbuild/esbuild-plugin.md index 5dba8a19770a4..e080e503494fc 100644 --- a/docs/shared/packages/esbuild/esbuild-plugin.md +++ b/docs/shared/packages/esbuild/esbuild-plugin.md @@ -45,13 +45,13 @@ This command will install the esbuild plugin if needed, and set `@nx/esbuild:esb If you already have a JS project that you want to use esbuild for, run this command: ```shell -nx g esbuild-project mylib +nx g @nx/esbuild:configuration mylib ``` This generator validates there isn't an existing `build` target. If you want to overwrite the existing target you can pass the `--skipValidation` option. ```shell -nx g esbuild-project mylib --skipValidation +nx g @nx/esbuild:configuration mylib --skipValidation ``` ## Using esbuild diff --git a/docs/shared/reference/sitemap.md b/docs/shared/reference/sitemap.md index bcf99cf1a0a1d..0eb10dc024c61 100644 --- a/docs/shared/reference/sitemap.md +++ b/docs/shared/reference/sitemap.md @@ -353,7 +353,7 @@ - [esbuild](/packages/esbuild/executors/esbuild) - [generators](/packages/esbuild/generators) - [init](/packages/esbuild/generators/init) - - [esbuild-project](/packages/esbuild/generators/esbuild-project) + - [configuration](/packages/esbuild/generators/configuration) - [eslint-plugin](/packages/eslint-plugin) - [documents](/packages/eslint-plugin/documents) - [Overview](/packages/eslint-plugin/documents/overview) @@ -558,7 +558,7 @@ - [rollup](/packages/rollup/executors/rollup) - [generators](/packages/rollup/generators) - [init](/packages/rollup/generators/init) - - [rollup-project](/packages/rollup/generators/rollup-project) + - [configuration](/packages/rollup/generators/configuration) - [storybook](/packages/storybook) - [documents](/packages/storybook/documents) - [Nx Storybook Plugin Overview](/packages/storybook/documents/overview) @@ -613,7 +613,7 @@ - [ssr-dev-server](/packages/webpack/executors/ssr-dev-server) - [generators](/packages/webpack/generators) - [init](/packages/webpack/generators/init) - - [webpack-project](/packages/webpack/generators/webpack-project) + - [configuration](/packages/webpack/generators/configuration) - [workspace](/packages/workspace) - [documents](/packages/workspace/documents) - [Overview](/packages/workspace/documents/overview) diff --git a/e2e/rollup/src/rollup.test.ts b/e2e/rollup/src/rollup.test.ts index 85777bab98801..704923b7d3d4e 100644 --- a/e2e/rollup/src/rollup.test.ts +++ b/e2e/rollup/src/rollup.test.ts @@ -20,7 +20,7 @@ describe('Rollup Plugin', () => { // babel (default) runCLI( - `generate @nx/rollup:rollup-project ${myPkg} --target=node --tsConfig=libs/${myPkg}/tsconfig.lib.json --main=libs/${myPkg}/src/index.ts` + `generate @nx/rollup:configuration ${myPkg} --target=node --tsConfig=libs/${myPkg}/tsconfig.lib.json --main=libs/${myPkg}/src/index.ts` ); rmDist(); runCLI(`build ${myPkg}`); @@ -34,7 +34,7 @@ describe('Rollup Plugin', () => { // swc runCLI( - `generate @nx/rollup:rollup-project ${myPkg} --target=node --tsConfig=libs/${myPkg}/tsconfig.lib.json --main=libs/${myPkg}/src/index.ts --compiler=swc` + `generate @nx/rollup:configuration ${myPkg} --target=node --tsConfig=libs/${myPkg}/tsconfig.lib.json --main=libs/${myPkg}/src/index.ts --compiler=swc` ); rmDist(); runCLI(`build ${myPkg}`); @@ -48,7 +48,7 @@ describe('Rollup Plugin', () => { // tsc runCLI( - `generate @nx/rollup:rollup-project ${myPkg} --target=node --tsConfig=libs/${myPkg}/tsconfig.lib.json --main=libs/${myPkg}/src/index.ts --compiler=tsc` + `generate @nx/rollup:configuration ${myPkg} --target=node --tsConfig=libs/${myPkg}/tsconfig.lib.json --main=libs/${myPkg}/src/index.ts --compiler=tsc` ); rmDist(); runCLI(`build ${myPkg}`); diff --git a/e2e/webpack/src/webpack.test.ts b/e2e/webpack/src/webpack.test.ts index 16073e79f84d5..b1d8a094868fe 100644 --- a/e2e/webpack/src/webpack.test.ts +++ b/e2e/webpack/src/webpack.test.ts @@ -19,7 +19,7 @@ describe('Webpack Plugin', () => { updateFile(`libs/${myPkg}/src/index.ts`, `console.log('Hello');\n`); runCLI( - `generate @nx/webpack:webpack-project ${myPkg} --target=node --tsConfig=libs/${myPkg}/tsconfig.lib.json --main=libs/${myPkg}/src/index.ts` + `generate @nx/webpack:configuration ${myPkg} --target=node --tsConfig=libs/${myPkg}/tsconfig.lib.json --main=libs/${myPkg}/src/index.ts` ); // Test `scriptType` later during during. @@ -52,7 +52,7 @@ module.exports = composePlugins(withNx(), (config) => { // swc runCLI( - `generate @nx/webpack:webpack-project ${myPkg} --target=node --tsConfig=libs/${myPkg}/tsconfig.lib.json --main=libs/${myPkg}/src/index.ts --compiler=swc` + `generate @nx/webpack:configuration ${myPkg} --target=node --tsConfig=libs/${myPkg}/tsconfig.lib.json --main=libs/${myPkg}/src/index.ts --compiler=swc` ); rmDist(); runCLI(`build ${myPkg}`); @@ -66,7 +66,7 @@ module.exports = composePlugins(withNx(), (config) => { // tsc runCLI( - `generate @nx/webpack:webpack-project ${myPkg} --target=node --tsConfig=libs/${myPkg}/tsconfig.lib.json --main=libs/${myPkg}/src/index.ts --compiler=tsc` + `generate @nx/webpack:configuration ${myPkg} --target=node --tsConfig=libs/${myPkg}/tsconfig.lib.json --main=libs/${myPkg}/src/index.ts --compiler=tsc` ); rmDist(); runCLI(`build ${myPkg}`); @@ -80,7 +80,7 @@ module.exports = composePlugins(withNx(), (config) => { updateFile(`libs/${myPkg}/src/index.ts`, `console.log('Hello');\n`); runCLI( - `generate @nx/webpack:webpack-project ${myPkg} --target=node --compiler=babel --tsConfig=libs/${myPkg}/tsconfig.lib.json --main=libs/${myPkg}/src/index.ts` + `generate @nx/webpack:configuration ${myPkg} --target=node --compiler=babel --tsConfig=libs/${myPkg}/tsconfig.lib.json --main=libs/${myPkg}/src/index.ts` ); updateFile( diff --git a/nx-dev/nx-dev/redirect-rules.js b/nx-dev/nx-dev/redirect-rules.js index f3c66b863c569..7dd284e779c90 100644 --- a/nx-dev/nx-dev/redirect-rules.js +++ b/nx-dev/nx-dev/redirect-rules.js @@ -148,6 +148,8 @@ const schemaUrls = { '/packages/cypress/generators/configuration', '/packages/cypress/generators/cypress-component-configuration': '/packages/cypress/generators/component-configuration', + '/packages/esbuild/generators/esbuild-project': + '/packages/esbuild/generators/configuration', '/packages/nx-plugin/generators/executor': '/packages/plugin/generators/executor', '/packages/nx-plugin/generators/migration': @@ -156,6 +158,10 @@ const schemaUrls = { '/packages/nx-plugin/generators/schematic': '/packages/plugin/generators/generator', '/packages/nx-plugin/generators/e2e': '/packages/plugin/executors/e2e', + '/packages/rollup/generators/rollup-project': + '/packages/rollup/generators/configuration', + '/packages/webpack/generators/webpack-project': + '/packages/webpack/generators/configuration', '/nx-plugin/executor': '/packages/plugin/generators/executor', '/nx-plugin/migration': '/packages/plugin/generators/migration', '/nx-plugin/plugin': '/packages/plugin/generators/plugin', diff --git a/packages/esbuild/docs/esbuild-project-examples.md b/packages/esbuild/docs/configuration-examples.md similarity index 60% rename from packages/esbuild/docs/esbuild-project-examples.md rename to packages/esbuild/docs/configuration-examples.md index 213a6ee233ccf..4c52a963e73c5 100644 --- a/packages/esbuild/docs/esbuild-project-examples.md +++ b/packages/esbuild/docs/configuration-examples.md @@ -1,15 +1,15 @@ ```bash -nx g @nx/esbuild:esbuild-project my-package +nx g @nx/esbuild:configuration my-package ``` {% callout type="note" title="Overwriting existing build option" %} -The `esbuild-projet` generator validates that an existing `build` target isn't already defined for the project. If you are adding esbuild to a project with an existing `build` target, pass the `--skipValidation` option. +The `configuration` generator validates that an existing `build` target isn't already defined for the project. If you are adding esbuild to a project with an existing `build` target, pass the `--skipValidation` option. {% /callout %} You may also provide a custom main entry file, or a custom tsconfig file if the defaults don't work. By default, the generator will look for a main file matching `src/index.ts` or `src/main.ts`, and a tsconfig file matching `tsconfig.app.json` or `tsconfig.lib.json`. ```bash -nx g @nx/esbuild:esbuild-project my-package \ +nx g @nx/esbuild:configuration my-package \ --main=packages/my-package/src/entry.ts \ --tsConfig=packages/my-package/tsconfig.custom.json ``` diff --git a/packages/esbuild/docs/esbuild-examples.md b/packages/esbuild/docs/esbuild-examples.md index ffbc549d640db..198f6280724a2 100644 --- a/packages/esbuild/docs/esbuild-examples.md +++ b/packages/esbuild/docs/esbuild-examples.md @@ -1,6 +1,6 @@ `/project.json`: -```json +```jsonc { //... "targets": { diff --git a/packages/esbuild/generators.json b/packages/esbuild/generators.json index b788442cc9eef..fd8a040874bbe 100644 --- a/packages/esbuild/generators.json +++ b/packages/esbuild/generators.json @@ -8,9 +8,10 @@ "description": "Initialize the `@nrwl/esbuild` plugin.", "hidden": true }, - "esbuild-project": { - "factory": "./src/generators/esbuild-project/esbuild-project#esbuildProjectSchematic", - "schema": "./src/generators/esbuild-project/schema.json", + "configuration": { + "aliases": ["esbuild-project"], + "factory": "./src/generators/configuration/configuration#compat", + "schema": "./src/generators/configuration/schema.json", "description": "Add esbuild configuration to a project.", "hidden": true } @@ -23,9 +24,10 @@ "aliases": ["ng-add"], "hidden": true }, - "esbuild-project": { - "factory": "./src/generators/esbuild-project/esbuild-project#esbuildProjectGenerator", - "schema": "./src/generators/esbuild-project/schema.json", + "configuration": { + "aliases": ["esbuild-project"], + "factory": "./src/generators/configuration/configuration", + "schema": "./src/generators/configuration/schema.json", "description": "Add esbuild configuration to a project.", "hidden": true } diff --git a/packages/esbuild/index.ts b/packages/esbuild/index.ts index 0dbda3a6b0ce1..e1b2c26514d88 100644 --- a/packages/esbuild/index.ts +++ b/packages/esbuild/index.ts @@ -1,3 +1,9 @@ +import { configurationGenerator } from './src/generators/configuration/configuration'; +export { configurationGenerator }; + +// Exported for backwards compatibility in case a plugin is using the old name. +/** @deprecated Use `configurationGenerator` instead. */ +const esbuildProjectGenerator = configurationGenerator; + export * from './src/generators/init/init'; -export * from './src/generators/esbuild-project/esbuild-project'; export * from './src/utils/versions'; diff --git a/packages/esbuild/src/generators/esbuild-project/esbuild-project.spec.ts b/packages/esbuild/src/generators/configuration/configuration.spec.ts similarity index 89% rename from packages/esbuild/src/generators/esbuild-project/esbuild-project.spec.ts rename to packages/esbuild/src/generators/configuration/configuration.spec.ts index 157ffcae7c5be..b241d770bbc41 100644 --- a/packages/esbuild/src/generators/esbuild-project/esbuild-project.spec.ts +++ b/packages/esbuild/src/generators/configuration/configuration.spec.ts @@ -5,9 +5,9 @@ import { writeJson, } from '@nx/devkit'; import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; -import esbuildProjectGenerator from './esbuild-project'; +import configurationGenerator from './configuration'; -describe('esbuildProjectGenerator', () => { +describe('configurationGenerator', () => { let tree: Tree; beforeEach(() => { @@ -25,7 +25,7 @@ describe('esbuildProjectGenerator', () => { tree.write(`mypkg/src/${main}`, 'console.log("main");'); writeJson(tree, `mypkg/${tsConfig}`, {}); - await esbuildProjectGenerator(tree, { + await configurationGenerator(tree, { project: 'mypkg', }); @@ -47,7 +47,7 @@ describe('esbuildProjectGenerator', () => { tree.write(`src/main.ts`, 'console.log("main");'); writeJson(tree, `tsconfig.app.json`, {}); - await esbuildProjectGenerator(tree, { + await configurationGenerator(tree, { project: 'mypkg', }); diff --git a/packages/esbuild/src/generators/esbuild-project/esbuild-project.ts b/packages/esbuild/src/generators/configuration/configuration.ts similarity index 95% rename from packages/esbuild/src/generators/esbuild-project/esbuild-project.ts rename to packages/esbuild/src/generators/configuration/configuration.ts index d6dc3d67772e4..d855d685a8f2b 100644 --- a/packages/esbuild/src/generators/esbuild-project/esbuild-project.ts +++ b/packages/esbuild/src/generators/configuration/configuration.ts @@ -14,7 +14,7 @@ import { esbuildInitGenerator } from '../init/init'; import { EsBuildExecutorOptions } from '../../executors/esbuild/schema'; import { EsBuildProjectSchema } from './schema'; -export async function esbuildProjectGenerator( +export async function configurationGenerator( tree: Tree, options: EsBuildProjectSchema ) { @@ -126,8 +126,6 @@ function getTsConfigFile(tree: Tree, options: EsBuildProjectSchema) { return options.tsConfig; } -export const esbuildProjectSchematic = convertNxGenerator( - esbuildProjectGenerator -); +export const compat = convertNxGenerator(configurationGenerator); -export default esbuildProjectGenerator; +export default configurationGenerator; diff --git a/packages/esbuild/src/generators/esbuild-project/schema.d.ts b/packages/esbuild/src/generators/configuration/schema.d.ts similarity index 100% rename from packages/esbuild/src/generators/esbuild-project/schema.d.ts rename to packages/esbuild/src/generators/configuration/schema.d.ts diff --git a/packages/esbuild/src/generators/esbuild-project/schema.json b/packages/esbuild/src/generators/configuration/schema.json similarity index 97% rename from packages/esbuild/src/generators/esbuild-project/schema.json rename to packages/esbuild/src/generators/configuration/schema.json index 1266626ab4638..3de4555f0d501 100644 --- a/packages/esbuild/src/generators/esbuild-project/schema.json +++ b/packages/esbuild/src/generators/configuration/schema.json @@ -63,5 +63,5 @@ } }, "required": [], - "examplesFile": "../../../docs/esbuild-project-examples.md" + "examplesFile": "../../../docs/configuration-examples.md" } diff --git a/packages/js/src/generators/setup-build/generator.ts b/packages/js/src/generators/setup-build/generator.ts index 0b85307f8d51d..91925f36fac3d 100644 --- a/packages/js/src/generators/setup-build/generator.ts +++ b/packages/js/src/generators/setup-build/generator.ts @@ -88,11 +88,11 @@ export async function setupBuildGenerator( break; } case 'esbuild': { - const { esbuildProjectGenerator } = ensurePackage( + const { configurationGenerator } = ensurePackage( '@nx/esbuild', nxVersion ); - const task = await esbuildProjectGenerator(tree, { + const task = await configurationGenerator(tree, { main: mainFile, buildTarget: options.buildTarget, project: options.project, @@ -102,8 +102,8 @@ export async function setupBuildGenerator( break; } case 'rollup': { - const { rollupProjectGenerator } = ensurePackage('@nx/rollup', nxVersion); - const task = await rollupProjectGenerator(tree, { + const { configurationGenerator } = ensurePackage('@nx/rollup', nxVersion); + const task = await configurationGenerator(tree, { buildTarget: options.buildTarget, main: mainFile, project: options.project, diff --git a/packages/rollup/generators.json b/packages/rollup/generators.json index 61e75a106b304..7f6dcad5e4ff6 100644 --- a/packages/rollup/generators.json +++ b/packages/rollup/generators.json @@ -8,9 +8,10 @@ "description": "Initialize the `@nrwl/rollup` plugin.", "hidden": true }, - "rollup-project": { - "factory": "./src/generators/rollup-project/rollup-project#rollupProjectSchematic", - "schema": "./src/generators/rollup-project/schema.json", + "configuration": { + "aliases": ["rollup-project"], + "factory": "./src/generators/configuration/configuration#compat", + "schema": "./src/generators/configuration/schema.json", "description": "Add rollup configuration to a project.", "hidden": true } @@ -23,9 +24,10 @@ "aliases": ["ng-add"], "hidden": true }, - "rollup-project": { - "factory": "./src/generators/rollup-project/rollup-project#rollupProjectGenerator", - "schema": "./src/generators/rollup-project/schema.json", + "configuration": { + "aliases": ["rollup-project"], + "factory": "./src/generators/configuration/configuration", + "schema": "./src/generators/configuration/schema.json", "description": "Add rollup configuration to a project.", "hidden": true } diff --git a/packages/rollup/index.ts b/packages/rollup/index.ts index 421854d13f0b5..324c8d6b90e01 100644 --- a/packages/rollup/index.ts +++ b/packages/rollup/index.ts @@ -1,5 +1,11 @@ +import { configurationGenerator } from './src/generators/configuration/configuration'; +export { configurationGenerator }; + +// Exported for backwards compatibility in case a plugin is using the old name. +/** @deprecated Use `configurationGenerator` instead. */ +export const rollupProjectGenerator = configurationGenerator; + export * from './src/generators/init/init'; -export * from './src/generators/rollup-project/rollup-project'; export type { AssetGlobPattern, Globals, diff --git a/packages/rollup/src/generators/rollup-project/rollup-project.spec.ts b/packages/rollup/src/generators/configuration/configuration.spec.ts similarity index 89% rename from packages/rollup/src/generators/rollup-project/rollup-project.spec.ts rename to packages/rollup/src/generators/configuration/configuration.spec.ts index 8274be292d38d..b9dfb242104d0 100644 --- a/packages/rollup/src/generators/rollup-project/rollup-project.spec.ts +++ b/packages/rollup/src/generators/configuration/configuration.spec.ts @@ -7,9 +7,9 @@ import { } from '@nx/devkit'; import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; -import { rollupProjectGenerator } from './rollup-project'; +import configurationGenerator from './configuration'; -describe('rollupProjectGenerator', () => { +describe('configurationGenerator', () => { let tree: Tree; beforeEach(async () => { @@ -22,7 +22,7 @@ describe('rollupProjectGenerator', () => { }); it('should generate files', async () => { - await rollupProjectGenerator(tree, { + await configurationGenerator(tree, { project: 'mypkg', }); @@ -50,7 +50,7 @@ describe('rollupProjectGenerator', () => { name: '@acme/mypkg', version: '1.0.0', }); - await rollupProjectGenerator(tree, { + await configurationGenerator(tree, { project: 'mypkg', }); @@ -61,7 +61,7 @@ describe('rollupProjectGenerator', () => { }); it('should support --main option', async () => { - await rollupProjectGenerator(tree, { + await configurationGenerator(tree, { project: 'mypkg', main: 'libs/mypkg/index.ts', }); @@ -81,7 +81,7 @@ describe('rollupProjectGenerator', () => { }); it('should support --tsConfig option', async () => { - await rollupProjectGenerator(tree, { + await configurationGenerator(tree, { project: 'mypkg', tsConfig: 'libs/mypkg/tsconfig.custom.json', }); diff --git a/packages/rollup/src/generators/rollup-project/rollup-project.ts b/packages/rollup/src/generators/configuration/configuration.ts similarity index 94% rename from packages/rollup/src/generators/rollup-project/rollup-project.ts rename to packages/rollup/src/generators/configuration/configuration.ts index e5efa0b870cc4..b08a871271209 100644 --- a/packages/rollup/src/generators/rollup-project/rollup-project.ts +++ b/packages/rollup/src/generators/configuration/configuration.ts @@ -13,7 +13,7 @@ import { rollupInitGenerator } from '../init/init'; import { RollupExecutorOptions } from '../../executors/rollup/schema'; import { RollupProjectSchema } from './schema'; -export async function rollupProjectGenerator( +export async function configurationGenerator( tree: Tree, options: RollupProjectSchema ) { @@ -99,8 +99,6 @@ function addBuildTarget(tree: Tree, options: RollupProjectSchema) { }); } -export default rollupProjectGenerator; +export default configurationGenerator; -export const rollupProjectSchematic = convertNxGenerator( - rollupProjectGenerator -); +export const compat = convertNxGenerator(configurationGenerator); diff --git a/packages/rollup/src/generators/rollup-project/schema.d.ts b/packages/rollup/src/generators/configuration/schema.d.ts similarity index 100% rename from packages/rollup/src/generators/rollup-project/schema.d.ts rename to packages/rollup/src/generators/configuration/schema.d.ts diff --git a/packages/rollup/src/generators/rollup-project/schema.json b/packages/rollup/src/generators/configuration/schema.json similarity index 100% rename from packages/rollup/src/generators/rollup-project/schema.json rename to packages/rollup/src/generators/configuration/schema.json diff --git a/packages/web/src/generators/application/application.ts b/packages/web/src/generators/application/application.ts index 2f6d643c7a72e..cf93df96c9d1f 100644 --- a/packages/web/src/generators/application/application.ts +++ b/packages/web/src/generators/application/application.ts @@ -73,14 +73,15 @@ async function setupBundler(tree: Tree, options: NormalizedSchema) { ]; if (options.bundler === 'webpack') { - const { webpackProjectGenerator } = ensurePackage('@nx/webpack', nxVersion); - await webpackProjectGenerator(tree, { + const { configurationGenerator } = ensurePackage< + typeof import('@nx/webpack') + >('@nx/webpack', nxVersion); + await configurationGenerator(tree, { project: options.projectName, main, tsConfig, compiler: options.compiler ?? 'babel', devServer: true, - isolatedConfig: true, webpackConfig: joinPathFragments( options.appProjectRoot, 'webpack.config.js' diff --git a/packages/webpack/generators.json b/packages/webpack/generators.json index 43913018f4c7d..9179cd979a2ea 100644 --- a/packages/webpack/generators.json +++ b/packages/webpack/generators.json @@ -8,9 +8,10 @@ "description": "Initialize the `@nrwl/webpack` plugin.", "hidden": true }, - "webpack-project": { - "factory": "./src/generators/webpack-project/webpack-project#webpackProjectSchematic", - "schema": "./src/generators/webpack-project/schema.json", + "configuration": { + "aliases": ["webpack-project"], + "factory": "./src/generators/configuration/configuration#compat", + "schema": "./src/generators/configuration/schema.json", "description": "Add webpack configuration to a project.", "hidden": true } @@ -23,9 +24,10 @@ "aliases": ["ng-add"], "hidden": true }, - "webpack-project": { - "factory": "./src/generators/webpack-project/webpack-project#webpackProjectGenerator", - "schema": "./src/generators/webpack-project/schema.json", + "configuration": { + "aliases": ["webpack-project"], + "factory": "./src/generators/configuration/configuration", + "schema": "./src/generators/configuration/schema.json", "description": "Add webpack configuration to a project.", "hidden": true } diff --git a/packages/webpack/index.ts b/packages/webpack/index.ts index 1cd12a35512ac..7b77994105e2c 100644 --- a/packages/webpack/index.ts +++ b/packages/webpack/index.ts @@ -1,7 +1,13 @@ +import { configurationGenerator } from './src/generators/configuration/configuration'; +export { configurationGenerator }; + +// Exported for backwards compatibility in case a plugin is using the old name. +/** @deprecated Use `configurationGenerator` instead. */ +export const webpackProjectGenerator = configurationGenerator; + export * from './src/utils/create-copy-plugin'; export * from './src/utils/config'; export * from './src/generators/init/init'; -export * from './src/generators/webpack-project/webpack-project'; export type { WebDevServerOptions } from './src/executors/dev-server/schema'; export * from './src/executors/dev-server/dev-server.impl'; export * from './src/executors/webpack/lib/normalize-options'; diff --git a/packages/webpack/src/generators/webpack-project/webpack-project.spec.ts b/packages/webpack/src/generators/configuration/configuration.spec.ts similarity index 91% rename from packages/webpack/src/generators/webpack-project/webpack-project.spec.ts rename to packages/webpack/src/generators/configuration/configuration.spec.ts index 21f1c82b09faf..0430b754cd35f 100644 --- a/packages/webpack/src/generators/webpack-project/webpack-project.spec.ts +++ b/packages/webpack/src/generators/configuration/configuration.spec.ts @@ -5,7 +5,7 @@ import { } from '@nx/devkit'; import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; -import { webpackProjectGenerator } from './webpack-project'; +import configurationGenerator from './configuration'; describe('webpackProject', () => { let tree: Tree; @@ -20,7 +20,7 @@ describe('webpackProject', () => { }); it('should generate files', async () => { - await webpackProjectGenerator(tree, { + await configurationGenerator(tree, { project: 'mypkg', }); @@ -39,7 +39,7 @@ describe('webpackProject', () => { }); it('should support --main option', async () => { - await webpackProjectGenerator(tree, { + await configurationGenerator(tree, { project: 'mypkg', main: 'libs/mypkg/index.ts', }); @@ -59,7 +59,7 @@ describe('webpackProject', () => { }); it('should support --tsConfig option', async () => { - await webpackProjectGenerator(tree, { + await configurationGenerator(tree, { project: 'mypkg', tsConfig: 'libs/mypkg/tsconfig.custom.json', }); @@ -79,7 +79,7 @@ describe('webpackProject', () => { }); it('should support --devServer option', async () => { - await webpackProjectGenerator(tree, { + await configurationGenerator(tree, { project: 'mypkg', devServer: true, }); diff --git a/packages/webpack/src/generators/webpack-project/webpack-project.ts b/packages/webpack/src/generators/configuration/configuration.ts similarity index 89% rename from packages/webpack/src/generators/webpack-project/webpack-project.ts rename to packages/webpack/src/generators/configuration/configuration.ts index 065662f559fc6..8778f1504a491 100644 --- a/packages/webpack/src/generators/webpack-project/webpack-project.ts +++ b/packages/webpack/src/generators/configuration/configuration.ts @@ -9,12 +9,12 @@ import { } from '@nx/devkit'; import { webpackInitGenerator } from '../init/init'; -import { WebpackProjectGeneratorSchema } from './schema'; +import { ConfigurationGeneratorSchema } from './schema'; import { WebpackExecutorOptions } from '../../executors/webpack/schema'; -export async function webpackProjectGenerator( +export async function configurationGenerator( tree: Tree, - options: WebpackProjectGeneratorSchema + options: ConfigurationGeneratorSchema ) { const task = await webpackInitGenerator(tree, { ...options, @@ -35,7 +35,7 @@ export async function webpackProjectGenerator( function checkForTargetConflicts( tree: Tree, - options: WebpackProjectGeneratorSchema + options: ConfigurationGeneratorSchema ) { if (options.skipValidation) return; @@ -54,7 +54,7 @@ function checkForTargetConflicts( } } -function addBuildTarget(tree: Tree, options: WebpackProjectGeneratorSchema) { +function addBuildTarget(tree: Tree, options: ConfigurationGeneratorSchema) { const project = readProjectConfiguration(tree, options.project); const buildOptions: WebpackExecutorOptions = { target: options.target, @@ -132,7 +132,7 @@ module.exports = composePlugins(withNx(), (config) => { }); } -function addServeTarget(tree: Tree, options: WebpackProjectGeneratorSchema) { +function addServeTarget(tree: Tree, options: ConfigurationGeneratorSchema) { const project = readProjectConfiguration(tree, options.project); updateProjectConfiguration(tree, options.project, { ...project, @@ -153,8 +153,6 @@ function addServeTarget(tree: Tree, options: WebpackProjectGeneratorSchema) { }); } -export default webpackProjectGenerator; +export default configurationGenerator; -export const webpackProjectSchematic = convertNxGenerator( - webpackProjectGenerator -); +export const compat = convertNxGenerator(configurationGenerator); diff --git a/packages/webpack/src/generators/webpack-project/schema.d.ts b/packages/webpack/src/generators/configuration/schema.d.ts similarity index 85% rename from packages/webpack/src/generators/webpack-project/schema.d.ts rename to packages/webpack/src/generators/configuration/schema.d.ts index 950a85f4aa541..fdf8c9f642661 100644 --- a/packages/webpack/src/generators/webpack-project/schema.d.ts +++ b/packages/webpack/src/generators/configuration/schema.d.ts @@ -1,4 +1,4 @@ -export interface WebpackProjectGeneratorSchema { +export interface ConfigurationGeneratorSchema { project: string; main?: string; tsConfig?: string; diff --git a/packages/webpack/src/generators/webpack-project/schema.json b/packages/webpack/src/generators/configuration/schema.json similarity index 100% rename from packages/webpack/src/generators/webpack-project/schema.json rename to packages/webpack/src/generators/configuration/schema.json From b1f19e3e915ecafe7a583649c882ad8fd5ef6e58 Mon Sep 17 00:00:00 2001 From: Nicholas Cunningham Date: Fri, 7 Jul 2023 13:39:17 -0600 Subject: [PATCH 032/262] fix(nextjs): Update @types/react version for yarn resolution (#18028) --- packages/react/migrations.json | 9 +++++++++ packages/react/src/utils/versions.ts | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/react/migrations.json b/packages/react/migrations.json index e1ad0a3b25e09..2c55c7390a1ae 100644 --- a/packages/react/migrations.json +++ b/packages/react/migrations.json @@ -950,6 +950,15 @@ "alwaysAddToPackageJson": false } } + }, + "16.5.0-beta.4": { + "version": "16.5.0-beta.4", + "packages": { + "@types/react": { + "version": "18.2.14", + "alwaysAddToPackageJson": false + } + } } } } diff --git a/packages/react/src/utils/versions.ts b/packages/react/src/utils/versions.ts index bdcda062134e5..1d62e18e16e01 100755 --- a/packages/react/src/utils/versions.ts +++ b/packages/react/src/utils/versions.ts @@ -8,7 +8,7 @@ export const reactDomVersion = '18.2.0'; export const reactIsVersion = '18.2.0'; export const swcLoaderVersion = '0.1.15'; export const babelLoaderVersion = '^9.1.2'; -export const typesReactVersion = '18.2.13'; +export const typesReactVersion = '18.2.14'; export const typesReactDomVersion = '18.2.6'; export const typesReactIsVersion = '18.2.1'; From c04053b4e931176d8be6cd364841f3e0990710d2 Mon Sep 17 00:00:00 2001 From: Jason Jean Date: Fri, 7 Jul 2023 16:06:44 -0400 Subject: [PATCH 033/262] fix(core): parse project configs only in js (#18009) --- Cargo.lock | 43 --- packages/nx/Cargo.toml | 3 - packages/nx/src/config/workspaces.ts | 30 +- .../generators/utils/project-configuration.ts | 2 +- packages/nx/src/native/index.d.ts | 7 +- packages/nx/src/native/index.js | 4 +- .../src/native/tests/workspace_files.spec.ts | 305 +++++++++--------- packages/nx/src/native/utils/path.rs | 4 + .../src/native/workspace/get_config_files.rs | 65 ++-- .../workspace/get_nx_workspace_files.rs | 122 ++----- packages/nx/src/native/workspace/types.rs | 7 - .../utils/retrieve-workspace-files.ts | 83 +++-- 12 files changed, 298 insertions(+), 377 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 03fbb212db6cc..b50c6e97e05e3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -844,15 +844,6 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" -[[package]] -name = "jsonc-parser" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b56a20e76235284255a09fcd1f45cf55d3c524ea657ebd3854735925c57743d" -dependencies = [ - "serde_json", -] - [[package]] name = "kqueue" version = "1.0.7" @@ -1171,13 +1162,10 @@ dependencies = [ "ignore", "ignore-files", "itertools", - "jsonc-parser", "napi", "napi-build", "napi-derive", "rayon", - "serde", - "serde_json", "thiserror", "tokio", "tracing", @@ -1447,12 +1435,6 @@ dependencies = [ "windows-sys 0.45.0", ] -[[package]] -name = "ryu" -version = "1.0.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" - [[package]] name = "same-file" version = "1.0.6" @@ -1479,31 +1461,6 @@ name = "serde" version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.152" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.107", -] - -[[package]] -name = "serde_json" -version = "1.0.96" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" -dependencies = [ - "itoa", - "ryu", - "serde", -] [[package]] name = "sha1_smol" diff --git a/packages/nx/Cargo.toml b/packages/nx/Cargo.toml index 37d4445d2e912..2443f8823382c 100644 --- a/packages/nx/Cargo.toml +++ b/packages/nx/Cargo.toml @@ -13,12 +13,9 @@ hashbrown = { version = "0.14.0", features = ["rayon"] } ignore = '0.4' ignore-files = "1.3.0" itertools = "0.10.5" -jsonc-parser = { version = "0.21.1", features = ["serde"] } napi = { version = '2.12.6', default-features = false, features = ['anyhow', 'napi4', 'tokio_rt'] } napi-derive = '2.9.3' rayon = "1.7.0" -serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0" thiserror = "1.0.40" tokio = { version = "1.28.2", features = ["fs"] } tracing = "0.1.37" diff --git a/packages/nx/src/config/workspaces.ts b/packages/nx/src/config/workspaces.ts index 40f4ab823a2d6..acb529bd28e3d 100644 --- a/packages/nx/src/config/workspaces.ts +++ b/packages/nx/src/config/workspaces.ts @@ -95,7 +95,7 @@ export class Workspaces { return this.cachedProjectsConfig; } const nxJson = this.readNxJson(); - const projectsConfigurations = buildProjectsConfigurationsFromProjectPaths( + let projectsConfigurations = buildProjectsConfigurationsFromProjectPaths( nxJson, globForProjectFiles( this.root, @@ -116,15 +116,18 @@ export class Workspaces { opts?._includeProjectsFromAngularJson ) ) { - projectsConfigurations.projects = mergeAngularJsonAndProjects( - projectsConfigurations.projects, + projectsConfigurations = mergeAngularJsonAndProjects( + projectsConfigurations, this.root ); } - this.cachedProjectsConfig = this.mergeTargetDefaultsIntoProjectDescriptions( - projectsConfigurations, - nxJson - ); + this.cachedProjectsConfig = { + version: 2, + projects: this.mergeTargetDefaultsIntoProjectDescriptions( + projectsConfigurations, + nxJson + ), + }; return this.cachedProjectsConfig; } @@ -140,10 +143,10 @@ export class Workspaces { } private mergeTargetDefaultsIntoProjectDescriptions( - config: ProjectsConfigurations, + projects: Record, nxJson: NxJsonConfiguration ) { - for (const proj of Object.values(config.projects)) { + for (const proj of Object.values(projects)) { if (proj.targets) { for (const targetName of Object.keys(proj.targets)) { const projectTargetDefinition = proj.targets[targetName]; @@ -163,7 +166,7 @@ export class Workspaces { } } } - return config; + return projects; } isNxExecutor(nodeModule: string, executor: string) { @@ -808,7 +811,7 @@ export function buildProjectsConfigurationsFromProjectPaths( projectFiles: string[], // making this parameter allows devkit to pick up newly created projects readJson: (string) => T = (string) => readJsonFile(string) // making this an arg allows us to reuse in devkit -): ProjectsConfigurations { +): Record { const projects: Record = {}; for (const file of projectFiles) { @@ -868,10 +871,7 @@ export function buildProjectsConfigurationsFromProjectPaths( } } - return { - version: 2, - projects: projects, - }; + return projects; } export function mergeTargetConfigurations( diff --git a/packages/nx/src/generators/utils/project-configuration.ts b/packages/nx/src/generators/utils/project-configuration.ts index 841fb0d860192..6a3e5b7b4113e 100644 --- a/packages/nx/src/generators/utils/project-configuration.ts +++ b/packages/nx/src/generators/utils/project-configuration.ts @@ -198,7 +198,7 @@ function readAndCombineAllProjectConfigurations(tree: Tree): { nxJson, projectFiles, (file) => readJson(tree, file) - ).projects; + ); } /** diff --git a/packages/nx/src/native/index.d.ts b/packages/nx/src/native/index.d.ts index a8f0c14fdc5c4..d5445ab9341d4 100644 --- a/packages/nx/src/native/index.d.ts +++ b/packages/nx/src/native/index.d.ts @@ -37,14 +37,13 @@ export const enum WorkspaceErrors { Generic = 'Generic' } /** Get workspace config files based on provided globs */ -export function getConfigFiles(workspaceRoot: string, globs: Array): Array +export function getProjectConfigurations(workspaceRoot: string, globs: Array, parseConfigurations: (arg0: Array) => Record): Record export interface NxWorkspaceFiles { projectFileMap: Record> globalFiles: Array - configFiles: Array + projectConfigurations: Record } -/** Throws exceptions */ -export function getWorkspaceFilesNative(workspaceRoot: string, globs: Array): NxWorkspaceFiles +export function getWorkspaceFilesNative(workspaceRoot: string, globs: Array, parseConfigurations: (arg0: Array) => Record): NxWorkspaceFiles export class Watcher { origin: string /** diff --git a/packages/nx/src/native/index.js b/packages/nx/src/native/index.js index 88e15863f1ddd..a1c22704faa12 100644 --- a/packages/nx/src/native/index.js +++ b/packages/nx/src/native/index.js @@ -246,7 +246,7 @@ if (!nativeBinding) { throw new Error(`Failed to load native binding`) } -const { expandOutputs, remove, copy, hashArray, hashFile, hashFiles, hashFilesMatchingGlobs, EventType, Watcher, WorkspaceErrors, getConfigFiles, getWorkspaceFilesNative } = nativeBinding +const { expandOutputs, remove, copy, hashArray, hashFile, hashFiles, hashFilesMatchingGlobs, EventType, Watcher, WorkspaceErrors, getProjectConfigurations, getWorkspaceFilesNative } = nativeBinding module.exports.expandOutputs = expandOutputs module.exports.remove = remove @@ -258,5 +258,5 @@ module.exports.hashFilesMatchingGlobs = hashFilesMatchingGlobs module.exports.EventType = EventType module.exports.Watcher = Watcher module.exports.WorkspaceErrors = WorkspaceErrors -module.exports.getConfigFiles = getConfigFiles +module.exports.getProjectConfigurations = getProjectConfigurations module.exports.getWorkspaceFilesNative = getWorkspaceFilesNative diff --git a/packages/nx/src/native/tests/workspace_files.spec.ts b/packages/nx/src/native/tests/workspace_files.spec.ts index 50f8cf3c1565e..9e067a911bb5c 100644 --- a/packages/nx/src/native/tests/workspace_files.spec.ts +++ b/packages/nx/src/native/tests/workspace_files.spec.ts @@ -1,12 +1,24 @@ -import { - getConfigFiles, - getWorkspaceFilesNative, - WorkspaceErrors, -} from '../index'; +import { getProjectConfigurations, getWorkspaceFilesNative } from '../index'; import { TempFs } from '../../utils/testing/temp-fs'; import { NxJsonConfiguration } from '../../config/nx-json'; +import { dirname, join } from 'path'; +import { readJsonFile } from '../../utils/fileutils'; describe('workspace files', () => { + function createParseConfigurationsFunction(tempDir: string) { + return (filenames: string[]) => { + const res = {}; + for (const filename of filenames) { + const json = readJsonFile(join(tempDir, filename)); + res[json.name] = { + ...json, + root: dirname(filename), + }; + } + return res; + }; + } + it('should gather workspace file information', async () => { const fs = new TempFs('workspace-files'); const nxJson: NxJsonConfiguration = {}; @@ -41,12 +53,16 @@ describe('workspace files', () => { }); let globs = ['project.json', '**/project.json', 'libs/*/package.json']; - let { projectFileMap, configFiles, globalFiles } = getWorkspaceFilesNative( - fs.tempDir, - globs - ); + let { projectFileMap, projectConfigurations, globalFiles } = + getWorkspaceFilesNative( + fs.tempDir, + globs, + createParseConfigurationsFunction(fs.tempDir) + ); - let sortedConfigs = configFiles.sort(); + let sortedConfigs = Object.values(projectConfigurations).sort((a, b) => + a['name'].localeCompare(b['name']) + ); expect(projectFileMap).toMatchInlineSnapshot(` { @@ -104,11 +120,26 @@ describe('workspace files', () => { `); expect(sortedConfigs).toMatchInlineSnapshot(` [ - "libs/nested/project/project.json", - "libs/package-project/package.json", - "libs/project1/project.json", - "libs/project2/project.json", - "libs/project3/project.json", + { + "name": "nested-project", + "root": "libs/nested/project", + }, + { + "name": "package-project", + "root": "libs/package-project", + }, + { + "name": "project1", + "root": "libs/project1", + }, + { + "name": "project2", + "root": "libs/project2", + }, + { + "name": "project3", + "root": "libs/project3", + }, ] `); expect(globalFiles).toMatchInlineSnapshot(` @@ -148,7 +179,8 @@ describe('workspace files', () => { const globs = ['project.json', '**/project.json', '**/package.json']; const { globalFiles, projectFileMap } = getWorkspaceFilesNative( fs.tempDir, - globs + globs, + createParseConfigurationsFunction(fs.tempDir) ); expect(globalFiles).toEqual([]); @@ -201,140 +233,117 @@ describe('workspace files', () => { }); let globs = ['project.json', '**/project.json', '**/package.json']; - let { configFiles } = getWorkspaceFilesNative(fs.tempDir, globs); - - configFiles = configFiles.sort(); - - expect(configFiles).toMatchInlineSnapshot(` - [ - "libs/project1/project.json", - "project.json", - ] - `); - let configFiles2 = getConfigFiles(fs.tempDir, globs).sort(); - expect(configFiles2).toMatchInlineSnapshot(` - [ - "libs/project1/project.json", - "project.json", - ] + let projectConfigurations = getProjectConfigurations( + fs.tempDir, + globs, + (filenames) => { + const res = {}; + for (const filename of filenames) { + const json = readJsonFile(join(fs.tempDir, filename)); + res[json.name] = { + ...json, + root: dirname(filename), + }; + } + return res; + } + ); + expect(projectConfigurations).toMatchInlineSnapshot(` + { + "project1": { + "name": "project1", + "root": "libs/project1", + }, + "repo-name": { + "name": "repo-name", + "root": ".", + }, + } `); }); - describe('errors', () => { - it('it should infer names of configuration files without a name', async () => { - const fs = new TempFs('workspace-files'); - const nxJson: NxJsonConfiguration = {}; - await fs.createFiles({ - './nx.json': JSON.stringify(nxJson), - './package.json': JSON.stringify({ - name: 'repo-name', - version: '0.0.0', - dependencies: {}, - }), - './libs/project1/project.json': JSON.stringify({ - name: 'project1', - }), - './libs/project1/index.js': '', - './libs/project2/project.json': JSON.stringify({}), - }); - - let globs = ['project.json', '**/project.json', 'libs/*/package.json']; - expect(getWorkspaceFilesNative(fs.tempDir, globs).projectFileMap) - .toMatchInlineSnapshot(` - { - "project1": [ - { - "file": "libs/project1/index.js", - "hash": "3244421341483603138", - }, - { - "file": "libs/project1/project.json", - "hash": "13466615737813422520", - }, - ], - "project2": [ - { - "file": "libs/project2/project.json", - "hash": "1389868326933519382", - }, - ], - } - `); - }); - - it('handles comments', async () => { - const fs = new TempFs('workspace-files'); - const nxJson: NxJsonConfiguration = {}; - await fs.createFiles({ - './nx.json': JSON.stringify(nxJson), - './package.json': JSON.stringify({ - name: 'repo-name', - version: '0.0.0', - dependencies: {}, - }), - './libs/project1/project.json': `{ - "name": "temp" - // this should not fail - }`, - './libs/project1/index.js': '', - }); - - let globs = ['project.json', '**/project.json', 'libs/*/package.json']; - expect(() => getWorkspaceFilesNative(fs.tempDir, globs)).not.toThrow(); - }); - - it('handles extra comma', async () => { - const fs = new TempFs('workspace-files'); - const nxJson: NxJsonConfiguration = {}; - await fs.createFiles({ - './nx.json': JSON.stringify(nxJson), - './package.json': JSON.stringify({ - name: 'repo-name', - version: '0.0.0', - dependencies: {}, - }), - './libs/project1/project.json': `{ - "name": "temp", - }`, - './libs/project1/index.js': '', - }); - - let globs = ['**/project.json']; - expect(() => getWorkspaceFilesNative(fs.tempDir, globs)).not.toThrow(); - }); - - it('throws parsing errors: missing brackets', async () => { - const fs = new TempFs('workspace-files'); - const nxJson: NxJsonConfiguration = {}; - await fs.createFiles({ - './nx.json': JSON.stringify(nxJson), - './package.json': JSON.stringify({ - name: 'repo-name', - version: '0.0.0', - dependencies: {}, - }), - './libs/project1/project.json': `{ - "name": "temp", "property": "child": 2 } - }`, - './libs/project1/index.js': '', - }); - - let globs = ['**/project.json']; - - const error = getError(() => getWorkspaceFilesNative(fs.tempDir, globs)); - expect(error.message).toMatchInlineSnapshot( - `"libs/project1/project.json"` - ); - expect(error).toHaveProperty('code', WorkspaceErrors.ParseError); - }); - }); + // describe('errors', () => { + // it('it should infer names of configuration files without a name', async () => { + // const fs = new TempFs('workspace-files'); + // const nxJson: NxJsonConfiguration = {}; + // await fs.createFiles({ + // './nx.json': JSON.stringify(nxJson), + // './package.json': JSON.stringify({ + // name: 'repo-name', + // version: '0.0.0', + // dependencies: {}, + // }), + // './libs/project1/project.json': JSON.stringify({ + // name: 'project1', + // }), + // './libs/project1/index.js': '', + // './libs/project2/project.json': JSON.stringify({}), + // }); + // + // let globs = ['project.json', '**/project.json', 'libs/*/package.json']; + // expect(getWorkspaceFilesNative(fs.tempDir, globs).projectFileMap) + // .toMatchInlineSnapshot(` + // { + // "libs/project1": [ + // { + // "file": "libs/project1/index.js", + // "hash": "3244421341483603138", + // }, + // { + // "file": "libs/project1/project.json", + // "hash": "13466615737813422520", + // }, + // ], + // "libs/project2": [ + // { + // "file": "libs/project2/project.json", + // "hash": "1389868326933519382", + // }, + // ], + // } + // `); + // }); + // + // it('handles comments', async () => { + // const fs = new TempFs('workspace-files'); + // const nxJson: NxJsonConfiguration = {}; + // await fs.createFiles({ + // './nx.json': JSON.stringify(nxJson), + // './package.json': JSON.stringify({ + // name: 'repo-name', + // version: '0.0.0', + // dependencies: {}, + // }), + // './libs/project1/project.json': `{ + // "name": "temp" + // // this should not fail + // }`, + // './libs/project1/index.js': '', + // }); + // + // let globs = ['project.json', '**/project.json', 'libs/*/package.json']; + // expect(() => getWorkspaceFilesNative(fs.tempDir, globs)).not.toThrow(); + // }); + // + // it('handles extra comma', async () => { + // const fs = new TempFs('workspace-files'); + // const nxJson: NxJsonConfiguration = {}; + // await fs.createFiles({ + // './nx.json': JSON.stringify(nxJson), + // './package.json': JSON.stringify({ + // name: 'repo-name', + // version: '0.0.0', + // dependencies: {}, + // }), + // './libs/project1/project.json': `{ + // "name": "temp", + // }`, + // './libs/project1/index.js': '', + // }); + // + // let globs = ['**/project.json']; + // expect(() => getWorkspaceFilesNative(fs.tempDir, globs)).not.toThrow(); + // }); + // }); }); - -const getError = (fn: () => unknown): Error => { - try { - fn(); - } catch (error: unknown) { - return error as Error; - } -}; diff --git a/packages/nx/src/native/utils/path.rs b/packages/nx/src/native/utils/path.rs index eb9edc0e4eea2..15fc00727f596 100644 --- a/packages/nx/src/native/utils/path.rs +++ b/packages/nx/src/native/utils/path.rs @@ -20,6 +20,10 @@ fn normalize_path

(path: P) -> String where P: AsRef, { + if path.as_ref() == Path::new("") { + return ".".into(); + } + // convert back-slashes in Windows paths, since the js expects only forward-slash path separators if cfg!(windows) { path.as_ref().display().to_string().replace('\\', "/") diff --git a/packages/nx/src/native/workspace/get_config_files.rs b/packages/nx/src/native/workspace/get_config_files.rs index 0050611acf8f6..518cc3b60827f 100644 --- a/packages/nx/src/native/workspace/get_config_files.rs +++ b/packages/nx/src/native/workspace/get_config_files.rs @@ -2,29 +2,42 @@ use crate::native::utils::glob::build_glob_set; use crate::native::utils::path::Normalize; use crate::native::walker::nx_walker; use globset::GlobSet; + +use napi::JsObject; use std::collections::hash_map::Entry; use std::collections::HashMap; use std::path::{Path, PathBuf}; #[napi] /// Get workspace config files based on provided globs -pub fn get_config_files(workspace_root: String, globs: Vec) -> anyhow::Result> { +pub fn get_project_configurations( + workspace_root: String, + globs: Vec, + + parse_configurations: ConfigurationParser, +) -> napi::Result> +where + ConfigurationParser: Fn(Vec) -> napi::Result>, +{ let globs = build_glob_set(globs)?; - Ok(nx_walker(workspace_root, move |rec| { - let mut config_paths: HashMap)> = HashMap::new(); - for (path, content) in rec { - insert_config_file_into_map((path, content), &mut config_paths, &globs); + let config_paths: Vec = nx_walker(workspace_root, move |rec| { + let mut config_paths: HashMap = HashMap::new(); + for (path, _) in rec { + insert_config_file_into_map(path, &mut config_paths, &globs); } + config_paths - .into_iter() - .map(|(_, (val, _))| val.to_normalized_string()) + .into_values() + .map(|p| p.to_normalized_string()) .collect() - })) + }); + + parse_configurations(config_paths) } pub fn insert_config_file_into_map( - (path, content): (PathBuf, Vec), - config_paths: &mut HashMap)>, + path: PathBuf, + config_paths: &mut HashMap, globs: &GlobSet, ) { if globs.is_match(&path) { @@ -34,25 +47,24 @@ pub fn insert_config_file_into_map( .file_name() .expect("Config paths always have file names"); if file_name == "project.json" { - config_paths.insert(parent, (path, content)); + config_paths.insert(parent, path); } else if file_name == "package.json" { match config_paths.entry(parent) { Entry::Occupied(mut o) => { if o.get() - .0 .file_name() .expect("Config paths always have file names") != "project.json" { - o.insert((path, content)); + o.insert(path); } } Entry::Vacant(v) => { - v.insert((path, content)); + v.insert(path); } } } else { - config_paths.entry(parent).or_insert((path, content)); + config_paths.entry(parent).or_insert(path); } } } @@ -65,34 +77,23 @@ mod test { #[test] fn should_insert_config_files_properly() { - let mut config_paths: HashMap)> = HashMap::new(); + let mut config_paths: HashMap = HashMap::new(); let globs = build_glob_set(vec!["**/*".into()]).unwrap(); + insert_config_file_into_map(PathBuf::from("project.json"), &mut config_paths, &globs); + insert_config_file_into_map(PathBuf::from("package.json"), &mut config_paths, &globs); insert_config_file_into_map( - (PathBuf::from("project.json"), vec![]), - &mut config_paths, - &globs, - ); - insert_config_file_into_map( - (PathBuf::from("package.json"), vec![]), - &mut config_paths, - &globs, - ); - insert_config_file_into_map( - (PathBuf::from("lib1/project.json"), vec![]), + PathBuf::from("lib1/project.json"), &mut config_paths, &globs, ); insert_config_file_into_map( - (PathBuf::from("lib2/package.json"), vec![]), + PathBuf::from("lib2/package.json"), &mut config_paths, &globs, ); - let config_files: Vec = config_paths - .into_iter() - .map(|(_, (path, _))| path) - .collect(); + let config_files: Vec = config_paths.into_values().collect(); assert!(config_files.contains(&PathBuf::from("project.json"))); assert!(config_files.contains(&PathBuf::from("lib1/project.json"))); diff --git a/packages/nx/src/native/workspace/get_nx_workspace_files.rs b/packages/nx/src/native/workspace/get_nx_workspace_files.rs index b8c6e68b48890..68973833035ad 100644 --- a/packages/nx/src/native/workspace/get_nx_workspace_files.rs +++ b/packages/nx/src/native/workspace/get_nx_workspace_files.rs @@ -1,5 +1,7 @@ -use jsonc_parser::ParseOptions; -use std::collections::HashMap; +use itertools::Itertools; +use napi::threadsafe_function::{ErrorStrategy, ThreadsafeFunction, ThreadsafeFunctionCallMode}; +use napi::{JsFunction, JsObject, JsUnknown, Status}; +use std::collections::{HashMap, HashSet}; use std::path::{Path, PathBuf}; use rayon::prelude::*; @@ -13,21 +15,24 @@ use crate::native::utils::path::Normalize; use crate::native::walker::nx_walker; use crate::native::workspace::errors::{InternalWorkspaceErrors, WorkspaceErrors}; use crate::native::workspace::get_config_files::insert_config_file_into_map; -use crate::native::workspace::types::{FileLocation, ProjectConfiguration}; +use crate::native::workspace::types::FileLocation; #[napi(object)] pub struct NxWorkspaceFiles { pub project_file_map: HashMap>, pub global_files: Vec, - pub config_files: Vec, + pub project_configurations: HashMap, } #[napi] -/// Throws exceptions -pub fn get_workspace_files_native( +pub fn get_workspace_files_native( workspace_root: String, globs: Vec, -) -> napi::Result { + parse_configurations: ConfigurationParser, +) -> napi::Result +where + ConfigurationParser: Fn(Vec) -> napi::Result>, +{ enable_logger(); trace!("{workspace_root}, {globs:?}"); @@ -35,7 +40,12 @@ pub fn get_workspace_files_native( let (projects, mut file_data) = get_file_data(&workspace_root, globs) .map_err(|err| napi::Error::new(WorkspaceErrors::Generic, err.to_string()))?; - let root_map = create_root_map(&projects)?; + let projects_vec: Vec = projects.iter().map(|p| p.to_normalized_string()).collect(); + + let project_configurations = parse_configurations(projects_vec) + .map_err(|e| napi::Error::new(WorkspaceErrors::ParseError, e.to_string()))?; + + let root_map = create_root_map(&project_configurations); trace!(?root_map); @@ -46,14 +56,14 @@ pub fn get_workspace_files_native( .into_par_iter() .map(|file_data| { let file_path = Path::new(&file_data.file); - let mut parent = file_path.parent().unwrap_or_else(|| Path::new("")); + let mut parent = file_path.parent().unwrap_or_else(|| Path::new(".")); - while root_map.get(parent).is_none() && parent != Path::new("") { - parent = parent.parent().unwrap_or_else(|| Path::new("")); + while root_map.get(parent).is_none() && parent != Path::new(".") { + parent = parent.parent().unwrap_or_else(|| Path::new(".")); } match root_map.get(parent) { - Some(project_name) => (FileLocation::Project(project_name.clone()), file_data), + Some(project_name) => (FileLocation::Project(project_name.into()), file_data), None => (FileLocation::Global, file_data), } }) @@ -76,7 +86,7 @@ pub fn get_workspace_files_native( FileLocation::Global => global_files.push(file_data), FileLocation::Project(project_name) => match project_file_map.get_mut(&project_name) { None => { - project_file_map.insert(project_name, vec![file_data]); + project_file_map.insert(project_name.clone(), vec![file_data]); } Some(project_files) => project_files.push(file_data), }, @@ -86,98 +96,34 @@ pub fn get_workspace_files_native( Ok(NxWorkspaceFiles { project_file_map, global_files, - config_files: projects - .keys() - .map(|path| path.to_normalized_string()) - .collect(), + project_configurations, }) } fn create_root_map( - projects: &HashMap>, -) -> Result, InternalWorkspaceErrors> { - projects - .par_iter() - .map(|(path, content)| { - let file_name = path - .file_name() - .expect("path should always have a filename"); - return if file_name == "project.json" || file_name == "package.json" { - // use serde_json to do the initial parse, if that fails fall back to jsonc_parser. - // If all those fail, expose the error from jsonc_parser - let project_configuration: ProjectConfiguration = - read_project_configuration(content, path)?; - - let Some(parent_path) = path.parent() else { - return Err(InternalWorkspaceErrors::Generic { - msg: format!("{path:?} has no parent"), - }) - }; - - let name: String = if let Some(name) = project_configuration.name { - Ok(name) - } else { - parent_path - .file_name() - .unwrap_or_default() - .to_os_string() - .into_string() - .map_err(|os_string| InternalWorkspaceErrors::Generic { - msg: format!("Cannot turn {os_string:?} into String"), - }) - }?; - Ok((parent_path, name)) - } else if let Some(parent_path) = path.parent() { - Ok(( - parent_path, - parent_path - .file_name() - .unwrap_or_default() - .to_os_string() - .into_string() - .map_err(|os_string| InternalWorkspaceErrors::Generic { - msg: format!("Cannot turn {os_string:?} into String"), - })?, - )) - } else { - Err(InternalWorkspaceErrors::Generic { - msg: format!("{path:?} has no parent"), - }) - }; + project_configurations: &HashMap, +) -> hashbrown::HashMap { + project_configurations + .iter() + .map(|(project_name, project_configuration)| { + let root: String = project_configuration.get("root").unwrap().unwrap(); + (PathBuf::from(root), project_name.clone()) }) .collect() } -fn read_project_configuration( - content: &[u8], - path: &Path, -) -> Result { - serde_json::from_slice(content).or_else(|_| { - let content_str = std::str::from_utf8(content).expect("content should be valid utf8"); - let parser_value = - jsonc_parser::parse_to_serde_value(content_str, &ParseOptions::default()).map_err( - |_| InternalWorkspaceErrors::ParseError { - file: PathBuf::from(path), - }, - )?; - serde_json::from_value(parser_value.into()).map_err(|_| InternalWorkspaceErrors::Generic { - msg: format!("Failed to parse {path:?}"), - }) - }) -} - -type WorkspaceData = (HashMap>, Vec); +type WorkspaceData = (HashSet, Vec); fn get_file_data(workspace_root: &str, globs: Vec) -> anyhow::Result { let globs = build_glob_set(globs)?; let (projects, file_data) = nx_walker(workspace_root, move |rec| { - let mut projects: HashMap)> = HashMap::new(); + let mut projects: HashMap = HashMap::new(); let mut file_hashes: Vec = vec![]; for (path, content) in rec { file_hashes.push(FileData { file: path.to_normalized_string(), hash: xxh3::xxh3_64(&content).to_string(), }); - insert_config_file_into_map((path, content), &mut projects, &globs) + insert_config_file_into_map(path, &mut projects, &globs) } (projects, file_hashes) }); diff --git a/packages/nx/src/native/workspace/types.rs b/packages/nx/src/native/workspace/types.rs index 83318cfac7df2..dc460dabcec66 100644 --- a/packages/nx/src/native/workspace/types.rs +++ b/packages/nx/src/native/workspace/types.rs @@ -1,10 +1,3 @@ -use serde::Deserialize; - -#[derive(Debug, Deserialize)] -pub(crate) struct ProjectConfiguration { - pub name: Option, -} - #[derive(Debug, Eq, PartialEq)] pub enum FileLocation { Global, diff --git a/packages/nx/src/project-graph/utils/retrieve-workspace-files.ts b/packages/nx/src/project-graph/utils/retrieve-workspace-files.ts index 8e80439cdba1c..b2df26cd1f039 100644 --- a/packages/nx/src/project-graph/utils/retrieve-workspace-files.ts +++ b/packages/nx/src/project-graph/utils/retrieve-workspace-files.ts @@ -9,14 +9,17 @@ import { import { getNxRequirePaths } from '../../utils/installation-directory'; import { readJsonFile } from '../../utils/fileutils'; import { join } from 'path'; -import { ProjectsConfigurations } from '../../config/workspace-json-project-json'; +import { + ProjectConfiguration, + ProjectsConfigurations, +} from '../../config/workspace-json-project-json'; import { mergeAngularJsonAndProjects, shouldMergeAngularProjects, } from '../../adapter/angular-json'; import { NxJsonConfiguration } from '../../config/nx-json'; import { FileData, ProjectFileMap } from '../../config/project-graph'; -import { NxWorkspaceFiles, WorkspaceErrors } from '../../native'; +import type { NxWorkspaceFiles } from '../../native'; /** * Walks the workspace directory to create the `projectFileMap`, `ProjectConfigurations` and `allWorkspaceFiles` @@ -40,19 +43,21 @@ export async function retrieveWorkspaceFiles( ); performance.mark('get-workspace-files:start'); - let workspaceFiles: NxWorkspaceFiles; - try { - workspaceFiles = getWorkspaceFilesNative(workspaceRoot, globs); - } catch (e) { - // If the error is a parse error from Rust, then use the JS readJsonFile function to write a pretty error message - if (e.code === WorkspaceErrors.ParseError) { - readJsonFile(join(workspaceRoot, e.message)); - // readJsonFile should always fail, but if it doesn't, then throw the original error - throw e; - } else { - throw e; - } - } + + const { projectConfigurations, projectFileMap, globalFiles } = + getWorkspaceFilesNative( + workspaceRoot, + globs, + (configs: string[]): Record => { + const projectConfigurations = createProjectConfigurations( + workspaceRoot, + nxJson, + configs + ); + + return projectConfigurations.projects; + } + ) as NxWorkspaceFiles; performance.mark('get-workspace-files:end'); performance.measure( 'get-workspace-files', @@ -61,16 +66,12 @@ export async function retrieveWorkspaceFiles( ); return { - allWorkspaceFiles: buildAllWorkspaceFiles( - workspaceFiles.projectFileMap, - workspaceFiles.globalFiles - ), - projectFileMap: workspaceFiles.projectFileMap, - projectConfigurations: createProjectConfigurations( - workspaceRoot, - nxJson, - workspaceFiles.configFiles - ), + allWorkspaceFiles: buildAllWorkspaceFiles(projectFileMap, globalFiles), + projectFileMap, + projectConfigurations: { + version: 2, + projects: projectConfigurations, + } as ProjectsConfigurations, }; } @@ -84,10 +85,21 @@ export async function retrieveProjectConfigurations( workspaceRoot: string, nxJson: NxJsonConfiguration ) { - const { getConfigFiles } = require('../../native'); + const { getProjectConfigurations } = require('../../native'); const globs = await configurationGlobs(workspaceRoot, nxJson); - const configPaths = getConfigFiles(workspaceRoot, globs); - return createProjectConfigurations(workspaceRoot, nxJson, configPaths); + return getProjectConfigurations( + workspaceRoot, + globs, + (configs: string[]): Record => { + const projectConfigurations = createProjectConfigurations( + workspaceRoot, + nxJson, + configs + ); + + return projectConfigurations.projects; + } + ); } function buildAllWorkspaceFiles( @@ -123,8 +135,8 @@ function createProjectConfigurations( ); if (shouldMergeAngularProjects(workspaceRoot, false)) { - projectConfigurations.projects = mergeAngularJsonAndProjects( - projectConfigurations.projects, + projectConfigurations = mergeAngularJsonAndProjects( + projectConfigurations, workspaceRoot ); } @@ -135,14 +147,17 @@ function createProjectConfigurations( 'build-project-configs:end' ); - return projectConfigurations; + return { + version: 2, + projects: projectConfigurations, + }; } function mergeTargetDefaultsIntoProjectDescriptions( - config: ProjectsConfigurations, + projects: Record, nxJson: NxJsonConfiguration ) { - for (const proj of Object.values(config.projects)) { + for (const proj of Object.values(projects)) { if (proj.targets) { for (const targetName of Object.keys(proj.targets)) { const projectTargetDefinition = proj.targets[targetName]; @@ -162,7 +177,7 @@ function mergeTargetDefaultsIntoProjectDescriptions( } } } - return config; + return projects; } async function configurationGlobs( From 5a7ffb93c9e84bffbf52f6ae9c6c1e3b8edb9d35 Mon Sep 17 00:00:00 2001 From: FrozenPandaz Date: Fri, 7 Jul 2023 16:10:00 -0400 Subject: [PATCH 034/262] chore(misc): publish 16.6.0-beta.0 --- lerna.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lerna.json b/lerna.json index 9ffc4c43a8b9c..5f0c55164af00 100644 --- a/lerna.json +++ b/lerna.json @@ -1,6 +1,6 @@ { "packages": ["build/packages/*", "build/packages/nx/native-packages/*"], - "version": "16.5.0", + "version": "16.6.0-beta.0", "granularPathspec": false, "command": { "publish": { From 38fa586b78564f1b9b69eea8b11adbdbe45f3fab Mon Sep 17 00:00:00 2001 From: Jack Hsu Date: Fri, 7 Jul 2023 16:17:41 -0400 Subject: [PATCH 035/262] feat(testing): rename jest-project generator to "configuration" generator for consistency in naming (#18006) --- docs/generated/manifests/menus.json | 6 +- docs/generated/manifests/packages.json | 10 +-- docs/generated/packages-metadata.json | 8 +- .../jest/generators/configuration.json | 89 +++++++++++++++++++ docs/shared/reference/sitemap.md | 2 +- nx-dev/nx-dev-e2e/src/e2e/packages.cy.ts | 4 +- nx-dev/nx-dev/redirect-rules.js | 2 + .../application/lib/add-unit-test-runner.ts | 4 +- .../angular/src/generators/library/library.ts | 4 +- packages/expo/src/utils/add-jest.ts | 4 +- packages/jest/generators.json | 12 +-- packages/jest/index.ts | 8 +- .../__snapshots__/configuration.spec.ts.snap} | 0 .../configuration.spec.ts} | 52 +++++------ .../configuration.ts} | 6 +- .../files-angular/jest.config.ts__tmpl__ | 0 .../files-angular/src/test-setup.ts__tmpl__ | 0 .../files-angular/tsconfig.spec.json__tmpl__ | 0 .../files/jest.config.ts__tmpl__ | 0 .../files/src/test-setup.ts__tmpl__ | 0 .../files/tsconfig.spec.json__tmpl__ | 0 .../lib/check-for-test-target.ts | 0 .../lib/create-files.ts | 0 .../lib/update-jestconfig.ts | 0 .../lib/update-tsconfig.ts | 0 .../lib/update-workspace.ts | 0 .../schema.d.ts | 0 .../schema.json | 0 packages/jest/src/generators/init/init.ts | 2 +- packages/js/src/generators/library/library.ts | 4 +- .../workspace-rules-project.ts | 9 +- .../generators/application/lib/add-jest.ts | 4 +- .../src/generators/application/application.ts | 4 +- .../plugin/src/generators/e2e-project/e2e.ts | 4 +- packages/react-native/src/utils/add-jest.ts | 4 +- .../generators/application/lib/add-jest.ts | 4 +- .../react/src/generators/library/library.ts | 4 +- .../src/generators/application/application.ts | 4 +- 38 files changed, 176 insertions(+), 78 deletions(-) create mode 100644 docs/generated/packages/jest/generators/configuration.json rename packages/jest/src/generators/{jest-project/__snapshots__/jest-project.spec.ts.snap => configuration/__snapshots__/configuration.spec.ts.snap} (100%) rename packages/jest/src/generators/{jest-project/jest-project.spec.ts => configuration/configuration.spec.ts} (91%) rename packages/jest/src/generators/{jest-project/jest-project.ts => configuration/configuration.ts} (92%) rename packages/jest/src/generators/{jest-project => configuration}/files-angular/jest.config.ts__tmpl__ (100%) rename packages/jest/src/generators/{jest-project => configuration}/files-angular/src/test-setup.ts__tmpl__ (100%) rename packages/jest/src/generators/{jest-project => configuration}/files-angular/tsconfig.spec.json__tmpl__ (100%) rename packages/jest/src/generators/{jest-project => configuration}/files/jest.config.ts__tmpl__ (100%) rename packages/jest/src/generators/{jest-project => configuration}/files/src/test-setup.ts__tmpl__ (100%) rename packages/jest/src/generators/{jest-project => configuration}/files/tsconfig.spec.json__tmpl__ (100%) rename packages/jest/src/generators/{jest-project => configuration}/lib/check-for-test-target.ts (100%) rename packages/jest/src/generators/{jest-project => configuration}/lib/create-files.ts (100%) rename packages/jest/src/generators/{jest-project => configuration}/lib/update-jestconfig.ts (100%) rename packages/jest/src/generators/{jest-project => configuration}/lib/update-tsconfig.ts (100%) rename packages/jest/src/generators/{jest-project => configuration}/lib/update-workspace.ts (100%) rename packages/jest/src/generators/{jest-project => configuration}/schema.d.ts (100%) rename packages/jest/src/generators/{jest-project => configuration}/schema.json (100%) diff --git a/docs/generated/manifests/menus.json b/docs/generated/manifests/menus.json index f2c0767a352c9..4d33016812df3 100644 --- a/docs/generated/manifests/menus.json +++ b/docs/generated/manifests/menus.json @@ -5174,9 +5174,9 @@ "disableCollapsible": false }, { - "id": "jest-project", - "path": "/packages/jest/generators/jest-project", - "name": "jest-project", + "id": "configuration", + "path": "/packages/jest/generators/configuration", + "name": "configuration", "children": [], "isExternal": false, "disableCollapsible": false diff --git a/docs/generated/manifests/packages.json b/docs/generated/manifests/packages.json index 181b7b7096873..91cae2e2b430a 100644 --- a/docs/generated/manifests/packages.json +++ b/docs/generated/manifests/packages.json @@ -963,13 +963,13 @@ "path": "/packages/jest/generators/init", "type": "generator" }, - "/packages/jest/generators/jest-project": { + "/packages/jest/generators/configuration": { "description": "Add Jest configuration to a project.", - "file": "generated/packages/jest/generators/jest-project.json", + "file": "generated/packages/jest/generators/configuration.json", "hidden": true, - "name": "jest-project", - "originalFilePath": "/packages/jest/src/generators/jest-project/schema.json", - "path": "/packages/jest/generators/jest-project", + "name": "configuration", + "originalFilePath": "/packages/jest/src/generators/configuration/schema.json", + "path": "/packages/jest/generators/configuration", "type": "generator" } }, diff --git a/docs/generated/packages-metadata.json b/docs/generated/packages-metadata.json index e3fe8f5992f7d..5f9aa7a25e503 100644 --- a/docs/generated/packages-metadata.json +++ b/docs/generated/packages-metadata.json @@ -950,11 +950,11 @@ }, { "description": "Add Jest configuration to a project.", - "file": "generated/packages/jest/generators/jest-project.json", + "file": "generated/packages/jest/generators/configuration.json", "hidden": true, - "name": "jest-project", - "originalFilePath": "/packages/jest/src/generators/jest-project/schema.json", - "path": "jest/generators/jest-project", + "name": "configuration", + "originalFilePath": "/packages/jest/src/generators/configuration/schema.json", + "path": "jest/generators/configuration", "type": "generator" } ], diff --git a/docs/generated/packages/jest/generators/configuration.json b/docs/generated/packages/jest/generators/configuration.json new file mode 100644 index 0000000000000..db31c454178e0 --- /dev/null +++ b/docs/generated/packages/jest/generators/configuration.json @@ -0,0 +1,89 @@ +{ + "name": "configuration", + "factory": "./src/generators/configuration/configuration", + "schema": { + "$schema": "http://json-schema.org/schema", + "$id": "NxJestProject", + "cli": "nx", + "title": "Add Jest Configuration to a project", + "description": "Add Jest Configuration to a project.", + "type": "object", + "properties": { + "project": { + "type": "string", + "description": "The name of the project.", + "$default": { "$source": "projectName" }, + "x-priority": "important" + }, + "skipSetupFile": { + "type": "boolean", + "description": "Skips the setup file required for angular.", + "default": false, + "x-deprecated": "Use `--setup-file` instead." + }, + "setupFile": { + "type": "string", + "enum": ["none", "angular", "web-components"], + "description": "The setup file to be generated.", + "default": "none", + "x-priority": "important" + }, + "skipSerializers": { + "type": "boolean", + "description": "Skips the serializers required to snapshot angular templates.", + "default": false + }, + "supportTsx": { + "type": "boolean", + "description": "Setup `tsx` support.", + "default": false, + "x-priority": "important" + }, + "testEnvironment": { + "type": "string", + "enum": ["jsdom", "node", "none"], + "description": "The test environment for jest.", + "default": "jsdom", + "x-priority": "important" + }, + "compiler": { + "type": "string", + "enum": ["tsc", "babel", "swc"], + "description": "The compiler to use for source and tests.", + "default": "tsc" + }, + "babelJest": { + "type": "boolean", + "alias": "babel-jest", + "description": "Use `babel-jest` instead of `ts-jest`.", + "x-deprecated": "Use `--compiler=babel` instead.", + "default": false + }, + "skipFormat": { + "description": "Skip formatting files", + "type": "boolean", + "default": false, + "x-priority": "internal" + }, + "skipPackageJson": { + "type": "boolean", + "default": false, + "description": "Do not add dependencies to `package.json`.", + "x-priority": "internal" + }, + "js": { + "type": "boolean", + "default": false, + "description": "Use JavaScript instead of TypeScript for config files" + } + }, + "required": [], + "presets": [] + }, + "description": "Add Jest configuration to a project.", + "hidden": true, + "implementation": "/packages/jest/src/generators/configuration/configuration.ts", + "aliases": [], + "path": "/packages/jest/src/generators/configuration/schema.json", + "type": "generator" +} diff --git a/docs/shared/reference/sitemap.md b/docs/shared/reference/sitemap.md index 0eb10dc024c61..895f7a1b6952b 100644 --- a/docs/shared/reference/sitemap.md +++ b/docs/shared/reference/sitemap.md @@ -393,7 +393,7 @@ - [jest](/packages/jest/executors/jest) - [generators](/packages/jest/generators) - [init](/packages/jest/generators/init) - - [jest-project](/packages/jest/generators/jest-project) + - [configuration](/packages/jest/generators/configuration) - [js](/packages/js) - [documents](/packages/js/documents) - [Overview](/packages/js/documents/overview) diff --git a/nx-dev/nx-dev-e2e/src/e2e/packages.cy.ts b/nx-dev/nx-dev-e2e/src/e2e/packages.cy.ts index 09fabfffe0ebe..e3cccf8da9764 100644 --- a/nx-dev/nx-dev-e2e/src/e2e/packages.cy.ts +++ b/nx-dev/nx-dev-e2e/src/e2e/packages.cy.ts @@ -164,8 +164,8 @@ describe('nx-dev: Packages Section', () => { { title: '@nx/jest', path: '/packages/jest' }, { title: '@nx/jest:init', path: '/packages/jest/generators/init' }, { - title: '@nx/jest:jest-project', - path: '/packages/jest/generators/jest-project', + title: '@nx/jest:configuration', + path: '/packages/jest/generators/configuration', }, { title: '@nx/jest', path: '/packages/jest/executors/jest' }, { title: '@nx/js', path: '/packages/js' }, diff --git a/nx-dev/nx-dev/redirect-rules.js b/nx-dev/nx-dev/redirect-rules.js index 7dd284e779c90..79d9530b58561 100644 --- a/nx-dev/nx-dev/redirect-rules.js +++ b/nx-dev/nx-dev/redirect-rules.js @@ -150,6 +150,8 @@ const schemaUrls = { '/packages/cypress/generators/component-configuration', '/packages/esbuild/generators/esbuild-project': '/packages/esbuild/generators/configuration', + '/packages/jest/generators/jest-project': + '/packages/jest/generators/configuration', '/packages/nx-plugin/generators/executor': '/packages/plugin/generators/executor', '/packages/nx-plugin/generators/migration': diff --git a/packages/angular/src/generators/application/lib/add-unit-test-runner.ts b/packages/angular/src/generators/application/lib/add-unit-test-runner.ts index f48d1cadfe855..165082806e93d 100644 --- a/packages/angular/src/generators/application/lib/add-unit-test-runner.ts +++ b/packages/angular/src/generators/application/lib/add-unit-test-runner.ts @@ -1,13 +1,13 @@ import { Tree, joinPathFragments } from '@nx/devkit'; import type { NormalizedSchema } from './normalized-schema'; -import { jestProjectGenerator } from '@nx/jest'; +import { configurationGenerator } from '@nx/jest'; import { UnitTestRunner } from '../../../utils/test-runners'; export async function addUnitTestRunner(host: Tree, options: NormalizedSchema) { if (options.unitTestRunner === UnitTestRunner.Jest) { - await jestProjectGenerator(host, { + await configurationGenerator(host, { project: options.name, setupFile: 'angular', supportTsx: false, diff --git a/packages/angular/src/generators/library/library.ts b/packages/angular/src/generators/library/library.ts index 8fe9f0f5567c1..69ca86e3b8a8c 100644 --- a/packages/angular/src/generators/library/library.ts +++ b/packages/angular/src/generators/library/library.ts @@ -5,7 +5,7 @@ import { joinPathFragments, Tree, } from '@nx/devkit'; -import { jestProjectGenerator } from '@nx/jest'; +import { configurationGenerator } from '@nx/jest'; import { Linter } from '@nx/linter'; import { addTsConfigPath } from '@nx/js'; import { lt } from 'semver'; @@ -124,7 +124,7 @@ async function addUnitTestRunner( options: NormalizedSchema['libraryOptions'] ) { if (options.unitTestRunner === 'jest') { - await jestProjectGenerator(host, { + await configurationGenerator(host, { project: options.name, setupFile: 'angular', supportTsx: false, diff --git a/packages/expo/src/utils/add-jest.ts b/packages/expo/src/utils/add-jest.ts index 5e225f5f6a776..418e3ea2c3c62 100644 --- a/packages/expo/src/utils/add-jest.ts +++ b/packages/expo/src/utils/add-jest.ts @@ -1,5 +1,5 @@ import { Tree } from '@nx/devkit'; -import { jestProjectGenerator } from '@nx/jest'; +import { configurationGenerator } from '@nx/jest'; export async function addJest( host: Tree, @@ -13,7 +13,7 @@ export async function addJest( return () => {}; } - const jestTask = await jestProjectGenerator(host, { + const jestTask = await configurationGenerator(host, { js, project: projectName, supportTsx: true, diff --git a/packages/jest/generators.json b/packages/jest/generators.json index d296c1db5f5ce..62fe83c0ccffd 100644 --- a/packages/jest/generators.json +++ b/packages/jest/generators.json @@ -9,9 +9,9 @@ "aliases": ["ng-add"], "hidden": true }, - "jest-project": { - "factory": "./src/generators/jest-project/jest-project#jestProjectSchematic", - "schema": "./src/generators/jest-project/schema.json", + "configuration": { + "factory": "./src/generators/configuration/configuration#compat", + "schema": "./src/generators/configuration/schema.json", "description": "Add Jest configuration to a project.", "hidden": true } @@ -24,9 +24,9 @@ "aliases": ["ng-add"], "hidden": true }, - "jest-project": { - "factory": "./src/generators/jest-project/jest-project#jestProjectGenerator", - "schema": "./src/generators/jest-project/schema.json", + "configuration": { + "factory": "./src/generators/configuration/configuration", + "schema": "./src/generators/configuration/schema.json", "description": "Add Jest configuration to a project.", "hidden": true } diff --git a/packages/jest/index.ts b/packages/jest/index.ts index 7f78752ba1555..19f5482a69b27 100644 --- a/packages/jest/index.ts +++ b/packages/jest/index.ts @@ -1,9 +1,15 @@ +import { configurationGenerator } from './src/generators/configuration/configuration'; +export { configurationGenerator }; + +// Exported for backwards compatibility in case a plugin is using the old name. +/** @deprecated Use `configurationGenerator` instead. */ +export const jestProjectGenerator = configurationGenerator; + export { addPropertyToJestConfig, removePropertyFromJestConfig, } from './src/utils/config/update-config'; export { jestConfigObjectAst } from './src/utils/config/functions'; -export { jestProjectGenerator } from './src/generators/jest-project/jest-project'; export { jestInitGenerator } from './src/generators/init/init'; export { getJestProjects, diff --git a/packages/jest/src/generators/jest-project/__snapshots__/jest-project.spec.ts.snap b/packages/jest/src/generators/configuration/__snapshots__/configuration.spec.ts.snap similarity index 100% rename from packages/jest/src/generators/jest-project/__snapshots__/jest-project.spec.ts.snap rename to packages/jest/src/generators/configuration/__snapshots__/configuration.spec.ts.snap diff --git a/packages/jest/src/generators/jest-project/jest-project.spec.ts b/packages/jest/src/generators/configuration/configuration.spec.ts similarity index 91% rename from packages/jest/src/generators/jest-project/jest-project.spec.ts rename to packages/jest/src/generators/configuration/configuration.spec.ts index 85a83f089a2ec..7735f9bad8ba7 100644 --- a/packages/jest/src/generators/jest-project/jest-project.spec.ts +++ b/packages/jest/src/generators/configuration/configuration.spec.ts @@ -8,7 +8,7 @@ import { import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; import { jestConfigObject } from '../../utils/config/functions'; -import { jestProjectGenerator } from './jest-project'; +import configurationGenerator from './configuration'; import { JestProjectSchema } from './schema.d'; describe('jestProject', () => { @@ -45,7 +45,7 @@ describe('jestProject', () => { }); it('should generate files', async () => { - await jestProjectGenerator(tree, { + await configurationGenerator(tree, { ...defaultOptions, project: 'lib1', setupFile: 'angular', @@ -61,7 +61,7 @@ describe('jestProject', () => { }); it('should alter project configuration', async () => { - await jestProjectGenerator(tree, { + await configurationGenerator(tree, { ...defaultOptions, project: 'lib1', setupFile: 'angular', @@ -87,7 +87,7 @@ describe('jestProject', () => { }); it('should create a jest.config.ts', async () => { - await jestProjectGenerator(tree, { + await configurationGenerator(tree, { ...defaultOptions, project: 'lib1', } as JestProjectSchema); @@ -95,7 +95,7 @@ describe('jestProject', () => { }); it('should add a reference to solution tsconfig.json', async () => { - await jestProjectGenerator(tree, { + await configurationGenerator(tree, { ...defaultOptions, project: 'lib1', } as JestProjectSchema); @@ -106,7 +106,7 @@ describe('jestProject', () => { }); it('should create a tsconfig.spec.json', async () => { - await jestProjectGenerator(tree, { + await configurationGenerator(tree, { ...defaultOptions, project: 'lib1', setupFile: 'angular', @@ -132,7 +132,7 @@ describe('jestProject', () => { describe('--setup-file', () => { it('should generate src/test-setup.ts', async () => { - await jestProjectGenerator(tree, { + await configurationGenerator(tree, { ...defaultOptions, project: 'lib1', } as JestProjectSchema); @@ -143,7 +143,7 @@ describe('jestProject', () => { }); it('should have setupFilesAfterEnv in the jest.config when generated for web-components', async () => { - await jestProjectGenerator(tree, { + await configurationGenerator(tree, { ...defaultOptions, project: 'lib1', setupFile: 'web-components', @@ -154,7 +154,7 @@ describe('jestProject', () => { }); it('should have setupFilesAfterEnv and globals.ts-jest in the jest.config when generated for angular', async () => { - await jestProjectGenerator(tree, { + await configurationGenerator(tree, { ...defaultOptions, project: 'lib1', setupFile: 'angular', @@ -168,7 +168,7 @@ describe('jestProject', () => { }); it('should not list the setup file in project configuration', async () => { - await jestProjectGenerator(tree, { + await configurationGenerator(tree, { ...defaultOptions, project: 'lib1', setupFile: 'none', @@ -178,7 +178,7 @@ describe('jestProject', () => { }); it('should not list the setup file in tsconfig.spec.json', async () => { - await jestProjectGenerator(tree, { + await configurationGenerator(tree, { ...defaultOptions, project: 'lib1', setupFile: 'none', @@ -190,7 +190,7 @@ describe('jestProject', () => { describe('--skip-setup-file', () => { it('should generate src/test-setup.ts', async () => { - await jestProjectGenerator(tree, { + await configurationGenerator(tree, { ...defaultOptions, project: 'lib1', skipSetupFile: true, @@ -199,7 +199,7 @@ describe('jestProject', () => { }); it('should not list the setup file in project configuration', async () => { - await jestProjectGenerator(tree, { + await configurationGenerator(tree, { ...defaultOptions, project: 'lib1', skipSetupFile: true, @@ -209,7 +209,7 @@ describe('jestProject', () => { }); it('should not list the setup file in tsconfig.spec.json', async () => { - await jestProjectGenerator(tree, { + await configurationGenerator(tree, { ...defaultOptions, project: 'lib1', skipSetupFile: true, @@ -221,7 +221,7 @@ describe('jestProject', () => { describe('--skip-serializers', () => { it('should not list the serializers in jest.config.ts', async () => { - await jestProjectGenerator(tree, { + await configurationGenerator(tree, { ...defaultOptions, project: 'lib1', skipSerializers: true, @@ -239,7 +239,7 @@ describe('jestProject', () => { describe('--support-tsx', () => { it('should add jest.transform', async () => { - await jestProjectGenerator(tree, { + await configurationGenerator(tree, { ...defaultOptions, project: 'lib1', supportTsx: true, @@ -254,7 +254,7 @@ describe('jestProject', () => { }); it('should add tsx to moduleExtensions', async () => { - await jestProjectGenerator(tree, { + await configurationGenerator(tree, { ...defaultOptions, project: 'lib1', supportTsx: true, @@ -270,7 +270,7 @@ describe('jestProject', () => { }); it('should create jest.config.js with --js flag', async () => { - await jestProjectGenerator(tree, { + await configurationGenerator(tree, { ...defaultOptions, project: 'lib1', js: true, @@ -284,7 +284,7 @@ describe('jestProject', () => { }); it('should use jest.config.js in project config with --js flag', async () => { - await jestProjectGenerator(tree, { + await configurationGenerator(tree, { ...defaultOptions, project: 'lib1', js: true, @@ -297,7 +297,7 @@ describe('jestProject', () => { it('should always use jest.preset.js with --js', async () => { tree.write('jest.preset.ts', ''); - await jestProjectGenerator(tree, { + await configurationGenerator(tree, { ...defaultOptions, project: 'lib1', js: true, @@ -309,7 +309,7 @@ describe('jestProject', () => { }); it('should use module.exports with --js flag', async () => { - await jestProjectGenerator(tree, { + await configurationGenerator(tree, { ...defaultOptions, project: 'lib1', js: true, @@ -322,7 +322,7 @@ describe('jestProject', () => { describe('--babelJest', () => { it('should generate proper jest.transform when babelJest is true', async () => { - await jestProjectGenerator(tree, { + await configurationGenerator(tree, { ...defaultOptions, project: 'lib1', babelJest: true, @@ -338,7 +338,7 @@ describe('jestProject', () => { }); it('should generate proper jest.transform when babelJest and supportTsx is true', async () => { - await jestProjectGenerator(tree, { + await configurationGenerator(tree, { ...defaultOptions, project: 'lib1', babelJest: true, @@ -348,7 +348,7 @@ describe('jestProject', () => { }); it('should generate proper jest.transform when --compiler=swc and supportTsx is true', async () => { - await jestProjectGenerator(tree, { + await configurationGenerator(tree, { ...defaultOptions, project: 'lib1', compiler: 'swc', @@ -371,7 +371,7 @@ describe('jestProject', () => { name: 'my-project', targets: {}, }); - await jestProjectGenerator(tree, { + await configurationGenerator(tree, { ...defaultOptions, project: 'my-project', }); @@ -402,7 +402,7 @@ describe('jestProject', () => { name: 'my-project', targets: {}, }); - await jestProjectGenerator(tree, { + await configurationGenerator(tree, { ...defaultOptions, project: 'my-project', js: true, diff --git a/packages/jest/src/generators/jest-project/jest-project.ts b/packages/jest/src/generators/configuration/configuration.ts similarity index 92% rename from packages/jest/src/generators/jest-project/jest-project.ts rename to packages/jest/src/generators/configuration/configuration.ts index 4c772b10e560f..048c237a9c217 100644 --- a/packages/jest/src/generators/jest-project/jest-project.ts +++ b/packages/jest/src/generators/configuration/configuration.ts @@ -56,7 +56,7 @@ function normalizeOptions( }; } -export async function jestProjectGenerator( +export async function configurationGenerator( tree: Tree, schema: JestProjectSchema ): Promise { @@ -74,4 +74,6 @@ export async function jestProjectGenerator( return installTask; } -export const jestProjectSchematic = convertNxGenerator(jestProjectGenerator); +export default configurationGenerator; + +export const compat = convertNxGenerator(configurationGenerator); diff --git a/packages/jest/src/generators/jest-project/files-angular/jest.config.ts__tmpl__ b/packages/jest/src/generators/configuration/files-angular/jest.config.ts__tmpl__ similarity index 100% rename from packages/jest/src/generators/jest-project/files-angular/jest.config.ts__tmpl__ rename to packages/jest/src/generators/configuration/files-angular/jest.config.ts__tmpl__ diff --git a/packages/jest/src/generators/jest-project/files-angular/src/test-setup.ts__tmpl__ b/packages/jest/src/generators/configuration/files-angular/src/test-setup.ts__tmpl__ similarity index 100% rename from packages/jest/src/generators/jest-project/files-angular/src/test-setup.ts__tmpl__ rename to packages/jest/src/generators/configuration/files-angular/src/test-setup.ts__tmpl__ diff --git a/packages/jest/src/generators/jest-project/files-angular/tsconfig.spec.json__tmpl__ b/packages/jest/src/generators/configuration/files-angular/tsconfig.spec.json__tmpl__ similarity index 100% rename from packages/jest/src/generators/jest-project/files-angular/tsconfig.spec.json__tmpl__ rename to packages/jest/src/generators/configuration/files-angular/tsconfig.spec.json__tmpl__ diff --git a/packages/jest/src/generators/jest-project/files/jest.config.ts__tmpl__ b/packages/jest/src/generators/configuration/files/jest.config.ts__tmpl__ similarity index 100% rename from packages/jest/src/generators/jest-project/files/jest.config.ts__tmpl__ rename to packages/jest/src/generators/configuration/files/jest.config.ts__tmpl__ diff --git a/packages/jest/src/generators/jest-project/files/src/test-setup.ts__tmpl__ b/packages/jest/src/generators/configuration/files/src/test-setup.ts__tmpl__ similarity index 100% rename from packages/jest/src/generators/jest-project/files/src/test-setup.ts__tmpl__ rename to packages/jest/src/generators/configuration/files/src/test-setup.ts__tmpl__ diff --git a/packages/jest/src/generators/jest-project/files/tsconfig.spec.json__tmpl__ b/packages/jest/src/generators/configuration/files/tsconfig.spec.json__tmpl__ similarity index 100% rename from packages/jest/src/generators/jest-project/files/tsconfig.spec.json__tmpl__ rename to packages/jest/src/generators/configuration/files/tsconfig.spec.json__tmpl__ diff --git a/packages/jest/src/generators/jest-project/lib/check-for-test-target.ts b/packages/jest/src/generators/configuration/lib/check-for-test-target.ts similarity index 100% rename from packages/jest/src/generators/jest-project/lib/check-for-test-target.ts rename to packages/jest/src/generators/configuration/lib/check-for-test-target.ts diff --git a/packages/jest/src/generators/jest-project/lib/create-files.ts b/packages/jest/src/generators/configuration/lib/create-files.ts similarity index 100% rename from packages/jest/src/generators/jest-project/lib/create-files.ts rename to packages/jest/src/generators/configuration/lib/create-files.ts diff --git a/packages/jest/src/generators/jest-project/lib/update-jestconfig.ts b/packages/jest/src/generators/configuration/lib/update-jestconfig.ts similarity index 100% rename from packages/jest/src/generators/jest-project/lib/update-jestconfig.ts rename to packages/jest/src/generators/configuration/lib/update-jestconfig.ts diff --git a/packages/jest/src/generators/jest-project/lib/update-tsconfig.ts b/packages/jest/src/generators/configuration/lib/update-tsconfig.ts similarity index 100% rename from packages/jest/src/generators/jest-project/lib/update-tsconfig.ts rename to packages/jest/src/generators/configuration/lib/update-tsconfig.ts diff --git a/packages/jest/src/generators/jest-project/lib/update-workspace.ts b/packages/jest/src/generators/configuration/lib/update-workspace.ts similarity index 100% rename from packages/jest/src/generators/jest-project/lib/update-workspace.ts rename to packages/jest/src/generators/configuration/lib/update-workspace.ts diff --git a/packages/jest/src/generators/jest-project/schema.d.ts b/packages/jest/src/generators/configuration/schema.d.ts similarity index 100% rename from packages/jest/src/generators/jest-project/schema.d.ts rename to packages/jest/src/generators/configuration/schema.d.ts diff --git a/packages/jest/src/generators/jest-project/schema.json b/packages/jest/src/generators/configuration/schema.json similarity index 100% rename from packages/jest/src/generators/jest-project/schema.json rename to packages/jest/src/generators/configuration/schema.json diff --git a/packages/jest/src/generators/init/init.ts b/packages/jest/src/generators/init/init.ts index 134171892fde0..6dd9e21ce856e 100644 --- a/packages/jest/src/generators/init/init.ts +++ b/packages/jest/src/generators/init/init.ts @@ -68,7 +68,7 @@ function createJestConfig(tree: Tree, options: NormalizedSchema) { addTestInputs(tree); } if (options.rootProject) { - // we don't want any config to be made because the `jestProjectGenerator` + // we don't want any config to be made because the `configurationGenerator` will do it. // will copy the template config file return; } diff --git a/packages/js/src/generators/library/library.ts b/packages/js/src/generators/library/library.ts index 83fa5f47b7ade..72fca66b35a0e 100644 --- a/packages/js/src/generators/library/library.ts +++ b/packages/js/src/generators/library/library.ts @@ -366,8 +366,8 @@ async function addJest( tree: Tree, options: NormalizedSchema ): Promise { - const { jestProjectGenerator } = ensurePackage('@nx/jest', nxVersion); - return await jestProjectGenerator(tree, { + const { configurationGenerator } = ensurePackage('@nx/jest', nxVersion); + return await configurationGenerator(tree, { ...options, project: options.name, setupFile: 'none', diff --git a/packages/linter/src/generators/workspace-rules-project/workspace-rules-project.ts b/packages/linter/src/generators/workspace-rules-project/workspace-rules-project.ts index 0261cf7c4a42a..19f66980e7813 100644 --- a/packages/linter/src/generators/workspace-rules-project/workspace-rules-project.ts +++ b/packages/linter/src/generators/workspace-rules-project/workspace-rules-project.ts @@ -30,10 +30,9 @@ export async function lintWorkspaceRulesProjectGenerator( tree: Tree, options: LintWorkspaceRulesProjectGeneratorOptions = {} ) { - const { addPropertyToJestConfig, jestProjectGenerator } = ensurePackage( - '@nx/jest', - nxVersion - ); + const { addPropertyToJestConfig, configurationGenerator } = ensurePackage< + typeof import('@nx/jest') + >('@nx/jest', nxVersion); // Noop if the workspace rules project already exists try { @@ -70,7 +69,7 @@ export async function lintWorkspaceRulesProjectGenerator( } // Add jest to the project and return installation task - const installTask = await jestProjectGenerator(tree, { + const installTask = await configurationGenerator(tree, { project: WORKSPACE_RULES_PROJECT_NAME, supportTsx: false, skipSerializers: true, diff --git a/packages/next/src/generators/application/lib/add-jest.ts b/packages/next/src/generators/application/lib/add-jest.ts index 4042f1df0eccf..8aeb691acdd23 100644 --- a/packages/next/src/generators/application/lib/add-jest.ts +++ b/packages/next/src/generators/application/lib/add-jest.ts @@ -14,11 +14,11 @@ export async function addJest(host: Tree, options: NormalizedSchema) { return () => {}; } - const { jestProjectGenerator } = ensurePackage( + const { configurationGenerator } = ensurePackage( '@nx/jest', nxVersion ); - const jestTask = await jestProjectGenerator(host, { + const jestTask = await configurationGenerator(host, { ...options, project: options.projectName, supportTsx: true, diff --git a/packages/node/src/generators/application/application.ts b/packages/node/src/generators/application/application.ts index 2dd541d4821ff..cb9ff86aac9f1 100644 --- a/packages/node/src/generators/application/application.ts +++ b/packages/node/src/generators/application/application.ts @@ -23,7 +23,7 @@ import { updateTsConfigsToJs, } from '@nx/devkit'; import { Linter, lintProjectGenerator } from '@nx/linter'; -import { jestProjectGenerator } from '@nx/jest'; +import { configurationGenerator } from '@nx/jest'; import { getRelativePathToRootTsConfig, tsConfigBaseOptions } from '@nx/js'; import { join } from 'path'; @@ -391,7 +391,7 @@ export async function applicationGenerator(tree: Tree, schema: Schema) { } if (options.unitTestRunner === 'jest') { - const jestTask = await jestProjectGenerator(tree, { + const jestTask = await configurationGenerator(tree, { ...options, project: options.name, setupFile: 'none', diff --git a/packages/plugin/src/generators/e2e-project/e2e.ts b/packages/plugin/src/generators/e2e-project/e2e.ts index bbe6e4e45d59c..6773b9bf95885 100644 --- a/packages/plugin/src/generators/e2e-project/e2e.ts +++ b/packages/plugin/src/generators/e2e-project/e2e.ts @@ -16,7 +16,7 @@ import { runTasksInSerial, updateProjectConfiguration, } from '@nx/devkit'; -import { addPropertyToJestConfig, jestProjectGenerator } from '@nx/jest'; +import { addPropertyToJestConfig, configurationGenerator } from '@nx/jest'; import { getRelativePathToRootTsConfig } from '@nx/js'; import { setupVerdaccio } from '@nx/js/src/generators/setup-verdaccio/generator'; import { addLocalRegistryScripts } from '@nx/js/src/utils/add-local-registry-scripts'; @@ -93,7 +93,7 @@ async function addJest(host: Tree, options: NormalizedSchema) { implicitDependencies: [options.pluginName], }); - const jestTask = await jestProjectGenerator(host, { + const jestTask = await configurationGenerator(host, { project: options.projectName, setupFile: 'none', supportTsx: false, diff --git a/packages/react-native/src/utils/add-jest.ts b/packages/react-native/src/utils/add-jest.ts index 2d7af82123970..ab38c72bb16fb 100644 --- a/packages/react-native/src/utils/add-jest.ts +++ b/packages/react-native/src/utils/add-jest.ts @@ -1,5 +1,5 @@ import { Tree } from '@nx/devkit'; -import { jestProjectGenerator } from '@nx/jest'; +import { configurationGenerator } from '@nx/jest'; export async function addJest( host: Tree, @@ -13,7 +13,7 @@ export async function addJest( return () => {}; } - const jestTask = await jestProjectGenerator(host, { + const jestTask = await configurationGenerator(host, { js, project: projectName, supportTsx: true, diff --git a/packages/react/src/generators/application/lib/add-jest.ts b/packages/react/src/generators/application/lib/add-jest.ts index 7773a009e7a5e..f42de9590e4a0 100644 --- a/packages/react/src/generators/application/lib/add-jest.ts +++ b/packages/react/src/generators/application/lib/add-jest.ts @@ -6,7 +6,7 @@ export async function addJest( host: Tree, options: NormalizedSchema ): Promise { - const { jestProjectGenerator } = ensurePackage( + const { configurationGenerator } = ensurePackage( '@nx/jest', nxVersion ); @@ -15,7 +15,7 @@ export async function addJest( return () => {}; } - return await jestProjectGenerator(host, { + return await configurationGenerator(host, { ...options, project: options.projectName, supportTsx: true, diff --git a/packages/react/src/generators/library/library.ts b/packages/react/src/generators/library/library.ts index aafcc6f1fa63f..4764a2f10da3e 100644 --- a/packages/react/src/generators/library/library.ts +++ b/packages/react/src/generators/library/library.ts @@ -84,12 +84,12 @@ export async function libraryGenerator(host: Tree, schema: Schema) { // Set up test target if (options.unitTestRunner === 'jest') { - const { jestProjectGenerator } = ensurePackage( + const { configurationGenerator } = ensurePackage( '@nx/jest', nxVersion ); - const jestTask = await jestProjectGenerator(host, { + const jestTask = await configurationGenerator(host, { ...options, project: options.name, setupFile: 'none', diff --git a/packages/web/src/generators/application/application.ts b/packages/web/src/generators/application/application.ts index cf93df96c9d1f..d839f2893cf3e 100644 --- a/packages/web/src/generators/application/application.ts +++ b/packages/web/src/generators/application/application.ts @@ -273,10 +273,10 @@ export async function applicationGenerator(host: Tree, schema: Schema) { tasks.push(cypressTask); } if (options.unitTestRunner === 'jest') { - const { jestProjectGenerator } = await ensurePackage< + const { configurationGenerator } = await ensurePackage< typeof import('@nx/jest') >('@nx/jest', nxVersion); - const jestTask = await jestProjectGenerator(host, { + const jestTask = await configurationGenerator(host, { project: options.projectName, skipSerializers: true, setupFile: 'web-components', From 6bf3dc91ad4e145cd920e854aba8f907d368a1b4 Mon Sep 17 00:00:00 2001 From: Julius Osokinas <20243687+josokinas@users.noreply.github.com> Date: Mon, 10 Jul 2023 13:42:59 +0300 Subject: [PATCH 036/262] feat(vite): server executor `https` prop as object (#18048) Co-authored-by: Julius Osokinas --- .../generated/packages/vite/executors/dev-server.json | 5 ++++- .../packages/vite/executors/preview-server.json | 5 ++++- packages/vite/src/executors/dev-server/schema.d.ts | 2 +- packages/vite/src/executors/dev-server/schema.json | 11 +++++++++-- .../vite/src/executors/preview-server/schema.d.ts | 2 +- .../vite/src/executors/preview-server/schema.json | 11 +++++++++-- 6 files changed, 28 insertions(+), 8 deletions(-) diff --git a/docs/generated/packages/vite/executors/dev-server.json b/docs/generated/packages/vite/executors/dev-server.json index 3c8f4707a752c..9c25f72d7e9af 100644 --- a/docs/generated/packages/vite/executors/dev-server.json +++ b/docs/generated/packages/vite/executors/dev-server.json @@ -37,7 +37,10 @@ "description": "Specify which IP addresses the server should listen on.", "oneOf": [{ "type": "boolean" }, { "type": "string" }] }, - "https": { "type": "boolean", "description": "Serve using HTTPS." }, + "https": { + "oneOf": [{ "type": "boolean" }, { "type": "object" }], + "description": "Serve using HTTPS. https://vitejs.dev/config/server-options.html#server-https" + }, "hmr": { "description": "Enable hot module replacement. For more options, use the 'hmr' option in the Vite configuration file.", "type": "boolean" diff --git a/docs/generated/packages/vite/executors/preview-server.json b/docs/generated/packages/vite/executors/preview-server.json index e52f409a5af9f..00eb6fcbd30be 100644 --- a/docs/generated/packages/vite/executors/preview-server.json +++ b/docs/generated/packages/vite/executors/preview-server.json @@ -27,7 +27,10 @@ "description": "Specify which IP addresses the server should listen on.", "oneOf": [{ "type": "boolean" }, { "type": "string" }] }, - "https": { "type": "boolean", "description": "Serve using HTTPS." }, + "https": { + "oneOf": [{ "type": "boolean" }, { "type": "object" }], + "description": "Serve using HTTPS. https://vitejs.dev/config/server-options.html#server-https" + }, "open": { "description": "Automatically open the app in the browser on server start. When the value is a string, it will be used as the URL's pathname.", "oneOf": [{ "type": "boolean" }, { "type": "string" }] diff --git a/packages/vite/src/executors/dev-server/schema.d.ts b/packages/vite/src/executors/dev-server/schema.d.ts index 533ab792ab878..f022f090519a0 100644 --- a/packages/vite/src/executors/dev-server/schema.d.ts +++ b/packages/vite/src/executors/dev-server/schema.d.ts @@ -4,7 +4,7 @@ export interface ViteDevServerExecutorOptions { proxyConfig?: string; port?: number; host?: string | boolean; - https?: boolean; + https?: boolean | Json; hmr?: boolean; open?: string | boolean; cors?: boolean; diff --git a/packages/vite/src/executors/dev-server/schema.json b/packages/vite/src/executors/dev-server/schema.json index a011c21bc01e2..53d5a7ca82c6e 100644 --- a/packages/vite/src/executors/dev-server/schema.json +++ b/packages/vite/src/executors/dev-server/schema.json @@ -48,8 +48,15 @@ ] }, "https": { - "type": "boolean", - "description": "Serve using HTTPS." + "oneOf": [ + { + "type": "boolean" + }, + { + "type": "object" + } + ], + "description": "Serve using HTTPS. https://vitejs.dev/config/server-options.html#server-https" }, "hmr": { "description": "Enable hot module replacement. For more options, use the 'hmr' option in the Vite configuration file.", diff --git a/packages/vite/src/executors/preview-server/schema.d.ts b/packages/vite/src/executors/preview-server/schema.d.ts index 5266f8ee8f3e6..af222aa7bfec9 100644 --- a/packages/vite/src/executors/preview-server/schema.d.ts +++ b/packages/vite/src/executors/preview-server/schema.d.ts @@ -3,7 +3,7 @@ export interface VitePreviewServerExecutorOptions { proxyConfig?: string; port?: number; host?: string | boolean; - https?: boolean; + https?: boolean | Json; open?: string | boolean; logLevel?: 'info' | 'warn' | 'error' | 'silent'; mode?: string; diff --git a/packages/vite/src/executors/preview-server/schema.json b/packages/vite/src/executors/preview-server/schema.json index e90856589be7f..24e6e9cf1988f 100644 --- a/packages/vite/src/executors/preview-server/schema.json +++ b/packages/vite/src/executors/preview-server/schema.json @@ -41,8 +41,15 @@ ] }, "https": { - "type": "boolean", - "description": "Serve using HTTPS." + "oneOf": [ + { + "type": "boolean" + }, + { + "type": "object" + } + ], + "description": "Serve using HTTPS. https://vitejs.dev/config/server-options.html#server-https" }, "open": { "description": "Automatically open the app in the browser on server start. When the value is a string, it will be used as the URL's pathname.", From 878955b50da6fe5485281da8036ca968ca2435b6 Mon Sep 17 00:00:00 2001 From: Katerina Skroumpelou Date: Mon, 10 Jul 2023 14:03:57 +0300 Subject: [PATCH 037/262] fix(storybook): dont throw if no project-level tsconfig (#18027) --- .../src/generators/configuration/lib/util-functions.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/storybook/src/generators/configuration/lib/util-functions.ts b/packages/storybook/src/generators/configuration/lib/util-functions.ts index 0b46fcd9220f8..5aa9d786bf7a8 100644 --- a/packages/storybook/src/generators/configuration/lib/util-functions.ts +++ b/packages/storybook/src/generators/configuration/lib/util-functions.ts @@ -675,7 +675,7 @@ export function renameAndMoveOldTsConfig( pathToStorybookConfigFile: string, tree: Tree ) { - if (pathToStorybookConfigFile) { + if (pathToStorybookConfigFile && tree.exists(pathToStorybookConfigFile)) { updateJson(tree, pathToStorybookConfigFile, (json) => { if (json.extends?.startsWith('../')) { // drop one level of nesting @@ -718,6 +718,11 @@ export function renameAndMoveOldTsConfig( } const projectTsConfig = joinPathFragments(projectRoot, 'tsconfig.json'); + + if (!tree.exists(projectTsConfig)) { + return; + } + updateJson(tree, projectTsConfig, (json) => { for (let i = 0; i < json.references?.length; i++) { if (json.references[i].path === './.storybook/tsconfig.json') { From 7c642e6dd56fa2c3b683f837fabf25b60afd2a7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leosvel=20P=C3=A9rez=20Espinosa?= Date: Mon, 10 Jul 2023 14:13:57 +0100 Subject: [PATCH 038/262] docs(misc): fix typo in nx usage at enterprises doc (#17959) --- docs/shared/monorepo-nx-enterprise.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/shared/monorepo-nx-enterprise.md b/docs/shared/monorepo-nx-enterprise.md index aca7a17aa602f..e68007b160df5 100644 --- a/docs/shared/monorepo-nx-enterprise.md +++ b/docs/shared/monorepo-nx-enterprise.md @@ -23,7 +23,7 @@ starting point not the definite list of what you must and must not do. - Apps configure dependency injection and wire up libraries. They should not contain any components, services, or business logic. -- Libs contain services, components, utilities, etc. They have well-≠defined public API. +- Libs contain services, components, utilities, etc. They have well-defined public API. A typical Nx workspace has many more libs than apps, so pay especially careful attention to the organization of the libs directory. From d905e36fb7820097a10c6030bc05c6168b2c623a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leosvel=20P=C3=A9rez=20Espinosa?= Date: Mon, 10 Jul 2023 14:15:04 +0100 Subject: [PATCH 039/262] docs(angular): add info for angular 16.1.0 in version compatibility matrix docs (#17993) --- .../packages/angular/documents/angular-nx-version-matrix.md | 1 + docs/shared/packages/angular/angular-nx-version-matrix.md | 1 + 2 files changed, 2 insertions(+) diff --git a/docs/generated/packages/angular/documents/angular-nx-version-matrix.md b/docs/generated/packages/angular/documents/angular-nx-version-matrix.md index e6d79e4d79005..0fc34f98d2849 100644 --- a/docs/generated/packages/angular/documents/angular-nx-version-matrix.md +++ b/docs/generated/packages/angular/documents/angular-nx-version-matrix.md @@ -14,6 +14,7 @@ We provide a recommended version, and it is usually the latest minor version of | Angular Version | **Nx Version _(recommended)_** | Nx Version _(range)_ | | --------------- | ------------------------------ | --------------------------------------- | +| ~16.1.0 | **latest** | 16.4.0 <= latest | | ~16.0.0 | **latest** | 16.1.0 <= latest | | ~15.2.0 | **latest** | 15.8.0 <= latest | | ~15.1.0 | **latest** | 15.5.0 <= latest | diff --git a/docs/shared/packages/angular/angular-nx-version-matrix.md b/docs/shared/packages/angular/angular-nx-version-matrix.md index e6d79e4d79005..0fc34f98d2849 100644 --- a/docs/shared/packages/angular/angular-nx-version-matrix.md +++ b/docs/shared/packages/angular/angular-nx-version-matrix.md @@ -14,6 +14,7 @@ We provide a recommended version, and it is usually the latest minor version of | Angular Version | **Nx Version _(recommended)_** | Nx Version _(range)_ | | --------------- | ------------------------------ | --------------------------------------- | +| ~16.1.0 | **latest** | 16.4.0 <= latest | | ~16.0.0 | **latest** | 16.1.0 <= latest | | ~15.2.0 | **latest** | 15.8.0 <= latest | | ~15.1.0 | **latest** | 15.5.0 <= latest | From d10aeb49ac9996e29287872231b468e2bccfa626 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leosvel=20P=C3=A9rez=20Espinosa?= Date: Mon, 10 Jul 2023 14:30:25 +0100 Subject: [PATCH 040/262] fix(js): post-process skipped tasks by the ts compiler in tsc batch implementation (#17938) --- e2e/js/src/js-tsc.test.ts | 9 ++ .../js/src/executors/tsc/tsc.batch-impl.ts | 95 ++++++++++++++----- 2 files changed, 80 insertions(+), 24 deletions(-) diff --git a/e2e/js/src/js-tsc.test.ts b/e2e/js/src/js-tsc.test.ts index 3494742bc2c64..ad2595c74f15e 100644 --- a/e2e/js/src/js-tsc.test.ts +++ b/e2e/js/src/js-tsc.test.ts @@ -187,6 +187,15 @@ describe('js e2e', () => { `dist/libs/${lib}/src/lib/${lib}.js`, `dist/libs/${lib}/src/lib/${lib}.d.ts` ); + + // run a second time skipping the nx cache and with the outputs present + const secondBatchBuildOutput = runCLI( + `build ${parentLib} --skip-nx-cache`, + { env: { NX_BATCH_MODE: 'true' } } + ); + expect(secondBatchBuildOutput).toContain( + `Successfully ran target build for project ${parentLib} and 1 task it depends on` + ); }, 240_000); it('should not create a `.babelrc` file when creating libs with js executors (--compiler=tsc)', () => { diff --git a/packages/js/src/executors/tsc/tsc.batch-impl.ts b/packages/js/src/executors/tsc/tsc.batch-impl.ts index e09616bb87c1f..e28a5702a4c0c 100644 --- a/packages/js/src/executors/tsc/tsc.batch-impl.ts +++ b/packages/js/src/executors/tsc/tsc.batch-impl.ts @@ -76,6 +76,20 @@ export async function* tscBatchExecutor( }, }; + const processTaskPostCompilation = (tsConfig: string) => { + if (tsConfigTaskInfoMap[tsConfig]) { + const taskInfo = tsConfigTaskInfoMap[tsConfig]; + taskInfo.assetsHandler.processAllAssetsOnceSync(); + updatePackageJson( + taskInfo.options, + taskInfo.context, + taskInfo.projectGraphNode, + taskInfo.buildableProjectNodeDependencies + ); + taskInfo.endTime = Date.now(); + } + }; + const typescriptCompilation = compileTypescriptSolution( tsCompilationContext, shouldWatch, @@ -86,19 +100,7 @@ export async function* tscBatchExecutor( tsConfigTaskInfoMap[tsConfig].startTime = Date.now(); } }, - afterProjectCompilationCallback: (tsConfig) => { - if (tsConfigTaskInfoMap[tsConfig]) { - const taskInfo = tsConfigTaskInfoMap[tsConfig]; - taskInfo.assetsHandler.processAllAssetsOnceSync(); - updatePackageJson( - taskInfo.options, - taskInfo.context, - taskInfo.projectGraphNode, - taskInfo.buildableProjectNodeDependencies - ); - taskInfo.endTime = Date.now(); - } - }, + afterProjectCompilationCallback: processTaskPostCompilation, } ); @@ -136,23 +138,68 @@ export async function* tscBatchExecutor( }); } + const toBatchExecutorTaskResult = ( + tsConfig: string, + success: boolean + ): BatchExecutorTaskResult => ({ + task: tsConfigTaskInfoMap[tsConfig].task, + result: { + success: success, + terminalOutput: tsConfigTaskInfoMap[tsConfig].terminalOutput, + startTime: tsConfigTaskInfoMap[tsConfig].startTime, + endTime: tsConfigTaskInfoMap[tsConfig].endTime, + }, + }); + + let isCompilationDone = false; + const taskTsConfigsToReport = new Set( + Object.keys(taskGraph.tasks).map((t) => taskInMemoryTsConfigMap[t].path) + ); + let tasksToReportIterator: IterableIterator; + + const processSkippedTasks = () => { + const { value: tsConfig, done } = tasksToReportIterator.next(); + if (done) { + return { value: undefined, done: true }; + } + + tsConfigTaskInfoMap[tsConfig].startTime = Date.now(); + processTaskPostCompilation(tsConfig); + + return { value: toBatchExecutorTaskResult(tsConfig, true), done: false }; + }; + return yield* mapAsyncIterable(typescriptCompilation, async (iterator) => { + if (isCompilationDone) { + return processSkippedTasks(); + } + const { value, done } = await iterator.next(); if (done) { - return { value, done: true }; + if (taskTsConfigsToReport.size > 0) { + /** + * TS compilation is done but we still have tasks to report. This can + * happen if, for example, a project is identified as affected, but + * no file in the TS project is actually changed or if running a + * task with `--skip-nx-cache` and the outputs are already there. There + * can still be changes to assets or other files we need to process. + * + * Switch to handle the iterator for the tasks we still need to report. + */ + isCompilationDone = true; + tasksToReportIterator = taskTsConfigsToReport.values(); + return processSkippedTasks(); + } + + return { value: undefined, done: true }; } - const taskResult: BatchExecutorTaskResult = { - task: tsConfigTaskInfoMap[value.tsConfig].task, - result: { - success: value.success, - terminalOutput: tsConfigTaskInfoMap[value.tsConfig].terminalOutput, - startTime: tsConfigTaskInfoMap[value.tsConfig].startTime, - endTime: tsConfigTaskInfoMap[value.tsConfig].endTime, - }, - }; + taskTsConfigsToReport.delete(value.tsConfig); - return { value: taskResult, done: false }; + return { + value: toBatchExecutorTaskResult(value.tsConfig, value.success), + done: false, + }; }); } From a08cb91891d3cbd05a3fc1e6607dbab91f54cd29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leosvel=20P=C3=A9rez=20Espinosa?= Date: Mon, 10 Jul 2023 14:41:10 +0100 Subject: [PATCH 041/262] fix(angular): explicitly depend on find-cache-dir to avoid npm resolution conflict (#18049) --- packages-legacy/angular/ng-package.json | 3 ++- packages/angular/ng-package.json | 3 ++- packages/angular/package.json | 1 + scripts/depcheck/missing.ts | 1 - 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/packages-legacy/angular/ng-package.json b/packages-legacy/angular/ng-package.json index c72d66f4cfbd8..fb93e3b8bd775 100644 --- a/packages-legacy/angular/ng-package.json +++ b/packages-legacy/angular/ng-package.json @@ -26,7 +26,8 @@ "webpack", "http-server", "magic-string", - "enquirer" + "enquirer", + "find-cache-dir" ], "keepLifecycleScripts": true } diff --git a/packages/angular/ng-package.json b/packages/angular/ng-package.json index 0a10730af0f58..5c009a81e0ab6 100644 --- a/packages/angular/ng-package.json +++ b/packages/angular/ng-package.json @@ -25,7 +25,8 @@ "webpack", "http-server", "magic-string", - "enquirer" + "enquirer", + "find-cache-dir" ], "keepLifecycleScripts": true } diff --git a/packages/angular/package.json b/packages/angular/package.json index 4c424489995fe..b6f509f229be9 100644 --- a/packages/angular/package.json +++ b/packages/angular/package.json @@ -49,6 +49,7 @@ "@typescript-eslint/type-utils": "^5.36.1", "chalk": "^4.1.0", "chokidar": "^3.5.1", + "find-cache-dir": "^3.3.2", "http-server": "^14.1.0", "ignore": "^5.0.4", "magic-string": "~0.26.2", diff --git a/scripts/depcheck/missing.ts b/scripts/depcheck/missing.ts index e742883d3c018..345ee33ec9b4b 100644 --- a/scripts/depcheck/missing.ts +++ b/scripts/depcheck/missing.ts @@ -36,7 +36,6 @@ const IGNORE_MATCHES_IN_PACKAGE = { 'injection-js', 'browserslist', 'cacache', - 'find-cache-dir', 'less', 'node-sass', 'node-sass-tilde-importer', From 92926b934693f5f13cf60c9e5c6e36660a658431 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leosvel=20P=C3=A9rez=20Espinosa?= Date: Mon, 10 Jul 2023 15:41:59 +0100 Subject: [PATCH 042/262] fix(core): handle undefined target defaults (#18044) --- packages/nx/src/tasks-runner/create-task-graph.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nx/src/tasks-runner/create-task-graph.ts b/packages/nx/src/tasks-runner/create-task-graph.ts index 7ab3cd2fa6e7d..97572012dd4f8 100644 --- a/packages/nx/src/tasks-runner/create-task-graph.ts +++ b/packages/nx/src/tasks-runner/create-task-graph.ts @@ -388,10 +388,10 @@ export function createTaskGraph( } export function mapTargetDefaultsToDependencies( - defaults: TargetDefaults + defaults: TargetDefaults | undefined ): TargetDependencies { const res = {}; - Object.keys(defaults).forEach((k) => { + Object.keys(defaults ?? {}).forEach((k) => { res[k] = defaults[k].dependsOn; }); From e25582780a296dfdf4783a855b5b7c9b1c144243 Mon Sep 17 00:00:00 2001 From: Chi Ma Date: Mon, 10 Jul 2023 21:48:44 +0700 Subject: [PATCH 043/262] fix(core): add missing perf_hooks import in tasks-runner/cache (#18043) --- packages/nx/src/tasks-runner/cache.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/nx/src/tasks-runner/cache.ts b/packages/nx/src/tasks-runner/cache.ts index fa3ed46fa2fd7..39e05d4c863f1 100644 --- a/packages/nx/src/tasks-runner/cache.ts +++ b/packages/nx/src/tasks-runner/cache.ts @@ -1,6 +1,7 @@ import { workspaceRoot } from '../utils/workspace-root'; import { mkdir, mkdirSync, pathExists, readFile, writeFile } from 'fs-extra'; import { join } from 'path'; +import { performance } from 'perf_hooks'; import { DefaultTasksRunnerOptions } from './default-tasks-runner'; import { spawn } from 'child_process'; import { cacheDir } from '../utils/cache-directory'; From 5d734b747b5ab5e511edc450c63cfb14cd52c51a Mon Sep 17 00:00:00 2001 From: Rares Matei Date: Mon, 10 Jul 2023 17:40:40 +0100 Subject: [PATCH 044/262] docs(nx-cloud): update release notes (#17992) --- docs/nx-cloud/reference/release-notes.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/nx-cloud/reference/release-notes.md b/docs/nx-cloud/reference/release-notes.md index 110747b9b3567..b0896e56b5de4 100644 --- a/docs/nx-cloud/reference/release-notes.md +++ b/docs/nx-cloud/reference/release-notes.md @@ -98,6 +98,11 @@ Cleanup: Handle issues with the network and the api in a consistent fashion. # Docker Containers +## 2306.01.2.patch3 + +- Fixes an issue with multiple admin organizations being created on new installations +- Fixes an issue where Enterprise licenses could not be applied on some new orgs + ## 2306.01.2.patch2 - Fixes an issue with the `single-image` container where the aggregation would block the API from starting up From 7a9a60324d6942e7da6cfe48c5c00d2bab0731b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Jona=C5=A1?= Date: Mon, 10 Jul 2023 19:59:07 +0200 Subject: [PATCH 045/262] cleanup(core): remove obsolete versions from workspace (#17984) --- packages/workspace/src/utils/versions.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/workspace/src/utils/versions.ts b/packages/workspace/src/utils/versions.ts index 3a9e3d7a8fac2..e0572876913e6 100644 --- a/packages/workspace/src/utils/versions.ts +++ b/packages/workspace/src/utils/versions.ts @@ -1,11 +1,7 @@ export const nxVersion = require('../../package.json').version; export const typescriptVersion = '~5.1.3'; -export const typescriptESLintVersion = '^5.60.1'; -export const eslintVersion = '~8.15.0'; -export const eslintConfigPrettierVersion = '8.1.0'; // TODO: remove when preset generation is reworked and // deps are not installed from workspace export const angularCliVersion = '~16.1.0'; -export const prettierVersion = '^2.6.2'; From 9aadae6a5d5b716b52423bc07783c3960209b177 Mon Sep 17 00:00:00 2001 From: Ethan Lowry Date: Tue, 11 Jul 2023 13:39:50 +0100 Subject: [PATCH 046/262] docs(misc): fix misleading typo in docs for Incremental Builds (#18067) --- docs/shared/incremental-builds.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/shared/incremental-builds.md b/docs/shared/incremental-builds.md index 56a4596f16728..087017fc4ddf6 100644 --- a/docs/shared/incremental-builds.md +++ b/docs/shared/incremental-builds.md @@ -8,7 +8,7 @@ nx g @nx/react:app myapp nx g @nx/react:lib mylib ``` -...and then import the library from the application. In this case, `mylib` isn't a buildable library. We cannot test and lint it independently, but the only way to build it is by building some application using it (in this case `myapp`). The default setup is to use Webpack, which builds "mylib" and bundles it directly into "myapp". +...and then import the library from the application. In this case, `mylib` isn't a buildable library. We can test and lint it independently, but the only way to build it is by building some application using it (in this case `myapp`). The default setup is to use Webpack, which builds "mylib" and bundles it directly into "myapp". This provides the best dev experience for small and medium-size applications, because Webpack is optimized for this scenario. But as your application keeps growing, the dev experience degrades. > The **duration** of the invoked operations should be **proportional** to the **size of the change** From 5c987266274b53821b9908cf405c40c7d47dad02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leosvel=20P=C3=A9rez=20Espinosa?= Date: Tue, 11 Jul 2023 15:29:20 +0100 Subject: [PATCH 047/262] cleanup(bundling): fix esbuild e2e test case (#17890) --- e2e/esbuild/src/esbuild.test.ts | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/e2e/esbuild/src/esbuild.test.ts b/e2e/esbuild/src/esbuild.test.ts index 66e0f983b611f..8cb740adc0f94 100644 --- a/e2e/esbuild/src/esbuild.test.ts +++ b/e2e/esbuild/src/esbuild.test.ts @@ -190,10 +190,18 @@ describe('EsBuild Plugin', () => { return json; }); - runCommand(`build ${myPkg}`); + runCLI(`build ${myPkg}`); - expect(runCommand(`node dist/libs/${myPkg}/main.js`)).toMatch(/main/); - expect(runCommand(`node dist/libs/${myPkg}/extra.js`)).toMatch(/extra/); + checkFilesExist( + `dist/libs/${myPkg}/index.js`, + `dist/libs/${myPkg}/extra.js` + ); + expect( + runCommand(`node dist/libs/${myPkg}/index.js`, { failOnError: true }) + ).toMatch(/main/); + expect( + runCommand(`node dist/libs/${myPkg}/extra.js`, { failOnError: true }) + ).toMatch(/extra/); }, 120_000); it('should support external esbuild.config.js file', async () => { From 8be6558700662e8c80351b11a74e655fbe62c593 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leosvel=20P=C3=A9rez=20Espinosa?= Date: Tue, 11 Jul 2023 16:21:24 +0100 Subject: [PATCH 048/262] fix(misc): fix migrations updating target options to consider target defaults (#18064) --- ...-projects-to-update-buildable-deps.spec.ts | 55 ++++++++++++++++++- ...y-set-projects-to-update-buildable-deps.ts | 33 ++++++----- ...-projects-to-update-buildable-deps.spec.ts | 49 ++++++++++++++++- ...y-set-projects-to-update-buildable-deps.ts | 33 ++++++----- ...-projects-to-update-buildable-deps.spec.ts | 49 ++++++++++++++++- ...y-set-projects-to-update-buildable-deps.ts | 33 ++++++----- 6 files changed, 204 insertions(+), 48 deletions(-) diff --git a/packages/angular/src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps.spec.ts b/packages/angular/src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps.spec.ts index cc0f0378242ae..beb741d5e2930 100644 --- a/packages/angular/src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps.spec.ts +++ b/packages/angular/src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps.spec.ts @@ -1,5 +1,6 @@ import { ProjectConfiguration, + ProjectGraph, Tree, addProjectConfiguration, readProjectConfiguration, @@ -7,11 +8,18 @@ import { import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; import migration from './explicitly-set-projects-to-update-buildable-deps'; +let projectGraph: ProjectGraph; +jest.mock('@nx/devkit', () => ({ + ...jest.requireActual('@nx/devkit'), + createProjectGraphAsync: () => Promise.resolve(projectGraph), +})); + describe('explicitly-set-projects-to-update-buildable-deps migration', () => { let tree: Tree; beforeEach(() => { tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' }); + projectGraph = { dependencies: {}, nodes: {} }; }); it.each([ @@ -22,7 +30,7 @@ describe('explicitly-set-projects-to-update-buildable-deps migration', () => { ])( 'should set updateBuildableProjectDepsInPackageJson option to "true" when not specified in target using "%s"', async (executor) => { - addProjectConfiguration(tree, 'lib1', { + addProject(tree, 'lib1', { root: 'libs/lib1', projectType: 'library', targets: { build: { executor, options: {} } }, @@ -37,6 +45,29 @@ describe('explicitly-set-projects-to-update-buildable-deps migration', () => { } ); + it.each([ + '@nx/angular:ng-packagr-lite', + '@nrwl/angular:ng-packagr-lite', + '@nx/angular:package', + '@nrwl/angular:package', + ])( + 'should set updateBuildableProjectDepsInPackageJson option to "true" when target has no options object defined using "%s"', + async (executor) => { + addProject(tree, 'lib1', { + root: 'libs/lib1', + projectType: 'library', + targets: { build: { executor } }, + }); + + await migration(tree); + + const project = readProjectConfiguration(tree, 'lib1'); + expect( + project.targets.build.options.updateBuildableProjectDepsInPackageJson + ).toBe(true); + } + ); + it.each([ '@nx/angular:ng-packagr-lite', '@nrwl/angular:ng-packagr-lite', @@ -45,7 +76,7 @@ describe('explicitly-set-projects-to-update-buildable-deps migration', () => { ])( 'should not overwrite updateBuildableProjectDepsInPackageJson option when it is specified in target using "%s"', async (executor) => { - addProjectConfiguration(tree, 'lib1', { + addProject(tree, 'lib1', { root: 'libs/lib1', projectType: 'library', targets: { @@ -76,7 +107,7 @@ describe('explicitly-set-projects-to-update-buildable-deps migration', () => { }, }, }; - addProjectConfiguration(tree, 'lib1', originalProjectConfig); + addProject(tree, 'lib1', originalProjectConfig); await migration(tree); @@ -84,3 +115,21 @@ describe('explicitly-set-projects-to-update-buildable-deps migration', () => { expect(project.targets).toStrictEqual(originalProjectConfig.targets); }); }); + +function addProject( + tree: Tree, + projectName: string, + config: ProjectConfiguration +): void { + projectGraph = { + dependencies: {}, + nodes: { + [projectName]: { + data: config, + name: projectName, + type: config.projectType === 'application' ? 'app' : 'lib', + }, + }, + }; + addProjectConfiguration(tree, projectName, config); +} diff --git a/packages/angular/src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps.ts b/packages/angular/src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps.ts index 09e5f6c9cc4d5..8842d8205e9c0 100644 --- a/packages/angular/src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps.ts +++ b/packages/angular/src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps.ts @@ -1,6 +1,7 @@ import { + createProjectGraphAsync, formatFiles, - getProjects, + readProjectConfiguration, Tree, updateProjectConfiguration, } from '@nx/devkit'; @@ -13,31 +14,37 @@ const executors = new Set([ ]); export default async function (tree: Tree) { - const projects = getProjects(tree); + // use project graph to get the expanded target configurations + const projectGraph = await createProjectGraphAsync(); - for (const [projectName, project] of projects) { - if (project.projectType !== 'library') { + for (const [projectName, { data: projectData }] of Object.entries( + projectGraph.nodes + )) { + if (projectData.projectType !== 'library') { continue; } - let updated = false; - for (const [, target] of Object.entries(project.targets || {})) { + for (const [targetName, target] of Object.entries( + projectData.targets || {} + )) { if (!executors.has(target.executor)) { continue; } if ( - target.options && + !target.options || target.options.updateBuildableProjectDepsInPackageJson === undefined ) { - target.options.updateBuildableProjectDepsInPackageJson = true; - updated = true; + // read the project configuration to write the explicit project configuration + // and avoid writing the expanded target configuration + const project = readProjectConfiguration(tree, projectName); + project.targets[targetName].options ??= {}; + project.targets[ + targetName + ].options.updateBuildableProjectDepsInPackageJson = true; + updateProjectConfiguration(tree, projectName, project); } } - - if (updated) { - updateProjectConfiguration(tree, projectName, project); - } } await formatFiles(tree); diff --git a/packages/js/src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps.spec.ts b/packages/js/src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps.spec.ts index 07caa361d79f4..3374fd0050e7c 100644 --- a/packages/js/src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps.spec.ts +++ b/packages/js/src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps.spec.ts @@ -1,5 +1,6 @@ import { ProjectConfiguration, + ProjectGraph, Tree, addProjectConfiguration, readProjectConfiguration, @@ -7,6 +8,12 @@ import { import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; import migration from './explicitly-set-projects-to-update-buildable-deps'; +let projectGraph: ProjectGraph; +jest.mock('@nx/devkit', () => ({ + ...jest.requireActual('@nx/devkit'), + createProjectGraphAsync: () => Promise.resolve(projectGraph), +})); + describe('explicitly-set-projects-to-update-buildable-deps migration', () => { let tree: Tree; @@ -17,7 +24,7 @@ describe('explicitly-set-projects-to-update-buildable-deps migration', () => { it.each(['@nx/js:swc', '@nrwl/js:swc', '@nx/js:tsc', '@nrwl/js:tsc'])( 'should set updateBuildableProjectDepsInPackageJson option to "true" when not specified in target using "%s"', async (executor) => { - addProjectConfiguration(tree, 'lib1', { + addProject(tree, 'lib1', { root: 'libs/lib1', projectType: 'library', targets: { build: { executor, options: {} } }, @@ -32,10 +39,28 @@ describe('explicitly-set-projects-to-update-buildable-deps migration', () => { } ); + it.each(['@nx/js:swc', '@nrwl/js:swc', '@nx/js:tsc', '@nrwl/js:tsc'])( + 'should set updateBuildableProjectDepsInPackageJson option to "true" when target has no options object defined using "%s"', + async (executor) => { + addProject(tree, 'lib1', { + root: 'libs/lib1', + projectType: 'library', + targets: { build: { executor } }, + }); + + await migration(tree); + + const project = readProjectConfiguration(tree, 'lib1'); + expect( + project.targets.build.options.updateBuildableProjectDepsInPackageJson + ).toBe(true); + } + ); + it.each(['@nx/js:swc', '@nrwl/js:swc', '@nx/js:tsc', '@nrwl/js:tsc'])( 'should not overwrite updateBuildableProjectDepsInPackageJson option when it is specified in target using "%s"', async (executor) => { - addProjectConfiguration(tree, 'lib1', { + addProject(tree, 'lib1', { root: 'libs/lib1', projectType: 'library', targets: { @@ -66,7 +91,7 @@ describe('explicitly-set-projects-to-update-buildable-deps migration', () => { }, }, }; - addProjectConfiguration(tree, 'lib1', originalProjectConfig); + addProject(tree, 'lib1', originalProjectConfig); await migration(tree); @@ -74,3 +99,21 @@ describe('explicitly-set-projects-to-update-buildable-deps migration', () => { expect(project.targets).toStrictEqual(originalProjectConfig.targets); }); }); + +function addProject( + tree: Tree, + projectName: string, + config: ProjectConfiguration +): void { + projectGraph = { + dependencies: {}, + nodes: { + [projectName]: { + data: config, + name: projectName, + type: config.projectType === 'application' ? 'app' : 'lib', + }, + }, + }; + addProjectConfiguration(tree, projectName, config); +} diff --git a/packages/js/src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps.ts b/packages/js/src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps.ts index 5273b2a748520..edbe446bf598f 100644 --- a/packages/js/src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps.ts +++ b/packages/js/src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps.ts @@ -1,6 +1,7 @@ import { + createProjectGraphAsync, formatFiles, - getProjects, + readProjectConfiguration, Tree, updateProjectConfiguration, } from '@nx/devkit'; @@ -13,31 +14,37 @@ const executors = new Set([ ]); export default async function (tree: Tree) { - const projects = getProjects(tree); + // use project graph to get the expanded target configurations + const projectGraph = await createProjectGraphAsync(); - for (const [projectName, project] of projects) { - if (project.projectType !== 'library') { + for (const [projectName, { data: projectData }] of Object.entries( + projectGraph.nodes + )) { + if (projectData.projectType !== 'library') { continue; } - let updated = false; - for (const [, target] of Object.entries(project.targets || {})) { + for (const [targetName, target] of Object.entries( + projectData.targets || {} + )) { if (!executors.has(target.executor)) { continue; } if ( - target.options && + !target.options || target.options.updateBuildableProjectDepsInPackageJson === undefined ) { - target.options.updateBuildableProjectDepsInPackageJson = true; - updated = true; + // read the project configuration to write the explicit project configuration + // and avoid writing the expanded target configuration + const project = readProjectConfiguration(tree, projectName); + project.targets[targetName].options ??= {}; + project.targets[ + targetName + ].options.updateBuildableProjectDepsInPackageJson = true; + updateProjectConfiguration(tree, projectName, project); } } - - if (updated) { - updateProjectConfiguration(tree, projectName, project); - } } await formatFiles(tree); diff --git a/packages/rollup/src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps.spec.ts b/packages/rollup/src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps.spec.ts index 0d244a11a33ec..e507d75aeaca3 100644 --- a/packages/rollup/src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps.spec.ts +++ b/packages/rollup/src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps.spec.ts @@ -1,5 +1,6 @@ import { ProjectConfiguration, + ProjectGraph, Tree, addProjectConfiguration, readProjectConfiguration, @@ -7,6 +8,12 @@ import { import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; import migration from './explicitly-set-projects-to-update-buildable-deps'; +let projectGraph: ProjectGraph; +jest.mock('@nx/devkit', () => ({ + ...jest.requireActual('@nx/devkit'), + createProjectGraphAsync: () => Promise.resolve(projectGraph), +})); + describe('explicitly-set-projects-to-update-buildable-deps migration', () => { let tree: Tree; @@ -17,7 +24,7 @@ describe('explicitly-set-projects-to-update-buildable-deps migration', () => { it.each(['@nx/rollup:rollup', '@nrwl/rollup:rollup'])( 'should set updateBuildableProjectDepsInPackageJson option to "true" when not specified in target using "%s"', async (executor) => { - addProjectConfiguration(tree, 'lib1', { + addProject(tree, 'lib1', { root: 'libs/lib1', projectType: 'library', targets: { build: { executor, options: {} } }, @@ -32,10 +39,28 @@ describe('explicitly-set-projects-to-update-buildable-deps migration', () => { } ); + it.each(['@nx/rollup:rollup', '@nrwl/rollup:rollup'])( + 'should set updateBuildableProjectDepsInPackageJson option to "true" when target has no options object defined using "%s"', + async (executor) => { + addProject(tree, 'lib1', { + root: 'libs/lib1', + projectType: 'library', + targets: { build: { executor } }, + }); + + await migration(tree); + + const project = readProjectConfiguration(tree, 'lib1'); + expect( + project.targets.build.options.updateBuildableProjectDepsInPackageJson + ).toBe(true); + } + ); + it.each(['@nx/js:swc', '@nrwl/js:swc', '@nx/js:tsc', '@nrwl/js:tsc'])( 'should not overwrite updateBuildableProjectDepsInPackageJson option when it is specified in target using "%s"', async (executor) => { - addProjectConfiguration(tree, 'lib1', { + addProject(tree, 'lib1', { root: 'libs/lib1', projectType: 'library', targets: { @@ -66,7 +91,7 @@ describe('explicitly-set-projects-to-update-buildable-deps migration', () => { }, }, }; - addProjectConfiguration(tree, 'lib1', originalProjectConfig); + addProject(tree, 'lib1', originalProjectConfig); await migration(tree); @@ -74,3 +99,21 @@ describe('explicitly-set-projects-to-update-buildable-deps migration', () => { expect(project.targets).toStrictEqual(originalProjectConfig.targets); }); }); + +function addProject( + tree: Tree, + projectName: string, + config: ProjectConfiguration +): void { + projectGraph = { + dependencies: {}, + nodes: { + [projectName]: { + data: config, + name: projectName, + type: config.projectType === 'application' ? 'app' : 'lib', + }, + }, + }; + addProjectConfiguration(tree, projectName, config); +} diff --git a/packages/rollup/src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps.ts b/packages/rollup/src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps.ts index e3377e89e2f7d..5af99c4f5b181 100644 --- a/packages/rollup/src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps.ts +++ b/packages/rollup/src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps.ts @@ -1,6 +1,7 @@ import { + createProjectGraphAsync, formatFiles, - getProjects, + readProjectConfiguration, Tree, updateProjectConfiguration, } from '@nx/devkit'; @@ -8,31 +9,37 @@ import { const executors = new Set(['@nx/rollup:rollup', '@nrwl/rollup:rollup']); export default async function (tree: Tree) { - const projects = getProjects(tree); + // use project graph to get the expanded target configurations + const projectGraph = await createProjectGraphAsync(); - for (const [projectName, project] of projects) { - if (project.projectType !== 'library') { + for (const [projectName, { data: projectData }] of Object.entries( + projectGraph.nodes + )) { + if (projectData.projectType !== 'library') { continue; } - let updated = false; - for (const [, target] of Object.entries(project.targets || {})) { + for (const [targetName, target] of Object.entries( + projectData.targets || {} + )) { if (!executors.has(target.executor)) { continue; } if ( - target.options && + !target.options || target.options.updateBuildableProjectDepsInPackageJson === undefined ) { - target.options.updateBuildableProjectDepsInPackageJson = true; - updated = true; + // read the project configuration to write the explicit project configuration + // and avoid writing the expanded target configuration + const project = readProjectConfiguration(tree, projectName); + project.targets[targetName].options ??= {}; + project.targets[ + targetName + ].options.updateBuildableProjectDepsInPackageJson = true; + updateProjectConfiguration(tree, projectName, project); } } - - if (updated) { - updateProjectConfiguration(tree, projectName, project); - } } await formatFiles(tree); From 95a2256a34609e4eecc2a29a802cbf8d292eda47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leosvel=20P=C3=A9rez=20Espinosa?= Date: Tue, 11 Jul 2023 16:28:03 +0100 Subject: [PATCH 049/262] feat(misc): deprecate executor options to generate package.json for libraries (#17923) --- .../angular/executors/ng-packagr-lite.json | 12 +++++----- .../packages/angular/executors/package.json | 10 ++++----- docs/generated/packages/js/executors/swc.json | 6 +++-- docs/generated/packages/js/executors/tsc.json | 6 +++-- .../packages/rollup/executors/rollup.json | 22 +++++-------------- .../src/executors/ng-packagr-lite/schema.json | 12 +++++----- .../angular/src/executors/package/schema.d.ts | 10 +++++++++ .../angular/src/executors/package/schema.json | 12 +++++----- .../src/executors/esbuild/esbuild.impl.ts | 9 +++++++- packages/js/src/executors/swc/schema.json | 6 +++-- packages/js/src/executors/tsc/schema.json | 6 +++-- packages/js/src/utils/schema.d.ts | 10 +++++++++ .../rollup/src/executors/rollup/schema.d.ts | 10 +++++++++ .../rollup/src/executors/rollup/schema.json | 19 ++++------------ .../vite/src/executors/build/build.impl.ts | 14 +++++++++++- .../src/executors/webpack/webpack.impl.ts | 9 +++++++- 16 files changed, 105 insertions(+), 68 deletions(-) diff --git a/docs/generated/packages/angular/executors/ng-packagr-lite.json b/docs/generated/packages/angular/executors/ng-packagr-lite.json index 306a1c5092183..83213a14c759c 100644 --- a/docs/generated/packages/angular/executors/ng-packagr-lite.json +++ b/docs/generated/packages/angular/executors/ng-packagr-lite.json @@ -16,11 +16,7 @@ }, { "name": "Updating Project Dependencies for Buildable Library", - "keys": [ - "project", - "updateBuildableProjectDepsInPackageJson", - "buildableProjectDepsInPackageJsonType" - ] + "keys": ["project"] } ], "properties": { @@ -43,13 +39,15 @@ "updateBuildableProjectDepsInPackageJson": { "type": "boolean", "description": "Whether to update the buildable project dependencies in the build output package.json.", - "default": false + "default": false, + "x-deprecated": "Configure the project to use the '@nx/dependency-checks' ESLint rule instead (https://nx.dev/packages/eslint-plugin/documents/dependency-checks). It will be removed in v17." }, "buildableProjectDepsInPackageJsonType": { "type": "string", "description": "When `updateBuildableProjectDepsInPackageJson` is `true`, this adds dependencies to either `peerDependencies` or `dependencies`.", "enum": ["dependencies", "peerDependencies"], - "default": "peerDependencies" + "default": "peerDependencies", + "x-deprecated": "Configure the '@nx/dependency-checks' ESLint rule instead (https://nx.dev/packages/eslint-plugin/documents/dependency-checks). It will be removed in v17." }, "tailwindConfig": { "type": "string", diff --git a/docs/generated/packages/angular/executors/package.json b/docs/generated/packages/angular/executors/package.json index a6cbc49aa14f9..a99e9c7cacf43 100644 --- a/docs/generated/packages/angular/executors/package.json +++ b/docs/generated/packages/angular/executors/package.json @@ -20,9 +20,7 @@ { "name": "Updating Project Dependencies for Publishable Library", "keys": [ - "project", - "updateBuildableProjectDepsInPackageJson", - "buildableProjectDepsInPackageJsonType" + "project" ] } ], @@ -46,7 +44,8 @@ "updateBuildableProjectDepsInPackageJson": { "type": "boolean", "description": "Whether to update the buildable project dependencies in the build output package.json.", - "default": false + "default": false, + "x-deprecated": "Configure the project to use the '@nx/dependency-checks' ESLint rule instead (https://nx.dev/packages/eslint-plugin/documents/dependency-checks). It will be removed in v17." }, "buildableProjectDepsInPackageJsonType": { "type": "string", @@ -55,7 +54,8 @@ "dependencies", "peerDependencies" ], - "default": "peerDependencies" + "default": "peerDependencies", + "x-deprecated": "Configure the project to use the '@nx/dependency-checks' ESLint rule instead (https://nx.dev/packages/eslint-plugin/documents/dependency-checks). It will be removed in v17." }, "tailwindConfig": { "type": "string", diff --git a/docs/generated/packages/js/executors/swc.json b/docs/generated/packages/js/executors/swc.json index 1578c85eb9da6..8d34b0241c960 100644 --- a/docs/generated/packages/js/executors/swc.json +++ b/docs/generated/packages/js/executors/swc.json @@ -98,13 +98,15 @@ "updateBuildableProjectDepsInPackageJson": { "type": "boolean", "description": "Whether to update the buildable project dependencies in the build output package.json.", - "default": false + "default": false, + "x-deprecated": "Configure the project to use the '@nx/dependency-checks' ESLint rule instead (https://nx.dev/packages/eslint-plugin/documents/dependency-checks). It will be removed in v17." }, "buildableProjectDepsInPackageJsonType": { "type": "string", "description": "When `updateBuildableProjectDepsInPackageJson` is `true`, this adds dependencies to either `peerDependencies` or `dependencies`.", "enum": ["dependencies", "peerDependencies"], - "default": "peerDependencies" + "default": "peerDependencies", + "x-deprecated": "Configure the project to use the '@nx/dependency-checks' ESLint rule instead (https://nx.dev/packages/eslint-plugin/documents/dependency-checks). It will be removed in v17." }, "external": { "description": "A list projects to be treated as external. This feature is experimental", diff --git a/docs/generated/packages/js/executors/tsc.json b/docs/generated/packages/js/executors/tsc.json index 61f9e1b61d88a..f69b076c19cb5 100644 --- a/docs/generated/packages/js/executors/tsc.json +++ b/docs/generated/packages/js/executors/tsc.json @@ -98,13 +98,15 @@ "updateBuildableProjectDepsInPackageJson": { "type": "boolean", "description": "Whether to update the buildable project dependencies in the build output package.json.", - "default": false + "default": false, + "x-deprecated": "Configure the project to use the '@nx/dependency-checks' ESLint rule instead (https://nx.dev/packages/eslint-plugin/documents/dependency-checks). It will be removed in v17." }, "buildableProjectDepsInPackageJsonType": { "type": "string", "description": "When `updateBuildableProjectDepsInPackageJson` is `true`, this adds dependencies to either `peerDependencies` or `dependencies`.", "enum": ["dependencies", "peerDependencies"], - "default": "peerDependencies" + "default": "peerDependencies", + "x-deprecated": "Configure the project to use the '@nx/dependency-checks' ESLint rule instead (https://nx.dev/packages/eslint-plugin/documents/dependency-checks). It will be removed in v17." }, "external": { "description": "A list projects to be treated as external. This feature is experimental", diff --git a/docs/generated/packages/rollup/executors/rollup.json b/docs/generated/packages/rollup/executors/rollup.json index 0034da2d0f532..7d9fbf88aebad 100644 --- a/docs/generated/packages/rollup/executors/rollup.json +++ b/docs/generated/packages/rollup/executors/rollup.json @@ -8,19 +8,6 @@ "description": "Packages a library for different web usages (ESM, CommonJS).", "cli": "nx", "type": "object", - "presets": [ - { - "name": "Including Dependencies in package.json", - "keys": [ - "main", - "outputPath", - "project", - "tsConfig", - "buildableProjectDepsInPackageJsonType", - "updateBuildableProjectDepsInPackageJson" - ] - } - ], "properties": { "project": { "type": "string", @@ -84,13 +71,15 @@ "updateBuildableProjectDepsInPackageJson": { "type": "boolean", "description": "Update buildable project dependencies in `package.json`.", - "default": false + "default": false, + "x-deprecated": "Configure the project to use the '@nx/dependency-checks' ESLint rule instead (https://nx.dev/packages/eslint-plugin/documents/dependency-checks). It will be removed in v17." }, "buildableProjectDepsInPackageJsonType": { "type": "string", "description": "When `updateBuildableProjectDepsInPackageJson` is `true`, this adds dependencies to either `peerDependencies` or `dependencies`.", "enum": ["dependencies", "peerDependencies"], - "default": "peerDependencies" + "default": "peerDependencies", + "x-deprecated": "Configure the project to use the '@nx/dependency-checks' ESLint rule instead (https://nx.dev/packages/eslint-plugin/documents/dependency-checks). It will be removed in v17." }, "rollupConfig": { "oneOf": [ @@ -203,7 +192,8 @@ ] } }, - "examplesFile": "{% tabs %}\n{% tab label=\"Including Dependencies\" %}\nTo include dependencies in the output `package.json`, the dependencies must be installed as a **dependencies** in the root `package.json`\n\n```json {% fileName=\"package.json\" %}\n{\n \"dependencies\": {\n \"some-dependency\": \"^1.0.0\"\n }\n}\n```\n\nTo have dependencies in the be listed in the final `package.json` of your project, set the `updateBuildableProjectDepsInPackageJson` option to `true`. After than dependencies will be added to the `peerDependencies` field of the output `package.json`. You can use `buildableProjectDepsInPackageJsonType` option to change which field the dependencies are output to.\n\n```json {% fileName=\"project.json\" %}\n{\n \"targets\": {\n \"build\": {\n \"executor\": \"@nx/rollup:rollup\",\n \"options\": {\n \"buildableProjectDepsInPackageJsonType\": \"dependencies\",\n \"updateBuildableProjectDepsInPackageJson\": true\n }\n }\n }\n}\n```\n\n{% /tab %}\n\n{% tab label=\"Using `babelUpwardRootMode`\" %}\n\nCopying from the [Babel documentation](https://babeljs.io/docs/config-files#root-babelconfigjson-file):\n\n> [...] if you are running your Babel compilation process from within a subpackage, you need to tell Babel where to look for the config. There are a few ways to do that, but the recommended way is the \"rootMode\" option with \"upward\", which will make Babel search from the working directory upward looking for your babel.config.json file, and will use its location as the \"root\" value.\n\nSetting `babelUpwardRootMode` to `true` in your `project.json` will set `rootMode` option to `upward` in the Babel config. You may want the `upward` mode in a monorepo when projects must apply their individual `.babelrc` file. We recommend that you don't set it at all, so it will use the default to `false` as the `upward` mode brings additional complexity to the build process.\n\n```json\n//...\n\"my-app\": {\n \"targets\": {\n \"build\": {\n \"executor\": \"@nx/rollup:rollup\",\n \"options\": {\n \"babelUpwardRootMode\": true,\n //...\n },\n //...\n },\n //...\n },\n //...\n}\n```\n\nWhen `babelUpwardRootMode` is `true`, Babel will look for a root `babel.config.json` at the root of the workspace, which should look something like this to include all packages:\n\n```json\n{ \"babelrcRoots\": [\"*\"] }\n```\n\nThen for each package, you must have a `.babelrc` file that will be applied to that package. For example:\n\n```json\n{\n \"presets\": [\"@babel/preset-env\", \"@babel/preset-typescript\"]\n}\n```\n\nAll packages will use its own `.babelrc` file, thus you must ensure the right presets and plugins are set in each config file. This behavior can lead to build discrepancies between packages, so we recommend that you don't set `babelUpwardRootMode` at all.\n\n```treeview\n├── packages\n│ ├── a\n│ │ └── .babelrc\n│ └── b\n│ └── .babelrc\n└── babel.config.json\n```\n\nIn workspace above, if `a` imports `b`, it will apply the config `packages/b/.babelrc` and not apply its own `packages/a/.babelrc` to `b`. Anything in `babel.config.json` will apply to all packages.\n\n{% /tab %}\n\n{% /tabs %}\n" + "examplesFile": "{% tabs %}\n{% tab label=\"Including Dependencies\" %}\nTo include dependencies in the output `package.json`, the dependencies must be installed as a **dependencies** in the root `package.json`\n\n```json {% fileName=\"package.json\" %}\n{\n \"dependencies\": {\n \"some-dependency\": \"^1.0.0\"\n }\n}\n```\n\nTo have dependencies in the be listed in the final `package.json` of your project, set the `updateBuildableProjectDepsInPackageJson` option to `true`. After than dependencies will be added to the `peerDependencies` field of the output `package.json`. You can use `buildableProjectDepsInPackageJsonType` option to change which field the dependencies are output to.\n\n```json {% fileName=\"project.json\" %}\n{\n \"targets\": {\n \"build\": {\n \"executor\": \"@nx/rollup:rollup\",\n \"options\": {\n \"buildableProjectDepsInPackageJsonType\": \"dependencies\",\n \"updateBuildableProjectDepsInPackageJson\": true\n }\n }\n }\n}\n```\n\n{% /tab %}\n\n{% tab label=\"Using `babelUpwardRootMode`\" %}\n\nCopying from the [Babel documentation](https://babeljs.io/docs/config-files#root-babelconfigjson-file):\n\n> [...] if you are running your Babel compilation process from within a subpackage, you need to tell Babel where to look for the config. There are a few ways to do that, but the recommended way is the \"rootMode\" option with \"upward\", which will make Babel search from the working directory upward looking for your babel.config.json file, and will use its location as the \"root\" value.\n\nSetting `babelUpwardRootMode` to `true` in your `project.json` will set `rootMode` option to `upward` in the Babel config. You may want the `upward` mode in a monorepo when projects must apply their individual `.babelrc` file. We recommend that you don't set it at all, so it will use the default to `false` as the `upward` mode brings additional complexity to the build process.\n\n```json\n//...\n\"my-app\": {\n \"targets\": {\n \"build\": {\n \"executor\": \"@nx/rollup:rollup\",\n \"options\": {\n \"babelUpwardRootMode\": true,\n //...\n },\n //...\n },\n //...\n },\n //...\n}\n```\n\nWhen `babelUpwardRootMode` is `true`, Babel will look for a root `babel.config.json` at the root of the workspace, which should look something like this to include all packages:\n\n```json\n{ \"babelrcRoots\": [\"*\"] }\n```\n\nThen for each package, you must have a `.babelrc` file that will be applied to that package. For example:\n\n```json\n{\n \"presets\": [\"@babel/preset-env\", \"@babel/preset-typescript\"]\n}\n```\n\nAll packages will use its own `.babelrc` file, thus you must ensure the right presets and plugins are set in each config file. This behavior can lead to build discrepancies between packages, so we recommend that you don't set `babelUpwardRootMode` at all.\n\n```treeview\n├── packages\n│ ├── a\n│ │ └── .babelrc\n│ └── b\n│ └── .babelrc\n└── babel.config.json\n```\n\nIn workspace above, if `a` imports `b`, it will apply the config `packages/b/.babelrc` and not apply its own `packages/a/.babelrc` to `b`. Anything in `babel.config.json` will apply to all packages.\n\n{% /tab %}\n\n{% /tabs %}\n", + "presets": [] }, "description": "Bundle a package using Rollup.", "aliases": [], diff --git a/packages/angular/src/executors/ng-packagr-lite/schema.json b/packages/angular/src/executors/ng-packagr-lite/schema.json index 2051bb28a8e0a..05f38f9ea261b 100644 --- a/packages/angular/src/executors/ng-packagr-lite/schema.json +++ b/packages/angular/src/executors/ng-packagr-lite/schema.json @@ -13,11 +13,7 @@ }, { "name": "Updating Project Dependencies for Buildable Library", - "keys": [ - "project", - "updateBuildableProjectDepsInPackageJson", - "buildableProjectDepsInPackageJsonType" - ] + "keys": ["project"] } ], "properties": { @@ -40,13 +36,15 @@ "updateBuildableProjectDepsInPackageJson": { "type": "boolean", "description": "Whether to update the buildable project dependencies in the build output package.json.", - "default": false + "default": false, + "x-deprecated": "Configure the project to use the '@nx/dependency-checks' ESLint rule instead (https://nx.dev/packages/eslint-plugin/documents/dependency-checks). It will be removed in v17." }, "buildableProjectDepsInPackageJsonType": { "type": "string", "description": "When `updateBuildableProjectDepsInPackageJson` is `true`, this adds dependencies to either `peerDependencies` or `dependencies`.", "enum": ["dependencies", "peerDependencies"], - "default": "peerDependencies" + "default": "peerDependencies", + "x-deprecated": "Configure the '@nx/dependency-checks' ESLint rule instead (https://nx.dev/packages/eslint-plugin/documents/dependency-checks). It will be removed in v17." }, "tailwindConfig": { "type": "string", diff --git a/packages/angular/src/executors/package/schema.d.ts b/packages/angular/src/executors/package/schema.d.ts index abe918b1ac5af..3a740b437e23c 100644 --- a/packages/angular/src/executors/package/schema.d.ts +++ b/packages/angular/src/executors/package/schema.d.ts @@ -1,8 +1,18 @@ export interface BuildAngularLibraryExecutorOptions { project: string; + /** + * @deprecated Configure the project to use the `@nx/dependency-checks` ESLint + * rule instead (https://nx.dev/packages/eslint-plugin/documents/dependency-checks). + * It will be removed in v17. + */ buildableProjectDepsInPackageJsonType?: 'dependencies' | 'peerDependencies'; tailwindConfig?: string; tsConfig?: string; + /** + * @deprecated Configure the project to use the `@nx/dependency-checks` ESLint + * rule instead (https://nx.dev/packages/eslint-plugin/documents/dependency-checks). + * It will be removed in v17. + */ updateBuildableProjectDepsInPackageJson?: boolean; watch?: boolean; } diff --git a/packages/angular/src/executors/package/schema.json b/packages/angular/src/executors/package/schema.json index 1279a11875937..303141dbcf6fa 100644 --- a/packages/angular/src/executors/package/schema.json +++ b/packages/angular/src/executors/package/schema.json @@ -13,11 +13,7 @@ }, { "name": "Updating Project Dependencies for Publishable Library", - "keys": [ - "project", - "updateBuildableProjectDepsInPackageJson", - "buildableProjectDepsInPackageJsonType" - ] + "keys": ["project"] } ], "properties": { @@ -40,13 +36,15 @@ "updateBuildableProjectDepsInPackageJson": { "type": "boolean", "description": "Whether to update the buildable project dependencies in the build output package.json.", - "default": false + "default": false, + "x-deprecated": "Configure the project to use the '@nx/dependency-checks' ESLint rule instead (https://nx.dev/packages/eslint-plugin/documents/dependency-checks). It will be removed in v17." }, "buildableProjectDepsInPackageJsonType": { "type": "string", "description": "When `updateBuildableProjectDepsInPackageJson` is `true`, this adds dependencies to either `peerDependencies` or `dependencies`.", "enum": ["dependencies", "peerDependencies"], - "default": "peerDependencies" + "default": "peerDependencies", + "x-deprecated": "Configure the project to use the '@nx/dependency-checks' ESLint rule instead (https://nx.dev/packages/eslint-plugin/documents/dependency-checks). It will be removed in v17." }, "tailwindConfig": { "type": "string", diff --git a/packages/esbuild/src/executors/esbuild/esbuild.impl.ts b/packages/esbuild/src/executors/esbuild/esbuild.impl.ts index 239b74828bd20..91109065b7119 100644 --- a/packages/esbuild/src/executors/esbuild/esbuild.impl.ts +++ b/packages/esbuild/src/executors/esbuild/esbuild.impl.ts @@ -1,7 +1,7 @@ import 'dotenv/config'; import * as chalk from 'chalk'; import type { ExecutorContext } from '@nx/devkit'; -import { cacheDir, joinPathFragments, logger } from '@nx/devkit'; +import { cacheDir, joinPathFragments, logger, stripIndents } from '@nx/devkit'; import { copyAssets, copyPackageJson, @@ -74,6 +74,13 @@ export async function* esbuildExecutor( let packageJsonResult; if (options.generatePackageJson) { + if (context.projectGraph.nodes[context.projectName].type !== 'app') { + logger.warn( + stripIndents`The project ${context.projectName} is using the 'generatePackageJson' option which is deprecated for library projects. It should only be used for applications. + For libraries, configure the project to use the '@nx/dependency-checks' ESLint rule instead (https://nx.dev/packages/eslint-plugin/documents/dependency-checks).` + ); + } + const cpjOptions: CopyPackageJsonOptions = { ...options, // TODO(jack): make types generate with esbuild diff --git a/packages/js/src/executors/swc/schema.json b/packages/js/src/executors/swc/schema.json index 6b356438d8d1b..07c7c2ac44de5 100644 --- a/packages/js/src/executors/swc/schema.json +++ b/packages/js/src/executors/swc/schema.json @@ -69,13 +69,15 @@ "updateBuildableProjectDepsInPackageJson": { "type": "boolean", "description": "Whether to update the buildable project dependencies in the build output package.json.", - "default": false + "default": false, + "x-deprecated": "Configure the project to use the '@nx/dependency-checks' ESLint rule instead (https://nx.dev/packages/eslint-plugin/documents/dependency-checks). It will be removed in v17." }, "buildableProjectDepsInPackageJsonType": { "type": "string", "description": "When `updateBuildableProjectDepsInPackageJson` is `true`, this adds dependencies to either `peerDependencies` or `dependencies`.", "enum": ["dependencies", "peerDependencies"], - "default": "peerDependencies" + "default": "peerDependencies", + "x-deprecated": "Configure the project to use the '@nx/dependency-checks' ESLint rule instead (https://nx.dev/packages/eslint-plugin/documents/dependency-checks). It will be removed in v17." }, "external": { "description": "A list projects to be treated as external. This feature is experimental", diff --git a/packages/js/src/executors/tsc/schema.json b/packages/js/src/executors/tsc/schema.json index 03078862a882d..1e0552ce4ba4a 100644 --- a/packages/js/src/executors/tsc/schema.json +++ b/packages/js/src/executors/tsc/schema.json @@ -57,13 +57,15 @@ "updateBuildableProjectDepsInPackageJson": { "type": "boolean", "description": "Whether to update the buildable project dependencies in the build output package.json.", - "default": false + "default": false, + "x-deprecated": "Configure the project to use the '@nx/dependency-checks' ESLint rule instead (https://nx.dev/packages/eslint-plugin/documents/dependency-checks). It will be removed in v17." }, "buildableProjectDepsInPackageJsonType": { "type": "string", "description": "When `updateBuildableProjectDepsInPackageJson` is `true`, this adds dependencies to either `peerDependencies` or `dependencies`.", "enum": ["dependencies", "peerDependencies"], - "default": "peerDependencies" + "default": "peerDependencies", + "x-deprecated": "Configure the project to use the '@nx/dependency-checks' ESLint rule instead (https://nx.dev/packages/eslint-plugin/documents/dependency-checks). It will be removed in v17." }, "external": { "description": "A list projects to be treated as external. This feature is experimental", diff --git a/packages/js/src/utils/schema.d.ts b/packages/js/src/utils/schema.d.ts index fec4d02bcefc1..b07b790e4ec42 100644 --- a/packages/js/src/utils/schema.d.ts +++ b/packages/js/src/utils/schema.d.ts @@ -42,7 +42,17 @@ export interface ExecutorOptions { watch: boolean; clean?: boolean; transformers: TransformerEntry[]; + /** + * @deprecated Configure the project to use the `@nx/dependency-checks` ESLint + * rule instead (https://nx.dev/packages/eslint-plugin/documents/dependency-checks). + * It will be removed in v17. + */ updateBuildableProjectDepsInPackageJson?: boolean; + /** + * @deprecated Configure the project to use the `@nx/dependency-checks` ESLint + * rule instead (https://nx.dev/packages/eslint-plugin/documents/dependency-checks). + * It will be removed in v17. + */ buildableProjectDepsInPackageJsonType?: 'dependencies' | 'peerDependencies'; external?: 'all' | 'none' | string[]; externalBuildTargets?: string[]; diff --git a/packages/rollup/src/executors/rollup/schema.d.ts b/packages/rollup/src/executors/rollup/schema.d.ts index 750d186e3abf1..9a08e09638f6c 100644 --- a/packages/rollup/src/executors/rollup/schema.d.ts +++ b/packages/rollup/src/executors/rollup/schema.d.ts @@ -24,7 +24,17 @@ export interface RollupExecutorOptions { rollupConfig?: string | string[]; watch?: boolean; assets?: any[]; + /** + * @deprecated Configure the project to use the `@nx/dependency-checks` ESLint + * rule instead (https://nx.dev/packages/eslint-plugin/documents/dependency-checks). + * It will be removed in v17. + */ updateBuildableProjectDepsInPackageJson?: boolean; + /** + * @deprecated Configure the project to use the `@nx/dependency-checks` ESLint + * rule instead (https://nx.dev/packages/eslint-plugin/documents/dependency-checks). + * It will be removed in v17. + */ buildableProjectDepsInPackageJsonType?: 'dependencies' | 'peerDependencies'; deleteOutputPath?: boolean; format?: string[]; diff --git a/packages/rollup/src/executors/rollup/schema.json b/packages/rollup/src/executors/rollup/schema.json index c30f11f6d18c8..3a0e4626e3458 100644 --- a/packages/rollup/src/executors/rollup/schema.json +++ b/packages/rollup/src/executors/rollup/schema.json @@ -5,19 +5,6 @@ "description": "Packages a library for different web usages (ESM, CommonJS).", "cli": "nx", "type": "object", - "presets": [ - { - "name": "Including Dependencies in package.json", - "keys": [ - "main", - "outputPath", - "project", - "tsConfig", - "buildableProjectDepsInPackageJsonType", - "updateBuildableProjectDepsInPackageJson" - ] - } - ], "properties": { "project": { "type": "string", @@ -92,13 +79,15 @@ "updateBuildableProjectDepsInPackageJson": { "type": "boolean", "description": "Update buildable project dependencies in `package.json`.", - "default": false + "default": false, + "x-deprecated": "Configure the project to use the '@nx/dependency-checks' ESLint rule instead (https://nx.dev/packages/eslint-plugin/documents/dependency-checks). It will be removed in v17." }, "buildableProjectDepsInPackageJsonType": { "type": "string", "description": "When `updateBuildableProjectDepsInPackageJson` is `true`, this adds dependencies to either `peerDependencies` or `dependencies`.", "enum": ["dependencies", "peerDependencies"], - "default": "peerDependencies" + "default": "peerDependencies", + "x-deprecated": "Configure the project to use the '@nx/dependency-checks' ESLint rule instead (https://nx.dev/packages/eslint-plugin/documents/dependency-checks). It will be removed in v17." }, "rollupConfig": { "oneOf": [ diff --git a/packages/vite/src/executors/build/build.impl.ts b/packages/vite/src/executors/build/build.impl.ts index 015177879c8dd..1ec6aea2db3cc 100644 --- a/packages/vite/src/executors/build/build.impl.ts +++ b/packages/vite/src/executors/build/build.impl.ts @@ -1,5 +1,10 @@ import 'dotenv/config'; -import { ExecutorContext, writeJsonFile } from '@nx/devkit'; +import { + ExecutorContext, + logger, + stripIndents, + writeJsonFile, +} from '@nx/devkit'; import { build, InlineConfig, mergeConfig } from 'vite'; import { getProjectTsConfigPath, @@ -52,6 +57,13 @@ export async function* viteBuildExecutor( // Generate a package.json if option has been set. if (options.generatePackageJson) { + if (context.projectGraph.nodes[context.projectName].type !== 'app') { + logger.warn( + stripIndents`The project ${context.projectName} is using the 'generatePackageJson' option which is deprecated for library projects. It should only be used for applications. + For libraries, configure the project to use the '@nx/dependency-checks' ESLint rule instead (https://nx.dev/packages/eslint-plugin/documents/dependency-checks).` + ); + } + const builtPackageJson = createPackageJson( context.projectName, context.projectGraph, diff --git a/packages/webpack/src/executors/webpack/webpack.impl.ts b/packages/webpack/src/executors/webpack/webpack.impl.ts index 73982730683a3..68516586e0258 100644 --- a/packages/webpack/src/executors/webpack/webpack.impl.ts +++ b/packages/webpack/src/executors/webpack/webpack.impl.ts @@ -1,5 +1,5 @@ import 'dotenv/config'; -import { ExecutorContext, logger } from '@nx/devkit'; +import { ExecutorContext, logger, stripIndents } from '@nx/devkit'; import { eachValueFrom } from '@nx/devkit/src/utils/rxjs-for-await'; import type { Configuration, Stats } from 'webpack'; import { from, of } from 'rxjs'; @@ -141,6 +141,13 @@ export async function* webpackExecutor( deleteOutputDir(context.root, options.outputPath); } + if (options.generatePackageJson && metadata.projectType !== 'application') { + logger.warn( + stripIndents`The project ${context.projectName} is using the 'generatePackageJson' option which is deprecated for library projects. It should only be used for applications. + For libraries, configure the project to use the '@nx/dependency-checks' ESLint rule instead (https://nx.dev/packages/eslint-plugin/documents/dependency-checks).` + ); + } + const configs = await getWebpackConfigs(options, context); return yield* eachValueFrom( From 1bc58c997d48c345778a8c63776de5a56e214416 Mon Sep 17 00:00:00 2001 From: Victor Savkin Date: Mon, 10 Jul 2023 14:49:40 -0400 Subject: [PATCH 050/262] feat(core): throw an error when unknown local cache source --- docs/generated/manifests/menus.json | 16 +++++ docs/generated/manifests/recipes.json | 20 ++++++ docs/map.json | 6 ++ docs/shared/guides/unknown-local-cache.md | 86 +++++++++++++++++++++++ docs/shared/reference/sitemap.md | 1 + package.json | 3 +- packages/nx/package.json | 3 +- packages/nx/src/tasks-runner/cache.ts | 44 ++++++++++++ pnpm-lock.yaml | 4 +- 9 files changed, 180 insertions(+), 3 deletions(-) create mode 100644 docs/shared/guides/unknown-local-cache.md diff --git a/docs/generated/manifests/menus.json b/docs/generated/manifests/menus.json index 4d33016812df3..8dd3c2713a8a0 100644 --- a/docs/generated/manifests/menus.json +++ b/docs/generated/manifests/menus.json @@ -3291,6 +3291,14 @@ "isExternal": false, "children": [], "disableCollapsible": false + }, + { + "name": "Unknown Local Cache Error", + "path": "/recipes/other/unknown-local-cache", + "id": "unknown-local-cache", + "isExternal": false, + "children": [], + "disableCollapsible": false } ], "disableCollapsible": false @@ -3494,6 +3502,14 @@ "isExternal": false, "children": [], "disableCollapsible": false + }, + { + "name": "Unknown Local Cache Error", + "path": "/recipes/other/unknown-local-cache", + "id": "unknown-local-cache", + "isExternal": false, + "children": [], + "disableCollapsible": false } ] }, diff --git a/docs/generated/manifests/recipes.json b/docs/generated/manifests/recipes.json index dee91d895781c..ea67ae2fe2120 100644 --- a/docs/generated/manifests/recipes.json +++ b/docs/generated/manifests/recipes.json @@ -1597,6 +1597,16 @@ "isExternal": false, "path": "/recipes/other/standalone-ngrx-apis", "tags": [] + }, + { + "id": "unknown-local-cache", + "name": "Unknown Local Cache Error", + "description": "", + "file": "shared/guides/unknown-local-cache", + "itemList": [], + "isExternal": false, + "path": "/recipes/other/unknown-local-cache", + "tags": [] } ], "isExternal": false, @@ -1852,5 +1862,15 @@ "isExternal": false, "path": "/recipes/other/standalone-ngrx-apis", "tags": [] + }, + "/recipes/other/unknown-local-cache": { + "id": "unknown-local-cache", + "name": "Unknown Local Cache Error", + "description": "", + "file": "shared/guides/unknown-local-cache", + "itemList": [], + "isExternal": false, + "path": "/recipes/other/unknown-local-cache", + "tags": [] } } diff --git a/docs/map.json b/docs/map.json index de3bc1853a0c5..d3fbcc151e952 100644 --- a/docs/map.json +++ b/docs/map.json @@ -1458,6 +1458,12 @@ "id": "standalone-ngrx-apis", "tags": [], "file": "shared/recipes/standalone-ngrx-apis" + }, + { + "name": "Unknown Local Cache Error", + "id": "unknown-local-cache", + "tags": [], + "file": "shared/guides/unknown-local-cache" } ] } diff --git a/docs/shared/guides/unknown-local-cache.md b/docs/shared/guides/unknown-local-cache.md new file mode 100644 index 0000000000000..2fb83f78d3bda --- /dev/null +++ b/docs/shared/guides/unknown-local-cache.md @@ -0,0 +1,86 @@ +# Unknown Local Cache Error + +This document will explain why the following error happens and how to address it. + +``` +NX Invalid Cache Directory for Task "myapp:build" + +The local cache artifact in "node_modules/.cache/nx/786524780459028195" was not been generated on this machine. +As a result, the cache's content integrity cannot be confirmed, which may make cache restoration potentially unsafe. +If your machine ID has changed since the artifact was cached, run "nx reset" to fix this issue. +Read about the error and how to address it here: https://nx.dev/recipes/other/unknown-local-cache +``` + +## Nx Tracks Cache Source + +Nx can cache tasks, which can drastically speed up your CI and local builds. However, this comes with the potential risk +of "cache poisoning", where cache artifacts could be intentionally or inadvertently overwritten. If another user +executes a task that matches the hash of the tainted artifact, they could retrieve the corrupted artifact and use it as +the outcome of the task. Nx and Nx Cloud contain several safeguards to minimize the likelihood of cache poisoning or, in +the case of Nx Cloud, completely prevent it. + +The error above is one such safeguard. + +Nx trusts the local cache. If you executed a task and stored the corresponding cached artifact on your machine, you can +safely restore it on the same machine without worrying about cache poisoning. After all, in order to tamper with the +cache artifact, the actor would need access to the machine itself. + +However, when artifacts in the local cache are created by a different machine, we cannot make such assumption. By +default, Nx will refuse to use such artifacts and will throw the "Invalid Cache Directory" error. + +## Your MachineId Has Changed + +Upgrading your computer's hardware may alter its Machine ID, yielding the error above. To fix it execute `nx reset` to +remove all the cache directories created under the previous Machine ID. After doing so, you should no longer see the +error. After doing so, you should no longer see the error. + +## You Share Cache with Another Machine Using a Network Drive + +You can prefix any Nx command with `NX_REJECT_UNKNOWN_LOCAL_CACHE=0` to ignore the error ( +e.g., `NX REJECT_UNKNOWN_LOCAL_CACHE=0 nx run-many -t build test`). This is similar to +setting `NODE_TLS_REJECT_UNAUTHORIZED=0` to ignore any errors stemming form self-signed certificates. Even though it +will make it work, this approach is discouraged. + +Storing Nx's local cache on a network drive can present security risks. When a network drive is shared, every CI run has +access to all the previously created Nx cache artifacts. Hence, it is plausible for every single artifact - for every +single task hash - to be accessed without leaving any trace. This is feasible due to the network drive's capability to +allow overwrites. + +Instead of sharing the network drive, we highly recommend you to implement the `RemoteCache` interface. + +## Implementing Remote Cache Interface + +This is the interface: + +```typescript +interface RemoteCache { + retrieve(hash: string, cachePath: string); + + store(hash: string, cachePath: string); +} +``` + +> You will need to wrap the default tasks runner to provide the remote cache implementation. + +## How Nx Cloud Makes Sure Sharing Cache is Safe + +The Nx Cloud runner provides an implementation of `RemoteCache` which does the following things making sharing the cache safe: + +1. **Immutable Artifacts:** Nx Cloud allows you to create and store new artifacts without the ability to override the + existing ones. This prevents any possibility of poisoning an existing artifact. This is achieved by managing the + cache using short-lived signed URLs. + +2. **Artifact Accessibility:** Nx Cloud provides access to the cache artifact specifically for the task that is + currently being executed. It restricts the ability to list all cache artifacts. + +3. **Visibility Control:** Nx Cloud comes with options to manage the visibility of your cache artifacts. For instance, + the cache artifacts created in `main` might be accessible by anyone across any branch, whereas the artifacts created + in your PR could be shared only within your PR runs. + +4. **Access Token Traceability:** Nx Cloud keeps a record of the access token used to create a cache artifact. In case + an access token gets compromised it can be easily removed, in turn deleting all the cache artifacts that were created + using it. + +Nx Cloud is not the only remote cache you can use. If you are using a different remote cache or using your +own implementation, we would highly recommend ensuring that the same safety mechanisms as Nx Cloud have been put in +place. diff --git a/docs/shared/reference/sitemap.md b/docs/shared/reference/sitemap.md index 895f7a1b6952b..1982d9287a28e 100644 --- a/docs/shared/reference/sitemap.md +++ b/docs/shared/reference/sitemap.md @@ -219,6 +219,7 @@ - [Identify Dependencies Between Folders](/recipes/other/identify-dependencies-between-folders) - [Rescope Packages from @nrwl to @nx](/recipes/other/rescope) - [Standalone NgRx APIs](/recipes/other/standalone-ngrx-apis) + - [Unknown Local Cache Error](/recipes/other/unknown-local-cache) - Plugins diff --git a/package.json b/package.json index 72295477ea91c..8185fee050a58 100644 --- a/package.json +++ b/package.json @@ -330,7 +330,8 @@ "tailwindcss": "3.2.4", "tslib": "^2.3.0", "vitest": "^0.32.0", - "weak-napi": "^2.0.2" + "weak-napi": "^2.0.2", + "node-machine-id": "1.1.12" }, "resolutions": { "minimist": "^1.2.6", diff --git a/packages/nx/package.json b/packages/nx/package.json index fc40c07e5cac8..33ade2fbc4acf 100644 --- a/packages/nx/package.json +++ b/packages/nx/package.json @@ -64,7 +64,8 @@ "tslib": "^2.3.0", "v8-compile-cache": "2.3.0", "yargs": "^17.6.2", - "yargs-parser": "21.1.1" + "yargs-parser": "21.1.1", + "node-machine-id": "1.1.12" }, "peerDependencies": { "@swc-node/register": "^1.4.2", diff --git a/packages/nx/src/tasks-runner/cache.ts b/packages/nx/src/tasks-runner/cache.ts index 39e05d4c863f1..16d22c1e79dd0 100644 --- a/packages/nx/src/tasks-runner/cache.ts +++ b/packages/nx/src/tasks-runner/cache.ts @@ -6,6 +6,7 @@ import { DefaultTasksRunnerOptions } from './default-tasks-runner'; import { spawn } from 'child_process'; import { cacheDir } from '../utils/cache-directory'; import { Task } from '../config/task-graph'; +import { machineId } from 'node-machine-id'; export type CachedResult = { terminalOutput: string; @@ -20,6 +21,8 @@ export class Cache { cachePath = this.createCacheDir(); terminalOutputsDir = this.createTerminalOutputsDir(); + private _currentMachineId: string = null; + constructor(private readonly options: DefaultTasksRunnerOptions) {} removeOldCacheRecords() { @@ -44,6 +47,20 @@ export class Cache { } } + async currentMachineId() { + if (!this._currentMachineId) { + try { + this._currentMachineId = await machineId(); + } catch (e) { + if (process.env.NX_VERBOSE_LOGGING == 'true') { + console.log(`Unable to get machineId. Error: ${e.message}`); + } + this._currentMachineId = ''; + } + } + return this._currentMachineId; + } + async get(task: Task): Promise { const res = await this.getFromLocalDir(task); @@ -98,6 +115,7 @@ export class Cache { // so if the process gets terminated while we are copying stuff into cache, // the cache entry won't be used. await writeFile(join(td, 'code'), code.toString()); + await writeFile(join(td, 'source'), await this.currentMachineId()); await writeFile(tdCommit, 'true'); if (this.options.remoteCache) { @@ -208,6 +226,32 @@ export class Cache { try { code = Number(await readFile(join(td, 'code'), 'utf-8')); } catch {} + + let sourceMachineId = null; + try { + sourceMachineId = await readFile(join(td, 'source'), 'utf-8'); + } catch {} + + if ( + sourceMachineId && + sourceMachineId != (await this.currentMachineId()) + ) { + if ( + process.env.NX_REJECT_UNKNOWN_LOCAL_CACHE != '0' && + process.env.NX_REJECT_UNKNOWN_LOCAL_CACHE != 'false' + ) { + const error = [ + `Invalid Cache Directory for Task "${task.id}"`, + `The local cache artifact in "${td}" was not been generated on this machine.`, + `As a result, the cache's content integrity cannot be confirmed, which may make cache restoration potentially unsafe.`, + `If your machine ID has changed since the artifact was cached, run "nx reset" to fix this issue.`, + `Read about the error and how to address it here: https://nx.dev/recipes/other/unknown-local-cache`, + ``, + ].join('\n'); + throw new Error(error); + } + } + return { terminalOutput, outputsPath: join(td, 'outputs'), diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 09a6392aee264..b323b4f4ca733 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -101,6 +101,9 @@ dependencies: next-seo: specifier: ^5.13.0 version: 5.13.0(next@13.3.4)(react-dom@18.2.0)(react@18.2.0) + node-machine-id: + specifier: 1.1.12 + version: 1.1.12 npm-run-path: specifier: ^4.0.1 version: 4.0.1 @@ -20359,7 +20362,6 @@ packages: /node-machine-id@1.1.12: resolution: {integrity: sha512-QNABxbrPa3qEIfrE6GOJ7BYIuignnJw7iQ2YPbc3Nla1HzRJjXzZOiikfF8m7eAMfichLt3M4VgLOetqgDmgGQ==} - dev: true /node-releases@2.0.10: resolution: {integrity: sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==} From bcb3251ef5ba65ac4f2e7b14a0e8c8e16c5b49da Mon Sep 17 00:00:00 2001 From: Jason Jean Date: Tue, 11 Jul 2023 15:00:51 -0400 Subject: [PATCH 051/262] fix(core): fix project configuration typings (#18073) --- ...project-graph-incremental-recomputation.ts | 15 ++++++- .../src/project-graph/file-map-utils.spec.ts | 42 +++++++++---------- .../nx/src/project-graph/file-map-utils.ts | 11 ++--- .../utils/retrieve-workspace-files.ts | 2 +- 4 files changed, 41 insertions(+), 29 deletions(-) diff --git a/packages/nx/src/daemon/server/project-graph-incremental-recomputation.ts b/packages/nx/src/daemon/server/project-graph-incremental-recomputation.ts index cf93177187fa0..3627baeb287d2 100644 --- a/packages/nx/src/daemon/server/project-graph-incremental-recomputation.ts +++ b/packages/nx/src/daemon/server/project-graph-incremental-recomputation.ts @@ -22,6 +22,7 @@ import { retrieveWorkspaceFiles, retrieveProjectConfigurations, } from '../../project-graph/utils/retrieve-workspace-files'; +import { ProjectConfiguration } from '../../config/workspace-json-project-json'; let cachedSerializedProjectGraphPromise: Promise<{ error: Error | null; @@ -115,8 +116,18 @@ export function addUpdatedAndDeletedFiles( } } -function computeWorkspaceConfigHash(projectsConfigurations: any) { - return hashArray([JSON.stringify(projectsConfigurations)]); +function computeWorkspaceConfigHash( + projectsConfigurations: Record +) { + const projectConfigurationStrings = Object.entries(projectsConfigurations) + .sort(([projectNameA], [projectNameB]) => + projectNameA.localeCompare(projectNameB) + ) + .map( + ([projectName, projectConfig]) => + `${projectName}:${JSON.stringify(projectConfig)}` + ); + return hashArray(projectConfigurationStrings); } /** diff --git a/packages/nx/src/project-graph/file-map-utils.spec.ts b/packages/nx/src/project-graph/file-map-utils.spec.ts index edcdf7d5622d8..1a9eb230f325c 100644 --- a/packages/nx/src/project-graph/file-map-utils.spec.ts +++ b/packages/nx/src/project-graph/file-map-utils.spec.ts @@ -1,24 +1,26 @@ +import { ProjectType } from '../config/workspace-json-project-json'; import { createProjectFileMap, updateProjectFileMap } from './file-map-utils'; describe('fileMapUtils', () => { describe('createFileMap', () => { it('should map files to projects', () => { const projectsConfigurations = { + version: 2, projects: { demo: { root: 'apps/demo', sourceRoot: 'apps/demo/src', - projectType: 'application', + projectType: 'application' as ProjectType, }, 'demo-e2e': { root: 'apps/demo-e2e', sourceRoot: 'apps/demo-e2e/src', - projectType: 'application', + projectType: 'application' as ProjectType, }, ui: { root: 'libs/ui', sourceRoot: 'libs/ui/src', - projectType: 'library', + projectType: 'library' as ProjectType, }, }, }; @@ -29,7 +31,7 @@ describe('fileMapUtils', () => { { file: 'tools/myfile.txt', hash: 'some-hash' }, ]; - const result = createProjectFileMap(projectsConfigurations as any, files); + const result = createProjectFileMap(projectsConfigurations, files); expect(result).toEqual({ projectFileMap: { @@ -52,22 +54,20 @@ describe('fileMapUtils', () => { describe('updateFileMap', () => { it('should map files to projects', () => { const projectsConfigurations = { - projects: { - demo: { - root: 'apps/demo', - sourceRoot: 'apps/demo/src', - projectType: 'application', - }, - 'demo-e2e': { - root: 'apps/demo-e2e', - sourceRoot: 'apps/demo-e2e/src', - projectType: 'application', - }, - ui: { - root: 'libs/ui', - sourceRoot: 'libs/ui/src', - projectType: 'library', - }, + demo: { + root: 'apps/demo', + sourceRoot: 'apps/demo/src', + projectType: 'application' as ProjectType, + }, + 'demo-e2e': { + root: 'apps/demo-e2e', + sourceRoot: 'apps/demo-e2e/src', + projectType: 'application' as ProjectType, + }, + ui: { + root: 'libs/ui', + sourceRoot: 'libs/ui/src', + projectType: 'library' as ProjectType, }, }; const files = [ @@ -87,7 +87,7 @@ describe('fileMapUtils', () => { ], }; const result = updateProjectFileMap( - projectsConfigurations as any, + projectsConfigurations, projectFileMap, files, new Map([ diff --git a/packages/nx/src/project-graph/file-map-utils.ts b/packages/nx/src/project-graph/file-map-utils.ts index 270ea7ac8c494..35f568c1138b7 100644 --- a/packages/nx/src/project-graph/file-map-utils.ts +++ b/packages/nx/src/project-graph/file-map-utils.ts @@ -7,7 +7,10 @@ import { createProjectRootMappingsFromProjectConfigurations, findProjectForPath, } from './utils/find-project-for-path'; -import { ProjectsConfigurations } from '../config/workspace-json-project-json'; +import { + ProjectConfiguration, + ProjectsConfigurations, +} from '../config/workspace-json-project-json'; import { daemonClient } from '../daemon/client/client'; import { readProjectsConfigurationFromProjectGraph } from './project-graph'; import { fileHasher } from '../hasher/file-hasher'; @@ -52,16 +55,14 @@ export function createProjectFileMap( } export function updateProjectFileMap( - projectsConfigurations: ProjectsConfigurations, + projectsConfigurations: Record, projectFileMap: ProjectFileMap, allWorkspaceFiles: FileData[], updatedFiles: Map, deletedFiles: string[] ): { projectFileMap: ProjectFileMap; allWorkspaceFiles: FileData[] } { const projectRootMappings = - createProjectRootMappingsFromProjectConfigurations( - projectsConfigurations.projects - ); + createProjectRootMappingsFromProjectConfigurations(projectsConfigurations); for (const f of updatedFiles.keys()) { const matchingProjectFiles = diff --git a/packages/nx/src/project-graph/utils/retrieve-workspace-files.ts b/packages/nx/src/project-graph/utils/retrieve-workspace-files.ts index b2df26cd1f039..3e8a0d9175741 100644 --- a/packages/nx/src/project-graph/utils/retrieve-workspace-files.ts +++ b/packages/nx/src/project-graph/utils/retrieve-workspace-files.ts @@ -84,7 +84,7 @@ export async function retrieveWorkspaceFiles( export async function retrieveProjectConfigurations( workspaceRoot: string, nxJson: NxJsonConfiguration -) { +): Promise> { const { getProjectConfigurations } = require('../../native'); const globs = await configurationGlobs(workspaceRoot, nxJson); return getProjectConfigurations( From 90172c579c70f3e793b9eb2867e7428a869f954a Mon Sep 17 00:00:00 2001 From: Caleb Ukle Date: Tue, 11 Jul 2023 15:15:33 -0500 Subject: [PATCH 052/262] feat(testing): update jest to v29.6.1 (#18061) --- packages/jest/migrations.json | 33 +++++++++++++++++++++++++++++ packages/jest/src/utils/versions.ts | 6 +++--- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/packages/jest/migrations.json b/packages/jest/migrations.json index 7189072a8ad46..fa19e79b3e5f7 100644 --- a/packages/jest/migrations.json +++ b/packages/jest/migrations.json @@ -285,6 +285,39 @@ "alwaysAddToPackageJson": false } } + }, + "16.5.2": { + "version": "16.5.2-beta.0", + "packages": { + "jest": { + "version": "~29.6.1", + "alwaysAddToPackageJson": false + }, + "@types/jest": { + "version": "~29.5.3", + "alwaysAddToPackageJson": false + }, + "expect": { + "version": "~29.6.1", + "alwaysAddToPackageJson": false + }, + "@jest/globals": { + "version": "~29.6.1", + "alwaysAddToPackageJson": false + }, + "jest-jasmine2": { + "version": "~29.6.1", + "alwaysAddToPackageJson": false + }, + "jest-environment-jsdom": { + "version": "~29.6.1", + "alwaysAddToPackageJson": false + }, + "babel-jest": { + "version": "~29.6.1", + "alwaysAddToPackageJson": false + } + } } } } diff --git a/packages/jest/src/utils/versions.ts b/packages/jest/src/utils/versions.ts index fcee08950aa0c..46ad0dfe41ab0 100644 --- a/packages/jest/src/utils/versions.ts +++ b/packages/jest/src/utils/versions.ts @@ -1,7 +1,7 @@ export const nxVersion = require('../../package.json').version; -export const jestVersion = '^29.4.1'; -export const babelJestVersion = '^29.4.1'; -export const jestTypesVersion = '^29.4.0'; +export const jestVersion = '^29.6.1'; +export const babelJestVersion = '^29.6.1'; +export const jestTypesVersion = '^29.5.3'; export const tsJestVersion = '^29.1.0'; export const tslibVersion = '^2.3.0'; export const swcJestVersion = '0.2.20'; From 460e469617e42c18bd44683c0cbafbd0f9c0591c Mon Sep 17 00:00:00 2001 From: Jonathan Cammisuli Date: Tue, 11 Jul 2023 16:46:00 -0400 Subject: [PATCH 053/262] fix(core): remove throttle from watch (#18077) --- packages/nx/src/native/watch/watch_config.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/nx/src/native/watch/watch_config.rs b/packages/nx/src/native/watch/watch_config.rs index 5605eaca0e496..073b6bf139319 100644 --- a/packages/nx/src/native/watch/watch_config.rs +++ b/packages/nx/src/native/watch/watch_config.rs @@ -36,7 +36,6 @@ pub(super) async fn create_runtime( runtime.filterer(Arc::new(WatchFilterer { inner: IgnoreFilterer(filter), })); - runtime.action_throttle(Duration::from_millis(500)); // let watch_directories = get_watch_directories(origin); // trace!(directories = ?watch_directories, "watching"); From 2128f8e3e2d79397892aabad57ae69690d5aaa19 Mon Sep 17 00:00:00 2001 From: Caleb Ukle Date: Tue, 11 Jul 2023 15:47:56 -0500 Subject: [PATCH 054/262] feat(testing): add @nx/playwright plugin (#17975) --- CODEOWNERS | 2 + e2e/playwright/jest.config.ts | 13 ++ e2e/playwright/project.json | 11 ++ e2e/playwright/src/playwright.test.ts | 171 ++++++++++++++++++ e2e/playwright/tsconfig.json | 13 ++ e2e/playwright/tsconfig.spec.json | 20 ++ e2e/utils/create-project-utils.ts | 1 + e2e/utils/get-env-info.ts | 4 + jest.config.ts | 2 +- packages/nx/package.json | 1 + packages/playwright/.eslintrc.json | 25 +++ packages/playwright/README.md | 11 ++ packages/playwright/executors.json | 16 ++ packages/playwright/jest.config.ts | 10 + packages/playwright/package.json | 43 +++++ packages/playwright/project.json | 50 +++++ .../src/executors/playwright/compat.ts | 4 + .../src/executors/playwright/playwright.ts | 113 ++++++++++++ .../src/executors/playwright/schema.json | 155 ++++++++++++++++ packages/playwright/src/index.ts | 4 + packages/playwright/tsconfig.json | 16 ++ packages/playwright/tsconfig.lib.json | 10 + packages/playwright/tsconfig.spec.json | 14 ++ tsconfig.base.json | 1 + 24 files changed, 709 insertions(+), 1 deletion(-) create mode 100644 e2e/playwright/jest.config.ts create mode 100644 e2e/playwright/project.json create mode 100644 e2e/playwright/src/playwright.test.ts create mode 100644 e2e/playwright/tsconfig.json create mode 100644 e2e/playwright/tsconfig.spec.json create mode 100644 packages/playwright/.eslintrc.json create mode 100644 packages/playwright/README.md create mode 100644 packages/playwright/executors.json create mode 100644 packages/playwright/jest.config.ts create mode 100644 packages/playwright/package.json create mode 100644 packages/playwright/project.json create mode 100644 packages/playwright/src/executors/playwright/compat.ts create mode 100644 packages/playwright/src/executors/playwright/playwright.ts create mode 100644 packages/playwright/src/executors/playwright/schema.json create mode 100644 packages/playwright/src/index.ts create mode 100644 packages/playwright/tsconfig.json create mode 100644 packages/playwright/tsconfig.lib.json create mode 100644 packages/playwright/tsconfig.spec.json diff --git a/CODEOWNERS b/CODEOWNERS index e118e1e31ea1d..3f039747aebfd 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -99,6 +99,8 @@ pnpm-lock.yaml @nrwl/nx-pipelines-reviewers /e2e/cypress/** @nrwl/nx-testing-tools-reviewers /packages/jest/** @nrwl/nx-testing-tools-reviewers /e2e/jest/** @nrwl/nx-testing-tools-reviewers +/packages/playwright/** @nrwl/nx-testing-tools-reviewers +/e2e/playwright/** @nrwl/nx-testing-tools-reviewers # Linter /docs/generated/packages/eslint-plugin/** @nrwl/nx-linter-reviewers @nrwl/nx-docs-reviewers diff --git a/e2e/playwright/jest.config.ts b/e2e/playwright/jest.config.ts new file mode 100644 index 0000000000000..7c27da3d36d24 --- /dev/null +++ b/e2e/playwright/jest.config.ts @@ -0,0 +1,13 @@ +/* eslint-disable */ +export default { + transform: { + '^.+\\.[tj]sx?$': ['ts-jest', { tsconfig: '/tsconfig.spec.json' }], + }, + moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html'], + maxWorkers: 1, + globals: {}, + globalSetup: '../utils/global-setup.ts', + globalTeardown: '../utils/global-teardown.ts', + displayName: 'e2e-playwright', + preset: '../../jest.preset.js', +}; diff --git a/e2e/playwright/project.json b/e2e/playwright/project.json new file mode 100644 index 0000000000000..f31e220d5879b --- /dev/null +++ b/e2e/playwright/project.json @@ -0,0 +1,11 @@ +{ + "name": "e2e-playwright", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "e2e/playwright", + "projectType": "application", + "targets": { + "e2e": {}, + "run-e2e-tests": {} + }, + "implicitDependencies": ["playwright"] +} diff --git a/e2e/playwright/src/playwright.test.ts b/e2e/playwright/src/playwright.test.ts new file mode 100644 index 0000000000000..05490b08ab772 --- /dev/null +++ b/e2e/playwright/src/playwright.test.ts @@ -0,0 +1,171 @@ +import { + cleanupProject, + newProject, + uniq, + createFile, + runCLI, + packageInstall, + runCommand, +} from '@nx/e2e/utils'; + +const TEN_MINS_MS = 600_000; +describe('Playwright E2E Test runner', () => { + beforeAll(() => { + newProject({ name: uniq('playwright') }); + packageInstall('@playwright/test', undefined, '^1.30.0', 'dev'); + runCommand('npx playwright install --with-deps'); + }); + + afterAll(() => cleanupProject()); + + it( + 'should test example app', + () => { + //TODO: remove when generators are setup.Need to have basic workspace deps setup + runCLI(`g @nx/js:init`); + addSampleProject(); + + // NOTE: playwright throws errors if it detects running inside jest process. tmp remove and restore the env var for playwright to run + const results = runCLI(`e2e demo-e2e`); + expect(results).toContain('6 passed'); + expect(results).toContain('Successfully ran target e2e for project'); + }, + TEN_MINS_MS + ); +}); + +// TODO: remove this when there are project generators +function addSampleProject() { + createFile( + 'apps/demo-e2e/src/example.spec.ts', + ` +import { test, expect } from '@playwright/test'; + +test('has title', async ({ page }) => { + await page.goto('https://playwright.dev/'); + + // Expect a title "to contain" a substring. + await expect(page).toHaveTitle(/Playwright/); +}); + +test('get started link', async ({ page }) => { + await page.goto('https://playwright.dev/'); + + // Click the get started link. + await page.getByRole('link', { name: 'Get started' }).click(); + + // Expects the URL to contain intro. + await expect(page).toHaveURL(/.*intro/); +}); +` + ); + createFile( + 'apps/demo-e2e/playwright.config.ts', + ` +import { defineConfig, devices } from '@playwright/test'; + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: './src', + outputDir: '../../dist/playwright/apps/demo-e2e/output', + /* Run tests in files in parallel */ + fullyParallel: true, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: [ + [ + 'html', + { + outputFolder: + '../../dist/playwright/apps/demo-e2e/playwright-report', + }, + ], + ], + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Base URL to use in actions like await page.goto('/'). */ + // baseURL: 'http://127.0.0.1:3000', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + }, + + { + name: 'firefox', + use: { ...devices['Desktop Firefox'] }, + }, + + { + name: 'webkit', + use: { ...devices['Desktop Safari'] }, + }, + + /* Test against mobile viewports. */ + // { + // name: 'Mobile Chrome', + // use: { ...devices['Pixel 5'] }, + // }, + // { + // name: 'Mobile Safari', + // use: { ...devices['iPhone 12'] }, + // }, + + /* Test against branded browsers. */ + // { + // name: 'Microsoft Edge', + // use: { ...devices['Desktop Edge'], channel: 'msedge' }, + // }, + // { + // name: 'Google Chrome', + // use: { ...devices['Desktop Chrome'], channel: 'chrome' }, + // }, + ], + + /* Run your local dev server before starting the tests */ + // webServer: { + // command: 'npm run start', + // url: 'http://127.0.0.1:3000', + // reuseExistingServer: !process.env.CI, + // }, +}); +` + ); + createFile( + 'apps/demo-e2e/project.json', + JSON.stringify( + { + name: 'demo-e2e', + root: 'apps/demo-e2e', + sourceRoot: 'apps/demo-e2e/src', + targets: { + e2e: { + executor: '@nx/playwright:playwright', + options: {}, + }, + }, + }, + null, + 2 + ) + ); +} diff --git a/e2e/playwright/tsconfig.json b/e2e/playwright/tsconfig.json new file mode 100644 index 0000000000000..6d5abf8483200 --- /dev/null +++ b/e2e/playwright/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "types": ["node", "jest"] + }, + "include": [], + "files": [], + "references": [ + { + "path": "./tsconfig.spec.json" + } + ] +} diff --git a/e2e/playwright/tsconfig.spec.json b/e2e/playwright/tsconfig.spec.json new file mode 100644 index 0000000000000..1a24bfb0a1353 --- /dev/null +++ b/e2e/playwright/tsconfig.spec.json @@ -0,0 +1,20 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"] + }, + "include": [ + "**/*.test.ts", + "**/*.spec.ts", + "**/*.spec.tsx", + "**/*.test.tsx", + "**/*.spec.js", + "**/*.test.js", + "**/*.spec.jsx", + "**/*.test.jsx", + "**/*.d.ts", + "jest.config.ts" + ] +} diff --git a/e2e/utils/create-project-utils.ts b/e2e/utils/create-project-utils.ts index e38f554fa4696..e5df3310a4264 100644 --- a/e2e/utils/create-project-utils.ts +++ b/e2e/utils/create-project-utils.ts @@ -72,6 +72,7 @@ export function newProject({ `@nx/next`, `@nx/node`, `@nx/plugin`, + `@nx/playwright`, `@nx/rollup`, `@nx/react`, `@nx/storybook`, diff --git a/e2e/utils/get-env-info.ts b/e2e/utils/get-env-info.ts index c607ff0eea101..0f52216689ea6 100644 --- a/e2e/utils/get-env-info.ts +++ b/e2e/utils/get-env-info.ts @@ -122,6 +122,10 @@ export function getStrippedEnvironmentVariables() { return false; } + if (key === 'JEST_WORKER_ID') { + return false; + } + return true; }) ); diff --git a/jest.config.ts b/jest.config.ts index 0830aab5bfcd2..d0dbd1b889d5f 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -1,4 +1,4 @@ -const { getJestProjects } = require('@nx/jest'); +import { getJestProjects } from '@nx/jest'; export default { projects: getJestProjects(), diff --git a/packages/nx/package.json b/packages/nx/package.json index 33ade2fbc4acf..a59782401b840 100644 --- a/packages/nx/package.json +++ b/packages/nx/package.json @@ -124,6 +124,7 @@ "@nrwl/next", "@nx/node", "@nrwl/node", + "@nx/playwright", "@nx/plugin", "@nrwl/nx-plugin", "@nx/react", diff --git a/packages/playwright/.eslintrc.json b/packages/playwright/.eslintrc.json new file mode 100644 index 0000000000000..7abd30b8828cf --- /dev/null +++ b/packages/playwright/.eslintrc.json @@ -0,0 +1,25 @@ +{ + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], + "rules": {} + }, + { + "files": ["*.ts", "*.tsx"], + "rules": {} + }, + { + "files": ["*.js", "*.jsx"], + "rules": {} + }, + { + "files": ["./package.json", "./executors.json"], + "parser": "jsonc-eslint-parser", + "rules": { + "@nx/nx-plugin-checks": "error" + } + } + ] +} diff --git a/packages/playwright/README.md b/packages/playwright/README.md new file mode 100644 index 0000000000000..37eb64ddbdbef --- /dev/null +++ b/packages/playwright/README.md @@ -0,0 +1,11 @@ +

Nx - Smart, Fast and Extensible Build System

+ +{{links}} + +
+ +# Nx: Smart, Fast and Extensible Build System + +Nx is a next generation build system with first class monorepo support and powerful integrations. + +{{content}} diff --git a/packages/playwright/executors.json b/packages/playwright/executors.json new file mode 100644 index 0000000000000..5cf4695be5392 --- /dev/null +++ b/packages/playwright/executors.json @@ -0,0 +1,16 @@ +{ + "builders": { + "playwright": { + "implementation": "./src/executors/playwright/compat", + "schema": "./src/executors/playwright/schema.json", + "description": "Run Playwright tests." + } + }, + "executors": { + "playwright": { + "implementation": "./src/executors/playwright/playwright", + "schema": "./src/executors/playwright/schema.json", + "description": "Run Playwright tests." + } + } +} diff --git a/packages/playwright/jest.config.ts b/packages/playwright/jest.config.ts new file mode 100644 index 0000000000000..c25a242028be8 --- /dev/null +++ b/packages/playwright/jest.config.ts @@ -0,0 +1,10 @@ +/* eslint-disable */ +export default { + displayName: 'playwright', + preset: '../../jest.preset.js', + transform: { + '^.+\\.[tj]s$': ['ts-jest', { tsconfig: '/tsconfig.spec.json' }], + }, + moduleFileExtensions: ['ts', 'js', 'html'], + coverageDirectory: '../../coverage/packages/playwright', +}; diff --git a/packages/playwright/package.json b/packages/playwright/package.json new file mode 100644 index 0000000000000..188baca9d424e --- /dev/null +++ b/packages/playwright/package.json @@ -0,0 +1,43 @@ +{ + "name": "@nx/playwright", + "version": "0.0.1", + "type": "commonjs", + "homepage": "https://nx.dev", + "private": true, + "description": "The Nx Plugin for Playwright contains executors and generators allowing your workspace to use the powerful Playwright integration testing capabilities.", + "keywords": [ + "Monorepo", + "Angular", + "React", + "Web", + "Node", + "Nest", + "Jest", + "Playwright", + "CLI" + ], + "main": "./index", + "typings": "./index.d.ts", + "author": "Victor Savkin", + "license": "MIT", + "bugs": { + "url": "https://github.com/nrwl/nx/issues" + }, + "repository": { + "type": "git", + "url": "https://github.com/nrwl/nx.git", + "directory": "packages/playwright" + }, + "dependencies": { + "@nx/devkit": "file:../devkit" + }, + "peerDependencies": { + "@playwright/test": "^1.30.0" + }, + "peerDependenciesMeta": { + "@playwright/test": { + "optional": true + } + }, + "executors": "./executors.json" +} diff --git a/packages/playwright/project.json b/packages/playwright/project.json new file mode 100644 index 0000000000000..75e993f33c62d --- /dev/null +++ b/packages/playwright/project.json @@ -0,0 +1,50 @@ +{ + "name": "playwright", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "packages/playwright/src", + "projectType": "library", + "targets": { + "build": { + "executor": "nx:run-commands", + "outputs": ["{workspaceRoot}/build/packages/playwright"], + "options": { + "commands": ["node ./scripts/copy-readme.js playwright"] + } + }, + "build-base": { + "executor": "@nx/js:tsc", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "build/packages/playwright", + "main": "packages/playwright/src/index.ts", + "tsConfig": "packages/playwright/tsconfig.lib.json", + "assets": [ + "packages/playwright/*.md", + { + "input": "./packages/playwright/src", + "glob": "**/!(*.ts)", + "output": "./src" + }, + { + "input": "./packages/playwright/src", + "glob": "**/*.d.ts", + "output": "./src" + }, + { + "input": "./packages/playwright", + "glob": "generators.json", + "output": "." + }, + { + "input": "./packages/playwright", + "glob": "executors.json", + "output": "." + } + ] + } + }, + "lint": {}, + "test": {} + }, + "tags": [] +} diff --git a/packages/playwright/src/executors/playwright/compat.ts b/packages/playwright/src/executors/playwright/compat.ts new file mode 100644 index 0000000000000..ca72a5cebe7c0 --- /dev/null +++ b/packages/playwright/src/executors/playwright/compat.ts @@ -0,0 +1,4 @@ +import { convertNxExecutor } from '@nx/devkit'; +import { playwrightExecutor } from './playwright'; + +export default convertNxExecutor(playwrightExecutor); diff --git a/packages/playwright/src/executors/playwright/playwright.ts b/packages/playwright/src/executors/playwright/playwright.ts new file mode 100644 index 0000000000000..b7ea1d5e20e97 --- /dev/null +++ b/packages/playwright/src/executors/playwright/playwright.ts @@ -0,0 +1,113 @@ +import { fork } from 'child_process'; +import { ExecutorContext, names } from '@nx/devkit'; +import { join } from 'path'; + +export interface PlaywrightExecutorSchema { + /* + * if 'projects' is configured then that name needs to be provided instead of + * all, chromium, firefox, webkit + **/ + browser?: 'all' | 'chromium' | 'firefox' | 'webkit' | string; + config?: string; + debug?: boolean; + forbidOnly?: boolean; + fullyParallel?: boolean; + grep?: string; + globalTimeout?: number; + grepInvert?: string; + headed?: boolean; + ignoreSnapshots?: boolean; + workers?: string; + list?: boolean; + maxFailures?: number | boolean; + noDeps?: boolean; + output?: string; + passWithNoTests?: boolean; + project?: string[]; + quiet?: boolean; + repeatEach?: number; + reporter?: + | 'list' + | 'line' + | 'dot' + | 'json' + | 'junit' + | 'null' + | 'github' + | 'html' + | 'blob'; + retries?: number; + shard?: string; + timeout?: number; + trace?: + | 'on' + | 'off' + | 'on-first-retry' + | 'on-all-retries' + | 'retain-on-failure'; + updateSnapshots?: boolean; + ui?: boolean; + uiHost?: string; + uiPort?: string; +} + +export async function playwrightExecutor( + options: PlaywrightExecutorSchema, + context: ExecutorContext +) { + const projectRoot = + context.projectGraph?.nodes?.[context?.projectName]?.data?.root; + + if (!projectRoot) { + throw new Error( + `Unable to find the Project Root for ${context.projectName}. Is it set in the project.json?` + ); + } + const args = createArgs(options); + const p = runPlaywright(args, join(context.root, projectRoot)); + + return new Promise<{ success: boolean }>((resolve) => { + p.on('close', (code) => { + resolve({ success: code === 0 }); + }); + }); +} + +function createArgs(opts: PlaywrightExecutorSchema): string[] { + const args: string[] = []; + + for (const key in opts) { + const value = opts[key]; + // NOTE: playwright doesn't accept pascalCase args, only kebab-case + const arg = names(key).fileName; + + if (Array.isArray(value)) { + args.push(`--${arg}=${value.map((v) => v.trim()).join(',')}`); + } else if (typeof value === 'boolean') { + // NOTE: playwright don't accept --arg=false, instead just don't pass the arg. + if (value) { + args.push(`--${arg}`); + } + } else { + args.push(`--${arg}=${value}`); + } + } + + return args; +} + +function runPlaywright(args: string[], cwd: string) { + try { + const cli = require.resolve('@playwright/test/cli'); + + return fork(cli, ['test', ...args], { + stdio: 'inherit', + cwd, + }); + } catch (e) { + console.error(e); + throw new Error('Unable to run playwright. Is @playwright/test installed?'); + } +} + +export default playwrightExecutor; diff --git a/packages/playwright/src/executors/playwright/schema.json b/packages/playwright/src/executors/playwright/schema.json new file mode 100644 index 0000000000000..e73ab3f1fc99a --- /dev/null +++ b/packages/playwright/src/executors/playwright/schema.json @@ -0,0 +1,155 @@ +{ + "$schema": "http://json-schema.org/schema", + "version": 2, + "title": "Playwright executor", + "description": "Run Playwright tests.", + "type": "object", + "properties": { + "browser": { + "type": "string", + "description": "Browser to use for tests, one of 'all', 'chromium', 'firefox' or 'webkit'. If a playwright config is provided/discovered then the browserName value is expected from the configured 'projects'", + "x-priority": "important" + }, + "config": { + "type": "string", + "description": "Configuration file, or a test directory with optional", + "x-completion-type": "file", + "x-completion-glob": "playwright?(*)@(.js|.cjs|.mjs|.ts|.cts|.mtx)", + "x-priority": "important" + }, + "debug": { + "type": "boolean", + "description": "Run tests with Playwright Inspector. Shortcut for 'PWDEBUG=1' environment variable and '--timeout=0',--max-failures=1 --headed --workers=1' options" + }, + "forbidOnly": { + "type": "boolean", + "description": "Fail if test.only is called" + }, + "fullyParallel": { + "type": "boolean", + "description": "Run all tests in parallel" + }, + "grep": { + "alias": "g", + "type": "string", + "description": "Only run tests matching this regular expression" + }, + "globalTimeout": { + "type": "number", + "description": "Maximum time this test suite can run in milliseconds" + }, + "grepInvert": { + "alias": "gv", + "type": "string", + "description": "Only run tests that do not match this regular expression" + }, + "headed": { + "type": "boolean", + "description": "Run tests in headed browsers", + "x-priority": "important" + }, + "ignoreSnapshots": { + "type": "boolean", + "description": "Ignore screenshot and snapshot expectations" + }, + "workers": { + "alias": "j", + "type": "string", + "description": "Number of concurrent workers or percentage of logical CPU cores, use 1 to run in a single worker" + }, + "list": { + "type": "boolean", + "description": "Collect all the tests and report them, but do not run" + }, + "maxFailures": { + "alias": "x", + "oneOf": [{ "type": "number" }, { "type": "boolean" }], + "description": "Stop after the first N failures" + }, + "noDeps": { + "type": "boolean", + "description": "Do not run project dependencies" + }, + "output": { + "type": "string", + "description": "Folder for output artifacts" + }, + "passWithNoTests": { + "type": "boolean", + "description": "Makes test run succeed even if no tests were found", + "default": true + }, + "project": { + "description": "Only run tests from the specified list of projects", + "type": "array", + "items": { + "type": "string" + } + }, + "quiet": { + "alias": "q", + "type": "boolean", + "description": "Suppress stdio" + }, + "repeatEach": { + "type": "number", + "description": "Run each test N times" + }, + "reporter": { + "type": "string", + "enum": [ + "list", + "line", + "dot", + "json", + "junit", + "null", + "github", + "html", + "blob" + ], + "description": "Reporter to use, comma-separated, can be 'list', 'line', 'dot', 'json', 'junit', 'null', 'github', 'html', 'blob'. To configure reporter options, use the playwright configuration." + }, + "retries": { + "type": "number", + "description": "Maximum retry count for flaky tests, zero for no retries" + }, + "shard": { + "type": "string", + "description": "Shard tests and execute only the selected shard, specify in the form 'current/all', 1-based, for example '3/5'" + }, + "timeout": { + "type": "number", + "description": "Specify test timeout threshold in milliseconds, zero for unlimited" + }, + "trace": { + "type": "string", + "enum": [ + "on", + "off", + "on-first-retry", + "on-all-retries", + "retain-on-failure" + ], + "description": "Force tracing mode, can be 'on', 'off', 'on-first-retry', 'on-all-retries', 'retain-on-failure'" + }, + "updateSnapshots": { + "alias": "u", + "type": "boolean", + "description": "Update snapshots with actual results. Snapshots will be created if missing." + }, + "ui": { + "type": "boolean", + "description": "Run tests in interactive UI mode" + }, + "uiHost": { + "type": "string", + "description": "Host to serve UI on; specifying this option opens UI in a browser tab" + }, + "uiPort": { + "type": "string", + "description": "Port to serve UI on, 0 for any free port; specifying this option opens UI in a browser tab" + } + }, + "required": [] +} diff --git a/packages/playwright/src/index.ts b/packages/playwright/src/index.ts new file mode 100644 index 0000000000000..8b96dbdf4ae12 --- /dev/null +++ b/packages/playwright/src/index.ts @@ -0,0 +1,4 @@ +export { + playwrightExecutor, + PlaywrightExecutorSchema, +} from './executors/playwright/playwright'; diff --git a/packages/playwright/tsconfig.json b/packages/playwright/tsconfig.json new file mode 100644 index 0000000000000..19b9eece4df14 --- /dev/null +++ b/packages/playwright/tsconfig.json @@ -0,0 +1,16 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "module": "commonjs" + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ] +} diff --git a/packages/playwright/tsconfig.lib.json b/packages/playwright/tsconfig.lib.json new file mode 100644 index 0000000000000..33eca2c2cdf8c --- /dev/null +++ b/packages/playwright/tsconfig.lib.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "declaration": true, + "types": ["node"] + }, + "include": ["src/**/*.ts"], + "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"] +} diff --git a/packages/playwright/tsconfig.spec.json b/packages/playwright/tsconfig.spec.json new file mode 100644 index 0000000000000..9b2a121d114b6 --- /dev/null +++ b/packages/playwright/tsconfig.spec.json @@ -0,0 +1,14 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"] + }, + "include": [ + "jest.config.ts", + "src/**/*.test.ts", + "src/**/*.spec.ts", + "src/**/*.d.ts" + ] +} diff --git a/tsconfig.base.json b/tsconfig.base.json index 56141482a5b30..06ae37ac3baa9 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -83,6 +83,7 @@ "@nx/nx-dev/ui-references": ["nx-dev/ui-references/src/index.ts"], "@nx/nx-dev/ui-sponsor-card": ["nx-dev/ui-sponsor-card/src/index.ts"], "@nx/nx-dev/ui-theme": ["nx-dev/ui-theme/src/index.ts"], + "@nx/playwright": ["packages/playwright/src/index.ts"], "@nx/plugin": ["packages/plugin"], "@nx/plugin/*": ["packages/plugin/*"], "@nx/react": ["packages/react"], From cf9f5cbe6a7ce3b916ec6505dc8488f669cbc52b Mon Sep 17 00:00:00 2001 From: FrozenPandaz Date: Tue, 11 Jul 2023 16:55:10 -0400 Subject: [PATCH 055/262] chore(misc): publish 16.6.0-beta.1 --- lerna.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lerna.json b/lerna.json index 5f0c55164af00..c96893f808c41 100644 --- a/lerna.json +++ b/lerna.json @@ -1,6 +1,6 @@ { "packages": ["build/packages/*", "build/packages/nx/native-packages/*"], - "version": "16.6.0-beta.0", + "version": "16.6.0-beta.1", "granularPathspec": false, "command": { "publish": { From 7bd4d61b8c016a0fba81e9f84cd01d11c7d2ea0f Mon Sep 17 00:00:00 2001 From: Nicholas Cunningham Date: Wed, 12 Jul 2023 04:11:14 -0600 Subject: [PATCH 056/262] docs(angular): Update example app URL (#18056) --- docs/README.md | 2 +- docs/shared/angular-standalone-tutorial/1-code-generation.md | 2 +- docs/shared/angular-standalone-tutorial/angular-standalone.md | 4 ++-- docs/shared/react-standalone-tutorial/1-code-generation.md | 2 +- docs/shared/react-standalone-tutorial/react-standalone.md | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/README.md b/docs/README.md index eb07a366c0a85..c4685a3a6691a 100644 --- a/docs/README.md +++ b/docs/README.md @@ -111,7 +111,7 @@ We can display a special button inviting the reader to go to a GitHub repository You can add an "open in stackblitz" button as follows: ```markdown -{% stackblitz-button url="github.com/nrwl/nx-recipes/tree/main/standalone-angular-app?file=README.md" /%} +{% stackblitz-button url="github.com/nrwl/nx-recipes/tree/main/angular-standalone?file=README.md" /%} ``` #### Install Nx Console diff --git a/docs/shared/angular-standalone-tutorial/1-code-generation.md b/docs/shared/angular-standalone-tutorial/1-code-generation.md index 1d9bc4ff0a1f8..7330fa224611d 100644 --- a/docs/shared/angular-standalone-tutorial/1-code-generation.md +++ b/docs/shared/angular-standalone-tutorial/1-code-generation.md @@ -12,7 +12,7 @@ src="https://www.youtube.com/embed/LYPVrWQNnEc" title="Tutorial: Standalone Angular Application" width="100%" /%} -{% github-repository url="https://github.com/nrwl/nx-recipes/tree/main/standalone-angular-app" /%} +{% github-repository url="https://github.com/nrwl/nx-recipes/tree/main/angular-standalone" /%} # Angular Standalone Tutorial - Part 1: Code Generation diff --git a/docs/shared/angular-standalone-tutorial/angular-standalone.md b/docs/shared/angular-standalone-tutorial/angular-standalone.md index a03f65a5faed8..84fd06ac9f9fe 100644 --- a/docs/shared/angular-standalone-tutorial/angular-standalone.md +++ b/docs/shared/angular-standalone-tutorial/angular-standalone.md @@ -18,9 +18,9 @@ Note, this tutorial sets up a repo with a single application at the root level t Here's the source code of the final result for this tutorial. -{% github-repository url="https://github.com/nrwl/nx-recipes/tree/main/standalone-angular-app" /%} +{% github-repository url="https://github.com/nrwl/nx-recipes/tree/main/angular-standalone" /%} -{% stackblitz-button url="github.com/nrwl/nx-recipes/tree/main/standalone-angular-app?file=README.md" /%} +{% stackblitz-button url="github.com/nrwl/nx-recipes/tree/main/angular-standalone?file=README.md" /%} Also, if you prefer learning with a video, join Juri and walk through the tutorial, step by step together. diff --git a/docs/shared/react-standalone-tutorial/1-code-generation.md b/docs/shared/react-standalone-tutorial/1-code-generation.md index 1aff10e3ab8a4..949e8126a95b6 100644 --- a/docs/shared/react-standalone-tutorial/1-code-generation.md +++ b/docs/shared/react-standalone-tutorial/1-code-generation.md @@ -13,7 +13,7 @@ src="https://www.youtube.com/embed/dqCZteGFP4k" title="Tutorial: React Standalone Application" width="100%" /%} -{% github-repository url="https://github.com/nrwl/nx-recipes/tree/main/standalone-react-app" /%} +{% github-repository url="https://github.com/nrwl/nx-recipes/tree/main/react-standalone" /%} # React Standalone Tutorial - Part 1: Code Generation diff --git a/docs/shared/react-standalone-tutorial/react-standalone.md b/docs/shared/react-standalone-tutorial/react-standalone.md index 12c39caa4d221..33bd330c34c58 100644 --- a/docs/shared/react-standalone-tutorial/react-standalone.md +++ b/docs/shared/react-standalone-tutorial/react-standalone.md @@ -23,9 +23,9 @@ Note, this tutorial sets up a repo with a single application at the root level t Here's the source code of the final result for this tutorial. -{% github-repository url="https://github.com/nrwl/nx-recipes/tree/main/standalone-react-app" /%} +{% github-repository url="https://github.com/nrwl/nx-recipes/tree/main/react-standalone" /%} -{% stackblitz-button url="github.com/nrwl/nx-recipes/tree/main/standalone-react-app?file=README.md" /%} +{% stackblitz-button url="github.com/nrwl/nx-recipes/tree/main/react-standalone?file=README.md" /%} ## Creating a new React App From c364207f3e3300a88857e49e5a24f38ac09513fe Mon Sep 17 00:00:00 2001 From: "C. T. Lin" Date: Wed, 12 Jul 2023 18:57:17 +0800 Subject: [PATCH 057/262] fix(core): use concat in buildAllWorkspaceFiles to avoid Maximum call stack size exceeded (#18065) --- packages/nx/src/project-graph/utils/retrieve-workspace-files.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nx/src/project-graph/utils/retrieve-workspace-files.ts b/packages/nx/src/project-graph/utils/retrieve-workspace-files.ts index 3e8a0d9175741..470259195a79b 100644 --- a/packages/nx/src/project-graph/utils/retrieve-workspace-files.ts +++ b/packages/nx/src/project-graph/utils/retrieve-workspace-files.ts @@ -109,7 +109,7 @@ function buildAllWorkspaceFiles( performance.mark('get-all-workspace-files:start'); let fileData = Object.values(projectFileMap).flat(); - fileData.push(...globalFiles); + fileData = fileData.concat(globalFiles); performance.mark('get-all-workspace-files:end'); performance.measure( 'get-all-workspace-files', From 58e1f233cfdc7ae48029a58ad65ef33cbddc3f22 Mon Sep 17 00:00:00 2001 From: Katerina Skroumpelou Date: Wed, 12 Jul 2023 18:02:12 +0300 Subject: [PATCH 058/262] feat(storybook): interaction testing init generator (#18051) --- .../generators/storybook-configuration.json | 25 +-- .../generators/storybook-configuration.json | 2 +- .../generators/storybook-configuration.json | 25 +-- .../storybook/generators/configuration.json | 17 +- e2e/storybook/src/storybook-nested.test.ts | 4 +- .../lib/generate-storybook-configuration.ts | 2 +- .../storybook-configuration/schema.d.ts | 2 +- .../storybook-configuration/schema.json | 25 +-- .../storybook-configuration/schema.json | 2 +- .../storybook-configuration/configuration.ts | 3 +- .../storybook-configuration/schema.d.ts | 2 +- .../storybook-configuration/schema.json | 25 +-- .../configuration-nested.spec.ts.snap | 8 +- .../__snapshots__/configuration.spec.ts.snap | 146 +++++++++++++++--- .../configuration-nested.spec.ts | 10 +- .../configuration/configuration.spec.ts | 18 ++- .../generators/configuration/configuration.ts | 17 +- .../configuration/lib/util-functions.ts | 10 +- .../.storybook/main.ts__tmpl__ | 2 +- .../project-files/.storybook/main.js__tmpl__ | 2 +- .../src/generators/configuration/schema.d.ts | 2 +- .../src/generators/configuration/schema.json | 17 +- .../migrate-defaults-5-to-6.ts | 1 + packages/storybook/src/utils/versions.ts | 4 +- 24 files changed, 256 insertions(+), 115 deletions(-) diff --git a/docs/generated/packages/angular/generators/storybook-configuration.json b/docs/generated/packages/angular/generators/storybook-configuration.json index 81f3b4f30f0f1..cda247f442ae7 100644 --- a/docs/generated/packages/angular/generators/storybook-configuration.json +++ b/docs/generated/packages/angular/generators/storybook-configuration.json @@ -18,12 +18,18 @@ "x-dropdown": "projects", "x-priority": "important" }, + "interactionTests": { + "type": "boolean", + "description": "Set up Storybook interaction tests.", + "x-prompt": "Do you want to set up Storybook interaction tests?", + "alias": ["configureTestRunner"], + "x-priority": "important", + "default": true + }, "configureCypress": { "type": "boolean", "description": "Specifies whether to configure Cypress or not.", - "x-prompt": "Configure a Cypress e2e app to run against the storybook instance?", - "default": true, - "x-priority": "important" + "x-deprecated": "Please use Storybook interaction tests instead." }, "generateStories": { "type": "boolean", @@ -35,9 +41,7 @@ "generateCypressSpecs": { "type": "boolean", "description": "Specifies whether to automatically generate test files in the generated Cypress e2e app.", - "x-prompt": "Automatically generate test files in the generated Cypress e2e app?", - "default": true, - "x-priority": "important" + "x-deprecated": "Please use Storybook interaction tests instead." }, "configureStaticServe": { "type": "boolean", @@ -48,7 +52,8 @@ }, "cypressDirectory": { "type": "string", - "description": "A directory where the Cypress project will be placed. Placed at the root by default." + "description": "A directory where the Cypress project will be placed. Placed at the root by default.", + "x-deprecated": "Please use Storybook interaction tests instead." }, "linter": { "description": "The tool to use for running lint checks.", @@ -59,7 +64,7 @@ "tsConfiguration": { "type": "boolean", "description": "Configure your project with TypeScript. Generate main.ts and preview.ts files, instead of main.js and preview.js.", - "default": false, + "default": true, "x-priority": "important" }, "skipFormat": { @@ -79,10 +84,6 @@ "**/**/src/**/*.other.*", "libs/my-lib/src/not-stories/**,**/**/src/**/*.other.*,apps/my-app/**/*.something.ts" ] - }, - "configureTestRunner": { - "type": "boolean", - "description": "Add a Storybook Test-Runner target." } }, "additionalProperties": false, diff --git a/docs/generated/packages/react-native/generators/storybook-configuration.json b/docs/generated/packages/react-native/generators/storybook-configuration.json index 8accbc33edd95..9293ae7b46e3e 100644 --- a/docs/generated/packages/react-native/generators/storybook-configuration.json +++ b/docs/generated/packages/react-native/generators/storybook-configuration.json @@ -32,7 +32,7 @@ "tsConfiguration": { "type": "boolean", "description": "Configure your project with TypeScript. Generate main.ts and preview.ts files, instead of main.js and preview.js.", - "default": false + "default": true }, "linter": { "description": "The tool to use for running lint checks.", diff --git a/docs/generated/packages/react/generators/storybook-configuration.json b/docs/generated/packages/react/generators/storybook-configuration.json index 02e15b30e1d18..decc8cfbd7ed7 100644 --- a/docs/generated/packages/react/generators/storybook-configuration.json +++ b/docs/generated/packages/react/generators/storybook-configuration.json @@ -18,12 +18,18 @@ "x-dropdown": "projects", "x-priority": "important" }, + "interactionTests": { + "type": "boolean", + "description": "Set up Storybook interaction tests.", + "x-prompt": "Do you want to set up Storybook interaction tests?", + "x-priority": "important", + "alias": ["configureTestRunner"], + "default": true + }, "configureCypress": { "type": "boolean", "description": "Run the cypress-configure generator.", - "x-prompt": "Configure a cypress e2e app to run against the storybook instance?", - "default": true, - "x-priority": "important" + "x-deprecated": "Please use Storybook interaction tests instead." }, "generateStories": { "type": "boolean", @@ -35,9 +41,7 @@ "generateCypressSpecs": { "type": "boolean", "description": "Automatically generate test files in the Cypress E2E app generated by the `cypress-configure` generator.", - "x-prompt": "Automatically generate test files in the Cypress E2E app generated by the cypress-configure generator?", - "default": true, - "x-priority": "important" + "x-deprecated": "Please use Storybook interaction tests instead." }, "configureStaticServe": { "type": "boolean", @@ -48,7 +52,8 @@ }, "cypressDirectory": { "type": "string", - "description": "A directory where the Cypress project will be placed. Placed at the root by default." + "description": "A directory where the Cypress project will be placed. Placed at the root by default.", + "x-deprecated": "Please use Storybook interaction tests instead." }, "js": { "type": "boolean", @@ -58,7 +63,7 @@ "tsConfiguration": { "type": "boolean", "description": "Configure your project with TypeScript. Generate main.ts and preview.ts files, instead of main.js and preview.js.", - "default": false + "default": true }, "linter": { "description": "The tool to use for running lint checks.", @@ -77,10 +82,6 @@ "**/**/src/**/*.other.*", "libs/my-lib/src/not-stories/**,**/**/src/**/*.other.*,apps/my-app/**/*.something.ts" ] - }, - "configureTestRunner": { - "type": "boolean", - "description": "Add a Storybook Test-Runner target." } }, "required": ["name"], diff --git a/docs/generated/packages/storybook/generators/configuration.json b/docs/generated/packages/storybook/generators/configuration.json index a3223720d7820..7c3c8b104361e 100644 --- a/docs/generated/packages/storybook/generators/configuration.json +++ b/docs/generated/packages/storybook/generators/configuration.json @@ -18,15 +18,22 @@ "x-dropdown": "projects", "x-priority": "important" }, + "interactionTests": { + "type": "boolean", + "description": "Set up Storybook interaction tests.", + "x-prompt": "Do you want to set up Storybook interaction tests?", + "alias": ["configureTestRunner"], + "default": true + }, "configureCypress": { "type": "boolean", "description": "Run the cypress-configure generator.", - "x-prompt": "Configure a cypress e2e app to run against the storybook instance?", - "x-priority": "important" + "x-deprecated": "Please use Storybook interaction tests instead." }, "cypressDirectory": { "type": "string", - "description": "A directory where the Cypress project will be placed. Added at root by default." + "description": "A directory where the Cypress project will be placed. Added at root by default.", + "x-deprecated": "Please use Storybook interaction tests instead." }, "linter": { "description": "The tool to use for running lint checks.", @@ -56,10 +63,6 @@ "description": "Add a static-storybook to serve the static storybook built files.", "default": false }, - "configureTestRunner": { - "type": "boolean", - "description": "Add a Storybook Test-Runner target." - }, "bundler": { "description": "The Storybook builder to use.", "type": "string", diff --git a/e2e/storybook/src/storybook-nested.test.ts b/e2e/storybook/src/storybook-nested.test.ts index dc581dffcaa9d..c4377052361bc 100644 --- a/e2e/storybook/src/storybook-nested.test.ts +++ b/e2e/storybook/src/storybook-nested.test.ts @@ -40,8 +40,8 @@ describe('Storybook generators and executors for standalone workspaces - using R describe('Storybook generated files', () => { it('should generate storybook files', () => { checkFilesExist( - '.storybook/main.js', - '.storybook/preview.js', + '.storybook/main.ts', + '.storybook/preview.ts', 'tsconfig.storybook.json' ); }); diff --git a/packages/angular/src/generators/storybook-configuration/lib/generate-storybook-configuration.ts b/packages/angular/src/generators/storybook-configuration/lib/generate-storybook-configuration.ts index 0f914169e29b1..65a040546d564 100644 --- a/packages/angular/src/generators/storybook-configuration/lib/generate-storybook-configuration.ts +++ b/packages/angular/src/generators/storybook-configuration/lib/generate-storybook-configuration.ts @@ -14,7 +14,7 @@ export async function generateStorybookConfiguration( linter: options.linter, cypressDirectory: options.cypressDirectory, tsConfiguration: options.tsConfiguration, - configureTestRunner: options.configureTestRunner, + interactionTests: options.interactionTests, configureStaticServe: options.configureStaticServe, skipFormat: true, }); diff --git a/packages/angular/src/generators/storybook-configuration/schema.d.ts b/packages/angular/src/generators/storybook-configuration/schema.d.ts index 01f6af061f76a..9c8867f4627a6 100644 --- a/packages/angular/src/generators/storybook-configuration/schema.d.ts +++ b/packages/angular/src/generators/storybook-configuration/schema.d.ts @@ -11,5 +11,5 @@ export interface StorybookConfigurationOptions { tsConfiguration?: boolean; skipFormat?: boolean; ignorePaths?: string[]; - configureTestRunner?: boolean; + interactionTests?: boolean; } diff --git a/packages/angular/src/generators/storybook-configuration/schema.json b/packages/angular/src/generators/storybook-configuration/schema.json index 419c4e3bd8e91..2d00d3817d3b7 100644 --- a/packages/angular/src/generators/storybook-configuration/schema.json +++ b/packages/angular/src/generators/storybook-configuration/schema.json @@ -18,12 +18,18 @@ "x-dropdown": "projects", "x-priority": "important" }, + "interactionTests": { + "type": "boolean", + "description": "Set up Storybook interaction tests.", + "x-prompt": "Do you want to set up Storybook interaction tests?", + "alias": ["configureTestRunner"], + "x-priority": "important", + "default": true + }, "configureCypress": { "type": "boolean", "description": "Specifies whether to configure Cypress or not.", - "x-prompt": "Configure a Cypress e2e app to run against the storybook instance?", - "default": true, - "x-priority": "important" + "x-deprecated": "Please use Storybook interaction tests instead." }, "generateStories": { "type": "boolean", @@ -35,9 +41,7 @@ "generateCypressSpecs": { "type": "boolean", "description": "Specifies whether to automatically generate test files in the generated Cypress e2e app.", - "x-prompt": "Automatically generate test files in the generated Cypress e2e app?", - "default": true, - "x-priority": "important" + "x-deprecated": "Please use Storybook interaction tests instead." }, "configureStaticServe": { "type": "boolean", @@ -48,7 +52,8 @@ }, "cypressDirectory": { "type": "string", - "description": "A directory where the Cypress project will be placed. Placed at the root by default." + "description": "A directory where the Cypress project will be placed. Placed at the root by default.", + "x-deprecated": "Please use Storybook interaction tests instead." }, "linter": { "description": "The tool to use for running lint checks.", @@ -59,7 +64,7 @@ "tsConfiguration": { "type": "boolean", "description": "Configure your project with TypeScript. Generate main.ts and preview.ts files, instead of main.js and preview.js.", - "default": false, + "default": true, "x-priority": "important" }, "skipFormat": { @@ -82,10 +87,6 @@ "**/**/src/**/*.other.*", "libs/my-lib/src/not-stories/**,**/**/src/**/*.other.*,apps/my-app/**/*.something.ts" ] - }, - "configureTestRunner": { - "type": "boolean", - "description": "Add a Storybook Test-Runner target." } }, "additionalProperties": false, diff --git a/packages/react-native/src/generators/storybook-configuration/schema.json b/packages/react-native/src/generators/storybook-configuration/schema.json index 3b5b1826b7528..4acf4b867de1c 100644 --- a/packages/react-native/src/generators/storybook-configuration/schema.json +++ b/packages/react-native/src/generators/storybook-configuration/schema.json @@ -32,7 +32,7 @@ "tsConfiguration": { "type": "boolean", "description": "Configure your project with TypeScript. Generate main.ts and preview.ts files, instead of main.js and preview.js.", - "default": false + "default": true }, "linter": { "description": "The tool to use for running lint checks.", diff --git a/packages/react/src/generators/storybook-configuration/configuration.ts b/packages/react/src/generators/storybook-configuration/configuration.ts index 9cc7223a36ff2..16d9f81d33aa9 100644 --- a/packages/react/src/generators/storybook-configuration/configuration.ts +++ b/packages/react/src/generators/storybook-configuration/configuration.ts @@ -10,6 +10,7 @@ import { import { nxVersion } from '../../utils/versions'; async function generateStories(host: Tree, schema: StorybookConfigureSchema) { + // TODO(katerina): Remove cypress stuff for Nx 17? ensurePackage('@nx/cypress', nxVersion); const { getE2eProjectName } = await import( '@nx/cypress/src/utils/project-name' @@ -57,7 +58,7 @@ export async function storybookConfigurationGenerator( linter: schema.linter, cypressDirectory: schema.cypressDirectory, tsConfiguration: schema.tsConfiguration, - configureTestRunner: schema.configureTestRunner, + interactionTests: schema.interactionTests, configureStaticServe: schema.configureStaticServe, uiFramework: bundler === 'vite' diff --git a/packages/react/src/generators/storybook-configuration/schema.d.ts b/packages/react/src/generators/storybook-configuration/schema.d.ts index 6d96bbc903da6..0094e3b656097 100644 --- a/packages/react/src/generators/storybook-configuration/schema.d.ts +++ b/packages/react/src/generators/storybook-configuration/schema.d.ts @@ -10,6 +10,6 @@ export interface StorybookConfigureSchema { linter?: Linter; cypressDirectory?: string; ignorePaths?: string[]; - configureTestRunner?: boolean; + interactionTests?: boolean; configureStaticServe?: boolean; } diff --git a/packages/react/src/generators/storybook-configuration/schema.json b/packages/react/src/generators/storybook-configuration/schema.json index 76bc6452b1441..599e0eb854e47 100644 --- a/packages/react/src/generators/storybook-configuration/schema.json +++ b/packages/react/src/generators/storybook-configuration/schema.json @@ -18,12 +18,18 @@ "x-dropdown": "projects", "x-priority": "important" }, + "interactionTests": { + "type": "boolean", + "description": "Set up Storybook interaction tests.", + "x-prompt": "Do you want to set up Storybook interaction tests?", + "x-priority": "important", + "alias": ["configureTestRunner"], + "default": true + }, "configureCypress": { "type": "boolean", "description": "Run the cypress-configure generator.", - "x-prompt": "Configure a cypress e2e app to run against the storybook instance?", - "default": true, - "x-priority": "important" + "x-deprecated": "Please use Storybook interaction tests instead." }, "generateStories": { "type": "boolean", @@ -35,9 +41,7 @@ "generateCypressSpecs": { "type": "boolean", "description": "Automatically generate test files in the Cypress E2E app generated by the `cypress-configure` generator.", - "x-prompt": "Automatically generate test files in the Cypress E2E app generated by the cypress-configure generator?", - "default": true, - "x-priority": "important" + "x-deprecated": "Please use Storybook interaction tests instead." }, "configureStaticServe": { "type": "boolean", @@ -48,7 +52,8 @@ }, "cypressDirectory": { "type": "string", - "description": "A directory where the Cypress project will be placed. Placed at the root by default." + "description": "A directory where the Cypress project will be placed. Placed at the root by default.", + "x-deprecated": "Please use Storybook interaction tests instead." }, "js": { "type": "boolean", @@ -58,7 +63,7 @@ "tsConfiguration": { "type": "boolean", "description": "Configure your project with TypeScript. Generate main.ts and preview.ts files, instead of main.js and preview.js.", - "default": false + "default": true }, "linter": { "description": "The tool to use for running lint checks.", @@ -80,10 +85,6 @@ "**/**/src/**/*.other.*", "libs/my-lib/src/not-stories/**,**/**/src/**/*.other.*,apps/my-app/**/*.something.ts" ] - }, - "configureTestRunner": { - "type": "boolean", - "description": "Add a Storybook Test-Runner target." } }, "required": ["name"], diff --git a/packages/storybook/src/generators/configuration/__snapshots__/configuration-nested.spec.ts.snap b/packages/storybook/src/generators/configuration/__snapshots__/configuration-nested.spec.ts.snap index 38665f14b0f16..82909b11da730 100644 --- a/packages/storybook/src/generators/configuration/__snapshots__/configuration-nested.spec.ts.snap +++ b/packages/storybook/src/generators/configuration/__snapshots__/configuration-nested.spec.ts.snap @@ -5,7 +5,7 @@ exports[`@nx/storybook:configuration for workspaces with Root project basic func const config: StorybookConfig = { stories: ['../src/app/**/*.stories.@(js|jsx|ts|tsx|mdx)'], - addons: ['@storybook/addon-essentials'], + addons: ['@storybook/addon-essentials', '@storybook/addon-interactions'], framework: { name: '@storybook/react-vite', options: { @@ -66,7 +66,11 @@ exports[`@nx/storybook:configuration for workspaces with Root project basic func const config: StorybookConfig = { stories: ['../src/app/**/*.stories.@(js|jsx|ts|tsx|mdx)'], - addons: ['@storybook/addon-essentials', '@nx/react/plugins/storybook'], + addons: [ + '@storybook/addon-essentials', + '@storybook/addon-interactions', + '@nx/react/plugins/storybook', + ], framework: { name: '@storybook/react-webpack5', options: {}, diff --git a/packages/storybook/src/generators/configuration/__snapshots__/configuration.spec.ts.snap b/packages/storybook/src/generators/configuration/__snapshots__/configuration.spec.ts.snap index 9a518eefde082..5e62759551bf0 100644 --- a/packages/storybook/src/generators/configuration/__snapshots__/configuration.spec.ts.snap +++ b/packages/storybook/src/generators/configuration/__snapshots__/configuration.spec.ts.snap @@ -5,7 +5,7 @@ exports[`@nx/storybook:configuration for Storybook v7 basic functionalities shou const config: StorybookConfig = { stories: ['../**/*.stories.@(js|jsx|ts|tsx|mdx)'], - addons: ['@storybook/addon-essentials'], + addons: ['@storybook/addon-essentials', '@storybook/addon-interactions'], framework: { name: '@storybook/angular', options: {}, @@ -87,6 +87,12 @@ exports[`@nx/storybook:configuration for Storybook v7 basic functionalities shou "{workspaceRoot}/coverage/{projectRoot}", ], }, + "test-storybook": { + "executor": "nx:run-commands", + "options": { + "command": "test-storybook -c libs/test-ui-lib/.storybook --url=http://localhost:4400", + }, + }, }, } `; @@ -98,7 +104,7 @@ exports[`@nx/storybook:configuration for Storybook v7 basic functionalities shou const config: StorybookConfig = { stories: ['../**/*.stories.@(js|jsx|ts|tsx|mdx)'], - addons: ['@storybook/addon-essentials'], + addons: ['@storybook/addon-essentials', '@storybook/addon-interactions'], framework: { name: '@storybook/angular', options: {}, @@ -151,7 +157,7 @@ exports[`@nx/storybook:configuration for Storybook v7 basic functionalities shou exports[`@nx/storybook:configuration for Storybook v7 generate Storybook configuration for all types of projects should contain the correct configuration in "apps/main-vite/.storybook/" 1`] = ` "const config = { stories: ['../src/app/**/*.stories.@(js|jsx|ts|tsx|mdx)'], - addons: ['@storybook/addon-essentials'], + addons: ['@storybook/addon-essentials', '@storybook/addon-interactions'], framework: { name: '@storybook/react-vite', options: { @@ -177,7 +183,7 @@ exports[`@nx/storybook:configuration for Storybook v7 generate Storybook configu const config: StorybookConfig = { stories: ['../src/app/**/*.stories.@(js|jsx|ts|tsx|mdx)'], - addons: ['@storybook/addon-essentials'], + addons: ['@storybook/addon-essentials', '@storybook/addon-interactions'], framework: { name: '@storybook/react-vite', options: { @@ -199,9 +205,15 @@ export default config; exports[`@nx/storybook:configuration for Storybook v7 generate Storybook configuration for all types of projects should contain the correct configuration in "apps/main-vite-ts/.storybook/" 2`] = `null`; exports[`@nx/storybook:configuration for Storybook v7 generate Storybook configuration for all types of projects should contain the correct configuration in "apps/main-webpack/.storybook/" 1`] = ` -"const config = { +"import type { StorybookConfig } from '@storybook/react-webpack5'; + +const config: StorybookConfig = { stories: ['../src/app/**/*.stories.@(js|jsx|ts|tsx|mdx)'], - addons: ['@storybook/addon-essentials', '@nx/react/plugins/storybook'], + addons: [ + '@storybook/addon-essentials', + '@storybook/addon-interactions', + '@nx/react/plugins/storybook', + ], framework: { name: '@storybook/react-webpack5', options: {}, @@ -219,9 +231,11 @@ export default config; exports[`@nx/storybook:configuration for Storybook v7 generate Storybook configuration for all types of projects should contain the correct configuration in "apps/main-webpack/.storybook/" 2`] = `null`; exports[`@nx/storybook:configuration for Storybook v7 generate Storybook configuration for all types of projects should contain the correct configuration in "apps/nextapp/.storybook/" 1`] = ` -"const config = { +"import type { StorybookConfig } from '@storybook/nextjs'; + +const config: StorybookConfig = { stories: ['../components/**/*.stories.@(js|jsx|ts|tsx|mdx)'], - addons: ['@storybook/addon-essentials'], + addons: ['@storybook/addon-essentials', '@storybook/addon-interactions'], framework: { name: '@storybook/nextjs', options: {}, @@ -239,9 +253,15 @@ export default config; exports[`@nx/storybook:configuration for Storybook v7 generate Storybook configuration for all types of projects should contain the correct configuration in "apps/nextapp/.storybook/" 2`] = `null`; exports[`@nx/storybook:configuration for Storybook v7 generate Storybook configuration for all types of projects should contain the correct configuration in "apps/react-swc/.storybook/" 1`] = ` -"const config = { +"import type { StorybookConfig } from '@storybook/react-webpack5'; + +const config: StorybookConfig = { stories: ['../src/app/**/*.stories.@(js|jsx|ts|tsx|mdx)'], - addons: ['@storybook/addon-essentials', '@nx/react/plugins/storybook'], + addons: [ + '@storybook/addon-essentials', + '@storybook/addon-interactions', + '@nx/react/plugins/storybook', + ], framework: { name: '@storybook/react-webpack5', options: {}, @@ -261,7 +281,7 @@ exports[`@nx/storybook:configuration for Storybook v7 generate Storybook configu exports[`@nx/storybook:configuration for Storybook v7 generate Storybook configuration for all types of projects should contain the correct configuration in "apps/reapp/.storybook/" 1`] = ` "const config = { stories: ['../src/app/**/*.stories.@(js|jsx|ts|tsx|mdx)'], - addons: ['@storybook/addon-essentials'], + addons: ['@storybook/addon-essentials', '@storybook/addon-interactions'], framework: { name: '@storybook/react-vite', options: { @@ -283,9 +303,15 @@ export default config; exports[`@nx/storybook:configuration for Storybook v7 generate Storybook configuration for all types of projects should contain the correct configuration in "apps/reapp/.storybook/" 2`] = `null`; exports[`@nx/storybook:configuration for Storybook v7 generate Storybook configuration for all types of projects should contain the correct configuration in "apps/reappw/.storybook/" 1`] = ` -"const config = { +"import type { StorybookConfig } from '@storybook/react-webpack5'; + +const config: StorybookConfig = { stories: ['../src/app/**/*.stories.@(js|jsx|ts|tsx|mdx)'], - addons: ['@storybook/addon-essentials', '@nx/react/plugins/storybook'], + addons: [ + '@storybook/addon-essentials', + '@storybook/addon-interactions', + '@nx/react/plugins/storybook', + ], framework: { name: '@storybook/react-webpack5', options: {}, @@ -303,9 +329,11 @@ export default config; exports[`@nx/storybook:configuration for Storybook v7 generate Storybook configuration for all types of projects should contain the correct configuration in "apps/reappw/.storybook/" 2`] = `null`; exports[`@nx/storybook:configuration for Storybook v7 generate Storybook configuration for all types of projects should contain the correct configuration in "apps/wv1/.storybook/" 1`] = ` -"const config = { +"import type { StorybookConfig } from '@storybook/web-components-vite'; + +const config: StorybookConfig = { stories: ['../src/app/**/*.stories.@(js|jsx|ts|tsx|mdx)'], - addons: ['@storybook/addon-essentials'], + addons: ['@storybook/addon-essentials', '@storybook/addon-interactions'], framework: { name: '@storybook/web-components-vite', options: { @@ -327,9 +355,11 @@ export default config; exports[`@nx/storybook:configuration for Storybook v7 generate Storybook configuration for all types of projects should contain the correct configuration in "apps/wv1/.storybook/" 2`] = `null`; exports[`@nx/storybook:configuration for Storybook v7 generate Storybook configuration for all types of projects should contain the correct configuration in "apps/ww1/.storybook/" 1`] = ` -"const config = { +"import type { StorybookConfig } from '@storybook/web-components-webpack5'; + +const config: StorybookConfig = { stories: ['../src/app/**/*.stories.@(js|jsx|ts|tsx|mdx)'], - addons: ['@storybook/addon-essentials'], + addons: ['@storybook/addon-essentials', '@storybook/addon-interactions'], framework: { name: '@storybook/web-components-webpack5', options: {}, @@ -347,9 +377,15 @@ export default config; exports[`@nx/storybook:configuration for Storybook v7 generate Storybook configuration for all types of projects should contain the correct configuration in "apps/ww1/.storybook/" 2`] = `null`; exports[`@nx/storybook:configuration for Storybook v7 generate Storybook configuration for all types of projects should contain the correct configuration in "libs/react-rollup/.storybook/" 1`] = ` -"const config = { +"import type { StorybookConfig } from '@storybook/react-webpack5'; + +const config: StorybookConfig = { stories: ['../src/lib/**/*.stories.@(js|jsx|ts|tsx|mdx)'], - addons: ['@storybook/addon-essentials', '@nx/react/plugins/storybook'], + addons: [ + '@storybook/addon-essentials', + '@storybook/addon-interactions', + '@nx/react/plugins/storybook', + ], framework: { name: '@storybook/react-webpack5', options: {}, @@ -367,9 +403,11 @@ export default config; exports[`@nx/storybook:configuration for Storybook v7 generate Storybook configuration for all types of projects should contain the correct configuration in "libs/react-rollup/.storybook/" 2`] = `null`; exports[`@nx/storybook:configuration for Storybook v7 generate Storybook configuration for all types of projects should contain the correct configuration in "libs/react-vite/.storybook/" 1`] = ` -"const config = { +"import type { StorybookConfig } from '@storybook/react-vite'; + +const config: StorybookConfig = { stories: ['../src/lib/**/*.stories.@(js|jsx|ts|tsx|mdx)'], - addons: ['@storybook/addon-essentials'], + addons: ['@storybook/addon-essentials', '@storybook/addon-interactions'], framework: { name: '@storybook/react-vite', options: { @@ -484,6 +522,12 @@ Map { "coverage/apps/main-vite", ], }, + "test-storybook": { + "executor": "nx:run-commands", + "options": { + "command": "test-storybook -c apps/main-vite/.storybook --url=http://localhost:4400", + }, + }, }, }, "main-vite-e2e" => { @@ -615,6 +659,12 @@ Map { "coverage/apps/main-vite-ts", ], }, + "test-storybook": { + "executor": "nx:run-commands", + "options": { + "command": "test-storybook -c apps/main-vite-ts/.storybook --url=http://localhost:4400", + }, + }, }, }, "main-vite-ts-e2e" => { @@ -774,6 +824,12 @@ Map { "{workspaceRoot}/coverage/{projectRoot}", ], }, + "test-storybook": { + "executor": "nx:run-commands", + "options": { + "command": "test-storybook -c apps/main-webpack/.storybook --url=http://localhost:4400", + }, + }, }, }, "main-webpack-e2e" => { @@ -930,6 +986,12 @@ Map { "{workspaceRoot}/coverage/{projectRoot}", ], }, + "test-storybook": { + "executor": "nx:run-commands", + "options": { + "command": "test-storybook -c apps/nextapp/.storybook --url=http://localhost:4400", + }, + }, }, }, "nextapp-e2e" => { @@ -1330,6 +1392,12 @@ Map { "{workspaceRoot}/coverage/{projectRoot}", ], }, + "test-storybook": { + "executor": "nx:run-commands", + "options": { + "command": "test-storybook -c apps/react-swc/.storybook --url=http://localhost:4400", + }, + }, }, }, "react-swc-e2e" => { @@ -1498,6 +1566,12 @@ Map { "coverage/apps/reapp", ], }, + "test-storybook": { + "executor": "nx:run-commands", + "options": { + "command": "test-storybook -c apps/reapp/.storybook --url=http://localhost:4400", + }, + }, }, }, "reapp-e2e" => { @@ -1656,6 +1730,12 @@ Map { "{workspaceRoot}/coverage/{projectRoot}", ], }, + "test-storybook": { + "executor": "nx:run-commands", + "options": { + "command": "test-storybook -c apps/reappw/.storybook --url=http://localhost:4400", + }, + }, }, }, "reappw-e2e" => { @@ -1787,6 +1867,12 @@ Map { "{workspaceRoot}/coverage/{projectRoot}", ], }, + "test-storybook": { + "executor": "nx:run-commands", + "options": { + "command": "test-storybook -c apps/wv1/.storybook --url=http://localhost:4400", + }, + }, }, }, "wv1-e2e" => { @@ -1933,6 +2019,12 @@ Map { "{workspaceRoot}/coverage/{projectRoot}", ], }, + "test-storybook": { + "executor": "nx:run-commands", + "options": { + "command": "test-storybook -c apps/ww1/.storybook --url=http://localhost:4400", + }, + }, }, }, "ww1-e2e" => { @@ -2197,6 +2289,12 @@ Map { "{workspaceRoot}/coverage/{projectRoot}", ], }, + "test-storybook": { + "executor": "nx:run-commands", + "options": { + "command": "test-storybook -c libs/react-rollup/.storybook --url=http://localhost:4400", + }, + }, }, }, "react-rollup-2" => { @@ -2328,6 +2426,12 @@ Map { "coverage/libs/react-vite", ], }, + "test-storybook": { + "executor": "nx:run-commands", + "options": { + "command": "test-storybook -c libs/react-vite/.storybook --url=http://localhost:4400", + }, + }, }, }, "react-vite-2" => { diff --git a/packages/storybook/src/generators/configuration/configuration-nested.spec.ts b/packages/storybook/src/generators/configuration/configuration-nested.spec.ts index 8e3780c55bd1d..124d6560b67b5 100644 --- a/packages/storybook/src/generators/configuration/configuration-nested.spec.ts +++ b/packages/storybook/src/generators/configuration/configuration-nested.spec.ts @@ -19,13 +19,6 @@ jest.mock('nx/src/project-graph/project-graph', () => ({ })); describe('@nx/storybook:configuration for workspaces with Root project', () => { - beforeAll(() => { - process.env.NX_INTERACTIVE = 'true'; - }); - afterAll(() => { - // cleanup - delete process.env.NX_INTERACTIVE; - }); describe('basic functionalities', () => { let tree: Tree; beforeEach(async () => { @@ -93,6 +86,7 @@ describe('@nx/storybook:configuration for workspaces with Root project', () => { await configurationGenerator(tree, { name: 'web', uiFramework: '@storybook/react-webpack5', + tsConfiguration: false, }); expect(tree.exists('.storybook/main.js')).toBeTruthy(); @@ -106,7 +100,6 @@ describe('@nx/storybook:configuration for workspaces with Root project', () => { await configurationGenerator(tree, { name: 'reapp', uiFramework: '@storybook/react-webpack5', - tsConfiguration: true, }); expect(tree.exists('.storybook/main.ts')).toBeFalsy(); @@ -120,7 +113,6 @@ describe('@nx/storybook:configuration for workspaces with Root project', () => { await configurationGenerator(tree, { name: 'web', uiFramework: '@storybook/react-vite', - tsConfiguration: true, }); expect(tree.exists('.storybook/main.ts')).toBeTruthy(); diff --git a/packages/storybook/src/generators/configuration/configuration.spec.ts b/packages/storybook/src/generators/configuration/configuration.spec.ts index f9f20b6875553..96c34ec3b37ef 100644 --- a/packages/storybook/src/generators/configuration/configuration.spec.ts +++ b/packages/storybook/src/generators/configuration/configuration.spec.ts @@ -189,7 +189,7 @@ describe('@nx/storybook:configuration for Storybook v7', () => { it('should add test-storybook target', async () => { await configurationGenerator(tree, { name: 'test-ui-lib', - configureTestRunner: true, + interactionTests: true, uiFramework: '@storybook/react-webpack5', }); @@ -197,6 +197,22 @@ describe('@nx/storybook:configuration for Storybook v7', () => { readJson(tree, 'package.json').devDependencies['@storybook/test-runner'] ).toBeTruthy(); + expect( + readJson(tree, 'package.json').devDependencies[ + '@storybook/testing-library' + ] + ).toBeTruthy(); + + expect( + readJson(tree, 'package.json').devDependencies['@storybook/jest'] + ).toBeTruthy(); + + expect( + readJson(tree, 'package.json').devDependencies[ + '@storybook/addon-interactions' + ] + ).toBeTruthy(); + const project = readProjectConfiguration(tree, 'test-ui-lib'); expect(project.targets['test-storybook']).toEqual({ executor: 'nx:run-commands', diff --git a/packages/storybook/src/generators/configuration/configuration.ts b/packages/storybook/src/generators/configuration/configuration.ts index ee2b66361d6b9..0365434575086 100644 --- a/packages/storybook/src/generators/configuration/configuration.ts +++ b/packages/storybook/src/generators/configuration/configuration.ts @@ -36,6 +36,8 @@ import { } from '../../utils/utilities'; import { nxVersion, + storybookJestVersion, + storybookTestingLibraryVersion, storybookTestRunnerVersion, storybookVersion, tsNodeVersion, @@ -109,6 +111,7 @@ export async function configurationGenerator( root, projectType, projectIsRootProjectInStandaloneWorkspace(root), + schema.interactionTests, mainDir, !!nextBuildTarget, compiler === 'swc', @@ -133,13 +136,13 @@ export async function configurationGenerator( addStorybookToNamedInputs(tree); if (schema.uiFramework === '@storybook/angular') { - addAngularStorybookTask(tree, schema.name, schema.configureTestRunner); + addAngularStorybookTask(tree, schema.name, schema.interactionTests); } else { addStorybookTask( tree, schema.name, schema.uiFramework, - schema.configureTestRunner + schema.interactionTests ); } @@ -147,6 +150,7 @@ export async function configurationGenerator( addStaticTarget(tree, schema); } + // TODO(katerina): remove this feature in 17? if (schema.configureCypress) { const e2eProject = await getE2EProjectName(tree, schema.name); if (!e2eProject) { @@ -176,9 +180,13 @@ export async function configurationGenerator( devDeps['ts-node'] = tsNodeVersion; } - if (schema.configureTestRunner === true) { + if (schema.interactionTests) { devDeps['@storybook/test-runner'] = storybookTestRunnerVersion; + devDeps['@storybook/addon-interactions'] = storybookVersion; + devDeps['@storybook/testing-library'] = storybookTestingLibraryVersion; + devDeps['@storybook/jest'] = storybookJestVersion; } + if (schema.configureStaticServe) { devDeps['@nx/web'] = nxVersion; } @@ -196,9 +204,10 @@ function normalizeSchema( schema: StorybookConfigureSchema ): StorybookConfigureSchema { const defaults = { - configureCypress: true, + interactionTests: true, linter: Linter.EsLint, js: false, + tsConfiguration: true, }; return { ...defaults, diff --git a/packages/storybook/src/generators/configuration/lib/util-functions.ts b/packages/storybook/src/generators/configuration/lib/util-functions.ts index 5aa9d786bf7a8..550d5ae485fd1 100644 --- a/packages/storybook/src/generators/configuration/lib/util-functions.ts +++ b/packages/storybook/src/generators/configuration/lib/util-functions.ts @@ -35,7 +35,7 @@ export function addStorybookTask( tree: Tree, projectName: string, uiFramework: string, - configureTestRunner: boolean + interactionTests: boolean ) { if (uiFramework === '@storybook/react-native') { return; @@ -68,7 +68,7 @@ export function addStorybookTask( }, }; - if (configureTestRunner === true) { + if (interactionTests === true) { projectConfig.targets['test-storybook'] = { executor: 'nx:run-commands', options: { @@ -83,7 +83,7 @@ export function addStorybookTask( export function addAngularStorybookTask( tree: Tree, projectName: string, - configureTestRunner: boolean + interactionTests: boolean ) { const projectConfig = readProjectConfiguration(tree, projectName); const { ngBuildTarget } = findStorybookAndBuildTargetsAndCompiler( @@ -124,7 +124,7 @@ export function addAngularStorybookTask( }, }; - if (configureTestRunner === true) { + if (interactionTests === true) { projectConfig.targets['test-storybook'] = { executor: 'nx:run-commands', options: { @@ -497,6 +497,7 @@ export function createProjectStorybookDir( root: string, projectType: string, projectIsRootProjectInStandaloneWorkspace: boolean, + interactionTests: boolean, mainDir?: string, isNextJs?: boolean, usesSwc?: boolean, @@ -533,6 +534,7 @@ export function createProjectStorybookDir( offsetFromRoot: offsetFromRoot(root), projectDirectory, projectType, + interactionTests, mainDir, isNextJs: isNextJs && projectType === 'application', usesSwc, diff --git a/packages/storybook/src/generators/configuration/project-files-ts/.storybook/main.ts__tmpl__ b/packages/storybook/src/generators/configuration/project-files-ts/.storybook/main.ts__tmpl__ index 77e672c8f748e..0e8a45f81a532 100644 --- a/packages/storybook/src/generators/configuration/project-files-ts/.storybook/main.ts__tmpl__ +++ b/packages/storybook/src/generators/configuration/project-files-ts/.storybook/main.ts__tmpl__ @@ -6,7 +6,7 @@ const config: StorybookConfig = { '../**/*.stories.@(js|jsx|ts|tsx|mdx)' <% } else { %> '../<%= projectDirectory %>/**/*.stories.@(js|jsx|ts|tsx|mdx)' <% } %>], - addons: ['@storybook/addon-essentials' <% if(uiFramework === '@storybook/react-webpack5') { %>, '@nx/react/plugins/storybook' <% } %><% if(uiFramework === '@storybook/react-native') { %>, '@storybook/addon-ondevice-actions', '@storybook/addon-ondevice-backgrounds', '@storybook/addon-ondevice-controls', '@storybook/addon-ondevice-notes' <% } %>], + addons: ['@storybook/addon-essentials' <% if(interactionTests) { %>, '@storybook/addon-interactions' <% } %><% if(uiFramework === '@storybook/react-webpack5') { %>, '@nx/react/plugins/storybook' <% } %><% if(uiFramework === '@storybook/react-native') { %>, '@storybook/addon-ondevice-actions', '@storybook/addon-ondevice-backgrounds', '@storybook/addon-ondevice-controls', '@storybook/addon-ondevice-notes' <% } %>], framework: { name: '<%= uiFramework %>', options: { diff --git a/packages/storybook/src/generators/configuration/project-files/.storybook/main.js__tmpl__ b/packages/storybook/src/generators/configuration/project-files/.storybook/main.js__tmpl__ index 1ff156c232267..67a0e00d9b5b4 100644 --- a/packages/storybook/src/generators/configuration/project-files/.storybook/main.js__tmpl__ +++ b/packages/storybook/src/generators/configuration/project-files/.storybook/main.js__tmpl__ @@ -4,7 +4,7 @@ const config = { '../**/*.stories.@(js|jsx|ts|tsx|mdx)' <% } else { %> '../<%= projectDirectory %>/**/*.stories.@(js|jsx|ts|tsx|mdx)' <% } %>], - addons: ['@storybook/addon-essentials' <% if(uiFramework === '@storybook/react-webpack5') { %>, '@nx/react/plugins/storybook' <% } %><% if(uiFramework === '@storybook/react-native') { %>, '@storybook/addon-ondevice-actions', '@storybook/addon-ondevice-backgrounds', '@storybook/addon-ondevice-controls', '@storybook/addon-ondevice-notes' <% } %>], + addons: ['@storybook/addon-essentials' <% if(interactionTests) { %>, '@storybook/addon-interactions' <% } %><% if(uiFramework === '@storybook/react-webpack5') { %>, '@nx/react/plugins/storybook' <% } %><% if(uiFramework === '@storybook/react-native') { %>, '@storybook/addon-ondevice-actions', '@storybook/addon-ondevice-backgrounds', '@storybook/addon-ondevice-controls', '@storybook/addon-ondevice-notes' <% } %>], framework: { name: '<%= uiFramework %>', options: { diff --git a/packages/storybook/src/generators/configuration/schema.d.ts b/packages/storybook/src/generators/configuration/schema.d.ts index d839c71d70aad..c41c2523a5c8d 100644 --- a/packages/storybook/src/generators/configuration/schema.d.ts +++ b/packages/storybook/src/generators/configuration/schema.d.ts @@ -7,10 +7,10 @@ export interface StorybookConfigureSchema { configureCypress?: boolean; linter?: Linter; js?: boolean; + interactionTests?: boolean; tsConfiguration?: boolean; cypressDirectory?: string; standaloneConfig?: boolean; - configureTestRunner?: boolean; configureStaticServe?: boolean; skipFormat?: boolean; } diff --git a/packages/storybook/src/generators/configuration/schema.json b/packages/storybook/src/generators/configuration/schema.json index db29da5ad7a58..34190a94b6393 100644 --- a/packages/storybook/src/generators/configuration/schema.json +++ b/packages/storybook/src/generators/configuration/schema.json @@ -18,15 +18,22 @@ "x-dropdown": "projects", "x-priority": "important" }, + "interactionTests": { + "type": "boolean", + "description": "Set up Storybook interaction tests.", + "x-prompt": "Do you want to set up Storybook interaction tests?", + "alias": ["configureTestRunner"], + "default": true + }, "configureCypress": { "type": "boolean", "description": "Run the cypress-configure generator.", - "x-prompt": "Configure a cypress e2e app to run against the storybook instance?", - "x-priority": "important" + "x-deprecated": "Please use Storybook interaction tests instead." }, "cypressDirectory": { "type": "string", - "description": "A directory where the Cypress project will be placed. Added at root by default." + "description": "A directory where the Cypress project will be placed. Added at root by default.", + "x-deprecated": "Please use Storybook interaction tests instead." }, "linter": { "description": "The tool to use for running lint checks.", @@ -56,10 +63,6 @@ "description": "Add a static-storybook to serve the static storybook built files.", "default": false }, - "configureTestRunner": { - "type": "boolean", - "description": "Add a Storybook Test-Runner target." - }, "bundler": { "description": "The Storybook builder to use.", "type": "string", diff --git a/packages/storybook/src/migrations/update-14-0-0/migrate-defaults-5-to-6/migrate-defaults-5-to-6.ts b/packages/storybook/src/migrations/update-14-0-0/migrate-defaults-5-to-6/migrate-defaults-5-to-6.ts index de840cafb23cb..6d20313448739 100644 --- a/packages/storybook/src/migrations/update-14-0-0/migrate-defaults-5-to-6/migrate-defaults-5-to-6.ts +++ b/packages/storybook/src/migrations/update-14-0-0/migrate-defaults-5-to-6/migrate-defaults-5-to-6.ts @@ -196,6 +196,7 @@ function migrateProjectLevelStorybookInstance( root, projectType, false, + false, mainDir, !!nextBuildTarget, compiler === 'swc' diff --git a/packages/storybook/src/utils/versions.ts b/packages/storybook/src/utils/versions.ts index 83633c1779fe4..e62270f770354 100644 --- a/packages/storybook/src/utils/versions.ts +++ b/packages/storybook/src/utils/versions.ts @@ -1,7 +1,9 @@ export const nxVersion = require('../../package.json').version; export const storybookReactNativeVersion = '^6.5.3'; export const reactNativeStorybookLoader = '^2.0.5'; -export const storybookTestRunnerVersion = '^0.7.2'; +export const storybookTestRunnerVersion = '^0.11.0'; +export const storybookTestingLibraryVersion = '~0.2.0'; +export const storybookJestVersion = '~0.1.0'; export const litVersion = '^2.6.1'; export const tsNodeVersion = '10.9.1'; From 77bb4b7429ac0c011afeb684b265662b25ae3d19 Mon Sep 17 00:00:00 2001 From: Colum Ferry Date: Wed, 12 Jul 2023 16:14:52 +0100 Subject: [PATCH 059/262] feat(angular): add support for TS Module Federation Config #15739 (#17876) --- packages/angular/package.json | 2 - .../builders/utilities/module-federation.ts | 55 +++++++++++---- .../angular/src/builders/utilities/webpack.ts | 23 +----- packages/js/package.json | 2 + .../src/utils/typescript/tsnode-register.ts | 21 ++++++ packages/next/package.json | 2 - .../executors/server/lib/tsnode-register.ts | 20 ------ .../module-federation-dev-server.impl.ts | 70 +++++++++++++++---- packages/webpack/package.json | 2 - .../src/utils/webpack/custom-webpack.ts | 25 +------ 10 files changed, 125 insertions(+), 97 deletions(-) create mode 100644 packages/js/src/utils/typescript/tsnode-register.ts delete mode 100644 packages/next/src/executors/server/lib/tsnode-register.ts diff --git a/packages/angular/package.json b/packages/angular/package.json index b6f509f229be9..45f04bf13dff3 100644 --- a/packages/angular/package.json +++ b/packages/angular/package.json @@ -55,8 +55,6 @@ "magic-string": "~0.26.2", "minimatch": "3.0.5", "semver": "7.5.3", - "ts-node": "10.9.1", - "tsconfig-paths": "^4.1.2", "webpack": "^5.80.0", "webpack-merge": "5.7.3", "enquirer": "^2.3.6", diff --git a/packages/angular/src/builders/utilities/module-federation.ts b/packages/angular/src/builders/utilities/module-federation.ts index eebc91bc660c1..73a118753053f 100644 --- a/packages/angular/src/builders/utilities/module-federation.ts +++ b/packages/angular/src/builders/utilities/module-federation.ts @@ -1,7 +1,8 @@ import { ProjectConfiguration } from 'nx/src/config/workspace-json-project-json'; import { join } from 'path'; import { existsSync, readFileSync } from 'fs'; -import { logger, Remotes } from '@nx/devkit'; +import { logger } from '@nx/devkit'; +import { tsNodeRegister } from '@nx/js/src/utils/typescript/tsnode-register'; export function getDynamicRemotes( project: ProjectConfiguration, @@ -71,26 +72,54 @@ export function getDynamicRemotes( return dynamicRemotes; } -export function getStaticRemotes( - project: ProjectConfiguration, - context: import('@angular-devkit/architect').BuilderContext, - workspaceProjects: Record, - remotesToSkip: Set -): string[] { - const mfConfigPath = join( - context.workspaceRoot, - project.root, +function getModuleFederationConfig( + tsconfigPath: string, + workspaceRoot: string, + projectRoot: string +) { + const moduleFederationConfigPathJS = join( + workspaceRoot, + projectRoot, 'module-federation.config.js' ); - let mfeConfig: { remotes: Remotes }; + const moduleFederationConfigPathTS = join( + workspaceRoot, + projectRoot, + 'module-federation.config.ts' + ); + + let moduleFederationConfigPath = moduleFederationConfigPathJS; + + if (existsSync(moduleFederationConfigPathTS)) { + tsNodeRegister(moduleFederationConfigPathTS, tsconfigPath); + moduleFederationConfigPath = moduleFederationConfigPathTS; + } + try { - mfeConfig = require(mfConfigPath); + const config = require(moduleFederationConfigPath); + return { + mfeConfig: config.default || config, + mfConfigPath: moduleFederationConfigPath, + }; } catch { throw new Error( - `Could not load ${mfConfigPath}. Was this project generated with "@nx/angular:host"?` + `Could not load ${moduleFederationConfigPath}. Was this project generated with "@nx/angular:host"?` ); } +} + +export function getStaticRemotes( + project: ProjectConfiguration, + context: import('@angular-devkit/architect').BuilderContext, + workspaceProjects: Record, + remotesToSkip: Set +): string[] { + const { mfeConfig, mfConfigPath } = getModuleFederationConfig( + project.targets.build.options.tsConfig, + context.workspaceRoot, + project.root + ); const remotesConfig = Array.isArray(mfeConfig.remotes) && mfeConfig.remotes.length > 0 diff --git a/packages/angular/src/builders/utilities/webpack.ts b/packages/angular/src/builders/utilities/webpack.ts index 0392d70b0f873..3e213d43939fa 100644 --- a/packages/angular/src/builders/utilities/webpack.ts +++ b/packages/angular/src/builders/utilities/webpack.ts @@ -1,4 +1,5 @@ import { merge } from 'webpack-merge'; +import { tsNodeRegister } from '@nx/js/src/utils/typescript/tsnode-register'; export async function mergeCustomWebpackConfig( baseWebpackConfig: any, @@ -48,25 +49,3 @@ export function resolveIndexHtmlTransformer( return (indexHtml) => transform(target, indexHtml); } - -function tsNodeRegister(file: string, tsConfig?: string) { - if (!file?.endsWith('.ts')) return; - // Register TS compiler lazily - require('ts-node').register({ - project: tsConfig, - compilerOptions: { - module: 'CommonJS', - types: ['node'], - }, - }); - - if (!tsConfig) return; - - // Register paths in tsConfig - const tsconfigPaths = require('tsconfig-paths'); - const { absoluteBaseUrl: baseUrl, paths } = - tsconfigPaths.loadConfig(tsConfig); - if (baseUrl && paths) { - tsconfigPaths.register({ baseUrl, paths }); - } -} diff --git a/packages/js/package.json b/packages/js/package.json index 2ec87c187a4a6..90d922000c143 100644 --- a/packages/js/package.json +++ b/packages/js/package.json @@ -47,6 +47,8 @@ "detect-port": "^1.5.1", "fast-glob": "3.2.7", "fs-extra": "^11.1.0", + "ts-node": "10.9.1", + "tsconfig-paths": "^4.1.2", "ignore": "^5.0.4", "js-tokens": "^4.0.0", "minimatch": "3.0.5", diff --git a/packages/js/src/utils/typescript/tsnode-register.ts b/packages/js/src/utils/typescript/tsnode-register.ts new file mode 100644 index 0000000000000..a1d2ef6eb8af7 --- /dev/null +++ b/packages/js/src/utils/typescript/tsnode-register.ts @@ -0,0 +1,21 @@ +export function tsNodeRegister(file: string, tsConfig?: string) { + if (!file?.endsWith('.ts')) return; + // Register TS compiler lazily + require('ts-node').register({ + project: tsConfig, + compilerOptions: { + module: 'CommonJS', + types: ['node'], + }, + }); + + if (!tsConfig) return; + + // Register paths in tsConfig + const tsconfigPaths = require('tsconfig-paths'); + const { absoluteBaseUrl: baseUrl, paths } = + tsconfigPaths.loadConfig(tsConfig); + if (baseUrl && paths) { + tsconfigPaths.register({ baseUrl, paths }); + } +} diff --git a/packages/next/package.json b/packages/next/package.json index 6bbb9db10d3eb..d9a7fefffd736 100644 --- a/packages/next/package.json +++ b/packages/next/package.json @@ -44,8 +44,6 @@ "http-proxy-middleware": "^2.0.6", "ignore": "^5.0.4", "semver": "7.5.3", - "ts-node": "10.9.1", - "tsconfig-paths": "^4.1.2", "url-loader": "^4.1.1", "webpack-merge": "^5.8.0", "@nx/devkit": "file:../devkit", diff --git a/packages/next/src/executors/server/lib/tsnode-register.ts b/packages/next/src/executors/server/lib/tsnode-register.ts deleted file mode 100644 index 6cfd836fc4385..0000000000000 --- a/packages/next/src/executors/server/lib/tsnode-register.ts +++ /dev/null @@ -1,20 +0,0 @@ -export function tsNodeRegister(file: string = '', tsConfig?: string) { - if (file && file.endsWith('.ts')) { - // Register TS compiler lazily - require('ts-node').register({ - project: tsConfig, - compilerOptions: { - module: 'CommonJS', - types: ['node'], - }, - }); - - // Register paths in tsConfig - const tsconfigPaths = require('tsconfig-paths'); - const { absoluteBaseUrl: baseUrl, paths } = - tsconfigPaths.loadConfig(tsConfig); - if (baseUrl && paths) { - tsconfigPaths.register({ baseUrl, paths }); - } - } -} diff --git a/packages/react/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts b/packages/react/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts index 262ac3d878dd2..68e0e5dd39191 100644 --- a/packages/react/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts +++ b/packages/react/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts @@ -1,4 +1,10 @@ -import { ExecutorContext, logger, runExecutor } from '@nx/devkit'; +import { + ExecutorContext, + logger, + parseTargetString, + readTargetOptions, + runExecutor, +} from '@nx/devkit'; import devServerExecutor from '@nx/webpack/src/executors/dev-server/dev-server.impl'; import { WebDevServerOptions } from '@nx/webpack/src/executors/dev-server/schema'; import { join } from 'path'; @@ -10,33 +16,72 @@ import * as chalk from 'chalk'; import { waitForPortOpen } from '@nx/web/src/utils/wait-for-port-open'; import { findMatchingProjects } from 'nx/src/utils/find-matching-projects'; import { fork } from 'child_process'; +import { existsSync } from 'fs'; +import { tsNodeRegister } from '@nx/js/src/utils/typescript/tsnode-register'; type ModuleFederationDevServerOptions = WebDevServerOptions & { devRemotes?: string | string[]; skipRemotes?: string[]; }; -export default async function* moduleFederationDevServer( - options: ModuleFederationDevServerOptions, - context: ExecutorContext -): AsyncIterableIterator<{ success: boolean; baseUrl?: string }> { - const currIter = devServerExecutor(options, context); - const p = context.projectsConfigurations.projects[context.projectName]; +function getBuildOptions(buildTarget: string, context: ExecutorContext) { + const target = parseTargetString(buildTarget, context.projectGraph); - const moduleFederationConfigPath = join( - context.root, - p.root, + const buildOptions = readTargetOptions(target, context); + + return { + ...buildOptions, + }; +} + +function getModuleFederationConfig( + tsconfigPath: string, + workspaceRoot: string, + projectRoot: string +) { + const moduleFederationConfigPathJS = join( + workspaceRoot, + projectRoot, 'module-federation.config.js' ); - let moduleFederationConfig: any; + const moduleFederationConfigPathTS = join( + workspaceRoot, + projectRoot, + 'module-federation.config.ts' + ); + + let moduleFederationConfigPath = moduleFederationConfigPathJS; + + if (existsSync(moduleFederationConfigPathTS)) { + tsNodeRegister(moduleFederationConfigPathTS, tsconfigPath); + moduleFederationConfigPath = moduleFederationConfigPathTS; + } + try { - moduleFederationConfig = require(moduleFederationConfigPath); + const config = require(moduleFederationConfigPath); + return config.default || config; } catch { throw new Error( `Could not load ${moduleFederationConfigPath}. Was this project generated with "@nx/react:host"?\nSee: https://nx.dev/recipes/module-federation/faster-builds` ); } +} + +export default async function* moduleFederationDevServer( + options: ModuleFederationDevServerOptions, + context: ExecutorContext +): AsyncIterableIterator<{ success: boolean; baseUrl?: string }> { + const nxBin = require.resolve('nx'); + const currIter = devServerExecutor(options, context); + const p = context.projectsConfigurations.projects[context.projectName]; + const buildOptions = getBuildOptions(options.buildTarget, context); + + const moduleFederationConfig = getModuleFederationConfig( + buildOptions.tsConfig, + context.root, + p.root + ); const remotesToSkip = new Set( findMatchingProjects(options.skipRemotes, context.projectGraph.nodes) ?? [] @@ -88,7 +133,6 @@ export default async function* moduleFederationDevServer( )} with ${knownRemotes.length} remotes` ); - const nxBin = require.resolve('nx'); const devRemoteIters: AsyncIterable<{ success: boolean }>[] = []; let isCollectingStaticRemoteOutput = true; diff --git a/packages/webpack/package.json b/packages/webpack/package.json index ec9cb46f34fe8..c74d0397865e9 100644 --- a/packages/webpack/package.json +++ b/packages/webpack/package.json @@ -59,8 +59,6 @@ "stylus-loader": "^7.1.0", "terser-webpack-plugin": "^5.3.3", "ts-loader": "^9.3.1", - "ts-node": "10.9.1", - "tsconfig-paths": "^4.1.2", "tsconfig-paths-webpack-plugin": "4.0.0", "tslib": "^2.3.0", "webpack": "^5.80.0", diff --git a/packages/webpack/src/utils/webpack/custom-webpack.ts b/packages/webpack/src/utils/webpack/custom-webpack.ts index dc963026e246d..7e4d00bc39f5e 100644 --- a/packages/webpack/src/utils/webpack/custom-webpack.ts +++ b/packages/webpack/src/utils/webpack/custom-webpack.ts @@ -1,26 +1,4 @@ -export function tsNodeRegister(file: string = '', tsConfig?: string) { - if (!file?.endsWith('.ts')) return; - - // Avoid double-registering which can lead to issues type-checking already transformed files. - if (isRegistered()) return; - - // Register TS compiler lazily - require('ts-node').register({ - project: tsConfig, - compilerOptions: { - module: 'CommonJS', - types: ['node'], - }, - }); - - // Register paths in tsConfig - const tsconfigPaths = require('tsconfig-paths'); - const { absoluteBaseUrl: baseUrl, paths } = - tsconfigPaths.loadConfig(tsConfig); - if (baseUrl && paths) { - tsconfigPaths.register({ baseUrl, paths }); - } -} +import { tsNodeRegister } from '@nx/js/src/utils/typescript/tsnode-register'; export function resolveCustomWebpackConfig(path: string, tsConfig: string) { tsNodeRegister(path, tsConfig); @@ -33,6 +11,7 @@ export function resolveCustomWebpackConfig(path: string, tsConfig: string) { // `{ default: { ... } }` return customWebpackConfig.default || customWebpackConfig; } + export function isRegistered() { return ( require.extensions['.ts'] != undefined || From da2674ded6be5dc7dfc4c564800c236e547ed69c Mon Sep 17 00:00:00 2001 From: Caleb Ukle Date: Wed, 12 Jul 2023 17:00:05 -0500 Subject: [PATCH 060/262] Revert "feat(testing): update jest to v29.6.1 (#18061)" (#18096) --- packages/jest/migrations.json | 33 ----------------------------- packages/jest/src/utils/versions.ts | 6 +++--- 2 files changed, 3 insertions(+), 36 deletions(-) diff --git a/packages/jest/migrations.json b/packages/jest/migrations.json index fa19e79b3e5f7..7189072a8ad46 100644 --- a/packages/jest/migrations.json +++ b/packages/jest/migrations.json @@ -285,39 +285,6 @@ "alwaysAddToPackageJson": false } } - }, - "16.5.2": { - "version": "16.5.2-beta.0", - "packages": { - "jest": { - "version": "~29.6.1", - "alwaysAddToPackageJson": false - }, - "@types/jest": { - "version": "~29.5.3", - "alwaysAddToPackageJson": false - }, - "expect": { - "version": "~29.6.1", - "alwaysAddToPackageJson": false - }, - "@jest/globals": { - "version": "~29.6.1", - "alwaysAddToPackageJson": false - }, - "jest-jasmine2": { - "version": "~29.6.1", - "alwaysAddToPackageJson": false - }, - "jest-environment-jsdom": { - "version": "~29.6.1", - "alwaysAddToPackageJson": false - }, - "babel-jest": { - "version": "~29.6.1", - "alwaysAddToPackageJson": false - } - } } } } diff --git a/packages/jest/src/utils/versions.ts b/packages/jest/src/utils/versions.ts index 46ad0dfe41ab0..fcee08950aa0c 100644 --- a/packages/jest/src/utils/versions.ts +++ b/packages/jest/src/utils/versions.ts @@ -1,7 +1,7 @@ export const nxVersion = require('../../package.json').version; -export const jestVersion = '^29.6.1'; -export const babelJestVersion = '^29.6.1'; -export const jestTypesVersion = '^29.5.3'; +export const jestVersion = '^29.4.1'; +export const babelJestVersion = '^29.4.1'; +export const jestTypesVersion = '^29.4.0'; export const tsJestVersion = '^29.1.0'; export const tslibVersion = '^2.3.0'; export const swcJestVersion = '0.2.20'; From ae773d547e91e3ffcd015a8afbef0c32ff7df137 Mon Sep 17 00:00:00 2001 From: Jack Hsu Date: Wed, 12 Jul 2023 20:59:36 -0400 Subject: [PATCH 061/262] fix(linter): skip verifying deps of deps by default in package.json (#18058) --- e2e/linter/src/linter.test.ts | 12 +- .../src/rules/dependency-checks.spec.ts | 171 +++++--- .../src/rules/dependency-checks.ts | 85 ++-- .../src/utils/package-json-utils.ts | 13 +- .../src/utils/find-npm-dependencies.spec.ts | 400 ++++++++++++++++++ .../js/src/utils/find-npm-dependencies.ts | 191 +++++++++ 6 files changed, 739 insertions(+), 133 deletions(-) create mode 100644 packages/js/src/utils/find-npm-dependencies.spec.ts create mode 100644 packages/js/src/utils/find-npm-dependencies.ts diff --git a/e2e/linter/src/linter.test.ts b/e2e/linter/src/linter.test.ts index 54d90f741fbd9..8049632344cf4 100644 --- a/e2e/linter/src/linter.test.ts +++ b/e2e/linter/src/linter.test.ts @@ -452,6 +452,12 @@ describe('Linter', () => { ]; return json; }); + // Set this to false for now until the `@nx/js:lib` generator is updated to include ts/swc helpers by default. + // TODO(jack): Remove this once the above is addressed in another PR. + updateJson(`libs/${mylib}/tsconfig.lib.json`, (json) => { + json.compilerOptions.importHelpers = false; + return json; + }); updateJson(`libs/${mylib}/project.json`, (json) => { json.targets.lint.options.lintFilePatterns = [ `libs/${mylib}/**/*.ts`, @@ -465,8 +471,7 @@ describe('Linter', () => { it('should report dependency check issues', () => { const rootPackageJson = readJson('package.json'); const nxVersion = rootPackageJson.devDependencies.nx; - const swcCoreVersion = rootPackageJson.devDependencies['@swc/core']; - const swcHelpersVersion = rootPackageJson.dependencies['@swc/helpers']; + const tslibVersion = rootPackageJson.devDependencies['tslib']; let out = runCLI(`lint ${mylib}`, { silenceError: true }); expect(out).toContain('All files pass linting'); @@ -495,9 +500,6 @@ describe('Linter', () => { { "dependencies": { "@nx/devkit": "${nxVersion}", - "@swc/core": "${swcCoreVersion}", - "@swc/helpers": "${swcHelpersVersion}", - "nx": "${nxVersion}", }, "name": "@proj/${mylib}", "type": "commonjs", diff --git a/packages/eslint-plugin/src/rules/dependency-checks.spec.ts b/packages/eslint-plugin/src/rules/dependency-checks.spec.ts index a0b40558615e3..c0fa7ade83621 100644 --- a/packages/eslint-plugin/src/rules/dependency-checks.spec.ts +++ b/packages/eslint-plugin/src/rules/dependency-checks.spec.ts @@ -104,7 +104,7 @@ describe('Dependency checks (eslint)', () => { const failures = runRule( {}, - `${process.cwd()}/proj/libs/liba/package.json`, + `/root/libs/liba/package.json`, JSON.stringify(packageJson, null, 2), { nodes: { @@ -134,6 +134,74 @@ describe('Dependency checks (eslint)', () => { expect(failures.length).toEqual(0); }); + it('should exclude files not matching input of the build target', () => { + const packageJson = { + name: '@mycompany/liba', + dependencies: {}, + }; + + const fileSys = { + './libs/liba/package.json': JSON.stringify(packageJson, null, 2), + './libs/liba/src/index.ts': '', + './libs/liba/project.json': JSON.stringify( + { + name: 'liba', + targets: { + build: { + command: 'tsc -p tsconfig.lib.json', + }, + }, + }, + null, + 2 + ), + './nx.json': JSON.stringify({ + targetDefaults: { + build: { + inputs: [ + '{projectRoot}/**/*', + '!{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)?(.snap)', + ], + }, + }, + }), + './package.json': JSON.stringify(rootPackageJson, null, 2), + }; + vol.fromJSON(fileSys, '/root'); + + const failures = runRule( + {}, + `/root/libs/liba/package.json`, + JSON.stringify(packageJson, null, 2), + { + nodes: { + liba: { + name: 'liba', + type: 'lib', + data: { + root: 'libs/liba', + targets: { + build: {}, + }, + }, + }, + }, + externalNodes, + dependencies: { + liba: [{ source: 'liba', target: 'npm:external1', type: 'static' }], + }, + }, + { + liba: [ + createFile(`libs/liba/src/main.ts`, []), + createFile(`libs/liba/src/main.spec.ts`, ['npm:external1']), + createFile(`libs/liba/package.json`, []), + ], + } + ); + expect(failures.length).toEqual(0); + }); + it('should report missing dependencies section and fix it', () => { const packageJson = { name: '@mycompany/liba', @@ -148,7 +216,7 @@ describe('Dependency checks (eslint)', () => { const failures = runRule( {}, - `${process.cwd()}/proj/libs/liba/package.json`, + `/root/libs/liba/package.json`, JSON.stringify(packageJson, null, 2), { nodes: { @@ -191,7 +259,6 @@ describe('Dependency checks (eslint)', () => { "{ "name": "@mycompany/liba", "dependencies": { - "external1": "~16.1.2" } }" `); @@ -211,7 +278,7 @@ describe('Dependency checks (eslint)', () => { const failures = runRule( { ignoredDependencies: ['external1'] }, - `${process.cwd()}/proj/libs/liba/package.json`, + `/root/libs/liba/package.json`, JSON.stringify(packageJson, null, 2), { nodes: { @@ -255,7 +322,7 @@ describe('Dependency checks (eslint)', () => { const failures = runRule( { ignoredDependencies: ['external1'] }, - `${process.cwd()}/proj/libs/liba/package.json`, + `/root/libs/liba/package.json`, JSON.stringify(packageJson, null, 2), { nodes: { @@ -299,7 +366,7 @@ describe('Dependency checks (eslint)', () => { const failures = runRule( { ignoredDependencies: ['external1'] }, - `${process.cwd()}/proj/libs/liba/package.json`, + `/root/libs/liba/package.json`, JSON.stringify(packageJson, null, 2), { nodes: { @@ -344,7 +411,7 @@ describe('Dependency checks (eslint)', () => { const failures = runRule( {}, - `${process.cwd()}/proj/libs/liba/package.json`, + `/root/libs/liba/package.json`, JSON.stringify(packageJson, null, 2), { nodes: { @@ -416,7 +483,7 @@ describe('Dependency checks (eslint)', () => { const failures = runRule( {}, - `${process.cwd()}/proj/libs/liba/package.json`, + `/root/libs/liba/package.json`, JSON.stringify(packageJson, null, 2), { nodes: { @@ -473,7 +540,7 @@ describe('Dependency checks (eslint)', () => { const failures = runRule( {}, - `${process.cwd()}/proj/libs/liba/package.json`, + `/root/libs/liba/package.json`, JSON.stringify(packageJson, null, 2), { nodes: { @@ -534,7 +601,7 @@ describe('Dependency checks (eslint)', () => { const failures = runRule( { buildTargets: ['notbuild'] }, - `${process.cwd()}/proj/libs/liba/package.json`, + `/root/libs/liba/package.json`, JSON.stringify(packageJson, null, 2), { nodes: { @@ -590,7 +657,7 @@ describe('Dependency checks (eslint)', () => { const failures = runRule( { checkMissingDependencies: false }, - `${process.cwd()}/proj/libs/liba/package.json`, + `/root/libs/liba/package.json`, JSON.stringify(packageJson, null, 2), { nodes: { @@ -646,7 +713,7 @@ describe('Dependency checks (eslint)', () => { const failures = runRule( { ignoredDependencies: ['external2'] }, - `${process.cwd()}/proj/libs/liba/package.json`, + `/root/libs/liba/package.json`, JSON.stringify(packageJson, null, 2), { nodes: { @@ -706,7 +773,7 @@ describe('Dependency checks (eslint)', () => { const failures = runRule( {}, - `${process.cwd()}/proj/libs/liba/package.json`, + `/root/libs/liba/package.json`, JSON.stringify(packageJson, null, 2), { nodes: { @@ -778,7 +845,7 @@ describe('Dependency checks (eslint)', () => { const failures = runRule( {}, - `${process.cwd()}/proj/libs/liba/package.json`, + `/root/libs/liba/package.json`, JSON.stringify(packageJson, null, 2), { nodes: { @@ -857,7 +924,7 @@ describe('Dependency checks (eslint)', () => { const failures = runRule( {}, - `${process.cwd()}/proj/libs/liba/package.json`, + `/root/libs/liba/package.json`, JSON.stringify(packageJson, null, 2), { nodes: { @@ -936,7 +1003,7 @@ describe('Dependency checks (eslint)', () => { const failures = runRule( {}, - `${process.cwd()}/proj/libs/liba/package.json`, + `/root/libs/liba/package.json`, JSON.stringify(packageJson, null, 2), { nodes: { @@ -1015,7 +1082,7 @@ describe('Dependency checks (eslint)', () => { const failures = runRule( { checkObsoleteDependencies: false }, - `${process.cwd()}/proj/libs/liba/package.json`, + `/root/libs/liba/package.json`, JSON.stringify(packageJson, null, 2), { nodes: { @@ -1068,7 +1135,7 @@ describe('Dependency checks (eslint)', () => { const failures = runRule( { ignoredDependencies: ['unneeded'] }, - `${process.cwd()}/proj/libs/liba/package.json`, + `/root/libs/liba/package.json`, JSON.stringify(packageJson, null, 2), { nodes: { @@ -1119,7 +1186,7 @@ describe('Dependency checks (eslint)', () => { const failures = runRule( {}, - `${process.cwd()}/proj/libs/liba/package.json`, + `/root/libs/liba/package.json`, JSON.stringify(packageJson, null, 2), { nodes: { @@ -1204,7 +1271,7 @@ describe('Dependency checks (eslint)', () => { const failures = runRule( { checkVersionMismatches: false }, - `${process.cwd()}/proj/libs/liba/package.json`, + `/root/libs/liba/package.json`, JSON.stringify(packageJson, null, 2), { nodes: { @@ -1261,7 +1328,7 @@ describe('Dependency checks (eslint)', () => { const failures = runRule( { ignoredDependencies: ['external1'] }, - `${process.cwd()}/proj/libs/liba/package.json`, + `/root/libs/liba/package.json`, JSON.stringify(packageJson, null, 2), { nodes: { @@ -1330,7 +1397,7 @@ describe('Dependency checks (eslint)', () => { include: ['**/*.ts'], }; - const tsConfiogBaseJson = { + const tsConfigBaseJson = { compilerOptions: { target: 'es2015', importHelpers: true, @@ -1353,15 +1420,15 @@ describe('Dependency checks (eslint)', () => { const fileSys = { './libs/liba/package.json': JSON.stringify(packageJson, null, 2), './libs/liba/src/index.ts': '', - './libs/libb/tsconfig.json': JSON.stringify(tsConfigJson, null, 2), + './libs/liba/tsconfig.json': JSON.stringify(tsConfigJson, null, 2), './package.json': JSON.stringify(rootPackageJson, null, 2), - './tsconfig.base.json': JSON.stringify(tsConfiogBaseJson, null, 2), + './tsconfig.base.json': JSON.stringify(tsConfigBaseJson, null, 2), }; vol.fromJSON(fileSys, '/root'); const failures = runRule( {}, - `${process.cwd()}/proj/libs/liba/package.json`, + `/root/libs/liba/package.json`, JSON.stringify(packageJson, null, 2), { nodes: { @@ -1370,21 +1437,11 @@ describe('Dependency checks (eslint)', () => { type: 'lib', data: { root: 'libs/liba', - targets: { - build: {}, - }, - }, - }, - libb: { - name: 'libb', - type: 'lib', - data: { - root: 'libs/libb', targets: { build: { executor: '@nx/js:tsc', options: { - tsConfig: 'libs/libb/tsconfig.json', + tsConfig: 'libs/liba/tsconfig.json', }, }, }, @@ -1393,26 +1450,20 @@ describe('Dependency checks (eslint)', () => { }, externalNodes, dependencies: { - liba: [ - { source: 'liba', target: 'npm:external1', type: 'static' }, - { source: 'liba', target: 'libb', type: 'static' }, - ], - libb: [{ source: 'libb', target: 'npm:external2', type: 'static' }], + liba: [{ source: 'liba', target: 'npm:external1', type: 'static' }], }, }, { liba: [ createFile(`libs/liba/src/main.ts`, ['npm:external1']), createFile(`libs/liba/package.json`, ['npm:external1']), - createFile(`libs/libb/src/main.ts`, ['npm:external2']), ], } ); expect(failures.length).toEqual(1); expect(failures[0].message).toMatchInlineSnapshot(` "The "liba" uses the following packages, but they are missing from the "dependencies": - - tslib - - external2" + - tslib" `); expect(failures[0].line).toEqual(3); }); @@ -1435,14 +1486,14 @@ it('should require swc if @nx/js:swc executor', () => { const fileSys = { './libs/liba/package.json': JSON.stringify(packageJson, null, 2), './libs/liba/src/index.ts': '', - './libs/libb/.swcrc': JSON.stringify(swcrc, null, 2), + './libs/liba/.swcrc': JSON.stringify(swcrc, null, 2), './package.json': JSON.stringify(rootPackageJson, null, 2), }; vol.fromJSON(fileSys, '/root'); const failures = runRule( {}, - `${process.cwd()}/proj/libs/liba/package.json`, + `/root/libs/liba/package.json`, JSON.stringify(packageJson, null, 2), { nodes: { @@ -1451,22 +1502,10 @@ it('should require swc if @nx/js:swc executor', () => { type: 'lib', data: { root: 'libs/liba', - targets: { - build: {}, - }, - }, - }, - libb: { - name: 'libb', - type: 'lib', - data: { - root: 'libs/libb', targets: { build: { executor: '@nx/js:swc', - options: { - tsConfig: 'libs/libb/tsconfig.json', - }, + options: {}, }, }, }, @@ -1474,26 +1513,21 @@ it('should require swc if @nx/js:swc executor', () => { }, externalNodes, dependencies: { - liba: [ - { source: 'liba', target: 'npm:external1', type: 'static' }, - { source: 'liba', target: 'libb', type: 'static' }, - ], - libb: [], + liba: [{ source: 'liba', target: 'npm:external1', type: 'static' }], }, }, { liba: [ createFile(`libs/liba/src/main.ts`, ['npm:external1']), createFile(`libs/liba/package.json`, ['npm:external1']), - createFile(`libs/libb/src/main.ts`), ], } ); expect(failures.length).toEqual(1); expect(failures[0].message).toMatchInlineSnapshot(` - "The "liba" uses the following packages, but they are missing from the "dependencies": - - @swc/helpers" -`); + "The "liba" uses the following packages, but they are missing from the "dependencies": + - @swc/helpers" + `); expect(failures[0].line).toEqual(3); }); @@ -1518,7 +1552,6 @@ function runRule( projectGraph: ProjectGraph, projectFileMap: ProjectFileMap ): Linter.LintMessage[] { - globalThis.projectPath = `${process.cwd()}/proj`; globalThis.projectGraph = projectGraph; globalThis.projectFileMap = projectFileMap; globalThis.projectRootMappings = createProjectRootMappings( diff --git a/packages/eslint-plugin/src/rules/dependency-checks.ts b/packages/eslint-plugin/src/rules/dependency-checks.ts index 25c4ae9c400e0..b539ebd27d6e2 100644 --- a/packages/eslint-plugin/src/rules/dependency-checks.ts +++ b/packages/eslint-plugin/src/rules/dependency-checks.ts @@ -1,18 +1,22 @@ +import { join } from 'path'; +import { satisfies } from 'semver'; import { AST } from 'jsonc-eslint-parser'; -import { normalizePath, workspaceRoot } from '@nx/devkit'; +import { type JSONLiteral } from 'jsonc-eslint-parser/lib/parser/ast'; +import { + normalizePath, + ProjectGraphProjectNode, + FileData, + workspaceRoot, +} from '@nx/devkit'; +import { findNpmDependencies } from '@nx/js/src/utils/find-npm-dependencies'; + import { createESLintRule } from '../utils/create-eslint-rule'; import { readProjectGraph } from '../utils/project-graph-utils'; import { findProject, getSourceFilePath } from '../utils/runtime-lint-utils'; -import { join } from 'path'; -import { findProjectsNpmDependencies } from '@nx/js/src/internal'; -import { satisfies } from 'semver'; -import { getHelperDependenciesFromProjectGraph } from '@nx/js'; import { getAllDependencies, getPackageJson, - removePackageJsonFromFileMap, } from '../utils/package-json-utils'; -import { JSONLiteral } from 'jsonc-eslint-parser/lib/parser/ast'; export type Options = [ { @@ -22,6 +26,7 @@ export type Options = [ checkVersionMismatches?: boolean; checkMissingPackageJson?: boolean; ignoredDependencies?: string[]; + includeTransitiveDependencies?: boolean; } ]; @@ -51,6 +56,7 @@ export default createESLintRule({ checkMissingDependencies: { type: 'boolean' }, checkObsoleteDependencies: { type: 'boolean' }, checkVersionMismatches: { type: 'boolean' }, + includeTransitiveDependencies: { type: 'boolean' }, }, additionalProperties: false, }, @@ -69,6 +75,7 @@ export default createESLintRule({ checkObsoleteDependencies: true, checkVersionMismatches: true, ignoredDependencies: [], + includeTransitiveDependencies: false, }, ], create( @@ -80,6 +87,7 @@ export default createESLintRule({ checkMissingDependencies, checkObsoleteDependencies, checkVersionMismatches, + includeTransitiveDependencies, }, ] ) { @@ -92,8 +100,7 @@ export default createESLintRule({ return {}; } - const projectPath = normalizePath(globalThis.projectPath || workspaceRoot); - const sourceFilePath = getSourceFilePath(fileName, projectPath); + const sourceFilePath = getSourceFilePath(fileName, workspaceRoot); const { projectGraph, projectRootMappings, projectFileMap } = readProjectGraph(RULE_NAME); @@ -120,32 +127,19 @@ export default createESLintRule({ return {}; } - // gather helper dependencies for @nx/js executors - const helperDependencies = getHelperDependenciesFromProjectGraph( - workspaceRoot, - sourceProject.name, - projectGraph - ); - const rootPackageJson = getPackageJson(join(workspaceRoot, 'package.json')); - // find all dependencies for the project - const npmDeps = findProjectsNpmDependencies( + const npmDependencies = findNpmDependencies( + workspaceRoot, sourceProject, projectGraph, - buildTarget, - rootPackageJson, + projectFileMap, + buildTarget, // TODO: What if child library has a build target different from the parent? { - helperDependencies: helperDependencies.map((dep) => dep.target), - isProduction: true, - }, - removePackageJsonFromFileMap(projectFileMap) + includeTransitiveDependencies, + } ); - const projDependencies = { - ...npmDeps.dependencies, - ...npmDeps.peerDependencies, - }; - const expectedDependencyNames = Object.keys(projDependencies); + const expectedDependencyNames = Object.keys(npmDependencies); const projPackageJsonPath = join( workspaceRoot, @@ -180,7 +174,7 @@ export default createESLintRule({ fix(fixer) { missingDeps.forEach((d) => { projPackageJsonDeps[d] = - rootPackageJsonDeps[d] || projDependencies[d]; + rootPackageJsonDeps[d] || npmDependencies[d]; }); const deps = (node.value as AST.JSONObjectExpression).properties; @@ -213,8 +207,9 @@ export default createESLintRule({ return; } if ( - projDependencies[packageName] === '*' || - satisfies(projDependencies[packageName], packageRange) + npmDependencies[packageName] === '*' || + packageRange === '*' || + satisfies(npmDependencies[packageName], packageRange) ) { return; } @@ -224,13 +219,13 @@ export default createESLintRule({ messageId: 'versionMismatch', data: { packageName: packageName, - version: projDependencies[packageName], + version: npmDependencies[packageName], }, fix: (fixer) => fixer.replaceText( node as any, `"${packageName}": "${ - rootPackageJsonDeps[packageName] || projDependencies[packageName] + rootPackageJsonDeps[packageName] || npmDependencies[packageName] }"` ), }); @@ -308,15 +303,15 @@ export default createESLintRule({ .join(), }, fix: (fixer) => { - expectedDependencyNames.sort().reduce((acc, d) => { - acc[d] = rootPackageJsonDeps[d] || projDependencies[d]; - return acc; - }, projPackageJsonDeps); - const dependencies = Object.keys(projPackageJsonDeps) .map((d) => `\n "${d}": "${projPackageJsonDeps[d]}"`) .join(','); + expectedDependencyNames.sort().reduce((acc, d) => { + acc[d] = rootPackageJsonDeps[d] || dependencies[d]; + return acc; + }, projPackageJsonDeps); + if (!node.properties.length) { return fixer.replaceText( node as any, @@ -337,7 +332,7 @@ export default createESLintRule({ ['JSONExpressionStatement > JSONObjectExpression > JSONProperty[key.value=/^(dev|peer|optional)?dependencies$/i]']( node: AST.JSONProperty ) { - return validateMissingDependencies(node); + validateMissingDependencies(node); }, ['JSONExpressionStatement > JSONObjectExpression > JSONProperty[key.value=/^(dev|peer|optional)?dependencies$/i] > JSONObjectExpression > JSONProperty']( node: AST.JSONProperty @@ -350,19 +345,15 @@ export default createESLintRule({ } if (expectedDependencyNames.includes(packageName)) { - return validateVersionMatchesInstalled( - node, - packageName, - packageRange - ); + validateVersionMatchesInstalled(node, packageName, packageRange); } else { - return reportObsoleteDependency(node, packageName); + reportObsoleteDependency(node, packageName); } }, ['JSONExpressionStatement > JSONObjectExpression']( node: AST.JSONObjectExpression ) { - return validateDependenciesSectionExistance(node); + validateDependenciesSectionExistance(node); }, }; }, diff --git a/packages/eslint-plugin/src/utils/package-json-utils.ts b/packages/eslint-plugin/src/utils/package-json-utils.ts index bf1759d37f32e..178e9d09e83c0 100644 --- a/packages/eslint-plugin/src/utils/package-json-utils.ts +++ b/packages/eslint-plugin/src/utils/package-json-utils.ts @@ -9,6 +9,7 @@ export function getAllDependencies( ...packageJson.dependencies, ...packageJson.devDependencies, ...packageJson.peerDependencies, + ...packageJson.optionalDependencies, }; } @@ -18,15 +19,3 @@ export function getPackageJson(path: string): PackageJson { } return {} as PackageJson; } - -export function removePackageJsonFromFileMap( - projectFileMap: ProjectFileMap -): ProjectFileMap { - const newFileMap = {}; - Object.keys(projectFileMap).forEach((key) => { - newFileMap[key] = projectFileMap[key].filter( - (f) => !f.file.endsWith('/package.json') - ); - }); - return newFileMap; -} diff --git a/packages/js/src/utils/find-npm-dependencies.spec.ts b/packages/js/src/utils/find-npm-dependencies.spec.ts new file mode 100644 index 0000000000000..d5f0f4cd16cff --- /dev/null +++ b/packages/js/src/utils/find-npm-dependencies.spec.ts @@ -0,0 +1,400 @@ +import 'nx/src/utils/testing/mock-fs'; +import { vol } from 'memfs'; +import { findNpmDependencies } from './find-npm-dependencies'; + +jest.mock('@nx/devkit', () => ({ + ...jest.requireActual('@nx/devkit'), + workspaceRoot: '/root', +})); + +jest.mock('nx/src/utils/workspace-root', () => ({ + workspaceRoot: '/root', +})); + +describe('findNpmDependencies', () => { + const nxJson = { + targetDefaults: { + build: { + inputs: [ + '{projectRoot}/**/*', + '!{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)?(.snap)', + ], + }, + }, + }; + + afterEach(() => { + vol.reset(); + }); + + it('should pick up external npm dependencies and their versions', () => { + vol.fromJSON( + { + './nx.json': JSON.stringify(nxJson), + }, + '/root' + ); + const libWithExternalDeps = { + name: 'my-lib', + type: 'lib' as const, + data: { + root: 'libs/my-lib', + targets: { build: {} }, + }, + }; + const projectGraph = { + nodes: { + 'my-lib': libWithExternalDeps, + }, + externalNodes: { + 'npm:foo': { + name: 'npm:foo' as const, + type: 'npm' as const, + data: { + packageName: 'foo', + version: '1.0.0', + }, + }, + }, + dependencies: {}, + }; + const projectFileMap = { + 'my-lib': [ + { + file: 'libs/my-lib/index.ts', + hash: '123', + deps: ['npm:foo'], + }, + ], + }; + + const results = findNpmDependencies( + '/root', + libWithExternalDeps, + projectGraph, + projectFileMap, + 'build' + ); + + expect(results).toEqual({ + foo: '1.0.0', + }); + }); + + it('should pick up helper npm dependencies if required', () => { + vol.fromJSON( + { + './nx.json': JSON.stringify(nxJson), + './libs/my-lib/tsconfig.json': JSON.stringify({ + compilerOptions: { + importHelpers: true, + }, + }), + './libs/my-lib/.swcrc': JSON.stringify({ + jsc: { + externalHelpers: true, + }, + }), + }, + '/root' + ); + const libWithHelpers = { + name: 'my-lib', + type: 'lib' as const, + data: { + root: 'libs/my-lib', + targets: { + build1: { + executor: '@nx/js:tsc', + options: { + tsConfig: 'libs/my-lib/tsconfig.json', + }, + }, + build2: { + executor: '@nx/js:swc', + options: {}, + }, + }, + }, + }; + const projectGraph = { + nodes: { + 'my-lib': libWithHelpers, + }, + externalNodes: { + 'npm:tslib': { + name: 'npm:tslib' as const, + type: 'npm' as const, + data: { + packageName: 'tslib', + version: '2.6.0', + }, + }, + 'npm:@swc/helpers': { + name: 'npm:@swc/helpers' as const, + type: 'npm' as const, + data: { + packageName: '@swc/helpers', + version: '0.5.0', + }, + }, + }, + dependencies: {}, + }; + const projectFileMap = { + 'my-lib': [], + }; + + expect( + findNpmDependencies( + '/root', + libWithHelpers, + projectGraph, + projectFileMap, + 'build1' + ) + ).toEqual({ + tslib: '2.6.0', + }); + expect( + findNpmDependencies( + '/root', + libWithHelpers, + projectGraph, + projectFileMap, + 'build2' + ) + ).toEqual({ + '@swc/helpers': '0.5.0', + }); + }); + + it('should not pick up helper npm dependencies if not required', () => { + vol.fromJSON( + { + './libs/my-lib/tsconfig.json': JSON.stringify({ + compilerOptions: { + importHelpers: false, + }, + }), + './libs/my-lib/.swcrc': JSON.stringify({ + jsc: { + externalHelpers: false, + }, + }), + }, + '/root' + ); + const libWithInlinedHelpers = { + name: 'my-lib', + type: 'lib' as const, + data: { + root: 'libs/my-lib', + targets: { + build1: { + executor: '@nx/js:tsc', + options: { + tsConfig: 'libs/my-lib/tsconfig.json', + }, + }, + build2: { + executor: '@nx/js:swc', + options: {}, + }, + }, + }, + }; + const projectGraph = { + nodes: { + 'my-lib': libWithInlinedHelpers, + }, + externalNodes: { + 'npm:tslib': { + name: 'npm:tslib' as const, + type: 'npm' as const, + data: { + packageName: 'tslib', + version: '2.6.0', + }, + }, + 'npm:@swc/helpers': { + name: 'npm:@swc/helpers' as const, + type: 'npm' as const, + data: { + packageName: '@swc/helpers', + version: '0.5.0', + }, + }, + }, + dependencies: {}, + }; + const projectFileMap = { + 'my-lib': [], + }; + + const results = findNpmDependencies( + '/root', + libWithInlinedHelpers, + projectGraph, + projectFileMap, + 'build' + ); + + expect(results).toEqual({}); + }); + + it('should support recursive collection of dependencies', () => { + vol.fromJSON( + { + './nx.json': JSON.stringify(nxJson), + }, + '/root' + ); + const parentLib = { + name: 'parent', + type: 'lib' as const, + data: { + root: 'libs/parent', + targets: { build: {} }, + }, + }; + const projectGraph = { + nodes: { + parent: parentLib, + child1: { + name: 'child1', + type: 'lib' as const, + data: { + root: 'libs/child1', + targets: { build: {} }, + }, + }, + child2: { + name: 'child2', + type: 'lib' as const, + data: { + root: 'libs/child2', + targets: { build: {} }, + }, + }, + }, + externalNodes: { + 'npm:foo': { + name: 'npm:foo' as const, + type: 'npm' as const, + data: { + packageName: 'foo', + version: '1.0.0', + }, + }, + }, + dependencies: { + parent: [ + { + type: 'static', + source: 'parent', + target: 'child1', + }, + ], + child1: [ + { + type: 'static', + source: 'child1', + target: 'child2', + }, + ], + child2: [ + { + type: 'static', + source: 'child2', + target: 'npm:foo', + }, + ], + }, + }; + const projectFileMap = { + parent: [{ file: 'libs/parent/index.ts', hash: '123', deps: ['child1'] }], + child1: [{ file: 'libs/child1/index.ts', hash: '123', deps: ['child2'] }], + child2: [ + { file: 'libs/child2/index.ts', hash: '123', deps: ['npm:foo'] }, + ], + }; + + const results = findNpmDependencies( + '/root', + parentLib, + projectGraph, + projectFileMap, + 'build', + { + includeTransitiveDependencies: true, + } + ); + + expect(results).toEqual({ + foo: '1.0.0', + }); + }); + + it('should find workspace dependencies', () => { + vol.fromJSON( + { + './libs/lib3/package.json': JSON.stringify({ + name: '@acme/lib3', + version: '0.0.1', + }), + './nx.json': JSON.stringify(nxJson), + }, + '/root' + ); + const lib1 = { + name: 'lib1', + type: 'lib' as const, + data: { + root: 'libs/lib1', + targets: { build: {} }, + }, + }; + const lib2 = { + name: 'lib2', + type: 'lib' as const, + data: { + root: 'libs/lib2', + targets: { build: {} }, + }, + }; + const lib3 = { + name: 'lib3', + type: 'lib' as const, + data: { + root: 'libs/lib3', + targets: { build: {} }, + }, + }; + const projectGraph = { + nodes: { + lib1: lib1, + lib2: lib2, + lib3: lib3, + }, + externalNodes: {}, + dependencies: {}, + }; + const projectFileMap = { + lib1: [{ file: 'libs/lib1/index.ts', hash: '123', deps: ['lib3'] }], + lib2: [{ file: 'libs/lib1/index.ts', hash: '123', deps: ['lib3'] }], + lib3: [], + }; + + expect( + findNpmDependencies('/root', lib1, projectGraph, projectFileMap, 'build') + ).toEqual({ + '@acme/lib3': '*', + }); + expect( + findNpmDependencies('/root', lib2, projectGraph, projectFileMap, 'build') + ).toEqual({ + '@acme/lib3': '*', + }); + }); +}); diff --git a/packages/js/src/utils/find-npm-dependencies.ts b/packages/js/src/utils/find-npm-dependencies.ts new file mode 100644 index 0000000000000..7a14fd70fcd62 --- /dev/null +++ b/packages/js/src/utils/find-npm-dependencies.ts @@ -0,0 +1,191 @@ +import { join } from 'path'; +import { readNxJson } from 'nx/src/project-graph/file-utils'; +import { + getTargetInputs, + filterUsingGlobPatterns, +} from 'nx/src/hasher/task-hasher'; +import { + type ProjectGraph, + type ProjectGraphProjectNode, + type ProjectFileMap, + readJsonFile, + FileData, + joinPathFragments, +} from '@nx/devkit'; +import { fileExists } from 'nx/src/utils/fileutils'; +import { fileDataDepTarget } from 'nx/src/config/project-graph'; +import { readTsConfig } from './typescript/ts-config'; + +/** + * Finds all npm dependencies and their expected versions for a given project. + */ +export function findNpmDependencies( + workspaceRoot: string, + sourceProject: ProjectGraphProjectNode, + projectGraph: ProjectGraph, + projectFileMap: ProjectFileMap, + buildTarget: string, + options: { + includeTransitiveDependencies?: boolean; + } = {} +): Record { + let seen: null | Set = null; + if (options.includeTransitiveDependencies) { + seen = new Set(); + } + + const results: Record = {}; + + function collectAll( + currentProject: ProjectGraphProjectNode, + collectedDeps: Record + ): void { + if (seen?.has(currentProject.name)) return; + + collectDependenciesFromFileMap( + workspaceRoot, + currentProject, + projectGraph, + projectFileMap, + buildTarget, + collectedDeps + ); + + collectHelperDependencies( + workspaceRoot, + currentProject, + projectGraph, + buildTarget, + collectedDeps + ); + + if (options.includeTransitiveDependencies) { + const projectDeps = projectGraph.dependencies[currentProject.name]; + for (const dep of projectDeps) { + const projectDep = projectGraph.nodes[dep.target]; + if (projectDep) collectAll(projectDep, collectedDeps); + } + } + } + + collectAll(sourceProject, results); + + return results; +} + +// Keep track of workspace libs we already read package.json for so we don't read from disk again. +const seenWorkspaceDeps: Record = {}; + +function collectDependenciesFromFileMap( + workspaceRoot: string, + sourceProject: ProjectGraphProjectNode, + projectGraph: ProjectGraph, + projectFileMap: ProjectFileMap, + buildTarget: string, + npmDeps: Record +): void { + const rawFiles = projectFileMap[sourceProject.name]; + if (!rawFiles) return; + + // Cannot read inputs if the target does not exist on the project. + if (!sourceProject.data.targets[buildTarget]) return; + + const inputs = getTargetInputs( + readNxJson(), + sourceProject, + buildTarget + ).selfInputs; + const files = filterUsingGlobPatterns( + sourceProject.data.root, + projectFileMap[sourceProject.name] || [], + inputs + ); + + for (const fileData of files) { + if ( + !fileData.deps || + fileData.file === + joinPathFragments(sourceProject.data.root, 'package.json') + ) { + continue; + } + + for (const dep of fileData.deps) { + const target = fileDataDepTarget(dep); + + // If the node is external, then read package info from `data`. + const externalDep = projectGraph.externalNodes[target]; + if (externalDep?.type === 'npm') { + npmDeps[externalDep.data.packageName] = externalDep.data.version; + continue; + } + + // If node is internal, then try reading package info from `package.json` (which must exist for this to work). + const workspaceDep = projectGraph.nodes[target]; + if (!workspaceDep) continue; + const cached = seenWorkspaceDeps[workspaceDep.name]; + if (cached) { + npmDeps[cached.name] = cached.version; + } else { + const packageJson = readPackageJson(workspaceDep, workspaceRoot); + if (packageJson) { + // This is a workspace lib so we can't reliably read in a specific version since it depends on how the workspace is set up. + // ASSUMPTION: Most users will use '*' for workspace lib versions. Otherwise, they can manually update it. + npmDeps[packageJson.name] = '*'; + seenWorkspaceDeps[workspaceDep.name] = { + name: packageJson.name, + version: '*', + }; + } + } + } + } +} + +function readPackageJson( + project: ProjectGraphProjectNode, + workspaceRoot: string +): null | { + name: string; + dependencies?: Record; + optionalDependencies?: Record; + peerDependencies?: Record; +} { + const packageJsonPath = join( + workspaceRoot, + project.data.root, + 'package.json' + ); + if (fileExists(packageJsonPath)) return readJsonFile(packageJsonPath); + return null; +} + +function collectHelperDependencies( + workspaceRoot: string, + sourceProject: ProjectGraphProjectNode, + projectGraph: ProjectGraph, + buildTarget: string, + npmDeps: Record +): void { + const target = sourceProject.data.targets[buildTarget]; + if (!target) return; + + if (target.executor === '@nx/js:tsc' && target.options?.tsConfig) { + const tsConfig = readTsConfig(join(workspaceRoot, target.options.tsConfig)); + if (tsConfig?.options['importHelpers']) { + npmDeps['tslib'] = projectGraph.externalNodes['npm:tslib']?.data.version; + } + } + if (target.executor === '@nx/js:swc') { + const swcConfigPath = target.options.swcrc + ? join(workspaceRoot, target.options.swcrc) + : join(workspaceRoot, sourceProject.data.root, '.swcrc'); + const swcConfig = fileExists(swcConfigPath) + ? readJsonFile(swcConfigPath) + : {}; + if (swcConfig?.jsc?.externalHelpers) { + npmDeps['@swc/helpers'] = + projectGraph.externalNodes['npm:@swc/helpers']?.data.version; + } + } +} From 6ce7fc57edda3e28a2d977ff802f57d3e7a4a0d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leosvel=20P=C3=A9rez=20Espinosa?= Date: Thu, 13 Jul 2023 08:22:09 +0100 Subject: [PATCH 062/262] fix(misc): prompt for workspace name when creating it using nx init (#18079) --- packages/nx/src/command-line/init/init.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/nx/src/command-line/init/init.ts b/packages/nx/src/command-line/init/init.ts index 3b6337a088408..75ae6e294674d 100644 --- a/packages/nx/src/command-line/init/init.ts +++ b/packages/nx/src/command-line/init/init.ts @@ -25,7 +25,8 @@ export interface InitArgs { } export async function initHandler(options: InitArgs) { - const args = process.argv.slice(2).join(' '); + // strip the 'init' command itself so we don't forward it + const args = process.argv.slice(3).join(' '); const flags = parser(args, { boolean: ['useDotNxInstallation'], alias: { From 4bba066d57712db6aba4a2dc8cf4493fdae8cf1a Mon Sep 17 00:00:00 2001 From: Katerina Skroumpelou Date: Thu, 13 Jul 2023 13:06:04 +0300 Subject: [PATCH 063/262] feat(react): interaction tests story generator (#18082) --- .../react/generators/component-story.json | 6 + .../packages/react/generators/stories.json | 13 +- .../component-story.spec.ts.snap | 446 ++++++++++++++---- .../component-story/component-story.spec.ts | 4 +- .../component-story/component-story.ts | 28 +- .../__componentFileName__.stories.__fileExt__ | 32 -- .../__componentFileName__.stories.jsx__tmpl__ | 29 ++ .../__componentFileName__.stories.tsx__tmpl__ | 33 ++ .../generators/component-story/schema.json | 6 + .../__snapshots__/stories.app.spec.ts.snap | 100 ++++ .../__snapshots__/stories.lib.spec.ts.snap | 95 ++++ .../react/src/generators/stories/schema.json | 13 +- .../generators/stories/stories.app.spec.ts | 43 +- .../generators/stories/stories.lib.spec.ts | 38 +- .../generators/stories/stories.nextjs.spec.ts | 15 +- .../react/src/generators/stories/stories.ts | 10 +- .../__snapshots__/configuration.spec.ts.snap | 93 ++++ .../configuration.spec.ts | 73 +-- .../storybook-configuration/configuration.ts | 7 +- .../storybook-configuration/schema.d.ts | 4 +- .../generators/configuration/configuration.ts | 2 +- 21 files changed, 846 insertions(+), 244 deletions(-) delete mode 100644 packages/react/src/generators/component-story/files/__componentFileName__.stories.__fileExt__ create mode 100644 packages/react/src/generators/component-story/files/jsx/__componentFileName__.stories.jsx__tmpl__ create mode 100644 packages/react/src/generators/component-story/files/tsx/__componentFileName__.stories.tsx__tmpl__ create mode 100644 packages/react/src/generators/stories/__snapshots__/stories.app.spec.ts.snap create mode 100644 packages/react/src/generators/stories/__snapshots__/stories.lib.spec.ts.snap create mode 100644 packages/react/src/generators/storybook-configuration/__snapshots__/configuration.spec.ts.snap diff --git a/docs/generated/packages/react/generators/component-story.json b/docs/generated/packages/react/generators/component-story.json index 1a959e4cac315..5122138cb60da 100644 --- a/docs/generated/packages/react/generators/component-story.json +++ b/docs/generated/packages/react/generators/component-story.json @@ -30,6 +30,12 @@ "type": "boolean", "default": false, "x-priority": "internal" + }, + "interactionTests": { + "type": "boolean", + "description": "Set up Storybook interaction tests.", + "default": true, + "x-priority": "important" } }, "required": ["project", "componentPath"], diff --git a/docs/generated/packages/react/generators/stories.json b/docs/generated/packages/react/generators/stories.json index 76138b57a15aa..af888ff74c229 100644 --- a/docs/generated/packages/react/generators/stories.json +++ b/docs/generated/packages/react/generators/stories.json @@ -20,12 +20,19 @@ "generateCypressSpecs": { "type": "boolean", "description": "Automatically generate `*.spec.ts` files in the cypress e2e app generated by the cypress-configure generator.", - "x-prompt": "Do you want to generate Cypress specs as well?", - "x-priority": "important" + "x-deprecated": "Please use Storybook interaction tests instead." }, "cypressProject": { "type": "string", - "description": "The Cypress project to generate the stories under. This is inferred from `project` by default." + "description": "The Cypress project to generate the stories under. This is inferred from `project` by default.", + "x-deprecated": "Please use Storybook interaction tests instead." + }, + "interactionTests": { + "type": "boolean", + "description": "Set up Storybook interaction tests.", + "x-prompt": "Do you want to set up Storybook interaction tests?", + "x-priority": "important", + "default": true }, "js": { "type": "boolean", diff --git a/packages/react/src/generators/component-story/__snapshots__/component-story.spec.ts.snap b/packages/react/src/generators/component-story/__snapshots__/component-story.spec.ts.snap index 8cf084cfe3722..ef8678b685a41 100644 --- a/packages/react/src/generators/component-story/__snapshots__/component-story.spec.ts.snap +++ b/packages/react/src/generators/component-story/__snapshots__/component-story.spec.ts.snap @@ -1,14 +1,18 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`react:component-story default setup Other types of component definitions Component files with DEFAULT export React component defined as: PureComponent class & then default export new JSX transform should properly setup the controls based on the component props 1`] = ` -"import type { Meta } from '@storybook/react'; +"import type { Meta, StoryObj } from '@storybook/react'; import { Test } from './test-ui-lib'; -const Story: Meta = { +import { within } from '@storybook/testing-library'; +import { expect } from '@storybook/jest'; + +const meta: Meta = { component: Test, title: 'Test', }; -export default Story; +export default meta; +type Story = StoryObj; export const Primary = { args: { @@ -16,18 +20,29 @@ export const Primary = { displayAge: false, }, }; + +export const Heading: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + expect(canvas.getByText(/Welcome to Test!/gi)).toBeTruthy(); + }, +}; " `; exports[`react:component-story default setup Other types of component definitions Component files with DEFAULT export React component defined as: PureComponent class & then default export should properly setup the controls based on the component props 1`] = ` -"import type { Meta } from '@storybook/react'; +"import type { Meta, StoryObj } from '@storybook/react'; import { Test } from './test-ui-lib'; -const Story: Meta = { +import { within } from '@storybook/testing-library'; +import { expect } from '@storybook/jest'; + +const meta: Meta = { component: Test, title: 'Test', }; -export default Story; +export default meta; +type Story = StoryObj; export const Primary = { args: { @@ -35,18 +50,29 @@ export const Primary = { displayAge: false, }, }; + +export const Heading: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + expect(canvas.getByText(/Welcome to Test!/gi)).toBeTruthy(); + }, +}; " `; exports[`react:component-story default setup Other types of component definitions Component files with DEFAULT export React component defined as: arrow function should properly setup the controls based on the component props 1`] = ` -"import type { Meta } from '@storybook/react'; +"import type { Meta, StoryObj } from '@storybook/react'; import { Test } from './test-ui-lib'; -const Story: Meta = { +import { within } from '@storybook/testing-library'; +import { expect } from '@storybook/jest'; + +const meta: Meta = { component: Test, title: 'Test', }; -export default Story; +export default meta; +type Story = StoryObj; export const Primary = { args: { @@ -54,18 +80,29 @@ export const Primary = { displayAge: false, }, }; + +export const Heading: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + expect(canvas.getByText(/Welcome to Test!/gi)).toBeTruthy(); + }, +}; " `; exports[`react:component-story default setup Other types of component definitions Component files with DEFAULT export React component defined as: arrow function without {..} should properly setup the controls based on the component props 1`] = ` -"import type { Meta } from '@storybook/react'; +"import type { Meta, StoryObj } from '@storybook/react'; import { Test } from './test-ui-lib'; -const Story: Meta = { +import { within } from '@storybook/testing-library'; +import { expect } from '@storybook/jest'; + +const meta: Meta = { component: Test, title: 'Test', }; -export default Story; +export default meta; +type Story = StoryObj; export const Primary = { args: { @@ -73,18 +110,29 @@ export const Primary = { displayAge: false, }, }; + +export const Heading: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + expect(canvas.getByText(/Welcome to Test!/gi)).toBeTruthy(); + }, +}; " `; exports[`react:component-story default setup Other types of component definitions Component files with DEFAULT export React component defined as: component class & then default export new JSX transform should properly setup the controls based on the component props 1`] = ` -"import type { Meta } from '@storybook/react'; +"import type { Meta, StoryObj } from '@storybook/react'; import { Test } from './test-ui-lib'; -const Story: Meta = { +import { within } from '@storybook/testing-library'; +import { expect } from '@storybook/jest'; + +const meta: Meta = { component: Test, title: 'Test', }; -export default Story; +export default meta; +type Story = StoryObj; export const Primary = { args: { @@ -92,18 +140,29 @@ export const Primary = { displayAge: false, }, }; + +export const Heading: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + expect(canvas.getByText(/Welcome to Test!/gi)).toBeTruthy(); + }, +}; " `; exports[`react:component-story default setup Other types of component definitions Component files with DEFAULT export React component defined as: component class & then default export should properly setup the controls based on the component props 1`] = ` -"import type { Meta } from '@storybook/react'; +"import type { Meta, StoryObj } from '@storybook/react'; import { Test } from './test-ui-lib'; -const Story: Meta = { +import { within } from '@storybook/testing-library'; +import { expect } from '@storybook/jest'; + +const meta: Meta = { component: Test, title: 'Test', }; -export default Story; +export default meta; +type Story = StoryObj; export const Primary = { args: { @@ -111,18 +170,29 @@ export const Primary = { displayAge: false, }, }; + +export const Heading: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + expect(canvas.getByText(/Welcome to Test!/gi)).toBeTruthy(); + }, +}; " `; exports[`react:component-story default setup Other types of component definitions Component files with DEFAULT export React component defined as: default export function should properly setup the controls based on the component props 1`] = ` -"import type { Meta } from '@storybook/react'; +"import type { Meta, StoryObj } from '@storybook/react'; import { Test } from './test-ui-lib'; -const Story: Meta = { +import { within } from '@storybook/testing-library'; +import { expect } from '@storybook/jest'; + +const meta: Meta = { component: Test, title: 'Test', }; -export default Story; +export default meta; +type Story = StoryObj; export const Primary = { args: { @@ -130,18 +200,29 @@ export const Primary = { displayAge: false, }, }; + +export const Heading: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + expect(canvas.getByText(/Welcome to Test!/gi)).toBeTruthy(); + }, +}; " `; exports[`react:component-story default setup Other types of component definitions Component files with DEFAULT export React component defined as: direct export of component class new JSX transform should properly setup the controls based on the component props 1`] = ` -"import type { Meta } from '@storybook/react'; +"import type { Meta, StoryObj } from '@storybook/react'; import { Test } from './test-ui-lib'; -const Story: Meta = { +import { within } from '@storybook/testing-library'; +import { expect } from '@storybook/jest'; + +const meta: Meta = { component: Test, title: 'Test', }; -export default Story; +export default meta; +type Story = StoryObj; export const Primary = { args: { @@ -149,18 +230,29 @@ export const Primary = { displayAge: false, }, }; + +export const Heading: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + expect(canvas.getByText(/Welcome to Test!/gi)).toBeTruthy(); + }, +}; " `; exports[`react:component-story default setup Other types of component definitions Component files with DEFAULT export React component defined as: direct export of component class should properly setup the controls based on the component props 1`] = ` -"import type { Meta } from '@storybook/react'; +"import type { Meta, StoryObj } from '@storybook/react'; import { Test } from './test-ui-lib'; -const Story: Meta = { +import { within } from '@storybook/testing-library'; +import { expect } from '@storybook/jest'; + +const meta: Meta = { component: Test, title: 'Test', }; -export default Story; +export default meta; +type Story = StoryObj; export const Primary = { args: { @@ -168,18 +260,29 @@ export const Primary = { displayAge: false, }, }; + +export const Heading: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + expect(canvas.getByText(/Welcome to Test!/gi)).toBeTruthy(); + }, +}; " `; exports[`react:component-story default setup Other types of component definitions Component files with DEFAULT export React component defined as: function and then export should properly setup the controls based on the component props 1`] = ` -"import type { Meta } from '@storybook/react'; +"import type { Meta, StoryObj } from '@storybook/react'; import { Test } from './test-ui-lib'; -const Story: Meta = { +import { within } from '@storybook/testing-library'; +import { expect } from '@storybook/jest'; + +const meta: Meta = { component: Test, title: 'Test', }; -export default Story; +export default meta; +type Story = StoryObj; export const Primary = { args: { @@ -187,18 +290,29 @@ export const Primary = { displayAge: false, }, }; + +export const Heading: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + expect(canvas.getByText(/Welcome to Test!/gi)).toBeTruthy(); + }, +}; " `; exports[`react:component-story default setup Other types of component definitions Component files with NO DEFAULT export React component defined as: no default PureComponent class & then default export new JSX transform should properly setup the controls based on the component props 1`] = ` -"import type { Meta } from '@storybook/react'; +"import type { Meta, StoryObj } from '@storybook/react'; import { Test } from './test-ui-lib'; -const Story: Meta = { +import { within } from '@storybook/testing-library'; +import { expect } from '@storybook/jest'; + +const meta: Meta = { component: Test, title: 'Test', }; -export default Story; +export default meta; +type Story = StoryObj; export const Primary = { args: { @@ -206,18 +320,29 @@ export const Primary = { displayAge: false, }, }; + +export const Heading: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + expect(canvas.getByText(/Welcome to Test!/gi)).toBeTruthy(); + }, +}; " `; exports[`react:component-story default setup Other types of component definitions Component files with NO DEFAULT export React component defined as: no default PureComponent class & then default export should properly setup the controls based on the component props 1`] = ` -"import type { Meta } from '@storybook/react'; +"import type { Meta, StoryObj } from '@storybook/react'; import { Test } from './test-ui-lib'; -const Story: Meta = { +import { within } from '@storybook/testing-library'; +import { expect } from '@storybook/jest'; + +const meta: Meta = { component: Test, title: 'Test', }; -export default Story; +export default meta; +type Story = StoryObj; export const Primary = { args: { @@ -225,18 +350,29 @@ export const Primary = { displayAge: false, }, }; + +export const Heading: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + expect(canvas.getByText(/Welcome to Test!/gi)).toBeTruthy(); + }, +}; " `; exports[`react:component-story default setup Other types of component definitions Component files with NO DEFAULT export React component defined as: no default arrow function should properly setup the controls based on the component props 1`] = ` -"import type { Meta } from '@storybook/react'; +"import type { Meta, StoryObj } from '@storybook/react'; import { Test } from './test-ui-lib'; -const Story: Meta = { +import { within } from '@storybook/testing-library'; +import { expect } from '@storybook/jest'; + +const meta: Meta = { component: Test, title: 'Test', }; -export default Story; +export default meta; +type Story = StoryObj; export const Primary = { args: { @@ -244,18 +380,29 @@ export const Primary = { displayAge: false, }, }; + +export const Heading: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + expect(canvas.getByText(/Welcome to Test!/gi)).toBeTruthy(); + }, +}; " `; exports[`react:component-story default setup Other types of component definitions Component files with NO DEFAULT export React component defined as: no default arrow function without {..} should properly setup the controls based on the component props 1`] = ` -"import type { Meta } from '@storybook/react'; +"import type { Meta, StoryObj } from '@storybook/react'; import { Test } from './test-ui-lib'; -const Story: Meta = { +import { within } from '@storybook/testing-library'; +import { expect } from '@storybook/jest'; + +const meta: Meta = { component: Test, title: 'Test', }; -export default Story; +export default meta; +type Story = StoryObj; export const Primary = { args: { @@ -263,18 +410,29 @@ export const Primary = { displayAge: false, }, }; + +export const Heading: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + expect(canvas.getByText(/Welcome to Test!/gi)).toBeTruthy(); + }, +}; " `; exports[`react:component-story default setup Other types of component definitions Component files with NO DEFAULT export React component defined as: no default component class should properly setup the controls based on the component props 1`] = ` -"import type { Meta } from '@storybook/react'; +"import type { Meta, StoryObj } from '@storybook/react'; import { Test } from './test-ui-lib'; -const Story: Meta = { +import { within } from '@storybook/testing-library'; +import { expect } from '@storybook/jest'; + +const meta: Meta = { component: Test, title: 'Test', }; -export default Story; +export default meta; +type Story = StoryObj; export const Primary = { args: { @@ -282,18 +440,29 @@ export const Primary = { displayAge: false, }, }; + +export const Heading: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + expect(canvas.getByText(/Welcome to Test!/gi)).toBeTruthy(); + }, +}; " `; exports[`react:component-story default setup Other types of component definitions Component files with NO DEFAULT export React component defined as: no default direct export of component class new JSX transform should properly setup the controls based on the component props 1`] = ` -"import type { Meta } from '@storybook/react'; +"import type { Meta, StoryObj } from '@storybook/react'; import { Test } from './test-ui-lib'; -const Story: Meta = { +import { within } from '@storybook/testing-library'; +import { expect } from '@storybook/jest'; + +const meta: Meta = { component: Test, title: 'Test', }; -export default Story; +export default meta; +type Story = StoryObj; export const Primary = { args: { @@ -301,18 +470,29 @@ export const Primary = { displayAge: false, }, }; + +export const Heading: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + expect(canvas.getByText(/Welcome to Test!/gi)).toBeTruthy(); + }, +}; " `; exports[`react:component-story default setup Other types of component definitions Component files with NO DEFAULT export React component defined as: no default direct export of component class should properly setup the controls based on the component props 1`] = ` -"import type { Meta } from '@storybook/react'; +"import type { Meta, StoryObj } from '@storybook/react'; import { Test } from './test-ui-lib'; -const Story: Meta = { +import { within } from '@storybook/testing-library'; +import { expect } from '@storybook/jest'; + +const meta: Meta = { component: Test, title: 'Test', }; -export default Story; +export default meta; +type Story = StoryObj; export const Primary = { args: { @@ -320,18 +500,29 @@ export const Primary = { displayAge: false, }, }; + +export const Heading: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + expect(canvas.getByText(/Welcome to Test!/gi)).toBeTruthy(); + }, +}; " `; exports[`react:component-story default setup Other types of component definitions Component files with NO DEFAULT export React component defined as: no default simple export function should properly setup the controls based on the component props 1`] = ` -"import type { Meta } from '@storybook/react'; +"import type { Meta, StoryObj } from '@storybook/react'; import { Test } from './test-ui-lib'; -const Story: Meta = { +import { within } from '@storybook/testing-library'; +import { expect } from '@storybook/jest'; + +const meta: Meta = { component: Test, title: 'Test', }; -export default Story; +export default meta; +type Story = StoryObj; export const Primary = { args: { @@ -339,71 +530,115 @@ export const Primary = { displayAge: false, }, }; + +export const Heading: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + expect(canvas.getByText(/Welcome to Test!/gi)).toBeTruthy(); + }, +}; " `; exports[`react:component-story default setup Other types of component definitions Component files with NO DEFAULT export should create stories for all components in a file with no default export 1`] = ` -"import type { Meta } from '@storybook/react'; +"import type { Meta, StoryObj } from '@storybook/react'; import { One } from './test-ui-lib'; -const Story: Meta = { +import { within } from '@storybook/testing-library'; +import { expect } from '@storybook/jest'; + +const meta: Meta = { component: One, title: 'One', }; -export default Story; +export default meta; +type Story = StoryObj; export const Primary = { args: {}, }; + +export const Heading: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + expect(canvas.getByText(/Welcome to One!/gi)).toBeTruthy(); + }, +}; " `; exports[`react:component-story default setup Other types of component definitions Component files with NO DEFAULT export should create stories for all components in a file with no default export 2`] = ` -"import type { Meta } from '@storybook/react'; +"import type { Meta, StoryObj } from '@storybook/react'; import { Two } from './test-ui-lib'; -const Story: Meta = { +import { within } from '@storybook/testing-library'; +import { expect } from '@storybook/jest'; + +const meta: Meta = { component: Two, title: 'Two', }; -export default Story; +export default meta; +type Story = StoryObj; export const Primary = { args: {}, }; + +export const Heading: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + expect(canvas.getByText(/Welcome to Two!/gi)).toBeTruthy(); + }, +}; " `; exports[`react:component-story default setup Other types of component definitions Component files with NO DEFAULT export should create stories for all components in a file with no default export 3`] = ` -"import type { Meta } from '@storybook/react'; +"import type { Meta, StoryObj } from '@storybook/react'; import { Three } from './test-ui-lib'; -const Story: Meta = { +import { within } from '@storybook/testing-library'; +import { expect } from '@storybook/jest'; + +const meta: Meta = { component: Three, title: 'Three', }; -export default Story; +export default meta; +type Story = StoryObj; export const Primary = { args: { name: '', }, }; + +export const Heading: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + expect(canvas.getByText(/Welcome to Three!/gi)).toBeTruthy(); + }, +}; " `; exports[`react:component-story default setup component with props and actions should setup controls based on the component props 1`] = ` -"import type { Meta } from '@storybook/react'; +"import type { Meta, StoryObj } from '@storybook/react'; import { Test } from './test-ui-lib'; -const Story: Meta = { +import { within } from '@storybook/testing-library'; +import { expect } from '@storybook/jest'; + +const meta: Meta = { component: Test, title: 'Test', argTypes: { someAction: { action: 'someAction executed!' }, }, }; -export default Story; +export default meta; +type Story = StoryObj; export const Primary = { args: { @@ -411,18 +646,29 @@ export const Primary = { displayAge: false, }, }; + +export const Heading: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + expect(canvas.getByText(/Welcome to Test!/gi)).toBeTruthy(); + }, +}; " `; exports[`react:component-story default setup component with props should setup controls based on the component props 1`] = ` -"import type { Meta } from '@storybook/react'; +"import type { Meta, StoryObj } from '@storybook/react'; import { Test } from './test-ui-lib'; -const Story: Meta = { +import { within } from '@storybook/testing-library'; +import { expect } from '@storybook/jest'; + +const meta: Meta = { component: Test, title: 'Test', }; -export default Story; +export default meta; +type Story = StoryObj; export const Primary = { args: { @@ -430,43 +676,75 @@ export const Primary = { displayAge: false, }, }; + +export const Heading: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + expect(canvas.getByText(/Welcome to Test!/gi)).toBeTruthy(); + }, +}; " `; exports[`react:component-story default setup component without any props defined should create a story without controls 1`] = ` -"import type { Meta } from '@storybook/react'; +"import type { Meta, StoryObj } from '@storybook/react'; import { Test } from './test-ui-lib'; -const Story: Meta = { +import { within } from '@storybook/testing-library'; +import { expect } from '@storybook/jest'; + +const meta: Meta = { component: Test, title: 'Test', }; -export default Story; +export default meta; +type Story = StoryObj; export const Primary = { args: {}, }; + +export const Heading: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + expect(canvas.getByText(/Welcome to Test!/gi)).toBeTruthy(); + }, +}; " `; exports[`react:component-story default setup default component setup should properly set up the story 1`] = ` -"import type { Meta } from '@storybook/react'; +"import type { Meta, StoryObj } from '@storybook/react'; import { TestUiLib } from './test-ui-lib'; -const Story: Meta = { +import { within } from '@storybook/testing-library'; +import { expect } from '@storybook/jest'; + +const meta: Meta = { component: TestUiLib, title: 'TestUiLib', }; -export default Story; +export default meta; +type Story = StoryObj; export const Primary = { args: {}, }; + +export const Heading: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + expect(canvas.getByText(/Welcome to TestUiLib!/gi)).toBeTruthy(); + }, +}; " `; exports[`react:component-story default setup when using plain JS components should properly set up the story 1`] = ` -"import Test from './test-ui-libplain'; +"import componentName from './test-ui-libplain'; + +import { within } from '@storybook/testing-library'; +import { expect } from '@storybook/jest'; export default { component: Test, @@ -476,18 +754,26 @@ export default { export const Primary = { args: {}, }; + +export const Heading: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + expect(canvas.getByText(/Welcome to Test!/gi)).toBeTruthy(); + }, +}; " `; -exports[`react:component-story using eslint should properly set up the story 1`] = ` -"import type { Meta } from '@storybook/react'; +exports[`react:component-story using eslint - not using interaction tests should properly set up the story 1`] = ` +"import type { Meta, StoryObj } from '@storybook/react'; import { TestUiLib } from './test-ui-lib'; -const Story: Meta = { +const meta: Meta = { component: TestUiLib, title: 'TestUiLib', }; -export default Story; +export default meta; +type Story = StoryObj; export const Primary = { args: {}, diff --git a/packages/react/src/generators/component-story/component-story.spec.ts b/packages/react/src/generators/component-story/component-story.spec.ts index 9a77bdd4dde4e..8c8f6e87ef35d 100644 --- a/packages/react/src/generators/component-story/component-story.spec.ts +++ b/packages/react/src/generators/component-story/component-story.spec.ts @@ -27,6 +27,7 @@ describe('react:component-story', () => { await componentStoryGenerator(appTree, { componentPath: 'lib/test-ui-lib.tsx', project: 'test-ui-lib', + interactionTests: true, }); } catch (e) { expect(e.message).toContain( @@ -506,12 +507,13 @@ describe('react:component-story', () => { }); }); - describe('using eslint', () => { + describe('using eslint - not using interaction tests', () => { beforeEach(async () => { appTree = await createTestUILib('test-ui-lib'); await componentStoryGenerator(appTree, { componentPath: 'lib/test-ui-lib.tsx', project: 'test-ui-lib', + interactionTests: false, }); }); diff --git a/packages/react/src/generators/component-story/component-story.ts b/packages/react/src/generators/component-story/component-story.ts index 6c1f494f96262..2507e1081120e 100644 --- a/packages/react/src/generators/component-story/component-story.ts +++ b/packages/react/src/generators/component-story/component-story.ts @@ -20,12 +20,13 @@ let tsModule: typeof import('typescript'); export interface CreateComponentStoriesFileSchema { project: string; componentPath: string; + interactionTests?: boolean; skipFormat?: boolean; } export function createComponentStoriesFile( host: Tree, - { project, componentPath }: CreateComponentStoriesFileSchema + { project, componentPath, interactionTests }: CreateComponentStoriesFileSchema ) { if (!tsModule) { tsModule = ensureTypescript(); @@ -42,12 +43,6 @@ export function createComponentStoriesFile( const isPlainJs = componentFilePath.endsWith('.jsx') || componentFilePath.endsWith('.js'); - let fileExt = 'tsx'; - if (componentFilePath.endsWith('.jsx')) { - fileExt = 'jsx'; - } else if (componentFilePath.endsWith('.js')) { - fileExt = 'js'; - } const componentFileName = componentFilePath .slice(componentFilePath.lastIndexOf('/') + 1) @@ -81,8 +76,8 @@ export function createComponentStoriesFile( declaration, componentDirectory, name, + interactionTests, isPlainJs, - fileExt, componentNodes.length > 1 ); }); @@ -98,8 +93,8 @@ export function createComponentStoriesFile( cmpDeclaration, componentDirectory, name, - isPlainJs, - fileExt + interactionTests, + isPlainJs ); } } @@ -110,8 +105,8 @@ export function findPropsAndGenerateFile( cmpDeclaration: ts.Node, componentDirectory: string, name: string, + interactionTests: boolean, isPlainJs: boolean, - fileExt: string, fromNodeArray?: boolean ) { const { propsTypeName, props, argTypes } = getDefaultsForComponent( @@ -121,9 +116,10 @@ export function findPropsAndGenerateFile( generateFiles( host, - joinPathFragments(__dirname, './files'), + joinPathFragments(__dirname, `./files${isPlainJs ? '/jsx' : '/tsx'}`), normalizePath(componentDirectory), { + tmpl: '', componentFileName: fromNodeArray ? `${name}--${(cmpDeclaration as any).name.text}` : name, @@ -132,8 +128,7 @@ export function findPropsAndGenerateFile( props, argTypes, componentName: (cmpDeclaration as any).name.text, - isPlainJs, - fileExt, + interactionTests, } ); } @@ -142,7 +137,10 @@ export async function componentStoryGenerator( host: Tree, schema: CreateComponentStoriesFileSchema ) { - createComponentStoriesFile(host, schema); + createComponentStoriesFile(host, { + ...schema, + interactionTests: schema.interactionTests ?? true, + }); if (!schema.skipFormat) { await formatFiles(host); diff --git a/packages/react/src/generators/component-story/files/__componentFileName__.stories.__fileExt__ b/packages/react/src/generators/component-story/files/__componentFileName__.stories.__fileExt__ deleted file mode 100644 index 12b9ccd9b1f5c..0000000000000 --- a/packages/react/src/generators/component-story/files/__componentFileName__.stories.__fileExt__ +++ /dev/null @@ -1,32 +0,0 @@ -<% if ( !isPlainJs ) { %>import type { Meta } from '@storybook/react';<% } %> -import<% if ( !isPlainJs ) { %> { <% } %> <%= componentName %> <% if ( !isPlainJs ) { %> } <% } %> from './<%= componentImportFileName %>'; - -<% if ( isPlainJs ) { %> -export default { - component: <%= componentName %>, - title: '<%= componentName %>',<% if ( argTypes && argTypes.length > 0 ) { %> - argTypes: {<% for (let argType of argTypes) { %> - <%= argType.name %>: { <%- argType.type %> : "<%- argType.actionText %>" },<% } %> -} - <% } %> -}; -<% } %> - - -<% if ( !isPlainJs ) { %> -const Story: Meta> = { - component: <%= componentName %>, - title: '<%= componentName %>',<% if ( argTypes && argTypes.length > 0 ) { %> - argTypes: {<% for (let argType of argTypes) { %> - <%= argType.name %>: { <%- argType.type %> : "<%- argType.actionText %>" },<% } %> -} - <% } %> -}; -export default Story; -<% } %> - -export const Primary = { - args: {<% for (let prop of props) { %> - <%= prop.name %>: <%- prop.defaultValue %>,<% } %> - }, -}; \ No newline at end of file diff --git a/packages/react/src/generators/component-story/files/jsx/__componentFileName__.stories.jsx__tmpl__ b/packages/react/src/generators/component-story/files/jsx/__componentFileName__.stories.jsx__tmpl__ new file mode 100644 index 0000000000000..5750a734eab0a --- /dev/null +++ b/packages/react/src/generators/component-story/files/jsx/__componentFileName__.stories.jsx__tmpl__ @@ -0,0 +1,29 @@ +import componentName from './<%= componentImportFileName %>'; +<% if ( interactionTests ) { %> +import { within } from '@storybook/testing-library'; +import { expect } from '@storybook/jest'; +<% } %> + +export default { + component: <%= componentName %>, + title: '<%= componentName %>',<% if ( argTypes && argTypes.length > 0 ) { %> + argTypes: {<% for (let argType of argTypes) { %> + <%= argType.name %>: { <%- argType.type %> : "<%- argType.actionText %>" },<% } %> +} + <% } %> +}; + +export const Primary = { + args: {<% for (let prop of props) { %> + <%= prop.name %>: <%- prop.defaultValue %>,<% } %> + }, +}; + +<% if ( interactionTests ) { %> +export const Heading: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + expect(canvas.getByText(/Welcome to <%=componentName%>!/gi)).toBeTruthy(); + }, +}; +<% } %> \ No newline at end of file diff --git a/packages/react/src/generators/component-story/files/tsx/__componentFileName__.stories.tsx__tmpl__ b/packages/react/src/generators/component-story/files/tsx/__componentFileName__.stories.tsx__tmpl__ new file mode 100644 index 0000000000000..257b72934ad3b --- /dev/null +++ b/packages/react/src/generators/component-story/files/tsx/__componentFileName__.stories.tsx__tmpl__ @@ -0,0 +1,33 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import { <%= componentName %> } from './<%= componentImportFileName %>'; +<% if ( interactionTests ) { %> +import { within } from '@storybook/testing-library'; +import { expect } from '@storybook/jest'; +<% } %> + +const meta: Meta> = { + component: <%= componentName %>, + title: '<%= componentName %>',<% if ( argTypes && argTypes.length > 0 ) { %> + argTypes: {<% for (let argType of argTypes) { %> + <%= argType.name %>: { <%- argType.type %> : "<%- argType.actionText %>" },<% } %> +} + <% } %> +}; +export default meta; +type Story = StoryObj>; + + +export const Primary = { + args: {<% for (let prop of props) { %> + <%= prop.name %>: <%- prop.defaultValue %>,<% } %> + }, +}; + +<% if ( interactionTests ) { %> +export const Heading: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + expect(canvas.getByText(/Welcome to <%=componentName%>!/gi)).toBeTruthy(); + }, +}; +<% } %> diff --git a/packages/react/src/generators/component-story/schema.json b/packages/react/src/generators/component-story/schema.json index df34160896a38..d7e48a93d92c4 100644 --- a/packages/react/src/generators/component-story/schema.json +++ b/packages/react/src/generators/component-story/schema.json @@ -30,6 +30,12 @@ "type": "boolean", "default": false, "x-priority": "internal" + }, + "interactionTests": { + "type": "boolean", + "description": "Set up Storybook interaction tests.", + "default": true, + "x-priority": "important" } }, "required": ["project", "componentPath"] diff --git a/packages/react/src/generators/stories/__snapshots__/stories.app.spec.ts.snap b/packages/react/src/generators/stories/__snapshots__/stories.app.spec.ts.snap new file mode 100644 index 0000000000000..9c6abe28dbe8a --- /dev/null +++ b/packages/react/src/generators/stories/__snapshots__/stories.app.spec.ts.snap @@ -0,0 +1,100 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react:stories for applications should create the stories with interaction tests 1`] = ` +"import type { Meta, StoryObj } from '@storybook/react'; +import { NxWelcome } from './nx-welcome'; + +import { within } from '@storybook/testing-library'; +import { expect } from '@storybook/jest'; + +const meta: Meta = { + component: NxWelcome, + title: 'NxWelcome', +}; +export default meta; +type Story = StoryObj; + +export const Primary = { + args: {}, +}; + +export const Heading: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + expect(canvas.getByText(/Welcome to NxWelcome!/gi)).toBeTruthy(); + }, +}; +" +`; + +exports[`react:stories for applications should create the stories with interaction tests 2`] = ` +"import type { Meta, StoryObj } from '@storybook/react'; +import { Test } from './another-cmp'; + +import { within } from '@storybook/testing-library'; +import { expect } from '@storybook/jest'; + +const meta: Meta = { + component: Test, + title: 'Test', +}; +export default meta; +type Story = StoryObj; + +export const Primary = { + args: { + name: '', + displayAge: false, + }, +}; + +export const Heading: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + expect(canvas.getByText(/Welcome to Test!/gi)).toBeTruthy(); + }, +}; +" +`; + +exports[`react:stories for applications should create the stories without interaction tests 1`] = ` +"import type { Meta, StoryObj } from '@storybook/react'; +import { NxWelcome } from './nx-welcome'; + +const meta: Meta = { + component: NxWelcome, + title: 'NxWelcome', +}; +export default meta; +type Story = StoryObj; + +export const Primary = { + args: {}, +}; +" +`; + +exports[`react:stories for applications should create the stories without interaction tests 2`] = ` +"import type { Meta, StoryObj } from '@storybook/react'; +import { Test } from './another-cmp'; + +const meta: Meta = { + component: Test, + title: 'Test', +}; +export default meta; +type Story = StoryObj; + +export const Primary = { + args: { + name: '', + displayAge: false, + }, +}; +" +`; + +exports[`react:stories for applications should not update existing stories 1`] = ` +"import { ComponentStory, ComponentMeta } from '@storybook/react'; +" +`; diff --git a/packages/react/src/generators/stories/__snapshots__/stories.lib.spec.ts.snap b/packages/react/src/generators/stories/__snapshots__/stories.lib.spec.ts.snap new file mode 100644 index 0000000000000..4b3b4afe27124 --- /dev/null +++ b/packages/react/src/generators/stories/__snapshots__/stories.lib.spec.ts.snap @@ -0,0 +1,95 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react:stories for libraries should create the stories with interaction tests 1`] = ` +"import type { Meta, StoryObj } from '@storybook/react'; +import { TestUiLib } from './test-ui-lib'; + +import { within } from '@storybook/testing-library'; +import { expect } from '@storybook/jest'; + +const meta: Meta = { + component: TestUiLib, + title: 'TestUiLib', +}; +export default meta; +type Story = StoryObj; + +export const Primary = { + args: {}, +}; + +export const Heading: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + expect(canvas.getByText(/Welcome to TestUiLib!/gi)).toBeTruthy(); + }, +}; +" +`; + +exports[`react:stories for libraries should create the stories with interaction tests 2`] = ` +"import type { Meta, StoryObj } from '@storybook/react'; +import { Test } from './another-cmp'; + +import { within } from '@storybook/testing-library'; +import { expect } from '@storybook/jest'; + +const meta: Meta = { + component: Test, + title: 'Test', +}; +export default meta; +type Story = StoryObj; + +export const Primary = { + args: { + name: '', + displayAge: false, + }, +}; + +export const Heading: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + expect(canvas.getByText(/Welcome to Test!/gi)).toBeTruthy(); + }, +}; +" +`; + +exports[`react:stories for libraries should create the stories without interaction tests 1`] = ` +"import type { Meta, StoryObj } from '@storybook/react'; +import { TestUiLib } from './test-ui-lib'; + +const meta: Meta = { + component: TestUiLib, + title: 'TestUiLib', +}; +export default meta; +type Story = StoryObj; + +export const Primary = { + args: {}, +}; +" +`; + +exports[`react:stories for libraries should create the stories without interaction tests 2`] = ` +"import type { Meta, StoryObj } from '@storybook/react'; +import { Test } from './another-cmp'; + +const meta: Meta = { + component: Test, + title: 'Test', +}; +export default meta; +type Story = StoryObj; + +export const Primary = { + args: { + name: '', + displayAge: false, + }, +}; +" +`; diff --git a/packages/react/src/generators/stories/schema.json b/packages/react/src/generators/stories/schema.json index 3fdd31177510f..10749a54c4d71 100644 --- a/packages/react/src/generators/stories/schema.json +++ b/packages/react/src/generators/stories/schema.json @@ -20,12 +20,19 @@ "generateCypressSpecs": { "type": "boolean", "description": "Automatically generate `*.spec.ts` files in the cypress e2e app generated by the cypress-configure generator.", - "x-prompt": "Do you want to generate Cypress specs as well?", - "x-priority": "important" + "x-deprecated": "Please use Storybook interaction tests instead." }, "cypressProject": { "type": "string", - "description": "The Cypress project to generate the stories under. This is inferred from `project` by default." + "description": "The Cypress project to generate the stories under. This is inferred from `project` by default.", + "x-deprecated": "Please use Storybook interaction tests instead." + }, + "interactionTests": { + "type": "boolean", + "description": "Set up Storybook interaction tests.", + "x-prompt": "Do you want to set up Storybook interaction tests?", + "x-priority": "important", + "default": true }, "js": { "type": "boolean", diff --git a/packages/react/src/generators/stories/stories.app.spec.ts b/packages/react/src/generators/stories/stories.app.spec.ts index 4f581029ffc37..762c95f8453bb 100644 --- a/packages/react/src/generators/stories/stories.app.spec.ts +++ b/packages/react/src/generators/stories/stories.app.spec.ts @@ -41,36 +41,37 @@ describe('react:stories for applications', () => { ); }); - it('should create the stories', async () => { + it('should create the stories with interaction tests', async () => { await storiesGenerator(appTree, { project: 'test-ui-app', - generateCypressSpecs: false, }); expect( - appTree.exists('apps/test-ui-app/src/app/nx-welcome.stories.tsx') - ).toBeTruthy(); + appTree.read('apps/test-ui-app/src/app/nx-welcome.stories.tsx', 'utf-8') + ).toMatchSnapshot(); expect( - appTree.exists( - 'apps/test-ui-app/src/app/anothercmp/another-cmp.stories.tsx' + appTree.read( + 'apps/test-ui-app/src/app/anothercmp/another-cmp.stories.tsx', + 'utf-8' ) - ).toBeTruthy(); + ).toMatchSnapshot(); }); - it('should generate Cypress specs', async () => { + it('should create the stories without interaction tests', async () => { await storiesGenerator(appTree, { project: 'test-ui-app', - generateCypressSpecs: true, + interactionTests: false, }); expect( - appTree.exists('apps/test-ui-app-e2e/src/e2e/app.cy.ts') - ).toBeTruthy(); + appTree.read('apps/test-ui-app/src/app/nx-welcome.stories.tsx', 'utf-8') + ).toMatchSnapshot(); expect( - appTree.exists( - 'apps/test-ui-app-e2e/src/e2e/another-cmp/another-cmp.cy.ts' + appTree.read( + 'apps/test-ui-app/src/app/anothercmp/another-cmp.stories.tsx', + 'utf-8' ) - ).toBeTruthy(); + ).toMatchSnapshot(); }); it('should ignore files that do not contain components', async () => { @@ -82,7 +83,6 @@ describe('react:stories for applications', () => { await storiesGenerator(appTree, { project: 'test-ui-app', - generateCypressSpecs: false, }); // should just create the story and not error, even though there's a js file @@ -93,24 +93,18 @@ describe('react:stories for applications', () => { }); it('should not update existing stories', async () => { - // ARRANGE appTree.write( 'apps/test-ui-app/src/app/nx-welcome.stories.tsx', `import { ComponentStory, ComponentMeta } from '@storybook/react'` ); - // ACT await storiesGenerator(appTree, { project: 'test-ui-app', - generateCypressSpecs: false, }); - // ASSERT expect( appTree.read('apps/test-ui-app/src/app/nx-welcome.stories.tsx', 'utf-8') - ).toEqual( - `import { ComponentStory, ComponentMeta } from '@storybook/react';\n` - ); + ).toMatchSnapshot(); }); describe('ignore paths', () => { @@ -164,7 +158,6 @@ describe('react:stories for applications', () => { it('should generate stories for all if no ignorePaths', async () => { await storiesGenerator(appTree, { project: 'test-ui-app', - generateCypressSpecs: false, }); expect( @@ -192,7 +185,6 @@ describe('react:stories for applications', () => { it('should ignore entire paths', async () => { await storiesGenerator(appTree, { project: 'test-ui-app', - generateCypressSpecs: false, ignorePaths: [ `apps/test-ui-app/src/app/anothercmp/**`, `**/**/src/**/test-path/ignore-it/**`, @@ -224,7 +216,6 @@ describe('react:stories for applications', () => { it('should ignore path or a pattern', async () => { await storiesGenerator(appTree, { project: 'test-ui-app', - generateCypressSpecs: false, ignorePaths: [ 'apps/test-ui-app/src/app/anothercmp/**/*.skip.*', '**/**/src/**/test-path/**', @@ -256,7 +247,6 @@ describe('react:stories for applications', () => { it('should ignore direct path to component', async () => { await storiesGenerator(appTree, { project: 'test-ui-app', - generateCypressSpecs: false, ignorePaths: ['apps/test-ui-app/src/app/anothercmp/**/*.skip.tsx'], }); @@ -308,7 +298,6 @@ describe('react:stories for applications', () => { await storiesGenerator(appTree, { project: 'test-ui-app', - generateCypressSpecs: false, ignorePaths: [ 'apps/test-ui-app/src/app/anothercmp/another-cmp-test.skip.tsx', ], diff --git a/packages/react/src/generators/stories/stories.lib.spec.ts b/packages/react/src/generators/stories/stories.lib.spec.ts index 93eb95768d887..009e63d7a2c29 100644 --- a/packages/react/src/generators/stories/stories.lib.spec.ts +++ b/packages/react/src/generators/stories/stories.lib.spec.ts @@ -36,42 +36,38 @@ describe('react:stories for libraries', () => { ); }); - it('should create the stories', async () => { + it('should create the stories with interaction tests', async () => { await storiesGenerator(appTree, { project: 'test-ui-lib', - generateCypressSpecs: false, }); expect( - appTree.exists('libs/test-ui-lib/src/lib/test-ui-lib.stories.tsx') - ).toBeTruthy(); + appTree.read('libs/test-ui-lib/src/lib/test-ui-lib.stories.tsx', 'utf-8') + ).toMatchSnapshot(); expect( - appTree.exists( - 'libs/test-ui-lib/src/lib/anothercmp/another-cmp.stories.tsx' + appTree.read( + 'libs/test-ui-lib/src/lib/anothercmp/another-cmp.stories.tsx', + 'utf-8' ) - ).toBeTruthy(); + ).toMatchSnapshot(); }); - it('should generate Cypress specs', async () => { + it('should create the stories without interaction tests', async () => { await storiesGenerator(appTree, { project: 'test-ui-lib', - generateCypressSpecs: true, + interactionTests: false, }); - expect( - appTree.exists( - 'apps/test-ui-lib-e2e/src/integration/test-ui-lib/test-ui-lib.spec.ts' - ) - ).toBeTruthy(); + appTree.read('libs/test-ui-lib/src/lib/test-ui-lib.stories.tsx', 'utf-8') + ).toMatchSnapshot(); expect( - appTree.exists( - 'apps/test-ui-lib-e2e/src/integration/another-cmp/another-cmp.spec.ts' + appTree.read( + 'libs/test-ui-lib/src/lib/anothercmp/another-cmp.stories.tsx', + 'utf-8' ) - ).toBeTruthy(); + ).toMatchSnapshot(); }); - it('should not overwrite existing stories', () => {}); - describe('ignore paths', () => { beforeEach(() => { appTree.write( @@ -119,7 +115,6 @@ describe('react:stories for libraries', () => { it('should generate stories for all if no ignorePaths', async () => { await storiesGenerator(appTree, { project: 'test-ui-lib', - generateCypressSpecs: false, }); expect( @@ -144,7 +139,6 @@ describe('react:stories for libraries', () => { it('should ignore entire paths', async () => { await storiesGenerator(appTree, { project: 'test-ui-lib', - generateCypressSpecs: false, ignorePaths: [ 'libs/test-ui-lib/src/lib/anothercmp/**', '**/**/src/**/test-path/ignore-it/**', @@ -173,7 +167,6 @@ describe('react:stories for libraries', () => { it('should ignore path or a pattern', async () => { await storiesGenerator(appTree, { project: 'test-ui-lib', - generateCypressSpecs: false, ignorePaths: [ 'libs/test-ui-lib/src/lib/anothercmp/**/*.skip.*', '**/test-ui-lib/src/**/test-path/**', @@ -209,7 +202,6 @@ describe('react:stories for libraries', () => { await storiesGenerator(appTree, { project: 'test-ui-lib', - generateCypressSpecs: false, }); // should just create the story and not error, even though there's a js file diff --git a/packages/react/src/generators/stories/stories.nextjs.spec.ts b/packages/react/src/generators/stories/stories.nextjs.spec.ts index 39e95f889da37..aac9b1b96a8a4 100644 --- a/packages/react/src/generators/stories/stories.nextjs.spec.ts +++ b/packages/react/src/generators/stories/stories.nextjs.spec.ts @@ -32,10 +32,20 @@ describe('nextjs:stories for applications', () => { ); }); - it('should create the stories', async () => { + it('should create the stories with interaction tests', async () => { await storiesGenerator(tree, { project: 'test-ui-app', - generateCypressSpecs: false, + }); + + expect( + tree.exists('apps/test-ui-app/components/test.stories.tsx') + ).toBeTruthy(); + }); + + it('should create the stories without interaction tests', async () => { + await storiesGenerator(tree, { + project: 'test-ui-app', + interactionTests: false, }); expect( @@ -46,7 +56,6 @@ describe('nextjs:stories for applications', () => { it('should ignore paths', async () => { await storiesGenerator(tree, { project: 'test-ui-app', - generateCypressSpecs: false, ignorePaths: ['apps/test-ui-app/components/**'], }); diff --git a/packages/react/src/generators/stories/stories.ts b/packages/react/src/generators/stories/stories.ts index 30afa8be0d42b..15be2f4256259 100644 --- a/packages/react/src/generators/stories/stories.ts +++ b/packages/react/src/generators/stories/stories.ts @@ -22,9 +22,10 @@ let tsModule: typeof import('typescript'); export interface StorybookStoriesSchema { project: string; - generateCypressSpecs: boolean; + interactionTests?: boolean; js?: boolean; cypressProject?: string; + generateCypressSpecs?: boolean; ignorePaths?: string[]; skipFormat?: boolean; } @@ -84,8 +85,9 @@ export function containsComponentDeclaration( export async function createAllStories( tree: Tree, projectName: string, - generateCypressSpecs: boolean, + interactionTests: boolean, js: boolean, + generateCypressSpecs?: boolean, cypressProject?: string, ignorePaths?: string[] ) { @@ -142,6 +144,7 @@ export async function createAllStories( componentPath: relativeCmpDir, project: projectName, skipFormat: true, + interactionTests, }); if (generateCypressSpecs && e2eProject) { @@ -164,8 +167,9 @@ export async function storiesGenerator( await createAllStories( host, schema.project, - schema.generateCypressSpecs, + schema.interactionTests ?? true, schema.js, + schema.generateCypressSpecs, schema.cypressProject, schema.ignorePaths ); diff --git a/packages/react/src/generators/storybook-configuration/__snapshots__/configuration.spec.ts.snap b/packages/react/src/generators/storybook-configuration/__snapshots__/configuration.spec.ts.snap new file mode 100644 index 0000000000000..54b8e3f57a168 --- /dev/null +++ b/packages/react/src/generators/storybook-configuration/__snapshots__/configuration.spec.ts.snap @@ -0,0 +1,93 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`react:storybook-configuration should configure everything at once 1`] = ` +"import type { StorybookConfig } from '@storybook/react-vite'; + +const config: StorybookConfig = { + stories: ['../src/lib/**/*.stories.@(js|jsx|ts|tsx|mdx)'], + addons: ['@storybook/addon-essentials', '@storybook/addon-interactions'], + framework: { + name: '@storybook/react-vite', + options: { + builder: { + viteConfigPath: '', + }, + }, + }, +}; + +export default config; + +// To customize your Vite configuration you can use the viteFinal field. +// Check https://storybook.js.org/docs/react/builders/vite#configuration +// and https://nx.dev/packages/storybook/documents/custom-builder-configs +" +`; + +exports[`react:storybook-configuration should generate stories for components 1`] = ` +"import type { Meta, StoryObj } from '@storybook/react'; +import { MyComponent } from './my-component'; + +import { within } from '@storybook/testing-library'; +import { expect } from '@storybook/jest'; + +const meta: Meta = { + component: MyComponent, + title: 'MyComponent', +}; +export default meta; +type Story = StoryObj; + +export const Primary = { + args: {}, +}; + +export const Heading: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + expect(canvas.getByText(/Welcome to MyComponent!/gi)).toBeTruthy(); + }, +}; +" +`; + +exports[`react:storybook-configuration should generate stories for components without interaction tests 1`] = ` +"import type { Meta, StoryObj } from '@storybook/react'; +import { MyComponent } from './my-component'; + +const meta: Meta = { + component: MyComponent, + title: 'MyComponent', +}; +export default meta; +type Story = StoryObj; + +export const Primary = { + args: {}, +}; +" +`; + +exports[`react:storybook-configuration should generate stories for components written in plain JS 1`] = ` +"import componentName from './test-ui-libplain'; + +import { within } from '@storybook/testing-library'; +import { expect } from '@storybook/jest'; + +export default { + component: Test, + title: 'Test', +}; + +export const Primary = { + args: {}, +}; + +export const Heading: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + expect(canvas.getByText(/Welcome to Test!/gi)).toBeTruthy(); + }, +}; +" +`; diff --git a/packages/react/src/generators/storybook-configuration/configuration.spec.ts b/packages/react/src/generators/storybook-configuration/configuration.spec.ts index 78b4b435b6330..5c8917d3664b8 100644 --- a/packages/react/src/generators/storybook-configuration/configuration.spec.ts +++ b/packages/react/src/generators/storybook-configuration/configuration.spec.ts @@ -1,3 +1,4 @@ +// TODO(katerina): remove Cypress for Nx 18 import { installedCypressVersion } from '@nx/cypress/src/utils/cypress-version'; import { logger, Tree } from '@nx/devkit'; import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; @@ -37,15 +38,13 @@ describe('react:storybook-configuration', () => { appTree = await createTestUILib('test-ui-lib'); await storybookConfigurationGenerator(appTree, { name: 'test-ui-lib', - configureCypress: true, }); - expect(appTree.exists('libs/test-ui-lib/.storybook/main.js')).toBeTruthy(); expect( - appTree.exists('libs/test-ui-lib/tsconfig.storybook.json') - ).toBeTruthy(); + appTree.read('libs/test-ui-lib/.storybook/main.ts', 'utf-8') + ).toMatchSnapshot(); expect( - appTree.exists('apps/test-ui-lib-e2e/cypress.config.ts') + appTree.exists('libs/test-ui-lib/tsconfig.storybook.json') ).toBeTruthy(); }); @@ -54,7 +53,6 @@ describe('react:storybook-configuration', () => { await storybookConfigurationGenerator(appTree, { name: 'test-ui-lib', generateStories: true, - configureCypress: false, }); expect( @@ -84,37 +82,28 @@ describe('react:storybook-configuration', () => { ); await storybookConfigurationGenerator(appTree, { name: 'test-ui-lib', - generateCypressSpecs: true, generateStories: true, - configureCypress: false, js: true, }); expect( - appTree.exists('libs/test-ui-lib/src/lib/test-ui-libplain.stories.js') - ).toBeTruthy(); + appTree.read( + 'libs/test-ui-lib/src/lib/test-ui-libplain.stories.jsx', + 'utf-8' + ) + ).toMatchSnapshot(); }); it('should configure everything at once', async () => { appTree = await createTestAppLib('test-ui-app'); await storybookConfigurationGenerator(appTree, { name: 'test-ui-app', - configureCypress: true, }); - expect(appTree.exists('apps/test-ui-app/.storybook/main.js')).toBeTruthy(); + expect(appTree.exists('apps/test-ui-app/.storybook/main.ts')).toBeTruthy(); expect( appTree.exists('apps/test-ui-app/tsconfig.storybook.json') ).toBeTruthy(); - - /** - * Note on the removal of - * expect(tree.exists('apps/test-ui-app-e2e/cypress.json')).toBeTruthy(); - * - * When calling createTestAppLib() we do not generate an e2e suite. - * The storybook schematic for apps does not generate e2e test. - * So, there exists no test-ui-app-e2e! - */ }); it('should generate stories for components', async () => { @@ -122,45 +111,33 @@ describe('react:storybook-configuration', () => { await storybookConfigurationGenerator(appTree, { name: 'test-ui-app', generateStories: true, - configureCypress: false, }); // Currently the auto-generate stories feature only picks up components under the 'lib' directory. // In our 'createTestAppLib' function, we call @nx/react:component to generate a component // under the specified 'lib' directory expect( - appTree.exists( - 'apps/test-ui-app/src/app/my-component/my-component.stories.tsx' + appTree.read( + 'apps/test-ui-app/src/app/my-component/my-component.stories.tsx', + 'utf-8' ) - ).toBeTruthy(); + ).toMatchSnapshot(); }); - it('should generate cypress tests in the correct folder', async () => { - appTree = await createTestUILib('test-ui-lib'); - await componentGenerator(appTree, { - name: 'my-component', - project: 'test-ui-lib', - style: 'css', - }); + it('should generate stories for components without interaction tests', async () => { + appTree = await createTestAppLib('test-ui-app'); await storybookConfigurationGenerator(appTree, { - name: 'test-ui-lib', + name: 'test-ui-app', generateStories: true, - configureCypress: true, - generateCypressSpecs: true, - cypressDirectory: 'one/two', - }); - [ - 'apps/one/two/test-ui-lib-e2e/cypress.config.ts', - 'apps/one/two/test-ui-lib-e2e/src/fixtures/example.json', - 'apps/one/two/test-ui-lib-e2e/src/support/commands.ts', - 'apps/one/two/test-ui-lib-e2e/src/support/e2e.ts', - 'apps/one/two/test-ui-lib-e2e/tsconfig.json', - 'apps/one/two/test-ui-lib-e2e/.eslintrc.json', - 'apps/one/two/test-ui-lib-e2e/src/e2e/test-ui-lib/test-ui-lib.cy.ts', - 'apps/one/two/test-ui-lib-e2e/src/e2e/my-component/my-component.cy.ts', - ].forEach((file) => { - expect(appTree.exists(file)).toBeTruthy(); + interactionTests: false, }); + + expect( + appTree.read( + 'apps/test-ui-app/src/app/my-component/my-component.stories.tsx', + 'utf-8' + ) + ).toMatchSnapshot(); }); }); diff --git a/packages/react/src/generators/storybook-configuration/configuration.ts b/packages/react/src/generators/storybook-configuration/configuration.ts index 16d9f81d33aa9..1469fe73b8983 100644 --- a/packages/react/src/generators/storybook-configuration/configuration.ts +++ b/packages/react/src/generators/storybook-configuration/configuration.ts @@ -10,7 +10,7 @@ import { import { nxVersion } from '../../utils/versions'; async function generateStories(host: Tree, schema: StorybookConfigureSchema) { - // TODO(katerina): Remove cypress stuff for Nx 17? + // TODO(katerina): remove Cypress for Nx 18 ensurePackage('@nx/cypress', nxVersion); const { getE2eProjectName } = await import( '@nx/cypress/src/utils/project-name' @@ -29,6 +29,7 @@ async function generateStories(host: Tree, schema: StorybookConfigureSchema) { cypressProject, ignorePaths: schema.ignorePaths, skipFormat: true, + interactionTests: schema.interactionTests ?? true, }); } @@ -57,8 +58,8 @@ export async function storybookConfigurationGenerator( js: schema.js, linter: schema.linter, cypressDirectory: schema.cypressDirectory, - tsConfiguration: schema.tsConfiguration, - interactionTests: schema.interactionTests, + tsConfiguration: schema.tsConfiguration ?? true, // default is true + interactionTests: schema.interactionTests ?? true, // default is true configureStaticServe: schema.configureStaticServe, uiFramework: bundler === 'vite' diff --git a/packages/react/src/generators/storybook-configuration/schema.d.ts b/packages/react/src/generators/storybook-configuration/schema.d.ts index 0094e3b656097..80aabb79f7ff7 100644 --- a/packages/react/src/generators/storybook-configuration/schema.d.ts +++ b/packages/react/src/generators/storybook-configuration/schema.d.ts @@ -2,14 +2,14 @@ import { Linter } from '@nx/linter'; export interface StorybookConfigureSchema { name: string; - configureCypress: boolean; + interactionTests?: boolean; generateStories?: boolean; + configureCypress?: boolean; generateCypressSpecs?: boolean; js?: boolean; tsConfiguration?: boolean; linter?: Linter; cypressDirectory?: string; ignorePaths?: string[]; - interactionTests?: boolean; configureStaticServe?: boolean; } diff --git a/packages/storybook/src/generators/configuration/configuration.ts b/packages/storybook/src/generators/configuration/configuration.ts index 0365434575086..3afadb47c69ee 100644 --- a/packages/storybook/src/generators/configuration/configuration.ts +++ b/packages/storybook/src/generators/configuration/configuration.ts @@ -150,7 +150,7 @@ export async function configurationGenerator( addStaticTarget(tree, schema); } - // TODO(katerina): remove this feature in 17? + // TODO(katerina): remove Cypress for Nx 18 if (schema.configureCypress) { const e2eProject = await getE2EProjectName(tree, schema.name); if (!e2eProject) { From e545db7da96fb0c1174f0e736e5439a831bb07a5 Mon Sep 17 00:00:00 2001 From: Katerina Skroumpelou Date: Thu, 13 Jul 2023 13:19:24 +0300 Subject: [PATCH 064/262] fix(storybook): change storybook tsconfig path in eslint file too (#18101) --- .../configuration/lib/util-functions.ts | 34 +++++++++++++------ 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/packages/storybook/src/generators/configuration/lib/util-functions.ts b/packages/storybook/src/generators/configuration/lib/util-functions.ts index 550d5ae485fd1..1ba51389ff470 100644 --- a/packages/storybook/src/generators/configuration/lib/util-functions.ts +++ b/packages/storybook/src/generators/configuration/lib/util-functions.ts @@ -721,17 +721,29 @@ export function renameAndMoveOldTsConfig( const projectTsConfig = joinPathFragments(projectRoot, 'tsconfig.json'); - if (!tree.exists(projectTsConfig)) { - return; + if (tree.exists(projectTsConfig)) { + updateJson(tree, projectTsConfig, (json) => { + for (let i = 0; i < json.references?.length; i++) { + if (json.references[i].path === './.storybook/tsconfig.json') { + json.references[i].path = './tsconfig.storybook.json'; + break; + } + } + return json; + }); } - updateJson(tree, projectTsConfig, (json) => { - for (let i = 0; i < json.references?.length; i++) { - if (json.references[i].path === './.storybook/tsconfig.json') { - json.references[i].path = './tsconfig.storybook.json'; - break; - } - } - return json; - }); + const projectEsLintFile = joinPathFragments(projectRoot, '.eslintrc.json'); + + if (tree.exists(projectEsLintFile)) { + updateJson(tree, projectEsLintFile, (json) => { + const jsonString = JSON.stringify(json); + const newJsonString = jsonString.replace( + /\.storybook\/tsconfig\.json/g, + 'tsconfig.storybook.json' + ); + json = JSON.parse(newJsonString); + return json; + }); + } } From c3d31711b71d648cedeff688fce9334d393b586b Mon Sep 17 00:00:00 2001 From: FrozenPandaz Date: Thu, 13 Jul 2023 09:54:25 -0400 Subject: [PATCH 065/262] chore(misc): publish 16.6.0-beta.2 --- lerna.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lerna.json b/lerna.json index c96893f808c41..74dbcdc0b8ff9 100644 --- a/lerna.json +++ b/lerna.json @@ -1,6 +1,6 @@ { "packages": ["build/packages/*", "build/packages/nx/native-packages/*"], - "version": "16.6.0-beta.1", + "version": "16.6.0-beta.2", "granularPathspec": false, "command": { "publish": { From e657de8583ba954f697ed8e9376bb6015e111600 Mon Sep 17 00:00:00 2001 From: Juri Strumpflohner Date: Thu, 13 Jul 2023 16:06:37 +0200 Subject: [PATCH 066/262] docs(core): improve formatting & visibility for daemon disabling options (#18105) --- docs/shared/daemon.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/shared/daemon.md b/docs/shared/daemon.md index 6a348395c8fbe..6bea760737dda 100644 --- a/docs/shared/daemon.md +++ b/docs/shared/daemon.md @@ -29,7 +29,10 @@ If you ever need to manually shut down the Nx Daemon, you can run `nx reset` wit ## Turning it Off -As of v13.6.0, the Nx Daemon is enabled by default when running on your local machine. If you want to turn it off, simply set `useDaemonProcess: false` in the runners options in nx.json. You can also set the `NX_DAEMON` env variable to `false`. +As of v13.6.0, the Nx Daemon is enabled by default when running on your local machine. If you want to turn it off + +- simply set `useDaemonProcess: false` in the runners options in `nx.json` or +- set the `NX_DAEMON` env variable to `false`. When using Nx in a CI environment, the Nx Daemon is disabled by default. Whether the process runs is determined by the following function: [https://github.com/nrwl/nx/blob/master/packages/nx/src/utils/is-ci.ts](https://github.com/nrwl/nx/blob/master/packages/nx/src/utils/is-ci.ts) From 6ccbbbc98f8c2802e8581a1bd418e8f890bc947f Mon Sep 17 00:00:00 2001 From: Katerina Skroumpelou Date: Thu, 13 Jul 2023 17:30:01 +0300 Subject: [PATCH 067/262] feat(nx-dev): new page for ai docs (#18025) --- nx-dev/data-access-ai/.eslintrc.json | 18 + nx-dev/data-access-ai/README.md | 11 + nx-dev/data-access-ai/jest.config.ts | 11 + nx-dev/data-access-ai/package.json | 5 + nx-dev/data-access-ai/project.json | 40 ++ nx-dev/data-access-ai/src/index.ts | 2 + .../data-access-ai/src/lib/data-access-ai.ts | 192 ++++++++ nx-dev/data-access-ai/src/lib/utils.ts | 50 +++ nx-dev/data-access-ai/tsconfig.json | 24 + nx-dev/data-access-ai/tsconfig.lib.json | 10 + nx-dev/data-access-ai/tsconfig.spec.json | 14 + nx-dev/feature-ai/.babelrc | 12 + nx-dev/feature-ai/.eslintrc.json | 18 + nx-dev/feature-ai/README.md | 7 + nx-dev/feature-ai/jest.config.ts | 10 + nx-dev/feature-ai/project.json | 11 + nx-dev/feature-ai/src/index.ts | 3 + nx-dev/feature-ai/src/lib/feature-ai.tsx | 120 +++++ nx-dev/feature-ai/tsconfig.json | 23 + nx-dev/feature-ai/tsconfig.lib.json | 20 + nx-dev/feature-ai/tsconfig.spec.json | 20 + .../src/lib/google-analytics.ts | 4 +- nx-dev/nx-dev/next-sitemap.config.js | 1 + nx-dev/nx-dev/pages/ai/index.tsx | 32 ++ package.json | 7 +- pnpm-lock.yaml | 424 ++++++++++++++---- tsconfig.base.json | 4 + 27 files changed, 1001 insertions(+), 92 deletions(-) create mode 100644 nx-dev/data-access-ai/.eslintrc.json create mode 100644 nx-dev/data-access-ai/README.md create mode 100644 nx-dev/data-access-ai/jest.config.ts create mode 100644 nx-dev/data-access-ai/package.json create mode 100644 nx-dev/data-access-ai/project.json create mode 100644 nx-dev/data-access-ai/src/index.ts create mode 100644 nx-dev/data-access-ai/src/lib/data-access-ai.ts create mode 100644 nx-dev/data-access-ai/src/lib/utils.ts create mode 100644 nx-dev/data-access-ai/tsconfig.json create mode 100644 nx-dev/data-access-ai/tsconfig.lib.json create mode 100644 nx-dev/data-access-ai/tsconfig.spec.json create mode 100644 nx-dev/feature-ai/.babelrc create mode 100644 nx-dev/feature-ai/.eslintrc.json create mode 100644 nx-dev/feature-ai/README.md create mode 100644 nx-dev/feature-ai/jest.config.ts create mode 100644 nx-dev/feature-ai/project.json create mode 100644 nx-dev/feature-ai/src/index.ts create mode 100644 nx-dev/feature-ai/src/lib/feature-ai.tsx create mode 100644 nx-dev/feature-ai/tsconfig.json create mode 100644 nx-dev/feature-ai/tsconfig.lib.json create mode 100644 nx-dev/feature-ai/tsconfig.spec.json create mode 100644 nx-dev/nx-dev/pages/ai/index.tsx diff --git a/nx-dev/data-access-ai/.eslintrc.json b/nx-dev/data-access-ai/.eslintrc.json new file mode 100644 index 0000000000000..9d9c0db55bb1e --- /dev/null +++ b/nx-dev/data-access-ai/.eslintrc.json @@ -0,0 +1,18 @@ +{ + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], + "rules": {} + }, + { + "files": ["*.ts", "*.tsx"], + "rules": {} + }, + { + "files": ["*.js", "*.jsx"], + "rules": {} + } + ] +} diff --git a/nx-dev/data-access-ai/README.md b/nx-dev/data-access-ai/README.md new file mode 100644 index 0000000000000..bbd268a800a01 --- /dev/null +++ b/nx-dev/data-access-ai/README.md @@ -0,0 +1,11 @@ +# nx-dev-data-access-ai + +This library was generated with [Nx](https://nx.dev). + +## Building + +Run `nx build nx-dev-data-access-ai` to build the library. + +## Running unit tests + +Run `nx test nx-dev-data-access-ai` to execute the unit tests via [Jest](https://jestjs.io). diff --git a/nx-dev/data-access-ai/jest.config.ts b/nx-dev/data-access-ai/jest.config.ts new file mode 100644 index 0000000000000..1a4f1efd3bc64 --- /dev/null +++ b/nx-dev/data-access-ai/jest.config.ts @@ -0,0 +1,11 @@ +/* eslint-disable */ +export default { + displayName: 'nx-dev-data-access-ai', + preset: '../../jest.preset.js', + testEnvironment: 'node', + transform: { + '^.+\\.[tj]s$': ['ts-jest', { tsconfig: '/tsconfig.spec.json' }], + }, + moduleFileExtensions: ['ts', 'js', 'html'], + coverageDirectory: '../../coverage/nx-dev/data-access-ai', +}; diff --git a/nx-dev/data-access-ai/package.json b/nx-dev/data-access-ai/package.json new file mode 100644 index 0000000000000..4952715963dbb --- /dev/null +++ b/nx-dev/data-access-ai/package.json @@ -0,0 +1,5 @@ +{ + "name": "@nx/nx-dev/data-access-ai", + "version": "0.0.1", + "type": "commonjs" +} diff --git a/nx-dev/data-access-ai/project.json b/nx-dev/data-access-ai/project.json new file mode 100644 index 0000000000000..804ace199f51f --- /dev/null +++ b/nx-dev/data-access-ai/project.json @@ -0,0 +1,40 @@ +{ + "name": "nx-dev-data-access-ai", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "nx-dev/data-access-ai/src", + "projectType": "library", + "targets": { + "build": { + "executor": "@nx/js:tsc", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/nx-dev/data-access-ai", + "main": "nx-dev/data-access-ai/src/index.ts", + "tsConfig": "nx-dev/data-access-ai/tsconfig.lib.json", + "assets": ["nx-dev/data-access-ai/*.md"] + } + }, + "lint": { + "executor": "@nx/linter:eslint", + "outputs": ["{options.outputFile}"], + "options": { + "lintFilePatterns": ["nx-dev/data-access-ai/**/*.ts"] + } + }, + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], + "options": { + "jestConfig": "nx-dev/data-access-ai/jest.config.ts", + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "codeCoverage": true + } + } + } + }, + "tags": [] +} diff --git a/nx-dev/data-access-ai/src/index.ts b/nx-dev/data-access-ai/src/index.ts new file mode 100644 index 0000000000000..4149f0e243fa5 --- /dev/null +++ b/nx-dev/data-access-ai/src/index.ts @@ -0,0 +1,2 @@ +export * from './lib/data-access-ai'; +export * from './lib/utils'; diff --git a/nx-dev/data-access-ai/src/lib/data-access-ai.ts b/nx-dev/data-access-ai/src/lib/data-access-ai.ts new file mode 100644 index 0000000000000..fd8c31ea3e60a --- /dev/null +++ b/nx-dev/data-access-ai/src/lib/data-access-ai.ts @@ -0,0 +1,192 @@ +// based on: +// https://github.com/supabase-community/nextjs-openai-doc-search/blob/main/pages/api/vector-search.ts + +import { createClient } from '@supabase/supabase-js'; +import GPT3Tokenizer from 'gpt3-tokenizer'; +import { + Configuration, + OpenAIApi, + CreateModerationResponse, + CreateEmbeddingResponse, + ChatCompletionRequestMessageRoleEnum, + CreateCompletionResponseUsage, +} from 'openai'; +import { getMessageFromResponse, sanitizeLinksInResponse } from './utils'; + +const openAiKey = process.env['NX_OPENAI_KEY']; +const supabaseUrl = process.env['NX_NEXT_PUBLIC_SUPABASE_URL']; +const supabaseServiceKey = process.env['NX_SUPABASE_SERVICE_ROLE_KEY']; +const config = new Configuration({ + apiKey: openAiKey, +}); +const openai = new OpenAIApi(config); + +export async function nxDevDataAccessAi( + query: string +): Promise<{ textResponse: string; usage?: CreateCompletionResponseUsage }> { + try { + if (!openAiKey) { + throw new ApplicationError('Missing environment variable NX_OPENAI_KEY'); + } + + if (!supabaseUrl) { + throw new ApplicationError( + 'Missing environment variable NX_NEXT_PUBLIC_SUPABASE_URL' + ); + } + + if (!supabaseServiceKey) { + throw new ApplicationError( + 'Missing environment variable NX_SUPABASE_SERVICE_ROLE_KEY' + ); + } + + if (!query) { + throw new UserError('Missing query in request data'); + } + + const supabaseClient = createClient(supabaseUrl, supabaseServiceKey); + + // Moderate the content to comply with OpenAI T&C + const sanitizedQuery = query.trim(); + const moderationResponse: CreateModerationResponse = await openai + .createModeration({ input: sanitizedQuery }) + .then((res) => res.data); + + const [results] = moderationResponse.results; + + if (results.flagged) { + throw new UserError('Flagged content', { + flagged: true, + categories: results.categories, + }); + } + + // Create embedding from query + const embeddingResponse = await openai.createEmbedding({ + model: 'text-embedding-ada-002', + input: sanitizedQuery, + }); + + if (embeddingResponse.status !== 200) { + throw new ApplicationError( + 'Failed to create embedding for question', + embeddingResponse + ); + } + + const { + data: [{ embedding }], + }: CreateEmbeddingResponse = embeddingResponse.data; + + const { error: matchError, data: pageSections } = await supabaseClient.rpc( + 'match_page_sections', + { + embedding, + match_threshold: 0.78, + match_count: 10, + min_content_length: 50, + } + ); + + if (matchError) { + throw new ApplicationError('Failed to match page sections', matchError); + } + + const tokenizer = new GPT3Tokenizer({ type: 'gpt3' }); + let tokenCount = 0; + let contextText = ''; + + for (let i = 0; i < pageSections.length; i++) { + const pageSection = pageSections[i]; + const content = pageSection.content; + const encoded = tokenizer.encode(content); + tokenCount += encoded.text.length; + + if (tokenCount >= 1500) { + break; + } + + contextText += `${content.trim()}\n---\n`; + } + + const prompt = ` + ${` + You are a knowledgeable Nx representative. + Your knowledge is based entirely on the official Nx documentation. + You should answer queries using ONLY that information. + Answer in markdown format. Always give an example, answer as thoroughly as you can, and + always provide a link to relevant documentation + on the https://nx.dev website. All the links you find or post + that look like local or relative links, always prepend with "https://nx.dev". + Your answer should be in the form of a Markdown article, much like the + existing Nx documentation. Include a title, and subsections, if it makes sense. + Mark the titles and the subsections with the appropriate markdown syntax. + If you are unsure and the answer is not explicitly written in the Nx documentation, say + "Sorry, I don't know how to help with that. + You can visit the [Nx documentation](https://nx.dev/getting-started/intro) for more info." + Remember, answer the question using ONLY the information provided in the Nx documentation. + Answer as markdown (including related code snippets if available). + ` + .replace(/\s+/g, ' ') + .trim()} + `; + + const chatGptMessages = [ + { + role: ChatCompletionRequestMessageRoleEnum.System, + content: prompt, + }, + { + role: ChatCompletionRequestMessageRoleEnum.Assistant, + content: contextText, + }, + { + role: ChatCompletionRequestMessageRoleEnum.User, + content: sanitizedQuery, + }, + ]; + + const response = await openai.createChatCompletion({ + model: 'gpt-3.5-turbo-16k', + messages: chatGptMessages, + temperature: 0, + stream: false, + }); + + if (response.status !== 200) { + const error = response.data; + throw new ApplicationError('Failed to generate completion', error); + } + + const message = getMessageFromResponse(response.data); + + const responseWithoutBadLinks = await sanitizeLinksInResponse(message); + + return { + textResponse: responseWithoutBadLinks, + usage: response.data.usage, + }; + } catch (err: unknown) { + if (err instanceof UserError) { + console.error(err.message); + } else if (err instanceof ApplicationError) { + // Print out application errors with their additional data + console.error(`${err.message}: ${JSON.stringify(err.data)}`); + } else { + // Print out unexpected errors as is to help with debugging + console.error(err); + } + + // TODO: include more response info in debug environments + console.error(err); + throw err; + } +} +export class ApplicationError extends Error { + constructor(message: string, public data: Record = {}) { + super(message); + } +} + +export class UserError extends ApplicationError {} diff --git a/nx-dev/data-access-ai/src/lib/utils.ts b/nx-dev/data-access-ai/src/lib/utils.ts new file mode 100644 index 0000000000000..295c4c35487c4 --- /dev/null +++ b/nx-dev/data-access-ai/src/lib/utils.ts @@ -0,0 +1,50 @@ +import { CreateChatCompletionResponse } from 'openai'; + +export function getMessageFromResponse( + response: CreateChatCompletionResponse +): string { + /** + * + * This function here will or may be enhanced + * once we add more functionality + */ + return response.choices[0].message?.content ?? ''; +} + +export async function sanitizeLinksInResponse( + response: string +): Promise { + const regex = /https:\/\/nx\.dev[^) \n]*[^).]/g; + const urls = response.match(regex); + + if (urls) { + for (const url of urls) { + const linkIsWrong = await is404(url); + if (linkIsWrong) { + response = response.replace( + url, + 'https://nx.dev/getting-started/intro' + ); + } + } + } + + return response; +} + +async function is404(url: string): Promise { + try { + const response = await fetch(url.replace('https://nx.dev', '')); + if (response.status === 404) { + return true; + } else { + return false; + } + } catch (error) { + if ((error as any)?.response?.status === 404) { + return true; + } else { + return false; + } + } +} diff --git a/nx-dev/data-access-ai/tsconfig.json b/nx-dev/data-access-ai/tsconfig.json new file mode 100644 index 0000000000000..dfe3c12605c55 --- /dev/null +++ b/nx-dev/data-access-ai/tsconfig.json @@ -0,0 +1,24 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "module": "commonjs", + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "target": "es2021", + "lib": ["es2021", "DOM"] + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ] +} diff --git a/nx-dev/data-access-ai/tsconfig.lib.json b/nx-dev/data-access-ai/tsconfig.lib.json new file mode 100644 index 0000000000000..33eca2c2cdf8c --- /dev/null +++ b/nx-dev/data-access-ai/tsconfig.lib.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "declaration": true, + "types": ["node"] + }, + "include": ["src/**/*.ts"], + "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"] +} diff --git a/nx-dev/data-access-ai/tsconfig.spec.json b/nx-dev/data-access-ai/tsconfig.spec.json new file mode 100644 index 0000000000000..9b2a121d114b6 --- /dev/null +++ b/nx-dev/data-access-ai/tsconfig.spec.json @@ -0,0 +1,14 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"] + }, + "include": [ + "jest.config.ts", + "src/**/*.test.ts", + "src/**/*.spec.ts", + "src/**/*.d.ts" + ] +} diff --git a/nx-dev/feature-ai/.babelrc b/nx-dev/feature-ai/.babelrc new file mode 100644 index 0000000000000..1ea870ead410c --- /dev/null +++ b/nx-dev/feature-ai/.babelrc @@ -0,0 +1,12 @@ +{ + "presets": [ + [ + "@nx/react/babel", + { + "runtime": "automatic", + "useBuiltIns": "usage" + } + ] + ], + "plugins": [] +} diff --git a/nx-dev/feature-ai/.eslintrc.json b/nx-dev/feature-ai/.eslintrc.json new file mode 100644 index 0000000000000..a39ac5d057803 --- /dev/null +++ b/nx-dev/feature-ai/.eslintrc.json @@ -0,0 +1,18 @@ +{ + "extends": ["plugin:@nx/react", "../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], + "rules": {} + }, + { + "files": ["*.ts", "*.tsx"], + "rules": {} + }, + { + "files": ["*.js", "*.jsx"], + "rules": {} + } + ] +} diff --git a/nx-dev/feature-ai/README.md b/nx-dev/feature-ai/README.md new file mode 100644 index 0000000000000..0cbb78eeafbbe --- /dev/null +++ b/nx-dev/feature-ai/README.md @@ -0,0 +1,7 @@ +# nx-dev-feature-ai + +This library was generated with [Nx](https://nx.dev). + +## Running unit tests + +Run `nx test nx-dev-feature-ai` to execute the unit tests via [Jest](https://jestjs.io). diff --git a/nx-dev/feature-ai/jest.config.ts b/nx-dev/feature-ai/jest.config.ts new file mode 100644 index 0000000000000..80eb900706dc2 --- /dev/null +++ b/nx-dev/feature-ai/jest.config.ts @@ -0,0 +1,10 @@ +/* eslint-disable */ +export default { + displayName: 'nx-dev-feature-search', + transform: { + '^.+\\.[tj]sx?$': ['babel-jest', { presets: ['@nx/next/babel'] }], + }, + moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'], + coverageDirectory: '../../coverage/nx-dev/feature-ai', + preset: '../../jest.preset.js', +}; diff --git a/nx-dev/feature-ai/project.json b/nx-dev/feature-ai/project.json new file mode 100644 index 0000000000000..2103b5fbf84c3 --- /dev/null +++ b/nx-dev/feature-ai/project.json @@ -0,0 +1,11 @@ +{ + "name": "nx-dev-feature-ai", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "nx-dev/feature-ai/src", + "projectType": "library", + "targets": { + "lint": {}, + "test": {} + }, + "tags": ["scope:nx-dev", "type:feature"] +} diff --git a/nx-dev/feature-ai/src/index.ts b/nx-dev/feature-ai/src/index.ts new file mode 100644 index 0000000000000..a717de0bafc73 --- /dev/null +++ b/nx-dev/feature-ai/src/index.ts @@ -0,0 +1,3 @@ +// Use this file to export React client components (e.g. those with 'use client' directive) or other non-server utilities + +export * from './lib/feature-ai'; diff --git a/nx-dev/feature-ai/src/lib/feature-ai.tsx b/nx-dev/feature-ai/src/lib/feature-ai.tsx new file mode 100644 index 0000000000000..733681efe036c --- /dev/null +++ b/nx-dev/feature-ai/src/lib/feature-ai.tsx @@ -0,0 +1,120 @@ +import { ReactNode, useState } from 'react'; +import { Button } from '@nx/nx-dev/ui-common'; +import { sendCustomEvent } from '@nx/nx-dev/feature-analytics'; + +import { renderMarkdown } from '@nx/nx-dev/ui-markdoc'; +import { nxDevDataAccessAi } from '@nx/nx-dev/data-access-ai'; + +export function FeatureAi(): JSX.Element { + const [finalResult, setFinalResult] = useState(null); + const [error, setError] = useState(null); + const [query, setSearchTerm] = useState(''); + const [loading, setLoading] = useState(false); + + const warning = ` + {% callout type="warning" title="Always double check!" %} + This feature is still in Alpha. + The results may not be accurate, so please always double check with our documentation. +{% /callout %} + + `; + + const handleSubmit = async () => { + setLoading(true); + let completeText = ''; + let usage; + try { + const aiResponse = await nxDevDataAccessAi(query); + completeText = aiResponse.textResponse; + usage = aiResponse.usage; + setLoading(false); + } catch (error) { + setError(error as any); + setLoading(false); + } + sendCustomEvent('ai_query', 'ai', 'query', undefined, { query, ...usage }); + setFinalResult( + renderMarkdown(warning + completeText, { filePath: '' }).node + ); + }; + + return ( +
+
+ setSearchTerm(event.target.value)} + onKeyDown={(event) => { + if (event.keyCode === 13 || event.key === 'Enter') { + handleSubmit(); + } + }} + type="search" + /> + +
+ {loading ? ( +
+

Thinking...

+
+ ) : null} + {finalResult && !error ? ( + <> +
+ {finalResult} +
+
+ + +
+ + ) : null} + {error ?
There was an error: {error['message']}
: null} +
+ ); +} + +export default FeatureAi; diff --git a/nx-dev/feature-ai/tsconfig.json b/nx-dev/feature-ai/tsconfig.json new file mode 100644 index 0000000000000..3230750a884f7 --- /dev/null +++ b/nx-dev/feature-ai/tsconfig.json @@ -0,0 +1,23 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "jsx": "react-jsx", + "allowJs": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ] +} diff --git a/nx-dev/feature-ai/tsconfig.lib.json b/nx-dev/feature-ai/tsconfig.lib.json new file mode 100644 index 0000000000000..cccfe3f7d83d9 --- /dev/null +++ b/nx-dev/feature-ai/tsconfig.lib.json @@ -0,0 +1,20 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "types": ["node"], + "lib": ["dom"] + }, + "files": [ + "../../node_modules/@nx/react/typings/cssmodule.d.ts", + "../../node_modules/@nx/react/typings/image.d.ts" + ], + "exclude": [ + "**/*.spec.ts", + "**/*.test.ts", + "**/*.spec.tsx", + "**/*.test.tsx", + "jest.config.ts" + ], + "include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"] +} diff --git a/nx-dev/feature-ai/tsconfig.spec.json b/nx-dev/feature-ai/tsconfig.spec.json new file mode 100644 index 0000000000000..46f9467f3bd81 --- /dev/null +++ b/nx-dev/feature-ai/tsconfig.spec.json @@ -0,0 +1,20 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"] + }, + "include": [ + "**/*.spec.ts", + "**/*.test.ts", + "**/*.spec.tsx", + "**/*.test.tsx", + "**/*.spec.js", + "**/*.test.js", + "**/*.spec.jsx", + "**/*.test.jsx", + "**/*.d.ts", + "jest.config.ts" + ] +} diff --git a/nx-dev/feature-analytics/src/lib/google-analytics.ts b/nx-dev/feature-analytics/src/lib/google-analytics.ts index 01362efa6e2d2..bfca9c46385ab 100644 --- a/nx-dev/feature-analytics/src/lib/google-analytics.ts +++ b/nx-dev/feature-analytics/src/lib/google-analytics.ts @@ -26,13 +26,15 @@ export function sendCustomEvent( action: string, category: string, label: string, - value?: number + value?: number, + customObject?: Record ): void { try { gtag('event', action, { event_category: category, event_label: label, value, + ...customObject, }); } catch (error) { throw new Error(`Cannot send Google Tag event: ${error}`); diff --git a/nx-dev/nx-dev/next-sitemap.config.js b/nx-dev/nx-dev/next-sitemap.config.js index 00aefe0cdf13c..34b985c514e11 100644 --- a/nx-dev/nx-dev/next-sitemap.config.js +++ b/nx-dev/nx-dev/next-sitemap.config.js @@ -3,6 +3,7 @@ const path = require('path'); module.exports = { siteUrl: process.env.SITE_URL || 'https://nx.dev', generateRobotsTxt: true, + exclude: ['/ai'], sourceDir: path.resolve(__dirname, '../../dist/nx-dev/nx-dev/.next'), outDir: path.resolve(__dirname, '../../dist/nx-dev/nx-dev/public'), }; diff --git a/nx-dev/nx-dev/pages/ai/index.tsx b/nx-dev/nx-dev/pages/ai/index.tsx new file mode 100644 index 0000000000000..1f55df54c8cdf --- /dev/null +++ b/nx-dev/nx-dev/pages/ai/index.tsx @@ -0,0 +1,32 @@ +import { DocumentationHeader } from '@nx/nx-dev/ui-common'; +import { FeatureAi } from '@nx/nx-dev/feature-ai'; +import { useNavToggle } from '../../lib/navigation-toggle.effect'; +import { NextSeo } from 'next-seo'; + +export default function AiDocs(): JSX.Element { + const { toggleNav, navIsOpen } = useNavToggle(); + return ( + <> + +
+
+ +
+
+ +
+
+ + ); +} diff --git a/package.json b/package.json index 8185fee050a58..705c988019505 100644 --- a/package.json +++ b/package.json @@ -92,6 +92,7 @@ "@storybook/react": "^7.0.24", "@storybook/react-webpack5": "^7.0.24", "@storybook/types": "^7.0.24", + "@supabase/supabase-js": "^2.26.0", "@svgr/rollup": "^8.0.1", "@svgr/webpack": "^8.0.1", "@swc-node/register": "^1.4.2", @@ -128,6 +129,7 @@ "@xstate/immer": "0.3.1", "@xstate/inspect": "0.7.0", "@xstate/react": "3.0.1", + "ai": "^2.1.15", "ajv": "^8.11.0", "autoprefixer": "10.4.13", "babel-jest": "29.4.3", @@ -173,6 +175,7 @@ "flat": "^5.0.2", "fork-ts-checker-webpack-plugin": "7.2.13", "fs-extra": "^11.1.0", + "gpt3-tokenizer": "^1.1.5", "html-webpack-plugin": "5.5.0", "http-server": "14.1.0", "husky": "^8.0.1", @@ -214,6 +217,7 @@ "nx-cloud": "16.0.5", "octokit": "^2.0.14", "open": "^8.4.0", + "openai":"~3.3.0", "ora": "5.3.0", "parse-markdown-links": "^1.0.4", "parse5": "4.0.0", @@ -354,5 +358,4 @@ "lerna@6.6.2": "patches/lerna@6.6.2.patch" } } -} - +} \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b323b4f4ca733..93994ca536850 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,9 +1,5 @@ lockfileVersion: '6.0' -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - overrides: minimist: ^1.2.6 underscore: ^1.12.1 @@ -349,6 +345,9 @@ devDependencies: '@storybook/types': specifier: ^7.0.24 version: 7.0.24 + '@supabase/supabase-js': + specifier: ^2.26.0 + version: 2.26.0 '@svgr/rollup': specifier: ^8.0.1 version: 8.0.1(rollup@2.79.0) @@ -457,6 +456,9 @@ devDependencies: '@xstate/react': specifier: 3.0.1 version: 3.0.1(@types/react@18.2.13)(react@18.2.0)(xstate@4.34.0) + ai: + specifier: ^2.1.15 + version: 2.1.15(react@18.2.0)(svelte@3.59.2)(vue@3.3.4) ajv: specifier: ^8.11.0 version: 8.11.0 @@ -592,6 +594,9 @@ devDependencies: fs-extra: specifier: ^11.1.0 version: 11.1.0 + gpt3-tokenizer: + specifier: ^1.1.5 + version: 1.1.5 html-webpack-plugin: specifier: 5.5.0 version: 5.5.0(webpack@5.88.0) @@ -715,6 +720,9 @@ devDependencies: open: specifier: ^8.4.0 version: 8.4.0 + openai: + specifier: ~3.3.0 + version: 3.3.0 ora: specifier: 5.3.0 version: 5.3.0 @@ -5808,7 +5816,6 @@ packages: dependencies: '@jridgewell/gen-mapping': 0.3.3 '@jridgewell/trace-mapping': 0.3.18 - dev: true /@jridgewell/sourcemap-codec@1.4.14: resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==} @@ -6891,42 +6898,6 @@ packages: - typescript dev: true - /@nrwl/js@15.8.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(nx@15.8.0)(prettier@2.7.1)(typescript@5.1.3): - resolution: {integrity: sha512-l2Q7oFpzx6ul7G0nKpMkrvnIEaOY+X8fc2g2Db5WqpnnBdfkrtWXZPg/O4DQ1p9O6BXrZ+Q2AK9bfgnliiwyEg==} - dependencies: - '@babel/core': 7.22.5 - '@babel/plugin-proposal-class-properties': 7.18.6(@babel/core@7.22.5) - '@babel/plugin-proposal-decorators': 7.21.0(@babel/core@7.22.5) - '@babel/plugin-transform-runtime': 7.22.5(@babel/core@7.22.5) - '@babel/preset-env': 7.22.5(@babel/core@7.22.5) - '@babel/preset-typescript': 7.21.4(@babel/core@7.22.5) - '@babel/runtime': 7.22.5 - '@nrwl/devkit': 15.8.0(nx@15.8.0)(typescript@5.1.3) - '@nrwl/workspace': 15.8.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(prettier@2.7.1)(typescript@5.1.3) - '@phenomnomnominal/tsquery': 4.1.1(typescript@5.1.3) - babel-plugin-const-enum: 1.2.0(@babel/core@7.22.5) - babel-plugin-macros: 2.8.0 - babel-plugin-transform-typescript-metadata: 0.3.2(@babel/core@7.22.5) - chalk: 4.1.2 - fast-glob: 3.2.7 - fs-extra: 11.1.1 - ignore: 5.2.0 - js-tokens: 4.0.0 - minimatch: 3.0.5 - source-map-support: 0.5.19 - tree-kill: 1.2.2 - tslib: 2.5.3 - transitivePeerDependencies: - - '@babel/traverse' - - '@swc-node/register' - - '@swc/core' - - debug - - nx - - prettier - - supports-color - - typescript - dev: true - /@nrwl/js@16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4): resolution: {integrity: sha512-6ZeiIEt67meBC5mTugzSCbMHsMLTrYGzqkaXWWr3jj+8WTxCgVqTqV8JSgUq/sW9btQM7zAqH7ABLp0Cr4FS+A==} dependencies: @@ -6951,7 +6922,7 @@ packages: optional: true dependencies: '@nrwl/devkit': 15.8.0(nx@15.8.0)(typescript@5.1.3) - '@nrwl/js': 15.8.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(nx@15.8.0)(prettier@2.7.1)(typescript@5.1.3) + '@nrwl/js': 15.8.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.5.0-beta.3)(prettier@2.7.1)(typescript@5.1.3) '@phenomnomnominal/tsquery': 4.1.1(typescript@5.1.3) eslint: 8.15.0 tmp: 0.2.1 @@ -8102,7 +8073,7 @@ packages: '@octokit/request-error': 3.0.3 '@octokit/types': 9.0.0 is-plain-object: 5.0.0 - node-fetch: 2.6.7 + node-fetch: 2.6.12 universal-user-agent: 6.0.0 transitivePeerDependencies: - encoding @@ -9085,7 +9056,7 @@ packages: glob-promise: 6.0.2(glob@8.1.0) handlebars: 4.7.7 lazy-universal-dotenv: 4.0.0 - node-fetch: 2.6.7 + node-fetch: 2.6.12 picomatch: 2.3.1 pkg-dir: 5.0.0 pretty-hrtime: 1.0.3 @@ -9599,6 +9570,62 @@ packages: file-system-cache: 2.3.0 dev: true + /@supabase/functions-js@2.1.2: + resolution: {integrity: sha512-QCR6pwJs9exCl37bmpMisUd6mf+0SUBJ6mUpiAjEkSJ/+xW8TCuO14bvkWHADd5hElJK9MxNlMQXxSA4DRz9nQ==} + dependencies: + cross-fetch: 3.1.8 + transitivePeerDependencies: + - encoding + dev: true + + /@supabase/gotrue-js@2.39.1: + resolution: {integrity: sha512-qRz9mBleA/QATGKOdMAUjpn+YcbZJrTHyWQCe2hAFqJo15JIe1XziD1ZeFraRpsXwja+vONslGeynGv7H8ZZeQ==} + dependencies: + cross-fetch: 3.1.8 + transitivePeerDependencies: + - encoding + dev: true + + /@supabase/postgrest-js@1.7.2: + resolution: {integrity: sha512-GK80JpRq8l6Qll85erICypAfQCied8tdlXfsDN14W844HqXCSOisk8AaE01DAwGJanieaoN5fuqhzA2yKxDvEQ==} + dependencies: + cross-fetch: 3.1.8 + transitivePeerDependencies: + - encoding + dev: true + + /@supabase/realtime-js@2.7.3: + resolution: {integrity: sha512-c7TzL81sx2kqyxsxcDduJcHL9KJdCOoKimGP6lQSqiZKX42ATlBZpWbyy9KFGFBjAP4nyopMf5JhPi2ZH9jyNw==} + dependencies: + '@types/phoenix': 1.6.0 + '@types/websocket': 1.0.5 + websocket: 1.0.34 + transitivePeerDependencies: + - supports-color + dev: true + + /@supabase/storage-js@2.5.1: + resolution: {integrity: sha512-nkR0fQA9ScAtIKA3vNoPEqbZv1k5B5HVRYEvRWdlP6mUpFphM9TwPL2jZ/ztNGMTG5xT6SrHr+H7Ykz8qzbhjw==} + dependencies: + cross-fetch: 3.1.8 + transitivePeerDependencies: + - encoding + dev: true + + /@supabase/supabase-js@2.26.0: + resolution: {integrity: sha512-RXmTPTobaYAwkSobadHZmEVLmzX3SGrtRZIGfLWnLv92VzBRrjuXn0a+bJqKl50GUzsyqPA+j5pod7EwMkcH5A==} + dependencies: + '@supabase/functions-js': 2.1.2 + '@supabase/gotrue-js': 2.39.1 + '@supabase/postgrest-js': 1.7.2 + '@supabase/realtime-js': 2.7.3 + '@supabase/storage-js': 2.5.1 + cross-fetch: 3.1.8 + transitivePeerDependencies: + - encoding + - supports-color + dev: true + /@svgr/babel-plugin-add-jsx-attribute@8.0.0(@babel/core@7.22.5): resolution: {integrity: sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==} engines: {node: '>=14'} @@ -10492,6 +10519,10 @@ packages: resolution: {integrity: sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==} dev: true + /@types/phoenix@1.6.0: + resolution: {integrity: sha512-qwfpsHmFuhAS/dVd4uBIraMxRd56vwBUYQGZ6GpXnFuM2XMRFJbIyruFKKlW2daQliuYZwe0qfn/UjFCDKic5g==} + dev: true + /@types/prettier@2.7.1: resolution: {integrity: sha512-ri0UmynRRvZiiUJdiz38MmIblKK+oH30MztdBVR95dv/Ubw6neWSb8u1XpRb72L4qsZOhz+L+z9JD40SJmfWow==} @@ -10602,6 +10633,12 @@ packages: resolution: {integrity: sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==} dev: true + /@types/websocket@1.0.5: + resolution: {integrity: sha512-NbsqiNX9CnEfC1Z0Vf4mE1SgAJ07JnRYcNex7AJ9zAVzmiGHmjKFEk7O4TJIsgv2B1sLEb6owKFZrACwdYngsQ==} + dependencies: + '@types/node': 18.16.9 + dev: true + /@types/ws@8.5.3: resolution: {integrity: sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==} dependencies: @@ -10958,6 +10995,15 @@ packages: source-map: 0.6.1 dev: true + /@vue/compiler-core@3.3.4: + resolution: {integrity: sha512-cquyDNvZ6jTbf/+x+AgM2Arrp6G4Dzbb0R64jiG804HRMfRiFXWI6kqUVqZ6ZR0bQhIoQjB4+2bhNtVwndW15g==} + dependencies: + '@babel/parser': 7.22.5 + '@vue/shared': 3.3.4 + estree-walker: 2.0.2 + source-map-js: 1.0.2 + dev: true + /@vue/compiler-dom@3.2.41: resolution: {integrity: sha512-xe5TbbIsonjENxJsYRbDJvthzqxLNk+tb3d/c47zgREDa/PCp6/Y4gC/skM4H6PIuX5DAxm7fFJdbjjUH2QTMw==} dependencies: @@ -10965,6 +11011,13 @@ packages: '@vue/shared': 3.2.41 dev: true + /@vue/compiler-dom@3.3.4: + resolution: {integrity: sha512-wyM+OjOVpuUukIq6p5+nwHYtj9cFroz9cwkfmP9O1nzH68BenTTv0u7/ndggT8cIQlnBeOo6sUT/gvHcIkLA5w==} + dependencies: + '@vue/compiler-core': 3.3.4 + '@vue/shared': 3.3.4 + dev: true + /@vue/compiler-sfc@3.2.41: resolution: {integrity: sha512-+1P2m5kxOeaxVmJNXnBskAn3BenbTmbxBxWOtBq3mQTCokIreuMULFantBUclP0+KnzNCMOvcnKinqQZmiOF8w==} dependencies: @@ -10980,6 +11033,21 @@ packages: source-map: 0.6.1 dev: true + /@vue/compiler-sfc@3.3.4: + resolution: {integrity: sha512-6y/d8uw+5TkCuzBkgLS0v3lSM3hJDntFEiUORM11pQ/hKvkhSKZrXW6i69UyXlJQisJxuUEJKAWEqWbWsLeNKQ==} + dependencies: + '@babel/parser': 7.22.5 + '@vue/compiler-core': 3.3.4 + '@vue/compiler-dom': 3.3.4 + '@vue/compiler-ssr': 3.3.4 + '@vue/reactivity-transform': 3.3.4 + '@vue/shared': 3.3.4 + estree-walker: 2.0.2 + magic-string: 0.30.0 + postcss: 8.4.19 + source-map-js: 1.0.2 + dev: true + /@vue/compiler-ssr@3.2.41: resolution: {integrity: sha512-Y5wPiNIiaMz/sps8+DmhaKfDm1xgj6GrH99z4gq2LQenfVQcYXmHIOBcs5qPwl7jaW3SUQWjkAPKMfQemEQZwQ==} dependencies: @@ -10987,6 +11055,13 @@ packages: '@vue/shared': 3.2.41 dev: true + /@vue/compiler-ssr@3.3.4: + resolution: {integrity: sha512-m0v6oKpup2nMSehwA6Uuu+j+wEwcy7QmwMkVNVfrV9P2qE5KshC6RwOCq8fjGS/Eak/uNb8AaWekfiXxbBB6gQ==} + dependencies: + '@vue/compiler-dom': 3.3.4 + '@vue/shared': 3.3.4 + dev: true + /@vue/reactivity-transform@3.2.41: resolution: {integrity: sha512-mK5+BNMsL4hHi+IR3Ft/ho6Za+L3FA5j8WvreJ7XzHrqkPq8jtF/SMo7tuc9gHjLDwKZX1nP1JQOKo9IEAn54A==} dependencies: @@ -10997,10 +11072,55 @@ packages: magic-string: 0.25.9 dev: true + /@vue/reactivity-transform@3.3.4: + resolution: {integrity: sha512-MXgwjako4nu5WFLAjpBnCj/ieqcjE2aJBINUNQzkZQfzIZA4xn+0fV1tIYBJvvva3N3OvKGofRLvQIwEQPpaXw==} + dependencies: + '@babel/parser': 7.22.5 + '@vue/compiler-core': 3.3.4 + '@vue/shared': 3.3.4 + estree-walker: 2.0.2 + magic-string: 0.30.0 + dev: true + + /@vue/reactivity@3.3.4: + resolution: {integrity: sha512-kLTDLwd0B1jG08NBF3R5rqULtv/f8x3rOFByTDz4J53ttIQEDmALqKqXY0J+XQeN0aV2FBxY8nJDf88yvOPAqQ==} + dependencies: + '@vue/shared': 3.3.4 + dev: true + + /@vue/runtime-core@3.3.4: + resolution: {integrity: sha512-R+bqxMN6pWO7zGI4OMlmvePOdP2c93GsHFM/siJI7O2nxFRzj55pLwkpCedEY+bTMgp5miZ8CxfIZo3S+gFqvA==} + dependencies: + '@vue/reactivity': 3.3.4 + '@vue/shared': 3.3.4 + dev: true + + /@vue/runtime-dom@3.3.4: + resolution: {integrity: sha512-Aj5bTJ3u5sFsUckRghsNjVTtxZQ1OyMWCr5dZRAPijF/0Vy4xEoRCwLyHXcj4D0UFbJ4lbx3gPTgg06K/GnPnQ==} + dependencies: + '@vue/runtime-core': 3.3.4 + '@vue/shared': 3.3.4 + csstype: 3.1.1 + dev: true + + /@vue/server-renderer@3.3.4(vue@3.3.4): + resolution: {integrity: sha512-Q6jDDzR23ViIb67v+vM1Dqntu+HUexQcsWKhhQa4ARVzxOY2HbC7QRW/ggkDBd5BU+uM1sV6XOAP0b216o34JQ==} + peerDependencies: + vue: 3.3.4 + dependencies: + '@vue/compiler-ssr': 3.3.4 + '@vue/shared': 3.3.4 + vue: 3.3.4 + dev: true + /@vue/shared@3.2.41: resolution: {integrity: sha512-W9mfWLHmJhkfAmV+7gDjcHeAWALQtgGT3JErxULl0oz6R6+3ug91I7IErs93eCFhPCZPHBs4QJS7YWEV7A3sxw==} dev: true + /@vue/shared@3.3.4: + resolution: {integrity: sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ==} + dev: true + /@webassemblyjs/ast@1.11.1: resolution: {integrity: sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==} dependencies: @@ -11463,6 +11583,31 @@ packages: indent-string: 4.0.0 dev: true + /ai@2.1.15(react@18.2.0)(svelte@3.59.2)(vue@3.3.4): + resolution: {integrity: sha512-ePxoo9yEpHrC6n2O5b0Ko9C0dZEEXBY9FuhbrR1PVgdo4cSislTqg9TSPdVKT3mnw01A2pEg24cQ8ikRyH9m4Q==} + engines: {node: '>=14.6'} + peerDependencies: + react: ^18.2.0 + svelte: ^4.0.0 + vue: ^3.3.4 + peerDependenciesMeta: + react: + optional: true + svelte: + optional: true + vue: + optional: true + dependencies: + eventsource-parser: 1.0.0 + nanoid: 3.3.6 + react: 18.2.0 + sswr: 1.10.0(svelte@3.59.2) + svelte: 3.59.2 + swr: 2.1.5(react@18.2.0) + swrv: 1.0.3(vue@3.3.4) + vue: 3.3.4 + dev: true + /ajv-formats@2.1.1(ajv@8.11.0): resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} peerDependencies: @@ -11748,6 +11893,10 @@ packages: is-string: 1.0.7 dev: true + /array-keyed-map@2.1.3: + resolution: {integrity: sha512-JIUwuFakO+jHjxyp4YgSiKXSZeC0U+R1jR94bXWBcVlFRBycqXlb+kH9JHxBGcxnVuSqx5bnn0Qz9xtSeKOjiA==} + dev: true + /array-union@2.1.0: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} @@ -11939,6 +12088,14 @@ packages: - debug dev: true + /axios@0.26.1: + resolution: {integrity: sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==} + dependencies: + follow-redirects: 1.15.2(debug@4.3.2) + transitivePeerDependencies: + - debug + dev: true + /axios@1.0.0: resolution: {integrity: sha512-SsHsGFN1qNPFT5QhSoSD37SHDfGyLSW5AESmyLk2JeCMHv5g0I9g0Hz/zQHx2KNe0jGXh2q2hAm7OdkXm360CA==} dependencies: @@ -12677,7 +12834,6 @@ packages: /buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - dev: true /buffer-indexof-polyfill@1.0.2: resolution: {integrity: sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==} @@ -12703,6 +12859,14 @@ packages: engines: {node: '>=0.2.0'} dev: true + /bufferutil@4.0.7: + resolution: {integrity: sha512-kukuqc39WOHtdxtw4UScxF/WVnMFVSQVKhtx3AjZJzhd0RGZZldcrfSEbVsWWe6KNH253574cq5F+wpv0G9pJw==} + engines: {node: '>=6.14.2'} + requiresBuild: true + dependencies: + node-gyp-build: 4.5.0 + dev: true + /builtin-modules@1.1.1: resolution: {integrity: sha512-wxXCdllwGhI2kCC0MnvTGYTMvnVZTvqgypkiTI8Pa5tcz2i6VqsqwYGgqwXji+4RgCzms6EajE4IxiUH6HH8nQ==} engines: {node: '>=0.10.0'} @@ -13250,7 +13414,6 @@ packages: /commander@2.20.3: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} - dev: true /commander@4.1.1: resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} @@ -13771,6 +13934,14 @@ packages: pretty-bytes: 5.6.0 dev: true + /cross-fetch@3.1.8: + resolution: {integrity: sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==} + dependencies: + node-fetch: 2.6.12 + transitivePeerDependencies: + - encoding + dev: true + /cross-spawn@5.1.0: resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==} dependencies: @@ -15645,6 +15816,11 @@ packages: engines: {node: '>=0.8.x'} dev: true + /eventsource-parser@1.0.0: + resolution: {integrity: sha512-9jgfSCa3dmEme2ES3mPByGXfgZ87VbP97tng1G2nWwWx6bV2nYxm2AWCrbQjXToSe+yYlqaZNtxffR9IeQr95g==} + engines: {node: '>=14.18'} + dev: true + /execa@0.7.0: resolution: {integrity: sha512-RztN09XglpYI7aBBrJCPW95jEH7YF1UEPOoX9yDhUTPdp7mK+CQvnLTuD10BNXZ3byLTu2uehZ8EcKT/4CGiFw==} engines: {node: '>=4'} @@ -16826,6 +17002,13 @@ packages: responselike: 2.0.1 dev: true + /gpt3-tokenizer@1.1.5: + resolution: {integrity: sha512-O9iCL8MqGR0Oe9wTh0YftzIbysypNQmS5a5JG3cB3M4LMYjlAVvNnf8LUzVY9MrI7tj+YLY356uHtO2lLX2HpA==} + engines: {node: '>=12'} + dependencies: + array-keyed-map: 2.1.3 + dev: true + /graceful-fs@4.2.10: resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} dev: true @@ -17966,7 +18149,7 @@ packages: /isomorphic-unfetch@3.1.0: resolution: {integrity: sha512-geDJjpoZ8N0kWexiwkX8F9NkTsXhetLPVbZFQ+JTW239QNOwvB0gniuR1Wc6f0AMTn7/mFGyXvHTifrCp/GH8Q==} dependencies: - node-fetch: 2.6.7 + node-fetch: 2.6.12 unfetch: 4.2.0 transitivePeerDependencies: - encoding @@ -18270,7 +18453,7 @@ packages: resolution: {integrity: sha512-Kijeg9Dag6CKtIDA7O21zNTACqD5MD/8HfIV8pdD94vFyFuer52SigdC3IQMhab3vACxXMiFk+yMHNdbqtyTGA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@babel/code-frame': 7.21.4 + '@babel/code-frame': 7.22.5 '@jest/types': 29.5.0 '@types/stack-utils': 2.0.1 chalk: 4.1.2 @@ -20315,6 +20498,18 @@ packages: lodash: 4.17.21 dev: true + /node-fetch@2.6.12: + resolution: {integrity: sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + dependencies: + whatwg-url: 5.0.0 + dev: true + /node-fetch@2.6.7: resolution: {integrity: sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==} engines: {node: 4.x || >=6.0.0} @@ -21015,6 +21210,15 @@ packages: is-wsl: 2.2.0 dev: true + /openai@3.3.0: + resolution: {integrity: sha512-uqxI/Au+aPRnsaQRe8CojU0eCR7I0mBiKjD3sNMzY6DaC1ZVrc85u98mtJW6voDug8fgGN+DIZmTDxTthxb7dQ==} + dependencies: + axios: 0.26.1 + form-data: 4.0.0 + transitivePeerDependencies: + - debug + dev: true + /opener@1.5.2: resolution: {integrity: sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==} hasBin: true @@ -24022,7 +24226,6 @@ packages: chokidar: 3.5.3 immutable: 4.1.0 source-map-js: 1.0.2 - dev: true /sax@1.2.4: resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==} @@ -24619,7 +24822,6 @@ packages: dependencies: buffer-from: 1.1.2 source-map: 0.6.1 - dev: true /source-map@0.6.1: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} @@ -24751,6 +24953,15 @@ packages: minipass: 3.3.4 dev: true + /sswr@1.10.0(svelte@3.59.2): + resolution: {integrity: sha512-nLWAJSQy3h8t7rrbTXanRyVHuQPj4PwKIVGe4IMlxJFdhyaxnN/JGACnvQKGDeWiTGYIZIx/jRuUsPEF0867Pg==} + peerDependencies: + svelte: ^3.29.0 + dependencies: + svelte: 3.59.2 + swrev: 3.0.0 + dev: true + /stable@0.1.8: resolution: {integrity: sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==} deprecated: 'Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility' @@ -25150,6 +25361,11 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} + /svelte@3.59.2: + resolution: {integrity: sha512-vzSyuGr3eEoAtT/A6bmajosJZIUWySzY2CzB3w2pgPvnkUjGqlDnsNnA0PMO+mMAhuyMul6C2uuZzY6ELSkzyA==} + engines: {node: '>= 8'} + dev: true + /svg-parser@2.0.4: resolution: {integrity: sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==} dev: true @@ -25185,6 +25401,27 @@ packages: resolution: {integrity: sha512-DlZARu6ckUFqDe0j5IPayO4k0gQvYQw9Un02MhxAgaMtVnTH2vmyyDe+yKeV0r1LiiPx3JbasdS/5Yyb/AV3iw==} dev: true + /swr@2.1.5(react@18.2.0): + resolution: {integrity: sha512-/OhfZMcEpuz77KavXST5q6XE9nrOBOVcBLWjMT+oAE/kQHyE3PASrevXCtQDZ8aamntOfFkbVJp7Il9tNBQWrw==} + peerDependencies: + react: ^16.11.0 || ^17.0.0 || ^18.0.0 + dependencies: + react: 18.2.0 + use-sync-external-store: 1.2.0(react@18.2.0) + dev: true + + /swrev@3.0.0: + resolution: {integrity: sha512-QJuZiptdOmbDY45pECBRVEgnoBlOKjeT2MWVz04wKHpWX15hM3P7EjcIbHDg5yLoPCMQ7to3349MEE+l9QF5HA==} + dev: true + + /swrv@1.0.3(vue@3.3.4): + resolution: {integrity: sha512-sl+eLEE+aPPjhP1E8gQ75q3RPRyw5Gd/kROnrTFo3+LkCeLskv7F+uAl5W97wgJkzitobL6FLsRPVm0DgIgN8A==} + peerDependencies: + vue: '>=3.2.26 < 4' + dependencies: + vue: 3.3.4 + dev: true + /symbol-observable@1.0.1: resolution: {integrity: sha512-Kb3PrPYz4HanVF1LVGuAdW6LoVgIwjUYJGzFe7NDrBLCN4lsV/5J0MFurV+ygS4bRVwrCEt2c7MQ1R2a72oJDw==} engines: {node: '>=0.10.0'} @@ -25469,7 +25706,6 @@ packages: acorn: 8.8.2 commander: 2.20.3 source-map-support: 0.5.21 - dev: true /terser@5.18.0: resolution: {integrity: sha512-pdL757Ig5a0I+owA42l6tIuEycRuM7FPY4n62h44mRLRfnOxJkkOHd6i89dOpwZlpF6JXBwaAHF6yWzFrt+QyA==} @@ -26025,6 +26261,12 @@ packages: resolution: {integrity: sha512-KNNZtayBCtmnNmbo5mG47p1XsCyrx6iVqomjcZnec/1Y5GGARaxPs6r49RnSPeUP3YjNYiU9sQHAtY4BBvnZwg==} dev: true + /typedarray-to-buffer@3.1.5: + resolution: {integrity: sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==} + dependencies: + is-typedarray: 1.0.0 + dev: true + /typedarray@0.0.6: resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} dev: true @@ -26363,6 +26605,14 @@ packages: react: 18.2.0 dev: true + /utf-8-validate@5.0.10: + resolution: {integrity: sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==} + engines: {node: '>=6.14.2'} + requiresBuild: true + dependencies: + node-gyp-build: 4.5.0 + dev: true + /util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} @@ -26556,7 +26806,7 @@ packages: mlly: 1.2.0 pathe: 1.1.0 picocolors: 1.0.0 - vite: 4.3.9(@types/node@18.16.9)(less@4.1.3)(sass@1.55.0)(stylus@0.59.0) + vite: 4.3.9(@types/node@18.16.9)(less@4.1.3)(sass@1.63.2)(stylus@0.59.0)(terser@5.17.7) transitivePeerDependencies: - '@types/node' - less @@ -26602,42 +26852,6 @@ packages: optionalDependencies: fsevents: 2.3.2 - /vite@4.3.9(@types/node@18.16.9)(less@4.1.3)(sass@1.55.0)(stylus@0.59.0): - resolution: {integrity: sha512-qsTNZjO9NoJNW7KnOrgYwczm0WctJ8m/yqYAMAK9Lxt4SoySUfS5S8ia9K7JHpa3KEeMfyF8LoJ3c5NeBJy6pg==} - engines: {node: ^14.18.0 || >=16.0.0} - hasBin: true - peerDependencies: - '@types/node': '>= 14' - less: '*' - sass: '*' - stylus: '*' - sugarss: '*' - terser: ^5.4.0 - peerDependenciesMeta: - '@types/node': - optional: true - less: - optional: true - sass: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - dependencies: - '@types/node': 18.16.9 - esbuild: 0.17.19 - less: 4.1.3 - postcss: 8.4.24 - rollup: 3.21.0 - sass: 1.55.0 - stylus: 0.59.0 - optionalDependencies: - fsevents: 2.3.2 - dev: false - /vite@4.3.9(@types/node@18.16.9)(less@4.1.3)(sass@1.63.2)(stylus@0.59.0)(terser@5.17.7): resolution: {integrity: sha512-qsTNZjO9NoJNW7KnOrgYwczm0WctJ8m/yqYAMAK9Lxt4SoySUfS5S8ia9K7JHpa3KEeMfyF8LoJ3c5NeBJy6pg==} engines: {node: ^14.18.0 || >=16.0.0} @@ -26673,7 +26887,6 @@ packages: terser: 5.17.7 optionalDependencies: fsevents: 2.3.2 - dev: true /vitest@0.32.0(less@4.1.3)(sass@1.55.0)(stylus@0.59.0): resolution: {integrity: sha512-SW83o629gCqnV3BqBnTxhB10DAwzwEx3z+rqYZESehUB+eWsJxwcBQx7CKy0otuGMJTYh7qCVuUX23HkftGl/Q==} @@ -26748,6 +26961,16 @@ packages: resolution: {integrity: sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==} dev: true + /vue@3.3.4: + resolution: {integrity: sha512-VTyEYn3yvIeY1Py0WaYGZsXnz3y5UnGi62GjVEqvEGPl6nxbOrCXbVOTQWBEJUqAyTUk2uJ5JLVnYJ6ZzGbrSw==} + dependencies: + '@vue/compiler-dom': 3.3.4 + '@vue/compiler-sfc': 3.3.4 + '@vue/runtime-dom': 3.3.4 + '@vue/server-renderer': 3.3.4(vue@3.3.4) + '@vue/shared': 3.3.4 + dev: true + /w3c-hr-time@1.0.2: resolution: {integrity: sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==} deprecated: Use your platform's native performance.now() and performance.timeOrigin. @@ -27224,6 +27447,20 @@ packages: engines: {node: '>=0.8.0'} dev: true + /websocket@1.0.34: + resolution: {integrity: sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ==} + engines: {node: '>=4.0.0'} + dependencies: + bufferutil: 4.0.7 + debug: 2.6.9 + es5-ext: 0.10.62 + typedarray-to-buffer: 3.1.5 + utf-8-validate: 5.0.10 + yaeti: 0.0.6 + transitivePeerDependencies: + - supports-color + dev: true + /well-known-symbols@2.0.0: resolution: {integrity: sha512-ZMjC3ho+KXo0BfJb7JgtQ5IBuvnShdlACNkKkdsqBmYw3bPAaJfPeYUo6tLUaT5tG/Gkh7xkpBhKRQ9e7pyg9Q==} engines: {node: '>=6'} @@ -27543,6 +27780,11 @@ packages: engines: {node: '>=10'} dev: true + /yaeti@0.0.6: + resolution: {integrity: sha512-MvQa//+KcZCUkBTIC9blM+CU9J2GzuTytsOUwf2lidtvkx/6gnEp1QvJv34t9vdjhFmha/mUiNDbN0D0mJWdug==} + engines: {node: '>=0.10.32'} + dev: true + /yallist@2.1.2: resolution: {integrity: sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==} dev: true @@ -27650,3 +27892,7 @@ packages: dependencies: tslib: 2.5.3 dev: true + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false diff --git a/tsconfig.base.json b/tsconfig.base.json index 06ae37ac3baa9..a5c319d6f1732 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -25,6 +25,8 @@ "@nx/detox": ["packages/detox"], "@nx/devkit": ["packages/devkit"], "@nx/devkit/*": ["packages/devkit/*"], + "@nx/docs": ["docs"], + "@nx/docs/*": ["docs/*"], "@nx/e2e/utils": ["e2e/utils"], "@nx/esbuild": ["packages/esbuild"], "@nx/eslint-plugin": ["packages/eslint-plugin/src"], @@ -45,6 +47,7 @@ "@nx/next/*": ["packages/next/*"], "@nx/node": ["packages/node"], "@nx/node/*": ["packages/node/*"], + "@nx/nx-dev/data-access-ai": ["nx-dev/data-access-ai/src/index.ts"], "@nx/nx-dev/data-access-documents": [ "nx-dev/data-access-documents/src/index.ts" ], @@ -58,6 +61,7 @@ "@nx/nx-dev/data-access-packages/node-only": [ "nx-dev/data-access-packages/src/node.index.ts" ], + "@nx/nx-dev/feature-ai": ["nx-dev/feature-ai/src/index.ts"], "@nx/nx-dev/feature-analytics": ["nx-dev/feature-analytics/src/index.ts"], "@nx/nx-dev/feature-doc-viewer": [ "nx-dev/feature-doc-viewer/src/index.ts" From 1c6a35913056847d6cd673d1dd1fe8bf45e80439 Mon Sep 17 00:00:00 2001 From: Emily Xiong Date: Fri, 14 Jul 2023 01:55:42 -0400 Subject: [PATCH 068/262] chore(core): copy isNxExecutor out of Workspaces class (#17996) --- .../module-federation-dev-server.impl.ts | 15 +- .../module-federation-dev-ssr.impl.ts | 10 +- .../executors/cypress/cypress.impl.spec.ts | 14 +- .../src/executors/cypress/cypress.impl.ts | 9 +- .../src/executors/read-target-options.ts | 8 +- packages/nx/src/adapter/ngcli-adapter.ts | 19 +- .../nx/src/command-line/run/executor-utils.ts | 128 +++++++++++++ packages/nx/src/command-line/run/run.ts | 8 +- packages/nx/src/config/schema-utils.ts | 73 ++++++++ packages/nx/src/config/workspaces.ts | 176 +----------------- packages/nx/src/devkit-internals.ts | 1 + .../nx/src/tasks-runner/batch/run-batch.ts | 5 +- .../src/tasks-runner/tasks-schedule.spec.ts | 41 ++-- packages/nx/src/tasks-runner/utils.ts | 3 +- 14 files changed, 283 insertions(+), 227 deletions(-) create mode 100644 packages/nx/src/command-line/run/executor-utils.ts create mode 100644 packages/nx/src/config/schema-utils.ts diff --git a/packages/angular/src/builders/module-federation-dev-server/module-federation-dev-server.impl.ts b/packages/angular/src/builders/module-federation-dev-server/module-federation-dev-server.impl.ts index c622db524c85e..e36b2839dc903 100644 --- a/packages/angular/src/builders/module-federation-dev-server/module-federation-dev-server.impl.ts +++ b/packages/angular/src/builders/module-federation-dev-server/module-federation-dev-server.impl.ts @@ -1,13 +1,9 @@ import type { Schema } from './schema'; -import { - logger, - readCachedProjectGraph, - workspaceRoot, - Workspaces, -} from '@nx/devkit'; +import { logger, readCachedProjectGraph, workspaceRoot } from '@nx/devkit'; import { scheduleTarget } from 'nx/src/adapter/ngcli-adapter'; import { executeWebpackDevServerBuilder } from '../webpack-dev-server/webpack-dev-server.impl'; import { readProjectsConfigurationFromProjectGraph } from 'nx/src/project-graph/project-graph'; +import { getExecutorInformation } from 'nx/src/command-line/run/executor-utils'; import { getDynamicRemotes, getStaticRemotes, @@ -25,7 +21,6 @@ export function executeModuleFederationDevServerBuilder( const projectGraph = readCachedProjectGraph(); const { projects: workspaceProjects } = readProjectsConfigurationFromProjectGraph(projectGraph); - const ws = new Workspaces(workspaceRoot); const project = workspaceProjects[context.target.project]; let pathToManifestFile = join( @@ -101,7 +96,11 @@ export function executeModuleFederationDevServerBuilder( if (options.verbose) { const [collection, executor] = workspaceProjects[remote].targets[target].executor.split(':'); - const { schema } = ws.readExecutor(collection, executor); + const { schema } = getExecutorInformation( + collection, + executor, + workspaceRoot + ); if (schema.additionalProperties || 'verbose' in schema.properties) { runOptions.verbose = options.verbose; diff --git a/packages/angular/src/builders/module-federation-dev-ssr/module-federation-dev-ssr.impl.ts b/packages/angular/src/builders/module-federation-dev-ssr/module-federation-dev-ssr.impl.ts index 164a7ca002d1d..eb22895a33553 100644 --- a/packages/angular/src/builders/module-federation-dev-ssr/module-federation-dev-ssr.impl.ts +++ b/packages/angular/src/builders/module-federation-dev-ssr/module-federation-dev-ssr.impl.ts @@ -1,6 +1,7 @@ import type { Schema } from './schema'; import { readProjectsConfigurationFromProjectGraph } from 'nx/src/project-graph/project-graph'; -import { readCachedProjectGraph, workspaceRoot, Workspaces } from '@nx/devkit'; +import { getExecutorInformation } from 'nx/src/command-line/run/executor-utils'; +import { readCachedProjectGraph, workspaceRoot } from '@nx/devkit'; import { getDynamicRemotes, getStaticRemotes, @@ -21,7 +22,6 @@ export function executeModuleFederationDevSSRBuilder( const projectGraph = readCachedProjectGraph(); const { projects: workspaceProjects } = readProjectsConfigurationFromProjectGraph(projectGraph); - const ws = new Workspaces(workspaceRoot); const project = workspaceProjects[context.target.project]; let pathToManifestFile = join( @@ -90,7 +90,11 @@ export function executeModuleFederationDevSSRBuilder( if (options.verbose) { const [collection, executor] = workspaceProjects[remote].targets[target].executor.split(':'); - const { schema } = ws.readExecutor(collection, executor); + const { schema } = getExecutorInformation( + collection, + executor, + workspaceRoot + ); if (schema.additionalProperties || 'verbose' in schema.properties) { runOptions.verbose = options.verbose; diff --git a/packages/cypress/src/executors/cypress/cypress.impl.spec.ts b/packages/cypress/src/executors/cypress/cypress.impl.spec.ts index 2b409c4ffeeaf..f60956aa88ca0 100644 --- a/packages/cypress/src/executors/cypress/cypress.impl.spec.ts +++ b/packages/cypress/src/executors/cypress/cypress.impl.spec.ts @@ -1,5 +1,6 @@ import { getTempTailwindPath } from '../../utils/ct-helpers'; import { ExecutorContext, stripIndents } from '@nx/devkit'; +import * as executorUtils from 'nx/src/command-line/run/executor-utils'; import * as path from 'path'; import { installedCypressVersion } from '../../utils/cypress-version'; import cypressExecutor, { CypressExecutorOptions } from './cypress.impl'; @@ -43,9 +44,17 @@ describe('Cypress builder', () => { }, }, } as any; - (devkit as any).readTargetOptions = jest.fn().mockReturnValue({ + jest.spyOn(devkit, 'readTargetOptions').mockReturnValue({ watch: true, }); + jest.spyOn(executorUtils, 'getExecutorInformation').mockReturnValue({ + schema: { properties: {} }, + hasherFactory: jest.fn(), + implementationFactory: jest.fn(), + batchImplementationFactory: jest.fn(), + isNgCompat: true, + isNxExecutor: true, + }); let runExecutor: any; let mockGetTailwindPath: jest.Mock> = getTempTailwindPath as any; @@ -57,9 +66,6 @@ describe('Cypress builder', () => { baseUrl: 'http://localhost:4200', }, ]); - (devkit as any).Workspaces = jest.fn().mockReturnValue({ - readExecutor: () => ({ schema: { properties: {} } }), - }); (devkit as any).stripIndents = (s) => s; (devkit as any).parseTargetString = (s) => { const [project, target, configuration] = s.split(':'); diff --git a/packages/cypress/src/executors/cypress/cypress.impl.ts b/packages/cypress/src/executors/cypress/cypress.impl.ts index b06d265fba87e..27ca6aed51792 100644 --- a/packages/cypress/src/executors/cypress/cypress.impl.ts +++ b/packages/cypress/src/executors/cypress/cypress.impl.ts @@ -5,11 +5,11 @@ import { readTargetOptions, runExecutor, stripIndents, - Workspaces, Target, targetToTargetString, output, } from '@nx/devkit'; +import { getExecutorInformation } from 'nx/src/command-line/run/executor-utils'; import 'dotenv/config'; import { existsSync, readdirSync, unlinkSync, writeFileSync } from 'fs'; import { basename, dirname, join } from 'path'; @@ -421,9 +421,12 @@ ${e.message || e}`); context.projectsConfigurations?.projects?.[target.project]; const targetConfig = projectConfig.targets[target.target]; - const workspace = new Workspaces(context.root); const [collection, executor] = targetConfig.executor.split(':'); - const { schema } = workspace.readExecutor(collection, executor); + const { schema } = getExecutorInformation( + collection, + executor, + context.root + ); // NOTE: schema won't have a default since readTargetOptions would have // already set that and this check wouldn't need to be made diff --git a/packages/devkit/src/executors/read-target-options.ts b/packages/devkit/src/executors/read-target-options.ts index cae627b8c0eba..679848c24ea08 100644 --- a/packages/devkit/src/executors/read-target-options.ts +++ b/packages/devkit/src/executors/read-target-options.ts @@ -4,7 +4,7 @@ import type { ExecutorContext } from 'nx/src/config/misc-interfaces'; import { combineOptionsForExecutor } from 'nx/src/utils/params'; import { requireNx } from '../../nx'; -const { Workspaces } = requireNx(); +const { Workspaces, getExecutorInformation } = requireNx(); /** * Reads and combines options for a given target. @@ -22,7 +22,11 @@ export function readTargetOptions( const ws = new Workspaces(context.root); const [nodeModule, executorName] = targetConfiguration.executor.split(':'); - const { schema } = ws.readExecutor(nodeModule, executorName); + const { schema } = getExecutorInformation( + nodeModule, + executorName, + context.root + ); const defaultProject = ws.calculateDefaultProjectName( context.cwd, diff --git a/packages/nx/src/adapter/ngcli-adapter.ts b/packages/nx/src/adapter/ngcli-adapter.ts index 8c8ba0e8d6697..5bba49270b0da 100644 --- a/packages/nx/src/adapter/ngcli-adapter.ts +++ b/packages/nx/src/adapter/ngcli-adapter.ts @@ -46,7 +46,8 @@ import { toNewFormat, toOldFormat, } from './angular-json'; -import { normalizeExecutorSchema, Workspaces } from '../config/workspaces'; +import { normalizeExecutorSchema } from '../command-line/run/executor-utils'; +import { Workspaces } from '../config/workspaces'; import { CustomHasher, Executor, @@ -55,6 +56,11 @@ import { TaskGraphExecutor, } from '../config/misc-interfaces'; import { readPluginPackageJson } from '../utils/nx-plugin'; +import { + getImplementationFactory, + resolveImplementation, + resolveSchema, +} from '../config/schema-utils'; export async function scheduleTarget( root: string, @@ -106,7 +112,7 @@ export async function scheduleTarget( readJsonFile(executorsFilePath).builders[builderName] .description, optionSchema: builderInfo.schema, - import: this.workspaces['resolveImplementation'].bind(this.workspaces)( + import: resolveImplementation( executorConfig.implementation, dirname(executorsFilePath) ), @@ -153,9 +159,7 @@ export async function scheduleTarget( const { executorsFilePath, executorConfig, isNgCompat } = this.readExecutorsJson(nodeModule, executor); const executorsDir = dirname(executorsFilePath); - const schemaPath = this.workspaces['resolveSchema'].bind( - this.workspaces - )(executorConfig.schema, executorsDir); + const schemaPath = resolveSchema(executorConfig.schema, executorsDir); const schema = normalizeExecutorSchema(readJsonFile(schemaPath)); const implementationFactory = this.getImplementationFactory( @@ -195,10 +199,7 @@ export async function scheduleTarget( implementation: string, executorsDir: string ): () => T { - return this.workspaces['getImplementationFactory'].bind(this.workspaces)( - implementation, - executorsDir - ); + return getImplementationFactory(implementation, executorsDir); } } diff --git a/packages/nx/src/command-line/run/executor-utils.ts b/packages/nx/src/command-line/run/executor-utils.ts new file mode 100644 index 0000000000000..08f016021e63a --- /dev/null +++ b/packages/nx/src/command-line/run/executor-utils.ts @@ -0,0 +1,128 @@ +import { dirname, join } from 'path'; + +import { readPluginPackageJson } from '../../utils/nx-plugin'; +import { + CustomHasher, + Executor, + ExecutorConfig, + ExecutorsJson, + TaskGraphExecutor, +} from '../../config/misc-interfaces'; +import { readJsonFile } from '../../utils/fileutils'; +import { + getImplementationFactory, + resolveSchema, +} from '../../config/schema-utils'; +import { getNxRequirePaths } from '../../utils/installation-directory'; + +export function normalizeExecutorSchema( + schema: Partial +): ExecutorConfig['schema'] { + const version = (schema.version ??= 1); + return { + version, + outputCapture: + schema.outputCapture ?? version < 2 ? 'direct-nodejs' : 'pipe', + properties: + !schema.properties || typeof schema.properties !== 'object' + ? {} + : schema.properties, + ...schema, + }; +} + +export function getExecutorInformation( + nodeModule: string, + executor: string, + root: string +): ExecutorConfig & { isNgCompat: boolean; isNxExecutor: boolean } { + try { + const { executorsFilePath, executorConfig, isNgCompat } = readExecutorsJson( + nodeModule, + executor, + root + ); + const executorsDir = dirname(executorsFilePath); + const schemaPath = resolveSchema(executorConfig.schema, executorsDir); + const schema = normalizeExecutorSchema(readJsonFile(schemaPath)); + + const implementationFactory = getImplementationFactory( + executorConfig.implementation, + executorsDir + ); + + const batchImplementationFactory = executorConfig.batchImplementation + ? getImplementationFactory( + executorConfig.batchImplementation, + executorsDir + ) + : null; + + const hasherFactory = executorConfig.hasher + ? getImplementationFactory( + executorConfig.hasher, + executorsDir + ) + : null; + + return { + schema, + implementationFactory, + batchImplementationFactory, + hasherFactory, + isNgCompat, + isNxExecutor: !isNgCompat, + }; + } catch (e) { + throw new Error( + `Unable to resolve ${nodeModule}:${executor}.\n${e.message}` + ); + } +} + +function readExecutorsJson( + nodeModule: string, + executor: string, + root: string +): { + executorsFilePath: string; + executorConfig: { + implementation: string; + batchImplementation?: string; + schema: string; + hasher?: string; + }; + isNgCompat: boolean; +} { + const { json: packageJson, path: packageJsonPath } = readPluginPackageJson( + nodeModule, + root + ? [root, __dirname, process.cwd(), ...getNxRequirePaths()] + : [__dirname, process.cwd(), ...getNxRequirePaths()] + ); + const executorsFile = packageJson.executors ?? packageJson.builders; + + if (!executorsFile) { + throw new Error( + `The "${nodeModule}" package does not support Nx executors.` + ); + } + + const executorsFilePath = require.resolve( + join(dirname(packageJsonPath), executorsFile) + ); + const executorsJson = readJsonFile(executorsFilePath); + const executorConfig: { + implementation: string; + batchImplementation?: string; + schema: string; + hasher?: string; + } = executorsJson.executors?.[executor] || executorsJson.builders?.[executor]; + if (!executorConfig) { + throw new Error( + `Cannot find executor '${executor}' in ${executorsFilePath}.` + ); + } + const isNgCompat = !executorsJson.executors?.[executor]; + return { executorsFilePath, executorConfig, isNgCompat }; +} diff --git a/packages/nx/src/command-line/run/run.ts b/packages/nx/src/command-line/run/run.ts index 751350798fa00..e6fd53a211b5b 100644 --- a/packages/nx/src/command-line/run/run.ts +++ b/packages/nx/src/command-line/run/run.ts @@ -32,6 +32,7 @@ import { getLastValueFromAsyncIterableIterator, isAsyncIterator, } from '../../utils/async-iterator'; +import { getExecutorInformation } from './executor-utils'; export interface Target { project: string; @@ -131,9 +132,10 @@ async function parseExecutorAndTarget( } const [nodeModule, executor] = targetConfig.executor.split(':'); - const { schema, implementationFactory } = ws.readExecutor( + const { schema, implementationFactory } = getExecutorInformation( nodeModule, - executor + executor, + root ); return { executor, implementationFactory, nodeModule, schema, targetConfig }; @@ -195,7 +197,7 @@ async function runExecutorInternal( isVerbose ); - if (ws.isNxExecutor(nodeModule, executor)) { + if (getExecutorInformation(nodeModule, executor, root).isNxExecutor) { const implementation = implementationFactory() as Executor; const r = implementation(combinedOptions, { root, diff --git a/packages/nx/src/config/schema-utils.ts b/packages/nx/src/config/schema-utils.ts new file mode 100644 index 0000000000000..6c92129a643d7 --- /dev/null +++ b/packages/nx/src/config/schema-utils.ts @@ -0,0 +1,73 @@ +import { existsSync } from 'fs'; +import { extname, join } from 'path'; +import { registerPluginTSTranspiler } from '../utils/nx-plugin'; + +/** + * This function is used to get the implementation factory of an executor or generator. + * @param implementation path to the implementation + * @param directory path to the directory + * @returns a function that returns the implementation + */ +export function getImplementationFactory( + implementation: string, + directory: string +): () => T { + const [implementationModulePath, implementationExportName] = + implementation.split('#'); + return () => { + const modulePath = resolveImplementation( + implementationModulePath, + directory + ); + if (extname(modulePath) === '.ts') { + registerPluginTSTranspiler(); + } + const module = require(modulePath); + return implementationExportName + ? module[implementationExportName] + : module.default ?? module; + }; +} + +/** + * This function is used to resolve the implementation of an executor or generator. + * @param implementationModulePath + * @param directory + * @returns path to the implementation + */ +export function resolveImplementation( + implementationModulePath: string, + directory: string +): string { + const validImplementations = ['', '.js', '.ts'].map( + (x) => implementationModulePath + x + ); + + for (const maybeImplementation of validImplementations) { + const maybeImplementationPath = join(directory, maybeImplementation); + if (existsSync(maybeImplementationPath)) { + return maybeImplementationPath; + } + + try { + return require.resolve(maybeImplementation, { + paths: [directory], + }); + } catch {} + } + + throw new Error( + `Could not resolve "${implementationModulePath}" from "${directory}".` + ); +} + +export function resolveSchema(schemaPath: string, directory: string): string { + const maybeSchemaPath = join(directory, schemaPath); + if (existsSync(maybeSchemaPath)) { + return maybeSchemaPath; + } + + return require.resolve(schemaPath, { + paths: [directory], + }); +} diff --git a/packages/nx/src/config/workspaces.ts b/packages/nx/src/config/workspaces.ts index acb529bd28e3d..93ff3efca1622 100644 --- a/packages/nx/src/config/workspaces.ts +++ b/packages/nx/src/config/workspaces.ts @@ -1,7 +1,7 @@ import { sync as globSync } from 'fast-glob'; -import { existsSync, readFileSync } from 'fs'; +import { existsSync } from 'fs'; import * as path from 'path'; -import { basename, dirname, extname, join } from 'path'; +import { basename, dirname, join } from 'path'; import { performance } from 'perf_hooks'; import { workspaceRoot } from '../utils/workspace-root'; import { readJsonFile, readYamlFile } from '../utils/fileutils'; @@ -10,7 +10,6 @@ import { loadNxPlugins, loadNxPluginsSync, readPluginPackageJson, - registerPluginTSTranspiler, } from '../utils/nx-plugin'; import type { NxJsonConfiguration, TargetDefaults } from './nx-json'; @@ -20,14 +19,9 @@ import { TargetConfiguration, } from './workspace-json-project-json'; import { - CustomHasher, - Executor, - ExecutorConfig, - ExecutorsJson, Generator, GeneratorsJson, GeneratorsJsonEntry, - TaskGraphExecutor, } from './misc-interfaces'; import { PackageJson } from '../utils/package-json'; import { output } from '../utils/output'; @@ -42,6 +36,7 @@ import { findProjectForPath, normalizeProjectRoot, } from '../project-graph/utils/find-project-for-path'; +import { getImplementationFactory, resolveSchema } from './schema-utils'; export class Workspaces { private cachedProjectsConfig: ProjectsConfigurations; @@ -169,61 +164,10 @@ export class Workspaces { return projects; } - isNxExecutor(nodeModule: string, executor: string) { - return !this.readExecutor(nodeModule, executor).isNgCompat; - } - isNxGenerator(collectionName: string, generatorName: string) { return !this.readGenerator(collectionName, generatorName).isNgCompat; } - readExecutor( - nodeModule: string, - executor: string - ): ExecutorConfig & { isNgCompat: boolean } { - try { - const { executorsFilePath, executorConfig, isNgCompat } = - this.readExecutorsJson(nodeModule, executor); - const executorsDir = path.dirname(executorsFilePath); - const schemaPath = this.resolveSchema( - executorConfig.schema, - executorsDir - ); - const schema = normalizeExecutorSchema(readJsonFile(schemaPath)); - - const implementationFactory = this.getImplementationFactory( - executorConfig.implementation, - executorsDir - ); - - const batchImplementationFactory = executorConfig.batchImplementation - ? this.getImplementationFactory( - executorConfig.batchImplementation, - executorsDir - ) - : null; - - const hasherFactory = executorConfig.hasher - ? this.getImplementationFactory( - executorConfig.hasher, - executorsDir - ) - : null; - - return { - schema, - implementationFactory, - batchImplementationFactory, - hasherFactory, - isNgCompat, - }; - } catch (e) { - throw new Error( - `Unable to resolve ${nodeModule}:${executor}.\n${e.message}` - ); - } - } - readGenerator( collectionName: string, generatorName: string @@ -251,17 +195,14 @@ export class Workspaces { generatorsJson.generators?.[normalizedGeneratorName] || generatorsJson.schematics?.[normalizedGeneratorName]; const isNgCompat = !generatorsJson.generators?.[normalizedGeneratorName]; - const schemaPath = this.resolveSchema( - generatorConfig.schema, - generatorsDir - ); + const schemaPath = resolveSchema(generatorConfig.schema, generatorsDir); const schema = readJsonFile(schemaPath); if (!schema.properties || typeof schema.properties !== 'object') { schema.properties = {}; } generatorConfig.implementation = generatorConfig.implementation || generatorConfig.factory; - const implementationFactory = this.getImplementationFactory( + const implementationFactory = getImplementationFactory( generatorConfig.implementation, generatorsDir ); @@ -322,97 +263,6 @@ export class Workspaces { } } - private getImplementationFactory( - implementation: string, - directory: string - ): () => T { - const [implementationModulePath, implementationExportName] = - implementation.split('#'); - return () => { - const modulePath = this.resolveImplementation( - implementationModulePath, - directory - ); - if (extname(modulePath) === '.ts') { - registerPluginTSTranspiler(); - } - const module = require(modulePath); - return implementationExportName - ? module[implementationExportName] - : module.default ?? module; - }; - } - - private resolveSchema(schemaPath: string, directory: string): string { - const maybeSchemaPath = join(directory, schemaPath); - if (existsSync(maybeSchemaPath)) { - return maybeSchemaPath; - } - - return require.resolve(schemaPath, { - paths: [directory], - }); - } - - private resolveImplementation( - implementationModulePath: string, - directory: string - ): string { - const validImplementations = ['', '.js', '.ts'].map( - (x) => implementationModulePath + x - ); - - for (const maybeImplementation of validImplementations) { - const maybeImplementationPath = join(directory, maybeImplementation); - if (existsSync(maybeImplementationPath)) { - return maybeImplementationPath; - } - - try { - return require.resolve(maybeImplementation, { - paths: [directory], - }); - } catch {} - } - - throw new Error( - `Could not resolve "${implementationModulePath}" from "${directory}".` - ); - } - - private readExecutorsJson(nodeModule: string, executor: string) { - const { json: packageJson, path: packageJsonPath } = readPluginPackageJson( - nodeModule, - this.resolvePaths() - ); - const executorsFile = packageJson.executors ?? packageJson.builders; - - if (!executorsFile) { - throw new Error( - `The "${nodeModule}" package does not support Nx executors.` - ); - } - - const executorsFilePath = require.resolve( - path.join(path.dirname(packageJsonPath), executorsFile) - ); - const executorsJson = readJsonFile(executorsFilePath); - const executorConfig: { - implementation: string; - batchImplementation?: string; - schema: string; - hasher?: string; - } = - executorsJson.executors?.[executor] || executorsJson.builders?.[executor]; - if (!executorConfig) { - throw new Error( - `Cannot find executor '${executor}' in ${executorsFilePath}.` - ); - } - const isNgCompat = !executorsJson.executors?.[executor]; - return { executorsFilePath, executorConfig, isNgCompat }; - } - private readGeneratorsJson( collectionName: string, generator: string @@ -485,22 +335,6 @@ function findMatchingProjectInCwd( return matchingProject; } -export function normalizeExecutorSchema( - schema: Partial -): ExecutorConfig['schema'] { - const version = (schema.version ??= 1); - return { - version, - outputCapture: - schema.outputCapture ?? version < 2 ? 'direct-nodejs' : 'pipe', - properties: - !schema.properties || typeof schema.properties !== 'object' - ? {} - : schema.properties, - ...schema, - }; -} - function findFullGeneratorName( name: string, generators: { diff --git a/packages/nx/src/devkit-internals.ts b/packages/nx/src/devkit-internals.ts index fca393f59c319..3e704825dcaeb 100644 --- a/packages/nx/src/devkit-internals.ts +++ b/packages/nx/src/devkit-internals.ts @@ -4,3 +4,4 @@ * These may not be available in certain version of Nx, so be sure to check them first. */ export { createTempNpmDirectory } from './utils/package-manager'; +export { getExecutorInformation } from './command-line/run/executor-utils'; diff --git a/packages/nx/src/tasks-runner/batch/run-batch.ts b/packages/nx/src/tasks-runner/batch/run-batch.ts index 391fa062c2d04..e286a952dbe05 100644 --- a/packages/nx/src/tasks-runner/batch/run-batch.ts +++ b/packages/nx/src/tasks-runner/batch/run-batch.ts @@ -5,7 +5,6 @@ import { CompleteTaskMessage, BatchResults, } from './batch-messages'; -import { Workspaces } from '../../config/workspaces'; import { workspaceRoot } from '../../utils/workspace-root'; import { combineOptionsForExecutor } from '../../utils/params'; import { TaskGraph } from '../../config/task-graph'; @@ -16,11 +15,11 @@ import { } from '../../project-graph/project-graph'; import { readNxJson } from '../../config/configuration'; import { isAsyncIterator } from '../../utils/async-iterator'; +import { getExecutorInformation } from '../../command-line/run/executor-utils'; function getBatchExecutor(executorName: string) { - const workspace = new Workspaces(workspaceRoot); const [nodeModule, exportName] = executorName.split(':'); - return workspace.readExecutor(nodeModule, exportName); + return getExecutorInformation(nodeModule, exportName, workspaceRoot); } async function runTasks( diff --git a/packages/nx/src/tasks-runner/tasks-schedule.spec.ts b/packages/nx/src/tasks-runner/tasks-schedule.spec.ts index cdeaed60cf84a..9114a2b3aa682 100644 --- a/packages/nx/src/tasks-runner/tasks-schedule.spec.ts +++ b/packages/nx/src/tasks-runner/tasks-schedule.spec.ts @@ -3,6 +3,7 @@ import { Workspaces } from '../config/workspaces'; import { removeTasksFromTaskGraph } from './utils'; import { Task, TaskGraph } from '../config/task-graph'; import { DependencyType, ProjectGraph } from '../config/project-graph'; +import * as executorUtils from '../command-line/run/executor-utils'; function createMockTask(id: string): Task { const [project, target] = id.split(':'); @@ -43,20 +44,20 @@ describe('TasksSchedule', () => { roots: ['lib1:build', 'app2:build'], }; const workspace: Partial = { - readExecutor() { - return { - schema: { - version: 2, - properties: {}, - }, - implementationFactory: jest.fn(), - batchImplementationFactory: jest.fn(), - } as any; - }, readNxJson() { return {}; }, }; + jest.spyOn(executorUtils, 'getExecutorInformation').mockReturnValue({ + schema: { + version: 2, + properties: {}, + }, + implementationFactory: jest.fn(), + batchImplementationFactory: jest.fn(), + isNgCompat: true, + isNxExecutor: true, + }); const projectGraph: ProjectGraph = { nodes: { @@ -269,20 +270,20 @@ describe('TasksSchedule', () => { roots: ['app1:test', 'app2:test', 'lib1:test'], }; const workspace: Partial = { - readExecutor() { - return { - schema: { - version: 2, - properties: {}, - }, - implementationFactory: jest.fn(), - batchImplementationFactory: jest.fn(), - } as any; - }, readNxJson() { return {}; }, }; + jest.spyOn(executorUtils, 'getExecutorInformation').mockReturnValue({ + schema: { + version: 2, + properties: {}, + }, + implementationFactory: jest.fn(), + batchImplementationFactory: jest.fn(), + isNgCompat: true, + isNxExecutor: true, + }); const projectGraph: ProjectGraph = { nodes: { diff --git a/packages/nx/src/tasks-runner/utils.ts b/packages/nx/src/tasks-runner/utils.ts index c083ae9dc8153..b39f139c79a17 100644 --- a/packages/nx/src/tasks-runner/utils.ts +++ b/packages/nx/src/tasks-runner/utils.ts @@ -16,6 +16,7 @@ import { joinPathFragments } from '../utils/path'; import { isRelativePath } from '../utils/fileutils'; import { serializeOverridesIntoCommandLine } from '../utils/serialize-overrides-into-command-line'; import { splitByColons, splitTarget } from '../utils/split-target'; +import { getExecutorInformation } from '../command-line/run/executor-utils'; export function getCommandAsString(execCommand: string, task: Task) { const args = getPrintableCommandArgsForTask(task); @@ -250,7 +251,7 @@ export async function getExecutorForTask( const executor = await getExecutorNameForTask(task, projectGraph); const [nodeModule, executorName] = executor.split(':'); - return workspace.readExecutor(nodeModule, executorName); + return getExecutorInformation(nodeModule, executorName, workspaceRoot); } export async function getCustomHasher( From 4f9f04fb96a5fc62a40d3f8a808600bf8a91d715 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leosvel=20P=C3=A9rez=20Espinosa?= Date: Fri, 14 Jul 2023 08:41:40 +0100 Subject: [PATCH 069/262] docs(js): add docs about @nx/js:tsc batch execution (#18071) --- docs/generated/packages/js/executors/tsc.json | 2 +- docs/shared/incremental-builds.md | 24 +++++++++++++- packages/js/docs/tsc-examples.md | 32 +++++++++++++++++++ 3 files changed, 56 insertions(+), 2 deletions(-) diff --git a/docs/generated/packages/js/executors/tsc.json b/docs/generated/packages/js/executors/tsc.json index f69b076c19cb5..0f3d35f73e4cb 100644 --- a/docs/generated/packages/js/executors/tsc.json +++ b/docs/generated/packages/js/executors/tsc.json @@ -174,7 +174,7 @@ ] } }, - "examplesFile": "## Examples\n\n{% tabs %}\n{% tab label=\"Using TypeScript Transformer Plugins\" %}\n\n`@nx/js:tsc` can run the [TypeScript Transformers](https://github.com/madou/typescript-transformer-handbook) by using the `transformers` option.\n\n```json {% fileName=\"libs/ts-lib/project.json\" %}\n{\n \"build\": {\n \"executor\": \"@nx/js:tsc\",\n \"options\": {\n \"outputPath\": \"dist/libs/ts-lib\",\n \"main\": \"libs/ts-lib/src/index.ts\",\n \"tsConfig\": \"libs/ts-lib/tsconfig.lib.json\",\n \"assets\": [\"libs/ts-lib/*.md\"],\n \"transformers\": [\n \"@nestjs/swagger/plugin\",\n {\n \"name\": \"@automapper/classes/transformer-plugin\",\n \"options\": {}\n }\n ]\n }\n }\n}\n```\n\n{% /tab %}\n{% tab label=\"Inline libraries\" %}\n\n`@nx/js:tsc` can inline non-buildable libraries by opt-in to **Inlining** mode with `external` option.\n\n```json {% fileName=\"libs/ts-lib/project.json\" %}\n{\n \"build\": {\n \"executor\": \"@nx/js:tsc\",\n \"options\": {\n \"outputPath\": \"dist/libs/ts-lib\",\n \"main\": \"libs/ts-lib/src/index.ts\",\n \"tsConfig\": \"libs/ts-lib/tsconfig.lib.json\",\n \"assets\": [\"libs/ts-lib/*.md\"],\n \"external\": \"all\"\n }\n }\n}\n```\n\n```shell\nnpx nx build ts-lib --external=all\n```\n\n`@nx/js:tsc` can also inline buildable libraries by setting `external: 'none'`\n\n```json {% fileName=\"libs/ts-lib/project.json\" %}\n{\n \"build\": {\n \"executor\": \"@nx/js:tsc\",\n \"options\": {\n \"outputPath\": \"dist/libs/ts-lib\",\n \"main\": \"libs/ts-lib/src/index.ts\",\n \"tsConfig\": \"libs/ts-lib/tsconfig.lib.json\",\n \"assets\": [\"libs/ts-lib/*.md\"],\n \"external\": \"none\"\n }\n }\n}\n```\n\n```shell\nnpx nx build ts-lib --external=none\n```\n\n{% /tab %}\n{% /tabs %}\n", + "examplesFile": "## Examples\n\n{% tabs %}\n{% tab label=\"Using TypeScript Transformer Plugins\" %}\n\n`@nx/js:tsc` can run the [TypeScript Transformers](https://github.com/madou/typescript-transformer-handbook) by using the `transformers` option.\n\n```json {% fileName=\"libs/ts-lib/project.json\" %}\n{\n \"build\": {\n \"executor\": \"@nx/js:tsc\",\n \"options\": {\n \"outputPath\": \"dist/libs/ts-lib\",\n \"main\": \"libs/ts-lib/src/index.ts\",\n \"tsConfig\": \"libs/ts-lib/tsconfig.lib.json\",\n \"assets\": [\"libs/ts-lib/*.md\"],\n \"transformers\": [\n \"@nestjs/swagger/plugin\",\n {\n \"name\": \"@automapper/classes/transformer-plugin\",\n \"options\": {}\n }\n ]\n }\n }\n}\n```\n\n{% /tab %}\n{% tab label=\"Inline libraries\" %}\n\n`@nx/js:tsc` can inline non-buildable libraries by opt-in to **Inlining** mode with `external` option.\n\n```json {% fileName=\"libs/ts-lib/project.json\" %}\n{\n \"build\": {\n \"executor\": \"@nx/js:tsc\",\n \"options\": {\n \"outputPath\": \"dist/libs/ts-lib\",\n \"main\": \"libs/ts-lib/src/index.ts\",\n \"tsConfig\": \"libs/ts-lib/tsconfig.lib.json\",\n \"assets\": [\"libs/ts-lib/*.md\"],\n \"external\": \"all\"\n }\n }\n}\n```\n\n```shell\nnpx nx build ts-lib --external=all\n```\n\n`@nx/js:tsc` can also inline buildable libraries by setting `external: 'none'`\n\n```json {% fileName=\"libs/ts-lib/project.json\" %}\n{\n \"build\": {\n \"executor\": \"@nx/js:tsc\",\n \"options\": {\n \"outputPath\": \"dist/libs/ts-lib\",\n \"main\": \"libs/ts-lib/src/index.ts\",\n \"tsConfig\": \"libs/ts-lib/tsconfig.lib.json\",\n \"assets\": [\"libs/ts-lib/*.md\"],\n \"external\": \"none\"\n }\n }\n}\n```\n\n```shell\nnpx nx build ts-lib --external=none\n```\n\n{% /tab %}\n{% tab label=\"Batch mode execution\" %}\n\nThe `@nx/js:tsc` executor supports running multiple tasks in a single process. When running in batch mode, the executor uses the [TypeScript APIs for incremental builds](https://www.typescriptlang.org/docs/handbook/project-references.html#build-mode-for-typescript). This results in a much faster build time when compared to the default implementation (the bigger the task graph to run, the more the performance improvements).\n\n{% callout type=\"warning\" title=\"Experimental feature\" %}\nExecuting tasks in batch mode is an experimental feature.\n{% /callout %}\n\nTo run your builds using the batch implementation, set the `NX_BATCH_MODE` environment variable to `true`:\n\n```shell\nNX_BATCH_MODE=true nx build ts-lib\n```\n\nFor optimal performance, you could set the `clean` option to `false`. Otherwise, the executor cleans the output folder before running the build, which results in the loss of the [`.tsbuildinfo` file](https://www.typescriptlang.org/tsconfig/#tsBuildInfoFile) and, consequently, the loss of important optimizations performed by TypeScript. This is not a requirement. Even if the `clean` option is not set to `false` there are other important optimizations that are performed by the batch implementation.\n\n```json {% fileName=\"libs/ts-lib/project.json\" %}\n{\n \"build\": {\n \"executor\": \"@nx/js:tsc\",\n \"options\": {\n \"outputPath\": \"dist/libs/ts-lib\",\n \"main\": \"libs/ts-lib/src/index.ts\",\n \"tsConfig\": \"libs/ts-lib/tsconfig.lib.json\",\n \"assets\": [\"libs/ts-lib/*.md\"],\n \"clean\": false\n }\n }\n}\n```\n\n{% /tab %}\n{% /tabs %}\n", "presets": [] }, "description": "Build a project using TypeScript.", diff --git a/docs/shared/incremental-builds.md b/docs/shared/incremental-builds.md index 087017fc4ddf6..fb54676b792dc 100644 --- a/docs/shared/incremental-builds.md +++ b/docs/shared/incremental-builds.md @@ -66,7 +66,29 @@ The downsides of incremental builds: If you are only planning to use incremental builds to speed up your CI, then the watch mode concern is irrelevant, and the only thing you need to assess is whether the benefits of skipping the compilation outweigh the costs of initializing the TypeScript compiler several times. -## Custom Serve Target +## Using the @nx/js:tsc Batch Implementation + +{% callout type="check" title="Available since Nx 16.5.0" %} +The `@nx/js:tsc` batch implementation was introduced in Nx **16.5.0**. +{% /callout %} + +If you're using the `@nx/js:tsc` to build your projects, you can opt-in to use its batch implementation. The batch implementation uses the [TypeScript APIs for incremental builds](https://www.typescriptlang.org/docs/handbook/project-references.html#build-mode-for-typescript) and batches the execution of the tasks into a single process. This results in a much faster build time when compared to the default implementation (the bigger the task graph to run, the more the performance improvements). + +{% callout type="warning" title="Experimental feature" %} +Executing tasks in batch mode is an experimental feature. +{% /callout %} + +To run your builds using the batch implementation, set the `NX_BATCH_MODE` environment variable to `true`: + +```shell +NX_BATCH_MODE=true nx build my-project +``` + +For optimal performance, you could set the `clean` option to `false`. Otherwise, the executor cleans the output folder before running the build, which results in the loss of the [`.tsbuildinfo` file](https://www.typescriptlang.org/tsconfig/#tsBuildInfoFile) and, consequently, the loss of important optimizations performed by TypeScript. This is not a requirement. Even if the `clean` option is not set to `false` there are other important optimizations that are performed by the batch implementation. + +You can get a sense of the performance improvements over using the `@nx/js:tsc` default implementation in the following example repository: https://github.com/nrwl/large-ts-monorepo. + +## Custom Serve Target with Webpack If you are implementing a custom serve command, you can use `WebpackNxBuildCoordinationPlugin` provided by `@nx/webpack`. It's a webpack plugin you can use to coordinate the compiling of the libs and the webpack linking. diff --git a/packages/js/docs/tsc-examples.md b/packages/js/docs/tsc-examples.md index 824e4a890d82c..0d872d8a53524 100644 --- a/packages/js/docs/tsc-examples.md +++ b/packages/js/docs/tsc-examples.md @@ -71,5 +71,37 @@ npx nx build ts-lib --external=all npx nx build ts-lib --external=none ``` +{% /tab %} +{% tab label="Batch mode execution" %} + +The `@nx/js:tsc` executor supports running multiple tasks in a single process. When running in batch mode, the executor uses the [TypeScript APIs for incremental builds](https://www.typescriptlang.org/docs/handbook/project-references.html#build-mode-for-typescript). This results in a much faster build time when compared to the default implementation (the bigger the task graph to run, the more the performance improvements). + +{% callout type="warning" title="Experimental feature" %} +Executing tasks in batch mode is an experimental feature. +{% /callout %} + +To run your builds using the batch implementation, set the `NX_BATCH_MODE` environment variable to `true`: + +```shell +NX_BATCH_MODE=true nx build ts-lib +``` + +For optimal performance, you could set the `clean` option to `false`. Otherwise, the executor cleans the output folder before running the build, which results in the loss of the [`.tsbuildinfo` file](https://www.typescriptlang.org/tsconfig/#tsBuildInfoFile) and, consequently, the loss of important optimizations performed by TypeScript. This is not a requirement. Even if the `clean` option is not set to `false` there are other important optimizations that are performed by the batch implementation. + +```json {% fileName="libs/ts-lib/project.json" %} +{ + "build": { + "executor": "@nx/js:tsc", + "options": { + "outputPath": "dist/libs/ts-lib", + "main": "libs/ts-lib/src/index.ts", + "tsConfig": "libs/ts-lib/tsconfig.lib.json", + "assets": ["libs/ts-lib/*.md"], + "clean": false + } + } +} +``` + {% /tab %} {% /tabs %} From b61373a30ffe3a2bd8ae4566aa120b29814cd075 Mon Sep 17 00:00:00 2001 From: Jonathan Cammisuli Date: Fri, 14 Jul 2023 10:44:05 -0400 Subject: [PATCH 070/262] fix(core): remove `fatal: no path specified` logs from daemon (#18117) --- .../daemon/server/project-graph-incremental-recomputation.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/nx/src/daemon/server/project-graph-incremental-recomputation.ts b/packages/nx/src/daemon/server/project-graph-incremental-recomputation.ts index 3627baeb287d2..b8e86f96b18bf 100644 --- a/packages/nx/src/daemon/server/project-graph-incremental-recomputation.ts +++ b/packages/nx/src/daemon/server/project-graph-incremental-recomputation.ts @@ -137,6 +137,10 @@ function computeWorkspaceConfigHash( * TODO(Cammisuli): remove after 16.4 - Rust watcher handles nested gitignores */ function filterUpdatedFiles(files: string[]) { + if (files.length === 0) { + return files; + } + try { const quoted = files.map((f) => '"' + f + '"'); const ignored = execSync(`git check-ignore ${quoted.join(' ')}`, { From 2a888ad2dfa03b3230c618ec6da983a61e231b75 Mon Sep 17 00:00:00 2001 From: Katerina Skroumpelou Date: Fri, 14 Jul 2023 17:44:36 +0300 Subject: [PATCH 071/262] fix(storybook): install core-js for non-vite libs (#18115) --- .../storybook-configuration/configuration.ts | 16 +++++++--------- .../configuration/configuration.spec.ts | 8 ++++++++ .../generators/configuration/configuration.ts | 8 ++++++++ packages/storybook/src/utils/versions.ts | 2 ++ 4 files changed, 25 insertions(+), 9 deletions(-) diff --git a/packages/react/src/generators/storybook-configuration/configuration.ts b/packages/react/src/generators/storybook-configuration/configuration.ts index 1469fe73b8983..be92e63c057d6 100644 --- a/packages/react/src/generators/storybook-configuration/configuration.ts +++ b/packages/react/src/generators/storybook-configuration/configuration.ts @@ -41,15 +41,16 @@ export async function storybookConfigurationGenerator( typeof import('@nx/storybook') >('@nx/storybook', nxVersion); - let bundler = 'vite'; + let uiFramework = '@storybook/react-vite'; const projectConfig = readProjectConfiguration(host, schema.name); if ( - projectConfig.projectType === 'application' && - (projectConfig.targets['build']?.executor === '@nx/webpack:webpack' || - projectConfig.targets['build']?.executor === '@nrwl/webpack:webpack') + projectConfig.targets['build']?.executor === '@nx/webpack:webpack' || + projectConfig.targets['build']?.executor === '@nrwl/webpack:webpack' || + projectConfig.targets['build']?.executor === '@nx/rollup:rollup' || + projectConfig.targets['build']?.executor === '@nrwl/rollup:rollup' ) { - bundler = 'webpack'; + uiFramework = '@storybook/react-webpack5'; } const installTask = await configurationGenerator(host, { @@ -61,10 +62,7 @@ export async function storybookConfigurationGenerator( tsConfiguration: schema.tsConfiguration ?? true, // default is true interactionTests: schema.interactionTests ?? true, // default is true configureStaticServe: schema.configureStaticServe, - uiFramework: - bundler === 'vite' - ? '@storybook/react-vite' - : '@storybook/react-webpack5', + uiFramework: uiFramework as any, // cannot import UiFramework7 type dynamically skipFormat: true, }); diff --git a/packages/storybook/src/generators/configuration/configuration.spec.ts b/packages/storybook/src/generators/configuration/configuration.spec.ts index 96c34ec3b37ef..681ddb8ec20b1 100644 --- a/packages/storybook/src/generators/configuration/configuration.spec.ts +++ b/packages/storybook/src/generators/configuration/configuration.spec.ts @@ -166,6 +166,10 @@ describe('@nx/storybook:configuration for Storybook v7', () => { expect( tree.read('libs/test-ui-lib2/tsconfig.storybook.json', 'utf-8') ).toMatchSnapshot(); + + expect( + readJson(tree, 'package.json').devDependencies['core-js'] + ).toBeTruthy(); }); it('should generate TS config for project if tsConfiguration true', async () => { @@ -197,6 +201,10 @@ describe('@nx/storybook:configuration for Storybook v7', () => { readJson(tree, 'package.json').devDependencies['@storybook/test-runner'] ).toBeTruthy(); + expect( + readJson(tree, 'package.json').devDependencies['core-js'] + ).toBeTruthy(); + expect( readJson(tree, 'package.json').devDependencies[ '@storybook/testing-library' diff --git a/packages/storybook/src/generators/configuration/configuration.ts b/packages/storybook/src/generators/configuration/configuration.ts index 3afadb47c69ee..1465d010bece2 100644 --- a/packages/storybook/src/generators/configuration/configuration.ts +++ b/packages/storybook/src/generators/configuration/configuration.ts @@ -35,6 +35,7 @@ import { storybookMajorVersion, } from '../../utils/utilities'; import { + coreJsVersion, nxVersion, storybookJestVersion, storybookTestingLibraryVersion, @@ -191,6 +192,13 @@ export async function configurationGenerator( devDeps['@nx/web'] = nxVersion; } + if ( + projectType !== 'application' && + schema.uiFramework === '@storybook/react-webpack5' + ) { + devDeps['core-js'] = coreJsVersion; + } + tasks.push(addDependenciesToPackageJson(tree, {}, devDeps)); if (!schema.skipFormat) { diff --git a/packages/storybook/src/utils/versions.ts b/packages/storybook/src/utils/versions.ts index e62270f770354..06bcac3a97721 100644 --- a/packages/storybook/src/utils/versions.ts +++ b/packages/storybook/src/utils/versions.ts @@ -10,3 +10,5 @@ export const tsNodeVersion = '10.9.1'; export const storybookVersion = '^7.0.24'; export const reactVersion = '^18.2.0'; export const viteVersion = '~4.3.9'; + +export const coreJsVersion = '^3.6.5'; From 5221cba645446166aaadbae6aa05d00deae4e6fb Mon Sep 17 00:00:00 2001 From: Jonathan Cammisuli Date: Fri, 14 Jul 2023 10:50:55 -0400 Subject: [PATCH 072/262] chore(core): improve watch e2e test for macos (#18086) --- e2e/nx-misc/src/watch.test.ts | 69 ++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 30 deletions(-) diff --git a/e2e/nx-misc/src/watch.test.ts b/e2e/nx-misc/src/watch.test.ts index 3729923eab48f..c38ce31bbc89e 100644 --- a/e2e/nx-misc/src/watch.test.ts +++ b/e2e/nx-misc/src/watch.test.ts @@ -1,6 +1,5 @@ import { cleanupProject, - createFile, newProject, runCLI, uniq, @@ -10,13 +9,23 @@ import { isVerboseE2ERun, } from '@nx/e2e/utils'; import { spawn } from 'child_process'; +import { join } from 'path'; +import { writeFileSync } from 'fs'; + +async function writeFileForWatcher(path: string, content: string) { + const e2ePath = join(tmpProjPath(), path); + + console.log(`writing to: ${e2ePath}`); + writeFileSync(e2ePath, content); + await wait(10); +} describe('Nx Commands', () => { let proj1 = uniq('proj1'); let proj2 = uniq('proj2'); let proj3 = uniq('proj3'); beforeAll(() => { - newProject({ packageManager: 'npm' }); + newProject(); runCLI(`generate @nx/js:lib ${proj1}`); runCLI(`generate @nx/js:lib ${proj2}`); runCLI(`generate @nx/js:lib ${proj3}`); @@ -28,22 +37,22 @@ describe('Nx Commands', () => { const getOutput = await runWatch( `--projects=${proj1} -- echo \\$NX_PROJECT_NAME` ); - createFile(`libs/${proj1}/newfile.txt`, 'content'); - createFile(`libs/${proj2}/newfile.txt`, 'content'); - createFile(`libs/${proj1}/newfile2.txt`, 'content'); - createFile(`libs/${proj3}/newfile2.txt`, 'content'); - createFile(`newfile2.txt`, 'content'); + await writeFileForWatcher(`libs/${proj1}/newfile.txt`, 'content'); + await writeFileForWatcher(`libs/${proj2}/newfile.txt`, 'content'); + await writeFileForWatcher(`libs/${proj1}/newfile2.txt`, 'content'); + await writeFileForWatcher(`libs/${proj3}/newfile2.txt`, 'content'); + await writeFileForWatcher(`newfile2.txt`, 'content'); expect(await getOutput()).toEqual([proj1]); }); it('should watch for all projects and output the project name', async () => { const getOutput = await runWatch(`--all -- echo \\$NX_PROJECT_NAME`); - createFile(`libs/${proj1}/newfile.txt`, 'content'); - createFile(`libs/${proj2}/newfile.txt`, 'content'); - createFile(`libs/${proj1}/newfile2.txt`, 'content'); - createFile(`libs/${proj3}/newfile2.txt`, 'content'); - createFile(`newfile2.txt`, 'content'); + await writeFileForWatcher(`libs/${proj1}/newfile.txt`, 'content'); + await writeFileForWatcher(`libs/${proj2}/newfile.txt`, 'content'); + await writeFileForWatcher(`libs/${proj1}/newfile2.txt`, 'content'); + await writeFileForWatcher(`libs/${proj3}/newfile2.txt`, 'content'); + await writeFileForWatcher(`newfile2.txt`, 'content'); let content = await getOutput(); let results = content.sort(); @@ -53,10 +62,10 @@ describe('Nx Commands', () => { it('should watch for all project changes and output the file name changes', async () => { const getOutput = await runWatch(`--all -- echo \\$NX_FILE_CHANGES`); - createFile(`libs/${proj1}/newfile.txt`, 'content'); - createFile(`libs/${proj2}/newfile.txt`, 'content'); - createFile(`libs/${proj1}/newfile2.txt`, 'content'); - createFile(`newfile2.txt`, 'content'); + await writeFileForWatcher(`libs/${proj1}/newfile.txt`, 'content'); + await writeFileForWatcher(`libs/${proj2}/newfile.txt`, 'content'); + await writeFileForWatcher(`libs/${proj1}/newfile2.txt`, 'content'); + await writeFileForWatcher(`newfile2.txt`, 'content'); let output = (await getOutput())[0]; let results = output.split(' ').sort(); @@ -72,10 +81,10 @@ describe('Nx Commands', () => { const getOutput = await runWatch( `--all --includeGlobalWorkspaceFiles -- echo \\$NX_FILE_CHANGES` ); - createFile(`libs/${proj1}/newfile.txt`, 'content'); - createFile(`libs/${proj2}/newfile.txt`, 'content'); - createFile(`libs/${proj1}/newfile2.txt`, 'content'); - createFile(`newfile2.txt`, 'content'); + await writeFileForWatcher(`libs/${proj1}/newfile.txt`, 'content'); + await writeFileForWatcher(`libs/${proj2}/newfile.txt`, 'content'); + await writeFileForWatcher(`libs/${proj1}/newfile2.txt`, 'content'); + await writeFileForWatcher(`newfile2.txt`, 'content'); let output = (await getOutput())[0]; let results = output.split(' ').sort(); @@ -92,11 +101,11 @@ describe('Nx Commands', () => { const getOutput = await runWatch( `--projects=${proj1},${proj3} -- echo \\$NX_PROJECT_NAME` ); - createFile(`libs/${proj1}/newfile.txt`, 'content'); - createFile(`libs/${proj2}/newfile.txt`, 'content'); - createFile(`libs/${proj1}/newfile2.txt`, 'content'); - createFile(`libs/${proj3}/newfile2.txt`, 'content'); - createFile(`newfile2.txt`, 'content'); + await writeFileForWatcher(`libs/${proj1}/newfile.txt`, 'content'); + await writeFileForWatcher(`libs/${proj2}/newfile.txt`, 'content'); + await writeFileForWatcher(`libs/${proj1}/newfile2.txt`, 'content'); + await writeFileForWatcher(`libs/${proj3}/newfile2.txt`, 'content'); + await writeFileForWatcher(`newfile2.txt`, 'content'); let output = await getOutput(); let results = output.sort(); @@ -113,11 +122,11 @@ describe('Nx Commands', () => { const getOutput = await runWatch( `--projects=${proj3} --includeDependentProjects -- echo \\$NX_PROJECT_NAME` ); - createFile(`libs/${proj1}/newfile.txt`, 'content'); - createFile(`libs/${proj2}/newfile.txt`, 'content'); - createFile(`libs/${proj1}/newfile2.txt`, 'content'); - createFile(`libs/${proj3}/newfile2.txt`, 'content'); - createFile(`newfile2.txt`, 'content'); + await writeFileForWatcher(`libs/${proj1}/newfile.txt`, 'content'); + await writeFileForWatcher(`libs/${proj2}/newfile.txt`, 'content'); + await writeFileForWatcher(`libs/${proj1}/newfile2.txt`, 'content'); + await writeFileForWatcher(`libs/${proj3}/newfile2.txt`, 'content'); + await writeFileForWatcher(`newfile2.txt`, 'content'); let output = await getOutput(); let results = output.sort(); From b195e910c6906806c8dd79626c03f569b7dd5a8d Mon Sep 17 00:00:00 2001 From: Lars Gyrup Brink Nielsen Date: Fri, 30 Jun 2023 22:50:14 +0000 Subject: [PATCH 073/262] docs(nx-dev): fix broken link in workspace-lint deprecation --- docs/shared/deprecated/workspace-lint.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/shared/deprecated/workspace-lint.md b/docs/shared/deprecated/workspace-lint.md index e47a3f586bc4e..5a605d5e96a1a 100644 --- a/docs/shared/deprecated/workspace-lint.md +++ b/docs/shared/deprecated/workspace-lint.md @@ -6,7 +6,7 @@ Before Nx 15, the `workspace-lint` command performed workspace wide lint checks 2. Checking for files that do not belong to a project 3. Ensuring that all the versions of Nx packages are in sync -Checks (1) and (2) are no longer necessary because [Nx no longer uses a `workspace.json` file](../workspace-json) to define project locations. Instead, Nx dynamically detects projects anywhere in the workspace based on the presence of `package.json` or `project.json` files. +Checks (1) and (2) are no longer necessary because [Nx no longer uses a `workspace.json` file](/deprecated/workspace-json) to define project locations. Instead, Nx dynamically detects projects anywhere in the workspace based on the presence of `package.json` or `project.json` files. Check (3) is now accomplished manually with the [`nx report` command](/packages/nx/documents/report). From 2cbad1a610a4a40f147272d5215d2fe8f48aef99 Mon Sep 17 00:00:00 2001 From: Aaron Chen Date: Sun, 2 Jul 2023 16:54:45 +0800 Subject: [PATCH 074/262] docs(misc): update react-standalone.md update the file path in the doc from `modules/products/src/lib/product-list.tsx` to `modules/products/src/lib/product-list/product-list.tsx`. --- docs/shared/react-standalone-tutorial/react-standalone.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/shared/react-standalone-tutorial/react-standalone.md b/docs/shared/react-standalone-tutorial/react-standalone.md index 33bd330c34c58..252c578961739 100644 --- a/docs/shared/react-standalone-tutorial/react-standalone.md +++ b/docs/shared/react-standalone-tutorial/react-standalone.md @@ -434,7 +434,7 @@ nx g @nx/react:component product-list --project=modules-products We don't need to implement anything fancy as we just want to learn how to import it into our main React application. -```tsx {% fileName="modules/products/src/lib/product-list.tsx" %} +```tsx {% fileName="modules/products/src/lib/product-list/product-list.tsx" %} import styles from './product-list.module.css'; /* eslint-disable-next-line */ From 435778c42a56c0efd752493b4e93a4ab546243c4 Mon Sep 17 00:00:00 2001 From: Juri Date: Thu, 13 Jul 2023 14:53:18 +0200 Subject: [PATCH 075/262] docs(core): add video embed for module boundaries --- docs/shared/core-features/enforce-project-boundaries.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/shared/core-features/enforce-project-boundaries.md b/docs/shared/core-features/enforce-project-boundaries.md index 8fde324e58cfd..6f61c463ef8d3 100644 --- a/docs/shared/core-features/enforce-project-boundaries.md +++ b/docs/shared/core-features/enforce-project-boundaries.md @@ -4,6 +4,11 @@ If you partition your code into well-defined cohesive units, even a small organi To help with that Nx uses code analysis to make sure projects can only depend on each other's well-defined public API. It also allows you to declaratively impose constraints on how projects can depend on each other. +{% youtube +src="https://www.youtube.com/embed/q0en5vlOsWY" +title="Applying Module Boundaries" +width="100%" /%} + ## Project APIs Nx provides an `enforce-module-boundaries` eslint rule that enforces the public API of projects in the repo. Each project defines its public API in an `index.ts` (or `index.js`) file. If another project tries to import a variable from a file deep within a different project, an error will be thrown during linting. From 178975c96bef42b4a014da92185771615e2bd701 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leosvel=20P=C3=A9rez=20Espinosa?= Date: Fri, 14 Jul 2023 16:36:27 +0100 Subject: [PATCH 076/262] docs(misc): replace mention of old @nx/node:package with @nx/js:tsc (#18102) --- docs/shared/recipes/include-assets-in-build.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/shared/recipes/include-assets-in-build.md b/docs/shared/recipes/include-assets-in-build.md index 6de805226f2e3..d2749dc21b977 100644 --- a/docs/shared/recipes/include-assets-in-build.md +++ b/docs/shared/recipes/include-assets-in-build.md @@ -9,7 +9,7 @@ There are two ways to identify assets to be copied into the output bundle: ```jsonc {% fileName="project.json" %} "build": { - "executor": "@nx/node:package", + "executor": "@nx/js:tsc", // or any other Nx executor that supports the `assets` option "options": { // shortened... "assets": [ From d489de59e0535571c2cb3b0363cd5b4fc846842b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leosvel=20P=C3=A9rez=20Espinosa?= Date: Fri, 14 Jul 2023 16:41:07 +0100 Subject: [PATCH 077/262] fix(core): do not duplicate output of tasks executed in batch mode (#18084) --- .../forked-process-task-runner.ts | 21 ------------------- 1 file changed, 21 deletions(-) diff --git a/packages/nx/src/tasks-runner/forked-process-task-runner.ts b/packages/nx/src/tasks-runner/forked-process-task-runner.ts index a74cb15d28180..ab6006eed1ceb 100644 --- a/packages/nx/src/tasks-runner/forked-process-task-runner.ts +++ b/packages/nx/src/tasks-runner/forked-process-task-runner.ts @@ -78,30 +78,9 @@ export class ForkedProcessTaskRunner { } }); - const printedTasks = new Set(); p.on('message', (message: BatchMessage) => { switch (message.type) { - case BatchMessageType.CompleteTask: { - this.options.lifeCycle.printTaskTerminalOutput( - batchTaskGraph.tasks[message.task], - message.result.success ? 'success' : 'failure', - message.result.terminalOutput - ); - printedTasks.add(message.task); - - break; - } case BatchMessageType.CompleteBatchExecution: { - Object.entries(message.results).forEach(([taskName, result]) => { - if (!printedTasks.has(taskName)) { - this.options.lifeCycle.printTaskTerminalOutput( - batchTaskGraph.tasks[taskName], - result.success ? 'success' : 'failure', - result.terminalOutput - ); - } - }); - res(message.results); break; } From e5e561d6485ad87e464e8391883bd291962299d9 Mon Sep 17 00:00:00 2001 From: Emily Xiong Date: Fri, 14 Jul 2023 12:17:10 -0400 Subject: [PATCH 078/262] feat(testing): add playwright configuration generator (#18013) --- e2e/playwright/src/playwright.test.ts | 159 ++---------------- e2e/utils/get-env-info.ts | 11 ++ packages/playwright/.eslintrc.json | 2 +- packages/playwright/generators.json | 28 +++ packages/playwright/package.json | 5 +- .../generators/configuration/configuration.ts | 80 +++++++++ .../__directory__/example.spec.ts.template | 18 ++ .../files/playwright.config.ts.template | 85 ++++++++++ .../src/generators/configuration/schema.d.ts | 7 + .../src/generators/configuration/schema.json | 42 +++++ .../playwright/src/generators/init/init.ts | 33 ++++ .../src/generators/init/schema.d.ts | 4 + .../src/generators/init/schema.json | 22 +++ packages/playwright/src/utils/versions.ts | 2 + 14 files changed, 353 insertions(+), 145 deletions(-) create mode 100644 packages/playwright/generators.json create mode 100644 packages/playwright/src/generators/configuration/configuration.ts create mode 100644 packages/playwright/src/generators/configuration/files/__directory__/example.spec.ts.template create mode 100644 packages/playwright/src/generators/configuration/files/playwright.config.ts.template create mode 100644 packages/playwright/src/generators/configuration/schema.d.ts create mode 100644 packages/playwright/src/generators/configuration/schema.json create mode 100644 packages/playwright/src/generators/init/init.ts create mode 100644 packages/playwright/src/generators/init/schema.d.ts create mode 100644 packages/playwright/src/generators/init/schema.json create mode 100644 packages/playwright/src/utils/versions.ts diff --git a/e2e/playwright/src/playwright.test.ts b/e2e/playwright/src/playwright.test.ts index 05490b08ab772..f6d591b98e2df 100644 --- a/e2e/playwright/src/playwright.test.ts +++ b/e2e/playwright/src/playwright.test.ts @@ -2,18 +2,14 @@ import { cleanupProject, newProject, uniq, - createFile, runCLI, - packageInstall, - runCommand, + ensurePlaywrightBrowsersInstallation, } from '@nx/e2e/utils'; const TEN_MINS_MS = 600_000; describe('Playwright E2E Test runner', () => { beforeAll(() => { newProject({ name: uniq('playwright') }); - packageInstall('@playwright/test', undefined, '^1.30.0', 'dev'); - runCommand('npx playwright install --with-deps'); }); afterAll(() => cleanupProject()); @@ -21,151 +17,30 @@ describe('Playwright E2E Test runner', () => { it( 'should test example app', () => { - //TODO: remove when generators are setup.Need to have basic workspace deps setup - runCLI(`g @nx/js:init`); - addSampleProject(); + runCLI(`g @nx/js:lib demo-e2e --unitTestRunner none --bundler none`); + runCLI(`g @nx/playwright:configuration --project demo-e2e`); + ensurePlaywrightBrowsersInstallation(); - // NOTE: playwright throws errors if it detects running inside jest process. tmp remove and restore the env var for playwright to run const results = runCLI(`e2e demo-e2e`); expect(results).toContain('6 passed'); expect(results).toContain('Successfully ran target e2e for project'); }, TEN_MINS_MS ); -}); - -// TODO: remove this when there are project generators -function addSampleProject() { - createFile( - 'apps/demo-e2e/src/example.spec.ts', - ` -import { test, expect } from '@playwright/test'; - -test('has title', async ({ page }) => { - await page.goto('https://playwright.dev/'); - - // Expect a title "to contain" a substring. - await expect(page).toHaveTitle(/Playwright/); -}); - -test('get started link', async ({ page }) => { - await page.goto('https://playwright.dev/'); - - // Click the get started link. - await page.getByRole('link', { name: 'Get started' }).click(); - // Expects the URL to contain intro. - await expect(page).toHaveURL(/.*intro/); -}); -` - ); - createFile( - 'apps/demo-e2e/playwright.config.ts', - ` -import { defineConfig, devices } from '@playwright/test'; - -/** - * Read environment variables from file. - * https://github.com/motdotla/dotenv - */ -// require('dotenv').config(); - -/** - * See https://playwright.dev/docs/test-configuration. - */ -export default defineConfig({ - testDir: './src', - outputDir: '../../dist/playwright/apps/demo-e2e/output', - /* Run tests in files in parallel */ - fullyParallel: true, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, - /* Retry on CI only */ - retries: process.env.CI ? 2 : 0, - /* Opt out of parallel tests on CI. */ - workers: process.env.CI ? 1 : undefined, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: [ - [ - 'html', - { - outputFolder: - '../../dist/playwright/apps/demo-e2e/playwright-report', - }, - ], - ], - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Base URL to use in actions like await page.goto('/'). */ - // baseURL: 'http://127.0.0.1:3000', - - /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', - }, - - /* Configure projects for major browsers */ - projects: [ - { - name: 'chromium', - use: { ...devices['Desktop Chrome'] }, - }, - - { - name: 'firefox', - use: { ...devices['Desktop Firefox'] }, - }, + it( + 'should test example app with js', + () => { + runCLI( + `g @nx/js:lib demo-js-e2e --unitTestRunner none --bundler none --js` + ); + runCLI(`g @nx/playwright:configuration --project demo-js-e2e --js`); + ensurePlaywrightBrowsersInstallation(); - { - name: 'webkit', - use: { ...devices['Desktop Safari'] }, + const results = runCLI(`e2e demo-js-e2e`); + expect(results).toContain('6 passed'); + expect(results).toContain('Successfully ran target e2e for project'); }, - - /* Test against mobile viewports. */ - // { - // name: 'Mobile Chrome', - // use: { ...devices['Pixel 5'] }, - // }, - // { - // name: 'Mobile Safari', - // use: { ...devices['iPhone 12'] }, - // }, - - /* Test against branded browsers. */ - // { - // name: 'Microsoft Edge', - // use: { ...devices['Desktop Edge'], channel: 'msedge' }, - // }, - // { - // name: 'Google Chrome', - // use: { ...devices['Desktop Chrome'], channel: 'chrome' }, - // }, - ], - - /* Run your local dev server before starting the tests */ - // webServer: { - // command: 'npm run start', - // url: 'http://127.0.0.1:3000', - // reuseExistingServer: !process.env.CI, - // }, -}); -` - ); - createFile( - 'apps/demo-e2e/project.json', - JSON.stringify( - { - name: 'demo-e2e', - root: 'apps/demo-e2e', - sourceRoot: 'apps/demo-e2e/src', - targets: { - e2e: { - executor: '@nx/playwright:playwright', - options: {}, - }, - }, - }, - null, - 2 - ) + TEN_MINS_MS ); -} +}); diff --git a/e2e/utils/get-env-info.ts b/e2e/utils/get-env-info.ts index 0f52216689ea6..81c97e83a6f8c 100644 --- a/e2e/utils/get-env-info.ts +++ b/e2e/utils/get-env-info.ts @@ -111,6 +111,17 @@ export function ensureCypressInstallation() { } } +export function ensurePlaywrightBrowsersInstallation() { + execSync('npx playwright install --with-deps --force', { + stdio: isVerbose() ? 'inherit' : 'pipe', + encoding: 'utf-8', + cwd: tmpProjPath(), + }); + e2eConsoleLogger( + `Playwright browsers ${execSync('npx playwright --version')} installed.` + ); +} + export function getStrippedEnvironmentVariables() { return Object.fromEntries( Object.entries(process.env).filter(([key, value]) => { diff --git a/packages/playwright/.eslintrc.json b/packages/playwright/.eslintrc.json index 7abd30b8828cf..d33dd4fda746e 100644 --- a/packages/playwright/.eslintrc.json +++ b/packages/playwright/.eslintrc.json @@ -15,7 +15,7 @@ "rules": {} }, { - "files": ["./package.json", "./executors.json"], + "files": ["./package.json", "./executors.json", "./generators.json"], "parser": "jsonc-eslint-parser", "rules": { "@nx/nx-plugin-checks": "error" diff --git a/packages/playwright/generators.json b/packages/playwright/generators.json new file mode 100644 index 0000000000000..c8d82df7d69f3 --- /dev/null +++ b/packages/playwright/generators.json @@ -0,0 +1,28 @@ +{ + "name": "Nx Playwright", + "version": "0.1", + "schematics": { + "configuration": { + "factory": "./src/generators/configuration/configuration#configurationSchematic", + "schema": "./src/generators/configuration/schema.json", + "description": "Add Nx Playwright configuration to your project" + }, + "init": { + "factory": "./src/generators/init/init#initSchematic", + "schema": "./src/generators/init/schema.json", + "description": "Initializes a Playwright project in the current workspace" + } + }, + "generators": { + "configuration": { + "factory": "./src/generators/configuration/configuration", + "schema": "./src/generators/configuration/schema.json", + "description": "Add Nx Playwright configuration to your project" + }, + "init": { + "factory": "./src/generators/init/init", + "schema": "./src/generators/init/schema.json", + "description": "Initializes a Playwright project in the current workspace" + } + } +} diff --git a/packages/playwright/package.json b/packages/playwright/package.json index 188baca9d424e..620cb529022ca 100644 --- a/packages/playwright/package.json +++ b/packages/playwright/package.json @@ -32,12 +32,13 @@ "@nx/devkit": "file:../devkit" }, "peerDependencies": { - "@playwright/test": "^1.30.0" + "@playwright/test": "^1.36.0" }, "peerDependenciesMeta": { "@playwright/test": { "optional": true } }, - "executors": "./executors.json" + "executors": "./executors.json", + "generators": "./generators.json" } diff --git a/packages/playwright/src/generators/configuration/configuration.ts b/packages/playwright/src/generators/configuration/configuration.ts new file mode 100644 index 0000000000000..a0c04a8cbd2c9 --- /dev/null +++ b/packages/playwright/src/generators/configuration/configuration.ts @@ -0,0 +1,80 @@ +import { + convertNxGenerator, + formatFiles, + generateFiles, + offsetFromRoot, + readNxJson, + readProjectConfiguration, + toJS, + Tree, + updateNxJson, + updateProjectConfiguration, +} from '@nx/devkit'; +import * as path from 'path'; +import { ConfigurationGeneratorSchema } from './schema'; +import initGenerator from '../init/init'; + +export async function configurationGenerator( + tree: Tree, + options: ConfigurationGeneratorSchema +) { + const projectConfig = readProjectConfiguration(tree, options.project); + generateFiles(tree, path.join(__dirname, 'files'), projectConfig.root, { + offsetFromRoot: offsetFromRoot(projectConfig.root), + projectRoot: projectConfig.root, + ...options, + }); + + addE2eTarget(tree, options); + setupE2ETargetDefaults(tree); + + if (options.js) { + toJS(tree); + } + if (!options.skipFormat) { + await formatFiles(tree); + } + + return initGenerator(tree, { + skipFormat: true, + skipPackageJson: options.skipPackageJson, + }); +} + +function setupE2ETargetDefaults(tree: Tree) { + const nxJson = readNxJson(tree); + + if (!nxJson.namedInputs) { + return; + } + + // E2e targets depend on all their project's sources + production sources of dependencies + nxJson.targetDefaults ??= {}; + + const productionFileSet = !!nxJson.namedInputs?.production; + nxJson.targetDefaults.e2e ??= {}; + nxJson.targetDefaults.e2e.inputs ??= [ + 'default', + productionFileSet ? '^production' : '^default', + ]; + + updateNxJson(tree, nxJson); +} + +function addE2eTarget(tree: Tree, options: ConfigurationGeneratorSchema) { + const projectConfig = readProjectConfiguration(tree, options.project); + if (projectConfig?.targets?.e2e) { + throw new Error(`Project ${options.project} already has an e2e target. +Rename or remove the existing e2e target.`); + } + projectConfig.targets.e2e = { + executor: '@nx/playwright:playwright', + options: {}, + }; + updateProjectConfiguration(tree, options.project, projectConfig); +} + +export default configurationGenerator; +export const configurationSchematic = convertNxGenerator( + configurationGenerator +); diff --git a/packages/playwright/src/generators/configuration/files/__directory__/example.spec.ts.template b/packages/playwright/src/generators/configuration/files/__directory__/example.spec.ts.template new file mode 100644 index 0000000000000..c511525c13be2 --- /dev/null +++ b/packages/playwright/src/generators/configuration/files/__directory__/example.spec.ts.template @@ -0,0 +1,18 @@ +import { test, expect } from '@playwright/test'; + +test('has title', async ({ page }) => { + await page.goto('https://playwright.dev/'); + + // Expect a title "to contain" a substring. + await expect(page).toHaveTitle(/Playwright/); +}); + +test('get started link', async ({ page }) => { + await page.goto('https://playwright.dev/'); + + // Click the get started link. + await page.getByRole('link', { name: 'Get started' }).click(); + + // Expects the URL to contain intro. + await expect(page).toHaveURL(/.*intro/); +}); diff --git a/packages/playwright/src/generators/configuration/files/playwright.config.ts.template b/packages/playwright/src/generators/configuration/files/playwright.config.ts.template new file mode 100644 index 0000000000000..f5067f8a64624 --- /dev/null +++ b/packages/playwright/src/generators/configuration/files/playwright.config.ts.template @@ -0,0 +1,85 @@ +import { defineConfig, devices } from '@playwright/test'; + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: './<%= directory %>', + /* Run tests in files in parallel */ + fullyParallel: true, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: [ + [ + 'html', + { + outputFolder: + '<%= offsetFromRoot %>/dist/playwright/<%= projectRoot %>/playwright-report', + }, + ], + ], + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Base URL to use in actions like `await page.goto('/')`. */ + // baseURL: 'http://127.0.0.1:3000', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + }, + + { + name: 'firefox', + use: { ...devices['Desktop Firefox'] }, + }, + + { + name: 'webkit', + use: { ...devices['Desktop Safari'] }, + }, + + /* Test against mobile viewports. */ + // { + // name: 'Mobile Chrome', + // use: { ...devices['Pixel 5'] }, + // }, + // { + // name: 'Mobile Safari', + // use: { ...devices['iPhone 12'] }, + // }, + + /* Test against branded browsers. */ + // { + // name: 'Microsoft Edge', + // use: { ...devices['Desktop Edge'], channel: 'msedge' }, + // }, + // { + // name: 'Google Chrome', + // use: { ...devices['Desktop Chrome'], channel: 'chrome' }, + // }, + ], + + /* Run your local dev server before starting the tests */ + // webServer: { + // command: 'npm run start', + // url: 'http://127.0.0.1:3000', + // reuseExistingServer: !process.env.CI, + // }, +}); diff --git a/packages/playwright/src/generators/configuration/schema.d.ts b/packages/playwright/src/generators/configuration/schema.d.ts new file mode 100644 index 0000000000000..99213e3ed939f --- /dev/null +++ b/packages/playwright/src/generators/configuration/schema.d.ts @@ -0,0 +1,7 @@ +export interface ConfigurationGeneratorSchema { + project: string; + directory: string; + js: boolean; // default is false + skipFormat: boolean; + skipPackageJson: boolean; +} diff --git a/packages/playwright/src/generators/configuration/schema.json b/packages/playwright/src/generators/configuration/schema.json new file mode 100644 index 0000000000000..26fded6567b08 --- /dev/null +++ b/packages/playwright/src/generators/configuration/schema.json @@ -0,0 +1,42 @@ +{ + "$schema": "http://json-schema.org/schema", + "$id": "NxPlaywrightConfiguration", + "description": "Add a Playwright configuration.", + "title": "Add a Playwright configuration", + "type": "object", + "properties": { + "project": { + "type": "string", + "description": "The project to add a Playwright configuration to", + "$default": { + "$source": "projectName" + }, + "x-priority": "important", + "x-prompt": "What is the name of the project to set up Playwright for?" + }, + "directory": { + "type": "string", + "description": "A directory where the project is placed relative from the project root", + "x-priority": "important", + "default": "playwright" + }, + "js": { + "type": "boolean", + "description": "Generate JavaScript files rather than TypeScript files.", + "default": false + }, + "skipFormat": { + "description": "Skip formatting files.", + "type": "boolean", + "default": false, + "x-priority": "internal" + }, + "skipPackageJson": { + "type": "boolean", + "default": false, + "description": "Do not add dependencies to `package.json`.", + "x-priority": "internal" + } + }, + "required": ["project"] +} diff --git a/packages/playwright/src/generators/init/init.ts b/packages/playwright/src/generators/init/init.ts new file mode 100644 index 0000000000000..f904c5d10b727 --- /dev/null +++ b/packages/playwright/src/generators/init/init.ts @@ -0,0 +1,33 @@ +import { + addDependenciesToPackageJson, + convertNxGenerator, + formatFiles, + GeneratorCallback, + runTasksInSerial, + Tree, +} from '@nx/devkit'; +import { InitGeneratorSchema } from './schema'; +import { nxVersion, playwrightVersion } from '../../utils/versions'; + +export async function initGenerator(tree: Tree, options: InitGeneratorSchema) { + const tasks: GeneratorCallback[] = []; + if (!options.skipPackageJson) { + tasks.push( + addDependenciesToPackageJson( + tree, + {}, + { + '@nx/playwright': nxVersion, + '@playwright/test': playwrightVersion, + } + ) + ); + } + if (!options.skipFormat) { + await formatFiles(tree); + } + return runTasksInSerial(...tasks); +} + +export default initGenerator; +export const initSchematic = convertNxGenerator(initGenerator); diff --git a/packages/playwright/src/generators/init/schema.d.ts b/packages/playwright/src/generators/init/schema.d.ts new file mode 100644 index 0000000000000..052f232474fb7 --- /dev/null +++ b/packages/playwright/src/generators/init/schema.d.ts @@ -0,0 +1,4 @@ +export interface InitGeneratorSchema { + skipFormat: boolean; + skipPackageJson: boolean; +} diff --git a/packages/playwright/src/generators/init/schema.json b/packages/playwright/src/generators/init/schema.json new file mode 100644 index 0000000000000..7ba08b9d0d1a5 --- /dev/null +++ b/packages/playwright/src/generators/init/schema.json @@ -0,0 +1,22 @@ +{ + "$schema": "http://json-schema.org/schema", + "$id": "NxPlaywrightInit", + "title": "Playwright Init Generator", + "description": "Initializes a Playwright project in the current workspace.", + "type": "object", + "properties": { + "skipFormat": { + "description": "Skip formatting files.", + "type": "boolean", + "default": false, + "x-priority": "internal" + }, + "skipPackageJson": { + "type": "boolean", + "default": false, + "description": "Do not add dependencies to `package.json`.", + "x-priority": "internal" + } + }, + "required": [] +} diff --git a/packages/playwright/src/utils/versions.ts b/packages/playwright/src/utils/versions.ts new file mode 100644 index 0000000000000..cb9d1709cb7d1 --- /dev/null +++ b/packages/playwright/src/utils/versions.ts @@ -0,0 +1,2 @@ +export const nxVersion = require('../../package.json').version; +export const playwrightVersion = '^1.36.0'; From 2a14d4c2d6f72dbe80cd48ad0d3be7226ae63854 Mon Sep 17 00:00:00 2001 From: Jason Jean Date: Fri, 14 Jul 2023 14:49:44 -0400 Subject: [PATCH 079/262] chore(repo): update nx to 16.6.0-beta.2 (#18054) --- jest.preset.js | 2 + package.json | 35 +-- pnpm-lock.yaml | 566 ++++++++++++++++++++++++++++++------------------- 3 files changed, 365 insertions(+), 238 deletions(-) diff --git a/jest.preset.js b/jest.preset.js index af1a0eff5b0a1..6c33c1524f672 100644 --- a/jest.preset.js +++ b/jest.preset.js @@ -8,6 +8,8 @@ module.exports = { '^.+\\.(ts|js|html)$': 'ts-jest', }, resolver: '../../scripts/patched-jest-resolver.js', + // Fixes https://github.com/jestjs/jest/issues/11956 + runtime: '@side/jest-runtime', moduleFileExtensions: ['ts', 'js', 'html'], coverageReporters: ['html'], maxWorkers: 1, diff --git a/package.json b/package.json index 705c988019505..81f933530cfdb 100644 --- a/package.json +++ b/package.json @@ -64,17 +64,17 @@ "@ngrx/router-store": "~16.0.0", "@ngrx/store": "~16.0.0", "@nguniversal/builders": "~16.1.0", - "@nx/cypress": "16.5.0-beta.3", - "@nx/devkit": "16.5.0-beta.3", - "@nx/eslint-plugin": "16.5.0-beta.3", - "@nx/jest": "16.5.0-beta.3", - "@nx/js": "16.5.0-beta.3", - "@nx/linter": "16.5.0-beta.3", - "@nx/next": "16.5.0-beta.3", - "@nx/react": "16.5.0-beta.3", - "@nx/storybook": "16.5.0-beta.3", - "@nx/web": "16.5.0-beta.3", - "@nx/webpack": "16.5.0-beta.3", + "@nx/cypress": "16.6.0-beta.2", + "@nx/devkit": "16.6.0-beta.2", + "@nx/eslint-plugin": "16.6.0-beta.2", + "@nx/jest": "16.6.0-beta.2", + "@nx/js": "16.6.0-beta.2", + "@nx/linter": "16.6.0-beta.2", + "@nx/next": "16.6.0-beta.2", + "@nx/react": "16.6.0-beta.2", + "@nx/storybook": "16.6.0-beta.2", + "@nx/web": "16.6.0-beta.2", + "@nx/webpack": "16.6.0-beta.2", "@parcel/watcher": "2.0.4", "@phenomnomnominal/tsquery": "~5.0.1", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.7", @@ -87,6 +87,7 @@ "@rollup/plugin-node-resolve": "^13.0.4", "@rollup/plugin-url": "^7.0.0", "@schematics/angular": "~16.1.0", + "@side/jest-runtime": "^1.1.0", "@storybook/addon-essentials": "^7.0.24", "@storybook/core-server": "^7.0.24", "@storybook/react": "^7.0.24", @@ -115,7 +116,7 @@ "@types/marked": "^2.0.0", "@types/node": "18.16.9", "@types/prettier": "^2.6.2", - "@types/react": "18.2.13", + "@types/react": "18.2.14", "@types/react-dom": "18.2.6", "@types/semver": "^7.5.0", "@types/tar-stream": "^2.2.2", @@ -213,11 +214,11 @@ "next-sitemap": "^3.1.10", "ng-packagr": "~16.1.0", "node-fetch": "^2.6.7", - "nx": "16.5.0-beta.3", - "nx-cloud": "16.0.5", + "nx": "16.6.0-beta.2", + "nx-cloud": "16.1.0", "octokit": "^2.0.14", "open": "^8.4.0", - "openai":"~3.3.0", + "openai": "~3.3.0", "ora": "5.3.0", "parse-markdown-links": "^1.0.4", "parse5": "4.0.0", @@ -319,6 +320,7 @@ "license-checker": "^25.0.1", "next": "13.3.4", "next-seo": "^5.13.0", + "node-machine-id": "1.1.12", "npm-run-path": "^4.0.1", "preact": "10.6.4", "react": "18.2.0", @@ -334,8 +336,7 @@ "tailwindcss": "3.2.4", "tslib": "^2.3.0", "vitest": "^0.32.0", - "weak-napi": "^2.0.2", - "node-machine-id": "1.1.12" + "weak-napi": "^2.0.2" }, "resolutions": { "minimist": "^1.2.6", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 93994ca536850..2161777fedaf5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,5 +1,9 @@ lockfileVersion: '6.0' +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + overrides: minimist: ^1.2.6 underscore: ^1.12.1 @@ -12,7 +16,7 @@ patchedDependencies: dependencies: '@docsearch/react': specifier: ^3.3.0 - version: 3.3.0(@algolia/client-search@4.17.2)(@types/react@18.2.13)(react-dom@18.2.0)(react@18.2.0) + version: 3.3.0(@algolia/client-search@4.17.2)(@types/react@18.2.14)(react-dom@18.2.0)(react@18.2.0) '@headlessui/react': specifier: ^1.7.3 version: 1.7.3(react-dom@18.2.0)(react@18.2.0) @@ -21,7 +25,7 @@ dependencies: version: 2.0.12(react@18.2.0) '@markdoc/markdoc': specifier: 0.2.2 - version: 0.2.2(@types/react@18.2.13)(react@18.2.0) + version: 0.2.2(@types/react@18.2.14)(react@18.2.0) '@monaco-editor/react': specifier: ^4.4.6 version: 4.4.6(monaco-editor@0.39.0)(react-dom@18.2.0)(react@18.2.0) @@ -212,7 +216,7 @@ devDependencies: version: 7.21.0 '@floating-ui/react': specifier: 0.19.2 - version: 0.19.2(@types/react@18.2.13)(react-dom@18.2.0)(react@18.2.0) + version: 0.19.2(@types/react@18.2.14)(react-dom@18.2.0)(react@18.2.0) '@jest/reporters': specifier: ^29.4.1 version: 29.5.0 @@ -224,7 +228,7 @@ devDependencies: version: 29.5.0 '@monodon/rust': specifier: 1.1.2 - version: 1.1.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.5.0-beta.3)(prettier@2.7.1)(typescript@5.1.3) + version: 1.1.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.6.0-beta.2)(prettier@2.7.1)(typescript@5.1.3) '@napi-rs/cli': specifier: 2.14.0 version: 2.14.0 @@ -262,38 +266,38 @@ devDependencies: specifier: ~16.1.0 version: 16.1.0(@angular-devkit/build-angular@16.1.0)(@angular/common@16.1.0)(@angular/core@16.1.0)(@types/express@4.17.14)(chokidar@3.5.3)(typescript@5.1.3) '@nx/cypress': - specifier: 16.5.0-beta.3 - version: 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(cypress@12.16.0)(eslint@8.15.0)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4) + specifier: 16.6.0-beta.2 + version: 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4) '@nx/devkit': - specifier: 16.5.0-beta.3 - version: 16.5.0-beta.3(nx@16.5.0-beta.3) + specifier: 16.6.0-beta.2 + version: 16.6.0-beta.2(nx@16.6.0-beta.2) '@nx/eslint-plugin': - specifier: 16.5.0-beta.3 - version: 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@typescript-eslint/parser@5.60.1)(eslint-config-prettier@8.5.0)(eslint@8.15.0)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4) + specifier: 16.6.0-beta.2 + version: 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(@typescript-eslint/parser@5.60.1)(eslint-config-prettier@8.5.0)(eslint@8.15.0)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4) '@nx/jest': - specifier: 16.5.0-beta.3 - version: 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.5.0-beta.3)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4) + specifier: 16.6.0-beta.2 + version: 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.2)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4) '@nx/js': - specifier: 16.5.0-beta.3 - version: 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4) + specifier: 16.6.0-beta.2 + version: 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4) '@nx/linter': - specifier: 16.5.0-beta.3 - version: 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4) + specifier: 16.6.0-beta.2 + version: 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4) '@nx/next': - specifier: 16.5.0-beta.3 - version: 16.5.0-beta.3(@babel/core@7.19.0)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/express@4.17.14)(@types/node@18.16.9)(eslint@8.15.0)(file-loader@6.2.0)(next@13.3.4)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) + specifier: 16.6.0-beta.2 + version: 16.6.0-beta.2(@babel/core@7.19.0)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/express@4.17.14)(@types/node@18.16.9)(eslint@8.15.0)(file-loader@6.2.0)(next@13.3.4)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) '@nx/react': - specifier: 16.5.0-beta.3 - version: 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) + specifier: 16.6.0-beta.2 + version: 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) '@nx/storybook': - specifier: 16.5.0-beta.3 - version: 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(cypress@12.16.0)(eslint@8.15.0)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4) + specifier: 16.6.0-beta.2 + version: 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4) '@nx/web': - specifier: 16.5.0-beta.3 - version: 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4) + specifier: 16.6.0-beta.2 + version: 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4) '@nx/webpack': - specifier: 16.5.0-beta.3 - version: 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(esbuild@0.17.5)(html-webpack-plugin@5.5.0)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4) + specifier: 16.6.0-beta.2 + version: 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(esbuild@0.17.5)(html-webpack-plugin@5.5.0)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4) '@parcel/watcher': specifier: 2.0.4 version: 2.0.4 @@ -330,6 +334,9 @@ devDependencies: '@schematics/angular': specifier: ~16.1.0 version: 16.1.0(chokidar@3.5.3) + '@side/jest-runtime': + specifier: ^1.1.0 + version: 1.1.0(@jest/transform@29.5.0)(jest-runtime@29.5.0)(jest@29.4.3) '@storybook/addon-essentials': specifier: ^7.0.24 version: 7.0.24(react-dom@18.2.0)(react@18.2.0) @@ -415,8 +422,8 @@ devDependencies: specifier: ^2.6.2 version: 2.7.1 '@types/react': - specifier: 18.2.13 - version: 18.2.13 + specifier: 18.2.14 + version: 18.2.14 '@types/react-dom': specifier: 18.2.6 version: 18.2.6 @@ -455,7 +462,7 @@ devDependencies: version: 0.7.0(ws@8.13.0)(xstate@4.34.0) '@xstate/react': specifier: 3.0.1 - version: 3.0.1(@types/react@18.2.13)(react@18.2.0)(xstate@4.34.0) + version: 3.0.1(@types/react@18.2.14)(react@18.2.0)(xstate@4.34.0) ai: specifier: ^2.1.15 version: 2.1.15(react@18.2.0)(svelte@3.59.2)(vue@3.3.4) @@ -709,11 +716,11 @@ devDependencies: specifier: ^2.6.7 version: 2.6.7 nx: - specifier: 16.5.0-beta.3 - version: 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51) + specifier: 16.6.0-beta.2 + version: 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51) nx-cloud: - specifier: 16.0.5 - version: 16.0.5 + specifier: 16.1.0 + version: 16.1.0 octokit: specifier: ^2.0.14 version: 2.0.14 @@ -758,7 +765,7 @@ devDependencies: version: 4.0.2(webpack@5.88.0) react-redux: specifier: 8.0.5 - version: 8.0.5(@types/react-dom@18.2.6)(@types/react@18.2.13)(react-dom@18.2.0)(react@18.2.0)(redux@4.2.0) + version: 8.0.5(@types/react-dom@18.2.6)(@types/react@18.2.14)(react-dom@18.2.0)(react@18.2.0)(redux@4.2.0) react-refresh: specifier: ^0.10.0 version: 0.10.0 @@ -4799,7 +4806,7 @@ packages: resolution: {integrity: sha512-rODCdDtGyudLj+Va8b6w6Y85KE85bXRsps/R4Yjwt5vueXKXZQKYw0aA9knxLBT6a/bI/GMrAcmCR75KYOM6hg==} dev: false - /@docsearch/react@3.3.0(@algolia/client-search@4.17.2)(@types/react@18.2.13)(react-dom@18.2.0)(react@18.2.0): + /@docsearch/react@3.3.0(@algolia/client-search@4.17.2)(@types/react@18.2.14)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-fhS5adZkae2SSdMYEMVg6pxI5a/cE+tW16ki1V0/ur4Fdok3hBRkmN/H8VvlXnxzggkQIIRIVvYPn00JPjen3A==} peerDependencies: '@types/react': '>= 16.8.0 < 19.0.0' @@ -4816,7 +4823,7 @@ packages: '@algolia/autocomplete-core': 1.7.2 '@algolia/autocomplete-preset-algolia': 1.7.2(@algolia/client-search@4.17.2)(algoliasearch@4.14.2) '@docsearch/css': 3.3.0 - '@types/react': 18.2.13 + '@types/react': 18.2.14 algoliasearch: 4.14.2 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) @@ -5470,14 +5477,14 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: true - /@floating-ui/react@0.19.2(@types/react@18.2.13)(react-dom@18.2.0)(react@18.2.0): + /@floating-ui/react@0.19.2(@types/react@18.2.14)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-JyNk4A0Ezirq8FlXECvRtQOX/iBe5Ize0W/pLkrZjfHW9GUV7Xnq6zm6fyZuQzaHHqEnVizmvlA96e1/CkZv+w==} peerDependencies: react: '>=16.8.0' react-dom: '>=16.8.0' dependencies: '@floating-ui/react-dom': 1.3.0(react-dom@18.2.0)(react@18.2.0) - aria-hidden: 1.2.2(@types/react@18.2.13)(react@18.2.0) + aria-hidden: 1.2.2(@types/react@18.2.14)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) tabbable: 6.0.1 @@ -5816,6 +5823,7 @@ packages: dependencies: '@jridgewell/gen-mapping': 0.3.3 '@jridgewell/trace-mapping': 0.3.18 + dev: true /@jridgewell/sourcemap-codec@1.4.14: resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==} @@ -5956,7 +5964,7 @@ packages: resolution: {integrity: sha512-lYtBcmvHustHQtg4X7TXUu1Xa/tbLC3p2wLvgQI+fWVySguVZJF60Snxijw5EiohumxZbR10kWYFFebh1zotiw==} dev: true - /@markdoc/markdoc@0.2.2(@types/react@18.2.13)(react@18.2.0): + /@markdoc/markdoc@0.2.2(@types/react@18.2.14)(react@18.2.0): resolution: {integrity: sha512-0TiD9jmA5h5znN4lxo7HECAu3WieU5g5vUsfByeucrdR/x88hEilpt16EydFyJwJddQ/3w5HQgW7Ovy62r4cyw==} engines: {node: '>=14.7.0'} peerDependencies: @@ -5968,7 +5976,7 @@ packages: react: optional: true dependencies: - '@types/react': 18.2.13 + '@types/react': 18.2.14 react: 18.2.0 optionalDependencies: '@types/markdown-it': 12.2.3 @@ -5980,7 +5988,7 @@ packages: react: '>=16' dependencies: '@types/mdx': 2.0.4 - '@types/react': 18.2.13 + '@types/react': 18.2.14 react: 18.2.0 dev: true @@ -6021,12 +6029,12 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false - /@monodon/rust@1.1.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.5.0-beta.3)(prettier@2.7.1)(typescript@5.1.3): + /@monodon/rust@1.1.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.6.0-beta.2)(prettier@2.7.1)(typescript@5.1.3): resolution: {integrity: sha512-lb667coCcsWmkHuSKfGHgEeaWK24VGrW3AgA7Wq2M8wVVhuVQeKAV2UDt5vgvQj+xPlXPyKs6iPqNFXi3c2nLA==} dependencies: '@ltd/j-toml': 1.38.0 - '@nrwl/devkit': 15.8.0(nx@16.5.0-beta.3)(typescript@5.1.3) - '@nrwl/js': 15.8.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.5.0-beta.3)(prettier@2.7.1)(typescript@5.1.3) + '@nrwl/devkit': 15.8.0(nx@16.6.0-beta.2)(typescript@5.1.3) + '@nrwl/js': 15.8.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.6.0-beta.2)(prettier@2.7.1)(typescript@5.1.3) chalk: 4.1.2 transitivePeerDependencies: - '@babel/traverse' @@ -6752,14 +6760,16 @@ packages: - debug dev: true - /@nrwl/cypress@16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(cypress@12.16.0)(eslint@8.15.0)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-RX7l2RyIF1QYGH3mubNC7xvmDI5GRsdkxGhF5SydPESelL4yjaVLOVIpygwvJ2EzSOPCxkGMx0GdhnVjB0A3ag==} + /@nrwl/cypress@16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-NWJPd2NzhoI1fStXZ5/v/EXkM1+6Jev37CiCMi52fNAdzjRVAewhu4V6vJBG1JaWSDZzLt7wMOqVdDim38HR/A==} dependencies: - '@nx/cypress': 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(cypress@12.16.0)(eslint@8.15.0)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/cypress': 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4) transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' - '@swc/core' + - '@swc/wasm' + - '@types/node' - cypress - debug - eslint @@ -6801,7 +6811,7 @@ packages: - typescript dev: true - /@nrwl/devkit@15.8.0(nx@16.5.0-beta.3)(typescript@5.1.3): + /@nrwl/devkit@15.8.0(nx@16.6.0-beta.2)(typescript@5.1.3): resolution: {integrity: sha512-qD+asvhTXIibXPXr3r1IDP7ap3Bw5H7tSd+C5mXFhIMMinTqRnQVXe6Odfs34VFP/dpWBIBZdkkwCM/+BsCLNw==} peerDependencies: nx: '>= 14.1 <= 16' @@ -6809,7 +6819,7 @@ packages: '@phenomnomnominal/tsquery': 4.1.1(typescript@5.1.3) ejs: 3.1.8 ignore: 5.2.0 - nx: 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51) + nx: 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51) semver: 7.3.4 tmp: 0.2.1 tslib: 2.5.3 @@ -6817,22 +6827,24 @@ packages: - typescript dev: true - /@nrwl/devkit@16.5.0-beta.3(nx@16.5.0-beta.3): - resolution: {integrity: sha512-i1LU5BVRv55kgsPdV+iKaCT7rWa9ms2N7+B3zRf2WeOo1CFvWxiZog+XN3BkOq8yBpNaeFCxWVubQ6w/UUWUyg==} + /@nrwl/devkit@16.6.0-beta.2(nx@16.6.0-beta.2): + resolution: {integrity: sha512-eITXJzlz3475QxL1seR4ACWSuXrFfkRL/MZOY0PVEBGK9AuKrIYKlgr2/dAepqfi6tkMzTA+x7Zf9Bd9xZftLg==} dependencies: - '@nx/devkit': 16.5.0-beta.3(nx@16.5.0-beta.3) + '@nx/devkit': 16.6.0-beta.2(nx@16.6.0-beta.2) transitivePeerDependencies: - nx dev: true - /@nrwl/eslint-plugin-nx@16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@typescript-eslint/parser@5.60.1)(eslint-config-prettier@8.5.0)(eslint@8.15.0)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-UIvs7RWq8tX9pwY0ChfeLimmg3654Kmc8ySFtlRdGIuSwaosYiwY1e6AmQF8yV1Kfoim7lFWmHHznrB7kvOQhA==} + /@nrwl/eslint-plugin-nx@16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(@typescript-eslint/parser@5.60.1)(eslint-config-prettier@8.5.0)(eslint@8.15.0)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-0yHz4cCSDRQC62Cv7+VYGQLO1dI6ZIKjOXT1TH5vP9JWUC5gcN21NAYwz4bNQ+9av6Z7wcCEGjAjTlznS3C90Q==} dependencies: - '@nx/eslint-plugin': 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@typescript-eslint/parser@5.60.1)(eslint-config-prettier@8.5.0)(eslint@8.15.0)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/eslint-plugin': 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(@typescript-eslint/parser@5.60.1)(eslint-config-prettier@8.5.0)(eslint@8.15.0)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4) transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' - '@swc/core' + - '@swc/wasm' + - '@types/node' - '@typescript-eslint/parser' - debug - eslint @@ -6843,14 +6855,15 @@ packages: - verdaccio dev: true - /@nrwl/jest@16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.5.0-beta.3)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-QFzBKo6SEJYlxZ+LBnH2bxOAtua4ZtU+YL6wtQ/2+VLJzOZKf8KQ91LOBUvxTmjHMvJGJeNC80WwV1/hVBnyng==} + /@nrwl/jest@16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.2)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-uU4nExiHN8X42pUemf9vHFw7zPUmi9dBNKjwKp/fFIT1mc7iDB3YZ0lTLMx0oh/2Ajh+UjnOoWsQMpiT3KiDCg==} dependencies: - '@nx/jest': 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.5.0-beta.3)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/jest': 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.2)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4) transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' - '@swc/core' + - '@swc/wasm' - '@types/node' - debug - node-notifier @@ -6861,7 +6874,7 @@ packages: - verdaccio dev: true - /@nrwl/js@15.8.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.5.0-beta.3)(prettier@2.7.1)(typescript@5.1.3): + /@nrwl/js@15.8.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.6.0-beta.2)(prettier@2.7.1)(typescript@5.1.3): resolution: {integrity: sha512-l2Q7oFpzx6ul7G0nKpMkrvnIEaOY+X8fc2g2Db5WqpnnBdfkrtWXZPg/O4DQ1p9O6BXrZ+Q2AK9bfgnliiwyEg==} dependencies: '@babel/core': 7.22.5 @@ -6871,7 +6884,7 @@ packages: '@babel/preset-env': 7.22.5(@babel/core@7.22.5) '@babel/preset-typescript': 7.21.4(@babel/core@7.22.5) '@babel/runtime': 7.22.5 - '@nrwl/devkit': 15.8.0(nx@16.5.0-beta.3)(typescript@5.1.3) + '@nrwl/devkit': 15.8.0(nx@16.6.0-beta.2)(typescript@5.1.3) '@nrwl/workspace': 15.8.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(prettier@2.7.1)(typescript@5.1.3) '@phenomnomnominal/tsquery': 4.1.1(typescript@5.1.3) babel-plugin-const-enum: 1.2.0(@babel/core@7.22.5) @@ -6898,14 +6911,52 @@ packages: - typescript dev: true - /@nrwl/js@16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-6ZeiIEt67meBC5mTugzSCbMHsMLTrYGzqkaXWWr3jj+8WTxCgVqTqV8JSgUq/sW9btQM7zAqH7ABLp0Cr4FS+A==} + /@nrwl/js@15.8.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(nx@15.8.0)(prettier@2.7.1)(typescript@5.1.3): + resolution: {integrity: sha512-l2Q7oFpzx6ul7G0nKpMkrvnIEaOY+X8fc2g2Db5WqpnnBdfkrtWXZPg/O4DQ1p9O6BXrZ+Q2AK9bfgnliiwyEg==} + dependencies: + '@babel/core': 7.22.5 + '@babel/plugin-proposal-class-properties': 7.18.6(@babel/core@7.22.5) + '@babel/plugin-proposal-decorators': 7.21.0(@babel/core@7.22.5) + '@babel/plugin-transform-runtime': 7.22.5(@babel/core@7.22.5) + '@babel/preset-env': 7.22.5(@babel/core@7.22.5) + '@babel/preset-typescript': 7.21.4(@babel/core@7.22.5) + '@babel/runtime': 7.22.5 + '@nrwl/devkit': 15.8.0(nx@15.8.0)(typescript@5.1.3) + '@nrwl/workspace': 15.8.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(prettier@2.7.1)(typescript@5.1.3) + '@phenomnomnominal/tsquery': 4.1.1(typescript@5.1.3) + babel-plugin-const-enum: 1.2.0(@babel/core@7.22.5) + babel-plugin-macros: 2.8.0 + babel-plugin-transform-typescript-metadata: 0.3.2(@babel/core@7.22.5) + chalk: 4.1.2 + fast-glob: 3.2.7 + fs-extra: 11.1.1 + ignore: 5.2.0 + js-tokens: 4.0.0 + minimatch: 3.0.5 + source-map-support: 0.5.19 + tree-kill: 1.2.2 + tslib: 2.5.3 + transitivePeerDependencies: + - '@babel/traverse' + - '@swc-node/register' + - '@swc/core' + - debug + - nx + - prettier + - supports-color + - typescript + dev: true + + /@nrwl/js@16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-NdXMqmd5MDcw3/EzNbcKTTiVAXVZMIGCtFsEsO+0DwHWnHLlqYtqDIGVHnsamnUKLZS2WuMSijrqnoxvvln4FQ==} dependencies: - '@nx/js': 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/js': 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4) transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' - '@swc/core' + - '@swc/wasm' + - '@types/node' - debug - nx - supports-color @@ -6922,7 +6973,7 @@ packages: optional: true dependencies: '@nrwl/devkit': 15.8.0(nx@15.8.0)(typescript@5.1.3) - '@nrwl/js': 15.8.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.5.0-beta.3)(prettier@2.7.1)(typescript@5.1.3) + '@nrwl/js': 15.8.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(nx@15.8.0)(prettier@2.7.1)(typescript@5.1.3) '@phenomnomnominal/tsquery': 4.1.1(typescript@5.1.3) eslint: 8.15.0 tmp: 0.2.1 @@ -6938,14 +6989,16 @@ packages: - typescript dev: true - /@nrwl/linter@16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-iXFBInyMZ6qO91wShIUOHl4rf1qxUzvGxmG4to+kv4+Sabn1BPg8CZQ1uEh/3H++tVPjGUC26j2U/GHZY5KA5w==} + /@nrwl/linter@16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-f7PVORIRPwKob3W43ZCX9ocP+VfmL7cC5DX8+T3C2YB4gzTW7AbtcvWX0xTJEoenjAK2PYmp5G2qul4Pxr6jag==} dependencies: - '@nx/linter': 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/linter': 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4) transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' - '@swc/core' + - '@swc/wasm' + - '@types/node' - debug - eslint - nx @@ -6954,10 +7007,10 @@ packages: - verdaccio dev: true - /@nrwl/next@16.5.0-beta.3(@babel/core@7.19.0)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/express@4.17.14)(@types/node@18.16.9)(eslint@8.15.0)(file-loader@6.2.0)(next@13.3.4)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0): - resolution: {integrity: sha512-zEINBeXfGgGGQINEOAWkWU15dJl+F5aHpW61DLWYfa/DvdBYu28oYemeRR9wtub3BVXA6KqPubTFNu0UPweYTQ==} + /@nrwl/next@16.6.0-beta.2(@babel/core@7.19.0)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/express@4.17.14)(@types/node@18.16.9)(eslint@8.15.0)(file-loader@6.2.0)(next@13.3.4)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0): + resolution: {integrity: sha512-kijyfEuwfOMGOq/85HTbpazqWLzMIyW7iPv/cePR8ix8NNRniwi+XTe+xUfp7vgE7/G5BMqWaiE6V9GB3hCjHA==} dependencies: - '@nx/next': 16.5.0-beta.3(@babel/core@7.19.0)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/express@4.17.14)(@types/node@18.16.9)(eslint@8.15.0)(file-loader@6.2.0)(next@13.3.4)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) + '@nx/next': 16.6.0-beta.2(@babel/core@7.19.0)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/express@4.17.14)(@types/node@18.16.9)(eslint@8.15.0)(file-loader@6.2.0)(next@13.3.4)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) transitivePeerDependencies: - '@babel/core' - '@babel/traverse' @@ -6977,10 +7030,10 @@ packages: - webpack dev: true - /@nrwl/nx-cloud@16.0.5: - resolution: {integrity: sha512-1p82ym8WE9ziejwgPslstn19iV/VkHfHfKr/5YOnfCHQS+NxUf92ogcYhHXtqWLblVZ9Zs4W4pkSXK4e04wCmQ==} + /@nrwl/nx-cloud@16.1.0: + resolution: {integrity: sha512-OFjbSqdCuZq9KRYU/mOlIN8SYLZREsLlZYqYpObZqXJ5meUgBDJbUSwRweUSUvt73fgRixLEau2jPysiLHKxSQ==} dependencies: - nx-cloud: 16.0.5 + nx-cloud: 16.1.0 transitivePeerDependencies: - debug dev: true @@ -7147,14 +7200,16 @@ packages: dev: true optional: true - /@nrwl/react@16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0): - resolution: {integrity: sha512-KAyVVE6BdGI9V8bGRWCptK6lo0YuJ4hObGOUqSyn3XzIftb82drkzb0V3KOSWXRgpvqwp56wwzKmaZIbc3lAuA==} + /@nrwl/react@16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0): + resolution: {integrity: sha512-ZTOIw8TLF4AOsUZAEk+g+AZKZWIwELykfDs6tJj0EFFlx01e1arji6mMzUhKsOaF2pQWOzen0QREc1C0VjDq7w==} dependencies: - '@nx/react': 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) + '@nx/react': 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' - '@swc/core' + - '@swc/wasm' + - '@types/node' - debug - eslint - nx @@ -7164,14 +7219,16 @@ packages: - webpack dev: true - /@nrwl/storybook@16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(cypress@12.16.0)(eslint@8.15.0)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-/QtTmk6/LEsL96bV6wasTzNaVjK08WYo8fAqTO+kEa2LSfiV/XcQbfEh/GcbKpmR1p5NS9axQIzAlwYk7UPj0Q==} + /@nrwl/storybook@16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-VqFowBz40dgs/JSa5wmOIEUaXYxfe0wS/xn8CFVVY1u1ibpXkZrQWMXDpaamCv0mLDGDz6/hCy3GY51IRXLWhQ==} dependencies: - '@nx/storybook': 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(cypress@12.16.0)(eslint@8.15.0)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/storybook': 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4) transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' - '@swc/core' + - '@swc/wasm' + - '@types/node' - cypress - debug - eslint @@ -7203,25 +7260,27 @@ packages: - debug dev: true - /@nrwl/tao@16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51): - resolution: {integrity: sha512-RxBGaywZxKk+NzLmEuzqH2zsj27FE9ro5cTe8WGKSVcVINfErPk2i855jPhXNlXQK5Jy/4XIgkSzseIk5gntlg==} + /@nrwl/tao@16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51): + resolution: {integrity: sha512-Cbei96ajYpeWNCddVHntLpgO0KynG9KGnJXm5wADfoXX2NqtIjTsxmx4z5Xj4UZ79jAoFu8WgGs7b7sTRYLr2w==} hasBin: true dependencies: - nx: 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51) + nx: 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51) transitivePeerDependencies: - '@swc-node/register' - '@swc/core' - debug dev: true - /@nrwl/web@16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-hAOjlGwr8ziBQhHNeEl0hfjg5XU0ZtU8Scd59sZN4FuYSshEbvdbPiIIFPRdlpqiGuBdgHkxP+bSvaJxds4peQ==} + /@nrwl/web@16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-EuLCczifHPjArZX2TYE953y4n/D2AuFseWp3/QXJKMuuuQctmyuZBopLAahkd8eCOgIpQbqYFXQzecWduvD6qQ==} dependencies: - '@nx/web': 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/web': 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4) transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' - '@swc/core' + - '@swc/wasm' + - '@types/node' - debug - nx - supports-color @@ -7229,10 +7288,10 @@ packages: - verdaccio dev: true - /@nrwl/webpack@16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(esbuild@0.17.5)(html-webpack-plugin@5.5.0)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-YiH/IShupZXhI6+F9raoNVAipQlhwdkt+c3fVsKQ9KIQsEB0ToH5/IMZHGm3INWALvRsZAarNxFC8qcmqR8eQg==} + /@nrwl/webpack@16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(esbuild@0.17.5)(html-webpack-plugin@5.5.0)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-egIdVz/K+ywc4i4zmYK5wbpZcOaPtDp7LMi0ar0V8yWor2OfRV3Tg+TkVQBQnG9+EKeRQ6Ci2fzh+5sCRIvHOA==} dependencies: - '@nx/webpack': 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(esbuild@0.17.5)(html-webpack-plugin@5.5.0)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/webpack': 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(esbuild@0.17.5)(html-webpack-plugin@5.5.0)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4) transitivePeerDependencies: - '@babel/traverse' - '@parcel/css' @@ -7302,10 +7361,10 @@ packages: - typescript dev: true - /@nrwl/workspace@16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51): - resolution: {integrity: sha512-vo866Pl0yfxuXHBggRuRKM4JKJvXPMTjOf6Dq+UuOza0IJOGjY08mgPZPSl9BSxH4ONSMw8saGU0PTSlk3y17w==} + /@nrwl/workspace@16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51): + resolution: {integrity: sha512-0yLr995QhRzjT8DTlUGg6eiBU103fU8l0MqKbDrOyOVUk7YnI/WSIeWsLkxPWZsKNU32up/8mBAjDj/zNCQd8A==} dependencies: - '@nx/workspace': 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51) + '@nx/workspace': 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51) transitivePeerDependencies: - '@swc-node/register' - '@swc/core' @@ -7324,18 +7383,18 @@ packages: - encoding dev: true - /@nx/cypress@16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(cypress@12.16.0)(eslint@8.15.0)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-9/y9Phx2M8qQp3oHH4tQFEWxY5Sq3GZSmis3xdrpoAUrC3uVfu0HgD6iOzNMTeyBJacdtdgcdb5J8YmU3wy4+w==} + /@nx/cypress@16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-iXTQKy06fhIPSN9jJYQPFQJUpbzvmn+Cv841usBX980RqdUisgCnWZWF15OMs/pSml7BHDy75j6EFSkjPMxnkw==} peerDependencies: cypress: '>= 3 < 13' peerDependenciesMeta: cypress: optional: true dependencies: - '@nrwl/cypress': 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(cypress@12.16.0)(eslint@8.15.0)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/devkit': 16.5.0-beta.3(nx@16.5.0-beta.3) - '@nx/js': 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/linter': 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4) + '@nrwl/cypress': 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/devkit': 16.6.0-beta.2(nx@16.6.0-beta.2) + '@nx/js': 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/linter': 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4) '@phenomnomnominal/tsquery': 5.0.1(typescript@5.1.3) cypress: 12.16.0 detect-port: 1.5.1 @@ -7345,6 +7404,8 @@ packages: - '@babel/traverse' - '@swc-node/register' - '@swc/core' + - '@swc/wasm' + - '@types/node' - debug - eslint - nx @@ -7353,32 +7414,32 @@ packages: - verdaccio dev: true - /@nx/devkit@16.5.0-beta.3(nx@16.5.0-beta.3): - resolution: {integrity: sha512-60wgc7HhaBS0YDxRKOuRX9g8keswSiRLEu/SWfJWJrnyHeKUIegCq09KRX2rVtAT2pLVyb2STA3dhRC3Eut02Q==} + /@nx/devkit@16.6.0-beta.2(nx@16.6.0-beta.2): + resolution: {integrity: sha512-aWlFVSVsEbtCJ8Qv6GozeP2qdRV+a3gM5ZDb6ejP0um9ANA4XupREbHhCGUQG2On/0A4vLDFAlkjMZRPsxFLIg==} peerDependencies: nx: '>= 15 <= 17' dependencies: - '@nrwl/devkit': 16.5.0-beta.3(nx@16.5.0-beta.3) + '@nrwl/devkit': 16.6.0-beta.2(nx@16.6.0-beta.2) ejs: 3.1.8 ignore: 5.2.0 - nx: 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51) + nx: 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51) semver: 7.5.3 tmp: 0.2.1 tslib: 2.5.3 dev: true - /@nx/eslint-plugin@16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@typescript-eslint/parser@5.60.1)(eslint-config-prettier@8.5.0)(eslint@8.15.0)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-b36qroInlZqd0fWm2p7n23tXlPwElgZAw5qnqHRjbAgKysX6d6Zodr4quNKh1x3q4HedafXkKx7h2NKvZXGRPg==} + /@nx/eslint-plugin@16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(@typescript-eslint/parser@5.60.1)(eslint-config-prettier@8.5.0)(eslint@8.15.0)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-u5pxhRvLdv64CrfnZYDDXmMWEWm+83e/Y5NJMUSXeIkY1E4DMw36iZ0/mAS/L8IjtSlzuig7oaTUfOw0Zpi53A==} peerDependencies: - '@typescript-eslint/parser': ^5.58.0 + '@typescript-eslint/parser': ^5.60.1 eslint-config-prettier: ^8.1.0 peerDependenciesMeta: eslint-config-prettier: optional: true dependencies: - '@nrwl/eslint-plugin-nx': 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@typescript-eslint/parser@5.60.1)(eslint-config-prettier@8.5.0)(eslint@8.15.0)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/devkit': 16.5.0-beta.3(nx@16.5.0-beta.3) - '@nx/js': 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4) + '@nrwl/eslint-plugin-nx': 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(@typescript-eslint/parser@5.60.1)(eslint-config-prettier@8.5.0)(eslint@8.15.0)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/devkit': 16.6.0-beta.2(nx@16.6.0-beta.2) + '@nx/js': 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4) '@typescript-eslint/parser': 5.60.1(eslint@8.15.0)(typescript@5.1.3) '@typescript-eslint/type-utils': 5.60.1(eslint@8.15.0)(typescript@5.1.3) '@typescript-eslint/utils': 5.60.1(eslint@8.15.0)(typescript@5.1.3) @@ -7391,6 +7452,8 @@ packages: - '@babel/traverse' - '@swc-node/register' - '@swc/core' + - '@swc/wasm' + - '@types/node' - debug - eslint - nx @@ -7399,14 +7462,14 @@ packages: - verdaccio dev: true - /@nx/jest@16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.5.0-beta.3)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-rzSSqzx+rUA0gFIFvgSwbWAwhNxutEx/AxmozE5IN+IxnG5+XsjhtRbxp5HvO3sFv8b4yHdJRzOnt08bzJy8AQ==} + /@nx/jest@16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.2)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-IXDlGRk6HJEKdl9YJ29SNowX5/iGGyYH7gOcL/c/4FXtpmRr3wXoZaUaat+bXSFlDEZcaEwkXS6CMOZFsl0A1A==} dependencies: '@jest/reporters': 29.5.0 '@jest/test-result': 29.5.0 - '@nrwl/jest': 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.5.0-beta.3)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/devkit': 16.5.0-beta.3(nx@16.5.0-beta.3) - '@nx/js': 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4) + '@nrwl/jest': 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.2)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/devkit': 16.6.0-beta.2(nx@16.6.0-beta.2) + '@nx/js': 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4) '@phenomnomnominal/tsquery': 5.0.1(typescript@5.1.3) chalk: 4.1.2 dotenv: 10.0.0 @@ -7420,6 +7483,7 @@ packages: - '@babel/traverse' - '@swc-node/register' - '@swc/core' + - '@swc/wasm' - '@types/node' - debug - node-notifier @@ -7430,8 +7494,8 @@ packages: - verdaccio dev: true - /@nx/js@16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-/5oeMyS3ig0/RhFQ7NgmAljGOgsmLORVr0HpfEA9ufaCg7jVGqp/rE+ljfjbvF0lPqpVpbxU6yt/vidajqlrmg==} + /@nx/js@16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-qI2JtZo6eSLUjap1NFnGAu/PWHJTIbkMo0dquC2/oaETTDmZOuEpTylGq49Oyz4AgSc5P/NhayIftAL0x1bJtQ==} peerDependencies: verdaccio: ^5.0.4 peerDependenciesMeta: @@ -7445,9 +7509,9 @@ packages: '@babel/preset-env': 7.22.5(@babel/core@7.22.5) '@babel/preset-typescript': 7.21.4(@babel/core@7.22.5) '@babel/runtime': 7.22.5 - '@nrwl/js': 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/devkit': 16.5.0-beta.3(nx@16.5.0-beta.3) - '@nx/workspace': 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51) + '@nrwl/js': 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/devkit': 16.6.0-beta.2(nx@16.6.0-beta.2) + '@nx/workspace': 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51) '@phenomnomnominal/tsquery': 5.0.1(typescript@5.1.3) babel-plugin-const-enum: 1.2.0(@babel/core@7.22.5) babel-plugin-macros: 2.8.0 @@ -7461,29 +7525,33 @@ packages: minimatch: 3.0.5 semver: 7.5.3 source-map-support: 0.5.19 + ts-node: 10.9.1(@swc/core@1.3.51)(@types/node@18.16.9)(typescript@5.1.3) + tsconfig-paths: 4.1.2 tslib: 2.5.3 verdaccio: 5.15.4(typanion@3.12.1) transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' - '@swc/core' + - '@swc/wasm' + - '@types/node' - debug - nx - supports-color - typescript dev: true - /@nx/linter@16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-aHLveHVWToc0suvMVhbf3bGPJ9B2h5cJBA2vPZfaVP0wP7WiTdWftM1rFTP7LVYwgN5x6TRk6unbjKzEITlBoA==} + /@nx/linter@16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-JhMgaJZmxSSz2a4LmgtsqYmwFwLLdePM/f4GHL4W7UZbERHUFr868HvNW8GXxlRyGohLKs3ezN6lGWQPd6NDng==} peerDependencies: eslint: ^8.0.0 peerDependenciesMeta: eslint: optional: true dependencies: - '@nrwl/linter': 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/devkit': 16.5.0-beta.3(nx@16.5.0-beta.3) - '@nx/js': 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4) + '@nrwl/linter': 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/devkit': 16.6.0-beta.2(nx@16.6.0-beta.2) + '@nx/js': 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4) '@phenomnomnominal/tsquery': 5.0.1(typescript@5.1.3) eslint: 8.15.0 tmp: 0.2.1 @@ -7492,6 +7560,8 @@ packages: - '@babel/traverse' - '@swc-node/register' - '@swc/core' + - '@swc/wasm' + - '@types/node' - debug - nx - supports-color @@ -7499,19 +7569,19 @@ packages: - verdaccio dev: true - /@nx/next@16.5.0-beta.3(@babel/core@7.19.0)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/express@4.17.14)(@types/node@18.16.9)(eslint@8.15.0)(file-loader@6.2.0)(next@13.3.4)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0): - resolution: {integrity: sha512-pzyZpAxogxzqaxzOBeVBESURuWo/UkyOu4ENMWmbywY3ChYTJt2G0NHNwPQwUjSoWnWWUR4ZUUtK9CrullUjRQ==} + /@nx/next@16.6.0-beta.2(@babel/core@7.19.0)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/express@4.17.14)(@types/node@18.16.9)(eslint@8.15.0)(file-loader@6.2.0)(next@13.3.4)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0): + resolution: {integrity: sha512-e/5hg+ZefQazSkW6XdDwefToAqzdm30T8y/7t/K2Ax8VxA11q1JpghXWILsGc0e1fdY/8wz6BmZfGLMv4R8NXw==} peerDependencies: next: '>=13.0.0' dependencies: '@babel/plugin-proposal-decorators': 7.21.0(@babel/core@7.19.0) - '@nrwl/next': 16.5.0-beta.3(@babel/core@7.19.0)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/express@4.17.14)(@types/node@18.16.9)(eslint@8.15.0)(file-loader@6.2.0)(next@13.3.4)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) - '@nx/devkit': 16.5.0-beta.3(nx@16.5.0-beta.3) - '@nx/js': 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/linter': 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/react': 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) - '@nx/web': 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/workspace': 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51) + '@nrwl/next': 16.6.0-beta.2(@babel/core@7.19.0)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/express@4.17.14)(@types/node@18.16.9)(eslint@8.15.0)(file-loader@6.2.0)(next@13.3.4)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) + '@nx/devkit': 16.6.0-beta.2(nx@16.6.0-beta.2) + '@nx/js': 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/linter': 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/react': 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) + '@nx/web': 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/workspace': 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51) '@svgr/webpack': 8.0.1 chalk: 4.1.2 copy-webpack-plugin: 10.2.4(webpack@5.88.0) @@ -7522,8 +7592,6 @@ packages: ignore: 5.2.0 next: 13.3.4(@babel/core@7.19.0)(react-dom@18.2.0)(react@18.2.0)(sass@1.55.0) semver: 7.5.3 - ts-node: 10.9.1(@swc/core@1.3.51)(@types/node@18.16.9)(typescript@5.1.3) - tsconfig-paths: 4.1.2 url-loader: 4.1.1(file-loader@6.2.0)(webpack@5.88.0) webpack-merge: 5.9.0 transitivePeerDependencies: @@ -7544,8 +7612,8 @@ packages: - webpack dev: true - /@nx/nx-darwin-arm64@16.5.0-beta.3: - resolution: {integrity: sha512-DGvJ9rgTLND+KPmuEK9gYOvuSlXGC19twkdf3ezI4blTmrZduoSZ9l5JQyexN2BTBLHHuxEZ8JhVctaTsqlT5g==} + /@nx/nx-darwin-arm64@16.6.0-beta.2: + resolution: {integrity: sha512-ywXlLuhkM20SVB45bstgGvTduE+/GQ2kzBW7947rSvArBCULDOMuBl6/zryAebNq45yHjM1z7Oqm4J5SxbPsMw==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] @@ -7553,8 +7621,8 @@ packages: dev: true optional: true - /@nx/nx-darwin-x64@16.5.0-beta.3: - resolution: {integrity: sha512-DPx1yhXL+lsnfM168yETXCaItgwYTn6xcwT8ZzxS17AJZkGkZup0x0L8gm+frcPFxJEqoB/ZCLxdmPNphBoQ3g==} + /@nx/nx-darwin-x64@16.6.0-beta.2: + resolution: {integrity: sha512-Xq5Retfo4yMbJxTUam3l/nGthFFfQYqO2iYuDqKcOfWBMwoOvADHTiBn0I9207gqkxDUrC4ZaMX1gc53HMaUxg==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] @@ -7562,8 +7630,8 @@ packages: dev: true optional: true - /@nx/nx-freebsd-x64@16.5.0-beta.3: - resolution: {integrity: sha512-22JraKQEST1p4wkeQXt12PNV2txXzlTt329Iz4AjAbk/FhI0wB1vPnXhn0wqDO2SWYGoOXj43gH1iAAwtamTRg==} + /@nx/nx-freebsd-x64@16.6.0-beta.2: + resolution: {integrity: sha512-TqEYZZm2wnh2WHajBIqT+9GFFFm13Ln7I0LmhDV32EDGkEvM1IhV+JLnUYwB67eWEnOx61TyqXDbqvroK0EdoQ==} engines: {node: '>= 10'} cpu: [x64] os: [freebsd] @@ -7571,8 +7639,8 @@ packages: dev: true optional: true - /@nx/nx-linux-arm-gnueabihf@16.5.0-beta.3: - resolution: {integrity: sha512-+HAEVo76v3wgMkusOJGi65MNXDJkUXyQMIPU6wXjmZOgN2ZZebKP/58bo0VBW17wCYfDKIf60vWbhYD7J4ki0A==} + /@nx/nx-linux-arm-gnueabihf@16.6.0-beta.2: + resolution: {integrity: sha512-0Ed+ErhtbpkzBkN1Md78A8iIHOXufj30TuNSC8poo17Ci0fXkPs645CCLStn7I1TzFE7XnM5DKsnn2gcQXmm1g==} engines: {node: '>= 10'} cpu: [arm] os: [linux] @@ -7580,8 +7648,8 @@ packages: dev: true optional: true - /@nx/nx-linux-arm64-gnu@16.5.0-beta.3: - resolution: {integrity: sha512-r4VphGLVNIHAvNBhQaGAmxOyddFPQC5CzasqlG4nuEIIdQL9kqw9k8wXO/aB3LHjVsImQLQ/kpxBCJsqOh48bw==} + /@nx/nx-linux-arm64-gnu@16.6.0-beta.2: + resolution: {integrity: sha512-lzB9d9SA8fXC9KlMLyfhi6k9Rhxeld25ZDIiqfg8QmCtUgy4Nb4O09ryPS+8QJVDp6+SFgJa9jWWMrzYKUpcAQ==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -7589,8 +7657,8 @@ packages: dev: true optional: true - /@nx/nx-linux-arm64-musl@16.5.0-beta.3: - resolution: {integrity: sha512-P1ggXPGbVBv40ofkdJWS7m1JmKCU8e3Fh6I5z32XRzq8oYYLm08q3mI/U968F+bN7rZHAU7rv9reTK/WKxI3PQ==} + /@nx/nx-linux-arm64-musl@16.6.0-beta.2: + resolution: {integrity: sha512-spQmfDXFn77+0Z9+OPYQXu4tFfHjpOAS1ZuLZOwWPyh4DjTxk7xPOgngxLs3ZnnOAYFspkc/tRCZ16/3H5+WVA==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -7598,8 +7666,8 @@ packages: dev: true optional: true - /@nx/nx-linux-x64-gnu@16.5.0-beta.3: - resolution: {integrity: sha512-78qFKDKrm2/XHIQ4sHg+C6EfFt8lXs5GeWdP4Ik+STxxdzZBbCzeXeHLGpRiv6UZ1vn0g2tvI7nP97gxBpO+cA==} + /@nx/nx-linux-x64-gnu@16.6.0-beta.2: + resolution: {integrity: sha512-C2yLKQcHNSfYKVKx/cbSlWzoqLDViwSgsqxP9JGj7vAAX88cxxxOcFXd4q5ltP0il9TjH8G2cEMKVXT8VyPDDw==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -7607,8 +7675,8 @@ packages: dev: true optional: true - /@nx/nx-linux-x64-musl@16.5.0-beta.3: - resolution: {integrity: sha512-4X5yPPo3FwAEFuZFx+snN6h+9o2iGBwKemze4QZGHyrYkPyYGZt8uExuBXziiUylra2f9p2JyENCa50YR1rOig==} + /@nx/nx-linux-x64-musl@16.6.0-beta.2: + resolution: {integrity: sha512-OdfV0UJTohwatNXa4ptxblYPvDvMIraNwc7OeCYiQ8R5P8G5iP3OQUVF71VXKV9a1GlwfdSe8F04JhXzRocWRA==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -7616,8 +7684,8 @@ packages: dev: true optional: true - /@nx/nx-win32-arm64-msvc@16.5.0-beta.3: - resolution: {integrity: sha512-uJW6YLwZ64zNJDHgEstT3lQwMZFZVakjJkobKWmp3+6ZMaGJjNUeIxw/maRcttmUNcmZh0is3yMHVvQtp/RFqw==} + /@nx/nx-win32-arm64-msvc@16.6.0-beta.2: + resolution: {integrity: sha512-0T7EiFUkdvrbeyUmBFAewzM2NF2zZthAcMYfZQMy8A+TQabSyU02nsx41pNqRjsvEvqyYff32oaYryR/upWLIw==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] @@ -7625,8 +7693,8 @@ packages: dev: true optional: true - /@nx/nx-win32-x64-msvc@16.5.0-beta.3: - resolution: {integrity: sha512-gYZpIABDYA57v/tg37uIAXxlI4ci6vbTtMNTqWdSICyZZNJ2f83HSuXiwCZYuYPNTCsVbLzp4z0TKceSL1BZbw==} + /@nx/nx-win32-x64-msvc@16.6.0-beta.2: + resolution: {integrity: sha512-9JRl9oVufSNuKPuMJru25OsRV7IHBzpv35Tbs8ZPKGK8fD8cVwZLxbkh4mhi+N8gFyjRi/7WRq7U9wHodX5Mzg==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -7634,14 +7702,14 @@ packages: dev: true optional: true - /@nx/react@16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0): - resolution: {integrity: sha512-JmUNntBoPzEckWg5Pt/VljXPHCQ9uC/P+TyezL+Q58YoaEyx62cK/SBkx8DpyiG1Q1hKgeg08ZuPvAClcJ+hQg==} + /@nx/react@16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0): + resolution: {integrity: sha512-+HfVXMA3sIyq5+LFuR7hugEWXa7KxhRs1Y5/wogxJC+mCEo6L5g+xOQP61F0atdvNLtwxkKbjWjZCe9by85Giw==} dependencies: - '@nrwl/react': 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) - '@nx/devkit': 16.5.0-beta.3(nx@16.5.0-beta.3) - '@nx/js': 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/linter': 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/web': 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4) + '@nrwl/react': 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) + '@nx/devkit': 16.6.0-beta.2(nx@16.6.0-beta.2) + '@nx/js': 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/linter': 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/web': 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4) '@phenomnomnominal/tsquery': 5.0.1(typescript@5.1.3) '@svgr/webpack': 8.0.1 chalk: 4.1.2 @@ -7651,6 +7719,8 @@ packages: - '@babel/traverse' - '@swc-node/register' - '@swc/core' + - '@swc/wasm' + - '@types/node' - debug - eslint - nx @@ -7660,15 +7730,15 @@ packages: - webpack dev: true - /@nx/storybook@16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(cypress@12.16.0)(eslint@8.15.0)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-gwt5RAYspXUmBoEE4BVsCqC+eR9GCb99h36KjGR4/OOJjCw+PGCkDH+3h0B3rY3cmuKLrLKVpgBjAP1XOx+8Kg==} + /@nx/storybook@16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-x4eD1kME8xuP0fPAm5kLbnos0CC9tlupKxKGi0jzKWVyj+BzyN2ChrUAfw3+u/+qjuNdZCh9bqDlt2HBDM8YFQ==} dependencies: - '@nrwl/storybook': 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(cypress@12.16.0)(eslint@8.15.0)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/cypress': 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(cypress@12.16.0)(eslint@8.15.0)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/devkit': 16.5.0-beta.3(nx@16.5.0-beta.3) - '@nx/js': 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/linter': 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/workspace': 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51) + '@nrwl/storybook': 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/cypress': 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/devkit': 16.6.0-beta.2(nx@16.6.0-beta.2) + '@nx/js': 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/linter': 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/workspace': 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51) '@phenomnomnominal/tsquery': 5.0.1(typescript@5.1.3) dotenv: 10.0.0 semver: 7.5.3 @@ -7676,6 +7746,8 @@ packages: - '@babel/traverse' - '@swc-node/register' - '@swc/core' + - '@swc/wasm' + - '@types/node' - cypress - debug - eslint @@ -7685,12 +7757,12 @@ packages: - verdaccio dev: true - /@nx/web@16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-yRAv8Whc7q9xdLzKUywkrw9S1UTVVFD9WcHB//XxjdO7R/xlGRf4O0LLCiFDAMjjeSbqt9zYDD3WzhTEginzUQ==} + /@nx/web@16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-wVmfrdytmHXEHNu3SI/s1WiXkqup3c5YK3FmjrgPxsRQi/7FFuTHFu6XU57rC+0qhzWjSCEJAIpGlXf/Wr6TJg==} dependencies: - '@nrwl/web': 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/devkit': 16.5.0-beta.3(nx@16.5.0-beta.3) - '@nx/js': 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4) + '@nrwl/web': 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/devkit': 16.6.0-beta.2(nx@16.6.0-beta.2) + '@nx/js': 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4) chalk: 4.1.2 chokidar: 3.5.3 detect-port: 1.5.1 @@ -7701,6 +7773,8 @@ packages: - '@babel/traverse' - '@swc-node/register' - '@swc/core' + - '@swc/wasm' + - '@types/node' - debug - nx - supports-color @@ -7708,13 +7782,13 @@ packages: - verdaccio dev: true - /@nx/webpack@16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(esbuild@0.17.5)(html-webpack-plugin@5.5.0)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-xzPdeWZIUFKXK/ONU7vSwHqRaiCdJFxwuCrnBa4VBDZUiz8A/oYkSCy+A2NhZC0bJfzAYbqqVXptWXZhBZ2VaA==} + /@nx/webpack@16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(esbuild@0.17.5)(html-webpack-plugin@5.5.0)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-Z6Qd7/JXgbSiGSSajRz8VyXcCppUh4liH7dmxY3FbyrLAxOHTvA+Y2m76CiRLx7K6nVhDgwnKaiy3NTCXz7lBw==} dependencies: '@babel/core': 7.22.5 - '@nrwl/webpack': 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(esbuild@0.17.5)(html-webpack-plugin@5.5.0)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/devkit': 16.5.0-beta.3(nx@16.5.0-beta.3) - '@nx/js': 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51)(nx@16.5.0-beta.3)(typescript@5.1.3)(verdaccio@5.15.4) + '@nrwl/webpack': 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(esbuild@0.17.5)(html-webpack-plugin@5.5.0)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/devkit': 16.6.0-beta.2(nx@16.6.0-beta.2) + '@nx/js': 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.2)(typescript@5.1.3)(verdaccio@5.15.4) autoprefixer: 10.4.13(postcss@8.4.19) babel-loader: 9.1.2(@babel/core@7.22.5)(webpack@5.88.0) browserslist: 4.21.7 @@ -7744,8 +7818,6 @@ packages: stylus-loader: 7.1.0(stylus@0.59.0)(webpack@5.88.0) terser-webpack-plugin: 5.3.9(@swc/core@1.3.51)(esbuild@0.17.5)(webpack@5.88.0) ts-loader: 9.4.1(typescript@5.1.3)(webpack@5.88.0) - ts-node: 10.9.1(@swc/core@1.3.51)(@types/node@18.16.9)(typescript@5.1.3) - tsconfig-paths: 4.1.2 tsconfig-paths-webpack-plugin: 4.0.0 tslib: 2.5.3 webpack: 5.88.0(@swc/core@1.3.51)(esbuild@0.17.5) @@ -7780,11 +7852,11 @@ packages: - webpack-cli dev: true - /@nx/workspace@16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51): - resolution: {integrity: sha512-Sfh1nyxuucb5urxSCLgKQ7bCZDLerS/AWM5Tfn8dwYSimifyEkTEI+MOrz8EK8iJ4ALpQI9Pm2OwmBkyfdmh/w==} + /@nx/workspace@16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51): + resolution: {integrity: sha512-SEEJPZ+cSrDOWU00GsQL/6qORFS+74N2zOWBReC+PG7LGZAsq7Peqwt40WiAmndNnFHYLEX+i4hw31b0G61nUA==} dependencies: - '@nrwl/workspace': 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51) - '@nx/devkit': 16.5.0-beta.3(nx@16.5.0-beta.3) + '@nrwl/workspace': 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51) + '@nx/devkit': 16.6.0-beta.2(nx@16.6.0-beta.2) '@parcel/watcher': 2.0.4 chalk: 4.1.2 chokidar: 3.5.3 @@ -7796,7 +7868,7 @@ packages: ignore: 5.2.0 minimatch: 3.0.5 npm-run-path: 4.0.1 - nx: 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51) + nx: 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51) open: 8.4.2 rxjs: 7.8.1 tmp: 0.2.1 @@ -8292,7 +8364,7 @@ packages: dependencies: immer: 9.0.16 react: 18.2.0 - react-redux: 8.0.5(@types/react-dom@18.2.6)(@types/react@18.2.13)(react-dom@18.2.0)(react@18.2.0)(redux@4.2.0) + react-redux: 8.0.5(@types/react-dom@18.2.6)(@types/react@18.2.14)(react-dom@18.2.0)(react@18.2.0)(redux@4.2.0) redux: 4.2.0 redux-thunk: 2.4.2(redux@4.2.0) reselect: 4.1.7 @@ -8479,6 +8551,19 @@ packages: - chokidar dev: true + /@side/jest-runtime@1.1.0(@jest/transform@29.5.0)(jest-runtime@29.5.0)(jest@29.4.3): + resolution: {integrity: sha512-KikALXowNWyOxn/zdy4AUgkYq/1hASkOEEP0+bcCDv5L3KJNwDw8kmzBcx7sljnwV8yi2cLGzt9QH9EjwA9TKg==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + peerDependencies: + '@jest/transform': '>=28' + jest: '>=28' + jest-runtime: '>=28' + dependencies: + '@jest/transform': 29.5.0 + jest: 29.4.3(@types/node@18.16.9)(ts-node@10.9.1) + jest-runtime: 29.5.0 + dev: true + /@sigstore/protobuf-specs@0.1.0: resolution: {integrity: sha512-a31EnjuIDSX8IXBUib3cYLDRlPMU36AWX4xS8ysLaNu4ZzUesDiPt83pgrW2X1YLMe5L2HbDyaKK5BrL4cNKaQ==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} @@ -10328,7 +10413,7 @@ packages: /@types/hoist-non-react-statics@3.3.1: resolution: {integrity: sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==} dependencies: - '@types/react': 18.2.13 + '@types/react': 18.2.14 hoist-non-react-statics: 3.3.2 dev: true @@ -10544,11 +10629,11 @@ packages: /@types/react-dom@18.2.6: resolution: {integrity: sha512-2et4PDvg6PVCyS7fuTc4gPoksV58bW0RwSxWKcPRcHZf0PRUGq03TKcD/rUHe3azfV6/5/biUBJw+HhCQjaP0A==} dependencies: - '@types/react': 18.2.13 + '@types/react': 18.2.14 dev: true - /@types/react@18.2.13: - resolution: {integrity: sha512-vJ+zElvi/Zn9cVXB5slX2xL8PZodPCwPRDpittQdw43JR2AJ5k3vKdgJJyneV/cYgIbLQUwXa9JVDvUZXGba+Q==} + /@types/react@18.2.14: + resolution: {integrity: sha512-A0zjq+QN/O0Kpe30hA1GidzyFjatVvrpIvWLxD+xv67Vt91TWWgco9IvrJBkeyHm1trGaFS/FSGqPlhyeZRm0g==} dependencies: '@types/prop-types': 15.7.5 '@types/scheduler': 0.16.2 @@ -11377,7 +11462,7 @@ packages: xstate: 4.34.0 dev: true - /@xstate/react@3.0.1(@types/react@18.2.13)(react@18.2.0)(xstate@4.34.0): + /@xstate/react@3.0.1(@types/react@18.2.14)(react@18.2.0)(xstate@4.34.0): resolution: {integrity: sha512-/tq/gg92P9ke8J+yDNDBv5/PAxBvXJf2cYyGDByzgtl5wKaxKxzDT82Gj3eWlCJXkrBg4J5/V47//gRJuVH2fA==} peerDependencies: '@xstate/fsm': ^2.0.0 @@ -11390,7 +11475,7 @@ packages: optional: true dependencies: react: 18.2.0 - use-isomorphic-layout-effect: 1.1.2(@types/react@18.2.13)(react@18.2.0) + use-isomorphic-layout-effect: 1.1.2(@types/react@18.2.14)(react@18.2.0) use-sync-external-store: 1.2.0(react@18.2.0) xstate: 4.34.0 transitivePeerDependencies: @@ -11831,7 +11916,7 @@ packages: /argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - /aria-hidden@1.2.2(@types/react@18.2.13)(react@18.2.0): + /aria-hidden@1.2.2(@types/react@18.2.14)(react@18.2.0): resolution: {integrity: sha512-6y/ogyDTk/7YAe91T3E2PR1ALVKyM2QbTio5HwM+N1Q6CMlCKhvClyIjkckBswa0f2xJhjsfzIGa1yVSe1UMVA==} engines: {node: '>=10'} peerDependencies: @@ -11841,7 +11926,7 @@ packages: '@types/react': optional: true dependencies: - '@types/react': 18.2.13 + '@types/react': 18.2.14 react: 18.2.0 tslib: 2.5.3 dev: true @@ -12834,6 +12919,7 @@ packages: /buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + dev: true /buffer-indexof-polyfill@1.0.2: resolution: {integrity: sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==} @@ -13414,6 +13500,7 @@ packages: /commander@2.20.3: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + dev: true /commander@4.1.1: resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} @@ -20833,17 +20920,17 @@ packages: resolution: {integrity: sha512-NHj4rzRo0tQdijE9ZqAx6kYDcoRwYwSYzCA8MY3JzfxlrvEU0jhnhJT9BhqhJs7I/dKcrDm6TyulaRqZPIhN5g==} dev: true - /nx-cloud@16.0.5: - resolution: {integrity: sha512-13P7r0aKikjBtmdZrNorwXzVPeVIV4MLEwqGY+DEG6doLBtI5KqEQk/d5B5l2dCF2BEi/LXEmLYCmf9gwbOJ+Q==} + /nx-cloud@16.1.0: + resolution: {integrity: sha512-2K5OuJ4MEDrn2solje2X+a3UxSCdfR5PIscCRQbBANyvJfl3hGJSTxz0n5xeJJX4cKcQlfAxDQFRH6DHNdTGPQ==} hasBin: true dependencies: - '@nrwl/nx-cloud': 16.0.5 + '@nrwl/nx-cloud': 16.1.0 axios: 1.1.3 chalk: 4.1.2 dotenv: 10.0.0 - fs-extra: 11.1.0 + fs-extra: 11.1.1 node-machine-id: 1.1.12 - open: 8.4.1 + open: 8.4.2 strip-json-comments: 3.1.1 tar: 6.1.11 yargs-parser: 21.1.1 @@ -20979,8 +21066,8 @@ packages: - debug dev: true - /nx@16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51): - resolution: {integrity: sha512-kCaFZ30KXZBV1WgmIN0ePKoiSY8HHcVJpVrBZK+ovyqgpEMqfggjI9QpvzNsM4KnJNKGsbEqwVwUBjgDFViMeg==} + /nx@16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51): + resolution: {integrity: sha512-9s6bGKROGvNB+iyOc2wJISq/Yn4lXv0OOtOD7K9B/1mDDQ7VFpwRgRfUbPFsTvnZcZrS93jr4BQ90On/iHQTsQ==} hasBin: true requiresBuild: true peerDependencies: @@ -20992,7 +21079,7 @@ packages: '@swc/core': optional: true dependencies: - '@nrwl/tao': 16.5.0-beta.3(@swc-node/register@1.5.4)(@swc/core@1.3.51) + '@nrwl/tao': 16.6.0-beta.2(@swc-node/register@1.5.4)(@swc/core@1.3.51) '@parcel/watcher': 2.0.4 '@swc-node/register': 1.5.4(@swc/core@1.3.51)(typescript@5.1.3) '@swc/core': 1.3.51(@swc/helpers@0.5.0) @@ -21016,6 +21103,7 @@ packages: jsonc-parser: 3.2.0 lines-and-columns: 2.0.3 minimatch: 3.0.5 + node-machine-id: 1.1.12 npm-run-path: 4.0.1 open: 8.4.2 semver: 7.5.3 @@ -21029,16 +21117,16 @@ packages: yargs: 17.7.2 yargs-parser: 21.1.1 optionalDependencies: - '@nx/nx-darwin-arm64': 16.5.0-beta.3 - '@nx/nx-darwin-x64': 16.5.0-beta.3 - '@nx/nx-freebsd-x64': 16.5.0-beta.3 - '@nx/nx-linux-arm-gnueabihf': 16.5.0-beta.3 - '@nx/nx-linux-arm64-gnu': 16.5.0-beta.3 - '@nx/nx-linux-arm64-musl': 16.5.0-beta.3 - '@nx/nx-linux-x64-gnu': 16.5.0-beta.3 - '@nx/nx-linux-x64-musl': 16.5.0-beta.3 - '@nx/nx-win32-arm64-msvc': 16.5.0-beta.3 - '@nx/nx-win32-x64-msvc': 16.5.0-beta.3 + '@nx/nx-darwin-arm64': 16.6.0-beta.2 + '@nx/nx-darwin-x64': 16.6.0-beta.2 + '@nx/nx-freebsd-x64': 16.6.0-beta.2 + '@nx/nx-linux-arm-gnueabihf': 16.6.0-beta.2 + '@nx/nx-linux-arm64-gnu': 16.6.0-beta.2 + '@nx/nx-linux-arm64-musl': 16.6.0-beta.2 + '@nx/nx-linux-x64-gnu': 16.6.0-beta.2 + '@nx/nx-linux-x64-musl': 16.6.0-beta.2 + '@nx/nx-win32-arm64-msvc': 16.6.0-beta.2 + '@nx/nx-win32-x64-msvc': 16.6.0-beta.2 transitivePeerDependencies: - debug dev: true @@ -23386,7 +23474,7 @@ packages: resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==} dev: true - /react-redux@8.0.5(@types/react-dom@18.2.6)(@types/react@18.2.13)(react-dom@18.2.0)(react@18.2.0)(redux@4.2.0): + /react-redux@8.0.5(@types/react-dom@18.2.6)(@types/react@18.2.14)(react-dom@18.2.0)(react@18.2.0)(redux@4.2.0): resolution: {integrity: sha512-Q2f6fCKxPFpkXt1qNRZdEDLlScsDWyrgSj0mliK59qU6W5gvBiKkdMEG2lJzhd1rCctf0hb6EtePPLZ2e0m1uw==} peerDependencies: '@types/react': ^16.8 || ^17.0 || ^18.0 @@ -23409,7 +23497,7 @@ packages: dependencies: '@babel/runtime': 7.21.0 '@types/hoist-non-react-statics': 3.3.1 - '@types/react': 18.2.13 + '@types/react': 18.2.14 '@types/react-dom': 18.2.6 '@types/use-sync-external-store': 0.0.3 hoist-non-react-statics: 3.3.2 @@ -24226,6 +24314,7 @@ packages: chokidar: 3.5.3 immutable: 4.1.0 source-map-js: 1.0.2 + dev: true /sax@1.2.4: resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==} @@ -24822,6 +24911,7 @@ packages: dependencies: buffer-from: 1.1.2 source-map: 0.6.1 + dev: true /source-map@0.6.1: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} @@ -25706,6 +25796,7 @@ packages: acorn: 8.8.2 commander: 2.20.3 source-map-support: 0.5.21 + dev: true /terser@5.18.0: resolution: {integrity: sha512-pdL757Ig5a0I+owA42l6tIuEycRuM7FPY4n62h44mRLRfnOxJkkOHd6i89dOpwZlpF6JXBwaAHF6yWzFrt+QyA==} @@ -26573,7 +26664,7 @@ packages: requires-port: 1.0.0 dev: true - /use-isomorphic-layout-effect@1.1.2(@types/react@18.2.13)(react@18.2.0): + /use-isomorphic-layout-effect@1.1.2(@types/react@18.2.14)(react@18.2.0): resolution: {integrity: sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==} peerDependencies: '@types/react': '*' @@ -26582,7 +26673,7 @@ packages: '@types/react': optional: true dependencies: - '@types/react': 18.2.13 + '@types/react': 18.2.14 react: 18.2.0 dev: true @@ -26806,7 +26897,7 @@ packages: mlly: 1.2.0 pathe: 1.1.0 picocolors: 1.0.0 - vite: 4.3.9(@types/node@18.16.9)(less@4.1.3)(sass@1.63.2)(stylus@0.59.0)(terser@5.17.7) + vite: 4.3.9(@types/node@18.16.9)(less@4.1.3)(sass@1.55.0)(stylus@0.59.0) transitivePeerDependencies: - '@types/node' - less @@ -26852,6 +26943,42 @@ packages: optionalDependencies: fsevents: 2.3.2 + /vite@4.3.9(@types/node@18.16.9)(less@4.1.3)(sass@1.55.0)(stylus@0.59.0): + resolution: {integrity: sha512-qsTNZjO9NoJNW7KnOrgYwczm0WctJ8m/yqYAMAK9Lxt4SoySUfS5S8ia9K7JHpa3KEeMfyF8LoJ3c5NeBJy6pg==} + engines: {node: ^14.18.0 || >=16.0.0} + hasBin: true + peerDependencies: + '@types/node': '>= 14' + less: '*' + sass: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + dependencies: + '@types/node': 18.16.9 + esbuild: 0.17.19 + less: 4.1.3 + postcss: 8.4.24 + rollup: 3.21.0 + sass: 1.55.0 + stylus: 0.59.0 + optionalDependencies: + fsevents: 2.3.2 + dev: false + /vite@4.3.9(@types/node@18.16.9)(less@4.1.3)(sass@1.63.2)(stylus@0.59.0)(terser@5.17.7): resolution: {integrity: sha512-qsTNZjO9NoJNW7KnOrgYwczm0WctJ8m/yqYAMAK9Lxt4SoySUfS5S8ia9K7JHpa3KEeMfyF8LoJ3c5NeBJy6pg==} engines: {node: ^14.18.0 || >=16.0.0} @@ -26887,6 +27014,7 @@ packages: terser: 5.17.7 optionalDependencies: fsevents: 2.3.2 + dev: true /vitest@0.32.0(less@4.1.3)(sass@1.55.0)(stylus@0.59.0): resolution: {integrity: sha512-SW83o629gCqnV3BqBnTxhB10DAwzwEx3z+rqYZESehUB+eWsJxwcBQx7CKy0otuGMJTYh7qCVuUX23HkftGl/Q==} @@ -27892,7 +28020,3 @@ packages: dependencies: tslib: 2.5.3 dev: true - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false From cd8c61d7a3b8ab9bc7bab068f5ca49bbf14abbf5 Mon Sep 17 00:00:00 2001 From: FrozenPandaz Date: Fri, 14 Jul 2023 18:14:54 -0400 Subject: [PATCH 080/262] chore(misc): publish 16.6.0-beta.3 --- lerna.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lerna.json b/lerna.json index 74dbcdc0b8ff9..4fac41b8c4477 100644 --- a/lerna.json +++ b/lerna.json @@ -1,6 +1,6 @@ { "packages": ["build/packages/*", "build/packages/nx/native-packages/*"], - "version": "16.6.0-beta.2", + "version": "16.6.0-beta.3", "granularPathspec": false, "command": { "publish": { From 2fa248d4f55d52a18e4190f36b7a7b004c7a8f34 Mon Sep 17 00:00:00 2001 From: Craigory Coppola Date: Mon, 17 Jul 2023 08:41:35 -0400 Subject: [PATCH 081/262] fix(misc): update invalid main field in @nrwl/eslint-plugin-nx package.json (#17974) --- packages-legacy/eslint-plugin-nx/package.json | 4 ++-- packages-legacy/js/package.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages-legacy/eslint-plugin-nx/package.json b/packages-legacy/eslint-plugin-nx/package.json index 003f127a5b5ea..a9d0b14406399 100644 --- a/packages-legacy/eslint-plugin-nx/package.json +++ b/packages-legacy/eslint-plugin-nx/package.json @@ -15,8 +15,8 @@ "ESLint", "CLI" ], - "main": "./src/index.js", - "typings": "./src/index.d.ts", + "main": "./index.js", + "typings": "./index.d.ts", "author": "Victor Savkin", "license": "MIT", "bugs": { diff --git a/packages-legacy/js/package.json b/packages-legacy/js/package.json index 7d19672e7f371..7239ee1d414e5 100644 --- a/packages-legacy/js/package.json +++ b/packages-legacy/js/package.json @@ -16,8 +16,8 @@ "Tsc", "CLI" ], - "main": "src/index.js", - "typings": "src/index.d.ts", + "main": "./index.js", + "typings": "./index.d.ts", "license": "MIT", "bugs": { "url": "https://github.com/nrwl/nx/issues" From 187842e14c2d8b65d6c2b265502e2b08519acb7c Mon Sep 17 00:00:00 2001 From: Jonathan Cammisuli Date: Mon, 17 Jul 2023 10:01:50 -0400 Subject: [PATCH 082/262] fix(core): write file directly instead of using `fs-extra.outputFileSync` (#18129) --- packages/nx/src/utils/testing/temp-fs.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/nx/src/utils/testing/temp-fs.ts b/packages/nx/src/utils/testing/temp-fs.ts index 0bfbd5637be24..0ded2e08fa2c7 100644 --- a/packages/nx/src/utils/testing/temp-fs.ts +++ b/packages/nx/src/utils/testing/temp-fs.ts @@ -1,4 +1,4 @@ -import { join } from 'path'; +import { basename, dirname, join } from 'path'; import { tmpdir } from 'os'; import { mkdtempSync, @@ -8,9 +8,10 @@ import { emptyDirSync, outputFileSync, unlinkSync, + mkdirpSync, } from 'fs-extra'; import { joinPathFragments } from '../path'; -import { appendFileSync, writeFileSync, renameSync } from 'fs'; +import { appendFileSync, writeFileSync, renameSync, existsSync } from 'fs'; type NestedFiles = { [fileName: string]: string; @@ -44,7 +45,11 @@ export class TempFs { } createFileSync(filePath: string, content: string) { - outputFileSync(joinPathFragments(this.tempDir, filePath), content); + let dir = joinPathFragments(this.tempDir, dirname(filePath)); + if (!existsSync(dir)) { + mkdirpSync(dir); + } + writeFileSync(joinPathFragments(this.tempDir, filePath), content); } async readFile(filePath: string): Promise { From 10fc4dd4d8537adb2b2c343e910eb58a230ad8a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Jona=C5=A1?= Date: Mon, 17 Jul 2023 16:35:18 +0200 Subject: [PATCH 083/262] fix(core): ensure proper yarn version detection even for nested projects (#18052) --- docs/generated/devkit/nx_devkit.md | 3 +- .../packages/devkit/documents/nx_devkit.md | 3 +- .../src/create-nx-workspace.test.ts | 62 ++++++++++++++++++- .../src/create-empty-workspace.ts | 4 +- .../create-nx-workspace/src/create-preset.ts | 5 +- .../src/utils/package-manager.ts | 22 +++++-- .../devkit/src/tasks/install-packages-task.ts | 10 ++- packages/nx/src/utils/package-manager.ts | 12 ++-- .../new/generate-workspace-files.spec.ts | 2 + .../new/generate-workspace-files.ts | 22 ++++--- .../workspace/src/generators/new/new.spec.ts | 2 + 11 files changed, 123 insertions(+), 24 deletions(-) diff --git a/docs/generated/devkit/nx_devkit.md b/docs/generated/devkit/nx_devkit.md index 463df7413aef4..d288ca40288b7 100644 --- a/docs/generated/devkit/nx_devkit.md +++ b/docs/generated/devkit/nx_devkit.md @@ -1397,7 +1397,7 @@ execSync(`${getPackageManagerCommand().addDev} my-dev-package`); ### getPackageManagerVersion -▸ **getPackageManagerVersion**(`packageManager?`): `string` +▸ **getPackageManagerVersion**(`packageManager?`, `cwd?`): `string` Returns the version of the package manager used in the workspace. By default, the package manager is derived based on the lock file, @@ -1408,6 +1408,7 @@ but it can also be passed in explicitly. | Name | Type | | :--------------- | :------------------------------------------------------------------ | | `packageManager` | [`PackageManager`](../../devkit/documents/nx_devkit#packagemanager) | +| `cwd` | `string` | #### Returns diff --git a/docs/generated/packages/devkit/documents/nx_devkit.md b/docs/generated/packages/devkit/documents/nx_devkit.md index 463df7413aef4..d288ca40288b7 100644 --- a/docs/generated/packages/devkit/documents/nx_devkit.md +++ b/docs/generated/packages/devkit/documents/nx_devkit.md @@ -1397,7 +1397,7 @@ execSync(`${getPackageManagerCommand().addDev} my-dev-package`); ### getPackageManagerVersion -▸ **getPackageManagerVersion**(`packageManager?`): `string` +▸ **getPackageManagerVersion**(`packageManager?`, `cwd?`): `string` Returns the version of the package manager used in the workspace. By default, the package manager is derived based on the lock file, @@ -1408,6 +1408,7 @@ but it can also be passed in explicitly. | Name | Type | | :--------------- | :------------------------------------------------------------------ | | `packageManager` | [`PackageManager`](../../devkit/documents/nx_devkit#packagemanager) | +| `cwd` | `string` | #### Returns diff --git a/e2e/workspace-create/src/create-nx-workspace.test.ts b/e2e/workspace-create/src/create-nx-workspace.test.ts index 8a85a39a520a5..fc78558f8b863 100644 --- a/e2e/workspace-create/src/create-nx-workspace.test.ts +++ b/e2e/workspace-create/src/create-nx-workspace.test.ts @@ -9,10 +9,12 @@ import { getSelectedPackageManager, packageManagerLockFile, readJson, + runCommand, runCreateWorkspace, uniq, } from '@nx/e2e/utils'; -import { existsSync, mkdirSync } from 'fs-extra'; +import { readFileSync } from 'fs'; +import { existsSync, mkdirSync, rmSync } from 'fs-extra'; describe('create-nx-workspace', () => { const packageManager = getSelectedPackageManager() || 'pnpm'; @@ -414,7 +416,7 @@ describe('create-nx-workspace', () => { }); }); -describe('create-nx-workspace custom parent folder', () => { +describe('create-nx-workspace parent folder', () => { const tmpDir = `${e2eCwd}/${uniq('with space')}`; const wsName = uniq('parent'); const packageManager = getSelectedPackageManager() || 'pnpm'; @@ -433,3 +435,59 @@ describe('create-nx-workspace custom parent folder', () => { expect(existsSync(`${tmpDir}/${wsName}/package.json`)).toBeTruthy(); }); }); + +describe('create-nx-workspace yarn berry', () => { + const tmpDir = `${e2eCwd}/${uniq('yarn-berry')}`; + let wsName: string; + + beforeAll(() => { + mkdirSync(tmpDir, { recursive: true }); + runCommand('corepack prepare yarn@stable --activate', { cwd: tmpDir }); + runCommand('yarn set version stable', { cwd: tmpDir }); + // previous command creates a package.json file which we don't want + rmSync(`${tmpDir}/package.json`); + process.env.YARN_ENABLE_IMMUTABLE_INSTALLS = 'false'; + }); + + afterEach(() => cleanupProject({ cwd: `${tmpDir}/${wsName}` })); + + it('should create a workspace with yarn berry', () => { + wsName = uniq('apps'); + + runCreateWorkspace(wsName, { + preset: 'apps', + packageManager: 'yarn', + cwd: tmpDir, + }); + + expect(existsSync(`${tmpDir}/${wsName}/.yarnrc.yml`)).toBeTruthy(); + expect( + readFileSync(`${tmpDir}/${wsName}/.yarnrc.yml`, { encoding: 'utf-8' }) + ).toMatchInlineSnapshot(` + "nodeLinker: node-modules + + yarnPath: .yarn/releases/yarn-3.6.1.cjs + " + `); + }); + + it('should create a js workspace with yarn berry', () => { + wsName = uniq('ts'); + + runCreateWorkspace(wsName, { + preset: 'ts', + packageManager: 'yarn', + cwd: tmpDir, + }); + + expect(existsSync(`${tmpDir}/${wsName}/.yarnrc.yml`)).toBeTruthy(); + expect( + readFileSync(`${tmpDir}/${wsName}/.yarnrc.yml`, { encoding: 'utf-8' }) + ).toMatchInlineSnapshot(` + "nodeLinker: node-modules + + yarnPath: .yarn/releases/yarn-3.6.1.cjs + " + `); + }); +}); diff --git a/packages/create-nx-workspace/src/create-empty-workspace.ts b/packages/create-nx-workspace/src/create-empty-workspace.ts index 168815b9bc800..d007af4ed4f5d 100644 --- a/packages/create-nx-workspace/src/create-empty-workspace.ts +++ b/packages/create-nx-workspace/src/create-empty-workspace.ts @@ -53,7 +53,9 @@ export async function createEmptyWorkspace( /\s/.test(nxWorkspaceRoot) && packageManager === 'npm' ) { - const pmVersion = +getPackageManagerVersion(packageManager).split('.')[0]; + const pmVersion = +getPackageManagerVersion(packageManager, tmpDir).split( + '.' + )[0]; if (pmVersion < 7) { nxWorkspaceRoot = `\\"${nxWorkspaceRoot.slice(1, -1)}\\"`; } diff --git a/packages/create-nx-workspace/src/create-preset.ts b/packages/create-nx-workspace/src/create-preset.ts index 8d9722b864322..68955738d47ef 100644 --- a/packages/create-nx-workspace/src/create-preset.ts +++ b/packages/create-nx-workspace/src/create-preset.ts @@ -33,7 +33,10 @@ export async function createPreset( /\s/.test(nxWorkspaceRoot) && packageManager === 'npm' ) { - const pmVersion = +getPackageManagerVersion(packageManager).split('.')[0]; + const pmVersion = +getPackageManagerVersion( + packageManager, + workingDir + ).split('.')[0]; if (pmVersion < 7) { nxWorkspaceRoot = `\\"${nxWorkspaceRoot.slice(1, -1)}\\"`; } diff --git a/packages/create-nx-workspace/src/utils/package-manager.ts b/packages/create-nx-workspace/src/utils/package-manager.ts index da3c77892d8f2..30f248d2cb90f 100644 --- a/packages/create-nx-workspace/src/utils/package-manager.ts +++ b/packages/create-nx-workspace/src/utils/package-manager.ts @@ -1,5 +1,5 @@ import { execSync } from 'child_process'; -import { existsSync, writeFileSync } from 'fs'; +import { existsSync, readFileSync, writeFileSync } from 'fs'; import { join } from 'path'; /* @@ -52,7 +52,8 @@ export function getPackageManagerCommand( install: useBerry ? installCommand : `${installCommand} --ignore-scripts`, - exec: 'yarn', + // using npx is necessary to avoid yarn classic manipulating the version detection when using berry + exec: useBerry ? 'npx' : 'yarn', }; case 'pnpm': @@ -85,15 +86,28 @@ export function generatePackageManagerFiles( join(root, '.yarnrc.yml'), 'nodeLinker: node-modules\nenableScripts: false' ); + // avoids errors when using nested yarn projects + writeFileSync(join(root, 'yarn.lock'), ''); } break; } } +const pmVersionCache = new Map(); + export function getPackageManagerVersion( - packageManager: PackageManager + packageManager: PackageManager, + cwd = process.cwd() ): string { - return execSync(`${packageManager} --version`).toString('utf-8').trim(); + if (pmVersionCache.has(packageManager)) { + return pmVersionCache.get(packageManager) as string; + } + const version = execSync(`${packageManager} --version`, { + cwd, + encoding: 'utf-8', + }).trim(); + pmVersionCache.set(packageManager, version); + return version; } /** diff --git a/packages/devkit/src/tasks/install-packages-task.ts b/packages/devkit/src/tasks/install-packages-task.ts index d52797f5590f5..05adbf0632a61 100644 --- a/packages/devkit/src/tasks/install-packages-task.ts +++ b/packages/devkit/src/tasks/install-packages-task.ts @@ -1,4 +1,4 @@ -import { execSync } from 'child_process'; +import { type ExecSyncOptions, execSync } from 'child_process'; import { join } from 'path'; import { requireNx } from '../../nx'; @@ -38,9 +38,13 @@ export function installPackagesTask( if (storedPackageJsonValue != packageJsonValue || alwaysRun) { global['__packageJsonInstallCache__'] = packageJsonValue; const pmc = getPackageManagerCommand(packageManager); - execSync(pmc.install, { + const execSyncOptions: ExecSyncOptions = { cwd: join(tree.root, cwd), stdio: process.env.NX_GENERATE_QUIET === 'true' ? 'ignore' : 'inherit', - }); + }; + if (pmc.preInstall) { + execSync(pmc.preInstall, execSyncOptions); + } + execSync(pmc.install, execSyncOptions); } } diff --git a/packages/nx/src/utils/package-manager.ts b/packages/nx/src/utils/package-manager.ts index 713bc57b7b361..20eefb184b6af 100644 --- a/packages/nx/src/utils/package-manager.ts +++ b/packages/nx/src/utils/package-manager.ts @@ -61,7 +61,7 @@ export function getPackageManagerCommand( ): PackageManagerCommands { const commands: { [pm in PackageManager]: () => PackageManagerCommands } = { yarn: () => { - const yarnVersion = getPackageManagerVersion('yarn'); + const yarnVersion = getPackageManagerVersion('yarn', root); const useBerry = gte(yarnVersion, '2.0.0'); return { @@ -81,7 +81,7 @@ export function getPackageManagerCommand( }; }, pnpm: () => { - const pnpmVersion = getPackageManagerVersion('pnpm'); + const pnpmVersion = getPackageManagerVersion('pnpm', root); const useExec = gte(pnpmVersion, '6.13.0'); const includeDoubleDashBeforeArgs = lt(pnpmVersion, '7.0.0'); const isPnpmWorkspace = existsSync(join(root, 'pnpm-workspace.yaml')); @@ -126,9 +126,13 @@ export function getPackageManagerCommand( * but it can also be passed in explicitly. */ export function getPackageManagerVersion( - packageManager: PackageManager = detectPackageManager() + packageManager: PackageManager = detectPackageManager(), + cwd = process.cwd() ): string { - return execSync(`${packageManager} --version`).toString('utf-8').trim(); + return execSync(`${packageManager} --version`, { + cwd, + encoding: 'utf-8', + }).trim(); } /** diff --git a/packages/workspace/src/generators/new/generate-workspace-files.spec.ts b/packages/workspace/src/generators/new/generate-workspace-files.spec.ts index 0a0931bd303ec..33ce79fc8f982 100644 --- a/packages/workspace/src/generators/new/generate-workspace-files.spec.ts +++ b/packages/workspace/src/generators/new/generate-workspace-files.spec.ts @@ -11,6 +11,8 @@ describe('@nx/workspace:generateWorkspaceFiles', () => { beforeEach(() => { tree = createTree(); + // we need an actual path for the package manager version check + tree.root = process.cwd(); }); it('should create files', async () => { diff --git a/packages/workspace/src/generators/new/generate-workspace-files.ts b/packages/workspace/src/generators/new/generate-workspace-files.ts index 8cd89ed85b1c3..34dcc820a1ee9 100644 --- a/packages/workspace/src/generators/new/generate-workspace-files.ts +++ b/packages/workspace/src/generators/new/generate-workspace-files.ts @@ -10,7 +10,7 @@ import { writeJson, } from '@nx/devkit'; import { nxVersion } from '../../utils/versions'; -import { join, join as pathJoin } from 'path'; +import { join } from 'path'; import { Preset } from '../utils/presets'; import { deduceDefaultBase } from '../../utilities/default-base'; import { NormalizedSchema } from './new'; @@ -22,18 +22,26 @@ export async function generateWorkspaceFiles( if (!options.name) { throw new Error(`Invalid options, "name" is required.`); } + // we need to check package manager version before the package.json is generated + // since it might influence the version report + const packageManagerVersion = getPackageManagerVersion( + options.packageManager as PackageManager, + tree.root + ); options = normalizeOptions(options); createReadme(tree, options); createFiles(tree, options); createNxJson(tree, options); - const [packageMajor] = getPackageManagerVersion( - options.packageManager as PackageManager - ).split('.'); + const [packageMajor] = packageManagerVersion.split('.'); if (options.packageManager === 'pnpm' && +packageMajor >= 7) { createNpmrc(tree, options); - } else if (options.packageManager === 'yarn' && +packageMajor >= 2) { - createYarnrcYml(tree, options); + } else if (options.packageManager === 'yarn') { + if (+packageMajor >= 2) { + createYarnrcYml(tree, options); + // avoids errors when using nested yarn projects + tree.write(join(options.directory, 'yarn.lock'), ''); + } } setPresetProperty(tree, options); addNpmScripts(tree, options); @@ -133,7 +141,7 @@ function createFiles(tree: Tree, options: NormalizedSchema) { : options.preset === Preset.NPM || options.preset === Preset.Core ? './files-package-based-repo' : './files-integrated-repo'; - generateFiles(tree, pathJoin(__dirname, filesDirName), options.directory, { + generateFiles(tree, join(__dirname, filesDirName), options.directory, { formattedNames, dot: '.', tmpl: '', diff --git a/packages/workspace/src/generators/new/new.spec.ts b/packages/workspace/src/generators/new/new.spec.ts index 0f3b362e9da91..80933dac107c6 100644 --- a/packages/workspace/src/generators/new/new.spec.ts +++ b/packages/workspace/src/generators/new/new.spec.ts @@ -32,6 +32,8 @@ describe('new', () => { beforeEach(() => { tree = createTree(); + // we need an actual path for the package manager version check + tree.root = process.cwd(); }); it('should generate an empty nx.json', async () => { From 74338d11787df8fc0c4678a8aaf33f28c2fcf38b Mon Sep 17 00:00:00 2001 From: Altan Stalker Date: Mon, 17 Jul 2023 10:49:28 -0400 Subject: [PATCH 084/262] docs(misc): clarify bitbucket token/username setup --- docs/nx-cloud/set-up/bitbucket-cloud.md | 6 ++++++ .../minimal-bitbucket-cloud-app-password.png | Bin 73139 -> 0 bytes .../minimal-bitbucket-cloud-app-password.webp | Bin 0 -> 24352 bytes 3 files changed, 6 insertions(+) delete mode 100644 docs/nx-cloud/set-up/minimal-bitbucket-cloud-app-password.png create mode 100644 docs/nx-cloud/set-up/minimal-bitbucket-cloud-app-password.webp diff --git a/docs/nx-cloud/set-up/bitbucket-cloud.md b/docs/nx-cloud/set-up/bitbucket-cloud.md index af3b57d04865a..d40e4f75ee1a5 100644 --- a/docs/nx-cloud/set-up/bitbucket-cloud.md +++ b/docs/nx-cloud/set-up/bitbucket-cloud.md @@ -26,4 +26,10 @@ For example, the url `https://bitbucket.org/nrwl/large-monorepo/src/main/` has a To use an app password for authentication, one must be generated with proper permissions. The minimum required permissions are write access to PRs. +![Create App Password](/nx-cloud/set-up/minimal-bitbucket-cloud-app-password.webp) + Once the app password is created, verify the username is correct, paste the value, and then click "Connect". This will verify that Nx Cloud can connect to your repo. Upon a successful test, your configuration is saved, and setup is complete. + +{% callout type="note" title="Use the correct username" %} +Make sure that you are using your Bitbucket username, found on the [account settings](https://bitbucket.org/account/settings) screen, and not your email address. +{% /callout %} diff --git a/docs/nx-cloud/set-up/minimal-bitbucket-cloud-app-password.png b/docs/nx-cloud/set-up/minimal-bitbucket-cloud-app-password.png deleted file mode 100644 index a438b328dca61ca096d757a0d1f5a08f481f731c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 73139 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 Aq5uE@ diff --git a/docs/nx-cloud/set-up/minimal-bitbucket-cloud-app-password.webp b/docs/nx-cloud/set-up/minimal-bitbucket-cloud-app-password.webp new file mode 100644 index 0000000000000000000000000000000000000000..8a498eacdac5f0e43587ccc5bf47668fa406160a GIT binary patch literal 24352 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 Date: Thu, 6 Jul 2023 14:44:40 -0400 Subject: [PATCH 085/262] docs(core): recipe standalone to integrated --- docs/generated/manifests/menus.json | 123 ++++++++------ docs/generated/manifests/nx.json | 4 +- docs/generated/manifests/recipes.json | 151 +++++++++++------- docs/generated/manifests/tags.json | 24 ++- docs/map.json | 23 ++- .../concepts/how-project-graph-is-built.md | 2 +- .../automate-updating-dependencies.md | 2 +- docs/shared/core-features/run-tasks.md | 2 +- docs/shared/guides/nx-and-angular-cli.md | 2 +- .../repo-types/standalone-to-integrated.md | 95 +++++++++++ docs/shared/reference/sitemap.md | 12 +- nx-dev/nx-dev/redirect-rules.js | 9 ++ .../nx/src/command-line/migrate/migrate.ts | 2 +- 13 files changed, 321 insertions(+), 130 deletions(-) create mode 100644 docs/shared/recipes/repo-types/standalone-to-integrated.md diff --git a/docs/generated/manifests/menus.json b/docs/generated/manifests/menus.json index 8dd3c2713a8a0..0174eb9f94a9e 100644 --- a/docs/generated/manifests/menus.json +++ b/docs/generated/manifests/menus.json @@ -3087,14 +3087,14 @@ "disableCollapsible": false }, { - "name": "Other", - "path": "/recipes/other", - "id": "other", + "name": "Managing Your Nx Repository", + "path": "/recipes/managing-repository", + "id": "managing-repository", "isExternal": false, "children": [ { "name": "Run Root-Level NPM Scripts with Nx", - "path": "/recipes/other/root-level-scripts", + "path": "/recipes/managing-repository/root-level-scripts", "id": "root-level-scripts", "isExternal": false, "children": [], @@ -3102,7 +3102,7 @@ }, { "name": "Disable Graph Links Created from Analyzing Source Files", - "path": "/recipes/other/analyze-source-files", + "path": "/recipes/managing-repository/analyze-source-files", "id": "analyze-source-files", "isExternal": false, "children": [], @@ -3110,7 +3110,7 @@ }, { "name": "Workspace Watching", - "path": "/recipes/other/workspace-watching", + "path": "/recipes/managing-repository/workspace-watching", "id": "workspace-watching", "isExternal": false, "children": [], @@ -3118,20 +3118,85 @@ }, { "name": "Advanced Update Process", - "path": "/recipes/other/advanced-update", + "path": "/recipes/managing-repository/advanced-update", "id": "advanced-update", "isExternal": false, "children": [], "disableCollapsible": false }, + { + "name": "Convert from a Standalone Repository to an Integrated Repository", + "path": "/recipes/managing-repository/standalone-to-integrated", + "id": "standalone-to-integrated", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, { "name": "JavaScript and TypeScript", - "path": "/recipes/other/js-and-ts", + "path": "/recipes/managing-repository/js-and-ts", "id": "js-and-ts", "isExternal": false, "children": [], "disableCollapsible": false - }, + } + ], + "disableCollapsible": false + }, + { + "name": "Run Root-Level NPM Scripts with Nx", + "path": "/recipes/managing-repository/root-level-scripts", + "id": "root-level-scripts", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Disable Graph Links Created from Analyzing Source Files", + "path": "/recipes/managing-repository/analyze-source-files", + "id": "analyze-source-files", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Workspace Watching", + "path": "/recipes/managing-repository/workspace-watching", + "id": "workspace-watching", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Advanced Update Process", + "path": "/recipes/managing-repository/advanced-update", + "id": "advanced-update", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Convert from a Standalone Repository to an Integrated Repository", + "path": "/recipes/managing-repository/standalone-to-integrated", + "id": "standalone-to-integrated", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "JavaScript and TypeScript", + "path": "/recipes/managing-repository/js-and-ts", + "id": "js-and-ts", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Other", + "path": "/recipes/other", + "id": "other", + "isExternal": false, + "children": [ { "name": "React Native with Nx", "path": "/recipes/other/react-native", @@ -3303,46 +3368,6 @@ ], "disableCollapsible": false }, - { - "name": "Run Root-Level NPM Scripts with Nx", - "path": "/recipes/other/root-level-scripts", - "id": "root-level-scripts", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Disable Graph Links Created from Analyzing Source Files", - "path": "/recipes/other/analyze-source-files", - "id": "analyze-source-files", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Workspace Watching", - "path": "/recipes/other/workspace-watching", - "id": "workspace-watching", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Advanced Update Process", - "path": "/recipes/other/advanced-update", - "id": "advanced-update", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "JavaScript and TypeScript", - "path": "/recipes/other/js-and-ts", - "id": "js-and-ts", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, { "name": "React Native with Nx", "path": "/recipes/other/react-native", diff --git a/docs/generated/manifests/nx.json b/docs/generated/manifests/nx.json index 905e1c190280d..03232f9af3847 100644 --- a/docs/generated/manifests/nx.json +++ b/docs/generated/manifests/nx.json @@ -1184,7 +1184,7 @@ "itemList": [], "isExternal": false, "path": "/concepts/integrated-vs-package-based", - "tags": ["intro"] + "tags": ["intro", "repository-types"] }, { "id": "mental-model", @@ -1259,7 +1259,7 @@ "itemList": [], "isExternal": false, "path": "/concepts/integrated-vs-package-based", - "tags": ["intro"] + "tags": ["intro", "repository-types"] }, "/concepts/mental-model": { "id": "mental-model", diff --git a/docs/generated/manifests/recipes.json b/docs/generated/manifests/recipes.json index ea67ae2fe2120..c710532b5c3de 100644 --- a/docs/generated/manifests/recipes.json +++ b/docs/generated/manifests/recipes.json @@ -1342,10 +1342,10 @@ "path": "/recipes/example-repos/dte", "tags": [] }, - "/recipes/other": { - "id": "other", - "name": "Other", - "description": "Other recipes you will find useful.", + "/recipes/managing-repository": { + "id": "managing-repository", + "name": "Managing Your Nx Repository", + "description": "Configuring the Repository Itself", "file": "", "itemList": [ { @@ -1355,7 +1355,7 @@ "file": "shared/recipes/root-level-scripts", "itemList": [], "isExternal": false, - "path": "/recipes/other/root-level-scripts", + "path": "/recipes/managing-repository/root-level-scripts", "tags": ["run-tasks"] }, { @@ -1365,7 +1365,7 @@ "file": "shared/recipes/analyze-source-files", "itemList": [], "isExternal": false, - "path": "/recipes/other/analyze-source-files", + "path": "/recipes/managing-repository/analyze-source-files", "tags": ["explore-graph"] }, { @@ -1375,7 +1375,7 @@ "file": "shared/recipes/workspace-watching", "itemList": [], "isExternal": false, - "path": "/recipes/other/workspace-watching", + "path": "/recipes/managing-repository/workspace-watching", "tags": ["workspace-watching"] }, { @@ -1385,9 +1385,19 @@ "file": "shared/recipes/advanced-update", "itemList": [], "isExternal": false, - "path": "/recipes/other/advanced-update", + "path": "/recipes/managing-repository/advanced-update", "tags": ["automate-updating-dependencies"] }, + { + "id": "standalone-to-integrated", + "name": "Convert from a Standalone Repository to an Integrated Repository", + "description": "", + "file": "shared/recipes/repo-types/standalone-to-integrated", + "itemList": [], + "isExternal": false, + "path": "/recipes/managing-repository/standalone-to-integrated", + "tags": ["repository-types"] + }, { "id": "js-and-ts", "name": "JavaScript and TypeScript", @@ -1395,9 +1405,80 @@ "file": "shared/guides/js-and-ts", "itemList": [], "isExternal": false, - "path": "/recipes/other/js-and-ts", + "path": "/recipes/managing-repository/js-and-ts", "tags": [] - }, + } + ], + "isExternal": false, + "path": "/recipes/managing-repository", + "tags": [] + }, + "/recipes/managing-repository/root-level-scripts": { + "id": "root-level-scripts", + "name": "Run Root-Level NPM Scripts with Nx", + "description": "", + "file": "shared/recipes/root-level-scripts", + "itemList": [], + "isExternal": false, + "path": "/recipes/managing-repository/root-level-scripts", + "tags": ["run-tasks"] + }, + "/recipes/managing-repository/analyze-source-files": { + "id": "analyze-source-files", + "name": "Disable Graph Links Created from Analyzing Source Files", + "description": "", + "file": "shared/recipes/analyze-source-files", + "itemList": [], + "isExternal": false, + "path": "/recipes/managing-repository/analyze-source-files", + "tags": ["explore-graph"] + }, + "/recipes/managing-repository/workspace-watching": { + "id": "workspace-watching", + "name": "Workspace Watching", + "description": "", + "file": "shared/recipes/workspace-watching", + "itemList": [], + "isExternal": false, + "path": "/recipes/managing-repository/workspace-watching", + "tags": ["workspace-watching"] + }, + "/recipes/managing-repository/advanced-update": { + "id": "advanced-update", + "name": "Advanced Update Process", + "description": "", + "file": "shared/recipes/advanced-update", + "itemList": [], + "isExternal": false, + "path": "/recipes/managing-repository/advanced-update", + "tags": ["automate-updating-dependencies"] + }, + "/recipes/managing-repository/standalone-to-integrated": { + "id": "standalone-to-integrated", + "name": "Convert from a Standalone Repository to an Integrated Repository", + "description": "", + "file": "shared/recipes/repo-types/standalone-to-integrated", + "itemList": [], + "isExternal": false, + "path": "/recipes/managing-repository/standalone-to-integrated", + "tags": ["repository-types"] + }, + "/recipes/managing-repository/js-and-ts": { + "id": "js-and-ts", + "name": "JavaScript and TypeScript", + "description": "", + "file": "shared/guides/js-and-ts", + "itemList": [], + "isExternal": false, + "path": "/recipes/managing-repository/js-and-ts", + "tags": [] + }, + "/recipes/other": { + "id": "other", + "name": "Other", + "description": "Other recipes you will find useful.", + "file": "", + "itemList": [ { "id": "react-native", "name": "React Native with Nx", @@ -1613,56 +1694,6 @@ "path": "/recipes/other", "tags": [] }, - "/recipes/other/root-level-scripts": { - "id": "root-level-scripts", - "name": "Run Root-Level NPM Scripts with Nx", - "description": "", - "file": "shared/recipes/root-level-scripts", - "itemList": [], - "isExternal": false, - "path": "/recipes/other/root-level-scripts", - "tags": ["run-tasks"] - }, - "/recipes/other/analyze-source-files": { - "id": "analyze-source-files", - "name": "Disable Graph Links Created from Analyzing Source Files", - "description": "", - "file": "shared/recipes/analyze-source-files", - "itemList": [], - "isExternal": false, - "path": "/recipes/other/analyze-source-files", - "tags": ["explore-graph"] - }, - "/recipes/other/workspace-watching": { - "id": "workspace-watching", - "name": "Workspace Watching", - "description": "", - "file": "shared/recipes/workspace-watching", - "itemList": [], - "isExternal": false, - "path": "/recipes/other/workspace-watching", - "tags": ["workspace-watching"] - }, - "/recipes/other/advanced-update": { - "id": "advanced-update", - "name": "Advanced Update Process", - "description": "", - "file": "shared/recipes/advanced-update", - "itemList": [], - "isExternal": false, - "path": "/recipes/other/advanced-update", - "tags": ["automate-updating-dependencies"] - }, - "/recipes/other/js-and-ts": { - "id": "js-and-ts", - "name": "JavaScript and TypeScript", - "description": "", - "file": "shared/guides/js-and-ts", - "itemList": [], - "isExternal": false, - "path": "/recipes/other/js-and-ts", - "tags": [] - }, "/recipes/other/react-native": { "id": "react-native", "name": "React Native with Nx", diff --git a/docs/generated/manifests/tags.json b/docs/generated/manifests/tags.json index 816c5753e50a8..29d24cc9507e7 100644 --- a/docs/generated/manifests/tags.json +++ b/docs/generated/manifests/tags.json @@ -26,7 +26,7 @@ "file": "shared/recipes/root-level-scripts", "id": "root-level-scripts", "name": "Run Root-Level NPM Scripts with Nx", - "path": "/recipes/other/root-level-scripts" + "path": "/recipes/managing-repository/root-level-scripts" }, { "description": "The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.", @@ -165,7 +165,7 @@ "file": "shared/recipes/analyze-source-files", "id": "analyze-source-files", "name": "Disable Graph Links Created from Analyzing Source Files", - "path": "/recipes/other/analyze-source-files" + "path": "/recipes/managing-repository/analyze-source-files" }, { "description": "", @@ -304,7 +304,7 @@ "file": "shared/recipes/advanced-update", "id": "advanced-update", "name": "Advanced Update Process", - "path": "/recipes/other/advanced-update" + "path": "/recipes/managing-repository/advanced-update" }, { "description": "The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.", @@ -616,6 +616,22 @@ "path": "/concepts/mental-model" } ], + "repository-types": [ + { + "description": "", + "file": "shared/concepts/integrated-vs-package-based", + "id": "integrated-vs-package-based", + "name": "Integrated Repos vs. Package-Based Repos vs. Standalone Apps", + "path": "/concepts/integrated-vs-package-based" + }, + { + "description": "", + "file": "shared/recipes/repo-types/standalone-to-integrated", + "id": "standalone-to-integrated", + "name": "Convert from a Standalone Repository to an Integrated Repository", + "path": "/recipes/managing-repository/standalone-to-integrated" + } + ], "create-your-own-plugin": [ { "description": "", @@ -963,7 +979,7 @@ "file": "shared/recipes/workspace-watching", "id": "workspace-watching", "name": "Workspace Watching", - "path": "/recipes/other/workspace-watching" + "path": "/recipes/managing-repository/workspace-watching" }, { "description": "The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.", diff --git a/docs/map.json b/docs/map.json index d3fbcc151e952..7c41f4c61023f 100644 --- a/docs/map.json +++ b/docs/map.json @@ -345,7 +345,7 @@ "itemList": [ { "name": "Integrated Repos vs. Package-Based Repos vs. Standalone Apps", - "tags": ["intro"], + "tags": ["intro", "repository-types"], "id": "integrated-vs-package-based", "file": "shared/concepts/integrated-vs-package-based" }, @@ -1316,9 +1316,9 @@ ] }, { - "name": "Other", - "id": "other", - "description": "Other recipes you will find useful.", + "name": "Managing Your Nx Repository", + "id": "managing-repository", + "description": "Configuring the Repository Itself", "itemList": [ { "name": "Run Root-Level NPM Scripts with Nx", @@ -1344,11 +1344,24 @@ "tags": ["automate-updating-dependencies"], "file": "shared/recipes/advanced-update" }, + { + "name": "Convert from a Standalone Repository to an Integrated Repository", + "id": "standalone-to-integrated", + "tags": ["repository-types"], + "file": "shared/recipes/repo-types/standalone-to-integrated" + }, { "name": "JavaScript and TypeScript", "id": "js-and-ts", "file": "shared/guides/js-and-ts" - }, + } + ] + }, + { + "name": "Other", + "id": "other", + "description": "Other recipes you will find useful.", + "itemList": [ { "name": "React Native with Nx", "id": "react-native", diff --git a/docs/shared/concepts/how-project-graph-is-built.md b/docs/shared/concepts/how-project-graph-is-built.md index e80a92c623837..b8ce6f1389552 100644 --- a/docs/shared/concepts/how-project-graph-is-built.md +++ b/docs/shared/concepts/how-project-graph-is-built.md @@ -28,7 +28,7 @@ Nx creates a graph of all the dependencies between projects in your workspace us Then `my-app` depends on `awesome-library` - This can be [turned on or off with the `analyzeSourceFiles` flag](../../recipes/other/analyze-source-files). + This can be [turned on or off with the `analyzeSourceFiles` flag](../../recipes/managing-repository/analyze-source-files). 3. Manually created `implicitDependencies` in the project configuration file. diff --git a/docs/shared/core-features/automate-updating-dependencies.md b/docs/shared/core-features/automate-updating-dependencies.md index 5edc4e1d6ce99..9b3c078f3bccf 100644 --- a/docs/shared/core-features/automate-updating-dependencies.md +++ b/docs/shared/core-features/automate-updating-dependencies.md @@ -63,4 +63,4 @@ Note: You may want to keep the `migrations.json` until every branch that was cre ## Need to opt-out of some migrations? -Sometimes you need to temporarily opt-out from some migrations because your workspace is not ready yet. You can manually adjust the `migrations.json` or run the update with the `--interactive` flag to choose which migrations you accept. Find more details in our [Advanced Update Process](/recipes/other/advanced-update) guide. +Sometimes you need to temporarily opt-out from some migrations because your workspace is not ready yet. You can manually adjust the `migrations.json` or run the update with the `--interactive` flag to choose which migrations you accept. Find more details in our [Advanced Update Process](/recipes/managing-repository/advanced-update) guide. diff --git a/docs/shared/core-features/run-tasks.md b/docs/shared/core-features/run-tasks.md index c643a7b69b21a..432d119d29372 100644 --- a/docs/shared/core-features/run-tasks.md +++ b/docs/shared/core-features/run-tasks.md @@ -136,7 +136,7 @@ If you want Nx to cache the task, but prefer to use npm (or pnpm/yarn) to run th } ``` -Learn more about root-level tasks [in our dedicated recipe page](/recipes/other/root-level-scripts). +Learn more about root-level tasks [in our dedicated recipe page](/recipes/managing-repository/root-level-scripts). ## Defining the Task Pipeline diff --git a/docs/shared/guides/nx-and-angular-cli.md b/docs/shared/guides/nx-and-angular-cli.md index 7ebff2fb303ac..582a2c96dfd9f 100644 --- a/docs/shared/guides/nx-and-angular-cli.md +++ b/docs/shared/guides/nx-and-angular-cli.md @@ -24,7 +24,7 @@ If you haven't used Nx before and used the Angular CLI, you probably ran `ng upd - Fix migrations that "almost work". - Commit a partially migrated state. - Change versions of packages to match org requirements. -- [Opt out of Angular updates when updating Nx versions](/recipes/other/advanced-update#choosing-optional-package-updates-to-apply) as long as [the Angular version is still supported](/packages/angular/documents/angular-nx-version-matrix) +- [Opt out of Angular updates when updating Nx versions](/recipes/managing-repository/advanced-update#choosing-optional-package-updates-to-apply) as long as [the Angular version is still supported](/packages/angular/documents/angular-nx-version-matrix) `nx migrate` does this by splitting the process into two steps. `nx migrate latest` creates a `migrations.json` file with a list of all the migrations that are needed by Nx, Angular and other packages. You then have a chance to modify that file before running `nx migrate --run-migrations` to actually execute those migrations. diff --git a/docs/shared/recipes/repo-types/standalone-to-integrated.md b/docs/shared/recipes/repo-types/standalone-to-integrated.md new file mode 100644 index 0000000000000..b2bb6df00b6c0 --- /dev/null +++ b/docs/shared/recipes/repo-types/standalone-to-integrated.md @@ -0,0 +1,95 @@ +# Convert from a Standalone Repository to an Integrated Repository + +In many ways, a standalone repository is an integrated repository, but with one primary app located at the root of the repository. Both types of repos use plugins to generate code and to keep dependencies and config files up to date. Both types of repos use executors to hide away unneeded complexity. + +You can always add another app to a standalone repository the same way you would in an integrated repo. But at some point, you may want to move the primary app out of the root of your repo because the repo is no longer primarily focused on that one app. There are other apps that are equally important and you want the folder structure to align with the new reality. + +## Strategy + +For this recipe, we'll assume that the root-level app is named `my-app`. The high-level process we'll go through to move the app involves four stages: + +1. Create a new app named `temp` under `apps/temp`. +2. Move source and config files from `my-app` into `apps/temp`. +3. Delete the files for `my-app`. +4. Rename `apps/temp` to `apps/my-app` + +## Steps + +1. Update the `workspaceLayout` property in `nx.json` to be: + + ```jsonc {% fileName="nx.json" %} + { + "workspaceLayout": { + "appsDir": "apps", + "libsDir": "libs" + } + } + ``` + + This will make sure that new apps are created under `apps` and new libraries are created under `libs`. + +2. If there is a `tsconfig.json` file in the root, rename it to `tsconfig.old.json` + + This step is to make sure that a `tsconfig.base.json` file is generated by the app generator in the next step. + +3. Create a new app using the appropriate plugin under `apps/temp` + + ```shell + nx g app temp + ``` + +4. Move the `/src` (and `/public`, if present) folders to `apps/temp/`, overwriting the folders already there. + +5. For each config file in `apps/temp`, copy over the corresponding file from the root of the repo. + + It can be difficult to know which files are root-level config files and which files are project-specific config files. Here is a non-exhaustive list of config files to help distinguish between the two. + + | Type of Config | Files | + | --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | + | _Root-level_ | `.eslintignore`, `.eslintrc.base.json`, `.gitignore`, `.prettierignore`, `jest.config.ts`, `jest.preset.js`, `.prettierrc`, `nx.json`, `package.json`, `tsconfig.base.json` | + | _Project-level_ | `.eslintrc.json`, `index.html`, `project.json`, `jest.config.app.ts`, `tsconfig.app.json`, `tsconfig.json`, `tsconfig.spec.json`, `vite.config.ts`, `webpack.config.js` | + + {% callout title="jest.config.app.ts" type="note" %} + `jest.config.app.ts` in the root should be renamed to `jest.config.ts` when moved to `apps/temp`. Also update the `jestConfig` option in `project.json` to point to `jest.config.ts` instead of `jest.config.app.ts`. + {% /callout %} + +6. Update the paths of the project-specific config files that were copied into `apps/temp`. + + Here is a non-exhaustive list of properties that will need to be updated to have the correct path: + + | Config File(s) | Properties to Check | + | ---------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | + | `project.json` | `$schema`, `sourceRoot`, `root`, `outputPath`, `reportsDirectory`, `cypressConfig`, `lintFilePatterns`, `index`, `main`, `tsConfig`, `assets`, `styles`, `jestConfig` | + | `tsconfig.json`, `tsconfig.app.json`, `tsconfig.spec.json` | `extends`, `outDir`, `files` | + | `.eslintrc.json` | `extends` | + | `jest.config.ts` | `preset`, `coverageDirectory` | + | `vite.config.ts` | `cacheDir`, `root`, `dir` | + +7. Doublecheck that all the tasks defined in the `apps/temp/project.json` file still work. + + ```shell + nx build temp + nx test temp + nx lint temp + ``` + +8. Move the `/e2e/src` folder to `/apps/temp-e2e`, overwriting the folder already there +9. For each config file in `apps/temp-e2e`, copy over the corresponding file from the root of the repo. Update the paths for these files in the same way you did for the `my-app` config files. +10. Update the `/apps/temp-e2e/project.json` `implicitDependencies` to be `temp` instead of `my-app` +11. Doublecheck that all the tasks defined in the `apps/temp-e2e/project.json` file still work. + + ```shell + nx lint temp-e2e + nx e2e temp-e2e + ``` + +12. Delete all the project specific config files in the root and under `e2e` +13. Once the `project.json` file has been deleted in the root, rename `temp-e2e` to `my-app-e2e` and rename `temp` to `my-app` + + ```shell + nx g move --projectName=temp-e2e --destination=my-app-e2e + nx g move --projectName=temp --destination=my-app + ``` + +14. Update the `defaultProject` in `nx.json` if needed +15. Check again that all the tasks still work and that the `nx graph` displays what you expect. diff --git a/docs/shared/reference/sitemap.md b/docs/shared/reference/sitemap.md index 1982d9287a28e..8cdca206300a4 100644 --- a/docs/shared/reference/sitemap.md +++ b/docs/shared/reference/sitemap.md @@ -193,12 +193,14 @@ - [Using Apollo GraphQL](/recipes/example-repos/apollo-react) - [Large Repo and Caching](/recipes/example-repos/caching) - [Large Repo and DTE](/recipes/example-repos/dte) + - [Managing Your Nx Repository](/recipes/managing-repository) + - [Run Root-Level NPM Scripts with Nx](/recipes/managing-repository/root-level-scripts) + - [Disable Graph Links Created from Analyzing Source Files](/recipes/managing-repository/analyze-source-files) + - [Workspace Watching](/recipes/managing-repository/workspace-watching) + - [Advanced Update Process](/recipes/managing-repository/advanced-update) + - [Convert from a Standalone Repository to an Integrated Repository](/recipes/managing-repository/standalone-to-integrated) + - [JavaScript and TypeScript](/recipes/managing-repository/js-and-ts) - [Other](/recipes/other) - - [Run Root-Level NPM Scripts with Nx](/recipes/other/root-level-scripts) - - [Disable Graph Links Created from Analyzing Source Files](/recipes/other/analyze-source-files) - - [Workspace Watching](/recipes/other/workspace-watching) - - [Advanced Update Process](/recipes/other/advanced-update) - - [JavaScript and TypeScript](/recipes/other/js-and-ts) - [React Native with Nx](/recipes/other/react-native) - [Remix with Nx](/recipes/other/remix) - [Adding Images, Fonts, and Files](/recipes/other/adding-assets-react) diff --git a/nx-dev/nx-dev/redirect-rules.js b/nx-dev/nx-dev/redirect-rules.js index 79d9530b58561..743ca1cac270c 100644 --- a/nx-dev/nx-dev/redirect-rules.js +++ b/nx-dev/nx-dev/redirect-rules.js @@ -365,6 +365,15 @@ const recipesUrls = { '/recipes/deployment/deploy-nextjs-to-vercel', '/recipes/other/azure-last-successful-commit': '/recipes/ci/azure-last-successful-commit', + '/recipes/other/root-level-scripts': + '/recipes/managing-repository/root-level-scripts', + '/recipes/other/analyze-source-files': + '/recipes/managing-repository/analyze-source-files', + '/recipes/other/workspace-watching': + '/recipes/managing-repository/workspace-watching', + '/recipes/other/advanced-update': + '/recipes/managing-repository/advanced-update', + '/recipes/other/js-and-ts': '/recipes/managing-repository/js-and-ts', }; /** diff --git a/packages/nx/src/command-line/migrate/migrate.ts b/packages/nx/src/command-line/migrate/migrate.ts index bba1815fdca28..0733c54e99db7 100644 --- a/packages/nx/src/command-line/migrate/migrate.ts +++ b/packages/nx/src/command-line/migrate/migrate.ts @@ -1280,7 +1280,7 @@ async function generateMigrationsJsonAndUpdatePackageJson( ? [ `- You opted out of some migrations for now. Write the following command down somewhere to apply these migrations later:`, ` nx migrate ${opts.targetVersion} --from ${opts.targetPackage}@${minVersionWithSkippedUpdates} --exclude-applied-migrations`, - `- To learn more go to https://nx.dev/recipes/other/advanced-update`, + `- To learn more go to https://nx.dev/recipes/managing-repository/advanced-update`, ] : [ `- To learn more go to https://nx.dev/core-features/automate-updating-dependencies`, From 6529be96cfafae3617dcd4d445e2ba2b9cf67e8e Mon Sep 17 00:00:00 2001 From: Caleb Ukle Date: Mon, 17 Jul 2023 10:42:12 -0500 Subject: [PATCH 086/262] feat(vite): add tsconfig paths resolution plugin (#17844) --- e2e/vite/src/vite.test.ts | 83 ++++++++-- packages/vite/migrations.json | 6 + packages/vite/package.json | 6 +- .../vite/plugins/nx-tsconfig-paths.plugin.ts | 89 +++++++++++ .../vite/src/executors/build/build.impl.ts | 7 +- .../executors/dev-server/dev-server.impl.ts | 4 +- .../__snapshots__/configuration.spec.ts.snap | 68 ++------ .../configuration/configuration.spec.ts | 1 - .../init/__snapshots__/init.spec.ts.snap | 4 - packages/vite/src/generators/init/init.ts | 2 - .../vitest/__snapshots__/vitest.spec.ts.snap | 45 ++---- .../change-ts-paths-plugin.spec.ts | 148 ++++++++++++++++++ .../change-ts-paths-plugin.ts | 64 ++++++++ packages/vite/src/utils/executor-utils.ts | 15 +- packages/vite/src/utils/generator-utils.ts | 12 +- packages/vite/src/utils/versions.ts | 1 - 16 files changed, 422 insertions(+), 133 deletions(-) create mode 100644 packages/vite/plugins/nx-tsconfig-paths.plugin.ts create mode 100644 packages/vite/src/migrations/update-16-6-0-change-ts-paths-plugin/change-ts-paths-plugin.spec.ts create mode 100644 packages/vite/src/migrations/update-16-6-0-change-ts-paths-plugin/change-ts-paths-plugin.ts diff --git a/e2e/vite/src/vite.test.ts b/e2e/vite/src/vite.test.ts index d1087fd689919..28ca5d8133c17 100644 --- a/e2e/vite/src/vite.test.ts +++ b/e2e/vite/src/vite.test.ts @@ -1,3 +1,4 @@ +import { names } from '@nx/devkit'; import { cleanupProject, createFile, @@ -240,6 +241,74 @@ describe('Vite Plugin', () => { 100_000; }); + describe('incremental building', () => { + const app = uniq('demo'); + const lib = uniq('my-lib'); + beforeAll(() => { + proj = newProject({ name: uniq('vite-incr-build') }); + runCLI(`generate @nx/react:app ${app} --bundler=vite --no-interactive`); + + // only this project will be directly used from dist + runCLI( + `generate @nx/react:lib ${lib}-buildable --unitTestRunner=none --bundler=vite --importPath="@acme/buildable" --no-interactive` + ); + + runCLI( + `generate @nx/react:lib ${lib} --unitTestRunner=none --bundler=none --importPath="@acme/non-buildable" --no-interactive` + ); + + // because the default js lib builds as cjs it cannot be loaded from dist + // so the paths plugin should always resolve to the libs source + runCLI( + `generate @nx/js:lib ${lib}-js --bundler=tsc --importPath="@acme/js-lib" --no-interactive` + ); + const buildableLibCmp = names(`${lib}-buildable`).className; + const nonBuildableLibCmp = names(lib).className; + const buildableJsLibFn = names(`${lib}-js`).propertyName; + + updateFile(`apps/${app}/src/app/app.tsx`, () => { + return `// eslint-disable-next-line @typescript-eslint/no-unused-vars +import styles from './app.module.css'; + +import NxWelcome from './nx-welcome'; +import { ${buildableLibCmp} } from '@acme/buildable'; +import { ${buildableJsLibFn} } from '@acme/js-lib'; +import { ${nonBuildableLibCmp} } from '@acme/non-buildable'; + +export function App() { + return ( +
+ <${buildableLibCmp} /> + <${nonBuildableLibCmp} /> +

{${buildableJsLibFn}()}

+ +
+ ); +} +export default App; +`; + }); + }); + + afterAll(() => { + cleanupProject(); + }); + + it('should build app from libs source', () => { + const results = runCLI(`build ${app} --buildLibsFromSource=true`); + expect(results).toContain('Successfully ran target build for project'); + // this should be more modules than build from dist + expect(results).toContain('40 modules transformed'); + }); + + it('should build app from libs dist', () => { + const results = runCLI(`build ${app} --buildLibsFromSource=false`); + expect(results).toContain('Successfully ran target build for project'); + // this should be less modules than building from source + expect(results).toContain('38 modules transformed'); + }); + }); + describe('should be able to create libs that use vitest', () => { const lib = uniq('my-lib'); beforeEach(() => { @@ -255,7 +324,6 @@ describe('Vite Plugin', () => { `Successfully ran target test for project ${lib}` ); - // TODO(caleb): run tests from project root and make sure they still work const nestedResults = await runCLIAsync(`test ${lib} --skip-nx-cache`, { cwd: `${tmpProjPath()}/libs/${lib}`, }); @@ -270,7 +338,7 @@ describe('Vite Plugin', () => { return `/// import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; - import viteTsConfigPaths from 'vite-tsconfig-paths'; + import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; export default defineConfig({ server: { @@ -279,9 +347,7 @@ describe('Vite Plugin', () => { }, plugins: [ react(), - viteTsConfigPaths({ - root: './', - }), + nxViteTsPaths() ], test: { globals: true, @@ -321,7 +387,8 @@ describe('Vite Plugin', () => { updateFile(`libs/${lib}/vite.config.ts`, () => { return `import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; -import viteTsConfigPaths from 'vite-tsconfig-paths'; +import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; + export default defineConfig({ server: { @@ -330,9 +397,7 @@ export default defineConfig({ }, plugins: [ react(), - viteTsConfigPaths({ - root: './', - }), + nxViteTsPaths() ], test: { globals: true, diff --git a/packages/vite/migrations.json b/packages/vite/migrations.json index b86d5bfcdee8b..dcad886b1b0ee 100644 --- a/packages/vite/migrations.json +++ b/packages/vite/migrations.json @@ -29,6 +29,12 @@ "description": "Changes the testFile config in the vite:test exectutor from a string to an array of strings", "cli": "nx", "implementation": "./src/migrations/update-16-4-1-update-test-file-config/update-16-4-1-test-file-config" + }, + "16-6-0-change-ts-paths-plugin": { + "version": "16.6.0-beta.4", + "description": "Change vite-tsconfig-paths plugin for first party nx-vite-tsconfig-paths plugin", + "cli": "nx", + "implementation": "./src/migrations/update-16-6-0-change-ts-paths-plugin/change-ts-paths-plugin" } }, "packageJsonUpdates": { diff --git a/packages/vite/package.json b/packages/vite/package.json index 4a4eb6a9324df..59a2e6e432f2e 100644 --- a/packages/vite/package.json +++ b/packages/vite/package.json @@ -34,7 +34,8 @@ "dotenv": "~10.0.0", "enquirer": "~2.3.6", "@nx/devkit": "file:../devkit", - "@nx/js": "file:../js" + "@nx/js": "file:../js", + "tsconfig-paths": "^4.1.2" }, "peerDependencies": { "vite": "^4.3.4", @@ -53,6 +54,7 @@ "./executors": "./executors.js", "./src/executors/*/schema.json": "./src/executors/*/schema.json", "./src/executors/*.impl": "./src/executors/*.impl.js", - "./src/executors/*/compat": "./src/executors/*/compat.js" + "./src/executors/*/compat": "./src/executors/*/compat.js", + "./plugins/nx-tsconfig-paths.plugin": "./plugins/nx-tsconfig-paths.plugin.js" } } diff --git a/packages/vite/plugins/nx-tsconfig-paths.plugin.ts b/packages/vite/plugins/nx-tsconfig-paths.plugin.ts new file mode 100644 index 0000000000000..afe9f478c0773 --- /dev/null +++ b/packages/vite/plugins/nx-tsconfig-paths.plugin.ts @@ -0,0 +1,89 @@ +import { stripIndents, workspaceRoot } from '@nx/devkit'; +import { existsSync } from 'node:fs'; +import { relative, join, resolve } from 'node:path'; +import { loadConfig, createMatchPath, MatchPath } from 'tsconfig-paths'; + +export function nxViteTsPaths() { + let matchTsPathEsm: MatchPath; + let matchTsPathFallback: MatchPath | undefined; + + return { + name: 'nx-vite-ts-paths', + configResolved(config: any) { + const projectRoot = config.root; + const projectRootFromWorkspaceRoot = relative(workspaceRoot, projectRoot); + + const foundTsConfigPath = getTsConfig( + join( + workspaceRoot, + 'tmp', + projectRootFromWorkspaceRoot, + 'tsconfig.generated.json' + ) + ); + if (!foundTsConfigPath) { + throw new Error(stripIndents`Unable to find a tsconfig in the workspace! +There should at least be a tsconfig.base.json or tsconfig.json in the root of the workspace ${workspaceRoot}`); + } + const parsed = loadConfig(foundTsConfigPath); + + logIt('first parsed tsconfig: ', parsed); + if (parsed.resultType === 'failed') { + throw new Error(`Failed loading tsonfig at ${foundTsConfigPath}`); + } + + matchTsPathEsm = createMatchPath(parsed.absoluteBaseUrl, parsed.paths, [ + ['exports', '.', 'import'], + 'module', + 'main', + ]); + + const rootLevelTsConfig = getTsConfig( + join(workspaceRoot, 'tsconfig.base.json') + ); + const rootLevelParsed = loadConfig(rootLevelTsConfig); + logIt('fallback parsed tsconfig: ', rootLevelParsed); + if (rootLevelParsed.resultType === 'success') { + matchTsPathFallback = createMatchPath( + rootLevelParsed.absoluteBaseUrl, + rootLevelParsed.paths, + ['main', 'module'] + ); + } + }, + resolveId(source: string) { + let resolvedFile: string; + try { + resolvedFile = matchTsPathEsm(source); + } catch (e) { + logIt('Using fallback path matching.'); + resolvedFile = matchTsPathFallback?.(source); + } + + if (!resolvedFile) { + logIt(`Unable to resolve ${source} with tsconfig paths`); + } + + return resolvedFile; + }, + }; +} + +function getTsConfig(preferredTsConfigPath: string): string { + return [ + resolve(preferredTsConfigPath), + resolve(join(workspaceRoot, 'tsconfig.base.json')), + resolve(join(workspaceRoot, 'tsconfig.json')), + ].find((tsPath) => { + if (existsSync(tsPath)) { + logIt('Found tsconfig at', tsPath); + return tsPath; + } + }); +} + +function logIt(...msg: any[]) { + if (process.env.NX_VERBOSE_LOGGING === 'true') { + console.debug('[Nx Vite TsPaths]', ...msg); + } +} diff --git a/packages/vite/src/executors/build/build.impl.ts b/packages/vite/src/executors/build/build.impl.ts index 1ec6aea2db3cc..24649df190cf5 100644 --- a/packages/vite/src/executors/build/build.impl.ts +++ b/packages/vite/src/executors/build/build.impl.ts @@ -21,7 +21,10 @@ import { import { existsSync, writeFileSync } from 'fs'; import { resolve } from 'path'; import { createAsyncIterable } from '@nx/devkit/src/utils/async-iterable'; -import { registerPaths, validateTypes } from '../../utils/executor-utils'; +import { + createBuildableTsConfig, + validateTypes, +} from '../../utils/executor-utils'; export async function* viteBuildExecutor( options: ViteBuildExecutorOptions, @@ -30,7 +33,7 @@ export async function* viteBuildExecutor( const projectRoot = context.projectsConfigurations.projects[context.projectName].root; - registerPaths(projectRoot, options, context); + createBuildableTsConfig(projectRoot, options, context); const normalizedOptions = normalizeOptions(options); diff --git a/packages/vite/src/executors/dev-server/dev-server.impl.ts b/packages/vite/src/executors/dev-server/dev-server.impl.ts index f43342fa39662..2ed3171b35bf7 100644 --- a/packages/vite/src/executors/dev-server/dev-server.impl.ts +++ b/packages/vite/src/executors/dev-server/dev-server.impl.ts @@ -11,7 +11,7 @@ import { import { ViteDevServerExecutorOptions } from './schema'; import { ViteBuildExecutorOptions } from '../build/schema'; -import { registerPaths } from '../../utils/executor-utils'; +import { createBuildableTsConfig } from '../../utils/executor-utils'; export async function* viteDevServerExecutor( options: ViteDevServerExecutorOptions, @@ -20,7 +20,7 @@ export async function* viteDevServerExecutor( const projectRoot = context.projectsConfigurations.projects[context.projectName].root; - registerPaths(projectRoot, options, context); + createBuildableTsConfig(projectRoot, options, context); // Retrieve the option for the configured buildTarget. const buildTargetOptions: ViteBuildExecutorOptions = getNxTargetOptions( diff --git a/packages/vite/src/generators/configuration/__snapshots__/configuration.spec.ts.snap b/packages/vite/src/generators/configuration/__snapshots__/configuration.spec.ts.snap index 2690351e4f874..13b7f088bbde1 100644 --- a/packages/vite/src/generators/configuration/__snapshots__/configuration.spec.ts.snap +++ b/packages/vite/src/generators/configuration/__snapshots__/configuration.spec.ts.snap @@ -4,7 +4,7 @@ exports[`@nx/vite:configuration library mode should add config for building libr "/// import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; -import viteTsConfigPaths from 'vite-tsconfig-paths'; +import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; import dts from 'vite-plugin-dts'; import * as path from 'path'; @@ -18,18 +18,12 @@ export default defineConfig({ skipDiagnostics: true, }), react(), - viteTsConfigPaths({ - root: '../', - }), + nxViteTsPaths(), ], // Uncomment this if you are using workers. // worker: { - // plugins: [ - // viteTsConfigPaths({ - // root: '../', - // }), - // ], + // plugins: [ nxViteTsPaths() ], // }, // Configuration for building your library. @@ -57,7 +51,7 @@ exports[`@nx/vite:configuration library mode should set up non buildable library "/// import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; -import viteTsConfigPaths from 'vite-tsconfig-paths'; +import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; import dts from 'vite-plugin-dts'; import * as path from 'path'; @@ -71,18 +65,12 @@ export default defineConfig({ skipDiagnostics: true, }), react(), - viteTsConfigPaths({ - root: '../../', - }), + nxViteTsPaths(), ], // Uncomment this if you are using workers. // worker: { - // plugins: [ - // viteTsConfigPaths({ - // root: '../../', - // }), - // ], + // plugins: [ nxViteTsPaths() ], // }, // Configuration for building your library. @@ -301,7 +289,7 @@ exports[`@nx/vite:configuration transform React app to use Vite should create vi "/// import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; -import viteTsConfigPaths from 'vite-tsconfig-paths'; +import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; export default defineConfig({ cacheDir: '../../node_modules/.vite/my-test-react-app', @@ -316,20 +304,11 @@ export default defineConfig({ host: 'localhost', }, - plugins: [ - react(), - viteTsConfigPaths({ - root: '../../', - }), - ], + plugins: [react(), nxViteTsPaths()], // Uncomment this if you are using workers. // worker: { - // plugins: [ - // viteTsConfigPaths({ - // root: '../../', - // }), - // ], + // plugins: [ nxViteTsPaths() ], // }, }); " @@ -451,7 +430,7 @@ exports[`@nx/vite:configuration transform Web app to use Vite should create vite "/// import { defineConfig } from 'vite'; -import viteTsConfigPaths from 'vite-tsconfig-paths'; +import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; export default defineConfig({ cacheDir: '../../node_modules/.vite/my-test-web-app', @@ -466,19 +445,11 @@ export default defineConfig({ host: 'localhost', }, - plugins: [ - viteTsConfigPaths({ - root: '../../', - }), - ], + plugins: [nxViteTsPaths()], // Uncomment this if you are using workers. // worker: { - // plugins: [ - // viteTsConfigPaths({ - // root: '../../', - // }), - // ], + // plugins: [ nxViteTsPaths() ], // }, }); " @@ -587,7 +558,7 @@ exports[`@nx/vite:configuration vitest should create a vitest configuration if " "/// import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; -import viteTsConfigPaths from 'vite-tsconfig-paths'; +import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; export default defineConfig({ cacheDir: '../../node_modules/.vite/my-test-react-app', @@ -602,20 +573,11 @@ export default defineConfig({ host: 'localhost', }, - plugins: [ - react(), - viteTsConfigPaths({ - root: '../../', - }), - ], + plugins: [react(), nxViteTsPaths()], // Uncomment this if you are using workers. // worker: { - // plugins: [ - // viteTsConfigPaths({ - // root: '../../', - // }), - // ], + // plugins: [ nxViteTsPaths() ], // }, test: { diff --git a/packages/vite/src/generators/configuration/configuration.spec.ts b/packages/vite/src/generators/configuration/configuration.spec.ts index 70d444f78ebb3..4d423ba05a92a 100644 --- a/packages/vite/src/generators/configuration/configuration.spec.ts +++ b/packages/vite/src/generators/configuration/configuration.spec.ts @@ -94,7 +94,6 @@ describe('@nx/vite:configuration', () => { const packageJson = readJson(tree, '/package.json'); expect(packageJson.devDependencies).toMatchObject({ vite: expect.any(String), - 'vite-tsconfig-paths': expect.any(String), }); }); diff --git a/packages/vite/src/generators/init/__snapshots__/init.spec.ts.snap b/packages/vite/src/generators/init/__snapshots__/init.spec.ts.snap index 3820d22ed0171..4ca1caf3b70eb 100644 --- a/packages/vite/src/generators/init/__snapshots__/init.spec.ts.snap +++ b/packages/vite/src/generators/init/__snapshots__/init.spec.ts.snap @@ -14,7 +14,6 @@ exports[`@nx/vite:init dependencies for package.json should add vite packages an "prettier": "^2.6.2", "typescript": "~5.1.3", "vite": "~4.3.9", - "vite-tsconfig-paths": "~4.2.0", "vitest": "~0.32.0", }, "name": "test-name", @@ -32,7 +31,6 @@ exports[`@nx/vite:init dependencies for package.json should support --testEnviro "prettier": "^2.6.2", "typescript": "~5.1.3", "vite": "~4.3.9", - "vite-tsconfig-paths": "~4.2.0", "vitest": "~0.32.0", }, "name": "test-name", @@ -50,7 +48,6 @@ exports[`@nx/vite:init dependencies for package.json should support --testEnviro "prettier": "^2.6.2", "typescript": "~5.1.3", "vite": "~4.3.9", - "vite-tsconfig-paths": "~4.2.0", "vitest": "~0.32.0", }, "name": "test-name", @@ -68,7 +65,6 @@ exports[`@nx/vite:init dependencies for package.json should support --testEnviro "prettier": "^2.6.2", "typescript": "~5.1.3", "vite": "~4.3.9", - "vite-tsconfig-paths": "~4.2.0", "vitest": "~0.32.0", }, "name": "test-name", diff --git a/packages/vite/src/generators/init/init.ts b/packages/vite/src/generators/init/init.ts index e4d4573ac2d94..bf2c38b961190 100644 --- a/packages/vite/src/generators/init/init.ts +++ b/packages/vite/src/generators/init/init.ts @@ -20,7 +20,6 @@ import { vitePluginReactSwcVersion, vitestUiVersion, vitestVersion, - viteTsConfigPathsVersion, viteVersion, happyDomVersion, edgeRuntimeVmVersion, @@ -37,7 +36,6 @@ function checkDependenciesInstalled(host: Tree, schema: InitGeneratorSchema) { // base deps devDependencies['@nx/vite'] = nxVersion; devDependencies['vite'] = viteVersion; - devDependencies['vite-tsconfig-paths'] = viteTsConfigPathsVersion; devDependencies['vitest'] = vitestVersion; devDependencies['@vitest/ui'] = vitestUiVersion; diff --git a/packages/vite/src/generators/vitest/__snapshots__/vitest.spec.ts.snap b/packages/vite/src/generators/vitest/__snapshots__/vitest.spec.ts.snap index bb857108f62d3..4087eb8e6d90a 100644 --- a/packages/vite/src/generators/vitest/__snapshots__/vitest.spec.ts.snap +++ b/packages/vite/src/generators/vitest/__snapshots__/vitest.spec.ts.snap @@ -4,25 +4,16 @@ exports[`vitest generator insourceTests should add the insourceSource option in "/// import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; -import viteTsConfigPaths from 'vite-tsconfig-paths'; +import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; export default defineConfig({ cacheDir: '../../node_modules/.vite/my-test-react-app', - plugins: [ - react(), - viteTsConfigPaths({ - root: '../../', - }), - ], + plugins: [react(), nxViteTsPaths()], // Uncomment this if you are using workers. // worker: { - // plugins: [ - // viteTsConfigPaths({ - // root: '../../', - // }), - // ], + // plugins: [ nxViteTsPaths() ], // }, define: { @@ -45,25 +36,16 @@ exports[`vitest generator vite.config should create correct vite.config.ts file "/// import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; -import viteTsConfigPaths from 'vite-tsconfig-paths'; +import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; export default defineConfig({ cacheDir: '../../node_modules/.vite/my-test-react-app', - plugins: [ - react(), - viteTsConfigPaths({ - root: '../../', - }), - ], + plugins: [react(), nxViteTsPaths()], // Uncomment this if you are using workers. // worker: { - // plugins: [ - // viteTsConfigPaths({ - // root: '../../', - // }), - // ], + // plugins: [ nxViteTsPaths() ], // }, test: { @@ -82,25 +64,16 @@ exports[`vitest generator vite.config should create correct vite.config.ts file "/// import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; -import viteTsConfigPaths from 'vite-tsconfig-paths'; +import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; export default defineConfig({ cacheDir: '../../node_modules/.vite/react-lib-nonb-jest', - plugins: [ - react(), - viteTsConfigPaths({ - root: '../../', - }), - ], + plugins: [react(), nxViteTsPaths()], // Uncomment this if you are using workers. // worker: { - // plugins: [ - // viteTsConfigPaths({ - // root: '../../', - // }), - // ], + // plugins: [ nxViteTsPaths() ], // }, test: { diff --git a/packages/vite/src/migrations/update-16-6-0-change-ts-paths-plugin/change-ts-paths-plugin.spec.ts b/packages/vite/src/migrations/update-16-6-0-change-ts-paths-plugin/change-ts-paths-plugin.spec.ts new file mode 100644 index 0000000000000..8cbcac9d428f3 --- /dev/null +++ b/packages/vite/src/migrations/update-16-6-0-change-ts-paths-plugin/change-ts-paths-plugin.spec.ts @@ -0,0 +1,148 @@ +import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; +import { Tree, addProjectConfiguration } from '@nx/devkit'; + +import changeTsPathsPlugin from './change-ts-paths-plugin'; + +describe('change-vite-ts-paths-plugin migration', () => { + let tree: Tree; + + beforeEach(() => { + tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' }); + }); + + it('should update viteTsConfigPaths to nxViteTsPaths plugin', () => { + addProject(tree, 'demo'); + + changeTsPathsPlugin(tree); + + expect(tree.read('apps/demo/vite.config.ts', 'utf-8')) + .toMatchInlineSnapshot(` + " + /// + import { defineConfig } from 'vite'; + import react from '@vitejs/plugin-react'; + import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; + + export default defineConfig({ + cacheDir: '../../node_modules/.vite/demo', + server: { + port: 4200, + host: 'localhost', + }, + + preview: { + port: 4300, + host: 'localhost', + }, + + plugins: [ + react(), + nxViteTsPaths() + ], + + // Uncomment this if you are using workers. + // worker: { + // plugins: [ + // viteTsConfigPaths({ + // root: '../../', + // }), + // ], + // }, + + test: { + globals: true, + cache: { + dir: '../../node_modules/.vitest', + }, + environment: 'jsdom', + include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], + }, + }); + + " + `); + }); + + it('should not change anything if viteTsConfigPaths is not used', () => { + addProject(tree, 'demo'); + tree.delete('apps/demo/vite.config.ts'); + + expect(() => changeTsPathsPlugin(tree)).not.toThrow(); + expect(tree.exists('apps/demo/vite.config.ts')).toBeFalsy(); + }); +}); + +function addProject(tree: Tree, name: string) { + addProjectConfiguration(tree, name, { + root: `apps/${name}`, + sourceRoot: `apps/${name}/src`, + targets: { + build: { + executor: '@nx/vite:build', + outputs: ['{options.outputPath}'], + defaultConfiguration: 'production', + options: { + outputPath: `dist/apps/${name}`, + buildLibsFromSource: false, + }, + configurations: { + development: { + mode: 'development', + }, + production: { + mode: 'production', + }, + }, + }, + }, + }); + + tree.write( + `apps/${name}/vite.config.ts`, + ` +/// +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; +import viteTsConfigPaths from 'vite-tsconfig-paths'; + +export default defineConfig({ + cacheDir: '../../node_modules/.vite/${name}', + server: { + port: 4200, + host: 'localhost', + }, + + preview: { + port: 4300, + host: 'localhost', + }, + + plugins: [ + react(), + viteTsConfigPaths({ + root: '../../' + }) + ], + + // Uncomment this if you are using workers. + // worker: { + // plugins: [ + // viteTsConfigPaths({ + // root: '../../', + // }), + // ], + // }, + + test: { + globals: true, + cache: { + dir: '../../node_modules/.vitest', + }, + environment: 'jsdom', + include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], + }, +}); + +` + ); +} diff --git a/packages/vite/src/migrations/update-16-6-0-change-ts-paths-plugin/change-ts-paths-plugin.ts b/packages/vite/src/migrations/update-16-6-0-change-ts-paths-plugin/change-ts-paths-plugin.ts new file mode 100644 index 0000000000000..ffadb39c139a2 --- /dev/null +++ b/packages/vite/src/migrations/update-16-6-0-change-ts-paths-plugin/change-ts-paths-plugin.ts @@ -0,0 +1,64 @@ +import { Tree, getProjects, joinPathFragments } from '@nx/devkit'; +import { forEachExecutorOptions } from '@nx/devkit/src/generators/executor-options-utils'; +import { ViteBuildExecutorOptions } from '../../executors/build/schema'; +import { tsquery } from '@phenomnomnominal/tsquery'; +import { ImportDeclaration } from 'typescript'; + +export default function update(tree: Tree) { + const projects = getProjects(tree); + forEachExecutorOptions( + tree, + '@nx/vite:build', + (options, projectName) => { + const projectConfig = projects.get(projectName); + const config = + options.configFile || findViteConfig(tree, projectConfig.root); + if (!config || !tree.exists(config)) { + return; + } + + const configContents = tree.read(config, 'utf-8'); + + const oldTsConfigPathPlugin = + tsquery.query( + configContents, + 'ImportDeclaration:has(StringLiteral[value="vite-tsconfig-paths"])' + ) ?? []; + + if (oldTsConfigPathPlugin.length === 0) { + return; + } + + const importName = + oldTsConfigPathPlugin[0]?.importClause?.name?.text ?? + 'viteTsConfigPaths'; + const updatedContent = tsquery.replace( + configContents, + `PropertyAssignment:has(Identifier[name="plugins"]) CallExpression:has(Identifier[name="${importName}"])`, + () => { + return `nxViteTsPaths()`; + } + ); + + const withImportChange = tsquery.replace( + updatedContent, + 'ImportDeclaration:has(StringLiteral[value="vite-tsconfig-paths"])', + () => { + return "import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';"; + } + ); + + tree.write(config, withImportChange); + } + ); +} + +function findViteConfig(tree: Tree, searchRoot: string) { + const allowsExt = ['js', 'mjs', 'ts', 'cjs', 'mts', 'cts']; + + for (const ext of allowsExt) { + if (tree.exists(joinPathFragments(searchRoot, `vite.config.${ext}`))) { + return joinPathFragments(searchRoot, `vite.config.${ext}`); + } + } +} diff --git a/packages/vite/src/utils/executor-utils.ts b/packages/vite/src/utils/executor-utils.ts index 470f1ff73d803..d80069746bde3 100644 --- a/packages/vite/src/utils/executor-utils.ts +++ b/packages/vite/src/utils/executor-utils.ts @@ -7,7 +7,6 @@ import { calculateProjectDependencies, createTmpTsConfig, } from '@nx/js/src/utils/buildable-libs-utils'; -import { registerTsConfigPaths } from '@nx/js/src/internal'; export async function validateTypes(opts: { workspaceRoot: string; @@ -27,7 +26,7 @@ export async function validateTypes(opts: { } } -export function registerPaths( +export function createBuildableTsConfig( projectRoot: string, options: ViteBuildExecutorOptions | ViteDevServerExecutorOptions, context: ExecutorContext @@ -43,15 +42,7 @@ export function registerPaths( context.targetName, context.configurationName ); - const tmpTsConfig = createTmpTsConfig( - tsConfig, - context.root, - projectRoot, - dependencies - ); - - registerTsConfigPaths(tmpTsConfig); - } else { - registerTsConfigPaths(tsConfig); + // this tsconfig is used via the vite ts paths plugin + createTmpTsConfig(tsConfig, context.root, projectRoot, dependencies); } } diff --git a/packages/vite/src/utils/generator-utils.ts b/packages/vite/src/utils/generator-utils.ts index 7c5ee1deec570..a20caeeb66f20 100644 --- a/packages/vite/src/utils/generator-utils.ts +++ b/packages/vite/src/utils/generator-utils.ts @@ -587,20 +587,14 @@ export function createOrEditViteConfig( plugins: [ ${dtsPlugin} ${reactPlugin} - viteTsConfigPaths({ - root: '${offsetFromRoot(projectConfig.root)}', - }), + nxViteTsPaths(), ], `; const workerOption = ` // Uncomment this if you are using workers. // worker: { - // plugins: [ - // viteTsConfigPaths({ - // root: '${offsetFromRoot(projectConfig.root)}', - // }), - // ], + // plugins: [ nxViteTsPaths() ], // },`; const cacheDir = `cacheDir: '${offsetFromRoot( @@ -628,7 +622,7 @@ export function createOrEditViteConfig( /// import { defineConfig } from 'vite'; ${reactPluginImportLine} - import viteTsConfigPaths from 'vite-tsconfig-paths'; + import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; ${dtsImportLine} export default defineConfig({ diff --git a/packages/vite/src/utils/versions.ts b/packages/vite/src/utils/versions.ts index cd3c3210791a3..e3e4ab39984ee 100644 --- a/packages/vite/src/utils/versions.ts +++ b/packages/vite/src/utils/versions.ts @@ -4,7 +4,6 @@ export const vitestVersion = '~0.32.0'; export const vitestUiVersion = '~0.32.0'; export const vitePluginReactVersion = '~4.0.0'; export const vitePluginReactSwcVersion = '~3.3.2'; -export const viteTsConfigPathsVersion = '~4.2.0'; export const jsdomVersion = '~22.1.0'; export const vitePluginDtsVersion = '~2.3.0'; export const happyDomVersion = '~9.20.3'; From 699a20ca03236676a7923cc96e4766b7cedbe519 Mon Sep 17 00:00:00 2001 From: Emily Xiong Date: Mon, 17 Jul 2023 13:07:46 -0400 Subject: [PATCH 087/262] feat(react-native): upgrade react-native to 0.72 (#17810) --- .../packages/expo/documents/overview.md | 28 +- .../packages/expo/executors/build.json | 3 +- .../packages/expo/executors/run.json | 1 + .../packages/expo/executors/start.json | 1 + .../react-native/executors/build-android.json | 20 +- .../react-native/executors/build-ios.json | 16 +- .../react-native/executors/pod-install.json | 12 +- .../react-native/executors/run-android.json | 12 +- .../react-native/executors/run-ios.json | 15 +- docs/shared/packages/expo/expo-plugin.md | 28 +- e2e/expo/src/expo.test.ts | 8 +- package.json | 3 +- .../application/application.spec.ts | 12 - .../files/app/.detoxrc.json.template | 18 - .../application/lib/get-targets.spec.ts | 11 +- .../generators/application/lib/get-targets.ts | 11 +- packages/expo/migrations.json | 73 ++ packages/expo/package.json | 7 +- packages/expo/plugins/with-nx-metro.ts | 34 +- packages/expo/plugins/with-nx-webpack.ts | 2 +- .../executors/build-list/build-list.impl.ts | 6 +- .../expo/src/executors/build/build.impl.ts | 17 +- packages/expo/src/executors/build/schema.json | 3 +- .../src/executors/download/download.impl.ts | 1 + .../expo/src/executors/export/export.impl.ts | 8 +- .../src/executors/install/install.impl.ts | 3 +- .../src/executors/prebuild/prebuild.impl.ts | 4 +- packages/expo/src/executors/run/run.impl.ts | 21 +- packages/expo/src/executors/run/schema.d.ts | 3 + packages/expo/src/executors/run/schema.json | 1 + packages/expo/src/executors/start/schema.d.ts | 4 +- packages/expo/src/executors/start/schema.json | 1 + .../expo/src/executors/start/start.impl.ts | 23 +- .../expo/src/executors/submit/submit.impl.ts | 9 +- .../expo/src/executors/update/update.impl.ts | 6 +- .../application/application.spec.ts | 36 - .../files/metro.config.js.template | 52 +- .../application/files/package.json.template | 1 + .../generators/application/lib/add-project.ts | 8 + .../update-16-6-0/add-depends-on.ts | 21 + .../update-16-6-0/update-metro-config.ts | 73 ++ packages/expo/src/utils/versions.ts | 27 +- packages/react-native/migrations.json | 78 ++ packages/react-native/package.json | 5 +- .../react-native/plugins/with-nx-metro.ts | 33 +- .../build-android/build-android.impl.ts | 71 +- .../src/executors/build-android/schema.d.ts | 8 +- .../src/executors/build-android/schema.json | 22 +- .../src/executors/build-ios/build-ios.impl.ts | 90 +-- .../src/executors/build-ios/schema.d.ts | 3 + .../src/executors/build-ios/schema.json | 14 +- .../src/executors/bundle/bundle.impl.ts | 47 +- .../executors/pod-install/pod-install.impl.ts | 2 +- .../src/executors/pod-install/schema.d.ts | 4 +- .../src/executors/pod-install/schema.json | 12 +- .../executors/run-android/run-android.impl.ts | 85 +-- .../src/executors/run-android/schema.d.ts | 4 +- .../src/executors/run-android/schema.json | 14 +- .../src/executors/run-ios/run-ios.impl.ts | 98 ++- .../src/executors/run-ios/schema.d.ts | 2 +- .../src/executors/run-ios/schema.json | 13 +- .../src/executors/start/start.impl.ts | 77 +- .../src/executors/storybook/schema.d.ts | 2 +- .../src/generators/application/application.ts | 6 - .../application/files/app/.ruby-version | 1 - .../application/files/app/Gemfile.template | 4 +- .../app/android/app/build.gradle.template | 51 +- .../MainActivity.java.template | 5 +- .../res/drawable/rn_edit_text_material.xml | 2 +- .../files/app/android/build.gradle.template | 2 +- .../files/app/android/gradle.properties | 2 +- .../android/gradle/wrapper/gradle-wrapper.jar | Bin 59821 -> 61574 bytes .../gradle/wrapper/gradle-wrapper.properties | 3 +- .../application/files/app/android/gradlew.bat | 15 +- .../files/app/android/gradlew.template | 18 +- .../app/android/settings.gradle.template | 3 +- .../files/app/ios/Podfile.template | 14 +- .../project.pbxproj.template | 8 +- .../ios/__className__/AppDelegate.mm.template | 10 - .../files/app/metro.config.js.template | 67 +- .../files/app/package.json.template | 1 + .../generators/application/lib/add-project.ts | 7 + .../react-native/src/generators/init/init.ts | 4 +- ...age.json__tmpl__ => package.json.template} | 0 .../{index.ts__tmpl__ => index.ts.template} | 0 ...ig.json__tmpl__ => tsconfig.json.template} | 0 ...son__tmpl__ => tsconfig.lib.json.template} | 0 .../src/generators/library/library.ts | 1 - .../update-16-6-0/add-depends-on.ts | 39 + .../update-16-6-0/update-metro-config.ts | 71 ++ .../react-native/src/utils/get-cli-options.ts | 4 +- .../src/utils/pod-install-task.ts | 38 +- packages/react-native/src/utils/versions.ts | 19 +- pnpm-lock.yaml | 705 ++++++++++++++++-- 94 files changed, 1651 insertions(+), 776 deletions(-) create mode 100644 packages/expo/src/migrations/update-16-6-0/add-depends-on.ts create mode 100644 packages/expo/src/migrations/update-16-6-0/update-metro-config.ts delete mode 100644 packages/react-native/src/generators/application/files/app/.ruby-version rename packages/react-native/src/generators/library/files/lib/{package.json__tmpl__ => package.json.template} (100%) rename packages/react-native/src/generators/library/files/lib/src/{index.ts__tmpl__ => index.ts.template} (100%) rename packages/react-native/src/generators/library/files/lib/{tsconfig.json__tmpl__ => tsconfig.json.template} (100%) rename packages/react-native/src/generators/library/files/lib/{tsconfig.lib.json__tmpl__ => tsconfig.lib.json.template} (100%) create mode 100644 packages/react-native/src/migrations/update-16-6-0/add-depends-on.ts create mode 100644 packages/react-native/src/migrations/update-16-6-0/update-metro-config.ts diff --git a/docs/generated/packages/expo/documents/overview.md b/docs/generated/packages/expo/documents/overview.md index 2bd3082683376..b7b9e37ba971a 100644 --- a/docs/generated/packages/expo/documents/overview.md +++ b/docs/generated/packages/expo/documents/overview.md @@ -50,7 +50,7 @@ nx start my-app To generate a new library run: ```shell -npx nx g @nx/react-native:lib your-lib-name +npx nx g @nx/expo:lib your-lib-name ``` ### Generating Components @@ -58,7 +58,7 @@ npx nx g @nx/react-native:lib your-lib-name To generate a new component inside library run: ```shell -npx nx g @nx/react-native:component your-component-name --project=your-lib-name --export +npx nx g @nx/expo:component your-component-name --project=your-lib-name --export ``` Replace `your-lib-name` with the app's name as defined in your `tsconfig.base.json` file or the `name` property of your `package.json` @@ -247,6 +247,28 @@ To check the details of your build status, run: nx build-list ``` +### Submit an EAS Build + +EAS Submit is a hosted service for uploading and submitting your app binaries to the app stores. Since it's a hosted service, you can submit your app to both stores as long as you can run EAS CLI on your machine. + +To submit an EAS build: + +```shell +nx submit +``` + +### Update an EAS Build + +EAS Update is a hosted service that serves updates for projects using the `expo-updates` library. + +EAS Update makes fixing small bugs and pushing quick fixes a snap in between app store submissions. It accomplishes this by allowing an end-user's app to swap out the non-native parts of their app (for example, JS, styling, and image changes) with a new update that contains bug fixes and other updates. + +To update an EAS build: + +```shell +nx update +``` + ### Testing Projects You can run unit tests with: @@ -269,6 +291,8 @@ Below table is a map between expo commands and Nx commands: | `expo install` | `nx install ` | | `eas build` | `nx build ` | | `eas build:list` | `nx build-list ` | +| `eas update` | `nx update ` | +| `eas submit` | `nx submit ` | ## More Documentation diff --git a/docs/generated/packages/expo/executors/build.json b/docs/generated/packages/expo/executors/build.json index c1bc9395e445f..7d5fc37afc68f 100644 --- a/docs/generated/packages/expo/executors/build.json +++ b/docs/generated/packages/expo/executors/build.json @@ -46,7 +46,8 @@ }, "output": { "type": "string", - "description": "Output path for local build" + "description": "Output path for local build", + "examples": ["../../dist/MyApp.tar.gz", "../../dist"] }, "wait": { "type": "boolean", diff --git a/docs/generated/packages/expo/executors/run.json b/docs/generated/packages/expo/executors/run.json index 668255c4e7e2f..2e93f59d43d55 100644 --- a/docs/generated/packages/expo/executors/run.json +++ b/docs/generated/packages/expo/executors/run.json @@ -42,6 +42,7 @@ "type": "boolean", "description": "Syncs npm dependencies to package.json (for React Native autolink).", "default": true, + "x-deprecated": "Add sync-deps to dependsOn in project.json for this target instead", "x-priority": "internal" }, "port": { diff --git a/docs/generated/packages/expo/executors/start.json b/docs/generated/packages/expo/executors/start.json index 5a1de553705ec..681aa875edc0e 100644 --- a/docs/generated/packages/expo/executors/start.json +++ b/docs/generated/packages/expo/executors/start.json @@ -88,6 +88,7 @@ "sync": { "type": "boolean", "description": "Syncs npm dependencies to package.json (for React Native autolink).", + "x-deprecated": "Add sync-deps to dependsOn in project.json for this target instead", "default": true } }, diff --git a/docs/generated/packages/react-native/executors/build-android.json b/docs/generated/packages/react-native/executors/build-android.json index cdac5b307debc..565bd793d24a0 100644 --- a/docs/generated/packages/react-native/executors/build-android.json +++ b/docs/generated/packages/react-native/executors/build-android.json @@ -45,7 +45,8 @@ "packager": { "type": "boolean", "description": "Launch packager while building", - "default": true + "default": true, + "x-deprecated": "Run `nx run :start` instead. Will be removed in Nx 17." }, "port": { "type": "number", @@ -53,8 +54,10 @@ "default": 8081 }, "tasks": { - "type": "array", - "items": { "type": "string" }, + "oneOf": [ + { "type": "array", "items": { "type": "string" } }, + { "type": "string" } + ], "description": "Run custom Gradle tasks. By default it's \"assembleDebug\". Will override passed mode and variant arguments.", "examples": [ "assembleDebug", @@ -71,8 +74,12 @@ "default": false }, "extraParams": { - "type": "string", - "description": "Custom params passed to gradle build command" + "oneOf": [ + { "type": "array", "items": { "type": "string" } }, + { "type": "string" } + ], + "description": "Custom params passed to gradle build command", + "examples": ["-x lint -x test"] }, "interactive": { "type": "boolean", @@ -81,7 +88,8 @@ "sync": { "type": "boolean", "description": "Syncs npm dependencies to `package.json` (for React Native autolink).", - "default": true + "default": true, + "x-deprecated": "Add sync-deps to dependsOn instead" }, "resetCache": { "type": "boolean", diff --git a/docs/generated/packages/react-native/executors/build-ios.json b/docs/generated/packages/react-native/executors/build-ios.json index 9f1d67083d601..861bd13c03539 100644 --- a/docs/generated/packages/react-native/executors/build-ios.json +++ b/docs/generated/packages/react-native/executors/build-ios.json @@ -11,11 +11,7 @@ "presets": [ { "name": "Build iOS for a simulator", "keys": ["simulator"] }, { "name": "Build iOS for a device", "keys": ["device"] }, - { "name": "Build iOS for a device with udid", "keys": ["udid"] }, - { - "name": "Run `pod install` before building iOS app", - "keys": ["install"] - } + { "name": "Build iOS for a device with udid", "keys": ["udid"] } ], "properties": { "simulator": { @@ -72,17 +68,22 @@ "description": "Explicitly select which scheme and configuration to use before running a build" }, "extraParams": { - "type": "string", + "oneOf": [ + { "type": "array", "items": { "type": "string" } }, + { "type": "string" } + ], "description": "Custom params that will be passed to xcodebuild command." }, "install": { "type": "boolean", "description": "Runs `pod install` for native modules before building iOS app.", + "x-deprecated": "Add pod-install to dependsOn in project.json for this target instead", "default": true }, "sync": { "type": "boolean", "description": "Syncs npm dependencies to `package.json` (for React Native autolink).", + "x-deprecated": "Add sync-deps to dependsOn in project.json for this target instead", "default": true }, "resetCache": { @@ -93,7 +94,8 @@ "packager": { "type": "boolean", "description": "Launch packager while building", - "default": true + "default": true, + "x-deprecated": "Run `nx run :start` instead. Will be removed in Nx 17." } }, "required": [], diff --git a/docs/generated/packages/react-native/executors/pod-install.json b/docs/generated/packages/react-native/executors/pod-install.json index da7c4b7f32ed1..2e4f9beae6847 100644 --- a/docs/generated/packages/react-native/executors/pod-install.json +++ b/docs/generated/packages/react-native/executors/pod-install.json @@ -12,9 +12,19 @@ "type": "object", "properties": { "buildFolder": { - "description": "Location for iOS build artifacts. Corresponds to Xcode's \"-derivedDataPath\". Relative to ios directory", + "description": "Location for iOS build artifacts. Corresponds to Xcode's \"-derivedDataPath\". Relative to ios directory.", "type": "string", "default": "./build" + }, + "repoUpdate": { + "description": "Force running `pod repo update` before install.", + "type": "boolean", + "default": false + }, + "deployment": { + "description": "Disallow any changes to the Podfile or the Podfile.lock during installation.", + "type": "boolean", + "default": false } }, "required": ["buildFolder"], diff --git a/docs/generated/packages/react-native/executors/run-android.json b/docs/generated/packages/react-native/executors/run-android.json index 1f64e92ced64d..cf0a67aa56360 100644 --- a/docs/generated/packages/react-native/executors/run-android.json +++ b/docs/generated/packages/react-native/executors/run-android.json @@ -77,8 +77,10 @@ "default": 8081 }, "tasks": { - "type": "array", - "items": { "type": "string" }, + "oneOf": [ + { "type": "array", "items": { "type": "string" } }, + { "type": "string" } + ], "description": "Run custom Gradle tasks. By default it's \"assembleDebug\". Will override passed mode and variant arguments.", "examples": [ "assembleDebug", @@ -95,7 +97,10 @@ "default": false }, "extraParams": { - "type": "string", + "oneOf": [ + { "type": "array", "items": { "type": "string" } }, + { "type": "string" } + ], "description": "Custom params passed to gradle build command" }, "interactive": { @@ -105,6 +110,7 @@ "sync": { "type": "boolean", "description": "Syncs npm dependencies to `package.json` (for React Native autolink).", + "x-deprecated": "Add sync-deps to dependsOn for this target in project.json instead", "default": true }, "resetCache": { diff --git a/docs/generated/packages/react-native/executors/run-ios.json b/docs/generated/packages/react-native/executors/run-ios.json index 58f619d5169ac..387f44a2b52c1 100644 --- a/docs/generated/packages/react-native/executors/run-ios.json +++ b/docs/generated/packages/react-native/executors/run-ios.json @@ -13,11 +13,7 @@ "presets": [ { "name": "Run iOS on a simulator", "keys": ["simulator"] }, { "name": "Run iOS on a device", "keys": ["device"] }, - { "name": "Run iOS on a device with udid", "keys": ["udid"] }, - { - "name": "Run `pod install` before building iOS app", - "keys": ["install"] - } + { "name": "Run iOS on a device with udid", "keys": ["udid"] } ], "properties": { "xcodeConfiguration": { @@ -81,17 +77,22 @@ "description": "Explicitly select which scheme and configuration to use before running a build" }, "extraParams": { - "type": "string", + "oneOf": [ + { "type": "array", "items": { "type": "string" } }, + { "type": "string" } + ], "description": "Custom params that will be passed to xcodebuild command." }, "install": { "type": "boolean", "description": "Runs `pod install` for native modules before building iOS app.", - "default": true + "default": true, + "x-deprecated": "Add `pod-install` to dependsOn for this target in project.json instead." }, "sync": { "type": "boolean", "description": "Syncs npm dependencies to `package.json` (for React Native autolink).", + "x-deprecated": "Add `sync-deps` to dependsOn for this target in project.json instead.", "default": true }, "resetCache": { diff --git a/docs/shared/packages/expo/expo-plugin.md b/docs/shared/packages/expo/expo-plugin.md index 2bd3082683376..b7b9e37ba971a 100644 --- a/docs/shared/packages/expo/expo-plugin.md +++ b/docs/shared/packages/expo/expo-plugin.md @@ -50,7 +50,7 @@ nx start my-app To generate a new library run: ```shell -npx nx g @nx/react-native:lib your-lib-name +npx nx g @nx/expo:lib your-lib-name ``` ### Generating Components @@ -58,7 +58,7 @@ npx nx g @nx/react-native:lib your-lib-name To generate a new component inside library run: ```shell -npx nx g @nx/react-native:component your-component-name --project=your-lib-name --export +npx nx g @nx/expo:component your-component-name --project=your-lib-name --export ``` Replace `your-lib-name` with the app's name as defined in your `tsconfig.base.json` file or the `name` property of your `package.json` @@ -247,6 +247,28 @@ To check the details of your build status, run: nx build-list ``` +### Submit an EAS Build + +EAS Submit is a hosted service for uploading and submitting your app binaries to the app stores. Since it's a hosted service, you can submit your app to both stores as long as you can run EAS CLI on your machine. + +To submit an EAS build: + +```shell +nx submit +``` + +### Update an EAS Build + +EAS Update is a hosted service that serves updates for projects using the `expo-updates` library. + +EAS Update makes fixing small bugs and pushing quick fixes a snap in between app store submissions. It accomplishes this by allowing an end-user's app to swap out the non-native parts of their app (for example, JS, styling, and image changes) with a new update that contains bug fixes and other updates. + +To update an EAS build: + +```shell +nx update +``` + ### Testing Projects You can run unit tests with: @@ -269,6 +291,8 @@ Below table is a map between expo commands and Nx commands: | `expo install` | `nx install ` | | `eas build` | `nx build ` | | `eas build:list` | `nx build-list ` | +| `eas update` | `nx update ` | +| `eas submit` | `nx submit ` | ## More Documentation diff --git a/e2e/expo/src/expo.test.ts b/e2e/expo/src/expo.test.ts index 139fb29b112ff..28ef3fe4f704d 100644 --- a/e2e/expo/src/expo.test.ts +++ b/e2e/expo/src/expo.test.ts @@ -92,15 +92,15 @@ describe('expo', () => { expect(prebuildResult.combinedOutput).toContain('Config synced'); }); - // TODO(emily): expo-cli always fetches the latest version of react native - // re-enable it when expo-cli is fixed + // TODO(emily): this test failed due to version conflict with conflict with @config-plugins/detox + // https://github.com/expo/config-plugins/issues/178 xit('should install', async () => { // run install command const installResults = await runCLIAsync( - `install ${appName} --no-interactive --check` + `install ${appName} --no-interactive` ); expect(installResults.combinedOutput).toContain( - 'Dependencies are up to date' + 'Successfully ran target install' ); }); diff --git a/package.json b/package.json index 81f933530cfdb..49bf7207ac268 100644 --- a/package.json +++ b/package.json @@ -208,7 +208,8 @@ "magic-string": "~0.26.2", "markdown-factory": "^0.0.6", "memfs": "^3.0.1", - "metro-resolver": "^0.74.1", + "metro-config": "0.76.7", + "metro-resolver": "0.76.7", "mini-css-extract-plugin": "~2.4.7", "minimatch": "3.0.5", "next-sitemap": "^3.1.10", diff --git a/packages/detox/src/generators/application/application.spec.ts b/packages/detox/src/generators/application/application.spec.ts index ef4ff058914a5..08e5f556b14ff 100644 --- a/packages/detox/src/generators/application/application.spec.ts +++ b/packages/detox/src/generators/application/application.spec.ts @@ -342,12 +342,6 @@ describe('detox application generator', () => { 'cd ../../../my-dir/my-app/android && ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug', type: 'android.apk', }, - 'android.eas': { - binaryPath: '../../../my-dir/my-app/dist/MyDirMyApp.apk', - build: - 'npx nx run my-dir-my-app:download --platform android --distribution simulator --output=../../../my-dir/my-app/dist/', - type: 'android.apk', - }, 'android.local': { binaryPath: '../../../my-dir/my-app/dist/MyDirMyApp.apk', build: @@ -368,12 +362,6 @@ describe('detox application generator', () => { "cd ../../../my-dir/my-app/ios && xcodebuild -workspace MyDirMyApp.xcworkspace -scheme MyDirMyApp -configuration Debug -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 14' -derivedDataPath ./build -quiet", type: 'ios.app', }, - 'ios.eas': { - binaryPath: '../../../my-dir/my-app/dist/MyDirMyApp.app', - build: - 'npx nx run my-dir-my-app:download --platform ios --distribution simulator --output=../../../my-dir/my-app/dist/', - type: 'ios.app', - }, 'ios.local': { binaryPath: '../../../my-dir/my-app/dist/MyDirMyApp.app', build: diff --git a/packages/detox/src/generators/application/files/app/.detoxrc.json.template b/packages/detox/src/generators/application/files/app/.detoxrc.json.template index 32023673a5f2e..622d7e779da76 100644 --- a/packages/detox/src/generators/application/files/app/.detoxrc.json.template +++ b/packages/detox/src/generators/application/files/app/.detoxrc.json.template @@ -20,11 +20,6 @@ "binaryPath": "<%= offsetFromRoot %><%= appRoot %>/ios/build/Build/Products/Release-iphonesimulator/<%= appClassName %>.app" }, <% if (framework === 'expo') { %> - "ios.eas": { - "type": "ios.app", - "build": "<%= exec %> nx run <%= appFileName %>:download --platform ios --distribution simulator --output=<%= offsetFromRoot %><%= appRoot %>/dist/", - "binaryPath": "<%= offsetFromRoot %><%= appRoot %>/dist/<%= appExpoName %>.app" - }, "ios.local": { "type": "ios.app", "build": "<%= exec %> nx run <%= appFileName %>:build --platform ios --profile preview --wait --local --no-interactive --output=<%= offsetFromRoot %><%= appRoot %>/dist/<%= appExpoName %>.tar.gz", @@ -42,11 +37,6 @@ "binaryPath": "<%= offsetFromRoot %><%= appRoot %>/android/app/build/outputs/apk/release/app-release.apk" }, <% if (framework === 'expo') { %> - "android.eas": { - "type": "android.apk", - "build": "<%= exec %> nx run <%= appFileName %>:download --platform android --distribution simulator --output=<%= offsetFromRoot %><%= appRoot %>/dist/", - "binaryPath": "<%= offsetFromRoot %><%= appRoot %>/dist/<%= appExpoName %>.apk" - }, "android.local": { "type": "android.apk", "build": "<%= exec %> nx run <%= appFileName %>:build --platform android --profile preview --wait --local --no-interactive --output=<%= offsetFromRoot %><%= appRoot %>/dist/<%= appExpoName %>.apk", @@ -78,10 +68,6 @@ "app": "ios.debug" }, <% if (framework === 'expo') { %> - "ios.sim.eas": { - "device": "simulator", - "app": "ios.eas" - }, "ios.sim.local": { "device": "simulator", "app": "ios.local" @@ -96,10 +82,6 @@ "app": "android.debug" }, <% if (framework === 'expo') { %> - "android.emu.eas": { - "device": "emulator", - "app": "android.eas" - }, "android.emu.local": { "device": "emulator", "app": "android.local" diff --git a/packages/detox/src/generators/application/lib/get-targets.spec.ts b/packages/detox/src/generators/application/lib/get-targets.spec.ts index 4ffddd609da9a..07730d357bf83 100644 --- a/packages/detox/src/generators/application/lib/get-targets.spec.ts +++ b/packages/detox/src/generators/application/lib/get-targets.spec.ts @@ -4,14 +4,10 @@ describe('getTargets', () => { it('should return ios test target for expo projects', () => { expect(expoTestTarget('ios.sim', 'test')).toEqual({ options: { - detoxConfiguration: 'ios.sim.eas', + detoxConfiguration: 'ios.sim.local', buildTarget: 'test:build-ios', }, configurations: { - local: { - detoxConfiguration: 'ios.sim.local', - buildTarget: 'test:build-ios:local', - }, bare: { detoxConfiguration: 'ios.sim.debug', buildTarget: 'test:build-ios:bare', @@ -27,12 +23,9 @@ describe('getTargets', () => { it('should return ios build target for expo projects', () => { expect(expoBuildTarget('ios.sim')).toEqual({ options: { - detoxConfiguration: 'ios.sim.eas', + detoxConfiguration: 'ios.sim.local', }, configurations: { - local: { - detoxConfiguration: 'ios.sim.local', - }, bare: { detoxConfiguration: 'ios.sim.debug', }, diff --git a/packages/detox/src/generators/application/lib/get-targets.ts b/packages/detox/src/generators/application/lib/get-targets.ts index b2bee0d29063d..b1cbfc4aa0f00 100644 --- a/packages/detox/src/generators/application/lib/get-targets.ts +++ b/packages/detox/src/generators/application/lib/get-targets.ts @@ -14,12 +14,9 @@ export function reactNativeBuildTarget(platform: 'ios.sim' | 'android.emu') { export function expoBuildTarget(platform: 'ios.sim' | 'android.emu') { return { options: { - detoxConfiguration: `${platform}.eas`, + detoxConfiguration: `${platform}.local`, }, configurations: { - local: { - detoxConfiguration: `${platform}.local`, - }, bare: { detoxConfiguration: `${platform}.debug`, }, @@ -58,14 +55,10 @@ export function expoTestTarget( return { options: { - detoxConfiguration: `${platform}.eas`, + detoxConfiguration: `${platform}.local`, buildTarget: `${e2eName}:build-${buildPlatform}`, }, configurations: { - local: { - detoxConfiguration: `${platform}.local`, - buildTarget: `${e2eName}:build-${buildPlatform}:local`, - }, bare: { detoxConfiguration: `${platform}.debug`, buildTarget: `${e2eName}:build-${buildPlatform}:bare`, diff --git a/packages/expo/migrations.json b/packages/expo/migrations.json index 1dfe135764424..14d37ee0b642b 100644 --- a/packages/expo/migrations.json +++ b/packages/expo/migrations.json @@ -65,6 +65,18 @@ "cli": "nx", "description": "Add app.json for detox", "factory": "./src/migrations/update-16-1-4/add-detox-app-json" + }, + "update-16-6-0-add-dependsOn": { + "cli": "nx", + "version": "16.6.0-beta.0", + "description": "Add dependsOn like ensure-symlink or sync-deps to targets", + "implementation": "./src/migrations/update-16-6-0/add-depends-on" + }, + "update-16-6-0-update-metro-config": { + "cli": "nx", + "version": "16.6.0-beta.0", + "description": "Update metro.config.js to use the new metro config format", + "implementation": "./src/migrations/update-16-6-0/update-metro-config" } }, "packageJsonUpdates": { @@ -855,6 +867,67 @@ "alwaysAddToPackageJson": false } } + }, + "16.6.0": { + "version": "16.6.0-beta.0", + "packages": { + "expo": { + "version": "^49.0.3", + "alwaysAddToPackageJson": false + }, + "@expo/metro-config": { + "version": "~0.10.6", + "alwaysAddToPackageJson": false + }, + "expo-splash-screen": { + "version": "~0.20.4", + "alwaysAddToPackageJson": false + }, + "expo-status-bar": { + "version": "~1.6.0", + "alwaysAddToPackageJson": false + }, + "@expo/cli": { + "version": "~0.10.10", + "alwaysAddToPackageJson": false + }, + "eas-cli": { + "version": "~3.15.0", + "alwaysAddToPackageJson": false + }, + "babel-preset-expo": { + "version": "~9.5.0", + "alwaysAddToPackageJson": false + }, + "jest-expo": { + "version": "~49.0.0", + "alwaysAddToPackageJson": false + }, + "metro-resolver": { + "version": "0.76.7", + "alwaysAddToPackageJson": false + }, + "metro": { + "version": "0.76.7", + "alwaysAddToPackageJson": false + }, + "react-native": { + "version": "0.72.3", + "alwaysAddToPackageJson": false + }, + "@types/react-native": { + "version": "0.72.2", + "alwaysAddToPackageJson": false + }, + "react-native-web": { + "version": "~0.19.6", + "alwaysAddToPackageJson": false + }, + "react-native-svg": { + "version": "13.9.0", + "alwaysAddToPackageJson": false + } + } } } } diff --git a/packages/expo/package.json b/packages/expo/package.json index 50ac01e23aace..f39394ca2ffe7 100644 --- a/packages/expo/package.json +++ b/packages/expo/package.json @@ -29,7 +29,8 @@ "chalk": "^4.1.0", "enhanced-resolve": "^5.8.3", "fs-extra": "^11.1.0", - "metro-resolver": "^0.74.1", + "metro-config": "0.76.7", + "metro-resolver": "0.76.7", "node-fetch": "^2.6.7", "tar-fs": "^2.1.1", "tsconfig-paths": "^4.1.2", @@ -43,7 +44,9 @@ "@nx/webpack": "file:../webpack" }, "peerDependencies": { - "expo": "^48.0.19" + "expo": ">= 49.0.0", + "@expo/cli": ">= 0.10.0", + "eas-cli": ">= 3.15.0" }, "builders": "./executors.json", "ng-update": { diff --git a/packages/expo/plugins/with-nx-metro.ts b/packages/expo/plugins/with-nx-metro.ts index 81ac08570064c..14f4171322c51 100644 --- a/packages/expo/plugins/with-nx-metro.ts +++ b/packages/expo/plugins/with-nx-metro.ts @@ -1,4 +1,6 @@ import { workspaceLayout, workspaceRoot } from '@nx/devkit'; +import { mergeConfig } from 'metro-config'; +import type { MetroConfig } from 'metro-config'; import { join } from 'path'; import { existsSync } from 'fs-extra'; @@ -7,35 +9,39 @@ import { getResolveRequest } from './metro-resolver'; interface WithNxOptions { debug?: boolean; extensions?: string[]; + /** + * @deprecated TODO(v17) in the metro.config.js, pass in to the getDefaultConfig instead: getDefaultConfig(__dirname) + */ projectRoot?: string; watchFolders?: string[]; } -export function withNxMetro(config: any, opts: WithNxOptions = {}) { +export async function withNxMetro( + userConfig: MetroConfig, + opts: WithNxOptions = {} +) { const extensions = ['', 'ts', 'tsx', 'js', 'jsx', 'json']; if (opts.debug) process.env.NX_REACT_NATIVE_DEBUG = 'true'; if (opts.extensions) extensions.push(...opts.extensions); - config.projectRoot = opts.projectRoot || workspaceRoot; - - // Add support for paths specified by tsconfig - config.resolver = { - ...config.resolver, - resolveRequest: getResolveRequest(extensions), - }; - - let watchFolders = config.watchFolders || []; - watchFolders = watchFolders.concat([ + let watchFolders = [ join(workspaceRoot, 'node_modules'), join(workspaceRoot, workspaceLayout().libsDir), join(workspaceRoot, 'packages'), - ]); + join(workspaceRoot, '.storybook'), + ]; if (opts.watchFolders?.length) { watchFolders = watchFolders.concat(opts.watchFolders); } watchFolders = watchFolders.filter((folder) => existsSync(folder)); - config.watchFolders = watchFolders; - return config; + const nxConfig: MetroConfig = { + resolver: { + resolveRequest: getResolveRequest(extensions), + }, + watchFolders, + }; + + return mergeConfig(userConfig, nxConfig); } diff --git a/packages/expo/plugins/with-nx-webpack.ts b/packages/expo/plugins/with-nx-webpack.ts index 01e71c633afad..814fb625bed65 100644 --- a/packages/expo/plugins/with-nx-webpack.ts +++ b/packages/expo/plugins/with-nx-webpack.ts @@ -2,7 +2,7 @@ import { TsconfigPathsPlugin } from 'tsconfig-paths-webpack-plugin'; import { resolve } from 'path'; /** - * @deprecated use bundler: 'metro' instead, will be removed in 16.0.0 + * @deprecated TODO(v17) use bundler: 'metro' instead, will be removed in 16.0.0 * This function add additional rules to expo's webpack config to make expo web working */ export async function withNxWebpack(config) { diff --git a/packages/expo/src/executors/build-list/build-list.impl.ts b/packages/expo/src/executors/build-list/build-list.impl.ts index 65a90bffa5003..1f2829a6f0ce7 100644 --- a/packages/expo/src/executors/build-list/build-list.impl.ts +++ b/packages/expo/src/executors/build-list/build-list.impl.ts @@ -1,5 +1,5 @@ import { ExecutorContext, logger, names } from '@nx/devkit'; -import { join } from 'path'; +import { resolve as pathResolve } from 'path'; import { ChildProcess, fork } from 'child_process'; import { ensureNodeModulesSymlink } from '../../utils/ensure-node-modules-symlink'; @@ -42,10 +42,10 @@ export function runCliBuildList( ): Promise { return new Promise((resolve, reject) => { childProcess = fork( - join(workspaceRoot, './node_modules/eas-cli/bin/run'), + require.resolve('eas-cli/bin/run'), ['build:list', ...createBuildListOptions(options)], { - cwd: join(workspaceRoot, projectRoot), + cwd: pathResolve(workspaceRoot, projectRoot), env: process.env, stdio: ['inherit', 'pipe', 'inherit', 'ipc'], // only stream stdout on child process } diff --git a/packages/expo/src/executors/build/build.impl.ts b/packages/expo/src/executors/build/build.impl.ts index fc89e7684c742..b67fbe68b5b5e 100644 --- a/packages/expo/src/executors/build/build.impl.ts +++ b/packages/expo/src/executors/build/build.impl.ts @@ -1,5 +1,5 @@ -import { ExecutorContext, names } from '@nx/devkit'; -import { join, normalize, sep } from 'path'; +import { ExecutorContext, names, output } from '@nx/devkit'; +import { normalize, sep, resolve as pathResolve, dirname } from 'path'; import { ChildProcess, fork } from 'child_process'; import { ensureNodeModulesSymlink } from '../../utils/ensure-node-modules-symlink'; @@ -20,21 +20,22 @@ export default async function* buildExecutor( ): AsyncGenerator { const projectRoot = context.projectsConfigurations.projects[context.projectName].root; - ensureNodeModulesSymlink(context.root, projectRoot); try { // remove the output app if it already existed if (options.local && options.output) { removeSync(options.output); + if (options.output.endsWith('.tar.gz')) { + // remove unzipped app if it already existed + removeSync(options.output.replace('.tar.gz', '.app')); + } } await runCliBuild(context.root, projectRoot, options); // unzip the build if it's a tar.gz if (options.local && options.output && options.output.endsWith('.tar.gz')) { - const directoryPath = normalize(options.output).split(sep); - directoryPath.pop(); - const outputDirectory = directoryPath.join(sep); + const outputDirectory = dirname(options.output); await unzipBuild(options.output, outputDirectory); } yield { success: true }; @@ -52,10 +53,10 @@ function runCliBuild( ) { return new Promise((resolve, reject) => { childProcess = fork( - join(workspaceRoot, './node_modules/eas-cli/bin/run'), + require.resolve('eas-cli/bin/run'), ['build', ...createBuildOptions(options)], { - cwd: join(workspaceRoot, projectRoot), + cwd: pathResolve(workspaceRoot, projectRoot), env: process.env, } ); diff --git a/packages/expo/src/executors/build/schema.json b/packages/expo/src/executors/build/schema.json index 64c399d6ccffa..2821cb7c2a29f 100644 --- a/packages/expo/src/executors/build/schema.json +++ b/packages/expo/src/executors/build/schema.json @@ -55,7 +55,8 @@ }, "output": { "type": "string", - "description": "Output path for local build" + "description": "Output path for local build", + "examples": ["../../dist/MyApp.tar.gz", "../../dist"] }, "wait": { "type": "boolean", diff --git a/packages/expo/src/executors/download/download.impl.ts b/packages/expo/src/executors/download/download.impl.ts index 28dc180b42758..cb21ed1ec15a6 100644 --- a/packages/expo/src/executors/download/download.impl.ts +++ b/packages/expo/src/executors/download/download.impl.ts @@ -28,6 +28,7 @@ export interface ReactNativeDownloadOutput { const streamPipeline = promisify(pipeline); /** + * @deprecated TODO(v17) this executor is to be removed in NX 17. It is no longer used. * This executor downloads the latest EAS build. * It calls the build list executor to list EAS builds with options passed in. */ diff --git a/packages/expo/src/executors/export/export.impl.ts b/packages/expo/src/executors/export/export.impl.ts index 6aecc5e28ba69..242012ce9a467 100644 --- a/packages/expo/src/executors/export/export.impl.ts +++ b/packages/expo/src/executors/export/export.impl.ts @@ -1,8 +1,7 @@ import { ExecutorContext, names } from '@nx/devkit'; import { ChildProcess, fork } from 'child_process'; -import { join } from 'path'; +import { resolve as pathResolve } from 'path'; -import { ensureNodeModulesSymlink } from '../../utils/ensure-node-modules-symlink'; import { ExportExecutorSchema } from './schema'; export interface ExpoExportOutput { @@ -17,7 +16,6 @@ export default async function* exportExecutor( ): AsyncGenerator { const projectRoot = context.projectsConfigurations.projects[context.projectName].root; - ensureNodeModulesSymlink(context.root, projectRoot); try { await exportAsync(context.root, projectRoot, options); @@ -39,13 +37,13 @@ function exportAsync( ): Promise { return new Promise((resolve, reject) => { childProcess = fork( - join(workspaceRoot, './node_modules/@expo/cli/build/bin/cli'), + require.resolve('@expo/cli/build/bin/cli'), [ `export${options.bundler === 'webpack' ? ':web' : ''}`, '.', ...createExportOptions(options), ], - { cwd: join(workspaceRoot, projectRoot), env: process.env } + { cwd: pathResolve(workspaceRoot, projectRoot), env: process.env } ); // Ensure the child process is killed when the parent exits diff --git a/packages/expo/src/executors/install/install.impl.ts b/packages/expo/src/executors/install/install.impl.ts index 751219597718e..ad1053ad0854b 100644 --- a/packages/expo/src/executors/install/install.impl.ts +++ b/packages/expo/src/executors/install/install.impl.ts @@ -1,6 +1,5 @@ import { ExecutorContext, names } from '@nx/devkit'; import { ChildProcess, fork } from 'child_process'; -import { join } from 'path'; import { ensureNodeModulesSymlink } from '../../utils/ensure-node-modules-symlink'; import { ExpoInstallOptions } from './schema'; @@ -38,7 +37,7 @@ export function installAsync( ): Promise { return new Promise((resolve, reject) => { childProcess = fork( - join(workspaceRoot, './node_modules/@expo/cli/build/bin/cli'), + require.resolve('@expo/cli/build/bin/cli'), ['install', ...createInstallOptions(options)], { cwd: workspaceRoot, env: process.env } ); diff --git a/packages/expo/src/executors/prebuild/prebuild.impl.ts b/packages/expo/src/executors/prebuild/prebuild.impl.ts index 2747473cc804e..05de40d8b7db7 100644 --- a/packages/expo/src/executors/prebuild/prebuild.impl.ts +++ b/packages/expo/src/executors/prebuild/prebuild.impl.ts @@ -27,7 +27,7 @@ export default async function* prebuildExecutor( if (options.install) { await installAsync(context.root, {}); if (options.platform === 'ios') { - await podInstall(join(context.root, projectRoot, 'ios')); + podInstall(join(context.root, projectRoot, 'ios')); } } @@ -48,7 +48,7 @@ export function prebuildAsync( ): Promise { return new Promise((resolve, reject) => { childProcess = fork( - join(workspaceRoot, './node_modules/@expo/cli/build/bin/cli'), + require.resolve('@expo/cli/build/bin/cli'), ['prebuild', ...createPrebuildOptions(options), '--no-install'], { cwd: join(workspaceRoot, projectRoot), env: process.env } ); diff --git a/packages/expo/src/executors/run/run.impl.ts b/packages/expo/src/executors/run/run.impl.ts index f2075f1e2c287..902af88770a40 100644 --- a/packages/expo/src/executors/run/run.impl.ts +++ b/packages/expo/src/executors/run/run.impl.ts @@ -1,5 +1,5 @@ import { ExecutorContext, names } from '@nx/devkit'; -import { join } from 'path'; +import { join, resolve as pathResolve } from 'path'; import { ChildProcess, fork } from 'child_process'; import { platform } from 'os'; import { existsSync } from 'fs-extra'; @@ -29,18 +29,6 @@ export default async function* runExecutor( } const projectRoot = context.projectsConfigurations.projects[context.projectName].root; - ensureNodeModulesSymlink(context.root, projectRoot); - if (options.sync) { - displayNewlyAddedDepsMessage( - context.projectName, - await syncDeps( - context.projectName, - projectRoot, - context.root, - context.projectGraph - ) - ); - } if (!existsSync(join(context.root, projectRoot, options.platform))) { await prebuildAsync(context.root, projectRoot, { @@ -53,7 +41,7 @@ export default async function* runExecutor( if (options.install) { await installAsync(context.root, {}); if (options.platform === 'ios') { - await podInstall(join(context.root, projectRoot, 'ios')); + podInstall(join(context.root, projectRoot, 'ios')); } } @@ -75,10 +63,11 @@ function runCliRun( ) { return new Promise((resolve, reject) => { childProcess = fork( - join(workspaceRoot, './node_modules/@expo/cli/build/bin/cli'), + require.resolve('@expo/cli/build/bin/cli'), ['run:' + options.platform, ...createRunOptions(options), '--no-install'], // pass in no-install to prevent node_modules install { - cwd: projectRoot, + cwd: pathResolve(workspaceRoot, projectRoot), + env: process.env, } ); diff --git a/packages/expo/src/executors/run/schema.d.ts b/packages/expo/src/executors/run/schema.d.ts index e1e6102dd0669..5cefa73aaad59 100644 --- a/packages/expo/src/executors/run/schema.d.ts +++ b/packages/expo/src/executors/run/schema.d.ts @@ -6,6 +6,9 @@ export interface ExpoRunOptions { // nx options platform: 'ios' | 'android'; + /** + * @deprecated TODO(v17) Add sync-deps to dependsOn in project.json for this target instead + */ sync: boolean; // default is true install?: boolean; // default is true clean?: boolean; // default is false diff --git a/packages/expo/src/executors/run/schema.json b/packages/expo/src/executors/run/schema.json index 3f96d584863ac..fe862b55fd9e9 100644 --- a/packages/expo/src/executors/run/schema.json +++ b/packages/expo/src/executors/run/schema.json @@ -39,6 +39,7 @@ "type": "boolean", "description": "Syncs npm dependencies to package.json (for React Native autolink).", "default": true, + "x-deprecated": "Add sync-deps to dependsOn in project.json for this target instead", "x-priority": "internal" }, "port": { diff --git a/packages/expo/src/executors/start/schema.d.ts b/packages/expo/src/executors/start/schema.d.ts index f172b4fce1ea2..1e7bd965abf68 100644 --- a/packages/expo/src/executors/start/schema.d.ts +++ b/packages/expo/src/executors/start/schema.d.ts @@ -20,6 +20,8 @@ export interface ExpoStartOptions { tunnel?: boolean; offline?: boolean; - // nx options + /** + * @deprecated TODO(v17) Add sync-deps to dependsOn in project.json for this target instead + */ sync?: boolean; // default is true } diff --git a/packages/expo/src/executors/start/schema.json b/packages/expo/src/executors/start/schema.json index 85a433da9e663..e74466325694c 100644 --- a/packages/expo/src/executors/start/schema.json +++ b/packages/expo/src/executors/start/schema.json @@ -91,6 +91,7 @@ "sync": { "type": "boolean", "description": "Syncs npm dependencies to package.json (for React Native autolink).", + "x-deprecated": "Add sync-deps to dependsOn in project.json for this target instead", "default": true } }, diff --git a/packages/expo/src/executors/start/start.impl.ts b/packages/expo/src/executors/start/start.impl.ts index 28ee17bc0628b..46ff86162eddf 100644 --- a/packages/expo/src/executors/start/start.impl.ts +++ b/packages/expo/src/executors/start/start.impl.ts @@ -1,14 +1,9 @@ import * as chalk from 'chalk'; import { ExecutorContext, logger, names } from '@nx/devkit'; import { ChildProcess, fork } from 'child_process'; -import { join } from 'path'; +import { resolve as pathResolve } from 'path'; -import { ensureNodeModulesSymlink } from '../../utils/ensure-node-modules-symlink'; import { ExpoStartOptions } from './schema'; -import { - displayNewlyAddedDepsMessage, - syncDeps, -} from '../sync-deps/sync-deps.impl'; export interface ExpoStartOutput { baseUrl?: string; @@ -23,18 +18,6 @@ export default async function* startExecutor( ): AsyncGenerator { const projectRoot = context.projectsConfigurations.projects[context.projectName].root; - ensureNodeModulesSymlink(context.root, projectRoot); - if (options.sync) { - displayNewlyAddedDepsMessage( - context.projectName, - await syncDeps( - context.projectName, - projectRoot, - context.root, - context.projectGraph - ) - ); - } try { const baseUrl = `http://localhost:${options.port}`; @@ -60,9 +43,9 @@ function startAsync( ): Promise { return new Promise((resolve, reject) => { childProcess = fork( - join(workspaceRoot, './node_modules/@expo/cli/build/bin/cli'), + require.resolve('@expo/cli/build/bin/cli'), ['start', ...createStartOptions(options)], - { cwd: join(workspaceRoot, projectRoot), env: process.env } + { cwd: pathResolve(workspaceRoot, projectRoot), env: process.env } ); // Ensure the child process is killed when the parent exits diff --git a/packages/expo/src/executors/submit/submit.impl.ts b/packages/expo/src/executors/submit/submit.impl.ts index d1bcbd7317ddf..a3d6c8b3f5822 100644 --- a/packages/expo/src/executors/submit/submit.impl.ts +++ b/packages/expo/src/executors/submit/submit.impl.ts @@ -1,9 +1,7 @@ import { ExecutorContext, names } from '@nx/devkit'; -import { join } from 'path'; +import { resolve as pathResolve } from 'path'; import { ChildProcess, fork } from 'child_process'; -import { ensureNodeModulesSymlink } from '../../utils/ensure-node-modules-symlink'; - import { SubmitExecutorSchema } from './schema'; export interface ReactNativeSubmitOutput { @@ -18,7 +16,6 @@ export default async function* submitExecutor( ): AsyncGenerator { const projectRoot = context.projectsConfigurations.projects[context.projectName].root; - ensureNodeModulesSymlink(context.root, projectRoot); try { await runCliSubmit(context.root, projectRoot, options); @@ -38,10 +35,10 @@ function runCliSubmit( ) { return new Promise((resolve, reject) => { childProcess = fork( - join(workspaceRoot, './node_modules/eas-cli/bin/run'), + require.resolve('eas-cli/bin/run'), ['submit', ...createSubmitOptions(options)], { - cwd: join(workspaceRoot, projectRoot), + cwd: pathResolve(workspaceRoot, projectRoot), env: process.env, } ); diff --git a/packages/expo/src/executors/update/update.impl.ts b/packages/expo/src/executors/update/update.impl.ts index 81c04652dccd3..99e828dbfaa45 100644 --- a/packages/expo/src/executors/update/update.impl.ts +++ b/packages/expo/src/executors/update/update.impl.ts @@ -1,5 +1,5 @@ import { ExecutorContext, names } from '@nx/devkit'; -import { join } from 'path'; +import { resolve as pathResolve } from 'path'; import { ChildProcess, fork } from 'child_process'; import { ensureNodeModulesSymlink } from '../../utils/ensure-node-modules-symlink'; @@ -53,9 +53,9 @@ function runCliUpdate( ) { return new Promise((resolve, reject) => { childProcess = fork( - join(workspaceRoot, './node_modules/eas-cli/bin/run'), + require.resolve('eas-cli/bin/run'), ['update', ...createUpdateOptions(options)], - { cwd: join(workspaceRoot, projectRoot), env: process.env } + { cwd: pathResolve(workspaceRoot, projectRoot), env: process.env } ); // Ensure the child process is killed when the parent exits diff --git a/packages/expo/src/generators/application/application.spec.ts b/packages/expo/src/generators/application/application.spec.ts index 709303c254997..2ce626375223c 100644 --- a/packages/expo/src/generators/application/application.spec.ts +++ b/packages/expo/src/generators/application/application.spec.ts @@ -121,12 +121,6 @@ describe('app', () => { 'cd ../../../apps/my-dir/my-app/android && ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug', type: 'android.apk', }, - 'android.eas': { - binaryPath: '../../../apps/my-dir/my-app/dist/MyApp.apk', - build: - 'npx nx run my-app:download --platform android --distribution simulator --output=../../../apps/my-dir/my-app/dist/', - type: 'android.apk', - }, 'android.local': { binaryPath: '../../../apps/my-dir/my-app/dist/MyApp.apk', build: @@ -147,12 +141,6 @@ describe('app', () => { "cd ../../../apps/my-dir/my-app/ios && xcodebuild -workspace MyApp.xcworkspace -scheme MyApp -configuration Debug -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 14' -derivedDataPath ./build -quiet", type: 'ios.app', }, - 'ios.eas': { - binaryPath: '../../../apps/my-dir/my-app/dist/MyApp.app', - build: - 'npx nx run my-app:download --platform ios --distribution simulator --output=../../../apps/my-dir/my-app/dist/', - type: 'ios.app', - }, 'ios.local': { binaryPath: '../../../apps/my-dir/my-app/dist/MyApp.app', build: @@ -196,12 +184,6 @@ describe('app', () => { 'cd ../../apps/my-app/android && ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug', type: 'android.apk', }, - 'android.eas': { - binaryPath: '../../apps/my-app/dist/MyApp.apk', - build: - 'npx nx run my-app:download --platform android --distribution simulator --output=../../apps/my-app/dist/', - type: 'android.apk', - }, 'android.local': { binaryPath: '../../apps/my-app/dist/MyApp.apk', build: @@ -222,12 +204,6 @@ describe('app', () => { "cd ../../apps/my-app/ios && xcodebuild -workspace MyApp.xcworkspace -scheme MyApp -configuration Debug -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 14' -derivedDataPath ./build -quiet", type: 'ios.app', }, - 'ios.eas': { - binaryPath: '../../apps/my-app/dist/MyApp.app', - build: - 'npx nx run my-app:download --platform ios --distribution simulator --output=../../apps/my-app/dist/', - type: 'ios.app', - }, 'ios.local': { binaryPath: '../../apps/my-app/dist/MyApp.app', build: @@ -272,12 +248,6 @@ describe('app', () => { 'cd ../../apps/my-app/android && ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug', type: 'android.apk', }, - 'android.eas': { - binaryPath: '../../apps/my-app/dist/myappname.apk', - build: - 'npx nx run my-app:download --platform android --distribution simulator --output=../../apps/my-app/dist/', - type: 'android.apk', - }, 'android.local': { binaryPath: '../../apps/my-app/dist/myappname.apk', build: @@ -298,12 +268,6 @@ describe('app', () => { "cd ../../apps/my-app/ios && xcodebuild -workspace MyApp.xcworkspace -scheme MyApp -configuration Debug -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 14' -derivedDataPath ./build -quiet", type: 'ios.app', }, - 'ios.eas': { - binaryPath: '../../apps/my-app/dist/myappname.app', - build: - 'npx nx run my-app:download --platform ios --distribution simulator --output=../../apps/my-app/dist/', - type: 'ios.app', - }, 'ios.local': { binaryPath: '../../apps/my-app/dist/myappname.app', build: diff --git a/packages/expo/src/generators/application/files/metro.config.js.template b/packages/expo/src/generators/application/files/metro.config.js.template index 792f11624b5d9..5b3d161a95497 100644 --- a/packages/expo/src/generators/application/files/metro.config.js.template +++ b/packages/expo/src/generators/application/files/metro.config.js.template @@ -1,25 +1,37 @@ const { withNxMetro } = require('@nx/expo'); const { getDefaultConfig } = require('@expo/metro-config'); +const { mergeConfig } = require('metro-config'); +const exclusionList = require('metro-config/src/defaults/exclusionList'); const defaultConfig = getDefaultConfig(__dirname); +const { assetExts, sourceExts } = defaultConfig.resolver; -module.exports = (async () => { - defaultConfig.transformer.babelTransformerPath = require.resolve( - 'react-native-svg-transformer' - ); - defaultConfig.resolver.assetExts = defaultConfig.resolver.assetExts.filter( - (ext) => ext !== 'svg' - ); - defaultConfig.resolver.sourceExts.push('svg'); - return withNxMetro(defaultConfig, { - // Change this to true to see debugging info. - // Useful if you have issues resolving modules - debug: false, - // all the file extensions used for imports other than 'ts', 'tsx', 'js', 'jsx' - extensions: [], - // the project root to start the metro server - projectRoot: __dirname, - // Specify any additional (to projectRoot) watch folders, this is used to know which files to watch - watchFolders: [] - }); -})(); +/** + * Metro configuration + * https://facebook.github.io/metro/docs/configuration + * + * @type {import('metro-config').MetroConfig} + */ +const customConfig = { + transformer: { + babelTransformerPath: require.resolve('react-native-svg-transformer'), + }, + resolver: { + assetExts: assetExts.filter((ext) => ext !== 'svg'), + sourceExts: [...sourceExts, 'svg'], + blockList: exclusionList([/^(?!.*node_modules).*\/dist\/.*/]), + unstable_enableSymlinks: true, + unstable_enablePackageExports: true, + }, +}; + + +module.exports = withNxMetro(mergeConfig(defaultConfig, customConfig), { + // Change this to true to see debugging info. + // Useful if you have issues resolving modules + debug: false, + // all the file extensions used for imports other than 'ts', 'tsx', 'js', 'jsx', 'json' + extensions: [], + // Specify folders to watch, in addition to Nx defaults (workspace libraries and node_modules) + watchFolders: [], +}); diff --git a/packages/expo/src/generators/application/files/package.json.template b/packages/expo/src/generators/application/files/package.json.template index 95287ac2bafb0..07bb68718ee62 100644 --- a/packages/expo/src/generators/application/files/package.json.template +++ b/packages/expo/src/generators/application/files/package.json.template @@ -5,6 +5,7 @@ "dependencies": { "@testing-library/jest-native": "*", "@testing-library/react-native": "*", + "metro-config": "*", "react-native": "*", "expo": "*", "react-native-svg": "*", diff --git a/packages/expo/src/generators/application/lib/add-project.ts b/packages/expo/src/generators/application/lib/add-project.ts index f158ab67992ee..d93911b7b9a4f 100644 --- a/packages/expo/src/generators/application/lib/add-project.ts +++ b/packages/expo/src/generators/application/lib/add-project.ts @@ -29,6 +29,7 @@ function getTargets(options: NormalizedSchema) { architect.start = { executor: '@nx/expo:start', + dependsOn: ['ensure-symlink', 'sync-deps'], options: { port: 8081, }, @@ -43,6 +44,7 @@ function getTargets(options: NormalizedSchema) { architect['run-ios'] = { executor: '@nx/expo:run', + dependsOn: ['ensure-symlink', 'sync-deps'], options: { platform: 'ios', }, @@ -50,6 +52,7 @@ function getTargets(options: NormalizedSchema) { architect['run-android'] = { executor: '@nx/expo:run', + dependsOn: ['ensure-symlink', 'sync-deps'], options: { platform: 'android', }, @@ -70,6 +73,9 @@ function getTargets(options: NormalizedSchema) { options: {}, }; + /** + * @deprecated TODO(v17) this executor is no longer used, to be removed in v17 + */ architect['download'] = { executor: '@nx/expo:download', options: { @@ -89,6 +95,7 @@ function getTargets(options: NormalizedSchema) { architect['prebuild'] = { executor: '@nx/expo:prebuild', + dependsOn: ['ensure-symlink', 'sync-deps'], options: {}, }; @@ -104,6 +111,7 @@ function getTargets(options: NormalizedSchema) { architect['export'] = { executor: '@nx/expo:export', + dependsOn: ['ensure-symlink', 'sync-deps'], options: { platform: 'all', outputDir: `${offsetFromRoot(options.appProjectRoot)}dist/${ diff --git a/packages/expo/src/migrations/update-16-6-0/add-depends-on.ts b/packages/expo/src/migrations/update-16-6-0/add-depends-on.ts new file mode 100644 index 0000000000000..3b826e5913081 --- /dev/null +++ b/packages/expo/src/migrations/update-16-6-0/add-depends-on.ts @@ -0,0 +1,21 @@ +import { Tree, getProjects, updateProjectConfiguration } from '@nx/devkit'; + +/** + * This migration adds dependsOn to project.json. + * + */ +export default async function update(tree: Tree) { + const projects = getProjects(tree); + + for (const [name, config] of projects.entries()) { + if (config.targets?.['start']?.executor === '@nx/expo:start') { + config.targets['start'].dependsOn = ['ensure-symlink', 'sync-deps']; + config.targets['run-ios'].dependsOn = ['ensure-symlink', 'sync-deps']; + config.targets['run-android'].dependsOn = ['ensure-symlink', 'sync-deps']; + config.targets['prebuild'].dependsOn = ['ensure-symlink', 'sync-deps']; + config.targets['export'].dependsOn = ['ensure-symlink', 'sync-deps']; + + updateProjectConfiguration(tree, name, config); + } + } +} diff --git a/packages/expo/src/migrations/update-16-6-0/update-metro-config.ts b/packages/expo/src/migrations/update-16-6-0/update-metro-config.ts new file mode 100644 index 0000000000000..31fee35fe5628 --- /dev/null +++ b/packages/expo/src/migrations/update-16-6-0/update-metro-config.ts @@ -0,0 +1,73 @@ +import { Tree, getProjects } from '@nx/devkit'; +import { join } from 'path'; + +/** + * This migration updates metro.config.js to export config as a default. + * + */ +export default async function update(tree: Tree) { + const projects = getProjects(tree); + + for (const [_, config] of projects.entries()) { + if (config.targets?.['start']?.executor === '@nx/expo:start') { + if (tree.exists(join(config.root, 'metro.config.js'))) { + const oldConfig = tree + .read(join(config.root, 'metro.config.js')) + .toString(); + tree.write( + join(config.root, 'metro-v71.config.js'), + oldConfigComment + oldConfig + ); + tree.write(join(config.root, 'metro.config.js'), content); + } + } + } +} + +const oldConfigComment = `/** + * Old custom configuration for React Native v0.71. + * From @react-native/metro-config 0.72.1, it is no longer necessary to use a config function to access the complete default config. + * Please port your custom configuration to metro.config.js. + * Please see https://docs.expo.dev/guides/customizing-metro/ to learn about configuration. + */ +`; + +const content = ` +const { withNxMetro } = require('@nx/expo'); +const { getDefaultConfig } = require('@expo/metro-config'); +const { mergeConfig } = require('metro-config'); +const exclusionList = require('metro-config/src/defaults/exclusionList'); + +const defaultConfig = getDefaultConfig(__dirname); +const { assetExts, sourceExts } = defaultConfig.resolver; + +/** + * Metro configuration + * https://facebook.github.io/metro/docs/configuration + * + * @type {import('metro-config').MetroConfig} + */ +const customConfig = { + transformer: { + babelTransformerPath: require.resolve('react-native-svg-transformer'), + }, + resolver: { + assetExts: assetExts.filter((ext) => ext !== 'svg'), + sourceExts: [...sourceExts, 'svg'], + blockList: exclusionList([/^(?!.*node_modules).*\/dist\/.*/]), + unstable_enableSymlinks: true, + unstable_enablePackageExports: true, + }, +}; + + +module.exports = withNxMetro(mergeConfig(defaultConfig, customConfig), { + // Change this to true to see debugging info. + // Useful if you have issues resolving modules + debug: false, + // all the file extensions used for imports other than 'ts', 'tsx', 'js', 'jsx', 'json' + extensions: [], + // Specify folders to watch, in addition to Nx defaults (workspace libraries and node_modules) + watchFolders: [], +}); +`; diff --git a/packages/expo/src/utils/versions.ts b/packages/expo/src/utils/versions.ts index a494bd29a0ac2..0dcbd8136fc9c 100644 --- a/packages/expo/src/utils/versions.ts +++ b/packages/expo/src/utils/versions.ts @@ -1,28 +1,27 @@ export const nxVersion = require('../../package.json').version; -export const expoVersion = '48.0.19'; -export const expoMetroConfigVersion = '0.7.1'; -export const expoSplashScreenVersion = '~0.18.2'; -export const expoStatusBarVersion = '~1.4.4'; -export const expoUpdatesVersion = '~0.16.4'; -export const expoCliVersion = '~0.7.3'; // @expo/cli -export const easCliVersion = '~3.13.3'; -export const babelPresetExpoVersion = '~9.3.2'; +export const expoVersion = '49.0.3'; +export const expoMetroConfigVersion = '~0.10.6'; +export const expoSplashScreenVersion = '~0.20.4'; +export const expoStatusBarVersion = '~1.6.0'; +export const expoCliVersion = '~0.10.10'; // @expo/cli +export const easCliVersion = '~3.15.1'; +export const babelPresetExpoVersion = '~9.5.0'; export const reactVersion = '18.2.0'; export const reactDomVersion = '18.2.0'; export const reactTestRendererVersion = '18.2.0'; export const typesReactVersion = '18.0.28'; -export const reactNativeVersion = '0.71.8'; -export const typesReactNativeVersion = '0.71.7'; -export const reactNativeWebVersion = '~0.18.12'; +export const reactNativeVersion = '0.72.3'; +export const typesReactNativeVersion = '0.72.2'; +export const reactNativeWebVersion = '~0.19.6'; export const reactNativeSvgTransformerVersion = '1.0.0'; -export const reactNativeSvgVersion = '13.4.0'; +export const reactNativeSvgVersion = '13.9.0'; -export const metroVersion = '0.74.1'; +export const metroVersion = '0.76.7'; export const testingLibraryReactNativeVersion = '12.1.2'; export const testingLibraryJestNativeVersion = '5.4.2'; -export const jestExpoVersion = '~48.0.2'; +export const jestExpoVersion = '~49.0.0'; diff --git a/packages/react-native/migrations.json b/packages/react-native/migrations.json index 2615b50013cf0..d11fb1032df34 100644 --- a/packages/react-native/migrations.json +++ b/packages/react-native/migrations.json @@ -89,6 +89,18 @@ "version": "16.1.0-beta.0", "description": "Upgrade @storybook/react-native to 6.5", "implementation": "./src/migrations/update-16-1-0/upgrade-storybook-6-5" + }, + "update-16-6-0-add-dependsOn": { + "cli": "nx", + "version": "16.6.0-beta.0", + "description": "Add dependsOn like ensure-symlink or sync-deps to targets", + "implementation": "./src/migrations/update-16-6-0/add-depends-on" + }, + "update-16-6-0-update-metro-config": { + "cli": "nx", + "version": "16.6.0-beta.0", + "description": "Update metro.config.js to use the new metro config format", + "implementation": "./src/migrations/update-16-6-0/update-metro-config" } }, "packageJsonUpdates": { @@ -1348,6 +1360,72 @@ "alwaysAddToPackageJson": false } } + }, + "16.6.0": { + "version": "16.6.0-beta.0", + "packages": { + "react-native": { + "version": "0.72.3", + "alwaysAddToPackageJson": false + }, + "@types/react-native": { + "version": "0.72.2", + "alwaysAddToPackageJson": false + }, + "metro": { + "version": "0.76.7", + "alwaysAddToPackageJson": false + }, + "metro-resolver": { + "version": "0.76.7", + "alwaysAddToPackageJson": false + }, + "metro-config": { + "version": "0.76.7", + "alwaysAddToPackageJson": false + }, + "metro-react-native-babel-preset": { + "version": "0.76.7", + "alwaysAddToPackageJson": false + }, + "metro-babel-register": { + "version": "0.76.7", + "alwaysAddToPackageJson": false + }, + "metro-react-native-babel-transformer": { + "version": "0.76.7", + "alwaysAddToPackageJson": false + }, + "@react-native/metro-config": { + "version": "^0.72.9", + "alwaysAddToPackageJson": false, + "addToPackageJson": "devDependencies" + }, + "@react-native-community/cli": { + "version": "11.3.5", + "alwaysAddToPackageJson": false + }, + "@react-native-community/cli-platform-android": { + "version": "11.3.5", + "alwaysAddToPackageJson": false + }, + "@react-native-community/cli-platform-ios": { + "version": "11.3.5", + "alwaysAddToPackageJson": false + }, + "@babel/runtime": { + "version": "7.22.6", + "alwaysAddToPackageJson": false + }, + "@react-native-async-storage/async-storage": { + "version": "1.19.0", + "alwaysAddToPackageJson": false + }, + "react-native-safe-area-context": { + "version": "4.7.1", + "alwaysAddToPackageJson": false + } + } } } } diff --git a/packages/react-native/package.json b/packages/react-native/package.json index 0231e5e88d8ef..7aa7ef0cd198d 100644 --- a/packages/react-native/package.json +++ b/packages/react-native/package.json @@ -30,7 +30,8 @@ "fs-extra": "^11.1.0", "glob": "7.1.4", "ignore": "^5.0.4", - "metro-resolver": "^0.74.1", + "metro-config": "0.76.7", + "metro-resolver": "0.76.7", "minimatch": "3.0.5", "node-fetch": "^2.6.7", "tsconfig-paths": "^4.1.2", @@ -43,7 +44,7 @@ "@nx/workspace": "file:../workspace" }, "peerDependencies": { - "react-native": ">= 0.71.0" + "react-native": ">= 0.72.0 < 0.73.0" }, "builders": "./executors.json", "ng-update": { diff --git a/packages/react-native/plugins/with-nx-metro.ts b/packages/react-native/plugins/with-nx-metro.ts index 6bf66f767af32..14f4171322c51 100644 --- a/packages/react-native/plugins/with-nx-metro.ts +++ b/packages/react-native/plugins/with-nx-metro.ts @@ -1,4 +1,6 @@ import { workspaceLayout, workspaceRoot } from '@nx/devkit'; +import { mergeConfig } from 'metro-config'; +import type { MetroConfig } from 'metro-config'; import { join } from 'path'; import { existsSync } from 'fs-extra'; @@ -7,36 +9,39 @@ import { getResolveRequest } from './metro-resolver'; interface WithNxOptions { debug?: boolean; extensions?: string[]; + /** + * @deprecated TODO(v17) in the metro.config.js, pass in to the getDefaultConfig instead: getDefaultConfig(__dirname) + */ projectRoot?: string; watchFolders?: string[]; } -export function withNxMetro(config: any, opts: WithNxOptions = {}) { +export async function withNxMetro( + userConfig: MetroConfig, + opts: WithNxOptions = {} +) { const extensions = ['', 'ts', 'tsx', 'js', 'jsx', 'json']; if (opts.debug) process.env.NX_REACT_NATIVE_DEBUG = 'true'; if (opts.extensions) extensions.push(...opts.extensions); - config.projectRoot = opts.projectRoot || workspaceRoot; - - // Add support for paths specified by tsconfig - config.resolver = { - ...config.resolver, - resolveRequest: getResolveRequest(extensions), - }; - - let watchFolders = config.watchFolders || []; - watchFolders = watchFolders.concat([ + let watchFolders = [ join(workspaceRoot, 'node_modules'), join(workspaceRoot, workspaceLayout().libsDir), join(workspaceRoot, 'packages'), join(workspaceRoot, '.storybook'), - ]); + ]; if (opts.watchFolders?.length) { watchFolders = watchFolders.concat(opts.watchFolders); } watchFolders = watchFolders.filter((folder) => existsSync(folder)); - config.watchFolders = watchFolders; - return config; + const nxConfig: MetroConfig = { + resolver: { + resolveRequest: getResolveRequest(extensions), + }, + watchFolders, + }; + + return mergeConfig(userConfig, nxConfig); } diff --git a/packages/react-native/src/executors/build-android/build-android.impl.ts b/packages/react-native/src/executors/build-android/build-android.impl.ts index e6082d2d64f53..0c907af737eb5 100644 --- a/packages/react-native/src/executors/build-android/build-android.impl.ts +++ b/packages/react-native/src/executors/build-android/build-android.impl.ts @@ -1,62 +1,24 @@ -import { ExecutorContext, names } from '@nx/devkit'; -import { join } from 'path'; -import { ensureNodeModulesSymlink } from '../../utils/ensure-node-modules-symlink'; +import { ExecutorContext } from '@nx/devkit'; +import { join, resolve as pathResolve } from 'path'; import { ChildProcess, fork } from 'child_process'; import { ReactNativeBuildAndroidOptions } from './schema'; import { chmodAndroidGradlewFiles } from '../../utils/chmod-android-gradle-files'; -import { runCliStart } from '../start/start.impl'; -import { - displayNewlyAddedDepsMessage, - syncDeps, -} from '../sync-deps/sync-deps.impl'; import { getCliOptions } from '../../utils/get-cli-options'; export interface ReactNativeBuildOutput { success: boolean; } -let childProcess: ChildProcess; - export default async function* buildAndroidExecutor( options: ReactNativeBuildAndroidOptions, context: ExecutorContext ): AsyncGenerator { const projectRoot = context.projectsConfigurations.projects[context.projectName].root; - ensureNodeModulesSymlink(context.root, projectRoot); - if (options.sync) { - displayNewlyAddedDepsMessage( - context.projectName, - await syncDeps( - context.projectName, - projectRoot, - context.root, - context.projectGraph - ) - ); - } - chmodAndroidGradlewFiles(join(projectRoot, 'android')); - try { - const tasks = [runCliBuild(context.root, projectRoot, options)]; - if (options.packager && options.mode !== 'release') { - tasks.push( - runCliStart(context.root, projectRoot, { - port: options.port, - resetCache: options.resetCache, - interactive: options.interactive, - }) - ); - } - - await Promise.all(tasks); - yield { success: true }; - } finally { - if (childProcess) { - childProcess.kill(); - } - } + await runCliBuild(context.root, projectRoot, options); + yield { success: true }; } function runCliBuild( @@ -64,30 +26,39 @@ function runCliBuild( projectRoot: string, options: ReactNativeBuildAndroidOptions ) { - return new Promise((resolve, reject) => { + return new Promise((res, reject) => { /** * Call the react native cli with option `--no-packager` * Not passing '--packager' due to cli will launch start command from the project root */ - childProcess = fork( - join(workspaceRoot, './node_modules/react-native/cli.js'), + const childProcess = fork( + require.resolve('react-native/cli.js'), ['build-android', ...createBuildAndroidOptions(options), '--no-packager'], { - cwd: join(workspaceRoot, projectRoot), + stdio: 'inherit', + cwd: pathResolve(workspaceRoot, projectRoot), env: { ...process.env, RCT_METRO_PORT: options.port.toString() }, } ); - // Ensure the child process is killed when the parent exits - process.on('exit', () => childProcess.kill()); - process.on('SIGTERM', () => childProcess.kill()); + /** + * Ensure the child process is killed when the parent exits + */ + const processExitListener = (signal?: number | NodeJS.Signals) => () => { + childProcess.kill(signal); + process.exit(); + }; + process.once('exit', (signal) => childProcess.kill(signal)); + process.once('SIGTERM', processExitListener); + process.once('SIGINT', processExitListener); + process.once('SIGQUIT', processExitListener); childProcess.on('error', (err) => { reject(err); }); childProcess.on('exit', (code) => { if (code === 0) { - resolve(code); + res(childProcess); } else { reject(code); } diff --git a/packages/react-native/src/executors/build-android/schema.d.ts b/packages/react-native/src/executors/build-android/schema.d.ts index 24c8d29ce7401..712fe67790139 100644 --- a/packages/react-native/src/executors/build-android/schema.d.ts +++ b/packages/react-native/src/executors/build-android/schema.d.ts @@ -1,4 +1,5 @@ // options taken from https://github.com/react-native-community/cli/blob/main/packages/cli-platform-android/src/commands/buildAndroid/index.ts +// https://github.com/react-native-community/cli/blob/main/packages/cli-platform-android/README.md#build-android import { ReactNativeStartOptions } from '../start/schema'; @@ -20,12 +21,13 @@ export interface ReactNativeBuildAndroidOptions // react native options mode: string; // default is debug activeArchOnly: boolean; // default is false - port: number; // default is 8081 - tasks?: Array; + tasks?: string | Array; extraParams?: Array; - interactive?: boolean; + interactive: boolean; // nx options + // @deprecated, no longer used packager: boolean; // default is true + // @deprecated, add to sync-deps to dependsOn sync: boolean; } diff --git a/packages/react-native/src/executors/build-android/schema.json b/packages/react-native/src/executors/build-android/schema.json index 16284032ae8cb..d2d5426aa2691 100644 --- a/packages/react-native/src/executors/build-android/schema.json +++ b/packages/react-native/src/executors/build-android/schema.json @@ -51,7 +51,8 @@ "packager": { "type": "boolean", "description": "Launch packager while building", - "default": true + "default": true, + "x-deprecated": "Run `nx run :start` instead. Will be removed in Nx 17." }, "port": { "type": "number", @@ -59,10 +60,10 @@ "default": 8081 }, "tasks": { - "type": "array", - "items": { - "type": "string" - }, + "oneOf": [ + { "type": "array", "items": { "type": "string" } }, + { "type": "string" } + ], "description": "Run custom Gradle tasks. By default it's \"assembleDebug\". Will override passed mode and variant arguments.", "examples": [ "assembleDebug", @@ -79,8 +80,12 @@ "default": false }, "extraParams": { - "type": "string", - "description": "Custom params passed to gradle build command" + "oneOf": [ + { "type": "array", "items": { "type": "string" } }, + { "type": "string" } + ], + "description": "Custom params passed to gradle build command", + "examples": ["-x lint -x test"] }, "interactive": { "type": "boolean", @@ -89,7 +94,8 @@ "sync": { "type": "boolean", "description": "Syncs npm dependencies to `package.json` (for React Native autolink).", - "default": true + "default": true, + "x-deprecated": "Add sync-deps to dependsOn instead" }, "resetCache": { "type": "boolean", diff --git a/packages/react-native/src/executors/build-ios/build-ios.impl.ts b/packages/react-native/src/executors/build-ios/build-ios.impl.ts index 7b58775717f8b..98452a453ccd7 100644 --- a/packages/react-native/src/executors/build-ios/build-ios.impl.ts +++ b/packages/react-native/src/executors/build-ios/build-ios.impl.ts @@ -1,25 +1,16 @@ import { ExecutorContext } from '@nx/devkit'; -import { join } from 'path'; +import { resolve as pathResolve } from 'path'; import { ChildProcess, fork } from 'child_process'; import { platform } from 'os'; -import { ensureNodeModulesSymlink } from '../../utils/ensure-node-modules-symlink'; -import { - displayNewlyAddedDepsMessage, - syncDeps, -} from '../sync-deps/sync-deps.impl'; -import { podInstall } from '../../utils/pod-install-task'; import { ReactNativeBuildIosOptions } from './schema'; -import { runCliStart } from '../start/start.impl'; import { getCliOptions } from '../../utils/get-cli-options'; export interface ReactNativeBuildIosOutput { success: boolean; } -let childProcess: ChildProcess; - -export default async function* runIosExecutor( +export default async function* buildIosExecutor( options: ReactNativeBuildIosOptions, context: ExecutorContext ): AsyncGenerator { @@ -28,77 +19,48 @@ export default async function* runIosExecutor( } const projectRoot = context.projectsConfigurations.projects[context.projectName].root; - ensureNodeModulesSymlink(context.root, projectRoot); - if (options.sync) { - displayNewlyAddedDepsMessage( - context.projectName, - await syncDeps( - context.projectName, - projectRoot, - context.root, - context.projectGraph - ) - ); - } - - if (options.install) { - await podInstall( - join(context.root, projectRoot, 'ios'), - options.buildFolder - ); - } - - try { - const tasks = [runCliBuildIOS(context.root, projectRoot, options)]; - if (options.packager && options.mode !== 'Release') { - tasks.push( - runCliStart(context.root, projectRoot, { - port: options.port, - resetCache: options.resetCache, - interactive: options.interactive, - }) - ); - } - await Promise.all(tasks); - - yield { success: true }; - } finally { - if (childProcess) { - childProcess.kill(); - } - } + await runCliBuildIOS(context.root, projectRoot, options); + return { success: true }; } function runCliBuildIOS( workspaceRoot: string, projectRoot: string, options: ReactNativeBuildIosOptions -) { - return new Promise((resolve, reject) => { - /** - * Call the react native cli with option `--no-packager` - * Not passing '--packager' due to cli will launch start command from the project root - */ - childProcess = fork( - join(workspaceRoot, './node_modules/react-native/cli.js'), - ['build-ios', ...createBuildIOSOptions(options)], +): Promise { + return new Promise((resolve, reject) => { + const childProcess = fork( + require.resolve('react-native/cli.js'), + [ + 'build-ios', + ...createBuildIOSOptions(options), + ...(process.env.NX_VERBOSE_LOGGING === 'true' ? ['--verbose'] : []), + ], { - cwd: join(workspaceRoot, projectRoot), + cwd: pathResolve(workspaceRoot, projectRoot), env: { ...process.env, RCT_METRO_PORT: options.port.toString() }, } ); - // Ensure the child process is killed when the parent exits - process.on('exit', () => childProcess.kill()); - process.on('SIGTERM', () => childProcess.kill()); + /** + * Ensure the child process is killed when the parent exits + */ + const processExitListener = (signal?: number | NodeJS.Signals) => () => { + childProcess.kill(signal); + process.exit(); + }; + process.once('exit', (signal) => childProcess.kill(signal)); + process.once('SIGTERM', processExitListener); + process.once('SIGINT', processExitListener); + process.once('SIGQUIT', processExitListener); childProcess.on('error', (err) => { reject(err); }); childProcess.on('exit', (code) => { if (code === 0) { - resolve(code); + resolve(childProcess); } else { reject(code); } diff --git a/packages/react-native/src/executors/build-ios/schema.d.ts b/packages/react-native/src/executors/build-ios/schema.d.ts index df4fac0ecc331..974d3271bf9d4 100644 --- a/packages/react-native/src/executors/build-ios/schema.d.ts +++ b/packages/react-native/src/executors/build-ios/schema.d.ts @@ -16,7 +16,10 @@ export interface ReactNativeBuildIosOptions extends ReactNativeStartOptions { extraParams?: string; // nx options + // @deprecated, no longer used packager: boolean; // default is true + // @deprecated, add to pod-install to dependsOn install: boolean; // default is true + // @deprecated, add to sync-deps to dependsOn sync: boolean; // default is true } diff --git a/packages/react-native/src/executors/build-ios/schema.json b/packages/react-native/src/executors/build-ios/schema.json index a23017767b411..1036e8f4c5eaa 100644 --- a/packages/react-native/src/executors/build-ios/schema.json +++ b/packages/react-native/src/executors/build-ios/schema.json @@ -17,10 +17,6 @@ { "name": "Build iOS for a device with udid", "keys": ["udid"] - }, - { - "name": "Run `pod install` before building iOS app", - "keys": ["install"] } ], "properties": { @@ -78,17 +74,22 @@ "description": "Explicitly select which scheme and configuration to use before running a build" }, "extraParams": { - "type": "string", + "oneOf": [ + { "type": "array", "items": { "type": "string" } }, + { "type": "string" } + ], "description": "Custom params that will be passed to xcodebuild command." }, "install": { "type": "boolean", "description": "Runs `pod install` for native modules before building iOS app.", + "x-deprecated": "Add pod-install to dependsOn in project.json for this target instead", "default": true }, "sync": { "type": "boolean", "description": "Syncs npm dependencies to `package.json` (for React Native autolink).", + "x-deprecated": "Add sync-deps to dependsOn in project.json for this target instead", "default": true }, "resetCache": { @@ -99,7 +100,8 @@ "packager": { "type": "boolean", "description": "Launch packager while building", - "default": true + "default": true, + "x-deprecated": "Run `nx run :start` instead. Will be removed in Nx 17." } }, "required": [], diff --git a/packages/react-native/src/executors/bundle/bundle.impl.ts b/packages/react-native/src/executors/bundle/bundle.impl.ts index 42f4a9004465f..dafdf71e1246c 100644 --- a/packages/react-native/src/executors/bundle/bundle.impl.ts +++ b/packages/react-native/src/executors/bundle/bundle.impl.ts @@ -1,18 +1,14 @@ import { createDirectory } from '@nx/workspace/src/utilities/fileutils'; import { names, ExecutorContext } from '@nx/devkit'; -import { dirname, join } from 'path'; +import { dirname, join, resolve as pathResolve } from 'path'; import { ChildProcess, fork } from 'child_process'; -import { ensureNodeModulesSymlink } from '../../utils/ensure-node-modules-symlink'; - import { ReactNativeBundleOptions } from './schema'; export interface ReactNativeBundleOutput { success: boolean; } -let childProcess: ChildProcess; - export default async function* bundleExecutor( options: ReactNativeBundleOptions, context: ExecutorContext @@ -23,41 +19,46 @@ export default async function* bundleExecutor( options.bundleOutput = join(context.root, options.bundleOutput); createDirectory(dirname(options.bundleOutput)); - ensureNodeModulesSymlink(context.root, projectRoot); - try { - await runCliBuild(context.root, projectRoot, options); - yield { success: true }; - } finally { - if (childProcess) { - childProcess.kill(); - } - } + await runCliBuild(context.root, projectRoot, options); + yield { success: true }; } function runCliBuild( workspaceRoot: string, projectRoot: string, options: ReactNativeBundleOptions -) { - return new Promise((resolve, reject) => { +): Promise { + return new Promise((resolve, reject) => { const cliOptions = createBundleOptions(options); - childProcess = fork( - join(workspaceRoot, './node_modules/react-native/cli.js'), + const childProcess = fork( + require.resolve('react-native/cli.js'), ['bundle', ...cliOptions], - { cwd: join(workspaceRoot, projectRoot), env: process.env } + { + stdio: 'inherit', + cwd: pathResolve(workspaceRoot, projectRoot), + env: process.env, + } ); - // Ensure the child process is killed when the parent exits - process.on('exit', () => childProcess.kill()); - process.on('SIGTERM', () => childProcess.kill()); + /** + * Ensure the child process is killed when the parent exits + */ + const processExitListener = (signal?: number | NodeJS.Signals) => () => { + childProcess.kill(signal); + process.exit(); + }; + process.once('exit', (signal) => childProcess.kill(signal)); + process.once('SIGTERM', processExitListener); + process.once('SIGINT', processExitListener); + process.once('SIGQUIT', processExitListener); childProcess.on('error', (err) => { reject(err); }); childProcess.on('exit', (code) => { if (code === 0) { - resolve(code); + resolve(childProcess); } else { reject(code); } diff --git a/packages/react-native/src/executors/pod-install/pod-install.impl.ts b/packages/react-native/src/executors/pod-install/pod-install.impl.ts index c4a283fca05d4..8ec0f80cffdb8 100644 --- a/packages/react-native/src/executors/pod-install/pod-install.impl.ts +++ b/packages/react-native/src/executors/pod-install/pod-install.impl.ts @@ -15,7 +15,7 @@ export default async function* podInstall( const projectRoot = context.projectsConfigurations.projects[context.projectName].root; const iosDirectory = join(context.root, projectRoot, 'ios'); - await runPodInstall(iosDirectory, true, options.buildFolder)(); + await runPodInstall(iosDirectory, true, options)(); yield { success: true }; } diff --git a/packages/react-native/src/executors/pod-install/schema.d.ts b/packages/react-native/src/executors/pod-install/schema.d.ts index 11f7664df8e04..41f36baf08d81 100644 --- a/packages/react-native/src/executors/pod-install/schema.d.ts +++ b/packages/react-native/src/executors/pod-install/schema.d.ts @@ -1,3 +1,5 @@ export interface ReactNativePodInstallOptions { - buildFolder: string; + buildFolder: string; // default is './build' + repoUpdate: boolean; // default is false + deployment: boolean; // default is false } diff --git a/packages/react-native/src/executors/pod-install/schema.json b/packages/react-native/src/executors/pod-install/schema.json index 0cc954d982e9e..e6e373c4c756f 100644 --- a/packages/react-native/src/executors/pod-install/schema.json +++ b/packages/react-native/src/executors/pod-install/schema.json @@ -9,9 +9,19 @@ "type": "object", "properties": { "buildFolder": { - "description": "Location for iOS build artifacts. Corresponds to Xcode's \"-derivedDataPath\". Relative to ios directory", + "description": "Location for iOS build artifacts. Corresponds to Xcode's \"-derivedDataPath\". Relative to ios directory.", "type": "string", "default": "./build" + }, + "repoUpdate": { + "description": "Force running `pod repo update` before install.", + "type": "boolean", + "default": false + }, + "deployment": { + "description": "Disallow any changes to the Podfile or the Podfile.lock during installation.", + "type": "boolean", + "default": false } }, "required": ["buildFolder"] diff --git a/packages/react-native/src/executors/run-android/run-android.impl.ts b/packages/react-native/src/executors/run-android/run-android.impl.ts index a73b3c197bbb9..2d28ab4db3aa6 100644 --- a/packages/react-native/src/executors/run-android/run-android.impl.ts +++ b/packages/react-native/src/executors/run-android/run-android.impl.ts @@ -1,14 +1,9 @@ import { ExecutorContext } from '@nx/devkit'; -import { join } from 'path'; +import { join, resolve as pathResolve } from 'path'; import { ChildProcess, fork } from 'child_process'; -import { ensureNodeModulesSymlink } from '../../utils/ensure-node-modules-symlink'; -import { - displayNewlyAddedDepsMessage, - syncDeps, -} from '../sync-deps/sync-deps.impl'; import { ReactNativeRunAndroidOptions } from './schema'; -import { runCliStart } from '../start/start.impl'; +import startExecutor from '../start/start.impl'; import { chmodAndroidGradlewFiles } from '../../utils/chmod-android-gradle-files'; import { getCliOptions } from '../../utils/get-cli-options'; @@ -24,72 +19,72 @@ export default async function* runAndroidExecutor( ): AsyncGenerator { const projectRoot = context.projectsConfigurations.projects[context.projectName].root; - ensureNodeModulesSymlink(context.root, projectRoot); chmodAndroidGradlewFiles(join(projectRoot, 'android')); - if (options.sync) { - displayNewlyAddedDepsMessage( - context.projectName, - await syncDeps( - context.projectName, - projectRoot, - context.root, - context.projectGraph - ) + if (options.packager && options.mode !== 'Release') { + const startResults = startExecutor( + { + port: options.port, + resetCache: options.resetCache, + interactive: true, + }, + context ); - } - - try { - const tasks = [runCliRunAndroid(context.root, projectRoot, options)]; - if (options.packager) { - tasks.push( - runCliStart(context.root, projectRoot, { - port: options.port, - resetCache: options.resetCache, - interactive: options.interactive, - }) - ); - } - - await Promise.all(tasks); - - yield { success: true }; - } finally { - if (childProcess) { - childProcess.kill(); + for await (const result of startResults) { + if (result.success) { + await runCliRunAndroid(context.root, projectRoot, options); + yield { + success: true, + }; + } else { + return result; + } } + } else { + await runCliRunAndroid(context.root, projectRoot, options); } + + yield { success: true }; } function runCliRunAndroid( workspaceRoot: string, projectRoot: string, options: ReactNativeRunAndroidOptions -) { - return new Promise((resolve, reject) => { +): Promise { + return new Promise((resolve, reject) => { /** * Call the react native cli with option `--no-packager` * Not passing '--packager' due to cli will launch start command from the project root */ childProcess = fork( - join(workspaceRoot, './node_modules/react-native/cli.js'), + require.resolve('react-native/cli.js'), ['run-android', ...createRunAndroidOptions(options), '--no-packager'], { - cwd: join(workspaceRoot, projectRoot), + stdio: 'inherit', + cwd: pathResolve(workspaceRoot, projectRoot), env: { ...process.env, RCT_METRO_PORT: options.port.toString() }, } ); - // Ensure the child process is killed when the parent exits - process.on('exit', () => childProcess.kill()); - process.on('SIGTERM', () => childProcess.kill()); + /** + * Ensure the child process is killed when the parent exits + */ + const processExitListener = (signal?: number | NodeJS.Signals) => () => { + childProcess.kill(signal); + process.exit(); + }; + process.once('exit', (signal) => childProcess.kill(signal)); + process.once('SIGTERM', processExitListener); + process.once('SIGINT', processExitListener); + process.once('SIGQUIT', processExitListener); childProcess.on('error', (err) => { reject(err); }); childProcess.on('exit', (code) => { if (code === 0) { - resolve(code); + resolve(childProcess); } else { reject(code); } diff --git a/packages/react-native/src/executors/run-android/schema.d.ts b/packages/react-native/src/executors/run-android/schema.d.ts index 710d98a8e58c8..7051e74836e1d 100644 --- a/packages/react-native/src/executors/run-android/schema.d.ts +++ b/packages/react-native/src/executors/run-android/schema.d.ts @@ -5,11 +5,11 @@ import { ReactNativeStartOptions } from '../start/schema'; export interface ReactNativeRunAndroidOptions extends ReactNativeBuildAndroidOptions { /** - * @deprecated use mode instead + * @deprecated TODO(v17) use mode instead */ variant: string; /** - * @deprecated no longer supported in react native cli + * @deprecated TODO(v17) no longer supported in react native cli * https://github.com/react-native-community/cli/commit/7c003f2b1d9d80ec5c167614ba533a004272c685 */ jetifier: boolean; diff --git a/packages/react-native/src/executors/run-android/schema.json b/packages/react-native/src/executors/run-android/schema.json index 41614a3ea6615..1854d664cd999 100644 --- a/packages/react-native/src/executors/run-android/schema.json +++ b/packages/react-native/src/executors/run-android/schema.json @@ -77,10 +77,10 @@ "default": 8081 }, "tasks": { - "type": "array", - "items": { - "type": "string" - }, + "oneOf": [ + { "type": "array", "items": { "type": "string" } }, + { "type": "string" } + ], "description": "Run custom Gradle tasks. By default it's \"assembleDebug\". Will override passed mode and variant arguments.", "examples": [ "assembleDebug", @@ -97,7 +97,10 @@ "default": false }, "extraParams": { - "type": "string", + "oneOf": [ + { "type": "array", "items": { "type": "string" } }, + { "type": "string" } + ], "description": "Custom params passed to gradle build command" }, "interactive": { @@ -107,6 +110,7 @@ "sync": { "type": "boolean", "description": "Syncs npm dependencies to `package.json` (for React Native autolink).", + "x-deprecated": "Add sync-deps to dependsOn for this target in project.json instead", "default": true }, "resetCache": { diff --git a/packages/react-native/src/executors/run-ios/run-ios.impl.ts b/packages/react-native/src/executors/run-ios/run-ios.impl.ts index 62b4581e7ef75..4eb48804f81a3 100644 --- a/packages/react-native/src/executors/run-ios/run-ios.impl.ts +++ b/packages/react-native/src/executors/run-ios/run-ios.impl.ts @@ -1,24 +1,16 @@ import { ExecutorContext } from '@nx/devkit'; -import { join } from 'path'; +import { resolve as pathResolve } from 'path'; import { ChildProcess, fork } from 'child_process'; import { platform } from 'os'; -import { ensureNodeModulesSymlink } from '../../utils/ensure-node-modules-symlink'; -import { - displayNewlyAddedDepsMessage, - syncDeps, -} from '../sync-deps/sync-deps.impl'; -import { podInstall } from '../../utils/pod-install-task'; -import { ReactNativeRunIosOptions } from './schema'; -import { runCliStart } from '../start/start.impl'; +import startExecutor from '../start/start.impl'; import { getCliOptions } from '../../utils/get-cli-options'; +import { ReactNativeRunIosOptions } from './schema'; export interface ReactNativeRunIosOutput { success: boolean; } -let childProcess: ChildProcess; - export default async function* runIosExecutor( options: ReactNativeRunIosOptions, context: ExecutorContext @@ -28,77 +20,71 @@ export default async function* runIosExecutor( } const projectRoot = context.projectsConfigurations.projects[context.projectName].root; - ensureNodeModulesSymlink(context.root, projectRoot); - if (options.sync) { - displayNewlyAddedDepsMessage( - context.projectName, - await syncDeps( - context.projectName, - projectRoot, - context.root, - context.projectGraph - ) - ); - } - if (options.install) { - await podInstall( - join(context.root, projectRoot, 'ios'), - options.buildFolder + if (options.packager && options.mode !== 'Release') { + const startResults = startExecutor( + { + port: options.port, + resetCache: options.resetCache, + interactive: true, + }, + context ); - } - - try { - const tasks = [runCliRunIOS(context.root, projectRoot, options)]; - if (options.packager && options.mode !== 'Release') { - tasks.push( - runCliStart(context.root, projectRoot, { - port: options.port, - resetCache: options.resetCache, - interactive: options.interactive, - }) - ); - } - - await Promise.all(tasks); - - yield { success: true }; - } finally { - if (childProcess) { - childProcess.kill(); + for await (const result of startResults) { + if (result.success) { + await runCliRunIOS(context.root, projectRoot, options); + yield { + success: true, + }; + } else { + return result; + } } + } else { + await runCliRunIOS(context.root, projectRoot, options); } + + yield { success: true }; } function runCliRunIOS( workspaceRoot: string, projectRoot: string, options: ReactNativeRunIosOptions -) { - return new Promise((resolve, reject) => { +): Promise { + return new Promise((resolve, reject) => { /** * Call the react native cli with option `--no-packager` * Not passing '--packager' due to cli will launch start command from the project root */ - childProcess = fork( - join(workspaceRoot, './node_modules/react-native/cli.js'), + const childProcess = fork( + require.resolve('react-native/cli.js'), ['run-ios', ...createRunIOSOptions(options), '--no-packager'], { - cwd: join(workspaceRoot, projectRoot), + stdio: 'inherit', + cwd: pathResolve(workspaceRoot, projectRoot), env: { ...process.env, RCT_METRO_PORT: options.port.toString() }, } ); - // Ensure the child process is killed when the parent exits - process.on('exit', () => childProcess.kill()); - process.on('SIGTERM', () => childProcess.kill()); + /** + * Ensure the child process is killed when the parent exits + */ + const processExitListener = (signal?: number | NodeJS.Signals) => () => { + childProcess.kill(signal); + process.exit(); + }; + process.once('exit', (signal) => childProcess.kill(signal)); + process.once('SIGTERM', processExitListener); + process.once('SIGINT', processExitListener); + process.once('SIGQUIT', processExitListener); childProcess.on('error', (err) => { reject(err); }); childProcess.on('exit', (code) => { if (code === 0) { - resolve(code); + resolve(childProcess); } else { reject(code); } diff --git a/packages/react-native/src/executors/run-ios/schema.d.ts b/packages/react-native/src/executors/run-ios/schema.d.ts index 934e49183eb8e..49b5bbbe55c6c 100644 --- a/packages/react-native/src/executors/run-ios/schema.d.ts +++ b/packages/react-native/src/executors/run-ios/schema.d.ts @@ -4,7 +4,7 @@ import { ReactNativeStartOptions } from '../start/schema'; // part of options form https://github.com/react-native-community/cli/blob/main/packages/cli-platform-ios/src/commands/runIOS/index.ts export interface ReactNativeRunIosOptions extends ReactNativeBuildIosOptions { /** - * @deprecated use mode instead, will be removed in nx 17. + * @deprecated TODO(v17) use mode instead, will be removed in nx 17. */ xcodeConfiguration?: string; diff --git a/packages/react-native/src/executors/run-ios/schema.json b/packages/react-native/src/executors/run-ios/schema.json index ca1182d5b473a..e23f006c61035 100644 --- a/packages/react-native/src/executors/run-ios/schema.json +++ b/packages/react-native/src/executors/run-ios/schema.json @@ -19,10 +19,6 @@ { "name": "Run iOS on a device with udid", "keys": ["udid"] - }, - { - "name": "Run `pod install` before building iOS app", - "keys": ["install"] } ], "properties": { @@ -87,17 +83,22 @@ "description": "Explicitly select which scheme and configuration to use before running a build" }, "extraParams": { - "type": "string", + "oneOf": [ + { "type": "array", "items": { "type": "string" } }, + { "type": "string" } + ], "description": "Custom params that will be passed to xcodebuild command." }, "install": { "type": "boolean", "description": "Runs `pod install` for native modules before building iOS app.", - "default": true + "default": true, + "x-deprecated": "Add `pod-install` to dependsOn for this target in project.json instead." }, "sync": { "type": "boolean", "description": "Syncs npm dependencies to `package.json` (for React Native autolink).", + "x-deprecated": "Add `sync-deps` to dependsOn for this target in project.json instead.", "default": true }, "resetCache": { diff --git a/packages/react-native/src/executors/start/start.impl.ts b/packages/react-native/src/executors/start/start.impl.ts index 8155da595bdeb..71304653f5b2a 100644 --- a/packages/react-native/src/executors/start/start.impl.ts +++ b/packages/react-native/src/executors/start/start.impl.ts @@ -1,18 +1,15 @@ -import * as chalk from 'chalk'; import { ExecutorContext, logger } from '@nx/devkit'; import { ChildProcess, fork } from 'child_process'; -import { join } from 'path'; +import { resolve as pathResolve } from 'path'; import { ensureNodeModulesSymlink } from '../../utils/ensure-node-modules-symlink'; import { isPackagerRunning } from './lib/is-packager-running'; import { ReactNativeStartOptions } from './schema'; export interface ReactNativeStartOutput { - baseUrl?: string; + port?: number; success: boolean; } -let childProcess: ChildProcess; - export default async function* startExecutor( options: ReactNativeStartOptions, context: ExecutorContext @@ -21,27 +18,27 @@ export default async function* startExecutor( context.projectsConfigurations.projects[context.projectName].root; ensureNodeModulesSymlink(context.root, projectRoot); - try { - const baseUrl = `http://localhost:${options.port}`; - const appName = context.projectName; - logger.info(chalk.cyan(`Packager is ready at ${baseUrl}`)); - logger.info( - `Use ${chalk.bold(`nx run-android ${appName}`)} or ${chalk.bold( - `nx run-ios ${appName}` - )} to run the native app.` - ); + const startProcess = await runCliStart(context.root, projectRoot, options); - await runCliStart(context.root, projectRoot, options); + yield { + port: options.port, + success: true, + }; - yield { - baseUrl, - success: true, - }; - } finally { - if (childProcess) { - childProcess.kill(); - } + if (!startProcess) { + return; } + await new Promise((resolve) => { + const processExitListener = (signal?: number | NodeJS.Signals) => () => { + startProcess.kill(signal); + resolve(); + process.exit(); + }; + process.once('exit', (signal) => startProcess.kill(signal)); + process.once('SIGTERM', processExitListener); + process.once('SIGINT', processExitListener); + process.once('SIGQUIT', processExitListener); + }); } /* @@ -52,10 +49,10 @@ export async function runCliStart( workspaceRoot: string, projectRoot: string, options: ReactNativeStartOptions -): Promise { +): Promise { const result = await isPackagerRunning(options.port); if (result === 'running') { - logger.info('JS server already running.'); + logger.info(`JS server already running on port ${options.port}.`); } else if (result === 'unrecognized') { logger.warn('JS server not recognized.'); } else { @@ -63,7 +60,7 @@ export async function runCliStart( logger.info('Starting JS server...'); try { - await startAsync(workspaceRoot, projectRoot, options); + return await startAsync(workspaceRoot, projectRoot, options); } catch (error) { logger.error( `Failed to start the packager server. Error details: ${error.message}` @@ -77,24 +74,34 @@ function startAsync( workspaceRoot: string, projectRoot: string, options: ReactNativeStartOptions -): Promise { - return new Promise((resolve, reject) => { - childProcess = fork( - join(workspaceRoot, './node_modules/react-native/cli.js'), +): Promise { + return new Promise((resolve, reject) => { + const childProcess = fork( + require.resolve('react-native/cli.js'), ['start', ...createStartOptions(options)], - { cwd: join(workspaceRoot, projectRoot), env: process.env } + { + cwd: pathResolve(workspaceRoot, projectRoot), + env: process.env, + stdio: ['inherit', 'pipe', 'pipe', 'ipc'], + } ); - // Ensure the child process is killed when the parent exits - process.on('exit', () => childProcess.kill()); - process.on('SIGTERM', () => childProcess.kill()); + childProcess.stdout.on('data', (data) => { + process.stdout.write(data); + if (data.toString().includes('reload the app')) { + resolve(childProcess); + } + }); + childProcess.stderr.on('data', (data) => { + process.stderr.write(data); + }); childProcess.on('error', (err) => { reject(err); }); childProcess.on('exit', (code) => { if (code === 0) { - resolve(code); + resolve(childProcess); } else { reject(code); } diff --git a/packages/react-native/src/executors/storybook/schema.d.ts b/packages/react-native/src/executors/storybook/schema.d.ts index 8f7e297aab34f..338fedcdf8e1b 100644 --- a/packages/react-native/src/executors/storybook/schema.d.ts +++ b/packages/react-native/src/executors/storybook/schema.d.ts @@ -3,7 +3,7 @@ export interface ReactNativeStorybookOptions { outputFile: string; pattern: string; /** - * @deprecated going to be removed in 17 + * @deprecated TODO(v17) no longer used going to be removed in 17 */ silent: boolean; } diff --git a/packages/react-native/src/generators/application/application.ts b/packages/react-native/src/generators/application/application.ts index 2381112bae027..fa5f0224cc71c 100644 --- a/packages/react-native/src/generators/application/application.ts +++ b/packages/react-native/src/generators/application/application.ts @@ -7,7 +7,6 @@ import { Tree, } from '@nx/devkit'; -import { runPodInstall } from '../../utils/pod-install-task'; import { runSymlink } from '../../utils/symlink-task'; import { addLinting } from '../../utils/add-linting'; import { addJest } from '../../utils/add-jest'; @@ -48,10 +47,6 @@ export async function reactNativeApplicationGenerator( ); const detoxTask = await addDetox(host, options); const symlinkTask = runSymlink(host.root, options.appProjectRoot); - const podInstallTask = runPodInstall( - joinPathFragments(host.root, options.iosProjectRoot), - options.install - ); const chmodTaskGradlew = chmodAndroidGradlewFilesTask( joinPathFragments(host.root, options.androidProjectRoot) ); @@ -66,7 +61,6 @@ export async function reactNativeApplicationGenerator( jestTask, detoxTask, symlinkTask, - podInstallTask, chmodTaskGradlew ); } diff --git a/packages/react-native/src/generators/application/files/app/.ruby-version b/packages/react-native/src/generators/application/files/app/.ruby-version deleted file mode 100644 index 49cdd668e1c82..0000000000000 --- a/packages/react-native/src/generators/application/files/app/.ruby-version +++ /dev/null @@ -1 +0,0 @@ -2.7.6 diff --git a/packages/react-native/src/generators/application/files/app/Gemfile.template b/packages/react-native/src/generators/application/files/app/Gemfile.template index 567e59805c4a7..1fa2c2e1abdee 100644 --- a/packages/react-native/src/generators/application/files/app/Gemfile.template +++ b/packages/react-native/src/generators/application/files/app/Gemfile.template @@ -1,6 +1,6 @@ source 'https://rubygems.org' # You may use http://rbenv.org/ or https://rvm.io/ to install and use this version -ruby File.read(File.join(__dir__, '.ruby-version')).strip +ruby ">= 2.6.10" -gem 'cocoapods', '~> 1.11', '>= 1.11.3' +gem 'cocoapods', '~> 1.12' diff --git a/packages/react-native/src/generators/application/files/app/android/app/build.gradle.template b/packages/react-native/src/generators/application/files/app/android/app/build.gradle.template index 8ce7b1ab639de..1fc5a2aeb5643 100644 --- a/packages/react-native/src/generators/application/files/app/android/app/build.gradle.template +++ b/packages/react-native/src/generators/application/files/app/android/app/build.gradle.template @@ -1,8 +1,6 @@ apply plugin: "com.android.application" apply plugin: "com.facebook.react" -import com.android.build.OutputFile - /** * This is the configuration block to customize your React Native Android app. * By default you don't need to apply any configuration, just uncomment the lines you need. @@ -13,8 +11,8 @@ react { // root = file("../") // The folder where the react-native NPM package is. Default is ../node_modules/react-native // reactNativeDir = file("../node_modules/react-native") - // The folder where the react-native Codegen package is. Default is ../node_modules/react-native-codegen - // codegenDir = file("../node_modules/react-native-codegen") + // The folder where the react-native Codegen package is. Default is ../node_modules/@react-native/codegen + // codegenDir = file("../node_modules/@react-native/codegen") // The cli.js file which is the React Native CLI entrypoint. Default is ../node_modules/react-native/cli.js // cliFile = file("../node_modules/react-native/cli.js") @@ -53,14 +51,6 @@ react { entryFile = file("../../<%= entryFile %>") } -/** - * Set this to true to create four separate APKs instead of one, - * one for each native architecture. This is useful if you don't - * use App Bundles (https://developer.android.com/guide/app-bundle/) - * and want to have separate APKs to upload to the Play Store. - */ -def enableSeparateBuildPerCPUArchitecture = false - /** * Set this to true to Run Proguard on Release builds to minify the Java bytecode. */ @@ -79,16 +69,6 @@ def enableProguardInReleaseBuilds = false */ def jscFlavor = 'org.webkit:android-jsc:+' -/** - * Private function to get the list of Native Architectures you want to build. - * This reads the value from reactNativeArchitectures in your gradle.properties - * file and works together with the --active-arch-only flag of react-native run-android. - */ -def reactNativeArchitectures() { - def value = project.getProperties().get("reactNativeArchitectures") - return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"] -} - android { ndkVersion rootProject.ext.ndkVersion @@ -106,15 +86,6 @@ android { testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner' <% } %> } - - splits { - abi { - reset() - enable enableSeparateBuildPerCPUArchitecture - universalApk false // If true, also generate a universal APK - include (*reactNativeArchitectures()) - } - } signingConfigs { debug { storeFile file('debug.keystore') @@ -138,22 +109,6 @@ android { <% } %> } } - - // applicationVariants are e.g. debug, release - applicationVariants.all { variant -> - variant.outputs.each { output -> - // For each separate APK per architecture, set a unique version code as described here: - // https://developer.android.com/studio/build/configure-apk-splits.html - // Example: versionCode 1 will generate 1001 for armeabi-v7a, 1002 for x86, etc. - def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4] - def abi = output.getFilter(OutputFile.ABI) - if (abi != null) { // null for the universal-debug, universal-release variants - output.versionCodeOverride = - defaultConfig.versionCode * 1000 + versionCodes.get(abi) - } - - } - } } dependencies { @@ -164,8 +119,6 @@ dependencies { // The version of react-native is set by the React Native Gradle Plugin implementation("com.facebook.react:react-android") - implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.0.0") - debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") { exclude group:'com.squareup.okhttp3', module:'okhttp' diff --git a/packages/react-native/src/generators/application/files/app/android/app/src/main/java/com/__lowerCaseName__/MainActivity.java.template b/packages/react-native/src/generators/application/files/app/android/app/src/main/java/com/__lowerCaseName__/MainActivity.java.template index 629bff52ba19f..14464a3569d31 100644 --- a/packages/react-native/src/generators/application/files/app/android/app/src/main/java/com/__lowerCaseName__/MainActivity.java.template +++ b/packages/react-native/src/generators/application/files/app/android/app/src/main/java/com/__lowerCaseName__/MainActivity.java.template @@ -27,9 +27,6 @@ public class MainActivity extends ReactActivity { this, getMainComponentName(), // If you opted-in for the New Architecture, we enable the Fabric Renderer. - DefaultNewArchitectureEntryPoint.getFabricEnabled(), // fabricEnabled - // If you opted-in for the New Architecture, we enable Concurrent React (i.e. React 18). - DefaultNewArchitectureEntryPoint.getConcurrentReactEnabled() // concurrentRootEnabled - ); + DefaultNewArchitectureEntryPoint.getFabricEnabled()); } } diff --git a/packages/react-native/src/generators/application/files/app/android/app/src/main/res/drawable/rn_edit_text_material.xml b/packages/react-native/src/generators/application/files/app/android/app/src/main/res/drawable/rn_edit_text_material.xml index f35d9962026a8..73b37e4d9963e 100644 --- a/packages/react-native/src/generators/application/files/app/android/app/src/main/res/drawable/rn_edit_text_material.xml +++ b/packages/react-native/src/generators/application/files/app/android/app/src/main/res/drawable/rn_edit_text_material.xml @@ -20,7 +20,7 @@ android:insetBottom="@dimen/abc_edit_text_inset_bottom_material"> - contents are moved over to use-task-executors + // ci + '/recipes/other/azure-last-successful-commit': + '/recipes/ci/azure-last-successful-commit', + // angular + '/recipes/adopting-nx/migration-angular': + '/recipes/angular/migration/angular', + '/recipes/adopting-nx-angular/angular-integrated': + '/recipes/angular/migration/angular', + '/recipes/adopting-nx-angular/angular-manual': + '/recipes/angular/migration/manual', + '/recipes/adopting-nx-angular/angular-multiple': + '/recipes/angular/migration/multiple', + '/recipes/adopting-nx/migration-angularjs': + '/recipes/angular/migration/angularjs', + '/recipes/environment-variables/use-environment-variables-in-angular': + '/recipes/angular/use-environment-variables-in-angular', + '/recipes/other/using-tailwind-css-with-angular-projects': + '/recipes/angular/using-tailwind-css-with-angular-projects', + '/recipes/module-federation/dynamic-module-federation-with-angular': + '/recipes/angular/dynamic-module-federation-with-angular', + '/recipes/other/setup-incremental-builds-angular': + '/recipes/angular/setup-incremental-builds-angular', + // react + '/recipes/adopting-nx/migration-cra': '/recipes/react/migration-cra', + '/recipes/other/react-18': '/recipes/react/react-18', + '/recipes/other/react-native': '/recipes/react/react-native', + '/recipes/other/remix': '/recipes/react/remix', + '/recipes/environment-variables/use-environment-variables-in-react': + '/recipes/react/use-environment-variables-in-react', + '/recipes/other/using-tailwind-css-in-react': + '/recipes/react/using-tailwind-css-in-react', + '/recipes/deployment/deploy-nextjs-to-vercel': + '/recipes/react/deploy-nextjs-to-vercel', + '/recipes/module-federation/module-federation-with-ssr': + '/recipes/react/module-federation-with-ssr', + '/recipes/other/adding-assets-react': '/recipes/react/adding-assets', + // node + '/recipes/deployment/node-server-fly-io': '/recipes/node/node-server-fly-io', + '/recipes/deployment/node-serverless-functions-netlify': + '/recipes/node/node-serverless-functions-netlify', + '/recipes/deployment/node-aws-lambda': '/recipes/node/node-aws-lambda', + // examples + '/recipes/module-federation/nx-examples': '/recipes/example-repos/mfe', + '/recipes/database/nestjs-prisma': '/recipes/example-repos/nestjs-prisma', + '/recipes/database/mongo-fastify': '/recipes/example-repos/mongo-fastify', + '/recipes/database/redis-fastify': '/recipes/example-repos/redis-fastify', + '/recipes/database/postgres-fastify': + '/recipes/example-repos/postgres-fastify', + '/recipes/database/serverless-fastify-planetscale': + '/recipes/example-repos/serverless-fastify-planetscale', + // troubleshooting + '/recipes/other/resolve-circular-dependencies': + '/recipes/troubleshooting/resolve-circular-dependencies', + '/recipes/ci/troubleshoot-nx-install-issues': + '/recipes/troubleshooting/troubleshoot-nx-install-issues', + '/recipes/other/troubleshoot-cache-misses': + '/recipes/troubleshooting/troubleshoot-cache-misses', + '/recipes/other/unknown-local-cache': + '/recipes/troubleshooting/unknown-local-cache', + '/recipes/other/performance-profiling': + '/recipes/troubleshooting/performance-profiling', + // tips and tricks + '/recipes/environment-variables/define-environment-variables': + '/recipes/tips-n-tricks/define-environment-variables', + '/recipes/other/eslint': '/recipes/tips-n-tricks/eslint', + '/recipes/other/browser-support': '/recipes/tips-n-tricks/browser-support', + '/recipes/other/include-assets-in-build': + '/recipes/tips-n-tricks/include-assets-in-build', + '/recipes/other/include-all-packagejson': + '/recipes/tips-n-tricks/include-all-packagejson', + '/recipes/other/identify-dependencies-between-folders': + '/recipes/tips-n-tricks/identify-dependencies-between-folders', + '/recipes/managing-repository/root-level-scripts': + '/recipes/tips-n-tricks/root-level-scripts', + '/recipes/managing-repository/analyze-source-files': + '/recipes/tips-n-tricks/analyze-source-files', + '/recipes/managing-repository/workspace-watching': + '/recipes/tips-n-tricks/workspace-watching', + '/recipes/managing-repository/standalone-to-integrated': + '/recipes/tips-n-tricks/standalone-to-integrated', + '/recipes/managing-repository/js-and-ts': '/recipes/tips-n-tricks/js-and-ts', + '/recipes/managing-repository/advanced-update': + '/recipes/tips-n-tricks/advanced-update', + '/recipes/executors/run-commands-executor': + '/recipes/tips-n-tricks/run-commands-executor', + // ci + '/recipes/ci/azure-last-successful-commit': '/recipes/ci/monorepo-ci-azure', + // other + '/recipes/deployment/deno-deploy': '/recipes/other/deno-deploy', + '/recipes/deployment/deno-netlify-functions': + '/recipes/other/deno-netlify-functions', + + // nx concepts + '/recipes/module-federation/faster-builds': + '/more-concepts/faster-builds-with-module-federation', +}; + /** * Public export API */ @@ -743,4 +849,5 @@ module.exports = { movePluginFeaturesToCore, makeMoreConceptsSubmenu, pluginsToExtendNx, + latestRecipesRefactoring, }; diff --git a/packages/nx/src/command-line/init/implementation/angular/index.ts b/packages/nx/src/command-line/init/implementation/angular/index.ts index 97e50d3ed588a..4bcf05d490252 100644 --- a/packages/nx/src/command-line/init/implementation/angular/index.ts +++ b/packages/nx/src/command-line/init/implementation/angular/index.ts @@ -65,7 +65,7 @@ export async function addNxToAngularCliRepo(options: Options) { } printFinalMessage({ - learnMoreLink: 'https://nx.dev/recipes/adopting-nx/migration-angular', + learnMoreLink: 'https://nx.dev/recipes/angular/migration/angular', bodyLines: [ '- Execute "npx nx build" twice to see the computation caching in action.', ], diff --git a/packages/nx/src/command-line/init/implementation/angular/legacy-angular-versions.ts b/packages/nx/src/command-line/init/implementation/angular/legacy-angular-versions.ts index d2a82779d1e58..2e36bcf08bcce 100644 --- a/packages/nx/src/command-line/init/implementation/angular/legacy-angular-versions.ts +++ b/packages/nx/src/command-line/init/implementation/angular/legacy-angular-versions.ts @@ -109,7 +109,7 @@ export async function getLegacyMigrationFunctionIfApplicable( } printFinalMessage({ - learnMoreLink: 'https://nx.dev/recipes/adopting-nx/migration-angular', + learnMoreLink: 'https://nx.dev/recipes/angular/migration/angular', bodyLines: [ '- Execute "npx nx build" twice to see the computation caching in action.', ], diff --git a/packages/nx/src/command-line/init/implementation/react/index.ts b/packages/nx/src/command-line/init/implementation/react/index.ts index bdfd25519ec16..44f7d8167bbd4 100644 --- a/packages/nx/src/command-line/init/implementation/react/index.ts +++ b/packages/nx/src/command-line/init/implementation/react/index.ts @@ -144,7 +144,7 @@ async function reorgnizeWorkspaceStructure(options: NormalizedOptions) { ? `npx nx build ${options.reactAppName}` : 'npm run build'; printFinalMessage({ - learnMoreLink: 'https://nx.dev/recipes/adopting-nx/migration-cra', + learnMoreLink: 'https://nx.dev/recipes/react/migration-cra', bodyLines: [ `- Execute "${buildCommand}" twice to see the computation caching in action.`, ], diff --git a/packages/nx/src/command-line/migrate/migrate.ts b/packages/nx/src/command-line/migrate/migrate.ts index 0733c54e99db7..ff504d9e0e9ab 100644 --- a/packages/nx/src/command-line/migrate/migrate.ts +++ b/packages/nx/src/command-line/migrate/migrate.ts @@ -1280,7 +1280,7 @@ async function generateMigrationsJsonAndUpdatePackageJson( ? [ `- You opted out of some migrations for now. Write the following command down somewhere to apply these migrations later:`, ` nx migrate ${opts.targetVersion} --from ${opts.targetPackage}@${minVersionWithSkippedUpdates} --exclude-applied-migrations`, - `- To learn more go to https://nx.dev/recipes/managing-repository/advanced-update`, + `- To learn more go to https://nx.dev/recipes/tips-n-tricks/advanced-update`, ] : [ `- To learn more go to https://nx.dev/core-features/automate-updating-dependencies`, diff --git a/packages/nx/src/native/assert-supported-platform.ts b/packages/nx/src/native/assert-supported-platform.ts index 1125d2ef3e22d..744ca3d5c6095 100644 --- a/packages/nx/src/native/assert-supported-platform.ts +++ b/packages/nx/src/native/assert-supported-platform.ts @@ -28,7 +28,7 @@ export function assertSupportedPlatform() { } bodyLines.push( - 'For more information please see https://nx.dev/recipes/ci/troubleshoot-nx-install-issues' + 'For more information please see https://nx.dev/recipes/troubleshooting/troubleshoot-nx-install-issues' ); output.error({ diff --git a/packages/nx/src/tasks-runner/cache.ts b/packages/nx/src/tasks-runner/cache.ts index 16d22c1e79dd0..286a9dd6c928d 100644 --- a/packages/nx/src/tasks-runner/cache.ts +++ b/packages/nx/src/tasks-runner/cache.ts @@ -245,7 +245,7 @@ export class Cache { `The local cache artifact in "${td}" was not been generated on this machine.`, `As a result, the cache's content integrity cannot be confirmed, which may make cache restoration potentially unsafe.`, `If your machine ID has changed since the artifact was cached, run "nx reset" to fix this issue.`, - `Read about the error and how to address it here: https://nx.dev/recipes/other/unknown-local-cache`, + `Read about the error and how to address it here: https://nx.dev/recipes/troubleshooting/unknown-local-cache`, ``, ].join('\n'); throw new Error(error); diff --git a/packages/react/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts b/packages/react/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts index 68e0e5dd39191..7c2fe37bae1b1 100644 --- a/packages/react/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts +++ b/packages/react/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts @@ -63,7 +63,7 @@ function getModuleFederationConfig( return config.default || config; } catch { throw new Error( - `Could not load ${moduleFederationConfigPath}. Was this project generated with "@nx/react:host"?\nSee: https://nx.dev/recipes/module-federation/faster-builds` + `Could not load ${moduleFederationConfigPath}. Was this project generated with "@nx/react:host"?\nSee: https://nx.dev/more-concepts/faster-builds-with-module-federation` ); } } diff --git a/tsconfig.base.json b/tsconfig.base.json index 27bc4a9441913..0ef4be573fd53 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -8,61 +8,136 @@ "experimentalDecorators": true, "emitDecoratorMetadata": true, "skipLibCheck": true, - "types": ["node", "jest"], - "lib": ["es2019"], + "types": [ + "node", + "jest" + ], + "lib": [ + "es2019" + ], "declaration": true, "resolveJsonModule": true, "baseUrl": ".", "rootDir": ".", "allowJs": true, "paths": { - "@nrwl/tao": ["packages/tao"], - "@nrwl/tao/*": ["packages/tao/*"], - "@nx/angular": ["packages/angular"], - "@nx/angular/*": ["packages/angular/*"], - "@nx/cypress": ["packages/cypress"], - "@nx/cypress/*": ["packages/cypress/*"], - "@nx/detox": ["packages/detox"], - "@nx/devkit": ["packages/devkit"], - "@nx/devkit/*": ["packages/devkit/*"], - "@nx/docs": ["docs"], - "@nx/docs/*": ["docs/*"], - "@nx/e2e/utils": ["e2e/utils"], - "@nx/esbuild": ["packages/esbuild"], - "@nx/eslint-plugin": ["packages/eslint-plugin/src"], - "@nx/expo": ["packages/expo"], - "@nx/expo/*": ["packages/expo/*"], - "@nx/express": ["packages/express"], - "@nx/graph/ui-components": ["graph/ui-components/src/index.ts"], - "@nx/graph/ui-graph": ["graph/ui-graph/src/index.ts"], - "@nx/graph/ui-tooltips": ["graph/ui-tooltips/src/index.ts"], - "@nx/jest": ["packages/jest"], - "@nx/jest/*": ["packages/jest/*"], - "@nx/js": ["packages/js/src"], - "@nx/js/*": ["packages/js/*"], - "@nx/linter": ["packages/linter"], - "@nx/linter/*": ["packages/linter/*"], - "@nx/nest": ["packages/nest"], - "@nx/next": ["packages/next"], - "@nx/next/*": ["packages/next/*"], - "@nx/node": ["packages/node"], - "@nx/node/*": ["packages/node/*"], - "@nx/nx-dev/data-access-ai": ["nx-dev/data-access-ai/src/index.ts"], + "@nrwl/tao": [ + "packages/tao" + ], + "@nrwl/tao/*": [ + "packages/tao/*" + ], + "@nx/angular": [ + "packages/angular" + ], + "@nx/angular/*": [ + "packages/angular/*" + ], + "@nx/cypress": [ + "packages/cypress" + ], + "@nx/cypress/*": [ + "packages/cypress/*" + ], + "@nx/detox": [ + "packages/detox" + ], + "@nx/devkit": [ + "packages/devkit" + ], + "@nx/devkit/*": [ + "packages/devkit/*" + ], + "@nx/docs": [ + "docs" + ], + "@nx/docs/*": [ + "docs/*" + ], + "@nx/e2e/utils": [ + "e2e/utils" + ], + "@nx/esbuild": [ + "packages/esbuild" + ], + "@nx/eslint-plugin": [ + "packages/eslint-plugin/src" + ], + "@nx/expo": [ + "packages/expo" + ], + "@nx/expo/*": [ + "packages/expo/*" + ], + "@nx/express": [ + "packages/express" + ], + "@nx/graph/ui-components": [ + "graph/ui-components/src/index.ts" + ], + "@nx/graph/ui-graph": [ + "graph/ui-graph/src/index.ts" + ], + "@nx/graph/ui-tooltips": [ + "graph/ui-tooltips/src/index.ts" + ], + "@nx/jest": [ + "packages/jest" + ], + "@nx/jest/*": [ + "packages/jest/*" + ], + "@nx/js": [ + "packages/js/src" + ], + "@nx/js/*": [ + "packages/js/*" + ], + "@nx/linter": [ + "packages/linter" + ], + "@nx/linter/*": [ + "packages/linter/*" + ], + "@nx/nest": [ + "packages/nest" + ], + "@nx/next": [ + "packages/next" + ], + "@nx/next/*": [ + "packages/next/*" + ], + "@nx/node": [ + "packages/node" + ], + "@nx/node/*": [ + "packages/node/*" + ], + "@nx/nx-dev/data-access-ai": [ + "nx-dev/data-access-ai/src/index.ts" + ], "@nx/nx-dev/data-access-documents": [ "nx-dev/data-access-documents/src/index.ts" ], "@nx/nx-dev/data-access-documents/node-only": [ "nx-dev/data-access-documents/src/node.index.ts" ], - "@nx/nx-dev/data-access-menu": ["nx-dev/data-access-menu/src/index.ts"], + "@nx/nx-dev/data-access-menu": [ + "nx-dev/data-access-menu/src/index.ts" + ], "@nx/nx-dev/data-access-packages": [ "nx-dev/data-access-packages/src/index.ts" ], "@nx/nx-dev/data-access-packages/node-only": [ "nx-dev/data-access-packages/src/node.index.ts" ], - "@nx/nx-dev/feature-ai": ["nx-dev/feature-ai/src/index.ts"], - "@nx/nx-dev/feature-analytics": ["nx-dev/feature-analytics/src/index.ts"], + "@nx/nx-dev/feature-ai": [ + "nx-dev/feature-ai/src/index.ts" + ], + "@nx/nx-dev/feature-analytics": [ + "nx-dev/feature-analytics/src/index.ts" + ], "@nx/nx-dev/feature-doc-viewer": [ "nx-dev/feature-doc-viewer/src/index.ts" ], @@ -72,46 +147,126 @@ "@nx/nx-dev/feature-package-schema-viewer/*": [ "nx-dev/feature-package-schema-viewer/*" ], - "@nx/nx-dev/feature-search": ["nx-dev/feature-search/src/index.ts"], - "@nx/nx-dev/models-document": ["nx-dev/models-document/src/index.ts"], - "@nx/nx-dev/models-menu": ["nx-dev/models-menu/src/index.ts"], - "@nx/nx-dev/models-package": ["nx-dev/models-package/src/index.ts"], - "@nx/nx-dev/ui-commands": ["nx-dev/ui-commands/src/index.ts"], - "@nx/nx-dev/ui-common": ["nx-dev/ui-common/src/index.ts"], - "@nx/nx-dev/ui-community": ["nx-dev/ui-community/src/index.ts"], - "@nx/nx-dev/ui-conference": ["nx-dev/ui-conference/src/index.ts"], - "@nx/nx-dev/ui-home": ["nx-dev/ui-home/src/index.ts"], - "@nx/nx-dev/ui-markdoc": ["nx-dev/ui-markdoc/src/index.ts"], - "@nx/nx-dev/ui-member-card": ["nx-dev/ui-member-card/src/index.ts"], - "@nx/nx-dev/ui-primitives": ["nx-dev/ui-primitives/src/index.ts"], - "@nx/nx-dev/ui-references": ["nx-dev/ui-references/src/index.ts"], - "@nx/nx-dev/ui-sponsor-card": ["nx-dev/ui-sponsor-card/src/index.ts"], - "@nx/nx-dev/ui-theme": ["nx-dev/ui-theme/src/index.ts"], - "@nx/playwright": ["packages/playwright/index.ts"], - "@nx/plugin": ["packages/plugin"], - "@nx/plugin/*": ["packages/plugin/*"], - "@nx/react": ["packages/react"], - "@nx/react-native": ["packages/react-native"], - "@nx/react-native/*": ["packages/react-native/*"], - "@nx/react/*": ["packages/react/*"], - "@nx/rollup": ["packages/rollup"], - "@nx/rollup/*": ["packages/rollup/*"], - "@nx/storybook": ["packages/storybook"], - "@nx/storybook/*": ["packages/storybook/*"], - "@nx/typedoc-theme": ["typedoc-theme/src/index.ts"], - "@nx/vite": ["packages/vite"], - "@nx/vite/*": ["packages/vite/*"], - "@nx/web": ["packages/web"], - "@nx/web/*": ["packages/web/*"], - "@nx/webpack": ["packages/webpack"], - "@nx/webpack/*": ["packages/webpack/*"], - "@nx/workspace": ["packages/workspace"], - "@nx/workspace/*": ["packages/workspace/*"], - "@nx/workspace/testing": ["packages/workspace/testing"], - "create-nx-workspace": ["packages/create-nx-workspace/index.ts"], - "create-nx-workspace/*": ["packages/create-nx-workspace/*"], - "nx": ["packages/nx"], - "nx/*": ["packages/nx/*"] + "@nx/nx-dev/feature-search": [ + "nx-dev/feature-search/src/index.ts" + ], + "@nx/nx-dev/models-document": [ + "nx-dev/models-document/src/index.ts" + ], + "@nx/nx-dev/models-menu": [ + "nx-dev/models-menu/src/index.ts" + ], + "@nx/nx-dev/models-package": [ + "nx-dev/models-package/src/index.ts" + ], + "@nx/nx-dev/ui-commands": [ + "nx-dev/ui-commands/src/index.ts" + ], + "@nx/nx-dev/ui-common": [ + "nx-dev/ui-common/src/index.ts" + ], + "@nx/nx-dev/ui-community": [ + "nx-dev/ui-community/src/index.ts" + ], + "@nx/nx-dev/ui-conference": [ + "nx-dev/ui-conference/src/index.ts" + ], + "@nx/nx-dev/ui-home": [ + "nx-dev/ui-home/src/index.ts" + ], + "@nx/nx-dev/ui-markdoc": [ + "nx-dev/ui-markdoc/src/index.ts" + ], + "@nx/nx-dev/ui-member-card": [ + "nx-dev/ui-member-card/src/index.ts" + ], + "@nx/nx-dev/ui-primitives": [ + "nx-dev/ui-primitives/src/index.ts" + ], + "@nx/nx-dev/ui-references": [ + "nx-dev/ui-references/src/index.ts" + ], + "@nx/nx-dev/ui-sponsor-card": [ + "nx-dev/ui-sponsor-card/src/index.ts" + ], + "@nx/nx-dev/ui-theme": [ + "nx-dev/ui-theme/src/index.ts" + ], + "@nx/playwright": [ + "packages/playwright/index.ts" + ], + "@nx/plugin": [ + "packages/plugin" + ], + "@nx/plugin/*": [ + "packages/plugin/*" + ], + "@nx/react": [ + "packages/react" + ], + "@nx/react-native": [ + "packages/react-native" + ], + "@nx/react-native/*": [ + "packages/react-native/*" + ], + "@nx/react/*": [ + "packages/react/*" + ], + "@nx/rollup": [ + "packages/rollup" + ], + "@nx/rollup/*": [ + "packages/rollup/*" + ], + "@nx/storybook": [ + "packages/storybook" + ], + "@nx/storybook/*": [ + "packages/storybook/*" + ], + "@nx/typedoc-theme": [ + "typedoc-theme/src/index.ts" + ], + "@nx/vite": [ + "packages/vite" + ], + "@nx/vite/*": [ + "packages/vite/*" + ], + "@nx/web": [ + "packages/web" + ], + "@nx/web/*": [ + "packages/web/*" + ], + "@nx/webpack": [ + "packages/webpack" + ], + "@nx/webpack/*": [ + "packages/webpack/*" + ], + "@nx/workspace": [ + "packages/workspace" + ], + "@nx/workspace/*": [ + "packages/workspace/*" + ], + "@nx/workspace/testing": [ + "packages/workspace/testing" + ], + "create-nx-workspace": [ + "packages/create-nx-workspace/index.ts" + ], + "create-nx-workspace/*": [ + "packages/create-nx-workspace/*" + ], + "nx": [ + "packages/nx" + ], + "nx/*": [ + "packages/nx/*" + ] } } } From 09b70521e748dd36359b25b0a39c01b0a6adf11b Mon Sep 17 00:00:00 2001 From: Miroslav Jonas Date: Mon, 24 Jul 2023 11:09:34 +0200 Subject: [PATCH 156/262] docs(nx-dev): make recipes to nx section --- docs/generated/manifests/menus.json | 2833 +++++++++++------ docs/generated/manifests/nx.json | 2684 +++++++++++++++- docs/generated/manifests/tags.json | 84 +- docs/map.json | 1070 +++---- docs/shared/migration/migration-angular.md | 8 +- docs/shared/reference/sitemap.md | 187 +- nx-dev/nx-dev/pages/[...segments].tsx | 2 +- nx-dev/nx-dev/pages/recipes/[...segments].tsx | 113 - nx-dev/nx-dev/pages/recipes/index.tsx | 96 - nx-dev/nx-dev/redirect-rules.js | 4 +- .../src/lib/documentation-header.tsx | 9 +- nx-dev/ui-common/src/lib/sidebar.tsx | 8 +- .../generators/generate-manifests.ts | 6 - tsconfig.base.json | 309 +- 14 files changed, 5195 insertions(+), 2218 deletions(-) delete mode 100644 nx-dev/nx-dev/pages/recipes/[...segments].tsx delete mode 100644 nx-dev/nx-dev/pages/recipes/index.tsx diff --git a/docs/generated/manifests/menus.json b/docs/generated/manifests/menus.json index ed74e04b15ec2..da6082ebfcac9 100644 --- a/docs/generated/manifests/menus.json +++ b/docs/generated/manifests/menus.json @@ -1594,19 +1594,753 @@ "disableCollapsible": false }, { - "name": "All Recipes »", + "name": "Recipes", "path": "/recipes", - "id": "all", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "CI Setup", - "path": "/recipes/ci/ci-setup", - "id": "ci-setup", + "id": "recipes", "isExternal": false, - "children": [], + "children": [ + { + "name": "Adopting Nx", + "path": "/recipes/adopting-nx", + "id": "adopting-nx", + "isExternal": false, + "children": [ + { + "name": "NPM/Yarn/PNPM workspaces", + "path": "/recipes/adopting-nx/adding-to-monorepo", + "id": "adding-to-monorepo", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Add to any Project", + "path": "/recipes/adopting-nx/adding-to-existing-project", + "id": "adding-to-existing-project", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Nx and Lerna", + "path": "/recipes/adopting-nx/lerna-and-nx", + "id": "lerna-and-nx", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Preserving Git Histories", + "path": "/recipes/adopting-nx/preserving-git-histories", + "id": "preserving-git-histories", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Manual migration", + "path": "/recipes/adopting-nx/manual", + "id": "manual", + "isExternal": false, + "children": [], + "disableCollapsible": false + } + ], + "disableCollapsible": false + }, + { + "name": "Angular", + "path": "/recipes/angular", + "id": "angular", + "isExternal": false, + "children": [ + { + "name": "Migration", + "path": "/recipes/angular/migration", + "id": "migration", + "isExternal": false, + "children": [ + { + "name": "Migrating from Angular CLI", + "path": "/recipes/angular/migration/angular", + "id": "angular", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Migrating From Multiple Angular CLI Repos", + "path": "/recipes/angular/migration/angular-multiple", + "id": "angular-multiple", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Migrating Angular Application manually", + "path": "/recipes/angular/migration/angular-manual", + "id": "angular-manual", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Migrating from AngularJS", + "path": "/recipes/angular/migration/angularjs", + "id": "angularjs", + "isExternal": false, + "children": [], + "disableCollapsible": false + } + ], + "disableCollapsible": false + }, + { + "name": "Use Environment Variables in Angular", + "path": "/recipes/angular/use-environment-variables-in-angular", + "id": "use-environment-variables-in-angular", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Using Tailwind CSS with Angular projects", + "path": "/recipes/angular/using-tailwind-css-with-angular-projects", + "id": "using-tailwind-css-with-angular-projects", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Setup Module Federation with SSR for Angular", + "path": "/recipes/angular/module-federation-with-ssr", + "id": "module-federation-with-ssr", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Advanced Micro Frontends with Angular using Dynamic Federation", + "path": "/recipes/angular/dynamic-module-federation-with-angular", + "id": "dynamic-module-federation-with-angular", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Setup incremental builds for Angular applications", + "path": "/recipes/angular/setup-incremental-builds-angular", + "id": "setup-incremental-builds-angular", + "isExternal": false, + "children": [], + "disableCollapsible": false + } + ], + "disableCollapsible": false + }, + { + "name": "React", + "path": "/recipes/react", + "id": "react", + "isExternal": false, + "children": [ + { + "name": "Migrating from CRA", + "path": "/recipes/react/migration-cra", + "id": "migration-cra", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "React 18 Migration", + "path": "/recipes/react/react-18", + "id": "react-18", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "React Native with Nx", + "path": "/recipes/react/react-native", + "id": "react-native", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Remix with Nx", + "path": "/recipes/react/remix", + "id": "remix", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Use Environment Variables in React", + "path": "/recipes/react/use-environment-variables-in-react", + "id": "use-environment-variables-in-react", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Using Tailwind CSS in React", + "path": "/recipes/react/using-tailwind-css-in-react", + "id": "using-tailwind-css-in-react", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Adding Images, Fonts, and Files", + "path": "/recipes/react/adding-assets-react", + "id": "adding-assets-react", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Setup Module Federation with SSR for React", + "path": "/recipes/react/module-federation-with-ssr", + "id": "module-federation-with-ssr", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Deploying Next.js applications to Vercel", + "path": "/recipes/react/deploy-nextjs-to-vercel", + "id": "deploy-nextjs-to-vercel", + "isExternal": false, + "children": [], + "disableCollapsible": false + } + ], + "disableCollapsible": false + }, + { + "name": "Node", + "path": "/recipes/node", + "id": "node", + "isExternal": false, + "children": [ + { + "name": "Deploying a Node App to Fly.io", + "path": "/recipes/node/node-server-fly-io", + "id": "node-server-fly-io", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Add and Deploy Netlify Edge Functions with Node", + "path": "/recipes/node/node-serverless-functions-netlify", + "id": "node-serverless-functions-netlify", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Deploying AWS lambda in Node.js", + "path": "/recipes/node/node-aws-lambda", + "id": "node-aws-lambda", + "isExternal": false, + "children": [], + "disableCollapsible": false + } + ], + "disableCollapsible": false + }, + { + "name": "Storybook", + "path": "/recipes/storybook", + "id": "storybook", + "isExternal": false, + "children": [ + { + "name": "One main Storybook instance for all projects", + "path": "/recipes/storybook/one-storybook-for-all", + "id": "one-storybook-for-all", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "One Storybook instance per scope", + "path": "/recipes/storybook/one-storybook-per-scope", + "id": "one-storybook-per-scope", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "One main Storybook instance using Storybook Composition", + "path": "/recipes/storybook/one-storybook-with-composition", + "id": "one-storybook-with-composition", + "isExternal": false, + "children": [], + "disableCollapsible": false + } + ], + "disableCollapsible": false + }, + { + "name": "Enforce Module Boundaries", + "path": "/recipes/enforce-module-boundaries", + "id": "enforce-module-boundaries", + "isExternal": false, + "children": [ + { + "name": "Ban Dependencies with Certain Tags", + "path": "/recipes/enforce-module-boundaries/ban-dependencies-with-tags", + "id": "ban-dependencies-with-tags", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Tag in Multiple Dimensions", + "path": "/recipes/enforce-module-boundaries/tag-multiple-dimensions", + "id": "tag-multiple-dimensions", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Ban External Imports", + "path": "/recipes/enforce-module-boundaries/ban-external-imports", + "id": "ban-external-imports", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Tags Allow List", + "path": "/recipes/enforce-module-boundaries/tags-allow-list", + "id": "tags-allow-list", + "isExternal": false, + "children": [], + "disableCollapsible": false + } + ], + "disableCollapsible": false + }, + { + "name": "CI", + "path": "/recipes/ci", + "id": "ci", + "isExternal": false, + "children": [ + { + "name": "CI Setup", + "path": "/recipes/ci/ci-setup", + "id": "ci-setup", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Prepare applications for deployment via CI", + "path": "/recipes/ci/ci-deployment", + "id": "ci-deployment", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Setting up Azure Pipelines", + "path": "/recipes/ci/monorepo-ci-azure", + "id": "monorepo-ci-azure", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Setting up CircleCI", + "path": "/recipes/ci/monorepo-ci-circle-ci", + "id": "monorepo-ci-circle-ci", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Setting up GitHub Actions", + "path": "/recipes/ci/monorepo-ci-github-actions", + "id": "monorepo-ci-github-actions", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Setting up Jenkins", + "path": "/recipes/ci/monorepo-ci-jenkins", + "id": "monorepo-ci-jenkins", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Setting up GitLab", + "path": "/recipes/ci/monorepo-ci-gitlab", + "id": "monorepo-ci-gitlab", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Setting up Bitbucket", + "path": "/recipes/ci/monorepo-ci-bitbucket-pipelines", + "id": "monorepo-ci-bitbucket-pipelines", + "isExternal": false, + "children": [], + "disableCollapsible": false + } + ], + "disableCollapsible": false + }, + { + "name": "Nx Console", + "path": "/recipes/nx-console", + "id": "nx-console", + "isExternal": false, + "children": [ + { + "name": "Telemetry", + "path": "/recipes/nx-console/console-telemetry", + "id": "console-telemetry", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Generate Command", + "path": "/recipes/nx-console/console-generate-command", + "id": "console-generate-command", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Run Command", + "path": "/recipes/nx-console/console-run-command", + "id": "console-run-command", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Add Dependency Command", + "path": "/recipes/nx-console/console-add-dependency-command", + "id": "console-add-dependency-command", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Project Pane", + "path": "/recipes/nx-console/console-project-pane", + "id": "console-project-pane", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Keyboard Shortcuts", + "path": "/recipes/nx-console/console-shortcuts", + "id": "console-shortcuts", + "isExternal": false, + "children": [], + "disableCollapsible": false + } + ], + "disableCollapsible": false + }, + { + "name": "Troubleshooting", + "path": "/recipes/troubleshooting", + "id": "troubleshooting", + "isExternal": false, + "children": [ + { + "name": "Resolve Circular Dependencies", + "path": "/recipes/troubleshooting/resolve-circular-dependencies", + "id": "resolve-circular-dependencies", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Troubleshooting Nx Install Issues", + "path": "/recipes/troubleshooting/troubleshoot-nx-install-issues", + "id": "troubleshoot-nx-install-issues", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Troubleshoot Cache Misses", + "path": "/recipes/troubleshooting/troubleshoot-cache-misses", + "id": "troubleshoot-cache-misses", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Unknown Local Cache Error", + "path": "/recipes/troubleshooting/unknown-local-cache", + "id": "unknown-local-cache", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Profiling Build Performance", + "path": "/recipes/troubleshooting/performance-profiling", + "id": "performance-profiling", + "isExternal": false, + "children": [], + "disableCollapsible": false + } + ], + "disableCollapsible": false + }, + { + "name": "Tips and tricks", + "path": "/recipes/tips-n-tricks", + "id": "tips-n-tricks", + "isExternal": false, + "children": [ + { + "name": "Configuring ESLint with Typescript", + "path": "/recipes/tips-n-tricks/eslint", + "id": "eslint", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Define Environment Variables", + "path": "/recipes/tips-n-tricks/define-environment-variables", + "id": "define-environment-variables", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Configuring Browser Support", + "path": "/recipes/tips-n-tricks/browser-support", + "id": "browser-support", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Include Assets in Build", + "path": "/recipes/tips-n-tricks/include-assets-in-build", + "id": "include-assets-in-build", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Include All package.json Files as Projects", + "path": "/recipes/tips-n-tricks/include-all-packagejson", + "id": "include-all-packagejson", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Identify Dependencies Between Folders", + "path": "/recipes/tips-n-tricks/identify-dependencies-between-folders", + "id": "identify-dependencies-between-folders", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Run Root-Level NPM Scripts with Nx", + "path": "/recipes/tips-n-tricks/root-level-scripts", + "id": "root-level-scripts", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Disable Graph Links Created from Analyzing Source Files", + "path": "/recipes/tips-n-tricks/analyze-source-files", + "id": "analyze-source-files", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Workspace Watching", + "path": "/recipes/tips-n-tricks/workspace-watching", + "id": "workspace-watching", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Convert from a Standalone Repository to an Integrated Repository", + "path": "/recipes/tips-n-tricks/standalone-to-integrated", + "id": "standalone-to-integrated", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Use JavaScript instead TypeScript", + "path": "/recipes/tips-n-tricks/js-and-ts", + "id": "js-and-ts", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Altering Migration Process", + "path": "/recipes/tips-n-tricks/advanced-update", + "id": "advanced-update", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Running Custom Commands", + "path": "/recipes/tips-n-tricks/run-commands-executor", + "id": "run-commands-executor", + "isExternal": false, + "children": [], + "disableCollapsible": false + } + ], + "disableCollapsible": false + }, + { + "name": "Other", + "path": "/recipes/other", + "id": "other", + "isExternal": false, + "children": [ + { + "name": "Serverless deployment with Deno Deploy", + "path": "/recipes/other/deno-deploy", + "id": "deno-deploy", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Add and Deploy Netlify Edge Functions with Deno", + "path": "/recipes/other/deno-netlify-functions", + "id": "deno-netlify-functions", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Rescope Packages from @nrwl to @nx", + "path": "/recipes/other/rescope", + "id": "rescope", + "isExternal": false, + "children": [], + "disableCollapsible": false + } + ], + "disableCollapsible": false + }, + { + "name": "Example Repos", + "path": "/recipes/example-repos", + "id": "example-repos", + "isExternal": false, + "children": [ + { + "name": "Powering Up React Development With Nx", + "path": "/recipes/example-repos/react-nx", + "id": "react-nx", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Using Apollo GraphQL", + "path": "/recipes/example-repos/apollo-react", + "id": "apollo-react", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Using Prisma with NestJS", + "path": "/recipes/example-repos/nestjs-prisma", + "id": "nestjs-prisma", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Using Mongo with Fastify", + "path": "/recipes/example-repos/mongo-fastify", + "id": "mongo-fastify", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Using Redis with Fastify", + "path": "/recipes/example-repos/redis-fastify", + "id": "redis-fastify", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Using Postgres with Fastify", + "path": "/recipes/example-repos/postgres-fastify", + "id": "postgres-fastify", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Using PlanetScale with Serverless Fastify", + "path": "/recipes/example-repos/serverless-fastify-planetscale", + "id": "serverless-fastify-planetscale", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Large Repo and Caching", + "path": "/recipes/example-repos/caching", + "id": "caching", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Large Repo and DTE", + "path": "/recipes/example-repos/dte", + "id": "dte", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Nx Micro-Frontend Example", + "path": "/recipes/example-repos/mfe", + "id": "mfe", + "isExternal": false, + "children": [], + "disableCollapsible": false + } + ], + "disableCollapsible": false + } + ], "disableCollapsible": false }, { @@ -1614,59 +2348,43 @@ "path": "/recipes/adopting-nx", "id": "adopting-nx", "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Reference", - "path": "/reference", - "id": "reference", - "isExternal": false, "children": [ { - "name": "Commands", - "path": "/reference/commands", - "id": "commands", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "nx.json", - "path": "/reference/nx-json", - "id": "nx-json", + "name": "NPM/Yarn/PNPM workspaces", + "path": "/recipes/adopting-nx/adding-to-monorepo", + "id": "adding-to-monorepo", "isExternal": false, "children": [], "disableCollapsible": false - }, - { - "name": "Project Configuration", - "path": "/reference/project-configuration", - "id": "project-configuration", + }, + { + "name": "Add to any Project", + "path": "/recipes/adopting-nx/adding-to-existing-project", + "id": "adding-to-existing-project", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": ".nxignore", - "path": "/reference/nxignore", - "id": "nxignore", + "name": "Nx and Lerna", + "path": "/recipes/adopting-nx/lerna-and-nx", + "id": "lerna-and-nx", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Environment Variables", - "path": "/reference/environment-variables", - "id": "environment-variables", + "name": "Preserving Git Histories", + "path": "/recipes/adopting-nx/preserving-git-histories", + "id": "preserving-git-histories", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Glossary", - "path": "/reference/glossary", - "id": "glossary", + "name": "Manual migration", + "path": "/recipes/adopting-nx/manual", + "id": "manual", "isExternal": false, "children": [], "disableCollapsible": false @@ -1675,281 +2393,322 @@ "disableCollapsible": false }, { - "name": "Commands", - "path": "/reference/commands", - "id": "commands", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "nx.json", - "path": "/reference/nx-json", - "id": "nx-json", + "name": "NPM/Yarn/PNPM workspaces", + "path": "/recipes/adopting-nx/adding-to-monorepo", + "id": "adding-to-monorepo", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Project Configuration", - "path": "/reference/project-configuration", - "id": "project-configuration", + "name": "Add to any Project", + "path": "/recipes/adopting-nx/adding-to-existing-project", + "id": "adding-to-existing-project", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": ".nxignore", - "path": "/reference/nxignore", - "id": "nxignore", + "name": "Nx and Lerna", + "path": "/recipes/adopting-nx/lerna-and-nx", + "id": "lerna-and-nx", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Environment Variables", - "path": "/reference/environment-variables", - "id": "environment-variables", + "name": "Preserving Git Histories", + "path": "/recipes/adopting-nx/preserving-git-histories", + "id": "preserving-git-histories", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Glossary", - "path": "/reference/glossary", - "id": "glossary", + "name": "Manual migration", + "path": "/recipes/adopting-nx/manual", + "id": "manual", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Deprecated", - "path": "/deprecated", - "id": "deprecated", + "name": "Angular", + "path": "/recipes/angular", + "id": "angular", "isExternal": false, "children": [ { - "name": "workspace.json", - "path": "/deprecated/workspace-json", - "id": "workspace-json", + "name": "Migration", + "path": "/recipes/angular/migration", + "id": "migration", + "isExternal": false, + "children": [ + { + "name": "Migrating from Angular CLI", + "path": "/recipes/angular/migration/angular", + "id": "angular", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Migrating From Multiple Angular CLI Repos", + "path": "/recipes/angular/migration/angular-multiple", + "id": "angular-multiple", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Migrating Angular Application manually", + "path": "/recipes/angular/migration/angular-manual", + "id": "angular-manual", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Migrating from AngularJS", + "path": "/recipes/angular/migration/angularjs", + "id": "angularjs", + "isExternal": false, + "children": [], + "disableCollapsible": false + } + ], + "disableCollapsible": false + }, + { + "name": "Use Environment Variables in Angular", + "path": "/recipes/angular/use-environment-variables-in-angular", + "id": "use-environment-variables-in-angular", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "workspace-lint", - "path": "/deprecated/workspace-lint", - "id": "workspace-lint", + "name": "Using Tailwind CSS with Angular projects", + "path": "/recipes/angular/using-tailwind-css-with-angular-projects", + "id": "using-tailwind-css-with-angular-projects", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Workspace Generators", - "path": "/deprecated/workspace-generators", - "id": "workspace-generators", + "name": "Setup Module Federation with SSR for Angular", + "path": "/recipes/angular/module-federation-with-ssr", + "id": "module-federation-with-ssr", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Workspace Executors", - "path": "/deprecated/workspace-executors", - "id": "workspace-executors", + "name": "Advanced Micro Frontends with Angular using Dynamic Federation", + "path": "/recipes/angular/dynamic-module-federation-with-angular", + "id": "dynamic-module-federation-with-angular", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "defaultCollection", - "path": "/deprecated/default-collection", - "id": "default-collection", + "name": "Setup incremental builds for Angular applications", + "path": "/recipes/angular/setup-incremental-builds-angular", + "id": "setup-incremental-builds-angular", + "isExternal": false, + "children": [], + "disableCollapsible": false + } + ], + "disableCollapsible": false + }, + { + "name": "Migration", + "path": "/recipes/angular/migration", + "id": "migration", + "isExternal": false, + "children": [ + { + "name": "Migrating from Angular CLI", + "path": "/recipes/angular/migration/angular", + "id": "angular", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "runtimeCacheInputs", - "path": "/deprecated/runtime-cache-inputs", - "id": "runtime-cache-inputs", + "name": "Migrating From Multiple Angular CLI Repos", + "path": "/recipes/angular/migration/angular-multiple", + "id": "angular-multiple", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "globalImplicitDependencies", - "path": "/deprecated/global-implicit-dependencies", - "id": "global-implicit-dependencies", + "name": "Migrating Angular Application manually", + "path": "/recipes/angular/migration/angular-manual", + "id": "angular-manual", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Storybook deprecated docs", - "path": "/deprecated/storybook", - "id": "storybook", + "name": "Migrating from AngularJS", + "path": "/recipes/angular/migration/angularjs", + "id": "angularjs", "isExternal": false, - "children": [ - { - "name": "Angular: Information about the Storybook targets", - "path": "/deprecated/storybook/angular-storybook-targets", - "id": "angular-storybook-targets", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Angular: The browserTarget", - "path": "/deprecated/storybook/angular-browser-target", - "id": "angular-browser-target", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Angular: Storybook Migration to webpackFinal", - "path": "/deprecated/storybook/migrate-webpack-final-angular", - "id": "migrate-webpack-final-angular", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Angular: Upgrading to Storybook 6", - "path": "/deprecated/storybook/upgrade-storybook-v6-angular", - "id": "upgrade-storybook-v6-angular", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "React: Storybook Migration to webpackFinal and the Nx Addon", - "path": "/deprecated/storybook/migrate-webpack-final-react", - "id": "migrate-webpack-final-react", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "React: Upgrading to Storybook 6", - "path": "/deprecated/storybook/upgrade-storybook-v6-react", - "id": "upgrade-storybook-v6-react", - "isExternal": false, - "children": [], - "disableCollapsible": false - } - ], + "children": [], "disableCollapsible": false } ], "disableCollapsible": false }, { - "name": "workspace.json", - "path": "/deprecated/workspace-json", - "id": "workspace-json", + "name": "Migrating from Angular CLI", + "path": "/recipes/angular/migration/angular", + "id": "angular", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "workspace-lint", - "path": "/deprecated/workspace-lint", - "id": "workspace-lint", + "name": "Migrating From Multiple Angular CLI Repos", + "path": "/recipes/angular/migration/angular-multiple", + "id": "angular-multiple", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Workspace Generators", - "path": "/deprecated/workspace-generators", - "id": "workspace-generators", + "name": "Migrating Angular Application manually", + "path": "/recipes/angular/migration/angular-manual", + "id": "angular-manual", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Migrating from AngularJS", + "path": "/recipes/angular/migration/angularjs", + "id": "angularjs", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Use Environment Variables in Angular", + "path": "/recipes/angular/use-environment-variables-in-angular", + "id": "use-environment-variables-in-angular", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Workspace Executors", - "path": "/deprecated/workspace-executors", - "id": "workspace-executors", + "name": "Using Tailwind CSS with Angular projects", + "path": "/recipes/angular/using-tailwind-css-with-angular-projects", + "id": "using-tailwind-css-with-angular-projects", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "defaultCollection", - "path": "/deprecated/default-collection", - "id": "default-collection", + "name": "Setup Module Federation with SSR for Angular", + "path": "/recipes/angular/module-federation-with-ssr", + "id": "module-federation-with-ssr", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "runtimeCacheInputs", - "path": "/deprecated/runtime-cache-inputs", - "id": "runtime-cache-inputs", + "name": "Advanced Micro Frontends with Angular using Dynamic Federation", + "path": "/recipes/angular/dynamic-module-federation-with-angular", + "id": "dynamic-module-federation-with-angular", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "globalImplicitDependencies", - "path": "/deprecated/global-implicit-dependencies", - "id": "global-implicit-dependencies", + "name": "Setup incremental builds for Angular applications", + "path": "/recipes/angular/setup-incremental-builds-angular", + "id": "setup-incremental-builds-angular", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Storybook deprecated docs", - "path": "/deprecated/storybook", - "id": "storybook", + "name": "React", + "path": "/recipes/react", + "id": "react", "isExternal": false, "children": [ { - "name": "Angular: Information about the Storybook targets", - "path": "/deprecated/storybook/angular-storybook-targets", - "id": "angular-storybook-targets", + "name": "Migrating from CRA", + "path": "/recipes/react/migration-cra", + "id": "migration-cra", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Angular: The browserTarget", - "path": "/deprecated/storybook/angular-browser-target", - "id": "angular-browser-target", + "name": "React 18 Migration", + "path": "/recipes/react/react-18", + "id": "react-18", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Angular: Storybook Migration to webpackFinal", - "path": "/deprecated/storybook/migrate-webpack-final-angular", - "id": "migrate-webpack-final-angular", + "name": "React Native with Nx", + "path": "/recipes/react/react-native", + "id": "react-native", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Angular: Upgrading to Storybook 6", - "path": "/deprecated/storybook/upgrade-storybook-v6-angular", - "id": "upgrade-storybook-v6-angular", + "name": "Remix with Nx", + "path": "/recipes/react/remix", + "id": "remix", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "React: Storybook Migration to webpackFinal and the Nx Addon", - "path": "/deprecated/storybook/migrate-webpack-final-react", - "id": "migrate-webpack-final-react", + "name": "Use Environment Variables in React", + "path": "/recipes/react/use-environment-variables-in-react", + "id": "use-environment-variables-in-react", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "React: Upgrading to Storybook 6", - "path": "/deprecated/storybook/upgrade-storybook-v6-react", - "id": "upgrade-storybook-v6-react", + "name": "Using Tailwind CSS in React", + "path": "/recipes/react/using-tailwind-css-in-react", + "id": "using-tailwind-css-in-react", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Adding Images, Fonts, and Files", + "path": "/recipes/react/adding-assets-react", + "id": "adding-assets-react", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Setup Module Federation with SSR for React", + "path": "/recipes/react/module-federation-with-ssr", + "id": "module-federation-with-ssr", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Deploying Next.js applications to Vercel", + "path": "/recipes/react/deploy-nextjs-to-vercel", + "id": "deploy-nextjs-to-vercel", "isExternal": false, "children": [], "disableCollapsible": false @@ -1958,127 +2717,160 @@ "disableCollapsible": false }, { - "name": "Angular: Information about the Storybook targets", - "path": "/deprecated/storybook/angular-storybook-targets", - "id": "angular-storybook-targets", + "name": "Migrating from CRA", + "path": "/recipes/react/migration-cra", + "id": "migration-cra", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Angular: The browserTarget", - "path": "/deprecated/storybook/angular-browser-target", - "id": "angular-browser-target", + "name": "React 18 Migration", + "path": "/recipes/react/react-18", + "id": "react-18", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Angular: Storybook Migration to webpackFinal", - "path": "/deprecated/storybook/migrate-webpack-final-angular", - "id": "migrate-webpack-final-angular", + "name": "React Native with Nx", + "path": "/recipes/react/react-native", + "id": "react-native", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Angular: Upgrading to Storybook 6", - "path": "/deprecated/storybook/upgrade-storybook-v6-angular", - "id": "upgrade-storybook-v6-angular", + "name": "Remix with Nx", + "path": "/recipes/react/remix", + "id": "remix", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "React: Storybook Migration to webpackFinal and the Nx Addon", - "path": "/deprecated/storybook/migrate-webpack-final-react", - "id": "migrate-webpack-final-react", + "name": "Use Environment Variables in React", + "path": "/recipes/react/use-environment-variables-in-react", + "id": "use-environment-variables-in-react", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "React: Upgrading to Storybook 6", - "path": "/deprecated/storybook/upgrade-storybook-v6-react", - "id": "upgrade-storybook-v6-react", + "name": "Using Tailwind CSS in React", + "path": "/recipes/react/using-tailwind-css-in-react", + "id": "using-tailwind-css-in-react", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "See Also", - "path": "/see-also", - "id": "see-also", + "name": "Adding Images, Fonts, and Files", + "path": "/recipes/react/adding-assets-react", + "id": "adding-assets-react", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Setup Module Federation with SSR for React", + "path": "/recipes/react/module-federation-with-ssr", + "id": "module-federation-with-ssr", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Deploying Next.js applications to Vercel", + "path": "/recipes/react/deploy-nextjs-to-vercel", + "id": "deploy-nextjs-to-vercel", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Node", + "path": "/recipes/node", + "id": "node", "isExternal": false, "children": [ { - "name": "Nx Cloud Documentation", - "path": "/nx-cloud/intro/what-is-nx-cloud", - "id": "nx-cloud-documentation", - "isExternal": true, - "children": [], - "disableCollapsible": false - }, - { - "name": "Nx Cloud Main Site", - "path": "https://nx.app", - "id": "nx-cloud-main-site", - "isExternal": true, - "children": [], - "disableCollapsible": false - }, - { - "name": "--skip-nx-cache flag", - "path": "/packages/nx/documents/affected#skip-nx-cache", - "id": "skip-nx-cache-flag", - "isExternal": true, - "children": [], - "disableCollapsible": false - }, - { - "name": "tasks-runner-options property", - "path": "/reference/nx-json#tasks-runner-options", - "id": "tasks-runner-options-property", - "isExternal": true, + "name": "Deploying a Node App to Fly.io", + "path": "/recipes/node/node-server-fly-io", + "id": "node-server-fly-io", + "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "nx.json reference: inputs and namedInputs", - "path": "/reference/nx-json#inputs-&-namedinputs", - "id": "nxjson-inputs", - "isExternal": true, + "name": "Add and Deploy Netlify Edge Functions with Node", + "path": "/recipes/node/node-serverless-functions-netlify", + "id": "node-serverless-functions-netlify", + "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Project Configuration reference: inputs and namedInputs", - "path": "/reference/project-configuration#inputs-&-namedinputs", - "id": "project-config-inputs", - "isExternal": true, + "name": "Deploying AWS lambda in Node.js", + "path": "/recipes/node/node-aws-lambda", + "id": "node-aws-lambda", + "isExternal": false, "children": [], "disableCollapsible": false - }, + } + ], + "disableCollapsible": false + }, + { + "name": "Deploying a Node App to Fly.io", + "path": "/recipes/node/node-server-fly-io", + "id": "node-server-fly-io", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Add and Deploy Netlify Edge Functions with Node", + "path": "/recipes/node/node-serverless-functions-netlify", + "id": "node-serverless-functions-netlify", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Deploying AWS lambda in Node.js", + "path": "/recipes/node/node-aws-lambda", + "id": "node-aws-lambda", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Storybook", + "path": "/recipes/storybook", + "id": "storybook", + "isExternal": false, + "children": [ { - "name": "nx.json workspaceLayout property", - "path": "/reference/nx-json#workspace-layout", - "id": "nxjson-workspaceLayout", - "isExternal": true, + "name": "One main Storybook instance for all projects", + "path": "/recipes/storybook/one-storybook-for-all", + "id": "one-storybook-for-all", + "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "nx.json generator defaults", - "path": "/reference/nx-json#generators", - "id": "nxjson-generator-defaults", - "isExternal": true, + "name": "One Storybook instance per scope", + "path": "/recipes/storybook/one-storybook-per-scope", + "id": "one-storybook-per-scope", + "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Site Map", - "path": "/see-also/sitemap", - "id": "sitemap", + "name": "One main Storybook instance using Storybook Composition", + "path": "/recipes/storybook/one-storybook-with-composition", + "id": "one-storybook-with-composition", "isExternal": false, "children": [], "disableCollapsible": false @@ -2087,116 +2879,168 @@ "disableCollapsible": false }, { - "name": "Nx Cloud Documentation", - "path": "/nx-cloud/intro/what-is-nx-cloud", - "id": "nx-cloud-documentation", - "isExternal": true, + "name": "One main Storybook instance for all projects", + "path": "/recipes/storybook/one-storybook-for-all", + "id": "one-storybook-for-all", + "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "--skip-nx-cache flag", - "path": "/packages/nx/documents/affected#skip-nx-cache", - "id": "skip-nx-cache-flag", - "isExternal": true, + "name": "One Storybook instance per scope", + "path": "/recipes/storybook/one-storybook-per-scope", + "id": "one-storybook-per-scope", + "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "tasks-runner-options property", - "path": "/reference/nx-json#tasks-runner-options", - "id": "tasks-runner-options-property", - "isExternal": true, + "name": "One main Storybook instance using Storybook Composition", + "path": "/recipes/storybook/one-storybook-with-composition", + "id": "one-storybook-with-composition", + "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "nx.json reference: inputs and namedInputs", - "path": "/reference/nx-json#inputs-&-namedinputs", - "id": "nxjson-inputs", - "isExternal": true, - "children": [], + "name": "Enforce Module Boundaries", + "path": "/recipes/enforce-module-boundaries", + "id": "enforce-module-boundaries", + "isExternal": false, + "children": [ + { + "name": "Ban Dependencies with Certain Tags", + "path": "/recipes/enforce-module-boundaries/ban-dependencies-with-tags", + "id": "ban-dependencies-with-tags", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Tag in Multiple Dimensions", + "path": "/recipes/enforce-module-boundaries/tag-multiple-dimensions", + "id": "tag-multiple-dimensions", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Ban External Imports", + "path": "/recipes/enforce-module-boundaries/ban-external-imports", + "id": "ban-external-imports", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Tags Allow List", + "path": "/recipes/enforce-module-boundaries/tags-allow-list", + "id": "tags-allow-list", + "isExternal": false, + "children": [], + "disableCollapsible": false + } + ], "disableCollapsible": false }, { - "name": "Project Configuration reference: inputs and namedInputs", - "path": "/reference/project-configuration#inputs-&-namedinputs", - "id": "project-config-inputs", - "isExternal": true, + "name": "Ban Dependencies with Certain Tags", + "path": "/recipes/enforce-module-boundaries/ban-dependencies-with-tags", + "id": "ban-dependencies-with-tags", + "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "nx.json workspaceLayout property", - "path": "/reference/nx-json#workspace-layout", - "id": "nxjson-workspaceLayout", - "isExternal": true, + "name": "Tag in Multiple Dimensions", + "path": "/recipes/enforce-module-boundaries/tag-multiple-dimensions", + "id": "tag-multiple-dimensions", + "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "nx.json generator defaults", - "path": "/reference/nx-json#generators", - "id": "nxjson-generator-defaults", - "isExternal": true, + "name": "Ban External Imports", + "path": "/recipes/enforce-module-boundaries/ban-external-imports", + "id": "ban-external-imports", + "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Site Map", - "path": "/see-also/sitemap", - "id": "sitemap", + "name": "Tags Allow List", + "path": "/recipes/enforce-module-boundaries/tags-allow-list", + "id": "tags-allow-list", "isExternal": false, "children": [], "disableCollapsible": false - } - ] - }, - { - "id": "recipes", - "menu": [ + }, { - "name": "Migrating to Nx", - "path": "/recipes/adopting-nx", - "id": "adopting-nx", + "name": "CI", + "path": "/recipes/ci", + "id": "ci", "isExternal": false, "children": [ { - "name": "NPM/Yarn/PNPM workspaces", - "path": "/recipes/adopting-nx/adding-to-monorepo", - "id": "adding-to-monorepo", + "name": "CI Setup", + "path": "/recipes/ci/ci-setup", + "id": "ci-setup", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Add to any Project", - "path": "/recipes/adopting-nx/adding-to-existing-project", - "id": "adding-to-existing-project", + "name": "Prepare applications for deployment via CI", + "path": "/recipes/ci/ci-deployment", + "id": "ci-deployment", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Nx and Lerna", - "path": "/recipes/adopting-nx/lerna-and-nx", - "id": "lerna-and-nx", + "name": "Setting up Azure Pipelines", + "path": "/recipes/ci/monorepo-ci-azure", + "id": "monorepo-ci-azure", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Preserving Git Histories", - "path": "/recipes/adopting-nx/preserving-git-histories", - "id": "preserving-git-histories", + "name": "Setting up CircleCI", + "path": "/recipes/ci/monorepo-ci-circle-ci", + "id": "monorepo-ci-circle-ci", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Manual migration", - "path": "/recipes/adopting-nx/manual", - "id": "manual", + "name": "Setting up GitHub Actions", + "path": "/recipes/ci/monorepo-ci-github-actions", + "id": "monorepo-ci-github-actions", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Setting up Jenkins", + "path": "/recipes/ci/monorepo-ci-jenkins", + "id": "monorepo-ci-jenkins", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Setting up GitLab", + "path": "/recipes/ci/monorepo-ci-gitlab", + "id": "monorepo-ci-gitlab", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Setting up Bitbucket", + "path": "/recipes/ci/monorepo-ci-bitbucket-pipelines", + "id": "monorepo-ci-bitbucket-pipelines", "isExternal": false, "children": [], "disableCollapsible": false @@ -2205,128 +3049,119 @@ "disableCollapsible": false }, { - "name": "NPM/Yarn/PNPM workspaces", - "path": "/recipes/adopting-nx/adding-to-monorepo", - "id": "adding-to-monorepo", + "name": "CI Setup", + "path": "/recipes/ci/ci-setup", + "id": "ci-setup", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Add to any Project", - "path": "/recipes/adopting-nx/adding-to-existing-project", - "id": "adding-to-existing-project", + "name": "Prepare applications for deployment via CI", + "path": "/recipes/ci/ci-deployment", + "id": "ci-deployment", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Nx and Lerna", - "path": "/recipes/adopting-nx/lerna-and-nx", - "id": "lerna-and-nx", + "name": "Setting up Azure Pipelines", + "path": "/recipes/ci/monorepo-ci-azure", + "id": "monorepo-ci-azure", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Preserving Git Histories", - "path": "/recipes/adopting-nx/preserving-git-histories", - "id": "preserving-git-histories", + "name": "Setting up CircleCI", + "path": "/recipes/ci/monorepo-ci-circle-ci", + "id": "monorepo-ci-circle-ci", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Manual migration", - "path": "/recipes/adopting-nx/manual", - "id": "manual", + "name": "Setting up GitHub Actions", + "path": "/recipes/ci/monorepo-ci-github-actions", + "id": "monorepo-ci-github-actions", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Angular", - "path": "/recipes/angular", - "id": "angular", + "name": "Setting up Jenkins", + "path": "/recipes/ci/monorepo-ci-jenkins", + "id": "monorepo-ci-jenkins", "isExternal": false, - "children": [ - { - "name": "Migration", - "path": "/recipes/angular/migration", - "id": "migration", - "isExternal": false, - "children": [ - { - "name": "Migrating from Angular CLI", - "path": "/recipes/angular/migration/angular", - "id": "angular", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Migrating From Multiple Angular CLI Repos", - "path": "/recipes/angular/migration/angular-multiple", - "id": "angular-multiple", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Migrating Angular Application manually", - "path": "/recipes/angular/migration/angular-manual", - "id": "angular-manual", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Migrating from AngularJS", - "path": "/recipes/angular/migration/angularjs", - "id": "angularjs", - "isExternal": false, - "children": [], - "disableCollapsible": false - } - ], + "children": [], + "disableCollapsible": false + }, + { + "name": "Setting up GitLab", + "path": "/recipes/ci/monorepo-ci-gitlab", + "id": "monorepo-ci-gitlab", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Setting up Bitbucket", + "path": "/recipes/ci/monorepo-ci-bitbucket-pipelines", + "id": "monorepo-ci-bitbucket-pipelines", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Nx Console", + "path": "/recipes/nx-console", + "id": "nx-console", + "isExternal": false, + "children": [ + { + "name": "Telemetry", + "path": "/recipes/nx-console/console-telemetry", + "id": "console-telemetry", + "isExternal": false, + "children": [], "disableCollapsible": false }, { - "name": "Use Environment Variables in Angular", - "path": "/recipes/angular/use-environment-variables-in-angular", - "id": "use-environment-variables-in-angular", + "name": "Generate Command", + "path": "/recipes/nx-console/console-generate-command", + "id": "console-generate-command", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Using Tailwind CSS with Angular projects", - "path": "/recipes/angular/using-tailwind-css-with-angular-projects", - "id": "using-tailwind-css-with-angular-projects", + "name": "Run Command", + "path": "/recipes/nx-console/console-run-command", + "id": "console-run-command", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Setup Module Federation with SSR for Angular", - "path": "/recipes/angular/module-federation-with-ssr", - "id": "module-federation-with-ssr", + "name": "Add Dependency Command", + "path": "/recipes/nx-console/console-add-dependency-command", + "id": "console-add-dependency-command", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Advanced Micro Frontends with Angular using Dynamic Federation", - "path": "/recipes/angular/dynamic-module-federation-with-angular", - "id": "dynamic-module-federation-with-angular", + "name": "Project Pane", + "path": "/recipes/nx-console/console-project-pane", + "id": "console-project-pane", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Setup incremental builds for Angular applications", - "path": "/recipes/angular/setup-incremental-builds-angular", - "id": "setup-incremental-builds-angular", + "name": "Keyboard Shortcuts", + "path": "/recipes/nx-console/console-shortcuts", + "id": "console-shortcuts", "isExternal": false, "children": [], "disableCollapsible": false @@ -2335,39 +3170,95 @@ "disableCollapsible": false }, { - "name": "Migration", - "path": "/recipes/angular/migration", - "id": "migration", + "name": "Telemetry", + "path": "/recipes/nx-console/console-telemetry", + "id": "console-telemetry", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Generate Command", + "path": "/recipes/nx-console/console-generate-command", + "id": "console-generate-command", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Run Command", + "path": "/recipes/nx-console/console-run-command", + "id": "console-run-command", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Add Dependency Command", + "path": "/recipes/nx-console/console-add-dependency-command", + "id": "console-add-dependency-command", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Project Pane", + "path": "/recipes/nx-console/console-project-pane", + "id": "console-project-pane", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Keyboard Shortcuts", + "path": "/recipes/nx-console/console-shortcuts", + "id": "console-shortcuts", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Troubleshooting", + "path": "/recipes/troubleshooting", + "id": "troubleshooting", "isExternal": false, "children": [ { - "name": "Migrating from Angular CLI", - "path": "/recipes/angular/migration/angular", - "id": "angular", + "name": "Resolve Circular Dependencies", + "path": "/recipes/troubleshooting/resolve-circular-dependencies", + "id": "resolve-circular-dependencies", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Migrating From Multiple Angular CLI Repos", - "path": "/recipes/angular/migration/angular-multiple", - "id": "angular-multiple", + "name": "Troubleshooting Nx Install Issues", + "path": "/recipes/troubleshooting/troubleshoot-nx-install-issues", + "id": "troubleshoot-nx-install-issues", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Migrating Angular Application manually", - "path": "/recipes/angular/migration/angular-manual", - "id": "angular-manual", + "name": "Troubleshoot Cache Misses", + "path": "/recipes/troubleshooting/troubleshoot-cache-misses", + "id": "troubleshoot-cache-misses", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Migrating from AngularJS", - "path": "/recipes/angular/migration/angularjs", - "id": "angularjs", + "name": "Unknown Local Cache Error", + "path": "/recipes/troubleshooting/unknown-local-cache", + "id": "unknown-local-cache", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Profiling Build Performance", + "path": "/recipes/troubleshooting/performance-profiling", + "id": "performance-profiling", "isExternal": false, "children": [], "disableCollapsible": false @@ -2376,151 +3267,151 @@ "disableCollapsible": false }, { - "name": "Migrating from Angular CLI", - "path": "/recipes/angular/migration/angular", - "id": "angular", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Migrating From Multiple Angular CLI Repos", - "path": "/recipes/angular/migration/angular-multiple", - "id": "angular-multiple", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Migrating Angular Application manually", - "path": "/recipes/angular/migration/angular-manual", - "id": "angular-manual", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Migrating from AngularJS", - "path": "/recipes/angular/migration/angularjs", - "id": "angularjs", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Use Environment Variables in Angular", - "path": "/recipes/angular/use-environment-variables-in-angular", - "id": "use-environment-variables-in-angular", + "name": "Resolve Circular Dependencies", + "path": "/recipes/troubleshooting/resolve-circular-dependencies", + "id": "resolve-circular-dependencies", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Using Tailwind CSS with Angular projects", - "path": "/recipes/angular/using-tailwind-css-with-angular-projects", - "id": "using-tailwind-css-with-angular-projects", + "name": "Troubleshooting Nx Install Issues", + "path": "/recipes/troubleshooting/troubleshoot-nx-install-issues", + "id": "troubleshoot-nx-install-issues", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Setup Module Federation with SSR for Angular", - "path": "/recipes/angular/module-federation-with-ssr", - "id": "module-federation-with-ssr", + "name": "Troubleshoot Cache Misses", + "path": "/recipes/troubleshooting/troubleshoot-cache-misses", + "id": "troubleshoot-cache-misses", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Advanced Micro Frontends with Angular using Dynamic Federation", - "path": "/recipes/angular/dynamic-module-federation-with-angular", - "id": "dynamic-module-federation-with-angular", + "name": "Unknown Local Cache Error", + "path": "/recipes/troubleshooting/unknown-local-cache", + "id": "unknown-local-cache", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Setup incremental builds for Angular applications", - "path": "/recipes/angular/setup-incremental-builds-angular", - "id": "setup-incremental-builds-angular", + "name": "Profiling Build Performance", + "path": "/recipes/troubleshooting/performance-profiling", + "id": "performance-profiling", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "React", - "path": "/recipes/react", - "id": "react", + "name": "Tips and tricks", + "path": "/recipes/tips-n-tricks", + "id": "tips-n-tricks", "isExternal": false, "children": [ { - "name": "Migrating from CRA", - "path": "/recipes/react/migration-cra", - "id": "migration-cra", + "name": "Configuring ESLint with Typescript", + "path": "/recipes/tips-n-tricks/eslint", + "id": "eslint", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "React 18 Migration", - "path": "/recipes/react/react-18", - "id": "react-18", + "name": "Define Environment Variables", + "path": "/recipes/tips-n-tricks/define-environment-variables", + "id": "define-environment-variables", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "React Native with Nx", - "path": "/recipes/react/react-native", - "id": "react-native", + "name": "Configuring Browser Support", + "path": "/recipes/tips-n-tricks/browser-support", + "id": "browser-support", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Remix with Nx", - "path": "/recipes/react/remix", - "id": "remix", + "name": "Include Assets in Build", + "path": "/recipes/tips-n-tricks/include-assets-in-build", + "id": "include-assets-in-build", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Include All package.json Files as Projects", + "path": "/recipes/tips-n-tricks/include-all-packagejson", + "id": "include-all-packagejson", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Identify Dependencies Between Folders", + "path": "/recipes/tips-n-tricks/identify-dependencies-between-folders", + "id": "identify-dependencies-between-folders", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Run Root-Level NPM Scripts with Nx", + "path": "/recipes/tips-n-tricks/root-level-scripts", + "id": "root-level-scripts", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Disable Graph Links Created from Analyzing Source Files", + "path": "/recipes/tips-n-tricks/analyze-source-files", + "id": "analyze-source-files", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Use Environment Variables in React", - "path": "/recipes/react/use-environment-variables-in-react", - "id": "use-environment-variables-in-react", + "name": "Workspace Watching", + "path": "/recipes/tips-n-tricks/workspace-watching", + "id": "workspace-watching", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Using Tailwind CSS in React", - "path": "/recipes/react/using-tailwind-css-in-react", - "id": "using-tailwind-css-in-react", + "name": "Convert from a Standalone Repository to an Integrated Repository", + "path": "/recipes/tips-n-tricks/standalone-to-integrated", + "id": "standalone-to-integrated", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Adding Images, Fonts, and Files", - "path": "/recipes/react/adding-assets-react", - "id": "adding-assets-react", + "name": "Use JavaScript instead TypeScript", + "path": "/recipes/tips-n-tricks/js-and-ts", + "id": "js-and-ts", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Setup Module Federation with SSR for React", - "path": "/recipes/react/module-federation-with-ssr", - "id": "module-federation-with-ssr", + "name": "Altering Migration Process", + "path": "/recipes/tips-n-tricks/advanced-update", + "id": "advanced-update", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Deploying Next.js applications to Vercel", - "path": "/recipes/react/deploy-nextjs-to-vercel", - "id": "deploy-nextjs-to-vercel", + "name": "Running Custom Commands", + "path": "/recipes/tips-n-tricks/run-commands-executor", + "id": "run-commands-executor", "isExternal": false, "children": [], "disableCollapsible": false @@ -2529,160 +3420,135 @@ "disableCollapsible": false }, { - "name": "Migrating from CRA", - "path": "/recipes/react/migration-cra", - "id": "migration-cra", + "name": "Configuring ESLint with Typescript", + "path": "/recipes/tips-n-tricks/eslint", + "id": "eslint", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "React 18 Migration", - "path": "/recipes/react/react-18", - "id": "react-18", + "name": "Define Environment Variables", + "path": "/recipes/tips-n-tricks/define-environment-variables", + "id": "define-environment-variables", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "React Native with Nx", - "path": "/recipes/react/react-native", - "id": "react-native", + "name": "Configuring Browser Support", + "path": "/recipes/tips-n-tricks/browser-support", + "id": "browser-support", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Remix with Nx", - "path": "/recipes/react/remix", - "id": "remix", + "name": "Include Assets in Build", + "path": "/recipes/tips-n-tricks/include-assets-in-build", + "id": "include-assets-in-build", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Use Environment Variables in React", - "path": "/recipes/react/use-environment-variables-in-react", - "id": "use-environment-variables-in-react", + "name": "Include All package.json Files as Projects", + "path": "/recipes/tips-n-tricks/include-all-packagejson", + "id": "include-all-packagejson", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Using Tailwind CSS in React", - "path": "/recipes/react/using-tailwind-css-in-react", - "id": "using-tailwind-css-in-react", + "name": "Identify Dependencies Between Folders", + "path": "/recipes/tips-n-tricks/identify-dependencies-between-folders", + "id": "identify-dependencies-between-folders", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Adding Images, Fonts, and Files", - "path": "/recipes/react/adding-assets-react", - "id": "adding-assets-react", + "name": "Run Root-Level NPM Scripts with Nx", + "path": "/recipes/tips-n-tricks/root-level-scripts", + "id": "root-level-scripts", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Setup Module Federation with SSR for React", - "path": "/recipes/react/module-federation-with-ssr", - "id": "module-federation-with-ssr", + "name": "Disable Graph Links Created from Analyzing Source Files", + "path": "/recipes/tips-n-tricks/analyze-source-files", + "id": "analyze-source-files", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Deploying Next.js applications to Vercel", - "path": "/recipes/react/deploy-nextjs-to-vercel", - "id": "deploy-nextjs-to-vercel", + "name": "Workspace Watching", + "path": "/recipes/tips-n-tricks/workspace-watching", + "id": "workspace-watching", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Node", - "path": "/recipes/node", - "id": "node", + "name": "Convert from a Standalone Repository to an Integrated Repository", + "path": "/recipes/tips-n-tricks/standalone-to-integrated", + "id": "standalone-to-integrated", "isExternal": false, - "children": [ - { - "name": "Deploying a Node App to Fly.io", - "path": "/recipes/node/node-server-fly-io", - "id": "node-server-fly-io", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Add and Deploy Netlify Edge Functions with Node", - "path": "/recipes/node/node-serverless-functions-netlify", - "id": "node-serverless-functions-netlify", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Deploying AWS lambda in Node.js", - "path": "/recipes/node/node-aws-lambda", - "id": "node-aws-lambda", - "isExternal": false, - "children": [], - "disableCollapsible": false - } - ], + "children": [], "disableCollapsible": false }, { - "name": "Deploying a Node App to Fly.io", - "path": "/recipes/node/node-server-fly-io", - "id": "node-server-fly-io", + "name": "Use JavaScript instead TypeScript", + "path": "/recipes/tips-n-tricks/js-and-ts", + "id": "js-and-ts", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Add and Deploy Netlify Edge Functions with Node", - "path": "/recipes/node/node-serverless-functions-netlify", - "id": "node-serverless-functions-netlify", + "name": "Altering Migration Process", + "path": "/recipes/tips-n-tricks/advanced-update", + "id": "advanced-update", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Deploying AWS lambda in Node.js", - "path": "/recipes/node/node-aws-lambda", - "id": "node-aws-lambda", + "name": "Running Custom Commands", + "path": "/recipes/tips-n-tricks/run-commands-executor", + "id": "run-commands-executor", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Storybook", - "path": "/recipes/storybook", - "id": "storybook", + "name": "Other", + "path": "/recipes/other", + "id": "other", "isExternal": false, "children": [ { - "name": "One main Storybook instance for all projects", - "path": "/recipes/storybook/one-storybook-for-all", - "id": "one-storybook-for-all", + "name": "Serverless deployment with Deno Deploy", + "path": "/recipes/other/deno-deploy", + "id": "deno-deploy", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "One Storybook instance per scope", - "path": "/recipes/storybook/one-storybook-per-scope", - "id": "one-storybook-per-scope", + "name": "Add and Deploy Netlify Edge Functions with Deno", + "path": "/recipes/other/deno-netlify-functions", + "id": "deno-netlify-functions", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "One main Storybook instance using Storybook Composition", - "path": "/recipes/storybook/one-storybook-with-composition", - "id": "one-storybook-with-composition", + "name": "Rescope Packages from @nrwl to @nx", + "path": "/recipes/other/rescope", + "id": "rescope", "isExternal": false, "children": [], "disableCollapsible": false @@ -2691,168 +3557,111 @@ "disableCollapsible": false }, { - "name": "One main Storybook instance for all projects", - "path": "/recipes/storybook/one-storybook-for-all", - "id": "one-storybook-for-all", + "name": "Serverless deployment with Deno Deploy", + "path": "/recipes/other/deno-deploy", + "id": "deno-deploy", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "One Storybook instance per scope", - "path": "/recipes/storybook/one-storybook-per-scope", - "id": "one-storybook-per-scope", + "name": "Add and Deploy Netlify Edge Functions with Deno", + "path": "/recipes/other/deno-netlify-functions", + "id": "deno-netlify-functions", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "One main Storybook instance using Storybook Composition", - "path": "/recipes/storybook/one-storybook-with-composition", - "id": "one-storybook-with-composition", + "name": "Rescope Packages from @nrwl to @nx", + "path": "/recipes/other/rescope", + "id": "rescope", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Enforce Module Boundaries", - "path": "/recipes/enforce-module-boundaries", - "id": "enforce-module-boundaries", + "name": "Example Repos", + "path": "/recipes/example-repos", + "id": "example-repos", "isExternal": false, "children": [ { - "name": "Ban Dependencies with Certain Tags", - "path": "/recipes/enforce-module-boundaries/ban-dependencies-with-tags", - "id": "ban-dependencies-with-tags", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Tag in Multiple Dimensions", - "path": "/recipes/enforce-module-boundaries/tag-multiple-dimensions", - "id": "tag-multiple-dimensions", + "name": "Powering Up React Development With Nx", + "path": "/recipes/example-repos/react-nx", + "id": "react-nx", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Ban External Imports", - "path": "/recipes/enforce-module-boundaries/ban-external-imports", - "id": "ban-external-imports", + "name": "Using Apollo GraphQL", + "path": "/recipes/example-repos/apollo-react", + "id": "apollo-react", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Tags Allow List", - "path": "/recipes/enforce-module-boundaries/tags-allow-list", - "id": "tags-allow-list", - "isExternal": false, - "children": [], - "disableCollapsible": false - } - ], - "disableCollapsible": false - }, - { - "name": "Ban Dependencies with Certain Tags", - "path": "/recipes/enforce-module-boundaries/ban-dependencies-with-tags", - "id": "ban-dependencies-with-tags", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Tag in Multiple Dimensions", - "path": "/recipes/enforce-module-boundaries/tag-multiple-dimensions", - "id": "tag-multiple-dimensions", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Ban External Imports", - "path": "/recipes/enforce-module-boundaries/ban-external-imports", - "id": "ban-external-imports", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Tags Allow List", - "path": "/recipes/enforce-module-boundaries/tags-allow-list", - "id": "tags-allow-list", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "CI", - "path": "/recipes/ci", - "id": "ci", - "isExternal": false, - "children": [ - { - "name": "CI Setup", - "path": "/recipes/ci/ci-setup", - "id": "ci-setup", + "name": "Using Prisma with NestJS", + "path": "/recipes/example-repos/nestjs-prisma", + "id": "nestjs-prisma", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Prepare applications for deployment via CI", - "path": "/recipes/ci/ci-deployment", - "id": "ci-deployment", + "name": "Using Mongo with Fastify", + "path": "/recipes/example-repos/mongo-fastify", + "id": "mongo-fastify", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Setting up Azure Pipelines", - "path": "/recipes/ci/monorepo-ci-azure", - "id": "monorepo-ci-azure", + "name": "Using Redis with Fastify", + "path": "/recipes/example-repos/redis-fastify", + "id": "redis-fastify", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Setting up CircleCI", - "path": "/recipes/ci/monorepo-ci-circle-ci", - "id": "monorepo-ci-circle-ci", + "name": "Using Postgres with Fastify", + "path": "/recipes/example-repos/postgres-fastify", + "id": "postgres-fastify", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Setting up GitHub Actions", - "path": "/recipes/ci/monorepo-ci-github-actions", - "id": "monorepo-ci-github-actions", + "name": "Using PlanetScale with Serverless Fastify", + "path": "/recipes/example-repos/serverless-fastify-planetscale", + "id": "serverless-fastify-planetscale", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Setting up Jenkins", - "path": "/recipes/ci/monorepo-ci-jenkins", - "id": "monorepo-ci-jenkins", + "name": "Large Repo and Caching", + "path": "/recipes/example-repos/caching", + "id": "caching", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Setting up GitLab", - "path": "/recipes/ci/monorepo-ci-gitlab", - "id": "monorepo-ci-gitlab", + "name": "Large Repo and DTE", + "path": "/recipes/example-repos/dte", + "id": "dte", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Setting up Bitbucket", - "path": "/recipes/ci/monorepo-ci-bitbucket-pipelines", - "id": "monorepo-ci-bitbucket-pipelines", + "name": "Nx Micro-Frontend Example", + "path": "/recipes/example-repos/mfe", + "id": "mfe", "isExternal": false, "children": [], "disableCollapsible": false @@ -2861,216 +3670,135 @@ "disableCollapsible": false }, { - "name": "CI Setup", - "path": "/recipes/ci/ci-setup", - "id": "ci-setup", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Prepare applications for deployment via CI", - "path": "/recipes/ci/ci-deployment", - "id": "ci-deployment", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Setting up Azure Pipelines", - "path": "/recipes/ci/monorepo-ci-azure", - "id": "monorepo-ci-azure", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Setting up CircleCI", - "path": "/recipes/ci/monorepo-ci-circle-ci", - "id": "monorepo-ci-circle-ci", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Setting up GitHub Actions", - "path": "/recipes/ci/monorepo-ci-github-actions", - "id": "monorepo-ci-github-actions", + "name": "Powering Up React Development With Nx", + "path": "/recipes/example-repos/react-nx", + "id": "react-nx", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Setting up Jenkins", - "path": "/recipes/ci/monorepo-ci-jenkins", - "id": "monorepo-ci-jenkins", + "name": "Using Apollo GraphQL", + "path": "/recipes/example-repos/apollo-react", + "id": "apollo-react", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Setting up GitLab", - "path": "/recipes/ci/monorepo-ci-gitlab", - "id": "monorepo-ci-gitlab", + "name": "Using Prisma with NestJS", + "path": "/recipes/example-repos/nestjs-prisma", + "id": "nestjs-prisma", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Setting up Bitbucket", - "path": "/recipes/ci/monorepo-ci-bitbucket-pipelines", - "id": "monorepo-ci-bitbucket-pipelines", + "name": "Using Mongo with Fastify", + "path": "/recipes/example-repos/mongo-fastify", + "id": "mongo-fastify", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Nx Console", - "path": "/recipes/nx-console", - "id": "nx-console", - "isExternal": false, - "children": [ - { - "name": "Telemetry", - "path": "/recipes/nx-console/console-telemetry", - "id": "console-telemetry", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Generate Command", - "path": "/recipes/nx-console/console-generate-command", - "id": "console-generate-command", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Run Command", - "path": "/recipes/nx-console/console-run-command", - "id": "console-run-command", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Add Dependency Command", - "path": "/recipes/nx-console/console-add-dependency-command", - "id": "console-add-dependency-command", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Project Pane", - "path": "/recipes/nx-console/console-project-pane", - "id": "console-project-pane", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Keyboard Shortcuts", - "path": "/recipes/nx-console/console-shortcuts", - "id": "console-shortcuts", - "isExternal": false, - "children": [], - "disableCollapsible": false - } - ], - "disableCollapsible": false - }, - { - "name": "Telemetry", - "path": "/recipes/nx-console/console-telemetry", - "id": "console-telemetry", + "name": "Using Redis with Fastify", + "path": "/recipes/example-repos/redis-fastify", + "id": "redis-fastify", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Generate Command", - "path": "/recipes/nx-console/console-generate-command", - "id": "console-generate-command", + "name": "Using Postgres with Fastify", + "path": "/recipes/example-repos/postgres-fastify", + "id": "postgres-fastify", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Run Command", - "path": "/recipes/nx-console/console-run-command", - "id": "console-run-command", + "name": "Using PlanetScale with Serverless Fastify", + "path": "/recipes/example-repos/serverless-fastify-planetscale", + "id": "serverless-fastify-planetscale", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Add Dependency Command", - "path": "/recipes/nx-console/console-add-dependency-command", - "id": "console-add-dependency-command", + "name": "Large Repo and Caching", + "path": "/recipes/example-repos/caching", + "id": "caching", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Project Pane", - "path": "/recipes/nx-console/console-project-pane", - "id": "console-project-pane", + "name": "Large Repo and DTE", + "path": "/recipes/example-repos/dte", + "id": "dte", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Keyboard Shortcuts", - "path": "/recipes/nx-console/console-shortcuts", - "id": "console-shortcuts", + "name": "Nx Micro-Frontend Example", + "path": "/recipes/example-repos/mfe", + "id": "mfe", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Troubleshooting", - "path": "/recipes/troubleshooting", - "id": "troubleshooting", + "name": "Reference", + "path": "/reference", + "id": "reference", "isExternal": false, "children": [ { - "name": "Resolve Circular Dependencies", - "path": "/recipes/troubleshooting/resolve-circular-dependencies", - "id": "resolve-circular-dependencies", + "name": "Commands", + "path": "/reference/commands", + "id": "commands", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Troubleshooting Nx Install Issues", - "path": "/recipes/troubleshooting/troubleshoot-nx-install-issues", - "id": "troubleshoot-nx-install-issues", + "name": "nx.json", + "path": "/reference/nx-json", + "id": "nx-json", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Troubleshoot Cache Misses", - "path": "/recipes/troubleshooting/troubleshoot-cache-misses", - "id": "troubleshoot-cache-misses", + "name": "Project Configuration", + "path": "/reference/project-configuration", + "id": "project-configuration", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Unknown Local Cache Error", - "path": "/recipes/troubleshooting/unknown-local-cache", - "id": "unknown-local-cache", + "name": ".nxignore", + "path": "/reference/nxignore", + "id": "nxignore", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Profiling Build Performance", - "path": "/recipes/troubleshooting/performance-profiling", - "id": "performance-profiling", + "name": "Environment Variables", + "path": "/reference/environment-variables", + "id": "environment-variables", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Glossary", + "path": "/reference/glossary", + "id": "glossary", "isExternal": false, "children": [], "disableCollapsible": false @@ -3079,288 +3807,281 @@ "disableCollapsible": false }, { - "name": "Resolve Circular Dependencies", - "path": "/recipes/troubleshooting/resolve-circular-dependencies", - "id": "resolve-circular-dependencies", + "name": "Commands", + "path": "/reference/commands", + "id": "commands", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Troubleshooting Nx Install Issues", - "path": "/recipes/troubleshooting/troubleshoot-nx-install-issues", - "id": "troubleshoot-nx-install-issues", + "name": "nx.json", + "path": "/reference/nx-json", + "id": "nx-json", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Project Configuration", + "path": "/reference/project-configuration", + "id": "project-configuration", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Troubleshoot Cache Misses", - "path": "/recipes/troubleshooting/troubleshoot-cache-misses", - "id": "troubleshoot-cache-misses", + "name": ".nxignore", + "path": "/reference/nxignore", + "id": "nxignore", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Unknown Local Cache Error", - "path": "/recipes/troubleshooting/unknown-local-cache", - "id": "unknown-local-cache", + "name": "Environment Variables", + "path": "/reference/environment-variables", + "id": "environment-variables", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Profiling Build Performance", - "path": "/recipes/troubleshooting/performance-profiling", - "id": "performance-profiling", + "name": "Glossary", + "path": "/reference/glossary", + "id": "glossary", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Tips and tricks", - "path": "/recipes/tips-n-tricks", - "id": "tips-n-tricks", + "name": "Deprecated", + "path": "/deprecated", + "id": "deprecated", "isExternal": false, "children": [ { - "name": "Configuring ESLint with Typescript", - "path": "/recipes/tips-n-tricks/eslint", - "id": "eslint", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Define Environment Variables", - "path": "/recipes/tips-n-tricks/define-environment-variables", - "id": "define-environment-variables", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Configuring Browser Support", - "path": "/recipes/tips-n-tricks/browser-support", - "id": "browser-support", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Include Assets in Build", - "path": "/recipes/tips-n-tricks/include-assets-in-build", - "id": "include-assets-in-build", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Include All package.json Files as Projects", - "path": "/recipes/tips-n-tricks/include-all-packagejson", - "id": "include-all-packagejson", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Identify Dependencies Between Folders", - "path": "/recipes/tips-n-tricks/identify-dependencies-between-folders", - "id": "identify-dependencies-between-folders", + "name": "workspace.json", + "path": "/deprecated/workspace-json", + "id": "workspace-json", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Run Root-Level NPM Scripts with Nx", - "path": "/recipes/tips-n-tricks/root-level-scripts", - "id": "root-level-scripts", + "name": "workspace-lint", + "path": "/deprecated/workspace-lint", + "id": "workspace-lint", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Disable Graph Links Created from Analyzing Source Files", - "path": "/recipes/tips-n-tricks/analyze-source-files", - "id": "analyze-source-files", + "name": "Workspace Generators", + "path": "/deprecated/workspace-generators", + "id": "workspace-generators", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Workspace Watching", - "path": "/recipes/tips-n-tricks/workspace-watching", - "id": "workspace-watching", + "name": "Workspace Executors", + "path": "/deprecated/workspace-executors", + "id": "workspace-executors", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Convert from a Standalone Repository to an Integrated Repository", - "path": "/recipes/tips-n-tricks/standalone-to-integrated", - "id": "standalone-to-integrated", + "name": "defaultCollection", + "path": "/deprecated/default-collection", + "id": "default-collection", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Use JavaScript instead TypeScript", - "path": "/recipes/tips-n-tricks/js-and-ts", - "id": "js-and-ts", + "name": "runtimeCacheInputs", + "path": "/deprecated/runtime-cache-inputs", + "id": "runtime-cache-inputs", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Altering Migration Process", - "path": "/recipes/tips-n-tricks/advanced-update", - "id": "advanced-update", + "name": "globalImplicitDependencies", + "path": "/deprecated/global-implicit-dependencies", + "id": "global-implicit-dependencies", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Running Custom Commands", - "path": "/recipes/tips-n-tricks/run-commands-executor", - "id": "run-commands-executor", + "name": "Storybook deprecated docs", + "path": "/deprecated/storybook", + "id": "storybook", "isExternal": false, - "children": [], + "children": [ + { + "name": "Angular: Information about the Storybook targets", + "path": "/deprecated/storybook/angular-storybook-targets", + "id": "angular-storybook-targets", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Angular: The browserTarget", + "path": "/deprecated/storybook/angular-browser-target", + "id": "angular-browser-target", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Angular: Storybook Migration to webpackFinal", + "path": "/deprecated/storybook/migrate-webpack-final-angular", + "id": "migrate-webpack-final-angular", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Angular: Upgrading to Storybook 6", + "path": "/deprecated/storybook/upgrade-storybook-v6-angular", + "id": "upgrade-storybook-v6-angular", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "React: Storybook Migration to webpackFinal and the Nx Addon", + "path": "/deprecated/storybook/migrate-webpack-final-react", + "id": "migrate-webpack-final-react", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "React: Upgrading to Storybook 6", + "path": "/deprecated/storybook/upgrade-storybook-v6-react", + "id": "upgrade-storybook-v6-react", + "isExternal": false, + "children": [], + "disableCollapsible": false + } + ], "disableCollapsible": false } ], "disableCollapsible": false }, { - "name": "Configuring ESLint with Typescript", - "path": "/recipes/tips-n-tricks/eslint", - "id": "eslint", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Define Environment Variables", - "path": "/recipes/tips-n-tricks/define-environment-variables", - "id": "define-environment-variables", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Configuring Browser Support", - "path": "/recipes/tips-n-tricks/browser-support", - "id": "browser-support", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Include Assets in Build", - "path": "/recipes/tips-n-tricks/include-assets-in-build", - "id": "include-assets-in-build", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Include All package.json Files as Projects", - "path": "/recipes/tips-n-tricks/include-all-packagejson", - "id": "include-all-packagejson", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Identify Dependencies Between Folders", - "path": "/recipes/tips-n-tricks/identify-dependencies-between-folders", - "id": "identify-dependencies-between-folders", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Run Root-Level NPM Scripts with Nx", - "path": "/recipes/tips-n-tricks/root-level-scripts", - "id": "root-level-scripts", + "name": "workspace.json", + "path": "/deprecated/workspace-json", + "id": "workspace-json", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Disable Graph Links Created from Analyzing Source Files", - "path": "/recipes/tips-n-tricks/analyze-source-files", - "id": "analyze-source-files", + "name": "workspace-lint", + "path": "/deprecated/workspace-lint", + "id": "workspace-lint", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Workspace Watching", - "path": "/recipes/tips-n-tricks/workspace-watching", - "id": "workspace-watching", + "name": "Workspace Generators", + "path": "/deprecated/workspace-generators", + "id": "workspace-generators", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Convert from a Standalone Repository to an Integrated Repository", - "path": "/recipes/tips-n-tricks/standalone-to-integrated", - "id": "standalone-to-integrated", + "name": "Workspace Executors", + "path": "/deprecated/workspace-executors", + "id": "workspace-executors", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Use JavaScript instead TypeScript", - "path": "/recipes/tips-n-tricks/js-and-ts", - "id": "js-and-ts", + "name": "defaultCollection", + "path": "/deprecated/default-collection", + "id": "default-collection", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Altering Migration Process", - "path": "/recipes/tips-n-tricks/advanced-update", - "id": "advanced-update", + "name": "runtimeCacheInputs", + "path": "/deprecated/runtime-cache-inputs", + "id": "runtime-cache-inputs", "isExternal": false, "children": [], "disableCollapsible": false }, - { - "name": "Running Custom Commands", - "path": "/recipes/tips-n-tricks/run-commands-executor", - "id": "run-commands-executor", + { + "name": "globalImplicitDependencies", + "path": "/deprecated/global-implicit-dependencies", + "id": "global-implicit-dependencies", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Other", - "path": "/recipes/other", - "id": "other", + "name": "Storybook deprecated docs", + "path": "/deprecated/storybook", + "id": "storybook", "isExternal": false, "children": [ { - "name": "Serverless deployment with Deno Deploy", - "path": "/recipes/other/deno-deploy", - "id": "deno-deploy", + "name": "Angular: Information about the Storybook targets", + "path": "/deprecated/storybook/angular-storybook-targets", + "id": "angular-storybook-targets", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Add and Deploy Netlify Edge Functions with Deno", - "path": "/recipes/other/deno-netlify-functions", - "id": "deno-netlify-functions", + "name": "Angular: The browserTarget", + "path": "/deprecated/storybook/angular-browser-target", + "id": "angular-browser-target", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Rescope Packages from @nrwl to @nx", - "path": "/recipes/other/rescope", - "id": "rescope", + "name": "Angular: Storybook Migration to webpackFinal", + "path": "/deprecated/storybook/migrate-webpack-final-angular", + "id": "migrate-webpack-final-angular", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Angular: Upgrading to Storybook 6", + "path": "/deprecated/storybook/upgrade-storybook-v6-angular", + "id": "upgrade-storybook-v6-angular", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "React: Storybook Migration to webpackFinal and the Nx Addon", + "path": "/deprecated/storybook/migrate-webpack-final-react", + "id": "migrate-webpack-final-react", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "React: Upgrading to Storybook 6", + "path": "/deprecated/storybook/upgrade-storybook-v6-react", + "id": "upgrade-storybook-v6-react", "isExternal": false, "children": [], "disableCollapsible": false @@ -3369,111 +4090,127 @@ "disableCollapsible": false }, { - "name": "Serverless deployment with Deno Deploy", - "path": "/recipes/other/deno-deploy", - "id": "deno-deploy", + "name": "Angular: Information about the Storybook targets", + "path": "/deprecated/storybook/angular-storybook-targets", + "id": "angular-storybook-targets", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Add and Deploy Netlify Edge Functions with Deno", - "path": "/recipes/other/deno-netlify-functions", - "id": "deno-netlify-functions", + "name": "Angular: The browserTarget", + "path": "/deprecated/storybook/angular-browser-target", + "id": "angular-browser-target", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Rescope Packages from @nrwl to @nx", - "path": "/recipes/other/rescope", - "id": "rescope", + "name": "Angular: Storybook Migration to webpackFinal", + "path": "/deprecated/storybook/migrate-webpack-final-angular", + "id": "migrate-webpack-final-angular", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Example Repos", - "path": "/recipes/example-repos", - "id": "example-repos", + "name": "Angular: Upgrading to Storybook 6", + "path": "/deprecated/storybook/upgrade-storybook-v6-angular", + "id": "upgrade-storybook-v6-angular", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "React: Storybook Migration to webpackFinal and the Nx Addon", + "path": "/deprecated/storybook/migrate-webpack-final-react", + "id": "migrate-webpack-final-react", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "React: Upgrading to Storybook 6", + "path": "/deprecated/storybook/upgrade-storybook-v6-react", + "id": "upgrade-storybook-v6-react", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "See Also", + "path": "/see-also", + "id": "see-also", "isExternal": false, "children": [ { - "name": "Powering Up React Development With Nx", - "path": "/recipes/example-repos/react-nx", - "id": "react-nx", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Using Apollo GraphQL", - "path": "/recipes/example-repos/apollo-react", - "id": "apollo-react", - "isExternal": false, + "name": "Nx Cloud Documentation", + "path": "/nx-cloud/intro/what-is-nx-cloud", + "id": "nx-cloud-documentation", + "isExternal": true, "children": [], "disableCollapsible": false }, { - "name": "Using Prisma with NestJS", - "path": "/recipes/example-repos/nestjs-prisma", - "id": "nestjs-prisma", - "isExternal": false, + "name": "Nx Cloud Main Site", + "path": "https://nx.app", + "id": "nx-cloud-main-site", + "isExternal": true, "children": [], "disableCollapsible": false }, { - "name": "Using Mongo with Fastify", - "path": "/recipes/example-repos/mongo-fastify", - "id": "mongo-fastify", - "isExternal": false, + "name": "--skip-nx-cache flag", + "path": "/packages/nx/documents/affected#skip-nx-cache", + "id": "skip-nx-cache-flag", + "isExternal": true, "children": [], "disableCollapsible": false }, { - "name": "Using Redis with Fastify", - "path": "/recipes/example-repos/redis-fastify", - "id": "redis-fastify", - "isExternal": false, + "name": "tasks-runner-options property", + "path": "/reference/nx-json#tasks-runner-options", + "id": "tasks-runner-options-property", + "isExternal": true, "children": [], "disableCollapsible": false }, { - "name": "Using Postgres with Fastify", - "path": "/recipes/example-repos/postgres-fastify", - "id": "postgres-fastify", - "isExternal": false, + "name": "nx.json reference: inputs and namedInputs", + "path": "/reference/nx-json#inputs-&-namedinputs", + "id": "nxjson-inputs", + "isExternal": true, "children": [], "disableCollapsible": false }, { - "name": "Using PlanetScale with Serverless Fastify", - "path": "/recipes/example-repos/serverless-fastify-planetscale", - "id": "serverless-fastify-planetscale", - "isExternal": false, + "name": "Project Configuration reference: inputs and namedInputs", + "path": "/reference/project-configuration#inputs-&-namedinputs", + "id": "project-config-inputs", + "isExternal": true, "children": [], "disableCollapsible": false }, { - "name": "Large Repo and Caching", - "path": "/recipes/example-repos/caching", - "id": "caching", - "isExternal": false, + "name": "nx.json workspaceLayout property", + "path": "/reference/nx-json#workspace-layout", + "id": "nxjson-workspaceLayout", + "isExternal": true, "children": [], "disableCollapsible": false }, { - "name": "Large Repo and DTE", - "path": "/recipes/example-repos/dte", - "id": "dte", - "isExternal": false, + "name": "nx.json generator defaults", + "path": "/reference/nx-json#generators", + "id": "nxjson-generator-defaults", + "isExternal": true, "children": [], "disableCollapsible": false }, { - "name": "Nx Micro-Frontend Example", - "path": "/recipes/example-repos/mfe", - "id": "mfe", + "name": "Site Map", + "path": "/see-also/sitemap", + "id": "sitemap", "isExternal": false, "children": [], "disableCollapsible": false @@ -3482,81 +4219,65 @@ "disableCollapsible": false }, { - "name": "Powering Up React Development With Nx", - "path": "/recipes/example-repos/react-nx", - "id": "react-nx", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Using Apollo GraphQL", - "path": "/recipes/example-repos/apollo-react", - "id": "apollo-react", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Using Prisma with NestJS", - "path": "/recipes/example-repos/nestjs-prisma", - "id": "nestjs-prisma", - "isExternal": false, + "name": "Nx Cloud Documentation", + "path": "/nx-cloud/intro/what-is-nx-cloud", + "id": "nx-cloud-documentation", + "isExternal": true, "children": [], "disableCollapsible": false }, { - "name": "Using Mongo with Fastify", - "path": "/recipes/example-repos/mongo-fastify", - "id": "mongo-fastify", - "isExternal": false, + "name": "--skip-nx-cache flag", + "path": "/packages/nx/documents/affected#skip-nx-cache", + "id": "skip-nx-cache-flag", + "isExternal": true, "children": [], "disableCollapsible": false }, { - "name": "Using Redis with Fastify", - "path": "/recipes/example-repos/redis-fastify", - "id": "redis-fastify", - "isExternal": false, + "name": "tasks-runner-options property", + "path": "/reference/nx-json#tasks-runner-options", + "id": "tasks-runner-options-property", + "isExternal": true, "children": [], "disableCollapsible": false }, { - "name": "Using Postgres with Fastify", - "path": "/recipes/example-repos/postgres-fastify", - "id": "postgres-fastify", - "isExternal": false, + "name": "nx.json reference: inputs and namedInputs", + "path": "/reference/nx-json#inputs-&-namedinputs", + "id": "nxjson-inputs", + "isExternal": true, "children": [], "disableCollapsible": false }, { - "name": "Using PlanetScale with Serverless Fastify", - "path": "/recipes/example-repos/serverless-fastify-planetscale", - "id": "serverless-fastify-planetscale", - "isExternal": false, + "name": "Project Configuration reference: inputs and namedInputs", + "path": "/reference/project-configuration#inputs-&-namedinputs", + "id": "project-config-inputs", + "isExternal": true, "children": [], "disableCollapsible": false }, { - "name": "Large Repo and Caching", - "path": "/recipes/example-repos/caching", - "id": "caching", - "isExternal": false, + "name": "nx.json workspaceLayout property", + "path": "/reference/nx-json#workspace-layout", + "id": "nxjson-workspaceLayout", + "isExternal": true, "children": [], "disableCollapsible": false }, { - "name": "Large Repo and DTE", - "path": "/recipes/example-repos/dte", - "id": "dte", - "isExternal": false, + "name": "nx.json generator defaults", + "path": "/reference/nx-json#generators", + "id": "nxjson-generator-defaults", + "isExternal": true, "children": [], "disableCollapsible": false }, { - "name": "Nx Micro-Frontend Example", - "path": "/recipes/example-repos/mfe", - "id": "mfe", + "name": "Site Map", + "path": "/see-also/sitemap", + "id": "sitemap", "isExternal": false, "children": [], "disableCollapsible": false diff --git a/docs/generated/manifests/nx.json b/docs/generated/manifests/nx.json index d1d7cc4dafc46..b6ac9e9510db9 100644 --- a/docs/generated/manifests/nx.json +++ b/docs/generated/manifests/nx.json @@ -1985,33 +1985,2691 @@ "tags": [] }, "/recipes": { - "id": "all", - "name": "All Recipes »", + "id": "recipes", + "name": "Recipes", + "description": "In depth recipes for common tasks", + "file": "", + "itemList": [ + { + "id": "adopting-nx", + "name": "Adopting Nx", + "description": "Adopting Nx incrementally, on existing project or from scratch.", + "file": "", + "itemList": [ + { + "id": "adding-to-monorepo", + "name": "NPM/Yarn/PNPM workspaces", + "description": "", + "file": "shared/migration/adding-to-monorepo", + "itemList": [], + "isExternal": false, + "path": "/recipes/adopting-nx/adding-to-monorepo", + "tags": [] + }, + { + "id": "adding-to-existing-project", + "name": "Add to any Project", + "description": "", + "file": "shared/migration/adding-to-existing-project", + "itemList": [], + "isExternal": false, + "path": "/recipes/adopting-nx/adding-to-existing-project", + "tags": [] + }, + { + "id": "lerna-and-nx", + "name": "Nx and Lerna", + "description": "", + "file": "shared/migration/lerna-and-nx", + "itemList": [], + "isExternal": false, + "path": "/recipes/adopting-nx/lerna-and-nx", + "tags": [] + }, + { + "id": "preserving-git-histories", + "name": "Preserving Git Histories", + "description": "", + "file": "shared/migration/preserving-git-histories", + "itemList": [], + "isExternal": false, + "path": "/recipes/adopting-nx/preserving-git-histories", + "tags": [] + }, + { + "id": "manual", + "name": "Manual migration", + "description": "", + "file": "shared/migration/manual", + "itemList": [], + "isExternal": false, + "path": "/recipes/adopting-nx/manual", + "tags": [] + } + ], + "isExternal": false, + "path": "/recipes/adopting-nx", + "tags": [] + }, + { + "id": "angular", + "name": "Angular", + "description": "Advanced guides to adopt Nx in Angular.", + "file": "", + "itemList": [ + { + "id": "migration", + "name": "Migration", + "description": "", + "file": "", + "itemList": [ + { + "id": "angular", + "name": "Migrating from Angular CLI", + "description": "", + "file": "shared/migration/migration-angular", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/migration/angular", + "tags": [] + }, + { + "id": "angular-multiple", + "name": "Migrating From Multiple Angular CLI Repos", + "description": "", + "file": "shared/migration/angular-multiple", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/migration/angular-multiple", + "tags": [] + }, + { + "id": "angular-manual", + "name": "Migrating Angular Application manually", + "description": "", + "file": "shared/migration/angular-manual", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/migration/angular-manual", + "tags": [] + }, + { + "id": "angularjs", + "name": "Migrating from AngularJS", + "description": "", + "file": "shared/migration/migration-angularjs", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/migration/angularjs", + "tags": [] + } + ], + "isExternal": false, + "path": "/recipes/angular/migration", + "tags": [] + }, + { + "id": "use-environment-variables-in-angular", + "name": "Use Environment Variables in Angular", + "description": "", + "file": "shared/guides/use-environment-variables-in-angular", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/use-environment-variables-in-angular", + "tags": ["environment-variables"] + }, + { + "id": "using-tailwind-css-with-angular-projects", + "name": "Using Tailwind CSS with Angular projects", + "description": "", + "file": "shared/guides/using-tailwind-css-with-angular-projects", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/using-tailwind-css-with-angular-projects", + "tags": [] + }, + { + "id": "module-federation-with-ssr", + "name": "Setup Module Federation with SSR for Angular", + "description": "", + "file": "shared/recipes/module-federation-with-ssr", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/module-federation-with-ssr", + "tags": ["use-task-executors", "module-federation", "angular"] + }, + { + "id": "dynamic-module-federation-with-angular", + "name": "Advanced Micro Frontends with Angular using Dynamic Federation", + "description": "", + "file": "shared/guides/module-federation/dynamic-mfe-angular", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/dynamic-module-federation-with-angular", + "tags": ["use-task-executors", "module-federation", "angular"] + }, + { + "id": "setup-incremental-builds-angular", + "name": "Setup incremental builds for Angular applications", + "description": "", + "file": "shared/guides/setup-incremental-builds-angular", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/setup-incremental-builds-angular", + "tags": [] + } + ], + "isExternal": false, + "path": "/recipes/angular", + "tags": [] + }, + { + "id": "react", + "name": "React", + "description": "Advanced guides to adopt Nx in React.", + "file": "", + "itemList": [ + { + "id": "migration-cra", + "name": "Migrating from CRA", + "description": "", + "file": "shared/migration/migration-cra", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/migration-cra", + "tags": [] + }, + { + "id": "react-18", + "name": "React 18 Migration", + "description": "", + "file": "shared/guides/react-18", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/react-18", + "tags": [] + }, + { + "id": "react-native", + "name": "React Native with Nx", + "description": "", + "file": "shared/guides/react-native", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/react-native", + "tags": [] + }, + { + "id": "remix", + "name": "Remix with Nx", + "description": "", + "file": "shared/guides/remix", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/remix", + "tags": [] + }, + { + "id": "use-environment-variables-in-react", + "name": "Use Environment Variables in React", + "description": "", + "file": "shared/guides/use-environment-variables-in-react", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/use-environment-variables-in-react", + "tags": ["environment-variables"] + }, + { + "id": "using-tailwind-css-in-react", + "name": "Using Tailwind CSS in React", + "description": "", + "file": "shared/guides/using-tailwind-css-in-react", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/using-tailwind-css-in-react", + "tags": [] + }, + { + "id": "adding-assets-react", + "name": "Adding Images, Fonts, and Files", + "description": "", + "file": "shared/guides/adding-assets", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/adding-assets-react", + "tags": [] + }, + { + "id": "module-federation-with-ssr", + "name": "Setup Module Federation with SSR for React", + "description": "", + "file": "shared/recipes/module-federation-with-ssr", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/module-federation-with-ssr", + "tags": ["use-task-executors", "module-federation", "react"] + }, + { + "id": "deploy-nextjs-to-vercel", + "name": "Deploying Next.js applications to Vercel", + "description": "", + "file": "shared/recipes/deployment/deploy-nextjs-to-vercel", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/deploy-nextjs-to-vercel", + "tags": [] + } + ], + "isExternal": false, + "path": "/recipes/react", + "tags": [] + }, + { + "id": "node", + "name": "Node", + "description": "Set of Node related recipes.", + "file": "", + "itemList": [ + { + "id": "node-server-fly-io", + "name": "Deploying a Node App to Fly.io", + "description": "", + "file": "shared/recipes/deployment/node-server-fly-io", + "itemList": [], + "isExternal": false, + "path": "/recipes/node/node-server-fly-io", + "tags": ["deployment", "node"] + }, + { + "id": "node-serverless-functions-netlify", + "name": "Add and Deploy Netlify Edge Functions with Node", + "description": "", + "file": "shared/recipes/deployment/node-serverless-functions-netlify", + "itemList": [], + "isExternal": false, + "path": "/recipes/node/node-serverless-functions-netlify", + "tags": ["deployment", "node"] + }, + { + "id": "node-aws-lambda", + "name": "Deploying AWS lambda in Node.js", + "description": "", + "file": "shared/recipes/deployment/node-aws-lambda", + "itemList": [], + "isExternal": false, + "path": "/recipes/node/node-aws-lambda", + "tags": ["deployment", "node"] + } + ], + "isExternal": false, + "path": "/recipes/node", + "tags": [] + }, + { + "id": "storybook", + "name": "Storybook", + "description": "Storybook how tos.", + "file": "", + "itemList": [ + { + "id": "one-storybook-for-all", + "name": "One main Storybook instance for all projects", + "description": "", + "file": "shared/recipes/one-storybook-for-all", + "itemList": [], + "isExternal": false, + "path": "/recipes/storybook/one-storybook-for-all", + "tags": ["storybook"] + }, + { + "id": "one-storybook-per-scope", + "name": "One Storybook instance per scope", + "description": "", + "file": "shared/recipes/one-storybook-per-scope", + "itemList": [], + "isExternal": false, + "path": "/recipes/storybook/one-storybook-per-scope", + "tags": ["storybook"] + }, + { + "id": "one-storybook-with-composition", + "name": "One main Storybook instance using Storybook Composition", + "description": "", + "file": "shared/recipes/one-storybook-with-composition", + "itemList": [], + "isExternal": false, + "path": "/recipes/storybook/one-storybook-with-composition", + "tags": ["storybook"] + } + ], + "isExternal": false, + "path": "/recipes/storybook", + "tags": [] + }, + { + "id": "enforce-module-boundaries", + "name": "Enforce Module Boundaries", + "description": "Configuring the enforce module boundaries rule", + "file": "", + "itemList": [ + { + "id": "ban-dependencies-with-tags", + "name": "Ban Dependencies with Certain Tags", + "description": "", + "file": "shared/recipes/ban-dependencies-with-tags", + "itemList": [], + "isExternal": false, + "path": "/recipes/enforce-module-boundaries/ban-dependencies-with-tags", + "tags": ["enforce-project-boundaries"] + }, + { + "id": "tag-multiple-dimensions", + "name": "Tag in Multiple Dimensions", + "description": "", + "file": "shared/recipes/tag-multiple-dimensions", + "itemList": [], + "isExternal": false, + "path": "/recipes/enforce-module-boundaries/tag-multiple-dimensions", + "tags": ["enforce-project-boundaries"] + }, + { + "id": "ban-external-imports", + "name": "Ban External Imports", + "description": "", + "file": "shared/recipes/ban-external-imports", + "itemList": [], + "isExternal": false, + "path": "/recipes/enforce-module-boundaries/ban-external-imports", + "tags": ["enforce-project-boundaries"] + }, + { + "id": "tags-allow-list", + "name": "Tags Allow List", + "description": "", + "file": "shared/recipes/tags-allow-list", + "itemList": [], + "isExternal": false, + "path": "/recipes/enforce-module-boundaries/tags-allow-list", + "tags": ["enforce-project-boundaries"] + } + ], + "isExternal": false, + "path": "/recipes/enforce-module-boundaries", + "tags": [] + }, + { + "id": "ci", + "name": "CI", + "description": "All recipes about how to use Nx to make your CI faster.", + "file": "", + "itemList": [ + { + "id": "ci-setup", + "name": "CI Setup", + "description": "", + "file": "shared/ci-overview", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/ci-setup", + "tags": ["distribute-task-execution"] + }, + { + "id": "ci-deployment", + "name": "Prepare applications for deployment via CI", + "description": "", + "file": "shared/recipes/ci-deployment", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/ci-deployment", + "tags": ["docker", "deploy"] + }, + { + "id": "monorepo-ci-azure", + "name": "Setting up Azure Pipelines", + "description": "", + "file": "shared/monorepo-ci-azure", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/monorepo-ci-azure", + "tags": [] + }, + { + "id": "monorepo-ci-circle-ci", + "name": "Setting up CircleCI", + "description": "", + "file": "shared/monorepo-ci-circle-ci", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/monorepo-ci-circle-ci", + "tags": [] + }, + { + "id": "monorepo-ci-github-actions", + "name": "Setting up GitHub Actions", + "description": "", + "file": "shared/monorepo-ci-github-actions", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/monorepo-ci-github-actions", + "tags": [] + }, + { + "id": "monorepo-ci-jenkins", + "name": "Setting up Jenkins", + "description": "", + "file": "shared/monorepo-ci-jenkins", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/monorepo-ci-jenkins", + "tags": [] + }, + { + "id": "monorepo-ci-gitlab", + "name": "Setting up GitLab", + "description": "", + "file": "shared/monorepo-ci-gitlab", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/monorepo-ci-gitlab", + "tags": [] + }, + { + "id": "monorepo-ci-bitbucket-pipelines", + "name": "Setting up Bitbucket", + "description": "", + "file": "shared/monorepo-ci-bitbucket-pipelines", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/monorepo-ci-bitbucket-pipelines", + "tags": [] + } + ], + "isExternal": false, + "path": "/recipes/ci", + "tags": [] + }, + { + "id": "nx-console", + "name": "Nx Console", + "description": "Checkout all the recipes related to Nx Console.", + "file": "", + "itemList": [ + { + "id": "console-telemetry", + "name": "Telemetry", + "description": "", + "file": "shared/recipes/console-telemetry", + "itemList": [], + "isExternal": false, + "path": "/recipes/nx-console/console-telemetry", + "tags": ["integrate-with-editors"] + }, + { + "id": "console-generate-command", + "name": "Generate Command", + "description": "", + "file": "shared/recipes/console-generate-command", + "itemList": [], + "isExternal": false, + "path": "/recipes/nx-console/console-generate-command", + "tags": ["integrate-with-editors"] + }, + { + "id": "console-run-command", + "name": "Run Command", + "description": "", + "file": "shared/recipes/console-run-command", + "itemList": [], + "isExternal": false, + "path": "/recipes/nx-console/console-run-command", + "tags": ["integrate-with-editors"] + }, + { + "id": "console-add-dependency-command", + "name": "Add Dependency Command", + "description": "", + "file": "shared/recipes/console-add-dependency-command", + "itemList": [], + "isExternal": false, + "path": "/recipes/nx-console/console-add-dependency-command", + "tags": ["integrate-with-editors"] + }, + { + "id": "console-project-pane", + "name": "Project Pane", + "description": "", + "file": "shared/recipes/console-project-pane", + "itemList": [], + "isExternal": false, + "path": "/recipes/nx-console/console-project-pane", + "tags": ["integrate-with-editors"] + }, + { + "id": "console-shortcuts", + "name": "Keyboard Shortcuts", + "description": "", + "file": "shared/recipes/console-shortcuts", + "itemList": [], + "isExternal": false, + "path": "/recipes/nx-console/console-shortcuts", + "tags": ["integrate-with-editors"] + } + ], + "isExternal": false, + "path": "/recipes/nx-console", + "tags": [] + }, + { + "id": "troubleshooting", + "name": "Troubleshooting", + "description": "Learn how to troubleshoot common problems.", + "file": "", + "itemList": [ + { + "id": "resolve-circular-dependencies", + "name": "Resolve Circular Dependencies", + "description": "", + "file": "shared/recipes/resolve-circular-dependencies", + "itemList": [], + "isExternal": false, + "path": "/recipes/troubleshooting/resolve-circular-dependencies", + "tags": ["explore-graph"] + }, + { + "id": "troubleshoot-nx-install-issues", + "name": "Troubleshooting Nx Install Issues", + "description": "", + "file": "shared/installation/troubleshoot-installation", + "itemList": [], + "isExternal": false, + "path": "/recipes/troubleshooting/troubleshoot-nx-install-issues", + "tags": [] + }, + { + "id": "troubleshoot-cache-misses", + "name": "Troubleshoot Cache Misses", + "description": "", + "file": "shared/recipes/troubleshoot-cache-misses", + "itemList": [], + "isExternal": false, + "path": "/recipes/troubleshooting/troubleshoot-cache-misses", + "tags": ["cache-task-results"] + }, + { + "id": "unknown-local-cache", + "name": "Unknown Local Cache Error", + "description": "", + "file": "shared/guides/unknown-local-cache", + "itemList": [], + "isExternal": false, + "path": "/recipes/troubleshooting/unknown-local-cache", + "tags": [] + }, + { + "id": "performance-profiling", + "name": "Profiling Build Performance", + "description": "", + "file": "shared/guides/performance-profiling", + "itemList": [], + "isExternal": false, + "path": "/recipes/troubleshooting/performance-profiling", + "tags": ["use-task-executors", "environment-variables"] + } + ], + "isExternal": false, + "path": "/recipes/troubleshooting", + "tags": [] + }, + { + "id": "tips-n-tricks", + "name": "Tips and tricks", + "description": "Various tips and tricks for using Nx.", + "file": "", + "itemList": [ + { + "id": "eslint", + "name": "Configuring ESLint with Typescript", + "description": "", + "file": "shared/eslint", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/eslint", + "tags": [] + }, + { + "id": "define-environment-variables", + "name": "Define Environment Variables", + "description": "", + "file": "shared/guides/define-environment-variables", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/define-environment-variables", + "tags": ["environment-variables"] + }, + { + "id": "browser-support", + "name": "Configuring Browser Support", + "description": "", + "file": "shared/guides/browser-support", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/browser-support", + "tags": [] + }, + { + "id": "include-assets-in-build", + "name": "Include Assets in Build", + "description": "", + "file": "shared/recipes/include-assets-in-build", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/include-assets-in-build", + "tags": [] + }, + { + "id": "include-all-packagejson", + "name": "Include All package.json Files as Projects", + "description": "", + "file": "shared/recipes/include-all-packagejson", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/include-all-packagejson", + "tags": [] + }, + { + "id": "identify-dependencies-between-folders", + "name": "Identify Dependencies Between Folders", + "description": "", + "file": "shared/recipes/identify-dependencies-between-folders", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/identify-dependencies-between-folders", + "tags": [] + }, + { + "id": "root-level-scripts", + "name": "Run Root-Level NPM Scripts with Nx", + "description": "", + "file": "shared/recipes/root-level-scripts", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/root-level-scripts", + "tags": ["run-tasks"] + }, + { + "id": "analyze-source-files", + "name": "Disable Graph Links Created from Analyzing Source Files", + "description": "", + "file": "shared/recipes/analyze-source-files", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/analyze-source-files", + "tags": ["explore-graph"] + }, + { + "id": "workspace-watching", + "name": "Workspace Watching", + "description": "", + "file": "shared/recipes/workspace-watching", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/workspace-watching", + "tags": ["workspace-watching"] + }, + { + "id": "standalone-to-integrated", + "name": "Convert from a Standalone Repository to an Integrated Repository", + "description": "", + "file": "shared/recipes/repo-types/standalone-to-integrated", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/standalone-to-integrated", + "tags": ["repository-types"] + }, + { + "id": "js-and-ts", + "name": "Use JavaScript instead TypeScript", + "description": "", + "file": "shared/guides/js-and-ts", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/js-and-ts", + "tags": [] + }, + { + "id": "advanced-update", + "name": "Altering Migration Process", + "description": "", + "file": "shared/recipes/advanced-update", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/advanced-update", + "tags": ["automate-updating-dependencies"] + }, + { + "id": "run-commands-executor", + "name": "Running Custom Commands", + "description": "", + "file": "shared/running-custom-commands", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/run-commands-executor", + "tags": ["use-task-executors"] + } + ], + "isExternal": false, + "path": "/recipes/tips-n-tricks", + "tags": [] + }, + { + "id": "other", + "name": "Other", + "description": "Other recipes you will find useful.", + "file": "", + "itemList": [ + { + "id": "deno-deploy", + "name": "Serverless deployment with Deno Deploy", + "description": "", + "file": "shared/recipes/deployment/deno-deploy", + "itemList": [], + "isExternal": false, + "path": "/recipes/other/deno-deploy", + "tags": ["deployment", "deno"] + }, + { + "id": "deno-netlify-functions", + "name": "Add and Deploy Netlify Edge Functions with Deno", + "description": "", + "file": "shared/recipes/deployment/deno-netlify-edge-functions", + "itemList": [], + "isExternal": false, + "path": "/recipes/other/deno-netlify-functions", + "tags": ["deployment", "deno"] + }, + { + "id": "rescope", + "name": "Rescope Packages from @nrwl to @nx", + "description": "", + "file": "shared/recipes/rescope", + "itemList": [], + "isExternal": false, + "path": "/recipes/other/rescope", + "tags": [] + } + ], + "isExternal": false, + "path": "/recipes/other", + "tags": [] + }, + { + "id": "example-repos", + "name": "Example Repos", + "description": "Examples of different ways to use Nx", + "file": "", + "itemList": [ + { + "id": "react-nx", + "name": "Powering Up React Development With Nx", + "description": "", + "file": "shared/examples/react-nx", + "itemList": [], + "isExternal": false, + "path": "/recipes/example-repos/react-nx", + "tags": [] + }, + { + "id": "apollo-react", + "name": "Using Apollo GraphQL", + "description": "", + "file": "shared/examples/apollo-react", + "itemList": [], + "isExternal": false, + "path": "/recipes/example-repos/apollo-react", + "tags": [] + }, + { + "id": "nestjs-prisma", + "name": "Using Prisma with NestJS", + "description": "", + "file": "shared/recipes/database/nestjs-prisma", + "itemList": [], + "isExternal": false, + "path": "/recipes/example-repos/nestjs-prisma", + "tags": ["database", "node"] + }, + { + "id": "mongo-fastify", + "name": "Using Mongo with Fastify", + "description": "", + "file": "shared/recipes/database/mongo-fastify", + "itemList": [], + "isExternal": false, + "path": "/recipes/example-repos/mongo-fastify", + "tags": ["database", "node"] + }, + { + "id": "redis-fastify", + "name": "Using Redis with Fastify", + "description": "", + "file": "shared/recipes/database/redis-fastify", + "itemList": [], + "isExternal": false, + "path": "/recipes/example-repos/redis-fastify", + "tags": ["database", "node"] + }, + { + "id": "postgres-fastify", + "name": "Using Postgres with Fastify", + "description": "", + "file": "shared/recipes/database/postgres-fastify", + "itemList": [], + "isExternal": false, + "path": "/recipes/example-repos/postgres-fastify", + "tags": ["database", "node"] + }, + { + "id": "serverless-fastify-planetscale", + "name": "Using PlanetScale with Serverless Fastify", + "description": "", + "file": "shared/recipes/database/serverless-fastify-planetscale", + "itemList": [], + "isExternal": false, + "path": "/recipes/example-repos/serverless-fastify-planetscale", + "tags": ["database", "node", "serverless"] + }, + { + "id": "caching", + "name": "Large Repo and Caching", + "description": "", + "file": "shared/examples/caching", + "itemList": [], + "isExternal": false, + "path": "/recipes/example-repos/caching", + "tags": [] + }, + { + "id": "dte", + "name": "Large Repo and DTE", + "description": "", + "file": "shared/examples/dte", + "itemList": [], + "isExternal": false, + "path": "/recipes/example-repos/dte", + "tags": [] + }, + { + "id": "mfe", + "name": "Nx Micro-Frontend Example", + "description": "", + "file": "shared/examples/nx-examples", + "itemList": [], + "isExternal": false, + "path": "/recipes/example-repos/mfe", + "tags": [] + } + ], + "isExternal": false, + "path": "/recipes/example-repos", + "tags": [] + } + ], + "isExternal": false, + "path": "/recipes", + "tags": [] + }, + "/recipes/adopting-nx": { + "id": "adopting-nx", + "name": "Adopting Nx", + "description": "Adopting Nx incrementally, on existing project or from scratch.", + "file": "", + "itemList": [ + { + "id": "adding-to-monorepo", + "name": "NPM/Yarn/PNPM workspaces", + "description": "", + "file": "shared/migration/adding-to-monorepo", + "itemList": [], + "isExternal": false, + "path": "/recipes/adopting-nx/adding-to-monorepo", + "tags": [] + }, + { + "id": "adding-to-existing-project", + "name": "Add to any Project", + "description": "", + "file": "shared/migration/adding-to-existing-project", + "itemList": [], + "isExternal": false, + "path": "/recipes/adopting-nx/adding-to-existing-project", + "tags": [] + }, + { + "id": "lerna-and-nx", + "name": "Nx and Lerna", + "description": "", + "file": "shared/migration/lerna-and-nx", + "itemList": [], + "isExternal": false, + "path": "/recipes/adopting-nx/lerna-and-nx", + "tags": [] + }, + { + "id": "preserving-git-histories", + "name": "Preserving Git Histories", + "description": "", + "file": "shared/migration/preserving-git-histories", + "itemList": [], + "isExternal": false, + "path": "/recipes/adopting-nx/preserving-git-histories", + "tags": [] + }, + { + "id": "manual", + "name": "Manual migration", + "description": "", + "file": "shared/migration/manual", + "itemList": [], + "isExternal": false, + "path": "/recipes/adopting-nx/manual", + "tags": [] + } + ], + "isExternal": false, + "path": "/recipes/adopting-nx", + "tags": [] + }, + "/recipes/adopting-nx/adding-to-monorepo": { + "id": "adding-to-monorepo", + "name": "NPM/Yarn/PNPM workspaces", + "description": "", + "file": "shared/migration/adding-to-monorepo", + "itemList": [], + "isExternal": false, + "path": "/recipes/adopting-nx/adding-to-monorepo", + "tags": [] + }, + "/recipes/adopting-nx/adding-to-existing-project": { + "id": "adding-to-existing-project", + "name": "Add to any Project", + "description": "", + "file": "shared/migration/adding-to-existing-project", + "itemList": [], + "isExternal": false, + "path": "/recipes/adopting-nx/adding-to-existing-project", + "tags": [] + }, + "/recipes/adopting-nx/lerna-and-nx": { + "id": "lerna-and-nx", + "name": "Nx and Lerna", + "description": "", + "file": "shared/migration/lerna-and-nx", + "itemList": [], + "isExternal": false, + "path": "/recipes/adopting-nx/lerna-and-nx", + "tags": [] + }, + "/recipes/adopting-nx/preserving-git-histories": { + "id": "preserving-git-histories", + "name": "Preserving Git Histories", + "description": "", + "file": "shared/migration/preserving-git-histories", + "itemList": [], + "isExternal": false, + "path": "/recipes/adopting-nx/preserving-git-histories", + "tags": [] + }, + "/recipes/adopting-nx/manual": { + "id": "manual", + "name": "Manual migration", + "description": "", + "file": "shared/migration/manual", + "itemList": [], + "isExternal": false, + "path": "/recipes/adopting-nx/manual", + "tags": [] + }, + "/recipes/angular": { + "id": "angular", + "name": "Angular", + "description": "Advanced guides to adopt Nx in Angular.", + "file": "", + "itemList": [ + { + "id": "migration", + "name": "Migration", + "description": "", + "file": "", + "itemList": [ + { + "id": "angular", + "name": "Migrating from Angular CLI", + "description": "", + "file": "shared/migration/migration-angular", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/migration/angular", + "tags": [] + }, + { + "id": "angular-multiple", + "name": "Migrating From Multiple Angular CLI Repos", + "description": "", + "file": "shared/migration/angular-multiple", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/migration/angular-multiple", + "tags": [] + }, + { + "id": "angular-manual", + "name": "Migrating Angular Application manually", + "description": "", + "file": "shared/migration/angular-manual", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/migration/angular-manual", + "tags": [] + }, + { + "id": "angularjs", + "name": "Migrating from AngularJS", + "description": "", + "file": "shared/migration/migration-angularjs", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/migration/angularjs", + "tags": [] + } + ], + "isExternal": false, + "path": "/recipes/angular/migration", + "tags": [] + }, + { + "id": "use-environment-variables-in-angular", + "name": "Use Environment Variables in Angular", + "description": "", + "file": "shared/guides/use-environment-variables-in-angular", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/use-environment-variables-in-angular", + "tags": ["environment-variables"] + }, + { + "id": "using-tailwind-css-with-angular-projects", + "name": "Using Tailwind CSS with Angular projects", + "description": "", + "file": "shared/guides/using-tailwind-css-with-angular-projects", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/using-tailwind-css-with-angular-projects", + "tags": [] + }, + { + "id": "module-federation-with-ssr", + "name": "Setup Module Federation with SSR for Angular", + "description": "", + "file": "shared/recipes/module-federation-with-ssr", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/module-federation-with-ssr", + "tags": ["use-task-executors", "module-federation", "angular"] + }, + { + "id": "dynamic-module-federation-with-angular", + "name": "Advanced Micro Frontends with Angular using Dynamic Federation", + "description": "", + "file": "shared/guides/module-federation/dynamic-mfe-angular", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/dynamic-module-federation-with-angular", + "tags": ["use-task-executors", "module-federation", "angular"] + }, + { + "id": "setup-incremental-builds-angular", + "name": "Setup incremental builds for Angular applications", + "description": "", + "file": "shared/guides/setup-incremental-builds-angular", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/setup-incremental-builds-angular", + "tags": [] + } + ], + "isExternal": false, + "path": "/recipes/angular", + "tags": [] + }, + "/recipes/angular/migration": { + "id": "migration", + "name": "Migration", + "description": "", + "file": "", + "itemList": [ + { + "id": "angular", + "name": "Migrating from Angular CLI", + "description": "", + "file": "shared/migration/migration-angular", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/migration/angular", + "tags": [] + }, + { + "id": "angular-multiple", + "name": "Migrating From Multiple Angular CLI Repos", + "description": "", + "file": "shared/migration/angular-multiple", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/migration/angular-multiple", + "tags": [] + }, + { + "id": "angular-manual", + "name": "Migrating Angular Application manually", + "description": "", + "file": "shared/migration/angular-manual", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/migration/angular-manual", + "tags": [] + }, + { + "id": "angularjs", + "name": "Migrating from AngularJS", + "description": "", + "file": "shared/migration/migration-angularjs", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/migration/angularjs", + "tags": [] + } + ], + "isExternal": false, + "path": "/recipes/angular/migration", + "tags": [] + }, + "/recipes/angular/migration/angular": { + "id": "angular", + "name": "Migrating from Angular CLI", + "description": "", + "file": "shared/migration/migration-angular", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/migration/angular", + "tags": [] + }, + "/recipes/angular/migration/angular-multiple": { + "id": "angular-multiple", + "name": "Migrating From Multiple Angular CLI Repos", + "description": "", + "file": "shared/migration/angular-multiple", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/migration/angular-multiple", + "tags": [] + }, + "/recipes/angular/migration/angular-manual": { + "id": "angular-manual", + "name": "Migrating Angular Application manually", + "description": "", + "file": "shared/migration/angular-manual", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/migration/angular-manual", + "tags": [] + }, + "/recipes/angular/migration/angularjs": { + "id": "angularjs", + "name": "Migrating from AngularJS", + "description": "", + "file": "shared/migration/migration-angularjs", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/migration/angularjs", + "tags": [] + }, + "/recipes/angular/use-environment-variables-in-angular": { + "id": "use-environment-variables-in-angular", + "name": "Use Environment Variables in Angular", + "description": "", + "file": "shared/guides/use-environment-variables-in-angular", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/use-environment-variables-in-angular", + "tags": ["environment-variables"] + }, + "/recipes/angular/using-tailwind-css-with-angular-projects": { + "id": "using-tailwind-css-with-angular-projects", + "name": "Using Tailwind CSS with Angular projects", + "description": "", + "file": "shared/guides/using-tailwind-css-with-angular-projects", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/using-tailwind-css-with-angular-projects", + "tags": [] + }, + "/recipes/angular/module-federation-with-ssr": { + "id": "module-federation-with-ssr", + "name": "Setup Module Federation with SSR for Angular", + "description": "", + "file": "shared/recipes/module-federation-with-ssr", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/module-federation-with-ssr", + "tags": ["use-task-executors", "module-federation", "angular"] + }, + "/recipes/angular/dynamic-module-federation-with-angular": { + "id": "dynamic-module-federation-with-angular", + "name": "Advanced Micro Frontends with Angular using Dynamic Federation", + "description": "", + "file": "shared/guides/module-federation/dynamic-mfe-angular", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/dynamic-module-federation-with-angular", + "tags": ["use-task-executors", "module-federation", "angular"] + }, + "/recipes/angular/setup-incremental-builds-angular": { + "id": "setup-incremental-builds-angular", + "name": "Setup incremental builds for Angular applications", + "description": "", + "file": "shared/guides/setup-incremental-builds-angular", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/setup-incremental-builds-angular", + "tags": [] + }, + "/recipes/react": { + "id": "react", + "name": "React", + "description": "Advanced guides to adopt Nx in React.", + "file": "", + "itemList": [ + { + "id": "migration-cra", + "name": "Migrating from CRA", + "description": "", + "file": "shared/migration/migration-cra", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/migration-cra", + "tags": [] + }, + { + "id": "react-18", + "name": "React 18 Migration", + "description": "", + "file": "shared/guides/react-18", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/react-18", + "tags": [] + }, + { + "id": "react-native", + "name": "React Native with Nx", + "description": "", + "file": "shared/guides/react-native", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/react-native", + "tags": [] + }, + { + "id": "remix", + "name": "Remix with Nx", + "description": "", + "file": "shared/guides/remix", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/remix", + "tags": [] + }, + { + "id": "use-environment-variables-in-react", + "name": "Use Environment Variables in React", + "description": "", + "file": "shared/guides/use-environment-variables-in-react", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/use-environment-variables-in-react", + "tags": ["environment-variables"] + }, + { + "id": "using-tailwind-css-in-react", + "name": "Using Tailwind CSS in React", + "description": "", + "file": "shared/guides/using-tailwind-css-in-react", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/using-tailwind-css-in-react", + "tags": [] + }, + { + "id": "adding-assets-react", + "name": "Adding Images, Fonts, and Files", + "description": "", + "file": "shared/guides/adding-assets", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/adding-assets-react", + "tags": [] + }, + { + "id": "module-federation-with-ssr", + "name": "Setup Module Federation with SSR for React", + "description": "", + "file": "shared/recipes/module-federation-with-ssr", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/module-federation-with-ssr", + "tags": ["use-task-executors", "module-federation", "react"] + }, + { + "id": "deploy-nextjs-to-vercel", + "name": "Deploying Next.js applications to Vercel", + "description": "", + "file": "shared/recipes/deployment/deploy-nextjs-to-vercel", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/deploy-nextjs-to-vercel", + "tags": [] + } + ], + "isExternal": false, + "path": "/recipes/react", + "tags": [] + }, + "/recipes/react/migration-cra": { + "id": "migration-cra", + "name": "Migrating from CRA", + "description": "", + "file": "shared/migration/migration-cra", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/migration-cra", + "tags": [] + }, + "/recipes/react/react-18": { + "id": "react-18", + "name": "React 18 Migration", + "description": "", + "file": "shared/guides/react-18", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/react-18", + "tags": [] + }, + "/recipes/react/react-native": { + "id": "react-native", + "name": "React Native with Nx", + "description": "", + "file": "shared/guides/react-native", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/react-native", + "tags": [] + }, + "/recipes/react/remix": { + "id": "remix", + "name": "Remix with Nx", + "description": "", + "file": "shared/guides/remix", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/remix", + "tags": [] + }, + "/recipes/react/use-environment-variables-in-react": { + "id": "use-environment-variables-in-react", + "name": "Use Environment Variables in React", + "description": "", + "file": "shared/guides/use-environment-variables-in-react", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/use-environment-variables-in-react", + "tags": ["environment-variables"] + }, + "/recipes/react/using-tailwind-css-in-react": { + "id": "using-tailwind-css-in-react", + "name": "Using Tailwind CSS in React", + "description": "", + "file": "shared/guides/using-tailwind-css-in-react", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/using-tailwind-css-in-react", + "tags": [] + }, + "/recipes/react/adding-assets-react": { + "id": "adding-assets-react", + "name": "Adding Images, Fonts, and Files", + "description": "", + "file": "shared/guides/adding-assets", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/adding-assets-react", + "tags": [] + }, + "/recipes/react/module-federation-with-ssr": { + "id": "module-federation-with-ssr", + "name": "Setup Module Federation with SSR for React", + "description": "", + "file": "shared/recipes/module-federation-with-ssr", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/module-federation-with-ssr", + "tags": ["use-task-executors", "module-federation", "react"] + }, + "/recipes/react/deploy-nextjs-to-vercel": { + "id": "deploy-nextjs-to-vercel", + "name": "Deploying Next.js applications to Vercel", + "description": "", + "file": "shared/recipes/deployment/deploy-nextjs-to-vercel", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/deploy-nextjs-to-vercel", + "tags": [] + }, + "/recipes/node": { + "id": "node", + "name": "Node", + "description": "Set of Node related recipes.", + "file": "", + "itemList": [ + { + "id": "node-server-fly-io", + "name": "Deploying a Node App to Fly.io", + "description": "", + "file": "shared/recipes/deployment/node-server-fly-io", + "itemList": [], + "isExternal": false, + "path": "/recipes/node/node-server-fly-io", + "tags": ["deployment", "node"] + }, + { + "id": "node-serverless-functions-netlify", + "name": "Add and Deploy Netlify Edge Functions with Node", + "description": "", + "file": "shared/recipes/deployment/node-serverless-functions-netlify", + "itemList": [], + "isExternal": false, + "path": "/recipes/node/node-serverless-functions-netlify", + "tags": ["deployment", "node"] + }, + { + "id": "node-aws-lambda", + "name": "Deploying AWS lambda in Node.js", + "description": "", + "file": "shared/recipes/deployment/node-aws-lambda", + "itemList": [], + "isExternal": false, + "path": "/recipes/node/node-aws-lambda", + "tags": ["deployment", "node"] + } + ], + "isExternal": false, + "path": "/recipes/node", + "tags": [] + }, + "/recipes/node/node-server-fly-io": { + "id": "node-server-fly-io", + "name": "Deploying a Node App to Fly.io", + "description": "", + "file": "shared/recipes/deployment/node-server-fly-io", + "itemList": [], + "isExternal": false, + "path": "/recipes/node/node-server-fly-io", + "tags": ["deployment", "node"] + }, + "/recipes/node/node-serverless-functions-netlify": { + "id": "node-serverless-functions-netlify", + "name": "Add and Deploy Netlify Edge Functions with Node", + "description": "", + "file": "shared/recipes/deployment/node-serverless-functions-netlify", + "itemList": [], + "isExternal": false, + "path": "/recipes/node/node-serverless-functions-netlify", + "tags": ["deployment", "node"] + }, + "/recipes/node/node-aws-lambda": { + "id": "node-aws-lambda", + "name": "Deploying AWS lambda in Node.js", + "description": "", + "file": "shared/recipes/deployment/node-aws-lambda", + "itemList": [], + "isExternal": false, + "path": "/recipes/node/node-aws-lambda", + "tags": ["deployment", "node"] + }, + "/recipes/storybook": { + "id": "storybook", + "name": "Storybook", + "description": "Storybook how tos.", + "file": "", + "itemList": [ + { + "id": "one-storybook-for-all", + "name": "One main Storybook instance for all projects", + "description": "", + "file": "shared/recipes/one-storybook-for-all", + "itemList": [], + "isExternal": false, + "path": "/recipes/storybook/one-storybook-for-all", + "tags": ["storybook"] + }, + { + "id": "one-storybook-per-scope", + "name": "One Storybook instance per scope", + "description": "", + "file": "shared/recipes/one-storybook-per-scope", + "itemList": [], + "isExternal": false, + "path": "/recipes/storybook/one-storybook-per-scope", + "tags": ["storybook"] + }, + { + "id": "one-storybook-with-composition", + "name": "One main Storybook instance using Storybook Composition", + "description": "", + "file": "shared/recipes/one-storybook-with-composition", + "itemList": [], + "isExternal": false, + "path": "/recipes/storybook/one-storybook-with-composition", + "tags": ["storybook"] + } + ], + "isExternal": false, + "path": "/recipes/storybook", + "tags": [] + }, + "/recipes/storybook/one-storybook-for-all": { + "id": "one-storybook-for-all", + "name": "One main Storybook instance for all projects", + "description": "", + "file": "shared/recipes/one-storybook-for-all", + "itemList": [], + "isExternal": false, + "path": "/recipes/storybook/one-storybook-for-all", + "tags": ["storybook"] + }, + "/recipes/storybook/one-storybook-per-scope": { + "id": "one-storybook-per-scope", + "name": "One Storybook instance per scope", + "description": "", + "file": "shared/recipes/one-storybook-per-scope", + "itemList": [], + "isExternal": false, + "path": "/recipes/storybook/one-storybook-per-scope", + "tags": ["storybook"] + }, + "/recipes/storybook/one-storybook-with-composition": { + "id": "one-storybook-with-composition", + "name": "One main Storybook instance using Storybook Composition", + "description": "", + "file": "shared/recipes/one-storybook-with-composition", + "itemList": [], + "isExternal": false, + "path": "/recipes/storybook/one-storybook-with-composition", + "tags": ["storybook"] + }, + "/recipes/enforce-module-boundaries": { + "id": "enforce-module-boundaries", + "name": "Enforce Module Boundaries", + "description": "Configuring the enforce module boundaries rule", + "file": "", + "itemList": [ + { + "id": "ban-dependencies-with-tags", + "name": "Ban Dependencies with Certain Tags", + "description": "", + "file": "shared/recipes/ban-dependencies-with-tags", + "itemList": [], + "isExternal": false, + "path": "/recipes/enforce-module-boundaries/ban-dependencies-with-tags", + "tags": ["enforce-project-boundaries"] + }, + { + "id": "tag-multiple-dimensions", + "name": "Tag in Multiple Dimensions", + "description": "", + "file": "shared/recipes/tag-multiple-dimensions", + "itemList": [], + "isExternal": false, + "path": "/recipes/enforce-module-boundaries/tag-multiple-dimensions", + "tags": ["enforce-project-boundaries"] + }, + { + "id": "ban-external-imports", + "name": "Ban External Imports", + "description": "", + "file": "shared/recipes/ban-external-imports", + "itemList": [], + "isExternal": false, + "path": "/recipes/enforce-module-boundaries/ban-external-imports", + "tags": ["enforce-project-boundaries"] + }, + { + "id": "tags-allow-list", + "name": "Tags Allow List", + "description": "", + "file": "shared/recipes/tags-allow-list", + "itemList": [], + "isExternal": false, + "path": "/recipes/enforce-module-boundaries/tags-allow-list", + "tags": ["enforce-project-boundaries"] + } + ], + "isExternal": false, + "path": "/recipes/enforce-module-boundaries", + "tags": [] + }, + "/recipes/enforce-module-boundaries/ban-dependencies-with-tags": { + "id": "ban-dependencies-with-tags", + "name": "Ban Dependencies with Certain Tags", + "description": "", + "file": "shared/recipes/ban-dependencies-with-tags", + "itemList": [], + "isExternal": false, + "path": "/recipes/enforce-module-boundaries/ban-dependencies-with-tags", + "tags": ["enforce-project-boundaries"] + }, + "/recipes/enforce-module-boundaries/tag-multiple-dimensions": { + "id": "tag-multiple-dimensions", + "name": "Tag in Multiple Dimensions", + "description": "", + "file": "shared/recipes/tag-multiple-dimensions", + "itemList": [], + "isExternal": false, + "path": "/recipes/enforce-module-boundaries/tag-multiple-dimensions", + "tags": ["enforce-project-boundaries"] + }, + "/recipes/enforce-module-boundaries/ban-external-imports": { + "id": "ban-external-imports", + "name": "Ban External Imports", + "description": "", + "file": "shared/recipes/ban-external-imports", + "itemList": [], + "isExternal": false, + "path": "/recipes/enforce-module-boundaries/ban-external-imports", + "tags": ["enforce-project-boundaries"] + }, + "/recipes/enforce-module-boundaries/tags-allow-list": { + "id": "tags-allow-list", + "name": "Tags Allow List", + "description": "", + "file": "shared/recipes/tags-allow-list", + "itemList": [], + "isExternal": false, + "path": "/recipes/enforce-module-boundaries/tags-allow-list", + "tags": ["enforce-project-boundaries"] + }, + "/recipes/ci": { + "id": "ci", + "name": "CI", + "description": "All recipes about how to use Nx to make your CI faster.", + "file": "", + "itemList": [ + { + "id": "ci-setup", + "name": "CI Setup", + "description": "", + "file": "shared/ci-overview", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/ci-setup", + "tags": ["distribute-task-execution"] + }, + { + "id": "ci-deployment", + "name": "Prepare applications for deployment via CI", + "description": "", + "file": "shared/recipes/ci-deployment", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/ci-deployment", + "tags": ["docker", "deploy"] + }, + { + "id": "monorepo-ci-azure", + "name": "Setting up Azure Pipelines", + "description": "", + "file": "shared/monorepo-ci-azure", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/monorepo-ci-azure", + "tags": [] + }, + { + "id": "monorepo-ci-circle-ci", + "name": "Setting up CircleCI", + "description": "", + "file": "shared/monorepo-ci-circle-ci", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/monorepo-ci-circle-ci", + "tags": [] + }, + { + "id": "monorepo-ci-github-actions", + "name": "Setting up GitHub Actions", + "description": "", + "file": "shared/monorepo-ci-github-actions", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/monorepo-ci-github-actions", + "tags": [] + }, + { + "id": "monorepo-ci-jenkins", + "name": "Setting up Jenkins", + "description": "", + "file": "shared/monorepo-ci-jenkins", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/monorepo-ci-jenkins", + "tags": [] + }, + { + "id": "monorepo-ci-gitlab", + "name": "Setting up GitLab", + "description": "", + "file": "shared/monorepo-ci-gitlab", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/monorepo-ci-gitlab", + "tags": [] + }, + { + "id": "monorepo-ci-bitbucket-pipelines", + "name": "Setting up Bitbucket", + "description": "", + "file": "shared/monorepo-ci-bitbucket-pipelines", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/monorepo-ci-bitbucket-pipelines", + "tags": [] + } + ], + "isExternal": false, + "path": "/recipes/ci", + "tags": [] + }, + "/recipes/ci/ci-setup": { + "id": "ci-setup", + "name": "CI Setup", + "description": "", + "file": "shared/ci-overview", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/ci-setup", + "tags": ["distribute-task-execution"] + }, + "/recipes/ci/ci-deployment": { + "id": "ci-deployment", + "name": "Prepare applications for deployment via CI", + "description": "", + "file": "shared/recipes/ci-deployment", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/ci-deployment", + "tags": ["docker", "deploy"] + }, + "/recipes/ci/monorepo-ci-azure": { + "id": "monorepo-ci-azure", + "name": "Setting up Azure Pipelines", + "description": "", + "file": "shared/monorepo-ci-azure", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/monorepo-ci-azure", + "tags": [] + }, + "/recipes/ci/monorepo-ci-circle-ci": { + "id": "monorepo-ci-circle-ci", + "name": "Setting up CircleCI", + "description": "", + "file": "shared/monorepo-ci-circle-ci", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/monorepo-ci-circle-ci", + "tags": [] + }, + "/recipes/ci/monorepo-ci-github-actions": { + "id": "monorepo-ci-github-actions", + "name": "Setting up GitHub Actions", + "description": "", + "file": "shared/monorepo-ci-github-actions", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/monorepo-ci-github-actions", + "tags": [] + }, + "/recipes/ci/monorepo-ci-jenkins": { + "id": "monorepo-ci-jenkins", + "name": "Setting up Jenkins", + "description": "", + "file": "shared/monorepo-ci-jenkins", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/monorepo-ci-jenkins", + "tags": [] + }, + "/recipes/ci/monorepo-ci-gitlab": { + "id": "monorepo-ci-gitlab", + "name": "Setting up GitLab", + "description": "", + "file": "shared/monorepo-ci-gitlab", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/monorepo-ci-gitlab", + "tags": [] + }, + "/recipes/ci/monorepo-ci-bitbucket-pipelines": { + "id": "monorepo-ci-bitbucket-pipelines", + "name": "Setting up Bitbucket", + "description": "", + "file": "shared/monorepo-ci-bitbucket-pipelines", + "itemList": [], + "isExternal": false, + "path": "/recipes/ci/monorepo-ci-bitbucket-pipelines", + "tags": [] + }, + "/recipes/nx-console": { + "id": "nx-console", + "name": "Nx Console", + "description": "Checkout all the recipes related to Nx Console.", + "file": "", + "itemList": [ + { + "id": "console-telemetry", + "name": "Telemetry", + "description": "", + "file": "shared/recipes/console-telemetry", + "itemList": [], + "isExternal": false, + "path": "/recipes/nx-console/console-telemetry", + "tags": ["integrate-with-editors"] + }, + { + "id": "console-generate-command", + "name": "Generate Command", + "description": "", + "file": "shared/recipes/console-generate-command", + "itemList": [], + "isExternal": false, + "path": "/recipes/nx-console/console-generate-command", + "tags": ["integrate-with-editors"] + }, + { + "id": "console-run-command", + "name": "Run Command", + "description": "", + "file": "shared/recipes/console-run-command", + "itemList": [], + "isExternal": false, + "path": "/recipes/nx-console/console-run-command", + "tags": ["integrate-with-editors"] + }, + { + "id": "console-add-dependency-command", + "name": "Add Dependency Command", + "description": "", + "file": "shared/recipes/console-add-dependency-command", + "itemList": [], + "isExternal": false, + "path": "/recipes/nx-console/console-add-dependency-command", + "tags": ["integrate-with-editors"] + }, + { + "id": "console-project-pane", + "name": "Project Pane", + "description": "", + "file": "shared/recipes/console-project-pane", + "itemList": [], + "isExternal": false, + "path": "/recipes/nx-console/console-project-pane", + "tags": ["integrate-with-editors"] + }, + { + "id": "console-shortcuts", + "name": "Keyboard Shortcuts", + "description": "", + "file": "shared/recipes/console-shortcuts", + "itemList": [], + "isExternal": false, + "path": "/recipes/nx-console/console-shortcuts", + "tags": ["integrate-with-editors"] + } + ], + "isExternal": false, + "path": "/recipes/nx-console", + "tags": [] + }, + "/recipes/nx-console/console-telemetry": { + "id": "console-telemetry", + "name": "Telemetry", + "description": "", + "file": "shared/recipes/console-telemetry", + "itemList": [], + "isExternal": false, + "path": "/recipes/nx-console/console-telemetry", + "tags": ["integrate-with-editors"] + }, + "/recipes/nx-console/console-generate-command": { + "id": "console-generate-command", + "name": "Generate Command", + "description": "", + "file": "shared/recipes/console-generate-command", + "itemList": [], + "isExternal": false, + "path": "/recipes/nx-console/console-generate-command", + "tags": ["integrate-with-editors"] + }, + "/recipes/nx-console/console-run-command": { + "id": "console-run-command", + "name": "Run Command", + "description": "", + "file": "shared/recipes/console-run-command", + "itemList": [], + "isExternal": false, + "path": "/recipes/nx-console/console-run-command", + "tags": ["integrate-with-editors"] + }, + "/recipes/nx-console/console-add-dependency-command": { + "id": "console-add-dependency-command", + "name": "Add Dependency Command", + "description": "", + "file": "shared/recipes/console-add-dependency-command", + "itemList": [], + "isExternal": false, + "path": "/recipes/nx-console/console-add-dependency-command", + "tags": ["integrate-with-editors"] + }, + "/recipes/nx-console/console-project-pane": { + "id": "console-project-pane", + "name": "Project Pane", + "description": "", + "file": "shared/recipes/console-project-pane", + "itemList": [], + "isExternal": false, + "path": "/recipes/nx-console/console-project-pane", + "tags": ["integrate-with-editors"] + }, + "/recipes/nx-console/console-shortcuts": { + "id": "console-shortcuts", + "name": "Keyboard Shortcuts", + "description": "", + "file": "shared/recipes/console-shortcuts", + "itemList": [], + "isExternal": false, + "path": "/recipes/nx-console/console-shortcuts", + "tags": ["integrate-with-editors"] + }, + "/recipes/troubleshooting": { + "id": "troubleshooting", + "name": "Troubleshooting", + "description": "Learn how to troubleshoot common problems.", + "file": "", + "itemList": [ + { + "id": "resolve-circular-dependencies", + "name": "Resolve Circular Dependencies", + "description": "", + "file": "shared/recipes/resolve-circular-dependencies", + "itemList": [], + "isExternal": false, + "path": "/recipes/troubleshooting/resolve-circular-dependencies", + "tags": ["explore-graph"] + }, + { + "id": "troubleshoot-nx-install-issues", + "name": "Troubleshooting Nx Install Issues", + "description": "", + "file": "shared/installation/troubleshoot-installation", + "itemList": [], + "isExternal": false, + "path": "/recipes/troubleshooting/troubleshoot-nx-install-issues", + "tags": [] + }, + { + "id": "troubleshoot-cache-misses", + "name": "Troubleshoot Cache Misses", + "description": "", + "file": "shared/recipes/troubleshoot-cache-misses", + "itemList": [], + "isExternal": false, + "path": "/recipes/troubleshooting/troubleshoot-cache-misses", + "tags": ["cache-task-results"] + }, + { + "id": "unknown-local-cache", + "name": "Unknown Local Cache Error", + "description": "", + "file": "shared/guides/unknown-local-cache", + "itemList": [], + "isExternal": false, + "path": "/recipes/troubleshooting/unknown-local-cache", + "tags": [] + }, + { + "id": "performance-profiling", + "name": "Profiling Build Performance", + "description": "", + "file": "shared/guides/performance-profiling", + "itemList": [], + "isExternal": false, + "path": "/recipes/troubleshooting/performance-profiling", + "tags": ["use-task-executors", "environment-variables"] + } + ], + "isExternal": false, + "path": "/recipes/troubleshooting", + "tags": [] + }, + "/recipes/troubleshooting/resolve-circular-dependencies": { + "id": "resolve-circular-dependencies", + "name": "Resolve Circular Dependencies", + "description": "", + "file": "shared/recipes/resolve-circular-dependencies", + "itemList": [], + "isExternal": false, + "path": "/recipes/troubleshooting/resolve-circular-dependencies", + "tags": ["explore-graph"] + }, + "/recipes/troubleshooting/troubleshoot-nx-install-issues": { + "id": "troubleshoot-nx-install-issues", + "name": "Troubleshooting Nx Install Issues", + "description": "", + "file": "shared/installation/troubleshoot-installation", + "itemList": [], + "isExternal": false, + "path": "/recipes/troubleshooting/troubleshoot-nx-install-issues", + "tags": [] + }, + "/recipes/troubleshooting/troubleshoot-cache-misses": { + "id": "troubleshoot-cache-misses", + "name": "Troubleshoot Cache Misses", + "description": "", + "file": "shared/recipes/troubleshoot-cache-misses", + "itemList": [], + "isExternal": false, + "path": "/recipes/troubleshooting/troubleshoot-cache-misses", + "tags": ["cache-task-results"] + }, + "/recipes/troubleshooting/unknown-local-cache": { + "id": "unknown-local-cache", + "name": "Unknown Local Cache Error", + "description": "", + "file": "shared/guides/unknown-local-cache", + "itemList": [], + "isExternal": false, + "path": "/recipes/troubleshooting/unknown-local-cache", + "tags": [] + }, + "/recipes/troubleshooting/performance-profiling": { + "id": "performance-profiling", + "name": "Profiling Build Performance", + "description": "", + "file": "shared/guides/performance-profiling", + "itemList": [], + "isExternal": false, + "path": "/recipes/troubleshooting/performance-profiling", + "tags": ["use-task-executors", "environment-variables"] + }, + "/recipes/tips-n-tricks": { + "id": "tips-n-tricks", + "name": "Tips and tricks", + "description": "Various tips and tricks for using Nx.", + "file": "", + "itemList": [ + { + "id": "eslint", + "name": "Configuring ESLint with Typescript", + "description": "", + "file": "shared/eslint", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/eslint", + "tags": [] + }, + { + "id": "define-environment-variables", + "name": "Define Environment Variables", + "description": "", + "file": "shared/guides/define-environment-variables", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/define-environment-variables", + "tags": ["environment-variables"] + }, + { + "id": "browser-support", + "name": "Configuring Browser Support", + "description": "", + "file": "shared/guides/browser-support", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/browser-support", + "tags": [] + }, + { + "id": "include-assets-in-build", + "name": "Include Assets in Build", + "description": "", + "file": "shared/recipes/include-assets-in-build", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/include-assets-in-build", + "tags": [] + }, + { + "id": "include-all-packagejson", + "name": "Include All package.json Files as Projects", + "description": "", + "file": "shared/recipes/include-all-packagejson", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/include-all-packagejson", + "tags": [] + }, + { + "id": "identify-dependencies-between-folders", + "name": "Identify Dependencies Between Folders", + "description": "", + "file": "shared/recipes/identify-dependencies-between-folders", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/identify-dependencies-between-folders", + "tags": [] + }, + { + "id": "root-level-scripts", + "name": "Run Root-Level NPM Scripts with Nx", + "description": "", + "file": "shared/recipes/root-level-scripts", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/root-level-scripts", + "tags": ["run-tasks"] + }, + { + "id": "analyze-source-files", + "name": "Disable Graph Links Created from Analyzing Source Files", + "description": "", + "file": "shared/recipes/analyze-source-files", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/analyze-source-files", + "tags": ["explore-graph"] + }, + { + "id": "workspace-watching", + "name": "Workspace Watching", + "description": "", + "file": "shared/recipes/workspace-watching", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/workspace-watching", + "tags": ["workspace-watching"] + }, + { + "id": "standalone-to-integrated", + "name": "Convert from a Standalone Repository to an Integrated Repository", + "description": "", + "file": "shared/recipes/repo-types/standalone-to-integrated", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/standalone-to-integrated", + "tags": ["repository-types"] + }, + { + "id": "js-and-ts", + "name": "Use JavaScript instead TypeScript", + "description": "", + "file": "shared/guides/js-and-ts", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/js-and-ts", + "tags": [] + }, + { + "id": "advanced-update", + "name": "Altering Migration Process", + "description": "", + "file": "shared/recipes/advanced-update", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/advanced-update", + "tags": ["automate-updating-dependencies"] + }, + { + "id": "run-commands-executor", + "name": "Running Custom Commands", + "description": "", + "file": "shared/running-custom-commands", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/run-commands-executor", + "tags": ["use-task-executors"] + } + ], + "isExternal": false, + "path": "/recipes/tips-n-tricks", + "tags": [] + }, + "/recipes/tips-n-tricks/eslint": { + "id": "eslint", + "name": "Configuring ESLint with Typescript", "description": "", - "file": "", + "file": "shared/eslint", "itemList": [], "isExternal": false, - "path": "/recipes", + "path": "/recipes/tips-n-tricks/eslint", "tags": [] }, - "/recipes/ci/ci-setup": { - "id": "ci-setup", - "name": "CI Setup", + "/recipes/tips-n-tricks/define-environment-variables": { + "id": "define-environment-variables", + "name": "Define Environment Variables", "description": "", - "file": "", + "file": "shared/guides/define-environment-variables", "itemList": [], "isExternal": false, - "path": "/recipes/ci/ci-setup", + "path": "/recipes/tips-n-tricks/define-environment-variables", + "tags": ["environment-variables"] + }, + "/recipes/tips-n-tricks/browser-support": { + "id": "browser-support", + "name": "Configuring Browser Support", + "description": "", + "file": "shared/guides/browser-support", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/browser-support", "tags": [] }, - "/recipes/adopting-nx": { - "id": "adopting-nx", - "name": "Adopting Nx", + "/recipes/tips-n-tricks/include-assets-in-build": { + "id": "include-assets-in-build", + "name": "Include Assets in Build", + "description": "", + "file": "shared/recipes/include-assets-in-build", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/include-assets-in-build", + "tags": [] + }, + "/recipes/tips-n-tricks/include-all-packagejson": { + "id": "include-all-packagejson", + "name": "Include All package.json Files as Projects", + "description": "", + "file": "shared/recipes/include-all-packagejson", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/include-all-packagejson", + "tags": [] + }, + "/recipes/tips-n-tricks/identify-dependencies-between-folders": { + "id": "identify-dependencies-between-folders", + "name": "Identify Dependencies Between Folders", + "description": "", + "file": "shared/recipes/identify-dependencies-between-folders", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/identify-dependencies-between-folders", + "tags": [] + }, + "/recipes/tips-n-tricks/root-level-scripts": { + "id": "root-level-scripts", + "name": "Run Root-Level NPM Scripts with Nx", + "description": "", + "file": "shared/recipes/root-level-scripts", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/root-level-scripts", + "tags": ["run-tasks"] + }, + "/recipes/tips-n-tricks/analyze-source-files": { + "id": "analyze-source-files", + "name": "Disable Graph Links Created from Analyzing Source Files", + "description": "", + "file": "shared/recipes/analyze-source-files", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/analyze-source-files", + "tags": ["explore-graph"] + }, + "/recipes/tips-n-tricks/workspace-watching": { + "id": "workspace-watching", + "name": "Workspace Watching", + "description": "", + "file": "shared/recipes/workspace-watching", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/workspace-watching", + "tags": ["workspace-watching"] + }, + "/recipes/tips-n-tricks/standalone-to-integrated": { + "id": "standalone-to-integrated", + "name": "Convert from a Standalone Repository to an Integrated Repository", + "description": "", + "file": "shared/recipes/repo-types/standalone-to-integrated", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/standalone-to-integrated", + "tags": ["repository-types"] + }, + "/recipes/tips-n-tricks/js-and-ts": { + "id": "js-and-ts", + "name": "Use JavaScript instead TypeScript", + "description": "", + "file": "shared/guides/js-and-ts", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/js-and-ts", + "tags": [] + }, + "/recipes/tips-n-tricks/advanced-update": { + "id": "advanced-update", + "name": "Altering Migration Process", + "description": "", + "file": "shared/recipes/advanced-update", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/advanced-update", + "tags": ["automate-updating-dependencies"] + }, + "/recipes/tips-n-tricks/run-commands-executor": { + "id": "run-commands-executor", + "name": "Running Custom Commands", + "description": "", + "file": "shared/running-custom-commands", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/run-commands-executor", + "tags": ["use-task-executors"] + }, + "/recipes/other": { + "id": "other", + "name": "Other", + "description": "Other recipes you will find useful.", + "file": "", + "itemList": [ + { + "id": "deno-deploy", + "name": "Serverless deployment with Deno Deploy", + "description": "", + "file": "shared/recipes/deployment/deno-deploy", + "itemList": [], + "isExternal": false, + "path": "/recipes/other/deno-deploy", + "tags": ["deployment", "deno"] + }, + { + "id": "deno-netlify-functions", + "name": "Add and Deploy Netlify Edge Functions with Deno", + "description": "", + "file": "shared/recipes/deployment/deno-netlify-edge-functions", + "itemList": [], + "isExternal": false, + "path": "/recipes/other/deno-netlify-functions", + "tags": ["deployment", "deno"] + }, + { + "id": "rescope", + "name": "Rescope Packages from @nrwl to @nx", + "description": "", + "file": "shared/recipes/rescope", + "itemList": [], + "isExternal": false, + "path": "/recipes/other/rescope", + "tags": [] + } + ], + "isExternal": false, + "path": "/recipes/other", + "tags": [] + }, + "/recipes/other/deno-deploy": { + "id": "deno-deploy", + "name": "Serverless deployment with Deno Deploy", + "description": "", + "file": "shared/recipes/deployment/deno-deploy", + "itemList": [], + "isExternal": false, + "path": "/recipes/other/deno-deploy", + "tags": ["deployment", "deno"] + }, + "/recipes/other/deno-netlify-functions": { + "id": "deno-netlify-functions", + "name": "Add and Deploy Netlify Edge Functions with Deno", "description": "", + "file": "shared/recipes/deployment/deno-netlify-edge-functions", + "itemList": [], + "isExternal": false, + "path": "/recipes/other/deno-netlify-functions", + "tags": ["deployment", "deno"] + }, + "/recipes/other/rescope": { + "id": "rescope", + "name": "Rescope Packages from @nrwl to @nx", + "description": "", + "file": "shared/recipes/rescope", + "itemList": [], + "isExternal": false, + "path": "/recipes/other/rescope", + "tags": [] + }, + "/recipes/example-repos": { + "id": "example-repos", + "name": "Example Repos", + "description": "Examples of different ways to use Nx", "file": "", + "itemList": [ + { + "id": "react-nx", + "name": "Powering Up React Development With Nx", + "description": "", + "file": "shared/examples/react-nx", + "itemList": [], + "isExternal": false, + "path": "/recipes/example-repos/react-nx", + "tags": [] + }, + { + "id": "apollo-react", + "name": "Using Apollo GraphQL", + "description": "", + "file": "shared/examples/apollo-react", + "itemList": [], + "isExternal": false, + "path": "/recipes/example-repos/apollo-react", + "tags": [] + }, + { + "id": "nestjs-prisma", + "name": "Using Prisma with NestJS", + "description": "", + "file": "shared/recipes/database/nestjs-prisma", + "itemList": [], + "isExternal": false, + "path": "/recipes/example-repos/nestjs-prisma", + "tags": ["database", "node"] + }, + { + "id": "mongo-fastify", + "name": "Using Mongo with Fastify", + "description": "", + "file": "shared/recipes/database/mongo-fastify", + "itemList": [], + "isExternal": false, + "path": "/recipes/example-repos/mongo-fastify", + "tags": ["database", "node"] + }, + { + "id": "redis-fastify", + "name": "Using Redis with Fastify", + "description": "", + "file": "shared/recipes/database/redis-fastify", + "itemList": [], + "isExternal": false, + "path": "/recipes/example-repos/redis-fastify", + "tags": ["database", "node"] + }, + { + "id": "postgres-fastify", + "name": "Using Postgres with Fastify", + "description": "", + "file": "shared/recipes/database/postgres-fastify", + "itemList": [], + "isExternal": false, + "path": "/recipes/example-repos/postgres-fastify", + "tags": ["database", "node"] + }, + { + "id": "serverless-fastify-planetscale", + "name": "Using PlanetScale with Serverless Fastify", + "description": "", + "file": "shared/recipes/database/serverless-fastify-planetscale", + "itemList": [], + "isExternal": false, + "path": "/recipes/example-repos/serverless-fastify-planetscale", + "tags": ["database", "node", "serverless"] + }, + { + "id": "caching", + "name": "Large Repo and Caching", + "description": "", + "file": "shared/examples/caching", + "itemList": [], + "isExternal": false, + "path": "/recipes/example-repos/caching", + "tags": [] + }, + { + "id": "dte", + "name": "Large Repo and DTE", + "description": "", + "file": "shared/examples/dte", + "itemList": [], + "isExternal": false, + "path": "/recipes/example-repos/dte", + "tags": [] + }, + { + "id": "mfe", + "name": "Nx Micro-Frontend Example", + "description": "", + "file": "shared/examples/nx-examples", + "itemList": [], + "isExternal": false, + "path": "/recipes/example-repos/mfe", + "tags": [] + } + ], + "isExternal": false, + "path": "/recipes/example-repos", + "tags": [] + }, + "/recipes/example-repos/react-nx": { + "id": "react-nx", + "name": "Powering Up React Development With Nx", + "description": "", + "file": "shared/examples/react-nx", "itemList": [], "isExternal": false, - "path": "/recipes/adopting-nx", + "path": "/recipes/example-repos/react-nx", + "tags": [] + }, + "/recipes/example-repos/apollo-react": { + "id": "apollo-react", + "name": "Using Apollo GraphQL", + "description": "", + "file": "shared/examples/apollo-react", + "itemList": [], + "isExternal": false, + "path": "/recipes/example-repos/apollo-react", + "tags": [] + }, + "/recipes/example-repos/nestjs-prisma": { + "id": "nestjs-prisma", + "name": "Using Prisma with NestJS", + "description": "", + "file": "shared/recipes/database/nestjs-prisma", + "itemList": [], + "isExternal": false, + "path": "/recipes/example-repos/nestjs-prisma", + "tags": ["database", "node"] + }, + "/recipes/example-repos/mongo-fastify": { + "id": "mongo-fastify", + "name": "Using Mongo with Fastify", + "description": "", + "file": "shared/recipes/database/mongo-fastify", + "itemList": [], + "isExternal": false, + "path": "/recipes/example-repos/mongo-fastify", + "tags": ["database", "node"] + }, + "/recipes/example-repos/redis-fastify": { + "id": "redis-fastify", + "name": "Using Redis with Fastify", + "description": "", + "file": "shared/recipes/database/redis-fastify", + "itemList": [], + "isExternal": false, + "path": "/recipes/example-repos/redis-fastify", + "tags": ["database", "node"] + }, + "/recipes/example-repos/postgres-fastify": { + "id": "postgres-fastify", + "name": "Using Postgres with Fastify", + "description": "", + "file": "shared/recipes/database/postgres-fastify", + "itemList": [], + "isExternal": false, + "path": "/recipes/example-repos/postgres-fastify", + "tags": ["database", "node"] + }, + "/recipes/example-repos/serverless-fastify-planetscale": { + "id": "serverless-fastify-planetscale", + "name": "Using PlanetScale with Serverless Fastify", + "description": "", + "file": "shared/recipes/database/serverless-fastify-planetscale", + "itemList": [], + "isExternal": false, + "path": "/recipes/example-repos/serverless-fastify-planetscale", + "tags": ["database", "node", "serverless"] + }, + "/recipes/example-repos/caching": { + "id": "caching", + "name": "Large Repo and Caching", + "description": "", + "file": "shared/examples/caching", + "itemList": [], + "isExternal": false, + "path": "/recipes/example-repos/caching", + "tags": [] + }, + "/recipes/example-repos/dte": { + "id": "dte", + "name": "Large Repo and DTE", + "description": "", + "file": "shared/examples/dte", + "itemList": [], + "isExternal": false, + "path": "/recipes/example-repos/dte", + "tags": [] + }, + "/recipes/example-repos/mfe": { + "id": "mfe", + "name": "Nx Micro-Frontend Example", + "description": "", + "file": "shared/examples/nx-examples", + "itemList": [], + "isExternal": false, + "path": "/recipes/example-repos/mfe", "tags": [] }, "/reference": { diff --git a/docs/generated/manifests/tags.json b/docs/generated/manifests/tags.json index ee48258c3164b..f4eedb8d4124a 100644 --- a/docs/generated/manifests/tags.json +++ b/docs/generated/manifests/tags.json @@ -79,6 +79,13 @@ "name": "Customizing Inputs", "path": "/concepts/more-concepts/customizing-inputs" }, + { + "description": "", + "file": "shared/recipes/troubleshoot-cache-misses", + "id": "troubleshoot-cache-misses", + "name": "Troubleshoot Cache Misses", + "path": "/recipes/troubleshooting/troubleshoot-cache-misses" + }, { "description": "", "file": "", @@ -114,13 +121,6 @@ "name": "Project Configuration reference: inputs and namedInputs", "path": "/reference/project-configuration#inputs-&-namedinputs" }, - { - "description": "", - "file": "shared/recipes/troubleshoot-cache-misses", - "id": "troubleshoot-cache-misses", - "name": "Troubleshoot Cache Misses", - "path": "/recipes/troubleshooting/troubleshoot-cache-misses" - }, { "description": "The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.", "file": "generated/packages/generated/packages/nx/documents/connect-to-nx-cloud", @@ -211,13 +211,6 @@ "name": "Illustrated Distributed Task Execution", "path": "/concepts/more-concepts/illustrated-dte" }, - { - "description": "", - "file": "", - "id": "nx-cloud-documentation", - "name": "Nx Cloud Documentation", - "path": "/nx-cloud/intro/what-is-nx-cloud" - }, { "description": "", "file": "shared/ci-overview", @@ -225,6 +218,13 @@ "name": "CI Setup", "path": "/recipes/ci/ci-setup" }, + { + "description": "", + "file": "", + "id": "nx-cloud-documentation", + "name": "Nx Cloud Documentation", + "path": "/nx-cloud/intro/what-is-nx-cloud" + }, { "description": "The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.", "file": "generated/packages/generated/packages/nx/documents/connect-to-nx-cloud", @@ -350,20 +350,6 @@ "name": "Grouping Libraries", "path": "/concepts/more-concepts/grouping-libraries" }, - { - "description": "", - "file": "shared/reference/nxignore", - "id": "nxignore", - "name": ".nxignore", - "path": "/reference/nxignore" - }, - { - "description": "", - "file": "", - "id": "nxjson-workspaceLayout", - "name": "nx.json workspaceLayout property", - "path": "/reference/nx-json#workspace-layout" - }, { "description": "", "file": "shared/recipes/ban-dependencies-with-tags", @@ -392,6 +378,20 @@ "name": "Tags Allow List", "path": "/recipes/enforce-module-boundaries/tags-allow-list" }, + { + "description": "", + "file": "shared/reference/nxignore", + "id": "nxignore", + "name": ".nxignore", + "path": "/reference/nxignore" + }, + { + "description": "", + "file": "", + "id": "nxjson-workspaceLayout", + "name": "nx.json workspaceLayout property", + "path": "/reference/nx-json#workspace-layout" + }, { "description": "The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.", "file": "generated/packages/generated/packages/nx/documents/format-check", @@ -436,13 +436,6 @@ "name": "Incremental Builds", "path": "/concepts/more-concepts/incremental-builds" }, - { - "description": "", - "file": "shared/reference/project-configuration", - "id": "project-configuration", - "name": "Project Configuration", - "path": "/reference/project-configuration" - }, { "description": "", "file": "shared/recipes/module-federation-with-ssr", @@ -478,6 +471,13 @@ "name": "Running Custom Commands", "path": "/recipes/tips-n-tricks/run-commands-executor" }, + { + "description": "", + "file": "shared/reference/project-configuration", + "id": "project-configuration", + "name": "Project Configuration", + "path": "/reference/project-configuration" + }, { "description": "", "file": "shared/recipes/plugins/local-executors", @@ -649,13 +649,6 @@ } ], "environment-variables": [ - { - "description": "", - "file": "shared/reference/environment-variables", - "id": "environment-variables", - "name": "Environment Variables", - "path": "/reference/environment-variables" - }, { "description": "", "file": "shared/guides/use-environment-variables-in-angular", @@ -683,6 +676,13 @@ "id": "define-environment-variables", "name": "Define Environment Variables", "path": "/recipes/tips-n-tricks/define-environment-variables" + }, + { + "description": "", + "file": "shared/reference/environment-variables", + "id": "environment-variables", + "name": "Environment Variables", + "path": "/reference/environment-variables" } ], "module-federation": [ diff --git a/docs/map.json b/docs/map.json index 37999e97a808d..8a9b921c275a4 100644 --- a/docs/map.json +++ b/docs/map.json @@ -506,22 +506,540 @@ { "name": "Recipes", "id": "recipes", - "description": "Learn quickly how to do things with Nx.", + "description": "In depth recipes for common tasks", "itemList": [ - { - "name": "CI Setup", - "id": "ci-setup", - "path": "/recipes/ci/ci-setup" - }, { "name": "Adopting Nx", "id": "adopting-nx", - "path": "/recipes/adopting-nx" + "description": "Adopting Nx incrementally, on existing project or from scratch.", + "itemList": [ + { + "name": "NPM/Yarn/PNPM workspaces", + "id": "adding-to-monorepo", + "file": "shared/migration/adding-to-monorepo" + }, + { + "name": "Add to any Project", + "id": "adding-to-existing-project", + "file": "shared/migration/adding-to-existing-project" + }, + { + "name": "Nx and Lerna", + "id": "lerna-and-nx", + "file": "shared/migration/lerna-and-nx" + }, + { + "name": "Preserving Git Histories", + "id": "preserving-git-histories", + "file": "shared/migration/preserving-git-histories" + }, + { + "name": "Manual migration", + "id": "manual", + "file": "shared/migration/manual" + } + ] }, { - "name": "All Recipes »", - "id": "all", - "path": "/recipes" + "name": "Angular", + "id": "angular", + "description": "Advanced guides to adopt Nx in Angular.", + "itemList": [ + { + "name": "Migration", + "id": "migration", + "itemList": [ + { + "name": "Migrating from Angular CLI", + "id": "angular", + "file": "shared/migration/migration-angular" + }, + { + "name": "Migrating From Multiple Angular CLI Repos", + "id": "angular-multiple", + "file": "shared/migration/angular-multiple" + }, + { + "name": "Migrating Angular Application manually", + "id": "angular-manual", + "file": "shared/migration/angular-manual" + }, + { + "name": "Migrating from AngularJS", + "id": "angularjs", + "file": "shared/migration/migration-angularjs" + } + ] + }, + { + "name": "Use Environment Variables in Angular", + "id": "use-environment-variables-in-angular", + "tags": ["environment-variables"], + "file": "shared/guides/use-environment-variables-in-angular" + }, + { + "name": "Using Tailwind CSS with Angular projects", + "id": "using-tailwind-css-with-angular-projects", + "file": "shared/guides/using-tailwind-css-with-angular-projects" + }, + { + "name": "Setup Module Federation with SSR for Angular", + "id": "module-federation-with-ssr", + "tags": [ + "use-task-executors", + "module-federation", + "angular" + ], + "file": "shared/recipes/module-federation-with-ssr" + }, + { + "name": "Advanced Micro Frontends with Angular using Dynamic Federation", + "id": "dynamic-module-federation-with-angular", + "tags": [ + "use-task-executors", + "module-federation", + "angular" + ], + "file": "shared/guides/module-federation/dynamic-mfe-angular" + }, + { + "name": "Setup incremental builds for Angular applications", + "id": "setup-incremental-builds-angular", + "file": "shared/guides/setup-incremental-builds-angular" + } + ] + }, + { + "name": "React", + "id": "react", + "description": "Advanced guides to adopt Nx in React.", + "itemList": [ + { + "name": "Migrating from CRA", + "id": "migration-cra", + "file": "shared/migration/migration-cra" + }, + { + "name": "React 18 Migration", + "id": "react-18", + "file": "shared/guides/react-18" + }, + { + "name": "React Native with Nx", + "id": "react-native", + "file": "shared/guides/react-native" + }, + { + "name": "Remix with Nx", + "id": "remix", + "file": "shared/guides/remix" + }, + { + "name": "Use Environment Variables in React", + "id": "use-environment-variables-in-react", + "tags": ["environment-variables"], + "file": "shared/guides/use-environment-variables-in-react" + }, + { + "name": "Using Tailwind CSS in React", + "id": "using-tailwind-css-in-react", + "file": "shared/guides/using-tailwind-css-in-react" + }, + { + "name": "Adding Images, Fonts, and Files", + "id": "adding-assets-react", + "file": "shared/guides/adding-assets" + }, + { + "name": "Setup Module Federation with SSR for React", + "id": "module-federation-with-ssr", + "tags": ["use-task-executors", "module-federation", "react"], + "file": "shared/recipes/module-federation-with-ssr" + }, + { + "name": "Deploying Next.js applications to Vercel", + "id": "deploy-nextjs-to-vercel", + "file": "shared/recipes/deployment/deploy-nextjs-to-vercel" + } + ] + }, + { + "name": "Node", + "id": "node", + "description": "Set of Node related recipes.", + "itemList": [ + { + "name": "Deploying a Node App to Fly.io", + "id": "node-server-fly-io", + "tags": ["deployment", "node"], + "file": "shared/recipes/deployment/node-server-fly-io" + }, + { + "name": "Add and Deploy Netlify Edge Functions with Node", + "id": "node-serverless-functions-netlify", + "tags": ["deployment", "node"], + "file": "shared/recipes/deployment/node-serverless-functions-netlify" + }, + { + "name": "Deploying AWS lambda in Node.js", + "id": "node-aws-lambda", + "tags": ["deployment", "node"], + "file": "shared/recipes/deployment/node-aws-lambda" + } + ] + }, + { + "name": "Storybook", + "id": "storybook", + "description": "Storybook how tos.", + "itemList": [ + { + "name": "One main Storybook instance for all projects", + "id": "one-storybook-for-all", + "tags": ["storybook"], + "file": "shared/recipes/one-storybook-for-all" + }, + { + "name": "One Storybook instance per scope", + "id": "one-storybook-per-scope", + "tags": ["storybook"], + "file": "shared/recipes/one-storybook-per-scope" + }, + { + "name": "One main Storybook instance using Storybook Composition", + "id": "one-storybook-with-composition", + "tags": ["storybook"], + "file": "shared/recipes/one-storybook-with-composition" + } + ] + }, + { + "name": "Enforce Module Boundaries", + "id": "enforce-module-boundaries", + "description": "Configuring the enforce module boundaries rule", + "itemList": [ + { + "name": "Ban Dependencies with Certain Tags", + "id": "ban-dependencies-with-tags", + "tags": ["enforce-project-boundaries"], + "file": "shared/recipes/ban-dependencies-with-tags" + }, + { + "name": "Tag in Multiple Dimensions", + "id": "tag-multiple-dimensions", + "tags": ["enforce-project-boundaries"], + "file": "shared/recipes/tag-multiple-dimensions" + }, + { + "name": "Ban External Imports", + "id": "ban-external-imports", + "tags": ["enforce-project-boundaries"], + "file": "shared/recipes/ban-external-imports" + }, + { + "name": "Tags Allow List", + "id": "tags-allow-list", + "tags": ["enforce-project-boundaries"], + "file": "shared/recipes/tags-allow-list" + } + ] + }, + { + "name": "CI", + "id": "ci", + "description": "All recipes about how to use Nx to make your CI faster.", + "itemList": [ + { + "name": "CI Setup", + "id": "ci-setup", + "tags": ["distribute-task-execution"], + "file": "shared/ci-overview" + }, + { + "name": "Prepare applications for deployment via CI", + "id": "ci-deployment", + "tags": ["docker", "deploy"], + "file": "shared/recipes/ci-deployment" + }, + { + "name": "Setting up Azure Pipelines", + "id": "monorepo-ci-azure", + "file": "shared/monorepo-ci-azure" + }, + { + "name": "Setting up CircleCI", + "id": "monorepo-ci-circle-ci", + "file": "shared/monorepo-ci-circle-ci" + }, + { + "name": "Setting up GitHub Actions", + "id": "monorepo-ci-github-actions", + "file": "shared/monorepo-ci-github-actions" + }, + { + "name": "Setting up Jenkins", + "id": "monorepo-ci-jenkins", + "file": "shared/monorepo-ci-jenkins" + }, + { + "name": "Setting up GitLab", + "id": "monorepo-ci-gitlab", + "file": "shared/monorepo-ci-gitlab" + }, + { + "name": "Setting up Bitbucket", + "id": "monorepo-ci-bitbucket-pipelines", + "file": "shared/monorepo-ci-bitbucket-pipelines" + } + ] + }, + { + "name": "Nx Console", + "id": "nx-console", + "description": "Checkout all the recipes related to Nx Console.", + "itemList": [ + { + "name": "Telemetry", + "id": "console-telemetry", + "tags": ["integrate-with-editors"], + "file": "shared/recipes/console-telemetry" + }, + { + "name": "Generate Command", + "id": "console-generate-command", + "tags": ["integrate-with-editors"], + "file": "shared/recipes/console-generate-command" + }, + { + "name": "Run Command", + "id": "console-run-command", + "tags": ["integrate-with-editors"], + "file": "shared/recipes/console-run-command" + }, + { + "name": "Add Dependency Command", + "id": "console-add-dependency-command", + "tags": ["integrate-with-editors"], + "file": "shared/recipes/console-add-dependency-command" + }, + { + "name": "Project Pane", + "id": "console-project-pane", + "tags": ["integrate-with-editors"], + "file": "shared/recipes/console-project-pane" + }, + { + "name": "Keyboard Shortcuts", + "id": "console-shortcuts", + "tags": ["integrate-with-editors"], + "file": "shared/recipes/console-shortcuts" + } + ] + }, + { + "name": "Troubleshooting", + "id": "troubleshooting", + "description": "Learn how to troubleshoot common problems.", + "itemList": [ + { + "name": "Resolve Circular Dependencies", + "id": "resolve-circular-dependencies", + "tags": ["explore-graph"], + "file": "shared/recipes/resolve-circular-dependencies" + }, + { + "name": "Troubleshooting Nx Install Issues", + "id": "troubleshoot-nx-install-issues", + "file": "shared/installation/troubleshoot-installation" + }, + { + "name": "Troubleshoot Cache Misses", + "id": "troubleshoot-cache-misses", + "tags": ["cache-task-results"], + "file": "shared/recipes/troubleshoot-cache-misses" + }, + { + "name": "Unknown Local Cache Error", + "id": "unknown-local-cache", + "tags": [], + "file": "shared/guides/unknown-local-cache" + }, + { + "name": "Profiling Build Performance", + "id": "performance-profiling", + "tags": ["use-task-executors", "environment-variables"], + "file": "shared/guides/performance-profiling" + } + ] + }, + { + "name": "Tips and tricks", + "id": "tips-n-tricks", + "description": "Various tips and tricks for using Nx.", + "itemList": [ + { + "name": "Configuring ESLint with Typescript", + "id": "eslint", + "file": "shared/eslint" + }, + { + "name": "Define Environment Variables", + "id": "define-environment-variables", + "tags": ["environment-variables"], + "file": "shared/guides/define-environment-variables" + }, + { + "name": "Configuring Browser Support", + "id": "browser-support", + "file": "shared/guides/browser-support" + }, + { + "name": "Include Assets in Build", + "id": "include-assets-in-build", + "tags": [], + "file": "shared/recipes/include-assets-in-build" + }, + { + "name": "Include All package.json Files as Projects", + "id": "include-all-packagejson", + "tags": [], + "file": "shared/recipes/include-all-packagejson" + }, + { + "name": "Identify Dependencies Between Folders", + "id": "identify-dependencies-between-folders", + "tags": [], + "file": "shared/recipes/identify-dependencies-between-folders" + }, + { + "name": "Run Root-Level NPM Scripts with Nx", + "id": "root-level-scripts", + "tags": ["run-tasks"], + "file": "shared/recipes/root-level-scripts" + }, + { + "name": "Disable Graph Links Created from Analyzing Source Files", + "id": "analyze-source-files", + "tags": ["explore-graph"], + "file": "shared/recipes/analyze-source-files" + }, + { + "name": "Workspace Watching", + "id": "workspace-watching", + "tags": ["workspace-watching"], + "file": "shared/recipes/workspace-watching" + }, + { + "name": "Convert from a Standalone Repository to an Integrated Repository", + "id": "standalone-to-integrated", + "tags": ["repository-types"], + "file": "shared/recipes/repo-types/standalone-to-integrated" + }, + { + "name": "Use JavaScript instead TypeScript", + "id": "js-and-ts", + "file": "shared/guides/js-and-ts" + }, + { + "name": "Altering Migration Process", + "id": "advanced-update", + "tags": ["automate-updating-dependencies"], + "file": "shared/recipes/advanced-update" + }, + { + "name": "Running Custom Commands", + "id": "run-commands-executor", + "tags": ["use-task-executors"], + "file": "shared/running-custom-commands" + } + ] + }, + { + "name": "Other", + "id": "other", + "description": "Other recipes you will find useful.", + "itemList": [ + { + "name": "Serverless deployment with Deno Deploy", + "id": "deno-deploy", + "tags": ["deployment", "deno"], + "file": "shared/recipes/deployment/deno-deploy" + }, + { + "name": "Add and Deploy Netlify Edge Functions with Deno", + "id": "deno-netlify-functions", + "tags": ["deployment", "deno"], + "file": "shared/recipes/deployment/deno-netlify-edge-functions" + }, + { + "name": "Rescope Packages from @nrwl to @nx", + "id": "rescope", + "tags": [], + "file": "shared/recipes/rescope" + } + ] + }, + { + "name": "Example Repos", + "id": "example-repos", + "description": "Examples of different ways to use Nx", + "itemList": [ + { + "name": "Powering Up React Development With Nx", + "id": "react-nx", + "file": "shared/examples/react-nx" + }, + { + "name": "Using Apollo GraphQL", + "id": "apollo-react", + "file": "shared/examples/apollo-react" + }, + { + "name": "Using Prisma with NestJS", + "id": "nestjs-prisma", + "tags": ["database", "node"], + "file": "shared/recipes/database/nestjs-prisma" + }, + { + "name": "Using Mongo with Fastify", + "id": "mongo-fastify", + "tags": ["database", "node"], + "file": "shared/recipes/database/mongo-fastify" + }, + { + "name": "Using Redis with Fastify", + "id": "redis-fastify", + "tags": ["database", "node"], + "file": "shared/recipes/database/redis-fastify" + }, + { + "name": "Using Postgres with Fastify", + "id": "postgres-fastify", + "tags": ["database", "node"], + "file": "shared/recipes/database/postgres-fastify" + }, + { + "name": "Using PlanetScale with Serverless Fastify", + "id": "serverless-fastify-planetscale", + "tags": ["database", "node", "serverless"], + "file": "shared/recipes/database/serverless-fastify-planetscale" + }, + { + "name": "Large Repo and Caching", + "id": "caching", + "file": "shared/examples/caching" + }, + { + "name": "Large Repo and DTE", + "id": "dte", + "file": "shared/examples/dte" + }, + { + "name": "Nx Micro-Frontend Example", + "id": "mfe", + "file": "shared/examples/nx-examples" + } + ] } ] }, @@ -848,538 +1366,6 @@ } ] }, - { - "name": "Recipes", - "id": "nx-recipes", - "description": "In depth recipes for common tasks", - "itemList": [ - { - "name": "Migrating to Nx", - "id": "adopting-nx", - "description": "Adopting Nx incrementally, on existing project or from scratch.", - "itemList": [ - { - "name": "NPM/Yarn/PNPM workspaces", - "id": "adding-to-monorepo", - "file": "shared/migration/adding-to-monorepo" - }, - { - "name": "Add to any Project", - "id": "adding-to-existing-project", - "file": "shared/migration/adding-to-existing-project" - }, - { - "name": "Nx and Lerna", - "id": "lerna-and-nx", - "file": "shared/migration/lerna-and-nx" - }, - { - "name": "Preserving Git Histories", - "id": "preserving-git-histories", - "file": "shared/migration/preserving-git-histories" - }, - { - "name": "Manual migration", - "id": "manual", - "file": "shared/migration/manual" - } - ] - }, - { - "name": "Angular", - "id": "angular", - "description": "Advanced guides to adopt Nx in Angular.", - "itemList": [ - { - "name": "Migration", - "id": "migration", - "itemList": [ - { - "name": "Migrating from Angular CLI", - "id": "angular", - "file": "shared/migration/migration-angular" - }, - { - "name": "Migrating From Multiple Angular CLI Repos", - "id": "angular-multiple", - "file": "shared/migration/angular-multiple" - }, - { - "name": "Migrating Angular Application manually", - "id": "angular-manual", - "file": "shared/migration/angular-manual" - }, - { - "name": "Migrating from AngularJS", - "id": "angularjs", - "file": "shared/migration/migration-angularjs" - } - ] - }, - { - "name": "Use Environment Variables in Angular", - "id": "use-environment-variables-in-angular", - "tags": ["environment-variables"], - "file": "shared/guides/use-environment-variables-in-angular" - }, - { - "name": "Using Tailwind CSS with Angular projects", - "id": "using-tailwind-css-with-angular-projects", - "file": "shared/guides/using-tailwind-css-with-angular-projects" - }, - { - "name": "Setup Module Federation with SSR for Angular", - "id": "module-federation-with-ssr", - "tags": ["use-task-executors", "module-federation", "angular"], - "file": "shared/recipes/module-federation-with-ssr" - }, - { - "name": "Advanced Micro Frontends with Angular using Dynamic Federation", - "id": "dynamic-module-federation-with-angular", - "tags": ["use-task-executors", "module-federation", "angular"], - "file": "shared/guides/module-federation/dynamic-mfe-angular" - }, - { - "name": "Setup incremental builds for Angular applications", - "id": "setup-incremental-builds-angular", - "file": "shared/guides/setup-incremental-builds-angular" - } - ] - }, - { - "name": "React", - "id": "react", - "description": "Advanced guides to adopt Nx in React.", - "itemList": [ - { - "name": "Migrating from CRA", - "id": "migration-cra", - "file": "shared/migration/migration-cra" - }, - { - "name": "React 18 Migration", - "id": "react-18", - "file": "shared/guides/react-18" - }, - { - "name": "React Native with Nx", - "id": "react-native", - "file": "shared/guides/react-native" - }, - { - "name": "Remix with Nx", - "id": "remix", - "file": "shared/guides/remix" - }, - { - "name": "Use Environment Variables in React", - "id": "use-environment-variables-in-react", - "tags": ["environment-variables"], - "file": "shared/guides/use-environment-variables-in-react" - }, - { - "name": "Using Tailwind CSS in React", - "id": "using-tailwind-css-in-react", - "file": "shared/guides/using-tailwind-css-in-react" - }, - { - "name": "Adding Images, Fonts, and Files", - "id": "adding-assets-react", - "file": "shared/guides/adding-assets" - }, - { - "name": "Setup Module Federation with SSR for React", - "id": "module-federation-with-ssr", - "tags": ["use-task-executors", "module-federation", "react"], - "file": "shared/recipes/module-federation-with-ssr" - }, - { - "name": "Deploying Next.js applications to Vercel", - "id": "deploy-nextjs-to-vercel", - "file": "shared/recipes/deployment/deploy-nextjs-to-vercel" - } - ] - }, - { - "name": "Node", - "id": "node", - "description": "Set of Node related recipes.", - "itemList": [ - { - "name": "Deploying a Node App to Fly.io", - "id": "node-server-fly-io", - "tags": ["deployment", "node"], - "file": "shared/recipes/deployment/node-server-fly-io" - }, - { - "name": "Add and Deploy Netlify Edge Functions with Node", - "id": "node-serverless-functions-netlify", - "tags": ["deployment", "node"], - "file": "shared/recipes/deployment/node-serverless-functions-netlify" - }, - { - "name": "Deploying AWS lambda in Node.js", - "id": "node-aws-lambda", - "tags": ["deployment", "node"], - "file": "shared/recipes/deployment/node-aws-lambda" - } - ] - }, - { - "name": "Storybook", - "id": "storybook", - "description": "Storybook how tos.", - "itemList": [ - { - "name": "One main Storybook instance for all projects", - "id": "one-storybook-for-all", - "tags": ["storybook"], - "file": "shared/recipes/one-storybook-for-all" - }, - { - "name": "One Storybook instance per scope", - "id": "one-storybook-per-scope", - "tags": ["storybook"], - "file": "shared/recipes/one-storybook-per-scope" - }, - { - "name": "One main Storybook instance using Storybook Composition", - "id": "one-storybook-with-composition", - "tags": ["storybook"], - "file": "shared/recipes/one-storybook-with-composition" - } - ] - }, - { - "name": "Enforce Module Boundaries", - "id": "enforce-module-boundaries", - "description": "Configuring the enforce module boundaries rule", - "itemList": [ - { - "name": "Ban Dependencies with Certain Tags", - "id": "ban-dependencies-with-tags", - "tags": ["enforce-project-boundaries"], - "file": "shared/recipes/ban-dependencies-with-tags" - }, - { - "name": "Tag in Multiple Dimensions", - "id": "tag-multiple-dimensions", - "tags": ["enforce-project-boundaries"], - "file": "shared/recipes/tag-multiple-dimensions" - }, - { - "name": "Ban External Imports", - "id": "ban-external-imports", - "tags": ["enforce-project-boundaries"], - "file": "shared/recipes/ban-external-imports" - }, - { - "name": "Tags Allow List", - "id": "tags-allow-list", - "tags": ["enforce-project-boundaries"], - "file": "shared/recipes/tags-allow-list" - } - ] - }, - { - "name": "CI", - "id": "ci", - "description": "All recipes about how to use Nx to make your CI faster.", - "itemList": [ - { - "name": "CI Setup", - "id": "ci-setup", - "tags": ["distribute-task-execution"], - "file": "shared/ci-overview" - }, - { - "name": "Prepare applications for deployment via CI", - "id": "ci-deployment", - "tags": ["docker", "deploy"], - "file": "shared/recipes/ci-deployment" - }, - { - "name": "Setting up Azure Pipelines", - "id": "monorepo-ci-azure", - "file": "shared/monorepo-ci-azure" - }, - { - "name": "Setting up CircleCI", - "id": "monorepo-ci-circle-ci", - "file": "shared/monorepo-ci-circle-ci" - }, - { - "name": "Setting up GitHub Actions", - "id": "monorepo-ci-github-actions", - "file": "shared/monorepo-ci-github-actions" - }, - { - "name": "Setting up Jenkins", - "id": "monorepo-ci-jenkins", - "file": "shared/monorepo-ci-jenkins" - }, - { - "name": "Setting up GitLab", - "id": "monorepo-ci-gitlab", - "file": "shared/monorepo-ci-gitlab" - }, - { - "name": "Setting up Bitbucket", - "id": "monorepo-ci-bitbucket-pipelines", - "file": "shared/monorepo-ci-bitbucket-pipelines" - } - ] - }, - { - "name": "Nx Console", - "id": "nx-console", - "description": "Checkout all the recipes related to Nx Console.", - "itemList": [ - { - "name": "Telemetry", - "id": "console-telemetry", - "tags": ["integrate-with-editors"], - "file": "shared/recipes/console-telemetry" - }, - { - "name": "Generate Command", - "id": "console-generate-command", - "tags": ["integrate-with-editors"], - "file": "shared/recipes/console-generate-command" - }, - { - "name": "Run Command", - "id": "console-run-command", - "tags": ["integrate-with-editors"], - "file": "shared/recipes/console-run-command" - }, - { - "name": "Add Dependency Command", - "id": "console-add-dependency-command", - "tags": ["integrate-with-editors"], - "file": "shared/recipes/console-add-dependency-command" - }, - { - "name": "Project Pane", - "id": "console-project-pane", - "tags": ["integrate-with-editors"], - "file": "shared/recipes/console-project-pane" - }, - { - "name": "Keyboard Shortcuts", - "id": "console-shortcuts", - "tags": ["integrate-with-editors"], - "file": "shared/recipes/console-shortcuts" - } - ] - }, - { - "name": "Troubleshooting", - "id": "troubleshooting", - "description": "Learn how to troubleshoot common problems.", - "itemList": [ - { - "name": "Resolve Circular Dependencies", - "id": "resolve-circular-dependencies", - "tags": ["explore-graph"], - "file": "shared/recipes/resolve-circular-dependencies" - }, - { - "name": "Troubleshooting Nx Install Issues", - "id": "troubleshoot-nx-install-issues", - "file": "shared/installation/troubleshoot-installation" - }, - { - "name": "Troubleshoot Cache Misses", - "id": "troubleshoot-cache-misses", - "tags": ["cache-task-results"], - "file": "shared/recipes/troubleshoot-cache-misses" - }, - { - "name": "Unknown Local Cache Error", - "id": "unknown-local-cache", - "tags": [], - "file": "shared/guides/unknown-local-cache" - }, - { - "name": "Profiling Build Performance", - "id": "performance-profiling", - "tags": ["use-task-executors", "environment-variables"], - "file": "shared/guides/performance-profiling" - } - ] - }, - { - "name": "Tips and tricks", - "id": "tips-n-tricks", - "description": "Various tips and tricks for using Nx.", - "itemList": [ - { - "name": "Configuring ESLint with Typescript", - "id": "eslint", - "file": "shared/eslint" - }, - { - "name": "Define Environment Variables", - "id": "define-environment-variables", - "tags": ["environment-variables"], - "file": "shared/guides/define-environment-variables" - }, - { - "name": "Configuring Browser Support", - "id": "browser-support", - "file": "shared/guides/browser-support" - }, - { - "name": "Include Assets in Build", - "id": "include-assets-in-build", - "tags": [], - "file": "shared/recipes/include-assets-in-build" - }, - { - "name": "Include All package.json Files as Projects", - "id": "include-all-packagejson", - "tags": [], - "file": "shared/recipes/include-all-packagejson" - }, - { - "name": "Identify Dependencies Between Folders", - "id": "identify-dependencies-between-folders", - "tags": [], - "file": "shared/recipes/identify-dependencies-between-folders" - }, - { - "name": "Run Root-Level NPM Scripts with Nx", - "id": "root-level-scripts", - "tags": ["run-tasks"], - "file": "shared/recipes/root-level-scripts" - }, - { - "name": "Disable Graph Links Created from Analyzing Source Files", - "id": "analyze-source-files", - "tags": ["explore-graph"], - "file": "shared/recipes/analyze-source-files" - }, - { - "name": "Workspace Watching", - "id": "workspace-watching", - "tags": ["workspace-watching"], - "file": "shared/recipes/workspace-watching" - }, - { - "name": "Convert from a Standalone Repository to an Integrated Repository", - "id": "standalone-to-integrated", - "tags": ["repository-types"], - "file": "shared/recipes/repo-types/standalone-to-integrated" - }, - { - "name": "Use JavaScript instead TypeScript", - "id": "js-and-ts", - "file": "shared/guides/js-and-ts" - }, - { - "name": "Altering Migration Process", - "id": "advanced-update", - "tags": ["automate-updating-dependencies"], - "file": "shared/recipes/advanced-update" - }, - { - "name": "Running Custom Commands", - "id": "run-commands-executor", - "tags": ["use-task-executors"], - "file": "shared/running-custom-commands" - } - ] - }, - { - "name": "Other", - "id": "other", - "description": "Other recipes you will find useful.", - "itemList": [ - { - "name": "Serverless deployment with Deno Deploy", - "id": "deno-deploy", - "tags": ["deployment", "deno"], - "file": "shared/recipes/deployment/deno-deploy" - }, - { - "name": "Add and Deploy Netlify Edge Functions with Deno", - "id": "deno-netlify-functions", - "tags": ["deployment", "deno"], - "file": "shared/recipes/deployment/deno-netlify-edge-functions" - }, - { - "name": "Rescope Packages from @nrwl to @nx", - "id": "rescope", - "tags": [], - "file": "shared/recipes/rescope" - } - ] - }, - { - "name": "Example Repos", - "id": "example-repos", - "description": "Examples of different ways to use Nx", - "itemList": [ - { - "name": "Powering Up React Development With Nx", - "id": "react-nx", - "file": "shared/examples/react-nx" - }, - { - "name": "Using Apollo GraphQL", - "id": "apollo-react", - "file": "shared/examples/apollo-react" - }, - { - "name": "Using Prisma with NestJS", - "id": "nestjs-prisma", - "tags": ["database", "node"], - "file": "shared/recipes/database/nestjs-prisma" - }, - { - "name": "Using Mongo with Fastify", - "id": "mongo-fastify", - "tags": ["database", "node"], - "file": "shared/recipes/database/mongo-fastify" - }, - { - "name": "Using Redis with Fastify", - "id": "redis-fastify", - "tags": ["database", "node"], - "file": "shared/recipes/database/redis-fastify" - }, - { - "name": "Using Postgres with Fastify", - "id": "postgres-fastify", - "tags": ["database", "node"], - "file": "shared/recipes/database/postgres-fastify" - }, - { - "name": "Using PlanetScale with Serverless Fastify", - "id": "serverless-fastify-planetscale", - "tags": ["database", "node", "serverless"], - "file": "shared/recipes/database/serverless-fastify-planetscale" - }, - { - "name": "Large Repo and Caching", - "id": "caching", - "file": "shared/examples/caching" - }, - { - "name": "Large Repo and DTE", - "id": "dte", - "file": "shared/examples/dte" - }, - { - "name": "Nx Micro-Frontend Example", - "id": "mfe", - "file": "shared/examples/nx-examples" - } - ] - } - ] - }, { "name": "Nx Cloud", "id": "nx-cloud-documentation", diff --git a/docs/shared/migration/migration-angular.md b/docs/shared/migration/migration-angular.md index bac712c24a30e..d8f8f50dbebb3 100644 --- a/docs/shared/migration/migration-angular.md +++ b/docs/shared/migration/migration-angular.md @@ -77,11 +77,11 @@ After the changes are applied, your workspace file structure should look similar ### Older Versions of Angular -Support for workspaces with multiple applications and libraries was added in Nx v14.1.0. If you are migrating using an older version of Nx, your workspace can only contain one application and no libraries in order to use the automated migration, otherwise, you can still [migrate manually](/recipes/angular/migration/manual). +Support for workspaces with multiple applications and libraries was added in Nx v14.1.0. If you are migrating using an older version of Nx, your workspace can only contain one application and no libraries in order to use the automated migration, otherwise, you can still [migrate manually](/recipes/angular/migration/angular-manual). ### Modified Folder Structure -The automated migration supports Angular CLI workspaces with a standard structure, configurations and features. If your workspace has deviated from what the Angular CLI generates, you might not be able to use the automated migration and you will need to [manually migrate your workspace](/recipes/angular/migration/manual). +The automated migration supports Angular CLI workspaces with a standard structure, configurations and features. If your workspace has deviated from what the Angular CLI generates, you might not be able to use the automated migration and you will need to [manually migrate your workspace](/recipes/angular/migration/angular-manual). Currently, the automated migration supports workspaces using the following executors (builders): @@ -152,8 +152,8 @@ If you're not ready to make the change yet, you can come back to this later: {% card title="Nx and the Angular CLI" description="Differences between Nx and the Angular CLI" type="documentation" url="/concepts/more-concepts/nx-and-angular" /%} -{% card title="Angular CLI manual migration" description="Add Nx by hand" type="documentation" url="/recipes/angular/migration/manual" /%} +{% card title="Angular CLI manual migration" description="Add Nx by hand" type="documentation" url="/recipes/angular/migration/angular-manual" /%} -{% card title="Multiple Angular Repositories to one Nx Workspace" description="Combine multiple Angular CLI workspaces into one Nx workspace" type="documentation" url="/recipes/angular/migration/multiple" /%} +{% card title="Multiple Angular Repositories to one Nx Workspace" description="Combine multiple Angular CLI workspaces into one Nx workspace" type="documentation" url="/recipes/angular/migration/angular-multiple" /%} {% /cards %} diff --git a/docs/shared/reference/sitemap.md b/docs/shared/reference/sitemap.md index b40d9badbc7cd..b224ee6267877 100644 --- a/docs/shared/reference/sitemap.md +++ b/docs/shared/reference/sitemap.md @@ -89,9 +89,98 @@ - [How the Project Graph is Built](/concepts/more-concepts/how-project-graph-is-built) - [Nx and the Nx Wrapper](/concepts/more-concepts/nx-and-the-wrapper) - [Managing your Global Nx Installation](/concepts/more-concepts/global-nx) - - [All Recipes »](/recipes) - - [CI Setup](/recipes/ci/ci-setup) + - [Recipes](/recipes) - [Adopting Nx](/recipes/adopting-nx) + - [NPM/Yarn/PNPM workspaces](/recipes/adopting-nx/adding-to-monorepo) + - [Add to any Project](/recipes/adopting-nx/adding-to-existing-project) + - [Nx and Lerna](/recipes/adopting-nx/lerna-and-nx) + - [Preserving Git Histories](/recipes/adopting-nx/preserving-git-histories) + - [Manual migration](/recipes/adopting-nx/manual) + - [Angular](/recipes/angular) + - [Migration](/recipes/angular/migration) + - [Migrating from Angular CLI](/recipes/angular/migration/angular) + - [Migrating From Multiple Angular CLI Repos](/recipes/angular/migration/angular-multiple) + - [Migrating Angular Application manually](/recipes/angular/migration/angular-manual) + - [Migrating from AngularJS](/recipes/angular/migration/angularjs) + - [Use Environment Variables in Angular](/recipes/angular/use-environment-variables-in-angular) + - [Using Tailwind CSS with Angular projects](/recipes/angular/using-tailwind-css-with-angular-projects) + - [Setup Module Federation with SSR for Angular](/recipes/angular/module-federation-with-ssr) + - [Advanced Micro Frontends with Angular using Dynamic Federation](/recipes/angular/dynamic-module-federation-with-angular) + - [Setup incremental builds for Angular applications](/recipes/angular/setup-incremental-builds-angular) + - [React](/recipes/react) + - [Migrating from CRA](/recipes/react/migration-cra) + - [React 18 Migration](/recipes/react/react-18) + - [React Native with Nx](/recipes/react/react-native) + - [Remix with Nx](/recipes/react/remix) + - [Use Environment Variables in React](/recipes/react/use-environment-variables-in-react) + - [Using Tailwind CSS in React](/recipes/react/using-tailwind-css-in-react) + - [Adding Images, Fonts, and Files](/recipes/react/adding-assets-react) + - [Setup Module Federation with SSR for React](/recipes/react/module-federation-with-ssr) + - [Deploying Next.js applications to Vercel](/recipes/react/deploy-nextjs-to-vercel) + - [Node](/recipes/node) + - [Deploying a Node App to Fly.io](/recipes/node/node-server-fly-io) + - [Add and Deploy Netlify Edge Functions with Node](/recipes/node/node-serverless-functions-netlify) + - [Deploying AWS lambda in Node.js](/recipes/node/node-aws-lambda) + - [Storybook](/recipes/storybook) + - [One main Storybook instance for all projects](/recipes/storybook/one-storybook-for-all) + - [One Storybook instance per scope](/recipes/storybook/one-storybook-per-scope) + - [One main Storybook instance using Storybook Composition](/recipes/storybook/one-storybook-with-composition) + - [Enforce Module Boundaries](/recipes/enforce-module-boundaries) + - [Ban Dependencies with Certain Tags](/recipes/enforce-module-boundaries/ban-dependencies-with-tags) + - [Tag in Multiple Dimensions](/recipes/enforce-module-boundaries/tag-multiple-dimensions) + - [Ban External Imports](/recipes/enforce-module-boundaries/ban-external-imports) + - [Tags Allow List](/recipes/enforce-module-boundaries/tags-allow-list) + - [CI](/recipes/ci) + - [CI Setup](/recipes/ci/ci-setup) + - [Prepare applications for deployment via CI](/recipes/ci/ci-deployment) + - [Setting up Azure Pipelines](/recipes/ci/monorepo-ci-azure) + - [Setting up CircleCI](/recipes/ci/monorepo-ci-circle-ci) + - [Setting up GitHub Actions](/recipes/ci/monorepo-ci-github-actions) + - [Setting up Jenkins](/recipes/ci/monorepo-ci-jenkins) + - [Setting up GitLab](/recipes/ci/monorepo-ci-gitlab) + - [Setting up Bitbucket](/recipes/ci/monorepo-ci-bitbucket-pipelines) + - [Nx Console](/recipes/nx-console) + - [Telemetry](/recipes/nx-console/console-telemetry) + - [Generate Command](/recipes/nx-console/console-generate-command) + - [Run Command](/recipes/nx-console/console-run-command) + - [Add Dependency Command](/recipes/nx-console/console-add-dependency-command) + - [Project Pane](/recipes/nx-console/console-project-pane) + - [Keyboard Shortcuts](/recipes/nx-console/console-shortcuts) + - [Troubleshooting](/recipes/troubleshooting) + - [Resolve Circular Dependencies](/recipes/troubleshooting/resolve-circular-dependencies) + - [Troubleshooting Nx Install Issues](/recipes/troubleshooting/troubleshoot-nx-install-issues) + - [Troubleshoot Cache Misses](/recipes/troubleshooting/troubleshoot-cache-misses) + - [Unknown Local Cache Error](/recipes/troubleshooting/unknown-local-cache) + - [Profiling Build Performance](/recipes/troubleshooting/performance-profiling) + - [Tips and tricks](/recipes/tips-n-tricks) + - [Configuring ESLint with Typescript](/recipes/tips-n-tricks/eslint) + - [Define Environment Variables](/recipes/tips-n-tricks/define-environment-variables) + - [Configuring Browser Support](/recipes/tips-n-tricks/browser-support) + - [Include Assets in Build](/recipes/tips-n-tricks/include-assets-in-build) + - [Include All package.json Files as Projects](/recipes/tips-n-tricks/include-all-packagejson) + - [Identify Dependencies Between Folders](/recipes/tips-n-tricks/identify-dependencies-between-folders) + - [Run Root-Level NPM Scripts with Nx](/recipes/tips-n-tricks/root-level-scripts) + - [Disable Graph Links Created from Analyzing Source Files](/recipes/tips-n-tricks/analyze-source-files) + - [Workspace Watching](/recipes/tips-n-tricks/workspace-watching) + - [Convert from a Standalone Repository to an Integrated Repository](/recipes/tips-n-tricks/standalone-to-integrated) + - [Use JavaScript instead TypeScript](/recipes/tips-n-tricks/js-and-ts) + - [Altering Migration Process](/recipes/tips-n-tricks/advanced-update) + - [Running Custom Commands](/recipes/tips-n-tricks/run-commands-executor) + - [Other](/recipes/other) + - [Serverless deployment with Deno Deploy](/recipes/other/deno-deploy) + - [Add and Deploy Netlify Edge Functions with Deno](/recipes/other/deno-netlify-functions) + - [Rescope Packages from @nrwl to @nx](/recipes/other/rescope) + - [Example Repos](/recipes/example-repos) + - [Powering Up React Development With Nx](/recipes/example-repos/react-nx) + - [Using Apollo GraphQL](/recipes/example-repos/apollo-react) + - [Using Prisma with NestJS](/recipes/example-repos/nestjs-prisma) + - [Using Mongo with Fastify](/recipes/example-repos/mongo-fastify) + - [Using Redis with Fastify](/recipes/example-repos/redis-fastify) + - [Using Postgres with Fastify](/recipes/example-repos/postgres-fastify) + - [Using PlanetScale with Serverless Fastify](/recipes/example-repos/serverless-fastify-planetscale) + - [Large Repo and Caching](/recipes/example-repos/caching) + - [Large Repo and DTE](/recipes/example-repos/dte) + - [Nx Micro-Frontend Example](/recipes/example-repos/mfe) - [Reference](/reference) - [Commands](/reference/commands) - [nx.json](/reference/nx-json) @@ -117,100 +206,6 @@ - [See Also](/see-also) - [Site Map](/see-also/sitemap) -- Recipes - - - [Migrating to Nx](/recipes/adopting-nx) - - [NPM/Yarn/PNPM workspaces](/recipes/adopting-nx/adding-to-monorepo) - - [Add to any Project](/recipes/adopting-nx/adding-to-existing-project) - - [Nx and Lerna](/recipes/adopting-nx/lerna-and-nx) - - [Preserving Git Histories](/recipes/adopting-nx/preserving-git-histories) - - [Manual migration](/recipes/adopting-nx/manual) - - [Angular](/recipes/angular) - - [Migration](/recipes/angular/migration) - - [Migrating from Angular CLI](/recipes/angular/migration/angular) - - [Migrating From Multiple Angular CLI Repos](/recipes/angular/migration/angular-multiple) - - [Migrating Angular Application manually](/recipes/angular/migration/angular-manual) - - [Migrating from AngularJS](/recipes/angular/migration/angularjs) - - [Use Environment Variables in Angular](/recipes/angular/use-environment-variables-in-angular) - - [Using Tailwind CSS with Angular projects](/recipes/angular/using-tailwind-css-with-angular-projects) - - [Setup Module Federation with SSR for Angular](/recipes/angular/module-federation-with-ssr) - - [Advanced Micro Frontends with Angular using Dynamic Federation](/recipes/angular/dynamic-module-federation-with-angular) - - [Setup incremental builds for Angular applications](/recipes/angular/setup-incremental-builds-angular) - - [React](/recipes/react) - - [Migrating from CRA](/recipes/react/migration-cra) - - [React 18 Migration](/recipes/react/react-18) - - [React Native with Nx](/recipes/react/react-native) - - [Remix with Nx](/recipes/react/remix) - - [Use Environment Variables in React](/recipes/react/use-environment-variables-in-react) - - [Using Tailwind CSS in React](/recipes/react/using-tailwind-css-in-react) - - [Adding Images, Fonts, and Files](/recipes/react/adding-assets-react) - - [Setup Module Federation with SSR for React](/recipes/react/module-federation-with-ssr) - - [Deploying Next.js applications to Vercel](/recipes/react/deploy-nextjs-to-vercel) - - [Node](/recipes/node) - - [Deploying a Node App to Fly.io](/recipes/node/node-server-fly-io) - - [Add and Deploy Netlify Edge Functions with Node](/recipes/node/node-serverless-functions-netlify) - - [Deploying AWS lambda in Node.js](/recipes/node/node-aws-lambda) - - [Storybook](/recipes/storybook) - - [One main Storybook instance for all projects](/recipes/storybook/one-storybook-for-all) - - [One Storybook instance per scope](/recipes/storybook/one-storybook-per-scope) - - [One main Storybook instance using Storybook Composition](/recipes/storybook/one-storybook-with-composition) - - [Enforce Module Boundaries](/recipes/enforce-module-boundaries) - - [Ban Dependencies with Certain Tags](/recipes/enforce-module-boundaries/ban-dependencies-with-tags) - - [Tag in Multiple Dimensions](/recipes/enforce-module-boundaries/tag-multiple-dimensions) - - [Ban External Imports](/recipes/enforce-module-boundaries/ban-external-imports) - - [Tags Allow List](/recipes/enforce-module-boundaries/tags-allow-list) - - [CI](/recipes/ci) - - [CI Setup](/recipes/ci/ci-setup) - - [Prepare applications for deployment via CI](/recipes/ci/ci-deployment) - - [Setting up Azure Pipelines](/recipes/ci/monorepo-ci-azure) - - [Setting up CircleCI](/recipes/ci/monorepo-ci-circle-ci) - - [Setting up GitHub Actions](/recipes/ci/monorepo-ci-github-actions) - - [Setting up Jenkins](/recipes/ci/monorepo-ci-jenkins) - - [Setting up GitLab](/recipes/ci/monorepo-ci-gitlab) - - [Setting up Bitbucket](/recipes/ci/monorepo-ci-bitbucket-pipelines) - - [Nx Console](/recipes/nx-console) - - [Telemetry](/recipes/nx-console/console-telemetry) - - [Generate Command](/recipes/nx-console/console-generate-command) - - [Run Command](/recipes/nx-console/console-run-command) - - [Add Dependency Command](/recipes/nx-console/console-add-dependency-command) - - [Project Pane](/recipes/nx-console/console-project-pane) - - [Keyboard Shortcuts](/recipes/nx-console/console-shortcuts) - - [Troubleshooting](/recipes/troubleshooting) - - [Resolve Circular Dependencies](/recipes/troubleshooting/resolve-circular-dependencies) - - [Troubleshooting Nx Install Issues](/recipes/troubleshooting/troubleshoot-nx-install-issues) - - [Troubleshoot Cache Misses](/recipes/troubleshooting/troubleshoot-cache-misses) - - [Unknown Local Cache Error](/recipes/troubleshooting/unknown-local-cache) - - [Profiling Build Performance](/recipes/troubleshooting/performance-profiling) - - [Tips and tricks](/recipes/tips-n-tricks) - - [Configuring ESLint with Typescript](/recipes/tips-n-tricks/eslint) - - [Define Environment Variables](/recipes/tips-n-tricks/define-environment-variables) - - [Configuring Browser Support](/recipes/tips-n-tricks/browser-support) - - [Include Assets in Build](/recipes/tips-n-tricks/include-assets-in-build) - - [Include All package.json Files as Projects](/recipes/tips-n-tricks/include-all-packagejson) - - [Identify Dependencies Between Folders](/recipes/tips-n-tricks/identify-dependencies-between-folders) - - [Run Root-Level NPM Scripts with Nx](/recipes/tips-n-tricks/root-level-scripts) - - [Disable Graph Links Created from Analyzing Source Files](/recipes/tips-n-tricks/analyze-source-files) - - [Workspace Watching](/recipes/tips-n-tricks/workspace-watching) - - [Convert from a Standalone Repository to an Integrated Repository](/recipes/tips-n-tricks/standalone-to-integrated) - - [Use JavaScript instead TypeScript](/recipes/tips-n-tricks/js-and-ts) - - [Altering Migration Process](/recipes/tips-n-tricks/advanced-update) - - [Running Custom Commands](/recipes/tips-n-tricks/run-commands-executor) - - [Other](/recipes/other) - - [Serverless deployment with Deno Deploy](/recipes/other/deno-deploy) - - [Add and Deploy Netlify Edge Functions with Deno](/recipes/other/deno-netlify-functions) - - [Rescope Packages from @nrwl to @nx](/recipes/other/rescope) - - [Example Repos](/recipes/example-repos) - - [Powering Up React Development With Nx](/recipes/example-repos/react-nx) - - [Using Apollo GraphQL](/recipes/example-repos/apollo-react) - - [Using Prisma with NestJS](/recipes/example-repos/nestjs-prisma) - - [Using Mongo with Fastify](/recipes/example-repos/mongo-fastify) - - [Using Redis with Fastify](/recipes/example-repos/redis-fastify) - - [Using Postgres with Fastify](/recipes/example-repos/postgres-fastify) - - [Using PlanetScale with Serverless Fastify](/recipes/example-repos/serverless-fastify-planetscale) - - [Large Repo and Caching](/recipes/example-repos/caching) - - [Large Repo and DTE](/recipes/example-repos/dte) - - [Nx Micro-Frontend Example](/recipes/example-repos/mfe) - - Extending-nx - [Intro](/extending-nx/intro) diff --git a/nx-dev/nx-dev/pages/[...segments].tsx b/nx-dev/nx-dev/pages/[...segments].tsx index e3e43978039eb..249ddce33cf1e 100644 --- a/nx-dev/nx-dev/pages/[...segments].tsx +++ b/nx-dev/nx-dev/pages/[...segments].tsx @@ -80,7 +80,7 @@ export default function NxDocumentation({ } export const getStaticPaths: GetStaticPaths = () => { - const reservedPaths = ['/recipes', '/nx-cloud', '/packages', '/changelog']; + const reservedPaths = ['/nx-cloud', '/packages', '/changelog']; return { paths: nxDocumentationApi .getSlugsStaticDocumentPaths() diff --git a/nx-dev/nx-dev/pages/recipes/[...segments].tsx b/nx-dev/nx-dev/pages/recipes/[...segments].tsx deleted file mode 100644 index 68e3e444a3b69..0000000000000 --- a/nx-dev/nx-dev/pages/recipes/[...segments].tsx +++ /dev/null @@ -1,113 +0,0 @@ -import { getBasicRecipesSection } from '@nx/nx-dev/data-access-menu'; -import { DocViewer } from '@nx/nx-dev/feature-doc-viewer'; -import { ProcessedDocument, RelatedDocument } from '@nx/nx-dev/models-document'; -import { Menu, MenuItem } from '@nx/nx-dev/models-menu'; -import { DocumentationHeader, SidebarContainer } from '@nx/nx-dev/ui-common'; -import { GetStaticPaths, GetStaticProps } from 'next'; -import { useRouter } from 'next/router'; -import { useEffect, useRef } from 'react'; -import { menusApi } from '../../lib/menus.api'; -import { useNavToggle } from '../../lib/navigation-toggle.effect'; -import { nxRecipesApi } from '../../lib/recipes.api'; -import { tagsApi } from '../../lib/tags.api'; - -export default function Recipes({ - document, - menu, - relatedDocuments, -}: { - document: ProcessedDocument; - menu: MenuItem[]; - relatedDocuments: RelatedDocument[]; -}): JSX.Element { - const router = useRouter(); - const { toggleNav, navIsOpen } = useNavToggle(); - const wrapperElement = useRef(null); - - useEffect(() => { - const handleRouteChange = (url: string) => { - if (url.includes('#')) return; - if (!wrapperElement) return; - - (wrapperElement as any).current.scrollTo({ - top: 0, - left: 0, - behavior: 'smooth', - }); - }; - - router.events.on('routeChangeComplete', handleRouteChange); - return () => router.events.off('routeChangeComplete', handleRouteChange); - }, [router, wrapperElement]); - - const vm: { - document: ProcessedDocument; - menu: Menu; - relatedDocuments: RelatedDocument[]; - } = { - document, - menu: { - sections: [getBasicRecipesSection(menu)], - }, - relatedDocuments, - }; - - return ( -
-
- -
-
- -
- -
-
-
- ); -} - -export const getStaticPaths: GetStaticPaths = () => { - return { - paths: nxRecipesApi.getSlugsStaticDocumentPaths(), - fallback: 'blocking', - }; -}; -export const getStaticProps: GetStaticProps = async ({ - params, -}: { - params: { segments: string[] }; -}) => { - try { - const segments = ['recipes', ...params.segments]; - const document = nxRecipesApi.getDocument(segments); - return { - props: { - document, - relatedDocuments: tagsApi - .getAssociatedItemsFromTags(document.tags) - .filter((item) => item.path !== '/' + segments.join('/')), // Remove currently displayed item - menu: menusApi.getMenu('recipes', ''), - }, - }; - } catch (e) { - return { - notFound: true, - props: { - statusCode: 404, - }, - }; - } -}; diff --git a/nx-dev/nx-dev/pages/recipes/index.tsx b/nx-dev/nx-dev/pages/recipes/index.tsx deleted file mode 100644 index 9e513353dd0a9..0000000000000 --- a/nx-dev/nx-dev/pages/recipes/index.tsx +++ /dev/null @@ -1,96 +0,0 @@ -import { getBasicRecipesSection } from '@nx/nx-dev/data-access-menu'; -import { DocViewer } from '@nx/nx-dev/feature-doc-viewer'; -import { ProcessedDocument, RelatedDocument } from '@nx/nx-dev/models-document'; -import { Menu, MenuItem } from '@nx/nx-dev/models-menu'; -import { DocumentationHeader, SidebarContainer } from '@nx/nx-dev/ui-common'; -import { GetStaticProps } from 'next'; -import { useRouter } from 'next/router'; -import { useEffect, useRef } from 'react'; -import { menusApi } from '../../lib/menus.api'; -import { useNavToggle } from '../../lib/navigation-toggle.effect'; -import { nxRecipesApi } from '../../lib/recipes.api'; -import { tagsApi } from '../../lib/tags.api'; - -export default function RecipesRoot({ - document, - menu, - relatedDocuments, -}: { - document: ProcessedDocument; - menu: MenuItem[]; - relatedDocuments: RelatedDocument[]; -}) { - const router = useRouter(); - const { toggleNav, navIsOpen } = useNavToggle(); - const wrapperElement = useRef(null); - - useEffect(() => { - const handleRouteChange = (url: string) => { - if (url.includes('#')) return; - if (!wrapperElement) return; - - (wrapperElement as any).current.scrollTo({ - top: 0, - left: 0, - behavior: 'smooth', - }); - }; - - router.events.on('routeChangeComplete', handleRouteChange); - return () => router.events.off('routeChangeComplete', handleRouteChange); - }, [router, wrapperElement]); - - const vm: { - document: ProcessedDocument; - menu: Menu; - relatedDocuments: RelatedDocument[]; - } = { - document, - menu: { - sections: [getBasicRecipesSection(menu)], - }, - relatedDocuments, - }; - - return ( -
-
- -
-
- -
- -
-
-
- ); -} - -export const getStaticProps: GetStaticProps = async () => { - const document = nxRecipesApi.generateRootDocumentIndex({ - name: 'Recipes', - description: 'Learn quickly how to do things with Nx.', - }); - return { - props: { - document, - menu: menusApi.getMenu('recipes', ''), - relatedDocuments: document.tags - .map((t) => tagsApi.getAssociatedItems(t)) - .flat(), - }, - }; -}; diff --git a/nx-dev/nx-dev/redirect-rules.js b/nx-dev/nx-dev/redirect-rules.js index 536e048dc910d..9d9be565962bc 100644 --- a/nx-dev/nx-dev/redirect-rules.js +++ b/nx-dev/nx-dev/redirect-rules.js @@ -738,9 +738,9 @@ const latestRecipesRefactoring = { '/recipes/adopting-nx-angular/angular-integrated': '/recipes/angular/migration/angular', '/recipes/adopting-nx-angular/angular-manual': - '/recipes/angular/migration/manual', + '/recipes/angular/migration/angular-manual', '/recipes/adopting-nx-angular/angular-multiple': - '/recipes/angular/migration/multiple', + '/recipes/angular/migration/angular-multiple', '/recipes/adopting-nx/migration-angularjs': '/recipes/angular/migration/angularjs', '/recipes/environment-variables/use-environment-variables-in-angular': diff --git a/nx-dev/ui-common/src/lib/documentation-header.tsx b/nx-dev/ui-common/src/lib/documentation-header.tsx index aaf123d2baf16..a9f28d228b730 100644 --- a/nx-dev/ui-common/src/lib/documentation-header.tsx +++ b/nx-dev/ui-common/src/lib/documentation-header.tsx @@ -41,10 +41,8 @@ export function DocumentationHeader({ const isNxCloud: boolean = router.asPath.startsWith('/nx-cloud'); const isPackages: boolean = router.asPath.startsWith('/packages'); const isPlugins: boolean = router.asPath.startsWith('/extending-nx'); - const isRecipes: boolean = router.asPath.startsWith('/recipes'); const isChangelog: boolean = router.asPath.startsWith('/changelog'); - const isNx: boolean = - !isNxCloud && !isPackages && !isPlugins && !isRecipes && !isChangelog; + const isNx: boolean = !isNxCloud && !isPackages && !isPlugins && !isChangelog; const sections = [ { name: 'Nx', href: '/getting-started/intro', current: isNx }, @@ -63,11 +61,6 @@ export function DocumentationHeader({ href: '/packages', current: isPackages, }, - { - name: 'Recipes', - href: '/recipes', - current: isRecipes, - }, { name: 'Changelog', href: '/changelog', diff --git a/nx-dev/ui-common/src/lib/sidebar.tsx b/nx-dev/ui-common/src/lib/sidebar.tsx index 26ba8bfeefc02..97919c7e99e2b 100644 --- a/nx-dev/ui-common/src/lib/sidebar.tsx +++ b/nx-dev/ui-common/src/lib/sidebar.tsx @@ -180,8 +180,7 @@ export function SidebarMobile({ const isNxCloud: boolean = router.asPath.startsWith('/nx-cloud'); const isPackages: boolean = router.asPath.startsWith('/packages'); const isPlugins: boolean = router.asPath.startsWith('/extending-nx'); - const isRecipes: boolean = router.asPath.startsWith('/recipes'); - const isNx: boolean = !isNxCloud && !isPackages && !isPlugins && !isRecipes; + const isNx: boolean = !isNxCloud && !isPackages && !isPlugins; const sections = [ { name: 'Home', href: '/', current: false }, @@ -201,11 +200,6 @@ export function SidebarMobile({ href: '/extending-nx/intro/getting-started', current: isPlugins, }, - { - name: 'Recipes', - href: '/recipes', - current: isRecipes, - }, ]; return ( diff --git a/scripts/documentation/generators/generate-manifests.ts b/scripts/documentation/generators/generate-manifests.ts index 9a0d9ee779229..aad8a7b3043ad 100644 --- a/scripts/documentation/generators/generate-manifests.ts +++ b/scripts/documentation/generators/generate-manifests.ts @@ -361,12 +361,6 @@ function createDocumentSections( .itemList as Partial[], prefix: '', }, - { - name: 'recipes', - content: documents.find((x) => x.id === 'nx-recipes')! - .itemList as Partial[], - prefix: 'recipes', - }, { name: 'extending-nx', content: documents.find((x) => x.id === 'extending-nx')! diff --git a/tsconfig.base.json b/tsconfig.base.json index 0ef4be573fd53..27bc4a9441913 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -8,136 +8,61 @@ "experimentalDecorators": true, "emitDecoratorMetadata": true, "skipLibCheck": true, - "types": [ - "node", - "jest" - ], - "lib": [ - "es2019" - ], + "types": ["node", "jest"], + "lib": ["es2019"], "declaration": true, "resolveJsonModule": true, "baseUrl": ".", "rootDir": ".", "allowJs": true, "paths": { - "@nrwl/tao": [ - "packages/tao" - ], - "@nrwl/tao/*": [ - "packages/tao/*" - ], - "@nx/angular": [ - "packages/angular" - ], - "@nx/angular/*": [ - "packages/angular/*" - ], - "@nx/cypress": [ - "packages/cypress" - ], - "@nx/cypress/*": [ - "packages/cypress/*" - ], - "@nx/detox": [ - "packages/detox" - ], - "@nx/devkit": [ - "packages/devkit" - ], - "@nx/devkit/*": [ - "packages/devkit/*" - ], - "@nx/docs": [ - "docs" - ], - "@nx/docs/*": [ - "docs/*" - ], - "@nx/e2e/utils": [ - "e2e/utils" - ], - "@nx/esbuild": [ - "packages/esbuild" - ], - "@nx/eslint-plugin": [ - "packages/eslint-plugin/src" - ], - "@nx/expo": [ - "packages/expo" - ], - "@nx/expo/*": [ - "packages/expo/*" - ], - "@nx/express": [ - "packages/express" - ], - "@nx/graph/ui-components": [ - "graph/ui-components/src/index.ts" - ], - "@nx/graph/ui-graph": [ - "graph/ui-graph/src/index.ts" - ], - "@nx/graph/ui-tooltips": [ - "graph/ui-tooltips/src/index.ts" - ], - "@nx/jest": [ - "packages/jest" - ], - "@nx/jest/*": [ - "packages/jest/*" - ], - "@nx/js": [ - "packages/js/src" - ], - "@nx/js/*": [ - "packages/js/*" - ], - "@nx/linter": [ - "packages/linter" - ], - "@nx/linter/*": [ - "packages/linter/*" - ], - "@nx/nest": [ - "packages/nest" - ], - "@nx/next": [ - "packages/next" - ], - "@nx/next/*": [ - "packages/next/*" - ], - "@nx/node": [ - "packages/node" - ], - "@nx/node/*": [ - "packages/node/*" - ], - "@nx/nx-dev/data-access-ai": [ - "nx-dev/data-access-ai/src/index.ts" - ], + "@nrwl/tao": ["packages/tao"], + "@nrwl/tao/*": ["packages/tao/*"], + "@nx/angular": ["packages/angular"], + "@nx/angular/*": ["packages/angular/*"], + "@nx/cypress": ["packages/cypress"], + "@nx/cypress/*": ["packages/cypress/*"], + "@nx/detox": ["packages/detox"], + "@nx/devkit": ["packages/devkit"], + "@nx/devkit/*": ["packages/devkit/*"], + "@nx/docs": ["docs"], + "@nx/docs/*": ["docs/*"], + "@nx/e2e/utils": ["e2e/utils"], + "@nx/esbuild": ["packages/esbuild"], + "@nx/eslint-plugin": ["packages/eslint-plugin/src"], + "@nx/expo": ["packages/expo"], + "@nx/expo/*": ["packages/expo/*"], + "@nx/express": ["packages/express"], + "@nx/graph/ui-components": ["graph/ui-components/src/index.ts"], + "@nx/graph/ui-graph": ["graph/ui-graph/src/index.ts"], + "@nx/graph/ui-tooltips": ["graph/ui-tooltips/src/index.ts"], + "@nx/jest": ["packages/jest"], + "@nx/jest/*": ["packages/jest/*"], + "@nx/js": ["packages/js/src"], + "@nx/js/*": ["packages/js/*"], + "@nx/linter": ["packages/linter"], + "@nx/linter/*": ["packages/linter/*"], + "@nx/nest": ["packages/nest"], + "@nx/next": ["packages/next"], + "@nx/next/*": ["packages/next/*"], + "@nx/node": ["packages/node"], + "@nx/node/*": ["packages/node/*"], + "@nx/nx-dev/data-access-ai": ["nx-dev/data-access-ai/src/index.ts"], "@nx/nx-dev/data-access-documents": [ "nx-dev/data-access-documents/src/index.ts" ], "@nx/nx-dev/data-access-documents/node-only": [ "nx-dev/data-access-documents/src/node.index.ts" ], - "@nx/nx-dev/data-access-menu": [ - "nx-dev/data-access-menu/src/index.ts" - ], + "@nx/nx-dev/data-access-menu": ["nx-dev/data-access-menu/src/index.ts"], "@nx/nx-dev/data-access-packages": [ "nx-dev/data-access-packages/src/index.ts" ], "@nx/nx-dev/data-access-packages/node-only": [ "nx-dev/data-access-packages/src/node.index.ts" ], - "@nx/nx-dev/feature-ai": [ - "nx-dev/feature-ai/src/index.ts" - ], - "@nx/nx-dev/feature-analytics": [ - "nx-dev/feature-analytics/src/index.ts" - ], + "@nx/nx-dev/feature-ai": ["nx-dev/feature-ai/src/index.ts"], + "@nx/nx-dev/feature-analytics": ["nx-dev/feature-analytics/src/index.ts"], "@nx/nx-dev/feature-doc-viewer": [ "nx-dev/feature-doc-viewer/src/index.ts" ], @@ -147,126 +72,46 @@ "@nx/nx-dev/feature-package-schema-viewer/*": [ "nx-dev/feature-package-schema-viewer/*" ], - "@nx/nx-dev/feature-search": [ - "nx-dev/feature-search/src/index.ts" - ], - "@nx/nx-dev/models-document": [ - "nx-dev/models-document/src/index.ts" - ], - "@nx/nx-dev/models-menu": [ - "nx-dev/models-menu/src/index.ts" - ], - "@nx/nx-dev/models-package": [ - "nx-dev/models-package/src/index.ts" - ], - "@nx/nx-dev/ui-commands": [ - "nx-dev/ui-commands/src/index.ts" - ], - "@nx/nx-dev/ui-common": [ - "nx-dev/ui-common/src/index.ts" - ], - "@nx/nx-dev/ui-community": [ - "nx-dev/ui-community/src/index.ts" - ], - "@nx/nx-dev/ui-conference": [ - "nx-dev/ui-conference/src/index.ts" - ], - "@nx/nx-dev/ui-home": [ - "nx-dev/ui-home/src/index.ts" - ], - "@nx/nx-dev/ui-markdoc": [ - "nx-dev/ui-markdoc/src/index.ts" - ], - "@nx/nx-dev/ui-member-card": [ - "nx-dev/ui-member-card/src/index.ts" - ], - "@nx/nx-dev/ui-primitives": [ - "nx-dev/ui-primitives/src/index.ts" - ], - "@nx/nx-dev/ui-references": [ - "nx-dev/ui-references/src/index.ts" - ], - "@nx/nx-dev/ui-sponsor-card": [ - "nx-dev/ui-sponsor-card/src/index.ts" - ], - "@nx/nx-dev/ui-theme": [ - "nx-dev/ui-theme/src/index.ts" - ], - "@nx/playwright": [ - "packages/playwright/index.ts" - ], - "@nx/plugin": [ - "packages/plugin" - ], - "@nx/plugin/*": [ - "packages/plugin/*" - ], - "@nx/react": [ - "packages/react" - ], - "@nx/react-native": [ - "packages/react-native" - ], - "@nx/react-native/*": [ - "packages/react-native/*" - ], - "@nx/react/*": [ - "packages/react/*" - ], - "@nx/rollup": [ - "packages/rollup" - ], - "@nx/rollup/*": [ - "packages/rollup/*" - ], - "@nx/storybook": [ - "packages/storybook" - ], - "@nx/storybook/*": [ - "packages/storybook/*" - ], - "@nx/typedoc-theme": [ - "typedoc-theme/src/index.ts" - ], - "@nx/vite": [ - "packages/vite" - ], - "@nx/vite/*": [ - "packages/vite/*" - ], - "@nx/web": [ - "packages/web" - ], - "@nx/web/*": [ - "packages/web/*" - ], - "@nx/webpack": [ - "packages/webpack" - ], - "@nx/webpack/*": [ - "packages/webpack/*" - ], - "@nx/workspace": [ - "packages/workspace" - ], - "@nx/workspace/*": [ - "packages/workspace/*" - ], - "@nx/workspace/testing": [ - "packages/workspace/testing" - ], - "create-nx-workspace": [ - "packages/create-nx-workspace/index.ts" - ], - "create-nx-workspace/*": [ - "packages/create-nx-workspace/*" - ], - "nx": [ - "packages/nx" - ], - "nx/*": [ - "packages/nx/*" - ] + "@nx/nx-dev/feature-search": ["nx-dev/feature-search/src/index.ts"], + "@nx/nx-dev/models-document": ["nx-dev/models-document/src/index.ts"], + "@nx/nx-dev/models-menu": ["nx-dev/models-menu/src/index.ts"], + "@nx/nx-dev/models-package": ["nx-dev/models-package/src/index.ts"], + "@nx/nx-dev/ui-commands": ["nx-dev/ui-commands/src/index.ts"], + "@nx/nx-dev/ui-common": ["nx-dev/ui-common/src/index.ts"], + "@nx/nx-dev/ui-community": ["nx-dev/ui-community/src/index.ts"], + "@nx/nx-dev/ui-conference": ["nx-dev/ui-conference/src/index.ts"], + "@nx/nx-dev/ui-home": ["nx-dev/ui-home/src/index.ts"], + "@nx/nx-dev/ui-markdoc": ["nx-dev/ui-markdoc/src/index.ts"], + "@nx/nx-dev/ui-member-card": ["nx-dev/ui-member-card/src/index.ts"], + "@nx/nx-dev/ui-primitives": ["nx-dev/ui-primitives/src/index.ts"], + "@nx/nx-dev/ui-references": ["nx-dev/ui-references/src/index.ts"], + "@nx/nx-dev/ui-sponsor-card": ["nx-dev/ui-sponsor-card/src/index.ts"], + "@nx/nx-dev/ui-theme": ["nx-dev/ui-theme/src/index.ts"], + "@nx/playwright": ["packages/playwright/index.ts"], + "@nx/plugin": ["packages/plugin"], + "@nx/plugin/*": ["packages/plugin/*"], + "@nx/react": ["packages/react"], + "@nx/react-native": ["packages/react-native"], + "@nx/react-native/*": ["packages/react-native/*"], + "@nx/react/*": ["packages/react/*"], + "@nx/rollup": ["packages/rollup"], + "@nx/rollup/*": ["packages/rollup/*"], + "@nx/storybook": ["packages/storybook"], + "@nx/storybook/*": ["packages/storybook/*"], + "@nx/typedoc-theme": ["typedoc-theme/src/index.ts"], + "@nx/vite": ["packages/vite"], + "@nx/vite/*": ["packages/vite/*"], + "@nx/web": ["packages/web"], + "@nx/web/*": ["packages/web/*"], + "@nx/webpack": ["packages/webpack"], + "@nx/webpack/*": ["packages/webpack/*"], + "@nx/workspace": ["packages/workspace"], + "@nx/workspace/*": ["packages/workspace/*"], + "@nx/workspace/testing": ["packages/workspace/testing"], + "create-nx-workspace": ["packages/create-nx-workspace/index.ts"], + "create-nx-workspace/*": ["packages/create-nx-workspace/*"], + "nx": ["packages/nx"], + "nx/*": ["packages/nx/*"] } } } From a8bc69b61eab3eeb80d4fbba8e0c4aeab00833ca Mon Sep 17 00:00:00 2001 From: Miroslav Jonas Date: Mon, 24 Jul 2023 11:42:27 +0200 Subject: [PATCH 157/262] docs(nx-dev): extract example repos --- docs/generated/manifests/menus.json | 229 +++++++------- docs/generated/manifests/nx.json | 297 +++++++++--------- docs/generated/manifests/tags.json | 22 +- docs/map.json | 9 +- docs/shared/reference/sitemap.md | 23 +- nx-dev/data-access-menu/src/lib/menu.utils.ts | 1 + nx-dev/nx-dev/redirect-rules.js | 21 +- 7 files changed, 316 insertions(+), 286 deletions(-) diff --git a/docs/generated/manifests/menus.json b/docs/generated/manifests/menus.json index da6082ebfcac9..d04a6234fd754 100644 --- a/docs/generated/manifests/menus.json +++ b/docs/generated/manifests/menus.json @@ -2250,95 +2250,6 @@ } ], "disableCollapsible": false - }, - { - "name": "Example Repos", - "path": "/recipes/example-repos", - "id": "example-repos", - "isExternal": false, - "children": [ - { - "name": "Powering Up React Development With Nx", - "path": "/recipes/example-repos/react-nx", - "id": "react-nx", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Using Apollo GraphQL", - "path": "/recipes/example-repos/apollo-react", - "id": "apollo-react", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Using Prisma with NestJS", - "path": "/recipes/example-repos/nestjs-prisma", - "id": "nestjs-prisma", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Using Mongo with Fastify", - "path": "/recipes/example-repos/mongo-fastify", - "id": "mongo-fastify", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Using Redis with Fastify", - "path": "/recipes/example-repos/redis-fastify", - "id": "redis-fastify", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Using Postgres with Fastify", - "path": "/recipes/example-repos/postgres-fastify", - "id": "postgres-fastify", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Using PlanetScale with Serverless Fastify", - "path": "/recipes/example-repos/serverless-fastify-planetscale", - "id": "serverless-fastify-planetscale", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Large Repo and Caching", - "path": "/recipes/example-repos/caching", - "id": "caching", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Large Repo and DTE", - "path": "/recipes/example-repos/dte", - "id": "dte", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Nx Micro-Frontend Example", - "path": "/recipes/example-repos/mfe", - "id": "mfe", - "isExternal": false, - "children": [], - "disableCollapsible": false - } - ], - "disableCollapsible": false } ], "disableCollapsible": false @@ -3580,15 +3491,113 @@ "children": [], "disableCollapsible": false }, + { + "name": "Showcase", + "path": "/showcase", + "id": "showcase", + "isExternal": false, + "children": [ + { + "name": "Example Repos", + "path": "/showcase/example-repos", + "id": "example-repos", + "isExternal": false, + "children": [ + { + "name": "Powering Up React Development With Nx", + "path": "/showcase/example-repos/react-nx", + "id": "react-nx", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Using Apollo GraphQL", + "path": "/showcase/example-repos/apollo-react", + "id": "apollo-react", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Using Prisma with NestJS", + "path": "/showcase/example-repos/nestjs-prisma", + "id": "nestjs-prisma", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Using Mongo with Fastify", + "path": "/showcase/example-repos/mongo-fastify", + "id": "mongo-fastify", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Using Redis with Fastify", + "path": "/showcase/example-repos/redis-fastify", + "id": "redis-fastify", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Using Postgres with Fastify", + "path": "/showcase/example-repos/postgres-fastify", + "id": "postgres-fastify", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Using PlanetScale with Serverless Fastify", + "path": "/showcase/example-repos/serverless-fastify-planetscale", + "id": "serverless-fastify-planetscale", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Large Repo and Caching", + "path": "/showcase/example-repos/caching", + "id": "caching", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Large Repo and DTE", + "path": "/showcase/example-repos/dte", + "id": "dte", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Nx Micro-Frontend Example", + "path": "/showcase/example-repos/mfe", + "id": "mfe", + "isExternal": false, + "children": [], + "disableCollapsible": false + } + ], + "disableCollapsible": false + } + ], + "disableCollapsible": false + }, { "name": "Example Repos", - "path": "/recipes/example-repos", + "path": "/showcase/example-repos", "id": "example-repos", "isExternal": false, "children": [ { "name": "Powering Up React Development With Nx", - "path": "/recipes/example-repos/react-nx", + "path": "/showcase/example-repos/react-nx", "id": "react-nx", "isExternal": false, "children": [], @@ -3596,7 +3605,7 @@ }, { "name": "Using Apollo GraphQL", - "path": "/recipes/example-repos/apollo-react", + "path": "/showcase/example-repos/apollo-react", "id": "apollo-react", "isExternal": false, "children": [], @@ -3604,7 +3613,7 @@ }, { "name": "Using Prisma with NestJS", - "path": "/recipes/example-repos/nestjs-prisma", + "path": "/showcase/example-repos/nestjs-prisma", "id": "nestjs-prisma", "isExternal": false, "children": [], @@ -3612,7 +3621,7 @@ }, { "name": "Using Mongo with Fastify", - "path": "/recipes/example-repos/mongo-fastify", + "path": "/showcase/example-repos/mongo-fastify", "id": "mongo-fastify", "isExternal": false, "children": [], @@ -3620,7 +3629,7 @@ }, { "name": "Using Redis with Fastify", - "path": "/recipes/example-repos/redis-fastify", + "path": "/showcase/example-repos/redis-fastify", "id": "redis-fastify", "isExternal": false, "children": [], @@ -3628,7 +3637,7 @@ }, { "name": "Using Postgres with Fastify", - "path": "/recipes/example-repos/postgres-fastify", + "path": "/showcase/example-repos/postgres-fastify", "id": "postgres-fastify", "isExternal": false, "children": [], @@ -3636,7 +3645,7 @@ }, { "name": "Using PlanetScale with Serverless Fastify", - "path": "/recipes/example-repos/serverless-fastify-planetscale", + "path": "/showcase/example-repos/serverless-fastify-planetscale", "id": "serverless-fastify-planetscale", "isExternal": false, "children": [], @@ -3644,7 +3653,7 @@ }, { "name": "Large Repo and Caching", - "path": "/recipes/example-repos/caching", + "path": "/showcase/example-repos/caching", "id": "caching", "isExternal": false, "children": [], @@ -3652,7 +3661,7 @@ }, { "name": "Large Repo and DTE", - "path": "/recipes/example-repos/dte", + "path": "/showcase/example-repos/dte", "id": "dte", "isExternal": false, "children": [], @@ -3660,7 +3669,7 @@ }, { "name": "Nx Micro-Frontend Example", - "path": "/recipes/example-repos/mfe", + "path": "/showcase/example-repos/mfe", "id": "mfe", "isExternal": false, "children": [], @@ -3671,7 +3680,7 @@ }, { "name": "Powering Up React Development With Nx", - "path": "/recipes/example-repos/react-nx", + "path": "/showcase/example-repos/react-nx", "id": "react-nx", "isExternal": false, "children": [], @@ -3679,7 +3688,7 @@ }, { "name": "Using Apollo GraphQL", - "path": "/recipes/example-repos/apollo-react", + "path": "/showcase/example-repos/apollo-react", "id": "apollo-react", "isExternal": false, "children": [], @@ -3687,7 +3696,7 @@ }, { "name": "Using Prisma with NestJS", - "path": "/recipes/example-repos/nestjs-prisma", + "path": "/showcase/example-repos/nestjs-prisma", "id": "nestjs-prisma", "isExternal": false, "children": [], @@ -3695,7 +3704,7 @@ }, { "name": "Using Mongo with Fastify", - "path": "/recipes/example-repos/mongo-fastify", + "path": "/showcase/example-repos/mongo-fastify", "id": "mongo-fastify", "isExternal": false, "children": [], @@ -3703,7 +3712,7 @@ }, { "name": "Using Redis with Fastify", - "path": "/recipes/example-repos/redis-fastify", + "path": "/showcase/example-repos/redis-fastify", "id": "redis-fastify", "isExternal": false, "children": [], @@ -3711,7 +3720,7 @@ }, { "name": "Using Postgres with Fastify", - "path": "/recipes/example-repos/postgres-fastify", + "path": "/showcase/example-repos/postgres-fastify", "id": "postgres-fastify", "isExternal": false, "children": [], @@ -3719,7 +3728,7 @@ }, { "name": "Using PlanetScale with Serverless Fastify", - "path": "/recipes/example-repos/serverless-fastify-planetscale", + "path": "/showcase/example-repos/serverless-fastify-planetscale", "id": "serverless-fastify-planetscale", "isExternal": false, "children": [], @@ -3727,7 +3736,7 @@ }, { "name": "Large Repo and Caching", - "path": "/recipes/example-repos/caching", + "path": "/showcase/example-repos/caching", "id": "caching", "isExternal": false, "children": [], @@ -3735,7 +3744,7 @@ }, { "name": "Large Repo and DTE", - "path": "/recipes/example-repos/dte", + "path": "/showcase/example-repos/dte", "id": "dte", "isExternal": false, "children": [], @@ -3743,7 +3752,7 @@ }, { "name": "Nx Micro-Frontend Example", - "path": "/recipes/example-repos/mfe", + "path": "/showcase/example-repos/mfe", "id": "mfe", "isExternal": false, "children": [], diff --git a/docs/generated/manifests/nx.json b/docs/generated/manifests/nx.json index b6ac9e9510db9..69bc1176235c6 100644 --- a/docs/generated/manifests/nx.json +++ b/docs/generated/manifests/nx.json @@ -2801,117 +2801,6 @@ "isExternal": false, "path": "/recipes/other", "tags": [] - }, - { - "id": "example-repos", - "name": "Example Repos", - "description": "Examples of different ways to use Nx", - "file": "", - "itemList": [ - { - "id": "react-nx", - "name": "Powering Up React Development With Nx", - "description": "", - "file": "shared/examples/react-nx", - "itemList": [], - "isExternal": false, - "path": "/recipes/example-repos/react-nx", - "tags": [] - }, - { - "id": "apollo-react", - "name": "Using Apollo GraphQL", - "description": "", - "file": "shared/examples/apollo-react", - "itemList": [], - "isExternal": false, - "path": "/recipes/example-repos/apollo-react", - "tags": [] - }, - { - "id": "nestjs-prisma", - "name": "Using Prisma with NestJS", - "description": "", - "file": "shared/recipes/database/nestjs-prisma", - "itemList": [], - "isExternal": false, - "path": "/recipes/example-repos/nestjs-prisma", - "tags": ["database", "node"] - }, - { - "id": "mongo-fastify", - "name": "Using Mongo with Fastify", - "description": "", - "file": "shared/recipes/database/mongo-fastify", - "itemList": [], - "isExternal": false, - "path": "/recipes/example-repos/mongo-fastify", - "tags": ["database", "node"] - }, - { - "id": "redis-fastify", - "name": "Using Redis with Fastify", - "description": "", - "file": "shared/recipes/database/redis-fastify", - "itemList": [], - "isExternal": false, - "path": "/recipes/example-repos/redis-fastify", - "tags": ["database", "node"] - }, - { - "id": "postgres-fastify", - "name": "Using Postgres with Fastify", - "description": "", - "file": "shared/recipes/database/postgres-fastify", - "itemList": [], - "isExternal": false, - "path": "/recipes/example-repos/postgres-fastify", - "tags": ["database", "node"] - }, - { - "id": "serverless-fastify-planetscale", - "name": "Using PlanetScale with Serverless Fastify", - "description": "", - "file": "shared/recipes/database/serverless-fastify-planetscale", - "itemList": [], - "isExternal": false, - "path": "/recipes/example-repos/serverless-fastify-planetscale", - "tags": ["database", "node", "serverless"] - }, - { - "id": "caching", - "name": "Large Repo and Caching", - "description": "", - "file": "shared/examples/caching", - "itemList": [], - "isExternal": false, - "path": "/recipes/example-repos/caching", - "tags": [] - }, - { - "id": "dte", - "name": "Large Repo and DTE", - "description": "", - "file": "shared/examples/dte", - "itemList": [], - "isExternal": false, - "path": "/recipes/example-repos/dte", - "tags": [] - }, - { - "id": "mfe", - "name": "Nx Micro-Frontend Example", - "description": "", - "file": "shared/examples/nx-examples", - "itemList": [], - "isExternal": false, - "path": "/recipes/example-repos/mfe", - "tags": [] - } - ], - "isExternal": false, - "path": "/recipes/example-repos", - "tags": [] } ], "isExternal": false, @@ -4461,7 +4350,129 @@ "path": "/recipes/other/rescope", "tags": [] }, - "/recipes/example-repos": { + "/showcase": { + "id": "showcase", + "name": "Showcase", + "description": "Discover our selection of examples and benchmarks.", + "file": "", + "itemList": [ + { + "id": "example-repos", + "name": "Example Repos", + "description": "Examples of different ways to use Nx", + "file": "", + "itemList": [ + { + "id": "react-nx", + "name": "Powering Up React Development With Nx", + "description": "", + "file": "shared/examples/react-nx", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/react-nx", + "tags": [] + }, + { + "id": "apollo-react", + "name": "Using Apollo GraphQL", + "description": "", + "file": "shared/examples/apollo-react", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/apollo-react", + "tags": [] + }, + { + "id": "nestjs-prisma", + "name": "Using Prisma with NestJS", + "description": "", + "file": "shared/recipes/database/nestjs-prisma", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/nestjs-prisma", + "tags": ["database", "node"] + }, + { + "id": "mongo-fastify", + "name": "Using Mongo with Fastify", + "description": "", + "file": "shared/recipes/database/mongo-fastify", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/mongo-fastify", + "tags": ["database", "node"] + }, + { + "id": "redis-fastify", + "name": "Using Redis with Fastify", + "description": "", + "file": "shared/recipes/database/redis-fastify", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/redis-fastify", + "tags": ["database", "node"] + }, + { + "id": "postgres-fastify", + "name": "Using Postgres with Fastify", + "description": "", + "file": "shared/recipes/database/postgres-fastify", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/postgres-fastify", + "tags": ["database", "node"] + }, + { + "id": "serverless-fastify-planetscale", + "name": "Using PlanetScale with Serverless Fastify", + "description": "", + "file": "shared/recipes/database/serverless-fastify-planetscale", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/serverless-fastify-planetscale", + "tags": ["database", "node", "serverless"] + }, + { + "id": "caching", + "name": "Large Repo and Caching", + "description": "", + "file": "shared/examples/caching", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/caching", + "tags": [] + }, + { + "id": "dte", + "name": "Large Repo and DTE", + "description": "", + "file": "shared/examples/dte", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/dte", + "tags": [] + }, + { + "id": "mfe", + "name": "Nx Micro-Frontend Example", + "description": "", + "file": "shared/examples/nx-examples", + "itemList": [], + "isExternal": false, + "path": "/showcase/example-repos/mfe", + "tags": [] + } + ], + "isExternal": false, + "path": "/showcase/example-repos", + "tags": [] + } + ], + "isExternal": false, + "path": "/showcase", + "tags": [] + }, + "/showcase/example-repos": { "id": "example-repos", "name": "Example Repos", "description": "Examples of different ways to use Nx", @@ -4474,7 +4485,7 @@ "file": "shared/examples/react-nx", "itemList": [], "isExternal": false, - "path": "/recipes/example-repos/react-nx", + "path": "/showcase/example-repos/react-nx", "tags": [] }, { @@ -4484,7 +4495,7 @@ "file": "shared/examples/apollo-react", "itemList": [], "isExternal": false, - "path": "/recipes/example-repos/apollo-react", + "path": "/showcase/example-repos/apollo-react", "tags": [] }, { @@ -4494,7 +4505,7 @@ "file": "shared/recipes/database/nestjs-prisma", "itemList": [], "isExternal": false, - "path": "/recipes/example-repos/nestjs-prisma", + "path": "/showcase/example-repos/nestjs-prisma", "tags": ["database", "node"] }, { @@ -4504,7 +4515,7 @@ "file": "shared/recipes/database/mongo-fastify", "itemList": [], "isExternal": false, - "path": "/recipes/example-repos/mongo-fastify", + "path": "/showcase/example-repos/mongo-fastify", "tags": ["database", "node"] }, { @@ -4514,7 +4525,7 @@ "file": "shared/recipes/database/redis-fastify", "itemList": [], "isExternal": false, - "path": "/recipes/example-repos/redis-fastify", + "path": "/showcase/example-repos/redis-fastify", "tags": ["database", "node"] }, { @@ -4524,7 +4535,7 @@ "file": "shared/recipes/database/postgres-fastify", "itemList": [], "isExternal": false, - "path": "/recipes/example-repos/postgres-fastify", + "path": "/showcase/example-repos/postgres-fastify", "tags": ["database", "node"] }, { @@ -4534,7 +4545,7 @@ "file": "shared/recipes/database/serverless-fastify-planetscale", "itemList": [], "isExternal": false, - "path": "/recipes/example-repos/serverless-fastify-planetscale", + "path": "/showcase/example-repos/serverless-fastify-planetscale", "tags": ["database", "node", "serverless"] }, { @@ -4544,7 +4555,7 @@ "file": "shared/examples/caching", "itemList": [], "isExternal": false, - "path": "/recipes/example-repos/caching", + "path": "/showcase/example-repos/caching", "tags": [] }, { @@ -4554,7 +4565,7 @@ "file": "shared/examples/dte", "itemList": [], "isExternal": false, - "path": "/recipes/example-repos/dte", + "path": "/showcase/example-repos/dte", "tags": [] }, { @@ -4564,112 +4575,112 @@ "file": "shared/examples/nx-examples", "itemList": [], "isExternal": false, - "path": "/recipes/example-repos/mfe", + "path": "/showcase/example-repos/mfe", "tags": [] } ], "isExternal": false, - "path": "/recipes/example-repos", + "path": "/showcase/example-repos", "tags": [] }, - "/recipes/example-repos/react-nx": { + "/showcase/example-repos/react-nx": { "id": "react-nx", "name": "Powering Up React Development With Nx", "description": "", "file": "shared/examples/react-nx", "itemList": [], "isExternal": false, - "path": "/recipes/example-repos/react-nx", + "path": "/showcase/example-repos/react-nx", "tags": [] }, - "/recipes/example-repos/apollo-react": { + "/showcase/example-repos/apollo-react": { "id": "apollo-react", "name": "Using Apollo GraphQL", "description": "", "file": "shared/examples/apollo-react", "itemList": [], "isExternal": false, - "path": "/recipes/example-repos/apollo-react", + "path": "/showcase/example-repos/apollo-react", "tags": [] }, - "/recipes/example-repos/nestjs-prisma": { + "/showcase/example-repos/nestjs-prisma": { "id": "nestjs-prisma", "name": "Using Prisma with NestJS", "description": "", "file": "shared/recipes/database/nestjs-prisma", "itemList": [], "isExternal": false, - "path": "/recipes/example-repos/nestjs-prisma", + "path": "/showcase/example-repos/nestjs-prisma", "tags": ["database", "node"] }, - "/recipes/example-repos/mongo-fastify": { + "/showcase/example-repos/mongo-fastify": { "id": "mongo-fastify", "name": "Using Mongo with Fastify", "description": "", "file": "shared/recipes/database/mongo-fastify", "itemList": [], "isExternal": false, - "path": "/recipes/example-repos/mongo-fastify", + "path": "/showcase/example-repos/mongo-fastify", "tags": ["database", "node"] }, - "/recipes/example-repos/redis-fastify": { + "/showcase/example-repos/redis-fastify": { "id": "redis-fastify", "name": "Using Redis with Fastify", "description": "", "file": "shared/recipes/database/redis-fastify", "itemList": [], "isExternal": false, - "path": "/recipes/example-repos/redis-fastify", + "path": "/showcase/example-repos/redis-fastify", "tags": ["database", "node"] }, - "/recipes/example-repos/postgres-fastify": { + "/showcase/example-repos/postgres-fastify": { "id": "postgres-fastify", "name": "Using Postgres with Fastify", "description": "", "file": "shared/recipes/database/postgres-fastify", "itemList": [], "isExternal": false, - "path": "/recipes/example-repos/postgres-fastify", + "path": "/showcase/example-repos/postgres-fastify", "tags": ["database", "node"] }, - "/recipes/example-repos/serverless-fastify-planetscale": { + "/showcase/example-repos/serverless-fastify-planetscale": { "id": "serverless-fastify-planetscale", "name": "Using PlanetScale with Serverless Fastify", "description": "", "file": "shared/recipes/database/serverless-fastify-planetscale", "itemList": [], "isExternal": false, - "path": "/recipes/example-repos/serverless-fastify-planetscale", + "path": "/showcase/example-repos/serverless-fastify-planetscale", "tags": ["database", "node", "serverless"] }, - "/recipes/example-repos/caching": { + "/showcase/example-repos/caching": { "id": "caching", "name": "Large Repo and Caching", "description": "", "file": "shared/examples/caching", "itemList": [], "isExternal": false, - "path": "/recipes/example-repos/caching", + "path": "/showcase/example-repos/caching", "tags": [] }, - "/recipes/example-repos/dte": { + "/showcase/example-repos/dte": { "id": "dte", "name": "Large Repo and DTE", "description": "", "file": "shared/examples/dte", "itemList": [], "isExternal": false, - "path": "/recipes/example-repos/dte", + "path": "/showcase/example-repos/dte", "tags": [] }, - "/recipes/example-repos/mfe": { + "/showcase/example-repos/mfe": { "id": "mfe", "name": "Nx Micro-Frontend Example", "description": "", "file": "shared/examples/nx-examples", "itemList": [], "isExternal": false, - "path": "/recipes/example-repos/mfe", + "path": "/showcase/example-repos/mfe", "tags": [] }, "/reference": { diff --git a/docs/generated/manifests/tags.json b/docs/generated/manifests/tags.json index f4eedb8d4124a..5acc0429ea6d0 100644 --- a/docs/generated/manifests/tags.json +++ b/docs/generated/manifests/tags.json @@ -797,35 +797,35 @@ "file": "shared/recipes/database/nestjs-prisma", "id": "nestjs-prisma", "name": "Using Prisma with NestJS", - "path": "/recipes/example-repos/nestjs-prisma" + "path": "/showcase/example-repos/nestjs-prisma" }, { "description": "", "file": "shared/recipes/database/mongo-fastify", "id": "mongo-fastify", "name": "Using Mongo with Fastify", - "path": "/recipes/example-repos/mongo-fastify" + "path": "/showcase/example-repos/mongo-fastify" }, { "description": "", "file": "shared/recipes/database/redis-fastify", "id": "redis-fastify", "name": "Using Redis with Fastify", - "path": "/recipes/example-repos/redis-fastify" + "path": "/showcase/example-repos/redis-fastify" }, { "description": "", "file": "shared/recipes/database/postgres-fastify", "id": "postgres-fastify", "name": "Using Postgres with Fastify", - "path": "/recipes/example-repos/postgres-fastify" + "path": "/showcase/example-repos/postgres-fastify" }, { "description": "", "file": "shared/recipes/database/serverless-fastify-planetscale", "id": "serverless-fastify-planetscale", "name": "Using PlanetScale with Serverless Fastify", - "path": "/recipes/example-repos/serverless-fastify-planetscale" + "path": "/showcase/example-repos/serverless-fastify-planetscale" } ], "storybook": [ @@ -907,35 +907,35 @@ "file": "shared/recipes/database/nestjs-prisma", "id": "nestjs-prisma", "name": "Using Prisma with NestJS", - "path": "/recipes/example-repos/nestjs-prisma" + "path": "/showcase/example-repos/nestjs-prisma" }, { "description": "", "file": "shared/recipes/database/mongo-fastify", "id": "mongo-fastify", "name": "Using Mongo with Fastify", - "path": "/recipes/example-repos/mongo-fastify" + "path": "/showcase/example-repos/mongo-fastify" }, { "description": "", "file": "shared/recipes/database/redis-fastify", "id": "redis-fastify", "name": "Using Redis with Fastify", - "path": "/recipes/example-repos/redis-fastify" + "path": "/showcase/example-repos/redis-fastify" }, { "description": "", "file": "shared/recipes/database/postgres-fastify", "id": "postgres-fastify", "name": "Using Postgres with Fastify", - "path": "/recipes/example-repos/postgres-fastify" + "path": "/showcase/example-repos/postgres-fastify" }, { "description": "", "file": "shared/recipes/database/serverless-fastify-planetscale", "id": "serverless-fastify-planetscale", "name": "Using PlanetScale with Serverless Fastify", - "path": "/recipes/example-repos/serverless-fastify-planetscale" + "path": "/showcase/example-repos/serverless-fastify-planetscale" } ], "serverless": [ @@ -944,7 +944,7 @@ "file": "shared/recipes/database/serverless-fastify-planetscale", "id": "serverless-fastify-planetscale", "name": "Using PlanetScale with Serverless Fastify", - "path": "/recipes/example-repos/serverless-fastify-planetscale" + "path": "/showcase/example-repos/serverless-fastify-planetscale" } ] } diff --git a/docs/map.json b/docs/map.json index 8a9b921c275a4..a4df93f889734 100644 --- a/docs/map.json +++ b/docs/map.json @@ -978,7 +978,14 @@ "file": "shared/recipes/rescope" } ] - }, + } + ] + }, + { + "name": "Showcase", + "id": "showcase", + "description": "Discover our selection of examples and benchmarks.", + "itemList": [ { "name": "Example Repos", "id": "example-repos", diff --git a/docs/shared/reference/sitemap.md b/docs/shared/reference/sitemap.md index b224ee6267877..50dcc3807b15b 100644 --- a/docs/shared/reference/sitemap.md +++ b/docs/shared/reference/sitemap.md @@ -170,17 +170,18 @@ - [Serverless deployment with Deno Deploy](/recipes/other/deno-deploy) - [Add and Deploy Netlify Edge Functions with Deno](/recipes/other/deno-netlify-functions) - [Rescope Packages from @nrwl to @nx](/recipes/other/rescope) - - [Example Repos](/recipes/example-repos) - - [Powering Up React Development With Nx](/recipes/example-repos/react-nx) - - [Using Apollo GraphQL](/recipes/example-repos/apollo-react) - - [Using Prisma with NestJS](/recipes/example-repos/nestjs-prisma) - - [Using Mongo with Fastify](/recipes/example-repos/mongo-fastify) - - [Using Redis with Fastify](/recipes/example-repos/redis-fastify) - - [Using Postgres with Fastify](/recipes/example-repos/postgres-fastify) - - [Using PlanetScale with Serverless Fastify](/recipes/example-repos/serverless-fastify-planetscale) - - [Large Repo and Caching](/recipes/example-repos/caching) - - [Large Repo and DTE](/recipes/example-repos/dte) - - [Nx Micro-Frontend Example](/recipes/example-repos/mfe) + - [Showcase](/showcase) + - [Example Repos](/showcase/example-repos) + - [Powering Up React Development With Nx](/showcase/example-repos/react-nx) + - [Using Apollo GraphQL](/showcase/example-repos/apollo-react) + - [Using Prisma with NestJS](/showcase/example-repos/nestjs-prisma) + - [Using Mongo with Fastify](/showcase/example-repos/mongo-fastify) + - [Using Redis with Fastify](/showcase/example-repos/redis-fastify) + - [Using Postgres with Fastify](/showcase/example-repos/postgres-fastify) + - [Using PlanetScale with Serverless Fastify](/showcase/example-repos/serverless-fastify-planetscale) + - [Large Repo and Caching](/showcase/example-repos/caching) + - [Large Repo and DTE](/showcase/example-repos/dte) + - [Nx Micro-Frontend Example](/showcase/example-repos/mfe) - [Reference](/reference) - [Commands](/reference/commands) - [nx.json](/reference/nx-json) diff --git a/nx-dev/data-access-menu/src/lib/menu.utils.ts b/nx-dev/data-access-menu/src/lib/menu.utils.ts index 1c97ec4dc099c..c4114220d7d42 100644 --- a/nx-dev/data-access-menu/src/lib/menu.utils.ts +++ b/nx-dev/data-access-menu/src/lib/menu.utils.ts @@ -12,6 +12,7 @@ export function getBasicNxSection(items: MenuItem[]): MenuSection { m.id === 'core-features' || m.id === 'concepts' || m.id === 'recipes' || + m.id === 'showcase' || m.id === 'reference' ) .map((m) => { diff --git a/nx-dev/nx-dev/redirect-rules.js b/nx-dev/nx-dev/redirect-rules.js index 9d9be565962bc..c9de8d30e22e4 100644 --- a/nx-dev/nx-dev/redirect-rules.js +++ b/nx-dev/nx-dev/redirect-rules.js @@ -361,10 +361,10 @@ const recipesUrls = { '/recipes/enforce-module-boundaries/ban-external-imports', '/recipes/other/tags-allow-list': '/recipes/enforce-module-boundaries/tags-allow-list', - '/recipes/other/react-nx': '/recipes/example-repos/react-nx', - '/recipes/other/apollo-react': '/recipes/example-repos/apollo-react', - '/recipes/other/caching': '/recipes/example-repos/caching', - '/recipes/other/dte': '/recipes/example-repos/dte', + '/recipes/other/react-nx': '/showcase/example-repos/react-nx', + '/recipes/other/apollo-react': '/showcase/example-repos/apollo-react', + '/recipes/other/caching': '/showcase/example-repos/caching', + '/recipes/other/dte': '/showcase/example-repos/dte', '/recipes/other/deploy-nextjs-to-vercel': '/recipes/deployment/deploy-nextjs-to-vercel', '/recipes/other/root-level-scripts': @@ -771,14 +771,15 @@ const latestRecipesRefactoring = { '/recipes/node/node-serverless-functions-netlify', '/recipes/deployment/node-aws-lambda': '/recipes/node/node-aws-lambda', // examples - '/recipes/module-federation/nx-examples': '/recipes/example-repos/mfe', - '/recipes/database/nestjs-prisma': '/recipes/example-repos/nestjs-prisma', - '/recipes/database/mongo-fastify': '/recipes/example-repos/mongo-fastify', - '/recipes/database/redis-fastify': '/recipes/example-repos/redis-fastify', + '/recipes/module-federation/nx-examples': '/showcase/example-repos/mfe', + '/recipes/database/nestjs-prisma': '/showcase/example-repos/nestjs-prisma', + '/recipes/database/mongo-fastify': '/showcase/example-repos/mongo-fastify', + '/recipes/database/redis-fastify': '/showcase/example-repos/redis-fastify', '/recipes/database/postgres-fastify': - '/recipes/example-repos/postgres-fastify', + '/showcase/example-repos/postgres-fastify', '/recipes/database/serverless-fastify-planetscale': - '/recipes/example-repos/serverless-fastify-planetscale', + '/showcase/example-repos/serverless-fastify-planetscale', + '/recipes/example-repos/:path*': '/showcase/example-repos/:path*', // troubleshooting '/recipes/other/resolve-circular-dependencies': '/recipes/troubleshooting/resolve-circular-dependencies', From b08c7e02f5d1d2e6397323862ddb541085d48ed7 Mon Sep 17 00:00:00 2001 From: Miroslav Jonas Date: Mon, 24 Jul 2023 11:45:08 +0200 Subject: [PATCH 158/262] docs(nx-dev): reorder menu items --- docs/generated/manifests/menus.json | 1042 +++++++++---------- docs/generated/manifests/nx.json | 1428 +++++++++++++-------------- docs/generated/manifests/tags.json | 78 +- docs/map.json | 266 ++--- docs/shared/reference/sitemap.md | 46 +- 5 files changed, 1430 insertions(+), 1430 deletions(-) diff --git a/docs/generated/manifests/menus.json b/docs/generated/manifests/menus.json index d04a6234fd754..1496e19820f2f 100644 --- a/docs/generated/manifests/menus.json +++ b/docs/generated/manifests/menus.json @@ -1648,6 +1648,87 @@ ], "disableCollapsible": false }, + { + "name": "React", + "path": "/recipes/react", + "id": "react", + "isExternal": false, + "children": [ + { + "name": "Migrating from CRA", + "path": "/recipes/react/migration-cra", + "id": "migration-cra", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "React 18 Migration", + "path": "/recipes/react/react-18", + "id": "react-18", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "React Native with Nx", + "path": "/recipes/react/react-native", + "id": "react-native", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Remix with Nx", + "path": "/recipes/react/remix", + "id": "remix", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Use Environment Variables in React", + "path": "/recipes/react/use-environment-variables-in-react", + "id": "use-environment-variables-in-react", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Using Tailwind CSS in React", + "path": "/recipes/react/using-tailwind-css-in-react", + "id": "using-tailwind-css-in-react", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Adding Images, Fonts, and Files", + "path": "/recipes/react/adding-assets-react", + "id": "adding-assets-react", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Setup Module Federation with SSR for React", + "path": "/recipes/react/module-federation-with-ssr", + "id": "module-federation-with-ssr", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Deploying Next.js applications to Vercel", + "path": "/recipes/react/deploy-nextjs-to-vercel", + "id": "deploy-nextjs-to-vercel", + "isExternal": false, + "children": [], + "disableCollapsible": false + } + ], + "disableCollapsible": false + }, { "name": "Angular", "path": "/recipes/angular", @@ -1738,87 +1819,6 @@ ], "disableCollapsible": false }, - { - "name": "React", - "path": "/recipes/react", - "id": "react", - "isExternal": false, - "children": [ - { - "name": "Migrating from CRA", - "path": "/recipes/react/migration-cra", - "id": "migration-cra", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "React 18 Migration", - "path": "/recipes/react/react-18", - "id": "react-18", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "React Native with Nx", - "path": "/recipes/react/react-native", - "id": "react-native", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Remix with Nx", - "path": "/recipes/react/remix", - "id": "remix", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Use Environment Variables in React", - "path": "/recipes/react/use-environment-variables-in-react", - "id": "use-environment-variables-in-react", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Using Tailwind CSS in React", - "path": "/recipes/react/using-tailwind-css-in-react", - "id": "using-tailwind-css-in-react", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Adding Images, Fonts, and Files", - "path": "/recipes/react/adding-assets-react", - "id": "adding-assets-react", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Setup Module Federation with SSR for React", - "path": "/recipes/react/module-federation-with-ssr", - "id": "module-federation-with-ssr", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Deploying Next.js applications to Vercel", - "path": "/recipes/react/deploy-nextjs-to-vercel", - "id": "deploy-nextjs-to-vercel", - "isExternal": false, - "children": [], - "disableCollapsible": false - } - ], - "disableCollapsible": false - }, { "name": "Node", "path": "/recipes/node", @@ -2000,217 +2000,217 @@ "disableCollapsible": false }, { - "name": "Nx Console", - "path": "/recipes/nx-console", - "id": "nx-console", + "name": "Tips and tricks", + "path": "/recipes/tips-n-tricks", + "id": "tips-n-tricks", "isExternal": false, "children": [ { - "name": "Telemetry", - "path": "/recipes/nx-console/console-telemetry", - "id": "console-telemetry", + "name": "Configuring ESLint with Typescript", + "path": "/recipes/tips-n-tricks/eslint", + "id": "eslint", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Generate Command", - "path": "/recipes/nx-console/console-generate-command", - "id": "console-generate-command", + "name": "Define Environment Variables", + "path": "/recipes/tips-n-tricks/define-environment-variables", + "id": "define-environment-variables", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Run Command", - "path": "/recipes/nx-console/console-run-command", - "id": "console-run-command", + "name": "Configuring Browser Support", + "path": "/recipes/tips-n-tricks/browser-support", + "id": "browser-support", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Add Dependency Command", - "path": "/recipes/nx-console/console-add-dependency-command", - "id": "console-add-dependency-command", + "name": "Include Assets in Build", + "path": "/recipes/tips-n-tricks/include-assets-in-build", + "id": "include-assets-in-build", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Project Pane", - "path": "/recipes/nx-console/console-project-pane", - "id": "console-project-pane", + "name": "Include All package.json Files as Projects", + "path": "/recipes/tips-n-tricks/include-all-packagejson", + "id": "include-all-packagejson", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Keyboard Shortcuts", - "path": "/recipes/nx-console/console-shortcuts", - "id": "console-shortcuts", + "name": "Identify Dependencies Between Folders", + "path": "/recipes/tips-n-tricks/identify-dependencies-between-folders", + "id": "identify-dependencies-between-folders", "isExternal": false, "children": [], "disableCollapsible": false - } - ], - "disableCollapsible": false - }, - { - "name": "Troubleshooting", - "path": "/recipes/troubleshooting", - "id": "troubleshooting", - "isExternal": false, - "children": [ + }, { - "name": "Resolve Circular Dependencies", - "path": "/recipes/troubleshooting/resolve-circular-dependencies", - "id": "resolve-circular-dependencies", + "name": "Run Root-Level NPM Scripts with Nx", + "path": "/recipes/tips-n-tricks/root-level-scripts", + "id": "root-level-scripts", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Troubleshooting Nx Install Issues", - "path": "/recipes/troubleshooting/troubleshoot-nx-install-issues", - "id": "troubleshoot-nx-install-issues", + "name": "Disable Graph Links Created from Analyzing Source Files", + "path": "/recipes/tips-n-tricks/analyze-source-files", + "id": "analyze-source-files", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Troubleshoot Cache Misses", - "path": "/recipes/troubleshooting/troubleshoot-cache-misses", - "id": "troubleshoot-cache-misses", + "name": "Workspace Watching", + "path": "/recipes/tips-n-tricks/workspace-watching", + "id": "workspace-watching", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Unknown Local Cache Error", - "path": "/recipes/troubleshooting/unknown-local-cache", - "id": "unknown-local-cache", + "name": "Convert from a Standalone Repository to an Integrated Repository", + "path": "/recipes/tips-n-tricks/standalone-to-integrated", + "id": "standalone-to-integrated", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Profiling Build Performance", - "path": "/recipes/troubleshooting/performance-profiling", - "id": "performance-profiling", + "name": "Use JavaScript instead TypeScript", + "path": "/recipes/tips-n-tricks/js-and-ts", + "id": "js-and-ts", "isExternal": false, "children": [], "disableCollapsible": false - } - ], - "disableCollapsible": false - }, - { - "name": "Tips and tricks", - "path": "/recipes/tips-n-tricks", - "id": "tips-n-tricks", - "isExternal": false, - "children": [ + }, { - "name": "Configuring ESLint with Typescript", - "path": "/recipes/tips-n-tricks/eslint", - "id": "eslint", + "name": "Altering Migration Process", + "path": "/recipes/tips-n-tricks/advanced-update", + "id": "advanced-update", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Define Environment Variables", - "path": "/recipes/tips-n-tricks/define-environment-variables", - "id": "define-environment-variables", + "name": "Running Custom Commands", + "path": "/recipes/tips-n-tricks/run-commands-executor", + "id": "run-commands-executor", "isExternal": false, "children": [], "disableCollapsible": false - }, + } + ], + "disableCollapsible": false + }, + { + "name": "Troubleshooting", + "path": "/recipes/troubleshooting", + "id": "troubleshooting", + "isExternal": false, + "children": [ { - "name": "Configuring Browser Support", - "path": "/recipes/tips-n-tricks/browser-support", - "id": "browser-support", + "name": "Resolve Circular Dependencies", + "path": "/recipes/troubleshooting/resolve-circular-dependencies", + "id": "resolve-circular-dependencies", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Include Assets in Build", - "path": "/recipes/tips-n-tricks/include-assets-in-build", - "id": "include-assets-in-build", + "name": "Troubleshooting Nx Install Issues", + "path": "/recipes/troubleshooting/troubleshoot-nx-install-issues", + "id": "troubleshoot-nx-install-issues", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Include All package.json Files as Projects", - "path": "/recipes/tips-n-tricks/include-all-packagejson", - "id": "include-all-packagejson", + "name": "Troubleshoot Cache Misses", + "path": "/recipes/troubleshooting/troubleshoot-cache-misses", + "id": "troubleshoot-cache-misses", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Identify Dependencies Between Folders", - "path": "/recipes/tips-n-tricks/identify-dependencies-between-folders", - "id": "identify-dependencies-between-folders", + "name": "Unknown Local Cache Error", + "path": "/recipes/troubleshooting/unknown-local-cache", + "id": "unknown-local-cache", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Run Root-Level NPM Scripts with Nx", - "path": "/recipes/tips-n-tricks/root-level-scripts", - "id": "root-level-scripts", + "name": "Profiling Build Performance", + "path": "/recipes/troubleshooting/performance-profiling", + "id": "performance-profiling", "isExternal": false, "children": [], "disableCollapsible": false - }, + } + ], + "disableCollapsible": false + }, + { + "name": "Nx Console", + "path": "/recipes/nx-console", + "id": "nx-console", + "isExternal": false, + "children": [ { - "name": "Disable Graph Links Created from Analyzing Source Files", - "path": "/recipes/tips-n-tricks/analyze-source-files", - "id": "analyze-source-files", + "name": "Telemetry", + "path": "/recipes/nx-console/console-telemetry", + "id": "console-telemetry", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Workspace Watching", - "path": "/recipes/tips-n-tricks/workspace-watching", - "id": "workspace-watching", + "name": "Generate Command", + "path": "/recipes/nx-console/console-generate-command", + "id": "console-generate-command", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Convert from a Standalone Repository to an Integrated Repository", - "path": "/recipes/tips-n-tricks/standalone-to-integrated", - "id": "standalone-to-integrated", + "name": "Run Command", + "path": "/recipes/nx-console/console-run-command", + "id": "console-run-command", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Use JavaScript instead TypeScript", - "path": "/recipes/tips-n-tricks/js-and-ts", - "id": "js-and-ts", + "name": "Add Dependency Command", + "path": "/recipes/nx-console/console-add-dependency-command", + "id": "console-add-dependency-command", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Altering Migration Process", - "path": "/recipes/tips-n-tricks/advanced-update", - "id": "advanced-update", + "name": "Project Pane", + "path": "/recipes/nx-console/console-project-pane", + "id": "console-project-pane", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Running Custom Commands", - "path": "/recipes/tips-n-tricks/run-commands-executor", - "id": "run-commands-executor", + "name": "Keyboard Shortcuts", + "path": "/recipes/nx-console/console-shortcuts", + "id": "console-shortcuts", "isExternal": false, "children": [], "disableCollapsible": false @@ -2343,6 +2343,159 @@ "children": [], "disableCollapsible": false }, + { + "name": "React", + "path": "/recipes/react", + "id": "react", + "isExternal": false, + "children": [ + { + "name": "Migrating from CRA", + "path": "/recipes/react/migration-cra", + "id": "migration-cra", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "React 18 Migration", + "path": "/recipes/react/react-18", + "id": "react-18", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "React Native with Nx", + "path": "/recipes/react/react-native", + "id": "react-native", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Remix with Nx", + "path": "/recipes/react/remix", + "id": "remix", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Use Environment Variables in React", + "path": "/recipes/react/use-environment-variables-in-react", + "id": "use-environment-variables-in-react", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Using Tailwind CSS in React", + "path": "/recipes/react/using-tailwind-css-in-react", + "id": "using-tailwind-css-in-react", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Adding Images, Fonts, and Files", + "path": "/recipes/react/adding-assets-react", + "id": "adding-assets-react", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Setup Module Federation with SSR for React", + "path": "/recipes/react/module-federation-with-ssr", + "id": "module-federation-with-ssr", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Deploying Next.js applications to Vercel", + "path": "/recipes/react/deploy-nextjs-to-vercel", + "id": "deploy-nextjs-to-vercel", + "isExternal": false, + "children": [], + "disableCollapsible": false + } + ], + "disableCollapsible": false + }, + { + "name": "Migrating from CRA", + "path": "/recipes/react/migration-cra", + "id": "migration-cra", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "React 18 Migration", + "path": "/recipes/react/react-18", + "id": "react-18", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "React Native with Nx", + "path": "/recipes/react/react-native", + "id": "react-native", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Remix with Nx", + "path": "/recipes/react/remix", + "id": "remix", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Use Environment Variables in React", + "path": "/recipes/react/use-environment-variables-in-react", + "id": "use-environment-variables-in-react", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Using Tailwind CSS in React", + "path": "/recipes/react/using-tailwind-css-in-react", + "id": "using-tailwind-css-in-react", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Adding Images, Fonts, and Files", + "path": "/recipes/react/adding-assets-react", + "id": "adding-assets-react", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Setup Module Federation with SSR for React", + "path": "/recipes/react/module-federation-with-ssr", + "id": "module-federation-with-ssr", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Deploying Next.js applications to Vercel", + "path": "/recipes/react/deploy-nextjs-to-vercel", + "id": "deploy-nextjs-to-vercel", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, { "name": "Angular", "path": "/recipes/angular", @@ -2546,159 +2699,6 @@ "children": [], "disableCollapsible": false }, - { - "name": "React", - "path": "/recipes/react", - "id": "react", - "isExternal": false, - "children": [ - { - "name": "Migrating from CRA", - "path": "/recipes/react/migration-cra", - "id": "migration-cra", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "React 18 Migration", - "path": "/recipes/react/react-18", - "id": "react-18", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "React Native with Nx", - "path": "/recipes/react/react-native", - "id": "react-native", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Remix with Nx", - "path": "/recipes/react/remix", - "id": "remix", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Use Environment Variables in React", - "path": "/recipes/react/use-environment-variables-in-react", - "id": "use-environment-variables-in-react", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Using Tailwind CSS in React", - "path": "/recipes/react/using-tailwind-css-in-react", - "id": "using-tailwind-css-in-react", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Adding Images, Fonts, and Files", - "path": "/recipes/react/adding-assets-react", - "id": "adding-assets-react", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Setup Module Federation with SSR for React", - "path": "/recipes/react/module-federation-with-ssr", - "id": "module-federation-with-ssr", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Deploying Next.js applications to Vercel", - "path": "/recipes/react/deploy-nextjs-to-vercel", - "id": "deploy-nextjs-to-vercel", - "isExternal": false, - "children": [], - "disableCollapsible": false - } - ], - "disableCollapsible": false - }, - { - "name": "Migrating from CRA", - "path": "/recipes/react/migration-cra", - "id": "migration-cra", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "React 18 Migration", - "path": "/recipes/react/react-18", - "id": "react-18", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "React Native with Nx", - "path": "/recipes/react/react-native", - "id": "react-native", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Remix with Nx", - "path": "/recipes/react/remix", - "id": "remix", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Use Environment Variables in React", - "path": "/recipes/react/use-environment-variables-in-react", - "id": "use-environment-variables-in-react", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Using Tailwind CSS in React", - "path": "/recipes/react/using-tailwind-css-in-react", - "id": "using-tailwind-css-in-react", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Adding Images, Fonts, and Files", - "path": "/recipes/react/adding-assets-react", - "id": "adding-assets-react", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Setup Module Federation with SSR for React", - "path": "/recipes/react/module-federation-with-ssr", - "id": "module-federation-with-ssr", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Deploying Next.js applications to Vercel", - "path": "/recipes/react/deploy-nextjs-to-vercel", - "id": "deploy-nextjs-to-vercel", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, { "name": "Node", "path": "/recipes/node", @@ -3024,55 +3024,111 @@ "disableCollapsible": false }, { - "name": "Nx Console", - "path": "/recipes/nx-console", - "id": "nx-console", + "name": "Tips and tricks", + "path": "/recipes/tips-n-tricks", + "id": "tips-n-tricks", "isExternal": false, "children": [ { - "name": "Telemetry", - "path": "/recipes/nx-console/console-telemetry", - "id": "console-telemetry", + "name": "Configuring ESLint with Typescript", + "path": "/recipes/tips-n-tricks/eslint", + "id": "eslint", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Generate Command", - "path": "/recipes/nx-console/console-generate-command", - "id": "console-generate-command", + "name": "Define Environment Variables", + "path": "/recipes/tips-n-tricks/define-environment-variables", + "id": "define-environment-variables", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Run Command", - "path": "/recipes/nx-console/console-run-command", - "id": "console-run-command", + "name": "Configuring Browser Support", + "path": "/recipes/tips-n-tricks/browser-support", + "id": "browser-support", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Add Dependency Command", - "path": "/recipes/nx-console/console-add-dependency-command", - "id": "console-add-dependency-command", + "name": "Include Assets in Build", + "path": "/recipes/tips-n-tricks/include-assets-in-build", + "id": "include-assets-in-build", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Project Pane", - "path": "/recipes/nx-console/console-project-pane", - "id": "console-project-pane", + "name": "Include All package.json Files as Projects", + "path": "/recipes/tips-n-tricks/include-all-packagejson", + "id": "include-all-packagejson", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Keyboard Shortcuts", - "path": "/recipes/nx-console/console-shortcuts", - "id": "console-shortcuts", + "name": "Identify Dependencies Between Folders", + "path": "/recipes/tips-n-tricks/identify-dependencies-between-folders", + "id": "identify-dependencies-between-folders", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Run Root-Level NPM Scripts with Nx", + "path": "/recipes/tips-n-tricks/root-level-scripts", + "id": "root-level-scripts", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Disable Graph Links Created from Analyzing Source Files", + "path": "/recipes/tips-n-tricks/analyze-source-files", + "id": "analyze-source-files", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Workspace Watching", + "path": "/recipes/tips-n-tricks/workspace-watching", + "id": "workspace-watching", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Convert from a Standalone Repository to an Integrated Repository", + "path": "/recipes/tips-n-tricks/standalone-to-integrated", + "id": "standalone-to-integrated", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Use JavaScript instead TypeScript", + "path": "/recipes/tips-n-tricks/js-and-ts", + "id": "js-and-ts", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Altering Migration Process", + "path": "/recipes/tips-n-tricks/advanced-update", + "id": "advanced-update", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Running Custom Commands", + "path": "/recipes/tips-n-tricks/run-commands-executor", + "id": "run-commands-executor", "isExternal": false, "children": [], "disableCollapsible": false @@ -3081,49 +3137,105 @@ "disableCollapsible": false }, { - "name": "Telemetry", - "path": "/recipes/nx-console/console-telemetry", - "id": "console-telemetry", + "name": "Configuring ESLint with Typescript", + "path": "/recipes/tips-n-tricks/eslint", + "id": "eslint", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Generate Command", - "path": "/recipes/nx-console/console-generate-command", - "id": "console-generate-command", + "name": "Define Environment Variables", + "path": "/recipes/tips-n-tricks/define-environment-variables", + "id": "define-environment-variables", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Run Command", - "path": "/recipes/nx-console/console-run-command", - "id": "console-run-command", + "name": "Configuring Browser Support", + "path": "/recipes/tips-n-tricks/browser-support", + "id": "browser-support", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Add Dependency Command", - "path": "/recipes/nx-console/console-add-dependency-command", - "id": "console-add-dependency-command", + "name": "Include Assets in Build", + "path": "/recipes/tips-n-tricks/include-assets-in-build", + "id": "include-assets-in-build", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Project Pane", - "path": "/recipes/nx-console/console-project-pane", - "id": "console-project-pane", + "name": "Include All package.json Files as Projects", + "path": "/recipes/tips-n-tricks/include-all-packagejson", + "id": "include-all-packagejson", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Keyboard Shortcuts", - "path": "/recipes/nx-console/console-shortcuts", - "id": "console-shortcuts", + "name": "Identify Dependencies Between Folders", + "path": "/recipes/tips-n-tricks/identify-dependencies-between-folders", + "id": "identify-dependencies-between-folders", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Run Root-Level NPM Scripts with Nx", + "path": "/recipes/tips-n-tricks/root-level-scripts", + "id": "root-level-scripts", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Disable Graph Links Created from Analyzing Source Files", + "path": "/recipes/tips-n-tricks/analyze-source-files", + "id": "analyze-source-files", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Workspace Watching", + "path": "/recipes/tips-n-tricks/workspace-watching", + "id": "workspace-watching", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Convert from a Standalone Repository to an Integrated Repository", + "path": "/recipes/tips-n-tricks/standalone-to-integrated", + "id": "standalone-to-integrated", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Use JavaScript instead TypeScript", + "path": "/recipes/tips-n-tricks/js-and-ts", + "id": "js-and-ts", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Altering Migration Process", + "path": "/recipes/tips-n-tricks/advanced-update", + "id": "advanced-update", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, + { + "name": "Running Custom Commands", + "path": "/recipes/tips-n-tricks/run-commands-executor", + "id": "run-commands-executor", "isExternal": false, "children": [], "disableCollapsible": false @@ -3218,111 +3330,55 @@ "disableCollapsible": false }, { - "name": "Tips and tricks", - "path": "/recipes/tips-n-tricks", - "id": "tips-n-tricks", + "name": "Nx Console", + "path": "/recipes/nx-console", + "id": "nx-console", "isExternal": false, "children": [ { - "name": "Configuring ESLint with Typescript", - "path": "/recipes/tips-n-tricks/eslint", - "id": "eslint", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Define Environment Variables", - "path": "/recipes/tips-n-tricks/define-environment-variables", - "id": "define-environment-variables", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Configuring Browser Support", - "path": "/recipes/tips-n-tricks/browser-support", - "id": "browser-support", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Include Assets in Build", - "path": "/recipes/tips-n-tricks/include-assets-in-build", - "id": "include-assets-in-build", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Include All package.json Files as Projects", - "path": "/recipes/tips-n-tricks/include-all-packagejson", - "id": "include-all-packagejson", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Identify Dependencies Between Folders", - "path": "/recipes/tips-n-tricks/identify-dependencies-between-folders", - "id": "identify-dependencies-between-folders", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Run Root-Level NPM Scripts with Nx", - "path": "/recipes/tips-n-tricks/root-level-scripts", - "id": "root-level-scripts", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Disable Graph Links Created from Analyzing Source Files", - "path": "/recipes/tips-n-tricks/analyze-source-files", - "id": "analyze-source-files", + "name": "Telemetry", + "path": "/recipes/nx-console/console-telemetry", + "id": "console-telemetry", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Workspace Watching", - "path": "/recipes/tips-n-tricks/workspace-watching", - "id": "workspace-watching", + "name": "Generate Command", + "path": "/recipes/nx-console/console-generate-command", + "id": "console-generate-command", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Convert from a Standalone Repository to an Integrated Repository", - "path": "/recipes/tips-n-tricks/standalone-to-integrated", - "id": "standalone-to-integrated", + "name": "Run Command", + "path": "/recipes/nx-console/console-run-command", + "id": "console-run-command", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Use JavaScript instead TypeScript", - "path": "/recipes/tips-n-tricks/js-and-ts", - "id": "js-and-ts", + "name": "Add Dependency Command", + "path": "/recipes/nx-console/console-add-dependency-command", + "id": "console-add-dependency-command", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Altering Migration Process", - "path": "/recipes/tips-n-tricks/advanced-update", - "id": "advanced-update", + "name": "Project Pane", + "path": "/recipes/nx-console/console-project-pane", + "id": "console-project-pane", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Running Custom Commands", - "path": "/recipes/tips-n-tricks/run-commands-executor", - "id": "run-commands-executor", + "name": "Keyboard Shortcuts", + "path": "/recipes/nx-console/console-shortcuts", + "id": "console-shortcuts", "isExternal": false, "children": [], "disableCollapsible": false @@ -3331,105 +3387,49 @@ "disableCollapsible": false }, { - "name": "Configuring ESLint with Typescript", - "path": "/recipes/tips-n-tricks/eslint", - "id": "eslint", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Define Environment Variables", - "path": "/recipes/tips-n-tricks/define-environment-variables", - "id": "define-environment-variables", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Configuring Browser Support", - "path": "/recipes/tips-n-tricks/browser-support", - "id": "browser-support", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Include Assets in Build", - "path": "/recipes/tips-n-tricks/include-assets-in-build", - "id": "include-assets-in-build", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Include All package.json Files as Projects", - "path": "/recipes/tips-n-tricks/include-all-packagejson", - "id": "include-all-packagejson", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Identify Dependencies Between Folders", - "path": "/recipes/tips-n-tricks/identify-dependencies-between-folders", - "id": "identify-dependencies-between-folders", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Run Root-Level NPM Scripts with Nx", - "path": "/recipes/tips-n-tricks/root-level-scripts", - "id": "root-level-scripts", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "Disable Graph Links Created from Analyzing Source Files", - "path": "/recipes/tips-n-tricks/analyze-source-files", - "id": "analyze-source-files", + "name": "Telemetry", + "path": "/recipes/nx-console/console-telemetry", + "id": "console-telemetry", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Workspace Watching", - "path": "/recipes/tips-n-tricks/workspace-watching", - "id": "workspace-watching", + "name": "Generate Command", + "path": "/recipes/nx-console/console-generate-command", + "id": "console-generate-command", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Convert from a Standalone Repository to an Integrated Repository", - "path": "/recipes/tips-n-tricks/standalone-to-integrated", - "id": "standalone-to-integrated", + "name": "Run Command", + "path": "/recipes/nx-console/console-run-command", + "id": "console-run-command", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Use JavaScript instead TypeScript", - "path": "/recipes/tips-n-tricks/js-and-ts", - "id": "js-and-ts", + "name": "Add Dependency Command", + "path": "/recipes/nx-console/console-add-dependency-command", + "id": "console-add-dependency-command", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Altering Migration Process", - "path": "/recipes/tips-n-tricks/advanced-update", - "id": "advanced-update", + "name": "Project Pane", + "path": "/recipes/nx-console/console-project-pane", + "id": "console-project-pane", "isExternal": false, "children": [], "disableCollapsible": false }, { - "name": "Running Custom Commands", - "path": "/recipes/tips-n-tricks/run-commands-executor", - "id": "run-commands-executor", + "name": "Keyboard Shortcuts", + "path": "/recipes/nx-console/console-shortcuts", + "id": "console-shortcuts", "isExternal": false, "children": [], "disableCollapsible": false diff --git a/docs/generated/manifests/nx.json b/docs/generated/manifests/nx.json index 69bc1176235c6..9aee0086cf4d9 100644 --- a/docs/generated/manifests/nx.json +++ b/docs/generated/manifests/nx.json @@ -2051,6 +2051,107 @@ "path": "/recipes/adopting-nx", "tags": [] }, + { + "id": "react", + "name": "React", + "description": "Advanced guides to adopt Nx in React.", + "file": "", + "itemList": [ + { + "id": "migration-cra", + "name": "Migrating from CRA", + "description": "", + "file": "shared/migration/migration-cra", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/migration-cra", + "tags": [] + }, + { + "id": "react-18", + "name": "React 18 Migration", + "description": "", + "file": "shared/guides/react-18", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/react-18", + "tags": [] + }, + { + "id": "react-native", + "name": "React Native with Nx", + "description": "", + "file": "shared/guides/react-native", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/react-native", + "tags": [] + }, + { + "id": "remix", + "name": "Remix with Nx", + "description": "", + "file": "shared/guides/remix", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/remix", + "tags": [] + }, + { + "id": "use-environment-variables-in-react", + "name": "Use Environment Variables in React", + "description": "", + "file": "shared/guides/use-environment-variables-in-react", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/use-environment-variables-in-react", + "tags": ["environment-variables"] + }, + { + "id": "using-tailwind-css-in-react", + "name": "Using Tailwind CSS in React", + "description": "", + "file": "shared/guides/using-tailwind-css-in-react", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/using-tailwind-css-in-react", + "tags": [] + }, + { + "id": "adding-assets-react", + "name": "Adding Images, Fonts, and Files", + "description": "", + "file": "shared/guides/adding-assets", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/adding-assets-react", + "tags": [] + }, + { + "id": "module-federation-with-ssr", + "name": "Setup Module Federation with SSR for React", + "description": "", + "file": "shared/recipes/module-federation-with-ssr", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/module-federation-with-ssr", + "tags": ["use-task-executors", "module-federation", "react"] + }, + { + "id": "deploy-nextjs-to-vercel", + "name": "Deploying Next.js applications to Vercel", + "description": "", + "file": "shared/recipes/deployment/deploy-nextjs-to-vercel", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/deploy-nextjs-to-vercel", + "tags": [] + } + ], + "isExternal": false, + "path": "/recipes/react", + "tags": [] + }, { "id": "angular", "name": "Angular", @@ -2163,107 +2264,6 @@ "path": "/recipes/angular", "tags": [] }, - { - "id": "react", - "name": "React", - "description": "Advanced guides to adopt Nx in React.", - "file": "", - "itemList": [ - { - "id": "migration-cra", - "name": "Migrating from CRA", - "description": "", - "file": "shared/migration/migration-cra", - "itemList": [], - "isExternal": false, - "path": "/recipes/react/migration-cra", - "tags": [] - }, - { - "id": "react-18", - "name": "React 18 Migration", - "description": "", - "file": "shared/guides/react-18", - "itemList": [], - "isExternal": false, - "path": "/recipes/react/react-18", - "tags": [] - }, - { - "id": "react-native", - "name": "React Native with Nx", - "description": "", - "file": "shared/guides/react-native", - "itemList": [], - "isExternal": false, - "path": "/recipes/react/react-native", - "tags": [] - }, - { - "id": "remix", - "name": "Remix with Nx", - "description": "", - "file": "shared/guides/remix", - "itemList": [], - "isExternal": false, - "path": "/recipes/react/remix", - "tags": [] - }, - { - "id": "use-environment-variables-in-react", - "name": "Use Environment Variables in React", - "description": "", - "file": "shared/guides/use-environment-variables-in-react", - "itemList": [], - "isExternal": false, - "path": "/recipes/react/use-environment-variables-in-react", - "tags": ["environment-variables"] - }, - { - "id": "using-tailwind-css-in-react", - "name": "Using Tailwind CSS in React", - "description": "", - "file": "shared/guides/using-tailwind-css-in-react", - "itemList": [], - "isExternal": false, - "path": "/recipes/react/using-tailwind-css-in-react", - "tags": [] - }, - { - "id": "adding-assets-react", - "name": "Adding Images, Fonts, and Files", - "description": "", - "file": "shared/guides/adding-assets", - "itemList": [], - "isExternal": false, - "path": "/recipes/react/adding-assets-react", - "tags": [] - }, - { - "id": "module-federation-with-ssr", - "name": "Setup Module Federation with SSR for React", - "description": "", - "file": "shared/recipes/module-federation-with-ssr", - "itemList": [], - "isExternal": false, - "path": "/recipes/react/module-federation-with-ssr", - "tags": ["use-task-executors", "module-federation", "react"] - }, - { - "id": "deploy-nextjs-to-vercel", - "name": "Deploying Next.js applications to Vercel", - "description": "", - "file": "shared/recipes/deployment/deploy-nextjs-to-vercel", - "itemList": [], - "isExternal": false, - "path": "/recipes/react/deploy-nextjs-to-vercel", - "tags": [] - } - ], - "isExternal": false, - "path": "/recipes/react", - "tags": [] - }, { "id": "node", "name": "Node", @@ -2489,74 +2489,144 @@ "tags": [] }, { - "id": "nx-console", - "name": "Nx Console", - "description": "Checkout all the recipes related to Nx Console.", + "id": "tips-n-tricks", + "name": "Tips and tricks", + "description": "Various tips and tricks for using Nx.", "file": "", "itemList": [ { - "id": "console-telemetry", - "name": "Telemetry", + "id": "eslint", + "name": "Configuring ESLint with Typescript", "description": "", - "file": "shared/recipes/console-telemetry", + "file": "shared/eslint", "itemList": [], "isExternal": false, - "path": "/recipes/nx-console/console-telemetry", - "tags": ["integrate-with-editors"] + "path": "/recipes/tips-n-tricks/eslint", + "tags": [] }, { - "id": "console-generate-command", - "name": "Generate Command", + "id": "define-environment-variables", + "name": "Define Environment Variables", "description": "", - "file": "shared/recipes/console-generate-command", + "file": "shared/guides/define-environment-variables", "itemList": [], "isExternal": false, - "path": "/recipes/nx-console/console-generate-command", - "tags": ["integrate-with-editors"] + "path": "/recipes/tips-n-tricks/define-environment-variables", + "tags": ["environment-variables"] }, { - "id": "console-run-command", - "name": "Run Command", + "id": "browser-support", + "name": "Configuring Browser Support", "description": "", - "file": "shared/recipes/console-run-command", + "file": "shared/guides/browser-support", "itemList": [], "isExternal": false, - "path": "/recipes/nx-console/console-run-command", - "tags": ["integrate-with-editors"] + "path": "/recipes/tips-n-tricks/browser-support", + "tags": [] }, { - "id": "console-add-dependency-command", - "name": "Add Dependency Command", + "id": "include-assets-in-build", + "name": "Include Assets in Build", "description": "", - "file": "shared/recipes/console-add-dependency-command", + "file": "shared/recipes/include-assets-in-build", "itemList": [], "isExternal": false, - "path": "/recipes/nx-console/console-add-dependency-command", - "tags": ["integrate-with-editors"] + "path": "/recipes/tips-n-tricks/include-assets-in-build", + "tags": [] }, { - "id": "console-project-pane", - "name": "Project Pane", + "id": "include-all-packagejson", + "name": "Include All package.json Files as Projects", "description": "", - "file": "shared/recipes/console-project-pane", + "file": "shared/recipes/include-all-packagejson", "itemList": [], "isExternal": false, - "path": "/recipes/nx-console/console-project-pane", - "tags": ["integrate-with-editors"] + "path": "/recipes/tips-n-tricks/include-all-packagejson", + "tags": [] }, { - "id": "console-shortcuts", - "name": "Keyboard Shortcuts", + "id": "identify-dependencies-between-folders", + "name": "Identify Dependencies Between Folders", "description": "", - "file": "shared/recipes/console-shortcuts", + "file": "shared/recipes/identify-dependencies-between-folders", "itemList": [], "isExternal": false, - "path": "/recipes/nx-console/console-shortcuts", - "tags": ["integrate-with-editors"] + "path": "/recipes/tips-n-tricks/identify-dependencies-between-folders", + "tags": [] + }, + { + "id": "root-level-scripts", + "name": "Run Root-Level NPM Scripts with Nx", + "description": "", + "file": "shared/recipes/root-level-scripts", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/root-level-scripts", + "tags": ["run-tasks"] + }, + { + "id": "analyze-source-files", + "name": "Disable Graph Links Created from Analyzing Source Files", + "description": "", + "file": "shared/recipes/analyze-source-files", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/analyze-source-files", + "tags": ["explore-graph"] + }, + { + "id": "workspace-watching", + "name": "Workspace Watching", + "description": "", + "file": "shared/recipes/workspace-watching", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/workspace-watching", + "tags": ["workspace-watching"] + }, + { + "id": "standalone-to-integrated", + "name": "Convert from a Standalone Repository to an Integrated Repository", + "description": "", + "file": "shared/recipes/repo-types/standalone-to-integrated", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/standalone-to-integrated", + "tags": ["repository-types"] + }, + { + "id": "js-and-ts", + "name": "Use JavaScript instead TypeScript", + "description": "", + "file": "shared/guides/js-and-ts", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/js-and-ts", + "tags": [] + }, + { + "id": "advanced-update", + "name": "Altering Migration Process", + "description": "", + "file": "shared/recipes/advanced-update", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/advanced-update", + "tags": ["automate-updating-dependencies"] + }, + { + "id": "run-commands-executor", + "name": "Running Custom Commands", + "description": "", + "file": "shared/running-custom-commands", + "itemList": [], + "isExternal": false, + "path": "/recipes/tips-n-tricks/run-commands-executor", + "tags": ["use-task-executors"] } ], "isExternal": false, - "path": "/recipes/nx-console", + "path": "/recipes/tips-n-tricks", "tags": [] }, { @@ -2621,144 +2691,74 @@ "tags": [] }, { - "id": "tips-n-tricks", - "name": "Tips and tricks", - "description": "Various tips and tricks for using Nx.", + "id": "nx-console", + "name": "Nx Console", + "description": "Checkout all the recipes related to Nx Console.", "file": "", "itemList": [ { - "id": "eslint", - "name": "Configuring ESLint with Typescript", - "description": "", - "file": "shared/eslint", - "itemList": [], - "isExternal": false, - "path": "/recipes/tips-n-tricks/eslint", - "tags": [] - }, - { - "id": "define-environment-variables", - "name": "Define Environment Variables", - "description": "", - "file": "shared/guides/define-environment-variables", - "itemList": [], - "isExternal": false, - "path": "/recipes/tips-n-tricks/define-environment-variables", - "tags": ["environment-variables"] - }, - { - "id": "browser-support", - "name": "Configuring Browser Support", - "description": "", - "file": "shared/guides/browser-support", - "itemList": [], - "isExternal": false, - "path": "/recipes/tips-n-tricks/browser-support", - "tags": [] - }, - { - "id": "include-assets-in-build", - "name": "Include Assets in Build", - "description": "", - "file": "shared/recipes/include-assets-in-build", - "itemList": [], - "isExternal": false, - "path": "/recipes/tips-n-tricks/include-assets-in-build", - "tags": [] - }, - { - "id": "include-all-packagejson", - "name": "Include All package.json Files as Projects", - "description": "", - "file": "shared/recipes/include-all-packagejson", - "itemList": [], - "isExternal": false, - "path": "/recipes/tips-n-tricks/include-all-packagejson", - "tags": [] - }, - { - "id": "identify-dependencies-between-folders", - "name": "Identify Dependencies Between Folders", - "description": "", - "file": "shared/recipes/identify-dependencies-between-folders", - "itemList": [], - "isExternal": false, - "path": "/recipes/tips-n-tricks/identify-dependencies-between-folders", - "tags": [] - }, - { - "id": "root-level-scripts", - "name": "Run Root-Level NPM Scripts with Nx", - "description": "", - "file": "shared/recipes/root-level-scripts", - "itemList": [], - "isExternal": false, - "path": "/recipes/tips-n-tricks/root-level-scripts", - "tags": ["run-tasks"] - }, - { - "id": "analyze-source-files", - "name": "Disable Graph Links Created from Analyzing Source Files", + "id": "console-telemetry", + "name": "Telemetry", "description": "", - "file": "shared/recipes/analyze-source-files", + "file": "shared/recipes/console-telemetry", "itemList": [], "isExternal": false, - "path": "/recipes/tips-n-tricks/analyze-source-files", - "tags": ["explore-graph"] + "path": "/recipes/nx-console/console-telemetry", + "tags": ["integrate-with-editors"] }, { - "id": "workspace-watching", - "name": "Workspace Watching", + "id": "console-generate-command", + "name": "Generate Command", "description": "", - "file": "shared/recipes/workspace-watching", + "file": "shared/recipes/console-generate-command", "itemList": [], "isExternal": false, - "path": "/recipes/tips-n-tricks/workspace-watching", - "tags": ["workspace-watching"] + "path": "/recipes/nx-console/console-generate-command", + "tags": ["integrate-with-editors"] }, { - "id": "standalone-to-integrated", - "name": "Convert from a Standalone Repository to an Integrated Repository", + "id": "console-run-command", + "name": "Run Command", "description": "", - "file": "shared/recipes/repo-types/standalone-to-integrated", + "file": "shared/recipes/console-run-command", "itemList": [], "isExternal": false, - "path": "/recipes/tips-n-tricks/standalone-to-integrated", - "tags": ["repository-types"] + "path": "/recipes/nx-console/console-run-command", + "tags": ["integrate-with-editors"] }, { - "id": "js-and-ts", - "name": "Use JavaScript instead TypeScript", + "id": "console-add-dependency-command", + "name": "Add Dependency Command", "description": "", - "file": "shared/guides/js-and-ts", + "file": "shared/recipes/console-add-dependency-command", "itemList": [], "isExternal": false, - "path": "/recipes/tips-n-tricks/js-and-ts", - "tags": [] + "path": "/recipes/nx-console/console-add-dependency-command", + "tags": ["integrate-with-editors"] }, { - "id": "advanced-update", - "name": "Altering Migration Process", + "id": "console-project-pane", + "name": "Project Pane", "description": "", - "file": "shared/recipes/advanced-update", + "file": "shared/recipes/console-project-pane", "itemList": [], "isExternal": false, - "path": "/recipes/tips-n-tricks/advanced-update", - "tags": ["automate-updating-dependencies"] + "path": "/recipes/nx-console/console-project-pane", + "tags": ["integrate-with-editors"] }, { - "id": "run-commands-executor", - "name": "Running Custom Commands", + "id": "console-shortcuts", + "name": "Keyboard Shortcuts", "description": "", - "file": "shared/running-custom-commands", + "file": "shared/recipes/console-shortcuts", "itemList": [], "isExternal": false, - "path": "/recipes/tips-n-tricks/run-commands-executor", - "tags": ["use-task-executors"] + "path": "/recipes/nx-console/console-shortcuts", + "tags": ["integrate-with-editors"] } ], "isExternal": false, - "path": "/recipes/tips-n-tricks", + "path": "/recipes/nx-console", "tags": [] }, { @@ -2918,38 +2918,229 @@ "path": "/recipes/adopting-nx/manual", "tags": [] }, - "/recipes/angular": { - "id": "angular", - "name": "Angular", - "description": "Advanced guides to adopt Nx in Angular.", + "/recipes/react": { + "id": "react", + "name": "React", + "description": "Advanced guides to adopt Nx in React.", "file": "", "itemList": [ { - "id": "migration", - "name": "Migration", + "id": "migration-cra", + "name": "Migrating from CRA", "description": "", - "file": "", - "itemList": [ - { - "id": "angular", - "name": "Migrating from Angular CLI", - "description": "", - "file": "shared/migration/migration-angular", - "itemList": [], - "isExternal": false, - "path": "/recipes/angular/migration/angular", - "tags": [] - }, - { - "id": "angular-multiple", - "name": "Migrating From Multiple Angular CLI Repos", - "description": "", - "file": "shared/migration/angular-multiple", - "itemList": [], - "isExternal": false, - "path": "/recipes/angular/migration/angular-multiple", - "tags": [] - }, + "file": "shared/migration/migration-cra", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/migration-cra", + "tags": [] + }, + { + "id": "react-18", + "name": "React 18 Migration", + "description": "", + "file": "shared/guides/react-18", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/react-18", + "tags": [] + }, + { + "id": "react-native", + "name": "React Native with Nx", + "description": "", + "file": "shared/guides/react-native", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/react-native", + "tags": [] + }, + { + "id": "remix", + "name": "Remix with Nx", + "description": "", + "file": "shared/guides/remix", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/remix", + "tags": [] + }, + { + "id": "use-environment-variables-in-react", + "name": "Use Environment Variables in React", + "description": "", + "file": "shared/guides/use-environment-variables-in-react", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/use-environment-variables-in-react", + "tags": ["environment-variables"] + }, + { + "id": "using-tailwind-css-in-react", + "name": "Using Tailwind CSS in React", + "description": "", + "file": "shared/guides/using-tailwind-css-in-react", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/using-tailwind-css-in-react", + "tags": [] + }, + { + "id": "adding-assets-react", + "name": "Adding Images, Fonts, and Files", + "description": "", + "file": "shared/guides/adding-assets", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/adding-assets-react", + "tags": [] + }, + { + "id": "module-federation-with-ssr", + "name": "Setup Module Federation with SSR for React", + "description": "", + "file": "shared/recipes/module-federation-with-ssr", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/module-federation-with-ssr", + "tags": ["use-task-executors", "module-federation", "react"] + }, + { + "id": "deploy-nextjs-to-vercel", + "name": "Deploying Next.js applications to Vercel", + "description": "", + "file": "shared/recipes/deployment/deploy-nextjs-to-vercel", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/deploy-nextjs-to-vercel", + "tags": [] + } + ], + "isExternal": false, + "path": "/recipes/react", + "tags": [] + }, + "/recipes/react/migration-cra": { + "id": "migration-cra", + "name": "Migrating from CRA", + "description": "", + "file": "shared/migration/migration-cra", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/migration-cra", + "tags": [] + }, + "/recipes/react/react-18": { + "id": "react-18", + "name": "React 18 Migration", + "description": "", + "file": "shared/guides/react-18", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/react-18", + "tags": [] + }, + "/recipes/react/react-native": { + "id": "react-native", + "name": "React Native with Nx", + "description": "", + "file": "shared/guides/react-native", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/react-native", + "tags": [] + }, + "/recipes/react/remix": { + "id": "remix", + "name": "Remix with Nx", + "description": "", + "file": "shared/guides/remix", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/remix", + "tags": [] + }, + "/recipes/react/use-environment-variables-in-react": { + "id": "use-environment-variables-in-react", + "name": "Use Environment Variables in React", + "description": "", + "file": "shared/guides/use-environment-variables-in-react", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/use-environment-variables-in-react", + "tags": ["environment-variables"] + }, + "/recipes/react/using-tailwind-css-in-react": { + "id": "using-tailwind-css-in-react", + "name": "Using Tailwind CSS in React", + "description": "", + "file": "shared/guides/using-tailwind-css-in-react", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/using-tailwind-css-in-react", + "tags": [] + }, + "/recipes/react/adding-assets-react": { + "id": "adding-assets-react", + "name": "Adding Images, Fonts, and Files", + "description": "", + "file": "shared/guides/adding-assets", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/adding-assets-react", + "tags": [] + }, + "/recipes/react/module-federation-with-ssr": { + "id": "module-federation-with-ssr", + "name": "Setup Module Federation with SSR for React", + "description": "", + "file": "shared/recipes/module-federation-with-ssr", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/module-federation-with-ssr", + "tags": ["use-task-executors", "module-federation", "react"] + }, + "/recipes/react/deploy-nextjs-to-vercel": { + "id": "deploy-nextjs-to-vercel", + "name": "Deploying Next.js applications to Vercel", + "description": "", + "file": "shared/recipes/deployment/deploy-nextjs-to-vercel", + "itemList": [], + "isExternal": false, + "path": "/recipes/react/deploy-nextjs-to-vercel", + "tags": [] + }, + "/recipes/angular": { + "id": "angular", + "name": "Angular", + "description": "Advanced guides to adopt Nx in Angular.", + "file": "", + "itemList": [ + { + "id": "migration", + "name": "Migration", + "description": "", + "file": "", + "itemList": [ + { + "id": "angular", + "name": "Migrating from Angular CLI", + "description": "", + "file": "shared/migration/migration-angular", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/migration/angular", + "tags": [] + }, + { + "id": "angular-multiple", + "name": "Migrating From Multiple Angular CLI Repos", + "description": "", + "file": "shared/migration/angular-multiple", + "itemList": [], + "isExternal": false, + "path": "/recipes/angular/migration/angular-multiple", + "tags": [] + }, { "id": "angular-manual", "name": "Migrating Angular Application manually", @@ -3158,208 +3349,17 @@ "file": "shared/guides/module-federation/dynamic-mfe-angular", "itemList": [], "isExternal": false, - "path": "/recipes/angular/dynamic-module-federation-with-angular", - "tags": ["use-task-executors", "module-federation", "angular"] - }, - "/recipes/angular/setup-incremental-builds-angular": { - "id": "setup-incremental-builds-angular", - "name": "Setup incremental builds for Angular applications", - "description": "", - "file": "shared/guides/setup-incremental-builds-angular", - "itemList": [], - "isExternal": false, - "path": "/recipes/angular/setup-incremental-builds-angular", - "tags": [] - }, - "/recipes/react": { - "id": "react", - "name": "React", - "description": "Advanced guides to adopt Nx in React.", - "file": "", - "itemList": [ - { - "id": "migration-cra", - "name": "Migrating from CRA", - "description": "", - "file": "shared/migration/migration-cra", - "itemList": [], - "isExternal": false, - "path": "/recipes/react/migration-cra", - "tags": [] - }, - { - "id": "react-18", - "name": "React 18 Migration", - "description": "", - "file": "shared/guides/react-18", - "itemList": [], - "isExternal": false, - "path": "/recipes/react/react-18", - "tags": [] - }, - { - "id": "react-native", - "name": "React Native with Nx", - "description": "", - "file": "shared/guides/react-native", - "itemList": [], - "isExternal": false, - "path": "/recipes/react/react-native", - "tags": [] - }, - { - "id": "remix", - "name": "Remix with Nx", - "description": "", - "file": "shared/guides/remix", - "itemList": [], - "isExternal": false, - "path": "/recipes/react/remix", - "tags": [] - }, - { - "id": "use-environment-variables-in-react", - "name": "Use Environment Variables in React", - "description": "", - "file": "shared/guides/use-environment-variables-in-react", - "itemList": [], - "isExternal": false, - "path": "/recipes/react/use-environment-variables-in-react", - "tags": ["environment-variables"] - }, - { - "id": "using-tailwind-css-in-react", - "name": "Using Tailwind CSS in React", - "description": "", - "file": "shared/guides/using-tailwind-css-in-react", - "itemList": [], - "isExternal": false, - "path": "/recipes/react/using-tailwind-css-in-react", - "tags": [] - }, - { - "id": "adding-assets-react", - "name": "Adding Images, Fonts, and Files", - "description": "", - "file": "shared/guides/adding-assets", - "itemList": [], - "isExternal": false, - "path": "/recipes/react/adding-assets-react", - "tags": [] - }, - { - "id": "module-federation-with-ssr", - "name": "Setup Module Federation with SSR for React", - "description": "", - "file": "shared/recipes/module-federation-with-ssr", - "itemList": [], - "isExternal": false, - "path": "/recipes/react/module-federation-with-ssr", - "tags": ["use-task-executors", "module-federation", "react"] - }, - { - "id": "deploy-nextjs-to-vercel", - "name": "Deploying Next.js applications to Vercel", - "description": "", - "file": "shared/recipes/deployment/deploy-nextjs-to-vercel", - "itemList": [], - "isExternal": false, - "path": "/recipes/react/deploy-nextjs-to-vercel", - "tags": [] - } - ], - "isExternal": false, - "path": "/recipes/react", - "tags": [] - }, - "/recipes/react/migration-cra": { - "id": "migration-cra", - "name": "Migrating from CRA", - "description": "", - "file": "shared/migration/migration-cra", - "itemList": [], - "isExternal": false, - "path": "/recipes/react/migration-cra", - "tags": [] - }, - "/recipes/react/react-18": { - "id": "react-18", - "name": "React 18 Migration", - "description": "", - "file": "shared/guides/react-18", - "itemList": [], - "isExternal": false, - "path": "/recipes/react/react-18", - "tags": [] - }, - "/recipes/react/react-native": { - "id": "react-native", - "name": "React Native with Nx", - "description": "", - "file": "shared/guides/react-native", - "itemList": [], - "isExternal": false, - "path": "/recipes/react/react-native", - "tags": [] - }, - "/recipes/react/remix": { - "id": "remix", - "name": "Remix with Nx", - "description": "", - "file": "shared/guides/remix", - "itemList": [], - "isExternal": false, - "path": "/recipes/react/remix", - "tags": [] - }, - "/recipes/react/use-environment-variables-in-react": { - "id": "use-environment-variables-in-react", - "name": "Use Environment Variables in React", - "description": "", - "file": "shared/guides/use-environment-variables-in-react", - "itemList": [], - "isExternal": false, - "path": "/recipes/react/use-environment-variables-in-react", - "tags": ["environment-variables"] - }, - "/recipes/react/using-tailwind-css-in-react": { - "id": "using-tailwind-css-in-react", - "name": "Using Tailwind CSS in React", - "description": "", - "file": "shared/guides/using-tailwind-css-in-react", - "itemList": [], - "isExternal": false, - "path": "/recipes/react/using-tailwind-css-in-react", - "tags": [] - }, - "/recipes/react/adding-assets-react": { - "id": "adding-assets-react", - "name": "Adding Images, Fonts, and Files", - "description": "", - "file": "shared/guides/adding-assets", - "itemList": [], - "isExternal": false, - "path": "/recipes/react/adding-assets-react", - "tags": [] - }, - "/recipes/react/module-federation-with-ssr": { - "id": "module-federation-with-ssr", - "name": "Setup Module Federation with SSR for React", - "description": "", - "file": "shared/recipes/module-federation-with-ssr", - "itemList": [], - "isExternal": false, - "path": "/recipes/react/module-federation-with-ssr", - "tags": ["use-task-executors", "module-federation", "react"] + "path": "/recipes/angular/dynamic-module-federation-with-angular", + "tags": ["use-task-executors", "module-federation", "angular"] }, - "/recipes/react/deploy-nextjs-to-vercel": { - "id": "deploy-nextjs-to-vercel", - "name": "Deploying Next.js applications to Vercel", + "/recipes/angular/setup-incremental-builds-angular": { + "id": "setup-incremental-builds-angular", + "name": "Setup incremental builds for Angular applications", "description": "", - "file": "shared/recipes/deployment/deploy-nextjs-to-vercel", + "file": "shared/guides/setup-incremental-builds-angular", "itemList": [], "isExternal": false, - "path": "/recipes/react/deploy-nextjs-to-vercel", + "path": "/recipes/angular/setup-incremental-builds-angular", "tags": [] }, "/recipes/node": { @@ -3753,260 +3753,18 @@ "file": "shared/monorepo-ci-gitlab", "itemList": [], "isExternal": false, - "path": "/recipes/ci/monorepo-ci-gitlab", - "tags": [] - }, - "/recipes/ci/monorepo-ci-bitbucket-pipelines": { - "id": "monorepo-ci-bitbucket-pipelines", - "name": "Setting up Bitbucket", - "description": "", - "file": "shared/monorepo-ci-bitbucket-pipelines", - "itemList": [], - "isExternal": false, - "path": "/recipes/ci/monorepo-ci-bitbucket-pipelines", - "tags": [] - }, - "/recipes/nx-console": { - "id": "nx-console", - "name": "Nx Console", - "description": "Checkout all the recipes related to Nx Console.", - "file": "", - "itemList": [ - { - "id": "console-telemetry", - "name": "Telemetry", - "description": "", - "file": "shared/recipes/console-telemetry", - "itemList": [], - "isExternal": false, - "path": "/recipes/nx-console/console-telemetry", - "tags": ["integrate-with-editors"] - }, - { - "id": "console-generate-command", - "name": "Generate Command", - "description": "", - "file": "shared/recipes/console-generate-command", - "itemList": [], - "isExternal": false, - "path": "/recipes/nx-console/console-generate-command", - "tags": ["integrate-with-editors"] - }, - { - "id": "console-run-command", - "name": "Run Command", - "description": "", - "file": "shared/recipes/console-run-command", - "itemList": [], - "isExternal": false, - "path": "/recipes/nx-console/console-run-command", - "tags": ["integrate-with-editors"] - }, - { - "id": "console-add-dependency-command", - "name": "Add Dependency Command", - "description": "", - "file": "shared/recipes/console-add-dependency-command", - "itemList": [], - "isExternal": false, - "path": "/recipes/nx-console/console-add-dependency-command", - "tags": ["integrate-with-editors"] - }, - { - "id": "console-project-pane", - "name": "Project Pane", - "description": "", - "file": "shared/recipes/console-project-pane", - "itemList": [], - "isExternal": false, - "path": "/recipes/nx-console/console-project-pane", - "tags": ["integrate-with-editors"] - }, - { - "id": "console-shortcuts", - "name": "Keyboard Shortcuts", - "description": "", - "file": "shared/recipes/console-shortcuts", - "itemList": [], - "isExternal": false, - "path": "/recipes/nx-console/console-shortcuts", - "tags": ["integrate-with-editors"] - } - ], - "isExternal": false, - "path": "/recipes/nx-console", - "tags": [] - }, - "/recipes/nx-console/console-telemetry": { - "id": "console-telemetry", - "name": "Telemetry", - "description": "", - "file": "shared/recipes/console-telemetry", - "itemList": [], - "isExternal": false, - "path": "/recipes/nx-console/console-telemetry", - "tags": ["integrate-with-editors"] - }, - "/recipes/nx-console/console-generate-command": { - "id": "console-generate-command", - "name": "Generate Command", - "description": "", - "file": "shared/recipes/console-generate-command", - "itemList": [], - "isExternal": false, - "path": "/recipes/nx-console/console-generate-command", - "tags": ["integrate-with-editors"] - }, - "/recipes/nx-console/console-run-command": { - "id": "console-run-command", - "name": "Run Command", - "description": "", - "file": "shared/recipes/console-run-command", - "itemList": [], - "isExternal": false, - "path": "/recipes/nx-console/console-run-command", - "tags": ["integrate-with-editors"] - }, - "/recipes/nx-console/console-add-dependency-command": { - "id": "console-add-dependency-command", - "name": "Add Dependency Command", - "description": "", - "file": "shared/recipes/console-add-dependency-command", - "itemList": [], - "isExternal": false, - "path": "/recipes/nx-console/console-add-dependency-command", - "tags": ["integrate-with-editors"] - }, - "/recipes/nx-console/console-project-pane": { - "id": "console-project-pane", - "name": "Project Pane", - "description": "", - "file": "shared/recipes/console-project-pane", - "itemList": [], - "isExternal": false, - "path": "/recipes/nx-console/console-project-pane", - "tags": ["integrate-with-editors"] - }, - "/recipes/nx-console/console-shortcuts": { - "id": "console-shortcuts", - "name": "Keyboard Shortcuts", - "description": "", - "file": "shared/recipes/console-shortcuts", - "itemList": [], - "isExternal": false, - "path": "/recipes/nx-console/console-shortcuts", - "tags": ["integrate-with-editors"] - }, - "/recipes/troubleshooting": { - "id": "troubleshooting", - "name": "Troubleshooting", - "description": "Learn how to troubleshoot common problems.", - "file": "", - "itemList": [ - { - "id": "resolve-circular-dependencies", - "name": "Resolve Circular Dependencies", - "description": "", - "file": "shared/recipes/resolve-circular-dependencies", - "itemList": [], - "isExternal": false, - "path": "/recipes/troubleshooting/resolve-circular-dependencies", - "tags": ["explore-graph"] - }, - { - "id": "troubleshoot-nx-install-issues", - "name": "Troubleshooting Nx Install Issues", - "description": "", - "file": "shared/installation/troubleshoot-installation", - "itemList": [], - "isExternal": false, - "path": "/recipes/troubleshooting/troubleshoot-nx-install-issues", - "tags": [] - }, - { - "id": "troubleshoot-cache-misses", - "name": "Troubleshoot Cache Misses", - "description": "", - "file": "shared/recipes/troubleshoot-cache-misses", - "itemList": [], - "isExternal": false, - "path": "/recipes/troubleshooting/troubleshoot-cache-misses", - "tags": ["cache-task-results"] - }, - { - "id": "unknown-local-cache", - "name": "Unknown Local Cache Error", - "description": "", - "file": "shared/guides/unknown-local-cache", - "itemList": [], - "isExternal": false, - "path": "/recipes/troubleshooting/unknown-local-cache", - "tags": [] - }, - { - "id": "performance-profiling", - "name": "Profiling Build Performance", - "description": "", - "file": "shared/guides/performance-profiling", - "itemList": [], - "isExternal": false, - "path": "/recipes/troubleshooting/performance-profiling", - "tags": ["use-task-executors", "environment-variables"] - } - ], - "isExternal": false, - "path": "/recipes/troubleshooting", - "tags": [] - }, - "/recipes/troubleshooting/resolve-circular-dependencies": { - "id": "resolve-circular-dependencies", - "name": "Resolve Circular Dependencies", - "description": "", - "file": "shared/recipes/resolve-circular-dependencies", - "itemList": [], - "isExternal": false, - "path": "/recipes/troubleshooting/resolve-circular-dependencies", - "tags": ["explore-graph"] - }, - "/recipes/troubleshooting/troubleshoot-nx-install-issues": { - "id": "troubleshoot-nx-install-issues", - "name": "Troubleshooting Nx Install Issues", - "description": "", - "file": "shared/installation/troubleshoot-installation", - "itemList": [], - "isExternal": false, - "path": "/recipes/troubleshooting/troubleshoot-nx-install-issues", - "tags": [] - }, - "/recipes/troubleshooting/troubleshoot-cache-misses": { - "id": "troubleshoot-cache-misses", - "name": "Troubleshoot Cache Misses", - "description": "", - "file": "shared/recipes/troubleshoot-cache-misses", - "itemList": [], - "isExternal": false, - "path": "/recipes/troubleshooting/troubleshoot-cache-misses", - "tags": ["cache-task-results"] - }, - "/recipes/troubleshooting/unknown-local-cache": { - "id": "unknown-local-cache", - "name": "Unknown Local Cache Error", - "description": "", - "file": "shared/guides/unknown-local-cache", - "itemList": [], - "isExternal": false, - "path": "/recipes/troubleshooting/unknown-local-cache", + "path": "/recipes/ci/monorepo-ci-gitlab", "tags": [] }, - "/recipes/troubleshooting/performance-profiling": { - "id": "performance-profiling", - "name": "Profiling Build Performance", + "/recipes/ci/monorepo-ci-bitbucket-pipelines": { + "id": "monorepo-ci-bitbucket-pipelines", + "name": "Setting up Bitbucket", "description": "", - "file": "shared/guides/performance-profiling", + "file": "shared/monorepo-ci-bitbucket-pipelines", "itemList": [], "isExternal": false, - "path": "/recipes/troubleshooting/performance-profiling", - "tags": ["use-task-executors", "environment-variables"] + "path": "/recipes/ci/monorepo-ci-bitbucket-pipelines", + "tags": [] }, "/recipes/tips-n-tricks": { "id": "tips-n-tricks", @@ -4279,6 +4037,248 @@ "path": "/recipes/tips-n-tricks/run-commands-executor", "tags": ["use-task-executors"] }, + "/recipes/troubleshooting": { + "id": "troubleshooting", + "name": "Troubleshooting", + "description": "Learn how to troubleshoot common problems.", + "file": "", + "itemList": [ + { + "id": "resolve-circular-dependencies", + "name": "Resolve Circular Dependencies", + "description": "", + "file": "shared/recipes/resolve-circular-dependencies", + "itemList": [], + "isExternal": false, + "path": "/recipes/troubleshooting/resolve-circular-dependencies", + "tags": ["explore-graph"] + }, + { + "id": "troubleshoot-nx-install-issues", + "name": "Troubleshooting Nx Install Issues", + "description": "", + "file": "shared/installation/troubleshoot-installation", + "itemList": [], + "isExternal": false, + "path": "/recipes/troubleshooting/troubleshoot-nx-install-issues", + "tags": [] + }, + { + "id": "troubleshoot-cache-misses", + "name": "Troubleshoot Cache Misses", + "description": "", + "file": "shared/recipes/troubleshoot-cache-misses", + "itemList": [], + "isExternal": false, + "path": "/recipes/troubleshooting/troubleshoot-cache-misses", + "tags": ["cache-task-results"] + }, + { + "id": "unknown-local-cache", + "name": "Unknown Local Cache Error", + "description": "", + "file": "shared/guides/unknown-local-cache", + "itemList": [], + "isExternal": false, + "path": "/recipes/troubleshooting/unknown-local-cache", + "tags": [] + }, + { + "id": "performance-profiling", + "name": "Profiling Build Performance", + "description": "", + "file": "shared/guides/performance-profiling", + "itemList": [], + "isExternal": false, + "path": "/recipes/troubleshooting/performance-profiling", + "tags": ["use-task-executors", "environment-variables"] + } + ], + "isExternal": false, + "path": "/recipes/troubleshooting", + "tags": [] + }, + "/recipes/troubleshooting/resolve-circular-dependencies": { + "id": "resolve-circular-dependencies", + "name": "Resolve Circular Dependencies", + "description": "", + "file": "shared/recipes/resolve-circular-dependencies", + "itemList": [], + "isExternal": false, + "path": "/recipes/troubleshooting/resolve-circular-dependencies", + "tags": ["explore-graph"] + }, + "/recipes/troubleshooting/troubleshoot-nx-install-issues": { + "id": "troubleshoot-nx-install-issues", + "name": "Troubleshooting Nx Install Issues", + "description": "", + "file": "shared/installation/troubleshoot-installation", + "itemList": [], + "isExternal": false, + "path": "/recipes/troubleshooting/troubleshoot-nx-install-issues", + "tags": [] + }, + "/recipes/troubleshooting/troubleshoot-cache-misses": { + "id": "troubleshoot-cache-misses", + "name": "Troubleshoot Cache Misses", + "description": "", + "file": "shared/recipes/troubleshoot-cache-misses", + "itemList": [], + "isExternal": false, + "path": "/recipes/troubleshooting/troubleshoot-cache-misses", + "tags": ["cache-task-results"] + }, + "/recipes/troubleshooting/unknown-local-cache": { + "id": "unknown-local-cache", + "name": "Unknown Local Cache Error", + "description": "", + "file": "shared/guides/unknown-local-cache", + "itemList": [], + "isExternal": false, + "path": "/recipes/troubleshooting/unknown-local-cache", + "tags": [] + }, + "/recipes/troubleshooting/performance-profiling": { + "id": "performance-profiling", + "name": "Profiling Build Performance", + "description": "", + "file": "shared/guides/performance-profiling", + "itemList": [], + "isExternal": false, + "path": "/recipes/troubleshooting/performance-profiling", + "tags": ["use-task-executors", "environment-variables"] + }, + "/recipes/nx-console": { + "id": "nx-console", + "name": "Nx Console", + "description": "Checkout all the recipes related to Nx Console.", + "file": "", + "itemList": [ + { + "id": "console-telemetry", + "name": "Telemetry", + "description": "", + "file": "shared/recipes/console-telemetry", + "itemList": [], + "isExternal": false, + "path": "/recipes/nx-console/console-telemetry", + "tags": ["integrate-with-editors"] + }, + { + "id": "console-generate-command", + "name": "Generate Command", + "description": "", + "file": "shared/recipes/console-generate-command", + "itemList": [], + "isExternal": false, + "path": "/recipes/nx-console/console-generate-command", + "tags": ["integrate-with-editors"] + }, + { + "id": "console-run-command", + "name": "Run Command", + "description": "", + "file": "shared/recipes/console-run-command", + "itemList": [], + "isExternal": false, + "path": "/recipes/nx-console/console-run-command", + "tags": ["integrate-with-editors"] + }, + { + "id": "console-add-dependency-command", + "name": "Add Dependency Command", + "description": "", + "file": "shared/recipes/console-add-dependency-command", + "itemList": [], + "isExternal": false, + "path": "/recipes/nx-console/console-add-dependency-command", + "tags": ["integrate-with-editors"] + }, + { + "id": "console-project-pane", + "name": "Project Pane", + "description": "", + "file": "shared/recipes/console-project-pane", + "itemList": [], + "isExternal": false, + "path": "/recipes/nx-console/console-project-pane", + "tags": ["integrate-with-editors"] + }, + { + "id": "console-shortcuts", + "name": "Keyboard Shortcuts", + "description": "", + "file": "shared/recipes/console-shortcuts", + "itemList": [], + "isExternal": false, + "path": "/recipes/nx-console/console-shortcuts", + "tags": ["integrate-with-editors"] + } + ], + "isExternal": false, + "path": "/recipes/nx-console", + "tags": [] + }, + "/recipes/nx-console/console-telemetry": { + "id": "console-telemetry", + "name": "Telemetry", + "description": "", + "file": "shared/recipes/console-telemetry", + "itemList": [], + "isExternal": false, + "path": "/recipes/nx-console/console-telemetry", + "tags": ["integrate-with-editors"] + }, + "/recipes/nx-console/console-generate-command": { + "id": "console-generate-command", + "name": "Generate Command", + "description": "", + "file": "shared/recipes/console-generate-command", + "itemList": [], + "isExternal": false, + "path": "/recipes/nx-console/console-generate-command", + "tags": ["integrate-with-editors"] + }, + "/recipes/nx-console/console-run-command": { + "id": "console-run-command", + "name": "Run Command", + "description": "", + "file": "shared/recipes/console-run-command", + "itemList": [], + "isExternal": false, + "path": "/recipes/nx-console/console-run-command", + "tags": ["integrate-with-editors"] + }, + "/recipes/nx-console/console-add-dependency-command": { + "id": "console-add-dependency-command", + "name": "Add Dependency Command", + "description": "", + "file": "shared/recipes/console-add-dependency-command", + "itemList": [], + "isExternal": false, + "path": "/recipes/nx-console/console-add-dependency-command", + "tags": ["integrate-with-editors"] + }, + "/recipes/nx-console/console-project-pane": { + "id": "console-project-pane", + "name": "Project Pane", + "description": "", + "file": "shared/recipes/console-project-pane", + "itemList": [], + "isExternal": false, + "path": "/recipes/nx-console/console-project-pane", + "tags": ["integrate-with-editors"] + }, + "/recipes/nx-console/console-shortcuts": { + "id": "console-shortcuts", + "name": "Keyboard Shortcuts", + "description": "", + "file": "shared/recipes/console-shortcuts", + "itemList": [], + "isExternal": false, + "path": "/recipes/nx-console/console-shortcuts", + "tags": ["integrate-with-editors"] + }, "/recipes/other": { "id": "other", "name": "Other", diff --git a/docs/generated/manifests/tags.json b/docs/generated/manifests/tags.json index 5acc0429ea6d0..e05f9cb0491a1 100644 --- a/docs/generated/manifests/tags.json +++ b/docs/generated/manifests/tags.json @@ -160,13 +160,6 @@ "name": "How the Project Graph is Built", "path": "/concepts/more-concepts/how-project-graph-is-built" }, - { - "description": "", - "file": "shared/recipes/resolve-circular-dependencies", - "id": "resolve-circular-dependencies", - "name": "Resolve Circular Dependencies", - "path": "/recipes/troubleshooting/resolve-circular-dependencies" - }, { "description": "", "file": "shared/recipes/analyze-source-files", @@ -174,6 +167,13 @@ "name": "Disable Graph Links Created from Analyzing Source Files", "path": "/recipes/tips-n-tricks/analyze-source-files" }, + { + "description": "", + "file": "shared/recipes/resolve-circular-dependencies", + "id": "resolve-circular-dependencies", + "name": "Resolve Circular Dependencies", + "path": "/recipes/troubleshooting/resolve-circular-dependencies" + }, { "description": "", "file": "shared/recipes/plugins/project-graph-plugins", @@ -436,6 +436,13 @@ "name": "Incremental Builds", "path": "/concepts/more-concepts/incremental-builds" }, + { + "description": "", + "file": "shared/recipes/module-federation-with-ssr", + "id": "module-federation-with-ssr", + "name": "Setup Module Federation with SSR for React", + "path": "/recipes/react/module-federation-with-ssr" + }, { "description": "", "file": "shared/recipes/module-federation-with-ssr", @@ -452,10 +459,10 @@ }, { "description": "", - "file": "shared/recipes/module-federation-with-ssr", - "id": "module-federation-with-ssr", - "name": "Setup Module Federation with SSR for React", - "path": "/recipes/react/module-federation-with-ssr" + "file": "shared/running-custom-commands", + "id": "run-commands-executor", + "name": "Running Custom Commands", + "path": "/recipes/tips-n-tricks/run-commands-executor" }, { "description": "", @@ -464,13 +471,6 @@ "name": "Profiling Build Performance", "path": "/recipes/troubleshooting/performance-profiling" }, - { - "description": "", - "file": "shared/running-custom-commands", - "id": "run-commands-executor", - "name": "Running Custom Commands", - "path": "/recipes/tips-n-tricks/run-commands-executor" - }, { "description": "", "file": "shared/reference/project-configuration", @@ -649,13 +649,6 @@ } ], "environment-variables": [ - { - "description": "", - "file": "shared/guides/use-environment-variables-in-angular", - "id": "use-environment-variables-in-angular", - "name": "Use Environment Variables in Angular", - "path": "/recipes/angular/use-environment-variables-in-angular" - }, { "description": "", "file": "shared/guides/use-environment-variables-in-react", @@ -665,10 +658,10 @@ }, { "description": "", - "file": "shared/guides/performance-profiling", - "id": "performance-profiling", - "name": "Profiling Build Performance", - "path": "/recipes/troubleshooting/performance-profiling" + "file": "shared/guides/use-environment-variables-in-angular", + "id": "use-environment-variables-in-angular", + "name": "Use Environment Variables in Angular", + "path": "/recipes/angular/use-environment-variables-in-angular" }, { "description": "", @@ -677,6 +670,13 @@ "name": "Define Environment Variables", "path": "/recipes/tips-n-tricks/define-environment-variables" }, + { + "description": "", + "file": "shared/guides/performance-profiling", + "id": "performance-profiling", + "name": "Profiling Build Performance", + "path": "/recipes/troubleshooting/performance-profiling" + }, { "description": "", "file": "shared/reference/environment-variables", @@ -686,6 +686,13 @@ } ], "module-federation": [ + { + "description": "", + "file": "shared/recipes/module-federation-with-ssr", + "id": "module-federation-with-ssr", + "name": "Setup Module Federation with SSR for React", + "path": "/recipes/react/module-federation-with-ssr" + }, { "description": "", "file": "shared/recipes/module-federation-with-ssr", @@ -699,7 +706,9 @@ "id": "dynamic-module-federation-with-angular", "name": "Advanced Micro Frontends with Angular using Dynamic Federation", "path": "/recipes/angular/dynamic-module-federation-with-angular" - }, + } + ], + "react": [ { "description": "", "file": "shared/recipes/module-federation-with-ssr", @@ -724,15 +733,6 @@ "path": "/recipes/angular/dynamic-module-federation-with-angular" } ], - "react": [ - { - "description": "", - "file": "shared/recipes/module-federation-with-ssr", - "id": "module-federation-with-ssr", - "name": "Setup Module Federation with SSR for React", - "path": "/recipes/react/module-federation-with-ssr" - } - ], "deployment": [ { "description": "", diff --git a/docs/map.json b/docs/map.json index a4df93f889734..0faafd16e9777 100644 --- a/docs/map.json +++ b/docs/map.json @@ -540,6 +540,60 @@ } ] }, + { + "name": "React", + "id": "react", + "description": "Advanced guides to adopt Nx in React.", + "itemList": [ + { + "name": "Migrating from CRA", + "id": "migration-cra", + "file": "shared/migration/migration-cra" + }, + { + "name": "React 18 Migration", + "id": "react-18", + "file": "shared/guides/react-18" + }, + { + "name": "React Native with Nx", + "id": "react-native", + "file": "shared/guides/react-native" + }, + { + "name": "Remix with Nx", + "id": "remix", + "file": "shared/guides/remix" + }, + { + "name": "Use Environment Variables in React", + "id": "use-environment-variables-in-react", + "tags": ["environment-variables"], + "file": "shared/guides/use-environment-variables-in-react" + }, + { + "name": "Using Tailwind CSS in React", + "id": "using-tailwind-css-in-react", + "file": "shared/guides/using-tailwind-css-in-react" + }, + { + "name": "Adding Images, Fonts, and Files", + "id": "adding-assets-react", + "file": "shared/guides/adding-assets" + }, + { + "name": "Setup Module Federation with SSR for React", + "id": "module-federation-with-ssr", + "tags": ["use-task-executors", "module-federation", "react"], + "file": "shared/recipes/module-federation-with-ssr" + }, + { + "name": "Deploying Next.js applications to Vercel", + "id": "deploy-nextjs-to-vercel", + "file": "shared/recipes/deployment/deploy-nextjs-to-vercel" + } + ] + }, { "name": "Angular", "id": "angular", @@ -609,60 +663,6 @@ } ] }, - { - "name": "React", - "id": "react", - "description": "Advanced guides to adopt Nx in React.", - "itemList": [ - { - "name": "Migrating from CRA", - "id": "migration-cra", - "file": "shared/migration/migration-cra" - }, - { - "name": "React 18 Migration", - "id": "react-18", - "file": "shared/guides/react-18" - }, - { - "name": "React Native with Nx", - "id": "react-native", - "file": "shared/guides/react-native" - }, - { - "name": "Remix with Nx", - "id": "remix", - "file": "shared/guides/remix" - }, - { - "name": "Use Environment Variables in React", - "id": "use-environment-variables-in-react", - "tags": ["environment-variables"], - "file": "shared/guides/use-environment-variables-in-react" - }, - { - "name": "Using Tailwind CSS in React", - "id": "using-tailwind-css-in-react", - "file": "shared/guides/using-tailwind-css-in-react" - }, - { - "name": "Adding Images, Fonts, and Files", - "id": "adding-assets-react", - "file": "shared/guides/adding-assets" - }, - { - "name": "Setup Module Federation with SSR for React", - "id": "module-federation-with-ssr", - "tags": ["use-task-executors", "module-federation", "react"], - "file": "shared/recipes/module-federation-with-ssr" - }, - { - "name": "Deploying Next.js applications to Vercel", - "id": "deploy-nextjs-to-vercel", - "file": "shared/recipes/deployment/deploy-nextjs-to-vercel" - } - ] - }, { "name": "Node", "id": "node", @@ -793,85 +793,6 @@ } ] }, - { - "name": "Nx Console", - "id": "nx-console", - "description": "Checkout all the recipes related to Nx Console.", - "itemList": [ - { - "name": "Telemetry", - "id": "console-telemetry", - "tags": ["integrate-with-editors"], - "file": "shared/recipes/console-telemetry" - }, - { - "name": "Generate Command", - "id": "console-generate-command", - "tags": ["integrate-with-editors"], - "file": "shared/recipes/console-generate-command" - }, - { - "name": "Run Command", - "id": "console-run-command", - "tags": ["integrate-with-editors"], - "file": "shared/recipes/console-run-command" - }, - { - "name": "Add Dependency Command", - "id": "console-add-dependency-command", - "tags": ["integrate-with-editors"], - "file": "shared/recipes/console-add-dependency-command" - }, - { - "name": "Project Pane", - "id": "console-project-pane", - "tags": ["integrate-with-editors"], - "file": "shared/recipes/console-project-pane" - }, - { - "name": "Keyboard Shortcuts", - "id": "console-shortcuts", - "tags": ["integrate-with-editors"], - "file": "shared/recipes/console-shortcuts" - } - ] - }, - { - "name": "Troubleshooting", - "id": "troubleshooting", - "description": "Learn how to troubleshoot common problems.", - "itemList": [ - { - "name": "Resolve Circular Dependencies", - "id": "resolve-circular-dependencies", - "tags": ["explore-graph"], - "file": "shared/recipes/resolve-circular-dependencies" - }, - { - "name": "Troubleshooting Nx Install Issues", - "id": "troubleshoot-nx-install-issues", - "file": "shared/installation/troubleshoot-installation" - }, - { - "name": "Troubleshoot Cache Misses", - "id": "troubleshoot-cache-misses", - "tags": ["cache-task-results"], - "file": "shared/recipes/troubleshoot-cache-misses" - }, - { - "name": "Unknown Local Cache Error", - "id": "unknown-local-cache", - "tags": [], - "file": "shared/guides/unknown-local-cache" - }, - { - "name": "Profiling Build Performance", - "id": "performance-profiling", - "tags": ["use-task-executors", "environment-variables"], - "file": "shared/guides/performance-profiling" - } - ] - }, { "name": "Tips and tricks", "id": "tips-n-tricks", @@ -954,6 +875,85 @@ } ] }, + { + "name": "Troubleshooting", + "id": "troubleshooting", + "description": "Learn how to troubleshoot common problems.", + "itemList": [ + { + "name": "Resolve Circular Dependencies", + "id": "resolve-circular-dependencies", + "tags": ["explore-graph"], + "file": "shared/recipes/resolve-circular-dependencies" + }, + { + "name": "Troubleshooting Nx Install Issues", + "id": "troubleshoot-nx-install-issues", + "file": "shared/installation/troubleshoot-installation" + }, + { + "name": "Troubleshoot Cache Misses", + "id": "troubleshoot-cache-misses", + "tags": ["cache-task-results"], + "file": "shared/recipes/troubleshoot-cache-misses" + }, + { + "name": "Unknown Local Cache Error", + "id": "unknown-local-cache", + "tags": [], + "file": "shared/guides/unknown-local-cache" + }, + { + "name": "Profiling Build Performance", + "id": "performance-profiling", + "tags": ["use-task-executors", "environment-variables"], + "file": "shared/guides/performance-profiling" + } + ] + }, + { + "name": "Nx Console", + "id": "nx-console", + "description": "Checkout all the recipes related to Nx Console.", + "itemList": [ + { + "name": "Telemetry", + "id": "console-telemetry", + "tags": ["integrate-with-editors"], + "file": "shared/recipes/console-telemetry" + }, + { + "name": "Generate Command", + "id": "console-generate-command", + "tags": ["integrate-with-editors"], + "file": "shared/recipes/console-generate-command" + }, + { + "name": "Run Command", + "id": "console-run-command", + "tags": ["integrate-with-editors"], + "file": "shared/recipes/console-run-command" + }, + { + "name": "Add Dependency Command", + "id": "console-add-dependency-command", + "tags": ["integrate-with-editors"], + "file": "shared/recipes/console-add-dependency-command" + }, + { + "name": "Project Pane", + "id": "console-project-pane", + "tags": ["integrate-with-editors"], + "file": "shared/recipes/console-project-pane" + }, + { + "name": "Keyboard Shortcuts", + "id": "console-shortcuts", + "tags": ["integrate-with-editors"], + "file": "shared/recipes/console-shortcuts" + } + ] + }, { "name": "Other", "id": "other", diff --git a/docs/shared/reference/sitemap.md b/docs/shared/reference/sitemap.md index 50dcc3807b15b..92a6b588331fe 100644 --- a/docs/shared/reference/sitemap.md +++ b/docs/shared/reference/sitemap.md @@ -96,6 +96,16 @@ - [Nx and Lerna](/recipes/adopting-nx/lerna-and-nx) - [Preserving Git Histories](/recipes/adopting-nx/preserving-git-histories) - [Manual migration](/recipes/adopting-nx/manual) + - [React](/recipes/react) + - [Migrating from CRA](/recipes/react/migration-cra) + - [React 18 Migration](/recipes/react/react-18) + - [React Native with Nx](/recipes/react/react-native) + - [Remix with Nx](/recipes/react/remix) + - [Use Environment Variables in React](/recipes/react/use-environment-variables-in-react) + - [Using Tailwind CSS in React](/recipes/react/using-tailwind-css-in-react) + - [Adding Images, Fonts, and Files](/recipes/react/adding-assets-react) + - [Setup Module Federation with SSR for React](/recipes/react/module-federation-with-ssr) + - [Deploying Next.js applications to Vercel](/recipes/react/deploy-nextjs-to-vercel) - [Angular](/recipes/angular) - [Migration](/recipes/angular/migration) - [Migrating from Angular CLI](/recipes/angular/migration/angular) @@ -107,16 +117,6 @@ - [Setup Module Federation with SSR for Angular](/recipes/angular/module-federation-with-ssr) - [Advanced Micro Frontends with Angular using Dynamic Federation](/recipes/angular/dynamic-module-federation-with-angular) - [Setup incremental builds for Angular applications](/recipes/angular/setup-incremental-builds-angular) - - [React](/recipes/react) - - [Migrating from CRA](/recipes/react/migration-cra) - - [React 18 Migration](/recipes/react/react-18) - - [React Native with Nx](/recipes/react/react-native) - - [Remix with Nx](/recipes/react/remix) - - [Use Environment Variables in React](/recipes/react/use-environment-variables-in-react) - - [Using Tailwind CSS in React](/recipes/react/using-tailwind-css-in-react) - - [Adding Images, Fonts, and Files](/recipes/react/adding-assets-react) - - [Setup Module Federation with SSR for React](/recipes/react/module-federation-with-ssr) - - [Deploying Next.js applications to Vercel](/recipes/react/deploy-nextjs-to-vercel) - [Node](/recipes/node) - [Deploying a Node App to Fly.io](/recipes/node/node-server-fly-io) - [Add and Deploy Netlify Edge Functions with Node](/recipes/node/node-serverless-functions-netlify) @@ -139,19 +139,6 @@ - [Setting up Jenkins](/recipes/ci/monorepo-ci-jenkins) - [Setting up GitLab](/recipes/ci/monorepo-ci-gitlab) - [Setting up Bitbucket](/recipes/ci/monorepo-ci-bitbucket-pipelines) - - [Nx Console](/recipes/nx-console) - - [Telemetry](/recipes/nx-console/console-telemetry) - - [Generate Command](/recipes/nx-console/console-generate-command) - - [Run Command](/recipes/nx-console/console-run-command) - - [Add Dependency Command](/recipes/nx-console/console-add-dependency-command) - - [Project Pane](/recipes/nx-console/console-project-pane) - - [Keyboard Shortcuts](/recipes/nx-console/console-shortcuts) - - [Troubleshooting](/recipes/troubleshooting) - - [Resolve Circular Dependencies](/recipes/troubleshooting/resolve-circular-dependencies) - - [Troubleshooting Nx Install Issues](/recipes/troubleshooting/troubleshoot-nx-install-issues) - - [Troubleshoot Cache Misses](/recipes/troubleshooting/troubleshoot-cache-misses) - - [Unknown Local Cache Error](/recipes/troubleshooting/unknown-local-cache) - - [Profiling Build Performance](/recipes/troubleshooting/performance-profiling) - [Tips and tricks](/recipes/tips-n-tricks) - [Configuring ESLint with Typescript](/recipes/tips-n-tricks/eslint) - [Define Environment Variables](/recipes/tips-n-tricks/define-environment-variables) @@ -166,6 +153,19 @@ - [Use JavaScript instead TypeScript](/recipes/tips-n-tricks/js-and-ts) - [Altering Migration Process](/recipes/tips-n-tricks/advanced-update) - [Running Custom Commands](/recipes/tips-n-tricks/run-commands-executor) + - [Troubleshooting](/recipes/troubleshooting) + - [Resolve Circular Dependencies](/recipes/troubleshooting/resolve-circular-dependencies) + - [Troubleshooting Nx Install Issues](/recipes/troubleshooting/troubleshoot-nx-install-issues) + - [Troubleshoot Cache Misses](/recipes/troubleshooting/troubleshoot-cache-misses) + - [Unknown Local Cache Error](/recipes/troubleshooting/unknown-local-cache) + - [Profiling Build Performance](/recipes/troubleshooting/performance-profiling) + - [Nx Console](/recipes/nx-console) + - [Telemetry](/recipes/nx-console/console-telemetry) + - [Generate Command](/recipes/nx-console/console-generate-command) + - [Run Command](/recipes/nx-console/console-run-command) + - [Add Dependency Command](/recipes/nx-console/console-add-dependency-command) + - [Project Pane](/recipes/nx-console/console-project-pane) + - [Keyboard Shortcuts](/recipes/nx-console/console-shortcuts) - [Other](/recipes/other) - [Serverless deployment with Deno Deploy](/recipes/other/deno-deploy) - [Add and Deploy Netlify Edge Functions with Deno](/recipes/other/deno-netlify-functions) From 3105203248539b335b69c1144af2d9a337664904 Mon Sep 17 00:00:00 2001 From: Miroslav Jonas Date: Mon, 24 Jul 2023 15:44:05 +0200 Subject: [PATCH 159/262] fix(nx-dev): fix missing link --- docs/shared/reference/glossary.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/shared/reference/glossary.md b/docs/shared/reference/glossary.md index 17d4cfe68f54d..dc3ab0bd1e132 100644 --- a/docs/shared/reference/glossary.md +++ b/docs/shared/reference/glossary.md @@ -56,7 +56,7 @@ Anything you run in the terminal. An example command that invokes a [task](#task A set of preconfigured options for a [target](#target) that should be enabled altogether. For example, a `production` configuration would set all the options needed for a build that could be deployed to production. -> See: [Use Executor Configurations](/plugin-features/use-task-executors#use-executor-configurations) +> See: [Use Executor Configurations](/core-features/plugin-features/use-task-executors#use-executor-configurations) ### Distributed Cache From e05ca1fd2faff7539c7fd04c411a1732200a5dbe Mon Sep 17 00:00:00 2001 From: Miroslav Jonas Date: Tue, 25 Jul 2023 09:38:17 +0200 Subject: [PATCH 160/262] fix(nx-dev): fix rebase --- docs/generated/manifests/menus.json | 24 ++++ docs/generated/manifests/nx.json | 35 ++++++ docs/generated/manifests/tags.json | 104 +++++++++++------- .../packages/angular/documents/overview.md | 2 +- .../webpack/documents/webpack-config-setup.md | 2 +- .../webpack/documents/webpack-plugins.md | 2 +- docs/map.json | 11 ++ .../micro-frontend-architecture.md | 8 +- docs/shared/incremental-builds.md | 2 +- .../shared/packages/angular/angular-plugin.md | 2 +- .../packages/webpack/webpack-config-setup.md | 2 +- .../packages/webpack/webpack-plugins.md | 2 +- .../recipes/module-federation-with-ssr.md | 2 +- docs/shared/reference/sitemap.md | 1 + nx-dev/nx-dev/redirect-rules.js | 2 +- .../module-federation-dev-server.impl.ts | 2 +- 16 files changed, 151 insertions(+), 52 deletions(-) diff --git a/docs/generated/manifests/menus.json b/docs/generated/manifests/menus.json index 1496e19820f2f..c295742503f55 100644 --- a/docs/generated/manifests/menus.json +++ b/docs/generated/manifests/menus.json @@ -1130,6 +1130,14 @@ "children": [], "disableCollapsible": false }, + { + "name": "Faster Builds with Module Federation", + "path": "/concepts/more-concepts/faster-builds-with-module-federation", + "id": "faster-builds-with-module-federation", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, { "name": "Applications and Libraries", "path": "/concepts/more-concepts/applications-and-libraries", @@ -1358,6 +1366,14 @@ "children": [], "disableCollapsible": false }, + { + "name": "Faster Builds with Module Federation", + "path": "/concepts/more-concepts/faster-builds-with-module-federation", + "id": "faster-builds-with-module-federation", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, { "name": "Applications and Libraries", "path": "/concepts/more-concepts/applications-and-libraries", @@ -1529,6 +1545,14 @@ "children": [], "disableCollapsible": false }, + { + "name": "Faster Builds with Module Federation", + "path": "/concepts/more-concepts/faster-builds-with-module-federation", + "id": "faster-builds-with-module-federation", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, { "name": "Applications and Libraries", "path": "/concepts/more-concepts/applications-and-libraries", diff --git a/docs/generated/manifests/nx.json b/docs/generated/manifests/nx.json index 9aee0086cf4d9..77af63ce46821 100644 --- a/docs/generated/manifests/nx.json +++ b/docs/generated/manifests/nx.json @@ -1403,6 +1403,21 @@ "path": "/concepts/more-concepts/micro-frontend-architecture", "tags": [] }, + { + "id": "faster-builds-with-module-federation", + "name": "Faster Builds with Module Federation", + "description": "", + "file": "shared/guides/module-federation/faster-builds", + "itemList": [], + "isExternal": false, + "path": "/concepts/more-concepts/faster-builds-with-module-federation", + "tags": [ + "use-task-executors", + "module-federation", + "angular", + "react" + ] + }, { "id": "applications-and-libraries", "name": "Applications and Libraries", @@ -1689,6 +1704,16 @@ "path": "/concepts/more-concepts/micro-frontend-architecture", "tags": [] }, + { + "id": "faster-builds-with-module-federation", + "name": "Faster Builds with Module Federation", + "description": "", + "file": "shared/guides/module-federation/faster-builds", + "itemList": [], + "isExternal": false, + "path": "/concepts/more-concepts/faster-builds-with-module-federation", + "tags": ["use-task-executors", "module-federation", "angular", "react"] + }, { "id": "applications-and-libraries", "name": "Applications and Libraries", @@ -1904,6 +1929,16 @@ "path": "/concepts/more-concepts/micro-frontend-architecture", "tags": [] }, + "/concepts/more-concepts/faster-builds-with-module-federation": { + "id": "faster-builds-with-module-federation", + "name": "Faster Builds with Module Federation", + "description": "", + "file": "shared/guides/module-federation/faster-builds", + "itemList": [], + "isExternal": false, + "path": "/concepts/more-concepts/faster-builds-with-module-federation", + "tags": ["use-task-executors", "module-federation", "angular", "react"] + }, "/concepts/more-concepts/applications-and-libraries": { "id": "applications-and-libraries", "name": "Applications and Libraries", diff --git a/docs/generated/manifests/tags.json b/docs/generated/manifests/tags.json index e05f9cb0491a1..72fdedc32a035 100644 --- a/docs/generated/manifests/tags.json +++ b/docs/generated/manifests/tags.json @@ -436,6 +436,13 @@ "name": "Incremental Builds", "path": "/concepts/more-concepts/incremental-builds" }, + { + "description": "", + "file": "shared/guides/module-federation/faster-builds", + "id": "faster-builds-with-module-federation", + "name": "Faster Builds with Module Federation", + "path": "/concepts/more-concepts/faster-builds-with-module-federation" + }, { "description": "", "file": "shared/recipes/module-federation-with-ssr", @@ -648,50 +655,43 @@ "path": "/extending-nx/recipes/project-inference-plugins" } ], - "environment-variables": [ - { - "description": "", - "file": "shared/guides/use-environment-variables-in-react", - "id": "use-environment-variables-in-react", - "name": "Use Environment Variables in React", - "path": "/recipes/react/use-environment-variables-in-react" - }, + "module-federation": [ { "description": "", - "file": "shared/guides/use-environment-variables-in-angular", - "id": "use-environment-variables-in-angular", - "name": "Use Environment Variables in Angular", - "path": "/recipes/angular/use-environment-variables-in-angular" + "file": "shared/guides/module-federation/faster-builds", + "id": "faster-builds-with-module-federation", + "name": "Faster Builds with Module Federation", + "path": "/concepts/more-concepts/faster-builds-with-module-federation" }, { "description": "", - "file": "shared/guides/define-environment-variables", - "id": "define-environment-variables", - "name": "Define Environment Variables", - "path": "/recipes/tips-n-tricks/define-environment-variables" + "file": "shared/recipes/module-federation-with-ssr", + "id": "module-federation-with-ssr", + "name": "Setup Module Federation with SSR for React", + "path": "/recipes/react/module-federation-with-ssr" }, { "description": "", - "file": "shared/guides/performance-profiling", - "id": "performance-profiling", - "name": "Profiling Build Performance", - "path": "/recipes/troubleshooting/performance-profiling" + "file": "shared/recipes/module-federation-with-ssr", + "id": "module-federation-with-ssr", + "name": "Setup Module Federation with SSR for Angular", + "path": "/recipes/angular/module-federation-with-ssr" }, { "description": "", - "file": "shared/reference/environment-variables", - "id": "environment-variables", - "name": "Environment Variables", - "path": "/reference/environment-variables" + "file": "shared/guides/module-federation/dynamic-mfe-angular", + "id": "dynamic-module-federation-with-angular", + "name": "Advanced Micro Frontends with Angular using Dynamic Federation", + "path": "/recipes/angular/dynamic-module-federation-with-angular" } ], - "module-federation": [ + "angular": [ { "description": "", - "file": "shared/recipes/module-federation-with-ssr", - "id": "module-federation-with-ssr", - "name": "Setup Module Federation with SSR for React", - "path": "/recipes/react/module-federation-with-ssr" + "file": "shared/guides/module-federation/faster-builds", + "id": "faster-builds-with-module-federation", + "name": "Faster Builds with Module Federation", + "path": "/concepts/more-concepts/faster-builds-with-module-federation" }, { "description": "", @@ -709,6 +709,13 @@ } ], "react": [ + { + "description": "", + "file": "shared/guides/module-federation/faster-builds", + "id": "faster-builds-with-module-federation", + "name": "Faster Builds with Module Federation", + "path": "/concepts/more-concepts/faster-builds-with-module-federation" + }, { "description": "", "file": "shared/recipes/module-federation-with-ssr", @@ -717,20 +724,41 @@ "path": "/recipes/react/module-federation-with-ssr" } ], - "angular": [ + "environment-variables": [ { "description": "", - "file": "shared/recipes/module-federation-with-ssr", - "id": "module-federation-with-ssr", - "name": "Setup Module Federation with SSR for Angular", - "path": "/recipes/angular/module-federation-with-ssr" + "file": "shared/guides/use-environment-variables-in-react", + "id": "use-environment-variables-in-react", + "name": "Use Environment Variables in React", + "path": "/recipes/react/use-environment-variables-in-react" }, { "description": "", - "file": "shared/guides/module-federation/dynamic-mfe-angular", - "id": "dynamic-module-federation-with-angular", - "name": "Advanced Micro Frontends with Angular using Dynamic Federation", - "path": "/recipes/angular/dynamic-module-federation-with-angular" + "file": "shared/guides/use-environment-variables-in-angular", + "id": "use-environment-variables-in-angular", + "name": "Use Environment Variables in Angular", + "path": "/recipes/angular/use-environment-variables-in-angular" + }, + { + "description": "", + "file": "shared/guides/define-environment-variables", + "id": "define-environment-variables", + "name": "Define Environment Variables", + "path": "/recipes/tips-n-tricks/define-environment-variables" + }, + { + "description": "", + "file": "shared/guides/performance-profiling", + "id": "performance-profiling", + "name": "Profiling Build Performance", + "path": "/recipes/troubleshooting/performance-profiling" + }, + { + "description": "", + "file": "shared/reference/environment-variables", + "id": "environment-variables", + "name": "Environment Variables", + "path": "/reference/environment-variables" } ], "deployment": [ diff --git a/docs/generated/packages/angular/documents/overview.md b/docs/generated/packages/angular/documents/overview.md index 94cf1fa3b7e08..8883e2a5db5e3 100644 --- a/docs/generated/packages/angular/documents/overview.md +++ b/docs/generated/packages/angular/documents/overview.md @@ -93,6 +93,6 @@ nx g @nx/angular:service my-service - [Angular Nx Tutorial](/angular-tutorial/1-code-generation) - [Migrating from the Angular CLI](/recipes/angular/migration/angular) -- [Setup Module Federation with Angular and Nx](/more-concepts/faster-builds-with-module-federation) +- [Setup Module Federation with Angular and Nx](/concepts/more-concepts/faster-builds-with-module-federation) - [Upgrading an AngularJS application to Angular](/recipes/angular/migration/angularjs) - [Using Tailwind CSS with Angular projects](/recipes/angular/using-tailwind-css-with-angular-projects) diff --git a/docs/generated/packages/webpack/documents/webpack-config-setup.md b/docs/generated/packages/webpack/documents/webpack-config-setup.md index 51bf80a52a7db..cd48bc0403e8e 100644 --- a/docs/generated/packages/webpack/documents/webpack-config-setup.md +++ b/docs/generated/packages/webpack/documents/webpack-config-setup.md @@ -157,7 +157,7 @@ module.exports = composePlugins(withNx(), (config, { options, context }) => { ### Configure webpack for Module Federation -If you use the [Module Federation](/more-concepts/faster-builds-with-module-federation) support from `@nx/angular` or `@nx/react` then +If you use the [Module Federation](/concepts/more-concepts/faster-builds-with-module-federation) support from `@nx/angular` or `@nx/react` then you can customize your webpack configuration as follows. ```js {% fileName="apps/my-app/webpack.config.js" %} diff --git a/docs/generated/packages/webpack/documents/webpack-plugins.md b/docs/generated/packages/webpack/documents/webpack-plugins.md index 2927c83e7b0f7..7d34a3dda3182 100644 --- a/docs/generated/packages/webpack/documents/webpack-plugins.md +++ b/docs/generated/packages/webpack/documents/webpack-plugins.md @@ -165,7 +165,7 @@ module.exports = composePlugins( The `withModuleFederation` and `withModuleFederationForSSR` plugins add module federation support to the webpack build. These plugins use [`ModuleFederationPlugin`](https://webpack.js.org/concepts/module-federation/) and provide a simpler API through Nx. -For more information, refer to the [Module Federation recipe](/more-concepts/faster-builds-with-module-federation). +For more information, refer to the [Module Federation recipe](/concepts/more-concepts/faster-builds-with-module-federation). ### Options diff --git a/docs/map.json b/docs/map.json index 0faafd16e9777..5d86ee6808580 100644 --- a/docs/map.json +++ b/docs/map.json @@ -454,6 +454,17 @@ "id": "micro-frontend-architecture", "file": "shared/guides/module-federation/micro-frontend-architecture" }, + { + "name": "Faster Builds with Module Federation", + "id": "faster-builds-with-module-federation", + "tags": [ + "use-task-executors", + "module-federation", + "angular", + "react" + ], + "file": "shared/guides/module-federation/faster-builds" + }, { "name": "Applications and Libraries", "id": "applications-and-libraries", diff --git a/docs/shared/guides/module-federation/micro-frontend-architecture.md b/docs/shared/guides/module-federation/micro-frontend-architecture.md index 81b3fa7e03eed..3d9eff4e588b3 100644 --- a/docs/shared/guides/module-federation/micro-frontend-architecture.md +++ b/docs/shared/guides/module-federation/micro-frontend-architecture.md @@ -1,9 +1,9 @@ # Micro Frontend Architecture -Since version 14, Nx provides out-of-the-box [Module Federation](/more-concepts/faster-builds-with-module-federation) support to both React +Since version 14, Nx provides out-of-the-box [Module Federation](/concepts/more-concepts/faster-builds-with-module-federation) support to both React and Angular. The Micro Frontend (MFE) architecture builds on top of Module Federation by providing _independent deployability_. -If you have not read the [Module Federation guide](/more-concepts/faster-builds-with-module-federation) yet, we recommend that you read it +If you have not read the [Module Federation guide](/concepts/more-concepts/faster-builds-with-module-federation) yet, we recommend that you read it before continuing with this MFE guide. ## When should I use micro frontend architecture? @@ -17,7 +17,7 @@ of MFEs and decide whether it makes sense for your own teams. logic that breaks compatibility with remotes. If you are looking at optimizing builds and do not need independent deployments, we recommend reading our guide on -[Faster Builds with Module Federation](/more-concepts/faster-builds-with-module-federation). +[Faster Builds with Module Federation](/concepts/more-concepts/faster-builds-with-module-federation). If you need to use MFEs, keep reading, and we'll examine the architecture and strategies to deal with shared libraries and deployments. @@ -29,7 +29,7 @@ With MFE architecture, a large application is split into: 1. A single **Host** application that references external... 2. **Remote** applications, which handle a single domain or feature. -In a normal Module Federation setup, we [recommend setting up implicit dependencies](/more-concepts/faster-builds-with-module-federation#architectural-overview) +In a normal Module Federation setup, we [recommend setting up implicit dependencies](/concepts/more-concepts/faster-builds-with-module-federation#architectural-overview) from the host application to remote applications. However, in an MFE architecture you _do not_ want these dependencies to exist between host and remotes. diff --git a/docs/shared/incremental-builds.md b/docs/shared/incremental-builds.md index 32bf95d9da01b..774acbe7c9516 100644 --- a/docs/shared/incremental-builds.md +++ b/docs/shared/incremental-builds.md @@ -100,4 +100,4 @@ But there are other ways to make the build process incremental. One of them is u When using WebPack Module Federation, you split the application into multiple webpack builds. Imagine the application has 3 big sections, and they are built using 3 webpack builds: `W1`, `W2`, and `W3`. Each of them has to build shared code in addition to building the corresponding application section code. So the time it takes to build all of them (`W1` + `W2` + `W3`) will be greater than `W`. However, if you change only Section 1, you will only need to run `W1`. `W2` and `W3` will be retrieved from cache. In addition, `W1`, `W2`, and `W3` can run on separate machines. Because of that, both the CI time and the local serve time can be drastically reduced. -Learn more: [Faster Builds with Module Federation](/more-concepts/faster-builds-with-module-federation) +Learn more: [Faster Builds with Module Federation](/concepts/more-concepts/faster-builds-with-module-federation) diff --git a/docs/shared/packages/angular/angular-plugin.md b/docs/shared/packages/angular/angular-plugin.md index 94cf1fa3b7e08..8883e2a5db5e3 100644 --- a/docs/shared/packages/angular/angular-plugin.md +++ b/docs/shared/packages/angular/angular-plugin.md @@ -93,6 +93,6 @@ nx g @nx/angular:service my-service - [Angular Nx Tutorial](/angular-tutorial/1-code-generation) - [Migrating from the Angular CLI](/recipes/angular/migration/angular) -- [Setup Module Federation with Angular and Nx](/more-concepts/faster-builds-with-module-federation) +- [Setup Module Federation with Angular and Nx](/concepts/more-concepts/faster-builds-with-module-federation) - [Upgrading an AngularJS application to Angular](/recipes/angular/migration/angularjs) - [Using Tailwind CSS with Angular projects](/recipes/angular/using-tailwind-css-with-angular-projects) diff --git a/docs/shared/packages/webpack/webpack-config-setup.md b/docs/shared/packages/webpack/webpack-config-setup.md index 51bf80a52a7db..cd48bc0403e8e 100644 --- a/docs/shared/packages/webpack/webpack-config-setup.md +++ b/docs/shared/packages/webpack/webpack-config-setup.md @@ -157,7 +157,7 @@ module.exports = composePlugins(withNx(), (config, { options, context }) => { ### Configure webpack for Module Federation -If you use the [Module Federation](/more-concepts/faster-builds-with-module-federation) support from `@nx/angular` or `@nx/react` then +If you use the [Module Federation](/concepts/more-concepts/faster-builds-with-module-federation) support from `@nx/angular` or `@nx/react` then you can customize your webpack configuration as follows. ```js {% fileName="apps/my-app/webpack.config.js" %} diff --git a/docs/shared/packages/webpack/webpack-plugins.md b/docs/shared/packages/webpack/webpack-plugins.md index 2927c83e7b0f7..7d34a3dda3182 100644 --- a/docs/shared/packages/webpack/webpack-plugins.md +++ b/docs/shared/packages/webpack/webpack-plugins.md @@ -165,7 +165,7 @@ module.exports = composePlugins( The `withModuleFederation` and `withModuleFederationForSSR` plugins add module federation support to the webpack build. These plugins use [`ModuleFederationPlugin`](https://webpack.js.org/concepts/module-federation/) and provide a simpler API through Nx. -For more information, refer to the [Module Federation recipe](/more-concepts/faster-builds-with-module-federation). +For more information, refer to the [Module Federation recipe](/concepts/more-concepts/faster-builds-with-module-federation). ### Options diff --git a/docs/shared/recipes/module-federation-with-ssr.md b/docs/shared/recipes/module-federation-with-ssr.md index 37f892d41ed3f..82ab3631076fa 100644 --- a/docs/shared/recipes/module-federation-with-ssr.md +++ b/docs/shared/recipes/module-federation-with-ssr.md @@ -133,5 +133,5 @@ To serve the `store` application and watch for changes on the `checkout` applica To learn more about Module Federation, we have some resources you might find useful: -- [Guide: Faster Builds with Module Federation](/more-concepts/faster-builds-with-module-federation) +- [Guide: Faster Builds with Module Federation](/concepts/more-concepts/faster-builds-with-module-federation) - [Video: Speed up your Angular serve and build times with Module Federation and Nx](https://www.youtube.com/watch?v=JkcaGzhRjkc) diff --git a/docs/shared/reference/sitemap.md b/docs/shared/reference/sitemap.md index 92a6b588331fe..a4daf54a488cf 100644 --- a/docs/shared/reference/sitemap.md +++ b/docs/shared/reference/sitemap.md @@ -81,6 +81,7 @@ - [Folder Structure](/concepts/more-concepts/folder-structure) - [Nx Devkit and Angular Devkit](/concepts/more-concepts/nx-devkit-angular-devkit) - [Micro Frontend Architecture](/concepts/more-concepts/micro-frontend-architecture) + - [Faster Builds with Module Federation](/concepts/more-concepts/faster-builds-with-module-federation) - [Applications and Libraries](/concepts/more-concepts/applications-and-libraries) - [Creating Libraries](/concepts/more-concepts/creating-libraries) - [Library Types](/concepts/more-concepts/library-types) diff --git a/nx-dev/nx-dev/redirect-rules.js b/nx-dev/nx-dev/redirect-rules.js index c9de8d30e22e4..37c93a58b3b9a 100644 --- a/nx-dev/nx-dev/redirect-rules.js +++ b/nx-dev/nx-dev/redirect-rules.js @@ -824,7 +824,7 @@ const latestRecipesRefactoring = { // nx concepts '/recipes/module-federation/faster-builds': - '/more-concepts/faster-builds-with-module-federation', + '/concepts/more-concepts/faster-builds-with-module-federation', }; /** diff --git a/packages/react/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts b/packages/react/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts index 7c2fe37bae1b1..b1b7db1c4b97c 100644 --- a/packages/react/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts +++ b/packages/react/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts @@ -63,7 +63,7 @@ function getModuleFederationConfig( return config.default || config; } catch { throw new Error( - `Could not load ${moduleFederationConfigPath}. Was this project generated with "@nx/react:host"?\nSee: https://nx.dev/more-concepts/faster-builds-with-module-federation` + `Could not load ${moduleFederationConfigPath}. Was this project generated with "@nx/react:host"?\nSee: https://nx.dev/concepts/more-concepts/faster-builds-with-module-federation` ); } } From e6c67e41ec373781fc05363925f1217f5840de60 Mon Sep 17 00:00:00 2001 From: Thiago Resende Date: Tue, 25 Jul 2023 10:51:08 -0300 Subject: [PATCH 161/262] chore(react): remove swcLoaderVersion import in application generator (#18041) --- packages/react/src/generators/application/application.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/react/src/generators/application/application.ts b/packages/react/src/generators/application/application.ts index ab1eec504ba5e..7086e4720084c 100644 --- a/packages/react/src/generators/application/application.ts +++ b/packages/react/src/generators/application/application.ts @@ -33,7 +33,6 @@ import { babelLoaderVersion, nxRspackVersion, nxVersion, - swcLoaderVersion, } from '../../utils/versions'; import { installCommonDependencies } from './lib/install-common-dependencies'; import { extractTsConfigBase } from '../../utils/create-ts-config'; From b6db266c9ee5aa582500107891f8c81ac97d7071 Mon Sep 17 00:00:00 2001 From: Jonathan Cammisuli Date: Tue, 25 Jul 2023 11:11:22 -0400 Subject: [PATCH 162/262] fix(core): handle complex glob patterns within rust (#18242) --- Cargo.lock | 45 +++- .../shared/reference/project-configuration.md | 15 ++ e2e/nx-run/src/cache.test.ts | 48 +++- packages/nx/Cargo.toml | 2 + packages/nx/migrations.json | 6 - .../update-16-5-4/update-output-globs.spec.ts | 77 ------ .../update-16-5-4/update-output-globs.ts | 54 ---- .../nx/src/native/cache/expand_outputs.rs | 2 +- packages/nx/src/native/hasher.rs | 2 +- packages/nx/src/native/utils/glob.rs | 234 ++++++++++++++++-- packages/nx/src/native/walker.rs | 14 +- packages/nx/src/native/watch/types.rs | 4 +- .../src/native/workspace/get_config_files.rs | 9 +- .../workspace/get_nx_workspace_files.rs | 2 +- 14 files changed, 322 insertions(+), 192 deletions(-) delete mode 100644 packages/nx/src/migrations/update-16-5-4/update-output-globs.spec.ts delete mode 100644 packages/nx/src/migrations/update-16-5-4/update-output-globs.ts diff --git a/Cargo.lock b/Cargo.lock index 4dd7491663b52..4275246ff42b9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -33,6 +33,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "aho-corasick" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" +dependencies = [ + "memchr", +] + [[package]] name = "allocator-api2" version = "0.2.14" @@ -155,7 +164,7 @@ checksum = "c3d4260bcc2e8fc9df1eac4919a720effeb63a3f0952f5bf4944adfa18897f09" dependencies = [ "memchr", "once_cell", - "regex-automata", + "regex-automata 0.1.10", "serde", ] @@ -740,7 +749,7 @@ version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc" dependencies = [ - "aho-corasick", + "aho-corasick 0.7.20", "bstr", "fnv", "log", @@ -1067,7 +1076,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" dependencies = [ - "regex-automata", + "regex-automata 0.1.10", ] [[package]] @@ -1343,7 +1352,9 @@ dependencies = [ "napi", "napi-build", "napi-derive", + "once_cell", "rayon", + "regex", "swc_common", "swc_ecma_ast", "swc_ecma_dep_graph", @@ -1652,13 +1663,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.7.0" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a" +checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575" dependencies = [ - "aho-corasick", + "aho-corasick 1.0.2", "memchr", - "regex-syntax", + "regex-automata 0.3.3", + "regex-syntax 0.7.4", ] [[package]] @@ -1667,7 +1679,18 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" dependencies = [ - "regex-syntax", + "regex-syntax 0.6.28", +] + +[[package]] +name = "regex-automata" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310" +dependencies = [ + "aho-corasick 1.0.2", + "memchr", + "regex-syntax 0.7.4", ] [[package]] @@ -1676,6 +1699,12 @@ version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" +[[package]] +name = "regex-syntax" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" + [[package]] name = "rustc-hash" version = "1.1.0" diff --git a/docs/shared/reference/project-configuration.md b/docs/shared/reference/project-configuration.md index aa16a5233bd8a..9331f12df6690 100644 --- a/docs/shared/reference/project-configuration.md +++ b/docs/shared/reference/project-configuration.md @@ -328,6 +328,21 @@ But if the above is not possible, globs (parsed by the [GlobSet](https://docs.rs } ``` +More advanced patterns can be used to exclude files and folders in a single line + +```json +{ + "targets": { + "build-js": { + "outputs": ["{workspaceRoot}/dist/libs/!(cache|.next)/**/*.{js,map}"] + }, + "build-css": { + "outputs": ["{workspaceRoot}/dist/libs/mylib/**/!(secondary).css"] + } + } +} +``` + ### dependsOn Targets can depend on other targets. This is the relevant portion of the configuration file: diff --git a/e2e/nx-run/src/cache.test.ts b/e2e/nx-run/src/cache.test.ts index cbebdc873770d..af2a0a044c718 100644 --- a/e2e/nx-run/src/cache.test.ts +++ b/e2e/nx-run/src/cache.test.ts @@ -1,10 +1,12 @@ import { cleanupProject, + directoryExists, listFiles, newProject, readFile, rmDist, runCLI, + tmpProjPath, uniq, updateFile, updateJson, @@ -157,18 +159,23 @@ describe('cache', () => { updateProjectConfig(mylib, (c) => { c.targets.build = { executor: 'nx:run-commands', - outputs: ['{workspaceRoot}/dist/*.{txt,md}'], + outputs: ['{workspaceRoot}/dist/!(.next)/**/!(z|x).(txt|md)'], options: { commands: [ 'rm -rf dist', 'mkdir dist', - 'echo a > dist/a.txt', - 'echo b > dist/b.txt', - 'echo c > dist/c.txt', - 'echo d > dist/d.txt', - 'echo e > dist/e.txt', - 'echo f > dist/f.md', - 'echo g > dist/g.html', + 'mkdir dist/apps', + 'mkdir dist/.next', + 'echo a > dist/apps/a.txt', + 'echo b > dist/apps/b.txt', + 'echo c > dist/apps/c.txt', + 'echo d > dist/apps/d.txt', + 'echo e > dist/apps/e.txt', + 'echo f > dist/apps/f.md', + 'echo g > dist/apps/g.html', + 'echo h > dist/.next/h.txt', + 'echo x > dist/apps/x.txt', + 'echo z > dist/apps/z.md', ], parallel: false, }, @@ -183,7 +190,10 @@ describe('cache', () => { // Rerun without touching anything const rerunWithUntouchedOutputs = runCLI(`build ${mylib}`); expect(rerunWithUntouchedOutputs).toContain('local cache'); - const outputsWithUntouchedOutputs = listFiles('dist'); + const outputsWithUntouchedOutputs = [ + ...listFiles('dist/apps'), + ...listFiles('dist/.next').map((f) => `.next/${f}`), + ]; expect(outputsWithUntouchedOutputs).toContain('a.txt'); expect(outputsWithUntouchedOutputs).toContain('b.txt'); expect(outputsWithUntouchedOutputs).toContain('c.txt'); @@ -191,14 +201,20 @@ describe('cache', () => { expect(outputsWithUntouchedOutputs).toContain('e.txt'); expect(outputsWithUntouchedOutputs).toContain('f.md'); expect(outputsWithUntouchedOutputs).toContain('g.html'); + expect(outputsWithUntouchedOutputs).toContain('.next/h.txt'); + expect(outputsWithUntouchedOutputs).toContain('x.txt'); + expect(outputsWithUntouchedOutputs).toContain('z.md'); // Create a file in the dist that does not match output glob - updateFile('dist/c.ts', ''); + updateFile('dist/apps/c.ts', ''); // Rerun const rerunWithNewUnrelatedFile = runCLI(`build ${mylib}`); expect(rerunWithNewUnrelatedFile).toContain('local cache'); - const outputsAfterAddingUntouchedFileAndRerunning = listFiles('dist'); + const outputsAfterAddingUntouchedFileAndRerunning = [ + ...listFiles('dist/apps'), + ...listFiles('dist/.next').map((f) => `.next/${f}`), + ]; expect(outputsAfterAddingUntouchedFileAndRerunning).toContain('a.txt'); expect(outputsAfterAddingUntouchedFileAndRerunning).toContain('b.txt'); expect(outputsAfterAddingUntouchedFileAndRerunning).toContain('c.txt'); @@ -206,6 +222,11 @@ describe('cache', () => { expect(outputsAfterAddingUntouchedFileAndRerunning).toContain('e.txt'); expect(outputsAfterAddingUntouchedFileAndRerunning).toContain('f.md'); expect(outputsAfterAddingUntouchedFileAndRerunning).toContain('g.html'); + expect(outputsAfterAddingUntouchedFileAndRerunning).toContain( + '.next/h.txt' + ); + expect(outputsAfterAddingUntouchedFileAndRerunning).toContain('x.txt'); + expect(outputsAfterAddingUntouchedFileAndRerunning).toContain('z.md'); expect(outputsAfterAddingUntouchedFileAndRerunning).toContain('c.ts'); // Clear Dist @@ -214,7 +235,8 @@ describe('cache', () => { // Rerun const rerunWithoutOutputs = runCLI(`build ${mylib}`); expect(rerunWithoutOutputs).toContain('read the output from the cache'); - const outputsWithoutOutputs = listFiles('dist'); + const outputsWithoutOutputs = listFiles('dist/apps'); + expect(directoryExists(`${tmpProjPath()}/dist/.next`)).toBe(false); expect(outputsWithoutOutputs).toContain('a.txt'); expect(outputsWithoutOutputs).toContain('b.txt'); expect(outputsWithoutOutputs).toContain('c.txt'); @@ -223,6 +245,8 @@ describe('cache', () => { expect(outputsWithoutOutputs).toContain('f.md'); expect(outputsWithoutOutputs).not.toContain('c.ts'); expect(outputsWithoutOutputs).not.toContain('g.html'); + expect(outputsWithoutOutputs).not.toContain('x.txt'); + expect(outputsWithoutOutputs).not.toContain('z.md'); }); it('should use consider filesets when hashing', async () => { diff --git a/packages/nx/Cargo.toml b/packages/nx/Cargo.toml index 286a0e7b450ad..dc4e73bd37c46 100644 --- a/packages/nx/Cargo.toml +++ b/packages/nx/Cargo.toml @@ -13,8 +13,10 @@ hashbrown = { version = "0.14.0", features = ["rayon"] } ignore = '0.4' ignore-files = "1.3.0" itertools = "0.10.5" +once_cell = "1.18.0" napi = { version = '2.12.6', default-features = false, features = ['anyhow', 'napi4', 'tokio_rt'] } napi-derive = '2.9.3' +regex = "1.9.1" rayon = "1.7.0" thiserror = "1.0.40" tokio = { version = "1.28.2", features = ["fs"] } diff --git a/packages/nx/migrations.json b/packages/nx/migrations.json index 6e74b4d901043..f287f739d45ba 100644 --- a/packages/nx/migrations.json +++ b/packages/nx/migrations.json @@ -77,12 +77,6 @@ "version": "16.2.0-beta.0", "description": "Remove outputPath from run commands", "implementation": "./src/migrations/update-16-2-0/remove-run-commands-output-path" - }, - "16.5.4-update-output-globs": { - "cli": "nx", - "version": "16.5.4-beta.0", - "description": "Update outdated non-standard globs to unix standard", - "implementation": "./src/migrations/update-16-5-4/update-output-globs" } } } diff --git a/packages/nx/src/migrations/update-16-5-4/update-output-globs.spec.ts b/packages/nx/src/migrations/update-16-5-4/update-output-globs.spec.ts deleted file mode 100644 index 6798e3ad7bb8a..0000000000000 --- a/packages/nx/src/migrations/update-16-5-4/update-output-globs.spec.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { createTreeWithEmptyWorkspace } from '../../generators/testing-utils/create-tree-with-empty-workspace'; -import { TargetConfiguration } from '../../config/workspace-json-project-json'; -import { - addProjectConfiguration, - readProjectConfiguration, -} from '../../generators/utils/project-configuration'; -import updateOutputsGlobs from './update-output-globs'; -import { readJson, updateJson } from '../../generators/utils/json'; -import { NxJsonConfiguration } from '../../config/nx-json'; - -describe('update output globs', () => { - it('should update output globs', () => { - const tree = createTreeWithEmptyWorkspace(); - const targets: Record = { - build: { - outputs: ['{options.outputPath}', 'dist/apps/my-app/*.(js|map|ts)'], - }, - lint: {}, - test: { - outputs: ['dist/apps/my-app/main.(js|map|ts)'], - }, - run: { - outputs: ['dist/apps/my-app'], - }, - }; - addProjectConfiguration(tree, 'my-app', { - root: 'apps/my-app', - targets, - }); - - updateJson(tree, 'nx.json', (json) => { - json.targetDefaults = { - lint: { - outputs: ['dist/apps/my-app', '*.(js|map|ts)'], - }, - }; - return json; - }); - - updateOutputsGlobs(tree); - - const migratedTargets = readProjectConfiguration(tree, 'my-app').targets; - expect(migratedTargets).toMatchInlineSnapshot(` - { - "build": { - "outputs": [ - "{options.outputPath}", - "dist/apps/my-app/*.{js,map,ts}", - ], - }, - "lint": {}, - "run": { - "outputs": [ - "dist/apps/my-app", - ], - }, - "test": { - "outputs": [ - "dist/apps/my-app/main.{js,map,ts}", - ], - }, - } - `); - - const nxJson = readJson(tree, 'nx.json'); - expect(nxJson.targetDefaults).toMatchInlineSnapshot(` - { - "lint": { - "outputs": [ - "dist/apps/my-app", - "*.{js,map,ts}", - ], - }, - } - `); - }); -}); diff --git a/packages/nx/src/migrations/update-16-5-4/update-output-globs.ts b/packages/nx/src/migrations/update-16-5-4/update-output-globs.ts deleted file mode 100644 index 47803469a4c3f..0000000000000 --- a/packages/nx/src/migrations/update-16-5-4/update-output-globs.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { Tree } from '../../generators/tree'; -import { - getProjects, - updateProjectConfiguration, -} from '../../generators/utils/project-configuration'; -import { formatChangedFilesWithPrettierIfAvailable } from '../../generators/internal-utils/format-changed-files-with-prettier-if-available'; -import { TargetConfiguration } from '../../config/workspace-json-project-json'; -import { updateJson } from '../../generators/utils/json'; -import { NxJsonConfiguration } from '../../config/nx-json'; - -function replaceOutput(output: string) { - // replace {projectRoot}/folder/*.(js|map|ts) to {projectRoot}/folder/*.{js,map,ts} - const regex = /\(([^)]+)\)/g; - return output.replace(regex, (match, group1) => { - let replacements = group1.split('|').join(','); - return `{${replacements}}`; - }); -} - -export default async function updateOutputsGlobs(tree: Tree) { - for (const [projectName, projectConfiguration] of getProjects( - tree - ).entries()) { - for (const [targetName, targetConfiguration] of Object.entries( - projectConfiguration.targets ?? {} - )) { - if (!Array.isArray(targetConfiguration.outputs)) { - continue; - } - - targetConfiguration.outputs = - targetConfiguration.outputs.map(replaceOutput); - } - updateProjectConfiguration(tree, projectName, projectConfiguration); - } - - if (tree.exists('nx.json')) { - updateJson(tree, 'nx.json', (json) => { - for (const [, targetConfiguration] of Object.entries( - json.targetDefaults ?? {} - )) { - if (!Array.isArray(targetConfiguration.outputs)) { - continue; - } - - targetConfiguration.outputs = - targetConfiguration.outputs.map(replaceOutput); - } - return json; - }); - } - - await formatChangedFilesWithPrettierIfAvailable(tree); -} diff --git a/packages/nx/src/native/cache/expand_outputs.rs b/packages/nx/src/native/cache/expand_outputs.rs index b039b92ba12d2..e203bdf44c80a 100644 --- a/packages/nx/src/native/cache/expand_outputs.rs +++ b/packages/nx/src/native/cache/expand_outputs.rs @@ -19,7 +19,7 @@ pub fn expand_outputs(directory: String, entries: Vec) -> anyhow::Result return Ok(existing_paths); } - let glob_set = build_glob_set(not_found)?; + let glob_set = build_glob_set(¬_found)?; let found_paths = nx_walker_sync(directory) .filter_map(|path| { if glob_set.is_match(&path) { diff --git a/packages/nx/src/native/hasher.rs b/packages/nx/src/native/hasher.rs index 0b3fd9e3080b8..911deb54250c4 100644 --- a/packages/nx/src/native/hasher.rs +++ b/packages/nx/src/native/hasher.rs @@ -43,7 +43,7 @@ fn hash_files_matching_globs( directory: String, glob_patterns: Vec, ) -> anyhow::Result> { - let glob_set = build_glob_set(glob_patterns)?; + let glob_set = build_glob_set(&glob_patterns)?; let mut hashes = nx_walker(directory, move |receiver| { let mut collection: Vec = Vec::new(); diff --git a/packages/nx/src/native/utils/glob.rs b/packages/nx/src/native/utils/glob.rs index 1fd47db978bb9..f874beb9be5e0 100644 --- a/packages/nx/src/native/utils/glob.rs +++ b/packages/nx/src/native/utils/glob.rs @@ -1,56 +1,260 @@ use globset::{GlobBuilder, GlobSet, GlobSetBuilder}; +use once_cell::sync::Lazy; +use regex::Regex; +use std::fmt::Debug; +use std::path::Path; +use tracing::trace; -pub(crate) fn build_glob_set(globs: Vec) -> anyhow::Result { - let mut glob_set_builder = GlobSetBuilder::new(); - for glob in globs { - let glob = GlobBuilder::new(&glob) +pub struct NxGlobSetBuilder { + included_globs: GlobSetBuilder, + excluded_globs: GlobSetBuilder, +} + +impl NxGlobSetBuilder { + pub fn new>(globs: &[S]) -> anyhow::Result { + let mut glob_set_builder = NxGlobSetBuilder { + included_globs: GlobSetBuilder::new(), + excluded_globs: GlobSetBuilder::new(), + }; + let mut globs: Vec<&str> = globs.iter().map(|s| s.as_ref()).collect(); + globs.sort(); + for glob in globs { + glob_set_builder.add(glob)?; + } + Ok(glob_set_builder) + } + + pub fn add(&mut self, glob: &str) -> anyhow::Result<&mut NxGlobSetBuilder> { + let negated = glob.starts_with('!'); + let glob_string = glob.strip_prefix('!').unwrap_or(glob).to_string(); + + let glob_string = if glob_string.ends_with('/') { + format!("{}**", glob_string) + } else { + glob_string + }; + + let glob = GlobBuilder::new(&glob_string) .literal_separator(true) .build() .map_err(anyhow::Error::from)?; - glob_set_builder.add(glob); + + if negated { + self.excluded_globs.add(glob); + } else { + self.included_globs.add(glob); + } + + Ok(self) + } + + pub fn build(&self) -> anyhow::Result { + Ok(NxGlobSet { + excluded_globs: self.excluded_globs.build()?, + included_globs: self.included_globs.build()?, + }) } +} - glob_set_builder.build().map_err(anyhow::Error::from) +pub struct NxGlobSet { + included_globs: GlobSet, + excluded_globs: GlobSet, +} +impl NxGlobSet { + pub fn is_match>(&self, path: P) -> bool { + self.included_globs.is_match(path.as_ref()) && !self.excluded_globs.is_match(path.as_ref()) + } +} + +pub(crate) fn build_glob_set + Debug>(globs: &[S]) -> anyhow::Result { + let result = globs + .iter() + .map(|s| convert_glob(s.as_ref())) + .collect::>>()? + .into_iter() + .flatten() + .collect::>(); + + trace!(?globs, ?result, "converted globs to result"); + + NxGlobSetBuilder::new(&result)?.build() +} + +// path/!(cache)/** +static NEGATIVE_DIR_REGEX: Lazy = Lazy::new(|| Regex::new(r"!\{(.*?)}").unwrap()); +// path/**/(subdir1|subdir2)/*.(js|ts) +static MULTI_PATTERNS_REGEX: Lazy = Lazy::new(|| Regex::new(r"\((.*?)\)").unwrap()); + +/// Converts a glob string to a list of globs +/// e.g. `path/!(cache)/**` -> `path/**`, `!path/cache/**` +fn convert_glob(glob: &str) -> anyhow::Result> { + // If there are no negations or multiple patterns, return the glob as is + if !glob.contains('!') && !glob.contains('|') && !glob.contains('(') { + return Ok(vec![glob.to_string()]); + } + + let glob = MULTI_PATTERNS_REGEX.replace_all(glob, |caps: ®ex::Captures| { + format!("{{{}}}", &caps[1].replace('|', ",")) + }); + + let mut globs: Vec = Vec::new(); + + globs.push(NEGATIVE_DIR_REGEX.replace_all(&glob, "*").into()); + + let matches: Vec<_> = NEGATIVE_DIR_REGEX.find_iter(&glob).collect(); + + if matches.len() == 1 { + globs.push(format!("!{}", glob.replace('!', ""))); + } else { + for matched in matches { + let a = glob.replace(matched.as_str(), "*"); + globs.push(format!("!{}", a.replace('!', ""))); + } + } + + Ok(globs) } #[cfg(test)] mod test { use super::*; + use std::assert_eq; + + #[test] + fn should_convert_globs() { + let full_convert = + convert_glob("dist/!(cache|cache2)/**/!(README|LICENSE).(js|ts)").unwrap(); + assert_eq!( + full_convert, + [ + "dist/*/**/*.{js,ts}", + "!dist/*/**/{README,LICENSE}.{js,ts}", + "!dist/{cache,cache2}/**/*.{js,ts}", + ] + ); + + let no_dirs = convert_glob("dist/**/!(README|LICENSE).(js|ts)").unwrap(); + assert_eq!( + no_dirs, + ["dist/**/*.{js,ts}", "!dist/**/{README,LICENSE}.{js,ts}"] + ); + + let no_files = convert_glob("dist/!(cache|cache2)/**/*.(js|ts)").unwrap(); + assert_eq!( + no_files, + ["dist/*/**/*.{js,ts}", "!dist/{cache,cache2}/**/*.{js,ts}"] + ); + + let no_extensions = convert_glob("dist/!(cache|cache2)/**/*.js").unwrap(); + assert_eq!( + no_extensions, + ["dist/*/**/*.js", "!dist/{cache,cache2}/**/*.js"] + ); + + let no_patterns = convert_glob("dist/**/*.js").unwrap(); + assert_eq!(no_patterns, ["dist/**/*.js",]); + } #[test] fn should_detect_package_json() { - let glob_set = build_glob_set(vec![String::from("packages/*/package.json")]).unwrap(); + let glob_set = build_glob_set(&["packages/*/package.json"]).unwrap(); assert!(glob_set.is_match("packages/nx/package.json")) } #[test] fn should_not_detect_deeply_nested_package_json() { - let glob_set = build_glob_set(vec![String::from("packages/*/package.json")]).unwrap(); + let glob_set = build_glob_set(&["packages/*/package.json"]).unwrap(); assert!(!glob_set.is_match("packages/nx/test-files/package.json")) } #[test] fn should_detect_deeply_nested_package_json() { - let glob_set = build_glob_set(vec![String::from("packages/**/package.json")]).unwrap(); + let glob_set = build_glob_set(&["packages/**/package.json"]).unwrap(); assert!(glob_set.is_match("packages/nx/test-files/package.json")) } #[test] fn should_detect_node_modules() { - let glob_set = build_glob_set(vec![String::from("**/node_modules")]).unwrap(); + let glob_set = build_glob_set(&["**/node_modules"]).unwrap(); assert!(glob_set.is_match("node_modules")); assert!(glob_set.is_match("packages/nx/node_modules")); } #[test] fn should_not_detect_root_plugin_configs() { - let glob_set = build_glob_set(vec![ - // String::from("!(Cargo.toml)"), - String::from("*/**/Cargo.toml"), - ]) - .unwrap(); + let glob_set = build_glob_set(&["*/**/Cargo.toml"]).unwrap(); assert!(glob_set.is_match("packages/a/Cargo.toml")); assert!(glob_set.is_match("a/Cargo.toml")); assert!(!glob_set.is_match("Cargo.toml")) } + + #[test] + fn should_handle_negated_globs() { + let glob_set = build_glob_set(&["!nested/ignore/", "nested/"]).unwrap(); + assert!(!glob_set.is_match("file.map")); + assert!(!glob_set.is_match("nested/ignore/file.js")); + assert!(!glob_set.is_match("another-nested/nested/file.ts")); + assert!(glob_set.is_match("nested/file.js")); + assert!(glob_set.is_match("nested/nested/file.ts")); + + let glob_set = build_glob_set(&["nested/", "!nested/*.{css,map}"]).unwrap(); + assert!(glob_set.is_match("nested/file.js")); + assert!(glob_set.is_match("nested/file.ts")); + assert!(!glob_set.is_match("nested/file.css")); + assert!(!glob_set.is_match("nested/file.map")); + + let glob_set = build_glob_set(&["!nested/**/ignore/", "nested/**"]).unwrap(); + assert!(glob_set.is_match("nested/nested/file.js")); + assert!(!glob_set.is_match("nested/ignore/file.ts")); + assert!(!glob_set.is_match("nested/nested/ignore/file.ts")); + } + + #[test] + fn should_handle_multiple_globs() { + let glob_set = build_glob_set(&["nested/", "doesnt-exist/"]).unwrap(); + assert!(glob_set.is_match("nested/file.js")); + assert!(!glob_set.is_match("file.js")); + } + + #[test] + fn should_handle_complex_patterns() { + // let glob_set = + // build_glob_set(&["dist/!(cache|cache2)/**/!(README|LICENSE).(txt|md)"]).unwrap(); + // + // // matches + // assert!(glob_set.is_match("dist/nested/file.txt")); + // assert!(glob_set.is_match("dist/nested/file.md")); + // // no matches + // assert!(!glob_set.is_match("dist/file.txt")); + // assert!(!glob_set.is_match("dist/cache/nested/README.txt")); + // assert!(!glob_set.is_match("dist/nested/LICENSE.md")); + // assert!(!glob_set.is_match("dist/cache/file.txt")); + // assert!(!glob_set.is_match("dist/cache2/file.txt")); + // assert!(!glob_set.is_match("dist/cache2/README.txt")); + // assert!(!glob_set.is_match("dist/LICENSE.md")); + // assert!(!glob_set.is_match("dist/README.txt")); + + let glob_set = build_glob_set(&["dist/*.(js|ts)"]).unwrap(); + // matches + assert!(glob_set.is_match("dist/file.js")); + assert!(glob_set.is_match("dist/file.ts")); + //no matches + assert!(!glob_set.is_match("dist/file.txt")); + assert!(!glob_set.is_match("dist/nested/file.js")); + + let glob_set = build_glob_set(&["dist/**/!(main).(js|ts)"]).unwrap(); + // matches + assert!(glob_set.is_match("dist/file.js")); + //no matches + assert!(!glob_set.is_match("dist/main.js")); + + let glob_set = build_glob_set(&["dist/!(main|cache)/"]).unwrap(); + // matches + assert!(glob_set.is_match("dist/nested/")); + // no matches + assert!(!glob_set.is_match("dist/main.js")); + assert!(!glob_set.is_match("dist/file.js")); + assert!(!glob_set.is_match("dist/cache/")); + assert!(!glob_set.is_match("dist/main/")); + } } diff --git a/packages/nx/src/native/walker.rs b/packages/nx/src/native/walker.rs index d017b7db7b656..0f79f292c9f6b 100644 --- a/packages/nx/src/native/walker.rs +++ b/packages/nx/src/native/walker.rs @@ -17,11 +17,8 @@ where { let base_dir: PathBuf = directory.as_ref().into(); - let ignore_glob_set = build_glob_set(vec![ - String::from("**/node_modules"), - String::from("**/.git"), - ]) - .expect("These static ignores always build"); + let ignore_glob_set = + build_glob_set(&["**/node_modules", "**/.git"]).expect("These static ignores always build"); // Use WalkDir instead of ignore::WalkBuilder because it's faster WalkDir::new(&base_dir) @@ -47,11 +44,8 @@ where let directory = directory.as_ref(); let nx_ignore = directory.join(".nxignore"); - let ignore_glob_set = build_glob_set(vec![ - String::from("**/node_modules"), - String::from("**/.git"), - ]) - .expect("These static ignores always build"); + let ignore_glob_set = + build_glob_set(&["**/node_modules", "**/.git"]).expect("These static ignores always build"); let mut walker = WalkBuilder::new(directory); walker.hidden(false); diff --git a/packages/nx/src/native/watch/types.rs b/packages/nx/src/native/watch/types.rs index 88fa2b0f2df4e..4a4453a3ebc22 100644 --- a/packages/nx/src/native/watch/types.rs +++ b/packages/nx/src/native/watch/types.rs @@ -2,8 +2,6 @@ use napi::bindgen_prelude::*; use std::path::PathBuf; use tracing::trace; -use watchexec_events::filekind::ModifyKind::Name; -use watchexec_events::filekind::RenameMode; use watchexec_events::{Event, Tag}; #[napi(string_enum)] @@ -96,6 +94,8 @@ impl From<&Event> for WatchEventInternal { #[cfg(not(target_os = "macos"))] { use watchexec_events::filekind::FileEventKind; + use watchexec_events::filekind::ModifyKind::Name; + use watchexec_events::filekind::RenameMode; match event_kind { FileEventKind::Create(_) => EventType::create, diff --git a/packages/nx/src/native/workspace/get_config_files.rs b/packages/nx/src/native/workspace/get_config_files.rs index 518cc3b60827f..13ed96dd7b49c 100644 --- a/packages/nx/src/native/workspace/get_config_files.rs +++ b/packages/nx/src/native/workspace/get_config_files.rs @@ -1,7 +1,6 @@ -use crate::native::utils::glob::build_glob_set; +use crate::native::utils::glob::{build_glob_set, NxGlobSet}; use crate::native::utils::path::Normalize; use crate::native::walker::nx_walker; -use globset::GlobSet; use napi::JsObject; use std::collections::hash_map::Entry; @@ -19,7 +18,7 @@ pub fn get_project_configurations( where ConfigurationParser: Fn(Vec) -> napi::Result>, { - let globs = build_glob_set(globs)?; + let globs = build_glob_set(&globs)?; let config_paths: Vec = nx_walker(workspace_root, move |rec| { let mut config_paths: HashMap = HashMap::new(); for (path, _) in rec { @@ -38,7 +37,7 @@ where pub fn insert_config_file_into_map( path: PathBuf, config_paths: &mut HashMap, - globs: &GlobSet, + globs: &NxGlobSet, ) { if globs.is_match(&path) { let parent = path.parent().unwrap_or_else(|| Path::new("")).to_path_buf(); @@ -78,7 +77,7 @@ mod test { #[test] fn should_insert_config_files_properly() { let mut config_paths: HashMap = HashMap::new(); - let globs = build_glob_set(vec!["**/*".into()]).unwrap(); + let globs = build_glob_set(&["**/*"]).unwrap(); insert_config_file_into_map(PathBuf::from("project.json"), &mut config_paths, &globs); insert_config_file_into_map(PathBuf::from("package.json"), &mut config_paths, &globs); diff --git a/packages/nx/src/native/workspace/get_nx_workspace_files.rs b/packages/nx/src/native/workspace/get_nx_workspace_files.rs index af90b926ec34c..92edc5d536c5c 100644 --- a/packages/nx/src/native/workspace/get_nx_workspace_files.rs +++ b/packages/nx/src/native/workspace/get_nx_workspace_files.rs @@ -112,7 +112,7 @@ fn create_root_map( type WorkspaceData = (HashSet, Vec); fn get_file_data(workspace_root: &str, globs: Vec) -> anyhow::Result { - let globs = build_glob_set(globs)?; + let globs = build_glob_set(&globs)?; let (projects, file_data) = nx_walker(workspace_root, move |rec| { let mut projects: HashMap = HashMap::new(); let mut file_hashes: Vec = vec![]; From 0957a9921563790bab5a88826ce60c917697d3c2 Mon Sep 17 00:00:00 2001 From: Juri Strumpflohner Date: Tue, 25 Jul 2023 17:12:14 +0200 Subject: [PATCH 163/262] chore(repo): increase Verdaccio fail limits (#18286) --- .verdaccio/config.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.verdaccio/config.yml b/.verdaccio/config.yml index 81ff6fb0d5d50..1293b915662c4 100644 --- a/.verdaccio/config.yml +++ b/.verdaccio/config.yml @@ -10,9 +10,13 @@ uplinks: npmjs: url: https://registry.npmjs.org/ maxage: 60m + max_fails: 20 + fail_timeout: 2m yarn: url: https://registry.yarnpkg.com maxage: 60m + max_fails: 20 + fail_timeout: 2m packages: '@*/*': From 2f59796ac0577dcc3a63cd7be0e23132be45b922 Mon Sep 17 00:00:00 2001 From: Emily Xiong Date: Tue, 25 Jul 2023 11:27:54 -0400 Subject: [PATCH 164/262] chore(core): move calculateDefaultProjectName out of workspaces (#18225) --- .../src/executors/read-target-options.ts | 21 +++-- packages/nx/src/command-line/exec/exec.ts | 2 +- .../nx/src/command-line/generate/generate.ts | 4 +- .../command-line/generate/generator-utils.ts | 1 - packages/nx/src/command-line/run/run-one.ts | 42 +--------- .../calculate-default-project-name.spec.ts | 81 +++++++++++++++++++ .../config/calculate-default-project-name.ts | 57 +++++++++++++ packages/nx/src/config/workspaces.ts | 46 ----------- packages/nx/src/devkit-internals.ts | 1 + 9 files changed, 160 insertions(+), 95 deletions(-) create mode 100644 packages/nx/src/config/calculate-default-project-name.spec.ts create mode 100644 packages/nx/src/config/calculate-default-project-name.ts diff --git a/packages/devkit/src/executors/read-target-options.ts b/packages/devkit/src/executors/read-target-options.ts index 4c7417f5739d6..bf9758eb477ac 100644 --- a/packages/devkit/src/executors/read-target-options.ts +++ b/packages/devkit/src/executors/read-target-options.ts @@ -4,7 +4,8 @@ import type { ExecutorContext } from 'nx/src/config/misc-interfaces'; import { combineOptionsForExecutor } from 'nx/src/utils/params'; import { requireNx } from '../../nx'; -const { Workspaces, getExecutorInformation } = requireNx(); +const { Workspaces, getExecutorInformation, calculateDefaultProjectName } = + requireNx(); /** * Reads and combines options for a given target. @@ -27,11 +28,19 @@ export function readTargetOptions( : // TODO(v18): remove readExecutor. This is to be backwards compatible with Nx 16.5 and below. (ws as any).readExecutor(nodeModule, executorName); - const defaultProject = ws.calculateDefaultProjectName( - context.cwd, - { version: 2, projects: context.projectsConfigurations.projects }, - context.nxJsonConfiguration - ); + const defaultProject = calculateDefaultProjectName + ? calculateDefaultProjectName( + context.cwd, + context.root, + { version: 2, projects: context.projectsConfigurations.projects }, + context.nxJsonConfiguration + ) + : // TODO(v18): remove calculateDefaultProjectName. This is to be backwards compatible with Nx 16.5 and below. + (ws as any).calculateDefaultProjectName( + context.cwd, + { version: 2, projects: context.projectsConfigurations.projects }, + context.nxJsonConfiguration + ); return combineOptionsForExecutor( {}, diff --git a/packages/nx/src/command-line/exec/exec.ts b/packages/nx/src/command-line/exec/exec.ts index 8d52baee55c7c..fef4670c64fa7 100644 --- a/packages/nx/src/command-line/exec/exec.ts +++ b/packages/nx/src/command-line/exec/exec.ts @@ -18,7 +18,7 @@ import { output } from '../../utils/output'; import { PackageJson } from '../../utils/package-json'; import { getPackageManagerCommand } from '../../utils/package-manager'; import { workspaceRoot } from '../../utils/workspace-root'; -import { calculateDefaultProjectName } from '../run/run-one'; +import { calculateDefaultProjectName } from '../../config/calculate-default-project-name'; export async function nxExecCommand( args: Record diff --git a/packages/nx/src/command-line/generate/generate.ts b/packages/nx/src/command-line/generate/generate.ts index 8804f0b37397d..57b4c901f3830 100644 --- a/packages/nx/src/command-line/generate/generate.ts +++ b/packages/nx/src/command-line/generate/generate.ts @@ -20,6 +20,7 @@ import { getLocalWorkspacePlugins } from '../../utils/plugins/local-plugins'; import { printHelp } from '../../utils/print-help'; import { workspaceRoot } from '../../utils/workspace-root'; import { NxJsonConfiguration } from '../../config/nx-json'; +import { calculateDefaultProjectName } from '../../config/calculate-default-project-name'; import { findInstalledPlugins } from '../../utils/plugins/installed-plugins'; import type { Arguments } from 'yargs'; import { output } from '../../utils/output'; @@ -359,8 +360,9 @@ export async function generate(cwd: string, args: { [k: string]: any }) { nxJsonConfiguration, schema, opts.interactive, - ws.calculateDefaultProjectName( + calculateDefaultProjectName( cwd, + workspaceRoot, projectsConfigurations, nxJsonConfiguration ), diff --git a/packages/nx/src/command-line/generate/generator-utils.ts b/packages/nx/src/command-line/generate/generator-utils.ts index 5712cae6a5884..74c42072a4009 100644 --- a/packages/nx/src/command-line/generate/generator-utils.ts +++ b/packages/nx/src/command-line/generate/generator-utils.ts @@ -10,7 +10,6 @@ import { } from '../../config/schema-utils'; import { readJsonFile } from '../../utils/fileutils'; import { readPluginPackageJson } from '../../utils/nx-plugin'; -import { getNxRequirePaths } from '../../utils/installation-directory'; export function getGeneratorInformation( collectionName: string, diff --git a/packages/nx/src/command-line/run/run-one.ts b/packages/nx/src/command-line/run/run-one.ts index 164241127b7ae..cdb768c6735b0 100644 --- a/packages/nx/src/command-line/run/run-one.ts +++ b/packages/nx/src/command-line/run/run-one.ts @@ -14,11 +14,9 @@ import { NxJsonConfiguration } from '../../config/nx-json'; import { workspaceRoot } from '../../utils/workspace-root'; import { splitTarget } from '../../utils/split-target'; import { output } from '../../utils/output'; -import { - ProjectsConfigurations, - TargetDependencyConfig, -} from '../../config/workspace-json-project-json'; +import { TargetDependencyConfig } from '../../config/workspace-json-project-json'; import { readNxJson } from '../../config/configuration'; +import { calculateDefaultProjectName } from '../../config/calculate-default-project-name'; import { workspaceConfigurationCheck } from '../../utils/workspace-configuration-check'; import { generateGraph } from '../graph/graph'; @@ -175,39 +173,3 @@ function parseRunOneOptions( return res; } - -export function calculateDefaultProjectName( - cwd: string, - root: string, - projectsConfigurations: ProjectsConfigurations, - nxJsonConfiguration: NxJsonConfiguration -) { - if (cwd && /^[A-Z]:/.test(cwd)) { - cwd = cwd.charAt(0).toLowerCase() + cwd.slice(1); - } - - if (root && /^[A-Z]:/.test(root)) { - root = root.charAt(0).toLowerCase() + root.slice(1); - } - - let relativeCwd = cwd.replace(/\\/g, '/').split(root.replace(/\\/g, '/'))[1]; - - relativeCwd = relativeCwd.startsWith('/') - ? relativeCwd.substring(1) - : relativeCwd; - const matchingProject = Object.keys(projectsConfigurations.projects).find( - (p) => { - const projectRoot = projectsConfigurations.projects[p].root; - return ( - relativeCwd == projectRoot || - (relativeCwd == '' && projectRoot == '.') || - relativeCwd.startsWith(`${projectRoot}/`) - ); - } - ); - if (matchingProject) return matchingProject; - return ( - (nxJsonConfiguration.cli as { defaultProjectName: string }) - ?.defaultProjectName || nxJsonConfiguration.defaultProject - ); -} diff --git a/packages/nx/src/config/calculate-default-project-name.spec.ts b/packages/nx/src/config/calculate-default-project-name.spec.ts new file mode 100644 index 0000000000000..5d99b964a4e79 --- /dev/null +++ b/packages/nx/src/config/calculate-default-project-name.spec.ts @@ -0,0 +1,81 @@ +import { + calculateDefaultProjectName, + findMatchingProjectInCwd, +} from './calculate-default-project-name'; + +describe('calculateDefaultProjectName', () => { + describe('findMatchingProjectInCwd', () => { + it('should return matching project if it is found', () => { + const projects = { + 'demo-app': { + name: 'demo-app', + root: 'apps/demo-app', + }, + }; + expect(findMatchingProjectInCwd(projects, 'apps/demo-app')).toEqual( + 'demo-app' + ); + expect( + findMatchingProjectInCwd(projects, 'apps/demo-app/src/main.tsx') + ).toEqual('demo-app'); + }); + + it('should return if it is root project and cwd is also root', () => { + const projects = { + 'demo-app': { + name: 'demo-app', + root: '.', + }, + }; + expect(findMatchingProjectInCwd(projects, '')).toEqual('demo-app'); + expect(findMatchingProjectInCwd(projects, '.')).toEqual('demo-app'); + }); + + it('should return undefined if no matching project is found', () => { + expect( + findMatchingProjectInCwd( + { + 'demo-app': { + name: 'demo-app', + root: 'apps/demo-app', + }, + }, + 'demo-app2' + ) + ).toEqual(undefined); + }); + }); + + it('should return default project if cwd is root', () => { + expect( + calculateDefaultProjectName( + '.', + '.', + { projects: { 'demo-app': { root: 'apps/demo-app' } }, version: 2 }, + { cli: { defaultProjectName: 'demo-app2' } } + ) + ).toEqual('demo-app2'); + }); + + it('should return matching app if cwd is inside an app', () => { + expect( + calculateDefaultProjectName( + 'apps/demo-app', + '.', + { projects: { 'demo-app': { root: 'apps/demo-app' } }, version: 2 }, + { cli: { defaultProjectName: 'demo-app2' } } + ) + ).toEqual('demo-app'); + }); + + it('should return matching app if cwd is at workspace root', () => { + expect( + calculateDefaultProjectName( + 'demo-app', + 'demo-app', + { projects: { 'demo-app': { root: '.' } }, version: 2 }, + { cli: { defaultProjectName: 'demo-app2' } } + ) + ).toEqual('demo-app'); + }); +}); diff --git a/packages/nx/src/config/calculate-default-project-name.ts b/packages/nx/src/config/calculate-default-project-name.ts new file mode 100644 index 0000000000000..ba0ea24f136ad --- /dev/null +++ b/packages/nx/src/config/calculate-default-project-name.ts @@ -0,0 +1,57 @@ +import type { NxJsonConfiguration } from './nx-json'; +import { + ProjectConfiguration, + ProjectsConfigurations, +} from './workspace-json-project-json'; +import { + findProjectForPath, + normalizeProjectRoot, +} from '../project-graph/utils/find-project-for-path'; +import { relative } from 'path'; + +export function calculateDefaultProjectName( + cwd: string, + root: string, + { projects }: ProjectsConfigurations, + nxJson: NxJsonConfiguration +) { + const relativeCwd = relative(root, cwd).replace(/\\/g, '/') ?? null; + if (relativeCwd !== null) { + const matchingProject = findMatchingProjectInCwd(projects, relativeCwd); + // We have found a project + if (matchingProject) { + // That is not at the root + if ( + projects[matchingProject].root !== '.' && + projects[matchingProject].root !== '' + ) { + return matchingProject; + // But its at the root, and NX_DEFAULT_PROJECT is set + } else if (process.env.NX_DEFAULT_PROJECT) { + return process.env.NX_DEFAULT_PROJECT; + // Its root, and NX_DEFAULT_PROJECT is not set + } else { + return matchingProject; + } + } + } + // There was no matching project in cwd. + return ( + process.env.NX_DEFAULT_PROJECT ?? + (nxJson.cli as { defaultProjectName: string })?.defaultProjectName ?? + nxJson?.defaultProject + ); +} + +export function findMatchingProjectInCwd( + projects: { [projectName: string]: ProjectConfiguration }, + relativeCwd: string +): string | undefined { + const projectRootMappings = new Map(); + for (const projectName of Object.keys(projects)) { + const { root } = projects[projectName]; + projectRootMappings.set(normalizeProjectRoot(root), projectName); + } + const matchingProject = findProjectForPath(relativeCwd, projectRootMappings); + return matchingProject; +} diff --git a/packages/nx/src/config/workspaces.ts b/packages/nx/src/config/workspaces.ts index 340e60285a8a1..6c206001b42e4 100644 --- a/packages/nx/src/config/workspaces.ts +++ b/packages/nx/src/config/workspaces.ts @@ -23,10 +23,6 @@ import { } from '../adapter/angular-json'; import { getNxRequirePaths } from '../utils/installation-directory'; import { getIgnoredGlobs } from '../utils/ignore'; -import { - findProjectForPath, - normalizeProjectRoot, -} from '../project-graph/utils/find-project-for-path'; import { readNxJson } from './nx-json'; export class Workspaces { @@ -38,35 +34,6 @@ export class Workspaces { return path.relative(this.root, cwd).replace(/\\/g, '/') || null; } - calculateDefaultProjectName( - cwd: string, - { projects }: ProjectsConfigurations, - nxJson: NxJsonConfiguration - ) { - const relativeCwd = this.relativeCwd(cwd); - if (relativeCwd) { - const matchingProject = findMatchingProjectInCwd(projects, relativeCwd); - // We have found a project - if (matchingProject) { - // That is not at the root - if ( - projects[matchingProject].root !== '.' && - projects[matchingProject].root !== '' - ) { - return matchingProject; - // But its at the root, and NX_DEFAULT_PROJECT is set - } else if (process.env.NX_DEFAULT_PROJECT) { - return process.env.NX_DEFAULT_PROJECT; - // Its root, and NX_DEFAULT_PROJECT is not set - } else { - return matchingProject; - } - } - } - // There was no matching project in cwd. - return process.env.NX_DEFAULT_PROJECT ?? nxJson?.defaultProject; - } - /** * @deprecated */ @@ -156,19 +123,6 @@ export class Workspaces { } } -function findMatchingProjectInCwd( - projects: { [projectName: string]: ProjectConfiguration }, - relativeCwd: string -) { - const projectRootMappings = new Map(); - for (const projectName of Object.keys(projects)) { - const { root } = projects[projectName]; - projectRootMappings.set(normalizeProjectRoot(root), projectName); - } - const matchingProject = findProjectForPath(relativeCwd, projectRootMappings); - return matchingProject; -} - /** * Pulled from toFileName in names from @nx/devkit. * Todo: Should refactor, not duplicate. diff --git a/packages/nx/src/devkit-internals.ts b/packages/nx/src/devkit-internals.ts index fc53181aabd51..0f6bf3e705cae 100644 --- a/packages/nx/src/devkit-internals.ts +++ b/packages/nx/src/devkit-internals.ts @@ -6,3 +6,4 @@ export { createTempNpmDirectory } from './utils/package-manager'; export { getExecutorInformation } from './command-line/run/executor-utils'; export { readNxJson as readNxJsonFromDisk } from './config/nx-json'; +export { calculateDefaultProjectName } from './config/calculate-default-project-name'; From bc85c544eb0a1ca6c71ec8a5f48bee86aa0345c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Jona=C5=A1?= Date: Tue, 25 Jul 2023 17:05:13 +0200 Subject: [PATCH 165/262] fix(nx-dev): update plugins home page redirect-rules --- nx-dev/nx-dev/redirect-rules.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nx-dev/nx-dev/redirect-rules.js b/nx-dev/nx-dev/redirect-rules.js index 37c93a58b3b9a..9f0bed7830f58 100644 --- a/nx-dev/nx-dev/redirect-rules.js +++ b/nx-dev/nx-dev/redirect-rules.js @@ -714,7 +714,7 @@ const makeMoreConceptsSubmenu = { }; const pluginsToExtendNx = { - '/plugins': '/extending-nx', + '/plugins': '/extending-nx/intro/getting-started', '/plugins/:path*': '/extending-nx/:path*', }; From b2763e1cc9093726a74365b9aa7fba98b82dd7bc Mon Sep 17 00:00:00 2001 From: Victor Savkin Date: Tue, 25 Jul 2023 11:56:42 -0400 Subject: [PATCH 166/262] chore(repo): update nx-cloud to 16.2.0-beta.0 (#18301) --- package.json | 2 +- pnpm-lock.yaml | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index c7452a3d4a679..7b6b20b4f0331 100644 --- a/package.json +++ b/package.json @@ -215,7 +215,7 @@ "ng-packagr": "~16.1.0", "node-fetch": "^2.6.7", "nx": "16.6.0-beta.4", - "nx-cloud": "16.1.1", + "nx-cloud": "16.2.0-beta.0", "octokit": "^2.0.14", "open": "^8.4.0", "openai": "~3.3.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0df1eac94c7c7..1f3ce0f1bbd9a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -718,8 +718,8 @@ devDependencies: specifier: 16.6.0-beta.4 version: 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51) nx-cloud: - specifier: 16.1.1 - version: 16.1.1 + specifier: 16.2.0-beta.0 + version: 16.2.0-beta.0 octokit: specifier: ^2.0.14 version: 2.0.14 @@ -6775,10 +6775,10 @@ packages: - webpack dev: true - /@nrwl/nx-cloud@16.1.1: - resolution: {integrity: sha512-iJIPP46+saFZK748FKU4u4YZH+Sv3ZvZPbMwGVMhwqhOYcrlO5aSa0lpilyoN8WuhooKNqcCfiqshx6V577fTg==} + /@nrwl/nx-cloud@16.2.0-beta.0: + resolution: {integrity: sha512-1kObridqdJi6A30J3zYtP5W1kT3PrBarIrUIsmil08NN/v+MbJsdamBm7u1YyES4IgecM9qhYHLw+EWpNalkMQ==} dependencies: - nx-cloud: 16.1.1 + nx-cloud: 16.2.0-beta.0 transitivePeerDependencies: - debug dev: true @@ -20971,11 +20971,11 @@ packages: resolution: {integrity: sha512-NHj4rzRo0tQdijE9ZqAx6kYDcoRwYwSYzCA8MY3JzfxlrvEU0jhnhJT9BhqhJs7I/dKcrDm6TyulaRqZPIhN5g==} dev: true - /nx-cloud@16.1.1: - resolution: {integrity: sha512-Rq7ynvkYzAJ67N3pDqU6cMqwvWP7WXJGP4EFjLxgUrRHNCccqDPggeAqePodfk3nZEUrZB8F5QBKZuuw1DR3oA==} + /nx-cloud@16.2.0-beta.0: + resolution: {integrity: sha512-7ZFF/2mVeXNzSENmshwHKr625LFpKtNlv82emNIFUIj7qEYomuhV2gzZSaOLnGW9w32kkgUQ5TQBYOqKFkMCLQ==} hasBin: true dependencies: - '@nrwl/nx-cloud': 16.1.1 + '@nrwl/nx-cloud': 16.2.0-beta.0 axios: 1.1.3 chalk: 4.1.2 dotenv: 10.0.0 From 2dda1914b53b4bd6daa227de5222d85cee80b77c Mon Sep 17 00:00:00 2001 From: Jason Jean Date: Tue, 25 Jul 2023 12:47:26 -0400 Subject: [PATCH 167/262] chore(core): remove globForProjectFiles (#18288) --- packages/nx/src/config/workspaces.spec.ts | 110 ++++++---------- packages/nx/src/config/workspaces.ts | 121 +----------------- .../generators/utils/project-configuration.ts | 10 +- .../update-15-1-0/set-project-names.ts | 16 +-- packages/nx/src/native/index.d.ts | 2 + packages/nx/src/native/index.js | 3 +- .../src/native/workspace/get_config_files.rs | 22 ++++ .../utils/retrieve-workspace-files.spec.ts} | 12 +- .../utils/retrieve-workspace-files.ts | 92 +++++++++---- packages/nx/src/utils/nx-plugin.ts | 15 +-- 10 files changed, 156 insertions(+), 247 deletions(-) rename packages/nx/src/{config/workspaces.glob-for-project-files.spec.ts => project-graph/utils/retrieve-workspace-files.spec.ts} (58%) diff --git a/packages/nx/src/config/workspaces.spec.ts b/packages/nx/src/config/workspaces.spec.ts index 90e10d357d87c..ed9e39558cfde 100644 --- a/packages/nx/src/config/workspaces.spec.ts +++ b/packages/nx/src/config/workspaces.spec.ts @@ -4,13 +4,8 @@ import { toProjectName, Workspaces, } from './workspaces'; -import { NxJsonConfiguration } from './nx-json'; -import { vol } from 'memfs'; - -import * as fastGlob from 'fast-glob'; import { TargetConfiguration } from './workspace-json-project-json'; - -jest.mock('fs', () => require('memfs').fs); +import { TempFs } from '../utils/testing/temp-fs'; const libConfig = (name) => ({ root: `libs/${name}`, @@ -24,26 +19,16 @@ const packageLibConfig = (root) => ({ }); describe('Workspaces', () => { - let globResults: string[]; + let fs: TempFs; beforeEach(() => { - globResults = [ - 'libs/lib1/package.json', - 'libs/lib1/project.json', - 'libs/lib2/package.json', - 'libs/domain/lib3/package.json', - 'libs/domain/lib4/project.json', - 'libs/domain/lib4/package.json', - ]; - jest.spyOn(fastGlob, 'sync').mockImplementation(() => globResults); + fs = new TempFs('Workspaces'); }); - afterEach(() => { - jest.resetAllMocks(); - vol.reset(); + fs.cleanup(); }); describe('readWorkspaceConfiguration', () => { - it('should be able to inline project configurations', () => { + it('should be able to inline project configurations', async () => { const standaloneConfig = libConfig('lib1'); const config = { @@ -53,46 +38,41 @@ describe('Workspaces', () => { lib2: libConfig('lib2'), }, }; - vol.fromJSON( - { - 'libs/lib1/project.json': JSON.stringify(standaloneConfig), - 'libs/lib2/package.json': JSON.stringify({}), - 'libs/domain/lib3/package.json': JSON.stringify({}), - 'libs/domain/lib4/project.json': JSON.stringify({}), - 'workspace.json': JSON.stringify(config), - }, - '/root' - ); + await fs.createFiles({ + 'libs/lib1/project.json': JSON.stringify(standaloneConfig), + 'libs/lib2/package.json': JSON.stringify({}), + 'libs/domain/lib3/package.json': JSON.stringify({}), + 'libs/domain/lib4/project.json': JSON.stringify({}), + 'workspace.json': JSON.stringify(config), + }); - const workspaces = new Workspaces('/root'); + const workspaces = new Workspaces(fs.tempDir); const resolved = workspaces.readProjectsConfigurations(); expect(resolved.projects.lib1).toEqual(standaloneConfig); }); - it('should build project configurations from glob', () => { + it('should build project configurations from glob', async () => { const lib1Config = libConfig('lib1'); const lib2Config = packageLibConfig('libs/lib2'); const domainPackageConfig = packageLibConfig('libs/domain/lib3'); const domainLibConfig = libConfig('domain/lib4'); - vol.fromJSON( - { - 'libs/lib1/project.json': JSON.stringify(lib1Config), - 'libs/lib1/package.json': JSON.stringify({ name: 'some-other-name' }), - 'libs/lib2/package.json': JSON.stringify({ name: 'lib2' }), - 'libs/domain/lib3/package.json': JSON.stringify({ - name: 'domain-lib3', - }), - 'libs/domain/lib4/project.json': JSON.stringify(domainLibConfig), - 'libs/domain/lib4/package.json': JSON.stringify({}), - 'package.json': JSON.stringify({ - workspaces: ['**/package.json'], - }), - }, - '/root' - ); + await fs.createFiles({ + 'libs/lib1/project.json': JSON.stringify(lib1Config), + 'libs/lib1/package.json': JSON.stringify({ name: 'some-other-name' }), + 'libs/lib2/package.json': JSON.stringify({ name: 'lib2' }), + 'libs/domain/lib3/package.json': JSON.stringify({ + name: 'domain-lib3', + }), + 'libs/domain/lib4/project.json': JSON.stringify(domainLibConfig), + 'libs/domain/lib4/package.json': JSON.stringify({}), + 'package.json': JSON.stringify({ + name: 'package-name', + workspaces: ['**/package.json'], + }), + }); - const workspaces = new Workspaces('/root'); + const workspaces = new Workspaces(fs.tempDir); const { projects } = workspaces.readProjectsConfigurations(); // projects got deduped so the workspace one remained expect(projects['lib1']).toEqual({ @@ -107,34 +87,24 @@ describe('Workspaces', () => { describe('to project name', () => { it('should lowercase names', () => { - const nxJson: NxJsonConfiguration = { - npmScope: '', - workspaceLayout: { - appsDir: 'my-apps', - libsDir: 'packages', - }, - }; const appResults = toProjectName('my-apps/directory/my-app/package.json'); const libResults = toProjectName('packages/directory/MyLib/package.json'); expect(appResults).toEqual('my-app'); expect(libResults).toEqual('mylib'); }); - it('should use the workspace globs in package.json', () => { - globResults = ['packages/my-package/package.json']; - vol.fromJSON( - { - 'packages/my-package/package.json': JSON.stringify({ - name: 'my-package', - }), - 'package.json': JSON.stringify({ - workspaces: ['packages/**'], - }), - }, - '/root2' - ); + it('should use the workspace globs in package.json', async () => { + await fs.createFiles({ + 'packages/my-package/package.json': JSON.stringify({ + name: 'my-package', + }), + 'package.json': JSON.stringify({ + name: 'package-name', + workspaces: ['packages/**'], + }), + }); - const workspaces = new Workspaces('/root2'); + const workspaces = new Workspaces(fs.tempDir); const resolved = workspaces.readProjectsConfigurations(); expect(resolved.projects['my-package']).toEqual({ root: 'packages/my-package', diff --git a/packages/nx/src/config/workspaces.ts b/packages/nx/src/config/workspaces.ts index 6c206001b42e4..8febcdb540a54 100644 --- a/packages/nx/src/config/workspaces.ts +++ b/packages/nx/src/config/workspaces.ts @@ -1,14 +1,13 @@ -import { sync as globSync } from 'fast-glob'; import { existsSync } from 'fs'; import * as path from 'path'; import { basename, dirname, join } from 'path'; -import { performance } from 'perf_hooks'; import { workspaceRoot } from '../utils/workspace-root'; import { readJsonFile, readYamlFile } from '../utils/fileutils'; import { logger, NX_PREFIX } from '../utils/logger'; import { loadNxPlugins, loadNxPluginsSync } from '../utils/nx-plugin'; import type { NxJsonConfiguration, TargetDefaults } from './nx-json'; +import { readNxJson } from './nx-json'; import { ProjectConfiguration, ProjectsConfigurations, @@ -21,9 +20,7 @@ import { mergeAngularJsonAndProjects, shouldMergeAngularProjects, } from '../adapter/angular-json'; -import { getNxRequirePaths } from '../utils/installation-directory'; -import { getIgnoredGlobs } from '../utils/ignore'; -import { readNxJson } from './nx-json'; +import { retrieveProjectConfigurationPaths } from '../project-graph/utils/retrieve-workspace-files'; export class Workspaces { private cachedProjectsConfig: ProjectsConfigurations; @@ -38,7 +35,6 @@ export class Workspaces { * @deprecated */ readProjectsConfigurations(opts?: { - _ignorePluginInference?: boolean; _includeProjectsFromAngularJson?: boolean; }): ProjectsConfigurations { if ( @@ -48,19 +44,10 @@ export class Workspaces { return this.cachedProjectsConfig; } const nxJson = readNxJson(this.root); + const projectPaths = retrieveProjectConfigurationPaths(this.root, nxJson); let projectsConfigurations = buildProjectsConfigurationsFromProjectPaths( nxJson, - globForProjectFiles( - this.root, - opts?._ignorePluginInference - ? [] - : getGlobPatternsFromPlugins( - nxJson, - getNxRequirePaths(this.root), - this.root - ), - nxJson - ), + projectPaths, (path) => readJsonFile(join(this.root, path)) ); if ( @@ -132,9 +119,6 @@ export function toProjectName(fileName: string): string { return parts[parts.length - 1].toLowerCase(); } -let projectGlobCache: string[]; -let projectGlobCacheKey: string; - /** * @deprecated Use getGlobPatternsFromPluginsAsync instead. */ @@ -247,103 +231,6 @@ function removeRelativePath(pattern: string): string { return pattern.startsWith('./') ? pattern.substring(2) : pattern; } -export function globForProjectFiles( - root: string, - pluginsGlobPatterns: string[], - nxJson?: NxJsonConfiguration -) { - // Deal w/ Caching - const cacheKey = [root, ...pluginsGlobPatterns].join(','); - if ( - process.env.NX_PROJECT_GLOB_CACHE !== 'false' && - projectGlobCache && - cacheKey === projectGlobCacheKey - ) { - return projectGlobCache; - } - projectGlobCacheKey = cacheKey; - - const _globPatternsFromPackageManagerWorkspaces = - getGlobPatternsFromPackageManagerWorkspaces(root); - - const globPatternsFromPackageManagerWorkspaces = - _globPatternsFromPackageManagerWorkspaces ?? []; - - const globsToInclude = globPatternsFromPackageManagerWorkspaces.filter( - (glob) => !glob.startsWith('!') - ); - - const globsToExclude = globPatternsFromPackageManagerWorkspaces - .filter((glob) => glob.startsWith('!')) - .map((glob) => glob.substring(1)) - .map((glob) => (glob.startsWith('/') ? glob.substring(1) : glob)); - - const projectGlobPatterns: string[] = [ - 'project.json', - '**/project.json', - ...globsToInclude, - ]; - - projectGlobPatterns.push(...pluginsGlobPatterns); - - const combinedProjectGlobPattern = '{' + projectGlobPatterns.join(',') + '}'; - - performance.mark('start-glob-for-projects'); - /** - * This configures the files and directories which we always want to ignore as part of file watching - * and which we know the location of statically (meaning irrespective of user configuration files). - * This has the advantage of being ignored directly within globSync - * - * Other ignored entries will need to be determined dynamically by reading and evaluating the user's - * .gitignore and .nxignore files below. - */ - - const staticIgnores = [ - 'node_modules', - '**/node_modules', - 'dist', - '.git', - ...globsToExclude, - ...getIgnoredGlobs(root, false), - ]; - - /** - * TODO: This utility has been implemented multiple times across the Nx codebase, - * discuss whether it should be moved to a shared location. - */ - const opts = { - ignore: staticIgnores, - absolute: false, - cwd: root, - dot: true, - suppressErrors: true, - }; - - const globResults = globSync(combinedProjectGlobPattern, opts); - - projectGlobCache = deduplicateProjectFiles(globResults); - - // TODO @vsavkin remove after Nx 16 - if ( - projectGlobCache.length === 0 && - _globPatternsFromPackageManagerWorkspaces === undefined && - nxJson?.extends === 'nx/presets/npm.json' - ) { - output.warn({ - title: - 'Nx could not find any projects. Check if you need to configure workspaces in package.json or pnpm-workspace.yaml', - }); - } - - performance.mark('finish-glob-for-projects'); - performance.measure( - 'glob-for-project-files', - 'start-glob-for-projects', - 'finish-glob-for-projects' - ); - return projectGlobCache; -} - /** * @description Loops through files and reduces them to 1 file per project. * @param files Array of files that may represent projects diff --git a/packages/nx/src/generators/utils/project-configuration.ts b/packages/nx/src/generators/utils/project-configuration.ts index 6a3e5b7b4113e..cd224c530843a 100644 --- a/packages/nx/src/generators/utils/project-configuration.ts +++ b/packages/nx/src/generators/utils/project-configuration.ts @@ -6,8 +6,6 @@ import { import { buildProjectsConfigurationsFromProjectPaths, deduplicateProjectFiles, - getGlobPatternsFromPlugins, - globForProjectFiles, renamePropertyWithStableKeys, } from '../../config/workspaces'; import { joinPathFragments, normalizePath } from '../../utils/path'; @@ -18,7 +16,7 @@ import { readJson, writeJson } from './json'; import { PackageJson } from '../../utils/package-json'; import { readNxJson } from './nx-json'; import { output } from '../../utils/output'; -import { getNxRequirePaths } from '../../utils/installation-directory'; +import { retrieveProjectConfigurationPaths } from '../../project-graph/utils/retrieve-workspace-files'; export { readNxJson, updateNxJson } from './nx-json'; export { @@ -183,11 +181,7 @@ function readAndCombineAllProjectConfigurations(tree: Tree): { } { const nxJson = readNxJson(tree); - const globbedFiles = globForProjectFiles( - tree.root, - getGlobPatternsFromPlugins(nxJson, getNxRequirePaths(tree.root), tree.root), - nxJson - ).map(normalizePath); + const globbedFiles = retrieveProjectConfigurationPaths(tree.root, nxJson); const createdFiles = findCreatedProjectFiles(tree); const deletedFiles = findDeletedProjectFiles(tree); const projectFiles = [...globbedFiles, ...createdFiles].filter( diff --git a/packages/nx/src/migrations/update-15-1-0/set-project-names.ts b/packages/nx/src/migrations/update-15-1-0/set-project-names.ts index 3791d03d37493..d15cd1b5b2c46 100644 --- a/packages/nx/src/migrations/update-15-1-0/set-project-names.ts +++ b/packages/nx/src/migrations/update-15-1-0/set-project-names.ts @@ -1,25 +1,13 @@ import { Tree } from '../../generators/tree'; import { readNxJson } from '../../generators/utils/nx-json'; -import { - getGlobPatternsFromPluginsAsync, - globForProjectFiles, -} from '../../config/workspaces'; import { dirname } from 'path'; import { readJson, writeJson } from '../../generators/utils/json'; import { formatChangedFilesWithPrettierIfAvailable } from '../../generators/internal-utils/format-changed-files-with-prettier-if-available'; -import { getNxRequirePaths } from '../../utils/installation-directory'; +import { retrieveProjectConfigurationPaths } from '../../project-graph/utils/retrieve-workspace-files'; export default async function (tree: Tree) { const nxJson = readNxJson(tree); - const projectFiles = globForProjectFiles( - tree.root, - await getGlobPatternsFromPluginsAsync( - nxJson, - getNxRequirePaths(tree.root), - tree.root - ), - nxJson - ); + const projectFiles = retrieveProjectConfigurationPaths(tree.root, nxJson); const projectJsons = projectFiles.filter((f) => f.endsWith('project.json')); for (let f of projectJsons) { diff --git a/packages/nx/src/native/index.d.ts b/packages/nx/src/native/index.d.ts index a57d3c97b3baf..b78cd8bdd8375 100644 --- a/packages/nx/src/native/index.d.ts +++ b/packages/nx/src/native/index.d.ts @@ -38,6 +38,8 @@ export const enum WorkspaceErrors { Generic = 'Generic' } /** Get workspace config files based on provided globs */ +export function getProjectConfigurationFiles(workspaceRoot: string, globs: Array): Array +/** Get workspace config files based on provided globs */ export function getProjectConfigurations(workspaceRoot: string, globs: Array, parseConfigurations: (arg0: Array) => Record): Record export interface NxWorkspaceFiles { projectFileMap: Record> diff --git a/packages/nx/src/native/index.js b/packages/nx/src/native/index.js index abb3085186c94..d8b0d85111585 100644 --- a/packages/nx/src/native/index.js +++ b/packages/nx/src/native/index.js @@ -246,7 +246,7 @@ if (!nativeBinding) { throw new Error(`Failed to load native binding`) } -const { expandOutputs, remove, copy, hashArray, hashFile, hashFiles, hashFilesMatchingGlobs, ImportResult, findImports, EventType, Watcher, WorkspaceErrors, getProjectConfigurations, getWorkspaceFilesNative } = nativeBinding +const { expandOutputs, remove, copy, hashArray, hashFile, hashFiles, hashFilesMatchingGlobs, ImportResult, findImports, EventType, Watcher, WorkspaceErrors, getProjectConfigurationFiles, getProjectConfigurations, getWorkspaceFilesNative } = nativeBinding module.exports.expandOutputs = expandOutputs module.exports.remove = remove @@ -260,5 +260,6 @@ module.exports.findImports = findImports module.exports.EventType = EventType module.exports.Watcher = Watcher module.exports.WorkspaceErrors = WorkspaceErrors +module.exports.getProjectConfigurationFiles = getProjectConfigurationFiles module.exports.getProjectConfigurations = getProjectConfigurations module.exports.getWorkspaceFilesNative = getWorkspaceFilesNative diff --git a/packages/nx/src/native/workspace/get_config_files.rs b/packages/nx/src/native/workspace/get_config_files.rs index 13ed96dd7b49c..989e63f92c323 100644 --- a/packages/nx/src/native/workspace/get_config_files.rs +++ b/packages/nx/src/native/workspace/get_config_files.rs @@ -7,6 +7,28 @@ use std::collections::hash_map::Entry; use std::collections::HashMap; use std::path::{Path, PathBuf}; +#[napi] +/// Get workspace config files based on provided globs +pub fn get_project_configuration_files( + workspace_root: String, + globs: Vec, +) -> napi::Result> { + let globs = build_glob_set(&globs)?; + let config_paths: Vec = nx_walker(workspace_root, move |rec| { + let mut config_paths: HashMap = HashMap::new(); + for (path, _) in rec { + insert_config_file_into_map(path, &mut config_paths, &globs); + } + + config_paths + .into_values() + .map(|p| p.to_normalized_string()) + .collect() + }); + + Ok(config_paths) +} + #[napi] /// Get workspace config files based on provided globs pub fn get_project_configurations( diff --git a/packages/nx/src/config/workspaces.glob-for-project-files.spec.ts b/packages/nx/src/project-graph/utils/retrieve-workspace-files.spec.ts similarity index 58% rename from packages/nx/src/config/workspaces.glob-for-project-files.spec.ts rename to packages/nx/src/project-graph/utils/retrieve-workspace-files.spec.ts index b4f8623d0e636..c8b01962308a7 100644 --- a/packages/nx/src/config/workspaces.glob-for-project-files.spec.ts +++ b/packages/nx/src/project-graph/utils/retrieve-workspace-files.spec.ts @@ -1,10 +1,10 @@ -import { TempFs } from '../utils/testing/temp-fs'; -import { globForProjectFiles } from './workspaces'; +import { TempFs } from '../../utils/testing/temp-fs'; +import { retrieveProjectConfigurationPaths } from './retrieve-workspace-files'; -describe('globForProjectFiles', () => { +describe('retrieveProjectConfigurationPaths', () => { let fs: TempFs; beforeAll(() => { - fs = new TempFs('glob-for-project-files'); + fs = new TempFs('retrieveProjectConfigurationPaths'); }); afterAll(() => { fs.cleanup(); @@ -24,10 +24,10 @@ describe('globForProjectFiles', () => { name: 'project-1', }) ); - expect(globForProjectFiles(fs.tempDir, [])).not.toContain( + expect(retrieveProjectConfigurationPaths(fs.tempDir, {})).not.toContain( 'not-projects/project.json' ); - expect(globForProjectFiles(fs.tempDir, [])).toContain( + expect(retrieveProjectConfigurationPaths(fs.tempDir, {})).toContain( 'projects/project.json' ); }); diff --git a/packages/nx/src/project-graph/utils/retrieve-workspace-files.ts b/packages/nx/src/project-graph/utils/retrieve-workspace-files.ts index 470259195a79b..f648838b55c04 100644 --- a/packages/nx/src/project-graph/utils/retrieve-workspace-files.ts +++ b/packages/nx/src/project-graph/utils/retrieve-workspace-files.ts @@ -2,6 +2,7 @@ import { performance } from 'perf_hooks'; import { buildProjectsConfigurationsFromProjectPaths, getGlobPatternsFromPackageManagerWorkspaces, + getGlobPatternsFromPlugins, getGlobPatternsFromPluginsAsync, mergeTargetConfigurations, readTargetDefaultsForTarget, @@ -17,7 +18,7 @@ import { mergeAngularJsonAndProjects, shouldMergeAngularProjects, } from '../../adapter/angular-json'; -import { NxJsonConfiguration } from '../../config/nx-json'; +import { NxJsonConfiguration, readNxJson } from '../../config/nx-json'; import { FileData, ProjectFileMap } from '../../config/project-graph'; import type { NxWorkspaceFiles } from '../../native'; @@ -49,13 +50,7 @@ export async function retrieveWorkspaceFiles( workspaceRoot, globs, (configs: string[]): Record => { - const projectConfigurations = createProjectConfigurations( - workspaceRoot, - nxJson, - configs - ); - - return projectConfigurations.projects; + return createProjectConfigurations(workspaceRoot, nxJson, configs); } ) as NxWorkspaceFiles; performance.mark('get-workspace-files:end'); @@ -85,21 +80,58 @@ export async function retrieveProjectConfigurations( workspaceRoot: string, nxJson: NxJsonConfiguration ): Promise> { - const { getProjectConfigurations } = require('../../native'); + const { getProjectConfigurations } = + require('../../native') as typeof import('../../native'); const globs = await configurationGlobs(workspaceRoot, nxJson); return getProjectConfigurations( workspaceRoot, globs, (configs: string[]): Record => { - const projectConfigurations = createProjectConfigurations( - workspaceRoot, - nxJson, - configs - ); + return createProjectConfigurations(workspaceRoot, nxJson, configs); + } + ) as Record; +} + +export function retrieveProjectConfigurationPaths( + root: string, + nxJson: NxJsonConfiguration +): string[] { + const projectGlobPatterns = configurationGlobsSync(root, nxJson); + const { getProjectConfigurationFiles } = + require('../../native') as typeof import('../../native'); + return getProjectConfigurationFiles(root, projectGlobPatterns); +} - return projectConfigurations.projects; +const projectsWithoutPluginCache = new Map< + string, + Record +>(); + +// TODO: This function is called way too often, it should be optimized without this cache +export function retrieveProjectConfigurationsWithoutPluginInference( + root: string +): Record { + const nxJson = readNxJson(root); + const projectGlobPatterns = configurationGlobsWithoutPlugins(root); + const cacheKey = root + ',' + projectGlobPatterns.join(','); + + if (projectsWithoutPluginCache.has(cacheKey)) { + return projectsWithoutPluginCache.get(cacheKey); + } + + const { getProjectConfigurations } = + require('../../native') as typeof import('../../native'); + const projectConfigurations = getProjectConfigurations( + root, + projectGlobPatterns, + (configs: string[]): Record => { + return createProjectConfigurations(root, nxJson, configs); } - ); + ) as Record; + + projectsWithoutPluginCache.set(cacheKey, projectConfigurations); + + return projectConfigurations; } function buildAllWorkspaceFiles( @@ -124,7 +156,7 @@ function createProjectConfigurations( workspaceRoot: string, nxJson: NxJsonConfiguration, configFiles: string[] -): ProjectsConfigurations { +): Record { performance.mark('build-project-configs:start'); let projectConfigurations = mergeTargetDefaultsIntoProjectDescriptions( @@ -147,10 +179,7 @@ function createProjectConfigurations( 'build-project-configs:end' ); - return { - version: 2, - projects: projectConfigurations, - }; + return projectConfigurations; } function mergeTargetDefaultsIntoProjectDescriptions( @@ -190,10 +219,29 @@ async function configurationGlobs( workspaceRoot ); + return [...configurationGlobsWithoutPlugins(workspaceRoot), ...pluginGlobs]; +} + +/** + * @deprecated Use {@link configurationGlobs} instead. + */ +function configurationGlobsSync( + workspaceRoot: string, + nxJson: NxJsonConfiguration +): string[] { + let pluginGlobs = getGlobPatternsFromPlugins( + nxJson, + getNxRequirePaths(workspaceRoot), + workspaceRoot + ); + + return [...configurationGlobsWithoutPlugins(workspaceRoot), ...pluginGlobs]; +} + +function configurationGlobsWithoutPlugins(workspaceRoot: string): string[] { return [ 'project.json', '**/project.json', - ...pluginGlobs, ...getGlobPatternsFromPackageManagerWorkspaces(workspaceRoot), ]; } diff --git a/packages/nx/src/utils/nx-plugin.ts b/packages/nx/src/utils/nx-plugin.ts index a5ca08f05b60d..57b9c1bdebe7b 100644 --- a/packages/nx/src/utils/nx-plugin.ts +++ b/packages/nx/src/utils/nx-plugin.ts @@ -2,7 +2,6 @@ import { sync } from 'fast-glob'; import { existsSync } from 'fs'; import * as path from 'path'; import { ProjectGraphProcessor } from '../config/project-graph'; -import { Workspaces } from '../config/workspaces'; import { workspaceRoot } from './workspace-root'; import { readJsonFile } from '../utils/fileutils'; @@ -16,7 +15,6 @@ import { } from '../plugins/js/utils/register'; import { ProjectConfiguration, - ProjectsConfigurations, TargetConfiguration, } from '../config/workspace-json-project-json'; import { logger } from './logger'; @@ -30,6 +28,7 @@ import { getNxRequirePaths } from './installation-directory'; import { readTsConfig } from '../plugins/js/utils/typescript'; import type * as ts from 'typescript'; +import { retrieveProjectConfigurationsWithoutPluginInference } from '../project-graph/utils/retrieve-workspace-files'; export type ProjectTargetConfigurator = ( file: string @@ -287,10 +286,8 @@ export function registerPluginTSTranspiler() { } function lookupLocalPlugin(importPath: string, root = workspaceRoot) { - const workspace = new Workspaces(root).readProjectsConfigurations({ - _ignorePluginInference: true, - }); - const plugin = findNxProjectForImportPath(importPath, workspace, root); + const projects = retrieveProjectConfigurationsWithoutPluginInference(root); + const plugin = findNxProjectForImportPath(importPath, projects, root); if (!plugin) { return null; } @@ -299,13 +296,13 @@ function lookupLocalPlugin(importPath: string, root = workspaceRoot) { registerPluginTSTranspiler(); } - const projectConfig = workspace.projects[plugin]; + const projectConfig: ProjectConfiguration = projects[plugin]; return { path: path.join(root, projectConfig.root), projectConfig }; } function findNxProjectForImportPath( importPath: string, - projects: ProjectsConfigurations, + projects: Record, root = workspaceRoot ): string | null { const tsConfigPaths: Record = readTsConfigPaths(root); @@ -314,7 +311,7 @@ function findNxProjectForImportPath( ); if (possiblePaths?.length) { const projectRootMappings = - createProjectRootMappingsFromProjectConfigurations(projects.projects); + createProjectRootMappingsFromProjectConfigurations(projects); for (const tsConfigPath of possiblePaths) { const nxProject = findProjectForPath(tsConfigPath, projectRootMappings); if (nxProject) { From a80abbf2c9a898ef62abd52784c41bcf5fec08be Mon Sep 17 00:00:00 2001 From: Craigory Coppola Date: Tue, 25 Jul 2023 12:51:11 -0400 Subject: [PATCH 168/262] fix(nx-plugin): don't generate `cli` property in migrations.json (#18304) --- e2e/plugin/src/nx-plugin.test.ts | 1 - packages/plugin/src/generators/migration/migration.ts | 1 - 2 files changed, 2 deletions(-) diff --git a/e2e/plugin/src/nx-plugin.test.ts b/e2e/plugin/src/nx-plugin.test.ts index 13c5f07269680..bca4be24b3ebe 100644 --- a/e2e/plugin/src/nx-plugin.test.ts +++ b/e2e/plugin/src/nx-plugin.test.ts @@ -76,7 +76,6 @@ describe('Nx Plugin', () => { [`update-${version}`]: { version, description: `update-${version}`, - cli: `nx`, implementation: `./src/migrations/update-${version}/update-${version}`, }, }), diff --git a/packages/plugin/src/generators/migration/migration.ts b/packages/plugin/src/generators/migration/migration.ts index b6fd7e4245a89..29fac57de980a 100644 --- a/packages/plugin/src/generators/migration/migration.ts +++ b/packages/plugin/src/generators/migration/migration.ts @@ -73,7 +73,6 @@ function updateMigrationsJson(host: Tree, options: NormalizedSchema) { generators[options.name] = { version: options.packageVersion, description: options.description, - cli: 'nx', implementation: `./src/migrations/${options.name}/${options.name}`, }; migrations.generators = generators; From aab868aa0c30949832fe2c4b9cb109c204442e39 Mon Sep 17 00:00:00 2001 From: FrozenPandaz Date: Tue, 25 Jul 2023 13:46:12 -0400 Subject: [PATCH 169/262] chore(misc): publish 16.6.0-beta.5 --- lerna.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lerna.json b/lerna.json index a44bd393fd8e2..f6f926fb3004f 100644 --- a/lerna.json +++ b/lerna.json @@ -1,6 +1,6 @@ { "packages": ["build/packages/*", "build/packages/nx/native-packages/*"], - "version": "16.6.0-beta.4", + "version": "16.6.0-beta.5", "granularPathspec": false, "command": { "publish": { From 54dcc0f8be9d34de2422dd17ee5bb668b0cd3706 Mon Sep 17 00:00:00 2001 From: Craigory Coppola Date: Tue, 25 Jul 2023 16:30:59 -0400 Subject: [PATCH 170/262] chore(repo): update codeowners for package.json (#18278) --- CODEOWNERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CODEOWNERS b/CODEOWNERS index 17d3f9e385a77..c864973e8d5a6 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -4,8 +4,8 @@ /e2e/**/* @FrozenPandaz @vsavkin @AgentEnder @jaysoo @JamesHenry /scripts/**/* @FrozenPandaz @vsavkin @AgentEnder @jaysoo @JamesHenry /tools/**/* @FrozenPandaz @vsavkin @AgentEnder @jaysoo @JamesHenry -package.json @nrwl/nx-pipelines-reviewers -pnpm-lock.yaml @nrwl/nx-pipelines-reviewers +package.json @nrwl/nx-core-reviewers +pnpm-lock.yaml @nrwl/nx-core-reviewers # Docs Site + Graph /docs @nrwl/nx-docs-reviewers From 810b584c334fd0deff178bba04d0884ea16f069a Mon Sep 17 00:00:00 2001 From: Jack Hsu Date: Tue, 25 Jul 2023 16:35:29 -0400 Subject: [PATCH 171/262] fix(js): generate ts standalone project with better import path (#18197) --- e2e/storybook/src/storybook-nested.test.ts | 2 +- .../js/src/generators/library/library.spec.ts | 27 +++++++++++++++++++ packages/js/src/generators/library/library.ts | 8 +++--- .../new/files-root-app/package.json__tmpl__ | 2 +- 4 files changed, 33 insertions(+), 6 deletions(-) diff --git a/e2e/storybook/src/storybook-nested.test.ts b/e2e/storybook/src/storybook-nested.test.ts index c4377052361bc..a40db2abfcd3f 100644 --- a/e2e/storybook/src/storybook-nested.test.ts +++ b/e2e/storybook/src/storybook-nested.test.ts @@ -79,7 +79,7 @@ describe('Storybook generators and executors for standalone workspaces - using R writeFileSync( tmpProjPath(`src/app/test-button.tsx`), ` - import { MyLib } from '@${appName}/my-lib'; + import { MyLib } from 'my-lib'; export function TestButton() { return ( diff --git a/packages/js/src/generators/library/library.spec.ts b/packages/js/src/generators/library/library.spec.ts index e0b546f1df59d..97a91e97cb737 100644 --- a/packages/js/src/generators/library/library.spec.ts +++ b/packages/js/src/generators/library/library.spec.ts @@ -383,6 +383,33 @@ describe('lib', () => { expect.assertions(1); }); + + it('should provide a default import path using npm scope', async () => { + await libraryGenerator(tree, { + ...defaultOptions, + name: 'myLib', + }); + + const tsconfigJson = readJson(tree, '/tsconfig.base.json'); + expect( + tsconfigJson.compilerOptions.paths['@proj/my-lib'] + ).toBeDefined(); + }); + + it('should read import path from existing name in package.json', async () => { + updateJson(tree, 'package.json', (json) => { + json.name = '@acme/core'; + return json; + }); + await libraryGenerator(tree, { + ...defaultOptions, + rootProject: true, + name: 'myLib', + }); + + const tsconfigJson = readJson(tree, '/tsconfig.base.json'); + expect(tsconfigJson.compilerOptions.paths['@acme/core']).toBeDefined(); + }); }); describe('--pascalCaseFiles', () => { diff --git a/packages/js/src/generators/library/library.ts b/packages/js/src/generators/library/library.ts index 550f12f33f421..3a84b740f25a6 100644 --- a/packages/js/src/generators/library/library.ts +++ b/packages/js/src/generators/library/library.ts @@ -12,6 +12,7 @@ import { names, offsetFromRoot, ProjectConfiguration, + readJson, runTasksInSerial, toJS, Tree, @@ -35,8 +36,6 @@ import { swcHelpersVersion, tsLibVersion, typesNodeVersion, - swcNodeVersion, - swcCoreVersion, } from '../../utils/versions'; import jsInitGenerator from '../init/init'; import { type PackageJson } from 'nx/src/utils/package-json'; @@ -539,8 +538,9 @@ function normalizeOptions( ? options.tags.split(',').map((s) => s.trim()) : []; - const importPath = - options.importPath || getImportPath(tree, projectDirectory); + const importPath = options.rootProject + ? readJson(tree, 'package.json').name ?? getImportPath(tree, 'core') + : options.importPath || getImportPath(tree, projectDirectory); options.minimal ??= false; diff --git a/packages/workspace/src/generators/new/files-root-app/package.json__tmpl__ b/packages/workspace/src/generators/new/files-root-app/package.json__tmpl__ index f1c9ad1d5c23e..43ba92facc48f 100644 --- a/packages/workspace/src/generators/new/files-root-app/package.json__tmpl__ +++ b/packages/workspace/src/generators/new/files-root-app/package.json__tmpl__ @@ -1,5 +1,5 @@ { - "name": "@<%= formattedNames.fileName %>/source", + "name": "<%= formattedNames.fileName %>", "version": "0.0.0", "license": "MIT", "scripts": { From bdcec6de55168d37ca0c1e1783921ea2555e5c47 Mon Sep 17 00:00:00 2001 From: Juri Date: Mon, 24 Jul 2023 23:44:51 +0200 Subject: [PATCH 172/262] feat(nx-dev): github star widget --- .../feature-doc-viewer/src/lib/doc-viewer.tsx | 12 +++- .../src/lib/table-of-contents.tsx | 59 ++++++++++--------- nx-dev/nx-dev/lib/githubStars.api.ts | 33 +++++++++++ nx-dev/nx-dev/pages/[...segments].tsx | 27 ++++----- .../pages/extending-nx/[...segments].tsx | 7 +++ nx-dev/nx-dev/pages/extending-nx/index.tsx | 7 +++ .../nx-dev/pages/nx-cloud/[...segments].tsx | 7 +++ nx-dev/nx-dev/pages/nx-cloud/index.tsx | 7 +++ .../[name]/documents/[...segments].tsx | 7 +++ .../packages/rspack/documents/overview.tsx | 7 +++ .../rspack/documents/rspack-config-setup.tsx | 7 +++ .../rspack/documents/rspack-plugins.tsx | 7 +++ nx-dev/ui-common/src/index.ts | 1 + .../ui-common/src/lib/github-star-widget.tsx | 58 ++++++++++++++++++ 14 files changed, 203 insertions(+), 43 deletions(-) create mode 100644 nx-dev/nx-dev/lib/githubStars.api.ts create mode 100644 nx-dev/ui-common/src/lib/github-star-widget.tsx diff --git a/nx-dev/feature-doc-viewer/src/lib/doc-viewer.tsx b/nx-dev/feature-doc-viewer/src/lib/doc-viewer.tsx index 2188ffeded64f..b784f689bb0c9 100644 --- a/nx-dev/feature-doc-viewer/src/lib/doc-viewer.tsx +++ b/nx-dev/feature-doc-viewer/src/lib/doc-viewer.tsx @@ -4,7 +4,7 @@ import { ProcessedDocument, RelatedDocument, } from '@nx/nx-dev/models-document'; -import { Breadcrumbs, Footer } from '@nx/nx-dev/ui-common'; +import { Breadcrumbs, Footer, GitHubStarWidget } from '@nx/nx-dev/ui-common'; import { renderMarkdown } from '@nx/nx-dev/ui-markdoc'; import { NextSeo } from 'next-seo'; import { useRouter } from 'next/router'; @@ -15,9 +15,11 @@ import { collectHeadings, TableOfContents } from './table-of-contents'; export function DocViewer({ document, relatedDocuments, + widgetData, }: { document: ProcessedDocument; relatedDocuments: RelatedDocument[]; + widgetData: { githubStarsCount: number }; }): JSX.Element { const router = useRouter(); const hideTableOfContent = @@ -109,7 +111,13 @@ export function DocViewer({ elementRef={ref} path={router.basePath} headings={vm.tableOfContent} - /> + > + {widgetData.githubStarsCount > 0 && ( + + )} +
)}
diff --git a/nx-dev/feature-doc-viewer/src/lib/table-of-contents.tsx b/nx-dev/feature-doc-viewer/src/lib/table-of-contents.tsx index d7afc3a502e8b..24bdabeb908ab 100644 --- a/nx-dev/feature-doc-viewer/src/lib/table-of-contents.tsx +++ b/nx-dev/feature-doc-viewer/src/lib/table-of-contents.tsx @@ -39,10 +39,12 @@ export function TableOfContents({ elementRef, headings, path, + children, }: { elementRef: any; headings: Heading[]; path: string; + children: React.ReactNode; }): JSX.Element { const headingLevelTargets: number[] = [1, 2, 3]; // matching to: H1, H2, H3... const items = headings.filter( @@ -60,32 +62,35 @@ export function TableOfContents({ ); return ( - + <> + +
{children}
+ ); } diff --git a/nx-dev/nx-dev/lib/githubStars.api.ts b/nx-dev/nx-dev/lib/githubStars.api.ts new file mode 100644 index 0000000000000..329709ad51525 --- /dev/null +++ b/nx-dev/nx-dev/lib/githubStars.api.ts @@ -0,0 +1,33 @@ +import { Octokit } from 'octokit'; + +let cachedGithubStarCountPromise: null | Promise = null; + +export async function fetchGithubStarCount() { + if (cachedGithubStarCountPromise !== null) { + // If the promise is in the cache, return it directly + return cachedGithubStarCountPromise; + } + + cachedGithubStarCountPromise = (async () => { + try { + const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN }); + const responseData = await octokit.request('GET /repos/{owner}/{repo}', { + owner: 'nrwl', + repo: 'nx', + headers: { + 'X-GitHub-Api-Version': '2022-11-28', + }, + retry: { enabled: false }, + throttle: { + enabled: true, + }, + }); + + return responseData.data.stargazers_count; + } catch (e) { + return 0; // fallback, will hide GitHub star widget + } + })(); + + return cachedGithubStarCountPromise; +} diff --git a/nx-dev/nx-dev/pages/[...segments].tsx b/nx-dev/nx-dev/pages/[...segments].tsx index 249ddce33cf1e..236a10d22e961 100644 --- a/nx-dev/nx-dev/pages/[...segments].tsx +++ b/nx-dev/nx-dev/pages/[...segments].tsx @@ -1,7 +1,7 @@ import { getBasicNxSection } from '@nx/nx-dev/data-access-menu'; import { DocViewer } from '@nx/nx-dev/feature-doc-viewer'; import { ProcessedDocument, RelatedDocument } from '@nx/nx-dev/models-document'; -import { Menu, MenuItem } from '@nx/nx-dev/models-menu'; +import { MenuItem } from '@nx/nx-dev/models-menu'; import { DocumentationHeader, SidebarContainer } from '@nx/nx-dev/ui-common'; import { GetStaticPaths, GetStaticProps } from 'next'; import { useRouter } from 'next/router'; @@ -10,15 +10,18 @@ import { menusApi } from '../lib/menus.api'; import { useNavToggle } from '../lib/navigation-toggle.effect'; import { nxDocumentationApi } from '../lib/nx.api'; import { tagsApi } from '../lib/tags.api'; +import { fetchGithubStarCount } from '../lib/githubStars.api'; export default function NxDocumentation({ document, menu, relatedDocuments, + widgetData, }: { document: ProcessedDocument; menu: MenuItem[]; relatedDocuments: RelatedDocument[]; + widgetData: { githubStarsCount: number }; }) { const router = useRouter(); const { toggleNav, navIsOpen } = useNavToggle(); @@ -40,16 +43,8 @@ export default function NxDocumentation({ return () => router.events.off('routeChangeComplete', handleRouteChange); }, [router, wrapperElement]); - const vm: { - document: ProcessedDocument; - menu: Menu; - relatedDocuments: RelatedDocument[]; - } = { - document, - menu: { - sections: [getBasicNxSection(menu)], - }, - relatedDocuments, + const menuWithSections = { + sections: [getBasicNxSection(menu)], }; return ( @@ -62,7 +57,7 @@ export default function NxDocumentation({ role="main" className="flex h-full flex-1 overflow-y-hidden" > - +
@@ -100,6 +96,9 @@ export const getStaticProps: GetStaticProps = async ({ return { props: { document, + widgetData: { + githubStarsCount: await fetchGithubStarCount(), + }, relatedDocuments: tagsApi .getAssociatedItemsFromTags(document.tags) .filter((item) => item.path !== '/' + params.segments.join('/')), // Remove currently displayed item diff --git a/nx-dev/nx-dev/pages/extending-nx/[...segments].tsx b/nx-dev/nx-dev/pages/extending-nx/[...segments].tsx index 3e9c375f6941d..6b7128517c3d7 100644 --- a/nx-dev/nx-dev/pages/extending-nx/[...segments].tsx +++ b/nx-dev/nx-dev/pages/extending-nx/[...segments].tsx @@ -10,15 +10,18 @@ import { menusApi } from '../../lib/menus.api'; import { useNavToggle } from '../../lib/navigation-toggle.effect'; import { nxPluginsApi } from '../../lib/plugins.api'; import { tagsApi } from '../../lib/tags.api'; +import { fetchGithubStarCount } from '../../lib/githubStars.api'; export default function Pages({ document, menu, relatedDocuments, + widgetData, }: { document: ProcessedDocument; menu: MenuItem[]; relatedDocuments: RelatedDocument[]; + widgetData: { githubStarsCount: number }; }): JSX.Element { const router = useRouter(); const { toggleNav, navIsOpen } = useNavToggle(); @@ -72,6 +75,7 @@ export default function Pages({ @@ -98,6 +102,9 @@ export const getStaticProps: GetStaticProps = async ({ return { props: { document, + widgetData: { + githubStarsCount: await fetchGithubStarCount(), + }, relatedDocuments: tagsApi .getAssociatedItemsFromTags(document.tags) .filter((item) => item.path !== '/' + segments.join('/')), // Remove currently displayed item diff --git a/nx-dev/nx-dev/pages/extending-nx/index.tsx b/nx-dev/nx-dev/pages/extending-nx/index.tsx index 1ace8563b1c8d..5d8f92214e5b9 100644 --- a/nx-dev/nx-dev/pages/extending-nx/index.tsx +++ b/nx-dev/nx-dev/pages/extending-nx/index.tsx @@ -10,15 +10,18 @@ import { menusApi } from '../../lib/menus.api'; import { useNavToggle } from '../../lib/navigation-toggle.effect'; import { nxPluginsApi } from '../../lib/plugins.api'; import { tagsApi } from '../../lib/tags.api'; +import { fetchGithubStarCount } from '../../lib/githubStars.api'; export default function PluginsRoot({ document, menu, relatedDocuments, + widgetData, }: { document: ProcessedDocument; menu: MenuItem[]; relatedDocuments: RelatedDocument[]; + widgetData: { githubStarsCount: number }; }) { const router = useRouter(); const { toggleNav, navIsOpen } = useNavToggle(); @@ -72,6 +75,7 @@ export default function PluginsRoot({ @@ -87,6 +91,9 @@ export const getStaticProps: GetStaticProps = async () => { return { props: { document, + widgetData: { + githubStarsCount: await fetchGithubStarCount(), + }, menu: menusApi.getMenu('extending-nx', ''), relatedDocuments: document.tags .map((t) => tagsApi.getAssociatedItems(t)) diff --git a/nx-dev/nx-dev/pages/nx-cloud/[...segments].tsx b/nx-dev/nx-dev/pages/nx-cloud/[...segments].tsx index 1bf55d9b576ef..b4d9791d0a975 100644 --- a/nx-dev/nx-dev/pages/nx-cloud/[...segments].tsx +++ b/nx-dev/nx-dev/pages/nx-cloud/[...segments].tsx @@ -13,15 +13,18 @@ import { nxCloudApi } from '../../lib/cloud.api'; import { menusApi } from '../../lib/menus.api'; import { useNavToggle } from '../../lib/navigation-toggle.effect'; import { tagsApi } from '../../lib/tags.api'; +import { fetchGithubStarCount } from '../../lib/githubStars.api'; export default function Pages({ document, menu, relatedDocuments, + widgetData, }: { document: ProcessedDocument; menu: MenuItem[]; relatedDocuments: RelatedDocument[]; + widgetData: { githubStarsCount: number }; }) { const router = useRouter(); const { toggleNav, navIsOpen } = useNavToggle(); @@ -75,6 +78,7 @@ export default function Pages({ @@ -99,6 +103,9 @@ export const getStaticProps: GetStaticProps = async ({ return { props: { document, + widgetData: { + githubStarsCount: await fetchGithubStarCount(), + }, relatedDocuments: tagsApi .getAssociatedItemsFromTags(document.tags) .filter((item) => item.path !== '/' + segments.join('/')), // Remove currently displayed item diff --git a/nx-dev/nx-dev/pages/nx-cloud/index.tsx b/nx-dev/nx-dev/pages/nx-cloud/index.tsx index 4ae72535b838f..9742328df419f 100644 --- a/nx-dev/nx-dev/pages/nx-cloud/index.tsx +++ b/nx-dev/nx-dev/pages/nx-cloud/index.tsx @@ -13,15 +13,18 @@ import { nxCloudApi } from '../../lib/cloud.api'; import { menusApi } from '../../lib/menus.api'; import { useNavToggle } from '../../lib/navigation-toggle.effect'; import { tagsApi } from '../../lib/tags.api'; +import { fetchGithubStarCount } from '../../lib/githubStars.api'; export default function CloudRoot({ document, menu, relatedDocuments, + widgetData, }: { document: ProcessedDocument; menu: MenuItem[]; relatedDocuments: RelatedDocument[]; + widgetData: { githubStarsCount: number }; }) { const router = useRouter(); const { toggleNav, navIsOpen } = useNavToggle(); @@ -75,6 +78,7 @@ export default function CloudRoot({ @@ -90,6 +94,9 @@ export const getStaticProps: GetStaticProps = async () => { return { props: { document, + widgetData: { + githubStarsCount: await fetchGithubStarCount(), + }, menu: menusApi.getMenu('cloud', ''), relatedDocuments: document.tags .map((t) => tagsApi.getAssociatedItems(t)) diff --git a/nx-dev/nx-dev/pages/packages/[name]/documents/[...segments].tsx b/nx-dev/nx-dev/pages/packages/[name]/documents/[...segments].tsx index 5cb45d0b854a8..de802de86702e 100644 --- a/nx-dev/nx-dev/pages/packages/[name]/documents/[...segments].tsx +++ b/nx-dev/nx-dev/pages/packages/[name]/documents/[...segments].tsx @@ -13,16 +13,19 @@ import { menusApi } from '../../../../lib/menus.api'; import { useNavToggle } from '../../../../lib/navigation-toggle.effect'; import { nxPackagesApi } from '../../../../lib/packages.api'; import { tagsApi } from '../../../../lib/tags.api'; +import { fetchGithubStarCount } from '../../../../lib/githubStars.api'; export default function PackageDocument({ document, menu, relatedDocuments, + widgetData, }: { document: ProcessedDocument; menu: MenuItem[]; pkg: ProcessedPackageMetadata; relatedDocuments: RelatedDocument[]; + widgetData: { githubStarsCount: number }; }): JSX.Element { const router = useRouter(); const { toggleNav, navIsOpen } = useNavToggle(); @@ -79,6 +82,7 @@ export default function PackageDocument({ @@ -120,6 +124,9 @@ export async function getStaticProps({ props: { pkg: nxPackagesApi.getPackage([params.name]), document, + widgetData: { + githubStarsCount: await fetchGithubStarCount(), + }, relatedDocuments: tagsApi .getAssociatedItemsFromTags(document.tags) .filter((item) => item.path !== '/' + segments.join('/')), // Remove currently displayed item diff --git a/nx-dev/nx-dev/pages/packages/rspack/documents/overview.tsx b/nx-dev/nx-dev/pages/packages/rspack/documents/overview.tsx index e4e5960e2bb0f..badb40132070f 100644 --- a/nx-dev/nx-dev/pages/packages/rspack/documents/overview.tsx +++ b/nx-dev/nx-dev/pages/packages/rspack/documents/overview.tsx @@ -11,16 +11,19 @@ import { menusApi } from '../../../../lib/menus.api'; import { useNavToggle } from '../../../../lib/navigation-toggle.effect'; import { content } from '../../../../lib/rspack/content/overview'; import { pkg } from '../../../../lib/rspack/pkg'; +import { fetchGithubStarCount } from '../../../../lib/githubStars.api'; export default function Overview({ document, menu, relatedDocuments, + widgetData, }: { document: ProcessedDocument; menu: MenuItem[]; pkg: ProcessedPackageMetadata; relatedDocuments: RelatedDocument[]; + widgetData: { githubStarsCount: number }; }): JSX.Element { const router = useRouter(); const { toggleNav, navIsOpen } = useNavToggle(); @@ -77,6 +80,7 @@ export default function Overview({ @@ -99,6 +103,9 @@ export async function getStaticProps() { props: { pkg, document, + widgetData: { + githubStarsCount: await fetchGithubStarCount(), + }, relatedDocuments: [], menu: menusApi.getMenu('packages', ''), }, diff --git a/nx-dev/nx-dev/pages/packages/rspack/documents/rspack-config-setup.tsx b/nx-dev/nx-dev/pages/packages/rspack/documents/rspack-config-setup.tsx index 028f2bbb8486a..0ba2309bf3385 100644 --- a/nx-dev/nx-dev/pages/packages/rspack/documents/rspack-config-setup.tsx +++ b/nx-dev/nx-dev/pages/packages/rspack/documents/rspack-config-setup.tsx @@ -11,16 +11,19 @@ import { menusApi } from '../../../../lib/menus.api'; import { useNavToggle } from '../../../../lib/navigation-toggle.effect'; import { content } from '../../../../lib/rspack/content/rspack-config-setup'; import { pkg } from '../../../../lib/rspack/pkg'; +import { fetchGithubStarCount } from '../../../../lib/githubStars.api'; export default function RspackConfigSetup({ document, menu, relatedDocuments, + widgetData, }: { document: ProcessedDocument; menu: MenuItem[]; pkg: ProcessedPackageMetadata; relatedDocuments: RelatedDocument[]; + widgetData: { githubStarsCount: number }; }): JSX.Element { const router = useRouter(); const { toggleNav, navIsOpen } = useNavToggle(); @@ -77,6 +80,7 @@ export default function RspackConfigSetup({ @@ -100,6 +104,9 @@ export async function getStaticProps() { props: { pkg, document, + widgetData: { + githubStarsCount: await fetchGithubStarCount(), + }, relatedDocuments: [], menu: menusApi.getMenu('packages', ''), }, diff --git a/nx-dev/nx-dev/pages/packages/rspack/documents/rspack-plugins.tsx b/nx-dev/nx-dev/pages/packages/rspack/documents/rspack-plugins.tsx index 065c3d1834dc1..6567ff04f58af 100644 --- a/nx-dev/nx-dev/pages/packages/rspack/documents/rspack-plugins.tsx +++ b/nx-dev/nx-dev/pages/packages/rspack/documents/rspack-plugins.tsx @@ -11,16 +11,19 @@ import { menusApi } from '../../../../lib/menus.api'; import { useNavToggle } from '../../../../lib/navigation-toggle.effect'; import { content } from '../../../../lib/rspack/content/rspack-plugin'; import { pkg } from '../../../../lib/rspack/pkg'; +import { fetchGithubStarCount } from '../../../../lib/githubStars.api'; export default function RspackPlugins({ document, menu, relatedDocuments, + widgetData, }: { document: ProcessedDocument; menu: MenuItem[]; pkg: ProcessedPackageMetadata; relatedDocuments: RelatedDocument[]; + widgetData: { githubStarsCount: number }; }): JSX.Element { const router = useRouter(); const { toggleNav, navIsOpen } = useNavToggle(); @@ -77,6 +80,7 @@ export default function RspackPlugins({ @@ -99,6 +103,9 @@ export async function getStaticProps() { props: { pkg, document, + widgetData: { + githubStarsCount: await fetchGithubStarCount(), + }, relatedDocuments: [], menu: menusApi.getMenu('packages', ''), }, diff --git a/nx-dev/ui-common/src/index.ts b/nx-dev/ui-common/src/index.ts index 1431e27616f01..0be0fe5c60da1 100644 --- a/nx-dev/ui-common/src/index.ts +++ b/nx-dev/ui-common/src/index.ts @@ -13,3 +13,4 @@ export * from './lib/nx-users-showcase'; export * from './lib/plugin-card'; export * from './lib/testimonial-card'; export * from './lib/typography'; +export * from './lib/github-star-widget'; diff --git a/nx-dev/ui-common/src/lib/github-star-widget.tsx b/nx-dev/ui-common/src/lib/github-star-widget.tsx new file mode 100644 index 0000000000000..f38e51ab799d9 --- /dev/null +++ b/nx-dev/ui-common/src/lib/github-star-widget.tsx @@ -0,0 +1,58 @@ +import { sendCustomEvent } from '@nx/nx-dev/feature-analytics'; + +const GithubIcon = (props: any) => { + return ( + + {/*GitHub*/} + + + ); +}; + +export function GitHubStarWidget({ starsCount }: { starsCount: number }) { + const formatStars = (count: number) => { + if (count >= 1000) { + return (count / 1000).toFixed(1) + 'k'; + } else { + return count; + } + }; + + const handleClick = (eventAction: string) => { + sendCustomEvent( + eventAction, + 'githubstars-toc-sidebar', + 'githubstarswidget' + ); + }; + + return ( +
+ ); +} From 7d1a44bc5779ead95d7587075ab03956ab0e0537 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leosvel=20P=C3=A9rez=20Espinosa?= Date: Tue, 25 Jul 2023 22:36:32 +0100 Subject: [PATCH 173/262] chore(misc): remove usage of deprecated updateBuildableProjectDepsInPackageJson option (#18305) --- packages-legacy/angular/project.json | 1 - packages-legacy/cypress/project.json | 1 - packages-legacy/detox/project.json | 1 - packages-legacy/devkit/project.json | 1 - packages-legacy/esbuild/project.json | 1 - packages-legacy/eslint-plugin-nx/project.json | 1 - packages-legacy/expo/project.json | 1 - packages-legacy/express/project.json | 1 - packages-legacy/jest/project.json | 1 - packages-legacy/js/project.json | 1 - packages-legacy/linter/project.json | 1 - packages-legacy/nest/project.json | 1 - packages-legacy/next/project.json | 1 - packages-legacy/node/project.json | 1 - packages-legacy/nx-plugin/project.json | 1 - packages-legacy/react-native/project.json | 1 - packages-legacy/react/project.json | 1 - packages-legacy/rollup/project.json | 1 - packages-legacy/storybook/project.json | 1 - packages-legacy/vite/project.json | 1 - packages-legacy/web/project.json | 1 - packages-legacy/webpack/project.json | 1 - packages-legacy/workspace/project.json | 1 - packages/vite/project.json | 1 - 24 files changed, 24 deletions(-) diff --git a/packages-legacy/angular/project.json b/packages-legacy/angular/project.json index f5a4fd48c5ba9..74bd16b022eeb 100644 --- a/packages-legacy/angular/project.json +++ b/packages-legacy/angular/project.json @@ -20,7 +20,6 @@ "main": "packages-legacy/angular/index.ts", "tsConfig": "packages-legacy/angular/tsconfig.json", "outputPath": "build/packages/angular-legacy", - "updateBuildableProjectDepsInPackageJson": false, "assets": [ { "input": "packages-legacy/angular", diff --git a/packages-legacy/cypress/project.json b/packages-legacy/cypress/project.json index a437aed8dc70c..09130f53e6742 100644 --- a/packages-legacy/cypress/project.json +++ b/packages-legacy/cypress/project.json @@ -14,7 +14,6 @@ "main": "packages-legacy/cypress/index.ts", "tsConfig": "packages-legacy/cypress/tsconfig.json", "outputPath": "build/packages/cypress-legacy", - "updateBuildableProjectDepsInPackageJson": false, "assets": [ { "input": "packages-legacy/cypress", diff --git a/packages-legacy/detox/project.json b/packages-legacy/detox/project.json index 64d2dcd4aec4a..d45f4b8a43b64 100644 --- a/packages-legacy/detox/project.json +++ b/packages-legacy/detox/project.json @@ -14,7 +14,6 @@ "main": "packages-legacy/detox/index.ts", "tsConfig": "packages-legacy/detox/tsconfig.json", "outputPath": "build/packages/detox-legacy", - "updateBuildableProjectDepsInPackageJson": false, "assets": [ { "input": "packages-legacy/detox", diff --git a/packages-legacy/devkit/project.json b/packages-legacy/devkit/project.json index 0cd6f38b8bd49..d52296d0285c4 100644 --- a/packages-legacy/devkit/project.json +++ b/packages-legacy/devkit/project.json @@ -14,7 +14,6 @@ "main": "packages-legacy/devkit/index.ts", "tsConfig": "packages-legacy/devkit/tsconfig.json", "outputPath": "build/packages/devkit-legacy", - "updateBuildableProjectDepsInPackageJson": false, "assets": [ { "input": "packages-legacy/devkit", diff --git a/packages-legacy/esbuild/project.json b/packages-legacy/esbuild/project.json index d648484a4049c..7db25464918e4 100644 --- a/packages-legacy/esbuild/project.json +++ b/packages-legacy/esbuild/project.json @@ -14,7 +14,6 @@ "main": "packages-legacy/esbuild/index.ts", "tsConfig": "packages-legacy/esbuild/tsconfig.json", "outputPath": "build/packages/esbuild-legacy", - "updateBuildableProjectDepsInPackageJson": false, "assets": [ { "input": "packages-legacy/esbuild", diff --git a/packages-legacy/eslint-plugin-nx/project.json b/packages-legacy/eslint-plugin-nx/project.json index c04dd74faca54..337f08d421c59 100644 --- a/packages-legacy/eslint-plugin-nx/project.json +++ b/packages-legacy/eslint-plugin-nx/project.json @@ -14,7 +14,6 @@ "main": "packages-legacy/eslint-plugin-nx/index.ts", "tsConfig": "packages-legacy/eslint-plugin-nx/tsconfig.json", "outputPath": "build/packages/eslint-plugin-nx-legacy", - "updateBuildableProjectDepsInPackageJson": false, "assets": [ { "input": "packages-legacy/eslint-plugin-nx", diff --git a/packages-legacy/expo/project.json b/packages-legacy/expo/project.json index f939c062d05cc..98c733b338046 100644 --- a/packages-legacy/expo/project.json +++ b/packages-legacy/expo/project.json @@ -14,7 +14,6 @@ "main": "packages-legacy/expo/index.ts", "tsConfig": "packages-legacy/expo/tsconfig.json", "outputPath": "build/packages/expo-legacy", - "updateBuildableProjectDepsInPackageJson": false, "assets": [ { "input": "packages-legacy/expo", diff --git a/packages-legacy/express/project.json b/packages-legacy/express/project.json index d2aa7c1be217e..3c01e640f3d70 100644 --- a/packages-legacy/express/project.json +++ b/packages-legacy/express/project.json @@ -14,7 +14,6 @@ "main": "packages-legacy/express/index.ts", "tsConfig": "packages-legacy/express/tsconfig.json", "outputPath": "build/packages/express-legacy", - "updateBuildableProjectDepsInPackageJson": false, "assets": [ { "input": "packages-legacy/express", diff --git a/packages-legacy/jest/project.json b/packages-legacy/jest/project.json index 9b1f1fe1ce4a9..180222f779cf7 100644 --- a/packages-legacy/jest/project.json +++ b/packages-legacy/jest/project.json @@ -14,7 +14,6 @@ "main": "packages-legacy/jest/index.ts", "tsConfig": "packages-legacy/jest/tsconfig.json", "outputPath": "build/packages/jest-legacy", - "updateBuildableProjectDepsInPackageJson": false, "assets": [ { "input": "packages-legacy/jest", diff --git a/packages-legacy/js/project.json b/packages-legacy/js/project.json index a71ed66d1c486..e6a23f321b425 100644 --- a/packages-legacy/js/project.json +++ b/packages-legacy/js/project.json @@ -14,7 +14,6 @@ "main": "packages-legacy/js/index.ts", "tsConfig": "packages-legacy/js/tsconfig.json", "outputPath": "build/packages/js-legacy", - "updateBuildableProjectDepsInPackageJson": false, "assets": [ { "input": "packages-legacy/js", diff --git a/packages-legacy/linter/project.json b/packages-legacy/linter/project.json index 9965f0b775635..735f0117810d7 100644 --- a/packages-legacy/linter/project.json +++ b/packages-legacy/linter/project.json @@ -14,7 +14,6 @@ "main": "packages-legacy/linter/index.ts", "tsConfig": "packages-legacy/linter/tsconfig.json", "outputPath": "build/packages/linter-legacy", - "updateBuildableProjectDepsInPackageJson": false, "assets": [ { "input": "packages-legacy/linter", diff --git a/packages-legacy/nest/project.json b/packages-legacy/nest/project.json index 5e7c90a30f006..b961e9a140b59 100644 --- a/packages-legacy/nest/project.json +++ b/packages-legacy/nest/project.json @@ -14,7 +14,6 @@ "main": "packages-legacy/nest/index.ts", "tsConfig": "packages-legacy/nest/tsconfig.json", "outputPath": "build/packages/nest-legacy", - "updateBuildableProjectDepsInPackageJson": false, "assets": [ { "input": "packages-legacy/nest", diff --git a/packages-legacy/next/project.json b/packages-legacy/next/project.json index 3d794c5c5e2ae..8521289cf1a6e 100644 --- a/packages-legacy/next/project.json +++ b/packages-legacy/next/project.json @@ -14,7 +14,6 @@ "main": "packages-legacy/next/index.ts", "tsConfig": "packages-legacy/next/tsconfig.json", "outputPath": "build/packages/next-legacy", - "updateBuildableProjectDepsInPackageJson": false, "assets": [ { "input": "packages-legacy/next", diff --git a/packages-legacy/node/project.json b/packages-legacy/node/project.json index e7326e5e9b5d5..f1d11744cd309 100644 --- a/packages-legacy/node/project.json +++ b/packages-legacy/node/project.json @@ -14,7 +14,6 @@ "main": "packages-legacy/node/index.ts", "tsConfig": "packages-legacy/node/tsconfig.json", "outputPath": "build/packages/node-legacy", - "updateBuildableProjectDepsInPackageJson": false, "assets": [ { "input": "packages-legacy/node", diff --git a/packages-legacy/nx-plugin/project.json b/packages-legacy/nx-plugin/project.json index 938b156a64624..cf8c473f4b6e7 100644 --- a/packages-legacy/nx-plugin/project.json +++ b/packages-legacy/nx-plugin/project.json @@ -14,7 +14,6 @@ "main": "packages-legacy/nx-plugin/index.ts", "tsConfig": "packages-legacy/nx-plugin/tsconfig.json", "outputPath": "build/packages/nx-plugin-legacy", - "updateBuildableProjectDepsInPackageJson": false, "assets": [ { "input": "packages-legacy/nx-plugin", diff --git a/packages-legacy/react-native/project.json b/packages-legacy/react-native/project.json index 3659ed64effbb..30ba2ac207317 100644 --- a/packages-legacy/react-native/project.json +++ b/packages-legacy/react-native/project.json @@ -14,7 +14,6 @@ "main": "packages-legacy/react-native/index.ts", "tsConfig": "packages-legacy/react-native/tsconfig.json", "outputPath": "build/packages/react-native-legacy", - "updateBuildableProjectDepsInPackageJson": false, "assets": [ { "input": "packages-legacy/react-native", diff --git a/packages-legacy/react/project.json b/packages-legacy/react/project.json index 5966515dbeb7f..3aa57ca765556 100644 --- a/packages-legacy/react/project.json +++ b/packages-legacy/react/project.json @@ -14,7 +14,6 @@ "main": "packages-legacy/react/index.ts", "tsConfig": "packages-legacy/react/tsconfig.json", "outputPath": "build/packages/react-legacy", - "updateBuildableProjectDepsInPackageJson": false, "assets": [ { "input": "packages-legacy/react", diff --git a/packages-legacy/rollup/project.json b/packages-legacy/rollup/project.json index 07371eea78150..4c5cc1a906f4f 100644 --- a/packages-legacy/rollup/project.json +++ b/packages-legacy/rollup/project.json @@ -14,7 +14,6 @@ "main": "packages-legacy/rollup/index.ts", "tsConfig": "packages-legacy/rollup/tsconfig.json", "outputPath": "build/packages/rollup-legacy", - "updateBuildableProjectDepsInPackageJson": false, "assets": [ { "input": "packages-legacy/rollup", diff --git a/packages-legacy/storybook/project.json b/packages-legacy/storybook/project.json index ee271a24e35b4..110d8ff6a9c21 100644 --- a/packages-legacy/storybook/project.json +++ b/packages-legacy/storybook/project.json @@ -14,7 +14,6 @@ "main": "packages-legacy/storybook/index.ts", "tsConfig": "packages-legacy/storybook/tsconfig.json", "outputPath": "build/packages/storybook-legacy", - "updateBuildableProjectDepsInPackageJson": false, "assets": [ { "input": "packages-legacy/storybook", diff --git a/packages-legacy/vite/project.json b/packages-legacy/vite/project.json index 097fb4fe62673..7d93621857c06 100644 --- a/packages-legacy/vite/project.json +++ b/packages-legacy/vite/project.json @@ -14,7 +14,6 @@ "main": "packages-legacy/vite/index.ts", "tsConfig": "packages-legacy/vite/tsconfig.json", "outputPath": "build/packages/vite-legacy", - "updateBuildableProjectDepsInPackageJson": false, "assets": [ { "input": "packages-legacy/vite", diff --git a/packages-legacy/web/project.json b/packages-legacy/web/project.json index 1c7adf79b1e9c..3416e3a61ccc7 100644 --- a/packages-legacy/web/project.json +++ b/packages-legacy/web/project.json @@ -14,7 +14,6 @@ "main": "packages-legacy/web/index.ts", "tsConfig": "packages-legacy/web/tsconfig.json", "outputPath": "build/packages/web-legacy", - "updateBuildableProjectDepsInPackageJson": false, "assets": [ { "input": "packages-legacy/web", diff --git a/packages-legacy/webpack/project.json b/packages-legacy/webpack/project.json index 54f7c2483ce9f..72a7dbb5c3ccd 100644 --- a/packages-legacy/webpack/project.json +++ b/packages-legacy/webpack/project.json @@ -14,7 +14,6 @@ "main": "packages-legacy/webpack/index.ts", "tsConfig": "packages-legacy/webpack/tsconfig.json", "outputPath": "build/packages/webpack-legacy", - "updateBuildableProjectDepsInPackageJson": false, "assets": [ { "input": "packages-legacy/webpack", diff --git a/packages-legacy/workspace/project.json b/packages-legacy/workspace/project.json index 29f4595800caa..cdadff38b9746 100644 --- a/packages-legacy/workspace/project.json +++ b/packages-legacy/workspace/project.json @@ -14,7 +14,6 @@ "main": "packages-legacy/workspace/index.ts", "tsConfig": "packages-legacy/workspace/tsconfig.json", "outputPath": "build/packages/workspace-legacy", - "updateBuildableProjectDepsInPackageJson": false, "assets": [ { "input": "packages-legacy/workspace", diff --git a/packages/vite/project.json b/packages/vite/project.json index 7cd0f7d589b48..aec9b6fd62482 100644 --- a/packages/vite/project.json +++ b/packages/vite/project.json @@ -18,7 +18,6 @@ "outputPath": "build/packages/vite", "tsConfig": "packages/vite/tsconfig.lib.json", "main": "packages/vite/index.ts", - "updateBuildableProjectDepsInPackageJson": false, "assets": [ { "input": "packages/vite", From 901b70a4fec92d2af875acd4f947acc7a91636e4 Mon Sep 17 00:00:00 2001 From: Craigory Coppola Date: Tue, 25 Jul 2023 18:15:26 -0400 Subject: [PATCH 174/262] chore(nx-plugin): add examples for generators (#17346) --- .../plugin/generators/create-package.json | 1 + .../plugin/generators/e2e-project.json | 7 +----- .../packages/plugin/generators/executor.json | 1 + .../packages/plugin/generators/migration.json | 2 +- .../plugin/generators/plugin-lint-checks.json | 6 +++++ .../packages/plugin/generators/plugin.json | 2 +- .../packages/plugin/generators/preset.json | 10 +++++++++ .../generators/create-package-examples.md | 13 +++++++++++ .../docs/generators/e2e-project-examples.md | 13 +++++++++++ .../docs/generators/executor-examples.md | 22 +++++++++++++++++++ .../src/generators/create-package/schema.json | 1 + .../src/generators/e2e-project/schema.json | 7 +----- .../src/generators/executor/schema.json | 1 + .../src/generators/lint-checks/schema.json | 6 +++++ .../src/generators/migration/schema.json | 2 +- .../plugin/src/generators/plugin/schema.json | 2 +- .../plugin/src/generators/preset/schema.json | 10 +++++++++ 17 files changed, 90 insertions(+), 16 deletions(-) create mode 100644 packages/plugin/docs/generators/create-package-examples.md create mode 100644 packages/plugin/docs/generators/e2e-project-examples.md create mode 100644 packages/plugin/docs/generators/executor-examples.md diff --git a/docs/generated/packages/plugin/generators/create-package.json b/docs/generated/packages/plugin/generators/create-package.json index 31d0171dbde33..81a8d5f1d63b7 100644 --- a/docs/generated/packages/plugin/generators/create-package.json +++ b/docs/generated/packages/plugin/generators/create-package.json @@ -7,6 +7,7 @@ "$id": "NxPluginCreatePackage", "title": "Create a framework package", "description": "Create a framework package that uses Nx CLI.", + "examplesFile": "## Examples\n\n{% tabs %}\n{% tab label=\"Basic executable\" %}\n\nCreate an executable that initializes an Nx workspace with {my-plugin}'s preset:\n\n```bash\nnx g @nx/plugin:create-package create-my-plugin --project my-plugin\n```\n\n{% /tab %}\n{% /tabs %}\n", "type": "object", "properties": { "name": { diff --git a/docs/generated/packages/plugin/generators/e2e-project.json b/docs/generated/packages/plugin/generators/e2e-project.json index 67f305138cc11..3f6aff6b7f07c 100644 --- a/docs/generated/packages/plugin/generators/e2e-project.json +++ b/docs/generated/packages/plugin/generators/e2e-project.json @@ -7,6 +7,7 @@ "$id": "NxPluginE2E", "title": "Create an E2E app for a Nx Plugin", "description": "Create an E2E app for a Nx Plugin.", + "examplesFile": "## Examples\n\n{% tabs %}\n{% tab label=\"E2E Project\" %}\n\nScaffolds an E2E project for the plugin `my-plugin`.\n\n```bash\nnx g @nx/plugin:e2e-project --pluginName my-plugin --npmPackageName my-plugin --pluginOutputPath dist/my-plugin\n```\n\n{% /tab %}\n{% /tabs %}\n", "type": "object", "properties": { "pluginName": { @@ -29,12 +30,6 @@ "x-priority": "important" }, "jestConfig": { "type": "string", "description": "Jest config file." }, - "standaloneConfig": { - "description": "Split the project configuration into `/project.json` rather than including it inside `workspace.json`.", - "type": "boolean", - "default": true, - "x-deprecated": "Nx only supports standaloneConfig" - }, "linter": { "description": "The tool to use for running lint checks.", "type": "string", diff --git a/docs/generated/packages/plugin/generators/executor.json b/docs/generated/packages/plugin/generators/executor.json index 2c3d9d58361f1..c051d667f6d52 100644 --- a/docs/generated/packages/plugin/generators/executor.json +++ b/docs/generated/packages/plugin/generators/executor.json @@ -7,6 +7,7 @@ "$id": "NxPluginExecutor", "title": "Create an Executor for an Nx Plugin", "description": "Create an Executor for an Nx Plugin.", + "examplesFile": "## Examples\n\n{% tabs %}\n{% tab label=\"Basic executor\" %}\n\nCreate a new executor called `build` inside the plugin `my-plugin`:\n\n```bash\nnx g @nx/plugin:executor build --project my-plugin\n```\n\n{% /tab %}\n{% tab label=\"With custom hashing\" %}\n\nCreate a new executor called `build` inside the plugin `my-plugin`, that uses a custom hashing function:\n\n```bash\nnx g @nx/plugin:executor build --project my-plugin --includeHasher\n```\n\n{% /tab %}\n{% /tabs %}\n", "type": "object", "examples": [ { diff --git a/docs/generated/packages/plugin/generators/migration.json b/docs/generated/packages/plugin/generators/migration.json index 86b39acba2130..10ba13c23bf8e 100644 --- a/docs/generated/packages/plugin/generators/migration.json +++ b/docs/generated/packages/plugin/generators/migration.json @@ -11,7 +11,7 @@ "examples": [ { "command": "nx g migration my-migration --project=my-plugin --version=1.0.0", - "description": "Generate `libs/my-plugin/src/migrations/my-migration`" + "description": "Adds a new migration to the project `my-plugin`, which will be triggered when migrating to version 1.0.0 or above from a previous version." } ], "properties": { diff --git a/docs/generated/packages/plugin/generators/plugin-lint-checks.json b/docs/generated/packages/plugin/generators/plugin-lint-checks.json index 3139aae60e97d..bdf4a50fe7c0b 100644 --- a/docs/generated/packages/plugin/generators/plugin-lint-checks.json +++ b/docs/generated/packages/plugin/generators/plugin-lint-checks.json @@ -8,6 +8,12 @@ "title": "", "type": "object", "description": "Adds linting configuration to validate common json files for nx plugins.", + "examples": [ + { + "command": "nx g @nx/plugin:lint-checks", + "description": "Sets up linting configuration to validate common json files for an nx plugin project." + } + ], "properties": { "projectName": { "type": "string", diff --git a/docs/generated/packages/plugin/generators/plugin.json b/docs/generated/packages/plugin/generators/plugin.json index d0fa0cbfbbae7..08671955a574c 100644 --- a/docs/generated/packages/plugin/generators/plugin.json +++ b/docs/generated/packages/plugin/generators/plugin.json @@ -11,7 +11,7 @@ "examples": [ { "command": "nx g plugin my-plugin --directory=plugins --importPath=@myorg/my-plugin", - "description": "Generate `libs/plugins/my-plugin`" + "description": "Generates an Nx plugin project called `plugins-my-plugin` at `libs/plugins/my-plugin`. The project will have an npm package name and import path of `@myorg/my-plugin`." } ], "properties": { diff --git a/docs/generated/packages/plugin/generators/preset.json b/docs/generated/packages/plugin/generators/preset.json index ba1a0769f05d0..4a0ba2b843cba 100644 --- a/docs/generated/packages/plugin/generators/preset.json +++ b/docs/generated/packages/plugin/generators/preset.json @@ -7,6 +7,16 @@ "$id": "NxPluginPreset", "title": "Generator ran by create-nx-plugin", "description": "Initializes a workspace with an nx-plugin inside of it. Use as: `create-nx-plugin` or `create-nx-workspace --preset @nx/nx-plugin`.", + "examples": [ + { + "command": "npx create-nx-plugin", + "description": "Creates a new Nx workspace containing an Nx plugin." + }, + { + "command": "npx create-nx-workspace --preset @nx/plugin", + "description": "Creates a new Nx workspace containing an Nx plugin." + } + ], "type": "object", "properties": { "pluginName": { diff --git a/packages/plugin/docs/generators/create-package-examples.md b/packages/plugin/docs/generators/create-package-examples.md new file mode 100644 index 0000000000000..0cd418a9cd183 --- /dev/null +++ b/packages/plugin/docs/generators/create-package-examples.md @@ -0,0 +1,13 @@ +## Examples + +{% tabs %} +{% tab label="Basic executable" %} + +Create an executable that initializes an Nx workspace with {my-plugin}'s preset: + +```bash +nx g @nx/plugin:create-package create-my-plugin --project my-plugin +``` + +{% /tab %} +{% /tabs %} diff --git a/packages/plugin/docs/generators/e2e-project-examples.md b/packages/plugin/docs/generators/e2e-project-examples.md new file mode 100644 index 0000000000000..8c914224abaa1 --- /dev/null +++ b/packages/plugin/docs/generators/e2e-project-examples.md @@ -0,0 +1,13 @@ +## Examples + +{% tabs %} +{% tab label="E2E Project" %} + +Scaffolds an E2E project for the plugin `my-plugin`. + +```bash +nx g @nx/plugin:e2e-project --pluginName my-plugin --npmPackageName my-plugin --pluginOutputPath dist/my-plugin +``` + +{% /tab %} +{% /tabs %} diff --git a/packages/plugin/docs/generators/executor-examples.md b/packages/plugin/docs/generators/executor-examples.md new file mode 100644 index 0000000000000..1e29f133535b7 --- /dev/null +++ b/packages/plugin/docs/generators/executor-examples.md @@ -0,0 +1,22 @@ +## Examples + +{% tabs %} +{% tab label="Basic executor" %} + +Create a new executor called `build` inside the plugin `my-plugin`: + +```bash +nx g @nx/plugin:executor build --project my-plugin +``` + +{% /tab %} +{% tab label="With custom hashing" %} + +Create a new executor called `build` inside the plugin `my-plugin`, that uses a custom hashing function: + +```bash +nx g @nx/plugin:executor build --project my-plugin --includeHasher +``` + +{% /tab %} +{% /tabs %} diff --git a/packages/plugin/src/generators/create-package/schema.json b/packages/plugin/src/generators/create-package/schema.json index 73a7bc0e247ba..fc85ba9b3f956 100644 --- a/packages/plugin/src/generators/create-package/schema.json +++ b/packages/plugin/src/generators/create-package/schema.json @@ -4,6 +4,7 @@ "$id": "NxPluginCreatePackage", "title": "Create a framework package", "description": "Create a framework package that uses Nx CLI.", + "examplesFile": "../../../docs/generators/create-package-examples.md", "type": "object", "properties": { "name": { diff --git a/packages/plugin/src/generators/e2e-project/schema.json b/packages/plugin/src/generators/e2e-project/schema.json index ae5729dfaf417..d9b7dca81856a 100644 --- a/packages/plugin/src/generators/e2e-project/schema.json +++ b/packages/plugin/src/generators/e2e-project/schema.json @@ -4,6 +4,7 @@ "$id": "NxPluginE2E", "title": "Create an E2E app for a Nx Plugin", "description": "Create an E2E app for a Nx Plugin.", + "examplesFile": "../../../docs/generators/e2e-project-examples.md", "type": "object", "properties": { "pluginName": { @@ -29,12 +30,6 @@ "type": "string", "description": "Jest config file." }, - "standaloneConfig": { - "description": "Split the project configuration into `/project.json` rather than including it inside `workspace.json`.", - "type": "boolean", - "default": true, - "x-deprecated": "Nx only supports standaloneConfig" - }, "linter": { "description": "The tool to use for running lint checks.", "type": "string", diff --git a/packages/plugin/src/generators/executor/schema.json b/packages/plugin/src/generators/executor/schema.json index 4337938fa6654..211c25b01a1df 100644 --- a/packages/plugin/src/generators/executor/schema.json +++ b/packages/plugin/src/generators/executor/schema.json @@ -4,6 +4,7 @@ "$id": "NxPluginExecutor", "title": "Create an Executor for an Nx Plugin", "description": "Create an Executor for an Nx Plugin.", + "examplesFile": "../../../docs/generators/executor-examples.md", "type": "object", "examples": [ { diff --git a/packages/plugin/src/generators/lint-checks/schema.json b/packages/plugin/src/generators/lint-checks/schema.json index a82390b6a3c52..81142fed83618 100644 --- a/packages/plugin/src/generators/lint-checks/schema.json +++ b/packages/plugin/src/generators/lint-checks/schema.json @@ -5,6 +5,12 @@ "title": "", "type": "object", "description": "Adds linting configuration to validate common json files for nx plugins.", + "examples": [ + { + "command": "nx g @nx/plugin:lint-checks", + "description": "Sets up linting configuration to validate common json files for an nx plugin project." + } + ], "properties": { "projectName": { "type": "string", diff --git a/packages/plugin/src/generators/migration/schema.json b/packages/plugin/src/generators/migration/schema.json index 73c4282cc4636..e1d0903faa53f 100644 --- a/packages/plugin/src/generators/migration/schema.json +++ b/packages/plugin/src/generators/migration/schema.json @@ -8,7 +8,7 @@ "examples": [ { "command": "nx g migration my-migration --project=my-plugin --version=1.0.0", - "description": "Generate `libs/my-plugin/src/migrations/my-migration`" + "description": "Adds a new migration to the project `my-plugin`, which will be triggered when migrating to version 1.0.0 or above from a previous version." } ], "properties": { diff --git a/packages/plugin/src/generators/plugin/schema.json b/packages/plugin/src/generators/plugin/schema.json index d3fde1578fb81..99b089c8c0d7b 100644 --- a/packages/plugin/src/generators/plugin/schema.json +++ b/packages/plugin/src/generators/plugin/schema.json @@ -8,7 +8,7 @@ "examples": [ { "command": "nx g plugin my-plugin --directory=plugins --importPath=@myorg/my-plugin", - "description": "Generate `libs/plugins/my-plugin`" + "description": "Generates an Nx plugin project called `plugins-my-plugin` at `libs/plugins/my-plugin`. The project will have an npm package name and import path of `@myorg/my-plugin`." } ], "properties": { diff --git a/packages/plugin/src/generators/preset/schema.json b/packages/plugin/src/generators/preset/schema.json index 3d5f5f0b1a209..24676350cf70c 100644 --- a/packages/plugin/src/generators/preset/schema.json +++ b/packages/plugin/src/generators/preset/schema.json @@ -4,6 +4,16 @@ "$id": "NxPluginPreset", "title": "Generator ran by create-nx-plugin", "description": "Initializes a workspace with an nx-plugin inside of it. Use as: `create-nx-plugin` or `create-nx-workspace --preset @nx/nx-plugin`.", + "examples": [ + { + "command": "npx create-nx-plugin", + "description": "Creates a new Nx workspace containing an Nx plugin." + }, + { + "command": "npx create-nx-workspace --preset @nx/plugin", + "description": "Creates a new Nx workspace containing an Nx plugin." + } + ], "type": "object", "properties": { "pluginName": { From 1dadb3d77275b6715fcfab0e224c585fa71e9869 Mon Sep 17 00:00:00 2001 From: Jason Jean Date: Tue, 25 Jul 2023 18:16:42 -0400 Subject: [PATCH 175/262] chore(repo): update nx to 16.6.0-beta.5 (#18309) --- package.json | 24 +- pnpm-lock.yaml | 703 +++++++++++++++++++++++++++++++------------------ 2 files changed, 464 insertions(+), 263 deletions(-) diff --git a/package.json b/package.json index 7b6b20b4f0331..654a54c07971c 100644 --- a/package.json +++ b/package.json @@ -63,17 +63,17 @@ "@ngrx/router-store": "~16.0.0", "@ngrx/store": "~16.0.0", "@nguniversal/builders": "~16.1.0", - "@nx/cypress": "16.6.0-beta.4", - "@nx/devkit": "16.6.0-beta.4", - "@nx/eslint-plugin": "16.6.0-beta.4", - "@nx/jest": "16.6.0-beta.4", - "@nx/js": "16.6.0-beta.4", - "@nx/linter": "16.6.0-beta.4", - "@nx/next": "16.6.0-beta.4", - "@nx/react": "16.6.0-beta.4", - "@nx/storybook": "16.6.0-beta.4", - "@nx/web": "16.6.0-beta.4", - "@nx/webpack": "16.6.0-beta.4", + "@nx/cypress": "16.6.0-beta.5", + "@nx/devkit": "16.6.0-beta.5", + "@nx/eslint-plugin": "16.6.0-beta.5", + "@nx/jest": "16.6.0-beta.5", + "@nx/js": "16.6.0-beta.5", + "@nx/linter": "16.6.0-beta.5", + "@nx/next": "16.6.0-beta.5", + "@nx/react": "16.6.0-beta.5", + "@nx/storybook": "16.6.0-beta.5", + "@nx/web": "16.6.0-beta.5", + "@nx/webpack": "16.6.0-beta.5", "@parcel/watcher": "2.0.4", "@phenomnomnominal/tsquery": "~5.0.1", "@playwright/test": "^1.36.1", @@ -214,7 +214,7 @@ "next-sitemap": "^3.1.10", "ng-packagr": "~16.1.0", "node-fetch": "^2.6.7", - "nx": "16.6.0-beta.4", + "nx": "16.6.0-beta.5", "nx-cloud": "16.2.0-beta.0", "octokit": "^2.0.14", "open": "^8.4.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1f3ce0f1bbd9a..034f772005318 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,5 +1,9 @@ lockfileVersion: '6.0' +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + overrides: minimist: ^1.2.6 underscore: ^1.12.1 @@ -224,7 +228,7 @@ devDependencies: version: 29.5.0 '@monodon/rust': specifier: 1.1.2 - version: 1.1.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.6.0-beta.4)(prettier@2.7.1)(typescript@5.1.3) + version: 1.1.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.6.0-beta.5)(prettier@2.7.1)(typescript@5.1.3) '@napi-rs/cli': specifier: 2.14.0 version: 2.14.0 @@ -262,38 +266,38 @@ devDependencies: specifier: ~16.1.0 version: 16.1.0(@angular-devkit/build-angular@16.1.0)(@angular/common@16.1.0)(@angular/core@16.1.0)(@types/express@4.17.14)(chokidar@3.5.3)(typescript@5.1.3) '@nx/cypress': - specifier: 16.6.0-beta.4 - version: 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + specifier: 16.6.0-beta.5 + version: 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) '@nx/devkit': - specifier: 16.6.0-beta.4 - version: 16.6.0-beta.4(nx@16.6.0-beta.4) + specifier: 16.6.0-beta.5 + version: 16.6.0-beta.5(nx@16.6.0-beta.5) '@nx/eslint-plugin': - specifier: 16.6.0-beta.4 - version: 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(@typescript-eslint/parser@5.60.1)(eslint-config-prettier@8.5.0)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + specifier: 16.6.0-beta.5 + version: 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(@typescript-eslint/parser@5.60.1)(eslint-config-prettier@8.5.0)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) '@nx/jest': - specifier: 16.6.0-beta.4 - version: 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4) + specifier: 16.6.0-beta.5 + version: 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4) '@nx/js': - specifier: 16.6.0-beta.4 - version: 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + specifier: 16.6.0-beta.5 + version: 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) '@nx/linter': - specifier: 16.6.0-beta.4 - version: 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + specifier: 16.6.0-beta.5 + version: 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) '@nx/next': - specifier: 16.6.0-beta.4 - version: 16.6.0-beta.4(@babel/core@7.22.9)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/express@4.17.14)(@types/node@18.16.9)(eslint@8.15.0)(file-loader@6.2.0)(next@13.3.4)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) + specifier: 16.6.0-beta.5 + version: 16.6.0-beta.5(@babel/core@7.22.9)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(file-loader@6.2.0)(next@13.3.4)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) '@nx/react': - specifier: 16.6.0-beta.4 - version: 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) + specifier: 16.6.0-beta.5 + version: 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) '@nx/storybook': - specifier: 16.6.0-beta.4 - version: 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + specifier: 16.6.0-beta.5 + version: 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) '@nx/web': - specifier: 16.6.0-beta.4 - version: 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + specifier: 16.6.0-beta.5 + version: 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) '@nx/webpack': - specifier: 16.6.0-beta.4 - version: 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(esbuild@0.17.5)(html-webpack-plugin@5.5.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + specifier: 16.6.0-beta.5 + version: 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(esbuild@0.17.5)(html-webpack-plugin@5.5.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) '@parcel/watcher': specifier: 2.0.4 version: 2.0.4 @@ -715,8 +719,8 @@ devDependencies: specifier: ^2.6.7 version: 2.6.7 nx: - specifier: 16.6.0-beta.4 - version: 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51) + specifier: 16.6.0-beta.5 + version: 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51) nx-cloud: specifier: 16.2.0-beta.0 version: 16.2.0-beta.0 @@ -1714,24 +1718,6 @@ packages: lru-cache: 5.1.1 semver: 6.3.1 - /@babel/helper-create-class-features-plugin@7.22.5(@babel/core@7.22.9): - resolution: {integrity: sha512-xkb58MyOYIslxu3gKmVXmjTtUPvBU4odYzbiIQbWwLKIHCsx6UGZGX6F1IznMFVnDdirseUZopzN+ZRt8Xb33Q==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-environment-visitor': 7.22.5 - '@babel/helper-function-name': 7.22.5 - '@babel/helper-member-expression-to-functions': 7.22.5 - '@babel/helper-optimise-call-expression': 7.22.5 - '@babel/helper-replace-supers': 7.22.9(@babel/core@7.22.9) - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.6 - semver: 6.3.1 - dev: true - /@babel/helper-create-class-features-plugin@7.22.9(@babel/core@7.22.5): resolution: {integrity: sha512-Pwyi89uO4YrGKxL/eNJ8lfEH55DnRloGPOseaA8NFNL6jAUnn+KccaISiFazCj5IolPPDjGSdzQzXVzODVRqUQ==} engines: {node: '>=6.9.0'} @@ -1958,20 +1944,6 @@ packages: - supports-color dev: true - /@babel/helper-replace-supers@7.22.5: - resolution: {integrity: sha512-aLdNM5I3kdI/V9xGNyKSF3X/gTyMUBohTZ+/3QdQKAA9vxIiy12E+8E2HoOP1/DjeqU+g6as35QHJNMDDYpuCg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-environment-visitor': 7.22.5 - '@babel/helper-member-expression-to-functions': 7.22.5 - '@babel/helper-optimise-call-expression': 7.22.5 - '@babel/template': 7.22.5 - '@babel/traverse': 7.22.8 - '@babel/types': 7.22.5 - transitivePeerDependencies: - - supports-color - dev: true - /@babel/helper-replace-supers@7.22.9(@babel/core@7.22.5): resolution: {integrity: sha512-LJIKvvpgPOPUThdYqcX6IXRuIcTkcAub0IaDRGCZH0p5GPUp7PhRU9QVgFcDDd51BaPkk77ZjqFwh6DZTAEmGg==} engines: {node: '>=6.9.0'} @@ -2108,7 +2080,7 @@ packages: '@babel/core': 7.22.5 '@babel/helper-plugin-utils': 7.22.5 '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - '@babel/plugin-transform-optional-chaining': 7.22.5(@babel/core@7.22.5) + '@babel/plugin-transform-optional-chaining': 7.22.6(@babel/core@7.22.5) dev: true /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.22.5(@babel/core@7.22.9): @@ -2120,7 +2092,7 @@ packages: '@babel/core': 7.22.9 '@babel/helper-plugin-utils': 7.22.5 '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - '@babel/plugin-transform-optional-chaining': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-optional-chaining': 7.22.6(@babel/core@7.22.9) dev: true /@babel/plugin-proposal-async-generator-functions@7.20.7(@babel/core@7.22.5): @@ -2160,7 +2132,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.22.9 - '@babel/helper-create-class-features-plugin': 7.22.5(@babel/core@7.22.9) + '@babel/helper-create-class-features-plugin': 7.22.9(@babel/core@7.22.9) '@babel/helper-plugin-utils': 7.22.5 dev: true @@ -2183,13 +2155,25 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.22.9 - '@babel/helper-create-class-features-plugin': 7.22.5(@babel/core@7.22.9) + '@babel/helper-create-class-features-plugin': 7.22.9(@babel/core@7.22.9) '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-replace-supers': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.5 + '@babel/helper-replace-supers': 7.22.9(@babel/core@7.22.9) + '@babel/helper-split-export-declaration': 7.22.6 '@babel/plugin-syntax-decorators': 7.21.0(@babel/core@7.22.9) - transitivePeerDependencies: - - supports-color + dev: true + + /@babel/plugin-proposal-decorators@7.22.7(@babel/core@7.22.9): + resolution: {integrity: sha512-omXqPF7Onq4Bb7wHxXjM3jSMSJvUUbvDvmmds7KI5n9Cq6Ln5I05I1W2nRlRof1rGdiUxJrxwe285WF96XlBXQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-create-class-features-plugin': 7.22.9(@babel/core@7.22.9) + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-replace-supers': 7.22.9(@babel/core@7.22.9) + '@babel/helper-split-export-declaration': 7.22.6 + '@babel/plugin-syntax-decorators': 7.22.5(@babel/core@7.22.9) dev: true /@babel/plugin-proposal-dynamic-import@7.18.6(@babel/core@7.22.9): @@ -2445,6 +2429,16 @@ packages: '@babel/helper-plugin-utils': 7.22.5 dev: true + /@babel/plugin-syntax-decorators@7.22.5(@babel/core@7.22.9): + resolution: {integrity: sha512-avpUOBS7IU6al8MmF1XpAyj9QYeLPuSDJI5D4pVMSMdL7xQokKqJPYQC67RCT0aCTashUXPiGwMJ0DEXXCEmMA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + /@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.22.5): resolution: {integrity: sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==} peerDependencies: @@ -2735,16 +2729,6 @@ packages: '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-syntax-typescript@7.20.0(@babel/core@7.22.9): - resolution: {integrity: sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.22.5 - dev: true - /@babel/plugin-syntax-typescript@7.22.5(@babel/core@7.22.9): resolution: {integrity: sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==} engines: {node: '>=6.9.0'} @@ -2827,6 +2811,21 @@ packages: - supports-color dev: true + /@babel/plugin-transform-async-generator-functions@7.22.7(@babel/core@7.22.9): + resolution: {integrity: sha512-7HmE7pk/Fmke45TODvxvkxRMV9RazV+ZZzhOL9AG8G29TLrr3jkjwF7uJfxZ30EoXpO+LJkq4oA8NjO2DTnEDg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-environment-visitor': 7.22.5 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-remap-async-to-generator': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.22.9) + transitivePeerDependencies: + - supports-color + dev: true + /@babel/plugin-transform-async-to-generator@7.22.5(@babel/core@7.22.5): resolution: {integrity: sha512-b1A8D8ZzE/VhNDoV1MSJTnpKkCG5bJo+19R4o4oy03zM7ws8yEMK755j61Dc3EyvdysbqH5BOOTquJ7ZX9C6vQ==} engines: {node: '>=6.9.0'} @@ -2977,6 +2976,24 @@ packages: globals: 11.12.0 dev: true + /@babel/plugin-transform-classes@7.22.6(@babel/core@7.22.9): + resolution: {integrity: sha512-58EgM6nuPNG6Py4Z3zSuu0xWu2VfodiMi72Jt5Kj2FECmaYk1RrTXA45z6KBFsu9tRgwQDwIiY4FXTt+YsSFAQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-annotate-as-pure': 7.22.5 + '@babel/helper-compilation-targets': 7.22.9(@babel/core@7.22.9) + '@babel/helper-environment-visitor': 7.22.5 + '@babel/helper-function-name': 7.22.5 + '@babel/helper-optimise-call-expression': 7.22.5 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-replace-supers': 7.22.9(@babel/core@7.22.9) + '@babel/helper-split-export-declaration': 7.22.6 + globals: 11.12.0 + dev: true + /@babel/plugin-transform-computed-properties@7.22.5(@babel/core@7.22.5): resolution: {integrity: sha512-4GHWBgRf0krxPX+AaPtgBAlTgTeZmqDynokHOX7aqqAB4tHs3U2Y02zH6ETFdLZGcg9UQSD1WCmkVrE9ErHeOg==} engines: {node: '>=6.9.0'} @@ -3542,6 +3559,30 @@ packages: '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.22.9) dev: true + /@babel/plugin-transform-optional-chaining@7.22.6(@babel/core@7.22.5): + resolution: {integrity: sha512-Vd5HiWml0mDVtcLHIoEU5sw6HOUW/Zk0acLs/SAeuLzkGNOPc9DB4nkUajemhCmTIz3eiaKREZn2hQQqF79YTg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.5 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.22.5) + dev: true + + /@babel/plugin-transform-optional-chaining@7.22.6(@babel/core@7.22.9): + resolution: {integrity: sha512-Vd5HiWml0mDVtcLHIoEU5sw6HOUW/Zk0acLs/SAeuLzkGNOPc9DB4nkUajemhCmTIz3eiaKREZn2hQQqF79YTg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.22.9) + dev: true + /@babel/plugin-transform-parameters@7.22.5(@babel/core@7.22.5): resolution: {integrity: sha512-AVkFUBurORBREOmHRKo06FjHYgjrabpdqRSwq6+C7R5iTCZOsM4QbcB27St0a4U6fffyAOqh3s/qEfybAhfivg==} engines: {node: '>=6.9.0'} @@ -4250,6 +4291,97 @@ packages: - supports-color dev: true + /@babel/preset-env@7.22.9(@babel/core@7.22.9): + resolution: {integrity: sha512-wNi5H/Emkhll/bqPjsjQorSykrlfY5OWakd6AulLvMEytpKasMVUpVy8RL4qBIBs5Ac6/5i0/Rv0b/Fg6Eag/g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/compat-data': 7.22.9 + '@babel/core': 7.22.9 + '@babel/helper-compilation-targets': 7.22.9(@babel/core@7.22.9) + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-validator-option': 7.22.5 + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.22.9) + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.22.9) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.22.9) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.22.9) + '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.22.9) + '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.22.9) + '@babel/plugin-syntax-import-assertions': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-syntax-import-attributes': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.22.9) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.22.9) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.22.9) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.22.9) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.22.9) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.22.9) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.22.9) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.22.9) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.22.9) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.22.9) + '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.22.9) + '@babel/plugin-transform-arrow-functions': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-async-generator-functions': 7.22.7(@babel/core@7.22.9) + '@babel/plugin-transform-async-to-generator': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-block-scoped-functions': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-block-scoping': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-class-properties': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-class-static-block': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-classes': 7.22.6(@babel/core@7.22.9) + '@babel/plugin-transform-computed-properties': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-destructuring': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-dotall-regex': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-duplicate-keys': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-dynamic-import': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-exponentiation-operator': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-export-namespace-from': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-for-of': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-function-name': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-json-strings': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-literals': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-logical-assignment-operators': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-member-expression-literals': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-modules-amd': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-modules-commonjs': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-modules-systemjs': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-modules-umd': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-named-capturing-groups-regex': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-new-target': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-nullish-coalescing-operator': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-numeric-separator': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-object-rest-spread': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-object-super': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-optional-catch-binding': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-optional-chaining': 7.22.6(@babel/core@7.22.9) + '@babel/plugin-transform-parameters': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-private-methods': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-private-property-in-object': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-property-literals': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-regenerator': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-reserved-words': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-shorthand-properties': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-spread': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-sticky-regex': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-template-literals': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-typeof-symbol': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-unicode-escapes': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-unicode-property-regex': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-unicode-regex': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-unicode-sets-regex': 7.22.5(@babel/core@7.22.9) + '@babel/preset-modules': 0.1.5(@babel/core@7.22.9) + '@babel/types': 7.22.5 + babel-plugin-polyfill-corejs2: 0.4.4(@babel/core@7.22.9) + babel-plugin-polyfill-corejs3: 0.8.2(@babel/core@7.22.9) + babel-plugin-polyfill-regenerator: 0.5.1(@babel/core@7.22.9) + core-js-compat: 3.31.1 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + dev: true + /@babel/preset-flow@7.21.4(@babel/core@7.22.9): resolution: {integrity: sha512-F24cSq4DIBmhq4OzK3dE63NHagb27OPE3eWR+HLekt4Z3Y5MzIIUGF3LlLgV0gN8vzbDViSY7HnrReNVCJXTeA==} engines: {node: '>=6.9.0'} @@ -4624,6 +4756,7 @@ packages: /@emotion/memoize@0.7.4: resolution: {integrity: sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==} + requiresBuild: true dev: false optional: true @@ -5600,6 +5733,7 @@ packages: dependencies: '@jridgewell/gen-mapping': 0.3.3 '@jridgewell/trace-mapping': 0.3.18 + dev: true /@jridgewell/sourcemap-codec@1.4.14: resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==} @@ -5805,12 +5939,12 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false - /@monodon/rust@1.1.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.6.0-beta.4)(prettier@2.7.1)(typescript@5.1.3): + /@monodon/rust@1.1.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.6.0-beta.5)(prettier@2.7.1)(typescript@5.1.3): resolution: {integrity: sha512-lb667coCcsWmkHuSKfGHgEeaWK24VGrW3AgA7Wq2M8wVVhuVQeKAV2UDt5vgvQj+xPlXPyKs6iPqNFXi3c2nLA==} dependencies: '@ltd/j-toml': 1.38.0 - '@nrwl/devkit': 15.8.0(nx@16.6.0-beta.4)(typescript@5.1.3) - '@nrwl/js': 15.8.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.6.0-beta.4)(prettier@2.7.1)(typescript@5.1.3) + '@nrwl/devkit': 15.8.0(nx@16.6.0-beta.5)(typescript@5.1.3) + '@nrwl/js': 15.8.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.6.0-beta.5)(prettier@2.7.1)(typescript@5.1.3) chalk: 4.1.2 transitivePeerDependencies: - '@babel/traverse' @@ -6541,10 +6675,10 @@ packages: - debug dev: true - /@nrwl/cypress@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-6AN9HxAKGLMARBVy7lJkMkDAAPfNxiv1iJDsKAOlGRfc3DfjmgrYBTH5dmzmNL8MvgKG+itSSNhBjAkiB2S9sQ==} + /@nrwl/cypress@16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-AoiEj7FLhyQbaIpbtKieJf2Nd0TVSB0t+5uOK5zz++XxCXt14KeHgni2A4+iYrGyE+4+6WIPwPdS8WorhpoPpg==} dependencies: - '@nx/cypress': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/cypress': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -6592,7 +6726,7 @@ packages: - typescript dev: true - /@nrwl/devkit@15.8.0(nx@16.6.0-beta.4)(typescript@5.1.3): + /@nrwl/devkit@15.8.0(nx@16.6.0-beta.5)(typescript@5.1.3): resolution: {integrity: sha512-qD+asvhTXIibXPXr3r1IDP7ap3Bw5H7tSd+C5mXFhIMMinTqRnQVXe6Odfs34VFP/dpWBIBZdkkwCM/+BsCLNw==} peerDependencies: nx: '>= 14.1 <= 16' @@ -6600,7 +6734,7 @@ packages: '@phenomnomnominal/tsquery': 4.1.1(typescript@5.1.3) ejs: 3.1.8 ignore: 5.2.0 - nx: 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51) + nx: 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51) semver: 7.3.4 tmp: 0.2.1 tslib: 2.5.3 @@ -6608,18 +6742,18 @@ packages: - typescript dev: true - /@nrwl/devkit@16.6.0-beta.4(nx@16.6.0-beta.4): - resolution: {integrity: sha512-chfHRQk7DKt4/Z3UHtr6yPXXOEHqXma+Dsnu7B/P3NGrSTkdcq0G8ytO24jkCX28RQnO/95S/4EYrM9dyeoouQ==} + /@nrwl/devkit@16.6.0-beta.5(nx@16.6.0-beta.5): + resolution: {integrity: sha512-f0Kq0dXbbTa032xmabnqA0OKzDGDTCLEqftk1cQSvAWW45jFNqbmP+nhzMV7/GGxdsd5/tVvWCE2L1vTUMPRdA==} dependencies: - '@nx/devkit': 16.6.0-beta.4(nx@16.6.0-beta.4) + '@nx/devkit': 16.6.0-beta.5(nx@16.6.0-beta.5) transitivePeerDependencies: - nx dev: true - /@nrwl/eslint-plugin-nx@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(@typescript-eslint/parser@5.60.1)(eslint-config-prettier@8.5.0)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-sGiNVikCBr3jc14YuJGUcFNISAjVnk0tleJRv8h98E8o02O0MpNwNdPiVmLF2nK4jCy9+X1tsrIko61+sOusFg==} + /@nrwl/eslint-plugin-nx@16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(@typescript-eslint/parser@5.60.1)(eslint-config-prettier@8.5.0)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-v59w9RgH4wRmNWl7DYjOkUdO0p+VSr6CYEC6BKEbr8+n8QstlJyddZHabWGOaOwSqdybvYiBz5f9TLWdkDIarQ==} dependencies: - '@nx/eslint-plugin': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(@typescript-eslint/parser@5.60.1)(eslint-config-prettier@8.5.0)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/eslint-plugin': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(@typescript-eslint/parser@5.60.1)(eslint-config-prettier@8.5.0)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -6636,10 +6770,10 @@ packages: - verdaccio dev: true - /@nrwl/jest@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-I2YMuBuD2+3HryDZy0JImw1ARHZdqjsza1iUeRbtfI8L10CfgiqQMedr9XmMSGcJiVA609iW6zQptRE3Y1y90Q==} + /@nrwl/jest@16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-nelWPin3nsHJNl/4k9TLUrgT6sUQkjISEboc6/AiY3Xs+4eSh3mdAfuor3R9gf6A8+C48vGmTMt/J0G0JaE5YQ==} dependencies: - '@nx/jest': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/jest': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4) transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -6655,7 +6789,7 @@ packages: - verdaccio dev: true - /@nrwl/js@15.8.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.6.0-beta.4)(prettier@2.7.1)(typescript@5.1.3): + /@nrwl/js@15.8.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.6.0-beta.5)(prettier@2.7.1)(typescript@5.1.3): resolution: {integrity: sha512-l2Q7oFpzx6ul7G0nKpMkrvnIEaOY+X8fc2g2Db5WqpnnBdfkrtWXZPg/O4DQ1p9O6BXrZ+Q2AK9bfgnliiwyEg==} dependencies: '@babel/core': 7.22.9 @@ -6665,7 +6799,7 @@ packages: '@babel/preset-env': 7.22.5(@babel/core@7.22.9) '@babel/preset-typescript': 7.22.5(@babel/core@7.22.9) '@babel/runtime': 7.22.6 - '@nrwl/devkit': 15.8.0(nx@16.6.0-beta.4)(typescript@5.1.3) + '@nrwl/devkit': 15.8.0(nx@16.6.0-beta.5)(typescript@5.1.3) '@nrwl/workspace': 15.8.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(prettier@2.7.1)(typescript@5.1.3) '@phenomnomnominal/tsquery': 4.1.1(typescript@5.1.3) babel-plugin-const-enum: 1.2.0(@babel/core@7.22.9) @@ -6692,10 +6826,46 @@ packages: - typescript dev: true - /@nrwl/js@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-jiwWyK0/6LWf/KDBp3cFhCxmN4kczXPN+lN2CpBS+ALtEDTVYQHofllAFEc0j9sXAMqu3cOvugxSS5VYheOk9A==} + /@nrwl/js@15.8.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(nx@15.8.0)(prettier@2.7.1)(typescript@5.1.3): + resolution: {integrity: sha512-l2Q7oFpzx6ul7G0nKpMkrvnIEaOY+X8fc2g2Db5WqpnnBdfkrtWXZPg/O4DQ1p9O6BXrZ+Q2AK9bfgnliiwyEg==} + dependencies: + '@babel/core': 7.22.9 + '@babel/plugin-proposal-class-properties': 7.18.6(@babel/core@7.22.9) + '@babel/plugin-proposal-decorators': 7.21.0(@babel/core@7.22.9) + '@babel/plugin-transform-runtime': 7.22.9(@babel/core@7.22.9) + '@babel/preset-env': 7.22.5(@babel/core@7.22.9) + '@babel/preset-typescript': 7.22.5(@babel/core@7.22.9) + '@babel/runtime': 7.22.6 + '@nrwl/devkit': 15.8.0(nx@15.8.0)(typescript@5.1.3) + '@nrwl/workspace': 15.8.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(prettier@2.7.1)(typescript@5.1.3) + '@phenomnomnominal/tsquery': 4.1.1(typescript@5.1.3) + babel-plugin-const-enum: 1.2.0(@babel/core@7.22.9) + babel-plugin-macros: 2.8.0 + babel-plugin-transform-typescript-metadata: 0.3.2(@babel/core@7.22.9) + chalk: 4.1.2 + fast-glob: 3.2.7 + fs-extra: 11.1.1 + ignore: 5.2.0 + js-tokens: 4.0.0 + minimatch: 3.0.5 + source-map-support: 0.5.19 + tree-kill: 1.2.2 + tslib: 2.5.3 + transitivePeerDependencies: + - '@babel/traverse' + - '@swc-node/register' + - '@swc/core' + - debug + - nx + - prettier + - supports-color + - typescript + dev: true + + /@nrwl/js@16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-zXf/M5pUcxwRttWHeEZHgfCNMX/TaMkUakwC2EypA+5Fhpc7bllEjVRsOvABh6i6yCMeRqAlhwutvMNYwyYEMw==} dependencies: - '@nx/js': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/js': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -6718,7 +6888,7 @@ packages: optional: true dependencies: '@nrwl/devkit': 15.8.0(nx@15.8.0)(typescript@5.1.3) - '@nrwl/js': 15.8.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.6.0-beta.4)(prettier@2.7.1)(typescript@5.1.3) + '@nrwl/js': 15.8.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(nx@15.8.0)(prettier@2.7.1)(typescript@5.1.3) '@phenomnomnominal/tsquery': 4.1.1(typescript@5.1.3) eslint: 8.15.0 tmp: 0.2.1 @@ -6734,10 +6904,10 @@ packages: - typescript dev: true - /@nrwl/linter@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-CpeDd7G2oMgY53jDdE9XPdD6GwD4xMIWnNI1agZBxpXZ80DNTEOFf+3NSeTSUl+eQII6obCfAEmwtHK90pjZDQ==} + /@nrwl/linter@16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-w7rtPVLMwmW7DEiVb2F80axM9j/cgF2TPgueUFIFmXpJcX0VNqogf0rokEhajPvtQkZWs9N6t3kchRqIG9QZtw==} dependencies: - '@nx/linter': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/linter': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -6752,17 +6922,16 @@ packages: - verdaccio dev: true - /@nrwl/next@16.6.0-beta.4(@babel/core@7.22.9)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/express@4.17.14)(@types/node@18.16.9)(eslint@8.15.0)(file-loader@6.2.0)(next@13.3.4)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0): - resolution: {integrity: sha512-A7hxhoSWOwA73HiUCD+Ns8BqoewcxIAPgune0C83vP6kdCTPSLe3udiACWSnebml5KEzzx026sovi3r5z4w1/w==} + /@nrwl/next@16.6.0-beta.5(@babel/core@7.22.9)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(file-loader@6.2.0)(next@13.3.4)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0): + resolution: {integrity: sha512-qXTb4w8+5C5qm/CK982H1s6yk7okIhVs9c5Ip8EP33cUhst3pmHLp/d8LaRszL/eJK5ABYAX88YtuWYvwvXesQ==} dependencies: - '@nx/next': 16.6.0-beta.4(@babel/core@7.22.9)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/express@4.17.14)(@types/node@18.16.9)(eslint@8.15.0)(file-loader@6.2.0)(next@13.3.4)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) + '@nx/next': 16.6.0-beta.5(@babel/core@7.22.9)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(file-loader@6.2.0)(next@13.3.4)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) transitivePeerDependencies: - '@babel/core' - '@babel/traverse' - '@swc-node/register' - '@swc/core' - '@swc/wasm' - - '@types/express' - '@types/node' - debug - eslint @@ -6945,10 +7114,10 @@ packages: dev: true optional: true - /@nrwl/react@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0): - resolution: {integrity: sha512-ZcWD0VcStqPXI/3tvfbUqJMAAQw95hl5SxWiGbiLgtMLcKn4Jg/PolMgCyQIMTKtfEo8Sqa/X0JwD8sOfokmWA==} + /@nrwl/react@16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0): + resolution: {integrity: sha512-6DFjCd0XTPrUjX+R8zKJ3FsP+hckAtrfhg+t3mw6ZnMDFCZXvUw+xtH4OvJHmdlvC+keIfB7w8IAVjypMoeVrQ==} dependencies: - '@nx/react': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) + '@nx/react': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -6964,10 +7133,10 @@ packages: - webpack dev: true - /@nrwl/storybook@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-Wd6xTN1udNIXNLARMs/l3DtODmyxf5K+wRzlyCfPkFtcvC039kSWiJ1v/sJxShbZd48+mZskaiUmMuJHjJPyEA==} + /@nrwl/storybook@16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-LSQFq0uxEqghtKG8Q+n1j7MMB3kU2XVy2WFRJuqiiKeFftpaRvekXm8hlJcVbKGI5SnLatuIuvvYacl90tf27w==} dependencies: - '@nx/storybook': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/storybook': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -7005,21 +7174,22 @@ packages: - debug dev: true - /@nrwl/tao@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51): - resolution: {integrity: sha512-wOKV3mBZEQUYKPn6lHSJeDAJm8UPc3carEwgO8etcrZNBCTq+OepYFJoOUukxavIIgf10KqfDT1lAwaeiip0pA==} + /@nrwl/tao@16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51): + resolution: {integrity: sha512-za4HgI0d6UxBwSawcCLZIlAf4rYnNOTSgBo5ysk0+4KGMTG2dVdZzxXbpCVrKgtbBC9kX3P3S/Lll5fgraHwww==} hasBin: true dependencies: - nx: 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51) + nx: 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51) + tslib: 2.5.3 transitivePeerDependencies: - '@swc-node/register' - '@swc/core' - debug dev: true - /@nrwl/web@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-Amtecs/uuy6eRSNl0FGWa3kfe3a9lYqZ17kmX4CGVcZ8aTYmhVkpGlcjeZvm8desnXBX/ESOXFHJpj/oxPvymw==} + /@nrwl/web@16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-lot+YMykAD+3Ntsd5o20Bk9jhtUqQw8+VQ0uxY6SbcMCNnsGxruShdvq5xIJj3gYVt2US+d/PQFUGjjccyHMHQ==} dependencies: - '@nx/web': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/web': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -7033,10 +7203,10 @@ packages: - verdaccio dev: true - /@nrwl/webpack@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(esbuild@0.17.5)(html-webpack-plugin@5.5.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-kmGfkZxLxovPWOZrEhxc9QpOtpnbqCk2QVWF9liMkQdP7+3i4qOJ+ndw9QBBAQ7u8pG/i1DPAMFyB4Yt7n6b+g==} + /@nrwl/webpack@16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(esbuild@0.17.5)(html-webpack-plugin@5.5.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-wUSGyk2frLhNx4mFgUe1LxFO40Z7vE5DEFia5vDUB/RsFyT5+2J2B7OkytR0uqI9d7i7waq1UPhtlP44glON5Q==} dependencies: - '@nx/webpack': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(esbuild@0.17.5)(html-webpack-plugin@5.5.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/webpack': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(esbuild@0.17.5)(html-webpack-plugin@5.5.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) transitivePeerDependencies: - '@babel/traverse' - '@parcel/css' @@ -7106,10 +7276,10 @@ packages: - typescript dev: true - /@nrwl/workspace@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51): - resolution: {integrity: sha512-q9uADz1YJGB/ZtSKsrKzKnN91nbcin4DPFKrxaNAG+XgEM4hhzdjC7W2+BNzsRkywEFE/pqGWtbpGqeGfSpgGg==} + /@nrwl/workspace@16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51): + resolution: {integrity: sha512-8ZTbqN19mEBh3qQ8T97gsLfUDOUp9vHfzZSEmd+O5YDjx7zSm3Rjjp0q849S4arOamadDiLl6A4A1Yw7WIsVmg==} dependencies: - '@nx/workspace': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51) + '@nx/workspace': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51) transitivePeerDependencies: - '@swc-node/register' - '@swc/core' @@ -7128,23 +7298,24 @@ packages: - encoding dev: true - /@nx/cypress@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-Co6g6CytxxY+ts9ns0Xah+oAO9CZ6oo8DJ6y8JoKHsZY9Oa28IZ/IOEwYMUGzo/maXAz8tVpzZYclN/sTFAs/A==} + /@nx/cypress@16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-DaiulZu+zql7s2VA8ERjaySNKWRMUjdHZWJTRk/QHjqapx2ScwiX0DBylTv5Yx0bZqcTek4ohV4z0KOeU+Eqpw==} peerDependencies: cypress: '>= 3 < 13' peerDependenciesMeta: cypress: optional: true dependencies: - '@nrwl/cypress': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/devkit': 16.6.0-beta.4(nx@16.6.0-beta.4) - '@nx/js': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/linter': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + '@nrwl/cypress': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/devkit': 16.6.0-beta.5(nx@16.6.0-beta.5) + '@nx/js': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/linter': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) '@phenomnomnominal/tsquery': 5.0.1(typescript@5.1.3) cypress: 12.16.0 detect-port: 1.5.1 dotenv: 10.0.0 semver: 7.5.3 + tslib: 2.5.3 transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -7159,22 +7330,22 @@ packages: - verdaccio dev: true - /@nx/devkit@16.6.0-beta.4(nx@16.6.0-beta.4): - resolution: {integrity: sha512-0+b12edK/Q5+JN3hnmzsK8MLcwGeTDmnca23q5+eayXQf4kOmwM9zbYM10PrWpYgN1c7Ltx4k09RP4J9HpBYbg==} + /@nx/devkit@16.6.0-beta.5(nx@16.6.0-beta.5): + resolution: {integrity: sha512-RAmwDwQ6wzeLCO3IXvNnJQrb86DbEYXHpNrCWDmzx0QCt15VCp09YnqnuIaZ66gIoGBHXgwmhk8igs7RWCPYaw==} peerDependencies: nx: '>= 15 <= 17' dependencies: - '@nrwl/devkit': 16.6.0-beta.4(nx@16.6.0-beta.4) + '@nrwl/devkit': 16.6.0-beta.5(nx@16.6.0-beta.5) ejs: 3.1.8 ignore: 5.2.0 - nx: 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51) + nx: 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51) semver: 7.5.3 tmp: 0.2.1 tslib: 2.5.3 dev: true - /@nx/eslint-plugin@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(@typescript-eslint/parser@5.60.1)(eslint-config-prettier@8.5.0)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-deIVitlkRs3wA9OKLanPokfnL+lGwh3LrVEwvvOsUkoyGhd77/PtjbCMDcN96oE7vYCNdSXPJ8Gli1Z0qDI7Mg==} + /@nx/eslint-plugin@16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(@typescript-eslint/parser@5.60.1)(eslint-config-prettier@8.5.0)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-UIdQcm7usqbU2Ac9YIm3Rd3i4ikyaQ6k6/gQkeibMS/usMefXFqqNwXWsE0aPV+fKwJCDgZwJ57pdn4rXcPB4Q==} peerDependencies: '@typescript-eslint/parser': ^5.60.1 eslint-config-prettier: ^8.1.0 @@ -7182,9 +7353,9 @@ packages: eslint-config-prettier: optional: true dependencies: - '@nrwl/eslint-plugin-nx': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(@typescript-eslint/parser@5.60.1)(eslint-config-prettier@8.5.0)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/devkit': 16.6.0-beta.4(nx@16.6.0-beta.4) - '@nx/js': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + '@nrwl/eslint-plugin-nx': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(@typescript-eslint/parser@5.60.1)(eslint-config-prettier@8.5.0)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/devkit': 16.6.0-beta.5(nx@16.6.0-beta.5) + '@nx/js': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) '@typescript-eslint/parser': 5.60.1(eslint@8.15.0)(typescript@5.1.3) '@typescript-eslint/type-utils': 5.60.1(eslint@8.15.0)(typescript@5.1.3) '@typescript-eslint/utils': 5.60.1(eslint@8.15.0)(typescript@5.1.3) @@ -7193,6 +7364,7 @@ packages: eslint-config-prettier: 8.5.0(eslint@8.15.0) jsonc-eslint-parser: 2.1.0 semver: 7.5.3 + tslib: 2.5.3 transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -7207,14 +7379,14 @@ packages: - verdaccio dev: true - /@nx/jest@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-Yb3CcWNlN89n+t15SuP20jIliHro5hPtlc5hktAEjXhj08o0YkjRequ8jUFjlAswdLPwrQlMUHZCQiqw5vySUg==} + /@nx/jest@16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-PDCj18LiT4EsSqk9iuSPWTFG3kpd/+eEx8+5NamLyiDkWSKKQl5IGoa7glf59Nb2Yv8dKs1/3C+qMfrp0mqvFg==} dependencies: '@jest/reporters': 29.5.0 '@jest/test-result': 29.5.0 - '@nrwl/jest': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/devkit': 16.6.0-beta.4(nx@16.6.0-beta.4) - '@nx/js': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + '@nrwl/jest': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/devkit': 16.6.0-beta.5(nx@16.6.0-beta.5) + '@nx/js': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) '@phenomnomnominal/tsquery': 5.0.1(typescript@5.1.3) chalk: 4.1.2 dotenv: 10.0.0 @@ -7239,8 +7411,8 @@ packages: - verdaccio dev: true - /@nx/js@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-Up4CPVzKIM6LGyhml5EkrXzVtx/fM9x67DbYEsFENAD0exlblrHdHf0XAsXP0Wc8ClhQnCH4F5O8b4T2/3HtRg==} + /@nx/js@16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-Gd8CC/RHVCSru5j9zt1uOHHpjfl7Cv/X4eLkWOXFrKssn5HR+Z1X/uIJEw5OyyVzIREnczHi5J9i2s3A3kZsHA==} peerDependencies: verdaccio: ^5.0.4 peerDependenciesMeta: @@ -7249,14 +7421,14 @@ packages: dependencies: '@babel/core': 7.22.9 '@babel/plugin-proposal-class-properties': 7.18.6(@babel/core@7.22.9) - '@babel/plugin-proposal-decorators': 7.21.0(@babel/core@7.22.9) + '@babel/plugin-proposal-decorators': 7.22.7(@babel/core@7.22.9) '@babel/plugin-transform-runtime': 7.22.9(@babel/core@7.22.9) - '@babel/preset-env': 7.22.5(@babel/core@7.22.9) + '@babel/preset-env': 7.22.9(@babel/core@7.22.9) '@babel/preset-typescript': 7.22.5(@babel/core@7.22.9) '@babel/runtime': 7.22.6 - '@nrwl/js': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/devkit': 16.6.0-beta.4(nx@16.6.0-beta.4) - '@nx/workspace': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51) + '@nrwl/js': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/devkit': 16.6.0-beta.5(nx@16.6.0-beta.5) + '@nx/workspace': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51) '@phenomnomnominal/tsquery': 5.0.1(typescript@5.1.3) babel-plugin-const-enum: 1.2.0(@babel/core@7.22.9) babel-plugin-macros: 2.8.0 @@ -7286,17 +7458,17 @@ packages: - typescript dev: true - /@nx/linter@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-CVtAutv8TrJ7inet/cUeXs2z3uQ7uajPkccQiisDAJR30dx4s0xNuiqKPNNy0LelWX3Q2lhycZDbNcn1cwtMSQ==} + /@nx/linter@16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-6qNPxGGy/BkPBi2MxyrB+0rqdWTMiXMqu/p76PJGUzP1SFRmpZaUJuOCfi83nsX/rnWphgaBTJ2LsQX62UPAUQ==} peerDependencies: eslint: ^8.0.0 peerDependenciesMeta: eslint: optional: true dependencies: - '@nrwl/linter': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/devkit': 16.6.0-beta.4(nx@16.6.0-beta.4) - '@nx/js': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + '@nrwl/linter': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/devkit': 16.6.0-beta.5(nx@16.6.0-beta.5) + '@nx/js': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) '@phenomnomnominal/tsquery': 5.0.1(typescript@5.1.3) eslint: 8.15.0 tmp: 0.2.1 @@ -7314,29 +7486,28 @@ packages: - verdaccio dev: true - /@nx/next@16.6.0-beta.4(@babel/core@7.22.9)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/express@4.17.14)(@types/node@18.16.9)(eslint@8.15.0)(file-loader@6.2.0)(next@13.3.4)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0): - resolution: {integrity: sha512-anknmoeDinyu+gV9j2fiYZUtgtXeXiNTzcaJp3aeSM9121huwHnQHMnBikNBnzG4h082vPppD0oE4cORz1HWUQ==} + /@nx/next@16.6.0-beta.5(@babel/core@7.22.9)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(file-loader@6.2.0)(next@13.3.4)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0): + resolution: {integrity: sha512-Bi5KLlsT7m9wHB3iw6rgu3bGTyMnmS7/DfXRDkqtefzB6uMHEER1E/u7PRILplQ24kkNLfO4wCrqP+yz1fTHxQ==} peerDependencies: next: '>=13.0.0' dependencies: - '@babel/plugin-proposal-decorators': 7.21.0(@babel/core@7.22.9) - '@nrwl/next': 16.6.0-beta.4(@babel/core@7.22.9)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/express@4.17.14)(@types/node@18.16.9)(eslint@8.15.0)(file-loader@6.2.0)(next@13.3.4)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) - '@nx/devkit': 16.6.0-beta.4(nx@16.6.0-beta.4) - '@nx/js': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/linter': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/react': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) - '@nx/web': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/workspace': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51) + '@babel/plugin-proposal-decorators': 7.22.7(@babel/core@7.22.9) + '@nrwl/next': 16.6.0-beta.5(@babel/core@7.22.9)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(file-loader@6.2.0)(next@13.3.4)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) + '@nx/devkit': 16.6.0-beta.5(nx@16.6.0-beta.5) + '@nx/js': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/linter': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/react': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) + '@nx/web': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/workspace': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51) '@svgr/webpack': 8.0.1 chalk: 4.1.2 copy-webpack-plugin: 10.2.4(webpack@5.88.0) dotenv: 10.0.0 - express: 4.18.2 fs-extra: 11.1.1 - http-proxy-middleware: 2.0.6(@types/express@4.17.14) ignore: 5.2.0 next: 13.3.4(@babel/core@7.22.9)(react-dom@18.2.0)(react@18.2.0)(sass@1.55.0) semver: 7.5.3 + tslib: 2.5.3 url-loader: 4.1.1(file-loader@6.2.0)(webpack@5.88.0) webpack-merge: 5.9.0 transitivePeerDependencies: @@ -7345,7 +7516,6 @@ packages: - '@swc-node/register' - '@swc/core' - '@swc/wasm' - - '@types/express' - '@types/node' - debug - eslint @@ -7357,8 +7527,8 @@ packages: - webpack dev: true - /@nx/nx-darwin-arm64@16.6.0-beta.4: - resolution: {integrity: sha512-WosSKoGph13tVtiO9oJXz0m+eAvOFXhoox2GTtesa76LSLOp1kMYfiCkRnAaEZimYD+ncshhqS3EHoomnwh1+w==} + /@nx/nx-darwin-arm64@16.6.0-beta.5: + resolution: {integrity: sha512-e7M/qBpnFSeCIvkqx91XV81TsGutv0Gh1TlxvJlXbhCCVfSyWayQjjhL2Q653nICZmh4uGra+6IHXFqkCQr3Iw==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] @@ -7366,8 +7536,8 @@ packages: dev: true optional: true - /@nx/nx-darwin-x64@16.6.0-beta.4: - resolution: {integrity: sha512-wTR4akGjY8+CPNO/AYh9UeuTH9EyEPx4Kwp+Z63CEbDF8oe2BBVtMWz3XHHm7KKnPOWzOXADi7gE/FI5HTAMvA==} + /@nx/nx-darwin-x64@16.6.0-beta.5: + resolution: {integrity: sha512-0v/SRVqZCfRAV+k/dBrFOzScCgaM+lJyhw4xm3zI8ZoAr0/u7/7IBzpB0Lr4R10zWAhuyCqO3Cu2Jbs2/MWcsA==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] @@ -7375,8 +7545,8 @@ packages: dev: true optional: true - /@nx/nx-freebsd-x64@16.6.0-beta.4: - resolution: {integrity: sha512-at3qt49FMBHG75p3Sbngy3b/H4fXAz80MhejcDS0CmyJJWZMgGIat9bXGkpQqZKVrAkk8EMhVcV972FlJZIYog==} + /@nx/nx-freebsd-x64@16.6.0-beta.5: + resolution: {integrity: sha512-ga81tbBIn0vLaJxxab7i5Lv49haVIIb3/z6gQ8wzhKKynbTElE5JxwjvKLkPIV2e3iop57sXuTlM8u6AwLBXwg==} engines: {node: '>= 10'} cpu: [x64] os: [freebsd] @@ -7384,8 +7554,8 @@ packages: dev: true optional: true - /@nx/nx-linux-arm-gnueabihf@16.6.0-beta.4: - resolution: {integrity: sha512-tWUb3GlYnWdC7Z3RAdbs6A4tc26187eaWBI7Rt5rVmXOqa5pIm5J0QHEAD4IctcY38z9HPehgi3cYjihOprCQA==} + /@nx/nx-linux-arm-gnueabihf@16.6.0-beta.5: + resolution: {integrity: sha512-uj5jsV0JJd88BHxAcL693i/b7ndd4yytakiAu+3A/BHZsUMY35mrMGz8e7mkC3rrY0EBBSVVzRmmsAiBn7ChAA==} engines: {node: '>= 10'} cpu: [arm] os: [linux] @@ -7393,8 +7563,8 @@ packages: dev: true optional: true - /@nx/nx-linux-arm64-gnu@16.6.0-beta.4: - resolution: {integrity: sha512-kMBCWIeQd4wzs8COXaeD71+LkLG+lsq99JpTGmQHXa1QB9rm4NBTtcixtveAWssqF8i7WNSpxlD1zo6z04HO4g==} + /@nx/nx-linux-arm64-gnu@16.6.0-beta.5: + resolution: {integrity: sha512-RGRlrdJgZ9w9r2iIWQtPhIlHKtnjyJnjmN4pnLlHpM0xluhR0nq3LQFUnI9QLkSqGIavWAj+GOhctFsdrSIKvg==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -7402,8 +7572,8 @@ packages: dev: true optional: true - /@nx/nx-linux-arm64-musl@16.6.0-beta.4: - resolution: {integrity: sha512-tiXZq2MHUMnyE5IBdZmaes3fNSPCkL9w+phQ7Fu33Rhvr9ZWcVudYmXhVxxPaznPT1r95Lg+mitegiKwzNKsFw==} + /@nx/nx-linux-arm64-musl@16.6.0-beta.5: + resolution: {integrity: sha512-NO5l/6788TkzXZzhkIZPGdj/K99Cf0F7HRclOU91D46z91t26ByQIJTYrdky3pwT+f1hV9xVMgDkia1QzaR5Qg==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -7411,8 +7581,8 @@ packages: dev: true optional: true - /@nx/nx-linux-x64-gnu@16.6.0-beta.4: - resolution: {integrity: sha512-3Ku1Gpq7LC+FOQbKVesRDp5Sfdh6EPeOpKW2tZduqS3xht++/7HdP6dF8825mxykOg6DFRdO+c66r8k8kijxMQ==} + /@nx/nx-linux-x64-gnu@16.6.0-beta.5: + resolution: {integrity: sha512-Sk7U5r+h5j5UCDnkNtlpCZo5rYe/DKPL3R+gtZ44o76BIbxO9TxY0pSD1SSX5kAdqXx8CkpWAc7fgchzZTN3tA==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -7420,8 +7590,8 @@ packages: dev: true optional: true - /@nx/nx-linux-x64-musl@16.6.0-beta.4: - resolution: {integrity: sha512-hQZJVtxsVmENUvwLjSuJ25OhvwM2Oi+4Em9rjWtChUNwQdMPYRDBl3RsUEtGbStGRWu0AnDbXh+TDo/4tV1FgA==} + /@nx/nx-linux-x64-musl@16.6.0-beta.5: + resolution: {integrity: sha512-fweJs+hKV0xLJ8V3YDvR9M9TcTsfMsOz0I0pUEzsYQi0P6SAajIMNJS3v0auE//pXNq6gJWJJ8cLifGW57yUTw==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -7429,8 +7599,8 @@ packages: dev: true optional: true - /@nx/nx-win32-arm64-msvc@16.6.0-beta.4: - resolution: {integrity: sha512-C7ptavIq4KqxNectfgsQRvR98vpB/c7GA3Xrj+PCrg6o5qLrAQ8qycla05IcfAiSF409oERrJCVqmCHJJQax8A==} + /@nx/nx-win32-arm64-msvc@16.6.0-beta.5: + resolution: {integrity: sha512-8pK7z0nfwR7yxoFdWoecuTd1NxJk3IJ1Ymef1lN6p2XG/uS/clCfHddO8g5nbilHRrNqQuEwOgksDsMsPhyNVg==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] @@ -7438,8 +7608,8 @@ packages: dev: true optional: true - /@nx/nx-win32-x64-msvc@16.6.0-beta.4: - resolution: {integrity: sha512-KvZ0/nnlIJgQKjLmMmjU18MvF4Lj8SapC4LHzyPaYVk3SkGZ5o5sHZ29J1RY7BcQ3GV51Azgdh9W8alu2z/oMA==} + /@nx/nx-win32-x64-msvc@16.6.0-beta.5: + resolution: {integrity: sha512-uQhRW5VqR8FeGffZhJoK1BJtTNF76xB877bzPxQZ3ZCPhkvZTfZnlsqOIHFbH2ROtt/SQkAUaeu5zjJ9Bz/mfQ==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -7447,19 +7617,20 @@ packages: dev: true optional: true - /@nx/react@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0): - resolution: {integrity: sha512-HeR6Maai48MvJxrIxUDhdrIl3XrcSULgdRpWAdO2Chugq8vOOGha5NHQ943UuXyqSsLb8+/VNCldAPPmZ27U4w==} + /@nx/react@16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0): + resolution: {integrity: sha512-17kgJPC25+fMmvVW7qd1DKLXlj+UldGxJJal+0DN+2Hpt5Voip4aJXSE1/UFp3h7AAeJqPovK9DvouYzTY39ig==} dependencies: - '@nrwl/react': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) - '@nx/devkit': 16.6.0-beta.4(nx@16.6.0-beta.4) - '@nx/js': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/linter': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/web': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + '@nrwl/react': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) + '@nx/devkit': 16.6.0-beta.5(nx@16.6.0-beta.5) + '@nx/js': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/linter': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/web': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) '@phenomnomnominal/tsquery': 5.0.1(typescript@5.1.3) '@svgr/webpack': 8.0.1 chalk: 4.1.2 file-loader: 6.2.0(webpack@5.88.0) minimatch: 3.0.5 + tslib: 2.5.3 transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -7475,18 +7646,19 @@ packages: - webpack dev: true - /@nx/storybook@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-FvW8OdmoitnB727YpqzP3gCTkK+3SF3GPXpGL4SOhlj842G6ey+9BQqRNHFbeaMxgzrRSTnyyDZznmLt//EsxQ==} + /@nx/storybook@16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-G1oILSZl2Sk9zhynonqLZF0nCiE3+M35Nkr1+oEeSOOJL4FFZbpk9/Uj9cG9ai+gXLfeH/Ec+37FG1TMWl98aA==} dependencies: - '@nrwl/storybook': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/cypress': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/devkit': 16.6.0-beta.4(nx@16.6.0-beta.4) - '@nx/js': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/linter': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/workspace': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51) + '@nrwl/storybook': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/cypress': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/devkit': 16.6.0-beta.5(nx@16.6.0-beta.5) + '@nx/js': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/linter': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/workspace': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51) '@phenomnomnominal/tsquery': 5.0.1(typescript@5.1.3) dotenv: 10.0.0 semver: 7.5.3 + tslib: 2.5.3 transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -7502,12 +7674,12 @@ packages: - verdaccio dev: true - /@nx/web@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-xSUm82LZ8G3Y0iJO7AIiHk8iAIG+sP7OKhjhUHhsm8mtSfSY81+i5FXuld/t+aQ6+RIqgTVWaIN78x9BCVhq2w==} + /@nx/web@16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-rReLXiZmVIBlz5BwSZJWt+fbpmDK3eY4nHqAyWTWF1hp5suRU5r8qq4d7hWgEhqJXoAHRficiFmpI4/pco4HSg==} dependencies: - '@nrwl/web': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/devkit': 16.6.0-beta.4(nx@16.6.0-beta.4) - '@nx/js': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + '@nrwl/web': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/devkit': 16.6.0-beta.5(nx@16.6.0-beta.5) + '@nx/js': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) chalk: 4.1.2 chokidar: 3.5.3 detect-port: 1.5.1 @@ -7527,16 +7699,16 @@ packages: - verdaccio dev: true - /@nx/webpack@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(esbuild@0.17.5)(html-webpack-plugin@5.5.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-y3mI85ZsHgK3ebuzeOaVNTGNEqdFsD/8pBx7HhumiSO7xqKfgRsvVWdN6EPn2a3HwRj2JgjrdBBIWu+nItIp8A==} + /@nx/webpack@16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(esbuild@0.17.5)(html-webpack-plugin@5.5.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-LJEgRLzhdpgvf1Zd8H8cqvZrqhgYccli0v9dddkCzbtCFHWAZk5zKjaWqhq912rSIji+s+cUidqX9ypV/HL8aw==} dependencies: '@babel/core': 7.22.9 - '@nrwl/webpack': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(esbuild@0.17.5)(html-webpack-plugin@5.5.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/devkit': 16.6.0-beta.4(nx@16.6.0-beta.4) - '@nx/js': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + '@nrwl/webpack': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(esbuild@0.17.5)(html-webpack-plugin@5.5.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/devkit': 16.6.0-beta.5(nx@16.6.0-beta.5) + '@nx/js': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) autoprefixer: 10.4.13(postcss@8.4.19) babel-loader: 9.1.2(@babel/core@7.22.9)(webpack@5.88.0) - browserslist: 4.21.7 + browserslist: 4.21.9 chalk: 4.1.2 chokidar: 3.5.3 copy-webpack-plugin: 10.2.4(webpack@5.88.0) @@ -7597,28 +7769,16 @@ packages: - webpack-cli dev: true - /@nx/workspace@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51): - resolution: {integrity: sha512-KVAEQjrWwMCbcZdiwoSG2PciELCsEZ1PLDX0wywNfJcRb1hK2bZDmswLuI5hxLSst9b7UXNH0PKG5S6QnIc0fw==} + /@nx/workspace@16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51): + resolution: {integrity: sha512-dbLITBHwjbustUk8BLk+NRnz6FxWV0pQGvPjG3X0Er52Rv7+mzdMTfj1g7IW9Bs4qajIe+xUpxjI6X6GgbOr6g==} dependencies: - '@nrwl/workspace': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51) - '@nx/devkit': 16.6.0-beta.4(nx@16.6.0-beta.4) - '@parcel/watcher': 2.0.4 + '@nrwl/workspace': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51) + '@nx/devkit': 16.6.0-beta.5(nx@16.6.0-beta.5) chalk: 4.1.2 - chokidar: 3.5.3 - cli-cursor: 3.1.0 - cli-spinners: 2.6.1 - dotenv: 10.0.0 - figures: 3.2.0 - flat: 5.0.2 ignore: 5.2.0 - minimatch: 3.0.5 - npm-run-path: 4.0.1 - nx: 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51) - open: 8.4.2 + nx: 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51) rxjs: 7.8.1 - tmp: 0.2.1 tslib: 2.5.3 - yargs: 17.7.2 yargs-parser: 21.1.1 transitivePeerDependencies: - '@swc-node/register' @@ -10276,6 +10436,7 @@ packages: /@types/linkify-it@3.0.2: resolution: {integrity: sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==} + requiresBuild: true dev: false optional: true @@ -10301,6 +10462,7 @@ packages: /@types/mdurl@1.0.2: resolution: {integrity: sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==} + requiresBuild: true dev: false optional: true @@ -11983,7 +12145,7 @@ packages: dependencies: '@babel/core': 7.22.9 '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-typescript': 7.20.0(@babel/core@7.22.9) + '@babel/plugin-syntax-typescript': 7.22.5(@babel/core@7.22.9) '@babel/traverse': 7.22.8 transitivePeerDependencies: - supports-color @@ -12613,6 +12775,7 @@ packages: /buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + dev: true /buffer-indexof-polyfill@1.0.2: resolution: {integrity: sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==} @@ -13220,6 +13383,7 @@ packages: /commander@2.20.3: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + dev: true /commander@4.1.1: resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} @@ -21117,8 +21281,8 @@ packages: - debug dev: true - /nx@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51): - resolution: {integrity: sha512-hbiYe4cxLBMTYO9sjLg6N3gh709Cf38tVXxbzv1y3ZXaRA2nyH6NSerk+VP7Om7IxQku8RTItscZqM8qsb4/mA==} + /nx@16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51): + resolution: {integrity: sha512-rz8yq62Prkp5uuMckxkmoJfwSk7RjNR/UXvDfZr3laZuXv4ORRG+y7LFFG5mpKX0AlD3dkrZvVds6qBT12QIJQ==} hasBin: true requiresBuild: true peerDependencies: @@ -21130,7 +21294,7 @@ packages: '@swc/core': optional: true dependencies: - '@nrwl/tao': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51) + '@nrwl/tao': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51) '@parcel/watcher': 2.0.4 '@swc-node/register': 1.5.4(@swc/core@1.3.51)(typescript@5.1.3) '@swc/core': 1.3.51(@swc/helpers@0.5.0) @@ -21168,16 +21332,16 @@ packages: yargs: 17.7.2 yargs-parser: 21.1.1 optionalDependencies: - '@nx/nx-darwin-arm64': 16.6.0-beta.4 - '@nx/nx-darwin-x64': 16.6.0-beta.4 - '@nx/nx-freebsd-x64': 16.6.0-beta.4 - '@nx/nx-linux-arm-gnueabihf': 16.6.0-beta.4 - '@nx/nx-linux-arm64-gnu': 16.6.0-beta.4 - '@nx/nx-linux-arm64-musl': 16.6.0-beta.4 - '@nx/nx-linux-x64-gnu': 16.6.0-beta.4 - '@nx/nx-linux-x64-musl': 16.6.0-beta.4 - '@nx/nx-win32-arm64-msvc': 16.6.0-beta.4 - '@nx/nx-win32-x64-msvc': 16.6.0-beta.4 + '@nx/nx-darwin-arm64': 16.6.0-beta.5 + '@nx/nx-darwin-x64': 16.6.0-beta.5 + '@nx/nx-freebsd-x64': 16.6.0-beta.5 + '@nx/nx-linux-arm-gnueabihf': 16.6.0-beta.5 + '@nx/nx-linux-arm64-gnu': 16.6.0-beta.5 + '@nx/nx-linux-arm64-musl': 16.6.0-beta.5 + '@nx/nx-linux-x64-gnu': 16.6.0-beta.5 + '@nx/nx-linux-x64-musl': 16.6.0-beta.5 + '@nx/nx-win32-arm64-msvc': 16.6.0-beta.5 + '@nx/nx-win32-x64-msvc': 16.6.0-beta.5 transitivePeerDependencies: - debug dev: true @@ -23315,6 +23479,7 @@ packages: /prr@1.0.1: resolution: {integrity: sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==} + requiresBuild: true optional: true /pseudomap@1.0.2: @@ -24365,6 +24530,7 @@ packages: chokidar: 3.5.3 immutable: 4.1.0 source-map-js: 1.0.2 + dev: true /sax@1.2.4: resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==} @@ -24959,6 +25125,7 @@ packages: dependencies: buffer-from: 1.1.2 source-map: 0.6.1 + dev: true /source-map@0.5.7: resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} @@ -25848,6 +26015,7 @@ packages: acorn: 8.8.2 commander: 2.20.3 source-map-support: 0.5.21 + dev: true /terser@5.18.0: resolution: {integrity: sha512-pdL757Ig5a0I+owA42l6tIuEycRuM7FPY4n62h44mRLRfnOxJkkOHd6i89dOpwZlpF6JXBwaAHF6yWzFrt+QyA==} @@ -26973,7 +27141,7 @@ packages: mlly: 1.2.0 pathe: 1.1.0 picocolors: 1.0.0 - vite: 4.3.9(@types/node@18.16.9)(less@4.1.3)(sass@1.63.2)(stylus@0.59.0)(terser@5.17.7) + vite: 4.3.9(@types/node@18.16.9)(less@4.1.3)(sass@1.55.0)(stylus@0.59.0) transitivePeerDependencies: - '@types/node' - less @@ -27019,6 +27187,42 @@ packages: optionalDependencies: fsevents: 2.3.2 + /vite@4.3.9(@types/node@18.16.9)(less@4.1.3)(sass@1.55.0)(stylus@0.59.0): + resolution: {integrity: sha512-qsTNZjO9NoJNW7KnOrgYwczm0WctJ8m/yqYAMAK9Lxt4SoySUfS5S8ia9K7JHpa3KEeMfyF8LoJ3c5NeBJy6pg==} + engines: {node: ^14.18.0 || >=16.0.0} + hasBin: true + peerDependencies: + '@types/node': '>= 14' + less: '*' + sass: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + dependencies: + '@types/node': 18.16.9 + esbuild: 0.17.19 + less: 4.1.3 + postcss: 8.4.24 + rollup: 3.21.0 + sass: 1.55.0 + stylus: 0.59.0 + optionalDependencies: + fsevents: 2.3.2 + dev: false + /vite@4.3.9(@types/node@18.16.9)(less@4.1.3)(sass@1.63.2)(stylus@0.59.0)(terser@5.17.7): resolution: {integrity: sha512-qsTNZjO9NoJNW7KnOrgYwczm0WctJ8m/yqYAMAK9Lxt4SoySUfS5S8ia9K7JHpa3KEeMfyF8LoJ3c5NeBJy6pg==} engines: {node: ^14.18.0 || >=16.0.0} @@ -27054,6 +27258,7 @@ packages: terser: 5.17.7 optionalDependencies: fsevents: 2.3.2 + dev: true /vitest@0.32.0(less@4.1.3)(sass@1.55.0)(stylus@0.59.0): resolution: {integrity: sha512-SW83o629gCqnV3BqBnTxhB10DAwzwEx3z+rqYZESehUB+eWsJxwcBQx7CKy0otuGMJTYh7qCVuUX23HkftGl/Q==} @@ -27501,7 +27706,7 @@ packages: '@webassemblyjs/wasm-parser': 1.11.1 acorn: 8.8.2 acorn-import-assertions: 1.9.0(acorn@8.8.2) - browserslist: 4.21.7 + browserslist: 4.21.9 chrome-trace-event: 1.0.3 enhanced-resolve: 5.15.0 es-module-lexer: 0.9.3 @@ -28063,7 +28268,3 @@ packages: dependencies: tslib: 2.5.3 dev: true - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false From c599d2fca46c3cbaa56cde681f6ff53921f7c9e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Jona=C5=A1?= Date: Wed, 26 Jul 2023 17:41:31 +0200 Subject: [PATCH 176/262] fix(angular): ensure ssr invokation uses current package manager (#18322) --- .../module-federation-dev-ssr.impl.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/angular/src/builders/module-federation-dev-ssr/module-federation-dev-ssr.impl.ts b/packages/angular/src/builders/module-federation-dev-ssr/module-federation-dev-ssr.impl.ts index eb22895a33553..614cd5783fd82 100644 --- a/packages/angular/src/builders/module-federation-dev-ssr/module-federation-dev-ssr.impl.ts +++ b/packages/angular/src/builders/module-federation-dev-ssr/module-federation-dev-ssr.impl.ts @@ -1,7 +1,11 @@ import type { Schema } from './schema'; import { readProjectsConfigurationFromProjectGraph } from 'nx/src/project-graph/project-graph'; import { getExecutorInformation } from 'nx/src/command-line/run/executor-utils'; -import { readCachedProjectGraph, workspaceRoot } from '@nx/devkit'; +import { + getPackageManagerCommand, + readCachedProjectGraph, + workspaceRoot, +} from '@nx/devkit'; import { getDynamicRemotes, getStaticRemotes, @@ -109,8 +113,9 @@ export function executeModuleFederationDevSSRBuilder( remoteProject.targets.server.options.outputPath, 'main.js' ); + const pm = getPackageManagerCommand(); execSync( - `npx nx run ${remote}:server${ + `${pm.exec} nx run ${remote}:server${ context.target.configuration ? `:${context.target.configuration}` : '' From eef0bd563de9996196e94948468f5e95d7ee89ca Mon Sep 17 00:00:00 2001 From: Jonathan Cammisuli Date: Wed, 26 Jul 2023 12:08:21 -0400 Subject: [PATCH 177/262] chore(core): reenable glob tests (#18320) --- packages/nx/src/native/utils/glob.rs | 30 ++++++++++++++-------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/packages/nx/src/native/utils/glob.rs b/packages/nx/src/native/utils/glob.rs index f874beb9be5e0..9038ebf54edb1 100644 --- a/packages/nx/src/native/utils/glob.rs +++ b/packages/nx/src/native/utils/glob.rs @@ -218,21 +218,21 @@ mod test { #[test] fn should_handle_complex_patterns() { - // let glob_set = - // build_glob_set(&["dist/!(cache|cache2)/**/!(README|LICENSE).(txt|md)"]).unwrap(); - // - // // matches - // assert!(glob_set.is_match("dist/nested/file.txt")); - // assert!(glob_set.is_match("dist/nested/file.md")); - // // no matches - // assert!(!glob_set.is_match("dist/file.txt")); - // assert!(!glob_set.is_match("dist/cache/nested/README.txt")); - // assert!(!glob_set.is_match("dist/nested/LICENSE.md")); - // assert!(!glob_set.is_match("dist/cache/file.txt")); - // assert!(!glob_set.is_match("dist/cache2/file.txt")); - // assert!(!glob_set.is_match("dist/cache2/README.txt")); - // assert!(!glob_set.is_match("dist/LICENSE.md")); - // assert!(!glob_set.is_match("dist/README.txt")); + let glob_set = + build_glob_set(&["dist/!(cache|cache2)/**/!(README|LICENSE).(txt|md)"]).unwrap(); + + // matches + assert!(glob_set.is_match("dist/nested/file.txt")); + assert!(glob_set.is_match("dist/nested/file.md")); + // no matches + assert!(!glob_set.is_match("dist/file.txt")); + assert!(!glob_set.is_match("dist/cache/nested/README.txt")); + assert!(!glob_set.is_match("dist/nested/LICENSE.md")); + assert!(!glob_set.is_match("dist/cache/file.txt")); + assert!(!glob_set.is_match("dist/cache2/file.txt")); + assert!(!glob_set.is_match("dist/cache2/README.txt")); + assert!(!glob_set.is_match("dist/LICENSE.md")); + assert!(!glob_set.is_match("dist/README.txt")); let glob_set = build_glob_set(&["dist/*.(js|ts)"]).unwrap(); // matches From 2b679599721f53516f6a08c75d18d859039a9380 Mon Sep 17 00:00:00 2001 From: Jason Jean Date: Wed, 26 Jul 2023 16:39:22 -0400 Subject: [PATCH 178/262] fix(core): fix migration and warn for invalid outputs (#18310) --- packages/nx/migrations.json | 6 ++++++ .../update-15-0-0/prefix-outputs.spec.ts | 4 ++-- .../migrations/update-15-0-0/prefix-outputs.ts | 17 ++++++++++------- packages/nx/src/tasks-runner/utils.ts | 3 ++- 4 files changed, 20 insertions(+), 10 deletions(-) diff --git a/packages/nx/migrations.json b/packages/nx/migrations.json index f287f739d45ba..cf5fd96773082 100644 --- a/packages/nx/migrations.json +++ b/packages/nx/migrations.json @@ -77,6 +77,12 @@ "version": "16.2.0-beta.0", "description": "Remove outputPath from run commands", "implementation": "./src/migrations/update-16-2-0/remove-run-commands-output-path" + }, + "16.6.0-prefix-outputs": { + "cli": "nx", + "version": "16.6.0-beta.6", + "description": "Prefix outputs with {workspaceRoot}/{projectRoot} if needed", + "implementation": "./src/migrations/update-15-0-0/prefix-outputs" } } } diff --git a/packages/nx/src/migrations/update-15-0-0/prefix-outputs.spec.ts b/packages/nx/src/migrations/update-15-0-0/prefix-outputs.spec.ts index 8f603e04f3ac1..c7f924ae710b9 100644 --- a/packages/nx/src/migrations/update-15-0-0/prefix-outputs.spec.ts +++ b/packages/nx/src/migrations/update-15-0-0/prefix-outputs.spec.ts @@ -91,7 +91,7 @@ describe('15.0.0 migration (prefix-outputs)', () => { nx: { targets: { build: { - outputs: ['dist/proj'], + outputs: ['dist/proj', 'proj/build'], }, }, }, @@ -101,7 +101,7 @@ describe('15.0.0 migration (prefix-outputs)', () => { await prefixOutputs(tree); expect(readJson(tree, 'proj/package.json').nx.targets.build).toEqual({ - outputs: ['dist/proj'], + outputs: ['{workspaceRoot}/dist/proj', '{projectRoot}/build'], }); }); diff --git a/packages/nx/src/migrations/update-15-0-0/prefix-outputs.ts b/packages/nx/src/migrations/update-15-0-0/prefix-outputs.ts index 5f99a0bec689c..6991ff9fb60e1 100644 --- a/packages/nx/src/migrations/update-15-0-0/prefix-outputs.ts +++ b/packages/nx/src/migrations/update-15-0-0/prefix-outputs.ts @@ -23,11 +23,7 @@ export default async function (tree: Tree) { const nxJson = readNxJson(tree); for (const [projectName, project] of getProjects(tree)) { - if (!project.targets) { - continue; - } - - for (const [_, target] of Object.entries(project.targets)) { + for (const [_, target] of Object.entries(project.targets ?? {})) { if (!target.outputs) { continue; } @@ -46,8 +42,15 @@ export default async function (tree: Tree) { tree, join(project.root, 'package.json'), (json) => { - json.nx ??= {}; - json.nx.targets ??= project.targets; + for (const target of Object.values(json.nx?.targets ?? {})) { + if (target.outputs) { + try { + validateOutputs(target.outputs); + } catch (e) { + target.outputs = transformLegacyOutputs(project.root, e); + } + } + } return json; } diff --git a/packages/nx/src/tasks-runner/utils.ts b/packages/nx/src/tasks-runner/utils.ts index 48ea06df4135e..e8501178dacdd 100644 --- a/packages/nx/src/tasks-runner/utils.ts +++ b/packages/nx/src/tasks-runner/utils.ts @@ -164,7 +164,8 @@ export function getOutputsForTargetAndConfiguration( validateOutputs(targetConfiguration.outputs); } catch (error) { if (error instanceof InvalidOutputsError) { - // TODO(v16): start warning for invalid outputs + // TODO(@FrozenPandaz): In v17, throw this error and do not transform. + console.warn(error.message); targetConfiguration.outputs = transformLegacyOutputs( node.data.root, error From aa557a029c0958b8d789a3b8edf1e44ced0cf48a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Jona=C5=A1?= Date: Wed, 26 Jul 2023 22:42:11 +0200 Subject: [PATCH 179/262] fix(core): shell script invocation should use yarn for berry (#18326) --- packages/nx/src/utils/package-manager.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nx/src/utils/package-manager.ts b/packages/nx/src/utils/package-manager.ts index 20eefb184b6af..896f568efbb07 100644 --- a/packages/nx/src/utils/package-manager.ts +++ b/packages/nx/src/utils/package-manager.ts @@ -75,7 +75,7 @@ export function getPackageManagerCommand( add: useBerry ? 'yarn add' : 'yarn add -W', addDev: useBerry ? 'yarn add -D' : 'yarn add -D -W', rm: 'yarn remove', - exec: useBerry ? 'yarn exec' : 'yarn', + exec: 'yarn', run: (script: string, args: string) => `yarn ${script} ${args}`, list: useBerry ? 'yarn info --name-only' : 'yarn list', }; From f113bea262e5600d49953d124be00af9a0741cc9 Mon Sep 17 00:00:00 2001 From: Jason Jean Date: Wed, 26 Jul 2023 17:49:39 -0400 Subject: [PATCH 180/262] Revert "chore(repo): update nx to 16.6.0-beta.5 (#18309)" (#18333) --- package.json | 24 +- pnpm-lock.yaml | 703 ++++++++++++++++++------------------------------- 2 files changed, 263 insertions(+), 464 deletions(-) diff --git a/package.json b/package.json index 654a54c07971c..7b6b20b4f0331 100644 --- a/package.json +++ b/package.json @@ -63,17 +63,17 @@ "@ngrx/router-store": "~16.0.0", "@ngrx/store": "~16.0.0", "@nguniversal/builders": "~16.1.0", - "@nx/cypress": "16.6.0-beta.5", - "@nx/devkit": "16.6.0-beta.5", - "@nx/eslint-plugin": "16.6.0-beta.5", - "@nx/jest": "16.6.0-beta.5", - "@nx/js": "16.6.0-beta.5", - "@nx/linter": "16.6.0-beta.5", - "@nx/next": "16.6.0-beta.5", - "@nx/react": "16.6.0-beta.5", - "@nx/storybook": "16.6.0-beta.5", - "@nx/web": "16.6.0-beta.5", - "@nx/webpack": "16.6.0-beta.5", + "@nx/cypress": "16.6.0-beta.4", + "@nx/devkit": "16.6.0-beta.4", + "@nx/eslint-plugin": "16.6.0-beta.4", + "@nx/jest": "16.6.0-beta.4", + "@nx/js": "16.6.0-beta.4", + "@nx/linter": "16.6.0-beta.4", + "@nx/next": "16.6.0-beta.4", + "@nx/react": "16.6.0-beta.4", + "@nx/storybook": "16.6.0-beta.4", + "@nx/web": "16.6.0-beta.4", + "@nx/webpack": "16.6.0-beta.4", "@parcel/watcher": "2.0.4", "@phenomnomnominal/tsquery": "~5.0.1", "@playwright/test": "^1.36.1", @@ -214,7 +214,7 @@ "next-sitemap": "^3.1.10", "ng-packagr": "~16.1.0", "node-fetch": "^2.6.7", - "nx": "16.6.0-beta.5", + "nx": "16.6.0-beta.4", "nx-cloud": "16.2.0-beta.0", "octokit": "^2.0.14", "open": "^8.4.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 034f772005318..1f3ce0f1bbd9a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,9 +1,5 @@ lockfileVersion: '6.0' -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - overrides: minimist: ^1.2.6 underscore: ^1.12.1 @@ -228,7 +224,7 @@ devDependencies: version: 29.5.0 '@monodon/rust': specifier: 1.1.2 - version: 1.1.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.6.0-beta.5)(prettier@2.7.1)(typescript@5.1.3) + version: 1.1.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.6.0-beta.4)(prettier@2.7.1)(typescript@5.1.3) '@napi-rs/cli': specifier: 2.14.0 version: 2.14.0 @@ -266,38 +262,38 @@ devDependencies: specifier: ~16.1.0 version: 16.1.0(@angular-devkit/build-angular@16.1.0)(@angular/common@16.1.0)(@angular/core@16.1.0)(@types/express@4.17.14)(chokidar@3.5.3)(typescript@5.1.3) '@nx/cypress': - specifier: 16.6.0-beta.5 - version: 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) + specifier: 16.6.0-beta.4 + version: 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) '@nx/devkit': - specifier: 16.6.0-beta.5 - version: 16.6.0-beta.5(nx@16.6.0-beta.5) + specifier: 16.6.0-beta.4 + version: 16.6.0-beta.4(nx@16.6.0-beta.4) '@nx/eslint-plugin': - specifier: 16.6.0-beta.5 - version: 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(@typescript-eslint/parser@5.60.1)(eslint-config-prettier@8.5.0)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) + specifier: 16.6.0-beta.4 + version: 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(@typescript-eslint/parser@5.60.1)(eslint-config-prettier@8.5.0)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) '@nx/jest': - specifier: 16.6.0-beta.5 - version: 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4) + specifier: 16.6.0-beta.4 + version: 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4) '@nx/js': - specifier: 16.6.0-beta.5 - version: 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) + specifier: 16.6.0-beta.4 + version: 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) '@nx/linter': - specifier: 16.6.0-beta.5 - version: 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) + specifier: 16.6.0-beta.4 + version: 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) '@nx/next': - specifier: 16.6.0-beta.5 - version: 16.6.0-beta.5(@babel/core@7.22.9)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(file-loader@6.2.0)(next@13.3.4)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) + specifier: 16.6.0-beta.4 + version: 16.6.0-beta.4(@babel/core@7.22.9)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/express@4.17.14)(@types/node@18.16.9)(eslint@8.15.0)(file-loader@6.2.0)(next@13.3.4)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) '@nx/react': - specifier: 16.6.0-beta.5 - version: 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) + specifier: 16.6.0-beta.4 + version: 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) '@nx/storybook': - specifier: 16.6.0-beta.5 - version: 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) + specifier: 16.6.0-beta.4 + version: 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) '@nx/web': - specifier: 16.6.0-beta.5 - version: 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) + specifier: 16.6.0-beta.4 + version: 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) '@nx/webpack': - specifier: 16.6.0-beta.5 - version: 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(esbuild@0.17.5)(html-webpack-plugin@5.5.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) + specifier: 16.6.0-beta.4 + version: 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(esbuild@0.17.5)(html-webpack-plugin@5.5.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) '@parcel/watcher': specifier: 2.0.4 version: 2.0.4 @@ -719,8 +715,8 @@ devDependencies: specifier: ^2.6.7 version: 2.6.7 nx: - specifier: 16.6.0-beta.5 - version: 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51) + specifier: 16.6.0-beta.4 + version: 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51) nx-cloud: specifier: 16.2.0-beta.0 version: 16.2.0-beta.0 @@ -1718,6 +1714,24 @@ packages: lru-cache: 5.1.1 semver: 6.3.1 + /@babel/helper-create-class-features-plugin@7.22.5(@babel/core@7.22.9): + resolution: {integrity: sha512-xkb58MyOYIslxu3gKmVXmjTtUPvBU4odYzbiIQbWwLKIHCsx6UGZGX6F1IznMFVnDdirseUZopzN+ZRt8Xb33Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-annotate-as-pure': 7.22.5 + '@babel/helper-environment-visitor': 7.22.5 + '@babel/helper-function-name': 7.22.5 + '@babel/helper-member-expression-to-functions': 7.22.5 + '@babel/helper-optimise-call-expression': 7.22.5 + '@babel/helper-replace-supers': 7.22.9(@babel/core@7.22.9) + '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 + semver: 6.3.1 + dev: true + /@babel/helper-create-class-features-plugin@7.22.9(@babel/core@7.22.5): resolution: {integrity: sha512-Pwyi89uO4YrGKxL/eNJ8lfEH55DnRloGPOseaA8NFNL6jAUnn+KccaISiFazCj5IolPPDjGSdzQzXVzODVRqUQ==} engines: {node: '>=6.9.0'} @@ -1944,6 +1958,20 @@ packages: - supports-color dev: true + /@babel/helper-replace-supers@7.22.5: + resolution: {integrity: sha512-aLdNM5I3kdI/V9xGNyKSF3X/gTyMUBohTZ+/3QdQKAA9vxIiy12E+8E2HoOP1/DjeqU+g6as35QHJNMDDYpuCg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-environment-visitor': 7.22.5 + '@babel/helper-member-expression-to-functions': 7.22.5 + '@babel/helper-optimise-call-expression': 7.22.5 + '@babel/template': 7.22.5 + '@babel/traverse': 7.22.8 + '@babel/types': 7.22.5 + transitivePeerDependencies: + - supports-color + dev: true + /@babel/helper-replace-supers@7.22.9(@babel/core@7.22.5): resolution: {integrity: sha512-LJIKvvpgPOPUThdYqcX6IXRuIcTkcAub0IaDRGCZH0p5GPUp7PhRU9QVgFcDDd51BaPkk77ZjqFwh6DZTAEmGg==} engines: {node: '>=6.9.0'} @@ -2080,7 +2108,7 @@ packages: '@babel/core': 7.22.5 '@babel/helper-plugin-utils': 7.22.5 '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - '@babel/plugin-transform-optional-chaining': 7.22.6(@babel/core@7.22.5) + '@babel/plugin-transform-optional-chaining': 7.22.5(@babel/core@7.22.5) dev: true /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.22.5(@babel/core@7.22.9): @@ -2092,7 +2120,7 @@ packages: '@babel/core': 7.22.9 '@babel/helper-plugin-utils': 7.22.5 '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - '@babel/plugin-transform-optional-chaining': 7.22.6(@babel/core@7.22.9) + '@babel/plugin-transform-optional-chaining': 7.22.5(@babel/core@7.22.9) dev: true /@babel/plugin-proposal-async-generator-functions@7.20.7(@babel/core@7.22.5): @@ -2132,7 +2160,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.22.9 - '@babel/helper-create-class-features-plugin': 7.22.9(@babel/core@7.22.9) + '@babel/helper-create-class-features-plugin': 7.22.5(@babel/core@7.22.9) '@babel/helper-plugin-utils': 7.22.5 dev: true @@ -2155,25 +2183,13 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.22.9 - '@babel/helper-create-class-features-plugin': 7.22.9(@babel/core@7.22.9) + '@babel/helper-create-class-features-plugin': 7.22.5(@babel/core@7.22.9) '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-replace-supers': 7.22.9(@babel/core@7.22.9) - '@babel/helper-split-export-declaration': 7.22.6 + '@babel/helper-replace-supers': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.5 '@babel/plugin-syntax-decorators': 7.21.0(@babel/core@7.22.9) - dev: true - - /@babel/plugin-proposal-decorators@7.22.7(@babel/core@7.22.9): - resolution: {integrity: sha512-omXqPF7Onq4Bb7wHxXjM3jSMSJvUUbvDvmmds7KI5n9Cq6Ln5I05I1W2nRlRof1rGdiUxJrxwe285WF96XlBXQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-create-class-features-plugin': 7.22.9(@babel/core@7.22.9) - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-replace-supers': 7.22.9(@babel/core@7.22.9) - '@babel/helper-split-export-declaration': 7.22.6 - '@babel/plugin-syntax-decorators': 7.22.5(@babel/core@7.22.9) + transitivePeerDependencies: + - supports-color dev: true /@babel/plugin-proposal-dynamic-import@7.18.6(@babel/core@7.22.9): @@ -2429,16 +2445,6 @@ packages: '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-syntax-decorators@7.22.5(@babel/core@7.22.9): - resolution: {integrity: sha512-avpUOBS7IU6al8MmF1XpAyj9QYeLPuSDJI5D4pVMSMdL7xQokKqJPYQC67RCT0aCTashUXPiGwMJ0DEXXCEmMA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.22.5 - dev: true - /@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.22.5): resolution: {integrity: sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==} peerDependencies: @@ -2729,6 +2735,16 @@ packages: '@babel/helper-plugin-utils': 7.22.5 dev: true + /@babel/plugin-syntax-typescript@7.20.0(@babel/core@7.22.9): + resolution: {integrity: sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + /@babel/plugin-syntax-typescript@7.22.5(@babel/core@7.22.9): resolution: {integrity: sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==} engines: {node: '>=6.9.0'} @@ -2811,21 +2827,6 @@ packages: - supports-color dev: true - /@babel/plugin-transform-async-generator-functions@7.22.7(@babel/core@7.22.9): - resolution: {integrity: sha512-7HmE7pk/Fmke45TODvxvkxRMV9RazV+ZZzhOL9AG8G29TLrr3jkjwF7uJfxZ30EoXpO+LJkq4oA8NjO2DTnEDg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-environment-visitor': 7.22.5 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-remap-async-to-generator': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.22.9) - transitivePeerDependencies: - - supports-color - dev: true - /@babel/plugin-transform-async-to-generator@7.22.5(@babel/core@7.22.5): resolution: {integrity: sha512-b1A8D8ZzE/VhNDoV1MSJTnpKkCG5bJo+19R4o4oy03zM7ws8yEMK755j61Dc3EyvdysbqH5BOOTquJ7ZX9C6vQ==} engines: {node: '>=6.9.0'} @@ -2976,24 +2977,6 @@ packages: globals: 11.12.0 dev: true - /@babel/plugin-transform-classes@7.22.6(@babel/core@7.22.9): - resolution: {integrity: sha512-58EgM6nuPNG6Py4Z3zSuu0xWu2VfodiMi72Jt5Kj2FECmaYk1RrTXA45z6KBFsu9tRgwQDwIiY4FXTt+YsSFAQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-compilation-targets': 7.22.9(@babel/core@7.22.9) - '@babel/helper-environment-visitor': 7.22.5 - '@babel/helper-function-name': 7.22.5 - '@babel/helper-optimise-call-expression': 7.22.5 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-replace-supers': 7.22.9(@babel/core@7.22.9) - '@babel/helper-split-export-declaration': 7.22.6 - globals: 11.12.0 - dev: true - /@babel/plugin-transform-computed-properties@7.22.5(@babel/core@7.22.5): resolution: {integrity: sha512-4GHWBgRf0krxPX+AaPtgBAlTgTeZmqDynokHOX7aqqAB4tHs3U2Y02zH6ETFdLZGcg9UQSD1WCmkVrE9ErHeOg==} engines: {node: '>=6.9.0'} @@ -3559,30 +3542,6 @@ packages: '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.22.9) dev: true - /@babel/plugin-transform-optional-chaining@7.22.6(@babel/core@7.22.5): - resolution: {integrity: sha512-Vd5HiWml0mDVtcLHIoEU5sw6HOUW/Zk0acLs/SAeuLzkGNOPc9DB4nkUajemhCmTIz3eiaKREZn2hQQqF79YTg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.5 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.22.5) - dev: true - - /@babel/plugin-transform-optional-chaining@7.22.6(@babel/core@7.22.9): - resolution: {integrity: sha512-Vd5HiWml0mDVtcLHIoEU5sw6HOUW/Zk0acLs/SAeuLzkGNOPc9DB4nkUajemhCmTIz3eiaKREZn2hQQqF79YTg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.22.9) - dev: true - /@babel/plugin-transform-parameters@7.22.5(@babel/core@7.22.5): resolution: {integrity: sha512-AVkFUBurORBREOmHRKo06FjHYgjrabpdqRSwq6+C7R5iTCZOsM4QbcB27St0a4U6fffyAOqh3s/qEfybAhfivg==} engines: {node: '>=6.9.0'} @@ -4291,97 +4250,6 @@ packages: - supports-color dev: true - /@babel/preset-env@7.22.9(@babel/core@7.22.9): - resolution: {integrity: sha512-wNi5H/Emkhll/bqPjsjQorSykrlfY5OWakd6AulLvMEytpKasMVUpVy8RL4qBIBs5Ac6/5i0/Rv0b/Fg6Eag/g==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/compat-data': 7.22.9 - '@babel/core': 7.22.9 - '@babel/helper-compilation-targets': 7.22.9(@babel/core@7.22.9) - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-validator-option': 7.22.5 - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.22.9) - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.22.9) - '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.22.9) - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.22.9) - '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.22.9) - '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.22.9) - '@babel/plugin-syntax-import-assertions': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-syntax-import-attributes': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.22.9) - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.22.9) - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.22.9) - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.22.9) - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.22.9) - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.22.9) - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.22.9) - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.22.9) - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.22.9) - '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.22.9) - '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.22.9) - '@babel/plugin-transform-arrow-functions': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-async-generator-functions': 7.22.7(@babel/core@7.22.9) - '@babel/plugin-transform-async-to-generator': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-block-scoped-functions': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-block-scoping': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-class-properties': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-class-static-block': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-classes': 7.22.6(@babel/core@7.22.9) - '@babel/plugin-transform-computed-properties': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-destructuring': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-dotall-regex': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-duplicate-keys': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-dynamic-import': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-exponentiation-operator': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-export-namespace-from': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-for-of': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-function-name': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-json-strings': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-literals': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-logical-assignment-operators': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-member-expression-literals': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-modules-amd': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-modules-commonjs': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-modules-systemjs': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-modules-umd': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-named-capturing-groups-regex': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-new-target': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-nullish-coalescing-operator': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-numeric-separator': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-object-rest-spread': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-object-super': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-optional-catch-binding': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-optional-chaining': 7.22.6(@babel/core@7.22.9) - '@babel/plugin-transform-parameters': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-private-methods': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-private-property-in-object': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-property-literals': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-regenerator': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-reserved-words': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-shorthand-properties': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-spread': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-sticky-regex': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-template-literals': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-typeof-symbol': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-unicode-escapes': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-unicode-property-regex': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-unicode-regex': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-unicode-sets-regex': 7.22.5(@babel/core@7.22.9) - '@babel/preset-modules': 0.1.5(@babel/core@7.22.9) - '@babel/types': 7.22.5 - babel-plugin-polyfill-corejs2: 0.4.4(@babel/core@7.22.9) - babel-plugin-polyfill-corejs3: 0.8.2(@babel/core@7.22.9) - babel-plugin-polyfill-regenerator: 0.5.1(@babel/core@7.22.9) - core-js-compat: 3.31.1 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - dev: true - /@babel/preset-flow@7.21.4(@babel/core@7.22.9): resolution: {integrity: sha512-F24cSq4DIBmhq4OzK3dE63NHagb27OPE3eWR+HLekt4Z3Y5MzIIUGF3LlLgV0gN8vzbDViSY7HnrReNVCJXTeA==} engines: {node: '>=6.9.0'} @@ -4756,7 +4624,6 @@ packages: /@emotion/memoize@0.7.4: resolution: {integrity: sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==} - requiresBuild: true dev: false optional: true @@ -5733,7 +5600,6 @@ packages: dependencies: '@jridgewell/gen-mapping': 0.3.3 '@jridgewell/trace-mapping': 0.3.18 - dev: true /@jridgewell/sourcemap-codec@1.4.14: resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==} @@ -5939,12 +5805,12 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false - /@monodon/rust@1.1.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.6.0-beta.5)(prettier@2.7.1)(typescript@5.1.3): + /@monodon/rust@1.1.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.6.0-beta.4)(prettier@2.7.1)(typescript@5.1.3): resolution: {integrity: sha512-lb667coCcsWmkHuSKfGHgEeaWK24VGrW3AgA7Wq2M8wVVhuVQeKAV2UDt5vgvQj+xPlXPyKs6iPqNFXi3c2nLA==} dependencies: '@ltd/j-toml': 1.38.0 - '@nrwl/devkit': 15.8.0(nx@16.6.0-beta.5)(typescript@5.1.3) - '@nrwl/js': 15.8.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.6.0-beta.5)(prettier@2.7.1)(typescript@5.1.3) + '@nrwl/devkit': 15.8.0(nx@16.6.0-beta.4)(typescript@5.1.3) + '@nrwl/js': 15.8.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.6.0-beta.4)(prettier@2.7.1)(typescript@5.1.3) chalk: 4.1.2 transitivePeerDependencies: - '@babel/traverse' @@ -6675,10 +6541,10 @@ packages: - debug dev: true - /@nrwl/cypress@16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-AoiEj7FLhyQbaIpbtKieJf2Nd0TVSB0t+5uOK5zz++XxCXt14KeHgni2A4+iYrGyE+4+6WIPwPdS8WorhpoPpg==} + /@nrwl/cypress@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-6AN9HxAKGLMARBVy7lJkMkDAAPfNxiv1iJDsKAOlGRfc3DfjmgrYBTH5dmzmNL8MvgKG+itSSNhBjAkiB2S9sQ==} dependencies: - '@nx/cypress': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/cypress': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -6726,7 +6592,7 @@ packages: - typescript dev: true - /@nrwl/devkit@15.8.0(nx@16.6.0-beta.5)(typescript@5.1.3): + /@nrwl/devkit@15.8.0(nx@16.6.0-beta.4)(typescript@5.1.3): resolution: {integrity: sha512-qD+asvhTXIibXPXr3r1IDP7ap3Bw5H7tSd+C5mXFhIMMinTqRnQVXe6Odfs34VFP/dpWBIBZdkkwCM/+BsCLNw==} peerDependencies: nx: '>= 14.1 <= 16' @@ -6734,7 +6600,7 @@ packages: '@phenomnomnominal/tsquery': 4.1.1(typescript@5.1.3) ejs: 3.1.8 ignore: 5.2.0 - nx: 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51) + nx: 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51) semver: 7.3.4 tmp: 0.2.1 tslib: 2.5.3 @@ -6742,18 +6608,18 @@ packages: - typescript dev: true - /@nrwl/devkit@16.6.0-beta.5(nx@16.6.0-beta.5): - resolution: {integrity: sha512-f0Kq0dXbbTa032xmabnqA0OKzDGDTCLEqftk1cQSvAWW45jFNqbmP+nhzMV7/GGxdsd5/tVvWCE2L1vTUMPRdA==} + /@nrwl/devkit@16.6.0-beta.4(nx@16.6.0-beta.4): + resolution: {integrity: sha512-chfHRQk7DKt4/Z3UHtr6yPXXOEHqXma+Dsnu7B/P3NGrSTkdcq0G8ytO24jkCX28RQnO/95S/4EYrM9dyeoouQ==} dependencies: - '@nx/devkit': 16.6.0-beta.5(nx@16.6.0-beta.5) + '@nx/devkit': 16.6.0-beta.4(nx@16.6.0-beta.4) transitivePeerDependencies: - nx dev: true - /@nrwl/eslint-plugin-nx@16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(@typescript-eslint/parser@5.60.1)(eslint-config-prettier@8.5.0)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-v59w9RgH4wRmNWl7DYjOkUdO0p+VSr6CYEC6BKEbr8+n8QstlJyddZHabWGOaOwSqdybvYiBz5f9TLWdkDIarQ==} + /@nrwl/eslint-plugin-nx@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(@typescript-eslint/parser@5.60.1)(eslint-config-prettier@8.5.0)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-sGiNVikCBr3jc14YuJGUcFNISAjVnk0tleJRv8h98E8o02O0MpNwNdPiVmLF2nK4jCy9+X1tsrIko61+sOusFg==} dependencies: - '@nx/eslint-plugin': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(@typescript-eslint/parser@5.60.1)(eslint-config-prettier@8.5.0)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/eslint-plugin': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(@typescript-eslint/parser@5.60.1)(eslint-config-prettier@8.5.0)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -6770,10 +6636,10 @@ packages: - verdaccio dev: true - /@nrwl/jest@16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-nelWPin3nsHJNl/4k9TLUrgT6sUQkjISEboc6/AiY3Xs+4eSh3mdAfuor3R9gf6A8+C48vGmTMt/J0G0JaE5YQ==} + /@nrwl/jest@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-I2YMuBuD2+3HryDZy0JImw1ARHZdqjsza1iUeRbtfI8L10CfgiqQMedr9XmMSGcJiVA609iW6zQptRE3Y1y90Q==} dependencies: - '@nx/jest': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/jest': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4) transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -6789,7 +6655,7 @@ packages: - verdaccio dev: true - /@nrwl/js@15.8.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.6.0-beta.5)(prettier@2.7.1)(typescript@5.1.3): + /@nrwl/js@15.8.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.6.0-beta.4)(prettier@2.7.1)(typescript@5.1.3): resolution: {integrity: sha512-l2Q7oFpzx6ul7G0nKpMkrvnIEaOY+X8fc2g2Db5WqpnnBdfkrtWXZPg/O4DQ1p9O6BXrZ+Q2AK9bfgnliiwyEg==} dependencies: '@babel/core': 7.22.9 @@ -6799,7 +6665,7 @@ packages: '@babel/preset-env': 7.22.5(@babel/core@7.22.9) '@babel/preset-typescript': 7.22.5(@babel/core@7.22.9) '@babel/runtime': 7.22.6 - '@nrwl/devkit': 15.8.0(nx@16.6.0-beta.5)(typescript@5.1.3) + '@nrwl/devkit': 15.8.0(nx@16.6.0-beta.4)(typescript@5.1.3) '@nrwl/workspace': 15.8.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(prettier@2.7.1)(typescript@5.1.3) '@phenomnomnominal/tsquery': 4.1.1(typescript@5.1.3) babel-plugin-const-enum: 1.2.0(@babel/core@7.22.9) @@ -6826,46 +6692,10 @@ packages: - typescript dev: true - /@nrwl/js@15.8.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(nx@15.8.0)(prettier@2.7.1)(typescript@5.1.3): - resolution: {integrity: sha512-l2Q7oFpzx6ul7G0nKpMkrvnIEaOY+X8fc2g2Db5WqpnnBdfkrtWXZPg/O4DQ1p9O6BXrZ+Q2AK9bfgnliiwyEg==} - dependencies: - '@babel/core': 7.22.9 - '@babel/plugin-proposal-class-properties': 7.18.6(@babel/core@7.22.9) - '@babel/plugin-proposal-decorators': 7.21.0(@babel/core@7.22.9) - '@babel/plugin-transform-runtime': 7.22.9(@babel/core@7.22.9) - '@babel/preset-env': 7.22.5(@babel/core@7.22.9) - '@babel/preset-typescript': 7.22.5(@babel/core@7.22.9) - '@babel/runtime': 7.22.6 - '@nrwl/devkit': 15.8.0(nx@15.8.0)(typescript@5.1.3) - '@nrwl/workspace': 15.8.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(prettier@2.7.1)(typescript@5.1.3) - '@phenomnomnominal/tsquery': 4.1.1(typescript@5.1.3) - babel-plugin-const-enum: 1.2.0(@babel/core@7.22.9) - babel-plugin-macros: 2.8.0 - babel-plugin-transform-typescript-metadata: 0.3.2(@babel/core@7.22.9) - chalk: 4.1.2 - fast-glob: 3.2.7 - fs-extra: 11.1.1 - ignore: 5.2.0 - js-tokens: 4.0.0 - minimatch: 3.0.5 - source-map-support: 0.5.19 - tree-kill: 1.2.2 - tslib: 2.5.3 - transitivePeerDependencies: - - '@babel/traverse' - - '@swc-node/register' - - '@swc/core' - - debug - - nx - - prettier - - supports-color - - typescript - dev: true - - /@nrwl/js@16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-zXf/M5pUcxwRttWHeEZHgfCNMX/TaMkUakwC2EypA+5Fhpc7bllEjVRsOvABh6i6yCMeRqAlhwutvMNYwyYEMw==} + /@nrwl/js@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-jiwWyK0/6LWf/KDBp3cFhCxmN4kczXPN+lN2CpBS+ALtEDTVYQHofllAFEc0j9sXAMqu3cOvugxSS5VYheOk9A==} dependencies: - '@nx/js': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/js': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -6888,7 +6718,7 @@ packages: optional: true dependencies: '@nrwl/devkit': 15.8.0(nx@15.8.0)(typescript@5.1.3) - '@nrwl/js': 15.8.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(nx@15.8.0)(prettier@2.7.1)(typescript@5.1.3) + '@nrwl/js': 15.8.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.6.0-beta.4)(prettier@2.7.1)(typescript@5.1.3) '@phenomnomnominal/tsquery': 4.1.1(typescript@5.1.3) eslint: 8.15.0 tmp: 0.2.1 @@ -6904,10 +6734,10 @@ packages: - typescript dev: true - /@nrwl/linter@16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-w7rtPVLMwmW7DEiVb2F80axM9j/cgF2TPgueUFIFmXpJcX0VNqogf0rokEhajPvtQkZWs9N6t3kchRqIG9QZtw==} + /@nrwl/linter@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-CpeDd7G2oMgY53jDdE9XPdD6GwD4xMIWnNI1agZBxpXZ80DNTEOFf+3NSeTSUl+eQII6obCfAEmwtHK90pjZDQ==} dependencies: - '@nx/linter': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/linter': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -6922,16 +6752,17 @@ packages: - verdaccio dev: true - /@nrwl/next@16.6.0-beta.5(@babel/core@7.22.9)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(file-loader@6.2.0)(next@13.3.4)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0): - resolution: {integrity: sha512-qXTb4w8+5C5qm/CK982H1s6yk7okIhVs9c5Ip8EP33cUhst3pmHLp/d8LaRszL/eJK5ABYAX88YtuWYvwvXesQ==} + /@nrwl/next@16.6.0-beta.4(@babel/core@7.22.9)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/express@4.17.14)(@types/node@18.16.9)(eslint@8.15.0)(file-loader@6.2.0)(next@13.3.4)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0): + resolution: {integrity: sha512-A7hxhoSWOwA73HiUCD+Ns8BqoewcxIAPgune0C83vP6kdCTPSLe3udiACWSnebml5KEzzx026sovi3r5z4w1/w==} dependencies: - '@nx/next': 16.6.0-beta.5(@babel/core@7.22.9)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(file-loader@6.2.0)(next@13.3.4)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) + '@nx/next': 16.6.0-beta.4(@babel/core@7.22.9)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/express@4.17.14)(@types/node@18.16.9)(eslint@8.15.0)(file-loader@6.2.0)(next@13.3.4)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) transitivePeerDependencies: - '@babel/core' - '@babel/traverse' - '@swc-node/register' - '@swc/core' - '@swc/wasm' + - '@types/express' - '@types/node' - debug - eslint @@ -7114,10 +6945,10 @@ packages: dev: true optional: true - /@nrwl/react@16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0): - resolution: {integrity: sha512-6DFjCd0XTPrUjX+R8zKJ3FsP+hckAtrfhg+t3mw6ZnMDFCZXvUw+xtH4OvJHmdlvC+keIfB7w8IAVjypMoeVrQ==} + /@nrwl/react@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0): + resolution: {integrity: sha512-ZcWD0VcStqPXI/3tvfbUqJMAAQw95hl5SxWiGbiLgtMLcKn4Jg/PolMgCyQIMTKtfEo8Sqa/X0JwD8sOfokmWA==} dependencies: - '@nx/react': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) + '@nx/react': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -7133,10 +6964,10 @@ packages: - webpack dev: true - /@nrwl/storybook@16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-LSQFq0uxEqghtKG8Q+n1j7MMB3kU2XVy2WFRJuqiiKeFftpaRvekXm8hlJcVbKGI5SnLatuIuvvYacl90tf27w==} + /@nrwl/storybook@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-Wd6xTN1udNIXNLARMs/l3DtODmyxf5K+wRzlyCfPkFtcvC039kSWiJ1v/sJxShbZd48+mZskaiUmMuJHjJPyEA==} dependencies: - '@nx/storybook': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/storybook': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -7174,22 +7005,21 @@ packages: - debug dev: true - /@nrwl/tao@16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51): - resolution: {integrity: sha512-za4HgI0d6UxBwSawcCLZIlAf4rYnNOTSgBo5ysk0+4KGMTG2dVdZzxXbpCVrKgtbBC9kX3P3S/Lll5fgraHwww==} + /@nrwl/tao@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51): + resolution: {integrity: sha512-wOKV3mBZEQUYKPn6lHSJeDAJm8UPc3carEwgO8etcrZNBCTq+OepYFJoOUukxavIIgf10KqfDT1lAwaeiip0pA==} hasBin: true dependencies: - nx: 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51) - tslib: 2.5.3 + nx: 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51) transitivePeerDependencies: - '@swc-node/register' - '@swc/core' - debug dev: true - /@nrwl/web@16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-lot+YMykAD+3Ntsd5o20Bk9jhtUqQw8+VQ0uxY6SbcMCNnsGxruShdvq5xIJj3gYVt2US+d/PQFUGjjccyHMHQ==} + /@nrwl/web@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-Amtecs/uuy6eRSNl0FGWa3kfe3a9lYqZ17kmX4CGVcZ8aTYmhVkpGlcjeZvm8desnXBX/ESOXFHJpj/oxPvymw==} dependencies: - '@nx/web': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/web': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -7203,10 +7033,10 @@ packages: - verdaccio dev: true - /@nrwl/webpack@16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(esbuild@0.17.5)(html-webpack-plugin@5.5.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-wUSGyk2frLhNx4mFgUe1LxFO40Z7vE5DEFia5vDUB/RsFyT5+2J2B7OkytR0uqI9d7i7waq1UPhtlP44glON5Q==} + /@nrwl/webpack@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(esbuild@0.17.5)(html-webpack-plugin@5.5.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-kmGfkZxLxovPWOZrEhxc9QpOtpnbqCk2QVWF9liMkQdP7+3i4qOJ+ndw9QBBAQ7u8pG/i1DPAMFyB4Yt7n6b+g==} dependencies: - '@nx/webpack': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(esbuild@0.17.5)(html-webpack-plugin@5.5.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/webpack': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(esbuild@0.17.5)(html-webpack-plugin@5.5.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) transitivePeerDependencies: - '@babel/traverse' - '@parcel/css' @@ -7276,10 +7106,10 @@ packages: - typescript dev: true - /@nrwl/workspace@16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51): - resolution: {integrity: sha512-8ZTbqN19mEBh3qQ8T97gsLfUDOUp9vHfzZSEmd+O5YDjx7zSm3Rjjp0q849S4arOamadDiLl6A4A1Yw7WIsVmg==} + /@nrwl/workspace@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51): + resolution: {integrity: sha512-q9uADz1YJGB/ZtSKsrKzKnN91nbcin4DPFKrxaNAG+XgEM4hhzdjC7W2+BNzsRkywEFE/pqGWtbpGqeGfSpgGg==} dependencies: - '@nx/workspace': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51) + '@nx/workspace': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51) transitivePeerDependencies: - '@swc-node/register' - '@swc/core' @@ -7298,24 +7128,23 @@ packages: - encoding dev: true - /@nx/cypress@16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-DaiulZu+zql7s2VA8ERjaySNKWRMUjdHZWJTRk/QHjqapx2ScwiX0DBylTv5Yx0bZqcTek4ohV4z0KOeU+Eqpw==} + /@nx/cypress@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-Co6g6CytxxY+ts9ns0Xah+oAO9CZ6oo8DJ6y8JoKHsZY9Oa28IZ/IOEwYMUGzo/maXAz8tVpzZYclN/sTFAs/A==} peerDependencies: cypress: '>= 3 < 13' peerDependenciesMeta: cypress: optional: true dependencies: - '@nrwl/cypress': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/devkit': 16.6.0-beta.5(nx@16.6.0-beta.5) - '@nx/js': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/linter': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) + '@nrwl/cypress': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/devkit': 16.6.0-beta.4(nx@16.6.0-beta.4) + '@nx/js': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/linter': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) '@phenomnomnominal/tsquery': 5.0.1(typescript@5.1.3) cypress: 12.16.0 detect-port: 1.5.1 dotenv: 10.0.0 semver: 7.5.3 - tslib: 2.5.3 transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -7330,22 +7159,22 @@ packages: - verdaccio dev: true - /@nx/devkit@16.6.0-beta.5(nx@16.6.0-beta.5): - resolution: {integrity: sha512-RAmwDwQ6wzeLCO3IXvNnJQrb86DbEYXHpNrCWDmzx0QCt15VCp09YnqnuIaZ66gIoGBHXgwmhk8igs7RWCPYaw==} + /@nx/devkit@16.6.0-beta.4(nx@16.6.0-beta.4): + resolution: {integrity: sha512-0+b12edK/Q5+JN3hnmzsK8MLcwGeTDmnca23q5+eayXQf4kOmwM9zbYM10PrWpYgN1c7Ltx4k09RP4J9HpBYbg==} peerDependencies: nx: '>= 15 <= 17' dependencies: - '@nrwl/devkit': 16.6.0-beta.5(nx@16.6.0-beta.5) + '@nrwl/devkit': 16.6.0-beta.4(nx@16.6.0-beta.4) ejs: 3.1.8 ignore: 5.2.0 - nx: 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51) + nx: 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51) semver: 7.5.3 tmp: 0.2.1 tslib: 2.5.3 dev: true - /@nx/eslint-plugin@16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(@typescript-eslint/parser@5.60.1)(eslint-config-prettier@8.5.0)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-UIdQcm7usqbU2Ac9YIm3Rd3i4ikyaQ6k6/gQkeibMS/usMefXFqqNwXWsE0aPV+fKwJCDgZwJ57pdn4rXcPB4Q==} + /@nx/eslint-plugin@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(@typescript-eslint/parser@5.60.1)(eslint-config-prettier@8.5.0)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-deIVitlkRs3wA9OKLanPokfnL+lGwh3LrVEwvvOsUkoyGhd77/PtjbCMDcN96oE7vYCNdSXPJ8Gli1Z0qDI7Mg==} peerDependencies: '@typescript-eslint/parser': ^5.60.1 eslint-config-prettier: ^8.1.0 @@ -7353,9 +7182,9 @@ packages: eslint-config-prettier: optional: true dependencies: - '@nrwl/eslint-plugin-nx': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(@typescript-eslint/parser@5.60.1)(eslint-config-prettier@8.5.0)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/devkit': 16.6.0-beta.5(nx@16.6.0-beta.5) - '@nx/js': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) + '@nrwl/eslint-plugin-nx': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(@typescript-eslint/parser@5.60.1)(eslint-config-prettier@8.5.0)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/devkit': 16.6.0-beta.4(nx@16.6.0-beta.4) + '@nx/js': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) '@typescript-eslint/parser': 5.60.1(eslint@8.15.0)(typescript@5.1.3) '@typescript-eslint/type-utils': 5.60.1(eslint@8.15.0)(typescript@5.1.3) '@typescript-eslint/utils': 5.60.1(eslint@8.15.0)(typescript@5.1.3) @@ -7364,7 +7193,6 @@ packages: eslint-config-prettier: 8.5.0(eslint@8.15.0) jsonc-eslint-parser: 2.1.0 semver: 7.5.3 - tslib: 2.5.3 transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -7379,14 +7207,14 @@ packages: - verdaccio dev: true - /@nx/jest@16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-PDCj18LiT4EsSqk9iuSPWTFG3kpd/+eEx8+5NamLyiDkWSKKQl5IGoa7glf59Nb2Yv8dKs1/3C+qMfrp0mqvFg==} + /@nx/jest@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-Yb3CcWNlN89n+t15SuP20jIliHro5hPtlc5hktAEjXhj08o0YkjRequ8jUFjlAswdLPwrQlMUHZCQiqw5vySUg==} dependencies: '@jest/reporters': 29.5.0 '@jest/test-result': 29.5.0 - '@nrwl/jest': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/devkit': 16.6.0-beta.5(nx@16.6.0-beta.5) - '@nx/js': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) + '@nrwl/jest': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/devkit': 16.6.0-beta.4(nx@16.6.0-beta.4) + '@nx/js': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) '@phenomnomnominal/tsquery': 5.0.1(typescript@5.1.3) chalk: 4.1.2 dotenv: 10.0.0 @@ -7411,8 +7239,8 @@ packages: - verdaccio dev: true - /@nx/js@16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-Gd8CC/RHVCSru5j9zt1uOHHpjfl7Cv/X4eLkWOXFrKssn5HR+Z1X/uIJEw5OyyVzIREnczHi5J9i2s3A3kZsHA==} + /@nx/js@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-Up4CPVzKIM6LGyhml5EkrXzVtx/fM9x67DbYEsFENAD0exlblrHdHf0XAsXP0Wc8ClhQnCH4F5O8b4T2/3HtRg==} peerDependencies: verdaccio: ^5.0.4 peerDependenciesMeta: @@ -7421,14 +7249,14 @@ packages: dependencies: '@babel/core': 7.22.9 '@babel/plugin-proposal-class-properties': 7.18.6(@babel/core@7.22.9) - '@babel/plugin-proposal-decorators': 7.22.7(@babel/core@7.22.9) + '@babel/plugin-proposal-decorators': 7.21.0(@babel/core@7.22.9) '@babel/plugin-transform-runtime': 7.22.9(@babel/core@7.22.9) - '@babel/preset-env': 7.22.9(@babel/core@7.22.9) + '@babel/preset-env': 7.22.5(@babel/core@7.22.9) '@babel/preset-typescript': 7.22.5(@babel/core@7.22.9) '@babel/runtime': 7.22.6 - '@nrwl/js': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/devkit': 16.6.0-beta.5(nx@16.6.0-beta.5) - '@nx/workspace': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51) + '@nrwl/js': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/devkit': 16.6.0-beta.4(nx@16.6.0-beta.4) + '@nx/workspace': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51) '@phenomnomnominal/tsquery': 5.0.1(typescript@5.1.3) babel-plugin-const-enum: 1.2.0(@babel/core@7.22.9) babel-plugin-macros: 2.8.0 @@ -7458,17 +7286,17 @@ packages: - typescript dev: true - /@nx/linter@16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-6qNPxGGy/BkPBi2MxyrB+0rqdWTMiXMqu/p76PJGUzP1SFRmpZaUJuOCfi83nsX/rnWphgaBTJ2LsQX62UPAUQ==} + /@nx/linter@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-CVtAutv8TrJ7inet/cUeXs2z3uQ7uajPkccQiisDAJR30dx4s0xNuiqKPNNy0LelWX3Q2lhycZDbNcn1cwtMSQ==} peerDependencies: eslint: ^8.0.0 peerDependenciesMeta: eslint: optional: true dependencies: - '@nrwl/linter': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/devkit': 16.6.0-beta.5(nx@16.6.0-beta.5) - '@nx/js': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) + '@nrwl/linter': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/devkit': 16.6.0-beta.4(nx@16.6.0-beta.4) + '@nx/js': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) '@phenomnomnominal/tsquery': 5.0.1(typescript@5.1.3) eslint: 8.15.0 tmp: 0.2.1 @@ -7486,28 +7314,29 @@ packages: - verdaccio dev: true - /@nx/next@16.6.0-beta.5(@babel/core@7.22.9)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(file-loader@6.2.0)(next@13.3.4)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0): - resolution: {integrity: sha512-Bi5KLlsT7m9wHB3iw6rgu3bGTyMnmS7/DfXRDkqtefzB6uMHEER1E/u7PRILplQ24kkNLfO4wCrqP+yz1fTHxQ==} + /@nx/next@16.6.0-beta.4(@babel/core@7.22.9)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/express@4.17.14)(@types/node@18.16.9)(eslint@8.15.0)(file-loader@6.2.0)(next@13.3.4)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0): + resolution: {integrity: sha512-anknmoeDinyu+gV9j2fiYZUtgtXeXiNTzcaJp3aeSM9121huwHnQHMnBikNBnzG4h082vPppD0oE4cORz1HWUQ==} peerDependencies: next: '>=13.0.0' dependencies: - '@babel/plugin-proposal-decorators': 7.22.7(@babel/core@7.22.9) - '@nrwl/next': 16.6.0-beta.5(@babel/core@7.22.9)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(file-loader@6.2.0)(next@13.3.4)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) - '@nx/devkit': 16.6.0-beta.5(nx@16.6.0-beta.5) - '@nx/js': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/linter': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/react': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) - '@nx/web': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/workspace': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51) + '@babel/plugin-proposal-decorators': 7.21.0(@babel/core@7.22.9) + '@nrwl/next': 16.6.0-beta.4(@babel/core@7.22.9)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/express@4.17.14)(@types/node@18.16.9)(eslint@8.15.0)(file-loader@6.2.0)(next@13.3.4)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) + '@nx/devkit': 16.6.0-beta.4(nx@16.6.0-beta.4) + '@nx/js': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/linter': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/react': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) + '@nx/web': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/workspace': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51) '@svgr/webpack': 8.0.1 chalk: 4.1.2 copy-webpack-plugin: 10.2.4(webpack@5.88.0) dotenv: 10.0.0 + express: 4.18.2 fs-extra: 11.1.1 + http-proxy-middleware: 2.0.6(@types/express@4.17.14) ignore: 5.2.0 next: 13.3.4(@babel/core@7.22.9)(react-dom@18.2.0)(react@18.2.0)(sass@1.55.0) semver: 7.5.3 - tslib: 2.5.3 url-loader: 4.1.1(file-loader@6.2.0)(webpack@5.88.0) webpack-merge: 5.9.0 transitivePeerDependencies: @@ -7516,6 +7345,7 @@ packages: - '@swc-node/register' - '@swc/core' - '@swc/wasm' + - '@types/express' - '@types/node' - debug - eslint @@ -7527,8 +7357,8 @@ packages: - webpack dev: true - /@nx/nx-darwin-arm64@16.6.0-beta.5: - resolution: {integrity: sha512-e7M/qBpnFSeCIvkqx91XV81TsGutv0Gh1TlxvJlXbhCCVfSyWayQjjhL2Q653nICZmh4uGra+6IHXFqkCQr3Iw==} + /@nx/nx-darwin-arm64@16.6.0-beta.4: + resolution: {integrity: sha512-WosSKoGph13tVtiO9oJXz0m+eAvOFXhoox2GTtesa76LSLOp1kMYfiCkRnAaEZimYD+ncshhqS3EHoomnwh1+w==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] @@ -7536,8 +7366,8 @@ packages: dev: true optional: true - /@nx/nx-darwin-x64@16.6.0-beta.5: - resolution: {integrity: sha512-0v/SRVqZCfRAV+k/dBrFOzScCgaM+lJyhw4xm3zI8ZoAr0/u7/7IBzpB0Lr4R10zWAhuyCqO3Cu2Jbs2/MWcsA==} + /@nx/nx-darwin-x64@16.6.0-beta.4: + resolution: {integrity: sha512-wTR4akGjY8+CPNO/AYh9UeuTH9EyEPx4Kwp+Z63CEbDF8oe2BBVtMWz3XHHm7KKnPOWzOXADi7gE/FI5HTAMvA==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] @@ -7545,8 +7375,8 @@ packages: dev: true optional: true - /@nx/nx-freebsd-x64@16.6.0-beta.5: - resolution: {integrity: sha512-ga81tbBIn0vLaJxxab7i5Lv49haVIIb3/z6gQ8wzhKKynbTElE5JxwjvKLkPIV2e3iop57sXuTlM8u6AwLBXwg==} + /@nx/nx-freebsd-x64@16.6.0-beta.4: + resolution: {integrity: sha512-at3qt49FMBHG75p3Sbngy3b/H4fXAz80MhejcDS0CmyJJWZMgGIat9bXGkpQqZKVrAkk8EMhVcV972FlJZIYog==} engines: {node: '>= 10'} cpu: [x64] os: [freebsd] @@ -7554,8 +7384,8 @@ packages: dev: true optional: true - /@nx/nx-linux-arm-gnueabihf@16.6.0-beta.5: - resolution: {integrity: sha512-uj5jsV0JJd88BHxAcL693i/b7ndd4yytakiAu+3A/BHZsUMY35mrMGz8e7mkC3rrY0EBBSVVzRmmsAiBn7ChAA==} + /@nx/nx-linux-arm-gnueabihf@16.6.0-beta.4: + resolution: {integrity: sha512-tWUb3GlYnWdC7Z3RAdbs6A4tc26187eaWBI7Rt5rVmXOqa5pIm5J0QHEAD4IctcY38z9HPehgi3cYjihOprCQA==} engines: {node: '>= 10'} cpu: [arm] os: [linux] @@ -7563,8 +7393,8 @@ packages: dev: true optional: true - /@nx/nx-linux-arm64-gnu@16.6.0-beta.5: - resolution: {integrity: sha512-RGRlrdJgZ9w9r2iIWQtPhIlHKtnjyJnjmN4pnLlHpM0xluhR0nq3LQFUnI9QLkSqGIavWAj+GOhctFsdrSIKvg==} + /@nx/nx-linux-arm64-gnu@16.6.0-beta.4: + resolution: {integrity: sha512-kMBCWIeQd4wzs8COXaeD71+LkLG+lsq99JpTGmQHXa1QB9rm4NBTtcixtveAWssqF8i7WNSpxlD1zo6z04HO4g==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -7572,8 +7402,8 @@ packages: dev: true optional: true - /@nx/nx-linux-arm64-musl@16.6.0-beta.5: - resolution: {integrity: sha512-NO5l/6788TkzXZzhkIZPGdj/K99Cf0F7HRclOU91D46z91t26ByQIJTYrdky3pwT+f1hV9xVMgDkia1QzaR5Qg==} + /@nx/nx-linux-arm64-musl@16.6.0-beta.4: + resolution: {integrity: sha512-tiXZq2MHUMnyE5IBdZmaes3fNSPCkL9w+phQ7Fu33Rhvr9ZWcVudYmXhVxxPaznPT1r95Lg+mitegiKwzNKsFw==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -7581,8 +7411,8 @@ packages: dev: true optional: true - /@nx/nx-linux-x64-gnu@16.6.0-beta.5: - resolution: {integrity: sha512-Sk7U5r+h5j5UCDnkNtlpCZo5rYe/DKPL3R+gtZ44o76BIbxO9TxY0pSD1SSX5kAdqXx8CkpWAc7fgchzZTN3tA==} + /@nx/nx-linux-x64-gnu@16.6.0-beta.4: + resolution: {integrity: sha512-3Ku1Gpq7LC+FOQbKVesRDp5Sfdh6EPeOpKW2tZduqS3xht++/7HdP6dF8825mxykOg6DFRdO+c66r8k8kijxMQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -7590,8 +7420,8 @@ packages: dev: true optional: true - /@nx/nx-linux-x64-musl@16.6.0-beta.5: - resolution: {integrity: sha512-fweJs+hKV0xLJ8V3YDvR9M9TcTsfMsOz0I0pUEzsYQi0P6SAajIMNJS3v0auE//pXNq6gJWJJ8cLifGW57yUTw==} + /@nx/nx-linux-x64-musl@16.6.0-beta.4: + resolution: {integrity: sha512-hQZJVtxsVmENUvwLjSuJ25OhvwM2Oi+4Em9rjWtChUNwQdMPYRDBl3RsUEtGbStGRWu0AnDbXh+TDo/4tV1FgA==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -7599,8 +7429,8 @@ packages: dev: true optional: true - /@nx/nx-win32-arm64-msvc@16.6.0-beta.5: - resolution: {integrity: sha512-8pK7z0nfwR7yxoFdWoecuTd1NxJk3IJ1Ymef1lN6p2XG/uS/clCfHddO8g5nbilHRrNqQuEwOgksDsMsPhyNVg==} + /@nx/nx-win32-arm64-msvc@16.6.0-beta.4: + resolution: {integrity: sha512-C7ptavIq4KqxNectfgsQRvR98vpB/c7GA3Xrj+PCrg6o5qLrAQ8qycla05IcfAiSF409oERrJCVqmCHJJQax8A==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] @@ -7608,8 +7438,8 @@ packages: dev: true optional: true - /@nx/nx-win32-x64-msvc@16.6.0-beta.5: - resolution: {integrity: sha512-uQhRW5VqR8FeGffZhJoK1BJtTNF76xB877bzPxQZ3ZCPhkvZTfZnlsqOIHFbH2ROtt/SQkAUaeu5zjJ9Bz/mfQ==} + /@nx/nx-win32-x64-msvc@16.6.0-beta.4: + resolution: {integrity: sha512-KvZ0/nnlIJgQKjLmMmjU18MvF4Lj8SapC4LHzyPaYVk3SkGZ5o5sHZ29J1RY7BcQ3GV51Azgdh9W8alu2z/oMA==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -7617,20 +7447,19 @@ packages: dev: true optional: true - /@nx/react@16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0): - resolution: {integrity: sha512-17kgJPC25+fMmvVW7qd1DKLXlj+UldGxJJal+0DN+2Hpt5Voip4aJXSE1/UFp3h7AAeJqPovK9DvouYzTY39ig==} + /@nx/react@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0): + resolution: {integrity: sha512-HeR6Maai48MvJxrIxUDhdrIl3XrcSULgdRpWAdO2Chugq8vOOGha5NHQ943UuXyqSsLb8+/VNCldAPPmZ27U4w==} dependencies: - '@nrwl/react': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) - '@nx/devkit': 16.6.0-beta.5(nx@16.6.0-beta.5) - '@nx/js': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/linter': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/web': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) + '@nrwl/react': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) + '@nx/devkit': 16.6.0-beta.4(nx@16.6.0-beta.4) + '@nx/js': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/linter': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/web': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) '@phenomnomnominal/tsquery': 5.0.1(typescript@5.1.3) '@svgr/webpack': 8.0.1 chalk: 4.1.2 file-loader: 6.2.0(webpack@5.88.0) minimatch: 3.0.5 - tslib: 2.5.3 transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -7646,19 +7475,18 @@ packages: - webpack dev: true - /@nx/storybook@16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-G1oILSZl2Sk9zhynonqLZF0nCiE3+M35Nkr1+oEeSOOJL4FFZbpk9/Uj9cG9ai+gXLfeH/Ec+37FG1TMWl98aA==} + /@nx/storybook@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-FvW8OdmoitnB727YpqzP3gCTkK+3SF3GPXpGL4SOhlj842G6ey+9BQqRNHFbeaMxgzrRSTnyyDZznmLt//EsxQ==} dependencies: - '@nrwl/storybook': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/cypress': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/devkit': 16.6.0-beta.5(nx@16.6.0-beta.5) - '@nx/js': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/linter': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/workspace': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51) + '@nrwl/storybook': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/cypress': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/devkit': 16.6.0-beta.4(nx@16.6.0-beta.4) + '@nx/js': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/linter': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/workspace': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51) '@phenomnomnominal/tsquery': 5.0.1(typescript@5.1.3) dotenv: 10.0.0 semver: 7.5.3 - tslib: 2.5.3 transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -7674,12 +7502,12 @@ packages: - verdaccio dev: true - /@nx/web@16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-rReLXiZmVIBlz5BwSZJWt+fbpmDK3eY4nHqAyWTWF1hp5suRU5r8qq4d7hWgEhqJXoAHRficiFmpI4/pco4HSg==} + /@nx/web@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-xSUm82LZ8G3Y0iJO7AIiHk8iAIG+sP7OKhjhUHhsm8mtSfSY81+i5FXuld/t+aQ6+RIqgTVWaIN78x9BCVhq2w==} dependencies: - '@nrwl/web': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/devkit': 16.6.0-beta.5(nx@16.6.0-beta.5) - '@nx/js': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) + '@nrwl/web': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/devkit': 16.6.0-beta.4(nx@16.6.0-beta.4) + '@nx/js': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) chalk: 4.1.2 chokidar: 3.5.3 detect-port: 1.5.1 @@ -7699,16 +7527,16 @@ packages: - verdaccio dev: true - /@nx/webpack@16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(esbuild@0.17.5)(html-webpack-plugin@5.5.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-LJEgRLzhdpgvf1Zd8H8cqvZrqhgYccli0v9dddkCzbtCFHWAZk5zKjaWqhq912rSIji+s+cUidqX9ypV/HL8aw==} + /@nx/webpack@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(esbuild@0.17.5)(html-webpack-plugin@5.5.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-y3mI85ZsHgK3ebuzeOaVNTGNEqdFsD/8pBx7HhumiSO7xqKfgRsvVWdN6EPn2a3HwRj2JgjrdBBIWu+nItIp8A==} dependencies: '@babel/core': 7.22.9 - '@nrwl/webpack': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(esbuild@0.17.5)(html-webpack-plugin@5.5.0)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/devkit': 16.6.0-beta.5(nx@16.6.0-beta.5) - '@nx/js': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.5)(typescript@5.1.3)(verdaccio@5.15.4) + '@nrwl/webpack': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(esbuild@0.17.5)(html-webpack-plugin@5.5.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/devkit': 16.6.0-beta.4(nx@16.6.0-beta.4) + '@nx/js': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) autoprefixer: 10.4.13(postcss@8.4.19) babel-loader: 9.1.2(@babel/core@7.22.9)(webpack@5.88.0) - browserslist: 4.21.9 + browserslist: 4.21.7 chalk: 4.1.2 chokidar: 3.5.3 copy-webpack-plugin: 10.2.4(webpack@5.88.0) @@ -7769,16 +7597,28 @@ packages: - webpack-cli dev: true - /@nx/workspace@16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51): - resolution: {integrity: sha512-dbLITBHwjbustUk8BLk+NRnz6FxWV0pQGvPjG3X0Er52Rv7+mzdMTfj1g7IW9Bs4qajIe+xUpxjI6X6GgbOr6g==} + /@nx/workspace@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51): + resolution: {integrity: sha512-KVAEQjrWwMCbcZdiwoSG2PciELCsEZ1PLDX0wywNfJcRb1hK2bZDmswLuI5hxLSst9b7UXNH0PKG5S6QnIc0fw==} dependencies: - '@nrwl/workspace': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51) - '@nx/devkit': 16.6.0-beta.5(nx@16.6.0-beta.5) + '@nrwl/workspace': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51) + '@nx/devkit': 16.6.0-beta.4(nx@16.6.0-beta.4) + '@parcel/watcher': 2.0.4 chalk: 4.1.2 + chokidar: 3.5.3 + cli-cursor: 3.1.0 + cli-spinners: 2.6.1 + dotenv: 10.0.0 + figures: 3.2.0 + flat: 5.0.2 ignore: 5.2.0 - nx: 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51) + minimatch: 3.0.5 + npm-run-path: 4.0.1 + nx: 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51) + open: 8.4.2 rxjs: 7.8.1 + tmp: 0.2.1 tslib: 2.5.3 + yargs: 17.7.2 yargs-parser: 21.1.1 transitivePeerDependencies: - '@swc-node/register' @@ -10436,7 +10276,6 @@ packages: /@types/linkify-it@3.0.2: resolution: {integrity: sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==} - requiresBuild: true dev: false optional: true @@ -10462,7 +10301,6 @@ packages: /@types/mdurl@1.0.2: resolution: {integrity: sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==} - requiresBuild: true dev: false optional: true @@ -12145,7 +11983,7 @@ packages: dependencies: '@babel/core': 7.22.9 '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-typescript': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-syntax-typescript': 7.20.0(@babel/core@7.22.9) '@babel/traverse': 7.22.8 transitivePeerDependencies: - supports-color @@ -12775,7 +12613,6 @@ packages: /buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - dev: true /buffer-indexof-polyfill@1.0.2: resolution: {integrity: sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==} @@ -13383,7 +13220,6 @@ packages: /commander@2.20.3: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} - dev: true /commander@4.1.1: resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} @@ -21281,8 +21117,8 @@ packages: - debug dev: true - /nx@16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51): - resolution: {integrity: sha512-rz8yq62Prkp5uuMckxkmoJfwSk7RjNR/UXvDfZr3laZuXv4ORRG+y7LFFG5mpKX0AlD3dkrZvVds6qBT12QIJQ==} + /nx@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51): + resolution: {integrity: sha512-hbiYe4cxLBMTYO9sjLg6N3gh709Cf38tVXxbzv1y3ZXaRA2nyH6NSerk+VP7Om7IxQku8RTItscZqM8qsb4/mA==} hasBin: true requiresBuild: true peerDependencies: @@ -21294,7 +21130,7 @@ packages: '@swc/core': optional: true dependencies: - '@nrwl/tao': 16.6.0-beta.5(@swc-node/register@1.5.4)(@swc/core@1.3.51) + '@nrwl/tao': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51) '@parcel/watcher': 2.0.4 '@swc-node/register': 1.5.4(@swc/core@1.3.51)(typescript@5.1.3) '@swc/core': 1.3.51(@swc/helpers@0.5.0) @@ -21332,16 +21168,16 @@ packages: yargs: 17.7.2 yargs-parser: 21.1.1 optionalDependencies: - '@nx/nx-darwin-arm64': 16.6.0-beta.5 - '@nx/nx-darwin-x64': 16.6.0-beta.5 - '@nx/nx-freebsd-x64': 16.6.0-beta.5 - '@nx/nx-linux-arm-gnueabihf': 16.6.0-beta.5 - '@nx/nx-linux-arm64-gnu': 16.6.0-beta.5 - '@nx/nx-linux-arm64-musl': 16.6.0-beta.5 - '@nx/nx-linux-x64-gnu': 16.6.0-beta.5 - '@nx/nx-linux-x64-musl': 16.6.0-beta.5 - '@nx/nx-win32-arm64-msvc': 16.6.0-beta.5 - '@nx/nx-win32-x64-msvc': 16.6.0-beta.5 + '@nx/nx-darwin-arm64': 16.6.0-beta.4 + '@nx/nx-darwin-x64': 16.6.0-beta.4 + '@nx/nx-freebsd-x64': 16.6.0-beta.4 + '@nx/nx-linux-arm-gnueabihf': 16.6.0-beta.4 + '@nx/nx-linux-arm64-gnu': 16.6.0-beta.4 + '@nx/nx-linux-arm64-musl': 16.6.0-beta.4 + '@nx/nx-linux-x64-gnu': 16.6.0-beta.4 + '@nx/nx-linux-x64-musl': 16.6.0-beta.4 + '@nx/nx-win32-arm64-msvc': 16.6.0-beta.4 + '@nx/nx-win32-x64-msvc': 16.6.0-beta.4 transitivePeerDependencies: - debug dev: true @@ -23479,7 +23315,6 @@ packages: /prr@1.0.1: resolution: {integrity: sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==} - requiresBuild: true optional: true /pseudomap@1.0.2: @@ -24530,7 +24365,6 @@ packages: chokidar: 3.5.3 immutable: 4.1.0 source-map-js: 1.0.2 - dev: true /sax@1.2.4: resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==} @@ -25125,7 +24959,6 @@ packages: dependencies: buffer-from: 1.1.2 source-map: 0.6.1 - dev: true /source-map@0.5.7: resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} @@ -26015,7 +25848,6 @@ packages: acorn: 8.8.2 commander: 2.20.3 source-map-support: 0.5.21 - dev: true /terser@5.18.0: resolution: {integrity: sha512-pdL757Ig5a0I+owA42l6tIuEycRuM7FPY4n62h44mRLRfnOxJkkOHd6i89dOpwZlpF6JXBwaAHF6yWzFrt+QyA==} @@ -27141,7 +26973,7 @@ packages: mlly: 1.2.0 pathe: 1.1.0 picocolors: 1.0.0 - vite: 4.3.9(@types/node@18.16.9)(less@4.1.3)(sass@1.55.0)(stylus@0.59.0) + vite: 4.3.9(@types/node@18.16.9)(less@4.1.3)(sass@1.63.2)(stylus@0.59.0)(terser@5.17.7) transitivePeerDependencies: - '@types/node' - less @@ -27187,42 +27019,6 @@ packages: optionalDependencies: fsevents: 2.3.2 - /vite@4.3.9(@types/node@18.16.9)(less@4.1.3)(sass@1.55.0)(stylus@0.59.0): - resolution: {integrity: sha512-qsTNZjO9NoJNW7KnOrgYwczm0WctJ8m/yqYAMAK9Lxt4SoySUfS5S8ia9K7JHpa3KEeMfyF8LoJ3c5NeBJy6pg==} - engines: {node: ^14.18.0 || >=16.0.0} - hasBin: true - peerDependencies: - '@types/node': '>= 14' - less: '*' - sass: '*' - stylus: '*' - sugarss: '*' - terser: ^5.4.0 - peerDependenciesMeta: - '@types/node': - optional: true - less: - optional: true - sass: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - dependencies: - '@types/node': 18.16.9 - esbuild: 0.17.19 - less: 4.1.3 - postcss: 8.4.24 - rollup: 3.21.0 - sass: 1.55.0 - stylus: 0.59.0 - optionalDependencies: - fsevents: 2.3.2 - dev: false - /vite@4.3.9(@types/node@18.16.9)(less@4.1.3)(sass@1.63.2)(stylus@0.59.0)(terser@5.17.7): resolution: {integrity: sha512-qsTNZjO9NoJNW7KnOrgYwczm0WctJ8m/yqYAMAK9Lxt4SoySUfS5S8ia9K7JHpa3KEeMfyF8LoJ3c5NeBJy6pg==} engines: {node: ^14.18.0 || >=16.0.0} @@ -27258,7 +27054,6 @@ packages: terser: 5.17.7 optionalDependencies: fsevents: 2.3.2 - dev: true /vitest@0.32.0(less@4.1.3)(sass@1.55.0)(stylus@0.59.0): resolution: {integrity: sha512-SW83o629gCqnV3BqBnTxhB10DAwzwEx3z+rqYZESehUB+eWsJxwcBQx7CKy0otuGMJTYh7qCVuUX23HkftGl/Q==} @@ -27706,7 +27501,7 @@ packages: '@webassemblyjs/wasm-parser': 1.11.1 acorn: 8.8.2 acorn-import-assertions: 1.9.0(acorn@8.8.2) - browserslist: 4.21.9 + browserslist: 4.21.7 chrome-trace-event: 1.0.3 enhanced-resolve: 5.15.0 es-module-lexer: 0.9.3 @@ -28268,3 +28063,7 @@ packages: dependencies: tslib: 2.5.3 dev: true + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false From b5b75332e470a34d774ae8b1c6c4e4c4107fb5ba Mon Sep 17 00:00:00 2001 From: Colum Ferry Date: Thu, 27 Jul 2023 13:15:26 +0100 Subject: [PATCH 181/262] fix(core): eslint dep check rule should check prereleases correctly (#18317) --- packages/eslint-plugin/src/rules/dependency-checks.ts | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/packages/eslint-plugin/src/rules/dependency-checks.ts b/packages/eslint-plugin/src/rules/dependency-checks.ts index b539ebd27d6e2..d633b7d7f2010 100644 --- a/packages/eslint-plugin/src/rules/dependency-checks.ts +++ b/packages/eslint-plugin/src/rules/dependency-checks.ts @@ -2,12 +2,7 @@ import { join } from 'path'; import { satisfies } from 'semver'; import { AST } from 'jsonc-eslint-parser'; import { type JSONLiteral } from 'jsonc-eslint-parser/lib/parser/ast'; -import { - normalizePath, - ProjectGraphProjectNode, - FileData, - workspaceRoot, -} from '@nx/devkit'; +import { normalizePath, workspaceRoot } from '@nx/devkit'; import { findNpmDependencies } from '@nx/js/src/utils/find-npm-dependencies'; import { createESLintRule } from '../utils/create-eslint-rule'; @@ -209,7 +204,9 @@ export default createESLintRule({ if ( npmDependencies[packageName] === '*' || packageRange === '*' || - satisfies(npmDependencies[packageName], packageRange) + satisfies(npmDependencies[packageName], packageRange, { + includePrerelease: true, + }) ) { return; } From 736a3ac11eefa862aa689315389462a56d833f65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Jona=C5=A1?= Date: Thu, 27 Jul 2023 15:35:09 +0200 Subject: [PATCH 182/262] fix(react): fix mfe dev server for yarn pnp (#18338) --- .../module-federation-ssr-dev-server.impl.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/react/src/executors/module-federation-ssr-dev-server/module-federation-ssr-dev-server.impl.ts b/packages/react/src/executors/module-federation-ssr-dev-server/module-federation-ssr-dev-server.impl.ts index e2e2c355a20e3..72bf329a4a6ba 100644 --- a/packages/react/src/executors/module-federation-ssr-dev-server/module-federation-ssr-dev-server.impl.ts +++ b/packages/react/src/executors/module-federation-ssr-dev-server/module-federation-ssr-dev-server.impl.ts @@ -1,5 +1,6 @@ import { ExecutorContext, + getPackageManagerCommand, logger, runExecutor, workspaceRoot, @@ -98,8 +99,9 @@ export default async function* moduleFederationSsrDevServer( remoteProject.targets.server.options.outputPath, 'main.js' ); + const pm = getPackageManagerCommand(); execSync( - `npx nx run ${appName}:server${ + `${pm.exec} nx run ${appName}:server${ context.configurationName ? `:${context.configurationName}` : '' }`, { stdio: 'inherit' } From 01ef42bc44f701cb9a5c52a2a23b0ee7224f94ef Mon Sep 17 00:00:00 2001 From: Koen Van Geert <103425830+koenvangeert@users.noreply.github.com> Date: Thu, 27 Jul 2023 15:44:56 +0200 Subject: [PATCH 183/262] fix(react): timeout after 20 min waiting for remote (#18099) Co-authored-by: Emily Xiong --- .../module-federation-dev-server.impl.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/react/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts b/packages/react/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts index b1b7db1c4b97c..fc6f574697d54 100644 --- a/packages/react/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts +++ b/packages/react/src/executors/module-federation-dev-server/module-federation-dev-server.impl.ts @@ -204,6 +204,7 @@ export default async function* moduleFederationDevServer( waitForPortOpen(port, { retries: 480, retryDelay: 2500, + host: 'localhost', }) ) ); From 1363baea28da820e2d5563ab0476d213c39217d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Jona=C5=A1?= Date: Thu, 27 Jul 2023 15:54:23 +0200 Subject: [PATCH 184/262] fix(nextjs): builder should work with pnp (#18325) --- packages/next/src/executors/build/build.impl.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/next/src/executors/build/build.impl.ts b/packages/next/src/executors/build/build.impl.ts index eb0678c66f76b..4481e5f74a820 100644 --- a/packages/next/src/executors/build/build.impl.ts +++ b/packages/next/src/executors/build/build.impl.ts @@ -1,6 +1,7 @@ import 'dotenv/config'; import { ExecutorContext, + getPackageManagerCommand, logger, readJsonFile, writeJsonFile, @@ -53,11 +54,11 @@ export default async function buildExecutor( process.env.NX_NEXT_OUTPUT_PATH ??= outputPath; const args = createCliOptions({ experimentalAppOnly, profile, debug }); - const command = `npx next build ${args.join(' ')}`; + const pm = getPackageManagerCommand(); + const command = `${pm.exec} next build ${projectRoot} ${args.join(' ')}`; const execSyncOptions: ExecSyncOptions = { stdio: 'inherit', encoding: 'utf-8', - cwd: projectRoot, }; try { execSync(command, execSyncOptions); From d02950bb1bf206446d505981cfe0507c469e9d70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Jona=C5=A1?= Date: Thu, 27 Jul 2023 16:21:33 +0200 Subject: [PATCH 185/262] feat(repo): enable custom version publish on e2e (#18341) --- e2e/utils/global-setup.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/e2e/utils/global-setup.ts b/e2e/utils/global-setup.ts index f2a732b237709..5f78d7e7dbf42 100644 --- a/e2e/utils/global-setup.ts +++ b/e2e/utils/global-setup.ts @@ -24,8 +24,9 @@ export default async function (globalConfig: Config.ConfigGlobals) { !existsSync('./build') ) { console.log('Publishing packages to local registry'); + const publishVersion = process.env.PUBLISHED_VERSION ?? 'major'; await new Promise((res, rej) => { - const publishProcess = exec('pnpm nx-release --local major', { + const publishProcess = exec(`pnpm nx-release --local ${publishVersion}`, { env: process.env, }); let logs = Buffer.from(''); From 423a68b70e6f7f45c0a45e46f73dbfb3ccffe713 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Jona=C5=A1?= Date: Thu, 27 Jul 2023 17:10:06 +0200 Subject: [PATCH 186/262] fix(core): improve yarn tarball detection (#18335) --- .../plugins/js/lock-file/yarn-parser.spec.ts | 185 ++++++++++++++++++ .../src/plugins/js/lock-file/yarn-parser.ts | 61 +++--- 2 files changed, 222 insertions(+), 24 deletions(-) diff --git a/packages/nx/src/plugins/js/lock-file/yarn-parser.spec.ts b/packages/nx/src/plugins/js/lock-file/yarn-parser.spec.ts index 9192ad4de64f9..748771b016731 100644 --- a/packages/nx/src/plugins/js/lock-file/yarn-parser.spec.ts +++ b/packages/nx/src/plugins/js/lock-file/yarn-parser.spec.ts @@ -616,6 +616,191 @@ describe('yarn LockFile utility', () => { }); }); + describe('auxiliary tagged version ranges', () => { + beforeEach(() => { + const fileSys = { + 'node_modules/@nrwl/nx-cloud/package.json': '{"version": "16.1.1"}', + 'node_modules/nx-cloud/package.json': '{"version": "16.1.1"}', + 'node_modules/postgres/package.json': '{"version": "3.2.4"}', + }; + vol.fromJSON(fileSys, '/root'); + }); + + it('should parse tagged version range in combination with semver', () => { + const lockFile = `# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + +"@nrwl/nx-cloud@16.1.1": + version "16.1.1" + resolved "http://localhost:4873/@nrwl%2fnx-cloud/-/nx-cloud-16.1.1.tgz#9e1ed2acff11ab0ae8a4c0c045d412034ac26be7" + integrity sha512-iJIPP46+saFZK748FKU4u4YZH+Sv3ZvZPbMwGVMhwqhOYcrlO5aSa0lpilyoN8WuhooKNqcCfiqshx6V577fTg== + dependencies: + nx-cloud "16.1.1" + +nx-cloud@16.1.1, nx-cloud@latest: + version "16.1.1" + resolved "http://localhost:4873/nx-cloud/-/nx-cloud-16.1.1.tgz#103ae0f13f5eb05d6ddd6d9bfcafc56cf295a59a" + integrity sha512-Rq7ynvkYzAJ67N3pDqU6cMqwvWP7WXJGP4EFjLxgUrRHNCccqDPggeAqePodfk3nZEUrZB8F5QBKZuuw1DR3oA== + dependencies: + "@nrwl/nx-cloud" "16.1.1" + +postgres@charsleysa/postgres#fix-errors-compiled: + version "3.2.4" + resolved "https://codeload.github.com/charsleysa/postgres/tar.gz/3b1a01b2da3e2fafb1a79006f838eff11a8de3cb" + `; + const packageJson: PackageJson = { + name: '@my-ns/example', + version: '0.0.1', + type: 'commonjs', + dependencies: { + 'nx-cloud': 'latest', + postgres: 'charsleysa/postgres#fix-errors-compiled', + }, + }; + + const builder = new ProjectGraphBuilder(); + parseYarnLockfile(lockFile, packageJson, builder); + const graph = builder.getUpdatedProjectGraph(); + expect(graph.externalNodes['npm:@nrwl/nx-cloud']).toMatchInlineSnapshot(` + { + "data": { + "hash": "sha512-iJIPP46+saFZK748FKU4u4YZH+Sv3ZvZPbMwGVMhwqhOYcrlO5aSa0lpilyoN8WuhooKNqcCfiqshx6V577fTg==", + "packageName": "@nrwl/nx-cloud", + "version": "16.1.1", + }, + "name": "npm:@nrwl/nx-cloud", + "type": "npm", + } + `); + expect(graph.externalNodes['npm:nx-cloud']).toMatchInlineSnapshot(` + { + "data": { + "hash": "sha512-Rq7ynvkYzAJ67N3pDqU6cMqwvWP7WXJGP4EFjLxgUrRHNCccqDPggeAqePodfk3nZEUrZB8F5QBKZuuw1DR3oA==", + "packageName": "nx-cloud", + "version": "16.1.1", + }, + "name": "npm:nx-cloud", + "type": "npm", + } + `); + expect(graph.externalNodes['npm:postgres']).toMatchInlineSnapshot(` + { + "data": { + "hash": "postgres|https://codeload.github.com/charsleysa/postgres/tar.gz/3b1a01b2da3e2fafb1a79006f838eff11a8de3cb", + "packageName": "postgres", + "version": "https://codeload.github.com/charsleysa/postgres/tar.gz/3b1a01b2da3e2fafb1a79006f838eff11a8de3cb", + }, + "name": "npm:postgres", + "type": "npm", + } + `); + }); + + it('should parse tagged version range in combination with semver in reverse order', () => { + const lockFile = `# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + +"@nrwl/nx-cloud@16.1.1": + version "16.1.1" + resolved "http://localhost:4873/@nrwl%2fnx-cloud/-/nx-cloud-16.1.1.tgz#9e1ed2acff11ab0ae8a4c0c045d412034ac26be7" + integrity sha512-iJIPP46+saFZK748FKU4u4YZH+Sv3ZvZPbMwGVMhwqhOYcrlO5aSa0lpilyoN8WuhooKNqcCfiqshx6V577fTg== + dependencies: + nx-cloud "16.1.1" + +nx-cloud@latest, nx-cloud@16.1.1: + version "16.1.1" + resolved "http://localhost:4873/nx-cloud/-/nx-cloud-16.1.1.tgz#103ae0f13f5eb05d6ddd6d9bfcafc56cf295a59a" + integrity sha512-Rq7ynvkYzAJ67N3pDqU6cMqwvWP7WXJGP4EFjLxgUrRHNCccqDPggeAqePodfk3nZEUrZB8F5QBKZuuw1DR3oA== + dependencies: + "@nrwl/nx-cloud" "16.1.1" + +postgres@charsleysa/postgres#fix-errors-compiled: + version "3.2.4" + resolved "https://codeload.github.com/charsleysa/postgres/tar.gz/3b1a01b2da3e2fafb1a79006f838eff11a8de3cb" + `; + const packageJson: PackageJson = { + name: '@my-ns/example', + version: '0.0.1', + type: 'commonjs', + dependencies: { + 'nx-cloud': 'latest', + postgres: 'charsleysa/postgres#fix-errors-compiled', + }, + }; + + const builder = new ProjectGraphBuilder(); + parseYarnLockfile(lockFile, packageJson, builder); + const graph = builder.getUpdatedProjectGraph(); + expect(graph.externalNodes['npm:@nrwl/nx-cloud']).toMatchInlineSnapshot(` + { + "data": { + "hash": "sha512-iJIPP46+saFZK748FKU4u4YZH+Sv3ZvZPbMwGVMhwqhOYcrlO5aSa0lpilyoN8WuhooKNqcCfiqshx6V577fTg==", + "packageName": "@nrwl/nx-cloud", + "version": "16.1.1", + }, + "name": "npm:@nrwl/nx-cloud", + "type": "npm", + } + `); + expect(graph.externalNodes['npm:nx-cloud']).toMatchInlineSnapshot(` + { + "data": { + "hash": "sha512-Rq7ynvkYzAJ67N3pDqU6cMqwvWP7WXJGP4EFjLxgUrRHNCccqDPggeAqePodfk3nZEUrZB8F5QBKZuuw1DR3oA==", + "packageName": "nx-cloud", + "version": "16.1.1", + }, + "name": "npm:nx-cloud", + "type": "npm", + } + `); + expect(graph.externalNodes['npm:postgres']).toMatchInlineSnapshot(` + { + "data": { + "hash": "postgres|https://codeload.github.com/charsleysa/postgres/tar.gz/3b1a01b2da3e2fafb1a79006f838eff11a8de3cb", + "packageName": "postgres", + "version": "https://codeload.github.com/charsleysa/postgres/tar.gz/3b1a01b2da3e2fafb1a79006f838eff11a8de3cb", + }, + "name": "npm:postgres", + "type": "npm", + } + `); + }); + + it('should parse tagged version range', () => { + const lockFile = `# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + +nx-cloud@latest: + version "16.1.1" + resolved "http://localhost:4873/nx-cloud/-/nx-cloud-16.1.1.tgz#103ae0f13f5eb05d6ddd6d9bfcafc56cf295a59a" + integrity sha512-Rq7ynvkYzAJ67N3pDqU6cMqwvWP7WXJGP4EFjLxgUrRHNCccqDPggeAqePodfk3nZEUrZB8F5QBKZuuw1DR3oA== + `; + const packageJson: PackageJson = { + name: '@my-ns/example', + version: '0.0.1', + type: 'commonjs', + dependencies: { + 'nx-cloud': 'latest', + }, + }; + + const builder = new ProjectGraphBuilder(); + parseYarnLockfile(lockFile, packageJson, builder); + const graph = builder.getUpdatedProjectGraph(); + expect(graph.externalNodes['npm:nx-cloud']).toMatchInlineSnapshot(` + { + "data": { + "hash": "sha512-Rq7ynvkYzAJ67N3pDqU6cMqwvWP7WXJGP4EFjLxgUrRHNCccqDPggeAqePodfk3nZEUrZB8F5QBKZuuw1DR3oA==", + "packageName": "nx-cloud", + "version": "16.1.1", + }, + "name": "npm:nx-cloud", + "type": "npm", + } + `); + }); + }); + describe('auxiliary packages PnP', () => { it('should parse yarn berry pnp', () => { const berryLockFile = require(joinPathFragments( diff --git a/packages/nx/src/plugins/js/lock-file/yarn-parser.ts b/packages/nx/src/plugins/js/lock-file/yarn-parser.ts index 3de74ed6373ac..75737bc1b6ac1 100644 --- a/packages/nx/src/plugins/js/lock-file/yarn-parser.ts +++ b/packages/nx/src/plugins/js/lock-file/yarn-parser.ts @@ -14,10 +14,6 @@ import { sortObjectByKeys } from '../../../utils/object-sort'; * - Classic has resolved and integrity * - Berry has resolution, checksum, languageName and linkType */ -type YarnLockFile = { - __metadata?: {}; -} & Record; - type YarnDependency = { version: string; dependencies?: Record; @@ -41,12 +37,17 @@ export function parseYarnLockfile( builder: ProjectGraphBuilder ) { const { parseSyml } = require('@yarnpkg/parsers'); - const data = parseSyml(lockFileContent); + const { __metadata, ...dependencies } = parseSyml(lockFileContent); + const isBerry = !!__metadata; // we use key => node map to avoid duplicate work when parsing keys const keyMap = new Map(); - addNodes(data, packageJson, builder, keyMap); - addDependencies(data, builder, keyMap); + + // yarn classic splits keys when parsing so we need to stich them back together + const groupedDependencies = groupDependencies(dependencies, isBerry); + + addNodes(groupedDependencies, packageJson, builder, keyMap, isBerry); + addDependencies(groupedDependencies, builder, keyMap); } function getPackageNames(keys: string): string[] { @@ -59,12 +60,12 @@ function getPackageNames(keys: string): string[] { } function addNodes( - { __metadata, ...dependencies }: YarnLockFile, + dependencies: Record, packageJson: NormalizedPackageJson, builder: ProjectGraphBuilder, - keyMap: Map + keyMap: Map, + isBerry: boolean ) { - const isBerry = !!__metadata; const nodes: Map> = new Map(); const combinedDeps = { ...packageJson.dependencies, @@ -200,20 +201,33 @@ function findVersion( return snapshot.resolution.slice(packageName.length + 1); } - if (!isBerry && snapshot.resolved && !isValidVersionRange(versionRange)) { + if (!isBerry && isTarballPackage(versionRange, snapshot)) { return snapshot.resolved; } // otherwise it's a standard version return snapshot.version; } -// check if value can be parsed as a semver range -function isValidVersionRange(versionRange: string): boolean { +// check if snapshot represents tarball package +function isTarballPackage( + versionRange: string, + snapshot: YarnDependency +): boolean { + // if resolved is missing it's internal link + if (!snapshot.resolved) { + return false; + } + // tarballs have no integrity + if (snapshot.integrity) { + return false; + } try { new Range(versionRange); - return true; - } catch { + // range is a valid semver return false; + } catch { + // range is not a valid semver, it can be an npm tag or url part of a tarball + return snapshot.version && !snapshot.resolved.includes(snapshot.version); } } @@ -225,7 +239,7 @@ function getHoistedVersion(packageName: string): string { } function addDependencies( - { __metadata, ...dependencies }: YarnLockFile, + dependencies: Record, builder: ProjectGraphBuilder, keyMap: Map ) { @@ -288,8 +302,12 @@ export function stringifyYarnLockfile( } function groupDependencies( - dependencies: Record + dependencies: Record, + isBerry: boolean ): Record { + if (isBerry) { + return dependencies; + } let groupedDependencies: Record; const resolutionMap = new Map(); const snapshotMap = new Map>(); @@ -342,13 +360,8 @@ function mapSnapshots( ...packageJson.peerDependencies, }; - let groupedDependencies: Record; - if (isBerry) { - groupedDependencies = dependencies; - } else { - // yarn classic splits keys when parsing so we need to stich them back together - groupedDependencies = groupDependencies(dependencies); - } + // yarn classic splits keys when parsing so we need to stich them back together + const groupedDependencies = groupDependencies(dependencies, isBerry); // collect snapshots and their matching keys Object.values(nodes).forEach((node) => { From 2dc6656f4ba081476cc230d8067c830ba078d2ea Mon Sep 17 00:00:00 2001 From: Jack Hsu Date: Thu, 27 Jul 2023 11:34:03 -0400 Subject: [PATCH 187/262] fix(bundling): add missing main export for @nx/vite (#18344) --- packages/vite/package.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/vite/package.json b/packages/vite/package.json index 59a2e6e432f2e..f8e01c2225658 100644 --- a/packages/vite/package.json +++ b/packages/vite/package.json @@ -45,9 +45,8 @@ "access": "public" }, "exports": { - "./package.json": { - "require": "./package.json" - }, + ".": "./index.js", + "./package.json": "./package.json", "./migrations.json": "./migrations.json", "./generators.json": "./generators.json", "./executors.json": "./executors.json", From 36dae70fb0cb7ce3b046867fbbc266be25c189d1 Mon Sep 17 00:00:00 2001 From: Mike Gregson Date: Thu, 27 Jul 2023 18:49:56 +0100 Subject: [PATCH 188/262] feat(vite): add v8 coverage support to vitest generator (#18114) --- .../packages/vite/generators/vitest.json | 4 +-- .../vite/src/generators/vitest/schema.d.ts | 2 +- .../vite/src/generators/vitest/schema.json | 8 +++-- .../src/generators/vitest/vitest-generator.ts | 32 +++++++++++++++---- packages/vite/src/utils/versions.ts | 1 + 5 files changed, 34 insertions(+), 13 deletions(-) diff --git a/docs/generated/packages/vite/generators/vitest.json b/docs/generated/packages/vite/generators/vitest.json index a4d5b38584f73..f9b72140e3a37 100644 --- a/docs/generated/packages/vite/generators/vitest.json +++ b/docs/generated/packages/vite/generators/vitest.json @@ -32,8 +32,8 @@ }, "coverageProvider": { "type": "string", - "enum": ["c8", "istanbul"], - "default": "c8", + "enum": ["v8", "c8", "istanbul"], + "default": "v8", "description": "Coverage provider to use." }, "testTarget": { diff --git a/packages/vite/src/generators/vitest/schema.d.ts b/packages/vite/src/generators/vitest/schema.d.ts index 0cc157eabb83e..5b5039be21855 100644 --- a/packages/vite/src/generators/vitest/schema.d.ts +++ b/packages/vite/src/generators/vitest/schema.d.ts @@ -1,7 +1,7 @@ export interface VitestGeneratorSchema { project: string; uiFramework: 'react' | 'none'; - coverageProvider: 'c8' | 'istanbul'; + coverageProvider: 'v8' | 'c8' | 'istanbul'; inSourceTests?: boolean; skipViteConfig?: boolean; testTarget?: string; diff --git a/packages/vite/src/generators/vitest/schema.json b/packages/vite/src/generators/vitest/schema.json index cb84f962042dd..6f98e0f49bcb2 100644 --- a/packages/vite/src/generators/vitest/schema.json +++ b/packages/vite/src/generators/vitest/schema.json @@ -9,7 +9,9 @@ "project": { "type": "string", "description": "The name of the project to test.", - "$default": { "$source": "projectName" } + "$default": { + "$source": "projectName" + } }, "uiFramework": { "type": "string", @@ -29,8 +31,8 @@ }, "coverageProvider": { "type": "string", - "enum": ["c8", "istanbul"], - "default": "c8", + "enum": ["v8", "c8", "istanbul"], + "default": "v8", "description": "Coverage provider to use." }, "testTarget": { diff --git a/packages/vite/src/generators/vitest/vitest-generator.ts b/packages/vite/src/generators/vitest/vitest-generator.ts index c5ca7e709d524..0ff7d26f4d8f8 100644 --- a/packages/vite/src/generators/vitest/vitest-generator.ts +++ b/packages/vite/src/generators/vitest/vitest-generator.ts @@ -22,6 +22,7 @@ import initGenerator from '../init/init'; import { vitestCoverageC8Version, vitestCoverageIstanbulVersion, + vitestCoverageV8Version, } from '../../utils/versions'; import { addTsLibDependencies } from '@nx/js'; @@ -64,16 +65,14 @@ export async function vitestGenerator( createFiles(tree, schema, root); updateTsConfig(tree, schema, root); + const coverageProviderDependency = getCoverageProviderDependency( + schema.coverageProvider + ); + const installCoverageProviderTask = addDependenciesToPackageJson( tree, {}, - schema.coverageProvider === 'istanbul' - ? { - '@vitest/coverage-istanbul': vitestCoverageIstanbulVersion, - } - : { - '@vitest/coverage-c8': vitestCoverageC8Version, - } + coverageProviderDependency ); tasks.push(installCoverageProviderTask); @@ -150,5 +149,24 @@ function createFiles( }); } +function getCoverageProviderDependency( + coverageProvider: VitestGeneratorSchema['coverageProvider'] +) { + switch (coverageProvider) { + case 'c8': + return { + '@vitest/coverage-c8': vitestCoverageC8Version, + }; + case 'istanbul': + return { + '@vitest/coverage-istanbul': vitestCoverageIstanbulVersion, + }; + default: + return { + '@vitest/coverage-v8': vitestCoverageV8Version, + }; + } +} + export default vitestGenerator; export const vitestSchematic = convertNxGenerator(vitestGenerator); diff --git a/packages/vite/src/utils/versions.ts b/packages/vite/src/utils/versions.ts index e3e4ab39984ee..ab7f9a103e3d0 100644 --- a/packages/vite/src/utils/versions.ts +++ b/packages/vite/src/utils/versions.ts @@ -11,4 +11,5 @@ export const edgeRuntimeVmVersion = '~3.0.2'; // Coverage providers export const vitestCoverageC8Version = '~0.32.0'; +export const vitestCoverageV8Version = '~0.32.0'; export const vitestCoverageIstanbulVersion = '~0.32.0'; From e4d23383f558dcbd20651017c937f2a034da2503 Mon Sep 17 00:00:00 2001 From: Jason Jean Date: Thu, 27 Jul 2023 14:33:08 -0400 Subject: [PATCH 189/262] fix(core): fix dep outputs hashing (#18331) --- .../with-environment.ts | 8 - .../__snapshots__/task-hasher.spec.ts.snap | 386 ++++++++++++++++ packages/nx/src/hasher/file-hasher.ts | 6 - packages/nx/src/hasher/task-hasher.spec.ts | 433 ++++++++---------- packages/nx/src/hasher/task-hasher.ts | 102 +++-- .../nx/src/native/cache/expand_outputs.rs | 65 ++- packages/nx/src/native/hasher.rs | 53 --- packages/nx/src/native/index.d.ts | 10 +- packages/nx/src/native/index.js | 4 +- packages/nx/src/native/utils/glob.rs | 6 + packages/nx/src/plugins/js/hasher/hasher.ts | 4 +- packages/nx/src/utils/workspace-root.ts | 4 - 12 files changed, 718 insertions(+), 363 deletions(-) create mode 100644 packages/nx/src/hasher/__snapshots__/task-hasher.spec.ts.snap diff --git a/packages/nx/internal-testing-utils/with-environment.ts b/packages/nx/internal-testing-utils/with-environment.ts index 95c4f1da453a9..739a2c70248fd 100644 --- a/packages/nx/internal-testing-utils/with-environment.ts +++ b/packages/nx/internal-testing-utils/with-environment.ts @@ -1,11 +1,3 @@ -export function withEnvironmentVariables( - env: Record, - callback: () => void -): void; -export function withEnvironmentVariables( - env: Record, - callback: () => Promise -): Promise; export function withEnvironmentVariables( env: Record, callback: () => void | Promise diff --git a/packages/nx/src/hasher/__snapshots__/task-hasher.spec.ts.snap b/packages/nx/src/hasher/__snapshots__/task-hasher.spec.ts.snap new file mode 100644 index 0000000000000..d3702d19e0b55 --- /dev/null +++ b/packages/nx/src/hasher/__snapshots__/task-hasher.spec.ts.snap @@ -0,0 +1,386 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`TaskHasher dependentTasksOutputFiles should depend on dependent tasks output files 1`] = ` +{ + "details": { + "command": "4062279404379299270", + "implicitDeps": {}, + "nodes": { + "ProjectConfiguration": "12802727827024321009", + "TsConfig": "8767608672024750088", + "dist/libs/child/index.d.ts": "3244421341483603138", + "dist/libs/grandchild/index.d.ts": "3244421341483603138", + "parent:!{projectRoot}/**/*.spec.ts": "17962802443644575456", + "target": "1389868326933519382", + "{workspaceRoot}/.gitignore": "3244421341483603138", + "{workspaceRoot}/.nxignore": "3244421341483603138", + "{workspaceRoot}/nx.json": "8942239360311677987", + }, + "runtime": {}, + }, + "value": "17939200785615949974", +} +`; + +exports[`TaskHasher dependentTasksOutputFiles should work with dependent tasks with globs as outputs 1`] = ` +{ + "details": { + "command": "4062279404379299270", + "implicitDeps": {}, + "nodes": { + "ProjectConfiguration": "12802727827024321009", + "TsConfig": "8767608672024750088", + "dist/libs/child/index.d.ts": "3244421341483603138", + "dist/libs/grandchild/index.d.ts": "3244421341483603138", + "parent:!{projectRoot}/**/*.spec.ts": "17962802443644575456", + "target": "1389868326933519382", + "{workspaceRoot}/.gitignore": "3244421341483603138", + "{workspaceRoot}/.nxignore": "3244421341483603138", + "{workspaceRoot}/nx.json": "8942239360311677987", + }, + "runtime": {}, + }, + "value": "17939200785615949974", +} +`; + +exports[`TaskHasher hashTarget should hash entire subtree of dependencies 1`] = ` +{ + "details": { + "command": "14389236043839781668", + "implicitDeps": {}, + "nodes": { + "ProjectConfiguration": "12026883044296863450", + "TsConfig": "8767608672024750088", + "app:{projectRoot}/**/*": "3244421341483603138", + "target": "3789300870433976270", + "{workspaceRoot}/.gitignore": "3244421341483603138", + "{workspaceRoot}/.nxignore": "3244421341483603138", + "{workspaceRoot}/nx.json": "8942239360311677987", + }, + "runtime": {}, + }, + "value": "11829832011053499600", +} +`; + +exports[`TaskHasher hashTarget should hash executor dependencies of @nx packages 1`] = ` +{ + "details": { + "command": "14389236043839781668", + "implicitDeps": {}, + "nodes": { + "ProjectConfiguration": "12026883044296863450", + "TsConfig": "8767608672024750088", + "app:{projectRoot}/**/*": "3244421341483603138", + "target": "1274004356858584726", + "{workspaceRoot}/.gitignore": "3244421341483603138", + "{workspaceRoot}/.nxignore": "3244421341483603138", + "{workspaceRoot}/nx.json": "8942239360311677987", + }, + "runtime": {}, + }, + "value": "15096054768893599383", +} +`; + +exports[`TaskHasher hashTarget should use externalDependencies to override nx:run-commands 1`] = ` +{ + "details": { + "command": "14389236043839781668", + "implicitDeps": {}, + "nodes": { + "ProjectConfiguration": "17956886683554891195", + "TsConfig": "8767608672024750088", + "app:{projectRoot}/**/*": "3244421341483603138", + "env:undefined": "3244421341483603138", + "target": "7688798210438770308", + "{workspaceRoot}/.gitignore": "3244421341483603138", + "{workspaceRoot}/.nxignore": "3244421341483603138", + "{workspaceRoot}/nx.json": "8942239360311677987", + }, + "runtime": {}, + }, + "value": "18142315317355318287", +} +`; + +exports[`TaskHasher hashTarget should use externalDependencies with empty array to ignore all deps 1`] = ` +{ + "details": { + "command": "14389236043839781668", + "implicitDeps": {}, + "nodes": { + "ProjectConfiguration": "9179552940021403596", + "TsConfig": "8767608672024750088", + "app:{projectRoot}/**/*": "3244421341483603138", + "env:undefined": "3244421341483603138", + "target": "3244421341483603138", + "{workspaceRoot}/.gitignore": "3244421341483603138", + "{workspaceRoot}/.nxignore": "3244421341483603138", + "{workspaceRoot}/nx.json": "8942239360311677987", + }, + "runtime": {}, + }, + "value": "13520777692097937224", +} +`; + +exports[`TaskHasher should be able to handle multiple filesets per project 1`] = ` +{ + "details": { + "command": "13785966310271077209", + "implicitDeps": {}, + "nodes": { + "ProjectConfiguration": "17211930887387929067", + "TsConfig": "8767608672024750088", + "child:!{projectRoot}/**/*.spec.ts": "17508782620731849000", + "env:MY_TEST_HASH_ENV": "17357374746554314488", + "parent:{projectRoot}/**/*": "7263479247245830838", + "target": "1389868326933519382", + "{workspaceRoot}/.gitignore": "3244421341483603138", + "{workspaceRoot}/.nxignore": "3244421341483603138", + "{workspaceRoot}/global1": "3052102066027208710", + "{workspaceRoot}/global2": "8197394511443659629", + "{workspaceRoot}/nx.json": "8942239360311677987", + }, + "runtime": {}, + }, + "value": "2881231822394274502", +} +`; + +exports[`TaskHasher should be able to handle multiple filesets per project 2`] = ` +{ + "details": { + "command": "6958627266354933907", + "implicitDeps": {}, + "nodes": { + "ProjectConfiguration": "17211930887387929067", + "TsConfig": "8767608672024750088", + "child:{projectRoot}/**/*": "2300207741412661544", + "target": "1389868326933519382", + "{workspaceRoot}/.gitignore": "3244421341483603138", + "{workspaceRoot}/.nxignore": "3244421341483603138", + "{workspaceRoot}/global1": "3052102066027208710", + "{workspaceRoot}/nx.json": "8942239360311677987", + }, + "runtime": {}, + }, + "value": "3952879073081711415", +} +`; + +exports[`TaskHasher should be able to include only a part of the base tsconfig 1`] = ` +{ + "details": { + "command": "4062279404379299270", + "implicitDeps": {}, + "nodes": { + "ProjectConfiguration": "18166168584521190546", + "TsConfig": "4035819825874039301", + "parent:{projectRoot}/**/*": "8263681721738113012", + "runtime:echo runtime123": "runtime123", + "runtime:echo runtime456": "runtime456", + "target": "1389868326933519382", + "{workspaceRoot}/.gitignore": "3244421341483603138", + "{workspaceRoot}/.nxignore": "3244421341483603138", + "{workspaceRoot}/nx.json": "8942239360311677987", + }, + "runtime": {}, + }, + "value": "9968611270204908917", +} +`; + +exports[`TaskHasher should create task hash 1`] = ` +{ + "details": { + "command": "4062279404379299270", + "implicitDeps": {}, + "nodes": { + "ProjectConfiguration": "4875698716044094030", + "TsConfig": "8767608672024750088", + "env:NONEXISTENTENV": "3244421341483603138", + "env:TESTENV": "6544740722075256274", + "parent:{projectRoot}/**/*": "8263681721738113012", + "runtime:echo runtime123": "runtime123", + "runtime:echo runtime456": "runtime456", + "tagged:{projectRoot}/**/*": "3244421341483603138", + "target": "1389868326933519382", + "unrelated:{projectRoot}/**/*": "10091615118977982257", + "{workspaceRoot}/.gitignore": "3244421341483603138", + "{workspaceRoot}/.nxignore": "3244421341483603138", + "{workspaceRoot}/nx.json": "8942239360311677987", + }, + "runtime": {}, + }, + "value": "11412486534571442418", +} +`; + +exports[`TaskHasher should hash multiple filesets of a project 1`] = ` +{ + "details": { + "command": "13785966310271077209", + "implicitDeps": {}, + "nodes": { + "ProjectConfiguration": "10499856664466672714", + "TsConfig": "8767608672024750088", + "parent:{projectRoot}/**/*": "7263479247245830838", + "target": "1389868326933519382", + "{workspaceRoot}/.gitignore": "3244421341483603138", + "{workspaceRoot}/.nxignore": "3244421341483603138", + "{workspaceRoot}/nx.json": "8942239360311677987", + }, + "runtime": {}, + }, + "value": "14016847448680534278", +} +`; + +exports[`TaskHasher should hash multiple filesets of a project 2`] = ` +{ + "details": { + "command": "4062279404379299270", + "implicitDeps": {}, + "nodes": { + "ProjectConfiguration": "10499856664466672714", + "TsConfig": "8767608672024750088", + "parent:!{projectRoot}/**/*.spec.ts": "17962802443644575456", + "target": "1389868326933519382", + "{workspaceRoot}/.gitignore": "3244421341483603138", + "{workspaceRoot}/.nxignore": "3244421341483603138", + "{workspaceRoot}/nx.json": "8942239360311677987", + }, + "runtime": {}, + }, + "value": "10694393160053318712", +} +`; + +exports[`TaskHasher should hash non-default filesets 1`] = ` +{ + "details": { + "command": "4062279404379299270", + "implicitDeps": {}, + "nodes": { + "ProjectConfiguration": "8196293273405506196", + "TsConfig": "8767608672024750088", + "child:{projectRoot}/**/*": "2300207741412661544", + "parent:!{projectRoot}/**/*.spec.ts": "17962802443644575456", + "target": "1389868326933519382", + "{workspaceRoot}/.gitignore": "3244421341483603138", + "{workspaceRoot}/.nxignore": "3244421341483603138", + "{workspaceRoot}/nx.json": "8942239360311677987", + }, + "runtime": {}, + }, + "value": "15803865862737990375", +} +`; + +exports[`TaskHasher should hash npm project versions 1`] = ` +{ + "details": { + "command": "14389236043839781668", + "implicitDeps": {}, + "nodes": { + "ProjectConfiguration": "8128657069648957137", + "TsConfig": "8767608672024750088", + "app:{projectRoot}/**/*": "9104199730100321982", + "npm:react": "4468841026152585217", + "target": "14358315432887000841", + "{workspaceRoot}/.gitignore": "3244421341483603138", + "{workspaceRoot}/.nxignore": "3244421341483603138", + "{workspaceRoot}/nx.json": "8942239360311677987", + }, + "runtime": {}, + }, + "value": "3668827038634092448", +} +`; + +exports[`TaskHasher should hash task where the project has dependencies 1`] = ` +{ + "details": { + "command": "4062279404379299270", + "implicitDeps": {}, + "nodes": { + "ProjectConfiguration": "8876282510060012181", + "TsConfig": "8767608672024750088", + "child:{projectRoot}/**/*": "5484012818475684626", + "parent:{projectRoot}/**/*": "14822394489351823627", + "target": "1389868326933519382", + "{workspaceRoot}/.gitignore": "3244421341483603138", + "{workspaceRoot}/.nxignore": "3244421341483603138", + "{workspaceRoot}/nx.json": "8942239360311677987", + }, + "runtime": {}, + }, + "value": "16888277333405079717", +} +`; + +exports[`TaskHasher should hash tasks where the project graph has circular dependencies 1`] = ` +{ + "details": { + "command": "4062279404379299270", + "implicitDeps": {}, + "nodes": { + "ProjectConfiguration": "9892649345820140726", + "TsConfig": "8767608672024750088", + "child:{projectRoot}/**/*": "8973015561538144423", + "parent:{projectRoot}/**/*": "9104199730100321982", + "target": "1389868326933519382", + "{workspaceRoot}/.gitignore": "3244421341483603138", + "{workspaceRoot}/.nxignore": "3244421341483603138", + "{workspaceRoot}/nx.json": "8942239360311677987", + }, + "runtime": {}, + }, + "value": "16567132351487630958", +} +`; + +exports[`TaskHasher should hash tasks where the project graph has circular dependencies 2`] = ` +{ + "details": { + "command": "7833005669885463868", + "implicitDeps": {}, + "nodes": { + "ProjectConfiguration": "18166168584521190546", + "TsConfig": "8767608672024750088", + "child:{projectRoot}/**/*": "8973015561538144423", + "parent:{projectRoot}/**/*": "9104199730100321982", + "target": "1389868326933519382", + "{workspaceRoot}/.gitignore": "3244421341483603138", + "{workspaceRoot}/.nxignore": "3244421341483603138", + "{workspaceRoot}/nx.json": "8942239360311677987", + }, + "runtime": {}, + }, + "value": "13014058586283814178", +} +`; + +exports[`TaskHasher should use targetDefaults from nx.json 1`] = ` +{ + "details": { + "command": "4062279404379299270", + "implicitDeps": {}, + "nodes": { + "ProjectConfiguration": "9892649345820140726", + "TsConfig": "8767608672024750088", + "child:!{projectRoot}/**/*.spec.ts": "17508782620731849000", + "parent:!{projectRoot}/**/*.spec.ts": "17962802443644575456", + "target": "1389868326933519382", + "{workspaceRoot}/.gitignore": "3244421341483603138", + "{workspaceRoot}/.nxignore": "3244421341483603138", + "{workspaceRoot}/nx.json": "8942239360311677987", + }, + "runtime": {}, + }, + "value": "2743377369761868812", +} +`; diff --git a/packages/nx/src/hasher/file-hasher.ts b/packages/nx/src/hasher/file-hasher.ts index ffe8224b67cbd..8c5a8936e5fd0 100644 --- a/packages/nx/src/hasher/file-hasher.ts +++ b/packages/nx/src/hasher/file-hasher.ts @@ -28,12 +28,6 @@ export class FileHasher { return hashFile(path).hash; } - hashFilesMatchingGlobs(path: string, globs: string[]): string { - // Import as needed. There is also an issue running unit tests in Nx repo if this is a top-level import. - const { hashFilesMatchingGlobs } = require('../native'); - return hashFilesMatchingGlobs(path, globs); - } - clear(): void { this.fileHashes = new Map(); this.isInitialized = false; diff --git a/packages/nx/src/hasher/task-hasher.spec.ts b/packages/nx/src/hasher/task-hasher.spec.ts index 33632e23a8d88..802f2403d3b7b 100644 --- a/packages/nx/src/hasher/task-hasher.spec.ts +++ b/packages/nx/src/hasher/task-hasher.spec.ts @@ -1,6 +1,7 @@ // This must come before the Hasher import +import { TempFs } from '../utils/testing/temp-fs'; +let tempFs = new TempFs('TaskHasher'); import { DependencyType } from '../config/project-graph'; -import { vol } from 'memfs'; import { expandNamedInput, filterUsingGlobPatterns, @@ -12,23 +13,10 @@ import { withEnvironmentVariables } from '../../internal-testing-utils/with-envi jest.mock('../utils/workspace-root', () => { return { - workspaceRoot: '/root', + workspaceRoot: tempFs.tempDir, }; }); -jest.mock('./file-hasher', () => { - return { - hashArray: (values: string[]) => values.join('|'), - }; -}); - -jest.mock('fs', () => require('memfs').fs); -jest.mock('../plugins/js/utils/typescript', () => ({ - getRootTsConfigFileName: jest - .fn() - .mockImplementation(() => '/root/tsconfig.base.json'), -})); - describe('TaskHasher', () => { const packageJson = { name: 'nrwl', @@ -54,26 +42,16 @@ describe('TaskHasher', () => { { file: 'global2', hash: 'global2.hash' }, ]; - function createFileHasher(): any { - return { - allFileData: () => allWorkspaceFiles, - }; - } - - beforeEach(() => { - vol.fromJSON( - { - 'tsconfig.base.json': tsConfigBaseJson, - 'yarn.lock': 'content', - 'package.json': JSON.stringify(packageJson), - }, - '/root' - ); + beforeEach(async () => { + await tempFs.createFiles({ + 'tsconfig.base.json': tsConfigBaseJson, + 'yarn.lock': 'content', + 'package.json': JSON.stringify(packageJson), + }); }); afterEach(() => { - jest.resetAllMocks(); - vol.reset(); + tempFs.reset(); }); it('should create task hash', () => @@ -147,7 +125,7 @@ describe('TaskHasher', () => { { runtimeCacheInputs: ['echo runtime456'], }, - createFileHasher() + fileHasher ); const hash = await hasher.hashTask({ @@ -156,34 +134,7 @@ describe('TaskHasher', () => { overrides: { prop: 'prop-value' }, }); - expect(hash.value).toContain('file.hash'); //project files - expect(hash.value).toContain('prop-value'); //overrides - expect(hash.value).toContain('parent'); //project - expect(hash.value).toContain('build'); //target - expect(hash.value).toContain('runtime123'); - expect(hash.value).toContain('runtime456'); - expect(hash.value).toContain('env123'); - expect(hash.value).toContain('filec.hash'); - - expect(hash.details.command).toEqual( - 'parent|build||{"prop":"prop-value"}' - ); - expect(hash.details.nodes).toEqual({ - 'parent:{projectRoot}/**/*': - '/file|file.hash|{"root":"libs/parent","targets":{"build":{"executor":"nx:run-commands","inputs":["default","^default",{"runtime":"echo runtime123"},{"env":"TESTENV"},{"env":"NONEXISTENTENV"},{"input":"default","projects":["unrelated","tag:some-tag"]}]}}}|{"compilerOptions":{"paths":{"@nx/parent":["libs/parent/src/index.ts"],"@nx/child":["libs/child/src/index.ts"]}}}', - target: 'nx:run-commands', - 'unrelated:{projectRoot}/**/*': - 'libs/unrelated/filec.ts|filec.hash|{"root":"libs/unrelated","targets":{"build":{}}}|{"compilerOptions":{"paths":{"@nx/parent":["libs/parent/src/index.ts"],"@nx/child":["libs/child/src/index.ts"]}}}', - 'tagged:{projectRoot}/**/*': - '{"root":"libs/tagged","targets":{"build":{}},"tags":["some-tag"]}|{"compilerOptions":{"paths":{"@nx/parent":["libs/parent/src/index.ts"],"@nx/child":["libs/child/src/index.ts"]}}}', - '{workspaceRoot}/nx.json': 'nx.json.hash', - '{workspaceRoot}/.gitignore': '', - '{workspaceRoot}/.nxignore': '', - 'runtime:echo runtime123': 'runtime123', - 'runtime:echo runtime456': 'runtime456', - 'env:TESTENV': 'env123', - 'env:NONEXISTENTENV': '', - }); + expect(hash).toMatchSnapshot(); })); it('should hash task where the project has dependencies', async () => { @@ -218,6 +169,7 @@ describe('TaskHasher', () => { }, }, }, + externalNodes: {}, dependencies: { parent: [{ source: 'parent', target: 'child', type: 'static' }], }, @@ -242,7 +194,7 @@ describe('TaskHasher', () => { }, {} as any, {}, - createFileHasher() + fileHasher ); const hash = await hasher.hashTask({ @@ -251,16 +203,7 @@ describe('TaskHasher', () => { overrides: { prop: 'prop-value' }, }); - assertFilesets(hash, { - 'child:{projectRoot}/**/*': { - contains: '/fileb.ts|/fileb.spec.ts', - excludes: '/filea.ts', - }, - 'parent:{projectRoot}/**/*': { - contains: '/filea.ts|/filea.spec.ts', - excludes: '/fileb.ts', - }, - }); + expect(hash).toMatchSnapshot(); }); it('should hash non-default filesets', async () => { @@ -303,6 +246,7 @@ describe('TaskHasher', () => { }, }, }, + externalNodes: {}, dependencies: { parent: [{ source: 'parent', target: 'child', type: 'static' }], }, @@ -331,7 +275,7 @@ describe('TaskHasher', () => { }, } as any, {}, - createFileHasher() + fileHasher ); const hash = await hasher.hashTask({ @@ -340,16 +284,7 @@ describe('TaskHasher', () => { overrides: { prop: 'prop-value' }, }); - assertFilesets(hash, { - 'child:{projectRoot}/**/*': { - contains: 'libs/child/fileb.ts|libs/child/fileb.spec.ts', - excludes: 'filea.ts', - }, - 'parent:!{projectRoot}/**/*.spec.ts': { - contains: 'filea.ts', - excludes: 'filea.spec.ts', - }, - }); + expect(hash).toMatchSnapshot(); }); it('should hash multiple filesets of a project', async () => { @@ -382,6 +317,7 @@ describe('TaskHasher', () => { }, }, }, + externalNodes: {}, dependencies: { parent: [], }, @@ -403,7 +339,7 @@ describe('TaskHasher', () => { }, } as any, {}, - createFileHasher() + fileHasher ); const test = await hasher.hashTask({ @@ -412,11 +348,7 @@ describe('TaskHasher', () => { overrides: { prop: 'prop-value' }, }); - assertFilesets(test, { - 'parent:{projectRoot}/**/*': { - contains: 'libs/parent/filea.ts|libs/parent/filea.spec.ts', - }, - }); + expect(test).toMatchSnapshot(); const build = await hasher.hashTask({ target: { project: 'parent', target: 'build' }, @@ -424,16 +356,11 @@ describe('TaskHasher', () => { overrides: { prop: 'prop-value' }, }); - assertFilesets(build, { - 'parent:!{projectRoot}/**/*.spec.ts': { - contains: 'libs/parent/filea.ts', - excludes: 'libs/parent/filea.spec.ts', - }, - }); + expect(build).toMatchSnapshot(); }); it('should be able to handle multiple filesets per project', async () => { - withEnvironmentVariables( + await withEnvironmentVariables( { MY_TEST_HASH_ENV: 'MY_TEST_HASH_ENV_VALUE' }, async () => { const hasher = new InProcessTaskHasher( @@ -484,6 +411,7 @@ describe('TaskHasher', () => { }, }, }, + externalNodes: {}, dependencies: { parent: [{ source: 'parent', target: 'child', type: 'static' }], }, @@ -513,7 +441,7 @@ describe('TaskHasher', () => { }, } as any, {}, - createFileHasher() + fileHasher ); const parentHash = await hasher.hashTask({ @@ -522,25 +450,7 @@ describe('TaskHasher', () => { overrides: { prop: 'prop-value' }, }); - assertFilesets(parentHash, { - 'child:!{projectRoot}/**/*.spec.ts': { - contains: 'libs/child/fileb.ts', - excludes: 'fileb.spec.ts', - }, - 'parent:{projectRoot}/**/*': { - contains: 'libs/parent/filea.ts|libs/parent/filea.spec.ts', - }, - }); - - expect(parentHash.details.nodes['{workspaceRoot}/global1']).toEqual( - 'global1.hash' - ); - expect(parentHash.details.nodes['{workspaceRoot}/global2']).toBe( - 'global2.hash' - ); - expect(parentHash.details.nodes['env:MY_TEST_HASH_ENV']).toEqual( - 'MY_TEST_HASH_ENV_VALUE' - ); + expect(parentHash).toMatchSnapshot(); const childHash = await hasher.hashTask({ target: { project: 'child', target: 'test' }, @@ -548,18 +458,7 @@ describe('TaskHasher', () => { overrides: { prop: 'prop-value' }, }); - assertFilesets(childHash, { - 'child:{projectRoot}/**/*': { - contains: 'libs/child/fileb.ts|libs/child/fileb.spec.ts', - }, - }); - expect(childHash.details.nodes['{workspaceRoot}/global1']).toEqual( - 'global1.hash' - ); - expect(childHash.details.nodes['{workspaceRoot}/global2']).toBe( - undefined - ); - expect(childHash.details.nodes['env:MY_TEST_HASH_ENV']).toBeUndefined(); + expect(childHash).toMatchSnapshot(); } ); }); @@ -632,7 +531,7 @@ describe('TaskHasher', () => { }, } as any, {}, - createFileHasher() + fileHasher ); const hash = await hasher.hashTask({ @@ -640,17 +539,7 @@ describe('TaskHasher', () => { id: 'parent-build', overrides: { prop: 'prop-value' }, }); - - assertFilesets(hash, { - 'child:!{projectRoot}/**/*.spec.ts': { - contains: 'libs/child/fileb.ts', - excludes: 'libs/child/fileb.spec.ts', - }, - 'parent:!{projectRoot}/**/*.spec.ts': { - contains: 'libs/parent/filea.ts', - excludes: 'libs/parent/filea.spec.ts', - }, - }); + expect(hash).toMatchSnapshot(); }); it('should be able to include only a part of the base tsconfig', async () => { @@ -691,7 +580,7 @@ describe('TaskHasher', () => { runtimeCacheInputs: ['echo runtime123', 'echo runtime456'], selectivelyHashTsConfig: true, }, - createFileHasher() + fileHasher ); const hash = await hasher.hashTask({ @@ -700,20 +589,7 @@ describe('TaskHasher', () => { overrides: { prop: 'prop-value' }, }); - expect(hash.value).toContain('file.hash'); //project files - expect(hash.value).toContain('prop-value'); //overrides - expect(hash.value).toContain('parent'); //project - expect(hash.value).toContain('build'); //target - expect(hash.value).toContain('runtime123'); //target - expect(hash.value).toContain('runtime456'); //target - - expect(hash.details.command).toEqual('parent|build||{"prop":"prop-value"}'); - - assertFilesets(hash, { - 'parent:{projectRoot}/**/*': { - contains: '/file', - }, - }); + expect(hash).toMatchSnapshot(); }); it('should hash tasks where the project graph has circular dependencies', async () => { @@ -768,7 +644,7 @@ describe('TaskHasher', () => { }, {} as any, {}, - createFileHasher() + fileHasher ); const tasksHash = await hasher.hashTask({ @@ -777,22 +653,7 @@ describe('TaskHasher', () => { overrides: { prop: 'prop-value' }, }); - expect(tasksHash.value).toContain('a.hash'); //project files - expect(tasksHash.value).toContain('b.hash'); //project files - expect(tasksHash.value).toContain('prop-value'); //overrides - expect(tasksHash.value).toContain('parent|build'); //project and target - expect(tasksHash.value).toContain('build'); //target - - assertFilesets(tasksHash, { - 'child:{projectRoot}/**/*': { - contains: 'fileb.ts', - excludes: 'filea.tx', - }, - 'parent:{projectRoot}/**/*': { - contains: 'filea.ts', - excludes: 'fileb.tx', - }, - }); + expect(tasksHash).toMatchSnapshot(); const hashb = await hasher.hashTask({ target: { project: 'child', target: 'build' }, @@ -800,22 +661,7 @@ describe('TaskHasher', () => { overrides: { prop: 'prop-value' }, }); - expect(hashb.value).toContain('a.hash'); //project files - expect(hashb.value).toContain('b.hash'); //project files - expect(hashb.value).toContain('prop-value'); //overrides - expect(hashb.value).toContain('child|build'); //project and target - expect(hashb.value).toContain('build'); //target - - assertFilesets(hashb, { - 'child:{projectRoot}/**/*': { - contains: 'fileb.ts', - excludes: 'filea.tx', - }, - 'parent:{projectRoot}/**/*': { - contains: 'filea.ts', - excludes: 'fileb.tx', - }, - }); + expect(hashb).toMatchSnapshot(); }); it('should throw an error when failed to execute runtimeCacheInputs', async () => { @@ -854,7 +700,7 @@ describe('TaskHasher', () => { { runtimeCacheInputs: ['boom'], }, - createFileHasher() + fileHasher ); try { @@ -920,7 +766,7 @@ describe('TaskHasher', () => { }, {} as any, {}, - createFileHasher() + fileHasher ); const hash = await hasher.hashTask({ @@ -928,11 +774,7 @@ describe('TaskHasher', () => { id: 'app-build', overrides: { prop: 'prop-value' }, }); - - // note that the parent hash is based on parent source files only! - assertFilesets(hash, { - 'npm:react': { contains: '17.0.0' }, - }); + expect(hash).toMatchSnapshot(); }); it('should hash missing dependent npm project versions', async () => { @@ -977,7 +819,7 @@ describe('TaskHasher', () => { }, {} as any, {}, - createFileHasher() + fileHasher ); const hash = await hasher.hashTask({ @@ -1042,11 +884,7 @@ describe('TaskHasher', () => { overrides: { prop: 'prop-value' }, }); - assertFilesets(hash, { - target: { contains: '@nx/webpack:webpack' }, - }); - - expect(hash.value).toContain('|16.0.0|'); + expect(hash).toMatchSnapshot(); }); it('should hash entire subtree of dependencies', async () => { @@ -1150,14 +988,7 @@ describe('TaskHasher', () => { overrides: { prop: 'prop-value' }, }); - assertFilesets(hash, { - target: { contains: '@nx/webpack:webpack' }, - }); - - expect(hash.value).toContain('|$nx/webpack16$|'); - expect(hash.value).toContain('|$nx/devkit16$|'); - expect(hash.value).toContain('|$nx16$|'); - expect(hash.value).toContain('|5.0.0|'); + expect(hash).toMatchSnapshot(); }); it('should hash entire subtree in a deterministic way', async () => { @@ -1353,8 +1184,7 @@ describe('TaskHasher', () => { overrides: { prop: 'prop-value' }, }); - expect(hash.value).not.toContain('|16.0.0|'); - expect(hash.details.nodes['target']).toEqual('nx:run-commands'); + expect(hash.details.nodes['target']).toEqual('13019111166724682201'); }); it('should use externalDependencies to override nx:run-commands', async () => { @@ -1430,10 +1260,7 @@ describe('TaskHasher', () => { overrides: { prop: 'prop-value' }, }); - expect(hash.value).not.toContain('|16.0.0|'); - expect(hash.value).toContain('|17.0.0|'); - expect(hash.value).toContain('|5.0.0|'); - expect(hash.details.nodes['target']).toEqual('nx:run-commands'); + expect(hash).toMatchSnapshot(); }); it('should use externalDependencies with empty array to ignore all deps', async () => { @@ -1509,21 +1336,12 @@ describe('TaskHasher', () => { overrides: { prop: 'prop-value' }, }); - expect(hash.details.nodes['npm:nx']).not.toBeDefined(); - expect(hash.details.nodes['app']).not.toBeDefined(); + expect(hash).toMatchSnapshot(); }); }); describe('dependentTasksOutputFiles', () => { it('should depend on dependent tasks output files', async () => { - const distFolder = [ - ['dist/libs/parent/filea.js', 'a.js.hash'], - ['dist/libs/parent/filea.d.ts', 'a.d.ts.hash'], - ['dist/libs/child/fileb.js', 'b.js.hash'], - ['dist/libs/child/fileb.d.ts', 'b.d.ts.hash'], - ['dist/libs/grandchild/filec.js', 'c.js.hash'], - ['dist/libs/grandchild/filec.d.ts', 'c.d.ts.hash'], - ]; const hasher = new InProcessTaskHasher( { parent: [ @@ -1567,10 +1385,6 @@ describe('TaskHasher', () => { dependsOn: ['^build'], inputs: ['prod', 'deps'], executor: 'nx:run-commands', - // options: { - // outputPath: 'dist/{projectRoot}', - // }, - // outputs: ['{options.outputPath}'], outputs: ['dist/{projectRoot}'], }, }, @@ -1592,6 +1406,7 @@ describe('TaskHasher', () => { }, }, }, + externalNodes: {}, dependencies: { parent: [{ source: 'parent', target: 'child', type: 'static' }], child: [{ source: 'child', target: 'grandchild', type: 'static' }], @@ -1641,39 +1456,153 @@ describe('TaskHasher', () => { }, } as any, {}, - { - hashFilesMatchingGlobs: (path: string, globs: string[]) => { - const hashes = []; - for (const [file, hash] of distFolder) { - if (!file.startsWith(path)) { - continue; - } - for (const glob of globs) { - if (file.endsWith(glob.split('**/*')[1])) { - hashes.push(hash); - } - } - } - return hashes.join('|'); - }, - } as any + fileHasher ); + await tempFs.createFiles({ + 'dist/libs/child/index.d.ts': '', + 'dist/libs/grandchild/index.d.ts': '', + }); + const hash = await hasher.hashTask({ target: { project: 'parent', target: 'build' }, id: 'parent-build', overrides: { prop: 'prop-value' }, }); - expect(hash.value).not.toContain('a.d.ts.hash'); - expect(hash.value).not.toContain('js.hash'); - expect(hash.value).toContain('b.d.ts.hash'); - expect(hash.value).toContain('c.d.ts.hash'); + expect(hash).toMatchSnapshot(); + }); + + it('should work with dependent tasks with globs as outputs', async () => { + const hasher = new InProcessTaskHasher( + { + parent: [ + { file: 'libs/parent/filea.ts', hash: 'a.hash' }, + { file: 'libs/parent/filea.spec.ts', hash: 'a.spec.hash' }, + ], + child: [ + { file: 'libs/child/fileb.ts', hash: 'b.hash' }, + { file: 'libs/child/fileb.spec.ts', hash: 'b.spec.hash' }, + ], + grandchild: [ + { file: 'libs/grandchild/filec.ts', hash: 'c.hash' }, + { file: 'libs/grandchild/filec.spec.ts', hash: 'c.spec.hash' }, + ], + }, + allWorkspaceFiles, + { + nodes: { + parent: { + name: 'parent', + type: 'lib', + data: { + root: 'libs/parent', + targets: { + build: { + dependsOn: ['^build'], + inputs: ['prod', 'deps'], + executor: 'nx:run-commands', + outputs: ['dist/{projectRoot}'], + }, + }, + }, + }, + child: { + name: 'child', + type: 'lib', + data: { + root: 'libs/child', + targets: { + build: { + dependsOn: ['^build'], + inputs: ['prod', 'deps'], + executor: 'nx:run-commands', + outputs: ['dist/{projectRoot}/**/*'], + }, + }, + }, + }, + grandchild: { + name: 'grandchild', + type: 'lib', + data: { + root: 'libs/grandchild', + targets: { + build: { + dependsOn: ['^build'], + inputs: ['prod', 'deps'], + executor: 'nx:run-commands', + outputs: ['dist/{projectRoot}'], + }, + }, + }, + }, + }, + externalNodes: {}, + dependencies: { + parent: [{ source: 'parent', target: 'child', type: 'static' }], + child: [{ source: 'child', target: 'grandchild', type: 'static' }], + }, + }, + { + roots: ['grandchild-build'], + tasks: { + 'parent-build': { + id: 'parent-build', + target: { project: 'parent', target: 'build' }, + overrides: {}, + }, + 'child-build': { + id: 'child-build', + target: { project: 'child', target: 'build' }, + overrides: {}, + }, + 'grandchild-build': { + id: 'grandchild-build', + target: { project: 'grandchild', target: 'build' }, + overrides: {}, + }, + }, + dependencies: { + 'parent-build': ['child-build'], + 'child-build': ['grandchild-build'], + }, + }, + { + namedInputs: { + prod: ['!{projectRoot}/**/*.spec.ts'], + deps: [ + { dependentTasksOutputFiles: '**/*.d.ts', transitive: true }, + ], + }, + targetDefaults: { + build: { + dependsOn: ['^build'], + inputs: ['prod', 'deps'], + executor: 'nx:run-commands', + options: { + outputPath: 'dist/libs/{projectRoot}', + }, + outputs: ['{options.outputPath}'], + }, + }, + } as any, + {}, + fileHasher + ); + + await tempFs.createFiles({ + 'dist/libs/child/index.d.ts': '', + 'dist/libs/grandchild/index.d.ts': '', + }); - assertFilesets(hash, { - 'dist/libs/child/**/*.d.ts': { contains: 'b.d.ts.hash' }, - 'dist/libs/grandchild/**/*.d.ts': { contains: 'c.d.ts.hash' }, + const hash = await hasher.hashTask({ + target: { project: 'parent', target: 'build' }, + id: 'parent-build', + overrides: { prop: 'prop-value' }, }); + + expect(hash).toMatchSnapshot(); }); }); diff --git a/packages/nx/src/hasher/task-hasher.ts b/packages/nx/src/hasher/task-hasher.ts index 9b3d5808bc1a7..acc8e5de56c7c 100644 --- a/packages/nx/src/hasher/task-hasher.ts +++ b/packages/nx/src/hasher/task-hasher.ts @@ -16,8 +16,10 @@ import { createProjectRootMappings } from '../project-graph/utils/find-project-f import { findMatchingProjects } from '../utils/find-matching-projects'; import { FileHasher, hashArray } from './file-hasher'; import { getOutputsForTargetAndConfiguration } from '../tasks-runner/utils'; -import { join } from 'path'; import { getHashEnv } from './set-hash-env'; +import { workspaceRoot } from '../utils/workspace-root'; +import { join, relative } from 'path'; +import { normalizePath } from '../utils/path'; type ExpandedSelfInput = | { fileset: string } @@ -282,8 +284,8 @@ class TaskHasherImpl { projectGraphDeps, visited ); - const depsOut = this.hashDepsOutputs(task, depsOutputs); - const projects = await this.hashProjectInputs(projectInputs, visited); + const depsOut = await this.hashDepsOutputs(task, depsOutputs); + const projects = await this.hashProjectInputs(projectInputs); let details = {}; for (const s of self) { @@ -350,27 +352,31 @@ class TaskHasherImpl { .filter((r) => !!r); } - private hashDepsOutputs( + private async hashDepsOutputs( task: Task, depsOutputs: ExpandedDepsOutput[] - ): PartialHash[] { + ): Promise { if (depsOutputs.length === 0) { return []; } const result: PartialHash[] = []; for (const { dependentTasksOutputFiles, transitive } of depsOutputs) { result.push( - ...this.hashDepOuputs(task, dependentTasksOutputFiles, transitive) + ...(await this.hashDepOuputs( + task, + dependentTasksOutputFiles, + transitive + )) ); } return result; } - private hashDepOuputs( + private async hashDepOuputs( task: Task, dependentTasksOutputFiles: string, transitive?: boolean - ): PartialHash[] { + ): Promise { // task has no dependencies if (!this.taskGraph.dependencies[task.id]) { return []; @@ -379,29 +385,38 @@ class TaskHasherImpl { const partialHashes: PartialHash[] = []; for (const d of this.taskGraph.dependencies[task.id]) { const childTask = this.taskGraph.tasks[d]; - const outputDirs = getOutputsForTargetAndConfiguration( + const outputs = getOutputsForTargetAndConfiguration( childTask, this.projectGraph.nodes[childTask.target.project] ); - const hashes = {}; - for (const outputDir of outputDirs) { - hashes[join(outputDir, dependentTasksOutputFiles)] = - this.fileHasher.hashFilesMatchingGlobs(outputDir, [ - dependentTasksOutputFiles, - ]); + const { getFilesForOutputs } = + require('../native') as typeof import('../native'); + const outputFiles = getFilesForOutputs(workspaceRoot, outputs); + const filteredFiles = outputFiles.filter( + (p) => + p === dependentTasksOutputFiles || + minimatch(p, dependentTasksOutputFiles) + ); + const hashDetails = {}; + const hashes: string[] = []; + for (const [file, hash] of await this.fileHasher.hashFiles( + filteredFiles.map((p) => join(workspaceRoot, p)) + )) { + hashes.push(hash); + hashDetails[normalizePath(relative(workspaceRoot, file))] = hash; } partialHashes.push({ - value: hashArray(Object.values(hashes)), - details: hashes, + value: hashArray(hashes), + details: hashDetails, }); if (transitive) { partialHashes.push( - ...this.hashDepOuputs( + ...(await this.hashDepOuputs( childTask, dependentTasksOutputFiles, transitive - ) + )) ); } } @@ -521,7 +536,7 @@ class TaskHasherImpl { return { value: hash, details: { - target: target.executor, + target: hash, }, }; } @@ -588,6 +603,8 @@ class TaskHasherImpl { const notFilesets = inputs.filter((r) => !r['fileset']); return Promise.all([ this.hashProjectFileset(projectName, projectFilesets), + this.hashProjectConfig(projectName), + this.hashTsConfig(projectName), ...[ ...workspaceFilesets, ...this.legacyFilesetInputs.map((r) => r.fileset), @@ -599,8 +616,7 @@ class TaskHasherImpl { } private async hashProjectInputs( - projectInputs: { input: string; projects: string[] }[], - visited: string[] + projectInputs: { input: string; projects: string[] }[] ): Promise { const partialHashes: Promise[] = []; for (const input of projectInputs) { @@ -653,6 +669,33 @@ class TaskHasherImpl { return this.filesetHashes[mapKey]; } + private hashProjectConfig(projectName: string): PartialHash { + const p = this.projectGraph.nodes[projectName]; + const projectConfig = hashArray([ + JSON.stringify({ ...p.data, files: undefined }), + ]); + + return { + value: projectConfig, + details: { + ProjectConfiguration: projectConfig, + }, + }; + } + + private hashTsConfig(projectName: string): PartialHash { + const p = this.projectGraph.nodes[projectName]; + const tsConfig = hashArray([ + hashTsConfig(p, this.projectRootMappings, this.options), + ]); + return { + value: tsConfig, + details: { + TsConfig: tsConfig, + }, + }; + } + private async hashProjectFileset( projectName: string, filesetPatterns: string[] @@ -666,15 +709,12 @@ class TaskHasherImpl { this.projectFileMap[projectName] || [], filesetPatterns ); - const fileNames = filteredFiles.map((f) => f.file); - const values = filteredFiles.map((f) => f.hash); - - const value = hashArray([ - ...fileNames, - ...values, - JSON.stringify({ ...p.data, files: undefined }), - hashTsConfig(p, this.projectRootMappings, this.options), - ]); + const files: string[] = []; + for (const { file, hash } of filteredFiles) { + files.push(file, hash); + } + + const value = hashArray(files); res({ value, details: { [mapKey]: value }, diff --git a/packages/nx/src/native/cache/expand_outputs.rs b/packages/nx/src/native/cache/expand_outputs.rs index e203bdf44c80a..dda9e75b81473 100644 --- a/packages/nx/src/native/cache/expand_outputs.rs +++ b/packages/nx/src/native/cache/expand_outputs.rs @@ -5,8 +5,8 @@ use crate::native::utils::path::Normalize; use crate::native::walker::nx_walker_sync; #[napi] -/// Expands the given entries into a list of existing files. -/// First checks if the entry exists, if not, it will glob the working directory to find the file. +/// Expands the given entries into a list of existing directories and files. +/// This is used for copying outputs to and from the cache pub fn expand_outputs(directory: String, entries: Vec) -> anyhow::Result> { let directory: PathBuf = directory.into(); @@ -33,6 +33,67 @@ pub fn expand_outputs(directory: String, entries: Vec) -> anyhow::Result Ok(found_paths.collect()) } +#[napi] +/// Expands the given outputs into a list of existing files. +/// This is used when hashing outputs +pub fn get_files_for_outputs( + directory: String, + entries: Vec, +) -> anyhow::Result> { + let directory: PathBuf = directory.into(); + + let mut globs: Vec = vec![]; + let mut files: Vec = vec![]; + let mut directories: Vec = vec![]; + for entry in entries.into_iter() { + let path = directory.join(&entry); + + if !path.exists() { + globs.push(entry); + } else if path.is_dir() { + directories.push(entry); + } else { + files.push(entry); + } + } + + if !globs.is_empty() { + let glob_set = build_glob_set(&globs)?; + let found_paths = nx_walker_sync(&directory).filter_map(|path| { + if glob_set.is_match(&path) { + Some(path.to_normalized_string()) + } else { + None + } + }); + + files.extend(found_paths); + } + + if !directories.is_empty() { + for dir in directories { + let dir = PathBuf::from(dir); + let dir_path = directory.join(&dir); + let files_in_dir: Vec = nx_walker_sync(&dir_path) + .filter_map(|e| { + let path = dir_path.join(&e); + + if path.is_file() { + Some(dir.join(e).to_normalized_string()) + } else { + None + } + }) + .collect(); + files.extend(files_in_dir); + } + } + + files.sort(); + + Ok(files) +} + #[cfg(test)] mod test { use super::*; diff --git a/packages/nx/src/native/hasher.rs b/packages/nx/src/native/hasher.rs index 911deb54250c4..2e8dfd64fa67d 100644 --- a/packages/nx/src/native/hasher.rs +++ b/packages/nx/src/native/hasher.rs @@ -1,8 +1,6 @@ use crate::native::types::FileData; -use crate::native::utils::glob::build_glob_set; use crate::native::utils::path::Normalize; use crate::native::walker::nx_walker; -use rayon::prelude::*; use std::collections::HashMap; use xxhash_rust::xxh3; @@ -38,38 +36,6 @@ pub fn hash_files(workspace_root: String) -> HashMap { }) } -#[napi] -fn hash_files_matching_globs( - directory: String, - glob_patterns: Vec, -) -> anyhow::Result> { - let glob_set = build_glob_set(&glob_patterns)?; - - let mut hashes = nx_walker(directory, move |receiver| { - let mut collection: Vec = Vec::new(); - for (path, content) in receiver { - if glob_set.is_match(&path) { - collection.push(FileData { - file: path.to_normalized_string(), - hash: xxh3::xxh3_64(&content).to_string(), - }); - } - } - collection - }); - - if hashes.is_empty() { - return Ok(None); - } - - // Sort the file data so that its in deterministically ordered by file path - hashes.par_sort(); - - let sorted_file_hashes: Vec = - hashes.into_iter().map(|file_data| file_data.hash).collect(); - Ok(Some(hash_array(sorted_file_hashes))) -} - #[cfg(test)] mod tests { use super::*; @@ -108,23 +74,4 @@ mod tests { assert_eq!(content.unwrap().hash, "6193209363630369380"); } - - #[test] - fn it_hashes_files_matching_globs() -> anyhow::Result<()> { - // handle empty workspaces - let content = - hash_files_matching_globs("/does/not/exist".into(), Vec::from([String::from("**/*")]))?; - assert!(content.is_none()); - - let temp_dir = setup_fs(); - - let content = hash_files_matching_globs( - temp_dir.display().to_string(), - Vec::from([String::from("fo*.txt")]), - )?; - // println!("{:?}", content); - assert_eq!(content.unwrap(), String::from("12742692716897613184"),); - - Ok(()) - } } diff --git a/packages/nx/src/native/index.d.ts b/packages/nx/src/native/index.d.ts index b78cd8bdd8375..7f411fd70bdb3 100644 --- a/packages/nx/src/native/index.d.ts +++ b/packages/nx/src/native/index.d.ts @@ -4,16 +4,20 @@ /* auto-generated by NAPI-RS */ /** - * Expands the given entries into a list of existing files. - * First checks if the entry exists, if not, it will glob the working directory to find the file. + * Expands the given entries into a list of existing directories and files. + * This is used for copying outputs to and from the cache */ export function expandOutputs(directory: string, entries: Array): Array +/** + * Expands the given outputs into a list of existing files. + * This is used when hashing outputs + */ +export function getFilesForOutputs(directory: string, entries: Array): Array export function remove(src: string): void export function copy(src: string, dest: string): void export function hashArray(input: Array): string export function hashFile(file: string): FileData | null export function hashFiles(workspaceRoot: string): Record -export function hashFilesMatchingGlobs(directory: string, globPatterns: Array): string | null export function findImports(projectFileMap: Record>): Array export interface FileData { file: string diff --git a/packages/nx/src/native/index.js b/packages/nx/src/native/index.js index d8b0d85111585..3c4d65f64eba1 100644 --- a/packages/nx/src/native/index.js +++ b/packages/nx/src/native/index.js @@ -246,15 +246,15 @@ if (!nativeBinding) { throw new Error(`Failed to load native binding`) } -const { expandOutputs, remove, copy, hashArray, hashFile, hashFiles, hashFilesMatchingGlobs, ImportResult, findImports, EventType, Watcher, WorkspaceErrors, getProjectConfigurationFiles, getProjectConfigurations, getWorkspaceFilesNative } = nativeBinding +const { expandOutputs, getFilesForOutputs, remove, copy, hashArray, hashFile, hashFiles, ImportResult, findImports, EventType, Watcher, WorkspaceErrors, getProjectConfigurationFiles, getProjectConfigurations, getWorkspaceFilesNative } = nativeBinding module.exports.expandOutputs = expandOutputs +module.exports.getFilesForOutputs = getFilesForOutputs module.exports.remove = remove module.exports.copy = copy module.exports.hashArray = hashArray module.exports.hashFile = hashFile module.exports.hashFiles = hashFiles -module.exports.hashFilesMatchingGlobs = hashFilesMatchingGlobs module.exports.ImportResult = ImportResult module.exports.findImports = findImports module.exports.EventType = EventType diff --git a/packages/nx/src/native/utils/glob.rs b/packages/nx/src/native/utils/glob.rs index 9038ebf54edb1..ebdaae94b3715 100644 --- a/packages/nx/src/native/utils/glob.rs +++ b/packages/nx/src/native/utils/glob.rs @@ -155,6 +155,12 @@ mod test { assert_eq!(no_patterns, ["dist/**/*.js",]); } + #[test] + fn should_work_with_simple_globs() { + let glob_set = build_glob_set(&["**/*"]).unwrap(); + assert!(glob_set.is_match("packages/nx/package.json")) + } + #[test] fn should_detect_package_json() { let glob_set = build_glob_set(&["packages/*/package.json"]).unwrap(); diff --git a/packages/nx/src/plugins/js/hasher/hasher.ts b/packages/nx/src/plugins/js/hasher/hasher.ts index 3d443290280fc..57f03aa939d86 100644 --- a/packages/nx/src/plugins/js/hasher/hasher.ts +++ b/packages/nx/src/plugins/js/hasher/hasher.ts @@ -1,6 +1,6 @@ import { ProjectGraphProjectNode } from '../../../config/project-graph'; import { readJsonFile } from '../../../utils/fileutils'; -import { getRootTsConfigFileName } from '../utils/typescript'; +import { getRootTsConfigPath } from '../utils/typescript'; import { findProjectForPath, ProjectRootMappings, @@ -16,7 +16,7 @@ interface TsconfigJsonConfiguration { function readTsConfigJson(): TsconfigJsonConfiguration { try { - const res = readJsonFile(getRootTsConfigFileName()); + const res = readJsonFile(getRootTsConfigPath()); res.compilerOptions.paths ??= {}; return res; } catch { diff --git a/packages/nx/src/utils/workspace-root.ts b/packages/nx/src/utils/workspace-root.ts index 7646a3af8e8b4..2395679f278a8 100644 --- a/packages/nx/src/utils/workspace-root.ts +++ b/packages/nx/src/utils/workspace-root.ts @@ -6,10 +6,6 @@ import { fileExists } from './fileutils'; */ export let workspaceRoot = workspaceRootInner(process.cwd(), process.cwd()); -export function setWorkspaceRoot(root: string): void { - workspaceRoot = root; -} - export function workspaceRootInner( dir: string, candidateRoot: string | null From 4a541418bbc62f4eed0d0ca3c316b6b2d814830c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Jona=C5=A1?= Date: Thu, 27 Jul 2023 20:39:26 +0200 Subject: [PATCH 190/262] fix(repo): fix silent yarn run on e2e for berry (#18340) --- e2e/utils/command-utils.ts | 6 ++++-- e2e/utils/get-env-info.ts | 16 ++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/e2e/utils/command-utils.ts b/e2e/utils/command-utils.ts index 3e609435b2513..f87350f610353 100644 --- a/e2e/utils/command-utils.ts +++ b/e2e/utils/command-utils.ts @@ -6,6 +6,7 @@ import { getNpmMajorVersion, getPublishedVersion, getStrippedEnvironmentVariables, + getYarnMajorVersion, isVerboseE2ERun, } from './get-env-info'; import { TargetConfiguration } from '@nx/devkit'; @@ -119,6 +120,7 @@ export function getPackageManagerCommand({ runLerna: string; } { const npmMajorVersion = getNpmMajorVersion(); + const yarnMajorVersion = getYarnMajorVersion(path); const publishedVersion = getPublishedVersion(); const isYarnWorkspace = fileExists(join(path, 'package.json')) ? readJson('package.json').workspaces @@ -147,14 +149,14 @@ export function getPackageManagerCommand({ } create-nx-workspace@${publishedVersion}`, run: (script: string, args: string) => `yarn ${script} ${args}`, runNx: `yarn nx`, - runNxSilent: `yarn --silent nx`, + runNxSilent: +yarnMajorVersion >= 2 ? 'yarn nx' : `yarn --silent nx`, runUninstalledPackage: 'npx --yes', install: 'yarn', ciInstall: 'yarn --frozen-lockfile', addProd: isYarnWorkspace ? 'yarn add -W' : 'yarn add', addDev: isYarnWorkspace ? 'yarn add -DW' : 'yarn add -D', list: 'yarn list --pattern', - runLerna: `yarn --silent lerna`, + runLerna: +yarnMajorVersion >= 2 ? 'yarn lerna' : `yarn --silent lerna`, }, // Pnpm 3.5+ adds nx to pnpm: { diff --git a/e2e/utils/get-env-info.ts b/e2e/utils/get-env-info.ts index a46ece3043f34..da3fc57361cbe 100644 --- a/e2e/utils/get-env-info.ts +++ b/e2e/utils/get-env-info.ts @@ -73,6 +73,22 @@ export function getNpmMajorVersion(): string { return npmMajorVersion; } +export function getYarnMajorVersion(path: string): string { + try { + // this fails if path is not yet created + const [yarnMajorVersion] = execSync(`yarn -v`, { + cwd: path, + encoding: 'utf-8', + }).split('.'); + return yarnMajorVersion; + } catch { + const [yarnMajorVersion] = execSync(`yarn -v`, { encoding: 'utf-8' }).split( + '.' + ); + return yarnMajorVersion; + } +} + export function getLatestLernaVersion(): string { const lernaVersion = execSync(`npm view lerna version`, { encoding: 'utf-8', From b25d5b06371d6bd5baf1a4e3f18416328c19974f Mon Sep 17 00:00:00 2001 From: Jason Jean Date: Thu, 27 Jul 2023 17:45:09 -0400 Subject: [PATCH 191/262] fix(core): deterministically hash external nodes (#18354) --- .../__snapshots__/task-hasher.spec.ts.snap | 64 ++++--- packages/nx/src/hasher/task-hasher.spec.ts | 154 +++++++++++++--- packages/nx/src/hasher/task-hasher.ts | 164 +++++++++--------- 3 files changed, 256 insertions(+), 126 deletions(-) diff --git a/packages/nx/src/hasher/__snapshots__/task-hasher.spec.ts.snap b/packages/nx/src/hasher/__snapshots__/task-hasher.spec.ts.snap index d3702d19e0b55..d7519823406ff 100644 --- a/packages/nx/src/hasher/__snapshots__/task-hasher.spec.ts.snap +++ b/packages/nx/src/hasher/__snapshots__/task-hasher.spec.ts.snap @@ -6,12 +6,12 @@ exports[`TaskHasher dependentTasksOutputFiles should depend on dependent tasks o "command": "4062279404379299270", "implicitDeps": {}, "nodes": { + "AllExternalDependencies": "1389868326933519382", "ProjectConfiguration": "12802727827024321009", "TsConfig": "8767608672024750088", "dist/libs/child/index.d.ts": "3244421341483603138", "dist/libs/grandchild/index.d.ts": "3244421341483603138", "parent:!{projectRoot}/**/*.spec.ts": "17962802443644575456", - "target": "1389868326933519382", "{workspaceRoot}/.gitignore": "3244421341483603138", "{workspaceRoot}/.nxignore": "3244421341483603138", "{workspaceRoot}/nx.json": "8942239360311677987", @@ -28,12 +28,12 @@ exports[`TaskHasher dependentTasksOutputFiles should work with dependent tasks w "command": "4062279404379299270", "implicitDeps": {}, "nodes": { + "AllExternalDependencies": "1389868326933519382", "ProjectConfiguration": "12802727827024321009", "TsConfig": "8767608672024750088", "dist/libs/child/index.d.ts": "3244421341483603138", "dist/libs/grandchild/index.d.ts": "3244421341483603138", "parent:!{projectRoot}/**/*.spec.ts": "17962802443644575456", - "target": "1389868326933519382", "{workspaceRoot}/.gitignore": "3244421341483603138", "{workspaceRoot}/.nxignore": "3244421341483603138", "{workspaceRoot}/nx.json": "8942239360311677987", @@ -53,14 +53,17 @@ exports[`TaskHasher hashTarget should hash entire subtree of dependencies 1`] = "ProjectConfiguration": "12026883044296863450", "TsConfig": "8767608672024750088", "app:{projectRoot}/**/*": "3244421341483603138", - "target": "3789300870433976270", + "npm:@nx/devkit": "$nx/devkit16$", + "npm:@nx/webpack": "$nx/webpack16$", + "npm:nx": "$nx16$", + "npm:webpack": "5.0.0", "{workspaceRoot}/.gitignore": "3244421341483603138", "{workspaceRoot}/.nxignore": "3244421341483603138", "{workspaceRoot}/nx.json": "8942239360311677987", }, "runtime": {}, }, - "value": "11829832011053499600", + "value": "17607022607820563118", } `; @@ -73,7 +76,7 @@ exports[`TaskHasher hashTarget should hash executor dependencies of @nx packages "ProjectConfiguration": "12026883044296863450", "TsConfig": "8767608672024750088", "app:{projectRoot}/**/*": "3244421341483603138", - "target": "1274004356858584726", + "npm:@nx/webpack": "16.0.0", "{workspaceRoot}/.gitignore": "3244421341483603138", "{workspaceRoot}/.nxignore": "3244421341483603138", "{workspaceRoot}/nx.json": "8942239360311677987", @@ -94,7 +97,8 @@ exports[`TaskHasher hashTarget should use externalDependencies to override nx:ru "TsConfig": "8767608672024750088", "app:{projectRoot}/**/*": "3244421341483603138", "env:undefined": "3244421341483603138", - "target": "7688798210438770308", + "npm:react": "17.0.0", + "npm:webpack": "5.0.0", "{workspaceRoot}/.gitignore": "3244421341483603138", "{workspaceRoot}/.nxignore": "3244421341483603138", "{workspaceRoot}/nx.json": "8942239360311677987", @@ -115,7 +119,6 @@ exports[`TaskHasher hashTarget should use externalDependencies with empty array "TsConfig": "8767608672024750088", "app:{projectRoot}/**/*": "3244421341483603138", "env:undefined": "3244421341483603138", - "target": "3244421341483603138", "{workspaceRoot}/.gitignore": "3244421341483603138", "{workspaceRoot}/.nxignore": "3244421341483603138", "{workspaceRoot}/nx.json": "8942239360311677987", @@ -132,12 +135,12 @@ exports[`TaskHasher should be able to handle multiple filesets per project 1`] = "command": "13785966310271077209", "implicitDeps": {}, "nodes": { + "AllExternalDependencies": "1389868326933519382", "ProjectConfiguration": "17211930887387929067", "TsConfig": "8767608672024750088", "child:!{projectRoot}/**/*.spec.ts": "17508782620731849000", "env:MY_TEST_HASH_ENV": "17357374746554314488", "parent:{projectRoot}/**/*": "7263479247245830838", - "target": "1389868326933519382", "{workspaceRoot}/.gitignore": "3244421341483603138", "{workspaceRoot}/.nxignore": "3244421341483603138", "{workspaceRoot}/global1": "3052102066027208710", @@ -156,10 +159,10 @@ exports[`TaskHasher should be able to handle multiple filesets per project 2`] = "command": "6958627266354933907", "implicitDeps": {}, "nodes": { + "AllExternalDependencies": "1389868326933519382", "ProjectConfiguration": "17211930887387929067", "TsConfig": "8767608672024750088", "child:{projectRoot}/**/*": "2300207741412661544", - "target": "1389868326933519382", "{workspaceRoot}/.gitignore": "3244421341483603138", "{workspaceRoot}/.nxignore": "3244421341483603138", "{workspaceRoot}/global1": "3052102066027208710", @@ -177,12 +180,12 @@ exports[`TaskHasher should be able to include only a part of the base tsconfig 1 "command": "4062279404379299270", "implicitDeps": {}, "nodes": { + "AllExternalDependencies": "1389868326933519382", "ProjectConfiguration": "18166168584521190546", "TsConfig": "4035819825874039301", "parent:{projectRoot}/**/*": "8263681721738113012", "runtime:echo runtime123": "runtime123", "runtime:echo runtime456": "runtime456", - "target": "1389868326933519382", "{workspaceRoot}/.gitignore": "3244421341483603138", "{workspaceRoot}/.nxignore": "3244421341483603138", "{workspaceRoot}/nx.json": "8942239360311677987", @@ -199,6 +202,7 @@ exports[`TaskHasher should create task hash 1`] = ` "command": "4062279404379299270", "implicitDeps": {}, "nodes": { + "AllExternalDependencies": "1389868326933519382", "ProjectConfiguration": "4875698716044094030", "TsConfig": "8767608672024750088", "env:NONEXISTENTENV": "3244421341483603138", @@ -207,7 +211,6 @@ exports[`TaskHasher should create task hash 1`] = ` "runtime:echo runtime123": "runtime123", "runtime:echo runtime456": "runtime456", "tagged:{projectRoot}/**/*": "3244421341483603138", - "target": "1389868326933519382", "unrelated:{projectRoot}/**/*": "10091615118977982257", "{workspaceRoot}/.gitignore": "3244421341483603138", "{workspaceRoot}/.nxignore": "3244421341483603138", @@ -219,16 +222,37 @@ exports[`TaskHasher should create task hash 1`] = ` } `; +exports[`TaskHasher should hash missing dependent npm project versions 1`] = ` +{ + "details": { + "command": "14389236043839781668", + "implicitDeps": {}, + "nodes": { + "AllExternalDependencies": "14358315432887000841", + "ProjectConfiguration": "8128657069648957137", + "TsConfig": "8767608672024750088", + "app:{projectRoot}/**/*": "9104199730100321982", + "npm:react": "17.0.0", + "{workspaceRoot}/.gitignore": "3244421341483603138", + "{workspaceRoot}/.nxignore": "3244421341483603138", + "{workspaceRoot}/nx.json": "8942239360311677987", + }, + "runtime": {}, + }, + "value": "3668827038634092448", +} +`; + exports[`TaskHasher should hash multiple filesets of a project 1`] = ` { "details": { "command": "13785966310271077209", "implicitDeps": {}, "nodes": { + "AllExternalDependencies": "1389868326933519382", "ProjectConfiguration": "10499856664466672714", "TsConfig": "8767608672024750088", "parent:{projectRoot}/**/*": "7263479247245830838", - "target": "1389868326933519382", "{workspaceRoot}/.gitignore": "3244421341483603138", "{workspaceRoot}/.nxignore": "3244421341483603138", "{workspaceRoot}/nx.json": "8942239360311677987", @@ -245,10 +269,10 @@ exports[`TaskHasher should hash multiple filesets of a project 2`] = ` "command": "4062279404379299270", "implicitDeps": {}, "nodes": { + "AllExternalDependencies": "1389868326933519382", "ProjectConfiguration": "10499856664466672714", "TsConfig": "8767608672024750088", "parent:!{projectRoot}/**/*.spec.ts": "17962802443644575456", - "target": "1389868326933519382", "{workspaceRoot}/.gitignore": "3244421341483603138", "{workspaceRoot}/.nxignore": "3244421341483603138", "{workspaceRoot}/nx.json": "8942239360311677987", @@ -265,11 +289,11 @@ exports[`TaskHasher should hash non-default filesets 1`] = ` "command": "4062279404379299270", "implicitDeps": {}, "nodes": { + "AllExternalDependencies": "1389868326933519382", "ProjectConfiguration": "8196293273405506196", "TsConfig": "8767608672024750088", "child:{projectRoot}/**/*": "2300207741412661544", "parent:!{projectRoot}/**/*.spec.ts": "17962802443644575456", - "target": "1389868326933519382", "{workspaceRoot}/.gitignore": "3244421341483603138", "{workspaceRoot}/.nxignore": "3244421341483603138", "{workspaceRoot}/nx.json": "8942239360311677987", @@ -286,11 +310,11 @@ exports[`TaskHasher should hash npm project versions 1`] = ` "command": "14389236043839781668", "implicitDeps": {}, "nodes": { + "AllExternalDependencies": "14358315432887000841", "ProjectConfiguration": "8128657069648957137", "TsConfig": "8767608672024750088", "app:{projectRoot}/**/*": "9104199730100321982", - "npm:react": "4468841026152585217", - "target": "14358315432887000841", + "npm:react": "17.0.0", "{workspaceRoot}/.gitignore": "3244421341483603138", "{workspaceRoot}/.nxignore": "3244421341483603138", "{workspaceRoot}/nx.json": "8942239360311677987", @@ -307,11 +331,11 @@ exports[`TaskHasher should hash task where the project has dependencies 1`] = ` "command": "4062279404379299270", "implicitDeps": {}, "nodes": { + "AllExternalDependencies": "1389868326933519382", "ProjectConfiguration": "8876282510060012181", "TsConfig": "8767608672024750088", "child:{projectRoot}/**/*": "5484012818475684626", "parent:{projectRoot}/**/*": "14822394489351823627", - "target": "1389868326933519382", "{workspaceRoot}/.gitignore": "3244421341483603138", "{workspaceRoot}/.nxignore": "3244421341483603138", "{workspaceRoot}/nx.json": "8942239360311677987", @@ -328,11 +352,11 @@ exports[`TaskHasher should hash tasks where the project graph has circular depen "command": "4062279404379299270", "implicitDeps": {}, "nodes": { + "AllExternalDependencies": "1389868326933519382", "ProjectConfiguration": "9892649345820140726", "TsConfig": "8767608672024750088", "child:{projectRoot}/**/*": "8973015561538144423", "parent:{projectRoot}/**/*": "9104199730100321982", - "target": "1389868326933519382", "{workspaceRoot}/.gitignore": "3244421341483603138", "{workspaceRoot}/.nxignore": "3244421341483603138", "{workspaceRoot}/nx.json": "8942239360311677987", @@ -349,11 +373,11 @@ exports[`TaskHasher should hash tasks where the project graph has circular depen "command": "7833005669885463868", "implicitDeps": {}, "nodes": { + "AllExternalDependencies": "1389868326933519382", "ProjectConfiguration": "18166168584521190546", "TsConfig": "8767608672024750088", "child:{projectRoot}/**/*": "8973015561538144423", "parent:{projectRoot}/**/*": "9104199730100321982", - "target": "1389868326933519382", "{workspaceRoot}/.gitignore": "3244421341483603138", "{workspaceRoot}/.nxignore": "3244421341483603138", "{workspaceRoot}/nx.json": "8942239360311677987", @@ -370,11 +394,11 @@ exports[`TaskHasher should use targetDefaults from nx.json 1`] = ` "command": "4062279404379299270", "implicitDeps": {}, "nodes": { + "AllExternalDependencies": "1389868326933519382", "ProjectConfiguration": "9892649345820140726", "TsConfig": "8767608672024750088", "child:!{projectRoot}/**/*.spec.ts": "17508782620731849000", "parent:!{projectRoot}/**/*.spec.ts": "17962802443644575456", - "target": "1389868326933519382", "{workspaceRoot}/.gitignore": "3244421341483603138", "{workspaceRoot}/.nxignore": "3244421341483603138", "{workspaceRoot}/nx.json": "8942239360311677987", diff --git a/packages/nx/src/hasher/task-hasher.spec.ts b/packages/nx/src/hasher/task-hasher.spec.ts index 802f2403d3b7b..1428ffaaeeb18 100644 --- a/packages/nx/src/hasher/task-hasher.spec.ts +++ b/packages/nx/src/hasher/task-hasher.spec.ts @@ -681,6 +681,7 @@ describe('TaskHasher', () => { }, }, }, + externalNodes: {}, dependencies: { parent: [], }, @@ -794,7 +795,16 @@ describe('TaskHasher', () => { }, }, }, - externalNodes: {}, + externalNodes: { + 'npm:react': { + name: 'npm:react', + type: 'npm', + data: { + version: '17.0.0', + packageName: 'react', + }, + }, + }, dependencies: { 'npm:react': [], app: [ @@ -829,9 +839,7 @@ describe('TaskHasher', () => { }); // note that the parent hash is based on parent source files only! - assertFilesets(hash, { - 'npm:react': { contains: '__npm:react__' }, - }); + expect(hash).toMatchSnapshot(); }); describe('hashTarget', () => { @@ -887,6 +895,113 @@ describe('TaskHasher', () => { expect(hash).toMatchSnapshot(); }); + it('should hash entire subtree of dependencies deterministically', async () => { + function createHasher() { + return new InProcessTaskHasher( + { + a: [{ file: 'a/filea.ts', hash: 'a.hash' }], + b: [{ file: 'b/fileb.ts', hash: 'b.hash' }], + }, + allWorkspaceFiles, + { + nodes: { + a: { + name: 'a', + type: 'lib', + data: { + root: 'a', + targets: { build: { executor: '@nx/webpack:webpack' } }, + }, + }, + b: { + name: 'b', + type: 'lib', + data: { + root: 'b', + targets: { build: { executor: '@nx/webpack:webpack' } }, + }, + }, + }, + externalNodes: { + 'npm:@nx/webpack': { + name: 'npm:@nx/webpack', + type: 'npm', + data: { + packageName: '@nx/webpack', + version: '16.0.0', + hash: '$nx/webpack16$', + }, + }, + }, + dependencies: { + a: [ + { + source: 'a', + target: 'b', + type: DependencyType.static, + }, + ], + b: [ + { + source: 'b', + target: 'a', + type: DependencyType.static, + }, + ], + 'npm:@nx/webpack': [], + }, + }, + { + roots: [], + tasks: { + 'a-build': { + id: 'a-build', + target: { project: 'a', target: 'build' }, + overrides: {}, + }, + 'b-build': { + id: 'b-build', + target: { project: 'b', target: 'build' }, + overrides: {}, + }, + }, + dependencies: {}, + }, + {} as any, + {}, + fileHasher + ); + } + + const hasher1 = createHasher(); + const hasher2 = createHasher(); + + const hashA1 = hasher1.hashTask({ + id: 'a-build', + target: { project: 'a', target: 'build' }, + overrides: {}, + }); + const hashB1 = hasher1.hashTask({ + id: 'b-build', + target: { project: 'b', target: 'build' }, + overrides: {}, + }); + + const hashB2 = hasher2.hashTask({ + id: 'b-build', + target: { project: 'b', target: 'build' }, + overrides: {}, + }); + const hashA2 = hasher2.hashTask({ + id: 'a-build', + target: { project: 'a', target: 'build' }, + overrides: {}, + }); + + expect(hashA1).toEqual(hashA2); + expect(hashB1).toEqual(hashB2); + }); + it('should hash entire subtree of dependencies', async () => { const hasher = new InProcessTaskHasher( {}, @@ -1043,6 +1158,15 @@ describe('TaskHasher', () => { hash: '$packageC0.0.0$', }, }, + 'npm:@nx/webpack': { + name: 'npm:@nx/webpack', + type: 'npm', + data: { + packageName: '@nx/webpack', + version: '0.0.0', + hash: '$@nx/webpack0.0.0$', + }, + }, }, dependencies: { appA: [ @@ -1184,7 +1308,9 @@ describe('TaskHasher', () => { overrides: { prop: 'prop-value' }, }); - expect(hash.details.nodes['target']).toEqual('13019111166724682201'); + expect(hash.details.nodes['AllExternalDependencies']).toEqual( + '13019111166724682201' + ); }); it('should use externalDependencies to override nx:run-commands', async () => { @@ -1716,21 +1842,3 @@ describe('TaskHasher', () => { }); }); }); - -function assertFilesets( - hash: Hash, - assertions: { [name: string]: { contains?: string; excludes?: string } } -) { - const nodes = hash.details.nodes; - for (let k of Object.keys(assertions)) { - expect(nodes[k]).toBeDefined(); - if (assertions[k].contains) { - expect(nodes[k]).toContain(assertions[k].contains); - } - if (assertions[k].excludes) { - expect(nodes[k]).not.toContain(assertions[k].excludes); - } - } -} - -//{ [name: string]: string } diff --git a/packages/nx/src/hasher/task-hasher.ts b/packages/nx/src/hasher/task-hasher.ts index acc8e5de56c7c..45c5a0a7f0284 100644 --- a/packages/nx/src/hasher/task-hasher.ts +++ b/packages/nx/src/hasher/task-hasher.ts @@ -186,7 +186,11 @@ class TaskHasherImpl { private runtimeHashes: { [runtime: string]: Promise; } = {}; - private externalDepsHashCache: { [packageName: string]: string } = {}; + private externalDependencyHashes: Map = new Map< + string, + PartialHash + >(); + private allExternalDependenciesHash: PartialHash; private projectRootMappings = createProjectRootMappings( this.projectGraph.nodes ); @@ -201,7 +205,10 @@ class TaskHasherImpl { private readonly taskGraph: TaskGraph, private readonly fileHasher: FileHasher, private readonly options: { selectivelyHashTsConfig: boolean } - ) {} + ) { + // External Dependencies are all calculated up front in a deterministic order + this.calculateExternalDependencyHashes(); + } async hashTask(task: Task, visited: string[]): Promise { return Promise.resolve().then(async () => { @@ -227,10 +234,7 @@ class TaskHasherImpl { selfInputs ); if (target) { - return { - value: hashArray([selfAndInputs.value, target.value]), - details: { ...selfAndInputs.details, ...target.details }, - }; + return this.combinePartialHashes([selfAndInputs, target]); } return selfAndInputs; }); @@ -287,26 +291,20 @@ class TaskHasherImpl { const depsOut = await this.hashDepsOutputs(task, depsOutputs); const projects = await this.hashProjectInputs(projectInputs); + return this.combinePartialHashes([ + ...self, + ...deps, + ...projects, + ...depsOut, + ]); + } + + private combinePartialHashes(partialHashes: PartialHash[]): PartialHash { let details = {}; - for (const s of self) { - details = { ...details, ...s.details }; - } - for (const s of deps) { - details = { ...details, ...s.details }; - } - for (const s of projects) { - details = { ...details, ...s.details }; - } - for (const s of depsOut) { - details = { ...details, ...s.details }; + for (const partial of partialHashes) { + details = { ...details, ...partial.details }; } - - const value = hashArray([ - ...self.map((d) => d.value), - ...deps.map((d) => d.value), - ...depsOut.map((d) => d.value), - ...projects.map((d) => d.value), - ]); + const value = hashArray(partialHashes.map(({ value }) => value)); return { value, details }; } @@ -334,13 +332,7 @@ class TaskHasherImpl { visited ); } else { - const { hash } = this.hashExternalDependency(d.target); - return { - value: hash, - details: { - [d.target]: hash, - }, - }; + return this.getExternalDependencyHash(d.target); } } }) @@ -423,63 +415,63 @@ class TaskHasherImpl { return partialHashes; } + private getExternalDependencyHash(externalNodeName: string) { + return this.externalDependencyHashes.get(externalNodeName); + } + private hashExternalDependency( - projectName: string, - parentProjects = new Set() - ): { fullyResolved: boolean; hash: string } { + externalNodeName: string, + visited: Set + ): PartialHash { // try to retrieve the hash from cache - if (this.externalDepsHashCache[projectName]) { - return { - fullyResolved: true, - hash: this.externalDepsHashCache[projectName], - }; + if (this.externalDependencyHashes.has(externalNodeName)) { + return this.externalDependencyHashes.get(externalNodeName); } - parentProjects.add(projectName); - const node = this.projectGraph.externalNodes[projectName]; - let partialHash: string; - let fullyResolved = true; + visited.add(externalNodeName); + const node = this.projectGraph.externalNodes[externalNodeName]; + let partialHash: PartialHash; if (node) { - const partialHashes: string[] = []; + const partialHashes: PartialHash[] = []; if (node.data.hash) { // we already know the hash of this dependency - partialHashes.push(node.data.hash); + partialHashes.push({ + value: node.data.hash, + details: { + [externalNodeName]: node.data.hash, + }, + }); } else { // we take version as a hash - partialHashes.push(node.data.version); + partialHashes.push({ + value: node.data.version, + details: { + [externalNodeName]: node.data.version, + }, + }); } // we want to calculate the hash of the entire dependency tree - if (this.projectGraph.dependencies[projectName]) { - this.projectGraph.dependencies[projectName].forEach((d) => { - if (!parentProjects.has(d.target)) { - const hashResult = this.hashExternalDependency( - d.target, - new Set(parentProjects) - ); - partialHashes.push(hashResult.hash); - if (!hashResult.fullyResolved) { - fullyResolved = false; - } - } else { - // NOTE: do not store hash to cache since it is only a partial hash - fullyResolved = false; + if (this.projectGraph.dependencies[externalNodeName]) { + this.projectGraph.dependencies[externalNodeName].forEach((d) => { + if (!visited.has(d.target)) { + partialHashes.push(this.hashExternalDependency(d.target, visited)); } }); } - - partialHash = hashArray(partialHashes); + partialHash = this.combinePartialHashes(partialHashes); } else { // unknown dependency // this may occur if dependency is not an npm package // but rather symlinked in node_modules or it's pointing to a remote git repo // in this case we have no information about the versioning of the given package - partialHash = `__${projectName}__`; - } - - if (fullyResolved) { - this.externalDepsHashCache[projectName] = partialHash; + partialHash = { + value: `__${externalNodeName}__`, + details: { + [externalNodeName]: `__${externalNodeName}__`, + }, + }; } - - return { fullyResolved, hash: partialHash }; + this.externalDependencyHashes.set(externalNodeName, partialHash); + return partialHash; } private hashTarget( @@ -504,10 +496,10 @@ class TaskHasherImpl { const executorPackage = target.executor.split(':')[0]; const executorNodeName = this.findExternalDependencyNodeName(executorPackage); - hash = this.hashExternalDependency(executorNodeName).hash; + return this.getExternalDependencyHash(executorNodeName); } else { // use command external dependencies if available to construct the hash - const partialHashes: string[] = []; + const partialHashes: PartialHash[] = []; let hasCommandExternalDependencies = false; for (const input of selfInputs) { if (input['externalDependencies']) { @@ -516,29 +508,28 @@ class TaskHasherImpl { const externalDependencies = input['externalDependencies']; for (let dep of externalDependencies) { dep = this.findExternalDependencyNodeName(dep); - partialHashes.push(this.hashExternalDependency(dep).hash); + partialHashes.push(this.getExternalDependencyHash(dep)); } } } if (hasCommandExternalDependencies) { - hash = hashArray(partialHashes); + return this.combinePartialHashes(partialHashes); } else { // cache the hash of the entire external dependencies tree - if (this.externalDepsHashCache['']) { - hash = this.externalDepsHashCache['']; + if (this.allExternalDependenciesHash) { + return this.allExternalDependenciesHash; } else { hash = hashArray([JSON.stringify(this.projectGraph.externalNodes)]); - this.externalDepsHashCache[''] = hash; + this.allExternalDependenciesHash = { + value: hash, + details: { + AllExternalDependencies: hash, + }, + }; + return this.allExternalDependenciesHash; } } } - - return { - value: hash, - details: { - target: hash, - }, - }; } private findExternalDependencyNodeName(packageName: string): string { @@ -762,6 +753,13 @@ class TaskHasherImpl { value, }; } + + private calculateExternalDependencyHashes() { + const keys = Object.keys(this.projectGraph.externalNodes); + for (const externalNodeName of keys) { + this.hashExternalDependency(externalNodeName, new Set()); + } + } } export function getNamedInputs( From 9aad21dbfb2b659e488b6626f59df58ab23c0032 Mon Sep 17 00:00:00 2001 From: FrozenPandaz Date: Thu, 27 Jul 2023 17:48:20 -0400 Subject: [PATCH 192/262] chore(misc): publish 16.6.0-beta.6 --- lerna.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lerna.json b/lerna.json index f6f926fb3004f..432b9c8087757 100644 --- a/lerna.json +++ b/lerna.json @@ -1,6 +1,6 @@ { "packages": ["build/packages/*", "build/packages/nx/native-packages/*"], - "version": "16.6.0-beta.5", + "version": "16.6.0-beta.6", "granularPathspec": false, "command": { "publish": { From 4c2f98ebf94382bd76baf08e7ad90e6d7f9cc49f Mon Sep 17 00:00:00 2001 From: Jack Hsu Date: Thu, 27 Jul 2023 19:18:39 -0400 Subject: [PATCH 193/262] fix(js): generate correct standalone setup (#18355) --- packages/js/src/generators/library/library.ts | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/packages/js/src/generators/library/library.ts b/packages/js/src/generators/library/library.ts index 3a84b740f25a6..74f93f7f56f5f 100644 --- a/packages/js/src/generators/library/library.ts +++ b/packages/js/src/generators/library/library.ts @@ -238,7 +238,7 @@ export async function addLint( options: NormalizedSchema ): Promise { const { lintProjectGenerator } = ensurePackage('@nx/linter', nxVersion); - return lintProjectGenerator(tree, { + const task = lintProjectGenerator(tree, { project: options.name, linter: options.linter, skipFormat: true, @@ -252,6 +252,22 @@ export async function addLint( setParserOptionsProject: options.setParserOptionsProject, rootProject: options.rootProject, }); + // Also update the root .eslintrc.json lintProjectGenerator will not generate it for root projects. + // But we need to set the package.json checks. + if (options.rootProject) { + updateJson(tree, '.eslintrc.json', (json) => { + json.overrides ??= []; + json.overrides.push({ + files: ['*.json'], + parser: 'jsonc-eslint-parser', + rules: { + '@nx/dependency-checks': 'error', + }, + }); + return json; + }); + } + return task; } function addBundlerDependencies(tree: Tree, options: NormalizedSchema) { @@ -351,8 +367,8 @@ function createFiles(tree: Tree, options: NormalizedSchema, filesDir: string) { updateJson(tree, packageJsonPath, (json) => { json.name = options.importPath; json.version = '0.0.1'; - // If the package is publishable, we should remove the private field. - if (json.private && options.publishable) { + // If the package is publishable or root/standalone, we should remove the private field. + if (json.private && (options.publishable || options.rootProject)) { delete json.private; } return { From 661efa913dc239db6dc9aedcc3e999fa63e415b9 Mon Sep 17 00:00:00 2001 From: Jack Hsu Date: Fri, 28 Jul 2023 03:04:26 -0400 Subject: [PATCH 194/262] feat(bundling): generate matching d.ts files for rollup (#18342) --- .../packages/rollup/executors/rollup.json | 12 +- e2e/expo/src/expo.test.ts | 2 +- e2e/react-core/src/react-package.test.ts | 26 ++--- e2e/react-native/src/react-native.test.ts | 2 +- e2e/rollup/src/rollup.test.ts | 61 ++++++++++- e2e/web/src/web.test.ts | 2 +- packages/js/src/executors/node/node.impl.ts | 26 ++--- .../js/src/plugins/rollup/type-definitions.ts | 61 +++++++++++ packages/rollup/package.json | 1 + .../executors/rollup/lib/normalize.spec.ts | 10 +- .../src/executors/rollup/lib/normalize.ts | 17 ++- .../rollup/lib/update-package-json.spec.ts | 79 +++++--------- .../rollup/lib/update-package-json.ts | 103 +++++++++++++----- .../executors/rollup/lib/validate-types.ts | 20 ---- .../src/executors/rollup/rollup.impl.spec.ts | 30 +++-- .../src/executors/rollup/rollup.impl.ts | 53 +++++---- .../rollup/src/executors/rollup/schema.d.ts | 3 +- .../rollup/src/executors/rollup/schema.json | 14 ++- .../generators/configuration/configuration.ts | 5 +- 19 files changed, 345 insertions(+), 182 deletions(-) create mode 100644 packages/js/src/plugins/rollup/type-definitions.ts delete mode 100644 packages/rollup/src/executors/rollup/lib/validate-types.ts diff --git a/docs/generated/packages/rollup/executors/rollup.json b/docs/generated/packages/rollup/executors/rollup.json index 7d9fbf88aebad..9c19c745f5bcb 100644 --- a/docs/generated/packages/rollup/executors/rollup.json +++ b/docs/generated/packages/rollup/executors/rollup.json @@ -151,8 +151,16 @@ }, "generateExportsField": { "type": "boolean", - "description": "Generate package.json with 'exports' field. This field defines entry points in the package and is used by Node and the TypeScript compiler.", - "default": false + "alias": "exports", + "description": "Update the output package.json file's 'exports' field. This field is used by Node and bundles.", + "default": false, + "x-priority": "important" + }, + "additionalEntryPoints": { + "type": "array", + "description": "Additional entry-points to add to exports field in the package.json file.", + "items": { "type": "string" }, + "x-priority": "important" }, "skipTypeCheck": { "type": "boolean", diff --git a/e2e/expo/src/expo.test.ts b/e2e/expo/src/expo.test.ts index 9b2abff7c93cb..01108caf26ee5 100644 --- a/e2e/expo/src/expo.test.ts +++ b/e2e/expo/src/expo.test.ts @@ -138,7 +138,7 @@ describe('expo', () => { it('should build publishable library', async () => { expect(() => { runCLI(`build ${libName}`); - checkFilesExist(`dist/libs/${libName}/index.js`); + checkFilesExist(`dist/libs/${libName}/index.esm.js`); checkFilesExist(`dist/libs/${libName}/src/index.d.ts`); }).not.toThrow(); }); diff --git a/e2e/react-core/src/react-package.test.ts b/e2e/react-core/src/react-package.test.ts index 6042f542cddd5..8a61dad360b07 100644 --- a/e2e/react-core/src/react-package.test.ts +++ b/e2e/react-core/src/react-package.test.ts @@ -119,9 +119,9 @@ describe('Build React libraries and apps', () => { runCLI(`build ${childLib}`); runCLI(`build ${childLib2}`); - checkFilesExist(`dist/libs/${childLib}/index.js`); + checkFilesExist(`dist/libs/${childLib}/index.esm.js`); - checkFilesExist(`dist/libs/${childLib2}/index.js`); + checkFilesExist(`dist/libs/${childLib2}/index.esm.js`); checkFilesExist(`dist/libs/${childLib}/assets/hello.txt`); checkFilesExist(`dist/libs/${childLib2}/README.md`); @@ -131,7 +131,7 @@ describe('Build React libraries and apps', () => { */ runCLI(`build ${parentLib} --updateBuildableProjectDepsInPackageJson`); - checkFilesExist(`dist/libs/${parentLib}/index.js`); + checkFilesExist(`dist/libs/${parentLib}/index.esm.js`); const jsonFile = readJson(`dist/libs/${parentLib}/package.json`); expect(jsonFile.peerDependencies).toEqual( @@ -148,14 +148,14 @@ describe('Build React libraries and apps', () => { runCLI(`build ${parentLib} --skip-nx-cache`); - checkFilesExist(`dist/libs/${parentLib}/index.js`); - checkFilesExist(`dist/libs/${childLib}/index.js`); - checkFilesExist(`dist/libs/${childLib2}/index.js`); + checkFilesExist(`dist/libs/${parentLib}/index.esm.js`); + checkFilesExist(`dist/libs/${childLib}/index.esm.js`); + checkFilesExist(`dist/libs/${childLib2}/index.esm.js`); - expect(readFile(`dist/libs/${childLib}/index.js`)).not.toContain( + expect(readFile(`dist/libs/${childLib}/index.esm.js`)).not.toContain( 'react/jsx-dev-runtime' ); - expect(readFile(`dist/libs/${childLib}/index.js`)).toContain( + expect(readFile(`dist/libs/${childLib}/index.esm.js`)).toContain( 'react/jsx-runtime' ); }); @@ -172,14 +172,14 @@ export async function h() { return 'c'; } runCLI(`build ${childLib} --format cjs,esm`); - checkFilesExist(`dist/libs/${childLib}/index.cjs`); - checkFilesExist(`dist/libs/${childLib}/index.js`); + checkFilesExist(`dist/libs/${childLib}/index.cjs.js`); + checkFilesExist(`dist/libs/${childLib}/index.esm.js`); const cjsPackageSize = getSize( - tmpProjPath(`dist/libs/${childLib}/index.cjs`) + tmpProjPath(`dist/libs/${childLib}/index.cjs.js`) ); const esmPackageSize = getSize( - tmpProjPath(`dist/libs/${childLib}/index.js`) + tmpProjPath(`dist/libs/${childLib}/index.esm.js`) ); // This is a loose requirement that ESM should be smaller than CJS output. @@ -228,7 +228,7 @@ export async function h() { return 'c'; } // What we're testing runCLI(`build ${myLib}`); // Assertion - const content = readFile(`dist/libs/${myLib}/index.js`); + const content = readFile(`dist/libs/${myLib}/index.esm.js`); /** * Then check if the result contains this "promise" polyfill? diff --git a/e2e/react-native/src/react-native.test.ts b/e2e/react-native/src/react-native.test.ts index 7de73a0fee948..67286404b7c42 100644 --- a/e2e/react-native/src/react-native.test.ts +++ b/e2e/react-native/src/react-native.test.ts @@ -172,7 +172,7 @@ describe('react native', () => { ); expect(() => { runCLI(`build ${libName}`); - checkFilesExist(`dist/libs/${libName}/index.js`); + checkFilesExist(`dist/libs/${libName}/index.esm.js`); checkFilesExist(`dist/libs/${libName}/src/index.d.ts`); }).not.toThrow(); }); diff --git a/e2e/rollup/src/rollup.test.ts b/e2e/rollup/src/rollup.test.ts index 704923b7d3d4e..59f81d4d1c162 100644 --- a/e2e/rollup/src/rollup.test.ts +++ b/e2e/rollup/src/rollup.test.ts @@ -1,6 +1,8 @@ import { + checkFilesExist, cleanupProject, newProject, + readJson, rmDist, runCLI, runCommand, @@ -23,8 +25,16 @@ describe('Rollup Plugin', () => { `generate @nx/rollup:configuration ${myPkg} --target=node --tsConfig=libs/${myPkg}/tsconfig.lib.json --main=libs/${myPkg}/src/index.ts` ); rmDist(); - runCLI(`build ${myPkg}`); - let output = runCommand(`node dist/libs/${myPkg}/index.cjs`); + runCLI(`build ${myPkg} --format=cjs,esm --generateExportsField`); + checkFilesExist(`dist/libs/${myPkg}/index.cjs.d.ts`); + expect(readJson(`dist/libs/${myPkg}/package.json`).exports).toEqual({ + '.': { + import: './index.esm.js', + default: './index.cjs.js', + }, + './package.json': './package.json', + }); + let output = runCommand(`node dist/libs/${myPkg}/index.cjs.js`); expect(output).toMatch(/Hello/); updateProjectConfig(myPkg, (config) => { @@ -38,7 +48,7 @@ describe('Rollup Plugin', () => { ); rmDist(); runCLI(`build ${myPkg}`); - output = runCommand(`node dist/libs/${myPkg}/index.cjs`); + output = runCommand(`node dist/libs/${myPkg}/index.cjs.js`); expect(output).toMatch(/Hello/); updateProjectConfig(myPkg, (config) => { @@ -52,10 +62,53 @@ describe('Rollup Plugin', () => { ); rmDist(); runCLI(`build ${myPkg}`); - output = runCommand(`node dist/libs/${myPkg}/index.cjs`); + output = runCommand(`node dist/libs/${myPkg}/index.cjs.js`); expect(output).toMatch(/Hello/); }, 500000); + it('should support additional entry-points', () => { + const myPkg = uniq('my-pkg'); + runCLI(`generate @nx/js:lib ${myPkg} --bundler=none`); + runCLI( + `generate @nx/rollup:configuration ${myPkg} --target=node --tsConfig=libs/${myPkg}/tsconfig.lib.json --main=libs/${myPkg}/src/index.ts --compiler=tsc` + ); + updateProjectConfig(myPkg, (config) => { + config.targets.build.options.format = ['cjs', 'esm']; + config.targets.build.options.generateExportsField = true; + config.targets.build.options.additionalEntryPoints = [ + `libs/${myPkg}/src/{foo,bar}.ts`, + ]; + return config; + }); + updateFile(`libs/${myPkg}/src/foo.ts`, `export const foo = 'foo';`); + updateFile(`libs/${myPkg}/src/bar.ts`, `export const bar = 'bar';`); + + runCLI(`build ${myPkg}`); + + checkFilesExist(`dist/libs/${myPkg}/index.esm.js`); + checkFilesExist(`dist/libs/${myPkg}/index.cjs.js`); + checkFilesExist(`dist/libs/${myPkg}/index.cjs.d.ts`); + checkFilesExist(`dist/libs/${myPkg}/foo.esm.js`); + checkFilesExist(`dist/libs/${myPkg}/foo.cjs.js`); + checkFilesExist(`dist/libs/${myPkg}/bar.esm.js`); + checkFilesExist(`dist/libs/${myPkg}/bar.cjs.js`); + expect(readJson(`dist/libs/${myPkg}/package.json`).exports).toEqual({ + './package.json': './package.json', + '.': { + import: './index.esm.js', + default: './index.cjs.js', + }, + './bar': { + import: './bar.esm.js', + default: './bar.cjs.js', + }, + './foo': { + import: './foo.esm.js', + default: './foo.cjs.js', + }, + }); + }); + it('should be able to build libs generated with @nx/js:lib --bundler rollup', () => { const jsLib = uniq('jslib'); runCLI(`generate @nx/js:lib ${jsLib} --bundler rollup`); diff --git a/e2e/web/src/web.test.ts b/e2e/web/src/web.test.ts index 7a8ce867e593b..78c8f2df7f1d9 100644 --- a/e2e/web/src/web.test.ts +++ b/e2e/web/src/web.test.ts @@ -125,7 +125,7 @@ describe('Web Components Applications', () => { checkFilesExist(`dist/apps/_should_not_remove.txt`); // Asset that React runtime is imported - expect(readFile(`dist/libs/${libName}/index.js`)).toMatch( + expect(readFile(`dist/libs/${libName}/index.esm.js`)).toMatch( /react\/jsx-runtime/ ); diff --git a/packages/js/src/executors/node/node.impl.ts b/packages/js/src/executors/node/node.impl.ts index ab1101d06f722..075b6d4d4e457 100644 --- a/packages/js/src/executors/node/node.impl.ts +++ b/packages/js/src/executors/node/node.impl.ts @@ -394,22 +394,18 @@ function getFileToRun( } function fileToRunCorrectPath(fileToRun: string): string { - if (!fileExists(fileToRun)) { - const cjsFile = fileToRun.replace(/\.js$/, '.cjs'); - if (fileExists(cjsFile)) { - fileToRun = cjsFile; - } else { - const mjsFile = fileToRun.replace(/\.js$/, '.mjs'); - if (fileExists(mjsFile)) { - fileToRun = mjsFile; - } else { - throw new Error( - `Could not find ${fileToRun}. Make sure your build succeeded.` - ); - } - } + if (fileExists(fileToRun)) return fileToRun; + + const extensionsToTry = ['.cjs', '.mjs', 'cjs.js', '.esm.js']; + + for (const ext of extensionsToTry) { + const file = fileToRun.replace(/\.js$/, ext); + if (fileExists(file)) return file; } - return fileToRun; + + throw new Error( + `Could not find ${fileToRun}. Make sure your build succeeded.` + ); } export default nodeExecutor; diff --git a/packages/js/src/plugins/rollup/type-definitions.ts b/packages/js/src/plugins/rollup/type-definitions.ts new file mode 100644 index 0000000000000..08b62d6fb1c1a --- /dev/null +++ b/packages/js/src/plugins/rollup/type-definitions.ts @@ -0,0 +1,61 @@ +// nx-ignore-next-line +import type { OutputBundle } from 'rollup'; // only used for types +import { relative } from 'path'; +import { stripIndents } from '@nx/devkit'; + +//NOTE: This is here so we can share between `@nx/rollup` and `@nx/vite`. + +/* + * This plugin takes all entry-points from the generated bundle and creates a + * bundled version of corresponding d.ts files. + * + * For example, `src/index.ts` generates two corresponding files: + * - `dist/xyz/index.js` + * - `dist/xyz/src/index.d.ts` + * + * We want a third file: `dist/index.d.ts` that re-exports from `src/index.d.ts`. + * That way, when TSC or IDEs look for types, it will find them in the right place. + */ +export function typeDefinitions(options: { + projectRoot: string; + main: string; +}) { + return { + name: 'dts-bundle', + async generateBundle(_opts: unknown, bundle: OutputBundle): Promise { + for (const [name, file] of Object.entries(bundle)) { + if ( + file.type === 'asset' || + !file.isEntry || + file.facadeModuleId == null + ) { + continue; + } + + const hasDefaultExport = file.exports.includes('default'); + const entrySourceFileName = relative( + options.projectRoot, + file.facadeModuleId + ); + const entrySourceDtsName = entrySourceFileName.replace( + /\.[cm]?[jt]sx?$/, + '' + ); + const dtsFileName = file.fileName.replace(/\.[cm]?js$/, '.d.ts'); + const relativeSourceDtsName = JSON.stringify('./' + entrySourceDtsName); + const dtsFileSource = hasDefaultExport + ? stripIndents` + export * from ${relativeSourceDtsName}; + export { default } from ${relativeSourceDtsName}; + ` + : `export * from ${relativeSourceDtsName};\n`; + + this.emitFile({ + type: 'asset', + fileName: dtsFileName, + source: dtsFileSource, + }); + } + }, + }; +} diff --git a/packages/rollup/package.json b/packages/rollup/package.json index 4a099b52f0fb2..6549858432f5f 100644 --- a/packages/rollup/package.json +++ b/packages/rollup/package.json @@ -38,6 +38,7 @@ "babel-plugin-transform-async-to-promises": "^0.8.15", "chalk": "^4.1.0", "dotenv": "~10.0.0", + "fast-glob": "^3.2.7", "postcss": "^8.4.14", "rollup": "^2.56.2", "rollup-plugin-copy": "^3.4.0", diff --git a/packages/rollup/src/executors/rollup/lib/normalize.spec.ts b/packages/rollup/src/executors/rollup/lib/normalize.spec.ts index 4956865c1cd6f..0747214bf6a70 100644 --- a/packages/rollup/src/executors/rollup/lib/normalize.spec.ts +++ b/packages/rollup/src/executors/rollup/lib/normalize.spec.ts @@ -20,7 +20,11 @@ describe('normalizeRollupExecutorOptions', () => { }); it('should resolve both node modules and relative path for rollupConfig', () => { - let result = normalizeRollupExecutorOptions(testOptions, root, sourceRoot); + let result = normalizeRollupExecutorOptions( + testOptions, + { root } as any, + sourceRoot + ); expect(result.rollupConfig).toEqual(['/root/apps/nodeapp/rollup.config']); result = normalizeRollupExecutorOptions( @@ -29,7 +33,7 @@ describe('normalizeRollupExecutorOptions', () => { // something that exists in node_modules rollupConfig: 'react', }, - root, + { root } as any, sourceRoot ); expect(result.rollupConfig).toHaveLength(1); @@ -42,7 +46,7 @@ describe('normalizeRollupExecutorOptions', () => { const result = normalizeRollupExecutorOptions( testOptions, - root, + { root } as any, sourceRoot ); expect(result.rollupConfig).toEqual([]); diff --git a/packages/rollup/src/executors/rollup/lib/normalize.ts b/packages/rollup/src/executors/rollup/lib/normalize.ts index aa1662e242980..2ce057633a2b7 100644 --- a/packages/rollup/src/executors/rollup/lib/normalize.ts +++ b/packages/rollup/src/executors/rollup/lib/normalize.ts @@ -1,6 +1,7 @@ import { basename, dirname, join, relative, resolve } from 'path'; +import { sync as globSync } from 'fast-glob'; import { statSync } from 'fs'; -import { normalizePath } from '@nx/devkit'; +import { ExecutorContext, normalizePath } from '@nx/devkit'; import type { AssetGlobPattern, RollupExecutorOptions } from '../schema'; @@ -13,9 +14,10 @@ export interface NormalizedRollupExecutorOptions extends RollupExecutorOptions { export function normalizeRollupExecutorOptions( options: RollupExecutorOptions, - root: string, + context: ExecutorContext, sourceRoot: string ): NormalizedRollupExecutorOptions { + const { root } = context; const main = `${root}/${options.main}`; const entryRoot = dirname(main); const project = options.project @@ -45,6 +47,7 @@ export function normalizeRollupExecutorOptions( projectRoot, outputPath, skipTypeCheck: options.skipTypeCheck || false, + additionalEntryPoints: createEntryPoints(options, context), }; } @@ -105,3 +108,13 @@ export function normalizeAssets( } }); } + +function createEntryPoints( + options: { additionalEntryPoints?: string[] }, + context: ExecutorContext +): string[] { + if (!options.additionalEntryPoints?.length) return []; + return globSync(options.additionalEntryPoints, { + cwd: context.root, + }); +} diff --git a/packages/rollup/src/executors/rollup/lib/update-package-json.spec.ts b/packages/rollup/src/executors/rollup/lib/update-package-json.spec.ts index e783760c55b88..b5b1e28ec3527 100644 --- a/packages/rollup/src/executors/rollup/lib/update-package-json.spec.ts +++ b/packages/rollup/src/executors/rollup/lib/update-package-json.spec.ts @@ -41,15 +41,12 @@ describe('updatePackageJson', () => { expect(utils.writeJsonFile).toHaveBeenCalledWith(expect.anything(), { exports: { - '.': { - types: './index.d.ts', - import: './index.js', - }, + './package.json': './package.json', + '.': './index.esm.js', }, - main: './index.js', - module: './index.js', + main: './index.esm.js', + module: './index.esm.js', type: 'module', - types: './index.d.ts', }); spy.mockRestore(); @@ -72,14 +69,11 @@ describe('updatePackageJson', () => { expect(utils.writeJsonFile).toHaveBeenCalledWith(expect.anything(), { exports: { - '.': { - types: './index.d.ts', - require: './index.cjs', - }, + './package.json': './package.json', + '.': './index.cjs.js', }, - main: './index.cjs', + main: './index.cjs.js', type: 'commonjs', - types: './index.d.ts', }); spy.mockRestore(); @@ -102,16 +96,14 @@ describe('updatePackageJson', () => { expect(utils.writeJsonFile).toHaveBeenCalledWith(expect.anything(), { exports: { + './package.json': './package.json', '.': { - types: './index.d.ts', - import: './index.js', - require: './index.cjs', + import: './index.esm.js', + default: './index.cjs.js', }, }, - main: './index.cjs', - module: './index.js', - type: 'module', - types: './index.d.ts', + main: './index.cjs.js', + module: './index.esm.js', }); spy.mockRestore(); @@ -131,27 +123,21 @@ describe('updatePackageJson', () => { [], { exports: { - './foo': { - import: './foo.js', - }, + './foo': './foo.esm.js', }, } as unknown as PackageJson ); expect(utils.writeJsonFile).toHaveBeenCalledWith(expect.anything(), { exports: { - '.': { - types: './index.d.ts', - import: './index.js', - }, - './foo': { - import: './foo.js', - }, + './package.json': './package.json', + '.': './index.esm.js', + + './foo': './foo.esm.js', }, - main: './index.js', - module: './index.js', + main: './index.esm.js', + module: './index.esm.js', type: 'module', - types: './index.d.ts', }); spy.mockRestore(); @@ -174,10 +160,9 @@ describe('updatePackageJson', () => { ); expect(utils.writeJsonFile).toHaveBeenCalledWith(expect.anything(), { - main: './index.js', - module: './index.js', + main: './index.esm.js', + module: './index.esm.js', type: 'module', - types: './index.d.ts', }); spy.mockRestore(); @@ -198,9 +183,8 @@ describe('updatePackageJson', () => { ); expect(utils.writeJsonFile).toHaveBeenCalledWith(expect.anything(), { - main: './index.cjs', + main: './index.cjs.js', type: 'commonjs', - types: './index.d.ts', }); spy.mockRestore(); @@ -221,10 +205,8 @@ describe('updatePackageJson', () => { ); expect(utils.writeJsonFile).toHaveBeenCalledWith(expect.anything(), { - main: './index.cjs', - module: './index.js', - type: 'module', - types: './index.d.ts', + main: './index.cjs.js', + module: './index.esm.js', }); spy.mockRestore(); @@ -243,22 +225,17 @@ describe('updatePackageJson', () => { [], { exports: { - './foo': { - import: './foo.js', - }, + './foo': './foo.esm.js', }, } as unknown as PackageJson ); expect(utils.writeJsonFile).toHaveBeenCalledWith(expect.anything(), { - main: './index.js', - module: './index.js', + main: './index.esm.js', + module: './index.esm.js', type: 'module', - types: './index.d.ts', exports: { - './foo': { - import: './foo.js', - }, + './foo': './foo.esm.js', }, }); diff --git a/packages/rollup/src/executors/rollup/lib/update-package-json.ts b/packages/rollup/src/executors/rollup/lib/update-package-json.ts index 79843aa988085..c1c0f7b7f0380 100644 --- a/packages/rollup/src/executors/rollup/lib/update-package-json.ts +++ b/packages/rollup/src/executors/rollup/lib/update-package-json.ts @@ -1,4 +1,4 @@ -import { relative } from 'path'; +import { basename, dirname, parse, relative } from 'path'; import { ExecutorContext } from 'nx/src/config/misc-interfaces'; import { ProjectGraphProjectNode } from 'nx/src/config/project-graph'; import { @@ -8,7 +8,9 @@ import { import { writeJsonFile } from 'nx/src/utils/fileutils'; import { PackageJson } from 'nx/src/utils/package-json'; import { NormalizedRollupExecutorOptions } from './normalize'; +import { normalizePath } from '@nx/devkit'; +// TODO(jack): Use updatePackageJson from @nx/js instead. export function updatePackageJson( options: NormalizedRollupExecutorOptions, context: ExecutorContext, @@ -19,45 +21,55 @@ export function updatePackageJson( const hasEsmFormat = options.format.includes('esm'); const hasCjsFormat = options.format.includes('cjs'); - const types = `./${relative(options.projectRoot, options.main).replace( - /\.[jt]sx?$/, - '.d.ts' - )}`; - const exports = { - // TS 4.5+ - '.': { - types, - }, - }; + if (options.generateExportsField) { + packageJson.exports = + typeof packageJson.exports === 'string' ? {} : { ...packageJson.exports }; + packageJson.exports['./package.json'] = './package.json'; + } if (hasEsmFormat) { - // `module` field is used by bundlers like rollup and webpack to detect ESM. - // May not be required in the future if type is already "module". - packageJson.module = './index.js'; - exports['.']['import'] = './index.js'; + const esmExports = getExports({ + ...options, + fileExt: '.esm.js', + }); + + packageJson.module = esmExports['.']; if (!hasCjsFormat) { - packageJson.main = './index.js'; + packageJson.type = 'module'; + packageJson.main ??= esmExports['.']; + } + + if (options.generateExportsField) { + for (const [exportEntry, filePath] of Object.entries(esmExports)) { + packageJson.exports[exportEntry] = hasCjsFormat + ? { import: filePath } + : filePath; + } } } if (hasCjsFormat) { - packageJson.main = './index.cjs'; - exports['.']['require'] = './index.cjs'; - } - if (!options.skipTypeField) { - packageJson.type = options.format.includes('esm') ? 'module' : 'commonjs'; - } + const cjsExports = getExports({ + ...options, + fileExt: '.cjs.js', + }); + + packageJson.main = cjsExports['.']; - // Support for older TS versions < 4.5 - packageJson.types = types; + if (!hasEsmFormat) { + packageJson.type = 'commonjs'; + } - // TODO(jack): remove this for Nx 16 - if (options.generateExportsField && typeof packageJson.exports !== 'string') { - packageJson.exports = { - ...packageJson.exports, - ...exports, - }; + if (options.generateExportsField) { + for (const [exportEntry, filePath] of Object.entries(cjsExports)) { + if (hasEsmFormat) { + packageJson.exports[exportEntry]['default'] ??= filePath; + } else { + packageJson.exports[exportEntry] = filePath; + } + } + } } writeJsonFile(`${options.outputPath}/package.json`, packageJson); @@ -77,3 +89,34 @@ export function updatePackageJson( ); } } + +interface Exports { + '.': string; + + [name: string]: string; +} + +function getExports( + options: Pick< + NormalizedRollupExecutorOptions, + 'main' | 'projectRoot' | 'outputFileName' | 'additionalEntryPoints' + > & { + fileExt: string; + } +): Exports { + const mainFile = options.outputFileName + ? options.outputFileName.replace(/\.[tj]s$/, '') + : basename(options.main).replace(/\.[tj]s$/, ''); + const exports: Exports = { + '.': './' + mainFile + options.fileExt, + }; + + if (options.additionalEntryPoints) { + for (const file of options.additionalEntryPoints) { + const { name: fileName } = parse(file); + exports['./' + fileName] = './' + fileName + options.fileExt; + } + } + + return exports; +} diff --git a/packages/rollup/src/executors/rollup/lib/validate-types.ts b/packages/rollup/src/executors/rollup/lib/validate-types.ts deleted file mode 100644 index 59628f2f316e7..0000000000000 --- a/packages/rollup/src/executors/rollup/lib/validate-types.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { printDiagnostics, runTypeCheck } from '@nx/js'; -import { join } from 'path'; - -export async function validateTypes(opts: { - workspaceRoot: string; - projectRoot: string; - tsconfig: string; -}): Promise { - const result = await runTypeCheck({ - workspaceRoot: opts.workspaceRoot, - tsConfigPath: join(opts.workspaceRoot, opts.tsconfig), - mode: 'noEmit', - }); - - await printDiagnostics(result.errors, result.warnings); - - if (result.errors.length > 0) { - throw new Error('Found type errors. See above.'); - } -} diff --git a/packages/rollup/src/executors/rollup/rollup.impl.spec.ts b/packages/rollup/src/executors/rollup/rollup.impl.spec.ts index 168af2cbbf89b..e088a2f7c05af 100644 --- a/packages/rollup/src/executors/rollup/rollup.impl.spec.ts +++ b/packages/rollup/src/executors/rollup/rollup.impl.spec.ts @@ -39,7 +39,11 @@ describe('rollupExecutor', () => { describe('createRollupOptions', () => { it('should create rollup options for valid config', () => { const result: any = createRollupOptions( - normalizeRollupExecutorOptions(testOptions, '/root', '/root/src'), + normalizeRollupExecutorOptions( + testOptions, + { root: '/root' } as any, + '/root/src' + ), [], context, { name: 'example' }, @@ -52,15 +56,15 @@ describe('rollupExecutor', () => { dir: '/root/dist/ui', format: 'esm', name: 'Example', - chunkFileNames: '[name].js', - entryFileNames: '[name].js', + chunkFileNames: '[name].esm.js', + entryFileNames: '[name].esm.js', }, { dir: '/root/dist/ui', format: 'cjs', name: 'Example', - chunkFileNames: '[name].cjs', - entryFileNames: '[name].cjs', + chunkFileNames: '[name].cjs.js', + entryFileNames: '[name].cjs.js', }, ]); }); @@ -74,7 +78,7 @@ describe('rollupExecutor', () => { const result: any = createRollupOptions( normalizeRollupExecutorOptions( { ...testOptions, rollupConfig: 'custom-rollup.config.ts' }, - '/root', + { root: '/root' } as any, '/root/src' ), [], @@ -110,7 +114,7 @@ describe('rollupExecutor', () => { 'custom-rollup-2.config.ts', ], }, - '/root', + { root: '/root' } as any, '/root/src' ), [], @@ -129,7 +133,11 @@ describe('rollupExecutor', () => { it(`should always use forward slashes for asset paths`, () => { createRollupOptions( { - ...normalizeRollupExecutorOptions(testOptions, '/root', '/root/src'), + ...normalizeRollupExecutorOptions( + testOptions, + { root: '/root' } as any, + '/root/src' + ), assets: [ { glob: 'README.md', @@ -154,7 +162,7 @@ describe('rollupExecutor', () => { const options = createRollupOptions( normalizeRollupExecutorOptions( { ...testOptions, external: 'all' }, - '/root', + { root: '/root' } as any, '/root/src' ), [], @@ -175,7 +183,7 @@ describe('rollupExecutor', () => { const options = createRollupOptions( normalizeRollupExecutorOptions( { ...testOptions, external: 'none' }, - '/root', + { root: '/root' } as any, '/root/src' ), [], @@ -196,7 +204,7 @@ describe('rollupExecutor', () => { const options = createRollupOptions( normalizeRollupExecutorOptions( { ...testOptions, external: ['rxjs'] }, - '/root', + { root: '/root' } as any, '/root/src' ), [], diff --git a/packages/rollup/src/executors/rollup/rollup.impl.ts b/packages/rollup/src/executors/rollup/rollup.impl.ts index a554d383405ca..c07ed5053ca4e 100644 --- a/packages/rollup/src/executors/rollup/rollup.impl.ts +++ b/packages/rollup/src/executors/rollup/rollup.impl.ts @@ -26,8 +26,8 @@ import { import { analyze } from './lib/analyze-plugin'; import { deleteOutputDir } from '../../utils/fs'; import { swc } from './lib/swc-plugin'; -import { validateTypes } from './lib/validate-types'; import { updatePackageJson } from './lib/update-package-json'; +import { typeDefinitions } from '@nx/js/src/plugins/rollup/type-definitions'; export type RollupExecutorEvent = { success: boolean; @@ -64,7 +64,7 @@ export async function* rollupExecutor( const options = normalizeRollupExecutorOptions( rawOptions, - context.root, + context, sourceRoot ); @@ -85,18 +85,6 @@ export async function* rollupExecutor( const outfile = resolveOutfile(context, options); - if (options.compiler === 'swc') { - try { - await validateTypes({ - workspaceRoot: context.root, - projectRoot: options.projectRoot, - tsconfig: options.tsConfig, - }); - } catch { - return { success: false }; - } - } - if (options.watch) { const watcher = rollup.watch(rollupOptions); return yield* eachValueFrom( @@ -204,6 +192,10 @@ export function createRollupOptions( } return options.format.map((format, idx) => { + // Either we're generating only one format, so we should bundle types + // OR we are generating dual formats, so only bundle types for CJS. + const shouldBundleTypes = options.format.length === 1 || format === 'cjs'; + const plugins = [ copy({ targets: convertCopyAssetsToRollupOptions( @@ -213,7 +205,7 @@ export function createRollupOptions( }), image(), json(), - (useTsc || useBabel) && + (useTsc || shouldBundleTypes) && require('rollup-plugin-typescript2')({ check: !options.skipTypeCheck, tsconfig: options.tsConfig, @@ -225,6 +217,11 @@ export function createRollupOptions( ), }, }), + shouldBundleTypes && + typeDefinitions({ + main: options.main, + projectRoot: options.projectRoot, + }), peerDepsExternal({ packageJsonPath: options.project, }), @@ -285,18 +282,21 @@ export function createRollupOptions( } externalPackages = [...new Set(externalPackages)]; + const mainEntryFileName = options.outputFileName || options.main; + const input: Record = {}; + input[parse(mainEntryFileName).name] = options.main; + options.additionalEntryPoints.forEach((entry) => { + input[parse(entry).name] = entry; + }); + const rollupConfig = { - input: options.outputFileName - ? { - [parse(options.outputFileName).name]: options.main, - } - : options.main, + input, output: { format, dir: `${options.outputPath}`, name: names(context.projectName).className, - entryFileNames: `[name].${format === 'esm' ? 'js' : 'cjs'}`, - chunkFileNames: `[name].${format === 'esm' ? 'js' : 'cjs'}`, + entryFileNames: `[name].${format}.js`, + chunkFileNames: `[name].${format}.js`, }, external: (id: string) => { return externalPackages.some( @@ -327,6 +327,9 @@ function createTsCompilerOptions( if (config.options.module === ts.ModuleKind.CommonJS) { compilerOptions['module'] = 'ESNext'; } + if (options.compiler === 'swc') { + compilerOptions['emitDeclarationOnly'] = true; + } return compilerOptions; } @@ -347,7 +350,9 @@ function convertCopyAssetsToRollupOptions( : undefined; } -function readCompatibleFormats(config: ts.ParsedCommandLine) { +function readCompatibleFormats( + config: ts.ParsedCommandLine +): ('cjs' | 'esm')[] { switch (config.options.module) { case ts.ModuleKind.CommonJS: case ts.ModuleKind.UMD: @@ -364,7 +369,7 @@ function resolveOutfile( ) { if (!options.format?.includes('cjs')) return undefined; const { name } = parse(options.outputFileName ?? options.main); - return resolve(context.root, options.outputPath, `${name}.cjs`); + return resolve(context.root, options.outputPath, `${name}.cjs.js`); } export default rollupExecutor; diff --git a/packages/rollup/src/executors/rollup/schema.d.ts b/packages/rollup/src/executors/rollup/schema.d.ts index 9a08e09638f6c..0f7ed0313e075 100644 --- a/packages/rollup/src/executors/rollup/schema.d.ts +++ b/packages/rollup/src/executors/rollup/schema.d.ts @@ -37,10 +37,11 @@ export interface RollupExecutorOptions { */ buildableProjectDepsInPackageJsonType?: 'dependencies' | 'peerDependencies'; deleteOutputPath?: boolean; - format?: string[]; + format?: ('cjs' | 'esm')[]; compiler?: 'babel' | 'tsc' | 'swc'; javascriptEnabled?: boolean; generateExportsField?: boolean; + additionalEntryPoints?: string[]; skipTypeCheck?: boolean; babelUpwardRootMode?: boolean; skipTypeField?: boolean; diff --git a/packages/rollup/src/executors/rollup/schema.json b/packages/rollup/src/executors/rollup/schema.json index 3a0e4626e3458..9091c4821f8f6 100644 --- a/packages/rollup/src/executors/rollup/schema.json +++ b/packages/rollup/src/executors/rollup/schema.json @@ -138,8 +138,18 @@ }, "generateExportsField": { "type": "boolean", - "description": "Generate package.json with 'exports' field. This field defines entry points in the package and is used by Node and the TypeScript compiler.", - "default": false + "alias": "exports", + "description": "Update the output package.json file's 'exports' field. This field is used by Node and bundles.", + "default": false, + "x-priority": "important" + }, + "additionalEntryPoints": { + "type": "array", + "description": "Additional entry-points to add to exports field in the package.json file.", + "items": { + "type": "string" + }, + "x-priority": "important" }, "skipTypeCheck": { "type": "boolean", diff --git a/packages/rollup/src/generators/configuration/configuration.ts b/packages/rollup/src/generators/configuration/configuration.ts index b08a871271209..dffa22a43c91e 100644 --- a/packages/rollup/src/generators/configuration/configuration.ts +++ b/packages/rollup/src/generators/configuration/configuration.ts @@ -55,7 +55,10 @@ function addBuildTarget(tree: Tree, options: RollupProjectSchema) { const buildOptions: RollupExecutorOptions = { main: options.main ?? joinPathFragments(project.root, 'src/main.ts'), - outputPath: joinPathFragments('dist', project.root), + outputPath: joinPathFragments( + 'dist', + project.root === '.' ? project.name : project.root + ), compiler: options.compiler ?? 'babel', tsConfig, project: `${project.root}/package.json`, From eb392109f706ba49c4cc858e170c00f6d0c9d0f1 Mon Sep 17 00:00:00 2001 From: Jack Hsu Date: Fri, 28 Jul 2023 03:05:39 -0400 Subject: [PATCH 195/262] fix(linter): do not report obsolete devDependencies since they are not used in production files (#18353) --- packages/eslint-plugin/src/rules/dependency-checks.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/eslint-plugin/src/rules/dependency-checks.ts b/packages/eslint-plugin/src/rules/dependency-checks.ts index d633b7d7f2010..2f5e799eda66c 100644 --- a/packages/eslint-plugin/src/rules/dependency-checks.ts +++ b/packages/eslint-plugin/src/rules/dependency-checks.ts @@ -331,7 +331,7 @@ export default createESLintRule({ ) { validateMissingDependencies(node); }, - ['JSONExpressionStatement > JSONObjectExpression > JSONProperty[key.value=/^(dev|peer|optional)?dependencies$/i] > JSONObjectExpression > JSONProperty']( + ['JSONExpressionStatement > JSONObjectExpression > JSONProperty[key.value=/^(peer|optional)?dependencies$/i] > JSONObjectExpression > JSONProperty']( node: AST.JSONProperty ) { const packageName = (node.key as any).value; From f4b7ec2c0decda0fc87c2d536a340e3b43c6452a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Jona=C5=A1?= Date: Fri, 28 Jul 2023 11:09:07 +0200 Subject: [PATCH 196/262] fix(linter): ensure tslint converter works with pnp (#18323) --- .../convert-tslint-to-eslint.spec.ts | 12 +++++++++++- .../convert-tslint-to-eslint.spec.ts | 12 +++++++++++- .../convert-to-eslint-config.ts | 6 +++--- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/packages/angular/src/generators/convert-tslint-to-eslint/convert-tslint-to-eslint.spec.ts b/packages/angular/src/generators/convert-tslint-to-eslint/convert-tslint-to-eslint.spec.ts index cbcf10b79c527..cf2c2412c76ef 100644 --- a/packages/angular/src/generators/convert-tslint-to-eslint/convert-tslint-to-eslint.spec.ts +++ b/packages/angular/src/generators/convert-tslint-to-eslint/convert-tslint-to-eslint.spec.ts @@ -14,7 +14,17 @@ import { conversionGenerator } from './convert-tslint-to-eslint'; /** * Don't run actual child_process implementation of installPackagesTask() */ -jest.mock('child_process'); +jest.mock('child_process', () => { + return { + ...jest.requireActual('child_process'), + execSync: jest.fn((command: string) => { + if (command.includes('pnpm --version')) { + return '8.2.0'; + } + return; + }), + }; +}); const appProjectName = 'angular-app-1'; const appProjectRoot = `apps/${appProjectName}`; diff --git a/packages/cypress/src/generators/convert-tslint-to-eslint/convert-tslint-to-eslint.spec.ts b/packages/cypress/src/generators/convert-tslint-to-eslint/convert-tslint-to-eslint.spec.ts index 0e981c95d1dd0..4cbcbc7b57a81 100644 --- a/packages/cypress/src/generators/convert-tslint-to-eslint/convert-tslint-to-eslint.spec.ts +++ b/packages/cypress/src/generators/convert-tslint-to-eslint/convert-tslint-to-eslint.spec.ts @@ -13,7 +13,17 @@ import { conversionGenerator } from './convert-tslint-to-eslint'; /** * Don't run actual child_process implementation of installPackagesTask() */ -jest.mock('child_process'); +jest.mock('child_process', () => { + return { + ...jest.requireActual('child_process'), + execSync: jest.fn((command: string) => { + if (command.includes('pnpm --version')) { + return '8.2.0'; + } + return; + }), + }; +}); const projectName = 'e2e-app-1'; const projectRoot = `apps/${projectName}`; diff --git a/packages/linter/src/utils/convert-tslint-to-eslint/convert-to-eslint-config.ts b/packages/linter/src/utils/convert-tslint-to-eslint/convert-to-eslint-config.ts index ffa41f252c5c8..a29113863f82e 100644 --- a/packages/linter/src/utils/convert-tslint-to-eslint/convert-to-eslint-config.ts +++ b/packages/linter/src/utils/convert-tslint-to-eslint/convert-to-eslint-config.ts @@ -103,8 +103,9 @@ export async function convertToESLintConfig( */ writeJsonFile(pathToTslintJson, updatedTSLintJson); } + const pm = getPackageManagerCommand(); const reportedConfiguration = await findReportedConfiguration( - 'npx tslint --print-config', + `${pm.exec} tslint --print-config`, pathToTslintJson ); @@ -121,8 +122,7 @@ export async function convertToESLintConfig( * This error could occur if, for example, the user does not have a TSLint plugin installed correctly that they * reference in their config. */ - const printConfigFailureMessageStart = - 'Command failed: npx tslint --print-config "tslint.json"'; + const printConfigFailureMessageStart = `Command failed: ${pm.exec} tslint --print-config "tslint.json"`; if ( reportedConfiguration.message.startsWith(printConfigFailureMessageStart) ) { From 48000a504438c6a69c88a5a88aa4ebd83ed12ef6 Mon Sep 17 00:00:00 2001 From: Miroslav Jonas Date: Thu, 27 Jul 2023 20:49:24 +0200 Subject: [PATCH 197/262] docs(nx-dev): remove reference commands --- docs/generated/manifests/menus.json | 20 ++------------------ docs/generated/manifests/nx.json | 24 ++---------------------- docs/map.json | 7 +------ docs/shared/reference/commands.md | 26 -------------------------- docs/shared/reference/sitemap.md | 3 +-- nx-dev/nx-dev/redirect-rules.js | 2 ++ 6 files changed, 8 insertions(+), 74 deletions(-) delete mode 100644 docs/shared/reference/commands.md diff --git a/docs/generated/manifests/menus.json b/docs/generated/manifests/menus.json index c295742503f55..74472ed22cf99 100644 --- a/docs/generated/manifests/menus.json +++ b/docs/generated/manifests/menus.json @@ -3789,15 +3789,7 @@ "isExternal": false, "children": [ { - "name": "Commands", - "path": "/reference/commands", - "id": "commands", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "nx.json", + "name": "Nx Configuration", "path": "/reference/nx-json", "id": "nx-json", "isExternal": false, @@ -3840,15 +3832,7 @@ "disableCollapsible": false }, { - "name": "Commands", - "path": "/reference/commands", - "id": "commands", - "isExternal": false, - "children": [], - "disableCollapsible": false - }, - { - "name": "nx.json", + "name": "Nx Configuration", "path": "/reference/nx-json", "id": "nx-json", "isExternal": false, diff --git a/docs/generated/manifests/nx.json b/docs/generated/manifests/nx.json index 77af63ce46821..3fd002b598c0a 100644 --- a/docs/generated/manifests/nx.json +++ b/docs/generated/manifests/nx.json @@ -4724,19 +4724,9 @@ "description": "Understand how to use Nx functionalities, what arguments and options are available for each component.", "file": "", "itemList": [ - { - "id": "commands", - "name": "Commands", - "description": "", - "file": "shared/reference/commands", - "itemList": [], - "isExternal": false, - "path": "/reference/commands", - "tags": [] - }, { "id": "nx-json", - "name": "nx.json", + "name": "Nx Configuration", "description": "", "file": "shared/reference/nx-json", "itemList": [], @@ -4789,19 +4779,9 @@ "path": "/reference", "tags": [] }, - "/reference/commands": { - "id": "commands", - "name": "Commands", - "description": "", - "file": "shared/reference/commands", - "itemList": [], - "isExternal": false, - "path": "/reference/commands", - "tags": [] - }, "/reference/nx-json": { "id": "nx-json", - "name": "nx.json", + "name": "Nx Configuration", "description": "", "file": "shared/reference/nx-json", "itemList": [], diff --git a/docs/map.json b/docs/map.json index 5d86ee6808580..4bb555750f4ab 100644 --- a/docs/map.json +++ b/docs/map.json @@ -1067,12 +1067,7 @@ "description": "Understand how to use Nx functionalities, what arguments and options are available for each component.", "itemList": [ { - "name": "Commands", - "id": "commands", - "file": "shared/reference/commands" - }, - { - "name": "nx.json", + "name": "Nx Configuration", "id": "nx-json", "file": "shared/reference/nx-json" }, diff --git a/docs/shared/reference/commands.md b/docs/shared/reference/commands.md deleted file mode 100644 index 3d5a0ae438944..0000000000000 --- a/docs/shared/reference/commands.md +++ /dev/null @@ -1,26 +0,0 @@ -# Nx CLI Commands - -- [create-nx-workspace](/packages/nx/documents/create-nx-workspace) -- [init](/packages/nx/documents/init) -- [generate](/packages/nx/documents/generate) -- [run](/packages/nx/documents/run) -- [daemon](/packages/nx/documents/daemon) -- [graph](/packages/nx/documents/dep-graph) -- [run-many](/packages/nx/documents/run-many) -- [affected](/packages/nx/documents/affected) -- [affected:graph](/packages/nx/documents/affected-dep-graph) -- [print-affected](/packages/nx/documents/print-affected) -- [format:check](/packages/nx/documents/format-check) -- [format:write](/packages/nx/documents/format-write) -- [migrate](/packages/nx/documents/migrate) -- [report](/packages/nx/documents/report) -- [list](/packages/nx/documents/list) -- [workspace-lint](/packages/nx/documents/workspace-lint) -- [workspace-generator](/packages/nx/documents/workspace-generator) -- [connect-to-nx-cloud](/packages/nx/documents/connect-to-nx-cloud) -- [reset](/packages/nx/documents/reset) -- [repair](/packages/nx/documents/repair) -- [exec](/packages/nx/documents/exec) -- [watch](/packages/nx/documents/watch) -- [show](/packages/nx/documents/show) -- [view-logs](/packages/nx/documents/view-logs) diff --git a/docs/shared/reference/sitemap.md b/docs/shared/reference/sitemap.md index a4daf54a488cf..3ac62d92968d4 100644 --- a/docs/shared/reference/sitemap.md +++ b/docs/shared/reference/sitemap.md @@ -184,8 +184,7 @@ - [Large Repo and DTE](/showcase/example-repos/dte) - [Nx Micro-Frontend Example](/showcase/example-repos/mfe) - [Reference](/reference) - - [Commands](/reference/commands) - - [nx.json](/reference/nx-json) + - [Nx Configuration](/reference/nx-json) - [Project Configuration](/reference/project-configuration) - [.nxignore](/reference/nxignore) - [Environment Variables](/reference/environment-variables) diff --git a/nx-dev/nx-dev/redirect-rules.js b/nx-dev/nx-dev/redirect-rules.js index 9f0bed7830f58..10bf10885f7d2 100644 --- a/nx-dev/nx-dev/redirect-rules.js +++ b/nx-dev/nx-dev/redirect-rules.js @@ -825,6 +825,8 @@ const latestRecipesRefactoring = { // nx concepts '/recipes/module-federation/faster-builds': '/concepts/more-concepts/faster-builds-with-module-federation', + + '/reference/commands': '/packages/nx', }; /** From 205b6fec10eb6c592dfe78f5ad75cfd010be1b76 Mon Sep 17 00:00:00 2001 From: Miroslav Jonas Date: Thu, 27 Jul 2023 20:57:33 +0200 Subject: [PATCH 198/262] fix(nx-dev): enable nx logo on docs to navigate to home --- nx-dev/ui-common/src/lib/documentation-header.tsx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/nx-dev/ui-common/src/lib/documentation-header.tsx b/nx-dev/ui-common/src/lib/documentation-header.tsx index a9f28d228b730..eabaf9aa23213 100644 --- a/nx-dev/ui-common/src/lib/documentation-header.tsx +++ b/nx-dev/ui-common/src/lib/documentation-header.tsx @@ -168,7 +168,7 @@ export function DocumentationHeader({ {/*LOGO*/}
Nx - + + + Docs From 1e30d43f7aa3a382aab405afd7012b3dbac2f958 Mon Sep 17 00:00:00 2001 From: Juri Date: Fri, 28 Jul 2023 08:58:59 +0200 Subject: [PATCH 199/262] docs(react): video and other improvements on tutorial --- .../react-standalone.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/docs/shared/react-standalone-tutorial/react-standalone.md b/docs/shared/react-standalone-tutorial/react-standalone.md index 3181ca5280c3f..560e23b10aa3b 100644 --- a/docs/shared/react-standalone-tutorial/react-standalone.md +++ b/docs/shared/react-standalone-tutorial/react-standalone.md @@ -19,6 +19,8 @@ Note, this tutorial sets up a repo with a single application at the root level t {% /callout %} +Note, while you could easily use Nx together with your manually set up React application, we're going to use the `@nx/react` plugin for this tutorial which provides some nice enhancements when working with React. [Visit our "Why Nx" page](/getting-started/why-nx) to learn more about plugins and what role they play in the Nx architecture. + ## Warm Up Here's the source code of the final result for this tutorial. @@ -27,6 +29,11 @@ Here's the source code of the final result for this tutorial. {% stackblitz-button url="github.com/nrwl/nx-recipes/tree/main/react-standalone?file=README.md" /%} +{% youtube +src="https://www.youtube.com/embed/OQ-Zc5tcxJE" +title="Tutorial: Standalone React Application" +width="100%" /%} + ## Creating a new React App Create a new standalone React application with the following command: @@ -214,6 +221,16 @@ Note that all of these targets are automatically cached by Nx. If you re-run a s Not all tasks might be cacheable though. You can configure `cacheableOperations` in the `nx.json` file. You can also [learn more about how caching works](/core-features/cache-task-results). +## Nx Plugins? Why? + +One thing you might be curious about is the project.json. You may wonder why we define tasks inside the `project.json` file instead of using the `package.json` file with scripts that directly launch Vite. + +Nx understands and supports both approaches, allowing you to define targets either in your `package.json` or `project.json` files. While both serve a similar purpose, the `project.json` file can be seen as an advanced form of `package.json` scripts, providing additional metadata and capabilities. In this tutorial, we utilize the `project.json` approach primarily because we take advantage of Nx Plugins. + +So, what are Nx Plugins? Nx Plugins are optional packages that extend the capabilities of Nx, catering to various specific technologies. For instance, we have plugins tailored to React (e.g., `@nx/react`), Vite (`@nx/vite`), Cypress (`@nx/cypress`), and more. These plugins offer additional features, making your development experience more efficient and enjoyable when working with specific tech stacks. + +[visit our "Why Nx" page](/getting-started/why-nx) for more deails. + ## Creating New Components You can just create new React components as you normally would. However, Nx plugins usually also ship [generators](/core-features/plugin-features/use-code-generators). They allow you to easily scaffold code, configuration or entire projects. To see what capabilities the `@nx/react` plugin ships, run the following command and inspect the output: From 461ec195056918050ec10e3fda3c377ff7a56983 Mon Sep 17 00:00:00 2001 From: Juri Date: Fri, 28 Jul 2023 10:12:20 +0200 Subject: [PATCH 200/262] feat(nx-dev): add video-link component --- docs/README.md | 8 ++++ nx-dev/ui-markdoc/src/index.ts | 3 ++ .../src/lib/tags/video-link.component.tsx | 47 +++++++++++++++++++ 3 files changed, 58 insertions(+) create mode 100644 nx-dev/ui-markdoc/src/lib/tags/video-link.component.tsx diff --git a/docs/README.md b/docs/README.md index c4685a3a6691a..bf590b581a835 100644 --- a/docs/README.md +++ b/docs/README.md @@ -170,6 +170,14 @@ title="Nx Console Run UI Form" width="100%" /%} ``` +#### Youtube Section Link + +Have a more decent button-like widget that you can place below sections of a tutorial with a link to a specific point in a Youtube video. + +```markdown +{% video-link link="https://youtu.be/OQ-Zc5tcxJE?t=64" /%} +``` + #### Graph Embed an Nx Graph visualization that can be panned by the user. diff --git a/nx-dev/ui-markdoc/src/index.ts b/nx-dev/ui-markdoc/src/index.ts index 98773fe96e2c6..15e516aa526d5 100644 --- a/nx-dev/ui-markdoc/src/index.ts +++ b/nx-dev/ui-markdoc/src/index.ts @@ -43,6 +43,7 @@ import { TerminalCommand, terminalCommand, } from './lib/tags/terminal-command.component'; +import { VideoLink, videoLink } from './lib/tags/video-link.component'; // TODO fix this export export { GithubRepository } from './lib/tags/github-repository.component'; @@ -75,6 +76,7 @@ export const getMarkdocCustomConfig = ( 'title-card': titleCard, youtube, 'terminal-command': terminalCommand, + 'video-link': videoLink, }, }, components: { @@ -98,6 +100,7 @@ export const getMarkdocCustomConfig = ( TitleCard, YouTube, TerminalCommand, + VideoLink, }, }); diff --git a/nx-dev/ui-markdoc/src/lib/tags/video-link.component.tsx b/nx-dev/ui-markdoc/src/lib/tags/video-link.component.tsx new file mode 100644 index 0000000000000..abd51fd99cdcf --- /dev/null +++ b/nx-dev/ui-markdoc/src/lib/tags/video-link.component.tsx @@ -0,0 +1,47 @@ +import { Schema } from '@markdoc/markdoc'; + +export const videoLink: Schema = { + render: 'VideoLink', + attributes: { + link: { + type: 'String', + required: true, + }, + text: { + type: 'String', + required: false, + }, + }, +}; + +const youtubeIcon = ( + + + +); + +export function VideoLink({ text, link }: { text: string; link: string }) { + return ( + + ); +} From 3c13d291dfe1762e6eaf3cef8d6d32dc342d7763 Mon Sep 17 00:00:00 2001 From: Juri Date: Fri, 28 Jul 2023 10:12:31 +0200 Subject: [PATCH 201/262] docs(react): add video-link sections for the React standalone docs --- .../react-standalone.md | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/docs/shared/react-standalone-tutorial/react-standalone.md b/docs/shared/react-standalone-tutorial/react-standalone.md index 560e23b10aa3b..c7e49e0c768cf 100644 --- a/docs/shared/react-standalone-tutorial/react-standalone.md +++ b/docs/shared/react-standalone-tutorial/react-standalone.md @@ -36,6 +36,8 @@ width="100%" /%} ## Creating a new React App +{% video-link link="https://youtu.be/OQ-Zc5tcxJE?t=64" /%} + Create a new standalone React application with the following command: ```shell {% command="npx create-nx-workspace@latest myreactapp --preset=react-standalone" path="~" %} @@ -90,6 +92,8 @@ Let me explain a couple of things that might be new to you. ## Serving the App +{% video-link link="https://youtu.be/OQ-Zc5tcxJE?t=207" /%} + The most common tasks are already mapped in the `package.json` file: ```json {% fileName="package.json" %} @@ -177,6 +181,8 @@ Learn more about how to [run tasks with Nx](/core-features/run-tasks). ## Testing and Linting - Running Multiple Tasks +{% video-link link="https://youtu.be/OQ-Zc5tcxJE?t=410" /%} + Our current setup doesn't just come with targets for serving and building the React application, but also has targets for unit testing, e2e testing and linting. Again, these are defined in the `project.json` file. We can use the same syntax as before to run these tasks: ```bash @@ -223,6 +229,8 @@ Not all tasks might be cacheable though. You can configure `cacheableOperations` ## Nx Plugins? Why? +{% video-link link="https://youtu.be/OQ-Zc5tcxJE?t=598" /%} + One thing you might be curious about is the project.json. You may wonder why we define tasks inside the `project.json` file instead of using the `package.json` file with scripts that directly launch Vite. Nx understands and supports both approaches, allowing you to define targets either in your `package.json` or `project.json` files. While both serve a similar purpose, the `project.json` file can be seen as an advanced form of `package.json` scripts, providing additional metadata and capabilities. In this tutorial, we utilize the `project.json` approach primarily because we take advantage of Nx Plugins. @@ -233,6 +241,8 @@ So, what are Nx Plugins? Nx Plugins are optional packages that extend the capabi ## Creating New Components +{% video-link link="https://youtu.be/OQ-Zc5tcxJE?t=706" /%} + You can just create new React components as you normally would. However, Nx plugins usually also ship [generators](/core-features/plugin-features/use-code-generators). They allow you to easily scaffold code, configuration or entire projects. To see what capabilities the `@nx/react` plugin ships, run the following command and inspect the output: ```shell {% command="npx nx list @nx/react" path="myreactapp" %} @@ -306,6 +316,8 @@ export default HelloWorld; ## Building the App for Deployment +{% video-link link="https://youtu.be/OQ-Zc5tcxJE?t=856" /%} + If you're ready and want to ship your application, you can build it using ```shell {% command="npx nx build" path="myreactapp" %} @@ -325,6 +337,8 @@ All the required files will be placed in the `dist/myreactapp` folder and can be ## You're ready to go! +{% video-link link="https://youtu.be/OQ-Zc5tcxJE?t=906" /%} + In the previous sections you learned about the basics of using Nx, running tasks and navigating an Nx workspace. You're ready to ship features now! But there's more to learn. You have two possibilities here: @@ -334,6 +348,8 @@ But there's more to learn. You have two possibilities here: ## Modularizing your React App with Local Libraries +{% video-link link="https://youtu.be/OQ-Zc5tcxJE?t=986" /%} + When you develop your React application, usually all your logic sits in the `app` folder. Ideally separated by various folder names which represent your "domains". As your app grows, this becomes more and more monolithic though. ``` @@ -363,6 +379,8 @@ Nx allows you to separate this logic into "local libraries". The main benefits i ### Creating Local Libraries +{% video-link link="https://youtu.be/OQ-Zc5tcxJE?t=1041" /%} + Let's assume our domain areas include `products`, `orders` and some more generic design system components, called `ui`. We can generate a new library for each of these areas using the React library generator: ``` @@ -427,6 +445,8 @@ Each of these libraries ### Importing Libraries into the React Application +{% video-link link="https://youtu.be/OQ-Zc5tcxJE?t=1245" /%} + All libraries that we generate automatically have aliases created in the root-level `tsconfig.base.json`. ```json {% fileName="tsconfig.base.json" %} @@ -561,6 +581,8 @@ export default App; ## Visualizing your Project Structure +{% video-link link="https://youtu.be/OQ-Zc5tcxJE?t=1416" /%} + Nx automatically detects the dependencies between the various parts of your workspace and builds a [project graph](/core-features/explore-graph). This graph is used by Nx to perform various optimizations such as determining the correct order of execution when running tasks like `nx build`, identifying [affected projects](/core-features/run-tasks#run-tasks-affected-by-a-pr) and more. Interestingly you can also visualize it. Just run: @@ -638,6 +660,8 @@ Exercise for you: change the codebase such that `modules-shared-ui` is used by ` ## Imposing Constraints with Module Boundary Rules +{% video-link link="https://youtu.be/OQ-Zc5tcxJE?t=1456" /%} + Once you modularize your codebase you want to make sure that the modules are not coupled to each other in an uncontrolled way. Here are some examples of how we might want to guard our small demo workspace: - we might want to allow `modules-orders` to import from `modules-shared-ui` but not the other way around From bd71ce35a462910306ac37a024a8a4d0105718be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leosvel=20P=C3=A9rez=20Espinosa?= Date: Fri, 28 Jul 2023 14:44:35 +0100 Subject: [PATCH 202/262] fix(js): fix misc issues in tsc batch executor (#18363) --- docs/generated/packages/js/executors/tsc.json | 2 +- docs/shared/incremental-builds.md | 4 + packages/js/docs/tsc-examples.md | 4 + .../batch/build-task-info-per-tsconfig-map.ts | 5 +- .../src/executors/tsc/lib/get-task-options.ts | 40 +-- .../js/src/executors/tsc/lib/get-tsconfig.ts | 258 +++++------------- 6 files changed, 87 insertions(+), 226 deletions(-) diff --git a/docs/generated/packages/js/executors/tsc.json b/docs/generated/packages/js/executors/tsc.json index 0f3d35f73e4cb..6d93739d9e9ec 100644 --- a/docs/generated/packages/js/executors/tsc.json +++ b/docs/generated/packages/js/executors/tsc.json @@ -174,7 +174,7 @@ ] } }, - "examplesFile": "## Examples\n\n{% tabs %}\n{% tab label=\"Using TypeScript Transformer Plugins\" %}\n\n`@nx/js:tsc` can run the [TypeScript Transformers](https://github.com/madou/typescript-transformer-handbook) by using the `transformers` option.\n\n```json {% fileName=\"libs/ts-lib/project.json\" %}\n{\n \"build\": {\n \"executor\": \"@nx/js:tsc\",\n \"options\": {\n \"outputPath\": \"dist/libs/ts-lib\",\n \"main\": \"libs/ts-lib/src/index.ts\",\n \"tsConfig\": \"libs/ts-lib/tsconfig.lib.json\",\n \"assets\": [\"libs/ts-lib/*.md\"],\n \"transformers\": [\n \"@nestjs/swagger/plugin\",\n {\n \"name\": \"@automapper/classes/transformer-plugin\",\n \"options\": {}\n }\n ]\n }\n }\n}\n```\n\n{% /tab %}\n{% tab label=\"Inline libraries\" %}\n\n`@nx/js:tsc` can inline non-buildable libraries by opt-in to **Inlining** mode with `external` option.\n\n```json {% fileName=\"libs/ts-lib/project.json\" %}\n{\n \"build\": {\n \"executor\": \"@nx/js:tsc\",\n \"options\": {\n \"outputPath\": \"dist/libs/ts-lib\",\n \"main\": \"libs/ts-lib/src/index.ts\",\n \"tsConfig\": \"libs/ts-lib/tsconfig.lib.json\",\n \"assets\": [\"libs/ts-lib/*.md\"],\n \"external\": \"all\"\n }\n }\n}\n```\n\n```shell\nnpx nx build ts-lib --external=all\n```\n\n`@nx/js:tsc` can also inline buildable libraries by setting `external: 'none'`\n\n```json {% fileName=\"libs/ts-lib/project.json\" %}\n{\n \"build\": {\n \"executor\": \"@nx/js:tsc\",\n \"options\": {\n \"outputPath\": \"dist/libs/ts-lib\",\n \"main\": \"libs/ts-lib/src/index.ts\",\n \"tsConfig\": \"libs/ts-lib/tsconfig.lib.json\",\n \"assets\": [\"libs/ts-lib/*.md\"],\n \"external\": \"none\"\n }\n }\n}\n```\n\n```shell\nnpx nx build ts-lib --external=none\n```\n\n{% /tab %}\n{% tab label=\"Batch mode execution\" %}\n\nThe `@nx/js:tsc` executor supports running multiple tasks in a single process. When running in batch mode, the executor uses the [TypeScript APIs for incremental builds](https://www.typescriptlang.org/docs/handbook/project-references.html#build-mode-for-typescript). This results in a much faster build time when compared to the default implementation (the bigger the task graph to run, the more the performance improvements).\n\n{% callout type=\"warning\" title=\"Experimental feature\" %}\nExecuting tasks in batch mode is an experimental feature.\n{% /callout %}\n\nTo run your builds using the batch implementation, set the `NX_BATCH_MODE` environment variable to `true`:\n\n```shell\nNX_BATCH_MODE=true nx build ts-lib\n```\n\nFor optimal performance, you could set the `clean` option to `false`. Otherwise, the executor cleans the output folder before running the build, which results in the loss of the [`.tsbuildinfo` file](https://www.typescriptlang.org/tsconfig/#tsBuildInfoFile) and, consequently, the loss of important optimizations performed by TypeScript. This is not a requirement. Even if the `clean` option is not set to `false` there are other important optimizations that are performed by the batch implementation.\n\n```json {% fileName=\"libs/ts-lib/project.json\" %}\n{\n \"build\": {\n \"executor\": \"@nx/js:tsc\",\n \"options\": {\n \"outputPath\": \"dist/libs/ts-lib\",\n \"main\": \"libs/ts-lib/src/index.ts\",\n \"tsConfig\": \"libs/ts-lib/tsconfig.lib.json\",\n \"assets\": [\"libs/ts-lib/*.md\"],\n \"clean\": false\n }\n }\n}\n```\n\n{% /tab %}\n{% /tabs %}\n", + "examplesFile": "## Examples\n\n{% tabs %}\n{% tab label=\"Using TypeScript Transformer Plugins\" %}\n\n`@nx/js:tsc` can run the [TypeScript Transformers](https://github.com/madou/typescript-transformer-handbook) by using the `transformers` option.\n\n```json {% fileName=\"libs/ts-lib/project.json\" %}\n{\n \"build\": {\n \"executor\": \"@nx/js:tsc\",\n \"options\": {\n \"outputPath\": \"dist/libs/ts-lib\",\n \"main\": \"libs/ts-lib/src/index.ts\",\n \"tsConfig\": \"libs/ts-lib/tsconfig.lib.json\",\n \"assets\": [\"libs/ts-lib/*.md\"],\n \"transformers\": [\n \"@nestjs/swagger/plugin\",\n {\n \"name\": \"@automapper/classes/transformer-plugin\",\n \"options\": {}\n }\n ]\n }\n }\n}\n```\n\n{% /tab %}\n{% tab label=\"Inline libraries\" %}\n\n`@nx/js:tsc` can inline non-buildable libraries by opt-in to **Inlining** mode with `external` option.\n\n```json {% fileName=\"libs/ts-lib/project.json\" %}\n{\n \"build\": {\n \"executor\": \"@nx/js:tsc\",\n \"options\": {\n \"outputPath\": \"dist/libs/ts-lib\",\n \"main\": \"libs/ts-lib/src/index.ts\",\n \"tsConfig\": \"libs/ts-lib/tsconfig.lib.json\",\n \"assets\": [\"libs/ts-lib/*.md\"],\n \"external\": \"all\"\n }\n }\n}\n```\n\n```shell\nnpx nx build ts-lib --external=all\n```\n\n`@nx/js:tsc` can also inline buildable libraries by setting `external: 'none'`\n\n```json {% fileName=\"libs/ts-lib/project.json\" %}\n{\n \"build\": {\n \"executor\": \"@nx/js:tsc\",\n \"options\": {\n \"outputPath\": \"dist/libs/ts-lib\",\n \"main\": \"libs/ts-lib/src/index.ts\",\n \"tsConfig\": \"libs/ts-lib/tsconfig.lib.json\",\n \"assets\": [\"libs/ts-lib/*.md\"],\n \"external\": \"none\"\n }\n }\n}\n```\n\n```shell\nnpx nx build ts-lib --external=none\n```\n\n{% /tab %}\n{% tab label=\"Batch mode execution\" %}\n\nThe `@nx/js:tsc` executor supports running multiple tasks in a single process. When running in batch mode, the executor uses the [TypeScript APIs for incremental builds](https://www.typescriptlang.org/docs/handbook/project-references.html#build-mode-for-typescript). This results in a much faster build time when compared to the default implementation (the bigger the task graph to run, the more the performance improvements).\n\n{% callout type=\"warning\" title=\"Experimental feature\" %}\nExecuting tasks in batch mode is an experimental feature.\n{% /callout %}\n\n{% callout type=\"info\" title=\"Requirements\" %}\nBuilding a project with the `@nx/js:tsc` executor in batch mode requires all dependent projects to be buildable and built using the `@nx/js:tsc` executor.\n{% /callout %}\n\nTo run your builds using the batch implementation, set the `NX_BATCH_MODE` environment variable to `true`:\n\n```shell\nNX_BATCH_MODE=true nx build ts-lib\n```\n\nFor optimal performance, you could set the `clean` option to `false`. Otherwise, the executor cleans the output folder before running the build, which results in the loss of the [`.tsbuildinfo` file](https://www.typescriptlang.org/tsconfig/#tsBuildInfoFile) and, consequently, the loss of important optimizations performed by TypeScript. This is not a requirement. Even if the `clean` option is not set to `false` there are other important optimizations that are performed by the batch implementation.\n\n```json {% fileName=\"libs/ts-lib/project.json\" %}\n{\n \"build\": {\n \"executor\": \"@nx/js:tsc\",\n \"options\": {\n \"outputPath\": \"dist/libs/ts-lib\",\n \"main\": \"libs/ts-lib/src/index.ts\",\n \"tsConfig\": \"libs/ts-lib/tsconfig.lib.json\",\n \"assets\": [\"libs/ts-lib/*.md\"],\n \"clean\": false\n }\n }\n}\n```\n\n{% /tab %}\n{% /tabs %}\n", "presets": [] }, "description": "Build a project using TypeScript.", diff --git a/docs/shared/incremental-builds.md b/docs/shared/incremental-builds.md index 774acbe7c9516..bca58cbe7a097 100644 --- a/docs/shared/incremental-builds.md +++ b/docs/shared/incremental-builds.md @@ -78,6 +78,10 @@ If you're using the `@nx/js:tsc` to build your projects, you can opt-in to use i Executing tasks in batch mode is an experimental feature. {% /callout %} +{% callout type="info" title="Requirements" %} +Building a project with the `@nx/js:tsc` executor in batch mode requires all dependent projects to be buildable and built using the `@nx/js:tsc` executor. +{% /callout %} + To run your builds using the batch implementation, set the `NX_BATCH_MODE` environment variable to `true`: ```shell diff --git a/packages/js/docs/tsc-examples.md b/packages/js/docs/tsc-examples.md index 0d872d8a53524..e32dc81ab0a83 100644 --- a/packages/js/docs/tsc-examples.md +++ b/packages/js/docs/tsc-examples.md @@ -80,6 +80,10 @@ The `@nx/js:tsc` executor supports running multiple tasks in a single process. W Executing tasks in batch mode is an experimental feature. {% /callout %} +{% callout type="info" title="Requirements" %} +Building a project with the `@nx/js:tsc` executor in batch mode requires all dependent projects to be buildable and built using the `@nx/js:tsc` executor. +{% /callout %} + To run your builds using the batch implementation, set the `NX_BATCH_MODE` environment variable to `true`: ```shell diff --git a/packages/js/src/executors/tsc/lib/batch/build-task-info-per-tsconfig-map.ts b/packages/js/src/executors/tsc/lib/batch/build-task-info-per-tsconfig-map.ts index 0a27acf5244db..902937b90907b 100644 --- a/packages/js/src/executors/tsc/lib/batch/build-task-info-per-tsconfig-map.ts +++ b/packages/js/src/executors/tsc/lib/batch/build-task-info-per-tsconfig-map.ts @@ -4,7 +4,7 @@ import { join, relative } from 'path'; import { CopyAssetsHandler } from '../../../../utils/assets/copy-assets-handler'; import { calculateProjectBuildableDependencies } from '../../../../utils/buildable-libs-utils'; import type { NormalizedExecutorOptions } from '../../../../utils/schema'; -import { getTaskWithTscExecutorOptions } from '../get-task-options'; +import { getTaskOptions } from '../get-task-options'; import type { TypescriptInMemoryTsConfig } from '../typescript-compilation'; import type { TaskInfo } from './types'; @@ -47,8 +47,7 @@ function processTasksAndPopulateTsConfigTaskInfoMap( } let taskOptions = - tasksOptions[taskName] ?? - getTaskWithTscExecutorOptions(taskName, context); + tasksOptions[taskName] ?? getTaskOptions(taskName, context); if (taskOptions) { const taskInfo = createTaskInfo(taskName, taskOptions, context, tsConfig); const tsConfigPath = join( diff --git a/packages/js/src/executors/tsc/lib/get-task-options.ts b/packages/js/src/executors/tsc/lib/get-task-options.ts index bc56ccf2ad1ff..6570eb26d79f3 100644 --- a/packages/js/src/executors/tsc/lib/get-task-options.ts +++ b/packages/js/src/executors/tsc/lib/get-task-options.ts @@ -3,52 +3,14 @@ import type { ProjectGraphProjectNode, Target, } from '@nx/devkit'; -import { getOutputsForTargetAndConfiguration } from '@nx/devkit'; -import { join } from 'path'; import type { ExecutorOptions, NormalizedExecutorOptions, } from '../../../utils/schema'; import { normalizeOptions } from './normalize-options'; -export function getTaskOptions( - taskName: string, - context: ExecutorContext -): - | NormalizedExecutorOptions - | { - tsConfig: string | null; - rootDir: string; - outputPath: string; - } { - const result = getTaskWithTscExecutorOptions(taskName, context); - if (result) { - return result; - } - - const { taskOptions, root, projectNode, target } = parseTaskInfo( - taskName, - context - ); - - const outputs = getOutputsForTargetAndConfiguration( - { overrides: context.taskGraph.tasks[taskName].overrides, target }, - projectNode - ); - - const outputPath = outputs.length - ? join(context.root, outputs[0]) - : join(context.root, 'dist', root); - const rootDir = join(context.root, root); - const tsConfig = taskOptions.tsConfig - ? join(context.root, taskOptions.tsConfig) - : null; - - return { tsConfig, rootDir, outputPath }; -} - const tasksOptionsCache = new Map(); -export function getTaskWithTscExecutorOptions( +export function getTaskOptions( taskName: string, context: ExecutorContext ): NormalizedExecutorOptions | null { diff --git a/packages/js/src/executors/tsc/lib/get-tsconfig.ts b/packages/js/src/executors/tsc/lib/get-tsconfig.ts index f2e4b5d87f915..eec791c91de40 100644 --- a/packages/js/src/executors/tsc/lib/get-tsconfig.ts +++ b/packages/js/src/executors/tsc/lib/get-tsconfig.ts @@ -1,15 +1,10 @@ import { - ExecutorContext, - getOutputsForTargetAndConfiguration, parseTargetString, readJsonFile, + stripIndents, + type ExecutorContext, } from '@nx/devkit'; -import { fileExists } from 'nx/src/utils/fileutils'; import { join } from 'path'; -import { - DependentBuildableProjectNode, - computeCompilerOptionsPaths, -} from '../../../utils/buildable-libs-utils'; import type { NormalizedExecutorOptions } from '../../../utils/schema'; import { getTaskOptions } from './get-task-options'; import type { TypescriptInMemoryTsConfig } from './typescript-compilation'; @@ -23,7 +18,7 @@ export function getProcessedTaskTsConfigs( {}; for (const task of tasks) { - generateTaskTsConfigOrGetDependentBuildableProjectNode( + generateTaskProjectTsConfig( task, tasksOptions, context, @@ -34,176 +29,101 @@ export function getProcessedTaskTsConfigs( return taskInMemoryTsConfigMap; } -const taskTsConfigGenerationCache = new Map< +const projectTsConfigCache = new Map< string, - { tsConfig: string } | DependentBuildableProjectNode + { tsConfigPath: string; tsConfig: TypescriptInMemoryTsConfig } >(); -function generateTaskTsConfigOrGetDependentBuildableProjectNode( +function generateTaskProjectTsConfig( task: string, tasksOptions: Record, context: ExecutorContext, taskInMemoryTsConfigMap: Record -): { tsConfig: string } | DependentBuildableProjectNode { - if (taskTsConfigGenerationCache.has(task)) { - return taskTsConfigGenerationCache.get(task); +): string { + const { project } = parseTargetString(task, context.projectGraph); + if (projectTsConfigCache.has(project)) { + const { tsConfig, tsConfigPath } = projectTsConfigCache.get(project); + taskInMemoryTsConfigMap[task] = tsConfig; + return tsConfigPath; } - let tsConfig = - tasksOptions[task]?.tsConfig ?? getTaskOptions(task, context).tsConfig; - let taskWithTsConfig = task; - - if (!tsConfig) { - // check if other tasks in the task graph from the same project has a tsConfig - const otherTasksInProject = getDependencyTasksInSameProject(task, context); - const taskTsConfig = findTaskWithTsConfig(otherTasksInProject, context); - - if (taskTsConfig) { - if (taskTsConfigGenerationCache.has(taskTsConfig.tsConfig)) { - return taskTsConfigGenerationCache.get(taskTsConfig.tsConfig); - } + const tasksInProject = [ + task, + ...getDependencyTasksInSameProject(task, context), + ]; + const taskWithTscExecutor = tasksInProject.find((t) => + hasTscExecutor(t, context) + ); - tsConfig = taskTsConfig.tsConfig; - taskWithTsConfig = taskTsConfig.task; - } + if (!taskWithTscExecutor) { + throw new Error( + stripIndents`The "@nx/js:tsc" batch executor requires all dependencies to use the "@nx/js:tsc" executor. + None of the following tasks in the "${project}" project use the "@nx/js:tsc" executor: + ${tasksInProject.map((t) => `- ${t}`).join('\n')}` + ); } - if (tsConfig) { - const { projectReferences, dependentBuildableProjectNodes } = - collectDependenciesFromTask( - task, + const projectReferences = []; + for (const task of tasksInProject) { + for (const depTask of getDependencyTasksInOtherProjects( + task, + project, + context + )) { + const tsConfigPath = generateTaskProjectTsConfig( + depTask, tasksOptions, context, taskInMemoryTsConfigMap ); - - taskInMemoryTsConfigMap[taskWithTsConfig] = getInMemoryTsConfig( - tsConfig, - tasksOptions[taskWithTsConfig] ?? - getTaskOptions(taskWithTsConfig, context), - projectReferences, - dependentBuildableProjectNodes - ); - - const result = { tsConfig }; - taskTsConfigGenerationCache.set(task, result); - - return result; + projectReferences.push(tsConfigPath); + } } - // there's no tsConfig, return a buildable project node so the path mapping - // is remapped to the output - const result = taskToDependentBuildableProjectNode(task, context); - taskTsConfigGenerationCache.set(task, result); + const taskOptions = + tasksOptions[taskWithTscExecutor] ?? + getTaskOptions(taskWithTscExecutor, context); + const tsConfigPath = taskOptions.tsConfig; - return result; -} - -const projectDependenciesCache = new Map< - string, - { - projectReferences: string[]; - dependentBuildableProjectNodes: DependentBuildableProjectNode[]; - } ->(); -function collectDependenciesFromTask( - task: string, - tasksOptions: Record, - context: ExecutorContext, - taskInMemoryTsConfigMap: Record -): { - projectReferences: string[]; - dependentBuildableProjectNodes: DependentBuildableProjectNode[]; -} { - const { project: taskProject } = parseTargetString( - task, - context.projectGraph + taskInMemoryTsConfigMap[taskWithTscExecutor] = getInMemoryTsConfig( + tsConfigPath, + taskOptions, + projectReferences ); - if (projectDependenciesCache.has(taskProject)) { - return projectDependenciesCache.get(taskProject); - } - - const dependentBuildableProjectNodes: DependentBuildableProjectNode[] = []; - const projectReferences = new Set(); - - const allProjectTasks = [ - task, - ...getDependencyTasksInSameProject(task, context), - ]; - for (const projectTask of allProjectTasks) { - for (const depTask of context.taskGraph.dependencies[projectTask] ?? []) { - if (task === depTask) { - continue; - } - - const { project: depTaskProject } = parseTargetString( - depTask, - context.projectGraph - ); - - if (depTaskProject === taskProject) { - // recursively collect dependencies for tasks in the same project - const result = collectDependenciesFromTask( - depTask, - tasksOptions, - context, - taskInMemoryTsConfigMap - ); - - result.projectReferences.forEach((pr) => { - projectReferences.add(pr); - }); - result.dependentBuildableProjectNodes.forEach((node) => { - dependentBuildableProjectNodes.push(node); - }); - } else { - // task is from a different project, get its project reference or buildable node - const result = generateTaskTsConfigOrGetDependentBuildableProjectNode( - depTask, - tasksOptions, - context, - taskInMemoryTsConfigMap - ); - if ('tsConfig' in result) { - projectReferences.add(result.tsConfig); - } else { - dependentBuildableProjectNodes.push(result); - } - } - } - } - - projectDependenciesCache.set(taskProject, { - projectReferences: Array.from(projectReferences), - dependentBuildableProjectNodes, + projectTsConfigCache.set(project, { + tsConfigPath: tsConfigPath, + tsConfig: taskInMemoryTsConfigMap[taskWithTscExecutor], }); - return projectDependenciesCache.get(taskProject); + return tsConfigPath; } -function taskToDependentBuildableProjectNode( +function getDependencyTasksInOtherProjects( task: string, + project: string, context: ExecutorContext -): DependentBuildableProjectNode { - const target = context.taskGraph.tasks[task].target; - const projectGraphNode = context.projectGraph.nodes[target.project]; +): string[] { + return context.taskGraph.dependencies[task].filter( + (t) => + t !== task && + parseTargetString(t, context.projectGraph).project !== project + ); +} - const libPackageJsonPath = join( - context.root, - projectGraphNode.data.root, - 'package.json' +function getDependencyTasksInSameProject( + task: string, + context: ExecutorContext +): string[] { + const { project: taskProject } = parseTargetString( + task, + context.projectGraph ); - return { - name: fileExists(libPackageJsonPath) - ? readJsonFile(libPackageJsonPath).name - : target.project, - outputs: getOutputsForTargetAndConfiguration( - { overrides: {}, target }, - projectGraphNode - ), - node: projectGraphNode, - }; + return Object.keys(context.taskGraph.tasks).filter( + (t) => + t !== task && + parseTargetString(t, context.projectGraph).project === taskProject + ); } function getInMemoryTsConfig( @@ -213,8 +133,7 @@ function getInMemoryTsConfig( rootDir: string; outputPath: string; }, - projectReferences: string[], - dependentBuildableProjectNodes: DependentBuildableProjectNode[] + projectReferences: string[] ): TypescriptInMemoryTsConfig { const originalTsConfig = readJsonFile(tsConfig, { allowTrailingComma: true, @@ -240,12 +159,6 @@ function getInMemoryTsConfig( declaration: true, declarationMap: true, tsBuildInfoFile: join(taskOptions.outputPath, 'tsconfig.tsbuildinfo'), - paths: dependentBuildableProjectNodes.length - ? computeCompilerOptionsPaths( - tsConfig, - dependentBuildableProjectNodes - ) - : originalTsConfig.compilerOptions?.paths, }, references: allProjectReferences.map((pr) => ({ path: pr })), }), @@ -253,32 +166,11 @@ function getInMemoryTsConfig( }; } -function findTaskWithTsConfig( - tasks: string[], - context: ExecutorContext -): { task: string; tsConfig: string } | null { - for (const task of tasks) { - const depTaskOptions = getTaskOptions(task, context); - if (depTaskOptions?.tsConfig) { - return { task: task, tsConfig: depTaskOptions.tsConfig }; - } - } - - return null; -} - -function getDependencyTasksInSameProject( - task: string, - context: ExecutorContext -): string[] { - const { project: taskProject } = parseTargetString( - task, - context.projectGraph - ); +function hasTscExecutor(task: string, context: ExecutorContext): boolean { + const { project, target } = parseTargetString(task, context.projectGraph); - return Object.keys(context.taskGraph.tasks).filter( - (t) => - t !== task && - parseTargetString(t, context.projectGraph).project === taskProject + return ( + context.projectGraph.nodes[project].data.targets[target].executor === + '@nx/js:tsc' ); } From 90574e5a216dce570688fd3259733099daf4c9be Mon Sep 17 00:00:00 2001 From: Juri Date: Fri, 28 Jul 2023 15:35:18 +0200 Subject: [PATCH 203/262] docs(angular): add video-links to angular tutorial --- .../angular-standalone.md | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/docs/shared/angular-standalone-tutorial/angular-standalone.md b/docs/shared/angular-standalone-tutorial/angular-standalone.md index af14bf7e05439..82a084cef53f9 100644 --- a/docs/shared/angular-standalone-tutorial/angular-standalone.md +++ b/docs/shared/angular-standalone-tutorial/angular-standalone.md @@ -31,6 +31,8 @@ width="100%" /%} ## Creating a new Angular App +{% video-link link="https://youtu.be/ZAO0yXupIIE?t=49" /%} + Create a new Angular application with the following command: ```shell {% command="npx create-nx-workspace@latest myngapp --preset=angular-standalone" path="~" %} @@ -107,6 +109,8 @@ Compared to the Angular CLI, you might notice the addition of an `nx.json` file ## Serving the App +{% video-link link="https://youtu.be/ZAO0yXupIIE?t=296" /%} + The most common tasks are already defined in the `package.json` file: ```json {% fileName="package.json" %} @@ -183,6 +187,8 @@ Learn more about how to [run tasks with Nx](/core-features/run-tasks). ## Testing and Linting - Running Multiple Tasks +{% video-link link="https://youtu.be/ZAO0yXupIIE?t=369" /%} + Our current setup not only has targets for serving and building the Angular application, but also has targets for unit testing, e2e testing and linting. Again, these are defined in the `project.json` file. We can use the same syntax as before to run these tasks: ```bash @@ -207,6 +213,8 @@ More conveniently, we can also run them in parallel using the following syntax: ### Caching +{% video-link link="https://youtu.be/ZAO0yXupIIE?t=443" /%} + One thing to highlight is that Nx is able to [cache the tasks you run](/core-features/cache-task-results). Note that all of these targets are automatically cached by Nx. If you re-run a single one or all of them again, you'll see that the task completes immediately. In addition, (as can be seen in the output example below) there will be a note that a matching cache result was found and therefore the task was not run again. @@ -229,6 +237,8 @@ Not all tasks might be cacheable though. You can configure `cacheableOperations` ## Creating New Components +{% video-link link="https://youtu.be/ZAO0yXupIIE?t=500" /%} + Similar to the Angular CLI, Nx comes with code generation abilities. What the Angular CLI calls "Schematics", Nx calls "Generators". Generators allow you to easily scaffold code, configuration or entire projects. To see what capabilities the `@nx/angular` plugin ships with, run the following command and inspect the output: @@ -314,6 +324,8 @@ export class HelloWorldComponent {} ## Building the App for Deployment +{% video-link link="https://youtu.be/ZAO0yXupIIE?t=680" /%} + If you're ready and want to ship your application, you can build it using ```shell {% command="npx nx build" path="myngapp" %} @@ -342,6 +354,8 @@ All the required files will be placed in the `dist/myngapp` folder and can be de ## You're ready to go! +{% video-link link="https://youtu.be/ZAO0yXupIIE?t=723" /%} + In the previous sections you learned about the basics of using Nx, running tasks and navigating an Nx workspace. You're ready to ship features now! But there's more to learn. You have two possibilities here: @@ -351,6 +365,8 @@ But there's more to learn. You have two possibilities here: ## Modularizing your Angular App with Local Libraries +{% video-link link="https://youtu.be/ZAO0yXupIIE?t=750" /%} + When you develop your Angular application, usually all your logic sits in the `app` folder. Ideally separated by various folder names which represent your "domains". As your app grows, this becomes more and more monolithic though. The following structure is a common example of this kind of monolithic code organization: @@ -382,6 +398,8 @@ Nx allows you to separate this logic into "local libraries". The main benefits i ### Creating Local Libraries +{% video-link link="https://youtu.be/ZAO0yXupIIE?t=818" /%} + Let's assume our domain areas include `products`, `orders` and some more generic design system components, called `ui`. We can generate a new library for each of these areas using the Angular library generator: ``` @@ -453,6 +471,8 @@ Each of these libraries ### Importing Libraries into the Angular Application +{% video-link link="https://youtu.be/ZAO0yXupIIE?t=976" /%} + All libraries that we generate automatically have aliases created in the root-level `tsconfig.base.json`. ```json {% fileName="tsconfig.base.json" %} @@ -557,6 +577,8 @@ A couple of notes: ## Visualizing your Project Structure +{% video-link link="https://youtu.be/ZAO0yXupIIE?t=958" /%} + Nx automatically detects the dependencies between the various parts of your workspace and builds a [project graph](/core-features/explore-graph). This graph is used by Nx to perform various optimizations such as determining the correct order of execution when running tasks like `nx build`, identifying [affected projects](/core-features/run-tasks#run-tasks-affected-by-a-pr) and more. Interestingly you can also visualize it. Just run: @@ -634,6 +656,8 @@ Exercise for you: change the codebase so that `modules-shared-ui` is used by `mo ## Imposing Constraints with Module Boundary Rules +{% video-link link="https://youtu.be/ZAO0yXupIIE?t=1147" /%} + Once you modularize your codebase you want to make sure that the modules are not coupled to each other in an uncontrolled way. Here are some examples of how we might want to guard our small demo workspace: - we might want to allow `modules-orders` to import from `modules-shared-ui` but not the other way around From e06b9e0954f1637622ea5d1d998b8dda3c99ac30 Mon Sep 17 00:00:00 2001 From: Katerina Skroumpelou Date: Fri, 21 Jul 2023 13:38:12 +0300 Subject: [PATCH 204/262] docs(storybook): interaction tests updated documentation --- docs/generated/manifests/menus.json | 8 + docs/generated/manifests/packages.json | 11 ++ docs/generated/packages-metadata.json | 11 ++ .../packages/angular/generators/stories.json | 2 +- .../generators/storybook-configuration.json | 2 +- .../packages/react/generators/stories.json | 2 +- .../generators/storybook-configuration.json | 2 +- .../documents/storybook-interaction-tests.md | 138 ++++++++++++++++++ .../storybook/generators/configuration.json | 2 +- docs/map.json | 6 + .../packages/storybook/interaction-tests.md | 138 ++++++++++++++++++ docs/shared/reference/sitemap.md | 1 + packages/angular/docs/stories-examples.md | 4 +- .../docs/storybook-configuration-examples.md | 22 +-- packages/react/docs/stories-examples.md | 4 +- .../docs/storybook-configuration-examples.md | 22 +-- .../docs/configuration-generator-examples.md | 9 +- 17 files changed, 350 insertions(+), 34 deletions(-) create mode 100644 docs/generated/packages/storybook/documents/storybook-interaction-tests.md create mode 100644 docs/shared/packages/storybook/interaction-tests.md diff --git a/docs/generated/manifests/menus.json b/docs/generated/manifests/menus.json index 74472ed22cf99..576c68769bf30 100644 --- a/docs/generated/manifests/menus.json +++ b/docs/generated/manifests/menus.json @@ -7423,6 +7423,14 @@ "children": [], "disableCollapsible": false }, + { + "name": "Setting up Storybook Interaction Tests with Nx", + "path": "/packages/storybook/documents/storybook-interaction-tests", + "id": "storybook-interaction-tests", + "isExternal": false, + "children": [], + "disableCollapsible": false + }, { "name": "Setting up Storybook Composition with Nx", "path": "/packages/storybook/documents/storybook-composition-setup", diff --git a/docs/generated/manifests/packages.json b/docs/generated/manifests/packages.json index 4e6723890e439..22f0e6ceecbf7 100644 --- a/docs/generated/manifests/packages.json +++ b/docs/generated/manifests/packages.json @@ -2440,6 +2440,17 @@ "tags": [], "originalFilePath": "shared/packages/storybook/custom-builder-configs" }, + "/packages/storybook/documents/storybook-interaction-tests": { + "id": "storybook-interaction-tests", + "name": "Setting up Storybook Interaction Tests with Nx", + "description": "This guide explains how you can set up Storybook interaction tests on your Nx workspace.", + "file": "generated/packages/storybook/documents/storybook-interaction-tests", + "itemList": [], + "isExternal": false, + "path": "/packages/storybook/documents/storybook-interaction-tests", + "tags": [], + "originalFilePath": "shared/packages/storybook/interaction-tests" + }, "/packages/storybook/documents/storybook-composition-setup": { "id": "storybook-composition-setup", "name": "Setting up Storybook Composition with Nx", diff --git a/docs/generated/packages-metadata.json b/docs/generated/packages-metadata.json index 80f67f8517a1c..20013fa4e1411 100644 --- a/docs/generated/packages-metadata.json +++ b/docs/generated/packages-metadata.json @@ -2416,6 +2416,17 @@ "tags": [], "originalFilePath": "shared/packages/storybook/custom-builder-configs" }, + { + "id": "storybook-interaction-tests", + "name": "Setting up Storybook Interaction Tests with Nx", + "description": "This guide explains how you can set up Storybook interaction tests on your Nx workspace.", + "file": "generated/packages/storybook/documents/storybook-interaction-tests", + "itemList": [], + "isExternal": false, + "path": "storybook/documents/storybook-interaction-tests", + "tags": [], + "originalFilePath": "shared/packages/storybook/interaction-tests" + }, { "id": "storybook-composition-setup", "name": "Setting up Storybook Composition with Nx", diff --git a/docs/generated/packages/angular/generators/stories.json b/docs/generated/packages/angular/generators/stories.json index dfc6a8a68701a..60b86a13beebf 100644 --- a/docs/generated/packages/angular/generators/stories.json +++ b/docs/generated/packages/angular/generators/stories.json @@ -54,7 +54,7 @@ }, "additionalProperties": false, "required": ["name"], - "examplesFile": "This generator will generate stories for all your components in your project. The stories will be generated using [Component Story Format 3 (CSF3)](https://storybook.js.org/blog/storybook-csf3-is-here/).\n\n```bash\nnx g @nx/angular:stories project-name\n```\n\nYou can read more about how this generator works, in the [Storybook for Angular overview page](/packages/storybook/documents/overview-angular#auto-generate-stories).\n\nWhen running this generator, you will be prompted to provide the following:\n\n- The `name` of the project you want to generate the configuration for.\n- Whether you want to `generateCypressSpecs`. If you choose `yes`, a test file is going to be generated in the project's Cypress e2e app for each of your components.\n\nYou must provide a `name` for the generator to work.\n\nThere are a number of other options available. Let's take a look at some examples.\n\n## Examples\n\n### Ignore certain paths when generating stories\n\n```bash\nnx g @nx/angular:stories ui --ignorePaths=libs/ui/src/not-stories/**,**/**/src/**/*.other.*\n```\n\nThis will generate stories for all the components in the `ui` project, except for the ones in the `libs/ui/src/not-stories` directory, and also for components that their file name is of the pattern `*.other.*`.\n\nThis is useful if you have a project that contains components that are not meant to be used in isolation, but rather as part of a larger component.\n", + "examplesFile": "This generator will generate stories for all your components in your project. The stories will be generated using [Component Story Format 3 (CSF3)](https://storybook.js.org/blog/storybook-csf3-is-here/).\n\n```bash\nnx g @nx/angular:stories project-name\n```\n\nYou can read more about how this generator works, in the [Storybook for Angular overview page](/packages/storybook/documents/overview-angular#auto-generate-stories).\n\nWhen running this generator, you will be prompted to provide the following:\n\n- The `name` of the project you want to generate the configuration for.\n- Whether you want to set up [Storybook interaction tests](https://storybook.js.org/docs/angular/writing-tests/interaction-testing) (`interactionTests`). If you choose `yes`, a `play` function will be added to your stories, and all the necessary dependencies will be installed. You can read more about this in the [Nx Storybook interaction tests documentation page](/packages/storybook/documents/interaction-tests).\n\nYou must provide a `name` for the generator to work.\n\nBy default, this generator will also set up [Storybook interaction tests](https://storybook.js.org/docs/angular/writing-tests/interaction-testing). If you don't want to set up Storybook interaction tests, you can pass the `--interactionTests=false` option, but it's not recommended.\n\nThere are a number of other options available. Let's take a look at some examples.\n\n## Examples\n\n### Ignore certain paths when generating stories\n\n```bash\nnx g @nx/angular:stories ui --ignorePaths=libs/ui/src/not-stories/**,**/**/src/**/*.other.*\n```\n\nThis will generate stories for all the components in the `ui` project, except for the ones in the `libs/ui/src/not-stories` directory, and also for components that their file name is of the pattern `*.other.*`.\n\nThis is useful if you have a project that contains components that are not meant to be used in isolation, but rather as part of a larger component.\n", "presets": [] }, "description": "Creates stories/specs for all components declared in a project.", diff --git a/docs/generated/packages/angular/generators/storybook-configuration.json b/docs/generated/packages/angular/generators/storybook-configuration.json index 2bc412f40ddf3..485de50efcbed 100644 --- a/docs/generated/packages/angular/generators/storybook-configuration.json +++ b/docs/generated/packages/angular/generators/storybook-configuration.json @@ -85,7 +85,7 @@ }, "additionalProperties": false, "required": ["name"], - "examplesFile": "This generator will set up Storybook for your **Angular** project. By default, starting Nx 16, Storybook v7 is used.\n\n```bash\nnx g @nx/angular:storybook-configuration project-name\n```\n\nYou can read more about how this generator works, in the [Storybook for Angular overview page](/packages/storybook/documents/overview-angular#generate-storybook-configuration-for-an-angular-project).\n\nWhen running this generator, you will be prompted to provide the following:\n\n- The `name` of the project you want to generate the configuration for.\n- Whether you want to `configureCypress`. If you choose `yes`, a Cypress e2e app will be created (or configured) to run against the project's Storybook instance. You can read more about this in the [Storybook for Angular - Cypress section](/packages/storybook/documents/overview-angular#cypress-tests-for-stories).\n- Whether you want to `generateStories` for the components in your project. If you choose `yes`, a `.stories.ts` file will be generated next to each of your components in your project.\n- Whether you want to `generateCypressSpecs`. If you choose `yes`, a test file is going to be generated in the project's Cypress e2e app for each of your components.\n- Whether you want to `configureTestRunner`. If you choose `yes`, a `test-storybook` target will be generated in your project's `project.json`, with a command to invoke the [Storybook `test-runner`](https://storybook.js.org/docs/react/writing-tests/test-runner).\n\nYou must provide a `name` for the generator to work.\n\nThere are a number of other options available. Let's take a look at some examples.\n\n## Examples\n\n### Generate Storybook configuration\n\n```bash\nnx g @nx/angular:storybook-configuration ui\n```\n\nThis will generate Storybook configuration for the `ui` project.\n\n### Generate Storybook configuration using TypeScript\n\n```bash\nnx g @nx/angular:storybook-configuration ui --tsConfiguration=true\n```\n\nThis will generate Storybook configuration for the `ui` project using TypeScript for the Storybook configuration files (the files inside the `.storybook` directory, eg. `.storybook/main.ts`).\n\n### Ignore certain paths when generating stories\n\n```bash\nnx g @nx/angular:storybook-configuration ui --generateStories=true --ignorePaths=libs/ui/src/not-stories/**,**/**/src/**/*.other.*,apps/my-app/**/*.something.ts\n```\n\nThis will generate a Storybook configuration for the `ui` project and generate stories for all components in the `libs/ui/src/lib` directory, except for the ones in the `libs/ui/src/not-stories` directory, and the ones in the `apps/my-app` directory that end with `.something.ts`, and also for components that their file name is of the pattern `*.other.*`.\n\nThis is useful if you have a project that contains components that are not meant to be used in isolation, but rather as part of a larger component.\n", + "examplesFile": "This generator will set up Storybook for your **Angular** project. By default, starting Nx 16, Storybook v7 is used.\n\n```bash\nnx g @nx/angular:storybook-configuration project-name\n```\n\nYou can read more about how this generator works, in the [Storybook for Angular overview page](/packages/storybook/documents/overview-angular#generate-storybook-configuration-for-an-angular-project).\n\nWhen running this generator, you will be prompted to provide the following:\n\n- The `name` of the project you want to generate the configuration for.\n- Whether you want to set up [Storybook interaction tests](https://storybook.js.org/docs/angular/writing-tests/interaction-testing) (`interactionTests`). If you choose `yes`, a `play` function will be added to your stories, and all the necessary dependencies will be installed. Also, a `test-storybook` target will be generated in your project's `project.json`, with a command to invoke the [Storybook `test-runner`](https://storybook.js.org/docs/angular/writing-tests/test-runner). You can read more about this in the [Nx Storybook interaction tests documentation page](/packages/storybook/documents/interaction-tests).\n- Whether you want to `generateStories` for the components in your project. If you choose `yes`, a `.stories.ts` file will be generated next to each of your components in your project.\n\nYou must provide a `name` for the generator to work.\n\nBy default, this generator will also set up [Storybook interaction tests](https://storybook.js.org/docs/angular/writing-tests/interaction-testing). If you don't want to set up Storybook interaction tests, you can pass the `--interactionTests=false` option, but it's not recommended.\n\nThere are a number of other options available. Let's take a look at some examples.\n\n## Examples\n\n### Generate Storybook configuration\n\n```bash\nnx g @nx/angular:storybook-configuration ui\n```\n\nThis will generate Storybook configuration for the `ui` project using TypeScript for the Storybook configuration files (the files inside the `.storybook` directory, eg. `.storybook/main.ts`).\n\n### Ignore certain paths when generating stories\n\n```bash\nnx g @nx/angular:storybook-configuration ui --generateStories=true --ignorePaths=libs/ui/src/not-stories/**,**/**/src/**/*.other.*,apps/my-app/**/*.something.ts\n```\n\nThis will generate a Storybook configuration for the `ui` project and generate stories for all components in the `libs/ui/src/lib` directory, except for the ones in the `libs/ui/src/not-stories` directory, and the ones in the `apps/my-app` directory that end with `.something.ts`, and also for components that their file name is of the pattern `*.other.*`.\n\nThis is useful if you have a project that contains components that are not meant to be used in isolation, but rather as part of a larger component.\n\n### Generate Storybook configuration using JavaScript\n\n```bash\nnx g @nx/angular:storybook-configuration ui --tsConfiguration=false\n```\n\nBy default, our generator generates TypeScript Storybook configuration files. You can choose to use JavaScript for the Storybook configuration files of your project (the files inside the `.storybook` directory, eg. `.storybook/main.js`).\n", "presets": [] }, "description": "Adds Storybook configuration to a project.", diff --git a/docs/generated/packages/react/generators/stories.json b/docs/generated/packages/react/generators/stories.json index a5d7a226482ba..3fe7c00699952 100644 --- a/docs/generated/packages/react/generators/stories.json +++ b/docs/generated/packages/react/generators/stories.json @@ -57,7 +57,7 @@ } }, "required": ["project"], - "examplesFile": "This generator will generate stories for all your components in your project. The stories will be generated using [Component Story Format 3 (CSF3)](https://storybook.js.org/blog/storybook-csf3-is-here/).\n\n```bash\nnx g @nx/react:stories project-name\n```\n\nYou can read more about how this generator works, in the [Storybook for React overview page](/packages/storybook/documents/overview-react#auto-generate-stories).\n\nWhen running this generator, you will be prompted to provide the following:\n\n- The `name` of the project you want to generate the configuration for.\n- Whether you want to `generateCypressSpecs`. If you choose `yes`, a test file is going to be generated in the project's Cypress e2e app for each of your components.\n\nYou must provide a `name` for the generator to work.\n\nThere are a number of other options available. Let's take a look at some examples.\n\n## Examples\n\n### Ignore certain paths when generating stories\n\n```bash\nnx g @nx/react:stories --name=ui --ignorePaths=libs/ui/src/not-stories/**,**/**/src/**/*.other.*\n```\n\nThis will generate stories for all the components in the `ui` project, except for the ones in the `libs/ui/src/not-stories` directory, and also for components that their file name is of the pattern `*.other.*`.\n\nThis is useful if you have a project that contains components that are not meant to be used in isolation, but rather as part of a larger component.\n\n### Generate stories using JavaScript instead of TypeScript\n\n```bash\nnx g @nx/react:stories --name=ui --js=true\n```\n\nThis will generate stories for all the components in the `ui` project using JavaScript instead of TypeScript. So, you will have `.stories.js` files next to your components.\n", + "examplesFile": "This generator will generate stories for all your components in your project. The stories will be generated using [Component Story Format 3 (CSF3)](https://storybook.js.org/blog/storybook-csf3-is-here/).\n\n```bash\nnx g @nx/react:stories project-name\n```\n\nYou can read more about how this generator works, in the [Storybook for React overview page](/packages/storybook/documents/overview-react#auto-generate-stories).\n\nWhen running this generator, you will be prompted to provide the following:\n\n- The `name` of the project you want to generate the configuration for.\n- Whether you want to set up [Storybook interaction tests](https://storybook.js.org/docs/angular/writing-tests/interaction-testing) (`interactionTests`). If you choose `yes`, a `play` function will be added to your stories, and all the necessary dependencies will be installed. You can read more about this in the [Nx Storybook interaction tests documentation page](/packages/storybook/documents/interaction-tests)..\n\nYou must provide a `name` for the generator to work.\n\nBy default, this generator will also set up [Storybook interaction tests](https://storybook.js.org/docs/angular/writing-tests/interaction-testing). If you don't want to set up Storybook interaction tests, you can pass the `--interactionTests=false` option, but it's not recommended.\n\nThere are a number of other options available. Let's take a look at some examples.\n\n## Examples\n\n### Ignore certain paths when generating stories\n\n```bash\nnx g @nx/react:stories --name=ui --ignorePaths=libs/ui/src/not-stories/**,**/**/src/**/*.other.*\n```\n\nThis will generate stories for all the components in the `ui` project, except for the ones in the `libs/ui/src/not-stories` directory, and also for components that their file name is of the pattern `*.other.*`.\n\nThis is useful if you have a project that contains components that are not meant to be used in isolation, but rather as part of a larger component.\n\n### Generate stories using JavaScript instead of TypeScript\n\n```bash\nnx g @nx/react:stories --name=ui --js=true\n```\n\nThis will generate stories for all the components in the `ui` project using JavaScript instead of TypeScript. So, you will have `.stories.js` files next to your components.\n", "presets": [] }, "description": "Create stories/specs for all components declared in an app or library.", diff --git a/docs/generated/packages/react/generators/storybook-configuration.json b/docs/generated/packages/react/generators/storybook-configuration.json index 452aaf66a3a60..bae3614598e5c 100644 --- a/docs/generated/packages/react/generators/storybook-configuration.json +++ b/docs/generated/packages/react/generators/storybook-configuration.json @@ -82,7 +82,7 @@ } }, "required": ["name"], - "examplesFile": "This generator will set up Storybook for your **React** project. You can also use this generator to generate Storybook configuration for your **Next.js** project. By default, starting Nx 16, Storybook v7 is used.\n\n```bash\nnx g @nx/react:storybook-configuration project-name\n```\n\nYou can read more about how this generator works, in the [Storybook for React overview page](/packages/storybook/documents/overview-react#generate-storybook-configuration-for-an-react-project).\n\nWhen running this generator, you will be prompted to provide the following:\n\n- The `name` of the project you want to generate the configuration for.\n- Whether you want to `configureCypress`. If you choose `yes`, a Cypress e2e app will be created (or configured) to run against the project's Storybook instance. You can read more about this in the [Storybook for React - Cypress section](/packages/storybook/documents/overview-react#cypress-tests-for-stories).\n- Whether you want to `generateStories` for the components in your project. If you choose `yes`, a `.stories.ts` file will be generated next to each of your components in your project.\n- Whether you want to `generateCypressSpecs`. If you choose `yes`, a test file is going to be generated in the project's Cypress e2e app for each of your components.\n- Whether you want to `configureTestRunner`. If you choose `yes`, a `test-storybook` target will be generated in your project's `project.json`, with a command to invoke the [Storybook `test-runner`](https://storybook.js.org/docs/react/writing-tests/test-runner).\n\nYou must provide a `name` for the generator to work.\n\nThere are a number of other options available. Let's take a look at some examples.\n\n## Examples\n\n### Generate Storybook configuration\n\n```bash\nnx g @nx/react:storybook-configuration ui\n```\n\nThis will generate Storybook configuration for the `ui` project.\n\n### Generate Storybook configuration using TypeScript\n\n```bash\nnx g @nx/react:storybook-configuration ui --tsConfiguration=true\n```\n\nThis will generate Storybook configuration for the `ui` project using TypeScript for the Storybook configuration files (the files inside the `.storybook` directory, eg. `.storybook/main.ts`).\n\n### Ignore certain paths when generating stories\n\n```bash\nnx g @nx/react:storybook-configuration ui --generateStories=true --ignorePaths=libs/ui/src/not-stories/**,**/**/src/**/*.other.*,apps/my-app/**/*.something.ts\n```\n\nThis will generate a Storybook configuration for the `ui` project and generate stories for all components in the `libs/ui/src/lib` directory, except for the ones in the `libs/ui/src/not-stories` directory, and the ones in the `apps/my-app` directory that end with `.something.ts`, and also for components that their file name is of the pattern `*.other.*`.\n\nThis is useful if you have a project that contains components that are not meant to be used in isolation, but rather as part of a larger component.\n\n### Generate stories using JavaScript instead of TypeScript\n\n```bash\nnx g @nx/react:storybook-configuration ui --generateStories=true --js=true\n```\n\nThis will generate stories for all the components in the `ui` project using JavaScript instead of TypeScript. So, you will have `.stories.js` files next to your components.\n", + "examplesFile": "This generator will set up Storybook for your **React** project. You can also use this generator to generate Storybook configuration for your **Next.js** project. By default, starting Nx 16, Storybook v7 is used.\n\n```bash\nnx g @nx/react:storybook-configuration project-name\n```\n\nYou can read more about how this generator works, in the [Storybook for React overview page](/packages/storybook/documents/overview-react#generate-storybook-configuration-for-an-react-project).\n\nWhen running this generator, you will be prompted to provide the following:\n\n- The `name` of the project you want to generate the configuration for.\n- Whether you want to set up [Storybook interaction tests](https://storybook.js.org/docs/react/writing-tests/interaction-testing) (`interactionTests`). If you choose `yes`, a `play` function will be added to your stories, and all the necessary dependencies will be installed. Also, a `test-storybook` target will be generated in your project's `project.json`, with a command to invoke the [Storybook `test-runner`](https://storybook.js.org/docs/react/writing-tests/test-runner). You can read more about this in the [Nx Storybook interaction tests documentation page](/packages/storybook/documents/interaction-tests)..\n- Whether you want to `generateStories` for the components in your project. If you choose `yes`, a `.stories.ts` file will be generated next to each of your components in your project.\n\nYou must provide a `name` for the generator to work.\n\nBy default, this generator will also set up [Storybook interaction tests](https://storybook.js.org/docs/react/writing-tests/interaction-testing). If you don't want to set up Storybook interaction tests, you can pass the `--interactionTests=false` option, but it's not recommended.\n\nThere are a number of other options available. Let's take a look at some examples.\n\n## Examples\n\n### Generate Storybook configuration\n\n```bash\nnx g @nx/react:storybook-configuration ui\n```\n\nThis will generate Storybook configuration for the `ui` project using TypeScript for the Storybook configuration files (the files inside the `.storybook` directory, eg. `.storybook/main.ts`).\n\n### Ignore certain paths when generating stories\n\n```bash\nnx g @nx/react:storybook-configuration ui --generateStories=true --ignorePaths=libs/ui/src/not-stories/**,**/**/src/**/*.other.*,apps/my-app/**/*.something.ts\n```\n\nThis will generate a Storybook configuration for the `ui` project and generate stories for all components in the `libs/ui/src/lib` directory, except for the ones in the `libs/ui/src/not-stories` directory, and the ones in the `apps/my-app` directory that end with `.something.ts`, and also for components that their file name is of the pattern `*.other.*`.\n\nThis is useful if you have a project that contains components that are not meant to be used in isolation, but rather as part of a larger component.\n\n### Generate stories using JavaScript instead of TypeScript\n\n```bash\nnx g @nx/react:storybook-configuration ui --generateStories=true --js=true\n```\n\nThis will generate stories for all the components in the `ui` project using JavaScript instead of TypeScript. So, you will have `.stories.js` files next to your components.\n\n### Generate Storybook configuration using JavaScript\n\n```bash\nnx g @nx/react:storybook-configuration ui --tsConfiguration=false\n```\n\nBy default, our generator generates TypeScript Storybook configuration files. You can choose to use JavaScript for the Storybook configuration files of your project (the files inside the `.storybook` directory, eg. `.storybook/main.js`).\n", "presets": [] }, "description": "Set up storybook for a React app or library.", diff --git a/docs/generated/packages/storybook/documents/storybook-interaction-tests.md b/docs/generated/packages/storybook/documents/storybook-interaction-tests.md new file mode 100644 index 0000000000000..b09cbe9ea2421 --- /dev/null +++ b/docs/generated/packages/storybook/documents/storybook-interaction-tests.md @@ -0,0 +1,138 @@ +--- +title: Setting up Storybook Interaction Tests with Nx +description: This guide explains how you can set up Storybook interaction tests on your Nx workspace. +--- + +# Setting up Storybook Interaction Tests with Nx + +[Storybook interaction tests](https://storybook.js.org/docs/react/writing-tests/interaction-testing) allow you to test user interactions within your Storybook stories. It enhances your [Storybook](https://storybook.js.org/) setup, ensuring that not only do your components look right, but they also work correctly when interacted with. + +You can read more about Storybook interaction tests in the following sections of the Storybook documentation: + +- [Storybook interaction tests for React](https://storybook.js.org/docs/react/writing-tests/interaction-testing) +- [Storybook interaction tests for Angular](https://storybook.js.org/docs/angular/writing-tests/interaction-testing) +- [Storybook test runner](https://storybook.js.org/docs/react/writing-tests/test-runner) +- [The `play` function](https://storybook.js.org/docs/react/writing-stories/play-function) + +{% callout type="warning" title="Set up Storybook in your workspace" %} +You first need to set up Storybook for your Nx workspace, if you haven't already. You can read the [Storybook plugin overview guide](/packages/storybook) to get started. +{% /callout %} + +## Setup Storybook Interaction Tests + +During the setup, you'll be prompted about setting up interaction tests. Choose `yes` when asked if you want to set up Storybook interaction tests. + +The `--interactionTests` flag is true by default, so when you're setting up Storybook, you can just press enter to accept the default value, or even pass the flag directly. Make sure to use the framework-specific generators, so that you also get your stories set up correctly: + +{% tabs %} +{% tab label="Angular" %} + +```shell +nx g @nx/angular:storybook-configuration project-name --interactionTests=true +``` + +{% /tab %} +{% tab label="React" %} + +```shell +nx g @nx/react:storybook-configuration project-name --interactionTests=true +``` + +{% /tab %} +{% tab label="No framework" %} + +```shell +nx g @nx/storybook:configuration project-name --interactionTests=true +``` + +{% /tab %} +{% /tabs %} + +This command will: + +- [Set up Storybook for your project](/packages/storybook) - including the `@storybook/addon-interactions` addon. +- Add a `play` function to your stories. +- Install the necessary dependencies. +- Generate a `test-storybook` target in your project's `project.json`, which has a command to invoke the Storybook test runner. + +## Writing an Interaction Test + +The Nx generator will create a very simple interaction test for you. You can find it in the `.stories.ts` file for your component. This test will only be asserting if some text exists in your component. +You can modify it to suit your needs. + +Let's take an example of a simple React component for a button: + +```typescript +import React, { useState } from 'react'; + +export function Button() { + const [count, setCount] = useState(0); + + const handleClick = () => { + setCount(count + 1); + }; + + return ( + + ); +} + +export default Button; +``` + +In your `.stories.ts` file for that component, you can use the play function to simulate interactions. For example: + +```typescript +export const ButtonClicked: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + const button = canvas.getByRole('button'); + await userEvent.click(button); + expect(canvas.getByRole('button').innerText).toBe( + "You've clicked me 1 times" + ); + await userEvent.click(button); + expect(canvas.getByRole('button').innerText).toBe( + "You've clicked me 2 times" + ); + }, +}; +``` + +Here, the play function is simulating a click on the button using the `userEvent.click` method. It is then asserting that the button's text has changed to reflect the number of times it has been clicked. + +You can read more about how to write interaction tests in the [Storybook documentation](https://storybook.js.org/docs/react/writing-tests/interaction-testing). + +## Running Interaction Tests + +To run the interaction tests, you can use the `test-storybook` target that was generated for your project: + +```bash +nx test-storybook project-name +``` + +Make sure you have Storybook running in another tab, so that the test runner can connect to it: + +```bash +nx storybook project-name +``` + +## Interaction Tests vs. Cypress E2E Tests + +As the landscape of testing has evolves, we are also adjusting our approach to testing in Nx, and the Storybook generators. Nx has been consistently suggesting the use of Cypress for e2e tests in conjunction with Storybook. This approach, while effective, had its own challenges. A new, separate e2e project would be generated, and setup specifically to work with Storybook, leading to a bifurcated setup: your component stories in one place, and the e2e tests that validated them in another. + +However, with the introduction of Storybook Interaction Tests, this approach can be simplified. This new feature allows developers to integrate tests directly within the stories they are already creating, making the development and testing process more straightforward. Why maintain two separate projects or setups when you can do everything in one place? + +Choosing to promote Storybook Interaction Tests over the previous Cypress e2e setup was not a decision made lightly. Here's why we believe it's a beneficial shift: + +- **Unified Workflow:** Interaction tests allow developers to keep their focus on one tool. Instead of juggling between Storybook and a separate e2e project, everything is integrated. This means quicker iterations and a simplified dev experience. + +- **Leaner Project Structure:** Avoiding the need to generate a separate e2e project means fewer files, less configuration, and a more straightforward project structure. This can make onboarding new developers or navigating the codebase simpler. + +- **Optimized Performance:** Interaction tests are lightweight and quick to execute compared to traditional e2e tests. They run directly in the context of the component story, ensuring that tests are precise and fast. + +- **Consistency:** Keeping the stories and their associated tests together ensures a tighter bond between what's developed and what's tested. It reduces the chances of tests becoming outdated or misaligned with the component's actual behavior. + +Because of these benefits, it made sense for our Storybook configuration generator to switch from the Cypress e2e + Storybook combination to the integrated approach of Storybook Interaction Tests. By integrating e2e-like tests into the existing Storybook setup, we offer developers a smoother, more efficient, and simpler setup and testing experience. diff --git a/docs/generated/packages/storybook/generators/configuration.json b/docs/generated/packages/storybook/generators/configuration.json index 3f8f207e66c5d..c36a985add65f 100644 --- a/docs/generated/packages/storybook/generators/configuration.json +++ b/docs/generated/packages/storybook/generators/configuration.json @@ -104,7 +104,7 @@ } }, "required": ["name", "uiFramework"], - "examplesFile": "---\ntitle: Storybook configuration generator examples\ndescription: This page contains examples for the @nx/storybook:configuration generator.\n---\n\nThis is a framework-agnostic generator for setting up Storybook configuration for a project.\n\n```bash\nnx g @nx/storybook:configuration\n```\n\nStarting Nx 16, Nx does not support Storybook v6 any more. So, Nx will configure your project to use Storybook v7. If you are not on Storybook 7 yet, please migrate. You can read more about how to migrate to Storybook 7 in our [Storybook 7 migration generator](/packages/storybook/generators/migrate-7) guide.\n\nWhen running this generator, you will be prompted to provide the following:\n\n- The `name` of the project you want to generate the configuration for.\n- The `uiFramework` you want to use. Supported values are:\n - `@storybook/angular`\n - `@storybook/html-webpack5`\n - `@storybook/nextjs`\n - `@storybook/preact-webpack5`\n - `@storybook/react-webpack5`\n - `@storybook/react-vite`\n - `@storybook/server-webpack5`\n - `@storybook/svelte-webpack5`\n - `@storybook/svelte-vite`\n - `@storybook/sveltekit`\n - `@storybook/vue-webpack5`\n - `@storybook/vue-vite`\n - `@storybook/vue3-webpack5`\n - `@storybook/vue3-vite`\n - `@storybook/web-components-webpack5`\n - `@storybook/web-components-vite`\n- Whether you want to `configureCypress`. If you choose `yes`, a Cypress e2e app will be created (or configured) to run against the project's Storybook instance.\n- Whether you want to `configureTestRunner`. If you choose `yes`, a `test-storybook` target will be generated in your project's `project.json`, with a command to invoke the [Storybook `test-runner`](https://storybook.js.org/docs/react/writing-tests/test-runner).\n\nYou must provide a `name` and a `uiFramework` for the generator to work.\n\nYou can read more about how this generator works, in the [Storybook package overview page](/packages/storybook#generating-storybook-configuration).\n\nIf you are using Angular, React, React Native or Next.js in your project, it's best to use the framework specific generator:\n\n- [React Storybook Configuration Generator](/packages/react/generators/storybook-configuration) (React and Next.js projects)\n\n- [Angular Storybook Configuration Generator](/packages/angular/generators/storybook-configuration)\n\n- [React Native Storybook Configuration Generator](/packages/react-native/generators/storybook-configuration)\n\n## Examples\n\n### Generate Storybook configuration using TypeScript\n\n```bash\nnx g @nx/storybook:configuration ui --uiFramework=@storybook/web-components-vite --tsConfiguration=true\n```\n\nThis will generate a Storybook configuration for the `ui` project using TypeScript for the Storybook configuration files (the files inside the `.storybook` directory).\n", + "examplesFile": "---\ntitle: Storybook configuration generator examples\ndescription: This page contains examples for the @nx/storybook:configuration generator.\n---\n\nThis is a framework-agnostic generator for setting up Storybook configuration for a project.\n\n```bash\nnx g @nx/storybook:configuration\n```\n\nStarting Nx 16, Nx does not support Storybook v6 any more. So, Nx will configure your project to use Storybook v7. If you are not on Storybook 7 yet, please migrate. You can read more about how to migrate to Storybook 7 in our [Storybook 7 migration generator](/packages/storybook/generators/migrate-7) guide.\n\nWhen running this generator, you will be prompted to provide the following:\n\n- The `name` of the project you want to generate the configuration for.\n- The `uiFramework` you want to use. Supported values are:\n - `@storybook/angular`\n - `@storybook/html-webpack5`\n - `@storybook/nextjs`\n - `@storybook/preact-webpack5`\n - `@storybook/react-webpack5`\n - `@storybook/react-vite`\n - `@storybook/server-webpack5`\n - `@storybook/svelte-webpack5`\n - `@storybook/svelte-vite`\n - `@storybook/sveltekit`\n - `@storybook/vue-webpack5`\n - `@storybook/vue-vite`\n - `@storybook/vue3-webpack5`\n - `@storybook/vue3-vite`\n - `@storybook/web-components-webpack5`\n - `@storybook/web-components-vite`\n- Whether you want to set up [Storybook interaction tests](https://storybook.js.org/docs/angular/writing-tests/interaction-testing) (`interactionTests`). If you choose `yes`, all the necessary dependencies will be installed. Also, a `test-storybook` target will be generated in your project's `project.json`, with a command to invoke the [Storybook `test-runner`](https://storybook.js.org/docs/angular/writing-tests/test-runner). You can read more about this in the [Nx Storybook interaction tests documentation page](/packages/storybook/documents/interaction-tests).\n\nYou must provide a `name` and a `uiFramework` for the generator to work.\n\nYou can read more about how this generator works, in the [Storybook package overview page](/packages/storybook#generating-storybook-configuration).\n\nIf you are using Angular, React, React Native or Next.js in your project, it's best to use the framework specific generator:\n\n- [React Storybook Configuration Generator](/packages/react/generators/storybook-configuration) (React and Next.js projects)\n\n- [Angular Storybook Configuration Generator](/packages/angular/generators/storybook-configuration)\n\n- [React Native Storybook Configuration Generator](/packages/react-native/generators/storybook-configuration)\n\n## Examples\n\n### Generate Storybook configuration using JavaScript\n\n```bash\nnx g @nx/storybook:configuration ui --uiFramework=@storybook/web-components-vite --tsConfiguration=false\n```\n\nBy default, our generator generates TypeScript Storybook configuration files. You can choose to use JavaScript for the Storybook configuration files of your project (the files inside the `.storybook` directory, eg. `.storybook/main.js`).\n", "presets": [] }, "description": "Add Storybook configuration to a UI library or an application.", diff --git a/docs/map.json b/docs/map.json index 4bb555750f4ab..cbcbaa2620221 100644 --- a/docs/map.json +++ b/docs/map.json @@ -1936,6 +1936,12 @@ "description": "This guide explains how to customize the webpack configuration and your vite configuration for Storybook.", "file": "shared/packages/storybook/custom-builder-configs" }, + { + "id": "storybook-interaction-tests", + "name": "Setting up Storybook Interaction Tests with Nx", + "description": "This guide explains how you can set up Storybook interaction tests on your Nx workspace.", + "file": "shared/packages/storybook/interaction-tests" + }, { "id": "storybook-composition-setup", "name": "Setting up Storybook Composition with Nx", diff --git a/docs/shared/packages/storybook/interaction-tests.md b/docs/shared/packages/storybook/interaction-tests.md new file mode 100644 index 0000000000000..b09cbe9ea2421 --- /dev/null +++ b/docs/shared/packages/storybook/interaction-tests.md @@ -0,0 +1,138 @@ +--- +title: Setting up Storybook Interaction Tests with Nx +description: This guide explains how you can set up Storybook interaction tests on your Nx workspace. +--- + +# Setting up Storybook Interaction Tests with Nx + +[Storybook interaction tests](https://storybook.js.org/docs/react/writing-tests/interaction-testing) allow you to test user interactions within your Storybook stories. It enhances your [Storybook](https://storybook.js.org/) setup, ensuring that not only do your components look right, but they also work correctly when interacted with. + +You can read more about Storybook interaction tests in the following sections of the Storybook documentation: + +- [Storybook interaction tests for React](https://storybook.js.org/docs/react/writing-tests/interaction-testing) +- [Storybook interaction tests for Angular](https://storybook.js.org/docs/angular/writing-tests/interaction-testing) +- [Storybook test runner](https://storybook.js.org/docs/react/writing-tests/test-runner) +- [The `play` function](https://storybook.js.org/docs/react/writing-stories/play-function) + +{% callout type="warning" title="Set up Storybook in your workspace" %} +You first need to set up Storybook for your Nx workspace, if you haven't already. You can read the [Storybook plugin overview guide](/packages/storybook) to get started. +{% /callout %} + +## Setup Storybook Interaction Tests + +During the setup, you'll be prompted about setting up interaction tests. Choose `yes` when asked if you want to set up Storybook interaction tests. + +The `--interactionTests` flag is true by default, so when you're setting up Storybook, you can just press enter to accept the default value, or even pass the flag directly. Make sure to use the framework-specific generators, so that you also get your stories set up correctly: + +{% tabs %} +{% tab label="Angular" %} + +```shell +nx g @nx/angular:storybook-configuration project-name --interactionTests=true +``` + +{% /tab %} +{% tab label="React" %} + +```shell +nx g @nx/react:storybook-configuration project-name --interactionTests=true +``` + +{% /tab %} +{% tab label="No framework" %} + +```shell +nx g @nx/storybook:configuration project-name --interactionTests=true +``` + +{% /tab %} +{% /tabs %} + +This command will: + +- [Set up Storybook for your project](/packages/storybook) - including the `@storybook/addon-interactions` addon. +- Add a `play` function to your stories. +- Install the necessary dependencies. +- Generate a `test-storybook` target in your project's `project.json`, which has a command to invoke the Storybook test runner. + +## Writing an Interaction Test + +The Nx generator will create a very simple interaction test for you. You can find it in the `.stories.ts` file for your component. This test will only be asserting if some text exists in your component. +You can modify it to suit your needs. + +Let's take an example of a simple React component for a button: + +```typescript +import React, { useState } from 'react'; + +export function Button() { + const [count, setCount] = useState(0); + + const handleClick = () => { + setCount(count + 1); + }; + + return ( + + ); +} + +export default Button; +``` + +In your `.stories.ts` file for that component, you can use the play function to simulate interactions. For example: + +```typescript +export const ButtonClicked: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + const button = canvas.getByRole('button'); + await userEvent.click(button); + expect(canvas.getByRole('button').innerText).toBe( + "You've clicked me 1 times" + ); + await userEvent.click(button); + expect(canvas.getByRole('button').innerText).toBe( + "You've clicked me 2 times" + ); + }, +}; +``` + +Here, the play function is simulating a click on the button using the `userEvent.click` method. It is then asserting that the button's text has changed to reflect the number of times it has been clicked. + +You can read more about how to write interaction tests in the [Storybook documentation](https://storybook.js.org/docs/react/writing-tests/interaction-testing). + +## Running Interaction Tests + +To run the interaction tests, you can use the `test-storybook` target that was generated for your project: + +```bash +nx test-storybook project-name +``` + +Make sure you have Storybook running in another tab, so that the test runner can connect to it: + +```bash +nx storybook project-name +``` + +## Interaction Tests vs. Cypress E2E Tests + +As the landscape of testing has evolves, we are also adjusting our approach to testing in Nx, and the Storybook generators. Nx has been consistently suggesting the use of Cypress for e2e tests in conjunction with Storybook. This approach, while effective, had its own challenges. A new, separate e2e project would be generated, and setup specifically to work with Storybook, leading to a bifurcated setup: your component stories in one place, and the e2e tests that validated them in another. + +However, with the introduction of Storybook Interaction Tests, this approach can be simplified. This new feature allows developers to integrate tests directly within the stories they are already creating, making the development and testing process more straightforward. Why maintain two separate projects or setups when you can do everything in one place? + +Choosing to promote Storybook Interaction Tests over the previous Cypress e2e setup was not a decision made lightly. Here's why we believe it's a beneficial shift: + +- **Unified Workflow:** Interaction tests allow developers to keep their focus on one tool. Instead of juggling between Storybook and a separate e2e project, everything is integrated. This means quicker iterations and a simplified dev experience. + +- **Leaner Project Structure:** Avoiding the need to generate a separate e2e project means fewer files, less configuration, and a more straightforward project structure. This can make onboarding new developers or navigating the codebase simpler. + +- **Optimized Performance:** Interaction tests are lightweight and quick to execute compared to traditional e2e tests. They run directly in the context of the component story, ensuring that tests are precise and fast. + +- **Consistency:** Keeping the stories and their associated tests together ensures a tighter bond between what's developed and what's tested. It reduces the chances of tests becoming outdated or misaligned with the component's actual behavior. + +Because of these benefits, it made sense for our Storybook configuration generator to switch from the Cypress e2e + Storybook combination to the integrated approach of Storybook Interaction Tests. By integrating e2e-like tests into the existing Storybook setup, we offer developers a smoother, more efficient, and simpler setup and testing experience. diff --git a/docs/shared/reference/sitemap.md b/docs/shared/reference/sitemap.md index 3ac62d92968d4..3b7c452a730c3 100644 --- a/docs/shared/reference/sitemap.md +++ b/docs/shared/reference/sitemap.md @@ -556,6 +556,7 @@ - [Storybook 7 overview](/packages/storybook/documents/storybook-7-setup) - [Configuring Storybook on Nx](/packages/storybook/documents/configuring-storybook) - [How to configure Webpack and Vite for Storybook](/packages/storybook/documents/custom-builder-configs) + - [Setting up Storybook Interaction Tests with Nx](/packages/storybook/documents/storybook-interaction-tests) - [Setting up Storybook Composition with Nx](/packages/storybook/documents/storybook-composition-setup) - [Angular: Set up Compodoc for Storybook on Nx](/packages/storybook/documents/angular-storybook-compodoc) - [Angular: Configuring styles and preprocessor options](/packages/storybook/documents/angular-configuring-styles) diff --git a/packages/angular/docs/stories-examples.md b/packages/angular/docs/stories-examples.md index ba441dc29df3d..969684d8ceec4 100644 --- a/packages/angular/docs/stories-examples.md +++ b/packages/angular/docs/stories-examples.md @@ -9,10 +9,12 @@ You can read more about how this generator works, in the [Storybook for Angular When running this generator, you will be prompted to provide the following: - The `name` of the project you want to generate the configuration for. -- Whether you want to `generateCypressSpecs`. If you choose `yes`, a test file is going to be generated in the project's Cypress e2e app for each of your components. +- Whether you want to set up [Storybook interaction tests](https://storybook.js.org/docs/angular/writing-tests/interaction-testing) (`interactionTests`). If you choose `yes`, a `play` function will be added to your stories, and all the necessary dependencies will be installed. You can read more about this in the [Nx Storybook interaction tests documentation page](/packages/storybook/documents/interaction-tests). You must provide a `name` for the generator to work. +By default, this generator will also set up [Storybook interaction tests](https://storybook.js.org/docs/angular/writing-tests/interaction-testing). If you don't want to set up Storybook interaction tests, you can pass the `--interactionTests=false` option, but it's not recommended. + There are a number of other options available. Let's take a look at some examples. ## Examples diff --git a/packages/angular/docs/storybook-configuration-examples.md b/packages/angular/docs/storybook-configuration-examples.md index 68c8c3b09eb1e..81fdc92fad260 100644 --- a/packages/angular/docs/storybook-configuration-examples.md +++ b/packages/angular/docs/storybook-configuration-examples.md @@ -9,13 +9,13 @@ You can read more about how this generator works, in the [Storybook for Angular When running this generator, you will be prompted to provide the following: - The `name` of the project you want to generate the configuration for. -- Whether you want to `configureCypress`. If you choose `yes`, a Cypress e2e app will be created (or configured) to run against the project's Storybook instance. You can read more about this in the [Storybook for Angular - Cypress section](/packages/storybook/documents/overview-angular#cypress-tests-for-stories). +- Whether you want to set up [Storybook interaction tests](https://storybook.js.org/docs/angular/writing-tests/interaction-testing) (`interactionTests`). If you choose `yes`, a `play` function will be added to your stories, and all the necessary dependencies will be installed. Also, a `test-storybook` target will be generated in your project's `project.json`, with a command to invoke the [Storybook `test-runner`](https://storybook.js.org/docs/angular/writing-tests/test-runner). You can read more about this in the [Nx Storybook interaction tests documentation page](/packages/storybook/documents/interaction-tests). - Whether you want to `generateStories` for the components in your project. If you choose `yes`, a `.stories.ts` file will be generated next to each of your components in your project. -- Whether you want to `generateCypressSpecs`. If you choose `yes`, a test file is going to be generated in the project's Cypress e2e app for each of your components. -- Whether you want to `configureTestRunner`. If you choose `yes`, a `test-storybook` target will be generated in your project's `project.json`, with a command to invoke the [Storybook `test-runner`](https://storybook.js.org/docs/react/writing-tests/test-runner). You must provide a `name` for the generator to work. +By default, this generator will also set up [Storybook interaction tests](https://storybook.js.org/docs/angular/writing-tests/interaction-testing). If you don't want to set up Storybook interaction tests, you can pass the `--interactionTests=false` option, but it's not recommended. + There are a number of other options available. Let's take a look at some examples. ## Examples @@ -26,14 +26,6 @@ There are a number of other options available. Let's take a look at some example nx g @nx/angular:storybook-configuration ui ``` -This will generate Storybook configuration for the `ui` project. - -### Generate Storybook configuration using TypeScript - -```bash -nx g @nx/angular:storybook-configuration ui --tsConfiguration=true -``` - This will generate Storybook configuration for the `ui` project using TypeScript for the Storybook configuration files (the files inside the `.storybook` directory, eg. `.storybook/main.ts`). ### Ignore certain paths when generating stories @@ -45,3 +37,11 @@ nx g @nx/angular:storybook-configuration ui --generateStories=true --ignorePaths This will generate a Storybook configuration for the `ui` project and generate stories for all components in the `libs/ui/src/lib` directory, except for the ones in the `libs/ui/src/not-stories` directory, and the ones in the `apps/my-app` directory that end with `.something.ts`, and also for components that their file name is of the pattern `*.other.*`. This is useful if you have a project that contains components that are not meant to be used in isolation, but rather as part of a larger component. + +### Generate Storybook configuration using JavaScript + +```bash +nx g @nx/angular:storybook-configuration ui --tsConfiguration=false +``` + +By default, our generator generates TypeScript Storybook configuration files. You can choose to use JavaScript for the Storybook configuration files of your project (the files inside the `.storybook` directory, eg. `.storybook/main.js`). diff --git a/packages/react/docs/stories-examples.md b/packages/react/docs/stories-examples.md index 2767e07ac44a8..3dc1d3956a613 100644 --- a/packages/react/docs/stories-examples.md +++ b/packages/react/docs/stories-examples.md @@ -9,10 +9,12 @@ You can read more about how this generator works, in the [Storybook for React ov When running this generator, you will be prompted to provide the following: - The `name` of the project you want to generate the configuration for. -- Whether you want to `generateCypressSpecs`. If you choose `yes`, a test file is going to be generated in the project's Cypress e2e app for each of your components. +- Whether you want to set up [Storybook interaction tests](https://storybook.js.org/docs/angular/writing-tests/interaction-testing) (`interactionTests`). If you choose `yes`, a `play` function will be added to your stories, and all the necessary dependencies will be installed. You can read more about this in the [Nx Storybook interaction tests documentation page](/packages/storybook/documents/interaction-tests).. You must provide a `name` for the generator to work. +By default, this generator will also set up [Storybook interaction tests](https://storybook.js.org/docs/angular/writing-tests/interaction-testing). If you don't want to set up Storybook interaction tests, you can pass the `--interactionTests=false` option, but it's not recommended. + There are a number of other options available. Let's take a look at some examples. ## Examples diff --git a/packages/react/docs/storybook-configuration-examples.md b/packages/react/docs/storybook-configuration-examples.md index 462c2f85bcba1..bbd36b40bc4f7 100644 --- a/packages/react/docs/storybook-configuration-examples.md +++ b/packages/react/docs/storybook-configuration-examples.md @@ -9,13 +9,13 @@ You can read more about how this generator works, in the [Storybook for React ov When running this generator, you will be prompted to provide the following: - The `name` of the project you want to generate the configuration for. -- Whether you want to `configureCypress`. If you choose `yes`, a Cypress e2e app will be created (or configured) to run against the project's Storybook instance. You can read more about this in the [Storybook for React - Cypress section](/packages/storybook/documents/overview-react#cypress-tests-for-stories). +- Whether you want to set up [Storybook interaction tests](https://storybook.js.org/docs/react/writing-tests/interaction-testing) (`interactionTests`). If you choose `yes`, a `play` function will be added to your stories, and all the necessary dependencies will be installed. Also, a `test-storybook` target will be generated in your project's `project.json`, with a command to invoke the [Storybook `test-runner`](https://storybook.js.org/docs/react/writing-tests/test-runner). You can read more about this in the [Nx Storybook interaction tests documentation page](/packages/storybook/documents/interaction-tests).. - Whether you want to `generateStories` for the components in your project. If you choose `yes`, a `.stories.ts` file will be generated next to each of your components in your project. -- Whether you want to `generateCypressSpecs`. If you choose `yes`, a test file is going to be generated in the project's Cypress e2e app for each of your components. -- Whether you want to `configureTestRunner`. If you choose `yes`, a `test-storybook` target will be generated in your project's `project.json`, with a command to invoke the [Storybook `test-runner`](https://storybook.js.org/docs/react/writing-tests/test-runner). You must provide a `name` for the generator to work. +By default, this generator will also set up [Storybook interaction tests](https://storybook.js.org/docs/react/writing-tests/interaction-testing). If you don't want to set up Storybook interaction tests, you can pass the `--interactionTests=false` option, but it's not recommended. + There are a number of other options available. Let's take a look at some examples. ## Examples @@ -26,14 +26,6 @@ There are a number of other options available. Let's take a look at some example nx g @nx/react:storybook-configuration ui ``` -This will generate Storybook configuration for the `ui` project. - -### Generate Storybook configuration using TypeScript - -```bash -nx g @nx/react:storybook-configuration ui --tsConfiguration=true -``` - This will generate Storybook configuration for the `ui` project using TypeScript for the Storybook configuration files (the files inside the `.storybook` directory, eg. `.storybook/main.ts`). ### Ignore certain paths when generating stories @@ -53,3 +45,11 @@ nx g @nx/react:storybook-configuration ui --generateStories=true --js=true ``` This will generate stories for all the components in the `ui` project using JavaScript instead of TypeScript. So, you will have `.stories.js` files next to your components. + +### Generate Storybook configuration using JavaScript + +```bash +nx g @nx/react:storybook-configuration ui --tsConfiguration=false +``` + +By default, our generator generates TypeScript Storybook configuration files. You can choose to use JavaScript for the Storybook configuration files of your project (the files inside the `.storybook` directory, eg. `.storybook/main.js`). diff --git a/packages/storybook/docs/configuration-generator-examples.md b/packages/storybook/docs/configuration-generator-examples.md index 75aa65edf174e..c21edeeed2618 100644 --- a/packages/storybook/docs/configuration-generator-examples.md +++ b/packages/storybook/docs/configuration-generator-examples.md @@ -31,8 +31,7 @@ When running this generator, you will be prompted to provide the following: - `@storybook/vue3-vite` - `@storybook/web-components-webpack5` - `@storybook/web-components-vite` -- Whether you want to `configureCypress`. If you choose `yes`, a Cypress e2e app will be created (or configured) to run against the project's Storybook instance. -- Whether you want to `configureTestRunner`. If you choose `yes`, a `test-storybook` target will be generated in your project's `project.json`, with a command to invoke the [Storybook `test-runner`](https://storybook.js.org/docs/react/writing-tests/test-runner). +- Whether you want to set up [Storybook interaction tests](https://storybook.js.org/docs/angular/writing-tests/interaction-testing) (`interactionTests`). If you choose `yes`, all the necessary dependencies will be installed. Also, a `test-storybook` target will be generated in your project's `project.json`, with a command to invoke the [Storybook `test-runner`](https://storybook.js.org/docs/angular/writing-tests/test-runner). You can read more about this in the [Nx Storybook interaction tests documentation page](/packages/storybook/documents/interaction-tests). You must provide a `name` and a `uiFramework` for the generator to work. @@ -48,10 +47,10 @@ If you are using Angular, React, React Native or Next.js in your project, it's b ## Examples -### Generate Storybook configuration using TypeScript +### Generate Storybook configuration using JavaScript ```bash -nx g @nx/storybook:configuration ui --uiFramework=@storybook/web-components-vite --tsConfiguration=true +nx g @nx/storybook:configuration ui --uiFramework=@storybook/web-components-vite --tsConfiguration=false ``` -This will generate a Storybook configuration for the `ui` project using TypeScript for the Storybook configuration files (the files inside the `.storybook` directory). +By default, our generator generates TypeScript Storybook configuration files. You can choose to use JavaScript for the Storybook configuration files of your project (the files inside the `.storybook` directory, eg. `.storybook/main.js`). From 35e95f0c539eaf6669d1f478eed96ee09775410f Mon Sep 17 00:00:00 2001 From: Max Kless Date: Thu, 27 Jul 2023 12:44:00 +0200 Subject: [PATCH 205/262] docs(misc): update nx console talk description --- nx-dev/ui-conference/src/lib/conf-schedule-short.tsx | 7 +++---- nx-dev/ui-conference/src/lib/conf-speakers.tsx | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/nx-dev/ui-conference/src/lib/conf-schedule-short.tsx b/nx-dev/ui-conference/src/lib/conf-schedule-short.tsx index 50b275eb778c7..ced760d4829cd 100644 --- a/nx-dev/ui-conference/src/lib/conf-schedule-short.tsx +++ b/nx-dev/ui-conference/src/lib/conf-schedule-short.tsx @@ -162,10 +162,9 @@ export function ConfScheduleShort(): JSX.Element { type: 'event', time: '5:05pm', title: 'Level Up Your Productivity with Nx Console', - description: `In today's fast-paced and demanding software development landscape, maximizing productivity is paramount. Are you seeking ways to enhance your coding efficiency and streamline your development workflows? Look no further than Nx Console! - In this talk, we will explore the powerful capabilities of Nx Console, a game-changing tool designed to supercharge your productivity and seamlessly integrate with popular editors like Visual Studio Code and JetBrains editors (WebStorm, IntelliJ IDEA, PhpStorm). - During the session, we will dive into the key features of Nx Console and demonstrate how it enhances code generation and boosts your ability to navigate and understand complex codebases. - Whether you are a seasoned developer or just starting your coding journey, this talk will provide you with valuable insights and practical tips on how to leverage the full potential of Nx Console in your daily development workflow. Don't miss this opportunity to discover some new features, accelerate your productivity and take your coding prowess to the next level! + description: `Tired of typing endless CLI commands? Can't remember every generator option? Look no further than Nx Console! + Nx Console is a game-changing tool designed to supercharge your productivity and seamlessly integrate with popular editors like Visual Studio Code and JetBrains editors (WebStorm, IntelliJ IDEA, PhpStorm). + We will dive into the key features of Nx Console and demonstrate how it enhances code generation and boosts your ability to navigate and understand complex codebases. Leverage the full potential of Nx Console in your daily development workflow! `, speakers: ['Jonathan Cammisuli', 'Max Kless'], videoUrl: '', diff --git a/nx-dev/ui-conference/src/lib/conf-speakers.tsx b/nx-dev/ui-conference/src/lib/conf-speakers.tsx index 11d957c465826..87feac25db770 100644 --- a/nx-dev/ui-conference/src/lib/conf-speakers.tsx +++ b/nx-dev/ui-conference/src/lib/conf-speakers.tsx @@ -36,7 +36,7 @@ export function ConfSpeakers(): JSX.Element { twitter: 'jcammisuli', }, { - description: `Max Kless is a senior software engineer at Nx, focussed on improving Nx Console and breaking Jon's code.`, + description: `Max Kless is a senior software engineer at Nx, focussed on building Nx Console and breaking Jon's code.`, imageUrl: '/images/conf/max-kless.webp', name: 'Max Kless', twitter: 'MaxKless', From 0fd8859c37c37213c8365208f3f4634eacec14f3 Mon Sep 17 00:00:00 2001 From: Jason Jean Date: Fri, 28 Jul 2023 10:33:40 -0400 Subject: [PATCH 206/262] fix(js): resolve imports as native node apis before npm modules (#18358) --- .../build-dependencies/target-project-locator.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/nx/src/plugins/js/project-graph/build-dependencies/target-project-locator.ts b/packages/nx/src/plugins/js/project-graph/build-dependencies/target-project-locator.ts index b12b0808c5a6a..a4ad206e0544f 100644 --- a/packages/nx/src/plugins/js/project-graph/build-dependencies/target-project-locator.ts +++ b/packages/nx/src/plugins/js/project-graph/build-dependencies/target-project-locator.ts @@ -60,6 +60,11 @@ export class TargetProjectLocator { } } + if (builtInModuleSet.has(normalizedImportExpr)) { + this.npmResolutionCache.set(normalizedImportExpr, null); + return null; + } + // try to find npm package before using expensive typescript resolution const npmProject = this.findNpmPackage(normalizedImportExpr); if (npmProject) { @@ -79,11 +84,6 @@ export class TargetProjectLocator { } } - if (builtInModuleSet.has(normalizedImportExpr)) { - this.npmResolutionCache.set(normalizedImportExpr, null); - return null; - } - try { const resolvedModule = this.resolveImportWithRequire( normalizedImportExpr, From cfeb6978958d813351063a5953cf8ee9beacbee3 Mon Sep 17 00:00:00 2001 From: Jack Hsu Date: Fri, 28 Jul 2023 11:00:21 -0400 Subject: [PATCH 207/262] Revert "fix(nextjs): builder should work with pnp" (#18367) --- packages/next/src/executors/build/build.impl.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/next/src/executors/build/build.impl.ts b/packages/next/src/executors/build/build.impl.ts index 4481e5f74a820..eb0678c66f76b 100644 --- a/packages/next/src/executors/build/build.impl.ts +++ b/packages/next/src/executors/build/build.impl.ts @@ -1,7 +1,6 @@ import 'dotenv/config'; import { ExecutorContext, - getPackageManagerCommand, logger, readJsonFile, writeJsonFile, @@ -54,11 +53,11 @@ export default async function buildExecutor( process.env.NX_NEXT_OUTPUT_PATH ??= outputPath; const args = createCliOptions({ experimentalAppOnly, profile, debug }); - const pm = getPackageManagerCommand(); - const command = `${pm.exec} next build ${projectRoot} ${args.join(' ')}`; + const command = `npx next build ${args.join(' ')}`; const execSyncOptions: ExecSyncOptions = { stdio: 'inherit', encoding: 'utf-8', + cwd: projectRoot, }; try { execSync(command, execSyncOptions); From d65736e125c09d040ae9a6be66fe8f12d97c6103 Mon Sep 17 00:00:00 2001 From: Emily Xiong Date: Fri, 28 Jul 2023 11:39:16 -0400 Subject: [PATCH 208/262] feat(detox): upgrade @config-plugins/detox to 6 (#18345) --- e2e/expo/src/expo.test.ts | 4 +--- packages/detox/migrations.json | 13 +++++++++++++ packages/detox/src/executors/build/schema.d.ts | 2 +- packages/detox/src/utils/versions.ts | 4 ++-- .../migrations/update-16-6-0/update-metro-config.ts | 2 +- .../migrations/update-16-6-0/update-metro-config.ts | 2 +- 6 files changed, 19 insertions(+), 8 deletions(-) diff --git a/e2e/expo/src/expo.test.ts b/e2e/expo/src/expo.test.ts index 01108caf26ee5..cb9f8a02f9cfe 100644 --- a/e2e/expo/src/expo.test.ts +++ b/e2e/expo/src/expo.test.ts @@ -105,9 +105,7 @@ describe('expo', () => { expect(prebuildResult.combinedOutput).toContain('Config synced'); }); - // TODO(emily): this test failed due to version conflict with conflict with @config-plugins/detox - // https://github.com/expo/config-plugins/issues/178 - xit('should install', async () => { + it('should install', async () => { // run install command const installResults = await runCLIAsync( `install ${appName} --no-interactive` diff --git a/packages/detox/migrations.json b/packages/detox/migrations.json index 5f96aca5ac9af..4e7f542ea29ab 100644 --- a/packages/detox/migrations.json +++ b/packages/detox/migrations.json @@ -250,6 +250,19 @@ "alwaysAddToPackageJson": false } } + }, + "16.6.0": { + "version": "16.6.0-beta.6", + "packages": { + "detox": { + "version": "^20.11.1", + "alwaysAddToPackageJson": false + }, + "@config-plugins/detox": { + "version": "~6.0.0", + "alwaysAddToPackageJson": false + } + } } } } diff --git a/packages/detox/src/executors/build/schema.d.ts b/packages/detox/src/executors/build/schema.d.ts index 7a8231e7f50a4..f4c037be480c2 100644 --- a/packages/detox/src/executors/build/schema.d.ts +++ b/packages/detox/src/executors/build/schema.d.ts @@ -1,4 +1,4 @@ -// options from https://github.com/wix/Detox/blob/master/docs/APIRef.DetoxCLI.md#build +// options from https://github.com/wix/Detox/blob/master/docs/cli/build.md export interface DetoxBuildOptions { detoxConfiguration?: string; configPath?: string; diff --git a/packages/detox/src/utils/versions.ts b/packages/detox/src/utils/versions.ts index 87be7987b1247..2051664bd3d56 100644 --- a/packages/detox/src/utils/versions.ts +++ b/packages/detox/src/utils/versions.ts @@ -1,5 +1,5 @@ export const nxVersion = require('../../package.json').version; -export const detoxVersion = '^20.9.0'; +export const detoxVersion = '^20.11.1'; export const testingLibraryJestDom = '5.16.5'; -export const configPluginsDetoxVersion = '~5.0.1'; // only required for expo +export const configPluginsDetoxVersion = '~6.0.0'; // only required for expo diff --git a/packages/expo/src/migrations/update-16-6-0/update-metro-config.ts b/packages/expo/src/migrations/update-16-6-0/update-metro-config.ts index 31fee35fe5628..be6f6caf6cb82 100644 --- a/packages/expo/src/migrations/update-16-6-0/update-metro-config.ts +++ b/packages/expo/src/migrations/update-16-6-0/update-metro-config.ts @@ -54,7 +54,7 @@ const customConfig = { resolver: { assetExts: assetExts.filter((ext) => ext !== 'svg'), sourceExts: [...sourceExts, 'svg'], - blockList: exclusionList([/^(?!.*node_modules).*\/dist\/.*/]), + blockList: exclusionList([/^(?!.*node_modules).*\\/dist\\/.*/]), unstable_enableSymlinks: true, unstable_enablePackageExports: true, }, diff --git a/packages/react-native/src/migrations/update-16-6-0/update-metro-config.ts b/packages/react-native/src/migrations/update-16-6-0/update-metro-config.ts index dbc25291602cb..035cef9722494 100644 --- a/packages/react-native/src/migrations/update-16-6-0/update-metro-config.ts +++ b/packages/react-native/src/migrations/update-16-6-0/update-metro-config.ts @@ -53,7 +53,7 @@ const customConfig = { resolver: { assetExts: assetExts.filter((ext) => ext !== 'svg'), sourceExts: [...sourceExts, 'svg'], - blockList: exclusionList([/^(?!.*node_modules).*\/dist\/.*/]), + blockList: exclusionList([/^(?!.*node_modules).*\\/dist\\/.*/]), unstable_enableSymlinks: true, unstable_enablePackageExports: true, }, From 4304a451cc36989e539fc5f1815a53eb568f1e94 Mon Sep 17 00:00:00 2001 From: Juri Date: Fri, 28 Jul 2023 17:37:23 +0200 Subject: [PATCH 209/262] docs(core): disable Stackblitz for now as those examples don't work with the latest version --- docs/shared/angular-standalone-tutorial/angular-standalone.md | 2 +- docs/shared/react-standalone-tutorial/react-standalone.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/shared/angular-standalone-tutorial/angular-standalone.md b/docs/shared/angular-standalone-tutorial/angular-standalone.md index 82a084cef53f9..e9555d848b9f2 100644 --- a/docs/shared/angular-standalone-tutorial/angular-standalone.md +++ b/docs/shared/angular-standalone-tutorial/angular-standalone.md @@ -20,7 +20,7 @@ Here's the source code of the final result for this tutorial. {% github-repository url="https://github.com/nrwl/nx-recipes/tree/main/angular-standalone" /%} -{% stackblitz-button url="github.com/nrwl/nx-recipes/tree/main/angular-standalone?file=README.md" /%} + Also, if you prefer learning with a video, join Juri and walk through the tutorial, step by step together. diff --git a/docs/shared/react-standalone-tutorial/react-standalone.md b/docs/shared/react-standalone-tutorial/react-standalone.md index c7e49e0c768cf..277613be9b246 100644 --- a/docs/shared/react-standalone-tutorial/react-standalone.md +++ b/docs/shared/react-standalone-tutorial/react-standalone.md @@ -27,7 +27,7 @@ Here's the source code of the final result for this tutorial. {% github-repository url="https://github.com/nrwl/nx-recipes/tree/main/react-standalone" /%} -{% stackblitz-button url="github.com/nrwl/nx-recipes/tree/main/react-standalone?file=README.md" /%} + {% youtube src="https://www.youtube.com/embed/OQ-Zc5tcxJE" From 3eba026e39039b27c74f746ae80a201f580645ab Mon Sep 17 00:00:00 2001 From: Jason Jean Date: Fri, 28 Jul 2023 12:23:14 -0400 Subject: [PATCH 210/262] fix(core): fix performance of hashing external dependencies up front (#18359) --- .../__snapshots__/task-hasher.spec.ts.snap | 10 ++--- packages/nx/src/hasher/task-hasher.spec.ts | 8 ++-- packages/nx/src/hasher/task-hasher.ts | 45 ++++++++++++------- 3 files changed, 37 insertions(+), 26 deletions(-) diff --git a/packages/nx/src/hasher/__snapshots__/task-hasher.spec.ts.snap b/packages/nx/src/hasher/__snapshots__/task-hasher.spec.ts.snap index d7519823406ff..a8dab6efd631f 100644 --- a/packages/nx/src/hasher/__snapshots__/task-hasher.spec.ts.snap +++ b/packages/nx/src/hasher/__snapshots__/task-hasher.spec.ts.snap @@ -63,7 +63,7 @@ exports[`TaskHasher hashTarget should hash entire subtree of dependencies 1`] = }, "runtime": {}, }, - "value": "17607022607820563118", + "value": "14419327228911184578", } `; @@ -83,7 +83,7 @@ exports[`TaskHasher hashTarget should hash executor dependencies of @nx packages }, "runtime": {}, }, - "value": "15096054768893599383", + "value": "379625642227035180", } `; @@ -105,7 +105,7 @@ exports[`TaskHasher hashTarget should use externalDependencies to override nx:ru }, "runtime": {}, }, - "value": "18142315317355318287", + "value": "14779270419297346086", } `; @@ -239,7 +239,7 @@ exports[`TaskHasher should hash missing dependent npm project versions 1`] = ` }, "runtime": {}, }, - "value": "3668827038634092448", + "value": "13210933885500739919", } `; @@ -321,7 +321,7 @@ exports[`TaskHasher should hash npm project versions 1`] = ` }, "runtime": {}, }, - "value": "3668827038634092448", + "value": "13210933885500739919", } `; diff --git a/packages/nx/src/hasher/task-hasher.spec.ts b/packages/nx/src/hasher/task-hasher.spec.ts index 1428ffaaeeb18..6524852c74303 100644 --- a/packages/nx/src/hasher/task-hasher.spec.ts +++ b/packages/nx/src/hasher/task-hasher.spec.ts @@ -976,23 +976,23 @@ describe('TaskHasher', () => { const hasher1 = createHasher(); const hasher2 = createHasher(); - const hashA1 = hasher1.hashTask({ + const hashA1 = await hasher1.hashTask({ id: 'a-build', target: { project: 'a', target: 'build' }, overrides: {}, }); - const hashB1 = hasher1.hashTask({ + const hashB1 = await hasher1.hashTask({ id: 'b-build', target: { project: 'b', target: 'build' }, overrides: {}, }); - const hashB2 = hasher2.hashTask({ + const hashB2 = await hasher2.hashTask({ id: 'b-build', target: { project: 'b', target: 'build' }, overrides: {}, }); - const hashA2 = hasher2.hashTask({ + const hashA2 = await hasher2.hashTask({ id: 'a-build', target: { project: 'a', target: 'build' }, overrides: {}, diff --git a/packages/nx/src/hasher/task-hasher.ts b/packages/nx/src/hasher/task-hasher.ts index 45c5a0a7f0284..f88cd7603c882 100644 --- a/packages/nx/src/hasher/task-hasher.ts +++ b/packages/nx/src/hasher/task-hasher.ts @@ -186,9 +186,9 @@ class TaskHasherImpl { private runtimeHashes: { [runtime: string]: Promise; } = {}; - private externalDependencyHashes: Map = new Map< + private externalDependencyHashes: Map = new Map< string, - PartialHash + PartialHash[] >(); private allExternalDependenciesHash: PartialHash; private projectRootMappings = createProjectRootMappings( @@ -300,11 +300,16 @@ class TaskHasherImpl { } private combinePartialHashes(partialHashes: PartialHash[]): PartialHash { - let details = {}; + if (partialHashes.length === 1) { + return partialHashes[0]; + } + const details = {}; + const hashValues: string[] = []; for (const partial of partialHashes) { - details = { ...details, ...partial.details }; + hashValues.push(partial.value); + Object.assign(details, partial.details); } - const value = hashArray(partialHashes.map(({ value }) => value)); + const value = hashArray(hashValues); return { value, details }; } @@ -416,25 +421,29 @@ class TaskHasherImpl { } private getExternalDependencyHash(externalNodeName: string) { - return this.externalDependencyHashes.get(externalNodeName); + const combinedHash = this.combinePartialHashes( + this.externalDependencyHashes.get(externalNodeName) + ); + // Set the combined hash into the hashes so it's not recalculated next time + this.externalDependencyHashes.set(externalNodeName, [combinedHash]); + return combinedHash; } private hashExternalDependency( externalNodeName: string, visited: Set - ): PartialHash { + ): PartialHash[] { // try to retrieve the hash from cache if (this.externalDependencyHashes.has(externalNodeName)) { return this.externalDependencyHashes.get(externalNodeName); } visited.add(externalNodeName); const node = this.projectGraph.externalNodes[externalNodeName]; - let partialHash: PartialHash; + const partialHashes: Set = new Set(); if (node) { - const partialHashes: PartialHash[] = []; if (node.data.hash) { // we already know the hash of this dependency - partialHashes.push({ + partialHashes.add({ value: node.data.hash, details: { [externalNodeName]: node.data.hash, @@ -442,7 +451,7 @@ class TaskHasherImpl { }); } else { // we take version as a hash - partialHashes.push({ + partialHashes.add({ value: node.data.version, details: { [externalNodeName]: node.data.version, @@ -453,25 +462,27 @@ class TaskHasherImpl { if (this.projectGraph.dependencies[externalNodeName]) { this.projectGraph.dependencies[externalNodeName].forEach((d) => { if (!visited.has(d.target)) { - partialHashes.push(this.hashExternalDependency(d.target, visited)); + for (const hash of this.hashExternalDependency(d.target, visited)) { + partialHashes.add(hash); + } } }); } - partialHash = this.combinePartialHashes(partialHashes); } else { // unknown dependency // this may occur if dependency is not an npm package // but rather symlinked in node_modules or it's pointing to a remote git repo // in this case we have no information about the versioning of the given package - partialHash = { + partialHashes.add({ value: `__${externalNodeName}__`, details: { [externalNodeName]: `__${externalNodeName}__`, }, - }; + }); } - this.externalDependencyHashes.set(externalNodeName, partialHash); - return partialHash; + const partialHashArray = Array.from(partialHashes); + this.externalDependencyHashes.set(externalNodeName, partialHashArray); + return partialHashArray; } private hashTarget( From 6afe0a7c20059d6cdc8e455758a17886f933a0dc Mon Sep 17 00:00:00 2001 From: FrozenPandaz Date: Fri, 28 Jul 2023 12:26:09 -0400 Subject: [PATCH 211/262] chore(misc): publish 16.6.0-beta.7 --- lerna.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lerna.json b/lerna.json index 432b9c8087757..f316678a1c3cf 100644 --- a/lerna.json +++ b/lerna.json @@ -1,6 +1,6 @@ { "packages": ["build/packages/*", "build/packages/nx/native-packages/*"], - "version": "16.6.0-beta.6", + "version": "16.6.0-beta.7", "granularPathspec": false, "command": { "publish": { From dbd61b5d9a91aa888cad7507c7ef3c67228fcd1c Mon Sep 17 00:00:00 2001 From: Caleb Ukle Date: Fri, 28 Jul 2023 11:40:52 -0500 Subject: [PATCH 212/262] fix(react-native): update generated jest config coverage dir (#18366) --- .../application/application.spec.ts | 16 ++++- .../src/generators/library/library.spec.ts | 66 +++++++++++++++++++ packages/react-native/src/utils/add-jest.ts | 7 +- 3 files changed, 86 insertions(+), 3 deletions(-) diff --git a/packages/react-native/src/generators/application/application.spec.ts b/packages/react-native/src/generators/application/application.spec.ts index aa50f34e6be5b..5ae6588961856 100644 --- a/packages/react-native/src/generators/application/application.spec.ts +++ b/packages/react-native/src/generators/application/application.spec.ts @@ -60,6 +60,21 @@ describe('app', () => { expect(tsconfig.extends).toEqual('../../tsconfig.base.json'); expect(appTree.exists('apps/my-app/.eslintrc.json')).toBe(true); + expect(appTree.read('apps/my-app/jest.config.ts', 'utf-8')) + .toMatchInlineSnapshot(` + "module.exports = { + displayName: 'my-app', + preset: 'react-native', + resolver: '@nx/jest/plugins/resolver', + moduleFileExtensions: ['ts', 'js', 'html', 'tsx', 'jsx'], + setupFilesAfterEnv: ['/test-setup.ts'], + moduleNameMapper: { + '\\\\.svg$': '@nx/react-native/plugins/jest/svg-mock', + }, + coverageDirectory: '../../coverage/apps/my-app', + }; + " + `); }); it('should generate targets', async () => { @@ -71,7 +86,6 @@ describe('app', () => { install: false, }); const targets = readProjectConfiguration(appTree, 'my-app').targets; - console.log(targets.test); expect(targets.test).toBeDefined(); }); diff --git a/packages/react-native/src/generators/library/library.spec.ts b/packages/react-native/src/generators/library/library.spec.ts index 4851ef14ad040..86fadf77f0dea 100644 --- a/packages/react-native/src/generators/library/library.spec.ts +++ b/packages/react-native/src/generators/library/library.spec.ts @@ -242,6 +242,72 @@ describe('lib', () => { outputs: ['{options.outputFile}'], }); }); + + it('should generate test configuration', async () => { + await libraryGenerator(appTree, { + ...defaultSchema, + unitTestRunner: 'jest', + }); + + expect(appTree.read('libs/my-lib/tsconfig.spec.json', 'utf-8')) + .toMatchInlineSnapshot(` + "{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"] + }, + "include": [ + "jest.config.ts", + "src/**/*.test.ts", + "src/**/*.spec.ts", + "src/**/*.test.tsx", + "src/**/*.spec.tsx", + "src/**/*.test.js", + "src/**/*.spec.js", + "src/**/*.test.jsx", + "src/**/*.spec.jsx", + "src/**/*.d.ts" + ] + } + " + `); + expect(appTree.read('libs/my-lib/jest.config.ts', 'utf-8')) + .toMatchInlineSnapshot(` + "module.exports = { + displayName: 'my-lib', + preset: 'react-native', + resolver: '@nx/jest/plugins/resolver', + moduleFileExtensions: ['ts', 'js', 'html', 'tsx', 'jsx'], + setupFilesAfterEnv: ['/test-setup.ts'], + moduleNameMapper: { + '\\\\.svg$': '@nx/react-native/plugins/jest/svg-mock', + }, + coverageDirectory: '../../coverage/libs/my-lib', + }; + " + `); + const projectConfiguration = readProjectConfiguration(appTree, 'my-lib'); + expect(projectConfiguration.targets.test).toMatchInlineSnapshot(` + { + "configurations": { + "ci": { + "ci": true, + "codeCoverage": true, + }, + }, + "executor": "@nx/jest:jest", + "options": { + "jestConfig": "libs/my-lib/jest.config.ts", + "passWithNoTests": true, + }, + "outputs": [ + "{workspaceRoot}/coverage/{projectRoot}", + ], + } + `); + }); }); describe('--buildable', () => { diff --git a/packages/react-native/src/utils/add-jest.ts b/packages/react-native/src/utils/add-jest.ts index ab38c72bb16fb..3a363006162ab 100644 --- a/packages/react-native/src/utils/add-jest.ts +++ b/packages/react-native/src/utils/add-jest.ts @@ -1,4 +1,4 @@ -import { Tree } from '@nx/devkit'; +import { Tree, offsetFromRoot } from '@nx/devkit'; import { configurationGenerator } from '@nx/jest'; export async function addJest( @@ -34,7 +34,10 @@ export async function addJest( setupFilesAfterEnv: ['/test-setup.${js ? 'js' : 'ts'}'], moduleNameMapper: { '\\\\.svg$': '@nx/react-native/plugins/jest/svg-mock' - } + }, + coverageDirectory: '${offsetFromRoot( + appProjectRoot + )}coverage/${appProjectRoot}' };`; host.write(configPath, content); From 9732188eee2989f597769b60bf75b0f850386e23 Mon Sep 17 00:00:00 2001 From: Juri Date: Fri, 28 Jul 2023 21:33:15 +0200 Subject: [PATCH 213/262] docs(core): fix localhost link on intro page --- docs/shared/getting-started/intro.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/shared/getting-started/intro.md b/docs/shared/getting-started/intro.md index cf006fd802267..aeb5abe91b146 100644 --- a/docs/shared/getting-started/intro.md +++ b/docs/shared/getting-started/intro.md @@ -28,7 +28,7 @@ You can use Nx to quickly scaffold a new project or even an entire monorepo. It {% title-card title="New Monorepo" url="#get-started-with-the-basics" /%} {% title-card title="Choose a Stack" url="#learn-about-nx-and-your-favorite-stack" /%} -{% title-card title="Add to an Existing Project" url="#http://localhost:4200/getting-started/intro#adding-nx-to-an-existing-project" /%} +{% title-card title="Add to an Existing Project" url="#adding-nx-to-an-existing-project" /%} {% /cards %} From fdd9c24a2a9bad48170b13e13e950be323099251 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Jona=C5=A1?= Date: Fri, 28 Jul 2023 21:43:25 +0200 Subject: [PATCH 214/262] fix(storybook): support pnp with storybook package (#18343) --- .../migrate-7/calling-storybook-cli.ts | 10 +++++---- .../migrate-7/helper-functions.spec.ts | 22 ++++++++++--------- .../generators/migrate-7/helper-functions.ts | 7 ++++-- 3 files changed, 23 insertions(+), 16 deletions(-) diff --git a/packages/storybook/src/generators/migrate-7/calling-storybook-cli.ts b/packages/storybook/src/generators/migrate-7/calling-storybook-cli.ts index 2f6986f20dd10..dbd7aede818fd 100644 --- a/packages/storybook/src/generators/migrate-7/calling-storybook-cli.ts +++ b/packages/storybook/src/generators/migrate-7/calling-storybook-cli.ts @@ -1,8 +1,9 @@ -import { output } from '@nx/devkit'; +import { getPackageManagerCommand, output } from '@nx/devkit'; import { execSync } from 'child_process'; import { Schema } from './schema'; export function callUpgrade(schema: Schema): 1 | Buffer { + const pm = getPackageManagerCommand(); try { output.log({ title: `Calling sb upgrade`, @@ -14,7 +15,7 @@ export function callUpgrade(schema: Schema): 1 | Buffer { }); execSync( - `npx storybook@latest upgrade ${ + `${pm.exec} storybook@latest upgrade ${ schema.autoAcceptAllPrompts ? '--yes' : '' }`, { @@ -36,7 +37,7 @@ export function callUpgrade(schema: Schema): 1 | Buffer { bodyLines: [ `🚨 The Storybook CLI failed to upgrade your @storybook/* packages to the latest version.`, `Please try running the sb upgrade command manually:`, - `npx storybook@latest upgrade`, + `${pm.exec} storybook@latest upgrade`, ], color: 'red', }); @@ -71,7 +72,8 @@ export function callAutomigrate( Object.entries(allStorybookProjects).forEach( ([projectName, storybookProjectInfo]) => { - const commandToRun = `npx storybook@latest automigrate --config-dir ${storybookProjectInfo.configDir} --renderer ${storybookProjectInfo.uiFramework}`; + const pm = getPackageManagerCommand(); + const commandToRun = `${pm.exec} storybook@latest automigrate --config-dir ${storybookProjectInfo.configDir} --renderer ${storybookProjectInfo.uiFramework}`; try { output.log({ title: `Calling sb automigrate for ${projectName}`, diff --git a/packages/storybook/src/generators/migrate-7/helper-functions.spec.ts b/packages/storybook/src/generators/migrate-7/helper-functions.spec.ts index d5fa986bb9aac..36826cf8087ff 100644 --- a/packages/storybook/src/generators/migrate-7/helper-functions.spec.ts +++ b/packages/storybook/src/generators/migrate-7/helper-functions.spec.ts @@ -1,5 +1,6 @@ import { addProjectConfiguration, + getPackageManagerCommand, output, ProjectConfiguration, readProjectConfiguration, @@ -73,28 +74,29 @@ describe('Helper functions for the Storybook 7 migration generator', () => { it('should onlyShowGuide and the correct instructions', () => { const outputSpy = jest.spyOn(output, 'log').mockImplementation(); onlyShowGuide(allStorybookInfo); + const pm = getPackageManagerCommand(); expect(outputSpy).toHaveBeenCalledWith( expect.objectContaining({ bodyLines: [ 'You can run the following commands manually to upgrade your Storybook projects to Storybook 7:', '', '1. Call the Storybook upgrade script:', - 'npx storybook@latest upgrade', + `${pm.exec} storybook@latest upgrade`, '', '2. Call the Nx generator to prepare your files for migration:', 'nx g @nx/storybook:migrate-7 --onlyPrepare', '', '3. Call the Storybook automigrate scripts:', 'Run the following commands for each Storybook project:', - 'npx storybook@latest automigrate --config-dir apps/nextapp/.storybook --renderer @storybook/react', - 'npx storybook@latest automigrate --config-dir apps/nextapp-ts/.storybook --renderer @storybook/react', - 'npx storybook@latest automigrate --config-dir apps/rv1/.storybook --renderer @storybook/react', - 'npx storybook@latest automigrate --config-dir apps/rv2-ts/.storybook --renderer @storybook/react', - 'npx storybook@latest automigrate --config-dir apps/rw1/.storybook --renderer @storybook/react', - 'npx storybook@latest automigrate --config-dir apps/wv1/.storybook --renderer @storybook/web-components', - 'npx storybook@latest automigrate --config-dir apps/ww1/.storybook --renderer @storybook/web-components', - 'npx storybook@latest automigrate --config-dir apps/ngapp/.storybook --renderer @storybook/angular', - 'npx storybook@latest automigrate --config-dir apps/ngapp-ts/.storybook --renderer @storybook/angular', + `${pm.exec} storybook@latest automigrate --config-dir apps/nextapp/.storybook --renderer @storybook/react`, + `${pm.exec} storybook@latest automigrate --config-dir apps/nextapp-ts/.storybook --renderer @storybook/react`, + `${pm.exec} storybook@latest automigrate --config-dir apps/rv1/.storybook --renderer @storybook/react`, + `${pm.exec} storybook@latest automigrate --config-dir apps/rv2-ts/.storybook --renderer @storybook/react`, + `${pm.exec} storybook@latest automigrate --config-dir apps/rw1/.storybook --renderer @storybook/react`, + `${pm.exec} storybook@latest automigrate --config-dir apps/wv1/.storybook --renderer @storybook/web-components`, + `${pm.exec} storybook@latest automigrate --config-dir apps/ww1/.storybook --renderer @storybook/web-components`, + `${pm.exec} storybook@latest automigrate --config-dir apps/ngapp/.storybook --renderer @storybook/angular`, + `${pm.exec} storybook@latest automigrate --config-dir apps/ngapp-ts/.storybook --renderer @storybook/angular`, '', '4. Call the Nx generator to finish the migration:', 'nx g @nx/storybook:migrate-7 --afterMigration', diff --git a/packages/storybook/src/generators/migrate-7/helper-functions.ts b/packages/storybook/src/generators/migrate-7/helper-functions.ts index 1dae3ca522d49..42b8118a5df1d 100644 --- a/packages/storybook/src/generators/migrate-7/helper-functions.ts +++ b/packages/storybook/src/generators/migrate-7/helper-functions.ts @@ -2,6 +2,7 @@ import { applyChangesToString, ChangeType, generateFiles, + getPackageManagerCommand, joinPathFragments, output, readProjectConfiguration, @@ -24,13 +25,15 @@ export function onlyShowGuide(storybookProjects: { viteConfigFilePath?: string; }; }) { + const pm = getPackageManagerCommand(); + output.log({ title: 'Storybook 7 Migration Guide', bodyLines: [ `You can run the following commands manually to upgrade your Storybook projects to Storybook 7:`, ``, `1. Call the Storybook upgrade script:`, - `npx storybook@latest upgrade`, + `${pm.exec} storybook@latest upgrade`, ``, `2. Call the Nx generator to prepare your files for migration:`, `nx g @nx/storybook:migrate-7 --onlyPrepare`, @@ -39,7 +42,7 @@ export function onlyShowGuide(storybookProjects: { `Run the following commands for each Storybook project:`, ...Object.entries(storybookProjects).map( ([_projectName, storybookProjectInfo]) => { - return `npx storybook@latest automigrate --config-dir ${storybookProjectInfo.configDir} --renderer ${storybookProjectInfo.uiFramework}`; + return `${pm.exec} storybook@latest automigrate --config-dir ${storybookProjectInfo.configDir} --renderer ${storybookProjectInfo.uiFramework}`; } ), ``, From 63521d7e1375711bda3abb64512b87053723ed8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Jona=C5=A1?= Date: Fri, 28 Jul 2023 21:43:40 +0200 Subject: [PATCH 215/262] fix(js): ensure compile swc uses current package manager (#18321) --- packages/js/src/executors/swc/swc.impl.ts | 45 +++++++++-------------- packages/js/src/utils/swc/compile-swc.ts | 16 +++++--- 2 files changed, 28 insertions(+), 33 deletions(-) diff --git a/packages/js/src/executors/swc/swc.impl.ts b/packages/js/src/executors/swc/swc.impl.ts index 91319542bad62..d9b7ba08fed9a 100644 --- a/packages/js/src/executors/swc/swc.impl.ts +++ b/packages/js/src/executors/swc/swc.impl.ts @@ -22,13 +22,13 @@ import { compileSwc, compileSwcWatch } from '../../utils/swc/compile-swc'; import { getSwcrcPath } from '../../utils/swc/get-swcrc-path'; import { generateTmpSwcrc } from '../../utils/swc/inline'; -export function normalizeOptions( +function normalizeOptions( options: SwcExecutorOptions, - contextRoot: string, - sourceRoot?: string, - projectRoot?: string + root: string, + sourceRoot: string, + projectRoot: string ): NormalizedSwcExecutorOptions { - const outputPath = join(contextRoot, options.outputPath); + const outputPath = join(root, options.outputPath); if (options.skipTypeCheck == null) { options.skipTypeCheck = false; @@ -54,23 +54,16 @@ export function normalizeOptions( const files: FileInputOutput[] = assetGlobsToFiles( options.assets, - contextRoot, + root, outputPath ); - const projectRootParts = projectRoot.split('/'); - // We pop the last part of the `projectRoot` to pass - // the last part (projectDir) and the remainder (projectRootParts) to swc - const projectDir = projectRootParts.pop(); - // default to current directory if projectRootParts is []. - // Eg: when a project is at the root level, outside of layout dir - const swcCwd = projectRootParts.join('/') || '.'; - const swcrcPath = getSwcrcPath(options, contextRoot, projectRoot); - + const swcrcPath = getSwcrcPath(options, root, projectRoot); + // TODO(meeroslav): Check why this is needed in order for swc to properly nest folders + const distParent = outputPath.split('/').slice(0, -1).join('/'); const swcCliOptions = { - srcPath: projectDir, - destPath: relative(join(contextRoot, swcCwd), outputPath), - swcCwd, + srcPath: projectRoot, + destPath: relative(root, distParent), swcrcPath, }; @@ -81,12 +74,12 @@ export function normalizeOptions( options.main.replace(`${projectRoot}/`, '').replace('.ts', '.js') ), files, - root: contextRoot, + root, sourceRoot, projectRoot, originalProjectRoot: projectRoot, outputPath, - tsConfig: join(contextRoot, options.tsConfig), + tsConfig: join(root, options.tsConfig), swcCliOptions, } as NormalizedSwcExecutorOptions; } @@ -127,13 +120,11 @@ export async function* swcExecutor( if (!isInlineGraphEmpty(inlineProjectGraph)) { options.projectRoot = '.'; // set to root of workspace to include other libs for type check - // remap paths for SWC compilation - options.swcCliOptions.srcPath = options.swcCliOptions.swcCwd; - options.swcCliOptions.swcCwd = '.'; - options.swcCliOptions.destPath = options.swcCliOptions.destPath - .split('../') - .at(-1) - .concat('/', options.swcCliOptions.srcPath); + options.swcCliOptions.srcPath = root.split('/').slice(0, -1).join('/'); // set to root of libraries to include other libs + options.swcCliOptions.destPath = join( + _options.outputPath, + options.swcCliOptions.srcPath + ); // new destPath is dist/{libs}/{parentLib}/{libs} // tmp swcrc with dependencies to exclude // - buildable libraries diff --git a/packages/js/src/utils/swc/compile-swc.ts b/packages/js/src/utils/swc/compile-swc.ts index 30dbab9edb689..7dfc4322c6b72 100644 --- a/packages/js/src/utils/swc/compile-swc.ts +++ b/packages/js/src/utils/swc/compile-swc.ts @@ -1,4 +1,9 @@ -import { cacheDir, ExecutorContext, logger } from '@nx/devkit'; +import { + cacheDir, + ExecutorContext, + getPackageManagerCommand, + logger, +} from '@nx/devkit'; import { exec, execSync } from 'child_process'; import { removeSync } from 'fs-extra'; import { createAsyncIterable } from '@nx/devkit/src/utils/async-iterable'; @@ -10,7 +15,8 @@ function getSwcCmd( { swcrcPath, srcPath, destPath }: SwcCliOptions, watch = false ) { - let swcCmd = `npx swc ${ + const packageManager = getPackageManagerCommand(); + let swcCmd = `${packageManager.exec} swc ${ // TODO(jack): clean this up when we remove inline module support // Handle root project srcPath === '.' ? 'src' : srcPath @@ -42,8 +48,6 @@ export async function compileSwc( normalizedOptions: NormalizedSwcExecutorOptions, postCompilationCallback: () => Promise ) { - const isRootProject = - context.projectGraph.nodes[context.projectName].data.root === '.'; logger.log(`Compiling with SWC for ${context.projectName}...`); if (normalizedOptions.clean) { @@ -51,8 +55,8 @@ export async function compileSwc( } const swcCmdLog = execSync(getSwcCmd(normalizedOptions.swcCliOptions), { - cwd: normalizedOptions.swcCliOptions.swcCwd, - }).toString(); + encoding: 'utf8', + }); logger.log(swcCmdLog.replace(/\n/, '')); const isCompileSuccess = swcCmdLog.includes('Successfully compiled'); From 80c470ac7f421c3bcb38e8050f77e77a52231459 Mon Sep 17 00:00:00 2001 From: Jason Jean Date: Fri, 28 Jul 2023 16:00:59 -0400 Subject: [PATCH 216/262] fix(core): do not error when hashing executors which are local plugins (#18372) --- .../__snapshots__/task-hasher.spec.ts.snap | 46 ++++++++ packages/nx/src/hasher/task-hasher.spec.ts | 3 + packages/nx/src/hasher/task-hasher.ts | 102 +++++++++--------- packages/nx/src/utils/project-graph-utils.ts | 29 +++-- 4 files changed, 117 insertions(+), 63 deletions(-) diff --git a/packages/nx/src/hasher/__snapshots__/task-hasher.spec.ts.snap b/packages/nx/src/hasher/__snapshots__/task-hasher.spec.ts.snap index a8dab6efd631f..7ce56a4b0ce80 100644 --- a/packages/nx/src/hasher/__snapshots__/task-hasher.spec.ts.snap +++ b/packages/nx/src/hasher/__snapshots__/task-hasher.spec.ts.snap @@ -44,6 +44,52 @@ exports[`TaskHasher dependentTasksOutputFiles should work with dependent tasks w } `; +exports[`TaskHasher hashTarget should hash entire subtree in a deterministic way 1`] = ` +{ + "details": { + "command": "81188892120010785", + "implicitDeps": {}, + "nodes": { + "ProjectConfiguration": "8474322003863204060", + "TsConfig": "8767608672024750088", + "appA:{projectRoot}/**/*": "3244421341483603138", + "npm:@nx/webpack": "$@nx/webpack0.0.0$", + "npm:packageA": "$packageA0.0.0$", + "npm:packageB": "$packageB0.0.0$", + "npm:packageC": "$packageC0.0.0$", + "{workspaceRoot}/.gitignore": "3244421341483603138", + "{workspaceRoot}/.nxignore": "3244421341483603138", + "{workspaceRoot}/nx.json": "8942239360311677987", + }, + "runtime": {}, + }, + "value": "12756041818139421941", +} +`; + +exports[`TaskHasher hashTarget should hash entire subtree in a deterministic way 2`] = ` +{ + "details": { + "command": "9096392622609675764", + "implicitDeps": {}, + "nodes": { + "ProjectConfiguration": "17724470359684527282", + "TsConfig": "8767608672024750088", + "appB:{projectRoot}/**/*": "3244421341483603138", + "npm:@nx/webpack": "$@nx/webpack0.0.0$", + "npm:packageA": "$packageA0.0.0$", + "npm:packageB": "$packageB0.0.0$", + "npm:packageC": "$packageC0.0.0$", + "{workspaceRoot}/.gitignore": "3244421341483603138", + "{workspaceRoot}/.nxignore": "3244421341483603138", + "{workspaceRoot}/nx.json": "8942239360311677987", + }, + "runtime": {}, + }, + "value": "15326312070983573452", +} +`; + exports[`TaskHasher hashTarget should hash entire subtree of dependencies 1`] = ` { "details": { diff --git a/packages/nx/src/hasher/task-hasher.spec.ts b/packages/nx/src/hasher/task-hasher.spec.ts index 6524852c74303..e04d8529d3be3 100644 --- a/packages/nx/src/hasher/task-hasher.spec.ts +++ b/packages/nx/src/hasher/task-hasher.spec.ts @@ -1257,6 +1257,9 @@ describe('TaskHasher', () => { expect(hashAppB1).toEqual(hashAppB2); expect(hashAppA1).toEqual(hashAppA2); + + expect(hashAppA1).toMatchSnapshot(); + expect(hashAppB1).toMatchSnapshot(); }); it('should not hash when nx:run-commands executor', async () => { diff --git a/packages/nx/src/hasher/task-hasher.ts b/packages/nx/src/hasher/task-hasher.ts index f88cd7603c882..da6641411e399 100644 --- a/packages/nx/src/hasher/task-hasher.ts +++ b/packages/nx/src/hasher/task-hasher.ts @@ -20,6 +20,7 @@ import { getHashEnv } from './set-hash-env'; import { workspaceRoot } from '../utils/workspace-root'; import { join, relative } from 'path'; import { normalizePath } from '../utils/path'; +import { findAllProjectNodeDependencies } from '../utils/project-graph-utils'; type ExpandedSelfInput = | { fileset: string } @@ -429,60 +430,39 @@ class TaskHasherImpl { return combinedHash; } - private hashExternalDependency( - externalNodeName: string, - visited: Set - ): PartialHash[] { - // try to retrieve the hash from cache - if (this.externalDependencyHashes.has(externalNodeName)) { - return this.externalDependencyHashes.get(externalNodeName); - } - visited.add(externalNodeName); + private hashSingleExternalDependency(externalNodeName: string): PartialHash { const node = this.projectGraph.externalNodes[externalNodeName]; - const partialHashes: Set = new Set(); - if (node) { - if (node.data.hash) { - // we already know the hash of this dependency - partialHashes.add({ - value: node.data.hash, - details: { - [externalNodeName]: node.data.hash, - }, - }); - } else { - // we take version as a hash - partialHashes.add({ - value: node.data.version, - details: { - [externalNodeName]: node.data.version, - }, - }); - } - // we want to calculate the hash of the entire dependency tree - if (this.projectGraph.dependencies[externalNodeName]) { - this.projectGraph.dependencies[externalNodeName].forEach((d) => { - if (!visited.has(d.target)) { - for (const hash of this.hashExternalDependency(d.target, visited)) { - partialHashes.add(hash); - } - } - }); - } + if (node.data.hash) { + // we already know the hash of this dependency + return { + value: node.data.hash, + details: { + [externalNodeName]: node.data.hash, + }, + }; } else { - // unknown dependency - // this may occur if dependency is not an npm package - // but rather symlinked in node_modules or it's pointing to a remote git repo - // in this case we have no information about the versioning of the given package - partialHashes.add({ - value: `__${externalNodeName}__`, + // we take version as a hash + return { + value: node.data.version, details: { - [externalNodeName]: `__${externalNodeName}__`, + [externalNodeName]: node.data.version, }, - }); + }; + } + } + + private hashExternalDependency(externalNodeName: string) { + const partialHashes: Set = new Set(); + partialHashes.add(this.hashSingleExternalDependency(externalNodeName)); + const deps = findAllProjectNodeDependencies( + externalNodeName, + this.projectGraph, + true + ); + for (const dep of deps) { + partialHashes.add(this.hashSingleExternalDependency(dep)); } - const partialHashArray = Array.from(partialHashes); - this.externalDependencyHashes.set(externalNodeName, partialHashArray); - return partialHashArray; + return Array.from(partialHashes); } private hashTarget( @@ -507,6 +487,13 @@ class TaskHasherImpl { const executorPackage = target.executor.split(':')[0]; const executorNodeName = this.findExternalDependencyNodeName(executorPackage); + + // This is either a local plugin or a non-existent executor + if (!executorNodeName) { + // TODO: This should not return null if it is a local plugin's executor + return null; + } + return this.getExternalDependencyHash(executorNodeName); } else { // use command external dependencies if available to construct the hash @@ -519,6 +506,12 @@ class TaskHasherImpl { const externalDependencies = input['externalDependencies']; for (let dep of externalDependencies) { dep = this.findExternalDependencyNodeName(dep); + if (!dep) { + throw new Error( + `The externalDependency "${dep}" for "${projectName}:${targetName}" could not be found` + ); + } + partialHashes.push(this.getExternalDependencyHash(dep)); } } @@ -543,7 +536,7 @@ class TaskHasherImpl { } } - private findExternalDependencyNodeName(packageName: string): string { + private findExternalDependencyNodeName(packageName: string): string | null { if (this.projectGraph.externalNodes[packageName]) { return packageName; } @@ -555,8 +548,8 @@ class TaskHasherImpl { return node.name; } } - // not found, just return the package name - return packageName; + // not found + return null; } private async hashSingleProjectInputs( @@ -768,7 +761,10 @@ class TaskHasherImpl { private calculateExternalDependencyHashes() { const keys = Object.keys(this.projectGraph.externalNodes); for (const externalNodeName of keys) { - this.hashExternalDependency(externalNodeName, new Set()); + this.externalDependencyHashes.set( + externalNodeName, + this.hashExternalDependency(externalNodeName) + ); } } } diff --git a/packages/nx/src/utils/project-graph-utils.ts b/packages/nx/src/utils/project-graph-utils.ts index 4bf89d30b59cd..e5cdd43ae75ae 100644 --- a/packages/nx/src/utils/project-graph-utils.ts +++ b/packages/nx/src/utils/project-graph-utils.ts @@ -75,21 +75,24 @@ export function getSourceDirOfDependentProjects( /** * Find all internal project dependencies. - * All the external (npm) dependencies will be filtered out + * All the external (npm) dependencies will be filtered out unless includeExternalDependencies is set to true * @param {string} parentNodeName * @param {ProjectGraph} projectGraph + * @param includeExternalDependencies * @returns {string[]} */ export function findAllProjectNodeDependencies( parentNodeName: string, - projectGraph = readCachedProjectGraph() + projectGraph = readCachedProjectGraph(), + includeExternalDependencies = false ): string[] { const dependencyNodeNames = new Set(); collectDependentProjectNodesNames( projectGraph as ProjectGraph, dependencyNodeNames, - parentNodeName + parentNodeName, + includeExternalDependencies ); return Array.from(dependencyNodeNames); @@ -99,7 +102,8 @@ export function findAllProjectNodeDependencies( function collectDependentProjectNodesNames( nxDeps: ProjectGraph, dependencyNodeNames: Set, - parentNodeName: string + parentNodeName: string, + includeExternalDependencies: boolean ) { const dependencies = nxDeps.dependencies[parentNodeName]; if (!dependencies) { @@ -111,23 +115,28 @@ function collectDependentProjectNodesNames( for (const dependency of dependencies) { const dependencyName = dependency.target; - // we're only interested in internal nodes, not external - if (nxDeps.externalNodes?.[dependencyName]) { - continue; - } - // skip dependencies already added (avoid circular dependencies) if (dependencyNodeNames.has(dependencyName)) { continue; } + // we're only interested in internal nodes, not external + if (nxDeps.externalNodes?.[dependencyName]) { + if (includeExternalDependencies) { + dependencyNodeNames.add(dependencyName); + } else { + continue; + } + } + dependencyNodeNames.add(dependencyName); // Get the dependencies of the dependencies collectDependentProjectNodesNames( nxDeps, dependencyNodeNames, - dependencyName + dependencyName, + includeExternalDependencies ); } } From d1d06349e703d903ac47fb7adc7d250ce140d77e Mon Sep 17 00:00:00 2001 From: FrozenPandaz Date: Fri, 28 Jul 2023 16:06:54 -0400 Subject: [PATCH 217/262] chore(misc): publish 16.6.0-beta.8 --- lerna.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lerna.json b/lerna.json index f316678a1c3cf..9e1748525bd8a 100644 --- a/lerna.json +++ b/lerna.json @@ -1,6 +1,6 @@ { "packages": ["build/packages/*", "build/packages/nx/native-packages/*"], - "version": "16.6.0-beta.7", + "version": "16.6.0-beta.8", "granularPathspec": false, "command": { "publish": { From 989f7f8f92f957cf07a5b1417b31795a8258b00a Mon Sep 17 00:00:00 2001 From: Jason Jean Date: Sat, 29 Jul 2023 10:39:53 -0400 Subject: [PATCH 218/262] chore(repo): update nx to 16.6.0-beta.8 (#18356) --- .circleci/config.yml | 1 + e2e/utils/create-project-utils.ts | 10 +- nx.json | 10 +- package.json | 32 +- packages-legacy/angular/project.json | 2 +- packages/angular/project.json | 2 +- .../styles/stylesheet-processor.ts | 2 +- .../styles/stylesheet-processor.ts | 2 +- .../node/node-with-require-overrides.ts | 2 +- .../files/server/main.ts__tmpl__ | 2 +- packages/nx/src/command-line/graph/graph.ts | 2 +- .../nx/src/command-line/migrate/migrate.ts | 2 +- .../init/__snapshots__/init.spec.ts.snap | 6 +- .../webpack/plugins/postcss-cli-resources.ts | 2 +- pnpm-lock.yaml | 1846 ++++++++++------- scripts/copy-local-native.js | 1 + scripts/nx-release.ts | 5 +- 17 files changed, 1185 insertions(+), 744 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index bbd8f17ac79ed..f9c1fbb8260f6 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -211,6 +211,7 @@ jobs: NX_DAEMON: 'true' NX_PERF_LOGGING: 'false' SELECTED_PM: 'npm' # explicitly define npm for macOS tests + NX_SKIP_NX_CACHE: 'true' # TODO: Figure out what is going on with the cache and renable it steps: - run: name: Set dynamic nx run variable diff --git a/e2e/utils/create-project-utils.ts b/e2e/utils/create-project-utils.ts index e5df3310a4264..45f6e55213ec7 100644 --- a/e2e/utils/create-project-utils.ts +++ b/e2e/utils/create-project-utils.ts @@ -202,11 +202,19 @@ export function runCreateWorkspace( command += ` ${extraArgs}`; } + if (isCI) { + command += ` --verbose`; + } + try { const create = execSync(`${command}${isVerbose() ? ' --verbose' : ''}`, { cwd, stdio: 'pipe', - env: { CI: 'true', ...process.env }, + env: { + CI: 'true', + NX_VERBOSE_LOGGING: isCI ? 'true' : 'false', + ...process.env, + }, encoding: 'utf-8', }); diff --git a/nx.json b/nx.json index b08b2fb8ebf4e..e14cc937548ea 100644 --- a/nx.json +++ b/nx.json @@ -58,8 +58,14 @@ }, "targetDefaults": { "build": { - "dependsOn": ["build-base"], - "inputs": ["production", "^production"] + "dependsOn": ["build-base", "build-native"], + "inputs": [ + "production", + "^production", + { + "dependentTasksOutputFiles": "**/*.node" + } + ] }, "build-native": { "inputs": ["native"] diff --git a/package.json b/package.json index 7b6b20b4f0331..bdb5664ba1b2b 100644 --- a/package.json +++ b/package.json @@ -63,17 +63,17 @@ "@ngrx/router-store": "~16.0.0", "@ngrx/store": "~16.0.0", "@nguniversal/builders": "~16.1.0", - "@nx/cypress": "16.6.0-beta.4", - "@nx/devkit": "16.6.0-beta.4", - "@nx/eslint-plugin": "16.6.0-beta.4", - "@nx/jest": "16.6.0-beta.4", - "@nx/js": "16.6.0-beta.4", - "@nx/linter": "16.6.0-beta.4", - "@nx/next": "16.6.0-beta.4", - "@nx/react": "16.6.0-beta.4", - "@nx/storybook": "16.6.0-beta.4", - "@nx/web": "16.6.0-beta.4", - "@nx/webpack": "16.6.0-beta.4", + "@nx/cypress": "16.6.0-beta.8", + "@nx/devkit": "16.6.0-beta.8", + "@nx/eslint-plugin": "16.6.0-beta.8", + "@nx/jest": "16.6.0-beta.8", + "@nx/js": "16.6.0-beta.8", + "@nx/linter": "16.6.0-beta.8", + "@nx/next": "16.6.0-beta.8", + "@nx/react": "16.6.0-beta.8", + "@nx/storybook": "16.6.0-beta.8", + "@nx/web": "16.6.0-beta.8", + "@nx/webpack": "16.6.0-beta.8", "@parcel/watcher": "2.0.4", "@phenomnomnominal/tsquery": "~5.0.1", "@playwright/test": "^1.36.1", @@ -88,10 +88,10 @@ "@rollup/plugin-url": "^7.0.0", "@schematics/angular": "~16.1.0", "@side/jest-runtime": "^1.1.0", - "@storybook/addon-essentials": "^7.0.24", - "@storybook/core-server": "^7.0.24", - "@storybook/react": "^7.0.24", - "@storybook/react-webpack5": "^7.0.24", + "@storybook/addon-essentials": "7.1.1", + "@storybook/core-server": "7.1.1", + "@storybook/react": "7.1.1", + "@storybook/react-webpack5": "7.1.1", "@storybook/types": "^7.0.24", "@supabase/supabase-js": "^2.26.0", "@svgr/rollup": "^8.0.1", @@ -214,7 +214,7 @@ "next-sitemap": "^3.1.10", "ng-packagr": "~16.1.0", "node-fetch": "^2.6.7", - "nx": "16.6.0-beta.4", + "nx": "16.6.0-beta.8", "nx-cloud": "16.2.0-beta.0", "octokit": "^2.0.14", "open": "^8.4.0", diff --git a/packages-legacy/angular/project.json b/packages-legacy/angular/project.json index 74bd16b022eeb..110df74eaa41f 100644 --- a/packages-legacy/angular/project.json +++ b/packages-legacy/angular/project.json @@ -11,7 +11,7 @@ "project": "packages-legacy/angular/ng-package.json", "tsConfig": "packages-legacy/angular/tsconfig.runtime.json" }, - "outputs": ["build/packages/angular-legacy"] + "outputs": ["{workspaceRoot}/build/packages/angular-legacy"] }, "build-base": { "executor": "@nx/js:tsc", diff --git a/packages/angular/project.json b/packages/angular/project.json index 558b5af6e273c..ad8a8844d7945 100644 --- a/packages/angular/project.json +++ b/packages/angular/project.json @@ -12,7 +12,7 @@ "project": "packages/angular/ng-package.json", "tsConfig": "packages/angular/tsconfig.lib.runtime.json" }, - "outputs": ["build/packages/angular"] + "outputs": ["{workspaceRoot}/build/packages/angular"] }, "build-base": { "executor": "@nx/js:tsc", diff --git a/packages/angular/src/executors/ng-packagr-lite/ng-packagr-adjustments/styles/stylesheet-processor.ts b/packages/angular/src/executors/ng-packagr-lite/ng-packagr-adjustments/styles/stylesheet-processor.ts index 5a420bb8fe3df..3185a2effbc7e 100644 --- a/packages/angular/src/executors/ng-packagr-lite/ng-packagr-adjustments/styles/stylesheet-processor.ts +++ b/packages/angular/src/executors/ng-packagr-lite/ng-packagr-adjustments/styles/stylesheet-processor.ts @@ -20,7 +20,7 @@ import * as log from 'ng-packagr/lib/utils/log'; import { dirname, extname, join } from 'path'; import * as postcssPresetEnv from 'postcss-preset-env'; import * as postcssUrl from 'postcss-url'; -import { pathToFileURL } from 'url'; +import { pathToFileURL } from 'node:url'; import { getInstalledAngularVersionInfo } from '../../../utilities/angular-version-utils'; import { getTailwindPostCssPlugins, diff --git a/packages/angular/src/executors/package/ng-packagr-adjustments/styles/stylesheet-processor.ts b/packages/angular/src/executors/package/ng-packagr-adjustments/styles/stylesheet-processor.ts index 2feacdad779e7..b4d043dd9df95 100644 --- a/packages/angular/src/executors/package/ng-packagr-adjustments/styles/stylesheet-processor.ts +++ b/packages/angular/src/executors/package/ng-packagr-adjustments/styles/stylesheet-processor.ts @@ -20,7 +20,7 @@ import * as log from 'ng-packagr/lib/utils/log'; import { dirname, extname, join } from 'path'; import * as postcssPresetEnv from 'postcss-preset-env'; import * as postcssUrl from 'postcss-url'; -import { pathToFileURL } from 'url'; +import { pathToFileURL } from 'node:url'; import { getInstalledAngularVersionInfo } from '../../../utilities/angular-version-utils'; import { getTailwindPostCssPlugins, diff --git a/packages/js/src/executors/node/node-with-require-overrides.ts b/packages/js/src/executors/node/node-with-require-overrides.ts index b860c5ba6a1f6..a67202a792b1d 100644 --- a/packages/js/src/executors/node/node-with-require-overrides.ts +++ b/packages/js/src/executors/node/node-with-require-overrides.ts @@ -1,5 +1,5 @@ const Module = require('module'); -const url = require('url'); +const url = require('node:url'); const originalLoader = Module._load; const dynamicImport = new Function('specifier', 'return import(specifier)'); diff --git a/packages/next/src/generators/custom-server/files/server/main.ts__tmpl__ b/packages/next/src/generators/custom-server/files/server/main.ts__tmpl__ index 9fd14335a7fb9..cb97705f924ae 100644 --- a/packages/next/src/generators/custom-server/files/server/main.ts__tmpl__ +++ b/packages/next/src/generators/custom-server/files/server/main.ts__tmpl__ @@ -7,7 +7,7 @@ * - Hapi: https://github.com/vercel/next.js/tree/canary/examples/custom-server-hapi */ import { createServer } from 'http'; -import { parse } from 'url'; +import { parse } from 'node:url'; import * as path from 'path'; import next from 'next'; diff --git a/packages/nx/src/command-line/graph/graph.ts b/packages/nx/src/command-line/graph/graph.ts index 4c0760b8ebacb..7da0551b49287 100644 --- a/packages/nx/src/command-line/graph/graph.ts +++ b/packages/nx/src/command-line/graph/graph.ts @@ -6,7 +6,7 @@ import * as http from 'http'; import * as open from 'open'; import { basename, dirname, extname, isAbsolute, join, parse } from 'path'; import { performance } from 'perf_hooks'; -import { URL } from 'url'; +import { URL } from 'node:url'; import { readNxJson, workspaceLayout } from '../../config/configuration'; import { output } from '../../utils/output'; import { writeJsonFile } from '../../utils/fileutils'; diff --git a/packages/nx/src/command-line/migrate/migrate.ts b/packages/nx/src/command-line/migrate/migrate.ts index ff504d9e0e9ab..57889a93ac56d 100644 --- a/packages/nx/src/command-line/migrate/migrate.ts +++ b/packages/nx/src/command-line/migrate/migrate.ts @@ -13,7 +13,7 @@ import { satisfies, valid, } from 'semver'; -import { URL } from 'url'; +import { URL } from 'node:url'; import { promisify } from 'util'; import { MigrationsJson, diff --git a/packages/storybook/src/generators/init/__snapshots__/init.spec.ts.snap b/packages/storybook/src/generators/init/__snapshots__/init.spec.ts.snap index 5bae80eb8cf4d..e70dd930701a8 100644 --- a/packages/storybook/src/generators/init/__snapshots__/init.spec.ts.snap +++ b/packages/storybook/src/generators/init/__snapshots__/init.spec.ts.snap @@ -11,9 +11,9 @@ exports[`@nx/storybook:init dependencies for package.json should add angular rel "@angular/forms": "*", "@nx/js": "0.0.1", "@nx/storybook": "0.0.1", - "@storybook/addon-essentials": "7.0.24", - "@storybook/angular": "7.0.24", - "@storybook/core-server": "7.0.24", + "@storybook/addon-essentials": "7.1.1", + "@storybook/angular": "7.1.1", + "@storybook/core-server": "7.1.1", "existing": "1.0.0", "prettier": "^2.6.2", "typescript": "~5.1.3", diff --git a/packages/webpack/src/utils/webpack/plugins/postcss-cli-resources.ts b/packages/webpack/src/utils/webpack/plugins/postcss-cli-resources.ts index c7223622b358d..5cff9e3dea8d9 100644 --- a/packages/webpack/src/utils/webpack/plugins/postcss-cli-resources.ts +++ b/packages/webpack/src/utils/webpack/plugins/postcss-cli-resources.ts @@ -1,7 +1,7 @@ import { interpolateName } from 'loader-utils'; import * as path from 'path'; import type { Declaration } from 'postcss'; -import * as url from 'url'; +import * as url from 'node:url'; import { LoaderContext } from 'webpack'; function wrapUrl(url: string): string { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1f3ce0f1bbd9a..6ddf88021233a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,5 +1,9 @@ lockfileVersion: '6.0' +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + overrides: minimist: ^1.2.6 underscore: ^1.12.1 @@ -224,7 +228,7 @@ devDependencies: version: 29.5.0 '@monodon/rust': specifier: 1.1.2 - version: 1.1.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.6.0-beta.4)(prettier@2.7.1)(typescript@5.1.3) + version: 1.1.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.6.0-beta.8)(prettier@2.7.1)(typescript@5.1.3) '@napi-rs/cli': specifier: 2.14.0 version: 2.14.0 @@ -262,38 +266,38 @@ devDependencies: specifier: ~16.1.0 version: 16.1.0(@angular-devkit/build-angular@16.1.0)(@angular/common@16.1.0)(@angular/core@16.1.0)(@types/express@4.17.14)(chokidar@3.5.3)(typescript@5.1.3) '@nx/cypress': - specifier: 16.6.0-beta.4 - version: 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + specifier: 16.6.0-beta.8 + version: 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4) '@nx/devkit': - specifier: 16.6.0-beta.4 - version: 16.6.0-beta.4(nx@16.6.0-beta.4) + specifier: 16.6.0-beta.8 + version: 16.6.0-beta.8(nx@16.6.0-beta.8) '@nx/eslint-plugin': - specifier: 16.6.0-beta.4 - version: 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(@typescript-eslint/parser@5.60.1)(eslint-config-prettier@8.5.0)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + specifier: 16.6.0-beta.8 + version: 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(@typescript-eslint/parser@5.60.1)(eslint-config-prettier@8.5.0)(eslint@8.15.0)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4) '@nx/jest': - specifier: 16.6.0-beta.4 - version: 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4) + specifier: 16.6.0-beta.8 + version: 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.8)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4) '@nx/js': - specifier: 16.6.0-beta.4 - version: 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + specifier: 16.6.0-beta.8 + version: 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4) '@nx/linter': - specifier: 16.6.0-beta.4 - version: 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + specifier: 16.6.0-beta.8 + version: 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4) '@nx/next': - specifier: 16.6.0-beta.4 - version: 16.6.0-beta.4(@babel/core@7.22.9)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/express@4.17.14)(@types/node@18.16.9)(eslint@8.15.0)(file-loader@6.2.0)(next@13.3.4)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) + specifier: 16.6.0-beta.8 + version: 16.6.0-beta.8(@babel/core@7.22.9)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(file-loader@6.2.0)(next@13.3.4)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) '@nx/react': - specifier: 16.6.0-beta.4 - version: 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) + specifier: 16.6.0-beta.8 + version: 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) '@nx/storybook': - specifier: 16.6.0-beta.4 - version: 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + specifier: 16.6.0-beta.8 + version: 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4) '@nx/web': - specifier: 16.6.0-beta.4 - version: 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + specifier: 16.6.0-beta.8 + version: 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4) '@nx/webpack': - specifier: 16.6.0-beta.4 - version: 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(esbuild@0.17.5)(html-webpack-plugin@5.5.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + specifier: 16.6.0-beta.8 + version: 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(esbuild@0.17.5)(html-webpack-plugin@5.5.0)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4) '@parcel/watcher': specifier: 2.0.4 version: 2.0.4 @@ -337,17 +341,17 @@ devDependencies: specifier: ^1.1.0 version: 1.1.0(@jest/transform@29.5.0)(jest-runtime@29.5.0)(jest@29.4.3) '@storybook/addon-essentials': - specifier: ^7.0.24 - version: 7.0.24(react-dom@18.2.0)(react@18.2.0) + specifier: 7.1.1 + version: 7.1.1(react-dom@18.2.0)(react@18.2.0) '@storybook/core-server': - specifier: ^7.0.24 - version: 7.0.24 + specifier: 7.1.1 + version: 7.1.1 '@storybook/react': - specifier: ^7.0.24 - version: 7.0.24(react-dom@18.2.0)(react@18.2.0)(typescript@5.1.3) + specifier: 7.1.1 + version: 7.1.1(react-dom@18.2.0)(react@18.2.0)(typescript@5.1.3) '@storybook/react-webpack5': - specifier: ^7.0.24 - version: 7.0.24(@babel/core@7.22.9)(@swc/core@1.3.51)(esbuild@0.17.5)(react-dom@18.2.0)(react@18.2.0)(typescript@5.1.3)(webpack-dev-server@4.11.1) + specifier: 7.1.1 + version: 7.1.1(@babel/core@7.22.9)(@swc/core@1.3.51)(@swc/helpers@0.5.0)(esbuild@0.17.5)(react-dom@18.2.0)(react@18.2.0)(typescript@5.1.3)(webpack-dev-server@4.11.1) '@storybook/types': specifier: ^7.0.24 version: 7.0.24 @@ -715,8 +719,8 @@ devDependencies: specifier: ^2.6.7 version: 2.6.7 nx: - specifier: 16.6.0-beta.4 - version: 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51) + specifier: 16.6.0-beta.8 + version: 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51) nx-cloud: specifier: 16.2.0-beta.0 version: 16.2.0-beta.0 @@ -1533,8 +1537,8 @@ packages: resolution: {integrity: sha512-H71nDOOL8Y7kWRLqf6Sums+01Q5msqBW2KhDUTemh1tvY04eSkSXrK0uj/4mmY0Xr16/3zyZmsrxN7CKuRbNRg==} dev: true - /@aw-web-design/x-default-browser@1.4.88: - resolution: {integrity: sha512-AkEmF0wcwYC2QkhK703Y83fxWARttIWXDmQN8+cof8FmFZ5BRhnNXGymeb1S73bOCLfWjYELxtujL56idCN/XA==} + /@aw-web-design/x-default-browser@1.4.126: + resolution: {integrity: sha512-Xk1sIhyNC/esHGGVjL/niHLowM0csl/kFO5uawBy4IrWwy0o1G8LGt3jP6nmWGz+USxeeqbihAmp/oVZju6wug==} hasBin: true dependencies: default-browser-id: 3.0.0 @@ -1630,16 +1634,6 @@ packages: transitivePeerDependencies: - supports-color - /@babel/generator@7.21.4: - resolution: {integrity: sha512-NieM3pVIYW2SwGzKoqfPrQsf4xGs9M9AIG3ThppsSRmO+m7eQhmI6amajKMUeIO37wFfsvnvcxQFx6x6iqxDnA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.22.5 - '@jridgewell/gen-mapping': 0.3.3 - '@jridgewell/trace-mapping': 0.3.18 - jsesc: 2.5.2 - dev: true - /@babel/generator@7.22.5: resolution: {integrity: sha512-+lcUbnTRhd0jOewtFSedLyiPsD5tswKkbgcezOqqWFUVNEwoUTlpPOBmvhG7OXWLR4jMdv0czPGH5XbflnD1EA==} engines: {node: '>=6.9.0'} @@ -1714,24 +1708,6 @@ packages: lru-cache: 5.1.1 semver: 6.3.1 - /@babel/helper-create-class-features-plugin@7.22.5(@babel/core@7.22.9): - resolution: {integrity: sha512-xkb58MyOYIslxu3gKmVXmjTtUPvBU4odYzbiIQbWwLKIHCsx6UGZGX6F1IznMFVnDdirseUZopzN+ZRt8Xb33Q==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-environment-visitor': 7.22.5 - '@babel/helper-function-name': 7.22.5 - '@babel/helper-member-expression-to-functions': 7.22.5 - '@babel/helper-optimise-call-expression': 7.22.5 - '@babel/helper-replace-supers': 7.22.9(@babel/core@7.22.9) - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.6 - semver: 6.3.1 - dev: true - /@babel/helper-create-class-features-plugin@7.22.9(@babel/core@7.22.5): resolution: {integrity: sha512-Pwyi89uO4YrGKxL/eNJ8lfEH55DnRloGPOseaA8NFNL6jAUnn+KccaISiFazCj5IolPPDjGSdzQzXVzODVRqUQ==} engines: {node: '>=6.9.0'} @@ -1958,20 +1934,6 @@ packages: - supports-color dev: true - /@babel/helper-replace-supers@7.22.5: - resolution: {integrity: sha512-aLdNM5I3kdI/V9xGNyKSF3X/gTyMUBohTZ+/3QdQKAA9vxIiy12E+8E2HoOP1/DjeqU+g6as35QHJNMDDYpuCg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-environment-visitor': 7.22.5 - '@babel/helper-member-expression-to-functions': 7.22.5 - '@babel/helper-optimise-call-expression': 7.22.5 - '@babel/template': 7.22.5 - '@babel/traverse': 7.22.8 - '@babel/types': 7.22.5 - transitivePeerDependencies: - - supports-color - dev: true - /@babel/helper-replace-supers@7.22.9(@babel/core@7.22.5): resolution: {integrity: sha512-LJIKvvpgPOPUThdYqcX6IXRuIcTkcAub0IaDRGCZH0p5GPUp7PhRU9QVgFcDDd51BaPkk77ZjqFwh6DZTAEmGg==} engines: {node: '>=6.9.0'} @@ -2064,14 +2026,6 @@ packages: chalk: 2.4.2 js-tokens: 4.0.0 - /@babel/parser@7.21.4: - resolution: {integrity: sha512-alVJj7k7zIxqBZ7BTRhz0IqJFxW1VJbm6N8JbcYhQ186df9ZBPbZBmWSqAMXwHGsCJdYks7z/voa3ibiS5bCIw==} - engines: {node: '>=6.0.0'} - hasBin: true - dependencies: - '@babel/types': 7.22.5 - dev: true - /@babel/parser@7.22.7: resolution: {integrity: sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q==} engines: {node: '>=6.0.0'} @@ -2160,7 +2114,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.22.9 - '@babel/helper-create-class-features-plugin': 7.22.5(@babel/core@7.22.9) + '@babel/helper-create-class-features-plugin': 7.22.9(@babel/core@7.22.9) '@babel/helper-plugin-utils': 7.22.5 dev: true @@ -2183,13 +2137,25 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.22.9 - '@babel/helper-create-class-features-plugin': 7.22.5(@babel/core@7.22.9) + '@babel/helper-create-class-features-plugin': 7.22.9(@babel/core@7.22.9) '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-replace-supers': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.5 + '@babel/helper-replace-supers': 7.22.9(@babel/core@7.22.9) + '@babel/helper-split-export-declaration': 7.22.6 '@babel/plugin-syntax-decorators': 7.21.0(@babel/core@7.22.9) - transitivePeerDependencies: - - supports-color + dev: true + + /@babel/plugin-proposal-decorators@7.22.7(@babel/core@7.22.9): + resolution: {integrity: sha512-omXqPF7Onq4Bb7wHxXjM3jSMSJvUUbvDvmmds7KI5n9Cq6Ln5I05I1W2nRlRof1rGdiUxJrxwe285WF96XlBXQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-create-class-features-plugin': 7.22.9(@babel/core@7.22.9) + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-replace-supers': 7.22.9(@babel/core@7.22.9) + '@babel/helper-split-export-declaration': 7.22.6 + '@babel/plugin-syntax-decorators': 7.22.5(@babel/core@7.22.9) dev: true /@babel/plugin-proposal-dynamic-import@7.18.6(@babel/core@7.22.9): @@ -2445,6 +2411,16 @@ packages: '@babel/helper-plugin-utils': 7.22.5 dev: true + /@babel/plugin-syntax-decorators@7.22.5(@babel/core@7.22.9): + resolution: {integrity: sha512-avpUOBS7IU6al8MmF1XpAyj9QYeLPuSDJI5D4pVMSMdL7xQokKqJPYQC67RCT0aCTashUXPiGwMJ0DEXXCEmMA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + /@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.22.5): resolution: {integrity: sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==} peerDependencies: @@ -2501,6 +2477,16 @@ packages: '@babel/helper-plugin-utils': 7.22.5 dev: true + /@babel/plugin-syntax-flow@7.22.5(@babel/core@7.22.9): + resolution: {integrity: sha512-9RdCl0i+q0QExayk2nOS7853w08yLucnnPML6EN9S8fgMPVtdLDCdx/cOQ/i44Lb9UeQX9A35yaqBBOMMZxPxQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + /@babel/plugin-syntax-import-assertions@7.22.5(@babel/core@7.22.5): resolution: {integrity: sha512-rdV97N7KqsRzeNGoWUOK6yUsWarLjE5Su/Snk9IYPU9CwkWHs4t+rTGOvffTR8XGkJMTAdLfO0xVnXm8wugIJg==} engines: {node: '>=6.9.0'} @@ -2735,16 +2721,6 @@ packages: '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-syntax-typescript@7.20.0(@babel/core@7.22.9): - resolution: {integrity: sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.22.5 - dev: true - /@babel/plugin-syntax-typescript@7.22.5(@babel/core@7.22.9): resolution: {integrity: sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==} engines: {node: '>=6.9.0'} @@ -2827,6 +2803,21 @@ packages: - supports-color dev: true + /@babel/plugin-transform-async-generator-functions@7.22.7(@babel/core@7.22.9): + resolution: {integrity: sha512-7HmE7pk/Fmke45TODvxvkxRMV9RazV+ZZzhOL9AG8G29TLrr3jkjwF7uJfxZ30EoXpO+LJkq4oA8NjO2DTnEDg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-environment-visitor': 7.22.5 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-remap-async-to-generator': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.22.9) + transitivePeerDependencies: + - supports-color + dev: true + /@babel/plugin-transform-async-to-generator@7.22.5(@babel/core@7.22.5): resolution: {integrity: sha512-b1A8D8ZzE/VhNDoV1MSJTnpKkCG5bJo+19R4o4oy03zM7ws8yEMK755j61Dc3EyvdysbqH5BOOTquJ7ZX9C6vQ==} engines: {node: '>=6.9.0'} @@ -2977,6 +2968,24 @@ packages: globals: 11.12.0 dev: true + /@babel/plugin-transform-classes@7.22.6(@babel/core@7.22.9): + resolution: {integrity: sha512-58EgM6nuPNG6Py4Z3zSuu0xWu2VfodiMi72Jt5Kj2FECmaYk1RrTXA45z6KBFsu9tRgwQDwIiY4FXTt+YsSFAQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-annotate-as-pure': 7.22.5 + '@babel/helper-compilation-targets': 7.22.9(@babel/core@7.22.9) + '@babel/helper-environment-visitor': 7.22.5 + '@babel/helper-function-name': 7.22.5 + '@babel/helper-optimise-call-expression': 7.22.5 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-replace-supers': 7.22.9(@babel/core@7.22.9) + '@babel/helper-split-export-declaration': 7.22.6 + globals: 11.12.0 + dev: true + /@babel/plugin-transform-computed-properties@7.22.5(@babel/core@7.22.5): resolution: {integrity: sha512-4GHWBgRf0krxPX+AaPtgBAlTgTeZmqDynokHOX7aqqAB4tHs3U2Y02zH6ETFdLZGcg9UQSD1WCmkVrE9ErHeOg==} engines: {node: '>=6.9.0'} @@ -3138,6 +3147,17 @@ packages: '@babel/plugin-syntax-flow': 7.18.6(@babel/core@7.22.9) dev: true + /@babel/plugin-transform-flow-strip-types@7.22.5(@babel/core@7.22.9): + resolution: {integrity: sha512-tujNbZdxdG0/54g/oua8ISToaXTFBf8EnSb5PgQSciIXWOWKX3S4+JR7ZE9ol8FZwf9kxitzkGQ+QWeov/mCiA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-syntax-flow': 7.22.5(@babel/core@7.22.9) + dev: true + /@babel/plugin-transform-for-of@7.22.5(@babel/core@7.22.5): resolution: {integrity: sha512-3kxQjX1dU9uudwSshyLeEipvrLjBCVthCgeTp6CzE/9JYrlAIaeekVxRpCWsDDfYTfRZRoCeZatCQvwo+wvK8A==} engines: {node: '>=6.9.0'} @@ -3542,6 +3562,18 @@ packages: '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.22.9) dev: true + /@babel/plugin-transform-optional-chaining@7.22.6(@babel/core@7.22.9): + resolution: {integrity: sha512-Vd5HiWml0mDVtcLHIoEU5sw6HOUW/Zk0acLs/SAeuLzkGNOPc9DB4nkUajemhCmTIz3eiaKREZn2hQQqF79YTg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.22.9) + dev: true + /@babel/plugin-transform-parameters@7.22.5(@babel/core@7.22.5): resolution: {integrity: sha512-AVkFUBurORBREOmHRKo06FjHYgjrabpdqRSwq6+C7R5iTCZOsM4QbcB27St0a4U6fffyAOqh3s/qEfybAhfivg==} engines: {node: '>=6.9.0'} @@ -4250,16 +4282,107 @@ packages: - supports-color dev: true - /@babel/preset-flow@7.21.4(@babel/core@7.22.9): - resolution: {integrity: sha512-F24cSq4DIBmhq4OzK3dE63NHagb27OPE3eWR+HLekt4Z3Y5MzIIUGF3LlLgV0gN8vzbDViSY7HnrReNVCJXTeA==} + /@babel/preset-env@7.22.9(@babel/core@7.22.9): + resolution: {integrity: sha512-wNi5H/Emkhll/bqPjsjQorSykrlfY5OWakd6AulLvMEytpKasMVUpVy8RL4qBIBs5Ac6/5i0/Rv0b/Fg6Eag/g==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: + '@babel/compat-data': 7.22.9 '@babel/core': 7.22.9 + '@babel/helper-compilation-targets': 7.22.9(@babel/core@7.22.9) '@babel/helper-plugin-utils': 7.22.5 '@babel/helper-validator-option': 7.22.5 - '@babel/plugin-transform-flow-strip-types': 7.21.0(@babel/core@7.22.9) + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.22.9) + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.22.9) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.22.9) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.22.9) + '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.22.9) + '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.22.9) + '@babel/plugin-syntax-import-assertions': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-syntax-import-attributes': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.22.9) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.22.9) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.22.9) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.22.9) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.22.9) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.22.9) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.22.9) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.22.9) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.22.9) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.22.9) + '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.22.9) + '@babel/plugin-transform-arrow-functions': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-async-generator-functions': 7.22.7(@babel/core@7.22.9) + '@babel/plugin-transform-async-to-generator': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-block-scoped-functions': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-block-scoping': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-class-properties': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-class-static-block': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-classes': 7.22.6(@babel/core@7.22.9) + '@babel/plugin-transform-computed-properties': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-destructuring': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-dotall-regex': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-duplicate-keys': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-dynamic-import': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-exponentiation-operator': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-export-namespace-from': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-for-of': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-function-name': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-json-strings': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-literals': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-logical-assignment-operators': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-member-expression-literals': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-modules-amd': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-modules-commonjs': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-modules-systemjs': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-modules-umd': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-named-capturing-groups-regex': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-new-target': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-nullish-coalescing-operator': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-numeric-separator': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-object-rest-spread': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-object-super': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-optional-catch-binding': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-optional-chaining': 7.22.6(@babel/core@7.22.9) + '@babel/plugin-transform-parameters': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-private-methods': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-private-property-in-object': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-property-literals': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-regenerator': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-reserved-words': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-shorthand-properties': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-spread': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-sticky-regex': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-template-literals': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-typeof-symbol': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-unicode-escapes': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-unicode-property-regex': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-unicode-regex': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-unicode-sets-regex': 7.22.5(@babel/core@7.22.9) + '@babel/preset-modules': 0.1.5(@babel/core@7.22.9) + '@babel/types': 7.22.5 + babel-plugin-polyfill-corejs2: 0.4.4(@babel/core@7.22.9) + babel-plugin-polyfill-corejs3: 0.8.2(@babel/core@7.22.9) + babel-plugin-polyfill-regenerator: 0.5.1(@babel/core@7.22.9) + core-js-compat: 3.31.1 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/preset-flow@7.22.5(@babel/core@7.22.9): + resolution: {integrity: sha512-ta2qZ+LSiGCrP5pgcGt8xMnnkXQrq8Sa4Ulhy06BOlF5QbLw9q5hIx7bn5MrsvyTGAfh6kTOo07Q+Pfld/8Y5Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-validator-option': 7.22.5 + '@babel/plugin-transform-flow-strip-types': 7.22.5(@babel/core@7.22.9) dev: true /@babel/preset-modules@0.1.5(@babel/core@7.22.5): @@ -4385,15 +4508,6 @@ packages: transitivePeerDependencies: - supports-color - /@babel/types@7.21.4: - resolution: {integrity: sha512-rU2oY501qDxE8Pyo7i/Orqma4ziCOrby0/9mvbDUGEfvZjb279Nk9k19e2fiCxHbRRpY2ZyrgW1eq22mvmOIzA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-string-parser': 7.22.5 - '@babel/helper-validator-identifier': 7.22.5 - to-fast-properties: 2.0.0 - dev: true - /@babel/types@7.22.5: resolution: {integrity: sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==} engines: {node: '>=6.9.0'} @@ -4624,6 +4738,7 @@ packages: /@emotion/memoize@0.7.4: resolution: {integrity: sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==} + requiresBuild: true dev: false optional: true @@ -4672,6 +4787,15 @@ packages: dev: true optional: true + /@esbuild/android-arm64@0.18.17: + resolution: {integrity: sha512-9np+YYdNDed5+Jgr1TdWBsozZ85U1Oa3xW0c7TWqH0y2aGghXtZsuT8nYRbzOMcl0bXZXjOGbksoTtVOlWrRZg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + /@esbuild/android-arm@0.17.18: resolution: {integrity: sha512-EmwL+vUBZJ7mhFCs5lA4ZimpUH3WMAoqvOIYhVQwdIgSpHC8ImHdsRyhHAVxpDYUSm0lWvd63z0XH1IlImS2Qw==} engines: {node: '>=12'} @@ -4697,6 +4821,15 @@ packages: dev: true optional: true + /@esbuild/android-arm@0.18.17: + resolution: {integrity: sha512-wHsmJG/dnL3OkpAcwbgoBTTMHVi4Uyou3F5mf58ZtmUyIKfcdA7TROav/6tCzET4A3QW2Q2FC+eFneMU+iyOxg==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + /@esbuild/android-x64@0.17.18: resolution: {integrity: sha512-x+0efYNBF3NPW2Xc5bFOSFW7tTXdAcpfEg2nXmxegm4mJuVeS+i109m/7HMiOQ6M12aVGGFlqJX3RhNdYM2lWg==} engines: {node: '>=12'} @@ -4722,6 +4855,15 @@ packages: dev: true optional: true + /@esbuild/android-x64@0.18.17: + resolution: {integrity: sha512-O+FeWB/+xya0aLg23hHEM2E3hbfwZzjqumKMSIqcHbNvDa+dza2D0yLuymRBQQnC34CWrsJUXyH2MG5VnLd6uw==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + /@esbuild/darwin-arm64@0.17.18: resolution: {integrity: sha512-6tY+djEAdF48M1ONWnQb1C+6LiXrKjmqjzPNPWXhu/GzOHTHX2nh8Mo2ZAmBFg0kIodHhciEgUBtcYCAIjGbjQ==} engines: {node: '>=12'} @@ -4747,6 +4889,15 @@ packages: dev: true optional: true + /@esbuild/darwin-arm64@0.18.17: + resolution: {integrity: sha512-M9uJ9VSB1oli2BE/dJs3zVr9kcCBBsE883prage1NWz6pBS++1oNn/7soPNS3+1DGj0FrkSvnED4Bmlu1VAE9g==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + /@esbuild/darwin-x64@0.17.18: resolution: {integrity: sha512-Qq84ykvLvya3dO49wVC9FFCNUfSrQJLbxhoQk/TE1r6MjHo3sFF2tlJCwMjhkBVq3/ahUisj7+EpRSz0/+8+9A==} engines: {node: '>=12'} @@ -4772,6 +4923,15 @@ packages: dev: true optional: true + /@esbuild/darwin-x64@0.18.17: + resolution: {integrity: sha512-XDre+J5YeIJDMfp3n0279DFNrGCXlxOuGsWIkRb1NThMZ0BsrWXoTg23Jer7fEXQ9Ye5QjrvXpxnhzl3bHtk0g==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + /@esbuild/freebsd-arm64@0.17.18: resolution: {integrity: sha512-fw/ZfxfAzuHfaQeMDhbzxp9mc+mHn1Y94VDHFHjGvt2Uxl10mT4CDavHm+/L9KG441t1QdABqkVYwakMUeyLRA==} engines: {node: '>=12'} @@ -4797,6 +4957,15 @@ packages: dev: true optional: true + /@esbuild/freebsd-arm64@0.18.17: + resolution: {integrity: sha512-cjTzGa3QlNfERa0+ptykyxs5A6FEUQQF0MuilYXYBGdBxD3vxJcKnzDlhDCa1VAJCmAxed6mYhA2KaJIbtiNuQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + /@esbuild/freebsd-x64@0.17.18: resolution: {integrity: sha512-FQFbRtTaEi8ZBi/A6kxOC0V0E9B/97vPdYjY9NdawyLd4Qk5VD5g2pbWN2VR1c0xhzcJm74HWpObPszWC+qTew==} engines: {node: '>=12'} @@ -4822,6 +4991,15 @@ packages: dev: true optional: true + /@esbuild/freebsd-x64@0.18.17: + resolution: {integrity: sha512-sOxEvR8d7V7Kw8QqzxWc7bFfnWnGdaFBut1dRUYtu+EIRXefBc/eIsiUiShnW0hM3FmQ5Zf27suDuHsKgZ5QrA==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-arm64@0.17.18: resolution: {integrity: sha512-R7pZvQZFOY2sxUG8P6A21eq6q+eBv7JPQYIybHVf1XkQYC+lT7nDBdC7wWKTrbvMXKRaGudp/dzZCwL/863mZQ==} engines: {node: '>=12'} @@ -4847,6 +5025,15 @@ packages: dev: true optional: true + /@esbuild/linux-arm64@0.18.17: + resolution: {integrity: sha512-c9w3tE7qA3CYWjT+M3BMbwMt+0JYOp3vCMKgVBrCl1nwjAlOMYzEo+gG7QaZ9AtqZFj5MbUc885wuBBmu6aADQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-arm@0.17.18: resolution: {integrity: sha512-jW+UCM40LzHcouIaqv3e/oRs0JM76JfhHjCavPxMUti7VAPh8CaGSlS7cmyrdpzSk7A+8f0hiedHqr/LMnfijg==} engines: {node: '>=12'} @@ -4872,6 +5059,15 @@ packages: dev: true optional: true + /@esbuild/linux-arm@0.18.17: + resolution: {integrity: sha512-2d3Lw6wkwgSLC2fIvXKoMNGVaeY8qdN0IC3rfuVxJp89CRfA3e3VqWifGDfuakPmp90+ZirmTfye1n4ncjv2lg==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-ia32@0.17.18: resolution: {integrity: sha512-ygIMc3I7wxgXIxk6j3V00VlABIjq260i967Cp9BNAk5pOOpIXmd1RFQJQX9Io7KRsthDrQYrtcx7QCof4o3ZoQ==} engines: {node: '>=12'} @@ -4897,6 +5093,15 @@ packages: dev: true optional: true + /@esbuild/linux-ia32@0.18.17: + resolution: {integrity: sha512-1DS9F966pn5pPnqXYz16dQqWIB0dmDfAQZd6jSSpiT9eX1NzKh07J6VKR3AoXXXEk6CqZMojiVDSZi1SlmKVdg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-loong64@0.17.18: resolution: {integrity: sha512-bvPG+MyFs5ZlwYclCG1D744oHk1Pv7j8psF5TfYx7otCVmcJsEXgFEhQkbhNW8otDHL1a2KDINW20cfCgnzgMQ==} engines: {node: '>=12'} @@ -4922,6 +5127,15 @@ packages: dev: true optional: true + /@esbuild/linux-loong64@0.18.17: + resolution: {integrity: sha512-EvLsxCk6ZF0fpCB6w6eOI2Fc8KW5N6sHlIovNe8uOFObL2O+Mr0bflPHyHwLT6rwMg9r77WOAWb2FqCQrVnwFg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-mips64el@0.17.18: resolution: {integrity: sha512-oVqckATOAGuiUOa6wr8TXaVPSa+6IwVJrGidmNZS1cZVx0HqkTMkqFGD2HIx9H1RvOwFeWYdaYbdY6B89KUMxA==} engines: {node: '>=12'} @@ -4947,6 +5161,15 @@ packages: dev: true optional: true + /@esbuild/linux-mips64el@0.18.17: + resolution: {integrity: sha512-e0bIdHA5p6l+lwqTE36NAW5hHtw2tNRmHlGBygZC14QObsA3bD4C6sXLJjvnDIjSKhW1/0S3eDy+QmX/uZWEYQ==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-ppc64@0.17.18: resolution: {integrity: sha512-3dLlQO+b/LnQNxgH4l9rqa2/IwRJVN9u/bK63FhOPB4xqiRqlQAU0qDU3JJuf0BmaH0yytTBdoSBHrb2jqc5qQ==} engines: {node: '>=12'} @@ -4972,6 +5195,15 @@ packages: dev: true optional: true + /@esbuild/linux-ppc64@0.18.17: + resolution: {integrity: sha512-BAAilJ0M5O2uMxHYGjFKn4nJKF6fNCdP1E0o5t5fvMYYzeIqy2JdAP88Az5LHt9qBoUa4tDaRpfWt21ep5/WqQ==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-riscv64@0.17.18: resolution: {integrity: sha512-/x7leOyDPjZV3TcsdfrSI107zItVnsX1q2nho7hbbQoKnmoeUWjs+08rKKt4AUXju7+3aRZSsKrJtaRmsdL1xA==} engines: {node: '>=12'} @@ -4997,6 +5229,15 @@ packages: dev: true optional: true + /@esbuild/linux-riscv64@0.18.17: + resolution: {integrity: sha512-Wh/HW2MPnC3b8BqRSIme/9Zhab36PPH+3zam5pqGRH4pE+4xTrVLx2+XdGp6fVS3L2x+DrsIcsbMleex8fbE6g==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-s390x@0.17.18: resolution: {integrity: sha512-cX0I8Q9xQkL/6F5zWdYmVf5JSQt+ZfZD2bJudZrWD+4mnUvoZ3TDDXtDX2mUaq6upMFv9FlfIh4Gfun0tbGzuw==} engines: {node: '>=12'} @@ -5022,6 +5263,15 @@ packages: dev: true optional: true + /@esbuild/linux-s390x@0.18.17: + resolution: {integrity: sha512-j/34jAl3ul3PNcK3pfI0NSlBANduT2UO5kZ7FCaK33XFv3chDhICLY8wJJWIhiQ+YNdQ9dxqQctRg2bvrMlYgg==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-x64@0.17.18: resolution: {integrity: sha512-66RmRsPlYy4jFl0vG80GcNRdirx4nVWAzJmXkevgphP1qf4dsLQCpSKGM3DUQCojwU1hnepI63gNZdrr02wHUA==} engines: {node: '>=12'} @@ -5047,6 +5297,15 @@ packages: dev: true optional: true + /@esbuild/linux-x64@0.18.17: + resolution: {integrity: sha512-QM50vJ/y+8I60qEmFxMoxIx4de03pGo2HwxdBeFd4nMh364X6TIBZ6VQ5UQmPbQWUVWHWws5MmJXlHAXvJEmpQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/netbsd-x64@0.17.18: resolution: {integrity: sha512-95IRY7mI2yrkLlTLb1gpDxdC5WLC5mZDi+kA9dmM5XAGxCME0F8i4bYH4jZreaJ6lIZ0B8hTrweqG1fUyW7jbg==} engines: {node: '>=12'} @@ -5072,6 +5331,15 @@ packages: dev: true optional: true + /@esbuild/netbsd-x64@0.18.17: + resolution: {integrity: sha512-/jGlhWR7Sj9JPZHzXyyMZ1RFMkNPjC6QIAan0sDOtIo2TYk3tZn5UDrkE0XgsTQCxWTTOcMPf9p6Rh2hXtl5TQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: true + optional: true + /@esbuild/openbsd-x64@0.17.18: resolution: {integrity: sha512-WevVOgcng+8hSZ4Q3BKL3n1xTv5H6Nb53cBrtzzEjDbbnOmucEVcZeGCsCOi9bAOcDYEeBZbD2SJNBxlfP3qiA==} engines: {node: '>=12'} @@ -5097,6 +5365,15 @@ packages: dev: true optional: true + /@esbuild/openbsd-x64@0.18.17: + resolution: {integrity: sha512-rSEeYaGgyGGf4qZM2NonMhMOP/5EHp4u9ehFiBrg7stH6BYEEjlkVREuDEcQ0LfIl53OXLxNbfuIj7mr5m29TA==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + /@esbuild/sunos-x64@0.17.18: resolution: {integrity: sha512-Rzf4QfQagnwhQXVBS3BYUlxmEbcV7MY+BH5vfDZekU5eYpcffHSyjU8T0xucKVuOcdCsMo+Ur5wmgQJH2GfNrg==} engines: {node: '>=12'} @@ -5122,6 +5399,15 @@ packages: dev: true optional: true + /@esbuild/sunos-x64@0.18.17: + resolution: {integrity: sha512-Y7ZBbkLqlSgn4+zot4KUNYst0bFoO68tRgI6mY2FIM+b7ZbyNVtNbDP5y8qlu4/knZZ73fgJDlXID+ohY5zt5g==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: true + optional: true + /@esbuild/win32-arm64@0.17.18: resolution: {integrity: sha512-Kb3Ko/KKaWhjeAm2YoT/cNZaHaD1Yk/pa3FTsmqo9uFh1D1Rfco7BBLIPdDOozrObj2sahslFuAQGvWbgWldAg==} engines: {node: '>=12'} @@ -5147,6 +5433,15 @@ packages: dev: true optional: true + /@esbuild/win32-arm64@0.18.17: + resolution: {integrity: sha512-bwPmTJsEQcbZk26oYpc4c/8PvTY3J5/QK8jM19DVlEsAB41M39aWovWoHtNm78sd6ip6prilxeHosPADXtEJFw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + /@esbuild/win32-ia32@0.17.18: resolution: {integrity: sha512-0/xUMIdkVHwkvxfbd5+lfG7mHOf2FRrxNbPiKWg9C4fFrB8H0guClmaM3BFiRUYrznVoyxTIyC/Ou2B7QQSwmw==} engines: {node: '>=12'} @@ -5172,6 +5467,15 @@ packages: dev: true optional: true + /@esbuild/win32-ia32@0.18.17: + resolution: {integrity: sha512-H/XaPtPKli2MhW+3CQueo6Ni3Avggi6hP/YvgkEe1aSaxw+AeO8MFjq8DlgfTd9Iz4Yih3QCZI6YLMoyccnPRg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + /@esbuild/win32-x64@0.17.18: resolution: {integrity: sha512-qU25Ma1I3NqTSHJUOKi9sAH1/Mzuvlke0ioMJRthLXKm7JiSKVwFghlGbDLOO2sARECGhja4xYfRAZNPAkooYg==} engines: {node: '>=12'} @@ -5197,6 +5501,15 @@ packages: dev: true optional: true + /@esbuild/win32-x64@0.18.17: + resolution: {integrity: sha512-fGEb8f2BSA3CW7riJVurug65ACLuQAzKq0SSqkY2b2yHHH0MzDfbLyKIGzHwOI/gkHcxM/leuSW6D5w/LMNitA==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + /@eslint-community/eslint-utils@4.4.0(eslint@8.15.0): resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -5600,6 +5913,7 @@ packages: dependencies: '@jridgewell/gen-mapping': 0.3.3 '@jridgewell/trace-mapping': 0.3.18 + dev: true /@jridgewell/sourcemap-codec@1.4.14: resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==} @@ -5805,12 +6119,12 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false - /@monodon/rust@1.1.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.6.0-beta.4)(prettier@2.7.1)(typescript@5.1.3): + /@monodon/rust@1.1.2(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.6.0-beta.8)(prettier@2.7.1)(typescript@5.1.3): resolution: {integrity: sha512-lb667coCcsWmkHuSKfGHgEeaWK24VGrW3AgA7Wq2M8wVVhuVQeKAV2UDt5vgvQj+xPlXPyKs6iPqNFXi3c2nLA==} dependencies: '@ltd/j-toml': 1.38.0 - '@nrwl/devkit': 15.8.0(nx@16.6.0-beta.4)(typescript@5.1.3) - '@nrwl/js': 15.8.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.6.0-beta.4)(prettier@2.7.1)(typescript@5.1.3) + '@nrwl/devkit': 15.8.0(nx@16.6.0-beta.8)(typescript@5.1.3) + '@nrwl/js': 15.8.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.6.0-beta.8)(prettier@2.7.1)(typescript@5.1.3) chalk: 4.1.2 transitivePeerDependencies: - '@babel/traverse' @@ -6541,10 +6855,10 @@ packages: - debug dev: true - /@nrwl/cypress@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-6AN9HxAKGLMARBVy7lJkMkDAAPfNxiv1iJDsKAOlGRfc3DfjmgrYBTH5dmzmNL8MvgKG+itSSNhBjAkiB2S9sQ==} + /@nrwl/cypress@16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-oduXI4OL/EmEzAFZYzwKVXBPZn/KbR4IcZoQyHlChCIDaBlaQwv4JPGdbAntRhQJilYApLGPA3Ajl9vwoXch8g==} dependencies: - '@nx/cypress': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/cypress': 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4) transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -6592,7 +6906,7 @@ packages: - typescript dev: true - /@nrwl/devkit@15.8.0(nx@16.6.0-beta.4)(typescript@5.1.3): + /@nrwl/devkit@15.8.0(nx@16.6.0-beta.8)(typescript@5.1.3): resolution: {integrity: sha512-qD+asvhTXIibXPXr3r1IDP7ap3Bw5H7tSd+C5mXFhIMMinTqRnQVXe6Odfs34VFP/dpWBIBZdkkwCM/+BsCLNw==} peerDependencies: nx: '>= 14.1 <= 16' @@ -6600,7 +6914,7 @@ packages: '@phenomnomnominal/tsquery': 4.1.1(typescript@5.1.3) ejs: 3.1.8 ignore: 5.2.0 - nx: 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51) + nx: 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51) semver: 7.3.4 tmp: 0.2.1 tslib: 2.5.3 @@ -6608,18 +6922,18 @@ packages: - typescript dev: true - /@nrwl/devkit@16.6.0-beta.4(nx@16.6.0-beta.4): - resolution: {integrity: sha512-chfHRQk7DKt4/Z3UHtr6yPXXOEHqXma+Dsnu7B/P3NGrSTkdcq0G8ytO24jkCX28RQnO/95S/4EYrM9dyeoouQ==} + /@nrwl/devkit@16.6.0-beta.8(nx@16.6.0-beta.8): + resolution: {integrity: sha512-gPqN+V1ZOwDeo26jFKrcAvepPA0ORA/LXJPpSPlgAhZtDZvkbUmdj0273konWabEQ9jUPyi4iHaJUH+a3cqInQ==} dependencies: - '@nx/devkit': 16.6.0-beta.4(nx@16.6.0-beta.4) + '@nx/devkit': 16.6.0-beta.8(nx@16.6.0-beta.8) transitivePeerDependencies: - nx dev: true - /@nrwl/eslint-plugin-nx@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(@typescript-eslint/parser@5.60.1)(eslint-config-prettier@8.5.0)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-sGiNVikCBr3jc14YuJGUcFNISAjVnk0tleJRv8h98E8o02O0MpNwNdPiVmLF2nK4jCy9+X1tsrIko61+sOusFg==} + /@nrwl/eslint-plugin-nx@16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(@typescript-eslint/parser@5.60.1)(eslint-config-prettier@8.5.0)(eslint@8.15.0)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-vAyLU+Ww7HE5lBeT9lGq7frqGqarU/Mic/Wc9nyTD1PF7mypA2i6ELOyE4NhEsNbTq82iXW4fTyN94wtsfQtGw==} dependencies: - '@nx/eslint-plugin': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(@typescript-eslint/parser@5.60.1)(eslint-config-prettier@8.5.0)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/eslint-plugin': 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(@typescript-eslint/parser@5.60.1)(eslint-config-prettier@8.5.0)(eslint@8.15.0)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4) transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -6636,10 +6950,10 @@ packages: - verdaccio dev: true - /@nrwl/jest@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-I2YMuBuD2+3HryDZy0JImw1ARHZdqjsza1iUeRbtfI8L10CfgiqQMedr9XmMSGcJiVA609iW6zQptRE3Y1y90Q==} + /@nrwl/jest@16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.8)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-TkGUf7YrKLFy8FPpPapEWzCNfKSzuNXyAITBsFiIuvfZJGjjAMrSPUmQiDNDgcwjCTQrbZFOkNgn8YH7voxbrw==} dependencies: - '@nx/jest': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/jest': 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.8)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4) transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -6655,7 +6969,7 @@ packages: - verdaccio dev: true - /@nrwl/js@15.8.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.6.0-beta.4)(prettier@2.7.1)(typescript@5.1.3): + /@nrwl/js@15.8.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.6.0-beta.8)(prettier@2.7.1)(typescript@5.1.3): resolution: {integrity: sha512-l2Q7oFpzx6ul7G0nKpMkrvnIEaOY+X8fc2g2Db5WqpnnBdfkrtWXZPg/O4DQ1p9O6BXrZ+Q2AK9bfgnliiwyEg==} dependencies: '@babel/core': 7.22.9 @@ -6665,7 +6979,7 @@ packages: '@babel/preset-env': 7.22.5(@babel/core@7.22.9) '@babel/preset-typescript': 7.22.5(@babel/core@7.22.9) '@babel/runtime': 7.22.6 - '@nrwl/devkit': 15.8.0(nx@16.6.0-beta.4)(typescript@5.1.3) + '@nrwl/devkit': 15.8.0(nx@16.6.0-beta.8)(typescript@5.1.3) '@nrwl/workspace': 15.8.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(prettier@2.7.1)(typescript@5.1.3) '@phenomnomnominal/tsquery': 4.1.1(typescript@5.1.3) babel-plugin-const-enum: 1.2.0(@babel/core@7.22.9) @@ -6692,10 +7006,46 @@ packages: - typescript dev: true - /@nrwl/js@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-jiwWyK0/6LWf/KDBp3cFhCxmN4kczXPN+lN2CpBS+ALtEDTVYQHofllAFEc0j9sXAMqu3cOvugxSS5VYheOk9A==} + /@nrwl/js@15.8.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(nx@15.8.0)(prettier@2.7.1)(typescript@5.1.3): + resolution: {integrity: sha512-l2Q7oFpzx6ul7G0nKpMkrvnIEaOY+X8fc2g2Db5WqpnnBdfkrtWXZPg/O4DQ1p9O6BXrZ+Q2AK9bfgnliiwyEg==} dependencies: - '@nx/js': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + '@babel/core': 7.22.9 + '@babel/plugin-proposal-class-properties': 7.18.6(@babel/core@7.22.9) + '@babel/plugin-proposal-decorators': 7.21.0(@babel/core@7.22.9) + '@babel/plugin-transform-runtime': 7.22.9(@babel/core@7.22.9) + '@babel/preset-env': 7.22.5(@babel/core@7.22.9) + '@babel/preset-typescript': 7.22.5(@babel/core@7.22.9) + '@babel/runtime': 7.22.6 + '@nrwl/devkit': 15.8.0(nx@15.8.0)(typescript@5.1.3) + '@nrwl/workspace': 15.8.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(prettier@2.7.1)(typescript@5.1.3) + '@phenomnomnominal/tsquery': 4.1.1(typescript@5.1.3) + babel-plugin-const-enum: 1.2.0(@babel/core@7.22.9) + babel-plugin-macros: 2.8.0 + babel-plugin-transform-typescript-metadata: 0.3.2(@babel/core@7.22.9) + chalk: 4.1.2 + fast-glob: 3.2.7 + fs-extra: 11.1.1 + ignore: 5.2.0 + js-tokens: 4.0.0 + minimatch: 3.0.5 + source-map-support: 0.5.19 + tree-kill: 1.2.2 + tslib: 2.5.3 + transitivePeerDependencies: + - '@babel/traverse' + - '@swc-node/register' + - '@swc/core' + - debug + - nx + - prettier + - supports-color + - typescript + dev: true + + /@nrwl/js@16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-tRXayCZWPqXl0hxcsC3mg56IY6svE2GV4DWEYC4qo78ckhvd/TDmUZMvomB4VcR8pIxGR1I8T3B9jr/BxKZK7g==} + dependencies: + '@nx/js': 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4) transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -6718,7 +7068,7 @@ packages: optional: true dependencies: '@nrwl/devkit': 15.8.0(nx@15.8.0)(typescript@5.1.3) - '@nrwl/js': 15.8.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(eslint@8.15.0)(nx@16.6.0-beta.4)(prettier@2.7.1)(typescript@5.1.3) + '@nrwl/js': 15.8.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(nx@15.8.0)(prettier@2.7.1)(typescript@5.1.3) '@phenomnomnominal/tsquery': 4.1.1(typescript@5.1.3) eslint: 8.15.0 tmp: 0.2.1 @@ -6734,10 +7084,10 @@ packages: - typescript dev: true - /@nrwl/linter@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-CpeDd7G2oMgY53jDdE9XPdD6GwD4xMIWnNI1agZBxpXZ80DNTEOFf+3NSeTSUl+eQII6obCfAEmwtHK90pjZDQ==} + /@nrwl/linter@16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-FuI8oZaKtG0e2m/uy8ocAqBkuvwepG1WxbRCYX2YeU27QJ4rx8xsvU9DHKH5rrVMPqc3VaNrcpSFfcdgK8tkYg==} dependencies: - '@nx/linter': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/linter': 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4) transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -6752,17 +7102,16 @@ packages: - verdaccio dev: true - /@nrwl/next@16.6.0-beta.4(@babel/core@7.22.9)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/express@4.17.14)(@types/node@18.16.9)(eslint@8.15.0)(file-loader@6.2.0)(next@13.3.4)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0): - resolution: {integrity: sha512-A7hxhoSWOwA73HiUCD+Ns8BqoewcxIAPgune0C83vP6kdCTPSLe3udiACWSnebml5KEzzx026sovi3r5z4w1/w==} + /@nrwl/next@16.6.0-beta.8(@babel/core@7.22.9)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(file-loader@6.2.0)(next@13.3.4)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0): + resolution: {integrity: sha512-Yz6jB2/l0hG4cCszcxNvO0shs15w3bp2lozm/pCe8UeULNikx0mFsAsMiS04OPfLwS3jGAoj/y8DiOaQyjjWAw==} dependencies: - '@nx/next': 16.6.0-beta.4(@babel/core@7.22.9)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/express@4.17.14)(@types/node@18.16.9)(eslint@8.15.0)(file-loader@6.2.0)(next@13.3.4)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) + '@nx/next': 16.6.0-beta.8(@babel/core@7.22.9)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(file-loader@6.2.0)(next@13.3.4)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) transitivePeerDependencies: - '@babel/core' - '@babel/traverse' - '@swc-node/register' - '@swc/core' - '@swc/wasm' - - '@types/express' - '@types/node' - debug - eslint @@ -6945,10 +7294,10 @@ packages: dev: true optional: true - /@nrwl/react@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0): - resolution: {integrity: sha512-ZcWD0VcStqPXI/3tvfbUqJMAAQw95hl5SxWiGbiLgtMLcKn4Jg/PolMgCyQIMTKtfEo8Sqa/X0JwD8sOfokmWA==} + /@nrwl/react@16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0): + resolution: {integrity: sha512-qEqYWhQG3XDZvCp5Kg+VfUXBv2yJfW+Wx8oVqbAXOHb4rUjIqTaTwBmF0TLCegGWopsE4Rv2EC9jhGxwmkq34w==} dependencies: - '@nx/react': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) + '@nx/react': 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -6964,10 +7313,10 @@ packages: - webpack dev: true - /@nrwl/storybook@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-Wd6xTN1udNIXNLARMs/l3DtODmyxf5K+wRzlyCfPkFtcvC039kSWiJ1v/sJxShbZd48+mZskaiUmMuJHjJPyEA==} + /@nrwl/storybook@16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-AQ4SybDvAwn9vKZUYJbH2UdZEFIwnf4kN41fviwvCsnMl/M4TEy+fyc2Y/43zswMQOfOJsHRUs8iqUm4n9pk2w==} dependencies: - '@nx/storybook': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/storybook': 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4) transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -7005,21 +7354,22 @@ packages: - debug dev: true - /@nrwl/tao@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51): - resolution: {integrity: sha512-wOKV3mBZEQUYKPn6lHSJeDAJm8UPc3carEwgO8etcrZNBCTq+OepYFJoOUukxavIIgf10KqfDT1lAwaeiip0pA==} + /@nrwl/tao@16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51): + resolution: {integrity: sha512-6X9L+oloDPoyLyIAWSrF821ks7g+ltweGjHHyVoKLLeUE38hdmPuQdCtkKbXjmHO3CJv2JIS9sTfSY1+ezWGjw==} hasBin: true dependencies: - nx: 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51) + nx: 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51) + tslib: 2.5.3 transitivePeerDependencies: - '@swc-node/register' - '@swc/core' - debug dev: true - /@nrwl/web@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-Amtecs/uuy6eRSNl0FGWa3kfe3a9lYqZ17kmX4CGVcZ8aTYmhVkpGlcjeZvm8desnXBX/ESOXFHJpj/oxPvymw==} + /@nrwl/web@16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-wd60yHGdc1MiNEHz5/HLx04rSH6JeBq1jv5hx0dRN2Zcp6LxbnH+3CFYCDIyW2vgCXeSsGu1HoCe1XeNpXBM4Q==} dependencies: - '@nx/web': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/web': 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4) transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -7033,10 +7383,10 @@ packages: - verdaccio dev: true - /@nrwl/webpack@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(esbuild@0.17.5)(html-webpack-plugin@5.5.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-kmGfkZxLxovPWOZrEhxc9QpOtpnbqCk2QVWF9liMkQdP7+3i4qOJ+ndw9QBBAQ7u8pG/i1DPAMFyB4Yt7n6b+g==} + /@nrwl/webpack@16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(esbuild@0.17.5)(html-webpack-plugin@5.5.0)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-4Ve5CFdb0eiq5tQNYrRt43jBEY0N16jOkww65kA73JqF7UseLszzL8ZX+6+P4ERcKL5YYN1HbAxcZKA1Wec8AQ==} dependencies: - '@nx/webpack': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(esbuild@0.17.5)(html-webpack-plugin@5.5.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/webpack': 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(esbuild@0.17.5)(html-webpack-plugin@5.5.0)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4) transitivePeerDependencies: - '@babel/traverse' - '@parcel/css' @@ -7106,10 +7456,10 @@ packages: - typescript dev: true - /@nrwl/workspace@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51): - resolution: {integrity: sha512-q9uADz1YJGB/ZtSKsrKzKnN91nbcin4DPFKrxaNAG+XgEM4hhzdjC7W2+BNzsRkywEFE/pqGWtbpGqeGfSpgGg==} + /@nrwl/workspace@16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51): + resolution: {integrity: sha512-O5Te+bb72xPAoOZAeLMTUMyZvwBZcHac03hKd76i4PeBijgVYvehIalynRPcqNQklF9lA0dr6Y4eLYoj4zrwpA==} dependencies: - '@nx/workspace': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51) + '@nx/workspace': 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51) transitivePeerDependencies: - '@swc-node/register' - '@swc/core' @@ -7128,23 +7478,24 @@ packages: - encoding dev: true - /@nx/cypress@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-Co6g6CytxxY+ts9ns0Xah+oAO9CZ6oo8DJ6y8JoKHsZY9Oa28IZ/IOEwYMUGzo/maXAz8tVpzZYclN/sTFAs/A==} + /@nx/cypress@16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-a5kjs/jvRcNPNYO+fWf9jrKacX2/Wy7tYFgITP64ypzvnF4+XxLh3Wq0KgtkgT14nbIT93j4acNDth5gysqIIg==} peerDependencies: cypress: '>= 3 < 13' peerDependenciesMeta: cypress: optional: true dependencies: - '@nrwl/cypress': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/devkit': 16.6.0-beta.4(nx@16.6.0-beta.4) - '@nx/js': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/linter': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + '@nrwl/cypress': 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/devkit': 16.6.0-beta.8(nx@16.6.0-beta.8) + '@nx/js': 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/linter': 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4) '@phenomnomnominal/tsquery': 5.0.1(typescript@5.1.3) cypress: 12.16.0 detect-port: 1.5.1 dotenv: 10.0.0 semver: 7.5.3 + tslib: 2.5.3 transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -7159,22 +7510,22 @@ packages: - verdaccio dev: true - /@nx/devkit@16.6.0-beta.4(nx@16.6.0-beta.4): - resolution: {integrity: sha512-0+b12edK/Q5+JN3hnmzsK8MLcwGeTDmnca23q5+eayXQf4kOmwM9zbYM10PrWpYgN1c7Ltx4k09RP4J9HpBYbg==} + /@nx/devkit@16.6.0-beta.8(nx@16.6.0-beta.8): + resolution: {integrity: sha512-B9Izv6BpgH3K7hPfG+8d/GkzvmkPDLd9Qd4/aoxUyg51/1NAQWlQWJkD9g0I6eIXiU8XAFw4vxxaDK+HVgc0QQ==} peerDependencies: nx: '>= 15 <= 17' dependencies: - '@nrwl/devkit': 16.6.0-beta.4(nx@16.6.0-beta.4) + '@nrwl/devkit': 16.6.0-beta.8(nx@16.6.0-beta.8) ejs: 3.1.8 ignore: 5.2.0 - nx: 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51) + nx: 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51) semver: 7.5.3 tmp: 0.2.1 tslib: 2.5.3 dev: true - /@nx/eslint-plugin@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(@typescript-eslint/parser@5.60.1)(eslint-config-prettier@8.5.0)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-deIVitlkRs3wA9OKLanPokfnL+lGwh3LrVEwvvOsUkoyGhd77/PtjbCMDcN96oE7vYCNdSXPJ8Gli1Z0qDI7Mg==} + /@nx/eslint-plugin@16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(@typescript-eslint/parser@5.60.1)(eslint-config-prettier@8.5.0)(eslint@8.15.0)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-uTsVqQnnn35i3N9adNq6ked79IyjerXeZZS62aCsAbxQBxxcwDpqvi/sWfOQ/Gne/5nGDa/X5jnrIuKb+2Hm3A==} peerDependencies: '@typescript-eslint/parser': ^5.60.1 eslint-config-prettier: ^8.1.0 @@ -7182,9 +7533,9 @@ packages: eslint-config-prettier: optional: true dependencies: - '@nrwl/eslint-plugin-nx': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(@typescript-eslint/parser@5.60.1)(eslint-config-prettier@8.5.0)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/devkit': 16.6.0-beta.4(nx@16.6.0-beta.4) - '@nx/js': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + '@nrwl/eslint-plugin-nx': 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(@typescript-eslint/parser@5.60.1)(eslint-config-prettier@8.5.0)(eslint@8.15.0)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/devkit': 16.6.0-beta.8(nx@16.6.0-beta.8) + '@nx/js': 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4) '@typescript-eslint/parser': 5.60.1(eslint@8.15.0)(typescript@5.1.3) '@typescript-eslint/type-utils': 5.60.1(eslint@8.15.0)(typescript@5.1.3) '@typescript-eslint/utils': 5.60.1(eslint@8.15.0)(typescript@5.1.3) @@ -7193,6 +7544,7 @@ packages: eslint-config-prettier: 8.5.0(eslint@8.15.0) jsonc-eslint-parser: 2.1.0 semver: 7.5.3 + tslib: 2.5.3 transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -7207,14 +7559,14 @@ packages: - verdaccio dev: true - /@nx/jest@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-Yb3CcWNlN89n+t15SuP20jIliHro5hPtlc5hktAEjXhj08o0YkjRequ8jUFjlAswdLPwrQlMUHZCQiqw5vySUg==} + /@nx/jest@16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.8)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-qmfEM2sbXfT+Eg8qBauvufDw+6+UTTZXW8+LMM8flvZ/DHn7gjg1eZ6AOv1JqPlSlPRqmGSIw2W+KSay3kax/Q==} dependencies: '@jest/reporters': 29.5.0 '@jest/test-result': 29.5.0 - '@nrwl/jest': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/devkit': 16.6.0-beta.4(nx@16.6.0-beta.4) - '@nx/js': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + '@nrwl/jest': 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.8)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/devkit': 16.6.0-beta.8(nx@16.6.0-beta.8) + '@nx/js': 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4) '@phenomnomnominal/tsquery': 5.0.1(typescript@5.1.3) chalk: 4.1.2 dotenv: 10.0.0 @@ -7239,8 +7591,8 @@ packages: - verdaccio dev: true - /@nx/js@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-Up4CPVzKIM6LGyhml5EkrXzVtx/fM9x67DbYEsFENAD0exlblrHdHf0XAsXP0Wc8ClhQnCH4F5O8b4T2/3HtRg==} + /@nx/js@16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-2S+kAve0Sumr/HdfaGTK0MkPDZTpzA8Q4awGyWQkjCcCMzgQvdkLdheTj/JWISJt4m0jKEeTxcxB8iMqUCqyyA==} peerDependencies: verdaccio: ^5.0.4 peerDependenciesMeta: @@ -7249,14 +7601,14 @@ packages: dependencies: '@babel/core': 7.22.9 '@babel/plugin-proposal-class-properties': 7.18.6(@babel/core@7.22.9) - '@babel/plugin-proposal-decorators': 7.21.0(@babel/core@7.22.9) + '@babel/plugin-proposal-decorators': 7.22.7(@babel/core@7.22.9) '@babel/plugin-transform-runtime': 7.22.9(@babel/core@7.22.9) - '@babel/preset-env': 7.22.5(@babel/core@7.22.9) + '@babel/preset-env': 7.22.9(@babel/core@7.22.9) '@babel/preset-typescript': 7.22.5(@babel/core@7.22.9) '@babel/runtime': 7.22.6 - '@nrwl/js': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/devkit': 16.6.0-beta.4(nx@16.6.0-beta.4) - '@nx/workspace': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51) + '@nrwl/js': 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/devkit': 16.6.0-beta.8(nx@16.6.0-beta.8) + '@nx/workspace': 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51) '@phenomnomnominal/tsquery': 5.0.1(typescript@5.1.3) babel-plugin-const-enum: 1.2.0(@babel/core@7.22.9) babel-plugin-macros: 2.8.0 @@ -7286,17 +7638,17 @@ packages: - typescript dev: true - /@nx/linter@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-CVtAutv8TrJ7inet/cUeXs2z3uQ7uajPkccQiisDAJR30dx4s0xNuiqKPNNy0LelWX3Q2lhycZDbNcn1cwtMSQ==} + /@nx/linter@16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-o0TVKwTpQm5U/wJJpuiiyJ4WSzKoLDcDCpxeRZQkWpyAbq+M9WwKbO+sEbcLy0QJ/tFHQ531aScS7Tp1ClbjDA==} peerDependencies: eslint: ^8.0.0 peerDependenciesMeta: eslint: optional: true dependencies: - '@nrwl/linter': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/devkit': 16.6.0-beta.4(nx@16.6.0-beta.4) - '@nx/js': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + '@nrwl/linter': 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/devkit': 16.6.0-beta.8(nx@16.6.0-beta.8) + '@nx/js': 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4) '@phenomnomnominal/tsquery': 5.0.1(typescript@5.1.3) eslint: 8.15.0 tmp: 0.2.1 @@ -7314,29 +7666,28 @@ packages: - verdaccio dev: true - /@nx/next@16.6.0-beta.4(@babel/core@7.22.9)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/express@4.17.14)(@types/node@18.16.9)(eslint@8.15.0)(file-loader@6.2.0)(next@13.3.4)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0): - resolution: {integrity: sha512-anknmoeDinyu+gV9j2fiYZUtgtXeXiNTzcaJp3aeSM9121huwHnQHMnBikNBnzG4h082vPppD0oE4cORz1HWUQ==} + /@nx/next@16.6.0-beta.8(@babel/core@7.22.9)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(file-loader@6.2.0)(next@13.3.4)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0): + resolution: {integrity: sha512-dFzibfeynGr0Ix4sERzF554mc30nVTJVyVY7RD7ro7nVHMrAWFQ5kz8DXo+8pbTfInVhTftZwvYDxJhg9yPkdQ==} peerDependencies: next: '>=13.0.0' dependencies: - '@babel/plugin-proposal-decorators': 7.21.0(@babel/core@7.22.9) - '@nrwl/next': 16.6.0-beta.4(@babel/core@7.22.9)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/express@4.17.14)(@types/node@18.16.9)(eslint@8.15.0)(file-loader@6.2.0)(next@13.3.4)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) - '@nx/devkit': 16.6.0-beta.4(nx@16.6.0-beta.4) - '@nx/js': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/linter': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/react': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) - '@nx/web': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/workspace': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51) + '@babel/plugin-proposal-decorators': 7.22.7(@babel/core@7.22.9) + '@nrwl/next': 16.6.0-beta.8(@babel/core@7.22.9)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(file-loader@6.2.0)(next@13.3.4)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) + '@nx/devkit': 16.6.0-beta.8(nx@16.6.0-beta.8) + '@nx/js': 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/linter': 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/react': 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) + '@nx/web': 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/workspace': 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51) '@svgr/webpack': 8.0.1 chalk: 4.1.2 copy-webpack-plugin: 10.2.4(webpack@5.88.0) dotenv: 10.0.0 - express: 4.18.2 fs-extra: 11.1.1 - http-proxy-middleware: 2.0.6(@types/express@4.17.14) ignore: 5.2.0 next: 13.3.4(@babel/core@7.22.9)(react-dom@18.2.0)(react@18.2.0)(sass@1.55.0) semver: 7.5.3 + tslib: 2.5.3 url-loader: 4.1.1(file-loader@6.2.0)(webpack@5.88.0) webpack-merge: 5.9.0 transitivePeerDependencies: @@ -7345,7 +7696,6 @@ packages: - '@swc-node/register' - '@swc/core' - '@swc/wasm' - - '@types/express' - '@types/node' - debug - eslint @@ -7357,8 +7707,8 @@ packages: - webpack dev: true - /@nx/nx-darwin-arm64@16.6.0-beta.4: - resolution: {integrity: sha512-WosSKoGph13tVtiO9oJXz0m+eAvOFXhoox2GTtesa76LSLOp1kMYfiCkRnAaEZimYD+ncshhqS3EHoomnwh1+w==} + /@nx/nx-darwin-arm64@16.6.0-beta.8: + resolution: {integrity: sha512-bocW6s79DJ/WtyPwrH9ypS5FscipEE3VDHTDfcHFvc/0jKzGvtYOG5OKgOveIbVn0d7zKuLiN381lAuqbwnt1Q==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] @@ -7366,8 +7716,8 @@ packages: dev: true optional: true - /@nx/nx-darwin-x64@16.6.0-beta.4: - resolution: {integrity: sha512-wTR4akGjY8+CPNO/AYh9UeuTH9EyEPx4Kwp+Z63CEbDF8oe2BBVtMWz3XHHm7KKnPOWzOXADi7gE/FI5HTAMvA==} + /@nx/nx-darwin-x64@16.6.0-beta.8: + resolution: {integrity: sha512-U7ItDFhIxuJ8TmRGCfc5vbG+YGzWuYx/Ita5cDsNi/dx9UPYn7Lxwyu/+9fgxggI+awOQyiPlZlfdVclF995oA==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] @@ -7375,8 +7725,8 @@ packages: dev: true optional: true - /@nx/nx-freebsd-x64@16.6.0-beta.4: - resolution: {integrity: sha512-at3qt49FMBHG75p3Sbngy3b/H4fXAz80MhejcDS0CmyJJWZMgGIat9bXGkpQqZKVrAkk8EMhVcV972FlJZIYog==} + /@nx/nx-freebsd-x64@16.6.0-beta.8: + resolution: {integrity: sha512-koChCuEwbY8HDzyvaLylCTuKk9ercEcefPfAZRzLZLrrd5Rf3d2lhiF8fwhW20HK6dC4XrQSmCLsVtPK+bWVDA==} engines: {node: '>= 10'} cpu: [x64] os: [freebsd] @@ -7384,8 +7734,8 @@ packages: dev: true optional: true - /@nx/nx-linux-arm-gnueabihf@16.6.0-beta.4: - resolution: {integrity: sha512-tWUb3GlYnWdC7Z3RAdbs6A4tc26187eaWBI7Rt5rVmXOqa5pIm5J0QHEAD4IctcY38z9HPehgi3cYjihOprCQA==} + /@nx/nx-linux-arm-gnueabihf@16.6.0-beta.8: + resolution: {integrity: sha512-F8sf37GjrLh12HdWAjSSYlMcWjPwY5Lufy/N32zj5g4iR26XgM+Vd9amILN21Xfx/gyxhf3xGoQl/Fkct+IVZw==} engines: {node: '>= 10'} cpu: [arm] os: [linux] @@ -7393,8 +7743,8 @@ packages: dev: true optional: true - /@nx/nx-linux-arm64-gnu@16.6.0-beta.4: - resolution: {integrity: sha512-kMBCWIeQd4wzs8COXaeD71+LkLG+lsq99JpTGmQHXa1QB9rm4NBTtcixtveAWssqF8i7WNSpxlD1zo6z04HO4g==} + /@nx/nx-linux-arm64-gnu@16.6.0-beta.8: + resolution: {integrity: sha512-iQx+c8TXjEUx0R8hGd1l6qnr2Ya9kSrqj2mz3BpjJv5j7dVAu6SpO9i96/A7juB4ypyPAV0a4HUae7N77k3Jqg==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -7402,8 +7752,8 @@ packages: dev: true optional: true - /@nx/nx-linux-arm64-musl@16.6.0-beta.4: - resolution: {integrity: sha512-tiXZq2MHUMnyE5IBdZmaes3fNSPCkL9w+phQ7Fu33Rhvr9ZWcVudYmXhVxxPaznPT1r95Lg+mitegiKwzNKsFw==} + /@nx/nx-linux-arm64-musl@16.6.0-beta.8: + resolution: {integrity: sha512-VVNOVhJ2hKeepUQ4SFZZzMSk1cQnMxF46r6XdpYqvWSPzy0JneXdp0H8ejQdv2jo4zdcQKTJ+cgzoFrDWfbvew==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -7411,8 +7761,8 @@ packages: dev: true optional: true - /@nx/nx-linux-x64-gnu@16.6.0-beta.4: - resolution: {integrity: sha512-3Ku1Gpq7LC+FOQbKVesRDp5Sfdh6EPeOpKW2tZduqS3xht++/7HdP6dF8825mxykOg6DFRdO+c66r8k8kijxMQ==} + /@nx/nx-linux-x64-gnu@16.6.0-beta.8: + resolution: {integrity: sha512-iM8smpFIEiIEwvT5sFdub9oxC8CQoIb/ZvZyD4J+KL5vuFOiHShuKUIIuiadGjGEi2Xg/ZNzV/RyeBRfwTc9Mg==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -7420,8 +7770,8 @@ packages: dev: true optional: true - /@nx/nx-linux-x64-musl@16.6.0-beta.4: - resolution: {integrity: sha512-hQZJVtxsVmENUvwLjSuJ25OhvwM2Oi+4Em9rjWtChUNwQdMPYRDBl3RsUEtGbStGRWu0AnDbXh+TDo/4tV1FgA==} + /@nx/nx-linux-x64-musl@16.6.0-beta.8: + resolution: {integrity: sha512-UYsdxaXPdct050UQJ6PM++O7g6EvNLXkiO5Swjro1JlfTqbWWO5eD+OAueK2UnGJVNAn8ffZ5He47HGRY7NU3Q==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -7429,8 +7779,8 @@ packages: dev: true optional: true - /@nx/nx-win32-arm64-msvc@16.6.0-beta.4: - resolution: {integrity: sha512-C7ptavIq4KqxNectfgsQRvR98vpB/c7GA3Xrj+PCrg6o5qLrAQ8qycla05IcfAiSF409oERrJCVqmCHJJQax8A==} + /@nx/nx-win32-arm64-msvc@16.6.0-beta.8: + resolution: {integrity: sha512-2uwwvOtoAe2C1lkSEhe/pvGTwCKIUwB8RHk8CDicEV47E7rRHTBI94o7MnMiAEGLmDa1QEuUOtcELbB2gZCXIQ==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] @@ -7438,8 +7788,8 @@ packages: dev: true optional: true - /@nx/nx-win32-x64-msvc@16.6.0-beta.4: - resolution: {integrity: sha512-KvZ0/nnlIJgQKjLmMmjU18MvF4Lj8SapC4LHzyPaYVk3SkGZ5o5sHZ29J1RY7BcQ3GV51Azgdh9W8alu2z/oMA==} + /@nx/nx-win32-x64-msvc@16.6.0-beta.8: + resolution: {integrity: sha512-juMJJN42a7RcPWaM4mo7vfTInWyfnN4S+Ei+e+TFpg0cc+v3zB7LlJNNcjIcqGcpk5DFMmYf+7AlSABBZo1n+A==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -7447,19 +7797,20 @@ packages: dev: true optional: true - /@nx/react@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0): - resolution: {integrity: sha512-HeR6Maai48MvJxrIxUDhdrIl3XrcSULgdRpWAdO2Chugq8vOOGha5NHQ943UuXyqSsLb8+/VNCldAPPmZ27U4w==} + /@nx/react@16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0): + resolution: {integrity: sha512-h0GV8eE23UYpym4G+X6hqufrLlRzfUz9A2Bd0A6l+82YhObrGwTCR0ZqLItoDPr4mN8019S1pYjpVQMd0Q26Bg==} dependencies: - '@nrwl/react': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) - '@nx/devkit': 16.6.0-beta.4(nx@16.6.0-beta.4) - '@nx/js': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/linter': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/web': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + '@nrwl/react': 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) + '@nx/devkit': 16.6.0-beta.8(nx@16.6.0-beta.8) + '@nx/js': 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/linter': 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/web': 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4) '@phenomnomnominal/tsquery': 5.0.1(typescript@5.1.3) '@svgr/webpack': 8.0.1 chalk: 4.1.2 file-loader: 6.2.0(webpack@5.88.0) minimatch: 3.0.5 + tslib: 2.5.3 transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -7475,18 +7826,19 @@ packages: - webpack dev: true - /@nx/storybook@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-FvW8OdmoitnB727YpqzP3gCTkK+3SF3GPXpGL4SOhlj842G6ey+9BQqRNHFbeaMxgzrRSTnyyDZznmLt//EsxQ==} + /@nx/storybook@16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-CRSmwWqe9Ug68ATHoNs0ExESAddHQ6nSXvw2BIKZCMFIV5w1bn6X+kI4alzxyS61jcjZ2Hs+kQzkB+WGCWMAUg==} dependencies: - '@nrwl/storybook': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/cypress': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/devkit': 16.6.0-beta.4(nx@16.6.0-beta.4) - '@nx/js': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/linter': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/workspace': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51) + '@nrwl/storybook': 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/cypress': 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@12.16.0)(eslint@8.15.0)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/devkit': 16.6.0-beta.8(nx@16.6.0-beta.8) + '@nx/js': 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/linter': 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.15.0)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/workspace': 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51) '@phenomnomnominal/tsquery': 5.0.1(typescript@5.1.3) dotenv: 10.0.0 semver: 7.5.3 + tslib: 2.5.3 transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -7502,12 +7854,12 @@ packages: - verdaccio dev: true - /@nx/web@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-xSUm82LZ8G3Y0iJO7AIiHk8iAIG+sP7OKhjhUHhsm8mtSfSY81+i5FXuld/t+aQ6+RIqgTVWaIN78x9BCVhq2w==} + /@nx/web@16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-FoL5m7XX6GDuLDPkp0D6G/KPns1RPGeI+LnUQLXUHqhcwtLi23DCeXpVrcwwleh8DG83L+paLwQoUfzkMnob/w==} dependencies: - '@nrwl/web': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/devkit': 16.6.0-beta.4(nx@16.6.0-beta.4) - '@nx/js': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + '@nrwl/web': 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/devkit': 16.6.0-beta.8(nx@16.6.0-beta.8) + '@nx/js': 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4) chalk: 4.1.2 chokidar: 3.5.3 detect-port: 1.5.1 @@ -7527,16 +7879,16 @@ packages: - verdaccio dev: true - /@nx/webpack@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(esbuild@0.17.5)(html-webpack-plugin@5.5.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4): - resolution: {integrity: sha512-y3mI85ZsHgK3ebuzeOaVNTGNEqdFsD/8pBx7HhumiSO7xqKfgRsvVWdN6EPn2a3HwRj2JgjrdBBIWu+nItIp8A==} + /@nx/webpack@16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(esbuild@0.17.5)(html-webpack-plugin@5.5.0)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4): + resolution: {integrity: sha512-pHGICLovvuV+T32IKkRDtY2RYsTG9W6NrQvol30fsf2ShrPQWwUae8VKMlm5TG43R6WcY0/BG1jr+D340uQ6dQ==} dependencies: '@babel/core': 7.22.9 - '@nrwl/webpack': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(esbuild@0.17.5)(html-webpack-plugin@5.5.0)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/devkit': 16.6.0-beta.4(nx@16.6.0-beta.4) - '@nx/js': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.4)(typescript@5.1.3)(verdaccio@5.15.4) + '@nrwl/webpack': 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(esbuild@0.17.5)(html-webpack-plugin@5.5.0)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/devkit': 16.6.0-beta.8(nx@16.6.0-beta.8) + '@nx/js': 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.6.0-beta.8)(typescript@5.1.3)(verdaccio@5.15.4) autoprefixer: 10.4.13(postcss@8.4.19) babel-loader: 9.1.2(@babel/core@7.22.9)(webpack@5.88.0) - browserslist: 4.21.7 + browserslist: 4.21.9 chalk: 4.1.2 chokidar: 3.5.3 copy-webpack-plugin: 10.2.4(webpack@5.88.0) @@ -7597,28 +7949,16 @@ packages: - webpack-cli dev: true - /@nx/workspace@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51): - resolution: {integrity: sha512-KVAEQjrWwMCbcZdiwoSG2PciELCsEZ1PLDX0wywNfJcRb1hK2bZDmswLuI5hxLSst9b7UXNH0PKG5S6QnIc0fw==} + /@nx/workspace@16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51): + resolution: {integrity: sha512-9Jgtlps/gbffky0XFxIg/y4W4sYbpQLvDoVVqi008vW/7O2/JxXPhsoDME5d7lRB8mQV87yJT7J5j9yvvsLukQ==} dependencies: - '@nrwl/workspace': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51) - '@nx/devkit': 16.6.0-beta.4(nx@16.6.0-beta.4) - '@parcel/watcher': 2.0.4 + '@nrwl/workspace': 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51) + '@nx/devkit': 16.6.0-beta.8(nx@16.6.0-beta.8) chalk: 4.1.2 - chokidar: 3.5.3 - cli-cursor: 3.1.0 - cli-spinners: 2.6.1 - dotenv: 10.0.0 - figures: 3.2.0 - flat: 5.0.2 ignore: 5.2.0 - minimatch: 3.0.5 - npm-run-path: 4.0.1 - nx: 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51) - open: 8.4.2 + nx: 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51) rxjs: 7.8.1 - tmp: 0.2.1 tslib: 2.5.3 - yargs: 17.7.2 yargs-parser: 21.1.1 transitivePeerDependencies: - '@swc-node/register' @@ -8350,8 +8690,8 @@ packages: resolution: {integrity: sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==} dev: true - /@storybook/addon-actions@7.0.24(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-sIPY6uH8I26KBWUb5fMYBB9xCKB02oSM8gIHzqPZ0DnW8zl+p6+dX3tAdX+XQvb9YOLJihxZ1GF1tOxFduc3Pw==} + /@storybook/addon-actions@7.1.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-IDxBmNnVgLFfQ407MxOUJmqjz0hgiZB9syi4sfp7BKp5MIPUDT1m+z603kGrvx0bk0W0DPqkp/H8ySEGEx0x6g==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 @@ -8361,14 +8701,14 @@ packages: react-dom: optional: true dependencies: - '@storybook/client-logger': 7.0.24 - '@storybook/components': 7.0.24(react-dom@18.2.0)(react@18.2.0) - '@storybook/core-events': 7.0.24 + '@storybook/client-logger': 7.1.1 + '@storybook/components': 7.1.1(react-dom@18.2.0)(react@18.2.0) + '@storybook/core-events': 7.1.1 '@storybook/global': 5.0.0 - '@storybook/manager-api': 7.0.24(react-dom@18.2.0)(react@18.2.0) - '@storybook/preview-api': 7.0.24 - '@storybook/theming': 7.0.24(react-dom@18.2.0)(react@18.2.0) - '@storybook/types': 7.0.24 + '@storybook/manager-api': 7.1.1(react-dom@18.2.0)(react@18.2.0) + '@storybook/preview-api': 7.1.1 + '@storybook/theming': 7.1.1(react-dom@18.2.0)(react@18.2.0) + '@storybook/types': 7.1.1 dequal: 2.0.3 lodash: 4.17.21 polished: 4.2.2 @@ -8381,8 +8721,8 @@ packages: uuid: 9.0.0 dev: true - /@storybook/addon-backgrounds@7.0.24(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-vThKkrSj+J7matGowxIJ4eV+kAF8iUHGQjlaW0J7vhzmVkNnxBvNn/DGOWWQLAJPCTmLVelLaBZEWcMNoKJiVA==} + /@storybook/addon-backgrounds@7.1.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-6YAjF01R/qFxeZc1B5cSxseaGXJzikMPPExSZaKkD0eW3max5Kpk+qb7rOX95m3jP2WD/0zfX6lEQUCbmDcxlg==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 @@ -8392,22 +8732,22 @@ packages: react-dom: optional: true dependencies: - '@storybook/client-logger': 7.0.24 - '@storybook/components': 7.0.24(react-dom@18.2.0)(react@18.2.0) - '@storybook/core-events': 7.0.24 + '@storybook/client-logger': 7.1.1 + '@storybook/components': 7.1.1(react-dom@18.2.0)(react@18.2.0) + '@storybook/core-events': 7.1.1 '@storybook/global': 5.0.0 - '@storybook/manager-api': 7.0.24(react-dom@18.2.0)(react@18.2.0) - '@storybook/preview-api': 7.0.24 - '@storybook/theming': 7.0.24(react-dom@18.2.0)(react@18.2.0) - '@storybook/types': 7.0.24 + '@storybook/manager-api': 7.1.1(react-dom@18.2.0)(react@18.2.0) + '@storybook/preview-api': 7.1.1 + '@storybook/theming': 7.1.1(react-dom@18.2.0)(react@18.2.0) + '@storybook/types': 7.1.1 memoizerific: 1.11.3 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) ts-dedent: 2.2.0 dev: true - /@storybook/addon-controls@7.0.24(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-x05Ng4wyBRkrupgSkBHKZSGPyUbvIDGiBseA/AjA/BNAMUMWy3t8ll9f7tlKzyDPaUeBSv8peP21r/Ry26Eqhw==} + /@storybook/addon-controls@7.1.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-qi7fxUSovTLFWeejZLagMV+4SedL0DIhZrufuQCnEeO1gbTJJPaL/KLZnilFlI3SgspkzGehhGDR6SVkDuwnZg==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 @@ -8417,15 +8757,15 @@ packages: react-dom: optional: true dependencies: - '@storybook/blocks': 7.0.24(react-dom@18.2.0)(react@18.2.0) - '@storybook/client-logger': 7.0.24 - '@storybook/components': 7.0.24(react-dom@18.2.0)(react@18.2.0) - '@storybook/core-common': 7.0.24 - '@storybook/manager-api': 7.0.24(react-dom@18.2.0)(react@18.2.0) - '@storybook/node-logger': 7.0.24 - '@storybook/preview-api': 7.0.24 - '@storybook/theming': 7.0.24(react-dom@18.2.0)(react@18.2.0) - '@storybook/types': 7.0.24 + '@storybook/blocks': 7.1.1(react-dom@18.2.0)(react@18.2.0) + '@storybook/client-logger': 7.1.1 + '@storybook/components': 7.1.1(react-dom@18.2.0)(react@18.2.0) + '@storybook/core-common': 7.1.1 + '@storybook/manager-api': 7.1.1(react-dom@18.2.0)(react@18.2.0) + '@storybook/node-logger': 7.1.1 + '@storybook/preview-api': 7.1.1 + '@storybook/theming': 7.1.1(react-dom@18.2.0)(react@18.2.0) + '@storybook/types': 7.1.1 lodash: 4.17.21 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) @@ -8435,29 +8775,27 @@ packages: - supports-color dev: true - /@storybook/addon-docs@7.0.24(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-O5S+E6+8c/EHEQc5WcrNQ8dOVg9Q2ONIOYxlbSAcfMUA/d+tRR9xXTZog7nv1tj4U0G29+Vr4pKgsGh3Ya5qcw==} + /@storybook/addon-docs@7.1.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-KfsrqvR6RA0qyCwBpJjeivu/+F+n3jcMMKkBtI56E/pyQCx4+pMTJXJ2l5gJibNWYoR1CVlS9f5n5ZNGz8BzeQ==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 dependencies: - '@babel/core': 7.22.9 - '@babel/plugin-transform-react-jsx': 7.22.5(@babel/core@7.22.9) '@jest/transform': 29.5.0 '@mdx-js/react': 2.3.0(react@18.2.0) - '@storybook/blocks': 7.0.24(react-dom@18.2.0)(react@18.2.0) - '@storybook/client-logger': 7.0.24 - '@storybook/components': 7.0.24(react-dom@18.2.0)(react@18.2.0) - '@storybook/csf-plugin': 7.0.24 - '@storybook/csf-tools': 7.0.24 + '@storybook/blocks': 7.1.1(react-dom@18.2.0)(react@18.2.0) + '@storybook/client-logger': 7.1.1 + '@storybook/components': 7.1.1(react-dom@18.2.0)(react@18.2.0) + '@storybook/csf-plugin': 7.1.1 + '@storybook/csf-tools': 7.1.1 '@storybook/global': 5.0.0 '@storybook/mdx2-csf': 1.0.0 - '@storybook/node-logger': 7.0.24 - '@storybook/postinstall': 7.0.24 - '@storybook/preview-api': 7.0.24 - '@storybook/react-dom-shim': 7.0.24(react-dom@18.2.0)(react@18.2.0) - '@storybook/theming': 7.0.24(react-dom@18.2.0)(react@18.2.0) - '@storybook/types': 7.0.24 + '@storybook/node-logger': 7.1.1 + '@storybook/postinstall': 7.1.1 + '@storybook/preview-api': 7.1.1 + '@storybook/react-dom-shim': 7.1.1(react-dom@18.2.0)(react@18.2.0) + '@storybook/theming': 7.1.1(react-dom@18.2.0)(react@18.2.0) + '@storybook/types': 7.1.1 fs-extra: 11.1.1 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) @@ -8469,25 +8807,25 @@ packages: - supports-color dev: true - /@storybook/addon-essentials@7.0.24(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-OL27TNQYUJv/FprFCU7Q9RQYrgGdM+4SH+XmsQCcuQuGa67s6/eRKyERwOdy4Pli3Payo76+Vz1DAeJZJ0F8oA==} + /@storybook/addon-essentials@7.1.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-eCty+Q7zBjkBbaJ0HaM/UaXxJ+77uKBtEc9g+hLZFqga50auPCfCcqjnqNnxkTmewkJomx3N91BJUJJzVPUlJA==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 dependencies: - '@storybook/addon-actions': 7.0.24(react-dom@18.2.0)(react@18.2.0) - '@storybook/addon-backgrounds': 7.0.24(react-dom@18.2.0)(react@18.2.0) - '@storybook/addon-controls': 7.0.24(react-dom@18.2.0)(react@18.2.0) - '@storybook/addon-docs': 7.0.24(react-dom@18.2.0)(react@18.2.0) - '@storybook/addon-highlight': 7.0.24 - '@storybook/addon-measure': 7.0.24(react-dom@18.2.0)(react@18.2.0) - '@storybook/addon-outline': 7.0.24(react-dom@18.2.0)(react@18.2.0) - '@storybook/addon-toolbars': 7.0.24(react-dom@18.2.0)(react@18.2.0) - '@storybook/addon-viewport': 7.0.24(react-dom@18.2.0)(react@18.2.0) - '@storybook/core-common': 7.0.24 - '@storybook/manager-api': 7.0.24(react-dom@18.2.0)(react@18.2.0) - '@storybook/node-logger': 7.0.24 - '@storybook/preview-api': 7.0.24 + '@storybook/addon-actions': 7.1.1(react-dom@18.2.0)(react@18.2.0) + '@storybook/addon-backgrounds': 7.1.1(react-dom@18.2.0)(react@18.2.0) + '@storybook/addon-controls': 7.1.1(react-dom@18.2.0)(react@18.2.0) + '@storybook/addon-docs': 7.1.1(react-dom@18.2.0)(react@18.2.0) + '@storybook/addon-highlight': 7.1.1 + '@storybook/addon-measure': 7.1.1(react-dom@18.2.0)(react@18.2.0) + '@storybook/addon-outline': 7.1.1(react-dom@18.2.0)(react@18.2.0) + '@storybook/addon-toolbars': 7.1.1(react-dom@18.2.0)(react@18.2.0) + '@storybook/addon-viewport': 7.1.1(react-dom@18.2.0)(react@18.2.0) + '@storybook/core-common': 7.1.1 + '@storybook/manager-api': 7.1.1(react-dom@18.2.0)(react@18.2.0) + '@storybook/node-logger': 7.1.1 + '@storybook/preview-api': 7.1.1 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) ts-dedent: 2.2.0 @@ -8496,16 +8834,16 @@ packages: - supports-color dev: true - /@storybook/addon-highlight@7.0.24: - resolution: {integrity: sha512-IoCJHiX5Ai+7S08isxt7BH4baNF2RsjuGUA/iMoJtto/rMc5u0xftVeIjh6oVqV3tjckowXpezI3oStnrLWuRw==} + /@storybook/addon-highlight@7.1.1: + resolution: {integrity: sha512-iOLzcv4JK2R2EBcbeDLB5uuYaW96M9Vh+ZrkpKEJvHwrQzzvBo3kJ7bP/AArAEXtR5MN1al3x7mnvRofu3OIdQ==} dependencies: - '@storybook/core-events': 7.0.24 + '@storybook/core-events': 7.1.1 '@storybook/global': 5.0.0 - '@storybook/preview-api': 7.0.24 + '@storybook/preview-api': 7.1.1 dev: true - /@storybook/addon-measure@7.0.24(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-4VNs4rjdz+YFiJCz9DfCmBJwFuoa3pLhcEsAAdT3B+Hrkae+hvLtnQWIvAMsOlSWdl4tiuEWssDf4cjCEne87w==} + /@storybook/addon-measure@7.1.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-LKJ9vN0qdFVeqjPeF44R2issR0UMAuL2LzbZNxAfeNX9SxdV7qONBOt8OZNKkmm7mJ+jBZsR9Ok68PCOsXA7Xw==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 @@ -8515,19 +8853,20 @@ packages: react-dom: optional: true dependencies: - '@storybook/client-logger': 7.0.24 - '@storybook/components': 7.0.24(react-dom@18.2.0)(react@18.2.0) - '@storybook/core-events': 7.0.24 + '@storybook/client-logger': 7.1.1 + '@storybook/components': 7.1.1(react-dom@18.2.0)(react@18.2.0) + '@storybook/core-events': 7.1.1 '@storybook/global': 5.0.0 - '@storybook/manager-api': 7.0.24(react-dom@18.2.0)(react@18.2.0) - '@storybook/preview-api': 7.0.24 - '@storybook/types': 7.0.24 + '@storybook/manager-api': 7.1.1(react-dom@18.2.0)(react@18.2.0) + '@storybook/preview-api': 7.1.1 + '@storybook/types': 7.1.1 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) + tiny-invariant: 1.3.1 dev: true - /@storybook/addon-outline@7.0.24(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-YwSfs8bsmh7mEF+rlmL7zBsebWA5e/Rsf09vVqt6/k3fpopgBrq44zQlMwo1dCWV/0YhhXQF21OGzeJ1dSb8fA==} + /@storybook/addon-outline@7.1.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-zdgOA46n61o/rqvnAn1OxAczl/C99D64e+6EoK8t+Xf9fvykPQCgfBUAPq19qEAaBG4RoPpTvGSJXH2nFqJZDw==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 @@ -8537,20 +8876,20 @@ packages: react-dom: optional: true dependencies: - '@storybook/client-logger': 7.0.24 - '@storybook/components': 7.0.24(react-dom@18.2.0)(react@18.2.0) - '@storybook/core-events': 7.0.24 + '@storybook/client-logger': 7.1.1 + '@storybook/components': 7.1.1(react-dom@18.2.0)(react@18.2.0) + '@storybook/core-events': 7.1.1 '@storybook/global': 5.0.0 - '@storybook/manager-api': 7.0.24(react-dom@18.2.0)(react@18.2.0) - '@storybook/preview-api': 7.0.24 - '@storybook/types': 7.0.24 + '@storybook/manager-api': 7.1.1(react-dom@18.2.0)(react@18.2.0) + '@storybook/preview-api': 7.1.1 + '@storybook/types': 7.1.1 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) ts-dedent: 2.2.0 dev: true - /@storybook/addon-toolbars@7.0.24(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-+nDVahs2kAojzF6RbChowJmN0z7cyD/5BGMEhBemhBWSuMVnQLLEgtQi/kOY5fUxq3z1BkqcE4LV98u5CIKgKg==} + /@storybook/addon-toolbars@7.1.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-tHMv1a8hg0kmxwtKf31BZ2Z1ULnxRF/TEoDLJKVvTthhcWLQm0LmqVIG82/bnuWn4vlDrsdGT7sAN+TU7B8p0A==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 @@ -8560,17 +8899,17 @@ packages: react-dom: optional: true dependencies: - '@storybook/client-logger': 7.0.24 - '@storybook/components': 7.0.24(react-dom@18.2.0)(react@18.2.0) - '@storybook/manager-api': 7.0.24(react-dom@18.2.0)(react@18.2.0) - '@storybook/preview-api': 7.0.24 - '@storybook/theming': 7.0.24(react-dom@18.2.0)(react@18.2.0) + '@storybook/client-logger': 7.1.1 + '@storybook/components': 7.1.1(react-dom@18.2.0)(react@18.2.0) + '@storybook/manager-api': 7.1.1(react-dom@18.2.0)(react@18.2.0) + '@storybook/preview-api': 7.1.1 + '@storybook/theming': 7.1.1(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: true - /@storybook/addon-viewport@7.0.24(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-bc3TR+feemGxVP1QQT6OsFSldHjLToJNuQAGd5EEBsDFhcMTsmitiGVoxIylqIhfioL9zauLIsk5eLZ/TYxuXQ==} + /@storybook/addon-viewport@7.1.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-OAb3+NSQF0zAVdKhZwW0YOC/VMCXDncXp51ufxaz/LkF3qOGuqfmHTOfDDwjx3P6d3kX1aWV+vLVuoRS0JRK5g==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 @@ -8580,47 +8919,47 @@ packages: react-dom: optional: true dependencies: - '@storybook/client-logger': 7.0.24 - '@storybook/components': 7.0.24(react-dom@18.2.0)(react@18.2.0) - '@storybook/core-events': 7.0.24 + '@storybook/client-logger': 7.1.1 + '@storybook/components': 7.1.1(react-dom@18.2.0)(react@18.2.0) + '@storybook/core-events': 7.1.1 '@storybook/global': 5.0.0 - '@storybook/manager-api': 7.0.24(react-dom@18.2.0)(react@18.2.0) - '@storybook/preview-api': 7.0.24 - '@storybook/theming': 7.0.24(react-dom@18.2.0)(react@18.2.0) + '@storybook/manager-api': 7.1.1(react-dom@18.2.0)(react@18.2.0) + '@storybook/preview-api': 7.1.1 + '@storybook/theming': 7.1.1(react-dom@18.2.0)(react@18.2.0) memoizerific: 1.11.3 prop-types: 15.8.1 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: true - /@storybook/addons@7.0.24(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-e15hORnOD0ugvOVOTyZyLJhbDTWa4G1OHVUlboazy8O4TSvAXNBdLV1wOdY5RGoGD6Z5A4iR/gZXM0qc6Fh9xg==} + /@storybook/addons@7.0.7(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-it8NWXsdm3dhjc237d9jj7dGJf6eHDfuDv12nirV64J1dzWrnW+lONeZMPMgxxdLlgYfxH52fLgjcw/dAC/E+Q==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 dependencies: - '@storybook/manager-api': 7.0.24(react-dom@18.2.0)(react@18.2.0) - '@storybook/preview-api': 7.0.24 - '@storybook/types': 7.0.24 + '@storybook/manager-api': 7.0.7(react-dom@18.2.0)(react@18.2.0) + '@storybook/preview-api': 7.0.7 + '@storybook/types': 7.0.7 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: true - /@storybook/addons@7.0.7(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-it8NWXsdm3dhjc237d9jj7dGJf6eHDfuDv12nirV64J1dzWrnW+lONeZMPMgxxdLlgYfxH52fLgjcw/dAC/E+Q==} + /@storybook/addons@7.1.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-cIjbmMV4+C6VJ7bzfaQWRrw944FCjGidU5pPxQTP8ROqlP2Noqq1GzQ3uqjxH6uiw6Wl3c4OAVU6bUV7F5B1lA==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 dependencies: - '@storybook/manager-api': 7.0.7(react-dom@18.2.0)(react@18.2.0) - '@storybook/preview-api': 7.0.7 - '@storybook/types': 7.0.7 + '@storybook/manager-api': 7.1.1(react-dom@18.2.0)(react@18.2.0) + '@storybook/preview-api': 7.1.1 + '@storybook/types': 7.1.1 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: true - /@storybook/api@7.0.24(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-rjWZgBbt43Ma5Vg2RwK9FtiF9ZkLRT+vOfDFtRL1PQkOIUlYlm33dOdPTh+HrW5QMO9cj/cchqmzU2AtgEZCyw==} + /@storybook/api@7.0.7(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-0++LcK6PX1Z2HsI9fyZyqvmeFrB5NDMcsbmIvJfA2NfK92UW8y7t6Ft2fq/2jUCJcWT8Jp3xpatUvYb28irfwg==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 @@ -8630,14 +8969,14 @@ packages: react-dom: optional: true dependencies: - '@storybook/client-logger': 7.0.24 - '@storybook/manager-api': 7.0.24(react-dom@18.2.0)(react@18.2.0) + '@storybook/client-logger': 7.0.7 + '@storybook/manager-api': 7.0.7(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: true - /@storybook/api@7.0.7(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-0++LcK6PX1Z2HsI9fyZyqvmeFrB5NDMcsbmIvJfA2NfK92UW8y7t6Ft2fq/2jUCJcWT8Jp3xpatUvYb28irfwg==} + /@storybook/api@7.1.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-beZ9NbGOkFqPBVnZLE67Q5b7hBKwm+OINbeN9DC5v8jrJmU/seLFs/itKzW2tEUFadyMjhJv+kcpyPjxK77m4g==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 @@ -8647,29 +8986,29 @@ packages: react-dom: optional: true dependencies: - '@storybook/client-logger': 7.0.7 - '@storybook/manager-api': 7.0.7(react-dom@18.2.0)(react@18.2.0) + '@storybook/client-logger': 7.1.1 + '@storybook/manager-api': 7.1.1(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: true - /@storybook/blocks@7.0.24(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-76pe4QC3WZBVxBt/RomGubW5xzbh4uF7LVn1Vonfujf4GaHgIDzu7KtLIjgM3NmDJCsp3PNfbgA1EKzWrPQz2A==} + /@storybook/blocks@7.1.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-YIpIJi/+sByZhKrpKbVmXazUP1hj/QXybVOzwz2PT6tphfhrubGLBgu3RJIp6hwJ/lWf9RfghR7P8n+7aN6U9w==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 dependencies: - '@storybook/channels': 7.0.24 - '@storybook/client-logger': 7.0.24 - '@storybook/components': 7.0.24(react-dom@18.2.0)(react@18.2.0) - '@storybook/core-events': 7.0.24 + '@storybook/channels': 7.1.1 + '@storybook/client-logger': 7.1.1 + '@storybook/components': 7.1.1(react-dom@18.2.0)(react@18.2.0) + '@storybook/core-events': 7.1.1 '@storybook/csf': 0.1.0 - '@storybook/docs-tools': 7.0.24 + '@storybook/docs-tools': 7.1.1 '@storybook/global': 5.0.0 - '@storybook/manager-api': 7.0.24(react-dom@18.2.0)(react@18.2.0) - '@storybook/preview-api': 7.0.24 - '@storybook/theming': 7.0.24(react-dom@18.2.0)(react@18.2.0) - '@storybook/types': 7.0.24 + '@storybook/manager-api': 7.1.1(react-dom@18.2.0)(react@18.2.0) + '@storybook/preview-api': 7.1.1 + '@storybook/theming': 7.1.1(react-dom@18.2.0)(react@18.2.0) + '@storybook/types': 7.1.1 '@types/lodash': 4.14.188 color-convert: 2.0.1 dequal: 2.0.3 @@ -8681,6 +9020,7 @@ packages: react-colorful: 5.6.1(react-dom@18.2.0)(react@18.2.0) react-dom: 18.2.0(react@18.2.0) telejson: 7.1.0 + tocbot: 4.21.0 ts-dedent: 2.2.0 util-deprecate: 1.0.2 transitivePeerDependencies: @@ -8688,19 +9028,19 @@ packages: - supports-color dev: true - /@storybook/builder-manager@7.0.24: - resolution: {integrity: sha512-qSehfB1yS1ch/XSUdqNaTXitboNry4aKASte+kFhM5wSJcAgGBeB5akz8pc+JiRPWozqyceYkIdTG/KcRDeojg==} + /@storybook/builder-manager@7.1.1: + resolution: {integrity: sha512-vocO/JjrXPOnkFnwCV2NqKxbTfyYD2qV8PGH8EFNw2+I13GNbZ5CphEZMhI7HmKm0aIYPKdZKbN4KNWkwOxyAQ==} dependencies: '@fal-works/esbuild-plugin-global-externals': 2.1.2 - '@storybook/core-common': 7.0.24 - '@storybook/manager': 7.0.24 - '@storybook/node-logger': 7.0.24 + '@storybook/core-common': 7.1.1 + '@storybook/manager': 7.1.1 + '@storybook/node-logger': 7.1.1 '@types/ejs': 3.1.2 '@types/find-cache-dir': 3.2.1 - '@yarnpkg/esbuild-plugin-pnp': 3.0.0-rc.15(esbuild@0.17.19) + '@yarnpkg/esbuild-plugin-pnp': 3.0.0-rc.15(esbuild@0.18.17) browser-assert: 1.2.1 ejs: 3.1.8 - esbuild: 0.17.19 + esbuild: 0.18.17 esbuild-plugin-alias: 0.2.1 express: 4.18.2 find-cache-dir: 3.3.2 @@ -8712,8 +9052,8 @@ packages: - supports-color dev: true - /@storybook/builder-webpack5@7.0.24(@swc/core@1.3.51)(esbuild@0.17.5)(react-dom@18.2.0)(react@18.2.0)(typescript@5.1.3): - resolution: {integrity: sha512-gA4otfsq9yTRT2IdYKkyqUdy+60a09CRDUtM1JB8a1eLmyL4az02qZv/l6D9Ccj/w5JNcJndtJX+3thOowOWOQ==} + /@storybook/builder-webpack5@7.1.1(@swc/helpers@0.5.0)(esbuild@0.17.5)(react-dom@18.2.0)(react@18.2.0)(typescript@5.1.3): + resolution: {integrity: sha512-is9BIExHJzNH8nbgLn8M/OWqDLu9XM2Ht4NQl1XqoKQNVurNffAtHYZr8Mhuxfx94ifwuJiZ8WSa2b8k16VquA==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 @@ -8723,34 +9063,35 @@ packages: optional: true dependencies: '@babel/core': 7.22.9 - '@storybook/addons': 7.0.24(react-dom@18.2.0)(react@18.2.0) - '@storybook/api': 7.0.24(react-dom@18.2.0)(react@18.2.0) - '@storybook/channel-postmessage': 7.0.24 - '@storybook/channel-websocket': 7.0.24 - '@storybook/channels': 7.0.24 - '@storybook/client-api': 7.0.24 - '@storybook/client-logger': 7.0.24 - '@storybook/components': 7.0.24(react-dom@18.2.0)(react@18.2.0) - '@storybook/core-common': 7.0.24 - '@storybook/core-events': 7.0.24 - '@storybook/core-webpack': 7.0.24 + '@storybook/addons': 7.1.1(react-dom@18.2.0)(react@18.2.0) + '@storybook/api': 7.1.1(react-dom@18.2.0)(react@18.2.0) + '@storybook/channel-postmessage': 7.1.1 + '@storybook/channels': 7.1.1 + '@storybook/client-api': 7.1.1 + '@storybook/client-logger': 7.1.1 + '@storybook/components': 7.1.1(react-dom@18.2.0)(react@18.2.0) + '@storybook/core-common': 7.1.1 + '@storybook/core-events': 7.1.1 + '@storybook/core-webpack': 7.1.1 '@storybook/global': 5.0.0 - '@storybook/manager-api': 7.0.24(react-dom@18.2.0)(react@18.2.0) - '@storybook/node-logger': 7.0.24 - '@storybook/preview': 7.0.24 - '@storybook/preview-api': 7.0.24 - '@storybook/router': 7.0.24(react-dom@18.2.0)(react@18.2.0) - '@storybook/store': 7.0.24 - '@storybook/theming': 7.0.24(react-dom@18.2.0)(react@18.2.0) + '@storybook/manager-api': 7.1.1(react-dom@18.2.0)(react@18.2.0) + '@storybook/node-logger': 7.1.1 + '@storybook/preview': 7.1.1 + '@storybook/preview-api': 7.1.1 + '@storybook/router': 7.1.1(react-dom@18.2.0)(react@18.2.0) + '@storybook/store': 7.1.1 + '@storybook/theming': 7.1.1(react-dom@18.2.0)(react@18.2.0) + '@swc/core': 1.3.51(@swc/helpers@0.5.0) '@types/node': 16.18.36 '@types/semver': 7.5.0 babel-loader: 9.1.2(@babel/core@7.22.9)(webpack@5.88.0) babel-plugin-named-exports-order: 0.0.2 browser-assert: 1.2.1 case-sensitive-paths-webpack-plugin: 2.4.0 + constants-browserify: 1.0.0 css-loader: 6.8.1(webpack@5.88.0) express: 4.18.2 - fork-ts-checker-webpack-plugin: 7.2.13(typescript@5.1.3)(webpack@5.88.0) + fork-ts-checker-webpack-plugin: 8.0.0(typescript@5.1.3)(webpack@5.88.0) fs-extra: 11.1.1 html-webpack-plugin: 5.5.0(webpack@5.88.0) path-browserify: 1.0.1 @@ -8759,36 +9100,26 @@ packages: react-dom: 18.2.0(react@18.2.0) semver: 7.5.3 style-loader: 3.3.1(webpack@5.88.0) + swc-loader: 0.2.3(@swc/core@1.3.51)(webpack@5.88.0) terser-webpack-plugin: 5.3.9(@swc/core@1.3.51)(esbuild@0.17.5)(webpack@5.88.0) ts-dedent: 2.2.0 typescript: 5.1.3 + url: 0.11.1 util: 0.12.5 util-deprecate: 1.0.2 webpack: 5.88.0(@swc/core@1.3.51)(esbuild@0.17.5) - webpack-dev-middleware: 5.3.3(webpack@5.88.0) + webpack-dev-middleware: 6.1.1(webpack@5.88.0) webpack-hot-middleware: 2.25.3 - webpack-virtual-modules: 0.4.6 + webpack-virtual-modules: 0.5.0 transitivePeerDependencies: - - '@swc/core' + - '@swc/helpers' - encoding - esbuild - supports-color - uglify-js - - vue-template-compiler - webpack-cli dev: true - /@storybook/channel-postmessage@7.0.24: - resolution: {integrity: sha512-QLtLXjEeTEwBN/7pB888mBaykmRU9Jy2BitvZuLJWyHHygTYm3vYZOaGR37DT+q/6Ob5GaZ0tURZmCSNDe8IIA==} - dependencies: - '@storybook/channels': 7.0.24 - '@storybook/client-logger': 7.0.24 - '@storybook/core-events': 7.0.24 - '@storybook/global': 5.0.0 - qs: 6.11.0 - telejson: 7.1.0 - dev: true - /@storybook/channel-postmessage@7.0.7: resolution: {integrity: sha512-XMtYfcaE0UoY/V7K1cTu9PcWETD4iyWb/Yswc4F9VrPw0Ui4UwGS1j4iaAu8DC06yyoJs4XvxYFBMlCQmKja6A==} dependencies: @@ -8800,13 +9131,11 @@ packages: telejson: 7.1.0 dev: true - /@storybook/channel-websocket@7.0.24: - resolution: {integrity: sha512-GKSlWx5FgMQM0TKRCSGNTxLh0YU7xmg7m6FH8b/mvhH0Uido487qcJap2Ma/WOLe8aRiZo9jJpfcbUsKBWhuMg==} + /@storybook/channel-postmessage@7.1.1: + resolution: {integrity: sha512-Gmjh3feilXKLmZkQdjgkT8BRrfHnrBJJ8CY86MwD4wQlohObeFIXfhueRof4vJEGvIfJwooUrk9CkkXb5YbluQ==} dependencies: - '@storybook/channels': 7.0.24 - '@storybook/client-logger': 7.0.24 - '@storybook/global': 5.0.0 - telejson: 7.1.0 + '@storybook/channels': 7.1.1 + '@storybook/client-logger': 7.1.1 dev: true /@storybook/channels@7.0.24: @@ -8817,17 +9146,22 @@ packages: resolution: {integrity: sha512-Om4ovBLNw8pVrBu83MpOKgAuGO9Dpr1Coh2qp8t64WRPkejX1mxOY9IgH723//zH3igx8LCkf9rvBvcrsyaScQ==} dev: true - /@storybook/client-api@7.0.24: - resolution: {integrity: sha512-D9brib29aET1peRq6Nu7iBFgE+9W7ia3KCua5/AS980RFnXgGPE9x07knTbaAOuiHxHFrmQpdFF9BvVms1GS4A==} + /@storybook/channels@7.1.1: + resolution: {integrity: sha512-uhkZFtLIeRnbBhyLlvQAZQmsRbftX/YMGQL+9WRzICrCkwl4xfZPAvMxEgCj1iJzNFcaX5ma9XzHb7q/i+wUCw==} dependencies: - '@storybook/client-logger': 7.0.24 - '@storybook/preview-api': 7.0.24 + '@storybook/client-logger': 7.1.1 + '@storybook/core-events': 7.1.1 + '@storybook/global': 5.0.0 + qs: 6.11.0 + telejson: 7.1.0 + tiny-invariant: 1.3.1 dev: true - /@storybook/client-logger@7.0.24: - resolution: {integrity: sha512-4zRTb+QQ1hWaRqad/UufZNRfi2d/cf5a40My72Ct97VwjhJFE6aQ3K+hl1Xt6hh8dncDL2JK3cgziw6ElqjT0w==} + /@storybook/client-api@7.1.1: + resolution: {integrity: sha512-e6dTrgZOfO29EcckvHiBcojPCWhW0UYWREId2aXBwL6W5hP6zejbirc3SEXECehOOrlKnyY816AWtF7xEGFNKw==} dependencies: - '@storybook/global': 5.0.0 + '@storybook/client-logger': 7.1.1 + '@storybook/preview-api': 7.1.1 dev: true /@storybook/client-logger@7.0.7: @@ -8836,17 +9170,23 @@ packages: '@storybook/global': 5.0.0 dev: true - /@storybook/components@7.0.24(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-Pu7zGurCyWyiuFl2Pb5gybHA0f4blmHuVqccbMqnUw4Ew80BRu8AqfhNqN2hNdxFCx0mmy0baRGVftx76rNZ0w==} + /@storybook/client-logger@7.1.1: + resolution: {integrity: sha512-R0bdVjzJ5CwLNAG3XMyMZ0e9XDteBkFkTTIZJ9m+WMh/+oa2PInCpXDxoYb180UI6abrqh1jEaAsrHMC1pTKnA==} + dependencies: + '@storybook/global': 5.0.0 + dev: true + + /@storybook/components@7.0.7(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-6PLs9LMkBuhH/w4bSJ72tYgICMbOOIHuoB/fQdVlzhsdnXL2fM/v4RVW2N7v+Oz3lYXp/JtV8V9Ub8h6eDQKXg==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 dependencies: - '@storybook/client-logger': 7.0.24 + '@storybook/client-logger': 7.0.7 '@storybook/csf': 0.1.0 '@storybook/global': 5.0.0 - '@storybook/theming': 7.0.24(react-dom@18.2.0)(react@18.2.0) - '@storybook/types': 7.0.24 + '@storybook/theming': 7.0.7(react-dom@18.2.0)(react@18.2.0) + '@storybook/types': 7.0.7 memoizerific: 1.11.3 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) @@ -8854,17 +9194,17 @@ packages: util-deprecate: 1.0.2 dev: true - /@storybook/components@7.0.7(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-6PLs9LMkBuhH/w4bSJ72tYgICMbOOIHuoB/fQdVlzhsdnXL2fM/v4RVW2N7v+Oz3lYXp/JtV8V9Ub8h6eDQKXg==} + /@storybook/components@7.1.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-RUSjDj2RDTZsdKfs48oY+3iaL/y3GHU07zuHm/V4kuEHqJscXUt3n5vIX/Z/GtezMrxc0aPDlCSyS/N/EU6bUQ==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 dependencies: - '@storybook/client-logger': 7.0.7 + '@storybook/client-logger': 7.1.1 '@storybook/csf': 0.1.0 '@storybook/global': 5.0.0 - '@storybook/theming': 7.0.7(react-dom@18.2.0)(react@18.2.0) - '@storybook/types': 7.0.7 + '@storybook/theming': 7.1.1(react-dom@18.2.0)(react@18.2.0) + '@storybook/types': 7.1.1 memoizerific: 1.11.3 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) @@ -8872,29 +9212,30 @@ packages: util-deprecate: 1.0.2 dev: true - /@storybook/core-client@7.0.24: - resolution: {integrity: sha512-uToMHbi5EnOk+8Z941j0hrRE1h9u/QWqCmqS2FBIWrBOeREwy0AAib1/hqihzhO7OzekY5mtLTANiCpIpLHAHQ==} + /@storybook/core-client@7.1.1: + resolution: {integrity: sha512-yFd617XKFS+Q5IFmItXR+DdMfpreHHcdy3f67dt8PLnnjNcGMpi7gEcp8t9yBAT+pIgnqSfE/FNUFTg0OEpRpw==} dependencies: - '@storybook/client-logger': 7.0.24 - '@storybook/preview-api': 7.0.24 + '@storybook/client-logger': 7.1.1 + '@storybook/preview-api': 7.1.1 dev: true - /@storybook/core-common@7.0.24: - resolution: {integrity: sha512-FHjL2dpwDHnicLTePkiZMfO5eFxJxpTP2xmGWFQnWFTyEgh+ipcWnLVoYYXiKcc6EzKED0yebk8rAIalbzpICg==} + /@storybook/core-common@7.1.1: + resolution: {integrity: sha512-DO7ZS6YDITykvqMHeOWSmnsPYk2w7gka9GtO2LPbEm0f6p5kG2nohBO5+nsI3PuXpKiHXOB7vKJjwfQqxvPj5A==} dependencies: - '@storybook/node-logger': 7.0.24 - '@storybook/types': 7.0.24 + '@storybook/node-logger': 7.1.1 + '@storybook/types': 7.1.1 + '@types/find-cache-dir': 3.2.1 '@types/node': 16.18.36 '@types/node-fetch': 2.6.4 '@types/pretty-hrtime': 1.0.1 chalk: 4.1.2 - esbuild: 0.17.19 - esbuild-register: 3.4.2(esbuild@0.17.19) + esbuild: 0.18.17 + esbuild-register: 3.4.2(esbuild@0.18.17) file-system-cache: 2.3.0 + find-cache-dir: 3.3.2 find-up: 5.0.0 fs-extra: 11.1.1 - glob: 8.1.0 - glob-promise: 6.0.2(glob@8.1.0) + glob: 10.2.2 handlebars: 4.7.7 lazy-universal-dotenv: 4.0.0 node-fetch: 2.6.12 @@ -8912,47 +9253,46 @@ packages: resolution: {integrity: sha512-1DCHCwHRL3+rlvnVVc/BCfReP31XaT2WYgcLeGTmkX1E43Po1MkgcM7PnJPSaa9POvSqZ+6YLZv5Bs1SXbufow==} dev: true - /@storybook/core-events@7.0.24: - resolution: {integrity: sha512-xkf/rihCkhqMeh5EA8lVp90/mzbb2gcg6I3oeFWw2hognVcTnPXg6llhWdU4Spqd0cals7GEFmQugIILCmH8GA==} - dev: true - /@storybook/core-events@7.0.7: resolution: {integrity: sha512-XNsR2RgaL2vBwuqsu+KA1DzGmB1UFfrAhpxhmyWTKDCniwtTLlaXgfKbqwcrOrPu/o1YswgIup/9UHepRHaf4A==} dev: true - /@storybook/core-server@7.0.24: - resolution: {integrity: sha512-FJgdbtLgppFMd/RedF728I+v45TRG7s5/3RJfwgRgbq4ZEhKFzZN66MwWFeq3i5Q8ETHVwAxyVvC/JrRqAJxoA==} + /@storybook/core-events@7.1.1: + resolution: {integrity: sha512-P5iI4zvCJo85de/sghglEHFK/GGkWAQQKzRFrz9kbVBX5LNaosfD7IYHIz/6ZWNPzxWR+RBOKcrRUfcArL4Njg==} + dev: true + + /@storybook/core-server@7.1.1: + resolution: {integrity: sha512-IfrkdcYwVoP4bltBTx8Yr1e++UAfICV8IYCgW8VFW26Uvl22biCVWwliE35iTYpUmHJgn+U489hCnEdGpr2CWw==} dependencies: - '@aw-web-design/x-default-browser': 1.4.88 + '@aw-web-design/x-default-browser': 1.4.126 '@discoveryjs/json-ext': 0.5.7 - '@storybook/builder-manager': 7.0.24 - '@storybook/core-common': 7.0.24 - '@storybook/core-events': 7.0.24 + '@storybook/builder-manager': 7.1.1 + '@storybook/channels': 7.1.1 + '@storybook/core-common': 7.1.1 + '@storybook/core-events': 7.1.1 '@storybook/csf': 0.1.0 - '@storybook/csf-tools': 7.0.24 + '@storybook/csf-tools': 7.1.1 '@storybook/docs-mdx': 0.1.0 '@storybook/global': 5.0.0 - '@storybook/manager': 7.0.24 - '@storybook/node-logger': 7.0.24 - '@storybook/preview-api': 7.0.24 - '@storybook/telemetry': 7.0.24 - '@storybook/types': 7.0.24 + '@storybook/manager': 7.1.1 + '@storybook/node-logger': 7.1.1 + '@storybook/preview-api': 7.1.1 + '@storybook/telemetry': 7.1.1 + '@storybook/types': 7.1.1 '@types/detect-port': 1.3.2 '@types/node': 16.18.36 - '@types/node-fetch': 2.6.2 '@types/pretty-hrtime': 1.0.1 '@types/semver': 7.5.0 - better-opn: 2.1.1 + better-opn: 3.0.2 chalk: 4.1.2 cli-table3: 0.6.3 compression: 1.7.4 detect-port: 1.5.1 express: 4.18.2 - fs-extra: 11.1.0 + fs-extra: 11.1.1 globby: 11.1.0 ip: 2.0.0 lodash: 4.17.21 - node-fetch: 2.6.7 open: 8.4.2 pretty-hrtime: 1.0.3 prompts: 2.4.2 @@ -8960,7 +9300,9 @@ packages: semver: 7.5.3 serve-favicon: 2.5.0 telejson: 7.1.0 + tiny-invariant: 1.3.1 ts-dedent: 2.2.0 + util: 0.12.5 util-deprecate: 1.0.2 watchpack: 2.4.0 ws: 8.13.0 @@ -8971,12 +9313,12 @@ packages: - utf-8-validate dev: true - /@storybook/core-webpack@7.0.24: - resolution: {integrity: sha512-sM0hX55uNFXfQdRMthFdY6luWmi9MG+dIj6bNPiVY2SxNenxj62P/0/R/1Ime27X/vzFbi12pqUijzPNUwiwQw==} + /@storybook/core-webpack@7.1.1: + resolution: {integrity: sha512-1dk5dX0JYM0Xs7dYLl+WVt9ytiFNPqeOZXYYIk/6ZU0Ejm2E91VwDB0KMI6Dl+YjTDDxSlbwmHNYpFLyW9LDUA==} dependencies: - '@storybook/core-common': 7.0.24 - '@storybook/node-logger': 7.0.24 - '@storybook/types': 7.0.24 + '@storybook/core-common': 7.1.1 + '@storybook/node-logger': 7.1.1 + '@storybook/types': 7.1.1 '@types/node': 16.18.36 ts-dedent: 2.2.0 transitivePeerDependencies: @@ -8984,24 +9326,24 @@ packages: - supports-color dev: true - /@storybook/csf-plugin@7.0.24: - resolution: {integrity: sha512-+oIZCIhrRFbvplXUwJn671ZM0kgNqZ59jM9RmehJGgu5N5h1JSbBcz1edXgStNsMk9e2NJopuOKrzZGTGyi0XA==} + /@storybook/csf-plugin@7.1.1: + resolution: {integrity: sha512-bokV+HU6rV/wlWIvgAtn1PUot1W71pto/Wft5hCUATDCsXDz4B5aI9d/ZCJhu7G1R4cYtjsxVdBJSHe9dem7Lg==} dependencies: - '@storybook/csf-tools': 7.0.24 - unplugin: 0.10.2 + '@storybook/csf-tools': 7.1.1 + unplugin: 1.4.0 transitivePeerDependencies: - supports-color dev: true - /@storybook/csf-tools@7.0.24: - resolution: {integrity: sha512-RBNiXY3ht6XpcIyVgxBo7mK2t32tJuC93OO/HgcoRFClcdA8HUnlva297XpJpMqCgrcF8fPqRo+ZcLeC7vjzvw==} + /@storybook/csf-tools@7.1.1: + resolution: {integrity: sha512-IdDW+NsTIxqv7BjeFaTonvX0Ac5HzzNiKvGkhydXrpaz7kJX4g0T96xpR+RhbEtPfQ0AcpiHnW0kMPx9YLJRew==} dependencies: - '@babel/generator': 7.21.4 - '@babel/parser': 7.21.4 - '@babel/traverse': 7.21.4(supports-color@5.5.0) - '@babel/types': 7.21.4 + '@babel/generator': 7.22.9 + '@babel/parser': 7.22.7 + '@babel/traverse': 7.22.8 + '@babel/types': 7.22.5 '@storybook/csf': 0.1.0 - '@storybook/types': 7.0.24 + '@storybook/types': 7.1.1 fs-extra: 11.1.1 recast: 0.23.1 ts-dedent: 2.2.0 @@ -9025,13 +9367,12 @@ packages: resolution: {integrity: sha512-JDaBR9lwVY4eSH5W8EGHrhODjygPd6QImRbwjAuJNEnY0Vw4ie3bPkeGfnacB3OBW6u/agqPv2aRlR46JcAQLg==} dev: true - /@storybook/docs-tools@7.0.24: - resolution: {integrity: sha512-vmDHmHB1B5CWsYQ7CEtfz4vdf36VK/EZdNQUox9kdN935Dks7KSuGcDdXiRlWc78e94/A9+1mJQpyfwtn3E8fQ==} + /@storybook/docs-tools@7.1.1: + resolution: {integrity: sha512-noDgogRHum1FuqgXBdlv2+wOdkIJOJqSUSi0ZGiuP1OEOdA9YdbCfbWn/z734UEmhwraoQSXYb2tvrIEjfzYSw==} dependencies: - '@babel/core': 7.22.9 - '@storybook/core-common': 7.0.24 - '@storybook/preview-api': 7.0.24 - '@storybook/types': 7.0.24 + '@storybook/core-common': 7.1.1 + '@storybook/preview-api': 7.1.1 + '@storybook/types': 7.1.1 '@types/doctrine': 0.0.3 doctrine: 3.0.0 lodash: 4.17.21 @@ -9044,20 +9385,20 @@ packages: resolution: {integrity: sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ==} dev: true - /@storybook/manager-api@7.0.24(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-cBpgDWq8reFgyrv4fBZlZJQyWYb9cDW0LDe476rWn/29uXNvYMNsHRwveLNgSA8Oy1NdyQCgf4ZgcYvY3wpvMA==} + /@storybook/manager-api@7.0.7(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-QTd/P72peAhofKqK+8yzIO9iWAEfPn8WUGGveV2KGaTlSlgbr87RLHEKilcXMZcYhBWC9izFRmjKum9ROdskrQ==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 dependencies: - '@storybook/channels': 7.0.24 - '@storybook/client-logger': 7.0.24 - '@storybook/core-events': 7.0.24 + '@storybook/channels': 7.0.7 + '@storybook/client-logger': 7.0.7 + '@storybook/core-events': 7.0.7 '@storybook/csf': 0.1.0 '@storybook/global': 5.0.0 - '@storybook/router': 7.0.24(react-dom@18.2.0)(react@18.2.0) - '@storybook/theming': 7.0.24(react-dom@18.2.0)(react@18.2.0) - '@storybook/types': 7.0.24 + '@storybook/router': 7.0.7(react-dom@18.2.0)(react@18.2.0) + '@storybook/theming': 7.0.7(react-dom@18.2.0)(react@18.2.0) + '@storybook/types': 7.0.7 dequal: 2.0.3 lodash: 4.17.21 memoizerific: 1.11.3 @@ -9069,20 +9410,20 @@ packages: ts-dedent: 2.2.0 dev: true - /@storybook/manager-api@7.0.7(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-QTd/P72peAhofKqK+8yzIO9iWAEfPn8WUGGveV2KGaTlSlgbr87RLHEKilcXMZcYhBWC9izFRmjKum9ROdskrQ==} + /@storybook/manager-api@7.1.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-gk429qAGMW33rAZwFXo7fDoeYGrnSbj4ddHXJYc0nzBcC6emlq5IS5GHgJthQ3Oe8CPbq8bwUkWW6I5E7OePWA==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 dependencies: - '@storybook/channels': 7.0.7 - '@storybook/client-logger': 7.0.7 - '@storybook/core-events': 7.0.7 + '@storybook/channels': 7.1.1 + '@storybook/client-logger': 7.1.1 + '@storybook/core-events': 7.1.1 '@storybook/csf': 0.1.0 '@storybook/global': 5.0.0 - '@storybook/router': 7.0.7(react-dom@18.2.0)(react@18.2.0) - '@storybook/theming': 7.0.7(react-dom@18.2.0)(react@18.2.0) - '@storybook/types': 7.0.7 + '@storybook/router': 7.1.1(react-dom@18.2.0)(react@18.2.0) + '@storybook/theming': 7.1.1(react-dom@18.2.0)(react@18.2.0) + '@storybook/types': 7.1.1 dequal: 2.0.3 lodash: 4.17.21 memoizerific: 1.11.3 @@ -9094,32 +9435,27 @@ packages: ts-dedent: 2.2.0 dev: true - /@storybook/manager@7.0.24: - resolution: {integrity: sha512-LsQd2cFJViwoPJ7K0A/XBWrBBhJv7F0J6+aa7qHszNmIZHVbMXyZfiX7JS3RHVs4I2kLuNpSk4X+iDG0QAafEQ==} + /@storybook/manager@7.1.1: + resolution: {integrity: sha512-kRW9sPuJWsEi8Swcyt9rYwdfvA0rqKEuPBCCbrmmjyIwZR60IYg2KHXcF7q4qdkvts2xee5YTbgHcdfc0iIPSg==} dev: true /@storybook/mdx2-csf@1.0.0: resolution: {integrity: sha512-dBAnEL4HfxxJmv7LdEYUoZlQbWj9APZNIbOaq0tgF8XkxiIbzqvgB0jhL/9UOrysSDbQWBiCRTu2wOVxedGfmw==} dev: true - /@storybook/node-logger@7.0.24: - resolution: {integrity: sha512-gjcYnreYBBtZVF6p/cHMas4FEafPddjsLMrAfB+0lLGoRdUwWVto46BZTHQ9seY5gPW0JQydAdDGHko8/kEOXA==} - dependencies: - '@types/npmlog': 4.1.4 - chalk: 4.1.2 - npmlog: 5.0.1 - pretty-hrtime: 1.0.3 + /@storybook/node-logger@7.1.1: + resolution: {integrity: sha512-gnAuNM+wNoOcGnUM6hLsYV0lwUgRI39Ep/Pp3VF1oXZAthEyrQRm7ImbeAdt93ObPc9DZgqTx9OI8QnErZuJiA==} dev: true - /@storybook/postinstall@7.0.24: - resolution: {integrity: sha512-UYMXyEU4nVIKyrlUdIs3NHQmILzrN+EkEDbmeQC2WMMPw+t4GY2cDVmpx90JYYZcn7gY+cNDgQ55iiqbvlamLQ==} + /@storybook/postinstall@7.1.1: + resolution: {integrity: sha512-qpe6BiFLVs9YYFQVGgRT0dJxPOKBtGLIAsnVEpXKUPrltEWQpTxQEqqOSJlut+FLoWB5MTxrwiJ/7891h4a5pw==} dev: true - /@storybook/preset-react-webpack@7.0.24(@babel/core@7.22.9)(@swc/core@1.3.51)(esbuild@0.17.5)(react-dom@18.2.0)(react@18.2.0)(typescript@5.1.3)(webpack-dev-server@4.11.1): - resolution: {integrity: sha512-9BI243TMv5f+CjzGVB3CFA82E2kWYhQTaRoeNKxxk7NvgiascFMATkgBjIwtGYVXL9umk8mytzulOq/oXPnscQ==} + /@storybook/preset-react-webpack@7.1.1(@babel/core@7.22.9)(@swc/core@1.3.51)(esbuild@0.17.5)(react-dom@18.2.0)(react@18.2.0)(typescript@5.1.3)(webpack-dev-server@4.11.1): + resolution: {integrity: sha512-SuYNaFzPf7FWDKn7+InsOPltAt/wooCOrpgVYYNTyeEOj7TXn+YvGcxb3d0HVzQAzQuYyobt10KQGfgjUUfxgQ==} engines: {node: '>=16.0.0'} peerDependencies: - '@babel/core': ^7.11.5 + '@babel/core': ^7.22.0 react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 typescript: '*' @@ -9130,13 +9466,13 @@ packages: optional: true dependencies: '@babel/core': 7.22.9 - '@babel/preset-flow': 7.21.4(@babel/core@7.22.9) + '@babel/preset-flow': 7.22.5(@babel/core@7.22.9) '@babel/preset-react': 7.22.5(@babel/core@7.22.9) '@pmmmwh/react-refresh-webpack-plugin': 0.5.10(react-refresh@0.11.0)(webpack-dev-server@4.11.1)(webpack@5.88.0) - '@storybook/core-webpack': 7.0.24 - '@storybook/docs-tools': 7.0.24 - '@storybook/node-logger': 7.0.24 - '@storybook/react': 7.0.24(react-dom@18.2.0)(react@18.2.0)(typescript@5.1.3) + '@storybook/core-webpack': 7.1.1 + '@storybook/docs-tools': 7.1.1 + '@storybook/node-logger': 7.1.1 + '@storybook/react': 7.1.1(react-dom@18.2.0)(react@18.2.0)(typescript@5.1.3) '@storybook/react-docgen-typescript-plugin': 1.0.6--canary.9.0c3f3b7.0(typescript@5.1.3)(webpack@5.88.0) '@types/node': 16.18.36 '@types/semver': 7.5.0 @@ -9164,16 +9500,16 @@ packages: - webpack-plugin-serve dev: true - /@storybook/preview-api@7.0.24: - resolution: {integrity: sha512-psycU07tuB5nyJvfAJiDN/9e8cjOdJ+5lrCSYC3vPzH86LxADDIN0/8xFb1CaQWcXZsADEFJGpHKWbRhjym5ew==} + /@storybook/preview-api@7.0.7: + resolution: {integrity: sha512-R5pmGTodpu6hbwEg2RM2ulWtW3d426YzsisHrZJ+FT9lecWauN1y9xHCz7HdNzEFhT8r4YOa24L9ZS3mosZ7hA==} dependencies: - '@storybook/channel-postmessage': 7.0.24 - '@storybook/channels': 7.0.24 - '@storybook/client-logger': 7.0.24 - '@storybook/core-events': 7.0.24 + '@storybook/channel-postmessage': 7.0.7 + '@storybook/channels': 7.0.7 + '@storybook/client-logger': 7.0.7 + '@storybook/core-events': 7.0.7 '@storybook/csf': 0.1.0 '@storybook/global': 5.0.0 - '@storybook/types': 7.0.24 + '@storybook/types': 7.0.7 '@types/qs': 6.9.7 dequal: 2.0.3 lodash: 4.17.21 @@ -9184,16 +9520,16 @@ packages: util-deprecate: 1.0.2 dev: true - /@storybook/preview-api@7.0.7: - resolution: {integrity: sha512-R5pmGTodpu6hbwEg2RM2ulWtW3d426YzsisHrZJ+FT9lecWauN1y9xHCz7HdNzEFhT8r4YOa24L9ZS3mosZ7hA==} + /@storybook/preview-api@7.1.1: + resolution: {integrity: sha512-uI8TVuoFfg3EBdaKdRVUa17JfGdmK78JI3+byLZLkzl6nR+q846BWHgi8eJmU8MHmO5CFaqT2kts/e8T34JDgw==} dependencies: - '@storybook/channel-postmessage': 7.0.7 - '@storybook/channels': 7.0.7 - '@storybook/client-logger': 7.0.7 - '@storybook/core-events': 7.0.7 + '@storybook/channel-postmessage': 7.1.1 + '@storybook/channels': 7.1.1 + '@storybook/client-logger': 7.1.1 + '@storybook/core-events': 7.1.1 '@storybook/csf': 0.1.0 '@storybook/global': 5.0.0 - '@storybook/types': 7.0.7 + '@storybook/types': 7.1.1 '@types/qs': 6.9.7 dequal: 2.0.3 lodash: 4.17.21 @@ -9204,8 +9540,8 @@ packages: util-deprecate: 1.0.2 dev: true - /@storybook/preview@7.0.24: - resolution: {integrity: sha512-rej4Wz8Qy4gVuyvg4cpQGkR4wJc3b+0Uv6EYylbmpdj2585cOhFtRBykagDVZteVU4xaLMT7YHIZRnoLmJKIgw==} + /@storybook/preview@7.1.1: + resolution: {integrity: sha512-F3ikRKzwmT9MlptYXxYOQmaSwmJckPag0k9lM0LvI0xYplLbyWJ5rfs2gLKl++wX+ag2A+1K4gId5Xaz4SKnxQ==} dev: true /@storybook/react-docgen-typescript-plugin@1.0.6--canary.9.0c3f3b7.0(typescript@5.1.3)(webpack@5.88.0): @@ -9227,8 +9563,8 @@ packages: - supports-color dev: true - /@storybook/react-dom-shim@7.0.24(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-YOP1C3dWTLYP5mPb7hNuDRIhADzz+ppfb+S22JNJ3kqm+tsyE/YtAbRf80k6QIG1LzukMpGoEnjjOPOsWsyvFQ==} + /@storybook/react-dom-shim@7.1.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-yfc0tCtg+OEfvOKwCF0+E0ot8XGpubMTpbfChahhzEYyI9zz1rA7OCwRzERMnX/C7TYW3aLab9f5MzWIKQClmQ==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 @@ -9237,11 +9573,11 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: true - /@storybook/react-webpack5@7.0.24(@babel/core@7.22.9)(@swc/core@1.3.51)(esbuild@0.17.5)(react-dom@18.2.0)(react@18.2.0)(typescript@5.1.3)(webpack-dev-server@4.11.1): - resolution: {integrity: sha512-z5TwjpLeNXyNAPVGvTsHcXa9sjOop4lorWa++prJAY5Bpx+2//dq/O8poQat7KivtwCBmAlgYWqW52AcxXwYXA==} + /@storybook/react-webpack5@7.1.1(@babel/core@7.22.9)(@swc/core@1.3.51)(@swc/helpers@0.5.0)(esbuild@0.17.5)(react-dom@18.2.0)(react@18.2.0)(typescript@5.1.3)(webpack-dev-server@4.11.1): + resolution: {integrity: sha512-iTliWdmqSXw5wz/iHefr7yKhI7rko8oN5JUfkYlZafqk7M3mXy0wamLgFcrOncnBcY2UNPX1oEAiLJBKSy9ulA==} engines: {node: '>=16.0.0'} peerDependencies: - '@babel/core': ^7.11.5 + '@babel/core': ^7.22.0 react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 typescript: '*' @@ -9252,15 +9588,16 @@ packages: optional: true dependencies: '@babel/core': 7.22.9 - '@storybook/builder-webpack5': 7.0.24(@swc/core@1.3.51)(esbuild@0.17.5)(react-dom@18.2.0)(react@18.2.0)(typescript@5.1.3) - '@storybook/preset-react-webpack': 7.0.24(@babel/core@7.22.9)(@swc/core@1.3.51)(esbuild@0.17.5)(react-dom@18.2.0)(react@18.2.0)(typescript@5.1.3)(webpack-dev-server@4.11.1) - '@storybook/react': 7.0.24(react-dom@18.2.0)(react@18.2.0)(typescript@5.1.3) + '@storybook/builder-webpack5': 7.1.1(@swc/helpers@0.5.0)(esbuild@0.17.5)(react-dom@18.2.0)(react@18.2.0)(typescript@5.1.3) + '@storybook/preset-react-webpack': 7.1.1(@babel/core@7.22.9)(@swc/core@1.3.51)(esbuild@0.17.5)(react-dom@18.2.0)(react@18.2.0)(typescript@5.1.3)(webpack-dev-server@4.11.1) + '@storybook/react': 7.1.1(react-dom@18.2.0)(react@18.2.0)(typescript@5.1.3) '@types/node': 16.18.36 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) typescript: 5.1.3 transitivePeerDependencies: - '@swc/core' + - '@swc/helpers' - '@types/webpack' - encoding - esbuild @@ -9268,15 +9605,14 @@ packages: - supports-color - type-fest - uglify-js - - vue-template-compiler - webpack-cli - webpack-dev-server - webpack-hot-middleware - webpack-plugin-serve dev: true - /@storybook/react@7.0.24(react-dom@18.2.0)(react@18.2.0)(typescript@5.1.3): - resolution: {integrity: sha512-JAgSs8ANysBl3+cOAjFSVG3bA2V/wP6jyu7oK0jSATRQhHRjRS/tHFMA82j0j98G2sr3JXQUxNt55Qq3k2mUcg==} + /@storybook/react@7.1.1(react-dom@18.2.0)(react@18.2.0)(typescript@5.1.3): + resolution: {integrity: sha512-qgZ/K2KKR+WrIHZEg5UZn0kqlzDk+sP51yosn7Ymt8j85yNgYm4G1q+oGYY+wKSIJEIi31mrQEz8oFHn8jaT2Q==} engines: {node: '>=16.0.0'} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 @@ -9286,13 +9622,13 @@ packages: typescript: optional: true dependencies: - '@storybook/client-logger': 7.0.24 - '@storybook/core-client': 7.0.24 - '@storybook/docs-tools': 7.0.24 + '@storybook/client-logger': 7.1.1 + '@storybook/core-client': 7.1.1 + '@storybook/docs-tools': 7.1.1 '@storybook/global': 5.0.0 - '@storybook/preview-api': 7.0.24 - '@storybook/react-dom-shim': 7.0.24(react-dom@18.2.0)(react@18.2.0) - '@storybook/types': 7.0.24 + '@storybook/preview-api': 7.1.1 + '@storybook/react-dom-shim': 7.1.1(react-dom@18.2.0)(react@18.2.0) + '@storybook/types': 7.1.1 '@types/escodegen': 0.0.6 '@types/estree': 0.0.51 '@types/node': 16.18.36 @@ -9307,7 +9643,7 @@ packages: react-dom: 18.2.0(react@18.2.0) react-element-to-jsx-string: 15.0.0(react-dom@18.2.0)(react@18.2.0) ts-dedent: 2.2.0 - type-fest: 2.19.0 + type-fest: 3.13.1 typescript: 5.1.3 util-deprecate: 1.0.2 transitivePeerDependencies: @@ -9315,78 +9651,77 @@ packages: - supports-color dev: true - /@storybook/router@7.0.24(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-SRCV+srCZUbko/V0phVN8jY8ilrxQWWAY/gegwNlIYaNqLJSyYqIj739VDmX+deXl6rOEpFLZreClVXWiDU9+w==} + /@storybook/router@7.0.7(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-/lM8/NHQKeshfnC3ayFuO8Y9TCSHnCAPRhIsVxvanBzcj+ILbCIyZ+TspvB3hT4MbX/Ez+JR8VrMbjXIGwmH8w==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 dependencies: - '@storybook/client-logger': 7.0.24 + '@storybook/client-logger': 7.0.7 memoizerific: 1.11.3 qs: 6.11.0 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: true - /@storybook/router@7.0.7(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-/lM8/NHQKeshfnC3ayFuO8Y9TCSHnCAPRhIsVxvanBzcj+ILbCIyZ+TspvB3hT4MbX/Ez+JR8VrMbjXIGwmH8w==} + /@storybook/router@7.1.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-GRYYWVsqAtDm7DHxnGXuaAmr3PQfj+tonYsP8/L3gC5sOdQNF3yaBmvv1pu+bqezwXVowq0ew+iVYECiaGoB3Q==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 dependencies: - '@storybook/client-logger': 7.0.7 + '@storybook/client-logger': 7.1.1 memoizerific: 1.11.3 qs: 6.11.0 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: true - /@storybook/store@7.0.24: - resolution: {integrity: sha512-T6BOXpiIAiGpQcfe0Hyu3d+8Gd0sUaVTSDXJLadfr7tqC6qmMpOuyApFu1qRfgJqh4aykUb75ESCvYWoEjwm+A==} + /@storybook/store@7.1.1: + resolution: {integrity: sha512-gg2DOYZdnhV3l0i1OVJ4Cjd2zH38gWdXhA/K0S8KTpfD/uakpf6U3+K543ADnS+9C8JT9I0Z2RUZmWEkv3fFBQ==} dependencies: - '@storybook/client-logger': 7.0.24 - '@storybook/preview-api': 7.0.24 + '@storybook/client-logger': 7.1.1 + '@storybook/preview-api': 7.1.1 dev: true - /@storybook/telemetry@7.0.24: - resolution: {integrity: sha512-mLGwm3yeWlM9Srrcecrpce4m8uyazIMkHIYcBC0cD2L/JzIRzeRS3Na8QlLKz4/+Hxawm7K/pE/DBrVjvBbm8A==} + /@storybook/telemetry@7.1.1: + resolution: {integrity: sha512-7bQBfphEHJA1kHyPVVvrRXRet57JhyRD4uxoWYfp4jkSt2wHzAAdGU8Iz7U+ozv4TG7AA1gb1Uh5BS4nCiijsw==} dependencies: - '@storybook/client-logger': 7.0.24 - '@storybook/core-common': 7.0.24 + '@storybook/client-logger': 7.1.1 + '@storybook/core-common': 7.1.1 + '@storybook/csf-tools': 7.1.1 chalk: 4.1.2 detect-package-manager: 2.0.1 fetch-retry: 5.0.3 fs-extra: 11.1.1 - isomorphic-unfetch: 3.1.0 - nanoid: 3.3.6 read-pkg-up: 7.0.1 transitivePeerDependencies: - encoding - supports-color dev: true - /@storybook/theming@7.0.24(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-CMeCCfqffJ/D5rBl1HpAM/e5Vw0h7ucT+CLzP0ALtLrguz9ZzOiIZYgMj17KpfvWqje7HT+DwEtNkSrnJ01FNQ==} + /@storybook/theming@7.0.7(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-InTZe+Sgco1NsxgiG+cyUKWQe3GsjlIyU/o5qDdtOTXcZ64HzyBuAZlAequSddqfDeMDqxRFPc2w1J28MAUHxA==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 dependencies: '@emotion/use-insertion-effect-with-fallbacks': 1.0.0(react@18.2.0) - '@storybook/client-logger': 7.0.24 + '@storybook/client-logger': 7.0.7 '@storybook/global': 5.0.0 memoizerific: 1.11.3 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: true - /@storybook/theming@7.0.7(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-InTZe+Sgco1NsxgiG+cyUKWQe3GsjlIyU/o5qDdtOTXcZ64HzyBuAZlAequSddqfDeMDqxRFPc2w1J28MAUHxA==} + /@storybook/theming@7.1.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-8ri/BvfgUzBln9EYB8N/xgRaxZIFFTG0IEEekuV2H5uv4q9JW9p3E5zqghmM1OC/vspJJa8e4Eajb1YiTO0W6w==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 dependencies: '@emotion/use-insertion-effect-with-fallbacks': 1.0.0(react@18.2.0) - '@storybook/client-logger': 7.0.7 + '@storybook/client-logger': 7.1.1 '@storybook/global': 5.0.0 memoizerific: 1.11.3 react: 18.2.0 @@ -9411,6 +9746,15 @@ packages: file-system-cache: 2.3.0 dev: true + /@storybook/types@7.1.1: + resolution: {integrity: sha512-0yxEHxYd/N0XfVCGrEq86QIMC4ljZBspHSDrjdLSCIYmmglMvwKboZBgHlLQmpcLP+of8m1E8Frbslpnt0giBg==} + dependencies: + '@storybook/channels': 7.1.1 + '@types/babel__core': 7.1.20 + '@types/express': 4.17.14 + file-system-cache: 2.3.0 + dev: true + /@supabase/functions-js@2.1.2: resolution: {integrity: sha512-QCR6pwJs9exCl37bmpMisUd6mf+0SUBJ6mUpiAjEkSJ/+xW8TCuO14bvkWHADd5hElJK9MxNlMQXxSA4DRz9nQ==} dependencies: @@ -10153,6 +10497,7 @@ packages: dependencies: '@types/minimatch': 5.1.2 '@types/node': 18.16.9 + dev: false /@types/graceful-fs@4.1.6: resolution: {integrity: sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==} @@ -10276,6 +10621,7 @@ packages: /@types/linkify-it@3.0.2: resolution: {integrity: sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==} + requiresBuild: true dev: false optional: true @@ -10301,6 +10647,7 @@ packages: /@types/mdurl@1.0.2: resolution: {integrity: sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==} + requiresBuild: true dev: false optional: true @@ -10323,13 +10670,6 @@ packages: resolution: {integrity: sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==} dev: true - /@types/node-fetch@2.6.2: - resolution: {integrity: sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A==} - dependencies: - '@types/node': 18.16.9 - form-data: 3.0.1 - dev: true - /@types/node-fetch@2.6.4: resolution: {integrity: sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg==} dependencies: @@ -10352,10 +10692,6 @@ packages: resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==} dev: true - /@types/npmlog@4.1.4: - resolution: {integrity: sha512-WKG4gTr8przEZBiJ5r3s8ZIAoMXNbOgQ+j/d5O4X3x6kZJRLNvyUJuUK/KoG3+8BaOHPhp2m7WC6JKKeovDSzQ==} - dev: true - /@types/parse-json@4.0.0: resolution: {integrity: sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==} dev: true @@ -11194,13 +11530,13 @@ packages: resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==} dev: true - /@yarnpkg/esbuild-plugin-pnp@3.0.0-rc.15(esbuild@0.17.19): + /@yarnpkg/esbuild-plugin-pnp@3.0.0-rc.15(esbuild@0.18.17): resolution: {integrity: sha512-kYzDJO5CA9sy+on/s2aIW0411AklfCi8Ck/4QDivOqsMKpStZA2SsR+X27VTggGwpStWaLrjJcDcdDMowtG8MA==} engines: {node: '>=14.15.0'} peerDependencies: esbuild: '>=0.10.0' dependencies: - esbuild: 0.17.19 + esbuild: 0.18.17 tslib: 2.5.3 dev: true @@ -11313,6 +11649,12 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + /acorn@8.10.0: + resolution: {integrity: sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: true + /acorn@8.8.1: resolution: {integrity: sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==} engines: {node: '>=0.4.0'} @@ -11571,14 +11913,6 @@ packages: resolution: {integrity: sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==} dev: true - /are-we-there-yet@2.0.0: - resolution: {integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==} - engines: {node: '>=10'} - dependencies: - delegates: 1.0.0 - readable-stream: 3.6.0 - dev: true - /are-we-there-yet@3.0.1: resolution: {integrity: sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} @@ -11838,7 +12172,7 @@ packages: peerDependencies: postcss: ^8.1.0 dependencies: - browserslist: 4.21.7 + browserslist: 4.21.9 caniuse-lite: 1.0.30001492 fraction.js: 4.2.0 normalize-range: 0.1.2 @@ -11983,7 +12317,7 @@ packages: dependencies: '@babel/core': 7.22.9 '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-typescript': 7.20.0(@babel/core@7.22.9) + '@babel/plugin-syntax-typescript': 7.22.5(@babel/core@7.22.9) '@babel/traverse': 7.22.8 transitivePeerDependencies: - supports-color @@ -12291,11 +12625,11 @@ packages: resolution: {integrity: sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==} dev: true - /better-opn@2.1.1: - resolution: {integrity: sha512-kIPXZS5qwyKiX/HcRvDYfmBQUa8XP17I0mYZZ0y4UhpYOSvtsLHDYqmomS+Mj20aDvD3knEiQ0ecQy2nhio3yA==} - engines: {node: '>8.0.0'} + /better-opn@3.0.2: + resolution: {integrity: sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ==} + engines: {node: '>=12.0.0'} dependencies: - open: 7.4.2 + open: 8.4.2 dev: true /big-integer@1.6.51: @@ -12613,6 +12947,7 @@ packages: /buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + dev: true /buffer-indexof-polyfill@1.0.2: resolution: {integrity: sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==} @@ -13220,6 +13555,7 @@ packages: /commander@2.20.3: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + dev: true /commander@4.1.1: resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} @@ -13376,6 +13712,10 @@ packages: resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} dev: true + /constants-browserify@1.0.0: + resolution: {integrity: sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==} + dev: true + /content-disposition@0.5.4: resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} engines: {node: '>= 0.6'} @@ -15079,13 +15419,13 @@ packages: resolution: {integrity: sha512-jyfL/pwPqaFXyKnj8lP8iLk6Z0m099uXR45aSN8Av1XD4vhvQutxxPzgA2bTcAwQpa1zCXDcWOlhFgyP3GKqhQ==} dev: true - /esbuild-register@3.4.2(esbuild@0.17.19): + /esbuild-register@3.4.2(esbuild@0.18.17): resolution: {integrity: sha512-kG/XyTDyz6+YDuyfB9ZoSIOOmgyFCH+xPRtsCa8W85HLRV5Csp+o3jWVbOSHgSLfyLc5DmP+KFDNwty4mEjC+Q==} peerDependencies: esbuild: '>=0.12 <1' dependencies: debug: 4.3.4(supports-color@5.5.0) - esbuild: 0.17.19 + esbuild: 0.18.17 transitivePeerDependencies: - supports-color dev: true @@ -15184,6 +15524,36 @@ packages: '@esbuild/win32-x64': 0.17.5 dev: true + /esbuild@0.18.17: + resolution: {integrity: sha512-1GJtYnUxsJreHYA0Y+iQz2UEykonY66HNWOb0yXYZi9/kNrORUEHVg87eQsCtqh59PEJ5YVZJO98JHznMJSWjg==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/android-arm': 0.18.17 + '@esbuild/android-arm64': 0.18.17 + '@esbuild/android-x64': 0.18.17 + '@esbuild/darwin-arm64': 0.18.17 + '@esbuild/darwin-x64': 0.18.17 + '@esbuild/freebsd-arm64': 0.18.17 + '@esbuild/freebsd-x64': 0.18.17 + '@esbuild/linux-arm': 0.18.17 + '@esbuild/linux-arm64': 0.18.17 + '@esbuild/linux-ia32': 0.18.17 + '@esbuild/linux-loong64': 0.18.17 + '@esbuild/linux-mips64el': 0.18.17 + '@esbuild/linux-ppc64': 0.18.17 + '@esbuild/linux-riscv64': 0.18.17 + '@esbuild/linux-s390x': 0.18.17 + '@esbuild/linux-x64': 0.18.17 + '@esbuild/netbsd-x64': 0.18.17 + '@esbuild/openbsd-x64': 0.18.17 + '@esbuild/sunos-x64': 0.18.17 + '@esbuild/win32-arm64': 0.18.17 + '@esbuild/win32-ia32': 0.18.17 + '@esbuild/win32-x64': 0.18.17 + dev: true + /escalade@3.1.1: resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} engines: {node: '>=6'} @@ -16181,6 +16551,29 @@ packages: webpack: 5.75.0(@swc/core@1.3.51)(esbuild@0.17.5) dev: true + /fork-ts-checker-webpack-plugin@8.0.0(typescript@5.1.3)(webpack@5.88.0): + resolution: {integrity: sha512-mX3qW3idpueT2klaQXBzrIM/pHw+T0B/V9KHEvNrqijTq9NFnMZU6oreVxDYcf33P8a5cW+67PjodNHthGnNVg==} + engines: {node: '>=12.13.0', yarn: '>=1.0.0'} + peerDependencies: + typescript: '>3.6.0' + webpack: ^5.11.0 + dependencies: + '@babel/code-frame': 7.22.5 + chalk: 4.1.2 + chokidar: 3.5.3 + cosmiconfig: 7.0.1 + deepmerge: 4.3.1 + fs-extra: 10.1.0 + memfs: 3.5.0 + minimatch: 3.0.5 + node-abort-controller: 3.1.1 + schema-utils: 3.2.0 + semver: 7.5.3 + tapable: 2.2.1 + typescript: 5.1.3 + webpack: 5.88.0(@swc/core@1.3.51)(esbuild@0.17.5) + dev: true + /form-data@2.3.3: resolution: {integrity: sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==} engines: {node: '>= 0.12'} @@ -16369,21 +16762,6 @@ packages: resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} dev: true - /gauge@3.0.2: - resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==} - engines: {node: '>=10'} - dependencies: - aproba: 2.0.0 - color-support: 1.1.3 - console-control-strings: 1.1.0 - has-unicode: 2.0.1 - object-assign: 4.1.1 - signal-exit: 3.0.7 - string-width: 4.2.3 - strip-ansi: 6.0.1 - wide-align: 1.1.5 - dev: true - /gauge@4.0.4: resolution: {integrity: sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} @@ -16599,16 +16977,6 @@ packages: glob: 7.2.3 dev: false - /glob-promise@6.0.2(glob@8.1.0): - resolution: {integrity: sha512-Ni2aDyD1ekD6x8/+K4hDriRDbzzfuK4yKpqSymJ4P7IxbtARiOOuU+k40kbHM0sLIlbf1Qh0qdMkAHMZYE6XJQ==} - engines: {node: '>=16'} - peerDependencies: - glob: ^8.0.3 - dependencies: - '@types/glob': 8.0.0 - glob: 8.1.0 - dev: true - /glob-to-regexp@0.4.1: resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} dev: true @@ -17965,15 +18333,6 @@ packages: engines: {node: '>=0.10.0'} dev: true - /isomorphic-unfetch@3.1.0: - resolution: {integrity: sha512-geDJjpoZ8N0kWexiwkX8F9NkTsXhetLPVbZFQ+JTW239QNOwvB0gniuR1Wc6f0AMTn7/mFGyXvHTifrCp/GH8Q==} - dependencies: - node-fetch: 2.6.12 - unfetch: 4.2.0 - transitivePeerDependencies: - - encoding - dev: true - /isstream@0.1.2: resolution: {integrity: sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==} dev: true @@ -20924,15 +21283,6 @@ packages: dependencies: path-key: 3.1.1 - /npmlog@5.0.1: - resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==} - dependencies: - are-we-there-yet: 2.0.0 - console-control-strings: 1.1.0 - gauge: 3.0.2 - set-blocking: 2.0.0 - dev: true - /npmlog@6.0.2: resolution: {integrity: sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} @@ -21117,8 +21467,8 @@ packages: - debug dev: true - /nx@16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51): - resolution: {integrity: sha512-hbiYe4cxLBMTYO9sjLg6N3gh709Cf38tVXxbzv1y3ZXaRA2nyH6NSerk+VP7Om7IxQku8RTItscZqM8qsb4/mA==} + /nx@16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51): + resolution: {integrity: sha512-qF2fzLo6IH9BRiITrIpK68w+VL/TlB+6jr28JugbfDvEOWAVCWTckUbtq7TdOcW/ns3pZ40SgqVfdiuLZJ/OGA==} hasBin: true requiresBuild: true peerDependencies: @@ -21130,7 +21480,7 @@ packages: '@swc/core': optional: true dependencies: - '@nrwl/tao': 16.6.0-beta.4(@swc-node/register@1.5.4)(@swc/core@1.3.51) + '@nrwl/tao': 16.6.0-beta.8(@swc-node/register@1.5.4)(@swc/core@1.3.51) '@parcel/watcher': 2.0.4 '@swc-node/register': 1.5.4(@swc/core@1.3.51)(typescript@5.1.3) '@swc/core': 1.3.51(@swc/helpers@0.5.0) @@ -21168,16 +21518,16 @@ packages: yargs: 17.7.2 yargs-parser: 21.1.1 optionalDependencies: - '@nx/nx-darwin-arm64': 16.6.0-beta.4 - '@nx/nx-darwin-x64': 16.6.0-beta.4 - '@nx/nx-freebsd-x64': 16.6.0-beta.4 - '@nx/nx-linux-arm-gnueabihf': 16.6.0-beta.4 - '@nx/nx-linux-arm64-gnu': 16.6.0-beta.4 - '@nx/nx-linux-arm64-musl': 16.6.0-beta.4 - '@nx/nx-linux-x64-gnu': 16.6.0-beta.4 - '@nx/nx-linux-x64-musl': 16.6.0-beta.4 - '@nx/nx-win32-arm64-msvc': 16.6.0-beta.4 - '@nx/nx-win32-x64-msvc': 16.6.0-beta.4 + '@nx/nx-darwin-arm64': 16.6.0-beta.8 + '@nx/nx-darwin-x64': 16.6.0-beta.8 + '@nx/nx-freebsd-x64': 16.6.0-beta.8 + '@nx/nx-linux-arm-gnueabihf': 16.6.0-beta.8 + '@nx/nx-linux-arm64-gnu': 16.6.0-beta.8 + '@nx/nx-linux-arm64-musl': 16.6.0-beta.8 + '@nx/nx-linux-x64-gnu': 16.6.0-beta.8 + '@nx/nx-linux-x64-musl': 16.6.0-beta.8 + '@nx/nx-win32-arm64-msvc': 16.6.0-beta.8 + '@nx/nx-win32-x64-msvc': 16.6.0-beta.8 transitivePeerDependencies: - debug dev: true @@ -21319,14 +21669,6 @@ packages: mimic-fn: 2.1.0 dev: true - /open@7.4.2: - resolution: {integrity: sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==} - engines: {node: '>=8'} - dependencies: - is-docker: 2.2.1 - is-wsl: 2.2.0 - dev: true - /open@8.4.0: resolution: {integrity: sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==} engines: {node: '>=12'} @@ -23315,6 +23657,7 @@ packages: /prr@1.0.1: resolution: {integrity: sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==} + requiresBuild: true optional: true /pseudomap@1.0.2: @@ -24365,6 +24708,7 @@ packages: chokidar: 3.5.3 immutable: 4.1.0 source-map-js: 1.0.2 + dev: true /sax@1.2.4: resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==} @@ -24959,6 +25303,7 @@ packages: dependencies: buffer-from: 1.1.2 source-map: 0.6.1 + dev: true /source-map@0.5.7: resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} @@ -25543,6 +25888,16 @@ packages: resolution: {integrity: sha512-DlZARu6ckUFqDe0j5IPayO4k0gQvYQw9Un02MhxAgaMtVnTH2vmyyDe+yKeV0r1LiiPx3JbasdS/5Yyb/AV3iw==} dev: true + /swc-loader@0.2.3(@swc/core@1.3.51)(webpack@5.88.0): + resolution: {integrity: sha512-D1p6XXURfSPleZZA/Lipb3A8pZ17fP4NObZvFCDjK/OKljroqDpPmsBdTraWhVBqUNpcWBQY1imWdoPScRlQ7A==} + peerDependencies: + '@swc/core': ^1.2.147 + webpack: '>=2' + dependencies: + '@swc/core': 1.3.51(@swc/helpers@0.5.0) + webpack: 5.88.0(@swc/core@1.3.51)(esbuild@0.17.5) + dev: true + /swr@2.1.5(react@18.2.0): resolution: {integrity: sha512-/OhfZMcEpuz77KavXST5q6XE9nrOBOVcBLWjMT+oAE/kQHyE3PASrevXCtQDZ8aamntOfFkbVJp7Il9tNBQWrw==} peerDependencies: @@ -25848,6 +26203,7 @@ packages: acorn: 8.8.2 commander: 2.20.3 source-map-support: 0.5.21 + dev: true /terser@5.18.0: resolution: {integrity: sha512-pdL757Ig5a0I+owA42l6tIuEycRuM7FPY4n62h44mRLRfnOxJkkOHd6i89dOpwZlpF6JXBwaAHF6yWzFrt+QyA==} @@ -25944,6 +26300,10 @@ packages: globrex: 0.1.2 dev: true + /tiny-invariant@1.3.1: + resolution: {integrity: sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==} + dev: true + /tinybench@2.5.0: resolution: {integrity: sha512-kRwSG8Zx4tjF9ZiyH4bhaebu+EDz1BOx9hOigYHlUW4xxI/wKIUQUqo018UlU4ar6ATPBsaMrdbKZ+tmPdohFA==} dev: false @@ -25986,6 +26346,10 @@ packages: dependencies: is-number: 7.0.0 + /tocbot@4.21.0: + resolution: {integrity: sha512-vXk8htr8mIl3hc2s2mDkaPTBfqmqZA2o0x7eXbxUibdrpEIPdpM0L9hH/RvEvlgSM+ZTgS34sGipk5+VrLJCLA==} + dev: true + /toggle-selection@1.0.6: resolution: {integrity: sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==} dev: false @@ -26389,6 +26753,11 @@ packages: engines: {node: '>=12.20'} dev: true + /type-fest@3.13.1: + resolution: {integrity: sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==} + engines: {node: '>=14.16'} + dev: true + /type-is@1.6.18: resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} engines: {node: '>= 0.6'} @@ -26506,10 +26875,6 @@ packages: resolution: {integrity: sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==} dev: true - /unfetch@4.2.0: - resolution: {integrity: sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA==} - dev: true - /unicode-canonical-property-names-ecmascript@2.0.0: resolution: {integrity: sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==} engines: {node: '>=4'} @@ -26629,13 +26994,13 @@ packages: engines: {node: '>= 0.8'} dev: true - /unplugin@0.10.2: - resolution: {integrity: sha512-6rk7GUa4ICYjae5PrAllvcDeuT8pA9+j5J5EkxbMFaV+SalHhxZ7X2dohMzu6C3XzsMT+6jwR/+pwPNR3uK9MA==} + /unplugin@1.4.0: + resolution: {integrity: sha512-5x4eIEL6WgbzqGtF9UV8VEC/ehKptPXDS6L2b0mv4FRMkJxRtjaJfOWDd6a8+kYbqsjklix7yWP0N3SUepjXcg==} dependencies: - acorn: 8.8.2 + acorn: 8.10.0 chokidar: 3.5.3 webpack-sources: 3.2.3 - webpack-virtual-modules: 0.4.6 + webpack-virtual-modules: 0.5.0 dev: true /untildify@4.0.0: @@ -26740,6 +27105,13 @@ packages: requires-port: 1.0.0 dev: true + /url@0.11.1: + resolution: {integrity: sha512-rWS3H04/+mzzJkv0eZ7vEDGiQbgquI1fGfOad6zKvgYQi1SzMmhl7c/DdRGxhaWrVH6z0qWITo8rpnxK/RfEhA==} + dependencies: + punycode: 1.4.1 + qs: 6.11.0 + dev: true + /use-isomorphic-layout-effect@1.1.2(@types/react@18.2.14)(react@18.2.0): resolution: {integrity: sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==} peerDependencies: @@ -26973,7 +27345,7 @@ packages: mlly: 1.2.0 pathe: 1.1.0 picocolors: 1.0.0 - vite: 4.3.9(@types/node@18.16.9)(less@4.1.3)(sass@1.63.2)(stylus@0.59.0)(terser@5.17.7) + vite: 4.3.9(@types/node@18.16.9)(less@4.1.3)(sass@1.55.0)(stylus@0.59.0) transitivePeerDependencies: - '@types/node' - less @@ -27019,6 +27391,42 @@ packages: optionalDependencies: fsevents: 2.3.2 + /vite@4.3.9(@types/node@18.16.9)(less@4.1.3)(sass@1.55.0)(stylus@0.59.0): + resolution: {integrity: sha512-qsTNZjO9NoJNW7KnOrgYwczm0WctJ8m/yqYAMAK9Lxt4SoySUfS5S8ia9K7JHpa3KEeMfyF8LoJ3c5NeBJy6pg==} + engines: {node: ^14.18.0 || >=16.0.0} + hasBin: true + peerDependencies: + '@types/node': '>= 14' + less: '*' + sass: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + dependencies: + '@types/node': 18.16.9 + esbuild: 0.17.19 + less: 4.1.3 + postcss: 8.4.24 + rollup: 3.21.0 + sass: 1.55.0 + stylus: 0.59.0 + optionalDependencies: + fsevents: 2.3.2 + dev: false + /vite@4.3.9(@types/node@18.16.9)(less@4.1.3)(sass@1.63.2)(stylus@0.59.0)(terser@5.17.7): resolution: {integrity: sha512-qsTNZjO9NoJNW7KnOrgYwczm0WctJ8m/yqYAMAK9Lxt4SoySUfS5S8ia9K7JHpa3KEeMfyF8LoJ3c5NeBJy6pg==} engines: {node: ^14.18.0 || >=16.0.0} @@ -27054,6 +27462,7 @@ packages: terser: 5.17.7 optionalDependencies: fsevents: 2.3.2 + dev: true /vitest@0.32.0(less@4.1.3)(sass@1.55.0)(stylus@0.59.0): resolution: {integrity: sha512-SW83o629gCqnV3BqBnTxhB10DAwzwEx3z+rqYZESehUB+eWsJxwcBQx7CKy0otuGMJTYh7qCVuUX23HkftGl/Q==} @@ -27266,6 +27675,23 @@ packages: webpack: 5.86.0(@swc/core@1.3.51)(esbuild@0.17.19) dev: true + /webpack-dev-middleware@6.1.1(webpack@5.88.0): + resolution: {integrity: sha512-y51HrHaFeeWir0YO4f0g+9GwZawuigzcAdRNon6jErXy/SqV/+O6eaVAzDqE6t3e3NpGeR5CS+cCDaTC+V3yEQ==} + engines: {node: '>= 14.15.0'} + peerDependencies: + webpack: ^5.0.0 + peerDependenciesMeta: + webpack: + optional: true + dependencies: + colorette: 2.0.19 + memfs: 3.5.0 + mime-types: 2.1.35 + range-parser: 1.2.1 + schema-utils: 4.1.0 + webpack: 5.88.0(@swc/core@1.3.51)(esbuild@0.17.5) + dev: true + /webpack-dev-server@4.11.1(webpack@5.88.0): resolution: {integrity: sha512-lILVz9tAUy1zGFwieuaQtYiadImb5M3d+H+L1zDYalYoDl0cksAB1UNyuE5MMWJrG6zR1tXkCP2fitl7yoUJiw==} engines: {node: '>= 12.13.0'} @@ -27480,8 +27906,8 @@ packages: webpack: 5.88.0(@swc/core@1.3.51)(esbuild@0.17.5) dev: true - /webpack-virtual-modules@0.4.6: - resolution: {integrity: sha512-5tyDlKLqPfMqjT3Q9TAqf2YqjwmnUleZwzJi1A5qXnlBCdj2AtOJ6wAWdglTIDOPgOiOrXeBeFcsQ8+aGQ6QbA==} + /webpack-virtual-modules@0.5.0: + resolution: {integrity: sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==} dev: true /webpack@5.75.0(@swc/core@1.3.51)(esbuild@0.17.5): @@ -27541,7 +27967,7 @@ packages: '@webassemblyjs/wasm-parser': 1.11.6 acorn: 8.8.2 acorn-import-assertions: 1.9.0(acorn@8.8.2) - browserslist: 4.21.7 + browserslist: 4.21.9 chrome-trace-event: 1.0.3 enhanced-resolve: 5.15.0 es-module-lexer: 1.3.0 @@ -28063,7 +28489,3 @@ packages: dependencies: tslib: 2.5.3 dev: true - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false diff --git a/scripts/copy-local-native.js b/scripts/copy-local-native.js index 1f27c716a3141..036d5f9b78a68 100644 --- a/scripts/copy-local-native.js +++ b/scripts/copy-local-native.js @@ -7,5 +7,6 @@ const p = process.argv[2]; const nativeFiles = glob.sync(`packages/${p}/**/*.node`); nativeFiles.forEach((file) => { + console.log('COPY', file, '=>', `build/${file}`); fs.copyFileSync(file, `build/${file}`); }); diff --git a/scripts/nx-release.ts b/scripts/nx-release.ts index 00dda6dac124e..6e9db2e27d78a 100755 --- a/scripts/nx-release.ts +++ b/scripts/nx-release.ts @@ -2,7 +2,7 @@ import * as yargs from 'yargs'; import { execSync } from 'child_process'; import { existsSync, readFileSync, rmSync, writeFileSync } from 'fs'; -import { URL } from 'url'; +import { URL } from 'node:url'; import { join } from 'path'; import { parse } from 'semver'; @@ -51,6 +51,9 @@ function hideFromGitIndex(uncommittedFiles: string[]) { execSync(buildCommand, { stdio: [0, 1, 2], }); + execSync(`ls -lah build/packages/nx/src/native`, { + stdio: [0, 1, 2], + }); if (options.local) { updateLernaJsonVersion(currentLatestVersion); From 47b3d49bb0d4826c1eef0677e0e260047bd3a0f9 Mon Sep 17 00:00:00 2001 From: Juri Date: Mon, 31 Jul 2023 09:54:55 +0200 Subject: [PATCH 219/262] feat(nx-dev): update youtube cmp to allow caption --- nx-dev/ui-markdoc/src/index.ts | 3 +- .../src/lib/tags/youtube.component.tsx | 46 +++++++++++++++++++ .../src/lib/tags/youtube.components.tsx | 12 ----- .../ui-markdoc/src/lib/tags/youtube.schema.ts | 19 -------- 4 files changed, 47 insertions(+), 33 deletions(-) create mode 100644 nx-dev/ui-markdoc/src/lib/tags/youtube.component.tsx delete mode 100644 nx-dev/ui-markdoc/src/lib/tags/youtube.components.tsx delete mode 100644 nx-dev/ui-markdoc/src/lib/tags/youtube.schema.ts diff --git a/nx-dev/ui-markdoc/src/index.ts b/nx-dev/ui-markdoc/src/index.ts index 15e516aa526d5..d8fc4637f0233 100644 --- a/nx-dev/ui-markdoc/src/index.ts +++ b/nx-dev/ui-markdoc/src/index.ts @@ -37,8 +37,7 @@ import { SideBySide } from './lib/tags/side-by-side.component'; import { sideBySide } from './lib/tags/side-by-side.schema'; import { Tab, Tabs } from './lib/tags/tabs.component'; import { tab, tabs } from './lib/tags/tabs.schema'; -import { YouTube } from './lib/tags/youtube.components'; -import { youtube } from './lib/tags/youtube.schema'; +import { YouTube, youtube } from './lib/tags/youtube.component'; import { TerminalCommand, terminalCommand, diff --git a/nx-dev/ui-markdoc/src/lib/tags/youtube.component.tsx b/nx-dev/ui-markdoc/src/lib/tags/youtube.component.tsx new file mode 100644 index 0000000000000..76ed8600ece6a --- /dev/null +++ b/nx-dev/ui-markdoc/src/lib/tags/youtube.component.tsx @@ -0,0 +1,46 @@ +import { Schema } from '@markdoc/markdoc'; + +export const youtube: Schema = { + render: 'YouTube', + attributes: { + src: { + type: 'String', + required: true, + }, + title: { + type: 'String', + required: true, + }, + width: { + type: 'String', + default: '50%', + }, + caption: { + // Added caption attribute here + type: 'String', + required: false, // Not required since it's optional + }, + }, +}; + +export function YouTube(props: any): JSX.Element { + return ( +
+ {' '} + {/* Center alignment applied to the container */} +