Appearance
Clients
Each client is a thin library over the API: one call per operation, with the same names in every language. None of them draws any UI. Your product shows its own Report a problem screen and calls the library.
| TypeScript | the browser and Node, typed |
| Godot 4 | an addon in GDScript, on native builds and on the web |
| C#/.NET (Unity), Swift, Kotlin, Unreal | planned |
Every client:
- asks the service for the user's identity the first time it's needed, and keeps it;
- sends reports with a screenshot, adding your product's context and telemetry from callbacks;
- watches for answers, over a stream where it can and by polling otherwise, and tells you about each answer once;
- gives and withdraws the user's contact;
- makes and claims transfer codes;
- gets the user's copy of their data, and erases it.
TypeScript
ts
import { AliasClient, LocalStorageIdentityStore } from 'alias-support'
const alias = new AliasClient({
url: 'https://support.example.com',
key: PRODUCT_KEY,
appVersion: '1.4.2',
store: new LocalStorageIdentityStore(), // keep the identity between visits
context: () => ({ level: game.level }),
telemetry: () => ({ fps: game.fps }),
})
const ticket = await alias.report({ note: "The door won't open", screenshot: await canvasJpeg() })
const stop = alias.watch((u) => toast(`Support answered #${u.ticket}`))- Calls:
getProduct,identity,me,report,tickets,ticket,reply,updates,watch,getContact,setContact,withdrawContact,newTransfer,claimTransfer,useIdentity,myData,eraseMe,forget. - Errors are thrown as
AliasError, carrying the status and the service's reason: a telemetry schema mismatch says which field. - Screenshots can be bytes, a
Blobor base64. - Identity stores: in memory,
localStorage, or your own (load,save).
Godot
gdscript
var alias := AliasSupport.new()
alias.url = "https://support.example.com"
alias.key = PRODUCT_KEY
alias.app_version = ProjectSettings.get_setting("application/config/version")
alias.context_provider = func() -> Dictionary: return {"level": level_name}
alias.telemetry_provider = func() -> Dictionary: return {"fps": Engine.get_frames_per_second()}
add_child(alias)
var r: Dictionary = await alias.report("The door won't open", get_viewport().get_texture().get_image())
if not r.ok:
show_error(r.error)
alias.answered.connect(func(u: Dictionary): notify("Support answered #%d" % u.ticket))
alias.watch()- Calls: the same as the TypeScript client's, in snake_case (
get_product,report,claim_transfer…). Each is a coroutine returning{ok, status, data, error}. - Screenshots can be an
Image(sent as a JPEG) or JPEG bytes. - The identity is kept in
user://, under a name of your choice, so one game can talk to several products. It's never made on the device: the service makes it from a secure random source, whatever the platform has. - Answers: native builds keep a stream open and also poll. Web builds poll only.
- Signals:
answeredandidentity_changed.