{"id":22798211,"url":"https://github.com/patxibocos/poetimizely","last_synced_at":"2025-07-13T09:37:30.317Z","repository":{"id":50849419,"uuid":"245565952","full_name":"patxibocos/poetimizely","owner":"patxibocos","description":"Generate Kotlin type safe accessors for Optimizely experiments and features","archived":false,"fork":false,"pushed_at":"2025-07-03T06:14:23.000Z","size":1088,"stargazers_count":19,"open_issues_count":3,"forks_count":1,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-07-03T07:26:31.004Z","etag":null,"topics":["gradle-plugin","kotlin","kotlinpoet","maven-plugin","optimizely","typesafe"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/patxibocos.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2020-03-07T04:08:46.000Z","updated_at":"2025-07-03T06:14:26.000Z","dependencies_parsed_at":"2023-12-07T17:27:13.745Z","dependency_job_id":"3ebb5190-2dd2-4b05-95f3-34c1e55ea255","html_url":"https://github.com/patxibocos/poetimizely","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/patxibocos/poetimizely","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patxibocos%2Fpoetimizely","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patxibocos%2Fpoetimizely/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patxibocos%2Fpoetimizely/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patxibocos%2Fpoetimizely/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/patxibocos","download_url":"https://codeload.github.com/patxibocos/poetimizely/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patxibocos%2Fpoetimizely/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265121387,"owners_count":23714502,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["gradle-plugin","kotlin","kotlinpoet","maven-plugin","optimizely","typesafe"],"created_at":"2024-12-12T06:09:22.177Z","updated_at":"2025-07-13T09:37:30.274Z","avatar_url":"https://github.com/patxibocos.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![codecov](https://codecov.io/gh/patxibocos/poetimizely/branch/main/graph/badge.svg)](https://codecov.io/gh/patxibocos/poetimizely)\n[![CI](https://github.com/patxibocos/poetimizely/workflows/CI/badge.svg)](https://github.com/patxibocos/poetimizely/actions?query=workflow%3ACI)\n[![poetimizely-core](https://img.shields.io/maven-central/v/io.github.patxibocos/poetimizely-core?label=poetimizely-core\u0026color=blue)](https://search.maven.org/artifact/io.github.patxibocos/poetimizely-core)\n[![poetimizely-gradle-plugin](https://img.shields.io/gradle-plugin-portal/v/io.github.patxibocos.poetimizely?label=poetimizely-gradle-plugin\u0026color=red)](https://plugins.gradle.org/plugin/io.github.patxibocos.poetimizely)\n[![poetimizely-maven-plugin](https://img.shields.io/maven-central/v/io.github.patxibocos/poetimizely-maven-plugin?label=poetimizely-maven-plugin\u0026color=blue)](https://search.maven.org/artifact/io.github.patxibocos/poetimizely-maven-plugin)\n\n## What is poetimizely ❓\n\n**poetimizely** is a library to generate type safe accessors for [Optimizely](https://www.optimizely.com/) experiments and features.\nGiven a Project ID and a token it will generate classes for every experiment + variations and features + variables.\n\n## Setup ⚙\n\nℹ️ Before editing the build file, there are three properties required to configure explained below:\n- **optimizelyProjectId** (Long): id of the Optimizely project to grab experiments and features from. \n- **optimizelyToken** (String): Optimizely personal access token. See [Personal token authentication](https://docs.developers.optimizely.com/web/docs/personal-token).\n- **packageName** (String): package where the code will be placed. The expected format is `your.destination.package`.\n\n### Gradle 🐘\n\n#### Kotlin DSL (build.gradle.kts)\n\n```kotlin\nplugins {\n  id(\"io.github.patxibocos.poetimizely\") version \"1.0.5\"\n}\n\npoetimizely {\n    optimizelyProjectId = $OPTIMIZELY_PROJECT_ID\n    optimizelyToken = $PERSONAL_ACCESS_TOKEN\n    packageName = $PACKAGE_NAME\n}\n```\n\n#### Groovy (build.gradle)\n\n```groovy\nplugins {\n  id \"io.github.patxibocos.poetimizely\" version \"1.0.5\"\n}\n\npoetimizely {\n    optimizelyProjectId = $OPTIMIZELY_PROJECT_ID\n    optimizelyToken = $PERSONAL_ACCESS_TOKEN\n    packageName = $PACKAGE_NAME\n}\n\n```\n\n### Maven 🕊️\n\n#### pom.xml\n\n```xml\n\u003cbuild\u003e\n    \u003cplugins\u003e\n        \u003cplugin\u003e\n            \u003cgroupId\u003eio.github.patxibocos\u003c/groupId\u003e\n            \u003cartifactId\u003epoetimizely-maven-plugin\u003c/artifactId\u003e\n            \u003cversion\u003e1.0.5\u003c/version\u003e\n            \u003cconfiguration\u003e\n                \u003coptimizelyProjectId\u003e$OPTIMIZELY_PROJECT_ID\u003c/optimizelyProjectId\u003e\n                \u003coptimizelyToken\u003e$PERSONAL_ACCESS_TOKEN\u003c/optimizelyToken\u003e\n                \u003cpackageName\u003e$PACKAGE_NAME\u003c/packageName\u003e\n            \u003c/configuration\u003e\n        \u003c/plugin\u003e\n    \u003c/plugins\u003e\n\u003c/build\u003e\n```\n\n## Usage 📋\n\nAfter the plugin has been setup, a new Gradle task / Maven goal named **poetimize** will be available. In order to run it successfully, both Optimizely project id and token must be valid.\n\nFor Gradle projects run:\n\n```shell\n./gradlew poetimize\n```\n\nor with Maven:\n\n```shell\n./mvnw poetimizely:poetimize\n```\n\nThis will generate all the code based on the experiments (and its variants) and features defined for the given Optimizely project.\n\n### Experiments 🧪\n\nFor each of the experiments, a new [object](https://kotlinlang.org/docs/reference/object-declarations.html#object-declarations) will be generated. And for the set of variations for each of the experiments an enum class will be also created.\n\nAn extension function for the Optimizely class is also available that brings the **type safety**:\n\n```kotlin\nwhen (optimizely.getVariationForExperiment(Experiments.ExampleExperiment, userId)) {\n    EXAMPLE_VARIATION -\u003e TODO() \n    null -\u003e TODO()\n}\n```\n\n### Features 💡\n\nKotlin objects will also be generated for features. For the set of variables that each of the features may have, a property is added to the object.\n\nTo check whether a feature is enabled an extension function is provided:\n\n```kotlin\nif (optimizely.isFeatureEnabled(Features.ExampleFeature, userId)) {\n    TODO()\n}\n```\n\nand also for getting feature variables values:\n\n```kotlin\nval booleanVariable: Boolean? = optimizely.getFeatureVariable(Features.ExampleFeature.exampleBooleanVariable)\nval stringVariable: String? = optimizely.getFeatureVariable(Features.ExampleFeature.exampleStringVariable)\nval doubleVariable: Double? = optimizely.getFeatureVariable(Features.ExampleFeature.exampleDoubleVariable)\nval intVariable: Int? = optimizely.getFeatureVariable(Features.ExampleFeature.exampleIntVariable)\n```\n\n## A look at the generated code 👀\n\nAfter running the task there will be two new classes generated in the given **packageName**:\n\n#### `Experiments.kt`\n\n```kotlin\ninterface BaseVariation {\n    val key: String\n}\n\nfun getAllExperiments(): List\u003cExperiments\u003cout BaseVariation\u003e\u003e =\n    listOf(Experiments.ExampleExperiment)\n\nfun \u003cV : BaseVariation\u003e Optimizely.getVariationForExperiment(\n    experiment: Experiments\u003cV\u003e,\n    userId: String,\n    attributes: Map\u003cString, Any\u003e = emptyMap()\n): V? {\n    val variation = this.activate(experiment.key, userId, attributes)\n    return experiment.variations.find { it.key == variation?.key }\n}\n\nenum class ExampleExperimentVariations : BaseVariation {\n    EXAMPLE_VARIATION {\n        override val key: String = \"example-variation\"\n    }\n}\n\nsealed class Experiments\u003cV : BaseVariation\u003e(\n    val key: String,\n    val variations: Array\u003cV\u003e\n) {\n    object ExampleExperiment : Experiments\u003cExampleExperimentVariations\u003e (\n        \"example-experiment\",\n        ExampleExperimentVariations.values()\n    )\n}\n```\n\n#### `Features.kt`\n\n```kotlin\nclass FeatureVariable\u003cT\u003e(\n    val featureKey: String,\n    val variableKey: String\n)\n\nsealed class Features(\n    val key: String\n) {\n    object ExampleFeature(\"example-feature\") {\n        val exampleVariable: FeatureVariable\u003cBoolean\u003e = FeatureVariable(\"example-feature\", \"example-variable\")\n    } \n}\n\npublic fun getAllFeatures(): List\u003cFeatures\u003e = listOf(Features.ExampleFeature)\n\nfun Optimizely.isFeatureEnabled(\n    feature: Features,\n    userId: String,\n    attributes: Map\u003cString, Any\u003e = emptyMap()\n): Boolean = this.isFeatureEnabled(feature.key, userId, attributes)\n\nfun Optimizely.getFeatureVariable(\n    variable: FeatureVariable\u003cBoolean\u003e,\n    userId: String,\n    attributes: Map\u003cString, Any\u003e = emptyMap()\n): Boolean? =\n    this.getFeatureVariableBoolean(variable.featureKey, variable.variableKey, userId, attributes)\n\nfun Optimizely.getFeatureVariable(\n    variable: FeatureVariable\u003cString\u003e,\n    userId: String,\n    attributes: Map\u003cString, Any\u003e = emptyMap()\n): String? =\n    this.getFeatureVariableString(variable.featureKey, variable.variableKey, userId, attributes)\n\nfun Optimizely.getFeatureVariable(\n    variable: FeatureVariable\u003cDouble\u003e,\n    userId: String,\n    attributes: Map\u003cString, Any\u003e = emptyMap()\n): Double? =\n    this.getFeatureVariableDouble(variable.featureKey, variable.variableKey, userId, attributes)\n\nfun Optimizely.getFeatureVariable(\n    variable: FeatureVariable\u003cInt\u003e,\n    userId: String,\n    attributes: Map\u003cString, Any\u003e = emptyMap()\n): Int? =\n    this.getFeatureVariableInteger(variable.featureKey, variable.variableKey, userId, attributes)\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpatxibocos%2Fpoetimizely","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpatxibocos%2Fpoetimizely","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpatxibocos%2Fpoetimizely/lists"}