Repository navigation
feat(vue): add @tryabby/vue integration #193
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
rodriguezmarco021-sys
wants to merge
1
commit into
tryabby:main
Choose a base branch
from
rodriguezmarco021-sys:vue-integration
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| --- | ||
| "@tryabby/vue": minor | ||
| --- | ||
|
|
||
| Add the `@tryabby/vue` integration with `useAbby`, `useFeatureFlag` and | ||
| `useRemoteConfig` composables, an `AbbyProvider` component and an installable | ||
| Vue plugin. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,187 @@ | ||
| import { Tab, Tabs, Callout } from "nextra-theme-docs"; | ||
|
|
||
| # Vue | ||
|
|
||
| Our Vue integration works with Vue 3 (SPAs as well as server side rendered apps) | ||
| and with Nuxt. | ||
|
|
||
| ## Installation | ||
|
|
||
| To get started make sure to install the package using your favorite package manager. | ||
|
|
||
| <Tabs items={["npm", "yarn", "pnpm"]}> | ||
| <Tab> | ||
| ```bash | ||
| npm i @tryabby/vue | ||
| ``` | ||
| </Tab> | ||
|
|
||
| <Tab> | ||
| ```bash | ||
| yarn add @tryabby/vue | ||
| ``` | ||
| </Tab> | ||
| <Tab> | ||
| ```bash | ||
| pnpm i @tryabby/vue | ||
| ``` | ||
| </Tab> | ||
| </Tabs> | ||
|
|
||
| ## Usage | ||
|
|
||
| ### Create your config | ||
|
|
||
| To use Abby you need to create your config first. You can do this by creating a | ||
| file called `abby.config.ts` in your `root` folder. This file will be used to | ||
| configure your project. | ||
|
|
||
| ```ts | ||
| // abby.config.ts | ||
| import { defineConfig } from "@tryabby/vue"; | ||
|
|
||
| export default defineConfig({ | ||
| projectId: "<YOUR_PROJECT_ID>", | ||
| currentEnvironment: import.meta.env.MODE, | ||
| environments: ["production", "development"], | ||
| tests: { | ||
| test: { variants: ["A", "B"] }, | ||
| footer: { variants: ["dark", "orange", "green"] }, | ||
| // ... your tests | ||
| }, | ||
| flags: ["darkMode", "newFeature"], | ||
| remoteConfig: { | ||
| customButtonText: "String", | ||
| }, | ||
| }); | ||
| ``` | ||
|
|
||
| ### Create your instance | ||
|
|
||
| To use Abby in your code you will need to create your typed composables first. | ||
| You can do this by using the `createAbby` function. Please copy the id of your | ||
| project from the dashboard to get started. | ||
|
|
||
| ```ts | ||
| import { createAbby } from "@tryabby/vue"; | ||
| import abbyConfig from "../abby.config"; | ||
|
|
||
| const { AbbyProvider, useAbby } = createAbby(abbyConfig); | ||
| ``` | ||
|
|
||
| <Callout type="info"> | ||
| Call `createAbby` once in its own module and import the returned composables | ||
| where you need them - that keeps the types of your tests, flags and remote | ||
| config available across your whole app. | ||
| </Callout> | ||
|
|
||
| ### Wrap your Application | ||
|
|
||
| Wrap your application in the `AbbyProvider`. The provider loads your project | ||
| data and provides it to all components below it. | ||
|
|
||
| ```html | ||
| <script setup lang="ts"> | ||
| import { AbbyProvider } from "./abby"; | ||
| </script> | ||
|
|
||
| <template> | ||
| <AbbyProvider> | ||
| <RouterView /> | ||
| </AbbyProvider> | ||
| </template> | ||
| ``` | ||
|
|
||
| If you prefer to use a plugin you can also install Abby on your app instance. | ||
| The composables need to be created outside of your components for this. | ||
|
|
||
| ```ts | ||
| // main.ts | ||
| import { createApp } from "vue"; | ||
| import { AbbyPlugin } from "./abby"; | ||
| import App from "./App.vue"; | ||
|
|
||
| createApp(App).use(AbbyPlugin).mount("#app"); | ||
| ``` | ||
|
|
||
| ### Use the composables | ||
|
|
||
| The composables can be used inside the `setup` function of your components. They | ||
| all return `ComputedRef`s, so they stay in sync when new project data arrives. | ||
|
|
||
| #### useAbby | ||
|
|
||
| `useAbby` takes the name of your test and returns the currently selected variant | ||
| as well as the `onAct` function, which you can call to track a conversion. | ||
|
|
||
| ```html | ||
| <script setup lang="ts"> | ||
| import { useAbby } from "./abby"; | ||
|
|
||
| const { variant, onAct } = useAbby("test"); | ||
| </script> | ||
|
|
||
| <template> | ||
| <div> | ||
| <p v-if="variant === 'A'">Variant A</p> | ||
| <p v-else>Variant B</p> | ||
|
|
||
| <button type="button" @click="onAct">Buy now</button> | ||
| </div> | ||
| </template> | ||
| ``` | ||
|
|
||
| #### useFeatureFlag | ||
|
|
||
| `useFeatureFlag` takes the name of your feature flag and returns its value. | ||
|
|
||
| ```html | ||
| <script setup lang="ts"> | ||
| import { useFeatureFlag } from "./abby"; | ||
|
|
||
| const darkModeEnabled = useFeatureFlag("darkMode"); | ||
| </script> | ||
|
|
||
| <template> | ||
| <div :class="{ dark: darkModeEnabled }">Hello World</div> | ||
| </template> | ||
| ``` | ||
|
|
||
| #### useRemoteConfig | ||
|
|
||
| `useRemoteConfig` takes the name of your remote config and returns its value. | ||
|
|
||
| ```html | ||
| <script setup lang="ts"> | ||
| import { useRemoteConfig } from "./abby"; | ||
|
|
||
| const buttonText = useRemoteConfig("customButtonText"); | ||
| </script> | ||
|
|
||
| <template> | ||
| <button type="button">{{ buttonText }}</button> | ||
| </template> | ||
| ``` | ||
|
|
||
| ### Nuxt | ||
|
|
||
| For Nuxt you can put your `createAbby` instance into a plugin and pass the | ||
| project data which is fetched during server side rendering as `initialData`. | ||
| This way the first render already contains your variants and flags. | ||
|
|
||
| ```ts | ||
| // plugins/abby.ts | ||
| import { createAbby } from "./abby"; | ||
|
|
||
| const { AbbyPlugin } = createAbby(abbyConfig); | ||
|
|
||
| export default defineNuxtPlugin((nuxtApp) => { | ||
| nuxtApp.vueApp.use(AbbyPlugin); | ||
| }); | ||
| ``` | ||
|
|
||
| <Callout type="info"> | ||
| `AbbyProvider` accepts an `initialData` prop (an `AbbyDataResponse` from | ||
| `@tryabby/core`). If you pass it, the provider will not fetch your project data | ||
| on the client, which avoids a hydration mismatch. | ||
| </Callout> | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,89 @@ | ||
| # API Reference (Vue) | ||
|
|
||
| ## createAbby | ||
|
|
||
| ### Parameters | ||
|
|
||
| The `createAbby` function takes an object as a parameter. The object can contain the following properties: | ||
|
|
||
| | Name | Type | Required | Description | | ||
| | ------------------ | -------- | :------: | ------------------------------------------------------------------------------------------------------------------------------------------------- | | ||
| | projectId | `string` | YES | The ID of your project in Abby | | ||
| | apiUrl | `string` | | The URL of the Abby API. Defaults to the hosted version | | ||
| | currentEnvironment | `string` | YES | The current environment of your application | | ||
| | tests | `object` | | An object containing your defined A/B Tests | | ||
| | flags | `array` | | An array containing your defined Feature Flags | | ||
| | remoteConfig | `object` | | An object containing the name of your remote config and their type | | ||
| | settings | `object` | | An object with additional settings for Abby | | ||
| | user | `object` | | Optional configuration for user properties that can be used for targeting feature flags. This enables conditional rules based on user attributes. | | ||
|
|
||
| ### Return value | ||
|
|
||
| | Name | Type | Description | | ||
| | -------------------------- | --------------------------------------------------- | --------------------------------------------------------------------------------------- | | ||
| | `AbbyProvider` | `Component` | Loads the project data and provides it to all child components | | ||
| | `AbbyPlugin` | `Plugin` | Vue plugin, install it with `app.use(AbbyPlugin, initialData?)` | | ||
| | `useAbby` | `(name, lookupObject?) => { variant, onAct }` | Returns the current variant of a test and a function to track an act | | ||
| | `useFeatureFlag` | `(name) => ComputedRef<boolean>` | Returns the value of a feature flag | | ||
| | `useFeatureFlags` | `() => ComputedRef<Array<{ name, value }>>` | Returns all feature flags with their current value | | ||
| | `useRemoteConfig` | `(name) => ComputedRef<value>` | Returns the value of a remote config | | ||
| | `useRemoteConfigVariables` | `() => ComputedRef<Array<{ name, value }>>` | Returns all remote config variables with their current value | | ||
| | `getFeatureFlagValue` | `(name) => boolean` | Non reactive helper to read a feature flag | | ||
| | `getRemoteConfig` | `(name) => value` | Non reactive helper to read a remote config | | ||
| | `getABTestValue` | `(name, lookupObject?) => value` | Non reactive helper to read the variant of a test | | ||
| | `getVariants` | `(name) => string[]` | Returns all variants of a test | | ||
| | `getABResetFunction` | `() => void` | Returns a function which resets the persisted variant of a test | | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win Correct the
🤖 Prompt for AI Agents |
||
| | `updateUserProperties` | `(userProperties) => void` | Updates the user properties which are sent to Abby | | ||
| | `__abby__` | `Abby` | The underlying `Abby` instance of `@tryabby/core` | | ||
|
|
||
| ## AbbyProvider | ||
|
|
||
| ### Props | ||
|
|
||
| | Name | Type | Required | Description | | ||
| | ------------- | ------------------ | :------: | ---------------------------------------------------------------------------------------------------------- | | ||
| | `initialData` | `AbbyDataResponse` | | Project data which is used instead of fetching it from the Abby API (for example during server rendering) | | ||
|
|
||
| ## useAbby | ||
|
|
||
| ### Parameters | ||
|
|
||
| | Name | Type | Required | Description | | ||
| | -------------- | -------- | :------: | -------------------------------------------------------------------------------------- | | ||
| | `name` | `string` | YES | The name of your A/B test | | ||
| | `lookupObject` | `object` | | A map from variant to the value you want to get back from `variant`, e.g. a component | | ||
|
|
||
| ### Return value | ||
|
|
||
| | Name | Type | Description | | ||
| | --------- | ------------------------------------- | ---------------------------------------------------------- | | ||
| | `variant` | `ComputedRef<Variant \| LookupValue>` | The currently selected variant (or its mapped value) | | ||
| | `onAct` | `() => void` | Call this function to track an act for the current variant | | ||
|
|
||
| ## useFeatureFlag | ||
|
|
||
| ### Parameters | ||
|
|
||
| | Name | Type | Required | Description | | ||
| | ------ | -------- | :------: | ------------------------------- | | ||
| | `name` | `string` | YES | The name of your feature flag | | ||
|
|
||
| ### Return value | ||
|
|
||
| | Name | Type | Description | | ||
| | ------- | ----------------------- | ----------------------------- | | ||
| | `value` | `ComputedRef<boolean>` | The value of the feature flag | | ||
|
|
||
| ## useRemoteConfig | ||
|
|
||
| ### Parameters | ||
|
|
||
| | Name | Type | Required | Description | | ||
| | ------ | -------- | :------: | ------------------------------ | | ||
| | `name` | `string` | YES | The name of your remote config | | ||
|
|
||
| ### Return value | ||
|
|
||
| | Name | Type | Description | | ||
| | ------- | --------------------------- | ------------------------------- | | ||
| | `value` | `ComputedRef<ConfigValue>` | The value of the remote config | | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| node_modules | ||
| dist | ||
| coverage |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🔎 Supported by static analysis
🏁 Script executed:
Repository: tryabby/abby
Length of output: 6487
🏁 Script executed:
Repository: tryabby/abby
Length of output: 28436
🏁 Script executed:
Repository: tryabby/abby
Length of output: 10581
Correct the Nuxt setup and pass the SSR data.
plugins/abby.tsis a separate module. Here,./abbyresolves to the plugin file itself, andabbyConfigis not in scope. Define the shared instance in a separate local module, exportAbbyPlugin, and import that export from the plugin.Also pass the server-fetched value as the second argument to
use. WithoutinitialData,AbbyPluginfetches project data in the browser, so the example does not implement the preceding SSR description. Show howinitialDatais obtained before using it, or remove the SSR claim from this example.🤖 Prompt for AI Agents