# AGENTS.md

## Setup
- Use npm here; `package-lock.json` is committed and CI installs with `npm ci --ignore-scripts`.
- `mise.toml` pins local Node 20, but CI runs Node 12, 14, 16, 18, 20, 22, and 24; keep `lib/` source compatible with old CommonJS-era syntax and runtime assumptions.
- CI order is `npm ci --ignore-scripts`, `npm run build`, then `npm test`.

## Commands
- `npm run build`: runs `grunt build`, which cleans `dist/` and uses Rollup from `lib/axios.js` to create `dist/axios*.js` and `dist/esm/axios*.js`.
- `npm test`: runs JS tests and declaration tests through `bin/ssl_hotfix.js`; use this full command on Node >16 so old tooling gets `NODE_OPTIONS=--openssl-legacy-provider`.
- `node bin/ssl_hotfix.js ./node_modules/.bin/grunt test`: JS-only verification, running ESLint on `lib/**/*.js`, Mocha on `test/unit/**/*.js`, and Karma on `test/specs/**/*.spec.js`.
- `./node_modules/.bin/mocha --timeout 30000 test/unit/<path>.js`: run one Node/Mocha unit test file without Karma or dtslint.
- `node bin/ssl_hotfix.js ./node_modules/.bin/grunt karma:single`: run the browser suite only.
- `node bin/ssl_hotfix.js ./node_modules/.bin/dtslint --localTs node_modules/typescript/lib`: run the declaration tests in `test/typescript/axios.ts`.
- `npm run fix`: ESLint autofix for `lib/**/*.js` only.

## Structure
- Package entry is `index.js` -> `lib/axios.js`; the TypeScript surface is the root `index.d.ts`.
- `lib/defaults/index.js` chooses the runtime adapter: `lib/adapters/xhr.js` for browsers and `lib/adapters/http.js` for Node.
- Browser bundlers also rely on `package.json` `browser` mappings from `./lib/adapters/http.js` to `./lib/adapters/xhr.js` and from `./lib/platform/node/index.js` to `./lib/platform/browser/index.js`.
- `lib/env/data.js` stores the package version and is generated by `grunt version` or `npm run preversion`; do not edit it except as part of a version bump.
- `grunt build` uses `rollup.config.js`; `webpack.config.js` is not the package build path, while Karma has its own webpack config inside `karma.conf.js`.

## Tests
- Node tests live in `test/unit/**/*.js` and use Mocha plus Node `assert`.
- Browser tests live in `test/specs/**/*.spec.js` and use Jasmine/Jasmine-Ajax; globals such as `axios` and `getAjaxRequest` come from `test/specs/__helpers.js`.
- Karma defaults to `FirefoxHeadless` and `ChromeHeadless` whenever `process.env.GITHUB_ACTIONS !== 'false'`, including when the variable is unset; set `GITHUB_ACTIONS=false` only if you need non-headless local browsers.
- There is no committed single-browser-spec target; do not leave `fdescribe`, `fit`, or `.only` in tests.
- Declaration changes should update both `index.d.ts` and `test/typescript/axios.ts`, then run the dtslint command above.

## Source Conventions
- `lib/` is CommonJS with `'use strict'`, `var`, semicolons, 2-space indentation, and no trailing commas; ESLint only checks `lib/**/*.js`.
- Public API behavior usually needs README docs, TypeScript declarations, and declaration tests updated together.
- Adapter or platform changes usually need both Node and browser paths considered, including Mocha coverage for `http.js` behavior and Karma coverage for `xhr.js` behavior.

## Node 12+ Compatibility
- All shipped code AND test code must run on Node 12 through Node 24. CI runs the full matrix, so a test that only works on Node 16+ will break the build. Avoid `??`, `?.`, top-level `await`, private class fields, `Array.prototype.at`, `structuredClone`, etc. in both `lib/` and `test/`.
- Be wary of `Object.prototype` pollution tests on Node 12/14: setting `Object.prototype.get` (or `set`) before any code that calls `Object.defineProperty` with a value-only descriptor will throw `TypeError: Getter must be a function`, because the descriptor inherits the polluted property. Construct servers/clients first, pre-load any lazy-required Node internals (e.g. `require('dns')`), then apply the pollution.
