Compare commits

...

130 Commits

Author SHA1 Message Date
OpenFeature Bot ee236396cd
chore(main): release react-sdk 1.0.1 (#1235)
🤖 I have created a release *beep* *boop*
---


##
[1.0.1](https://github.com/open-feature/js-sdk/compare/react-sdk-v1.0.0...react-sdk-v1.0.1)
(2025-08-18)


### 🐛 Bug Fixes

* **react:** re-evaluate flags on re-render to detect silent provider …
([#1226](https://github.com/open-feature/js-sdk/issues/1226))
([3105595](3105595926))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Signed-off-by: OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>
2025-08-18 16:26:25 +00:00
Michael Beemer 9aab3d053b
chore: remove hardcoded react v1
Signed-off-by: Michael Beemer <beeme1mr@users.noreply.github.com>
2025-08-18 11:56:09 -04:00
Michael Beemer 3105595926
fix(react): re-evaluate flags on re-render to detect silent provider … (#1226)
## This PR

- Added `useEffect` that runs on re-render to re-evaluate the flag value
- Only updates state if the resolved value actually changed (using
`isEqual` comparison)
- Used lazy initialization for `useState` to avoid redundant initial
evaluation
  - Added `useCallback` memoization for event handlers
  - Fixed `AbortController` scope issue

### Notes

This resolves a subtle issue where the provider state may update without
emitting a change event, leading to confusing results. The `useFlag`
hook sets the initial evaluated value in a `useState`. Since this wasn't
in a closure, this evaluation happened any time the component using the
hook rerendered but the result was essentially ignored. Adding a logging
hook shows that the current results but since this evaluation was made
in an existing `useState`, the result had no effect.

This resolves a subtle issue where the provider state may update without
emitting a change event, leading to stale flag values being displayed.

The `useFlag` hook was evaluating the flag on every re-render (as part
of the `useState` initialization), but because `useState` only uses its
initial value on the first render, these subsequent evaluations were
being discarded. This meant that even though the hook was fetching the
correct updated value from the provider on each re-render, it was
throwing that value away and continuing to display the stale cached
value.

Adding a logging hook would show the correct evaluation happening
(proving the provider had the updated value), but the UI would remain
stuck with the old value because the `useState` was ignoring the
re-evaluated result.

The fix ensures that these re-evaluations on re-render actually update
the component's state when the resolved value changes.

The key insight is that the evaluation WAS happening on every re-render
(due to how useState works), but React was discarding the result. Your
fix makes those evaluations actually matter by checking if the value
changed and updating state accordingly.

Original thread:
https://cloud-native.slack.com/archives/C06E4DE6S07/p1754508917397519

### How to test

I created a test that reproduced the issue, and it failed. I then
implemented the changes and verified that the test passed.

---------

Signed-off-by: Developer <developer@example.com>
Signed-off-by: Michael Beemer <beeme1mr@users.noreply.github.com>
Co-authored-by: Developer <developer@example.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: Lukas Reining <lukas.reining@codecentric.de>
Co-authored-by: Todd Baert <todd.baert@dynatrace.com>
2025-08-18 15:08:51 +00:00
renovate[bot] 1dbbd5161b
chore(deps): update dependency rxjs to v7.8.2 (#1230)
This PR contains the following updates:

| Package | Change | Age | Confidence |
|---|---|---|---|
| [rxjs](https://rxjs.dev)
([source](https://redirect.github.com/reactivex/rxjs)) | [`7.8.1` ->
`7.8.2`](https://renovatebot.com/diffs/npm/rxjs/7.8.1/7.8.2) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/rxjs/7.8.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/rxjs/7.8.1/7.8.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>reactivex/rxjs (rxjs)</summary>

###
[`v7.8.2`](https://redirect.github.com/reactivex/rxjs/compare/7.8.1...7.8.2)

[Compare
Source](https://redirect.github.com/reactivex/rxjs/compare/7.8.1...7.8.2)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled because a matching PR was automerged
previously.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/open-feature/js-sdk).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS43MS4xIiwidXBkYXRlZEluVmVyIjoiNDEuNzEuMSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-15 09:06:37 -04:00
renovate[bot] 2287083de7
chore(deps): update dependency shx to ^0.4.0 (#1213)
This PR contains the following updates:

| Package | Change | Age | Confidence |
|---|---|---|---|
| [shx](https://redirect.github.com/shelljs/shx) | [`^0.3.4` ->
`^0.4.0`](https://renovatebot.com/diffs/npm/shx/0.3.4/0.4.0) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/shx/0.4.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/shx/0.3.4/0.4.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>shelljs/shx (shx)</summary>

###
[`v0.4.0`](https://redirect.github.com/shelljs/shx/releases/tag/v0.4.0)

[Compare
Source](https://redirect.github.com/shelljs/shx/compare/v0.3.4...v0.4.0)

####  Highlighted changes

- This is based on ShellJS v0.9! This means we bumped the minimum node
version to >= v18.
- Small bash compatibility change to `shx sed`. Now if you invoke `shx
sed -i`, this will not print any output to stdout (this is for
consistency with unix `sed`). Using `shx sed` without the `-i` flag will
still print to stdout as before.

#### What's Changed

- chore: remove codecov devDependency by
[@&#8203;nfischer](https://redirect.github.com/nfischer) in
[https://github.com/shelljs/shx/pull/198](https://redirect.github.com/shelljs/shx/pull/198)
- chore(ci): run tests up to node v16 by
[@&#8203;nfischer](https://redirect.github.com/nfischer) in
[https://github.com/shelljs/shx/pull/197](https://redirect.github.com/shelljs/shx/pull/197)
- chore: rename master -> main by
[@&#8203;nfischer](https://redirect.github.com/nfischer) in
[https://github.com/shelljs/shx/pull/204](https://redirect.github.com/shelljs/shx/pull/204)
- chore: update deps by
[@&#8203;nfischer](https://redirect.github.com/nfischer) in
[https://github.com/shelljs/shx/pull/205](https://redirect.github.com/shelljs/shx/pull/205)
- chore: update CI to include v18 by
[@&#8203;nfischer](https://redirect.github.com/nfischer) in
[https://github.com/shelljs/shx/pull/206](https://redirect.github.com/shelljs/shx/pull/206)
- fix(lint): fixes import order lint warnings by
[@&#8203;nfischer](https://redirect.github.com/nfischer) in
[https://github.com/shelljs/shx/pull/215](https://redirect.github.com/shelljs/shx/pull/215)
- doc: highlight globs and emphasize double quotes by
[@&#8203;nfischer](https://redirect.github.com/nfischer) in
[https://github.com/shelljs/shx/pull/214](https://redirect.github.com/shelljs/shx/pull/214)
- chore: update CI to test against node v20 by
[@&#8203;nfischer](https://redirect.github.com/nfischer) in
[https://github.com/shelljs/shx/pull/212](https://redirect.github.com/shelljs/shx/pull/212)
- docs: change GitHub Actions README badge by
[@&#8203;nfischer](https://redirect.github.com/nfischer) in
[https://github.com/shelljs/shx/pull/216](https://redirect.github.com/shelljs/shx/pull/216)
- chore: keep node < 16 around longer by
[@&#8203;nfischer](https://redirect.github.com/nfischer) in
[https://github.com/shelljs/shx/pull/219](https://redirect.github.com/shelljs/shx/pull/219)
- Bump GitHub workflow action to latest version by
[@&#8203;deining](https://redirect.github.com/deining) in
[https://github.com/shelljs/shx/pull/220](https://redirect.github.com/shelljs/shx/pull/220)
- Update minimist for CVE-2021-44906 by
[@&#8203;tomhaines432](https://redirect.github.com/tomhaines432) in
[https://github.com/shelljs/shx/pull/218](https://redirect.github.com/shelljs/shx/pull/218)
- chore: add codecov token by
[@&#8203;nfischer](https://redirect.github.com/nfischer) in
[https://github.com/shelljs/shx/pull/222](https://redirect.github.com/shelljs/shx/pull/222)
- chore: remove unsupported node configs from CI by
[@&#8203;nfischer](https://redirect.github.com/nfischer) in
[https://github.com/shelljs/shx/pull/221](https://redirect.github.com/shelljs/shx/pull/221)
- chore: switch to codecov v4 by
[@&#8203;nfischer](https://redirect.github.com/nfischer) in
[https://github.com/shelljs/shx/pull/223](https://redirect.github.com/shelljs/shx/pull/223)
- chore(dependencies): update js-yaml by
[@&#8203;nfischer](https://redirect.github.com/nfischer) in
[https://github.com/shelljs/shx/pull/224](https://redirect.github.com/shelljs/shx/pull/224)
- doc: Fix typo in README by
[@&#8203;mpaw](https://redirect.github.com/mpaw) in
[https://github.com/shelljs/shx/pull/227](https://redirect.github.com/shelljs/shx/pull/227)
- chore: update shelljs and drop old node support by
[@&#8203;nfischer](https://redirect.github.com/nfischer) in
[https://github.com/shelljs/shx/pull/228](https://redirect.github.com/shelljs/shx/pull/228)
- chore: drop non-LTS node versions by
[@&#8203;nfischer](https://redirect.github.com/nfischer) in
[https://github.com/shelljs/shx/pull/229](https://redirect.github.com/shelljs/shx/pull/229)
- chore: drop some dependencies and simplify by
[@&#8203;nfischer](https://redirect.github.com/nfischer) in
[https://github.com/shelljs/shx/pull/230](https://redirect.github.com/shelljs/shx/pull/230)
- chore: update dependencies by
[@&#8203;nfischer](https://redirect.github.com/nfischer) in
[https://github.com/shelljs/shx/pull/231](https://redirect.github.com/shelljs/shx/pull/231)
- fix: add back ShellJS version in --version by
[@&#8203;nfischer](https://redirect.github.com/nfischer) in
[https://github.com/shelljs/shx/pull/232](https://redirect.github.com/shelljs/shx/pull/232)
- Adding a global --negate flag by
[@&#8203;SoTrx](https://redirect.github.com/SoTrx) in
[https://github.com/shelljs/shx/pull/189](https://redirect.github.com/shelljs/shx/pull/189)
- refactor: code cleanup for the --negate flag by
[@&#8203;nfischer](https://redirect.github.com/nfischer) in
[https://github.com/shelljs/shx/pull/233](https://redirect.github.com/shelljs/shx/pull/233)

#### New Contributors

- [@&#8203;deining](https://redirect.github.com/deining) made their
first contribution in
[https://github.com/shelljs/shx/pull/220](https://redirect.github.com/shelljs/shx/pull/220)
- [@&#8203;tomhaines432](https://redirect.github.com/tomhaines432) made
their first contribution in
[https://github.com/shelljs/shx/pull/218](https://redirect.github.com/shelljs/shx/pull/218)
- [@&#8203;mpaw](https://redirect.github.com/mpaw) made their first
contribution in
[https://github.com/shelljs/shx/pull/227](https://redirect.github.com/shelljs/shx/pull/227)
- [@&#8203;SoTrx](https://redirect.github.com/SoTrx) made their first
contribution in
[https://github.com/shelljs/shx/pull/189](https://redirect.github.com/shelljs/shx/pull/189)

**Full Changelog**:
https://github.com/shelljs/shx/compare/v0.3.4...v0.4.0

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/open-feature/js-sdk).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MC40MC4zIiwidXBkYXRlZEluVmVyIjoiNDEuNzEuMSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-15 09:06:26 -04:00
OpenFeature Bot 04139affcb
chore(main): release server-sdk 1.19.0 (#1181)
🤖 I have created a release *beep* *boop*
---


##
[1.19.0](https://github.com/open-feature/js-sdk/compare/server-sdk-v1.18.0...server-sdk-v1.19.0)
(2025-08-14)


###  New Features

* add evaluation-scoped hook data
([#1216](https://github.com/open-feature/js-sdk/issues/1216))
([07af3a9](07af3a9eda))


### 🐛 Bug Fixes

* update core dep
([#1228](https://github.com/open-feature/js-sdk/issues/1228))
([845d24c](845d24c5fe))


### 🧹 Chore

* update node to v20+
([#1203](https://github.com/open-feature/js-sdk/issues/1203))
([1f33453](1f33453c23))


### 📚 Documentation

* Clarify the behavior of setProviderAndWait
([#1180](https://github.com/open-feature/js-sdk/issues/1180))
([4fe8d87](4fe8d87a2e))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Signed-off-by: OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
Co-authored-by: Todd Baert <todd.baert@dynatrace.com>
2025-08-14 15:57:34 -04:00
OpenFeature Bot 1e330a2e13
chore(main): release web-sdk 1.6.1 (#1229)
🤖 I have created a release *beep* *boop*
---


##
[1.6.1](https://github.com/open-feature/js-sdk/compare/web-sdk-v1.6.0...web-sdk-v1.6.1)
(2025-08-14)


### 🐛 Bug Fixes

* update core dep
([#1228](https://github.com/open-feature/js-sdk/issues/1228))
([845d24c](845d24c5fe))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Signed-off-by: OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>
2025-08-14 13:37:46 -04:00
Todd Baert 7df8a8eedc
chore: engine version in root
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
2025-08-14 13:28:59 -04:00
Todd Baert 3b3515b601 chore: fix lockfile again
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
2025-08-14 13:18:01 -04:00
Todd Baert 63a1feb213 chore: fix lockfile
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
2025-08-14 13:10:38 -04:00
Todd Baert 845d24c5fe
fix: update core dep (#1228)
As astutely pointed out by @JasperJuergensen in
https://github.com/open-feature/js-sdk/issues/1227, we added API surface
in core which we use in the latest web, but did't accordingly update the
min version of core in web.

(I also updated the min core version in server, just because).

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
2025-08-14 13:03:20 -04:00
OpenFeature Bot dc1970e717
chore(main): release web-sdk 1.6.0 (#1182)
🤖 I have created a release *beep* *boop*
---


##
[1.6.0](https://github.com/open-feature/js-sdk/compare/web-sdk-v1.5.0...web-sdk-v1.6.0)
(2025-08-12)


###  New Features

* add evaluation-scoped hook data
([#1216](https://github.com/open-feature/js-sdk/issues/1216))
([07af3a9](07af3a9eda))
* **web-global-build:** publish web packages to unpkg and jsdelivr
([#1225](https://github.com/open-feature/js-sdk/issues/1225))
([40a512e](40a512e212))


### 📚 Documentation

* Clarify the behavior of setProviderAndWait
([#1180](https://github.com/open-feature/js-sdk/issues/1180))
([4fe8d87](4fe8d87a2e))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Signed-off-by: OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>
2025-08-12 23:27:08 +02:00
OpenFeature Bot e6e5ff3edf
chore(main): release core 1.9.0 (#1219)
🤖 I have created a release *beep* *boop*
---


##
[1.9.0](https://github.com/open-feature/js-sdk/compare/core-v1.8.1...core-v1.9.0)
(2025-08-10)


###  New Features

* add evaluation-scoped hook data
([#1216](https://github.com/open-feature/js-sdk/issues/1216))
([07af3a9](07af3a9eda))
* support Angular 20
([#1220](https://github.com/open-feature/js-sdk/issues/1220))
([aa232a9](aa232a9d6a))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Signed-off-by: OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>
2025-08-12 21:08:51 +00:00
Patryk Zdunowski 40a512e212
feat(web-global-build): impl (#1225)
<!-- Please use this template for your pull request. -->
<!-- Please use the sections that you need and delete other sections -->

## This PR

- Implements a global (IIFE) build for the web.
- Adds support for global distribution via CDN by including `unpkg` and
`jsdelivr` fields in `package.json`.

### Notes

- The global build outputs to `dist/global/index.js`.
- The global bundle is exposed under the global name `OpenFeature`.

### Follow-up Tasks

- Consider adding automated tests or validation for the global bundle.
- If this bundle should be included in a release checklist or CI, link
the appropriate issue here.

### How to test

1. Run `npm run build` and ensure `dist/global/index.js` is generated.
2. Serve the file locally or upload to a CDN and verify that
`window.OpenFeature` is available in the browser console.

### Motivation
Trying to load OpenFeature as a first dependency before browser will
resolve any modules.

---------

Signed-off-by: Patryk Zdunowski <zdunekhere@gmail.com>
2025-08-10 14:24:01 +00:00
OpenFeature Bot 28850b7f6d
chore(main): release angular-sdk 0.0.16 (#1221) 2025-07-25 21:18:43 +02:00
Lukas Reining aa232a9d6a
feat: support Angular 20 (#1220)
Adds Angular 20 support.

This also remove the custom jest setup as it was not compatible with
Angular 20 and uses builtin support for vitest in Angular 20.
For this, Angular has been removed from the jest setup and the pipeline
runs it separately now.

Fixes #1206

---------

Signed-off-by: Lukas Reining <lukas.reining@codecentric.de>
2025-07-25 18:48:38 +02:00
Michael Beemer 07af3a9eda
feat: add evaluation-scoped hook data (#1216)
Signed-off-by: Michael Beemer <beeme1mr@users.noreply.github.com>
2025-07-18 15:08:01 -04:00
OpenFeature Bot d8bd93b6d5
chore(main): release core 1.8.1 (#1208)
🤖 I have created a release *beep* *boop*
---


##
[1.8.1](https://github.com/open-feature/js-sdk/compare/core-v1.8.0...core-v1.8.1)
(2025-06-04)


### 🔄 Refactoring

* **telemetry:** update telemetry attributes and remove unused
evaluation data
([#1189](https://github.com/open-feature/js-sdk/issues/1189))
([3e6bcae](3e6bcaef0b))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Signed-off-by: OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>
2025-06-26 20:15:03 +00:00
renovate[bot] 1b3ac12a35
chore(deps): update dependency eslint-plugin-jsdoc to v50.7.1 (#1211)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[eslint-plugin-jsdoc](https://redirect.github.com/gajus/eslint-plugin-jsdoc)
| [`50.7.0` ->
`50.7.1`](https://renovatebot.com/diffs/npm/eslint-plugin-jsdoc/50.7.0/50.7.1)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/eslint-plugin-jsdoc/50.7.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/eslint-plugin-jsdoc/50.7.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/eslint-plugin-jsdoc/50.7.0/50.7.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/eslint-plugin-jsdoc/50.7.0/50.7.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>gajus/eslint-plugin-jsdoc (eslint-plugin-jsdoc)</summary>

###
[`v50.7.1`](https://redirect.github.com/gajus/eslint-plugin-jsdoc/releases/tag/v50.7.1)

[Compare
Source](https://redirect.github.com/gajus/eslint-plugin-jsdoc/compare/v50.7.0...v50.7.1)

##### Bug Fixes

- revert are-docs-informative upgrade; fixes
[#&#8203;1393](https://redirect.github.com/gajus/eslint-plugin-jsdoc/issues/1393)
([#&#8203;1394](https://redirect.github.com/gajus/eslint-plugin-jsdoc/issues/1394))
([99cb131](99cb131ee4))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/open-feature/js-sdk).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MC40MC4zIiwidXBkYXRlZEluVmVyIjoiNDAuNDAuMyIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-04 18:54:59 +00:00
Todd Baert d3bca54979
chore: update workflows to node 20 (#1209)
I missed a few workflows when I updated the node version. We should
update these for consistency.

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
2025-06-04 14:54:45 -04:00
renovate[bot] baf0dfbd5b
chore(deps): update dependency rollup-plugin-dts to v6.2.1 (#1196)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[rollup-plugin-dts](https://redirect.github.com/Swatinem/rollup-plugin-dts)
| [`6.1.1` ->
`6.2.1`](https://renovatebot.com/diffs/npm/rollup-plugin-dts/6.1.1/6.2.1)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/rollup-plugin-dts/6.2.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/rollup-plugin-dts/6.2.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/rollup-plugin-dts/6.1.1/6.2.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/rollup-plugin-dts/6.1.1/6.2.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>Swatinem/rollup-plugin-dts (rollup-plugin-dts)</summary>

###
[`v6.2.1`](https://redirect.github.com/Swatinem/rollup-plugin-dts/compare/v6.2.0...v6.2.1)

[Compare
Source](https://redirect.github.com/Swatinem/rollup-plugin-dts/compare/v6.2.0...v6.2.1)

###
[`v6.2.0`](https://redirect.github.com/Swatinem/rollup-plugin-dts/blob/HEAD/CHANGELOG.md#620)

[Compare
Source](https://redirect.github.com/Swatinem/rollup-plugin-dts/compare/v6.1.1...v6.2.0)

**Features**:

-   Support importing json modules
-   Return Source Map Differences to Rollup

**Fixes**:

- Unable to find the program when entry points exist intersection
dependency
-   Create program for `imports` input file
-   Force emit types even when there's errors
-   Preserve type members of namespace in re-exported module
-   Imports and exports follows type-only
-   Import "local types" from "global modules"
-   Correctly restore type-only import/export names

**Thank you**:

Features, fixes and improvements in this release have been contributed
by:

-   [@&#8203;NWYLZW](https://redirect.github.com/NWYLZW)
-   [@&#8203;castarco](https://redirect.github.com/castarco)
-   [@&#8203;hyrious](https://redirect.github.com/hyrious)
-   [@&#8203;andersk](https://redirect.github.com/andersk)
-   [@&#8203;kricsleo](https://redirect.github.com/kricsleo)
-   [@&#8203;alan-agius4](https://redirect.github.com/alan-agius4)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/open-feature/js-sdk).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MC4xMS4xOCIsInVwZGF0ZWRJblZlciI6IjQwLjExLjE4IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-04 16:34:40 +00:00
renovate[bot] 2fd944d317
chore(deps): update dependency eslint-plugin-jsdoc to v50.7.0 (#1199)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[eslint-plugin-jsdoc](https://redirect.github.com/gajus/eslint-plugin-jsdoc)
| [`50.6.14` ->
`50.7.0`](https://renovatebot.com/diffs/npm/eslint-plugin-jsdoc/50.6.14/50.7.0)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/eslint-plugin-jsdoc/50.7.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/eslint-plugin-jsdoc/50.7.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/eslint-plugin-jsdoc/50.6.14/50.7.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/eslint-plugin-jsdoc/50.6.14/50.7.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>gajus/eslint-plugin-jsdoc (eslint-plugin-jsdoc)</summary>

###
[`v50.7.0`](https://redirect.github.com/gajus/eslint-plugin-jsdoc/releases/tag/v50.7.0)

[Compare
Source](https://redirect.github.com/gajus/eslint-plugin-jsdoc/compare/v50.6.17...v50.7.0)

##### Features

- **`getJsdocProcessorPlugin`:** add `allowedLanguagesToProcess` option
([#&#8203;1392](https://redirect.github.com/gajus/eslint-plugin-jsdoc/issues/1392))
([0adbf43](0adbf43b6b))

###
[`v50.6.17`](https://redirect.github.com/gajus/eslint-plugin-jsdoc/releases/tag/v50.6.17)

[Compare
Source](https://redirect.github.com/gajus/eslint-plugin-jsdoc/compare/v50.6.16...v50.6.17)

##### Bug Fixes

- **`require-param`:** update jsdoccomment to support exported
TSFunctionType type; fixes
[#&#8203;1386](https://redirect.github.com/gajus/eslint-plugin-jsdoc/issues/1386)
([#&#8203;1389](https://redirect.github.com/gajus/eslint-plugin-jsdoc/issues/1389))
([e26a11a](e26a11a399))

###
[`v50.6.16`](https://redirect.github.com/gajus/eslint-plugin-jsdoc/releases/tag/v50.6.16)

[Compare
Source](https://redirect.github.com/gajus/eslint-plugin-jsdoc/compare/v50.6.15...v50.6.16)

##### Bug Fixes

- **`valid-types`:** fix parsing of expressions like
`[@returns](https://redirect.github.com/returns)
{[@&#8203;link](https://redirect.github.com/link) SomeType}`; fixes
[#&#8203;1381](https://redirect.github.com/gajus/eslint-plugin-jsdoc/issues/1381)
([#&#8203;1382](https://redirect.github.com/gajus/eslint-plugin-jsdoc/issues/1382))
([2bd7242](2bd7242901))

###
[`v50.6.15`](https://redirect.github.com/gajus/eslint-plugin-jsdoc/releases/tag/v50.6.15)

[Compare
Source](https://redirect.github.com/gajus/eslint-plugin-jsdoc/compare/v50.6.14...v50.6.15)

##### Bug Fixes

- **`no-undefined-types`:** avoid eslint 8 error; fixes
[#&#8203;1387](https://redirect.github.com/gajus/eslint-plugin-jsdoc/issues/1387)
([#&#8203;1388](https://redirect.github.com/gajus/eslint-plugin-jsdoc/issues/1388))
([1bef636](1bef63677e))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/open-feature/js-sdk).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MC4xNi4wIiwidXBkYXRlZEluVmVyIjoiNDAuMzMuNiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-04 16:34:07 +00:00
renovate[bot] 3598b5e822
chore(deps): update dependency rollup to v4.41.1 (#1205)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [rollup](https://rollupjs.org/)
([source](https://redirect.github.com/rollup/rollup)) | [`4.40.2` ->
`4.41.1`](https://renovatebot.com/diffs/npm/rollup/4.40.2/4.41.1) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/rollup/4.41.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/rollup/4.41.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/rollup/4.40.2/4.41.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/rollup/4.40.2/4.41.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>rollup/rollup (rollup)</summary>

###
[`v4.41.1`](https://redirect.github.com/rollup/rollup/blob/HEAD/CHANGELOG.md#4411)

[Compare
Source](https://redirect.github.com/rollup/rollup/compare/v4.41.0...v4.41.1)

*2025-05-24*

##### Bug Fixes

- If a plugin calls `this.resolve` with `skipSelf: true`, subsequent
calls when handling this by the same plugin with same parameters will
return `null` to avoid infinite recursions
([#&#8203;5945](https://redirect.github.com/rollup/rollup/issues/5945))

##### Pull Requests

- [#&#8203;5945](https://redirect.github.com/rollup/rollup/pull/5945):
Avoid recursively calling a plugin's resolveId hook with same id and
importer ([@&#8203;younggglcy](https://redirect.github.com/younggglcy),
[@&#8203;lukastaegert](https://redirect.github.com/lukastaegert))
- [#&#8203;5963](https://redirect.github.com/rollup/rollup/pull/5963):
fix(deps): update swc monorepo (major)
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])
- [#&#8203;5964](https://redirect.github.com/rollup/rollup/pull/5964):
fix(deps): lock file maintenance minor/patch updates
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])

###
[`v4.41.0`](https://redirect.github.com/rollup/rollup/blob/HEAD/CHANGELOG.md#4410)

[Compare
Source](https://redirect.github.com/rollup/rollup/compare/v4.40.2...v4.41.0)

*2025-05-18*

##### Features

- Detect named exports in more dynamic import scenarios
([#&#8203;5954](https://redirect.github.com/rollup/rollup/issues/5954))

##### Pull Requests

- [#&#8203;5949](https://redirect.github.com/rollup/rollup/pull/5949):
ci: use node 24 ([@&#8203;btea](https://redirect.github.com/btea),
[@&#8203;lukastaegert](https://redirect.github.com/lukastaegert))
- [#&#8203;5951](https://redirect.github.com/rollup/rollup/pull/5951):
chore(deps): update dependency pretty-bytes to v7
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])
- [#&#8203;5952](https://redirect.github.com/rollup/rollup/pull/5952):
fix(deps): update swc monorepo (major)
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot],
[@&#8203;lukastaegert](https://redirect.github.com/lukastaegert))
- [#&#8203;5953](https://redirect.github.com/rollup/rollup/pull/5953):
chore(deps): lock file maintenance minor/patch updates
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])
- [#&#8203;5954](https://redirect.github.com/rollup/rollup/pull/5954):
enhance tree-shaking for dynamic imports
([@&#8203;TrickyPi](https://redirect.github.com/TrickyPi),
[@&#8203;renovate](https://redirect.github.com/renovate)\[bot],
[@&#8203;lukastaegert](https://redirect.github.com/lukastaegert))
- [#&#8203;5957](https://redirect.github.com/rollup/rollup/pull/5957):
chore(deps): update dependency lint-staged to v16
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot],
[@&#8203;lukastaegert](https://redirect.github.com/lukastaegert))
- [#&#8203;5958](https://redirect.github.com/rollup/rollup/pull/5958):
fix(deps): update rust crate swc_compiler_base to v20
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot],
[@&#8203;lukastaegert](https://redirect.github.com/lukastaegert))
- [#&#8203;5959](https://redirect.github.com/rollup/rollup/pull/5959):
fix(deps): lock file maintenance minor/patch updates
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot],
[@&#8203;lukastaegert](https://redirect.github.com/lukastaegert))
- [#&#8203;5960](https://redirect.github.com/rollup/rollup/pull/5960):
Use spawn to run CLI tests
([@&#8203;lukastaegert](https://redirect.github.com/lukastaegert))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/open-feature/js-sdk).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MC4zMy42IiwidXBkYXRlZEluVmVyIjoiNDAuMzMuNiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-04 16:32:59 +00:00
renovate[bot] 52ed31ad96
chore(deps): update dependency esbuild to v0.25.5 (#1204)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [esbuild](https://redirect.github.com/evanw/esbuild) | [`0.25.4` ->
`0.25.5`](https://renovatebot.com/diffs/npm/esbuild/0.25.4/0.25.5) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/esbuild/0.25.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/esbuild/0.25.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/esbuild/0.25.4/0.25.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/esbuild/0.25.4/0.25.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>evanw/esbuild (esbuild)</summary>

###
[`v0.25.5`](https://redirect.github.com/evanw/esbuild/blob/HEAD/CHANGELOG.md#0255)

[Compare
Source](https://redirect.github.com/evanw/esbuild/compare/v0.25.4...v0.25.5)

- Fix a regression with `browser` in `package.json`
([#&#8203;4187](https://redirect.github.com/evanw/esbuild/issues/4187))

The fix to
[#&#8203;4144](https://redirect.github.com/evanw/esbuild/issues/4144) in
version 0.25.3 introduced a regression that caused `browser` overrides
specified in `package.json` to fail to override relative path names that
end in a trailing slash. That behavior change affected the
`axios@0.30.0` package. This regression has been fixed, and now has test
coverage.

- Add support for certain keywords as TypeScript tuple labels
([#&#8203;4192](https://redirect.github.com/evanw/esbuild/issues/4192))

Previously esbuild could incorrectly fail to parse certain keywords as
TypeScript tuple labels that are parsed by the official TypeScript
compiler if they were followed by a `?` modifier. These labels included
`function`, `import`, `infer`, `new`, `readonly`, and `typeof`. With
this release, these keywords will now be parsed correctly. Here's an
example of some affected code:

    ```ts
    type Foo = [
      value: any,
      readonly?: boolean, // This is now parsed correctly
    ]
    ```

- Add CSS prefixes for the `stretch` sizing value
([#&#8203;4184](https://redirect.github.com/evanw/esbuild/issues/4184))

This release adds support for prefixing CSS declarations such as `div {
width: stretch }`. That CSS is now transformed into this depending on
what the `--target=` setting includes:

    ```css
    div {
      width: -webkit-fill-available;
      width: -moz-available;
      width: stretch;
    }
    ```

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/open-feature/js-sdk).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MC4zMy42IiwidXBkYXRlZEluVmVyIjoiNDAuMzMuNiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-04 12:33:54 -04:00
Michael Beemer 3e6bcaef0b
refactor(telemetry): update telemetry attributes and remove unused evaluation data (#1189)
## This PR

- update the evaluation event to match the latest OTel semcon

### Related Issues

Fixes #1188

### Notes

Update the createEvaluationEvent to match the latest OpenTelemetry spec.
Unforutnately, this is a breaking change. I'll denote this in the
release notes but not in the library version. That's because we're
following the experimental OTel spec and the method itself is currently
undocumented except from the generated JS Doc.

It's also worth noting that OTel JS SDK event API doesn't currently
support object as attribute values. @dyladan will update the OTel SDK.

### Follow-up Tasks

Update the ToggleShop.

### How to test

`npm run test`

Signed-off-by: Michael Beemer <beeme1mr@users.noreply.github.com>
2025-06-03 13:51:28 +00:00
renovate[bot] 66a3ce05af
chore(deps): update dependency @types/node to v22.15.23 (#1198)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[@types/node](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node)
([source](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node))
| [`22.15.17` ->
`22.15.23`](https://renovatebot.com/diffs/npm/@types%2fnode/22.15.17/22.15.23)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2fnode/22.15.23?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2fnode/22.15.23?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2fnode/22.15.17/22.15.23?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2fnode/22.15.17/22.15.23?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/open-feature/js-sdk).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MC4xNi4wIiwidXBkYXRlZEluVmVyIjoiNDAuMzMuNiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-30 20:46:03 +00:00
renovate[bot] 1cb4a506aa
chore(deps): update dependency prettier to v3.5.3 (#1195)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [prettier](https://prettier.io)
([source](https://redirect.github.com/prettier/prettier)) | [`3.4.2` ->
`3.5.3`](https://renovatebot.com/diffs/npm/prettier/3.4.2/3.5.3) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/prettier/3.5.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/prettier/3.5.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/prettier/3.4.2/3.5.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/prettier/3.4.2/3.5.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>prettier/prettier (prettier)</summary>

###
[`v3.5.3`](https://redirect.github.com/prettier/prettier/compare/3.5.2...b51ba9d46765bcfab714ebca982bd04ad25ae562)

[Compare
Source](https://redirect.github.com/prettier/prettier/compare/3.5.2...3.5.3)

###
[`v3.5.2`](https://redirect.github.com/prettier/prettier/blob/HEAD/CHANGELOG.md#352)

[Compare
Source](https://redirect.github.com/prettier/prettier/compare/3.5.1...3.5.2)


[diff](https://redirect.github.com/prettier/prettier/compare/3.5.1...3.5.2)

##### Remove `module-sync` condition
([#&#8203;17156](https://redirect.github.com/prettier/prettier/pull/17156)
by [@&#8203;fisker](https://redirect.github.com/fisker))

In Prettier 3.5.0, [we added `module-sync` condition to
`package.json`](https://prettier.io/blog/2025/02/09/3.5.0#use-esm-entrypoint-for-requireesm-16958-by-tats-u),
so that `require("prettier")` can use ESM version, but turns out it
doesn't work if CommonJS and ESM plugins both imports builtin plugins.
To solve this problem, we decide simply remove the `module-sync`
condition, so `require("prettier")` will still use the CommonJS version,
we'll revisit until `require(ESM)` feature is more stable.

###
[`v3.5.1`](https://redirect.github.com/prettier/prettier/blob/HEAD/CHANGELOG.md#351)

[Compare
Source](https://redirect.github.com/prettier/prettier/compare/3.5.0...3.5.1)


[diff](https://redirect.github.com/prettier/prettier/compare/3.5.0...3.5.1)

##### Fix CLI crash when cache for old version exists
([#&#8203;17100](https://redirect.github.com/prettier/prettier/pull/17100)
by [@&#8203;sosukesuzuki](https://redirect.github.com/sosukesuzuki))

Prettier 3.5 uses a different cache format than previous versions,
Prettier 3.5.0 crashes when reading existing cache file, Prettier 3.5.1
fixed the problem.

##### Support dockercompose and github-actions-workflow in VSCode
([#&#8203;17101](https://redirect.github.com/prettier/prettier/pull/17101)
by [@&#8203;remcohaszing](https://redirect.github.com/remcohaszing))

Prettier now supports the `dockercompose` and `github-actions-workflow`
languages in Visual Studio Code.

###
[`v3.5.0`](https://redirect.github.com/prettier/prettier/blob/HEAD/CHANGELOG.md#350)

[Compare
Source](https://redirect.github.com/prettier/prettier/compare/3.4.2...3.5.0)


[diff](https://redirect.github.com/prettier/prettier/compare/3.4.2...3.5.0)

🔗 [Release Notes](https://prettier.io/blog/2025/02/09/3.5.0.html)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/open-feature/js-sdk).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MC4xMS4xOCIsInVwZGF0ZWRJblZlciI6IjQwLjExLjE4IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-30 20:45:45 +00:00
Todd Baert 1f33453c23
chore: update node to v20+ (#1203)
node v18 is now EOL

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
2025-05-29 19:38:31 +00:00
OpenFeature Bot 2838d6afce
chore(main): release nestjs-sdk 0.2.5 (#1183)
🤖 I have created a release *beep* *boop*
---


##
[0.2.5](https://github.com/open-feature/js-sdk/compare/nestjs-sdk-v0.2.4...nestjs-sdk-v0.2.5)
(2025-05-27)


###  New Features

* adds RequireFlagsEnabled decorator
([#1159](https://github.com/open-feature/js-sdk/issues/1159))
([59b8fe9](59b8fe904f))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

---------

Signed-off-by: OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>
Signed-off-by: Lukas Reining <lukas.reining@codecentric.de>
Co-authored-by: Lukas Reining <lukas.reining@codecentric.de>
2025-05-27 22:08:11 +00:00
Lukas Reining aadc7a6636
fix: environment for npm publish (#1202)
Adds the environment for NPM publish step of the pipeline to the correct
job.

Signed-off-by: Lukas Reining <lukas.reining@codecentric.de>
2025-05-27 23:51:57 +02:00
OpenFeature Bot dae36bba1f
chore(main): release angular-sdk 0.0.15 (#1201)
🤖 I have created a release *beep* *boop*
---


##
[0.0.15](https://github.com/open-feature/js-sdk/compare/angular-sdk-v0.0.14...angular-sdk-v0.0.15)
(2025-05-27)


### 🐛 Bug Fixes

* **angular:** update docs
([#1200](https://github.com/open-feature/js-sdk/issues/1200))
([b6ea588](b6ea5884f2))


### Dependencies

* The following workspace dependencies were updated
  * devDependencies
    * @openfeature/web-sdk bumped from * to 1.5.1

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

---------

Signed-off-by: OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>
Signed-off-by: Lukas Reining <lukas.reining@codecentric.de>
Co-authored-by: Lukas Reining <lukas.reining@codecentric.de>
2025-05-27 22:56:32 +02:00
Lukas Reining b6ea5884f2
fix(angular): update docs (#1200)
Signed-off-by: Lukas Reining <lukas.reining@codecentric.de>
2025-05-27 22:50:11 +02:00
renovate[bot] affdecb619
chore(deps): update dependency jest-preset-angular to v14.5.5 (#1192)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [jest-preset-angular](https://thymikee.github.io/jest-preset-angular)
([source](https://redirect.github.com/thymikee/jest-preset-angular)) |
[`14.5.1` ->
`14.5.5`](https://renovatebot.com/diffs/npm/jest-preset-angular/14.5.1/14.5.5)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/jest-preset-angular/14.5.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/jest-preset-angular/14.5.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/jest-preset-angular/14.5.1/14.5.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/jest-preset-angular/14.5.1/14.5.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>thymikee/jest-preset-angular (jest-preset-angular)</summary>

###
[`v14.5.5`](https://redirect.github.com/thymikee/jest-preset-angular/blob/HEAD/CHANGELOG.md#1455-2025-04-15)

[Compare
Source](https://redirect.github.com/thymikee/jest-preset-angular/compare/v14.5.4...v14.5.5)

##### Bug Fixes

- fix: allow name exports for `presets` subpath
([9100baf](https://redirect.github.com/thymikee/jest-preset-angular/commit/9100baf))

###
[`v14.5.4`](https://redirect.github.com/thymikee/jest-preset-angular/blob/HEAD/CHANGELOG.md#1454-2025-03-31)

[Compare
Source](https://redirect.github.com/thymikee/jest-preset-angular/compare/v14.5.3...v14.5.4)

##### Bug Fixes

- fix: warn when using both `isolatedModules` and
`emitDecoratorMetadata`
([#&#8203;3029](https://redirect.github.com/thymikee/jest-preset-angular/issues/3029))
([51db8f4](https://redirect.github.com/thymikee/jest-preset-angular/commit/51db8f4)),
closes
[#&#8203;3029](https://redirect.github.com/thymikee/jest-preset-angular/issues/3029)
- update dependency ts-jest to v29.3.0
([1d8415d](https://redirect.github.com/thymikee/jest-preset-angular/commit/1d8415d))

###
[`v14.5.3`](https://redirect.github.com/thymikee/jest-preset-angular/blob/HEAD/CHANGELOG.md#1453-2025-02-24)

[Compare
Source](https://redirect.github.com/thymikee/jest-preset-angular/compare/v14.5.2...v14.5.3)

##### Bug Fixes

- build: update bundle `jit_transform.js`, closes
[#&#8203;2979](https://redirect.github.com/thymikee/jest-preset-angular/issues/2979)

###
[`v14.5.2`](https://redirect.github.com/thymikee/jest-preset-angular/blob/HEAD/CHANGELOG.md#1452-2025-02-21)

[Compare
Source](https://redirect.github.com/thymikee/jest-preset-angular/compare/v14.5.1...v14.5.2)

##### Bug Fixes

- fix: transform `js` ESM file from `node_modules`
([b2b3934](https://redirect.github.com/thymikee/jest-preset-angular/commit/b2b3934)),
closes
[#&#8203;2913](https://redirect.github.com/thymikee/jest-preset-angular/issues/2913)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/open-feature/js-sdk).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MC4xMS4xOCIsInVwZGF0ZWRJblZlciI6IjQwLjExLjE4IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-26 17:57:01 +00:00
renovate[bot] f2121671fa
chore(deps): update dependency rxjs to v7.8.2 (#1193)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [rxjs](https://rxjs.dev)
([source](https://redirect.github.com/reactivex/rxjs)) | [`7.8.1` ->
`7.8.2`](https://renovatebot.com/diffs/npm/rxjs/7.8.1/7.8.2) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/rxjs/7.8.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/rxjs/7.8.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/rxjs/7.8.1/7.8.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/rxjs/7.8.1/7.8.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>reactivex/rxjs (rxjs)</summary>

###
[`v7.8.2`](https://redirect.github.com/reactivex/rxjs/compare/7.8.1...7.8.2)

[Compare
Source](https://redirect.github.com/reactivex/rxjs/compare/7.8.1...7.8.2)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/open-feature/js-sdk).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MC4xMS4xOCIsInVwZGF0ZWRJblZlciI6IjQwLjExLjE4IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-26 17:53:11 +00:00
OpenFeature Bot 9f887a965c
chore(main): release angular-sdk 0.0.14 (#1178)
🤖 I have created a release *beep* *boop*
---


##
[0.0.14](https://github.com/open-feature/js-sdk/compare/angular-sdk-v0.0.13...angular-sdk-v0.0.14)
(2025-05-25)


### 🐛 Bug Fixes

* **angular:** add license and url field to package.json
([b2784f5](b2784f53b8))


### Dependencies

* The following workspace dependencies were updated
  * devDependencies
    * @openfeature/web-sdk bumped from * to 1.5.1

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

---------

Signed-off-by: OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>
Signed-off-by: Lukas Reining <lukas.reining@codecentric.de>
Co-authored-by: Lukas Reining <lukas.reining@codecentric.de>
2025-05-25 12:07:48 +02:00
Lukas Reining b2784f53b8 fix(angular): add license and url field to package.json
Signed-off-by: Lukas Reining <lukas.reining@codecentric.de>
2025-05-25 12:00:05 +02:00
renovate[bot] 14761998bf
chore(deps): update dependency eslint-plugin-jsdoc to v50.6.14 (#1191)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[eslint-plugin-jsdoc](https://redirect.github.com/gajus/eslint-plugin-jsdoc)
| [`50.6.3` ->
`50.6.14`](https://renovatebot.com/diffs/npm/eslint-plugin-jsdoc/50.6.3/50.6.14)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/eslint-plugin-jsdoc/50.6.14?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/eslint-plugin-jsdoc/50.6.14?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/eslint-plugin-jsdoc/50.6.3/50.6.14?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/eslint-plugin-jsdoc/50.6.3/50.6.14?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>gajus/eslint-plugin-jsdoc (eslint-plugin-jsdoc)</summary>

###
[`v50.6.14`](https://redirect.github.com/gajus/eslint-plugin-jsdoc/releases/tag/v50.6.14)

[Compare
Source](https://redirect.github.com/gajus/eslint-plugin-jsdoc/compare/v50.6.13...v50.6.14)

##### Bug Fixes

- **lines-before-block:** Switch to a whitelist of punctuators
([#&#8203;1385](https://redirect.github.com/gajus/eslint-plugin-jsdoc/issues/1385))
([0a30832](0a30832b41))

###
[`v50.6.13`](https://redirect.github.com/gajus/eslint-plugin-jsdoc/releases/tag/v50.6.13)

[Compare
Source](https://redirect.github.com/gajus/eslint-plugin-jsdoc/compare/v50.6.12...v50.6.13)

##### Bug Fixes

- **`lines-before-block`:** Only trigger after ';', '}', '|', and '&'
([#&#8203;1383](https://redirect.github.com/gajus/eslint-plugin-jsdoc/issues/1383))
([19fa3dc](19fa3dcb32)),
closes
[#&#8203;1379](https://redirect.github.com/gajus/eslint-plugin-jsdoc/issues/1379)
[#&#8203;1343](https://redirect.github.com/gajus/eslint-plugin-jsdoc/issues/1343)

###
[`v50.6.12`](https://redirect.github.com/gajus/eslint-plugin-jsdoc/releases/tag/v50.6.12)

[Compare
Source](https://redirect.github.com/gajus/eslint-plugin-jsdoc/compare/v50.6.11...v50.6.12)

##### Bug Fixes

- **`no-undefined-types`:** workaround `parse-imports-exports` bug in
handling trailing whitespace; fixes
[#&#8203;1373](https://redirect.github.com/gajus/eslint-plugin-jsdoc/issues/1373)
([#&#8203;1384](https://redirect.github.com/gajus/eslint-plugin-jsdoc/issues/1384))
([f32989c](f32989c259))

###
[`v50.6.11`](https://redirect.github.com/gajus/eslint-plugin-jsdoc/releases/tag/v50.6.11)

[Compare
Source](https://redirect.github.com/gajus/eslint-plugin-jsdoc/compare/v50.6.10...v50.6.11)

##### Bug Fixes

- **`check-values`:** workaround `parse-imports-exports` bug in handling
trailing whitespace; fixes
[#&#8203;1373](https://redirect.github.com/gajus/eslint-plugin-jsdoc/issues/1373)
([#&#8203;1374](https://redirect.github.com/gajus/eslint-plugin-jsdoc/issues/1374))
([65b0dc0](65b0dc0f58))

###
[`v50.6.10`](https://redirect.github.com/gajus/eslint-plugin-jsdoc/releases/tag/v50.6.10)

[Compare
Source](https://redirect.github.com/gajus/eslint-plugin-jsdoc/compare/v50.6.9...v50.6.10)

##### Bug Fixes

- **`check-values`, `no-undefined-types`:** avoid need for worker; fixes
[#&#8203;1371](https://redirect.github.com/gajus/eslint-plugin-jsdoc/issues/1371)
([#&#8203;1372](https://redirect.github.com/gajus/eslint-plugin-jsdoc/issues/1372))
([6d5c9fb](6d5c9fb650))

###
[`v50.6.9`](https://redirect.github.com/gajus/eslint-plugin-jsdoc/releases/tag/v50.6.9)

[Compare
Source](https://redirect.github.com/gajus/eslint-plugin-jsdoc/compare/v50.6.8...v50.6.9)

##### Reverts

- Revert "refactor: replace `synckit` with `make-synchronized`
([#&#8203;1366](https://redirect.github.com/gajus/eslint-plugin-jsdoc/issues/1366))"
([#&#8203;1367](https://redirect.github.com/gajus/eslint-plugin-jsdoc/issues/1367))
([771eadf](771eadfa44))

###
[`v50.6.8`](https://redirect.github.com/gajus/eslint-plugin-jsdoc/releases/tag/v50.6.8)

[Compare
Source](https://redirect.github.com/gajus/eslint-plugin-jsdoc/compare/v50.6.7...v50.6.8)

##### Bug Fixes

- add missing config type(s)
([#&#8203;1365](https://redirect.github.com/gajus/eslint-plugin-jsdoc/issues/1365))
([ed62262](ed622628fc))

###
[`v50.6.7`](https://redirect.github.com/gajus/eslint-plugin-jsdoc/releases/tag/v50.6.7)

[Compare
Source](https://redirect.github.com/gajus/eslint-plugin-jsdoc/compare/v50.6.6...v50.6.7)

##### Bug Fixes

- **no-undefined-types:** allow any available identifier; fixes
[#&#8203;178](https://redirect.github.com/gajus/eslint-plugin-jsdoc/issues/178),[#&#8203;1342](https://redirect.github.com/gajus/eslint-plugin-jsdoc/issues/1342)
([1c38930](1c38930dd1))

###
[`v50.6.6`](https://redirect.github.com/gajus/eslint-plugin-jsdoc/releases/tag/v50.6.6)

[Compare
Source](https://redirect.github.com/gajus/eslint-plugin-jsdoc/compare/v50.6.5...v50.6.6)

##### Bug Fixes

- **`empty-tags`:** allow for JSDoc-block final asterisks; fixes
[#&#8203;670](https://redirect.github.com/gajus/eslint-plugin-jsdoc/issues/670)
([23b4bfa](23b4bfa1a8))

###
[`v50.6.5`](https://redirect.github.com/gajus/eslint-plugin-jsdoc/releases/tag/v50.6.5)

[Compare
Source](https://redirect.github.com/gajus/eslint-plugin-jsdoc/compare/v50.6.4...v50.6.5)

##### Bug Fixes

- **`text-escaping`:** always allow content in example tags; fixes
[#&#8203;1360](https://redirect.github.com/gajus/eslint-plugin-jsdoc/issues/1360)
([6baad05](6baad05aab))

###
[`v50.6.4`](https://redirect.github.com/gajus/eslint-plugin-jsdoc/releases/tag/v50.6.4)

[Compare
Source](https://redirect.github.com/gajus/eslint-plugin-jsdoc/compare/v50.6.3...v50.6.4)

##### Bug Fixes

- force release
([9edf4b1](9edf4b18f9))
- force release
([b08733a](b08733a127))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/open-feature/js-sdk).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MC4xMS4xOCIsInVwZGF0ZWRJblZlciI6IjQwLjExLjE4IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-15 16:11:58 +00:00
renovate[bot] 43b14b4869
chore(deps): update dependency @types/node to v22.15.17 (#1190)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[@types/node](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node)
([source](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node))
| [`22.15.3` ->
`22.15.17`](https://renovatebot.com/diffs/npm/@types%2fnode/22.15.3/22.15.17)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2fnode/22.15.17?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2fnode/22.15.17?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2fnode/22.15.3/22.15.17?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2fnode/22.15.3/22.15.17?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/open-feature/js-sdk).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MC4xMS4xOCIsInVwZGF0ZWRJblZlciI6IjQwLjExLjE4IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-15 16:10:34 +00:00
renovate[bot] cd8017d537
chore(deps): update dependency esbuild to v0.25.4 (#1185)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [esbuild](https://redirect.github.com/evanw/esbuild) | [`0.25.2` ->
`0.25.4`](https://renovatebot.com/diffs/npm/esbuild/0.25.2/0.25.4) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/esbuild/0.25.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/esbuild/0.25.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/esbuild/0.25.2/0.25.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/esbuild/0.25.2/0.25.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>evanw/esbuild (esbuild)</summary>

###
[`v0.25.4`](https://redirect.github.com/evanw/esbuild/blob/HEAD/CHANGELOG.md#0254)

[Compare
Source](https://redirect.github.com/evanw/esbuild/compare/v0.25.3...v0.25.4)

- Add simple support for CORS to esbuild's development server
([#&#8203;4125](https://redirect.github.com/evanw/esbuild/issues/4125))

Starting with version 0.25.0, esbuild's development server is no longer
configured to serve cross-origin requests. This was a deliberate change
to prevent any website you visit from accessing your running esbuild
development server. However, this change prevented (by design) certain
use cases such as "debugging in production" by having your production
website load code from `localhost` where the esbuild development server
is running.

To enable this use case, esbuild is adding a feature to allow
[Cross-Origin Resource
Sharing](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CORS)
(a.k.a. CORS) for [simple
requests](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CORS#simple_requests).
Specifically, passing your origin to the new `cors` option will now set
the `Access-Control-Allow-Origin` response header when the request has a
matching `Origin` header. Note that this currently only works for
requests that don't send a preflight `OPTIONS` request, as esbuild's
development server doesn't currently support `OPTIONS` requests.

    Some examples:

    -   **CLI:**

            esbuild --servedir=. --cors-origin=https://example.com

    -   **JS:**

        ```js
        const ctx = await esbuild.context({})
        await ctx.serve({
          servedir: '.',
          cors: {
            origin: 'https://example.com',
          },
        })
        ```

    -   **Go:**

        ```go
        ctx, _ := api.Context(api.BuildOptions{})
        ctx.Serve(api.ServeOptions{
          Servedir: ".",
          CORS: api.CORSOptions{
            Origin: []string{"https://example.com"},
          },
        })
        ```

The special origin `*` can be used to allow any origin to access
esbuild's development server. Note that this means any website you visit
will be able to read everything served by esbuild.

- Pass through invalid URLs in source maps unmodified
([#&#8203;4169](https://redirect.github.com/evanw/esbuild/issues/4169))

This fixes a regression in version 0.25.0 where `sources` in source maps
that form invalid URLs were not being passed through to the output.
Version 0.25.0 changed the interpretation of `sources` from file paths
to URLs, which means that URL parsing can now fail. Previously URLs that
couldn't be parsed were replaced with the empty string. With this
release, invalid URLs in `sources` should now be passed through
unmodified.

- Handle exports named `__proto__` in ES modules
([#&#8203;4162](https://redirect.github.com/evanw/esbuild/issues/4162),
[#&#8203;4163](https://redirect.github.com/evanw/esbuild/pull/4163))

In JavaScript, the special property name `__proto__` sets the prototype
when used inside an object literal. Previously esbuild's ESM-to-CommonJS
conversion didn't special-case the property name of exports named
`__proto__` so the exported getter accidentally became the prototype of
the object literal. It's unclear what this affects, if anything, but
it's better practice to avoid this by using a computed property name in
this case.

This fix was contributed by
[@&#8203;magic-akari](https://redirect.github.com/magic-akari).

###
[`v0.25.3`](https://redirect.github.com/evanw/esbuild/blob/HEAD/CHANGELOG.md#0253)

[Compare
Source](https://redirect.github.com/evanw/esbuild/compare/v0.25.2...v0.25.3)

- Fix lowered `async` arrow functions before `super()`
([#&#8203;4141](https://redirect.github.com/evanw/esbuild/issues/4141),
[#&#8203;4142](https://redirect.github.com/evanw/esbuild/pull/4142))

This change makes it possible to call an `async` arrow function in a
constructor before calling `super()` when targeting environments without
`async` support, as long as the function body doesn't reference `this`.
Here's an example (notice the change from `this` to `null`):

    ```js
    // Original code
    class Foo extends Object {
      constructor() {
        (async () => await foo())()
        super()
      }
    }

    // Old output (with --target=es2016)
    class Foo extends Object {
      constructor() {
        (() => __async(this, null, function* () {
          return yield foo();
        }))();
        super();
      }
    }

    // New output (with --target=es2016)
    class Foo extends Object {
      constructor() {
        (() => __async(null, null, function* () {
          return yield foo();
        }))();
        super();
      }
    }
    ```

Some background: Arrow functions with the `async` keyword are
transformed into generator functions for older language targets such as
`--target=es2016`. Since arrow functions capture `this`, the generated
code forwards `this` into the body of the generator function. However,
JavaScript class syntax forbids using `this` in a constructor before
calling `super()`, and this forwarding was problematic since previously
happened even when the function body doesn't use `this`. Starting with
this release, esbuild will now only forward `this` if it's used within
the function body.

This fix was contributed by
[@&#8203;magic-akari](https://redirect.github.com/magic-akari).

- Fix memory leak with `--watch=true`
([#&#8203;4131](https://redirect.github.com/evanw/esbuild/issues/4131),
[#&#8203;4132](https://redirect.github.com/evanw/esbuild/pull/4132))

This release fixes a memory leak with esbuild when `--watch=true` is
used instead of `--watch`. Previously using `--watch=true` caused
esbuild to continue to use more and more memory for every rebuild, but
`--watch=true` should now behave like `--watch` and not leak memory.

This bug happened because esbuild disables the garbage collector when
it's not run as a long-lived process for extra speed, but esbuild's
checks for which arguments cause esbuild to be a long-lived process
weren't updated for the new `--watch=true` style of boolean command-line
flags. This has been an issue since this boolean flag syntax was added
in version 0.14.24 in 2022. These checks are unfortunately separate from
the regular argument parser because of how esbuild's internals are
organized (the command-line interface is exposed as a separate [Go
API](https://pkg.go.dev/github.com/evanw/esbuild/pkg/cli) so you can
build your own custom esbuild CLI).

This fix was contributed by
[@&#8203;mxschmitt](https://redirect.github.com/mxschmitt).

- More concise output for repeated legal comments
([#&#8203;4139](https://redirect.github.com/evanw/esbuild/issues/4139))

Some libraries have many files and also use the same legal comment text
in all files. Previously esbuild would copy each legal comment to the
output file. Starting with this release, legal comments duplicated
across separate files will now be grouped in the output file by unique
comment content.

- Allow a custom host with the development server
([#&#8203;4110](https://redirect.github.com/evanw/esbuild/issues/4110))

With this release, you can now use a custom non-IP `host` with esbuild's
local development server (either with `--serve=` for the CLI or with the
`serve()` call for the API). This was previously possible, but was
intentionally broken in [version
0.25.0](https://redirect.github.com/evanw/esbuild/releases/v0.25.0) to
fix a security issue. This change adds the functionality back except
that it's now opt-in and only for a single domain name that you provide.

For example, if you add a mapping in your `/etc/hosts` file from
`local.example.com` to `127.0.0.1` and then use `esbuild
--serve=local.example.com:8000`, you will now be able to visit
http://local.example.com:8000/ in your browser and successfully connect
to esbuild's development server (doing that would previously have been
blocked by the browser). This should also work with HTTPS if it's
enabled (see esbuild's documentation for how to do that).

- Add a limit to CSS nesting expansion
([#&#8203;4114](https://redirect.github.com/evanw/esbuild/issues/4114))

With this release, esbuild will now fail with an error if there is too
much CSS nesting expansion. This can happen when nested CSS is converted
to CSS without nesting for older browsers as expanding CSS nesting is
inherently exponential due to the resulting combinatorial explosion. The
expansion limit is currently hard-coded and cannot be changed, but is
extremely unlikely to trigger for real code. It exists to prevent
esbuild from using too much time and/or memory. Here's an example:

    ```css

a,b{a,b{a,b{a,b{a,b{a,b{a,b{a,b{a,b{a,b{a,b{a,b{a,b{a,b{a,b{a,b{a,b{a,b{a,b{a,b{color:red}}}}}}}}}}}}}}}}}}}}
    ```

Previously, transforming this file with `--target=safari1` took 5
seconds and generated 40mb of CSS. Trying to do that will now generate
the following error instead:

        ✘ [ERROR] CSS nesting is causing too much expansion

            example.css:1:60:
1 │
a,b{a,b{a,b{a,b{a,b{a,b{a,b{a,b{a,b{a,b{a,b{a,b{a,b{a,b{a,b{a,b{a,b{a,b{a,b{a,b{color:red}}}}}}}}}}}}}}}}}}}}
╵ ^

CSS nesting expansion was terminated because a rule was generated with
65536 selectors. This limit
exists to prevent esbuild from using too much time and/or memory. Please
change your CSS to use
          fewer levels of nesting.

- Fix path resolution edge case
([#&#8203;4144](https://redirect.github.com/evanw/esbuild/issues/4144))

This fixes an edge case where esbuild's path resolution algorithm could
deviate from node's path resolution algorithm. It involves a confusing
situation where a directory shares the same file name as a file (but
without the file extension). See the linked issue for specific details.
This appears to be a case where esbuild is correctly following [node's
published resolution
algorithm](https://nodejs.org/api/modules.html#all-together) but where
node itself is doing something different. Specifically the step
`LOAD_AS_FILE` appears to be skipped when the input ends with `..`. This
release changes esbuild's behavior for this edge case to match node's
behavior.

- Update Go from 1.23.7 to 1.23.8
([#&#8203;4133](https://redirect.github.com/evanw/esbuild/issues/4133),
[#&#8203;4134](https://redirect.github.com/evanw/esbuild/pull/4134))

This should have no effect on existing code as this version change does
not change Go's operating system support. It may remove certain reports
from vulnerability scanners that detect which version of the Go compiler
esbuild uses, such as for CVE-2025-22871.

As a reminder, esbuild's development server is intended for development,
not for production, so I do not consider most networking-related
vulnerabilities in Go to be vulnerabilities in esbuild. Please do not
use esbuild's development server in production.

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/open-feature/js-sdk).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS4yNjQuMCIsInVwZGF0ZWRJblZlciI6IjQwLjExLjE4IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-15 12:11:42 -04:00
renovate[bot] 273af9e20b
chore(deps): update dependency @rollup/plugin-typescript to v12 (#1059)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[@rollup/plugin-typescript](https://redirect.github.com/rollup/plugins/tree/master/packages/typescript/#readme)
([source](https://redirect.github.com/rollup/plugins/tree/HEAD/packages/typescript))
| [`^11.1.6` ->
`^12.0.0`](https://renovatebot.com/diffs/npm/@rollup%2fplugin-typescript/11.1.6/12.1.2)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@rollup%2fplugin-typescript/12.1.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@rollup%2fplugin-typescript/12.1.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@rollup%2fplugin-typescript/11.1.6/12.1.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@rollup%2fplugin-typescript/11.1.6/12.1.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>rollup/plugins (@&#8203;rollup/plugin-typescript)</summary>

###
[`v12.1.2`](https://redirect.github.com/rollup/plugins/blob/HEAD/packages/typescript/CHANGELOG.md#v1212)

*2024-12-15*

##### Bugfixes

- fix: path validation issue in validatePaths function
([#&#8203;1800](https://redirect.github.com/rollup/plugins/issues/1800))

###
[`v12.1.1`](https://redirect.github.com/rollup/plugins/blob/HEAD/packages/typescript/CHANGELOG.md#v1211)

*2024-10-16*

##### Bugfixes

- fix: allow for files to be nested in folders within outDir
([#&#8203;1783](https://redirect.github.com/rollup/plugins/issues/1783))

###
[`v12.1.0`](https://redirect.github.com/rollup/plugins/blob/HEAD/packages/typescript/CHANGELOG.md#v1210)

*2024-09-22*

##### Features

- feat: add transformers factory.
([#&#8203;1668](https://redirect.github.com/rollup/plugins/issues/1668))

###
[`v12.0.0`](https://redirect.github.com/rollup/plugins/blob/HEAD/packages/typescript/CHANGELOG.md#v1200)

*2024-09-22*

##### Breaking Changes

- fix!: correctly resolve filenames of declaration files for
`output.file`
([#&#8203;1728](https://redirect.github.com/rollup/plugins/issues/1728))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/open-feature/js-sdk).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC4xMjAuMSIsInVwZGF0ZWRJblZlciI6IjQwLjExLjE4IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-15 12:10:18 -04:00
renovate[bot] 8f9b1ae34f
chore(deps): update dependency rollup to v4.40.2 (#1131)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [rollup](https://rollupjs.org/)
([source](https://redirect.github.com/rollup/rollup)) | [`4.24.2` ->
`4.40.2`](https://renovatebot.com/diffs/npm/rollup/4.24.2/4.40.2) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/rollup/4.40.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/rollup/4.40.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/rollup/4.24.2/4.40.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/rollup/4.24.2/4.40.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>rollup/rollup (rollup)</summary>

###
[`v4.40.2`](https://redirect.github.com/rollup/rollup/blob/HEAD/CHANGELOG.md#4402)

[Compare
Source](https://redirect.github.com/rollup/rollup/compare/v4.40.1...v4.40.2)

*2025-05-06*

##### Bug Fixes

- Create correct IIFE/AMD/UMD bundles when using a mutable default
export
([#&#8203;5934](https://redirect.github.com/rollup/rollup/issues/5934))
- Fix execution order when using top-level await for dynamic imports
with inlineDynamicImports
([#&#8203;5937](https://redirect.github.com/rollup/rollup/issues/5937))
- Throw when the output is watched in watch mode
([#&#8203;5939](https://redirect.github.com/rollup/rollup/issues/5939))

##### Pull Requests

- [#&#8203;5934](https://redirect.github.com/rollup/rollup/pull/5934):
fix(exports): avoid "exports is not defined" `ReferenceError`
([@&#8203;dasa](https://redirect.github.com/dasa))
- [#&#8203;5937](https://redirect.github.com/rollup/rollup/pull/5937):
consider TLA imports have higher execution priority
([@&#8203;TrickyPi](https://redirect.github.com/TrickyPi))
- [#&#8203;5939](https://redirect.github.com/rollup/rollup/pull/5939):
fix: watch mode input should not be an output subpath
([@&#8203;btea](https://redirect.github.com/btea))
- [#&#8203;5940](https://redirect.github.com/rollup/rollup/pull/5940):
chore(deps): update dependency vite to v6.3.4 \[security]
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])
- [#&#8203;5941](https://redirect.github.com/rollup/rollup/pull/5941):
chore(deps): update dependency eslint-plugin-unicorn to v59
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])
- [#&#8203;5942](https://redirect.github.com/rollup/rollup/pull/5942):
fix(deps): lock file maintenance minor/patch updates
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])
- [#&#8203;5943](https://redirect.github.com/rollup/rollup/pull/5943):
fix(deps): lock file maintenance minor/patch updates
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])

###
[`v4.40.1`](https://redirect.github.com/rollup/rollup/blob/HEAD/CHANGELOG.md#4401)

[Compare
Source](https://redirect.github.com/rollup/rollup/compare/v4.40.0...v4.40.1)

*2025-04-28*

##### Bug Fixes

- Limit hash size for asset file names to the supported 21
([#&#8203;5921](https://redirect.github.com/rollup/rollup/issues/5921))
- Do not inline user-defined entry chunks or chunks with explicit file
name
([#&#8203;5923](https://redirect.github.com/rollup/rollup/issues/5923))
- Avoid top-level-await cycles when non-entry chunks use top-level await
([#&#8203;5930](https://redirect.github.com/rollup/rollup/issues/5930))
- Expose package.json via exports
([#&#8203;5931](https://redirect.github.com/rollup/rollup/issues/5931))

##### Pull Requests

- [#&#8203;5921](https://redirect.github.com/rollup/rollup/pull/5921):
fix(assetFileNames): reduce max hash size to 21
([@&#8203;shulaoda](https://redirect.github.com/shulaoda))
- [#&#8203;5923](https://redirect.github.com/rollup/rollup/pull/5923):
fix: generate the separate chunk for the entry module with explicated
chunk filename or name
([@&#8203;TrickyPi](https://redirect.github.com/TrickyPi))
- [#&#8203;5926](https://redirect.github.com/rollup/rollup/pull/5926):
fix(deps): update rust crate swc_compiler_base to v18
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])
- [#&#8203;5927](https://redirect.github.com/rollup/rollup/pull/5927):
fix(deps): lock file maintenance minor/patch updates
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])
- [#&#8203;5928](https://redirect.github.com/rollup/rollup/pull/5928):
fix(deps): lock file maintenance minor/patch updates
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])
- [#&#8203;5930](https://redirect.github.com/rollup/rollup/pull/5930):
Avoid chunks TLA dynamic import circular when TLA dynamic import used in
non-entry modules
([@&#8203;TrickyPi](https://redirect.github.com/TrickyPi))
- [#&#8203;5931](https://redirect.github.com/rollup/rollup/pull/5931):
chore: add new `./package.json` entry
([@&#8203;JounQin](https://redirect.github.com/JounQin),
[@&#8203;lukastaegert](https://redirect.github.com/lukastaegert))
- [#&#8203;5936](https://redirect.github.com/rollup/rollup/pull/5936):
fix(deps): lock file maintenance minor/patch updates
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])

###
[`v4.40.0`](https://redirect.github.com/rollup/rollup/blob/HEAD/CHANGELOG.md#4400)

[Compare
Source](https://redirect.github.com/rollup/rollup/compare/v4.39.0...v4.40.0)

*2025-04-12*

##### Features

- Only show `eval` warnings on first render and only when the call is
not tree-shaken
([#&#8203;5892](https://redirect.github.com/rollup/rollup/issues/5892))
- Tree-shake non-included dynamic import members when the handler just
maps to one named export
([#&#8203;5898](https://redirect.github.com/rollup/rollup/issues/5898))

##### Bug Fixes

- Consider dynamic imports nested within top-level-awaited dynamic
import expressions to be awaited as well
([#&#8203;5900](https://redirect.github.com/rollup/rollup/issues/5900))
- Fix namespace rendering when tree-shaking is disabled
([#&#8203;5908](https://redirect.github.com/rollup/rollup/issues/5908))
- When using multiple transform hook filters, all of them need to be
satisfied together
([#&#8203;5909](https://redirect.github.com/rollup/rollup/issues/5909))

##### Pull Requests

- [#&#8203;5892](https://redirect.github.com/rollup/rollup/pull/5892):
Warn when eval or namespace calls are rendered, not when they are parsed
([@&#8203;SunsetFi](https://redirect.github.com/SunsetFi),
[@&#8203;lukastaegert](https://redirect.github.com/lukastaegert))
- [#&#8203;5898](https://redirect.github.com/rollup/rollup/pull/5898):
feat: treeshake dynamic import chained member expression
([@&#8203;privatenumber](https://redirect.github.com/privatenumber),
[@&#8203;lukastaegert](https://redirect.github.com/lukastaegert))
- [#&#8203;5900](https://redirect.github.com/rollup/rollup/pull/5900):
consider the dynamic import within a TLA call expression as a TLA import
([@&#8203;TrickyPi](https://redirect.github.com/TrickyPi))
- [#&#8203;5904](https://redirect.github.com/rollup/rollup/pull/5904):
fix(deps): update swc monorepo (major)
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])
- [#&#8203;5905](https://redirect.github.com/rollup/rollup/pull/5905):
chore(deps): lock file maintenance minor/patch updates
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])
- [#&#8203;5908](https://redirect.github.com/rollup/rollup/pull/5908):
Fix `treeshake: false` breaking destructured namespace imports
([@&#8203;Skn0tt](https://redirect.github.com/Skn0tt))
- [#&#8203;5909](https://redirect.github.com/rollup/rollup/pull/5909):
Correct the behavior when multiple transform filter options are
specified ([@&#8203;sapphi-red](https://redirect.github.com/sapphi-red))
- [#&#8203;5915](https://redirect.github.com/rollup/rollup/pull/5915):
chore(deps): update dependency
[@&#8203;types/picomatch](https://redirect.github.com/types/picomatch)
to v4 ([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])
- [#&#8203;5916](https://redirect.github.com/rollup/rollup/pull/5916):
fix(deps): update rust crate swc_compiler_base to v17
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])
- [#&#8203;5917](https://redirect.github.com/rollup/rollup/pull/5917):
chore(deps): lock file maintenance minor/patch updates
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot],
[@&#8203;lukastaegert](https://redirect.github.com/lukastaegert))
- [#&#8203;5918](https://redirect.github.com/rollup/rollup/pull/5918):
chore(deps): update dependency vite to v6.2.6 \[security]
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot],
[@&#8203;lukastaegert](https://redirect.github.com/lukastaegert))

###
[`v4.39.0`](https://redirect.github.com/rollup/rollup/blob/HEAD/CHANGELOG.md#4390)

[Compare
Source](https://redirect.github.com/rollup/rollup/compare/v4.38.0...v4.39.0)

*2025-04-02*

##### Features

- Do not create separate facade chunks if a chunk would contain several
entry modules that allow export extension if there are no export name
conflicts
([#&#8203;5891](https://redirect.github.com/rollup/rollup/issues/5891))

##### Bug Fixes

- Mark the `id` property as optional in the filter for the `resolveId`
hook
([#&#8203;5896](https://redirect.github.com/rollup/rollup/issues/5896))

##### Pull Requests

- [#&#8203;5891](https://redirect.github.com/rollup/rollup/pull/5891):
chunk: merge allow-extension modules
([@&#8203;wmertens](https://redirect.github.com/wmertens),
[@&#8203;lukastaegert](https://redirect.github.com/lukastaegert))
- [#&#8203;5893](https://redirect.github.com/rollup/rollup/pull/5893):
chore(deps): update dependency vite to v6.2.4 \[security]
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])
- [#&#8203;5896](https://redirect.github.com/rollup/rollup/pull/5896):
fix: resolveId id filter is optional
([@&#8203;sapphi-red](https://redirect.github.com/sapphi-red))

###
[`v4.38.0`](https://redirect.github.com/rollup/rollup/blob/HEAD/CHANGELOG.md#4380)

[Compare
Source](https://redirect.github.com/rollup/rollup/compare/v4.37.0...v4.38.0)

*2025-03-29*

##### Features

- Support `.filter` option in `resolveId`, `load` and `transform` hooks
([#&#8203;5882](https://redirect.github.com/rollup/rollup/issues/5882))

##### Pull Requests

- [#&#8203;5882](https://redirect.github.com/rollup/rollup/pull/5882):
Add support for hook filters
([@&#8203;sapphi-red](https://redirect.github.com/sapphi-red))
- [#&#8203;5894](https://redirect.github.com/rollup/rollup/pull/5894):
fix(deps): lock file maintenance minor/patch updates
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])
- [#&#8203;5895](https://redirect.github.com/rollup/rollup/pull/5895):
chore(deps): update dependency eslint-plugin-unicorn to v58
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])

###
[`v4.37.0`](https://redirect.github.com/rollup/rollup/blob/HEAD/CHANGELOG.md#4370)

[Compare
Source](https://redirect.github.com/rollup/rollup/compare/v4.36.0...v4.37.0)

*2025-03-23*

##### Features

- Support Musl Linux on Riscv64 architectures
([#&#8203;5726](https://redirect.github.com/rollup/rollup/issues/5726))
- Handles class decorators placed before the `export` keyword
([#&#8203;5871](https://redirect.github.com/rollup/rollup/issues/5871))

##### Bug Fixes

- Log Rust panic messages to the console when using the WASM build
([#&#8203;5875](https://redirect.github.com/rollup/rollup/issues/5875))

##### Pull Requests

- [#&#8203;5726](https://redirect.github.com/rollup/rollup/pull/5726):
Add support for linux riscv64 musl
([@&#8203;fossdd](https://redirect.github.com/fossdd),
[@&#8203;leso-kn](https://redirect.github.com/leso-kn))
- [#&#8203;5871](https://redirect.github.com/rollup/rollup/pull/5871):
feat: support decorators before or after export
([@&#8203;TrickyPi](https://redirect.github.com/TrickyPi))
- [#&#8203;5875](https://redirect.github.com/rollup/rollup/pull/5875):
capture Rust panic messages and output them to the console.
([@&#8203;luyahan](https://redirect.github.com/luyahan),
[@&#8203;lukastaegert](https://redirect.github.com/lukastaegert))
- [#&#8203;5883](https://redirect.github.com/rollup/rollup/pull/5883):
Pin digest of 3rd party actions
([@&#8203;re-taro](https://redirect.github.com/re-taro))
- [#&#8203;5885](https://redirect.github.com/rollup/rollup/pull/5885):
fix(deps): lock file maintenance minor/patch updates
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])

###
[`v4.36.0`](https://redirect.github.com/rollup/rollup/blob/HEAD/CHANGELOG.md#4360)

[Compare
Source](https://redirect.github.com/rollup/rollup/compare/v4.35.0...v4.36.0)

*2025-03-17*

##### Features

- Extend `renderDynamicImport` hook to provide information about static
dependencies of the imported module
([#&#8203;5870](https://redirect.github.com/rollup/rollup/issues/5870))
- Export several additional types used by Vite
([#&#8203;5879](https://redirect.github.com/rollup/rollup/issues/5879))

##### Bug Fixes

- Do not merge chunks if that would create a top-level await cycle
between chunks
([#&#8203;5843](https://redirect.github.com/rollup/rollup/issues/5843))

##### Pull Requests

- [#&#8203;5843](https://redirect.github.com/rollup/rollup/pull/5843):
avoiding top level await circular
([@&#8203;TrickyPi](https://redirect.github.com/TrickyPi),
[@&#8203;lukastaegert](https://redirect.github.com/lukastaegert))
- [#&#8203;5870](https://redirect.github.com/rollup/rollup/pull/5870):
draft for extended renderDynamicImport hook
([@&#8203;iczero](https://redirect.github.com/iczero),
[@&#8203;lukastaegert](https://redirect.github.com/lukastaegert))
- [#&#8203;5876](https://redirect.github.com/rollup/rollup/pull/5876):
Update axios overrides to 1.8.2
([@&#8203;vadym-khodak](https://redirect.github.com/vadym-khodak))
- [#&#8203;5877](https://redirect.github.com/rollup/rollup/pull/5877):
chore(deps): update dependency eslint-plugin-vue to v10
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])
- [#&#8203;5878](https://redirect.github.com/rollup/rollup/pull/5878):
fix(deps): lock file maintenance minor/patch updates
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])
- [#&#8203;5879](https://redirect.github.com/rollup/rollup/pull/5879):
fix: export types ([@&#8203;sxzz](https://redirect.github.com/sxzz))

###
[`v4.35.0`](https://redirect.github.com/rollup/rollup/blob/HEAD/CHANGELOG.md#4350)

[Compare
Source](https://redirect.github.com/rollup/rollup/compare/v4.34.9...v4.35.0)

*2025-03-08*

##### Features

- Pass build errors to the closeBundle hook
([#&#8203;5867](https://redirect.github.com/rollup/rollup/issues/5867))

##### Pull Requests

- [#&#8203;5852](https://redirect.github.com/rollup/rollup/pull/5852):
chore(deps): update dependency eslint-plugin-unicorn to v57
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot],
[@&#8203;lukastaegert](https://redirect.github.com/lukastaegert))
- [#&#8203;5862](https://redirect.github.com/rollup/rollup/pull/5862):
fix(deps): update swc monorepo (major)
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot],
[@&#8203;lukastaegert](https://redirect.github.com/lukastaegert))
- [#&#8203;5867](https://redirect.github.com/rollup/rollup/pull/5867):
feat(5858): make closeBundle hook receive the last error
([@&#8203;GauBen](https://redirect.github.com/GauBen))
- [#&#8203;5872](https://redirect.github.com/rollup/rollup/pull/5872):
chore(deps): update dependency builtin-modules to v5
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])
- [#&#8203;5873](https://redirect.github.com/rollup/rollup/pull/5873):
chore(deps): update uraimo/run-on-arch-action action to v3
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])
- [#&#8203;5874](https://redirect.github.com/rollup/rollup/pull/5874):
fix(deps): lock file maintenance minor/patch updates
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])

###
[`v4.34.9`](https://redirect.github.com/rollup/rollup/blob/HEAD/CHANGELOG.md#4349)

[Compare
Source](https://redirect.github.com/rollup/rollup/compare/v4.34.8...v4.34.9)

*2025-03-01*

##### Bug Fixes

- Support JSX modes in WASM
([#&#8203;5866](https://redirect.github.com/rollup/rollup/issues/5866))
- Allow the CustomPluginOptions to be extended
([#&#8203;5850](https://redirect.github.com/rollup/rollup/issues/5850))

##### Pull Requests

- [#&#8203;5850](https://redirect.github.com/rollup/rollup/pull/5850):
Revert CustomPluginOptions to be an interface
([@&#8203;sapphi-red](https://redirect.github.com/sapphi-red),
[@&#8203;lukastaegert](https://redirect.github.com/lukastaegert))
- [#&#8203;5851](https://redirect.github.com/rollup/rollup/pull/5851):
Javascript to JavaScript
([@&#8203;dasa](https://redirect.github.com/dasa),
[@&#8203;lukastaegert](https://redirect.github.com/lukastaegert))
- [#&#8203;5853](https://redirect.github.com/rollup/rollup/pull/5853):
chore(deps): update dependency pinia to v3
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])
- [#&#8203;5854](https://redirect.github.com/rollup/rollup/pull/5854):
fix(deps): update swc monorepo (major)
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])
- [#&#8203;5855](https://redirect.github.com/rollup/rollup/pull/5855):
fix(deps): lock file maintenance minor/patch updates
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot],
[@&#8203;lukastaegert](https://redirect.github.com/lukastaegert))
- [#&#8203;5860](https://redirect.github.com/rollup/rollup/pull/5860):
chore(deps): update dependency
[@&#8203;shikijs/vitepress-twoslash](https://redirect.github.com/shikijs/vitepress-twoslash)
to v3 ([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])
- [#&#8203;5861](https://redirect.github.com/rollup/rollup/pull/5861):
chore(deps): update dependency globals to v16
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])
- [#&#8203;5863](https://redirect.github.com/rollup/rollup/pull/5863):
fix(deps): lock file maintenance minor/patch updates
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])
- [#&#8203;5864](https://redirect.github.com/rollup/rollup/pull/5864):
chore(deps): lock file maintenance minor/patch updates
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])
- [#&#8203;5866](https://redirect.github.com/rollup/rollup/pull/5866):
Add jsx parameter to parseAsync in native.wasm.js
([@&#8203;TrickyPi](https://redirect.github.com/TrickyPi))

###
[`v4.34.8`](https://redirect.github.com/rollup/rollup/blob/HEAD/CHANGELOG.md#4348)

[Compare
Source](https://redirect.github.com/rollup/rollup/compare/v4.34.7...v4.34.8)

*2025-02-17*

##### Bug Fixes

- Do not make assumptions about the value of nested paths in logical
expressions if the expression cannot be simplified
([#&#8203;5846](https://redirect.github.com/rollup/rollup/issues/5846))

##### Pull Requests

- [#&#8203;5846](https://redirect.github.com/rollup/rollup/pull/5846):
return UnknownValue if the usedbranch is unkown and the path is not
empty ([@&#8203;TrickyPi](https://redirect.github.com/TrickyPi))

###
[`v4.34.7`](https://redirect.github.com/rollup/rollup/blob/HEAD/CHANGELOG.md#4347)

[Compare
Source](https://redirect.github.com/rollup/rollup/compare/v4.34.6...v4.34.7)

*2025-02-14*

##### Bug Fixes

- Ensure that calls to parameters are included correctly when using
try-catch deoptimization
([#&#8203;5842](https://redirect.github.com/rollup/rollup/issues/5842))

##### Pull Requests

- [#&#8203;5840](https://redirect.github.com/rollup/rollup/pull/5840):
fix(deps): lock file maintenance minor/patch updates
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])
- [#&#8203;5842](https://redirect.github.com/rollup/rollup/pull/5842):
Fix prop inclusion with try-catch-deoptimization
([@&#8203;lukastaegert](https://redirect.github.com/lukastaegert))

###
[`v4.34.6`](https://redirect.github.com/rollup/rollup/blob/HEAD/CHANGELOG.md#4346)

[Compare
Source](https://redirect.github.com/rollup/rollup/compare/v4.34.5...v4.34.6)

*2025-02-07*

##### Bug Fixes

- Retain "void 0" in the output for smaller output and fewer surprises
([#&#8203;5838](https://redirect.github.com/rollup/rollup/issues/5838))

##### Pull Requests

- [#&#8203;5835](https://redirect.github.com/rollup/rollup/pull/5835):
fix(deps): update swc monorepo (major)
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot],
[@&#8203;lukastaegert](https://redirect.github.com/lukastaegert))
- [#&#8203;5838](https://redirect.github.com/rollup/rollup/pull/5838):
replace undefined with void 0 for operator void
([@&#8203;TrickyPi](https://redirect.github.com/TrickyPi))

###
[`v4.34.5`](https://redirect.github.com/rollup/rollup/blob/HEAD/CHANGELOG.md#4345)

[Compare
Source](https://redirect.github.com/rollup/rollup/compare/v4.34.4...v4.34.5)

*2025-02-07*

##### Bug Fixes

- Ensure namespace reexports always include all properties of all
exports
([#&#8203;5837](https://redirect.github.com/rollup/rollup/issues/5837))

##### Pull Requests

- [#&#8203;5836](https://redirect.github.com/rollup/rollup/pull/5836):
fix(deps): lock file maintenance minor/patch updates
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])
- [#&#8203;5837](https://redirect.github.com/rollup/rollup/pull/5837):
Include all paths of reexports if namespace is used
([@&#8203;lukastaegert](https://redirect.github.com/lukastaegert))

###
[`v4.34.4`](https://redirect.github.com/rollup/rollup/blob/HEAD/CHANGELOG.md#4344)

[Compare
Source](https://redirect.github.com/rollup/rollup/compare/v4.34.3...v4.34.4)

*2025-02-05*

##### Bug Fixes

- Do not tree-shake properties if a rest element is used in
destructuring
([#&#8203;5833](https://redirect.github.com/rollup/rollup/issues/5833))

##### Pull Requests

- [#&#8203;5833](https://redirect.github.com/rollup/rollup/pull/5833):
include all properties if a rest element is destructed
([@&#8203;TrickyPi](https://redirect.github.com/TrickyPi))

###
[`v4.34.3`](https://redirect.github.com/rollup/rollup/blob/HEAD/CHANGELOG.md#4343)

[Compare
Source](https://redirect.github.com/rollup/rollup/compare/v4.34.2...v4.34.3)

*2025-02-05*

##### Bug Fixes

- Ensure properties of "this" are included in getters
([#&#8203;5831](https://redirect.github.com/rollup/rollup/issues/5831))

##### Pull Requests

- [#&#8203;5831](https://redirect.github.com/rollup/rollup/pull/5831):
include the properties that accessed by this
([@&#8203;TrickyPi](https://redirect.github.com/TrickyPi))

###
[`v4.34.2`](https://redirect.github.com/rollup/rollup/blob/HEAD/CHANGELOG.md#4342)

[Compare
Source](https://redirect.github.com/rollup/rollup/compare/v4.34.1...v4.34.2)

*2025-02-04*

##### Bug Fixes

- Fix an issue where not all usages of a function were properly detected
([#&#8203;5827](https://redirect.github.com/rollup/rollup/issues/5827))

##### Pull Requests

- [#&#8203;5827](https://redirect.github.com/rollup/rollup/pull/5827):
Ensure that functions provided to a constructor are properly deoptimized
([@&#8203;lukastaegert](https://redirect.github.com/lukastaegert))

###
[`v4.34.1`](https://redirect.github.com/rollup/rollup/blob/HEAD/CHANGELOG.md#4341)

[Compare
Source](https://redirect.github.com/rollup/rollup/compare/v4.34.0...v4.34.1)

*2025-02-03*

##### Bug Fixes

- Ensure throwing objects includes the entire object
([#&#8203;5825](https://redirect.github.com/rollup/rollup/issues/5825))

##### Pull Requests

- [#&#8203;5825](https://redirect.github.com/rollup/rollup/pull/5825):
Ensure that all properties of throw statements are included
([@&#8203;lukastaegert](https://redirect.github.com/lukastaegert))

###
[`v4.34.0`](https://redirect.github.com/rollup/rollup/blob/HEAD/CHANGELOG.md#4340)

[Compare
Source](https://redirect.github.com/rollup/rollup/compare/v4.33.0...v4.34.0)

*2025-02-01*

##### Features

- Tree-shake unused properties in object literals (re-implements
[#&#8203;5420](https://redirect.github.com/rollup/rollup/issues/5420))
([#&#8203;5737](https://redirect.github.com/rollup/rollup/issues/5737))

##### Pull Requests

- [#&#8203;5737](https://redirect.github.com/rollup/rollup/pull/5737):
Reapply object tree-shaking
([@&#8203;lukastaegert](https://redirect.github.com/lukastaegert),
[@&#8203;TrickyPi](https://redirect.github.com/TrickyPi))

###
[`v4.33.0`](https://redirect.github.com/rollup/rollup/blob/HEAD/CHANGELOG.md#4330)

[Compare
Source](https://redirect.github.com/rollup/rollup/compare/v4.32.1...v4.33.0)

*2025-02-01*

##### Features

- Correctly detect literal value of more negated expressions
([#&#8203;5812](https://redirect.github.com/rollup/rollup/issues/5812))

##### Bug Fixes

- Use the correct with/assert attribute key in dynamic imports
([#&#8203;5818](https://redirect.github.com/rollup/rollup/issues/5818))
- Fix an issue where logical expressions were considered to have the
wrong value
([#&#8203;5819](https://redirect.github.com/rollup/rollup/issues/5819))

##### Pull Requests

- [#&#8203;5812](https://redirect.github.com/rollup/rollup/pull/5812):
feat: optimize the literal value of unary expressions
([@&#8203;TrickyPi](https://redirect.github.com/TrickyPi))
- [#&#8203;5816](https://redirect.github.com/rollup/rollup/pull/5816):
fix(deps): update swc monorepo (major)
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot],
[@&#8203;lukastaegert](https://redirect.github.com/lukastaegert))
- [#&#8203;5817](https://redirect.github.com/rollup/rollup/pull/5817):
fix(deps): lock file maintenance minor/patch updates
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot],
[@&#8203;lukastaegert](https://redirect.github.com/lukastaegert))
- [#&#8203;5818](https://redirect.github.com/rollup/rollup/pull/5818):
support for changing the attributes key for dynamic imports
([@&#8203;TrickyPi](https://redirect.github.com/TrickyPi))
- [#&#8203;5819](https://redirect.github.com/rollup/rollup/pull/5819):
Return UnknownValue if getLiteralValueAtPath is called recursively
within logical expressions
([@&#8203;TrickyPi](https://redirect.github.com/TrickyPi))
- [#&#8203;5820](https://redirect.github.com/rollup/rollup/pull/5820):
return null
([@&#8203;kingma-sbw](https://redirect.github.com/kingma-sbw))

###
[`v4.32.1`](https://redirect.github.com/rollup/rollup/blob/HEAD/CHANGELOG.md#4321)

[Compare
Source](https://redirect.github.com/rollup/rollup/compare/v4.32.0...v4.32.1)

*2025-01-28*

##### Bug Fixes

- Fix possible crash when optimizing logical expressions
([#&#8203;5804](https://redirect.github.com/rollup/rollup/issues/5804))

##### Pull Requests

- [#&#8203;5804](https://redirect.github.com/rollup/rollup/pull/5804):
fix: set hasDeoptimizedCache to true as early as possible
([@&#8203;TrickyPi](https://redirect.github.com/TrickyPi))
- [#&#8203;5813](https://redirect.github.com/rollup/rollup/pull/5813):
Fix typo ([@&#8203;kantuni](https://redirect.github.com/kantuni))

###
[`v4.32.0`](https://redirect.github.com/rollup/rollup/blob/HEAD/CHANGELOG.md#4320)

[Compare
Source](https://redirect.github.com/rollup/rollup/compare/v4.31.0...v4.32.0)

*2025-01-24*

##### Features

- Add watch.onInvalidate option to trigger actions immediately when a
file is changed
([#&#8203;5799](https://redirect.github.com/rollup/rollup/issues/5799))

##### Bug Fixes

- Fix incorrect urls in CLI warnings
([#&#8203;5809](https://redirect.github.com/rollup/rollup/issues/5809))

##### Pull Requests

- [#&#8203;5799](https://redirect.github.com/rollup/rollup/pull/5799):
Feature/watch on invalidate
([@&#8203;drebrez](https://redirect.github.com/drebrez),
[@&#8203;lukastaegert](https://redirect.github.com/lukastaegert))
- [#&#8203;5808](https://redirect.github.com/rollup/rollup/pull/5808):
chore(deps): update dependency vite to v6.0.9 \[security]
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])
- [#&#8203;5809](https://redirect.github.com/rollup/rollup/pull/5809):
fix: avoid duplicate rollupjs.org prefix
([@&#8203;GauBen](https://redirect.github.com/GauBen),
[@&#8203;lukastaegert](https://redirect.github.com/lukastaegert))
- [#&#8203;5810](https://redirect.github.com/rollup/rollup/pull/5810):
chore(deps): update dependency
[@&#8203;shikijs/vitepress-twoslash](https://redirect.github.com/shikijs/vitepress-twoslash)
to v2 ([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])
- [#&#8203;5811](https://redirect.github.com/rollup/rollup/pull/5811):
fix(deps): lock file maintenance minor/patch updates
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])

###
[`v4.31.0`](https://redirect.github.com/rollup/rollup/blob/HEAD/CHANGELOG.md#4310)

[Compare
Source](https://redirect.github.com/rollup/rollup/compare/v4.30.1...v4.31.0)

*2025-01-19*

##### Features

- Do not immediately quit when trying to use watch mode from within
non-TTY environments
([#&#8203;5803](https://redirect.github.com/rollup/rollup/issues/5803))

##### Bug Fixes

- Handle files with more than one UTF-8 BOM header
([#&#8203;5806](https://redirect.github.com/rollup/rollup/issues/5806))

##### Pull Requests

- [#&#8203;5792](https://redirect.github.com/rollup/rollup/pull/5792):
fix(deps): update rust crate swc_compiler_base to v8
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])
- [#&#8203;5793](https://redirect.github.com/rollup/rollup/pull/5793):
fix(deps): lock file maintenance minor/patch updates
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])
- [#&#8203;5794](https://redirect.github.com/rollup/rollup/pull/5794):
chore(deps): lock file maintenance
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])
- [#&#8203;5801](https://redirect.github.com/rollup/rollup/pull/5801):
chore(deps): update dependency eslint-config-prettier to v10
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])
- [#&#8203;5802](https://redirect.github.com/rollup/rollup/pull/5802):
fix(deps): lock file maintenance minor/patch updates
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])
- [#&#8203;5803](https://redirect.github.com/rollup/rollup/pull/5803):
Support watch mode in yarn, gradle and containers
([@&#8203;lukastaegert](https://redirect.github.com/lukastaegert))
- [#&#8203;5806](https://redirect.github.com/rollup/rollup/pull/5806):
fix: strip all BOMs
([@&#8203;TrickyPi](https://redirect.github.com/TrickyPi))

###
[`v4.30.1`](https://redirect.github.com/rollup/rollup/blob/HEAD/CHANGELOG.md#4301)

[Compare
Source](https://redirect.github.com/rollup/rollup/compare/v4.30.0...v4.30.1)

*2025-01-07*

##### Bug Fixes

- Prevent invalid code when simplifying unary expressions in switch
cases
([#&#8203;5786](https://redirect.github.com/rollup/rollup/issues/5786))

##### Pull Requests

- [#&#8203;5786](https://redirect.github.com/rollup/rollup/pull/5786):
fix: consider that literals cannot following switch case.
([@&#8203;TrickyPi](https://redirect.github.com/TrickyPi))

###
[`v4.30.0`](https://redirect.github.com/rollup/rollup/blob/HEAD/CHANGELOG.md#4300)

[Compare
Source](https://redirect.github.com/rollup/rollup/compare/v4.29.2...v4.30.0)

*2025-01-06*

##### Features

- Inline values of resolvable unary expressions for improved
tree-shaking
([#&#8203;5775](https://redirect.github.com/rollup/rollup/issues/5775))

##### Pull Requests

- [#&#8203;5775](https://redirect.github.com/rollup/rollup/pull/5775):
feat: enhance the treehshaking for unary expression
([@&#8203;TrickyPi](https://redirect.github.com/TrickyPi))
- [#&#8203;5783](https://redirect.github.com/rollup/rollup/pull/5783):
Improve CI caching for node_modules
([@&#8203;lukastaegert](https://redirect.github.com/lukastaegert))

###
[`v4.29.2`](https://redirect.github.com/rollup/rollup/blob/HEAD/CHANGELOG.md#4292)

[Compare
Source](https://redirect.github.com/rollup/rollup/compare/v4.29.1...v4.29.2)

*2025-01-05*

##### Bug Fixes

- Keep import attributes when using dynamic ESM `import()` expressions
from CommonJS
([#&#8203;5781](https://redirect.github.com/rollup/rollup/issues/5781))

##### Pull Requests

- [#&#8203;5772](https://redirect.github.com/rollup/rollup/pull/5772):
Improve caching on CI
([@&#8203;lukastaegert](https://redirect.github.com/lukastaegert))
- [#&#8203;5773](https://redirect.github.com/rollup/rollup/pull/5773):
fix(deps): lock file maintenance minor/patch updates
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])
- [#&#8203;5780](https://redirect.github.com/rollup/rollup/pull/5780):
feat: use picocolors instead of colorette
([@&#8203;re-taro](https://redirect.github.com/re-taro))
- [#&#8203;5781](https://redirect.github.com/rollup/rollup/pull/5781):
fix: keep import attributes for cjs format
([@&#8203;TrickyPi](https://redirect.github.com/TrickyPi))

###
[`v4.29.1`](https://redirect.github.com/rollup/rollup/blob/HEAD/CHANGELOG.md#4291)

[Compare
Source](https://redirect.github.com/rollup/rollup/compare/v4.29.0...v4.29.1)

*2024-12-21*

##### Bug Fixes

- Fix crash from deoptimized logical expressions
([#&#8203;5771](https://redirect.github.com/rollup/rollup/issues/5771))

##### Pull Requests

- [#&#8203;5769](https://redirect.github.com/rollup/rollup/pull/5769):
Remove unnecessary lifetimes
([@&#8203;lukastaegert](https://redirect.github.com/lukastaegert))
- [#&#8203;5771](https://redirect.github.com/rollup/rollup/pull/5771):
fix: do not optimize the literal value if the cache is deoptimized
([@&#8203;TrickyPi](https://redirect.github.com/TrickyPi))

###
[`v4.29.0`](https://redirect.github.com/rollup/rollup/blob/HEAD/CHANGELOG.md#4290)

[Compare
Source](https://redirect.github.com/rollup/rollup/compare/v4.28.1...v4.29.0)

*2024-12-20*

##### Features

- Treat objects as truthy and always check second argument to better
simplify logical expressions
([#&#8203;5763](https://redirect.github.com/rollup/rollup/issues/5763))

##### Pull Requests

- [#&#8203;5759](https://redirect.github.com/rollup/rollup/pull/5759):
docs: add utf-8 encoding to JSON file reading
([@&#8203;chouchouji](https://redirect.github.com/chouchouji))
- [#&#8203;5760](https://redirect.github.com/rollup/rollup/pull/5760):
fix(deps): lock file maintenance minor/patch updates
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])
- [#&#8203;5763](https://redirect.github.com/rollup/rollup/pull/5763):
fix: introduce UnknownFalsyValue for enhancing if statement tree-shaking
([@&#8203;TrickyPi](https://redirect.github.com/TrickyPi))
- [#&#8203;5766](https://redirect.github.com/rollup/rollup/pull/5766):
chore(deps): update dependency
[@&#8203;rollup/plugin-node-resolve](https://redirect.github.com/rollup/plugin-node-resolve)
to v16 ([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])
- [#&#8203;5767](https://redirect.github.com/rollup/rollup/pull/5767):
fix(deps): lock file maintenance minor/patch updates
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])

###
[`v4.28.1`](https://redirect.github.com/rollup/rollup/blob/HEAD/CHANGELOG.md#4281)

[Compare
Source](https://redirect.github.com/rollup/rollup/compare/v4.28.0...v4.28.1)

*2024-12-06*

##### Bug Fixes

- Support running Rollup natively on LoongArch
([#&#8203;5749](https://redirect.github.com/rollup/rollup/issues/5749))
- Add optional `debugId` to `SourceMap` types
([#&#8203;5751](https://redirect.github.com/rollup/rollup/issues/5751))

##### Pull Requests

- [#&#8203;5749](https://redirect.github.com/rollup/rollup/pull/5749):
feat: add support for LoongArch
([@&#8203;darkyzhou](https://redirect.github.com/darkyzhou))
- [#&#8203;5751](https://redirect.github.com/rollup/rollup/pull/5751):
feat: Add `debugId` to `SourceMap` types
([@&#8203;timfish](https://redirect.github.com/timfish),
[@&#8203;lukastaegert](https://redirect.github.com/lukastaegert))
- [#&#8203;5752](https://redirect.github.com/rollup/rollup/pull/5752):
chore(deps): update dependency mocha to v11
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])
- [#&#8203;5753](https://redirect.github.com/rollup/rollup/pull/5753):
chore(deps): update dependency vite to v6
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])
- [#&#8203;5754](https://redirect.github.com/rollup/rollup/pull/5754):
fix(deps): update swc monorepo (major)
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])
- [#&#8203;5755](https://redirect.github.com/rollup/rollup/pull/5755):
chore(deps): lock file maintenance minor/patch updates
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])
- [#&#8203;5756](https://redirect.github.com/rollup/rollup/pull/5756):
Test if saving the Cargo cache can speed up FreeBSD
([@&#8203;lukastaegert](https://redirect.github.com/lukastaegert))

###
[`v4.28.0`](https://redirect.github.com/rollup/rollup/blob/HEAD/CHANGELOG.md#4280)

[Compare
Source](https://redirect.github.com/rollup/rollup/compare/v4.27.4...v4.28.0)

*2024-11-30*

##### Features

- Allow to specify how to handle import attributes when transpiling
Rollup config files
([#&#8203;5743](https://redirect.github.com/rollup/rollup/issues/5743))

##### Pull Requests

- [#&#8203;5743](https://redirect.github.com/rollup/rollup/pull/5743):
fix: supports modify the import attributes key in the config file
([@&#8203;TrickyPi](https://redirect.github.com/TrickyPi),
[@&#8203;lukastaegert](https://redirect.github.com/lukastaegert))
- [#&#8203;5747](https://redirect.github.com/rollup/rollup/pull/5747):
chore(deps): update codecov/codecov-action action to v5
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])
- [#&#8203;5748](https://redirect.github.com/rollup/rollup/pull/5748):
chore(deps): lock file maintenance minor/patch updates
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])

###
[`v4.27.4`](https://redirect.github.com/rollup/rollup/blob/HEAD/CHANGELOG.md#4274)

[Compare
Source](https://redirect.github.com/rollup/rollup/compare/v4.27.3...v4.27.4)

*2024-11-23*

##### Bug Fixes

- Update bundled magic-string to support sourcemap debug ids
([#&#8203;5740](https://redirect.github.com/rollup/rollup/issues/5740))

##### Pull Requests

- [#&#8203;5740](https://redirect.github.com/rollup/rollup/pull/5740):
chore(deps): lock file maintenance minor/patch updates
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])

###
[`v4.27.3`](https://redirect.github.com/rollup/rollup/blob/HEAD/CHANGELOG.md#4273)

[Compare
Source](https://redirect.github.com/rollup/rollup/compare/v4.27.2...v4.27.3)

*2024-11-18*

##### Bug Fixes

- Revert object property tree-shaking for now
([#&#8203;5736](https://redirect.github.com/rollup/rollup/issues/5736))

##### Pull Requests

- [#&#8203;5736](https://redirect.github.com/rollup/rollup/pull/5736):
Revert object tree-shaking until some issues have been resolved
([@&#8203;lukastaegert](https://redirect.github.com/lukastaegert))

###
[`v4.27.2`](https://redirect.github.com/rollup/rollup/blob/HEAD/CHANGELOG.md#4272)

[Compare
Source](https://redirect.github.com/rollup/rollup/compare/v4.27.1...v4.27.2)

*2024-11-15*

##### Bug Fixes

- Ensure unused variables in patterns are always deconflicted if
rendered
([#&#8203;5728](https://redirect.github.com/rollup/rollup/issues/5728))

##### Pull Requests

- [#&#8203;5728](https://redirect.github.com/rollup/rollup/pull/5728):
Fix more variable deconflicting issues
([@&#8203;lukastaegert](https://redirect.github.com/lukastaegert))

###
[`v4.27.1`](https://redirect.github.com/rollup/rollup/blob/HEAD/CHANGELOG.md#4271)

[Compare
Source](https://redirect.github.com/rollup/rollup/compare/v4.27.0...v4.27.1)

*2024-11-15*

##### Bug Fixes

- Fix some situations where parameter declarations could put Rollup into
an infinite loop
([#&#8203;5727](https://redirect.github.com/rollup/rollup/issues/5727))

##### Pull Requests

- [#&#8203;5727](https://redirect.github.com/rollup/rollup/pull/5727):
Debug out-of-memory issues with Rollup v4.27.0
([@&#8203;lukastaegert](https://redirect.github.com/lukastaegert))

###
[`v4.27.0`](https://redirect.github.com/rollup/rollup/blob/HEAD/CHANGELOG.md#4270)

[Compare
Source](https://redirect.github.com/rollup/rollup/compare/v4.26.0...v4.27.0)

*2024-11-15*

##### Features

- Tree-shake unused properties in object literals
([#&#8203;5420](https://redirect.github.com/rollup/rollup/issues/5420))

##### Bug Fixes

- Change hash length limit to 21 to avoid inconsistent hash length
([#&#8203;5423](https://redirect.github.com/rollup/rollup/issues/5423))

##### Pull Requests

- [#&#8203;5420](https://redirect.github.com/rollup/rollup/pull/5420):
feat: implement object tree-shaking
([@&#8203;TrickyPi](https://redirect.github.com/TrickyPi),
[@&#8203;lukastaegert](https://redirect.github.com/lukastaegert))
- [#&#8203;5723](https://redirect.github.com/rollup/rollup/pull/5723):
Reduce max hash size to 21
([@&#8203;lukastaegert](https://redirect.github.com/lukastaegert))
- [#&#8203;5724](https://redirect.github.com/rollup/rollup/pull/5724):
fix(deps): update swc monorepo (major)
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])
- [#&#8203;5725](https://redirect.github.com/rollup/rollup/pull/5725):
chore(deps): lock file maintenance minor/patch updates
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])

###
[`v4.26.0`](https://redirect.github.com/rollup/rollup/blob/HEAD/CHANGELOG.md#4260)

[Compare
Source](https://redirect.github.com/rollup/rollup/compare/v4.25.0...v4.26.0)

*2024-11-13*

##### Features

- Allow to avoid `await bundle.close()` via explicit resource management
in TypeScript
([#&#8203;5721](https://redirect.github.com/rollup/rollup/issues/5721))

##### Pull Requests

- [#&#8203;5721](https://redirect.github.com/rollup/rollup/pull/5721):
feat: support `using` for `RollupBuild`
([@&#8203;shulaoda](https://redirect.github.com/shulaoda))

###
[`v4.25.0`](https://redirect.github.com/rollup/rollup/blob/HEAD/CHANGELOG.md#4250)

[Compare
Source](https://redirect.github.com/rollup/rollup/compare/v4.24.4...v4.25.0)

*2024-11-09*

##### Features

- Add `output.sourcemapDebugIds` option to add matching debug ids to
sourcemaps and code for tools like Sentry or Rollbar
([#&#8203;5712](https://redirect.github.com/rollup/rollup/issues/5712))

##### Bug Fixes

- Make it easier to manually reproduce base16 hashes by using a more
standard base16 conversion algorithm
([#&#8203;5719](https://redirect.github.com/rollup/rollup/issues/5719))

##### Pull Requests

- [#&#8203;5712](https://redirect.github.com/rollup/rollup/pull/5712):
feat: Add support for injecting Debug IDs
([@&#8203;timfish](https://redirect.github.com/timfish))
- [#&#8203;5717](https://redirect.github.com/rollup/rollup/pull/5717):
fix(deps): update swc monorepo (major)
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])
- [#&#8203;5718](https://redirect.github.com/rollup/rollup/pull/5718):
chore(deps): lock file maintenance minor/patch updates
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])
- [#&#8203;5719](https://redirect.github.com/rollup/rollup/pull/5719):
Use a less surprising base-16 encoding
([@&#8203;lukastaegert](https://redirect.github.com/lukastaegert))

###
[`v4.24.4`](https://redirect.github.com/rollup/rollup/blob/HEAD/CHANGELOG.md#4244)

[Compare
Source](https://redirect.github.com/rollup/rollup/compare/v4.24.3...v4.24.4)

*2024-11-04*

##### Bug Fixes

- Ensure mutations by handlers in Proxy definitions are always respected
when tree-shaking
([#&#8203;5713](https://redirect.github.com/rollup/rollup/issues/5713))

##### Pull Requests

- [#&#8203;5708](https://redirect.github.com/rollup/rollup/pull/5708):
Update configuration-options document
([@&#8203;sacru2red](https://redirect.github.com/sacru2red),
[@&#8203;lukastaegert](https://redirect.github.com/lukastaegert))
- [#&#8203;5711](https://redirect.github.com/rollup/rollup/pull/5711):
chore(deps): lock file maintenance minor/patch updates
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])
- [#&#8203;5713](https://redirect.github.com/rollup/rollup/pull/5713):
fix: Deoptimize the proxied object if its property is reassigned in the
handler functions
([@&#8203;TrickyPi](https://redirect.github.com/TrickyPi))

###
[`v4.24.3`](https://redirect.github.com/rollup/rollup/blob/HEAD/CHANGELOG.md#4243)

[Compare
Source](https://redirect.github.com/rollup/rollup/compare/v4.24.2...v4.24.3)

*2024-10-29*

##### Bug Fixes

- Slightly reduce memory consumption by specifying fixed array sizes
where possible
([#&#8203;5703](https://redirect.github.com/rollup/rollup/issues/5703))

##### Pull Requests

- [#&#8203;5703](https://redirect.github.com/rollup/rollup/pull/5703):
perf: use pre-allocated arrays for known result sizes
([@&#8203;GalacticHypernova](https://redirect.github.com/GalacticHypernova))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/open-feature/js-sdk).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNDUuMCIsInVwZGF0ZWRJblZlciI6IjQwLjcuMSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-15 15:48:41 +00:00
renovate[bot] cb14827639
chore(deps): update dependency @types/supertest to v6.0.3 (#1169)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[@types/supertest](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/supertest)
([source](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/supertest))
| [`6.0.2` ->
`6.0.3`](https://renovatebot.com/diffs/npm/@types%2fsupertest/6.0.2/6.0.3)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2fsupertest/6.0.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2fsupertest/6.0.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2fsupertest/6.0.2/6.0.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2fsupertest/6.0.2/6.0.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/open-feature/js-sdk).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMzguMCIsInVwZGF0ZWRJblZlciI6IjM5LjIzOC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-15 15:48:17 +00:00
renovate[bot] c00675c9bd
chore(deps): update dependency @types/node to v22 (#1067)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[@types/node](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node)
([source](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node))
| [`^20.11.16` ->
`^22.0.0`](https://renovatebot.com/diffs/npm/@types%2fnode/20.17.31/22.15.17)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2fnode/22.15.17?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2fnode/22.15.17?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2fnode/20.17.31/22.15.17?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2fnode/20.17.31/22.15.17?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/open-feature/js-sdk).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC4xMzMuMSIsInVwZGF0ZWRJblZlciI6IjQwLjcuMSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-15 15:48:00 +00:00
renovate[bot] 1e58d2b65e
chore(deps): update dependency @types/node to v20.17.31 (#1138)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[@types/node](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node)
([source](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node))
| [`20.17.16` ->
`20.17.31`](https://renovatebot.com/diffs/npm/@types%2fnode/20.17.16/20.17.31)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2fnode/20.17.31?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2fnode/20.17.31?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2fnode/20.17.16/20.17.31?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2fnode/20.17.16/20.17.31?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/open-feature/js-sdk).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNDUuMCIsInVwZGF0ZWRJblZlciI6IjM5LjI1Ny4zIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-30 13:01:21 -04:00
Michael Beemer 59c2f5df76
chore: regenerate package lock (#1184)
Attempting to address the E2E failure:
https://github.com/open-feature/js-sdk/actions/runs/14643009193/job/41089818968?pr=1181

Signed-off-by: Michael Beemer <beeme1mr@users.noreply.github.com>
2025-04-24 12:25:37 -04:00
Kaushal Kapasi 59b8fe904f
feat: adds RequireFlagsEnabled decorator (#1159)
## This PR
- Feature: Adds a `RequireFlagsEnabled` decorator to allow a simple,
reusable way to block access to a specific controller or endpoint based
on the value of a list of one, or many, boolean flags

### Notes
- Discussions on the approach & implementation are welcome!

### Follow-up Tasks
- Update OpenFeature NestJS docs to include new `RequireFlagsEnabled`
decorator & usage examples

### How to test
`npx jest --selectProject=nest`

---------

Signed-off-by: Kaushal Kapasi <kaushal.kapasi@taplytics.com>
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
Co-authored-by: Todd Baert <todd.baert@dynatrace.com>
2025-04-24 13:32:55 +00:00
Michael Beemer 4fe8d87a2e
docs: Clarify the behavior of setProviderAndWait (#1180)
## This PR

- Updates readme examples to include a try/catch around
setProviderAndWait
- Improves the setProviderAndWait JS Doc

### Related Issues

Fixes #1179

### Notes

https://cloud-native.slack.com/archives/C0344AANLA1/p1745326882304199

---------

Signed-off-by: Michael Beemer <beeme1mr@users.noreply.github.com>
2025-04-23 13:16:18 -04:00
OpenFeature Bot a259b9097b
chore(main): release angular-sdk 0.0.13 (#1175) 2025-04-20 19:07:29 +02:00
OpenFeature Bot d13adca9cd
chore(main): release nestjs-sdk 0.2.4 (#1177) 2025-04-20 19:07:06 +02:00
Lukas Reining 42a3b39c24
chore(nest): allow nestjs version 11 (#1176) 2025-04-20 09:26:13 +02:00
Todd Baert 2f55a36dca
chore: use publish env
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
2025-04-16 12:27:46 -04:00
Lukas Reining 21a32ec92e
docs: fix readme typo (#1174)
Signed-off-by: Lukas Reining <lukas.reining@codecentric.de>
2025-04-14 16:41:22 -04:00
OpenFeature Bot 07a3d85742
chore(main): release react-sdk 1.0.0 (#1154)
🤖 I have created a release *beep* *boop*
---


##
[1.0.0](https://github.com/open-feature/js-sdk/compare/react-sdk-v0.4.11...react-sdk-v1.0.0)
(2025-04-14)


###  New Features

* add polyfill for react use hook
([#1157](https://github.com/open-feature/js-sdk/issues/1157))
([5afe61f](5afe61f9e3))
* add support for abort controllers to event handlers
([#1151](https://github.com/open-feature/js-sdk/issues/1151))
([6a22483](6a224830fa))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

---------

Signed-off-by: OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
Co-authored-by: Todd Baert <todd.baert@dynatrace.com>
2025-04-14 17:03:15 +00:00
OpenFeature Bot 37bcf3cf48
chore(main): release web-sdk 1.5.0 (#1156)
🤖 I have created a release *beep* *boop*
---


##
[1.5.0](https://github.com/open-feature/js-sdk/compare/web-sdk-v1.4.1...web-sdk-v1.5.0)
(2025-04-11)


###  New Features

* add a top-level method for accessing providers
([#1152](https://github.com/open-feature/js-sdk/issues/1152))
([ae8fce8](ae8fce8753))
* add support for abort controllers to event handlers
([#1151](https://github.com/open-feature/js-sdk/issues/1151))
([6a22483](6a224830fa))


### 🐛 Bug Fixes

* Typo in name of the function
([2c5b37c](2c5b37c79d))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

---------

Signed-off-by: OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
Co-authored-by: Lukas Reining <lukas.reining@codecentric.de>
Co-authored-by: Todd Baert <todd.baert@dynatrace.com>
2025-04-14 15:48:45 +00:00
OpenFeature Bot aff60f6776
chore(main): release server-sdk 1.18.0 (#1153)
🤖 I have created a release *beep* *boop*
---


##
[1.18.0](https://github.com/open-feature/js-sdk/compare/server-sdk-v1.17.1...server-sdk-v1.18.0)
(2025-04-11)


###  New Features

* add a top-level method for accessing providers
([#1152](https://github.com/open-feature/js-sdk/issues/1152))
([ae8fce8](ae8fce8753))
* add support for abort controllers to event handlers
([#1151](https://github.com/open-feature/js-sdk/issues/1151))
([6a22483](6a224830fa))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Signed-off-by: OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>
Co-authored-by: Lukas Reining <lukas.reining@codecentric.de>
2025-04-11 14:30:17 +02:00
OpenFeature Bot 7864bd704c
chore(main): release nestjs-sdk 0.2.3 (#1144)
🤖 I have created a release *beep* *boop*
---


##
[0.2.3](https://github.com/open-feature/js-sdk/compare/nestjs-sdk-v0.2.2...nestjs-sdk-v0.2.3)
(2025-04-11)


### 🧹 Chore

* update sdk peer
([#1142](https://github.com/open-feature/js-sdk/issues/1142))
([8bb6206](8bb620601e))


### Dependencies

* The following workspace dependencies were updated
  * devDependencies
    * @openfeature/server-sdk bumped from * to 1.18.0

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Signed-off-by: OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>
2025-04-11 14:17:48 +02:00
OpenFeature Bot 191433e705
chore(main): release angular-sdk 0.0.12 (#1171)
🤖 I have created a release *beep* *boop*
---


##
[0.0.12](https://github.com/open-feature/js-sdk/compare/angular-sdk-v0.0.11...angular-sdk-v0.0.12)
(2025-04-11)


###  New Features

* **angular:** add docs for setting evaluation context in angular
([#1170](https://github.com/open-feature/js-sdk/issues/1170))
([24f1b23](24f1b230bf))


### Dependencies

* The following workspace dependencies were updated
  * devDependencies
    * @openfeature/web-sdk bumped from * to 1.5.0

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

---------

Signed-off-by: OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>
Signed-off-by: Lukas Reining <lukas.reining@codecentric.de>
Co-authored-by: Lukas Reining <lukas.reining@codecentric.de>
2025-04-11 14:04:30 +02:00
Lukas Reining 24f1b230bf
feat(angular): add docs for setting evaluation context in angular (#1170)
<!-- Please use this template for your pull request. -->
<!-- Please use the sections that you need and delete other sections -->

Adds docs for setting evaluation context in angular

Signed-off-by: Lukas Reining <lukas.reining@codecentric.de>
2025-04-11 13:56:24 +02:00
renovate[bot] 5f85a56362
chore(deps): update dependency esbuild to ^0.25.0 [security] (#1145)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [esbuild](https://redirect.github.com/evanw/esbuild) | [`^0.24.0` ->
`^0.25.0`](https://renovatebot.com/diffs/npm/esbuild/0.24.2/0.25.0) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/esbuild/0.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/esbuild/0.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/esbuild/0.24.2/0.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/esbuild/0.24.2/0.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

### GitHub Vulnerability Alerts

####
[GHSA-67mh-4wv8-2f99](https://redirect.github.com/evanw/esbuild/security/advisories/GHSA-67mh-4wv8-2f99)

### Summary

esbuild allows any websites to send any request to the development
server and read the response due to default CORS settings.

### Details

esbuild sets `Access-Control-Allow-Origin: *` header to all requests,
including the SSE connection, which allows any websites to send any
request to the development server and read the response.


df815ac27b/pkg/api/serve_other.go (L121)

df815ac27b/pkg/api/serve_other.go (L363)

**Attack scenario**:

1. The attacker serves a malicious web page
(`http://malicious.example.com`).
1. The user accesses the malicious web page.
1. The attacker sends a `fetch('http://127.0.0.1:8000/main.js')` request
by JS in that malicious web page. This request is normally blocked by
same-origin policy, but that's not the case for the reasons above.
1. The attacker gets the content of `http://127.0.0.1:8000/main.js`.

In this scenario, I assumed that the attacker knows the URL of the
bundle output file name. But the attacker can also get that information
by

- Fetching `/index.html`: normally you have a script tag here
- Fetching `/assets`: it's common to have a `assets` directory when you
have JS files and CSS files in a different directory and the directory
listing feature tells the attacker the list of files
- Connecting `/esbuild` SSE endpoint: the SSE endpoint sends the URL
path of the changed files when the file is changed (`new
EventSource('/esbuild').addEventListener('change', e =>
console.log(e.type, e.data))`)
- Fetching URLs in the known file: once the attacker knows one file, the
attacker can know the URLs imported from that file

The scenario above fetches the compiled content, but if the victim has
the source map option enabled, the attacker can also get the
non-compiled content by fetching the source map file.

### PoC

1. Download
[reproduction.zip](https://redirect.github.com/user-attachments/files/18561484/reproduction.zip)
2. Extract it and move to that directory
1. Run `npm i`
1. Run `npm run watch`
1. Run `fetch('http://127.0.0.1:8000/app.js').then(r =>
r.text()).then(content => console.log(content))` in a different
website's dev tools.


![image](https://redirect.github.com/user-attachments/assets/08fc2e4d-e1ec-44ca-b0ea-78a73c3c40e9)

### Impact

Users using the serve feature may get the source code stolen by
malicious websites.

---

### Release Notes

<details>
<summary>evanw/esbuild (esbuild)</summary>

###
[`v0.25.0`](https://redirect.github.com/evanw/esbuild/blob/HEAD/CHANGELOG.md#v0250)

[Compare
Source](https://redirect.github.com/evanw/esbuild/compare/v0.24.2...v0.25.0)

**This release deliberately contains backwards-incompatible changes.**
To avoid automatically picking up releases like this, you should either
be pinning the exact version of `esbuild` in your `package.json` file
(recommended) or be using a version range syntax that only accepts patch
upgrades such as `^0.24.0` or `~0.24.0`. See npm's documentation about
[semver](https://docs.npmjs.com/cli/v6/using-npm/semver/) for more
information.

- Restrict access to esbuild's development server
([GHSA-67mh-4wv8-2f99](https://redirect.github.com/evanw/esbuild/security/advisories/GHSA-67mh-4wv8-2f99))

This change addresses esbuild's first security vulnerability report.
Previously esbuild set the `Access-Control-Allow-Origin` header to `*`
to allow esbuild's development server to be flexible in how it's used
for development. However, this allows the websites you visit to make
HTTP requests to esbuild's local development server, which gives
read-only access to your source code if the website were to fetch your
source code's specific URL. You can read more information in [the
report](https://redirect.github.com/evanw/esbuild/security/advisories/GHSA-67mh-4wv8-2f99).

Starting with this release,
[CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) will now
be disabled, and requests will now be denied if the host does not match
the one provided to `--serve=`. The default host is `0.0.0.0`, which
refers to all of the IP addresses that represent the local machine (e.g.
both `127.0.0.1` and `192.168.0.1`). If you want to customize anything
about esbuild's development server, you can [put a proxy in front of
esbuild](https://esbuild.github.io/api/#serve-proxy) and modify the
incoming and/or outgoing requests.

In addition, the `serve()` API call has been changed to return an array
of `hosts` instead of a single `host` string. This makes it possible to
determine all of the hosts that esbuild's development server will
accept.

Thanks to [@&#8203;sapphi-red](https://redirect.github.com/sapphi-red)
for reporting this issue.

- Delete output files when a build fails in watch mode
([#&#8203;3643](https://redirect.github.com/evanw/esbuild/issues/3643))

It has been requested for esbuild to delete files when a build fails in
watch mode. Previously esbuild left the old files in place, which could
cause people to not immediately realize that the most recent build
failed. With this release, esbuild will now delete all output files if a
rebuild fails. Fixing the build error and triggering another rebuild
will restore all output files again.

- Fix correctness issues with the CSS nesting transform
([#&#8203;3620](https://redirect.github.com/evanw/esbuild/issues/3620),
[#&#8203;3877](https://redirect.github.com/evanw/esbuild/issues/3877),
[#&#8203;3933](https://redirect.github.com/evanw/esbuild/issues/3933),
[#&#8203;3997](https://redirect.github.com/evanw/esbuild/issues/3997),
[#&#8203;4005](https://redirect.github.com/evanw/esbuild/issues/4005),
[#&#8203;4037](https://redirect.github.com/evanw/esbuild/pull/4037),
[#&#8203;4038](https://redirect.github.com/evanw/esbuild/pull/4038))

    This release fixes the following problems:

- Naive expansion of CSS nesting can result in an exponential blow-up of
generated CSS if each nesting level has multiple selectors. Previously
esbuild sometimes collapsed individual nesting levels using `:is()` to
limit expansion. However, this collapsing wasn't correct in some cases,
so it has been removed to fix correctness issues.

        ```css
        /* Original code */
        .parent {
          > .a,
          > .b1 > .b2 {
            color: red;
          }
        }

        /* Old output (with --supported:nesting=false) */
        .parent > :is(.a, .b1 > .b2) {
          color: red;
        }

        /* New output (with --supported:nesting=false) */
        .parent > .a,
        .parent > .b1 > .b2 {
          color: red;
        }
        ```

Thanks to [@&#8203;tim-we](https://redirect.github.com/tim-we) for
working on a fix.

- The `&` CSS nesting selector can be repeated multiple times to
increase CSS specificity. Previously esbuild ignored this possibility
and incorrectly considered `&&` to have the same specificity as `&`.
With this release, this should now work correctly:

        ```css
        /* Original code (color should be red) */
        div {
          && { color: red }
          & { color: blue }
        }

        /* Old output (with --supported:nesting=false) */
        div {
          color: red;
        }
        div {
          color: blue;
        }

        /* New output (with --supported:nesting=false) */
        div:is(div) {
          color: red;
        }
        div {
          color: blue;
        }
        ```

Thanks to [@&#8203;CPunisher](https://redirect.github.com/CPunisher) for
working on a fix.

- Previously transforming nested CSS incorrectly removed leading
combinators from within pseudoclass selectors such as `:where()`. This
edge case has been fixed and how has test coverage.

        ```css
        /* Original code */
        a b:has(> span) {
          a & {
            color: green;
          }
        }

        /* Old output (with --supported:nesting=false) */
        a :is(a b:has(span)) {
          color: green;
        }

        /* New output (with --supported:nesting=false) */
        a :is(a b:has(> span)) {
          color: green;
        }
        ```

This fix was contributed by
[@&#8203;NoremacNergfol](https://redirect.github.com/NoremacNergfol).

- The CSS minifier contains logic to remove the `&` selector when it can
be implied, which happens when there is only one and it's the leading
token. However, this logic was incorrectly also applied to selector
lists inside of pseudo-class selectors such as `:where()`. With this
release, the minifier will now avoid applying this logic in this edge
case:

        ```css
        /* Original code */
        .a {
          & .b { color: red }
          :where(& .b) { color: blue }
        }

        /* Old output (with --minify) */
        .a{.b{color:red}:where(.b){color:#&#8203;00f}}

        /* New output (with --minify) */
        .a{.b{color:red}:where(& .b){color:#&#8203;00f}}
        ```

- Fix some correctness issues with source maps
([#&#8203;1745](https://redirect.github.com/evanw/esbuild/issues/1745),
[#&#8203;3183](https://redirect.github.com/evanw/esbuild/issues/3183),
[#&#8203;3613](https://redirect.github.com/evanw/esbuild/issues/3613),
[#&#8203;3982](https://redirect.github.com/evanw/esbuild/issues/3982))

Previously esbuild incorrectly treated source map path references as
file paths instead of as URLs. With this release, esbuild will now treat
source map path references as URLs. This fixes the following problems
with source maps:

- File names in `sourceMappingURL` that contained a space previously did
not encode the space as `%20`, which resulted in JavaScript tools
(including esbuild) failing to read that path back in when consuming the
generated output file. This should now be fixed.

- Absolute URLs in `sourceMappingURL` that use the `file://` scheme
previously attempted to read from a folder called `file:`. These URLs
should now be recognized and parsed correctly.

- Entries in the `sources` array in the source map are now treated as
URLs instead of file paths. The correct behavior for this is much more
clear now that source maps has a [formal
specification](https://tc39.es/ecma426/). Many thanks to those who
worked on the specification.

- Fix incorrect package for `@esbuild/netbsd-arm64`
([#&#8203;4018](https://redirect.github.com/evanw/esbuild/issues/4018))

Due to a copy+paste typo, the binary published to
`@esbuild/netbsd-arm64` was not actually for `arm64`, and didn't run in
that environment. This release should fix running esbuild in that
environment (NetBSD on 64-bit ARM). Sorry about the mistake.

- Fix a minification bug with bitwise operators and bigints
([#&#8203;4065](https://redirect.github.com/evanw/esbuild/issues/4065))

This change removes an incorrect assumption in esbuild that all bitwise
operators result in a numeric integer. That assumption was correct up
until the introduction of bigints in ES2020, but is no longer correct
because almost all bitwise operators now operate on both numbers and
bigints. Here's an example of the incorrect minification:

    ```js
    // Original code
    if ((a & b) !== 0) found = true

    // Old output (with --minify)
    a&b&&(found=!0);

    // New output (with --minify)
    (a&b)!==0&&(found=!0);
    ```

- Fix esbuild incorrectly rejecting valid TypeScript edge case
([#&#8203;4027](https://redirect.github.com/evanw/esbuild/issues/4027))

    The following TypeScript code is valid:

    ```ts
    export function open(async?: boolean): void {
      console.log(async as boolean)
    }
    ```

Before this version, esbuild would fail to parse this with a syntax
error as it expected the token sequence `async as ...` to be the start
of an async arrow function expression `async as => ...`. This edge case
should be parsed correctly by esbuild starting with this release.

- Transform BigInt values into constructor calls when unsupported
([#&#8203;4049](https://redirect.github.com/evanw/esbuild/issues/4049))

Previously esbuild would refuse to compile the BigInt literals (such as
`123n`) if they are unsupported in the configured target environment
(such as with `--target=es6`). The rationale was that they cannot be
polyfilled effectively because they change the behavior of JavaScript's
arithmetic operators and JavaScript doesn't have operator overloading.

However, this prevents using esbuild with certain libraries that would
otherwise work if BigInt literals were ignored, such as with old
versions of the [`buffer`
library](https://redirect.github.com/feross/buffer) before the library
fixed support for running in environments without BigInt support. So
with this release, esbuild will now turn BigInt literals into BigInt
constructor calls (so `123n` becomes `BigInt(123)`) and generate a
warning in this case. You can turn off the warning with
`--log-override:bigint=silent` or restore the warning to an error with
`--log-override:bigint=error` if needed.

- Change how `console` API dropping works
([#&#8203;4020](https://redirect.github.com/evanw/esbuild/issues/4020))

Previously the `--drop:console` feature replaced all method calls off of
the `console` global with `undefined` regardless of how long the
property access chain was (so it applied to `console.log()` and
`console.log.call(console)` and `console.log.not.a.method()`). However,
it was pointed out that this breaks uses of `console.log.bind(console)`.
That's also incompatible with Terser's implementation of the feature,
which is where this feature originally came from (it does support
`bind`). So with this release, using this feature with esbuild will now
only replace one level of method call (unless extended by `call` or
`apply`) and will replace the method being called with an empty function
in complex cases:

    ```js
    // Original code
    const x = console.log('x')
    const y = console.log.call(console, 'y')
    const z = console.log.bind(console)('z')

    // Old output (with --drop-console)
    const x = void 0;
    const y = void 0;
    const z = (void 0)("z");

    // New output (with --drop-console)
    const x = void 0;
    const y = void 0;
    const z = (() => {
    }).bind(console)("z");
    ```

    This should more closely match Terser's existing behavior.

-   Allow BigInt literals as `define` values

With this release, you can now use BigInt literals as define values,
such as with `--define:FOO=123n`. Previously trying to do this resulted
in a syntax error.

- Fix a bug with resolve extensions in `node_modules`
([#&#8203;4053](https://redirect.github.com/evanw/esbuild/issues/4053))

The `--resolve-extensions=` option lets you specify the order in which
to try resolving implicit file extensions. For complicated reasons,
esbuild reorders TypeScript file extensions after JavaScript ones inside
of `node_modules` so that JavaScript source code is always preferred to
TypeScript source code inside of dependencies. However, this reordering
had a bug that could accidentally change the relative order of
TypeScript file extensions if one of them was a prefix of the other.
That bug has been fixed in this release. You can see the issue for
details.

- Better minification of statically-determined `switch` cases
([#&#8203;4028](https://redirect.github.com/evanw/esbuild/issues/4028))

With this release, esbuild will now try to trim unused code within
`switch` statements when the test expression and `case` expressions are
primitive literals. This can arise when the test expression is an
identifier that is substituted for a primitive literal at compile time.
For example:

    ```js
    // Original code
    switch (MODE) {
      case 'dev':
        installDevToolsConsole()
        break
      case 'prod':
        return
      default:
        throw new Error
    }

    // Old output (with --minify '--define:MODE="prod"')

switch("prod"){case"dev":installDevToolsConsole();break;case"prod":return;default:throw
new Error}

    // New output (with --minify '--define:MODE="prod"')
    return;
    ```

- Emit `/* @&#8203;__KEY__ */` for string literals derived from property
names
([#&#8203;4034](https://redirect.github.com/evanw/esbuild/issues/4034))

Property name mangling is an advanced feature that shortens certain
property names for better minification (I say "advanced feature" because
it's very easy to break your code with it). Sometimes you need to store
a property name in a string, such as `obj.get('foo')` instead of
`obj.foo`. JavaScript minifiers such as esbuild and
[Terser](https://terser.org/) have a convention where a `/*
@&#8203;__KEY__ */` comment before the string makes it behave like a
property name. So `obj.get(/* @&#8203;__KEY__ */ 'foo')` allows the
contents of the string `'foo'` to be shortened.

However, esbuild sometimes itself generates string literals containing
property names when transforming code, such as when lowering class
fields to ES6 or when transforming TypeScript decorators. Previously
esbuild didn't generate its own `/* @&#8203;__KEY__ */` comments in this
case, which means that minifying your code by running esbuild again on
its own output wouldn't work correctly (this does not affect people that
both minify and transform their code in a single step).

With this release, esbuild will now generate `/* @&#8203;__KEY__ */`
comments for property names in generated string literals. To avoid lots
of unnecessary output for people that don't use this advanced feature,
the generated comments will only be present when the feature is active.
If you want to generate the comments but not actually mangle any
property names, you can use a flag that has no effect such as
`--reserve-props=.`, which tells esbuild to not mangle any property
names (but still activates this feature).

- The `text` loader now strips the UTF-8 BOM if present
([#&#8203;3935](https://redirect.github.com/evanw/esbuild/issues/3935))

Some software (such as Notepad on Windows) can create text files that
start with the three bytes `0xEF 0xBB 0xBF`, which is referred to as the
"byte order mark". This prefix is intended to be removed before using
the text. Previously esbuild's `text` loader included this byte sequence
in the string, which turns into a prefix of `\uFEFF` in a JavaScript
string when decoded from UTF-8. With this release, esbuild's `text`
loader will now remove these bytes when they occur at the start of the
file.

- Omit legal comment output files when empty
([#&#8203;3670](https://redirect.github.com/evanw/esbuild/issues/3670))

Previously configuring esbuild with `--legal-comment=external` or
`--legal-comment=linked` would always generate a `.LEGAL.txt` output
file even if it was empty. Starting with this release, esbuild will now
only do this if the file will be non-empty. This should result in a more
organized output directory in some cases.

- Update Go from 1.23.1 to 1.23.5
([#&#8203;4056](https://redirect.github.com/evanw/esbuild/issues/4056),
[#&#8203;4057](https://redirect.github.com/evanw/esbuild/pull/4057))

This should have no effect on existing code as this version change does
not change Go's operating system support. It may remove certain reports
from vulnerability scanners that detect which version of the Go compiler
esbuild uses.

This PR was contributed by
[@&#8203;MikeWillCook](https://redirect.github.com/MikeWillCook).

- Allow passing a port of 0 to the development server
([#&#8203;3692](https://redirect.github.com/evanw/esbuild/issues/3692))

Unix sockets interpret a port of 0 to mean "pick a random unused port in
the [ephemeral port](https://en.wikipedia.org/wiki/Ephemeral_port)
range". However, esbuild's default behavior when the port is not
specified is to pick the first unused port starting from 8000 and
upward. This is more convenient because port 8000 is typically free, so
you can for example restart the development server and reload your app
in the browser without needing to change the port in the URL. Since
esbuild is written in Go (which does not have optional fields like
JavaScript), not specifying the port in Go means it defaults to 0, so
previously passing a port of 0 to esbuild caused port 8000 to be picked.

Starting with this release, passing a port of 0 to esbuild when using
the CLI or the JS API will now pass port 0 to the OS, which will pick a
random ephemeral port. To make this possible, the `Port` option in the
Go API has been changed from `uint16` to `int` (to allow for additional
sentinel values) and passing a port of -1 in Go now picks a random port.
Both the CLI and JS APIs now remap an explicitly-provided port of 0 into
-1 for the internal Go API.

Another option would have been to change `Port` in Go from `uint16` to
`*uint16` (Go's closest equivalent of `number | undefined`). However,
that would make the common case of providing an explicit port in Go very
awkward as Go doesn't support taking the address of integer constants.
This tradeoff isn't worth it as picking a random ephemeral port is a
rare use case. So the CLI and JS APIs should now match standard Unix
behavior when the port is 0, but you need to use -1 instead with Go API.

- Minification now avoids inlining constants with direct `eval`
([#&#8203;4055](https://redirect.github.com/evanw/esbuild/issues/4055))

    Direct `eval` can be used to introduce a new variable like this:

    ```js
    const variable = false
    ;(function () {
      eval("var variable = true")
      console.log(variable)
    })()
    ```

Previously esbuild inlined `variable` here (which became `false`), which
changed the behavior of the code. This inlining is now avoided, but
please keep in mind that direct `eval` breaks many assumptions that
JavaScript tools hold about normal code (especially when bundling) and I
do not recommend using it. There are usually better alternatives that
have a more localized impact on your code. You can read more about this
here: https://esbuild.github.io/link/direct-eval/

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "" (UTC), Automerge - At any time (no
schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/open-feature/js-sdk).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNjQuMSIsInVwZGF0ZWRJblZlciI6IjM5LjE2NC4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-11 10:21:28 +00:00
renovate[bot] 9218e987a0
chore(deps): update angular-eslint monorepo to v19 (major) (#1140)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[@angular-eslint/builder](https://redirect.github.com/angular-eslint/angular-eslint)
([source](https://redirect.github.com/angular-eslint/angular-eslint/tree/HEAD/packages/builder))
| [`18.4.3` ->
`19.3.0`](https://renovatebot.com/diffs/npm/@angular-eslint%2fbuilder/18.4.3/19.3.0)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@angular-eslint%2fbuilder/19.3.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@angular-eslint%2fbuilder/19.3.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@angular-eslint%2fbuilder/18.4.3/19.3.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@angular-eslint%2fbuilder/18.4.3/19.3.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
|
[@angular-eslint/eslint-plugin](https://redirect.github.com/angular-eslint/angular-eslint)
([source](https://redirect.github.com/angular-eslint/angular-eslint/tree/HEAD/packages/eslint-plugin))
| [`18.4.3` ->
`19.3.0`](https://renovatebot.com/diffs/npm/@angular-eslint%2feslint-plugin/18.4.3/19.3.0)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@angular-eslint%2feslint-plugin/19.3.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@angular-eslint%2feslint-plugin/19.3.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@angular-eslint%2feslint-plugin/18.4.3/19.3.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@angular-eslint%2feslint-plugin/18.4.3/19.3.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
|
[@angular-eslint/eslint-plugin-template](https://redirect.github.com/angular-eslint/angular-eslint)
([source](https://redirect.github.com/angular-eslint/angular-eslint/tree/HEAD/packages/eslint-plugin-template))
| [`18.4.3` ->
`19.3.0`](https://renovatebot.com/diffs/npm/@angular-eslint%2feslint-plugin-template/18.4.3/19.3.0)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@angular-eslint%2feslint-plugin-template/19.3.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@angular-eslint%2feslint-plugin-template/19.3.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@angular-eslint%2feslint-plugin-template/18.4.3/19.3.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@angular-eslint%2feslint-plugin-template/18.4.3/19.3.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
|
[@angular-eslint/schematics](https://redirect.github.com/angular-eslint/angular-eslint)
([source](https://redirect.github.com/angular-eslint/angular-eslint/tree/HEAD/packages/schematics))
| [`18.4.3` ->
`19.3.0`](https://renovatebot.com/diffs/npm/@angular-eslint%2fschematics/18.4.3/19.3.0)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@angular-eslint%2fschematics/19.3.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@angular-eslint%2fschematics/19.3.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@angular-eslint%2fschematics/18.4.3/19.3.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@angular-eslint%2fschematics/18.4.3/19.3.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
|
[@angular-eslint/template-parser](https://redirect.github.com/angular-eslint/angular-eslint)
([source](https://redirect.github.com/angular-eslint/angular-eslint/tree/HEAD/packages/template-parser))
| [`18.4.3` ->
`19.3.0`](https://renovatebot.com/diffs/npm/@angular-eslint%2ftemplate-parser/18.4.3/19.3.0)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@angular-eslint%2ftemplate-parser/19.3.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@angular-eslint%2ftemplate-parser/19.3.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@angular-eslint%2ftemplate-parser/18.4.3/19.3.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@angular-eslint%2ftemplate-parser/18.4.3/19.3.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>angular-eslint/angular-eslint
(@&#8203;angular-eslint/builder)</summary>

###
[`v19.3.0`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/builder/CHANGELOG.md#1930-2025-03-22)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v19.2.1...v19.3.0)

This was a version bump only for builder to align it with other
projects, there were no code changes.

###
[`v19.2.1`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/builder/CHANGELOG.md#1921-2025-03-08)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v19.2.0...v19.2.1)

This was a version bump only for builder to align it with other
projects, there were no code changes.

###
[`v19.2.0`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/builder/CHANGELOG.md#1920-2025-03-02)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v19.1.0...v19.2.0)

##### 🩹 Fixes

- **eslint-plugin-template:** find inline templates on components in
blocks
([#&#8203;2238](https://redirect.github.com/angular-eslint/angular-eslint/pull/2238))

##### ❤️ Thank You

-   Dave [@&#8203;reduckted](https://redirect.github.com/reduckted)

###
[`v19.1.0`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/builder/CHANGELOG.md#1910-2025-02-09)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v19.0.2...v19.1.0)

This was a version bump only for builder to align it with other
projects, there were no code changes.

###
[`v19.0.2`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/builder/CHANGELOG.md#1902-2024-12-10)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v19.0.1...v19.0.2)

This was a version bump only for builder to align it with other
projects, there were no code changes.

###
[`v19.0.1`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/builder/CHANGELOG.md#1901-2024-12-06)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v19.0.0...v19.0.1)

This was a version bump only for builder to align it with other
projects, there were no code changes.

###
[`v19.0.0`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/builder/CHANGELOG.md#1900-2024-11-29)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v18.4.3...v19.0.0)

##### 🚀 Features

- update angular packages to the stable v19
([#&#8203;2120](https://redirect.github.com/angular-eslint/angular-eslint/pull/2120))

##### ❤️ Thank You

- Leosvel Pérez Espinosa
[@&#8203;leosvelperez](https://redirect.github.com/leosvelperez)

#### 18.4.3 (2024-11-29)

##### 🩹 Fixes

- yarn pnp issues
([#&#8203;2143](https://redirect.github.com/angular-eslint/angular-eslint/pull/2143))

##### ❤️ Thank You

- James Henry
[@&#8203;JamesHenry](https://redirect.github.com/JamesHenry)

#### 18.4.2 (2024-11-23)

This was a version bump only for builder to align it with other
projects, there were no code changes.

#### 18.4.1 (2024-11-18)

This was a version bump only for builder to align it with other
projects, there were no code changes.

#### 18.4.0 (2024-10-21)

##### 🚀 Features

- support ESM configs and .cjs and .mjs extensions
([#&#8203;2068](https://redirect.github.com/angular-eslint/angular-eslint/pull/2068))

##### 🩹 Fixes

- update dependency eslint to v9.13.0, support noConfigLookup
([#&#8203;2045](https://redirect.github.com/angular-eslint/angular-eslint/pull/2045))

##### ❤️ Thank You

- James Henry
[@&#8203;JamesHenry](https://redirect.github.com/JamesHenry)

#### 18.3.1 (2024-09-11)

This was a version bump only for builder to align it with other
projects, there were no code changes.

#### 18.3.0 (2024-08-13)

##### 🩹 Fixes

-   ensure consistent nx dependency versions

##### ❤️ Thank You

-   James Henry

#### 18.2.0 (2024-07-31)

This was a version bump only for builder to align it with other
projects, there were no code changes.

#### 18.1.0 (2024-07-01)

This was a version bump only for builder to align it with other
projects, there were no code changes.

#### 18.0.1 (2024-05-30)

##### 🩹 Fixes

- move typescript-eslint packages to peerDeps, consistently allow v7 and
v8

##### ❤️ Thank You

-   James Henry

</details>

<details>
<summary>angular-eslint/angular-eslint
(@&#8203;angular-eslint/eslint-plugin)</summary>

###
[`v19.3.0`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#1930-2025-03-22)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v19.2.1...v19.3.0)

This was a version bump only for eslint-plugin to align it with other
projects, there were no code changes.

###
[`v19.2.1`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#1921-2025-03-08)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v19.2.0...v19.2.1)

This was a version bump only for eslint-plugin to align it with other
projects, there were no code changes.

###
[`v19.2.0`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#1920-2025-03-02)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v19.1.0...v19.2.0)

##### 🚀 Features

- **eslint-plugin:** add rule require-lifecycle-on-prototype
([#&#8203;2259](https://redirect.github.com/angular-eslint/angular-eslint/pull/2259))

##### 🩹 Fixes

- **eslint-plugin-template:** find inline templates on components in
blocks
([#&#8203;2238](https://redirect.github.com/angular-eslint/angular-eslint/pull/2238))

##### ❤️ Thank You

-   Dave [@&#8203;reduckted](https://redirect.github.com/reduckted)

###
[`v19.1.0`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#1910-2025-02-09)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v19.0.2...v19.1.0)

##### 🚀 Features

- **eslint-plugin:** prefer-signals now checks .asReadonly() calls
([#&#8203;2218](https://redirect.github.com/angular-eslint/angular-eslint/pull/2218))
- **eslint-plugin:** prefer-signals read-only suggestion is now a fix
([#&#8203;2175](https://redirect.github.com/angular-eslint/angular-eslint/pull/2175))

##### 🩹 Fixes

- **eslint-plugin:** \[no-input-prefix] false positive on input
initializer value
([#&#8203;2184](https://redirect.github.com/angular-eslint/angular-eslint/pull/2184))
- **eslint-plugin:** \[prefer-signals] support linkedSignal
([#&#8203;2213](https://redirect.github.com/angular-eslint/angular-eslint/pull/2213))

##### ❤️ Thank You

- Cédric Exbrayat
[@&#8203;cexbrayat](https://redirect.github.com/cexbrayat)
-   Dave [@&#8203;reduckted](https://redirect.github.com/reduckted)
-   Lucas Neto Moreira

###
[`v19.0.2`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#1902-2024-12-10)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v19.0.1...v19.0.2)

##### 🩹 Fixes

- **eslint-plugin:** \[prefer-standalone] error range should only
include property and value
([#&#8203;2172](https://redirect.github.com/angular-eslint/angular-eslint/pull/2172))

##### ❤️ Thank You

- James Henry
[@&#8203;JamesHenry](https://redirect.github.com/JamesHenry)

###
[`v19.0.1`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#1901-2024-12-06)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v19.0.0...v19.0.1)

##### 🩹 Fixes

- **eslint-plugin:** adding prefer-signals rule to exported config
([#&#8203;2150](https://redirect.github.com/angular-eslint/angular-eslint/pull/2150))

##### ❤️ Thank You

- Quentin Deroubaix
[@&#8203;quentinderoubaix](https://redirect.github.com/quentinderoubaix)

###
[`v19.0.0`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#1900-2024-11-29)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v18.4.3...v19.0.0)

##### 🚀 Features

- ⚠️ **eslint-plugin:** promote prefer-standalone to recommended
([8dfdc4f4](https://redirect.github.com/angular-eslint/angular-eslint/commit/8dfdc4f4))
- **eslint-plugin:** new rule prefer-signals
([#&#8203;1872](https://redirect.github.com/angular-eslint/angular-eslint/pull/1872))
- ⚠️ **eslint-plugin:** remove deprecated no-host-metadata-property rule
([#&#8203;2113](https://redirect.github.com/angular-eslint/angular-eslint/pull/2113))
- ⚠️ **eslint-plugin:** remove deprecated sort-ngmodule-metadata-arrays
rule
([#&#8203;2114](https://redirect.github.com/angular-eslint/angular-eslint/pull/2114))
- ⚠️ **eslint-plugin:** prefer-standalone recognizes that standalone is
the default
([#&#8203;2096](https://redirect.github.com/angular-eslint/angular-eslint/pull/2096))
- ⚠️ **eslint-plugin:** remove deprecated prefer-standalone-component
rule
([#&#8203;2112](https://redirect.github.com/angular-eslint/angular-eslint/pull/2112))

##### ⚠️ Breaking Changes

- ⚠️ **eslint-plugin:** promote prefer-standalone to recommended
([8dfdc4f4](https://redirect.github.com/angular-eslint/angular-eslint/commit/8dfdc4f4))
- ⚠️ **eslint-plugin:** remove deprecated no-host-metadata-property rule
([#&#8203;2113](https://redirect.github.com/angular-eslint/angular-eslint/pull/2113))
- ⚠️ **eslint-plugin:** remove deprecated sort-ngmodule-metadata-arrays
rule
([#&#8203;2114](https://redirect.github.com/angular-eslint/angular-eslint/pull/2114))
- ⚠️ **eslint-plugin:** prefer-standalone recognizes that standalone is
the default
([#&#8203;2096](https://redirect.github.com/angular-eslint/angular-eslint/pull/2096))
- ⚠️ **eslint-plugin:** remove deprecated prefer-standalone-component
rule
([#&#8203;2112](https://redirect.github.com/angular-eslint/angular-eslint/pull/2112))

##### ❤️ Thank You

- Daniel Kimmich
[@&#8203;json-derulo](https://redirect.github.com/json-derulo)
-   Dave [@&#8203;reduckted](https://redirect.github.com/reduckted)
- James Henry
[@&#8203;JamesHenry](https://redirect.github.com/JamesHenry)
- JamesHenry
[@&#8203;JamesHenry](https://redirect.github.com/JamesHenry)

#### 18.4.3 (2024-11-29)

This was a version bump only for eslint-plugin to align it with other
projects, there were no code changes.

#### 18.4.2 (2024-11-23)

##### 🩹 Fixes

- **eslint-plugin:** fix placement of lifecycle interface for subclasses
([#&#8203;1965](https://redirect.github.com/angular-eslint/angular-eslint/pull/1965))
- **eslint-plugin:** handle `output()` and `input()` functions in
various rules
([#&#8203;2098](https://redirect.github.com/angular-eslint/angular-eslint/pull/2098))

##### ❤️ Thank You

-   Aleksandr Martirosyan
-   Dave [@&#8203;reduckted](https://redirect.github.com/reduckted)

#### 18.4.1 (2024-11-18)

This was a version bump only for eslint-plugin to align it with other
projects, there were no code changes.

#### 18.4.0 (2024-10-21)

This was a version bump only for eslint-plugin to align it with other
projects, there were no code changes.

#### 18.3.1 (2024-09-11)

This was a version bump only for eslint-plugin to align it with other
projects, there were no code changes.

#### 18.3.0 (2024-08-13)

##### 🚀 Features

-   **eslint-plugin:** new rule runtime-localize

##### ❤️ Thank You

-   m-akinc

#### 18.2.0 (2024-07-31)

##### 🚀 Features

-   update typescript-eslint to v8 stable, eslint v9.8.0

##### 🩹 Fixes

- **eslint-plugin:** \[prefer-standalone] ignore empty Directive
decorators

##### ❤️ Thank You

-   James Henry
-   Paweł Maniecki

#### 18.1.0 (2024-07-01)

##### 🚀 Features

- **eslint-plugin:** \[prefer-output-readonly] support output() function

##### 🩹 Fixes

-   update typescript-eslint packages to v8.0.0-alpha.37

##### ❤️ Thank You

-   Christian Svensson
-   Daniel Kimmich
-   Dave
-   Martijn van der Meij
-   Maximilian Main

#### 18.0.1 (2024-05-30)

##### 🩹 Fixes

- move typescript-eslint packages to peerDeps, consistently allow v7 and
v8

##### ❤️ Thank You

-   James Henry

</details>

<details>
<summary>angular-eslint/angular-eslint
(@&#8203;angular-eslint/eslint-plugin-template)</summary>

###
[`v19.3.0`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/eslint-plugin-template/CHANGELOG.md#1930-2025-03-22)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v19.2.1...v19.3.0)

##### 🚀 Features

- use
[@&#8203;angular/compiler](https://redirect.github.com/angular/compiler)
19.2.3 and rename some AST nodes to match
([#&#8203;2320](https://redirect.github.com/angular-eslint/angular-eslint/pull/2320))
- **eslint-plugin-template:** add rule prefer-contextual-for-variables
([#&#8203;2311](https://redirect.github.com/angular-eslint/angular-eslint/pull/2311))
- **eslint-plugin-template:** \[button-has-type] add option to ignore
missing type
([#&#8203;2326](https://redirect.github.com/angular-eslint/angular-eslint/pull/2326))

##### 🩹 Fixes

- **eslint-plugin-template:** \[attributes-order] treat inputs without
square brackets as attributes
([#&#8203;2316](https://redirect.github.com/angular-eslint/angular-eslint/pull/2316))
- **eslint-plugin-template:** \[attributes-order] order i18n attributes
([#&#8203;2307](https://redirect.github.com/angular-eslint/angular-eslint/pull/2307))
- **eslint-plugin-template:** \[i18n] Avoid exception in i18n rule with
allowMarkupInContent=false
([#&#8203;2327](https://redirect.github.com/angular-eslint/angular-eslint/pull/2327))

##### ❤️ Thank You

-   Dave [@&#8203;reduckted](https://redirect.github.com/reduckted)
-   m-akinc [@&#8203;m-akinc](https://redirect.github.com/m-akinc)

###
[`v19.2.1`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/eslint-plugin-template/CHANGELOG.md#1921-2025-03-08)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v19.2.0...v19.2.1)

##### 🩹 Fixes

- **eslint-plugin-template:** \[prefer-self-closing-tags] resolve wrong
reports when structural directive + no content + no self-closing
([#&#8203;2287](https://redirect.github.com/angular-eslint/angular-eslint/pull/2287))

##### ❤️ Thank You

-   Guillaume DROUARD

###
[`v19.2.0`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/eslint-plugin-template/CHANGELOG.md#1920-2025-03-02)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v19.1.0...v19.2.0)

##### 🩹 Fixes

- **prefer-static-string-properties:** exclude special attributes
([#&#8203;2273](https://redirect.github.com/angular-eslint/angular-eslint/pull/2273))
- **prefer-static-string-properties:** resolve bug with directives
([#&#8203;2271](https://redirect.github.com/angular-eslint/angular-eslint/pull/2271))
- **eslint-plugin-template:** find inline templates on components in
blocks
([#&#8203;2238](https://redirect.github.com/angular-eslint/angular-eslint/pull/2238))
- **eslint-plugin-template:** \[prefer-static-string-properties] do not
check structural directives
([#&#8203;2253](https://redirect.github.com/angular-eslint/angular-eslint/pull/2253))
- **eslint-plugin-template:** \[prefer-self-closing-tags] allow nested
ng-content
([#&#8203;2257](https://redirect.github.com/angular-eslint/angular-eslint/pull/2257))
- **eslint-plugin-template:** \[prefer-self-closing-tags] do not treat
comments as whitespace
([#&#8203;2256](https://redirect.github.com/angular-eslint/angular-eslint/pull/2256))

##### ❤️ Thank You

-   Dave [@&#8203;reduckted](https://redirect.github.com/reduckted)
- Marie Briand
[@&#8203;mbriand-lucca](https://redirect.github.com/mbriand-lucca)

###
[`v19.1.0`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/eslint-plugin-template/CHANGELOG.md#1910-2025-02-09)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v19.0.2...v19.1.0)

##### 🚀 Features

- **eslint-plugin-template:** add rule prefer-static-string-properties
([#&#8203;2228](https://redirect.github.com/angular-eslint/angular-eslint/pull/2228))

##### 🩹 Fixes

- **eslint-plugin-template:** \[attribute-order] check for ng-template
within svg
([#&#8203;2223](https://redirect.github.com/angular-eslint/angular-eslint/pull/2223))
- **eslint-plugin-template:** \[prefer-self-closing-tags] do not remove
HTML-encoded whitespace
([#&#8203;2229](https://redirect.github.com/angular-eslint/angular-eslint/pull/2229))

##### ❤️ Thank You

-   Dave [@&#8203;reduckted](https://redirect.github.com/reduckted)

###
[`v19.0.2`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/eslint-plugin-template/CHANGELOG.md#1902-2024-12-10)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v19.0.1...v19.0.2)

This was a version bump only for eslint-plugin-template to align it with
other projects, there were no code changes.

###
[`v19.0.1`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/eslint-plugin-template/CHANGELOG.md#1901-2024-12-06)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v19.0.0...v19.0.1)

##### 🩹 Fixes

- **eslint-plugin-template:** prevent the slot tag from being
self-closing
([#&#8203;2088](https://redirect.github.com/angular-eslint/angular-eslint/pull/2088))

##### ❤️ Thank You

- Joan Llenas
[@&#8203;joanllenas](https://redirect.github.com/joanllenas)

###
[`v19.0.0`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/eslint-plugin-template/CHANGELOG.md#1900-2024-11-29)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v18.4.3...v19.0.0)

This was a version bump only for eslint-plugin-template to align it with
other projects, there were no code changes.

#### 18.4.3 (2024-11-29)

This was a version bump only for eslint-plugin-template to align it with
other projects, there were no code changes.

#### 18.4.2 (2024-11-23)

This was a version bump only for eslint-plugin-template to align it with
other projects, there were no code changes.

#### 18.4.1 (2024-11-18)

This was a version bump only for eslint-plugin-template to align it with
other projects, there were no code changes.

#### 18.4.0 (2024-10-21)

##### 🩹 Fixes

- update typescript-eslint packages to v8.10.0
([#&#8203;2046](https://redirect.github.com/angular-eslint/angular-eslint/pull/2046))
- update dependency aria-query to v5.3.2
([#&#8203;2053](https://redirect.github.com/angular-eslint/angular-eslint/pull/2053))
- update dependency aria-query to v5.3.1
([#&#8203;2043](https://redirect.github.com/angular-eslint/angular-eslint/pull/2043))

#### 18.3.1 (2024-09-11)

##### 🩹 Fixes

-   **template-parser:** visit receiver of Call expression

-   **template-parser:** visit receiver of Call expression"

-   **template-parser:** visit receiver of Call expression

##### ❤️ Thank You

-   James Henry
-   Paweł Maniecki

#### 18.3.0 (2024-08-13)

##### 🩹 Fixes

- **eslint-plugin-template:** \[interactive-supports-focus] allowList
with form as default option to support event bubbling

- **eslint-plugin-template:** \[prefer-self-closing-tags] fix ng-content
with rich default content

-   **prefer-self-closing-tags:** handle both forward and backward slash

##### ❤️ Thank You

-   Daniel Kimmich
-   Sandi Barr
-   Simon

#### 18.2.0 (2024-07-31)

##### 🚀 Features

-   update typescript-eslint to v8 stable, eslint v9.8.0

##### 🩹 Fixes

-   update dependency axobject-query to v4.1.0

- **eslint-plugin-template:** add meta to preprocessor to resolve eslint
cache error

##### ❤️ Thank You

-   James Henry
-   kwiateusz

#### 18.1.0 (2024-07-01)

##### 🚀 Features

- **eslint-plugin:** \[no-call-expression] add allowPrefix and
allowSuffix

##### 🩹 Fixes

-   update typescript-eslint packages to v8.0.0-alpha.37

- **eslint-plugin-template:** \[prefer-self-closing-tags] always ignore
index.html files

- **eslint-plugin-template:** \[prefer-self-closing-tags] support
ng-content with fallback content

##### ❤️ Thank You

-   Christian Svensson
-   Daniel Kimmich
-   Dave
-   Martijn van der Meij
-   Maximilian Main

#### 18.0.1 (2024-05-30)

##### 🩹 Fixes

- move typescript-eslint packages to peerDeps, consistently allow v7 and
v8

##### ❤️ Thank You

-   James Henry

</details>

<details>
<summary>angular-eslint/angular-eslint
(@&#8203;angular-eslint/schematics)</summary>

###
[`v19.3.0`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/schematics/CHANGELOG.md#1930-2025-03-22)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v19.2.1...v19.3.0)

##### 🩹 Fixes

- update dependency eslint to v9.23.0
([#&#8203;2331](https://redirect.github.com/angular-eslint/angular-eslint/pull/2331))
- update typescript-eslint packages to v8.27.0
([#&#8203;2328](https://redirect.github.com/angular-eslint/angular-eslint/pull/2328))
- update typescript-eslint packages to v8.26.1
([#&#8203;2313](https://redirect.github.com/angular-eslint/angular-eslint/pull/2313))

###
[`v19.2.1`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/schematics/CHANGELOG.md#1921-2025-03-08)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v19.2.0...v19.2.1)

##### 🩹 Fixes

- update dependency eslint to v9.22.0
([#&#8203;2294](https://redirect.github.com/angular-eslint/angular-eslint/pull/2294))
- update typescript-eslint packages to v8.26.0
([#&#8203;2282](https://redirect.github.com/angular-eslint/angular-eslint/pull/2282))

###
[`v19.2.0`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/schematics/CHANGELOG.md#1920-2025-03-02)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v19.1.0...v19.2.0)

##### 🩹 Fixes

- update typescript-eslint packages to v8.25.0
([#&#8203;2263](https://redirect.github.com/angular-eslint/angular-eslint/pull/2263))
- update dependency eslint to v9.21.0
([#&#8203;2243](https://redirect.github.com/angular-eslint/angular-eslint/pull/2243))
- **eslint-plugin-template:** find inline templates on components in
blocks
([#&#8203;2238](https://redirect.github.com/angular-eslint/angular-eslint/pull/2238))
- update typescript-eslint packages to v8.24.0
([#&#8203;2240](https://redirect.github.com/angular-eslint/angular-eslint/pull/2240))

##### ❤️ Thank You

-   Dave [@&#8203;reduckted](https://redirect.github.com/reduckted)

###
[`v19.1.0`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/schematics/CHANGELOG.md#1910-2025-02-09)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v19.0.2...v19.1.0)

##### 🩹 Fixes

- update dependency eslint to v9.20.0
([#&#8203;2217](https://redirect.github.com/angular-eslint/angular-eslint/pull/2217))
- update typescript-eslint packages to v8.23.0
([#&#8203;2212](https://redirect.github.com/angular-eslint/angular-eslint/pull/2212))
- update dependency semver to v7.7.1
([#&#8203;2225](https://redirect.github.com/angular-eslint/angular-eslint/pull/2225))
- update typescript-eslint packages to v8.20.0
([#&#8203;2185](https://redirect.github.com/angular-eslint/angular-eslint/pull/2185))
- update dependency eslint to v9.18.0
([#&#8203;2181](https://redirect.github.com/angular-eslint/angular-eslint/pull/2181))
- update dependency ignore to v7
([#&#8203;2200](https://redirect.github.com/angular-eslint/angular-eslint/pull/2200))

###
[`v19.0.2`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/schematics/CHANGELOG.md#1902-2024-12-10)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v19.0.1...v19.0.2)

##### 🩹 Fixes

- update typescript-eslint packages to v8.18.0
([#&#8203;2171](https://redirect.github.com/angular-eslint/angular-eslint/pull/2171))

###
[`v19.0.1`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/schematics/CHANGELOG.md#1901-2024-12-06)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v19.0.0...v19.0.1)

##### 🩹 Fixes

- update typescript-eslint packages to v8.17.0
([#&#8203;2153](https://redirect.github.com/angular-eslint/angular-eslint/pull/2153))
- update dependency eslint to v9.16.0
([#&#8203;2148](https://redirect.github.com/angular-eslint/angular-eslint/pull/2148))

###
[`v19.0.0`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/schematics/CHANGELOG.md#1900-2024-11-29)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v18.4.3...v19.0.0)

##### 🚀 Features

- allow referencing angular-eslint as the schematics collection
([2be3107b](https://redirect.github.com/angular-eslint/angular-eslint/commit/2be3107b))
- update angular packages to the stable v19
([#&#8203;2120](https://redirect.github.com/angular-eslint/angular-eslint/pull/2120))

##### ❤️ Thank You

- JamesHenry
[@&#8203;JamesHenry](https://redirect.github.com/JamesHenry)
- Leosvel Pérez Espinosa
[@&#8203;leosvelperez](https://redirect.github.com/leosvelperez)

#### 18.4.3 (2024-11-29)

##### 🩹 Fixes

- update typescript-eslint packages to v8.16.0
([#&#8203;2135](https://redirect.github.com/angular-eslint/angular-eslint/pull/2135))
- yarn pnp issues
([#&#8203;2143](https://redirect.github.com/angular-eslint/angular-eslint/pull/2143))

##### ❤️ Thank You

- James Henry
[@&#8203;JamesHenry](https://redirect.github.com/JamesHenry)

#### 18.4.2 (2024-11-23)

This was a version bump only for schematics to align it with other
projects, there were no code changes.

#### 18.4.1 (2024-11-18)

##### 🩹 Fixes

- update dependency ignore to v6
([#&#8203;2047](https://redirect.github.com/angular-eslint/angular-eslint/pull/2047))

#### 18.4.0 (2024-10-21)

##### 🚀 Features

- support ESM configs and .cjs and .mjs extensions
([#&#8203;2068](https://redirect.github.com/angular-eslint/angular-eslint/pull/2068))

##### 🩹 Fixes

- update dependency eslint to v9.13.0, support noConfigLookup
([#&#8203;2045](https://redirect.github.com/angular-eslint/angular-eslint/pull/2045))
- update typescript-eslint packages to v8.10.0
([#&#8203;2046](https://redirect.github.com/angular-eslint/angular-eslint/pull/2046))
- update typescript-eslint packages to v8.5.0
([#&#8203;2020](https://redirect.github.com/angular-eslint/angular-eslint/pull/2020))

##### ❤️ Thank You

- James Henry
[@&#8203;JamesHenry](https://redirect.github.com/JamesHenry)

#### 18.3.1 (2024-09-11)

##### 🩹 Fixes

-   update dependency eslint to v9.9.1

-   update typescript-eslint packages to v8.2.0

#### 18.3.0 (2024-08-13)

##### 🩹 Fixes

-   ensure consistent nx dependency versions

-   update dependency eslint to v9.9.0

-   update dependency ignore to v5.3.2

-   update typescript-eslint packages to v8.0.1

-   update typescript-eslint packages to v8.1.0

##### ❤️ Thank You

-   James Henry

#### 18.2.0 (2024-07-31)

##### 🚀 Features

-   update typescript-eslint to v8 stable, eslint v9.8.0

##### 🩹 Fixes

-   update dependency semver to v7.6.3

##### ❤️ Thank You

-   James Henry

#### 18.1.0 (2024-07-01)

##### 🩹 Fixes

-   update dependency eslint to v9.4.0

-   update dependency eslint to v9.5.0

-   update dependency eslint to v9.6.0

-   update typescript-eslint packages to v8.0.0-alpha.37

-   update typescript-eslint packages to v8.0.0-alpha.38

##### ❤️ Thank You

-   Christian Svensson
-   Daniel Kimmich
-   Dave
-   Martijn van der Meij
-   Maximilian Main

#### 18.0.1 (2024-05-30)

This was a version bump only for schematics to align it with other
projects, there were no code changes.

</details>

<details>
<summary>angular-eslint/angular-eslint
(@&#8203;angular-eslint/template-parser)</summary>

###
[`v19.3.0`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/template-parser/CHANGELOG.md#1930-2025-03-22)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v19.2.1...v19.3.0)

##### 🚀 Features

- use
[@&#8203;angular/compiler](https://redirect.github.com/angular/compiler)
19.2.3 and rename some AST nodes to match
([#&#8203;2320](https://redirect.github.com/angular-eslint/angular-eslint/pull/2320))
- **template-parser:** visit
[@&#8203;let](https://redirect.github.com/let) child nodes
([#&#8203;2312](https://redirect.github.com/angular-eslint/angular-eslint/pull/2312))

##### ❤️ Thank You

-   Dave [@&#8203;reduckted](https://redirect.github.com/reduckted)

###
[`v19.2.1`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/template-parser/CHANGELOG.md#1921-2025-03-08)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v19.2.0...v19.2.1)

This was a version bump only for template-parser to align it with other
projects, there were no code changes.

###
[`v19.2.0`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/template-parser/CHANGELOG.md#1920-2025-03-02)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v19.1.0...v19.2.0)

##### 🩹 Fixes

- **eslint-plugin-template:** find inline templates on components in
blocks
([#&#8203;2238](https://redirect.github.com/angular-eslint/angular-eslint/pull/2238))

##### ❤️ Thank You

-   Dave [@&#8203;reduckted](https://redirect.github.com/reduckted)

###
[`v19.1.0`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/template-parser/CHANGELOG.md#1910-2025-02-09)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v19.0.2...v19.1.0)

This was a version bump only for template-parser to align it with other
projects, there were no code changes.

###
[`v19.0.2`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/template-parser/CHANGELOG.md#1902-2024-12-10)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v19.0.1...v19.0.2)

This was a version bump only for template-parser to align it with other
projects, there were no code changes.

###
[`v19.0.1`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/template-parser/CHANGELOG.md#1901-2024-12-06)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v19.0.0...v19.0.1)

This was a version bump only for template-parser to align it with other
projects, there were no code changes.

###
[`v19.0.0`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/template-parser/CHANGELOG.md#1900-2024-11-29)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v18.4.3...v19.0.0)

This was a version bump only for template-parser to align it with other
projects, there were no code changes.

#### 18.4.3 (2024-11-29)

This was a version bump only for template-parser to align it with other
projects, there were no code changes.

#### 18.4.2 (2024-11-23)

This was a version bump only for template-parser to align it with other
projects, there were no code changes.

#### 18.4.1 (2024-11-18)

This was a version bump only for template-parser to align it with other
projects, there were no code changes.

#### 18.4.0 (2024-10-21)

##### 🩹 Fixes

- **template-parser:** traverse ng-content fallback content
([#&#8203;2031](https://redirect.github.com/angular-eslint/angular-eslint/pull/2031))

##### ❤️ Thank You

- Matt Lewis
[@&#8203;mattlewis92](https://redirect.github.com/mattlewis92)

#### 18.3.1 (2024-09-11)

##### 🩹 Fixes

-   **template-parser:** visit receiver of Call expression

-   **template-parser:** visit receiver of Call expression"

-   **template-parser:** visit receiver of Call expression

##### ❤️ Thank You

-   James Henry
-   Paweł Maniecki

#### 18.3.0 (2024-08-13)

This was a version bump only for template-parser to align it with other
projects, there were no code changes.

#### 18.2.0 (2024-07-31)

##### 🚀 Features

-   update typescript-eslint to v8 stable, eslint v9.8.0

##### ❤️ Thank You

-   James Henry

#### 18.1.0 (2024-07-01)

This was a version bump only for template-parser to align it with other
projects, there were no code changes.

#### 18.0.1 (2024-05-30)

This was a version bump only for template-parser to align it with other
projects, there were no code changes.

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about these
updates again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/open-feature/js-sdk).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNDUuMCIsInVwZGF0ZWRJblZlciI6IjM5LjIwNy4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-11 12:20:57 +02:00
OpenFeature Bot 7f81917226
chore(main): release angular-sdk 0.0.11 (#1167)
🤖 I have created a release *beep* *boop*
---


##
[0.0.11](https://github.com/open-feature/js-sdk/compare/angular-sdk-v0.0.10...angular-sdk-v0.0.11)
(2025-04-11)


###  New Features

* **angular:** add option for initial context injection
([aafdb43](aafdb4382f))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

---------

Signed-off-by: OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>
Signed-off-by: Lukas Reining <lukas.reining@codecentric.de>
Co-authored-by: Lukas Reining <lukas.reining@codecentric.de>
2025-04-11 12:08:35 +02:00
Lukas Reining aafdb4382f feat(angular): add option for initial context injection
Signed-off-by: Lukas Reining <lukas.reining@codecentric.de>
2025-04-11 12:02:02 +02:00
OpenFeature Bot b60c3df372
chore(main): release core 1.8.0 (#1155)
🤖 I have created a release *beep* *boop*
---


##
[1.8.0](https://github.com/open-feature/js-sdk/compare/core-v1.7.2...core-v1.8.0)
(2025-04-10)


###  New Features

* add support for abort controllers to event handlers
([#1151](https://github.com/open-feature/js-sdk/issues/1151))
([6a22483](6a224830fa))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Signed-off-by: OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>
2025-04-10 13:52:28 +00:00
Todd Baert 5b19eb035a
chore: use server src not dist in nest tests (#1166)
Fixes issue where nest test suite was running using dist not source of
server sdk.

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
2025-04-10 14:39:39 +02:00
Michael Beemer 5afe61f9e3
feat: add polyfill for react use hook (#1157)
## This PR

- adds an internal `use` polyfill
- refactors suspense support to maintain state across rerenders

### Notes

Previously, the Next.JS build process would timeout when using a
suspense flag hook. The reason for this is because the noop provider
(which is used during a build) is never ready. That meant that the
promise thrown to initiate suspense never resolved. To address this,
I've added global state using a weak map that's keyed off a provider. A
`useRef` won't help because the value is only retained if the component
renders successfully.

> [!NOTE]
> This unblocks suspense in our demo app but does not mean NextJS is
officially support (yet).

### How to test

I've added some tests and manually tested in the Toggle Shop.

---------

Signed-off-by: Michael Beemer <beeme1mr@users.noreply.github.com>
Co-authored-by: Todd Baert <todd.baert@dynatrace.com>
2025-04-10 12:06:19 +00:00
Todd Baert 60401b6cec
chore: prompt release of react v1 (#1162)
This proposes prompting the release of `@openfeature/react-sdk` 1.0.0.

My reasoning:

- as far as I know, there's no breaking changes on the horizon
- this is being used in production by multiple orgs
- it only depends on other 1.0+ deps

Please let me know what you think, especially if you have objections.

⚠️ this will not release 1.0, but will mark the NEXT release of
the react SDK as 1.0

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
2025-04-07 06:46:59 +00:00
Simon Schrottner 4482c2b33a
chore: add global maintainers to codeowners (#1163)
Global maintainers approval should also work as a codeowner approval

Signed-off-by: Simon Schrottner <simon.schrottner@dynatrace.com>
2025-04-05 16:18:44 +00:00
Thomas Poignant 2c5b37c79d
fix: Typo in name of the function
Signed-off-by: Thomas Poignant <thomas.poignant@gofeatureflag.org>
2025-03-28 17:37:58 +01:00
Todd Baert cf89e7da24
chore: add nest to test script (#1160)
Somehow we forgot to add this module here.

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
2025-03-25 13:29:46 -04:00
Michael Beemer ae8fce8753
feat: add a top-level method for accessing providers (#1152)
## This PR

- add a top-level method for accessing providers

### Notes

While working on some improvements to the way Suspense works in the
React SDK, I ran into a few scenarios were having access to the provider
itself was important. I needed a way to confidently tell that a provider
was the noop provider since it has special properties like never being
in a ready state. There are a few ways could could achieve this but I
noticed that the Java SDK [already has
methods](https://github.com/open-feature/java-sdk/blob/main/src/main/java/dev/openfeature/sdk/OpenFeatureAPI.java#L279)
that expose the provider. It also allowed me to improve some of our
existing tests.

### How to test

Unit tests have been updated accordingly.

Signed-off-by: Michael Beemer <beeme1mr@users.noreply.github.com>
2025-03-06 20:50:06 +00:00
renovate[bot] eec21dda82
chore(deps): update dependency uuid to v11 (#1073)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [uuid](https://redirect.github.com/uuidjs/uuid) | [`^9.0.1` ->
`^11.0.0`](https://renovatebot.com/diffs/npm/uuid/9.0.1/11.1.0) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/uuid/11.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/uuid/11.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/uuid/9.0.1/11.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/uuid/9.0.1/11.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>uuidjs/uuid (uuid)</summary>

###
[`v11.1.0`](https://redirect.github.com/uuidjs/uuid/blob/HEAD/CHANGELOG.md#1110-2025-02-19)

[Compare
Source](https://redirect.github.com/uuidjs/uuid/compare/v11.0.5...v11.1.0)

##### Features

- update TS types to allow`Uint8Array` subtypes for `buffer` option
([#&#8203;865](https://redirect.github.com/uuidjs/uuid/issues/865))
([a5231e7](a5231e7e1b))

###
[`v11.0.5`](https://redirect.github.com/uuidjs/uuid/blob/HEAD/CHANGELOG.md#1105-2025-01-09)

[Compare
Source](https://redirect.github.com/uuidjs/uuid/compare/v11.0.4...v11.0.5)

##### Bug Fixes

- add TS unit test, pin to typescript@5.0.4
([#&#8203;860](https://redirect.github.com/uuidjs/uuid/issues/860))
([24ac2fd](24ac2fd067))

###
[`v11.0.4`](https://redirect.github.com/uuidjs/uuid/blob/HEAD/CHANGELOG.md#1104-2025-01-05)

[Compare
Source](https://redirect.github.com/uuidjs/uuid/compare/v11.0.3...v11.0.4)

##### Bug Fixes

- **docs:** insure -> ensure
([#&#8203;843](https://redirect.github.com/uuidjs/uuid/issues/843))
([d2a61e1](d2a61e154d))
- exclude tests from published package
([#&#8203;840](https://redirect.github.com/uuidjs/uuid/issues/840))
([f992ff4](f992ff4780))
- Test for invalid byte array sizes and ranges in `v1()`, `v4()`, and
`v7()`
([#&#8203;845](https://redirect.github.com/uuidjs/uuid/issues/845))
([e0ee900](e0ee90051e))

###
[`v11.0.3`](https://redirect.github.com/uuidjs/uuid/blob/HEAD/CHANGELOG.md#1103-2024-11-04)

[Compare
Source](https://redirect.github.com/uuidjs/uuid/compare/v11.0.2...v11.0.3)

##### Bug Fixes

- apply stricter typing to the v\* signatures
([#&#8203;831](https://redirect.github.com/uuidjs/uuid/issues/831))
([c2d3fed](c2d3fed22c))
- export internal uuid types
([#&#8203;833](https://redirect.github.com/uuidjs/uuid/issues/833))
([341edf4](341edf444c))
- remove sourcemaps
([#&#8203;827](https://redirect.github.com/uuidjs/uuid/issues/827))
([b93ea10](b93ea101af))
- revert "simplify type for v3 and v5"
([#&#8203;835](https://redirect.github.com/uuidjs/uuid/issues/835))
([e2dee69](e2dee691e9))

###
[`v11.0.2`](https://redirect.github.com/uuidjs/uuid/blob/HEAD/CHANGELOG.md#1102-2024-10-28)

[Compare
Source](https://redirect.github.com/uuidjs/uuid/compare/v11.0.1...v11.0.2)

##### Bug Fixes

- remove wrapper.mjs
([2a18871](2a18871f00))
- remove wrapper.mjs
([#&#8203;822](https://redirect.github.com/uuidjs/uuid/issues/822))
([6683ad3](6683ad38b0))

###
[`v11.0.1`](https://redirect.github.com/uuidjs/uuid/blob/HEAD/CHANGELOG.md#1101-2024-10-27)

[Compare
Source](https://redirect.github.com/uuidjs/uuid/compare/v11.0.0...v11.0.1)

##### Bug Fixes

- restore package.json#browser field
([#&#8203;817](https://redirect.github.com/uuidjs/uuid/issues/817))
([ae8f386](ae8f38657b))

###
[`v11.0.0`](https://redirect.github.com/uuidjs/uuid/blob/HEAD/CHANGELOG.md#1100-2024-10-27)

[Compare
Source](https://redirect.github.com/uuidjs/uuid/compare/v10.0.0...v11.0.0)

##### ⚠ BREAKING CHANGES

- refactor v1 internal state and options logic
([#&#8203;780](https://redirect.github.com/uuidjs/uuid/issues/780))
- refactor v7 internal state and options logic, fixes
[#&#8203;764](https://redirect.github.com/uuidjs/uuid/issues/764)
([#&#8203;779](https://redirect.github.com/uuidjs/uuid/issues/779))
- Port to TypeScript, closes
[#&#8203;762](https://redirect.github.com/uuidjs/uuid/issues/762)
([#&#8203;763](https://redirect.github.com/uuidjs/uuid/issues/763))
- update node support matrix (only support node 16-20)
([#&#8203;750](https://redirect.github.com/uuidjs/uuid/issues/750))
- This library always aims at supporting one EOLed LTS release which by
this time now is 12.x which has reached EOL 30 Apr 2022.
-   Remove the minified UMD build from the package.
- Drop support for browsers that don't correctly implement const/let and
default arguments, and no longer transpile the browser build to ES2015.
- Although in practice this is currently a noop since the resulting
build does not change, the build will no longer transpiles future
changes for Node.js 8.x targets, so semantically this is still a
breaking change.
- Deep requiring specific algorithms of this library like
require('uuid/v4'), which has been deprecated in uuid@7, is no longer
supported.
- The default export, which used to be the v4() method but which was
already discouraged in v3.x of this library, has been removed.
- Explicitly note that deep imports of the different uuid version
functions are deprecated and no longer encouraged and that ECMAScript
module named imports should be used instead. Emit a deprecation warning
for people who deep-require the different algorithm variants.
- Remove builtin support for insecure random number generators in the
browser. Users who want that will have to supply their own random number
generator function.
-   Remove support for generating v3 and v5 UUIDs in Node.js<4.x
- Convert code base to ECMAScript Modules (ESM) and release CommonJS
build for node and ESM build for browser bundlers.

##### Features

- add parse/stringify/validate/version/NIL APIs
([#&#8203;479](https://redirect.github.com/uuidjs/uuid/issues/479))
([0e6c10b](0e6c10ba1b))
- add support for MAX uuid (new in RFC9562)
([#&#8203;714](https://redirect.github.com/uuidjs/uuid/issues/714))
([0385cd3](0385cd3f18))
- add UMD build to npm package
([#&#8203;357](https://redirect.github.com/uuidjs/uuid/issues/357))
([4e75adf](4e75adf435))
- add various es module and CommonJS examples
([b238510](b238510bf3))
- enforce Conventional Commit style commit messages
([#&#8203;282](https://redirect.github.com/uuidjs/uuid/issues/282))
([0705cd5](0705cd5bae))
- ensure that docs are up-to-date in CI
([ee5e77d](ee5e77db54))
- hybrid CommonJS & ECMAScript modules build
([a3f078f](a3f078faa0))
- improve performance of v1 string representation
([#&#8203;453](https://redirect.github.com/uuidjs/uuid/issues/453))
([0ee0b67](0ee0b67c37))
- improve v4 performance by reusing random number array
([#&#8203;435](https://redirect.github.com/uuidjs/uuid/issues/435))
([bf4af0d](bf4af0d711))
- optimize uuid.v1 by 1.3x uuid.v4 by 4.3x (430%)
([#&#8203;597](https://redirect.github.com/uuidjs/uuid/issues/597))
([3a033f6](3a033f6bab))
- optimize V8 performance of bytesToUuid
([#&#8203;434](https://redirect.github.com/uuidjs/uuid/issues/434))
([e156415](e156415448))
- Port to TypeScript, closes
[#&#8203;762](https://redirect.github.com/uuidjs/uuid/issues/762)
([#&#8203;763](https://redirect.github.com/uuidjs/uuid/issues/763))
([1e0f987](1e0f9870db))
- remove deep requires
([#&#8203;426](https://redirect.github.com/uuidjs/uuid/issues/426))
([daf72b8](daf72b84ce))
- remove deprecated v4 string parameter
([#&#8203;454](https://redirect.github.com/uuidjs/uuid/issues/454))
([88ce3ca](88ce3ca0ba))
- remove insecure fallback random number generator
([3a5842b](3a5842b141))
- remove support for pre Node.js v4 Buffer API
([#&#8203;356](https://redirect.github.com/uuidjs/uuid/issues/356))
([b59b5c5](b59b5c5eca))
- remove UMD build
([#&#8203;645](https://redirect.github.com/uuidjs/uuid/issues/645))
([e948a0f](e948a0f22b)),
closes [#&#8203;620](https://redirect.github.com/uuidjs/uuid/issues/620)
- rename repository to github:uuidjs/uuid
([#&#8203;351](https://redirect.github.com/uuidjs/uuid/issues/351))
([c37a518](c37a518e36)),
closes [#&#8203;338](https://redirect.github.com/uuidjs/uuid/issues/338)
- rename repository to github:uuidjs/uuid
([#&#8203;351](https://redirect.github.com/uuidjs/uuid/issues/351))
([e2d7314](e2d731463b)),
closes [#&#8203;338](https://redirect.github.com/uuidjs/uuid/issues/338)
- support v6 uuids
([#&#8203;754](https://redirect.github.com/uuidjs/uuid/issues/754))
([c4ed13e](c4ed13e715))
- update node support matrix (only support node 16-20)
([#&#8203;750](https://redirect.github.com/uuidjs/uuid/issues/750))
([883b163](883b163b9a))
- use native crypto.randomUUID when available
([#&#8203;600](https://redirect.github.com/uuidjs/uuid/issues/600))
([c9e076c](c9e076c852))
- v8 support
([#&#8203;759](https://redirect.github.com/uuidjs/uuid/issues/759))
([35a5342](35a5342820))

##### Bug Fixes

- 248
([#&#8203;251](https://redirect.github.com/uuidjs/uuid/issues/251))
([67d697c](67d697cd83))
- 30, \_rb not defined for lesser node.js versions
([8a6c03f](8a6c03f969))
- add CommonJS syntax example to README quickstart section
([#&#8203;417](https://redirect.github.com/uuidjs/uuid/issues/417))
([e0ec840](e0ec8402c7))
- add deep-require proxies for local testing and adjust tests
([#&#8203;365](https://redirect.github.com/uuidjs/uuid/issues/365))
([7fedc79](7fedc79ac8))
- add Jest/jsdom compatibility
([#&#8203;642](https://redirect.github.com/uuidjs/uuid/issues/642))
([16f9c46](16f9c469ed))
- add missing exports and tests for new APIs
([#&#8203;495](https://redirect.github.com/uuidjs/uuid/issues/495))
([681e1da](681e1dabfb))
- assignment to readonly property to allow running in strict mode
([#&#8203;270](https://redirect.github.com/uuidjs/uuid/issues/270))
([d062fdc](d062fdc14a))
- change default export to named function
([#&#8203;545](https://redirect.github.com/uuidjs/uuid/issues/545))
([c57bc5a](c57bc5a9a0))
- clean up esm builds for node and browser
([#&#8203;383](https://redirect.github.com/uuidjs/uuid/issues/383))
([59e6a49](59e6a49e7c))
- export package.json required by react-native and bundlers
([#&#8203;449](https://redirect.github.com/uuidjs/uuid/issues/449))
([be1c8fe](be1c8fe9a3)),
closes [#&#8203;444](https://redirect.github.com/uuidjs/uuid/issues/444)
- fix [#&#8203;229](https://redirect.github.com/uuidjs/uuid/issues/229)
([d9033cf](d9033cf358))
- fix [#&#8203;284](https://redirect.github.com/uuidjs/uuid/issues/284)
by setting function name in try-catch
([f2a60f2](f2a60f2fcd))
- Get correct version of IE11 crypto
([#&#8203;274](https://redirect.github.com/uuidjs/uuid/issues/274))
([205e0ed](205e0ed1f7))
- handle error when parameter is not set in v3 and v5
([#&#8203;622](https://redirect.github.com/uuidjs/uuid/issues/622))
([fcd7388](fcd7388169))
- lazy load getRandomValues
([#&#8203;537](https://redirect.github.com/uuidjs/uuid/issues/537))
([16c8f6d](16c8f6df2f)),
closes [#&#8203;536](https://redirect.github.com/uuidjs/uuid/issues/536)
- make access to msCrypto consistent
([#&#8203;393](https://redirect.github.com/uuidjs/uuid/issues/393))
([8bf2a20](8bf2a20f35))
- make deep require deprecation warning work in browsers
([#&#8203;409](https://redirect.github.com/uuidjs/uuid/issues/409))
([4b71107](4b71107d8c))
- mem issue when generating uuid
([#&#8203;267](https://redirect.github.com/uuidjs/uuid/issues/267))
([c47702c](c47702c291))
- missing v7 expectations in browser spec
([#&#8203;751](https://redirect.github.com/uuidjs/uuid/issues/751))
([f54a866](f54a866ced))
- prepare package exports for webpack 5
([#&#8203;468](https://redirect.github.com/uuidjs/uuid/issues/468))
([8d6e6a5](8d6e6a5f89))
- provide browser versions independent from module system
([#&#8203;380](https://redirect.github.com/uuidjs/uuid/issues/380))
([4344a22](4344a22e7a))
- refactor v1 internal state and options logic
([#&#8203;780](https://redirect.github.com/uuidjs/uuid/issues/780))
([031b3d3](031b3d3d73))
- refactor v7 internal state and options logic, fixes
[#&#8203;764](https://redirect.github.com/uuidjs/uuid/issues/764)
([#&#8203;779](https://redirect.github.com/uuidjs/uuid/issues/779))
([9dbd1cd](9dbd1cd417))
- remove v4 options default assignment preventing native.randomUUID from
being used
([#&#8203;786](https://redirect.github.com/uuidjs/uuid/issues/786))
([afe6232](afe62323c4))
- revert "perf: remove superfluous call to toLowerCase
([#&#8203;677](https://redirect.github.com/uuidjs/uuid/issues/677))"
([#&#8203;738](https://redirect.github.com/uuidjs/uuid/issues/738))
([e267b90](e267b9073d))
- run npm audit fix
([#&#8203;644](https://redirect.github.com/uuidjs/uuid/issues/644))
([04686f5](04686f54c5))
- seq_hi shift for byte 6
([#&#8203;775](https://redirect.github.com/uuidjs/uuid/issues/775))
([1d532ca](1d532ca374))
- simplify link in deprecation warning
([#&#8203;391](https://redirect.github.com/uuidjs/uuid/issues/391))
([bb2c8e4](bb2c8e4e9f))
- support expo>=39.0.0
([#&#8203;515](https://redirect.github.com/uuidjs/uuid/issues/515))
([c65a0f3](c65a0f3fa7)),
closes [#&#8203;375](https://redirect.github.com/uuidjs/uuid/issues/375)
- tsconfig module type
([#&#8203;778](https://redirect.github.com/uuidjs/uuid/issues/778))
([7eff835](7eff835cba))
- typo
([305d877](305d877790))
- update links to match content in readme
([#&#8203;386](https://redirect.github.com/uuidjs/uuid/issues/386))
([44f2f86](44f2f86e9d))
- upgrading from uuid3 broken link
([#&#8203;568](https://redirect.github.com/uuidjs/uuid/issues/568))
([1c849da](1c849da6e1))
- use msCrypto if available. Fixes
[#&#8203;241](https://redirect.github.com/uuidjs/uuid/issues/241)
([#&#8203;247](https://redirect.github.com/uuidjs/uuid/issues/247))
([1fef18b](1fef18baf2))

##### Performance Improvements

- **nodejs:** introduce pool into default rng
([#&#8203;513](https://redirect.github.com/uuidjs/uuid/issues/513))
([7f1af04](7f1af044be))
- remove superfluous call to toLowerCase
([#&#8203;677](https://redirect.github.com/uuidjs/uuid/issues/677))
([e53793f](e53793f5be))

##### Documentation

- add note about removal of default export
([#&#8203;372](https://redirect.github.com/uuidjs/uuid/issues/372))
([12749b7](12749b700e)),
closes [#&#8203;370](https://redirect.github.com/uuidjs/uuid/issues/370)
- deprecated deep requiring of the different algorithm versions
([#&#8203;361](https://redirect.github.com/uuidjs/uuid/issues/361))
([c0bdf15](c0bdf15e41))

##### Miscellaneous Chores

- drop node 10.x to upgrade dev dependencies
([#&#8203;653](https://redirect.github.com/uuidjs/uuid/issues/653))
([28a5712](28a571283f))
- release 11.0.0
([#&#8203;805](https://redirect.github.com/uuidjs/uuid/issues/805))
([b003cde](b003cdeda4))

##### Build System

- drop Node.js 8.x from babel transpile target
([#&#8203;603](https://redirect.github.com/uuidjs/uuid/issues/603))
([aa11485](aa11485826))
- drop support for legacy browsers (IE11, Safari 10)
([#&#8203;604](https://redirect.github.com/uuidjs/uuid/issues/604))
([0f433e5](0f433e5ec4))

###
[`v10.0.0`](https://redirect.github.com/uuidjs/uuid/blob/HEAD/CHANGELOG.md#1000-2024-06-07)

[Compare
Source](https://redirect.github.com/uuidjs/uuid/compare/v9.0.1...v10.0.0)

##### ⚠ BREAKING CHANGES

- update node support (drop node@12, node@14, add node@20)
([#&#8203;750](https://redirect.github.com/uuidjs/uuid/issues/750))

##### Features

- support support rfc9562 MAX uuid (new in RFC9562)
([#&#8203;714](https://redirect.github.com/uuidjs/uuid/issues/714))
([0385cd3](0385cd3f18))
- support rfc9562 v6 uuids
([#&#8203;754](https://redirect.github.com/uuidjs/uuid/issues/754))
([c4ed13e](c4ed13e715))
- support rfc9562 v7 uuids
([#&#8203;681](https://redirect.github.com/uuidjs/uuid/issues/681))
([db76a12](db76a12847))
- update node support matrix (only support node 16-20)
([#&#8203;750](https://redirect.github.com/uuidjs/uuid/issues/750))
([883b163](883b163b9a))
- support rfc9562 v8 uuids
([#&#8203;759](https://redirect.github.com/uuidjs/uuid/issues/759))
([35a5342](35a5342820))

##### Bug Fixes

- revert "perf: remove superfluous call to toLowerCase
([#&#8203;677](https://redirect.github.com/uuidjs/uuid/issues/677))"
([#&#8203;738](https://redirect.github.com/uuidjs/uuid/issues/738))
([e267b90](e267b9073d))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/open-feature/js-sdk).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC4xMzUuMiIsInVwZGF0ZWRJblZlciI6IjM5LjE3Ni4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-27 10:59:42 -05:00
Michael Beemer 6a224830fa
feat: add support for abort controllers to event handlers (#1151)
Signed-off-by: Michael Beemer <beeme1mr@users.noreply.github.com>
2025-02-26 16:17:28 -05:00
OpenFeature Bot a703ee7a6f
chore(main): release core 1.7.2 (#1150)
🤖 I have created a release *beep* *boop*
---


##
[1.7.2](https://github.com/open-feature/js-sdk/compare/core-v1.7.1...core-v1.7.2)
(2025-02-18)


### 🐛 Bug Fixes

* rename evaluation event property from data to body
([4c2b01e](4c2b01e367))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Signed-off-by: OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>
2025-02-18 13:50:35 -05:00
Michael Beemer 4c2b01e367
fix: rename evaluation event property from data to body
Signed-off-by: Michael Beemer <beeme1mr@users.noreply.github.com>
2025-02-18 18:46:02 +00:00
OpenFeature Bot 40deec0414
chore(main): release angular-sdk 0.0.10 (#1143)
🤖 I have created a release *beep* *boop*
---


##
[0.0.10](https://github.com/open-feature/js-sdk/compare/angular-sdk-v0.0.9-experimental...angular-sdk-v0.0.10)
(2025-02-13)


### 🧹 Chore

* **angular:** update angular package to a non-experimental version
([#1147](https://github.com/open-feature/js-sdk/issues/1147))
([5272f76](5272f76c40)),
closes [#1110](https://github.com/open-feature/js-sdk/issues/1110)
* update sdk peer
([#1142](https://github.com/open-feature/js-sdk/issues/1142))
([8bb6206](8bb620601e))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Signed-off-by: OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>
2025-02-13 21:11:57 +00:00
Lukas Reining 5272f76c40
chore(angular): update angular package to a non-experimental version (#1147)
Release Angular SDK as non-experimental version as described in #1110 

Release-As: 0.0.10

Fixes #1110

Signed-off-by: Lukas Reining <lukas.reining@codecentric.de>
Co-authored-by: Michael Beemer <beeme1mr@users.noreply.github.com>
2025-02-13 22:08:56 +01:00
OpenFeature Bot 30004ea88f
chore(main): release core 1.7.1 (#1149)
🤖 I have created a release *beep* *boop*
---


##
[1.7.1](https://github.com/open-feature/js-sdk/compare/core-v1.7.0...core-v1.7.1)
(2025-02-13)


### 🐛 Bug Fixes

* export missing telemetry functionality
([#1148](https://github.com/open-feature/js-sdk/issues/1148))
([dcbc300](dcbc30090e))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Signed-off-by: OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>
2025-02-13 16:03:13 -05:00
Michael Beemer dcbc30090e
fix: export missing telemetry functionality (#1148)
Signed-off-by: Michael Beemer <beeme1mr@users.noreply.github.com>
2025-02-13 15:59:56 -05:00
OpenFeature Bot 23ba0b3d8c
chore(main): release react-sdk 0.4.11 (#1122)
🤖 I have created a release *beep* *boop*
---


##
[0.4.11](https://github.com/open-feature/js-sdk/compare/react-sdk-v0.4.10...react-sdk-v0.4.11)
(2025-02-07)


###  New Features

* export useOpenFeatureClientStatus hook
([#1082](https://github.com/open-feature/js-sdk/issues/1082))
([4a6b860](4a6b860544))


### 🧹 Chore

* update sdk peer
([#1142](https://github.com/open-feature/js-sdk/issues/1142))
([8bb6206](8bb620601e))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Signed-off-by: OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>
2025-02-07 21:05:41 +00:00
Michael Beemer 8bb620601e
chore: update sdk peer (#1142)
Signed-off-by: Michael Beemer <beeme1mr@users.noreply.github.com>
2025-02-07 16:02:31 -05:00
OpenFeature Bot ffceec91bc
chore(main): release web-sdk 1.4.1 (#1135)
🤖 I have created a release *beep* *boop*
---


##
[1.4.1](https://github.com/open-feature/js-sdk/compare/web-sdk-v1.4.0...web-sdk-v1.4.1)
(2025-02-07)


### 🐛 Bug Fixes

* msg missing when providers return err resolutions
([#1134](https://github.com/open-feature/js-sdk/issues/1134))
([bc9f6e4](bc9f6e44da))


### 🧹 Chore

* update core peer
([8bbd43e](8bbd43e579))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Signed-off-by: OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
Co-authored-by: Todd Baert <todd.baert@dynatrace.com>
2025-02-07 20:35:51 +00:00
OpenFeature Bot 045842027c
chore(main): release server-sdk 1.17.1 (#1133)
🤖 I have created a release *beep* *boop*
---


##
[1.17.1](https://github.com/open-feature/js-sdk/compare/server-sdk-v1.17.0...server-sdk-v1.17.1)
(2025-02-07)


### 🐛 Bug Fixes

* msg missing when providers return err resolutions
([#1134](https://github.com/open-feature/js-sdk/issues/1134))
([bc9f6e4](bc9f6e44da))


### 🧹 Chore

* update core peer
([8bbd43e](8bbd43e579))


### 📚 Documentation

* fix eval context link
([#1132](https://github.com/open-feature/js-sdk/issues/1132))
([f6bc695](f6bc6951a3))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Signed-off-by: OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>
2025-02-07 20:26:32 +00:00
Todd Baert 8bbd43e579 chore: update core peer
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
2025-02-07 15:22:52 -05:00
OpenFeature Bot 644b9a148d
chore(main): release core 1.7.0 (#1137)
🤖 I have created a release *beep* *boop*
---


##
[1.7.0](https://github.com/open-feature/js-sdk/compare/core-v1.6.0...core-v1.7.0)
(2025-02-07)


###  New Features

* add telemetry helper utils
([#1120](https://github.com/open-feature/js-sdk/issues/1120))
([1e93b3c](1e93b3c6fa))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Signed-off-by: OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>
2025-02-07 20:01:55 +00:00
renovate[bot] 0f3e80cb64
chore(deps): update dependency eslint-plugin-jsdoc to v50.6.3 (#1127)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[eslint-plugin-jsdoc](https://redirect.github.com/gajus/eslint-plugin-jsdoc)
| [`50.4.3` ->
`50.6.3`](https://renovatebot.com/diffs/npm/eslint-plugin-jsdoc/50.4.3/50.6.3)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/eslint-plugin-jsdoc/50.6.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/eslint-plugin-jsdoc/50.6.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/eslint-plugin-jsdoc/50.4.3/50.6.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/eslint-plugin-jsdoc/50.4.3/50.6.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>gajus/eslint-plugin-jsdoc (eslint-plugin-jsdoc)</summary>

###
[`v50.6.3`](https://redirect.github.com/gajus/eslint-plugin-jsdoc/releases/tag/v50.6.3)

[Compare
Source](https://redirect.github.com/gajus/eslint-plugin-jsdoc/compare/v50.6.2...v50.6.3)

##### Bug Fixes

- **`check-template-names`:** stop restricting template names to single
letters; fixes
[#&#8203;1352](https://redirect.github.com/gajus/eslint-plugin-jsdoc/issues/1352)
([c283729](c283729387))

###
[`v50.6.2`](https://redirect.github.com/gajus/eslint-plugin-jsdoc/releases/tag/v50.6.2)

[Compare
Source](https://redirect.github.com/gajus/eslint-plugin-jsdoc/compare/v50.6.1...v50.6.2)

##### Bug Fixes

- **`valid-types`:** update closure suppress types; fixes
[#&#8203;1349](https://redirect.github.com/gajus/eslint-plugin-jsdoc/issues/1349)
([#&#8203;1350](https://redirect.github.com/gajus/eslint-plugin-jsdoc/issues/1350))
([a57f36e](a57f36e346))

###
[`v50.6.1`](https://redirect.github.com/gajus/eslint-plugin-jsdoc/releases/tag/v50.6.1)

[Compare
Source](https://redirect.github.com/gajus/eslint-plugin-jsdoc/compare/v50.6.0...v50.6.1)

##### Bug Fixes

- **types:** update configs types
([#&#8203;1344](https://redirect.github.com/gajus/eslint-plugin-jsdoc/issues/1344))
([d2c6040](d2c60403bb))

###
[`v50.6.0`](https://redirect.github.com/gajus/eslint-plugin-jsdoc/releases/tag/v50.6.0)

[Compare
Source](https://redirect.github.com/gajus/eslint-plugin-jsdoc/compare/v50.5.0...v50.6.0)

##### Features

- **lines-before-block:** move start-of-block checking behind
off-by-default `checkBlockStarts` option
([#&#8203;1341](https://redirect.github.com/gajus/eslint-plugin-jsdoc/issues/1341))
([f9b102d](f9b102dec5))

###
[`v50.5.0`](https://redirect.github.com/gajus/eslint-plugin-jsdoc/releases/tag/v50.5.0)

[Compare
Source](https://redirect.github.com/gajus/eslint-plugin-jsdoc/compare/v50.4.3...v50.5.0)

##### Features

- ability to import iterateJsdoc
([#&#8203;1338](https://redirect.github.com/gajus/eslint-plugin-jsdoc/issues/1338))
([b9091f8](b9091f8da9))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/open-feature/js-sdk).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNDUuMCIsInVwZGF0ZWRJblZlciI6IjM5LjE0NS4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-07 19:57:53 +00:00
renovate[bot] d202db53db
chore(deps): update dependency prettier to v3.4.2 (#1130)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [prettier](https://prettier.io)
([source](https://redirect.github.com/prettier/prettier)) | [`3.3.3` ->
`3.4.2`](https://renovatebot.com/diffs/npm/prettier/3.3.3/3.4.2) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/prettier/3.4.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/prettier/3.4.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/prettier/3.3.3/3.4.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/prettier/3.3.3/3.4.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>prettier/prettier (prettier)</summary>

###
[`v3.4.2`](https://redirect.github.com/prettier/prettier/blob/HEAD/CHANGELOG.md#342)

[Compare
Source](https://redirect.github.com/prettier/prettier/compare/3.4.1...3.4.2)


[diff](https://redirect.github.com/prettier/prettier/compare/3.4.1...3.4.2)

##### Treat U+30A0 & U+30FB in Katakana Block as CJK
([#&#8203;16796](https://redirect.github.com/prettier/prettier/pull/16796)
by [@&#8203;tats-u](https://redirect.github.com/tats-u))

Prettier doesn't treat U+30A0 & U+30FB as Japanese. U+30FB is commonly
used in Japanese to represent the delimitation of first and last names
of non-Japanese people or “and”. The following “C言語・C++・Go・Rust” means
“C language & C++ & Go & Rust” in Japanese.

<!-- prettier-ignore -->

```md
<!-- Input (--prose-wrap=never) -->

C言
語
・
C++
・
Go
・
Rust

<!-- Prettier 3.4.1 -->
C言語・ C++ ・ Go ・ Rust

<!-- Prettier 3.4.2 -->
C言語・C++・Go・Rust
```

U+30A0 can be used as the replacement of the `-` in non-Japanese names
(e.g. “Saint-Saëns” (Charles Camille Saint-Saëns) can be represented as
“サン゠サーンス” in Japanese), but substituted by ASCII hyphen (U+002D) or
U+FF1D (full width hyphen) in many cases (e.g. “サン=サーンス” or “サン=サーンス”).

##### Fix comments print on class methods with decorators
([#&#8203;16891](https://redirect.github.com/prettier/prettier/pull/16891)
by [@&#8203;fisker](https://redirect.github.com/fisker))

<!-- prettier-ignore -->

```jsx
// Input
class A {
  @&#8203;decorator
  /** 
   * The method description
   *
  */
  async method(foo: Foo, bar: Bar) {
    console.log(foo);
  }
}

// Prettier 3.4.1
class A {
  @&#8203;decorator
  async /**
   * The method description
   *
   */
  method(foo: Foo, bar: Bar) {
    console.log(foo);
  }
}

// Prettier 3.4.2
class A {
  @&#8203;decorator
  /**
   * The method description
   *
   */
  async method(foo: Foo, bar: Bar) {
    console.log(foo);
  }
}
```

##### Fix non-idempotent formatting
([#&#8203;16899](https://redirect.github.com/prettier/prettier/pull/16899)
by [@&#8203;seiyab](https://redirect.github.com/seiyab))

This bug fix is not language-specific. You may see similar change in any
languages. This fixes regression in 3.4.0 so change caused by it should
yield same formatting as 3.3.3.

<!-- prettier-ignore -->

```jsx
// Input
<div>
  foo
  <span>longlonglonglonglonglonglonglonglonglonglonglonglonglonglongl foo</span>
  , abc
</div>;

// Prettier 3.4.1 (first)
<div>
  foo
  <span>
    longlonglonglonglonglonglonglonglonglonglonglonglonglonglongl foo
  </span>, abc
</div>;

// Prettier 3.4.1 (second)
<div>
  foo
  <span>longlonglonglonglonglonglonglonglonglonglonglonglonglonglongl foo</span>
  , abc
</div>;

// Prettier 3.4.2
<div>
  foo
  <span>longlonglonglonglonglonglonglonglonglonglonglonglonglonglongl foo</span>
  , abc
</div>;
```

###
[`v3.4.1`](https://redirect.github.com/prettier/prettier/blob/HEAD/CHANGELOG.md#341)

[Compare
Source](https://redirect.github.com/prettier/prettier/compare/3.4.0...3.4.1)


[diff](https://redirect.github.com/prettier/prettier/compare/3.4.0...3.4.1)

##### Remove unnecessary parentheses around assignment in `v-on`
([#&#8203;16887](https://redirect.github.com/prettier/prettier/pull/16887)
by [@&#8203;fisker](https://redirect.github.com/fisker))

<!-- prettier-ignore -->

```vue
<!-- Input -->
<template>
  <button @&#8203;click="foo += 2">Click</button>
</template>

<!-- Prettier 3.4.0 -->
<template>
  <button @&#8203;click="(foo += 2)">Click</button>
</template>

<!-- Prettier 3.4.1 -->
<template>
  <button @&#8203;click="foo += 2">Click</button>
</template>
```

###
[`v3.4.0`](https://redirect.github.com/prettier/prettier/blob/HEAD/CHANGELOG.md#340)

[Compare
Source](https://redirect.github.com/prettier/prettier/compare/3.3.3...3.4.0)


[diff](https://redirect.github.com/prettier/prettier/compare/3.3.3...3.4.0)

🔗 [Release Notes](https://prettier.io/blog/2024/11/26/3.4.0.html)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/open-feature/js-sdk).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNDUuMCIsInVwZGF0ZWRJblZlciI6IjM5LjE0NS4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-07 19:57:00 +00:00
Michael Beemer 1e93b3c6fa
feat: add telemetry helper utils (#1120)
## This PR

- adds a method to core that returns a semantically valid flag
evaluation event

### Related Issues

Fixes #1118

## Notes

I've omitted value type because it is likely to be declined in the OTel
spec and adds complexity. We should consider removing that section from
[appendix
d](https://openfeature.dev/specification/appendix-d#evaluation-details).

---------

Signed-off-by: Michael Beemer <beeme1mr@users.noreply.github.com>
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
Co-authored-by: Todd Baert <todd.baert@dynatrace.com>
2025-02-07 19:56:42 +00:00
Todd Baert bc9f6e44da
fix: msg missing when providers return err resolutions (#1134)
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
2025-02-06 13:39:55 -05:00
Michael Beemer f6bc6951a3
docs: fix eval context link (#1132)
Signed-off-by: Michael Beemer <beeme1mr@users.noreply.github.com>
2025-02-05 16:23:35 -05:00
renovate[bot] 9196ac9acd
chore(deps): update dependency jest-preset-angular to v14.5.1 (#1128)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [jest-preset-angular](https://thymikee.github.io/jest-preset-angular)
([source](https://redirect.github.com/thymikee/jest-preset-angular)) |
[`14.2.4` ->
`14.5.1`](https://renovatebot.com/diffs/npm/jest-preset-angular/14.2.4/14.5.1)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/jest-preset-angular/14.5.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/jest-preset-angular/14.5.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/jest-preset-angular/14.2.4/14.5.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/jest-preset-angular/14.2.4/14.5.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>thymikee/jest-preset-angular (jest-preset-angular)</summary>

###
[`v14.5.1`](https://redirect.github.com/thymikee/jest-preset-angular/blob/HEAD/CHANGELOG.md#1451-2025-01-25)

[Compare
Source](https://redirect.github.com/thymikee/jest-preset-angular/compare/v14.5.0...v14.5.1)

##### Bug Fixes

- fix: properly handle types for presets module
([#&#8203;2945](https://redirect.github.com/thymikee/jest-preset-angular/issues/2945))
([e0323bd](https://redirect.github.com/thymikee/jest-preset-angular/commit/e0323bd)),
closes
[#&#8203;2945](https://redirect.github.com/thymikee/jest-preset-angular/issues/2945)

###
[`v14.5.0`](https://redirect.github.com/thymikee/jest-preset-angular/blob/HEAD/CHANGELOG.md#1450-2025-01-10)

[Compare
Source](https://redirect.github.com/thymikee/jest-preset-angular/compare/v14.4.2...v14.5.0)

##### Features

- feat: add custom `jsdom` env
[#&#8203;2904](https://redirect.github.com/thymikee/jest-preset-angular/issues/2904)
([6045a96](https://redirect.github.com/thymikee/jest-preset-angular/commit/6045a96)),
closes
[#&#8203;2883](https://redirect.github.com/thymikee/jest-preset-angular/issues/2883)

##### Code Refactoring

- refactor: add type for `serializers/index.ts`
([dd64d78](https://redirect.github.com/thymikee/jest-preset-angular/commit/dd64d78))

##### DEPRECATIONS

- refactor: deprecate `defaultTransformerOptions` in `presets`
([99d3112](https://redirect.github.com/thymikee/jest-preset-angular/commit/99d3112))
- refactor: deprecate `ngcc` util via `globalSetup`
([edeaa3f](https://redirect.github.com/thymikee/jest-preset-angular/commit/edeaa3f))

###
[`v14.4.2`](https://redirect.github.com/thymikee/jest-preset-angular/blob/HEAD/CHANGELOG.md#1442-2024-12-03)

[Compare
Source](https://redirect.github.com/thymikee/jest-preset-angular/compare/v14.4.1...v14.4.2)

##### Bug Fixes

- fix: revert commit
[`ad7a297`](https://redirect.github.com/thymikee/jest-preset-angular/commit/ad7a297e)
to fix perf regression
([b19cd6e](https://redirect.github.com/thymikee/jest-preset-angular/commit/b19cd6e)),
closes
[#&#8203;2886](https://redirect.github.com/thymikee/jest-preset-angular/issues/2886)

###
[`v14.4.1`](https://redirect.github.com/thymikee/jest-preset-angular/blob/HEAD/CHANGELOG.md#1441-2024-11-28)

[Compare
Source](https://redirect.github.com/thymikee/jest-preset-angular/compare/v14.4.0...v14.4.1)

##### Bug Fixes

- fix: remove `@angular-devkit/build-angular` from `peerDependencies`
([2f6bc3d](https://redirect.github.com/thymikee/jest-preset-angular/commit/2f6bc3d))

###
[`v14.4.0`](https://redirect.github.com/thymikee/jest-preset-angular/blob/HEAD/CHANGELOG.md#1440-2024-11-27)

[Compare
Source](https://redirect.github.com/thymikee/jest-preset-angular/compare/v14.3.3...v14.4.0)

##### Features

- feat: add preset creator functions
([552922e](https://redirect.github.com/thymikee/jest-preset-angular/commit/552922e))
- feat: add support for Angular 19
([4a73245](https://redirect.github.com/thymikee/jest-preset-angular/commit/4a73245))

##### Code Refactoring

- refactor: use `createCjsPreset` function for `jest-preset.js`
([9d18d0f](https://redirect.github.com/thymikee/jest-preset-angular/commit/9d18d0f))
- refactor: deprecate legacy presets
([8da5630](https://redirect.github.com/thymikee/jest-preset-angular/commit/8da5630))

##### DEPRECATIONS

- Using `preset: 'jest-preset-angular'` is deprecated. The recommended
approach is
https://thymikee.github.io/jest-preset-angular/docs/getting-started/presets#createcjspresetoptions
- Using `preset: 'jest-preset-angular/presets/defaults-esm'` is
deprecated. The recommended approach is
https://thymikee.github.io/jest-preset-angular/docs/getting-started/presets#createesmpresetoptions

###
[`v14.3.3`](https://redirect.github.com/thymikee/jest-preset-angular/blob/HEAD/CHANGELOG.md#1433-2024-11-22)

[Compare
Source](https://redirect.github.com/thymikee/jest-preset-angular/compare/v14.3.2...v14.3.3)

##### Features

- feat: support configuring zoneless test env for CJS
([7a270b1](https://redirect.github.com/thymikee/jest-preset-angular/commit/7a270b1))

###
[`v14.3.2`](https://redirect.github.com/thymikee/jest-preset-angular/blob/HEAD/CHANGELOG.md#1432-2024-11-20)

[Compare
Source](https://redirect.github.com/thymikee/jest-preset-angular/compare/v14.3.1...v14.3.2)

##### Bug Fixes

- fix: include `version` from `package.json` into cache key
([de02c79](https://redirect.github.com/thymikee/jest-preset-angular/commit/de02c79)),
closes
[#&#8203;2844](https://redirect.github.com/thymikee/jest-preset-angular/issues/2844)

###
[`v14.3.1`](https://redirect.github.com/thymikee/jest-preset-angular/blob/HEAD/CHANGELOG.md#1431-2024-11-18)

[Compare
Source](https://redirect.github.com/thymikee/jest-preset-angular/compare/v14.3.0...v14.3.1)

##### Documentation

- docs: simplify `README.md` about installation and configuration
([79ea18b](https://redirect.github.com/thymikee/jest-preset-angular/commit/79ea18b))

###
[`v14.3.0`](https://redirect.github.com/thymikee/jest-preset-angular/blob/HEAD/CHANGELOG.md#1430-2024-11-15)

[Compare
Source](https://redirect.github.com/thymikee/jest-preset-angular/compare/v14.2.4...v14.3.0)

##### Features

- feat: add new setup test env functions
([21c0238](https://redirect.github.com/thymikee/jest-preset-angular/commit/21c0238)),
closes
[#&#8203;354](https://redirect.github.com/thymikee/jest-preset-angular/issues/354)
[#&#8203;2755](https://redirect.github.com/thymikee/jest-preset-angular/issues/2755)
- feat: build package with type definitions
([a269daa](https://redirect.github.com/thymikee/jest-preset-angular/commit/a269daa))
- feat: deprecate `setup-jest.js` and `setup-jest.mjs`
([a304036](https://redirect.github.com/thymikee/jest-preset-angular/commit/a304036))

##### Code Refactoring

- test: switch example app test config files to ts
([e61f1ff](https://redirect.github.com/thymikee/jest-preset-angular/commit/e61f1ff))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/open-feature/js-sdk).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNDUuMCIsInVwZGF0ZWRJblZlciI6IjM5LjE0NS4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-03 19:27:29 +00:00
renovate[bot] c577e0d28e
chore(deps): update dependency eslint-plugin-jest to v28.11.0 (#1126)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[eslint-plugin-jest](https://redirect.github.com/jest-community/eslint-plugin-jest)
| [`28.8.3` ->
`28.11.0`](https://renovatebot.com/diffs/npm/eslint-plugin-jest/28.8.3/28.11.0)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/eslint-plugin-jest/28.11.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/eslint-plugin-jest/28.11.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/eslint-plugin-jest/28.8.3/28.11.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/eslint-plugin-jest/28.8.3/28.11.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>jest-community/eslint-plugin-jest
(eslint-plugin-jest)</summary>

###
[`v28.11.0`](https://redirect.github.com/jest-community/eslint-plugin-jest/blob/HEAD/CHANGELOG.md#28110-2025-01-15)

[Compare
Source](https://redirect.github.com/jest-community/eslint-plugin-jest/compare/v28.10.1...v28.11.0)

##### Features

- **valid-expect:** allow calling `expect` with no arguments
([#&#8203;1688](https://redirect.github.com/jest-community/eslint-plugin-jest/issues/1688))
([ff0349e](ff0349ea0b))

####
[28.10.1](https://redirect.github.com/jest-community/eslint-plugin-jest/compare/v28.10.0...v28.10.1)
(2025-01-15)

##### Bug Fixes

- **padding-around-test-blocks:** update description
([#&#8203;1691](https://redirect.github.com/jest-community/eslint-plugin-jest/issues/1691))
([9cb4ecc](9cb4eccab0))

###
[`v28.10.1`](https://redirect.github.com/jest-community/eslint-plugin-jest/blob/HEAD/CHANGELOG.md#28101-2025-01-15)

[Compare
Source](https://redirect.github.com/jest-community/eslint-plugin-jest/compare/v28.10.0...v28.10.1)

##### Bug Fixes

- **padding-around-test-blocks:** update description
([#&#8203;1691](https://redirect.github.com/jest-community/eslint-plugin-jest/issues/1691))
([9cb4ecc](9cb4eccab0))

###
[`v28.10.0`](https://redirect.github.com/jest-community/eslint-plugin-jest/blob/HEAD/CHANGELOG.md#28100-2024-12-19)

[Compare
Source](https://redirect.github.com/jest-community/eslint-plugin-jest/compare/v28.9.0...v28.10.0)

##### Features

- **unbound-method:** ignore functions passed to `jest.mocked`
([#&#8203;1681](https://redirect.github.com/jest-community/eslint-plugin-jest/issues/1681))
([d868636](d868636623))

###
[`v28.9.0`](https://redirect.github.com/jest-community/eslint-plugin-jest/blob/HEAD/CHANGELOG.md#2890-2024-11-05)

[Compare
Source](https://redirect.github.com/jest-community/eslint-plugin-jest/compare/v28.8.3...v28.9.0)

##### Features

- add TypeScript types
([#&#8203;1667](https://redirect.github.com/jest-community/eslint-plugin-jest/issues/1667))
([1ce1258](1ce12588e7))

####
[28.8.3](https://redirect.github.com/jest-community/eslint-plugin-jest/compare/v28.8.2...v28.8.3)
(2024-09-04)

##### Bug Fixes

- **prefer-importing-jest-globals:** don't add imports in the middle of
statements
([#&#8203;1645](https://redirect.github.com/jest-community/eslint-plugin-jest/issues/1645))
([9c4197c](9c4197c91f))

####
[28.8.2](https://redirect.github.com/jest-community/eslint-plugin-jest/compare/v28.8.1...v28.8.2)
(2024-09-02)

##### Performance Improvements

- **prefer-importing-jest-globals:** stop collecting import specifiers
for no reason
([#&#8203;1646](https://redirect.github.com/jest-community/eslint-plugin-jest/issues/1646))
([0660242](066024289e))

####
[28.8.1](https://redirect.github.com/jest-community/eslint-plugin-jest/compare/v28.8.0...v28.8.1)
(2024-08-29)

##### Bug Fixes

- **prefer-importing-jest-globals:** support typescript-eslint parser
([#&#8203;1639](https://redirect.github.com/jest-community/eslint-plugin-jest/issues/1639))
([307f6a7](307f6a7b3a))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/open-feature/js-sdk).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNDUuMCIsInVwZGF0ZWRJblZlciI6IjM5LjE0NS4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-03 18:00:38 +00:00
renovate[bot] 31eff43554
chore(deps): update nest monorepo to v10.4.15 (#1124)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [@nestjs/common](https://nestjs.com)
([source](https://redirect.github.com/nestjs/nest/tree/HEAD/packages/common))
| [`10.4.6` ->
`10.4.15`](https://renovatebot.com/diffs/npm/@nestjs%2fcommon/10.4.6/10.4.15)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@nestjs%2fcommon/10.4.15?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@nestjs%2fcommon/10.4.15?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@nestjs%2fcommon/10.4.6/10.4.15?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@nestjs%2fcommon/10.4.6/10.4.15?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [@nestjs/core](https://nestjs.com)
([source](https://redirect.github.com/nestjs/nest/tree/HEAD/packages/core))
| [`10.4.6` ->
`10.4.15`](https://renovatebot.com/diffs/npm/@nestjs%2fcore/10.4.6/10.4.15)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@nestjs%2fcore/10.4.15?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@nestjs%2fcore/10.4.15?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@nestjs%2fcore/10.4.6/10.4.15?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@nestjs%2fcore/10.4.6/10.4.15?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [@nestjs/platform-express](https://nestjs.com)
([source](https://redirect.github.com/nestjs/nest/tree/HEAD/packages/platform-express))
| [`10.4.6` ->
`10.4.15`](https://renovatebot.com/diffs/npm/@nestjs%2fplatform-express/10.4.6/10.4.15)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@nestjs%2fplatform-express/10.4.15?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@nestjs%2fplatform-express/10.4.15?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@nestjs%2fplatform-express/10.4.6/10.4.15?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@nestjs%2fplatform-express/10.4.6/10.4.15?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [@nestjs/testing](https://nestjs.com)
([source](https://redirect.github.com/nestjs/nest/tree/HEAD/packages/testing))
| [`10.4.6` ->
`10.4.15`](https://renovatebot.com/diffs/npm/@nestjs%2ftesting/10.4.6/10.4.15)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@nestjs%2ftesting/10.4.15?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@nestjs%2ftesting/10.4.15?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@nestjs%2ftesting/10.4.6/10.4.15?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@nestjs%2ftesting/10.4.6/10.4.15?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>nestjs/nest (@&#8203;nestjs/common)</summary>

###
[`v10.4.15`](https://redirect.github.com/nestjs/nest/releases/tag/v10.4.15)

[Compare
Source](https://redirect.github.com/nestjs/nest/compare/v10.4.14...v10.4.15)

##### v10.4.15 (2024-12-09)

##### Dependencies

-   `platform-express`
- [#&#8203;14282](https://redirect.github.com/nestjs/nest/pull/14282)
fix(deps): update dependency express to v4.21.2
([@&#8203;renovate\[bot\]](https://redirect.github.com/apps/renovate))

###
[`v10.4.14`](https://redirect.github.com/nestjs/nest/compare/v10.4.13...v10.4.14)

[Compare
Source](https://redirect.github.com/nestjs/nest/compare/v10.4.13...v10.4.14)

###
[`v10.4.13`](https://redirect.github.com/nestjs/nest/compare/v10.4.12...1eba0121a089be0e4880f37503dab7870602bb8e)

[Compare
Source](https://redirect.github.com/nestjs/nest/compare/v10.4.12...v10.4.13)

###
[`v10.4.12`](https://redirect.github.com/nestjs/nest/releases/tag/v10.4.12)

[Compare
Source](https://redirect.github.com/nestjs/nest/compare/v10.4.11...v10.4.12)

##### v10.4.12 (2024-11-29)

##### Bug fixes

-   `common`
- [#&#8203;14241](https://redirect.github.com/nestjs/nest/pull/14241)
fix(common): enforce string type in validationpipe
([@&#8203;LhonRafaat](https://redirect.github.com/LhonRafaat))

##### Dependencies

-   Other
- [#&#8203;14243](https://redirect.github.com/nestjs/nest/pull/14243)
chore(deps): update dependency
[@&#8203;types/node](https://redirect.github.com/types/node) to v20.17.9
([@&#8203;renovate\[bot\]](https://redirect.github.com/apps/renovate))
- [#&#8203;14240](https://redirect.github.com/nestjs/nest/pull/14240)
chore(deps): update dependency
[@&#8203;types/multer](https://redirect.github.com/types/multer) to
v1.4.12
([@&#8203;renovate\[bot\]](https://redirect.github.com/apps/renovate))
- [#&#8203;14239](https://redirect.github.com/nestjs/nest/pull/14239)
chore(deps): update dependency
[@&#8203;types/chai](https://redirect.github.com/types/chai) to v4.3.20
([@&#8203;renovate\[bot\]](https://redirect.github.com/apps/renovate))
- [#&#8203;14237](https://redirect.github.com/nestjs/nest/pull/14237)
chore(deps): update confluentinc/cp-zookeeper docker tag to v7.7.2
([@&#8203;renovate\[bot\]](https://redirect.github.com/apps/renovate))
- [#&#8203;14236](https://redirect.github.com/nestjs/nest/pull/14236)
chore(deps): update confluentinc/cp-kafka docker tag to v7.7.2
([@&#8203;renovate\[bot\]](https://redirect.github.com/apps/renovate))
- [#&#8203;12253](https://redirect.github.com/nestjs/nest/pull/12253)
fix(deps): update apollo graphql packages
([@&#8203;renovate\[bot\]](https://redirect.github.com/apps/renovate))
- [#&#8203;14235](https://redirect.github.com/nestjs/nest/pull/14235)
chore(deps-dev): bump
[@&#8203;commitlint/config-angular](https://redirect.github.com/commitlint/config-angular)
from 19.5.0 to 19.6.0
([@&#8203;dependabot\[bot\]](https://redirect.github.com/apps/dependabot))
- [#&#8203;14233](https://redirect.github.com/nestjs/nest/pull/14233)
chore(deps): update nest monorepo
([@&#8203;renovate\[bot\]](https://redirect.github.com/apps/renovate))
- [#&#8203;14232](https://redirect.github.com/nestjs/nest/pull/14232)
fix(deps): update dependency path-to-regexp to v3.3.0 \[security]
([@&#8203;renovate\[bot\]](https://redirect.github.com/apps/renovate))
- [#&#8203;14229](https://redirect.github.com/nestjs/nest/pull/14229)
chore(deps): update mongo docker tag to v8
([@&#8203;renovate\[bot\]](https://redirect.github.com/apps/renovate))
- [#&#8203;14228](https://redirect.github.com/nestjs/nest/pull/14228)
chore(deps): update dependency
[@&#8203;types/node](https://redirect.github.com/types/node) to v22.10.0
([@&#8203;renovate\[bot\]](https://redirect.github.com/apps/renovate))
- [#&#8203;14227](https://redirect.github.com/nestjs/nest/pull/14227)
fix(deps): update nest-graphql monorepo to v12.2.1
([@&#8203;renovate\[bot\]](https://redirect.github.com/apps/renovate))
- [#&#8203;14224](https://redirect.github.com/nestjs/nest/pull/14224)
fix(deps): update dependency sequelize to v6.37.5
([@&#8203;renovate\[bot\]](https://redirect.github.com/apps/renovate))
- [#&#8203;14230](https://redirect.github.com/nestjs/nest/pull/14230)
chore(deps): update mysql docker tag to v9
([@&#8203;renovate\[bot\]](https://redirect.github.com/apps/renovate))
- [#&#8203;14231](https://redirect.github.com/nestjs/nest/pull/14231)
fix(deps): update dependency
[@&#8203;nestjs/swagger](https://redirect.github.com/nestjs/swagger) to
v8
([@&#8203;renovate\[bot\]](https://redirect.github.com/apps/renovate))
- `common`, `core`, `microservices`, `platform-express`,
`platform-fastify`, `platform-socket.io`, `platform-ws`, `testing`,
`websockets`
- [#&#8203;14226](https://redirect.github.com/nestjs/nest/pull/14226)
fix(deps): update dependency tslib to v2.8.1
([@&#8203;renovate\[bot\]](https://redirect.github.com/apps/renovate))
-   `platform-socket.io`
- [#&#8203;14225](https://redirect.github.com/nestjs/nest/pull/14225)
fix(deps): update dependency socket.io to v4.8.1
([@&#8203;renovate\[bot\]](https://redirect.github.com/apps/renovate))

##### Committers: 1

-   Lhon ([@&#8203;LhonRafaat](https://redirect.github.com/LhonRafaat))

###
[`v10.4.11`](https://redirect.github.com/nestjs/nest/compare/v10.4.10...v10.4.11)

[Compare
Source](https://redirect.github.com/nestjs/nest/compare/v10.4.10...v10.4.11)

###
[`v10.4.10`](https://redirect.github.com/nestjs/nest/releases/tag/v10.4.10)

[Compare
Source](https://redirect.github.com/nestjs/nest/compare/v10.4.9...v10.4.10)

##### v10.4.10 (2024-11-27)

##### Bug fixes

-   `platform-socket.io`, `websockets`
- [#&#8203;14204](https://redirect.github.com/nestjs/nest/pull/14204)
fix(websockets): ensure non-shared servers call close method
([@&#8203;sapenlei](https://redirect.github.com/sapenlei))

##### Dependencies

- [#&#8203;14221](https://redirect.github.com/nestjs/nest/pull/14221)
chore(deps): update mysql docker tag to v8.4.3
([@&#8203;renovate\[bot\]](https://redirect.github.com/apps/renovate))
- [#&#8203;14220](https://redirect.github.com/nestjs/nest/pull/14220)
chore(deps): update dependency webpack to v5.96.1
([@&#8203;renovate\[bot\]](https://redirect.github.com/apps/renovate))
- [#&#8203;14219](https://redirect.github.com/nestjs/nest/pull/14219)
chore(deps): update dependency nodemon to v3.1.7
([@&#8203;renovate\[bot\]](https://redirect.github.com/apps/renovate))
- [#&#8203;14218](https://redirect.github.com/nestjs/nest/pull/14218)
chore(deps): update confluentinc/cp-zookeeper docker tag to v7.7.1
([@&#8203;renovate\[bot\]](https://redirect.github.com/apps/renovate))
- [#&#8203;14217](https://redirect.github.com/nestjs/nest/pull/14217)
chore(deps): update confluentinc/cp-kafka docker tag to v7.7.1
([@&#8203;renovate\[bot\]](https://redirect.github.com/apps/renovate))
- [#&#8203;14216](https://redirect.github.com/nestjs/nest/pull/14216)
fix(deps): update dependency rimraf to v5.0.10
([@&#8203;renovate\[bot\]](https://redirect.github.com/apps/renovate))
- [#&#8203;14215](https://redirect.github.com/nestjs/nest/pull/14215)
fix(deps): update dependency dotenv to v16.4.5
([@&#8203;renovate\[bot\]](https://redirect.github.com/apps/renovate))
- [#&#8203;14214](https://redirect.github.com/nestjs/nest/pull/14214)
fix(deps): update dependency
[@&#8203;grpc/reflection](https://redirect.github.com/grpc/reflection)
to v1.0.4
([@&#8203;renovate\[bot\]](https://redirect.github.com/apps/renovate))
- [#&#8203;12940](https://redirect.github.com/nestjs/nest/pull/12940)
fix(deps): update dependency mongoose to v8.8.3
([@&#8203;renovate\[bot\]](https://redirect.github.com/apps/renovate))
- [#&#8203;14207](https://redirect.github.com/nestjs/nest/pull/14207)
chore(deps): update dependency
[@&#8203;types/dotenv](https://redirect.github.com/types/dotenv) to
v8.2.3
([@&#8203;renovate\[bot\]](https://redirect.github.com/apps/renovate))
- [#&#8203;14208](https://redirect.github.com/nestjs/nest/pull/14208)
chore(deps): update dependency
[@&#8203;types/node](https://redirect.github.com/types/node) to v20.17.8
([@&#8203;renovate\[bot\]](https://redirect.github.com/apps/renovate))
- [#&#8203;14209](https://redirect.github.com/nestjs/nest/pull/14209)
chore(deps): update dependency amqplib to v0.10.5
([@&#8203;renovate\[bot\]](https://redirect.github.com/apps/renovate))
- [#&#8203;14212](https://redirect.github.com/nestjs/nest/pull/14212)
chore(deps): update dependency webpack to v5.94.0 \[security]
([@&#8203;renovate\[bot\]](https://redirect.github.com/apps/renovate))
- [#&#8203;14210](https://redirect.github.com/nestjs/nest/pull/14210)
chore(deps): update dependency husky to v9.1.7
([@&#8203;renovate\[bot\]](https://redirect.github.com/apps/renovate))
- [#&#8203;14211](https://redirect.github.com/nestjs/nest/pull/14211)
chore(deps): update nest monorepo
([@&#8203;renovate\[bot\]](https://redirect.github.com/apps/renovate))
- [#&#8203;14206](https://redirect.github.com/nestjs/nest/pull/14206)
chore(deps-dev): bump mongoose from 8.8.1 to 8.8.3
([@&#8203;dependabot\[bot\]](https://redirect.github.com/apps/dependabot))

##### Committers: 1

-   sapenlei ([@&#8203;sapenlei](https://redirect.github.com/sapenlei))

###
[`v10.4.9`](https://redirect.github.com/nestjs/nest/releases/tag/v10.4.9)

[Compare
Source](https://redirect.github.com/nestjs/nest/compare/v10.4.8...v10.4.9)

##### v10.4.9 (2024-11-25)

##### Bug fixes

-   `core`, `microservices`
- [#&#8203;13923](https://redirect.github.com/nestjs/nest/pull/13923)
fix(core): merge req context with tenant payload in the request instance
([@&#8203;DylanVeldra](https://redirect.github.com/DylanVeldra))
-   `websockets`
- [#&#8203;14185](https://redirect.github.com/nestjs/nest/pull/14185)
fix(websockets): Prevent HTTP server early close in Socket.IO shutdown
([@&#8203;sapenlei](https://redirect.github.com/sapenlei))
-   `common`
- [#&#8203;14181](https://redirect.github.com/nestjs/nest/pull/14181)
fix(common): fallback to empty string for enums when validating (swc
builder)
([@&#8203;kamilmysliwiec](https://redirect.github.com/kamilmysliwiec))
-   `core`
- [#&#8203;13804](https://redirect.github.com/nestjs/nest/pull/13804)
fix(core): dependencies not resolving for transient lazy providers
([@&#8203;patrickacioli](https://redirect.github.com/patrickacioli))
-   `microservices`
- [#&#8203;14163](https://redirect.github.com/nestjs/nest/pull/14163)
fix(microservices): grpc client streaming bugs
([@&#8203;kamilmysliwiec](https://redirect.github.com/kamilmysliwiec))

##### Enhancements

-   `common`, `core`
- [#&#8203;14175](https://redirect.github.com/nestjs/nest/pull/14175)
fix(common,core): align the logic of optional provider
([@&#8203;micalevisk](https://redirect.github.com/micalevisk))
-   `microservices`
- [#&#8203;12954](https://redirect.github.com/nestjs/nest/pull/12954)
feat: emit batch ([@&#8203;gunb0s](https://redirect.github.com/gunb0s))

##### Dependencies

-   Other
- [#&#8203;14192](https://redirect.github.com/nestjs/nest/pull/14192)
chore(deps): update dependency webpack to v5.94.0 \[security]
([@&#8203;renovate\[bot\]](https://redirect.github.com/apps/renovate))
- [#&#8203;14188](https://redirect.github.com/nestjs/nest/pull/14188)
chore(deps): bump cross-spawn from 7.0.3 to 7.0.6 in
/sample/30-event-emitter
([@&#8203;dependabot\[bot\]](https://redirect.github.com/apps/dependabot))
- [#&#8203;14187](https://redirect.github.com/nestjs/nest/pull/14187)
chore(deps): bump cookie and
[@&#8203;nestjs/platform-express](https://redirect.github.com/nestjs/platform-express)
in /sample/34-using-esm-packages
([@&#8203;dependabot\[bot\]](https://redirect.github.com/apps/dependabot))
- [#&#8203;14189](https://redirect.github.com/nestjs/nest/pull/14189)
chore(deps): bump cross-spawn from 7.0.3 to 7.0.6 in /sample/19-auth-jwt
([@&#8203;dependabot\[bot\]](https://redirect.github.com/apps/dependabot))
- [#&#8203;14186](https://redirect.github.com/nestjs/nest/pull/14186)
chore(deps): bump cross-spawn from 7.0.3 to 7.0.6 in
/sample/31-graphql-federation-code-first/posts-application
([@&#8203;dependabot\[bot\]](https://redirect.github.com/apps/dependabot))
- [#&#8203;14183](https://redirect.github.com/nestjs/nest/pull/14183)
chore(deps): bump cross-spawn from 7.0.3 to 7.0.6 in
/sample/32-graphql-federation-schema-first/posts-application
([@&#8203;dependabot\[bot\]](https://redirect.github.com/apps/dependabot))
- [#&#8203;14176](https://redirect.github.com/nestjs/nest/pull/14176)
chore(deps): bump cross-spawn from 7.0.3 to 7.0.6 in
/sample/32-graphql-federation-schema-first/users-application
([@&#8203;dependabot\[bot\]](https://redirect.github.com/apps/dependabot))
- [#&#8203;14179](https://redirect.github.com/nestjs/nest/pull/14179)
chore(deps-dev): bump
[@&#8203;types/mocha](https://redirect.github.com/types/mocha) from
10.0.9 to 10.0.10
([@&#8203;dependabot\[bot\]](https://redirect.github.com/apps/dependabot))
- [#&#8203;14174](https://redirect.github.com/nestjs/nest/pull/14174)
chore(deps): bump cross-spawn from 7.0.3 to 7.0.6 in
/sample/22-graphql-prisma
([@&#8203;dependabot\[bot\]](https://redirect.github.com/apps/dependabot))
- [#&#8203;14173](https://redirect.github.com/nestjs/nest/pull/14173)
chore(deps): bump cross-spawn from 7.0.3 to 7.0.6 in /sample/28-sse
([@&#8203;dependabot\[bot\]](https://redirect.github.com/apps/dependabot))
- [#&#8203;14165](https://redirect.github.com/nestjs/nest/pull/14165)
chore(deps-dev): bump
[@&#8203;typescript-eslint/parser](https://redirect.github.com/typescript-eslint/parser)
from 8.14.0 to 8.15.0
([@&#8203;dependabot\[bot\]](https://redirect.github.com/apps/dependabot))
- [#&#8203;14171](https://redirect.github.com/nestjs/nest/pull/14171)
chore(deps): bump cross-spawn from 7.0.3 to 7.0.6 in /sample/11-swagger
([@&#8203;dependabot\[bot\]](https://redirect.github.com/apps/dependabot))
- [#&#8203;14172](https://redirect.github.com/nestjs/nest/pull/14172)
chore(deps): bump cookie and
[@&#8203;nestjs/platform-express](https://redirect.github.com/nestjs/platform-express)
in /sample/35-use-esm-package-after-node22
([@&#8203;dependabot\[bot\]](https://redirect.github.com/apps/dependabot))
- [#&#8203;14170](https://redirect.github.com/nestjs/nest/pull/14170)
chore(deps): bump cross-spawn from 7.0.3 to 7.0.6 in
/sample/24-serve-static
([@&#8203;dependabot\[bot\]](https://redirect.github.com/apps/dependabot))
- [#&#8203;14169](https://redirect.github.com/nestjs/nest/pull/14169)
chore(deps): bump cross-spawn from 7.0.3 to 7.0.6 in /sample/15-mvc
([@&#8203;dependabot\[bot\]](https://redirect.github.com/apps/dependabot))
- [#&#8203;14164](https://redirect.github.com/nestjs/nest/pull/14164)
chore(deps): bump cross-spawn from 7.0.3 to 7.0.6 in /sample/01-cats-app
([@&#8203;dependabot\[bot\]](https://redirect.github.com/apps/dependabot))
- [#&#8203;14167](https://redirect.github.com/nestjs/nest/pull/14167)
chore(deps-dev): bump
[@&#8203;typescript-eslint/eslint-plugin](https://redirect.github.com/typescript-eslint/eslint-plugin)
from 8.14.0 to 8.15.0
([@&#8203;dependabot\[bot\]](https://redirect.github.com/apps/dependabot))
- [#&#8203;14161](https://redirect.github.com/nestjs/nest/pull/14161)
chore(deps): bump cross-spawn from 7.0.3 to 7.0.5 in
/sample/25-dynamic-modules
([@&#8203;dependabot\[bot\]](https://redirect.github.com/apps/dependabot))
- [#&#8203;14159](https://redirect.github.com/nestjs/nest/pull/14159)
chore(deps): bump cross-spawn from 7.0.3 to 7.0.5 in
/sample/33-graphql-mercurius
([@&#8203;dependabot\[bot\]](https://redirect.github.com/apps/dependabot))
- [#&#8203;13632](https://redirect.github.com/nestjs/nest/pull/13632)
fix(deps): update dependency mysql2 to v3.9.8 \[security]
([@&#8203;renovate\[bot\]](https://redirect.github.com/apps/renovate))
- [#&#8203;14151](https://redirect.github.com/nestjs/nest/pull/14151)
chore(deps): bump cross-spawn from 7.0.3 to 7.0.5 in
/sample/27-scheduling
([@&#8203;dependabot\[bot\]](https://redirect.github.com/apps/dependabot))
- [#&#8203;14155](https://redirect.github.com/nestjs/nest/pull/14155)
build(sample): replace cli-color with smaller and faster ansis
([@&#8203;webdiscus](https://redirect.github.com/webdiscus))
- [#&#8203;14146](https://redirect.github.com/nestjs/nest/pull/14146)
chore(deps): bump cookie and
[@&#8203;nestjs/platform-express](https://redirect.github.com/nestjs/platform-express)
in /sample/28-sse
([@&#8203;dependabot\[bot\]](https://redirect.github.com/apps/dependabot))
- [#&#8203;14149](https://redirect.github.com/nestjs/nest/pull/14149)
chore(deps): bump cross-spawn from 7.0.3 to 7.0.5 in
/sample/32-graphql-federation-schema-first/gateway
([@&#8203;dependabot\[bot\]](https://redirect.github.com/apps/dependabot))
- [#&#8203;12995](https://redirect.github.com/nestjs/nest/pull/12995)
chore(deps): update dependency supertest to v6.3.4
([@&#8203;renovate\[bot\]](https://redirect.github.com/apps/renovate))
- [#&#8203;12815](https://redirect.github.com/nestjs/nest/pull/12815)
chore(deps): update dependency
[@&#8203;types/node](https://redirect.github.com/types/node) to v20.17.6
([@&#8203;renovate\[bot\]](https://redirect.github.com/apps/renovate))
- [#&#8203;14147](https://redirect.github.com/nestjs/nest/pull/14147)
chore: upgrade deps
([@&#8203;kamilmysliwiec](https://redirect.github.com/kamilmysliwiec))
- [#&#8203;14144](https://redirect.github.com/nestjs/nest/pull/14144)
chore(deps): bump cookie, light-my-request and
[@&#8203;nestjs/platform-fastify](https://redirect.github.com/nestjs/platform-fastify)
in /sample/33-graphql-mercurius
([@&#8203;dependabot\[bot\]](https://redirect.github.com/apps/dependabot))
-   `platform-fastify`
- [#&#8203;14191](https://redirect.github.com/nestjs/nest/pull/14191)
chore(deps): bump light-my-request from 6.1.0 to 6.3.0
([@&#8203;dependabot\[bot\]](https://redirect.github.com/apps/dependabot))

##### Committers: 7

- Kamil Mysliwiec
([@&#8203;kamilmysliwiec](https://redirect.github.com/kamilmysliwiec))
- Micael Levi L. Cavalcante
([@&#8203;micalevisk](https://redirect.github.com/micalevisk))
- Patrick Acioli
([@&#8203;patrickacioli](https://redirect.github.com/patrickacioli))
-   [@&#8203;DylanVeldra](https://redirect.github.com/DylanVeldra)
-   [@&#8203;webdiscus](https://redirect.github.com/webdiscus)
-   cain ([@&#8203;gunb0s](https://redirect.github.com/gunb0s))
-   sapenlei ([@&#8203;sapenlei](https://redirect.github.com/sapenlei))

###
[`v10.4.8`](https://redirect.github.com/nestjs/nest/releases/tag/v10.4.8)

[Compare
Source](https://redirect.github.com/nestjs/nest/compare/v10.4.7...v10.4.8)

##### v10.4.8 (2024-11-15)

##### Bug fixes

-   `microservices`
- [#&#8203;14059](https://redirect.github.com/nestjs/nest/pull/14059)
fix(microservices): include discarded rmq client options
([@&#8203;v-sum](https://redirect.github.com/v-sum))
- [#&#8203;14132](https://redirect.github.com/nestjs/nest/pull/14132)
fix(microservices): no messages emitted with mqtt when qos set
([@&#8203;kamilmysliwiec](https://redirect.github.com/kamilmysliwiec))
-   `core`
- [#&#8203;14133](https://redirect.github.com/nestjs/nest/pull/14133)
fix(core): flaky durable provider, remove instance on error
([@&#8203;kamilmysliwiec](https://redirect.github.com/kamilmysliwiec))

##### Enhancements

-   `core`
- [#&#8203;14143](https://redirect.github.com/nestjs/nest/pull/14143)
feat(core): expose listening stream from http adapter host
([@&#8203;kamilmysliwiec](https://redirect.github.com/kamilmysliwiec))
- [#&#8203;14139](https://redirect.github.com/nestjs/nest/pull/14139)
chore(core): defer application shutdown until init finishes
([@&#8203;mksony](https://redirect.github.com/mksony))

##### Committers: 3

- Kamil Mysliwiec
([@&#8203;kamilmysliwiec](https://redirect.github.com/kamilmysliwiec))
-   Max ([@&#8203;mksony](https://redirect.github.com/mksony))
- Vasile Sumanschi ([@&#8203;v-sum](https://redirect.github.com/v-sum))

###
[`v10.4.7`](https://redirect.github.com/nestjs/nest/compare/v10.4.6...v10.4.7)

[Compare
Source](https://redirect.github.com/nestjs/nest/compare/v10.4.6...v10.4.7)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about these
updates again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/open-feature/js-sdk).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS4xMjUuMSIsInVwZGF0ZWRJblZlciI6IjM5LjEyNS4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-30 21:42:43 +00:00
renovate[bot] 006698f7dd
chore(deps): update dependency @types/node to v20.17.16 (#1111)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[@types/node](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node)
([source](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node))
| [`20.17.1` ->
`20.17.16`](https://renovatebot.com/diffs/npm/@types%2fnode/20.17.1/20.17.16)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2fnode/20.17.16?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2fnode/20.17.16?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2fnode/20.17.1/20.17.16?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2fnode/20.17.1/20.17.16?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/open-feature/js-sdk).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS41OC4xIiwidXBkYXRlZEluVmVyIjoiMzkuMTI1LjEiLCJ0YXJnZXRCcmFuY2giOiJtYWluIiwibGFiZWxzIjpbXX0=-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-30 21:42:33 +00:00
renovate[bot] 59ef7a3bb1
chore(deps): update dependency esbuild to v0.24.2 (#1123)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [esbuild](https://redirect.github.com/evanw/esbuild) | [`0.24.0` ->
`0.24.2`](https://renovatebot.com/diffs/npm/esbuild/0.24.0/0.24.2) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/esbuild/0.24.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/esbuild/0.24.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/esbuild/0.24.0/0.24.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/esbuild/0.24.0/0.24.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>evanw/esbuild (esbuild)</summary>

###
[`v0.24.2`](https://redirect.github.com/evanw/esbuild/blob/HEAD/CHANGELOG.md#0242)

[Compare
Source](https://redirect.github.com/evanw/esbuild/compare/v0.24.1...v0.24.2)

- Fix regression with `--define` and `import.meta`
([#&#8203;4010](https://redirect.github.com/evanw/esbuild/issues/4010),
[#&#8203;4012](https://redirect.github.com/evanw/esbuild/issues/4012),
[#&#8203;4013](https://redirect.github.com/evanw/esbuild/pull/4013))

The previous change in version 0.24.1 to use a more expression-like
parser for `define` values to allow quoted property names introduced a
regression that removed the ability to use `--define:import.meta=...`.
Even though `import` is normally a keyword that can't be used as an
identifier, ES modules special-case the `import.meta` expression to
behave like an identifier anyway. This change fixes the regression.

This fix was contributed by
[@&#8203;sapphi-red](https://redirect.github.com/sapphi-red).

###
[`v0.24.1`](https://redirect.github.com/evanw/esbuild/blob/HEAD/CHANGELOG.md#0241)

[Compare
Source](https://redirect.github.com/evanw/esbuild/compare/v0.24.0...v0.24.1)

- Allow `es2024` as a target in `tsconfig.json`
([#&#8203;4004](https://redirect.github.com/evanw/esbuild/issues/4004))

TypeScript recently [added
`es2024`](https://devblogs.microsoft.com/typescript/announcing-typescript-5-7/#support-for---target-es2024-and---lib-es2024)
as a compilation target, so esbuild now supports this in the `target`
field of `tsconfig.json` files, such as in the following configuration
file:

    ```json
    {
      "compilerOptions": {
        "target": "ES2024"
      }
    }
    ```

As a reminder, the only thing that esbuild uses this field for is
determining whether or not to use legacy TypeScript behavior for class
fields. You can read more in [the
documentation](https://esbuild.github.io/content-types/#tsconfig-json).

This fix was contributed by
[@&#8203;billyjanitsch](https://redirect.github.com/billyjanitsch).

-   Allow automatic semicolon insertion after `get`/`set`

This change fixes a grammar bug in the parser that incorrectly treated
the following code as a syntax error:

    ```ts
    class Foo {
      get
      *x() {}
      set
      *y() {}
    }
    ```

The above code will be considered valid starting with this release. This
change to esbuild follows a [similar change to
TypeScript](https://redirect.github.com/microsoft/TypeScript/pull/60225)
which will allow this syntax starting with TypeScript 5.7.

- Allow quoted property names in `--define` and `--pure`
([#&#8203;4008](https://redirect.github.com/evanw/esbuild/issues/4008))

The `define` and `pure` API options now accept identifier expressions
containing quoted property names. Previously all identifiers in the
identifier expression had to be bare identifiers. This change now makes
`--define` and `--pure` consistent with `--global-name`, which already
supported quoted property names. For example, the following is now
possible:

    ```js
    // The following code now transforms to "return true;\n"
    console.log(esbuild.transformSync(
      `return process.env['SOME-TEST-VAR']`,
      { define: { 'process.env["SOME-TEST-VAR"]': 'true' } },
    ))
    ```

Note that if you're passing values like this on the command line using
esbuild's `--define` flag, then you'll need to know how to escape quote
characters for your shell. You may find esbuild's JavaScript API more
ergonomic and portable than writing shell code.

- Minify empty `try`/`catch`/`finally` blocks
([#&#8203;4003](https://redirect.github.com/evanw/esbuild/issues/4003))

With this release, esbuild will now attempt to minify empty `try`
blocks:

    ```js
    // Original code
    try {} catch { foo() } finally { bar() }

    // Old output (with --minify)
    try{}catch{foo()}finally{bar()}

    // New output (with --minify)
    bar();
    ```

    This can sometimes expose additional minification opportunities.

- Include `entryPoint` metadata for the `copy` loader
([#&#8203;3985](https://redirect.github.com/evanw/esbuild/issues/3985))

Almost all entry points already include a `entryPoint` field in the
`outputs` map in esbuild's build metadata. However, this wasn't the case
for the `copy` loader as that loader is a special-case that doesn't
behave like other loaders. This release adds the `entryPoint` field in
this case.

- Source mappings may now contain `null` entries
([#&#8203;3310](https://redirect.github.com/evanw/esbuild/issues/3310),
[#&#8203;3878](https://redirect.github.com/evanw/esbuild/issues/3878))

With this change, sources that result in an empty source map may now
emit a `null` source mapping (i.e. one with a generated position but
without a source index or original position). This change improves
source map accuracy by fixing a problem where minified code from a
source without any source mappings could potentially still be associated
with a mapping from another source file earlier in the generated output
on the same minified line. It manifests as nonsensical files in source
mapped stack traces. Now the `null` mapping "resets" the source map so
that any lookups into the minified code without any mappings resolves to
`null` (which appears as the output file in stack traces) instead of the
incorrect source file.

This change shouldn't affect anything in most situations. I'm only
mentioning it in the release notes in case it introduces a bug with
source mapping. It's part of a work-in-progress future feature that will
let you omit certain unimportant files from the generated source map to
reduce source map size.

- Avoid using the parent directory name for determinism
([#&#8203;3998](https://redirect.github.com/evanw/esbuild/issues/3998))

To make generated code more readable, esbuild includes the name of the
source file when generating certain variable names within the file.
Specifically bundling a CommonJS file generates a variable to store the
lazily-evaluated module initializer. However, if a file is named
`index.js` (or with a different extension), esbuild will use the name of
the parent directory instead for a better name (since many packages have
files all named `index.js` but have unique directory names).

This is problematic when the bundle entry point is named `index.js` and
the parent directory name is non-deterministic (e.g. a temporary
directory created by a build script). To avoid non-determinism in
esbuild's output, esbuild will now use `index` instead of the parent
directory in this case. Specifically this will happen if the parent
directory is equal to esbuild's `outbase` API option, which defaults to
the [lowest common
ancestor](https://en.wikipedia.org/wiki/Lowest_common_ancestor) of all
user-specified entry point paths.

- Experimental support for esbuild on NetBSD
([#&#8203;3974](https://redirect.github.com/evanw/esbuild/pull/3974))

With this release, esbuild now has a published binary executable for
[NetBSD](https://www.netbsd.org/) in the
[`@esbuild/netbsd-arm64`](https://www.npmjs.com/package/@&#8203;esbuild/netbsd-arm64)
npm package, and esbuild's installer has been modified to attempt to use
it when on NetBSD. Hopefully this makes installing esbuild via npm work
on NetBSD. This change was contributed by
[@&#8203;bsiegert](https://redirect.github.com/bsiegert).

⚠️ Note: NetBSD is not one of [Node's supported
platforms](https://nodejs.org/api/process.html#process_process_platform),
so installing esbuild may or may not work on NetBSD depending on how
Node has been patched. This is not a problem with esbuild. ⚠️

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/open-feature/js-sdk).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS4xMjUuMSIsInVwZGF0ZWRJblZlciI6IjM5LjEyNS4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-30 16:40:11 -05:00
renovate[bot] 952c43f3b8
chore(deps): update angular-eslint monorepo to v18.4.3 (#1098)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[@angular-eslint/builder](https://redirect.github.com/angular-eslint/angular-eslint)
([source](https://redirect.github.com/angular-eslint/angular-eslint/tree/HEAD/packages/builder))
| [`18.4.0` ->
`18.4.3`](https://renovatebot.com/diffs/npm/@angular-eslint%2fbuilder/18.4.0/18.4.3)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@angular-eslint%2fbuilder/18.4.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@angular-eslint%2fbuilder/18.4.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@angular-eslint%2fbuilder/18.4.0/18.4.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@angular-eslint%2fbuilder/18.4.0/18.4.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
|
[@angular-eslint/eslint-plugin](https://redirect.github.com/angular-eslint/angular-eslint)
([source](https://redirect.github.com/angular-eslint/angular-eslint/tree/HEAD/packages/eslint-plugin))
| [`18.4.0` ->
`18.4.3`](https://renovatebot.com/diffs/npm/@angular-eslint%2feslint-plugin/18.4.0/18.4.3)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@angular-eslint%2feslint-plugin/18.4.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@angular-eslint%2feslint-plugin/18.4.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@angular-eslint%2feslint-plugin/18.4.0/18.4.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@angular-eslint%2feslint-plugin/18.4.0/18.4.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
|
[@angular-eslint/eslint-plugin-template](https://redirect.github.com/angular-eslint/angular-eslint)
([source](https://redirect.github.com/angular-eslint/angular-eslint/tree/HEAD/packages/eslint-plugin-template))
| [`18.4.0` ->
`18.4.3`](https://renovatebot.com/diffs/npm/@angular-eslint%2feslint-plugin-template/18.4.0/18.4.3)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@angular-eslint%2feslint-plugin-template/18.4.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@angular-eslint%2feslint-plugin-template/18.4.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@angular-eslint%2feslint-plugin-template/18.4.0/18.4.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@angular-eslint%2feslint-plugin-template/18.4.0/18.4.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
|
[@angular-eslint/schematics](https://redirect.github.com/angular-eslint/angular-eslint)
([source](https://redirect.github.com/angular-eslint/angular-eslint/tree/HEAD/packages/schematics))
| [`18.4.0` ->
`18.4.3`](https://renovatebot.com/diffs/npm/@angular-eslint%2fschematics/18.4.0/18.4.3)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@angular-eslint%2fschematics/18.4.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@angular-eslint%2fschematics/18.4.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@angular-eslint%2fschematics/18.4.0/18.4.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@angular-eslint%2fschematics/18.4.0/18.4.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
|
[@angular-eslint/template-parser](https://redirect.github.com/angular-eslint/angular-eslint)
([source](https://redirect.github.com/angular-eslint/angular-eslint/tree/HEAD/packages/template-parser))
| [`18.4.0` ->
`18.4.3`](https://renovatebot.com/diffs/npm/@angular-eslint%2ftemplate-parser/18.4.0/18.4.3)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@angular-eslint%2ftemplate-parser/18.4.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@angular-eslint%2ftemplate-parser/18.4.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@angular-eslint%2ftemplate-parser/18.4.0/18.4.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@angular-eslint%2ftemplate-parser/18.4.0/18.4.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>angular-eslint/angular-eslint
(@&#8203;angular-eslint/builder)</summary>

###
[`v18.4.3`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/builder/CHANGELOG.md#1843-2024-11-29)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v18.4.2...v18.4.3)

##### 🩹 Fixes

- yarn pnp issues
([#&#8203;2143](https://redirect.github.com/angular-eslint/angular-eslint/pull/2143))

##### ❤️ Thank You

- James Henry
[@&#8203;JamesHenry](https://redirect.github.com/JamesHenry)

###
[`v18.4.2`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/builder/CHANGELOG.md#1842-2024-11-23)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v18.4.1...v18.4.2)

This was a version bump only for builder to align it with other
projects, there were no code changes.

###
[`v18.4.1`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/builder/CHANGELOG.md#1841-2024-11-18)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v18.4.0...v18.4.1)

This was a version bump only for builder to align it with other
projects, there were no code changes.

</details>

<details>
<summary>angular-eslint/angular-eslint
(@&#8203;angular-eslint/eslint-plugin)</summary>

###
[`v18.4.3`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#1843-2024-11-29)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v18.4.2...v18.4.3)

This was a version bump only for eslint-plugin to align it with other
projects, there were no code changes.

###
[`v18.4.2`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#1842-2024-11-23)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v18.4.1...v18.4.2)

##### 🩹 Fixes

- **eslint-plugin:** fix placement of lifecycle interface for subclasses
([#&#8203;1965](https://redirect.github.com/angular-eslint/angular-eslint/pull/1965))
- **eslint-plugin:** handle `output()` and `input()` functions in
various rules
([#&#8203;2098](https://redirect.github.com/angular-eslint/angular-eslint/pull/2098))

##### ❤️ Thank You

-   Aleksandr Martirosyan
-   Dave [@&#8203;reduckted](https://redirect.github.com/reduckted)

###
[`v18.4.1`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#1841-2024-11-18)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v18.4.0...v18.4.1)

This was a version bump only for eslint-plugin to align it with other
projects, there were no code changes.

</details>

<details>
<summary>angular-eslint/angular-eslint
(@&#8203;angular-eslint/eslint-plugin-template)</summary>

###
[`v18.4.3`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/eslint-plugin-template/CHANGELOG.md#1843-2024-11-29)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v18.4.2...v18.4.3)

This was a version bump only for eslint-plugin-template to align it with
other projects, there were no code changes.

###
[`v18.4.2`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/eslint-plugin-template/CHANGELOG.md#1842-2024-11-23)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v18.4.1...v18.4.2)

This was a version bump only for eslint-plugin-template to align it with
other projects, there were no code changes.

###
[`v18.4.1`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/eslint-plugin-template/CHANGELOG.md#1841-2024-11-18)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v18.4.0...v18.4.1)

This was a version bump only for eslint-plugin-template to align it with
other projects, there were no code changes.

</details>

<details>
<summary>angular-eslint/angular-eslint
(@&#8203;angular-eslint/schematics)</summary>

###
[`v18.4.3`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/schematics/CHANGELOG.md#1843-2024-11-29)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v18.4.2...v18.4.3)

##### 🩹 Fixes

- update typescript-eslint packages to v8.16.0
([#&#8203;2135](https://redirect.github.com/angular-eslint/angular-eslint/pull/2135))
- yarn pnp issues
([#&#8203;2143](https://redirect.github.com/angular-eslint/angular-eslint/pull/2143))

##### ❤️ Thank You

- James Henry
[@&#8203;JamesHenry](https://redirect.github.com/JamesHenry)

###
[`v18.4.2`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/schematics/CHANGELOG.md#1842-2024-11-23)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v18.4.1...v18.4.2)

This was a version bump only for schematics to align it with other
projects, there were no code changes.

###
[`v18.4.1`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/schematics/CHANGELOG.md#1841-2024-11-18)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v18.4.0...v18.4.1)

##### 🩹 Fixes

- update dependency ignore to v6
([#&#8203;2047](https://redirect.github.com/angular-eslint/angular-eslint/pull/2047))

</details>

<details>
<summary>angular-eslint/angular-eslint
(@&#8203;angular-eslint/template-parser)</summary>

###
[`v18.4.3`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/template-parser/CHANGELOG.md#1843-2024-11-29)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v18.4.2...v18.4.3)

This was a version bump only for template-parser to align it with other
projects, there were no code changes.

###
[`v18.4.2`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/template-parser/CHANGELOG.md#1842-2024-11-23)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v18.4.1...v18.4.2)

This was a version bump only for template-parser to align it with other
projects, there were no code changes.

###
[`v18.4.1`](https://redirect.github.com/angular-eslint/angular-eslint/blob/HEAD/packages/template-parser/CHANGELOG.md#1841-2024-11-18)

[Compare
Source](https://redirect.github.com/angular-eslint/angular-eslint/compare/v18.4.0...v18.4.1)

This was a version bump only for template-parser to align it with other
projects, there were no code changes.

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about these
updates again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/open-feature/js-sdk).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS40Mi40IiwidXBkYXRlZEluVmVyIjoiMzkuNDIuNCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-28 19:41:25 +00:00
renovate[bot] b99fc01a6d
chore(deps): update dependency @types/react to v18.3.18 (#1112)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[@types/react](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/react)
([source](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react))
| [`18.3.12` ->
`18.3.18`](https://renovatebot.com/diffs/npm/@types%2freact/18.3.12/18.3.18)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2freact/18.3.18?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2freact/18.3.18?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2freact/18.3.12/18.3.18?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2freact/18.3.12/18.3.18?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/open-feature/js-sdk).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS41OC4xIiwidXBkYXRlZEluVmVyIjoiMzkuODAuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-28 19:41:08 +00:00
Will C. 4a6b860544
feat: export useOpenFeatureClientStatus hook (#1082)
<!-- Please use this template for your pull request. -->
<!-- Please use the sections that you need and delete other sections -->

## This PR
<!-- add the description of the PR here -->

exposes the internal open feature client status hook so developers can
act on non-ready resolved states

### Related Issues
<!-- add here the GitHub issue that this PR resolves if applicable -->

Fixes #1036

### Notes
<!-- any additional notes for this PR -->

### Follow-up Tasks
<!-- anything that is related to this PR but not done here should be
noted under this section -->
<!-- if there is a need for a new issue, please link it here -->

### How to test
<!-- if applicable, add testing instructions under this section -->

---------

Signed-off-by: William Chou <iam@willchou.dev>
Signed-off-by: Will Chou <w.chou06@gmail.com>
Co-authored-by: Lukas Reining <lukas.reining@codecentric.de>
2025-01-28 19:40:48 +00:00
Todd Baert 9e338f2ca3
chore: remove release-as from nest sdk
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
2025-01-07 14:18:46 -05:00
Michael Beemer 0587d8a5da
ci: add node 22 to test matrix (#1115)
## This PR

- adds node 22 to the test matrix

### Notes

Node 22 is the current active LTS version. We still should target Node
18 but test Node 22.

Signed-off-by: Michael Beemer <beeme1mr@users.noreply.github.com>
2025-01-03 08:56:42 -05:00
OpenFeature Bot 52c8de630b
chore(main): release react-sdk 0.4.10 (#1105)
🤖 I have created a release *beep* *boop*
---


##
[0.4.10](https://github.com/open-feature/js-sdk/compare/react-sdk-v0.4.9...react-sdk-v0.4.10)
(2024-12-18)


### 🔄 Refactoring

* export public option types
([#1101](https://github.com/open-feature/js-sdk/issues/1101))
([16321c3](16321c31f2))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Signed-off-by: OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>
Co-authored-by: Michael Beemer <beeme1mr@users.noreply.github.com>
2024-12-18 13:58:49 -05:00
OpenFeature Bot edab97019a
chore(main): release server-sdk 1.17.0 (#1104)
🤖 I have created a release *beep* *boop*
---


##
[1.17.0](https://github.com/open-feature/js-sdk/compare/server-sdk-v1.16.2...server-sdk-v1.17.0)
(2024-12-18)

### ⚠ BREAKING CHANGES

The signature of the `finally` hook stage has been changed. The
signature now includes the `evaluation details`, as per the [OpenFeature
specification](https://openfeature.dev/specification/sections/hooks#requirement-438).
Note that since hooks are still `experimental,` this does not constitute
a change requiring a new major version. To migrate, update any hook that
implements the `finally` stage to accept `evaluation details` as the
second argument.

* add evaluation details to finally hook
([#1087](https://github.com/open-feature/js-sdk/issues/1087))
([2135254](2135254c4b))

###  New Features

* add evaluation details to finally hook
([#1087](https://github.com/open-feature/js-sdk/issues/1087))
([2135254](2135254c4b))


### 📚 Documentation

* fix comment in README for Hook’s after method
([#1103](https://github.com/open-feature/js-sdk/issues/1103))
([e335615](e3356157d5))


### 🔄 Refactoring

* improve track interface for providers
([#1100](https://github.com/open-feature/js-sdk/issues/1100))
([5e5b160](5e5b160221))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

---------

Signed-off-by: OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>
Signed-off-by: Michael Beemer <beeme1mr@users.noreply.github.com>
Co-authored-by: Michael Beemer <beeme1mr@users.noreply.github.com>
2024-12-18 13:53:23 -05:00
OpenFeature Bot 79de7cabd3
chore(main): release web-sdk 1.4.0 (#1106)
🤖 I have created a release *beep* *boop*
---


##
[1.4.0](https://github.com/open-feature/js-sdk/compare/web-sdk-v1.3.2...web-sdk-v1.4.0)
(2024-12-18)

### ⚠ BREAKING CHANGES

The signature of the `finally` hook stage has been changed. The
signature now includes the `evaluation details`, as per the [OpenFeature
specification](https://openfeature.dev/specification/sections/hooks#requirement-438).
Note that since hooks are still `experimental,` this does not constitute
a change requiring a new major version. To migrate, update any hook that
implements the `finally` stage to accept `evaluation details` as the
second argument.

* add evaluation details to finally hook
([#1087](https://github.com/open-feature/js-sdk/issues/1087))
([2135254](2135254c4b))

###  New Features

* add evaluation details to finally hook
([#1087](https://github.com/open-feature/js-sdk/issues/1087))
([2135254](2135254c4b))


### 📚 Documentation

* fix comment in README for Hook’s after method
([#1102](https://github.com/open-feature/js-sdk/issues/1102))
([ba8d1ae](ba8d1aeec8))


### 🔄 Refactoring

* improve track interface for providers
([#1100](https://github.com/open-feature/js-sdk/issues/1100))
([5e5b160](5e5b160221))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

---------

Signed-off-by: OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>
Signed-off-by: Michael Beemer <beeme1mr@users.noreply.github.com>
Co-authored-by: Michael Beemer <beeme1mr@users.noreply.github.com>
2024-12-18 13:48:25 -05:00
OpenFeature Bot bd26d0a234
chore(main): release core 1.6.0 (#1107)
🤖 I have created a release *beep* *boop*
---


##
[1.6.0](https://github.com/open-feature/js-sdk/compare/core-v1.5.0...core-v1.6.0)
(2024-12-12)

### ⚠ BREAKING CHANGES

The signature of the `finally` hook stage has been changed. The
signature now includes the `evaluation details`, as per the [OpenFeature
specification](https://openfeature.dev/specification/sections/hooks#requirement-438).
Note that since hooks are still `experimental,` this does not constitute
a change requiring a new major version. To migrate, update any hook that
implements the `finally` stage to accept `evaluation details` as the
second argument.

* add evaluation details to finally hook
([#1087](https://github.com/open-feature/js-sdk/issues/1087))
([2135254](2135254c4b))

###  New Features

* add evaluation details to finally hook
([#1087](https://github.com/open-feature/js-sdk/issues/1087))
([2135254](2135254c4b))


### 🔄 Refactoring

* improve track interface for providers
([#1100](https://github.com/open-feature/js-sdk/issues/1100))
([5e5b160](5e5b160221))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

---------

Signed-off-by: OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>
Signed-off-by: Michael Beemer <beeme1mr@users.noreply.github.com>
Co-authored-by: Michael Beemer <beeme1mr@users.noreply.github.com>
2024-12-18 18:40:39 +00:00
renovate[bot] 38d9a3bee3
chore(deps): update typescript-eslint monorepo to v7.18.0 (#1065)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[@typescript-eslint/eslint-plugin](https://typescript-eslint.io/packages/eslint-plugin)
([source](https://redirect.github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin))
| [`7.11.0` ->
`7.18.0`](https://renovatebot.com/diffs/npm/@typescript-eslint%2feslint-plugin/7.11.0/7.18.0)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@typescript-eslint%2feslint-plugin/7.18.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@typescript-eslint%2feslint-plugin/7.18.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@typescript-eslint%2feslint-plugin/7.11.0/7.18.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@typescript-eslint%2feslint-plugin/7.11.0/7.18.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
|
[@typescript-eslint/parser](https://typescript-eslint.io/packages/parser)
([source](https://redirect.github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser))
| [`7.11.0` ->
`7.18.0`](https://renovatebot.com/diffs/npm/@typescript-eslint%2fparser/7.11.0/7.18.0)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@typescript-eslint%2fparser/7.18.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@typescript-eslint%2fparser/7.18.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@typescript-eslint%2fparser/7.11.0/7.18.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@typescript-eslint%2fparser/7.11.0/7.18.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>typescript-eslint/typescript-eslint
(@&#8203;typescript-eslint/eslint-plugin)</summary>

###
[`v7.18.0`](https://redirect.github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#7180-2024-07-29)

[Compare
Source](https://redirect.github.com/typescript-eslint/typescript-eslint/compare/v7.17.0...v7.18.0)

##### 🩹 Fixes

- **eslint-plugin:** \[no-unnecessary-type-assertion] prevent runtime
error when asserting a variable declared in default TS lib

- **eslint-plugin:** \[unbound-method] report on destructuring in
function parameters

- **eslint-plugin:** \[no-duplicate-type-constituents] shouldn't report
on error types

- **eslint-plugin:** \[strict-boolean-expressions] support branded
booleans

##### ❤️  Thank You

-   auvred
-   Oliver Salzburg
-   Vinccool96
-   Yukihiro Hasegawa

You can read about our [versioning
strategy](https://main--typescript-eslint.netlify.app/users/versioning)
and
[releases](https://main--typescript-eslint.netlify.app/users/releases)
on our website.

###
[`v7.17.0`](https://redirect.github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#7170-2024-07-22)

[Compare
Source](https://redirect.github.com/typescript-eslint/typescript-eslint/compare/v7.16.1...v7.17.0)

##### 🚀 Features

- **eslint-plugin:** backport no-unsafe-function type,
no-wrapper-object-types from v8 to v7

- **eslint-plugin:** \[return-await] add option to report in
error-handling scenarios only, and deprecate "never"

##### 🩹 Fixes

- **eslint-plugin:** \[no-floating-promises] check top-level type
assertions (and more)

- **eslint-plugin:** \[strict-boolean-expressions] consider assertion
function argument a boolean context

- **eslint-plugin:** \[no-unnecessary-condition] false positive on
optional private field

##### ❤️  Thank You

-   Armano
-   Josh Goldberg 
-   Kirk Waiblinger
-   StyleShit

You can read about our [versioning
strategy](https://main--typescript-eslint.netlify.app/users/versioning)
and
[releases](https://main--typescript-eslint.netlify.app/users/releases)
on our website.

###
[`v7.16.1`](https://redirect.github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#7161-2024-07-15)

[Compare
Source](https://redirect.github.com/typescript-eslint/typescript-eslint/compare/v7.16.0...v7.16.1)

##### 🩹 Fixes

- **eslint-plugin:** \[no-unnecessary-type-parameters] descend into all
parts of mapped types in no-unnecessary-type-parameters

##### ❤️  Thank You

-   Dan Vanderkam

You can read about our [versioning
strategy](https://main--typescript-eslint.netlify.app/users/versioning)
and
[releases](https://main--typescript-eslint.netlify.app/users/releases)
on our website.

###
[`v7.16.0`](https://redirect.github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#7160-2024-07-08)

[Compare
Source](https://redirect.github.com/typescript-eslint/typescript-eslint/compare/v7.15.0...v7.16.0)

##### 🚀 Features

-   **rule-tester:** stricter rule test validations

- **eslint-plugin:** \[no-unnecessary-parameter-property-assignment] add
new rule

- **eslint-plugin:** add support for nested namespaces to
unsafe-member-access

-   **eslint-plugin:** \[no-floating-promises] add checkThenables option

##### 🩹 Fixes

- **deps:** update dependency
[@&#8203;eslint-community/regexpp](https://redirect.github.com/eslint-community/regexpp)
to v4.11.0

- **eslint-plugin:** \[no-floating-promises] add `suggestions` to tests
from
[#&#8203;9263](https://redirect.github.com/typescript-eslint/typescript-eslint/issues/9263)
`checkThenables`

-   **website:** react key error on internal pages of website

- **eslint-plugin:** \[restrict-template-expressions] don't report
tuples if `allowArray` option is enabled

##### ❤️  Thank You

-   Abraham Guo
-   auvred
-   Josh Goldberg 
-   Juan Sanchez
-   Vinccool96
-   YeonJuan
-   Yukihiro Hasegawa

You can read about our [versioning
strategy](https://main--typescript-eslint.netlify.app/users/versioning)
and
[releases](https://main--typescript-eslint.netlify.app/users/releases)
on our website.

###
[`v7.15.0`](https://redirect.github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#7150-2024-07-01)

[Compare
Source](https://redirect.github.com/typescript-eslint/typescript-eslint/compare/v7.14.1...v7.15.0)

##### 🚀 Features

-   **eslint-plugin:** \[array-type] detect `Readonly<string[]>` case

- **eslint-plugin:** back-port new rules around empty object types from
v8

##### 🩹 Fixes

- disable `EXPERIMENTAL_useProjectService` in `disabled-type-checked`
shared config

- **eslint-plugin:** \[no-unsafe-return] differentiate a types-error any
from a true any

- **eslint-plugin:** \[no-unsafe-call] differentiate a types-error any
from a true any

##### ❤️  Thank You

-   auvred
-   Kim Sang Du
-   rgehbt
-   Vinccool96

You can read about our [versioning
strategy](https://main--typescript-eslint.netlify.app/users/versioning)
and
[releases](https://main--typescript-eslint.netlify.app/users/releases)
on our website.

###
[`v7.14.1`](https://redirect.github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#7141-2024-06-24)

[Compare
Source](https://redirect.github.com/typescript-eslint/typescript-eslint/compare/v7.14.0...v7.14.1)

##### 🩹 Fixes

- **eslint-plugin:** \[prefer-nullish-coalescing] treat enums and
literals as their underlying primitive types

- **eslint-plugin:** \[prefer-nullish-coalescing] ensure ternary fix
does not remove parens

##### ❤️  Thank You

-   Jake Bailey

You can read about our [versioning
strategy](https://main--typescript-eslint.netlify.app/users/versioning)
and
[releases](https://main--typescript-eslint.netlify.app/users/releases)
on our website.

###
[`v7.14.0`](https://redirect.github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#7140-2024-06-24)

[Compare
Source](https://redirect.github.com/typescript-eslint/typescript-eslint/compare/v7.13.1...v7.14.0)

##### 🚀 Features

-   support TypeScript 5.5

##### 🩹 Fixes

-   **eslint-plugin:** \[no-extraneous-class] handle abstract members

- **eslint-plugin:** \[prefer-nullish-coalescing] handle intersected
primitive types

-   **eslint-plugin:** \[no-invalid-this] support AccessorProperty

##### ❤️  Thank You

-   Brad Zacher
-   cm-ayf
-   Jake Bailey
-   James Zhan
-   Joshua Chen
-   yoshi2no

You can read about our [versioning
strategy](https://main--typescript-eslint.netlify.app/users/versioning)
and
[releases](https://main--typescript-eslint.netlify.app/users/releases)
on our website.

###
[`v7.13.1`](https://redirect.github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#7131-2024-06-17)

[Compare
Source](https://redirect.github.com/typescript-eslint/typescript-eslint/compare/v7.13.0...v7.13.1)

##### 🩹 Fixes

-   **eslint-plugin:** \[prefer-readonly] refine report locations

- **eslint-plugin:** \[return-await] support explicit resource
management

- **eslint-plugin:** \[no-unsafe-member-access] differentiate a
types-error any from a true any

##### ❤️  Thank You

-   Kirk Waiblinger
-   Yukihiro Hasegawa

You can read about our [versioning
strategy](https://main--typescript-eslint.netlify.app/users/versioning)
and
[releases](https://main--typescript-eslint.netlify.app/users/releases)
on our website.

###
[`v7.13.0`](https://redirect.github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#7130-2024-06-10)

[Compare
Source](https://redirect.github.com/typescript-eslint/typescript-eslint/compare/v7.12.0...v7.13.0)

##### 🚀 Features

- **typescript-estree:** require `import = require()` argument to be a
string literal

- **typescript-estree:** forbid `.body`, `.async`, `.generator` on
`declare function`

- **eslint-plugin:** \[no-dynamic-delete] allow all string literals as
index

##### 🩹 Fixes

- **ast-spec:** function-call-like callee should be Expression not
LeftHandSideExpression

-   **scope-manager:** handle index signature in class

-   **eslint-plugin:** \[init-declarations] refine report locations

- **eslint-plugin:** \[no-base-to-string] make error message more
nuanced

- **eslint-plugin:** \[no-unsafe-assignment] be more specific about
error types

- **eslint-plugin:** \[no-magic-numbers] fix implementation of the
`ignore` option

##### ❤️  Thank You

-   Fotis Papadogeorgopoulos
-   Joshua Chen
-   Kirk Waiblinger
-   Tobiloba Adedeji
-   Vinccool96
-   YeonJuan

You can read about our [versioning
strategy](https://main--typescript-eslint.netlify.app/users/versioning)
and
[releases](https://main--typescript-eslint.netlify.app/users/releases)
on our website.

###
[`v7.12.0`](https://redirect.github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#7120-2024-06-03)

[Compare
Source](https://redirect.github.com/typescript-eslint/typescript-eslint/compare/v7.11.0...v7.12.0)

##### 🚀 Features

- **eslint-plugin:** \[no-useless-template-literals] rename to
`no-useless-template-expression` (deprecate
`no-useless-template-literals`)

-   **rule-tester:** check for parsing errors in suggestion fixes

-   **rule-tester:** port `checkDuplicateTestCases` from ESLint

- **eslint-plugin:** \[no-floating-promises] add option
'allowForKnownSafePromises'

##### 🩹 Fixes

-   no-useless-template-expression -> no-unnecessary-template-expression

- **eslint-plugin:** \[no-unnecessary-type-assertion] combine template
literal check with `const` variable check

- **eslint-plugin:** \[dot-notation] fix false positive when accessing
private/protected property with optional chaining

- **eslint-plugin:** \[explicit-member-accessibility] refine report
locations

- **eslint-plugin:** \[no-unnecessary-type-assertion] declares are
always defined, so always check `declare`s

- **eslint-plugin:** \[prefer-literal-enum-member] allow using member it
self on allowBitwiseExpressions

- **eslint-plugin:** \[return-await] clean up in-try-catch detection and
make autofixes safe

- **eslint-plugin:** \[member-ordering] also TSMethodSignature can be
get/set

##### ❤️  Thank You

-   Abraham Guo
-   Han Yeong-woo
-   Joshua Chen
-   Kim Sang Du
-   Kirk Waiblinger
-   YeonJuan

You can read about our [versioning
strategy](https://main--typescript-eslint.netlify.app/users/versioning)
and
[releases](https://main--typescript-eslint.netlify.app/users/releases)
on our website.

</details>

<details>
<summary>typescript-eslint/typescript-eslint
(@&#8203;typescript-eslint/parser)</summary>

###
[`v7.18.0`](https://redirect.github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/parser/CHANGELOG.md#7180-2024-07-29)

[Compare
Source](https://redirect.github.com/typescript-eslint/typescript-eslint/compare/v7.17.0...v7.18.0)

This was a version bump only for parser to align it with other projects,
there were no code changes.

You can read about our [versioning
strategy](https://main--typescript-eslint.netlify.app/users/versioning)
and
[releases](https://main--typescript-eslint.netlify.app/users/releases)
on our website.

###
[`v7.17.0`](https://redirect.github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/parser/CHANGELOG.md#7170-2024-07-22)

[Compare
Source](https://redirect.github.com/typescript-eslint/typescript-eslint/compare/v7.16.1...v7.17.0)

This was a version bump only for parser to align it with other projects,
there were no code changes.

You can read about our [versioning
strategy](https://main--typescript-eslint.netlify.app/users/versioning)
and
[releases](https://main--typescript-eslint.netlify.app/users/releases)
on our website.

###
[`v7.16.1`](https://redirect.github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/parser/CHANGELOG.md#7161-2024-07-15)

[Compare
Source](https://redirect.github.com/typescript-eslint/typescript-eslint/compare/v7.16.0...v7.16.1)

This was a version bump only for parser to align it with other projects,
there were no code changes.

You can read about our [versioning
strategy](https://main--typescript-eslint.netlify.app/users/versioning)
and
[releases](https://main--typescript-eslint.netlify.app/users/releases)
on our website.

###
[`v7.16.0`](https://redirect.github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/parser/CHANGELOG.md#7160-2024-07-08)

[Compare
Source](https://redirect.github.com/typescript-eslint/typescript-eslint/compare/v7.15.0...v7.16.0)

##### 🩹 Fixes

- **deps:** update dependency
[@&#8203;eslint-community/regexpp](https://redirect.github.com/eslint-community/regexpp)
to v4.11.0

-   **website:** react key error on internal pages of website

##### ❤️  Thank You

-   Abraham Guo
-   auvred
-   Josh Goldberg 
-   Juan Sanchez
-   Vinccool96
-   YeonJuan
-   Yukihiro Hasegawa

You can read about our [versioning
strategy](https://main--typescript-eslint.netlify.app/users/versioning)
and
[releases](https://main--typescript-eslint.netlify.app/users/releases)
on our website.

###
[`v7.15.0`](https://redirect.github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/parser/CHANGELOG.md#7150-2024-07-01)

[Compare
Source](https://redirect.github.com/typescript-eslint/typescript-eslint/compare/v7.14.1...v7.15.0)

This was a version bump only for parser to align it with other projects,
there were no code changes.

You can read about our [versioning
strategy](https://main--typescript-eslint.netlify.app/users/versioning)
and
[releases](https://main--typescript-eslint.netlify.app/users/releases)
on our website.

###
[`v7.14.1`](https://redirect.github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/parser/CHANGELOG.md#7141-2024-06-24)

[Compare
Source](https://redirect.github.com/typescript-eslint/typescript-eslint/compare/v7.14.0...v7.14.1)

This was a version bump only for parser to align it with other projects,
there were no code changes.

You can read about our [versioning
strategy](https://main--typescript-eslint.netlify.app/users/versioning)
and
[releases](https://main--typescript-eslint.netlify.app/users/releases)
on our website.

###
[`v7.14.0`](https://redirect.github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/parser/CHANGELOG.md#7140-2024-06-24)

[Compare
Source](https://redirect.github.com/typescript-eslint/typescript-eslint/compare/v7.13.1...v7.14.0)

##### 🚀 Features

-   support TypeScript 5.5

##### ❤️  Thank You

-   Brad Zacher
-   cm-ayf
-   Jake Bailey
-   James Zhan
-   Joshua Chen
-   yoshi2no

You can read about our [versioning
strategy](https://main--typescript-eslint.netlify.app/users/versioning)
and
[releases](https://main--typescript-eslint.netlify.app/users/releases)
on our website.

###
[`v7.13.1`](https://redirect.github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/parser/CHANGELOG.md#7131-2024-06-17)

[Compare
Source](https://redirect.github.com/typescript-eslint/typescript-eslint/compare/v7.13.0...v7.13.1)

This was a version bump only for parser to align it with other projects,
there were no code changes.

You can read about our [versioning
strategy](https://main--typescript-eslint.netlify.app/users/versioning)
and
[releases](https://main--typescript-eslint.netlify.app/users/releases)
on our website.

###
[`v7.13.0`](https://redirect.github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/parser/CHANGELOG.md#7130-2024-06-10)

[Compare
Source](https://redirect.github.com/typescript-eslint/typescript-eslint/compare/v7.12.0...v7.13.0)

##### 🚀 Features

- **parser, typescript-estree:** export withoutProjectParserOptions
utility

##### ❤️  Thank You

-   Fotis Papadogeorgopoulos
-   Joshua Chen
-   Kirk Waiblinger
-   Tobiloba Adedeji
-   Vinccool96
-   YeonJuan

You can read about our [versioning
strategy](https://main--typescript-eslint.netlify.app/users/versioning)
and
[releases](https://main--typescript-eslint.netlify.app/users/releases)
on our website.

###
[`v7.12.0`](https://redirect.github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/parser/CHANGELOG.md#7120-2024-06-03)

[Compare
Source](https://redirect.github.com/typescript-eslint/typescript-eslint/compare/v7.11.0...v7.12.0)

##### 🩹 Fixes

-   **types:** correct typing ParserOptions

##### ❤️  Thank You

-   Abraham Guo
-   Han Yeong-woo
-   Joshua Chen
-   Kim Sang Du
-   Kirk Waiblinger
-   YeonJuan

You can read about our [versioning
strategy](https://main--typescript-eslint.netlify.app/users/versioning)
and
[releases](https://main--typescript-eslint.netlify.app/users/releases)
on our website.

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled because a matching PR was automerged
previously.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about these
updates again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/open-feature/js-sdk).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC4xMzMuMSIsInVwZGF0ZWRJblZlciI6IjM4LjEzMy4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-12 08:51:55 -05:00
Michael Beemer 2135254c4b
feat: add evaluation details to finally hook (#1087)
## This PR

- adds evaluation details to the `finally` stage in hooks.

### Notes

This breaks the signature of the `finally` stages based on [this spec
enhancement](https://github.com/open-feature/spec/pull/280). It is
**not** considered a breaking change to the SDK because hooks are marked
as experimental in the spec, and the change has no impact on known
hooks.

The noteworthy change to the interface is:

```diff
- finally?(hookContext: Readonly<HookContext<T>>, hookHints?: HookHints): HooksReturn;
+ finally?(hookContext: Readonly<HookContext<T>>, evaluationDetails: EvaluationDetails<T>, hookHints?: HookHints): HooksReturn;
```

### Follow-up Tasks

- Update the JS contribs repo

---------

Signed-off-by: Michael Beemer <beeme1mr@users.noreply.github.com>
2024-12-12 13:49:09 +00:00
Michael Beemer 5e5b160221
refactor: improve track interface for providers (#1100)
## This PR

- updates the context and trackingEventDetails on the tracking interface
to not be optional since they're always supplied by the SDK.

### Notes

This is a small QoL improvement for provider devs implementing the
tracking interface.

### How to test

The SDK still compiles, and the tests don't need to be modified.

---------

Signed-off-by: Michael Beemer <beeme1mr@users.noreply.github.com>
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
Co-authored-by: Todd Baert <todd.baert@dynatrace.com>
2024-12-11 20:09:12 +00:00
Christian Llontop ba8d1aeec8
docs: fix comment in README for Hook’s after method (#1102)
## This PR

- Fixes incorrect comment in the README for the Hook implementation's
`after` method.

Signed-off-by: Christian Llontop <me@chrisllontop.com>
Co-authored-by: Todd Baert <todd.baert@dynatrace.com>
2024-12-10 14:13:53 -05:00
Michael Beemer 16321c31f2
refactor: export public option types (#1101)
## This PR

- renames the `shared` folder to `internal` to prevent accident exports
- export public option types

### Notes

This will make it easier for devs who need access to the option types.

---------

Signed-off-by: Michael Beemer <beeme1mr@users.noreply.github.com>
2024-12-10 14:12:17 -05:00
Christian Llontop e3356157d5
docs: fix comment in README for Hook’s after method (#1103)
## This PR

- Fixes incorrect comment in the README for the Hook implementation's
`after` method.

Signed-off-by: Christian Llontop <me@chrisllontop.com>
2024-12-10 14:09:46 -05:00
renovate[bot] d09f5467ea
chore(deps): update dependency @types/uuid to v10 (#1061)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[@types/uuid](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/uuid)
([source](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/uuid))
| [`^9.0.8` ->
`^10.0.0`](https://renovatebot.com/diffs/npm/@types%2fuuid/9.0.8/10.0.0)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2fuuid/10.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2fuuid/10.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2fuuid/9.0.8/10.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2fuuid/9.0.8/10.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/open-feature/js-sdk).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC4xMjAuMSIsInVwZGF0ZWRJblZlciI6IjM4LjEzNS4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-09 09:11:20 -05:00
OpenFeature Bot 3c9f2c6e36
chore(main): release react-sdk 0.4.9 (#1076)
🤖 I have created a release *beep* *boop*
---


##
[0.4.9](https://github.com/open-feature/js-sdk/compare/react-sdk-v0.4.8...react-sdk-v0.4.9)
(2024-12-04)


###  New Features

* re-render if flagsChanged is falsy
([#1095](https://github.com/open-feature/js-sdk/issues/1095))
([78516f4](78516f4181))


### 📚 Documentation

* fix typos, links, and format
([#1075](https://github.com/open-feature/js-sdk/issues/1075))
([418409e](418409e3fa))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Signed-off-by: OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>
2024-12-04 13:36:51 -05:00
Todd Baert 78516f4181
feat: re-render if flagsChanged is falsy (#1095)
Adds an improvement to the React SDK which supports re-renders if the
[flags
changed](https://open-feature.github.io/js-sdk/types/_openfeature_server_sdk.ConfigChangeEvent.html)
array from a provider event is falsy.

Since some providers have no knowledge of flags which are changed, this
allows them to support dynamic re-rendering by not defining this
property. If the prop is null/undefined, we diff all flags... If the
property is explicitly set to an empty array, that means no flags have
changed and the React SDK skips all diff checks.

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
2024-12-04 18:31:56 +00:00
OpenFeature Bot 5ece80e16a
chore(main): release angular-sdk 0.0.9-experimental (#1094)
🤖 I have created a release *beep* *boop*
---


##
[0.0.9-experimental](https://github.com/open-feature/js-sdk/compare/angular-sdk-v0.0.8-experimental...angular-sdk-v0.0.9-experimental)
(2024-11-21)


### 🧹 Chore

* **angular:** add repository to package.json
([#1093](https://github.com/open-feature/js-sdk/issues/1093))
([35f000e](35f000e0f3))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Signed-off-by: OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>
2024-11-21 21:24:23 +01:00
Lukas Reining 35f000e0f3
chore(angular): add repository to package.json (#1093)
<!-- Please use this template for your pull request. -->
<!-- Please use the sections that you need and delete other sections -->

## This PR
<!-- add the description of the PR here -->

- adds this new feature

### Related Issues
<!-- add here the GitHub issue that this PR resolves if applicable -->

Fixes #1234523

### Notes
<!-- any additional notes for this PR -->

### Follow-up Tasks
<!-- anything that is related to this PR but not done here should be
noted under this section -->
<!-- if there is a need for a new issue, please link it here -->

### How to test
<!-- if applicable, add testing instructions under this section -->

Signed-off-by: Lukas Reining <lukas.reining@codecentric.de>
2024-11-21 21:23:19 +01:00
OpenFeature Bot d521f2dd6e
chore(main): release angular-sdk 0.0.8-experimental (#1092)
🤖 I have created a release *beep* *boop*
---


##
[0.0.8-experimental](https://github.com/open-feature/js-sdk/compare/angular-sdk-v0.0.7-experimental...angular-sdk-v0.0.8-experimental)
(2024-11-21)


###  New Features

* Angular SDK
([#997](https://github.com/open-feature/js-sdk/issues/997))
([105fd95](105fd95e34))
* **angular:** add Angular 18 support
([#1063](https://github.com/open-feature/js-sdk/issues/1063))
([e62d6d4](e62d6d4b7e))
* **angular:** add angular 19 to peerDependencies
([4893d6f](4893d6f000))


### 🐛 Bug Fixes

* **angular:** add package description
([#1026](https://github.com/open-feature/js-sdk/issues/1026))
([dc63ca8](dc63ca8b9d))
* **angular:** fix race condition on initialization
([#1052](https://github.com/open-feature/js-sdk/issues/1052))
([12eaa97](12eaa9758d))
* copy license to package correctly
([#1011](https://github.com/open-feature/js-sdk/issues/1011))
([458d278](458d278345))
* fix release of angular sdk
([4a370cc](4a370cc73f))


### 🧹 Chore

* add npm keywords for angular
([#1015](https://github.com/open-feature/js-sdk/issues/1015))
([6b11165](6b11165aa1))
* **main:** release angular-sdk 0.0.1-experimental
([#1003](https://github.com/open-feature/js-sdk/issues/1003))
([ed3aaa4](ed3aaa48c0))
* **main:** release angular-sdk 0.0.1-experimental
([#1010](https://github.com/open-feature/js-sdk/issues/1010))
([eb42c4c](eb42c4c9e6))
* **main:** release angular-sdk 0.0.2-experimental
([#1008](https://github.com/open-feature/js-sdk/issues/1008))
([f74056c](f74056c02b))
* **main:** release angular-sdk 0.0.2-experimental
([#1012](https://github.com/open-feature/js-sdk/issues/1012))
([8bdc164](8bdc16430c))
* **main:** release angular-sdk 0.0.3-experimental
([#1014](https://github.com/open-feature/js-sdk/issues/1014))
([baec2fb](baec2fb350))
* **main:** release angular-sdk 0.0.4-experimental
([#1027](https://github.com/open-feature/js-sdk/issues/1027))
([c1374bb](c1374bb7b3))
* **main:** release angular-sdk 0.0.5-experimental
([#1053](https://github.com/open-feature/js-sdk/issues/1053))
([5636983](56369839b6))
* **main:** release angular-sdk 0.0.6-experimental
([#1064](https://github.com/open-feature/js-sdk/issues/1064))
([7f9001e](7f9001ec0a))
* **main:** release angular-sdk 0.0.7-experimental
([#1088](https://github.com/open-feature/js-sdk/issues/1088))
([6016465](6016465f9a))
* **main:** release angular-sdk 0.0.7-experimental
([#1091](https://github.com/open-feature/js-sdk/issues/1091))
([2a21f4f](2a21f4fd60))


### 📚 Documentation

* **angular:** improve angular readme layout
([#1013](https://github.com/open-feature/js-sdk/issues/1013))
([ee52da9](ee52da9a01))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

---------

Signed-off-by: OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>
Signed-off-by: Lukas Reining <lukas.reining@codecentric.de>
Co-authored-by: Lukas Reining <lukas.reining@codecentric.de>
2024-11-21 21:15:34 +01:00
OpenFeature Bot 2a21f4fd60
chore(main): release angular-sdk 0.0.7-experimental (#1091)
rereleases angular 0.0.7

---------

Signed-off-by: OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>
Signed-off-by: Lukas Reining <lukas.reining@codecentric.de>
Co-authored-by: Lukas Reining <lukas.reining@codecentric.de>
2024-11-21 21:11:05 +01:00
Michael Beemer 39da1a9ba1
ci: add id token write permissions (#1090)
Signed-off-by: Michael Beemer <beeme1mr@users.noreply.github.com>
2024-11-21 14:16:19 -05:00
OpenFeature Bot 6016465f9a
chore(main): release angular-sdk 0.0.7-experimental (#1088)
🤖 I have created a release *beep* *boop*
---


##
[0.0.7-experimental](https://github.com/open-feature/js-sdk/compare/angular-sdk-v0.0.6-experimental...angular-sdk-v0.0.7-experimental)
(2024-11-21)


###  New Features

* **angular:** add angular 19 to peerDependencies
([4893d6f](4893d6f000))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Signed-off-by: OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>
2024-11-21 18:17:05 +01:00
Lukas Reining 4893d6f000 feat(angular): add angular 19 to peerDependencies
Signed-off-by: Lukas Reining <lukas.reining@codecentric.de>
2024-11-21 18:14:28 +01:00
Lukas Reining 21f53ef956
feat(angular): add angular 19 support (#1084) 2024-11-21 17:35:51 +01:00
Michael Beemer c97d6d1794
ci: add provenance statement to released artifacts (#1081)
## This PR

- add provenance statement to released artifacts 

### Notes

Snippet from the NPM docs:

> You can generate provenance statements for the packages you publish.
This allows you to publicly establish where a package was built and who
published a package, which can increase supply-chain security for your
packages.

It also adds a cool badge in NPM 😎 

### Resources

-
https://docs.npmjs.com/generating-provenance-statements#example-github-actions-workflow

Signed-off-by: Michael Beemer <beeme1mr@users.noreply.github.com>
2024-11-20 14:36:08 -05:00
OpenFeature Bot 1ba149d8e5
chore(main): release server-sdk 1.16.2 (#1079)
🤖 I have created a release *beep* *boop*
---


##
[1.16.2](https://github.com/open-feature/js-sdk/compare/server-sdk-v1.16.1...server-sdk-v1.16.2)
(2024-11-07)


### 🧹 Chore

* loosen peer dependency requirements, remove some ci automation
([#1080](https://github.com/open-feature/js-sdk/issues/1080))
([ef3ba21](ef3ba2167a))


### 🚀 Performance

* avoid using exceptions for flow control
([#1074](https://github.com/open-feature/js-sdk/issues/1074))
([26264d6](26264d6d09))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Signed-off-by: OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
Co-authored-by: Todd Baert <todd.baert@dynatrace.com>
2024-11-07 12:16:03 -05:00
OpenFeature Bot 6f1c0b33ec
chore(main): release web-sdk 1.3.2 (#1078)
🤖 I have created a release *beep* *boop*
---


##
[1.3.2](https://github.com/open-feature/js-sdk/compare/web-sdk-v1.3.1...web-sdk-v1.3.2)
(2024-11-07)


### 🐛 Bug Fixes

* update OpenFeature core version to 1.5.0
([#1077](https://github.com/open-feature/js-sdk/issues/1077))
([a3469b6](a3469b6799))


### 🧹 Chore

* loosen peer dependency requirements, remove some ci automation
([#1080](https://github.com/open-feature/js-sdk/issues/1080))
([ef3ba21](ef3ba2167a))


### 🚀 Performance

* avoid using exceptions for flow control
([#1074](https://github.com/open-feature/js-sdk/issues/1074))
([26264d6](26264d6d09))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Signed-off-by: OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>
2024-11-07 12:09:48 -05:00
Todd Baert ef3ba2167a
chore: loosen peer dependency requirements, remove some ci automation (#1080)
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
2024-11-07 12:04:41 -05:00
Michael Beemer a3469b6799
fix: update OpenFeature core version to 1.5.0 (#1077)
## This PR

- bumps OpenFeature core version to match the current release

### Notes

This should have been automatically by the CI but it didn't work for
some reason. I'll look into why after the issue is resolved.


fe3ad8eeb9 (diff-e35631c960979816b4b2bda7950788e968930fcaf2cf39b482ff23117cd13888R50)

Signed-off-by: Michael Beemer <beeme1mr@users.noreply.github.com>
Co-authored-by: Todd Baert <todd.baert@dynatrace.com>
2024-11-07 08:34:36 -05:00
Michael Beemer 26264d6d09
perf: avoid using exceptions for flow control (#1074)
## This PR

- avoids using error codes as flow control during an evaluation

Signed-off-by: Michael Beemer <beeme1mr@users.noreply.github.com>
2024-11-06 21:50:01 +00:00
Michael Beemer 418409e3fa
docs: fix typos, links, and format (#1075)
Signed-off-by: Michael Beemer <beeme1mr@users.noreply.github.com>
2024-11-05 13:06:41 -05:00
OpenFeature Bot 57ec47bb21
chore(main): release react-sdk 0.4.8 (#1071)
🤖 I have created a release *beep* *boop*
---


##
[0.4.8](https://github.com/open-feature/js-sdk/compare/react-sdk-v0.4.7...react-sdk-v0.4.8)
(2024-10-29)


### 🧹 Chore

* bump minimum web peer
([#1072](https://github.com/open-feature/js-sdk/issues/1072))
([eca8205](eca8205da7))


### 📚 Documentation

* add tracking sections
([#1068](https://github.com/open-feature/js-sdk/issues/1068))
([e131faf](e131faffad))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Signed-off-by: OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>
2024-10-29 14:08:09 -04:00
Todd Baert eca8205da7
chore: bump minimum web peer (#1072)
- require web 1.3.0+ for tracking

Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
2024-10-29 18:03:30 +00:00
OpenFeature Bot b257cb41b9
chore(main): release web-sdk 1.3.1 (#1069)
🤖 I have created a release *beep* *boop*
---


##
[1.3.1](https://github.com/open-feature/js-sdk/compare/web-sdk-v1.3.0...web-sdk-v1.3.1)
(2024-10-29)


### 📚 Documentation

* add tracking sections
([#1068](https://github.com/open-feature/js-sdk/issues/1068))
([e131faf](e131faffad))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Signed-off-by: OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
Co-authored-by: Todd Baert <todd.baert@dynatrace.com>
2024-10-29 13:18:33 -04:00
105 changed files with 11834 additions and 8868 deletions

View File

@ -29,21 +29,6 @@ jobs:
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 18
node-version: 20
registry-url: "https://registry.npmjs.org"
cache: 'npm'
# if this is an @openfeature/core release, but the SDKs to use this version as a peer, and commit back
- name: Update Peer Version in Dependants
if: ${{ endsWith(github.ref_name, env.CORE_PACKAGE) }}
run: |
npm run update-core-peers && \
! git diff-files --quiet && \
( echo 'Updated peer dependency in dependents, committing...'
git add --all && \
git config user.name "openfeature-peer-update-bot" && \
git config user.email "openfeature-peer-update-bot@openfeature.dev" && \
git commit -m 'fix: bump @openfeature/${{ env.CORE_PACKAGE }} peer' -s && \
git push ) || echo 'Peer dependency in dependents is already up to date.'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -16,7 +16,7 @@ jobs:
- uses: actions/setup-node@v4
with:
registry-url: 'https://registry.npmjs.org'
node-version: 18
node-version: 20
cache: 'npm'
- name: Install

View File

@ -16,8 +16,9 @@ jobs:
strategy:
matrix:
node-version:
- 18.x
- 20.x
- 22.x
- 24.x
steps:
- uses: actions/checkout@v4
@ -36,8 +37,11 @@ jobs:
- name: Lint
run: npm run lint
- name: Test
run: npm run test
- name: Test Jest Projects
run: npm run test:jest
- name: Test Angular SDK
run: npm run test:angular
codecov-and-docs:
runs-on: ubuntu-latest
@ -46,7 +50,7 @@ jobs:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 18
node-version: 20
cache: 'npm'
- name: Install
@ -68,8 +72,7 @@ jobs:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
# we need 'fetch' for this test, which is only in 18
node-version: 18
node-version: 20
cache: 'npm'
- name: Install

View File

@ -38,7 +38,7 @@ jobs:
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 18
node-version: 20
- name: Generate SBOM
run: |
npm install -g npm@^10.2.0
@ -54,6 +54,10 @@ jobs:
needs: release-please
runs-on: ubuntu-latest
if: ${{ needs.release-please.outputs.release_created }}
environment: publish
permissions:
id-token: write
contents: write
steps:
# The logic below handles the npm publication:
- name: Checkout Repository
@ -61,7 +65,7 @@ jobs:
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 18
node-version: 20
registry-url: "https://registry.npmjs.org"
cache: 'npm'
- name: Build Packages
@ -74,6 +78,8 @@ jobs:
- name: Publish to NPM
env:
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
# https://docs.npmjs.com/generating-provenance-statements
NPM_CONFIG_PROVENANCE: true
run: npm run publish-all
- name: Build Docs

View File

@ -1,9 +1,8 @@
{
"packages/nest": "0.2.2",
"packages/react": "0.4.7",
"packages/angular": "0.0.1-experimental",
"packages/web": "1.3.0",
"packages/server": "1.16.1",
"packages/shared": "1.5.0",
"packages/angular/projects/angular-sdk": "0.0.6-experimental"
"packages/nest": "0.2.5",
"packages/react": "1.0.1",
"packages/web": "1.6.1",
"packages/server": "1.19.0",
"packages/shared": "1.9.0",
"packages/angular/projects/angular-sdk": "0.0.16"
}

View File

@ -3,4 +3,4 @@
#
# Managed by Peribolos: https://github.com/open-feature/community/blob/main/config/open-feature/sdk-javascript/workgroup.yaml
#
* @open-feature/sdk-javascript-maintainers
* @open-feature/sdk-javascript-maintainers @open-feature/maintainers

View File

@ -120,6 +120,16 @@ on each other), the owner should try to get people aligned by:
- If none of the above worked and the PR has been stuck for more than 2 weeks,
the owner should bring it to the OpenFeatures [meeting](README.md#contributing).
## Releasing
As with most OpenFeature repos, release-please supports our release process.
For this SDK specifically, keep in mind this is a monorepo with dependencies with between components.
If there are multiple release PRs open, ensure that you release them in order consistent with their dependency graph, waiting for each to fully complete.
For example, if there are pending releases for: `@openfeature/core`, `@openfeature/web-sdk` and `@openfeature/react-sdk`, release them in that order.
Also ensure that if there are changes in an artifact which depend on changes in a dependency, that you reflect that in the `peerDependencies` field.
For example, if a new release of `@openfeature/web-sdk` depends on features added in `@openfeature/core`, update the required minimum version of the `@openfeature/core` peer in the `@openfeature/web-sdk` package.json.
## Design Choices
As with other OpenFeature SDKs, js-sdk follows the

View File

@ -161,6 +161,7 @@ export default {
testMatch: ['<rootDir>/packages/nest/test/**/*.spec.ts'],
moduleNameMapper: {
'@openfeature/core': '<rootDir>/packages/shared/src',
'@openfeature/server-sdk': '<rootDir>/packages/server/src',
},
transform: {
'^.+\\.ts$': [
@ -189,26 +190,6 @@ export default {
],
},
},
{
displayName: 'angular',
testEnvironment: 'jsdom',
preset: 'jest-preset-angular',
testMatch: ['<rootDir>/packages/angular/projects/angular-sdk/src/**/*.spec.{ts,tsx}'],
setupFilesAfterEnv: ['<rootDir>/packages/angular/setup-jest.ts'],
moduleNameMapper: {
'@openfeature/core': '<rootDir>/packages/shared/src',
'@openfeature/web-sdk': '<rootDir>/packages/web/src',
},
transform: {
'^.+\\.(ts|js|html|svg)$': [
'jest-preset-angular',
{
tsconfig: '<rootDir>/packages/angular/tsconfig.json',
isolatedModules: true,
},
],
},
}
],
// Use this configuration option to add custom reporters to Jest

16490
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,15 @@
{
"name": "@openfeature/js",
"engines": {
"npm": "^10.0.0"
},
"version": "0.0.0",
"private": true,
"description": "OpenFeature SDK for JavaScript",
"scripts": {
"test": "jest --selectProjects=shared --selectProjects=server --selectProjects=web --selectProjects=react --selectProjects=angular --silent",
"test": "npm run test:jest && npm run test:angular",
"test:jest": "jest --selectProjects=shared --selectProjects=server --selectProjects=web --selectProjects=react --selectProjects=nest --silent",
"test:angular": "npm run test:coverage --workspace=packages/angular",
"e2e-server": "git submodule update --init --recursive && shx cp test-harness/features/evaluation.feature packages/server/e2e/features && jest --selectProjects=server-e2e --verbose",
"e2e-web": "git submodule update --init --recursive && shx cp test-harness/features/evaluation.feature packages/web/e2e/features && jest --selectProjects=web-e2e --verbose",
"e2e": "npm run e2e-server && npm run e2e-web",
@ -13,9 +18,7 @@
"clean": "shx rm -rf ./dist",
"build": "npm run build --workspace=packages/shared --workspace=packages/server --workspace=packages/web --workspace=packages/react --workspace=packages/angular --workspace=packages/nest",
"publish-all": "npm run publish-if-not-exists --workspace=packages/shared --workspace=packages/server --workspace=packages/web --workspace=packages/react --workspace=packages/angular --workspace=packages/nest",
"docs": "typedoc",
"core-version": "npm run version --workspace=packages/shared",
"update-core-peers": "export OPENFEATURE_CORE_VERSION=$(npm run --silent core-version) && npm run update-core-peer --workspace=packages/server --workspace=packages/web"
"docs": "typedoc"
},
"repository": {
"type": "git",
@ -33,18 +36,15 @@
"url": "https://github.com/open-feature/js-sdk/issues"
},
"homepage": "https://github.com/open-feature/js-sdk#readme",
"engines": {
"node": ">=18"
},
"devDependencies": {
"@rollup/plugin-typescript": "^11.1.6",
"@rollup/plugin-typescript": "^12.0.0",
"@testing-library/jest-dom": "^6.4.2",
"@testing-library/react": "^16.0.0",
"@types/jest": "^29.5.12",
"@types/node": "^20.11.16",
"@types/node": "^22.0.0",
"@types/react": "^18.2.55",
"@types/uuid": "^9.0.8",
"esbuild": "^0.24.0",
"@types/uuid": "^10.0.0",
"esbuild": "^0.25.0",
"eslint": "^8.56.0",
"eslint-config-prettier": "^9.1.0",
"eslint-import-resolver-alias": "^1.1.2",
@ -59,23 +59,18 @@
"jest-environment-jsdom": "^29.7.0",
"jest-environment-node": "^29.7.0",
"jest-junit": "^16.0.0",
"jest-preset-angular": "^14.2.4",
"ng-packagr": "^18.2.1",
"prettier": "^3.2.5",
"react": "^18.2.0",
"rollup": "^4.0.0",
"rollup-plugin-dts": "^6.1.1",
"rxjs": "~7.8.0",
"shx": "^0.3.4",
"shx": "^0.4.0",
"ts-jest": "^29.1.2",
"ts-node": "^10.9.2",
"tslib": "^2.3.0",
"typedoc": "^0.26.0",
"typescript": "^4.7.4",
"uuid": "^9.0.1"
},
"overrides": {
"typescript": "^4.7.4"
"uuid": "^11.0.0"
},
"workspaces": [
"packages/shared",

View File

@ -10,7 +10,7 @@
"prefix": "lib",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:ng-packagr",
"builder": "@angular/build:ng-packagr",
"options": {
"project": "projects/angular-sdk/ng-package.json"
},
@ -32,6 +32,15 @@
"projects/angular-sdk/**/*.html"
]
}
},
"test": {
"builder": "@angular/build:unit-test",
"options": {
"tsConfig": "projects/angular-sdk/tsconfig.spec.json",
"providersFile": "projects/angular-sdk/src/test-provider.ts",
"runner": "vitest",
"buildTarget": "::development"
}
}
}
}

View File

@ -7,37 +7,42 @@
"lint": "ng lint",
"lint:fix": "ng lint --fix",
"watch": "ng build --watch --configuration development",
"test": "jest",
"test": "ng test",
"test:coverage": "ng test --no-watch --code-coverage",
"build": "ng build && npm run postbuild",
"postbuild": "shx cp ./../../LICENSE ./dist/angular/LICENSE",
"publish-if-not-exists": "cp $NPM_CONFIG_USERCONFIG .npmrc && if [ \"$(npm --prefix dist/angular run current-published-version -s)\" = \"$(npm --prefix dist/angular run current-version -s)\" ]; then echo 'already published, skipping'; else cd dist/angular && npm publish --access public; fi"
},
"private": true,
"devDependencies": {
"@angular-devkit/build-angular": "^18.2.10",
"@angular-eslint/builder": "18.4.0",
"@angular-eslint/eslint-plugin": "18.4.0",
"@angular-eslint/eslint-plugin-template": "18.4.0",
"@angular-eslint/schematics": "18.4.0",
"@angular-eslint/template-parser": "18.4.0",
"@angular/animations": "^18.2.9",
"@angular/cli": "^18.2.10",
"@angular/common": "^18.2.9",
"@angular/compiler": "^18.2.9",
"@angular/compiler-cli": "^18.2.9",
"@angular/core": "^18.2.9",
"@angular/forms": "^18.2.9",
"@angular/platform-browser": "^18.2.9",
"@angular/platform-browser-dynamic": "^18.2.9",
"@angular/router": "^18.2.9",
"@typescript-eslint/eslint-plugin": "7.11.0",
"@typescript-eslint/parser": "7.11.0",
"@angular-eslint/builder": "^20.1.1",
"@angular-eslint/eslint-plugin": "^20.1.1",
"@angular-eslint/eslint-plugin-template": "^20.1.1",
"@angular-eslint/schematics": "^20.1.1",
"@angular-eslint/template-parser": "^20.1.1",
"@angular/animations": "^20.1.1",
"@angular/build": "^20.1.1",
"@angular/cli": "^20.1.1",
"@angular/common": "^20.1.1",
"@angular/compiler": "^20.1.1",
"@angular/compiler-cli": "^20.1.1",
"@angular/core": "^20.1.1",
"@angular/forms": "^20.1.1",
"@angular/platform-browser": "^20.1.1",
"@angular/platform-browser-dynamic": "^20.1.1",
"@angular/router": "^20.1.1",
"@typescript-eslint/eslint-plugin": "7.18.0",
"@typescript-eslint/parser": "7.18.0",
"@vitest/browser": "^3.2.4",
"@vitest/coverage-v8": "^3.2.4",
"eslint": "^8.57.0",
"jest-preset-angular": "^14.2.4",
"ng-packagr": "^18.2.1",
"jsdom": "^26.1.0",
"ng-packagr": "^20.1.0",
"playwright": "^1.53.2",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
"typescript": "^5.5.4",
"zone.js": "~0.14.3"
"typescript": "^5.8.3",
"vitest": "^3.2.4",
"zone.js": "~0.15.0"
}
}

View File

@ -0,0 +1,18 @@
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
# For additional information regarding the format and rule options, please see:
# https://github.com/browserslist/browserslist#queries
# For Angular's browser support policy, please see:
# https://angular.dev/reference/versions#browser-support
# You can see what browsers were selected by your queries by running:
# npx browserslist
Chrome >= 107
ChromeAndroid >= 107
Edge >= 107
Firefox >= 104
FirefoxAndroid >= 104
Safari >= 16
iOS >= 16

View File

@ -1,5 +1,82 @@
# Changelog
## [0.0.16](https://github.com/open-feature/js-sdk/compare/angular-sdk-v0.0.15...angular-sdk-v0.0.16) (2025-07-25)
### ✨ New Features
* support Angular 20 ([#1220](https://github.com/open-feature/js-sdk/issues/1220)) ([aa232a9](https://github.com/open-feature/js-sdk/commit/aa232a9d6a8dfa416380ccdecd71843d3e361048))
## [0.0.15](https://github.com/open-feature/js-sdk/compare/angular-sdk-v0.0.14...angular-sdk-v0.0.15) (2025-05-27)
### 🐛 Bug Fixes
* **angular:** update docs ([#1200](https://github.com/open-feature/js-sdk/issues/1200)) ([b6ea588](https://github.com/open-feature/js-sdk/commit/b6ea5884f2ab9f4f94c8b258c4cf7268ea6dbeb8))
## [0.0.14](https://github.com/open-feature/js-sdk/compare/angular-sdk-v0.0.13...angular-sdk-v0.0.14) (2025-05-25)
### 🐛 Bug Fixes
* **angular:** add license and url field to package.json ([b2784f5](https://github.com/open-feature/js-sdk/commit/b2784f53b85a11c58abb8e2a0f87a31890885c54))
## [0.0.13](https://github.com/open-feature/js-sdk/compare/angular-sdk-v0.0.12...angular-sdk-v0.0.13) (2025-04-20)
### 📚 Documentation
* fix readme typo ([#1174](https://github.com/open-feature/js-sdk/issues/1174)) ([21a32ec](https://github.com/open-feature/js-sdk/commit/21a32ec92ecde9ec43c9d72b5921035af13448d1))
## [0.0.12](https://github.com/open-feature/js-sdk/compare/angular-sdk-v0.0.11...angular-sdk-v0.0.12) (2025-04-11)
### ✨ New Features
* **angular:** add docs for setting evaluation context in angular ([#1170](https://github.com/open-feature/js-sdk/issues/1170)) ([24f1b23](https://github.com/open-feature/js-sdk/commit/24f1b230bf1d57971a336ac21b9ee46e8baf0cab))
## [0.0.11](https://github.com/open-feature/js-sdk/compare/angular-sdk-v0.0.10...angular-sdk-v0.0.11) (2025-04-11)
### ✨ New Features
* **angular:** add option for initial context injection ([aafdb43](https://github.com/open-feature/js-sdk/commit/aafdb4382f113f96a649f5fc0cecadb4178ada67))
## [0.0.10](https://github.com/open-feature/js-sdk/compare/angular-sdk-v0.0.9-experimental...angular-sdk-v0.0.10) (2025-02-13)
### 🧹 Chore
* **angular:** update angular package to a non-experimental version ([#1147](https://github.com/open-feature/js-sdk/issues/1147)) ([5272f76](https://github.com/open-feature/js-sdk/commit/5272f76c4075ebbd21f9b24dacac8f2d22e31ca9)), closes [#1110](https://github.com/open-feature/js-sdk/issues/1110)
* update sdk peer ([#1142](https://github.com/open-feature/js-sdk/issues/1142)) ([8bb6206](https://github.com/open-feature/js-sdk/commit/8bb620601e2b8dc7b62d717169b585bd1c886996))
## [0.0.9-experimental](https://github.com/open-feature/js-sdk/compare/angular-sdk-v0.0.8-experimental...angular-sdk-v0.0.9-experimental) (2024-11-21)
### 🧹 Chore
* **angular:** add repository to package.json ([#1093](https://github.com/open-feature/js-sdk/issues/1093)) ([35f000e](https://github.com/open-feature/js-sdk/commit/35f000e0f3c3ff7d60c05883312691d14f01c5fd))
## [0.0.8-experimental](https://github.com/open-feature/js-sdk/compare/angular-sdk-v0.0.7-experimental...angular-sdk-v0.0.8-experimental) (2024-11-21)
### ✨ New Features
* **angular:** add angular 19 to peerDependencies ([4893d6f](https://github.com/open-feature/js-sdk/commit/4893d6f0003fbdcdcd4c7c061e9aed49e20b8976))
## [0.0.7-experimental](https://github.com/open-feature/js-sdk/compare/angular-sdk-v0.0.6-experimental...angular-sdk-v0.0.7-experimental) (2024-11-21)
Note: This version did not release
## [0.0.6-experimental](https://github.com/open-feature/js-sdk/compare/angular-sdk-v0.0.5-experimental...angular-sdk-v0.0.6-experimental) (2024-10-28)

View File

@ -16,8 +16,8 @@
<img alt="Specification" src="https://img.shields.io/static/v1?label=specification&message=v0.8.0&color=yellow&style=for-the-badge" />
</a>
<!-- x-release-please-start-version -->
<a href="https://github.com/open-feature/js-sdk/releases/tag/angular-sdk-v0.0.6-experimental">
<img alt="Release" src="https://img.shields.io/static/v1?label=release&message=v0.0.6-experimental&color=blue&style=for-the-badge" />
<a href="https://github.com/open-feature/js-sdk/releases/tag/angular-sdk-v0.0.16">
<img alt="Release" src="https://img.shields.io/static/v1?label=release&message=v0.0.16&color=blue&style=for-the-badge" />
</a>
<!-- x-release-please-end -->
<br/>
@ -44,21 +44,22 @@ In addition to the features provided by the [web sdk](https://openfeature.dev/do
- [Overview](#overview)
- [Quick start](#quick-start)
- [Requirements](#requirements)
- [Install](#install)
- [npm](#npm)
- [yarn](#yarn)
- [Required peer dependencies](#required-peer-dependencies)
- [Usage](#usage)
- [Module](#module)
- [Minimal Example](#minimal-example)
- [How to use](#how-to-use)
- [Boolean Feature Flag](#boolean-feature-flag)
- [Number Feature Flag](#number-feature-flag)
- [String Feature Flag](#string-feature-flag)
- [Object Feature Flag](#object-feature-flag)
- [Opting-out of automatic re-rendering](#opting-out-of-automatic-re-rendering)
- [Consuming the evaluation details](#consuming-the-evaluation-details)
- [Requirements](#requirements)
- [Install](#install)
- [npm](#npm)
- [yarn](#yarn)
- [Required peer dependencies](#required-peer-dependencies)
- [Usage](#usage)
- [Module](#module)
- [Minimal Example](#minimal-example)
- [How to use](#how-to-use)
- [Boolean Feature Flag](#boolean-feature-flag)
- [Number Feature Flag](#number-feature-flag)
- [String Feature Flag](#string-feature-flag)
- [Object Feature Flag](#object-feature-flag)
- [Opting-out of automatic re-rendering](#opting-out-of-automatic-re-rendering)
- [Consuming the evaluation details](#consuming-the-evaluation-details)
- [Setting Evaluation Context](#setting-evaluation-context)
- [FAQ and troubleshooting](#faq-and-troubleshooting)
- [Resources](#resources)
@ -113,7 +114,7 @@ import { OpenFeatureModule } from '@openfeature/angular-sdk';
CommonModule,
OpenFeatureModule.forRoot({
provider: yourFeatureProvider,
// domainBoundProviders are optional, mostly needed if more than one provider is needed
// domainBoundProviders are optional, mostly needed if more than one provider is used in the application.
domainBoundProviders: {
domain1: new YourOpenFeatureProvider(),
domain2: new YourOtherOpenFeatureProvider(),
@ -281,6 +282,63 @@ This can be used to just render the flag value or details without conditional re
</div>
```
##### Setting evaluation context
To set the initial evaluation context, you can add the `context` parameter to the `OpenFeatureModule` configuration.
This context can be either an object or a factory function that returns an `EvaluationContext`.
> [!TIP]
> Updating the context can be done directly via the global OpenFeature API using `OpenFeature.setContext()`
Heres how you can define and use the initial client evaluation context:
###### Using a static object
```typescript
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { OpenFeatureModule } from '@openfeature/angular-sdk';
const initialContext = {
user: {
id: 'user123',
role: 'admin',
}
};
@NgModule({
imports: [
CommonModule,
OpenFeatureModule.forRoot({
provider: yourFeatureProvider,
context: initialContext
})
],
})
export class AppModule {}
```
###### Using a factory function
```typescript
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { OpenFeatureModule, EvaluationContext } from '@openfeature/angular-sdk';
const contextFactory = (): EvaluationContext => loadContextFromLocalStorage();
@NgModule({
imports: [
CommonModule,
OpenFeatureModule.forRoot({
provider: yourFeatureProvider,
context: contextFactory
})
],
})
export class AppModule {}
```
## FAQ and troubleshooting
> I can import things form the `@openfeature/angular-sdk`, `@openfeature/web-sdk`, and `@openfeature/core`; which should I use?
@ -291,4 +349,4 @@ Avoid importing anything from `@openfeature/web-sdk` or `@openfeature/core`.
## Resources
- [Example repo](https://github.com/open-feature/angular-test-app)
- [Example repo](https://github.com/open-feature/angular-test-app)

View File

@ -1,25 +1,34 @@
{
"name": "@openfeature/angular-sdk",
"version": "0.0.6-experimental",
"version": "0.0.16",
"description": "OpenFeature Angular SDK",
"repository": {
"type": "git",
"url": "git+https://github.com/open-feature/js-sdk.git"
},
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/open-feature/js-sdk/issues"
},
"homepage": "https://github.com/open-feature/js-sdk#readme",
"scripts": {
"current-published-version": "npm show $npm_package_name@$npm_package_version version",
"current-version": "echo $npm_package_version",
"prepack": "shx cp ./../../../../LICENSE ./LICENSE"
},
"peerDependencies": {
"@angular/common": "^16.2.12 || ^17.3.0 || ^18.0.0",
"@angular/core": "^16.2.12 || ^17.3.0 || ^18.0.0",
"@openfeature/web-sdk": "^1.2.3"
"@angular/common": "^16.2.12 || ^17.3.0 || ^18.0.0 || ^19.0.0 || ^20.0.0",
"@angular/core": "^16.2.12 || ^17.3.0 || ^18.0.0 || ^19.0.0 || ^20.0.0",
"@openfeature/web-sdk": "^1.4.1"
},
"dependencies": {
"tslib": "^2.3.0"
},
"devDependencies": {
"@openfeature/core": "*",
"@openfeature/web-sdk": "*",
"@angular/common": "^18.2.9",
"@angular/core": "^18.2.9"
"@openfeature/core": "^1.8.1",
"@openfeature/web-sdk": "^1.5.0",
"@angular/common": "^20.1.2",
"@angular/core": "^20.1.2"
},
"sideEffects": false,
"keywords": [

View File

@ -253,6 +253,7 @@ describe('FeatureFlagDirective', () => {
await expectRenderedText(fixture, 'case-2', 'Flag On');
await updateFlagValue(provider, false);
fixture.detectChanges(); // Ensure change detection after flag update
await expectRenderedText(fixture, 'case-2', 'Flag Off');
});
});
@ -393,7 +394,9 @@ describe('FeatureFlagDirective', () => {
await waitForClientReady(client);
await expectRenderedText(fixture, 'case-6', 'Flag On');
fixture.componentInstance.specialFlagKey = 'new-test-flag';
fixture.componentRef.setInput('specialFlagKey', 'new-test-flag');
await fixture.whenStable();
await expectRenderedText(fixture, 'case-6', 'Flag Off');
});
@ -445,7 +448,9 @@ describe('FeatureFlagDirective', () => {
);
await OpenFeature.setProviderAndWait(newDomain, newProvider);
fixture.componentInstance.domain = newDomain;
fixture.componentRef.setInput('domain', newDomain);
await fixture.whenStable();
await expectRenderedText(fixture, 'case-6', 'Flag Off');
});
});
@ -560,8 +565,7 @@ async function createTestingModule(config?: {
],
}).createComponent(TestComponent);
fixture.componentInstance.domain = domain;
fixture.detectChanges();
fixture.componentRef.setInput('domain', domain);
await fixture.whenStable();
const client = OpenFeature.getClient(domain);

View File

@ -8,6 +8,7 @@ import {
OnInit,
TemplateRef,
ViewContainerRef,
inject,
} from '@angular/core';
import {
Client,
@ -35,6 +36,9 @@ class FeatureFlagDirectiveContext<T extends FlagValue> {
selector: '[featureFlag]',
})
export abstract class FeatureFlagDirective<T extends FlagValue> implements OnInit, OnDestroy, OnChanges {
protected _changeDetectorRef: ChangeDetectorRef;
protected _viewContainerRef: ViewContainerRef;
protected _featureFlagDefault: T;
protected _featureFlagDomain: string | undefined;
@ -64,13 +68,7 @@ export abstract class FeatureFlagDirective<T extends FlagValue> implements OnIni
protected _reconcilingTemplateRef: TemplateRef<FeatureFlagDirectiveContext<T>> | null;
protected _reconcilingViewRef: EmbeddedViewRef<unknown> | null;
protected constructor(
protected _changeDetectorRef: ChangeDetectorRef,
protected _viewContainerRef: ViewContainerRef,
templateRef: TemplateRef<FeatureFlagDirectiveContext<T>>,
) {
this._thenTemplateRef = templateRef;
}
protected constructor() {}
set featureFlagDomain(domain: string | undefined) {
/**
@ -232,6 +230,10 @@ export abstract class FeatureFlagDirective<T extends FlagValue> implements OnIni
selector: '[booleanFeatureFlag]',
})
export class BooleanFeatureFlagDirective extends FeatureFlagDirective<boolean> implements OnChanges {
override _changeDetectorRef = inject(ChangeDetectorRef);
override _viewContainerRef = inject(ViewContainerRef);
override _thenTemplateRef = inject<TemplateRef<FeatureFlagDirectiveContext<boolean>>>(TemplateRef);
/**
* The key of the boolean feature flag.
*/
@ -242,12 +244,8 @@ export class BooleanFeatureFlagDirective extends FeatureFlagDirective<boolean> i
*/
@Input({ required: true }) booleanFeatureFlagDefault: boolean;
constructor(
_changeDetectorRef: ChangeDetectorRef,
_viewContainerRef: ViewContainerRef,
templateRef: TemplateRef<FeatureFlagDirectiveContext<boolean>>,
) {
super(_changeDetectorRef, _viewContainerRef, templateRef);
constructor() {
super();
}
override ngOnChanges() {
@ -347,6 +345,10 @@ export class BooleanFeatureFlagDirective extends FeatureFlagDirective<boolean> i
selector: '[numberFeatureFlag]',
})
export class NumberFeatureFlagDirective extends FeatureFlagDirective<number> implements OnChanges {
override _changeDetectorRef = inject(ChangeDetectorRef);
override _viewContainerRef = inject(ViewContainerRef);
override _thenTemplateRef = inject<TemplateRef<FeatureFlagDirectiveContext<number>>>(TemplateRef);
/**
* The key of the number feature flag.
*/
@ -362,12 +364,8 @@ export class NumberFeatureFlagDirective extends FeatureFlagDirective<number> imp
*/
@Input({ required: false }) numberFeatureFlagValue?: number;
constructor(
_changeDetectorRef: ChangeDetectorRef,
_viewContainerRef: ViewContainerRef,
templateRef: TemplateRef<FeatureFlagDirectiveContext<number>>,
) {
super(_changeDetectorRef, _viewContainerRef, templateRef);
constructor() {
super();
}
override ngOnChanges() {
@ -467,6 +465,10 @@ export class NumberFeatureFlagDirective extends FeatureFlagDirective<number> imp
selector: '[stringFeatureFlag]',
})
export class StringFeatureFlagDirective extends FeatureFlagDirective<string> implements OnChanges {
override _changeDetectorRef = inject(ChangeDetectorRef);
override _viewContainerRef = inject(ViewContainerRef);
override _thenTemplateRef = inject<TemplateRef<FeatureFlagDirectiveContext<string>>>(TemplateRef);
/**
* The key of the string feature flag.
*/
@ -482,12 +484,8 @@ export class StringFeatureFlagDirective extends FeatureFlagDirective<string> imp
*/
@Input({ required: false }) stringFeatureFlagValue?: string;
constructor(
_changeDetectorRef: ChangeDetectorRef,
_viewContainerRef: ViewContainerRef,
templateRef: TemplateRef<FeatureFlagDirectiveContext<string>>,
) {
super(_changeDetectorRef, _viewContainerRef, templateRef);
constructor() {
super();
}
override ngOnChanges() {
@ -587,6 +585,10 @@ export class StringFeatureFlagDirective extends FeatureFlagDirective<string> imp
selector: '[objectFeatureFlag]',
})
export class ObjectFeatureFlagDirective<T extends JsonValue> extends FeatureFlagDirective<T> implements OnChanges {
override _changeDetectorRef = inject(ChangeDetectorRef);
override _viewContainerRef = inject(ViewContainerRef);
override _thenTemplateRef = inject<TemplateRef<FeatureFlagDirectiveContext<T>>>(TemplateRef);
/**
* The key of the object feature flag.
*/
@ -602,12 +604,8 @@ export class ObjectFeatureFlagDirective<T extends JsonValue> extends FeatureFlag
*/
@Input({ required: false }) objectFeatureFlagValue?: T;
constructor(
_changeDetectorRef: ChangeDetectorRef,
_viewContainerRef: ViewContainerRef,
templateRef: TemplateRef<FeatureFlagDirectiveContext<T>>,
) {
super(_changeDetectorRef, _viewContainerRef, templateRef);
constructor() {
super();
}
override ngOnChanges() {

View File

@ -1,10 +1,13 @@
import { InjectionToken, ModuleWithProviders, NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { OpenFeature, Provider } from '@openfeature/web-sdk';
import { EvaluationContext, OpenFeature, Provider } from '@openfeature/web-sdk';
export type EvaluationContextFactory = () => EvaluationContext;
export interface OpenFeatureConfig {
provider: Provider;
domainBoundProviders?: Record<string, Provider>;
context?: EvaluationContext | EvaluationContextFactory;
}
export const OPEN_FEATURE_CONFIG_TOKEN = new InjectionToken<OpenFeatureConfig>('OPEN_FEATURE_CONFIG_TOKEN');
@ -16,7 +19,9 @@ export const OPEN_FEATURE_CONFIG_TOKEN = new InjectionToken<OpenFeatureConfig>('
})
export class OpenFeatureModule {
static forRoot(config: OpenFeatureConfig): ModuleWithProviders<OpenFeatureModule> {
OpenFeature.setProvider(config.provider);
const context = typeof config.context === 'function' ? config.context() : config.context;
OpenFeature.setProvider(config.provider, context);
if (config.domainBoundProviders) {
Object.entries(config.domainBoundProviders).map(([domain, provider]) =>
OpenFeature.setProvider(domain, provider),

View File

@ -0,0 +1,3 @@
import { provideZonelessChangeDetection } from '@angular/core';
export default [provideZonelessChangeDetection()];

View File

@ -3,15 +3,20 @@
"compilerOptions": {
"outDir": "./out-tsc/spec",
"types": [
"jest",
"vitest/globals",
"node"
],
"paths": {
"angular": [
"./dist/angular"
]
},
"esModuleInterop": true,
"emitDecoratorMetadata": true
},
"include": [
"src/**/*.spec.ts",
"src/**/*.d.ts",
"setup-jest.ts"
"src/test-provider.ts"
]
}

View File

@ -1 +0,0 @@
import 'jest-preset-angular/setup-jest';

View File

@ -23,8 +23,8 @@
"experimentalDecorators": true,
"moduleResolution": "node",
"importHelpers": true,
"target": "ES2015",
"module": "ES2015",
"target": "ES2022",
"module": "ES2022",
"useDefineForClassFields": false,
"strictNullChecks": false,
"lib": [

View File

@ -3,13 +3,14 @@
"compilerOptions": {
"outDir": "./out-tsc/spec",
"types": [
"jest"
"vitest/globals",
"node"
],
"esModuleInterop": true,
"emitDecoratorMetadata": true
},
"include": [
"src/**/*.spec.ts",
"src/**/*.d.ts"
"projects/angular-sdk/src/**/*.spec.ts",
"projects/angular-sdk/src/**/*.d.ts"
]
}

View File

@ -0,0 +1,10 @@
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
coverage: {
provider: 'v8',
reporter: ['text', 'json', 'html'],
},
},
});

View File

@ -1,5 +1,34 @@
# Changelog
## [0.2.5](https://github.com/open-feature/js-sdk/compare/nestjs-sdk-v0.2.4...nestjs-sdk-v0.2.5) (2025-05-27)
### ✨ New Features
* adds RequireFlagsEnabled decorator ([#1159](https://github.com/open-feature/js-sdk/issues/1159)) ([59b8fe9](https://github.com/open-feature/js-sdk/commit/59b8fe904f053e4aa3d0c72631af34183ff54dc7))
## [0.2.4](https://github.com/open-feature/js-sdk/compare/nestjs-sdk-v0.2.3...nestjs-sdk-v0.2.4) (2025-04-20)
### 🧹 Chore
* **nest:** allow nestjs version 11 ([#1176](https://github.com/open-feature/js-sdk/issues/1176)) ([42a3b39](https://github.com/open-feature/js-sdk/commit/42a3b39c2488002f249b37ce86794ef2f77eb31c))
## [0.2.3](https://github.com/open-feature/js-sdk/compare/nestjs-sdk-v0.2.2...nestjs-sdk-v0.2.3) (2025-04-11)
### 🧹 Chore
* update sdk peer ([#1142](https://github.com/open-feature/js-sdk/issues/1142)) ([8bb6206](https://github.com/open-feature/js-sdk/commit/8bb620601e2b8dc7b62d717169b585bd1c886996))
### Dependencies
* The following workspace dependencies were updated
* devDependencies
* @openfeature/server-sdk bumped from * to 1.18.0
## [0.2.2](https://github.com/open-feature/js-sdk/compare/nestjs-sdk-v0.2.1-experimental...nestjs-sdk-v0.2.2) (2024-10-29)

View File

@ -16,8 +16,8 @@
<img alt="Specification" src="https://img.shields.io/static/v1?label=specification&message=v0.8.0&color=yellow&style=for-the-badge" />
</a>
<!-- x-release-please-start-version -->
<a href="https://github.com/open-feature/js-sdk/releases/tag/nestjs-sdk-v0.2.2">
<img alt="Release" src="https://img.shields.io/static/v1?label=release&message=v0.2.2&color=blue&style=for-the-badge" />
<a href="https://github.com/open-feature/js-sdk/releases/tag/nestjs-sdk-v0.2.5">
<img alt="Release" src="https://img.shields.io/static/v1?label=release&message=v0.2.5&color=blue&style=for-the-badge" />
</a>
<!-- x-release-please-end -->
<br/>
@ -50,7 +50,7 @@ Capabilities include:
### Requirements
- Node.js version 18+
- Node.js version 20+
- NestJS version 8+
### Install
@ -72,10 +72,10 @@ yarn add @openfeature/nestjs-sdk @openfeature/server-sdk @openfeature/core
The following list contains the peer dependencies of `@openfeature/nestjs-sdk` with its expected and compatible versions:
* `@openfeature/server-sdk`: >=1.7.5
* `@nestjs/common`: ^8.0.0 || ^9.0.0 || ^10.0.0
* `@nestjs/core`: ^8.0.0 || ^9.0.0 || ^10.0.0
* `rxjs`: ^6.0.0 || ^7.0.0 || ^8.0.0
- `@openfeature/server-sdk`: >=1.7.5
- `@nestjs/common`: ^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0
- `@nestjs/core`: ^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0
- `rxjs`: ^6.0.0 || ^7.0.0 || ^8.0.0
The minimum required version of `@openfeature/server-sdk` currently is `1.7.5`.
@ -152,6 +152,24 @@ export class OpenFeatureTestService {
}
```
#### Managing Controller or Route Access via Feature Flags
The `RequireFlagsEnabled` decorator can be used to manage access to a controller or route based on the enabled state of a feature flag. The decorator will throw an exception if the required feature flag(s) are not enabled.
```ts
import { Controller, Get } from '@nestjs/common';
import { RequireFlagsEnabled } from '@openfeature/nestjs-sdk';
@Controller()
export class OpenFeatureController {
@RequireFlagsEnabled({ flags: [{ flagKey: 'testBooleanFlag' }] })
@Get('/welcome')
public async welcome() {
return 'Welcome to this OpenFeature-enabled NestJS app!';
}
}
```
## Module additional information
### Flag evaluation context injection

View File

@ -1,6 +1,6 @@
{
"name": "@openfeature/nestjs-sdk",
"version": "0.2.2",
"version": "0.2.5",
"description": "OpenFeature Nest.js SDK",
"main": "./dist/cjs/index.js",
"files": [
@ -46,18 +46,18 @@
},
"homepage": "https://github.com/open-feature/js-sdk#readme",
"peerDependencies": {
"@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0",
"@nestjs/core": "^8.0.0 || ^9.0.0 || ^10.0.0",
"@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0",
"@nestjs/core": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0",
"rxjs": "^6.0.0 || ^7.0.0 || 8.0.0",
"@openfeature/server-sdk": ">=1.14.0"
"@openfeature/server-sdk": "^1.17.1"
},
"devDependencies": {
"@nestjs/common": "^10.3.6",
"@nestjs/core": "^10.3.6",
"@nestjs/platform-express": "^10.3.6",
"@nestjs/testing": "^10.3.6",
"@nestjs/common": "^11.0.20",
"@nestjs/core": "^11.0.20",
"@nestjs/platform-express": "^11.0.20",
"@nestjs/testing": "^11.0.20",
"@openfeature/core": "*",
"@openfeature/server-sdk": "*",
"@openfeature/server-sdk": "1.18.0",
"@types/supertest": "^6.0.0",
"supertest": "^7.0.0"
}

View File

@ -1,16 +1,10 @@
import { createParamDecorator, Inject } from '@nestjs/common';
import type {
EvaluationContext,
EvaluationDetails,
FlagValue,
JsonValue} from '@openfeature/server-sdk';
import {
OpenFeature,
Client,
} from '@openfeature/server-sdk';
import type { EvaluationContext, EvaluationDetails, FlagValue, JsonValue } from '@openfeature/server-sdk';
import { Client } from '@openfeature/server-sdk';
import { getOpenFeatureClientToken } from './open-feature.module';
import type { Observable } from 'rxjs';
import { from } from 'rxjs';
import { getClientForEvaluation } from './utils';
/**
* Options for injecting an OpenFeature client into a constructor.
@ -56,16 +50,6 @@ interface FeatureProps<T extends FlagValue> {
context?: EvaluationContext;
}
/**
* Returns a domain scoped or the default OpenFeature client with the given context.
* @param {string} domain The domain of the OpenFeature client.
* @param {EvaluationContext} context The evaluation context of the client.
* @returns {Client} The OpenFeature client.
*/
function getClientForEvaluation(domain?: string, context?: EvaluationContext) {
return domain ? OpenFeature.getClient(domain, context) : OpenFeature.getClient(context);
}
/**
* Route handler parameter decorator.
*

View File

@ -2,5 +2,6 @@ export * from './open-feature.module';
export * from './feature.decorator';
export * from './evaluation-context-interceptor';
export * from './context-factory';
export * from './require-flags-enabled.decorator';
// re-export the server-sdk so consumers can access that API from the nestjs-sdk
export * from '@openfeature/server-sdk';

View File

@ -0,0 +1,104 @@
import type { CallHandler, ExecutionContext, HttpException, NestInterceptor } from '@nestjs/common';
import { applyDecorators, mixin, NotFoundException, UseInterceptors } from '@nestjs/common';
import { getClientForEvaluation } from './utils';
import type { EvaluationContext } from '@openfeature/server-sdk';
import type { ContextFactory } from './context-factory';
type RequiredFlag = {
flagKey: string;
defaultValue?: boolean;
};
/**
* Options for using one or more Boolean feature flags to control access to a Controller or Route.
*/
interface RequireFlagsEnabledProps {
/**
* The key and default value of the feature flag.
* @see {@link Client#getBooleanValue}
*/
flags: RequiredFlag[];
/**
* The exception to throw if any of the required feature flags are not enabled.
* Defaults to a 404 Not Found exception.
* @see {@link HttpException}
* @default new NotFoundException(`Cannot ${req.method} ${req.url}`)
*/
exception?: HttpException;
/**
* The domain of the OpenFeature client, if a domain scoped client should be used.
* @see {@link OpenFeature#getClient}
*/
domain?: string;
/**
* The {@link EvaluationContext} for evaluating the feature flag.
* @see {@link OpenFeature#setContext}
*/
context?: EvaluationContext;
/**
* A factory function for creating an OpenFeature {@link EvaluationContext} from Nest {@link ExecutionContext}.
* For example, this can be used to get header info from an HTTP request or information from a gRPC call to be used in the {@link EvaluationContext}.
* @see {@link ContextFactory}
*/
contextFactory?: ContextFactory;
}
/**
* Controller or Route permissions handler decorator.
*
* Requires that the given feature flags are enabled for the request to be processed, else throws an exception.
*
* For example:
* ```typescript
* @RequireFlagsEnabled({
* flags: [ // Required, an array of Boolean flags to check, with optional default values (defaults to false)
* { flagKey: 'flagName' },
* { flagKey: 'flagName2', defaultValue: true },
* ],
* exception: new ForbiddenException(), // Optional, defaults to a 404 Not Found Exception
* domain: 'my-domain', // Optional, defaults to the default OpenFeature Client
* context: { // Optional, defaults to the global OpenFeature Context
* targetingKey: 'user-id',
* },
* contextFactory: (context: ExecutionContext) => { // Optional, defaults to the global OpenFeature Context. Takes precedence over the context option.
* return {
* targetingKey: context.switchToHttp().getRequest().headers['x-user-id'],
* };
* },
* })
* @Get('/')
* public async handleGetRequest()
* ```
* @param {RequireFlagsEnabledProps} props The options for injecting the feature flag.
* @returns {ClassDecorator & MethodDecorator} The decorator that can be used to require Boolean Feature Flags to be enabled for a controller or a specific route.
*/
export const RequireFlagsEnabled = (props: RequireFlagsEnabledProps): ClassDecorator & MethodDecorator =>
applyDecorators(UseInterceptors(FlagsEnabledInterceptor(props)));
const FlagsEnabledInterceptor = (props: RequireFlagsEnabledProps) => {
class FlagsEnabledInterceptor implements NestInterceptor {
constructor() {}
async intercept(context: ExecutionContext, next: CallHandler) {
const req = context.switchToHttp().getRequest();
const evaluationContext = props.contextFactory ? await props.contextFactory(context) : props.context;
const client = getClientForEvaluation(props.domain, evaluationContext);
for (const flag of props.flags) {
const endpointAccessible = await client.getBooleanValue(flag.flagKey, flag.defaultValue ?? false);
if (!endpointAccessible) {
throw props.exception || new NotFoundException(`Cannot ${req.method} ${req.url}`);
}
}
return next.handle();
}
}
return mixin(FlagsEnabledInterceptor);
};

View File

@ -0,0 +1,12 @@
import type { Client, EvaluationContext } from '@openfeature/server-sdk';
import { OpenFeature } from '@openfeature/server-sdk';
/**
* Returns a domain scoped or the default OpenFeature client with the given context.
* @param {string} domain The domain of the OpenFeature client.
* @param {EvaluationContext} context The evaluation context of the client.
* @returns {Client} The OpenFeature client.
*/
export function getClientForEvaluation(domain?: string, context?: EvaluationContext) {
return domain ? OpenFeature.getClient(domain, context) : OpenFeature.getClient(context);
}

View File

@ -1,4 +1,5 @@
import { InMemoryProvider } from '@openfeature/server-sdk';
import type { EvaluationContext } from '@openfeature/server-sdk';
import type { ExecutionContext } from '@nestjs/common';
import { OpenFeatureModule } from '../src';
@ -23,6 +24,17 @@ export const defaultProvider = new InMemoryProvider({
variants: { default: { client: 'default' } },
disabled: false,
},
testBooleanFlag2: {
defaultVariant: 'default',
variants: { default: false, enabled: true },
disabled: false,
contextEvaluator: (ctx: EvaluationContext) => {
if (ctx.targetingKey === '123') {
return 'enabled';
}
return 'default';
},
},
});
export const providers = {

View File

@ -2,7 +2,12 @@ import type { TestingModule } from '@nestjs/testing';
import { Test } from '@nestjs/testing';
import type { INestApplication } from '@nestjs/common';
import supertest from 'supertest';
import { OpenFeatureController, OpenFeatureControllerContextScopedController, OpenFeatureTestService } from './test-app';
import {
OpenFeatureController,
OpenFeatureContextScopedController,
OpenFeatureRequireFlagsEnabledController,
OpenFeatureTestService,
} from './test-app';
import { exampleContextFactory, getOpenFeatureDefaultTestModule } from './fixtures';
import { OpenFeatureModule } from '../src';
import { defaultProvider, providers } from './fixtures';
@ -14,11 +19,9 @@ describe('OpenFeature SDK', () => {
beforeAll(async () => {
moduleRef = await Test.createTestingModule({
imports: [
getOpenFeatureDefaultTestModule()
],
imports: [getOpenFeatureDefaultTestModule()],
providers: [OpenFeatureTestService],
controllers: [OpenFeatureController],
controllers: [OpenFeatureController, OpenFeatureRequireFlagsEnabledController],
}).compile();
app = moduleRef.createNestApplication();
app = await app.init();
@ -112,7 +115,7 @@ describe('OpenFeature SDK', () => {
});
describe('evaluation context service should', () => {
it('inject the evaluation context from contex factory', async function() {
it('inject the evaluation context from contex factory', async function () {
const evaluationSpy = jest.spyOn(defaultProvider, 'resolveBooleanEvaluation');
await supertest(app.getHttpServer())
.get('/dynamic-context-in-service')
@ -122,26 +125,77 @@ describe('OpenFeature SDK', () => {
expect(evaluationSpy).toHaveBeenCalledWith('testBooleanFlag', false, { targetingKey: 'dynamic-user' }, {});
});
});
describe('require flags enabled decorator', () => {
describe('OpenFeatureController', () => {
it('should sucessfully return the response if the flag is enabled', async () => {
await supertest(app.getHttpServer()).get('/flags-enabled').expect(200).expect('Get Boolean Flag Success!');
});
it('should throw an exception if the flag is disabled', async () => {
jest.spyOn(defaultProvider, 'resolveBooleanEvaluation').mockResolvedValueOnce({
value: false,
reason: 'DISABLED',
});
await supertest(app.getHttpServer()).get('/flags-enabled').expect(404);
});
it('should throw a custom exception if the flag is disabled', async () => {
jest.spyOn(defaultProvider, 'resolveBooleanEvaluation').mockResolvedValueOnce({
value: false,
reason: 'DISABLED',
});
await supertest(app.getHttpServer()).get('/flags-enabled-custom-exception').expect(403);
});
it('should throw a custom exception if the flag is disabled with context', async () => {
await supertest(app.getHttpServer())
.get('/flags-enabled-custom-exception-with-context')
.set('x-user-id', '123')
.expect(403);
});
});
describe('OpenFeatureControllerRequireFlagsEnabled', () => {
it('should allow access to the RequireFlagsEnabled controller with global context interceptor', async () => {
await supertest(app.getHttpServer())
.get('/require-flags-enabled')
.set('x-user-id', '123')
.expect(200)
.expect('Hello, world!');
});
it('should throw a 403 - Forbidden exception if user does not match targeting requirements', async () => {
await supertest(app.getHttpServer()).get('/require-flags-enabled').set('x-user-id', 'not-123').expect(403);
});
it('should throw a 403 - Forbidden exception if one of the flags is disabled', async () => {
jest.spyOn(defaultProvider, 'resolveBooleanEvaluation').mockResolvedValueOnce({
value: false,
reason: 'DISABLED',
});
await supertest(app.getHttpServer()).get('/require-flags-enabled').set('x-user-id', '123').expect(403);
});
});
});
});
describe('Without global context interceptor', () => {
let moduleRef: TestingModule;
let app: INestApplication;
beforeAll(async () => {
moduleRef = await Test.createTestingModule({
imports: [
OpenFeatureModule.forRoot({
contextFactory: exampleContextFactory,
defaultProvider,
providers,
useGlobalInterceptor: false
useGlobalInterceptor: false,
}),
],
providers: [OpenFeatureTestService],
controllers: [OpenFeatureController, OpenFeatureControllerContextScopedController],
controllers: [OpenFeatureController, OpenFeatureContextScopedController],
}).compile();
app = moduleRef.createNestApplication();
app = await app.init();
@ -158,7 +212,7 @@ describe('OpenFeature SDK', () => {
});
describe('evaluation context service should', () => {
it('inject empty context if no context interceptor is configured', async function() {
it('inject empty context if no context interceptor is configured', async function () {
const evaluationSpy = jest.spyOn(defaultProvider, 'resolveBooleanEvaluation');
await supertest(app.getHttpServer())
.get('/dynamic-context-in-service')
@ -172,9 +226,26 @@ describe('OpenFeature SDK', () => {
describe('With Controller bound Context interceptor', () => {
it('should not use context if global context interceptor is not configured', async () => {
const evaluationSpy = jest.spyOn(defaultProvider, 'resolveBooleanEvaluation');
await supertest(app.getHttpServer()).get('/controller-context').set('x-user-id', '123').expect(200).expect('true');
await supertest(app.getHttpServer())
.get('/controller-context')
.set('x-user-id', '123')
.expect(200)
.expect('true');
expect(evaluationSpy).toHaveBeenCalledWith('testBooleanFlag', false, { targetingKey: '123' }, {});
});
});
describe('require flags enabled decorator', () => {
it('should return a 404 - Not Found exception if the flag is disabled', async () => {
jest.spyOn(providers.domainScopedClient, 'resolveBooleanEvaluation').mockResolvedValueOnce({
value: false,
reason: 'DISABLED',
});
await supertest(app.getHttpServer())
.get('/controller-context/flags-enabled')
.set('x-user-id', '123')
.expect(404);
});
});
});
});

View File

@ -1,7 +1,14 @@
import { Controller, Get, Injectable, UseInterceptors } from '@nestjs/common';
import type { Observable} from 'rxjs';
import { Controller, ForbiddenException, Get, Injectable, UseInterceptors } from '@nestjs/common';
import type { Observable } from 'rxjs';
import { map } from 'rxjs';
import { BooleanFeatureFlag, ObjectFeatureFlag, NumberFeatureFlag, OpenFeatureClient, StringFeatureFlag } from '../src';
import {
BooleanFeatureFlag,
ObjectFeatureFlag,
NumberFeatureFlag,
OpenFeatureClient,
StringFeatureFlag,
RequireFlagsEnabled,
} from '../src';
import type { Client, EvaluationDetails, FlagValue } from '@openfeature/server-sdk';
import { EvaluationContextInterceptor } from '../src';
@ -84,11 +91,40 @@ export class OpenFeatureController {
public async handleDynamicContextInServiceRequest() {
return this.testService.serviceMethodWithDynamicContext('testBooleanFlag');
}
@RequireFlagsEnabled({
flags: [{ flagKey: 'testBooleanFlag' }],
})
@Get('/flags-enabled')
public async handleGuardedBooleanRequest() {
return 'Get Boolean Flag Success!';
}
@RequireFlagsEnabled({
flags: [{ flagKey: 'testBooleanFlag' }],
exception: new ForbiddenException(),
})
@Get('/flags-enabled-custom-exception')
public async handleBooleanRequestWithCustomException() {
return 'Get Boolean Flag Success!';
}
@RequireFlagsEnabled({
flags: [{ flagKey: 'testBooleanFlag2' }],
exception: new ForbiddenException(),
context: {
targetingKey: 'user-id',
},
})
@Get('/flags-enabled-custom-exception-with-context')
public async handleBooleanRequestWithCustomExceptionAndContext() {
return 'Get Boolean Flag Success!';
}
}
@Controller()
@UseInterceptors(EvaluationContextInterceptor)
export class OpenFeatureControllerContextScopedController {
export class OpenFeatureContextScopedController {
constructor(private testService: OpenFeatureTestService) {}
@Get('/controller-context')
@ -101,4 +137,27 @@ export class OpenFeatureControllerContextScopedController {
) {
return feature.pipe(map((details) => this.testService.serviceMethod(details)));
}
@RequireFlagsEnabled({
flags: [{ flagKey: 'testBooleanFlag' }],
domain: 'domainScopedClient',
})
@Get('/controller-context/flags-enabled')
public async handleBooleanRequest() {
return 'Get Boolean Flag Success!';
}
}
@Controller('require-flags-enabled')
@RequireFlagsEnabled({
flags: [{ flagKey: 'testBooleanFlag', defaultValue: false }, { flagKey: 'testBooleanFlag2' }],
exception: new ForbiddenException(),
})
export class OpenFeatureRequireFlagsEnabledController {
constructor() {}
@Get('/')
public async handleGetRequest() {
return 'Hello, world!';
}
}

View File

@ -1,5 +1,63 @@
# Changelog
## [1.0.1](https://github.com/open-feature/js-sdk/compare/react-sdk-v1.0.0...react-sdk-v1.0.1) (2025-08-18)
### 🐛 Bug Fixes
* **react:** re-evaluate flags on re-render to detect silent provider … ([#1226](https://github.com/open-feature/js-sdk/issues/1226)) ([3105595](https://github.com/open-feature/js-sdk/commit/31055959265a53f52102590f54fa3168811ec678))
## [1.0.0](https://github.com/open-feature/js-sdk/compare/react-sdk-v0.4.11...react-sdk-v1.0.0) (2025-04-14)
### ✨ New Features
* add polyfill for react use hook ([#1157](https://github.com/open-feature/js-sdk/issues/1157)) ([5afe61f](https://github.com/open-feature/js-sdk/commit/5afe61f9e351b037b04c93a1d81aee8016756748))
* add support for abort controllers to event handlers ([#1151](https://github.com/open-feature/js-sdk/issues/1151)) ([6a22483](https://github.com/open-feature/js-sdk/commit/6a224830fa4e62fc30a7802536f6f6fc3f772038))
## [0.4.11](https://github.com/open-feature/js-sdk/compare/react-sdk-v0.4.10...react-sdk-v0.4.11) (2025-02-07)
### ✨ New Features
* export useOpenFeatureClientStatus hook ([#1082](https://github.com/open-feature/js-sdk/issues/1082)) ([4a6b860](https://github.com/open-feature/js-sdk/commit/4a6b8605444edeaf43355713357fecb97dd850b6))
### 🧹 Chore
* update sdk peer ([#1142](https://github.com/open-feature/js-sdk/issues/1142)) ([8bb6206](https://github.com/open-feature/js-sdk/commit/8bb620601e2b8dc7b62d717169b585bd1c886996))
## [0.4.10](https://github.com/open-feature/js-sdk/compare/react-sdk-v0.4.9...react-sdk-v0.4.10) (2024-12-18)
### 🔄 Refactoring
* export public option types ([#1101](https://github.com/open-feature/js-sdk/issues/1101)) ([16321c3](https://github.com/open-feature/js-sdk/commit/16321c31f27c5fce2c8e2adea893cf6e7e8ce3de))
## [0.4.9](https://github.com/open-feature/js-sdk/compare/react-sdk-v0.4.8...react-sdk-v0.4.9) (2024-12-04)
### ✨ New Features
* re-render if flagsChanged is falsy ([#1095](https://github.com/open-feature/js-sdk/issues/1095)) ([78516f4](https://github.com/open-feature/js-sdk/commit/78516f4181c82baf8c42fd64798fc2cfd8ff1056))
### 📚 Documentation
* fix typos, links, and format ([#1075](https://github.com/open-feature/js-sdk/issues/1075)) ([418409e](https://github.com/open-feature/js-sdk/commit/418409e3faafc6868a9f893267a4733db9931f93))
## [0.4.8](https://github.com/open-feature/js-sdk/compare/react-sdk-v0.4.7...react-sdk-v0.4.8) (2024-10-29)
### 🧹 Chore
* bump minimum web peer ([#1072](https://github.com/open-feature/js-sdk/issues/1072)) ([eca8205](https://github.com/open-feature/js-sdk/commit/eca8205da7945395d19c09a4da67cd4c2d516227))
### 📚 Documentation
* add tracking sections ([#1068](https://github.com/open-feature/js-sdk/issues/1068)) ([e131faf](https://github.com/open-feature/js-sdk/commit/e131faffad9025e9c7194f39558bf3b3cec31807))
## [0.4.7](https://github.com/open-feature/js-sdk/compare/react-sdk-v0.4.6...react-sdk-v0.4.7) (2024-10-29)

View File

@ -16,8 +16,8 @@
<img alt="Specification" src="https://img.shields.io/static/v1?label=specification&message=v0.8.0&color=yellow&style=for-the-badge" />
</a>
<!-- x-release-please-start-version -->
<a href="https://github.com/open-feature/js-sdk/releases/tag/react-sdk-v0.4.7">
<img alt="Release" src="https://img.shields.io/static/v1?label=release&message=v0.4.7&color=blue&style=for-the-badge" />
<a href="https://github.com/open-feature/js-sdk/releases/tag/react-sdk-v1.0.1">
<img alt="Release" src="https://img.shields.io/static/v1?label=release&message=v1.0.1&color=blue&style=for-the-badge" />
</a>
<!-- x-release-please-end -->
<br/>
@ -149,7 +149,7 @@ function Page() {
}
```
You can use the strongly-typed flag value and flag evaluation detail hooks as well, if you prefer.
You can use the strongly typed flag value and flag evaluation detail hooks as well if you prefer.
```tsx
import { useBooleanFlagValue } from '@openfeature/react-sdk';
@ -175,7 +175,7 @@ const {
Multiple providers can be used by passing a `domain` to the `OpenFeatureProvider`:
```tsx
// Flags within this domain will use the a client/provider associated with `my-domain`,
// Flags within this domain will use the client/provider associated with `my-domain`,
function App() {
return (
<OpenFeatureProvider domain={'my-domain'}>
@ -233,16 +233,19 @@ function Page() {
}
```
Note that if your provider doesn't support updates, this configuration has no impact.
If your provider doesn't support updates, this configuration has no impact.
> [!NOTE]
> If your provider includes a list of [flags changed](https://open-feature.github.io/js-sdk/types/_openfeature_server_sdk.ConfigChangeEvent.html) in its `PROVIDER_CONFIGURATION_CHANGED` event, that list of flags is used to decide which flag evaluation hooks should re-run by diffing the latest value of these flags with the previous render.
> If your provider event does not the include the `flags changed` list, then the SDK diffs all flags with the previous render to determine which hooks should re-run.
#### Suspense Support
> [!NOTE]
> React suspense is an experimental feature and subject to change in future versions.
> React suspense is an experimental feature and is subject to change in future versions.
Frequently, providers need to perform some initial startup tasks.
It may be desireable not to display components with feature flags until this is complete, or when the context changes.
It may be desirable not to display components with feature flags until this is complete or when the context changes.
Built-in [suspense](https://react.dev/reference/react/Suspense) support makes this easy.
Use `useSuspenseFlag` or pass `{ suspend: true }` in the hook options to leverage this functionality.
@ -283,22 +286,21 @@ This can be disabled in the hook options (or in the [OpenFeatureProvider](#openf
The tracking API allows you to use OpenFeature abstractions and objects to associate user actions with feature flag evaluations.
This is essential for robust experimentation powered by feature flags.
For example, a flag enhancing the appearance of a UI component might drive user engagement to a new feature; to test this hypothesis, telemetry collected by a [hook](#hooks) or [provider](#providers) can be associated with telemetry reported in the client's `track` function.
For example, a flag enhancing the appearance of a UI component might drive user engagement to a new feature; to test this hypothesis, telemetry collected by a [hook](https://openfeature.dev/docs/reference/technologies/client/web/#hooks) or [provider](https://openfeature.dev/docs/reference/technologies/client/web/#providers) can be associated with telemetry reported in the client's `track` function.
The React SDK includes a hook for firing tracking events in the <OpenFeatureProvider> context in use:
The React SDK includes a hook for firing tracking events in the `<OpenFeatureProvider>` context in use:
```tsx
function MyComponent() {
function MyComponent() {
// get a tracking function for this <OpenFeatureProvider>.
const { track } = useTrack();
// get a tracking function for this <OpenFeatureProvider>.
const { track } = useTrack();
// call the tracking event
// can be done in render, useEffect, or in handlers, depending on your use case
track(eventName, trackingDetails);
// call the tracking event
// can be done in render, useEffect, or in handlers, depending on your use case
track(eventName, trackingDetails);
return <>...</>;
}
return <>...</>;
}
```
### Testing
@ -365,23 +367,23 @@ class MyTestProvider implements Partial<Provider> {
> I get an error that says something like: `A React component suspended while rendering, but no fallback UI was specified.`
The OpenFeature React SDK features built-in [suspense support](#suspense-support).
This means that it will render your loading fallback automatically while the your provider starts up, and during context reconciliation for any of your components using feature flags!
This means that it will render your loading fallback automatically while your provider starts up and during context reconciliation for any of your components using feature flags!
If you use suspense and neglect to create a suspense boundary around any components using feature flags, you will see this error.
Add a suspense boundary to resolve this issue.
Alternatively, you can disable this suspense (the default) by removing `suspendWhileReconciling=true`, `suspendUntilReady=true` or `suspend=true` in the [evaluation hooks](#evaluation-hooks) or the [OpenFeatureProvider](#openfeatureprovider-context-provider) (which applies to all evaluation hooks in child components).
> I get odd rendering issues, or errors when components mount, if I use the suspense features.
> I get odd rendering issues or errors when components mount if I use the suspense features.
In React 16/17's "Legacy Suspense", when a component suspends, its sibling components initially mount and then are hidden.
This can cause surprising effects and inconsistencies if sibling components are rendered while the provider is still getting ready.
To fix this, you can upgrade to React 18, which uses "Concurrent Suspense", in which siblings are not mounted until their suspended sibling resolves.
Alternatively, if you cannot upgrade to React 18, you can use the `useWhenProviderReady` utility hook in any sibling components to prevent them from mounting until the provider is ready.
> I am using multiple `OpenFeatureProvider` contexts, but they are sharing the same provider or evaluation context. Why?
> I am using multiple `OpenFeatureProvider` contexts, but they share the same provider or evaluation context. Why?
The `OpenFeatureProvider` binds a `client` to all child components, but the provider and context associated with that client is controlled by the `domain` parameter.
This is consistent with all OpenFeature SDKs.
To scope an OpenFeatureProvider to a particular provider/context set the `domain` parameter on your `OpenFeatureProvider`:
To scope an OpenFeatureProvider to a particular provider/context, set the `domain` parameter on your `OpenFeatureProvider`:
```tsx
<OpenFeatureProvider domain={'my-domain'}>
@ -391,7 +393,7 @@ To scope an OpenFeatureProvider to a particular provider/context set the `domain
> I can import things form the `@openfeature/react-sdk`, `@openfeature/web-sdk`, and `@openfeature/core`; which should I use?
The `@openfeature/react-sdk` re-exports everything from its peers (`@openfeature/web-sdk` and `@openfeature/core`), and adds the React-specific features.
The `@openfeature/react-sdk` re-exports everything from its peers (`@openfeature/web-sdk` and `@openfeature/core`) and adds the React-specific features.
You can import everything from the `@openfeature/react-sdk` directly.
Avoid importing anything from `@openfeature/web-sdk` or `@openfeature/core`.

View File

@ -1,6 +1,6 @@
{
"name": "@openfeature/react-sdk",
"version": "0.4.7",
"version": "1.0.1",
"description": "OpenFeature React SDK",
"main": "./dist/cjs/index.js",
"files": [
@ -47,7 +47,7 @@
},
"homepage": "https://github.com/open-feature/js-sdk#readme",
"peerDependencies": {
"@openfeature/web-sdk": "^1.2.2",
"@openfeature/web-sdk": "^1.5.0",
"react": ">=16.8.0"
},
"devDependencies": {

View File

@ -1,83 +0,0 @@
import type { FlagEvaluationOptions } from '@openfeature/web-sdk';
export type ReactFlagEvaluationOptions = ({
/**
* Enable or disable all suspense functionality.
* Cannot be used in conjunction with `suspendUntilReady` and `suspendWhileReconciling` options.
* @experimental Suspense is an experimental feature subject to change in future versions.
*/
suspend?: boolean;
suspendUntilReady?: never;
suspendWhileReconciling?: never;
} | {
/**
* Suspend flag evaluations while the provider is not ready.
* Set to false if you don't want to show suspense fallbacks until the provider is initialized.
* Defaults to false.
* Cannot be used in conjunction with `suspend` option.
* @experimental Suspense is an experimental feature subject to change in future versions.
*/
suspendUntilReady?: boolean;
/**
* Suspend flag evaluations while the provider's context is being reconciled.
* Set to true if you want to show suspense fallbacks while flags are re-evaluated after context changes.
* Defaults to false.
* Cannot be used in conjunction with `suspend` option.
* @experimental Suspense is an experimental feature subject to change in future versions.
*/
suspendWhileReconciling?: boolean;
suspend?: never;
}) & {
/**
* Update the component if the provider emits a ConfigurationChanged event.
* Set to false to prevent components from re-rendering when flag value changes
* are received by the associated provider.
* Defaults to true.
*/
updateOnConfigurationChanged?: boolean;
/**
* Update the component when the OpenFeature context changes.
* Set to false to prevent components from re-rendering when attributes which
* may be factors in flag evaluation change.
* Defaults to true.
*/
updateOnContextChanged?: boolean;
} & FlagEvaluationOptions;
export type NormalizedOptions = Omit<ReactFlagEvaluationOptions, 'suspend'>;
/**
* Default options.
* DO NOT EXPORT PUBLICLY
* @internal
*/
export const DEFAULT_OPTIONS: ReactFlagEvaluationOptions = {
updateOnContextChanged: true,
updateOnConfigurationChanged: true,
suspendUntilReady: false,
suspendWhileReconciling: false,
};
/**
* Returns normalization options (all `undefined` fields removed, and `suspend` decomposed to `suspendUntilReady` and `suspendWhileReconciling`).
* DO NOT EXPORT PUBLICLY
* @internal
* @param {ReactFlagEvaluationOptions} options options to normalize
* @returns {NormalizedOptions} normalized options
*/
export const normalizeOptions: (options?: ReactFlagEvaluationOptions) => NormalizedOptions = (options: ReactFlagEvaluationOptions = {}) => {
const updateOnContextChanged = options.updateOnContextChanged;
const updateOnConfigurationChanged = options.updateOnConfigurationChanged;
// fall-back the suspense options to the catch-all `suspend` property
const suspendUntilReady = 'suspendUntilReady' in options ? options.suspendUntilReady : options.suspend;
const suspendWhileReconciling = 'suspendWhileReconciling' in options ? options.suspendWhileReconciling : options.suspend;
return {
// only return these if properly set (no undefined to allow overriding with spread)
...(typeof suspendUntilReady === 'boolean' && {suspendUntilReady}),
...(typeof suspendWhileReconciling === 'boolean' && {suspendWhileReconciling}),
...(typeof updateOnContextChanged === 'boolean' && {updateOnContextChanged}),
...(typeof updateOnConfigurationChanged === 'boolean' && {updateOnConfigurationChanged}),
};
};

View File

@ -1,21 +0,0 @@
import type { Client} from '@openfeature/web-sdk';
import { ProviderEvents } from '@openfeature/web-sdk';
/**
* Suspends until the client is ready to evaluate feature flags.
* DO NOT EXPORT PUBLICLY
* @param {Client} client OpenFeature client
*/
export function suspendUntilReady(client: Client): Promise<void> {
let resolve: (value: unknown) => void;
let reject: () => void;
throw new Promise((_resolve, _reject) => {
resolve = _resolve;
reject = _reject;
client.addHandler(ProviderEvents.Ready, resolve);
client.addHandler(ProviderEvents.Error, reject);
}).finally(() => {
client.removeHandler(ProviderEvents.Ready, resolve);
client.removeHandler(ProviderEvents.Ready, reject);
});
}

View File

@ -1,7 +1,7 @@
import { useCallback, useContext, useRef } from 'react';
import type { EvaluationContext } from '@openfeature/web-sdk';
import { OpenFeature } from '@openfeature/web-sdk';
import { Context } from '../common';
import { Context } from '../internal';
export type ContextMutationOptions = {
/**

View File

@ -5,18 +5,24 @@ import type {
EventHandler,
FlagEvaluationOptions,
FlagValue,
JsonValue} from '@openfeature/web-sdk';
import {
ProviderEvents,
ProviderStatus,
JsonValue,
} from '@openfeature/web-sdk';
import { useEffect, useRef, useState } from 'react';
import type { ReactFlagEvaluationOptions} from '../common';
import { DEFAULT_OPTIONS, isEqual, normalizeOptions, suspendUntilReady, useProviderOptions } from '../common';
import { ProviderEvents, ProviderStatus } from '@openfeature/web-sdk';
import { useCallback, useEffect, useRef, useState } from 'react';
import {
DEFAULT_OPTIONS,
isEqual,
normalizeOptions,
suspendUntilInitialized,
suspendUntilReconciled,
useProviderOptions,
} from '../internal';
import type { ReactFlagEvaluationNoSuspenseOptions, ReactFlagEvaluationOptions } from '../options';
import { useOpenFeatureClient } from '../provider/use-open-feature-client';
import { useOpenFeatureClientStatus } from '../provider/use-open-feature-client-status';
import { useOpenFeatureProvider } from '../provider/use-open-feature-provider';
import type { FlagQuery } from '../query';
import { HookFlagQuery } from './hook-flag-query';
import { HookFlagQuery } from '../internal/hook-flag-query';
// This type is a bit wild-looking, but I think we need it.
// We have to use the conditional, because otherwise useFlag('key', false) would return false, not boolean (too constrained).
@ -33,9 +39,6 @@ type ConstrainedFlagQuery<T> = FlagQuery<
: JsonValue
>;
// suspense options removed for the useSuspenseFlag hooks
type NoSuspenseOptions = Omit<ReactFlagEvaluationOptions, 'suspend' | 'suspendUntilReady' | 'suspendWhileReconciling'>;
/**
* Evaluates a feature flag generically, returning an react-flavored queryable object.
* The resolver method to use is based on the type of the defaultValue.
@ -84,13 +87,13 @@ type UseFlagReturn<T extends FlagValue> = ReturnType<typeof useFlag<T>>;
* @param {string} flagKey the flag identifier
* @template {FlagValue} T A optional generic argument constraining the default.
* @param {T} defaultValue the default value; used to determine what resolved type should be used.
* @param {NoSuspenseOptions} options for this evaluation
* @param {ReactFlagEvaluationNoSuspenseOptions} options for this evaluation
* @returns { UseFlagReturn<T> } a queryable object containing useful information about the flag.
*/
export function useSuspenseFlag<T extends FlagValue = FlagValue>(
flagKey: string,
defaultValue: T,
options?: NoSuspenseOptions,
options?: ReactFlagEvaluationNoSuspenseOptions,
): UseFlagReturn<T> {
return useFlag(flagKey, defaultValue, { ...options, suspendUntilReady: true, suspendWhileReconciling: true });
}
@ -267,7 +270,8 @@ export function useObjectFlagDetails<T extends JsonValue = JsonValue>(
// determines if a flag should be re-evaluated based on a list of changed flags
function shouldEvaluateFlag(flagKey: string, flagsChanged?: string[]): boolean {
return !!flagsChanged && flagsChanged.includes(flagKey);
// if flagsChange is missing entirely, we don't know what to re-render
return !flagsChanged || flagsChanged.includes(flagKey);
}
function attachHandlersAndResolve<T extends FlagValue>(
@ -282,19 +286,33 @@ function attachHandlersAndResolve<T extends FlagValue>(
const defaultedOptions = { ...DEFAULT_OPTIONS, ...useProviderOptions(), ...normalizeOptions(options) };
const client = useOpenFeatureClient();
const status = useOpenFeatureClientStatus();
const provider = useOpenFeatureProvider();
const isFirstRender = useRef(true);
// suspense
if (defaultedOptions.suspendUntilReady && status === ProviderStatus.NOT_READY) {
suspendUntilReady(client);
suspendUntilInitialized(provider, client);
}
if (defaultedOptions.suspendWhileReconciling && status === ProviderStatus.RECONCILING) {
suspendUntilReady(client);
suspendUntilReconciled(client);
}
const [evaluationDetails, setEvaluationDetails] = useState<EvaluationDetails<T>>(
const [evaluationDetails, setEvaluationDetails] = useState<EvaluationDetails<T>>(() =>
resolver(client).call(client, flagKey, defaultValue, options),
);
// Re-evaluate when dependencies change (handles prop changes like flagKey), or if during a re-render, we have detected a change in the evaluated value
useEffect(() => {
if (isFirstRender.current) {
isFirstRender.current = false;
return;
}
const newDetails = resolver(client).call(client, flagKey, defaultValue, options);
if (!isEqual(newDetails.value, evaluationDetails.value)) {
setEvaluationDetails(newDetails);
}
}, [client, flagKey, defaultValue, options, resolver, evaluationDetails]);
// Maintain a mutable reference to the evaluation details to have a up-to-date reference in the handlers.
const evaluationDetailsRef = useRef<EvaluationDetails<T>>(evaluationDetails);
@ -302,7 +320,7 @@ function attachHandlersAndResolve<T extends FlagValue>(
evaluationDetailsRef.current = evaluationDetails;
}, [evaluationDetails]);
const updateEvaluationDetailsCallback = () => {
const updateEvaluationDetailsCallback = useCallback(() => {
const updatedEvaluationDetails = resolver(client).call(client, flagKey, defaultValue, options);
/**
@ -313,41 +331,47 @@ function attachHandlersAndResolve<T extends FlagValue>(
if (!isEqual(updatedEvaluationDetails.value, evaluationDetailsRef.current.value)) {
setEvaluationDetails(updatedEvaluationDetails);
}
};
}, [client, flagKey, defaultValue, options, resolver]);
const configurationChangeCallback: EventHandler<ClientProviderEvents.ConfigurationChanged> = (eventDetails) => {
if (shouldEvaluateFlag(flagKey, eventDetails?.flagsChanged)) {
updateEvaluationDetailsCallback();
}
};
const configurationChangeCallback = useCallback<EventHandler<ClientProviderEvents.ConfigurationChanged>>(
(eventDetails) => {
if (shouldEvaluateFlag(flagKey, eventDetails?.flagsChanged)) {
updateEvaluationDetailsCallback();
}
},
[flagKey, updateEvaluationDetailsCallback],
);
useEffect(() => {
const controller = new AbortController();
if (status === ProviderStatus.NOT_READY) {
// update when the provider is ready
client.addHandler(ProviderEvents.Ready, updateEvaluationDetailsCallback);
client.addHandler(ProviderEvents.Ready, updateEvaluationDetailsCallback, { signal: controller.signal });
}
if (defaultedOptions.updateOnContextChanged) {
// update when the context changes
client.addHandler(ProviderEvents.ContextChanged, updateEvaluationDetailsCallback);
client.addHandler(ProviderEvents.ContextChanged, updateEvaluationDetailsCallback, { signal: controller.signal });
}
return () => {
// cleanup the handlers
client.removeHandler(ProviderEvents.Ready, updateEvaluationDetailsCallback);
client.removeHandler(ProviderEvents.ContextChanged, updateEvaluationDetailsCallback);
};
}, []);
useEffect(() => {
if (defaultedOptions.updateOnConfigurationChanged) {
// update when the provider configuration changes
client.addHandler(ProviderEvents.ConfigurationChanged, configurationChangeCallback);
client.addHandler(ProviderEvents.ConfigurationChanged, configurationChangeCallback, {
signal: controller.signal,
});
}
return () => {
// cleanup the handlers
client.removeHandler(ProviderEvents.ConfigurationChanged, configurationChangeCallback);
controller.abort();
};
}, []);
}, [
client,
status,
defaultedOptions.updateOnContextChanged,
defaultedOptions.updateOnConfigurationChanged,
updateEvaluationDetailsCallback,
configurationChangeCallback,
]);
return evaluationDetails;
}

View File

@ -3,5 +3,6 @@ export * from './query';
export * from './provider';
export * from './context';
export * from './tracking';
export * from './options';
// re-export the web-sdk so consumers can access that API from the react-sdk
export * from '@openfeature/web-sdk';

View File

@ -1,18 +1,22 @@
import type { Client } from '@openfeature/web-sdk';
import React from 'react';
import type { NormalizedOptions, ReactFlagEvaluationOptions} from '../common';
import { normalizeOptions } from '../common';
import type { NormalizedOptions, ReactFlagEvaluationOptions } from '../options';
import { normalizeOptions } from '.';
/**
* The underlying React context.
* DO NOT EXPORT PUBLICLY
*
* **DO NOT EXPORT PUBLICLY**
* @internal
*/
export const Context = React.createContext<{ client: Client; domain?: string; options: ReactFlagEvaluationOptions } | undefined>(undefined);
export const Context = React.createContext<
{ client: Client; domain?: string; options: ReactFlagEvaluationOptions } | undefined
>(undefined);
/**
* Get a normalized copy of the options used for this OpenFeatureProvider, see {@link normalizeOptions}.
* DO NOT EXPORT PUBLICLY
*
* **DO NOT EXPORT PUBLICLY**
* @internal
* @returns {NormalizedOptions} normalized options the defaulted options, not defaulted or normalized.
*/

View File

@ -0,0 +1,9 @@
const context = 'Components using OpenFeature must be wrapped with an <OpenFeatureProvider>.';
const tip = 'If you are seeing this in a test, see: https://openfeature.dev/docs/reference/technologies/client/web/react#testing';
export class MissingContextError extends Error {
constructor(reason: string) {
super(`${reason}: ${context} ${tip}`);
this.name = 'MissingContextError';
}
}

View File

@ -0,0 +1,40 @@
import type { ReactFlagEvaluationOptions, NormalizedOptions } from '../options';
/**
* Default options.
* DO NOT EXPORT PUBLICLY
* @internal
*/
export const DEFAULT_OPTIONS: ReactFlagEvaluationOptions = {
updateOnContextChanged: true,
updateOnConfigurationChanged: true,
suspendUntilReady: false,
suspendWhileReconciling: false,
};
/**
* Returns normalization options (all `undefined` fields removed, and `suspend` decomposed to `suspendUntilReady` and `suspendWhileReconciling`).
* DO NOT EXPORT PUBLICLY
* @internal
* @param {ReactFlagEvaluationOptions} options options to normalize
* @returns {NormalizedOptions} normalized options
*/
export const normalizeOptions: (options?: ReactFlagEvaluationOptions) => NormalizedOptions = (
options: ReactFlagEvaluationOptions = {},
) => {
const updateOnContextChanged = options.updateOnContextChanged;
const updateOnConfigurationChanged = options.updateOnConfigurationChanged;
// fall-back the suspense options to the catch-all `suspend` property
const suspendUntilReady = 'suspendUntilReady' in options ? options.suspendUntilReady : options.suspend;
const suspendWhileReconciling =
'suspendWhileReconciling' in options ? options.suspendWhileReconciling : options.suspend;
return {
// only return these if properly set (no undefined to allow overriding with spread)
...(typeof suspendUntilReady === 'boolean' && { suspendUntilReady }),
...(typeof suspendWhileReconciling === 'boolean' && { suspendWhileReconciling }),
...(typeof updateOnContextChanged === 'boolean' && { updateOnContextChanged }),
...(typeof updateOnConfigurationChanged === 'boolean' && { updateOnConfigurationChanged }),
};
};

View File

@ -0,0 +1,56 @@
import type { Client, Provider } from '@openfeature/web-sdk';
import { NOOP_PROVIDER, ProviderEvents } from '@openfeature/web-sdk';
import { use } from './use';
/**
* A weak map is used to store the global suspense status for each provider. It's
* important for this to be global to avoid rerender loops. Using useRef won't
* work because the value isn't preserved when a promise is thrown in a component,
* which is how suspense operates.
*/
const globalProviderSuspenseStatus = new WeakMap<Provider, Promise<unknown>>();
/**
* Suspends until the client is ready to evaluate feature flags.
*
* **DO NOT EXPORT PUBLICLY**
* @internal
* @param {Provider} provider the provider to suspend for
* @param {Client} client the client to check for readiness
*/
export function suspendUntilInitialized(provider: Provider, client: Client) {
const statusPromiseRef = globalProviderSuspenseStatus.get(provider);
if (!statusPromiseRef) {
// Noop provider is never ready, so we resolve immediately
const statusPromise = provider !== NOOP_PROVIDER ? isProviderReady(client) : Promise.resolve();
globalProviderSuspenseStatus.set(provider, statusPromise);
// Use will throw the promise and React will trigger a rerender when it's resolved
use(statusPromise);
} else {
// Reuse the existing promise, use won't rethrow if the promise has settled.
use(statusPromiseRef);
}
}
/**
* Suspends until the provider has finished reconciling.
*
* **DO NOT EXPORT PUBLICLY**
* @internal
* @param {Client} client the client to check for readiness
*/
export function suspendUntilReconciled(client: Client) {
use(isProviderReady(client));
}
async function isProviderReady(client: Client) {
const controller = new AbortController();
try {
return await new Promise((resolve, reject) => {
client.addHandler(ProviderEvents.Ready, resolve, { signal: controller.signal });
client.addHandler(ProviderEvents.Error, reject, { signal: controller.signal });
});
} finally {
controller.abort();
}
}

View File

@ -0,0 +1,53 @@
/// <reference types="react/experimental" />
// This function is adopted from https://github.com/vercel/swr
import React from 'react';
/**
* Extends a Promise-like value to include status tracking.
* The extra properties are used to manage the lifecycle of the Promise, indicating its current state.
* More information can be found in the React RFE for the use hook.
* @see https://github.com/reactjs/rfcs/pull/229
*/
export type UsePromise<T> =
Promise<T> & {
status?: 'pending' | 'fulfilled' | 'rejected';
value?: T;
reason?: unknown;
};
/**
* React.use is a React API that lets you read the value of a resource like a Promise or context.
* It was officially added in React 19, so needs to be polyfilled to support older React versions.
* @param {UsePromise} thenable A thenable object that represents a Promise-like value.
* @returns {unknown} The resolved value of the thenable or throws if it's still pending or rejected.
*/
export const use =
React.use ||
// This extra generic is to avoid TypeScript mixing up the generic and JSX syntax
// and emitting an error.
// We assume that this is only for the `use(thenable)` case, not `use(context)`.
// https://github.com/facebook/react/blob/aed00dacfb79d17c53218404c52b1c7aa59c4a89/packages/react-server/src/ReactFizzThenable.js#L45
// eslint-disable-next-line @typescript-eslint/no-unused-vars
(<T, _>(thenable: UsePromise<T>): T => {
switch (thenable.status) {
case 'pending':
throw thenable;
case 'fulfilled':
return thenable.value as T;
case 'rejected':
throw thenable.reason;
default:
thenable.status = 'pending';
thenable.then(
(v) => {
thenable.status = 'fulfilled';
thenable.value = v;
},
(e) => {
thenable.status = 'rejected';
thenable.reason = e;
},
);
throw thenable;
}
});

View File

@ -0,0 +1,53 @@
import type { FlagEvaluationOptions } from '@openfeature/web-sdk';
export type ReactFlagEvaluationOptions = (
| {
/**
* Enable or disable all suspense functionality.
* Cannot be used in conjunction with `suspendUntilReady` and `suspendWhileReconciling` options.
* @experimental Suspense is an experimental feature subject to change in future versions.
*/
suspend?: boolean;
suspendUntilReady?: never;
suspendWhileReconciling?: never;
}
| {
/**
* Suspend flag evaluations while the provider is not ready.
* Set to false if you don't want to show suspense fallbacks until the provider is initialized.
* Defaults to false.
* Cannot be used in conjunction with `suspend` option.
* @experimental Suspense is an experimental feature subject to change in future versions.
*/
suspendUntilReady?: boolean;
/**
* Suspend flag evaluations while the provider's context is being reconciled.
* Set to true if you want to show suspense fallbacks while flags are re-evaluated after context changes.
* Defaults to false.
* Cannot be used in conjunction with `suspend` option.
* @experimental Suspense is an experimental feature subject to change in future versions.
*/
suspendWhileReconciling?: boolean;
suspend?: never;
}
) & {
/**
* Update the component if the provider emits a ConfigurationChanged event.
* Set to false to prevent components from re-rendering when flag value changes
* are received by the associated provider.
* Defaults to true.
*/
updateOnConfigurationChanged?: boolean;
/**
* Update the component when the OpenFeature context changes.
* Set to false to prevent components from re-rendering when attributes which
* may be factors in flag evaluation change.
* Defaults to true.
*/
updateOnContextChanged?: boolean;
} & FlagEvaluationOptions;
// suspense options removed for the useSuspenseFlag hooks
export type ReactFlagEvaluationNoSuspenseOptions = Omit<ReactFlagEvaluationOptions, 'suspend' | 'suspendUntilReady' | 'suspendWhileReconciling'>;
export type NormalizedOptions = Omit<ReactFlagEvaluationOptions, 'suspend'>;

View File

@ -1,4 +1,5 @@
export * from './provider';
export * from './use-open-feature-client';
export * from './use-when-provider-ready';
export * from './use-open-feature-client-status';
export * from './test-provider';

View File

@ -1,8 +1,8 @@
import type { Client} from '@openfeature/web-sdk';
import { OpenFeature } from '@openfeature/web-sdk';
import * as React from 'react';
import type { ReactFlagEvaluationOptions } from '../common';
import { Context } from '../common';
import type { ReactFlagEvaluationOptions } from '../options';
import { Context } from '../internal';
type ClientOrDomain =
| {
@ -31,7 +31,7 @@ type ProviderProps = {
* @param {ProviderProps} properties props for the context provider
* @returns {OpenFeatureProvider} context provider
*/
export function OpenFeatureProvider({ client, domain, children, ...options }: ProviderProps) {
export function OpenFeatureProvider({ client, domain, children, ...options }: ProviderProps): JSX.Element {
if (!client) {
client = OpenFeature.getClient(domain);
}

View File

@ -7,7 +7,7 @@ import {
OpenFeature
} from '@openfeature/web-sdk';
import React from 'react';
import type { NormalizedOptions } from '../common';
import type { NormalizedOptions } from '../options';
import { OpenFeatureProvider } from './provider';
type FlagValueMap = { [flagKey: string]: JsonValue };

View File

@ -9,23 +9,19 @@ import { ProviderEvents } from '@openfeature/web-sdk';
*/
export function useOpenFeatureClientStatus(): ProviderStatus {
const client = useOpenFeatureClient();
const [status, setStatus] = useState(client.providerStatus);
const [status, setStatus] = useState<ProviderStatus>(client.providerStatus);
const controller = new AbortController();
useEffect(() => {
const updateStatus = () => setStatus(client.providerStatus);
client.addHandler(ProviderEvents.ConfigurationChanged, updateStatus);
client.addHandler(ProviderEvents.ContextChanged, updateStatus);
client.addHandler(ProviderEvents.Error, updateStatus);
client.addHandler(ProviderEvents.Ready, updateStatus);
client.addHandler(ProviderEvents.Stale, updateStatus);
client.addHandler(ProviderEvents.Reconciling, updateStatus);
client.addHandler(ProviderEvents.ConfigurationChanged, updateStatus, { signal: controller.signal });
client.addHandler(ProviderEvents.ContextChanged, updateStatus, { signal: controller.signal });
client.addHandler(ProviderEvents.Error, updateStatus, { signal: controller.signal });
client.addHandler(ProviderEvents.Ready, updateStatus, { signal: controller.signal });
client.addHandler(ProviderEvents.Stale, updateStatus, { signal: controller.signal });
client.addHandler(ProviderEvents.Reconciling, updateStatus, { signal: controller.signal });
return () => {
client.removeHandler(ProviderEvents.ConfigurationChanged, updateStatus);
client.removeHandler(ProviderEvents.ContextChanged, updateStatus);
client.removeHandler(ProviderEvents.Error, updateStatus);
client.removeHandler(ProviderEvents.Ready, updateStatus);
client.removeHandler(ProviderEvents.Stale, updateStatus);
client.removeHandler(ProviderEvents.Reconciling, updateStatus);
controller.abort();
};
}, [client]);

View File

@ -1,6 +1,7 @@
import React from 'react';
import { Context } from '../common';
import type { Client } from '@openfeature/web-sdk';
import { Context } from '../internal';
import { type Client } from '@openfeature/web-sdk';
import { MissingContextError } from '../internal/errors';
/**
* Get the {@link Client} instance for this OpenFeatureProvider context.
@ -11,9 +12,7 @@ export function useOpenFeatureClient(): Client {
const { client } = React.useContext(Context) || {};
if (!client) {
throw new Error(
'No OpenFeature client available - components using OpenFeature must be wrapped with an <OpenFeatureProvider>. If you are seeing this in a test, see: https://openfeature.dev/docs/reference/technologies/client/web/react#testing',
);
throw new MissingContextError('No OpenFeature client available');
}
return client;

View File

@ -0,0 +1,21 @@
import React from 'react';
import { Context } from '../internal';
import { OpenFeature } from '@openfeature/web-sdk';
import type { Provider } from '@openfeature/web-sdk';
import { MissingContextError } from '../internal/errors';
/**
* Get the {@link Provider} bound to the domain specified in the OpenFeatureProvider context.
* Note that it isn't recommended to interact with the provider directly, but rather through
* an OpenFeature client.
* @returns {Provider} provider for this scope
*/
export function useOpenFeatureProvider(): Provider {
const openFeatureContext = React.useContext(Context);
if (!openFeatureContext) {
throw new MissingContextError('No OpenFeature context available');
}
return OpenFeature.getProvider(openFeatureContext.domain);
}

View File

@ -1,8 +1,9 @@
import { ProviderStatus } from '@openfeature/web-sdk';
import { useOpenFeatureClient } from './use-open-feature-client';
import { useOpenFeatureClientStatus } from './use-open-feature-client-status';
import type { ReactFlagEvaluationOptions} from '../common';
import { DEFAULT_OPTIONS, useProviderOptions, normalizeOptions, suspendUntilReady } from '../common';
import type { ReactFlagEvaluationOptions } from '../options';
import { DEFAULT_OPTIONS, useProviderOptions, normalizeOptions, suspendUntilInitialized } from '../internal';
import { useOpenFeatureProvider } from './use-open-feature-provider';
type Options = Pick<ReactFlagEvaluationOptions, 'suspendUntilReady'>;
@ -14,14 +15,14 @@ type Options = Pick<ReactFlagEvaluationOptions, 'suspendUntilReady'>;
* @returns {boolean} boolean indicating if provider is {@link ProviderStatus.READY}, useful if suspense is disabled and you want to handle loaders on your own
*/
export function useWhenProviderReady(options?: Options): boolean {
const client = useOpenFeatureClient();
const status = useOpenFeatureClientStatus();
// highest priority > evaluation hook options > provider options > default options > lowest priority
const defaultedOptions = { ...DEFAULT_OPTIONS, ...useProviderOptions(), ...normalizeOptions(options) };
const client = useOpenFeatureClient();
const status = useOpenFeatureClientStatus();
const provider = useOpenFeatureProvider();
// suspense
if (defaultedOptions.suspendUntilReady && status === ProviderStatus.NOT_READY) {
suspendUntilReady(client);
suspendUntilInitialized(provider, client);
}
return status === ProviderStatus.READY;

View File

@ -1,10 +1,12 @@
import { jest } from '@jest/globals';
import type { ProviderEmittableEvents } from '@openfeature/web-sdk';
import { ClientProviderEvents } from '@openfeature/web-sdk';
import type { FlagConfiguration } from '@openfeature/web-sdk/src/provider/in-memory-provider/flag-configuration';
import '@testing-library/jest-dom'; // see: https://testing-library.com/docs/react-testing-library/setup
import { act, render, renderHook, screen, waitFor } from '@testing-library/react';
import * as React from 'react';
import type {
EvaluationContext,
EvaluationDetails,
Hook} from '../src/';
import { startTransition, useState } from 'react';
import type { EvaluationContext, EvaluationDetails, EventContext, Hook } from '../src/';
import {
ErrorCode,
InMemoryProvider,
@ -22,10 +24,21 @@ import {
useStringFlagValue,
useSuspenseFlag,
} from '../src/';
import { HookFlagQuery } from '../src/internal/hook-flag-query';
import { TestingProvider } from './test.utils';
import { HookFlagQuery } from '../src/evaluation/hook-flag-query';
import { startTransition, useState } from 'react';
import { jest } from '@jest/globals';
// custom provider to have better control over the emitted events
class CustomEventInMemoryProvider extends InMemoryProvider {
putConfigurationWithCustomEvent(
flagConfiguration: FlagConfiguration,
event: ProviderEmittableEvents,
eventContext: EventContext,
) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
this['_flagConfiguration'] = { ...flagConfiguration }; // private access hack
this.events.emit(event, eventContext);
}
}
describe('evaluation', () => {
const EVALUATION = 'evaluation';
@ -262,7 +275,7 @@ describe('evaluation', () => {
describe('re-render', () => {
const RERENDER_DOMAIN = 'rerender';
const rerenderProvider = new InMemoryProvider(FLAG_CONFIG);
const rerenderProvider = new CustomEventInMemoryProvider(FLAG_CONFIG);
function TestComponentFactory() {
let renderCount = 0;
@ -370,7 +383,7 @@ describe('evaluation', () => {
expect(screen.queryByTestId('render-count')).toHaveTextContent('2');
});
it('should not render on flag change because the provider did not include changed flags in the change event', async () => {
it('should not render on flag change when the provider change event has empty flagsChanged', async () => {
const TestComponent = TestComponentFactory();
render(
<OpenFeatureProvider domain={RERENDER_DOMAIN}>
@ -380,14 +393,52 @@ describe('evaluation', () => {
expect(screen.queryByTestId('render-count')).toHaveTextContent('1');
await act(async () => {
await rerenderProvider.putConfiguration({
...FLAG_CONFIG,
});
await rerenderProvider.putConfigurationWithCustomEvent(
{
...FLAG_CONFIG,
[BOOL_FLAG_KEY]: {
...FLAG_CONFIG[BOOL_FLAG_KEY],
// Change the default; this should be ignored and not cause a re-render because flagsChanged is empty
defaultVariant: 'off',
},
// if the flagsChanged is empty, we know nothing has changed, so we don't bother diffing
},
ClientProviderEvents.ConfigurationChanged,
{ flagsChanged: [] },
);
});
expect(screen.queryByTestId('render-count')).toHaveTextContent('1');
});
it('should re-render on flag change because the provider change event has falsy flagsChanged', async () => {
const TestComponent = TestComponentFactory();
render(
<OpenFeatureProvider domain={RERENDER_DOMAIN}>
<TestComponent></TestComponent>
</OpenFeatureProvider>,
);
expect(screen.queryByTestId('render-count')).toHaveTextContent('1');
await act(async () => {
await rerenderProvider.putConfigurationWithCustomEvent(
{
...FLAG_CONFIG,
[BOOL_FLAG_KEY]: {
...FLAG_CONFIG[BOOL_FLAG_KEY],
// Change the default variant to trigger a rerender since not only do we check flagsChanged, but we also diff the value
defaultVariant: 'off',
},
// if the flagsChanged is falsy, we don't know what flags changed - so we attempt to diff everything
},
ClientProviderEvents.ConfigurationChanged,
{ flagsChanged: undefined },
);
});
expect(screen.queryByTestId('render-count')).toHaveTextContent('2');
});
it('should not rerender on flag change because the evaluated values did not change', async () => {
const TestComponent = TestComponentFactory();
render(
@ -526,10 +577,41 @@ describe('evaluation', () => {
},
};
afterEach(() => {
OpenFeature.clearProviders();
});
const suspendingProvider = () => {
return new TestingProvider(CONFIG, DELAY); // delay init by 100ms
};
describe('when using the noop provider', () => {
function TestComponent() {
const { value } = useSuspenseFlag(SUSPENSE_FLAG_KEY, DEFAULT);
return (
<>
<div>{value}</div>
</>
);
}
it('should fallback to the default value on the next rerender', async () => {
render(
<OpenFeatureProvider>
<React.Suspense fallback={<div>{FALLBACK}</div>}>
<TestComponent></TestComponent>
</React.Suspense>
</OpenFeatureProvider>,
);
// The loading indicator should be shown on the first render
expect(screen.queryByText(FALLBACK)).toBeInTheDocument();
// The default value should be shown on the next render
await waitFor(() => expect(screen.queryByText(DEFAULT)).toBeInTheDocument(), {
timeout: DELAY,
});
});
});
describe('updateOnConfigurationChanged=true (default)', () => {
function TestComponent() {
const { value } = useFlag(SUSPENSE_FLAG_KEY, DEFAULT);
@ -842,17 +924,124 @@ describe('evaluation', () => {
OpenFeature.setContext(SUSPEND_OFF, { user: TARGETED_USER });
});
// expect to see static value until we reconcile
await waitFor(() => expect(screen.queryByText(STATIC_FLAG_VALUE_A)).toBeInTheDocument(), {
timeout: DELAY / 2,
});
// make sure we updated after reconciling
// With the fix for useState initialization, the hook now immediately
// reflects provider state changes. This is intentional to handle cases
// where providers don't emit proper events.
// The value updates immediately to the targeted value.
await waitFor(() => expect(screen.queryByText(TARGETED_FLAG_VALUE)).toBeInTheDocument(), {
timeout: DELAY * 2,
});
});
});
describe('re-render behavior when flag values change without provider events', ()=> {
it('should reflect provider state changes on re-render even without provider events', async () => {
let providerValue = 'initial-value';
class SilentUpdateProvider extends InMemoryProvider {
resolveBooleanEvaluation() {
return {
value: true,
variant: 'on',
reason: StandardResolutionReasons.STATIC,
};
}
resolveStringEvaluation() {
return {
value: providerValue,
variant: providerValue,
reason: StandardResolutionReasons.STATIC,
};
}
}
const provider = new SilentUpdateProvider({});
await OpenFeature.setProviderAndWait('test', provider);
// The triggerRender prop forces a re-render
const TestComponent = ({ triggerRender }: { triggerRender: number }) => {
const { value } = useFlag('test-flag', 'default');
return <div data-testid="flag-value" data-render-count={triggerRender}>{value}</div>;
};
const WrapperComponent = () => {
const [renderCount, setRenderCount] = useState(0);
return (
<>
<button onClick={() => setRenderCount(c => c + 1)}>Force Re-render</button>
<TestComponent triggerRender={renderCount} />
</>
);
};
const { getByText } = render(
<OpenFeatureProvider client={OpenFeature.getClient('test')}>
<WrapperComponent />
</OpenFeatureProvider>
);
// Initial value should be rendered
await waitFor(() => {
expect(screen.getByTestId('flag-value')).toHaveTextContent('initial-value');
});
// Change the provider's internal state (without emitting events)
providerValue = 'updated-value';
// Force a re-render of the component
act(() => {
getByText('Force Re-render').click();
});
await waitFor(() => {
expect(screen.getByTestId('flag-value')).toHaveTextContent('updated-value');
});
});
it('should update flag value when flag key prop changes without provider events', async () => {
const provider = new InMemoryProvider({
'flag-a': {
disabled: false,
variants: { on: 'value-a' },
defaultVariant: 'on',
},
'flag-b': {
disabled: false,
variants: { on: 'value-b' },
defaultVariant: 'on',
},
});
await OpenFeature.setProviderAndWait(EVALUATION, provider);
const TestComponent = ({ flagKey }: { flagKey: string }) => {
const { value } = useFlag(flagKey, 'default');
return <div data-testid="flag-value">{value}</div>;
};
const { rerender } = render(
<OpenFeatureProvider client={OpenFeature.getClient(EVALUATION)}>
<TestComponent flagKey="flag-a" />
</OpenFeatureProvider>
);
await waitFor(() => {
expect(screen.getByTestId('flag-value')).toHaveTextContent('value-a');
});
// Change to flag-b (without any provider events)
rerender(
<OpenFeatureProvider client={OpenFeature.getClient(EVALUATION)}>
<TestComponent flagKey="flag-b" />
</OpenFeatureProvider>
);
await waitFor(() => {
expect(screen.getByTestId('flag-value')).toHaveTextContent('value-b');
});
});
});
});
describe('context, hooks and options', () => {
@ -1105,3 +1294,4 @@ describe('evaluation', () => {
});
});
});

View File

@ -1,4 +1,4 @@
import { isEqual } from '../src/common/is-equal';
import { isEqual } from '../src/internal/is-equal';
describe('isEqual', () => {
it('should return true for equal primitive values', () => {

View File

@ -1,4 +1,4 @@
import { normalizeOptions } from '../src/common/options';
import { normalizeOptions } from '../src/internal/options';
describe('normalizeOptions', () => {
// we spread results from this function, so we never want to return null

View File

@ -288,7 +288,7 @@ describe('OpenFeatureProvider', () => {
{ timeout: DELAY * 4 },
);
expect(screen.getByText('Will says hi')).toBeInTheDocument();
expect(screen.getByText('Will says aloha')).toBeInTheDocument();
});
});
});

View File

@ -1,5 +1,86 @@
# Changelog
## [1.19.0](https://github.com/open-feature/js-sdk/compare/server-sdk-v1.18.0...server-sdk-v1.19.0) (2025-08-14)
### ✨ New Features
* add evaluation-scoped hook data ([#1216](https://github.com/open-feature/js-sdk/issues/1216)) ([07af3a9](https://github.com/open-feature/js-sdk/commit/07af3a9eda895e9edb24c7ee1e3c1c4f16e17431))
### 🐛 Bug Fixes
* update core dep ([#1228](https://github.com/open-feature/js-sdk/issues/1228)) ([845d24c](https://github.com/open-feature/js-sdk/commit/845d24c5fecc80de3080e49fde839f08ecac6b33))
### 🧹 Chore
* update node to v20+ ([#1203](https://github.com/open-feature/js-sdk/issues/1203)) ([1f33453](https://github.com/open-feature/js-sdk/commit/1f33453c23df0763cbf0d0b44db8d91216377009))
### 📚 Documentation
* Clarify the behavior of setProviderAndWait ([#1180](https://github.com/open-feature/js-sdk/issues/1180)) ([4fe8d87](https://github.com/open-feature/js-sdk/commit/4fe8d87a2e5df2cbd4086cc4f4a380e8857ed8ba))
## [1.18.0](https://github.com/open-feature/js-sdk/compare/server-sdk-v1.17.1...server-sdk-v1.18.0) (2025-04-11)
### ✨ New Features
* add a top-level method for accessing providers ([#1152](https://github.com/open-feature/js-sdk/issues/1152)) ([ae8fce8](https://github.com/open-feature/js-sdk/commit/ae8fce87530005ed20f7e68dc696ce67053fca31))
* add support for abort controllers to event handlers ([#1151](https://github.com/open-feature/js-sdk/issues/1151)) ([6a22483](https://github.com/open-feature/js-sdk/commit/6a224830fa4e62fc30a7802536f6f6fc3f772038))
## [1.17.1](https://github.com/open-feature/js-sdk/compare/server-sdk-v1.17.0...server-sdk-v1.17.1) (2025-02-07)
### 🐛 Bug Fixes
* msg missing when providers return err resolutions ([#1134](https://github.com/open-feature/js-sdk/issues/1134)) ([bc9f6e4](https://github.com/open-feature/js-sdk/commit/bc9f6e44da3f1c0a66659aee2d0316629ac34fbf))
### 🧹 Chore
* update core peer ([8bbd43e](https://github.com/open-feature/js-sdk/commit/8bbd43e579a0c2e0c5b7eec00f94bbcffce04773))
### 📚 Documentation
* fix eval context link ([#1132](https://github.com/open-feature/js-sdk/issues/1132)) ([f6bc695](https://github.com/open-feature/js-sdk/commit/f6bc6951a32fbbed9b35c1bdfd023b02874b87a1))
## [1.17.0](https://github.com/open-feature/js-sdk/compare/server-sdk-v1.16.2...server-sdk-v1.17.0) (2024-12-18)
### ⚠ BREAKING CHANGES
The signature of the `finally` hook stage has been changed. The signature now includes the `evaluation details`, as per the [OpenFeature specification](https://openfeature.dev/specification/sections/hooks#requirement-438). Note that since hooks are still `experimental,` this does not constitute a change requiring a new major version. To migrate, update any hook that implements the `finally` stage to accept `evaluation details` as the second argument.
* add evaluation details to finally hook ([#1087](https://github.com/open-feature/js-sdk/issues/1087)) ([2135254](https://github.com/open-feature/js-sdk/commit/2135254c4bee52b4bcadfbf8b99a896cfd930cca))
### ✨ New Features
* add evaluation details to finally hook ([#1087](https://github.com/open-feature/js-sdk/issues/1087)) ([2135254](https://github.com/open-feature/js-sdk/commit/2135254c4bee52b4bcadfbf8b99a896cfd930cca))
### 📚 Documentation
* fix comment in README for Hooks after method ([#1103](https://github.com/open-feature/js-sdk/issues/1103)) ([e335615](https://github.com/open-feature/js-sdk/commit/e3356157d5910d9196e8968c20d4c9a46c4de910))
### 🔄 Refactoring
* improve track interface for providers ([#1100](https://github.com/open-feature/js-sdk/issues/1100)) ([5e5b160](https://github.com/open-feature/js-sdk/commit/5e5b16022122b71760634ac90e3fd962aa831c74))
## [1.16.2](https://github.com/open-feature/js-sdk/compare/server-sdk-v1.16.1...server-sdk-v1.16.2) (2024-11-07)
### 🧹 Chore
* loosen peer dependency requirements, remove some ci automation ([#1080](https://github.com/open-feature/js-sdk/issues/1080)) ([ef3ba21](https://github.com/open-feature/js-sdk/commit/ef3ba2167ac95cd0c6a046d206bd60bbcf84e80c))
### 🚀 Performance
* avoid using exceptions for flow control ([#1074](https://github.com/open-feature/js-sdk/issues/1074)) ([26264d6](https://github.com/open-feature/js-sdk/commit/26264d6d090b2ed31b27d36e71194b9fa911563b))
## [1.16.1](https://github.com/open-feature/js-sdk/compare/server-sdk-v1.16.0...server-sdk-v1.16.1) (2024-10-29)

View File

@ -16,8 +16,8 @@
<img alt="Specification" src="https://img.shields.io/static/v1?label=specification&message=v0.8.0&color=yellow&style=for-the-badge" />
</a>
<!-- x-release-please-start-version -->
<a href="https://github.com/open-feature/js-sdk/releases/tag/server-sdk-v1.16.1">
<img alt="Release" src="https://img.shields.io/static/v1?label=release&message=v1.16.1&color=blue&style=for-the-badge" />
<a href="https://github.com/open-feature/js-sdk/releases/tag/server-sdk-v1.19.0">
<img alt="Release" src="https://img.shields.io/static/v1?label=release&message=v1.19.0&color=blue&style=for-the-badge" />
</a>
<!-- x-release-please-end -->
<br/>
@ -75,7 +75,11 @@ yarn add @openfeature/server-sdk @openfeature/core
import { OpenFeature } from '@openfeature/server-sdk';
// Register your feature flag provider
await OpenFeature.setProviderAndWait(new YourProviderOfChoice());
try {
await OpenFeature.setProviderAndWait(new YourProviderOfChoice());
} catch (error) {
console.error('Failed to initialize provider:', error);
}
// create a new client
const client = OpenFeature.getClient();
@ -97,12 +101,12 @@ See [here](https://open-feature.github.io/js-sdk/modules/_openfeature_server_sdk
| Status | Features | Description |
| ------ | ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| ✅ | [Providers](#providers) | Integrate with a commercial, open source, or in-house feature management tool. |
| ✅ | [Targeting](#targeting) | Contextually-aware flag evaluation using [evaluation context](/docs/reference/concepts/evaluation-context). |
| ✅ | [Targeting](#targeting) | Contextually-aware flag evaluation using [evaluation context](https://openfeature.dev/docs/reference/concepts/evaluation-context). |
| ✅ | [Hooks](#hooks) | Add functionality to various stages of the flag evaluation life-cycle. |
| ✅ | [Logging](#logging) | Integrate with popular logging packages. |
| ✅ | [Domains](#domains) | Logically bind clients with providers. |
| ✅ | [Eventing](#eventing) | React to state changes in the provider or flag management system. |
| ✅ | [Transaction Context Propagation](#transaction-context-propagation) | Set a specific [evaluation context](/docs/reference/concepts/evaluation-context) for a transaction (e.g. an HTTP request or a thread) |
| ✅ | [Transaction Context Propagation](#transaction-context-propagation) | Set a specific [evaluation context](https://openfeature.dev/docs/reference/concepts/evaluation-context) for a transaction (e.g. an HTTP request or a thread) |
| ✅ | [Tracking](#tracking) | Associate user actions with feature flag evaluations, particularly for A/B testing. |
| ✅ | [Shutdown](#shutdown) | Gracefully clean up a provider during application shutdown. |
| ✅ | [Extending](#extending) | Extend OpenFeature with custom providers and hooks. |
@ -383,7 +387,7 @@ import type { Hook, HookContext, EvaluationDetails, FlagValue } from "@openfeatu
export class MyHook implements Hook {
after(hookContext: HookContext, evaluationDetails: EvaluationDetails<FlagValue>) {
// code that runs when there's an error during a flag evaluation
// code that runs after flag values are successfully resolved from the provider
}
}
```

View File

@ -1,6 +1,6 @@
{
"name": "@openfeature/server-sdk",
"version": "1.16.1",
"version": "1.19.0",
"description": "OpenFeature SDK for JavaScript",
"main": "./dist/cjs/index.js",
"files": [
@ -25,8 +25,7 @@
"postbuild": "shx cp ./../../package.esm.json ./dist/esm/package.json",
"current-version": "echo $npm_package_version",
"prepack": "shx cp ./../../LICENSE ./LICENSE",
"publish-if-not-exists": "cp $NPM_CONFIG_USERCONFIG .npmrc && if [ \"$(npm show $npm_package_name@$npm_package_version version)\" = \"$(npm run current-version -s)\" ]; then echo 'already published, skipping'; else npm publish --access public; fi",
"update-core-peer": "npm install --save-peer --save-exact @openfeature/core@$OPENFEATURE_CORE_VERSION"
"publish-if-not-exists": "cp $NPM_CONFIG_USERCONFIG .npmrc && if [ \"$(npm show $npm_package_name@$npm_package_version version)\" = \"$(npm run current-version -s)\" ]; then echo 'already published, skipping'; else npm publish --access public; fi"
},
"repository": {
"type": "git",
@ -46,12 +45,12 @@
},
"homepage": "https://github.com/open-feature/js-sdk#readme",
"engines": {
"node": ">=18"
"node": ">=20"
},
"peerDependencies": {
"@openfeature/core": "1.5.0"
"@openfeature/core": "^1.9.0"
},
"devDependencies": {
"@openfeature/core": "1.5.0"
"@openfeature/core": "^1.9.0"
}
}

View File

@ -10,7 +10,10 @@ import type {
Logger,
TrackingEventDetails,
OpenFeatureError,
ResolutionDetails} from '@openfeature/core';
FlagMetadata,
ResolutionDetails,
EventOptions,
} from '@openfeature/core';
import {
ErrorCode,
ProviderFatalError,
@ -19,12 +22,13 @@ import {
StandardResolutionReasons,
instantiateErrorByErrorCode,
statusMatchesEvent,
MapHookData,
} from '@openfeature/core';
import type { FlagEvaluationOptions } from '../../evaluation';
import type { ProviderEvents } from '../../events';
import type { InternalEventEmitter } from '../../events/internal/internal-event-emitter';
import type { Hook } from '../../hooks';
import type { Provider} from '../../provider';
import type { Provider } from '../../provider';
import { ProviderStatus } from '../../provider';
import type { Client } from './../client';
@ -77,7 +81,7 @@ export class OpenFeatureClient implements Client {
return this.providerStatusAccessor();
}
addHandler(eventType: ProviderEvents, handler: EventHandler): void {
addHandler(eventType: ProviderEvents, handler: EventHandler, options?: EventOptions): void {
this.emitterAccessor().addHandler(eventType, handler);
const shouldRunNow = statusMatchesEvent(eventType, this._providerStatus);
@ -93,6 +97,12 @@ export class OpenFeatureClient implements Client {
this._logger?.error('Error running event handler:', err);
}
}
if (options?.signal && typeof options.signal.addEventListener === 'function') {
options.signal.addEventListener('abort', () => {
this.removeHandler(eventType, handler);
});
}
}
removeHandler(eventType: ProviderEvents, handler: EventHandler) {
@ -226,7 +236,7 @@ export class OpenFeatureClient implements Client {
return this.evaluate<T>(flagKey, this._provider.resolveObjectEvaluation, defaultValue, 'object', context, options);
}
track(occurrenceKey: string, context: EvaluationContext, occurrenceDetails: TrackingEventDetails): void {
track(occurrenceKey: string, context: EvaluationContext = {}, occurrenceDetails: TrackingEventDetails = {}): void {
try {
this.shortCircuitIfNotReady();
@ -267,90 +277,105 @@ export class OpenFeatureClient implements Client {
const mergedContext = this.mergeContexts(invocationContext);
// this reference cannot change during the course of evaluation
// it may be used as a key in WeakMaps
const hookContext: Readonly<HookContext> = {
flagKey,
defaultValue,
flagValueType: flagType,
clientMetadata: this.metadata,
providerMetadata: this._provider.metadata,
context: mergedContext,
logger: this._logger,
};
// Create hook context instances for each hook (stable object references for the entire evaluation)
// This ensures hooks can use WeakMaps with hookContext as keys across lifecycle methods
// NOTE: Uses the reversed order to reduce the number of times we have to calculate the index.
const hookContexts = allHooksReversed.map<HookContext>(() =>
Object.freeze({
flagKey,
defaultValue,
flagValueType: flagType,
clientMetadata: this.metadata,
providerMetadata: this._provider.metadata,
context: mergedContext,
logger: this._logger,
hookData: new MapHookData(),
}),
);
let evaluationDetails: EvaluationDetails<T>;
try {
const frozenContext = await this.beforeHooks(allHooks, hookContext, options);
const frozenContext = await this.beforeHooks(allHooks, hookContexts, mergedContext, options);
this.shortCircuitIfNotReady();
// run the referenced resolver, binding the provider.
const resolution = await resolver.call(this._provider, flagKey, defaultValue, frozenContext, this._logger);
const evaluationDetails = {
const resolutionDetails = {
...resolution,
flagMetadata: Object.freeze(resolution.flagMetadata ?? {}),
flagKey,
};
if (evaluationDetails.errorCode) {
throw instantiateErrorByErrorCode(evaluationDetails.errorCode);
if (resolutionDetails.errorCode) {
const err = instantiateErrorByErrorCode(resolutionDetails.errorCode, resolutionDetails.errorMessage);
await this.errorHooks(allHooksReversed, hookContexts, err, options);
evaluationDetails = this.getErrorEvaluationDetails(flagKey, defaultValue, err, resolutionDetails.flagMetadata);
} else {
await this.afterHooks(allHooksReversed, hookContexts, resolutionDetails, options);
evaluationDetails = resolutionDetails;
}
await this.afterHooks(allHooksReversed, hookContext, evaluationDetails, options);
return evaluationDetails;
} catch (err: unknown) {
const errorMessage: string = (err as Error)?.message;
const errorCode: ErrorCode = (err as OpenFeatureError)?.code || ErrorCode.GENERAL;
await this.errorHooks(allHooksReversed, hookContext, err, options);
return {
errorCode,
errorMessage,
value: defaultValue,
reason: StandardResolutionReasons.ERROR,
flagMetadata: Object.freeze({}),
flagKey,
};
} finally {
await this.finallyHooks(allHooksReversed, hookContext, options);
await this.errorHooks(allHooksReversed, hookContexts, err, options);
evaluationDetails = this.getErrorEvaluationDetails(flagKey, defaultValue, err);
}
await this.finallyHooks(allHooksReversed, hookContexts, evaluationDetails, options);
return evaluationDetails;
}
private async beforeHooks(hooks: Hook[], hookContext: HookContext, options: FlagEvaluationOptions) {
for (const hook of hooks) {
// freeze the hookContext
Object.freeze(hookContext);
private async beforeHooks(
hooks: Hook[],
hookContexts: HookContext[],
mergedContext: EvaluationContext,
options: FlagEvaluationOptions,
) {
let accumulatedContext = mergedContext;
// use Object.assign to avoid modification of frozen hookContext
Object.assign(hookContext.context, {
...hookContext.context,
...(await hook?.before?.(hookContext, Object.freeze(options.hookHints))),
});
for (const [index, hook] of hooks.entries()) {
const hookContextIndex = hooks.length - 1 - index; // reverse index for before hooks
const hookContext = hookContexts[hookContextIndex];
// Update the context on the stable hook context object
Object.assign(hookContext.context, accumulatedContext);
const hookResult = await hook?.before?.(hookContext, Object.freeze(options.hookHints));
if (hookResult) {
accumulatedContext = {
...accumulatedContext,
...hookResult,
};
for (let i = 0; i < hooks.length; i++) {
Object.assign(hookContexts[hookContextIndex].context, accumulatedContext);
}
}
}
// after before hooks, freeze the EvaluationContext.
return Object.freeze(hookContext.context);
return Object.freeze(accumulatedContext);
}
private async afterHooks(
hooks: Hook[],
hookContext: HookContext,
hookContexts: HookContext[],
evaluationDetails: EvaluationDetails<FlagValue>,
options: FlagEvaluationOptions,
) {
// run "after" hooks sequentially
for (const hook of hooks) {
for (const [index, hook] of hooks.entries()) {
const hookContext = hookContexts[index];
await hook?.after?.(hookContext, evaluationDetails, options.hookHints);
}
}
private async errorHooks(hooks: Hook[], hookContext: HookContext, err: unknown, options: FlagEvaluationOptions) {
private async errorHooks(hooks: Hook[], hookContexts: HookContext[], err: unknown, options: FlagEvaluationOptions) {
// run "error" hooks sequentially
for (const hook of hooks) {
for (const [index, hook] of hooks.entries()) {
try {
const hookContext = hookContexts[index];
await hook?.error?.(hookContext, err, options.hookHints);
} catch (err) {
this._logger.error(`Unhandled error during 'error' hook: ${err}`);
@ -362,11 +387,17 @@ export class OpenFeatureClient implements Client {
}
}
private async finallyHooks(hooks: Hook[], hookContext: HookContext, options: FlagEvaluationOptions) {
private async finallyHooks(
hooks: Hook[],
hookContexts: HookContext[],
evaluationDetails: EvaluationDetails<FlagValue>,
options: FlagEvaluationOptions,
) {
// run "finally" hooks sequentially
for (const hook of hooks) {
for (const [index, hook] of hooks.entries()) {
try {
await hook?.finally?.(hookContext, options.hookHints);
const hookContext = hookContexts[index];
await hook?.finally?.(hookContext, evaluationDetails, options.hookHints);
} catch (err) {
this._logger.error(`Unhandled error during 'finally' hook: ${err}`);
if (err instanceof Error) {
@ -407,4 +438,23 @@ export class OpenFeatureClient implements Client {
throw new ProviderFatalError('provider is in an irrecoverable error state');
}
}
private getErrorEvaluationDetails<T extends FlagValue>(
flagKey: string,
defaultValue: T,
err: unknown,
flagMetadata: FlagMetadata = {},
): EvaluationDetails<T> {
const errorMessage: string = (err as Error)?.message;
const errorCode: ErrorCode = (err as OpenFeatureError)?.code || ErrorCode.GENERAL;
return {
errorCode,
errorMessage,
value: defaultValue,
reason: StandardResolutionReasons.ERROR,
flagMetadata: Object.freeze(flagMetadata),
flagKey,
};
}
}

View File

@ -1,7 +1,8 @@
import type { BaseHook, EvaluationContext, FlagValue } from '@openfeature/core';
export type Hook = BaseHook<
export type Hook<TData = Record<string, unknown>> = BaseHook<
FlagValue,
TData,
Promise<EvaluationContext | void> | EvaluationContext | void,
Promise<void> | void
>;

View File

@ -82,7 +82,7 @@ export class OpenFeatureAPI
* Setting a provider supersedes the current provider used in new and existing unbound clients.
* @param {Provider} provider The provider responsible for flag evaluations.
* @returns {Promise<void>}
* @throws Uncaught exceptions thrown by the provider during initialization.
* @throws {Error} If the provider throws an exception during initialization.
*/
setProviderAndWait(provider: Provider): Promise<void>;
/**
@ -92,7 +92,7 @@ export class OpenFeatureAPI
* @param {string} domain The name to identify the client
* @param {Provider} provider The provider responsible for flag evaluations.
* @returns {Promise<void>}
* @throws Uncaught exceptions thrown by the provider during initialization.
* @throws {Error} If the provider throws an exception during initialization.
*/
setProviderAndWait(domain: string, provider: Provider): Promise<void>;
async setProviderAndWait(domainOrProvider?: string | Provider, providerOrUndefined?: Provider): Promise<void> {
@ -138,6 +138,27 @@ export class OpenFeatureAPI
return this;
}
/**
* Get the default provider.
*
* Note that it isn't recommended to interact with the provider directly, but rather through
* an OpenFeature client.
* @returns {Provider} Default Provider
*/
getProvider(): Provider;
/**
* Get the provider bound to the specified domain.
*
* Note that it isn't recommended to interact with the provider directly, but rather through
* an OpenFeature client.
* @param {string} domain An identifier which logically binds clients with providers
* @returns {Provider} Domain-scoped provider
*/
getProvider(domain?: string): Provider;
getProvider(domain?: string): Provider {
return this.getProviderForClient(domain);
}
setContext(context: EvaluationContext): this {
this._context = context;
return this;

View File

@ -859,6 +859,18 @@ describe('OpenFeatureClient', () => {
}).not.toThrow();
});
it('provide empty tracking details to provider if not supplied in call', async () => {
await OpenFeature.setProviderAndWait({ ...MOCK_PROVIDER });
const client = OpenFeature.getClient();
client.track(eventName);
expect(MOCK_PROVIDER.track).toHaveBeenCalledWith(
eventName,
expect.any(Object),
expect.any(Object),
);
});
it('should call provider with correct context', async () => {
await OpenFeature.setProviderAndWait({ ...MOCK_PROVIDER });
OpenFeature.setContext({ [globalContextKey]: globalContextValue });

View File

@ -449,7 +449,21 @@ describe('Events', () => {
expect(OpenFeature.getHandlers(eventType)).toHaveLength(0);
});
it('The API provides a function allowing the removal of event handlers', () => {
it('The event handler can be removed using an abort signal', () => {
const abortController = new AbortController();
const handler1 = jest.fn();
const handler2 = jest.fn();
const eventType = ProviderEvents.Stale;
OpenFeature.addHandler(eventType, handler1, { signal: abortController.signal });
OpenFeature.addHandler(eventType, handler2);
expect(OpenFeature.getHandlers(eventType)).toHaveLength(2);
abortController.abort();
expect(OpenFeature.getHandlers(eventType)).toHaveLength(1);
});
it('The API provides a function allowing the removal of event handlers from client', () => {
const client = OpenFeature.getClient(domain);
const handler = jest.fn();
const eventType = ProviderEvents.Stale;
@ -459,6 +473,21 @@ describe('Events', () => {
client.removeHandler(eventType, handler);
expect(client.getHandlers(eventType)).toHaveLength(0);
});
it('The event handler on the client can be removed using an abort signal', () => {
const abortController = new AbortController();
const client = OpenFeature.getClient(domain);
const handler1 = jest.fn();
const handler2 = jest.fn();
const eventType = ProviderEvents.Stale;
client.addHandler(eventType, handler1, { signal: abortController.signal });
client.addHandler(eventType, handler2);
expect(client.getHandlers(eventType)).toHaveLength(2);
abortController.abort();
expect(client.getHandlers(eventType)).toHaveLength(1);
});
});
describe('Requirement 5.3.1', () => {

View File

@ -0,0 +1,508 @@
import { OpenFeature } from '../src';
import type { Client } from '../src/client';
import type {
JsonValue,
ResolutionDetails,
HookContext,
BeforeHookContext,
HookData} from '@openfeature/core';
import {
StandardResolutionReasons
} from '@openfeature/core';
import type { Provider } from '../src/provider';
import type { Hook } from '../src/hooks';
const BOOLEAN_VALUE = true;
const STRING_VALUE = 'val';
const NUMBER_VALUE = 1;
const OBJECT_VALUE = { key: 'value' };
// A test hook that stores data in the before stage and retrieves it in after/error/finally
class TestHookWithData implements Hook {
beforeData: unknown;
afterData: unknown;
errorData: unknown;
finallyData: unknown;
async before(hookContext: BeforeHookContext) {
// Store some data
hookContext.hookData.set('testKey', 'testValue');
hookContext.hookData.set('timestamp', Date.now());
hookContext.hookData.set('object', { nested: 'value' });
this.beforeData = hookContext.hookData.get('testKey');
}
async after(hookContext: HookContext) {
// Retrieve data stored in before
this.afterData = hookContext.hookData.get('testKey');
}
async error(hookContext: HookContext) {
// Retrieve data stored in before
this.errorData = hookContext.hookData.get('testKey');
}
async finally(hookContext: HookContext) {
// Retrieve data stored in before
this.finallyData = hookContext.hookData.get('testKey');
}
}
// Typed hook example demonstrating improved type safety
interface OpenTelemetryData {
spanId: string;
traceId: string;
startTime: number;
attributes: Record<string, string | number | boolean>;
}
class TypedOpenTelemetryHook implements Hook {
spanId?: string;
duration?: number;
async before(hookContext: BeforeHookContext) {
const spanId = `span-${Math.random().toString(36).substring(2, 11)}`;
const traceId = `trace-${Math.random().toString(36).substring(2, 11)}`;
// Demonstrate that we can cast for type safety while maintaining compatibility
const typedHookData = hookContext.hookData as unknown as HookData<OpenTelemetryData>;
// Type-safe setting with proper intellisense
typedHookData.set('spanId', spanId);
typedHookData.set('traceId', traceId);
typedHookData.set('startTime', Date.now());
typedHookData.set('attributes', {
flagKey: hookContext.flagKey,
clientName: hookContext.clientMetadata.name || 'unknown',
providerName: hookContext.providerMetadata.name,
});
this.spanId = spanId;
}
async after(hookContext: HookContext) {
// Type-safe getting with proper return types
const typedHookData = hookContext.hookData as unknown as HookData<OpenTelemetryData>;
const startTime: number | undefined = typedHookData.get('startTime');
const spanId: string | undefined = typedHookData.get('spanId');
if (startTime && spanId) {
this.duration = Date.now() - startTime;
// Simulate span completion
}
}
async error(hookContext: HookContext) {
const typedHookData = hookContext.hookData as unknown as HookData<OpenTelemetryData>;
const spanId: string | undefined = typedHookData.get('spanId');
if (spanId) {
// Mark span as error
}
}
}
// A timing hook that measures evaluation duration
class TimingHook implements Hook {
duration?: number;
async before(hookContext: BeforeHookContext) {
hookContext.hookData.set('startTime', Date.now());
}
async after(hookContext: HookContext) {
const startTime = hookContext.hookData.get('startTime') as number;
if (startTime) {
this.duration = Date.now() - startTime;
}
}
async error(hookContext: HookContext) {
const startTime = hookContext.hookData.get('startTime') as number;
if (startTime) {
this.duration = Date.now() - startTime;
}
}
}
// Hook that tests hook data isolation
class IsolationTestHook implements Hook {
hookId: string;
constructor(id: string) {
this.hookId = id;
}
before(hookContext: BeforeHookContext) {
const storedId = hookContext.hookData.get('hookId');
if (storedId) {
throw new Error('Hook data isolation violated! Data is set in before hook.');
}
// Each hook instance should have its own data
hookContext.hookData.set('hookId', this.hookId);
hookContext.hookData.set(`data_${this.hookId}`, `value_${this.hookId}`);
}
after(hookContext: HookContext) {
// Verify we can only see our own data
const storedId = hookContext.hookData.get('hookId');
if (storedId !== this.hookId) {
throw new Error(`Hook data isolation violated! Expected ${this.hookId}, got ${storedId}`);
}
}
}
// Mock provider for testing
const MOCK_PROVIDER: Provider = {
metadata: { name: 'mock-provider' },
async resolveBooleanEvaluation(): Promise<ResolutionDetails<boolean>> {
return {
value: BOOLEAN_VALUE,
variant: 'default',
reason: StandardResolutionReasons.DEFAULT,
};
},
async resolveStringEvaluation(): Promise<ResolutionDetails<string>> {
return {
value: STRING_VALUE,
variant: 'default',
reason: StandardResolutionReasons.DEFAULT,
};
},
async resolveNumberEvaluation(): Promise<ResolutionDetails<number>> {
return {
value: NUMBER_VALUE,
variant: 'default',
reason: StandardResolutionReasons.DEFAULT,
};
},
async resolveObjectEvaluation<T extends JsonValue>(): Promise<ResolutionDetails<T>> {
return {
value: OBJECT_VALUE as unknown as T,
variant: 'default',
reason: StandardResolutionReasons.DEFAULT,
};
},
};
// Mock provider that throws an error
const ERROR_PROVIDER: Provider = {
metadata: { name: 'error-provider' },
async resolveBooleanEvaluation(): Promise<ResolutionDetails<boolean>> {
throw new Error('Provider error');
},
async resolveStringEvaluation(): Promise<ResolutionDetails<string>> {
throw new Error('Provider error');
},
async resolveNumberEvaluation(): Promise<ResolutionDetails<number>> {
throw new Error('Provider error');
},
async resolveObjectEvaluation<T extends JsonValue>(): Promise<ResolutionDetails<T>> {
throw new Error('Provider error');
},
};
describe('Hook Data', () => {
let client: Client;
beforeEach(async () => {
OpenFeature.clearHooks();
await OpenFeature.setProviderAndWait(MOCK_PROVIDER);
client = OpenFeature.getClient();
});
afterEach(async () => {
await OpenFeature.clearProviders();
});
describe('Basic Hook Data Functionality', () => {
it('should allow hooks to store and retrieve data across stages', async () => {
const hook = new TestHookWithData();
client.addHooks(hook);
await client.getBooleanValue('test-flag', false);
// Verify data was stored in before and retrieved in all other stages
expect(hook.beforeData).toBe('testValue');
expect(hook.afterData).toBe('testValue');
expect(hook.finallyData).toBe('testValue');
});
it('should support storing different data types', async () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const storedValues: any = {};
const hook: Hook = {
async before(hookContext: BeforeHookContext) {
// Store various types
hookContext.hookData.set('string', 'test');
hookContext.hookData.set('number', 42);
hookContext.hookData.set('boolean', true);
hookContext.hookData.set('object', { key: 'value' });
hookContext.hookData.set('array', [1, 2, 3]);
hookContext.hookData.set('null', null);
hookContext.hookData.set('undefined', undefined);
},
async after(hookContext: HookContext) {
storedValues.string = hookContext.hookData.get('string');
storedValues.number = hookContext.hookData.get('number');
storedValues.boolean = hookContext.hookData.get('boolean');
storedValues.object = hookContext.hookData.get('object');
storedValues.array = hookContext.hookData.get('array');
storedValues.null = hookContext.hookData.get('null');
storedValues.undefined = hookContext.hookData.get('undefined');
},
};
client.addHooks(hook);
await client.getBooleanValue('test-flag', false);
expect(storedValues.string).toBe('test');
expect(storedValues.number).toBe(42);
expect(storedValues.boolean).toBe(true);
expect(storedValues.object).toEqual({ key: 'value' });
expect(storedValues.array).toEqual([1, 2, 3]);
expect(storedValues.null).toBeNull();
expect(storedValues.undefined).toBeUndefined();
});
it('should handle hook data in error scenarios', async () => {
await OpenFeature.setProviderAndWait(ERROR_PROVIDER);
const hook = new TestHookWithData();
client.addHooks(hook);
await client.getBooleanValue('test-flag', false);
// Verify data was accessible in error and finally stages
expect(hook.beforeData).toBe('testValue');
expect(hook.errorData).toBe('testValue');
expect(hook.finallyData).toBe('testValue');
expect(hook.afterData).toBeUndefined(); // after should not run on error
});
});
describe('Hook Data API', () => {
it('should support has() method', async () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const hasResults: any = {};
const hook: Hook = {
async before(hookContext: BeforeHookContext) {
hookContext.hookData.set('exists', 'value');
hasResults.beforeExists = hookContext.hookData.has('exists');
hasResults.beforeNotExists = hookContext.hookData.has('notExists');
},
async after(hookContext: HookContext) {
hasResults.afterExists = hookContext.hookData.has('exists');
hasResults.afterNotExists = hookContext.hookData.has('notExists');
},
};
client.addHooks(hook);
await client.getBooleanValue('test-flag', false);
expect(hasResults.beforeExists).toBe(true);
expect(hasResults.beforeNotExists).toBe(false);
expect(hasResults.afterExists).toBe(true);
expect(hasResults.afterNotExists).toBe(false);
});
it('should support delete() method', async () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const deleteResults: any = {};
const hook: Hook = {
async before(hookContext: BeforeHookContext) {
hookContext.hookData.set('toDelete', 'value');
deleteResults.hasBeforeDelete = hookContext.hookData.has('toDelete');
deleteResults.deleteResult = hookContext.hookData.delete('toDelete');
deleteResults.hasAfterDelete = hookContext.hookData.has('toDelete');
deleteResults.deleteAgainResult = hookContext.hookData.delete('toDelete');
},
};
client.addHooks(hook);
await client.getBooleanValue('test-flag', false);
expect(deleteResults.hasBeforeDelete).toBe(true);
expect(deleteResults.deleteResult).toBe(true);
expect(deleteResults.hasAfterDelete).toBe(false);
expect(deleteResults.deleteAgainResult).toBe(false);
});
it('should support clear() method', async () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const clearResults: any = {};
const hook: Hook = {
async before(hookContext: BeforeHookContext) {
hookContext.hookData.set('key1', 'value1');
hookContext.hookData.set('key2', 'value2');
hookContext.hookData.set('key3', 'value3');
clearResults.hasBeforeClear = hookContext.hookData.has('key1');
hookContext.hookData.clear();
clearResults.hasAfterClear = hookContext.hookData.has('key1');
},
async after(hookContext: HookContext) {
// Verify all data was cleared
clearResults.afterHasKey1 = hookContext.hookData.has('key1');
clearResults.afterHasKey2 = hookContext.hookData.has('key2');
clearResults.afterHasKey3 = hookContext.hookData.has('key3');
},
};
client.addHooks(hook);
await client.getBooleanValue('test-flag', false);
expect(clearResults.hasBeforeClear).toBe(true);
expect(clearResults.hasAfterClear).toBe(false);
expect(clearResults.afterHasKey1).toBe(false);
expect(clearResults.afterHasKey2).toBe(false);
expect(clearResults.afterHasKey3).toBe(false);
});
});
describe('Hook Data Isolation', () => {
it('should isolate data between different hook instances', async () => {
const hook1 = new IsolationTestHook('hook1');
const hook2 = new IsolationTestHook('hook2');
const hook3 = new IsolationTestHook('hook3');
client.addHooks(hook1, hook2, hook3);
expect(await client.getBooleanValue('test-flag', false)).toBe(true);
});
it('should isolate data between the same hook instance', async () => {
const hook = new IsolationTestHook('hook');
client.addHooks(hook, hook);
expect(await client.getBooleanValue('test-flag', false)).toBe(true);
});
it('should not share data between different evaluations', async () => {
let firstEvalData: unknown;
let secondEvalData: unknown;
const hook: Hook = {
async before(hookContext: BeforeHookContext) {
// Check if data exists from previous evaluation
const existingData = hookContext.hookData.get('evalData');
if (existingData) {
throw new Error('Hook data leaked between evaluations!');
}
hookContext.hookData.set('evalData', 'evaluation-specific');
},
async after(hookContext: HookContext) {
if (!firstEvalData) {
firstEvalData = hookContext.hookData.get('evalData');
} else {
secondEvalData = hookContext.hookData.get('evalData');
}
},
};
client.addHooks(hook);
// First evaluation
await client.getBooleanValue('test-flag', false);
// Second evaluation
await client.getBooleanValue('test-flag', false);
expect(firstEvalData).toBe('evaluation-specific');
expect(secondEvalData).toBe('evaluation-specific');
});
it('should isolate data between global, client, and invocation hooks', async () => {
const globalHook = new IsolationTestHook('global');
const clientHook = new IsolationTestHook('client');
const invocationHook = new IsolationTestHook('invocation');
OpenFeature.addHooks(globalHook);
client.addHooks(clientHook);
expect(await client.getBooleanValue('test-flag', false, {}, { hooks: [invocationHook] })).toBe(true);
});
});
describe('Use Cases', () => {
it('should support timing measurements', async () => {
const timingHook = new TimingHook();
client.addHooks(timingHook);
await client.getBooleanValue('test-flag', false);
expect(timingHook.duration).toBeDefined();
expect(timingHook.duration).toBeGreaterThanOrEqual(0);
});
it('should support multi-stage validation accumulation', async () => {
let finalErrors: string[] = [];
const validationHook: Hook = {
async before(hookContext: BeforeHookContext) {
hookContext.hookData.set('errors', []);
// Simulate validation
const errors = hookContext.hookData.get('errors') as string[];
if (!hookContext.context.userId) {
errors.push('Missing userId');
}
if (!hookContext.context.region) {
errors.push('Missing region');
}
},
async finally(hookContext: HookContext) {
finalErrors = (hookContext.hookData.get('errors') as string[]) || [];
},
};
client.addHooks(validationHook);
await client.getBooleanValue('test-flag', false, {});
expect(finalErrors).toContain('Missing userId');
expect(finalErrors).toContain('Missing region');
});
it('should support request correlation', async () => {
let correlationId: string | undefined;
const correlationHook: Hook = {
async before(hookContext: BeforeHookContext) {
const id = `req-${Date.now()}-${Math.random()}`;
hookContext.hookData.set('correlationId', id);
},
async after(hookContext: HookContext) {
correlationId = hookContext.hookData.get('correlationId') as string;
},
};
client.addHooks(correlationHook);
await client.getBooleanValue('test-flag', false);
expect(correlationId).toBeDefined();
expect(correlationId).toMatch(/^req-\d+-[\d.]+$/);
});
it('should support typed hook data for better type safety', async () => {
const typedHook = new TypedOpenTelemetryHook();
client.addHooks(typedHook);
await client.getBooleanValue('test-flag', false);
// Verify the typed hook worked correctly
expect(typedHook.spanId).toBeDefined();
expect(typedHook.spanId).toMatch(/^span-[a-z0-9]+$/);
expect(typedHook.duration).toBeDefined();
expect(typeof typedHook.duration).toBe('number');
expect(typedHook.duration).toBeGreaterThanOrEqual(0);
});
});
});

View File

@ -439,6 +439,30 @@ describe('Hooks', () => {
});
});
});
describe('Requirement 4.3.8', () => {
it('"evaluation details" passed to the "finally" stage matches the evaluation details returned to the application author', async () => {
OpenFeature.setProvider(MOCK_PROVIDER);
let evaluationDetailsHooks;
const evaluationDetails = await client.getBooleanDetails(
FLAG_KEY,
false,
{},
{
hooks: [
{
finally: (_, details) => {
evaluationDetailsHooks = details;
},
},
],
},
);
expect(evaluationDetailsHooks).toEqual(evaluationDetails);
});
});
});
describe('Requirement 4.4.2', () => {
@ -922,14 +946,14 @@ describe('Hooks', () => {
done(err);
}
},
after: (_hookContext, _evaluationDetils, hookHints) => {
after: (_hookContext, _evaluationDetails, hookHints) => {
try {
expect(hookHints?.hint).toBeTruthy();
} catch (err) {
done(err);
}
},
finally: (_, hookHints) => {
finally: (_, _evaluationDetails, hookHints) => {
try {
expect(hookHints?.hint).toBeTruthy();
done();

View File

@ -74,8 +74,8 @@ describe('OpenFeature', () => {
it('should set the default provider if no domain is provided', () => {
const provider = mockProvider();
OpenFeature.setProvider(provider);
const client = OpenFeature.getClient();
expect(client.metadata.providerMetadata.name).toEqual(provider.metadata.name);
const registeredProvider = OpenFeature.getProvider();
expect(registeredProvider).toEqual(provider);
});
it('should not change providers associated with a domain when setting a new default provider', () => {
@ -85,11 +85,11 @@ describe('OpenFeature', () => {
OpenFeature.setProvider(provider);
OpenFeature.setProvider(domain, fakeProvider);
const defaultClient = OpenFeature.getClient();
const domainSpecificClient = OpenFeature.getClient(domain);
const defaultProvider = OpenFeature.getProvider();
const domainSpecificProvider = OpenFeature.getProvider(domain);
expect(defaultClient.metadata.providerMetadata.name).toEqual(provider.metadata.name);
expect(domainSpecificClient.metadata.providerMetadata.name).toEqual(fakeProvider.metadata.name);
expect(defaultProvider).toEqual(provider);
expect(domainSpecificProvider).toEqual(fakeProvider);
});
it('should bind a new provider to existing clients in a matching domain', () => {

View File

@ -1,5 +1,67 @@
# Changelog
## [1.9.0](https://github.com/open-feature/js-sdk/compare/core-v1.8.1...core-v1.9.0) (2025-08-10)
### ✨ New Features
* add evaluation-scoped hook data ([#1216](https://github.com/open-feature/js-sdk/issues/1216)) ([07af3a9](https://github.com/open-feature/js-sdk/commit/07af3a9eda895e9edb24c7ee1e3c1c4f16e17431))
* support Angular 20 ([#1220](https://github.com/open-feature/js-sdk/issues/1220)) ([aa232a9](https://github.com/open-feature/js-sdk/commit/aa232a9d6a8dfa416380ccdecd71843d3e361048))
## [1.8.1](https://github.com/open-feature/js-sdk/compare/core-v1.8.0...core-v1.8.1) (2025-06-04)
### 🔄 Refactoring
* **telemetry:** update telemetry attributes and remove unused evaluation data ([#1189](https://github.com/open-feature/js-sdk/issues/1189)) ([3e6bcae](https://github.com/open-feature/js-sdk/commit/3e6bcaef0bb5c05e914a0078f0cb884b7f74f068))
## [1.8.0](https://github.com/open-feature/js-sdk/compare/core-v1.7.2...core-v1.8.0) (2025-04-10)
### ✨ New Features
* add support for abort controllers to event handlers ([#1151](https://github.com/open-feature/js-sdk/issues/1151)) ([6a22483](https://github.com/open-feature/js-sdk/commit/6a224830fa4e62fc30a7802536f6f6fc3f772038))
## [1.7.2](https://github.com/open-feature/js-sdk/compare/core-v1.7.1...core-v1.7.2) (2025-02-18)
### 🐛 Bug Fixes
* rename evaluation event property from data to body ([4c2b01e](https://github.com/open-feature/js-sdk/commit/4c2b01e36773091038d758ac10bba06056ff4c45))
## [1.7.1](https://github.com/open-feature/js-sdk/compare/core-v1.7.0...core-v1.7.1) (2025-02-13)
### 🐛 Bug Fixes
* export missing telemetry functionality ([#1148](https://github.com/open-feature/js-sdk/issues/1148)) ([dcbc300](https://github.com/open-feature/js-sdk/commit/dcbc30090e7611c60e06d05826f6471f0c8c4009))
## [1.7.0](https://github.com/open-feature/js-sdk/compare/core-v1.6.0...core-v1.7.0) (2025-02-07)
### ✨ New Features
* add telemetry helper utils ([#1120](https://github.com/open-feature/js-sdk/issues/1120)) ([1e93b3c](https://github.com/open-feature/js-sdk/commit/1e93b3c6fa4494dfb41389043921751e00acafd2))
## [1.6.0](https://github.com/open-feature/js-sdk/compare/core-v1.5.0...core-v1.6.0) (2024-12-12)
### ⚠ BREAKING CHANGES
The signature of the `finally` hook stage has been changed. The signature now includes the `evaluation details`, as per the [OpenFeature specification](https://openfeature.dev/specification/sections/hooks#requirement-438).
Note that since hooks are still `experimental,` this does not constitute a change requiring a new major version.
To migrate, update any hook that implements the `finally` stage to accept `evaluation details` as the second argument.
* add evaluation details to finally hook ([#1087](https://github.com/open-feature/js-sdk/issues/1087)) ([2135254](https://github.com/open-feature/js-sdk/commit/2135254c4bee52b4bcadfbf8b99a896cfd930cca))
### ✨ New Features
* add evaluation details to finally hook ([#1087](https://github.com/open-feature/js-sdk/issues/1087)) ([2135254](https://github.com/open-feature/js-sdk/commit/2135254c4bee52b4bcadfbf8b99a896cfd930cca))
### 🔄 Refactoring
* improve track interface for providers ([#1100](https://github.com/open-feature/js-sdk/issues/1100)) ([5e5b160](https://github.com/open-feature/js-sdk/commit/5e5b16022122b71760634ac90e3fd962aa831c74))
## [1.5.0](https://github.com/open-feature/js-sdk/compare/core-v1.4.0...core-v1.5.0) (2024-10-29)

View File

@ -1,6 +1,6 @@
{
"name": "@openfeature/core",
"version": "1.5.0",
"version": "1.9.0",
"description": "Shared OpenFeature JS components (server and web)",
"main": "./dist/cjs/index.js",
"files": [

View File

@ -18,3 +18,4 @@ export abstract class OpenFeatureError extends Error {
this.cause = options?.cause;
}
}

View File

@ -3,7 +3,7 @@ import type { JsonValue } from '../types/structure';
export type FlagValueType = 'boolean' | 'string' | 'number' | 'object';
/**
* Represents a JSON node value, or Date.
* Represents a JSON node value.
*/
export type FlagValue = boolean | string | number | JsonValue;

View File

@ -66,6 +66,9 @@ export type EventDetails<
export type EventHandler<
T extends ServerProviderEvents | ClientProviderEvents = ServerProviderEvents | ClientProviderEvents,
> = (eventDetails?: EventDetails<T>) => Promise<unknown> | unknown;
export type EventOptions = {
signal?: AbortSignal;
};
export interface Eventing<T extends ServerProviderEvents | ClientProviderEvents> {
/**
@ -73,6 +76,7 @@ export interface Eventing<T extends ServerProviderEvents | ClientProviderEvents>
* The handlers are called in the order they have been added.
* @param eventType The provider event type to listen to
* @param {EventHandler} handler The handler to run on occurrence of the event type
* @param {EventOptions} options Optional options such as signal for aborting
*/
addHandler(
eventType: T extends ClientProviderEvents
@ -83,14 +87,17 @@ export interface Eventing<T extends ServerProviderEvents | ClientProviderEvents>
? ClientProviderEvents.ConfigurationChanged
: ServerProviderEvents.ConfigurationChanged
>,
options?: EventOptions,
): void;
addHandler(
eventType: T extends ClientProviderEvents ? ClientNotChangeEvents : ServerNotChangeEvents,
handler: EventHandler<T extends ClientProviderEvents ? ClientNotChangeEvents : ServerNotChangeEvents>,
options?: EventOptions,
): void;
addHandler(
eventType: T extends ClientProviderEvents ? ClientProviderEvents : ServerProviderEvents,
handler: EventHandler<T extends ClientProviderEvents ? ClientProviderEvents : ServerProviderEvents>,
options?: EventOptions,
): void;
/**

View File

@ -0,0 +1,72 @@
/**
* A mutable data structure for hooks to maintain state across their lifecycle.
* Each hook instance gets its own isolated data store that persists for the
* duration of a single flag evaluation.
* @template TData - A record type that defines the shape of the stored data
*/
export interface HookData<TData = Record<string, unknown>> {
/**
* Sets a value in the hook data store.
* @param key The key to store the value under
* @param value The value to store
*/
set<K extends keyof TData>(key: K, value: TData[K]): void;
set(key: string, value: unknown): void;
/**
* Gets a value from the hook data store.
* @param key The key to retrieve the value for
* @returns The stored value, or undefined if not found
*/
get<K extends keyof TData>(key: K): TData[K] | undefined;
get(key: string): unknown;
/**
* Checks if a key exists in the hook data store.
* @param key The key to check
* @returns True if the key exists, false otherwise
*/
has<K extends keyof TData>(key: K): boolean;
has(key: string): boolean;
/**
* Deletes a value from the hook data store.
* @param key The key to delete
* @returns True if the key was deleted, false if it didn't exist
*/
delete<K extends keyof TData>(key: K): boolean;
delete(key: string): boolean;
/**
* Clears all values from the hook data store.
*/
clear(): void;
}
/**
* Default implementation of HookData using a Map.
* @template TData - A record type that defines the shape of the stored data
*/
export class MapHookData<TData = Record<string, unknown>> implements HookData<TData> {
private readonly data = new Map<keyof TData, TData[keyof TData]>();
set<K extends keyof TData>(key: K, value: TData[K]): void {
this.data.set(key, value);
}
get<K extends keyof TData>(key: K): TData[K] | undefined {
return this.data.get(key) as TData[K] | undefined;
}
has<K extends keyof TData>(key: K): boolean {
return this.data.has(key);
}
delete<K extends keyof TData>(key: K): boolean {
return this.data.delete(key);
}
clear(): void {
this.data.clear();
}
}

View File

@ -1,14 +1,19 @@
import type { BeforeHookContext, HookContext, HookHints } from './hooks';
import type { EvaluationDetails, FlagValue } from '../evaluation';
export interface BaseHook<T extends FlagValue = FlagValue, BeforeHookReturn = unknown, HooksReturn = unknown> {
export interface BaseHook<
T extends FlagValue = FlagValue,
TData = Record<string, unknown>,
BeforeHookReturn = unknown,
HooksReturn = unknown
> {
/**
* Runs before flag values are resolved from the provider.
* If an EvaluationContext is returned, it will be merged with the pre-existing EvaluationContext.
* @param hookContext
* @param hookHints
*/
before?(hookContext: BeforeHookContext, hookHints?: HookHints): BeforeHookReturn;
before?(hookContext: BeforeHookContext<T, TData>, hookHints?: HookHints): BeforeHookReturn;
/**
* Runs after flag values are successfully resolved from the provider.
@ -17,7 +22,7 @@ export interface BaseHook<T extends FlagValue = FlagValue, BeforeHookReturn = un
* @param hookHints
*/
after?(
hookContext: Readonly<HookContext<T>>,
hookContext: Readonly<HookContext<T, TData>>,
evaluationDetails: EvaluationDetails<T>,
hookHints?: HookHints,
): HooksReturn;
@ -28,13 +33,18 @@ export interface BaseHook<T extends FlagValue = FlagValue, BeforeHookReturn = un
* @param error
* @param hookHints
*/
error?(hookContext: Readonly<HookContext<T>>, error: unknown, hookHints?: HookHints): HooksReturn;
error?(hookContext: Readonly<HookContext<T, TData>>, error: unknown, hookHints?: HookHints): HooksReturn;
/**
* Runs after all other hook stages, regardless of success or error.
* Errors thrown here are unhandled by the client and will surface in application code.
* @param hookContext
* @param evaluationDetails
* @param hookHints
*/
finally?(hookContext: Readonly<HookContext<T>>, hookHints?: HookHints): HooksReturn;
finally?(
hookContext: Readonly<HookContext<T, TData>>,
evaluationDetails: EvaluationDetails<T>,
hookHints?: HookHints,
): HooksReturn;
}

View File

@ -2,10 +2,11 @@ import type { ProviderMetadata } from '../provider';
import type { ClientMetadata } from '../client';
import type { EvaluationContext, FlagValue, FlagValueType } from '../evaluation';
import type { Logger } from '../logger';
import type { HookData } from './hook-data';
export type HookHints = Readonly<Record<string, unknown>>;
export interface HookContext<T extends FlagValue = FlagValue> {
export interface HookContext<T extends FlagValue = FlagValue, TData = Record<string, unknown>> {
readonly flagKey: string;
readonly defaultValue: T;
readonly flagValueType: FlagValueType;
@ -13,8 +14,9 @@ export interface HookContext<T extends FlagValue = FlagValue> {
readonly clientMetadata: ClientMetadata;
readonly providerMetadata: ProviderMetadata;
readonly logger: Logger;
readonly hookData: HookData<TData>;
}
export interface BeforeHookContext extends HookContext {
export interface BeforeHookContext<T extends FlagValue = FlagValue, TData = Record<string, unknown>> extends HookContext<T, TData> {
context: EvaluationContext;
}

View File

@ -1,3 +1,4 @@
export * from './hook';
export * from './hooks';
export * from './evaluation-lifecycle';
export * from './hook-data';

View File

@ -4,6 +4,7 @@ export * from './client';
export * from './errors';
export * from './events';
export * from './logger';
export * from './telemetry';
export * from './provider';
export * from './evaluation';
export * from './type-guards';

View File

@ -7,14 +7,13 @@ import type {
EventDetails,
EventHandler,
Eventing,
GenericEventEmitter} from './events';
import {
AllProviderEvents,
statusMatchesEvent,
EventOptions,
GenericEventEmitter,
} from './events';
import { AllProviderEvents, statusMatchesEvent } from './events';
import { isDefined } from './filter';
import type { BaseHook, EvaluationLifeCycle } from './hooks';
import type { Logger, ManageLogger} from './logger';
import type { Logger, ManageLogger } from './logger';
import { DefaultLogger, SafeLogger } from './logger';
import type { ClientProviderStatus, CommonProvider, ProviderMetadata, ServerProviderStatus } from './provider';
import { objectOrUndefined, stringOrUndefined } from './type-guards';
@ -154,8 +153,9 @@ export abstract class OpenFeatureCommonAPI<
* API (global) events run for all providers.
* @param {AnyProviderEvent} eventType The provider event type to listen to
* @param {EventHandler} handler The handler to run on occurrence of the event type
* @param {EventOptions} options Optional options such as signal for aborting
*/
addHandler<T extends AnyProviderEvent>(eventType: T, handler: EventHandler): void {
addHandler<T extends AnyProviderEvent>(eventType: T, handler: EventHandler, options?: EventOptions): void {
[...new Map([[undefined, this._defaultProvider]]), ...this._domainScopedProviders].forEach((keyProviderTuple) => {
const domain = keyProviderTuple[0];
const provider = keyProviderTuple[1].provider;
@ -173,6 +173,11 @@ export abstract class OpenFeatureCommonAPI<
});
this._apiEmitter.addHandler(eventType, handler);
if (options?.signal && typeof options.signal.addEventListener === 'function') {
options.signal.addEventListener('abort', () => {
this.removeHandler(eventType, handler);
});
}
}
/**
@ -248,7 +253,7 @@ export abstract class OpenFeatureCommonAPI<
// initialize the provider if it implements "initialize" and it's not already registered
if (typeof provider.initialize === 'function' && !this.allProviders.includes(provider)) {
initializationPromise = provider
.initialize?.(domain ? this._domainScopedContext.get(domain) ?? this._context : this._context)
.initialize?.(domain ? (this._domainScopedContext.get(domain) ?? this._context) : this._context)
?.then(() => {
wrappedProvider.status = this._statusEnumType.READY;
// fetch the most recent event emitters, some may have been added during init

View File

@ -133,5 +133,5 @@ export interface CommonProvider<S extends ClientProviderStatus | ServerProviderS
* @param context
* @param trackingEventDetails
*/
track?(trackingEventName: string, context?: EvaluationContext, trackingEventDetails?: TrackingEventDetails): void;
track?(trackingEventName: string, context: EvaluationContext, trackingEventDetails: TrackingEventDetails): void;
}

View File

@ -0,0 +1,89 @@
/**
* The attributes of an OpenTelemetry compliant event for flag evaluation.
* @see https://opentelemetry.io/docs/specs/semconv/feature-flags/feature-flags-logs/
*/
export const TelemetryAttribute = {
/**
* The lookup key of the feature flag.
*
* - type: `string`
* - requirement level: `required`
* - example: `logo-color`
*/
KEY: 'feature_flag.key',
/**
* Describes a class of error the operation ended with.
*
* - type: `string`
* - requirement level: `conditionally required`
* - condition: `reason` is `error`
* - example: `flag_not_found`
*/
ERROR_CODE: 'error.type',
/**
* A message explaining the nature of an error occurring during flag evaluation.
*
* - type: `string`
* - requirement level: `recommended`
* - example: `Flag not found`
*/
ERROR_MESSAGE: 'error.message',
/**
* A semantic identifier for an evaluated flag value.
*
* - type: `string`
* - requirement level: `conditionally required`
* - condition: variant is defined on the evaluation details
* - example: `blue`; `on`; `true`
*/
VARIANT: 'feature_flag.result.variant',
/**
* The evaluated value of the feature flag.
*
* - type: `undefined`
* - requirement level: `conditionally required`
* - condition: variant is not defined on the evaluation details
* - example: `#ff0000`; `1`; `true`
*/
VALUE: 'feature_flag.result.value',
/**
* The unique identifier for the flag evaluation context. For example, the targeting key.
*
* - type: `string`
* - requirement level: `recommended`
* - example: `5157782b-2203-4c80-a857-dbbd5e7761db`
*/
CONTEXT_ID: 'feature_flag.context.id',
/**
* The reason code which shows how a feature flag value was determined.
*
* - type: `string`
* - requirement level: `recommended`
* - example: `targeting_match`
*/
REASON: 'feature_flag.result.reason',
/**
* Describes a class of error the operation ended with.
*
* - type: `string`
* - requirement level: `recommended`
* - example: `flag_not_found`
*/
PROVIDER: 'feature_flag.provider.name',
/**
* The identifier of the flag set to which the feature flag belongs.
*
* - type: `string`
* - requirement level: `recommended`
* - example: `proj-1`; `ab98sgs`; `service1/dev`
*/
FLAG_SET_ID: 'feature_flag.set.id',
/**
* The version of the ruleset used during the evaluation. This may be any stable value which uniquely identifies the ruleset.
*
* - type: `string`
* - requirement level: `recommended`
* - example: `1.0.0`; `2021-01-01`
*/
VERSION: 'feature_flag.version',
} as const;

View File

@ -0,0 +1,70 @@
import { ErrorCode, StandardResolutionReasons, type EvaluationDetails, type FlagValue } from '../evaluation/evaluation';
import type { HookContext } from '../hooks/hooks';
import { TelemetryAttribute } from './attributes';
import { TelemetryFlagMetadata } from './flag-metadata';
type EvaluationEvent = {
/**
* The name of the feature flag evaluation event.
*/
name: string;
/**
* The attributes of an OpenTelemetry compliant event for flag evaluation.
* @experimental The attributes are subject to change.
* @see https://opentelemetry.io/docs/specs/semconv/feature-flags/feature-flags-logs/
*/
attributes: Record<string, string | number | boolean | FlagValue>;
};
const FLAG_EVALUATION_EVENT_NAME = 'feature_flag.evaluation';
/**
* Returns an OpenTelemetry compliant event for flag evaluation.
* @param {HookContext} hookContext Contextual information about the flag evaluation
* @param {EvaluationDetails} evaluationDetails The details of the flag evaluation
* @returns {EvaluationEvent} An evaluation event object containing the event name and attributes
*/
export function createEvaluationEvent(
hookContext: Readonly<HookContext<FlagValue>>,
evaluationDetails: EvaluationDetails<FlagValue>,
): EvaluationEvent {
const attributes: EvaluationEvent['attributes'] = {
[TelemetryAttribute.KEY]: hookContext.flagKey,
[TelemetryAttribute.PROVIDER]: hookContext.providerMetadata.name,
[TelemetryAttribute.REASON]: (evaluationDetails.reason ?? StandardResolutionReasons.UNKNOWN).toLowerCase(),
};
if (evaluationDetails.variant) {
attributes[TelemetryAttribute.VARIANT] = evaluationDetails.variant;
} else {
attributes[TelemetryAttribute.VALUE] = evaluationDetails.value;
}
const contextId =
evaluationDetails.flagMetadata[TelemetryFlagMetadata.CONTEXT_ID] || hookContext.context.targetingKey;
if (contextId) {
attributes[TelemetryAttribute.CONTEXT_ID] = contextId;
}
const setId = evaluationDetails.flagMetadata[TelemetryFlagMetadata.FLAG_SET_ID];
if (setId) {
attributes[TelemetryAttribute.FLAG_SET_ID] = setId;
}
const version = evaluationDetails.flagMetadata[TelemetryFlagMetadata.VERSION];
if (version) {
attributes[TelemetryAttribute.VERSION] = version;
}
if (evaluationDetails.reason === StandardResolutionReasons.ERROR) {
attributes[TelemetryAttribute.ERROR_CODE] = (evaluationDetails.errorCode ?? ErrorCode.GENERAL).toLowerCase();
if (evaluationDetails.errorMessage) {
attributes[TelemetryAttribute.ERROR_MESSAGE] = evaluationDetails.errorMessage;
}
}
return {
name: FLAG_EVALUATION_EVENT_NAME,
attributes,
};
}

View File

@ -0,0 +1,20 @@
/**
* Well-known flag metadata attributes for telemetry events.
* @see https://openfeature.dev/specification/appendix-d#flag-metadata
*/
export const TelemetryFlagMetadata = {
/**
* The context identifier returned in the flag metadata uniquely identifies
* the subject of the flag evaluation. If not available, the targeting key
* should be used.
*/
CONTEXT_ID: 'contextId',
/**
* A logical identifier for the flag set.
*/
FLAG_SET_ID: 'flagSetId',
/**
* A version string (format unspecified) for the flag or flag set.
*/
VERSION: 'version',
} as const;

View File

@ -0,0 +1,3 @@
export * from './attributes';
export * from './flag-metadata';
export * from './evaluation-event';

View File

@ -14,17 +14,23 @@ class TestEventEmitter extends GenericEventEmitter<AnyProviderEvent> {
}
}
// a little function to make sure we're at least waiting for the event loop
// a little function to make sure we're at least waiting for the event loop
// to clear before we start making assertions
const wait = (millis = 0) => {
return new Promise(resolve => {setTimeout(resolve, millis);});
return new Promise((resolve) => {
setTimeout(resolve, millis);
});
};
describe('GenericEventEmitter', () => {
const emitter = new TestEventEmitter();
afterEach(() => {
emitter.removeAllHandlers();
});
describe('addHandler should', function () {
it('attach handler for event type', async function () {
const emitter = new TestEventEmitter();
const handler1 = jest.fn();
emitter.addHandler(AllProviderEvents.Ready, handler1);
emitter.emit(AllProviderEvents.Ready);
@ -35,8 +41,6 @@ describe('GenericEventEmitter', () => {
});
it('attach several handlers for event type', async function () {
const emitter = new TestEventEmitter();
const handler1 = jest.fn();
const handler2 = jest.fn();
const handler3 = jest.fn();
@ -64,7 +68,6 @@ describe('GenericEventEmitter', () => {
debug: () => done(),
};
const emitter = new TestEventEmitter();
emitter.setLogger(logger);
emitter.addHandler(AllProviderEvents.Ready, async () => {
@ -74,8 +77,6 @@ describe('GenericEventEmitter', () => {
});
it('trigger handler for event type', async function () {
const emitter = new TestEventEmitter();
const handler1 = jest.fn();
emitter.addHandler(AllProviderEvents.Ready, handler1);
emitter.emit(AllProviderEvents.Ready);
@ -87,7 +88,6 @@ describe('GenericEventEmitter', () => {
it('trigger handler for event type with event data', async function () {
const event: ReadyEvent = { message: 'message' };
const emitter = new TestEventEmitter();
const handler1 = jest.fn();
emitter.addHandler(AllProviderEvents.Ready, handler1);
@ -99,8 +99,6 @@ describe('GenericEventEmitter', () => {
});
it('trigger several handlers for event type', async function () {
const emitter = new TestEventEmitter();
const handler1 = jest.fn();
const handler2 = jest.fn();
const handler3 = jest.fn();
@ -121,8 +119,6 @@ describe('GenericEventEmitter', () => {
describe('removeHandler should', () => {
it('remove single handler', async function () {
const emitter = new TestEventEmitter();
const handler1 = jest.fn();
emitter.addHandler(AllProviderEvents.Ready, handler1);
@ -138,8 +134,6 @@ describe('GenericEventEmitter', () => {
describe('removeAllHandlers should', () => {
it('remove all handlers for event type', async function () {
const emitter = new TestEventEmitter();
const handler1 = jest.fn();
const handler2 = jest.fn();
emitter.addHandler(AllProviderEvents.Ready, handler1);
@ -156,8 +150,6 @@ describe('GenericEventEmitter', () => {
});
it('remove same handler when assigned to multiple events', async function () {
const emitter = new TestEventEmitter();
const handler = jest.fn();
emitter.addHandler(AllProviderEvents.Stale, handler);
emitter.addHandler(AllProviderEvents.ContextChanged, handler);
@ -174,8 +166,6 @@ describe('GenericEventEmitter', () => {
});
it('allow addition/removal of duplicate handlers', async function () {
const emitter = new TestEventEmitter();
const handler = jest.fn();
emitter.addHandler(AllProviderEvents.Stale, handler);
emitter.addHandler(AllProviderEvents.Stale, handler);
@ -191,8 +181,6 @@ describe('GenericEventEmitter', () => {
});
it('allow duplicate event handlers and call them', async function () {
const emitter = new TestEventEmitter();
const handler = jest.fn();
emitter.addHandler(AllProviderEvents.Stale, handler);
emitter.addHandler(AllProviderEvents.Stale, handler);
@ -205,8 +193,6 @@ describe('GenericEventEmitter', () => {
});
it('remove all handlers only for event type', async function () {
const emitter = new TestEventEmitter();
const handler1 = jest.fn();
const handler2 = jest.fn();
emitter.addHandler(AllProviderEvents.Ready, handler1);
@ -223,8 +209,6 @@ describe('GenericEventEmitter', () => {
});
it('remove all handlers if no event type is given', async function () {
const emitter = new TestEventEmitter();
const handler1 = jest.fn();
const handler2 = jest.fn();
emitter.addHandler(AllProviderEvents.Ready, handler1);

View File

@ -0,0 +1,214 @@
import type { HookData, BaseHook, BeforeHookContext, HookContext } from '../src/hooks';
import { MapHookData } from '../src/hooks';
import type { FlagValue } from '../src/evaluation';
describe('Hook Data Type Safety', () => {
it('should provide type safety with typed hook data', () => {
// Define a strict type for hook data
interface MyHookData {
startTime: number;
userId: string;
metadata: { version: string; feature: boolean };
tags: string[];
}
const hookData = new MapHookData<MyHookData>();
// Type-safe setting and getting
hookData.set('startTime', 123456);
hookData.set('userId', 'user-123');
hookData.set('metadata', { version: '1.0.0', feature: true });
hookData.set('tags', ['tag1', 'tag2']);
// TypeScript should infer the correct return types
const startTime: number | undefined = hookData.get('startTime');
const userId: string | undefined = hookData.get('userId');
const metadata: { version: string; feature: boolean } | undefined = hookData.get('metadata');
const tags: string[] | undefined = hookData.get('tags');
// Verify the values
expect(startTime).toBe(123456);
expect(userId).toBe('user-123');
expect(metadata).toEqual({ version: '1.0.0', feature: true });
expect(tags).toEqual(['tag1', 'tag2']);
// Type-safe existence checks
expect(hookData.has('startTime')).toBe(true);
expect(hookData.has('userId')).toBe(true);
expect(hookData.has('metadata')).toBe(true);
expect(hookData.has('tags')).toBe(true);
// Type-safe deletion
expect(hookData.delete('tags')).toBe(true);
expect(hookData.has('tags')).toBe(false);
});
it('should support untyped usage for backward compatibility', () => {
const hookData: HookData = new MapHookData();
// Untyped usage still works
hookData.set('anyKey', 'anyValue');
hookData.set('numberKey', 42);
hookData.set('objectKey', { nested: true });
const value: unknown = hookData.get('anyKey');
const numberValue: unknown = hookData.get('numberKey');
const objectValue: unknown = hookData.get('objectKey');
expect(value).toBe('anyValue');
expect(numberValue).toBe(42);
expect(objectValue).toEqual({ nested: true });
});
it('should support mixed usage with typed and untyped keys', () => {
interface PartiallyTypedData {
correlationId: string;
timestamp: number;
}
const hookData: HookData<PartiallyTypedData> = new MapHookData<PartiallyTypedData>();
// Typed usage
hookData.set('correlationId', 'abc-123');
hookData.set('timestamp', Date.now());
// Untyped usage for additional keys
hookData.set('dynamicKey', 'dynamicValue');
// Type-safe retrieval for typed keys
const correlationId: string | undefined = hookData.get('correlationId');
const timestamp: number | undefined = hookData.get('timestamp');
// Untyped retrieval for dynamic keys
const dynamicValue: unknown = hookData.get('dynamicKey');
expect(correlationId).toBe('abc-123');
expect(typeof timestamp).toBe('number');
expect(dynamicValue).toBe('dynamicValue');
});
it('should work with complex nested types', () => {
interface ComplexHookData {
request: {
id: string;
headers: Record<string, string>;
body?: { [key: string]: unknown };
};
response: {
status: number;
data: unknown;
headers: Record<string, string>;
};
metrics: {
startTime: number;
endTime?: number;
duration?: number;
};
}
const hookData: HookData<ComplexHookData> = new MapHookData<ComplexHookData>();
const requestData = {
id: 'req-123',
headers: { 'Content-Type': 'application/json' },
body: { flag: 'test-flag' },
};
hookData.set('request', requestData);
hookData.set('metrics', { startTime: Date.now() });
const retrievedRequest = hookData.get('request');
const retrievedMetrics = hookData.get('metrics');
expect(retrievedRequest).toEqual(requestData);
expect(retrievedMetrics?.startTime).toBeDefined();
expect(typeof retrievedMetrics?.startTime).toBe('number');
});
it('should support generic type inference', () => {
// This function demonstrates how the generic types work in practice
function createTypedHookData<T>(): HookData<T> {
return new MapHookData<T>();
}
interface TimingData {
start: number;
checkpoint: number;
}
const timingHookData = createTypedHookData<TimingData>();
timingHookData.set('start', performance.now());
timingHookData.set('checkpoint', performance.now());
const start: number | undefined = timingHookData.get('start');
const checkpoint: number | undefined = timingHookData.get('checkpoint');
expect(typeof start).toBe('number');
expect(typeof checkpoint).toBe('number');
});
it('should work with BaseHook interface without casting', () => {
interface TestHookData {
testId: string;
startTime: number;
metadata: { version: string };
}
class TestTypedHook implements BaseHook<FlagValue, TestHookData> {
capturedData: { testId?: string; duration?: number } = {};
before(hookContext: BeforeHookContext<FlagValue, TestHookData>) {
// No casting needed - TypeScript knows the types
hookContext.hookData.set('testId', 'test-123');
hookContext.hookData.set('startTime', Date.now());
hookContext.hookData.set('metadata', { version: '1.0.0' });
}
after(hookContext: HookContext<FlagValue, TestHookData>) {
// Type-safe getting with proper return types
const testId: string | undefined = hookContext.hookData.get('testId');
const startTime: number | undefined = hookContext.hookData.get('startTime');
if (testId && startTime) {
this.capturedData = {
testId,
duration: Date.now() - startTime,
};
}
}
}
const hook = new TestTypedHook();
// Create mock contexts that satisfy the BaseHook interface
const mockBeforeContext: BeforeHookContext<FlagValue, TestHookData> = {
flagKey: 'test-flag',
defaultValue: true,
flagValueType: 'boolean',
context: {},
clientMetadata: {
name: 'test-client',
domain: 'test-domain',
providerMetadata: { name: 'test-provider' },
},
providerMetadata: { name: 'test-provider' },
logger: { debug: jest.fn(), info: jest.fn(), warn: jest.fn(), error: jest.fn() },
hookData: new MapHookData<TestHookData>(),
};
const mockAfterContext: HookContext<FlagValue, TestHookData> = {
...mockBeforeContext,
context: Object.freeze({}),
};
// Execute the hook methods
hook.before!(mockBeforeContext);
hook.after!(mockAfterContext);
// Verify the typed hook worked correctly
expect(hook.capturedData.testId).toBe('test-123');
expect(hook.capturedData.duration).toBeDefined();
expect(typeof hook.capturedData.duration).toBe('number');
});
});

View File

@ -0,0 +1,113 @@
import { createEvaluationEvent } from '../src/telemetry/evaluation-event';
import { ErrorCode, StandardResolutionReasons, type EvaluationDetails } from '../src/evaluation/evaluation';
import type { HookContext } from '../src/hooks/hooks';
import { TelemetryAttribute, TelemetryFlagMetadata } from '../src/telemetry';
import { MapHookData } from '../src/hooks/hook-data';
describe('evaluationEvent', () => {
const flagKey = 'test-flag';
const providerMetadata = {
name: 'test-provider',
};
const mockHookContext: HookContext<boolean> = {
flagKey,
providerMetadata: providerMetadata,
context: {
targetingKey: 'test-target',
},
clientMetadata: {
providerMetadata,
},
defaultValue: false,
flagValueType: 'boolean',
logger: {
debug: jest.fn(),
info: jest.fn(),
error: jest.fn(),
warn: jest.fn(),
},
hookData: new MapHookData(),
};
it('should return basic event body with mandatory fields', () => {
const details: EvaluationDetails<boolean> = {
value: true,
reason: StandardResolutionReasons.STATIC,
flagMetadata: {},
flagKey,
};
const result = createEvaluationEvent(mockHookContext, details);
expect(result.name).toBe('feature_flag.evaluation');
expect(result.attributes).toEqual({
[TelemetryAttribute.KEY]: 'test-flag',
[TelemetryAttribute.PROVIDER]: 'test-provider',
[TelemetryAttribute.REASON]: StandardResolutionReasons.STATIC.toLowerCase(),
[TelemetryAttribute.CONTEXT_ID]: 'test-target',
[TelemetryAttribute.VALUE]: true,
});
});
it('should include variant when provided', () => {
const details: EvaluationDetails<boolean> = {
flagKey,
value: true,
variant: 'test-variant',
reason: StandardResolutionReasons.STATIC,
flagMetadata: {},
};
const result = createEvaluationEvent(mockHookContext, details);
expect(result.attributes[TelemetryAttribute.VARIANT]).toBe('test-variant');
expect(result.attributes[TelemetryAttribute.VALUE]).toBeUndefined();
});
it('should include flag metadata when provided', () => {
const details: EvaluationDetails<boolean> = {
flagKey,
value: true,
reason: StandardResolutionReasons.STATIC,
flagMetadata: {
[TelemetryFlagMetadata.FLAG_SET_ID]: 'test-set',
[TelemetryFlagMetadata.VERSION]: 'v1.0',
[TelemetryFlagMetadata.CONTEXT_ID]: 'metadata-context',
},
};
const result = createEvaluationEvent(mockHookContext, details);
expect(result.attributes[TelemetryAttribute.FLAG_SET_ID]).toBe('test-set');
expect(result.attributes[TelemetryAttribute.VERSION]).toBe('v1.0');
expect(result.attributes[TelemetryAttribute.CONTEXT_ID]).toBe('metadata-context');
});
it('should handle error cases', () => {
const details: EvaluationDetails<boolean> = {
flagKey,
value: false,
reason: StandardResolutionReasons.ERROR,
errorCode: ErrorCode.GENERAL,
errorMessage: 'test error',
flagMetadata: {},
};
const result = createEvaluationEvent(mockHookContext, details);
expect(result.attributes[TelemetryAttribute.ERROR_CODE]).toBe(ErrorCode.GENERAL.toLowerCase());
expect(result.attributes[TelemetryAttribute.ERROR_MESSAGE]).toBe('test error');
});
it('should use unknown reason when reason is not provided', () => {
const details: EvaluationDetails<boolean> = {
flagKey,
value: true,
flagMetadata: {},
};
const result = createEvaluationEvent(mockHookContext, details);
expect(result.attributes[TelemetryAttribute.REASON]).toBe(StandardResolutionReasons.UNKNOWN.toLowerCase());
});
});

View File

@ -1,6 +1,97 @@
# Changelog
## [1.6.1](https://github.com/open-feature/js-sdk/compare/web-sdk-v1.6.0...web-sdk-v1.6.1) (2025-08-14)
### 🐛 Bug Fixes
* update core dep ([#1228](https://github.com/open-feature/js-sdk/issues/1228)) ([845d24c](https://github.com/open-feature/js-sdk/commit/845d24c5fecc80de3080e49fde839f08ecac6b33))
## [1.6.0](https://github.com/open-feature/js-sdk/compare/web-sdk-v1.5.0...web-sdk-v1.6.0) (2025-08-12)
### ✨ New Features
* add evaluation-scoped hook data ([#1216](https://github.com/open-feature/js-sdk/issues/1216)) ([07af3a9](https://github.com/open-feature/js-sdk/commit/07af3a9eda895e9edb24c7ee1e3c1c4f16e17431))
* **web-global-build:** impl ([#1225](https://github.com/open-feature/js-sdk/issues/1225)) ([40a512e](https://github.com/open-feature/js-sdk/commit/40a512e21204eb92dc3ef4161b383f9c1fd74da7))
### 📚 Documentation
* Clarify the behavior of setProviderAndWait ([#1180](https://github.com/open-feature/js-sdk/issues/1180)) ([4fe8d87](https://github.com/open-feature/js-sdk/commit/4fe8d87a2e5df2cbd4086cc4f4a380e8857ed8ba))
## [1.5.0](https://github.com/open-feature/js-sdk/compare/web-sdk-v1.4.1...web-sdk-v1.5.0) (2025-04-11)
### ✨ New Features
* add a top-level method for accessing providers ([#1152](https://github.com/open-feature/js-sdk/issues/1152)) ([ae8fce8](https://github.com/open-feature/js-sdk/commit/ae8fce87530005ed20f7e68dc696ce67053fca31))
* add support for abort controllers to event handlers ([#1151](https://github.com/open-feature/js-sdk/issues/1151)) ([6a22483](https://github.com/open-feature/js-sdk/commit/6a224830fa4e62fc30a7802536f6f6fc3f772038))
### 🐛 Bug Fixes
* Typo in name of the function ([2c5b37c](https://github.com/open-feature/js-sdk/commit/2c5b37c79d72d60864c27b9e67d96e99ef4ae241))
## [1.4.1](https://github.com/open-feature/js-sdk/compare/web-sdk-v1.4.0...web-sdk-v1.4.1) (2025-02-07)
### 🐛 Bug Fixes
* msg missing when providers return err resolutions ([#1134](https://github.com/open-feature/js-sdk/issues/1134)) ([bc9f6e4](https://github.com/open-feature/js-sdk/commit/bc9f6e44da3f1c0a66659aee2d0316629ac34fbf))
### 🧹 Chore
* update core peer ([8bbd43e](https://github.com/open-feature/js-sdk/commit/8bbd43e579a0c2e0c5b7eec00f94bbcffce04773))
## [1.4.0](https://github.com/open-feature/js-sdk/compare/web-sdk-v1.3.2...web-sdk-v1.4.0) (2024-12-18)
### ⚠ BREAKING CHANGES
The signature of the `finally` hook stage has been changed. The signature now includes the `evaluation details`, as per the [OpenFeature specification](https://openfeature.dev/specification/sections/hooks#requirement-438). Note that since hooks are still `experimental,` this does not constitute a change requiring a new major version. To migrate, update any hook that implements the `finally` stage to accept `evaluation details` as the second argument.
* add evaluation details to finally hook ([#1087](https://github.com/open-feature/js-sdk/issues/1087)) ([2135254](https://github.com/open-feature/js-sdk/commit/2135254c4bee52b4bcadfbf8b99a896cfd930cca))
### ✨ New Features
* add evaluation details to finally hook ([#1087](https://github.com/open-feature/js-sdk/issues/1087)) ([2135254](https://github.com/open-feature/js-sdk/commit/2135254c4bee52b4bcadfbf8b99a896cfd930cca))
### 📚 Documentation
* fix comment in README for Hooks after method ([#1102](https://github.com/open-feature/js-sdk/issues/1102)) ([ba8d1ae](https://github.com/open-feature/js-sdk/commit/ba8d1aeec837cb089cda3499d44ecc505ea0c947))
### 🔄 Refactoring
* improve track interface for providers ([#1100](https://github.com/open-feature/js-sdk/issues/1100)) ([5e5b160](https://github.com/open-feature/js-sdk/commit/5e5b16022122b71760634ac90e3fd962aa831c74))
## [1.3.2](https://github.com/open-feature/js-sdk/compare/web-sdk-v1.3.1...web-sdk-v1.3.2) (2024-11-07)
### 🐛 Bug Fixes
* update OpenFeature core version to 1.5.0 ([#1077](https://github.com/open-feature/js-sdk/issues/1077)) ([a3469b6](https://github.com/open-feature/js-sdk/commit/a3469b6799c3f0d77cb38dcdc708ce615123d7f6))
### 🧹 Chore
* loosen peer dependency requirements, remove some ci automation ([#1080](https://github.com/open-feature/js-sdk/issues/1080)) ([ef3ba21](https://github.com/open-feature/js-sdk/commit/ef3ba2167ac95cd0c6a046d206bd60bbcf84e80c))
### 🚀 Performance
* avoid using exceptions for flow control ([#1074](https://github.com/open-feature/js-sdk/issues/1074)) ([26264d6](https://github.com/open-feature/js-sdk/commit/26264d6d090b2ed31b27d36e71194b9fa911563b))
## [1.3.1](https://github.com/open-feature/js-sdk/compare/web-sdk-v1.3.0...web-sdk-v1.3.1) (2024-10-29)
### 📚 Documentation
* add tracking sections ([#1068](https://github.com/open-feature/js-sdk/issues/1068)) ([e131faf](https://github.com/open-feature/js-sdk/commit/e131faffad9025e9c7194f39558bf3b3cec31807))
## [1.3.0](https://github.com/open-feature/js-sdk/compare/web-sdk-v1.2.4...web-sdk-v1.3.0) (2024-10-29)

View File

@ -16,8 +16,8 @@
<img alt="Specification" src="https://img.shields.io/static/v1?label=specification&message=v0.8.0&color=yellow&style=for-the-badge" />
</a>
<!-- x-release-please-start-version -->
<a href="https://github.com/open-feature/js-sdk/releases/tag/web-sdk-v1.3.0">
<img alt="Release" src="https://img.shields.io/static/v1?label=release&message=v1.3.0&color=blue&style=for-the-badge" />
<a href="https://github.com/open-feature/js-sdk/releases/tag/web-sdk-v1.6.1">
<img alt="Release" src="https://img.shields.io/static/v1?label=release&message=v1.6.1&color=blue&style=for-the-badge" />
</a>
<!-- x-release-please-end -->
<br/>
@ -75,7 +75,11 @@ yarn add @openfeature/web-sdk @openfeature/core
import { OpenFeature } from '@openfeature/web-sdk';
// Register your feature flag provider
await OpenFeature.setProviderAndWait(new YourProviderOfChoice());
try {
await OpenFeature.setProviderAndWait(new YourProviderOfChoice());
} catch (error) {
console.error('Failed to initialize provider:', error);
}
// create a new client
const client = OpenFeature.getClient();
@ -121,7 +125,11 @@ Once you've added a provider as a dependency, it can be registered with OpenFeat
To register a provider and ensure it is ready before further actions are taken, you can use the `setProviderAndWait` method as shown below:
```ts
await OpenFeature.setProviderAndWait(new MyProvider());
try {
await OpenFeature.setProviderAndWait(new MyProvider());
} catch (error) {
console.error('Failed to initialize provider:', error);
}
```
#### Synchronous
@ -172,7 +180,7 @@ await OpenFeature.setContext({ targetingKey: localStorage.getItem("targetingKey"
```
Context is global and setting it is `async`.
Providers may implement an `onContextChanged` method that receives the old and newer contexts.
Providers may implement an `onContextChange` method that receives the old and newer contexts.
Given a context change, providers can use this method internally to detect if the flag values cached on the client are still valid.
If needed, a request will be made to the provider with the new context in order to get the correct flag values.
@ -379,7 +387,7 @@ import type { Hook, HookContext, EvaluationDetails, FlagValue } from "@openfeatu
export class MyHook implements Hook {
after(hookContext: HookContext, evaluationDetails: EvaluationDetails<FlagValue>) {
// code that runs when there's an error during a flag evaluation
// code that runs after flag values are successfully resolved from the provider
}
}
```

View File

@ -1,8 +1,10 @@
{
"name": "@openfeature/web-sdk",
"version": "1.3.0",
"version": "1.6.1",
"description": "OpenFeature SDK for Web",
"main": "./dist/cjs/index.js",
"unpkg": "dist/global/index.min.js",
"jsdelivr": "dist/global/index.min.js",
"files": [
"dist/"
],
@ -20,13 +22,14 @@
"clean": "shx rm -rf ./dist",
"build:web-esm": "esbuild src/index.ts --bundle --external:@openfeature/core --sourcemap --target=es2015 --platform=browser --format=esm --outfile=./dist/esm/index.js --analyze",
"build:web-cjs": "esbuild src/index.ts --bundle --external:@openfeature/core --sourcemap --target=es2015 --platform=browser --format=cjs --outfile=./dist/cjs/index.js --analyze",
"build:web-global": "esbuild src/index.ts --bundle --sourcemap --target=es2015 --platform=browser --format=iife --outfile=./dist/global/index.js --global-name=OpenFeature --analyze",
"build:web-global:min": "esbuild src/index.ts --bundle --sourcemap --target=es2015 --platform=browser --format=iife --outfile=./dist/global/index.min.js --global-name=OpenFeature --minify --analyze",
"build:rollup-types": "rollup -c ../../rollup.config.mjs",
"build": "npm run clean && npm run build:web-esm && npm run build:web-cjs && npm run build:rollup-types",
"build": "npm run clean && npm run build:web-esm && npm run build:web-cjs && npm run build:web-global && npm run build:web-global:min && npm run build:rollup-types",
"postbuild": "shx cp ./../../package.esm.json ./dist/esm/package.json",
"current-version": "echo $npm_package_version",
"prepack": "shx cp ./../../LICENSE ./LICENSE",
"publish-if-not-exists": "cp $NPM_CONFIG_USERCONFIG .npmrc && if [ \"$(npm show $npm_package_name@$npm_package_version version)\" = \"$(npm run current-version -s)\" ]; then echo 'already published, skipping'; else npm publish --access public; fi",
"update-core-peer": "npm install --save-peer --save-exact @openfeature/core@$OPENFEATURE_CORE_VERSION"
"publish-if-not-exists": "cp $NPM_CONFIG_USERCONFIG .npmrc && if [ \"$(npm show $npm_package_name@$npm_package_version version)\" = \"$(npm run current-version -s)\" ]; then echo 'already published, skipping'; else npm publish --access public; fi"
},
"repository": {
"type": "git",
@ -47,9 +50,9 @@
},
"homepage": "https://github.com/open-feature/js-sdk#readme",
"peerDependencies": {
"@openfeature/core": "1.4.0"
"@openfeature/core": "^1.9.0"
},
"devDependencies": {
"@openfeature/core": "1.5.0"
"@openfeature/core": "^1.9.0"
}
}

View File

@ -10,7 +10,10 @@ import type {
Logger,
TrackingEventDetails,
OpenFeatureError,
ResolutionDetails } from '@openfeature/core';
FlagMetadata,
ResolutionDetails,
EventOptions,
} from '@openfeature/core';
import {
ErrorCode,
ProviderFatalError,
@ -19,12 +22,13 @@ import {
StandardResolutionReasons,
instantiateErrorByErrorCode,
statusMatchesEvent,
MapHookData,
} from '@openfeature/core';
import type { FlagEvaluationOptions } from '../../evaluation';
import type { ProviderEvents } from '../../events';
import type { InternalEventEmitter } from '../../events/internal/internal-event-emitter';
import type { Hook } from '../../hooks';
import type { Provider} from '../../provider';
import type { Provider } from '../../provider';
import { ProviderStatus } from '../../provider';
import type { Client } from './../client';
@ -72,7 +76,7 @@ export class OpenFeatureClient implements Client {
return this.providerStatusAccessor();
}
addHandler(eventType: ProviderEvents, handler: EventHandler): void {
addHandler(eventType: ProviderEvents, handler: EventHandler, options: EventOptions): void {
this.emitterAccessor().addHandler(eventType, handler);
const shouldRunNow = statusMatchesEvent(eventType, this.providerStatus);
@ -88,6 +92,12 @@ export class OpenFeatureClient implements Client {
this._logger?.error('Error running event handler:', err);
}
}
if (options?.signal && typeof options.signal.addEventListener === 'function') {
options.signal.addEventListener('abort', () => {
this.removeHandler(eventType, handler);
});
}
}
removeHandler(notificationType: ProviderEvents, handler: EventHandler): void {
@ -183,7 +193,7 @@ export class OpenFeatureClient implements Client {
return this.evaluate<T>(flagKey, this._provider.resolveObjectEvaluation, defaultValue, 'object', options);
}
track(occurrenceKey: string, occurrenceDetails: TrackingEventDetails): void {
track(occurrenceKey: string, occurrenceDetails: TrackingEventDetails = {}): void {
try {
this.shortCircuitIfNotReady();
@ -222,83 +232,82 @@ export class OpenFeatureClient implements Client {
...this.apiContextAccessor(this?.options?.domain),
};
// this reference cannot change during the course of evaluation
// it may be used as a key in WeakMaps
const hookContext: Readonly<HookContext> = {
flagKey,
defaultValue,
flagValueType: flagType,
clientMetadata: this.metadata,
providerMetadata: this._provider.metadata,
context,
logger: this._logger,
};
// Create hook context instances for each hook (stable object references for the entire evaluation)
// This ensures hooks can use WeakMaps with hookContext as keys across lifecycle methods
// NOTE: Uses the reversed order to reduce the number of times we have to calculate the index.
const hookContexts = allHooksReversed.map<HookContext>(() =>
Object.freeze({
flagKey,
defaultValue,
flagValueType: flagType,
clientMetadata: this.metadata,
providerMetadata: this._provider.metadata,
context,
logger: this._logger,
hookData: new MapHookData(),
}),
);
let evaluationDetails: EvaluationDetails<T>;
try {
this.beforeHooks(allHooks, hookContext, options);
this.beforeHooks(allHooks, hookContexts, options);
this.shortCircuitIfNotReady();
// run the referenced resolver, binding the provider.
const resolution = resolver.call(this._provider, flagKey, defaultValue, context, this._logger);
const evaluationDetails = {
const resolutionDetails = {
...resolution,
flagMetadata: Object.freeze(resolution.flagMetadata ?? {}),
flagKey,
};
if (evaluationDetails.errorCode) {
throw instantiateErrorByErrorCode(evaluationDetails.errorCode);
if (resolutionDetails.errorCode) {
const err = instantiateErrorByErrorCode(resolutionDetails.errorCode, resolutionDetails.errorMessage);
this.errorHooks(allHooksReversed, hookContexts, err, options);
evaluationDetails = this.getErrorEvaluationDetails(flagKey, defaultValue, err, resolutionDetails.flagMetadata);
} else {
this.afterHooks(allHooksReversed, hookContexts, resolutionDetails, options);
evaluationDetails = resolutionDetails;
}
this.afterHooks(allHooksReversed, hookContext, evaluationDetails, options);
return evaluationDetails;
} catch (err: unknown) {
const errorMessage: string = (err as Error)?.message;
const errorCode: ErrorCode = (err as OpenFeatureError)?.code || ErrorCode.GENERAL;
this.errorHooks(allHooksReversed, hookContext, err, options);
return {
errorCode,
errorMessage,
value: defaultValue,
reason: StandardResolutionReasons.ERROR,
flagMetadata: Object.freeze({}),
flagKey,
};
} finally {
this.finallyHooks(allHooksReversed, hookContext, options);
this.errorHooks(allHooksReversed, hookContexts, err, options);
evaluationDetails = this.getErrorEvaluationDetails(flagKey, defaultValue, err);
}
this.finallyHooks(allHooksReversed, hookContexts, evaluationDetails, options);
return evaluationDetails;
}
private beforeHooks(hooks: Hook[], hookContext: HookContext, options: FlagEvaluationOptions) {
Object.freeze(hookContext);
Object.freeze(hookContext.context);
for (const hook of hooks) {
private beforeHooks(hooks: Hook[], hookContexts: HookContext[], options: FlagEvaluationOptions) {
for (const [index, hook] of hooks.entries()) {
const hookContextIndex = hooks.length - 1 - index; // reverse index for before hooks
const hookContext = hookContexts[hookContextIndex];
Object.freeze(hookContext);
Object.freeze(hookContext.context);
hook?.before?.(hookContext, Object.freeze(options.hookHints));
}
}
private afterHooks(
hooks: Hook[],
hookContext: HookContext,
hookContexts: HookContext[],
evaluationDetails: EvaluationDetails<FlagValue>,
options: FlagEvaluationOptions,
) {
// run "after" hooks sequentially
for (const hook of hooks) {
for (const [index, hook] of hooks.entries()) {
const hookContext = hookContexts[index];
hook?.after?.(hookContext, evaluationDetails, options.hookHints);
}
}
private errorHooks(hooks: Hook[], hookContext: HookContext, err: unknown, options: FlagEvaluationOptions) {
private errorHooks(hooks: Hook[], hookContexts: HookContext[], err: unknown, options: FlagEvaluationOptions) {
// run "error" hooks sequentially
for (const hook of hooks) {
for (const [index, hook] of hooks.entries()) {
try {
const hookContext = hookContexts[index];
hook?.error?.(hookContext, err, options.hookHints);
} catch (err) {
this._logger.error(`Unhandled error during 'error' hook: ${err}`);
@ -310,11 +319,17 @@ export class OpenFeatureClient implements Client {
}
}
private finallyHooks(hooks: Hook[], hookContext: HookContext, options: FlagEvaluationOptions) {
private finallyHooks(
hooks: Hook[],
hookContexts: HookContext[],
evaluationDetails: EvaluationDetails<FlagValue>,
options: FlagEvaluationOptions,
) {
// run "finally" hooks sequentially
for (const hook of hooks) {
for (const [index, hook] of hooks.entries()) {
try {
hook?.finally?.(hookContext, options.hookHints);
const hookContext = hookContexts[index];
hook?.finally?.(hookContext, evaluationDetails, options.hookHints);
} catch (err) {
this._logger.error(`Unhandled error during 'finally' hook: ${err}`);
if (err instanceof Error) {
@ -341,4 +356,23 @@ export class OpenFeatureClient implements Client {
throw new ProviderFatalError('provider is in an irrecoverable error state');
}
}
private getErrorEvaluationDetails<T extends FlagValue>(
flagKey: string,
defaultValue: T,
err: unknown,
flagMetadata: FlagMetadata = {},
): EvaluationDetails<T> {
const errorMessage: string = (err as Error)?.message;
const errorCode: ErrorCode = (err as OpenFeatureError)?.code || ErrorCode.GENERAL;
return {
errorCode,
errorMessage,
value: defaultValue,
reason: StandardResolutionReasons.ERROR,
flagMetadata: Object.freeze(flagMetadata),
flagKey,
};
}
}

View File

@ -1,3 +1,3 @@
import type { BaseHook, FlagValue } from '@openfeature/core';
export type Hook = BaseHook<FlagValue, void, void>;
export type Hook<TData = Record<string, unknown>> = BaseHook<FlagValue, TData, void, void>;

View File

@ -77,7 +77,7 @@ export class OpenFeatureAPI
* Setting a provider supersedes the current provider used in new and existing unbound clients.
* @param {Provider} provider The provider responsible for flag evaluations.
* @returns {Promise<void>}
* @throws Uncaught exceptions thrown by the provider during initialization.
* @throws {Error} If the provider throws an exception during initialization.
*/
setProviderAndWait(provider: Provider): Promise<void>;
/**
@ -87,7 +87,7 @@ export class OpenFeatureAPI
* @param {Provider} provider The provider responsible for flag evaluations.
* @param {EvaluationContext} context The evaluation context to use for flag evaluations.
* @returns {Promise<void>}
* @throws Uncaught exceptions thrown by the provider during initialization.
* @throws {Error} If the provider throws an exception during initialization.
*/
setProviderAndWait(provider: Provider, context: EvaluationContext): Promise<void>;
/**
@ -97,7 +97,7 @@ export class OpenFeatureAPI
* @param {string} domain The name to identify the client
* @param {Provider} provider The provider responsible for flag evaluations.
* @returns {Promise<void>}
* @throws Uncaught exceptions thrown by the provider during initialization.
* @throws {Error} If the provider throws an exception during initialization.
*/
setProviderAndWait(domain: string, provider: Provider): Promise<void>;
/**
@ -108,7 +108,7 @@ export class OpenFeatureAPI
* @param {Provider} provider The provider responsible for flag evaluations.
* @param {EvaluationContext} context The evaluation context to use for flag evaluations.
* @returns {Promise<void>}
* @throws Uncaught exceptions thrown by the provider during initialization.
* @throws {Error} If the provider throws an exception during initialization.
*/
setProviderAndWait(domain: string, provider: Provider, context: EvaluationContext): Promise<void>;
async setProviderAndWait(
@ -205,6 +205,27 @@ export class OpenFeatureAPI
return this;
}
/**
* Get the default provider.
*
* Note that it isn't recommended to interact with the provider directly, but rather through
* an OpenFeature client.
* @returns {Provider} Default Provider
*/
getProvider(): Provider;
/**
* Get the provider bound to the specified domain.
*
* Note that it isn't recommended to interact with the provider directly, but rather through
* an OpenFeature client.
* @param {string} domain An identifier which logically binds clients with providers
* @returns {Provider} Domain-scoped provider
*/
getProvider(domain?: string): Provider;
getProvider(domain?: string): Provider {
return this.getProviderForClient(domain);
}
/**
* Sets the evaluation context globally.
* This will be used by all providers that have not bound to a domain.
@ -325,9 +346,9 @@ export class OpenFeatureAPI
}
/**
* A factory function for creating new named OpenFeature clients. Clients can contain
* their own state (e.g. logger, hook, context). Multiple clients can be used
* to segment feature flag configuration.
* A factory function for creating new domain-scoped OpenFeature clients. Clients
* can contain their own state (e.g. logger, hook, context). Multiple domains
* can be used to segment feature flag configuration.
*
* If there is already a provider bound to this name via {@link this.setProvider setProvider}, this provider will be used.
* Otherwise, the default provider is used until a provider is assigned to that name.

View File

@ -655,6 +655,18 @@ describe('OpenFeatureClient', () => {
}).not.toThrow();
});
it('provide empty tracking details to provider if not supplied in call', async () => {
await OpenFeature.setProviderAndWait({ ...MOCK_PROVIDER });
const client = OpenFeature.getClient();
client.track(eventName);
expect(MOCK_PROVIDER.track).toHaveBeenCalledWith(
eventName,
expect.any(Object),
expect.any(Object),
);
});
it('should no-op and not throw if provider throws', async () => {
await OpenFeature.setProviderAndWait({
...MOCK_PROVIDER,

Some files were not shown because too many files have changed in this diff Show More