linksnap

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 15, 2026 License: MIT Imports: 17 Imported by: 0

README

linksnap (Go)

Official Go SDK for LinkSnap.

Install

go get github.com/hachimi-cat/linksnap-go

Quickstart

LinkSnap uses Huudis as its OIDC issuer. Pick one of three ways to authenticate:

1. Static API key (CI / headless)
package main

import (
    "context"
    "log"

    linksnap "github.com/hachimi-cat/linksnap-go"
)

func main() {
    c := linksnap.NewClient(linksnap.ClientOptions{
        APIKey: "lk_live_xxx",
    })
    link, err := c.Links.Create(context.Background(), linksnap.LinksCreateInput{
        URL: "https://forjio.com",
    }, "")
    if err != nil {
        log.Fatal(err)
    }
    log.Printf("created %s", link.Slug)
}
2. Session (Huudis device flow)
ctx := context.Background()
issuer := "https://huudis.com"
clientID := "oc_linksnap_cli"

start, _ := linksnap.StartDeviceFlow(ctx, linksnap.StartDeviceFlowOptions{
    Issuer: issuer, ClientID: clientID, Scope: "openid profile email offline_access",
})
log.Printf("visit %s and enter code %s", start.VerificationURI, start.UserCode)

tokens, _ := linksnap.PollDeviceToken(ctx, linksnap.PollDeviceTokenOptions{
    Issuer: issuer, ClientID: clientID, DeviceCode: start.DeviceCode, Interval: start.Interval,
})

sess := linksnap.NewSession(linksnap.SessionOptions{
    Issuer: issuer, ClientID: clientID,
    AccessToken:  tokens.AccessToken,
    RefreshToken: tokens.RefreshToken,
    ExpiresAt:    tokens.ExpiresAt,
})

c := linksnap.NewClient(linksnap.ClientOptions{Session: sess})
me, _ := c.Account.Me(ctx, "")

The client proactively refreshes within 5 minutes of expiry and reactively retries once on 401 — single-flight, so concurrent calls share the same refresh round-trip (avoids Huudis refresh-token-family revocation).

3. Per-call token override

Every resource method accepts a final authToken string argument that overrides whatever the client was constructed with — useful for multi-tenant servers handling per-request user tokens.

c.Account.Me(ctx, request.Header.Get("Authorization"))

Verifying access tokens (server-side)

claims, err := linksnap.VerifyAccessToken(
    r.Context(),
    r.Header.Get("Authorization"),
    linksnap.VerifyOptions{},
)
if err != nil {
    http.Error(w, err.Error(), http.StatusUnauthorized)
    return
}
log.Printf("authenticated as %s (account %s)", claims.Sub, claims.AccountID)

Falls back to HUUDIS_ISSUER / HUUDIS_AUDIENCE env vars. JWKS keys are fetched per issuer and cached for one hour with rotation handling.

Resources

Namespace Methods
Links List, Get, Create, Update, Delete, Bulk, Export, Import
Stats Show, Export, Workspace
QR List, Get, Create, Delete, Download, Stats
Tags List
Domains List, Add, Verify, Remove
Billing Plans, Plan, Subscription, Usage, History, Invoices, Checkout, Cancel, Downgrade
Workspace Show, Rename, Members.List/Add/Remove
APIKeys List, Create, Delete
Account Me, Update, ChangePassword, Delete
(top-level) Health()

License

MIT

Documentation

Overview

Package linksnap is the official Go SDK for LinkSnap.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ClearDiscoveryCache

func ClearDiscoveryCache()

ClearDiscoveryCache resets the in-process discovery cache (test seam).

Types

type APIClient

type APIClient struct {
	BaseURL          string
	Session          *Session
	HTTP             *http.Client
	RefreshBufferSec int64
	// DefaultToken is used as the Bearer when no Session is set and the
	// caller did not pass a per-call token. Typically a long-lived API key.
	DefaultToken string
}

APIClient is the typed HTTP client every resource calls into. Mirrors the Python SDK's ApiClient: Bearer auth, proactive refresh, reactive single retry on 401 with a refresh in between, Forjio envelope (data/error/meta) unwrap.

func NewAPIClient

func NewAPIClient(opts APIClientOptions) *APIClient

NewAPIClient builds an APIClient with sensible defaults.

func (*APIClient) Delete

func (c *APIClient) Delete(ctx context.Context, path string, out any, opts *RequestOptions) error

Delete sends a DELETE.

func (*APIClient) Do

func (c *APIClient) Do(ctx context.Context, method, path string, body, out any, opts *RequestOptions) error

Do is the lower-level entry point. Handles proactive refresh + reactive 401 retry and envelope unwrap.

func (*APIClient) Get

func (c *APIClient) Get(ctx context.Context, path string, out any, opts *RequestOptions) error

Get sends a GET and decodes the JSON `data` payload into out (out may be nil).

func (*APIClient) Patch

func (c *APIClient) Patch(ctx context.Context, path string, body, out any, opts *RequestOptions) error

Patch sends a PATCH.

func (*APIClient) Post

func (c *APIClient) Post(ctx context.Context, path string, body, out any, opts *RequestOptions) error

Post sends a POST with a JSON body and decodes the JSON `data` payload into out.

func (*APIClient) Put

func (c *APIClient) Put(ctx context.Context, path string, body, out any, opts *RequestOptions) error

Put sends a PUT.

type APIClientOptions

type APIClientOptions struct {
	BaseURL          string
	Session          *Session
	HTTP             *http.Client
	RefreshBufferSec int64
	DefaultToken     string
}

APIClientOptions configures NewAPIClient.

type APIKey

type APIKey struct {
	ID        string `json:"id"`
	Name      string `json:"name"`
	Prefix    string `json:"prefix"`
	Secret    string `json:"secret,omitempty"`
	CreatedAt string `json:"createdAt"`
}

APIKey mirrors the Node SDK's `ApiKey` interface. Secret only present on create.

type APIKeysResource

type APIKeysResource struct {
	// contains filtered or unexported fields
}

APIKeysResource is the `/api/v1/auth/api-keys` namespace.

func (*APIKeysResource) Create

func (r *APIKeysResource) Create(ctx context.Context, name, authToken string) (*APIKey, error)

Create mints a new API key. The plaintext secret is only returned once.

func (*APIKeysResource) Delete

func (r *APIKeysResource) Delete(ctx context.Context, id, authToken string) error

Delete revokes an API key.

func (*APIKeysResource) List

func (r *APIKeysResource) List(ctx context.Context, authToken string) ([]APIKey, error)

List returns every API key owned by the principal.

type AccountResource

type AccountResource struct {
	// contains filtered or unexported fields
}

AccountResource is the `/api/v1/auth/*` profile namespace.

func (*AccountResource) ChangePassword

func (r *AccountResource) ChangePassword(ctx context.Context, currentPassword, newPassword, authToken string) error

ChangePassword rotates the account password.

func (*AccountResource) Delete

func (r *AccountResource) Delete(ctx context.Context, authToken string) error

Delete permanently deletes the account.

func (*AccountResource) Me

func (r *AccountResource) Me(ctx context.Context, authToken string) (map[string]any, error)

Me returns the authenticated principal.

func (*AccountResource) Update

func (r *AccountResource) Update(ctx context.Context, patch map[string]any, authToken string) (map[string]any, error)

Update patches the profile.

type BillingInvoicesQuery

type BillingInvoicesQuery struct {
	Limit int
}

BillingInvoicesQuery is the optional query for BillingResource.Invoices.

type BillingPlan

type BillingPlan struct {
	ID       string   `json:"id"`
	Name     string   `json:"name"`
	Monthly  float64  `json:"monthly"`
	Features []string `json:"features"`
}

BillingPlan mirrors the Node SDK's `BillingPlan` interface.

type BillingResource

type BillingResource struct {
	// contains filtered or unexported fields
}

BillingResource is the `/api/v1/billing/*` namespace.

func (*BillingResource) Cancel

func (r *BillingResource) Cancel(ctx context.Context, authToken string) (map[string]any, error)

Cancel cancels the active subscription at period end.

func (*BillingResource) Checkout

func (r *BillingResource) Checkout(ctx context.Context, planID, authToken string) (*CheckoutResult, error)

Checkout creates a hosted checkout session for a given plan.

func (*BillingResource) Downgrade

func (r *BillingResource) Downgrade(ctx context.Context, planID, authToken string) (map[string]any, error)

Downgrade schedules a downgrade to a cheaper plan at period end.

func (*BillingResource) History

func (r *BillingResource) History(ctx context.Context, authToken string) ([]map[string]any, error)

History returns the workspace's payment history.

func (*BillingResource) Invoices

func (r *BillingResource) Invoices(ctx context.Context, q BillingInvoicesQuery, authToken string) ([]map[string]any, error)

Invoices returns past invoices.

func (*BillingResource) Plan

func (r *BillingResource) Plan(ctx context.Context, authToken string) (map[string]any, error)

Plan returns the current workspace's plan.

func (*BillingResource) Plans

func (r *BillingResource) Plans(ctx context.Context, authToken string) ([]BillingPlan, error)

Plans returns the list of plans available for sign-up.

func (*BillingResource) Subscription

func (r *BillingResource) Subscription(ctx context.Context, authToken string) (map[string]any, error)

Subscription returns the active subscription metadata.

func (*BillingResource) Usage

func (r *BillingResource) Usage(ctx context.Context, authToken string) (*BillingUsage, error)

Usage returns the current period's usage counters.

type BillingUsage

type BillingUsage struct {
	LinksCreated      int    `json:"linksCreated"`
	MonthlyClickLimit int    `json:"monthlyClickLimit"`
	MonthlyClicksUsed int    `json:"monthlyClicksUsed"`
	AsOf              string `json:"asOf"`
}

BillingUsage mirrors the Node SDK's `BillingUsage` interface.

type CheckoutResult

type CheckoutResult struct {
	URL string `json:"url"`
}

CheckoutResult is the Plugipay-hosted checkout URL.

type Claims

type Claims struct {
	Iss          string `json:"iss"`
	Aud          string `json:"aud"`
	Sub          string `json:"sub"`
	Exp          int64  `json:"exp"`
	Iat          int64  `json:"iat"`
	AccountID    string `json:"accountId"`
	IdentityID   string `json:"identityId"`
	IdentityType string `json:"identityType"`
	Scope        string `json:"scope"`
	MfaVerified  bool   `json:"mfaVerified,omitempty"`
	Email        string `json:"email,omitempty"`
	EmailVerif   bool   `json:"email_verified,omitempty"`
	Name         string `json:"name,omitempty"`
	Raw          map[string]any
}

Claims is the typed view over a Huudis-issued JWT (LinkSnap uses Huudis as its OIDC issuer). Mirrors `huudis-go`'s `Claims`.

func VerifyAccessToken

func VerifyAccessToken(ctx context.Context, tokenOrHeader string, opts VerifyOptions) (*Claims, error)

VerifyAccessToken validates a Huudis-issued JWT against the issuer's JWKS. Accepts either a raw token or a full `Authorization: Bearer …` header value.

type ClickStats

type ClickStats struct {
	TotalClicks    int                 `json:"totalClicks"`
	UniqueVisitors int                 `json:"uniqueVisitors"`
	ByDay          []ClickStatsByDay   `json:"byDay"`
	ByCountry      []ClickStatsCountry `json:"byCountry"`
	ByReferer      []ClickStatsReferer `json:"byReferer"`
	ByDevice       []ClickStatsDevice  `json:"byDevice"`
}

ClickStats mirrors the Node SDK's `ClickStats` interface.

type ClickStatsByDay

type ClickStatsByDay struct {
	Date   string `json:"date"`
	Clicks int    `json:"clicks"`
}

type ClickStatsCountry

type ClickStatsCountry struct {
	Country string `json:"country"`
	Clicks  int    `json:"clicks"`
}

type ClickStatsDevice

type ClickStatsDevice struct {
	Device string `json:"device"`
	Clicks int    `json:"clicks"`
}

type ClickStatsReferer

type ClickStatsReferer struct {
	Referer string `json:"referer"`
	Clicks  int    `json:"clicks"`
}

type Client

type Client struct {
	BaseURL string
	API     *APIClient

	Links     *LinksResource
	Stats     *StatsResource
	QR        *QRResource
	Tags      *TagsResource
	Domains   *DomainsResource
	Billing   *BillingResource
	Workspace *WorkspaceResource
	APIKeys   *APIKeysResource
	Account   *AccountResource
}

Client is the high-level LinkSnap SDK surface. Mirrors the Node SDK's `LinkSnapClient`: every developer-facing endpoint lives under a typed resource namespace (Links, Stats, QR, Tags, Domains, Billing, Workspace, APIKeys, Account) plus an unauthenticated Health() call.

func NewClient

func NewClient(opts ClientOptions) *Client

NewClient builds a Client with sensible defaults.

func (*Client) Health

func (c *Client) Health(ctx context.Context) (*HealthStatus, error)

Health calls the unauthenticated /api/v1/health endpoint.

type ClientOptions

type ClientOptions struct {
	// BaseURL defaults to https://linksnap.forjio.com.
	BaseURL string
	// Session, when set, auto-attaches its Bearer token to every request
	// and refreshes on 401 (single-flight).
	Session *Session
	// APIKey is the fallback Bearer token used when no Session is set
	// (and no per-call AuthToken is passed). Suitable for CI / headless
	// runs.
	APIKey string
	// HTTP is the underlying http.Client. Defaults to http.DefaultClient.
	HTTP *http.Client
}

ClientOptions configures NewClient.

type DeviceFlowStart

type DeviceFlowStart struct {
	DeviceCode              string `json:"device_code"`
	UserCode                string `json:"user_code"`
	VerificationURI         string `json:"verification_uri"`
	VerificationURIComplete string `json:"verification_uri_complete,omitempty"`
	ExpiresIn               int    `json:"expires_in"`
	Interval                int    `json:"interval"`
}

DeviceFlowStart is the result of starting an RFC 8628 device-code flow.

func StartDeviceFlow

func StartDeviceFlow(ctx context.Context, opts StartDeviceFlowOptions) (*DeviceFlowStart, error)

StartDeviceFlow kicks off the RFC 8628 device authorization grant.

type DeviceTokens

type DeviceTokens struct {
	AccessToken  string
	ExpiresAt    int64
	TokenType    string
	RefreshToken string
	Scope        string
}

DeviceTokens is the result of a successful /token call. ExpiresAt is unix epoch seconds (computed locally from `expires_in`).

func PollDeviceToken

func PollDeviceToken(ctx context.Context, opts PollDeviceTokenOptions) (*DeviceTokens, error)

PollDeviceToken polls the token endpoint per RFC 8628 §3.4 until the user approves, denies, or the code expires. Honors `slow_down`.

func RefreshAccessToken

func RefreshAccessToken(ctx context.Context, opts RefreshAccessTokenOptions) (*DeviceTokens, error)

RefreshAccessToken exchanges a refresh token for a new access token. If the server omits a new refresh token, the original is preserved (per RFC 6749 §6).

type DiscoveryDocument

type DiscoveryDocument struct {
	Issuer                      string `json:"issuer"`
	DeviceAuthorizationEndpoint string `json:"device_authorization_endpoint"`
	TokenEndpoint               string `json:"token_endpoint"`
	JWKSURI                     string `json:"jwks_uri"`
	AuthorizationEndpoint       string `json:"authorization_endpoint,omitempty"`
	UserInfoEndpoint            string `json:"userinfo_endpoint,omitempty"`
	EndSessionEndpoint          string `json:"end_session_endpoint,omitempty"`
}

DiscoveryDocument is the subset of the OIDC discovery JSON the SDK cares about. Mirrors the Python SDK's `DiscoveryDocument`.

func FetchDiscovery

func FetchDiscovery(ctx context.Context, issuer string, httpClient *http.Client) (*DiscoveryDocument, error)

FetchDiscovery loads `<issuer>/.well-known/openid-configuration` (and caches it for the process lifetime). Pass a non-nil `httpClient` to override the default.

type Domain

type Domain struct {
	ID        string `json:"id"`
	Domain    string `json:"domain"`
	Status    string `json:"status"`
	CreatedAt string `json:"createdAt"`
}

Domain mirrors the Node SDK's `Domain` interface. Status is one of "pending" | "verified" | "failed".

type DomainsResource

type DomainsResource struct {
	// contains filtered or unexported fields
}

DomainsResource is the `/api/v1/domains` namespace.

func (*DomainsResource) Add

func (r *DomainsResource) Add(ctx context.Context, domain, authToken string) (*Domain, error)

Add attaches a custom domain.

func (*DomainsResource) List

func (r *DomainsResource) List(ctx context.Context, authToken string) ([]Domain, error)

List returns every custom domain configured on the workspace.

func (*DomainsResource) Remove

func (r *DomainsResource) Remove(ctx context.Context, id, authToken string) error

Remove detaches a domain.

func (*DomainsResource) Verify

func (r *DomainsResource) Verify(ctx context.Context, id, authToken string) (*Domain, error)

Verify triggers DNS-verification on a pending domain.

type Error

type Error struct {
	Code      string
	Message   string
	Status    int
	RequestID string
	Details   map[string]any
}

Error is the single error type returned by every operation in this package. Wraps an opaque code plus a message and the HTTP status (zero when not transport-derived) so callers can branch on well-defined reasons without matching strings. Mirrors the Node SDK's `LinkSnapError` (which re-exports `@forjio/sdk`'s `ApiError`).

func (*Error) Error

func (e *Error) Error() string

type HealthStatus

type HealthStatus struct {
	Status string `json:"status"`
}

HealthStatus is the shape returned by GET /api/v1/health.

type Link struct {
	ID          string   `json:"id"`
	Slug        string   `json:"slug"`
	URL         string   `json:"url"`
	Title       *string  `json:"title,omitempty"`
	Description *string  `json:"description,omitempty"`
	Tags        []string `json:"tags,omitempty"`
	ExpiresAt   *string  `json:"expiresAt,omitempty"`
	Password    bool     `json:"password,omitempty"`
	WorkspaceID string   `json:"workspaceId"`
	DomainID    *string  `json:"domainId,omitempty"`
	Clicks      int      `json:"clicks,omitempty"`
	CreatedAt   string   `json:"createdAt"`
	UpdatedAt   string   `json:"updatedAt"`
}

Link mirrors the Node SDK's `Link` interface.

type LinkListPage

type LinkListPage struct {
	Items      []Link `json:"items"`
	NextCursor string `json:"nextCursor,omitempty"`
}

LinkListPage is the paginated `links.List` response shape. LinkSnap returns either `{items, nextCursor}` or a bare array — both decode into this type via the resource method.

type LinksBulkResult

type LinksBulkResult struct {
	Affected int `json:"affected"`
}

LinksBulkResult mirrors `{ affected: number }`.

type LinksCreateInput

type LinksCreateInput struct {
	URL         string   `json:"url"`
	Slug        string   `json:"slug,omitempty"`
	Title       string   `json:"title,omitempty"`
	Description string   `json:"description,omitempty"`
	Tags        []string `json:"tags,omitempty"`
	ExpiresAt   string   `json:"expiresAt,omitempty"`
}

LinksCreateInput is the body for LinksResource.Create.

type LinksImportResult

type LinksImportResult struct {
	Imported int `json:"imported"`
}

LinksImportResult mirrors `{ imported: number }`.

type LinksListQuery

type LinksListQuery struct {
	Tag      string
	Archived *bool
	Limit    int
	Cursor   string
}

LinksListQuery is the optional query for LinksResource.List.

type LinksResource

type LinksResource struct {
	// contains filtered or unexported fields
}

LinksResource is the `/api/v1/links` namespace.

func (*LinksResource) Bulk

func (r *LinksResource) Bulk(ctx context.Context, action string, ids []string, authToken string) (*LinksBulkResult, error)

Bulk runs a bulk operation. action ∈ {"delete", "archive", "tag"}.

func (*LinksResource) Create

func (r *LinksResource) Create(ctx context.Context, in LinksCreateInput, authToken string) (*Link, error)

Create makes a new short link.

func (*LinksResource) Delete

func (r *LinksResource) Delete(ctx context.Context, idOrSlug, authToken string) error

Delete removes a link.

func (*LinksResource) Export

func (r *LinksResource) Export(ctx context.Context, authToken string) (string, error)

Export downloads all links as CSV (returned as a string).

func (*LinksResource) Get

func (r *LinksResource) Get(ctx context.Context, idOrSlug, authToken string) (*Link, error)

Get returns a single link by id or slug.

func (*LinksResource) Import

func (r *LinksResource) Import(ctx context.Context, csv, authToken string) (*LinksImportResult, error)

Import ingests a CSV payload.

func (*LinksResource) List

func (r *LinksResource) List(ctx context.Context, q LinksListQuery, authToken string) (*LinkListPage, error)

List returns links for the current workspace. Handles both paged (`{items, nextCursor}`) and bare-array responses.

func (*LinksResource) Update

func (r *LinksResource) Update(ctx context.Context, idOrSlug string, patch map[string]any, authToken string) (*Link, error)

Update patches an existing link. Pass a map of fields to mutate (matches the Node SDK's `Partial<…>` shape).

type PollDeviceTokenOptions

type PollDeviceTokenOptions struct {
	Issuer     string
	ClientID   string
	DeviceCode string
	Interval   int // seconds — defaults to 5
	OnPending  func()
	HTTPClient *http.Client
	Sleep      func(time.Duration) // test seam
}

PollDeviceTokenOptions parameterizes PollDeviceToken.

type QRCode

type QRCode struct {
	ID        string  `json:"id"`
	URL       string  `json:"url"`
	Label     *string `json:"label,omitempty"`
	ImageURL  string  `json:"imageUrl"`
	Scans     int     `json:"scans,omitempty"`
	CreatedAt string  `json:"createdAt"`
}

QRCode mirrors the Node SDK's `QRCode` interface.

type QRCreateInput

type QRCreateInput struct {
	URL   string `json:"url"`
	Label string `json:"label,omitempty"`
}

QRCreateInput is the body for QRResource.Create.

type QRResource

type QRResource struct {
	// contains filtered or unexported fields
}

QRResource is the `/api/v1/qr-codes` namespace.

func (*QRResource) Create

func (r *QRResource) Create(ctx context.Context, in QRCreateInput, authToken string) (*QRCode, error)

Create generates a new QR code.

func (*QRResource) Delete

func (r *QRResource) Delete(ctx context.Context, id, authToken string) error

Delete removes a QR code.

func (*QRResource) Download

func (r *QRResource) Download(ctx context.Context, id, authToken string) (string, error)

Download returns the QR code download URL (or inline payload).

func (*QRResource) Get

func (r *QRResource) Get(ctx context.Context, id, authToken string) (*QRCode, error)

Get returns a single QR code.

func (*QRResource) List

func (r *QRResource) List(ctx context.Context, authToken string) ([]QRCode, error)

List returns every QR code in the workspace.

func (*QRResource) Stats

func (r *QRResource) Stats(ctx context.Context, id, authToken string) (*ClickStats, error)

Stats returns QR-code click stats.

type RefreshAccessTokenOptions

type RefreshAccessTokenOptions struct {
	Issuer       string
	ClientID     string
	RefreshToken string
	Scope        string
	HTTPClient   *http.Client
}

RefreshAccessTokenOptions parameterizes RefreshAccessToken.

type RequestOptions

type RequestOptions struct {
	Query   map[string]any
	Headers map[string]string
	// AuthToken overrides the client-level Bearer for this single call.
	// Empty means "use session / default".
	AuthToken string
}

RequestOptions tunes a single Do call.

type Session

type Session struct {
	Issuer   string
	ClientID string
	// contains filtered or unexported fields
}

Session is a minimal in-process token holder mirroring `@forjio/sdk`'s Session — just enough surface for the client to attach a Bearer token and refresh it on 401. Persisting credentials to disk (as the Python SDK does via INI) is intentionally not implemented here: Go consumers either own a CLI that manages its own credential store or are running in a server context where in-memory is enough.

All methods are safe for concurrent use. Refresh is single-flight — concurrent callers share the same network round-trip, which matters because Huudis revokes the entire refresh-token family on reuse.

func NewSession

func NewSession(opts SessionOptions) *Session

NewSession constructs a Session. At minimum Issuer + ClientID + AccessToken are required; RefreshToken is needed if you want auto-refresh on 401 / proactive refresh.

func (*Session) AccessToken

func (s *Session) AccessToken() string

AccessToken returns the current access token (may be empty if cleared).

func (*Session) ExpiresAt

func (s *Session) ExpiresAt() int64

ExpiresAt returns the access token's unix expiry.

func (*Session) IsExpired

func (s *Session) IsExpired() bool

IsExpired reports whether the access token's expiry has passed.

func (*Session) Refresh

func (s *Session) Refresh(ctx context.Context) error

Refresh exchanges the stored refresh token for a new access token. Single-flight: concurrent callers wait on the same in-flight request.

func (*Session) RefreshToken

func (s *Session) RefreshToken() string

RefreshToken returns the current refresh token.

func (*Session) SetTokens

func (s *Session) SetTokens(accessToken, refreshToken string, expiresAt int64, scope string)

SetTokens replaces the in-memory tokens (e.g. after a fresh device flow).

func (*Session) WillExpireSoon

func (s *Session) WillExpireSoon(bufferSec int64) bool

WillExpireSoon reports whether the access token expires within `bufferSec` seconds from now. Use this for proactive refresh.

type SessionOptions

type SessionOptions struct {
	Issuer       string
	ClientID     string
	AccessToken  string
	RefreshToken string
	// ExpiresAt is unix epoch seconds. Zero means "unknown" (treated as expired).
	ExpiresAt  int64
	Scope      string
	HTTPClient *http.Client
}

SessionOptions seeds a new Session.

type StartDeviceFlowOptions

type StartDeviceFlowOptions struct {
	Issuer     string
	ClientID   string
	Scope      string
	HTTPClient *http.Client
}

StartDeviceFlowOptions parameterizes StartDeviceFlow.

type StatsResource

type StatsResource struct {
	// contains filtered or unexported fields
}

StatsResource is the click-analytics namespace.

func (*StatsResource) Export

func (r *StatsResource) Export(ctx context.Context, idOrSlug, authToken string) (string, error)

Export downloads a per-link stats CSV.

func (*StatsResource) Show

func (r *StatsResource) Show(ctx context.Context, idOrSlug string, q StatsShowQuery, authToken string) (*ClickStats, error)

Show returns click stats for a single link.

func (*StatsResource) Workspace

func (r *StatsResource) Workspace(ctx context.Context, q StatsShowQuery, authToken string) (*ClickStats, error)

Workspace returns aggregate stats for the active workspace.

type StatsShowQuery

type StatsShowQuery struct {
	From string
	To   string
}

StatsShowQuery is the optional from/to range for StatsResource.Show.

type Tag

type Tag struct {
	Name      string `json:"name"`
	LinkCount int    `json:"linkCount"`
}

Tag mirrors the Node SDK's `Tag` interface.

type TagsResource

type TagsResource struct {
	// contains filtered or unexported fields
}

TagsResource is the `/api/v1/tags` namespace.

func (*TagsResource) List

func (r *TagsResource) List(ctx context.Context, authToken string) ([]Tag, error)

List returns every tag in the workspace plus its link count.

type VerifyOptions

type VerifyOptions struct {
	Issuer     string
	Audience   string
	RequireMFA bool
}

VerifyOptions configures VerifyAccessToken. Falls back to HUUDIS_ISSUER / HUUDIS_AUDIENCE env vars when fields are empty.

type Workspace

type Workspace struct {
	ID        string `json:"id"`
	Name      string `json:"name"`
	Plan      string `json:"plan,omitempty"`
	CreatedAt string `json:"createdAt"`
}

Workspace mirrors the Node SDK's `Workspace` interface.

type WorkspaceMembersResource

type WorkspaceMembersResource struct {
	// contains filtered or unexported fields
}

WorkspaceMembersResource is the workspace members namespace.

func (*WorkspaceMembersResource) Add

func (r *WorkspaceMembersResource) Add(ctx context.Context, email, role, authToken string) (map[string]any, error)

Add invites an email to the workspace.

func (*WorkspaceMembersResource) List

func (r *WorkspaceMembersResource) List(ctx context.Context, authToken string) ([]map[string]any, error)

List returns the workspace's members.

func (*WorkspaceMembersResource) Remove

func (r *WorkspaceMembersResource) Remove(ctx context.Context, memberID, authToken string) error

Remove kicks a member.

type WorkspaceResource

type WorkspaceResource struct {
	Members *WorkspaceMembersResource
	// contains filtered or unexported fields
}

WorkspaceResource is the `/api/v1/workspaces/current` namespace.

func (*WorkspaceResource) Rename

func (r *WorkspaceResource) Rename(ctx context.Context, name, authToken string) (*Workspace, error)

Rename updates the workspace name.

func (*WorkspaceResource) Show

func (r *WorkspaceResource) Show(ctx context.Context, authToken string) (*Workspace, error)

Show returns the current workspace.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL