Shipeasy
ReferenceKotlin

Snippets

Minimal copy-paste blocks for flags, configs, kill switches, experiments and i18n.

Minimal copy-paste blocks, grouped by the registry taxonomy. These are the same leaves the docs get op returns.

release

release / flags

Read a feature gate with a bound Client. Assumes configure() ran at startup — see Installation.

import ai.shipeasy.Client

// construct once per callsite (cheap; binds the user, no own connection/poll)
val flags = Client(currentUser)

// getFlag(name, default = false): default is returned ONLY when the gate can't
// be evaluated (SDK not ready / flag unknown) — never for a real `false`.
if (flags.getFlag("{{FLAG_KEY}}", default = false)) {
    // gate is on for this user
}

release / configs

Read a dynamic config value, with a default when the key is absent. Assumes configure() ran at startup — see Installation.

import ai.shipeasy.Client

// construct once per callsite (cheap; binds the user)
val flags = Client(currentUser)

// getConfig(name, default = null): default is returned when the key is absent.
val value = flags.getConfig("{{CONFIG_KEY}}", default = "Pay now")

release / killswitches

Check a kill switch — true means the feature is killed. Assumes configure() ran at startup — see Installation.

import ai.shipeasy.Client

// construct once per callsite (cheap; binds the user)
val flags = Client(currentUser)

// getKillswitch(name, switchKey = null): without switchKey → true when the whole
// kill switch is killed; with switchKey → true when that named per-key override
// is on (an unconfigured key falls back to the top-level value).
if (flags.getKillswitch("{{KILLSWITCH_KEY}}", switchKey = null)) {
    return serviceUnavailable()   // killed — short-circuit
}

release / experiments

Assign a variant and track the conversion event — both on the same bound Client. Assumes configure() ran at startup — see Installation.

import ai.shipeasy.Client

// construct once per callsite (cheap; binds the user)
val flags = Client(currentUser)

// getExperiment(name, defaultParams): defaultParams is returned as `params` when
// the user isn't in the experiment (or the experiment has no params).
val r = flags.getExperiment("{{EXPERIMENT_KEY}}", mapOf("color" to "blue"))
if (r.inExperiment) {
    @Suppress("UNCHECKED_CAST")
    val color = (r.params as? Map<String, Any?>)?.get("color")
    // …present the treatment…
}

// on conversion — same bound Client, no user arg (unit comes from the bound bag)
// track(event, props = emptyMap()): event = the metric; props = optional event
// properties (private attributes are stripped).
flags.track("{{SUCCESS_EVENT}}", mapOf("amount" to 49))

metrics

metrics / track

Track a metric/conversion event from the bound Client. Metrics in the dashboard are computed from these events. Assumes configure() ran at startup — see Installation.

Track an event

import ai.shipeasy.Client

// construct once per callsite (cheap; binds the user)
val flags = Client(currentUser)

// track(event, props = emptyMap())
//   event — the event your metric is built on (required)
//   props — optional payload; numeric/string fields you can sum/filter on in a
//           metric (private attributes are stripped before egress)
flags.track("{{EVENT_NAME}}", mapOf("amount" to 49, "currency" to "usd"))

Fire-and-forget (never blocks your response) and a no-op under configureForTesting / configureForOffline. The unit is the bound user (user_id, else anonymous_id); with no unit the call is a no-op.

Track without properties

import ai.shipeasy.Client

// construct once per callsite (cheap; binds the user)
val flags = Client(currentUser)

flags.track("{{EVENT_NAME}}")   // props are optional (default emptyMap())

i18n

i18n / setup

Server-side: render the i18n loader tag into your document <head> with the public client key and the profile. (The Kotlin SDK has no server t() — rendering happens in the browser via the client SDK.) Assumes configure() ran at startup — see Installation.

import ai.shipeasy.i18nScriptTag

// i18nScriptTag(clientKey, profile = "en:prod", baseUrl = null):
//   clientKey — the PUBLIC client key (never the server key)
//   profile   — the locale profile to hydrate, e.g. "{{PROFILE}}"
//   baseUrl   — CDN origin override; default https://cdn.shipeasy.ai
// top-level function, backed by the global configure() state — no object to hold
val head = i18nScriptTag(clientKey, "{{PROFILE}}")

i18n / render

Label rendering is client-side only — the Kotlin server SDK has no t(). Once the loader (from setup) has hydrated translations for {{PROFILE}}, the browser SDK renders labels:

// browser, @shipeasy/sdk client
import { t } from "@shipeasy/sdk/client";
t("checkout.pay_now");

ops

ops / see

Report a caught, handled error (or a non-exception "violation") to Shipeasy with see() — fire-and-forget, never re-throws. Package-level, so it reports against the SDK configured by configure(). Assumes configure() ran at startup — see Installation.

Report a handled exception

import ai.shipeasy.see

try {
    charge(order)
} catch (e: Exception) {
    // .causesThe(subject)   what the error affects (e.g. "checkout")
    // .to(outcome)          the terminal — what you do about it; builds + fires once
    see(e).causesThe("checkout").to("use the backup processor")
    fallbackCharge(order)
}

Attach context with .extras(...)

import ai.shipeasy.see

try {
    charge(order)
} catch (e: Exception) {
    // .extras(map)          structured fields attached to the report (String /
    //                       finite Number / Boolean only; capped at 20 keys)
    see(e).causesThe("checkout").extras(mapOf("order_id" to oid)).to("use cached prices")
}

Report a non-exception violation

import ai.shipeasy.seeViolation

// a bad state that isn't an exception — the name is a STABLE fingerprint; put
// variable data in .extras, never the name. .to() is the terminal.
seeViolation("missing_invoice").causesThe("billing").to("skip the dunning email")

Mark an expected exception — report NOTHING

import ai.shipeasy.controlFlowException

try {
    parse(token)
} catch (e: NoSuchElementException) {
    // transmits nothing; .because(...) / .extras() are local-debug only
    controlFlowException(e).because("end of stream is expected")
}
Was this page helpful?
✎ Edit this page

On this page