sdk

package
v0.37.0 Latest Latest
Warning

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

Go to latest
Published: Jul 20, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package sdk is the shared contract between `gofastr generate sdk` (which emits client SDKs and packs the downloadable artifacts) and the serving side (framework/sdkdocs, which hosts them). It owns three things:

  • the artifact manifest schema (manifest.json in the dist directory),
  • the schema hash both sides compute to detect drift between the artifacts a developer generated and the API the running app serves,
  • the deterministic zip packer the generator uses so re-running generation on an unchanged schema produces byte-identical archives.

The package is a leaf: it imports only framework/entity and core/schema, so both cmd/gofastr and framework/uihost can depend on it without cycles.

Index

Constants

View Source
const (
	// ManifestFile is the machine-readable index of the dist directory.
	ManifestFile = "manifest.json"
	// GoArtifact is the downloadable Go SDK: a plain zip holding a
	// standalone stdlib-only module (client.go + go.mod + README.md).
	GoArtifact = "sdk-go.zip"
	// JSArtifact is the JS SDK: one handrolled ESM file, importable
	// directly from the served URL or dropped into a project. There is
	// deliberately no npm packaging — publishing is the app owner's call.
	JSArtifact = "client.js"
	// JSTypesArtifact is the TypeScript declaration file matching
	// JSArtifact.
	JSTypesArtifact = "client.d.ts"
	// SchemaVersion is the manifest schema version this package writes
	// and understands. A manifest with a different SchemaVersion is
	// treated as unknown provenance, not as stale (the hash algorithm may
	// have changed between gofastr versions).
	SchemaVersion = 1
)

Artifact and manifest file names inside the dist directory. The names are stable — regeneration overwrites in place — so download URLs never change; version and content hash travel in the manifest instead.

Variables

This section is empty.

Functions

func PackZip

func PackZip(prefix string, files []File) ([]byte, error)

PackZip builds a deterministic zip archive: entries are written in sorted path order with zeroed timestamps and fixed permissions, so packing the same files twice yields byte-identical archives (regeneration on an unchanged schema must not churn the artifact or its hash).

prefix, when non-empty, becomes the top-level directory every entry is placed under (e.g. "myapp-sdk" → "myapp-sdk/go.mod"), so extracting the archive never splats files into the current directory.

func SchemaHash

func SchemaHash(named []NamedConfig) string

SchemaHash returns a deterministic "sha256:<hex>" digest of the API-visible schema of the given entities. Both halves of the SDK feature compute it: `gofastr generate sdk` records it in the manifest at generation time; sdkdocs.Mount recomputes it from the live registry (restricted to Manifest.Entities) to warn when the downloadable SDKs no longer match the running API.

Every config is normalized through entity.Define before projection, so a raw declaration config (no injected id/timestamp columns, empty Table) and an already-registered entity hash identically. Define is idempotent for this purpose.

The projection covers exactly what changes a generated client's surface: name, table (route path), Public, SoftDelete (trashed listing), sorted SearchFields (?q=), relations (?include=), and every non-Hidden field's name, type, required/unique/readonly/auto flags, enum values, and default. Hidden fields never appear on the wire, so flipping one is invisible to SDKs and deliberately does not change the hash. Field order is sorted away for the same reason.

Types

type Artifact

type Artifact struct {
	// File is the dist-relative file name (one of GoArtifact, JSArtifact,
	// JSTypesArtifact).
	File string `json:"file"`
	// SHA256 is the lowercase hex digest of the file contents at
	// generation time. The serving side uses it as the ETag.
	SHA256 string `json:"sha256"`
	// Bytes is the file size, used for Content-Length and display.
	Bytes int64 `json:"bytes"`
	// Module is the Go module path baked into the Go SDK's go.mod.
	// Empty for non-Go artifacts.
	Module string `json:"module,omitempty"`
}

Artifact describes one downloadable file in the dist directory.

type File

type File struct {
	Path string
	Data []byte
}

File is one generated file: a dist-relative path and its bytes. Data is []byte (not string) because artifacts include binary archives.

type Manifest

type Manifest struct {
	SchemaVersion int `json:"schemaVersion"`
	// App is the display/app name the SDKs were generated for.
	App string `json:"app"`
	// SDKVersion is the semver stamped into the SDKs (0.0.0-dev default).
	SDKVersion string `json:"sdkVersion"`
	// GofastrVersion is the gofastr toolchain version that generated the
	// artifacts (from the host app's go.mod require line, or "dev").
	GofastrVersion string    `json:"gofastrVersion"`
	GeneratedAt    time.Time `json:"generatedAt"`
	// Entities lists the entity names the SDKs cover, sorted. The serving
	// side restricts its live SchemaHash computation to this set so the
	// drift check compares like with like even when the SDK was generated
	// with --only/--exclude.
	Entities []string `json:"entities"`
	// SchemaHash is SchemaHash() over the covered entities at generation
	// time ("sha256:<hex>").
	SchemaHash string `json:"schemaHash"`
	// Artifacts is keyed "go", "js", "js-types" — targets that were not
	// generated are absent.
	Artifacts map[string]Artifact `json:"artifacts"`
}

Manifest is the machine-readable index `gofastr generate sdk` writes as manifest.json beside the artifacts. The serving side reads it to render download links (size, version, generated-at) and to detect drift between the generated artifacts and the live entity registry via SchemaHash.

func ReadManifest

func ReadManifest(fsys fs.FS) (*Manifest, error)

ReadManifest loads and validates ManifestFile from the root of fsys (the dist directory). It returns an error when the file is missing, malformed, or structurally empty; a SchemaVersion mismatch is NOT an error — callers detect it via Manifest.SchemaVersion and degrade the drift check to "unknown provenance".

type NamedConfig

type NamedConfig struct {
	Name   string
	Config entity.EntityConfig
}

NamedConfig pairs an entity name with its config — the generation-side input to SchemaHash (declarations converted via EntityDeclaration.Config() carry no Name of their own).

func RegistryNamedConfigs

func RegistryNamedConfigs(reg entity.Registry, names []string) []NamedConfig

RegistryNamedConfigs adapts a live entity registry to SchemaHash input, restricted to the given entity names (the manifest's Entities list). Unknown names are skipped — an entity that was deleted since generation changes the hash by omission, which is exactly the drift signal wanted.

Jump to

Keyboard shortcuts

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