faynosync

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: May 28, 2026 License: Apache-2.0 Imports: 12 Imported by: 0

README

faynoSync Go SDK

Production-oriented Go SDK for checking application updates with faynoSync.

This package is a small typed transport and developer experience layer. It does not implement update installation, platform normalization, metadata verification, caching, or business rules.

Installation

go get github.com/ku9nov/faynosync-sdk-go

Quick Start

package main

import (
	"context"
	"fmt"
	"log"

	faynosync "github.com/ku9nov/faynosync-sdk-go"
)

func main() {
	client := faynosync.NewClient(faynosync.Config{
		BaseURL: "https://api.example.com",
	})

	resp, err := client.CheckForUpdates(context.Background(), faynosync.CheckOptions{
		Owner:    "admin",
		AppName:  "tuf",
		Version:  "0.0.0.5",
		Channel:  "nightly",
		Platform: "darwin",
		Arch:     "arm64",
	})
	if err != nil {
		log.Fatal(err)
	}

	if resp.UpdateAvailable {
		if resp.UpdateURL != "" {
			fmt.Printf("Update is available: %s\n", resp.UpdateURL)
		}
		for _, packageURL := range resp.PackageURLs {
			fmt.Printf("%s update is available: %s\n", packageURL.Package, packageURL.URL)
		}
	}
}

Configuration

client := faynosync.NewClient(faynosync.Config{
	BaseURL: "https://api.example.com",
	EdgeURL: "https://cdn.example.com",
	HTTPClient: &http.Client{
		Timeout: 10 * time.Second,
	},
})

BaseURL is required. It points to the faynoSync API.

EdgeURL is optional. When configured, the SDK tries a static edge JSON response before falling back to the API.

HTTPClient is optional. When omitted, the SDK creates an http.Client with a default timeout. Custom clients are useful for timeouts, proxies, custom transports, and connection pooling policies.

The client is safe for concurrent use.

Update Checks

CheckForUpdates sends a context-aware request and returns a typed response:

resp, err := client.CheckForUpdates(ctx, faynosync.CheckOptions{
	Owner:    "admin",
	AppName:  "tuf",
	Version:  "0.0.0.5",
	Channel:  "nightly",
	Platform: "darwin",
	Arch:     "arm64",
	DeviceID: "optional-device-id",
})

DeviceID is optional. When set, the SDK sends it as the X-Device-ID header.

Base API Request

The BaseURL API request uses GET /checkVersion:

GET /checkVersion?app_name=tuf&version=0.0.0.5&channel=nightly&platform=darwin&arch=arm64&owner=admin
X-Device-ID: optional

Query parameters are built from CheckOptions with typed fields. The SDK does not use untyped maps in its public API.

Response Model

faynoSync may return a direct binary update URL:

{
  "update_available": true,
  "update_url": "https://downloads.example.com/app"
}

It may also return package-specific URLs with dynamic field names:

{
  "update_available": true,
  "update_url_deb": "https://downloads.example.com/app.deb",
  "update_url_rpm": "https://downloads.example.com/app.rpm",
  "changelog": "### Changelog\n\n- Added feature X",
  "critical": true,
  "is_intermediate_required": true,
  "possible_rollback": true
}

The SDK decodes these into a typed response:

if resp.UpdateURL != "" {
	fmt.Println(resp.UpdateURL)
}

for _, packageURL := range resp.PackageURLs {
	fmt.Println(packageURL.Package, packageURL.URL)
}

EdgeURL Fallback

When EdgeURL is configured, the SDK first tries a static JSON response:

GET /responses/{owner}/{app_name}/{channel}/{platform}/{arch}/{version}.json

For example:

GET /responses/admin/tuf/nightly/darwin/arm64/0.0.0.5.json

If the edge response succeeds with HTTP 200 and valid JSON, UpdateResponse.Source is SourceEdge.

The SDK falls back to the BaseURL API when the edge request has:

  • a network error;
  • a timeout;
  • invalid JSON;
  • HTTP 404;
  • any other non-200 response.

If the fallback API succeeds, UpdateResponse.Source is SourceAPI.

Platform, Channel, And Architecture Values

faynoSync supports fully custom platform, channel, and architecture values. This SDK never normalizes or remaps them.

The SDK will not change values such as:

  • macos to darwin;
  • osx to darwin;
  • stable to default.

Whatever string you pass in CheckOptions.Channel, CheckOptions.Platform, and CheckOptions.Arch is the string sent to faynoSync.

Optional System Helpers

The SDK provides optional helpers:

platform := faynosync.SystemPlatform() // runtime.GOOS
arch := faynosync.SystemArch()         // runtime.GOARCH

These helpers are never used automatically. Use them only when Go runtime values match your faynoSync configuration.

Error Handling

The SDK validates required fields and returns typed sentinel errors:

resp, err := client.CheckForUpdates(ctx, opts)
if err != nil {
	switch {
	case errors.Is(err, faynosync.ErrMissingBaseURL):
		// Configure Config.BaseURL.
	case errors.Is(err, faynosync.ErrMissingOwner):
		// Set CheckOptions.Owner.
	case errors.Is(err, faynosync.ErrMissingAppName):
		// Set CheckOptions.AppName.
	case errors.Is(err, faynosync.ErrMissingVersion):
		// Set CheckOptions.Version.
	case errors.Is(err, faynosync.ErrRequestFailed):
		// Inspect the wrapped endpoint error.
	default:
		// Handle any other error.
	}
}

Request failures preserve underlying causes for errors.Is and errors.As:

var endpointErr *faynosync.EndpointError
if errors.As(err, &endpointErr) {
	fmt.Println(endpointErr.URL)
	fmt.Println(endpointErr.StatusCode)
}

Examples

Runnable examples are available in:

  • examples/basic
  • examples/edge-fallback
  • examples/custom-http-client

Security Scope

This SDK version performs update-check transport requests and typed response decoding only.

It does not verify TUF metadata, signatures, thresholds, expiration, rollback protection, or cache safety. Applications that need secure update metadata verification must perform that verification in the appropriate faynoSync component or a future SDK layer that explicitly implements it.

No signature, threshold, expiration, rollback, freeze, root-of-trust, or cache protection is weakened by this transport-only SDK.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrMissingBaseURL is returned when Config.BaseURL is empty.
	ErrMissingBaseURL = errors.New("faynosync: missing base URL")

	// ErrInvalidBaseURL is returned when Config.BaseURL cannot be used as an absolute URL.
	ErrInvalidBaseURL = errors.New("faynosync: invalid base URL")

	// ErrInvalidEdgeURL is returned when Config.EdgeURL cannot be used as an absolute URL.
	ErrInvalidEdgeURL = errors.New("faynosync: invalid edge URL")

	// ErrMissingOwner is returned when CheckOptions.Owner is empty.
	ErrMissingOwner = errors.New("faynosync: missing owner")

	// ErrMissingAppName is returned when CheckOptions.AppName is empty.
	ErrMissingAppName = errors.New("faynosync: missing app name")

	// ErrMissingVersion is returned when CheckOptions.Version is empty.
	ErrMissingVersion = errors.New("faynosync: missing version")

	// ErrRequestFailed is returned when an update check request fails.
	ErrRequestFailed = errors.New("faynosync: request failed")
)

Functions

func SystemArch

func SystemArch() string

SystemArch returns runtime.GOARCH.

The SDK never calls this automatically. It is provided only for callers that choose to use Go runtime architecture names as their faynoSync arch values.

func SystemPlatform

func SystemPlatform() string

SystemPlatform returns runtime.GOOS.

The SDK never calls this automatically. It is provided only for callers that choose to use Go runtime platform names as their faynoSync platform values.

Types

type CheckError

type CheckError struct {
	EdgeErr error
	APIErr  error
}

CheckError describes a failed update check after all configured endpoints fail.

func (*CheckError) Error

func (e *CheckError) Error() string

Error returns a human-readable update check error message.

func (*CheckError) Is

func (e *CheckError) Is(target error) bool

Is reports whether the check error matches a sentinel error.

func (*CheckError) Unwrap

func (e *CheckError) Unwrap() []error

Unwrap returns all endpoint errors that contributed to the failed check.

type CheckOptions

type CheckOptions struct {
	Owner   string
	AppName string
	Version string

	Channel  string
	Platform string
	Arch     string

	// DeviceID optionally enables server-side telemetry when supported by the API.
	// When empty, the X-Device-ID header is omitted.
	DeviceID string
}

CheckOptions contains the typed parameters used to check for updates.

Channel, Platform, and Arch are intentionally user-controlled values. The SDK does not detect, normalize, remap, or default them.

type Client

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

Client is a concurrency-safe faynoSync SDK client.

func NewClient

func NewClient(cfg Config) *Client

NewClient creates a new faynoSync SDK client.

The returned client is safe for concurrent use. If cfg.HTTPClient is nil, the SDK creates an HTTP client with a default timeout and reusable connections.

func (*Client) CheckForUpdates

func (c *Client) CheckForUpdates(ctx context.Context, opts CheckOptions) (*UpdateResponse, error)

CheckForUpdates checks whether an update is available for the provided app.

If Config.EdgeURL is configured, the client first tries the static edge JSON response and falls back to the BaseURL API when the edge misses or fails.

type Config

type Config struct {
	// BaseURL is the required faynoSync API base URL.
	BaseURL string

	// EdgeURL is an optional static response edge base URL.
	// When configured, the client tries EdgeURL before falling back to BaseURL.
	EdgeURL string

	// HTTPClient is an optional HTTP client.
	// When nil, the SDK creates a client with a reasonable default timeout.
	HTTPClient *http.Client
}

Config configures a faynoSync SDK client.

type EndpointError

type EndpointError struct {
	Source     UpdateSource
	URL        string
	StatusCode int
	Err        error
}

EndpointError describes a failed request to one faynoSync endpoint.

func (*EndpointError) Error

func (e *EndpointError) Error() string

Error returns a human-readable endpoint error message.

func (*EndpointError) Is

func (e *EndpointError) Is(target error) bool

Is reports whether the endpoint error matches a sentinel error.

func (*EndpointError) Unwrap

func (e *EndpointError) Unwrap() error

Unwrap returns the underlying endpoint error.

type PackageUpdateURL

type PackageUpdateURL struct {
	Package string
	URL     string
}

PackageUpdateURL contains one package-specific update URL.

type UpdateResponse

type UpdateResponse struct {
	UpdateAvailable        bool   `json:"update_available"`
	UpdateURL              string `json:"update_url,omitempty"`
	Changelog              string `json:"changelog,omitempty"`
	Critical               bool   `json:"critical,omitempty"`
	IsIntermediateRequired bool   `json:"is_intermediate_required,omitempty"`
	PossibleRollback       bool   `json:"possible_rollback,omitempty"`

	// PackageURLs contains package-specific URLs decoded from fields such as
	// update_url_deb, update_url_rpm, or any future update_url_<package> key.
	PackageURLs []PackageUpdateURL `json:"-"`

	// Source identifies whether the response came from the edge or API fallback.
	Source UpdateSource `json:"-"`
}

UpdateResponse contains the typed faynoSync update check response.

func (*UpdateResponse) UnmarshalJSON

func (r *UpdateResponse) UnmarshalJSON(data []byte) error

UnmarshalJSON decodes fixed response fields and dynamic update_url_<package> fields into a typed representation.

type UpdateSource

type UpdateSource int

UpdateSource identifies where an update response was loaded from.

const (
	// SourceUnknown indicates that the response source is unknown.
	SourceUnknown UpdateSource = iota

	// SourceEdge indicates that the response came from the configured EdgeURL.
	SourceEdge

	// SourceAPI indicates that the response came from the configured BaseURL API.
	SourceAPI
)

Directories

Path Synopsis
examples
basic command
edge-fallback command

Jump to

Keyboard shortcuts

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