Skip to content

Latest commit

 

History

History
174 lines (125 loc) · 4.87 KB

File metadata and controls

174 lines (125 loc) · 4.87 KB

App SDK

The App SDK is the Go package app code compiles against:

import "github.com/hapyco/dygo/pkg/dygo"

Everything under internal/ is private framework implementation. App-owned hooks and Jobs should only depend on pkg/dygo and normal Go packages.

The supported public package is pkg/dygo.

SDK Vs HTTP API

Go SDK   - Go code imported by dygo apps
HTTP API - Network API used by clients and Studio

App SDK code is trusted server-side code. It does not run the same permission path as a browser or HTTP client calling the dygo HTTP API.

Current Surface

The current SDK exposes:

  • Record lifecycle hook types and registration
  • transactional Record reads and writes inside hooks
  • durable Job handler types and registration
  • Job enqueueing from hooks and Jobs
  • best-effort and strict persisted Log helpers
  • durable in-app notifications with optional email delivery
  • project runner integration types

Record Hooks

Record hooks register functions for Entity lifecycle events:

func Register(registry dygo.RecordHookRegistry) error {
	return registry.RegisterEntity("crm", "contact", dygo.RecordAfterCreate, "send-welcome", SendWelcome)
}

func SendWelcome(ctx context.Context, hook dygo.RecordHook) error {
	return nil
}

Supported events:

before-validate
validate
before-create
after-create
before-update
after-update
before-delete
after-delete

Hooks receive dygo.RecordHook, which includes the Entity identity, current input, old/new Record snapshots, changes, and SDK services.

Record Access

Hooks read and write metadata-backed Records through hook.Records:

record, err := hook.Records.Get(ctx, "crm", "contact", 42)
created, err := hook.Records.Create(ctx, "crm", "activity", dygo.RecordInput{
	"subject": json.RawMessage(`"Welcome"`),
})
updated, err := hook.Records.Update(ctx, "crm", "contact", 42, dygo.RecordInput{
	"status": json.RawMessage(`"Active"`),
})
err := hook.Records.Delete(ctx, "crm", "contact", 42)

Record access uses app-scoped Entity identity:

<app>, <entity>

Do not use route slugs as SDK Entity identity.

Hook Record writes run dygo framework hooks, such as Activity, but do not re-enter app hooks.

RecordData also provides permission-aware Count, Exists, Aggregate, GroupBy, relationship filters, ordered Lock, and Transaction. Use AsActor for user access. Use AsSystem only with a non-empty audit reason.

Entity actions receive the actor and transaction-scoped Records, Jobs, Files, Timeline, and Notifications services. Register one action on one Entity with EntityActionRegistry.RegisterEntity.

FileData uploads, attaches, opens, and removes private files. TimelineData adds append-only comments and events to Core Activity.

Jobs

Generated Job files expose one Run function:

func Run(ctx context.Context, job dygo.JobExecution) error {
	return nil
}

Job handlers and transactional Record hooks can enqueue durable background work:

execution, err := job.Jobs.Enqueue(ctx, "crm", "send-welcome-email", payload, dygo.EnqueueOptions{
	IdempotencyKey: "email:welcome:contact-42",
	Priority:       0,
	RunAfter:       time.Now().Add(10 * time.Minute),
})

Inside a Record hook, use hook.Jobs.Enqueue with the same arguments.

Job access uses app-scoped Job identity:

<app>, <job>

Do not use labels or routes as SDK Job identity.

Logs

App code can write persisted diagnostic Logs through package helpers:

dygo.Info(ctx, "Customer import started")
dygo.Error(ctx, "Customer import failed", err)

The helper functions are best-effort. Use dygo.Log(ctx, dygo.LogEntry{...}) when code needs to handle persistence errors. See Logs for the Log Entity contract and field mapping.

Notifications

Actions, Hooks, and Jobs send user notifications through their Notifications service:

_, err := call.Notifications.Send(ctx, dygo.NotificationMessage{
    Recipient:      "person@example.com",
    Title:          "Leave approved",
    Message:        "Your leave request was approved.",
    DeepLink:       "/hr-leave-request/HRL-2026-00001",
    Email:          true,
    IdempotencyKey: "hr:leave-approved:HRL-2026-00001",
})

Recipient is the Core User Record name. The idempotency key is unique for that recipient. Send creates the in-app Notification and, when requested, enqueues the Core email Job in the current transaction. SMTP delivery and retries happen after commit. Email failure does not remove the in-app Notification.

Runtime Rules

hooks   - run inside the current Record transaction
jobs    - run outside user requests
pages   - metadata contract; rendering remains framework-owned
reports - coming soon

Coming Soon

Planned SDK surfaces include:

dygo.Config        - app/runtime config reads
dygo.Secrets       - controlled secret reads
dygo.Metadata      - Entity, Field, and Page metadata reads