# @mitodl/course-search-utils

> JS utils for interacting with MIT Open Course search

Latest version **3.8.1** (published 2026-09-03) · BSD-3-Clause license · 0 weekly downloads

## Install

```sh
npm install @mitodl/course-search-utils
pnpm add @mitodl/course-search-utils
yarn add @mitodl/course-search-utils
bun add @mitodl/course-search-utils
```

## Health

**Score 65/100 (B)** — status: active.

Positive: esm support; no vulnerabilities; has provenance; recently updated; high maintenance score.

Warnings: low downloads; no types.

## Facts

| | |
|---|---|
| Version | 3.8.1 |
| Published | 2026-09-03 |
| First published | 2020-09-16 |
| Weekly downloads | 0 |
| License | BSD-3-Clause |
| TypeScript types | none |
| Module format | ESM + CommonJS |
| Dependencies | 4 |
| Unpacked size | 142.2 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Provenance | attested (GitHub Actions) |
| GitHub stars | 0 |
| Author | MITOL |
| Maintainers | mitx-devops, rhysyngsun, gumaerc, cchudzicki, abeglova |
| Keywords | JS, React |

## Links

- npm: https://www.npmjs.com/package/@mitodl/course-search-utils
- Repository: https://github.com/mitodl/course-search-utils
- Homepage: https://github.com/mitodl/course-search-utils#readme
- Issues: https://github.com/mitodl/course-search-utils/issues
- npm.io page: https://npm.io/package/@mitodl/course-search-utils

## Dependencies (4)

- [axios](https://npm.io/package/axios.md) ^1.6.7
- [fuse.js](https://npm.io/package/fuse.js.md) ^7.0.0
- [@remixicon/react](https://npm.io/package/@remixicon/react.md) ^4.2.0
- [@mitodl/mit-learn-api-axios](https://npm.io/package/@mitodl/mit-learn-api-axios.md) ^2026.8.19

## Alternatives

- [@mapbox/jsonlint-lines-primitives](https://npm.io/package/@mapbox/jsonlint-lines-primitives.md) — 5.3M weekly downloads
- [reftools](https://npm.io/package/reftools.md) — 3.5M weekly downloads
- [@hey-api/openapi-ts](https://npm.io/package/@hey-api/openapi-ts.md) — 3.5M weekly downloads
- [@mapbox/geojson-rewind](https://npm.io/package/@mapbox/geojson-rewind.md) — 2.4M weekly downloads
- [turbo-stream](https://npm.io/package/turbo-stream.md) — 1.7M weekly downloads

## Recent versions

- 3.8.1 (latest) — 2026-09-03
- 0.0.0-007f616 (preview) — 2026-08-24
- 3.8.0 — 2026-08-24
- 3.7.0 — 2026-08-20
- 0.0.0-e2e8067 — 2026-08-20
- 3.5.2 — 2026-03-06
- 3.5.1 — 2026-03-02
- 3.5.0 — 2025-10-29
- 3.4.1 — 2025-10-21
- 3.4.0 — 2025-10-21
- 2.3.3 — 2025-03-13
- 3.3.2 — 2024-11-22
- 3.3.1 — 2024-10-23
- 3.3.0 — 2024-10-21
- 3.2.5 — 2024-10-16
- … 47 more at https://npm.io/package/@mitodl/course-search-utils/versions

## README

# Course Search Utils

This repo holds the core logic for our learning resource search. The basic API
is a React hook (`useCourseSearch`) which provides for deserializing the params from
the URL, managing the internal state of which facets are selected, etc.

## development

run the tests:

```
npm run test
npm run test:watch # for watch mode
```

run the typechecker:

```
npm run typecheck
```

## publishing

We squash-merge, so **your PR title sets the version bump** ([conventional commits](https://www.conventionalcommits.org/en/v1.0.0/), enforced by the `Validate PR title` check):

| PR title | Bump |
| --- | --- |
| `fix:` / `perf:` | patch |
| `feat:` | minor |
| `feat!:` (or a `BREAKING CHANGE:` footer) | major |
| `chore:` `docs:` `ci:` `test:` `refactor:` | **nothing is published** |

⚠️ If your change should reach consumers, title it `fix:` or `feat:`. A user-facing change titled `refactor:` or `chore:` silently never ships.

**To release:** Actions → "Releases (Semantic & Pre-release)" → Run workflow → `main` → `release-type: semantic-release`. Merging alone does not publish; someone has to dispatch this.

**To test in a consuming app:** run that action against your branch with `release-type: pre-release`. It publishes `0.0.0-<short-sha>` under the `preview` tag, never touching `latest`, and comments the version on your PR.

Don't edit `version` in `package.json` — it stays `0.0.0`; git tags and npm are the source of truth. Publishing uses [npm trusted publishing](https://docs.npmjs.com/trusted-publishers) via GitHub Actions OIDC, so no npm tokens are stored here. Notes through 3.6.0 are archived in [`RELEASE.rst`](./RELEASE.rst); newer ones are in [GitHub Releases](https://github.com/mitodl/course-search-utils/releases).

## Usage

### Hooks

`@mitodl/course-search-utils` exports a few hooks to assist in making search requests to MIT Open's APIs. They are:

1. `useResourceSearchParams({ searchParams, setSearchParams, ...opts? })` and `useContentFileSearchParams`: Derive search API parameters from a `URLSearchParams` object. Often, the `URLSearchParams` object will be derived from the browser URL, though it could be state internal to react.

   The hook extracts validated API parameters from the `URLSearchParams` object and returns setters that can be used to manipulate the `URLSearchParams` (e.g., toggling a search facet on or off).

   The `URLSearchParams` keys are mapped directly to API parameters.

2. `useInfiniteSearch({ params, endpoint, baseUrl, ...opts? })`: Assists in making search API calls used in an infinite scrolling UI. The initial page is loaded by the hook, susbsequent pages via returm value `{ fetchNextPage }`. The hook's result is based on [useInfiniteQuery](https://tanstack.com/query/v4/docs/framework/react/reference/useInfiniteQuery).

See Typescript annotations and docstrings for more information on hook props and results. Typical usage might look like:

```tsx
import { useSearchQueryParams, useInfiniteSearch, } from "@mitodl/course-search-utils"
import type { UseInfiniteSearchProps } from "@mitodl/course-search-utils"

const CONSTANT_PARAMETERS = {
  platform: ["ocw"],
  aggregations: ["topic", "offered_by"]
}

const SearchPage: React.FC = () => {
  const [searchParams, setSearchParams] = useSearchParams()
  const {
    params,
    toggleParamValue,
    clearAllFacets,
    currentText,
    setCurrentText,
    setCurrentTextAndQuery,
  } = useSearchQueryParams({
    searchParams,
    setSearchParams,
    facets: FACETS
  })

  // If necessary
  const allParams = useMemo(() => {
    return _.merge(params, CONSTANT_PARAMETERS)
  }, [params])

  const { pages, hasNextPage, fetchNextPage } = useInfiniteSearch({
    params: allParams,
    baseUrl: "http://mitopen.odl.mit.edu/",
    keepPreviousData: true,
  })

  const results = pages?.flatMap(p => p.results) ?? []

  return (/* Search component JSX*/)
}
```

---
_Source: https://npm.io/package/@mitodl/course-search-utils · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
