From 4fa6a438a8377880aefeaf35b9a803910ed31126 Mon Sep 17 00:00:00 2001 From: OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com> Date: Mon, 26 Aug 2024 17:24:13 +0000 Subject: [PATCH] chore: update sdk readmes Signed-off-by: OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com> --- docs/reference/technologies/client/kotlin.mdx | 2 +- docs/reference/technologies/client/swift.mdx | 8 +- .../technologies/client/web/index.mdx | 6 +- .../technologies/client/web/react.mdx | 66 ++++++++++++++- docs/reference/technologies/server/dotnet.mdx | 84 ++++++++++--------- docs/reference/technologies/server/go.mdx | 2 +- docs/reference/technologies/server/java.mdx | 14 ++-- .../technologies/server/javascript/index.mdx | 2 +- .../technologies/server/javascript/nestjs.mdx | 2 +- docs/reference/technologies/server/php.mdx | 6 +- docs/reference/technologies/server/python.mdx | 10 +-- docs/reference/technologies/server/ruby.mdx | 2 +- src/datasets/sdks/sdk-compatibility.json | 14 ++-- 13 files changed, 140 insertions(+), 78 deletions(-) diff --git a/docs/reference/technologies/client/kotlin.mdx b/docs/reference/technologies/client/kotlin.mdx index f1250cdca..46b6c2c67 100644 --- a/docs/reference/technologies/client/kotlin.mdx +++ b/docs/reference/technologies/client/kotlin.mdx @@ -10,7 +10,7 @@ This content has been automatically generated from kotlin-sdk. Edits should be made here: https://github.com/open-feature/kotlin-sdk Once a repo has been updated, docs can be generated by running: yarn update:sdk-docs -Last updated at Thu Jun 13 2024 08:07:56 GMT+0000 (Coordinated Universal Time) +Last updated at Mon Aug 26 2024 17:24:12 GMT+0000 (Coordinated Universal Time) -->

diff --git a/docs/reference/technologies/client/swift.mdx b/docs/reference/technologies/client/swift.mdx index 6e0625095..3a2d584a0 100644 --- a/docs/reference/technologies/client/swift.mdx +++ b/docs/reference/technologies/client/swift.mdx @@ -10,7 +10,7 @@ This content has been automatically generated from swift-sdk. Edits should be made here: https://github.com/open-feature/swift-sdk Once a repo has been updated, docs can be generated by running: yarn update:sdk-docs -Last updated at Thu Jun 13 2024 08:07:56 GMT+0000 (Coordinated Universal Time) +Last updated at Mon Aug 26 2024 17:24:12 GMT+0000 (Coordinated Universal Time) -->

@@ -20,8 +20,8 @@ Last updated at Thu Jun 13 2024 08:07:56 GMT+0000 (Coordinated Universal Time) - - Release + + Release @@ -58,7 +58,7 @@ First, ensure you have your GitHub account added as an option (+ > Add Source Co If you manage dependencies through SPM, in the dependencies section of Package.swift add: ```swift -.package(url: "git@github.com:open-feature/swift-sdk.git", from: "0.1.0") +.package(url: "git@github.com:open-feature/swift-sdk.git", from: "0.2.0") ``` and in the target dependencies section add: diff --git a/docs/reference/technologies/client/web/index.mdx b/docs/reference/technologies/client/web/index.mdx index 7df4909fc..a1374b0c5 100644 --- a/docs/reference/technologies/client/web/index.mdx +++ b/docs/reference/technologies/client/web/index.mdx @@ -10,7 +10,7 @@ This content has been automatically generated from js-sdk. Edits should be made here: https://github.com/open-feature/js-sdk Once a repo has been updated, docs can be generated by running: yarn update:sdk-docs -Last updated at Thu Jun 13 2024 08:07:56 GMT+0000 (Coordinated Universal Time) +Last updated at Mon Aug 26 2024 17:24:12 GMT+0000 (Coordinated Universal Time) -->

@@ -18,8 +18,8 @@ Last updated at Thu Jun 13 2024 08:07:56 GMT+0000 (Coordinated Universal Time) Specification - - Release + + Release
diff --git a/docs/reference/technologies/client/web/react.mdx b/docs/reference/technologies/client/web/react.mdx index 26545b473..8f870eb2e 100644 --- a/docs/reference/technologies/client/web/react.mdx +++ b/docs/reference/technologies/client/web/react.mdx @@ -10,7 +10,7 @@ This content has been automatically generated from js-sdk. Edits should be made here: https://github.com/open-feature/js-sdk Once a repo has been updated, docs can be generated by running: yarn update:sdk-docs -Last updated at Thu Jun 13 2024 08:07:56 GMT+0000 (Coordinated Universal Time) +Last updated at Mon Aug 26 2024 17:24:12 GMT+0000 (Coordinated Universal Time) -->

@@ -18,8 +18,8 @@ Last updated at Thu Jun 13 2024 08:07:56 GMT+0000 (Coordinated Universal Time) Specification - - Release + + Release
@@ -51,6 +51,7 @@ In addition to the feature provided by the [web sdk](/docs/reference/technologie - [Re-rendering with Context Changes](#re-rendering-with-context-changes) - [Re-rendering with Flag Configuration Changes](#re-rendering-with-flag-configuration-changes) - [Suspense Support](#suspense-support) + - [Testing](#testing) - [FAQ and troubleshooting](#faq-and-troubleshooting) - [Resources](#resources) @@ -274,6 +275,65 @@ function Fallback() { This can be disabled in the hook options (or in the [OpenFeatureProvider](#openfeatureprovider-context-provider)). +### Testing + +The React SDK includes a built-in context provider for testing. +This allows you to easily test components that use evaluation hooks, such as `useFlag`. +If you try to test a component (in this case, `MyComponent`) which uses an evaluation hook, you might see an error message like: + +> No OpenFeature client available - components using OpenFeature must be wrapped with an ``. + +You can resolve this by simply wrapping your component under test in the OpenFeatureTestProvider: + +```tsx +// use default values for all evaluations + + + +``` + +The basic configuration above will simply use the default value provided in code. +If you'd like to control the values returned by the evaluation hooks, you can pass a map of flag keys and values: + +```tsx +// return `true` for all evaluations of `'my-boolean-flag'` + + + +``` + +Additionally, you can pass an artificial delay for the provider startup to test your suspense boundaries or loaders/spinners impacted by feature flags: + +```tsx +// delay the provider start by 1000ms and then return `true` for all evaluations of `'my-boolean-flag'` + + + +``` + +For maximum control, you can also pass your own mock provider implementation. +The type of this option is `Partial`, so you can pass an incomplete implementation: + +```tsx +class MyTestProvider implements Partial { + // implement the relevant resolver + resolveBooleanEvaluation(): ResolutionDetails { + return { + value: true, + variant: 'my-variant', + reason: 'MY_REASON', + }; + } +} +``` + +```tsx +// use your custom testing provider + + +, +``` + ## FAQ and troubleshooting > I get an error that says something like: `A React component suspended while rendering, but no fallback UI was specified.` diff --git a/docs/reference/technologies/server/dotnet.mdx b/docs/reference/technologies/server/dotnet.mdx index edec5f74a..5446f125c 100644 --- a/docs/reference/technologies/server/dotnet.mdx +++ b/docs/reference/technologies/server/dotnet.mdx @@ -10,13 +10,13 @@ This content has been automatically generated from dotnet-sdk. Edits should be made here: https://github.com/open-feature/dotnet-sdk Once a repo has been updated, docs can be generated by running: yarn update:sdk-docs -Last updated at Thu Jun 13 2024 08:07:55 GMT+0000 (Coordinated Universal Time) +Last updated at Mon Aug 26 2024 17:24:11 GMT+0000 (Coordinated Universal Time) --> [![Specification](https://img.shields.io/static/v1?label=specification&message=v0.7.0&color=yellow&style=for-the-badge)](https://github.com/open-feature/spec/releases/tag/v0.7.0) [ - ![Release](https://img.shields.io/static/v1?label=release&message=v1.5.0&color=blue&style=for-the-badge) -](https://github.com/open-feature/dotnet-sdk/releases/tag/v1.5.0) + ![Release](https://img.shields.io/static/v1?label=release&message=v2.0.0&color=blue&style=for-the-badge) +](https://github.com/open-feature/dotnet-sdk/releases/tag/v2.0.0) [![Slack](https://img.shields.io/badge/slack-%40cncf%2Fopenfeature-brightgreen?style=flat&logo=slack)](https://cloud-native.slack.com/archives/C0344AANLA1) [![Codecov](https://codecov.io/gh/open-feature/dotnet-sdk/branch/main/graph/badge.svg?token=MONAVJBXUJ)](https://codecov.io/gh/open-feature/dotnet-sdk) @@ -53,13 +53,13 @@ dotnet add package OpenFeature public async Task Example() { // Register your feature flag provider - await Api.Instance.SetProvider(new InMemoryProvider()); + await Api.Instance.SetProviderAsync(new InMemoryProvider()); // Create a new client FeatureClient client = Api.Instance.GetClient(); // Evaluate your feature flag - bool v2Enabled = await client.GetBooleanValue("v2_enabled", false); + bool v2Enabled = await client.GetBooleanValueAsync("v2_enabled", false); if ( v2Enabled ) { @@ -70,16 +70,16 @@ public async Task Example() ## Features -| 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). | -| ✅ | [Hooks](#hooks) | Add functionality to various stages of the flag evaluation life-cycle. | -| ✅ | [Logging](#logging) | Integrate with popular logging packages. | -| ✅ | [Named clients](#named-clients) | Utilize multiple providers in a single application. | -| ✅ | [Eventing](#eventing) | React to state changes in the provider or flag management system. | -| ✅ | [Shutdown](#shutdown) | Gracefully clean up a provider during application shutdown. | -| ✅ | [Extending](#extending) | Extend OpenFeature with custom providers and hooks. | +| 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). | +| ✅ | [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. | +| ✅ | [Shutdown](#shutdown) | Gracefully clean up a provider during application shutdown. | +| ✅ | [Extending](#extending) | Extend OpenFeature with custom providers and hooks. | > Implemented: ✅ | In-progress: ⚠️ | Not implemented yet: ❌ @@ -93,11 +93,11 @@ If the provider you're looking for hasn't been created yet, see the [develop a p Once you've added a provider as a dependency, it can be registered with OpenFeature like this: ```csharp -await Api.Instance.SetProvider(new MyProvider()); +await Api.Instance.SetProviderAsync(new MyProvider()); ``` In some situations, it may be beneficial to register multiple providers in the same application. -This is possible using [named clients](#named-clients), which is covered in more detail below. +This is possible using [domains](#domains), which is covered in more detail below. ### Targeting @@ -124,7 +124,7 @@ builder = EvaluationContext.Builder(); builder.Set("region", "us-east-1"); EvaluationContext reqCtx = builder.Build(); -bool flagValue = await client.GetBooleanValue("some-flag", false, reqCtx); +bool flagValue = await client.GetBooleanValuAsync("some-flag", false, reqCtx); ``` @@ -145,34 +145,36 @@ var client = Api.Instance.GetClient(); client.AddHooks(new ExampleClientHook()); // add a hook for this evaluation only -var value = await client.GetBooleanValue("boolFlag", false, context, new FlagEvaluationOptions(new ExampleInvocationHook())); +var value = await client.GetBooleanValueAsync("boolFlag", false, context, new FlagEvaluationOptions(new ExampleInvocationHook())); ``` ### Logging The .NET SDK uses Microsoft.Extensions.Logging. See the [manual](https://learn.microsoft.com/en-us/dotnet/core/extensions/logging?tabs=command-line) for complete documentation. -### Named clients +### Domains -Clients can be given a name. -A name is a logical identifier that can be used to associate clients with a particular provider. -If a name has no associated provider, the global provider is used. +Clients can be assigned to a domain. +A domain is a logical identifier which can be used to associate clients with a particular provider. +If a domain has no associated provider, the default provider is used. ```csharp // registering the default provider -await Api.Instance.SetProvider(new LocalProvider()); +await Api.Instance.SetProviderAsync(new LocalProvider()); -// registering a named provider -await Api.Instance.SetProvider("clientForCache", new CachedProvider()); +// registering a provider to a domain +await Api.Instance.SetProviderAsync("clientForCache", new CachedProvider()); // a client backed by default provider FeatureClient clientDefault = Api.Instance.GetClient(); // a client backed by CachedProvider -FeatureClient clientNamed = Api.Instance.GetClient("clientForCache"); - +FeatureClient scopedClient = Api.Instance.GetClient("clientForCache"); ``` +Domains can be defined on a provider during registration. +For more details, please refer to the [providers](#providers) section. + ### Eventing Events allow you to react to state changes in the provider or underlying flag management system, such as flag definition changes, @@ -205,7 +207,7 @@ EventHandlerDelegate callback = EventHandler; var myClient = Api.Instance.GetClient("my-client"); var provider = new ExampleProvider(); -await Api.Instance.SetProvider(myClient.GetMetadata().Name, provider); +await Api.Instance.SetProviderAsync(myClient.GetMetadata().Name, provider); myClient.AddHandler(ProviderEventTypes.ProviderReady, callback); ``` @@ -216,7 +218,7 @@ The OpenFeature API provides a close function to perform a cleanup of all regist ```csharp // Shut down all providers -await Api.Instance.Shutdown(); +await Api.Instance.ShutdownAsync(); ``` ## Extending @@ -235,27 +237,27 @@ public class MyProvider : FeatureProvider return new Metadata("My Provider"); } - public override Task> ResolveBooleanValue(string flagKey, bool defaultValue, EvaluationContext context = null) + public override Task> ResolveBooleanValueAsync(string flagKey, bool defaultValue, EvaluationContext? context = null, CancellationToken cancellationToken = default) { // resolve a boolean flag value } - public override Task> ResolveDoubleValue(string flagKey, double defaultValue, EvaluationContext context = null) + public override Task> ResolveStringValueAsync(string flagKey, string defaultValue, EvaluationContext? context = null, CancellationToken cancellationToken = default) { - // resolve a double flag value + // resolve a string flag value } - public override Task> ResolveIntegerValue(string flagKey, int defaultValue, EvaluationContext context = null) + public override Task> ResolveIntegerValueAsync(string flagKey, int defaultValue, EvaluationContext context = null) { // resolve an int flag value } - public override Task> ResolveStringValue(string flagKey, string defaultValue, EvaluationContext context = null) + public override Task> ResolveDoubleValueAsync(string flagKey, double defaultValue, EvaluationContext? context = null, CancellationToken cancellationToken = default) { - // resolve a string flag value + // resolve a double flag value } - public override Task> ResolveStructureValue(string flagKey, Value defaultValue, EvaluationContext context = null) + public override Task> ResolveStructureValueAsync(string flagKey, Value defaultValue, EvaluationContext? context = null, CancellationToken cancellationToken = default) { // resolve an object flag value } @@ -272,25 +274,25 @@ To satisfy the interface, all methods (`Before`/`After`/`Finally`/`Error`) need ```csharp public class MyHook : Hook { - public Task Before(HookContext context, + public ValueTask BeforeAsync(HookContext context, IReadOnlyDictionary hints = null) { // code to run before flag evaluation } - public virtual Task After(HookContext context, FlagEvaluationDetails details, + public ValueTask AfterAsync(HookContext context, FlagEvaluationDetails details, IReadOnlyDictionary hints = null) { // code to run after successful flag evaluation } - public virtual Task Error(HookContext context, Exception error, + public ValueTask ErrorAsync(HookContext context, Exception error, IReadOnlyDictionary hints = null) { // code to run if there's an error during before hooks or during flag evaluation } - public virtual Task Finally(HookContext context, IReadOnlyDictionary hints = null) + public ValueTask FinallyAsync(HookContext context, IReadOnlyDictionary hints = null) { // code to run after all other stages, regardless of success/failure } diff --git a/docs/reference/technologies/server/go.mdx b/docs/reference/technologies/server/go.mdx index a1b08c0eb..5d1b108aa 100644 --- a/docs/reference/technologies/server/go.mdx +++ b/docs/reference/technologies/server/go.mdx @@ -9,7 +9,7 @@ This content has been automatically generated from go-sdk. Edits should be made here: https://github.com/open-feature/go-sdk Once a repo has been updated, docs can be generated by running: yarn update:sdk-docs -Last updated at Thu Jun 13 2024 08:07:55 GMT+0000 (Coordinated Universal Time) +Last updated at Mon Aug 26 2024 17:24:11 GMT+0000 (Coordinated Universal Time) -->

diff --git a/docs/reference/technologies/server/java.mdx b/docs/reference/technologies/server/java.mdx index 8fb963053..b2b8f5aae 100644 --- a/docs/reference/technologies/server/java.mdx +++ b/docs/reference/technologies/server/java.mdx @@ -9,7 +9,7 @@ This content has been automatically generated from java-sdk. Edits should be made here: https://github.com/open-feature/java-sdk Once a repo has been updated, docs can be generated by running: yarn update:sdk-docs -Last updated at Thu Jun 13 2024 08:07:55 GMT+0000 (Coordinated Universal Time) +Last updated at Mon Aug 26 2024 17:24:10 GMT+0000 (Coordinated Universal Time) -->

@@ -18,8 +18,8 @@ Last updated at Thu Jun 13 2024 08:07:55 GMT+0000 (Coordinated Universal Time) - - Release + + Release @@ -54,7 +54,7 @@ Note that this library is intended to be used in server-side contexts and has no dev.openfeature sdk - 1.8.0 + 1.9.1 ``` @@ -66,8 +66,8 @@ If you would like snapshot builds, this is the relevant repository information: true - sonartype - Sonartype Repository + sonatype + Sonatype Repository https://s01.oss.sonatype.org/content/repositories/snapshots/ @@ -77,7 +77,7 @@ If you would like snapshot builds, this is the relevant repository information: ```groovy dependencies { - implementation 'dev.openfeature:sdk:1.8.0' + implementation 'dev.openfeature:sdk:1.9.1' } ``` diff --git a/docs/reference/technologies/server/javascript/index.mdx b/docs/reference/technologies/server/javascript/index.mdx index ceb50dfcd..73d19fe3e 100644 --- a/docs/reference/technologies/server/javascript/index.mdx +++ b/docs/reference/technologies/server/javascript/index.mdx @@ -10,7 +10,7 @@ This content has been automatically generated from js-sdk. Edits should be made here: https://github.com/open-feature/js-sdk Once a repo has been updated, docs can be generated by running: yarn update:sdk-docs -Last updated at Thu Jun 13 2024 08:07:55 GMT+0000 (Coordinated Universal Time) +Last updated at Mon Aug 26 2024 17:24:10 GMT+0000 (Coordinated Universal Time) -->

diff --git a/docs/reference/technologies/server/javascript/nestjs.mdx b/docs/reference/technologies/server/javascript/nestjs.mdx index 1b4af3e00..30e056c05 100644 --- a/docs/reference/technologies/server/javascript/nestjs.mdx +++ b/docs/reference/technologies/server/javascript/nestjs.mdx @@ -10,7 +10,7 @@ This content has been automatically generated from js-sdk. Edits should be made here: https://github.com/open-feature/js-sdk Once a repo has been updated, docs can be generated by running: yarn update:sdk-docs -Last updated at Thu Jun 13 2024 08:07:55 GMT+0000 (Coordinated Universal Time) +Last updated at Mon Aug 26 2024 17:24:11 GMT+0000 (Coordinated Universal Time) -->

diff --git a/docs/reference/technologies/server/php.mdx b/docs/reference/technologies/server/php.mdx index cbf44afa4..a4cb4a408 100644 --- a/docs/reference/technologies/server/php.mdx +++ b/docs/reference/technologies/server/php.mdx @@ -9,7 +9,7 @@ This content has been automatically generated from php-sdk. Edits should be made here: https://github.com/open-feature/php-sdk Once a repo has been updated, docs can be generated by running: yarn update:sdk-docs -Last updated at Thu Jun 13 2024 08:07:56 GMT+0000 (Coordinated Universal Time) +Last updated at Mon Aug 26 2024 17:24:12 GMT+0000 (Coordinated Universal Time) -->

@@ -19,8 +19,8 @@ Last updated at Thu Jun 13 2024 08:07:56 GMT+0000 (Coordinated Universal Time) - - Release + + Release diff --git a/docs/reference/technologies/server/python.mdx b/docs/reference/technologies/server/python.mdx index 3f884d9b3..5e17571b9 100644 --- a/docs/reference/technologies/server/python.mdx +++ b/docs/reference/technologies/server/python.mdx @@ -9,7 +9,7 @@ This content has been automatically generated from python-sdk. Edits should be made here: https://github.com/open-feature/python-sdk Once a repo has been updated, docs can be generated by running: yarn update:sdk-docs -Last updated at Thu Jun 13 2024 08:07:56 GMT+0000 (Coordinated Universal Time) +Last updated at Mon Aug 26 2024 17:24:11 GMT+0000 (Coordinated Universal Time) -->

@@ -20,8 +20,8 @@ Last updated at Thu Jun 13 2024 08:07:56 GMT+0000 (Coordinated Universal Time) - - Latest version + + Latest version @@ -54,13 +54,13 @@ Last updated at Thu Jun 13 2024 08:07:56 GMT+0000 (Coordinated Universal Time) #### Pip install ```bash -pip install openfeature-sdk==0.7.0 +pip install openfeature-sdk==0.7.1 ``` #### requirements.txt ```bash -openfeature-sdk==0.7.0 +openfeature-sdk==0.7.1 ``` ```python diff --git a/docs/reference/technologies/server/ruby.mdx b/docs/reference/technologies/server/ruby.mdx index e5930a9fd..a788f85fd 100644 --- a/docs/reference/technologies/server/ruby.mdx +++ b/docs/reference/technologies/server/ruby.mdx @@ -10,7 +10,7 @@ This content has been automatically generated from ruby-sdk. Edits should be made here: https://github.com/open-feature/ruby-sdk Once a repo has been updated, docs can be generated by running: yarn update:sdk-docs -Last updated at Thu Aug 08 2024 08:53:36 GMT-0400 (Eastern Daylight Time) +Last updated at Mon Aug 26 2024 17:24:13 GMT+0000 (Coordinated Universal Time) -->

diff --git a/src/datasets/sdks/sdk-compatibility.json b/src/datasets/sdks/sdk-compatibility.json index d8ca1313f..4e680b0d6 100644 --- a/src/datasets/sdks/sdk-compatibility.json +++ b/src/datasets/sdks/sdk-compatibility.json @@ -4,8 +4,8 @@ "path": "/docs/reference/technologies/server/java", "category": "Server", "release": { - "href": "https://github.com/open-feature/java-sdk/releases/tag/v1.9.0", - "version": "1.9.0", + "href": "https://github.com/open-feature/java-sdk/releases/tag/v1.9.1", + "version": "1.9.1", "stable": true }, "spec": { @@ -108,8 +108,8 @@ "path": "/docs/reference/technologies/server/dotnet", "category": "Server", "release": { - "href": "https://github.com/open-feature/dotnet-sdk/releases/tag/v1.5.0", - "version": "1.5.0", + "href": "https://github.com/open-feature/dotnet-sdk/releases/tag/v2.0.0", + "version": "2.0.0", "stable": true }, "spec": { @@ -135,7 +135,7 @@ }, "Domains": { "status": "✅", - "path": "/docs/reference/technologies/server/dotnet#named-clients" + "path": "/docs/reference/technologies/server/dotnet#domains" }, "Eventing": { "status": "✅", @@ -316,8 +316,8 @@ "path": "/docs/reference/technologies/client/web", "category": "Client", "release": { - "href": "https://github.com/open-feature/js-sdk/releases/tag/web-sdk-v1.2.1", - "version": "1.2.1", + "href": "https://github.com/open-feature/js-sdk/releases/tag/web-sdk-v1.2.2", + "version": "1.2.2", "stable": true }, "spec": {