Class: HeedKit::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/heedkit/client.rb

Overview

Server-side client for the HeedKit API. Talks to the public roadmap endpoint and the end-user SDK endpoints (X-Project-Key auth).

Identity: this SDK runs where the project SECRET may live, so it can sign identities itself — configure secret_key and #identify computes the required user_hash automatically (or expose #user_hash_for to your frontend widget). Authenticated calls (submit/vote/comment) take the identity token #identify returned; the client is stateless so one instance can serve many end-users.

Constant Summary collapse

DEFAULT_TIMEOUT =
5

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(project_key:, endpoint:, secret_key: nil, timeout: DEFAULT_TIMEOUT) ⇒ Client

Returns a new instance of Client.

Raises:

  • (ArgumentError)


22
23
24
25
26
27
28
29
30
# File 'lib/heedkit/client.rb', line 22

def initialize(project_key:, endpoint:, secret_key: nil, timeout: DEFAULT_TIMEOUT)
  raise ArgumentError, "project_key is required" if project_key.to_s.empty?
  raise ArgumentError, "endpoint is required" if endpoint.to_s.empty?

  @project_key = project_key
  @endpoint = endpoint.to_s.chomp("/")
  @secret_key = secret_key
  @timeout = timeout
end

Instance Attribute Details

#endpointObject (readonly)

Returns the value of attribute endpoint.



20
21
22
# File 'lib/heedkit/client.rb', line 20

def endpoint
  @endpoint
end

#project_keyObject (readonly)

Returns the value of attribute project_key.



20
21
22
# File 'lib/heedkit/client.rb', line 20

def project_key
  @project_key
end

Instance Method Details

#changelogObject

GET the public changelog. Returns a HeedKit::Changelog.



48
49
50
# File 'lib/heedkit/client.rb', line 48

def changelog
  Changelog.from_payload(get("/public/projects/#{project_key}/changelog"))
end

#comment(feature_id, identity:, body:) ⇒ Object

POST /sdk/features/:id/comments — comment as the end-user the token names.



79
80
81
# File 'lib/heedkit/client.rb', line 79

def comment(feature_id, identity:, body:)
  sdk_post("/sdk/features/#{feature_id}/comments", identity:, body:)
end

#features(identity: nil, status: nil, kind: nil, sort: "top", cursor: nil) ⇒ Object

GET /sdk/features — public features, plus the caller's own private submissions when an identity token is given.



63
64
65
66
# File 'lib/heedkit/client.rb', line 63

def features(identity: nil, status: nil, kind: nil, sort: "top", cursor: nil)
  query = { status:, kind:, sort:, cursor: }.compact
  sdk_get("/sdk/features", query, identity:)
end

#identify(external_id: nil, user_hash: nil, email: nil, name: nil, avatar_url: nil, platform: nil) ⇒ Object

POST /sdk/init — identify (find-or-create) an end-user. Returns the parsed body ({ "end_user_id" => ..., "identity" => "", "project" => ... }); pass that "identity" to submit/vote/comment. With an external_id, user_hash is computed from the configured secret_key when not given explicitly.



56
57
58
59
# File 'lib/heedkit/client.rb', line 56

def identify(external_id: nil, user_hash: nil, email: nil, name: nil, avatar_url: nil, platform: nil)
  user_hash ||= user_hash_for(external_id) if external_id && !@secret_key.to_s.empty?
  sdk_post("/sdk/init", external_id:, user_hash:, email:, name:, avatar_url:, platform:)
end

#roadmapObject

GET the public roadmap. Returns a HeedKit::Roadmap.



43
44
45
# File 'lib/heedkit/client.rb', line 43

def roadmap
  Roadmap.from_payload(get("/public/projects/#{project_key}/roadmap"))
end

#submit(identity:, title:, description: nil, kind: "feature_request", tag: nil) ⇒ Object

POST /sdk/features — submit a feature as the end-user the token names.



69
70
71
# File 'lib/heedkit/client.rb', line 69

def submit(identity:, title:, description: nil, kind: "feature_request", tag: nil)
  sdk_post("/sdk/features", identity:, title:, description:, kind:, tag:)
end

#user_hash_for(external_id) ⇒ Object

HMAC_SHA256(secret_key, external_id) as lowercase hex — the signature /sdk/init requires alongside any external_id (unsigned ids are rejected with 401 invalid_user_signature). Also handy for building the identity payload a frontend widget fetches ({ externalId, userHash, name, email }).

Raises:



36
37
38
39
40
# File 'lib/heedkit/client.rb', line 36

def user_hash_for(external_id)
  raise Error, "secret_key not configured — pass secret_key: to HeedKit::Client.new" if @secret_key.to_s.empty?

  OpenSSL::HMAC.hexdigest("SHA256", @secret_key, external_id.to_s)
end

#vote(feature_id, identity:) ⇒ Object

POST /sdk/features/:id/vote — toggle the end-user's vote.



74
75
76
# File 'lib/heedkit/client.rb', line 74

def vote(feature_id, identity:)
  sdk_post("/sdk/features/#{feature_id}/vote", identity:)
end