[
  {
    "path": ".eslintrc.json",
    "content": "{\n  \"env\": {\n    \"es2021\": true,\n    \"node\": true\n  },\n  \"extends\": [\"eslint:recommended\", \"plugin:@typescript-eslint/recommended\"],\n  \"overrides\": [],\n  \"parser\": \"@typescript-eslint/parser\",\n  \"parserOptions\": {\n    \"ecmaVersion\": \"latest\",\n    \"sourceType\": \"module\"\n  },\n  \"plugins\": [\"@typescript-eslint\"],\n  \"rules\": {\n    \"@typescript-eslint/no-explicit-any\": \"off\",\n    \"@typescript-eslint/no-var-requires\": \"off\",\n    \"@typescript-eslint/no-non-null-assertion\": \"off\"\n  }\n}\n"
  },
  {
    "path": ".gitattributes",
    "content": "* text=auto eol=lf\n"
  },
  {
    "path": ".github/CODEOWNERS",
    "content": "* @dilanx\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "# These are supported funding model platforms\n\ngithub: [dilanx]\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\nname: Bug report\nabout: Something with CRACO isn't working correctly\ntitle: ''\nlabels: bug\nassignees: ''\n\n---\n\n**What's happening**\n(clearly describe what's going wrong)\n\n**What should happen**\n(clearly describe what should happen instead)\n\n**To reproduce**\n(list the steps to reproduce this behavior)\n\n**CRACO version**\n(ex. 7.0.0)\n\n**CRACO config**\n```js\n// paste your config here\n```\n\n**package.json**\n```jsonc\n// paste your package.json (or at least your project dependencies) here\n```\n\n**Additional information**\n(anything else that could be useful for us to help you solve your problem)\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "content": "---\nname: Feature request\nabout: CRACO should have this functionality\ntitle: ''\nlabels: feature request\nassignees: ''\n\n---\n\n(clearly describe the functionality you think CRACO should have)\n"
  },
  {
    "path": ".github/workflows/run-tests.yml",
    "content": "name: tests\n\non: [push, pull_request]\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    timeout-minutes: 10\n\n    strategy:\n      matrix:\n        node-version: [16.x, 18.x]\n\n    steps:\n      - uses: actions/checkout@v2\n      - name: Use Node.js ${{ matrix.node-version }}\n        uses: actions/setup-node@v2\n        with:\n          node-version: ${{ matrix.node-version }}\n      - run: npm ci\n      - run: npm run build\n      - run: npm run test:unit\n      - run: npx playwright install-deps\n      - run: NODE_ENV=production npm run test:integration\n"
  },
  {
    "path": ".github/workflows/website-deploy.yml",
    "content": "name: Deploy website to GitHub Pages\n\non:\n  push:\n    branches:\n      - main\n    paths:\n      - '.github/workflows/website-deploy.yml'\n      - 'website/**'\n\njobs:\n  deploy:\n    name: Deploy website to GitHub Pages\n    runs-on: ubuntu-latest\n    defaults:\n      run:\n        working-directory: website\n    steps:\n      - uses: actions/checkout@v2\n      - uses: actions/setup-node@v3\n        with:\n          node-version: 18\n          cache: npm\n\n      - name: Install dependencies\n        run: npm ci\n      - name: Build website\n        run: npm run build\n\n      - name: Deploy to GitHub Pages\n        uses: peaceiris/actions-gh-pages@v3\n        with:\n          github_token: ${{ secrets.GITHUB_TOKEN }}\n          publish_dir: ./website/build\n          user_name: github-actions[bot]\n          user_email: 41898282+github-actions[bot]@users.noreply.github.com\n"
  },
  {
    "path": ".github/workflows/website-test-deploy.yml",
    "content": "name: Test website deployment\n\ndefaults:\n  run:\n    working-directory: website\n\non:\n  pull_request:\n    branches:\n      - main\n    paths:\n      - 'website/**'\n\njobs:\n  test-deploy:\n    name: Test website deployment\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v2\n      - uses: actions/setup-node@v3\n        with:\n          node-version: 18\n          cache: npm\n\n      - name: Install dependencies\n        run: npm ci\n      - name: Test build website\n        run: npm run build\n"
  },
  {
    "path": ".gitignore",
    "content": "# See https://help.github.com/ignore-files/ for more about ignoring files.\n\n# compiled\ndist\n\n# dependencies\nnode_modules\npackages/debug\n\n# misc\n.DS_Store\n/.idea\nnpm-debug.log*\nlerna-debug.log*\n*.tgz\n"
  },
  {
    "path": ".prettierignore",
    "content": "/.vscode\n/node_modules\n/recipes\npackage.json\npackage-lock.json\ntsconfig.json"
  },
  {
    "path": ".vscode/extensions.json",
    "content": "{\n    \"recommendations\": [\n        \"esbenp.prettier-vscode\"\n    ]\n}\n"
  },
  {
    "path": "LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n"
  },
  {
    "path": "README.md",
    "content": "<div align=\"center\">\n  <a href=\"https://craco.js.org\">\n    <img src=\"https://craco.js.org/img/craco.png\" width=\"200\" height=\"200\">\n  </a>\n  <h1>CRACO</h1>\n  <p>\n  \n**C**reate **R**eact **A**pp **C**onfiguration **O**verride, an easy and comprehensible configuration layer for create-react-app.\n\n**Find config docs, API docs, plugins, and example configs at [craco.js.org](https://craco.js.org)!**\n\n  </p>\n\n  <br>\n\n[![npm status](https://img.shields.io/npm/v/@craco/craco.svg)](https://www.npmjs.com/package/@craco/craco) [![npm downloads](https://img.shields.io/npm/dm/@craco/craco.svg)](https://www.npmjs.com/package/@craco/craco) [![npm license](https://img.shields.io/npm/l/@craco/craco?color=orange)](https://github.com/dilanx/craco/blob/main/packages/craco/LICENSE) [![GitHub stars](https://img.shields.io/github/stars/dilanx/craco?color=red)](https://github.com/dilanx/craco) [![GitHub contributors](https://img.shields.io/github/contributors/dilanx/craco?color=blueviolet)](https://github.com/dilanx/craco/graphs/contributors) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-blueviolet.svg)](https://github.com/dilanx/craco/pulls) ![Node.js CI](https://github.com/dilanx/craco/actions/workflows/run-tests.yml/badge.svg)\n\n</div>\n\nGet all the benefits of [Create React App](https://create-react-app.dev) **and** customization without using 'eject' by adding a single configuration (e.g. `craco.config.js`) file at the root of your application and customize your ESLint, Babel, PostCSS configurations and many more.\n\n1. Install the latest version of the package from npm as a dev dependency:\n\n   ```\n   npm i -D @craco/craco\n   ```\n\n2. Create a CRACO configuration file in your project's root directory and [configure](https://craco.js.org/docs/):\n\n   ```diff\n     my-app\n     ├── node_modules\n   + ├── craco.config.js\n     └── package.json\n   ```\n\n3. Update the existing calls to `react-scripts` in the `scripts` section of your `package.json` to use the `craco` CLI:\n\n   ```diff title=\"package.json\"\n   \"scripts\": {\n   -  \"start\": \"react-scripts start\"\n   +  \"start\": \"craco start\"\n   -  \"build\": \"react-scripts build\"\n   +  \"build\": \"craco build\"\n   -  \"test\": \"react-scripts test\"\n   +  \"test\": \"craco test\"\n   }\n   ```\n\nVisit [craco.js.org](https://craco.js.org) to learn more.\n"
  },
  {
    "path": "lerna.json",
    "content": "{\n  \"$schema\": \"node_modules/lerna/schemas/lerna-schema.json\",\n  \"useWorkspaces\": true,\n  \"version\": \"7.1.0\"\n}\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"craco\",\n  \"private\": true,\n  \"license\": \"Apache-2.0\",\n  \"keywords\": [\n    \"react\",\n    \"create-react-app\",\n    \"cra\"\n  ],\n  \"workspaces\": [\n    \"packages/*\"\n  ],\n  \"scripts\": {\n    \"test:unit\": \"jest --config test/unit/jest.config.js\",\n    \"test:integration\": \"NODE_ENV=production jest --config test/integration/jest.config.js --runInBand\",\n    \"lint\": \"npm run lint:ts && npm run lint:es\",\n    \"lint:ts\": \"tsc --noEmit\",\n    \"lint:es\": \"eslint --ext .ts\",\n    \"tslint\": \"tsc --noEmit\",\n    \"bootstrap\": \"lerna bootstrap\",\n    \"build\": \"lerna exec npm run build\",\n    \"build:types\": \"npm run build -w @craco/types\",\n    \"build:craco\": \"npm run build -w @craco/craco\",\n    \"publish\": \"lerna publish --no-private\",\n    \"publish:alpha\": \"lerna publish --dist-tag alpha --no-private\",\n    \"pack\": \"lerna exec npm pack\",\n    \"refresh\": \"npm run build && npm run bootstrap\",\n    \"refresh:types\": \"npm run build:types && npm run bootstrap\"\n  },\n  \"prettier\": \"@dilanx/config/prettier\",\n  \"devDependencies\": {\n    \"@dilanx/config\": \"^1.1.0\",\n    \"@typescript-eslint/eslint-plugin\": \"^5.38.1\",\n    \"@typescript-eslint/parser\": \"^5.38.1\",\n    \"eslint\": \"^8.24.0\",\n    \"jest\": \"^29.5.0\",\n    \"jest-playwright-preset\": \"^3.0.1\",\n    \"lerna\": \"^6.5.1\",\n    \"playwright\": \"^1.33.0\",\n    \"prettier\": \"2.7.1\"\n  }\n}\n"
  },
  {
    "path": "packages/craco/LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n"
  },
  {
    "path": "packages/craco/README.md",
    "content": "<div align=\"center\">\n  <a href=\"https://craco.js.org\">\n    <img src=\"https://craco.js.org/img/craco.png\" width=\"200\" height=\"200\">\n  </a>\n  <h1>CRACO</h1>\n  <p>\n  \n**C**reate **R**eact **A**pp **C**onfiguration **O**verride, an easy and comprehensible configuration layer for create-react-app.\n\n**Find config docs, API docs, plugins, and example configs at [craco.js.org](https://craco.js.org)!**\n\n  </p>\n\n  <br>\n\n[![npm status](https://img.shields.io/npm/v/@craco/craco.svg)](https://www.npmjs.com/package/@craco/craco) [![npm downloads](https://img.shields.io/npm/dm/@craco/craco.svg)](https://www.npmjs.com/package/@craco/craco) [![npm license](https://img.shields.io/npm/l/@craco/craco?color=orange)](https://github.com/dilanx/craco/blob/main/packages/craco/LICENSE) [![GitHub stars](https://img.shields.io/github/stars/dilanx/craco?color=red)](https://github.com/dilanx/craco) [![GitHub contributors](https://img.shields.io/github/contributors/dilanx/craco?color=blueviolet)](https://github.com/dilanx/craco/graphs/contributors) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-blueviolet.svg)](https://github.com/dilanx/craco/pulls)\n\n</div>\n\nGet all the benefits of [Create React App](https://create-react-app.dev) **and** customization without using 'eject' by adding a single configuration (e.g. `craco.config.js`) file at the root of your application and customize your ESLint, Babel, PostCSS configurations and many more.\n\n1. Install the latest version of the package from npm as a dev dependency:\n\n   ```\n   npm i -D @craco/craco\n   ```\n\n2. Create a CRACO configuration file in your project's root directory and [configure](https://craco.js.org/docs/):\n\n   ```diff\n     my-app\n     ├── node_modules\n   + ├── craco.config.js\n     └── package.json\n   ```\n\n3. Update the existing calls to `react-scripts` in the `scripts` section of your `package.json` to use the `craco` CLI:\n\n   ```diff title=\"package.json\"\n   \"scripts\": {\n   -  \"start\": \"react-scripts start\"\n   +  \"start\": \"craco start\"\n   -  \"build\": \"react-scripts build\"\n   +  \"build\": \"craco build\"\n   -  \"test\": \"react-scripts test\"\n   +  \"test\": \"craco test\"\n   }\n   ```\n\nVisit [craco.js.org](https://craco.js.org) to learn more.\n"
  },
  {
    "path": "packages/craco/package.json",
    "content": "{\n  \"name\": \"@craco/craco\",\n  \"description\": \"Create React App Configuration Override, an easy and comprehensible configuration layer for create-react-app.\",\n  \"version\": \"7.1.0\",\n  \"main\": \"dist/index.js\",\n  \"types\": \"dist/index.d.ts\",\n  \"files\": [\n    \"dist\"\n  ],\n  \"scripts\": {\n    \"build\": \"tsc\",\n    \"prepack\": \"npm run build\"\n  },\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/dilanx/craco.git\",\n    \"directory\": \"packages/craco\"\n  },\n  \"keywords\": [\n    \"react\",\n    \"create-react-app\",\n    \"cra\"\n  ],\n  \"author\": \"Dilan Nair (https://www.dilanxd.com)\",\n  \"contributors\": [\n    \"Groupe Sharegate inc.\"\n  ],\n  \"license\": \"Apache-2.0\",\n  \"bugs\": {\n    \"url\": \"https://github.com/dilanx/craco/issues\"\n  },\n  \"homepage\": \"https://craco.js.org\",\n  \"engines\": {\n    \"node\": \">=6\"\n  },\n  \"bin\": {\n    \"craco\": \"./dist/bin/craco.js\"\n  },\n  \"peerDependencies\": {\n    \"react-scripts\": \"^5.0.0\"\n  },\n  \"devDependencies\": {\n    \"@babel/types\": \"^7.19.3\",\n    \"@craco/types\": \"^7.1.0\",\n    \"@jest/types\": \"^27.5.1\",\n    \"@types/cross-spawn\": \"^6.0.2\",\n    \"@types/eslint\": \"^8.4.6\",\n    \"@types/jest\": \"^27.5.2\",\n    \"@types/lodash\": \"^4.14.186\",\n    \"@types/semver\": \"^7.3.12\",\n    \"babel-jest\": \"^29.7.0\",\n    \"eslint-webpack-plugin\": \"^3.2.0\",\n    \"jest\": \"^27.5.1\",\n    \"react-scripts\": \"5.*\",\n    \"ts-jest\": \"^27.1.5\",\n    \"typescript\": \"^4.8.4\",\n    \"webpack\": \"^5.74.0\"\n  },\n  \"dependencies\": {\n    \"autoprefixer\": \"^10.4.12\",\n    \"cosmiconfig\": \"^7.0.1\",\n    \"cosmiconfig-typescript-loader\": \"^1.0.0\",\n    \"cross-spawn\": \"^7.0.3\",\n    \"lodash\": \"^4.17.21\",\n    \"semver\": \"^7.3.7\",\n    \"webpack-merge\": \"^5.8.0\"\n  }\n}\n"
  },
  {
    "path": "packages/craco/src/bin/craco.ts",
    "content": "#!/usr/bin/env node\n\nimport spawn from 'cross-spawn';\n\nconst args = process.argv.slice(2);\nconst scriptIndex = args.findIndex(\n    (x) => x === 'build' || x === 'start' || x === 'test'\n);\nconst script = scriptIndex === -1 ? args[0] : args[scriptIndex];\n\nswitch (script) {\n    case 'build':\n    case 'start':\n    case 'test': {\n        const nodeArgs = scriptIndex > 0 ? args.slice(0, scriptIndex) : [];\n        const scriptPath = require.resolve(`../scripts/${script}`);\n        const scriptArgs = args.slice(scriptIndex + 1);\n        const processArgs = nodeArgs.concat(scriptPath).concat(scriptArgs);\n\n        const child = spawn.sync('node', processArgs, { stdio: 'inherit' });\n\n        if (child.signal) {\n            if (child.signal === 'SIGKILL') {\n                console.log(`\n                    The build failed because the process exited too early.\n                    This probably means the system ran out of memory or someone called\n                    \\`kill -9\\` on the process.\n                `);\n            } else if (child.signal === 'SIGTERM') {\n                console.log(`\n                    The build failed because the process exited too early.\n                    Someone might have called  \\`kill\\` or \\`killall\\`, or the system could\n                    be shutting down.\n                `);\n            }\n\n            process.exit(1);\n        }\n\n        process.exit(child.status ?? undefined);\n        break;\n    }\n    default:\n        console.log(`Unknown script \"${script}\".`);\n        console.log('Perhaps you need to update craco?');\n        break;\n}\n"
  },
  {
    "path": "packages/craco/src/bin/jest.ts",
    "content": "#!/usr/bin/env node\n\n/*\n * Copied (and converted to TS) from https://github.com/timarney/react-app-rewired/blob/master/packages/react-app-rewired/bin/jest.js\n\n * This file is necessary to allow usage of craco as a drop-in replacement\n * for react-scripts with WebStorms's test runner UI.\n *\n * For more information, see https://github.com/dilanx/craco/pull/41\n */\n\nimport spawn from 'cross-spawn';\nconst args = process.argv.slice(2);\n\nconst setupScriptFileIndex =\n  args.findIndex((x) => x === '--setupTestFrameworkScriptFile') + 1;\nconst isIntelliJ =\n  setupScriptFileIndex !== -1\n    ? false\n    : args[setupScriptFileIndex].indexOf('jest-intellij') !== -1;\n\nconst result = spawn.sync(\n  process.argv[0],\n  ([] as any[]).concat(require.resolve('../scripts/test'), args),\n  {\n    stdio: 'inherit',\n    env: Object.assign({}, process.env, isIntelliJ ? { CI: 1 } : null),\n  }\n);\n\nprocess.exit(result.signal ? 1 : result.status ?? undefined);\n"
  },
  {
    "path": "packages/craco/src/index.ts",
    "content": "import {\n  addAfterAssetModule,\n  addAfterAssetModules,\n  addBeforeAssetModule,\n  addBeforeAssetModules,\n  assetModuleByName,\n  getAssetModule,\n  getAssetModules,\n  removeAssetModules,\n} from './lib/asset-modules';\nimport { createDevServerConfigProviderProxy } from './lib/features/dev-server/api';\nimport { createJestConfig } from './lib/features/jest/api';\nimport {\n  createWebpackDevConfig,\n  createWebpackProdConfig,\n} from './lib/features/webpack/api';\nimport {\n  addAfterLoader,\n  addAfterLoaders,\n  addBeforeLoader,\n  addBeforeLoaders,\n  getLoader,\n  getLoaders,\n  loaderByName,\n  removeLoaders,\n} from './lib/loaders';\nimport { gitHubIssueUrl, throwUnexpectedConfigError } from './lib/plugin-utils';\nimport { when, whenDev, whenProd, whenTest } from './lib/user-config-utils';\nimport {\n  addPlugins,\n  getPlugin,\n  pluginByName,\n  removePlugins,\n} from './lib/webpack-plugins';\n\nexport {\n  getLoader,\n  getLoaders,\n  removeLoaders,\n  addBeforeLoader,\n  addBeforeLoaders,\n  addAfterLoader,\n  addAfterLoaders,\n  loaderByName,\n  getAssetModule,\n  getAssetModules,\n  removeAssetModules,\n  addBeforeAssetModule,\n  addBeforeAssetModules,\n  addAfterAssetModule,\n  addAfterAssetModules,\n  assetModuleByName,\n  getPlugin,\n  pluginByName,\n  addPlugins,\n  removePlugins,\n  when,\n  whenDev,\n  whenProd,\n  whenTest,\n  throwUnexpectedConfigError,\n  gitHubIssueUrl,\n  createJestConfig,\n  createWebpackDevConfig,\n  createWebpackProdConfig,\n  createDevServerConfigProviderProxy,\n};\n"
  },
  {
    "path": "packages/craco/src/lib/args.ts",
    "content": "export interface CliArgs {\n  [key: string]: string | boolean;\n}\n\nexport interface CliArgSpec {\n  [key: string]: { arg: string; value: boolean };\n}\n\nconst args: CliArgSpec = {\n  verbose: {\n    arg: '--verbose',\n    value: false,\n  },\n  config: {\n    arg: '--config',\n    value: true,\n  },\n};\n\nlet processedArgs: CliArgs = {};\n\nexport function getArgs() {\n  return processedArgs;\n}\n\nexport function setArgs(values?: CliArgs) {\n  processedArgs = {\n    ...processedArgs,\n    ...values,\n  };\n}\n\nexport function findArgsFromCli() {\n  const processed: CliArgs = {};\n  let i = 0;\n  while (i < process.argv.length) {\n    const arg = process.argv[i];\n    for (const a in args) {\n      if (arg === args[a].arg) {\n        processed[a] = args[a].value ? process.argv[i + 1] : true;\n        i++;\n      }\n    }\n    i++;\n  }\n  setArgs(processed);\n}\n"
  },
  {
    "path": "packages/craco/src/lib/asset-modules.ts",
    "content": "import type {\n  AssetModule,\n  AssetModuleMatcher,\n  AssetModuleType,\n} from '@craco/types';\nimport type { Configuration as WebpackConfig, RuleSetRule } from 'webpack';\n\nexport function assetModuleByName(assetModuleName: AssetModuleType) {\n  return (rule: RuleSetRule) => rule.type === assetModuleName;\n}\n\nconst toMatchingAssetModule = (\n  rule: RuleSetRule,\n  index: number\n): AssetModule => ({\n  rule,\n  index,\n});\n\nexport function getAssetModule(\n  webpackConfig: WebpackConfig,\n  matcher: AssetModuleMatcher\n) {\n  let matchingAssetModule: AssetModule | undefined;\n  (webpackConfig.module?.rules as RuleSetRule[])?.some((rule, index) => {\n    if (matcher(rule)) {\n      matchingAssetModule = toMatchingAssetModule(rule, index);\n    }\n    return matchingAssetModule !== undefined;\n  });\n  return {\n    isFound: matchingAssetModule !== undefined,\n    match: matchingAssetModule,\n  };\n}\n\nexport function getAssetModules(\n  webpackConfig: WebpackConfig,\n  matcher: AssetModuleMatcher\n) {\n  const matchingAssetModules: AssetModule[] = [];\n  (webpackConfig.module?.rules as RuleSetRule[])?.forEach((rule, index) => {\n    if (matcher(rule)) {\n      matchingAssetModules.push(toMatchingAssetModule(rule, index));\n    }\n  });\n\n  return {\n    hasFoundAny: matchingAssetModules.length !== 0,\n    matches: matchingAssetModules,\n  };\n}\n\nexport function removeAssetModules(\n  webpackConfig: WebpackConfig,\n  matcher: AssetModuleMatcher\n) {\n  const toRemove: number[] = [];\n  (webpackConfig.module?.rules as RuleSetRule[])?.forEach((rule, index) => {\n    if (matcher(rule)) {\n      toRemove.push(index);\n    }\n  });\n\n  toRemove.forEach((index) => {\n    webpackConfig.module?.rules?.splice(index, 1);\n  });\n\n  return {\n    rules: webpackConfig.module?.rules,\n    removedCount: toRemove.length,\n  };\n}\n\nfunction addAssetModule(\n  webpackConfig: WebpackConfig,\n  matcher: AssetModuleMatcher,\n  newAssetModule: RuleSetRule,\n  positionAdapter: (index: number) => number\n) {\n  const { match } = getAssetModule(webpackConfig, matcher);\n\n  if (match !== undefined) {\n    webpackConfig.module?.rules?.splice(\n      positionAdapter(match.index),\n      0,\n      newAssetModule\n    );\n\n    return { isAdded: true };\n  }\n\n  return { isAdded: false };\n}\n\nexport const addBeforeAssetModule = (\n  webpackConfig: WebpackConfig,\n  matcher: AssetModuleMatcher,\n  newAssetModule: RuleSetRule\n) => addAssetModule(webpackConfig, matcher, newAssetModule, (x) => x);\n\nexport const addAfterAssetModule = (\n  webpackConfig: WebpackConfig,\n  matcher: AssetModuleMatcher,\n  newAssetModule: RuleSetRule\n) => addAssetModule(webpackConfig, matcher, newAssetModule, (x) => x + 1);\n\nfunction addAssetModules(\n  webpackConfig: WebpackConfig,\n  matcher: AssetModuleMatcher,\n  newAssetModule: RuleSetRule,\n  positionAdapter: (index: number) => number\n) {\n  const { matches } = getAssetModules(webpackConfig, matcher);\n\n  if (matches.length !== 0) {\n    matches.forEach((match) => {\n      webpackConfig.module?.rules?.splice(\n        positionAdapter(match.index),\n        0,\n        newAssetModule\n      );\n    });\n\n    return { isAdded: true, addedCount: matches.length };\n  }\n\n  return { isAdded: false, addedCount: 0 };\n}\n\nexport const addBeforeAssetModules = (\n  webpackConfig: WebpackConfig,\n  matcher: AssetModuleMatcher,\n  newAssetModule: RuleSetRule\n) => addAssetModules(webpackConfig, matcher, newAssetModule, (x) => x);\n\nexport const addAfterAssetModules = (\n  webpackConfig: WebpackConfig,\n  matcher: AssetModuleMatcher,\n  newAssetModule: RuleSetRule\n) => addAssetModules(webpackConfig, matcher, newAssetModule, (x) => x + 1);\n"
  },
  {
    "path": "packages/craco/src/lib/config.ts",
    "content": "import type { BaseContext, CracoConfig } from '@craco/types';\n\nimport { cosmiconfigSync } from 'cosmiconfig';\nimport tsLoader from 'cosmiconfig-typescript-loader';\nimport path from 'path';\nimport { getArgs } from './args';\nimport { applyCracoConfigPlugins } from './features/plugins';\nimport { log } from './logger';\nimport { projectRoot } from './paths';\nimport { deepMergeWithArray, isArray, isFunction, isString } from './utils';\n\nconst DEFAULT_CONFIG: CracoConfig = {\n  reactScriptsVersion: 'react-scripts',\n  style: {\n    postcss: {\n      mode: 'extends',\n    },\n  },\n  eslint: {\n    mode: 'extends',\n  },\n  jest: {\n    babel: {\n      addPresets: true,\n      addPlugins: true,\n    },\n  },\n};\n\nconst moduleName = 'craco';\nconst explorer = cosmiconfigSync(moduleName, {\n  searchPlaces: [\n    'package.json',\n    `${moduleName}.config.ts`,\n    `${moduleName}.config.js`,\n    `${moduleName}.config.cjs`,\n    `.${moduleName}rc.ts`,\n    `.${moduleName}rc.js`,\n    `.${moduleName}rc`,\n  ],\n  loaders: {\n    '.ts': tsLoader(),\n  },\n});\n\nfunction ensureConfigSanity(cracoConfig: CracoConfig) {\n  if (cracoConfig.plugins && isArray(cracoConfig.plugins)) {\n    cracoConfig.plugins.forEach((x, index) => {\n      if (!x.plugin) {\n        throw new Error(\n          `craco: Malformed plugin at index: ${index} of 'plugins'.`\n        );\n      }\n    });\n  }\n}\n\nexport function processCracoConfig(\n  cracoConfig: CracoConfig,\n  context: BaseContext\n) {\n  const resultingCracoConfig = deepMergeWithArray(\n    {},\n    DEFAULT_CONFIG,\n    cracoConfig\n  );\n  ensureConfigSanity(resultingCracoConfig);\n\n  return applyCracoConfigPlugins(resultingCracoConfig, context);\n}\n\nfunction getConfigPath() {\n  const args = getArgs();\n\n  if (args.config && isString(args.config)) {\n    return path.resolve(projectRoot, args.config);\n  } else {\n    const packageJsonPath = path.join(projectRoot, 'package.json');\n\n    const packageJson = require(packageJsonPath);\n\n    if (packageJson.cracoConfig && isString(packageJson.cracoConfig)) {\n      // take it as the path to the config file if it's path-like, otherwise assume it contains the config content below\n      return path.resolve(projectRoot, packageJson.cracoConfig);\n    } else {\n      const result = explorer.search(projectRoot);\n\n      if (result === null) {\n        throw new Error(\n          'craco: Config file not found. check if file exists at root (craco.config.ts, craco.config.js, .cracorc.js, .cracorc.json, .cracorc.yaml, .cracorc)'\n        );\n      }\n\n      return result.filepath;\n    }\n  }\n}\n\nfunction getConfigAsObject(context: BaseContext) {\n  const configFilePath = getConfigPath();\n  log('Config file path resolved to: ', configFilePath);\n  const result = explorer.load(configFilePath);\n\n  const configAsObject = isFunction(result?.config)\n    ? result?.config(context)\n    : result?.config;\n\n  if (!configAsObject) {\n    throw new Error(\"craco: Config function didn't return a config object.\");\n  }\n  return configAsObject;\n}\n\nexport function loadCracoConfig(context: BaseContext) {\n  const configAsObject = getConfigAsObject(context);\n\n  if (configAsObject instanceof Promise) {\n    throw new Error(\n      'craco: Config function returned a promise. Use `loadCracoConfigAsync` instead of `loadCracoConfig`.'\n    );\n  }\n\n  return processCracoConfig(configAsObject, context);\n}\n\n// The \"build\", \"start\", and \"test\" scripts use this to wait for any promises to resolve before they run.\nexport async function loadCracoConfigAsync(context: BaseContext) {\n  const configAsObject = await getConfigAsObject(context);\n\n  if (!configAsObject) {\n    throw new Error(\"craco: Async config didn't return a config object.\");\n  }\n\n  return processCracoConfig(configAsObject, context);\n}\n"
  },
  {
    "path": "packages/craco/src/lib/cra.ts",
    "content": "import type {\n  CracoConfig,\n  CraPaths,\n  DevServerConfigProvider,\n  JestConfigProvider,\n} from '@craco/types';\nimport type { Configuration as WebpackConfig } from 'webpack';\n\nimport path from 'path';\nimport semver from 'semver';\nimport { log } from './logger';\nimport { projectRoot } from './paths';\n\nlet envLoaded = false;\nconst CRA_LATEST_SUPPORTED_MAJOR_VERSION = '5.0.0';\n\n/************  Common  ************/\n\nfunction resolveConfigFilePath(cracoConfig: CracoConfig, fileName: string) {\n  if (!envLoaded) {\n    // Environment variables must be loaded before the CRA paths, otherwise they will not be applied.\n    require(resolveConfigFilePathInner(cracoConfig, 'env.js'));\n\n    envLoaded = true;\n  }\n\n  return resolveConfigFilePathInner(cracoConfig, fileName);\n}\n\nfunction resolveConfigFilePathInner(\n  cracoConfig: CracoConfig,\n  fileName: string\n) {\n  return require.resolve(\n    path.join(\n      cracoConfig.reactScriptsVersion ?? 'react-scripts',\n      'config',\n      fileName\n    ),\n    { paths: [projectRoot] }\n  );\n}\n\nfunction resolveScriptsFilePath(cracoConfig: CracoConfig, fileName: string) {\n  return require.resolve(\n    path.join(\n      cracoConfig.reactScriptsVersion ?? 'react-scripts',\n      'scripts',\n      fileName\n    ),\n    { paths: [projectRoot] }\n  );\n}\n\nfunction resolveReactDevUtilsPath(fileName: string) {\n  return require.resolve(path.join('react-dev-utils', fileName), {\n    paths: [projectRoot],\n  });\n}\n\nfunction overrideModule(modulePath: string, newModule: any) {\n  if (!require.cache[modulePath]) {\n    throw new Error(`Module not found: ${modulePath}`);\n  }\n  require.cache[modulePath]!.exports = newModule;\n  log(`Overrode require cache for module: ${modulePath}`);\n}\n\nfunction resolvePackageJson(cracoConfig: CracoConfig) {\n  return require.resolve(\n    path.join(\n      cracoConfig.reactScriptsVersion ?? 'react-scripts',\n      'package.json'\n    ),\n    { paths: [projectRoot] }\n  );\n}\n\nexport function getReactScriptVersion(cracoConfig: CracoConfig) {\n  const reactScriptPackageJsonPath = resolvePackageJson(cracoConfig);\n  const { version } = require(reactScriptPackageJsonPath);\n\n  return {\n    version,\n    isSupported: semver.gte(version, CRA_LATEST_SUPPORTED_MAJOR_VERSION),\n  };\n}\n\n/************  Paths  ************/\n\nlet _resolvedCraPaths: any = null;\n\nexport function getCraPathsPath(cracoConfig: CracoConfig) {\n  return resolveConfigFilePath(cracoConfig, 'paths.js');\n}\n\nexport function getCraPaths(cracoConfig: CracoConfig) {\n  if (!_resolvedCraPaths) {\n    _resolvedCraPaths = require(getCraPathsPath(cracoConfig));\n  }\n\n  return _resolvedCraPaths;\n}\n\nexport function overrideCraPaths(\n  cracoConfig: CracoConfig,\n  newConfig?: CraPaths\n) {\n  overrideModule(getCraPathsPath(cracoConfig), newConfig);\n\n  log('Overrode CRA paths config.');\n}\n\n/************  Webpack Dev Config  ************/\n\nfunction getWebpackDevConfigPath(cracoConfig: CracoConfig) {\n  try {\n    return {\n      filepath: resolveConfigFilePath(cracoConfig, 'webpack.config.js'),\n      isLegacy: false,\n    };\n  } catch (e) {\n    return {\n      filepath: resolveConfigFilePath(cracoConfig, 'webpack.config.dev.js'),\n      isLegacy: true,\n    };\n  }\n}\n\nexport function loadWebpackDevConfig(cracoConfig: CracoConfig): WebpackConfig {\n  const result = getWebpackDevConfigPath(cracoConfig);\n\n  log('Found Webpack dev config at: ', result.filepath);\n\n  if (result.isLegacy) {\n    return require(result.filepath);\n  }\n\n  return require(result.filepath)('development');\n}\n\nexport function overrideWebpackDevConfig(\n  cracoConfig: CracoConfig,\n  newConfig: WebpackConfig\n) {\n  const result = getWebpackDevConfigPath(cracoConfig);\n\n  if (result.isLegacy) {\n    overrideModule(result.filepath, newConfig);\n  } else {\n    overrideModule(result.filepath, () => newConfig);\n  }\n\n  log('Overrode Webpack dev config.');\n}\n\n/************  Webpack Prod Config  ************/\n\nfunction getWebpackProdConfigPath(cracoConfig: CracoConfig) {\n  try {\n    return {\n      filepath: resolveConfigFilePath(cracoConfig, 'webpack.config.js'),\n      isLegacy: false,\n    };\n  } catch (e) {\n    return {\n      filepath: resolveConfigFilePath(cracoConfig, 'webpack.config.prod.js'),\n      isLegacy: true,\n    };\n  }\n}\n\nexport function loadWebpackProdConfig(cracoConfig: CracoConfig): WebpackConfig {\n  const result = getWebpackProdConfigPath(cracoConfig);\n\n  log('Found Webpack prod config at: ', result.filepath);\n\n  if (result.isLegacy) {\n    return require(result.filepath);\n  }\n\n  return require(result.filepath)('production');\n}\n\nexport function overrideWebpackProdConfig(\n  cracoConfig: CracoConfig,\n  newConfig: WebpackConfig\n) {\n  const result = getWebpackProdConfigPath(cracoConfig);\n\n  if (result.isLegacy) {\n    overrideModule(result.filepath, newConfig);\n  } else {\n    overrideModule(result.filepath, () => newConfig);\n  }\n\n  log('Overrode Webpack prod config.');\n}\n\n/************  Dev Server Config  ************/\n\nfunction getDevServerConfigPath(cracoConfig: CracoConfig) {\n  return resolveConfigFilePath(cracoConfig, 'webpackDevServer.config.js');\n}\n\nfunction getDevServerUtilsPath() {\n  return resolveReactDevUtilsPath('WebpackDevServerUtils.js');\n}\n\nexport function loadDevServerConfigProvider(\n  cracoConfig: CracoConfig\n): DevServerConfigProvider {\n  const filepath = getDevServerConfigPath(cracoConfig);\n\n  log('Found dev server config at: ', filepath);\n\n  return require(filepath);\n}\n\nexport function overrideDevServerConfigProvider(\n  cracoConfig: CracoConfig,\n  configProvider: any\n) {\n  const filepath = getDevServerConfigPath(cracoConfig);\n\n  overrideModule(filepath, configProvider);\n\n  log('Overrode dev server config provider.');\n}\n\nexport function loadDevServerUtils() {\n  const filepath = getDevServerUtilsPath();\n\n  log('Found dev server utils at: ', filepath);\n\n  return require(filepath);\n}\n\nexport function overrideDevServerUtils(newUtils: any) {\n  const filepath = getDevServerUtilsPath();\n\n  overrideModule(filepath, newUtils);\n\n  log('Overrode dev server utils.');\n}\n\n/************  Jest Config  ************/\n\nfunction getCreateJestConfigPath(cracoConfig: CracoConfig) {\n  return resolveScriptsFilePath(cracoConfig, 'utils/createJestConfig.js');\n}\n\n// https://github.com/facebook/create-react-app/blob/main/packages/react-scripts/scripts/utils/createJestConfig.js\n\nexport function loadJestConfigProvider(\n  cracoConfig: CracoConfig\n): JestConfigProvider {\n  const filepath = getCreateJestConfigPath(cracoConfig);\n\n  log('Found jest config at: ', filepath);\n\n  return require(filepath);\n}\n\nexport function overrideJestConfigProvider(\n  cracoConfig: CracoConfig,\n  configProvider: any\n) {\n  const filepath = getCreateJestConfigPath(cracoConfig);\n\n  overrideModule(filepath, configProvider);\n\n  log('Overrode Jest config provider.');\n}\n\n/************  Scripts  *******************/\n\nexport function start(cracoConfig: CracoConfig) {\n  const filepath = resolveScriptsFilePath(cracoConfig, 'start.js');\n\n  log('Starting CRA at: ', filepath);\n\n  require(filepath);\n}\n\nexport function build(cracoConfig: CracoConfig) {\n  const filepath = resolveScriptsFilePath(cracoConfig, 'build.js');\n\n  log('Building CRA at: ', filepath);\n\n  require(filepath);\n}\n\nexport function test(cracoConfig: CracoConfig) {\n  const filepath = resolveScriptsFilePath(cracoConfig, 'test.js');\n\n  log('Testing CRA at: ', filepath);\n\n  require(filepath);\n}\n"
  },
  {
    "path": "packages/craco/src/lib/features/dev-server/api.ts",
    "content": "import type { CracoConfig, DevServerContext } from '@craco/types';\nimport type { CliArgs } from '../../args';\n\nimport { setArgs } from '../../args';\nimport { processCracoConfig } from '../../config';\nimport { getCraPaths } from '../../cra';\nimport { isFunction } from '../../utils';\nimport { createConfigProviderProxy } from './create-config-provider-proxy';\n\nexport function createDevServerConfigProviderProxy(\n  callerCracoConfig: CracoConfig,\n  callerContext: DevServerContext,\n  options: CliArgs\n) {\n  if (!callerCracoConfig) {\n    throw new Error(\"craco: 'cracoConfig' is required.\");\n  }\n  if (isFunction(callerCracoConfig)) {\n    throw new Error(\"craco: 'cracoConfig' should be an object.\");\n  }\n\n  if (!process.env.NODE_ENV) {\n    process.env.NODE_ENV = 'development';\n  }\n\n  setArgs(options);\n\n  const context: DevServerContext = {\n    env: process.env.NODE_ENV,\n    ...callerContext,\n  };\n\n  const cracoConfig = processCracoConfig(callerCracoConfig, context);\n  context.paths = getCraPaths(cracoConfig);\n\n  const proxy = createConfigProviderProxy(cracoConfig, context);\n\n  return proxy;\n}\n"
  },
  {
    "path": "packages/craco/src/lib/features/dev-server/create-config-provider-proxy.ts",
    "content": "import type {\n  CracoConfig,\n  DevServerContext,\n  DevServerConfigProvider,\n} from '@craco/types';\nimport type { Configuration as DevServerConfig } from 'webpack-dev-server';\n\nimport merge from 'webpack-merge';\nimport { loadDevServerConfigProvider } from '../../cra';\nimport { log } from '../../logger';\nimport { isFunction } from '../../utils';\nimport { applyDevServerConfigPlugins } from '../plugins';\nimport { setEnvironmentVariables } from './set-environment-variables';\n\nfunction createProxy(\n  cracoConfig: CracoConfig,\n  craDevServerConfigProvider: DevServerConfigProvider,\n  context: DevServerContext\n) {\n  const proxy = (proxy: any, allowedHost: string) => {\n    let devServerConfig = craDevServerConfigProvider(proxy, allowedHost);\n\n    if (isFunction(cracoConfig.devServer)) {\n      devServerConfig = cracoConfig.devServer(devServerConfig, {\n        ...context,\n        proxy,\n        allowedHost,\n      });\n\n      if (!devServerConfig) {\n        throw new Error(\n          \"craco: 'devServer' function didn't return a config object.\"\n        );\n      }\n    } else {\n      // TODO: ensure is otherwise a plain object, if not, log an error.\n      devServerConfig = merge<DevServerConfig>(\n        devServerConfig,\n        cracoConfig.devServer || {}\n      );\n    }\n\n    devServerConfig = applyDevServerConfigPlugins(\n      cracoConfig,\n      devServerConfig,\n      {\n        ...context,\n        proxy,\n        allowedHost,\n      }\n    );\n\n    log('Merged DevServer config.');\n\n    return devServerConfig;\n  };\n\n  return proxy;\n}\n\nexport function createConfigProviderProxy(\n  cracoConfig: CracoConfig,\n  context: DevServerContext\n) {\n  const craDevServerConfigProvider = loadDevServerConfigProvider(cracoConfig);\n  const proxy = createProxy(cracoConfig, craDevServerConfigProvider, context);\n\n  return proxy;\n}\n"
  },
  {
    "path": "packages/craco/src/lib/features/dev-server/override-utils.ts",
    "content": "import type { CracoConfig } from '@craco/types';\n\nimport { loadDevServerUtils, overrideDevServerUtils } from '../../cra';\nimport { log } from '../../logger';\n\nfunction overrideWebpackCompilerToDisableTypeScriptTypeChecking(\n  craDevServersUtils: any\n) {\n  if (craDevServersUtils.createCompiler) {\n    const craCreateCompiler = craDevServersUtils.createCompiler;\n\n    craDevServersUtils.createCompiler = (args: any) => {\n      const newArgs = {\n        ...args,\n        useTypeScript: false,\n      };\n\n      return craCreateCompiler(newArgs);\n    };\n\n    log('Overrided Webpack compiler to disable TypeScript type checking.');\n  }\n\n  return craDevServersUtils;\n}\n\nfunction overrideUtils(cracoConfig: CracoConfig) {\n  if (cracoConfig.typescript) {\n    const { enableTypeChecking } = cracoConfig.typescript;\n\n    if (enableTypeChecking === false) {\n      const craDevServersUtils = loadDevServerUtils();\n      const resultingDevServersUtils =\n        overrideWebpackCompilerToDisableTypeScriptTypeChecking(\n          craDevServersUtils\n        );\n\n      overrideDevServerUtils(resultingDevServersUtils);\n    }\n  }\n}\n\nexport { overrideUtils as overrideDevServerUtils };\n"
  },
  {
    "path": "packages/craco/src/lib/features/dev-server/override.ts",
    "content": "import type { CracoConfig, DevServerContext } from '@craco/types';\n\nimport { overrideDevServerConfigProvider } from '../../cra';\nimport { isFunction } from '../../utils';\nimport { createConfigProviderProxy } from './create-config-provider-proxy';\nimport { overrideDevServerUtils } from './override-utils';\nimport { setEnvironmentVariables } from './set-environment-variables';\n\nexport function overrideDevServer(\n  cracoConfig: CracoConfig,\n  context: DevServerContext\n) {\n  overrideDevServerUtils(cracoConfig);\n\n  if (cracoConfig.devServer && !isFunction(cracoConfig.devServer)) {\n    setEnvironmentVariables(cracoConfig.devServer);\n  }\n\n  const proxy = createConfigProviderProxy(cracoConfig, context);\n  overrideDevServerConfigProvider(cracoConfig, proxy);\n}\n"
  },
  {
    "path": "packages/craco/src/lib/features/dev-server/set-environment-variables.ts",
    "content": "import type { Configuration as DevServerConfig } from 'webpack-dev-server';\n\nimport { isString } from '../../utils';\n\nfunction setEnvironmentVariable(envProperty: string, value: any) {\n  if (!isString(value)) {\n    process.env[envProperty] = value.toString();\n  } else {\n    process.env[envProperty] = value;\n  }\n}\n\nexport function setEnvironmentVariables(devServerConfig: DevServerConfig) {\n  const { open, https, host, port } = devServerConfig;\n\n  if (open === false) {\n    setEnvironmentVariable('BROWSER', 'none');\n  }\n\n  if (https) {\n    setEnvironmentVariable('HTTPS', 'true');\n  }\n\n  if (host) {\n    setEnvironmentVariable('HOST', host);\n  }\n\n  if (port) {\n    setEnvironmentVariable('PORT', port);\n  }\n}\n"
  },
  {
    "path": "packages/craco/src/lib/features/jest/api.ts",
    "content": "import type { CracoConfig, JestContext } from '@craco/types';\nimport type { Config as JestConfig } from '@jest/types';\nimport type { CliArgs } from '../../args';\n\nimport { setArgs } from '../../args';\nimport { processCracoConfig } from '../../config';\nimport { getCraPaths, loadJestConfigProvider } from '../../cra';\nimport { isFunction } from '../../utils';\nimport { mergeJestConfig } from './merge-jest-config';\n\nexport function createJestConfig(\n  callerCracoConfig: CracoConfig,\n  callerContext: JestContext = {},\n  options: CliArgs = {}\n): JestConfig.InitialOptions {\n  if (!callerCracoConfig) {\n    throw new Error(\"craco: 'cracoConfig' is required.\");\n  }\n  if (isFunction(callerCracoConfig)) {\n    throw new Error(\"craco: 'cracoConfig' should be an object.\");\n  }\n\n  if (!process.env.NODE_ENV) {\n    process.env.NODE_ENV = 'development';\n  }\n\n  setArgs(options);\n\n  const context: JestContext = {\n    env: process.env.NODE_ENV,\n    ...callerContext,\n  };\n\n  const cracoConfig = processCracoConfig(callerCracoConfig, context);\n  context.paths = getCraPaths(cracoConfig);\n\n  const craJestConfigProvider = loadJestConfigProvider(cracoConfig);\n\n  return mergeJestConfig(cracoConfig, craJestConfigProvider, context);\n}\n"
  },
  {
    "path": "packages/craco/src/lib/features/jest/create-jest-babel-transform.ts",
    "content": "import type { CracoConfig } from '@craco/types';\n\nimport babelJest from 'babel-jest';\nimport { loadCracoConfig } from '../../config';\nimport { isArray } from '../../utils';\n\n/**\n * To check if support jsx-runtime\n * Copy from https://github.com/facebook/create-react-app/blob/2b1161b34641bb4d2f269661cd636bbcd4888406/packages/react-scripts/config/jest/babelTransform.js#L12\n */\nconst hasJsxRuntime = (() => {\n  if (process.env.DISABLE_NEW_JSX_TRANSFORM === 'true') {\n    return false;\n  }\n\n  try {\n    require.resolve('react/jsx-runtime');\n    return true;\n  } catch (e) {\n    return false;\n  }\n})();\n\nexport function createJestBabelTransform(cracoConfig?: CracoConfig): any {\n  if (!cracoConfig) {\n    const context = { env: process.env.NODE_ENV };\n    cracoConfig = loadCracoConfig(context);\n  }\n\n  const craBabelTransformer: any = {\n    presets: [\n      [\n        'babel-preset-react-app',\n        {\n          runtime: hasJsxRuntime ? 'automatic' : 'classic',\n        },\n      ],\n    ],\n    babelrc: false,\n    configFile: false,\n  };\n\n  if (cracoConfig) {\n    const { addPresets, addPlugins } = cracoConfig.jest?.babel ?? {};\n\n    if (cracoConfig.babel) {\n      if (addPresets) {\n        const { presets } = cracoConfig.babel;\n\n        if (isArray(presets)) {\n          craBabelTransformer.presets =\n            craBabelTransformer.presets?.concat(presets);\n        }\n      }\n\n      if (addPlugins) {\n        const { plugins } = cracoConfig.babel;\n\n        if (isArray(plugins)) {\n          craBabelTransformer.plugins = plugins;\n        }\n      }\n    }\n  }\n\n  return babelJest.createTransformer\n    ? babelJest.createTransformer(craBabelTransformer)\n    : undefined;\n}\n"
  },
  {
    "path": "packages/craco/src/lib/features/jest/jest-babel-transform.ts",
    "content": "import type { TransformOptions as BTransformOptions } from '@babel/core';\nimport type {\n  SyncTransformer,\n  TransformOptions as JTransformOptions,\n} from '@jest/transform';\n\nimport { loadCracoConfigAsync } from '../../config';\nimport { createJestBabelTransform } from './create-jest-babel-transform';\n\nlet jestBabelTransform: SyncTransformer<BTransformOptions> | undefined;\n\n// cracoConfig is only available inside the transform, but the transform needs to include whatever options cracoConfig\n// specifies. So, the first time this transform is run, it generates a new transform -- using cracoConfig -- and\n// uses that to process files.\nmodule.exports = {\n  ...createJestBabelTransform(),\n  async processAsync(\n    src: string,\n    filename: string,\n    transformOptions: JTransformOptions<BTransformOptions>\n  ) {\n    if (!jestBabelTransform) {\n      const context = { env: process.env.NODE_ENV };\n      const cracoConfig = await loadCracoConfigAsync(context);\n      jestBabelTransform = createJestBabelTransform(cracoConfig);\n    }\n\n    return jestBabelTransform?.process(src, filename, transformOptions);\n  },\n};\n"
  },
  {
    "path": "packages/craco/src/lib/features/jest/merge-jest-config.ts",
    "content": "import type {\n  Configure,\n  CracoConfig,\n  JestConfigProvider,\n  JestContext,\n} from '@craco/types';\nimport type { Config as JestConfig } from '@jest/types';\n\nimport path from 'path';\nimport { log } from '../../logger';\nimport { projectRoot } from '../../paths';\nimport { deepMergeWithArray, isArray, isFunction } from '../../utils';\nimport { applyJestConfigPlugins } from '../plugins';\n\nconst BABEL_TRANSFORM_ENTRY_KEY = '^.+\\\\.(js|jsx|mjs|cjs|ts|tsx)$';\n\nfunction overrideBabelTransform(\n  jestConfig: JestConfig.InitialOptions,\n  cracoConfig: CracoConfig,\n  transformKey: string\n) {\n  // The cracoConfig needs to be available within the jest-babel-transform in order to honor its settings.\n  // This approach is based on https://github.com/facebook/jest/issues/1468#issuecomment-384825178\n  jestConfig.globals = jestConfig.globals || {};\n  jestConfig.globals._cracoConfig = cracoConfig;\n\n  if (!jestConfig.transform) {\n    jestConfig.transform = {};\n  }\n\n  jestConfig.transform[transformKey] = require.resolve(\n    './jest-babel-transform'\n  );\n  log('Overrided Jest Babel transformer.');\n}\n\nfunction configureBabel(\n  jestConfig: JestConfig.InitialOptions,\n  cracoConfig: CracoConfig\n) {\n  const { addPresets, addPlugins } = cracoConfig.jest?.babel ?? {};\n\n  if (addPresets || addPlugins) {\n    if (cracoConfig.babel) {\n      const { presets, plugins } = cracoConfig.babel;\n\n      if (isArray(presets) || isArray(plugins)) {\n        if (!jestConfig.transform) {\n          jestConfig.transform = {};\n        }\n        if (jestConfig.transform[BABEL_TRANSFORM_ENTRY_KEY]) {\n          overrideBabelTransform(\n            jestConfig,\n            cracoConfig,\n            BABEL_TRANSFORM_ENTRY_KEY\n          );\n        } else {\n          throw new Error(\n            `craco: Cannot find Jest transform entry for Babel ${BABEL_TRANSFORM_ENTRY_KEY}.`\n          );\n        }\n      }\n    }\n  }\n}\n\nfunction giveTotalControl(\n  jestConfig: JestConfig.InitialOptions,\n  configureJest: Configure<JestConfig.InitialOptions, JestContext>,\n  context: JestContext\n) {\n  if (isFunction(configureJest)) {\n    jestConfig = configureJest(jestConfig, context);\n\n    if (!jestConfig) {\n      throw new Error(\n        \"craco: 'jest.configure' function didn't returned a Jest config object.\"\n      );\n    }\n  } else {\n    // TODO: ensure is otherwise a plain object, if not, log an error.\n    jestConfig = deepMergeWithArray({}, jestConfig, configureJest);\n  }\n\n  log(\"Merged Jest config with 'jest.configure'.\");\n\n  return jestConfig;\n}\n\nexport function mergeJestConfig(\n  cracoConfig: CracoConfig,\n  craJestConfigProvider: JestConfigProvider,\n  context: JestContext\n): JestConfig.InitialOptions {\n  const customResolve = (relativePath: string) =>\n    require.resolve(\n      path.join(\n        cracoConfig.reactScriptsVersion ?? 'react-scripts',\n        relativePath\n      ),\n      { paths: [projectRoot] }\n    );\n\n  let jestConfig = craJestConfigProvider(customResolve, projectRoot, false);\n\n  if (cracoConfig.jest) {\n    configureBabel(jestConfig, cracoConfig);\n\n    const jestContext = {\n      ...context,\n      resolve: customResolve,\n      rootDir: projectRoot,\n    };\n\n    if (cracoConfig.jest.configure) {\n      jestConfig = giveTotalControl(\n        jestConfig,\n        cracoConfig.jest.configure,\n        jestContext\n      );\n    }\n\n    jestConfig = applyJestConfigPlugins(cracoConfig, jestConfig, jestContext);\n\n    log('Merged Jest config.');\n  }\n\n  return jestConfig;\n}\n"
  },
  {
    "path": "packages/craco/src/lib/features/jest/override.ts",
    "content": "import type { CracoConfig, JestContext } from '@craco/types';\n\nimport { loadJestConfigProvider, overrideJestConfigProvider } from '../../cra';\nimport { log } from '../../logger';\nimport { mergeJestConfig } from './merge-jest-config';\n\nexport function overrideJest(cracoConfig: CracoConfig, context: JestContext) {\n  if (cracoConfig.jest) {\n    const craJestConfigProvider = loadJestConfigProvider(cracoConfig);\n\n    const proxy = () => {\n      return mergeJestConfig(cracoConfig, craJestConfigProvider, context);\n    };\n\n    overrideJestConfigProvider(cracoConfig, proxy);\n\n    log('Overrided Jest config.');\n  }\n}\n"
  },
  {
    "path": "packages/craco/src/lib/features/paths/override.ts",
    "content": "import type { BaseContext, CracoConfig, CraPaths } from '@craco/types';\n\nimport { overrideCraPaths } from '../../cra';\nimport { isFunction } from '../../utils';\n\nexport function overridePaths(cracoConfig: CracoConfig, context: BaseContext) {\n  let newConfig: CraPaths | undefined = context.paths;\n  if (cracoConfig.paths) {\n    if (isFunction(cracoConfig.paths)) {\n      newConfig = cracoConfig.paths(newConfig, context);\n    } else {\n      newConfig = {\n        ...newConfig,\n        ...cracoConfig.paths,\n      };\n    }\n\n    overrideCraPaths(cracoConfig, newConfig);\n  }\n\n  return newConfig;\n}\n"
  },
  {
    "path": "packages/craco/src/lib/features/plugins.ts",
    "content": "import type {\n  BaseContext,\n  CracoConfig,\n  CracoPluginDefinition,\n  DevServerContext,\n  JestContext,\n  WebpackContext,\n} from '@craco/types';\nimport type { Config as JestConfig } from '@jest/types';\nimport type { Configuration as WebpackConfig } from 'webpack';\nimport type { Configuration as DevServerConfig } from 'webpack-dev-server';\n\nimport { log } from '../logger';\n\n/************  Craco Config  ************/\n\nfunction overrideCraco(\n  { plugin, options }: CracoPluginDefinition<any>,\n  cracoConfig: CracoConfig,\n  context: BaseContext\n) {\n  if (plugin.overrideCracoConfig) {\n    const resultingConfig = plugin.overrideCracoConfig({\n      cracoConfig: cracoConfig,\n      pluginOptions: options,\n      context: context,\n    });\n\n    if (!resultingConfig) {\n      throw new Error('craco: Plugin returned an undefined craco config.');\n    }\n\n    return resultingConfig;\n  }\n\n  log('Overrided craco config with plugin.');\n\n  return cracoConfig;\n}\n\nexport function applyCracoConfigPlugins(\n  cracoConfig: CracoConfig,\n  context: BaseContext\n) {\n  if (cracoConfig.plugins) {\n    cracoConfig.plugins.forEach((plugin) => {\n      cracoConfig = overrideCraco(plugin, cracoConfig, context);\n    });\n  }\n\n  log('Applied craco config plugins.');\n\n  return cracoConfig;\n}\n\n/************  Webpack Config  ************/\n\nfunction overrideWebpack(\n  { plugin, options }: CracoPluginDefinition<any>,\n  cracoConfig: CracoConfig,\n  webpackConfig: WebpackConfig,\n  context: WebpackContext\n) {\n  if (plugin.overrideWebpackConfig) {\n    const resultingConfig = plugin.overrideWebpackConfig({\n      cracoConfig: cracoConfig,\n      webpackConfig: webpackConfig,\n      pluginOptions: options,\n      context: context,\n    });\n\n    if (!resultingConfig) {\n      throw new Error('craco: Plugin returned an undefined webpack config.');\n    }\n\n    return resultingConfig;\n  }\n\n  log('Overrided webpack config with plugin.');\n\n  return webpackConfig;\n}\n\nexport function applyWebpackConfigPlugins(\n  cracoConfig: CracoConfig,\n  webpackConfig: WebpackConfig,\n  context: WebpackContext\n) {\n  if (cracoConfig.plugins) {\n    cracoConfig.plugins.forEach((plugin) => {\n      webpackConfig = overrideWebpack(\n        plugin,\n        cracoConfig,\n        webpackConfig,\n        context\n      );\n    });\n  }\n\n  log('Applied webpack config plugins.');\n\n  return webpackConfig;\n}\n\n/************  DevServer Config  ************/\n\nfunction overrideDevServer(\n  { plugin, options }: CracoPluginDefinition<any>,\n  cracoConfig: CracoConfig,\n  devServerConfig: DevServerConfig,\n  context: DevServerContext\n) {\n  if (plugin.overrideDevServerConfig) {\n    const resultingConfig = plugin.overrideDevServerConfig({\n      cracoConfig: cracoConfig,\n      devServerConfig: devServerConfig,\n      pluginOptions: options,\n      context: context,\n    });\n\n    if (!resultingConfig) {\n      throw new Error('craco: Plugin returned an undefined devServer config.');\n    }\n\n    return resultingConfig;\n  }\n\n  log('Overrided devServer config with plugin.');\n\n  return devServerConfig;\n}\n\nexport function applyDevServerConfigPlugins(\n  cracoConfig: CracoConfig,\n  devServerConfig: DevServerConfig,\n  context: DevServerContext\n) {\n  if (cracoConfig.plugins) {\n    cracoConfig.plugins.forEach((plugin) => {\n      devServerConfig = overrideDevServer(\n        plugin,\n        cracoConfig,\n        devServerConfig,\n        context\n      );\n    });\n  }\n\n  log('Applied devServer config plugins.');\n\n  return devServerConfig;\n}\n\n/************  Jest Config  *******************/\n\nfunction overrideJest(\n  { plugin, options }: CracoPluginDefinition<any>,\n  cracoConfig: CracoConfig,\n  jestConfig: JestConfig.InitialOptions,\n  context: JestContext\n) {\n  if (plugin.overrideJestConfig) {\n    const resultingConfig = plugin.overrideJestConfig({\n      cracoConfig: cracoConfig,\n      jestConfig: jestConfig,\n      pluginOptions: options,\n      context: context,\n    });\n\n    if (!resultingConfig) {\n      throw new Error('craco: Plugin returned an undefined Jest config.');\n    }\n\n    return resultingConfig;\n  }\n\n  log('Overrided Jest config with plugin.');\n\n  return jestConfig;\n}\n\nexport function applyJestConfigPlugins(\n  cracoConfig: CracoConfig,\n  jestConfig: JestConfig.InitialOptions,\n  context: JestContext\n) {\n  if (cracoConfig.plugins) {\n    cracoConfig.plugins.forEach((plugin) => {\n      jestConfig = overrideJest(plugin, cracoConfig, jestConfig, context);\n    });\n  }\n\n  log('Applied Jest config plugins.');\n\n  return jestConfig;\n}\n"
  },
  {
    "path": "packages/craco/src/lib/features/webpack/api.ts",
    "content": "import type { CracoConfig, WebpackContext } from '@craco/types';\nimport type { Configuration as WebpackConfig } from 'webpack';\nimport type { CliArgs } from '../../args';\n\nimport { setArgs } from '../../args';\nimport { processCracoConfig } from '../../config';\nimport {\n  getCraPaths,\n  loadWebpackDevConfig,\n  loadWebpackProdConfig,\n} from '../../cra';\nimport { isFunction } from '../../utils';\nimport { mergeWebpackConfig } from './merge-webpack-config';\n\nexport function createWebpackDevConfig(\n  callerCracoConfig: CracoConfig,\n  callerContext?: WebpackContext,\n  options?: CliArgs\n) {\n  return createWebpackConfig(\n    callerCracoConfig,\n    callerContext,\n    loadWebpackDevConfig,\n    'development',\n    options\n  );\n}\n\nexport function createWebpackProdConfig(\n  callerCracoConfig: CracoConfig,\n  callerContext?: WebpackContext,\n  options?: CliArgs\n) {\n  return createWebpackConfig(\n    callerCracoConfig,\n    callerContext,\n    loadWebpackProdConfig,\n    'production',\n    options\n  );\n}\n\nfunction createWebpackConfig(\n  callerCracoConfig: CracoConfig,\n  callerContext: WebpackContext = {},\n  loadWebpackConfig: (cracoConfig: CracoConfig) => WebpackConfig,\n  env: string,\n  options: CliArgs = {}\n) {\n  if (!callerCracoConfig) {\n    throw new Error(\"craco: 'cracoConfig' is required.\");\n  }\n  if (isFunction(callerCracoConfig)) {\n    throw new Error(\"craco: 'cracoConfig' should be an object.\");\n  }\n\n  if (!process.env.NODE_ENV) {\n    process.env.NODE_ENV = env;\n  }\n\n  setArgs(options);\n\n  const context: WebpackContext = {\n    env: process.env.NODE_ENV,\n    ...callerContext,\n  };\n\n  const cracoConfig = processCracoConfig(callerCracoConfig, context);\n  context.paths = getCraPaths(cracoConfig);\n\n  const craWebpackConfig = loadWebpackConfig(cracoConfig);\n  const resultingWebpackConfig = mergeWebpackConfig(\n    cracoConfig,\n    craWebpackConfig,\n    context\n  );\n\n  return resultingWebpackConfig;\n}\n"
  },
  {
    "path": "packages/craco/src/lib/features/webpack/babel.ts",
    "content": "import type {\n  BaseContext,\n  CompleteLoader,\n  Configure,\n  CracoConfig,\n} from '@craco/types';\nimport type { Configuration as WebpackConfig, RuleSetRule } from 'webpack';\n\nimport { TransformOptions } from '@babel/core';\nimport { getLoaders, loaderByName } from '../../loaders';\nimport { log, logError } from '../../logger';\nimport { deepMergeWithArray, isArray, isFunction, isString } from '../../utils';\n\n// TODO: CRA use a cacheIdentifier, should we update it with the new plugins?\n\nfunction addPresets(loader: RuleSetRule, babelPresets: any[]) {\n  if (isArray(babelPresets)) {\n    if (loader.options && !isString(loader.options)) {\n      if (loader.options.presets) {\n        loader.options.presets = loader.options.presets.concat(babelPresets);\n      } else {\n        loader.options.presets = babelPresets;\n      }\n    } else {\n      loader.options = {\n        presets: babelPresets,\n      };\n    }\n  }\n\n  log('Added Babel presets.');\n}\n\nfunction addPlugins(loader: RuleSetRule, babelPlugins: any[]) {\n  if (isArray(babelPlugins)) {\n    if (loader.options && !isString(loader.options)) {\n      if (loader.options.plugins) {\n        loader.options.plugins = loader.options.plugins.concat(babelPlugins);\n      } else {\n        loader.options.plugins = babelPlugins;\n      }\n    } else {\n      loader.options = {\n        plugins: babelPlugins,\n      };\n    }\n  }\n\n  log('Added Babel plugins.');\n}\n\nfunction addAssumptions(\n  loader: RuleSetRule,\n  babelAssumptions: { [assumption: string]: boolean }\n) {\n  if (loader.options && !isString(loader.options)) {\n    if (loader.options.assumptions) {\n      loader.options.assumptions = {\n        ...loader.options.assumptions,\n        ...babelAssumptions,\n      };\n    } else {\n      loader.options.assumptions = babelAssumptions;\n    }\n  } else {\n    loader.options = {\n      assumptions: babelAssumptions,\n    };\n  }\n\n  log('Added Babel assumptions.');\n}\n\nfunction applyLoaderOptions(\n  loader: RuleSetRule,\n  loaderOptions: Configure<TransformOptions, BaseContext>,\n  context: BaseContext\n) {\n  if (isFunction(loaderOptions)) {\n    loader.options = loaderOptions(\n      (loader.options as TransformOptions) || {},\n      context\n    );\n\n    if (!loader.options) {\n      throw new Error(\n        \"craco: 'babel.loaderOptions' function didn't return a loader config object.\"\n      );\n    }\n  } else {\n    // TODO: ensure is otherwise a plain object, if not, log an error.\n    loader.options = deepMergeWithArray(\n      {},\n      loader.options || {},\n      loaderOptions\n    );\n  }\n\n  log('Applied Babel loader options.');\n}\n\nfunction overrideLoader(\n  match: CompleteLoader,\n  cracoConfig: CracoConfig,\n  context: BaseContext\n) {\n  const { presets, plugins, assumptions, loaderOptions } =\n    cracoConfig.babel ?? {};\n\n  if (presets) {\n    addPresets(match.loader, presets);\n  }\n\n  if (plugins) {\n    addPlugins(match.loader, plugins);\n  }\n\n  if (assumptions) {\n    addAssumptions(match.loader, assumptions);\n  }\n\n  if (loaderOptions) {\n    applyLoaderOptions(match.loader, loaderOptions, context);\n  }\n}\n\nexport function overrideBabel(\n  cracoConfig: CracoConfig,\n  webpackConfig: WebpackConfig,\n  context: BaseContext\n) {\n  if (cracoConfig.babel) {\n    const { hasFoundAny, matches } = getLoaders(\n      webpackConfig,\n      loaderByName('babel-loader')\n    );\n\n    if (!hasFoundAny) {\n      logError('Cannot find any Babel loaders.');\n\n      return webpackConfig;\n    }\n\n    matches.forEach((x) => {\n      overrideLoader(x as CompleteLoader, cracoConfig, context);\n    });\n  }\n\n  return webpackConfig;\n}\n"
  },
  {
    "path": "packages/craco/src/lib/features/webpack/eslint.ts",
    "content": "import type {\n  BaseContext,\n  Configure,\n  CracoConfig,\n  CracoEsLintConfig,\n} from '@craco/types';\nimport type { PluginOptions } from 'eslint-webpack-plugin/types/options';\nimport type { Configuration as WebpackConfig } from 'webpack';\n\nimport { log, logError } from '../../logger';\nimport { deepMergeWithArray, isFunction } from '../../utils';\nimport { getPlugin, pluginByName, removePlugins } from '../../webpack-plugins';\n\nfunction disableEslint(webpackConfig: WebpackConfig) {\n  const { hasRemovedAny } = removePlugins(\n    webpackConfig,\n    pluginByName('ESLintWebpackPlugin')\n  );\n\n  if (hasRemovedAny) {\n    log('Disabled ESLint.');\n  } else {\n    logError(\"Couldn't disabled ESLint.\");\n  }\n}\n\nfunction extendsEslintConfig(\n  plugin: any,\n  eslintConfig: CracoEsLintConfig,\n  context: BaseContext\n) {\n  const { configure } = eslintConfig;\n\n  if (configure) {\n    if (isFunction(configure)) {\n      if (plugin.options) {\n        plugin.options.baseConfig = configure(\n          plugin.options.baseConfig || {},\n          context\n        );\n      } else {\n        plugin.options = {\n          baseConfig: configure({}, context),\n        };\n      }\n\n      if (!plugin.options.baseConfig) {\n        throw new Error(\n          \"craco: 'eslint.configure' function didn't return a config object.\"\n        );\n      }\n    } else {\n      // TODO: ensure is otherwise a plain object, if not, log an error.\n      if (plugin.options) {\n        plugin.options.baseConfig = deepMergeWithArray(\n          {},\n          plugin.options.baseConfig || {},\n          configure\n        );\n      } else {\n        plugin.options = {\n          baseConfig: configure,\n        };\n      }\n    }\n\n    log(\"Merged ESLint config with 'eslint.configure'.\");\n  }\n}\n\nfunction useEslintConfigFile(plugin: any) {\n  if (plugin.options) {\n    plugin.options.useEslintrc = true;\n    delete plugin.options.baseConfig;\n  } else {\n    plugin.options = {\n      useEslintrc: true,\n    };\n  }\n\n  log('Overrided ESLint config to use a config file.');\n}\n\nfunction enableEslintIgnoreFile(plugin: any) {\n  if (plugin.options) {\n    plugin.options.ignore = true;\n  } else {\n    plugin.options = {\n      ignore: true,\n    };\n  }\n\n  log('Overrided ESLint config to enable an ignore file.');\n}\n\nfunction applyPluginOptions(\n  plugin: any,\n  pluginOptions: Configure<PluginOptions, BaseContext>,\n  context: BaseContext\n) {\n  if (isFunction(pluginOptions)) {\n    plugin.options = pluginOptions(plugin.options || {}, context);\n\n    if (!plugin.options) {\n      throw new Error(\n        \"craco: 'eslint.pluginOptions' function didn't return a config object.\"\n      );\n    }\n  } else {\n    // TODO: ensure is otherwise a plain object, if not, log an error.\n    plugin.options = deepMergeWithArray(plugin.options || {}, pluginOptions);\n  }\n\n  log('Applied ESLint plugin options.');\n}\n\nexport function overrideEsLint(\n  cracoConfig: CracoConfig,\n  webpackConfig: WebpackConfig,\n  context: BaseContext\n) {\n  if (cracoConfig.eslint) {\n    const { isFound, match } = getPlugin(\n      webpackConfig,\n      pluginByName('ESLintWebpackPlugin')\n    );\n    if (!isFound) {\n      logError('Cannot find ESLint plugin (ESLintWebpackPlugin).');\n      return webpackConfig;\n    }\n\n    const { enable, mode, pluginOptions } = cracoConfig.eslint;\n\n    if (enable === false) {\n      disableEslint(webpackConfig);\n\n      return webpackConfig;\n    }\n\n    enableEslintIgnoreFile(match);\n\n    if (mode === 'file') {\n      useEslintConfigFile(match);\n    } else {\n      extendsEslintConfig(match, cracoConfig.eslint, context);\n    }\n\n    if (pluginOptions) {\n      applyPluginOptions(match, pluginOptions, context);\n    }\n  }\n\n  return webpackConfig;\n}\n"
  },
  {
    "path": "packages/craco/src/lib/features/webpack/merge-webpack-config.ts",
    "content": "import type {\n  AddWebpackPlugins,\n  Configure,\n  CracoConfig,\n  WebpackAlias,\n  WebpackContext,\n} from '@craco/types';\nimport type { Configuration as WebpackConfig } from 'webpack';\n\nimport merge from 'webpack-merge';\nimport { log } from '../../logger';\nimport { isArray, isFunction } from '../../utils';\nimport {\n  addPlugins as addWebpackPlugins,\n  pluginByName,\n  removePlugins as removeWebpackPlugins,\n} from '../../webpack-plugins';\nimport { applyWebpackConfigPlugins } from '../plugins';\nimport { overrideBabel } from './babel';\nimport { overrideEsLint } from './eslint';\nimport { overrideStyle } from './style/style';\nimport { overrideTypeScript } from './typescript';\n\nfunction addAlias(webpackConfig: WebpackConfig, webpackAlias: WebpackAlias) {\n  if (webpackConfig.resolve) {\n    // TODO: ensure is a plain object, if not, log an error.\n    webpackConfig.resolve.alias = Object.assign(\n      webpackConfig.resolve.alias || {},\n      webpackAlias\n    );\n  }\n\n  log('Added webpack alias.');\n}\n\nfunction addPlugins(\n  webpackConfig: WebpackConfig,\n  webpackPlugins: AddWebpackPlugins\n) {\n  if (isArray(webpackPlugins)) {\n    addWebpackPlugins(webpackConfig, webpackPlugins);\n\n    log('Added webpack plugins.');\n  } else {\n    throw new Error(\n      `craco: 'webpack.plugins.add' needs to be a an array of plugins`\n    );\n  }\n}\n\nfunction removePluginsFromWebpackConfig(\n  webpackConfig: WebpackConfig,\n  remove: string[] | undefined\n) {\n  if (!remove) {\n    return;\n  }\n\n  if (isArray(remove)) {\n    for (const pluginName of remove) {\n      const { hasRemovedAny } = removeWebpackPlugins(\n        webpackConfig,\n        pluginByName(pluginName)\n      );\n\n      if (hasRemovedAny) {\n        log(`Removed webpack plugin ${pluginName}.`);\n      } else {\n        log(`Did not remove webpack plugin ${pluginName}.`);\n      }\n    }\n\n    log('Removed webpack plugins.');\n  } else {\n    throw new Error(\n      `craco: 'webpack.plugins.remove' needs to be a an array of plugin names`\n    );\n  }\n}\n\nfunction giveTotalControl(\n  webpackConfig: WebpackConfig,\n  configureWebpack: Configure<WebpackConfig, WebpackContext>,\n  context: WebpackContext\n) {\n  if (isFunction(configureWebpack)) {\n    webpackConfig = configureWebpack(webpackConfig, context);\n\n    if (!webpackConfig) {\n      throw new Error(\n        \"craco: 'webpack.configure' function didn't returned a webpack config object.\"\n      );\n    }\n  } else {\n    // TODO: ensure is otherwise a plain object, if not, log an error.\n    webpackConfig = merge(webpackConfig, configureWebpack);\n  }\n\n  log(\"Merged webpack config with 'webpack.configure'.\");\n\n  return webpackConfig;\n}\n\nexport function mergeWebpackConfig(\n  cracoConfig: CracoConfig,\n  webpackConfig: WebpackConfig,\n  context: WebpackContext\n) {\n  let resultingWebpackConfig = webpackConfig;\n\n  resultingWebpackConfig = overrideBabel(\n    cracoConfig,\n    resultingWebpackConfig,\n    context\n  );\n  resultingWebpackConfig = overrideEsLint(\n    cracoConfig,\n    resultingWebpackConfig,\n    context\n  );\n  resultingWebpackConfig = overrideStyle(\n    cracoConfig,\n    resultingWebpackConfig,\n    context\n  );\n  resultingWebpackConfig = overrideTypeScript(\n    cracoConfig,\n    resultingWebpackConfig\n  );\n\n  if (cracoConfig.webpack) {\n    const { alias, plugins, configure } = cracoConfig.webpack;\n\n    if (alias) {\n      addAlias(resultingWebpackConfig, alias);\n    }\n\n    if (plugins) {\n      // we still support the old format of plugin: [] where the array is a list of the plugins to add\n      if (isArray(plugins)) {\n        addPlugins(resultingWebpackConfig, plugins);\n      } else {\n        const { add, remove } = plugins;\n\n        if (remove) {\n          removePluginsFromWebpackConfig(resultingWebpackConfig, remove);\n        }\n\n        // Add after removing to preserve any plugins explicitly added via the Craco config\n        if (add) {\n          addPlugins(resultingWebpackConfig, add);\n        }\n      }\n    }\n\n    if (configure) {\n      resultingWebpackConfig = giveTotalControl(\n        resultingWebpackConfig,\n        configure,\n        context\n      );\n    }\n  }\n\n  resultingWebpackConfig = applyWebpackConfigPlugins(\n    cracoConfig,\n    resultingWebpackConfig,\n    context\n  );\n\n  return resultingWebpackConfig;\n}\n"
  },
  {
    "path": "packages/craco/src/lib/features/webpack/override.ts",
    "content": "import type { CracoConfig, WebpackContext } from '@craco/types';\n\nimport {\n  loadWebpackDevConfig,\n  loadWebpackProdConfig,\n  overrideWebpackDevConfig,\n  overrideWebpackProdConfig,\n} from '../../cra';\nimport { mergeWebpackConfig } from './merge-webpack-config';\n\nexport function overrideWebpackDev(\n  cracoConfig: CracoConfig,\n  context: WebpackContext\n) {\n  const craWebpackConfig = loadWebpackDevConfig(cracoConfig);\n  const resultingWebpackConfig = mergeWebpackConfig(\n    cracoConfig,\n    craWebpackConfig,\n    context\n  );\n\n  overrideWebpackDevConfig(cracoConfig, resultingWebpackConfig);\n}\n\nexport function overrideWebpackProd(\n  cracoConfig: CracoConfig,\n  context: WebpackContext\n) {\n  const craWebpackConfig = loadWebpackProdConfig(cracoConfig);\n  const resultingWebpackConfig = mergeWebpackConfig(\n    cracoConfig,\n    craWebpackConfig,\n    context\n  );\n\n  overrideWebpackProdConfig(cracoConfig, resultingWebpackConfig);\n}\n"
  },
  {
    "path": "packages/craco/src/lib/features/webpack/style/css.ts",
    "content": "import type {\n  BaseContext,\n  CompleteLoader,\n  Configure,\n  CracoStyleConfig,\n} from '@craco/types';\nimport type { Configuration as WebpackConfig, RuleSetRule } from 'webpack';\n\nimport { getLoaders, loaderByName } from '../../../loaders';\nimport { log, logError } from '../../../logger';\nimport {\n  deepMergeWithArray,\n  isBoolean,\n  isFunction,\n  isString,\n} from '../../../utils';\n\ninterface CompleteLoaderModule {\n  loader: {\n    options: {\n      [key: string]: any;\n    };\n  };\n}\n\nfunction setModuleLocalIdentName(\n  match: CompleteLoaderModule,\n  localIdentName: string\n) {\n  // The css-loader version of create-react-app has changed from 2.1.1 to 3.2.0\n  // https://github.com/facebook/create-react-app/commit/f79f30\n  if (isBoolean(match.loader.options.modules)) {\n    delete match.loader?.options?.getLocalIdent;\n    match.loader.options.localIdentName = localIdentName;\n  } else {\n    // This setting applies to create-react-app@3.3.0\n    delete match.loader.options.modules.getLocalIdent;\n    match.loader.options.modules.localIdentName = localIdentName;\n  }\n\n  log('Overrided CSS modules local ident name.');\n}\n\nfunction applyLoaderOptions(\n  match: CompleteLoader,\n  loaderOptions: Configure<any, BaseContext>,\n  context: BaseContext\n) {\n  if (isFunction(loaderOptions)) {\n    match.loader.options = loaderOptions(\n      (match.loader as RuleSetRule).options || {},\n      context\n    );\n\n    if (!match.loader.options) {\n      throw new Error(\n        \"craco: 'style.css.loaderOptions' function didn't return a loader config object.\"\n      );\n    }\n  } else {\n    // TODO: ensure is otherwise a plain object, if not, log an error.\n    match.loader.options = deepMergeWithArray(\n      {},\n      match.loader.options || {},\n      loaderOptions\n    );\n  }\n\n  log('Applied CSS loaders options.');\n}\n\nfunction overrideCssLoader(\n  match: CompleteLoader,\n  { css: cssOptions }: CracoStyleConfig,\n  context: BaseContext\n) {\n  if (cssOptions?.loaderOptions) {\n    applyLoaderOptions(match, cssOptions.loaderOptions, context);\n\n    log('Overrided CSS loader.');\n  }\n}\n\nfunction overrideModuleLoader(\n  match: CompleteLoader,\n  modulesOptions: { [key: string]: any } | undefined\n) {\n  if (modulesOptions?.localIdentName) {\n    setModuleLocalIdentName(\n      match as CompleteLoaderModule,\n      modulesOptions.localIdentName\n    );\n\n    log('Overrided CSS module loader.');\n  }\n}\n\nexport function overrideCss(\n  styleConfig: CracoStyleConfig,\n  webpackConfig: WebpackConfig,\n  context: BaseContext\n) {\n  if (styleConfig.modules || styleConfig.css) {\n    const { hasFoundAny, matches } = getLoaders(\n      webpackConfig,\n      loaderByName('css-loader')\n    );\n\n    if (!hasFoundAny) {\n      logError('Cannot find any CSS loaders.');\n      return webpackConfig;\n    }\n\n    if (styleConfig.modules) {\n      const cssModuleLoaders = matches.filter(\n        (x) =>\n          !isString(x.loader) &&\n          x.loader?.options &&\n          !isString(x.loader?.options) &&\n          x.loader.options.modules\n      );\n\n      cssModuleLoaders.forEach((x) => {\n        overrideModuleLoader(x as CompleteLoader, styleConfig.modules);\n      });\n    }\n\n    if (styleConfig.css) {\n      matches.forEach((x) => {\n        overrideCssLoader(x as CompleteLoader, styleConfig, context);\n      });\n    }\n  }\n\n  return webpackConfig;\n}\n"
  },
  {
    "path": "packages/craco/src/lib/features/webpack/style/postcss.ts",
    "content": "import type {\n  BaseContext,\n  CompleteLoader,\n  Configure,\n  CracoStyleConfig,\n  Loader,\n} from '@craco/types';\nimport type { Configuration as WebpackConfig } from 'webpack';\n\nimport { isString } from 'lodash';\nimport { getLoaders, loaderByName } from '../../../loaders';\nimport { log, logError } from '../../../logger';\nimport { projectRoot } from '../../../paths';\nimport { deepMergeWithArray, isArray, isFunction } from '../../../utils';\n\nconst CRA_PLUGINS = (presetEnv: any) => {\n  return [\n    require('postcss-flexbugs-fixes'),\n    require('postcss-preset-env')(presetEnv),\n    require(require.resolve('postcss-normalize', { paths: [projectRoot] })),\n  ];\n};\n\nconst CRA_PRESET_ENV = {\n  autoprefixer: {\n    flexbox: 'no-2009',\n  },\n  stage: 3,\n};\n\nfunction usePostcssConfigFile(match: Loader) {\n  if (\n    !isString(match.loader?.options) &&\n    match.loader?.options?.postcssOptions\n  ) {\n    const ident = match.loader.options.postcssOptions.ident;\n    const sourceMap = match.loader.options.postcssOptions.sourceMap;\n\n    match.loader.options.postcssOptions = {\n      ident: ident,\n      sourceMap: sourceMap,\n    };\n\n    log('Overwrited PostCSS config to use a config file.');\n  }\n}\n\nfunction extendsPostcss(\n  match: CompleteLoader,\n  { postcss: postcssOptions }: CracoStyleConfig\n) {\n  const { plugins, env } = postcssOptions ?? {};\n  if (isArray(plugins) || env) {\n    let postcssPlugins: any[];\n\n    if (env) {\n      const mergedPreset = deepMergeWithArray({}, CRA_PRESET_ENV, env);\n      postcssPlugins = CRA_PLUGINS(mergedPreset);\n\n      log('Merged PostCSS env preset.');\n    } else {\n      let craPlugins: any[] = [];\n\n      if (!isString(match.loader.options)) {\n        const options = match.loader.options?.postcssOptions;\n        if (isFunction(options)) {\n          craPlugins = options().plugins;\n        } else {\n          craPlugins = options?.plugins;\n        }\n      }\n\n      postcssPlugins = craPlugins || [];\n    }\n\n    if (plugins) {\n      postcssPlugins = isFunction(plugins)\n        ? plugins(postcssPlugins)\n        : postcssPlugins.concat(plugins);\n\n      log('Added PostCSS plugins.');\n    }\n\n    if (match.loader.options && !isString(match.loader.options)) {\n      if (match.loader.options.postcssOptions) {\n        match.loader.options.postcssOptions.plugins = postcssPlugins;\n      } else {\n        match.loader.options.postcssOptions = {\n          plugins: postcssPlugins,\n        };\n      }\n    }\n  }\n}\n\nfunction applyLoaderOptions(\n  match: CompleteLoader,\n  loaderOptions: Configure<any, BaseContext>,\n  context: BaseContext\n) {\n  if (isFunction(loaderOptions)) {\n    match.loader.options = loaderOptions(match.loader.options || {}, context);\n\n    if (!match.loader.options) {\n      throw new Error(\n        \"craco: 'style.postcss.loaderOptions' function didn't return a loader config object.\"\n      );\n    }\n  } else {\n    // TODO: ensure is otherwise a plain object, if not, log an error.\n    match.loader.options = deepMergeWithArray(\n      {},\n      match.loader.options || {},\n      loaderOptions\n    );\n  }\n\n  log('Applied PostCSS loaders options.');\n}\n\nfunction overrideLoader(\n  match: CompleteLoader,\n  styleConfig: CracoStyleConfig,\n  context: BaseContext\n) {\n  const { mode, loaderOptions } = styleConfig.postcss ?? {};\n\n  if (mode === 'file') {\n    usePostcssConfigFile(match);\n  } else {\n    extendsPostcss(match, styleConfig);\n  }\n\n  if (loaderOptions) {\n    applyLoaderOptions(match, loaderOptions, context);\n  }\n\n  log('Overrided PostCSS loader.');\n}\n\nexport function overridePostcss(\n  styleConfig: CracoStyleConfig,\n  webpackConfig: WebpackConfig,\n  context: BaseContext\n) {\n  if (styleConfig.postcss) {\n    const { hasFoundAny, matches } = getLoaders(\n      webpackConfig,\n      loaderByName('postcss-loader')\n    );\n\n    if (!hasFoundAny) {\n      logError('Cannot find any PostCSS loaders.');\n\n      return webpackConfig;\n    }\n\n    matches.forEach((x) => {\n      overrideLoader(x as CompleteLoader, styleConfig, context);\n    });\n  }\n\n  return webpackConfig;\n}\n"
  },
  {
    "path": "packages/craco/src/lib/features/webpack/style/sass.ts",
    "content": "import type {\n  BaseContext,\n  CompleteLoader,\n  Configure,\n  CracoStyleConfig,\n} from '@craco/types';\nimport type { Configuration as WebpackConfig } from 'webpack';\n\nimport { getLoaders, loaderByName } from '../../../loaders';\nimport { log, logError } from '../../../logger';\nimport { deepMergeWithArray, isFunction, isString } from '../../../utils';\n\nfunction setLoaderProperty(\n  match: CompleteLoader,\n  key: string,\n  valueProviders: {\n    whenString: () => any;\n    whenObject: () => any;\n  }\n) {\n  if (isString(match.loader)) {\n    (match.parent as any)[match.index] = {\n      loader: match.loader,\n      [key]: valueProviders.whenString(),\n    };\n  } else {\n    (match.loader as any)[key] = valueProviders.whenObject();\n  }\n}\n\nfunction applyLoaderOptions(\n  match: CompleteLoader,\n  loaderOptions: Configure<any, BaseContext>,\n  context: BaseContext\n) {\n  if (isFunction(loaderOptions)) {\n    setLoaderProperty(match, 'options', {\n      whenString: () => loaderOptions({}, context),\n      whenObject: () => loaderOptions(match.loader.options || {}, context),\n    });\n\n    if (!match.loader.options) {\n      throw new Error(\n        \"craco: 'style.sass.loaderOptions' function didn't return a loader config object.\"\n      );\n    }\n  } else {\n    // TODO: ensure is otherwise a plain object, if not, log an error.\n    setLoaderProperty(match, 'options', {\n      whenString: () => loaderOptions,\n      whenObject: () =>\n        deepMergeWithArray({}, match.loader.options || {}, loaderOptions),\n    });\n  }\n\n  log('Applied Sass loaders options.');\n}\n\nfunction overrideLoader(\n  match: CompleteLoader,\n  { sass: sassOptions }: CracoStyleConfig,\n  context: BaseContext\n) {\n  const { loaderOptions } = sassOptions ?? {};\n\n  if (loaderOptions) {\n    applyLoaderOptions(match, loaderOptions, context);\n\n    log('Overrided Sass loader.');\n  }\n}\n\nexport function overrideSass(\n  styleConfig: CracoStyleConfig,\n  webpackConfig: WebpackConfig,\n  context: BaseContext\n) {\n  if (styleConfig.sass) {\n    const { hasFoundAny, matches } = getLoaders(\n      webpackConfig,\n      loaderByName('sass-loader')\n    );\n\n    if (!hasFoundAny) {\n      logError('Cannot find any Sass loaders.');\n\n      return webpackConfig;\n    }\n\n    matches.forEach((x) => {\n      overrideLoader(x as CompleteLoader, styleConfig, context);\n    });\n  }\n\n  return webpackConfig;\n}\n"
  },
  {
    "path": "packages/craco/src/lib/features/webpack/style/style.ts",
    "content": "import type { BaseContext, CracoConfig } from '@craco/types';\nimport type { Configuration as WebpackConfig } from 'webpack';\n\nimport { overrideCss } from './css';\nimport { overridePostcss } from './postcss';\nimport { overrideSass } from './sass';\n\nexport function overrideStyle(\n  cracoConfig: CracoConfig,\n  webpackConfig: WebpackConfig,\n  context: BaseContext\n) {\n  if (cracoConfig.style) {\n    webpackConfig = overrideCss(cracoConfig.style, webpackConfig, context);\n    webpackConfig = overrideSass(cracoConfig.style, webpackConfig, context);\n    webpackConfig = overridePostcss(cracoConfig.style, webpackConfig, context);\n  }\n\n  return webpackConfig;\n}\n"
  },
  {
    "path": "packages/craco/src/lib/features/webpack/typescript.ts",
    "content": "import type { CracoConfig } from '@craco/types';\nimport type { Configuration as WebpackConfig } from 'webpack';\n\nimport { log } from '../../logger';\n\nfunction disableTypeChecking(webpackConfig: WebpackConfig) {\n  webpackConfig.plugins = webpackConfig.plugins?.filter(\n    (plugin) => plugin.constructor.name !== 'ForkTsCheckerWebpackPlugin'\n  );\n\n  log('Disabled TypeScript type checking.');\n\n  return webpackConfig;\n}\n\nexport function overrideTypeScript(\n  cracoConfig: CracoConfig,\n  webpackConfig: WebpackConfig\n) {\n  if (cracoConfig.typescript) {\n    const { enableTypeChecking } = cracoConfig.typescript;\n\n    if (enableTypeChecking === false) {\n      disableTypeChecking(webpackConfig);\n    }\n  }\n\n  return webpackConfig;\n}\n"
  },
  {
    "path": "packages/craco/src/lib/loaders.ts",
    "content": "import type { Loader, LoaderMatcher } from '@craco/types';\nimport type {\n  Configuration as WebpackConfig,\n  RuleSetRule,\n  RuleSetUseItem,\n} from 'webpack';\n\nimport path from 'path';\nimport { isArray, isString } from './utils';\n\ntype Ul<T> = T[] | undefined;\n\nexport function loaderByName(targetLoaderName: string) {\n  return (rule: RuleSetRule | RuleSetUseItem) => {\n    if (!isString(rule) && 'loader' in rule && isString(rule.loader)) {\n      return (\n        rule.loader.indexOf(`${path.sep}${targetLoaderName}${path.sep}`) !==\n          -1 || rule.loader.indexOf(`@${targetLoaderName}${path.sep}`) !== -1\n      );\n    } else if (isString(rule)) {\n      return (\n        rule.indexOf(`${path.sep}${targetLoaderName}${path.sep}`) !== -1 ||\n        rule.indexOf(`@${targetLoaderName}${path.sep}`) !== -1\n      );\n    }\n\n    return false;\n  };\n}\n\nconst toMatchingLoader = (\n  loader: RuleSetRule,\n  parent: Ul<RuleSetRule>,\n  index: number\n): Loader => ({ loader, parent, index });\n\nfunction getLoaderRecursively(rules: Ul<RuleSetRule>, matcher: LoaderMatcher) {\n  let loader: Loader | undefined;\n\n  rules?.some((rule, index) => {\n    if (rule) {\n      if (matcher(rule)) {\n        loader = toMatchingLoader(rule, rules, index);\n      } else if (!isString(rule)) {\n        if (rule.use) {\n          if (isString(rule.use) && matcher(rule.use)) {\n            loader = toMatchingLoader({ loader: rule.use }, rules, index);\n          } else {\n            loader = getLoaderRecursively(rule.use as RuleSetRule[], matcher);\n          }\n        } else if (rule.oneOf) {\n          loader = getLoaderRecursively(rule.oneOf, matcher);\n        } else if (isArray(rule.loader)) {\n          loader = getLoaderRecursively(rule.loader, matcher);\n        }\n      }\n    }\n\n    return loader !== undefined;\n  });\n\n  return loader;\n}\n\nexport function getLoader(\n  webpackConfig: WebpackConfig,\n  matcher: LoaderMatcher\n) {\n  const matchingLoader = getLoaderRecursively(\n    webpackConfig.module?.rules as RuleSetRule[],\n    matcher\n  );\n\n  return { isFound: matchingLoader !== undefined, match: matchingLoader };\n}\n\nfunction getLoadersRecursively(\n  rules: Ul<RuleSetRule>,\n  matcher: LoaderMatcher,\n  matchingLoaders: Loader[]\n) {\n  rules?.forEach((rule, index) => {\n    if (rule) {\n      if (matcher(rule)) {\n        matchingLoaders.push(toMatchingLoader(rule, rules, index));\n      } else if (!isString(rule)) {\n        if (rule.use) {\n          if (isString(rule.use) && matcher(rule.use)) {\n            matchingLoaders.push(\n              toMatchingLoader({ loader: rule.use }, rules, index)\n            );\n          } else {\n            getLoadersRecursively(\n              rule.use as RuleSetRule[],\n              matcher,\n              matchingLoaders\n            );\n          }\n        } else if (rule.oneOf) {\n          getLoadersRecursively(rule.oneOf, matcher, matchingLoaders);\n        } else if (isArray(rule.loader)) {\n          getLoadersRecursively(rule.loader, matcher, matchingLoaders);\n        }\n      }\n    }\n  });\n}\n\nexport function getLoaders(\n  webpackConfig: WebpackConfig,\n  matcher: LoaderMatcher\n) {\n  const matchingLoaders: Loader[] = [];\n\n  getLoadersRecursively(\n    webpackConfig.module?.rules as Ul<RuleSetRule>,\n    matcher,\n    matchingLoaders\n  );\n\n  return {\n    hasFoundAny: matchingLoaders.length !== 0,\n    matches: matchingLoaders,\n  };\n}\n\nfunction removeLoadersRecursively(\n  rules: Ul<RuleSetRule>,\n  matcher: LoaderMatcher\n): {\n  rules: Ul<RuleSetRule>;\n  removedCount: number;\n} {\n  const toRemove = [];\n  let removedCount = 0;\n\n  if (!rules) {\n    return { rules, removedCount: 0 };\n  }\n\n  for (let i = 0, max = rules.length; i < max; i += 1) {\n    const rule = rules[i];\n\n    if (rule) {\n      if (matcher(rule)) {\n        toRemove.push(i);\n      } else if (!isString(rule)) {\n        if (rule.use) {\n          let result;\n          if (isString(rule.use) && matcher(rule.use)) {\n            toRemove.push(i);\n            removedCount++;\n            rule.use = undefined;\n          } else {\n            result = removeLoadersRecursively(\n              rule.use as RuleSetRule[],\n              matcher\n            );\n            removedCount += result.removedCount;\n            (rule.use as Ul<RuleSetRule>) = result.rules;\n          }\n        } else if (rule.oneOf) {\n          const result = removeLoadersRecursively(rule.oneOf, matcher);\n\n          removedCount += result.removedCount;\n          (rule.oneOf as Ul<RuleSetRule>) = result.rules;\n        }\n      }\n    }\n  }\n\n  toRemove.forEach((ruleIndex, i) => {\n    rules.splice(ruleIndex - i, 1);\n  });\n\n  return { rules, removedCount: removedCount + toRemove.length };\n}\n\nexport function removeLoaders(\n  webpackConfig: WebpackConfig,\n  matcher: LoaderMatcher\n) {\n  const result = removeLoadersRecursively(\n    webpackConfig.module?.rules as Ul<RuleSetRule>,\n    matcher\n  );\n\n  return {\n    hasRemovedAny: result.removedCount > 0,\n    removedCount: result.removedCount,\n  };\n}\n\nfunction addLoader(\n  webpackConfig: WebpackConfig,\n  matcher: LoaderMatcher,\n  newLoader: RuleSetRule,\n  positionAdapter: (index: number) => number\n) {\n  const { isFound, match } = getLoader(webpackConfig, matcher);\n\n  if (isFound) {\n    match!.parent?.splice(positionAdapter(match!.index), 0, newLoader);\n\n    return { isAdded: true };\n  }\n\n  return { isAdded: false };\n}\n\nexport const addBeforeLoader = (\n  webpackConfig: WebpackConfig,\n  matcher: LoaderMatcher,\n  newLoader: RuleSetRule\n) => addLoader(webpackConfig, matcher, newLoader, (x) => x);\n\nexport const addAfterLoader = (\n  webpackConfig: WebpackConfig,\n  matcher: LoaderMatcher,\n  newLoader: RuleSetRule\n) => addLoader(webpackConfig, matcher, newLoader, (x) => x + 1);\n\nfunction addLoaders(\n  webpackConfig: WebpackConfig,\n  matcher: LoaderMatcher,\n  newLoader: RuleSetRule,\n  positionAdapter: (index: number) => number\n) {\n  const { hasFoundAny, matches } = getLoaders(webpackConfig, matcher);\n\n  if (hasFoundAny) {\n    matches.forEach((match) => {\n      match!.parent?.splice(positionAdapter(match.index), 0, newLoader);\n    });\n\n    return { isAdded: true, addedCount: matches.length };\n  }\n\n  return { isAdded: false, addedCount: 0 };\n}\n\nexport const addBeforeLoaders = (\n  webpackConfig: WebpackConfig,\n  matcher: LoaderMatcher,\n  newLoader: RuleSetRule\n) => addLoaders(webpackConfig, matcher, newLoader, (x) => x);\n\nexport const addAfterLoaders = (\n  webpackConfig: WebpackConfig,\n  matcher: LoaderMatcher,\n  newLoader: RuleSetRule\n) => addLoaders(webpackConfig, matcher, newLoader, (x) => x + 1);\n"
  },
  {
    "path": "packages/craco/src/lib/logger.ts",
    "content": "import { getArgs } from './args';\n\nexport function log(...rest: any[]) {\n    if (getArgs().verbose) {\n        console.log(...rest);\n    }\n}\n\nexport function logError(...rest: any[]) {\n    console.error(...rest);\n}\n"
  },
  {
    "path": "packages/craco/src/lib/paths.ts",
    "content": "import fs from 'fs';\nimport { log } from './logger';\n\nexport const projectRoot = fs.realpathSync(process.cwd());\n\nlog('Project root path resolved to: ', projectRoot);\n"
  },
  {
    "path": "packages/craco/src/lib/plugin-utils.ts",
    "content": "interface ConfigError {\n  message: string;\n  packageName?: string;\n  githubRepo?: string;\n  githubIssueQuery?: string;\n}\n\nexport function gitHubIssueUrl(repo: string, query?: string) {\n  return `https://github.com/${repo}/issues?q=is%3Aissue${\n    query ? `+${query}` : ''\n  }`;\n}\n\nfunction showNpmPackageUrl(packageName: string) {\n  return `\\n   * https://www.npmjs.com/package/${packageName}\\n\\n`;\n}\n\nfunction showGitHubIssueUrl(repo: string, query?: string) {\n  return (\n    `Please check to see if there's already an issue in the ${repo} repo:\\n\\n` +\n    `   * ${gitHubIssueUrl(repo, query)}\\n\\n` +\n    \"If not, please open an issue and we'll take a look. (Or you can send a PR!)\\n\\n\"\n  );\n}\n\nfunction showPackageUpdateInstructions(\n  packageName: string,\n  repo?: string,\n  query?: string\n) {\n  return (\n    `Please try updating ${packageName} to the latest version:\\n\\n` +\n    `   $ yarn upgrade ${packageName}\\n\\n` +\n    'Or:\\n\\n' +\n    `   $ npm update ${packageName}\\n\\n` +\n    `If that doesn't work, ${packageName} needs to be fixed to support the latest version.\\n` +\n    (repo ? showGitHubIssueUrl(repo, query) : showNpmPackageUrl(packageName))\n  );\n}\n\nexport function throwUnexpectedConfigError({\n  message,\n  packageName,\n  githubRepo: repo,\n  githubIssueQuery: query,\n}: ConfigError) {\n  throw new Error(\n    `${message}\\n\\n` +\n      'This error probably occurred because you updated react-scripts or craco. ' +\n      (packageName\n        ? showPackageUpdateInstructions(packageName, repo, query)\n        : 'You will need to update this plugin to work with the latest version.\\n\\n') +\n      'You might also want to look for related issues in the ' +\n      'craco and create-react-app repos:\\n\\n' +\n      `   * ${gitHubIssueUrl('dilanx/craco', query)}\\n` +\n      `   * ${gitHubIssueUrl('facebook/create-react-app', query)}\\n`\n  );\n}\n"
  },
  {
    "path": "packages/craco/src/lib/user-config-utils.ts",
    "content": "export function when<T>(\n  condition: boolean,\n  fn: () => T,\n  unmetValue?: T\n): T | undefined {\n  if (condition) {\n    return fn();\n  }\n\n  return unmetValue;\n}\n\nexport function whenDev<T>(fn: () => T, unmetValue?: T): T | undefined {\n  return when<T>(process.env.NODE_ENV === 'development', fn, unmetValue);\n}\n\nexport function whenProd<T>(fn: () => T, unmetValue?: T): T | undefined {\n  return when<T>(process.env.NODE_ENV === 'production', fn, unmetValue);\n}\n\nexport function whenTest<T>(fn: () => T, unmetValue?: T): T | undefined {\n  return when<T>(process.env.NODE_ENV === 'test', fn, unmetValue);\n}\n"
  },
  {
    "path": "packages/craco/src/lib/utils.ts",
    "content": "import { mergeWith } from 'lodash';\n\nexport function isFunction(value: any): value is (...args: any[]) => any {\n  return typeof value === 'function';\n}\n\nexport function isArray(value: any): value is Array<any> {\n  return Array.isArray(value);\n}\n\nexport function isString(value: any): value is string {\n  return typeof value === 'string';\n}\n\nexport function isBoolean(value: any): value is boolean {\n  return typeof value === 'boolean';\n}\n\nexport function deepMergeWithArray(dest: any, ...src: any) {\n  return mergeWith(dest, ...src, (x: any, y: any) => {\n    if (isArray(x)) {\n      return x.concat(y);\n    }\n  });\n}\n"
  },
  {
    "path": "packages/craco/src/lib/validate-cra-version.ts",
    "content": "import type { CracoConfig } from '@craco/types';\n\nimport { getReactScriptVersion } from '../lib/cra';\n\nexport function validateCraVersion(cracoConfig: CracoConfig) {\n  const { isSupported, version } = getReactScriptVersion(cracoConfig);\n  if (!isSupported) {\n    throw new Error(\n      `Your current version of react-scripts(${version}) is not supported by this version of CRACO. Please try updating react-scripts to the latest version:\\n\\n` +\n        `   $ yarn upgrade react-scripts\\n\\n` +\n        'Or:\\n\\n' +\n        `   $ npm update react-scripts\\n\\n` +\n        `If that doesn't work or if you can't, refer to the following table to choose the right version of CRACO.\\n` +\n        'https://github.com/gsoft-inc/craco/blob/master/packages/craco/README.md#backward-compatibility'\n    );\n  }\n}\n"
  },
  {
    "path": "packages/craco/src/lib/webpack-plugins.ts",
    "content": "import type { Configuration as WebpackConfig } from 'webpack';\n\nexport function pluginByName(targetPluginName: string) {\n    return (plugin: any) => {\n        return plugin.constructor.name === targetPluginName;\n    };\n}\n\nexport function getPlugin(\n    webpackConfig: WebpackConfig,\n    matcher: (value: any, index?: number, obj?: any[]) => boolean\n) {\n    const matchingPlugin = webpackConfig.plugins?.find(matcher);\n\n    return {\n        isFound: matchingPlugin !== undefined,\n        match: matchingPlugin,\n    };\n}\n\nexport function addPlugins(\n    webpackConfig: WebpackConfig,\n    webpackPlugins: any[]\n) {\n    const prependPlugins = [];\n    const appendPlugins = [];\n\n    for (const webpackPlugin of webpackPlugins) {\n        if (Array.isArray(webpackPlugin)) {\n            const [plugin, order] = webpackPlugin;\n            if (order === 'append') {\n                appendPlugins.push(plugin);\n            } else {\n                // Existing behaviour is to prepend\n                prependPlugins.push(plugin);\n            }\n            continue;\n        }\n        prependPlugins.push(webpackPlugin);\n    }\n\n    webpackConfig.plugins = [\n        ...prependPlugins,\n        ...(webpackConfig.plugins as any[]),\n        ...appendPlugins,\n    ];\n}\n\nexport function removePlugins(\n    webpackConfig: WebpackConfig,\n    matcher: (value: any, index?: number, array?: any[]) => boolean\n) {\n    const prevCount = webpackConfig.plugins?.length ?? 0;\n    webpackConfig.plugins = webpackConfig.plugins?.filter(\n        (x, i, a) => !matcher(x, i, a)\n    );\n    const removedPluginsCount =\n        prevCount - (webpackConfig.plugins?.length ?? 0);\n\n    return {\n        hasRemovedAny: removedPluginsCount > 0,\n        removedCount: removedPluginsCount,\n    };\n}\n"
  },
  {
    "path": "packages/craco/src/scripts/build.ts",
    "content": "import type { BaseContext } from '@craco/types';\n\nprocess.env.NODE_ENV = process.env.NODE_ENV || 'production';\n\nimport { findArgsFromCli } from '../lib/args';\n\n// Make sure this is called before \"paths\" is imported.\nfindArgsFromCli();\n\nimport { loadCracoConfigAsync } from '../lib/config';\nimport { build, getCraPaths } from '../lib/cra';\nimport { overridePaths } from '../lib/features/paths/override';\nimport {\n  overrideWebpackProd,\n  overrideWebpackDev,\n} from '../lib/features/webpack/override';\nimport { log } from '../lib/logger';\nimport { validateCraVersion } from '../lib/validate-cra-version';\n\nlog('Override started with arguments: ', process.argv);\nlog('For environment: ', process.env.NODE_ENV);\n\nconst context: BaseContext = {\n  env: process.env.NODE_ENV,\n};\n\nloadCracoConfigAsync(context).then((cracoConfig) => {\n  validateCraVersion(cracoConfig);\n\n  context.paths = getCraPaths(cracoConfig);\n  context.paths = overridePaths(cracoConfig, context);\n\n  process.env.NODE_ENV === 'production'\n    ? overrideWebpackProd(cracoConfig, context)\n    : overrideWebpackDev(cracoConfig, context);\n  build(cracoConfig);\n});\n"
  },
  {
    "path": "packages/craco/src/scripts/start.ts",
    "content": "import type { BaseContext, CracoConfig } from '@craco/types';\n\nprocess.env.NODE_ENV = process.env.NODE_ENV || 'development';\n\nimport { findArgsFromCli } from '../lib/args';\n\n// Make sure this is called before \"paths\" is imported.\nfindArgsFromCli();\n\nimport { loadCracoConfigAsync } from '../lib/config';\nimport { getCraPaths, start } from '../lib/cra';\nimport { overrideDevServer } from '../lib/features/dev-server/override';\nimport { overrideWebpackDev } from '../lib/features/webpack/override';\nimport { overridePaths } from '../lib/features/paths/override';\nimport { log } from '../lib/logger';\nimport { validateCraVersion } from '../lib/validate-cra-version';\n\nlog('Override started with arguments: ', process.argv);\nlog('For environment: ', process.env.NODE_ENV);\n\nconst context: BaseContext = {\n  env: process.env.NODE_ENV,\n};\n\nloadCracoConfigAsync(context).then((cracoConfig: CracoConfig) => {\n  validateCraVersion(cracoConfig);\n\n  context.paths = getCraPaths(cracoConfig);\n  context.paths = overridePaths(cracoConfig, context);\n\n  overrideWebpackDev(cracoConfig, context);\n  overrideDevServer(cracoConfig, context);\n\n  start(cracoConfig);\n});\n"
  },
  {
    "path": "packages/craco/src/scripts/test.ts",
    "content": "import type { BaseContext, CracoConfig } from '@craco/types';\n\nprocess.env.NODE_ENV = process.env.NODE_ENV || 'test';\n\nimport { findArgsFromCli } from '../lib/args';\n\n// Make sure this is called before \"paths\" is imported.\nfindArgsFromCli();\n\nimport { loadCracoConfigAsync } from '../lib/config';\nimport { getCraPaths, test } from '../lib/cra';\nimport { overrideJest } from '../lib/features/jest/override';\nimport { overridePaths } from '../lib/features/paths/override';\nimport { log } from '../lib/logger';\nimport { validateCraVersion } from '../lib/validate-cra-version';\n\nlog('Override started with arguments: ', process.argv);\nlog('For environment: ', process.env.NODE_ENV);\n\nconst context: BaseContext = {\n  env: process.env.NODE_ENV,\n};\n\nloadCracoConfigAsync(context).then((cracoConfig: CracoConfig) => {\n  validateCraVersion(cracoConfig);\n\n  context.paths = getCraPaths(cracoConfig);\n  context.paths = overridePaths(cracoConfig, context);\n\n  overrideJest(cracoConfig, context);\n  test(cracoConfig);\n});\n"
  },
  {
    "path": "packages/craco/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"noEmit\": false,\n    \"outDir\": \"dist\"\n  },\n  \"include\": [\"src\"]\n}\n"
  },
  {
    "path": "packages/craco-types/README.md",
    "content": "# @craco/types\n\nOfficial type definitions for [CRACO](https://www.npmjs.com/package/@craco/craco)\n"
  },
  {
    "path": "packages/craco-types/package.json",
    "content": "{\n  \"name\": \"@craco/types\",\n  \"description\": \"Official type declarations for @craco/craco\",\n  \"version\": \"7.1.0\",\n  \"main\": \"dist/index.js\",\n  \"types\": \"dist/index.d.ts\",\n  \"files\": [\n    \"dist\"\n  ],\n  \"scripts\": {\n    \"build\": \"tsc\",\n    \"prepack\": \"npm run build\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/dilanx/craco.git\",\n    \"directory\": \"packages/craco-types\"\n  },\n  \"author\": \"Dilan Nair (https://www.dilanxd.com)\",\n  \"license\": \"Apache-2.0\",\n  \"bugs\": {\n    \"url\": \"https://github.com/dilanx/craco/issues\"\n  },\n  \"homepage\": \"https://craco.js.org\",\n  \"dependencies\": {\n    \"@babel/types\": \"^7.19.3\",\n    \"@jest/types\": \"^27.5.1\",\n    \"@types/eslint\": \"^8.4.6\",\n    \"autoprefixer\": \"^10.4.12\",\n    \"eslint-webpack-plugin\": \"^3.2.0\",\n    \"webpack\": \"^5.74.0\"\n  },\n  \"devDependencies\": {\n    \"typescript\": \"^4.8.4\"\n  },\n  \"publishConfig\": {\n    \"access\": \"public\"\n  }\n}\n"
  },
  {
    "path": "packages/craco-types/src/asset-modules.ts",
    "content": "import type { RuleSetRule } from 'webpack';\n\nexport type AssetModuleType =\n  | 'javascript/auto'\n  | 'javascript/dynamic'\n  | 'javascript/esm'\n  | 'json'\n  | 'webassembly/sync'\n  | 'webassembly/async'\n  | 'asset'\n  | 'asset/source'\n  | 'asset/resource'\n  | 'asset/inline';\n\nexport type AssetModuleMatcher = (rule: RuleSetRule) => boolean;\n\nexport interface AssetModule {\n  rule: RuleSetRule;\n  index: number;\n}\n"
  },
  {
    "path": "packages/craco-types/src/config.ts",
    "content": "import type { TransformOptions } from '@babel/core';\nimport type { Options as AutoprefixerOptions } from 'autoprefixer';\nimport type { Linter } from 'eslint';\nimport type { PluginOptions } from 'eslint-webpack-plugin/types/options';\nimport type {\n  Configuration as WebpackConfig,\n  WebpackPluginInstance,\n} from 'webpack';\nimport type { Configuration as DevServerConfig } from 'webpack-dev-server';\nimport type {\n  BaseContext,\n  CraPaths,\n  DevServerContext,\n  JestContext,\n  WebpackContext,\n} from './context';\nimport type { CracoPlugin } from './plugins';\nimport type { Config as JestConfig } from '@jest/types';\n\nexport type Configure<Config, Context> =\n  | Config\n  | ((config: Config, context: Context) => Config);\n\nexport interface CracoStyleConfig {\n  modules?: {\n    localIdentName?: string;\n  };\n  css?: {\n    loaderOptions?: Configure<any, BaseContext>;\n  };\n  sass?: {\n    loaderOptions?: Configure<any, BaseContext>;\n  };\n  postcss?: {\n    mode?: 'extends' | 'file';\n    plugins?: any[] | ((plugins: any[]) => any[]);\n    env?: {\n      autoprefixer?: AutoprefixerOptions;\n      stage?: 0 | 1 | 2 | 3 | 4 | false;\n      features?: { [featureId: string]: any };\n    };\n    loaderOptions?: Configure<any, BaseContext>;\n  };\n}\n\nexport interface CracoBabelConfig {\n  presets?: any[];\n  plugins?: any[];\n  assumptions?: { [assumption: string]: boolean };\n  loaderOptions?: Configure<TransformOptions, BaseContext>;\n}\n\nexport interface CracoEsLintConfig {\n  enable?: boolean;\n  mode?: 'extends' | 'file';\n  configure?: Configure<Linter.Config, BaseContext>;\n  pluginOptions?: Configure<PluginOptions, BaseContext>;\n}\n\nexport type WebpackAlias = { [alias: string]: string };\nexport type AddWebpackPlugins = (\n  | WebpackPluginInstance\n  | [WebpackPluginInstance, 'append' | 'prepend']\n)[];\n\nexport interface CracoWebpackConfig {\n  alias?: WebpackAlias;\n  plugins?: {\n    add?: AddWebpackPlugins;\n    remove?: string[];\n  };\n  configure?: Configure<WebpackConfig, WebpackContext>;\n}\n\nexport type CracoDevServerConfig = Configure<DevServerConfig, DevServerContext>;\n\nexport interface CracoJestConfig {\n  babel?: {\n    addPresets?: boolean;\n    addPlugins?: boolean;\n  };\n\n  configure?: Configure<JestConfig.InitialOptions, JestContext>;\n}\n\nexport interface CracoTypeScriptConfig {\n  enableTypeChecking?: boolean;\n}\n\nexport interface CracoPluginDefinition<Options> {\n  plugin: CracoPlugin;\n  options?: Options;\n}\n\nexport interface CracoConfig {\n  reactScriptsVersion?: string;\n  style?: CracoStyleConfig;\n  eslint?: CracoEsLintConfig;\n  babel?: CracoBabelConfig;\n  jest?: CracoJestConfig;\n  typescript?: CracoTypeScriptConfig;\n  webpack?: CracoWebpackConfig;\n  devServer?: CracoDevServerConfig;\n  plugins?: CracoPluginDefinition<any>[];\n  paths?: Configure<CraPaths | undefined, BaseContext>;\n}\n"
  },
  {
    "path": "packages/craco-types/src/context.ts",
    "content": "import type { ProxyConfigArray } from 'webpack-dev-server';\n\nexport interface CraPaths {\n  dotenv: string;\n  appPath: string;\n  appBuild: string;\n  appPublic: string;\n  appHtml: string;\n  appIndexJs: string;\n  appPackageJson: string;\n  appSrc: string;\n  appTsConfig: string;\n  appJsConfig: string;\n  yarnLockFile: string;\n  testsSetup: string;\n  proxySetup: string;\n  appNodeModules: string;\n  swSrc: string;\n  publicUrlOrPath: string;\n  ownPath: string;\n  ownNodeModules: string;\n  appTypeDeclarations: string;\n  ownTypeDeclarations: string;\n  moduleFileExtensions: string[];\n}\n\nexport interface BaseContext {\n  env?: string;\n  paths?: CraPaths;\n}\n\nexport type WebpackContext = BaseContext;\n\nexport interface DevServerContext extends BaseContext {\n  proxy?: ProxyConfigArray;\n  allowedHost?: string;\n}\n\nexport interface JestContext extends BaseContext {\n  resolve?: (id: string) => string;\n  rootDir?: string;\n}\n"
  },
  {
    "path": "packages/craco-types/src/index.ts",
    "content": "export {\n  AssetModuleType,\n  AssetModuleMatcher,\n  AssetModule,\n} from './asset-modules';\n\nexport {\n  Configure,\n  CracoStyleConfig,\n  CracoBabelConfig,\n  CracoEsLintConfig,\n  WebpackAlias,\n  AddWebpackPlugins,\n  CracoWebpackConfig,\n  CracoDevServerConfig,\n  CracoJestConfig,\n  CracoTypeScriptConfig,\n  CracoPluginDefinition,\n  CracoConfig,\n} from './config';\n\nexport {\n  CraPaths,\n  BaseContext,\n  WebpackContext,\n  DevServerContext,\n  JestContext,\n} from './context';\n\nexport { LoaderMatcher, Loader, CompleteLoader } from './loaders';\n\nexport {\n  PluginOptions,\n  CracoConfigOverride,\n  WebpackConfigOverride,\n  DevServerConfigOverride,\n  JestConfigOverride,\n  CracoPlugin,\n} from './plugins';\n\nexport { DevServerConfigProvider, JestConfigProvider } from './providers';\n"
  },
  {
    "path": "packages/craco-types/src/loaders.ts",
    "content": "import type { RuleSetRule, RuleSetUseItem } from 'webpack';\n\n// TODO these typings need to be updated I'm pretty sure\n\nexport type LoaderMatcher = (rule: RuleSetRule | RuleSetUseItem) => boolean;\n\nexport interface Loader {\n  loader?: RuleSetRule;\n  parent?: RuleSetRule[];\n  index: number;\n}\n\nexport type CompleteLoader = Loader & {\n  loader: RuleSetRule;\n};\n"
  },
  {
    "path": "packages/craco-types/src/plugins.ts",
    "content": "import type { CracoConfig } from './config';\nimport type { Configuration as DevServerConfig } from 'webpack-dev-server';\nimport type { Config as JestConfig } from '@jest/types';\nimport type { Configuration as WebpackConfig } from 'webpack';\nimport type {\n  BaseContext,\n  DevServerContext,\n  JestContext,\n  WebpackContext,\n} from './context';\n\nexport type PluginOptions = any;\n\nexport interface CracoConfigOverride {\n  cracoConfig: CracoConfig;\n  pluginOptions: PluginOptions;\n  context: BaseContext;\n}\n\nexport interface WebpackConfigOverride {\n  webpackConfig: WebpackConfig;\n  cracoConfig: CracoConfig;\n  pluginOptions: PluginOptions;\n  context: WebpackContext;\n}\n\nexport interface DevServerConfigOverride {\n  devServerConfig: DevServerConfig;\n  cracoConfig: CracoConfig;\n  pluginOptions: PluginOptions;\n  context: DevServerContext;\n}\n\nexport interface JestConfigOverride {\n  jestConfig: JestConfig.InitialOptions;\n  cracoConfig: CracoConfig;\n  pluginOptions: PluginOptions;\n  context: JestContext;\n}\n\nexport interface CracoPlugin {\n  overrideCracoConfig?: (\n    cracoConfigOverride: CracoConfigOverride\n  ) => CracoConfig;\n  overrideWebpackConfig?: (\n    webpackConfigOverride: WebpackConfigOverride\n  ) => WebpackConfig;\n  overrideDevServerConfig?: (\n    devServerConfigOverride: DevServerConfigOverride\n  ) => DevServerConfig;\n  overrideJestConfig?: (\n    jestConfigOverride: JestConfigOverride\n  ) => JestConfig.InitialOptions;\n}\n"
  },
  {
    "path": "packages/craco-types/src/providers.ts",
    "content": "import type { Configuration as DevServerConfig } from 'webpack-dev-server';\nimport type { Config as JestConfig } from '@jest/types';\n\nexport type DevServerConfigProvider = (\n  proxy: any,\n  allowedHost: string\n) => DevServerConfig;\n\nexport type JestConfigProvider = (\n  customResolve: (relativePath: string) => string,\n  projectRoot: string,\n  isEjecting: boolean\n) => JestConfig.InitialOptions;\n"
  },
  {
    "path": "packages/craco-types/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"noEmit\": false,\n    \"outDir\": \"dist\"\n  },\n  \"include\": [\"src\"]\n}\n"
  },
  {
    "path": "recipes/README.md",
    "content": "# CRACO Recipes\n\nRecipes have been moved to https://craco.js.org/recipes/.\n"
  },
  {
    "path": "test/README.md",
    "content": "# CRACO End-to-End Tests\n\n## Usage\n\nThese tests ensure various functionality contracts are upheld across dependency upgrades.\n\nTo get started locally, run `npm run test:unit` or `npm run test:integration`.\n\n## How do these work?\n\n### `unit/`\n\nThese tests are non-integration and do not involve the building of any individual packages.\n\n### `integration/fixtures/`\n\nEach `fixture/` gets spun up in a temporary directory and has its dependencies installed with npm.<br>\n\n### `integration/setup.js`\n\nThis script runs before any integration tests are executed. It creates a temporary directory for each fixture, installs the local version of CRACO, any other required packages, and builds the package. You can then use an individual <test>.test.js within the fixture to start a server or check for properties of the build files.\n\n### `integration/teardown.js`\n\nThis removes all temporary directories generated during integration tests.\n\n## How can I make my own tests?\n\n### Unit tests\n\nTo create your own unit test, you can simply setup a directory within `unit/`, make a <test>.test.js, import necessary craco files, then test specific features. This test can be run with `npm run test:unit`.\n\n### Integration tests\n\nTo create your own integration test, create a new directory under `integration/fixtures/`. You can then create a directory within called `test-package-files`, which should contain all necessary files for your package (public/index.html, craco.config.js, src/index.js, etc). These will be copied over to the temporary directory on test execution.\n\nYou can then create a index.test.js in `integration/fixtures/<testname>` to interface with the built package. It's recommended run a local server, then use playwright to test individual features of the live website. View `integration/fixtures/basic-integration-test` for an example.\n\nThis integration test will be run with `npm run test:integration`.\n"
  },
  {
    "path": "test/integration/fixtures/autoprefixer-test/index.test.js",
    "content": "'use strict';\nconst path = require('path');\nconst fs = require('fs');\n\ntest('Should have the expected styles', async () => {\n  const expectedStyles = \"::-webkit-input-placeholder{color:gray}::placeholder{color:gray}.image{background-image:url(https://google.com)}@media (-webkit-min-device-pixel-ratio:2),(min-resolution:2dppx){.image{background-image:url(http://nxetflix.com)}}\";\n  \n  //we check if the compiled css is what we expect for autoprefixer\n  const prom = new Promise((resolve, reject) => {\n    fs.readdir('./test/integration/fixtures/autoprefixer-test/test-project/build/static/css', (err, files) => {\n      if (err) reject();\n      //we don't know what the bundle name will be beforehand\n      const cssFile = files.find(file => path.extname(file) === '.css');\n      expect(cssFile).not.toBe(0);\n\n      fs.readFile(`./test/integration/fixtures/autoprefixer-test/test-project/build/static/css/${cssFile}`, 'utf8', (err, data) => {\n        if (err) reject();\n        data = data.substring(0, data.indexOf(\"/*\")-1);\n        expect(data).toBe(expectedStyles);\n        resolve();\n      });\n    });\n  });\n  await prom;\n});\n"
  },
  {
    "path": "test/integration/fixtures/autoprefixer-test/test-package-files/craco.config.js",
    "content": "const webpack = require('webpack');\nconst isDevelopment = false;\nmodule.exports = {\n  style: {\n    postcss: {\n      plugins: [\n        require('autoprefixer')()\n      ]\n    }\n  }\n};\n"
  },
  {
    "path": "test/integration/fixtures/autoprefixer-test/test-package-files/package.json",
    "content": "{\n  \"name\": \"craco-postcss-test\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"dependencies\": {\n    \"react\": \"^18.2.0\",\n    \"react-dom\": \"^18.2.0\",\n    \"web-vitals\": \"^3.3.1\",\n    \"autoprefixer\": \"^10.4.14\"\n  },\n  \"scripts\": {\n    \"start\": \"craco start\",\n    \"build\": \"craco build\",\n    \"test\": \"craco test\",\n    \"eject\": \"react-scripts eject\"\n  },\n  \"browserslist\": [\n    \">0.2%\",\n    \"not dead\",\n    \"not ie <= 11\",\n    \"not op_mini all\"\n  ]\n}\n"
  },
  {
    "path": "test/integration/fixtures/autoprefixer-test/test-package-files/public/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <title>React App</title>\n    <link rel=\"stylesheet\" href=\"index.css\" />\n  </head>\n  <body>\n    <div id=\"root\"></div>\n    <script src=\"index.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "test/integration/fixtures/autoprefixer-test/test-package-files/src/index.css",
    "content": "::placeholder {\n  color: gray;\n}\n\n.image {\n  background-image: url(\"https://google.com\");\n}\n@media (min-resolution: 2dppx) {\n  .image {\n    background-image: url(\"http://nxetflix.com\");\n  }\n}\n"
  },
  {
    "path": "test/integration/fixtures/autoprefixer-test/test-package-files/src/index.js",
    "content": "import React from 'react';\nimport ReactDOM from 'react-dom';\nimport './index.css';\n\nReactDOM.render(\n  <React.StrictMode>\n    <div className=\"container\">\n      <h1>Hi!</h1>\n    </div>\n  </React.StrictMode>,\n  document.getElementById('root')\n);\n"
  },
  {
    "path": "test/integration/fixtures/basic-integration-test/index.test.js",
    "content": "'use strict';\nconst { join } = require('path');\nconst { execSync, spawn } = require('child_process');\n\nbeforeAll(async () => {\n  // Start a local server to serve the test project\n  // We cached serve by installing it locally\n  const server = spawn('npx', ['serve@14.2.0', '-s', 'build', '-l', global.PORT], {\n    cwd: join(__dirname, 'test-project'),\n  });\n\n  // Log any server errors to the console\n  server.stderr.on('data', (data) => {\n    console.error(`stderr: ${data}`);\n  });\n\n  // Leave time for the server to initialize\n  await new Promise((resolve) => {\n    setTimeout(resolve, 5000);\n  });\n});\n\ntest('Should have the expected custom craco variable name', async () => {\n  await page.goto(global.URL, { waitUntil: 'domcontentloaded' }); //todo: make the url changeble\n\n  const cracoTestText = await page.$eval(\n    '#craco-test',\n    (element) => element.textContent\n  );\n  expect(cracoTestText).toBe('CRACO is working!');\n});\n\nafterAll(() => {\n  // Stop the local server\n  execSync(`kill $(lsof -t -i:${global.PORT} -a -c node)`, {\n    cwd: __dirname,\n    stdio: 'ignore',\n  });\n});\n"
  },
  {
    "path": "test/integration/fixtures/basic-integration-test/test-package-files/craco.config.js",
    "content": "const webpack = require('webpack');\nconst isDevelopment = false;\nmodule.exports = {\n  webpack: {\n    configure: (webpackConfig) => {\n      webpackConfig.plugins.push(\n        new webpack.DefinePlugin({\n          __CUSTOM_GLOBAL_CONSTANT__: JSON.stringify('CRACO is working!'),\n        })\n      );\n\n      return webpackConfig;\n    },\n  },\n};\n"
  },
  {
    "path": "test/integration/fixtures/basic-integration-test/test-package-files/package.json",
    "content": "{\n  \"name\": \"craco-basic-test\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"dependencies\": {\n    \"react\": \"^18.2.0\",\n    \"react-dom\": \"^18.2.0\",\n    \"serve\": \"14.2.0\",\n    \"web-vitals\": \"^3.3.1\"\n  },\n  \"scripts\": {\n    \"start\": \"craco start\",\n    \"build\": \"craco build\",\n    \"test\": \"craco test\",\n    \"eject\": \"react-scripts eject\"\n  },\n  \"browserslist\": [\n    \">0.2%\",\n    \"not dead\",\n    \"not ie <= 11\",\n    \"not op_mini all\"\n  ]\n}\n"
  },
  {
    "path": "test/integration/fixtures/basic-integration-test/test-package-files/public/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <title>React App</title>\n    <link rel=\"stylesheet\" href=\"index.css\" />\n  </head>\n  <body>\n    <div id=\"root\"></div>\n    <script src=\"index.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "test/integration/fixtures/basic-integration-test/test-package-files/src/index.js",
    "content": "/* global __CUSTOM_GLOBAL_CONSTANT__ */\nimport React from 'react';\nimport ReactDOM from 'react-dom';\nimport './index.css';\n\nReactDOM.render(\n  <React.StrictMode>\n    <div className=\"container\">\n      <h1>Testing CRACO</h1>\n      <p id=\"craco-test\">{__CUSTOM_GLOBAL_CONSTANT__}</p>\n    </div>\n  </React.StrictMode>,\n  document.getElementById('root')\n);\n"
  },
  {
    "path": "test/integration/jest.config.js",
    "content": "'use strict';\n\nmodule.exports = {\n  // testEnvironment: 'node',\n  testMatch: ['<rootDir>/**/*.test.js'],\n  testPathIgnorePatterns: ['/src/', 'node_modules'],\n  transform: {\n    '^.+\\\\.jsx?$': 'babel-jest',\n  },\n  moduleNameMapper: {\n    '\\\\.(css|less|scss|sass)$': 'identity-obj-proxy',\n  },\n  globalSetup: './setup.js',\n  globalTeardown: './teardown.js',\n  testEnvironmentOptions: {\n    'jest-playwright': {\n      browsers: ['firefox'],\n      launchOptions: {\n        headless: true,\n        timeout: 500000,\n      },\n    },\n  },\n  globals: {\n    PORT: 3009,\n    URL: 'http://localhost:3009',\n  },\n  preset: 'jest-playwright-preset',\n};\n"
  },
  {
    "path": "test/integration/setup.js",
    "content": "const { join } = require('path');\nconst { execSync } = require('child_process');\nconst fs = require('fs');\nconst rootPath = 'test/integration/fixtures';\n\nconst cwd = process.cwd();\n\n// Set up the environment for integration tests\nmodule.exports = async function (globalConfig, projectConfig) {\n  fs.readdir(rootPath, { withFileTypes: true }, (err, entries) => {\n    if (err) {\n      console.error(`Error reading directory: ${err.message}`);\n      return;\n    }\n\n    const directoryNames = entries\n      .filter((entry) => entry.isDirectory())\n      .map((entry) => entry.name);\n\n    directoryNames.forEach((directoryName) => {\n      //copy files in directory/test-package-files to directory/test-project\n      const testPackageFilesPath = join(\n        rootPath,\n        directoryName,\n        'test-package-files'\n      );\n      const testProjectPath = join(rootPath, directoryName, 'test-project');\n      execSync(\n        `cd ${join(\n          rootPath,\n          directoryName\n        )} && npx create-react-app test-project`,\n        { cwd: cwd, stdio: 'inherit' }\n      );\n      execSync(`cp -r ${testPackageFilesPath}/* ${testProjectPath}`, {\n        cwd: cwd\n      });\n      //install craco\n      execSync(`npm install ../../../../../packages/craco`, {\n        cwd: testProjectPath, stdio: 'inherit'\n      });\n      //install other necessary files\n      execSync(`npm install`, { cwd: testProjectPath, stdio: 'inherit' });\n      //build project\n      execSync('npm run build', { cwd: testProjectPath, stdio: 'inherit' });\n    });\n  });\n};\n"
  },
  {
    "path": "test/integration/teardown.js",
    "content": "// Clean up the environment after integration tests\nconst { execSync } = require('child_process');\nconst { join } = require('path');\nconst fs = require('fs');\n\nconst rootPath = 'test/integration/fixtures';\n\nconst cwd = process.cwd();\n\nmodule.exports = async () => {\n  fs.readdir(rootPath, { withFileTypes: true }, (err, entries) => {\n    if (err) {\n      console.error(`Error reading directory: ${err.message}`);\n      return;\n    }\n\n    const directoryNames = entries\n      .filter((entry) => entry.isDirectory())\n      .map((entry) => entry.name);\n\n    directoryNames.forEach((directoryName) => {\n      //clean up test-project\n      execSync(`rm -rf ${join(rootPath, directoryName, 'test-project')}`, {\n        cwd: cwd,\n      });\n    });\n  });\n};\n"
  },
  {
    "path": "test/unit/jest.config.js",
    "content": "'use strict';\n\nmodule.exports = {\n  testEnvironment: 'node',\n  testMatch: ['<rootDir>/**/*.test.js'],\n  testPathIgnorePatterns: ['/src/', 'node_modules'],\n  transform: {\n    '^.+\\\\.jsx?$': 'babel-jest',\n  },\n  moduleNameMapper: {\n    '\\\\.(css|less|scss|sass)$': 'identity-obj-proxy',\n  },\n};\n"
  },
  {
    "path": "test/unit/merging-tests/autoprefixer-options/autoprefixer.test.js",
    "content": "const cracoConfig = require('./craco.config');\nconst autoprefixer = require('autoprefixer');\n\ndescribe('CRACO autoprefixer configuration', () => {\n  it('correctly applies custom autoprefixer options', () => {\n    const postcssPlugins = cracoConfig.style.postcss.plugins;\n    const autoprefixerPluginEntry = postcssPlugins.find(\n      (pluginEntry) => pluginEntry.plugin === autoprefixer\n    );\n\n    expect(autoprefixerPluginEntry).toBeDefined();\n    expect(autoprefixerPluginEntry.options.grid).toEqual('autoplace');\n    expect(autoprefixerPluginEntry.options.overrideBrowserslist).toEqual([\n      '>1%',\n      'last 4 versions',\n      'Firefox ESR',\n      'not ie < 11',\n    ]);\n  });\n\n  it('does not remove other PostCSS plugins', () => {\n    const postcssPlugins = cracoConfig.style.postcss.plugins;\n    const autoprefixerPluginEntry = postcssPlugins.find(\n      (pluginEntry) => pluginEntry.plugin === autoprefixer\n    );\n\n    const pluginCountWithoutAutoprefixer =\n      postcssPlugins.length - (autoprefixerPluginEntry ? 1 : 0);\n    expect(pluginCountWithoutAutoprefixer).toBeGreaterThanOrEqual(0);\n  });\n});\n"
  },
  {
    "path": "test/unit/merging-tests/autoprefixer-options/craco.config.js",
    "content": "module.exports = {\n  style: {\n    postcss: {\n      plugins: [\n        {\n          plugin: require('autoprefixer'),\n          options: {\n            grid: 'autoplace',\n            overrideBrowserslist: [\n              '>1%',\n              'last 4 versions',\n              'Firefox ESR',\n              'not ie < 11',\n            ],\n          },\n        },\n      ],\n    },\n  },\n};\n"
  },
  {
    "path": "test/unit/merging-tests/configuration-merging/cra.mock.config.js",
    "content": "const craConfigMock = {\n  entry: './src/index.js',\n  output: {\n    path: '/dist',\n    filename: 'bundle.js',\n  },\n  module: {\n    rules: [\n      {\n        test: /\\.(js|jsx)$/,\n        exclude: /node_modules/,\n        use: 'babel-loader',\n      },\n    ],\n  },\n};\n\nmodule.exports = craConfigMock;\n"
  },
  {
    "path": "test/unit/merging-tests/configuration-merging/craco.config.js",
    "content": "module.exports = {\n  webpack: {\n    configure: (webpackConfig, { env, paths }) => {\n      // Add a custom loader for SVG files\n      webpackConfig.module.rules.push({\n        test: /\\.svg$/,\n        use: ['@svgr/webpack'],\n      });\n\n      // Ensure webpackConfig.resolve exists\n      if (!webpackConfig.resolve) {\n        webpackConfig.resolve = {};\n      }\n\n      // Add an alias\n      webpackConfig.resolve.alias = {\n        ...webpackConfig.resolve.alias,\n        '@components': './src/components',\n      };\n\n      // Update output folder\n      webpackConfig.output.path = '/dist/custom';\n\n      return webpackConfig;\n    },\n  },\n  babel: {\n    plugins: [\n      // Add an additional Babel plugin\n      'babel-plugin-transform-class-properties',\n    ],\n  },\n};\n"
  },
  {
    "path": "test/unit/merging-tests/configuration-merging/merging.test.js",
    "content": "'use strict';\nconst cracoConfig = require('./craco.config');\nconst craConfigMock = require('./cra.mock.config');\n\n//Create a simple mock of the CRA configuration and a custom CRACO configuration\n//Then ensure that the final configuration produced by CRACO correctly merges both configurations\ndescribe('CRACO configuration merging', () => {\n  it('correctly merges CRA and CRACO configurations', () => {\n    const webpackConfig = cracoConfig.webpack.configure(craConfigMock, {});\n\n    // Test if the original CRA rules are present\n    const jsRule = webpackConfig.module.rules.find(\n      (rule) => rule.test.toString() === /\\.(js|jsx)$/.toString()\n    );\n    expect(jsRule).toBeDefined();\n    expect(jsRule.exclude).toEqual(/node_modules/);\n    expect(jsRule.use).toEqual('babel-loader');\n\n    // Test if the custom SVG loader is added\n    const svgRule = webpackConfig.module.rules.find(\n      (rule) => rule.test.toString() === /\\.svg$/.toString()\n    );\n    expect(svgRule).toBeDefined();\n    expect(svgRule.use).toEqual(['@svgr/webpack']);\n\n    // Test if the alias is added\n    expect(webpackConfig.resolve.alias['@components']).toEqual(\n      './src/components'\n    );\n\n    // Test if the output path is updated\n    expect(webpackConfig.output.path).toEqual('/dist/custom');\n  });\n\n  it('correctly adds the additional Babel plugin', () => {\n    const babelConfig = cracoConfig.babel;\n\n    // Test if the Babel plugin is added\n    expect(babelConfig.plugins).toContain(\n      'babel-plugin-transform-class-properties'\n    );\n  });\n});\n"
  },
  {
    "path": "test/unit/merging-tests/custom-babel-config/babel.config.mock.js",
    "content": "const babelConfigMock = {\n  presets: ['@babel/preset-env', '@babel/preset-react'],\n};\n\nmodule.exports = babelConfigMock;\n"
  },
  {
    "path": "test/unit/merging-tests/custom-babel-config/babel.test.js",
    "content": "const cracoConfig = require('./craco.config');\nconst babelConfigMock = require('./babel.config.mock');\n\ndescribe('CRACO Babel configuration', () => {\n  it('correctly applies custom Babel presets', () => {\n    const babelConfig = cracoConfig.babel.loaderOptions;\n\n    // Test if the original Babel presets are present\n    expect(babelConfig.presets).toContain('@babel/preset-env');\n    expect(babelConfig.presets).toContain('@babel/preset-react');\n\n    // Test if the custom Babel preset is added\n    expect(babelConfig.presets).toContain('@babel/preset-typescript');\n  });\n\n  it('does not remove existing Babel presets', () => {\n    const babelConfig = cracoConfig.babel.loaderOptions;\n\n    // Test if the number of presets in the custom configuration is greater than or equal to the original configuration\n    expect(babelConfig.presets.length).toBeGreaterThanOrEqual(\n      babelConfigMock.presets.length\n    );\n  });\n});\n"
  },
  {
    "path": "test/unit/merging-tests/custom-babel-config/craco.config.js",
    "content": "module.exports = {\n  babel: {\n    loaderOptions: {\n      presets: [\n        '@babel/preset-env',\n        '@babel/preset-react',\n        '@babel/preset-typescript',\n      ],\n    },\n  },\n};\n"
  },
  {
    "path": "test/unit/merging-tests/custom-craco-plugin/craco-plugin-mock/index.js",
    "content": "const fs = require('fs');\nconst path = require('path');\n\nfunction onPostBuild({ paths }) {\n  const pluginLogPath = path.join(__dirname, '..', 'plugin.log');\n  fs.writeFileSync(pluginLogPath, 'Plugin executed successfully');\n}\n\nmodule.exports = {\n  onPostBuild,\n};\n"
  },
  {
    "path": "test/unit/merging-tests/custom-craco-plugin/craco.config.js",
    "content": "const CracoPluginMock = require('./craco-plugin-mock');\n\nmodule.exports = {\n  plugins: [\n    {\n      plugin: CracoPluginMock,\n    },\n  ],\n};\n"
  },
  {
    "path": "test/unit/merging-tests/custom-craco-plugin/plugin.test.js",
    "content": "const fs = require('fs');\nconst path = require('path');\nconst cracoConfig = require('./craco.config');\nconst CracoPluginMock = require('./craco-plugin-mock');\n\ndescribe('CRACO custom plugin', () => {\n  const pluginLogPath = path.join(__dirname, 'plugin.log');\n\n  afterEach(() => {\n    if (fs.existsSync(pluginLogPath)) {\n      fs.unlinkSync(pluginLogPath);\n    }\n  });\n\n  it('correctly includes the custom plugin', () => {\n    const pluginEntry = cracoConfig.plugins.find(\n      (pluginEntry) => pluginEntry.plugin === CracoPluginMock\n    );\n    expect(pluginEntry).toBeDefined();\n  });\n\n  it('correctly executes the onPostBuild function of the custom plugin', () => {\n    const pluginEntry = cracoConfig.plugins.find(\n      (pluginEntry) => pluginEntry.plugin === CracoPluginMock\n    );\n\n    pluginEntry.plugin.onPostBuild({});\n\n    const logContent = fs.readFileSync(pluginLogPath, 'utf-8');\n    expect(logContent).toEqual('Plugin executed successfully');\n  });\n});\n"
  },
  {
    "path": "test/unit/merging-tests/custom-env-variables/craco.config.js",
    "content": "module.exports = {\n  env: {\n    MY_CUSTOM_ENV_VAR: 'custom-env-value',\n  },\n};\n"
  },
  {
    "path": "test/unit/merging-tests/custom-env-variables/env.test.js",
    "content": "const cracoConfig = require('./craco.config');\n\ndescribe('CRACO environment variables', () => {\n  it('correctly sets custom environment variables', () => {\n    const originalProcessEnv = { ...process.env };\n\n    // Apply the custom environment variables from the CRACO configuration\n    process.env = {\n      ...process.env,\n      ...cracoConfig.env,\n    };\n\n    // Test if the custom environment variable is set\n    expect(process.env.MY_CUSTOM_ENV_VAR).toEqual('custom-env-value');\n\n    // Restore the original process.env to avoid side effects\n    process.env = originalProcessEnv;\n  });\n\n  it('does not remove existing environment variables', () => {\n    const originalProcessEnv = { ...process.env };\n\n    // Apply the custom environment variables from the CRACO configuration\n    process.env = {\n      ...process.env,\n      ...cracoConfig.env,\n    };\n\n    // Test if the existing environment variables are not removed\n    const originalEnvVarCount = Object.keys(originalProcessEnv).length;\n    const newEnvVarCount = Object.keys(process.env).length;\n\n    expect(newEnvVarCount).toBeGreaterThanOrEqual(originalEnvVarCount);\n\n    // Restore the original process.env to avoid side effects\n    process.env = originalProcessEnv;\n  });\n});\n"
  },
  {
    "path": "test/unit/merging-tests/custom-eslint-config/craco.config.js",
    "content": "module.exports = {\n  eslint: {\n    configure: {\n      extends: ['react-app', 'plugin:prettier/recommended'],\n      rules: {\n        'no-console': 'error',\n        'no-debugger': 'error',\n      },\n    },\n  },\n};\n"
  },
  {
    "path": "test/unit/merging-tests/custom-eslint-config/eslint.config.mock.js",
    "content": "const eslintConfigMock = {\n  extends: ['react-app'],\n  rules: {\n    'no-console': 'warn',\n  },\n};\n\nmodule.exports = eslintConfigMock;\n"
  },
  {
    "path": "test/unit/merging-tests/custom-eslint-config/eslint.test.js",
    "content": "const cracoConfig = require('./craco.config');\nconst eslintConfigMock = require('./eslint.config.mock');\n\ndescribe('CRACO ESLint configuration', () => {\n  it('correctly applies custom ESLint configuration', () => {\n    const eslintConfig = cracoConfig.eslint.configure;\n\n    // Test if the original ESLint extends are present\n    expect(eslintConfig.extends).toContain('react-app');\n\n    // Test if the custom ESLint extends are added\n    expect(eslintConfig.extends).toContain('plugin:prettier/recommended');\n\n    // Test if the custom ESLint rules are applied\n    expect(eslintConfig.rules['no-console']).toEqual('error');\n    expect(eslintConfig.rules['no-debugger']).toEqual('error');\n  });\n\n  it('does not remove existing ESLint rules', () => {\n    const eslintConfig = cracoConfig.eslint.configure;\n\n    // Test if the number of rules in the custom configuration is greater than or equal to the original configuration\n    expect(Object.keys(eslintConfig.rules).length).toBeGreaterThanOrEqual(\n      Object.keys(eslintConfigMock.rules).length\n    );\n  });\n});\n"
  },
  {
    "path": "test/unit/merging-tests/custom-jest-config/craco.config.js",
    "content": "module.exports = {\n  jest: {\n    configure: {\n      transform: {\n        '^.+\\\\.[t|j]sx?$': 'babel-jest',\n      },\n      moduleNameMapper: {\n        '^@components/(.*)$': '<rootDir>/src/components/$1',\n      },\n    },\n  },\n};\n"
  },
  {
    "path": "test/unit/merging-tests/custom-jest-config/jest.config.mock.js",
    "content": "const jestConfigMock = {\n  transform: {\n    '^.+\\\\.[t|j]sx?$': 'babel-jest',\n  },\n};\n\nmodule.exports = jestConfigMock;\n"
  },
  {
    "path": "test/unit/merging-tests/custom-jest-config/jest.test.js",
    "content": "const cracoConfig = require('./craco.config');\nconst jestConfigMock = require('./jest.config.mock');\n\ndescribe('CRACO Jest configuration', () => {\n  it('correctly applies custom Jest configuration', () => {\n    const jestConfig = cracoConfig.jest.configure;\n\n    // Test if the original Jest transform configuration is present\n    expect(jestConfig.transform['^.+\\\\.[t|j]sx?$']).toEqual('babel-jest');\n\n    // Test if the custom Jest moduleNameMapper configuration is added\n    expect(jestConfig.moduleNameMapper['^@components/(.*)$']).toEqual(\n      '<rootDir>/src/components/$1'\n    );\n  });\n\n  it('does not remove existing Jest configurations', () => {\n    const jestConfig = cracoConfig.jest.configure;\n\n    // Test if the number of configurations in the custom configuration is greater than or equal to the original configuration\n    expect(Object.keys(jestConfig).length).toBeGreaterThanOrEqual(\n      Object.keys(jestConfigMock).length\n    );\n  });\n});\n"
  },
  {
    "path": "test/unit/merging-tests/custom-postcss-config/craco.config.js",
    "content": "module.exports = {\n  style: {\n    postcss: {\n      plugins: [require('autoprefixer'), require('postcss-nested')],\n    },\n  },\n};\n"
  },
  {
    "path": "test/unit/merging-tests/custom-postcss-config/postcss.config.mock.js",
    "content": "const postcssConfigMock = {\n  plugins: [require('autoprefixer')],\n};\n\nmodule.exports = postcssConfigMock;\n"
  },
  {
    "path": "test/unit/merging-tests/custom-postcss-config/postcss.test.js",
    "content": "const cracoConfig = require('./craco.config');\nconst postcssConfigMock = require('./postcss.config.mock');\n\n//Checks if a custom PostCSS configuration is correctly applied\ndescribe('CRACO PostCSS configuration', () => {\n  it('correctly applies custom PostCSS plugins', () => {\n    const postcssConfig = cracoConfig.style.postcss;\n\n    // Test if the original PostCSS plugins are present\n    expect(postcssConfig.plugins).toContainEqual(require('autoprefixer'));\n\n    // Test if the custom PostCSS plugin is added\n    expect(postcssConfig.plugins).toContainEqual(require('postcss-nested'));\n  });\n\n  it('does not remove existing PostCSS plugins', () => {\n    const postcssConfig = cracoConfig.style.postcss;\n\n    // Test if the number of plugins in the custom configuration is greater than or equal to the original configuration\n    expect(postcssConfig.plugins.length).toBeGreaterThanOrEqual(\n      postcssConfigMock.plugins.length\n    );\n  });\n});\n"
  },
  {
    "path": "test/unit/merging-tests/html-webpack-plugin/craco.config.js",
    "content": "module.exports = {\n  webpack: {\n    configure: (webpackConfig, { env, paths }) => {\n      const HtmlWebpackPlugin = require('html-webpack-plugin');\n\n      // Find the HtmlWebpackPlugin in the plugins array\n      const htmlWebpackPluginIndex = webpackConfig.plugins.findIndex(\n        (plugin) => plugin instanceof HtmlWebpackPlugin\n      );\n\n      if (htmlWebpackPluginIndex >= 0) {\n        // Create a new HtmlWebpackPlugin instance with the custom title\n        const updatedHtmlWebpackPlugin = new HtmlWebpackPlugin({\n          ...webpackConfig.plugins[htmlWebpackPluginIndex].userOptions,\n          title: 'My Custom Title',\n        });\n\n        // Replace the original HtmlWebpackPlugin instance with the updated one\n        webpackConfig.plugins.splice(\n          htmlWebpackPluginIndex,\n          1,\n          updatedHtmlWebpackPlugin\n        );\n      }\n\n      return webpackConfig;\n    },\n  },\n};\n"
  },
  {
    "path": "test/unit/merging-tests/html-webpack-plugin/html-webpack-plugin.test.js",
    "content": "const webpack = require('webpack');\nconst HtmlWebpackPlugin = require('html-webpack-plugin');\nconst cracoConfig = require('./craco.config');\n\ndescribe('CRACO HtmlWebpackPlugin configuration', () => {\n  it('correctly applies custom HtmlWebpackPlugin configuration', async () => {\n    const webpackConfig = {\n      mode: 'development',\n      plugins: [new HtmlWebpackPlugin()],\n    };\n\n    // Apply custom configuration to the webpack config\n    const newWebpackConfig = cracoConfig.webpack.configure(webpackConfig, {});\n\n    // Find the HtmlWebpackPlugin in the newWebpackConfig\n    const htmlWebpackPlugin = newWebpackConfig.plugins.find(\n      (plugin) => plugin instanceof HtmlWebpackPlugin\n    );\n\n    // Test if the custom title is set\n    expect(htmlWebpackPlugin.userOptions.title).toEqual('My Custom Title');\n  });\n});\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n    \"compilerOptions\": {\n        \"target\": \"es5\",\n        \"module\": \"commonjs\",\n        \"allowJs\": true,\n        \"skipLibCheck\": true,\n        \"esModuleInterop\": true,\n        \"allowSyntheticDefaultImports\": true,\n        \"strict\": true,\n        \"forceConsistentCasingInFileNames\": true,\n        \"noFallthroughCasesInSwitch\": true,\n        \"moduleResolution\": \"node\",\n        \"downlevelIteration\": true,\n        \"declaration\": true,\n        \"noEmit\": true,\n    },\n    \"include\": [\"packages/**/*\"]\n}\n"
  },
  {
    "path": "website/.gitignore",
    "content": "# Dependencies\n/node_modules\n\n# Production\n/build\n\n# Generated files\n.docusaurus\n.cache-loader\n\n# Misc\n.DS_Store\n.env.local\n.env.development.local\n.env.test.local\n.env.production.local\n\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n"
  },
  {
    "path": "website/README.md",
    "content": "# Website\n\nThis website is built using [Docusaurus 2](https://docusaurus.io/), a modern static website generator.\n\n### Installation\n\n```\n$ yarn\n```\n\n### Local Development\n\n```\n$ yarn start\n```\n\nThis command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.\n\n### Build\n\n```\n$ yarn build\n```\n\nThis command generates static content into the `build` directory and can be served using any static contents hosting service.\n\n### Deployment\n\nUsing SSH:\n\n```\n$ USE_SSH=true yarn deploy\n```\n\nNot using SSH:\n\n```\n$ GIT_USER=<Your GitHub username> yarn deploy\n```\n\nIf you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch.\n"
  },
  {
    "path": "website/babel.config.js",
    "content": "module.exports = {\n  presets: [require.resolve('@docusaurus/core/lib/babel/preset')],\n};\n"
  },
  {
    "path": "website/docs/configuration/babel.md",
    "content": "---\ndescription: Customize Babel\n---\n\n# Babel\n\n<!-- prettier-ignore -->\n```js title=\"craco.config.js\"\nmodule.exports = {\n  // ...\n  babel: {\n    presets: [ /* ... */ ],\n    plugins: [ /* ... */ ],\n    loaderOptions: { /* ... */ },\n    loaderOptions: (babelLoaderOptions, { env, paths }) => {\n      /* ... */\n      return babelLoaderOptions;\n    },\n  },\n};\n```\n\n:::tip\n\nProperties listed twice in the outline above (for example, `loaderOptions`) can be assigned an **object literal** or a **function**. See [configuration tips](./getting-started.md#object-literals-and-functions) for details.\n\n:::\n\n## babel.presets\n\n`[string | [string, object]]`\n\nAny Babel presets: https://babeljs.io/docs/en/presets/\n\n## babel.plugins\n\n`[string | [string, object]]`\n\nAny Babel plugins: https://babeljs.io/docs/en/plugins\n\n## babel.loaderOptions\n\n`BabelLoaderOptions` or `(options: BabelLoaderOptions, { env, paths }) => BabelLoaderOptions`\n\nAny babel-loader options: https://github.com/babel/babel-loader#options\n"
  },
  {
    "path": "website/docs/configuration/devserver.md",
    "content": "---\ndescription: Configure DevServer\n---\n\n# DevServer\n\n<!-- prettier-ignore -->\n```js title=\"craco.config.js\"\nmodule.exports = {\n  // ...\n  devServer: { /* ... */ },\n  devServer: (devServerConfig, { env, paths, proxy, allowedHost }) => {\n    /* ... */\n    return devServerConfig;\n  },\n};\n```\n\n:::tip\n\nProperties listed twice in the outline above (for example, `devServer`) can be assigned an **object literal** or a **function**. See [configuration tips](./getting-started.md#object-literals-and-functions) for details.\n\n:::\n\n## devServer\n\n`DevServerConfig` or `(config: DevServerConfig, { env, paths, proxy, allowedHost }) => DevServerConfig`\n\nAny DevServer configuration options: https://webpack.js.org/configuration/dev-server/#devserver\n\nThe function version of `configure` provides two extra properties within the [context object](./getting-started.md#context-object--env-paths-):\n\n- `proxy` - DevServer proxy config array\n- `allowedHost` - the allowed host\n"
  },
  {
    "path": "website/docs/configuration/eslint.md",
    "content": "---\ndescription: Customize ESLint\n---\n\n# ESLint\n\n<!-- prettier-ignore -->\n```js title=\"craco.config.js\"\nmodule.exports = {\n  // ...\n  eslint: {\n    enable: true /* (default value) */,\n    mode: 'extends' /* (default value) */ || 'file',\n    configure: { /* ... */ },\n    configure: (eslintConfig, { env, paths }) => {\n      /* ... */\n      return eslintConfig;\n    },\n    pluginOptions: { /* ... */ },\n    pluginOptions: (eslintPluginOptions, { env, paths }) => {\n      /* ... */\n      return eslintPluginOptions;\n    },\n  },\n};\n```\n\n:::tip\n\nProperties listed twice in the outline above (for example, `configure`) can be assigned an **object literal** or a **function**. See [configuration tips](./getting-started.md#object-literals-and-functions) for details.\n\n:::\n\n## eslint.enable\n\n`boolean = true`\n\nWhether or not ESLint is enabled.\n\n## eslint.mode\n\n`'extends' | 'file' = 'extends'`\n\nSee [override modes](./getting-started.md#override-modes).\n\n## eslint.configure\n\n`ESLintConfig` or `(config: ESLintConfig, { env, paths }) => ESLintConfig`\n\nAny ESLint configuration options: https://eslint.org/docs/latest/user-guide/configuring/\n\n## eslint.pluginOptions\n\n`ESLintPluginOptions` or `(options: ESLintPluginOptions, { env, paths }) => ESLintPluginOptions`\n\nAny ESLint plugin configuration options: https://github.com/webpack-contrib/eslint-webpack-plugin#options\n"
  },
  {
    "path": "website/docs/configuration/getting-started.md",
    "content": "---\ndescription: Setting up the configuration file\n---\n\n# Getting Started\n\n## Creating the file\n\nCRACO can be configured in a file with any of the following names:\n\n1. `craco.config.ts`\n2. `craco.config.js`\n3. `craco.config.cjs`\n4. `.cracorc.ts`\n5. `.cracorc.js`\n6. `.cracorc`\n\nIf multiple configuration files are found, CRACO will use the one highest on the list above. You can also [specify a file path in your `package.json` file], which will take priority over all files listed above.\n\n### Setting a custom location\n\n#### Option 1: package.json (recommended)\n\nYou can change the location of your config file by specifying a value for `cracoConfig` in your `package.json` file.\n\n```json title=\"package.json\"\n{\n  \"cracoConfig\": \"config/craco-config-with-custom-name.js\"\n}\n```\n\n#### Option 2: CLI (for backward compatibility)\n\nYou can change the location of your config file by specifying a file path with the `--config` CLI option.\n\n```json title=\"package.json\"\n{\n  \"scripts\": {\n    \"start\": \"craco start --config config/craco-config-with-custom-name.js\"\n  }\n}\n```\n\n:::caution\n\nThe CLI option doesn't support Babel with Jest.\n\n:::\n\n## Configuration tips\n\n### Object literals and functions\n\nMany config override properties in the CRACO config can be assigned either one of two things:\n\n- an **object literal**, which will be merged with the original config\n\n  ```js title=\"craco.config.js (example)\"\n  module.exports = {\n    webpack: {\n      configure: {\n        entry: './path/to/my/entry/file.js',\n      },\n    },\n  };\n  ```\n\n- a **function** that takes in the original config as the first argument (and optionally a [context object](#context-object--env-paths-)) and returns the new config\n\n  ```js title=\"craco.config.js (example)\"\n  module.exports = {\n    webpack: {\n      configure: (webpackConfig, { env, paths }) => {\n        webpackConfig.entry = './path/to/my/entry/file.js';\n        return webpackConfig;\n      },\n    },\n  };\n  ```\n\nConfiguration outlines within this documentation will show both of these options as two properties with the same name (for example, two properties named `configure` where one is an object literal and the other is a function).\n\n### Context object (`{ env, paths }`)\n\nThe function version of config override properties accepts an optional second argument, which is a single object containing the following properties:\n\n- `env` - the current NODE_ENV (development, production, etc.)\n- `paths` - an object that contains all the paths used by CRA\n\nSome configuration sections, like [`jest.configure`](./jest.md#jestconfigure) and [`devServer`](./devserver.md#devserver-1), include extra properties in their context object.\n\n### Override modes\n\nSome sections have a `mode` property, which can be assigned one of two values:\n\n- `extends` - the provided configuration will extend the CRA settings (**default**)\n- `file` - the CRA settings will be reset and you'll need to provide an official configuration file for the plugin that will supersede any settings\n\n## Configuration helpers\n\n### when\n\n```js title=\"craco.config.js (example)\"\nmodule.exports = {\n  eslint: {\n    mode: 'file',\n    configure: {\n      formatter: when(\n        process.env.NODE_ENV === 'CI',\n        require('eslint-formatter-vso')\n      ),\n    },\n  },\n  webpack: {\n    plugins: [\n      new ConfigWebpackPlugin(),\n      ...whenDev(() => [new CircularDependencyPlugin()], []),\n    ],\n  },\n};\n```\n\n#### `when(condition, fn, [unmetValue])`\n\n`when<T>(condition: boolean, fn: () => T, unmetValue?: T): T | undefined`\n\nIf `condition` evaluates to true, `fn` is called and the helper will return what that function returns. If false, `unmetValue` will be returned (or `undefined` if not provided).\n\n#### `whenDev(fn, [unmetValue])`\n\n`whenDev<T>(fn: () => T, unmetValue?: T): T | undefined`\n\nEquivalent to `when(process.env.NODE_ENV === 'development', fn, unmetValue)`.\n\n#### `whenProd(fn, [unmetValue])`\n\n`whenProd<T>(fn: () => T, unmetValue?: T): T | undefined`\n\nEquivalent to `when(process.env.NODE_ENV === 'production', fn, unmetValue)`.\n\n#### `whenTest(fn, [unmetValue])`\n\n`whenTest<T>(fn: () => T, unmetValue?: T): T | undefined`\n\nEquivalent to `when(process.env.NODE_ENV === 'test', fn, unmetValue)`.\n\n## Exporting your configuration\n\nYou can export your configuration in a variety of ways.\n\n:::tip\n\nThe function options will be called with an object containing the current environment variables (for example, `NODE_ENV`).\n\n:::\n\n### Object literal\n\n```js title=\"craco.config.js\"\nmodule.exports = {\n  ...\n};\n```\n\n### Function\n\n```js title=\"craco.config.js\"\nmodule.exports = function ({ env }) {\n  return {\n    ...\n  };\n};\n```\n\n### Promise or Async Function\n\n```js title=\"craco.config.js\"\nmodule.exports = async function ({ env }) {\n  await ...;\n\n  return {\n    ...\n  };\n};\n```\n\n## Using a custom `react-scripts` package\n\nIf you're using a fork of Create React App's `react-scripts` package, you can specify the name in your configuration so CRACO knows where the scripts are. If this property is omitted, CRACO defaults to `react-scripts`.\n\n```js title=\"craco.config.js\"\nmodule.exports = {\n  // ...\n  reactScriptsVersion: 'custom-react-scripts-package',\n};\n```\n"
  },
  {
    "path": "website/docs/configuration/jest.md",
    "content": "---\ndescription: Customize Jest\n---\n\n# Jest\n\n<!-- prettier-ignore -->\n```js title=\"craco.config.js\"\nmodule.exports = {\n  // ...\n  jest: {\n    babel: {\n      addPresets: true /* (default value) */,\n      addPlugins: true /* (default value) */,\n    },\n    configure: { /* ... */ },\n    configure: (jestConfig, { env, paths, resolve, rootDir }) => {\n      /* ... */\n      return jestConfig;\n    },\n  },\n};\n```\n\n:::tip\n\nProperties listed twice in the outline above (for example, `configure`) can be assigned an **object literal** or a **function**. See [configuration tips](./getting-started.md#object-literals-and-functions) for details.\n\n:::\n\n## jest.babel\n\nConfiguration options for the `babel-jest` transformer: https://jestjs.io/docs/code-transformation\n\n### jest.babel.addPresets\n\n`boolean = true`\n\nWhether or not Babel presets should be added.\n\n### jest.babel.addPlugins\n\n`boolean = true`\n\nWhether or not Babel plugins should be added.\n\n## jest.configure\n\n`JestConfig` or `(config: JestConfig, { env, paths, resolve, rootDir }) => JestConfig`\n\nAny Jest configuration options: https://jestjs.io/docs/configuration\n\nThe function version of `configure` provides two extra properties within the [context object](./getting-started.md#context-object--env-paths-):\n\n- `resolve` - provided by CRA\n- `rootDir` - provided by CRA\n"
  },
  {
    "path": "website/docs/configuration/plugins.md",
    "content": "---\ndescription: Include third-party CRACO plugins\n---\n\n# CRACO Plugins\n\nView a list of [community maintained plugins](/plugins) or [develop your own](../plugin-api/getting-started.md).\n\n<!-- prettier-ignore -->\n```js title=\"craco.config.js\"\nmodule.exports = {\n  // ...\n  plugins: [\n    {\n      plugin: require('some-craco-plugin'),\n      options: { /* ... */ },\n    },\n    // ...\n  ],\n};\n```\n"
  },
  {
    "path": "website/docs/configuration/style.md",
    "content": "---\ndescription: Customize CSS preprocessors\n---\n\n# Style\n\n<!-- prettier-ignore -->\n```js title=\"craco.config.js\"\nmodule.exports = {\n  // ...\n  style: {\n    modules: {\n      localIdentName: '',\n    },\n    css: {\n      loaderOptions: { /* ... */ },\n      loaderOptions: (cssLoaderOptions, { env, paths }) => {\n        /* ... */\n        return cssLoaderOptions;\n      },\n    },\n    sass: {\n      loaderOptions: { /* ... */ },\n      loaderOptions: (sassLoaderOptions, { env, paths }) => {\n        /* ... */\n        return sassLoaderOptions;\n      },\n    },\n    postcss: {\n      mode: 'extends' /* (default value) */ || 'file',\n      plugins: [require('plugin-to-append')],\n      plugins: (plugins) => [require('plugin-to-prepend')].concat(plugins),\n      env: {\n        autoprefixer: { /* ... */ },\n        stage: 3,\n        features: { /* ... */ },\n      },\n      loaderOptions: { /* ... */ },\n      loaderOptions: (postcssLoaderOptions, { env, paths }) => {\n        /* ... */\n        return postcssLoaderOptions;\n      },\n    },\n  },\n};\n```\n\n:::tip\n\nProperties listed twice in the outline above (for example, `loaderOptions`) can be assigned an **object literal** or a **function**. See [configuration tips](./getting-started.md#object-literals-and-functions) for details.\n\n:::\n\n## style.modules\n\n### style.modules.localIdentName\n\n`string`\n\nhttps://github.com/webpack-contrib/css-loader#localidentname\n\n## style.css\n\n### style.css.loaderOptions\n\n`CSSLoaderOptions` or `(options: CSSLoaderOptions, { env, paths }) => CSSLoaderOptions`\n\nAny css-loader configuration options: https://github.com/webpack-contrib/css-loader#options\n\n## style.sass\n\n### style.sass.loaderOptions\n\n`SASSLoaderOptions` or `(options: SASSLoaderOptions, { env, paths }) => SASSLoaderOptions`\n\nAny sass-loader configuration options: https://github.com/webpack-contrib/sass-loader#options\n\n## style.postcss\n\n### style.postcss.mode\n\n`'extends' | 'file' = 'extends'`\n\nSee [override modes](./getting-started.md#override-modes).\n\n### style.postcss.plugins\n\n`[PostCSSPlugin]` or `(plugins: [PostCSSPlugin]) => [PostCSSPlugin]`\n\nAny PostCSS plugins: https://github.com/postcss/postcss#plugins\n\n### style.postcss.env\n\n#### style.postcss.env.autoprefixer\n\n`AutoprefixerOptions`\n\nAny autoprefixer options: https://github.com/postcss/autoprefixer#options\n\n#### style.postcss.env.stage\n\n`0 | 1 | 2 | 3 | 4`\n\nAny valid CSS stage: https://cssdb.org/#the-staging-process\n\n#### style.postcss.env.features\n\nAny CSS features: https://preset-env.cssdb.org/features/\n\n### style.postcss.loaderOptions\n\n`PostCSSLoaderOptions` or `(options: PostCSSLoaderOptions, { env, paths }) => PostCSSLoaderOptions`\n\nAny postcss-loader options: https://github.com/webpack-contrib/postcss-loader#options\n"
  },
  {
    "path": "website/docs/configuration/typescript.md",
    "content": "---\ndescription: Customize TypeScript\n---\n\n# TypeScript\n\n<!-- prettier-ignore -->\n```js title=\"craco.config.js\"\nmodule.exports = {\n  // ...\n  typescript: {\n    enableTypeChecking: true /* (default value) */,\n  },\n};\n```\n\n## typescript.enableTypeChecking\n\n`boolean = true`\n\nWhether or not TypeScript type checking is enabled.\n"
  },
  {
    "path": "website/docs/configuration/webpack.md",
    "content": "---\ndescription: Customize Webpack\n---\n\n# Webpack\n\n<!-- prettier-ignore -->\n```js title=\"craco.config.js\"\nmodule.exports = {\n  // ...\n  webpack: {\n    alias: { /* ... */ },\n    plugins: {\n      add: [ /* ... */ ],\n      remove: [ /* ... */ ],\n    },\n    configure: { /* ... */},\n    configure: (webpackConfig, { env, paths }) => {\n      /* ... */\n      return webpackConfig;\n    },\n  },\n};\n```\n\n:::tip\n\nProperties listed twice in the outline above (for example, `configure`) can be assigned an **object literal** or a **function**. See [configuration tips](./getting-started.md#object-literals-and-functions) for details.\n\n:::\n\n## webpack.alias\n\n`object`\n\nSee https://webpack.js.org/configuration/resolve/#resolvealias.\n\n## webpack.plugins\n\n### webpack.plugins.add\n\n`[WebpackPlugin | [WebpackPlugin, 'append' | 'prepend']]`\n\nAn array of Webpack plugins to add: https://webpack.js.org/plugins/\n\nYou can specify whether or not each plugin is appended or prepended to the existing list of Webpack plugins. If not specified, the default is to prepend. Check out the following example:\n\n```js title=\"craco.config.js\"\nconst CopyPlugin = require('copy-webpack-plugin');\nconst ESLintPlugin = require('eslint-webpack-plugin');\nconst HtmlPlugin = require('html-webpack-plugin');\n\nmodule.exports = {\n  webpack: {\n    plugins: {\n      add: [\n        new CopyPlugin() /* this plugin will be prepended */,\n        [new ESLintPlugin(), 'prepend'] /* this one, too */,\n        [new HtmlPlugin(), 'append'] /* not this one though */,\n      ],\n    },\n  },\n};\n```\n\n### webpack.plugins.remove\n\n`[string]`\n\nAn array of plugin constructor names to remove.\n\n## webpack.configure\n\n`WebpackConfig` or `(config: WebpackConfig, { env, paths }) => WebpackConfig`\n\nAny Webpack configuration options: https://webpack.js.org/configuration/\n"
  },
  {
    "path": "website/docs/configuration-api.md",
    "content": "# Configuration API\n\nTo integrate with other tools, it's useful to have access to the configuration generated by CRACO.\n\nThe CRACO Configuration API supports Jest and Webpack.\n\n## Jest\n\n`createJestConfig(cracoConfig, context = {}, options = { verbose: false, config: null })`\n\nA [CRACO config](./configuration/getting-started.md), a [JEST context object](./configuration/jest.md#jestconfigure), and an options object (`{ verbose?: boolean, config?: string }`) are taken as arguments and the generated Jest config object is returned.\n\n:::note\n\n`createJestConfig` does **not** accept `cracoConfig` as a function. If your `craco.config.js` exposes a config function, you have to call it yourself before using it here.\n\n:::\n\n```js title=\"jest.config.js (example)\"\nconst { createJestConfig } = require('@craco/craco');\n\nconst cracoConfig = require('./craco.config.js');\nconst jestConfig = createJestConfig(cracoConfig);\n\nmodule.exports = jestConfig;\n```\n\n## Webpack\n\n`createWebpackDevConfig(cracoConfig, context = {}, options = { verbose: false, config: null })`\n\n`createWebpackProdConfig(cracoConfig, context = {}, options = { verbose: false, config: null })`\n\n:::note\n\n`createWebpackDevConfig` and `createWebpackProdConfig` do **not** accept `cracoConfig` as a function. If your `craco.config.js` exposes a config function, you have to call it yourself before using it here.\n\n:::\n\n```js title=\"webpack.config.js (example)\"\nconst { createWebpackDevConfig } = require('@craco/craco');\n\nconst cracoConfig = require('./craco.config.js');\nconst webpackConfig = createWebpackDevConfig(cracoConfig);\n\nmodule.exports = webpackConfig;\n```\n"
  },
  {
    "path": "website/docs/getting-started.md",
    "content": "# Getting Started\n\n:::info\n\nThe current **CRACO** version requires **Create React App 5** (`react-scripts 5.x.x`). If using an older version of CRA, [use the appropriate version of CRACO](#backward-compatibility).\n\n:::\n\n## Set up CRACO\n\n1. Install the latest version of the package from npm as a dev dependency:\n\n   ```\n   npm i -D @craco/craco\n   ```\n\n2. Create a CRACO configuration file in your project's root directory and [configure](./configuration/getting-started.md):\n\n   ```diff\n     my-app\n     ├── node_modules\n   + ├── craco.config.js\n     └── package.json\n   ```\n\n3. Update the existing calls to `react-scripts` in the `scripts` section of your `package.json` to use the `craco` CLI:\n\n   ```diff title=\"package.json\"\n   \"scripts\": {\n   -  \"start\": \"react-scripts start\"\n   +  \"start\": \"craco start\"\n   -  \"build\": \"react-scripts build\"\n   +  \"build\": \"craco build\"\n   -  \"test\": \"react-scripts test\"\n   +  \"test\": \"craco test\"\n   }\n   ```\n\nYou can now start or build your app like normal:\n\n```\nnpm start\n```\n\n```\nnpm run build\n```\n\n## Start configuring\n\nCheck out the [configuration documentation](./configuration/getting-started.md).\n\n## TypeScript support\n\nCRACO provides official typings that you can use if you'd like type checking and IDE autocompletion in your configuration file:\n\n```\nnpm i -D @craco/types\n```\n\n## Backward compatibility\n\nCRACO is not meant to be backward compatible with older versions of Create React App and will only support the latest version. If your project uses an old version (which can be determined by the version of the `react-scripts` dependency in your project), refer to the following table to select the appropriate CRACO version.\n\n| react-scripts version | CRACO version |\n| --------------------- | ------------- |\n| 5.x.x (latest)        | 7.0.0         |\n| 4.x.x                 | 6.4.5         |\n| < 4.0.0               | 5.8.0         |\n\n## Debugging\n\n### Verbose logging\n\nTo activate verbose logging, specify the CLI option `--verbose`\n\n```json title=\"package.json\"\n{\n  \"scripts\": {\n    \"start\": \"craco start --verbose\"\n  }\n}\n```\n"
  },
  {
    "path": "website/docs/plugin-api/getting-started.md",
    "content": "---\ndescription: Get started with CRACO plugin development\n---\n\n# Getting Started\n\nCRACO has a nice plugin API. You can view a list of [community maintained plugins](/plugins) or develop your own.\n\n## Develop a plugin\n\nCRACO provides a bunch of [hooks](./hooks.md) and [utility functions](../../category/utility-functions) to make plugin development easy. A plugin is structured using the four hooks (all are optional):\n\n```js title=\"craco-example-plugin.js\"\nmodule.exports = {\n  overrideCracoConfig: ({ cracoConfig, pluginOptions, context }) => {\n    /* ... */\n    return cracoConfig;\n  },\n\n  overrideWebpackConfig: ({\n    webpackConfig,\n    cracoConfig,\n    pluginOptions,\n    context,\n  }) => {\n    /* ... */\n    return webpackConfig;\n  },\n\n  overrideDevServerConfig: ({\n    devServerConfig,\n    cracoConfig,\n    pluginOptions,\n    context,\n  }) => {\n    /* ... */\n    return devServerConfig;\n  },\n\n  overrideJestConfig: ({ jestConfig, cracoConfig, pluginOptions, context }) => {\n    /* ... */\n    return jestConfig;\n  },\n};\n```\n\n:::note\n\nNotice how all hooks only accept a single object as an argument. The outline above destructures each object.\n\n:::\n\n:::caution important\n\nAll functions must return the updated configuration object.\n\n:::\n\nGet started by checking out the documentation for [hooks](./hooks.md).\n"
  },
  {
    "path": "website/docs/plugin-api/hooks.md",
    "content": "---\ndescription: Hooks available to CRACO plugins\n---\n\n# Hooks\n\nThere are four hooks available to a plugin:\n\n- [`overrideCracoConfig`](#overridecracoconfig) - customize the CRACO config object **before** it is processed by CRACO\n- [`overrideWebpackConfig`](#overridewebpackconfig) - customize the Webpack config **after** it is processed by CRACO\n- [`overrideDevServerConfig`](#overridedevserverconfig) - customize the DevServer config **after** it is processed by CRACO\n- [`overrideJestConfig`](#overridejestconfig) - customize the Jest config **after** it is processed by CRACO\n\n:::caution important\n\nEvery function **must** return the updated configuration object.\n\n:::\n\n## overrideCracoConfig\n\n`overrideCracoConfig(data): CracoConfig`\n\n`data` is an object with the following structure:\n\n| Property        | Description                                                                                                     |\n| --------------- | --------------------------------------------------------------------------------------------------------------- |\n| `cracoConfig`   | The config object read from the [CRACO config](../configuration/getting-started.md) provided by the consumer    |\n| `pluginOptions` | The plugin options provided by the consumer                                                                     |\n| `context`       | A [context object](../configuration/getting-started.md#context-object--env-paths-) containing `env` and `paths` |\n\nThis function must return a valid [CRACO config](../configuration/getting-started.md).\n\n<details>\n  <summary>Example</summary>\n\n```js title=\"craco-log-plugin.js\"\nmodule.exports = {\n  overrideCracoConfig: ({\n    cracoConfig,\n    pluginOptions,\n    context: { env, paths },\n  }) => {\n    if (pluginOptions.preText) {\n      console.log(pluginOptions.preText);\n    }\n\n    console.log(JSON.stringify(cracoConfig, null, 4));\n\n    return cracoConfig;\n  },\n};\n```\n\n```js title=\"craco.config.js\"\nconst logPlugin = require('./craco-log-plugin');\n\nmodule.exports = {\n  // ...\n  plugins: [\n    {\n      plugin: logPlugin,\n      options: { preText: 'CRACO CONFIG' },\n    },\n  ],\n};\n```\n\n</details>\n\n## overrideWebpackConfig\n\n`overrideWebpackConfig(data): WebpackConfig`\n\n`data` is an object with the following structure:\n\n| Property        | Description                                                                                                     |\n| --------------- | --------------------------------------------------------------------------------------------------------------- |\n| `webpackConfig` | The [Webpack config](https://webpack.js.org/configuration/) object already customized by CRACO                  |\n| `cracoConfig`   | The config object read from the [CRACO config](../configuration/getting-started.md) provided by the consumer    |\n| `pluginOptions` | The plugin options provided by the consumer                                                                     |\n| `context`       | A [context object](../configuration/getting-started.md#context-object--env-paths-) containing `env` and `paths` |\n\nThis function must return a valid [Webpack config](https://webpack.js.org/configuration/).\n\n<details>\n  <summary>Example</summary>\n\n```js title=\"craco-log-plugin.js\"\nmodule.exports = {\n  overrideWebpackConfig: ({\n    webpackConfig,\n    cracoConfig,\n    pluginOptions,\n    context: { env, paths },\n  }) => {\n    if (pluginOptions.preText) {\n      console.log(pluginOptions.preText);\n    }\n\n    console.log(JSON.stringify(webpackConfig, null, 4));\n\n    return webpackConfig;\n  },\n};\n```\n\n```js title=\"craco.config.js\"\nconst logPlugin = require('./craco-log-plugin');\n\nmodule.exports = {\n  // ...\n  plugins: [\n    {\n      plugin: logPlugin,\n      options: { preText: 'WEBPACK CONFIG' },\n    },\n  ],\n};\n```\n\n</details>\n\n## overrideDevServerConfig\n\n`overrideDevServerConfig(data): DevServerConfig`\n\n`data` is an object with the following structure:\n\n| Property          | Description                                                                                                                                                                                       |\n| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `devServerConfig` | The [DevServer config](https://webpack.js.org/configuration/dev-server/#devserver) object already customized by CRACO                                                                             |\n| `cracoConfig`     | The config object read from the [CRACO config](../configuration/getting-started.md) provided by the consumer                                                                                      |\n| `pluginOptions`   | The plugin options provided by the consumer                                                                                                                                                       |\n| `context`         | A [context object](../configuration/getting-started.md#context-object--env-paths-) ([DevServer-specific](../configuration/devserver.md#devserver-1)) containing `env`, `paths`, and `allowedHost` |\n\nThis function must return a valid [DevServer config](https://webpack.js.org/configuration/dev-server/#devserver).\n\n<details>\n  <summary>Example</summary>\n\n```js title=\"craco-log-plugin.js\"\nmodule.exports = {\n  overrideDevServerConfig: ({\n    devServerConfig,\n    cracoConfig,\n    pluginOptions,\n    context: { env, paths, allowedHost },\n  }) => {\n    if (pluginOptions.preText) {\n      console.log(pluginOptions.preText);\n    }\n\n    console.log(JSON.stringify(devServerConfig, null, 4));\n\n    return devServerConfig;\n  },\n};\n```\n\n```js title=\"craco.config.js\"\nconst logPlugin = require('./craco-log-plugin');\n\nmodule.exports = {\n  // ...\n  plugins: [\n    {\n      plugin: logPlugin,\n      options: { preText: 'DEVSERVER CONFIG' },\n    },\n  ],\n};\n```\n\n</details>\n\n## overrideJestConfig\n\n`overrideJestConfig(data): JestConfig`\n\n`data` is an object with the following structure:\n\n| Property        | Description                                                                                                                                                                                      |\n| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| `jestConfig`    | The [Jest config](https://jestjs.io/docs/configuration) object already customized by CRACO                                                                                                       |\n| `cracoConfig`   | The config object read from the [CRACO config](../configuration/getting-started.md) provided by the consumer                                                                                     |\n| `pluginOptions` | The plugin options provided by the consumer                                                                                                                                                      |\n| `context`       | A [context object](../configuration/getting-started.md#context-object--env-paths-) ([Jest-specific](../configuration/jest.md#jestconfigure)) containing `env`, `paths`, `resolve`, and `rootDir` |\n\nThis function must return a valid [Jest config](https://jestjs.io/docs/configuration).\n\n<details>\n  <summary>Example</summary>\n\n```js title=\"craco-log-plugin.js\"\nmodule.exports = {\n  overrideJestConfig: ({\n    jestConfig,\n    cracoConfig,\n    pluginOptions,\n    context: { env, paths, resolve, rootDir },\n  }) => {\n    if (pluginOptions.preText) {\n      console.log(pluginOptions.preText);\n    }\n\n    console.log(JSON.stringify(jestConfig, null, 4));\n\n    return jestConfig;\n  },\n};\n```\n\n```js title=\"craco.config.js\"\nconst logPlugin = require('./craco-log-plugin');\n\nmodule.exports = {\n  // ...\n  plugins: [\n    {\n      plugin: logPlugin,\n      options: { preText: 'JEST CONFIG' },\n    },\n  ],\n};\n```\n\n</details>\n"
  },
  {
    "path": "website/docs/plugin-api/utility-functions/miscellaneous.md",
    "content": "# Miscellaneous\n\nOther useful utility functions\n\n```js\nconst { throwUnexpectedConfigError } = require('@craco/craco');\n```\n\n## Functions\n\n### throwUnexpectedConfigError\n\n`throwUnexpectedConfigError(options)`\n\nRaises an error and crashes Node.js.\n\n`options` should be an object with the following structure:\n\n| Property           | Description                                 | Type / Format         | Required |\n| ------------------ | ------------------------------------------- | --------------------- | -------- |\n| `message`          | An error message explaining what went wrong | string                | Yes      |\n| `packageName`      | npm package name                            | string                | No       |\n| `githubRepo`       | GitHub repo where people can open an issue  | string: username/repo | No       |\n| `githubIssueQuery` | Search string to find related issues        | string                | No       |\n\n:::tip\n\nThrow an error if the configuration changes and does not match your expectations. (For example, `getLoader` cannot find a loader and `isFound` is false.) Create React App might update the structure of their webpack config, so it is very important to show a helpful error message when something breaks.\n\n:::\n\n#### Example\n\n```\n$ yarn start\nyarn run v1.12.3\n$ craco start\n/path/to/your/app/craco.config.js:23\n            throw new Error(\n            ^\n\n    Error: Can't find eslint-loader in the webpack config!\n\n    This error probably occurred because you updated react-scripts or craco. Please try updating craco-less to the latest version:\n\n       $ yarn upgrade craco-less\n\n    Or:\n\n       $ npm update craco-less\n\n    If that doesn't work, craco-less needs to be fixed to support the latest version.\n    Please check to see if there's already an issue in the ndbroadbent/craco-less repo:\n\n       * https://github.com/DocSpring/craco-less/issues?q=is%3Aissue+webpack+eslint-loader\n\n    If not, please open an issue and we'll take a look. (Or you can send a PR!)\n\n    You might also want to look for related issues in the craco and create-react-app repos:\n\n       * https://github.com/dilanx/craco/issues?q=is%3Aissue+webpack+eslint-loader\n       * https://github.com/facebook/create-react-app/issues?q=is%3Aissue+webpack+eslint-loader\n\n    at throwUnexpectedConfigError (/path/to/your/app/craco.config.js:23:19)\n    ...\n```\n\n#### Usage\n\n```js\nconst {\n  getLoader,\n  loaderByName,\n  throwUnexpectedConfigError,\n} = require('@craco/craco');\n\n// Create a helper function if you need to call this multiple times\nconst throwError = (message, githubIssueQuery) =>\n  throwUnexpectedConfigError({\n    packageName: 'craco-less',\n    githubRepo: 'ndbroadbent/craco-less',\n    message,\n    githubIssueQuery,\n  });\n\nconst { isFound, match } = getLoader(\n  webpackConfig,\n  loaderByName('eslint-loader')\n);\n\nif (!isFound) {\n  throwError(\n    \"Can't find eslint-loader in the webpack config!\",\n    'webpack+eslint-loader'\n  );\n}\n```\n"
  },
  {
    "path": "website/docs/plugin-api/utility-functions/webpack-asset-modules.md",
    "content": "# Webpack Asset Modules\n\nUtility functions for [Webpack asset modules](https://webpack.js.org/guides/asset-modules/)\n\n```js\nconst {\n  assetModuleByName,\n  getAssetModule,\n  getAssetModules,\n  addBeforeAssetModule,\n  addBeforeAssetModules,\n  addAfterAssetModule,\n  addAfterAssetModules,\n  removeAssetModules,\n} = require('@craco/craco');\n```\n\n## Functions\n\n### assetModuleByName\n\n`assetModuleByName(targetAssetModuleName: string): AssetModuleMatcher`\n\nReturns an [asset module matcher](#assetmodulematcher) function to be used with other asset module utility functions to match a name to an existing asset module.\n\n### getAssetModule\n\n`getAssetModule(webpackConfig: WebpackConfig, matcher: AssetModuleMatcher)`\n\nRetrieve the **first** asset module for which the matcher returns true from the Webpack config.\n\n#### Return Type\n\n```\n{\n  isFound: boolean;\n  match: {\n    rule: Rule;\n    index: number;\n  }\n}\n```\n\n#### Usage\n\n```js\nconst { getAssetModule, assetModuleByName } = require('@craco/craco');\n\nconst { isFound, match } = getAssetModule(\n  webpackConfig,\n  assetModuleByName('asset/source')\n);\n\nif (isFound) {\n  // do stuff...\n}\n```\n\n### getAssetModules\n\n`getAssetModules(webpackConfig: WebpackConfig, matcher: AssetModuleMatcher)`\n\nRetrieve **all** of the asset modules for which the matcher returns true from the Webpack config.\n\n#### Return Type\n\n```\n{\n  hasFoundAny: boolean;\n  matches: [\n    {\n      rule: Rule;\n      index: number;\n    }\n  ]\n}\n```\n\n#### Usage\n\n```js\nconst { getAssetModules, assetModuleByName } = require('@craco/craco');\n\nconst { hasFoundAny, matches } = getAssetModules(\n  webpackConfig,\n  assetModuleByName('asset/inline')\n);\n\nif (hasFoundAny) {\n  matches.forEach((x) => {\n    // do stuff...\n  });\n}\n```\n\n### addBeforeAssetModule\n\n`addBeforeAssetModule(webpackConfig: WebpackConfig, matcher: AssetModuleMatcher, newAssetModule: Rule)`\n\nAdd a new asset module **before** the asset module for which the matcher returns true in the Webpack config.\n\n#### Return Type\n\n```\n{\n  isAdded: boolean;\n}\n```\n\n#### Usage\n\n```js\nconst { addBeforeAssetModule, assetModuleByName } = require('@craco/craco');\n\nconst myNewWebpackAssetModule = {\n  test: /\\.png/,\n  type: 'asset/resource',\n};\n\naddBeforeAssetModule(\n  webpackConfig,\n  assetModuleByName('asset/source'),\n  myNewWebpackAssetModule\n);\n```\n\n### addBeforeAssetModules\n\n`addBeforeAssetModules(webpackConfig: WebpackConfig, matcher: AssetModuleMatcher, newAssetModule: Rule)`\n\nAdd a new asset module **before all** of the asset modules for which the matcher returns true in the Webpack config.\n\n#### Return Type\n\n```\n{\n  isAdded: boolean;\n  addedCount: number;\n}\n```\n\n#### Usage\n\n```js\nconst { addBeforeAssetModules, assetModuleByName } = require('@craco/craco');\n\nconst myNewWebpackAssetModule = {\n  test: /\\.png/,\n  type: 'asset/resource',\n};\n\naddBeforeAssetModules(\n  webpackConfig,\n  assetModuleByName('asset/source'),\n  myNewWebpackAssetModule\n);\n```\n\n### addAfterAssetModule\n\n`addAfterAssetModule(webpackConfig: WebpackConfig, matcher: AssetModuleMatcher, newAssetModule: Rule)`\n\nAdd a new asset module **after** the asset module for which the matcher returns true in the Webpack config.\n\n#### Return Type\n\n```\n{\n  isAdded: boolean;\n}\n```\n\n#### Usage\n\n```js\nconst { addAfterAssetModule, assetModuleByName } = require('@craco/craco');\n\nconst myNewWebpackAssetModule = {\n  test: /\\.png/,\n  type: 'asset/resource',\n};\n\naddAfterAssetModule(\n  webpackConfig,\n  assetModuleByName('asset/source'),\n  myNewWebpackAssetModule\n);\n```\n\n### addAfterAssetModules\n\n`addAfterAssetModules(webpackConfig: WebpackConfig, matcher: AssetModuleMatcher, newAssetModule: Rule)`\n\nAdd a new asset module **after all** of the asset modules for which the matcher returns true in the Webpack config.\n\n#### Return Type\n\n```\n{\n  isAdded: boolean;\n  addedCount: number;\n}\n```\n\n#### Usage\n\n```js\nconst { addAfterAssetModules, assetModuleByName } = require('@craco/craco');\n\nconst myNewWebpackAssetModule = {\n  test: /\\.png/,\n  type: 'asset/resource',\n};\n\naddAfterAssetModules(\n  webpackConfig,\n  assetModuleByName('asset/source'),\n  myNewWebpackAssetModule\n);\n```\n\n### removeAssetModules\n\n`removeAssetModules(webpackConfig: WebpackConfig, matcher: AssetModuleMatcher)`\n\nRemove **all** of the asset modules for which the matcher returns true from the Webpack config.\n\n#### Return Type\n\n```\n{\n  hasRemovedAny: boolean;\n  removedCount: number;\n}\n```\n\n#### Usage\n\n```js\nconst { removeAssetModules, assetModuleByName } = require('@craco/craco');\n\nremoveAssetModules(webpackConfig, assetModuleByName('asset/source'));\n```\n\n## Reference\n\n### WebpackConfig\n\nSee https://webpack.js.org/configuration/.\n\n### AssetModuleMatcher\n\nAn asset module matcher should return true if the provided asset module (within a rule) matches the specified criteria. The function is of the following type:\n\n```\n(rule: Rule) => boolean;\n```\n\n### Rule\n\nSee https://webpack.js.org/configuration/module/#rule.\n\n###\n"
  },
  {
    "path": "website/docs/plugin-api/utility-functions/webpack-loaders.md",
    "content": "# Webpack Loaders\n\nUtility functions for [Webpack loaders](https://webpack.js.org/loaders/)\n\n```js\nconst {\n  loaderByName,\n  getLoader,\n  getLoaders,\n  addBeforeLoader,\n  addBeforeLoaders,\n  addAfterLoader,\n  addAfterLoaders,\n  removeLoaders,\n} = require('@craco/craco');\n```\n\n## Functions\n\n### loaderByName\n\n`loaderByName(targetLoaderName: string): LoaderMatcher`\n\nReturns a [loader matcher](#loadermatcher) function to be used with other loader utility functions to match a name to an existing loader.\n\n### getLoader\n\n`getLoader(webpackConfig: WebpackConfig, matcher: LoaderMatcher)`\n\nRetrieve the **first** loader for which the matcher returns true from the Webpack config.\n\n#### Return Type\n\n```\n{\n  isFound: boolean;\n  match: {\n    loader: Rule;\n    parent: Rule[];\n    index: number;\n  }\n}\n```\n\n#### Usage\n\n```js\nconst { getLoader, loaderByName } = require('@craco/craco');\n\nconst { isFound, match } = getLoader(\n  webpackConfig,\n  loaderByName('eslint-loader')\n);\n\nif (isFound) {\n  // do stuff...\n}\n```\n\n### getLoaders\n\n`getLoaders(webpackConfig: WebpackConfig, matcher: LoaderMatcher)`\n\nRetrieve **all** of the loaders for which the matcher returns true from the Webpack config.\n\n#### Return Type\n\n```\n{\n  hasFoundAny: boolean;\n  matches: [\n    {\n      loader: Rule;\n      parent: Rule[];\n      index: number;\n    }\n  ]\n}\n```\n\n#### Usage\n\n```js\nconst { getLoaders, loaderByName } = require('@craco/craco');\n\nconst { hasFoundAny, matches } = getLoaders(\n  webpackConfig,\n  loaderByName('babel-loader')\n);\n\nif (hasFoundAny) {\n  matches.forEach((x) => {\n    // do stuff...\n  });\n}\n```\n\n### addBeforeLoader\n\n`addBeforeLoader(webpackConfig: WebpackConfig, matcher: LoaderMatcher, newLoader: Rule)`\n\nAdd a new loader **before** the loader for which the matcher returns true in the Webpack config.\n\n#### Return Type\n\n```\n{\n  isAdded: boolean;\n}\n```\n\n#### Usage\n\n```js\nconst { addBeforeLoader, loaderByName } = require('@craco/craco');\n\nconst myNewWebpackLoader = {\n  loader: require.resolve('tslint-loader'),\n};\n\naddBeforeLoader(\n  webpackConfig,\n  loaderByName('eslint-loader'),\n  myNewWebpackLoader\n);\n```\n\n### addBeforeLoaders\n\n`addBeforeLoaders(webpackConfig: WebpackConfig, matcher: LoaderMatcher, newLoader: Rule)`\n\nAdd a new loader **before all** of the loaders for which the matcher returns true in the Webpack config.\n\n#### Return Type\n\n```\n{\n  isAdded: boolean;\n  addedCount: number;\n}\n```\n\n#### Usage\n\n```js\nconst { addBeforeLoaders, loaderByName } = require('@craco/craco');\n\nconst myNewWebpackLoader = {\n  loader: require.resolve('tslint-loader'),\n};\n\naddBeforeLoaders(\n  webpackConfig,\n  loaderByName('eslint-loader'),\n  myNewWebpackLoader\n);\n```\n\n### addAfterLoader\n\n`addAfterLoader(webpackConfig: WebpackConfig, matcher: LoaderMatcher, newLoader: Rule)`\n\nAdd a new loader **after** the loader for which the matcher returns true in the Webpack config.\n\n#### Return Type\n\n```\n{\n  isAdded: boolean;\n}\n```\n\n#### Usage\n\n```js\nconst { addAfterLoader, loaderByName } = require('@craco/craco');\n\nconst myNewWebpackLoader = {\n  loader: require.resolve('tslint-loader'),\n};\n\naddAfterLoader(\n  webpackConfig,\n  loaderByName('eslint-loader'),\n  myNewWebpackLoader\n);\n```\n\n### addAfterLoaders\n\n`addAfterLoaders(webpackConfig: WebpackConfig, matcher: LoaderMatcher, newLoader: Rule)`\n\nAdd a new loader **after all** of the loaders for which the matcher returns true in the Webpack config.\n\n#### Return Type\n\n```\n{\n  isAdded: boolean;\n  addedCount: number;\n}\n```\n\n#### Usage\n\n```js\nconst { addAfterLoaders, loaderByName } = require('@craco/craco');\n\nconst myNewWebpackLoader = {\n  loader: require.resolve('tslint-loader'),\n};\n\naddAfterLoaders(\n  webpackConfig,\n  loaderByName('eslint-loader'),\n  myNewWebpackLoader\n);\n```\n\n### removeLoaders\n\n`removeLoaders(webpackConfig: WebpackConfig, matcher: LoaderMatcher)`\n\nRemove **all** of the loaders for which the matcher returns true from the Webpack config.\n\n#### Return Type\n\n```\n{\n  hasRemovedAny: boolean;\n  removedCount: number;\n}\n```\n\n#### Usage\n\n```js\nconst { removeLoaders, loaderByName } = require('@craco/craco');\n\nremoveLoaders(webpackConfig, loaderByName('eslint-loader'));\n```\n\n## Reference\n\n### WebpackConfig\n\nSee https://webpack.js.org/configuration/.\n\n### LoaderMatcher\n\nA loader matcher should return true if the provided loader (within a rule) matches the specified criteria. The function is of the following type:\n\n```\n(rule: Rule) => boolean;\n```\n\n### Rule\n\nSee https://webpack.js.org/configuration/module/#rule.\n\n###\n"
  },
  {
    "path": "website/docs/plugin-api/utility-functions/webpack-plugins.md",
    "content": "# Webpack Plugins\n\nUtility functions for [Webpack plugins](https://webpack.js.org/plugins/)\n\n```js\nconst {\n  pluginByName,\n  getPlugin,\n  addPlugins,\n  removePlugins,\n} = require('@craco/craco');\n```\n\n## Functions\n\n### pluginByName\n\n`pluginByName(targetPluginName: string): PluginMatcher`\n\nReturns a [plugin matcher](#pluginmatcher) function to be used with other plugin utility functions to match a name to an existing plugin. This name is the plugin's constructor (`plugin.constructor.name`).\n\n### getPlugin\n\n`getPlugin(webpackConfig: WebpackConfig, matcher: PluginMatcher)`\n\nRetrieve the **first** plugin for which the matcher returns true from the Webpack config.\n\n#### Return Type\n\n```\n{\n  isFound: boolean;\n  match: WebpackPlugin;\n}\n```\n\n#### Usage\n\n```js\nconst { getPlugin, pluginByName } = require('@craco/craco');\n\nconst { isFound, match } = getPlugin(\n  webpackConfig,\n  pluginByName('ESLintWebpackPlugin')\n);\n\nif (isFound) {\n  // do stuff...\n}\n```\n\n### addPlugins\n\n`addPlugins(webpackConfig: WebpackConfig, plugins: [WebpackPlugin | [WebpackPlugin, 'append' | 'prepend']]): void`\n\nAdd new plugins to the Webpack config. Plugins are added with the [same syntax used within the CRACO config](../../configuration/webpack.md#webpackpluginsadd).\n\n#### Usage\n\n```js\nconst { addPlugins } = require('@craco/craco');\n\nconst myNewWebpackPlugin = require.resolve('ESLintWebpackPlugin');\n\naddPlugins(webpackConfig, [myNewWebpackPlugin]);\naddPlugins(webpackConfig, [[myNewWebpackPlugin, 'append']]);\naddPlugins(webpackConfig, [[myNewWebpackPlugin, 'prepend']]);\n```\n\n### removePlugins\n\n`removePlugins(webpackConfig: WebpackConfig, matcher: PluginMatcher)`\n\nRemove **all** of the plugins for which the matcher returns true from the Webpack config.\n\n#### Return Type\n\n```\n{\n  hasRemovedAny: boolean;\n  removedCount: number;\n}\n```\n\n#### Usage\n\n```js\nconst { removePlugins, pluginByName } = require('@craco/craco');\n\nremovePlugins(webpackConfig, pluginByName('ESLintWebpackPlugin'));\n```\n\n## Reference\n\n### WebpackConfig\n\nSee https://webpack.js.org/configuration/.\n\n### PluginMatcher\n\nA loader matcher should return true if the provided plugin matches the specified criteria. The function is of the following type:\n\n```\n(plugin: WebpackPlugin) => boolean;\n```\n\n### WebpackPlugin\n\nSee https://webpack.js.org/plugins/.\n"
  },
  {
    "path": "website/docs/welcome.md",
    "content": "---\ntitle: Welcome\nslug: /\n---\n\n# CRACO\n\n## What is CRACO?\n\nTo customize most things when using [Create React App](https://create-react-app.dev), you can eject. However, you'll then need to maintain every configuration and script yourself, which can be a bit annoying. **CRACO**, which stands for **C**reate **R**eact **A**pp **C**onfiguration **O**verride, allows you to get all of the benefits of [Create React App](https://create-react-app.dev) without ejecting. Customize your configurations ESLint, Babel, PostCSS, and many more with just a single configuration file at the root of your project.\n\n:::caution\n\nBy doing this you're breaking the [\"guarantees\"](https://github.com/facebookincubator/create-react-app/issues/99#issuecomment-234657710) that CRA provides. That is to say, you now \"own\" the configs. **No support** will be provided. Proceed with caution.\n\n:::\n\n## About the documentation\n\nOn this site, you can find the complete documentation for CRACO. If you notice any mistakes or have something you think should be added, create an [issue](https://github.com/dilanx/craco/issues) or submit a pull request.\n\n## CRA toolchain\n\n### Introduction\n\nCreate React App is intended to allow people to get started with writing React apps quickly. It does this by packaging several key components with a solid default configuration.\n\nAfter some initial experimentation, many people find the default CRA is not quite the right fit. Yet, selecting and configuring a toolchain featuring all of the components CRA already offers is overwhelming.\n\nCRACO allows you to enjoy the recognizable project structure of CRA while changing detailed configuration settings of each component.\n\n### Notes on CRA configurations and problem solving\n\nKeep in mind that there are _some_ configuration settings available to CRA without CRACO.\n\nGetting exactly what you want may involve a combination of making changes through your CRACO configuration file and by using some of the more limited but still important settings available in CRA.\n\nBefore jumping into customizing your CRACO configuration, step back and think about each part of the problem you're trying to solve. Be sure to review these resources on the CRA configuration, as it may save you time:\n\n- [Important environment variables that configure CRA](https://create-react-app.dev/docs/advanced-configuration/)\n- [Learn about using `postbuild` commands in `package.json`](https://stackoverflow.com/questions/41495658/use-custom-build-output-folder-when-using-create-react-app/51818028#51818028)\n- [Proxying API or other requests](https://create-react-app.dev/docs/proxying-api-requests-in-development/) or [\"how to integrate CRA's dev server with a second backend\"](https://github.com/facebook/create-react-app/issues/147)\n- [Search CRACO issues for gotchas, hints, and examples](https://github.com/dilanx/craco/issues?q=is%3Aissue+sort%3Aupdated-desc)\n\n### Ejecting CRA to learn\n\nAvoiding ejecting is a major goal for many CRACO users. However, if you're still learning toolchains and modern frontend workflows, it may be helpful to create a sample ejected CRA project to see how the default CRA app configures each of the components.\n\nWhile CRACO's default configuration inherits directly from CRA's default settings, seeing the default CRA config files throughout the ejected CRA file structure may give you useful perspective.\n\nYou may even want to try testing a change in the ejected app to better understand how it would be done with your CRACO-based project.\n\n## Acknowledgements\n\n- Thanks to [@gsoft-inc](https://github.com/gsoft-inc), the original creator of CRACO, who then passed the project off to me. Specifically, a big shout out to [@patricklafrance](https://github.com/patricklafrance).\n- Thanks to [@timarney](https://github.com/timarney), the creator of [react-app-rewired](https://github.com/timarney/react-app-rewired), for his original idea.\n\n## License\n\nCopyright © 2022 Dilan Nair.\n\nThis code is licensed under the Apache License 2.0, which can be viewed [here](https://github.com/dilanx/craco/blob/main/packages/craco/LICENSE).\n"
  },
  {
    "path": "website/docusaurus.config.js",
    "content": "// @ts-check\n// Note: type annotations allow type checking and IDEs autocompletion\n\nconst darkCodeThemeStyles =\n  require('prism-react-renderer/themes/vsDark').styles;\n\n/** @type {import('@docusaurus/types').Config} */\nconst config = {\n  title: 'CRACO',\n  tagline: 'Create React App Configuration Override',\n  url: 'https://craco.js.org',\n  baseUrl: '/',\n  onBrokenLinks: 'throw',\n  onBrokenMarkdownLinks: 'warn',\n  favicon: 'img/favicon.ico',\n  trailingSlash: true,\n\n  // GitHub pages deployment config.\n  // If you aren't using GitHub pages, you don't need these.\n  organizationName: 'dilanx', // Usually your GitHub org/user name.\n  projectName: 'craco', // Usually your repo name.\n\n  // Even if you don't use internalization, you can use this field to set useful\n  // metadata like html lang. For example, if your site is Chinese, you may want\n  // to replace \"en\" with \"zh-Hans\".\n\n  i18n: {\n    defaultLocale: 'en',\n    locales: ['en'],\n  },\n\n  presets: [\n    [\n      'classic',\n      /** @type {import('@docusaurus/preset-classic').Options} */\n      ({\n        docs: {\n          sidebarPath: require.resolve('./sidebars.js'),\n          // Please change this to your repo.\n          // Remove this to remove the \"edit this page\" links.\n          editUrl: 'https://github.com/dilanx/craco/tree/main/website',\n        },\n        blog: false,\n        theme: {\n          customCss: require.resolve('./src/css/custom.scss'),\n        },\n        gtag: {\n          trackingID: \"G-WNH8FQZPF4\",\n        },\n      }),\n    ],\n  ],\n\n  plugins: [\n    [\n      '@docusaurus/plugin-content-docs',\n      {\n        id: 'plugins',\n        path: 'plugins',\n        routeBasePath: 'plugins',\n        sidebarPath: false,\n        editUrl: 'https://github.com/dilanx/craco/tree/main/website',\n      },\n    ],\n    [\n      '@docusaurus/plugin-content-docs',\n      {\n        id: 'recipes',\n        path: 'recipes',\n        routeBasePath: 'recipes',\n        sidebarPath: require.resolve('./sidebarsRecipes.js'),\n        editUrl: 'https://github.com/dilanx/craco/tree/main/website',\n      },\n    ],\n    'docusaurus-plugin-sass',\n  ],\n\n  themeConfig:\n    /** @type {import('@docusaurus/preset-classic').ThemeConfig} */\n    ({\n      navbar: {\n        title: 'CRACO',\n        logo: {\n          alt: 'CRACO logo',\n          src: 'img/craco.png',\n        },\n        items: [\n          {\n            type: 'doc',\n            docId: 'welcome',\n            position: 'left',\n            label: 'Documentation',\n          },\n          {\n            to: 'plugins',\n            label: 'Plugins',\n            position: 'left',\n          },\n          {\n            to: 'recipes',\n            label: 'Recipes',\n            position: 'left',\n          },\n          {\n            href: 'https://github.com/dilanx/craco',\n            label: 'GitHub',\n            position: 'right',\n          },\n          {\n            href: 'https://www.npmjs.com/package/@craco/craco',\n            label: 'npm',\n            position: 'right',\n          },\n        ],\n      },\n      footer: {\n        style: 'dark',\n        logo: {\n          alt: 'Dilan Nair Open Source Logo',\n          src: '/img/open-source.svg',\n          href: 'https://www.dilanxd.com',\n          width: 280,\n          target: '_blank',\n        },\n        links: [\n          {\n            title: 'Documentation',\n            items: [\n              {\n                label: 'About CRACO',\n                to: 'docs',\n              },\n              {\n                label: 'Getting Started',\n                to: 'docs/getting-started',\n              },\n              {\n                label: 'Configuration',\n                to: 'docs/configuration/getting-started',\n              },\n              {\n                label: 'Configuration API',\n                to: 'docs/configuration-api',\n              },\n              {\n                label: 'Plugin API',\n                to: 'docs/plugin-api/getting-started',\n              },\n            ],\n          },\n          {\n            title: 'Community',\n            items: [\n              {\n                label: 'Community Maintained Plugins',\n                to: 'plugins',\n              },\n              {\n                label: 'Recipes',\n                to: 'recipes',\n              },\n              {\n                label: 'Issues',\n                href: 'https://github.com/dilanx/craco/issues',\n              },\n              {\n                label: 'Discussions',\n                href: 'https://github.com/dilanx/craco/discussions',\n              },\n              {\n                label: 'Stack Overflow',\n                href: 'https://stackoverflow.com/questions/tagged/craco',\n              },\n            ],\n          },\n          {\n            title: 'More',\n            items: [\n              {\n                label: 'GitHub',\n                href: 'https://github.com/dilanx/craco',\n              },\n              {\n                label: 'npm',\n                href: 'https://www.npmjs.com/package/@craco/craco',\n              },\n            ],\n          },\n        ],\n\n        copyright: `Copyright © ${new Date().getFullYear()} Dilan Nair`,\n      },\n      prism: {\n        darkTheme: {\n          plain: {\n            color: '#D4D4D4',\n            backgroundColor: '#212121',\n          },\n          styles: [\n            ...darkCodeThemeStyles,\n            {\n              types: ['title'],\n              style: {\n                color: '#569CD6',\n                fontWeight: 'bold',\n              },\n            },\n            {\n              types: ['property', 'parameter'],\n              style: {\n                color: '#9CDCFE',\n              },\n            },\n            {\n              types: ['script'],\n              style: {\n                color: '#D4D4D4',\n              },\n            },\n            {\n              types: ['boolean', 'arrow', 'atrule', 'tag'],\n              style: {\n                color: '#569CD6',\n              },\n            },\n            {\n              types: ['number', 'color', 'unit'],\n              style: {\n                color: '#B5CEA8',\n              },\n            },\n            {\n              types: ['font-matter'],\n              style: {\n                color: '#CE9178',\n              },\n            },\n            {\n              types: ['keyword', 'rule'],\n              style: {\n                color: '#C586C0',\n              },\n            },\n            {\n              types: ['regex'],\n              style: {\n                color: '#D16969',\n              },\n            },\n            {\n              types: ['maybe-class-name'],\n              style: {\n                color: '#4EC9B0',\n              },\n            },\n            {\n              types: ['constant'],\n              style: {\n                color: '#4FC1FF',\n              },\n            },\n          ],\n        },\n      },\n      colorMode: {\n        defaultMode: 'dark',\n        disableSwitch: true,\n      },\n    }),\n};\n\nmodule.exports = config;\n"
  },
  {
    "path": "website/package.json",
    "content": "{\n  \"name\": \"craco-website\",\n  \"version\": \"0.0.0\",\n  \"private\": true,\n  \"scripts\": {\n    \"docusaurus\": \"docusaurus\",\n    \"start\": \"docusaurus start\",\n    \"build\": \"docusaurus build\",\n    \"swizzle\": \"docusaurus swizzle\",\n    \"deploy\": \"GIT_USER=dilanx docusaurus deploy\",\n    \"clear\": \"docusaurus clear\",\n    \"serve\": \"docusaurus serve\",\n    \"write-translations\": \"docusaurus write-translations\",\n    \"write-heading-ids\": \"docusaurus write-heading-ids\"\n  },\n  \"dependencies\": {\n    \"@docusaurus/core\": \"^2.2.0\",\n    \"@docusaurus/preset-classic\": \"^2.2.0\",\n    \"@heroicons/react\": \"^2.0.12\",\n    \"@mdx-js/react\": \"^1.6.22\",\n    \"clsx\": \"^1.2.1\",\n    \"docusaurus-plugin-sass\": \"^0.2.2\",\n    \"prism-react-renderer\": \"^1.3.5\",\n    \"react\": \"^17.0.2\",\n    \"react-dom\": \"^17.0.2\",\n    \"sass\": \"^1.55.0\"\n  },\n  \"devDependencies\": {\n    \"@docusaurus/module-type-aliases\": \"^2.2.0\"\n  },\n  \"browserslist\": {\n    \"production\": [\n      \">0.5%\",\n      \"not dead\",\n      \"not op_mini all\"\n    ],\n    \"development\": [\n      \"last 1 chrome version\",\n      \"last 1 firefox version\",\n      \"last 1 safari version\"\n    ]\n  },\n  \"engines\": {\n    \"node\": \">=16.14\"\n  }\n}\n"
  },
  {
    "path": "website/plugins/plugins.md",
    "content": "---\ntitle: Plugins\nslug: /\n---\n\n# Community Maintained Plugins\n\nHere is a list of some CRACO plugins maintained by the community.\n\n- [craco-antd](https://github.com/DocSpring/craco-antd) by [@DocSpring](https://github.com/DocSpring)\n- [craco-babel-loader](https://github.com/rjerue/craco-babel-loader) by [@rjerue](https://github.com/rjerue/)\n- [craco-base64-inline-loader](https://github.com/melMass/craco-base64-inline-loader) by [@melMass](https://github.com/melMass)\n- [craco-cesium](https://www.npmjs.com/package/craco-cesium) by [rot1024](https://github.com/rot1024)\n- [craco-css-modules](https://www.npmjs.com/package/craco-css-modules) by [@crazyurus](https://github.com/crazyurus)\n- [craco-esbuild](https://github.com/pradel/create-react-app-esbuild) by [@pradel](https://github.com/pradel)\n- [craco-favicons](https://github.com/rickysullivan/craco-favicons) by [@rickysullivan](https://github.com/rickysullivan)\n- [craco-image-optimizer-plugin](https://github.com/kkulbae/craco-image-optimizer-plugin) by [@kkulbae](https://github.com/kkulbae)\n- [craco-interpolate-html-plugin](https://github.com/kkulbae/craco-interpolate-html-plugin) by [@kkulbae](https://github.com/kkulbae)\n- [craco-less](https://github.com/DocSpring/craco-less) by [@DocSpring](https://github.com/DocSpring)\n- [craco-linaria](https://github.com/jednano/craco-linaria) by [jednano](https://github.com/jednano)\n- [craco-parameter-decorator](https://github.com/org-redtea/craco-parameter-decorator) by [@Hokid](https://github.com/Hokid)\n- [craco-plugin-env](https://github.com/ponjs/craco-plugin-env) by [@ponjs](https://github.com/ponjs)\n- [craco-plugin-react-hot-reload](https://github.com/HasanAyan/craco-plugin-react-hot-reload) by [@hasanayan](https://github.com/hasanayan)\n- [craco-plugin-scoped-css](https://github.com/gaoxiaoliangz/react-scoped-css/tree/master/packages/craco-plugin-scoped-css) by [gaoxiaoliangz](https://github.com/gaoxiaoliangz)\n- [craco-plugin-single-spa-application](https://github.com/hasanayan/craco-plugin-single-spa-application) by [@hasanayan](https://github.com/hasanayan)\n- [craco-purescript-loader](https://github.com/andys8/craco-purescript-loader) by [@andys8](https://github.com/andys8)\n- [craco-styled-jsx](https://github.com/cr4zyc4t/craco-styled-jsx) by [@cr4zyc4t](https://github.com/cr4zyc4t)\n- [craco-preact](https://github.com/DocSpring/craco-preact) by [@DocSpring](https://github.com/DocSpring)\n- [craco-raw-loader](https://github.com/melMass/craco-raw-loader) by [@melMass](https://github.com/melMass)\n- [craco-sass-resources-loader](https://github.com/tilap/craco-sass-resources-loader) by [tilap](https://github.com/tilap)\n- [craco-use-babelrc](https://github.com/jackwilsdon/craco-use-babelrc) by [@jackwilsdon](https://github.com/jackwilsdon)\n- [craco-workbox](https://github.com/kevinsperrine/craco-workbox) by [@kevinsperrine](https://github.com/kevinsperrine)\n- [react-app-alias](https://github.com/oklas/react-app-alias) by [@oklas](https://github.com/oklas)\n- [storybook-preset-craco](https://github.com/artisanofcode/storybook-preset-craco) by [@danielknell](https://github.com/danielknell)\n\nDeveloped one yourself? [Add it to the list!](https://github.com/dilanx/craco/tree/main/website/plugins/plugins.md)\n"
  },
  {
    "path": "website/recipes/add-autoprefixer-options.md",
    "content": "# Add Autoprefixer options\n\n```js title=\"craco.config.js\"\nmodule.exports = {\n  style: {\n    postcss: {\n      env: {\n        autoprefixer: {\n          cascade: true,\n        },\n      },\n    },\n  },\n};\n```\n"
  },
  {
    "path": "website/recipes/add-postcss-features.md",
    "content": "# Add PostCSS features\n\n```js title=\"craco.config.js\"\nmodule.exports = {\n  style: {\n    postcss: {\n      env: {\n        stage: 3,\n        features: {\n          'nesting-rules': true,\n        },\n      },\n    },\n  },\n};\n```\n"
  },
  {
    "path": "website/recipes/add-stylelint.md",
    "content": "# Add Stylelint\n\n```js title=\"craco.config.js\"\nconst path = require('path');\n\nconst StyleLintPlugin = require('stylelint-webpack-plugin');\n\nmodule.exports = {\n  webpack: {\n    plugins: {\n      add: [\n        new StyleLintPlugin({\n          configBasedir: __dirname,\n          context: path.resolve(__dirname, 'src'),\n          files: ['**/*.css'],\n        }),\n      ],\n    },\n  },\n};\n```\n"
  },
  {
    "path": "website/recipes/add-webpack-alias-to-jest.md",
    "content": "# Add Webpack alias to Jest\n\n```js title=\"craco.config.js\"\n// You can also use craco-alias plugin: https://github.com/risenforces/craco-alias\n\nconst path = require('path');\n\nmodule.exports = {\n  webpack: {\n    alias: {\n      '@components': path.resolve(__dirname, 'src/components/'),\n    },\n  },\n  jest: {\n    configure: {\n      moduleNameMapper: {\n        '^@components(.*)$': '<rootDir>/src/components$1',\n      },\n    },\n  },\n};\n```\n"
  },
  {
    "path": "website/recipes/extends-postcss-plugins.md",
    "content": "# Extends PostCSS plugins\n\n```js title=\"craco.config.js\"\nmodule.exports = {\n  style: {\n    postcss: {\n      plugins: [\n        require('cssnano')({\n          preset: 'default',\n        }),\n      ],\n    },\n  },\n};\n```\n"
  },
  {
    "path": "website/recipes/set-css-loader-locals-convention.md",
    "content": "# Set css-loader locals convention\n\n```js title=\"craco.config.js\"\n/**\n * This example shows how to add the localsConvention option to the css-loader.\n * Useful if you like to write CSS/SASS classes using BEM notation in css modules.\n * https://github.com/webpack-contrib/css-loader#localsconvention\n */\nmodule.exports = {\n  style: {\n    css: {\n      loaderOptions: {\n        localsConvention: 'camelCase',\n      },\n    },\n  },\n};\n```\n"
  },
  {
    "path": "website/recipes/use-a-jest-config-file.md",
    "content": "# Use a Jest config file\n\n```js title=\"craco.config.js\"\nmodule.exports = {\n  jest: {\n    configure: {\n      globals: {\n        CONFIG: true,\n      },\n    },\n  },\n};\n```\n\n```js title=\"jest.config.js\"\nconst { createJestConfig } = require('@craco/craco');\n\nconst cracoConfig = require('./craco.config.js');\nconst jestConfig = createJestConfig(cracoConfig);\n\nmodule.exports = jestConfig;\n```\n"
  },
  {
    "path": "website/recipes/use-a-postcss-config-file.md",
    "content": "# Use a PostCSS config file\n\n```js title=\"craco.config.js\"\nconst { POSTCSS_MODES } = require('@craco/craco');\n\nmodule.exports = {\n  style: {\n    postcss: {\n      mode: POSTCSS_MODES.file,\n    },\n  },\n};\n```\n\n```js title=\"postcss.config.js\"\nmodule.exports = {\n  plugins: [\n    require('postcss-flexbugs-fixes'),\n    require('postcss-preset-env')({\n      autoprefixer: {\n        flexbox: 'no-2009',\n      },\n      stage: 3,\n      features: {\n        'nesting-rules': true,\n      },\n    }),\n  ],\n};\n```\n"
  },
  {
    "path": "website/recipes/use-an-eslint-config-file.md",
    "content": "# Use an ESLint config file\n\n```js title=\"craco.config.js\"\nmodule.exports = {\n  eslint: {\n    mode: 'file',\n  },\n};\n```\n\n```js title=\".eslintrc.js\"\nmodule.exports = {\n  extends: ['eslint-config-react-app'],\n};\n```\n"
  },
  {
    "path": "website/recipes/use-an-https-dev-server.md",
    "content": "# Use an HTTPS dev server\n\n```js title=\"craco.config.js\"\nconst path = require('path');\nconst fs = require('fs');\n\nconst { whenDev } = require('@craco/craco');\n\nmodule.exports = {\n  devServer: whenDev(() => ({\n    https: true,\n    pfx: fs.readFileSync(path.resolve('./localhost.pfx')),\n    pfxPassphrase: 'temp123!',\n  })),\n};\n```\n"
  },
  {
    "path": "website/recipes/use-ant-design.md",
    "content": "# Use Ant Design\n\n```js title=\"craco.config.js\"\n// Official documentation available at: https://github.com/FormAPI/craco-antd\n\nmodule.exports = {\n  plugins: [\n    {\n      plugin: require('craco-antd'),\n      options: {\n        customizeTheme: {\n          '@primary-color': '#1DA57A',\n        },\n        lessLoaderOptions: {\n          noIeCompat: true,\n        },\n      },\n    },\n  ],\n};\n```\n"
  },
  {
    "path": "website/recipes/use-babel-plugin-react-css-modules.md",
    "content": "# Use babel-plugin-react-css-modules\n\n```js title=\"craco.config.js\"\nconst CSS_MODULE_LOCAL_IDENT_NAME = '[local]___[hash:base64:5]';\n\nmodule.exports = {\n  style: {\n    modules: {\n      localIdentName: CSS_MODULE_LOCAL_IDENT_NAME,\n    },\n  },\n  babel: {\n    plugins: [\n      [\n        'babel-plugin-react-css-modules',\n        {\n          generateScopedName: CSS_MODULE_LOCAL_IDENT_NAME,\n          attributeNames: { activeStyleName: 'activeClassName' },\n        },\n      ],\n    ],\n  },\n};\n```\n"
  },
  {
    "path": "website/recipes/use-dart-sass.md",
    "content": "# Use Dart Sass\n\n```js title=\"craco.config.js\"\n/**\n * This example shows how to configure the sass-loader for Dart Sass.\n * Note: Only Dart Sass ('sass') currently supports @use.\n */\nmodule.exports = {\n  style: {\n    sass: {\n      loaderOptions: {\n        // Prefer 'sass' (dart-sass) over 'node-sass' if both packages are installed.\n        implementation: require('sass'),\n        // Workaround for this bug: https://github.com/webpack-contrib/sass-loader/issues/804\n        webpackImporter: false,\n      },\n    },\n  },\n};\n```\n"
  },
  {
    "path": "website/recipes/use-html-loader.md",
    "content": "# Use html-loader\n\n```js title=\"craco.config.js\"\n/**\n * To use this, ensure you have added `html-loader` as a dev dependency in your `package.json` first\n * Learn more: https://github.com/webpack-contrib/html-loader\n */\nconst { loaderByName, addBeforeLoader } = require('@craco/craco');\n\nmodule.exports = {\n  webpack: {\n    configure: (webpackConfig) => {\n      webpackConfig.resolve.extensions.push('.html');\n\n      const htmlLoader = {\n        loader: require.resolve('html-loader'),\n        test: /\\.html$/,\n        exclude: /node_modules/,\n      };\n\n      addBeforeLoader(webpackConfig, loaderByName('file-loader'), htmlLoader);\n\n      return webpackConfig;\n    },\n  },\n};\n```\n\n```ts title=\"typings.d.ts\"\n/**\n * To resolve \"Cannot find module error on importing html file in webpack\" if you use Typescript\n * Usage: import foo from './foo.html';\n */\ndeclare module '*.html' {\n  const value: string;\n  export default value;\n}\n```\n"
  },
  {
    "path": "website/recipes/use-less-loader.md",
    "content": "# Use less-loader\n\n```js title=\"craco.config.js\"\n// Official documentation available at: https://github.com/FormAPI/craco-less\n\nmodule.exports = {\n  plugins: [\n    {\n      plugin: require('craco-less'),\n      options: {\n        noIeCompat: true,\n      },\n    },\n  ],\n};\n```\n"
  },
  {
    "path": "website/recipes/use-linaria.md",
    "content": "# Use Linaria\n\n```js title=\"craco.config.js\"\n// Official documentation available at: https://github.com/jednano/craco-linaria\n\nmodule.exports = {\n  plugins: [{ plugin: require('craco-linaria') }],\n};\n```\n"
  },
  {
    "path": "website/recipes/use-markdown-loader.md",
    "content": "# Use markdown-loader\n\n```js title=\"craco.config.js\"\n// Import Markdown files as HTML into your React Application\n// <https://github.com/peerigon/markdown-loader>\n\nconst { addBeforeLoader, loaderByName } = require('@craco/craco');\n\n// Additional configuration for Typescript users: add `declare module '*.md'` to your `index.d.ts` file.\n\nmodule.exports = {\n  webpack: {\n    configure: (webpackConfig) => {\n      webpackConfig.resolve.extensions.push('.md');\n\n      const markdownLoader = {\n        test: /\\.md$/,\n        exclude: /node_modules/,\n        use: [\n          {\n            loader: require.resolve('html-loader'),\n          },\n          {\n            loader: require.resolve('markdown-loader'),\n            options: {\n              // see <https://marked.js.org/using_advanced#options>\n            },\n          },\n        ],\n      };\n\n      addBeforeLoader(\n        webpackConfig,\n        loaderByName('file-loader'),\n        markdownLoader\n      );\n\n      return webpackConfig;\n    },\n  },\n};\n```\n"
  },
  {
    "path": "website/recipes/use-mobx.md",
    "content": "# Use MobX\n\n```js title=\"craco.config.js\"\nmodule.exports = {\n  babel: {\n    plugins: [['@babel/plugin-proposal-decorators', { legacy: true }]],\n  },\n};\n```\n"
  },
  {
    "path": "website/recipes/use-preact.md",
    "content": "# Use Preact\n\n```js title=\"craco.config.js\"\n// Official documentation available at: https://github.com/FormAPI/craco-preact\n\nmodule.exports = {\n  plugins: [{ plugin: require('craco-preact') }],\n};\n```\n"
  },
  {
    "path": "website/recipes/use-purescript.md",
    "content": "# Use PureScript\n\n```js title=\"craco.config.js\"\n// Use PureScript in React Application\n// <https://www.purescript.org>\n\nconst { addBeforeLoader, loaderByName } = require('@craco/craco');\nconst path = require('path');\n\n// Detect watch\n// <https://github.com/purescript/spago#get-started-from-scratch-with-webpack-frontend-projects>\nconst isWatch = process.argv.some((a) => a === '--watch');\nconst isWebpackDevServer = process.argv.some(\n  (a) => path.basename(a) === 'webpack-dev-server'\n);\n\nmodule.exports = {\n  webpack: {\n    configure: (webpackConfig) => {\n      const { resolve } = webpackConfig;\n\n      // Resolve purescript extension\n      resolve.extensions.push('.purs');\n\n      // Allow imports outside of `src` folder for purescript dependencies\n      webpackConfig.resolve.plugins = resolve.plugins.filter(\n        ({ constructor: c }) => !c || c.name !== 'ModuleScopePlugin'\n      );\n\n      // PureScript loader\n      const pursLoader = {\n        loader: 'purs-loader',\n        test: /\\.purs$/,\n        exclude: /node_modules/,\n        query: {\n          src: ['src/**/*.purs'],\n          spago: true,\n          pscIde: true,\n          watch: isWebpackDevServer || isWatch,\n        },\n      };\n\n      // Append purs-loader before file-loader\n      addBeforeLoader(webpackConfig, loaderByName('file-loader'), pursLoader);\n\n      return webpackConfig;\n    },\n  },\n};\n```\n"
  },
  {
    "path": "website/recipes/use-ts-loader.md",
    "content": "# Use ts-loader\n\n```js title=\"craco.config.js\"\n// This recipe replaces usage of babel-loader for compilation of TypeScript / JavaScript application code\n// with ts-loader running in transpileOnly mode (as type checking is still performed by the\n// fork-ts-checker-webpack-plugin). Should further customisation of ts-loader be required, the options\n// below can be adjusted. babel-loader is still used to require non-application TypeScript / JavaScript\n// To use this, ensure you have added ts-loader as a dependency in your `package.json` first\nconst {\n  addAfterLoader,\n  removeLoaders,\n  loaderByName,\n  getLoaders,\n  throwUnexpectedConfigError,\n} = require('@craco/craco');\n\nconst throwError = (message) =>\n  throwUnexpectedConfigError({\n    packageName: 'craco',\n    githubRepo: 'gsoft-inc/craco',\n    message,\n    githubIssueQuery: 'webpack',\n  });\n\nmodule.exports = {\n  webpack: {\n    configure: (webpackConfig, { paths }) => {\n      const { hasFoundAny, matches } = getLoaders(\n        webpackConfig,\n        loaderByName('babel-loader')\n      );\n      if (!hasFoundAny) throwError('failed to find babel-loader');\n\n      console.log('removing babel-loader');\n      const { hasRemovedAny, removedCount } = removeLoaders(\n        webpackConfig,\n        loaderByName('babel-loader')\n      );\n      if (!hasRemovedAny) throwError('no babel-loader to remove');\n      if (removedCount !== 2)\n        throwError('had expected to remove 2 babel loader instances');\n\n      console.log('adding ts-loader');\n\n      const tsLoader = {\n        test: /\\.(js|mjs|jsx|ts|tsx)$/,\n        include: paths.appSrc,\n        loader: require.resolve('ts-loader'),\n        options: { transpileOnly: true },\n      };\n\n      const { isAdded: tsLoaderIsAdded } = addAfterLoader(\n        webpackConfig,\n        loaderByName('url-loader'),\n        tsLoader\n      );\n      if (!tsLoaderIsAdded) throwError('failed to add ts-loader');\n      console.log('added ts-loader');\n\n      console.log('adding non-application JS babel-loader back');\n      const { isAdded: babelLoaderIsAdded } = addAfterLoader(\n        webpackConfig,\n        loaderByName('ts-loader'),\n        matches[1].loader // babel-loader\n      );\n      if (!babelLoaderIsAdded)\n        throwError('failed to add back babel-loader for non-application JS');\n      console.log('added non-application JS babel-loader back');\n\n      return webpackConfig;\n    },\n  },\n};\n```\n"
  },
  {
    "path": "website/sidebars.js",
    "content": "// @ts-check\n\n/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */\nconst sidebars = {\n  docs: [\n    'welcome',\n    'getting-started',\n    {\n      type: 'category',\n      label: 'Configuration',\n      link: {\n        type: 'generated-index',\n      },\n      items: [\n        'configuration/getting-started',\n        'configuration/style',\n        'configuration/eslint',\n        'configuration/babel',\n        'configuration/typescript',\n        'configuration/webpack',\n        'configuration/jest',\n        'configuration/devserver',\n        'configuration/plugins',\n      ],\n    },\n    'configuration-api',\n    {\n      type: 'category',\n      label: 'Plugin API',\n      link: {\n        type: 'generated-index',\n      },\n      items: [\n        'plugin-api/getting-started',\n        'plugin-api/hooks',\n        {\n          type: 'category',\n          label: 'Utility Functions',\n          link: {\n            type: 'generated-index',\n            description:\n              'CRACO provides a suite of utility functions to help you develop your plugins.',\n          },\n          items: [\n            'plugin-api/utility-functions/webpack-loaders',\n            'plugin-api/utility-functions/webpack-asset-modules',\n            'plugin-api/utility-functions/webpack-plugins',\n            'plugin-api/utility-functions/miscellaneous',\n          ],\n        },\n      ],\n    },\n  ],\n};\n\nmodule.exports = sidebars;\n"
  },
  {
    "path": "website/sidebarsRecipes.js",
    "content": "// @ts-check\n\n/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */\nconst sidebarsRecipes = {\n  docs: [\n    {\n      type: 'category',\n      label: 'Recipes',\n      link: {\n        type: 'generated-index',\n        slug: '/',\n        description: 'A collection of configs for common use cases.',\n      },\n      items: [\n        {\n          type: 'autogenerated',\n          dirName: '.',\n        },\n      ],\n    },\n  ],\n};\n\nmodule.exports = sidebarsRecipes;\n"
  },
  {
    "path": "website/src/components/HomepageFeatures/index.js",
    "content": "import React from 'react';\nimport clsx from 'clsx';\nimport styles from './styles.module.css';\n\nconst FeatureList = [\n  {\n    title: 'Easy to Use',\n    Svg: require('@site/static/img/undraw_docusaurus_mountain.svg').default,\n    description: (\n      <>\n        Docusaurus was designed from the ground up to be easily installed and\n        used to get your website up and running quickly.\n      </>\n    ),\n  },\n  {\n    title: 'Focus on What Matters',\n    Svg: require('@site/static/img/undraw_docusaurus_tree.svg').default,\n    description: (\n      <>\n        Docusaurus lets you focus on your docs, and we&apos;ll do the chores. Go\n        ahead and move your docs into the <code>docs</code> directory.\n      </>\n    ),\n  },\n  {\n    title: 'Powered by React',\n    Svg: require('@site/static/img/undraw_docusaurus_react.svg').default,\n    description: (\n      <>\n        Extend or customize your website layout by reusing React. Docusaurus can\n        be extended while reusing the same header and footer.\n      </>\n    ),\n  },\n];\n\nfunction Feature({Svg, title, description}) {\n  return (\n    <div className={clsx('col col--4')}>\n      <div className=\"text--center\">\n        <Svg className={styles.featureSvg} role=\"img\" />\n      </div>\n      <div className=\"text--center padding-horiz--md\">\n        <h3>{title}</h3>\n        <p>{description}</p>\n      </div>\n    </div>\n  );\n}\n\nexport default function HomepageFeatures() {\n  return (\n    <section className={styles.features}>\n      <div className=\"container\">\n        <div className=\"row\">\n          {FeatureList.map((props, idx) => (\n            <Feature key={idx} {...props} />\n          ))}\n        </div>\n      </div>\n    </section>\n  );\n}\n"
  },
  {
    "path": "website/src/components/HomepageFeatures/styles.module.css",
    "content": ".features {\n  display: flex;\n  align-items: center;\n  padding: 2rem 0;\n  width: 100%;\n}\n\n.featureSvg {\n  height: 200px;\n  width: 200px;\n}\n"
  },
  {
    "path": "website/src/css/custom.scss",
    "content": "/**\n * Any CSS included here will be global. The classic template\n * bundles Infima by default. Infima is a CSS framework designed to\n * work well for content-centric websites.\n */\n\n/* You can override the default Infima variables here. */\n:root {\n  --ifm-color-primary: #2e8555;\n  --ifm-color-primary-dark: #29784c;\n  --ifm-color-primary-darker: #277148;\n  --ifm-color-primary-darkest: #205d3b;\n  --ifm-color-primary-light: #33925d;\n  --ifm-color-primary-lighter: #359962;\n  --ifm-color-primary-lightest: #3cad6e;\n  --ifm-code-font-size: 95%;\n  --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1);\n}\n\n/* For readability concerns, you should choose a lighter palette in dark mode. */\n[data-theme='dark'] {\n  --ifm-color-primary: #28dfb7;\n  --ifm-color-primary-dark: #1fcea8;\n  --ifm-color-primary-darker: #1dc39e;\n  --ifm-color-primary-darkest: #18a082;\n  --ifm-color-primary-light: #3fe2bf;\n  --ifm-color-primary-lighter: #4ae4c2;\n  --ifm-color-primary-lightest: #6de9ce;\n}\n\n.craco-main {\n  display: flex;\n  flex-direction: column;\n  justify-content: center;\n  align-items: center;\n  margin: 64px;\n\n  .header {\n    display: flex;\n    justify-content: center;\n    align-items: center;\n    gap: 16px;\n\n    img {\n      width: 256px;\n      height: 256px;\n    }\n\n    .text {\n      font-size: 48px;\n      font-weight: bold;\n      p {\n        margin: 0;\n      }\n      span {\n        color: var(--ifm-color-primary);\n      }\n      margin-bottom: 32px;\n    }\n\n    @media screen and (max-width: 768px) {\n      flex-direction: column;\n      img {\n        width: 128px;\n        height: 128px;\n      }\n      .text {\n        font-size: 32px;\n      }\n    }\n  }\n\n  .buttons {\n    display: flex;\n    gap: 16px;\n    flex-wrap: wrap;\n    justify-content: center;\n    align-items: center;\n\n    a {\n      padding: 12px 48px;\n      font-size: 18px;\n      font-weight: bold;\n      color: var(--color);\n      border: 2px solid var(--color);\n      border-radius: 16px;\n      display: flex;\n      justify-content: center;\n      align-items: center;\n      gap: 8px;\n\n      &:hover {\n        text-decoration: none;\n        background-color: var(--color);\n        color: black;\n      }\n\n      p {\n        margin: 0;\n      }\n\n      svg {\n        width: 24px;\n        height: 24px;\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "website/src/pages/index.js",
    "content": "import React, { useEffect, useState } from 'react';\nimport Layout from '@theme/Layout';\nimport { PlayIcon, StarIcon } from '@heroicons/react/24/solid';\nimport CracoLogo from '@site/static/img/craco.png';\n\nexport default function Home() {\n  const [stars, setStars] = useState('-');\n\n  useEffect(() => {\n    fetch('https://api.github.com/repos/dilanx/craco')\n      .then((response) => response.json())\n      .then((data) =>\n        setStars(\n          data.stargazers_count.toString().replace(/\\B(?=(\\d{3})+(?!\\d))/g, ',')\n        )\n      );\n  }, []);\n\n  return (\n    <Layout\n      title={`Configure CRA without ejecting.`}\n      description=\"Create React App Configuration Override\"\n    >\n      <main className=\"craco-main\">\n        <div className=\"header\">\n          <img src={CracoLogo} alt=\"CRACO logo\" />\n          <div className=\"text\">\n            <p>\n              <span>C</span>REATE\n            </p>\n            <p>\n              <span>R</span>EACT\n            </p>\n            <p>\n              <span>A</span>PP\n            </p>\n            <p>\n              <span>C</span>ONFIGURATION\n            </p>\n            <p>\n              <span>O</span>VERRIDE\n            </p>\n          </div>\n        </div>\n        <div className=\"buttons\">\n          <a href=\"/docs/\" style={{ '--color': 'white' }}>\n            <PlayIcon />\n            <p>Get Started</p>\n          </a>\n          <a\n            href=\"https://github.com/dilanx/craco\"\n            style={{ '--color': 'gold' }}\n          >\n            <StarIcon />\n            <p>{stars}</p>\n          </a>\n        </div>\n      </main>\n    </Layout>\n  );\n}\n"
  },
  {
    "path": "website/static/.nojekyll",
    "content": ""
  },
  {
    "path": "website/static/CNAME",
    "content": "craco.js.org\n"
  }
]