Skip to content

Commit

Permalink
Added: Explicit API - Strict mode in Kotlin
Browse files Browse the repository at this point in the history
Helps in preventing internal API being published as public API.
  • Loading branch information
hsinha610 committed Apr 16, 2024
1 parent 1c2139d commit e530f2f
Show file tree
Hide file tree
Showing 25 changed files with 199 additions and 194 deletions.
5 changes: 5 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import org.gradle.api.tasks.testing.logging.TestExceptionFormat
import org.gradle.api.tasks.testing.logging.TestLogEvent
import org.jetbrains.kotlin.gradle.dsl.ExplicitApiMode.Strict

plugins {
// Apply the org.jetbrains.kotlin.jvm Plugin to add support for Kotlin.
Expand Down Expand Up @@ -44,6 +45,10 @@ publishing {
}
}

kotlin {
explicitApi = Strict
}

dependencies {
// Use the Kotlin JUnit 5 integration.
testImplementation("org.jetbrains.kotlin:kotlin-test-junit5")
Expand Down
2 changes: 1 addition & 1 deletion src/main/kotlin/com/featurevisor/sdk/Bucket.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package com.featurevisor.sdk
import com.goncalossilva.murmurhash.MurmurHash3
import kotlin.math.floor

object Bucket {
internal object Bucket {

private const val HASH_SEED = 1u
private const val MAX_HASH_VALUE = 4294967296 // 2^32
Expand Down
2 changes: 1 addition & 1 deletion src/main/kotlin/com/featurevisor/sdk/Conditions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import com.featurevisor.types.Operator.SEMVER_NOT_EQUALS
import com.featurevisor.types.Operator.STARTS_WITH
import net.swiftzer.semver.SemVer

object Conditions {
internal object Conditions {

fun conditionIsMatched(condition: Plain, context: Context): Boolean {
val (attributeKey, operator, conditionValue) = condition
Expand Down
2 changes: 1 addition & 1 deletion src/main/kotlin/com/featurevisor/sdk/DatafileReader.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import com.featurevisor.types.FeatureKey
import com.featurevisor.types.Segment
import com.featurevisor.types.SegmentKey

class DatafileReader constructor(
internal class DatafileReader constructor(
datafileJson: DatafileContent,
) {

Expand Down
2 changes: 1 addition & 1 deletion src/main/kotlin/com/featurevisor/sdk/Emitter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package com.featurevisor.sdk

import com.featurevisor.types.EventName

class Emitter {
internal class Emitter {

private val listeners = mutableMapOf<EventName, (Array<out Any>) -> Unit>()

Expand Down
12 changes: 6 additions & 6 deletions src/main/kotlin/com/featurevisor/sdk/FeaturevisorError.kt
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
package com.featurevisor.sdk

sealed class FeaturevisorError(message: String) : Throwable(message = message) {
public sealed class FeaturevisorError(message: String) : Throwable(message = message) {

/// Thrown when attempting to init Featurevisor instance without passing datafile and datafileUrl.
/// At least one of them is required to init the SDK correctly
object MissingDatafileOptions : FeaturevisorError("Missing data file options")
public object MissingDatafileOptions : FeaturevisorError("Missing data file options")

class FetchingDataFileFailed(val result: String) : FeaturevisorError("Fetching data file failed")
public class FetchingDataFileFailed(public val result: String) : FeaturevisorError("Fetching data file failed")

/// Thrown when receiving unparseable Datafile JSON responses.
/// - Parameters:
/// - data: The data being parsed.
/// - errorMessage: The message from the error which occured during parsing.
class UnparsableJson(val data: String?, errorMessage: String) : FeaturevisorError(errorMessage)
public class UnparsableJson(public val data: String?, errorMessage: String) : FeaturevisorError(errorMessage)

/// Thrown when attempting to construct an invalid URL.
/// - Parameter string: The invalid URL string.
class InvalidUrl(val url: String?) : FeaturevisorError("Invalid URL")
public class InvalidUrl(public val url: String?) : FeaturevisorError("Invalid URL")

object MissingDatafileUrlWhileRefreshing : FeaturevisorError("Missing datafile url need to refresh")
public object MissingDatafileUrlWhileRefreshing : FeaturevisorError("Missing datafile url need to refresh")
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import com.featurevisor.types.EventName.ACTIVATION
import com.featurevisor.types.FeatureKey
import com.featurevisor.types.VariationValue

fun FeaturevisorInstance.activate(featureKey: FeatureKey, context: Context = emptyMap()): VariationValue? {
public fun FeaturevisorInstance.activate(featureKey: FeatureKey, context: Context = emptyMap()): VariationValue? {
val evaluation = evaluateVariation(featureKey, context)
val variationValue = evaluation.variation?.value ?: evaluation.variationValue ?: return null
val finalContext = interceptContext?.invoke(context) ?: context
Expand Down
14 changes: 7 additions & 7 deletions src/main/kotlin/com/featurevisor/sdk/Instance+Evaluation.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import kotlinx.serialization.json.Json
import kotlinx.serialization.json.decodeFromJsonElement
import kotlinx.serialization.json.encodeToJsonElement

enum class EvaluationReason(val value: String) {
public enum class EvaluationReason(public val value: String) {
NOT_FOUND("not_found"),
NO_VARIATIONS("no_variations"),
DISABLED("disabled"),
Expand All @@ -41,7 +41,7 @@ enum class EvaluationReason(val value: String) {
}

@Serializable
data class Evaluation(
public data class Evaluation(
val featureKey: FeatureKey,
val reason: EvaluationReason,
val bucketValue: BucketValue? = null,
Expand All @@ -56,7 +56,7 @@ data class Evaluation(
val variableValue: VariableValue? = null,
val variableSchema: VariableSchema? = null,
) {
fun toDictionary(): Map<String, Any> {
public fun toDictionary(): Map<String, Any> {
val data = try {
val json = Json.encodeToJsonElement(this)
Json.decodeFromJsonElement<Map<String, Any>>(json)
Expand All @@ -68,13 +68,13 @@ data class Evaluation(
}
}

fun FeaturevisorInstance.isEnabled(featureKey: FeatureKey, context: Context = emptyMap()): Boolean {
public fun FeaturevisorInstance.isEnabled(featureKey: FeatureKey, context: Context = emptyMap()): Boolean {
val evaluation = evaluateFlag(featureKey, context)
return evaluation.enabled == true
}

@Suppress("UNREACHABLE_CODE")
fun FeaturevisorInstance.evaluateVariation(featureKey: FeatureKey, context: Context = emptyMap()): Evaluation {
public fun FeaturevisorInstance.evaluateVariation(featureKey: FeatureKey, context: Context = emptyMap()): Evaluation {
var evaluation: Evaluation
try {
val flag = evaluateFlag(featureKey, context)
Expand Down Expand Up @@ -231,7 +231,7 @@ fun FeaturevisorInstance.evaluateVariation(featureKey: FeatureKey, context: Cont


@Suppress("UNREACHABLE_CODE")
fun FeaturevisorInstance.evaluateFlag(featureKey: FeatureKey, context: Context = emptyMap()): Evaluation {
public fun FeaturevisorInstance.evaluateFlag(featureKey: FeatureKey, context: Context = emptyMap()): Evaluation {

var evaluation: Evaluation

Expand Down Expand Up @@ -443,7 +443,7 @@ fun FeaturevisorInstance.evaluateFlag(featureKey: FeatureKey, context: Context =
}

@Suppress("UNREACHABLE_CODE")
fun FeaturevisorInstance.evaluateVariable(
public fun FeaturevisorInstance.evaluateVariable(
featureKey: FeatureKey,
variableKey: VariableKey,
context: Context = emptyMap(),
Expand Down
6 changes: 3 additions & 3 deletions src/main/kotlin/com/featurevisor/sdk/Instance+Feature.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import com.featurevisor.types.Feature
import com.featurevisor.types.Force
import com.featurevisor.types.Traffic

fun FeaturevisorInstance.getFeatureByKey(featureKey: String): Feature? {
public fun FeaturevisorInstance.getFeatureByKey(featureKey: String): Feature? {
return datafileReader.getFeature(featureKey)
}

fun FeaturevisorInstance.getFeature(featureKey: String): Feature?{
public fun FeaturevisorInstance.getFeature(featureKey: String): Feature?{
return datafileReader.getFeature(featureKey)
}

Expand Down Expand Up @@ -58,7 +58,7 @@ internal fun FeaturevisorInstance.getMatchedAllocation(
}
}

data class MatchedTrafficAndAllocation(
internal data class MatchedTrafficAndAllocation(
val matchedTraffic: Traffic?,
val matchedAllocation: Allocation?,
)
Expand Down
2 changes: 1 addition & 1 deletion src/main/kotlin/com/featurevisor/sdk/Instance+Fetch.kt
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ private fun fetchDatafileContentFromUrl(
}
}

const val BODY_BYTE_COUNT = 1000000L
internal const val BODY_BYTE_COUNT = 1000000L
private inline fun fetch(
request: Request,
crossinline completion: (Result<DatafileContent>) -> Unit,
Expand Down
4 changes: 2 additions & 2 deletions src/main/kotlin/com/featurevisor/sdk/Instance+Refresh.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch

fun FeaturevisorInstance.startRefreshing() = when {
public fun FeaturevisorInstance.startRefreshing(): Unit? = when {
datafileUrl == null -> {
logger?.error("cannot start refreshing since `datafileUrl` is not provided")
throw MissingDatafileUrlWhileRefreshing
Expand All @@ -26,7 +26,7 @@ fun FeaturevisorInstance.startRefreshing() = when {
}
}

fun FeaturevisorInstance.stopRefreshing() {
public fun FeaturevisorInstance.stopRefreshing() {
refreshJob?.cancel()
refreshJob = null
logger?.warn("refreshing has stopped")
Expand Down
2 changes: 1 addition & 1 deletion src/main/kotlin/com/featurevisor/sdk/Instance+Status.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.featurevisor.sdk

data class Statuses(var ready: Boolean, var refreshInProgress: Boolean)
internal data class Statuses(var ready: Boolean, var refreshInProgress: Boolean)

internal fun FeaturevisorInstance.isReady(): Boolean {
return statuses.ready
Expand Down
16 changes: 8 additions & 8 deletions src/main/kotlin/com/featurevisor/sdk/Instance+Variable.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import kotlinx.serialization.json.Json
import kotlinx.serialization.json.decodeFromJsonElement
import kotlinx.serialization.json.encodeToJsonElement

fun FeaturevisorInstance.getVariable(
public fun FeaturevisorInstance.getVariable(
featureKey: FeatureKey,
variableKey: VariableKey,
context: Context = emptyMap(),
Expand All @@ -30,47 +30,47 @@ fun FeaturevisorInstance.getVariable(
return evaluation.variableValue
}

fun FeaturevisorInstance.getVariableBoolean(
public fun FeaturevisorInstance.getVariableBoolean(
featureKey: FeatureKey,
variableKey: VariableKey,
context: Context,
): Boolean? {
return (getVariable(featureKey, variableKey, context) as? BooleanValue)?.value
}

fun FeaturevisorInstance.getVariableString(
public fun FeaturevisorInstance.getVariableString(
featureKey: FeatureKey,
variableKey: VariableKey,
context: Context,
): String? {
return (getVariable(featureKey, variableKey, context) as? StringValue)?.value
}

fun FeaturevisorInstance.getVariableInteger(
public fun FeaturevisorInstance.getVariableInteger(
featureKey: FeatureKey,
variableKey: VariableKey,
context: Context,
): Int? {
return (getVariable(featureKey, variableKey, context) as? IntValue)?.value
}

fun FeaturevisorInstance.getVariableDouble(
public fun FeaturevisorInstance.getVariableDouble(
featureKey: FeatureKey,
variableKey: VariableKey,
context: Context,
): Double? {
return (getVariable(featureKey, variableKey, context) as? DoubleValue)?.value
}

fun FeaturevisorInstance.getVariableArray(
public fun FeaturevisorInstance.getVariableArray(
featureKey: FeatureKey,
variableKey: VariableKey,
context: Context,
): List<String>? {
return (getVariable(featureKey, variableKey, context) as? ArrayValue)?.values
}

inline fun <reified T : Any> FeaturevisorInstance.getVariableObject(
public inline fun <reified T : Any> FeaturevisorInstance.getVariableObject(
featureKey: FeatureKey,
variableKey: VariableKey,
context: Context,
Expand All @@ -84,7 +84,7 @@ inline fun <reified T : Any> FeaturevisorInstance.getVariableObject(
}
}

inline fun <reified T : Any> FeaturevisorInstance.getVariableJSON(
public inline fun <reified T : Any> FeaturevisorInstance.getVariableJSON(
featureKey: FeatureKey,
variableKey: VariableKey,
context: Context,
Expand Down
28 changes: 14 additions & 14 deletions src/main/kotlin/com/featurevisor/sdk/Instance.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,27 @@ import kotlinx.coroutines.Job
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json

typealias ConfigureBucketKey = (Feature, Context, BucketKey) -> BucketKey
typealias ConfigureBucketValue = (Feature, Context, BucketValue) -> BucketValue
typealias InterceptContext = (Context) -> Context
typealias DatafileFetchHandler = (datafileUrl: String) -> Result<DatafileContent>
internal typealias ConfigureBucketKey = (Feature, Context, BucketKey) -> BucketKey
internal typealias ConfigureBucketValue = (Feature, Context, BucketValue) -> BucketValue
internal typealias InterceptContext = (Context) -> Context
internal typealias DatafileFetchHandler = (datafileUrl: String) -> Result<DatafileContent>

var emptyDatafile = DatafileContent(
internal var emptyDatafile = DatafileContent(
schemaVersion = "1",
revision = "unknown",
attributes = emptyList(),
segments = emptyList(),
features = emptyList(),
)

class FeaturevisorInstance private constructor(options: InstanceOptions) {
public class FeaturevisorInstance private constructor(options: InstanceOptions) {

companion object {
fun createInstance(options: InstanceOptions): FeaturevisorInstance {
public companion object {
public fun createInstance(options: InstanceOptions): FeaturevisorInstance {
return FeaturevisorInstance(options)
}

var companionLogger: Logger? = null
public var companionLogger: Logger? = null
}

private val on: (EventName, Listener) -> Unit
Expand Down Expand Up @@ -118,11 +118,11 @@ class FeaturevisorInstance private constructor(options: InstanceOptions) {
}
}

fun setLogLevels(levels: List<Logger.LogLevel>) {
public fun setLogLevels(levels: List<Logger.LogLevel>) {
this.logger?.setLevels(levels)
}

fun setDatafile(datafileJSON: String) {
public fun setDatafile(datafileJSON: String) {
val data = datafileJSON.toByteArray(Charsets.UTF_8)
try {
val datafileContent = Json.decodeFromString<DatafileContent>(String(data))
Expand All @@ -132,15 +132,15 @@ class FeaturevisorInstance private constructor(options: InstanceOptions) {
}
}

fun setDatafile(datafileContent: DatafileContent) {
public fun setDatafile(datafileContent: DatafileContent) {
datafileReader = DatafileReader(datafileJson = datafileContent)
}

fun setStickyFeatures(stickyFeatures: StickyFeatures?) {
public fun setStickyFeatures(stickyFeatures: StickyFeatures?) {
this.stickyFeatures = stickyFeatures
}

fun getRevision(): String {
public fun getRevision(): String {
return datafileReader.getRevision()
}
}
6 changes: 3 additions & 3 deletions src/main/kotlin/com/featurevisor/sdk/InstanceOptions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import com.featurevisor.types.DatafileContent
import com.featurevisor.types.InitialFeatures
import com.featurevisor.types.StickyFeatures

typealias Listener = (Array<out Any>) -> Unit
public typealias Listener = (Array<out Any>) -> Unit

data class InstanceOptions(
public data class InstanceOptions(
val bucketKeySeparator: String = defaultBucketKeySeparator,
val configureBucketKey: ConfigureBucketKey? = null,
val configureBucketValue: ConfigureBucketValue? = null,
Expand All @@ -24,7 +24,7 @@ data class InstanceOptions(
val refreshInterval: Long? = null, // seconds
val stickyFeatures: StickyFeatures? = null,
) {
companion object {
internal companion object {
private const val defaultBucketKeySeparator = "."
}
}
Loading

0 comments on commit e530f2f

Please sign in to comment.