# Version 2.2.0

> Two new init() config knobs - intercept toggles and essentialKeys/Patterns - that make headless integrations cleaner without breaking any v2.1 consumer

Source: https://zest.freshjuice.dev/changelog/v2.2.0/
Date: 2026-04-26

`@freshjuice/zest@2.2.0` adds two new `init()` config fields that fix real friction points discovered while wiring Zest into projects where the consent state machine was wanted, but the cookie / storage / script interceptors weren't. See the [full release on GitHub](https://github.com/freshjuice-dev/zest/releases/tag/v2.2.0).

> **Zero runtime change for v2.1 consumers.** Every default is preserved.

## Highlights

### `intercept` toggles

Disable any of Zest's interceptor channels independently. Defaults are all on, so existing consumers keep their current behaviour.

```javascript
Zest.init({
  intercept: {
    cookies: false,
    storage: false,
    scripts: false
  }
});
```

Use this when you gate optional scripts and storage yourself and want Zest only for the consent state machine — DNT/GPC handling, the signed `zest_consent` cookie, the `Zest.on()` event surface, and the consent proof.

Previously the only way to dodge the storage / cookie interceptor was to skip `Zest.init()` entirely, which also threw away the consent engine. The `mode` field only ever affected the script blocker, so headless consumers had no clean lever for the other two channels.

### `essentialKeys` — declare strictly-necessary names

The easy case for "I have storage keys X and Y, treat them as essential":

```javascript
Zest.init({
  essentialKeys: ['app_settings', 'theme_pref']
});
```

Each name is anchored as `^name$` and **appended** to the essential category. The built-in essential patterns (`zest_*`, `csrf*`, `xsrf*`, `session*`, `__host-*`, `__secure-*`) stay intact — your additions sit alongside.

### `essentialPatterns` — regex source strings

For prefix or family matches:

```javascript
Zest.init({
  essentialPatterns: ['^app_', '^_my_csrf']
});
```

Validated via the same `safeRegExp` used everywhere else in Zest. Invalid or catastrophic-backtracking patterns are dropped silently with a console warning. Capped at 500 characters per pattern.

### Why not just use `patterns.essential`?

The existing `patterns` config is still there and still works, but it **replaces** the patterns for any category you pass in. If you set `patterns.essential` you silently lose the built-in defaults. The new fields are additive — you keep all defaults and just extend.

Use `patterns` when you want full control of the matcher for a category. Use `essentialKeys` / `essentialPatterns` when you just want to add a few entries.

## TypeScript types

`InitOptions` now exposes `intercept`, `essentialKeys`, `essentialPatterns`, and `patterns` as first-class typed fields in both `zest.d.ts` and `zest.headless.d.ts`. The `[key: string]: unknown` escape hatch is no longer needed for any of these.

```typescript
import Zest, { InitOptions, InterceptToggles } from '@freshjuice/zest/headless';

const config: InitOptions = {
  respectDNT: true,
  intercept: { scripts: false },
  essentialKeys: ['ct_settings'],
  essentialPatterns: ['^app_']
};

Zest.init(config);
```

## Migration from v2.1

None required. Every existing config keeps working exactly as before.

If you previously worked around storage interception by overriding `patterns.essential` with the built-in list plus your own keys, you can now drop the boilerplate:

```diff
- patterns: {
-   essential: [
-     '^zest_',
-     '^csrf', '^xsrf', '^session',
-     '^__host-', '^__secure-',
-     '^my_app_storage$'
-   ]
- }
+ essentialKeys: ['my_app_storage']
```

## Install

```bash
npm install @freshjuice/zest
```

```javascript
// Full build (banner + modal + widget, auto-init)
import Zest from '@freshjuice/zest';

// Headless (BYO UI, manual init)
import Zest from '@freshjuice/zest/headless';
Zest.init({
  essentialKeys: ['my_app_settings'],
  intercept: { scripts: false }
});
```

Or via CDN:

```html
<script src="https://unpkg.com/@freshjuice/zest@2"></script>
```

